useInsertFromCreateSelection.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import { useCallback, type RefObject } from 'react';
  2. import { useCanvasStore } from '@/lib/store';
  3. import type { CreateElementSelectionData } from '@/lib/types/edit';
  4. export function useInsertFromCreateSelection(viewportRef: RefObject<HTMLElement | null>) {
  5. const canvasScale = useCanvasStore.use.canvasScale();
  6. const creatingElement = useCanvasStore.use.creatingElement();
  7. const setCreatingElement = useCanvasStore.use.setCreatingElement();
  8. // Calculate selection position and size from the start and end points of mouse drag selection
  9. const formatCreateSelection = useCallback(
  10. (selectionData: CreateElementSelectionData) => {
  11. const { start, end } = selectionData;
  12. if (!viewportRef.current) return;
  13. const viewportRect = viewportRef.current.getBoundingClientRect();
  14. const [startX, startY] = start;
  15. const [endX, endY] = end;
  16. const minX = Math.min(startX, endX);
  17. const maxX = Math.max(startX, endX);
  18. const minY = Math.min(startY, endY);
  19. const maxY = Math.max(startY, endY);
  20. const left = (minX - viewportRect.x) / canvasScale;
  21. const top = (minY - viewportRect.y) / canvasScale;
  22. const width = (maxX - minX) / canvasScale;
  23. const height = (maxY - minY) / canvasScale;
  24. return { left, top, width, height };
  25. },
  26. [viewportRef, canvasScale],
  27. );
  28. // Calculate line position and start/end points on canvas from the start and end points of mouse drag selection
  29. const formatCreateSelectionForLine = useCallback(
  30. (selectionData: CreateElementSelectionData) => {
  31. const { start, end } = selectionData;
  32. if (!viewportRef.current) return;
  33. const viewportRect = viewportRef.current.getBoundingClientRect();
  34. const [startX, startY] = start;
  35. const [endX, endY] = end;
  36. const minX = Math.min(startX, endX);
  37. const maxX = Math.max(startX, endX);
  38. const minY = Math.min(startY, endY);
  39. const maxY = Math.max(startY, endY);
  40. const left = (minX - viewportRect.x) / canvasScale;
  41. const top = (minY - viewportRect.y) / canvasScale;
  42. const width = (maxX - minX) / canvasScale;
  43. const height = (maxY - minY) / canvasScale;
  44. const _start: [number, number] = [startX === minX ? 0 : width, startY === minY ? 0 : height];
  45. const _end: [number, number] = [endX === minX ? 0 : width, endY === minY ? 0 : height];
  46. return {
  47. left,
  48. top,
  49. start: _start,
  50. end: _end,
  51. };
  52. },
  53. [viewportRef, canvasScale],
  54. );
  55. // Insert element based on mouse selection position and size
  56. const insertElementFromCreateSelection = useCallback(
  57. (selectionData: CreateElementSelectionData) => {
  58. if (!creatingElement) return;
  59. const type = creatingElement.type;
  60. if (type === 'text') {
  61. const position = formatCreateSelection(selectionData);
  62. if (position) {
  63. // TODO: Implement createTextElement
  64. }
  65. } else if (type === 'shape') {
  66. const position = formatCreateSelection(selectionData);
  67. if (position) {
  68. // TODO: Implement createShapeElement
  69. }
  70. } else if (type === 'line') {
  71. const position = formatCreateSelectionForLine(selectionData);
  72. if (position) {
  73. // TODO: Implement createLineElement
  74. }
  75. }
  76. setCreatingElement(null);
  77. },
  78. [creatingElement, formatCreateSelection, formatCreateSelectionForLine, setCreatingElement],
  79. );
  80. return {
  81. formatCreateSelection,
  82. insertElementFromCreateSelection,
  83. };
  84. }