@bemedev/mind-flow 0.3.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -12
- package/lib/helpers/clamp.d.ts +2 -0
- package/lib/helpers/clamp.d.ts.map +1 -0
- package/lib/helpers/createContext.d.ts +1 -1
- package/lib/helpers/createContext.d.ts.map +1 -1
- package/lib/helpers/index.d.ts +3 -0
- package/lib/helpers/index.d.ts.map +1 -0
- package/lib/index.cjs.js +1 -1
- package/lib/index.d.ts +9 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.es.js +2543 -448
- package/lib/output.css +1 -1
- package/lib/server.cjs.js +1129 -397
- package/lib/server.es.js +1095 -407
- package/lib/services/main.machine.d.ts +2453 -576
- package/lib/services/main.machine.d.ts.map +1 -1
- package/lib/services/main.machine.data.d.ts +14 -1
- package/lib/services/main.machine.data.d.ts.map +1 -1
- package/lib/services/main.machine.helpers.d.ts +1 -1
- package/lib/services/main.machine.helpers.d.ts.map +1 -1
- package/lib/services/main.machine.test.d.ts +2 -0
- package/lib/services/main.machine.test.d.ts.map +1 -0
- package/lib/services/main.machine.typings.d.ts +26 -8
- package/lib/services/main.machine.typings.d.ts.map +1 -1
- package/lib/ui/Flow.d.ts +8 -4
- package/lib/ui/Flow.d.ts.map +1 -1
- package/lib/ui/components/Bounds.d.ts.map +1 -1
- package/lib/ui/components/EdgeComponent.d.ts.map +1 -1
- package/lib/ui/components/EdgesBoard.d.ts.map +1 -1
- package/lib/ui/components/EditPanel.d.ts +19 -0
- package/lib/ui/components/EditPanel.d.ts.map +1 -0
- package/lib/ui/components/EditPanel.hooks.d.ts +29 -0
- package/lib/ui/components/EditPanel.hooks.d.ts.map +1 -0
- package/lib/ui/components/EditPanel.types.d.ts +47 -0
- package/lib/ui/components/EditPanel.types.d.ts.map +1 -0
- package/lib/ui/components/FlowChart.context.d.ts +2452 -575
- package/lib/ui/components/FlowChart.context.d.ts.map +1 -1
- package/lib/ui/components/FlowChart.d.ts +8 -47
- package/lib/ui/components/FlowChart.d.ts.map +1 -1
- package/lib/ui/components/FlowChart.types.d.ts +87 -0
- package/lib/ui/components/FlowChart.types.d.ts.map +1 -0
- package/lib/ui/components/NodeComponent.d.ts +10 -12
- package/lib/ui/components/NodeComponent.d.ts.map +1 -1
- package/lib/ui/components/NodesBoard.d.ts +17 -2
- package/lib/ui/components/NodesBoard.d.ts.map +1 -1
- package/lib/ui/components/Panels.d.ts +12 -0
- package/lib/ui/components/Panels.d.ts.map +1 -0
- package/lib/ui/globals/components/atoms/TypingText.d.ts +29 -0
- package/lib/ui/globals/components/atoms/TypingText.d.ts.map +1 -0
- package/lib/ui/globals/components/molecules/FadingDots.d.ts +21 -0
- package/lib/ui/globals/components/molecules/FadingDots.d.ts.map +1 -0
- package/lib/ui/globals/components/organisms/LoadingFallback.d.ts +46 -0
- package/lib/ui/globals/components/organisms/LoadingFallback.d.ts.map +1 -0
- package/lib/ui/globals/constants/index.d.ts +3 -0
- package/lib/ui/globals/constants/index.d.ts.map +1 -0
- package/lib/ui/globals/constants/links.d.ts +4 -0
- package/lib/ui/globals/constants/links.d.ts.map +1 -0
- package/lib/ui/globals/constants/strings.d.ts +5 -0
- package/lib/ui/globals/constants/strings.d.ts.map +1 -0
- package/lib/ui/globals/directives/clickOutside.d.ts +9 -0
- package/lib/ui/globals/directives/clickOutside.d.ts.map +1 -0
- package/lib/ui/globals/directives/index.d.ts +16 -0
- package/lib/ui/globals/directives/index.d.ts.map +1 -0
- package/lib/ui/globals/directives/mouseOut.d.ts +33 -0
- package/lib/ui/globals/directives/mouseOut.d.ts.map +1 -0
- package/lib/ui/globals/directives/mouseOut.test.d.ts +2 -0
- package/lib/ui/globals/directives/mouseOut.test.d.ts.map +1 -0
- package/lib/ui/globals/directives/resize.d.ts +11 -0
- package/lib/ui/globals/directives/resize.d.ts.map +1 -0
- package/lib/ui/globals/helpers/espace.d.ts +17 -0
- package/lib/ui/globals/helpers/espace.d.ts.map +1 -0
- package/lib/ui/globals/signals/createTyping.d.ts +27 -0
- package/lib/ui/globals/signals/createTyping.d.ts.map +1 -0
- package/lib/ui/globals/types.d.ts +54 -0
- package/lib/ui/globals/types.d.ts.map +1 -0
- package/lib/ui/utils.d.ts +11 -0
- package/lib/ui/utils.d.ts.map +1 -0
- package/package.json +2 -3
- package/src/helpers/clamp.ts +3 -0
- package/src/helpers/createContext.ts +20 -4
- package/src/helpers/index.ts +2 -0
- package/src/index.ts +9 -1
- package/src/services/main.machine.data.ts +13 -2
- package/src/services/main.machine.helpers.ts +12 -4
- package/src/services/main.machine.test.ts +205 -0
- package/src/services/main.machine.ts +253 -75
- package/src/services/main.machine.typings.ts +31 -6
- package/src/ui/Flow.tsx +47 -8
- package/src/ui/components/Bounds.tsx +0 -2
- package/src/ui/components/EdgeComponent.tsx +60 -46
- package/src/ui/components/EdgesBoard.tsx +1 -2
- package/src/ui/components/EditPanel.hooks.ts +69 -0
- package/src/ui/components/EditPanel.tsx +89 -0
- package/src/ui/components/EditPanel.types.ts +49 -0
- package/src/ui/components/FlowChart.context.ts +22 -141
- package/src/ui/components/FlowChart.tsx +27 -64
- package/src/ui/components/FlowChart.types.ts +92 -0
- package/src/ui/components/NodeComponent.tsx +88 -65
- package/src/ui/components/NodesBoard.tsx +61 -56
- package/src/ui/components/Panels.tsx +40 -0
- package/src/ui/globals/components/atoms/TypingText.tsx +63 -0
- package/src/ui/globals/components/molecules/FadingDots.tsx +45 -0
- package/src/ui/globals/components/organisms/LoadingFallback.tsx +116 -0
- package/src/ui/globals/constants/index.ts +2 -0
- package/src/ui/globals/constants/links.ts +15 -0
- package/src/ui/globals/constants/strings.ts +5 -0
- package/src/ui/globals/directives/clickOutside.ts +18 -0
- package/src/ui/globals/directives/index.ts +16 -0
- package/src/ui/globals/directives/mouseOut.test.ts +115 -0
- package/src/ui/globals/directives/mouseOut.ts +98 -0
- package/src/ui/globals/directives/resize.ts +33 -0
- package/src/ui/globals/helpers/espace.ts +26 -0
- package/src/ui/globals/signals/createTyping.ts +82 -0
- package/src/ui/globals/types.ts +83 -0
- package/src/ui/utils.ts +14 -0
package/lib/server.cjs.js
CHANGED
|
@@ -1,12 +1,190 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let _bemedev_app_bemedev = require("@bemedev/app/bemedev");
|
|
2
3
|
let solid_js_web = require("solid-js/web");
|
|
3
4
|
let _bemedev_app_solidjs = require("@bemedev/app-solidjs");
|
|
4
5
|
let solid_js = require("solid-js");
|
|
5
6
|
let _bemedev_app = require("@bemedev/app");
|
|
6
|
-
let _bemedev_app_bemedev = require("@bemedev/app/bemedev");
|
|
7
7
|
let nanoid = require("nanoid");
|
|
8
8
|
let _thisbeyond_solid_dnd = require("@thisbeyond/solid-dnd");
|
|
9
9
|
let dequal = require("dequal");
|
|
10
|
+
let clsx = require("clsx");
|
|
11
|
+
let tailwind_merge = require("tailwind-merge");
|
|
12
|
+
//#region src/services/main.machine.data.ts
|
|
13
|
+
/** Horizontal gap in pixels between a parent node and newly created child node. */
|
|
14
|
+
var PARENT_CHILD_GAP_WIDTH = 100;
|
|
15
|
+
/** Default width and height dimensions for newly created flowchart nodes. */
|
|
16
|
+
var DEFAULT_SIZE = {
|
|
17
|
+
width: 192,
|
|
18
|
+
height: 50
|
|
19
|
+
};
|
|
20
|
+
/** Default node width in pixels. */
|
|
21
|
+
var DEFAULT_NODE_WIDTH = DEFAULT_SIZE.width;
|
|
22
|
+
/** Default node height in pixels. */
|
|
23
|
+
var DEFAULT_NODE_HEIGHT = DEFAULT_SIZE.height;
|
|
24
|
+
/** Default node data payload applied when creating new nodes. */
|
|
25
|
+
var DEFAULT_DATA = { content: "<Nouveau nœud>" };
|
|
26
|
+
/** Border width in pixels for a node container. */
|
|
27
|
+
var NODE_BORDER_WIDTH = 1.5;
|
|
28
|
+
/** Diameter in pixels of a node connection handle. */
|
|
29
|
+
var HANDLE_SIZE = 12;
|
|
30
|
+
/** Radius in pixels of a node connection handle. */
|
|
31
|
+
var HANDLE_RADIUS = 6;
|
|
32
|
+
/** Top margin in pixels for positioning connection handles. */
|
|
33
|
+
var HANDLE_MARGIN_TOP = 12;
|
|
34
|
+
/** Horizontal container offset in pixels for handle placement. */
|
|
35
|
+
var HANDLE_CONTAINER_OFFSET_X = 18;
|
|
36
|
+
/** Y-axis center coordinate in pixels of a handle. */
|
|
37
|
+
var HANDLE_CENTER_Y = 18;
|
|
38
|
+
/** X-axis center offset in pixels from the node container edge. */
|
|
39
|
+
var HANDLE_CENTER_X_OFFSET = 10.5;
|
|
40
|
+
/** Default X offset in pixels for input connection handles. */
|
|
41
|
+
var DEFAULT_INPUT_OFFSET_X = -10.5;
|
|
42
|
+
/** Default Y offset in pixels for input connection handles. */
|
|
43
|
+
var DEFAULT_INPUT_OFFSET_Y = 18;
|
|
44
|
+
/** Default 2D offset coordinates for input connection handles. */
|
|
45
|
+
var DEFAULT_INPUT_OFFSET = {
|
|
46
|
+
x: DEFAULT_INPUT_OFFSET_X,
|
|
47
|
+
y: 18
|
|
48
|
+
};
|
|
49
|
+
/** Dimensions representing width and height of the flow chart container canvas. */
|
|
50
|
+
var CONTAINER_DIMENSIONS = {
|
|
51
|
+
WIDTH: 5e3,
|
|
52
|
+
HEIGHT: 3500
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Computes default output handle offset coordinates given a node width.
|
|
56
|
+
*
|
|
57
|
+
* @param width - Node width in pixels, defaults to `0`.
|
|
58
|
+
*
|
|
59
|
+
* @returns 2D offset coordinates for the output handle.
|
|
60
|
+
*
|
|
61
|
+
* @see {@linkcode HANDLE_CENTER_X_OFFSET}, {@linkcode HANDLE_CENTER_Y}
|
|
62
|
+
*/
|
|
63
|
+
var getDefaultOutputOffset = (width = 0) => ({
|
|
64
|
+
x: width + HANDLE_CENTER_X_OFFSET,
|
|
65
|
+
y: 18
|
|
66
|
+
});
|
|
67
|
+
/** Top offset in pixels for node action toolbars. */
|
|
68
|
+
var TOOLBAR_TOP_OFFSET = 30;
|
|
69
|
+
/** Safety buffer in pixels applied above the toolbar. */
|
|
70
|
+
var TOOLBAR_BUFFER = 5;
|
|
71
|
+
/**
|
|
72
|
+
* Boundary padding constraints for node dragging and positioning within the
|
|
73
|
+
* viewport.
|
|
74
|
+
*/
|
|
75
|
+
var BOUNDS_CONSTRAINTS = {
|
|
76
|
+
horizontal: 55,
|
|
77
|
+
vertical: 40
|
|
78
|
+
};
|
|
79
|
+
/** Multiplier factor used to compute canvas virtual scroll dimensions. */
|
|
80
|
+
var CANVAS_FACTOR = 5;
|
|
81
|
+
/** Multiplier factor used to compute canvas scroll dimensions. */
|
|
82
|
+
var SCROLL_MULTIPLIER = 3;
|
|
83
|
+
/**
|
|
84
|
+
* Default node items of type {@linkcode NodeProps} provided when no initial
|
|
85
|
+
* configuration is given.
|
|
86
|
+
*/
|
|
87
|
+
var DEFAULT_NODES = [{
|
|
88
|
+
id: "node-0",
|
|
89
|
+
data: {
|
|
90
|
+
content: "Some text",
|
|
91
|
+
label: "Root node"
|
|
92
|
+
},
|
|
93
|
+
position: {
|
|
94
|
+
x: 350,
|
|
95
|
+
y: 100
|
|
96
|
+
}
|
|
97
|
+
}];
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region src/services/main.machine.typings.ts
|
|
100
|
+
/** Schema definition for 2D coordinates `(x, y)`. */
|
|
101
|
+
var point = (0, _bemedev_app_bemedev.type)({
|
|
102
|
+
x: "number",
|
|
103
|
+
y: "number"
|
|
104
|
+
});
|
|
105
|
+
/**
|
|
106
|
+
* Schema definition for node handle offsets (input and output).
|
|
107
|
+
*
|
|
108
|
+
* @see {@linkcode point}
|
|
109
|
+
*/
|
|
110
|
+
var nodeOffset = (0, _bemedev_app_bemedev.type)(({ use }) => ({
|
|
111
|
+
input: use(point),
|
|
112
|
+
output: use(point)
|
|
113
|
+
}));
|
|
114
|
+
/** Schema definition for edge extremities. */
|
|
115
|
+
var extremities = (0, _bemedev_app_bemedev.type)({
|
|
116
|
+
from: "string",
|
|
117
|
+
to: "string"
|
|
118
|
+
});
|
|
119
|
+
/** Schema definition for primitive values allowed in node data. */
|
|
120
|
+
var nodeDataValue = (0, _bemedev_app_bemedev.type)(({ union }) => union("string", "boolean", "number"));
|
|
121
|
+
/**
|
|
122
|
+
* Schema definition for serialized node data dictionary.
|
|
123
|
+
*
|
|
124
|
+
* @see {@linkcode nodeDataValue}
|
|
125
|
+
*/
|
|
126
|
+
var data = (0, _bemedev_app_bemedev.type)(({ record, use }) => record(use(nodeDataValue)));
|
|
127
|
+
/**
|
|
128
|
+
* Schema definition for a serialized flowchart node entity.
|
|
129
|
+
*
|
|
130
|
+
* @see {@linkcode point}, {@linkcode data}
|
|
131
|
+
*/
|
|
132
|
+
var nodeJSON = (0, _bemedev_app_bemedev.type)(({ use }) => ({
|
|
133
|
+
position: use(point),
|
|
134
|
+
data: use(data)
|
|
135
|
+
}));
|
|
136
|
+
/**
|
|
137
|
+
* Schema definition for a serialized flowchart edge entity.
|
|
138
|
+
*
|
|
139
|
+
* @see {@linkcode extremities}
|
|
140
|
+
*/
|
|
141
|
+
var edgeJSON = extremities;
|
|
142
|
+
/**
|
|
143
|
+
* Schema definition for layout dimensions and connection points of a node.
|
|
144
|
+
*
|
|
145
|
+
* @see {@linkcode point}
|
|
146
|
+
*/
|
|
147
|
+
var dimension = (0, _bemedev_app_bemedev.type)(({ optional, use }) => ({
|
|
148
|
+
width: "number",
|
|
149
|
+
height: "number",
|
|
150
|
+
output: use(point),
|
|
151
|
+
input: optional(use(point)),
|
|
152
|
+
inputOffset: optional(use(point)),
|
|
153
|
+
outputOffset: optional(use(point))
|
|
154
|
+
}));
|
|
155
|
+
/**
|
|
156
|
+
* Schema definition for a 2D line vector representing edge coordinates `(x0, y0)` to
|
|
157
|
+
* `(x1, y1)`.
|
|
158
|
+
*/
|
|
159
|
+
var vector = (0, _bemedev_app_bemedev.type)({
|
|
160
|
+
x0: "number",
|
|
161
|
+
y0: "number",
|
|
162
|
+
x1: "number",
|
|
163
|
+
y1: "number"
|
|
164
|
+
});
|
|
165
|
+
/**
|
|
166
|
+
* Schema definition for an ongoing new connection edge creation preview between
|
|
167
|
+
* source node and cursor position.
|
|
168
|
+
*
|
|
169
|
+
* @see {@linkcode vector}
|
|
170
|
+
*/
|
|
171
|
+
var newEdge = (0, _bemedev_app_bemedev.type)(({ intersection, use }) => intersection({ from: "string" }, use(vector)));
|
|
172
|
+
/** Schema definition for flowchart board geometry and container scroll dimensions. */
|
|
173
|
+
var board = (0, _bemedev_app_bemedev.type)(({ optional }) => ({
|
|
174
|
+
self: {
|
|
175
|
+
left: "number",
|
|
176
|
+
top: "number",
|
|
177
|
+
width: "number",
|
|
178
|
+
height: "number"
|
|
179
|
+
},
|
|
180
|
+
parent: optional({
|
|
181
|
+
scrollLeft: "number",
|
|
182
|
+
scrollTop: "number",
|
|
183
|
+
height: "number",
|
|
184
|
+
width: "number"
|
|
185
|
+
})
|
|
186
|
+
}));
|
|
187
|
+
//#endregion
|
|
10
188
|
//#region src/ui/components/classes.ts
|
|
11
189
|
/**
|
|
12
190
|
* List of Tailwind CSS class names used across flowchart UI components to ensure
|
|
@@ -93,50 +271,11 @@ var CLASSES = [
|
|
|
93
271
|
"cursor-crosshair",
|
|
94
272
|
"mt-3"
|
|
95
273
|
];
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
x: -10.5,
|
|
101
|
-
y: 18
|
|
102
|
-
};
|
|
103
|
-
/**
|
|
104
|
-
* Computes default output handle offset coordinates given a node width.
|
|
105
|
-
*
|
|
106
|
-
* @param width - Node width in pixels, defaults to `0`.
|
|
107
|
-
*
|
|
108
|
-
* @returns 2D offset coordinates for the output handle.
|
|
109
|
-
*
|
|
110
|
-
* @see {@linkcode HANDLE_CENTER_X_OFFSET}, {@linkcode HANDLE_CENTER_Y}
|
|
111
|
-
*/
|
|
112
|
-
var getDefaultOutputOffset = (width = 0) => ({
|
|
113
|
-
x: width + HANDLE_CENTER_X_OFFSET,
|
|
114
|
-
y: 18
|
|
115
|
-
});
|
|
116
|
-
/**
|
|
117
|
-
* Boundary padding constraints for node dragging and positioning within the
|
|
118
|
-
* viewport.
|
|
119
|
-
*/
|
|
120
|
-
var BOUNDS_CONSTRAINTS = {
|
|
121
|
-
horizontal: 55,
|
|
122
|
-
vertical: 40
|
|
274
|
+
//#endregion
|
|
275
|
+
//#region src/helpers/clamp.ts
|
|
276
|
+
var clamp = (value, min, max) => {
|
|
277
|
+
return Math.min(Math.max(value, min), max);
|
|
123
278
|
};
|
|
124
|
-
/**
|
|
125
|
-
* Default node items of type {@linkcode NodeProps} provided when no initial
|
|
126
|
-
* configuration is given.
|
|
127
|
-
*/
|
|
128
|
-
var DEFAULT_NODES = [{
|
|
129
|
-
id: "node-0",
|
|
130
|
-
data: {
|
|
131
|
-
content: "Some text",
|
|
132
|
-
label: "Root node"
|
|
133
|
-
},
|
|
134
|
-
input: false,
|
|
135
|
-
position: {
|
|
136
|
-
x: 350,
|
|
137
|
-
y: 100
|
|
138
|
-
}
|
|
139
|
-
}];
|
|
140
279
|
//#endregion
|
|
141
280
|
//#region src/helpers/createContext.ts
|
|
142
281
|
/**
|
|
@@ -154,12 +293,20 @@ var DEFAULT_NODES = [{
|
|
|
154
293
|
* @see {@linkcode createSolidContext}, {@linkcode useContext}
|
|
155
294
|
*/
|
|
156
295
|
var createContext = (context, options) => {
|
|
157
|
-
const _context = (0, solid_js.createContext)(
|
|
158
|
-
const Provider = (
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
296
|
+
const _context = (0, solid_js.createContext)(void 0, options);
|
|
297
|
+
const Provider = (props) => {
|
|
298
|
+
return (0, solid_js.createComponent)(_context.Provider, {
|
|
299
|
+
value: context(),
|
|
300
|
+
get children() {
|
|
301
|
+
return props.children;
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
};
|
|
305
|
+
const _useContext = () => {
|
|
306
|
+
const __context = (0, solid_js.useContext)(_context);
|
|
307
|
+
if (!__context) throw new Error("useContext must be used within a Provider");
|
|
308
|
+
return __context;
|
|
309
|
+
};
|
|
163
310
|
return [
|
|
164
311
|
Provider,
|
|
165
312
|
_useContext,
|
|
@@ -199,17 +346,17 @@ var buildNodeID = (generated) => {
|
|
|
199
346
|
*
|
|
200
347
|
* @returns Node layout dimension object of type {@linkcode Dimension}.
|
|
201
348
|
*
|
|
202
|
-
* @see {@linkcode getDefaultOutputOffset}, {@linkcode DEFAULT_INPUT_OFFSET}
|
|
349
|
+
* @see {@linkcode getDefaultOutputOffset}, {@linkcode DEFAULT_INPUT_OFFSET}, {@linkcode DEFAULT_SIZE}
|
|
203
350
|
*/
|
|
204
351
|
var calculateDimensions = (position, parentDimension = {
|
|
205
|
-
width:
|
|
206
|
-
height:
|
|
352
|
+
width: DEFAULT_SIZE.width,
|
|
353
|
+
height: DEFAULT_SIZE.height,
|
|
207
354
|
inputOffset: DEFAULT_INPUT_OFFSET
|
|
208
355
|
}) => {
|
|
209
356
|
const width = parentDimension.width;
|
|
210
357
|
const height = parentDimension.height;
|
|
211
358
|
const outputOffset = parentDimension.outputOffset ?? getDefaultOutputOffset(width);
|
|
212
|
-
const inputOffset = parentDimension.inputOffset;
|
|
359
|
+
const inputOffset = parentDimension.inputOffset ?? DEFAULT_INPUT_OFFSET;
|
|
213
360
|
return {
|
|
214
361
|
width,
|
|
215
362
|
height,
|
|
@@ -226,92 +373,12 @@ var calculateDimensions = (position, parentDimension = {
|
|
|
226
373
|
};
|
|
227
374
|
};
|
|
228
375
|
//#endregion
|
|
229
|
-
//#region src/services/main.machine.typings.ts
|
|
230
|
-
/** Schema definition for 2D coordinates `(x, y)`. */
|
|
231
|
-
var point = (0, _bemedev_app_bemedev.type)({
|
|
232
|
-
x: "number",
|
|
233
|
-
y: "number"
|
|
234
|
-
});
|
|
235
|
-
(0, _bemedev_app_bemedev.type)(({ optional, use }) => ({
|
|
236
|
-
input: optional(use(point)),
|
|
237
|
-
output: use(point)
|
|
238
|
-
}));
|
|
239
|
-
/** Schema definition for edge extremities. */
|
|
240
|
-
var extremities = (0, _bemedev_app_bemedev.type)({
|
|
241
|
-
from: "string",
|
|
242
|
-
to: "string"
|
|
243
|
-
});
|
|
244
|
-
/**
|
|
245
|
-
* Schema definition for a serialized flowchart node entity.
|
|
246
|
-
*
|
|
247
|
-
* @see {@linkcode point}
|
|
248
|
-
*/
|
|
249
|
-
var nodeJSON = (0, _bemedev_app_bemedev.type)(({ optional, use }) => ({
|
|
250
|
-
position: use(point),
|
|
251
|
-
data: {
|
|
252
|
-
label: optional("string"),
|
|
253
|
-
content: "string"
|
|
254
|
-
},
|
|
255
|
-
input: "boolean"
|
|
256
|
-
}));
|
|
257
|
-
/**
|
|
258
|
-
* Schema definition for a serialized flowchart edge entity.
|
|
259
|
-
*
|
|
260
|
-
* @see {@linkcode extremities}
|
|
261
|
-
*/
|
|
262
|
-
var edgeJSON = extremities;
|
|
263
|
-
/**
|
|
264
|
-
* Schema definition for layout dimensions and connection points of a node.
|
|
265
|
-
*
|
|
266
|
-
* @see {@linkcode point}
|
|
267
|
-
*/
|
|
268
|
-
var dimension = (0, _bemedev_app_bemedev.type)(({ optional, use }) => ({
|
|
269
|
-
width: "number",
|
|
270
|
-
height: "number",
|
|
271
|
-
output: use(point),
|
|
272
|
-
input: optional(use(point)),
|
|
273
|
-
inputOffset: optional(use(point)),
|
|
274
|
-
outputOffset: optional(use(point))
|
|
275
|
-
}));
|
|
276
|
-
/**
|
|
277
|
-
* Schema definition for a 2D line vector representing edge coordinates `(x0, y0)` to
|
|
278
|
-
* `(x1, y1)`.
|
|
279
|
-
*/
|
|
280
|
-
var vector = (0, _bemedev_app_bemedev.type)({
|
|
281
|
-
x0: "number",
|
|
282
|
-
y0: "number",
|
|
283
|
-
x1: "number",
|
|
284
|
-
y1: "number"
|
|
285
|
-
});
|
|
286
|
-
/**
|
|
287
|
-
* Schema definition for an ongoing new connection edge creation preview between
|
|
288
|
-
* source node and cursor position.
|
|
289
|
-
*
|
|
290
|
-
* @see {@linkcode vector}
|
|
291
|
-
*/
|
|
292
|
-
var newEdge = (0, _bemedev_app_bemedev.type)(({ intersection, use }) => intersection({ from: "string" }, use(vector)));
|
|
293
|
-
/** Schema definition for flowchart board geometry and container scroll dimensions. */
|
|
294
|
-
var board = (0, _bemedev_app_bemedev.type)(({ optional }) => ({
|
|
295
|
-
self: {
|
|
296
|
-
left: "number",
|
|
297
|
-
top: "number",
|
|
298
|
-
width: "number",
|
|
299
|
-
height: "number"
|
|
300
|
-
},
|
|
301
|
-
parent: optional({
|
|
302
|
-
scrollLeft: "number",
|
|
303
|
-
scrollTop: "number",
|
|
304
|
-
height: "number",
|
|
305
|
-
width: "number"
|
|
306
|
-
})
|
|
307
|
-
}));
|
|
308
|
-
//#endregion
|
|
309
376
|
//#region src/services/main.machine.ts
|
|
310
377
|
/**
|
|
311
378
|
* State machine managing flowchart state transitions, nodes, edges, selection, and
|
|
312
379
|
* layout actions.
|
|
313
380
|
*
|
|
314
|
-
* @see {@linkcode calculateDimensions}, {@linkcode buildEdgeId}, {@linkcode buildNodeID}, {@linkcode getDefaultOutputOffset}, {@linkcode DEFAULT_INPUT_OFFSET}
|
|
381
|
+
* @see {@linkcode calculateDimensions}, {@linkcode buildEdgeId}, {@linkcode buildNodeID}, {@linkcode getDefaultOutputOffset}, {@linkcode DEFAULT_INPUT_OFFSET}, {@linkcode DEFAULT_SIZE}, {@linkcode DEFAULT_DATA}
|
|
315
382
|
*/
|
|
316
383
|
var machine = (0, _bemedev_app.createMachine)({
|
|
317
384
|
initial: "idle",
|
|
@@ -320,7 +387,7 @@ var machine = (0, _bemedev_app.createMachine)({
|
|
|
320
387
|
idle: { on: {
|
|
321
388
|
CONFIGURE: {
|
|
322
389
|
actions: ["configure"],
|
|
323
|
-
target: "/
|
|
390
|
+
target: "/construction"
|
|
324
391
|
},
|
|
325
392
|
CONFIGURE_EMPTY: "/working"
|
|
326
393
|
} },
|
|
@@ -329,6 +396,10 @@ var machine = (0, _bemedev_app.createMachine)({
|
|
|
329
396
|
target: "/working"
|
|
330
397
|
} },
|
|
331
398
|
working: { on: {
|
|
399
|
+
CONFIGURE: {
|
|
400
|
+
actions: ["configure"],
|
|
401
|
+
target: "/construction"
|
|
402
|
+
},
|
|
332
403
|
MOVE_IMMEDIATE: { actions: [{
|
|
333
404
|
name: "buildUI",
|
|
334
405
|
description: "Must be in the ui"
|
|
@@ -355,7 +426,6 @@ var machine = (0, _bemedev_app.createMachine)({
|
|
|
355
426
|
],
|
|
356
427
|
target: "/construction"
|
|
357
428
|
},
|
|
358
|
-
ADD_DIMENSION: { actions: ["addDimension"] },
|
|
359
429
|
ADD_SIBLING: {
|
|
360
430
|
actions: [
|
|
361
431
|
"generateID",
|
|
@@ -367,6 +437,7 @@ var machine = (0, _bemedev_app.createMachine)({
|
|
|
367
437
|
],
|
|
368
438
|
target: "/construction"
|
|
369
439
|
},
|
|
440
|
+
RESIZE: { actions: ["resize", "buildUI"] },
|
|
370
441
|
MOVE: {
|
|
371
442
|
actions: ["moveNode", "buildUI"],
|
|
372
443
|
target: "/construction"
|
|
@@ -386,14 +457,18 @@ var machine = (0, _bemedev_app.createMachine)({
|
|
|
386
457
|
DESELECT: { actions: ["deselect"] },
|
|
387
458
|
ZOOM: { actions: ["zoom"] },
|
|
388
459
|
TOGGLE_ZOOM: { actions: ["toggleZoom"] },
|
|
389
|
-
SET_BOARD: { actions: ["setBoard"] }
|
|
460
|
+
SET_BOARD: { actions: ["setBoard"] },
|
|
461
|
+
SET_NODE_DATA: { actions: ["setNodeData"] },
|
|
462
|
+
EDIT: { actions: ["edit"] },
|
|
463
|
+
STOP_EDIT: { actions: ["stopEdit"] }
|
|
390
464
|
} }
|
|
391
465
|
}
|
|
392
466
|
}, {
|
|
393
|
-
eventsMap: (0, _bemedev_app_bemedev.type)(({ intersection, use, array }) => ({
|
|
467
|
+
eventsMap: (0, _bemedev_app_bemedev.type)(({ intersection, use, array, optional }) => ({
|
|
394
468
|
CONFIGURE: {
|
|
395
469
|
nodes: array(intersection(use(nodeJSON), { id: "string" })),
|
|
396
|
-
edges: array(intersection(use(edgeJSON), { id: "string" }))
|
|
470
|
+
edges: array(intersection(use(edgeJSON), { id: "string" })),
|
|
471
|
+
defaultData: optional(use(data))
|
|
397
472
|
},
|
|
398
473
|
SET_BOARD: use(board),
|
|
399
474
|
CONFIGURE_EMPTY: "never",
|
|
@@ -413,15 +488,24 @@ var machine = (0, _bemedev_app.createMachine)({
|
|
|
413
488
|
DELETE: "string",
|
|
414
489
|
SELECT: "string",
|
|
415
490
|
DESELECT: "never",
|
|
491
|
+
EDIT: "string",
|
|
492
|
+
STOP_EDIT: "never",
|
|
416
493
|
ADD_EDGE: use(extremities),
|
|
417
494
|
START_NEW_EDGE: "string",
|
|
418
495
|
MOVE_NEW_EDGE: use(point),
|
|
419
496
|
CLEAR_NEW_EDGE: "never",
|
|
420
497
|
ZOOM: "number",
|
|
421
498
|
TOGGLE_ZOOM: "never",
|
|
422
|
-
|
|
499
|
+
RESIZE: {
|
|
500
|
+
id: "string",
|
|
501
|
+
size: {
|
|
502
|
+
width: "number",
|
|
503
|
+
height: "number"
|
|
504
|
+
}
|
|
505
|
+
},
|
|
506
|
+
SET_NODE_DATA: {
|
|
423
507
|
id: "string",
|
|
424
|
-
|
|
508
|
+
data: use(data)
|
|
425
509
|
}
|
|
426
510
|
})),
|
|
427
511
|
sync: true,
|
|
@@ -429,6 +513,7 @@ var machine = (0, _bemedev_app.createMachine)({
|
|
|
429
513
|
generatedId: union("string", "null"),
|
|
430
514
|
previousZoom: optional("number"),
|
|
431
515
|
dimensions: record(use(dimension)),
|
|
516
|
+
defaultData: optional(use(data)),
|
|
432
517
|
getBoardPosition: custom(),
|
|
433
518
|
clampPosition: custom(),
|
|
434
519
|
calculateDimensions: custom()
|
|
@@ -448,18 +533,42 @@ var machine = (0, _bemedev_app.createMachine)({
|
|
|
448
533
|
edgesPositions: record(use(vector)),
|
|
449
534
|
newEdge: optional(use(newEdge)),
|
|
450
535
|
selected: optional("string"),
|
|
536
|
+
editing: optional("string"),
|
|
451
537
|
updatingUI: optional("boolean"),
|
|
452
538
|
zoom: "number",
|
|
453
539
|
bounds: use(point)
|
|
454
540
|
}))
|
|
455
541
|
}).provideOptions(({ assign, batch, erase, filter, action }) => ({ actions: {
|
|
456
|
-
configure: batch(assign("data", { CONFIGURE: ({ payload
|
|
542
|
+
configure: batch(assign("data", { CONFIGURE: ({ payload: { nodes, edges } }) => ({
|
|
543
|
+
nodes,
|
|
544
|
+
edges
|
|
545
|
+
}) }), assign("newEdge", () => void 0), assign("updatingUI", () => false), action(({ pContext }) => {
|
|
457
546
|
pContext.generatedId = null;
|
|
458
|
-
}), action({ CONFIGURE: ({ payload: { nodes }, pContext
|
|
547
|
+
}), action({ CONFIGURE: ({ payload: { nodes, defaultData }, pContext }) => {
|
|
548
|
+
pContext.defaultData = defaultData;
|
|
459
549
|
nodes.forEach(({ id, position }) => {
|
|
460
|
-
dimensions[id] = calculateDimensions(position);
|
|
550
|
+
pContext.dimensions[id] = calculateDimensions(position);
|
|
461
551
|
});
|
|
462
552
|
} })),
|
|
553
|
+
setNodeData: assign("data.nodes", { SET_NODE_DATA: ({ context: { data }, payload: { id, data: newData } }) => {
|
|
554
|
+
return data?.nodes?.map((node) => {
|
|
555
|
+
if (node.id === id) return {
|
|
556
|
+
...node,
|
|
557
|
+
data: {
|
|
558
|
+
...node.data,
|
|
559
|
+
...newData
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
return node;
|
|
563
|
+
});
|
|
564
|
+
} }),
|
|
565
|
+
setBoard: assign("board", { SET_BOARD: ({ payload }) => payload }),
|
|
566
|
+
generateID: action(({ pContext }) => pContext.generatedId = (0, nanoid.nanoid)()),
|
|
567
|
+
select: assign("selected", { SELECT: ({ payload }) => payload }),
|
|
568
|
+
clearNewEdge: erase("newEdge"),
|
|
569
|
+
deselect: batch(erase("selected"), erase("editing")),
|
|
570
|
+
edit: batch(assign("editing", { EDIT: ({ payload }) => payload }), assign("selected", { EDIT: ({ payload }) => payload })),
|
|
571
|
+
stopEdit: erase("editing"),
|
|
463
572
|
startNewEdge: assign("newEdge", { START_NEW_EDGE: ({ payload: from, pContext: { dimensions } }) => {
|
|
464
573
|
const { x, y } = dimensions[from].output;
|
|
465
574
|
return {
|
|
@@ -470,13 +579,13 @@ var machine = (0, _bemedev_app.createMachine)({
|
|
|
470
579
|
y1: y
|
|
471
580
|
};
|
|
472
581
|
} }),
|
|
473
|
-
setBoard: assign("board", { SET_BOARD: ({ payload }) => payload }),
|
|
474
582
|
buildUI: batch(assign("edgesPositions", {
|
|
475
583
|
MOVE: ({ context: { data, edgesPositions }, payload, pContext: { dimensions } }) => {
|
|
476
584
|
const edges = data?.edges;
|
|
477
585
|
const dimension = dimensions[payload.id];
|
|
478
|
-
|
|
479
|
-
const
|
|
586
|
+
if (!dimension) return;
|
|
587
|
+
const outputOffset = dimension.outputOffset ?? getDefaultOutputOffset(dimension.width);
|
|
588
|
+
const inputOffset = dimension.inputOffset ?? DEFAULT_INPUT_OFFSET;
|
|
480
589
|
const output = {
|
|
481
590
|
x: payload.x + outputOffset.x,
|
|
482
591
|
y: payload.y + outputOffset.y
|
|
@@ -485,44 +594,45 @@ var machine = (0, _bemedev_app.createMachine)({
|
|
|
485
594
|
x: payload.x + inputOffset.x,
|
|
486
595
|
y: payload.y + inputOffset.y
|
|
487
596
|
};
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
dimension.input = input;
|
|
491
|
-
}
|
|
597
|
+
dimension.output = output;
|
|
598
|
+
dimension.input = input;
|
|
492
599
|
edges?.forEach(({ from, to, id }) => {
|
|
600
|
+
const edgePosition = edgesPositions[id];
|
|
601
|
+
if (!edgePosition) return;
|
|
493
602
|
if (from === payload.id) {
|
|
494
|
-
|
|
495
|
-
|
|
603
|
+
edgePosition.x0 = output.x;
|
|
604
|
+
edgePosition.y0 = output.y;
|
|
496
605
|
}
|
|
497
606
|
if (to === payload.id) {
|
|
498
|
-
|
|
499
|
-
|
|
607
|
+
edgePosition.x1 = input.x;
|
|
608
|
+
edgePosition.y1 = input.y;
|
|
500
609
|
}
|
|
501
610
|
});
|
|
502
611
|
return edgesPositions;
|
|
503
612
|
},
|
|
504
613
|
MOVE_IMMEDIATE: ({ context: { data, edgesPositions }, payload, pContext: { dimensions } }) => {
|
|
505
|
-
|
|
614
|
+
data?.edges?.forEach(({ from, to, id }) => {
|
|
615
|
+
const dimension = dimensions[payload.id];
|
|
616
|
+
const edgePosition = edgesPositions[id];
|
|
617
|
+
if (!edgePosition || !dimension) return;
|
|
506
618
|
if (from === payload.id) {
|
|
507
|
-
const
|
|
508
|
-
const offset = dimension?.outputOffset ?? getDefaultOutputOffset(dimension?.width);
|
|
619
|
+
const offset = dimension.outputOffset ?? getDefaultOutputOffset(dimension.width);
|
|
509
620
|
const x0 = payload.x + offset.x;
|
|
510
621
|
const y0 = payload.y + offset.y;
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
}
|
|
622
|
+
edgePosition.x0 = x0;
|
|
623
|
+
edgePosition.y0 = y0;
|
|
624
|
+
dimension.output = {
|
|
625
|
+
x: x0,
|
|
626
|
+
y: y0
|
|
627
|
+
};
|
|
517
628
|
}
|
|
518
629
|
if (to === payload.id) {
|
|
519
|
-
const dimension = dimensions[payload.id];
|
|
520
630
|
const offset = dimension?.inputOffset ?? DEFAULT_INPUT_OFFSET;
|
|
521
631
|
const x1 = payload.x + offset.x;
|
|
522
632
|
const y1 = payload.y + offset.y;
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
633
|
+
edgePosition.x1 = x1;
|
|
634
|
+
edgePosition.y1 = y1;
|
|
635
|
+
dimension.input = {
|
|
526
636
|
x: x1,
|
|
527
637
|
y: y1
|
|
528
638
|
};
|
|
@@ -530,32 +640,47 @@ var machine = (0, _bemedev_app.createMachine)({
|
|
|
530
640
|
});
|
|
531
641
|
return edgesPositions;
|
|
532
642
|
},
|
|
533
|
-
else: ({ context: { data
|
|
534
|
-
const
|
|
535
|
-
|
|
536
|
-
edges.forEach(({ from, id, to }) => {
|
|
643
|
+
else: ({ context: { data }, pContext: { dimensions } }) => {
|
|
644
|
+
const nextEdgesPositions = {};
|
|
645
|
+
data?.edges?.forEach(({ from, id, to }) => {
|
|
537
646
|
const output = dimensions[from]?.output;
|
|
538
647
|
const input = dimensions[to]?.input;
|
|
539
|
-
if (output && input)
|
|
648
|
+
if (output && input) nextEdgesPositions[id] = {
|
|
540
649
|
x0: output.x,
|
|
541
650
|
y0: output.y,
|
|
542
651
|
x1: input.x,
|
|
543
652
|
y1: input.y
|
|
544
653
|
};
|
|
545
|
-
else delete edgesPositions[id];
|
|
546
654
|
});
|
|
547
|
-
return
|
|
655
|
+
return nextEdgesPositions;
|
|
548
656
|
}
|
|
549
657
|
}), assign("updatingUI", () => true)),
|
|
550
|
-
|
|
551
|
-
dimensions[id]
|
|
658
|
+
resize: action({ RESIZE: ({ payload: { id, size: { width, height } }, context: { data }, pContext: { dimensions } }) => {
|
|
659
|
+
const dimension = dimensions[id];
|
|
660
|
+
if (!dimension) return;
|
|
661
|
+
dimension.width = width;
|
|
662
|
+
dimension.height = height;
|
|
663
|
+
const node = data?.nodes?.find((n) => n.id === id);
|
|
664
|
+
const outputOffset = getDefaultOutputOffset(width);
|
|
665
|
+
const inputOffset = dimension.inputOffset ?? DEFAULT_INPUT_OFFSET;
|
|
666
|
+
dimension.outputOffset = outputOffset;
|
|
667
|
+
dimension.inputOffset = inputOffset;
|
|
668
|
+
if (node) {
|
|
669
|
+
dimension.output = {
|
|
670
|
+
x: node.position.x + outputOffset.x,
|
|
671
|
+
y: node.position.y + outputOffset.y
|
|
672
|
+
};
|
|
673
|
+
dimension.input = {
|
|
674
|
+
x: node.position.x + inputOffset.x,
|
|
675
|
+
y: node.position.y + inputOffset.y
|
|
676
|
+
};
|
|
677
|
+
} else dimension.output = {
|
|
678
|
+
x: dimension.output.x,
|
|
679
|
+
y: dimension.output.y
|
|
680
|
+
};
|
|
552
681
|
} }),
|
|
553
|
-
|
|
554
|
-
pContext.generatedId = (0, nanoid.nanoid)();
|
|
555
|
-
}),
|
|
556
|
-
linkChild: batch(assign("data.edges", { ADD_CHILD: ({ context: { data }, pContext, payload }) => {
|
|
682
|
+
linkChild: batch(assign("data.edges", { ADD_CHILD: ({ context: { data }, pContext, payload: from }) => {
|
|
557
683
|
const edges = _bemedev_app_bemedev.toArray.typed(data?.edges);
|
|
558
|
-
const from = payload;
|
|
559
684
|
const generatedId = pContext?.generatedId;
|
|
560
685
|
const to = buildNodeID(generatedId);
|
|
561
686
|
const id = buildEdgeId(from, to);
|
|
@@ -581,23 +706,21 @@ var machine = (0, _bemedev_app.createMachine)({
|
|
|
581
706
|
return edges;
|
|
582
707
|
} }), assign("selected", ({ pContext: { generatedId } }) => buildNodeID(generatedId))),
|
|
583
708
|
selectParent: assign("selected", ({ pContext: { generatedId } }) => buildNodeID(generatedId)),
|
|
584
|
-
moveNode: assign("data.nodes", { MOVE: ({ context: { data }, payload }) => {
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
...d,
|
|
709
|
+
moveNode: assign("data.nodes", { MOVE: ({ context: { data }, payload: { id, x, y } }) => {
|
|
710
|
+
return data?.nodes?.map((node) => {
|
|
711
|
+
if (node.id === id) return {
|
|
712
|
+
...node,
|
|
589
713
|
position: {
|
|
590
714
|
x,
|
|
591
715
|
y
|
|
592
716
|
}
|
|
593
717
|
};
|
|
594
|
-
return
|
|
595
|
-
})
|
|
718
|
+
return node;
|
|
719
|
+
});
|
|
596
720
|
} }),
|
|
597
|
-
select: assign("selected", { SELECT: ({ payload }) => payload }),
|
|
598
721
|
delete: batch(filter("data.edges", { DELETE: ({ id, from, to }, _, { payload }) => {
|
|
599
722
|
return id !== payload && from !== payload && to !== payload;
|
|
600
|
-
} }), filter("data.nodes", { DELETE: ({ id }, _, { payload }) => id !== payload })),
|
|
723
|
+
} }), filter("data.nodes", { DELETE: ({ id }, _, { payload }) => id !== payload }), erase("editing")),
|
|
601
724
|
addEdge: batch(assign("data.edges", { ADD_EDGE: ({ context, payload: { from, to } }) => {
|
|
602
725
|
const edges = context.data?.edges ?? [];
|
|
603
726
|
const id = buildEdgeId(from, to);
|
|
@@ -608,11 +731,8 @@ var machine = (0, _bemedev_app.createMachine)({
|
|
|
608
731
|
to
|
|
609
732
|
}];
|
|
610
733
|
} }), erase("newEdge")),
|
|
611
|
-
clearNewEdge: erase("newEdge"),
|
|
612
|
-
deselect: erase("selected"),
|
|
613
734
|
zoom: assign("zoom", { ZOOM: ({ context: { zoom }, payload, pContext }) => {
|
|
614
|
-
const
|
|
615
|
-
const clamped = Math.min(Math.max(Number(next.toFixed(2)), .2), 3);
|
|
735
|
+
const clamped = clamp(zoom + payload, .1, 3);
|
|
616
736
|
pContext.previousZoom = void 0;
|
|
617
737
|
return clamped;
|
|
618
738
|
} }),
|
|
@@ -624,6 +744,84 @@ var machine = (0, _bemedev_app.createMachine)({
|
|
|
624
744
|
}
|
|
625
745
|
pContext.previousZoom = zoom;
|
|
626
746
|
return 1;
|
|
747
|
+
} }),
|
|
748
|
+
placeChild: assign("data.nodes", { ADD_CHILD: ({ payload, context: { data, board }, pContext }) => {
|
|
749
|
+
if (!board) return data?.nodes;
|
|
750
|
+
const nodes = data?.nodes;
|
|
751
|
+
if (!payload) return nodes;
|
|
752
|
+
const parentNode = nodes?.find((node) => node.id === payload);
|
|
753
|
+
if (!parentNode) return nodes;
|
|
754
|
+
const parentDimension = pContext.dimensions[payload];
|
|
755
|
+
const id = `node-${pContext.generatedId}`;
|
|
756
|
+
const width = parentDimension?.width ?? DEFAULT_SIZE.width;
|
|
757
|
+
const height = parentDimension?.height ?? DEFAULT_SIZE.height;
|
|
758
|
+
const initialX = parentNode.position.x + width + 100;
|
|
759
|
+
const initialY = parentNode.position.y;
|
|
760
|
+
const position = pContext.clampPosition(board, initialX, initialY, width, height);
|
|
761
|
+
const defaultData = pContext.defaultData ?? DEFAULT_DATA;
|
|
762
|
+
nodes?.push({
|
|
763
|
+
id,
|
|
764
|
+
data: { ...defaultData },
|
|
765
|
+
position
|
|
766
|
+
});
|
|
767
|
+
pContext.dimensions[id] = pContext.calculateDimensions(position, parentDimension ?? DEFAULT_SIZE);
|
|
768
|
+
return nodes;
|
|
769
|
+
} }),
|
|
770
|
+
placeParent: assign("data.nodes", { ADD_PARENT: ({ context: { data, zoom = 1, board }, pContext }) => {
|
|
771
|
+
if (!board) return data?.nodes;
|
|
772
|
+
const nodes = data?.nodes;
|
|
773
|
+
const id = `node-${pContext.generatedId}`;
|
|
774
|
+
const container = board.parent;
|
|
775
|
+
const scrollLeft = container?.scrollLeft ?? 0;
|
|
776
|
+
const scrollTop = container?.scrollTop ?? 0;
|
|
777
|
+
const width = container?.width ?? 0;
|
|
778
|
+
const height = container?.height ?? 0;
|
|
779
|
+
const currentZoom = zoom;
|
|
780
|
+
const x = (scrollLeft + width / 2) / currentZoom;
|
|
781
|
+
const y = (scrollTop + height / 2) / currentZoom;
|
|
782
|
+
const position = pContext.clampPosition(board, x, y, DEFAULT_SIZE.width, DEFAULT_SIZE.height);
|
|
783
|
+
const defaultData = pContext.defaultData ?? DEFAULT_DATA;
|
|
784
|
+
nodes?.push({
|
|
785
|
+
id,
|
|
786
|
+
data: { ...defaultData },
|
|
787
|
+
position
|
|
788
|
+
});
|
|
789
|
+
pContext.dimensions[id] = pContext.calculateDimensions(position, DEFAULT_SIZE);
|
|
790
|
+
return nodes;
|
|
791
|
+
} }),
|
|
792
|
+
placeSibling: assign("data.nodes", { ADD_SIBLING: ({ payload, context: { data, board }, pContext }) => {
|
|
793
|
+
if (!board) return data?.nodes;
|
|
794
|
+
const edges = data?.edges;
|
|
795
|
+
const nodes = data?.nodes;
|
|
796
|
+
const parentID = edges?.find((edge) => edge.to === payload)?.from;
|
|
797
|
+
if (!parentID) return nodes;
|
|
798
|
+
const parentNode = nodes?.find((node) => node.id === parentID);
|
|
799
|
+
if (!parentNode) return nodes;
|
|
800
|
+
const parentDimension = pContext.dimensions[parentID];
|
|
801
|
+
const id = `node-${pContext.generatedId}`;
|
|
802
|
+
const width = parentDimension?.width ?? DEFAULT_SIZE.width;
|
|
803
|
+
const height = parentDimension?.height ?? DEFAULT_SIZE.height;
|
|
804
|
+
const initialX = parentNode.position.x + width + 100;
|
|
805
|
+
const initialY = parentNode.position.y + 100;
|
|
806
|
+
const position = pContext.clampPosition(board, initialX, initialY, width, height);
|
|
807
|
+
const defaultData = pContext.defaultData ?? DEFAULT_DATA;
|
|
808
|
+
nodes?.push({
|
|
809
|
+
id,
|
|
810
|
+
data: { ...defaultData },
|
|
811
|
+
position
|
|
812
|
+
});
|
|
813
|
+
pContext.dimensions[id] = pContext.calculateDimensions(position, parentDimension ?? DEFAULT_SIZE);
|
|
814
|
+
return nodes;
|
|
815
|
+
} }),
|
|
816
|
+
moveNewEdge: assign("newEdge", { MOVE_NEW_EDGE: ({ context: { newEdge, board }, payload, pContext }) => {
|
|
817
|
+
if (!board) return void 0;
|
|
818
|
+
if (!newEdge) return void 0;
|
|
819
|
+
const { x: x1, y: y1 } = pContext.getBoardPosition(payload.x, payload.y, board);
|
|
820
|
+
return {
|
|
821
|
+
...newEdge,
|
|
822
|
+
x1,
|
|
823
|
+
y1
|
|
824
|
+
};
|
|
627
825
|
} })
|
|
628
826
|
} }));
|
|
629
827
|
//#endregion
|
|
@@ -657,7 +855,7 @@ var [Provider, useFlow] = createContext(() => {
|
|
|
657
855
|
*
|
|
658
856
|
* @returns Calculated 2D coordinate of type {@linkcode Point}.
|
|
659
857
|
*/
|
|
660
|
-
getBoardPosition(clientX, clientY, el) {
|
|
858
|
+
getBoardPosition: (clientX, clientY, el) => {
|
|
661
859
|
if (!el) return {
|
|
662
860
|
x: clientX,
|
|
663
861
|
y: clientY
|
|
@@ -675,14 +873,15 @@ var [Provider, useFlow] = createContext(() => {
|
|
|
675
873
|
* {@linkcode Board}.
|
|
676
874
|
* @param x - Desired X position in pixels.
|
|
677
875
|
* @param y - Desired Y position in pixels.
|
|
678
|
-
* @param nodeWidth - Node width in pixels, defaults to `
|
|
679
|
-
* @param nodeHeight - Node height in pixels, defaults to
|
|
876
|
+
* @param nodeWidth - Node width in pixels, defaults to `DEFAULT_SIZE.width`.
|
|
877
|
+
* @param nodeHeight - Node height in pixels, defaults to
|
|
878
|
+
* `DEFAULT_SIZE.height`.
|
|
680
879
|
*
|
|
681
880
|
* @returns Clamped coordinate of type {@linkcode Point}.
|
|
682
881
|
*
|
|
683
|
-
* @see {@linkcode BOUNDS_CONSTRAINTS}
|
|
882
|
+
* @see {@linkcode BOUNDS_CONSTRAINTS}, {@linkcode DEFAULT_SIZE}
|
|
684
883
|
*/
|
|
685
|
-
clampPosition(board, x, y, nodeWidth =
|
|
884
|
+
clampPosition: (board, x, y, nodeWidth = DEFAULT_SIZE.width, nodeHeight = DEFAULT_SIZE.height) => {
|
|
686
885
|
const container = board?.parent;
|
|
687
886
|
if (!container) return {
|
|
688
887
|
x,
|
|
@@ -694,8 +893,8 @@ var [Provider, useFlow] = createContext(() => {
|
|
|
694
893
|
const minY = container.scrollTop / currentZoom + BOUNDS_CONSTRAINTS.vertical;
|
|
695
894
|
const maxY = Math.max(minY, (container.scrollTop + container.height) / currentZoom - BOUNDS_CONSTRAINTS.vertical - nodeHeight);
|
|
696
895
|
return {
|
|
697
|
-
x:
|
|
698
|
-
y:
|
|
896
|
+
x: clamp(x, minX, maxX),
|
|
897
|
+
y: clamp(y, minY, maxY)
|
|
699
898
|
};
|
|
700
899
|
},
|
|
701
900
|
/**
|
|
@@ -706,17 +905,17 @@ var [Provider, useFlow] = createContext(() => {
|
|
|
706
905
|
*
|
|
707
906
|
* @returns Calculated dimension object of type {@linkcode Dimension}.
|
|
708
907
|
*
|
|
709
|
-
* @see {@linkcode DEFAULT_INPUT_OFFSET}, {@linkcode getDefaultOutputOffset}
|
|
908
|
+
* @see {@linkcode DEFAULT_INPUT_OFFSET}, {@linkcode getDefaultOutputOffset}, {@linkcode DEFAULT_SIZE}
|
|
710
909
|
*/
|
|
711
910
|
calculateDimensions: (position, parentDimension = {
|
|
712
|
-
width:
|
|
713
|
-
height:
|
|
911
|
+
width: DEFAULT_SIZE.width,
|
|
912
|
+
height: DEFAULT_SIZE.height,
|
|
714
913
|
inputOffset: DEFAULT_INPUT_OFFSET
|
|
715
914
|
}) => {
|
|
716
915
|
const width = parentDimension.width;
|
|
717
916
|
const height = parentDimension.height;
|
|
718
917
|
const outputOffset = parentDimension.outputOffset ?? getDefaultOutputOffset(width);
|
|
719
|
-
const inputOffset = parentDimension.inputOffset;
|
|
918
|
+
const inputOffset = parentDimension.inputOffset ?? DEFAULT_INPUT_OFFSET;
|
|
720
919
|
return {
|
|
721
920
|
width,
|
|
722
921
|
height,
|
|
@@ -734,89 +933,6 @@ var [Provider, useFlow] = createContext(() => {
|
|
|
734
933
|
}
|
|
735
934
|
}
|
|
736
935
|
});
|
|
737
|
-
service.addOptions(({ assign }) => ({ actions: {
|
|
738
|
-
placeChild: assign("data.nodes", { ADD_CHILD: ({ payload, context: { data, board }, pContext }) => {
|
|
739
|
-
if (!board) return data?.nodes;
|
|
740
|
-
const nodes = data?.nodes;
|
|
741
|
-
if (!payload) return nodes;
|
|
742
|
-
const parentNode = nodes?.find((node) => node.id === payload);
|
|
743
|
-
if (!parentNode) return nodes;
|
|
744
|
-
const parentDimension = pContext.dimensions[payload];
|
|
745
|
-
const id = `node-${pContext.generatedId}`;
|
|
746
|
-
const width = parentDimension?.width ?? 192;
|
|
747
|
-
const height = parentDimension?.height ?? 50;
|
|
748
|
-
const initialX = parentNode.position.x + width + 100;
|
|
749
|
-
const initialY = parentNode.position.y;
|
|
750
|
-
const position = pContext.clampPosition(board, initialX, initialY, width, height);
|
|
751
|
-
const dimension = pContext.calculateDimensions(position, parentDimension);
|
|
752
|
-
nodes?.push({
|
|
753
|
-
id,
|
|
754
|
-
data: { content: "<Nouveau nœud>" },
|
|
755
|
-
input: true,
|
|
756
|
-
position
|
|
757
|
-
});
|
|
758
|
-
pContext.dimensions[id] = dimension;
|
|
759
|
-
return nodes;
|
|
760
|
-
} }),
|
|
761
|
-
placeParent: assign("data.nodes", { ADD_PARENT: ({ context: { data, zoom = 1, board }, pContext }) => {
|
|
762
|
-
if (!board) return data?.nodes;
|
|
763
|
-
const nodes = data?.nodes;
|
|
764
|
-
const id = `node-${pContext.generatedId}`;
|
|
765
|
-
const container = board.parent;
|
|
766
|
-
const scrollLeft = container?.scrollLeft ?? 0;
|
|
767
|
-
const scrollTop = container?.scrollTop ?? 0;
|
|
768
|
-
const width = container?.width ?? 0;
|
|
769
|
-
const height = container?.height ?? 0;
|
|
770
|
-
const currentZoom = zoom;
|
|
771
|
-
const x = (scrollLeft + width / 2) / currentZoom;
|
|
772
|
-
const y = (scrollTop + height / 2) / currentZoom;
|
|
773
|
-
const position = pContext.clampPosition(board, x, y);
|
|
774
|
-
const dimension = pContext.calculateDimensions(position);
|
|
775
|
-
nodes?.push({
|
|
776
|
-
id,
|
|
777
|
-
data: { content: "<Nouveau nœud>" },
|
|
778
|
-
input: false,
|
|
779
|
-
position
|
|
780
|
-
});
|
|
781
|
-
pContext.dimensions[id] = dimension;
|
|
782
|
-
return nodes;
|
|
783
|
-
} }),
|
|
784
|
-
placeSibling: assign("data.nodes", { ADD_SIBLING: ({ payload, context: { data, board }, pContext }) => {
|
|
785
|
-
if (!board) return data?.nodes;
|
|
786
|
-
const edges = data?.edges;
|
|
787
|
-
const nodes = data?.nodes;
|
|
788
|
-
const parentID = edges?.find((edge) => edge.to === payload)?.from;
|
|
789
|
-
if (!parentID) return nodes;
|
|
790
|
-
const parentNode = nodes?.find((node) => node.id === parentID);
|
|
791
|
-
if (!parentNode) return nodes;
|
|
792
|
-
const parentDimension = pContext.dimensions[parentID];
|
|
793
|
-
const id = `node-${pContext.generatedId}`;
|
|
794
|
-
const width = parentDimension?.width ?? 192;
|
|
795
|
-
const height = parentDimension?.height ?? 50;
|
|
796
|
-
const initialX = parentNode.position.x + width + 100;
|
|
797
|
-
const initialY = parentNode.position.y + 100;
|
|
798
|
-
const position = pContext.clampPosition(board, initialX, initialY, width, height);
|
|
799
|
-
const dimension = pContext.calculateDimensions(position, parentDimension);
|
|
800
|
-
nodes?.push({
|
|
801
|
-
id,
|
|
802
|
-
data: { content: "<Nouveau nœud>" },
|
|
803
|
-
input: true,
|
|
804
|
-
position
|
|
805
|
-
});
|
|
806
|
-
pContext.dimensions[id] = dimension;
|
|
807
|
-
return nodes;
|
|
808
|
-
} }),
|
|
809
|
-
moveNewEdge: assign("newEdge", { MOVE_NEW_EDGE: ({ context: { newEdge, board }, payload, pContext }) => {
|
|
810
|
-
if (!board) return void 0;
|
|
811
|
-
if (!newEdge) return void 0;
|
|
812
|
-
const { x: x1, y: y1 } = pContext.getBoardPosition(payload.x, payload.y, board);
|
|
813
|
-
return {
|
|
814
|
-
...newEdge,
|
|
815
|
-
x1,
|
|
816
|
-
y1
|
|
817
|
-
};
|
|
818
|
-
} })
|
|
819
|
-
} }));
|
|
820
936
|
service.start();
|
|
821
937
|
return service;
|
|
822
938
|
}, { name: "FlowContext" });
|
|
@@ -870,14 +986,14 @@ var DragBounds = () => {
|
|
|
870
986
|
};
|
|
871
987
|
//#endregion
|
|
872
988
|
//#region src/ui/components/EdgeComponent.tsx
|
|
873
|
-
var _tmpl$$
|
|
989
|
+
var _tmpl$$10 = [
|
|
874
990
|
"<path",
|
|
875
991
|
" class=\"",
|
|
876
992
|
"\" style=\"",
|
|
877
993
|
"\"",
|
|
878
994
|
"></path>"
|
|
879
995
|
];
|
|
880
|
-
var _tmpl$2$
|
|
996
|
+
var _tmpl$2$5 = [
|
|
881
997
|
"<g",
|
|
882
998
|
" cursor=\"pointer\" transform=\"",
|
|
883
999
|
"\" style=\"",
|
|
@@ -890,6 +1006,13 @@ var _tmpl$2$2 = [
|
|
|
890
1006
|
*
|
|
891
1007
|
* @returns Offset distance in pixels for bezier curvature.
|
|
892
1008
|
*/
|
|
1009
|
+
/**
|
|
1010
|
+
* Computes bezier curve control point offset based on horizontal distance.
|
|
1011
|
+
*
|
|
1012
|
+
* @param value - Absolute horizontal delta between start and end points.
|
|
1013
|
+
*
|
|
1014
|
+
* @returns Offset distance in pixels for bezier curvature.
|
|
1015
|
+
*/
|
|
893
1016
|
var calculateOffset = (value) => value * 100 / 200;
|
|
894
1017
|
/**
|
|
895
1018
|
* Generates an SVG cubic bezier path `d` string between coordinates `(x0, y0)` and
|
|
@@ -901,7 +1024,9 @@ var calculateOffset = (value) => value * 100 / 200;
|
|
|
901
1024
|
*
|
|
902
1025
|
* @see {@linkcode calculateOffset}
|
|
903
1026
|
*/
|
|
904
|
-
var draw = (
|
|
1027
|
+
var draw = (vector) => {
|
|
1028
|
+
if (!vector) return "";
|
|
1029
|
+
const { x0, y0, x1, y1 } = vector;
|
|
905
1030
|
return `M ${x0} ${y0} C ${x0 + calculateOffset(Math.abs(x1 - x0))} ${y0}, ${x1 - calculateOffset(Math.abs(x1 - x0))} ${y1}, ${x1} ${y1}`;
|
|
906
1031
|
};
|
|
907
1032
|
/**
|
|
@@ -927,23 +1052,32 @@ var EdgeComponent = (props) => {
|
|
|
927
1052
|
/** Computes the 2D midpoint coordinate of the edge curve for handle placement. */
|
|
928
1053
|
const middlePoint = () => {
|
|
929
1054
|
const v = vector();
|
|
1055
|
+
if (!v) return {
|
|
1056
|
+
x: 0,
|
|
1057
|
+
y: 0
|
|
1058
|
+
};
|
|
930
1059
|
return {
|
|
931
1060
|
x: v.x0 + (v.x1 - v.x0) / 2,
|
|
932
1061
|
y: v.y0 + (v.y1 - v.y0) / 2
|
|
933
1062
|
};
|
|
934
1063
|
};
|
|
935
|
-
return
|
|
1064
|
+
return (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
936
1065
|
get when() {
|
|
937
|
-
return
|
|
1066
|
+
return vector();
|
|
938
1067
|
},
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
1068
|
+
children: (v) => [(0, solid_js_web.ssr)(_tmpl$$10, (0, solid_js_web.ssrHydrationKey)(), `relative cursor-pointer fill-transparent ${!!props.isNew ? "stroke-[rgba(168,168,168,0.4)] stroke-3 z-200" : ""} ${selected() && !props.isNew ? "stroke-[rgba(168,168,168,1)] stroke-4 z-100" : ""} ${!selected() && !props.isNew ? "stroke-[rgba(168,168,168,0.8)] stroke-3" : ""}`, (0, solid_js_web.ssrStyleProperty)("pointer-events:", props.isNew ? "none" : "all"), (0, solid_js_web.ssrAttribute)("d", (0, solid_js_web.escape)(draw(v()), true), false)), (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1069
|
+
get when() {
|
|
1070
|
+
return selected();
|
|
1071
|
+
},
|
|
1072
|
+
get children() {
|
|
1073
|
+
return (0, solid_js_web.ssr)(_tmpl$2$5, (0, solid_js_web.ssrHydrationKey)(), `translate(${(0, solid_js_web.escape)(middlePoint().x, true)}, ${(0, solid_js_web.escape)(middlePoint().y, true)})`, (0, solid_js_web.ssrStyleProperty)("pointer-events:", "all") + (0, solid_js_web.ssrStyleProperty)(";z-index:", "30"));
|
|
1074
|
+
}
|
|
1075
|
+
})]
|
|
1076
|
+
});
|
|
943
1077
|
};
|
|
944
1078
|
//#endregion
|
|
945
1079
|
//#region src/ui/components/EdgesBoard.tsx
|
|
946
|
-
var _tmpl$$
|
|
1080
|
+
var _tmpl$$9 = [
|
|
947
1081
|
"<svg",
|
|
948
1082
|
" class=\"pointer-events-none h-full w-full overflow-visible\"><!--$-->",
|
|
949
1083
|
"<!--/--><!--$-->",
|
|
@@ -961,10 +1095,10 @@ var EdgesBoard = () => {
|
|
|
961
1095
|
const service = useFlow();
|
|
962
1096
|
const hasNewEdge = (0, _bemedev_app_solidjs.createState)(service, { selector: (s) => !!s.context.newEdge });
|
|
963
1097
|
const edgeIds = (0, _bemedev_app_solidjs.createState)(service, {
|
|
964
|
-
selector: ({ context }) => Object.keys(context.edgesPositions),
|
|
1098
|
+
selector: ({ context }) => Object.keys(context.edgesPositions ?? {}),
|
|
965
1099
|
equals: (prev, next) => prev.length === next.length
|
|
966
1100
|
});
|
|
967
|
-
return (0, solid_js_web.ssr)(_tmpl$$
|
|
1101
|
+
return (0, solid_js_web.ssr)(_tmpl$$9, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.Show, {
|
|
968
1102
|
get when() {
|
|
969
1103
|
return hasNewEdge();
|
|
970
1104
|
},
|
|
@@ -983,18 +1117,12 @@ var EdgesBoard = () => {
|
|
|
983
1117
|
};
|
|
984
1118
|
//#endregion
|
|
985
1119
|
//#region src/ui/components/NodeComponent.tsx
|
|
986
|
-
var _tmpl$$
|
|
1120
|
+
var _tmpl$$8 = [
|
|
987
1121
|
"<svg",
|
|
988
1122
|
" class=\"cursor-pointer overflow-visible rounded-full bg-green-500 p-0.5 text-center font-bold hover:bg-green-600\" style=\"",
|
|
989
1123
|
"\" viewBox=\"0 0 1024 1024\" preserveAspectRatio=\"xMaxYMax\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"white\"><g id=\"background\"><path d=\"M467.40667,277.66696c-0.05948,-14.53055 5.75527,-22.95613 -8.62044,-20.90487c-112.55699,16.0607 -222.1609,112.14558 -245.06161,239.85765c-46.52056,259.43466 231.33083,443.06705 449.51209,316.97506c117.31668,-67.80002 160.95215,-190.43324 151.34416,-288.29849c-5.92276,-60.32819 -27.80273,-107.95668 -53.44246,-144.25469l59.39269,-42.05363c111.72214,156.309 73.11535,351.55635 -25.06953,459.45565c-184.18877,202.4124 -470.46624,145.52064 -592.95027,-32.92123c-156.18269,-227.53604 -27.15324,-543.64371 261.18883,-582.44416c5.0579,-0.68061 3.56556,-7.04079 3.56442,-8.58985c-0.05594,-76.3354 -0.11021,-76.7687 1.10909,-77.24589c2.06886,-0.80969 151.41433,118.4561 151.92482,118.95524c4.65592,4.55233 -0.99548,7.829 -29.07828,30.50907c-120.49369,97.31245 -120.4977,98.55675 -123.0691,97.87586c-0.43639,-0.11555 -0.80698,-0.31322 -0.74442,-66.91571Z\"></path><path d=\"M316.61562,611.03414c0.11517,-90.16257 -0.25516,-99.92912 0.64739,-101.78856c1.56486,-3.22393 131.99102,0.91032 134.6959,-1.89763c2.21336,-2.2977 -0.59362,-129.97807 1.1376,-132.37034c0.7253,-1.00225 11.10552,-0.99175 12.07474,-0.99077c104.50336,0.10564 104.90098,-0.37811 105.967,0.85765c1.56461,1.81373 0.25596,114.18436 0.67852,129.81412c0.1322,4.88975 3.22386,3.28152 99.72028,3.4563c33.0841,0.05992 36.14259,-1.40368 36.21852,4.50462c0.11713,9.11348 1.41954,110.45369 -0.40274,113.92715c-1.81106,3.45208 -130.39967,-0.42618 -134.48289,1.62075c-2.29035,1.14816 -0.36989,101.12392 -1.11542,130.51904c-0.09548,3.76459 -2.13506,3.20617 -47.84854,3.17365c-69.30253,-0.0493 -69.31099,-0.25627 -69.65762,-0.42191c-3.77927,-1.80595 0.16287,-129.33555 -2.24266,-132.58994c-1.79931,-2.43424 -124.06108,-0.29118 -132.80252,-0.97392c-3.81102,-0.29766 -2.58229,-14.8847 -2.58758,-16.8402Z\"></path></g></svg>"
|
|
990
1124
|
];
|
|
991
|
-
var _tmpl$2$
|
|
992
|
-
"<div",
|
|
993
|
-
" id=\"outputs\" class=\"pointer-events-none absolute top-0 z-10 flex cursor-default flex-col\" style=\"",
|
|
994
|
-
"\"><div class=\"cursor-default rounded-full bg-[#e38b29] shadow-md\" style=\"",
|
|
995
|
-
"\"></div></div>"
|
|
996
|
-
];
|
|
997
|
-
var _tmpl$3$1 = [
|
|
1125
|
+
var _tmpl$2$4 = [
|
|
998
1126
|
"<div",
|
|
999
1127
|
" class=\"",
|
|
1000
1128
|
"\" style=\"",
|
|
@@ -1003,28 +1131,44 @@ var _tmpl$3$1 = [
|
|
|
1003
1131
|
"\"><svg class=\"cursor-pointer rounded-full fill-[#a11111] opacity-100 transition-all duration-200 ease-in-out\" fill=\"currentColor\" stroke-width=\"2\" viewBox=\"4 4 16 16\" style=\"",
|
|
1004
1132
|
"\"><path d=\"M12 4c-4.419 0-8 3.582-8 8s3.581 8 8 8 8-3.582 8-8-3.581-8-8-8zm3.707 10.293a.999.999 0 11-1.414 1.414L12 13.414l-2.293 2.293a.997.997 0 01-1.414 0 .999.999 0 010-1.414L10.586 12 8.293 9.707a.999.999 0 111.414-1.414L12 10.586l2.293-2.293a.999.999 0 111.414 1.414L13.414 12l2.293 2.293z\"></path></svg><!--$-->",
|
|
1005
1133
|
"<!--/--><svg class=\"flex cursor-pointer items-center justify-center rounded-lg bg-blue-500 p-0.5 text-center font-bold text-white hover:bg-blue-600\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\" style=\"",
|
|
1006
|
-
"\"><path d=\"M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z\"></path></svg></div
|
|
1007
|
-
"
|
|
1008
|
-
"
|
|
1009
|
-
"
|
|
1134
|
+
"\"><path d=\"M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z\"></path></svg></div><div>",
|
|
1135
|
+
"</div><div id=\"inputs\" class=\"pointer-events-none absolute top-0 z-10 flex cursor-default flex-col\" style=\"",
|
|
1136
|
+
"\"><div class=\"cursor-default rounded-full bg-[#e38b29] shadow-md\" style=\"",
|
|
1137
|
+
"\"></div></div><div id=\"outputs\" class=\"pointer-events-none absolute top-0 z-10 flex flex-col\" style=\"",
|
|
1010
1138
|
"\"><div class=\"cursor-crosshair rounded-full bg-[#e38b29] shadow-md\" style=\"",
|
|
1011
1139
|
"\"></div></div></div>"
|
|
1012
1140
|
];
|
|
1141
|
+
var _tmpl$3$2 = [
|
|
1142
|
+
"<div",
|
|
1143
|
+
" class=\"p-3 select-none\"><!--$-->",
|
|
1144
|
+
"<!--/--><!--$-->",
|
|
1145
|
+
"<!--/--><!--$-->",
|
|
1146
|
+
"<!--/--></div>"
|
|
1147
|
+
];
|
|
1013
1148
|
var _tmpl$4 = [
|
|
1014
1149
|
"<span",
|
|
1015
|
-
" class=\"min-w-max border-b border-[#f0f0f0]
|
|
1150
|
+
" class=\"mb-2 block min-w-max border-b border-[#f0f0f0] pb-2 font-semibold whitespace-nowrap text-red-600 select-none\">",
|
|
1016
1151
|
"</span>"
|
|
1017
1152
|
];
|
|
1018
1153
|
var _tmpl$5 = [
|
|
1019
1154
|
"<div",
|
|
1020
|
-
" class=\"
|
|
1155
|
+
" class=\"select-none\">",
|
|
1021
1156
|
"</div>"
|
|
1022
1157
|
];
|
|
1158
|
+
var _tmpl$6 = [
|
|
1159
|
+
"<div",
|
|
1160
|
+
"><span class=\"font-semibold\"><!--$-->",
|
|
1161
|
+
"<!--/-->: </span><span>",
|
|
1162
|
+
"</span></div>"
|
|
1163
|
+
];
|
|
1023
1164
|
/**
|
|
1024
1165
|
* Interactive flowchart node component supporting dragging, selection, handle
|
|
1025
1166
|
* connections, and child/sibling creation.
|
|
1026
1167
|
*
|
|
1027
|
-
* @
|
|
1168
|
+
* @template | {@linkcode NodeData} `D` - Custom node data dictionary type extending
|
|
1169
|
+
* {@linkcode NodeData}.
|
|
1170
|
+
*
|
|
1171
|
+
* @param props - Node rendering properties of type {@linkcode NodeComponentProps}.
|
|
1028
1172
|
*
|
|
1029
1173
|
* @returns The rendered Solid component.
|
|
1030
1174
|
*
|
|
@@ -1032,60 +1176,134 @@ var _tmpl$5 = [
|
|
|
1032
1176
|
*/
|
|
1033
1177
|
var NodeComponent = (props) => {
|
|
1034
1178
|
const service = useFlow();
|
|
1179
|
+
(0, _bemedev_app_solidjs.createState)(service, { selector: (s) => s.context.newEdge });
|
|
1180
|
+
(0, _thisbeyond_solid_dnd.createDraggable)(props.id);
|
|
1035
1181
|
const node = (0, _bemedev_app_solidjs.createState)(service, {
|
|
1036
1182
|
selector: ({ context }) => {
|
|
1037
1183
|
const item = _bemedev_app.toArray.typed(context.data?.nodes).find((n) => n.id === props.id);
|
|
1038
1184
|
return {
|
|
1039
|
-
x: item
|
|
1040
|
-
y: item
|
|
1041
|
-
|
|
1042
|
-
content: item.data.content ?? "",
|
|
1043
|
-
input: item.input
|
|
1185
|
+
x: item?.position.x ?? 0,
|
|
1186
|
+
y: item?.position.y ?? 0,
|
|
1187
|
+
data: item?.data ?? {}
|
|
1044
1188
|
};
|
|
1045
1189
|
},
|
|
1046
1190
|
equals: dequal.dequal
|
|
1047
1191
|
});
|
|
1048
|
-
(0, _bemedev_app_solidjs.createState)(service, { selector: (
|
|
1049
|
-
const selected = (0, _bemedev_app_solidjs.createState)(service, { selector: (s) => s.context.selected === props.id });
|
|
1192
|
+
const selected = (0, _bemedev_app_solidjs.createState)(service, { selector: ({ context }) => context.selected === props.id });
|
|
1050
1193
|
const hasParent = (0, _bemedev_app_solidjs.createState)(service, { selector: ({ context: { data } }) => {
|
|
1051
1194
|
const edges = data?.edges;
|
|
1052
1195
|
if (!edges) return false;
|
|
1053
1196
|
return edges.some(({ to }) => to === props.id);
|
|
1054
1197
|
} });
|
|
1055
|
-
(0,
|
|
1056
|
-
return (0, solid_js_web.ssr)(_tmpl$3$1, (0, solid_js_web.ssrHydrationKey)(), `flex flex-col absolute cursor-grab bg-white rounded-md shadow-md select-none transition-[border,box-shadow] duration-200 ease-in-out hover:shadow-lg draggable ${selected() ? "border border-[#e38c29] z-[100]" : ""} ${!selected() ? "border border-[#e6d4be] z-[1]" : ""} min-w-48`, (0, solid_js_web.ssrStyleProperty)("top:", `${(0, solid_js_web.escape)(node().y, true)}px`) + (0, solid_js_web.ssrStyleProperty)(";left:", `${(0, solid_js_web.escape)(node().x, true)}px`), (0, solid_js_web.ssrAttribute)("id", (0, solid_js_web.escape)(props.id, true), false), `pointer-events-none absolute flex items-center justify-end -top-7.5 right-0 transition-all duration-200 ease-in-out space-x-2 ${selected() ? "w-full opacity-100" : ""} ${!selected() ? "w-0 -right-3 opacity-0 overflow-hidden" : ""}`, (0, solid_js_web.ssrStyleProperty)("overflow:", "visible") + (0, solid_js_web.ssrStyleProperty)(";pointer-events:", "all") + (0, solid_js_web.ssrStyleProperty)(";width:", `${(0, solid_js_web.escape)(12, true) * 2}px`) + (0, solid_js_web.ssrStyleProperty)(";height:", `${(0, solid_js_web.escape)(12, true) * 2}px`), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1198
|
+
return (0, solid_js_web.ssr)(_tmpl$2$4, (0, solid_js_web.ssrHydrationKey)(), `flex flex-col absolute cursor-grab bg-white rounded-md shadow-md select-none transition-[border,box-shadow] duration-200 ease-in-out hover:shadow-lg draggable ${selected() ? "border border-[#e38c29] z-100" : ""} ${!selected() ? "border border-[#e6d4be] z-1" : ""} min-w-48`, (0, solid_js_web.ssrStyleProperty)("top:", `${(0, solid_js_web.escape)(node().y, true)}px`) + (0, solid_js_web.ssrStyleProperty)(";left:", `${(0, solid_js_web.escape)(node().x, true)}px`), (0, solid_js_web.ssrAttribute)("id", (0, solid_js_web.escape)(props.id, true), false), `pointer-events-none absolute flex items-center justify-end -top-7.5 right-0 transition-all duration-200 ease-in-out space-x-2 ${selected() ? "w-full opacity-100" : ""} ${!selected() ? "w-0 -right-3 opacity-0 overflow-hidden" : ""}`, (0, solid_js_web.ssrStyleProperty)("overflow:", "visible") + (0, solid_js_web.ssrStyleProperty)(";pointer-events:", "all") + (0, solid_js_web.ssrStyleProperty)(";width:", `${(0, solid_js_web.escape)(12, true) * 2}px`) + (0, solid_js_web.ssrStyleProperty)(";height:", `${(0, solid_js_web.escape)(12, true) * 2}px`), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1057
1199
|
get when() {
|
|
1058
1200
|
return hasParent();
|
|
1059
1201
|
},
|
|
1060
1202
|
get children() {
|
|
1061
|
-
return (0, solid_js_web.ssr)(_tmpl$$
|
|
1203
|
+
return (0, solid_js_web.ssr)(_tmpl$$8, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.ssrStyleProperty)("pointer-events:", "all") + (0, solid_js_web.ssrStyleProperty)(";fill-rule:", "evenodd") + (0, solid_js_web.ssrStyleProperty)(";clip-rule:", "evenodd") + (0, solid_js_web.ssrStyleProperty)(";stroke-linejoin:", "round") + (0, solid_js_web.ssrStyleProperty)(";stroke-miterlimit:", "2") + (0, solid_js_web.ssrStyleProperty)(";width:", `${(0, solid_js_web.escape)(12, true) * 2}px`) + (0, solid_js_web.ssrStyleProperty)(";height:", `${(0, solid_js_web.escape)(12, true) * 2}px`));
|
|
1062
1204
|
}
|
|
1063
1205
|
})), (0, solid_js_web.ssrStyleProperty)("pointer-events:", "all") + (0, solid_js_web.ssrStyleProperty)(";width:", `${(0, solid_js_web.escape)(12, true) * 2}px`) + (0, solid_js_web.ssrStyleProperty)(";height:", `${(0, solid_js_web.escape)(12, true) * 2}px`), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1064
1206
|
get when() {
|
|
1065
|
-
return
|
|
1066
|
-
},
|
|
1067
|
-
keyed: true,
|
|
1068
|
-
children: (label) => (0, solid_js_web.ssr)(_tmpl$4, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)(label))
|
|
1069
|
-
})), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1070
|
-
get when() {
|
|
1071
|
-
return node().content;
|
|
1207
|
+
return props.children;
|
|
1072
1208
|
},
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1209
|
+
get fallback() {
|
|
1210
|
+
return (0, solid_js_web.ssr)(_tmpl$3$2, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1211
|
+
get when() {
|
|
1212
|
+
return node().data.label;
|
|
1213
|
+
},
|
|
1214
|
+
keyed: true,
|
|
1215
|
+
children: (label) => (0, solid_js_web.ssr)(_tmpl$4, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)(String(label)))
|
|
1216
|
+
})), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1217
|
+
get when() {
|
|
1218
|
+
return node().data.content;
|
|
1219
|
+
},
|
|
1220
|
+
keyed: true,
|
|
1221
|
+
children: (content) => (0, solid_js_web.ssr)(_tmpl$5, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)(String(content)))
|
|
1222
|
+
})), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1223
|
+
get when() {
|
|
1224
|
+
return (0, solid_js_web.memo)(() => !!!node().data.label)() && !node().data.content;
|
|
1225
|
+
},
|
|
1226
|
+
get children() {
|
|
1227
|
+
return (0, solid_js_web.createComponent)(solid_js.For, {
|
|
1228
|
+
get each() {
|
|
1229
|
+
return Object.entries(node().data);
|
|
1230
|
+
},
|
|
1231
|
+
children: ([key, val]) => (0, solid_js_web.ssr)(_tmpl$6, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)(key), (0, solid_js_web.escape)(String(val)))
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1234
|
+
})));
|
|
1078
1235
|
},
|
|
1079
1236
|
get children() {
|
|
1080
|
-
return (0, solid_js_web.
|
|
1237
|
+
return (0, solid_js_web.createComponent)(solid_js_web.Dynamic, (0, solid_js_web.mergeProps)({ get component() {
|
|
1238
|
+
return props.children;
|
|
1239
|
+
} }, () => node().data));
|
|
1081
1240
|
}
|
|
1082
|
-
})), (0, solid_js_web.ssrStyleProperty)("right:", `-${(0, solid_js_web.escape)(18, true)}px`), (0, solid_js_web.ssrStyleProperty)("width:", `${(0, solid_js_web.escape)(12, true)}px`) + (0, solid_js_web.ssrStyleProperty)(";height:", `${(0, solid_js_web.escape)(12, true)}px`) + (0, solid_js_web.ssrStyleProperty)(";margin-top:", `${(0, solid_js_web.escape)(12, true)}px`) + (0, solid_js_web.ssrStyleProperty)(";pointer-events:", "all"));
|
|
1241
|
+
})), (0, solid_js_web.ssrStyleProperty)("left:", `-${(0, solid_js_web.escape)(18, true)}px`), (0, solid_js_web.ssrStyleProperty)("width:", `${(0, solid_js_web.escape)(12, true)}px`) + (0, solid_js_web.ssrStyleProperty)(";height:", `${(0, solid_js_web.escape)(12, true)}px`) + (0, solid_js_web.ssrStyleProperty)(";margin-top:", `${(0, solid_js_web.escape)(12, true)}px`) + (0, solid_js_web.ssrStyleProperty)(";pointer-events:", "all"), (0, solid_js_web.ssrStyleProperty)("right:", `-${(0, solid_js_web.escape)(18, true)}px`), (0, solid_js_web.ssrStyleProperty)("width:", `${(0, solid_js_web.escape)(12, true)}px`) + (0, solid_js_web.ssrStyleProperty)(";height:", `${(0, solid_js_web.escape)(12, true)}px`) + (0, solid_js_web.ssrStyleProperty)(";margin-top:", `${(0, solid_js_web.escape)(12, true)}px`) + (0, solid_js_web.ssrStyleProperty)(";pointer-events:", "all"));
|
|
1242
|
+
};
|
|
1243
|
+
//#endregion
|
|
1244
|
+
//#region src/ui/components/Panels.tsx
|
|
1245
|
+
var _tmpl$$7 = [
|
|
1246
|
+
"<div",
|
|
1247
|
+
" class=\"absolute top-4 left-4 z-50\">",
|
|
1248
|
+
"</div>"
|
|
1249
|
+
];
|
|
1250
|
+
var _tmpl$2$3 = [
|
|
1251
|
+
"<div",
|
|
1252
|
+
" class=\"absolute top-4 right-4 z-50\">",
|
|
1253
|
+
"</div>"
|
|
1254
|
+
];
|
|
1255
|
+
var _tmpl$3$1 = [
|
|
1256
|
+
"<div",
|
|
1257
|
+
" class=\"absolute bottom-4 left-4 z-50\">",
|
|
1258
|
+
"</div>"
|
|
1259
|
+
];
|
|
1260
|
+
/**
|
|
1261
|
+
* Overlay container rendering custom panel slots positioned around the flowchart
|
|
1262
|
+
* canvas.
|
|
1263
|
+
*
|
|
1264
|
+
* @param props - Flow panels layout properties of type {@linkcode FlowPanels}.
|
|
1265
|
+
*
|
|
1266
|
+
* @returns Rendered overlay panels JSX elements.
|
|
1267
|
+
*/
|
|
1268
|
+
var Panels = (props) => {
|
|
1269
|
+
return [
|
|
1270
|
+
(0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1271
|
+
get when() {
|
|
1272
|
+
return props.topLeft;
|
|
1273
|
+
},
|
|
1274
|
+
keyed: true,
|
|
1275
|
+
children: (Panel) => {
|
|
1276
|
+
const Component = typeof Panel === "function" ? (0, solid_js_web.createComponent)(Panel, {}) : Panel;
|
|
1277
|
+
return (0, solid_js_web.ssr)(_tmpl$$7, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)(Component));
|
|
1278
|
+
}
|
|
1279
|
+
}),
|
|
1280
|
+
(0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1281
|
+
get when() {
|
|
1282
|
+
return props.topRight;
|
|
1283
|
+
},
|
|
1284
|
+
keyed: true,
|
|
1285
|
+
children: (Panel) => {
|
|
1286
|
+
const Component = typeof Panel === "function" ? (0, solid_js_web.createComponent)(Panel, {}) : Panel;
|
|
1287
|
+
return (0, solid_js_web.ssr)(_tmpl$2$3, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)(Component));
|
|
1288
|
+
}
|
|
1289
|
+
}),
|
|
1290
|
+
(0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1291
|
+
get when() {
|
|
1292
|
+
return props.bottomLeft;
|
|
1293
|
+
},
|
|
1294
|
+
keyed: true,
|
|
1295
|
+
children: (Panel) => {
|
|
1296
|
+
const Component = typeof Panel === "function" ? (0, solid_js_web.createComponent)(Panel, {}) : Panel;
|
|
1297
|
+
return (0, solid_js_web.ssr)(_tmpl$3$1, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)(Component));
|
|
1298
|
+
}
|
|
1299
|
+
})
|
|
1300
|
+
];
|
|
1083
1301
|
};
|
|
1084
1302
|
//#endregion
|
|
1085
1303
|
//#region src/ui/components/NodesBoard.tsx
|
|
1086
|
-
var _tmpl$$
|
|
1304
|
+
var _tmpl$$6 = [
|
|
1087
1305
|
"<div",
|
|
1088
|
-
" class=\"relative h-full w-full overflow-auto
|
|
1306
|
+
" class=\"relative h-full w-full overflow-auto\"><!--$-->",
|
|
1089
1307
|
"<!--/--><div class=\"",
|
|
1090
1308
|
"\" style=\"",
|
|
1091
1309
|
"\"><div class=\"relative h-full w-full\" style=\"",
|
|
@@ -1094,32 +1312,36 @@ var _tmpl$$1 = [
|
|
|
1094
1312
|
"<!--/--><!--$-->",
|
|
1095
1313
|
"<!--/--></div></div></div>"
|
|
1096
1314
|
];
|
|
1097
|
-
var _tmpl$2 = [
|
|
1315
|
+
var _tmpl$2$2 = [
|
|
1098
1316
|
"<div",
|
|
1099
1317
|
" class=\"absolute right-4 bottom-4 z-50 flex items-center gap-2 rounded-xl border border-gray-200 bg-white/90 p-2 shadow-lg backdrop-blur-md\"><button type=\"button\" class=\"flex size-9 cursor-pointer items-center justify-center rounded-lg bg-gray-100 text-lg font-bold text-gray-700 shadow-sm transition-all duration-150 hover:bg-gray-200 active:scale-95\" title=\"Zoom out\" aria-label=\"Zoom out\">-</button><button type=\"button\" class=\"h-9 cursor-pointer rounded-lg px-2 text-xs font-semibold text-gray-700 transition-colors hover:bg-gray-100\" title=\"Reset zoom\" aria-label=\"Reset zoom\"><!--$-->",
|
|
1100
1318
|
"<!--/-->%</button><button type=\"button\" class=\"flex size-9 cursor-pointer items-center justify-center rounded-lg bg-gray-100 text-lg font-bold text-gray-700 shadow-sm transition-all duration-150 hover:bg-gray-200 active:scale-95\" title=\"Zoom in\" aria-label=\"Zoom in\">+</button><div class=\"h-5 w-px bg-gray-300\"></div><button type=\"button\" class=\"flex size-9 cursor-pointer items-center justify-center rounded-lg bg-blue-600 text-white shadow transition-all duration-150 hover:bg-blue-700 active:scale-95\" title=\"Add parent node\" aria-label=\"Add parent node\"><svg class=\"size-5\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z\"></path></svg></button></div>"
|
|
1101
1319
|
];
|
|
1102
1320
|
var _tmpl$3 = [
|
|
1103
1321
|
"<div",
|
|
1104
|
-
" class=\"relative mx-auto h-
|
|
1322
|
+
" class=\"relative mx-auto h-full w-full overflow-hidden\">",
|
|
1105
1323
|
"</div>"
|
|
1106
1324
|
];
|
|
1107
1325
|
/**
|
|
1108
1326
|
* Interactive board component containing the drag-drop viewport, zoom controls,
|
|
1109
1327
|
* panning gestures, and rendered nodes/edges.
|
|
1110
1328
|
*
|
|
1329
|
+
* @template | {@linkcode NodeData} `D` - Custom node data dictionary type extending
|
|
1330
|
+
* {@linkcode NodeData}.
|
|
1331
|
+
*
|
|
1332
|
+
* @param props - Board component properties of type {@linkcode Props}.
|
|
1333
|
+
*
|
|
1111
1334
|
* @returns The rendered Solid component.
|
|
1112
1335
|
*
|
|
1113
1336
|
* @see {@linkcode DragBounds}, {@linkcode EdgesBoard}, {@linkcode NodeComponent}, {@linkcode useFlow}, {@linkcode CANVAS_FACTOR}, {@linkcode SCROLL_MULTIPLIER}
|
|
1114
1337
|
*/
|
|
1115
|
-
var NodesBoard = () => {
|
|
1338
|
+
var NodesBoard = (props) => {
|
|
1116
1339
|
let containerRef;
|
|
1117
1340
|
const [isPanning, setIsPanning] = (0, solid_js.createSignal)(false);
|
|
1118
1341
|
const [transform, setTransform] = (0, solid_js.createSignal)({
|
|
1119
1342
|
x: 0,
|
|
1120
1343
|
y: 0
|
|
1121
1344
|
});
|
|
1122
|
-
const [id, setId] = (0, solid_js.createSignal)("");
|
|
1123
1345
|
const [ref, setRef] = (0, solid_js.createSignal)();
|
|
1124
1346
|
let percentX = 0;
|
|
1125
1347
|
let percentY = 0;
|
|
@@ -1165,14 +1387,6 @@ var NodesBoard = () => {
|
|
|
1165
1387
|
}, { defer: true }));
|
|
1166
1388
|
(0, solid_js.onMount)(sendBoard);
|
|
1167
1389
|
const selectedId = (0, _bemedev_app_solidjs.createState)(service, { selector: (s) => s.context?.selected });
|
|
1168
|
-
/**
|
|
1169
|
-
* Determines whether the given element ID matches the currently selected entity.
|
|
1170
|
-
*
|
|
1171
|
-
* @param id - The node or edge identifier to check.
|
|
1172
|
-
*
|
|
1173
|
-
* @returns `true` if the item is currently selected, otherwise `false`.
|
|
1174
|
-
*/
|
|
1175
|
-
const selected = (id) => selectedId() === id;
|
|
1176
1390
|
const nodeIds = (0, _bemedev_app_solidjs.createState)(service, {
|
|
1177
1391
|
selector: ({ context }) => {
|
|
1178
1392
|
return _bemedev_app.toArray.typed(context.data?.nodes).map((item) => item.id);
|
|
@@ -1188,37 +1402,33 @@ var NodesBoard = () => {
|
|
|
1188
1402
|
const cHeight = () => `calc((${CANVAS_SIZE}vh - ${MARGIN_Y}px) * ${zoom()})`;
|
|
1189
1403
|
return (0, solid_js_web.ssr)(_tmpl$3, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(_thisbeyond_solid_dnd.DragDropProvider, {
|
|
1190
1404
|
onDragMove: ({ draggable: { transform: _transform, node, id } }) => {
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
y: deltaY * currentZoom
|
|
1217
|
-
});
|
|
1218
|
-
}
|
|
1405
|
+
const grandParent = node.parentElement?.parentElement;
|
|
1406
|
+
const currentZoom = zoom();
|
|
1407
|
+
const minX = 0;
|
|
1408
|
+
const maxX = grandParent ? Math.max(0, grandParent.clientWidth / currentZoom - node.offsetWidth) : Infinity;
|
|
1409
|
+
const minY = 0;
|
|
1410
|
+
const maxY = grandParent ? Math.max(0, grandParent.clientHeight / currentZoom - node.offsetHeight) : Infinity;
|
|
1411
|
+
const targetX = node.offsetLeft + _transform.x / currentZoom;
|
|
1412
|
+
const targetY = node.offsetTop + _transform.y / currentZoom;
|
|
1413
|
+
const x = Math.min(Math.max(targetX, minX), maxX);
|
|
1414
|
+
const y = Math.min(Math.max(targetY, minY), maxY);
|
|
1415
|
+
const deltaX = x - node.offsetLeft;
|
|
1416
|
+
const deltaY = y - node.offsetTop;
|
|
1417
|
+
node.style.setProperty("transform", `translate3d(${deltaX}px, ${deltaY}px, 0)`);
|
|
1418
|
+
service.send({
|
|
1419
|
+
type: "MOVE_IMMEDIATE",
|
|
1420
|
+
payload: {
|
|
1421
|
+
id: `${id}`,
|
|
1422
|
+
x,
|
|
1423
|
+
y
|
|
1424
|
+
}
|
|
1425
|
+
});
|
|
1426
|
+
setTransform({
|
|
1427
|
+
x: deltaX * currentZoom,
|
|
1428
|
+
y: deltaY * currentZoom
|
|
1429
|
+
});
|
|
1219
1430
|
},
|
|
1220
1431
|
onDragEnd: ({ draggable: { node, id } }) => {
|
|
1221
|
-
if (!selected(id)) return;
|
|
1222
1432
|
const grandParent = node.parentElement?.parentElement;
|
|
1223
1433
|
const currentZoom = zoom();
|
|
1224
1434
|
const minX = 0;
|
|
@@ -1249,16 +1459,22 @@ var NodesBoard = () => {
|
|
|
1249
1459
|
},
|
|
1250
1460
|
get children() {
|
|
1251
1461
|
return [
|
|
1252
|
-
(0, solid_js_web.ssr)(_tmpl$$
|
|
1462
|
+
(0, solid_js_web.ssr)(_tmpl$$6, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(_thisbeyond_solid_dnd.DragDropSensors, {})), `relative cursor-crosshair overflow-hidden ${isPanning() ? "cursor-grabbing" : ""}`, (0, solid_js_web.ssrStyleProperty)("height:", (0, solid_js_web.escape)(cHeight(), true)) + (0, solid_js_web.ssrStyleProperty)(";width:", (0, solid_js_web.escape)(cWidth(), true)), (0, solid_js_web.ssrStyleProperty)("scale:", (0, solid_js_web.escape)(zoom(), true)) + (0, solid_js_web.ssrStyleProperty)(";transform-origin:", "top left"), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(DragBounds, {})), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(EdgesBoard, {})), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.For, {
|
|
1253
1463
|
get each() {
|
|
1254
1464
|
return nodeIds();
|
|
1255
1465
|
},
|
|
1256
|
-
children: (id) => (0, solid_js_web.createComponent)(NodeComponent, {
|
|
1466
|
+
children: (id) => (0, solid_js_web.createComponent)(NodeComponent, {
|
|
1467
|
+
id,
|
|
1468
|
+
get children() {
|
|
1469
|
+
return props.component;
|
|
1470
|
+
}
|
|
1471
|
+
})
|
|
1257
1472
|
}))),
|
|
1258
|
-
(0, solid_js_web.
|
|
1473
|
+
(0, solid_js_web.createComponent)(Panels, (0, solid_js_web.mergeProps)(() => props.panels)),
|
|
1474
|
+
(0, solid_js_web.ssr)(_tmpl$2$2, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)(Math.round(zoom() * 100))),
|
|
1259
1475
|
(0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1260
1476
|
get when() {
|
|
1261
|
-
return !
|
|
1477
|
+
return !selectedId();
|
|
1262
1478
|
},
|
|
1263
1479
|
get children() {
|
|
1264
1480
|
return (0, solid_js_web.createComponent)(_thisbeyond_solid_dnd.DragOverlay, { children: "" });
|
|
@@ -1270,9 +1486,9 @@ var NodesBoard = () => {
|
|
|
1270
1486
|
};
|
|
1271
1487
|
//#endregion
|
|
1272
1488
|
//#region src/ui/components/FlowChart.tsx
|
|
1273
|
-
var _tmpl
|
|
1489
|
+
var _tmpl$$5 = [
|
|
1274
1490
|
"<div",
|
|
1275
|
-
" class=\"relative h-full w-full\"><div class=\"
|
|
1491
|
+
" class=\"relative h-full w-full\"><div class=\"h-full w-full\" style=\"",
|
|
1276
1492
|
"\">",
|
|
1277
1493
|
"</div></div>"
|
|
1278
1494
|
];
|
|
@@ -1280,6 +1496,9 @@ var _tmpl$ = [
|
|
|
1280
1496
|
* Flowchart board canvas component that renders interactive nodes, edges, pan/zoom,
|
|
1281
1497
|
* and toolbar controls.
|
|
1282
1498
|
*
|
|
1499
|
+
* @template | {@linkcode NodeData} `D` - Custom node data dictionary type extending
|
|
1500
|
+
* {@linkcode NodeData}.
|
|
1501
|
+
*
|
|
1283
1502
|
* @param props - Flowchart configuration and event handlers of type
|
|
1284
1503
|
* {@linkcode FlowProps}.
|
|
1285
1504
|
*
|
|
@@ -1292,35 +1511,548 @@ var FlowChart = (props) => {
|
|
|
1292
1511
|
const primaryEdges = props.config?.edges;
|
|
1293
1512
|
const service = useFlow();
|
|
1294
1513
|
const hasNewEdge = (0, _bemedev_app_solidjs.createState)(service, { selector: (s) => !!s.context.newEdge });
|
|
1514
|
+
(0, solid_js.onCleanup)(service.pause);
|
|
1295
1515
|
(0, solid_js.onMount)(() => {
|
|
1296
1516
|
service.resume();
|
|
1297
1517
|
service.send({
|
|
1298
1518
|
type: "CONFIGURE",
|
|
1299
1519
|
payload: {
|
|
1300
1520
|
nodes: primaryNodes,
|
|
1301
|
-
edges: primaryEdges ?? []
|
|
1521
|
+
edges: primaryEdges ?? [],
|
|
1522
|
+
defaultData: props.defaultData
|
|
1302
1523
|
}
|
|
1303
1524
|
});
|
|
1304
1525
|
});
|
|
1305
|
-
(0,
|
|
1306
|
-
|
|
1526
|
+
return (0, solid_js_web.ssr)(_tmpl$$5, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.ssrStyleProperty)("cursor:", hasNewEdge() ? "inherit" : "crosshair"), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(NodesBoard, {
|
|
1527
|
+
get panels() {
|
|
1528
|
+
return props.panels;
|
|
1529
|
+
},
|
|
1530
|
+
get component() {
|
|
1531
|
+
return props.component;
|
|
1532
|
+
}
|
|
1533
|
+
})));
|
|
1534
|
+
};
|
|
1535
|
+
//#endregion
|
|
1536
|
+
//#region src/ui/utils.ts
|
|
1537
|
+
/**
|
|
1538
|
+
* Merges conditional CSS class names using `clsx` and resolves Tailwind CSS class
|
|
1539
|
+
* conflicts with `twMerge`.
|
|
1540
|
+
*
|
|
1541
|
+
* @param inputs - Variable list of class values, objects, or arrays.
|
|
1542
|
+
*
|
|
1543
|
+
* @returns The resolved single class name string.
|
|
1544
|
+
*/
|
|
1545
|
+
function cn(...inputs) {
|
|
1546
|
+
return (0, tailwind_merge.twMerge)((0, clsx.clsx)(inputs));
|
|
1547
|
+
}
|
|
1548
|
+
//#endregion
|
|
1549
|
+
//#region src/ui/globals/helpers/espace.ts
|
|
1550
|
+
/**
|
|
1551
|
+
* Returns a zero-width space if string is empty, preserving layout flow.
|
|
1552
|
+
*
|
|
1553
|
+
* @param newText - The input text string.
|
|
1554
|
+
*
|
|
1555
|
+
* @returns The input text or zero-width visible space placeholder.
|
|
1556
|
+
*/
|
|
1557
|
+
var espace = (newText) => {
|
|
1558
|
+
if (newText === "") return "";
|
|
1559
|
+
return newText;
|
|
1560
|
+
};
|
|
1561
|
+
//#endregion
|
|
1562
|
+
//#region src/ui/globals/signals/createTyping.ts
|
|
1563
|
+
/**
|
|
1564
|
+
* Creates a reactive typewriter effect signal with oscillatory typing delay and
|
|
1565
|
+
* optional rewind.
|
|
1566
|
+
*
|
|
1567
|
+
* @param props - Configuration properties of type {@linkcode Props}.
|
|
1568
|
+
*
|
|
1569
|
+
* @returns An object containing the current text signal, type trigger, and text
|
|
1570
|
+
* setter.
|
|
1571
|
+
*/
|
|
1572
|
+
var createTyping = ({ content, min, ...props }) => {
|
|
1573
|
+
const rewind = props.rewind ?? false;
|
|
1574
|
+
const rewindDelay = props.rewindDelay ?? 500;
|
|
1575
|
+
const OSCILLATION = Math.min(min / 10 + content.length / 10, 10);
|
|
1576
|
+
const [text, setText] = (0, solid_js.createSignal)("");
|
|
1577
|
+
let timeoutId;
|
|
1578
|
+
let index = 0;
|
|
1579
|
+
let isTyping = true;
|
|
1580
|
+
const max = min + OSCILLATION;
|
|
1581
|
+
let interval = min;
|
|
1582
|
+
let intervalDirection = 1;
|
|
1583
|
+
const type = () => {
|
|
1584
|
+
if (isTyping) {
|
|
1585
|
+
if (index < content.length) {
|
|
1586
|
+
setText((prev) => prev + content[index]);
|
|
1587
|
+
index++;
|
|
1588
|
+
timeoutId = setTimeout(type, interval);
|
|
1589
|
+
} else if (rewind) {
|
|
1590
|
+
isTyping = false;
|
|
1591
|
+
intervalDirection = 1;
|
|
1592
|
+
timeoutId = setTimeout(type, rewindDelay);
|
|
1593
|
+
}
|
|
1594
|
+
} else if (index > 0) {
|
|
1595
|
+
index--;
|
|
1596
|
+
setText(espace(content.substring(0, index)));
|
|
1597
|
+
timeoutId = setTimeout(type, interval);
|
|
1598
|
+
} else {
|
|
1599
|
+
isTyping = true;
|
|
1600
|
+
intervalDirection = 1;
|
|
1601
|
+
timeoutId = setTimeout(type, rewindDelay);
|
|
1602
|
+
}
|
|
1603
|
+
interval += intervalDirection;
|
|
1604
|
+
if (interval >= max) intervalDirection = -1;
|
|
1605
|
+
else if (interval <= min) intervalDirection = 1;
|
|
1606
|
+
};
|
|
1607
|
+
(0, solid_js.onCleanup)(() => {
|
|
1608
|
+
if (timeoutId !== void 0) clearTimeout(timeoutId);
|
|
1609
|
+
});
|
|
1610
|
+
return {
|
|
1611
|
+
text,
|
|
1612
|
+
type,
|
|
1613
|
+
setText
|
|
1614
|
+
};
|
|
1615
|
+
};
|
|
1616
|
+
//#endregion
|
|
1617
|
+
//#region src/ui/globals/components/atoms/TypingText.tsx
|
|
1618
|
+
var _tmpl$$4 = [
|
|
1619
|
+
"<div",
|
|
1620
|
+
">",
|
|
1621
|
+
"</div>"
|
|
1622
|
+
];
|
|
1623
|
+
/**
|
|
1624
|
+
* Renders animated text with a typewriter keystroke animation effect.
|
|
1625
|
+
*
|
|
1626
|
+
* @param props - Component configuration properties of type {@linkcode Props}.
|
|
1627
|
+
*
|
|
1628
|
+
* @returns Rendered animated typing text JSX container.
|
|
1629
|
+
*/
|
|
1630
|
+
var TypingText = (props) => {
|
|
1631
|
+
const min = props.interval ?? 62;
|
|
1632
|
+
const rewind = props.rewind ?? false;
|
|
1633
|
+
const rewindDelay = props.rewindDelay ?? 500;
|
|
1634
|
+
const content = props.children;
|
|
1635
|
+
const disabled = (0, solid_js.createMemo)(() => props.disabled ? props.disabled() : false, false);
|
|
1636
|
+
const { text, type, setText } = createTyping({
|
|
1637
|
+
content,
|
|
1638
|
+
min,
|
|
1639
|
+
rewind,
|
|
1640
|
+
rewindDelay
|
|
1641
|
+
});
|
|
1642
|
+
(0, solid_js.createEffect)((0, solid_js.on)(disabled, () => setText("")));
|
|
1643
|
+
(0, solid_js.createEffect)(() => {
|
|
1644
|
+
if (disabled()) setText(content);
|
|
1645
|
+
else type();
|
|
1646
|
+
});
|
|
1647
|
+
return (0, solid_js_web.ssr)(_tmpl$$4, (0, solid_js_web.ssrHydrationKey)() + (0, solid_js_web.ssrAttribute)("class", (0, solid_js_web.escape)(props.class, true), false), (0, solid_js_web.escape)(text()));
|
|
1648
|
+
};
|
|
1649
|
+
//#endregion
|
|
1650
|
+
//#region src/ui/globals/components/molecules/FadingDots.tsx
|
|
1651
|
+
var _tmpl$$3 = [
|
|
1652
|
+
"<div",
|
|
1653
|
+
" class=\"mt-4 flex items-center justify-center space-x-4\">",
|
|
1654
|
+
"</div>"
|
|
1655
|
+
];
|
|
1656
|
+
/**
|
|
1657
|
+
* Loading animation component displaying animated pulsing dots.
|
|
1658
|
+
*
|
|
1659
|
+
* @param props - Fading dots configuration properties.
|
|
1660
|
+
* @param props.count - The number of dots to display.
|
|
1661
|
+
* @param props.duration - Animation duration in milliseconds. Defaults to 500.
|
|
1662
|
+
* @param props.innerProps - Additional properties and CSS styles applied to dot
|
|
1663
|
+
* elements.
|
|
1664
|
+
*
|
|
1665
|
+
* @returns Rendered animated dots container JSX element.
|
|
1666
|
+
*/
|
|
1667
|
+
var FadingDots = ({ count: length, innerProps = {}, duration = 500 }) => {
|
|
1668
|
+
const [local, rest] = (0, solid_js.splitProps)(innerProps, ["class", "style"]);
|
|
1669
|
+
return (0, solid_js_web.ssr)(_tmpl$$3, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)(Array.from({ length }, (_, i) => (0, solid_js_web.ssrElement)("span", (0, solid_js_web.mergeProps)({
|
|
1670
|
+
get ["class"]() {
|
|
1671
|
+
return cn("rounded-full animate-out direction-alternate repeat-infinite fade-out-5 size-4 bg-gray-600", local.class);
|
|
1672
|
+
},
|
|
1673
|
+
get style() {
|
|
1674
|
+
return {
|
|
1675
|
+
...local.style,
|
|
1676
|
+
"animation-duration": `${duration}ms`,
|
|
1677
|
+
"animation-delay": `${duration / i}ms`
|
|
1678
|
+
};
|
|
1679
|
+
},
|
|
1680
|
+
"aria-hidden": "true"
|
|
1681
|
+
}, rest), void 0, true))));
|
|
1682
|
+
};
|
|
1683
|
+
//#endregion
|
|
1684
|
+
//#region src/ui/globals/components/organisms/LoadingFallback.tsx
|
|
1685
|
+
var _tmpl$$2 = [
|
|
1686
|
+
"<div",
|
|
1687
|
+
" role=\"status\" aria-live=\"polite\" aria-label=\"Chargement en cours\"><div class=\"relative\"><div",
|
|
1688
|
+
" aria-hidden=\"true\"></div><div",
|
|
1689
|
+
" aria-hidden=\"true\"></div></div><div class=\"text-center\"",
|
|
1690
|
+
"><!--$-->",
|
|
1691
|
+
"<!--/--><!--$-->",
|
|
1692
|
+
"<!--/--></div></div>"
|
|
1693
|
+
];
|
|
1694
|
+
/**
|
|
1695
|
+
* Fallback loading screen component displaying an animated spinner and typewriter
|
|
1696
|
+
* text.
|
|
1697
|
+
*
|
|
1698
|
+
* @example
|
|
1699
|
+
* ```tsx
|
|
1700
|
+
* <Show when={data()} fallback={<LoadingFallback />}>
|
|
1701
|
+
* <DataComponent data={data()!} />
|
|
1702
|
+
* </Show>;
|
|
1703
|
+
* ```;
|
|
1704
|
+
*
|
|
1705
|
+
* @param props - Loading fallback properties of type
|
|
1706
|
+
* {@linkcode LoadingFallbackProps}.
|
|
1707
|
+
*
|
|
1708
|
+
* @returns Rendered full-screen loading fallback JSX element.
|
|
1709
|
+
*/
|
|
1710
|
+
var LoadingFallback = (props) => {
|
|
1711
|
+
const message = props.message ?? "Chargement en cours...";
|
|
1712
|
+
const spinnerSizes = {
|
|
1713
|
+
sm: "w-8 h-8",
|
|
1714
|
+
md: "w-12 h-12",
|
|
1715
|
+
lg: "w-16 h-16",
|
|
1716
|
+
xl: "w-24 h-24"
|
|
1717
|
+
};
|
|
1718
|
+
const size = props.size ?? "lg";
|
|
1719
|
+
return (0, solid_js_web.ssr)(_tmpl$$2, (0, solid_js_web.ssrHydrationKey)() + (0, solid_js_web.ssrAttribute)("class", (0, solid_js_web.escape)(cn("flex flex-col items-center justify-center gap-6", "h-screen w-screen overflow-hidden p-4", props.class), true), false), (0, solid_js_web.ssrAttribute)("class", (0, solid_js_web.escape)(cn(spinnerSizes[size], "rounded-full border-4 border-[#4B9CAD]/20", "animate-spin", "border-t-[#4B9CAD]"), true), false), (0, solid_js_web.ssrAttribute)("class", (0, solid_js_web.escape)(cn("absolute inset-2", "rounded-full border-4 border-transparent", "border-b-[#4B9CAD]/40", "animate-spin", "animation-duration-[1.5s]", "direction-[reverse]"), true), false), (0, solid_js_web.ssrAttribute)("aria-label", (0, solid_js_web.escape)(message, true), false), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(TypingText, {
|
|
1720
|
+
"class": "text-lg font-medium text-gray-700 md:text-xl dark:text-gray-300",
|
|
1721
|
+
get interval() {
|
|
1722
|
+
return props.interval ?? 80;
|
|
1723
|
+
},
|
|
1724
|
+
get rewind() {
|
|
1725
|
+
return props.rewind ?? true;
|
|
1726
|
+
},
|
|
1727
|
+
get rewindDelay() {
|
|
1728
|
+
return props.rewindDelay ?? 2e3;
|
|
1729
|
+
},
|
|
1730
|
+
children: message
|
|
1731
|
+
})), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(FadingDots, {
|
|
1732
|
+
count: 5,
|
|
1733
|
+
innerProps: { class: "bg-[#3d8091]" }
|
|
1734
|
+
})));
|
|
1307
1735
|
};
|
|
1308
1736
|
//#endregion
|
|
1309
1737
|
//#region src/ui/Flow.tsx
|
|
1738
|
+
var _tmpl$$1 = [
|
|
1739
|
+
"<div",
|
|
1740
|
+
" style=\"",
|
|
1741
|
+
"\" class=\"relative flex h-full w-full rounded-lg border-2 border-gray-600 bg-white bg-size-[30px_30px]\">",
|
|
1742
|
+
"</div>"
|
|
1743
|
+
];
|
|
1744
|
+
var _tmpl$2$1 = [
|
|
1745
|
+
"<div",
|
|
1746
|
+
" class=\"relative flex flex-1 items-center justify-center\">",
|
|
1747
|
+
"</div>"
|
|
1748
|
+
];
|
|
1310
1749
|
/**
|
|
1311
1750
|
* Root Flow component wrapping the {@linkcode FlowChart} inside the flow context
|
|
1312
1751
|
* provider.
|
|
1313
1752
|
*
|
|
1753
|
+
* @template | {@linkcode NodeData} `D` - Custom node data dictionary type extending
|
|
1754
|
+
* {@linkcode NodeData}.
|
|
1755
|
+
*
|
|
1314
1756
|
* @param props - Flow chart configuration and callbacks of type
|
|
1315
1757
|
* {@linkcode FlowProps}.
|
|
1316
1758
|
*
|
|
1317
1759
|
* @returns The rendered Solid component.
|
|
1318
1760
|
*
|
|
1319
|
-
* @see {@linkcode Provider}
|
|
1761
|
+
* @see {@linkcode Provider}, {@linkcode FlowChart}
|
|
1762
|
+
*/
|
|
1763
|
+
var Flow = (props) => {
|
|
1764
|
+
const [isMounted, setIsMounted] = (0, solid_js.createSignal)(false);
|
|
1765
|
+
(0, solid_js.onMount)(() => setTimeout(() => setIsMounted(true), props.delay));
|
|
1766
|
+
return (0, solid_js_web.ssr)(_tmpl$$1, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.ssrStyleProperty)("background-image:", "radial-gradient(circle, #b8b8b8bf 1px, rgba(0, 0, 0, 0) 1px)"), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1767
|
+
get when() {
|
|
1768
|
+
return isMounted();
|
|
1769
|
+
},
|
|
1770
|
+
keyed: true,
|
|
1771
|
+
get fallback() {
|
|
1772
|
+
return (0, solid_js_web.ssr)(_tmpl$2$1, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(LoadingFallback, {
|
|
1773
|
+
message: "Chart is loading...",
|
|
1774
|
+
interval: 35,
|
|
1775
|
+
rewind: true,
|
|
1776
|
+
rewindDelay: 1e3
|
|
1777
|
+
})));
|
|
1778
|
+
},
|
|
1779
|
+
get children() {
|
|
1780
|
+
return (0, solid_js_web.createComponent)(Provider, { get children() {
|
|
1781
|
+
return (0, solid_js_web.createComponent)(FlowChart, props);
|
|
1782
|
+
} });
|
|
1783
|
+
}
|
|
1784
|
+
})));
|
|
1785
|
+
};
|
|
1786
|
+
//#endregion
|
|
1787
|
+
//#region src/ui/globals/directives/clickOutside.ts
|
|
1788
|
+
/**
|
|
1789
|
+
* Solid custom directive that triggers a callback when a click occurs outside the
|
|
1790
|
+
* bound element.
|
|
1791
|
+
*
|
|
1792
|
+
* @param el - The bound DOM element.
|
|
1793
|
+
* @param accessor - Accessor returning the callback function to execute.
|
|
1794
|
+
*/
|
|
1795
|
+
var clickOutside = (el, accessor) => {
|
|
1796
|
+
const onClick = (e) => {
|
|
1797
|
+
if (!el.contains(e.target)) accessor()?.();
|
|
1798
|
+
};
|
|
1799
|
+
document.body.addEventListener("click", onClick);
|
|
1800
|
+
(0, solid_js.onCleanup)(() => document.body.removeEventListener("click", onClick));
|
|
1801
|
+
};
|
|
1802
|
+
//#endregion
|
|
1803
|
+
//#region src/ui/globals/directives/mouseOut.ts
|
|
1804
|
+
/**
|
|
1805
|
+
* Solid custom directive that triggers a callback when the mouse leaves the bound
|
|
1806
|
+
* element after a specified timer duration. If the user re-enters the component
|
|
1807
|
+
* before the timer expires, the timer is reset/cancelled.
|
|
1808
|
+
*
|
|
1809
|
+
* @param el - The bound DOM element.
|
|
1810
|
+
* @param accessor - Accessor returning a callback, tuple `[callback, delay]`, or
|
|
1811
|
+
* type {@linkcode MouseOutOptions}.
|
|
1812
|
+
*/
|
|
1813
|
+
var mouseOut = (el, accessor) => {
|
|
1814
|
+
let timer;
|
|
1815
|
+
const clear = () => {
|
|
1816
|
+
if (timer !== void 0) {
|
|
1817
|
+
clearTimeout(timer);
|
|
1818
|
+
timer = void 0;
|
|
1819
|
+
}
|
|
1820
|
+
};
|
|
1821
|
+
const onMouseEnter = () => {
|
|
1822
|
+
clear();
|
|
1823
|
+
};
|
|
1824
|
+
const onMouseLeave = (event) => {
|
|
1825
|
+
clear();
|
|
1826
|
+
const param = accessor();
|
|
1827
|
+
if (!param) return;
|
|
1828
|
+
let callback;
|
|
1829
|
+
let delay = 0;
|
|
1830
|
+
if (typeof param === "function") callback = param;
|
|
1831
|
+
else if (Array.isArray(param)) {
|
|
1832
|
+
callback = param[0];
|
|
1833
|
+
delay = param[1] ?? 0;
|
|
1834
|
+
} else if (typeof param === "object") {
|
|
1835
|
+
callback = param.callback ?? param.onMouseOut;
|
|
1836
|
+
delay = param.delay ?? 0;
|
|
1837
|
+
}
|
|
1838
|
+
if (!callback) return;
|
|
1839
|
+
if (delay > 0) timer = setTimeout(() => {
|
|
1840
|
+
callback?.(event);
|
|
1841
|
+
timer = void 0;
|
|
1842
|
+
}, delay);
|
|
1843
|
+
else callback(event);
|
|
1844
|
+
};
|
|
1845
|
+
el.addEventListener("mouseleave", onMouseLeave);
|
|
1846
|
+
el.addEventListener("mouseenter", onMouseEnter);
|
|
1847
|
+
(0, solid_js.onCleanup)(() => {
|
|
1848
|
+
clear();
|
|
1849
|
+
el.removeEventListener("mouseleave", onMouseLeave);
|
|
1850
|
+
el.removeEventListener("mouseenter", onMouseEnter);
|
|
1851
|
+
});
|
|
1852
|
+
};
|
|
1853
|
+
//#endregion
|
|
1854
|
+
//#region src/ui/globals/directives/resize.ts
|
|
1855
|
+
/**
|
|
1856
|
+
* Creates a ResizeObserver hook attached to the node content container element,
|
|
1857
|
+
* dispatching RESIZE events to update node dimensions and edge positioning in
|
|
1858
|
+
* real-time.
|
|
1859
|
+
*
|
|
1860
|
+
* @param id - Unique identifier of the flowchart node.
|
|
1861
|
+
*
|
|
1862
|
+
* @returns Ref callback attaching and cleaning up the observer on unmount.
|
|
1863
|
+
*/
|
|
1864
|
+
var resize = (id) => (el) => {
|
|
1865
|
+
const service = useFlow();
|
|
1866
|
+
const resize = new ResizeObserver((entries) => {
|
|
1867
|
+
const entry = entries[0].target;
|
|
1868
|
+
if (!entry) return;
|
|
1869
|
+
const width = entry.clientWidth;
|
|
1870
|
+
const height = entry.clientHeight;
|
|
1871
|
+
if (width > 0 && height > 0) service.send({
|
|
1872
|
+
type: "RESIZE",
|
|
1873
|
+
payload: {
|
|
1874
|
+
id,
|
|
1875
|
+
size: {
|
|
1876
|
+
width,
|
|
1877
|
+
height
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
});
|
|
1881
|
+
});
|
|
1882
|
+
resize.observe(el);
|
|
1883
|
+
return () => {
|
|
1884
|
+
resize.unobserve(el);
|
|
1885
|
+
resize.disconnect();
|
|
1886
|
+
};
|
|
1887
|
+
};
|
|
1888
|
+
//#endregion
|
|
1889
|
+
//#region src/ui/components/EditPanel.hooks.ts
|
|
1890
|
+
/**
|
|
1891
|
+
* Hook providing reactive state and mutation helpers for editing flowchart node
|
|
1892
|
+
* data.
|
|
1893
|
+
*
|
|
1894
|
+
* @template | {@linkcode NodeData} `D` - Custom node data dictionary type extending
|
|
1895
|
+
* {@linkcode NodeData}.
|
|
1896
|
+
*
|
|
1897
|
+
* @param timeout - Transition delay in milliseconds before closing the panel.
|
|
1898
|
+
* Defaults to `270`.
|
|
1899
|
+
*
|
|
1900
|
+
* @returns An object containing reactive accessors and mutation callbacks for the
|
|
1901
|
+
* active node.
|
|
1902
|
+
*
|
|
1903
|
+
* @see {@linkcode useFlow}
|
|
1904
|
+
*/
|
|
1905
|
+
var useHook = (timeout = 270) => {
|
|
1906
|
+
const service = useFlow();
|
|
1907
|
+
const directClose = () => service.send("STOP_EDIT");
|
|
1908
|
+
const [closing, setClosing] = (0, solid_js.createSignal)(false);
|
|
1909
|
+
const senderData = service.sender("SET_NODE_DATA");
|
|
1910
|
+
const _editing = (0, _bemedev_app_solidjs.createState)(service, {
|
|
1911
|
+
selector: ({ context }) => {
|
|
1912
|
+
const editingId = context.editing;
|
|
1913
|
+
if (!(0, _bemedev_app_bemedev.isDefined)(editingId)) return;
|
|
1914
|
+
const item = context.data?.nodes?.find((n) => n.id === editingId);
|
|
1915
|
+
if (!(0, _bemedev_app_bemedev.isDefined)(item)) return;
|
|
1916
|
+
return {
|
|
1917
|
+
id: item.id,
|
|
1918
|
+
data: item.data
|
|
1919
|
+
};
|
|
1920
|
+
},
|
|
1921
|
+
equals: _bemedev_app.deepEqual
|
|
1922
|
+
});
|
|
1923
|
+
const close = () => {
|
|
1924
|
+
setClosing(true);
|
|
1925
|
+
setTimeout(() => {
|
|
1926
|
+
directClose();
|
|
1927
|
+
setClosing(false);
|
|
1928
|
+
}, timeout);
|
|
1929
|
+
};
|
|
1930
|
+
const updateField = (field, value) => {
|
|
1931
|
+
const current = _editing();
|
|
1932
|
+
if (!current) return;
|
|
1933
|
+
return senderData({
|
|
1934
|
+
...current,
|
|
1935
|
+
data: {
|
|
1936
|
+
...current.data,
|
|
1937
|
+
[field]: value
|
|
1938
|
+
}
|
|
1939
|
+
});
|
|
1940
|
+
};
|
|
1941
|
+
const updateData = (data) => {
|
|
1942
|
+
const current = _editing();
|
|
1943
|
+
if (!current) return;
|
|
1944
|
+
return senderData({
|
|
1945
|
+
...current,
|
|
1946
|
+
data: {
|
|
1947
|
+
...current.data,
|
|
1948
|
+
...data
|
|
1949
|
+
}
|
|
1950
|
+
});
|
|
1951
|
+
};
|
|
1952
|
+
return {
|
|
1953
|
+
editing: _editing,
|
|
1954
|
+
updateField,
|
|
1955
|
+
updateData,
|
|
1956
|
+
close,
|
|
1957
|
+
closing,
|
|
1958
|
+
directClose
|
|
1959
|
+
};
|
|
1960
|
+
};
|
|
1961
|
+
//#endregion
|
|
1962
|
+
//#region src/ui/components/EditPanel.tsx
|
|
1963
|
+
var _tmpl$ = [
|
|
1964
|
+
"<div",
|
|
1965
|
+
" class=\"",
|
|
1966
|
+
"\" style=\"",
|
|
1967
|
+
"\"><div class=\"flex flex-col gap-3\"><!--$-->",
|
|
1968
|
+
"<!--/--><!--$-->",
|
|
1969
|
+
"<!--/--></div></div>"
|
|
1970
|
+
];
|
|
1971
|
+
var _tmpl$2 = [
|
|
1972
|
+
"<div",
|
|
1973
|
+
" class=\"flex items-center justify-between border-b border-gray-100 pb-2\"><div class=\"flex items-center gap-2\"><h3 class=\"text-sm font-bold text-gray-800\">Edit</h3><span class=\"font-mono text-[11px] text-gray-400\">",
|
|
1974
|
+
"</span></div><button type=\"button\" title=\"Close editor\" aria-label=\"Close editor\" class=\"cursor-pointer rounded-full p-1 text-gray-400 hover:bg-gray-100 hover:text-gray-700\"><svg class=\"size-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M18 6L6 18M6 6l12 12\"></path></svg></button></div>"
|
|
1975
|
+
];
|
|
1976
|
+
/**
|
|
1977
|
+
* Generic overlay edit panel component for modifying the data of the currently
|
|
1978
|
+
* active/double-clicked flowchart node.
|
|
1979
|
+
*
|
|
1980
|
+
* @template | {@linkcode NodeData} `D` - Custom node data dictionary type extending
|
|
1981
|
+
* {@linkcode NodeData}.
|
|
1982
|
+
*
|
|
1983
|
+
* @param props - Edit panel configuration properties of type
|
|
1984
|
+
* {@linkcode EditPanelProps}.
|
|
1985
|
+
*
|
|
1986
|
+
* @returns The rendered Solid component or `null` when no node is being edited.
|
|
1987
|
+
*
|
|
1988
|
+
* @see {@linkcode useHook}, {@linkcode clickOutside}
|
|
1320
1989
|
*/
|
|
1321
|
-
var
|
|
1322
|
-
|
|
1323
|
-
|
|
1990
|
+
var EditPanel = (props) => {
|
|
1991
|
+
const hooks = useHook(props.timeout);
|
|
1992
|
+
const classList = () => props.classList instanceof Function ? props.classList(hooks) : props.classList;
|
|
1993
|
+
return (0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1994
|
+
get when() {
|
|
1995
|
+
return hooks.editing();
|
|
1996
|
+
},
|
|
1997
|
+
children: (node) => (0, solid_js_web.ssr)(_tmpl$, (0, solid_js_web.ssrHydrationKey)(), `${(0, solid_js_web.escape)(cn(`w-80 cursor-default rounded-2xl border border-gray-200 bg-white/95 p-4 shadow-xl backdrop-blur-md transition-all ${props.class ?? ""}`) || "", true)} ${(0, solid_js_web.escape)((0, solid_js_web.ssrClassList)(classList()) || "", true)}`, (0, solid_js_web.ssrStyle)(props.style), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.Show, {
|
|
1998
|
+
get when() {
|
|
1999
|
+
return props.header;
|
|
2000
|
+
},
|
|
2001
|
+
keyed: true,
|
|
2002
|
+
get fallback() {
|
|
2003
|
+
return (0, solid_js_web.ssr)(_tmpl$2, (0, solid_js_web.ssrHydrationKey)(), (0, solid_js_web.escape)(node().id));
|
|
2004
|
+
},
|
|
2005
|
+
children: (header) => header({
|
|
2006
|
+
id: node().id,
|
|
2007
|
+
close: hooks.close
|
|
2008
|
+
})
|
|
2009
|
+
})), (0, solid_js_web.escape)(props.children(hooks)))
|
|
2010
|
+
});
|
|
2011
|
+
};
|
|
1324
2012
|
//#endregion
|
|
2013
|
+
exports.BOUNDS_CONSTRAINTS = BOUNDS_CONSTRAINTS;
|
|
2014
|
+
exports.CANVAS_FACTOR = CANVAS_FACTOR;
|
|
1325
2015
|
exports.CLASSES = CLASSES;
|
|
2016
|
+
exports.CONTAINER_DIMENSIONS = CONTAINER_DIMENSIONS;
|
|
2017
|
+
exports.DEFAULT_DATA = DEFAULT_DATA;
|
|
2018
|
+
exports.DEFAULT_INPUT_OFFSET = DEFAULT_INPUT_OFFSET;
|
|
2019
|
+
exports.DEFAULT_INPUT_OFFSET_X = DEFAULT_INPUT_OFFSET_X;
|
|
2020
|
+
exports.DEFAULT_INPUT_OFFSET_Y = DEFAULT_INPUT_OFFSET_Y;
|
|
2021
|
+
exports.DEFAULT_NODES = DEFAULT_NODES;
|
|
2022
|
+
exports.DEFAULT_NODE_HEIGHT = DEFAULT_NODE_HEIGHT;
|
|
2023
|
+
exports.DEFAULT_NODE_WIDTH = DEFAULT_NODE_WIDTH;
|
|
2024
|
+
exports.DEFAULT_SIZE = DEFAULT_SIZE;
|
|
2025
|
+
exports.EditPanel = EditPanel;
|
|
1326
2026
|
exports.Flow = Flow;
|
|
2027
|
+
exports.FlowChart = FlowChart;
|
|
2028
|
+
exports.HANDLE_CENTER_X_OFFSET = HANDLE_CENTER_X_OFFSET;
|
|
2029
|
+
exports.HANDLE_CENTER_Y = HANDLE_CENTER_Y;
|
|
2030
|
+
exports.HANDLE_CONTAINER_OFFSET_X = HANDLE_CONTAINER_OFFSET_X;
|
|
2031
|
+
exports.HANDLE_MARGIN_TOP = HANDLE_MARGIN_TOP;
|
|
2032
|
+
exports.HANDLE_RADIUS = HANDLE_RADIUS;
|
|
2033
|
+
exports.HANDLE_SIZE = HANDLE_SIZE;
|
|
2034
|
+
exports.NODE_BORDER_WIDTH = NODE_BORDER_WIDTH;
|
|
2035
|
+
exports.PARENT_CHILD_GAP_WIDTH = PARENT_CHILD_GAP_WIDTH;
|
|
2036
|
+
exports.Panels = Panels;
|
|
2037
|
+
exports.Provider = Provider;
|
|
2038
|
+
exports.SCROLL_MULTIPLIER = SCROLL_MULTIPLIER;
|
|
2039
|
+
exports.TOOLBAR_BUFFER = TOOLBAR_BUFFER;
|
|
2040
|
+
exports.TOOLBAR_TOP_OFFSET = TOOLBAR_TOP_OFFSET;
|
|
2041
|
+
exports.board = board;
|
|
2042
|
+
exports.clamp = clamp;
|
|
2043
|
+
exports.clickOutside = clickOutside;
|
|
2044
|
+
exports.createContext = createContext;
|
|
2045
|
+
exports.data = data;
|
|
2046
|
+
exports.dimension = dimension;
|
|
2047
|
+
exports.edgeJSON = edgeJSON;
|
|
2048
|
+
exports.extremities = extremities;
|
|
2049
|
+
exports.getDefaultOutputOffset = getDefaultOutputOffset;
|
|
2050
|
+
exports.mouseOut = mouseOut;
|
|
2051
|
+
exports.newEdge = newEdge;
|
|
2052
|
+
exports.nodeDataValue = nodeDataValue;
|
|
2053
|
+
exports.nodeJSON = nodeJSON;
|
|
2054
|
+
exports.nodeOffset = nodeOffset;
|
|
2055
|
+
exports.point = point;
|
|
2056
|
+
exports.resize = resize;
|
|
2057
|
+
exports.useFlow = useFlow;
|
|
2058
|
+
exports.vector = vector;
|