seat-editor 2.0.0 → 2.1.1

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