seat-editor 3.3.13 → 3.3.15

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 (136) hide show
  1. package/dist/app/constant.d.ts +1 -0
  2. package/dist/app/constant.js +1 -0
  3. package/dist/app/layout.d.ts +6 -0
  4. package/dist/app/layout.jsx +27 -0
  5. package/dist/app/new-board/page.jsx +55 -0
  6. package/dist/app/old-board/page.d.ts +3 -0
  7. package/dist/app/old-board/page.jsx +510 -0
  8. package/dist/app/only-view/chair.d.ts +1 -0
  9. package/dist/app/only-view/chair.js +12 -0
  10. package/dist/app/only-view/constant.d.ts +60 -0
  11. package/dist/app/only-view/constant.js +1336 -0
  12. package/dist/app/only-view/page.jsx +248 -0
  13. package/dist/app/only-view/user.d.ts +1 -0
  14. package/dist/app/only-view/user.js +12 -0
  15. package/dist/app/page.d.ts +2 -0
  16. package/dist/app/page.jsx +13 -0
  17. package/dist/app/test/page.d.ts +2 -0
  18. package/dist/app/test/page.jsx +45 -0
  19. package/dist/app/v2/page.d.ts +2 -0
  20. package/dist/app/v2/page.jsx +13 -0
  21. package/dist/components/button-tools/index.d.ts +11 -0
  22. package/dist/components/button-tools/index.jsx +17 -0
  23. package/dist/components/form-tools/label.d.ts +2 -0
  24. package/dist/components/form-tools/label.jsx +63 -0
  25. package/dist/components/form-tools/shape.d.ts +8 -0
  26. package/dist/components/form-tools/shape.jsx +113 -0
  27. package/dist/components/input/number-indicator.d.ts +7 -0
  28. package/dist/components/input/number-indicator.jsx +36 -0
  29. package/dist/components/joystick/index.d.ts +12 -0
  30. package/dist/components/joystick/index.jsx +49 -0
  31. package/dist/components/layer/index.d.ts +19 -0
  32. package/dist/components/layer/index.jsx +383 -0
  33. package/dist/components/layer-v2/index.d.ts +19 -0
  34. package/dist/components/layer-v2/index.jsx +370 -0
  35. package/dist/components/layer-v3/index.d.ts +13 -0
  36. package/dist/components/layer-v3/index.jsx +631 -0
  37. package/dist/components/layer-v3/utils.d.ts +19 -0
  38. package/dist/components/layer-v3/utils.js +72 -0
  39. package/dist/components/layer-v4/constant.d.ts +60 -0
  40. package/dist/components/layer-v4/constant.js +93 -0
  41. package/dist/components/layer-v4/index.d.ts +24 -0
  42. package/dist/components/layer-v4/index.jsx +1046 -0
  43. package/dist/components/lib/index.d.ts +8 -0
  44. package/dist/components/lib/index.jsx +33 -0
  45. package/dist/components/modal-preview/index.d.ts +4 -0
  46. package/dist/components/modal-preview/index.jsx +11 -0
  47. package/dist/dto/event-handler.d.ts +1 -0
  48. package/dist/dto/event-handler.js +1 -0
  49. package/dist/dto/table.d.ts +80 -0
  50. package/dist/dto/table.js +1 -0
  51. package/dist/features/board/board-slice.d.ts +14 -0
  52. package/dist/features/board/board-slice.js +52 -0
  53. package/dist/features/board/index.d.ts +6 -0
  54. package/dist/features/board/index.jsx +725 -0
  55. package/dist/features/board-v2/board-slice.d.ts +14 -0
  56. package/dist/features/board-v2/board-slice.js +52 -0
  57. package/dist/features/board-v2/index.d.ts +8 -0
  58. package/dist/features/board-v2/index.jsx +869 -0
  59. package/dist/features/board-v3/board-slice.d.ts +19 -0
  60. package/dist/features/board-v3/board-slice.js +274 -0
  61. package/dist/features/board-v3/constant.d.ts +5 -0
  62. package/dist/features/board-v3/constant.js +5 -0
  63. package/dist/features/board-v3/history-slice.d.ts +27 -0
  64. package/dist/features/board-v3/history-slice.js +27 -0
  65. package/dist/features/board-v3/icons.d.ts +4 -0
  66. package/dist/features/board-v3/icons.jsx +100 -0
  67. package/dist/features/board-v3/index.d.ts +16 -0
  68. package/dist/features/board-v3/index.jsx +1678 -0
  69. package/dist/features/board-v3/polygon.d.ts +28 -0
  70. package/dist/features/board-v3/polygon.js +109 -0
  71. package/dist/features/board-v3/rect.d.ts +9 -0
  72. package/dist/features/board-v3/rect.js +152 -0
  73. package/dist/features/board-v3/resize-element.d.ts +12 -0
  74. package/dist/features/board-v3/resize-element.js +43 -0
  75. package/dist/features/board-v3/utils.d.ts +180 -0
  76. package/dist/features/board-v3/utils.js +1235 -0
  77. package/dist/features/navbar/index.d.ts +2 -0
  78. package/dist/features/navbar/index.jsx +5 -0
  79. package/dist/features/panel/index.d.ts +6 -0
  80. package/dist/features/panel/index.jsx +251 -0
  81. package/dist/features/panel/panel-slice.d.ts +23 -0
  82. package/dist/features/panel/panel-slice.js +46 -0
  83. package/dist/features/panel/select-tool.d.ts +6 -0
  84. package/dist/features/panel/select-tool.jsx +70 -0
  85. package/dist/features/panel/selected-group.d.ts +2 -0
  86. package/dist/features/panel/selected-group.jsx +93 -0
  87. package/dist/features/panel/square-circle-tool.d.ts +2 -0
  88. package/dist/features/panel/square-circle-tool.jsx +10 -0
  89. package/dist/features/panel/table-seat-circle.d.ts +2 -0
  90. package/dist/features/panel/table-seat-circle.jsx +36 -0
  91. package/dist/features/panel/table-seat-square.d.ts +2 -0
  92. package/dist/features/panel/table-seat-square.jsx +51 -0
  93. package/dist/features/panel/text-tool.d.ts +2 -0
  94. package/dist/features/panel/text-tool.jsx +57 -0
  95. package/dist/features/panel/upload-tool.d.ts +10 -0
  96. package/dist/features/panel/upload-tool.jsx +176 -0
  97. package/dist/features/panel/utils.d.ts +5 -0
  98. package/dist/features/panel/utils.js +47 -0
  99. package/dist/features/side-tool/index.d.ts +8 -0
  100. package/dist/features/side-tool/index.jsx +390 -0
  101. package/dist/features/side-tool/side-tool-slice.d.ts +16 -0
  102. package/dist/features/side-tool/side-tool-slice.js +28 -0
  103. package/dist/features/theme/theme-slice.d.ts +12 -0
  104. package/dist/features/theme/theme-slice.js +15 -0
  105. package/dist/features/view-only/index.d.ts +19 -0
  106. package/dist/features/view-only/index.jsx +205 -0
  107. package/dist/features/view-only-2/index.d.ts +19 -0
  108. package/dist/features/view-only-2/index.jsx +190 -0
  109. package/dist/features/view-only-3/index.d.ts +89 -0
  110. package/dist/features/view-only-3/index.jsx +590 -0
  111. package/dist/features/view-only-3/utils.d.ts +1 -0
  112. package/dist/features/view-only-3/utils.js +3 -0
  113. package/dist/hooks/use-redux.d.ts +4 -0
  114. package/dist/hooks/use-redux.js +3 -0
  115. package/dist/index.js +10 -0
  116. package/dist/libs/middleware.d.ts +2 -0
  117. package/dist/libs/middleware.js +5 -0
  118. package/dist/libs/rootReducer.d.ts +12 -0
  119. package/dist/libs/rootReducer.js +14 -0
  120. package/dist/libs/store.d.ts +18 -0
  121. package/dist/libs/store.js +19 -0
  122. package/dist/provider/antd-provider.d.ts +4 -0
  123. package/dist/provider/antd-provider.jsx +46 -0
  124. package/dist/provider/redux-provider.d.ts +3 -0
  125. package/dist/provider/redux-provider.jsx +6 -0
  126. package/dist/provider/store-provider.d.ts +4 -0
  127. package/dist/provider/store-provider.jsx +10 -0
  128. package/dist/utils/constant.d.ts +3 -0
  129. package/dist/utils/constant.js +13 -0
  130. package/dist/utils/format.d.ts +2 -0
  131. package/dist/utils/format.js +29 -0
  132. package/dist/utils/injectCss.d.ts +1 -0
  133. package/dist/utils/injectCss.js +13 -0
  134. package/dist/utils/regex.d.ts +3 -0
  135. package/dist/utils/regex.js +3 -0
  136. package/package.json +1 -1
@@ -0,0 +1,1235 @@
1
+ // interface ResizeParams {
2
+ // selectionStart: {
3
+ // x: number;
4
+ // y: number;
5
+ // width: number;
6
+ // height: number;
7
+ // };
8
+ // rotate: number;
9
+ // element: {
10
+ // x: number;
11
+ // y: number;
12
+ // width: number;
13
+ // height: number;
14
+ // };
15
+ // mouse: {
16
+ // x: number;
17
+ // y: number;
18
+ // };
19
+ // mouseCurrent: {
20
+ // x: number;
21
+ // y: number;
22
+ // };
23
+ // }
24
+ export const resizeElementSelection = ({ selectionStart, currentSelection, rotate, element, mouse, mouseCurrent, }) => {
25
+ const dx = mouse.x - mouseCurrent.x;
26
+ const dy = mouse.y - mouseCurrent.y;
27
+ const startX = selectionStart.x;
28
+ const startY = selectionStart.y;
29
+ const angle = (rotate * Math.PI) / 180;
30
+ const localDx = dx * Math.cos(angle) + dy * Math.sin(angle);
31
+ const localDy = -dx * Math.sin(angle) + dy * Math.cos(angle);
32
+ const scaleYSelection = (selectionStart.height + localDy) / currentSelection.height;
33
+ const scaleXSelection = (selectionStart.width + localDx) / currentSelection.width;
34
+ const scaleConsist = Math.min(scaleXSelection, scaleYSelection);
35
+ const x = startX + localDx * scaleXSelection;
36
+ const y = startY + localDy * scaleYSelection;
37
+ const width = element.width * scaleConsist;
38
+ const height = element.height * scaleConsist;
39
+ return {
40
+ // x,
41
+ // y,
42
+ width,
43
+ height,
44
+ };
45
+ };
46
+ export function resizeBox({ box, dx, dy, rotate, handle }) {
47
+ // 1. mouse → local
48
+ const local = toLocalDelta(dx, dy, rotate);
49
+ // 2. scale
50
+ const { sx, sy } = calcScaleByHandle(handle, local.x, local.y, box.width, box.height);
51
+ const scale = (sx + sy) / 2;
52
+ // 3. anchor
53
+ const { ax, ay } = getAnchor(handle, box);
54
+ // 4. ukuran baru
55
+ const newWidth = box.width * scale;
56
+ const newHeight = box.height * scale;
57
+ // 5. posisi baru dari anchor
58
+ const newX = ax - newWidth * ((ax - box.x) / box.width);
59
+ const newY = ay - newHeight * ((ay - box.y) / box.height);
60
+ return {
61
+ x: newX,
62
+ y: newY,
63
+ width: newWidth,
64
+ height: newHeight,
65
+ };
66
+ }
67
+ function getAnchor(handle, box) {
68
+ const l = box.x;
69
+ const r = box.x + box.width;
70
+ const t = box.y;
71
+ const b = box.y + box.height;
72
+ const cx = box.x + box.width / 2;
73
+ const cy = box.y + box.height / 2;
74
+ switch (handle) {
75
+ case "top":
76
+ return { ax: cx, ay: b };
77
+ case "bottom":
78
+ return { ax: cx, ay: t };
79
+ case "left":
80
+ return { ax: r, ay: cy };
81
+ case "right":
82
+ return { ax: l, ay: cy };
83
+ case "top-left":
84
+ return { ax: r, ay: b };
85
+ case "top-right":
86
+ return { ax: l, ay: b };
87
+ case "bottom-left":
88
+ return { ax: r, ay: t };
89
+ case "bottom-right":
90
+ return { ax: l, ay: t };
91
+ }
92
+ }
93
+ function calcScaleByHandle(handle, localDx, localDy, w, h) {
94
+ let sx = 1;
95
+ let sy = 1;
96
+ if (handle.includes("right")) {
97
+ sx = (w + localDx) / w;
98
+ }
99
+ if (handle.includes("left")) {
100
+ sx = (w - localDx) / w;
101
+ }
102
+ if (handle.includes("bottom")) {
103
+ sy = (h + localDy) / h;
104
+ }
105
+ if (handle.includes("top")) {
106
+ sy = (h - localDy) / h;
107
+ }
108
+ return { sx, sy };
109
+ }
110
+ function toLocalDelta(dx, dy, rotate) {
111
+ const rad = (rotate * Math.PI) / 180;
112
+ const cos = Math.cos(rad);
113
+ const sin = Math.sin(rad);
114
+ return {
115
+ x: dx * cos + dy * sin,
116
+ y: -dx * sin + dy * cos,
117
+ };
118
+ }
119
+ export function getAnchorByHandle(handle, box) {
120
+ const l = box.x;
121
+ const r = box.x + box.width;
122
+ const t = box.y;
123
+ const b = box.y + box.height;
124
+ const cx = box.x + box.width / 2;
125
+ const cy = box.y + box.height / 2;
126
+ switch (handle) {
127
+ case "top":
128
+ return { ax: cx, ay: b };
129
+ case "bottom":
130
+ return { ax: cx, ay: t };
131
+ case "left":
132
+ return { ax: r, ay: cy };
133
+ case "right":
134
+ return { ax: l, ay: cy };
135
+ case "top-left":
136
+ return { ax: r, ay: b };
137
+ case "top-right":
138
+ return { ax: l, ay: b };
139
+ case "bottom-left":
140
+ return { ax: r, ay: t };
141
+ case "bottom-right":
142
+ return { ax: l, ay: t };
143
+ }
144
+ }
145
+ import { isEqual } from "lodash";
146
+ import { arcByDirection, distributeWithSpacing, rectToPolygonNodes, } from "../../components/layer-v3/utils";
147
+ import { MIN_HEIGHT, MIN_WIDTH } from "./constant";
148
+ export const resizeSeatSquare = ({ seatsPositions, r = 10, openSpace, newElement, seats, seatGroup, }) => {
149
+ let top = [];
150
+ let left = [];
151
+ let bottom = [];
152
+ let right = [];
153
+ const topCount = seatsPositions.top;
154
+ const rightCount = seatsPositions.right;
155
+ const bottomCount = seatsPositions.bottom;
156
+ const leftCount = seatsPositions.left;
157
+ const seatCountTopBottom = Math.ceil(Math.max(topCount, bottomCount) / 2);
158
+ const seatCountLeftRight = Math.ceil(Math.max(leftCount, rightCount) / 2);
159
+ const availableWidth = newElement.width * (1 - openSpace);
160
+ const availableHeight = newElement.height * (1 - openSpace);
161
+ const spacingWidth = availableWidth / seatCountTopBottom;
162
+ const spacingHeight = availableHeight / seatCountLeftRight;
163
+ for (let seat of seats) {
164
+ const sideById = seat === null || seat === void 0 ? void 0 : seat.getAttribute("id");
165
+ if (sideById.includes("top")) {
166
+ top.push(seat);
167
+ }
168
+ if (sideById.includes("left")) {
169
+ left.push(seat);
170
+ }
171
+ if (sideById.includes("bottom")) {
172
+ bottom.push(seat);
173
+ }
174
+ if (sideById.includes("right")) {
175
+ right.push(seat);
176
+ }
177
+ }
178
+ const topXs = distributeWithSpacing({
179
+ start: newElement.x,
180
+ length: newElement.width,
181
+ count: topCount,
182
+ radius: r,
183
+ spacing: spacingWidth,
184
+ });
185
+ const topSeats = topXs.map((cx) => ({
186
+ cx,
187
+ cy: newElement.y - r,
188
+ id: "top",
189
+ }));
190
+ const leftYs = distributeWithSpacing({
191
+ start: newElement.y,
192
+ length: newElement.height,
193
+ count: leftCount,
194
+ radius: r,
195
+ spacing: spacingHeight,
196
+ });
197
+ const leftSeats = leftYs.map((cy) => ({
198
+ cx: newElement.x - r,
199
+ cy,
200
+ id: "left",
201
+ }));
202
+ const bottomXs = distributeWithSpacing({
203
+ start: newElement.x,
204
+ length: newElement.width,
205
+ count: bottomCount,
206
+ radius: r,
207
+ spacing: spacingWidth,
208
+ });
209
+ const bottomSeats = bottomXs.map((cx) => ({
210
+ cx,
211
+ cy: newElement.y + newElement.height + r,
212
+ id: "bottom",
213
+ }));
214
+ const rightYs = distributeWithSpacing({
215
+ start: newElement.y,
216
+ length: newElement.height,
217
+ count: rightCount,
218
+ radius: r,
219
+ spacing: spacingHeight,
220
+ });
221
+ const rightSeats = rightYs.map((cy) => ({
222
+ cx: newElement.x + newElement.width + r,
223
+ cy,
224
+ id: "right",
225
+ }));
226
+ top === null || top === void 0 ? void 0 : top.forEach((seat, i) => {
227
+ var _a, _b;
228
+ const cx = (_a = topSeats[i]) === null || _a === void 0 ? void 0 : _a.cx;
229
+ const cy = (_b = topSeats[i]) === null || _b === void 0 ? void 0 : _b.cy;
230
+ seat.setAttribute("cx", cx);
231
+ seat.setAttribute("cy", cy);
232
+ });
233
+ left === null || left === void 0 ? void 0 : left.forEach((seat, i) => {
234
+ var _a, _b;
235
+ const cx = (_a = leftSeats[i]) === null || _a === void 0 ? void 0 : _a.cx;
236
+ const cy = (_b = leftSeats[i]) === null || _b === void 0 ? void 0 : _b.cy;
237
+ seat.setAttribute("cx", cx);
238
+ seat.setAttribute("cy", cy);
239
+ });
240
+ bottom === null || bottom === void 0 ? void 0 : bottom.forEach((seat, i) => {
241
+ var _a, _b;
242
+ const cx = (_a = bottomSeats[i]) === null || _a === void 0 ? void 0 : _a.cx;
243
+ const cy = (_b = bottomSeats[i]) === null || _b === void 0 ? void 0 : _b.cy;
244
+ seat.setAttribute("cx", cx);
245
+ seat.setAttribute("cy", cy);
246
+ });
247
+ right === null || right === void 0 ? void 0 : right.forEach((seat, i) => {
248
+ var _a, _b;
249
+ const cx = (_a = rightSeats[i]) === null || _a === void 0 ? void 0 : _a.cx;
250
+ const cy = (_b = rightSeats[i]) === null || _b === void 0 ? void 0 : _b.cy;
251
+ seat.setAttribute("cx", cx);
252
+ seat.setAttribute("cy", cy);
253
+ });
254
+ seatGroup === null || seatGroup === void 0 ? void 0 : seatGroup.setAttribute("transform", `translate(${-newElement.x}, ${-newElement.y})`);
255
+ };
256
+ export const resizeSeatCircle = ({ seatCount, r = 10, openSpace, seats, seatGroup, newElement, }) => {
257
+ const centerX = newElement.width / 2;
258
+ const centerY = newElement.height / 2;
259
+ const tableRadius = Math.min(newElement.width, newElement.height) / 2;
260
+ const seatRadius = r;
261
+ const fullAngle = Math.PI * 2;
262
+ const availableAngle = fullAngle * (1 - openSpace);
263
+ const angleStart = (fullAngle - availableAngle) / 2;
264
+ const angleStep = availableAngle / seatCount;
265
+ const seatCircles = Array.from({ length: seatCount }, (_, i) => {
266
+ const angle = angleStart + i * angleStep;
267
+ const cx = centerX + (tableRadius + seatRadius) * Math.cos(angle);
268
+ const cy = centerY + (tableRadius + seatRadius) * Math.sin(angle);
269
+ return { cx, cy };
270
+ });
271
+ seatCircles.forEach((seatCircle, i) => {
272
+ const seat = seats[i];
273
+ seat.setAttribute("cx", seatCircle.cx);
274
+ seat.setAttribute("cy", seatCircle.cy);
275
+ });
276
+ };
277
+ export const resizeSeatSide = ({ seatsPositions, r = 10, openSpace, newElement, seats, seatGroup, }) => {
278
+ let top = [];
279
+ let left = [];
280
+ let bottom = [];
281
+ let right = [];
282
+ const seatRaidus = Math.max(newElement.width, newElement.height) * 0.15;
283
+ const topCount = seatsPositions.top;
284
+ const rightCount = seatsPositions.right;
285
+ const bottomCount = seatsPositions.bottom;
286
+ const leftCount = seatsPositions.left;
287
+ const seatCountTopBottom = Math.ceil(Math.max(topCount, bottomCount) / 2);
288
+ const seatCountLeftRight = Math.ceil(Math.max(leftCount, rightCount) / 2);
289
+ const availableWidth = newElement.width * (1 - openSpace);
290
+ const availableHeight = newElement.height * (1 - openSpace);
291
+ const spacingWidth = availableWidth / seatCountTopBottom;
292
+ const spacingHeight = availableHeight / seatCountLeftRight;
293
+ for (let seat of seats) {
294
+ const sideById = seat === null || seat === void 0 ? void 0 : seat.getAttribute("id");
295
+ if (sideById.includes("top")) {
296
+ top.push(seat);
297
+ }
298
+ if (sideById.includes("left")) {
299
+ left.push(seat);
300
+ }
301
+ if (sideById.includes("bottom")) {
302
+ bottom.push(seat);
303
+ }
304
+ if (sideById.includes("right")) {
305
+ right.push(seat);
306
+ }
307
+ }
308
+ const topXs = distributeWithSpacing({
309
+ start: newElement.x,
310
+ length: newElement.width,
311
+ count: topCount,
312
+ radius: seatRaidus,
313
+ spacing: spacingWidth,
314
+ });
315
+ const topSeats = topXs.map((cx) => ({
316
+ cx,
317
+ cy: newElement.y - seatRaidus,
318
+ id: "top",
319
+ d: arcByDirection({
320
+ cx,
321
+ cy: newElement.y - seatRaidus * 0.1,
322
+ r: seatRaidus,
323
+ direction: "top",
324
+ fraction: 0.4,
325
+ }),
326
+ }));
327
+ const leftYs = distributeWithSpacing({
328
+ start: newElement.y,
329
+ length: newElement.height,
330
+ count: leftCount,
331
+ radius: seatRaidus,
332
+ spacing: spacingHeight,
333
+ });
334
+ const leftSeats = leftYs.map((cy) => ({
335
+ cx: newElement.x - seatRaidus * 0.1,
336
+ cy,
337
+ id: "left",
338
+ d: arcByDirection({
339
+ cx: newElement.x - seatRaidus * 0.1,
340
+ cy,
341
+ r: seatRaidus,
342
+ direction: "left",
343
+ fraction: 0.4,
344
+ }),
345
+ }));
346
+ const bottomXs = distributeWithSpacing({
347
+ start: newElement.x,
348
+ length: newElement.width,
349
+ count: bottomCount,
350
+ radius: seatRaidus,
351
+ spacing: spacingWidth,
352
+ });
353
+ const bottomSeats = bottomXs.map((cx) => ({
354
+ cx,
355
+ cy: newElement.y + newElement.height + seatRaidus * 0.1,
356
+ id: "bottom",
357
+ d: arcByDirection({
358
+ cx,
359
+ cy: newElement.y + newElement.height + seatRaidus * 0.1,
360
+ r: seatRaidus,
361
+ direction: "bottom",
362
+ fraction: 0.4,
363
+ }),
364
+ }));
365
+ const rightYs = distributeWithSpacing({
366
+ start: newElement.y,
367
+ length: newElement.height,
368
+ count: rightCount,
369
+ radius: r,
370
+ spacing: spacingHeight,
371
+ });
372
+ const rightSeats = rightYs.map((cy) => ({
373
+ cx: newElement.x + newElement.width + +seatRaidus * 0.1,
374
+ cy,
375
+ id: "right",
376
+ d: arcByDirection({
377
+ cx: newElement.x + newElement.width + +seatRaidus * 0.1,
378
+ cy,
379
+ r,
380
+ direction: "right",
381
+ fraction: 0.4,
382
+ }),
383
+ }));
384
+ top === null || top === void 0 ? void 0 : top.forEach((seat, i) => {
385
+ var _a;
386
+ seat.setAttribute("d", (_a = topSeats[i]) === null || _a === void 0 ? void 0 : _a.d);
387
+ });
388
+ left === null || left === void 0 ? void 0 : left.forEach((seat, i) => {
389
+ var _a;
390
+ seat.setAttribute("d", (_a = leftSeats[i]) === null || _a === void 0 ? void 0 : _a.d);
391
+ });
392
+ bottom === null || bottom === void 0 ? void 0 : bottom.forEach((seat, i) => {
393
+ var _a;
394
+ seat.setAttribute("d", (_a = bottomSeats[i]) === null || _a === void 0 ? void 0 : _a.d);
395
+ });
396
+ right === null || right === void 0 ? void 0 : right.forEach((seat, i) => {
397
+ var _a;
398
+ seat.setAttribute("d", (_a = rightSeats[i]) === null || _a === void 0 ? void 0 : _a.d);
399
+ });
400
+ seatGroup === null || seatGroup === void 0 ? void 0 : seatGroup.setAttribute("transform", `translate(${-newElement.x}, ${-newElement.y})`);
401
+ };
402
+ export const resizeSeatRectCircle = ({ seatsPositions, r = 10, openSpace, newElement, seats, seatGroup, }) => {
403
+ let top = [];
404
+ let left = [];
405
+ let bottom = [];
406
+ let right = [];
407
+ const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
408
+ const width = newElement.width;
409
+ const height = newElement.height;
410
+ const x = newElement.x;
411
+ const y = newElement.y;
412
+ const seatRadius = Math.min(width, height) * 0.2;
413
+ const topCount = seatsPositions.top;
414
+ const rightCount = seatsPositions.right;
415
+ const bottomCount = seatsPositions.bottom;
416
+ const leftCount = seatsPositions.left;
417
+ const seatCountTopBottom = Math.ceil(Math.max(topCount, bottomCount) / 2);
418
+ const seatCountLeftRight = Math.ceil(Math.max(leftCount, rightCount) / 2);
419
+ const availableWidth = newElement.width * (1 - openSpace);
420
+ const availableHeight = newElement.height * (1 - openSpace);
421
+ const spacingWidth = availableWidth / seatCountTopBottom;
422
+ const spacingHeight = availableHeight / seatCountLeftRight;
423
+ const base = clamp(Math.min(width, height) * 0.08, 12, 28);
424
+ const seatSizeTB = {
425
+ w: base * 1.8, // lebih panjang
426
+ h: base * 0.9, // lebih tipis
427
+ };
428
+ const seatSizeLR = {
429
+ w: base * 0.9, // lebih tipis
430
+ h: base * 1.8, // lebih panjang
431
+ };
432
+ for (let seat of seats) {
433
+ const sideById = seat === null || seat === void 0 ? void 0 : seat.getAttribute("id");
434
+ if (sideById.includes("top")) {
435
+ top.push(seat);
436
+ }
437
+ if (sideById.includes("left")) {
438
+ left.push(seat);
439
+ }
440
+ if (sideById.includes("bottom")) {
441
+ bottom.push(seat);
442
+ }
443
+ if (sideById.includes("right")) {
444
+ right.push(seat);
445
+ }
446
+ }
447
+ const topXs = distributeWithSpacing({
448
+ start: newElement.x,
449
+ length: newElement.width,
450
+ count: topCount,
451
+ radius: seatRadius,
452
+ spacing: spacingWidth,
453
+ });
454
+ const topSeats = topXs.map((cx) => ({
455
+ x: cx - seatSizeTB.w / 2,
456
+ y: y - seatSizeTB.h,
457
+ width: seatSizeTB.w,
458
+ height: seatSizeTB.h,
459
+ id: "top",
460
+ }));
461
+ const leftYs = distributeWithSpacing({
462
+ start: newElement.y,
463
+ length: newElement.height,
464
+ count: leftCount,
465
+ radius: seatRadius,
466
+ spacing: spacingHeight,
467
+ });
468
+ const leftSeats = leftYs.map((cy) => ({
469
+ x: -seatSizeLR.w,
470
+ y: cy - seatSizeLR.h / 2,
471
+ width: seatSizeLR.w,
472
+ height: seatSizeLR.h,
473
+ id: "left",
474
+ }));
475
+ const bottomXs = distributeWithSpacing({
476
+ start: newElement.x,
477
+ length: newElement.width,
478
+ count: bottomCount,
479
+ radius: seatRadius,
480
+ spacing: spacingWidth,
481
+ });
482
+ const bottomSeats = bottomXs.map((cx) => ({
483
+ x: cx - seatSizeTB.w / 2,
484
+ y: y + height,
485
+ width: seatSizeTB.w,
486
+ height: seatSizeTB.h,
487
+ id: "bottom",
488
+ }));
489
+ const rightYs = distributeWithSpacing({
490
+ start: newElement.y,
491
+ length: newElement.height,
492
+ count: rightCount,
493
+ radius: seatRadius,
494
+ spacing: spacingHeight,
495
+ });
496
+ const rightSeats = rightYs.map((cy) => ({
497
+ x: width,
498
+ y: cy - seatSizeLR.h / 2,
499
+ width: seatSizeLR.w,
500
+ height: seatSizeLR.h,
501
+ id: "right",
502
+ }));
503
+ top === null || top === void 0 ? void 0 : top.forEach((seat, i) => {
504
+ var _a, _b, _c, _d;
505
+ seat.setAttribute("x", (_a = topSeats[i]) === null || _a === void 0 ? void 0 : _a.x);
506
+ seat.setAttribute("y", (_b = topSeats[i]) === null || _b === void 0 ? void 0 : _b.y);
507
+ seat.setAttribute("height", (_c = topSeats[i]) === null || _c === void 0 ? void 0 : _c.height);
508
+ seat.setAttribute("width", (_d = topSeats[i]) === null || _d === void 0 ? void 0 : _d.width);
509
+ });
510
+ left === null || left === void 0 ? void 0 : left.forEach((seat, i) => {
511
+ var _a, _b, _c, _d;
512
+ seat.setAttribute("x", (_a = leftSeats[i]) === null || _a === void 0 ? void 0 : _a.x);
513
+ seat.setAttribute("y", (_b = leftSeats[i]) === null || _b === void 0 ? void 0 : _b.y);
514
+ seat.setAttribute("height", (_c = leftSeats[i]) === null || _c === void 0 ? void 0 : _c.height);
515
+ seat.setAttribute("width", (_d = leftSeats[i]) === null || _d === void 0 ? void 0 : _d.width);
516
+ });
517
+ bottom === null || bottom === void 0 ? void 0 : bottom.forEach((seat, i) => {
518
+ var _a, _b, _c, _d;
519
+ seat.setAttribute("x", (_a = bottomSeats[i]) === null || _a === void 0 ? void 0 : _a.x);
520
+ seat.setAttribute("y", (_b = bottomSeats[i]) === null || _b === void 0 ? void 0 : _b.y);
521
+ seat.setAttribute("height", (_c = bottomSeats[i]) === null || _c === void 0 ? void 0 : _c.height);
522
+ seat.setAttribute("width", (_d = bottomSeats[i]) === null || _d === void 0 ? void 0 : _d.width);
523
+ });
524
+ right === null || right === void 0 ? void 0 : right.forEach((seat, i) => {
525
+ var _a, _b, _c, _d;
526
+ seat.setAttribute("x", (_a = rightSeats[i]) === null || _a === void 0 ? void 0 : _a.x);
527
+ seat.setAttribute("y", (_b = rightSeats[i]) === null || _b === void 0 ? void 0 : _b.y);
528
+ seat.setAttribute("height", (_c = rightSeats[i]) === null || _c === void 0 ? void 0 : _c.height);
529
+ seat.setAttribute("width", (_d = rightSeats[i]) === null || _d === void 0 ? void 0 : _d.width);
530
+ });
531
+ seatGroup === null || seatGroup === void 0 ? void 0 : seatGroup.setAttribute("transform", `translate(${-newElement.x}, ${-newElement.y})`);
532
+ };
533
+ export const resizeSeatRectSquare = ({ seatsPositions, r = 10, openSpace, newElement, seats, seatGroup, }) => {
534
+ let top = [];
535
+ let left = [];
536
+ let bottom = [];
537
+ let right = [];
538
+ const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
539
+ const width = newElement.width;
540
+ const height = newElement.height;
541
+ const y = newElement.y;
542
+ const x = newElement.x;
543
+ const base = clamp(Math.min(width, height) * 0.08, 12, 28);
544
+ const seatSizeTB = {
545
+ w: base * 1.8, // lebih panjang
546
+ h: base * 0.9, // lebih tipis
547
+ };
548
+ const seatSizeLR = {
549
+ w: base * 0.9, // lebih tipis
550
+ h: base * 1.8, // lebih panjang
551
+ };
552
+ const seatRadius = Math.min(width, height) * 0.2;
553
+ const topCount = seatsPositions.top;
554
+ const rightCount = seatsPositions.right;
555
+ const bottomCount = seatsPositions.bottom;
556
+ const leftCount = seatsPositions.left;
557
+ const seatCountTopBottom = Math.ceil(Math.max(topCount, bottomCount) / 2);
558
+ const seatCountLeftRight = Math.ceil(Math.max(leftCount, rightCount) / 2);
559
+ const availableWidth = width * (1 - openSpace);
560
+ const availableHeight = height * (1 - openSpace);
561
+ const spacingWidth = availableWidth / seatCountTopBottom;
562
+ const spacingHeight = availableHeight / seatCountLeftRight;
563
+ for (let seat of seats) {
564
+ const sideById = seat === null || seat === void 0 ? void 0 : seat.getAttribute("id");
565
+ if (sideById.includes("top")) {
566
+ top.push(seat);
567
+ }
568
+ if (sideById.includes("left")) {
569
+ left.push(seat);
570
+ }
571
+ if (sideById.includes("bottom")) {
572
+ bottom.push(seat);
573
+ }
574
+ if (sideById.includes("right")) {
575
+ right.push(seat);
576
+ }
577
+ }
578
+ const topXs = distributeWithSpacing({
579
+ start: newElement.x,
580
+ length: width,
581
+ count: topCount,
582
+ radius: seatRadius,
583
+ spacing: spacingWidth,
584
+ });
585
+ const topSeats = topXs.map((cx) => ({
586
+ x: (cx) - seatSizeTB.w / 2,
587
+ y: y - seatSizeTB.h,
588
+ width: seatSizeTB.w,
589
+ height: seatSizeTB.h,
590
+ id: "top",
591
+ }));
592
+ const leftYs = distributeWithSpacing({
593
+ start: newElement.y,
594
+ length: height,
595
+ count: leftCount,
596
+ radius: seatRadius,
597
+ spacing: spacingHeight,
598
+ });
599
+ const leftSeats = leftYs.map((cy) => ({
600
+ x: -seatSizeLR.w,
601
+ y: cy - seatSizeLR.h / 2,
602
+ width: seatSizeLR.w,
603
+ height: seatSizeLR.h,
604
+ id: "left",
605
+ }));
606
+ const bottomXs = distributeWithSpacing({
607
+ start: newElement.x,
608
+ length: newElement.width,
609
+ count: bottomCount,
610
+ radius: seatRadius,
611
+ spacing: spacingWidth,
612
+ });
613
+ const bottomSeats = bottomXs.map((cx) => ({
614
+ x: cx - seatSizeTB.w / 2,
615
+ y: y + height,
616
+ width: seatSizeTB.w,
617
+ height: seatSizeTB.h,
618
+ id: "bottom",
619
+ }));
620
+ const rightYs = distributeWithSpacing({
621
+ start: newElement.y,
622
+ length: newElement.height,
623
+ count: rightCount,
624
+ radius: seatRadius,
625
+ spacing: spacingHeight,
626
+ });
627
+ const rightSeats = rightYs.map((cy) => ({
628
+ x: width,
629
+ y: cy - seatSizeLR.h / 2,
630
+ width: seatSizeLR.w,
631
+ height: seatSizeLR.h,
632
+ id: "right",
633
+ }));
634
+ top === null || top === void 0 ? void 0 : top.forEach((seat, i) => {
635
+ var _a, _b, _c, _d;
636
+ seat.setAttribute("x", (_a = topSeats[i]) === null || _a === void 0 ? void 0 : _a.x);
637
+ seat.setAttribute("y", (_b = topSeats[i]) === null || _b === void 0 ? void 0 : _b.y);
638
+ seat.setAttribute("height", (_c = topSeats[i]) === null || _c === void 0 ? void 0 : _c.height);
639
+ seat.setAttribute("width", (_d = topSeats[i]) === null || _d === void 0 ? void 0 : _d.width);
640
+ });
641
+ left === null || left === void 0 ? void 0 : left.forEach((seat, i) => {
642
+ var _a, _b, _c, _d;
643
+ seat.setAttribute("x", (_a = leftSeats[i]) === null || _a === void 0 ? void 0 : _a.x);
644
+ seat.setAttribute("y", (_b = leftSeats[i]) === null || _b === void 0 ? void 0 : _b.y);
645
+ seat.setAttribute("height", (_c = leftSeats[i]) === null || _c === void 0 ? void 0 : _c.height);
646
+ seat.setAttribute("width", (_d = leftSeats[i]) === null || _d === void 0 ? void 0 : _d.width);
647
+ });
648
+ bottom === null || bottom === void 0 ? void 0 : bottom.forEach((seat, i) => {
649
+ var _a, _b, _c, _d;
650
+ seat.setAttribute("x", (_a = bottomSeats[i]) === null || _a === void 0 ? void 0 : _a.x);
651
+ seat.setAttribute("y", (_b = bottomSeats[i]) === null || _b === void 0 ? void 0 : _b.y);
652
+ seat.setAttribute("height", (_c = bottomSeats[i]) === null || _c === void 0 ? void 0 : _c.height);
653
+ seat.setAttribute("width", (_d = bottomSeats[i]) === null || _d === void 0 ? void 0 : _d.width);
654
+ });
655
+ right === null || right === void 0 ? void 0 : right.forEach((seat, i) => {
656
+ var _a, _b, _c, _d;
657
+ seat.setAttribute("x", (_a = rightSeats[i]) === null || _a === void 0 ? void 0 : _a.x);
658
+ seat.setAttribute("y", (_b = rightSeats[i]) === null || _b === void 0 ? void 0 : _b.y);
659
+ seat.setAttribute("height", (_c = rightSeats[i]) === null || _c === void 0 ? void 0 : _c.height);
660
+ seat.setAttribute("width", (_d = rightSeats[i]) === null || _d === void 0 ? void 0 : _d.width);
661
+ });
662
+ seatGroup === null || seatGroup === void 0 ? void 0 : seatGroup.setAttribute("transform", `translate(${-newElement.x}, ${-newElement.y})`);
663
+ };
664
+ export function mergeById(base, updates) {
665
+ const map = new Map(updates.map((item) => [item.id, item]));
666
+ return base.map((item) => map.has(item.id) ? Object.assign(Object.assign({}, item), map.get(item.id)) : item);
667
+ }
668
+ export function updateSingleComponent(state, component, setState) {
669
+ const prev = state.find((item) => item.id === component.id);
670
+ if (!prev || isEqual(prev, component))
671
+ return;
672
+ const next = mergeById(state, [component]);
673
+ setState(next);
674
+ return next;
675
+ }
676
+ export function updateManyComponents(state, components, setState) {
677
+ if (!components.length)
678
+ return state;
679
+ const next = mergeById(state, components);
680
+ setState(next);
681
+ return next;
682
+ }
683
+ export function normalizeAngle(angle) {
684
+ return ((angle % 360) + 360) % 360;
685
+ }
686
+ export function createTableGhost({ x, y, width, height, fill, shape, id = "ghost-element-create", }) {
687
+ // buat group dulu
688
+ const SVG_NS = "http://www.w3.org/2000/svg";
689
+ let el = null;
690
+ // tambahkan rectangle
691
+ if (shape === "square" ||
692
+ shape === "table-seat-circle" ||
693
+ shape === "selection-box" ||
694
+ shape === "bounding-box") {
695
+ el = document.createElementNS(SVG_NS, "rect");
696
+ el.setAttribute("id", id);
697
+ el.setAttribute("x", x);
698
+ el.setAttribute("y", y);
699
+ el.setAttribute("width", width);
700
+ el.setAttribute("height", height);
701
+ el.setAttribute("fill", fill);
702
+ el.setAttribute("stroke", "blue");
703
+ el.setAttribute("data-table", JSON.stringify({
704
+ x,
705
+ y,
706
+ width,
707
+ height,
708
+ shape,
709
+ fill,
710
+ stroke: "blue",
711
+ rotation: 0,
712
+ }));
713
+ }
714
+ else if (shape === "circle") {
715
+ el = document.createElementNS(SVG_NS, "circle");
716
+ el.setAttribute("id", id);
717
+ el.setAttribute("cx", x);
718
+ el.setAttribute("cy", y);
719
+ el.setAttribute("r", Math.min(width, height) / 2);
720
+ el.setAttribute("fill", fill);
721
+ el.setAttribute("stroke", "blue");
722
+ el.setAttribute("data-table", JSON.stringify({
723
+ x,
724
+ y,
725
+ width,
726
+ height,
727
+ shape,
728
+ fill,
729
+ stroke: "blue",
730
+ rotation: 0,
731
+ }));
732
+ }
733
+ else if (shape === "text") {
734
+ el = document.createElementNS(SVG_NS, "text");
735
+ el.setAttribute("id", id);
736
+ el.setAttribute("x", x);
737
+ el.setAttribute("y", y + height / 2);
738
+ el.setAttribute("fill", "#000000");
739
+ el.setAttribute("data-table", JSON.stringify({
740
+ x,
741
+ y,
742
+ width,
743
+ height,
744
+ shape,
745
+ fill,
746
+ stroke: "blue",
747
+ rotation: 0,
748
+ fontSize: 14,
749
+ }));
750
+ el.textContent = "Text";
751
+ el.setAttribute("color", "white");
752
+ el.setAttribute("fontSize", "14px");
753
+ }
754
+ return el;
755
+ }
756
+ export function updateSelectionBox(svg, boxSelection, id, unFollowCursor) {
757
+ var _a, _b, _c, _d, _e;
758
+ const rect = svg.querySelector("#selection-lines");
759
+ if (!rect)
760
+ return;
761
+ const nodes = svg.querySelectorAll(`#circle-corner-${id}`);
762
+ const helperRotate = svg.querySelector("#help-group-0");
763
+ const lineHelp = svg.querySelector("#line-help");
764
+ const circleHelp = svg.querySelector("#circle-help");
765
+ // 1. Move selection group
766
+ rect.setAttribute("transform", `translate(${boxSelection.x}, ${boxSelection.y})`);
767
+ const nodesRaw = rectToPolygonNodes(boxSelection.width, boxSelection.height);
768
+ if (!unFollowCursor) {
769
+ const mx = (_a = nodesRaw === null || nodesRaw === void 0 ? void 0 : nodesRaw[1]) === null || _a === void 0 ? void 0 : _a.x;
770
+ const my = (_b = nodesRaw === null || nodesRaw === void 0 ? void 0 : nodesRaw[3]) === null || _b === void 0 ? void 0 : _b.y;
771
+ const x1 = mx;
772
+ const y1 = my;
773
+ const x2 = mx;
774
+ const y2 = my - boxSelection.height + 10;
775
+ lineHelp === null || lineHelp === void 0 ? void 0 : lineHelp.setAttribute("x1", String(x1));
776
+ lineHelp === null || lineHelp === void 0 ? void 0 : lineHelp.setAttribute("y1", String(y1));
777
+ lineHelp === null || lineHelp === void 0 ? void 0 : lineHelp.setAttribute("x2", String(x2));
778
+ lineHelp === null || lineHelp === void 0 ? void 0 : lineHelp.setAttribute("y2", String(y2));
779
+ circleHelp === null || circleHelp === void 0 ? void 0 : circleHelp.setAttribute("cx", String(x2));
780
+ circleHelp === null || circleHelp === void 0 ? void 0 : circleHelp.setAttribute("cy", String(y2));
781
+ helperRotate.setAttribute("transform", `translate(${boxSelection.x}, ${boxSelection.y})`);
782
+ }
783
+ // 2. Resize rect
784
+ const selectionRect = (_e = (_d = (_c = rect.children) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.children) === null || _e === void 0 ? void 0 : _e[0];
785
+ if (selectionRect) {
786
+ selectionRect.setAttribute("width", String(boxSelection.width));
787
+ selectionRect.setAttribute("height", String(boxSelection.height));
788
+ }
789
+ // 3. Update corner nodes
790
+ const points = rectToPolygonNodes(boxSelection.width, boxSelection.height);
791
+ nodes.forEach((node, index) => {
792
+ const p = points[index];
793
+ if (!p)
794
+ return;
795
+ node.setAttribute("cx", String(p.x));
796
+ node.setAttribute("cy", String(p.y));
797
+ });
798
+ }
799
+ export function getGlobalBBox(svg, el) {
800
+ var _a;
801
+ const bbox = el === null || el === void 0 ? void 0 : el.getBBox();
802
+ // matrix dari element ke screen pixel
803
+ const m = el === null || el === void 0 ? void 0 : el.getScreenCTM();
804
+ if (!m)
805
+ return null;
806
+ // matrix dari screen pixel ke svg user coords
807
+ const screenToSvg = (_a = svg.getScreenCTM()) === null || _a === void 0 ? void 0 : _a.inverse();
808
+ if (!screenToSvg)
809
+ return null;
810
+ function transformPoint(x, y) {
811
+ const p = new DOMPoint(x, y)
812
+ .matrixTransform(m)
813
+ .matrixTransform(screenToSvg);
814
+ return { x: p.x, y: p.y };
815
+ }
816
+ const p1 = transformPoint(bbox.x, bbox.y);
817
+ const p2 = transformPoint(bbox.x + bbox.width, bbox.y);
818
+ const p3 = transformPoint(bbox.x + bbox.width, bbox.y + bbox.height);
819
+ const p4 = transformPoint(bbox.x, bbox.y + bbox.height);
820
+ const xs = [p1.x, p2.x, p3.x, p4.x];
821
+ const ys = [p1.y, p2.y, p3.y, p4.y];
822
+ // const rotation = Math.atan2(p2.y - p1.y, p2.x - p1.x) * (180 / Math.PI);
823
+ return {
824
+ x: Math.min(...xs),
825
+ y: Math.min(...ys),
826
+ width: Math.max(...xs) - Math.min(...xs),
827
+ height: Math.max(...ys) - Math.min(...ys),
828
+ // rotation
829
+ };
830
+ }
831
+ function localToWorld(dx, dy, angle) {
832
+ const cosR = Math.cos(angle);
833
+ const sinR = Math.sin(angle);
834
+ return {
835
+ x: dx * cosR - dy * sinR,
836
+ y: dx * sinR + dy * cosR,
837
+ };
838
+ }
839
+ export function getTranslate(el) {
840
+ if (!el)
841
+ return {
842
+ x: null,
843
+ y: null,
844
+ };
845
+ const t = el.getAttribute("transform") || "";
846
+ // cari pola translate( x , y )
847
+ const match = t.match(/translate\(\s*([-\d.]+)[ ,]+([-\d.]+)\s*\)/);
848
+ if (!match)
849
+ return { x: 0, y: 0 };
850
+ return {
851
+ x: parseFloat(match[1]),
852
+ y: parseFloat(match[2]),
853
+ };
854
+ }
855
+ export function getSize(el) {
856
+ const bbox = el.getBBox();
857
+ return {
858
+ width: bbox.width,
859
+ height: bbox.height,
860
+ };
861
+ }
862
+ export function stabilizeRotation(tx, ty, W, H, oldAngle, newAngle) {
863
+ const cx = W / 2;
864
+ const cy = H / 2;
865
+ const oldA = (oldAngle * Math.PI) / 180;
866
+ const newA = (newAngle * Math.PI) / 180;
867
+ // old center global
868
+ const oldGx = tx + (cx * Math.cos(oldA) - cy * Math.sin(oldA));
869
+ const oldGy = ty + (cx * Math.sin(oldA) + cy * Math.cos(oldA));
870
+ // new center global
871
+ const newGx = tx + (cx * Math.cos(newA) - cy * Math.sin(newA));
872
+ const newGy = ty + (cx * Math.sin(newA) + cy * Math.cos(newA));
873
+ // delta shift
874
+ const dx = oldGx - newGx;
875
+ const dy = oldGy - newGy;
876
+ return { tx: tx + dx, ty: ty + dy };
877
+ }
878
+ const SNAP_RADIUS = 10;
879
+ export function isClosingPolygon(mouseX, mouseY, points) {
880
+ const p0 = points[0]; // titik awal
881
+ const dx = mouseX - p0.x;
882
+ const dy = mouseY - p0.y;
883
+ const dist = Math.sqrt(dx * dx + dy * dy);
884
+ return dist < SNAP_RADIUS;
885
+ }
886
+ export function getPolygonCenter(points) {
887
+ if (!points.length) {
888
+ return { cx: 0, cy: 0 };
889
+ }
890
+ let minX = Infinity;
891
+ let minY = Infinity;
892
+ let maxX = -Infinity;
893
+ let maxY = -Infinity;
894
+ for (const p of points) {
895
+ if (p.x < minX)
896
+ minX = p.x;
897
+ if (p.y < minY)
898
+ minY = p.y;
899
+ if (p.x > maxX)
900
+ maxX = p.x;
901
+ if (p.y > maxY)
902
+ maxY = p.y;
903
+ }
904
+ return {
905
+ cx: (minX + maxX) / 2,
906
+ cy: (minY + maxY) / 2,
907
+ };
908
+ }
909
+ export function stabilizeTranslateOnRotate({ points, oldAngle, newAngle, tx, ty, }) {
910
+ // center polygon (bbox center)
911
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
912
+ for (const p of points) {
913
+ minX = Math.min(minX, p.x);
914
+ minY = Math.min(minY, p.y);
915
+ maxX = Math.max(maxX, p.x);
916
+ maxY = Math.max(maxY, p.y);
917
+ }
918
+ const cx = (minX + maxX) / 2;
919
+ const cy = (minY + maxY) / 2;
920
+ const r0 = (oldAngle * Math.PI) / 180;
921
+ const r1 = (newAngle * Math.PI) / 180;
922
+ const x0 = cx * Math.cos(r0) - cy * Math.sin(r0);
923
+ const y0 = cx * Math.sin(r0) + cy * Math.cos(r0);
924
+ const x1 = cx * Math.cos(r1) - cy * Math.sin(r1);
925
+ const y1 = cx * Math.sin(r1) + cy * Math.cos(r1);
926
+ return {
927
+ tx: tx + (x0 - x1),
928
+ ty: ty + (y0 - y1),
929
+ };
930
+ }
931
+ export function pointsStringToArray(pointsStr) {
932
+ return pointsStr
933
+ .trim()
934
+ .split(/\s+/) // pisah antar titik
935
+ .map((pair) => {
936
+ const [x, y] = pair.split(",").map(Number);
937
+ return { x, y };
938
+ })
939
+ .filter((p) => !Number.isNaN(p.x) && !Number.isNaN(p.y));
940
+ }
941
+ export function arrayToSvgPointsAttr(points) {
942
+ return points === null || points === void 0 ? void 0 : points.map((p) => `${p.x},${p.y}`).join(" ");
943
+ }
944
+ export function getSvgElementSize(el) {
945
+ if (el instanceof SVGRectElement) {
946
+ return {
947
+ width: el.width.baseVal.value,
948
+ height: el.height.baseVal.value,
949
+ };
950
+ }
951
+ if (el instanceof SVGCircleElement) {
952
+ const r = el.r.baseVal.value;
953
+ return {
954
+ width: r * 2,
955
+ height: r * 2,
956
+ };
957
+ }
958
+ if (el instanceof SVGEllipseElement) {
959
+ return {
960
+ width: el.rx.baseVal.value * 2,
961
+ height: el.ry.baseVal.value * 2,
962
+ };
963
+ }
964
+ if (el instanceof SVGImageElement) {
965
+ return {
966
+ width: el.width.baseVal.value,
967
+ height: el.height.baseVal.value,
968
+ };
969
+ }
970
+ return {
971
+ width: 0,
972
+ height: 0,
973
+ };
974
+ }
975
+ const updateSvgAttrs = (el, attrs) => {
976
+ if (!el)
977
+ return;
978
+ for (const key in attrs) {
979
+ const value = attrs[key];
980
+ if (value == null)
981
+ continue;
982
+ const next = String(value);
983
+ if (el.getAttribute(key) !== next) {
984
+ el.setAttribute(key, next);
985
+ }
986
+ }
987
+ };
988
+ export function applyResizeToSvgElement(element, group, resize, component) {
989
+ const tagName = element.tagName.toLowerCase();
990
+ switch (tagName) {
991
+ case "rect":
992
+ case "image": {
993
+ updateSvgAttrs(element, {
994
+ width: resize.width < 60 ? 60 : resize.width,
995
+ height: resize.height < MIN_HEIGHT ? MIN_HEIGHT : resize.height,
996
+ // fill: component.fill,
997
+ });
998
+ updateSvgAttrs(group, {
999
+ transform: `translate(${resize.x}, ${resize.y})`,
1000
+ });
1001
+ break;
1002
+ }
1003
+ case "circle": {
1004
+ const width = resize.width < MIN_WIDTH ? MIN_WIDTH : resize.width;
1005
+ const height = resize.height < MIN_HEIGHT ? MIN_HEIGHT : resize.height;
1006
+ const r = Math.min(width, height) / 2;
1007
+ updateSvgAttrs(element, {
1008
+ r,
1009
+ cx: width / 2,
1010
+ cy: height / 2,
1011
+ // fill: component.fill,
1012
+ });
1013
+ group.setAttribute("transform", `translate(${resize.x}, ${resize.y})`);
1014
+ // inner
1015
+ break;
1016
+ }
1017
+ case "ellipse": {
1018
+ element.setAttribute("rx", String(resize.width / 2));
1019
+ element.setAttribute("ry", String(resize.height / 2));
1020
+ break;
1021
+ }
1022
+ case "polygon": {
1023
+ const points = resize.points;
1024
+ element.setAttribute("points", arrayToSvgPointsAttr(points));
1025
+ break;
1026
+ }
1027
+ default: {
1028
+ console.warn(`[applyResizeToSvgElement] Unsupported SVG tag: ${tagName}`);
1029
+ }
1030
+ }
1031
+ // translate selalu di group
1032
+ }
1033
+ function applySizeToSvgElement(element, width, height) {
1034
+ const tag = element.tagName.toLowerCase();
1035
+ if (tag === "rect" || tag === "image") {
1036
+ element.setAttribute("width", String(width));
1037
+ element.setAttribute("height", String(height));
1038
+ return;
1039
+ }
1040
+ if (tag === "circle") {
1041
+ const r = Math.max(0, Math.min(width, height) / 2);
1042
+ element.setAttribute("r", String(r));
1043
+ element.setAttribute("cx", String(width / 2));
1044
+ element.setAttribute("cy", String(height / 2));
1045
+ return;
1046
+ }
1047
+ if (tag === "ellipse") {
1048
+ element.setAttribute("rx", String(width / 2));
1049
+ element.setAttribute("ry", String(height / 2));
1050
+ return;
1051
+ }
1052
+ }
1053
+ const RESIZE_RULES_SECOND = {
1054
+ right: {
1055
+ widthFactor: 1,
1056
+ heightFactor: 0,
1057
+ moveX: () => 0,
1058
+ moveY: () => 0,
1059
+ },
1060
+ left: {
1061
+ widthFactor: -1,
1062
+ heightFactor: 0,
1063
+ moveX: (dx) => dx,
1064
+ moveY: () => 0,
1065
+ },
1066
+ bottom: {
1067
+ widthFactor: 0,
1068
+ heightFactor: 1,
1069
+ moveX: () => 0,
1070
+ moveY: () => 0,
1071
+ },
1072
+ top: {
1073
+ widthFactor: 0,
1074
+ heightFactor: -1,
1075
+ moveX: () => 0,
1076
+ moveY: (dy) => dy,
1077
+ },
1078
+ "bottom-right": {
1079
+ widthFactor: 1,
1080
+ heightFactor: 1,
1081
+ moveX: () => 0,
1082
+ moveY: () => 0,
1083
+ },
1084
+ "bottom-left": {
1085
+ widthFactor: -1,
1086
+ heightFactor: 1,
1087
+ moveX: (dx) => dx,
1088
+ moveY: () => 0,
1089
+ },
1090
+ "top-right": {
1091
+ widthFactor: 1,
1092
+ heightFactor: -1,
1093
+ moveX: () => 0,
1094
+ moveY: (dy) => dy,
1095
+ },
1096
+ "top-left": {
1097
+ widthFactor: -1,
1098
+ heightFactor: -1,
1099
+ moveX: (dx) => dx,
1100
+ moveY: (dy) => dy,
1101
+ },
1102
+ };
1103
+ const RESIZE_RULES = {
1104
+ "bottom-right": {
1105
+ widthFactor: 1,
1106
+ heightFactor: 1,
1107
+ moveLocalX: () => 0,
1108
+ moveLocalY: () => 0,
1109
+ },
1110
+ "bottom-left": {
1111
+ widthFactor: -1,
1112
+ heightFactor: 1,
1113
+ moveLocalX: (dx) => dx,
1114
+ moveLocalY: () => 0,
1115
+ },
1116
+ "top-left": {
1117
+ widthFactor: -1,
1118
+ heightFactor: -1,
1119
+ moveLocalX: (dx) => dx,
1120
+ moveLocalY: (_, dy) => dy,
1121
+ },
1122
+ "top-right": {
1123
+ widthFactor: 1,
1124
+ heightFactor: -1,
1125
+ moveLocalX: () => 0,
1126
+ moveLocalY: (_, dy) => dy,
1127
+ },
1128
+ left: {
1129
+ widthFactor: -1,
1130
+ heightFactor: 0,
1131
+ moveLocalX: (dx) => dx,
1132
+ moveLocalY: () => 0,
1133
+ },
1134
+ right: {
1135
+ widthFactor: 1,
1136
+ heightFactor: 0,
1137
+ moveLocalX: () => 0,
1138
+ moveLocalY: () => 0,
1139
+ },
1140
+ top: {
1141
+ widthFactor: 0,
1142
+ heightFactor: -1,
1143
+ moveLocalX: () => 0,
1144
+ moveLocalY: (_, dy) => dy,
1145
+ },
1146
+ bottom: {
1147
+ widthFactor: 0,
1148
+ heightFactor: 1,
1149
+ moveLocalX: () => 0,
1150
+ moveLocalY: () => 0,
1151
+ },
1152
+ };
1153
+ export function applyResizeWithRotation({ element, group, resizeSide, widthOriginal, heightOriginal, deltaLocalX, deltaLocalY, xOriginal, yOriginal, angle, seats, }) {
1154
+ const rule = RESIZE_RULES[resizeSide];
1155
+ let newWidth = widthOriginal;
1156
+ let newHeight = heightOriginal;
1157
+ if (rule.widthFactor !== 0) {
1158
+ newWidth = widthOriginal + rule.widthFactor * deltaLocalX;
1159
+ }
1160
+ if (rule.heightFactor !== 0) {
1161
+ newHeight = heightOriginal + rule.heightFactor * deltaLocalY;
1162
+ }
1163
+ // clamp
1164
+ newWidth = Math.max(0, newWidth);
1165
+ newHeight = Math.max(0, newHeight);
1166
+ // 🔹 apply size (rect / circle / ellipse)
1167
+ applySizeToSvgElement(element, newWidth, newHeight);
1168
+ // 🔹 move anchor (kalau perlu)
1169
+ const moveLocalX = rule.moveLocalX(deltaLocalX, deltaLocalY);
1170
+ const moveLocalY = rule.moveLocalY(deltaLocalX, deltaLocalY);
1171
+ if (moveLocalX !== 0 || moveLocalY !== 0) {
1172
+ const { x: mx, y: my } = localToWorld(moveLocalX, moveLocalY, angle);
1173
+ group.setAttribute("transform", `translate(${xOriginal + mx}, ${yOriginal + my})`);
1174
+ }
1175
+ }
1176
+ export function getRotation(transformList) {
1177
+ for (let i = 0; i < (transformList === null || transformList === void 0 ? void 0 : transformList.numberOfItems); i++) {
1178
+ const t = transformList.getItem(i);
1179
+ if (t.type === SVGTransform.SVG_TRANSFORM_ROTATE) {
1180
+ return t.angle;
1181
+ }
1182
+ }
1183
+ return 0;
1184
+ }
1185
+ function toLocal(x, y, cx, cy, angle) {
1186
+ const dx = x - cx;
1187
+ const dy = y - cy;
1188
+ const cos = Math.cos(-angle);
1189
+ const sin = Math.sin(-angle);
1190
+ return {
1191
+ x: dx * cos - dy * sin,
1192
+ y: dx * sin + dy * cos,
1193
+ };
1194
+ }
1195
+ function toGlobal(lx, ly, cx, cy, angle) {
1196
+ const cos = Math.cos(angle);
1197
+ const sin = Math.sin(angle);
1198
+ return {
1199
+ x: cx + lx * cos - ly * sin,
1200
+ y: cy + lx * sin + ly * cos,
1201
+ };
1202
+ }
1203
+ export const updateSelectionGuides = (svg, rect, ids, range = 10000) => {
1204
+ if (!svg)
1205
+ return;
1206
+ const { x, y, width, height } = rect;
1207
+ const cx = x + width / 2;
1208
+ const cy = y + height / 2;
1209
+ const v = (id, xPos) => {
1210
+ const line = svg.querySelector(`#${id}`);
1211
+ if (!line)
1212
+ return;
1213
+ line.setAttribute("x1", `${xPos}`);
1214
+ line.setAttribute("x2", `${xPos}`);
1215
+ line.setAttribute("y1", `${-range}`);
1216
+ line.setAttribute("y2", `${range}`);
1217
+ };
1218
+ const h = (id, yPos) => {
1219
+ const line = svg.querySelector(`#${id}`);
1220
+ if (!line)
1221
+ return;
1222
+ line.setAttribute("y1", `${yPos}`);
1223
+ line.setAttribute("y2", `${yPos}`);
1224
+ line.setAttribute("x1", `${-range}`);
1225
+ line.setAttribute("x2", `${range}`);
1226
+ };
1227
+ // vertical guides (dipakai top & bottom)
1228
+ v(ids.vLeft, x);
1229
+ v(ids.vCenter, cx);
1230
+ v(ids.vRight, x + width);
1231
+ // horizontal guides (dipakai left & right)
1232
+ h(ids.hTop, y);
1233
+ h(ids.hCenter, cy);
1234
+ h(ids.hBottom, y + height);
1235
+ };