seat-editor 3.3.35 → 3.3.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/app/constant.d.ts +3 -0
  2. package/dist/app/constant.js +2 -0
  3. package/dist/app/layout.d.ts +1 -1
  4. package/dist/app/layout.js +22 -0
  5. package/dist/app/new-board/page.d.ts +1 -1
  6. package/dist/app/new-board/page.js +58 -0
  7. package/dist/app/old-board/page.d.ts +1 -2
  8. package/dist/app/old-board/page.js +377 -0
  9. package/dist/app/only-view/chair.d.ts +1 -1
  10. package/dist/app/only-view/chair.js +2 -10
  11. package/dist/app/only-view/page.d.ts +1 -1
  12. package/dist/app/only-view/page.js +226 -0
  13. package/dist/app/only-view/user.d.ts +1 -1
  14. package/dist/app/only-view/user.js +2 -10
  15. package/dist/app/page.d.ts +1 -1
  16. package/dist/app/page.js +8 -0
  17. package/dist/app/test/page.d.ts +1 -2
  18. package/dist/app/test/page.js +43 -0
  19. package/dist/app/v2/page.d.ts +1 -1
  20. package/dist/app/v2/page.js +8 -0
  21. package/dist/components/button-tools/index.d.ts +1 -1
  22. package/dist/components/button-tools/index.js +11 -0
  23. package/dist/components/form-tools/label.d.ts +1 -1
  24. package/dist/components/form-tools/label.js +21 -0
  25. package/dist/components/form-tools/shape.d.ts +1 -1
  26. package/dist/components/form-tools/shape.js +69 -0
  27. package/dist/components/input/number-indicator.d.ts +1 -1
  28. package/dist/components/input/number-indicator.js +27 -0
  29. package/dist/components/joystick/index.d.ts +1 -2
  30. package/dist/components/joystick/index.js +48 -0
  31. package/dist/components/layer/index.d.ts +1 -1
  32. package/dist/components/layer/index.js +295 -0
  33. package/dist/components/layer-v2/index.d.ts +1 -1
  34. package/dist/components/layer-v2/index.js +282 -0
  35. package/dist/components/layer-v3/index.d.ts +1 -1
  36. package/dist/components/layer-v3/index.js +483 -0
  37. package/dist/components/layer-v4/index.d.ts +1 -1
  38. package/dist/components/layer-v4/index.js +924 -0
  39. package/dist/components/lib/index.d.ts +1 -1
  40. package/dist/components/lib/index.js +28 -0
  41. package/dist/components/modal-preview/index.d.ts +1 -1
  42. package/dist/components/modal-preview/index.js +10 -0
  43. package/dist/features/board/index.d.ts +1 -1
  44. package/dist/features/board/index.js +666 -0
  45. package/dist/features/board-v2/index.d.ts +1 -2
  46. package/dist/features/board-v2/index.js +807 -0
  47. package/dist/features/board-v3/icons.js +16 -0
  48. package/dist/features/board-v3/index.d.ts +1 -1
  49. package/dist/features/board-v3/index.js +1587 -0
  50. package/dist/features/navbar/index.d.ts +1 -1
  51. package/dist/features/navbar/index.js +6 -0
  52. package/dist/features/package/index.d.ts +1 -1
  53. package/dist/features/package/index.js +166 -0
  54. package/dist/features/panel/index.d.ts +1 -1
  55. package/dist/features/panel/index.js +243 -0
  56. package/dist/features/panel/select-tool.d.ts +1 -1
  57. package/dist/features/panel/select-tool.js +57 -0
  58. package/dist/features/panel/selected-group.d.ts +1 -1
  59. package/dist/features/panel/selected-group.js +35 -0
  60. package/dist/features/panel/square-circle-tool.d.ts +1 -1
  61. package/dist/features/panel/square-circle-tool.js +8 -0
  62. package/dist/features/panel/table-seat-circle.d.ts +1 -1
  63. package/dist/features/panel/table-seat-circle.js +9 -0
  64. package/dist/features/panel/table-seat-square.d.ts +1 -1
  65. package/dist/features/panel/table-seat-square.js +9 -0
  66. package/dist/features/panel/text-tool.d.ts +1 -1
  67. package/dist/features/panel/text-tool.js +22 -0
  68. package/dist/features/panel/upload-tool.d.ts +1 -1
  69. package/dist/features/panel/upload-tool.js +150 -0
  70. package/dist/features/side-tool/index.d.ts +1 -1
  71. package/dist/features/side-tool/index.js +365 -0
  72. package/dist/features/view-only/index.d.ts +1 -1
  73. package/dist/features/view-only/index.js +198 -0
  74. package/dist/features/view-only-2/index.d.ts +84 -14
  75. package/dist/features/view-only-2/index.js +558 -0
  76. package/dist/features/view-only-3/index.d.ts +1 -1
  77. package/dist/features/view-only-3/index.js +577 -0
  78. package/dist/provider/antd-provider.js +43 -0
  79. package/dist/provider/redux-provider.d.ts +1 -1
  80. package/dist/provider/redux-provider.js +7 -0
  81. package/dist/provider/store-provider.d.ts +1 -1
  82. package/dist/provider/store-provider.js +9 -0
  83. package/package.json +1 -1
@@ -0,0 +1,807 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ import { TransformWrapper, TransformComponent, MiniMap, } from "react-zoom-pan-pinch";
5
+ import { useAppSelector, useAppDispatch } from "../../hooks/use-redux";
6
+ import Layers from "../../components/layer-v2";
7
+ import { throttle } from "lodash";
8
+ import ModalPreview from "../../components/modal-preview";
9
+ import LayerView from "../view-only-2";
10
+ import { isEqual, debounce } from "lodash";
11
+ import { ZoomIn, ZoomOut } from "lucide-react";
12
+ import { Button } from "antd";
13
+ const BoardTemplate = ({ onSelectComponent, viewOnly }) => {
14
+ var _a, _b;
15
+ const dispatch = useAppDispatch();
16
+ const theme = useAppSelector((state) => state.theme);
17
+ const transformRef = useRef(null);
18
+ const containerRef = useRef(null);
19
+ const [widthBoard, setWidthBoard] = useState(0);
20
+ const [heightBoard, setHeightBoard] = useState(0);
21
+ const svgRef = useRef(null);
22
+ const [shadowShape, setShadowShape] = useState([]);
23
+ const [startPoint, setStartPoint] = useState(null);
24
+ const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
25
+ // const [moveComponent, setMoveComponent] = useState(false);
26
+ const [scale, setScale] = useState(1);
27
+ const activeTool = useAppSelector((state) => state.tool.active);
28
+ const grid = useAppSelector((state) => state.tool.grid);
29
+ const lockBackground = useAppSelector((state) => state.tool.lockBackground);
30
+ const { components: componentsProps, extraComponents: extraComponentsProps, flagChange, } = useAppSelector((state) => state.board);
31
+ const isTouching = useRef(false);
32
+ useEffect(() => {
33
+ var _a;
34
+ if (activeTool !== ((_a = shadowShape[0]) === null || _a === void 0 ? void 0 : _a.shape)) {
35
+ setShadowShape([]);
36
+ }
37
+ }, [activeTool]);
38
+ // const [isDragging, setIsDragging] = useState(false);
39
+ const [resizeDirection, setResizeDirection] = useState(null);
40
+ const backgroundColor = useAppSelector((state) => state.board.backgroundColor);
41
+ const selectedComponentProps = useAppSelector((state) => state.panel.selectedComponent);
42
+ const screenCTMRef = useRef(null);
43
+ const dragIndex = useRef(null);
44
+ const [componentsState, setComponentsState] = useState([]);
45
+ const [extraComponentsState, setExtraComponentsState] = useState([]);
46
+ const [selectedComponent, setSelectedComponent] = useState(null);
47
+ const isSyncingFromRedux = useRef(false);
48
+ const startPos = useRef({ x: 0, y: 0 });
49
+ const isDragging = useRef(false);
50
+ const moveComponent = useRef(false);
51
+ const debouncedSyncToReduxSelected = useRef(debounce((data) => {
52
+ throttledDispatch(data);
53
+ }, 300)).current;
54
+ const debouncedSyncComponents = useRef(debounce((data) => {
55
+ dispatch({
56
+ type: "board/setNewComponents",
57
+ payload: data,
58
+ });
59
+ }, 300));
60
+ const debouncedSyncExtraComponents = useRef(debounce((data) => {
61
+ dispatch({
62
+ type: "board/setNewExtraComponents",
63
+ payload: data,
64
+ });
65
+ }, 300));
66
+ // Redux → Local
67
+ useEffect(() => {
68
+ if (flagChange) {
69
+ if (!isEqual(componentsProps, componentsState)) {
70
+ isSyncingFromRedux.current = true;
71
+ setComponentsState(componentsProps !== null && componentsProps !== void 0 ? componentsProps : []);
72
+ }
73
+ if (!isEqual(extraComponentsProps, extraComponentsState)) {
74
+ isSyncingFromRedux.current = true;
75
+ setExtraComponentsState(extraComponentsProps !== null && extraComponentsProps !== void 0 ? extraComponentsProps : []);
76
+ }
77
+ if (!isEqual(selectedComponentProps, selectedComponent)) {
78
+ isSyncingFromRedux.current = true;
79
+ setSelectedComponent(selectedComponentProps !== null && selectedComponentProps !== void 0 ? selectedComponentProps : []);
80
+ }
81
+ dispatch({ type: "board/setFlagChange", payload: false });
82
+ }
83
+ }, [
84
+ componentsProps,
85
+ extraComponentsProps,
86
+ selectedComponentProps,
87
+ flagChange,
88
+ ]);
89
+ // Local → Redux
90
+ useEffect(() => {
91
+ if (isSyncingFromRedux.current) {
92
+ isSyncingFromRedux.current = false;
93
+ return;
94
+ }
95
+ if (!isEqual(componentsState, componentsProps) &&
96
+ !isEqual(componentsState, [])) {
97
+ debouncedSyncComponents.current(componentsState);
98
+ }
99
+ if (!isEqual(extraComponentsState, extraComponentsProps) &&
100
+ !isEqual(extraComponentsState, [])) {
101
+ debouncedSyncExtraComponents.current(extraComponentsState);
102
+ }
103
+ }, [componentsState, extraComponentsState]);
104
+ const handleAddComponent = (shape) => {
105
+ dispatch({
106
+ type: activeTool === "text"
107
+ ? "board/setExtraComponent"
108
+ : "board/addComponent",
109
+ payload: Object.assign(Object.assign({}, shape), { fill: theme === null || theme === void 0 ? void 0 : theme.primaryColor }),
110
+ });
111
+ const payload = Object.assign(Object.assign({}, shape), { fill: theme === null || theme === void 0 ? void 0 : theme.primaryColor });
112
+ if (activeTool === "text") {
113
+ setExtraComponentsState((prev) => [...prev, payload]);
114
+ }
115
+ else {
116
+ setComponentsState((prev) => [...prev, payload]);
117
+ }
118
+ };
119
+ const getSvgCoords = (e) => {
120
+ var _a;
121
+ const svg = svgRef.current;
122
+ const point = svg.createSVGPoint();
123
+ point.x = e.clientX;
124
+ point.y = e.clientY;
125
+ const transformed = point.matrixTransform((_a = svg.getScreenCTM()) === null || _a === void 0 ? void 0 : _a.inverse());
126
+ return { x: transformed.x, y: transformed.y };
127
+ };
128
+ const createShape = (x, y, fill) => ({
129
+ x,
130
+ y,
131
+ width: 50,
132
+ height: 50,
133
+ shape: activeTool,
134
+ id: Date.now(),
135
+ fill,
136
+ rotation: activeTool === "diamond" ? 45 : 0,
137
+ seatCount: activeTool === "table-seat-circle" ? 6 : 0,
138
+ openSpace: activeTool === "table-seat-circle" ? 0 : undefined,
139
+ seatFill: activeTool === "table-seat-circle" ? "#DADADA" : undefined,
140
+ text: activeTool === "text" ? "Text" : "",
141
+ fontColor: activeTool === "text" ? "#DADADA" : undefined,
142
+ points: [],
143
+ });
144
+ const getCoords = (e) => {
145
+ const svgRect = svgRef.current.getBoundingClientRect();
146
+ if ("touches" in e) {
147
+ return {
148
+ x: e.touches[0].clientX,
149
+ y: e.touches[0].clientY,
150
+ };
151
+ }
152
+ return {
153
+ x: e.clientX - svgRect.x,
154
+ y: e.clientY - svgRect.y,
155
+ };
156
+ };
157
+ const handleMouseDown = (e, item, direction) => {
158
+ if (!item && !direction) {
159
+ if (["node", "select"].includes(activeTool)) {
160
+ setSelectedComponent(null);
161
+ dispatch({ type: "panel/setSelectedComponent", payload: null });
162
+ }
163
+ return;
164
+ }
165
+ if (["node", "select"].includes(activeTool) && item && !direction) {
166
+ const coords = getCoords(e);
167
+ // startPos.current = { x: e.clientX, y: e.clientY };
168
+ // const rectBox = (e?.target as HTMLElement).getBoundingClientRect();
169
+ if (activeTool === "node") {
170
+ moveComponent.current = true;
171
+ isDragging.current = false;
172
+ dispatch({ type: "panel/setShow", payload: false });
173
+ // dispatch({
174
+ // type: "tool/setActiveTool",
175
+ // payload: "node",
176
+ // });
177
+ }
178
+ if (activeTool === "select") {
179
+ isDragging.current = true;
180
+ moveComponent.current = false;
181
+ dispatch({ type: "panel/setShow", payload: true });
182
+ }
183
+ const rectBox = (e === null || e === void 0 ? void 0 : e.target).getBoundingClientRect();
184
+ setDragOffset({
185
+ x: coords.x - rectBox.left + ((item === null || item === void 0 ? void 0 : item.strokeWidth) || 0),
186
+ y: coords.y - rectBox.top + ((item === null || item === void 0 ? void 0 : item.strokeWidth) || 0),
187
+ });
188
+ setSelectedComponent(item);
189
+ dispatch({
190
+ type: "panel/setSelectedComponent",
191
+ payload: item,
192
+ });
193
+ // const handleMouseMove = (event: MouseEvent) => {
194
+ // const dx = Math.abs(event.clientX - startPos.current.x);
195
+ // const dy = Math.abs(event.clientY - startPos.current.y);
196
+ // if (dx > 1 || dy > 1) {
197
+ // if (!moveComponent.current && item) {
198
+ // dispatch({ type: "panel/setSelectedComponent", payload: item });
199
+ // setSelectedComponent(item);
200
+ // }
201
+ // moveComponent.current = true;
202
+ // }
203
+ // };
204
+ // const handleMouseUp = () => {
205
+ // document.removeEventListener("mousemove", handleMouseMove);
206
+ // document.removeEventListener("mouseup", handleMouseUp);
207
+ // if (moveComponent.current) {
208
+ // moveComponent.current = false;
209
+ // } else {
210
+ // isDragging.current = true;
211
+ // moveComponent.current = false;
212
+ // setResizeDirection(direction);
213
+ // if (item) {
214
+ // dispatch({ type: "panel/setSelectedComponent", payload: item });
215
+ // dispatch({ type: "panel/setShow", payload: true });
216
+ // setSelectedComponent(item);
217
+ // }
218
+ // }
219
+ // };
220
+ // Pasang ke `document` agar global
221
+ // document.addEventListener("mousemove", handleMouseMove);
222
+ // document.addEventListener("mouseup", handleMouseUp);
223
+ }
224
+ // if(activeTool === "select" && item && !direction) {
225
+ // dispatch({
226
+ // type: "tool/setActiveTool",
227
+ // payload: "node",
228
+ // });
229
+ // }
230
+ if (activeTool === "select" && direction) {
231
+ setResizeDirection(direction);
232
+ }
233
+ };
234
+ const handleMouseEnter = () => {
235
+ if (![
236
+ "square",
237
+ "circle",
238
+ "diamond",
239
+ "table-seat-circle",
240
+ "table-seat-square",
241
+ "text",
242
+ ].includes(activeTool))
243
+ return;
244
+ };
245
+ const handleMouseLeave = () => {
246
+ if (![
247
+ "square",
248
+ "circle",
249
+ "diamond",
250
+ "table-seat-circle",
251
+ "table-seat-square",
252
+ "text",
253
+ ].includes(activeTool))
254
+ return;
255
+ setShadowShape([]);
256
+ };
257
+ const handleMouseClick = (e) => {
258
+ if (["select", "node"].includes(activeTool) && selectedComponent) {
259
+ handleUnSelectComponent();
260
+ return;
261
+ }
262
+ if (![
263
+ "square",
264
+ "circle",
265
+ "diamond",
266
+ "table-seat-circle",
267
+ "table-seat-square",
268
+ "text",
269
+ ].includes(activeTool)) {
270
+ return;
271
+ }
272
+ const { x, y } = getSvgCoords(e);
273
+ setStartPoint({ x, y });
274
+ handleAddComponent(createShape(x, y, theme === null || theme === void 0 ? void 0 : theme.primaryColor));
275
+ };
276
+ const throttledDispatch = useCallback(throttle((component) => {
277
+ // dispatch({
278
+ // type: "board/updateComponent",
279
+ // payload: component,
280
+ // });
281
+ dispatch({
282
+ type: "panel/updateSelectedComponent",
283
+ payload: component,
284
+ });
285
+ }, 16), // 16ms ≈ 60fps
286
+ [dispatch]);
287
+ const handleMouseMove = (e) => {
288
+ var _a;
289
+ if ([
290
+ "square",
291
+ "circle",
292
+ "diamond",
293
+ "table-seat-circle",
294
+ "table-seat-square",
295
+ "text",
296
+ "ruler",
297
+ ].includes(activeTool)) {
298
+ const { x, y } = getSvgCoords(e);
299
+ setShadowShape([createShape(x, y, theme === null || theme === void 0 ? void 0 : theme.primaryColor)]);
300
+ return;
301
+ }
302
+ if ((selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.shape) === "background" && lockBackground)
303
+ return;
304
+ if (activeTool === "node" &&
305
+ selectedComponent &&
306
+ moveComponent.current &&
307
+ dragOffset &&
308
+ // !isTouching.current &&
309
+ !resizeDirection) {
310
+ const workspaceRect = e.currentTarget.getBoundingClientRect();
311
+ const coords = getCoords(e);
312
+ const newX = coords.x - workspaceRect.left - (dragOffset === null || dragOffset === void 0 ? void 0 : dragOffset.x);
313
+ const newY = coords.y - workspaceRect.top - (dragOffset === null || dragOffset === void 0 ? void 0 : dragOffset.y);
314
+ let newPosition = {
315
+ x: newX / scale,
316
+ y: newY / scale,
317
+ };
318
+ requestAnimationFrame(() => {
319
+ setComponentsState((prev) => {
320
+ return prev.map((component) => {
321
+ if (component.id === selectedComponent.id) {
322
+ return Object.assign(Object.assign({}, component), { x: newPosition.x, y: newPosition.y });
323
+ }
324
+ return component;
325
+ });
326
+ });
327
+ setExtraComponentsState((prev) => {
328
+ return prev.map((component) => {
329
+ if (component.id === selectedComponent.id) {
330
+ return Object.assign(Object.assign({}, component), { x: newPosition.x, y: newPosition.y });
331
+ }
332
+ return component;
333
+ });
334
+ });
335
+ setSelectedComponent((prev) => {
336
+ return Object.assign(Object.assign({}, prev), { x: newPosition.x, y: newPosition.y });
337
+ });
338
+ });
339
+ debouncedSyncToReduxSelected(Object.assign(Object.assign({}, selectedComponent), newPosition));
340
+ return;
341
+ }
342
+ if (activeTool === "select" && resizeDirection) {
343
+ const coords = getCoords(e);
344
+ const workspaceRect = e.currentTarget.getBoundingClientRect();
345
+ const instance = (_a = transformRef.current) === null || _a === void 0 ? void 0 : _a.instance;
346
+ if (!instance)
347
+ return;
348
+ const { positionX, positionY } = instance.transformState;
349
+ const currentX = (coords.x - workspaceRect.left + 25 - positionX) / scale;
350
+ const currentY = (coords.y - workspaceRect.top + 25 - positionY) / scale;
351
+ const { x, y, width, height } = selectedComponent;
352
+ const relativeX = coords.x - workspaceRect.left;
353
+ const relativeY = coords.y - workspaceRect.top;
354
+ // 🧠 Ini posisi world (unscaled)
355
+ const worldX = (relativeX - positionX) / scale;
356
+ const worldY = (relativeY - positionY) / scale;
357
+ let newShape = Object.assign({}, selectedComponent);
358
+ if (!["table-seat-circle", "table-seat-square"].includes(selectedComponent.shape)) {
359
+ switch (resizeDirection) {
360
+ case "top-left":
361
+ // if (currentX < x || currentY < y) return;
362
+ newShape.width = width + (x - currentX);
363
+ newShape.height = height + (y - currentY);
364
+ newShape.x = currentX;
365
+ newShape.y = currentY;
366
+ break;
367
+ case "top-right":
368
+ newShape.width = currentX - newShape.x;
369
+ newShape.height = newShape.height + (newShape.y - currentY);
370
+ newShape.y = currentY;
371
+ break;
372
+ case "bottom-left":
373
+ newShape.width += newShape.x - currentX;
374
+ newShape.height = currentY - newShape.y;
375
+ newShape.x = currentX;
376
+ break;
377
+ case "bottom-right":
378
+ newShape.width = currentX - newShape.x;
379
+ newShape.height = currentY - newShape.y;
380
+ break;
381
+ case "left-center":
382
+ newShape.width += newShape.x - currentX;
383
+ newShape.x = currentX;
384
+ break;
385
+ case "right-center":
386
+ newShape.width = currentX - newShape.x;
387
+ break;
388
+ case "top-center": {
389
+ const delta = newShape.y - worldY;
390
+ newShape.height += delta;
391
+ newShape.y = worldY;
392
+ break;
393
+ }
394
+ case "bottom-center":
395
+ newShape.height = currentY - newShape.y;
396
+ break;
397
+ default:
398
+ break;
399
+ }
400
+ }
401
+ else if (["table-seat-circle", "table-seat-square"].includes(selectedComponent.shape)) {
402
+ switch (resizeDirection) {
403
+ case "top-left":
404
+ newShape.width = width + (x - currentX);
405
+ newShape.height = height + (y - currentY);
406
+ newShape.x = currentX;
407
+ newShape.y = currentY;
408
+ break;
409
+ case "top-right":
410
+ newShape.width = currentX - newShape.x;
411
+ newShape.height = newShape.height + (newShape.y - currentY);
412
+ newShape.y = currentY;
413
+ break;
414
+ case "bottom-left":
415
+ newShape.width += newShape.x - currentX;
416
+ newShape.height = currentY - newShape.y;
417
+ newShape.x = currentX;
418
+ break;
419
+ case "bottom-right":
420
+ newShape.width = currentX - newShape.x;
421
+ newShape.height = currentY - newShape.y;
422
+ break;
423
+ default:
424
+ break;
425
+ }
426
+ }
427
+ requestAnimationFrame(() => {
428
+ setComponentsState((prev) => {
429
+ return prev.map((component) => {
430
+ if (component.id === selectedComponent.id) {
431
+ return Object.assign(Object.assign({}, component), newShape);
432
+ }
433
+ return component;
434
+ });
435
+ });
436
+ setExtraComponentsState((prev) => {
437
+ return prev.map((component) => {
438
+ if (component.id === selectedComponent.id) {
439
+ return Object.assign(Object.assign({}, component), newShape);
440
+ }
441
+ return component;
442
+ });
443
+ });
444
+ setSelectedComponent(newShape);
445
+ });
446
+ debouncedSyncToReduxSelected(newShape);
447
+ }
448
+ };
449
+ const handleMouseUp = () => {
450
+ if (["select", "node"].includes(activeTool) && selectedComponent) {
451
+ setResizeDirection(null);
452
+ moveComponent.current = false;
453
+ }
454
+ };
455
+ useEffect(() => {
456
+ if (containerRef.current) {
457
+ setWidthBoard(containerRef.current.offsetWidth);
458
+ setHeightBoard(containerRef.current.offsetHeight);
459
+ }
460
+ }, [(_a = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth, (_b = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current) === null || _b === void 0 ? void 0 : _b.offsetHeight, viewOnly]);
461
+ const handleUnSelectComponent = () => {
462
+ dispatch({ type: "panel/setSelectedComponent", payload: null });
463
+ setSelectedComponent(null);
464
+ };
465
+ // const handleTouchStart = (
466
+ // e: React.TouchEvent<
467
+ // SVGRectElement | SVGCircleElement | SVGTextElement | SVGImageElement
468
+ // >,
469
+ // items: any,
470
+ // direction?: string
471
+ // ) => {
472
+ // if (activeTool === "node" && !direction && items) {
473
+ // // dispatch({ type: "panel/setShow", payload: false });
474
+ // // setMoveComponent(true);
475
+ // moveComponent.current = true;
476
+ // isTouching.current = true;
477
+ // // dispatch({ type: "panel/setSelectedComponent", payload: item });
478
+ // onSelectComponent && onSelectComponent(items);
479
+ // dispatch({ type: "panel/setSelectedComponent", payload: items });
480
+ // setSelectedComponent(items);
481
+ // // selectedComponentRef.current = items;
482
+ // const touch = e.touches[0];
483
+ // const svg = e.currentTarget.ownerSVGElement;
484
+ // const pt = svg.createSVGPoint();
485
+ // if (!svg) return;
486
+ // pt.x = touch.clientX;
487
+ // pt.y = touch.clientY;
488
+ // const cursorpt = pt.matrixTransform(svg.getScreenCTM()?.inverse());
489
+ // screenCTMRef.current = svg.getScreenCTM()?.inverse() || null;
490
+ // setDragOffset({
491
+ // x: cursorpt.x - items.x,
492
+ // y: cursorpt.y - items.y,
493
+ // });
494
+ // // dragOffset.current = {
495
+ // // x: cursorpt.x - items.x,
496
+ // // y: cursorpt.y - items.y
497
+ // // }
498
+ // } else if (activeTool === "select" && direction) {
499
+ // setResizeDirection(direction);
500
+ // // setIsDragging(true);
501
+ // // setMoveComponent(true);
502
+ // moveComponent.current = true;
503
+ // isDragging.current = true;
504
+ // isTouching.current = true;
505
+ // const touch = e.touches[0];
506
+ // const svg = e.currentTarget.ownerSVGElement;
507
+ // const pt = svg.createSVGPoint();
508
+ // if (!svg) return;
509
+ // pt.x = touch.clientX;
510
+ // pt.y = touch.clientY;
511
+ // const cursorpt = pt.matrixTransform(svg.getScreenCTM()?.inverse());
512
+ // screenCTMRef.current = svg.getScreenCTM()?.inverse() || null;
513
+ // setDragOffset({
514
+ // x: cursorpt.x - items.x,
515
+ // y: cursorpt.y - items.y,
516
+ // });
517
+ // // dragOffset.current = {
518
+ // // x: cursorpt.x - items.x,
519
+ // // y: cursorpt.y - items.y
520
+ // // }
521
+ // }
522
+ // };
523
+ // const handleTouchMove = (
524
+ // e: React.TouchEvent<
525
+ // SVGRectElement | SVGCircleElement | SVGTextElement | SVGImageElement
526
+ // >
527
+ // ) => {
528
+ // if (
529
+ // activeTool === "node" &&
530
+ // moveComponent &&
531
+ // isTouching.current &&
532
+ // !resizeDirection
533
+ // ) {
534
+ // isDragging.current = true;
535
+ // moveComponent.current = true;
536
+ // const touch = e.touches[0];
537
+ // const svg = e.currentTarget.ownerSVGElement;
538
+ // if (!svg) return;
539
+ // const pt = svg.createSVGPoint();
540
+ // pt.x = touch.clientX;
541
+ // pt.y = touch.clientY;
542
+ // const cursorpt = pt.matrixTransform(screenCTMRef.current);
543
+ // requestAnimationFrame(() => {
544
+ // if (selectedComponent?.shape != "background") {
545
+ // setComponentsState((prev) => {
546
+ // return prev.map((component) => {
547
+ // if (component.id === selectedComponent.id) {
548
+ // return {
549
+ // ...component,
550
+ // x: cursorpt.x - dragOffset?.x,
551
+ // y: cursorpt.y - dragOffset?.y,
552
+ // };
553
+ // }
554
+ // return component;
555
+ // });
556
+ // });
557
+ // }
558
+ // if (selectedComponent?.shape == "background") {
559
+ // setExtraComponentsState((prev) => {
560
+ // return prev.map((component) => {
561
+ // if (component.id === selectedComponent.id) {
562
+ // return {
563
+ // ...component,
564
+ // x: cursorpt.x - dragOffset?.x,
565
+ // y: cursorpt.y - dragOffset?.y,
566
+ // };
567
+ // }
568
+ // return component;
569
+ // });
570
+ // });
571
+ // }
572
+ // setSelectedComponent({
573
+ // ...selectedComponent,
574
+ // x: cursorpt.x - dragOffset?.x,
575
+ // y: cursorpt.y - dragOffset?.y,
576
+ // });
577
+ // });
578
+ // // updateComponentRef({
579
+ // // ...(typeof selectedComponent === "object" && selectedComponent !== null
580
+ // // ? selectedComponent
581
+ // // : {}),
582
+ // // x: cursorpt.x - dragOffset?.current.x,
583
+ // // y: cursorpt.y - dragOffset?.current.y,
584
+ // // });
585
+ // } else if (
586
+ // activeTool === "select" &&
587
+ // moveComponent.current &&
588
+ // isTouching.current &&
589
+ // resizeDirection
590
+ // ) {
591
+ // // setIsDragging(true);
592
+ // isDragging.current = true;
593
+ // const touch = e.touches[0];
594
+ // const svg = e.currentTarget.ownerSVGElement;
595
+ // if (!svg) return;
596
+ // const pt = svg.createSVGPoint();
597
+ // pt.x = touch.clientX;
598
+ // pt.y = touch.clientY;
599
+ // const cursorpt = pt.matrixTransform(screenCTMRef.current);
600
+ // let newShape = { ...selectedComponent };
601
+ // switch (resizeDirection) {
602
+ // case "top-left":
603
+ // newShape.width = newShape.width + (newShape.x - cursorpt.x);
604
+ // newShape.height = newShape.height + (newShape.y - cursorpt.y);
605
+ // newShape.x = cursorpt.x;
606
+ // newShape.y = cursorpt.y;
607
+ // break;
608
+ // case "top-right":
609
+ // newShape.width = cursorpt.x - newShape.x;
610
+ // newShape.height = newShape.height + (newShape.y - cursorpt.y);
611
+ // newShape.y = cursorpt.y;
612
+ // break;
613
+ // case "bottom-left":
614
+ // newShape.width = newShape.width + (newShape.x - cursorpt.x);
615
+ // newShape.height = cursorpt.y - newShape.y;
616
+ // newShape.x = cursorpt.x;
617
+ // break;
618
+ // case "bottom-right":
619
+ // newShape.width = cursorpt.x - newShape.x;
620
+ // newShape.height = cursorpt.y - newShape.y;
621
+ // break;
622
+ // case "top-center":
623
+ // newShape.height = newShape.height + (newShape.y - cursorpt.y);
624
+ // newShape.y = cursorpt.y;
625
+ // break;
626
+ // case "bottom-center":
627
+ // newShape.height = cursorpt.y - newShape.y;
628
+ // break;
629
+ // case "right-center":
630
+ // newShape.width = cursorpt.x - newShape.x;
631
+ // break;
632
+ // case "left-center":
633
+ // newShape.width = newShape.width + (newShape.x - cursorpt.x);
634
+ // newShape.x = cursorpt.x;
635
+ // break;
636
+ // default:
637
+ // break;
638
+ // }
639
+ // // updateComponentRef({
640
+ // // ...(typeof selectedComponent === "object" && selectedComponent !== null
641
+ // // ? selectedComponent
642
+ // // : {}),
643
+ // // ...newShape,
644
+ // // });
645
+ // requestAnimationFrame(() => {
646
+ // setComponentsState((prev) => {
647
+ // return prev.map((component) => {
648
+ // if (component.id === selectedComponent.id) {
649
+ // return {
650
+ // ...component,
651
+ // ...newShape,
652
+ // };
653
+ // }
654
+ // return component;
655
+ // });
656
+ // });
657
+ // setExtraComponentsState((prev) => {
658
+ // return prev.map((component) => {
659
+ // if (component.id === selectedComponent.id) {
660
+ // return {
661
+ // ...component,
662
+ // ...newShape,
663
+ // };
664
+ // }
665
+ // return component;
666
+ // });
667
+ // });
668
+ // setSelectedComponent({
669
+ // ...selectedComponent,
670
+ // ...newShape,
671
+ // });
672
+ // });
673
+ // debouncedSyncToReduxSelected(newShape);
674
+ // }
675
+ // };
676
+ // const handleTouchEnd = () => {
677
+ // // setMoveComponent(false);
678
+ // // setIsDragging(false);
679
+ // moveComponent.current = false;
680
+ // isDragging.current = false;
681
+ // isTouching.current = false;
682
+ // setResizeDirection(null);
683
+ // };
684
+ const getCursorStyle = () => {
685
+ if (activeTool === "select" && moveComponent.current) {
686
+ return "grabbing";
687
+ }
688
+ else if (activeTool === "select" && resizeDirection) {
689
+ return "grab";
690
+ }
691
+ else if (activeTool === "grab") {
692
+ return "grab";
693
+ }
694
+ else if (activeTool === "ruler") {
695
+ return "crosshair";
696
+ }
697
+ };
698
+ const renderMiniMap = () => {
699
+ return (_jsx(MiniMap, { width: 250, height: 250, children: _jsx("div", { className: "w-full h-full", children: _jsx("svg", { id: "workspace", width: "100%", height: "100%", viewBox: `0 0 ${widthBoard} ${heightBoard}`, className: "h-screen w-full", xmlns: "http://www.w3.org/2000/svg", preserveAspectRatio: "xMidYMid meet", style: {
700
+ background: "#f5f5f5",
701
+ display: "block",
702
+ }, children: _jsx(Layers, { shadowShape: shadowShape, components: [...extraComponentsState, ...componentsState], activeTool: activeTool,
703
+ // onClick={handleSelectComponent}
704
+ // onMouseDown={handleMouseDown}
705
+ // onMouseUp={handleMouseUp}
706
+ // onBlur={handleUnSelectComponent}
707
+ selectedComponent: selectedComponent }) }) }) }));
708
+ };
709
+ const handelZoomIn = () => {
710
+ var _a;
711
+ if (activeTool !== "grab") {
712
+ dispatch({
713
+ type: "tool/setActiveTool",
714
+ payload: "grab",
715
+ });
716
+ }
717
+ (_a = transformRef.current) === null || _a === void 0 ? void 0 : _a.zoomIn();
718
+ };
719
+ const handleZoomOut = () => {
720
+ var _a;
721
+ if (activeTool !== "grab") {
722
+ dispatch({
723
+ type: "tool/setActiveTool",
724
+ payload: "grab",
725
+ });
726
+ }
727
+ (_a = transformRef.current) === null || _a === void 0 ? void 0 : _a.zoomOut();
728
+ };
729
+ // const handleSelectComponent = (item: Component) => {
730
+ // if (activeTool === "select" && item) {
731
+ // if (item.shape === "background") {
732
+ // dispatch({ type: "panel/setSelectedComponent", payload: item });
733
+ // setSelectedComponent(item);
734
+ // return;
735
+ // }
736
+ // if (item.id === selectedComponent?.id) {
737
+ // handleUnSelectComponent();
738
+ // return;
739
+ // }
740
+ // dispatch({ type: "panel/setSelectedComponent", payload: item });
741
+ // setSelectedComponent(item);
742
+ // // setSelectedComponent(item);
743
+ // throttledDispatch(item);
744
+ // }
745
+ // };
746
+ // activeTool === "select" &&
747
+ // moveComponent &&
748
+ // isTouching.current &&
749
+ // !resizeDirection
750
+ const [nodes, setNodes] = useState([
751
+ { x: 80, y: 40 },
752
+ { x: 220, y: 40 },
753
+ { x: 260, y: 160 },
754
+ { x: 40, y: 160 },
755
+ ]);
756
+ const addNode = () => {
757
+ if (nodes.length < 30) {
758
+ const midIndex = Math.floor(nodes.length / 2);
759
+ const prev = nodes[midIndex - 1];
760
+ const curr = nodes[midIndex];
761
+ const newNode = {
762
+ x: (prev.x + curr.x) / 2,
763
+ y: (prev.y + curr.y) / 2,
764
+ };
765
+ const newNodes = [...nodes];
766
+ newNodes.splice(midIndex, 0, newNode);
767
+ setNodes(newNodes);
768
+ }
769
+ };
770
+ const removeNode = () => {
771
+ if (nodes.length > 3) {
772
+ const midIndex = Math.floor(nodes.length / 2);
773
+ const newNodes = [...nodes];
774
+ newNodes.splice(midIndex, 1);
775
+ setNodes(newNodes);
776
+ }
777
+ };
778
+ return (_jsxs(_Fragment, { children: [_jsx(ModalPreview, { children: _jsx(LayerView, { statusKey: "status" }) }), _jsxs("div", { className: "relative w-full h-screen flex-1 overflow-hidden", ref: containerRef, children: [_jsx("div", { className: "absolute bottom-5 left-1/2 transform -translate-x-1/2 z-10", children: _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { icon: _jsx(ZoomIn, {}), onClick: handelZoomIn }), _jsx(Button, { icon: _jsx(ZoomOut, {}), onClick: handleZoomOut }), _jsx(Button, { onClick: addNode, children: "Add Node" }), _jsx(Button, { onClick: removeNode, children: "Remove Node" })] }) }), _jsxs(TransformWrapper, { ref: transformRef, panning: { disabled: ["node", "select"].includes(activeTool) }, centerZoomedOut: true, onTransformed: ({ state: { scale } }) => setScale(scale), minScale: 1, maxScale: 1000, initialScale: 1, pinch: { step: 1 }, smooth: true, doubleClick: { step: 1, disabled: activeTool === "select" }, disablePadding: true, children: [scale > 1 && (_jsx("div", { className: "absolute bottom-[60px] left-1/2 transform -translate-x-1/2 z-10", children: renderMiniMap() })), _jsx(TransformComponent, { wrapperStyle: {
779
+ width: "100%",
780
+ height: "100%",
781
+ overflow: "hidden",
782
+ }, contentStyle: {
783
+ width: "100%",
784
+ height: "100%",
785
+ }, children: _jsxs("svg", { id: "workspace", ref: svgRef, width: "100%", height: "100%", viewBox: `0 0 ${widthBoard} ${heightBoard}`, className: "h-screen", onMouseUp: handleMouseUp, onMouseMove: handleMouseMove,
786
+ // onMouseEnter={handleMouseEnter}
787
+ // onMouseUp={handleEnd}
788
+ onTouchMove: handleMouseMove, onTouchEnd: handleMouseUp, onClick: (e) => {
789
+ e.stopPropagation();
790
+ handleMouseClick(e);
791
+ },
792
+ // onMouseLeave={handleMouseLeave}
793
+ xmlns: "http://www.w3.org/2000/svg", preserveAspectRatio: "xMidYMid meet", style: {
794
+ background: backgroundColor,
795
+ display: "block",
796
+ cursor: activeTool === "ruler" ? "crosshair" : "auto",
797
+ touchAction: "none",
798
+ }, children: [_jsx(Layers, { shadowShape: shadowShape, components: [...extraComponentsState, ...componentsState], style: {
799
+ cursor: getCursorStyle(),
800
+ },
801
+ // onClick={handleSelectComponent}
802
+ onMouseDown: handleMouseDown,
803
+ // onMouseUp={handleMouseUp}
804
+ // onBlur={handleUnSelectComponent}
805
+ selectedComponent: selectedComponent, activeTool: activeTool, onTouchStart: handleMouseDown }), activeTool === "ruler" && (_jsxs(_Fragment, { children: [_jsxs("g", { id: "horizontal-ruler", children: [_jsx("rect", { x: "0", y: "0", width: window.innerWidth, height: "30", fill: "#e0e0e0" }), _jsx("g", { stroke: "#888", "font-size": "10", "text-anchor": "middle", children: Array.from({ length: window.innerWidth / 50 }, (_, i) => (_jsxs("g", { children: [_jsx("line", { x1: i * 50, y1: "0", x2: i * 50, y2: "10" }), _jsx("text", { x: i * 50, y: "15", children: i * 50 })] }, i))) })] }), _jsxs("g", { id: "vertical-ruler", children: [_jsx("rect", { x: "0", y: "0", width: "30", height: window.innerHeight, fill: "#e0e0e0" }), _jsx("g", { stroke: "#888", "font-size": "10", "text-anchor": "middle", children: Array.from({ length: window.innerHeight / 10 }, (_, i) => (_jsxs("g", { children: [_jsx("line", { x1: "0", y1: i * 50, x2: "10", y2: i * 50 }), _jsx("text", { x: "15", y: i * 50, children: i * 50 })] }, i))) })] })] })), grid && (_jsxs("g", { stroke: "#ddd", strokeWidth: 0.5, children: [Array.from({ length: widthBoard / 10 }, (_, i) => (_jsx("line", { x1: i * 10, y1: 0, x2: i * 10, y2: heightBoard }, `v-${i}`))), Array.from({ length: heightBoard / 10 }, (_, i) => (_jsx("line", { x1: 0, y1: i * 10, x2: widthBoard, y2: i * 10 }, `h-${i}`)))] }))] }) })] })] })] }));
806
+ };
807
+ export default BoardTemplate;