seat-editor 3.0.0 → 3.0.2

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 (100) hide show
  1. package/dist/app/layout.d.ts +1 -1
  2. package/dist/app/{layout.js → layout.jsx} +7 -2
  3. package/dist/app/new-board/page.d.ts +1 -1
  4. package/dist/app/new-board/page.jsx +55 -0
  5. package/dist/app/old-board/page.d.ts +2 -1
  6. package/dist/app/old-board/{page.js → page.jsx} +215 -82
  7. package/dist/app/only-view/chair.d.ts +1 -1
  8. package/dist/app/only-view/chair.js +10 -2
  9. package/dist/app/only-view/page.d.ts +1 -1
  10. package/dist/app/only-view/page.jsx +101 -0
  11. package/dist/app/only-view/user.d.ts +1 -1
  12. package/dist/app/only-view/user.js +10 -2
  13. package/dist/app/page.d.ts +1 -1
  14. package/dist/app/page.jsx +13 -0
  15. package/dist/app/test/page.d.ts +2 -1
  16. package/dist/app/test/{page.js → page.jsx} +5 -3
  17. package/dist/app/v2/page.d.ts +1 -1
  18. package/dist/app/v2/page.jsx +13 -0
  19. package/dist/components/button-tools/index.d.ts +1 -1
  20. package/dist/components/button-tools/index.jsx +17 -0
  21. package/dist/components/form-tools/label.d.ts +1 -1
  22. package/dist/components/form-tools/label.jsx +44 -0
  23. package/dist/components/form-tools/shape.d.ts +1 -1
  24. package/dist/components/form-tools/shape.jsx +66 -0
  25. package/dist/components/input/number-indicator.d.ts +1 -1
  26. package/dist/components/input/{number-indicator.js → number-indicator.jsx} +11 -2
  27. package/dist/components/joystick/index.d.ts +2 -1
  28. package/dist/components/joystick/{index.js → index.jsx} +14 -13
  29. package/dist/components/layer/index.d.ts +1 -1
  30. package/dist/components/layer/index.jsx +383 -0
  31. package/dist/components/layer-v2/index.d.ts +1 -1
  32. package/dist/components/layer-v2/index.jsx +370 -0
  33. package/dist/components/layer-v3/index.d.ts +1 -1
  34. package/dist/components/layer-v3/{index.js → index.jsx} +242 -102
  35. package/dist/components/layer-v4/index.d.ts +1 -1
  36. package/dist/components/layer-v4/{index.js → index.jsx} +157 -80
  37. package/dist/components/lib/index.d.ts +1 -1
  38. package/dist/components/lib/{index.js → index.jsx} +7 -2
  39. package/dist/components/modal-preview/index.d.ts +1 -1
  40. package/dist/components/modal-preview/index.jsx +11 -0
  41. package/dist/features/board/index.d.ts +1 -1
  42. package/dist/features/board/{index.js → index.jsx} +90 -31
  43. package/dist/features/board-v2/index.d.ts +2 -1
  44. package/dist/features/board-v2/{index.js → index.jsx} +101 -39
  45. package/dist/features/board-v3/index copy.d.ts +2 -1
  46. package/dist/features/board-v3/{index copy.js → index copy.jsx } +128 -50
  47. package/dist/features/board-v3/index.d.ts +2 -1
  48. package/dist/features/board-v3/{index.js → index.jsx} +110 -32
  49. package/dist/features/navbar/index.d.ts +1 -1
  50. package/dist/features/navbar/index.jsx +5 -0
  51. package/dist/features/package/index.d.ts +1 -1
  52. package/dist/features/package/{index.js → index.jsx} +16 -6
  53. package/dist/features/panel/index.d.ts +1 -1
  54. package/dist/features/panel/{index.js → index.jsx} +25 -7
  55. package/dist/features/panel/select-tool.d.ts +1 -1
  56. package/dist/features/panel/{select-tool.js → select-tool.jsx} +23 -10
  57. package/dist/features/panel/selected-group.d.ts +1 -1
  58. package/dist/features/panel/selected-group.jsx +47 -0
  59. package/dist/features/panel/square-circle-tool.d.ts +1 -1
  60. package/dist/features/panel/{square-circle-tool.js → square-circle-tool.jsx} +4 -2
  61. package/dist/features/panel/table-seat-circle.d.ts +1 -1
  62. package/dist/features/panel/table-seat-circle.jsx +31 -0
  63. package/dist/features/panel/table-seat-square.d.ts +1 -1
  64. package/dist/features/panel/table-seat-square.jsx +46 -0
  65. package/dist/features/panel/text-tool.d.ts +1 -1
  66. package/dist/features/panel/text-tool.jsx +26 -0
  67. package/dist/features/panel/upload-tool.d.ts +1 -1
  68. package/dist/features/panel/{upload-tool.js → upload-tool.jsx} +24 -2
  69. package/dist/features/side-tool/index.d.ts +1 -1
  70. package/dist/features/side-tool/{index.js → index.jsx} +120 -98
  71. package/dist/features/view-only/index.d.ts +1 -1
  72. package/dist/features/view-only/{index.js → index.jsx} +38 -31
  73. package/dist/features/view-only-2/index.d.ts +1 -1
  74. package/dist/features/view-only-2/{index.js → index.jsx} +16 -13
  75. package/dist/features/view-only-3/index.d.ts +1 -1
  76. package/dist/features/view-only-3/{index.js → index.jsx} +46 -27
  77. package/dist/index.d.ts +2 -1
  78. package/dist/index.js +2 -1
  79. package/dist/provider/antd-provider.jsx +46 -0
  80. package/dist/provider/redux-provider.d.ts +1 -1
  81. package/dist/provider/{redux-provider.js → redux-provider.jsx} +1 -2
  82. package/dist/provider/store-provider.d.ts +1 -1
  83. package/dist/provider/{store-provider.js → store-provider.jsx} +3 -2
  84. package/package.json +1 -1
  85. package/dist/app/new-board/page.js +0 -33
  86. package/dist/app/only-view/page.js +0 -78
  87. package/dist/app/page.js +0 -8
  88. package/dist/app/v2/page.js +0 -8
  89. package/dist/components/button-tools/index.js +0 -11
  90. package/dist/components/form-tools/label.js +0 -7
  91. package/dist/components/form-tools/shape.js +0 -25
  92. package/dist/components/layer/index.js +0 -295
  93. package/dist/components/layer-v2/index.js +0 -282
  94. package/dist/components/modal-preview/index.js +0 -10
  95. package/dist/features/navbar/index.js +0 -6
  96. package/dist/features/panel/selected-group.js +0 -7
  97. package/dist/features/panel/table-seat-circle.js +0 -9
  98. package/dist/features/panel/table-seat-square.js +0 -9
  99. package/dist/features/panel/text-tool.js +0 -7
  100. package/dist/provider/antd-provider.js +0 -43
@@ -1,6 +1,4 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { createElement as _createElement } from "react";
4
2
  import { isEmpty, omit } from "lodash";
5
3
  import { TABLE_KEYS } from "@/utils/constant";
6
4
  import { distributeWithSpacing } from "../layer-v3";
@@ -85,23 +83,26 @@ const Layers = ({ components, selectedTable, iconTags, eventMatchTable, onHighli
85
83
  offsetSymbolY = size / 4;
86
84
  break;
87
85
  }
88
- return (_createElement("tspan", Object.assign({}, symbol, { key: `symbol-${tagIndex}-${i}`, x: posX + offsetSymbolX, y: posY + offsetSymbolY, textAnchor: "middle", dominantBaseline: "middle", transform: `rotate(${rotate} ${posX} ${posY})` }), symbol.value));
86
+ return (<tspan {...symbol} key={`symbol-${tagIndex}-${i}`} x={posX + offsetSymbolX} y={posY + offsetSymbolY} textAnchor="middle" dominantBaseline="middle" transform={`rotate(${rotate} ${posX} ${posY})`}>
87
+ {symbol.value}
88
+ </tspan>);
89
89
  };
90
90
  if (item.type === "icon") {
91
91
  const iconTag = iconTags === null || iconTags === void 0 ? void 0 : iconTags.find((icon) => icon.key === item.value);
92
92
  if (!iconTag)
93
93
  return null;
94
- return (_createElement("g", Object.assign({}, item, { key: `icon-${tagIndex}-${i}`, transform: `translate(${posX - 10}, ${posY - 10})` }), iconTag.icon));
94
+ return (<g {...item} key={`icon-${tagIndex}-${i}`} transform={`translate(${posX - 10}, ${posY - 10})`}>
95
+ {iconTag.icon}
96
+ </g>);
95
97
  }
96
98
  if (item.type === "text") {
97
- return (_createElement("text", Object.assign({}, item, { key: `text-${tagIndex}-${i}`, x: posX, y: posY, textAnchor: "middle", dominantBaseline: "middle", transform: `rotate(${rotate} ${posX} ${posY})` }),
98
- item.value,
99
- " ",
100
- renderSymbol(item === null || item === void 0 ? void 0 : item.symbol)));
99
+ return (<text {...item} key={`text-${tagIndex}-${i}`} x={posX} y={posY} textAnchor="middle" dominantBaseline="middle" transform={`rotate(${rotate} ${posX} ${posY})`}>
100
+ {item.value} {renderSymbol(item === null || item === void 0 ? void 0 : item.symbol)}
101
+ </text>);
101
102
  }
102
103
  return null;
103
104
  });
104
- return _jsx("g", { children: elements }, `group-${tagIndex}`);
105
+ return <g key={`group-${tagIndex}`}>{elements}</g>;
105
106
  });
106
107
  };
107
108
  let commonProps = {
@@ -185,93 +186,111 @@ const Layers = ({ components, selectedTable, iconTags, eventMatchTable, onHighli
185
186
  const transformRotate = `rotate(${rotate} ${x + width / 2} ${y + height / 2})`;
186
187
  switch (shape) {
187
188
  case "square":
188
- return (_jsxs("g", { "data-id": id, style: { pointerEvents: "all" }, onContextMenu: (e) => e.preventDefault(), onDragEnter: (e) => {
189
+ return (<g key={id}
190
+ // data-table={JSON.stringify(item)}
191
+ data-id={id} style={{ pointerEvents: "all" }} onContextMenu={(e) => e.preventDefault()} onDragEnter={(e) => {
189
192
  const group = e.currentTarget;
190
193
  highlightGroup(group, "dragenter");
191
- }, onDragOver: (e) => {
194
+ }} onDragOver={(e) => {
192
195
  e.preventDefault(); // agar drop diterima
193
- }, onDragLeave: (e) => {
196
+ }} onDragLeave={(e) => {
194
197
  const group = e.currentTarget;
195
198
  unhighlightGroup(group);
196
- }, onDrop: (e) => {
199
+ }} onDrop={(e) => {
197
200
  const group = e.currentTarget;
198
201
  // restore langsung dan reset
199
202
  forceRestoreGroup(group, "drop");
200
- }, onPointerOver: (e) => {
203
+ }} onPointerOver={(e) => {
201
204
  // e.preventDefault(); // penting
202
205
  const group = e.currentTarget;
203
206
  highlightGroup(group, "pointerover");
204
- }, onPointerOut: (e) => {
207
+ }} onPointerOut={(e) => {
205
208
  const group = e.currentTarget;
206
209
  unhighlightGroup(group);
207
- }, onPointerUp: (e) => {
210
+ }} onPointerUp={(e) => {
208
211
  const group = e.currentTarget;
209
212
  // restore langsung dan reset
210
213
  forceRestoreGroup(group, "pointerup");
211
- }, onPointerDown: (e) => {
214
+ }} onPointerDown={(e) => {
212
215
  const group = e.currentTarget;
213
216
  highlightGroup(group, "pointerdown");
214
- },
215
- // onPointerEnter={(e) => {
216
- // const group = e.currentTarget as SVGGElement;
217
- // highlightGroup(group, "pointerenter");
218
- // }}
219
- onPointerLeave: (e) => {
217
+ }}
218
+ // onPointerEnter={(e) => {
219
+ // const group = e.currentTarget as SVGGElement;
220
+ // highlightGroup(group, "pointerenter");
221
+ // }}
222
+ onPointerLeave={(e) => {
220
223
  const group = e.currentTarget;
221
224
  unhighlightGroup(group);
222
- }, onMouseEnter: (e) => {
225
+ }} onMouseEnter={(e) => {
223
226
  // e.preventDefault(); // penting
224
227
  const group = e.currentTarget;
225
228
  highlightGroup(group, "mouseenter");
226
- }, onMouseLeave: (e) => {
229
+ }} onMouseLeave={(e) => {
227
230
  const group = e.currentTarget;
228
231
  unhighlightGroup(group);
229
- }, children: [_jsx("rect", Object.assign({ x: x, y: y, width: width, height: height, fill: fill, className: "blink-2", transform: transformRotate }, omit(item, TABLE_KEYS), commonProps), `${id}-rect`), renderTags(tags), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
230
- var _a, _b, _c, _d;
231
- return (_createElement("text", Object.assign({}, omit(commonProps, ["opacity", "stroke", "strokeWidth"]), { key: `${id}-label-${index}`, x: x + width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0), y: y + height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0), fill: (_c = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _c !== void 0 ? _c : "black", fontSize: `${(_d = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _d !== void 0 ? _d : 10}px`, fontWeight: "bold", textAnchor: "middle", dominantBaseline: "middle", transform: transformRotate }, _), _ === null || _ === void 0 ? void 0 : _.label));
232
- })] }, id));
232
+ }}>
233
+ <rect key={`${id}-rect`} x={x} y={y} width={width} height={height} fill={fill} className="blink-2" transform={transformRotate} {...omit(item, TABLE_KEYS)} {...commonProps}/>
234
+
235
+ {renderTags(tags)}
236
+
237
+ {labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
238
+ var _a, _b, _c, _d;
239
+ return (<text {...omit(commonProps, ["opacity", "stroke", "strokeWidth"])} key={`${id}-label-${index}`} x={x + width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0)} y={y + height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0)} fill={(_c = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _c !== void 0 ? _c : "black"} fontSize={`${(_d = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _d !== void 0 ? _d : 10}px`} fontWeight="bold" textAnchor="middle" dominantBaseline="middle" transform={transformRotate} {..._}>
240
+ {_ === null || _ === void 0 ? void 0 : _.label}
241
+ </text>);
242
+ })}
243
+ </g>);
233
244
  case "circle":
234
- return (_jsxs("g", { style: { pointerEvents: "all" }, "data-id": id, onContextMenu: (e) => e.preventDefault(), onDragEnter: (e) => {
245
+ return (<g key={id} style={{ pointerEvents: "all" }}
246
+ // data-table={JSON.stringify(item)}
247
+ data-id={id} onContextMenu={(e) => e.preventDefault()} onDragEnter={(e) => {
235
248
  e.preventDefault(); // penting
236
249
  const group = e.currentTarget;
237
250
  highlightGroup(group, "dragenter");
238
- }, onDragOver: (e) => {
251
+ }} onDragOver={(e) => {
239
252
  e.preventDefault(); // agar drop diterima
240
- }, onDragLeave: (e) => {
253
+ }} onDragLeave={(e) => {
241
254
  const group = e.currentTarget;
242
255
  unhighlightGroup(group);
243
- }, onDrop: (e) => {
256
+ }} onDrop={(e) => {
244
257
  e.preventDefault();
245
258
  const group = e.currentTarget;
246
259
  // restore langsung dan reset
247
260
  forceRestoreGroup(group);
248
- }, onPointerOver: (e) => {
261
+ }} onPointerOver={(e) => {
249
262
  e.preventDefault(); // penting
250
263
  const group = e.currentTarget;
251
264
  highlightGroup(group, "pointerover");
252
- }, onPointerOut: (e) => {
265
+ }} onPointerOut={(e) => {
253
266
  const group = e.currentTarget;
254
267
  unhighlightGroup(group);
255
- }, onPointerUp: (e) => {
268
+ }} onPointerUp={(e) => {
256
269
  e.preventDefault();
257
270
  const group = e.currentTarget;
258
271
  // restore langsung dan reset
259
272
  forceRestoreGroup(group);
260
- }, onMouseDown: (e) => {
273
+ }} onMouseDown={(e) => {
261
274
  e.preventDefault();
262
275
  const group = e.currentTarget;
263
276
  highlightGroup(group, "mousedown");
264
- }, onMouseEnter: (e) => {
277
+ }} onMouseEnter={(e) => {
265
278
  // e.preventDefault(); // penting
266
279
  const group = e.currentTarget;
267
280
  highlightGroup(group, "mouseenter");
268
- }, onMouseLeave: (e) => {
281
+ }} onMouseLeave={(e) => {
269
282
  const group = e.currentTarget;
270
283
  unhighlightGroup(group);
271
- }, children: [_jsx("circle", Object.assign({ cx: x + width / 2, cy: y + height / 2, r: width / 2 }, commonProps), id), renderTags(tags), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
272
- var _a, _b, _c, _d;
273
- return (_jsx("text", { x: x + width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0), y: y + height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0), fill: (_c = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _c !== void 0 ? _c : "black", fontSize: `${(_d = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _d !== void 0 ? _d : 10}px`, fontWeight: "bold", textAnchor: "middle", dominantBaseline: "middle", transform: transformRotate, children: _ === null || _ === void 0 ? void 0 : _.label }, `${id}-label-${index}`));
274
- })] }, id));
284
+ }}>
285
+ <circle key={id} cx={x + width / 2} cy={y + height / 2} r={width / 2} {...commonProps}/>
286
+ {renderTags(tags)}
287
+ {labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
288
+ var _a, _b, _c, _d;
289
+ 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}>
290
+ {_ === null || _ === void 0 ? void 0 : _.label}
291
+ </text>);
292
+ })}
293
+ </g>);
275
294
  case "table-seat-circle": {
276
295
  const seatCount = item.seatCount;
277
296
  const openSpace = (_a = item.openSpace) !== null && _a !== void 0 ? _a : 0;
@@ -292,50 +311,76 @@ const Layers = ({ components, selectedTable, iconTags, eventMatchTable, onHighli
292
311
  const cy = centerY + (tableRadius + seatRadius) * Math.sin(angle);
293
312
  return { cx, cy };
294
313
  });
295
- return (_jsxs("g", { style: { pointerEvents: "all" }, "data-id": id, transform: `translate(${x}, ${y})`,
296
- // data-table={JSON.stringify(item)}
297
- // data-id={id}
298
- onContextMenu: (e) => e.preventDefault(), onDragEnter: (e) => {
314
+ return (<g key={id} style={{ pointerEvents: "all" }} data-id={id} transform={`translate(${x}, ${y})`}
315
+ // data-table={JSON.stringify(item)}
316
+ // data-id={id}
317
+ onContextMenu={(e) => e.preventDefault()} onDragEnter={(e) => {
299
318
  e.preventDefault(); // penting
300
319
  const group = e.currentTarget;
301
320
  highlightGroup(group, "dragenter");
302
- }, onDragOver: (e) => {
321
+ }} onDragOver={(e) => {
303
322
  e.preventDefault(); // agar drop diterima
304
- }, onDragLeave: (e) => {
323
+ }} onDragLeave={(e) => {
305
324
  const group = e.currentTarget;
306
325
  unhighlightGroup(group);
307
- }, onDrop: (e) => {
326
+ }} onDrop={(e) => {
308
327
  e.preventDefault();
309
328
  const group = e.currentTarget;
310
329
  // restore langsung dan reset
311
330
  forceRestoreGroup(group);
312
- }, onPointerOver: (e) => {
331
+ }} onPointerOver={(e) => {
313
332
  e.preventDefault(); // penting
314
333
  const group = e.currentTarget;
315
334
  highlightGroup(group, "pointerover");
316
- }, onPointerOut: (e) => {
335
+ }} onPointerOut={(e) => {
317
336
  const group = e.currentTarget;
318
337
  unhighlightGroup(group);
319
- }, onPointerUp: (e) => {
338
+ }} onPointerUp={(e) => {
320
339
  e.preventDefault();
321
340
  const group = e.currentTarget;
322
341
  // restore langsung dan reset
323
342
  forceRestoreGroup(group);
324
- }, onMouseDown: (e) => {
343
+ }} onMouseDown={(e) => {
325
344
  e.preventDefault();
326
345
  const group = e.currentTarget;
327
346
  highlightGroup(group, "mousedown");
328
- }, onMouseEnter: (e) => {
347
+ }} onMouseEnter={(e) => {
329
348
  // e.preventDefault(); // penting
330
349
  const group = e.currentTarget;
331
350
  highlightGroup(group, "mouseenter");
332
- }, onMouseLeave: (e) => {
351
+ }} onMouseLeave={(e) => {
333
352
  const group = e.currentTarget;
334
353
  unhighlightGroup(group);
335
- }, children: [_jsx("circle", Object.assign({ cx: centerX, cy: centerY, r: tableRadius, fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill }, commonProps)), _jsx("g", { "data-seat": `${id}-seats`, children: seatCircles.map(({ cx, cy }, i) => (_jsx("circle", { cx: cx, cy: cy, r: seatRadius, fill: seatFill || "white" }, `${id}-seat-${i}`))) }), renderTags(tags), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
336
- var _a, _b, _c, _d;
337
- return (_jsx("text", { x: x + width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0), y: y + height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0), fill: (_c = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _c !== void 0 ? _c : "black", fontSize: `${(_d = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _d !== void 0 ? _d : 10}px`, fontWeight: "bold", textAnchor: "middle", dominantBaseline: "middle", transform: transformRotate, children: _ === null || _ === void 0 ? void 0 : _.label }, `${id}-label-${index}`));
338
- })] }, id));
354
+ }}>
355
+ <circle cx={centerX} cy={centerY} r={tableRadius} fill={selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill} {...commonProps}/>
356
+ <g data-seat={`${id}-seats`}>
357
+ {seatCircles.map(({ cx, cy }, i) => (<circle key={`${id}-seat-${i}`} cx={cx} cy={cy} r={seatRadius} fill={seatFill || "white"}/>))}
358
+ </g>
359
+ {renderTags(tags)}
360
+
361
+ {labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
362
+ var _a, _b, _c, _d;
363
+ 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}>
364
+ {_ === null || _ === void 0 ? void 0 : _.label}
365
+ </text>);
366
+ })}
367
+ {/* <g
368
+ fill="#e6b9c0"
369
+ stroke="#c49ba3"
370
+ key={`${id}-seats`}
371
+ strokeWidth="1"
372
+ >
373
+ {seatCircles.map(({ cx, cy }, i) => (
374
+ <circle
375
+ key={`${id}-seat-${i}`}
376
+ cx={cx}
377
+ cy={cy}
378
+ r={seatRadius}
379
+ fill={seatFill}
380
+ />
381
+ ))}
382
+ </g> */}
383
+ </g>);
339
384
  }
340
385
  case "table-seat-square": {
341
386
  const openSpace = item.openSpace || 0; // from 0 to 0.9
@@ -391,55 +436,87 @@ const Layers = ({ components, selectedTable, iconTags, eventMatchTable, onHighli
391
436
  cy,
392
437
  id: "right",
393
438
  }));
394
- return (_jsx("g", { "data-id": id, transform: `translate(${x}, ${y})`, children: _jsxs("g", { transform: `rotate(${rotate}, 0, 0)`, children: [_jsx("rect", Object.assign({ width: width, height: height }, commonProps, { fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill })), renderTags(tags), _jsx("g", { fill: "#e6b9c0", stroke: "#c49ba3", strokeWidth: "1", "data-seat": `${id}-seats`, transform: `translate(${-x}, ${-y})`, children: [...topSeats, ...bottomSeats, ...leftSeats, ...rightSeats].map(({ cx, cy, id }, i) => (_jsx("circle", { id: `seat-${id}`, cx: cx, cy: cy, r: r, fill: seatFill }, `${id}-seat-${i}`))) }, `${id}-seats`), _jsx("text", { x: x + width / 2, y: y + height / 2, fill: fontColor !== null && fontColor !== void 0 ? fontColor : "black", fontSize: `${fontSize !== null && fontSize !== void 0 ? fontSize : 10}px`, fontWeight: "bold", textAnchor: "middle", dominantBaseline: "middle", children: label })] }) }, id));
439
+ return (<g key={id} data-id={id} transform={`translate(${x}, ${y})`}>
440
+ <g transform={`rotate(${rotate}, 0, 0)`}>
441
+ {/* Square Table */}
442
+ <rect width={width} height={height} {...commonProps} fill={selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill}/>
443
+ {renderTags(tags)}
444
+
445
+ {/* Seats */}
446
+ <g fill="#e6b9c0" stroke="#c49ba3" strokeWidth="1" key={`${id}-seats`} data-seat={`${id}-seats`} transform={`translate(${-x}, ${-y})`}>
447
+ {[...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}/>))}
448
+ </g>
449
+
450
+ <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">
451
+ {label}
452
+ </text>
453
+ </g>
454
+ </g>);
395
455
  }
396
456
  case "text":
397
- return (_jsxs("g", { onContextMenu: (e) => e.preventDefault(), children: [_jsx("rect", { x: x, y: y, width: width, height: height, fill: "transparent", opacity: opacity }), _jsx("text", Object.assign({ x: x + width / 2, y: y + height / 2, textAnchor: "middle", dominantBaseline: "middle", fill: fontColor, fontSize: fontSize !== null && fontSize !== void 0 ? fontSize : height * 0.6, opacity: opacity }, omit(commonProps, ["fill", "opacity"]), { children: text }))] }, id));
457
+ return (<g key={id} onContextMenu={(e) => e.preventDefault()}>
458
+ <rect x={x} y={y} width={width} height={height} fill="transparent" opacity={opacity}/>
459
+ <text 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"])}>
460
+ {text}
461
+ </text>
462
+ </g>);
398
463
  case "image-table":
399
- return (_jsxs("g", { onContextMenu: (e) => e.preventDefault(), onDragEnter: (e) => {
464
+ return (<g key={id} onContextMenu={(e) => e.preventDefault()} onDragEnter={(e) => {
400
465
  e.preventDefault(); // penting
401
466
  const group = e.currentTarget;
402
467
  highlightGroup(group, "dragenter");
403
- }, onDragOver: (e) => {
468
+ }} onDragOver={(e) => {
404
469
  e.preventDefault(); // agar drop diterima
405
- }, onDragLeave: (e) => {
470
+ }} onDragLeave={(e) => {
406
471
  const group = e.currentTarget;
407
472
  unhighlightGroup(group);
408
- }, onDrop: (e) => {
473
+ }} onDrop={(e) => {
409
474
  e.preventDefault();
410
475
  const group = e.currentTarget;
411
476
  // restore langsung dan reset
412
477
  forceRestoreGroup(group);
413
- }, onPointerOver: (e) => {
478
+ }} onPointerOver={(e) => {
414
479
  e.preventDefault(); // penting
415
480
  const group = e.currentTarget;
416
481
  highlightGroup(group, "pointerover");
417
- }, onPointerOut: (e) => {
482
+ }} onPointerOut={(e) => {
418
483
  const group = e.currentTarget;
419
484
  unhighlightGroup(group);
420
- }, onPointerUp: (e) => {
485
+ }} onPointerUp={(e) => {
421
486
  e.preventDefault();
422
487
  const group = e.currentTarget;
423
488
  // restore langsung dan reset
424
489
  forceRestoreGroup(group);
425
- }, onMouseDown: (e) => {
490
+ }} onMouseDown={(e) => {
426
491
  e.preventDefault();
427
492
  const group = e.currentTarget;
428
493
  highlightGroup(group, "mousedown");
429
- }, children: [_jsx("image", Object.assign({ href: src, x: x, y: y, "data-id": id, width: width, height: height, transform: transformRotate }, commonProps)), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
430
- var _a, _b, _c, _d;
431
- return (_jsx("text", { x: x + width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0), y: y + height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0), fill: (_c = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _c !== void 0 ? _c : "black", fontSize: `${(_d = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _d !== void 0 ? _d : 10}px`, fontWeight: "bold", textAnchor: "middle", dominantBaseline: "middle", transform: transformRotate, children: _ === null || _ === void 0 ? void 0 : _.label }, index));
432
- })] }, id));
494
+ }}>
495
+ <image href={src} x={x} y={y}
496
+ // data-table={JSON.stringify(item)}
497
+ data-id={id} width={width} height={height} transform={transformRotate} {...commonProps}/>
498
+ {labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
499
+ var _a, _b, _c, _d;
500
+ 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}>
501
+ {_ === null || _ === void 0 ? void 0 : _.label}
502
+ </text>);
503
+ })}
504
+ </g>);
433
505
  case "background":
434
- return (_jsxs("g", { onContextMenu: (e) => e.preventDefault(), children: [_jsx("image", Object.assign({ href: src, x: x, y: y, width: width, height: height, transform: transformRotate }, commonProps)), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
435
- var _a, _b, _c, _d;
436
- return (_jsx("text", { x: x + width / 2 + ((_a = _ === null || _ === void 0 ? void 0 : _.x) !== null && _a !== void 0 ? _a : 0), y: y + height / 2 + ((_b = _ === null || _ === void 0 ? void 0 : _.y) !== null && _b !== void 0 ? _b : 0), fill: (_c = _ === null || _ === void 0 ? void 0 : _.fontColor) !== null && _c !== void 0 ? _c : "black", fontSize: `${(_d = _ === null || _ === void 0 ? void 0 : _.fontSize) !== null && _d !== void 0 ? _d : 10}px`, fontWeight: "bold", textAnchor: "middle", dominantBaseline: "middle", transform: transformRotate, children: _ === null || _ === void 0 ? void 0 : _.label }, index));
437
- })] }, id));
506
+ return (<g key={id} onContextMenu={(e) => e.preventDefault()}>
507
+ <image href={src} x={x} y={y} width={width} height={height} transform={transformRotate} {...commonProps}/>
508
+ {labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
509
+ var _a, _b, _c, _d;
510
+ 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}>
511
+ {_ === null || _ === void 0 ? void 0 : _.label}
512
+ </text>);
513
+ })}
514
+ </g>);
438
515
  default:
439
- return _jsx("g", {}, id);
516
+ return <g key={id}/>;
440
517
  }
441
518
  };
442
519
  let date = new Date();
443
- return _jsx("g", { children: components === null || components === void 0 ? void 0 : components.map(renderShape) }, `${date}`);
520
+ return <g key={`${date}`}>{components === null || components === void 0 ? void 0 : components.map(renderShape)}</g>;
444
521
  };
445
522
  export default Layers;
@@ -3,6 +3,6 @@ export interface LayerViewProps {
3
3
  componentProps: any[];
4
4
  extraComponentProps: any[];
5
5
  }
6
- declare const TableEditor: ({ componentProps, extraComponentProps, }: LayerViewProps) => import("react/jsx-runtime").JSX.Element;
6
+ declare const TableEditor: ({ componentProps, extraComponentProps, }: LayerViewProps) => import("react").JSX.Element;
7
7
  export default TableEditor;
8
8
  export { LayerView };
@@ -1,5 +1,4 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
2
  import { useEffect } from "react";
4
3
  import Board from "../../features/board";
5
4
  import SideTool from "../../features/side-tool";
@@ -22,7 +21,13 @@ const TableEditor = ({ componentProps = [], extraComponentProps = [], }) => {
22
21
  });
23
22
  }
24
23
  }, [componentProps, extraComponentProps]);
25
- return (_jsx(_Fragment, { children: _jsxs("div", { className: "w-full h-screen flex relative", children: [_jsx(SideTool, {}), _jsx(Board, {}), _jsx(ControlPanels, {})] }) }));
24
+ return (<>
25
+ <div className="w-full h-screen flex relative">
26
+ <SideTool />
27
+ <Board />
28
+ <ControlPanels />
29
+ </div>
30
+ </>);
26
31
  };
27
32
  export default TableEditor;
28
33
  export { LayerView };
@@ -1,4 +1,4 @@
1
1
  declare const ModalPreview: ({ children }: {
2
2
  children: React.ReactNode;
3
- }) => import("react/jsx-runtime").JSX.Element;
3
+ }) => import("react").JSX.Element;
4
4
  export default ModalPreview;
@@ -0,0 +1,11 @@
1
+ "use client";
2
+ import { Modal } from "antd";
3
+ import { useAppSelector, useAppDispatch } from "../../hooks/use-redux";
4
+ const ModalPreview = ({ children }) => {
5
+ const { isPreview } = useAppSelector((state) => state.tool);
6
+ const dispatch = useAppDispatch();
7
+ return (<Modal open={isPreview} onCancel={() => dispatch({ type: "tool/setTooglePreview", payload: false })} width={700} title="Preview Board" centered footer={null}>
8
+ <div className="flex flex-col p-4 h-[500px]">{children}</div>
9
+ </Modal>);
10
+ };
11
+ export default ModalPreview;
@@ -2,5 +2,5 @@ interface BoardTemplateProps {
2
2
  onSelectComponent?: (items: any) => void;
3
3
  mappingKey?: string;
4
4
  }
5
- declare const BoardTemplate: ({ onSelectComponent }: BoardTemplateProps) => import("react/jsx-runtime").JSX.Element;
5
+ declare const BoardTemplate: ({ onSelectComponent }: BoardTemplateProps) => import("react").JSX.Element;
6
6
  export default BoardTemplate;
@@ -1,5 +1,4 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
2
  import { useCallback, useEffect, useRef, useState } from "react";
4
3
  import { TransformWrapper, TransformComponent, MiniMap, } from "react-zoom-pan-pinch";
5
4
  import { useAppSelector, useAppDispatch } from "../../hooks/use-redux";
@@ -607,15 +606,21 @@ const BoardTemplate = ({ onSelectComponent }) => {
607
606
  }
608
607
  };
609
608
  const renderMiniMap = () => {
610
- return (_jsx(MiniMap, { width: 250, height: 250, children: _jsx("div", { className: "w-full h-full", children: _jsx("svg", { id: "workspace", width: "100%", height: "100%", viewBox: `0 0 ${widthBoard} ${heightBoard}`, className: "h-screen w-full", xmlns: "http://www.w3.org/2000/svg", preserveAspectRatio: "xMidYMid meet", style: {
611
- background: "#f5f5f5",
612
- display: "block",
613
- }, children: _jsx(Layers, { shadowShape: shadowShape, components: [...extraComponentsState, ...componentsState], activeTool: activeTool,
614
- // onClick={handleSelectComponent}
615
- // onMouseDown={handleMouseDown}
616
- // onMouseUp={handleMouseUp}
617
- // onBlur={handleUnSelectComponent}
618
- selectedComponent: selectedComponent }) }) }) }));
609
+ return (<MiniMap width={250} height={250}>
610
+ <div className="w-full h-full">
611
+ <svg id="workspace" width="100%" height="100%" viewBox={`0 0 ${widthBoard} ${heightBoard}`} className="h-screen w-full" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" style={{
612
+ background: "#f5f5f5",
613
+ display: "block",
614
+ }}>
615
+ <Layers shadowShape={shadowShape} components={[...extraComponentsState, ...componentsState]} activeTool={activeTool}
616
+ // onClick={handleSelectComponent}
617
+ // onMouseDown={handleMouseDown}
618
+ // onMouseUp={handleMouseUp}
619
+ // onBlur={handleUnSelectComponent}
620
+ selectedComponent={selectedComponent}/>
621
+ </svg>
622
+ </div>
623
+ </MiniMap>);
619
624
  };
620
625
  const handelZoomIn = () => {
621
626
  var _a;
@@ -641,26 +646,80 @@ const BoardTemplate = ({ onSelectComponent }) => {
641
646
  // moveComponent &&
642
647
  // isTouching.current &&
643
648
  // !resizeDirection
644
- return (_jsxs(_Fragment, { children: [_jsx(ModalPreview, { children: _jsx(LayerView, { statusKey: "status" }) }), _jsxs("div", { className: "relative w-full h-screen flex-1 overflow-hidden", ref: containerRef, children: [_jsx("div", { className: "absolute bottom-5 left-1/2 transform -translate-x-1/2 z-10", children: _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { icon: _jsx(ZoomIn, {}), onClick: handelZoomIn }), _jsx(Button, { icon: _jsx(ZoomOut, {}), onClick: handleZoomOut })] }) }), _jsxs(TransformWrapper, { ref: transformRef, panning: { disabled: activeTool === "select" }, centerZoomedOut: true, onTransformed: ({ state: { scale } }) => setScale(scale), minScale: 1, maxScale: 1000, initialScale: 1, pinch: { step: 1 }, smooth: true, doubleClick: { step: 1, disabled: activeTool === "select" }, disablePadding: true, children: [scale > 1 && (_jsx("div", { className: "absolute bottom-[60px] left-1/2 transform -translate-x-1/2 z-10", children: renderMiniMap() })), _jsx(TransformComponent, { wrapperStyle: {
645
- width: "100%",
646
- height: "100%",
647
- overflow: "hidden",
648
- }, contentStyle: {
649
- width: "100%",
650
- height: "100%",
651
- }, children: _jsxs("svg", { id: "workspace", ref: svgRef, width: "100%", height: "100%", viewBox: `0 0 ${widthBoard} ${heightBoard}`, className: "h-screen", onMouseUp: handleMouseUp, onMouseMove: handleMouseMove, onMouseEnter: handleMouseEnter, onClick: (e) => {
652
- e.stopPropagation();
653
- handleMouseClick(e);
654
- }, onMouseLeave: handleMouseLeave, xmlns: "http://www.w3.org/2000/svg", preserveAspectRatio: "xMidYMid meet", style: {
655
- background: backgroundColor,
656
- display: "block",
657
- cursor: activeTool === "ruler" ? "crosshair" : "auto",
658
- }, children: [_jsx(Layers, { shadowShape: shadowShape, components: [...extraComponentsState, ...componentsState], style: {
659
- cursor: getCursorStyle(),
660
- },
661
- // onClick={handleSelectComponent}
662
- onMouseDown: handleMouseDown,
663
- // onMouseUp={handleMouseUp}
664
- onBlur: handleUnSelectComponent, selectedComponent: selectedComponent, activeTool: activeTool, onTouchStart: (e, item, direction) => handleTouchStart(e, item, direction), onTouchMove: (e) => handleTouchMove(e), onTouchEnd: handleTouchEnd }), activeTool === "ruler" && (_jsxs(_Fragment, { children: [_jsxs("g", { id: "horizontal-ruler", children: [_jsx("rect", { x: "0", y: "0", width: window.innerWidth, height: "30", fill: "#e0e0e0" }), _jsx("g", { stroke: "#888", "font-size": "10", "text-anchor": "middle", children: Array.from({ length: window.innerWidth / 50 }, (_, i) => (_jsxs("g", { children: [_jsx("line", { x1: i * 50, y1: "0", x2: i * 50, y2: "10" }), _jsx("text", { x: i * 50, y: "15", children: i * 50 })] }, i))) })] }), _jsxs("g", { id: "vertical-ruler", children: [_jsx("rect", { x: "0", y: "0", width: "30", height: window.innerHeight, fill: "#e0e0e0" }), _jsx("g", { stroke: "#888", "font-size": "10", "text-anchor": "middle", children: Array.from({ length: window.innerHeight / 10 }, (_, i) => (_jsxs("g", { children: [_jsx("line", { x1: "0", y1: i * 50, x2: "10", y2: i * 50 }), _jsx("text", { x: "15", y: i * 50, children: i * 50 })] }, i))) })] })] })), grid && (_jsxs("g", { stroke: "#ddd", strokeWidth: 0.5, children: [Array.from({ length: widthBoard / 10 }, (_, i) => (_jsx("line", { x1: i * 10, y1: 0, x2: i * 10, y2: heightBoard }, `v-${i}`))), Array.from({ length: heightBoard / 10 }, (_, i) => (_jsx("line", { x1: 0, y1: i * 10, x2: widthBoard, y2: i * 10 }, `h-${i}`)))] }))] }) })] })] })] }));
649
+ return (<>
650
+ <ModalPreview>
651
+ <LayerView statusKey="status"/>
652
+ </ModalPreview>
653
+ <div className="relative w-full h-screen flex-1 overflow-hidden" ref={containerRef}>
654
+ <div className="absolute bottom-5 left-1/2 transform -translate-x-1/2 z-10">
655
+ <div className="flex gap-2">
656
+ <Button icon={<ZoomIn />} onClick={handelZoomIn}/>
657
+ <Button icon={<ZoomOut />} onClick={handleZoomOut}/>
658
+ </div>
659
+ </div>
660
+ <TransformWrapper ref={transformRef} panning={{ disabled: activeTool === "select" }} centerZoomedOut={true} onTransformed={({ state: { scale } }) => setScale(scale)} minScale={1} // sangat kecil = bisa zoom out jauh
661
+ maxScale={1000} initialScale={1} pinch={{ step: 1 }} smooth={true} doubleClick={{ step: 1, disabled: activeTool === "select" }} disablePadding>
662
+ {scale > 1 && (<div className="absolute bottom-[60px] left-1/2 transform -translate-x-1/2 z-10">
663
+ {renderMiniMap()}
664
+ </div>)}
665
+ <TransformComponent wrapperStyle={{
666
+ width: "100%",
667
+ height: "100%",
668
+ overflow: "hidden",
669
+ }} contentStyle={{
670
+ width: "100%",
671
+ height: "100%",
672
+ }}>
673
+ <svg id="workspace" ref={svgRef} width="100%" height="100%" viewBox={`0 0 ${widthBoard} ${heightBoard}`} className="h-screen" onMouseUp={handleMouseUp} onMouseMove={handleMouseMove} onMouseEnter={handleMouseEnter} onClick={(e) => {
674
+ e.stopPropagation();
675
+ handleMouseClick(e);
676
+ }} onMouseLeave={handleMouseLeave} xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" style={{
677
+ background: backgroundColor,
678
+ display: "block",
679
+ cursor: activeTool === "ruler" ? "crosshair" : "auto",
680
+ }}>
681
+ <Layers shadowShape={shadowShape} components={[...extraComponentsState, ...componentsState]} style={{
682
+ cursor: getCursorStyle(),
683
+ }}
684
+ // onClick={handleSelectComponent}
685
+ onMouseDown={handleMouseDown}
686
+ // onMouseUp={handleMouseUp}
687
+ onBlur={handleUnSelectComponent} selectedComponent={selectedComponent} activeTool={activeTool} onTouchStart={(e, item, direction) => handleTouchStart(e, item, direction)} onTouchMove={(e) => handleTouchMove(e)} onTouchEnd={handleTouchEnd}/>
688
+ {activeTool === "ruler" && (<>
689
+ <g id="horizontal-ruler">
690
+ <rect x="0" y="0" width={window.innerWidth} height="30" fill="#e0e0e0"/>
691
+ <g stroke="#888" font-size="10" text-anchor="middle">
692
+ {Array.from({ length: window.innerWidth / 50 }, (_, i) => (<g key={i}>
693
+ <line x1={i * 50} y1="0" x2={i * 50} y2="10"/>
694
+ <text x={i * 50} y="15">
695
+ {i * 50}
696
+ </text>
697
+ </g>))}
698
+ </g>
699
+ </g>
700
+ <g id="vertical-ruler">
701
+ <rect x="0" y="0" width="30" height={window.innerHeight} fill="#e0e0e0"/>
702
+ <g stroke="#888" font-size="10" text-anchor="middle">
703
+ {Array.from({ length: window.innerHeight / 10 }, (_, i) => (<g key={i}>
704
+ <line x1="0" y1={i * 50} x2="10" y2={i * 50}/>
705
+ <text x="15" y={i * 50}>
706
+ {i * 50}
707
+ </text>
708
+ </g>))}
709
+ </g>
710
+ </g>
711
+ </>)}
712
+ {grid && (<g stroke="#ddd" strokeWidth={0.5}>
713
+ {/* Vertical lines */}
714
+ {Array.from({ length: widthBoard / 10 }, (_, i) => (<line key={`v-${i}`} x1={i * 10} y1={0} x2={i * 10} y2={heightBoard}/>))}
715
+
716
+ {/* Horizontal lines */}
717
+ {Array.from({ length: heightBoard / 10 }, (_, i) => (<line key={`h-${i}`} x1={0} y1={i * 10} x2={widthBoard} y2={i * 10}/>))}
718
+ </g>)}
719
+ </svg>
720
+ </TransformComponent>
721
+ </TransformWrapper>
722
+ </div>
723
+ </>);
665
724
  };
666
725
  export default BoardTemplate;