seat-editor 1.2.26 → 1.2.28

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.
@@ -0,0 +1,168 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { omit } from "lodash";
4
+ const Layers = ({ shadowShape, components, onClick, selectedComponent, selectedTable, activeTool, onMouseDown, onMouseUp, onBlur, selectedTableColor, mode = "edit", style }) => {
5
+ const renderShadowShape = (item) => {
6
+ const { id, x, y, width, height, fill, opacity, rotation, shape, fontColor, text, seatFill, labels, } = item;
7
+ const commonProps = { fill, opacity };
8
+ switch (shape) {
9
+ case "square":
10
+ return (_jsx("rect", Object.assign({ x: x, y: y, width: width, height: height }, commonProps), id));
11
+ case "circle":
12
+ return (_jsx("circle", Object.assign({ cx: x + width / 2, cy: y + height / 2, r: width / 2 }, commonProps), id));
13
+ case "diamond":
14
+ return (_jsx("rect", Object.assign({ x: x, y: y, width: width, height: height, transform: `rotate(${rotation}, ${x}, ${y})` }, commonProps), id));
15
+ case "table-seat-circle": {
16
+ const seatCount = item.seatCount;
17
+ const openSpace = item.openSpace; // nilai antara 0 (tidak ada ruang) sampai maksimal ~0.9
18
+ const centerX = x + width / 2;
19
+ const centerY = y + height / 2;
20
+ const radius = width;
21
+ const seatRadius = width / 4;
22
+ const fullAngle = 2 * Math.PI;
23
+ const availableAngle = fullAngle * (1 - openSpace); // sudut yang dipakai untuk kursi
24
+ const angleStart = (fullAngle - availableAngle) / 2; // agar tetap seimbang
25
+ const angleStep = availableAngle / seatCount;
26
+ const seatCircles = Array.from({ length: seatCount }, (_, i) => {
27
+ const angle = angleStart + i * angleStep;
28
+ const cx = centerX + radius * Math.cos(angle);
29
+ const cy = centerY + radius * Math.sin(angle);
30
+ return { cx, cy };
31
+ });
32
+ return (_jsxs("g", { transform: `rotate(${rotation} ${x + width / 2} ${y + height / 2})`, children: [_jsx("circle", Object.assign({ cx: centerX, cy: centerY, r: width - 15 }, 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) => {
33
+ var _a, _b, _c, _d;
34
+ 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 }, `${id}-label-${index}`));
35
+ }), _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));
36
+ }
37
+ case "table-seat-square": {
38
+ const seatCount = item.seatCount || 6;
39
+ const openSpace = item.openSpace || 0; // from 0 to 0.9
40
+ const seatRadius = width / 6;
41
+ // split seats evenly on top and bottom
42
+ const seatCountPerSide = Math.ceil(seatCount / 2);
43
+ const availableWidth = width * (1 - openSpace);
44
+ const startX = x + (width * openSpace) / 2;
45
+ const spacing = seatCountPerSide > 1 ? availableWidth / (seatCountPerSide - 1) : 0;
46
+ const topSeats = Array.from({ length: seatCountPerSide }, (_, i) => ({
47
+ cx: startX + i * spacing,
48
+ cy: y - seatRadius * 1.5,
49
+ }));
50
+ const bottomSeats = Array.from({ length: seatCount - seatCountPerSide }, // in case it's odd
51
+ (_, i) => ({
52
+ cx: startX + i * spacing,
53
+ cy: y + height + seatRadius * 1.5,
54
+ }));
55
+ 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));
56
+ }
57
+ case "text":
58
+ return (_jsxs("g", { onClick: () => onClick(item), children: [_jsx("rect", { x: x, y: y, width: width, height: height, fill: "transparent", opacity: opacity }), _jsx("text", { x: x + width / 2, y: y + height / 2, textAnchor: "middle", dominantBaseline: "middle", fill: fontColor, fontSize: height * 0.6, opacity: opacity, children: text })] }, id));
59
+ default:
60
+ return null;
61
+ }
62
+ };
63
+ const renderShape = (item) => {
64
+ const { id, x, y, width, height, fill, opacity, rotation, shape, text, stroke, strokeWidth, labels, fontSize, fontColor, label, seatFill, src, } = item;
65
+ const commonProps = {
66
+ fill,
67
+ opacity,
68
+ onClick: (e) => {
69
+ // e.stopPropagation();
70
+ onClick(item);
71
+ },
72
+ stroke,
73
+ strokeWidth,
74
+ onMouseDown: (e) => {
75
+ // e.stopPropagation();
76
+ onMouseDown === null || onMouseDown === void 0 ? void 0 : onMouseDown(e, item);
77
+ },
78
+ onMouseUp: (e) => {
79
+ // e.stopPropagation();
80
+ onMouseUp === null || onMouseUp === void 0 ? void 0 : onMouseUp(e);
81
+ },
82
+ onBlur: (e) => {
83
+ // e.stopPropagation();
84
+ onBlur === null || onBlur === void 0 ? void 0 : onBlur();
85
+ },
86
+ };
87
+ switch (shape) {
88
+ case "square":
89
+ return (_jsxs(_Fragment, { children: [_jsx("rect", Object.assign({ x: x, y: y, width: width, height: height, fill: selectedTableColor !== null && selectedTableColor !== void 0 ? selectedTableColor : fill, style: Object.assign({ cursor: mode === "view" ? "pointer" : "default" }, style), opacity: id === (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id) ? 0.5 : opacity }, omit(commonProps, "opacity"), { transform: `rotate(${rotation} ${x + width / 2} ${y + height / 2})` }), id), labels === null || labels === void 0 ? void 0 : labels.map((_, index) => {
90
+ var _a, _b, _c, _d;
91
+ 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) => {
92
+ e.stopPropagation();
93
+ onClick(item);
94
+ }, children: _ === null || _ === void 0 ? void 0 : _.label }, `${id}-label-${index}`));
95
+ })] }));
96
+ case "circle":
97
+ return (_jsxs(_Fragment, { children: [_jsx("circle", Object.assign({ cx: x + width / 2, cy: y + height / 2, r: width / 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) => {
98
+ var _a, _b, _c, _d;
99
+ 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) => {
100
+ e.stopPropagation();
101
+ onClick(item);
102
+ }, children: _ === null || _ === void 0 ? void 0 : _.label }, `${id}-label-${index}`));
103
+ })] }));
104
+ case "diamond":
105
+ return (_jsxs(_Fragment, { 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 })] }));
106
+ case "table-seat-circle": {
107
+ const seatCount = item.seatCount;
108
+ const openSpace = item.openSpace; // nilai antara 0 (tidak ada ruang) sampai maksimal ~0.9
109
+ const centerX = x + width / 2;
110
+ const centerY = y + height / 2;
111
+ const radius = width;
112
+ const seatRadius = width / 4;
113
+ const fullAngle = 2 * Math.PI;
114
+ const availableAngle = fullAngle * (1 - openSpace); // sudut yang dipakai untuk kursi
115
+ const angleStart = (fullAngle - availableAngle) / 2; // agar tetap seimbang
116
+ const angleStep = availableAngle / seatCount;
117
+ const seatCircles = Array.from({ length: seatCount }, (_, i) => {
118
+ const angle = angleStart + i * angleStep;
119
+ const cx = centerX + radius * Math.cos(angle);
120
+ const cy = centerY + radius * Math.sin(angle);
121
+ return { cx, cy };
122
+ });
123
+ return (_jsxs("g", { transform: `rotate(${rotation} ${x + width / 2} ${y + height / 2})`, children: [_jsx("circle", Object.assign({ cx: centerX, style: Object.assign({ cursor: mode === "view" ? "pointer" : "default" }, style), cy: centerY, r: width - 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) => {
124
+ var _a, _b, _c, _d;
125
+ 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) => {
126
+ e.stopPropagation();
127
+ onClick(item);
128
+ }, children: _ === null || _ === void 0 ? void 0 : _.label }, `${id}-label-${index}`));
129
+ }), _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));
130
+ }
131
+ case "table-seat-square": {
132
+ const seatCount = item.seatCount || 6;
133
+ const openSpace = item.openSpace || 0; // from 0 to 0.9
134
+ const seatRadius = width / 6;
135
+ // split seats evenly on top and bottom
136
+ const seatCountPerSide = Math.ceil(seatCount / 2);
137
+ const availableWidth = width * (1 - openSpace);
138
+ const startX = x + (width * openSpace) / 2;
139
+ const spacing = seatCountPerSide > 1 ? availableWidth / (seatCountPerSide - 1) : 0;
140
+ const topSeats = Array.from({ length: seatCountPerSide }, (_, i) => ({
141
+ cx: startX + i * spacing,
142
+ cy: y - seatRadius * 1.5,
143
+ }));
144
+ const bottomSeats = Array.from({ length: seatCount - seatCountPerSide }, // in case it's odd
145
+ (_, i) => ({
146
+ cx: startX + i * spacing,
147
+ cy: y + height + seatRadius * 1.5,
148
+ }));
149
+ 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));
150
+ }
151
+ case "text":
152
+ return (_jsxs("g", { children: [_jsx("rect", { x: x, y: y, width: width, height: height, fill: "transparent", opacity: opacity, onClick: (e) => {
153
+ e.stopPropagation();
154
+ onClick(item);
155
+ } }), _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));
156
+ case "image-table":
157
+ case "background":
158
+ return (_jsxs("g", { onClick: () => onClick(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) => {
159
+ var _a, _b, _c, _d;
160
+ 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));
161
+ })] }, id));
162
+ default:
163
+ return null;
164
+ }
165
+ };
166
+ return (_jsxs("g", { children: [components === null || components === void 0 ? void 0 : components.map(renderShape), shadowShape === null || shadowShape === void 0 ? void 0 : shadowShape.map(renderShadowShape)] }));
167
+ };
168
+ export default Layers;
@@ -0,0 +1,28 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useEffect } from "react";
4
+ import Board from "../../features/board";
5
+ import SideTool from "../../features/side-tool";
6
+ import ControlPanels from "../../features/panel";
7
+ import LayerView from "../../features/view";
8
+ import { useAppDispatch } from "../../hooks/use-redux";
9
+ const TableEditor = ({ componentProps = [], extraComponentProps = [], }) => {
10
+ const dispatch = useAppDispatch();
11
+ useEffect(() => {
12
+ if (componentProps.length > 0) {
13
+ dispatch({
14
+ type: "board/setNewComponents",
15
+ payload: componentProps,
16
+ });
17
+ }
18
+ if (extraComponentProps.length > 0) {
19
+ dispatch({
20
+ type: "board/setNewExtraComponent",
21
+ payload: extraComponentProps,
22
+ });
23
+ }
24
+ }, [componentProps, extraComponentProps]);
25
+ return (_jsx(_Fragment, { children: _jsxs("div", { className: "w-full h-screen flex relative", children: [_jsx(SideTool, {}), _jsx(Board, {}), _jsx(ControlPanels, {})] }) }));
26
+ };
27
+ export default TableEditor;
28
+ export { LayerView };
@@ -0,0 +1,10 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { Modal } from "antd";
4
+ import { useAppSelector, useAppDispatch } from "../../hooks/use-redux";
5
+ const ModalPreview = ({ children }) => {
6
+ const { isPreview } = useAppSelector((state) => state.tool);
7
+ const dispatch = useAppDispatch();
8
+ return (_jsx(Modal, { open: isPreview, onCancel: () => dispatch({ type: "tool/setTooglePreview", payload: false }), width: 700, title: "Preview Board", centered: true, footer: null, children: _jsx("div", { className: "flex flex-col p-4 h-[500px]", children: children }) }));
9
+ };
10
+ export default ModalPreview;
@@ -0,0 +1,297 @@
1
+ "use client";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ import { TransformWrapper, TransformComponent, } from "react-zoom-pan-pinch";
5
+ import { useAppSelector, useAppDispatch } from "../../hooks/use-redux";
6
+ import Layers from "../../components/layer";
7
+ import { throttle } from "lodash";
8
+ import ModalPreview from "../../components/modal-preview";
9
+ import LayerView from "../view";
10
+ const BoardTemplate = ({ onSelectComponent }) => {
11
+ const dispatch = useAppDispatch();
12
+ const transformRef = useRef(null);
13
+ const containerRef = useRef(null);
14
+ const [widthBoard, setWidthBoard] = useState(0);
15
+ const [heightBoard, setHeightBoard] = useState(0);
16
+ const svgRef = useRef(null);
17
+ const [shadowShape, setShadowShape] = useState([]);
18
+ const [startPoint, setStartPoint] = useState(null);
19
+ const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
20
+ const [moveComponent, setMoveComponent] = useState(false);
21
+ const [scale, setScale] = useState(1);
22
+ const activeTool = useAppSelector((state) => state.tool.active);
23
+ const { components, extraComponents } = useAppSelector((state) => state.board);
24
+ // useEffect(() => {
25
+ // if (dataDummy.length > 0) {
26
+ // dispatch({
27
+ // type: "board/setNewComponents",
28
+ // payload: dataDummy,
29
+ // });
30
+ // }
31
+ // if (dummyImage.length > 0) {
32
+ // dispatch({
33
+ // type: "board/setNewExtraComponents",
34
+ // payload: dummyImage,
35
+ // });
36
+ // }
37
+ // if(defaultBackground) {
38
+ // dispatch({
39
+ // type: "board/setBackgroundColor",
40
+ // payload: defaultBackground,
41
+ // });
42
+ // }
43
+ // }, []);
44
+ const backgroundColor = useAppSelector((state) => state.board.backgroundColor);
45
+ const selectedComponent = useAppSelector((state) => state.panel.selectedComponent);
46
+ // useEffect(() => {
47
+ // const handleKeyDown = (event: KeyboardEvent) => {
48
+ // if (event.key === 'Backspace' && selectedComponent) {
49
+ // dispatch({
50
+ // type:"board/removeComponent",
51
+ // payload:selectedComponent
52
+ // })
53
+ // dispatch({
54
+ // type:"panel/setUnSelectedComponent",
55
+ // })
56
+ // }
57
+ // };
58
+ // window.addEventListener('keydown', handleKeyDown);
59
+ // return () => {
60
+ // window.removeEventListener('keydown', handleKeyDown);
61
+ // };
62
+ // }, [selectedComponent]);
63
+ const handleAddComponent = (shape) => {
64
+ dispatch({
65
+ type: activeTool === "text"
66
+ ? "board/setExtraComponent"
67
+ : "board/addComponent",
68
+ payload: Object.assign(Object.assign({}, shape), { fill: "#4A90E2" }),
69
+ });
70
+ };
71
+ const handleUpdateComponent = () => {
72
+ if (!selectedComponent)
73
+ return;
74
+ dispatch({
75
+ type: "board/updateComponent",
76
+ payload: Object.assign({}, (typeof selectedComponent === "object" && selectedComponent !== null
77
+ ? selectedComponent
78
+ : {})),
79
+ });
80
+ };
81
+ const getSvgCoords = (e) => {
82
+ var _a;
83
+ const svg = svgRef.current;
84
+ const point = svg.createSVGPoint();
85
+ point.x = e.clientX;
86
+ point.y = e.clientY;
87
+ const transformed = point.matrixTransform((_a = svg.getScreenCTM()) === null || _a === void 0 ? void 0 : _a.inverse());
88
+ return { x: transformed.x, y: transformed.y };
89
+ };
90
+ const createShape = (x, y, fill) => ({
91
+ x,
92
+ y,
93
+ width: 50,
94
+ height: 50,
95
+ shape: activeTool,
96
+ id: Date.now(),
97
+ fill,
98
+ rotation: activeTool === "diamond" ? 45 : 0,
99
+ seatCount: activeTool === "table-seat-circle" ? 6 : 0,
100
+ openSpace: activeTool === "table-seat-circle" ? 0 : undefined,
101
+ seatFill: activeTool === "table-seat-circle" ? "#DADADA" : undefined,
102
+ text: activeTool === "text" ? "Text" : "",
103
+ fontColor: activeTool === "text" ? "#DADADA" : undefined,
104
+ });
105
+ // console.log({ moveComponent})
106
+ const handleMouseDown = (e, item) => {
107
+ // console.log(" mouse down", item);
108
+ // if (!isEmpty(item)) {
109
+ // handleSelectComponent(item);
110
+ // }
111
+ if (activeTool === "select") {
112
+ if (e) {
113
+ dispatch({ type: "panel/setShow", payload: false });
114
+ setMoveComponent(true);
115
+ dispatch({ type: "panel/setSelectedComponent", payload: item });
116
+ const rectBox = (e === null || e === void 0 ? void 0 : e.target).getBoundingClientRect();
117
+ setDragOffset({
118
+ x: e.clientX - rectBox.left,
119
+ y: e.clientY - rectBox.top,
120
+ });
121
+ // dispatch({ type: "panel/setShow" , payload: false });
122
+ }
123
+ }
124
+ };
125
+ const handleMouseUp = () => {
126
+ if (activeTool === "select") {
127
+ setMoveComponent(false);
128
+ dispatch({ type: "panel/setShow", payload: false });
129
+ }
130
+ };
131
+ const handleMouseEnter = () => {
132
+ if (![
133
+ "square",
134
+ "circle",
135
+ "diamond",
136
+ "table-seat-circle",
137
+ "table-seat-square",
138
+ "text",
139
+ ].includes(activeTool))
140
+ return;
141
+ };
142
+ const handleMouseLeave = () => {
143
+ if (![
144
+ "square",
145
+ "circle",
146
+ "diamond",
147
+ "table-seat-circle",
148
+ "table-seat-square",
149
+ "text",
150
+ ].includes(activeTool))
151
+ return;
152
+ setShadowShape([]);
153
+ };
154
+ const handleMouseClick = (e) => {
155
+ if (![
156
+ "square",
157
+ "circle",
158
+ "diamond",
159
+ "table-seat-circle",
160
+ "table-seat-square",
161
+ "text",
162
+ ].includes(activeTool))
163
+ return;
164
+ const { x, y } = getSvgCoords(event);
165
+ setStartPoint({ x, y });
166
+ handleAddComponent(createShape(x, y, "#4A90E2"));
167
+ };
168
+ const throttledDispatch = useCallback(throttle((component) => {
169
+ dispatch({
170
+ type: "board/updateComponent",
171
+ payload: component,
172
+ });
173
+ }, 16), // 16ms ≈ 60fps
174
+ [dispatch]);
175
+ const handleMouseMove = (e) => {
176
+ if ([
177
+ "square",
178
+ "circle",
179
+ "diamond",
180
+ "table-seat-circle",
181
+ "table-seat-square",
182
+ "text",
183
+ ].includes(activeTool)) {
184
+ const { x, y } = getSvgCoords(event);
185
+ setShadowShape([createShape(x, y, "white")]);
186
+ return;
187
+ }
188
+ if (activeTool === "select" &&
189
+ selectedComponent &&
190
+ moveComponent &&
191
+ dragOffset) {
192
+ const workspaceRect = e.currentTarget.getBoundingClientRect();
193
+ const newX = e.clientX - workspaceRect.left - dragOffset.x;
194
+ const newY = e.clientY - workspaceRect.top - dragOffset.y;
195
+ let newPosition = {
196
+ x: newX,
197
+ y: newY,
198
+ };
199
+ throttledDispatch(Object.assign(Object.assign({}, (typeof selectedComponent === "object" && selectedComponent !== null
200
+ ? selectedComponent
201
+ : {})), { x: newPosition.x, y: newPosition.y }));
202
+ // dispatch({
203
+ // type: "board/updateComponent",
204
+ // payload: {
205
+ // ...(typeof selectedComponent === "object" &&
206
+ // selectedComponent !== null
207
+ // ? selectedComponent
208
+ // : {}),
209
+ // x: newPosition.x,
210
+ // y: newPosition.y,
211
+ // },
212
+ // });
213
+ return;
214
+ }
215
+ };
216
+ // if (activeTool === "table-seat-circle") {
217
+ // shape = {
218
+ // x: Math.min(x, startPoint.x),
219
+ // y: Math.min(y, startPoint.y),
220
+ // width: Math.abs(x - startPoint.x),
221
+ // height: Math.abs(y - startPoint.y),
222
+ // shape: activeTool,
223
+ // id: Date.now(),
224
+ // fill: "#4A90E2",
225
+ // seats: 6,
226
+ // };
227
+ // }
228
+ // if (activeTool === "text") {
229
+ // shape = {
230
+ // x: Math.min(x, startPoint.x),
231
+ // y: Math.min(y, startPoint.y),
232
+ // width: Math.abs(x - startPoint.x),
233
+ // height: Math.abs(y - startPoint.y),
234
+ // shape: activeTool,
235
+ // id: Date.now(),
236
+ // fill: "#4A90E2",
237
+ // text: "Text",
238
+ // };
239
+ // }
240
+ // if (activeTool === "select" && selectedComponent) {
241
+ // shape = {
242
+ // ...selectedComponent,
243
+ // x: Math.min(x, startPoint.x),
244
+ // y: Math.min(y, startPoint.y),
245
+ // width: Math.abs(x - startPoint.x),
246
+ // height: Math.abs(y - startPoint.y),
247
+ // };
248
+ // setSelectedComponent(shape);
249
+ // return;
250
+ // }
251
+ // }
252
+ const handleSelectComponent = (items) => {
253
+ if (activeTool === "select") {
254
+ // if (isEmpty(items)) {
255
+ // dispatch({ type: "panel/setSelectedComponent", payload: null });
256
+ // setMoveComponent(false);
257
+ // } else {
258
+ onSelectComponent && onSelectComponent(items);
259
+ dispatch({ type: "panel/setSelectedComponent", payload: items });
260
+ dispatch({ type: "panel/setShow", payload: true });
261
+ // }
262
+ }
263
+ };
264
+ useEffect(() => {
265
+ if (containerRef.current) {
266
+ setWidthBoard(containerRef.current.offsetWidth);
267
+ setHeightBoard(containerRef.current.offsetHeight);
268
+ }
269
+ });
270
+ const handleUnSelectComponent = () => {
271
+ dispatch({ type: "panel/setSelectedComponent", payload: null });
272
+ };
273
+ return (_jsxs(_Fragment, { children: [_jsx(ModalPreview, { children: _jsx(LayerView, { statusKey: "status", defaultBackground: "#ffffff" }) }), _jsx("div", { className: "relative w-full h-screen flex-1", ref: containerRef, children: _jsx(TransformWrapper, { ref: transformRef, panning: { disabled: false }, centerZoomedOut: true, onTransformed: ({ state: { scale } }) => setScale(scale), minScale: 1, maxScale: 1000, initialScale: 1, pinch: { step: 1 }, smooth: true,
274
+ // doubleClick={{ step: 2, mode: "zoomIn" }}
275
+ disablePadding: true, children: _jsx(TransformComponent, { wrapperStyle: {
276
+ width: "100%",
277
+ height: "100%",
278
+ overflow: "hidden",
279
+ }, contentStyle: {
280
+ width: "100%",
281
+ height: "100%",
282
+ }, children: _jsx("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) => {
283
+ e.stopPropagation();
284
+ handleMouseClick(e);
285
+ }, onMouseLeave: handleMouseLeave,
286
+ // onMouseDown={(e) => {
287
+ // e.stopPropagation();
288
+ // }}
289
+ // onFocus={(e) => {
290
+ // console.log(e.target);
291
+ // }}
292
+ xmlns: "http://www.w3.org/2000/svg", preserveAspectRatio: "xMidYMid meet", style: {
293
+ background: backgroundColor,
294
+ display: "block",
295
+ }, children: _jsx(Layers, { shadowShape: shadowShape, components: [...extraComponents, ...components], onClick: handleSelectComponent, onMouseDown: handleMouseDown, onMouseUp: handleMouseUp, onBlur: handleUnSelectComponent, selectedComponent: selectedComponent, activeTool: activeTool }) }) }) }) })] }));
296
+ };
297
+ export default BoardTemplate;
@@ -0,0 +1,6 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ const Navbar = () => {
4
+ return _jsx("div", { children: "Navbar" });
5
+ };
6
+ export default Navbar;
@@ -0,0 +1,41 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useEffect } from "react";
4
+ import Board from "../board";
5
+ import SideTool from "../side-tool";
6
+ import ControlPanels from "../panel";
7
+ import { useAppDispatch, useAppSelector } from "../../hooks/use-redux";
8
+ const TableEditor = (props) => {
9
+ const { componentProps, extraComponentProps, onCurrentStateChange } = props;
10
+ const { components, extraComponents } = useAppSelector((state) => state.board);
11
+ const dispatch = useAppDispatch();
12
+ useEffect(() => {
13
+ onCurrentStateChange &&
14
+ onCurrentStateChange({
15
+ components,
16
+ extraComponents,
17
+ });
18
+ }, [components, extraComponents]);
19
+ useEffect(() => {
20
+ if ((componentProps === null || componentProps === void 0 ? void 0 : componentProps.length) > 0) {
21
+ dispatch({
22
+ type: "board/setNewComponents",
23
+ payload: componentProps,
24
+ });
25
+ }
26
+ if ((extraComponentProps === null || extraComponentProps === void 0 ? void 0 : extraComponentProps.length) > 0) {
27
+ dispatch({
28
+ type: "board/setNewExtraComponent",
29
+ payload: extraComponentProps,
30
+ });
31
+ }
32
+ if (props === null || props === void 0 ? void 0 : props.defaultBackground) {
33
+ dispatch({
34
+ type: "board/setBackgroundColor",
35
+ payload: props === null || props === void 0 ? void 0 : props.defaultBackground,
36
+ });
37
+ }
38
+ }, [componentProps, extraComponentProps, props === null || props === void 0 ? void 0 : props.defaultBackground]);
39
+ return (_jsx(_Fragment, { children: _jsxs("div", { className: "w-full h-screen flex relative", children: [_jsx(SideTool, {}), _jsx(Board, { onSelectComponent: props.onSelectComponent }), _jsx(ControlPanels, { action: props.action, responseMapping: props.responseMapping })] }) }));
40
+ };
41
+ export default TableEditor;
@@ -0,0 +1,78 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import { useAppDispatch, useAppSelector } from "../../hooks/use-redux";
5
+ import { Form, Drawer, Input } from "antd";
6
+ import SelectToolForm from "./select-tool";
7
+ import SquareToolForm from "./square-circle-tool";
8
+ import SeatCircle from "./table-seat-circle";
9
+ import UploadTool from "./upload-tool";
10
+ const ControlPanels = (props) => {
11
+ const { action, responseMapping } = props;
12
+ const dispatch = useAppDispatch();
13
+ const tool = useAppSelector((state) => state.tool);
14
+ const selectedComponent = useAppSelector((state) => state.panel.selectedComponent);
15
+ const { show } = useAppSelector((state) => state.panel);
16
+ const [open, setOpen] = useState(false);
17
+ const [form] = Form.useForm();
18
+ let values = Form.useWatch([], form);
19
+ useEffect(() => {
20
+ if (selectedComponent) {
21
+ const isDifferentId = (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id) !== (values === null || values === void 0 ? void 0 : values.id) || !(values === null || values === void 0 ? void 0 : values.id);
22
+ const isSameIdAndSameDimensions = (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id) === (values === null || values === void 0 ? void 0 : values.id) &&
23
+ (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.height) === (values === null || values === void 0 ? void 0 : values.height) &&
24
+ (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.width) === (values === null || values === void 0 ? void 0 : values.width) &&
25
+ (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.x) === (values === null || values === void 0 ? void 0 : values.x) &&
26
+ (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.y) === (values === null || values === void 0 ? void 0 : values.y);
27
+ if (show && (isDifferentId || isSameIdAndSameDimensions)) {
28
+ setOpen(true);
29
+ }
30
+ form.setFieldsValue(selectedComponent);
31
+ }
32
+ else {
33
+ setOpen(false);
34
+ }
35
+ }, [selectedComponent]);
36
+ useEffect(() => {
37
+ if (tool.active === "background" || tool.active === "image-table") {
38
+ setOpen(true);
39
+ }
40
+ }, [tool]);
41
+ const handleChangeComponent = (values, allValues) => {
42
+ dispatch({
43
+ type: "board/updateComponent",
44
+ payload: Object.assign(Object.assign({}, (selectedComponent || {})), allValues),
45
+ });
46
+ dispatch({
47
+ type: "panel/updateSelectedComponent",
48
+ payload: Object.assign(Object.assign({}, (selectedComponent || {})), allValues),
49
+ });
50
+ };
51
+ const renderFormPanel = () => {
52
+ switch (tool.active) {
53
+ case "select":
54
+ return _jsx(SelectToolForm, {});
55
+ case "square":
56
+ case "circle":
57
+ return _jsx(SquareToolForm, {});
58
+ case "table-seat-circle":
59
+ return _jsx(SeatCircle, {});
60
+ case "image-table":
61
+ return (_jsx(UploadTool, { name: tool.active, type: "component", action: action, responseMapping: responseMapping }));
62
+ case "background":
63
+ return (_jsx(UploadTool, { name: tool.active, type: "background", action: action, responseMapping: responseMapping }));
64
+ default:
65
+ return null;
66
+ }
67
+ };
68
+ const handleClose = () => {
69
+ setOpen(false);
70
+ dispatch({
71
+ type: "panel/setShow",
72
+ payload: false,
73
+ });
74
+ };
75
+ // if(!show) return null
76
+ return (_jsx(Drawer, { open: show, onClose: handleClose, title: "Panel", children: _jsx("div", { className: "bg-white h-full max-h-screen overflow-y-auto w-[300px]", children: _jsxs(Form, { layout: "vertical", form: form, name: "table", onFinish: (values) => { }, onValuesChange: handleChangeComponent, initialValues: { labels: [{}] }, children: [_jsx(Form.Item, { name: "id", hidden: true, children: _jsx(Input, {}) }), renderFormPanel()] }) }) }));
77
+ };
78
+ export default ControlPanels;