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