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.
- package/dist/app/layout.js +22 -0
- package/dist/app/new-board/page.js +7 -0
- package/dist/app/old-board/page.js +382 -0
- package/dist/app/only-view/page.js +40 -0
- package/dist/app/only-view/page.jsx +5 -2
- package/dist/app/page.js +8 -0
- package/dist/components/button-tools/index.js +11 -0
- package/dist/components/form-tools/label.js +7 -0
- package/dist/components/form-tools/shape.js +7 -0
- package/dist/components/input/number-indicator.js +27 -0
- package/dist/components/layer/index.js +168 -0
- package/dist/components/lib/index.js +28 -0
- package/dist/components/modal-preview/index.js +10 -0
- package/dist/features/board/index.js +297 -0
- package/dist/features/navbar/index.js +6 -0
- package/dist/features/package/index.js +41 -0
- package/dist/features/panel/index.js +78 -0
- package/dist/features/panel/select-tool.js +36 -0
- package/dist/features/panel/square-circle-tool.js +8 -0
- package/dist/features/panel/table-seat-circle.js +9 -0
- package/dist/features/panel/text-tool.js +7 -0
- package/dist/features/panel/upload-tool.js +119 -0
- package/dist/features/side-tool/index.js +197 -0
- package/dist/features/view/index.d.ts +2 -0
- package/dist/features/view/index.js +156 -0
- package/dist/features/view/index.jsx +15 -7
- package/dist/provider/antd-provider.js +27 -0
- package/dist/provider/redux-provider.js +7 -0
- package/dist/provider/store-provider.js +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useAppSelector } from "../../hooks/use-redux";
|
|
4
|
+
import SquareToolForm from "./square-circle-tool";
|
|
5
|
+
import SeatCircle from "./table-seat-circle";
|
|
6
|
+
import UploadTool from "./upload-tool";
|
|
7
|
+
import TextTool from "./text-tool";
|
|
8
|
+
const SelectToolForm = ({ title = "Title" }) => {
|
|
9
|
+
const components = useAppSelector((state) => state.board.components);
|
|
10
|
+
const selectedComponent = useAppSelector((state) => state.panel.selectedComponent);
|
|
11
|
+
const SummaryComponents = () => {
|
|
12
|
+
const countByShape = components === null || components === void 0 ? void 0 : components.reduce((acc, item) => {
|
|
13
|
+
acc[item.shape] = (acc[item.shape] || 0) + 1;
|
|
14
|
+
return acc;
|
|
15
|
+
}, {});
|
|
16
|
+
return (_jsxs("div", { className: "flex flex-col", children: [_jsx("h1", { className: "heading-s", children: title }), _jsx("div", { className: "flex flex-col gap-2 mt-5", children: Object.entries(countByShape).map(([shape, count]) => (_jsxs("div", { children: [_jsxs("span", { className: "font-bold", children: [shape, ":"] }), " ", count] }, shape))) })] }));
|
|
17
|
+
};
|
|
18
|
+
const renderComponent = () => {
|
|
19
|
+
switch (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.shape) {
|
|
20
|
+
case "square":
|
|
21
|
+
case "circle":
|
|
22
|
+
return _jsx(SquareToolForm, {});
|
|
23
|
+
case "table-seat-circle":
|
|
24
|
+
return _jsx(SeatCircle, {});
|
|
25
|
+
case "image-table":
|
|
26
|
+
case "background":
|
|
27
|
+
return _jsx(UploadTool, { name: selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.name });
|
|
28
|
+
case "text":
|
|
29
|
+
return _jsx(TextTool, {});
|
|
30
|
+
default:
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
return (_jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(SummaryComponents, {}), renderComponent()] }));
|
|
35
|
+
};
|
|
36
|
+
export default SelectToolForm;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import SectionLabel from "../../components/form-tools/label";
|
|
4
|
+
import SectionShape from "../../components/form-tools/shape";
|
|
5
|
+
const SquareToolForm = () => {
|
|
6
|
+
return (_jsxs(_Fragment, { children: [_jsx(SectionShape, {}), _jsx(SectionLabel, {})] }));
|
|
7
|
+
};
|
|
8
|
+
export default SquareToolForm;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { ColorPicker, Flex, Form, InputNumber } from "antd";
|
|
4
|
+
import SectionLabel from "../../components/form-tools/label";
|
|
5
|
+
import SectionShape from "../../components/form-tools/shape";
|
|
6
|
+
const SeatCircle = () => {
|
|
7
|
+
return (_jsx(_Fragment, { children: _jsxs("div", { className: "py-2", children: [_jsx("h1", { className: "heading-s", children: " Round table" }), _jsxs(Flex, { children: [_jsx(Form.Item, { name: "seatCount", label: "Seat Count", className: "w-full", children: _jsx(InputNumber, {}) }), _jsx(Form.Item, { name: "openSpace", label: "Open Space", className: "w-full", children: _jsx(InputNumber, { max: 1, min: 0, step: 0.1 }) })] }), _jsxs(Flex, { gap: 2, children: [_jsx(Form.Item, { label: "Seat Fill", name: "seatFill", getValueFromEvent: (color) => color.toHexString(), className: "w-full ", children: _jsx(ColorPicker, { allowClear: true, format: "hex", defaultFormat: "hex" }) }), _jsx(Form.Item, { label: "Table Fill", name: "fill", getValueFromEvent: (color) => color.toHexString(), className: "w-full ", children: _jsx(ColorPicker, { allowClear: true, format: "hex", defaultFormat: "hex" }) })] }), _jsx(SectionShape, {}), _jsx(SectionLabel, {})] }) }));
|
|
8
|
+
};
|
|
9
|
+
export default SeatCircle;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { ColorPicker, Form, Input, InputNumber } from "antd";
|
|
4
|
+
const TextTool = () => {
|
|
5
|
+
return (_jsxs("div", { className: "py-2", children: [_jsx(Form.Item, { name: "text", label: "Text", children: _jsx(Input, {}) }), _jsx(Form.Item, { name: "fontColor", label: "Color", getValueFromEvent: (color) => color.toHexString(), children: _jsx(ColorPicker, { allowClear: true, format: "hex", defaultFormat: "hex" }) }), _jsx(Form.Item, { name: "x", label: "X", children: _jsx(InputNumber, {}) }), _jsx(Form.Item, { name: "y", label: "Y", children: _jsx(InputNumber, {}) }), _jsx(Form.Item, { name: "fontSize", label: "Size", children: _jsx(InputNumber, { suffix: "px" }) })] }));
|
|
6
|
+
};
|
|
7
|
+
export default TextTool;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
12
|
+
import { Upload, message } from "antd";
|
|
13
|
+
import { InboxOutlined } from "@ant-design/icons";
|
|
14
|
+
import { useAppDispatch } from "../../hooks/use-redux";
|
|
15
|
+
import SectionLabel from "../../components/form-tools/label";
|
|
16
|
+
import SectionShape from "../../components/form-tools/shape";
|
|
17
|
+
const { Dragger } = Upload;
|
|
18
|
+
// const actionResponseBased = {
|
|
19
|
+
// status: 200,
|
|
20
|
+
// message: "Upload successful",
|
|
21
|
+
// data: {
|
|
22
|
+
// id: "12345",
|
|
23
|
+
// url: "https://example.com/image.png",
|
|
24
|
+
// },
|
|
25
|
+
// };
|
|
26
|
+
const UploadTool = ({ name, type, action, responseMapping, }) => {
|
|
27
|
+
var _a, _b;
|
|
28
|
+
const dispatch = useAppDispatch();
|
|
29
|
+
const widthWorkspace = ((_a = document === null || document === void 0 ? void 0 : document.getElementById("workspace")) === null || _a === void 0 ? void 0 : _a.clientWidth) || 0;
|
|
30
|
+
const heightWorkspace = ((_b = document === null || document === void 0 ? void 0 : document.getElementById("workspace")) === null || _b === void 0 ? void 0 : _b.clientHeight) || 0;
|
|
31
|
+
const props = {
|
|
32
|
+
name: "file",
|
|
33
|
+
multiple: false,
|
|
34
|
+
maxCount: 1,
|
|
35
|
+
showUploadList: false,
|
|
36
|
+
onChange: (info) => __awaiter(void 0, void 0, void 0, function* () {
|
|
37
|
+
var _a;
|
|
38
|
+
const { status } = info.file;
|
|
39
|
+
if (status !== "uploading" && info.file.originFileObj) {
|
|
40
|
+
const file = info.file.originFileObj;
|
|
41
|
+
const img = new window.Image();
|
|
42
|
+
let srcFromResponse = "";
|
|
43
|
+
try {
|
|
44
|
+
// ⬇️ IF ada custom action (upload ke server)
|
|
45
|
+
if (action && responseMapping) {
|
|
46
|
+
const res = yield action(file);
|
|
47
|
+
const isSuccess = (res === null || res === void 0 ? void 0 : res[responseMapping.status]) === 200;
|
|
48
|
+
if (isSuccess) {
|
|
49
|
+
srcFromResponse =
|
|
50
|
+
(_a = res === null || res === void 0 ? void 0 : res[responseMapping.data]) === null || _a === void 0 ? void 0 : _a[responseMapping.src];
|
|
51
|
+
img.onload = () => {
|
|
52
|
+
const scaleX = widthWorkspace / img.width;
|
|
53
|
+
const scaleY = heightWorkspace / img.height;
|
|
54
|
+
const scale = Math.min(1, scaleX, scaleY);
|
|
55
|
+
const width = img.width * scale;
|
|
56
|
+
const height = img.height * scale;
|
|
57
|
+
dispatch({
|
|
58
|
+
type: type === "component"
|
|
59
|
+
? "board/addComponent"
|
|
60
|
+
: "board/setExtraComponent",
|
|
61
|
+
payload: {
|
|
62
|
+
id: new Date().getTime(),
|
|
63
|
+
x: 0,
|
|
64
|
+
y: 0,
|
|
65
|
+
width,
|
|
66
|
+
height,
|
|
67
|
+
rotation: 0,
|
|
68
|
+
shape: name,
|
|
69
|
+
src: srcFromResponse,
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
message.success(`${info.file.name} uploaded successfully.`);
|
|
73
|
+
};
|
|
74
|
+
// Set img src AFTER onload
|
|
75
|
+
img.src = srcFromResponse;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
message.error((res === null || res === void 0 ? void 0 : res[responseMapping.message]) || "Upload failed");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// ⬇️ IF local upload
|
|
82
|
+
else {
|
|
83
|
+
img.onload = () => {
|
|
84
|
+
const scaleX = widthWorkspace / img.width;
|
|
85
|
+
const scaleY = heightWorkspace / img.height;
|
|
86
|
+
const scale = Math.min(1, scaleX, scaleY);
|
|
87
|
+
const width = img.width * scale;
|
|
88
|
+
const height = img.height * scale;
|
|
89
|
+
dispatch({
|
|
90
|
+
type: type === "component"
|
|
91
|
+
? "board/addComponent"
|
|
92
|
+
: "board/setExtraComponent",
|
|
93
|
+
payload: {
|
|
94
|
+
id: new Date().getTime(),
|
|
95
|
+
x: 0,
|
|
96
|
+
y: 0,
|
|
97
|
+
width,
|
|
98
|
+
height,
|
|
99
|
+
rotation: 0,
|
|
100
|
+
shape: name,
|
|
101
|
+
src: img.src,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
message.success(`${info.file.name} uploaded successfully.`);
|
|
105
|
+
};
|
|
106
|
+
// Set img src AFTER onload
|
|
107
|
+
img.src = URL.createObjectURL(file);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch (e) {
|
|
111
|
+
console.error("Upload error:", e);
|
|
112
|
+
message.error("Upload failed, please try again.");
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}),
|
|
116
|
+
};
|
|
117
|
+
return (_jsxs(_Fragment, { children: [_jsxs(Dragger, Object.assign({}, props, { children: [_jsx("p", { className: "ant-upload-drag-icon", children: _jsx(InboxOutlined, {}) }), _jsx("p", { className: "ant-upload-text", children: "Click or drag file to this area to upload" }), _jsx("p", { className: "ant-upload-hint", children: "Support for a single or bulk upload. Strictly prohibited from uploading company data or other banned files." })] })), _jsx(SectionShape, {}), _jsx(SectionLabel, {})] }));
|
|
118
|
+
};
|
|
119
|
+
export default UploadTool;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Circle, CopyPlus, Eye, EyeOff, Image, Layers2, MousePointer, PaintBucket, Ratio, SquareMousePointer, Trash, Type, Upload, } from "lucide-react";
|
|
4
|
+
import ButtonTools from "../../components/button-tools";
|
|
5
|
+
import { Divider, ColorPicker, Button, } from "antd";
|
|
6
|
+
import { useAppDispatch, useAppSelector } from "../../hooks/use-redux";
|
|
7
|
+
import { useState } from "react";
|
|
8
|
+
const SideTool = () => {
|
|
9
|
+
const [color, setColor] = useState("#000000");
|
|
10
|
+
const dispatch = useAppDispatch();
|
|
11
|
+
const { active } = useAppSelector((state) => state.tool);
|
|
12
|
+
const { selectedComponent } = useAppSelector((state) => state.panel);
|
|
13
|
+
const { components } = useAppSelector((state) => state.board);
|
|
14
|
+
const [preview, setPreview] = useState(false);
|
|
15
|
+
const tools = [
|
|
16
|
+
{
|
|
17
|
+
id: "select",
|
|
18
|
+
name: "Select Tool",
|
|
19
|
+
icon: _jsx(MousePointer, {}),
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
const actionsTools = [
|
|
23
|
+
// {
|
|
24
|
+
// id: "table-split",
|
|
25
|
+
// name: "Table Split",
|
|
26
|
+
// icon: <TableCellsSplit />,
|
|
27
|
+
// },
|
|
28
|
+
{
|
|
29
|
+
id: "square",
|
|
30
|
+
name: "Square",
|
|
31
|
+
icon: _jsx(SquareMousePointer, {}),
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: "circle",
|
|
35
|
+
name: "Circle",
|
|
36
|
+
icon: _jsx(Circle, {}),
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "table-seat-circle",
|
|
40
|
+
name: "Table Seat Circle",
|
|
41
|
+
icon: _jsx(Ratio, {}),
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: "image-table",
|
|
45
|
+
name: "Image Table",
|
|
46
|
+
icon: _jsx(Upload, {}),
|
|
47
|
+
},
|
|
48
|
+
// {
|
|
49
|
+
// id: "table-seat-square",
|
|
50
|
+
// name: "Table Seat Square",
|
|
51
|
+
// icon: <Dock />,
|
|
52
|
+
// },
|
|
53
|
+
// {
|
|
54
|
+
// id: "diamond",
|
|
55
|
+
// name: "Diamond",
|
|
56
|
+
// icon: <Diamond />,
|
|
57
|
+
// },
|
|
58
|
+
];
|
|
59
|
+
const controlTools = [
|
|
60
|
+
{
|
|
61
|
+
id: "background",
|
|
62
|
+
name: "Background",
|
|
63
|
+
icon: _jsx(Image, {}),
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: "text",
|
|
67
|
+
name: "Text",
|
|
68
|
+
icon: _jsx(Type, {}),
|
|
69
|
+
},
|
|
70
|
+
// {
|
|
71
|
+
// id: "background-color",
|
|
72
|
+
// name: "Background Color",
|
|
73
|
+
// icon: <PaintBucket/>
|
|
74
|
+
// }
|
|
75
|
+
];
|
|
76
|
+
const hanldeSelectTool = (id) => {
|
|
77
|
+
if (id === "background" || id === "text" || id === "image-table") {
|
|
78
|
+
dispatch({
|
|
79
|
+
type: "panel/setShow",
|
|
80
|
+
payload: true
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
dispatch({
|
|
84
|
+
type: "tool/setActiveTool",
|
|
85
|
+
payload: id,
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
const handleChangeColorBackground = (color) => {
|
|
89
|
+
setColor(color.toHexString());
|
|
90
|
+
dispatch({
|
|
91
|
+
type: "board/setBackgroundColor",
|
|
92
|
+
payload: color.toHexString(),
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
const handleOpenModalPreview = () => {
|
|
96
|
+
dispatch({
|
|
97
|
+
type: "tool/setTooglePreview",
|
|
98
|
+
payload: true,
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
const handleRemoveComponent = () => {
|
|
102
|
+
dispatch({
|
|
103
|
+
type: "board/removeComponent",
|
|
104
|
+
payload: selectedComponent,
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
const handleDuplicateComponent = () => {
|
|
108
|
+
const newComponent = Object.assign(Object.assign({}, selectedComponent), { x: selectedComponent.x + 20, y: selectedComponent.y + 20, id: Date.now() });
|
|
109
|
+
dispatch({
|
|
110
|
+
type: "board/addComponent",
|
|
111
|
+
payload: newComponent
|
|
112
|
+
});
|
|
113
|
+
dispatch({
|
|
114
|
+
type: "panel/setSelectedComponent",
|
|
115
|
+
payload: newComponent
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
function swapOneStepById(arr, id, direction) {
|
|
119
|
+
const index = arr.findIndex(item => (item === null || item === void 0 ? void 0 : item.id) === id);
|
|
120
|
+
if (index === -1)
|
|
121
|
+
return arr; // id tidak ditemukan
|
|
122
|
+
const newArr = [...arr];
|
|
123
|
+
if (direction === 'left' && index > 0) {
|
|
124
|
+
[newArr[index - 1], newArr[index]] = [newArr[index], newArr[index - 1]];
|
|
125
|
+
}
|
|
126
|
+
if (direction === 'right' && index < arr.length - 1) {
|
|
127
|
+
[newArr[index + 1], newArr[index]] = [newArr[index], newArr[index + 1]];
|
|
128
|
+
}
|
|
129
|
+
return newArr;
|
|
130
|
+
}
|
|
131
|
+
const handleOverride = () => {
|
|
132
|
+
const newArr = swapOneStepById(components, selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id, 'right');
|
|
133
|
+
dispatch({
|
|
134
|
+
type: "board/setNewComponents",
|
|
135
|
+
payload: newArr
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
return (_jsxs("div", { className: "h-screen left-0 flex flex-col items-center border-r-2 border-gray-300 bg-white px-2 pt-4", children: [tools === null || tools === void 0 ? void 0 : tools.map((tool) => (_jsx(ButtonTools, { buttonProps: {
|
|
139
|
+
icon: tool.icon,
|
|
140
|
+
type: "text",
|
|
141
|
+
name: tool.name,
|
|
142
|
+
onClick: () => hanldeSelectTool(tool.id),
|
|
143
|
+
style: active === tool.id ? { color: "red" } : {},
|
|
144
|
+
}, popoverProps: {
|
|
145
|
+
content: _jsx("div", { children: tool.name }),
|
|
146
|
+
trigger: "hover",
|
|
147
|
+
placement: "right",
|
|
148
|
+
}, items: [] }, tool.id))), _jsx(ButtonTools, { buttonProps: {
|
|
149
|
+
icon: _jsx(CopyPlus, {}),
|
|
150
|
+
type: "text",
|
|
151
|
+
name: "duplicate",
|
|
152
|
+
onClick: () => handleDuplicateComponent(),
|
|
153
|
+
}, items: [], popoverProps: {
|
|
154
|
+
content: _jsx("div", { children: "Duplicate" }),
|
|
155
|
+
trigger: "hover",
|
|
156
|
+
placement: "right",
|
|
157
|
+
} }), _jsx(ButtonTools, { buttonProps: {
|
|
158
|
+
onClick: () => handleRemoveComponent(),
|
|
159
|
+
icon: _jsx(Trash, {}),
|
|
160
|
+
type: "text",
|
|
161
|
+
name: "trash",
|
|
162
|
+
}, items: [], popoverProps: {
|
|
163
|
+
content: _jsx("div", { children: "Trash" }),
|
|
164
|
+
trigger: "hover",
|
|
165
|
+
placement: "right",
|
|
166
|
+
} }), _jsx(ButtonTools, { buttonProps: {
|
|
167
|
+
onClick: () => handleOverride(),
|
|
168
|
+
icon: _jsx(Layers2, {}),
|
|
169
|
+
type: "text",
|
|
170
|
+
name: "override",
|
|
171
|
+
}, items: [], popoverProps: {
|
|
172
|
+
content: _jsx("div", { children: "Override" }),
|
|
173
|
+
trigger: "hover",
|
|
174
|
+
placement: "right",
|
|
175
|
+
} }), _jsx(Divider, {}), actionsTools === null || actionsTools === void 0 ? void 0 : actionsTools.map((tool) => (_jsx(ButtonTools, { buttonProps: {
|
|
176
|
+
icon: tool.icon,
|
|
177
|
+
type: "text",
|
|
178
|
+
name: tool.name,
|
|
179
|
+
onClick: () => hanldeSelectTool(tool.id),
|
|
180
|
+
style: active === tool.id ? { color: "red" } : {},
|
|
181
|
+
}, popoverProps: {
|
|
182
|
+
content: _jsx("div", { children: tool.name }),
|
|
183
|
+
trigger: "hover",
|
|
184
|
+
placement: "right",
|
|
185
|
+
}, items: [] }, tool.id))), _jsx(Divider, {}), controlTools === null || controlTools === void 0 ? void 0 : controlTools.map((tool) => (_jsx(ButtonTools, { buttonProps: {
|
|
186
|
+
icon: tool.icon,
|
|
187
|
+
type: "text",
|
|
188
|
+
name: tool.name,
|
|
189
|
+
onClick: () => hanldeSelectTool(tool.id),
|
|
190
|
+
style: active === tool.id ? { color: "red" } : {},
|
|
191
|
+
}, popoverProps: {
|
|
192
|
+
content: _jsx("div", { children: tool.name }),
|
|
193
|
+
trigger: "hover",
|
|
194
|
+
placement: "right",
|
|
195
|
+
}, items: [] }, tool.id))), _jsx(ColorPicker, { value: color, onChange: handleChangeColorBackground, children: _jsx(Button, { icon: _jsx(PaintBucket, {}), type: "text", name: "Background Color", onClick: () => hanldeSelectTool("background-color"), style: active === "background-color" ? { color: "red" } : {} }) }), _jsx(Button, { icon: preview ? _jsx(EyeOff, {}) : _jsx(Eye, {}), type: "text", name: "Preview", onClick: handleOpenModalPreview, style: active === "preview" ? { color: "red" } : {} })] }));
|
|
196
|
+
};
|
|
197
|
+
export default SideTool;
|
|
@@ -12,6 +12,8 @@ export interface LayerViewProps {
|
|
|
12
12
|
statusKey: string;
|
|
13
13
|
defaultBackground?: string;
|
|
14
14
|
transformProps?: any;
|
|
15
|
+
containerProps?: any;
|
|
16
|
+
svgProps?: any;
|
|
15
17
|
}
|
|
16
18
|
declare const LayerView: (props: LayerViewProps) => import("react").JSX.Element;
|
|
17
19
|
export default LayerView;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { TransformWrapper, TransformComponent, } from "react-zoom-pan-pinch";
|
|
6
|
+
import { useAppDispatch, useAppSelector } from "../../hooks/use-redux";
|
|
7
|
+
import Layers from "../../components/layer";
|
|
8
|
+
const LayerView = (props) => {
|
|
9
|
+
const { componentProps, extraComponentProps, onSelectComponent, onCurrentStateChange, mappingKey, selectedTableColor, colorMatchKey, statusKey, defaultBackground, } = props;
|
|
10
|
+
const transformRef = useRef(null);
|
|
11
|
+
const containerRef = useRef(null);
|
|
12
|
+
const svgRef = useRef(null);
|
|
13
|
+
const [scale, setScale] = useState(1);
|
|
14
|
+
const [selectedTable, setSelectedTable] = useState(null);
|
|
15
|
+
const { components: componentsEditor, extraComponents: extraComponentsEditor, } = useAppSelector((state) => state.board);
|
|
16
|
+
const backgroundColor = useAppSelector((state) => state.board.backgroundColor);
|
|
17
|
+
const dispatch = useAppDispatch();
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if ((componentProps === null || componentProps === void 0 ? void 0 : componentProps.length) > 0) {
|
|
20
|
+
dispatch({
|
|
21
|
+
type: "board/setNewComponents",
|
|
22
|
+
payload: componentProps,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
if ((extraComponentProps === null || extraComponentProps === void 0 ? void 0 : extraComponentProps.length) > 0) {
|
|
26
|
+
dispatch({
|
|
27
|
+
type: "board/setNewExtraComponents",
|
|
28
|
+
payload: extraComponentProps,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
if (defaultBackground) {
|
|
32
|
+
dispatch({
|
|
33
|
+
type: "board/setBackgroundColor",
|
|
34
|
+
payload: defaultBackground,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}, [componentProps, extraComponentProps, defaultBackground]);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
onCurrentStateChange &&
|
|
40
|
+
onCurrentStateChange({
|
|
41
|
+
components: componentsEditor,
|
|
42
|
+
extraComponents: extraComponentsEditor,
|
|
43
|
+
});
|
|
44
|
+
}, [componentsEditor, extraComponentsEditor]);
|
|
45
|
+
const handleSelectComponent = (items) => {
|
|
46
|
+
const find = componentsEditor.find((item) => {
|
|
47
|
+
if (mappingKey && (item === null || item === void 0 ? void 0 : item[mappingKey])) {
|
|
48
|
+
return item[mappingKey].id === (items === null || items === void 0 ? void 0 : items.id);
|
|
49
|
+
}
|
|
50
|
+
return (item === null || item === void 0 ? void 0 : item.id) === (items === null || items === void 0 ? void 0 : items.id);
|
|
51
|
+
});
|
|
52
|
+
onSelectComponent && onSelectComponent(find);
|
|
53
|
+
setSelectedTable(find);
|
|
54
|
+
};
|
|
55
|
+
const boundingBox = useMemo(() => {
|
|
56
|
+
if (!componentsEditor && (componentsEditor === null || componentsEditor === void 0 ? void 0 : componentsEditor.length) === 0) {
|
|
57
|
+
return { minX: 0, minY: 0, width: 500, height: 500 };
|
|
58
|
+
}
|
|
59
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
60
|
+
componentsEditor === null || componentsEditor === void 0 ? void 0 : componentsEditor.forEach((_) => {
|
|
61
|
+
var _a, _b, _c, _d;
|
|
62
|
+
let values = mappingKey ? _[mappingKey] : _.shape;
|
|
63
|
+
if (!values)
|
|
64
|
+
return;
|
|
65
|
+
if ((_a = values === null || values === void 0 ? void 0 : values.shape) === null || _a === void 0 ? void 0 : _a.includes("square")) {
|
|
66
|
+
minX = Math.min(minX, values.x);
|
|
67
|
+
minY = Math.min(minY, values.y);
|
|
68
|
+
maxX = Math.max(maxX, values.x + values.width);
|
|
69
|
+
maxY = Math.max(maxY, values.y + values.height);
|
|
70
|
+
}
|
|
71
|
+
if ((_b = values === null || values === void 0 ? void 0 : values.shape) === null || _b === void 0 ? void 0 : _b.includes("circle")) {
|
|
72
|
+
minX = Math.min(minX, values.x);
|
|
73
|
+
minY = Math.min(minY, values.y);
|
|
74
|
+
maxX = Math.max(maxX, values.x + values.width);
|
|
75
|
+
maxY = Math.max(maxY, values.y + values.height);
|
|
76
|
+
}
|
|
77
|
+
if ((_c = values === null || values === void 0 ? void 0 : values.shape) === null || _c === void 0 ? void 0 : _c.includes("table-seat-circle")) {
|
|
78
|
+
minX = Math.min(minX, values.x);
|
|
79
|
+
minY = Math.min(minY, values.y);
|
|
80
|
+
maxX = Math.max(maxX, values.x + values.width);
|
|
81
|
+
maxY = Math.max(maxY, values.y + values.height);
|
|
82
|
+
}
|
|
83
|
+
if ((_d = values === null || values === void 0 ? void 0 : values.shape) === null || _d === void 0 ? void 0 : _d.includes("image-table")) {
|
|
84
|
+
minX = Math.min(minX, values.x);
|
|
85
|
+
minY = Math.min(minY, values.y);
|
|
86
|
+
maxX = Math.max(maxX, values.x + values.width);
|
|
87
|
+
maxY = Math.max(maxY, values.y + values.height);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
extraComponentsEditor === null || extraComponentsEditor === void 0 ? void 0 : extraComponentsEditor.forEach((values) => {
|
|
91
|
+
var _a;
|
|
92
|
+
if ((_a = values === null || values === void 0 ? void 0 : values.shape) === null || _a === void 0 ? void 0 : _a.includes("background")) {
|
|
93
|
+
minX = values.x;
|
|
94
|
+
minY = values.y;
|
|
95
|
+
maxX = values.width;
|
|
96
|
+
maxY = values.height;
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
if ((extraComponentsEditor === null || extraComponentsEditor === void 0 ? void 0 : extraComponentsEditor.length) < 1) {
|
|
100
|
+
minX = minX - minX * 0.5;
|
|
101
|
+
minY = minY - minY * 0.5;
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
minX,
|
|
105
|
+
minY,
|
|
106
|
+
width: maxX,
|
|
107
|
+
height: maxY,
|
|
108
|
+
};
|
|
109
|
+
}, [componentsEditor, extraComponentsEditor]);
|
|
110
|
+
let elementEditor = [, ...componentsEditor];
|
|
111
|
+
const renderElements = (elementEditor, mappingKey, colorMatchKey) => {
|
|
112
|
+
return elementEditor.map((editorItem, i) => {
|
|
113
|
+
var _a, _b, _c, _d;
|
|
114
|
+
const isUsingMapping = mappingKey &&
|
|
115
|
+
typeof editorItem[mappingKey] === "object" &&
|
|
116
|
+
editorItem[mappingKey] !== null;
|
|
117
|
+
const finalProps = isUsingMapping ? editorItem[mappingKey] : editorItem;
|
|
118
|
+
if (colorMatchKey) {
|
|
119
|
+
if (isUsingMapping) {
|
|
120
|
+
return Object.assign(Object.assign({}, finalProps), { fill: (_b = (_a = colorMatchKey.find((item) => item.key == (editorItem === null || editorItem === void 0 ? void 0 : editorItem[statusKey]))) === null || _a === void 0 ? void 0 : _a.color) !== null && _b !== void 0 ? _b : finalProps.fill });
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
return Object.assign(Object.assign({}, finalProps), { fill: (_d = (_c = colorMatchKey.find((item) => item.key == (editorItem === null || editorItem === void 0 ? void 0 : editorItem[statusKey]))) === null || _c === void 0 ? void 0 : _c.color) !== null && _d !== void 0 ? _d : finalProps.fill });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return finalProps;
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
return (_jsx("div", Object.assign({ className: "relative w-full h-full flex-1", ref: containerRef, style: {
|
|
130
|
+
height: "100vh",
|
|
131
|
+
overflow: "auto",
|
|
132
|
+
WebkitOverflowScrolling: "touch",
|
|
133
|
+
touchAction: "pan-y",
|
|
134
|
+
} }, props.containerProps, { children: _jsx(TransformWrapper, Object.assign({ ref: transformRef }, props.transformProps, { panning: {
|
|
135
|
+
disabled: false,
|
|
136
|
+
velocityDisabled: true,
|
|
137
|
+
}, limitToBounds: false, doubleClick: { disabled: true }, pinch: { disabled: false }, wheel: { disabled: true }, disabled: true, disablePadding: true, centerZoomedOut: true, onTransformed: ({ state: { scale } }) => setScale(scale), minScale: 1, maxScale: 1000, initialScale: 1,
|
|
138
|
+
// pinch={{ step: 1 }}
|
|
139
|
+
smooth: true, children: _jsx(TransformComponent, { wrapperStyle: {
|
|
140
|
+
width: "100%",
|
|
141
|
+
height: "100%",
|
|
142
|
+
overflow: "visible",
|
|
143
|
+
}, contentStyle: {
|
|
144
|
+
width: "100%",
|
|
145
|
+
height: "100%",
|
|
146
|
+
}, children: _jsx("svg", Object.assign({}, props.svgProps, { id: "workspace", ref: svgRef, width: "100%", height: "100%", viewBox: `${boundingBox.minX} ${boundingBox.minY} ${boundingBox.width} ${boundingBox.height}`, className: "h-full", xmlns: "http://www.w3.org/2000/svg", preserveAspectRatio: "xMidYMid meet", style: {
|
|
147
|
+
background: "#000000",
|
|
148
|
+
display: "block",
|
|
149
|
+
pointerEvents: "auto",
|
|
150
|
+
touchAction: "pan-y",
|
|
151
|
+
}, children: _jsx(Layers, { mode: "view", components: [
|
|
152
|
+
...extraComponentsEditor,
|
|
153
|
+
...renderElements(componentsEditor, mappingKey, colorMatchKey),
|
|
154
|
+
], onClick: handleSelectComponent, selectedTable: selectedTable, selectedTableColor: selectedTableColor }) })) }) })) })));
|
|
155
|
+
};
|
|
156
|
+
export default LayerView;
|
|
@@ -130,11 +130,19 @@ const LayerView = (props) => {
|
|
|
130
130
|
overflow: "auto",
|
|
131
131
|
WebkitOverflowScrolling: "touch",
|
|
132
132
|
touchAction: "pan-y",
|
|
133
|
-
}}>
|
|
134
|
-
<TransformWrapper ref={transformRef} {...props.transformProps}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
}} {...props.containerProps}>
|
|
134
|
+
<TransformWrapper ref={transformRef} {...props.transformProps}
|
|
135
|
+
// panning={{
|
|
136
|
+
// disabled: false,
|
|
137
|
+
// velocityDisabled: true,
|
|
138
|
+
// }}
|
|
139
|
+
// limitToBounds={false}
|
|
140
|
+
// doubleClick={{ disabled: true }}
|
|
141
|
+
// pinch={{ disabled: false }}
|
|
142
|
+
// wheel={{ disabled: true }}
|
|
143
|
+
// disabled={true}
|
|
144
|
+
// disablePadding={true}
|
|
145
|
+
centerZoomedOut={true} onTransformed={({ state: { scale } }) => setScale(scale)} minScale={1} maxScale={1000} initialScale={1}
|
|
138
146
|
// pinch={{ step: 1 }}
|
|
139
147
|
smooth={true}>
|
|
140
148
|
<TransformComponent wrapperStyle={{
|
|
@@ -145,11 +153,11 @@ const LayerView = (props) => {
|
|
|
145
153
|
width: "100%",
|
|
146
154
|
height: "100%",
|
|
147
155
|
}}>
|
|
148
|
-
<svg id="workspace" ref={svgRef} width="100%" height="100%" viewBox={`${boundingBox.minX} ${boundingBox.minY} ${boundingBox.width} ${boundingBox.height}`} className="h-full" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" style={{
|
|
156
|
+
<svg {...props.svgProps} id="workspace" ref={svgRef} width="100%" height="100%" viewBox={`${boundingBox.minX} ${boundingBox.minY} ${boundingBox.width} ${boundingBox.height}`} className="h-full" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet" style={{
|
|
149
157
|
background: "#000000",
|
|
150
158
|
display: "block",
|
|
151
159
|
pointerEvents: "auto",
|
|
152
|
-
touchAction: "
|
|
160
|
+
// touchAction: "pan-y",
|
|
153
161
|
}}>
|
|
154
162
|
<Layers mode="view" components={[
|
|
155
163
|
...extraComponentsEditor,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { ConfigProvider } from "antd";
|
|
4
|
+
import { AntdRegistry } from "@ant-design/nextjs-registry";
|
|
5
|
+
import { useAppSelector } from "../hooks/use-redux";
|
|
6
|
+
export const AntdProvider = ({ children, }) => {
|
|
7
|
+
const theme = useAppSelector((state) => state.theme);
|
|
8
|
+
return (_jsx(AntdRegistry, { children: _jsx(ConfigProvider, { theme: {
|
|
9
|
+
// token: {
|
|
10
|
+
// colorPrimary: theme.theme["--primary-color"],
|
|
11
|
+
// colorPrimaryBorderHover: theme.theme["--primary-color"],
|
|
12
|
+
// fontFamily: "var(--font-inter), sans-serif",
|
|
13
|
+
// colorError: theme.theme["--danger"],
|
|
14
|
+
// controlOutlineWidth: 4,
|
|
15
|
+
// controlOutline: theme.theme["--surface-color"],
|
|
16
|
+
// colorBgContainerDisabled: "var(--netral-03)",
|
|
17
|
+
// colorTextPlaceholder: "var(--netral-06)",
|
|
18
|
+
// },
|
|
19
|
+
components: {
|
|
20
|
+
Form: {
|
|
21
|
+
labelFontSize: 14,
|
|
22
|
+
fontWeightStrong: 500,
|
|
23
|
+
itemMarginBottom: 12,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
}, children: children }) }));
|
|
27
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { ReduxProvider } from "./redux-provider";
|
|
4
|
+
import { AntdProvider } from "./antd-provider";
|
|
5
|
+
export const StoreProvider = ({ children }) => {
|
|
6
|
+
return (_jsx(ReduxProvider, { children: _jsx(AntdProvider, { children: children }) }));
|
|
7
|
+
};
|