seat-editor 3.4.7 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist/app/constant.d.ts +1 -1
  2. package/dist/app/graph-view/page.d.ts +1 -0
  3. package/dist/app/graph-view/page.js +343 -0
  4. package/dist/app/graph-view/page.jsx +445 -0
  5. package/dist/app/graph-view-new/constant.d.ts +581 -0
  6. package/dist/app/graph-view-new/constant.js +6973 -0
  7. package/dist/app/graph-view-new/page.d.ts +1 -0
  8. package/dist/app/graph-view-new/page.js +71 -0
  9. package/dist/app/graph-view-new/page.jsx +98 -0
  10. package/dist/app/new-board/page.js +43 -7
  11. package/dist/app/new-board/page.jsx +45 -12
  12. package/dist/components/button-tools/index.js +7 -5
  13. package/dist/components/button-tools/index.jsx +21 -9
  14. package/dist/components/form-tools/label.js +9 -20
  15. package/dist/components/form-tools/label.jsx +38 -28
  16. package/dist/components/form-tools/shape.js +5 -5
  17. package/dist/components/form-tools/shape.jsx +8 -8
  18. package/dist/components/layer-v3/index.js +44 -3
  19. package/dist/components/layer-v3/index.jsx +120 -3
  20. package/dist/components/layer-v4/index.js +3 -2
  21. package/dist/components/layer-v4/index.jsx +3 -2
  22. package/dist/components/layer-v5/constant.d.ts +60 -0
  23. package/dist/components/layer-v5/constant.js +93 -0
  24. package/dist/components/layer-v5/index.d.ts +24 -0
  25. package/dist/components/layer-v5/index.js +927 -0
  26. package/dist/components/layer-v5/index.jsx +1049 -0
  27. package/dist/features/board-v3/index.js +350 -72
  28. package/dist/features/board-v3/index.jsx +369 -75
  29. package/dist/features/board-v3/resize-element.js +5 -0
  30. package/dist/features/board-v3/utils.d.ts +8 -0
  31. package/dist/features/board-v3/utils.js +23 -7
  32. package/dist/features/package/index.d.ts +2 -0
  33. package/dist/features/package/index.js +1 -1
  34. package/dist/features/package/index.jsx +6 -1
  35. package/dist/features/panel/index.d.ts +8 -0
  36. package/dist/features/panel/index.js +160 -38
  37. package/dist/features/panel/index.jsx +173 -46
  38. package/dist/features/panel/polygon.d.ts +2 -0
  39. package/dist/features/panel/polygon.js +44 -0
  40. package/dist/features/panel/polygon.jsx +70 -0
  41. package/dist/features/panel/select-tool.js +3 -0
  42. package/dist/features/panel/select-tool.jsx +3 -0
  43. package/dist/features/panel/selected-group.js +24 -26
  44. package/dist/features/panel/selected-group.jsx +56 -51
  45. package/dist/features/panel/text-tool.js +17 -2
  46. package/dist/features/panel/text-tool.jsx +19 -2
  47. package/dist/features/panel/upload-tool.js +17 -3
  48. package/dist/features/panel/upload-tool.jsx +23 -4
  49. package/dist/features/side-tool/index.js +43 -6
  50. package/dist/features/side-tool/index.jsx +47 -10
  51. package/dist/features/view-only-4/connect-handle.d.ts +13 -0
  52. package/dist/features/view-only-4/connect-handle.js +23 -0
  53. package/dist/features/view-only-4/connect-handle.jsx +30 -0
  54. package/dist/features/view-only-4/connection-layer.d.ts +21 -0
  55. package/dist/features/view-only-4/connection-layer.js +219 -0
  56. package/dist/features/view-only-4/connection-layer.jsx +291 -0
  57. package/dist/features/view-only-4/index.d.ts +99 -0
  58. package/dist/features/view-only-4/index.js +684 -0
  59. package/dist/features/view-only-4/index.jsx +722 -0
  60. package/dist/features/view-only-4/integration-guide.d.ts +0 -0
  61. package/dist/features/view-only-4/integration-guide.js +0 -0
  62. package/dist/features/view-only-4/use-connection-graph.d.ts +41 -0
  63. package/dist/features/view-only-4/use-connection-graph.js +182 -0
  64. package/dist/features/view-only-4/utils.d.ts +74 -0
  65. package/dist/features/view-only-4/utils.js +106 -0
  66. package/dist/features/view-only-5/connect-handle.d.ts +30 -0
  67. package/dist/features/view-only-5/connect-handle.js +88 -0
  68. package/dist/features/view-only-5/connect-handle.jsx +96 -0
  69. package/dist/features/view-only-5/connection-layer.d.ts +34 -0
  70. package/dist/features/view-only-5/connection-layer.js +182 -0
  71. package/dist/features/view-only-5/connection-layer.jsx +265 -0
  72. package/dist/features/view-only-5/index.d.ts +102 -0
  73. package/dist/features/view-only-5/index.js +585 -0
  74. package/dist/features/view-only-5/index.jsx +614 -0
  75. package/dist/features/view-only-5/use-connection-graph.d.ts +57 -0
  76. package/dist/features/view-only-5/use-connection-graph.js +196 -0
  77. package/dist/features/view-only-5/utils.d.ts +52 -0
  78. package/dist/features/view-only-5/utils.js +80 -0
  79. package/dist/features/view-only-6/connect-handle.d.ts +13 -0
  80. package/dist/features/view-only-6/connect-handle.js +20 -0
  81. package/dist/features/view-only-6/connect-handle.jsx +21 -0
  82. package/dist/features/view-only-6/connection-layer.d.ts +22 -0
  83. package/dist/features/view-only-6/connection-layer.js +191 -0
  84. package/dist/features/view-only-6/connection-layer.jsx +244 -0
  85. package/dist/features/view-only-6/index.d.ts +99 -0
  86. package/dist/features/view-only-6/index.js +687 -0
  87. package/dist/features/view-only-6/index.jsx +724 -0
  88. package/dist/features/view-only-6/use-connection-graph.d.ts +26 -0
  89. package/dist/features/view-only-6/use-connection-graph.js +103 -0
  90. package/dist/features/view-only-6/utils.d.ts +66 -0
  91. package/dist/features/view-only-6/utils.js +96 -0
  92. package/dist/features/view-only-7/connect-handle.d.ts +13 -0
  93. package/dist/features/view-only-7/connect-handle.js +23 -0
  94. package/dist/features/view-only-7/connect-handle.jsx +30 -0
  95. package/dist/features/view-only-7/connection-layer.d.ts +22 -0
  96. package/dist/features/view-only-7/connection-layer.js +165 -0
  97. package/dist/features/view-only-7/connection-layer.jsx +217 -0
  98. package/dist/features/view-only-7/index.d.ts +99 -0
  99. package/dist/features/view-only-7/index.js +687 -0
  100. package/dist/features/view-only-7/index.jsx +724 -0
  101. package/dist/features/view-only-7/use-connection-graph.d.ts +26 -0
  102. package/dist/features/view-only-7/use-connection-graph.js +104 -0
  103. package/dist/features/view-only-7/utils.d.ts +69 -0
  104. package/dist/features/view-only-7/utils.js +144 -0
  105. package/dist/index.d.ts +2 -1
  106. package/dist/index.js +2 -1
  107. package/dist/seat-editor.css +1 -1
  108. package/package.json +1 -1
@@ -1,16 +1,18 @@
1
1
  "use client";
2
2
  import { optionsShape } from "../../components/form-tools/shape";
3
3
  import { ColorPicker, Flex, Form, InputNumber, Select } from "antd";
4
- import SeatCircle from "./table-seat-circle";
5
- import SeatSquare from "./table-seat-square";
6
4
  import { useAppSelector } from "../../hooks/use-redux";
7
5
  import SectionLabel from "../../components/form-tools/label";
6
+ import { useFormPlaceholder } from ".";
8
7
  const { Option } = Select;
9
8
  const SelectedGroup = () => {
10
9
  var _a;
10
+ const { placeholders, setPlaceholder, unsetPlaceholder, setPlaceholderBulk, resetPlaceholders, } = useFormPlaceholder();
11
11
  const shape = Form.useWatch("shape");
12
12
  const selectedGroup = useAppSelector((state) => state.panel.selectedGroup);
13
13
  const allShapeSelected = selectedGroup.map((item) => item.shape);
14
+ const hasExtraComponent = allShapeSelected.some((shape) => ["text", "background", "polygon"].includes(shape));
15
+ console.log({ hasExtraComponent });
14
16
  const sameShape = [
15
17
  "table-seat-circle",
16
18
  "table-seat-rect-circle",
@@ -30,60 +32,62 @@ const SelectedGroup = () => {
30
32
  <div className="py-2">
31
33
  <h1 className="heading-s"> Group Selection</h1>
32
34
  <div className="py-2">
33
- {/* {!shapeIncludeImage && ( */}
34
- <Flex gap={2} className="w-full">
35
+ {!hasExtraComponent && (<Flex gap={2} className="w-full">
35
36
  <Form.Item label="Name" name="shape" className="w-full">
36
37
  <Select className="w-full">
37
38
  {optionsSelect === null || optionsSelect === void 0 ? void 0 : optionsSelect.map((item) => {
38
- const disabled = item.value === "table-seat-rect-circle" && maxSeat;
39
- return (<Option key={item.value} value={item.value} disabled={disabled}>
40
- {item.value === "table-seat-rect-circle" ?
41
- `Type 5 (only for 4 ${seatKey})` : item.label}
39
+ const disabled = item.value === "table-seat-rect-circle" && maxSeat;
40
+ return (<Option key={item.value} value={item.value} disabled={disabled}>
41
+ {item.value === "table-seat-rect-circle"
42
+ ? `Type 5 (only for 4 ${seatKey})`
43
+ : item.label}
42
44
  </Option>);
43
- })}
45
+ })}
44
46
  </Select>
45
47
  </Form.Item>
46
- </Flex>
47
- {/* )} */}
48
- <Flex gap={2} className="w-full">
49
- {["table-seat-circle", "table-seat-rect-circle"].includes(shape) && <SeatCircle />}
50
- {[
48
+ </Flex>)}
49
+ {/* <Flex gap={2} className="w-full">
50
+ {["table-seat-circle", "table-seat-rect-circle"].includes(
51
+ shape
52
+ ) && <SeatCircle />}
53
+ {[
51
54
  "table-seat-square",
52
55
  "table-seat-square",
53
56
  "table-seat-rect-square",
54
57
  "table-seat-half-square",
55
- ].includes(shape) && <SeatSquare />}
56
- </Flex>
57
- {!sameShape && (<>
58
- <Flex gap={2} className="w-full">
58
+ ].includes(shape) && <SeatSquare />}
59
+ </Flex> */}
60
+ {/* {!sameShape && (
61
+ <> */}
62
+ <Flex gap={2} className="w-full" vertical>
59
63
  {!shapeAllIncludePolygon && (<>
60
- <Form.Item label="Width" name="width" className="w-full">
61
- <InputNumber suffix="px"/>
64
+ <Form.Item label="Width" name="width" className="w-full" layout="horizontal" labelCol={{ style: { width: 100, textAlign: "left" } }} wrapperCol={{ style: { flex: 1 } }}>
65
+ <InputNumber suffix="px" name="width" placeholder={placeholders["width"]} style={{ width: "100%" }}/>
62
66
  </Form.Item>
63
- <Form.Item label="Height" name="height" className="w-full">
64
- <InputNumber suffix="px"/>
67
+ <Form.Item label="Height" name="height" className="w-full" layout="horizontal" labelCol={{ style: { width: 100, textAlign: "left" } }} wrapperCol={{ style: { flex: 1 } }}>
68
+ <InputNumber suffix="px" name="height" placeholder={placeholders["height"]} style={{ width: "100%" }}/>
65
69
  </Form.Item>
66
70
  </>)}
67
- {!(shape === null || shape === void 0 ? void 0 : shape.includes("circle")) && !shapeAllIncludePolygon && (<Form.Item label="Radius" name={"radius"} className="w-full">
68
- <InputNumber suffix="px" parser={(value) => {
69
- var _a;
70
- const onlyNumber = (_a = value === null || value === void 0 ? void 0 : value.replace(/\D/g, "")) !== null && _a !== void 0 ? _a : "";
71
- return onlyNumber === ""
72
- ? 1
73
- : Math.max(1, Number(onlyNumber));
74
- }}/>
71
+ {!(shape === null || shape === void 0 ? void 0 : shape.includes("circle")) && !shapeAllIncludePolygon && (<Form.Item label="Radius" name={"radius"} className="w-full" layout="horizontal" labelCol={{ style: { width: 100, textAlign: "left" } }} wrapperCol={{ style: { flex: 1 } }}>
72
+ <InputNumber name={"radius"} suffix="px" style={{ width: "100%" }} placeholder={placeholders["radius"]} parser={(value) => {
73
+ var _a;
74
+ const onlyNumber = (_a = value === null || value === void 0 ? void 0 : value.replace(/\D/g, "")) !== null && _a !== void 0 ? _a : "";
75
+ return onlyNumber === ""
76
+ ? 1
77
+ : Math.max(1, Number(onlyNumber));
78
+ }}/>
75
79
  </Form.Item>)}
76
80
  </Flex>
77
81
  {!shapeAllIncludePolygon && (<>
78
- <Flex gap={2}>
79
- <Form.Item label="Position X" name="x" className="w-full">
80
- <InputNumber />
82
+ <Flex gap={2} vertical>
83
+ <Form.Item label="Position X" name="x" className="w-full" layout="horizontal" labelCol={{ style: { width: 100, textAlign: "left" } }} wrapperCol={{ style: { flex: 1 } }}>
84
+ <InputNumber placeholder={placeholders["x"]} style={{ width: "100%" }} suffix="px" name="x"/>
81
85
  </Form.Item>
82
- <Form.Item label="Position Y" name="y" className="w-full">
83
- <InputNumber />
86
+ <Form.Item label="Position Y" name="y" className="w-full" layout="horizontal" labelCol={{ style: { width: 100, textAlign: "left" } }} wrapperCol={{ style: { flex: 1 } }}>
87
+ <InputNumber suffix="px" name="y" placeholder={placeholders["y"]} style={{ width: "100%" }}/>
84
88
  </Form.Item>
85
- <Form.Item label="Rotation" name="rotation" className="w-full">
86
- <InputNumber max={360} min={0}/>
89
+ <Form.Item label="Rotation" name="rotation" className="w-full" layout="horizontal" labelCol={{ style: { width: 100, textAlign: "left" } }} wrapperCol={{ style: { flex: 1 } }}>
90
+ <InputNumber name="rotation" suffix="°" max={360} min={0} style={{ width: "100%" }} placeholder={placeholders["rotation"]}/>
87
91
  </Form.Item>
88
92
  </Flex>
89
93
  </>)}
@@ -95,24 +99,25 @@ const SelectedGroup = () => {
95
99
  <ColorPicker allowClear format="hex" defaultFormat="hex"/>
96
100
  </Form.Item>
97
101
  </Flex>
98
- <Flex>
99
- <Form.Item label="Stroke Width" name={"strokeWidth"} className="w-full">
100
- <InputNumber />
102
+ <Flex vertical>
103
+ <Form.Item label="Stroke Size" name={"strokeWidth"} className="w-full" layout="horizontal" labelCol={{ style: { width: 100, textAlign: "left" } }} wrapperCol={{ style: { flex: 1 } }}>
104
+ <InputNumber name={"strokeWidth"} suffix="px" style={{ width: "100%" }} placeholder={placeholders["strokeWidth"]}/>
101
105
  </Form.Item>
102
- <Form.Item label="opacity" name={"opacity"} className="w-full">
103
- <InputNumber step={10} max={100} min={0} parser={(value) => {
104
- if (value === undefined || value === null || value === "")
105
- return null;
106
- const cleaned = value.replace(/[^0-9.]/g, "");
107
- const num = Number(cleaned);
108
- if (Number.isNaN(num))
109
- return null;
110
- return Math.min(100, Math.max(0, num));
111
- }} suffix="%"/>
106
+ <Form.Item label="opacity" name={"opacity"} className="w-full" layout="horizontal" labelCol={{ style: { width: 100, textAlign: "left" } }} wrapperCol={{ style: { flex: 1 } }}>
107
+ <InputNumber style={{ width: "100%" }} step={10} max={100} min={0} placeholder={placeholders["opacity"]} parser={(value) => {
108
+ if (value === undefined || value === null || value === "")
109
+ return null;
110
+ const cleaned = value.replace(/[^0-9.]/g, "");
111
+ const num = Number(cleaned);
112
+ if (Number.isNaN(num))
113
+ return null;
114
+ return Math.min(100, Math.max(0, num));
115
+ }} suffix="%"/>
112
116
  </Form.Item>
113
117
  </Flex>
114
118
  <SectionLabel />
115
- </>)}
119
+ {/* </>
120
+ )} */}
116
121
  </div>
117
122
  </div>
118
123
  </>);
@@ -1,7 +1,22 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { ColorPicker, Flex, Form, Input, InputNumber } from "antd";
3
+ import { useAppDispatch, useAppSelector } from "@/hooks/use-redux";
4
+ import { Button, ColorPicker, Flex, Form, Input, InputNumber } from "antd";
4
5
  const TextTool = () => {
6
+ const dispatch = useAppDispatch();
7
+ const selectedComponent = useAppSelector((state) => state.panel.selectedComponent);
8
+ const deleteText = () => {
9
+ dispatch({
10
+ type: "board/removeExtraComponent",
11
+ payload: selectedComponent,
12
+ });
13
+ dispatch({ type: "board/setFlagChange", payload: true });
14
+ dispatch({ type: "board/setUpdateBy", payload: "global" });
15
+ dispatch({ type: "panel/setSelectedComponent", payload: null });
16
+ dispatch({ type: "panel/setSelectedGroup", payload: null });
17
+ dispatch({ type: "panel/setShow", payload: false });
18
+ dispatch({ type: "tool/setActiveTool", payload: "select" });
19
+ };
5
20
  return (_jsxs("div", { className: "py-2", children: [_jsx(Form.Item, { label: "Name", name: "shape", className: "w-full hidden", children: _jsx(Input, { defaultValue: "text" }) }), _jsx(Form.Item, { name: "text", label: "Text", children: _jsx(Input, {}) }), _jsxs(Flex, { className: "w-full", gap: 2, children: [_jsx(Form.Item, { name: "fontColor", label: "Color", getValueFromEvent: (color) => color.toHexString(), children: _jsx(ColorPicker, { allowClear: true, format: "hex", defaultFormat: "hex" }) }), _jsx(Form.Item, { name: "fontSize", label: "Size", children: _jsx(InputNumber, { suffix: "px" }) })] }), _jsxs(Flex, { gap: 2, className: "w-full", children: [_jsx(Form.Item, { label: "Width", name: "width", className: "w-full", children: _jsx(InputNumber, { suffix: "px", controls: true, parser: (value) => {
6
21
  var _a;
7
22
  const onlyNumber = (_a = value === null || value === void 0 ? void 0 : value.replace(/\D/g, "")) !== null && _a !== void 0 ? _a : "";
@@ -17,6 +32,6 @@ const TextTool = () => {
17
32
  if (Number.isNaN(num))
18
33
  return 0;
19
34
  return Math.min(360, Math.max(0, num));
20
- } }) })] })] }));
35
+ } }) })] }), _jsx(Button, { type: "default", onClick: deleteText, className: "w-full", children: "Delete" })] }));
21
36
  };
22
37
  export default TextTool;
@@ -1,6 +1,21 @@
1
1
  "use client";
2
- import { ColorPicker, Flex, Form, Input, InputNumber } from "antd";
2
+ import { useAppDispatch, useAppSelector } from "@/hooks/use-redux";
3
+ import { Button, ColorPicker, Flex, Form, Input, InputNumber } from "antd";
3
4
  const TextTool = () => {
5
+ const dispatch = useAppDispatch();
6
+ const selectedComponent = useAppSelector((state) => state.panel.selectedComponent);
7
+ const deleteText = () => {
8
+ dispatch({
9
+ type: "board/removeExtraComponent",
10
+ payload: selectedComponent,
11
+ });
12
+ dispatch({ type: "board/setFlagChange", payload: true });
13
+ dispatch({ type: "board/setUpdateBy", payload: "global" });
14
+ dispatch({ type: "panel/setSelectedComponent", payload: null });
15
+ dispatch({ type: "panel/setSelectedGroup", payload: null });
16
+ dispatch({ type: "panel/setShow", payload: false });
17
+ dispatch({ type: "tool/setActiveTool", payload: "select" });
18
+ };
4
19
  return (<div className="py-2">
5
20
  <Form.Item label="Name" name="shape" className="w-full hidden">
6
21
  <Input defaultValue={"text"}/>
@@ -51,7 +66,9 @@ const TextTool = () => {
51
66
  }}/>
52
67
  </Form.Item>
53
68
  </Flex>
54
-
69
+ <Button type="default" onClick={deleteText} className="w-full">
70
+ Delete
71
+ </Button>
55
72
  </div>);
56
73
  };
57
74
  export default TextTool;
@@ -8,9 +8,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
11
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
12
12
  import { useState, useEffect } from "react";
13
- import { Upload, Image, Button, Form } from "antd";
13
+ import { Upload, Image, Button, Form, Flex } from "antd";
14
14
  import { InboxOutlined, LoadingOutlined } from "@ant-design/icons";
15
15
  import { useAppDispatch, useAppSelector } from "../../hooks/use-redux";
16
16
  import SectionLabel from "../../components/form-tools/label";
@@ -55,6 +55,7 @@ const UploadTool = ({ name, type, action, defaultValue, transform, }) => {
55
55
  rotation: 0,
56
56
  shape: name,
57
57
  src,
58
+ opacity: 1,
58
59
  });
59
60
  const propsUpload = {
60
61
  name: "file",
@@ -147,6 +148,19 @@ const UploadTool = ({ name, type, action, defaultValue, transform, }) => {
147
148
  const handleDelete = () => {
148
149
  setDefaultSrc(null);
149
150
  };
150
- return (_jsxs(Form.Item, { label: "", name: "src", className: "w-full", children: [defaultSrc ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "w-full flex flex-col items-center gap-2 max-h-[200px] overflow-y-auto", children: _jsx(Image, { src: defaultSrc }) }), _jsx(Button, { type: "primary", onClick: handleDelete, className: "w-full mt-4", children: "Edit" })] })) : (_jsx(Dragger, Object.assign({ beforeUpload: () => false }, propsUpload, { children: loading ? (_jsx("div", { className: "w-full flex flex-col items-center gap-2 max-h-[200px]", children: _jsx(LoadingOutlined, {}) })) : (_jsxs(_Fragment, { 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." })] })) }))), (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id) && (_jsxs(_Fragment, { children: [_jsx(SectionShape, { allowChangeShape: type === "component" }), _jsx(SectionLabel, {})] }))] }));
151
+ const deleteImages = () => {
152
+ setLoading(true);
153
+ dispatch({
154
+ type: "board/removeExtraComponent",
155
+ payload: selectedComponent,
156
+ });
157
+ dispatch({ type: "board/setFlagChange", payload: true });
158
+ dispatch({ type: "board/setUpdateBy", payload: "global" });
159
+ dispatch({ type: "panel/setSelectedComponent", payload: null });
160
+ dispatch({ type: "panel/setSelectedGroup", payload: null });
161
+ dispatch({ type: "panel/setShow", payload: false });
162
+ dispatch({ type: "tool/setActiveTool", payload: "select" });
163
+ };
164
+ return (_jsxs(Form.Item, { label: "", name: "src", className: "w-full", children: [defaultSrc ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "w-full flex flex-col items-center gap-2 max-h-[200px] overflow-y-auto", children: _jsx(Image, { src: defaultSrc }) }), _jsxs(Flex, { vertical: true, gap: 5, children: [_jsx(Button, { type: "primary", onClick: handleDelete, className: "w-full mt-4", loading: loading, children: "Edit" }), _jsx(Button, { type: "default", onClick: deleteImages, className: "w-full", loading: loading, children: "Delete" })] })] })) : (_jsx(Dragger, Object.assign({ beforeUpload: () => false }, propsUpload, { children: loading ? (_jsx("div", { className: "w-full flex flex-col items-center gap-2 max-h-[200px]", children: _jsx(LoadingOutlined, {}) })) : (_jsxs(_Fragment, { 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." })] })) }))), (selectedComponent === null || selectedComponent === void 0 ? void 0 : selectedComponent.id) && (_jsxs(_Fragment, { children: [_jsx(SectionShape, { allowChangeShape: type === "component" }), _jsx(SectionLabel, {})] }))] }));
151
165
  };
152
166
  export default UploadTool;
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  import { useState, useEffect } from "react";
12
- import { Upload, Image, Button, Form } from "antd";
12
+ import { Upload, Image, Button, Form, Flex } from "antd";
13
13
  import { InboxOutlined, LoadingOutlined } from "@ant-design/icons";
14
14
  import { useAppDispatch, useAppSelector } from "../../hooks/use-redux";
15
15
  import SectionLabel from "../../components/form-tools/label";
@@ -54,6 +54,7 @@ const UploadTool = ({ name, type, action, defaultValue, transform, }) => {
54
54
  rotation: 0,
55
55
  shape: name,
56
56
  src,
57
+ opacity: 1,
57
58
  });
58
59
  const propsUpload = {
59
60
  name: "file",
@@ -146,14 +147,32 @@ const UploadTool = ({ name, type, action, defaultValue, transform, }) => {
146
147
  const handleDelete = () => {
147
148
  setDefaultSrc(null);
148
149
  };
150
+ const deleteImages = () => {
151
+ setLoading(true);
152
+ dispatch({
153
+ type: "board/removeExtraComponent",
154
+ payload: selectedComponent,
155
+ });
156
+ dispatch({ type: "board/setFlagChange", payload: true });
157
+ dispatch({ type: "board/setUpdateBy", payload: "global" });
158
+ dispatch({ type: "panel/setSelectedComponent", payload: null });
159
+ dispatch({ type: "panel/setSelectedGroup", payload: null });
160
+ dispatch({ type: "panel/setShow", payload: false });
161
+ dispatch({ type: "tool/setActiveTool", payload: "select" });
162
+ };
149
163
  return (<Form.Item label="" name="src" className="w-full">
150
164
  {defaultSrc ? (<>
151
165
  <div className="w-full flex flex-col items-center gap-2 max-h-[200px] overflow-y-auto">
152
166
  <Image src={defaultSrc}/>
153
167
  </div>
154
- <Button type="primary" onClick={handleDelete} className="w-full mt-4">
155
- Edit
156
- </Button>
168
+ <Flex vertical gap={5}>
169
+ <Button type="primary" onClick={handleDelete} className="w-full mt-4" loading={loading}>
170
+ Edit
171
+ </Button>
172
+ <Button type="default" onClick={deleteImages} className="w-full" loading={loading}>
173
+ Delete
174
+ </Button>
175
+ </Flex>
157
176
  </>) : (<Dragger beforeUpload={() => false} {...propsUpload}>
158
177
  {loading ? (<div className="w-full flex flex-col items-center gap-2 max-h-[200px]">
159
178
  <LoadingOutlined />
@@ -79,12 +79,12 @@ const SideTool = ({ dragOnly, deleteAutorized, }) => {
79
79
  const controlTools = [
80
80
  {
81
81
  id: "background",
82
- name: "Background",
82
+ name: "Image Tool",
83
83
  icon: _jsx(Image, {}),
84
84
  },
85
85
  {
86
86
  id: "text",
87
- name: "Text",
87
+ name: "Text Tool",
88
88
  icon: _jsx(Type, {}),
89
89
  },
90
90
  {
@@ -267,13 +267,17 @@ const SideTool = ({ dragOnly, deleteAutorized, }) => {
267
267
  dispatch({ type: "board/undoHistory" });
268
268
  dispatch({ type: "board/setFlagChange", payload: true });
269
269
  dispatch({ type: "board/setUpdateBy", payload: "global" });
270
+ dispatch({ type: "panel/setShow", payload: false });
270
271
  };
271
272
  const handleRedo = () => {
272
273
  dispatch({ type: "board/redoHistory" });
273
274
  dispatch({ type: "board/setFlagChange", payload: true });
274
275
  dispatch({ type: "board/setUpdateBy", payload: "global" });
276
+ dispatch({ type: "panel/setShow", payload: false });
275
277
  };
276
- return (_jsxs("div", { className: "h-full 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: {
278
+ const [openPreview, setOpenPreview] = useState(false);
279
+ const [colorPickerOpen, setColorPickerOpen] = useState(false);
280
+ return (_jsxs("div", { className: "h-full left-0 flex flex-col items-center border-r-2 border-gray-300 bg-white px-2 pt-4 mt-[78px]", children: [tools === null || tools === void 0 ? void 0 : tools.map((tool) => (_jsx(ButtonTools, { buttonProps: {
277
281
  icon: tool.icon,
278
282
  type: "text",
279
283
  name: tool.name,
@@ -330,13 +334,46 @@ const SideTool = ({ dragOnly, deleteAutorized, }) => {
330
334
  content: _jsx("div", { children: tool.name }),
331
335
  trigger: "hover",
332
336
  placement: "right",
333
- }, 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(Popover, { trigger: "hover", placement: "right", content: _jsxs(Flex, { vertical: true, children: [_jsx(Button, { icon: _jsx(Scan, {}), type: "text", name: "Bounding Box", onClick: () => hanldeSelectTool("bounding-box"), style: active === "bounding-box" ? { color: "red" } : {} }), _jsx(Button, { icon: preview ? _jsx(EyeOff, {}) : _jsx(Eye, {}), type: "text", name: "Preview", onClick: handleOpenModalPreview, style: active === "preview" ? { color: "red" } : {} })] }), children: _jsx(Button, { icon: _jsx(ScanEye, {}), type: "text" }) }), _jsx(Button, { icon: _jsx(Grid, {}), type: "text", name: "Grid", onClick: () => toggleGrid() }), _jsx(ButtonTools, { buttonProps: {
337
+ }, items: [] }, tool.id))), _jsx(ColorPicker, { value: color, open: colorPickerOpen, onOpenChange: setColorPickerOpen, onChange: handleChangeColorBackground, placement: "right", children: _jsx(ButtonTools, { buttonProps: {
338
+ icon: _jsx(PaintBucket, {}),
339
+ type: "text",
340
+ name: "background-color",
341
+ style: active === "background-color" ? { color: "red" } : {},
342
+ onClick: () => {
343
+ hanldeSelectTool("background-color");
344
+ setColorPickerOpen((prev) => !prev);
345
+ },
346
+ }, items: [], popoverProps: {
347
+ content: _jsx("div", { children: "Fill Tool" }),
348
+ trigger: "hover",
349
+ placement: "right",
350
+ } }) }), _jsx(Popover, { trigger: "click", placement: "right", open: openPreview, onOpenChange: setOpenPreview, content: _jsxs(Flex, { vertical: true, children: [_jsx(Button, { icon: _jsx(Scan, {}), type: "text", name: "Bounding Box", onClick: () => hanldeSelectTool("bounding-box"), style: active === "bounding-box" ? { color: "red" } : {} }), _jsx(Button, { icon: preview ? _jsx(EyeOff, {}) : _jsx(Eye, {}), type: "text", name: "Preview", onClick: handleOpenModalPreview, style: active === "preview" ? { color: "red" } : {} })] }), children: _jsx(ButtonTools, { buttonProps: {
351
+ icon: _jsx(ScanEye, {}),
352
+ type: "text",
353
+ name: "Preview",
354
+ onClick: () => setOpenPreview((prev) => !prev),
355
+ style: (active === "bounding-box") || (active === "preview") ? { color: "red" } : {},
356
+ }, items: [], popoverProps: {
357
+ content: _jsx("div", { children: "Layour View Tool" }),
358
+ trigger: "hover",
359
+ placement: "right",
360
+ } }) }), _jsx(ButtonTools, { buttonProps: {
361
+ icon: _jsx(Grid, {}),
362
+ onClick: () => toggleGrid(),
363
+ type: "text",
364
+ name: "Grid",
365
+ style: active === "grid" ? { color: "red" } : {},
366
+ }, items: [], popoverProps: {
367
+ content: _jsx("div", { children: "Grid Tool" }),
368
+ trigger: "hover",
369
+ placement: "right",
370
+ } }), _jsx(ButtonTools, { buttonProps: {
334
371
  onClick: () => handleRemoveComponent(),
335
372
  icon: _jsx(Trash, {}),
336
373
  type: "text",
337
374
  name: "trash",
338
375
  }, items: [], popoverProps: {
339
- content: _jsx("div", { children: "Trash" }),
376
+ content: _jsx("div", { children: "Trash Tool" }),
340
377
  trigger: "hover",
341
378
  placement: "right",
342
379
  } }), _jsx(ButtonTools, { buttonProps: {
@@ -345,7 +382,7 @@ const SideTool = ({ dragOnly, deleteAutorized, }) => {
345
382
  type: "text",
346
383
  name: "trash",
347
384
  }, items: [], popoverProps: {
348
- content: (_jsx("div", { children: lockBackground ? "Unlock Background" : "Lock Background" })),
385
+ content: (_jsx("div", { children: lockBackground ? "Unlock Images Tool" : "Lock Images Tool" })),
349
386
  trigger: "hover",
350
387
  placement: "right",
351
388
  } }), _jsx(ButtonTools, { buttonProps: {
@@ -78,12 +78,12 @@ const SideTool = ({ dragOnly, deleteAutorized, }) => {
78
78
  const controlTools = [
79
79
  {
80
80
  id: "background",
81
- name: "Background",
81
+ name: "Image Tool",
82
82
  icon: <Image />,
83
83
  },
84
84
  {
85
85
  id: "text",
86
- name: "Text",
86
+ name: "Text Tool",
87
87
  icon: <Type />,
88
88
  },
89
89
  {
@@ -266,13 +266,17 @@ const SideTool = ({ dragOnly, deleteAutorized, }) => {
266
266
  dispatch({ type: "board/undoHistory" });
267
267
  dispatch({ type: "board/setFlagChange", payload: true });
268
268
  dispatch({ type: "board/setUpdateBy", payload: "global" });
269
+ dispatch({ type: "panel/setShow", payload: false });
269
270
  };
270
271
  const handleRedo = () => {
271
272
  dispatch({ type: "board/redoHistory" });
272
273
  dispatch({ type: "board/setFlagChange", payload: true });
273
274
  dispatch({ type: "board/setUpdateBy", payload: "global" });
275
+ dispatch({ type: "panel/setShow", payload: false });
274
276
  };
275
- return (<div className="h-full left-0 flex flex-col items-center border-r-2 border-gray-300 bg-white px-2 pt-4">
277
+ const [openPreview, setOpenPreview] = useState(false);
278
+ const [colorPickerOpen, setColorPickerOpen] = useState(false);
279
+ return (<div className="h-full left-0 flex flex-col items-center border-r-2 border-gray-300 bg-white px-2 pt-4 mt-[78px]">
276
280
  {tools === null || tools === void 0 ? void 0 : tools.map((tool) => (<ButtonTools key={tool.id} buttonProps={{
277
281
  icon: tool.icon,
278
282
  type: "text",
@@ -343,25 +347,58 @@ const SideTool = ({ dragOnly, deleteAutorized, }) => {
343
347
  trigger: "hover",
344
348
  placement: "right",
345
349
  }} items={[]}/>))}
346
- <ColorPicker value={color} onChange={handleChangeColorBackground}>
347
- <Button icon={<PaintBucket />} type="text" name="Background Color" onClick={() => hanldeSelectTool("background-color")} style={active === "background-color" ? { color: "red" } : {}}/>
350
+ <ColorPicker value={color} open={colorPickerOpen} onOpenChange={setColorPickerOpen} onChange={handleChangeColorBackground} placement="right">
351
+ <ButtonTools buttonProps={{
352
+ icon: <PaintBucket />,
353
+ type: "text",
354
+ name: "background-color",
355
+ style: active === "background-color" ? { color: "red" } : {},
356
+ onClick: () => {
357
+ hanldeSelectTool("background-color");
358
+ setColorPickerOpen((prev) => !prev);
359
+ },
360
+ }} items={[]} popoverProps={{
361
+ content: <div>Fill Tool</div>,
362
+ trigger: "hover",
363
+ placement: "right",
364
+ }}/>
348
365
  </ColorPicker>
349
366
 
350
- <Popover trigger={"hover"} placement="right" content={<Flex vertical>
367
+ <Popover trigger={"click"} placement="right" open={openPreview} onOpenChange={setOpenPreview} content={<Flex vertical>
351
368
  <Button icon={<Scan />} type="text" name="Bounding Box" onClick={() => hanldeSelectTool("bounding-box")} style={active === "bounding-box" ? { color: "red" } : {}}/>
352
369
  <Button icon={preview ? <EyeOff /> : <Eye />} type="text" name="Preview" onClick={handleOpenModalPreview} style={active === "preview" ? { color: "red" } : {}}/>
353
370
  </Flex>}>
354
- <Button icon={<ScanEye />} type="text"/>
371
+ <ButtonTools buttonProps={{
372
+ icon: <ScanEye />,
373
+ type: "text",
374
+ name: "Preview",
375
+ onClick: () => setOpenPreview((prev) => !prev),
376
+ style: (active === "bounding-box") || (active === "preview") ? { color: "red" } : {},
377
+ }} items={[]} popoverProps={{
378
+ content: <div>Layour View Tool</div>,
379
+ trigger: "hover",
380
+ placement: "right",
381
+ }}/>
355
382
  </Popover>
356
383
 
357
- <Button icon={<Grid />} type="text" name="Grid" onClick={() => toggleGrid()}/>
384
+ <ButtonTools buttonProps={{
385
+ icon: <Grid />,
386
+ onClick: () => toggleGrid(),
387
+ type: "text",
388
+ name: "Grid",
389
+ style: active === "grid" ? { color: "red" } : {},
390
+ }} items={[]} popoverProps={{
391
+ content: <div>Grid Tool</div>,
392
+ trigger: "hover",
393
+ placement: "right",
394
+ }}/>
358
395
  <ButtonTools buttonProps={{
359
396
  onClick: () => handleRemoveComponent(),
360
397
  icon: <Trash />,
361
398
  type: "text",
362
399
  name: "trash",
363
400
  }} items={[]} popoverProps={{
364
- content: <div>Trash</div>,
401
+ content: <div>Trash Tool</div>,
365
402
  trigger: "hover",
366
403
  placement: "right",
367
404
  }}/>
@@ -372,7 +409,7 @@ const SideTool = ({ dragOnly, deleteAutorized, }) => {
372
409
  name: "trash",
373
410
  }} items={[]} popoverProps={{
374
411
  content: (<div>
375
- {lockBackground ? "Unlock Background" : "Lock Background"}
412
+ {lockBackground ? "Unlock Images Tool" : "Lock Images Tool"}
376
413
  </div>),
377
414
  trigger: "hover",
378
415
  placement: "right",
@@ -0,0 +1,13 @@
1
+ type Props = {
2
+ cx: number;
3
+ cy: number;
4
+ width: number;
5
+ height: number;
6
+ nodeId: string;
7
+ rotation?: number;
8
+ isConnecting: boolean;
9
+ onStartConnect: (nodeId: string) => void;
10
+ onEndConnect: (nodeId: string) => void;
11
+ };
12
+ export declare const ConnectHandle: React.FC<Props>;
13
+ export {};
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export const ConnectHandle = ({ cx, cy, width, height, nodeId, rotation = 0, // ← tambah ini
3
+ isConnecting, onStartConnect, onEndConnect, }) => {
4
+ const hw = width / 2;
5
+ const hh = height / 2;
6
+ // Tombol ⊕ di pojok kanan atas (dalam local space)
7
+ const btnLocalX = hw - 2;
8
+ const btnLocalY = -hh - 8;
9
+ return (
10
+ // Semua di-wrap dalam g dengan translate ke center + rotate
11
+ // Sama persis seperti struktur render node aslinya
12
+ _jsx("g", { transform: `translate(${cx}, ${cy}) rotate(${rotation})`, children: isConnecting ? (
13
+ // Mode connecting: overlay seluruh node
14
+ _jsx("rect", { x: -hw - 4, y: -hh - 4, width: width + 8, height: height + 8, fill: "transparent", stroke: "#a78bfa", strokeWidth: 1.5, strokeDasharray: "4 2", rx: 4, style: { cursor: "crosshair" }, onMouseDown: (e) => {
15
+ e.stopPropagation();
16
+ onEndConnect(nodeId);
17
+ } })) : (
18
+ // Tombol ⊕ — posisi relatif dari center node
19
+ _jsxs("g", { transform: `translate(${btnLocalX}, ${btnLocalY})`, style: { cursor: "crosshair" }, onMouseDown: (e) => {
20
+ e.stopPropagation();
21
+ onStartConnect(nodeId);
22
+ }, children: [_jsx("circle", { r: 8, fill: "#0a0e1a", stroke: "#38bdf8", strokeWidth: 1.2, opacity: 0.9 }), _jsx("text", { textAnchor: "middle", dominantBaseline: "middle", fill: "#38bdf8", fontSize: 11, fontWeight: 700, style: { pointerEvents: "none", userSelect: "none" }, children: "\u2295" })] })) }));
23
+ };
@@ -0,0 +1,30 @@
1
+ export const ConnectHandle = ({ cx, cy, width, height, nodeId, rotation = 0, // ← tambah ini
2
+ isConnecting, onStartConnect, onEndConnect, }) => {
3
+ const hw = width / 2;
4
+ const hh = height / 2;
5
+ // Tombol ⊕ di pojok kanan atas (dalam local space)
6
+ const btnLocalX = hw - 2;
7
+ const btnLocalY = -hh - 8;
8
+ return (
9
+ // Semua di-wrap dalam g dengan translate ke center + rotate
10
+ // Sama persis seperti struktur render node aslinya
11
+ <g transform={`translate(${cx}, ${cy}) rotate(${rotation})`}>
12
+
13
+ {isConnecting ? (
14
+ // Mode connecting: overlay seluruh node
15
+ <rect x={-hw - 4} y={-hh - 4} width={width + 8} height={height + 8} fill="transparent" stroke="#a78bfa" strokeWidth={1.5} strokeDasharray="4 2" rx={4} style={{ cursor: "crosshair" }} onMouseDown={(e) => {
16
+ e.stopPropagation();
17
+ onEndConnect(nodeId);
18
+ }}/>) : (
19
+ // Tombol ⊕ — posisi relatif dari center node
20
+ <g transform={`translate(${btnLocalX}, ${btnLocalY})`} style={{ cursor: "crosshair" }} onMouseDown={(e) => {
21
+ e.stopPropagation();
22
+ onStartConnect(nodeId);
23
+ }}>
24
+ <circle r={8} fill="#0a0e1a" stroke="#38bdf8" strokeWidth={1.2} opacity={0.9}/>
25
+ <text textAnchor="middle" dominantBaseline="middle" fill="#38bdf8" fontSize={11} fontWeight={700} style={{ pointerEvents: "none", userSelect: "none" }}>
26
+
27
+ </text>
28
+ </g>)}
29
+ </g>);
30
+ };
@@ -0,0 +1,21 @@
1
+ import React from "react";
2
+ import { NodeType } from "./utils";
3
+ import { EdgeType } from "./utils";
4
+ type Props = {
5
+ edges: EdgeType[];
6
+ selectedEdge: string | null;
7
+ connecting: {
8
+ fromId: string;
9
+ } | null;
10
+ mousePos: {
11
+ x: number;
12
+ y: number;
13
+ };
14
+ getNodeById: (id: string) => NodeType | null;
15
+ onSelectEdge: (edgeId: string) => void;
16
+ onStartDragWaypoint: (e: React.MouseEvent, edgeId: string, index: number) => void;
17
+ onInsertWaypoint: (e: React.MouseEvent, edgeId: string, insertIndex: number, x: number, y: number) => void;
18
+ onRemoveWaypoint: (e: React.MouseEvent, edgeId: string, index: number) => void;
19
+ };
20
+ export declare const ConnectionLayer: React.FC<Props>;
21
+ export {};