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
@@ -0,0 +1,20 @@
1
+ import { EventHandleType } from "@/dto/event-handler";
2
+ import { PropertiesProps } from "@/dto/table";
3
+ import { TableMatchEvent } from "@/features/view-only-3";
4
+ interface LayersProps {
5
+ components?: PropertiesProps[];
6
+ selectedComponent?: PropertiesProps;
7
+ activeTool?: string;
8
+ onBlur?: () => void;
9
+ selectedTable?: PropertiesProps;
10
+ iconTags?: {
11
+ icon: React.JSX.Element;
12
+ key: string;
13
+ }[];
14
+ eventMatchTable?: TableMatchEvent[];
15
+ onHighlightGroup?: (group: SVGGElement, eventType: EventHandleType) => void;
16
+ onForceRestoreGroup?: (group: SVGGElement, eventType: EventHandleType) => void;
17
+ selectedTableColor?: string;
18
+ }
19
+ declare const Layers: ({ components, selectedTable, iconTags, eventMatchTable, onHighlightGroup, onForceRestoreGroup, selectedTableColor, }: LayersProps) => import("react/jsx-runtime").JSX.Element;
20
+ export default Layers;
@@ -0,0 +1,445 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { createElement as _createElement } from "react";
4
+ import { isEmpty, omit } from "lodash";
5
+ import { TABLE_KEYS } from "@/utils/constant";
6
+ import { distributeWithSpacing } from "../layer-v3";
7
+ const Layers = ({ components, selectedTable, iconTags, eventMatchTable, onHighlightGroup, onForceRestoreGroup, selectedTableColor, }) => {
8
+ const renderShape = (item) => {
9
+ var _a, _b, _c, _d, _e;
10
+ const { id, x, y, width, height, fill, opacity, rotate = 0, shape, text, stroke, strokeWidth, labels, fontSize, fontColor, seatFill, src, tags, gapTags, label, } = item;
11
+ const renderTags = (tags) => {
12
+ const gapBetweenTags = gapTags || 0;
13
+ const defaultFontSize = fontSize || 12;
14
+ // Hitung total tinggi semua grup tag (buat center vertikal)
15
+ const totalTagHeight = (tags === null || tags === void 0 ? void 0 : tags.reduce((sum, tag) => {
16
+ var _a;
17
+ const items = tag.items || [];
18
+ const isColumn = (_a = tag.direction) === null || _a === void 0 ? void 0 : _a.includes("column");
19
+ const tagHeight = isColumn
20
+ ? items.length * defaultFontSize +
21
+ (items.length - 1) * (Number(tag.gap) || 2)
22
+ : defaultFontSize; // horizontal = 1 line
23
+ return sum + tagHeight + gapBetweenTags;
24
+ }, 0)) - gapBetweenTags;
25
+ const startY = height / 2 - totalTagHeight / 2; // titik awal supaya semua di tengah
26
+ let currentY = startY;
27
+ return tags === null || tags === void 0 ? void 0 : tags.map((tag, tagIndex) => {
28
+ var _a;
29
+ const direction = ((_a = tag.direction) === null || _a === void 0 ? void 0 : _a.includes("column")) ? "column" : "flex";
30
+ const gap = Number(tag.gap) || 2;
31
+ const items = tag.items || [];
32
+ const fontSize = defaultFontSize;
33
+ const isColumn = direction === "column";
34
+ const groupHeight = isColumn
35
+ ? items.length * fontSize + (items.length - 1) * gap
36
+ : fontSize;
37
+ const centerX = width / 2;
38
+ const centerY = currentY + groupHeight / 2;
39
+ // naikkan posisi Y untuk grup berikutnya
40
+ currentY += groupHeight + gapBetweenTags;
41
+ // kumpulkan elemen yang akan dirender (bisa mix text + icon)
42
+ const elements = items.map((item, i) => {
43
+ var _a, _b;
44
+ const offsetY = isColumn
45
+ ? i * (fontSize + gap) - groupHeight / 2 + fontSize / 2
46
+ : 0;
47
+ const offsetX = !isColumn
48
+ ? i * (fontSize + gap) - ((items.length - 1) * (fontSize + gap)) / 2
49
+ : 0;
50
+ const posX = centerX + offsetX + ((_a = tag.offsetX) !== null && _a !== void 0 ? _a : 0);
51
+ const posY = centerY + offsetY + ((_b = tag.offsetY) !== null && _b !== void 0 ? _b : 0);
52
+ const renderSymbol = (symbol) => {
53
+ if (!symbol)
54
+ return null;
55
+ const { position = "right", size = (item === null || item === void 0 ? void 0 : item.fontSize) || 12, gap: symbolGap = 0, } = symbol;
56
+ let offsetSymbolX = 0;
57
+ let offsetSymbolY = 0;
58
+ switch (position) {
59
+ case "right":
60
+ offsetSymbolX = size + symbolGap;
61
+ break;
62
+ case "left":
63
+ offsetSymbolX = -(size + symbolGap);
64
+ break;
65
+ case "top":
66
+ offsetSymbolY = -(size + symbolGap);
67
+ break;
68
+ case "bottom":
69
+ offsetSymbolY = size + symbolGap;
70
+ break;
71
+ case "right-top":
72
+ offsetSymbolX = size + symbolGap;
73
+ offsetSymbolY = -(size / 4);
74
+ break;
75
+ case "right-bottom":
76
+ offsetSymbolX = size + symbolGap;
77
+ offsetSymbolY = size / 4;
78
+ break;
79
+ case "left-top":
80
+ offsetSymbolX = -size - symbolGap;
81
+ offsetSymbolY = -(size / 4);
82
+ break;
83
+ case "left-bottom":
84
+ offsetSymbolX = -size - symbolGap;
85
+ offsetSymbolY = size / 4;
86
+ break;
87
+ }
88
+ return (_createElement("tspan", Object.assign({}, symbol, { key: `symbol-${tagIndex}-${i}`, x: posX + offsetSymbolX, y: posY + offsetSymbolY, textAnchor: "middle", dominantBaseline: "middle", transform: `rotate(${rotate} ${posX} ${posY})` }), symbol.value));
89
+ };
90
+ if (item.type === "icon") {
91
+ const iconTag = iconTags === null || iconTags === void 0 ? void 0 : iconTags.find((icon) => icon.key === item.value);
92
+ if (!iconTag)
93
+ return null;
94
+ return (_createElement("g", Object.assign({}, item, { key: `icon-${tagIndex}-${i}`, transform: `translate(${posX - 10}, ${posY - 10})` }), iconTag.icon));
95
+ }
96
+ if (item.type === "text") {
97
+ return (_createElement("text", Object.assign({}, item, { key: `text-${tagIndex}-${i}`, x: posX, y: posY, textAnchor: "middle", dominantBaseline: "middle", transform: `rotate(${rotate} ${posX} ${posY})` }),
98
+ item.value,
99
+ " ",
100
+ renderSymbol(item === null || item === void 0 ? void 0 : item.symbol)));
101
+ }
102
+ return null;
103
+ });
104
+ return _jsx("g", { children: elements }, `group-${tagIndex}`);
105
+ });
106
+ };
107
+ let commonProps = {
108
+ fill,
109
+ opacity,
110
+ stroke,
111
+ strokeWidth,
112
+ };
113
+ const hasSelected = (selectedTable === null || selectedTable === void 0 ? void 0 : selectedTable.id) === id;
114
+ if (hasSelected) {
115
+ const eventSelectedStyles = eventMatchTable === null || eventMatchTable === void 0 ? void 0 : eventMatchTable.find((style) => style.event === "selected");
116
+ commonProps = Object.assign(Object.assign({}, commonProps), eventSelectedStyles === null || eventSelectedStyles === void 0 ? void 0 : eventSelectedStyles.properties);
117
+ }
118
+ // helper: highlight / unhighlight dengan enter-counter
119
+ let properties = {};
120
+ const highlightGroup = (group, eventType) => {
121
+ if (!group)
122
+ return;
123
+ onHighlightGroup === null || onHighlightGroup === void 0 ? void 0 : onHighlightGroup(group, eventType);
124
+ eventMatchTable === null || eventMatchTable === void 0 ? void 0 : eventMatchTable.forEach((styleConfig) => {
125
+ if (styleConfig.event === eventType) {
126
+ properties = styleConfig.properties;
127
+ }
128
+ });
129
+ if (isEmpty(properties))
130
+ return;
131
+ // counter
132
+ const count = Number(group.dataset.dragEnterCount || "0") + 1;
133
+ group.dataset.dragEnterCount = String(count);
134
+ // selalu ubah warna, tapi simpan original hanya sekali
135
+ ["rect", "circle"].forEach((selector) => {
136
+ const el = group.querySelector(selector);
137
+ if (!el)
138
+ return;
139
+ Object.entries(properties).forEach(([key]) => {
140
+ el.dataset[key] = el.getAttribute(key) || "";
141
+ });
142
+ Object.entries(properties).forEach(([key, value]) => {
143
+ el.setAttribute(key, value);
144
+ });
145
+ });
146
+ };
147
+ const unhighlightGroup = (group) => {
148
+ if (!group)
149
+ return;
150
+ const count = Math.max(0, Number(group.dataset.dragEnterCount || "0") - 1);
151
+ group.dataset.dragEnterCount = String(count);
152
+ // restore hanya saat counter = 0
153
+ if (count === 0) {
154
+ ["rect", "circle"].forEach((selector) => {
155
+ const el = group.querySelector(selector);
156
+ if (!el)
157
+ return;
158
+ // bersihkan data
159
+ const dataset = el.dataset;
160
+ Object.entries(dataset).forEach(([key, value]) => {
161
+ el.setAttribute(key, value);
162
+ delete el.dataset[key];
163
+ properties = {};
164
+ });
165
+ });
166
+ delete group.dataset.dragEnterCount;
167
+ }
168
+ };
169
+ const forceRestoreGroup = (group, type) => {
170
+ // langsung restore (dipanggil pada drop)
171
+ onForceRestoreGroup === null || onForceRestoreGroup === void 0 ? void 0 : onForceRestoreGroup(group, type);
172
+ ["rect", "circle"].forEach((selector) => {
173
+ const el = group === null || group === void 0 ? void 0 : group.querySelector(selector);
174
+ if (!el)
175
+ return;
176
+ const dataset = el.dataset;
177
+ Object.entries(dataset).forEach(([key, value]) => {
178
+ el.setAttribute(key, value);
179
+ delete el.dataset[key];
180
+ properties = {};
181
+ });
182
+ });
183
+ delete group.dataset.dragEnterCount;
184
+ };
185
+ const transformRotate = `rotate(${rotate} ${x + width / 2} ${y + height / 2})`;
186
+ switch (shape) {
187
+ case "square":
188
+ return (_jsxs("g", { "data-id": id, style: { pointerEvents: "all" }, onContextMenu: (e) => e.preventDefault(), onDragEnter: (e) => {
189
+ const group = e.currentTarget;
190
+ highlightGroup(group, "dragenter");
191
+ }, onDragOver: (e) => {
192
+ e.preventDefault(); // agar drop diterima
193
+ }, onDragLeave: (e) => {
194
+ const group = e.currentTarget;
195
+ unhighlightGroup(group);
196
+ }, onDrop: (e) => {
197
+ const group = e.currentTarget;
198
+ // restore langsung dan reset
199
+ forceRestoreGroup(group, "drop");
200
+ }, onPointerOver: (e) => {
201
+ // e.preventDefault(); // penting
202
+ const group = e.currentTarget;
203
+ highlightGroup(group, "pointerover");
204
+ }, onPointerOut: (e) => {
205
+ const group = e.currentTarget;
206
+ unhighlightGroup(group);
207
+ }, onPointerUp: (e) => {
208
+ const group = e.currentTarget;
209
+ // restore langsung dan reset
210
+ forceRestoreGroup(group, "pointerup");
211
+ }, onPointerDown: (e) => {
212
+ const group = e.currentTarget;
213
+ highlightGroup(group, "pointerdown");
214
+ },
215
+ // onPointerEnter={(e) => {
216
+ // const group = e.currentTarget as SVGGElement;
217
+ // highlightGroup(group, "pointerenter");
218
+ // }}
219
+ onPointerLeave: (e) => {
220
+ const group = e.currentTarget;
221
+ unhighlightGroup(group);
222
+ }, onMouseEnter: (e) => {
223
+ // e.preventDefault(); // penting
224
+ const group = e.currentTarget;
225
+ highlightGroup(group, "mouseenter");
226
+ }, onMouseLeave: (e) => {
227
+ const group = e.currentTarget;
228
+ unhighlightGroup(group);
229
+ }, children: [_jsx("rect", Object.assign({ x: x, y: y, width: width, height: height, fill: fill, className: "blink-2", transform: transformRotate }, omit(item, TABLE_KEYS), commonProps), `${id}-rect`), renderTags(tags), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
230
+ var _a, _b, _c, _d;
231
+ return (_createElement("text", Object.assign({}, omit(commonProps, ["opacity", "stroke", "strokeWidth"]), { key: `${id}-label-${index}`, x: x + width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0), y: y + height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0), fill: (_c = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _c !== void 0 ? _c : "black", fontSize: `${(_d = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _d !== void 0 ? _d : 10}px`, fontWeight: "bold", textAnchor: "middle", dominantBaseline: "middle", transform: transformRotate }, _), _ === null || _ === void 0 ? void 0 : _.label));
232
+ })] }, id));
233
+ case "circle":
234
+ return (_jsxs("g", { style: { pointerEvents: "all" }, "data-id": id, onContextMenu: (e) => e.preventDefault(), onDragEnter: (e) => {
235
+ e.preventDefault(); // penting
236
+ const group = e.currentTarget;
237
+ highlightGroup(group, "dragenter");
238
+ }, onDragOver: (e) => {
239
+ e.preventDefault(); // agar drop diterima
240
+ }, onDragLeave: (e) => {
241
+ const group = e.currentTarget;
242
+ unhighlightGroup(group);
243
+ }, onDrop: (e) => {
244
+ e.preventDefault();
245
+ const group = e.currentTarget;
246
+ // restore langsung dan reset
247
+ forceRestoreGroup(group);
248
+ }, onPointerOver: (e) => {
249
+ e.preventDefault(); // penting
250
+ const group = e.currentTarget;
251
+ highlightGroup(group, "pointerover");
252
+ }, onPointerOut: (e) => {
253
+ const group = e.currentTarget;
254
+ unhighlightGroup(group);
255
+ }, onPointerUp: (e) => {
256
+ e.preventDefault();
257
+ const group = e.currentTarget;
258
+ // restore langsung dan reset
259
+ forceRestoreGroup(group);
260
+ }, onMouseDown: (e) => {
261
+ e.preventDefault();
262
+ const group = e.currentTarget;
263
+ highlightGroup(group, "mousedown");
264
+ }, onMouseEnter: (e) => {
265
+ // e.preventDefault(); // penting
266
+ const group = e.currentTarget;
267
+ highlightGroup(group, "mouseenter");
268
+ }, onMouseLeave: (e) => {
269
+ const group = e.currentTarget;
270
+ unhighlightGroup(group);
271
+ }, children: [_jsx("circle", Object.assign({ cx: x + width / 2, cy: y + height / 2, r: width / 2 }, commonProps), id), renderTags(tags), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
272
+ var _a, _b, _c, _d;
273
+ return (_jsx("text", { x: x + width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0), y: y + height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0), fill: (_c = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _c !== void 0 ? _c : "black", fontSize: `${(_d = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _d !== void 0 ? _d : 10}px`, fontWeight: "bold", textAnchor: "middle", dominantBaseline: "middle", transform: transformRotate, children: _ === null || _ === void 0 ? void 0 : _.label }, `${id}-label-${index}`));
274
+ })] }, id));
275
+ case "table-seat-circle": {
276
+ const seatCount = item.seatCount;
277
+ const openSpace = (_a = item.openSpace) !== null && _a !== void 0 ? _a : 0;
278
+ // LOCAL SPACE (tanpa x,y)
279
+ const centerX = width / 2;
280
+ const centerY = height / 2;
281
+ // meja
282
+ const tableRadius = Math.min(width, height) / 2;
283
+ // seat statis
284
+ const seatRadius = 10;
285
+ const fullAngle = Math.PI * 2;
286
+ const availableAngle = fullAngle * (1 - openSpace);
287
+ const angleStart = (fullAngle - availableAngle) / 2;
288
+ const angleStep = availableAngle / seatCount;
289
+ const seatCircles = Array.from({ length: seatCount }, (_, i) => {
290
+ const angle = angleStart + i * angleStep;
291
+ const cx = centerX + (tableRadius + seatRadius) * Math.cos(angle);
292
+ const cy = centerY + (tableRadius + seatRadius) * Math.sin(angle);
293
+ return { cx, cy };
294
+ });
295
+ return (_jsxs("g", { style: { pointerEvents: "all" }, "data-id": id, transform: `translate(${x}, ${y})`,
296
+ // data-table={JSON.stringify(item)}
297
+ // data-id={id}
298
+ onContextMenu: (e) => e.preventDefault(), onDragEnter: (e) => {
299
+ e.preventDefault(); // penting
300
+ const group = e.currentTarget;
301
+ highlightGroup(group, "dragenter");
302
+ }, onDragOver: (e) => {
303
+ e.preventDefault(); // agar drop diterima
304
+ }, onDragLeave: (e) => {
305
+ const group = e.currentTarget;
306
+ unhighlightGroup(group);
307
+ }, onDrop: (e) => {
308
+ e.preventDefault();
309
+ const group = e.currentTarget;
310
+ // restore langsung dan reset
311
+ forceRestoreGroup(group);
312
+ }, onPointerOver: (e) => {
313
+ e.preventDefault(); // penting
314
+ const group = e.currentTarget;
315
+ highlightGroup(group, "pointerover");
316
+ }, onPointerOut: (e) => {
317
+ const group = e.currentTarget;
318
+ unhighlightGroup(group);
319
+ }, onPointerUp: (e) => {
320
+ e.preventDefault();
321
+ const group = e.currentTarget;
322
+ // restore langsung dan reset
323
+ forceRestoreGroup(group);
324
+ }, onMouseDown: (e) => {
325
+ e.preventDefault();
326
+ const group = e.currentTarget;
327
+ highlightGroup(group, "mousedown");
328
+ }, onMouseEnter: (e) => {
329
+ // e.preventDefault(); // penting
330
+ const group = e.currentTarget;
331
+ highlightGroup(group, "mouseenter");
332
+ }, onMouseLeave: (e) => {
333
+ const group = e.currentTarget;
334
+ unhighlightGroup(group);
335
+ }, children: [_jsx("circle", Object.assign({ cx: centerX, cy: centerY, r: tableRadius, fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill }, commonProps)), _jsx("g", { "data-seat": `${id}-seats`, children: seatCircles.map(({ cx, cy }, i) => (_jsx("circle", { cx: cx, cy: cy, r: seatRadius, fill: seatFill || "white" }, `${id}-seat-${i}`))) }), renderTags(tags), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
336
+ var _a, _b, _c, _d;
337
+ return (_jsx("text", { x: x + width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0), y: y + height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0), fill: (_c = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _c !== void 0 ? _c : "black", fontSize: `${(_d = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _d !== void 0 ? _d : 10}px`, fontWeight: "bold", textAnchor: "middle", dominantBaseline: "middle", transform: transformRotate, children: _ === null || _ === void 0 ? void 0 : _.label }, `${id}-label-${index}`));
338
+ })] }, id));
339
+ }
340
+ case "table-seat-square": {
341
+ const openSpace = item.openSpace || 0; // from 0 to 0.9
342
+ const r = 10;
343
+ const seatPositions = item.seatPositions;
344
+ const topCount = (_b = seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.top) !== null && _b !== void 0 ? _b : 0;
345
+ const bottomCount = (_c = seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.bottom) !== null && _c !== void 0 ? _c : 0;
346
+ const leftCount = (_d = seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.left) !== null && _d !== void 0 ? _d : 0;
347
+ const rightCount = (_e = seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.right) !== null && _e !== void 0 ? _e : 0;
348
+ // split seats evenly on top and bottom
349
+ const seatCountTopBottom = Math.ceil(Math.max(topCount, bottomCount) / 2);
350
+ const seatCountLeftRight = Math.ceil(Math.max(leftCount, rightCount) / 2);
351
+ const availableWidth = width * (1 - openSpace);
352
+ const availableHeight = height * (1 - openSpace);
353
+ const spacingWidth = availableWidth / seatCountTopBottom;
354
+ const spacingHeight = availableHeight / seatCountLeftRight;
355
+ const topXs = distributeWithSpacing({
356
+ start: x,
357
+ length: width,
358
+ count: topCount,
359
+ radius: r,
360
+ spacing: spacingWidth,
361
+ });
362
+ const topSeats = topXs.map((cx) => ({ cx, cy: y - r, id: "top" }));
363
+ // TOP
364
+ const bottomSeats = distributeWithSpacing({
365
+ start: x,
366
+ length: width,
367
+ count: bottomCount,
368
+ radius: r,
369
+ spacing: spacingWidth,
370
+ }).map((cx) => ({
371
+ cx: cx,
372
+ cy: y + height + r,
373
+ id: "bottom",
374
+ }));
375
+ const leftYs = distributeWithSpacing({
376
+ start: y,
377
+ length: height,
378
+ count: leftCount,
379
+ radius: r,
380
+ spacing: spacingHeight,
381
+ });
382
+ const leftSeats = leftYs.map((cy) => ({ cx: x - r, cy, id: "left" }));
383
+ const rightSeats = distributeWithSpacing({
384
+ start: y,
385
+ length: height,
386
+ count: rightCount,
387
+ radius: r,
388
+ spacing: spacingHeight,
389
+ }).map((cy) => ({
390
+ cx: x + width + r,
391
+ cy,
392
+ id: "right",
393
+ }));
394
+ return (_jsx("g", { "data-id": id, transform: `translate(${x}, ${y})`, children: _jsxs("g", { transform: `rotate(${rotate}, 0, 0)`, children: [_jsx("rect", Object.assign({ width: width, height: height }, commonProps, { fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill })), renderTags(tags), _jsx("g", { fill: "#e6b9c0", stroke: "#c49ba3", strokeWidth: "1", "data-seat": `${id}-seats`, transform: `translate(${-x}, ${-y})`, children: [...topSeats, ...bottomSeats, ...leftSeats, ...rightSeats].map(({ cx, cy, id }, i) => (_jsx("circle", { id: `seat-${id}`, cx: cx, cy: cy, r: r, fill: seatFill }, `${id}-seat-${i}`))) }, `${id}-seats`), _jsx("text", { x: x + width / 2, y: y + height / 2, fill: fontColor !== null && fontColor !== void 0 ? fontColor : "black", fontSize: `${fontSize !== null && fontSize !== void 0 ? fontSize : 10}px`, fontWeight: "bold", textAnchor: "middle", dominantBaseline: "middle", children: label })] }) }, id));
395
+ }
396
+ case "text":
397
+ return (_jsxs("g", { onContextMenu: (e) => e.preventDefault(), children: [_jsx("rect", { x: x, y: y, width: width, height: height, fill: "transparent", opacity: opacity }), _jsx("text", Object.assign({ x: x + width / 2, y: y + height / 2, textAnchor: "middle", dominantBaseline: "middle", fill: fontColor, fontSize: fontSize !== null && fontSize !== void 0 ? fontSize : height * 0.6, opacity: opacity }, omit(commonProps, ["fill", "opacity"]), { children: text }))] }, id));
398
+ case "image-table":
399
+ return (_jsxs("g", { onContextMenu: (e) => e.preventDefault(), onDragEnter: (e) => {
400
+ e.preventDefault(); // penting
401
+ const group = e.currentTarget;
402
+ highlightGroup(group, "dragenter");
403
+ }, onDragOver: (e) => {
404
+ e.preventDefault(); // agar drop diterima
405
+ }, onDragLeave: (e) => {
406
+ const group = e.currentTarget;
407
+ unhighlightGroup(group);
408
+ }, onDrop: (e) => {
409
+ e.preventDefault();
410
+ const group = e.currentTarget;
411
+ // restore langsung dan reset
412
+ forceRestoreGroup(group);
413
+ }, onPointerOver: (e) => {
414
+ e.preventDefault(); // penting
415
+ const group = e.currentTarget;
416
+ highlightGroup(group, "pointerover");
417
+ }, onPointerOut: (e) => {
418
+ const group = e.currentTarget;
419
+ unhighlightGroup(group);
420
+ }, onPointerUp: (e) => {
421
+ e.preventDefault();
422
+ const group = e.currentTarget;
423
+ // restore langsung dan reset
424
+ forceRestoreGroup(group);
425
+ }, onMouseDown: (e) => {
426
+ e.preventDefault();
427
+ const group = e.currentTarget;
428
+ highlightGroup(group, "mousedown");
429
+ }, children: [_jsx("image", Object.assign({ href: src, x: x, y: y, "data-id": id, width: width, height: height, transform: transformRotate }, commonProps)), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
430
+ var _a, _b, _c, _d;
431
+ return (_jsx("text", { x: x + width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0), y: y + height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0), fill: (_c = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _c !== void 0 ? _c : "black", fontSize: `${(_d = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _d !== void 0 ? _d : 10}px`, fontWeight: "bold", textAnchor: "middle", dominantBaseline: "middle", transform: transformRotate, children: _ === null || _ === void 0 ? void 0 : _.label }, index));
432
+ })] }, id));
433
+ case "background":
434
+ return (_jsxs("g", { onContextMenu: (e) => e.preventDefault(), children: [_jsx("image", Object.assign({ href: src, x: x, y: y, width: width, height: height, transform: transformRotate }, commonProps)), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
435
+ var _a, _b, _c, _d;
436
+ return (_jsx("text", { x: x + width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0), y: y + height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0), fill: (_c = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _c !== void 0 ? _c : "black", fontSize: `${(_d = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _d !== void 0 ? _d : 10}px`, fontWeight: "bold", textAnchor: "middle", dominantBaseline: "middle", transform: transformRotate, children: _ === null || _ === void 0 ? void 0 : _.label }, index));
437
+ })] }, id));
438
+ default:
439
+ return _jsx("g", {}, id);
440
+ }
441
+ };
442
+ let date = new Date();
443
+ return _jsx("g", { children: components === null || components === void 0 ? void 0 : components.map(renderShape) }, `${date}`);
444
+ };
445
+ export default Layers;
@@ -1,4 +1,4 @@
1
- import LayerView from "../../features/view";
1
+ import LayerView from "../../features/view-only";
2
2
  export interface LayerViewProps {
3
3
  componentProps: any[];
4
4
  extraComponentProps: any[];
@@ -4,7 +4,7 @@ import { useEffect } from "react";
4
4
  import Board from "../../features/board";
5
5
  import SideTool from "../../features/side-tool";
6
6
  import ControlPanels from "../../features/panel";
7
- import LayerView from "../../features/view";
7
+ import LayerView from "../../features/view-only";
8
8
  import { useAppDispatch } from "../../hooks/use-redux";
9
9
  const TableEditor = ({ componentProps = [], extraComponentProps = [], }) => {
10
10
  const dispatch = useAppDispatch();
@@ -6,7 +6,7 @@ import { useAppSelector, useAppDispatch } from "../../hooks/use-redux";
6
6
  import Layers from "../../components/layer";
7
7
  import { throttle } from "lodash";
8
8
  import ModalPreview from "../../components/modal-preview";
9
- import LayerView from "../view";
9
+ import LayerView from "../view-only";
10
10
  import { isEqual, debounce } from "lodash";
11
11
  import { ZoomIn, ZoomOut } from "lucide-react";
12
12
  import { Button } from "antd";
@@ -6,7 +6,7 @@ import { useAppSelector, useAppDispatch } from "../../hooks/use-redux";
6
6
  import Layers from "../../components/layer-v2";
7
7
  import { 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";
@@ -10,6 +10,7 @@ export interface InitialState {
10
10
  flagChange: boolean;
11
11
  historyChanges: any[];
12
12
  pointer: number;
13
+ updateBy: "global" | "local";
13
14
  }
14
15
  export declare const addComponent: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "board/addComponent">, removeComponent: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "board/removeComponent">, updateComponent: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "board/updateComponent">, setBackgroundColor: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "board/setBackgroundColor">, removeExtraComponent: import("@reduxjs/toolkit").ActionCreatorWithPayload<any, "board/removeExtraComponent">;
15
16
  declare const _default: import("redux").Reducer<InitialState>;
@@ -6,13 +6,17 @@ const initialState = {
6
6
  extraComponents: [],
7
7
  flagChange: false,
8
8
  historyChanges: [],
9
- pointer: 0
9
+ pointer: 0,
10
+ updateBy: "global",
10
11
  };
11
12
  const MAX_HISTORY_CHANGES = 20;
12
13
  const boardSlice = createSlice({
13
14
  name: "board",
14
15
  initialState,
15
16
  reducers: {
17
+ setUpdateBy: (state, action) => {
18
+ state.updateBy = action.payload;
19
+ },
16
20
  addComponent: (state, action) => {
17
21
  state.components.push(action.payload);
18
22
  },
@@ -39,10 +43,23 @@ const boardSlice = createSlice({
39
43
  state.extraComponents[indexExtra] = Object.assign(Object.assign({}, state.extraComponents[indexExtra]), action.payload);
40
44
  }
41
45
  },
46
+ updateAllComponents: (state, action) => {
47
+ [...state.components, ...state.extraComponents].forEach((component) => {
48
+ const updatedComponent = action.payload.find((comp) => comp.id === component.id);
49
+ if (updatedComponent) {
50
+ Object.assign(component, Object.assign(Object.assign({}, component), updatedComponent));
51
+ }
52
+ });
53
+ },
42
54
  setBackgroundColor: (state, action) => {
43
55
  state.backgroundColor = action.payload;
44
56
  },
45
57
  setNewComponents: (state, action) => {
58
+ const currentPointer = state.pointer;
59
+ const totalHistory = state.historyChanges.length;
60
+ if (currentPointer < totalHistory) {
61
+ state.historyChanges = state.historyChanges.slice(0, currentPointer + 1);
62
+ }
46
63
  state.components = action.payload;
47
64
  state.historyChanges.push(state.components);
48
65
  if (state.historyChanges.length > MAX_HISTORY_CHANGES) {
@@ -61,8 +78,14 @@ const boardSlice = createSlice({
61
78
  },
62
79
  undoHistory: (state) => {
63
80
  if (state.pointer > 1) {
64
- state.pointer -= 1;
65
- const prev = state.historyChanges[state.pointer - 1];
81
+ const lengthHistory = state.historyChanges.length;
82
+ if (lengthHistory === state.pointer) {
83
+ state.pointer = lengthHistory - 2;
84
+ }
85
+ else {
86
+ state.pointer -= 1;
87
+ }
88
+ const prev = state.historyChanges[state.pointer];
66
89
  state.components = current(prev);
67
90
  }
68
91
  else if (state.pointer === 1) {
@@ -0,0 +1,5 @@
1
+ declare const MIN_HEIGHT = 10;
2
+ declare const MIN_WIDTH = 10;
3
+ declare const MIN_X = 10;
4
+ declare const MIN_Y = 10;
5
+ export { MIN_HEIGHT, MIN_WIDTH, MIN_X, MIN_Y };
@@ -0,0 +1,5 @@
1
+ const MIN_HEIGHT = 10;
2
+ const MIN_WIDTH = 10;
3
+ const MIN_X = 10;
4
+ const MIN_Y = 10;
5
+ export { MIN_HEIGHT, MIN_WIDTH, MIN_X, MIN_Y };
@@ -0,0 +1,47 @@
1
+ interface BoardTemplateProps {
2
+ onSelectComponent?: (items: any) => void;
3
+ mappingKey?: string;
4
+ viewOnly?: boolean;
5
+ }
6
+ declare const BoardTemplate: ({ onSelectComponent, viewOnly }: BoardTemplateProps) => import("react/jsx-runtime").JSX.Element;
7
+ export default BoardTemplate;
8
+ export declare function getTranslate(el: any): {
9
+ x: number;
10
+ y: number;
11
+ };
12
+ export declare function getSize(el: any): {
13
+ width: any;
14
+ height: any;
15
+ };
16
+ type ResizeSide = string;
17
+ export declare function getPolygonCenter(points: Pt[]): {
18
+ cx: number;
19
+ cy: number;
20
+ };
21
+ type Pt = {
22
+ x: number;
23
+ y: number;
24
+ };
25
+ type ResizeResult = {
26
+ x: number;
27
+ y: number;
28
+ width: number;
29
+ height: number;
30
+ cx: number;
31
+ cy: number;
32
+ };
33
+ export declare function applyResizeToSvgElement(element: SVGGraphicsElement, group: SVGGElement, resize: ResizeResult, inner: any): void;
34
+ type ResizeParams = {
35
+ element: SVGGraphicsElement;
36
+ group: SVGGElement;
37
+ resizeSide: ResizeSide;
38
+ widthOriginal: number;
39
+ heightOriginal: number;
40
+ deltaLocalX: number;
41
+ deltaLocalY: number;
42
+ xOriginal: number;
43
+ yOriginal: number;
44
+ angle: number;
45
+ seats?: any;
46
+ };
47
+ export declare function applyResizeWithRotation({ element, group, resizeSide, widthOriginal, heightOriginal, deltaLocalX, deltaLocalY, xOriginal, yOriginal, angle, seats, }: ResizeParams): void;