Zone.jsx 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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 "../views/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. onItem.forEach((action) => {
  42. switch (action) {
  43. case "reveal":
  44. actionMap["reveal"].action(insideItems);
  45. break;
  46. case "hide":
  47. actionMap["hide"].action(insideItems);
  48. break;
  49. case "revealSelf":
  50. actionMap["revealSelf"].action(insideItems);
  51. break;
  52. case "hideSelf":
  53. actionMap["sideSelf"].action(insideItems);
  54. break;
  55. case "stack":
  56. actionMap["stack"].action(insideItems);
  57. break;
  58. }
  59. });
  60. },
  61. [actionMap, onItem]
  62. );
  63. React.useEffect(() => {
  64. const unregisterList = [];
  65. if (onItem?.length) {
  66. unregisterList.push(register(onInsideItem));
  67. }
  68. return () => {
  69. unregisterList.forEach((callback) => callback());
  70. };
  71. }, [onInsideItem, onItem, register]);
  72. return (
  73. <ZoneWrapper width={width} height={height} ref={zoneRef}>
  74. <div>{label}</div>
  75. </ZoneWrapper>
  76. );
  77. };
  78. export default memo(Zone);