seat-editor 2.1.2 → 3.0.0

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 (57) hide show
  1. package/dist/app/constant.d.ts +232 -0
  2. package/dist/app/constant.js +3683 -3045
  3. package/dist/app/new-board/page.js +5 -6
  4. package/dist/app/only-view/chair.d.ts +1 -0
  5. package/dist/app/only-view/chair.js +4 -0
  6. package/dist/app/only-view/constant.d.ts +22 -2
  7. package/dist/app/only-view/constant.js +4 -4
  8. package/dist/app/only-view/page.js +74 -37
  9. package/dist/app/only-view/user.d.ts +1 -0
  10. package/dist/app/only-view/user.js +4 -0
  11. package/dist/components/layer-v3/index.d.ts +23 -4
  12. package/dist/components/layer-v3/index.js +329 -146
  13. package/dist/components/layer-v4/index.d.ts +20 -0
  14. package/dist/components/layer-v4/index.js +445 -0
  15. package/dist/components/lib/index.d.ts +1 -1
  16. package/dist/components/lib/index.js +1 -1
  17. package/dist/features/board/index.js +1 -1
  18. package/dist/features/board-v2/index.js +1 -1
  19. package/dist/features/board-v3/board-slice.d.ts +1 -0
  20. package/dist/features/board-v3/board-slice.js +26 -3
  21. package/dist/features/board-v3/constant.d.ts +5 -0
  22. package/dist/features/board-v3/constant.js +5 -0
  23. package/dist/features/board-v3/index copy.d.ts +47 -0
  24. package/dist/features/board-v3/index copy.js +2073 -0
  25. package/dist/features/board-v3/index.js +1409 -647
  26. package/dist/features/board-v3/polygon.d.ts +28 -0
  27. package/dist/features/board-v3/polygon.js +109 -0
  28. package/dist/features/board-v3/rect.d.ts +9 -0
  29. package/dist/features/board-v3/rect.js +152 -0
  30. package/dist/features/board-v3/resize-element.d.ts +12 -0
  31. package/dist/features/board-v3/resize-element.js +40 -0
  32. package/dist/features/board-v3/utils.d.ts +162 -0
  33. package/dist/features/board-v3/utils.js +787 -0
  34. package/dist/features/package/index.js +1 -1
  35. package/dist/features/panel/index.js +130 -20
  36. package/dist/features/panel/panel-slice.d.ts +5 -0
  37. package/dist/features/panel/panel-slice.js +15 -0
  38. package/dist/features/panel/select-tool.js +11 -1
  39. package/dist/features/panel/selected-group.d.ts +2 -0
  40. package/dist/features/panel/selected-group.js +7 -0
  41. package/dist/features/panel/table-seat-square.d.ts +2 -0
  42. package/dist/features/panel/table-seat-square.js +9 -0
  43. package/dist/features/side-tool/index.js +13 -6
  44. package/dist/features/view-only/index.js +0 -1
  45. package/dist/features/view-only-2/index.js +0 -1
  46. package/dist/features/view-only-3/index.d.ts +68 -0
  47. package/dist/features/view-only-3/index.js +510 -0
  48. package/dist/features/view-only-3/utils.d.ts +1 -0
  49. package/dist/features/view-only-3/utils.js +3 -0
  50. package/dist/seat-editor.css +1 -1
  51. package/dist/utils/constant.d.ts +1 -0
  52. package/dist/utils/constant.js +11 -0
  53. package/dist/utils/format.d.ts +2 -0
  54. package/dist/utils/format.js +29 -0
  55. package/package.json +3 -1
  56. package/dist/features/view/index.d.ts +0 -19
  57. package/dist/features/view/index.js +0 -221
@@ -1,70 +1,222 @@
1
1
  "use client";
2
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";
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ import { TransformWrapper, TransformComponent, } from "react-zoom-pan-pinch";
5
5
  import { useAppSelector, useAppDispatch } from "../../hooks/use-redux";
6
6
  import Layers from "../../components/layer-v3";
7
- import { throttle } from "lodash";
7
+ import { isEmpty, isPlainObject, isUndefined, throttle } from "lodash";
8
8
  import ModalPreview from "../../components/modal-preview";
9
- import LayerView from "../view";
9
+ import LayerView from "../view-only-2";
10
10
  import { isEqual, debounce } from "lodash";
11
11
  import { ZoomIn, ZoomOut } from "lucide-react";
12
12
  import { Button } from "antd";
13
+ import { getAttributeElement, getAttributeElements } from "./resize-element";
14
+ import { applyResizeToSvgElement, arrayToSvgPointsAttr, createTableGhost, getGlobalBBox, getRotation, getSvgElementSize, getTranslate, isClosingPolygon, normalizeAngle, pointsStringToArray, resizeBox, resizeSeatCircle, resizeSeatSquare, stabilizeRotation, stabilizeTranslateOnRotate, updateManyComponents, updateSelectionBox, updateSingleComponent, } from "./utils";
15
+ const toolElement = ["square", "circle", "table-seat-circle"];
16
+ const idSelectionBoxGhost = "selection-box-ghost";
17
+ const nameShapeSelectionBoxGhost = "selection-box";
13
18
  const BoardTemplate = ({ onSelectComponent, viewOnly }) => {
14
19
  const dispatch = useAppDispatch();
15
- const theme = useAppSelector((state) => state.theme);
16
20
  const transformRef = useRef(null);
17
21
  const containerRef = useRef(null);
22
+ const releaseGroupRef = useRef(false);
23
+ const dataSetGhost = useRef(null);
18
24
  const [widthBoard, setWidthBoard] = useState(20000);
19
25
  const [heightBoard, setHeightBoard] = useState(20000);
20
26
  const svgRef = useRef(null);
21
27
  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
28
  const [scale, setScale] = useState(1);
29
+ const [boardSize, setBoardSize] = useState({ width: 20100, height: 20100 });
30
+ const [minCoords, setMinCoords] = useState({ x: -200, y: -200 });
31
+ const [hasInitialized, setHasInitialzed] = useState(false);
32
+ const [isLoading, setIsLoading] = useState(false);
26
33
  const activeTool = useAppSelector((state) => state.tool.active);
27
34
  const grid = useAppSelector((state) => state.tool.grid);
28
35
  const lockBackground = useAppSelector((state) => state.tool.lockBackground);
29
- const { components: componentsProps, extraComponents: extraComponentsProps, flagChange, } = useAppSelector((state) => state.board);
30
- const isTouching = useRef(false);
36
+ const { components: componentsProps, extraComponents: extraComponentsProps, flagChange, updateBy, } = useAppSelector((state) => state.board);
37
+ const { selectionLines } = useAppSelector((state) => state.panel);
38
+ const [selectedLines, setSelectedLines] = useState([]);
39
+ useEffect(() => {
40
+ if (activeTool === "select" || activeTool !== "select") {
41
+ handleUnSelectComponent();
42
+ }
43
+ }, [activeTool]);
44
+ useEffect(() => {
45
+ if (selectionLines) {
46
+ setSelectedLines(selectionLines);
47
+ const idSelected = dataElementSelectionGroupRef.current.map((item) => item.id);
48
+ const newSelectionData = [
49
+ ...componentsState,
50
+ ...extraComponentsState,
51
+ ].filter((comp) => idSelected.includes(comp.id));
52
+ dataElementSelectionGroupRef.current = newSelectionData;
53
+ }
54
+ }, [selectionLines]);
31
55
  useEffect(() => {
32
56
  var _a;
33
57
  if (activeTool !== ((_a = shadowShape[0]) === null || _a === void 0 ? void 0 : _a.shape)) {
34
58
  setShadowShape([]);
35
59
  }
36
60
  }, [activeTool]);
37
- // const [isDragging, setIsDragging] = useState(false);
38
61
  const [resizeDirection, setResizeDirection] = useState(null);
39
62
  const backgroundColor = useAppSelector((state) => state.board.backgroundColor);
40
63
  const selectedComponentProps = useAppSelector((state) => state.panel.selectedComponent);
41
- const screenCTMRef = useRef(null);
42
- const dragIndex = useRef(null);
43
64
  const [componentsState, setComponentsState] = useState([]);
44
65
  const [extraComponentsState, setExtraComponentsState] = useState([]);
45
66
  const [selectedComponent, setSelectedComponent] = useState(null);
46
67
  const isSyncingFromRedux = useRef(false);
47
- const startPos = useRef({ x: 0, y: 0 });
48
68
  const isDragging = useRef(false);
49
69
  const moveComponent = useRef(false);
70
+ useEffect(() => {
71
+ var _a, _b, _c, _d, _e, _f, _g, _h;
72
+ if (hasInitialized)
73
+ return;
74
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
75
+ // let widthMinX = 0;
76
+ // let heightMinY = 0;
77
+ componentsProps === null || componentsProps === void 0 ? void 0 : componentsProps.forEach((_) => {
78
+ var _a, _b, _c, _d;
79
+ let values = _;
80
+ if ((_a = values === null || values === void 0 ? void 0 : values.shape) === null || _a === void 0 ? void 0 : _a.includes("square")) {
81
+ minX = Math.min(minX, values.x);
82
+ minY = Math.min(minY, values.y);
83
+ maxX = Math.max(maxX, values.x + values.width);
84
+ maxY = Math.max(maxY, values.y + values.height);
85
+ }
86
+ if ((_b = values === null || values === void 0 ? void 0 : values.shape) === null || _b === void 0 ? void 0 : _b.includes("circle")) {
87
+ minX = Math.min(minX, values.x);
88
+ minY = Math.min(minY, values.y);
89
+ maxX = Math.max(maxX, values.x + values.width);
90
+ maxY = Math.max(maxY, values.y + values.height);
91
+ }
92
+ if ((_c = values === null || values === void 0 ? void 0 : values.shape) === null || _c === void 0 ? void 0 : _c.includes("table-seat-circle")) {
93
+ minX = Math.min(minX, values.x);
94
+ minY = Math.min(minY, values.y);
95
+ maxX = Math.max(maxX, values.x + values.width);
96
+ maxY = Math.max(maxY, values.y + values.height);
97
+ }
98
+ if ((_d = values === null || values === void 0 ? void 0 : values.shape) === null || _d === void 0 ? void 0 : _d.includes("image-table")) {
99
+ minX = Math.min(minX, values.x);
100
+ minY = Math.min(minY, values.y);
101
+ maxX = Math.max(maxX, values.x + values.width);
102
+ maxY = Math.max(maxY, values.y + values.height);
103
+ }
104
+ // if (minX === _.x) {
105
+ // widthMinX = _.width;
106
+ // }
107
+ // if (minY === _.y) {
108
+ // heightMinY = _.height;
109
+ // }
110
+ });
111
+ extraComponentsProps === null || extraComponentsProps === void 0 ? void 0 : extraComponentsProps.forEach((values) => {
112
+ var _a, _b;
113
+ if ((_a = values === null || values === void 0 ? void 0 : values.shape) === null || _a === void 0 ? void 0 : _a.includes("background")) {
114
+ minX = Math.min(minX, values.x);
115
+ minY = Math.min(minY, values.y);
116
+ maxX = Math.max(maxX, values.x + values.width);
117
+ maxY = Math.max(maxY, values.y + values.height);
118
+ }
119
+ if ((_b = values === null || values === void 0 ? void 0 : values.shape) === null || _b === void 0 ? void 0 : _b.includes("text")) {
120
+ minX = Math.min(minX, values.x);
121
+ minY = Math.min(minY, values.y);
122
+ maxX = Math.max(maxX, values.x + values.width);
123
+ maxY = Math.max(maxY, values.y + values.height);
124
+ }
125
+ // if (minX === values.x) {
126
+ // widthMinX = values.width;
127
+ // }
128
+ // if (minY === values.y) {
129
+ // heightMinY = values.height;
130
+ // }
131
+ });
132
+ let backgroundHasOne = false;
133
+ if ((extraComponentsProps === null || extraComponentsProps === void 0 ? void 0 : extraComponentsProps.length) === 1 &&
134
+ ((_b = (_a = extraComponentsProps === null || extraComponentsProps === void 0 ? void 0 : extraComponentsProps[0]) === null || _a === void 0 ? void 0 : _a.shape) === null || _b === void 0 ? void 0 : _b.includes("background"))) {
135
+ backgroundHasOne = true;
136
+ minX = (_c = extraComponentsProps === null || extraComponentsProps === void 0 ? void 0 : extraComponentsProps[0]) === null || _c === void 0 ? void 0 : _c.x;
137
+ minY = (_d = extraComponentsProps === null || extraComponentsProps === void 0 ? void 0 : extraComponentsProps[0]) === null || _d === void 0 ? void 0 : _d.y;
138
+ maxX = (_e = extraComponentsProps === null || extraComponentsProps === void 0 ? void 0 : extraComponentsProps[0]) === null || _e === void 0 ? void 0 : _e.width;
139
+ maxY = (_f = extraComponentsProps === null || extraComponentsProps === void 0 ? void 0 : extraComponentsProps[0]) === null || _f === void 0 ? void 0 : _f.height;
140
+ // if (minX === extraComponentsProps?.[0]?.x) {
141
+ // widthMinX = extraComponentsProps?.[0]?.width;
142
+ // }
143
+ // if (minY === extraComponentsProps?.[0]?.y) {
144
+ // heightMinY = extraComponentsProps?.[0]?.height;
145
+ // }
146
+ }
147
+ if ((extraComponentsProps === null || extraComponentsProps === void 0 ? void 0 : extraComponentsProps.length) < 1 &&
148
+ ["background", "text"].includes((_g = componentsProps === null || componentsProps === void 0 ? void 0 : componentsProps[0]) === null || _g === void 0 ? void 0 : _g.shape)) {
149
+ minX = minX - minX * 0.5;
150
+ minY = minY - minY * 0.5;
151
+ }
152
+ if ((minX !== Infinity || minY !== Infinity) && !activeTool) {
153
+ (_h = transformRef.current) === null || _h === void 0 ? void 0 : _h.setTransform(-minX, -minY, scale);
154
+ setHasInitialzed(true);
155
+ }
156
+ // }
157
+ // if (!backgroundHasOne) {
158
+ // setMinCoords({ x: minX - minX * 0.5, y: minY - minY * 0.5 });
159
+ // }
160
+ // if(maxX > boardSize.width){
161
+ // setBoardSize((prev) => ({ ...prev, width: maxX }));
162
+ // }
163
+ // if(maxY > boardSize.height){
164
+ // setBoardSize((prev) => ({ ...prev, height: maxY }));
165
+ // }
166
+ // return {
167
+ // minX: backgroundHasOne ? minX : minX - minX * 0.5,
168
+ // minY: backgroundHasOne ? minY : minY - minY * 0.5,
169
+ // width: maxX,
170
+ // height: maxY,
171
+ // };
172
+ }, [componentsProps, extraComponentsProps]);
50
173
  const debouncedSyncToReduxSelected = useRef(debounce((data) => {
51
174
  throttledDispatch(data);
52
175
  }, 300)).current;
53
- const debouncedSyncComponents = useRef(debounce((data) => {
176
+ const updateQueue = useRef([]);
177
+ const isFlushing = useRef(false);
178
+ const updateFlushToRedux = () => {
179
+ if (isFlushing.current)
180
+ return;
181
+ isFlushing.current = true;
182
+ requestAnimationFrame(() => {
183
+ const batch = updateQueue.current;
184
+ updateQueue.current = [];
185
+ isFlushing.current = false;
186
+ dispatch({
187
+ type: "board/setNewComponents",
188
+ payload: batch === null || batch === void 0 ? void 0 : batch[0],
189
+ });
190
+ });
191
+ };
192
+ const queueUpdateComponents = (data) => {
54
193
  dispatch({
55
194
  type: "board/setNewComponents",
56
195
  payload: data,
57
196
  });
58
- }, 300));
197
+ };
198
+ const queueUpdateExtraComponents = (data) => {
199
+ dispatch({
200
+ type: "board/setNewExtraComponents",
201
+ payload: data,
202
+ });
203
+ };
59
204
  const debouncedSyncExtraComponents = useRef(debounce((data) => {
60
205
  dispatch({
61
206
  type: "board/setNewExtraComponents",
62
207
  payload: data,
63
208
  });
209
+ }, 1000));
210
+ const debouncedUpdateSelectedLines = useRef(debounce((data) => {
211
+ const id = data;
212
+ const { g } = getAttributeElement(svgRef.current, id);
213
+ const getBBox = getGlobalBBox(svgRef.current, g);
214
+ console.log("masukkk update");
215
+ setSelectedLines((prev) => (Object.assign(Object.assign({}, prev), getBBox)));
64
216
  }, 300));
65
217
  // Redux → Local
66
218
  useEffect(() => {
67
- if (flagChange) {
219
+ if (flagChange && updateBy === "global") {
68
220
  if (!isEqual(componentsProps, componentsState)) {
69
221
  isSyncingFromRedux.current = true;
70
222
  setComponentsState(componentsProps !== null && componentsProps !== void 0 ? componentsProps : []);
@@ -76,44 +228,50 @@ const BoardTemplate = ({ onSelectComponent, viewOnly }) => {
76
228
  if (!isEqual(selectedComponentProps, selectedComponent)) {
77
229
  isSyncingFromRedux.current = true;
78
230
  setSelectedComponent(selectedComponentProps !== null && selectedComponentProps !== void 0 ? selectedComponentProps : []);
231
+ console.log("masukkk");
232
+ debouncedUpdateSelectedLines.current(selectedComponentProps === null || selectedComponentProps === void 0 ? void 0 : selectedComponentProps.id);
79
233
  }
80
234
  dispatch({ type: "board/setFlagChange", payload: false });
81
235
  }
82
236
  }, [
83
237
  componentsProps,
84
238
  extraComponentsProps,
85
- selectedComponentProps,
86
- flagChange,
239
+ // selectedComponentProps,
240
+ // flagChange,
87
241
  ]);
88
- // Local Redux
89
- useEffect(() => {
90
- if (isSyncingFromRedux.current) {
91
- isSyncingFromRedux.current = false;
242
+ const updateComponentAttribute = (component) => {
243
+ if (!component)
92
244
  return;
245
+ const updatedComponents = updateSingleComponent(componentsState, component, setComponentsState);
246
+ if (updatedComponents) {
247
+ dispatch({ type: "board/setUpdateBy", payload: "local" });
248
+ queueUpdateComponents(updatedComponents);
93
249
  }
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]);
250
+ const updatedExtra = updateSingleComponent(extraComponentsState, component, setExtraComponentsState);
251
+ if (updatedExtra) {
252
+ dispatch({ type: "board/setUpdateBy", payload: "local" });
253
+ queueUpdateExtraComponents(updatedExtra);
254
+ debouncedSyncExtraComponents.current(updatedExtra);
113
255
  }
114
- else {
115
- setComponentsState((prev) => [...prev, payload]);
256
+ };
257
+ const updateComponentsAttribute = (components) => {
258
+ if (!components.length)
259
+ return;
260
+ const isExtra = components === null || components === void 0 ? void 0 : components.filter((item) => (item === null || item === void 0 ? void 0 : item.shape) === "polygon");
261
+ if (isExtra) {
262
+ const nextExtra = updateManyComponents(extraComponentsState, components, setExtraComponentsState);
263
+ dispatch({ type: "board/setUpdateBy", payload: "local" });
264
+ queueUpdateComponents(nextExtra);
116
265
  }
266
+ const nextComponents = updateManyComponents(componentsState, components, setComponentsState);
267
+ dispatch({ type: "board/setUpdateBy", payload: "local" });
268
+ queueUpdateExtraComponents(nextComponents);
269
+ };
270
+ const addComponents = (components) => {
271
+ const newComponentState = [...extraComponentsState, components];
272
+ setExtraComponentsState(newComponentState);
273
+ dispatch({ type: "board/setUpdateBy", payload: "local" });
274
+ dispatch({ type: "board/setExtraComponent", payload: components });
117
275
  };
118
276
  const getSvgCoords = (e) => {
119
277
  var _a;
@@ -124,154 +282,6 @@ const BoardTemplate = ({ onSelectComponent, viewOnly }) => {
124
282
  const transformed = point.matrixTransform((_a = svg.getScreenCTM()) === null || _a === void 0 ? void 0 : _a.inverse());
125
283
  return { x: transformed.x, y: transformed.y };
126
284
  };
127
- const createShape = (x, y, fill) => ({
128
- x,
129
- y,
130
- width: 50 / scale,
131
- height: 50 / scale,
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
285
  const throttledDispatch = useCallback(throttle((component) => {
276
286
  // dispatch({
277
287
  // type: "board/updateComponent",
@@ -283,372 +293,6 @@ const BoardTemplate = ({ onSelectComponent, viewOnly }) => {
283
293
  });
284
294
  }, 16), // 16ms ≈ 60fps
285
295
  [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 - 50 - positionX) / scale;
349
- const currentY = (coords.y + workspaceRect.top - positionY) / scale;
350
- const { x, y, width, height } = selectedComponent;
351
- let newShape = Object.assign({}, selectedComponent);
352
- switch (resizeDirection) {
353
- case "top-left":
354
- newShape.width = width + (x - currentX);
355
- newShape.height = height + (y - currentY);
356
- newShape.x = currentX;
357
- newShape.y = currentY;
358
- break;
359
- case "top-right":
360
- newShape.width = currentX - newShape.x;
361
- newShape.height = newShape.height + (newShape.y - currentY);
362
- newShape.y = currentY;
363
- break;
364
- case "bottom-left":
365
- newShape.width += newShape.x - currentX;
366
- newShape.height = currentY - newShape.y;
367
- newShape.x = currentX;
368
- break;
369
- case "bottom-right":
370
- newShape.width = currentX - newShape.x;
371
- newShape.height = currentY - newShape.y;
372
- break;
373
- case "left":
374
- newShape.width += newShape.x - currentX;
375
- newShape.x = currentX;
376
- break;
377
- case "right":
378
- newShape.width = currentX - newShape.x;
379
- break;
380
- case "top": {
381
- newShape.height += newShape.y - currentY;
382
- newShape.y = currentY;
383
- break;
384
- }
385
- case "bottom":
386
- newShape.height = currentY - newShape.y;
387
- break;
388
- default:
389
- break;
390
- }
391
- requestAnimationFrame(() => {
392
- setComponentsState((prev) => {
393
- return prev.map((component) => {
394
- if (component.id === selectedComponent.id) {
395
- return Object.assign(Object.assign({}, component), newShape);
396
- }
397
- return component;
398
- });
399
- });
400
- setExtraComponentsState((prev) => {
401
- return prev.map((component) => {
402
- if (component.id === selectedComponent.id) {
403
- return Object.assign(Object.assign({}, component), newShape);
404
- }
405
- return component;
406
- });
407
- });
408
- setSelectedComponent(newShape);
409
- });
410
- debouncedSyncToReduxSelected(newShape);
411
- }
412
- };
413
- const handleMouseUp = () => {
414
- if (["select", "node"].includes(activeTool) && selectedComponent) {
415
- setResizeDirection(null);
416
- moveComponent.current = false;
417
- }
418
- };
419
- // useEffect(() => {
420
- // if (containerRef.current) {
421
- // setWidthBoard(containerRef.current.offsetWidth);
422
- // setHeightBoard(containerRef.current.offsetHeight);
423
- // }
424
- // }, [
425
- // containerRef?.current?.offsetWidth,
426
- // containerRef?.current?.offsetHeight,
427
- // viewOnly,
428
- // ]);
429
- const handleUnSelectComponent = () => {
430
- dispatch({ type: "panel/setSelectedComponent", payload: null });
431
- setSelectedComponent(null);
432
- };
433
- // const handleTouchStart = (
434
- // e: React.TouchEvent<
435
- // SVGRectElement | SVGCircleElement | SVGTextElement | SVGImageElement
436
- // >,
437
- // items: any,
438
- // direction?: string
439
- // ) => {
440
- // if (activeTool === "node" && !direction && items) {
441
- // // dispatch({ type: "panel/setShow", payload: false });
442
- // // setMoveComponent(true);
443
- // moveComponent.current = true;
444
- // isTouching.current = true;
445
- // // dispatch({ type: "panel/setSelectedComponent", payload: item });
446
- // onSelectComponent && onSelectComponent(items);
447
- // dispatch({ type: "panel/setSelectedComponent", payload: items });
448
- // setSelectedComponent(items);
449
- // // selectedComponentRef.current = items;
450
- // const touch = e.touches[0];
451
- // const svg = e.currentTarget.ownerSVGElement;
452
- // const pt = svg.createSVGPoint();
453
- // if (!svg) return;
454
- // pt.x = touch.clientX;
455
- // pt.y = touch.clientY;
456
- // const cursorpt = pt.matrixTransform(svg.getScreenCTM()?.inverse());
457
- // screenCTMRef.current = svg.getScreenCTM()?.inverse() || null;
458
- // setDragOffset({
459
- // x: cursorpt.x - items.x,
460
- // y: cursorpt.y - items.y,
461
- // });
462
- // // dragOffset.current = {
463
- // // x: cursorpt.x - items.x,
464
- // // y: cursorpt.y - items.y
465
- // // }
466
- // } else if (activeTool === "select" && direction) {
467
- // setResizeDirection(direction);
468
- // // setIsDragging(true);
469
- // // setMoveComponent(true);
470
- // moveComponent.current = true;
471
- // isDragging.current = true;
472
- // isTouching.current = true;
473
- // const touch = e.touches[0];
474
- // const svg = e.currentTarget.ownerSVGElement;
475
- // const pt = svg.createSVGPoint();
476
- // if (!svg) return;
477
- // pt.x = touch.clientX;
478
- // pt.y = touch.clientY;
479
- // const cursorpt = pt.matrixTransform(svg.getScreenCTM()?.inverse());
480
- // screenCTMRef.current = svg.getScreenCTM()?.inverse() || null;
481
- // setDragOffset({
482
- // x: cursorpt.x - items.x,
483
- // y: cursorpt.y - items.y,
484
- // });
485
- // // dragOffset.current = {
486
- // // x: cursorpt.x - items.x,
487
- // // y: cursorpt.y - items.y
488
- // // }
489
- // }
490
- // };
491
- // const handleTouchMove = (
492
- // e: React.TouchEvent<
493
- // SVGRectElement | SVGCircleElement | SVGTextElement | SVGImageElement
494
- // >
495
- // ) => {
496
- // if (
497
- // activeTool === "node" &&
498
- // moveComponent &&
499
- // isTouching.current &&
500
- // !resizeDirection
501
- // ) {
502
- // isDragging.current = true;
503
- // moveComponent.current = true;
504
- // const touch = e.touches[0];
505
- // const svg = e.currentTarget.ownerSVGElement;
506
- // if (!svg) return;
507
- // const pt = svg.createSVGPoint();
508
- // pt.x = touch.clientX;
509
- // pt.y = touch.clientY;
510
- // const cursorpt = pt.matrixTransform(screenCTMRef.current);
511
- // requestAnimationFrame(() => {
512
- // if (selectedComponent?.shape != "background") {
513
- // setComponentsState((prev) => {
514
- // return prev.map((component) => {
515
- // if (component.id === selectedComponent.id) {
516
- // return {
517
- // ...component,
518
- // x: cursorpt.x - dragOffset?.x,
519
- // y: cursorpt.y - dragOffset?.y,
520
- // };
521
- // }
522
- // return component;
523
- // });
524
- // });
525
- // }
526
- // if (selectedComponent?.shape == "background") {
527
- // setExtraComponentsState((prev) => {
528
- // return prev.map((component) => {
529
- // if (component.id === selectedComponent.id) {
530
- // return {
531
- // ...component,
532
- // x: cursorpt.x - dragOffset?.x,
533
- // y: cursorpt.y - dragOffset?.y,
534
- // };
535
- // }
536
- // return component;
537
- // });
538
- // });
539
- // }
540
- // setSelectedComponent({
541
- // ...selectedComponent,
542
- // x: cursorpt.x - dragOffset?.x,
543
- // y: cursorpt.y - dragOffset?.y,
544
- // });
545
- // });
546
- // // updateComponentRef({
547
- // // ...(typeof selectedComponent === "object" && selectedComponent !== null
548
- // // ? selectedComponent
549
- // // : {}),
550
- // // x: cursorpt.x - dragOffset?.current.x,
551
- // // y: cursorpt.y - dragOffset?.current.y,
552
- // // });
553
- // } else if (
554
- // activeTool === "select" &&
555
- // moveComponent.current &&
556
- // isTouching.current &&
557
- // resizeDirection
558
- // ) {
559
- // // setIsDragging(true);
560
- // isDragging.current = true;
561
- // const touch = e.touches[0];
562
- // const svg = e.currentTarget.ownerSVGElement;
563
- // if (!svg) return;
564
- // const pt = svg.createSVGPoint();
565
- // pt.x = touch.clientX;
566
- // pt.y = touch.clientY;
567
- // const cursorpt = pt.matrixTransform(screenCTMRef.current);
568
- // let newShape = { ...selectedComponent };
569
- // switch (resizeDirection) {
570
- // case "top-left":
571
- // newShape.width = newShape.width + (newShape.x - cursorpt.x);
572
- // newShape.height = newShape.height + (newShape.y - cursorpt.y);
573
- // newShape.x = cursorpt.x;
574
- // newShape.y = cursorpt.y;
575
- // break;
576
- // case "top-right":
577
- // newShape.width = cursorpt.x - newShape.x;
578
- // newShape.height = newShape.height + (newShape.y - cursorpt.y);
579
- // newShape.y = cursorpt.y;
580
- // break;
581
- // case "bottom-left":
582
- // newShape.width = newShape.width + (newShape.x - cursorpt.x);
583
- // newShape.height = cursorpt.y - newShape.y;
584
- // newShape.x = cursorpt.x;
585
- // break;
586
- // case "bottom-right":
587
- // newShape.width = cursorpt.x - newShape.x;
588
- // newShape.height = cursorpt.y - newShape.y;
589
- // break;
590
- // case "top-center":
591
- // newShape.height = newShape.height + (newShape.y - cursorpt.y);
592
- // newShape.y = cursorpt.y;
593
- // break;
594
- // case "bottom-center":
595
- // newShape.height = cursorpt.y - newShape.y;
596
- // break;
597
- // case "right-center":
598
- // newShape.width = cursorpt.x - newShape.x;
599
- // break;
600
- // case "left-center":
601
- // newShape.width = newShape.width + (newShape.x - cursorpt.x);
602
- // newShape.x = cursorpt.x;
603
- // break;
604
- // default:
605
- // break;
606
- // }
607
- // // updateComponentRef({
608
- // // ...(typeof selectedComponent === "object" && selectedComponent !== null
609
- // // ? selectedComponent
610
- // // : {}),
611
- // // ...newShape,
612
- // // });
613
- // requestAnimationFrame(() => {
614
- // setComponentsState((prev) => {
615
- // return prev.map((component) => {
616
- // if (component.id === selectedComponent.id) {
617
- // return {
618
- // ...component,
619
- // ...newShape,
620
- // };
621
- // }
622
- // return component;
623
- // });
624
- // });
625
- // setExtraComponentsState((prev) => {
626
- // return prev.map((component) => {
627
- // if (component.id === selectedComponent.id) {
628
- // return {
629
- // ...component,
630
- // ...newShape,
631
- // };
632
- // }
633
- // return component;
634
- // });
635
- // });
636
- // setSelectedComponent({
637
- // ...selectedComponent,
638
- // ...newShape,
639
- // });
640
- // });
641
- // debouncedSyncToReduxSelected(newShape);
642
- // }
643
- // };
644
- // const handleTouchEnd = () => {
645
- // // setMoveComponent(false);
646
- // // setIsDragging(false);
647
- // moveComponent.current = false;
648
- // isDragging.current = false;
649
- // isTouching.current = false;
650
- // setResizeDirection(null);
651
- // };
652
296
  const getCursorStyle = () => {
653
297
  if (activeTool === "select" && moveComponent.current) {
654
298
  return "grabbing";
@@ -663,19 +307,6 @@ const BoardTemplate = ({ onSelectComponent, viewOnly }) => {
663
307
  return "crosshair";
664
308
  }
665
309
  };
666
- const renderMiniMap = () => {
667
- return (_jsx(MiniMap, { width: 250, height: 250, children: _jsx("div", { className: "w-full h-full", children: _jsx("svg", { id: "workspace", width: "100%", height: "100%",
668
- // viewBox={`0 0 ${widthBoard} ${heightBoard}`}
669
- className: "h-screen w-full", xmlns: "http://www.w3.org/2000/svg", preserveAspectRatio: "xMidYMid meet", style: {
670
- background: "#f5f5f5",
671
- display: "block",
672
- }, children: _jsx(Layers, { shadowShape: shadowShape, components: [...extraComponentsState, ...componentsState], activeTool: activeTool,
673
- // onClick={handleSelectComponent}
674
- onMouseDown: handleMouseDown,
675
- // onMouseUp={handleMouseUp}
676
- // onBlur={handleUnSelectComponent}
677
- selectedComponent: selectedComponent }) }) }) }));
678
- };
679
310
  const handelZoomIn = () => {
680
311
  var _a;
681
312
  if (activeTool !== "grab") {
@@ -696,90 +327,1221 @@ const BoardTemplate = ({ onSelectComponent, viewOnly }) => {
696
327
  }
697
328
  (_a = transformRef.current) === null || _a === void 0 ? void 0 : _a.zoomOut();
698
329
  };
699
- // const handleSelectComponent = (item: Component) => {
700
- // if (activeTool === "select" && item) {
701
- // if (item.shape === "background") {
702
- // dispatch({ type: "panel/setSelectedComponent", payload: item });
703
- // setSelectedComponent(item);
704
- // return;
705
- // }
706
- // if (item.id === selectedComponent?.id) {
707
- // handleUnSelectComponent();
708
- // return;
709
- // }
710
- // dispatch({ type: "panel/setSelectedComponent", payload: item });
711
- // setSelectedComponent(item);
712
- // // setSelectedComponent(item);
713
- // throttledDispatch(item);
714
- // }
715
- // };
716
- // activeTool === "select" &&
717
- // moveComponent &&
718
- // isTouching.current &&
719
- // !resizeDirection
720
- // const [nodes, setNodes] = useState([
721
- // { x: 80, y: 40 },
722
- // { x: 220, y: 40 },
723
- // { x: 260, y: 160 },
724
- // { x: 40, y: 160 },
725
- // ]);
726
- const addNode = () => {
727
- // if (nodes.length < 30) {
728
- // const midIndex = Math.floor(nodes.length / 2);
729
- // const prev = nodes[midIndex - 1];
730
- // const curr = nodes[midIndex];
731
- // const newNode = {
732
- // x: (prev.x + curr.x) / 2,
733
- // y: (prev.y + curr.y) / 2,
734
- // };
735
- // const newNodes = [...nodes];
736
- // newNodes.splice(midIndex, 0, newNode);
737
- // setNodes(newNodes);
738
- // }
330
+ // const [touch, setTouch] = useState(false);
331
+ const handleUnSelectComponent = () => {
332
+ dispatch({ type: "panel/setSelectedComponent", payload: null });
333
+ setSelectedComponent(null);
334
+ setSelectedLines(null);
335
+ dispatch({ type: "panel/setShow", payload: false });
336
+ dataElementSelectionGroupRef.current = [];
739
337
  };
740
- const removeNode = () => {
741
- // if (nodes.length > 3) {
742
- // const midIndex = Math.floor(nodes.length / 2);
743
- // const newNodes = [...nodes];
744
- // newNodes.splice(midIndex, 1);
745
- // setNodes(newNodes);
338
+ const startAngleRef = useRef(0);
339
+ const startRotationRef = useRef(0);
340
+ const ghostRotateElement = useRef(0);
341
+ const isResizeRef = useRef(false);
342
+ const isResizeSelectionRef = useRef(false);
343
+ const selectionDataRef = useRef([]);
344
+ // const selectionElementsRef = useRef<any>([]);
345
+ // const selectionElementRawsRef = useRef<any>([]);
346
+ const hadSelectionRef = useRef(false);
347
+ //FLAGE EVERY HANDLE EVENT
348
+ //CREATE
349
+ const isCreateElementRef = useRef(false);
350
+ //RESIZE
351
+ const onResizeSelectionRef = useRef(false);
352
+ //ROTATE
353
+ const isRotatingRef = useRef(false);
354
+ const rotationSelectionRef = useRef(0);
355
+ //DRAG/MOVE
356
+ //SELECT
357
+ const isSelectingRef = useRef(false);
358
+ const activeIdSelectedRef = useRef(null);
359
+ //SELECTION
360
+ const selectionLinesRef = useRef(null);
361
+ const onMakeSelectionRef = useRef(false);
362
+ // const dataElementSelectionGroupRawRef = useRef<Element[]>([]);
363
+ const onMoveSelectionBoxRef = useRef(false);
364
+ const onResizeSelectionBoxRef = useRef(false);
365
+ const dataElementSelectionGroupRef = useRef([]);
366
+ //polygon
367
+ const isPolygonRef = useRef(false);
368
+ const polygonElementRef = useRef([]);
369
+ const isOnMakePolygonRef = useRef(false);
370
+ const startPointPolygonLineRef = useRef({ x: 0, y: 0 });
371
+ const handlePointerDown = (e) => {
372
+ var _a, _b, _c, _d, _e;
373
+ const shiftActive = e.shiftKey;
374
+ console.log("shiftActive", shiftActive);
375
+ const svg = svgRef.current;
376
+ if (!e.isPrimary)
377
+ return;
378
+ if (!svg)
379
+ return;
380
+ isDragging.current = false;
381
+ let hasMoved = false;
382
+ releaseGroupRef.current = false;
383
+ const startX = e.clientX;
384
+ const startY = e.clientY;
385
+ const pt = svg.createSVGPoint();
386
+ pt.x = e.clientX;
387
+ pt.y = e.clientY;
388
+ const { x, y } = getSvgCoords(e);
389
+ //CREATE ELEMENT
390
+ const isInitialCreateElemente = toolElement.includes(activeTool) && !isCreateElementRef.current;
391
+ if (isInitialCreateElemente) {
392
+ console.log("INITIAL CREATE ELEMENT");
393
+ const tables = createTableGhost({
394
+ x,
395
+ y,
396
+ width: 1,
397
+ height: 1,
398
+ fill: "red",
399
+ shape: activeTool,
400
+ });
401
+ // setGhostCreateElement(tables);
402
+ (_a = svgRef.current) === null || _a === void 0 ? void 0 : _a.appendChild(tables);
403
+ isCreateElementRef.current = true;
404
+ }
405
+ const targetSelection = e.target.closest("g[id='selection-lines']");
406
+ //ROTATE
407
+ const targetRotate = e.target.closest("circle[data-role]");
408
+ if (targetRotate) {
409
+ console.log("TARGET ROTATE");
410
+ isRotatingRef.current = true;
411
+ }
412
+ // RESIZE
413
+ const targetGroup = e.target.closest("g[data-id]");
414
+ const targetPointPolygon = e.target.closest("circle[data-point]");
415
+ // TARGET ELEMENT
416
+ let idTargetElement = JSON.parse((targetGroup === null || targetGroup === void 0 ? void 0 : targetGroup.getAttribute("data-id")) || "{}");
417
+ const selectionTarget = (_c = (_b = targetSelection === null || targetSelection === void 0 ? void 0 : targetSelection.dataset) === null || _b === void 0 ? void 0 : _b.selection) === null || _c === void 0 ? void 0 : _c.replace("selection-", "");
418
+ const activeId = selectionTarget !== null && selectionTarget !== void 0 ? selectionTarget : idTargetElement;
419
+ const isInSelectionTarget = !isUndefined(selectionTarget);
420
+ const isInTargetElement = !isPlainObject(idTargetElement);
421
+ const isSingleSelection = isInSelectionTarget && (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id) === activeId;
422
+ console.log("activeId", activeId);
423
+ const { g, inner } = getAttributeElement(svg, activeId);
424
+ if (targetGroup && shiftActive) {
425
+ const findById = [...componentsState, ...extraComponentsState].find((comp) => comp.id == activeId);
426
+ console.log("findById", findById, "HIT TARGET USING SHIFT");
427
+ const dataSelection = [...dataElementSelectionGroupRef.current, findById];
428
+ dataElementSelectionGroupRef.current = dataSelection;
429
+ }
430
+ const box = getGlobalBBox(svg, g);
431
+ const { x: initialXG, y: initialYG } = getTranslate(g);
432
+ const targetDragPosition = e.target.closest("circle[data-position]");
433
+ const { clientX, clientY } = e;
434
+ const hitPoint = document.elementFromPoint(clientX, clientY);
435
+ // CHECK FOR HIT ON SVG FOR SELECTION BOX
436
+ // MAKE AND UNMAKE SELECTION BOX START ------
437
+ const hadSelectionBox = ((_d = dataElementSelectionGroupRef.current) === null || _d === void 0 ? void 0 : _d.length) > 0 && !isSingleSelection;
438
+ const downInSelectionBox = hadSelectionBox && (hitPoint === null || hitPoint === void 0 ? void 0 : hitPoint.nodeName) !== "svg";
439
+ const downOutSelectionBox = hadSelectionBox && (hitPoint === null || hitPoint === void 0 ? void 0 : hitPoint.nodeName) === "svg";
440
+ const downBeforeHasSelectionBox = !downInSelectionBox &&
441
+ (hitPoint === null || hitPoint === void 0 ? void 0 : hitPoint.nodeName) === "svg" &&
442
+ activeTool === "select";
443
+ const isRotateSelectionBox = targetRotate && hadSelectionBox;
444
+ let currentRotation = 0;
445
+ if (isRotateSelectionBox) {
446
+ console.log("LAGI ROTATE SELECTION BOX");
447
+ currentRotation = rotationSelectionRef.current;
448
+ }
449
+ //move tanpa ada selection single element dan bisa move juga ketika ada selection box
450
+ //JIKA PUNYA SELECTION TAPI DOWN DI ELEMENT LAIN
451
+ const downInMatchSelectionBox = downInSelectionBox && (hitPoint === null || hitPoint === void 0 ? void 0 : hitPoint.nodeName) !== "svg" && isInSelectionTarget;
452
+ if (downInSelectionBox) {
453
+ console.log("HIT IN SELECTION BOX");
454
+ hadSelectionRef.current = true;
455
+ }
456
+ if (downOutSelectionBox) {
457
+ console.log("HIT OUT SELECTION BOX");
458
+ hadSelectionRef.current = false;
459
+ onMoveSelectionBoxRef.current = false;
460
+ handleUnSelectComponent();
461
+ }
462
+ if (downBeforeHasSelectionBox) {
463
+ console.log("HIT BEFORE HAS SELECTION BOX");
464
+ // RELEASE SELECT
465
+ releaseGroupRef.current = true;
466
+ // MAKING SELECTION BOX DOWN
467
+ onMakeSelectionRef.current = true;
468
+ onMoveSelectionBoxRef.current = false;
469
+ handleUnSelectComponent();
470
+ const boxSelection = createTableGhost({
471
+ x,
472
+ y,
473
+ width: 1,
474
+ height: 1,
475
+ fill: "transparent",
476
+ shape: nameShapeSelectionBoxGhost,
477
+ id: idSelectionBoxGhost,
478
+ });
479
+ (_e = svgRef.current) === null || _e === void 0 ? void 0 : _e.appendChild(boxSelection);
480
+ }
481
+ // MAKE AND UNMAKE SELECTION BOX END ------
482
+ // RESIZE SELECTION BOX
483
+ const resizeSide = (targetDragPosition === null || targetDragPosition === void 0 ? void 0 : targetDragPosition.dataset.position) || "{}";
484
+ const downAtResizePosition = resizeSide !== "{}";
485
+ const downOutResizePosition = resizeSide === "{}";
486
+ //down in selection box (need check element didalammnya)
487
+ const downOutResizePositionAndInSelectionBox = downOutResizePosition &&
488
+ hadSelectionBox &&
489
+ !downOutSelectionBox &&
490
+ isInSelectionTarget &&
491
+ !isSingleSelection &&
492
+ !isInTargetElement;
493
+ const downAtResizePositionAndHasSelectionBox = downAtResizePosition && hadSelectionBox && !isRotateSelectionBox;
494
+ const isMightResizeElement = !isEmpty(selectedComponent) &&
495
+ downAtResizePosition &&
496
+ downAtResizePosition &&
497
+ !hadSelectionBox;
498
+ const isMightMove = activeId &&
499
+ !targetPointPolygon &&
500
+ isInTargetElement &&
501
+ !isMightResizeElement;
502
+ const isMightMoveOneElementSelection = isSingleSelection && !isMightResizeElement;
503
+ console.log({ isMightResizeElement });
504
+ // if (
505
+ // !downInMatchSelectionBox &&
506
+ // !downAtResizePositionAndHasSelectionBox &&
507
+ // !targetRotate &&
508
+ // !isMightResizeElement &&
509
+ // !targetPointPolygon &&
510
+ // !isMightMove &&
511
+ // !targetSelection
512
+ // ) {
513
+ // console.log("MAUK UNSELET");
514
+ // hadSelectionRef.current = false;
515
+ // onMoveSelectionBoxRef.current = false;
516
+ // handleUnSelectComponent();
517
+ // selectionLinesRef.current = null;
746
518
  // }
519
+ if (downOutResizePositionAndInSelectionBox) {
520
+ console.log("DOWN OUT RESIZE POSITION AND IN SELECTION BOX");
521
+ onMoveSelectionBoxRef.current = true;
522
+ }
523
+ if (downAtResizePosition) {
524
+ console.log("DOWN AT RESIZE POSITION");
525
+ onResizeSelectionRef.current = true;
526
+ }
527
+ // targetGroup?.removeAttribute("transform");
528
+ const mousePositionInGroup = {
529
+ x: x - (box === null || box === void 0 ? void 0 : box.x),
530
+ y: y - (box === null || box === void 0 ? void 0 : box.y),
531
+ };
532
+ const offset = {
533
+ x: x - initialXG,
534
+ y: y - initialYG,
535
+ };
536
+ // create polygon
537
+ const isInitialPolyGon = activeTool === "polygon" && !isCreateElementRef.current;
538
+ if (isInitialPolyGon && (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.shape) !== "polygon") {
539
+ console.log("DOWN CREATE POLYGON");
540
+ const newPolygon = {
541
+ id: `${Date.now()}`,
542
+ shape: "polygon",
543
+ fill: "red",
544
+ points: [{ x, y }],
545
+ rotation: 0,
546
+ };
547
+ polygonElementRef.current = newPolygon;
548
+ // addComponents(newPolygon);
549
+ setSelectedComponent(newPolygon);
550
+ dispatch({
551
+ type: "panel/setSelectedComponent",
552
+ payload: newPolygon,
553
+ });
554
+ isOnMakePolygonRef.current = true;
555
+ }
556
+ // const selectionLines = svgRef.current?.querySelector(
557
+ // "#selection-lines"
558
+ // ) as SVGGElement;
559
+ // const boxSelection = svgRef.current?.querySelector(
560
+ // "#rect-box-selection"
561
+ // ) as SVGRectElement;
562
+ // const allElementInSelection = svgRef.current?.querySelectorAll(
563
+ // "#ghost-element-has-selection"
564
+ // );
565
+ const pointerHandleMove = (ev) => {
566
+ var _a;
567
+ //SVG POINTER
568
+ const pt = svg.createSVGPoint();
569
+ pt.x = ev.clientX;
570
+ pt.y = ev.clientY;
571
+ const pos = pt.matrixTransform(svg.getScreenCTM().inverse());
572
+ //RESIZE POLYGON
573
+ const onResizePolygon = (pos) => {
574
+ var _a, _b;
575
+ console.log("on resize polygon");
576
+ const dx = pos.x - x;
577
+ const dy = pos.y - y;
578
+ const { g, inner, element } = getAttributeElement(svg, activeId);
579
+ const angleDeg = getRotation(inner.transform.baseVal); // 0–360
580
+ const angleRad = (angleDeg * Math.PI) / 180;
581
+ const cos = Math.cos(-angleRad);
582
+ const sin = Math.sin(-angleRad);
583
+ const localDx = dx * cos - dy * sin;
584
+ const localDy = dx * sin + dy * cos;
585
+ const index = Number(targetPointPolygon.getAttribute("id"));
586
+ const points = element === null || element === void 0 ? void 0 : element.getAttribute("points");
587
+ let arrayPoints = pointsStringToArray(points);
588
+ const pointsStart = (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.points) || [];
589
+ arrayPoints[index] = {
590
+ x: ((_a = pointsStart[index]) === null || _a === void 0 ? void 0 : _a.x) + localDx,
591
+ y: ((_b = pointsStart[index]) === null || _b === void 0 ? void 0 : _b.y) + localDy,
592
+ };
593
+ const newPointsAttr = arrayToSvgPointsAttr(arrayPoints);
594
+ element === null || element === void 0 ? void 0 : element.setAttribute("points", newPointsAttr);
595
+ };
596
+ if (targetPointPolygon && targetGroup) {
597
+ onResizePolygon(pos);
598
+ }
599
+ //ROTATE SELECTION BOX
600
+ const onRotateSelectionBox = (pos) => {
601
+ var _a, _b, _c, _d;
602
+ console.log("rotate selection");
603
+ const selectionLines = (_a = svgRef.current) === null || _a === void 0 ? void 0 : _a.querySelector("#selection-lines");
604
+ const circleHelper = svg.querySelector("#circle-help");
605
+ const lineHelper = svg.querySelector("#line-help");
606
+ const inner = (_b = selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.children) === null || _b === void 0 ? void 0 : _b[0];
607
+ const x0 = (selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.x) || 0;
608
+ const y0 = (selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.y) || 0;
609
+ const w0 = (selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.width) || 0;
610
+ const h0 = (selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.height) || 0;
611
+ const bbox = getGlobalBBox(svg, inner);
612
+ const cx = bbox.x + bbox.width / 2;
613
+ const cy = bbox.y + bbox.height / 2;
614
+ //start center
615
+ const dx0 = x - cx;
616
+ const dy0 = y - cy;
617
+ // ✅ ANGLE DARI CENTER
618
+ const dx = pos.x - cx;
619
+ const dy = pos.y - cy;
620
+ //start angle
621
+ const startAngle = Math.atan2(dy0, dx0);
622
+ const currentAngle = Math.atan2(dy, dx);
623
+ const newAngle = normalizeAngle(0 + ((currentAngle - startAngle) * 180) / Math.PI);
624
+ const angle = (0 * Math.PI) / 180;
625
+ // helper line
626
+ const centerX = w0 / 2;
627
+ const centerY = h0 / 2;
628
+ const cos = Math.cos(angle);
629
+ const sin = Math.sin(angle);
630
+ // GLOBAL → LOCAL
631
+ const localDx = dx * cos + dy * sin;
632
+ const localDy = -dx * sin + dy * cos;
633
+ // helper (LOCAL SPACE)
634
+ const x2 = centerX + localDx;
635
+ const y2 = centerY + localDy;
636
+ lineHelper === null || lineHelper === void 0 ? void 0 : lineHelper.setAttribute("x1", `${centerX}`);
637
+ lineHelper === null || lineHelper === void 0 ? void 0 : lineHelper.setAttribute("y1", `${centerY}`);
638
+ lineHelper === null || lineHelper === void 0 ? void 0 : lineHelper.setAttribute("x2", `${x2}`);
639
+ lineHelper === null || lineHelper === void 0 ? void 0 : lineHelper.setAttribute("y2", `${y2}`);
640
+ circleHelper === null || circleHelper === void 0 ? void 0 : circleHelper.setAttribute("cx", `${x2}`);
641
+ circleHelper === null || circleHelper === void 0 ? void 0 : circleHelper.setAttribute("cy", `${y2}`);
642
+ (_c = selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.children) === null || _c === void 0 ? void 0 : _c[0].setAttribute("transform", `rotate(${newAngle}, 0, 0)`);
643
+ const { tx, ty } = stabilizeRotation(x0, y0, w0, h0, 0, newAngle);
644
+ selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.setAttribute("transform", `translate(${tx}, ${ty}) `);
645
+ // ROTATE ALL ELEMENT IN SELECTION
646
+ const allID = (_d = dataElementSelectionGroupRef.current) === null || _d === void 0 ? void 0 : _d.map((el) => el.id);
647
+ const deltaAngle = newAngle - 0;
648
+ const rad = (deltaAngle * Math.PI) / 180;
649
+ const cosA = Math.cos(rad);
650
+ const sinA = Math.sin(rad);
651
+ const allGroupsAtrribute = getAttributeElements(svg, allID);
652
+ allGroupsAtrribute.forEach(({ g, inner }, i) => {
653
+ var _a;
654
+ const el = (_a = dataElementSelectionGroupRef.current) === null || _a === void 0 ? void 0 : _a[i];
655
+ if (!el)
656
+ return;
657
+ const rotateBefore = normalizeAngle(el.rotation);
658
+ const ex = el.x;
659
+ const ey = el.y;
660
+ // 🔑 ROTATE AROUND SELECTION CENTER
661
+ const dx = ex - cx;
662
+ const dy = ey - cy;
663
+ const nx = cx + dx * cosA - dy * sinA;
664
+ const ny = cy + dx * sinA + dy * cosA;
665
+ g.setAttribute("data-is-rotating", "1");
666
+ inner.setAttribute("transform", `rotate(${normalizeAngle(rotateBefore + deltaAngle)}, 0, 0)`);
667
+ g.setAttribute("transform", `translate(${nx}, ${ny})`);
668
+ });
669
+ };
670
+ if (isRotateSelectionBox) {
671
+ onRotateSelectionBox(pos);
672
+ }
673
+ //RESIZE SELECTION BOX
674
+ const onResizeSelectionBox = (ev) => {
675
+ var _a, _b;
676
+ console.log("RESIZE SELECTION BOX");
677
+ const dx = pos.x - x;
678
+ const dy = pos.y - y;
679
+ isResizeSelectionRef.current = true;
680
+ const oldSel = {
681
+ x: selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.x,
682
+ y: selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.y,
683
+ width: selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.width,
684
+ height: selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.height,
685
+ };
686
+ const allID = (_a = dataElementSelectionGroupRef.current) === null || _a === void 0 ? void 0 : _a.map((el) => el.id);
687
+ const allDataRealSelection = (_b = [
688
+ ...componentsState,
689
+ ...extraComponentsState,
690
+ ]) === null || _b === void 0 ? void 0 : _b.filter((el) => allID.includes(el.id));
691
+ const allGroupsAttribute = getAttributeElements(svg, allID);
692
+ const resultSelection = resizeBox({
693
+ box: oldSel,
694
+ dx,
695
+ dy,
696
+ rotate: 0,
697
+ handle: resizeSide,
698
+ });
699
+ updateSelectionBox(svg, resultSelection);
700
+ const scaleX = resultSelection.width / oldSel.width;
701
+ const scaleY = resultSelection.height / oldSel.height;
702
+ allGroupsAttribute.forEach(({ g, element, inner, seatGroup, seats }, i) => {
703
+ var _a, _b;
704
+ const activeId = JSON.parse(g === null || g === void 0 ? void 0 : g.getAttribute("data-id"));
705
+ const elementOld = allDataRealSelection === null || allDataRealSelection === void 0 ? void 0 : allDataRealSelection.find((el) => el.id == activeId);
706
+ const { x: translateX, y: translateY } = getTranslate(g);
707
+ const newWidth = (elementOld === null || elementOld === void 0 ? void 0 : elementOld.width) * scaleX;
708
+ const newHeight = (elementOld === null || elementOld === void 0 ? void 0 : elementOld.height) * scaleY;
709
+ // Jarak relatif element dari pojok kiri atas selection (sebelum resize)
710
+ const relativeX = (elementOld === null || elementOld === void 0 ? void 0 : elementOld.x) - oldSel.x;
711
+ const relativeY = (elementOld === null || elementOld === void 0 ? void 0 : elementOld.y) - oldSel.y;
712
+ // Jarak relatif baru (sesudah resize)
713
+ const newX = resultSelection.x + relativeX * scaleX;
714
+ const newY = resultSelection.y + relativeY * scaleY;
715
+ const relativePoinst = ((_a = elementOld === null || elementOld === void 0 ? void 0 : elementOld.points) === null || _a === void 0 ? void 0 : _a.length) !== 0 &&
716
+ ((_b = elementOld === null || elementOld === void 0 ? void 0 : elementOld.points) === null || _b === void 0 ? void 0 : _b.map((point) => {
717
+ const { x, y } = point;
718
+ const relativeX = x - oldSel.x;
719
+ const relativeY = y - oldSel.y;
720
+ return {
721
+ x: resultSelection.x + relativeX * scaleX,
722
+ y: resultSelection.y + relativeY * scaleY,
723
+ };
724
+ }));
725
+ const newElement = {
726
+ x: newX,
727
+ y: newY,
728
+ width: newWidth,
729
+ height: newHeight,
730
+ points: relativePoinst,
731
+ };
732
+ if (seats.length !== 0) {
733
+ const seatsPositions = elementOld === null || elementOld === void 0 ? void 0 : elementOld.seatPositions;
734
+ const openSpace = elementOld === null || elementOld === void 0 ? void 0 : elementOld.openSpace;
735
+ if ((elementOld === null || elementOld === void 0 ? void 0 : elementOld.shape) === "table-seat-circle") {
736
+ resizeSeatCircle({
737
+ seatCount: elementOld === null || elementOld === void 0 ? void 0 : elementOld.seatCount,
738
+ r: 10,
739
+ openSpace,
740
+ newElement,
741
+ seats,
742
+ seatGroup,
743
+ });
744
+ }
745
+ else if ((elementOld === null || elementOld === void 0 ? void 0 : elementOld.shape) === "table-seat-square") {
746
+ resizeSeatSquare({
747
+ seatsPositions,
748
+ r: 10,
749
+ openSpace,
750
+ newElement,
751
+ seats,
752
+ seatGroup,
753
+ });
754
+ }
755
+ }
756
+ applyResizeToSvgElement(element, g, newElement);
757
+ });
758
+ };
759
+ if (downAtResizePositionAndHasSelectionBox)
760
+ onResizeSelectionBox(ev);
761
+ //SELECTION BOX MOVE
762
+ const onMoveSelectionBox = () => {
763
+ var _a, _b;
764
+ console.log("move selection box");
765
+ const allID = (_a = dataElementSelectionGroupRef.current) === null || _a === void 0 ? void 0 : _a.map((el) => el.id);
766
+ const allDataRealSelection = (_b = [
767
+ ...componentsState,
768
+ ...extraComponentsState,
769
+ ]) === null || _b === void 0 ? void 0 : _b.filter((el) => allID.includes(el.id));
770
+ allDataRealSelection.forEach((item) => {
771
+ const { g } = getAttributeElement(svg, item.id);
772
+ const newX = pos.x - x;
773
+ const newY = pos.y - y;
774
+ g.setAttribute("transform", `translate(${item.x + newX}, ${item.y + newY})`);
775
+ });
776
+ const newX = pos.x - x;
777
+ const newY = pos.y - y;
778
+ updateSelectionBox(svg, {
779
+ x: (selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.x) + newX,
780
+ y: (selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.y) + newY,
781
+ width: selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.width,
782
+ height: selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.height,
783
+ });
784
+ };
785
+ if (downOutResizePositionAndInSelectionBox && !isRotateSelectionBox)
786
+ onMoveSelectionBox();
787
+ // MAKING SELECTION BOX MOVE
788
+ const onMakeSelectionBox = (ev) => {
789
+ var _a, _b;
790
+ console.log("lagi bikin selection box");
791
+ const svgSize = svg.getBoundingClientRect();
792
+ let selectionBoxGhost = svg.querySelector("#selection-box-ghost");
793
+ const selX = Math.min(pos.x, x);
794
+ const selY = Math.min(pos.y, y);
795
+ const selW = Math.abs(pos.x - x);
796
+ const selH = Math.abs(pos.y - y);
797
+ selectionBoxGhost === null || selectionBoxGhost === void 0 ? void 0 : selectionBoxGhost.setAttribute("x", String(selX));
798
+ selectionBoxGhost === null || selectionBoxGhost === void 0 ? void 0 : selectionBoxGhost.setAttribute("y", String(selY));
799
+ selectionBoxGhost === null || selectionBoxGhost === void 0 ? void 0 : selectionBoxGhost.setAttribute("width", String(selW));
800
+ selectionBoxGhost === null || selectionBoxGhost === void 0 ? void 0 : selectionBoxGhost.setAttribute("height", String(selH));
801
+ // FIND ALL COMPONENTS INSIDE SELECTION BOX
802
+ const allGroups = (_a = svgRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll("g[data-id]");
803
+ const selLeft = selX;
804
+ const selTop = selY;
805
+ const selectedIds = [...allGroups]
806
+ .map((g) => JSON === null || JSON === void 0 ? void 0 : JSON.parse((g === null || g === void 0 ? void 0 : g.getAttribute("data-id")) || "{}"))
807
+ .filter((d) => {
808
+ const { g, element } = getAttributeElement(svg, d);
809
+ const box = getGlobalBBox(svg, element);
810
+ // console.log(
811
+ // box.x < selLeft + selW,
812
+ // "x",
813
+ // box.x + box.width > selLeft,
814
+ // "x2",
815
+ // box.y < selTop + selH,
816
+ // "y",
817
+ // box.y + box.height > selTop,
818
+ // "y2"
819
+ // );
820
+ return ((box === null || box === void 0 ? void 0 : box.x) < selLeft + selW &&
821
+ (box === null || box === void 0 ? void 0 : box.x) + box.width > selLeft &&
822
+ (box === null || box === void 0 ? void 0 : box.y) < selTop + selH &&
823
+ (box === null || box === void 0 ? void 0 : box.y) + box.height > selTop);
824
+ })
825
+ .map((d) => `${d}`);
826
+ if (selectedIds.length === 0)
827
+ return;
828
+ const selectedComps = (_b = [...componentsState, ...extraComponentsState]
829
+ .filter((c) => selectedIds.map(String).includes(String(c.id)))) === null || _b === void 0 ? void 0 : _b.map((item) => {
830
+ const { g } = getAttributeElement(svg, item.id);
831
+ const { x, y } = getTranslate(g);
832
+ const box = getGlobalBBox(svg, g);
833
+ return Object.assign(Object.assign({}, item), {
834
+ // x: box.x,
835
+ // y: box.y,
836
+ width: box.width, height: box.height });
837
+ });
838
+ dataElementSelectionGroupRef.current = selectedComps;
839
+ };
840
+ if (downBeforeHasSelectionBox)
841
+ onMakeSelectionBox(ev);
842
+ // CREATE GHOST ELEMENT ---
843
+ const onDrawNewElements = toolElement.includes(activeTool) && isCreateElementRef.current;
844
+ if (onDrawNewElements) {
845
+ const ghost = (_a = svgRef.current) === null || _a === void 0 ? void 0 : _a.querySelector("#ghost-element-create");
846
+ if (!ghost)
847
+ return;
848
+ const data = JSON.parse(ghost.getAttribute("data-table") || "{}");
849
+ const { x: ox, y: oy } = data;
850
+ // ---- HITUNG RECT BARU ----
851
+ const x1 = Math.min(ox, pos.x);
852
+ const y1 = Math.min(oy, pos.y);
853
+ const x2 = Math.max(ox, pos.x);
854
+ const y2 = Math.max(oy, pos.y);
855
+ const newX = x1;
856
+ const newY = y1;
857
+ const newW = x2 - x1;
858
+ const newH = y2 - y1;
859
+ // ---- RECT ----
860
+ if (["square", "table-seat-circle"].includes(activeTool)) {
861
+ ghost.setAttribute("x", String(newX));
862
+ ghost.setAttribute("y", String(newY));
863
+ ghost.setAttribute("width", String(newW));
864
+ ghost.setAttribute("height", String(newH));
865
+ }
866
+ // ---- CIRCLE (ambil dari bounding box) ----
867
+ if (activeTool === "circle") {
868
+ const cx = newX + newW / 2;
869
+ const cy = newY + newH / 2;
870
+ const r = Math.min(newW, newH) / 2;
871
+ ghost.setAttribute("cx", String(cx));
872
+ ghost.setAttribute("cy", String(cy));
873
+ ghost.setAttribute("r", String(r));
874
+ }
875
+ // ---- UPDATE DATA TABLE ----
876
+ ghost.setAttribute("data-table", JSON.stringify(Object.assign(Object.assign({}, data), { x: newX, y: newY, width: newW, height: newH })));
877
+ }
878
+ // RESIZE GHOST SINGLE ELEMENT ---
879
+ const onResize = (ev) => {
880
+ var _a, _b;
881
+ console.log("lagi resize single element");
882
+ const activeId = selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id;
883
+ const svg = svgRef.current;
884
+ console.log({ svg, activeId });
885
+ const { g, element, inner, seats, seatGroup } = getAttributeElement(svg, activeId);
886
+ const elementSelect = {
887
+ x: selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.x,
888
+ y: selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.y,
889
+ width: selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.width,
890
+ height: selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.height,
891
+ seatPositions: selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.seatPositions,
892
+ seatCount: selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.seatCount,
893
+ openSpace: selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.openSpace,
894
+ points: selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.points,
895
+ };
896
+ const oldSel = {
897
+ x: selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.x,
898
+ y: selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.y,
899
+ width: selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.width,
900
+ height: selectedLines === null || selectedLines === void 0 ? void 0 : selectedLines.height,
901
+ };
902
+ const dx = pos.x - x;
903
+ const dy = pos.y - y;
904
+ const resultSelection = resizeBox({
905
+ box: oldSel,
906
+ dx,
907
+ dy,
908
+ rotate: 0,
909
+ handle: resizeSide,
910
+ });
911
+ updateSelectionBox(svg, resultSelection, activeId);
912
+ const scaleX = resultSelection.width / oldSel.width;
913
+ const scaleY = resultSelection.height / oldSel.height;
914
+ const newWidth = elementSelect.width * scaleX;
915
+ const newHeight = elementSelect.height * scaleY;
916
+ // Jarak relatif element dari pojok kiri atas selection (sebelum resize)
917
+ const relativeX = elementSelect.x - oldSel.x;
918
+ const relativeY = elementSelect.y - oldSel.y;
919
+ // Jarak relatif baru (sesudah resize)
920
+ const newX = resultSelection.x + relativeX * scaleX;
921
+ const newY = resultSelection.y + relativeY * scaleY;
922
+ const relativePoinst = ((_a = elementSelect === null || elementSelect === void 0 ? void 0 : elementSelect.points) === null || _a === void 0 ? void 0 : _a.length) !== 0 &&
923
+ ((_b = elementSelect === null || elementSelect === void 0 ? void 0 : elementSelect.points) === null || _b === void 0 ? void 0 : _b.map((point) => {
924
+ const { x, y } = point;
925
+ const relativeX = x - oldSel.x;
926
+ const relativeY = y - oldSel.y;
927
+ return {
928
+ x: resultSelection.x + relativeX * scaleX,
929
+ y: resultSelection.y + relativeY * scaleY,
930
+ };
931
+ }));
932
+ const newElement = {
933
+ x: newX,
934
+ y: newY,
935
+ width: newWidth,
936
+ height: newHeight,
937
+ points: relativePoinst,
938
+ };
939
+ if (seats.length !== 0) {
940
+ if ((selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.shape) === "table-seat-circle") {
941
+ resizeSeatCircle({
942
+ seatCount: elementSelect === null || elementSelect === void 0 ? void 0 : elementSelect.seatCount,
943
+ r: 10,
944
+ openSpace: elementSelect === null || elementSelect === void 0 ? void 0 : elementSelect.openSpace,
945
+ newElement,
946
+ seats,
947
+ seatGroup,
948
+ });
949
+ }
950
+ else if ((selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.shape) === "table-seat-square") {
951
+ resizeSeatSquare({
952
+ seatsPositions: elementSelect.seatPositions,
953
+ r: 10,
954
+ newElement,
955
+ openSpace: elementSelect.openSpace,
956
+ seats,
957
+ seatGroup,
958
+ });
959
+ }
960
+ }
961
+ applyResizeToSvgElement(element, g, newElement);
962
+ isResizeRef.current = true;
963
+ };
964
+ // const hasSelectedOneElement =
965
+ // !isEmpty(selectedComponent) &&
966
+ // onResizeSelectionRef.current &&
967
+ // downAtResizePosition;
968
+ if (!isEmpty(selectedComponent) && isMightResizeElement)
969
+ onResize(ev);
970
+ //ROTATE
971
+ const onRotate = (ev) => {
972
+ console.log("rotate single element");
973
+ const svg = svgRef.current;
974
+ if (!svg || !selectedComponent)
975
+ return;
976
+ const lineHelper = svg.querySelector("#line-help");
977
+ const circleHelper = svg.querySelector("#circle-help");
978
+ const { inner, g } = getAttributeElement(svg, selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id);
979
+ if (!inner || !g)
980
+ return;
981
+ // mouse → SVG space
982
+ // 🔴 GLOBAL BBOX (INI KUNCI)
983
+ const bbox = getGlobalBBox(svg, inner);
984
+ const boxSelection = getGlobalBBox(svg, g);
985
+ if (!bbox)
986
+ return;
987
+ const cx = bbox.x + bbox.width / 2;
988
+ const cy = bbox.y + bbox.height / 2;
989
+ // vector awal & sekarang (GLOBAL)
990
+ const dx0 = x - cx;
991
+ const dy0 = y - cy;
992
+ const dx = pos.x - cx;
993
+ const dy = pos.y - cy;
994
+ const startAngle = Math.atan2(dy0, dx0);
995
+ const currentAngle = Math.atan2(dy, dx);
996
+ const newAngle = (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.rotation) +
997
+ ((currentAngle - startAngle) * 180) / Math.PI;
998
+ // helper line
999
+ console.log({ selectedLines }, "haduuuhh");
1000
+ const centerX = selectedLines.width / 2;
1001
+ const centerY = selectedLines.height / 2;
1002
+ const angle = (0 * Math.PI) / 180;
1003
+ const cos = Math.cos(angle);
1004
+ const sin = Math.sin(angle);
1005
+ // GLOBAL → LOCAL
1006
+ const localDx = dx * cos + dy * sin;
1007
+ const localDy = -dx * sin + dy * cos;
1008
+ // helper (LOCAL SPACE)
1009
+ const x2 = centerX + localDx;
1010
+ const y2 = centerY + localDy;
1011
+ console.log({ centerX, centerY, localDx, localDy });
1012
+ lineHelper === null || lineHelper === void 0 ? void 0 : lineHelper.setAttribute("x1", `${centerX}`);
1013
+ lineHelper === null || lineHelper === void 0 ? void 0 : lineHelper.setAttribute("y1", `${centerY}`);
1014
+ lineHelper === null || lineHelper === void 0 ? void 0 : lineHelper.setAttribute("x2", `${x2}`);
1015
+ lineHelper === null || lineHelper === void 0 ? void 0 : lineHelper.setAttribute("y2", `${y2}`);
1016
+ circleHelper === null || circleHelper === void 0 ? void 0 : circleHelper.setAttribute("cx", `${x2}`);
1017
+ circleHelper === null || circleHelper === void 0 ? void 0 : circleHelper.setAttribute("cy", `${y2}`);
1018
+ // rotate di local space
1019
+ inner.setAttribute("transform", `rotate(${newAngle}, 0, 0)`);
1020
+ // stabilize translate
1021
+ const { tx, ty } = selectedComponent.shape === "polygon"
1022
+ ? stabilizeTranslateOnRotate({
1023
+ points: selectedComponentProps === null || selectedComponentProps === void 0 ? void 0 : selectedComponentProps.points,
1024
+ oldAngle: selectedComponent.rotation,
1025
+ newAngle,
1026
+ tx: selectedComponent.x,
1027
+ ty: selectedComponent.y,
1028
+ })
1029
+ : stabilizeRotation(selectedComponent.x, selectedComponent.y, selectedComponent.width, selectedComponent.height, selectedComponent.rotation, newAngle);
1030
+ g.setAttribute("transform", `translate(${tx}, ${ty})`);
1031
+ ghostRotateElement.current = newAngle;
1032
+ updateSelectionBox(svg, boxSelection, selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id, true);
1033
+ };
1034
+ if (targetRotate && !isRotateSelectionBox)
1035
+ onRotate(ev);
1036
+ const onMove = (ev) => {
1037
+ console.log("movv");
1038
+ // const selectionLines = svg.querySelector("#selection-lines");
1039
+ const dx = ev.clientX - startX;
1040
+ const dy = ev.clientY - startY;
1041
+ const distance = Math.sqrt(dx * dx + dy * dy);
1042
+ // onPanning(ev);
1043
+ if (!hasMoved && distance > 0) {
1044
+ // only move ghost if the mouse has moved more than 5 pixels
1045
+ hasMoved = true;
1046
+ }
1047
+ const newX = pos.x - offset.x;
1048
+ const newY = pos.y - offset.y;
1049
+ // let activeId = JSON.parse(targetGroup?.getAttribute("data-id") || "{}");
1050
+ const isMatchWithSelection = activeId === (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id);
1051
+ const { g } = getAttributeElement(svg, activeId);
1052
+ console.log({ activeId });
1053
+ g === null || g === void 0 ? void 0 : g.setAttribute("transform", `translate(${newX}, ${newY})`);
1054
+ if (isMatchWithSelection) {
1055
+ const boxSelection = getGlobalBBox(svg, g);
1056
+ updateSelectionBox(svg, boxSelection, activeId);
1057
+ }
1058
+ };
1059
+ const moveSingleElement = (isMightMove &&
1060
+ !(!isEmpty(selectedComponent) && !isMightResizeElement) &&
1061
+ !targetRotate) ||
1062
+ (isMightMoveOneElementSelection && !isMightResizeElement) ||
1063
+ (isMightMove && !isEmpty(selectedComponent) && !isMightResizeElement);
1064
+ if (moveSingleElement) {
1065
+ onMove(ev);
1066
+ }
1067
+ };
1068
+ const pointerHandleUp = (e) => {
1069
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
1070
+ //POLYGON RESIZE
1071
+ if (targetSelection) {
1072
+ console.log("KLIK UP SELECTION");
1073
+ //show
1074
+ dispatch({ type: "panel/setShow", payload: true });
1075
+ }
1076
+ if (targetPointPolygon && targetGroup) {
1077
+ console.log("KLIK UP POINT POLYGON");
1078
+ const { element } = getAttributeElement(svg, targetGroup.dataset.id);
1079
+ const points = element === null || element === void 0 ? void 0 : element.getAttribute("points");
1080
+ const pointsArray = pointsStringToArray(points);
1081
+ const findById = [...componentsState, ...extraComponentsState].find((c) => c.id === targetGroup.dataset.id);
1082
+ const newDataComponent = Object.assign(Object.assign({}, findById), { points: pointsArray });
1083
+ updateComponentAttribute(newDataComponent);
1084
+ setSelectedComponent(newDataComponent);
1085
+ dispatch({
1086
+ type: "panel/setSelectedComponent",
1087
+ payload: newDataComponent,
1088
+ });
1089
+ selectionLinesRef.current = newDataComponent;
1090
+ }
1091
+ //POLYGON
1092
+ const isInitialPolyGon = activeTool === "polygon" && (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.shape) === "polygon";
1093
+ if (isInitialPolyGon) {
1094
+ console.log("Create polygon");
1095
+ const closing = isClosingPolygon(x, y, selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.points);
1096
+ const newCoord = closing
1097
+ ? {
1098
+ x: (_a = selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.points[0]) === null || _a === void 0 ? void 0 : _a.x,
1099
+ y: (_b = selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.points[0]) === null || _b === void 0 ? void 0 : _b.y,
1100
+ }
1101
+ : { x, y };
1102
+ const newPoints = Object.assign(Object.assign({}, selectedComponent), { points: [...selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.points, newCoord] });
1103
+ (_c = svg.querySelector("#polyline-helper")) === null || _c === void 0 ? void 0 : _c.setAttribute("opacity", "1");
1104
+ if (closing && ((_d = selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.points) === null || _d === void 0 ? void 0 : _d.length) > 2) {
1105
+ const { g, inner } = getAttributeElement(svg, selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id);
1106
+ const { height, width } = getGlobalBBox(svg, inner);
1107
+ isOnMakePolygonRef.current = false;
1108
+ setSelectedComponent(null);
1109
+ dispatch({
1110
+ type: "panel/setSelectedComponent",
1111
+ payload: null,
1112
+ });
1113
+ polygonElementRef.current = [];
1114
+ addComponents(Object.assign(Object.assign({}, newPoints), { x: 0, y: 0, width, height }));
1115
+ (_e = svg.querySelector("#selection-box-ghost")) === null || _e === void 0 ? void 0 : _e.remove();
1116
+ const polyline = svg.querySelector("#polyline-helper");
1117
+ // polyline?.remove();
1118
+ console.log({ polyline });
1119
+ (_f = svg.querySelector("#polyline-helper")) === null || _f === void 0 ? void 0 : _f.setAttribute("opacity", "0");
1120
+ }
1121
+ else {
1122
+ setSelectedComponent(newPoints);
1123
+ dispatch({
1124
+ type: "panel/setSelectedComponent",
1125
+ payload: newPoints,
1126
+ });
1127
+ polygonElementRef.current = newPoints;
1128
+ }
1129
+ }
1130
+ // ROTATE
1131
+ if (targetRotate && !isRotateSelectionBox) {
1132
+ console.log("KLIK UP ROTATE");
1133
+ const activeId = selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id;
1134
+ const { g, inner, element } = getAttributeElement(svg, activeId);
1135
+ const boxLines = getGlobalBBox(svg, g);
1136
+ const findById = [...componentsState, ...extraComponentsState].find((c) => c.id === activeId);
1137
+ const { x, y } = getTranslate(g);
1138
+ const newDataComponent = Object.assign(Object.assign({}, findById), { x,
1139
+ y, rotation: ghostRotateElement.current });
1140
+ const boxSelection = Object.assign(Object.assign(Object.assign({
1141
+ // x,
1142
+ // y,
1143
+ // width,
1144
+ // height,
1145
+ // rotation: ghostRotateElement.current,
1146
+ shape: "selection-box", id: `${Date.now()}` }, findById), boxLines), { rotation: 0 });
1147
+ if (boxLines)
1148
+ setSelectedLines(boxSelection);
1149
+ updateComponentAttribute(newDataComponent);
1150
+ setSelectedComponent(newDataComponent);
1151
+ dispatch({
1152
+ type: "panel/setSelectedComponent",
1153
+ payload: newDataComponent,
1154
+ });
1155
+ //LOGIC FOR SET SHOW
1156
+ dispatch({ type: "panel/setShow", payload: false });
1157
+ }
1158
+ //CREATE NEW ELEMENT
1159
+ if (toolElement.includes(activeTool) && isCreateElementRef.current) {
1160
+ console.log("CREATE new element");
1161
+ const ghostElementNew = (_g = svgRef.current) === null || _g === void 0 ? void 0 : _g.querySelector("#ghost-element-create");
1162
+ if (!ghostElementNew)
1163
+ return;
1164
+ const dataOriginal = JSON.parse(ghostElementNew.getAttribute("data-table") || "{}");
1165
+ const newComponent = Object.assign(Object.assign({ id: `${Date.now()}` }, dataOriginal), { seatCount: 4 });
1166
+ const newExtraComponent = [...extraComponentsState, newComponent];
1167
+ //ADD TO REDUX
1168
+ setExtraComponentsState(newExtraComponent);
1169
+ // setComponentsState(newComponentState);
1170
+ addComponents(newComponent);
1171
+ // syncFromLocalToRedux(newComponentState);
1172
+ //REMOVE GHOST ELEMENT
1173
+ (_h = svgRef.current) === null || _h === void 0 ? void 0 : _h.querySelectorAll("#ghost-element-create").forEach((el) => el.remove());
1174
+ isCreateElementRef.current = false;
1175
+ }
1176
+ // CREATE POLYGON
1177
+ const hasSelectedOneElement = !isEmpty(selectedComponent) &&
1178
+ onResizeSelectionRef.current &&
1179
+ downAtResizePosition;
1180
+ const idDataset = targetGroup === null || targetGroup === void 0 ? void 0 : targetGroup.dataset.id;
1181
+ const isSelectElement = !hasMoved &&
1182
+ !releaseGroupRef.current &&
1183
+ !targetRotate &&
1184
+ !hasSelectedOneElement &&
1185
+ idDataset &&
1186
+ activeTool === "select";
1187
+ if (isSelectElement) {
1188
+ //KLIK UP
1189
+ console.log("KLIK UP");
1190
+ const findById = [...componentsState, ...extraComponentsState].find((component) => component.id === idDataset);
1191
+ console.log({ findById });
1192
+ if (!findById) {
1193
+ return;
1194
+ }
1195
+ const { g } = getAttributeElement(svg, idDataset);
1196
+ if (shiftActive) {
1197
+ const allElementSelectionGroup = dataElementSelectionGroupRef.current;
1198
+ // HITUNG BOUNDING BOX
1199
+ let xs = [];
1200
+ let ys = [];
1201
+ let x2 = [];
1202
+ let y2 = [];
1203
+ allElementSelectionGroup.forEach((element) => {
1204
+ const activeId = element.id;
1205
+ const { g } = getAttributeElement(svg, activeId);
1206
+ const { x, y, width, height } = getGlobalBBox(svg, g);
1207
+ xs.push(x);
1208
+ ys.push(y);
1209
+ x2.push(x + width);
1210
+ y2.push(y + height);
1211
+ });
1212
+ const selectionBox = {
1213
+ x: Math.min(...xs),
1214
+ y: Math.min(...ys),
1215
+ width: Math.max(...x2) - Math.min(...xs),
1216
+ height: Math.max(...y2) - Math.min(...ys),
1217
+ stroke: "red",
1218
+ shape: "selection-box",
1219
+ fill: "transparent",
1220
+ id: `${Date.now()}`,
1221
+ rotation: 0,
1222
+ };
1223
+ selectionLinesRef.current = selectionBox;
1224
+ setSelectedLines(selectionBox);
1225
+ dispatch({
1226
+ type: "panel/setSelectedGroup",
1227
+ payload: allElementSelectionGroup,
1228
+ });
1229
+ setSelectedComponent(null);
1230
+ dispatch({
1231
+ type: "panel/setSelectedComponent",
1232
+ payload: null,
1233
+ });
1234
+ }
1235
+ else {
1236
+ console.log("SELECT SINGLE ELEMENT");
1237
+ dataElementSelectionGroupRef.current = [];
1238
+ const boxGroup = getGlobalBBox(svg, g);
1239
+ let boxSelection = Object.assign(Object.assign(Object.assign({}, findById), boxGroup), {
1240
+ // x,
1241
+ // y,
1242
+ // width,
1243
+ // height: height ,
1244
+ // width,
1245
+ // height,
1246
+ // x:boxGroup.x,
1247
+ // y:boxGroup.y,
1248
+ shape: "selection-box", rotation: 0 });
1249
+ console.log({ boxSelection });
1250
+ // if (findById?.shape === "polygon") {
1251
+ // const boxGroup = getGlobalBBox(svg, g);
1252
+ // boxSelection = {
1253
+ // ...boxSelection,
1254
+ // ...(boxGroup ? { x: boxGroup.x } : {}),
1255
+ // ...(boxGroup ? { y: boxGroup.y } : {}),
1256
+ // ...(boxGroup ? { width: boxGroup.width } : {}),
1257
+ // ...(boxGroup ? { height: boxGroup.height } : {}),
1258
+ // shape: "selection-box",
1259
+ // };
1260
+ // }
1261
+ if ((boxSelection === null || boxSelection === void 0 ? void 0 : boxSelection.width) &&
1262
+ (boxSelection === null || boxSelection === void 0 ? void 0 : boxSelection.height)) {
1263
+ console.log({ boxSelection });
1264
+ setSelectedLines(boxSelection);
1265
+ setSelectedComponent(findById);
1266
+ dispatch({
1267
+ type: "panel/setSelectedComponent",
1268
+ payload: findById,
1269
+ });
1270
+ selectionLinesRef.current = boxSelection;
1271
+ }
1272
+ }
1273
+ //LOGIC FOR SET SHOW
1274
+ dispatch({ type: "panel/setShow", payload: true });
1275
+ }
1276
+ //UPDATE DATASET TO STATE IF RESIZE
1277
+ if (isMightResizeElement) {
1278
+ console.log("KLIK UP RESIZE SINGLE ELEMENT");
1279
+ const activeId = selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id;
1280
+ const svg = svgRef.current;
1281
+ const { g, element, points } = getAttributeElement(svg, activeId);
1282
+ const selectionBox = getGlobalBBox(svg, g);
1283
+ const { width, height } = getSvgElementSize(element);
1284
+ const { x, y } = getTranslate(g);
1285
+ const newSelectedComponent = Object.assign(Object.assign({}, selectedComponent), { x: x, y: y, width: width, height: height, points: points });
1286
+ const newSelection = Object.assign({ shape: "selection-box", id: `${Date.now()}` }, selectionBox);
1287
+ setSelectedLines(newSelection);
1288
+ // dragGhostRef.current = false;
1289
+ setSelectedComponent(newSelectedComponent);
1290
+ dispatch({
1291
+ type: "panel/setSelectedComponent",
1292
+ payload: newSelectedComponent,
1293
+ });
1294
+ updateComponentAttribute(newSelectedComponent);
1295
+ //LOGIC FOR SET SHOW
1296
+ dispatch({ type: "panel/setShow", payload: false });
1297
+ // isResizeRef.current = false;
1298
+ }
1299
+ //MAKING SELECTION BOX UP
1300
+ const isMakingSelectionBoxUp = downBeforeHasSelectionBox && activeTool === "select";
1301
+ if (isMakingSelectionBoxUp
1302
+ // &&
1303
+ // !hadSelectionRef.current &&
1304
+ // !isResizeSelectionRef.current
1305
+ ) {
1306
+ console.log("MAKING SELECTION BOX UP");
1307
+ const allElementSelectionGroup = dataElementSelectionGroupRef.current;
1308
+ let xs = [];
1309
+ let ys = [];
1310
+ let x2 = [];
1311
+ let y2 = [];
1312
+ allElementSelectionGroup.forEach((element) => {
1313
+ const activeId = element.id;
1314
+ const { g, inner, element: el } = getAttributeElement(svg, activeId);
1315
+ const { x, y, width, height } = getGlobalBBox(svg, g);
1316
+ xs.push(x);
1317
+ ys.push(y);
1318
+ x2.push(x + width);
1319
+ y2.push(y + height);
1320
+ });
1321
+ const selectionBox = {
1322
+ x: Math.min(...xs),
1323
+ y: Math.min(...ys),
1324
+ width: Math.max(...x2) - Math.min(...xs),
1325
+ height: Math.max(...y2) - Math.min(...ys),
1326
+ stroke: "red",
1327
+ shape: "selection-box",
1328
+ fill: "transparent",
1329
+ id: `${Date.now()}`,
1330
+ rotation: 0,
1331
+ };
1332
+ function hasInvalidNumber(obj) {
1333
+ return Object.values(obj).some((v) => typeof v === "number" && !Number.isFinite(v));
1334
+ }
1335
+ if (!hasInvalidNumber(selectionBox)) {
1336
+ selectionLinesRef.current = selectionBox;
1337
+ setSelectedLines(selectionBox);
1338
+ dispatch({
1339
+ type: "panel/setSelectedGroup",
1340
+ payload: allElementSelectionGroup,
1341
+ });
1342
+ }
1343
+ setSelectedComponent(null);
1344
+ dispatch({
1345
+ type: "panel/setSelectedComponent",
1346
+ payload: null,
1347
+ });
1348
+ rotationSelectionRef.current = 0;
1349
+ (_k = (_j = svgRef.current) === null || _j === void 0 ? void 0 : _j.querySelectorAll("#selection-box-ghost")) === null || _k === void 0 ? void 0 : _k.forEach((el) => el.remove());
1350
+ }
1351
+ //RESIZE SELECTION BOX UP
1352
+ if (downAtResizePositionAndHasSelectionBox || isRotateSelectionBox) {
1353
+ console.log("Resize selection and rotate selection");
1354
+ const selectionLines = (_l = svgRef.current) === null || _l === void 0 ? void 0 : _l.querySelector("#selection-lines");
1355
+ isResizeSelectionRef.current = false;
1356
+ const results = (_m = dataElementSelectionGroupRef.current) === null || _m === void 0 ? void 0 : _m.map((item) => {
1357
+ const { g, element, inner, points } = getAttributeElement(svg, item.id);
1358
+ const { x, y } = getTranslate(g);
1359
+ const { width, height } = getSvgElementSize(element);
1360
+ const rotate = getRotation(inner.transform.baseVal);
1361
+ const selectionBox = getGlobalBBox(svg, g);
1362
+ console.log({ points });
1363
+ const newDataComponent = Object.assign(Object.assign({}, item), { points,
1364
+ x,
1365
+ y,
1366
+ width,
1367
+ height, rotation: rotate });
1368
+ const newDataSelection = Object.assign(Object.assign({}, newDataComponent), { x: selectionBox.x, y: selectionBox.y, width: selectionBox.width, height: selectionBox.height, shape: "selection-box", id: `${Date.now()}`, rotate: 0 });
1369
+ return {
1370
+ newDataComponent,
1371
+ newDataSelection,
1372
+ };
1373
+ });
1374
+ const newDataComponent = results.map((r) => r.newDataComponent);
1375
+ const dataSelection = results.map((r) => r.newDataSelection);
1376
+ // const currentRotation = getRotation(
1377
+ // (selectionLines?.children[0] as SVGGraphicsElement)?.transform
1378
+ // ?.baseVal
1379
+ // );
1380
+ // rotationSelectionRef.current = currentRotation;
1381
+ const sizeSelection = getSvgElementSize((_o = selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.children[0]) === null || _o === void 0 ? void 0 : _o.children[0]);
1382
+ // const newBoxSelection = getGlobalBBox(svg, selectionLines);
1383
+ updateComponentsAttribute(newDataComponent);
1384
+ const newDataSelection = {
1385
+ x: Math.min(...dataSelection.map((d) => d.x)),
1386
+ y: Math.min(...dataSelection.map((d) => d.y)),
1387
+ width: Math.max(...dataSelection.map((d) => d.x + d.width)) -
1388
+ Math.min(...dataSelection.map((d) => d.x)),
1389
+ height: Math.max(...dataSelection.map((d) => d.y + d.height)) -
1390
+ Math.min(...dataSelection.map((d) => d.y)),
1391
+ shape: "selection-box",
1392
+ id: `${Date.now()}`,
1393
+ };
1394
+ dispatch({
1395
+ type: "panel/setSelectedGroup",
1396
+ payload: newDataComponent,
1397
+ });
1398
+ setSelectedComponent(null);
1399
+ dispatch({
1400
+ type: "panel/setSelectedComponent",
1401
+ payload: null,
1402
+ });
1403
+ setSelectedLines(newDataSelection);
1404
+ dataElementSelectionGroupRef.current = newDataComponent;
1405
+ // // remove ghost element
1406
+ // svgRef.current
1407
+ // ?.querySelectorAll("#ghost-element-has-selection")
1408
+ // .forEach((el) => el.remove());
1409
+ hadSelectionRef.current = false;
1410
+ }
1411
+ //MOVE SELECTION BOX UP
1412
+ if (downOutResizePositionAndInSelectionBox &&
1413
+ !shiftActive &&
1414
+ !isRotateSelectionBox) {
1415
+ console.log("MOVE SELECTION BOX UP");
1416
+ const selectionLines = (_p = svgRef.current) === null || _p === void 0 ? void 0 : _p.querySelector("#selection-lines");
1417
+ isResizeSelectionRef.current = false;
1418
+ const results = (_q = dataElementSelectionGroupRef.current) === null || _q === void 0 ? void 0 : _q.map((item) => {
1419
+ const { g, element, inner } = getAttributeElement(svg, item.id);
1420
+ const { x, y } = getTranslate(g);
1421
+ const getBBox = getGlobalBBox(svg, g);
1422
+ const findComponent = [
1423
+ ...componentsState,
1424
+ ...extraComponentsState,
1425
+ ].find((c) => c.id === item.id);
1426
+ const newDataComponent = Object.assign(Object.assign({}, findComponent), { x,
1427
+ y });
1428
+ const newDataSelection = Object.assign({}, getBBox);
1429
+ return {
1430
+ newDataComponent,
1431
+ newDataSelection,
1432
+ };
1433
+ });
1434
+ const newDataComponent = results.map((r) => r.newDataComponent);
1435
+ const dataSelection = results.map((r) => r.newDataSelection);
1436
+ const newSelection = {
1437
+ x: Math.min(...dataSelection.map((d) => d.x)),
1438
+ y: Math.min(...dataSelection.map((d) => d.y)),
1439
+ width: Math.max(...dataSelection.map((d) => d.x + d.width)) -
1440
+ Math.min(...dataSelection.map((d) => d.x)),
1441
+ height: Math.max(...dataSelection.map((d) => d.y + d.height)) -
1442
+ Math.min(...dataSelection.map((d) => d.y)),
1443
+ };
1444
+ updateComponentsAttribute(newDataComponent);
1445
+ const newDataSelection = Object.assign(Object.assign({}, newSelection), { shape: "selection-box", id: `${Date.now()}-from-move`, rotation: 0 });
1446
+ dispatch({
1447
+ type: "panel/setSelectedGroup",
1448
+ payload: newDataComponent,
1449
+ });
1450
+ setSelectedComponent(null);
1451
+ dispatch({
1452
+ type: "panel/setSelectedComponent",
1453
+ payload: null,
1454
+ });
1455
+ setSelectedLines(newDataSelection);
1456
+ // if (newDataSelection?.height?.id) {
1457
+ // newDataSelection.height = newDataSelection.height.id;
1458
+ // }
1459
+ // if (newDataSelection?.x) {
1460
+ // setSelectedLines(newDataSelection);
1461
+ // }
1462
+ dataElementSelectionGroupRef.current = newDataComponent;
1463
+ hadSelectionRef.current = false;
1464
+ }
1465
+ //DELETE GHOST ELEMENT BISA MEMBU
1466
+ (_r = svgRef.current) === null || _r === void 0 ? void 0 : _r.querySelectorAll("#ghost-element").forEach((el) => el.remove());
1467
+ dataSetGhost.current = null;
1468
+ //UPDATE DATASET TO STATE IF MOVEk
1469
+ // if (releaseGroupRef.current) return;
1470
+ if ((isMightMove &&
1471
+ !isMakingSelectionBoxUp &&
1472
+ !isSelectElement &&
1473
+ !isMightResizeElement) ||
1474
+ isMightMoveOneElementSelection) {
1475
+ console.log("MOVE ONE ELEMENT");
1476
+ const findData = [...componentsState, ...extraComponentsState].find((item) => item.id == activeId);
1477
+ const { g } = getAttributeElement(svg, activeId);
1478
+ const bbox = getGlobalBBox(svg, g);
1479
+ const bboxSelection = getTranslate(g);
1480
+ const updateComponent = Object.assign(Object.assign({}, findData), { x: bboxSelection === null || bboxSelection === void 0 ? void 0 : bboxSelection.x, y: bboxSelection === null || bboxSelection === void 0 ? void 0 : bboxSelection.y });
1481
+ const selectionLines = Object.assign(Object.assign(Object.assign({}, selectedLines), bbox), { shape: "selection-box" });
1482
+ if (findData) {
1483
+ if (isSingleSelection) {
1484
+ setSelectedLines(selectionLines);
1485
+ setSelectedComponent(updateComponent);
1486
+ dispatch({
1487
+ type: "panel/updateSelectedComponent",
1488
+ payload: updateComponent,
1489
+ });
1490
+ }
1491
+ updateComponentAttribute(updateComponent);
1492
+ }
1493
+ }
1494
+ window.removeEventListener("pointermove", pointerHandleMove);
1495
+ window.removeEventListener("pointerup", pointerHandleUp);
1496
+ };
1497
+ window.addEventListener("pointermove", pointerHandleMove);
1498
+ window.addEventListener("pointerup", pointerHandleUp);
747
1499
  };
748
- const [touch, setTouch] = useState(false);
749
- const onTouchStartLine = () => {
750
- setTouch(true);
751
- };
752
- const onTouchEndLine = () => {
753
- setTouch(false);
1500
+ const handlePointerMove = (e) => {
1501
+ const svg = svgRef.current;
1502
+ const pt = svg.createSVGPoint();
1503
+ pt.x = e.clientX;
1504
+ pt.y = e.clientY;
1505
+ const pos = pt.matrixTransform(svg.getScreenCTM().inverse());
1506
+ if (isOnMakePolygonRef === null || isOnMakePolygonRef === void 0 ? void 0 : isOnMakePolygonRef.current) {
1507
+ const polylineHelper = svg === null || svg === void 0 ? void 0 : svg.querySelector("#polyline-helper");
1508
+ // const startPoint =
1509
+ // selectedComponent?.points[selectedComponent?.points?.length - 1];
1510
+ const newPoints = [...selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.points, { x: pos.x, y: pos.y }];
1511
+ const points = newPoints.map((item) => `${item.x},${item.y}`).join(" ");
1512
+ polylineHelper === null || polylineHelper === void 0 ? void 0 : polylineHelper.setAttribute("points", points);
1513
+ //lin helper from start to move
1514
+ }
754
1515
  };
755
- return (_jsxs(_Fragment, { children: [_jsx(ModalPreview, { children: _jsx(LayerView, { statusKey: "status" }) }), touch && _jsx(Button, { onClick: () => setTouch(false), children: "Stop Touch" }), _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 })] }) }), _jsxs(TransformWrapper, { ref: transformRef, panning: { disabled: ["node", "select"].includes(activeTool) }, centerZoomedOut: true, onTransformed: ({ state: { scale } }) => setScale(scale), minScale: 0.1, maxScale: 1000, initialScale: 1, pinch: { step: 1 }, wheel: { disabled: true }, smooth: true, doubleClick: { step: 1, disabled: activeTool === "select" }, disablePadding: true, centerOnInit: 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: {
756
- width: "100%",
757
- height: "100%",
758
- }, contentStyle: {
759
- width: "20000px", height: "20000px"
760
- }, children: _jsxs("svg", { id: "workspace", ref: svgRef, width: "100%", height: "100%",
761
- // viewBox={`0 0 ${widthBoard} ${heightBoard}`}
762
- // className="h-screen"
763
- onMouseUp: handleMouseUp, onMouseMove: handleMouseMove,
764
- // onMouseEnter={handleMouseEnter}
765
- // onMouseUp={handleEnd}
766
- onTouchMove: handleMouseMove, onTouchEnd: handleMouseUp, onClick: (e) => {
767
- e.stopPropagation();
768
- handleMouseClick(e);
769
- },
770
- // onMouseLeave={handleMouseLeave}
771
- xmlns: "http://www.w3.org/2000/svg", preserveAspectRatio: "xMidYMid meet", style: {
1516
+ 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(TransformWrapper, { ref: transformRef,
1517
+ // limitToBounds={true}
1518
+ panning: {
1519
+ disabled: [
1520
+ "node",
1521
+ "select",
1522
+ "square",
1523
+ "circle",
1524
+ "table-seat-circle",
1525
+ ].includes(activeTool),
1526
+ },
1527
+ // centerZoomedOut={true}
1528
+ // onTransformed={handleTransformed}
1529
+ minScale: 0.1, maxScale: 1000, initialScale: scale, pinch: { step: 1 }, wheel: { disabled: true }, smooth: true, doubleClick: { step: 1, disabled: activeTool === "select" }, disablePadding: true, centerOnInit: true, children: _jsxs(TransformComponent, { wrapperStyle: {
1530
+ width: "100%",
1531
+ height: "100%",
1532
+ }, contentStyle: { width: boardSize.width, height: boardSize.height }, children: [isLoading && (_jsx("div", { className: "absolute z-20 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2", children: "Loading..." })), _jsxs("svg", { id: "workspace", ref: svgRef, width: boardSize.width, height: boardSize.height, viewBox: `${minCoords.x} ${minCoords.y} ${boardSize.width} ${boardSize.height}`, onPointerDown: handlePointerDown, onPointerMove: handlePointerMove, xmlns: "http://www.w3.org/2000/svg", preserveAspectRatio: "xMidYMid meet", style: {
772
1533
  background: backgroundColor,
773
1534
  display: "block",
774
1535
  cursor: activeTool === "ruler" ? "crosshair" : "auto",
775
1536
  touchAction: "none",
776
- }, children: [_jsx(Layers, { shadowShape: shadowShape, components: [...extraComponentsState, ...componentsState], style: {
1537
+ pointerEvents: "all",
1538
+ userSelect: "none",
1539
+ }, children: [_jsx(Layers, { shadowShape: shadowShape, components: [
1540
+ ...extraComponentsState,
1541
+ ...componentsState,
1542
+ polygonElementRef === null || polygonElementRef === void 0 ? void 0 : polygonElementRef.current,
1543
+ ], style: {
777
1544
  cursor: getCursorStyle(),
778
- },
779
- // onClick={handleSelectComponent}
780
- onMouseDown: handleMouseDown,
781
- // onMouseUp={handleMouseUp}
782
- // onBlur={handleUnSelectComponent}
783
- 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 * scale) }, (_, i) => (_jsx("line", { x1: i * 10 * scale, y1: 0, x2: i * 10 * scale, y2: heightBoard }, `v-${i}`))), Array.from({ length: heightBoard / (10 * scale) }, (_, i) => (_jsx("line", { x1: 0, y1: i * 10 * scale, x2: widthBoard, y2: i * 10 * scale }, `h-${i}`)))] }))] }) })] })] })] }));
1545
+ }, selectedComponent: selectedComponent, selectionLines: selectedLines, activeTool: activeTool }), activeTool === "polygon" && (_jsx("polyline", { id: "polyline-helper", stroke: "#4a90e2", fill: "transparent", strokeWidth: 2 })), 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 * scale) }, (_, i) => (_jsx("line", { x1: i * 10 * scale, y1: 0, x2: i * 10 * scale, y2: heightBoard }, `v-${i}`))), Array.from({ length: heightBoard / (10 * scale) }, (_, i) => (_jsx("line", { x1: 0, y1: i * 10 * scale, x2: widthBoard, y2: i * 10 * scale }, `h-${i}`)))] }))] })] }) })] })] }));
784
1546
  };
785
1547
  export default BoardTemplate;