Zone.jsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import React from "react";
  2. import { memo } from "react";
  3. import styled, { css } from "styled-components";
  4. import { useItemInteraction } from "react-sync-board";
  5. import { isItemInsideElement } from "..//utils";
  6. import useGameItemActions from "./useGameItemActions";
  7. const ZoneWrapper = styled.div`
  8. ${({ width = 200, height = 200 }) => css`
  9. width: ${width}px;
  10. height: ${height}px;
  11. border: 0.5em dotted #ccc;
  12. opacity: 0.2;
  13. border-radius: 1em;
  14. position: relative;
  15. & > div {
  16. font-size: 1.5em;
  17. letter-spacing: -3px;
  18. user-select: none;
  19. background-color: #ccc;
  20. position: absolute;
  21. padding: 1em 0em;
  22. top: 1em;
  23. left: -1em;
  24. border-radius: 0.5em;
  25. color: var(--color-darkGrey);
  26. writing-mode: vertical-rl;
  27. text-orientation: upright;
  28. }
  29. `}
  30. `;
  31. const Zone = ({ width, height, label, onItem }) => {
  32. const { register } = useItemInteraction("place");
  33. const zoneRef = React.useRef(null);
  34. const { actionMap } = useGameItemActions();
  35. const onInsideItem = React.useCallback(
  36. (itemIds) => {
  37. const insideItems = itemIds.filter((itemId) =>
  38. isItemInsideElement(document.getElementById(itemId), zoneRef.current)
  39. );
  40. if (!insideItems.length) return;
  41. const onItemActions = onItem.map((action) => {
  42. if (typeof action === "string") {
  43. return { name: action };
  44. }
  45. return action;
  46. });
  47. onItemActions.forEach(({ name, args }) => {
  48. switch (name) {
  49. case "reveal":
  50. actionMap["reveal"].action(args)(insideItems);
  51. break;
  52. case "hide":
  53. actionMap["hide"].action(args)(insideItems);
  54. break;
  55. case "revealSelf":
  56. actionMap["revealSelf"].action(args)(insideItems);
  57. break;
  58. case "hideSelf":
  59. actionMap["hideSelf"].action(args)(insideItems);
  60. break;
  61. case "stack":
  62. actionMap["stack"].action(args)(insideItems);
  63. break;
  64. }
  65. });
  66. },
  67. [actionMap, onItem]
  68. );
  69. React.useEffect(() => {
  70. const unregisterList = [];
  71. if (onItem?.length) {
  72. unregisterList.push(register(onInsideItem));
  73. }
  74. return () => {
  75. unregisterList.forEach((callback) => callback());
  76. };
  77. }, [onInsideItem, onItem, register]);
  78. return (
  79. <ZoneWrapper width={width} height={height} ref={zoneRef}>
  80. <div>{label}</div>
  81. </ZoneWrapper>
  82. );
  83. };
  84. export default memo(Zone);