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,1046 @@
1
+ "use client";
2
+ import { isEmpty, omit } from "lodash";
3
+ import { arcByDirection, distributeWithSpacing } from "../layer-v3/utils";
4
+ import { PRIVILEGED_TAGS, tagsDummy } from "./constant";
5
+ import { useAppSelector } from "../../hooks/use-redux";
6
+ import { RsvpIcons } from "../../features/board-v3/icons";
7
+ const toKebabCase = (str) => str.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase());
8
+ const iconNames = [
9
+ "upcoming",
10
+ "late",
11
+ "overtime",
12
+ "overlapping",
13
+ "hold",
14
+ "reserved",
15
+ "armchair",
16
+ "cheque",
17
+ "people",
18
+ ];
19
+ const dummyIconTags = iconNames === null || iconNames === void 0 ? void 0 : iconNames.map((item) => {
20
+ const Icon = RsvpIcons === null || RsvpIcons === void 0 ? void 0 : RsvpIcons[item];
21
+ return {
22
+ key: item,
23
+ icon: <Icon />,
24
+ };
25
+ });
26
+ const getIconFromId = (data) => {
27
+ const id = String(data);
28
+ let hash = 0;
29
+ for (let i = 0; i < id.length; i++) {
30
+ hash += id.charCodeAt(i);
31
+ }
32
+ return iconNames[hash % iconNames.length];
33
+ };
34
+ const Layers = ({ components, selectedTable, iconTags, eventMatchTable, onHighlightGroup, onForceRestoreGroup, selectedTableColor, privilegedTags = [], }) => {
35
+ const { isShowTagType } = useAppSelector((state) => state.board);
36
+ const showLabels = !["type-1", "type-2"].includes(isShowTagType) && !iconTags;
37
+ const renderShape = (item) => {
38
+ var _a, _b, _c, _d, _e, _f;
39
+ const { id, x, y, width, height, fill, opacity, rotate = 0, rotation, shape, text, stroke, strokeWidth, labels, fontSize, fontColor, seatFill, src, tags, gapTags, label, points, seatPositions, radius, } = item;
40
+ const renderTags = (data) => {
41
+ var _a;
42
+ const tags = data !== null && data !== void 0 ? data : tagsDummy(((_a = labels === null || labels === void 0 ? void 0 : labels[0]) === null || _a === void 0 ? void 0 : _a.label) || "Table", getIconFromId(id));
43
+ const privileged = !isEmpty(privilegedTags)
44
+ ? privilegedTags
45
+ : isShowTagType === "type-1"
46
+ ? PRIVILEGED_TAGS["CURRENT_TIME"]
47
+ : isShowTagType === "type-2"
48
+ ? PRIVILEGED_TAGS["NEXT_3_RESERVATION"]
49
+ : undefined;
50
+ if (tags && (tags === null || tags === void 0 ? void 0 : tags.length) > 0) {
51
+ const gapBetweenTags = Number(gapTags || 20);
52
+ const defaultFontSize = Number(fontSize || 12);
53
+ // Hitung total tinggi semua grup tag (buat center vertikal)
54
+ const totalTagHeight = (tags === null || tags === void 0 ? void 0 : tags.filter((tag) => privileged === null || privileged === void 0 ? void 0 : privileged.find((p) => p.key === tag.key)).reduce((sum, tag) => {
55
+ var _a;
56
+ const items = tag.items || [];
57
+ const isColumn = (_a = tag.direction) === null || _a === void 0 ? void 0 : _a.includes("column");
58
+ const tagHeight = isColumn
59
+ ? items.length * defaultFontSize + 2 * (Number(tag.gap) || 2)
60
+ : defaultFontSize; // horizontal = 1 line
61
+ return sum + tagHeight + gapBetweenTags;
62
+ }, 0)) - gapBetweenTags;
63
+ const startY = Number(height) / 4 - totalTagHeight / 3; // titik awal supaya semua di tengah
64
+ let currentY = startY;
65
+ return tags
66
+ .filter((tag) => privileged === null || privileged === void 0 ? void 0 : privileged.find((p) => p.key === tag.key))
67
+ .map((tag, tagIndex) => {
68
+ var _a;
69
+ const itemsPriv = privileged[tagIndex].items;
70
+ const direction = ((_a = tag.direction) === null || _a === void 0 ? void 0 : _a.includes("column"))
71
+ ? "column"
72
+ : "flex";
73
+ const gap = Number(tag.gap || 2);
74
+ const items = tag.items || [];
75
+ const fontSize = Number(defaultFontSize);
76
+ const isColumn = direction === "column";
77
+ const groupHeight = isColumn
78
+ ? items.length * fontSize + 2 * gap
79
+ : fontSize;
80
+ const centerX = width / 2;
81
+ const centerY = currentY + groupHeight;
82
+ // naikkan posisi Y untuk grup berikutnya
83
+ currentY += groupHeight + gapBetweenTags;
84
+ const elements = items
85
+ .filter((item) => itemsPriv.includes(item.type))
86
+ .map((item, i) => {
87
+ var _a, _b;
88
+ const offsetY = isColumn
89
+ ? i * (fontSize + gap) - groupHeight / 2 + fontSize / 2
90
+ : 0;
91
+ const offsetX = !isColumn
92
+ ? i * (fontSize + gap) - (1 * (fontSize + gap)) / 2
93
+ : 0;
94
+ const posX = centerX + offsetX + Number((_a = tag.offsetX) !== null && _a !== void 0 ? _a : 0);
95
+ const posY = centerY + offsetY + Number((_b = tag.offsetY) !== null && _b !== void 0 ? _b : 0);
96
+ const renderSymbol = (symbol) => {
97
+ if (!symbol)
98
+ return null;
99
+ const { position = "right", size = (item === null || item === void 0 ? void 0 : item.fontSize) || Number(fontSize), gap: symbolGap = 0, } = symbol;
100
+ const sizeFont = (item === null || item === void 0 ? void 0 : item.fontSize) || Number(fontSize) / 3;
101
+ let offsetSymbolX = 0;
102
+ let offsetSymbolY = 0;
103
+ switch (position) {
104
+ case "right":
105
+ offsetSymbolX = size + symbolGap;
106
+ break;
107
+ case "left":
108
+ offsetSymbolX = -(size + symbolGap);
109
+ break;
110
+ case "top":
111
+ offsetSymbolY = -(size + symbolGap);
112
+ break;
113
+ case "bottom":
114
+ offsetSymbolY = size + symbolGap;
115
+ break;
116
+ case "right-top":
117
+ offsetSymbolX = size + symbolGap;
118
+ offsetSymbolY = -(size / 4);
119
+ break;
120
+ case "right-bottom":
121
+ offsetSymbolX = size + symbolGap;
122
+ offsetSymbolY = size / 4;
123
+ break;
124
+ case "left-top":
125
+ offsetSymbolX = -size - symbolGap;
126
+ offsetSymbolY = -(size / 4);
127
+ break;
128
+ case "left-bottom":
129
+ offsetSymbolX = -size - symbolGap;
130
+ offsetSymbolY = size / 4;
131
+ break;
132
+ }
133
+ return (<tspan {...symbol} key={`symbol-${tagIndex}-${i}`} x={posX + offsetSymbolX} y={posY + offsetSymbolY} textAnchor="middle" dominantBaseline="middle" fontSize={`${sizeFont}px`}>
134
+ {symbol.value}
135
+ </tspan>);
136
+ };
137
+ if (item.type === "icon") {
138
+ const icons = iconTags !== null && iconTags !== void 0 ? iconTags : dummyIconTags;
139
+ const iconTag = icons === null || icons === void 0 ? void 0 : icons.find((icon) => icon.key === item.value);
140
+ if (!iconTag)
141
+ return null;
142
+ return (<g {...item} key={`icon-${tagIndex}-${i}`} transform={`translate(${posX - 10}, ${posY - 10})`}>
143
+ {iconTag.icon}
144
+ </g>);
145
+ }
146
+ if (item.type === "text") {
147
+ return (<text {...item} key={`text-${tagIndex}-${i}`} x={posX} y={posY} textAnchor="middle" dominantBaseline="middle" fontSize={(Number(defaultFontSize) * 3) / 4}>
148
+ {item.value} {renderSymbol(item === null || item === void 0 ? void 0 : item.symbol)}
149
+ </text>);
150
+ }
151
+ return null;
152
+ });
153
+ return (<g key={`group-${tagIndex}`} pointerEvents="none">
154
+ {elements}
155
+ </g>);
156
+ });
157
+ }
158
+ };
159
+ let commonProps = {
160
+ fill,
161
+ opacity,
162
+ stroke,
163
+ strokeWidth,
164
+ };
165
+ const hasSelected = (selectedTable === null || selectedTable === void 0 ? void 0 : selectedTable.id) === id;
166
+ if (hasSelected) {
167
+ const eventSelectedStyles = eventMatchTable === null || eventMatchTable === void 0 ? void 0 : eventMatchTable.find((style) => style.event === "selected");
168
+ commonProps = Object.assign(Object.assign({}, commonProps), eventSelectedStyles === null || eventSelectedStyles === void 0 ? void 0 : eventSelectedStyles.properties);
169
+ }
170
+ // helper: highlight / unhighlight dengan enter-counter
171
+ let properties = {};
172
+ const highlightGroup = (group, eventType) => {
173
+ if (!group)
174
+ return;
175
+ onHighlightGroup === null || onHighlightGroup === void 0 ? void 0 : onHighlightGroup(group, eventType);
176
+ eventMatchTable === null || eventMatchTable === void 0 ? void 0 : eventMatchTable.forEach((styleConfig) => {
177
+ if (styleConfig.event === eventType) {
178
+ properties = omit(styleConfig.properties || {}, "points");
179
+ const hasStroke = (properties === null || properties === void 0 ? void 0 : properties.stroke) || (commonProps === null || commonProps === void 0 ? void 0 : commonProps.stroke);
180
+ const hasStrokeWidth = properties === null || properties === void 0 ? void 0 : properties.strokeWidth;
181
+ if (hasStrokeWidth && !hasStroke) {
182
+ properties.stroke = "#E1E3EA";
183
+ }
184
+ }
185
+ });
186
+ if (isEmpty(properties))
187
+ return;
188
+ // counter
189
+ const count = Number(group.dataset.dragEnterCount || "0") + 1;
190
+ group.dataset.dragEnterCount = String(count);
191
+ // selalu ubah warna, tapi simpan original hanya sekali
192
+ ["rect", "circle"].forEach((selector) => {
193
+ const el = group.querySelector(selector);
194
+ if (!el)
195
+ return;
196
+ Object.entries(properties).forEach(([key]) => {
197
+ el.dataset[key] = el.getAttribute(key) || "";
198
+ });
199
+ Object.entries(properties).forEach(([key, value]) => {
200
+ el.setAttribute(toKebabCase(key), value);
201
+ });
202
+ });
203
+ };
204
+ const unhighlightGroup = (group) => {
205
+ if (!group)
206
+ return;
207
+ const count = Math.max(0, Number(group.dataset.dragEnterCount || "0") - 1);
208
+ group.dataset.dragEnterCount = String(count);
209
+ // restore hanya saat counter = 0
210
+ if (count === 0) {
211
+ ["rect", "circle"].forEach((selector) => {
212
+ const el = group.querySelector(selector);
213
+ if (!el)
214
+ return;
215
+ // bersihkan data
216
+ const dataset = el.dataset;
217
+ Object.entries(dataset).forEach(([key, value]) => {
218
+ el.setAttribute(toKebabCase(key), value);
219
+ delete el.dataset[key];
220
+ properties = {};
221
+ });
222
+ });
223
+ delete group.dataset.dragEnterCount;
224
+ }
225
+ };
226
+ const forceRestoreGroup = (group, type) => {
227
+ // langsung restore (dipanggil pada drop)
228
+ onForceRestoreGroup === null || onForceRestoreGroup === void 0 ? void 0 : onForceRestoreGroup(group, type);
229
+ ["rect", "circle"].forEach((selector) => {
230
+ const el = group === null || group === void 0 ? void 0 : group.querySelector(selector);
231
+ if (!el)
232
+ return;
233
+ const dataset = el.dataset;
234
+ Object.entries(dataset).forEach(([key, value]) => {
235
+ el.setAttribute(toKebabCase(key), value);
236
+ delete el.dataset[key];
237
+ properties = {};
238
+ });
239
+ });
240
+ delete group.dataset.dragEnterCount;
241
+ };
242
+ const transformRotate = `rotate(${rotate} ${x + width / 2} ${y + height / 2})`;
243
+ switch (shape) {
244
+ case "square":
245
+ return (<g key={id} id={id} data-id={id} transform={`translate(${x}, ${y})`} style={{ pointerEvents: "all" }} onContextMenu={(e) => e.preventDefault()} onDragEnter={(e) => {
246
+ const group = e.currentTarget;
247
+ highlightGroup(group, "dragenter");
248
+ }} onDragOver={(e) => {
249
+ e.preventDefault(); // agar drop diterima
250
+ }} onDragLeave={(e) => {
251
+ const group = e.currentTarget;
252
+ unhighlightGroup(group);
253
+ }} onDrop={(e) => {
254
+ const group = e.currentTarget;
255
+ // restore langsung dan reset
256
+ forceRestoreGroup(group, "drop");
257
+ }} onPointerOver={(e) => {
258
+ // e.preventDefault(); // penting
259
+ const group = e.currentTarget;
260
+ highlightGroup(group, "pointerover");
261
+ }} onPointerOut={(e) => {
262
+ const group = e.currentTarget;
263
+ unhighlightGroup(group);
264
+ }} onPointerUp={(e) => {
265
+ const group = e.currentTarget;
266
+ // restore langsung dan reset
267
+ forceRestoreGroup(group, "pointerup");
268
+ }} onPointerDown={(e) => {
269
+ const group = e.currentTarget;
270
+ highlightGroup(group, "pointerdown");
271
+ }}
272
+ // onPointerEnter={(e) => {
273
+ // const group = e.currentTarget as SVGGElement;
274
+ // highlightGroup(group, "pointerenter");
275
+ // }}
276
+ onPointerLeave={(e) => {
277
+ const group = e.currentTarget;
278
+ unhighlightGroup(group);
279
+ }} onMouseEnter={(e) => {
280
+ // e.preventDefault(); // penting
281
+ const group = e.currentTarget;
282
+ highlightGroup(group, "mouseenter");
283
+ }} onMouseLeave={(e) => {
284
+ const group = e.currentTarget;
285
+ unhighlightGroup(group);
286
+ }}>
287
+ <g transform={`rotate(${rotation}, 0,0)`}>
288
+ <rect key={`${id}-rect`} width={width} height={height} fill={fill} rx={radius} {...omit(item, ["x", "y", "label", "points", "tags"])} {...commonProps}/>
289
+ {renderTags(tags)}
290
+ {showLabels && (<g transform={`rotate(${-rotation}, ${width / 2}, ${height / 2})`} pointerEvents="none">
291
+ {labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
292
+ var _a, _b, _c, _d, _e, _f, _g;
293
+ const cx = width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0);
294
+ const cy = height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0);
295
+ return (<text pointerEvents="none" {...omit(commonProps, [
296
+ "opacity",
297
+ "stroke",
298
+ "strokeWidth",
299
+ ])} transform={`rotate(${(_c = _ === null || _ === void 0 ? void 0 : _.rotation) !== null && _c !== void 0 ? _c : 0}, ${cx},${cy})`} key={`${id}-label-${index}`} x={width / 2 + ((_d = _ === null || _ === void 0 ? void 0 : _.x) !== null && _d !== void 0 ? _d : 0)} y={height / 2 + ((_e = _ === null || _ === void 0 ? void 0 : _.y) !== null && _e !== void 0 ? _e : 0)} fill={(_f = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _f !== void 0 ? _f : "black"} fontSize={`${(_g = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _g !== void 0 ? _g : 10}px`} fontWeight="bold" textAnchor="middle" dominantBaseline="middle">
300
+ {_ === null || _ === void 0 ? void 0 : _.label}
301
+ </text>);
302
+ })}
303
+ </g>)}
304
+ </g>
305
+ </g>);
306
+ case "polygon":
307
+ const finalPoint = points.map((p) => `${p.x},${p.y}`).join(" ");
308
+ return (<g key={id} data-id={id} transform={`translate(${x}, ${y})`}>
309
+ <g transform={`rotate(${rotation}, 0, 0)`}>
310
+ <polygon {...commonProps} key={id} points={finalPoint} x="0" y="0"/>
311
+ </g>
312
+ </g>);
313
+ case "circle":
314
+ return (<g key={id} style={{ pointerEvents: "all" }} data-id={id} transform={`translate(${x}, ${y})`} onContextMenu={(e) => e.preventDefault()} onDragEnter={(e) => {
315
+ e.preventDefault(); // penting
316
+ const group = e.currentTarget;
317
+ highlightGroup(group, "dragenter");
318
+ }} onDragOver={(e) => {
319
+ e.preventDefault(); // agar drop diterima
320
+ }} onDragLeave={(e) => {
321
+ const group = e.currentTarget;
322
+ unhighlightGroup(group);
323
+ }} onDrop={(e) => {
324
+ e.preventDefault();
325
+ const group = e.currentTarget;
326
+ // restore langsung dan reset
327
+ forceRestoreGroup(group);
328
+ }} onPointerOver={(e) => {
329
+ e.preventDefault(); // penting
330
+ const group = e.currentTarget;
331
+ highlightGroup(group, "pointerover");
332
+ }} onPointerOut={(e) => {
333
+ const group = e.currentTarget;
334
+ unhighlightGroup(group);
335
+ }} onPointerUp={(e) => {
336
+ e.preventDefault();
337
+ const group = e.currentTarget;
338
+ // restore langsung dan reset
339
+ forceRestoreGroup(group);
340
+ }} onMouseDown={(e) => {
341
+ e.preventDefault();
342
+ const group = e.currentTarget;
343
+ highlightGroup(group, "mousedown");
344
+ }} onMouseEnter={(e) => {
345
+ // e.preventDefault(); // penting
346
+ const group = e.currentTarget;
347
+ highlightGroup(group, "mouseenter");
348
+ }} onMouseLeave={(e) => {
349
+ const group = e.currentTarget;
350
+ unhighlightGroup(group);
351
+ }}>
352
+ {" "}
353
+ <g transform={`rotate(${-rotation}, 0, 0)`}>
354
+ <circle key={id} cx={width / 2} cy={height / 2} r={Math.min(height, width) / 2} fill={fill} {...commonProps} {...omit(item, ["x", "y", "label", "points", "tags"])}/>
355
+ {renderTags(tags)}
356
+ {showLabels && (<g transform={`rotate(${-rotation}, ${width / 2}, ${height / 2})`}>
357
+ {labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
358
+ var _a, _b, _c, _d, _e, _f, _g;
359
+ const cx = width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0);
360
+ const cy = height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0);
361
+ return (<text {...omit(commonProps, [
362
+ "opacity",
363
+ "stroke",
364
+ "strokeWidth",
365
+ ])} transform={`rotate(${(_c = _ === null || _ === void 0 ? void 0 : _.rotation) !== null && _c !== void 0 ? _c : 0}, ${cx},${cy})`} key={`${id}-label-${index}`} x={width / 2 + ((_d = _ === null || _ === void 0 ? void 0 : _.x) !== null && _d !== void 0 ? _d : 0)} y={height / 2 + ((_e = _ === null || _ === void 0 ? void 0 : _.y) !== null && _e !== void 0 ? _e : 0)} fill={(_f = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _f !== void 0 ? _f : "black"} fontSize={`${(_g = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _g !== void 0 ? _g : 10}px`} fontWeight="bold" textAnchor="middle" dominantBaseline="middle">
366
+ {_ === null || _ === void 0 ? void 0 : _.label}
367
+ </text>);
368
+ })}
369
+ </g>)}
370
+ </g>
371
+ </g>);
372
+ case "table-seat-circle": {
373
+ const seatCount = item.seatCount;
374
+ const openSpace = (_a = item.openSpace) !== null && _a !== void 0 ? _a : 0;
375
+ // LOCAL SPACE (tanpa x,y)
376
+ const centerX = width / 2;
377
+ const centerY = height / 2;
378
+ // meja
379
+ const tableRadius = Math.min(width, height) / 2;
380
+ // seat statis
381
+ const seatRadius = 10;
382
+ const fullAngle = Math.PI * 2;
383
+ const availableAngle = fullAngle * (1 - openSpace);
384
+ const angleStart = (fullAngle - availableAngle) / 2;
385
+ const angleStep = availableAngle / seatCount;
386
+ const seatCircles = Array.from({ length: seatCount }, (_, i) => {
387
+ const angle = angleStart + i * angleStep;
388
+ const cx = centerX + (tableRadius + seatRadius) * Math.cos(angle);
389
+ const cy = centerY + (tableRadius + seatRadius) * Math.sin(angle);
390
+ return { cx, cy };
391
+ });
392
+ return (<g key={id} style={{ pointerEvents: "all" }} data-id={id} id={id} transform={`translate(${x}, ${y})`} onContextMenu={(e) => e.preventDefault()} onDragEnter={(e) => {
393
+ e.preventDefault(); // penting
394
+ const group = e.currentTarget;
395
+ highlightGroup(group, "dragenter");
396
+ }} onDragOver={(e) => {
397
+ e.preventDefault(); // agar drop diterima
398
+ }} onDragLeave={(e) => {
399
+ const group = e.currentTarget;
400
+ unhighlightGroup(group);
401
+ }} onDrop={(e) => {
402
+ e.preventDefault();
403
+ const group = e.currentTarget;
404
+ // restore langsung dan reset
405
+ forceRestoreGroup(group);
406
+ }} onPointerOver={(e) => {
407
+ e.preventDefault(); // penting
408
+ const group = e.currentTarget;
409
+ highlightGroup(group, "pointerover");
410
+ }} onPointerOut={(e) => {
411
+ const group = e.currentTarget;
412
+ unhighlightGroup(group);
413
+ }} onPointerUp={(e) => {
414
+ e.preventDefault();
415
+ const group = e.currentTarget;
416
+ // restore langsung dan reset
417
+ forceRestoreGroup(group);
418
+ }} onMouseDown={(e) => {
419
+ e.preventDefault();
420
+ const group = e.currentTarget;
421
+ highlightGroup(group, "mousedown");
422
+ }} onMouseEnter={(e) => {
423
+ // e.preventDefault(); // penting
424
+ const group = e.currentTarget;
425
+ highlightGroup(group, "mouseenter");
426
+ }} onMouseLeave={(e) => {
427
+ const group = e.currentTarget;
428
+ unhighlightGroup(group);
429
+ }}>
430
+ <g transform={`rotate(${rotation}, 0, 0)`}>
431
+ <circle cx={centerX} cy={centerY} r={tableRadius} fill={selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill} {...omit(item, ["x", "y", "label", "points", "tags"])} {...commonProps}/>
432
+ <g data-seat={`${id}-seats`}>
433
+ {seatCircles.map(({ cx, cy }, i) => (<circle key={`${id}-seat-${i}`} cx={cx} cy={cy} r={seatRadius} fill={seatFill} className={item === null || item === void 0 ? void 0 : item.className}/>))}
434
+ </g>
435
+
436
+ {renderTags(tags)}
437
+ {showLabels && (<g transform={`rotate(${-rotation}, ${width / 2}, ${height / 2})`}>
438
+ {labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
439
+ var _a, _b, _c, _d;
440
+ return (<text 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}>
441
+ {_ === null || _ === void 0 ? void 0 : _.label}
442
+ </text>);
443
+ })}
444
+ </g>)}
445
+ </g>
446
+ </g>);
447
+ }
448
+ case "table-seat-rect-circle": {
449
+ const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
450
+ const base = clamp(Math.min(width, height) * 0.08, 12, 28);
451
+ const tableRadius = Math.min(width, height) / 2;
452
+ const seatSizeTB = {
453
+ w: base * 1.8, // lebih panjang
454
+ h: base * 0.9, // lebih tipis
455
+ };
456
+ const seatSizeLR = {
457
+ w: base * 0.9, // lebih tipis
458
+ h: base * 1.8, // lebih panjang
459
+ };
460
+ const openSpace = item.openSpace || 0;
461
+ const seatRadius = Math.min(width, height) * 0.2;
462
+ const top = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.top) || 0;
463
+ const right = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.right) || 0;
464
+ const bottom = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.bottom) || 0;
465
+ const left = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.left) || 0;
466
+ // split seats evenly on top and bottom
467
+ const seatCountTopBottom = Math.ceil(Math.max(top, bottom) / 2);
468
+ const seatCountLeftRight = Math.ceil(Math.max(left, left) / 2);
469
+ const availableWidth = width * (1 - openSpace);
470
+ const availableHeight = height * (1 - openSpace);
471
+ const spacingWidth = availableWidth / seatCountTopBottom;
472
+ const spacingHeight = availableHeight / seatCountLeftRight;
473
+ const topSeats = distributeWithSpacing({
474
+ start: 0,
475
+ length: width,
476
+ count: top,
477
+ radius: seatRadius,
478
+ spacing: spacingWidth,
479
+ }).map((cx) => ({
480
+ x: cx - seatSizeTB.w / 2,
481
+ y: -seatSizeTB.h,
482
+ width: seatSizeTB.w,
483
+ height: seatSizeTB.h,
484
+ id: "top",
485
+ }));
486
+ const bottomSeats = distributeWithSpacing({
487
+ start: 0,
488
+ length: width,
489
+ count: bottom,
490
+ radius: seatRadius,
491
+ spacing: spacingWidth,
492
+ }).map((cx) => ({
493
+ x: cx - seatSizeTB.w / 2,
494
+ y: height,
495
+ width: seatSizeTB.w,
496
+ height: seatSizeTB.h,
497
+ id: "bottom",
498
+ }));
499
+ const leftSeats = distributeWithSpacing({
500
+ start: 0,
501
+ length: height,
502
+ count: left,
503
+ radius: seatRadius,
504
+ spacing: spacingHeight,
505
+ }).map((cy) => ({
506
+ x: -seatSizeLR.w,
507
+ y: cy - seatSizeLR.h / 2,
508
+ width: seatSizeLR.w,
509
+ height: seatSizeLR.h,
510
+ id: "left",
511
+ }));
512
+ const rightSeats = distributeWithSpacing({
513
+ start: 0,
514
+ length: height,
515
+ count: right,
516
+ radius: seatRadius,
517
+ spacing: spacingHeight,
518
+ }).map((cy) => ({
519
+ x: width,
520
+ y: cy - seatSizeLR.h / 2,
521
+ width: seatSizeLR.w,
522
+ height: seatSizeLR.h,
523
+ id: "right",
524
+ }));
525
+ const seats = [
526
+ ...topSeats,
527
+ ...bottomSeats,
528
+ ...leftSeats,
529
+ ...rightSeats,
530
+ ];
531
+ return (<g key={id} transform={`translate(${x}, ${y})`} data-id={id} onContextMenu={(e) => e.preventDefault()} onDragEnter={(e) => {
532
+ e.preventDefault(); // penting
533
+ const group = e.currentTarget;
534
+ highlightGroup(group, "dragenter");
535
+ }} onDragOver={(e) => {
536
+ e.preventDefault(); // agar drop diterima
537
+ }} onDragLeave={(e) => {
538
+ const group = e.currentTarget;
539
+ unhighlightGroup(group);
540
+ }} onDrop={(e) => {
541
+ e.preventDefault();
542
+ const group = e.currentTarget;
543
+ // restore langsung dan reset
544
+ forceRestoreGroup(group);
545
+ }} onPointerOver={(e) => {
546
+ e.preventDefault(); // penting
547
+ const group = e.currentTarget;
548
+ highlightGroup(group, "pointerover");
549
+ }} onPointerOut={(e) => {
550
+ const group = e.currentTarget;
551
+ unhighlightGroup(group);
552
+ }} onPointerUp={(e) => {
553
+ e.preventDefault();
554
+ const group = e.currentTarget;
555
+ // restore langsung dan reset
556
+ forceRestoreGroup(group);
557
+ }} onMouseDown={(e) => {
558
+ e.preventDefault();
559
+ const group = e.currentTarget;
560
+ highlightGroup(group, "mousedown");
561
+ }} onMouseEnter={(e) => {
562
+ // e.preventDefault(); // penting
563
+ const group = e.currentTarget;
564
+ highlightGroup(group, "mouseenter");
565
+ }} onMouseLeave={(e) => {
566
+ const group = e.currentTarget;
567
+ unhighlightGroup(group);
568
+ }}>
569
+ <g transform={`rotate(${rotation}, 0, 0)`}>
570
+ {/* Seats */}
571
+ <circle cx={width / 2} cy={height / 2} r={tableRadius} fill={fill} {...omit(item, ["x", "y", "label", "points", "tags"])} {...commonProps}/>
572
+ <g key={`${id}-seats`} data-seat={`${id}-seats`}>
573
+ {seats === null || seats === void 0 ? void 0 : seats.map(({ height, width, x, y, id }, i) => (<rect x={x} y={y} key={`${id}-seat-${i}`} id={`seat-${id}`} height={height} width={width} rx={radius / 4} fill={seatFill} className={item === null || item === void 0 ? void 0 : item.className}/>))}
574
+ </g>
575
+ {renderTags(tags)}
576
+ {showLabels && (<g transform={`rotate(${-rotation}, ${width / 2}, ${height / 2})`}>
577
+ {labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
578
+ var _a, _b, _c, _d, _e, _f, _g;
579
+ const cx = width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0);
580
+ const cy = height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0);
581
+ return (<text {...omit(commonProps, [
582
+ "opacity",
583
+ "stroke",
584
+ "strokeWidth",
585
+ ])} transform={`rotate(${(_c = _ === null || _ === void 0 ? void 0 : _.rotation) !== null && _c !== void 0 ? _c : 0}, ${cx},${cy})`} key={`${id}-label-${index}`} x={width / 2 + ((_d = _ === null || _ === void 0 ? void 0 : _.x) !== null && _d !== void 0 ? _d : 0)} y={height / 2 + ((_e = _ === null || _ === void 0 ? void 0 : _.y) !== null && _e !== void 0 ? _e : 0)} fill={(_f = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _f !== void 0 ? _f : "black"} fontSize={`${(_g = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _g !== void 0 ? _g : 10}px`} fontWeight="bold" textAnchor="middle" dominantBaseline="middle">
586
+ {_ === null || _ === void 0 ? void 0 : _.label}
587
+ </text>);
588
+ })}
589
+ </g>)}
590
+ </g>
591
+ </g>);
592
+ }
593
+ case "table-seat-square": {
594
+ const openSpace = item.openSpace || 0; // from 0 to 0.9
595
+ const r = 10;
596
+ const seatPositions = item.seatPositions;
597
+ const topCount = (_b = seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.top) !== null && _b !== void 0 ? _b : 0;
598
+ const bottomCount = (_c = seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.bottom) !== null && _c !== void 0 ? _c : 0;
599
+ const leftCount = (_d = seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.left) !== null && _d !== void 0 ? _d : 0;
600
+ const rightCount = (_e = seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.right) !== null && _e !== void 0 ? _e : 0;
601
+ // split seats evenly on top and bottom
602
+ const seatCountTopBottom = Math.ceil(Math.max(topCount, bottomCount) / 2);
603
+ const seatCountLeftRight = Math.ceil(Math.max(leftCount, rightCount) / 2);
604
+ const availableWidth = width * (1 - openSpace);
605
+ const availableHeight = height * (1 - openSpace);
606
+ const spacingWidth = availableWidth / seatCountTopBottom;
607
+ const spacingHeight = availableHeight / seatCountLeftRight;
608
+ const topXs = distributeWithSpacing({
609
+ start: x,
610
+ length: width,
611
+ count: topCount,
612
+ radius: r,
613
+ spacing: spacingWidth,
614
+ });
615
+ const topSeats = topXs.map((cx) => ({ cx, cy: y - r, id: "top" }));
616
+ // TOP
617
+ const bottomSeats = distributeWithSpacing({
618
+ start: x,
619
+ length: width,
620
+ count: bottomCount,
621
+ radius: r,
622
+ spacing: spacingWidth,
623
+ }).map((cx) => ({
624
+ cx: cx,
625
+ cy: y + height + r,
626
+ id: "bottom",
627
+ }));
628
+ const leftYs = distributeWithSpacing({
629
+ start: y,
630
+ length: height,
631
+ count: leftCount,
632
+ radius: r,
633
+ spacing: spacingHeight,
634
+ });
635
+ const leftSeats = leftYs.map((cy) => ({ cx: x - r, cy, id: "left" }));
636
+ const rightSeats = distributeWithSpacing({
637
+ start: y,
638
+ length: height,
639
+ count: rightCount,
640
+ radius: r,
641
+ spacing: spacingHeight,
642
+ }).map((cy) => ({
643
+ cx: x + width + r,
644
+ cy,
645
+ id: "right",
646
+ }));
647
+ return (<g key={id} data-id={id} transform={`translate(${x}, ${y})`} onContextMenu={(e) => e.preventDefault()} onDragEnter={(e) => {
648
+ e.preventDefault(); // penting
649
+ const group = e.currentTarget;
650
+ highlightGroup(group, "dragenter");
651
+ }} onDragOver={(e) => {
652
+ e.preventDefault(); // agar drop diterima
653
+ }} onDragLeave={(e) => {
654
+ const group = e.currentTarget;
655
+ unhighlightGroup(group);
656
+ }} onDrop={(e) => {
657
+ e.preventDefault();
658
+ const group = e.currentTarget;
659
+ // restore langsung dan reset
660
+ forceRestoreGroup(group);
661
+ }} onPointerOver={(e) => {
662
+ e.preventDefault(); // penting
663
+ const group = e.currentTarget;
664
+ highlightGroup(group, "pointerover");
665
+ }} onPointerOut={(e) => {
666
+ const group = e.currentTarget;
667
+ unhighlightGroup(group);
668
+ }} onPointerUp={(e) => {
669
+ e.preventDefault();
670
+ const group = e.currentTarget;
671
+ // restore langsung dan reset
672
+ forceRestoreGroup(group);
673
+ }} onMouseDown={(e) => {
674
+ e.preventDefault();
675
+ const group = e.currentTarget;
676
+ highlightGroup(group, "mousedown");
677
+ }} onMouseEnter={(e) => {
678
+ // e.preventDefault(); // penting
679
+ const group = e.currentTarget;
680
+ highlightGroup(group, "mouseenter");
681
+ }} onMouseLeave={(e) => {
682
+ const group = e.currentTarget;
683
+ unhighlightGroup(group);
684
+ }}>
685
+ <g transform={`rotate(${rotate}, 0, 0)`}>
686
+ {/* Square Table */}
687
+ <rect width={width} height={height} {...commonProps} fill={selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill} {...omit(item, ["x", "y", "label", "points", "tags"])}/>
688
+ {renderTags(tags)}
689
+
690
+ {/* Seats */}
691
+ <g key={`${id}-seats`} data-seat={`${id}-seats`} transform={`translate(${-x}, ${-y})`}>
692
+ {[...topSeats, ...bottomSeats, ...leftSeats, ...rightSeats].map(({ cx, cy, id }, i) => (<circle key={`${id}-seat-${i}`} id={`seat-${id}`} cx={cx} cy={cy} r={r} fill={seatFill} className={item === null || item === void 0 ? void 0 : item.className}/>))}
693
+ </g>
694
+ {showLabels && (<g transform={`rotate(${-rotation}, ${width / 2}, ${height / 2})`}>
695
+ {labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
696
+ var _a, _b, _c, _d, _e, _f, _g;
697
+ const cx = width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0);
698
+ const cy = height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0);
699
+ return (<text {...omit(commonProps, [
700
+ "opacity",
701
+ "stroke",
702
+ "strokeWidth",
703
+ ])} transform={`rotate(${(_c = _ === null || _ === void 0 ? void 0 : _.rotation) !== null && _c !== void 0 ? _c : 0}, ${cx},${cy})`} key={`${id}-label-${index}`} x={width / 2 + ((_d = _ === null || _ === void 0 ? void 0 : _.x) !== null && _d !== void 0 ? _d : 0)} y={height / 2 + ((_e = _ === null || _ === void 0 ? void 0 : _.y) !== null && _e !== void 0 ? _e : 0)} fill={(_f = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _f !== void 0 ? _f : "black"} fontSize={`${(_g = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _g !== void 0 ? _g : 10}px`} fontWeight="bold" textAnchor="middle" dominantBaseline="middle">
704
+ {_ === null || _ === void 0 ? void 0 : _.label}
705
+ </text>);
706
+ })}
707
+ </g>)}
708
+ </g>
709
+ </g>);
710
+ }
711
+ case "table-seat-half-square": {
712
+ const openSpace = item.openSpace || 0;
713
+ const seatRadius = Math.min(width, height) * 0.15;
714
+ const top = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.top) || 0;
715
+ const right = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.right) || 0;
716
+ const bottom = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.bottom) || 0;
717
+ const left = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.left) || 0;
718
+ // split seats evenly on top and bottom
719
+ const seatCountTopBottom = Math.ceil(Math.max(top, bottom) / 2);
720
+ const seatCountLeftRight = Math.ceil(Math.max(left, left) / 2);
721
+ const availableWidth = width * (1 - openSpace);
722
+ const availableHeight = height * (1 - openSpace);
723
+ const spacingWidth = availableWidth / seatCountTopBottom;
724
+ const spacingHeight = availableHeight / seatCountLeftRight;
725
+ const topSeats = distributeWithSpacing({
726
+ start: 0,
727
+ length: width,
728
+ count: top,
729
+ radius: seatRadius,
730
+ spacing: spacingWidth,
731
+ }).map((cx) => ({ cx, cy: seatRadius * 0.1, id: "top" }));
732
+ const bottomSeats = distributeWithSpacing({
733
+ start: 0,
734
+ length: width,
735
+ count: bottom,
736
+ radius: seatRadius,
737
+ spacing: spacingWidth,
738
+ }).map((cx) => ({
739
+ cx,
740
+ cy: height - seatRadius * 0.1,
741
+ id: "bottom",
742
+ }));
743
+ const leftSeats = distributeWithSpacing({
744
+ start: 0,
745
+ length: height,
746
+ count: left,
747
+ radius: seatRadius,
748
+ spacing: spacingHeight,
749
+ }).map((cy) => ({ cx: seatRadius * 0.1, cy, id: "left" }));
750
+ const rightSeats = distributeWithSpacing({
751
+ start: 0,
752
+ length: height,
753
+ count: right,
754
+ radius: seatRadius,
755
+ spacing: spacingHeight,
756
+ }).map((cy) => ({ cx: width - seatRadius * 0.1, cy, id: "right" }));
757
+ const seats = (_f = [
758
+ ...topSeats,
759
+ ...bottomSeats,
760
+ ...leftSeats,
761
+ ...rightSeats,
762
+ ]) === null || _f === void 0 ? void 0 : _f.map((seat) => (Object.assign(Object.assign({}, seat), { d: arcByDirection({
763
+ cx: seat.cx,
764
+ cy: seat.cy,
765
+ r: seatRadius,
766
+ direction: seat.id,
767
+ fraction: 0.4,
768
+ }) })));
769
+ return (<g key={id} transform={`translate(${x}, ${y})`} data-id={id} onContextMenu={(e) => e.preventDefault()} onDragEnter={(e) => {
770
+ e.preventDefault(); // penting
771
+ const group = e.currentTarget;
772
+ highlightGroup(group, "dragenter");
773
+ }} onDragOver={(e) => {
774
+ e.preventDefault(); // agar drop diterima
775
+ }} onDragLeave={(e) => {
776
+ const group = e.currentTarget;
777
+ unhighlightGroup(group);
778
+ }} onDrop={(e) => {
779
+ e.preventDefault();
780
+ const group = e.currentTarget;
781
+ // restore langsung dan reset
782
+ forceRestoreGroup(group);
783
+ }} onPointerOver={(e) => {
784
+ e.preventDefault(); // penting
785
+ const group = e.currentTarget;
786
+ highlightGroup(group, "pointerover");
787
+ }} onPointerOut={(e) => {
788
+ const group = e.currentTarget;
789
+ unhighlightGroup(group);
790
+ }} onPointerUp={(e) => {
791
+ e.preventDefault();
792
+ const group = e.currentTarget;
793
+ // restore langsung dan reset
794
+ forceRestoreGroup(group);
795
+ }} onMouseDown={(e) => {
796
+ e.preventDefault();
797
+ const group = e.currentTarget;
798
+ highlightGroup(group, "mousedown");
799
+ }} onMouseEnter={(e) => {
800
+ // e.preventDefault(); // penting
801
+ const group = e.currentTarget;
802
+ highlightGroup(group, "mouseenter");
803
+ }} onMouseLeave={(e) => {
804
+ const group = e.currentTarget;
805
+ unhighlightGroup(group);
806
+ }}>
807
+ <g transform={`rotate(${rotation}, 0, 0)`}>
808
+ {/* Seats */}
809
+ <rect width={width} height={height} rx={radius} {...commonProps} fill={fill} {...omit(item, ["x", "y", "label", "points", "tags"])}/>
810
+ <g key={`${id}-seats`} data-seat={`${id}-seats`}>
811
+ {seats === null || seats === void 0 ? void 0 : seats.map(({ d, id }, i) => (<path key={`${id}-seat-${i}`} id={`seat-${id}`} d={d} fill="white" className={item === null || item === void 0 ? void 0 : item.className}/>))}
812
+ </g>
813
+ {renderTags(tags)}
814
+ {showLabels && (<g transform={`rotate(${-rotation}, ${width / 2}, ${height / 2})`}>
815
+ {labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
816
+ var _a, _b, _c, _d, _e, _f, _g;
817
+ const cx = width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0);
818
+ const cy = height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0);
819
+ return (<text {...omit(commonProps, [
820
+ "opacity",
821
+ "stroke",
822
+ "strokeWidth",
823
+ ])} transform={`rotate(${(_c = _ === null || _ === void 0 ? void 0 : _.rotation) !== null && _c !== void 0 ? _c : 0}, ${cx},${cy})`} key={`${id}-label-${index}`} x={width / 2 + ((_d = _ === null || _ === void 0 ? void 0 : _.x) !== null && _d !== void 0 ? _d : 0)} y={height / 2 + ((_e = _ === null || _ === void 0 ? void 0 : _.y) !== null && _e !== void 0 ? _e : 0)} fill={(_f = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _f !== void 0 ? _f : "black"} fontSize={`${(_g = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _g !== void 0 ? _g : 10}px`} fontWeight="bold" textAnchor="middle" dominantBaseline="middle">
824
+ {_ === null || _ === void 0 ? void 0 : _.label}
825
+ </text>);
826
+ })}
827
+ </g>)}
828
+ </g>
829
+ </g>);
830
+ }
831
+ case "table-seat-rect-square": {
832
+ const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
833
+ const base = clamp(Math.min(width, height) * 0.08, 12, 28);
834
+ const seatSizeTB = {
835
+ w: base * 1.8, // lebih panjang
836
+ h: base * 0.9, // lebih tipis
837
+ };
838
+ const seatSizeLR = {
839
+ w: base * 0.9, // lebih tipis
840
+ h: base * 1.8, // lebih panjang
841
+ };
842
+ const openSpace = item.openSpace || 0;
843
+ const seatRadius = Math.min(width, height) * 0.2;
844
+ const top = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.top) || 0;
845
+ const right = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.right) || 0;
846
+ const bottom = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.bottom) || 0;
847
+ const left = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.left) || 0;
848
+ // split seats evenly on top and bottom
849
+ const seatCountTopBottom = Math.ceil(Math.max(top, bottom) / 2);
850
+ const seatCountLeftRight = Math.ceil(Math.max(left, left) / 2);
851
+ const availableWidth = width * (1 - openSpace);
852
+ const availableHeight = height * (1 - openSpace);
853
+ const spacingWidth = availableWidth / seatCountTopBottom;
854
+ const spacingHeight = availableHeight / seatCountLeftRight;
855
+ const topSeats = distributeWithSpacing({
856
+ start: 0,
857
+ length: width,
858
+ count: top,
859
+ radius: seatRadius,
860
+ spacing: spacingWidth,
861
+ }).map((cx) => ({
862
+ x: cx - seatSizeTB.w / 2,
863
+ y: y - seatSizeTB.h,
864
+ width: seatSizeTB.w,
865
+ height: seatSizeTB.h,
866
+ id: "top",
867
+ }));
868
+ const bottomSeats = distributeWithSpacing({
869
+ start: 0,
870
+ length: width,
871
+ count: bottom,
872
+ radius: seatRadius,
873
+ spacing: spacingWidth,
874
+ }).map((cx) => ({
875
+ x: cx - seatSizeTB.w / 2,
876
+ y: y + height,
877
+ width: seatSizeTB.w,
878
+ height: seatSizeTB.h,
879
+ id: "bottom",
880
+ }));
881
+ const leftSeats = distributeWithSpacing({
882
+ start: 0,
883
+ length: height,
884
+ count: left,
885
+ radius: seatRadius,
886
+ spacing: spacingHeight,
887
+ }).map((cy) => ({
888
+ x: -seatSizeLR.w,
889
+ y: y + cy - seatSizeLR.h / 2,
890
+ width: seatSizeLR.w,
891
+ height: seatSizeLR.h,
892
+ id: "left",
893
+ }));
894
+ const rightSeats = distributeWithSpacing({
895
+ start: 0,
896
+ length: height,
897
+ count: right,
898
+ radius: seatRadius,
899
+ spacing: spacingHeight,
900
+ }).map((cy) => ({
901
+ x: width,
902
+ y: y + cy - seatSizeLR.h / 2,
903
+ width: seatSizeLR.w,
904
+ height: seatSizeLR.h,
905
+ id: "right",
906
+ }));
907
+ const seats = [
908
+ ...topSeats,
909
+ ...bottomSeats,
910
+ ...leftSeats,
911
+ ...rightSeats,
912
+ ];
913
+ return (<g key={id} transform={`translate(${x}, ${y})`} data-id={id} onContextMenu={(e) => e.preventDefault()} onDragEnter={(e) => {
914
+ e.preventDefault(); // penting
915
+ const group = e.currentTarget;
916
+ highlightGroup(group, "dragenter");
917
+ }} onDragOver={(e) => {
918
+ e.preventDefault(); // agar drop diterima
919
+ }} onDragLeave={(e) => {
920
+ const group = e.currentTarget;
921
+ unhighlightGroup(group);
922
+ }} onDrop={(e) => {
923
+ e.preventDefault();
924
+ const group = e.currentTarget;
925
+ // restore langsung dan reset
926
+ forceRestoreGroup(group);
927
+ }} onPointerOver={(e) => {
928
+ e.preventDefault(); // penting
929
+ const group = e.currentTarget;
930
+ highlightGroup(group, "pointerover");
931
+ }} onPointerOut={(e) => {
932
+ const group = e.currentTarget;
933
+ unhighlightGroup(group);
934
+ }} onPointerUp={(e) => {
935
+ e.preventDefault();
936
+ const group = e.currentTarget;
937
+ // restore langsung dan reset
938
+ forceRestoreGroup(group);
939
+ }} onMouseDown={(e) => {
940
+ e.preventDefault();
941
+ const group = e.currentTarget;
942
+ highlightGroup(group, "mousedown");
943
+ }} onMouseEnter={(e) => {
944
+ // e.preventDefault(); // penting
945
+ const group = e.currentTarget;
946
+ highlightGroup(group, "mouseenter");
947
+ }} onMouseLeave={(e) => {
948
+ const group = e.currentTarget;
949
+ unhighlightGroup(group);
950
+ }}>
951
+ <g transform={`rotate(${rotation}, 0, 0)`}>
952
+ {/* Seats */}
953
+ <rect width={width} height={height} rx={radius} {...commonProps} fill={fill} {...omit(item, ["x", "y", "label", "points", "tags"])}/>
954
+ <g key={`${id}-seats`} data-seat={`${id}-seats`} transform={`translate(${-x}, ${-y})`}>
955
+ {seats === null || seats === void 0 ? void 0 : seats.map(({ height, width, x, y, id }, i) => (<rect x={x} y={y} key={`${id}-seat-${i}`} id={`seat-${id}`} height={height} width={width} rx={radius / 4} fill={seatFill}/>))}
956
+ </g>
957
+ {renderTags(tags)}
958
+ {showLabels && (<g transform={`rotate(${-rotation}, ${width / 2}, ${height / 2})`}>
959
+ {labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
960
+ var _a, _b, _c, _d, _e, _f, _g;
961
+ const cx = width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0);
962
+ const cy = height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0);
963
+ return (<text {...omit(commonProps, [
964
+ "opacity",
965
+ "stroke",
966
+ "strokeWidth",
967
+ ])} transform={`rotate(${(_c = _ === null || _ === void 0 ? void 0 : _.rotation) !== null && _c !== void 0 ? _c : 0}, ${cx},${cy})`} key={`${id}-label-${index}`} x={width / 2 + ((_d = _ === null || _ === void 0 ? void 0 : _.x) !== null && _d !== void 0 ? _d : 0)} y={height / 2 + ((_e = _ === null || _ === void 0 ? void 0 : _.y) !== null && _e !== void 0 ? _e : 0)} fill={(_f = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _f !== void 0 ? _f : "black"} fontSize={`${(_g = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _g !== void 0 ? _g : 10}px`} fontWeight="bold" textAnchor="middle" dominantBaseline="middle">
968
+ {_ === null || _ === void 0 ? void 0 : _.label}
969
+ </text>);
970
+ })}
971
+ </g>)}
972
+ </g>
973
+ </g>);
974
+ }
975
+ case "text":
976
+ return (<g key={id} onContextMenu={(e) => e.preventDefault()} data-id={id} transform={`translate(${x}, ${y})`}>
977
+ <g transform={`rotate(${rotation}, 0, 0)`}>
978
+ <rect width={width} height={height} fill="transparent" opacity={opacity}/>
979
+ <text x={width / 2} y={height / 2} textAnchor="middle" dominantBaseline="middle" fill={fill} fontSize={fontSize !== null && fontSize !== void 0 ? fontSize : height * 0.6} opacity={opacity} {...omit(commonProps, ["fill", "opacity"])}>
980
+ {text}
981
+ </text>
982
+ </g>
983
+ </g>);
984
+ case "image-table":
985
+ return (<g key={id} id={id} data-id={id} transform={`translate(${x}, ${y})`} onContextMenu={(e) => e.preventDefault()} onDragEnter={(e) => {
986
+ e.preventDefault(); // penting
987
+ const group = e.currentTarget;
988
+ highlightGroup(group, "dragenter");
989
+ }} onDragOver={(e) => {
990
+ e.preventDefault(); // agar drop diterima
991
+ }} onDragLeave={(e) => {
992
+ const group = e.currentTarget;
993
+ unhighlightGroup(group);
994
+ }} onDrop={(e) => {
995
+ e.preventDefault();
996
+ const group = e.currentTarget;
997
+ // restore langsung dan reset
998
+ forceRestoreGroup(group);
999
+ }} onPointerOver={(e) => {
1000
+ e.preventDefault(); // penting
1001
+ const group = e.currentTarget;
1002
+ highlightGroup(group, "pointerover");
1003
+ }} onPointerOut={(e) => {
1004
+ const group = e.currentTarget;
1005
+ unhighlightGroup(group);
1006
+ }} onPointerUp={(e) => {
1007
+ e.preventDefault();
1008
+ const group = e.currentTarget;
1009
+ // restore langsung dan reset
1010
+ forceRestoreGroup(group);
1011
+ }} onMouseDown={(e) => {
1012
+ e.preventDefault();
1013
+ const group = e.currentTarget;
1014
+ highlightGroup(group, "mousedown");
1015
+ }}>
1016
+ <g transform={`rotate(${rotation}, 0, 0)`}>
1017
+ <image href={src} width={width} height={height} transform={transformRotate} {...commonProps}/>
1018
+ {renderTags(tags)}
1019
+ {showLabels && (<g transform={`rotate(${-rotation}, ${width / 2}, ${height / 2})`}>
1020
+ {labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
1021
+ var _a, _b, _c, _d;
1022
+ return (<text key={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}>
1023
+ {_ === null || _ === void 0 ? void 0 : _.label}
1024
+ </text>);
1025
+ })}
1026
+ </g>)}
1027
+ </g>
1028
+ </g>);
1029
+ case "background":
1030
+ return (<g key={id} onContextMenu={(e) => e.preventDefault()}>
1031
+ <image href={src} x={x} y={y} width={width} height={height} transform={transformRotate} {...commonProps}/>
1032
+ {labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
1033
+ var _a, _b, _c, _d;
1034
+ return (<text key={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}>
1035
+ {_ === null || _ === void 0 ? void 0 : _.label}
1036
+ </text>);
1037
+ })}
1038
+ </g>);
1039
+ default:
1040
+ return <g key={id}/>;
1041
+ }
1042
+ };
1043
+ let date = new Date();
1044
+ return <g key={`${date}`}>{components === null || components === void 0 ? void 0 : components.map(renderShape)}</g>;
1045
+ };
1046
+ export default Layers;