NewItems.jsx 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import React, { memo } from "react";
  2. import { nanoid } from "nanoid";
  3. import { useRecoilCallback } from "recoil";
  4. import styled from "styled-components";
  5. import { useItems } from "./board/Items";
  6. import { PanZoomRotateAtom } from "./board";
  7. import { itemMap } from "./boardComponents";
  8. const ItemList = styled.div`
  9. display: flex;
  10. flex-wrap: wrap;
  11. align-items: end;
  12. justify-content: space-around;
  13. `;
  14. const Item = styled.div`
  15. padding: 1em;
  16. margin: 0.3em;
  17. cursor: pointer;
  18. opacity: 0.7;
  19. &:hover {
  20. opacity: 1;
  21. }
  22. & > div {
  23. display: flex;
  24. align-items: center;
  25. flex-direction: column;
  26. }
  27. `;
  28. const size = 70;
  29. const NewItem = memo(({ type }) => {
  30. const { pushItem } = useItems();
  31. const addItem = useRecoilCallback(
  32. ({ snapshot }) => async () => {
  33. const { centerX, centerY } = await snapshot.getPromise(PanZoomRotateAtom);
  34. pushItem({
  35. ...itemMap[type].template,
  36. x: centerX,
  37. y: centerY,
  38. id: nanoid(),
  39. type,
  40. });
  41. },
  42. [pushItem, type]
  43. );
  44. const Component = itemMap[type].component;
  45. return (
  46. <>
  47. <Item onClick={addItem}>
  48. <div style={{ pointerEvents: "none" }}>
  49. <Component width={size} height={size} size={size} />
  50. <span>{itemMap[type].label}</span>
  51. </div>
  52. </Item>
  53. </>
  54. );
  55. });
  56. NewItem.displayName = "NewItem";
  57. const NewItems = () => {
  58. return (
  59. <ItemList>
  60. {Object.keys(itemMap).map((type) => (
  61. <NewItem type={type} key={type} />
  62. ))}
  63. </ItemList>
  64. );
  65. };
  66. export default memo(NewItems);