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
@@ -3,12 +3,10 @@ import { createElement as _createElement } from "react";
3
3
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
4
4
  import { useRef } from "react";
5
5
  import { isArray, isEmpty, omit } from "lodash";
6
- import clsx from "clsx";
7
- const Layers = ({ shadowShape, components, onClick, selectedComponent, selectedTable, activeTool, onMouseDown, onMouseUp, onBlur, selectedTableColor, mode = "edit", style,
8
- // onTouchEnd,
9
- // onTouchMove,
10
- onTouchStart, }) => {
6
+ const Layers = ({ shadowShape, components, onClick, selectedComponent, selectedTable, activeTool, onMouseDown, onMouseUp, onBlur, selectedTableColor, mode = "edit", style, selectionLines, }) => {
7
+ var _a;
11
8
  const refItemTemp = useRef(null);
9
+ const hasPoints = selectionLines && !isEmpty(selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.points);
12
10
  const handleOnHover = (item) => {
13
11
  if (mode === "edit") {
14
12
  refItemTemp.current = item;
@@ -24,15 +22,6 @@ onTouchStart, }) => {
24
22
  .join(" ");
25
23
  return points;
26
24
  }
27
- function rectToPolygonNodes(x, y, width, height) {
28
- const points = [
29
- { x: x, y: y },
30
- { x: x + width, y: y },
31
- { x: x + width, y: y + height },
32
- { x: x, y: y + height },
33
- ];
34
- return points;
35
- }
36
25
  const renderShadowShape = (item) => {
37
26
  var _a;
38
27
  const { id, x, y, width, height, fill, opacity, rotation, shape, fontColor, text, seatFill, labels, points, } = item;
@@ -40,17 +29,18 @@ onTouchStart, }) => {
40
29
  switch (shape) {
41
30
  case "square":
42
31
  case "polygon":
32
+ case "selection-box":
43
33
  const pointsFormat = !isEmpty(points)
44
34
  ? points
45
35
  : rectToPolygonPoints(x, y, width, height);
46
36
  return _jsx("polygon", Object.assign({ points: pointsFormat }, commonProps), id);
47
37
  case "circle":
48
- return (_jsx("circle", Object.assign({ cx: x + width / 2, cy: y + height / 2, r: width / 2 }, commonProps), id));
38
+ return (_jsx("circle", Object.assign({ cx: x + width / 2, cy: y + height / 2, r: Math.min(height, width) / 2 }, commonProps), id));
49
39
  case "diamond":
50
40
  return (_jsx("rect", Object.assign({ x: x, y: y, width: width, height: height, transform: `rotate(${rotation}, ${x}, ${y})` }, commonProps), id));
51
41
  case "table-seat-circle": {
52
42
  const seatCount = item.seatCount;
53
- const openSpace = (_a = item.openSpace) !== null && _a !== void 0 ? _a : 0;
43
+ const openSpace = (_a = item.openSpace) !== null && _a !== void 0 ? _a : 0.2;
54
44
  const centerX = x + width / 2;
55
45
  const centerY = y + height / 2;
56
46
  const baseSize = Math.min(width, height);
@@ -68,13 +58,13 @@ onTouchStart, }) => {
68
58
  const cy = centerY + (radius - inset) * Math.sin(angle);
69
59
  return { cx, cy };
70
60
  });
71
- return (_jsxs("g", { transform: `rotate(${rotation} ${centerX} ${centerY})`, children: [_jsx("circle", Object.assign({ cx: centerX, cy: centerY, r: radius - 15, fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill }, commonProps, { opacity: id === (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id) ? 0.5 : opacity })), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
61
+ return (_jsxs("g", { transform: `rotate(${rotation} ${centerX} ${centerY})`, children: [_jsx("circle", Object.assign({ cx: centerX, cy: centerY, r: radius - 15, fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill }, commonProps)), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
72
62
  var _a, _b, _c, _d;
73
63
  return (_jsx("text", { x: centerX + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0), y: centerY + ((_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: `rotate(${rotation} ${centerX} ${centerY})`, onClick: (e) => {
74
64
  e.stopPropagation();
75
65
  onClick && onClick(item);
76
66
  }, children: _ === null || _ === void 0 ? void 0 : _.label }, `${id}-label-${index}`));
77
- }), _jsx("g", { fill: "#e6b9c0", opacity: id === (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id) ? 0.5 : opacity, stroke: "#c49ba3", strokeWidth: "1", children: seatCircles.map(({ cx, cy }, i) => (_jsx("circle", { cx: cx, cy: cy, r: seatRadius, fill: seatFill }, `${id}-seat-${i}`))) })] }, id));
67
+ }), _jsx("g", { fill: "#e6b9c0", stroke: "#c49ba3", strokeWidth: "1", children: seatCircles.map(({ cx, cy }, i) => (_jsx("circle", { cx: cx, cy: cy, r: seatRadius, fill: seatFill }, `${id}-seat-${i}`))) })] }, id));
78
68
  }
79
69
  case "table-seat-square": {
80
70
  const seatCount = item.seatCount || 6;
@@ -87,14 +77,14 @@ onTouchStart, }) => {
87
77
  const spacing = seatCountPerSide > 1 ? availableWidth / (seatCountPerSide - 1) : 0;
88
78
  const topSeats = Array.from({ length: seatCountPerSide }, (_, i) => ({
89
79
  cx: startX + i * spacing,
90
- cy: y - seatRadius * 1.5,
80
+ cy: y - seatRadius * 1.5 + 50,
91
81
  }));
92
82
  const bottomSeats = Array.from({ length: seatCount - seatCountPerSide }, // in case it's odd
93
83
  (_, i) => ({
94
84
  cx: startX + i * spacing,
95
85
  cy: y + height + seatRadius * 1.5,
96
86
  }));
97
- return (_jsxs("g", { children: [_jsx("rect", Object.assign({ x: x, y: y, width: width, height: height }, commonProps)), _jsx("g", { fill: "#e6b9c0", fillOpacity: "0.5", stroke: "#c49ba3", strokeWidth: "1", children: [...topSeats, ...bottomSeats].map(({ cx, cy }, i) => (_jsx("circle", { cx: cx, cy: cy, r: seatRadius }, `${id}-seat-${i}`))) }, `${id}-seats`)] }, id));
87
+ return (_jsxs("g", { children: [_jsx("g", { fill: "#e6b9c0", fillOpacity: "0.5", stroke: "#c49ba3", strokeWidth: "1", children: [...topSeats, ...bottomSeats].map(({ cx, cy }, i) => (_jsx("circle", { cx: cx, cy: cy, r: seatRadius }, `${id}-seat-${i}`))) }, `${id}-seats`), _jsx("rect", Object.assign({ x: x, y: y, width: width, height: height }, commonProps))] }, id));
98
88
  }
99
89
  case "text":
100
90
  return (_jsxs("g", { onClick: () => {
@@ -107,8 +97,8 @@ onTouchStart, }) => {
107
97
  }
108
98
  };
109
99
  const renderShape = (item) => {
110
- var _a;
111
- const { id, x, y, width, height, fill, opacity, rotation = 0, shape, text, stroke, strokeWidth, labels, fontSize, fontColor, label, seatFill, src, points, } = item;
100
+ var _a, _b, _c, _d, _e, _f;
101
+ const { id, x, y, width, height, fill, opacity, rotation = 0, shape, text, stroke, strokeWidth, labels, fontSize, fontColor, label, seatFill, src, points, transform, seatPositions, } = item;
112
102
  const commonProps = {
113
103
  fill,
114
104
  opacity,
@@ -143,7 +133,7 @@ onTouchStart, }) => {
143
133
  // },
144
134
  onTouchStart: (e) => {
145
135
  // e.stopPropagation();
146
- onTouchStart === null || onTouchStart === void 0 ? void 0 : onTouchStart(e, item);
136
+ // onTouchStart?.(e, item);
147
137
  },
148
138
  // onTouchEnd: (
149
139
  // e: React.TouchEvent<
@@ -160,116 +150,250 @@ onTouchStart, }) => {
160
150
  };
161
151
  switch (shape) {
162
152
  case "square":
153
+ return (_jsx("g", { "data-id": id,
154
+ // data-table={JSON.stringify(item)}
155
+ transform: `translate(${x}, ${y})`, stroke: "red", children: _jsxs("g", { transform: `rotate(${rotation}, 0, 0)`, children: [_createElement("rect", Object.assign({}, commonProps, { key: id, width: width, height: height })), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
156
+ var _a, _b, _c, _d;
157
+ 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: `rotate(${rotation} ${x + width / 2} ${y + height / 2})`, onClick: (e) => {
158
+ e.stopPropagation();
159
+ onClick && onClick(item);
160
+ } }), _ === null || _ === void 0 ? void 0 : _.text));
161
+ })] }) }, id));
163
162
  case "polygon":
163
+ function isPolygonClosed(points) {
164
+ if (points.length < 3)
165
+ return false;
166
+ const first = points[0];
167
+ const last = points[points.length - 1];
168
+ return first.x === last.x && first.y === last.y;
169
+ }
170
+ const finalPoint = points.map((p) => `${p.x},${p.y}`).join(" ");
171
+ const isClosed = isPolygonClosed(points);
172
+ console.log({ isClosed });
173
+ const showPoints = (selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.id) == id;
174
+ return (_jsx("g", { "data-id": id, transform: `translate(${x}, ${y})`, children: _jsxs("g", { transform: `rotate(${rotation}, 0, 0)`, children: [_createElement("polygon", Object.assign({}, commonProps, { key: id, points: finalPoint, x: "0", y: "0" })), (showPoints || !isClosed) &&
175
+ points.map((_, index) => {
176
+ return (_jsxs(_Fragment, { children: [_jsx("rect", { "data-point": JSON.stringify(_), id: `${index}`, x: (_ === null || _ === void 0 ? void 0 : _.x) - 5, y: (_ === null || _ === void 0 ? void 0 : _.y) - 5, width: 10, height: 10, fill: "#4a90e2", cursor: "pointer" }, `${id}-point-${index}`), _jsx("circle", { "data-point": JSON.stringify(_), id: `${index}`, cx: _ === null || _ === void 0 ? void 0 : _.x, cy: _ === null || _ === void 0 ? void 0 : _.y, r: 15, fill: "transparent", cursor: "pointer" }, `${id}-point-${index}`)] }));
177
+ })] }) }, id));
178
+ case "selection-box":
164
179
  const pointsFormat = !isEmpty(points)
165
180
  ? points
166
181
  : rectToPolygonPoints(x, y, width, height);
167
- return (_jsx("g", { children: _createElement("polygon", Object.assign({}, commonProps, { key: id, points: pointsFormat })) }, id));
168
- // return (
169
- // <g key={id}>
170
- // <rect
171
- // key={id}
172
- // x={x}
173
- // y={y}
174
- // width={width}
175
- // height={height}
176
- // fill={selectedTableColor ?? fill}
177
- // style={{
178
- // cursor: mode === "view" ? "pointer" : "default",
179
- // ...style,
180
- // }}
181
- // opacity={id === selectedComponent?.id ? 0.5 : opacity}
182
- // {...omit(commonProps, "opacity")}
183
- // transform={`rotate(${rotation} ${x + width / 2} ${
184
- // y + height / 2
185
- // })`}
186
- // />
187
- // {labels?.map((_: any, index: number) => {
188
- // return (
189
- // <text
190
- // {...omit(commonProps, ["opacity", "stroke", "strokeWidth"])}
191
- // key={`${id}-label-${index}`}
192
- // x={x + width / 2 + (_?.x ?? 0)}
193
- // y={y + height / 2 + (_?.y ?? 0)}
194
- // fill={_?.fontColor ?? "black"}
195
- // fontSize={`${_?.fontSize ?? 10}px`}
196
- // fontWeight="bold"
197
- // textAnchor="middle"
198
- // dominantBaseline="middle"
199
- // transform={`rotate(${rotation} ${x + width / 2} ${
200
- // y + height / 2
201
- // })`}
202
- // onClick={(e) => {
203
- // e.stopPropagation();
204
- // onClick&& onClick(item);
205
- // }}
206
- // >
207
- // {_?.label}
208
- // </text>
209
- // );
210
- // })}
211
- // </g>
212
- // );
182
+ return (_jsx("g", { "data-table": JSON.stringify(item), "data-id": id, children: _jsxs("g", { transform: `rotate(${rotation} ${x + width / 2} ${y + height / 2})`, children: [_createElement("polygon", Object.assign({}, commonProps, { key: id, points: pointsFormat })), points.map((_, index) => {
183
+ return (_jsx("rect", { x: (_ === null || _ === void 0 ? void 0 : _.x) - 5, y: (_ === null || _ === void 0 ? void 0 : _.y) - 5, width: 10, height: 10, fill: "blue" }, `${id}-point-${index}`));
184
+ }), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
185
+ var _a, _b, _c, _d;
186
+ 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: `rotate(${rotation} ${x + width / 2} ${y + height / 2})`, onClick: (e) => {
187
+ e.stopPropagation();
188
+ onClick && onClick(item);
189
+ } }), _ === null || _ === void 0 ? void 0 : _.label));
190
+ })] }) }, id));
213
191
  case "circle":
214
- return (_jsxs("g", { children: [_jsx("circle", Object.assign({ cx: x + width / 2, cy: y + height / 2, r: Math.min(width, height) / 2, style: Object.assign({ cursor: mode === "view" ? "pointer" : "default" }, style), fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill, opacity: id === (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id) ? 0.5 : opacity }, omit(commonProps, "opacity")), id), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
215
- var _a, _b, _c, _d;
216
- 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: `rotate(${rotation} ${x + width / 2} ${y + height / 2})`, onClick: (e) => {
217
- e.stopPropagation();
218
- onClick && onClick(item);
219
- }, children: _ === null || _ === void 0 ? void 0 : _.label }, `${id}-label-${index}`));
220
- })] }, id));
192
+ return (_jsx("g", { "data-id": id, transform: `translate(${x}, ${y})`, children: _jsxs("g", { transform: `rotate(${rotation}, 0, 0)`, children: [_jsx("circle", Object.assign({ cx: width / 2, cy: height / 2, r: Math.min(height, width) / 2, style: Object.assign({ cursor: mode === "view" ? "pointer" : "default" }, style), fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill }, omit(commonProps, "opacity")), id), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
193
+ var _a, _b, _c, _d;
194
+ return (_jsx("text", { x: width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0), y: width / 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: `rotate(${rotation} ${x + width / 2} ${y + height / 2})`, onClick: (e) => {
195
+ e.stopPropagation();
196
+ onClick && onClick(item);
197
+ }, children: _ === null || _ === void 0 ? void 0 : _.label }, `${id}-label-${index}`));
198
+ })] }) }, id));
199
+ // case "elipse":
200
+ // return (
201
+ // <g
202
+ // key={id}
203
+ // id={id}
204
+ // transform={`translate(${x}, ${y})`}
205
+ // >
206
+ // <g transform={`rotate(${rotation}, 0, 0)`}>
207
+ // <ellipse
208
+ // key={id}
209
+ // cx={width / 2}
210
+ // cy={height / 2}
211
+ // rx={width / 2}
212
+ // ry={height / 2}
213
+ // style={{
214
+ // cursor: mode === "view" ? "pointer" : "default",
215
+ // ...style,
216
+ // }}
217
+ // // transform={transform}
218
+ // fill={selectedTableColor ?? fill}
219
+ // {...omit(commonProps, ["opacity","x","y","height","width"])}
220
+ // />
221
+ // {labels?.map((_: any, index: number) => {
222
+ // return (
223
+ // <text
224
+ // key={`${id}-label-${index}`}
225
+ // x={width / 2 + (_?.x ?? 0)}
226
+ // y={width / 2 + (_?.y ?? 0)}
227
+ // fill={_?.fontColor ?? "black"}
228
+ // fontSize={`${_?.fontSize ?? 10}px`}
229
+ // fontWeight="bold"
230
+ // textAnchor="middle"
231
+ // dominantBaseline="middle"
232
+ // transform={`rotate(${rotation} ${width / 2} ${
233
+ // height / 2
234
+ // })`}
235
+ // onClick={(e) => {
236
+ // e.stopPropagation();
237
+ // onClick && onClick(item);
238
+ // }}
239
+ // >
240
+ // {_?.label}
241
+ // </text>
242
+ // );
243
+ // })}
244
+ // </g>
245
+ // </g>
246
+ // );
221
247
  case "diamond":
222
- return (_jsxs("g", { children: [_jsx("rect", Object.assign({ x: x, y: y, width: width, height: height, style: Object.assign({ cursor: mode === "view" ? "pointer" : "default" }, style), transform: `rotate(${rotation}, ${x}, ${y})` }, commonProps, { fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill }), id), _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));
248
+ return (_jsxs("g", { "data-table": JSON.stringify(item), children: [_jsx("rect", Object.assign({ x: x, y: y, width: width, height: height, style: Object.assign({ cursor: mode === "view" ? "pointer" : "default" }, style), transform: `rotate(${rotation}, ${x}, ${y})` }, commonProps, { fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill }), id), _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));
223
249
  case "table-seat-circle": {
224
250
  const seatCount = item.seatCount;
225
251
  const openSpace = (_a = item.openSpace) !== null && _a !== void 0 ? _a : 0;
226
- const centerX = x + width / 2;
227
- const centerY = y + height / 2;
228
- const baseSize = Math.min(width, height);
229
- const radius = baseSize / 2; // jarak kursi dari pusat
230
- const seatRadius = baseSize / 6; // ukuran kursi
231
- const fullAngle = 2 * Math.PI;
252
+ // LOCAL SPACE (tanpa x,y)
253
+ const centerX = width / 2;
254
+ const centerY = height / 2;
255
+ // meja
256
+ const tableRadius = Math.min(width, height) / 2;
257
+ // seat statis
258
+ const seatRadius = 10;
259
+ const fullAngle = Math.PI * 2;
232
260
  const availableAngle = fullAngle * (1 - openSpace);
233
261
  const angleStart = (fullAngle - availableAngle) / 2;
234
262
  const angleStep = availableAngle / seatCount;
235
- const seatInsetFactor = 0.3;
236
263
  const seatCircles = Array.from({ length: seatCount }, (_, i) => {
237
264
  const angle = angleStart + i * angleStep;
238
- const inset = seatRadius * seatInsetFactor; // default 0.3
239
- const cx = centerX + (radius - inset) * Math.cos(angle);
240
- const cy = centerY + (radius - inset) * Math.sin(angle);
265
+ const cx = centerX + (tableRadius + seatRadius) * Math.cos(angle);
266
+ const cy = centerY + (tableRadius + seatRadius) * Math.sin(angle);
241
267
  return { cx, cy };
242
268
  });
243
- return (_jsxs("g", { transform: `rotate(${rotation} ${centerX} ${centerY})`, children: [_jsx("circle", Object.assign({ cx: centerX, cy: centerY, r: radius - 15, fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill }, commonProps, { opacity: id === (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id) ? 0.5 : opacity })), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
244
- var _a, _b, _c, _d;
245
- return (_jsx("text", { x: centerX + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0), y: centerY + ((_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: `rotate(${rotation} ${centerX} ${centerY})`, onClick: (e) => {
246
- e.stopPropagation();
247
- onClick && onClick(item);
248
- }, children: _ === null || _ === void 0 ? void 0 : _.label }, `${id}-label-${index}`));
249
- }), _jsx("g", { fill: "#e6b9c0", opacity: id === (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id) ? 0.5 : opacity, stroke: "#c49ba3", strokeWidth: "1", children: seatCircles.map(({ cx, cy }, i) => (_jsx("circle", { cx: cx, cy: cy, r: seatRadius, fill: seatFill }, `${id}-seat-${i}`))) })] }, id));
269
+ return (_jsx("g", { "data-id": id, transform: `translate(${x}, ${y})`, children: _jsxs("g", { transform: `rotate(${rotation}, 0, 0)`, 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 }, `${id}-seat-${i}`))) }), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
270
+ var _a, _b, _c, _d;
271
+ return (_jsx("text", { x: centerX + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0), y: centerY + ((_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: `rotate(${rotation} ${centerX} ${centerY})`, onClick: (e) => {
272
+ e.stopPropagation();
273
+ onClick && onClick(item);
274
+ }, children: _ === null || _ === void 0 ? void 0 : _.label }, `${id}-label-${index}`));
275
+ })] }) }, id));
250
276
  }
251
277
  case "table-seat-square": {
252
- const seatCount = item.seatCount || 6;
253
278
  const openSpace = item.openSpace || 0; // from 0 to 0.9
254
- const seatRadius = width / 6;
279
+ const r = 10;
280
+ const seatPositions = item.seatPositions;
281
+ const topCount = (_b = seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.top) !== null && _b !== void 0 ? _b : 0;
282
+ const bottomCount = (_c = seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.bottom) !== null && _c !== void 0 ? _c : 0;
283
+ const leftCount = (_d = seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.left) !== null && _d !== void 0 ? _d : 0;
284
+ const rightCount = (_e = seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.right) !== null && _e !== void 0 ? _e : 0;
255
285
  // split seats evenly on top and bottom
256
- const seatCountPerSide = Math.ceil(seatCount / 2);
286
+ const seatCountTopBottom = Math.ceil(Math.max(topCount, bottomCount) / 2);
287
+ const seatCountLeftRight = Math.ceil(Math.max(leftCount, rightCount) / 2);
257
288
  const availableWidth = width * (1 - openSpace);
258
- const startX = x + (width * openSpace) / 2;
259
- const spacing = seatCountPerSide > 1 ? availableWidth / (seatCountPerSide - 1) : 0;
260
- const topSeats = Array.from({ length: seatCountPerSide }, (_, i) => ({
261
- cx: startX + i * spacing,
262
- cy: y - seatRadius * 1.5,
289
+ const availableHeight = height * (1 - openSpace);
290
+ const spacingWidth = availableWidth / seatCountTopBottom;
291
+ const spacingHeight = availableHeight / seatCountLeftRight;
292
+ const topXs = distributeWithSpacing({
293
+ start: x,
294
+ length: width,
295
+ count: topCount,
296
+ radius: r,
297
+ spacing: spacingWidth,
298
+ });
299
+ const topSeats = topXs.map((cx) => ({ cx, cy: y - r, id: "top" }));
300
+ // TOP
301
+ const bottomSeats = distributeWithSpacing({
302
+ start: x,
303
+ length: width,
304
+ count: bottomCount,
305
+ radius: r,
306
+ spacing: spacingWidth,
307
+ }).map((cx) => ({
308
+ cx: cx,
309
+ cy: y + height + r,
310
+ id: "bottom",
263
311
  }));
264
- const bottomSeats = Array.from({ length: seatCount - seatCountPerSide }, // in case it's odd
265
- (_, i) => ({
266
- cx: startX + i * spacing,
267
- cy: y + height + seatRadius * 1.5,
312
+ const leftYs = distributeWithSpacing({
313
+ start: y,
314
+ length: height,
315
+ count: leftCount,
316
+ radius: r,
317
+ spacing: spacingHeight,
318
+ });
319
+ const leftSeats = leftYs.map((cy) => ({ cx: x - r, cy, id: "left" }));
320
+ const rightSeats = distributeWithSpacing({
321
+ start: y,
322
+ length: height,
323
+ count: rightCount,
324
+ radius: r,
325
+ spacing: spacingHeight,
326
+ }).map((cy) => ({
327
+ cx: x + width + r,
328
+ cy,
329
+ id: "right",
268
330
  }));
269
- return (_jsxs("g", { transform: `rotate(${rotation}, ${x}, ${y})`, children: [_jsx("rect", Object.assign({ x: x, y: y, style: Object.assign({ cursor: mode === "view" ? "pointer" : "default" }, style), width: width, height: height }, commonProps, { fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill })), _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 }), _jsx("g", { fill: "#e6b9c0", fillOpacity: "0.5", stroke: "#c49ba3", strokeWidth: "1", children: [...topSeats, ...bottomSeats].map(({ cx, cy }, i) => (_jsx("circle", { cx: cx, cy: cy, r: seatRadius }, `${id}-seat-${i}`))) }, `${id}-seats`)] }, id));
331
+ return (_jsx("g", { "data-id": id, transform: `translate(${x}, ${y})`, children: _jsxs("g", { transform: `rotate(${rotation}, 0, 0)`, children: [_jsx("rect", Object.assign({ width: width, height: height }, commonProps, { fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill })), _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));
332
+ }
333
+ case "table-seat-square-side": {
334
+ const seatRadius = Math.min(width, height) * 0.15;
335
+ const top = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.top) || 0;
336
+ const right = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.right) || 0;
337
+ const bottom = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.bottom) || 0;
338
+ const left = (seatPositions === null || seatPositions === void 0 ? void 0 : seatPositions.left) || 0;
339
+ const topSeats = distributeWithSpacing({
340
+ start: x,
341
+ length: width,
342
+ count: top,
343
+ radius: seatRadius,
344
+ }).map((cx) => ({ cx, cy: y - seatRadius * 0.1, id: "top" }));
345
+ console.log({ topSeats });
346
+ const bottomSeats = distributeWithSpacing({
347
+ start: x,
348
+ length: width,
349
+ count: bottom,
350
+ radius: seatRadius,
351
+ }).map((cx) => ({ cx, cy: y + height + seatRadius * 0.1, id: "bottom" }));
352
+ const leftSeats = distributeWithSpacing({
353
+ start: y,
354
+ length: height,
355
+ count: left,
356
+ radius: seatRadius,
357
+ }).map((cy) => ({ cx: x - seatRadius * 0.1, cy, id: "left" }));
358
+ const rightSeats = distributeWithSpacing({
359
+ start: y,
360
+ length: height,
361
+ count: right,
362
+ radius: seatRadius,
363
+ }).map((cy) => ({ cx: x + width + seatRadius * 0.1, cy, id: "right" }));
364
+ const seats = (_f = [
365
+ ...topSeats,
366
+ ...bottomSeats,
367
+ ...leftSeats,
368
+ ...rightSeats,
369
+ ]) === null || _f === void 0 ? void 0 : _f.map(seat => (Object.assign(Object.assign({}, seat), { d: arcByDirection({ cx: seat.cx, cy: seat.cy, r: seatRadius, direction: seat.id, fraction: 0.4 }) })));
370
+ // console.log("seats", seats);
371
+ // const seats = [
372
+ // // TOP (tengah)
373
+ // {
374
+ // cx: x + width / 2,
375
+ // cy: y - seatRadius * 0.1,
376
+ // },
377
+ // // RIGHT (tengah)
378
+ // {
379
+ // cx: x + width + seatRadius * 0.1,
380
+ // cy: y + height / 2,
381
+ // },
382
+ // // BOTTOM (tengah)
383
+ // {
384
+ // cx: x + width / 2,
385
+ // cy: y + height + seatRadius * 0.1,
386
+ // },
387
+ // // LEFT (tengah)
388
+ // {
389
+ // cx: x - seatRadius * 0.1,
390
+ // cy: y + height / 2,
391
+ // },
392
+ // ];
393
+ return (_jsx("g", { transform: `translate(${x}, ${y}) )`, "data-id": id, children: _jsxs("g", { transform: `rotate(${rotation}, 0, 0)`, children: [_jsx("rect", Object.assign({ x: x, y: y, width: width, height: height, rx: 10 }, commonProps, { fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill })), _jsx("g", { children: seats === null || seats === void 0 ? void 0 : seats.map(({ d }, i) => (_jsx("path", { id: `seat-${id}`, d: d, fill: "white" }, `${id}-seat-${i}`))) }), _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));
270
394
  }
271
395
  case "text":
272
- return (_jsxs("g", { children: [_jsx("rect", { x: x, y: y, width: width, height: height, fill: "transparent", opacity: opacity, onClick: (e) => {
396
+ return (_jsxs("g", { "data-table": JSON.stringify(item), children: [_jsx("rect", { x: x, y: y, width: width, height: height, fill: "transparent", opacity: opacity, onClick: (e) => {
273
397
  e.stopPropagation();
274
398
  onClick && onClick(item);
275
399
  } }), _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));
@@ -277,7 +401,7 @@ onTouchStart, }) => {
277
401
  case "background":
278
402
  return (_jsxs("g", { onClick: () => {
279
403
  onClick && onClick(item);
280
- }, children: [_jsx("image", Object.assign({ href: src, x: x, y: y, width: width, height: height, transform: `rotate(${rotation} ${x + width / 2} ${y + height / 2})` }, commonProps)), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
404
+ }, "data-table": JSON.stringify(item), children: [_jsx("image", Object.assign({ href: src, x: x, y: y, width: width, height: height, transform: `rotate(${rotation} ${x + width / 2} ${y + height / 2})` }, commonProps)), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
281
405
  var _a, _b, _c, _d;
282
406
  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: `rotate(${rotation} ${x + width / 2} ${y + height / 2})`, children: _ === null || _ === void 0 ? void 0 : _.label }, index));
283
407
  })] }, id));
@@ -286,14 +410,15 @@ onTouchStart, }) => {
286
410
  }
287
411
  };
288
412
  let date = new Date();
289
- const nodesRaw = !isEmpty(selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.nodes) && isArray(selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.nodes)
290
- ? selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.nodes
291
- : rectToPolygonNodes(selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.x, selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.y, selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.width, selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.height);
413
+ const nodesRaw = !isEmpty(selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.nodes) && isArray(selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.nodes)
414
+ ? selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.nodes
415
+ : rectToPolygonNodes(selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.x, selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.y, selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.width, selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.height);
416
+ const points = selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.points;
292
417
  const polylinePoints = [...nodesRaw, nodesRaw[0]]
293
418
  .map((n) => `${n.x},${n.y}`)
294
419
  .join(" ");
295
- return (_jsxs("g", { children: [components === null || components === void 0 ? void 0 : components.map(renderShape), shadowShape === null || shadowShape === void 0 ? void 0 : shadowShape.map(renderShadowShape), selectedComponent && activeTool === "select" && (_jsxs(_Fragment, { children: [nodesRaw.map((p1, index) => {
296
- const p2 = nodesRaw[(index + 1) % nodesRaw.length]; // sisi berikutnya (wrap ke awal)
420
+ return (_jsxs("g", { id: "selection-layer", children: [components === null || components === void 0 ? void 0 : components.map(renderShape), shadowShape === null || shadowShape === void 0 ? void 0 : shadowShape.map(renderShadowShape), !isEmpty(selectionLines) && activeTool === "select" && (_jsxs(_Fragment, { children: [nodesRaw.map((p1, index) => {
421
+ const p2 = nodesRaw[(index + 2) % nodesRaw.length];
297
422
  const side = index === 0
298
423
  ? "top"
299
424
  : index === 1
@@ -301,37 +426,95 @@ onTouchStart, }) => {
301
426
  : index === 2
302
427
  ? "bottom"
303
428
  : "left";
304
- return (_jsx("polyline", { points: `${p1.x},${p1.y} ${p2.x},${p2.y}`, fill: "none", stroke: "transparent", strokeWidth: 5, className: clsx([
305
- {
306
- "cursor-ns-resize": side === "top" || side === "bottom",
307
- "cursor-ew-resize": side === "left" || side === "right",
308
- },
309
- ]), onMouseDown: (e) => {
310
- e.stopPropagation();
311
- if (side === "top" || side === "bottom") {
312
- onMouseDown(e, selectedComponent, side); // misal "top" / "bottom"
313
- }
314
- else if (side === "left" || side === "right") {
315
- onMouseDown(e, selectedComponent, side);
316
- }
317
- } }, index));
318
- }), nodesRaw === null || nodesRaw === void 0 ? void 0 : nodesRaw.map((node, index) => {
319
- const corner = index === 0
320
- ? "top-left"
321
- : index === 1
322
- ? "top-right"
323
- : index === 2
324
- ? "bottom-right"
325
- : "bottom-left";
326
- return (_jsx("rect", { x: node.x - 10, y: node.y - 10, width: 20, height: 20, fill: "transparent", className: clsx([
327
- {
328
- "cursor-nwse-resize": corner === "top-left" || corner === "bottom-right",
329
- "cursor-nesw-resize": corner === "top-right" || corner === "bottom-left",
330
- },
331
- ]), onMouseDown: (e) => {
332
- e.stopPropagation();
333
- onMouseDown(e, selectedComponent, corner);
334
- } }, index));
335
- }), _jsx("polyline", { points: polylinePoints, fill: "none", stroke: "blue", strokeWidth: 1 })] }))] }, `${date}`));
429
+ const mx = (p1.x + p2.x) / 2;
430
+ const my = (p1.y + p2.y) / 2;
431
+ if (side === "top")
432
+ return (_jsx("g", { id: "help-group-0", "data-selection": `selection-${selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id}`, transform: `translate(${selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.x},${selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.y})`, children: _jsx("g", { transform: `rotate(${(selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.rotation) || 0}, 0,0)`, children: side === "top" && (_jsxs("g", { id: "help-group-1", children: [_jsx("line", { x1: mx, y1: my + selectionLines.height / 2, x2: mx, y2: my - selectionLines.height / 3 - 10, stroke: "#4a90e2", strokeWidth: 2, id: "line-help" }), _jsx("circle", { id: "circle-help", "data-role": "rotate", cx: mx, cy: my - selectionLines.height / 3 - 10, r: 8, fill: "#4a90e2" })] })) }) }, `selection-${date}`));
433
+ }), _jsx("g", { id: "selection-lines", "data-selection": `selection-${(_a = selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id) !== null && _a !== void 0 ? _a : selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.id}`, transform: `translate(${selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.x},${selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.y})`, children: _jsxs("g", { transform: `rotate(${(selectionLines === null || selectionLines === void 0 ? void 0 : selectionLines.rotation) || 0}, 0,0)`, children: [!hasPoints && (_jsx("rect", { width: selectionLines.width, height: selectionLines.height, fill: "none", stroke: "#4a90e2", strokeWidth: 1, id: "rect-box-selection" })), !hasPoints &&
434
+ (nodesRaw === null || nodesRaw === void 0 ? void 0 : nodesRaw.map((node, index) => {
435
+ const corner = (index) => {
436
+ switch (index) {
437
+ case 0:
438
+ return "top-left";
439
+ case 1:
440
+ return "top";
441
+ case 2:
442
+ return "top-right";
443
+ case 3:
444
+ return "right";
445
+ case 4:
446
+ return "bottom-right";
447
+ case 5:
448
+ return "bottom";
449
+ case 6:
450
+ return "bottom-left";
451
+ case 7:
452
+ return "left";
453
+ }
454
+ };
455
+ return (_jsxs(_Fragment, { children: [_jsx("circle", { "data-position": corner(index), r: 5, cx: node.x, cy: node.y, fill: "transparent", style: { cursor: "pointer" } }, index), _jsx("circle", { "data-position": corner(index), r: 5, cx: node.x, cy: node.y, fill: "#4a90e2", id: `circle-corner-${selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id}`, style: { cursor: "pointer" } }, index)] }));
456
+ }))] }) }, `selection-${date}`)] }))] }, `${date}`));
336
457
  };
337
458
  export default Layers;
459
+ export function rectToPolygonNodes(x, y, width, height) {
460
+ const points = [
461
+ { x: 0, y: 0 },
462
+ { x: 0 + width / 2, y: 0 },
463
+ { x: 0 + width, y: 0 },
464
+ { x: 0 + width, y: 0 + height / 2 },
465
+ { x: 0 + width, y: 0 + height },
466
+ { x: 0 + width / 2, y: 0 + height },
467
+ { x: 0, y: 0 + height },
468
+ { x: 0, y: 0 + height / 2 },
469
+ ];
470
+ return points;
471
+ }
472
+ export function distributeWithSpacing({ start, length, count, radius, spacing, }) {
473
+ if (count === 0)
474
+ return [];
475
+ // ✅ satu seat → selalu center
476
+ if (count === 1) {
477
+ return [start + length / 2];
478
+ }
479
+ const usable = length - 2 * radius;
480
+ // spacing default = bagi penuh
481
+ const defaultSpacing = usable / (count - 1);
482
+ const s = spacing != null ? Math.min(spacing, defaultSpacing) : defaultSpacing;
483
+ // total panjang seat berdasarkan spacing
484
+ const total = (count - 1) * s;
485
+ // start supaya CENTERED
486
+ const offset = (usable - total) / 2;
487
+ return Array.from({ length: count }, (_, i) => start + radius + offset + i * s);
488
+ }
489
+ // utils/svgPath.ts
490
+ // utils/svgArc.ts
491
+ export const arcByDirection = ({ cx, cy, r, direction = "top", fraction = 0.5, }) => {
492
+ const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
493
+ const frac = clamp(fraction, 0.01, 1);
494
+ const sweep = 360 * frac;
495
+ // angle tengah untuk tiap direction
496
+ const centerAngleMap = {
497
+ top: -90,
498
+ right: 0,
499
+ bottom: 90,
500
+ left: 180,
501
+ };
502
+ const centerAngle = centerAngleMap[direction];
503
+ const startAngle = centerAngle - sweep / 2;
504
+ const endAngle = centerAngle + sweep / 2;
505
+ const rad = (deg) => (deg * Math.PI) / 180;
506
+ const start = {
507
+ x: cx + r * Math.cos(rad(startAngle)),
508
+ y: cy + r * Math.sin(rad(startAngle)),
509
+ };
510
+ const end = {
511
+ x: cx + r * Math.cos(rad(endAngle)),
512
+ y: cy + r * Math.sin(rad(endAngle)),
513
+ };
514
+ const largeArcFlag = sweep > 180 ? 1 : 0;
515
+ const sweepFlag = 1;
516
+ return `
517
+ M ${start.x} ${start.y}
518
+ A ${r} ${r} 0 ${largeArcFlag} ${sweepFlag} ${end.x} ${end.y}
519
+ `;
520
+ };