@dschz/solid-flow 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index/index.js +4940 -3
- package/dist/index/index.jsx +4448 -185
- package/dist/styles/index.css +592 -1
- package/package.json +3 -7
package/dist/index/index.jsx
CHANGED
|
@@ -1,207 +1,4470 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
// src/components/container/EdgeRenderer.tsx
|
|
2
|
+
import { For as For2 } from "solid-js";
|
|
3
|
+
|
|
4
|
+
// src/components/contexts/edgeId.tsx
|
|
5
|
+
import { createContext, useContext } from "solid-js";
|
|
6
|
+
var EdgeIdContext = createContext();
|
|
7
|
+
function useEdgeId() {
|
|
8
|
+
const ctx = useContext(EdgeIdContext);
|
|
9
|
+
if (!ctx) {
|
|
10
|
+
throw new Error(
|
|
11
|
+
"solid-flow: Your application must be wrapped with <SolidFlow> in order to invoke useEdgeId"
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
return ctx;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// src/components/contexts/flow.tsx
|
|
18
|
+
import { createContext as createContext4, useContext as useContext4 } from "solid-js";
|
|
19
|
+
|
|
20
|
+
// src/data/createSolidFlow.tsx
|
|
21
|
+
import { ReactiveMap } from "@solid-primitives/map";
|
|
22
|
+
import { createMediaQuery } from "@solid-primitives/media";
|
|
23
|
+
import {
|
|
24
|
+
addEdge as systemAddEdge,
|
|
25
|
+
calculateNodePosition,
|
|
26
|
+
clampPosition as clampPosition2,
|
|
27
|
+
fitViewport,
|
|
28
|
+
getEdgePosition,
|
|
29
|
+
getElevatedEdgeZIndex,
|
|
30
|
+
getInternalNodesBounds,
|
|
31
|
+
getNodeDimensions as getNodeDimensions2,
|
|
32
|
+
getNodePositionWithOrigin as getNodePositionWithOrigin2,
|
|
33
|
+
getViewportForBounds,
|
|
34
|
+
infiniteExtent as infiniteExtent3,
|
|
35
|
+
initialConnection,
|
|
36
|
+
isCoordinateExtent as isCoordinateExtent2,
|
|
37
|
+
isEdgeVisible,
|
|
38
|
+
mergeAriaLabelConfig,
|
|
39
|
+
panBy as panBySystem,
|
|
40
|
+
pointToRendererPoint,
|
|
41
|
+
snapPosition,
|
|
42
|
+
updateAbsolutePositions,
|
|
43
|
+
updateNodeInternals as systemUpdateNodeInternals
|
|
44
|
+
} from "@xyflow/system";
|
|
45
|
+
import {
|
|
46
|
+
batch as batch2,
|
|
47
|
+
createComputed,
|
|
48
|
+
createEffect as createEffect4,
|
|
49
|
+
createMemo as createMemo5,
|
|
50
|
+
createSignal as createSignal5,
|
|
51
|
+
mapArray,
|
|
52
|
+
mergeProps as mergeProps8,
|
|
53
|
+
onCleanup as onCleanup2,
|
|
54
|
+
untrack
|
|
55
|
+
} from "solid-js";
|
|
56
|
+
import { produce } from "solid-js/store";
|
|
57
|
+
|
|
58
|
+
// src/components/graph/edge/BaseEdge.tsx
|
|
59
|
+
import clsx2 from "clsx";
|
|
60
|
+
import { mergeProps as mergeProps2, Show as Show2, splitProps as splitProps2 } from "solid-js";
|
|
61
|
+
|
|
62
|
+
// src/components/graph/edge/EdgeLabel.tsx
|
|
63
|
+
import clsx from "clsx";
|
|
64
|
+
import { mergeProps, splitProps } from "solid-js";
|
|
65
|
+
|
|
66
|
+
// src/utils.ts
|
|
67
|
+
import { isEdgeBase, isNodeBase } from "@xyflow/system";
|
|
68
|
+
import { createMemo, createSignal } from "solid-js";
|
|
69
|
+
import { createStore } from "solid-js/store";
|
|
70
|
+
var isNode = (element) => isNodeBase(element);
|
|
71
|
+
var isEdge = (element) => isEdgeBase(element);
|
|
72
|
+
var toPxString = (value) => value === void 0 ? void 0 : `${value}px`;
|
|
73
|
+
var ARROW_KEY_DIFFS = {
|
|
74
|
+
ArrowUp: { x: 0, y: -1 },
|
|
75
|
+
ArrowDown: { x: 0, y: 1 },
|
|
76
|
+
ArrowLeft: { x: -1, y: 0 },
|
|
77
|
+
ArrowRight: { x: 1, y: 0 }
|
|
78
|
+
};
|
|
79
|
+
function createWritable(accessor) {
|
|
80
|
+
const signal = createMemo(() => createSignal(accessor()));
|
|
81
|
+
const get = () => signal()[0]();
|
|
82
|
+
const set = (v) => signal()[1](v);
|
|
83
|
+
return [get, set];
|
|
84
|
+
}
|
|
85
|
+
function createWritableStore(accessor) {
|
|
86
|
+
const storeMemo = createMemo(() => {
|
|
87
|
+
const [get, set] = createStore(accessor());
|
|
88
|
+
return { get, set };
|
|
89
|
+
});
|
|
90
|
+
return {
|
|
91
|
+
get() {
|
|
92
|
+
return storeMemo().get;
|
|
93
|
+
},
|
|
94
|
+
get set() {
|
|
95
|
+
return storeMemo().set;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// src/components/graph/edge/EdgeLabelRenderer.tsx
|
|
101
|
+
import { Show } from "solid-js";
|
|
102
|
+
import { Portal } from "solid-js/web";
|
|
103
|
+
var EdgeLabelRenderer = (props) => {
|
|
104
|
+
const { store } = useInternalSolidFlow();
|
|
105
|
+
const labelNode = () => store.domNode?.querySelector(".solid-flow__edge-labels");
|
|
106
|
+
return <Show when={labelNode()}>{(root) => <Portal mount={root()}>{props.children}</Portal>}</Show>;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// src/components/graph/edge/EdgeLabel.tsx
|
|
110
|
+
var EdgeLabel = (props) => {
|
|
111
|
+
const _props = mergeProps(
|
|
112
|
+
{
|
|
113
|
+
x: 0,
|
|
114
|
+
y: 0,
|
|
115
|
+
selectEdgeOnClick: false,
|
|
116
|
+
transparent: false,
|
|
117
|
+
style: {}
|
|
118
|
+
},
|
|
119
|
+
props
|
|
120
|
+
);
|
|
121
|
+
const [local, rest] = splitProps(_props, [
|
|
122
|
+
"x",
|
|
123
|
+
"y",
|
|
124
|
+
"width",
|
|
125
|
+
"height",
|
|
126
|
+
"selectEdgeOnClick",
|
|
127
|
+
"transparent",
|
|
128
|
+
"children",
|
|
129
|
+
"class",
|
|
130
|
+
"style"
|
|
131
|
+
]);
|
|
132
|
+
const { actions } = useInternalSolidFlow();
|
|
133
|
+
const id = useEdgeId();
|
|
134
|
+
const zIndex = () => actions.getEdge(id())?.zIndex;
|
|
135
|
+
return <EdgeLabelRenderer>
|
|
136
|
+
<div
|
|
137
|
+
role="button"
|
|
138
|
+
tabIndex={-1}
|
|
139
|
+
class={clsx("solid-flow__edge-label", { transparent: local.transparent }, local.class)}
|
|
140
|
+
style={{
|
|
141
|
+
// TODO: Add hideOnSSR
|
|
142
|
+
"pointer-events": "all",
|
|
143
|
+
width: toPxString(local.width),
|
|
144
|
+
height: toPxString(local.height),
|
|
145
|
+
transform: `translate(-50%, -50%) translate(${local.x}px,${local.y}px)`,
|
|
146
|
+
cursor: local.selectEdgeOnClick ? "pointer" : void 0,
|
|
147
|
+
"z-index": zIndex(),
|
|
148
|
+
...local.style
|
|
149
|
+
}}
|
|
150
|
+
onClick={() => {
|
|
151
|
+
if (local.selectEdgeOnClick) actions.handleEdgeSelection(id());
|
|
152
|
+
}}
|
|
153
|
+
{...rest}
|
|
154
|
+
>
|
|
155
|
+
{local.children}
|
|
4
156
|
</div>
|
|
5
|
-
</
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
157
|
+
</EdgeLabelRenderer>;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// src/components/graph/edge/BaseEdge.tsx
|
|
161
|
+
var BaseEdge = (props) => {
|
|
162
|
+
const _props = mergeProps2(
|
|
163
|
+
{
|
|
164
|
+
interactionWidth: 20
|
|
165
|
+
},
|
|
166
|
+
props
|
|
167
|
+
);
|
|
168
|
+
const [local, rest] = splitProps2(_props, [
|
|
169
|
+
"class",
|
|
170
|
+
"style",
|
|
171
|
+
"path",
|
|
172
|
+
"interactionWidth",
|
|
173
|
+
"label",
|
|
174
|
+
"labelStyle",
|
|
175
|
+
"labelX",
|
|
176
|
+
"labelY",
|
|
177
|
+
"markerStart",
|
|
178
|
+
"markerEnd"
|
|
179
|
+
]);
|
|
180
|
+
return <>
|
|
181
|
+
<path
|
|
182
|
+
d={local.path}
|
|
183
|
+
class={clsx2(["solid-flow__edge-path", local.class])}
|
|
184
|
+
marker-start={local.markerStart}
|
|
185
|
+
marker-end={local.markerEnd}
|
|
186
|
+
fill="none"
|
|
187
|
+
style={local.style}
|
|
188
|
+
{...rest}
|
|
189
|
+
/>
|
|
190
|
+
|
|
191
|
+
<Show2 when={local.interactionWidth > 0}>
|
|
192
|
+
<path
|
|
193
|
+
d={local.path}
|
|
194
|
+
stroke-opacity={0}
|
|
195
|
+
stroke-width={local.interactionWidth}
|
|
196
|
+
fill="none"
|
|
197
|
+
class="solid-flow__edge-interaction"
|
|
198
|
+
/>
|
|
199
|
+
</Show2>
|
|
200
|
+
|
|
201
|
+
<Show2 when={local.label}>
|
|
202
|
+
<EdgeLabel x={local.labelX} y={local.labelY} style={local.labelStyle}>
|
|
203
|
+
{local.label}
|
|
204
|
+
</EdgeLabel>
|
|
205
|
+
</Show2>
|
|
206
|
+
</>;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// src/components/graph/edge/BezierEdge.tsx
|
|
210
|
+
import { getBezierPath } from "@xyflow/system";
|
|
211
|
+
var BezierEdge = (props) => {
|
|
212
|
+
const pathData = () => {
|
|
213
|
+
const [path, labelX, labelY] = getBezierPath({
|
|
214
|
+
sourceX: props.sourceX,
|
|
215
|
+
sourceY: props.sourceY,
|
|
216
|
+
targetX: props.targetX,
|
|
217
|
+
targetY: props.targetY,
|
|
218
|
+
sourcePosition: props.sourcePosition,
|
|
219
|
+
targetPosition: props.targetPosition,
|
|
220
|
+
curvature: props.pathOptions?.curvature
|
|
221
|
+
});
|
|
222
|
+
return { path, labelX, labelY };
|
|
223
|
+
};
|
|
224
|
+
return <BaseEdge
|
|
225
|
+
id={props.id}
|
|
226
|
+
path={pathData().path}
|
|
227
|
+
labelX={pathData().labelX}
|
|
228
|
+
labelY={pathData().labelY}
|
|
229
|
+
label={props.label}
|
|
230
|
+
labelStyle={props.labelStyle}
|
|
231
|
+
markerStart={props.markerStart}
|
|
232
|
+
markerEnd={props.markerEnd}
|
|
233
|
+
interactionWidth={props.interactionWidth}
|
|
234
|
+
style={props.style}
|
|
235
|
+
/>;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// src/components/graph/edge/BezierEdgeInternal.tsx
|
|
239
|
+
import { getBezierPath as getBezierPath2 } from "@xyflow/system";
|
|
240
|
+
var BezierEdgeInternal = (props) => {
|
|
241
|
+
const pathData = () => {
|
|
242
|
+
const [path, labelX, labelY] = getBezierPath2({
|
|
243
|
+
sourceX: props.sourceX,
|
|
244
|
+
sourceY: props.sourceY,
|
|
245
|
+
targetX: props.targetX,
|
|
246
|
+
targetY: props.targetY,
|
|
247
|
+
sourcePosition: props.sourcePosition,
|
|
248
|
+
targetPosition: props.targetPosition
|
|
249
|
+
});
|
|
250
|
+
return { path, labelX, labelY };
|
|
251
|
+
};
|
|
252
|
+
return <BaseEdge
|
|
253
|
+
path={pathData().path}
|
|
254
|
+
labelX={pathData().labelX}
|
|
255
|
+
labelY={pathData().labelY}
|
|
256
|
+
label={props.label}
|
|
257
|
+
labelStyle={props.labelStyle}
|
|
258
|
+
markerStart={props.markerStart}
|
|
259
|
+
markerEnd={props.markerEnd}
|
|
260
|
+
interactionWidth={props.interactionWidth}
|
|
261
|
+
style={props.style}
|
|
262
|
+
/>;
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// src/components/graph/edge/EdgeReconnectAnchor.tsx
|
|
266
|
+
import { XYHandle } from "@xyflow/system";
|
|
267
|
+
import clsx3 from "clsx";
|
|
268
|
+
import { createSignal as createSignal2, mergeProps as mergeProps3, Show as Show3, splitProps as splitProps3 } from "solid-js";
|
|
269
|
+
var EdgeReconnectAnchor = (props) => {
|
|
270
|
+
const _props = mergeProps3(
|
|
271
|
+
{
|
|
272
|
+
size: 25,
|
|
273
|
+
reconnecting: false,
|
|
274
|
+
style: {}
|
|
275
|
+
},
|
|
276
|
+
props
|
|
277
|
+
);
|
|
278
|
+
const [local, rest] = splitProps3(_props, [
|
|
279
|
+
"type",
|
|
280
|
+
"class",
|
|
281
|
+
"style",
|
|
282
|
+
"position",
|
|
283
|
+
"size",
|
|
284
|
+
"reconnecting",
|
|
285
|
+
"children"
|
|
286
|
+
]);
|
|
287
|
+
const { store, nodeLookup, edgeLookup, actions } = useInternalSolidFlow();
|
|
288
|
+
const edgeId = useEdgeId();
|
|
289
|
+
const [reconnecting, setReconnecting] = createSignal2(false);
|
|
290
|
+
if (!edgeId()) {
|
|
291
|
+
throw new Error("[solid-flow]: EdgeReconnectAnchor must be used within an Edge component");
|
|
292
|
+
}
|
|
293
|
+
const edge = () => edgeLookup.get(edgeId());
|
|
294
|
+
const onPointerDown = (event) => {
|
|
295
|
+
if (event.button !== 0) {
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
setReconnecting(true);
|
|
299
|
+
store.onReconnectStart?.(event, edge(), local.type);
|
|
300
|
+
const opposite = local.type === "target" ? {
|
|
301
|
+
nodeId: edge().source,
|
|
302
|
+
handleId: edge().sourceHandle ?? null,
|
|
303
|
+
type: "source"
|
|
304
|
+
} : {
|
|
305
|
+
nodeId: edge().target,
|
|
306
|
+
handleId: edge().targetHandle ?? null,
|
|
307
|
+
type: "target"
|
|
308
|
+
};
|
|
309
|
+
XYHandle.onPointerDown(event, {
|
|
310
|
+
lib: store.lib,
|
|
311
|
+
flowId: store.id,
|
|
312
|
+
domNode: store.domNode,
|
|
313
|
+
nodeId: opposite.nodeId,
|
|
314
|
+
handleId: opposite.handleId,
|
|
315
|
+
autoPanOnConnect: store.autoPanOnConnect,
|
|
316
|
+
connectionMode: store.connectionMode,
|
|
317
|
+
connectionRadius: store.connectionRadius,
|
|
318
|
+
nodeLookup,
|
|
319
|
+
isTarget: opposite.type === "target",
|
|
320
|
+
edgeUpdaterType: opposite.type,
|
|
321
|
+
cancelConnection: actions.cancelConnection,
|
|
322
|
+
panBy: actions.panBy,
|
|
323
|
+
updateConnection: actions.setConnection,
|
|
324
|
+
isValidConnection: store.isValidConnection,
|
|
325
|
+
onConnectStart: store.onConnectStart,
|
|
326
|
+
onConnectEnd: store.onConnectEnd,
|
|
327
|
+
onConnect: (connection) => {
|
|
328
|
+
let newEdge = { ...edge(), ...connection };
|
|
329
|
+
newEdge = store.onBeforeReconnect?.(newEdge, edge()) ?? newEdge;
|
|
330
|
+
if (newEdge) {
|
|
331
|
+
actions.setEdges((edges) => edges.map((e) => e.id === edge().id ? newEdge : e));
|
|
332
|
+
}
|
|
333
|
+
store.onReconnect?.(edge(), connection);
|
|
334
|
+
},
|
|
335
|
+
onReconnectEnd: (event2, connectionState) => {
|
|
336
|
+
setReconnecting(false);
|
|
337
|
+
store.onReconnectEnd?.(event2, edge(), opposite.type, connectionState);
|
|
338
|
+
},
|
|
339
|
+
getTransform: () => store.transform,
|
|
340
|
+
getFromHandle: () => store.connection.fromHandle,
|
|
341
|
+
autoPanSpeed: store.autoPanSpeed,
|
|
342
|
+
dragThreshold: store.connectionDragThreshold,
|
|
343
|
+
handleDomNode: event.currentTarget
|
|
344
|
+
});
|
|
345
|
+
};
|
|
346
|
+
return <EdgeLabel x={local.position?.x} y={local.position?.y} style={local.style} {...rest}>
|
|
347
|
+
<div
|
|
348
|
+
onPointerDown={onPointerDown}
|
|
349
|
+
class={clsx3(
|
|
350
|
+
"solid-flow__edgeupdater",
|
|
351
|
+
`solid-flow__edgeupdater-${local.type}`,
|
|
352
|
+
store.noPanClass,
|
|
353
|
+
local.class
|
|
354
|
+
)}
|
|
355
|
+
style={{
|
|
356
|
+
width: toPxString(local.size),
|
|
357
|
+
height: toPxString(local.size),
|
|
358
|
+
background: "transparent",
|
|
359
|
+
border: "none",
|
|
360
|
+
cursor: "move",
|
|
361
|
+
...local.style
|
|
362
|
+
}}
|
|
363
|
+
>
|
|
364
|
+
<Show3 when={!reconnecting()}>{local.children}</Show3>
|
|
20
365
|
</div>
|
|
21
|
-
</
|
|
22
|
-
|
|
23
|
-
|
|
366
|
+
</EdgeLabel>;
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
// src/components/graph/edge/EdgeWrapper.tsx
|
|
370
|
+
import { elementSelectionKeys, getMarkerId } from "@xyflow/system";
|
|
371
|
+
import clsx4 from "clsx";
|
|
372
|
+
import { Show as Show5 } from "solid-js";
|
|
373
|
+
import { Dynamic } from "solid-js/web";
|
|
374
|
+
|
|
375
|
+
// src/components/accessibility/A11yDescriptions.tsx
|
|
376
|
+
import { Show as Show4 } from "solid-js";
|
|
377
|
+
|
|
378
|
+
// src/components/accessibility/constants.ts
|
|
379
|
+
var ARIA_NODE_DESC_KEY = "solid-flow__node-desc";
|
|
380
|
+
var ARIA_EDGE_DESC_KEY = "solid-flow__edge-desc";
|
|
381
|
+
var ARIA_LIVE_MESSAGE = "solid-flow__aria-live";
|
|
382
|
+
|
|
383
|
+
// src/components/accessibility/A11yDescriptions.tsx
|
|
384
|
+
var A11yDescriptions = () => {
|
|
385
|
+
const { store } = useInternalSolidFlow();
|
|
386
|
+
return <>
|
|
387
|
+
<div id={`${ARIA_NODE_DESC_KEY}-${store.id}`} class="a11y-hidden">
|
|
388
|
+
{store.disableKeyboardA11y ? store.ariaLabelConfig["node.a11yDescription.default"] : store.ariaLabelConfig["node.a11yDescription.keyboardDisabled"]}
|
|
24
389
|
</div>
|
|
25
|
-
<div id={`${
|
|
26
|
-
{
|
|
390
|
+
<div id={`${ARIA_EDGE_DESC_KEY}-${store.id}`} class="a11y-hidden">
|
|
391
|
+
{store.ariaLabelConfig["edge.a11yDescription.default"]}
|
|
27
392
|
</div>
|
|
28
393
|
|
|
29
|
-
<
|
|
30
|
-
<div
|
|
31
|
-
|
|
394
|
+
<Show4 when={!store.disableKeyboardA11y}>
|
|
395
|
+
<div
|
|
396
|
+
id={`${ARIA_LIVE_MESSAGE}-${store.id}`}
|
|
397
|
+
aria-live="assertive"
|
|
398
|
+
aria-atomic="true"
|
|
399
|
+
class="a11y-live-msg"
|
|
400
|
+
>
|
|
401
|
+
{store.ariaLiveMessage}
|
|
32
402
|
</div>
|
|
33
|
-
</
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
403
|
+
</Show4>
|
|
404
|
+
</>;
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
// src/components/graph/edge/EdgeWrapper.tsx
|
|
408
|
+
var EdgeWrapper = (props) => {
|
|
409
|
+
let edgeRef;
|
|
410
|
+
const { store, actions } = useInternalSolidFlow();
|
|
411
|
+
const edgeId = () => props.edgeId;
|
|
412
|
+
const edge = () => actions.getEdge(edgeId());
|
|
413
|
+
const edgeType = () => edge().type ?? "default";
|
|
414
|
+
const selectable = () => edge().selectable ?? store.elementsSelectable;
|
|
415
|
+
const focusable = () => edge().focusable ?? store.edgesFocusable;
|
|
416
|
+
const edgeComponent = () => store.edgeTypes[edgeType()];
|
|
417
|
+
const markerStartUrl = () => edge().markerStart ? `url('#${getMarkerId(edge().markerStart, store.id)}')` : void 0;
|
|
418
|
+
const markerEndUrl = () => edge().markerEnd ? `url('#${getMarkerId(edge().markerEnd, store.id)}')` : void 0;
|
|
419
|
+
const onClick = (event) => {
|
|
420
|
+
if (selectable()) {
|
|
421
|
+
actions.handleEdgeSelection(edgeId());
|
|
422
|
+
}
|
|
423
|
+
props.onEdgeClick?.({ edge: edge(), event });
|
|
424
|
+
};
|
|
425
|
+
const onPointerEvent = (event, type) => {
|
|
426
|
+
const handlers = {
|
|
427
|
+
contextmenu: props.onEdgeContextMenu,
|
|
428
|
+
pointerenter: props.onEdgePointerEnter,
|
|
429
|
+
pointerleave: props.onEdgePointerLeave
|
|
430
|
+
};
|
|
431
|
+
handlers[type]?.({ edge: edge(), event });
|
|
432
|
+
};
|
|
433
|
+
const onKeyDown = (event) => {
|
|
434
|
+
if (store.disableKeyboardA11y || !elementSelectionKeys.includes(event.key) || !selectable()) {
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
const unselect = event.key === "Escape";
|
|
438
|
+
if (unselect) {
|
|
439
|
+
edgeRef?.blur();
|
|
440
|
+
actions.unselectNodesAndEdges({ edges: [edge()] });
|
|
441
|
+
} else {
|
|
442
|
+
actions.addSelectedEdges([edge().id]);
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
const ariaLabel = () => edge().ariaLabel ?? `Edge from ${edge().source} to ${edge().target}`;
|
|
446
|
+
return <EdgeIdContext.Provider value={edgeId}>
|
|
447
|
+
<Show5 when={!edge().hidden}>
|
|
448
|
+
<svg class="solid-flow__edge-wrapper" style={{ "z-index": edge().zIndex }}>
|
|
449
|
+
<g
|
|
450
|
+
ref={edgeRef}
|
|
451
|
+
data-id={edge().id}
|
|
452
|
+
tabIndex={focusable() ? 0 : void 0}
|
|
453
|
+
role={edge().ariaRole ?? (focusable() ? "group" : "img")}
|
|
454
|
+
aria-label={ariaLabel()}
|
|
455
|
+
aria-roledescription="edge"
|
|
456
|
+
aria-describedby={focusable() ? `${ARIA_EDGE_DESC_KEY}-${store.id}` : void 0}
|
|
457
|
+
class={clsx4(
|
|
458
|
+
"solid-flow__edge",
|
|
459
|
+
`solid-flow__edge-${edgeType()}`,
|
|
460
|
+
{
|
|
461
|
+
animated: edge().animated,
|
|
462
|
+
selected: edge().selected,
|
|
463
|
+
selectable: selectable()
|
|
464
|
+
},
|
|
465
|
+
edge().class
|
|
466
|
+
)}
|
|
467
|
+
onClick={onClick}
|
|
468
|
+
onKeyDown={(e) => focusable() && onKeyDown(e)}
|
|
469
|
+
onContextMenu={(e) => onPointerEvent(e, "contextmenu")}
|
|
470
|
+
onPointerEnter={(e) => onPointerEvent(e, "pointerenter")}
|
|
471
|
+
onPointerLeave={(e) => onPointerEvent(e, "pointerleave")}
|
|
472
|
+
{...edge().domAttributes}
|
|
473
|
+
>
|
|
474
|
+
<Dynamic
|
|
475
|
+
component={edgeComponent()}
|
|
476
|
+
id={edge().id}
|
|
477
|
+
source={edge().source}
|
|
478
|
+
target={edge().target}
|
|
479
|
+
sourceX={edge().sourceX}
|
|
480
|
+
sourceY={edge().sourceY}
|
|
481
|
+
targetX={edge().targetX}
|
|
482
|
+
targetY={edge().targetY}
|
|
483
|
+
sourcePosition={edge().sourcePosition}
|
|
484
|
+
targetPosition={edge().targetPosition}
|
|
485
|
+
animated={edge().animated}
|
|
486
|
+
selected={edge().selected}
|
|
487
|
+
label={edge().label}
|
|
488
|
+
labelStyle={edge().labelStyle}
|
|
489
|
+
data={edge().data}
|
|
490
|
+
style={edge().style}
|
|
491
|
+
interactionWidth={edge().interactionWidth}
|
|
492
|
+
selectable={selectable()}
|
|
493
|
+
deletable={edge().deletable ?? true}
|
|
494
|
+
type={edgeType()}
|
|
495
|
+
sourceHandleId={edge().sourceHandle}
|
|
496
|
+
targetHandleId={edge().targetHandle}
|
|
497
|
+
markerStart={markerStartUrl()}
|
|
498
|
+
markerEnd={markerEndUrl()}
|
|
499
|
+
/>
|
|
39
500
|
</g>
|
|
40
501
|
</svg>
|
|
41
|
-
</
|
|
42
|
-
</
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
502
|
+
</Show5>
|
|
503
|
+
</EdgeIdContext.Provider>;
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
// src/components/graph/edge/SmoothStepEdge.tsx
|
|
507
|
+
import { getSmoothStepPath } from "@xyflow/system";
|
|
508
|
+
import { createMemo as createMemo2 } from "solid-js";
|
|
509
|
+
var SmoothStepEdge = (props) => {
|
|
510
|
+
const pathData = createMemo2(() => {
|
|
511
|
+
const [path, labelX, labelY] = getSmoothStepPath({
|
|
512
|
+
sourceX: props.sourceX,
|
|
513
|
+
sourceY: props.sourceY,
|
|
514
|
+
targetX: props.targetX,
|
|
515
|
+
targetY: props.targetY,
|
|
516
|
+
sourcePosition: props.sourcePosition,
|
|
517
|
+
targetPosition: props.targetPosition,
|
|
518
|
+
borderRadius: props.pathOptions?.borderRadius,
|
|
519
|
+
offset: props.pathOptions?.offset
|
|
520
|
+
});
|
|
521
|
+
return { path, labelX, labelY };
|
|
522
|
+
});
|
|
523
|
+
return <BaseEdge
|
|
524
|
+
id={props.id}
|
|
525
|
+
path={pathData().path}
|
|
526
|
+
labelX={pathData().labelX}
|
|
527
|
+
labelY={pathData().labelY}
|
|
528
|
+
label={props.label}
|
|
529
|
+
labelStyle={props.labelStyle}
|
|
530
|
+
markerStart={props.markerStart}
|
|
531
|
+
markerEnd={props.markerEnd}
|
|
532
|
+
interactionWidth={props.interactionWidth}
|
|
533
|
+
style={props.style}
|
|
534
|
+
/>;
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
// src/components/graph/edge/SmoothStepEdgeInternal.tsx
|
|
538
|
+
import { getSmoothStepPath as getSmoothStepPath2 } from "@xyflow/system";
|
|
539
|
+
var SmoothStepEdgeInternal = (props) => {
|
|
540
|
+
const pathData = () => {
|
|
541
|
+
const [path, labelX, labelY] = getSmoothStepPath2({
|
|
542
|
+
sourceX: props.sourceX,
|
|
543
|
+
sourceY: props.sourceY,
|
|
544
|
+
targetX: props.targetX,
|
|
545
|
+
targetY: props.targetY,
|
|
546
|
+
sourcePosition: props.sourcePosition,
|
|
547
|
+
targetPosition: props.targetPosition
|
|
548
|
+
});
|
|
549
|
+
return { path, labelX, labelY };
|
|
550
|
+
};
|
|
551
|
+
return <BaseEdge
|
|
552
|
+
path={pathData().path}
|
|
553
|
+
labelX={pathData().labelX}
|
|
554
|
+
labelY={pathData().labelY}
|
|
555
|
+
label={props.label}
|
|
556
|
+
labelStyle={props.labelStyle}
|
|
557
|
+
markerStart={props.markerStart}
|
|
558
|
+
markerEnd={props.markerEnd}
|
|
559
|
+
interactionWidth={props.interactionWidth}
|
|
560
|
+
style={props.style}
|
|
561
|
+
/>;
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
// src/components/graph/edge/StepEdge.tsx
|
|
565
|
+
import { getSmoothStepPath as getSmoothStepPath3 } from "@xyflow/system";
|
|
566
|
+
import { createMemo as createMemo3 } from "solid-js";
|
|
567
|
+
var StepEdge = (props) => {
|
|
568
|
+
const pathData = createMemo3(() => {
|
|
569
|
+
const [path, labelX, labelY] = getSmoothStepPath3({
|
|
570
|
+
sourceX: props.sourceX,
|
|
571
|
+
sourceY: props.sourceY,
|
|
572
|
+
targetX: props.targetX,
|
|
573
|
+
targetY: props.targetY,
|
|
574
|
+
sourcePosition: props.sourcePosition,
|
|
575
|
+
targetPosition: props.targetPosition,
|
|
576
|
+
borderRadius: 0,
|
|
577
|
+
offset: props.pathOptions?.offset
|
|
578
|
+
});
|
|
579
|
+
return { path, labelX, labelY };
|
|
580
|
+
});
|
|
581
|
+
return <BaseEdge
|
|
582
|
+
id={props.id}
|
|
583
|
+
path={pathData().path}
|
|
584
|
+
labelX={pathData().labelX}
|
|
585
|
+
labelY={pathData().labelY}
|
|
586
|
+
label={props.label}
|
|
587
|
+
labelStyle={props.labelStyle}
|
|
588
|
+
markerStart={props.markerStart}
|
|
589
|
+
markerEnd={props.markerEnd}
|
|
590
|
+
interactionWidth={props.interactionWidth}
|
|
591
|
+
style={props.style}
|
|
592
|
+
/>;
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
// src/components/graph/edge/StepEdgeInternal.tsx
|
|
596
|
+
import { getSmoothStepPath as getSmoothStepPath4 } from "@xyflow/system";
|
|
597
|
+
var StepEdgeInternal = (props) => {
|
|
598
|
+
const pathData = () => {
|
|
599
|
+
const [path, labelX, labelY] = getSmoothStepPath4({
|
|
600
|
+
sourceX: props.sourceX,
|
|
601
|
+
sourceY: props.sourceY,
|
|
602
|
+
targetX: props.targetX,
|
|
603
|
+
targetY: props.targetY,
|
|
604
|
+
sourcePosition: props.sourcePosition,
|
|
605
|
+
targetPosition: props.targetPosition,
|
|
606
|
+
borderRadius: 0
|
|
607
|
+
});
|
|
608
|
+
return { path, labelX, labelY };
|
|
609
|
+
};
|
|
610
|
+
return <BaseEdge
|
|
611
|
+
path={pathData().path}
|
|
612
|
+
labelX={pathData().labelX}
|
|
613
|
+
labelY={pathData().labelY}
|
|
614
|
+
label={props.label}
|
|
615
|
+
labelStyle={props.labelStyle}
|
|
616
|
+
markerStart={props.markerStart}
|
|
617
|
+
markerEnd={props.markerEnd}
|
|
618
|
+
interactionWidth={props.interactionWidth}
|
|
619
|
+
style={props.style}
|
|
620
|
+
/>;
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
// src/components/graph/edge/StraightEdge.tsx
|
|
624
|
+
import { getStraightPath } from "@xyflow/system";
|
|
625
|
+
import { createMemo as createMemo4 } from "solid-js";
|
|
626
|
+
var StraightEdge = (props) => {
|
|
627
|
+
const pathData = createMemo4(() => {
|
|
628
|
+
const [path, labelX, labelY] = getStraightPath({
|
|
629
|
+
sourceX: props.sourceX,
|
|
630
|
+
sourceY: props.sourceY,
|
|
631
|
+
targetX: props.targetX,
|
|
632
|
+
targetY: props.targetY
|
|
633
|
+
});
|
|
634
|
+
return { path, labelX, labelY };
|
|
635
|
+
});
|
|
636
|
+
return <BaseEdge
|
|
637
|
+
id={props.id}
|
|
638
|
+
path={pathData().path}
|
|
639
|
+
labelX={pathData().labelX}
|
|
640
|
+
labelY={pathData().labelY}
|
|
641
|
+
label={props.label}
|
|
642
|
+
labelStyle={props.labelStyle}
|
|
643
|
+
markerStart={props.markerStart}
|
|
644
|
+
markerEnd={props.markerEnd}
|
|
645
|
+
interactionWidth={props.interactionWidth}
|
|
646
|
+
style={props.style}
|
|
647
|
+
/>;
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
// src/components/graph/edge/StraightEdgeInternal.tsx
|
|
651
|
+
import { getStraightPath as getStraightPath2 } from "@xyflow/system";
|
|
652
|
+
var StraightEdgeInternal = (props) => {
|
|
653
|
+
const pathData = () => {
|
|
654
|
+
const [path, labelX, labelY] = getStraightPath2({
|
|
655
|
+
sourceX: props.sourceX,
|
|
656
|
+
sourceY: props.sourceY,
|
|
657
|
+
targetX: props.targetX,
|
|
658
|
+
targetY: props.targetY
|
|
659
|
+
});
|
|
660
|
+
return { path, labelX, labelY };
|
|
661
|
+
};
|
|
662
|
+
return <BaseEdge
|
|
663
|
+
path={pathData().path}
|
|
664
|
+
labelX={pathData().labelX}
|
|
665
|
+
labelY={pathData().labelY}
|
|
666
|
+
label={props.label}
|
|
667
|
+
labelStyle={props.labelStyle}
|
|
668
|
+
markerStart={props.markerStart}
|
|
669
|
+
markerEnd={props.markerEnd}
|
|
670
|
+
interactionWidth={props.interactionWidth}
|
|
671
|
+
style={props.style}
|
|
672
|
+
/>;
|
|
673
|
+
};
|
|
674
|
+
|
|
675
|
+
// src/components/graph/node/DefaultNode.tsx
|
|
676
|
+
import { mergeProps as mergeProps5 } from "solid-js";
|
|
677
|
+
|
|
678
|
+
// src/components/graph/handle/Handle.tsx
|
|
679
|
+
import {
|
|
680
|
+
areConnectionMapsEqual,
|
|
681
|
+
getHostForElement,
|
|
682
|
+
handleConnectionChange,
|
|
683
|
+
XYHandle as XYHandle2
|
|
684
|
+
} from "@xyflow/system";
|
|
685
|
+
import clsx5 from "clsx";
|
|
686
|
+
import { createEffect, mergeProps as mergeProps4, splitProps as splitProps4 } from "solid-js";
|
|
687
|
+
import { unwrap } from "solid-js/store";
|
|
688
|
+
|
|
689
|
+
// src/data/utils.ts
|
|
690
|
+
import {
|
|
691
|
+
getNodesInside
|
|
692
|
+
} from "@xyflow/system";
|
|
693
|
+
var getEdgeId = (connection) => {
|
|
694
|
+
const { source, sourceHandle, target, targetHandle } = connection;
|
|
695
|
+
return `xy-edge__${source}${sourceHandle || ""}-${target}${targetHandle || ""}`;
|
|
696
|
+
};
|
|
697
|
+
|
|
698
|
+
// src/components/contexts/nodeConnectable.tsx
|
|
699
|
+
import { createContext as createContext2, useContext as useContext2 } from "solid-js";
|
|
700
|
+
var NodeConnectableContext = createContext2();
|
|
701
|
+
function useNodeConnectable() {
|
|
702
|
+
const ctx = useContext2(NodeConnectableContext);
|
|
703
|
+
if (!ctx) {
|
|
704
|
+
throw new Error(
|
|
705
|
+
"solid-flow: Your application must be wrapped with <SolidFlow> in order to invoke useNodeConnectable"
|
|
706
|
+
);
|
|
707
|
+
}
|
|
708
|
+
return ctx;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// src/components/graph/handle/Handle.tsx
|
|
712
|
+
var Handle = (props) => {
|
|
713
|
+
const _props = mergeProps4(
|
|
714
|
+
{
|
|
715
|
+
id: null,
|
|
716
|
+
type: "source",
|
|
717
|
+
position: "top",
|
|
718
|
+
isConnectableStart: true,
|
|
719
|
+
isConnectableEnd: true
|
|
720
|
+
},
|
|
721
|
+
props
|
|
722
|
+
);
|
|
723
|
+
const { store, nodeLookup, connectionLookup, actions } = useInternalSolidFlow();
|
|
724
|
+
const [local, rest] = splitProps4(_props, [
|
|
725
|
+
"id",
|
|
726
|
+
"type",
|
|
727
|
+
"position",
|
|
728
|
+
"isConnectable",
|
|
729
|
+
"isConnectableStart",
|
|
730
|
+
"isConnectableEnd",
|
|
731
|
+
"isValidConnection",
|
|
732
|
+
"onConnect",
|
|
733
|
+
"onDisconnect",
|
|
734
|
+
"children",
|
|
735
|
+
"class",
|
|
736
|
+
"style"
|
|
737
|
+
]);
|
|
738
|
+
const nodeId = useNodeId();
|
|
739
|
+
const nodeConnectable = useNodeConnectable();
|
|
740
|
+
const connectable = () => local.isConnectable ?? nodeConnectable();
|
|
741
|
+
const isTarget = () => local.type === "target";
|
|
742
|
+
const handleId = () => local.id ?? null;
|
|
743
|
+
const connectionInProcess = () => Boolean(store.connection.fromHandle);
|
|
744
|
+
const connectingFrom = () => store.connection.fromHandle && store.connection.fromHandle.nodeId === nodeId() && store.connection.fromHandle.type === local.type && store.connection.fromHandle.id === handleId();
|
|
745
|
+
const connectingTo = () => store.connection.toHandle && store.connection.toHandle.nodeId === nodeId() && store.connection.toHandle.type === local.type && store.connection.toHandle.id === handleId();
|
|
746
|
+
const isPossibleTargetHandle = () => store.connectionMode === "strict" ? store.connection.fromHandle?.type !== local.type : nodeId() !== store.connection.fromHandle?.nodeId || handleId() !== store.connection.fromHandle?.id;
|
|
747
|
+
const valid = () => Boolean(connectingTo() && store.connection.isValid);
|
|
748
|
+
let prevConnections = null;
|
|
749
|
+
let connections;
|
|
750
|
+
createEffect(() => {
|
|
751
|
+
if (!local.onConnect && !local.onDisconnect) return;
|
|
752
|
+
const conectionKey = `${nodeId()}-${local.type}${local.id ? `-${local.id}` : ""}`;
|
|
753
|
+
connections = connectionLookup.get(conectionKey);
|
|
754
|
+
if (prevConnections && !areConnectionMapsEqual(connections, prevConnections)) {
|
|
755
|
+
const _connections = connections ?? /* @__PURE__ */ new Map();
|
|
756
|
+
handleConnectionChange(prevConnections, _connections, props.onDisconnect);
|
|
757
|
+
handleConnectionChange(_connections, prevConnections, props.onConnect);
|
|
758
|
+
}
|
|
759
|
+
prevConnections = connections ?? /* @__PURE__ */ new Map();
|
|
760
|
+
});
|
|
761
|
+
const onConnectExtended = (connection) => {
|
|
762
|
+
const handleConnection = {
|
|
763
|
+
...connection,
|
|
764
|
+
id: getEdgeId(connection)
|
|
765
|
+
};
|
|
766
|
+
const edge = store.onBeforeConnect?.(handleConnection) ?? handleConnection;
|
|
767
|
+
actions.addEdge(edge);
|
|
768
|
+
store.onConnect?.(handleConnection);
|
|
769
|
+
};
|
|
770
|
+
const onPointerDown = (event) => {
|
|
771
|
+
XYHandle2.onPointerDown(event, {
|
|
772
|
+
handleId: handleId(),
|
|
773
|
+
nodeId: nodeId(),
|
|
774
|
+
isTarget: isTarget(),
|
|
775
|
+
connectionRadius: store.connectionRadius,
|
|
776
|
+
domNode: store.domNode,
|
|
777
|
+
nodeLookup,
|
|
778
|
+
connectionMode: store.connectionMode,
|
|
779
|
+
lib: store.lib,
|
|
780
|
+
autoPanOnConnect: store.autoPanOnConnect,
|
|
781
|
+
flowId: store.id,
|
|
782
|
+
isValidConnection: local.isValidConnection ?? store.isValidConnection,
|
|
783
|
+
updateConnection: actions.setConnection,
|
|
784
|
+
cancelConnection: actions.cancelConnection,
|
|
785
|
+
panBy: actions.panBy,
|
|
786
|
+
onConnect: onConnectExtended,
|
|
787
|
+
onConnectStart: (event2, startParams) => {
|
|
788
|
+
store.onConnectStart?.(event2, {
|
|
789
|
+
nodeId: startParams.nodeId,
|
|
790
|
+
handleId: startParams.handleId,
|
|
791
|
+
handleType: startParams.handleType
|
|
792
|
+
});
|
|
793
|
+
},
|
|
794
|
+
onConnectEnd: store.onConnectEnd,
|
|
795
|
+
getTransform: () => store.transform,
|
|
796
|
+
getFromHandle: () => store.connection.fromHandle,
|
|
797
|
+
autoPanSpeed: store.autoPanSpeed,
|
|
798
|
+
dragThreshold: store.connectionDragThreshold,
|
|
799
|
+
handleDomNode: event.currentTarget
|
|
800
|
+
});
|
|
801
|
+
};
|
|
802
|
+
const onClick = (event) => {
|
|
803
|
+
if (!nodeId() || !store.clickConnectStartHandle && !local.isConnectableStart) {
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
if (!store.clickConnectStartHandle) {
|
|
807
|
+
store.onClickConnectStart?.(event, {
|
|
808
|
+
nodeId: nodeId(),
|
|
809
|
+
handleId: handleId(),
|
|
810
|
+
handleType: local.type
|
|
811
|
+
});
|
|
812
|
+
actions.setClickConnectStartHandle({ nodeId: nodeId(), type: local.type, id: handleId() });
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
const doc = getHostForElement(event.target);
|
|
816
|
+
const isValidConnectionHandler = local.isValidConnection ?? store.isValidConnection;
|
|
817
|
+
const { connection, isValid } = XYHandle2.isValid(event, {
|
|
818
|
+
handle: {
|
|
819
|
+
nodeId: nodeId(),
|
|
820
|
+
id: handleId(),
|
|
821
|
+
type: local.type
|
|
822
|
+
},
|
|
823
|
+
connectionMode: store.connectionMode,
|
|
824
|
+
fromNodeId: store.clickConnectStartHandle.nodeId,
|
|
825
|
+
fromHandleId: store.clickConnectStartHandle.id ?? null,
|
|
826
|
+
fromType: store.clickConnectStartHandle.type,
|
|
827
|
+
isValidConnection: isValidConnectionHandler,
|
|
828
|
+
flowId: store.id,
|
|
829
|
+
doc,
|
|
830
|
+
lib: store.lib,
|
|
831
|
+
nodeLookup
|
|
832
|
+
});
|
|
833
|
+
if (isValid && connection) {
|
|
834
|
+
onConnectExtended(connection);
|
|
835
|
+
}
|
|
836
|
+
const connectionClone = structuredClone(unwrap(store.connection));
|
|
837
|
+
delete connectionClone.inProgress;
|
|
838
|
+
connectionClone.toPosition = connectionClone.toHandle ? connectionClone.toHandle.position : null;
|
|
839
|
+
store.onClickConnectEnd?.(event, connectionClone);
|
|
840
|
+
actions.setClickConnectStartHandle(void 0);
|
|
841
|
+
};
|
|
842
|
+
const connectionIndicator = () => connectable() && (!connectionInProcess() || isPossibleTargetHandle()) && (connectionInProcess() || store.clickConnectStartHandle ? local.isConnectableEnd : local.isConnectableStart);
|
|
843
|
+
return <div
|
|
844
|
+
role="button"
|
|
845
|
+
aria-label={store.ariaLabelConfig[`handle.ariaLabel`]}
|
|
846
|
+
tabIndex={-1}
|
|
847
|
+
data-handleid={handleId()}
|
|
848
|
+
data-nodeid={nodeId()}
|
|
849
|
+
data-handlepos={local.position}
|
|
850
|
+
data-id={`${store.id}-${nodeId()}-${local.id || null}-${local.type}`}
|
|
851
|
+
onClick={store.clickConnect ? onClick : void 0}
|
|
852
|
+
onPointerDown={onPointerDown}
|
|
853
|
+
style={local.style}
|
|
854
|
+
class={clsx5(
|
|
855
|
+
"solid-flow__handle",
|
|
856
|
+
`solid-flow__handle-${local.position}`,
|
|
857
|
+
store.noDragClass,
|
|
858
|
+
store.noPanClass,
|
|
859
|
+
local.class,
|
|
860
|
+
{
|
|
861
|
+
valid: valid(),
|
|
862
|
+
connectingto: connectingTo(),
|
|
863
|
+
connectingfrom: connectingFrom(),
|
|
864
|
+
source: !isTarget(),
|
|
865
|
+
target: isTarget(),
|
|
866
|
+
connectablestart: _props.isConnectableStart,
|
|
867
|
+
connectableend: _props.isConnectableEnd,
|
|
868
|
+
connectable: connectable(),
|
|
869
|
+
connectionindicator: connectionIndicator()
|
|
870
|
+
}
|
|
871
|
+
)}
|
|
872
|
+
{...rest}
|
|
873
|
+
>
|
|
874
|
+
{local.children}
|
|
875
|
+
</div>;
|
|
876
|
+
};
|
|
877
|
+
|
|
878
|
+
// src/components/graph/node/DefaultNode.tsx
|
|
879
|
+
var DefaultNode = (props) => {
|
|
880
|
+
const _props = mergeProps5(
|
|
881
|
+
{
|
|
882
|
+
targetPosition: "top",
|
|
883
|
+
sourcePosition: "bottom"
|
|
884
|
+
},
|
|
885
|
+
props
|
|
886
|
+
);
|
|
887
|
+
return <>
|
|
888
|
+
<Handle type="target" position={_props.targetPosition} isConnectable={_props.isConnectable} />
|
|
889
|
+
{props.data.label}
|
|
890
|
+
<Handle type="source" position={_props.sourcePosition} isConnectable={_props.isConnectable} />
|
|
891
|
+
</>;
|
|
892
|
+
};
|
|
893
|
+
|
|
894
|
+
// src/components/graph/node/GroupNode.tsx
|
|
895
|
+
var GroupNode = (props) => <div
|
|
896
|
+
style={{
|
|
897
|
+
position: "absolute",
|
|
898
|
+
left: 0,
|
|
899
|
+
top: 0,
|
|
900
|
+
width: toPxString(props.width),
|
|
901
|
+
height: toPxString(props.height)
|
|
902
|
+
}}
|
|
903
|
+
/>;
|
|
904
|
+
|
|
905
|
+
// src/components/graph/node/InputNode.tsx
|
|
906
|
+
import { mergeProps as mergeProps6 } from "solid-js";
|
|
907
|
+
var InputNode = (props) => {
|
|
908
|
+
const _props = mergeProps6(
|
|
909
|
+
{
|
|
910
|
+
sourcePosition: "bottom"
|
|
911
|
+
},
|
|
912
|
+
props
|
|
913
|
+
);
|
|
914
|
+
return <>
|
|
915
|
+
{props.data?.label}
|
|
916
|
+
<Handle type="source" position={_props.sourcePosition} isConnectable={_props.isConnectable} />
|
|
917
|
+
</>;
|
|
918
|
+
};
|
|
919
|
+
|
|
920
|
+
// src/components/graph/node/NodeWrapper.tsx
|
|
921
|
+
import {
|
|
922
|
+
elementSelectionKeys as elementSelectionKeys2,
|
|
923
|
+
getNodesInside as getNodesInside2,
|
|
924
|
+
isInputDOMNode,
|
|
925
|
+
nodeHasDimensions
|
|
926
|
+
} from "@xyflow/system";
|
|
927
|
+
import clsx6 from "clsx";
|
|
928
|
+
import { batch, createEffect as createEffect3, createSignal as createSignal4, Show as Show6 } from "solid-js";
|
|
929
|
+
import { Dynamic as Dynamic2 } from "solid-js/web";
|
|
930
|
+
|
|
931
|
+
// src/actions/createDraggable.tsx
|
|
932
|
+
import { XYDrag } from "@xyflow/system";
|
|
933
|
+
import { createEffect as createEffect2, createSignal as createSignal3, onCleanup, onMount } from "solid-js";
|
|
934
|
+
var createDraggable = (elem, params) => {
|
|
935
|
+
const { store, nodeLookup, actions } = useInternalSolidFlow();
|
|
936
|
+
const [dragging, setDragging] = createSignal3(false);
|
|
937
|
+
onMount(() => {
|
|
938
|
+
const { onDrag, onDragStart, onDragStop, onNodeMouseDown } = params();
|
|
939
|
+
const dragInstance = XYDrag({
|
|
940
|
+
onDrag,
|
|
941
|
+
onDragStart: (event, dragItems, node, nodes) => {
|
|
942
|
+
setDragging(true);
|
|
943
|
+
onDragStart?.(event, dragItems, node, nodes);
|
|
944
|
+
},
|
|
945
|
+
onDragStop: (event, dragItems, node, nodes) => {
|
|
946
|
+
setDragging(false);
|
|
947
|
+
onDragStop?.(event, dragItems, node, nodes);
|
|
948
|
+
},
|
|
949
|
+
onNodeMouseDown,
|
|
950
|
+
getStoreItems: () => {
|
|
951
|
+
return {
|
|
952
|
+
nodes: store.nodes,
|
|
953
|
+
nodeLookup,
|
|
954
|
+
edges: store.edges,
|
|
955
|
+
nodeExtent: store.nodeExtent,
|
|
956
|
+
snapGrid: store.snapGrid ?? [0, 0],
|
|
957
|
+
snapToGrid: !!store.snapGrid,
|
|
958
|
+
autoPanSpeed: store.autoPanSpeed,
|
|
959
|
+
nodeOrigin: store.nodeOrigin,
|
|
960
|
+
multiSelectionActive: store.multiselectionKeyPressed,
|
|
961
|
+
domNode: store.domNode,
|
|
962
|
+
transform: store.transform,
|
|
963
|
+
autoPanOnNodeDrag: store.autoPanOnNodeDrag,
|
|
964
|
+
nodesDraggable: store.nodesDraggable,
|
|
965
|
+
selectNodesOnDrag: store.selectNodesOnDrag,
|
|
966
|
+
nodeDragThreshold: store.nodeDragThreshold,
|
|
967
|
+
unselectNodesAndEdges: actions.unselectNodesAndEdges,
|
|
968
|
+
updateNodePositions: actions.updateNodePositions,
|
|
969
|
+
panBy: actions.panBy
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
});
|
|
973
|
+
function updateDrag(elem2, params2) {
|
|
974
|
+
if (params2.disabled) {
|
|
975
|
+
dragInstance.destroy();
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
dragInstance.update({
|
|
979
|
+
domNode: elem2,
|
|
980
|
+
nodeId: params2.nodeId,
|
|
981
|
+
noDragClassName: params2.noDragClass,
|
|
982
|
+
handleSelector: params2.handleSelector,
|
|
983
|
+
isSelectable: params2.isSelectable,
|
|
984
|
+
nodeClickDistance: params2.nodeClickDistance
|
|
985
|
+
});
|
|
986
|
+
}
|
|
987
|
+
createEffect2(() => {
|
|
988
|
+
updateDrag(elem(), params());
|
|
989
|
+
});
|
|
990
|
+
onCleanup(() => {
|
|
991
|
+
dragInstance.destroy();
|
|
992
|
+
});
|
|
993
|
+
});
|
|
994
|
+
return dragging;
|
|
995
|
+
};
|
|
996
|
+
var createDraggable_default = createDraggable;
|
|
997
|
+
|
|
998
|
+
// src/components/contexts/nodeId.tsx
|
|
999
|
+
import { createContext as createContext3, useContext as useContext3 } from "solid-js";
|
|
1000
|
+
var NodeIdContext = createContext3();
|
|
1001
|
+
function useNodeId() {
|
|
1002
|
+
const ctx = useContext3(NodeIdContext);
|
|
1003
|
+
if (!ctx) {
|
|
1004
|
+
throw new Error(
|
|
1005
|
+
"solid-flow: Your application must be wrapped with <SolidFlow> in order to invoke useNodeId"
|
|
1006
|
+
);
|
|
1007
|
+
}
|
|
1008
|
+
return ctx;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
// src/components/graph/node/NodeWrapper.tsx
|
|
1012
|
+
var NodeWrapper = (props) => {
|
|
1013
|
+
const { store, nodeLookup, parentLookup, actions } = useInternalSolidFlow();
|
|
1014
|
+
const [nodeRef, setNodeRef] = createSignal4();
|
|
1015
|
+
const node = () => nodeLookup.get(props.nodeId);
|
|
1016
|
+
const nodeId = () => node().id;
|
|
1017
|
+
const nodeType = () => node().type ?? "default";
|
|
1018
|
+
const deletable = () => node().deletable ?? true;
|
|
1019
|
+
const selectable = () => node().selectable ?? store.elementsSelectable;
|
|
1020
|
+
const focusable = () => node().focusable ?? store.nodesFocusable;
|
|
1021
|
+
const draggable = () => node().draggable ?? store.nodesDraggable;
|
|
1022
|
+
const connectable = () => node().connectable ?? store.nodesConnectable;
|
|
1023
|
+
const userNode = () => node().internals.userNode;
|
|
1024
|
+
const nodeTypeValid = () => nodeType() in store.nodeTypes;
|
|
1025
|
+
const nodeComponent = () => store.nodeTypes[nodeType()];
|
|
1026
|
+
const isParentNode = () => parentLookup.has(node().id);
|
|
1027
|
+
const transform = () => {
|
|
1028
|
+
const { x, y } = node().internals.positionAbsolute;
|
|
1029
|
+
return `translate(${x}px, ${y}px)`;
|
|
1030
|
+
};
|
|
1031
|
+
const sizeStyle = () => {
|
|
1032
|
+
const w = node().width ?? node().initialWidth;
|
|
1033
|
+
const h = node().height ?? node().initialHeight;
|
|
1034
|
+
return {
|
|
1035
|
+
...node().style,
|
|
1036
|
+
...w ? { width: toPxString(w) } : {},
|
|
1037
|
+
...h ? { height: toPxString(h) } : {}
|
|
1038
|
+
};
|
|
1039
|
+
};
|
|
1040
|
+
const style = () => ({
|
|
1041
|
+
"z-index": node().internals.z,
|
|
1042
|
+
transform: transform(),
|
|
1043
|
+
visibility: nodeHasDimensions(node()) ? "visible" : "hidden",
|
|
1044
|
+
...sizeStyle(),
|
|
1045
|
+
...node().style ?? {}
|
|
1046
|
+
});
|
|
1047
|
+
createEffect3(() => {
|
|
1048
|
+
if (!nodeTypeValid()) {
|
|
1049
|
+
}
|
|
1050
|
+
});
|
|
1051
|
+
createEffect3((prev) => {
|
|
1052
|
+
if (prev && prev.sourcePosition === node().sourcePosition && prev.targetPosition === node().targetPosition && prev.nodeType === nodeType()) {
|
|
1053
|
+
return prev;
|
|
1054
|
+
}
|
|
1055
|
+
actions.requestUpdateNodeInternals([
|
|
1056
|
+
[
|
|
1057
|
+
node().id,
|
|
1058
|
+
{
|
|
1059
|
+
id: node().id,
|
|
1060
|
+
nodeElement: nodeRef(),
|
|
1061
|
+
force: true
|
|
1062
|
+
}
|
|
1063
|
+
]
|
|
1064
|
+
]);
|
|
1065
|
+
return {
|
|
1066
|
+
nodeType: nodeType(),
|
|
1067
|
+
sourcePosition: node().sourcePosition,
|
|
1068
|
+
targetPosition: node().targetPosition
|
|
1069
|
+
};
|
|
1070
|
+
});
|
|
1071
|
+
createEffect3((prevNodeRef) => {
|
|
1072
|
+
const currentNodeRef = nodeRef();
|
|
1073
|
+
if (currentNodeRef === prevNodeRef && nodeHasDimensions(node())) {
|
|
1074
|
+
return prevNodeRef;
|
|
1075
|
+
}
|
|
1076
|
+
if (prevNodeRef) {
|
|
1077
|
+
props.resizeObserver.unobserve(prevNodeRef);
|
|
1078
|
+
}
|
|
1079
|
+
if (currentNodeRef) {
|
|
1080
|
+
props.resizeObserver.observe(currentNodeRef);
|
|
1081
|
+
}
|
|
1082
|
+
return currentNodeRef;
|
|
1083
|
+
});
|
|
1084
|
+
const onSelectNodeHandler = (event) => {
|
|
1085
|
+
if (selectable() && (!store.selectNodesOnDrag || !draggable() || store.nodeDragThreshold > 0)) {
|
|
1086
|
+
actions.handleNodeSelection(node().id);
|
|
1087
|
+
}
|
|
1088
|
+
props.onNodeClick?.({ node: userNode(), event });
|
|
1089
|
+
};
|
|
1090
|
+
const onKeyDown = (event) => {
|
|
1091
|
+
if (isInputDOMNode(event) || store.disableKeyboardA11y) {
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
if (elementSelectionKeys2.includes(event.key) && selectable()) {
|
|
1095
|
+
actions.handleNodeSelection(node().id, event.key === "Escape", nodeRef());
|
|
1096
|
+
return;
|
|
1097
|
+
}
|
|
1098
|
+
const arrowKeyDiff = ARROW_KEY_DIFFS[event.key];
|
|
1099
|
+
if (draggable() && node().selected && arrowKeyDiff) {
|
|
1100
|
+
batch(() => {
|
|
1101
|
+
event.preventDefault();
|
|
1102
|
+
actions.setAriaLiveMessage(
|
|
1103
|
+
store.ariaLabelConfig["node.a11yDescription.ariaLiveMessage"]({
|
|
1104
|
+
direction: event.key.replace("Arrow", "").toLowerCase(),
|
|
1105
|
+
x: ~~node().internals.positionAbsolute.x,
|
|
1106
|
+
y: ~~node().internals.positionAbsolute.y
|
|
1107
|
+
})
|
|
1108
|
+
);
|
|
1109
|
+
actions.moveSelectedNodes(arrowKeyDiff, event.shiftKey ? 4 : 1);
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1112
|
+
};
|
|
1113
|
+
const onFocus = () => {
|
|
1114
|
+
if (store.disableKeyboardA11y || !store.autoPanOnNodeFocus || !nodeRef()?.matches(":focus-visible")) {
|
|
1115
|
+
return;
|
|
1116
|
+
}
|
|
1117
|
+
const { width, height, viewport } = store;
|
|
1118
|
+
const withinViewport = getNodesInside2(
|
|
1119
|
+
/* @__PURE__ */ new Map([[node().id, node()]]),
|
|
1120
|
+
{ x: 0, y: 0, width, height },
|
|
1121
|
+
[viewport.x, viewport.y, viewport.zoom],
|
|
1122
|
+
true
|
|
1123
|
+
).length > 0;
|
|
1124
|
+
if (withinViewport) return;
|
|
1125
|
+
void actions.setCenter(
|
|
1126
|
+
node().position.x + (node().measured.width ?? 0) / 2,
|
|
1127
|
+
node().position.y + (node().measured.height ?? 0) / 2,
|
|
1128
|
+
{ zoom: viewport.zoom }
|
|
1129
|
+
);
|
|
1130
|
+
};
|
|
1131
|
+
const dragging = createDraggable_default(nodeRef, () => ({
|
|
1132
|
+
nodeId: node().id,
|
|
1133
|
+
isSelectable: selectable(),
|
|
1134
|
+
disabled: !draggable(),
|
|
1135
|
+
handleSelector: node().dragHandle,
|
|
1136
|
+
noDragClass: store.noDragClass,
|
|
1137
|
+
nodeClickDistance: props.nodeClickDistance,
|
|
1138
|
+
onNodeMouseDown: actions.handleNodeSelection,
|
|
1139
|
+
onDrag: (event, _, targetNode, nodes) => {
|
|
1140
|
+
props.onNodeDrag?.({ event, targetNode, nodes });
|
|
1141
|
+
},
|
|
1142
|
+
onDragStart: (event, _, targetNode, nodes) => {
|
|
1143
|
+
props.onNodeDragStart?.({
|
|
1144
|
+
event,
|
|
1145
|
+
targetNode,
|
|
1146
|
+
nodes
|
|
1147
|
+
});
|
|
1148
|
+
},
|
|
1149
|
+
onDragStop: (event, _, targetNode, nodes) => {
|
|
1150
|
+
props.onNodeDragStop?.({
|
|
1151
|
+
event,
|
|
1152
|
+
targetNode,
|
|
1153
|
+
nodes
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
}));
|
|
1157
|
+
return <Show6 when={!node().hidden}>
|
|
1158
|
+
<div
|
|
1159
|
+
ref={setNodeRef}
|
|
1160
|
+
data-id={node().id}
|
|
1161
|
+
class={clsx6(
|
|
1162
|
+
"solid-flow__node",
|
|
1163
|
+
`solid-flow__node-${nodeType()}`,
|
|
1164
|
+
{
|
|
1165
|
+
connectable: connectable(),
|
|
1166
|
+
draggable: draggable(),
|
|
1167
|
+
dragging: dragging(),
|
|
1168
|
+
nopan: draggable(),
|
|
1169
|
+
parent: isParentNode(),
|
|
1170
|
+
selectable: selectable(),
|
|
1171
|
+
selected: node().selected
|
|
1172
|
+
},
|
|
1173
|
+
node().class
|
|
1174
|
+
)}
|
|
1175
|
+
style={style()}
|
|
1176
|
+
onClick={onSelectNodeHandler}
|
|
1177
|
+
onPointerEnter={(event) => props.onNodePointerEnter?.({ node: userNode(), event })}
|
|
1178
|
+
onPointerLeave={(event) => props.onNodePointerLeave?.({ node: userNode(), event })}
|
|
1179
|
+
onPointerMove={(event) => props.onNodePointerMove?.({ node: userNode(), event })}
|
|
1180
|
+
onContextMenu={(event) => props.onNodeContextMenu?.({ node: userNode(), event })}
|
|
1181
|
+
onKeyDown={(e) => focusable() && onKeyDown(e)}
|
|
1182
|
+
onFocus={() => focusable() && onFocus()}
|
|
1183
|
+
tabIndex={focusable() ? 0 : void 0}
|
|
1184
|
+
role={node().ariaRole ?? (focusable() ? "group" : void 0)}
|
|
1185
|
+
aria-roledescription="node"
|
|
1186
|
+
aria-describedby={store.disableKeyboardA11y ? void 0 : `${ARIA_NODE_DESC_KEY}-${store.id}`}
|
|
1187
|
+
{...node().domAttributes}
|
|
1188
|
+
>
|
|
1189
|
+
<NodeIdContext.Provider value={nodeId}>
|
|
1190
|
+
<NodeConnectableContext.Provider value={connectable}>
|
|
1191
|
+
<Dynamic2
|
|
1192
|
+
component={nodeComponent()}
|
|
1193
|
+
data={node().data}
|
|
1194
|
+
id={node().id}
|
|
1195
|
+
selected={Boolean(node().selected)}
|
|
1196
|
+
selectable={selectable()}
|
|
1197
|
+
deletable={deletable()}
|
|
1198
|
+
sourcePosition={node().sourcePosition}
|
|
1199
|
+
targetPosition={node().targetPosition}
|
|
1200
|
+
zIndex={node().internals.z}
|
|
1201
|
+
dragging={dragging()}
|
|
1202
|
+
draggable={draggable()}
|
|
1203
|
+
dragHandle={node().dragHandle}
|
|
1204
|
+
parentId={node().parentId}
|
|
1205
|
+
type={nodeType()}
|
|
1206
|
+
isConnectable={connectable()}
|
|
1207
|
+
positionAbsoluteX={node().internals.positionAbsolute.x}
|
|
1208
|
+
positionAbsoluteY={node().internals.positionAbsolute.y}
|
|
1209
|
+
width={node().width}
|
|
1210
|
+
height={node().height}
|
|
1211
|
+
/>
|
|
1212
|
+
</NodeConnectableContext.Provider>
|
|
1213
|
+
</NodeIdContext.Provider>
|
|
58
1214
|
</div>
|
|
59
|
-
</
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
</>};import{devWarn as Di,infiniteExtent as Oi}from"@xyflow/system";var we=()=>({id:"1",nodes:[],edges:[],nodeOrigin:[0,0],nodeExtent:Oi,defaultEdgeOptions:{},colorMode:"system",colorModeSSR:"light",connectionMode:"strict",connectionLineType:"default",connectionRadius:20,nodeDragThreshold:1,minZoom:.5,maxZoom:2,selectionMode:"partial",fitView:!1,noPanClass:"nopan",noDragClass:"nodrag",noWheelClass:"nowheel",autoPanOnNodeDrag:!0,autoPanOnConnect:!0,autoPanOnNodeFocus:!0,autoPanSpeed:15,elevateEdgesOnSelect:!0,nodesDraggable:!0,nodesConnectable:!0,nodesFocusable:!0,edgesFocusable:!0,elementsSelectable:!0,selectNodesOnDrag:!0,elevateNodesOnSelect:!0,onlyRenderVisibleElements:!1,disableKeyboardA11y:!1,defaultMarkerColor:"#b1b1b7",ariaLiveMessage:"",style:{},isValidConnection:()=>!0,onFlowError:Di});import{clampPosition as Vo,clampPositionToParent as zi,getBoundsOfRects as rg,getDimensions as ig,getHandleBounds as sg,getNodeDimensions as tn,getNodePositionWithOrigin as nn,infiniteExtent as Ri,isCoordinateExtent as rn,isNumeric as Ai,nodeToRect as dg}from"@xyflow/system";var sn={nodeOrigin:[0,0],nodeExtent:Ri,elevateNodesOnSelect:!0,defaults:{}},_i={...sn,checkEquality:!0};function dn(e,o){let t={...e};for(let N in o)o[N]!==void 0&&(t[N]=o[N]);return t}function an(e,o,t,N){let S=dn(_i,N),P=e.length>0,x=new Map(o),b=S?.elevateNodesOnSelect?1e3:0;o.clear(),t.clear();for(let C of e){let T=x.get(C.id);if(S.checkEquality&&C===T?.internals.userNode)o.set(C.id,T);else{let v=nn(C,S.nodeOrigin),E=rn(C.extent)?C.extent:S.nodeExtent,w=Vo(v,E,tn(C));T={...S.defaults,...C,measured:{width:C.measured?.width,height:C.measured?.height},internals:{positionAbsolute:w,handleBounds:C.measured?T?.internals.handleBounds:void 0,z:$e(C,b),userNode:C}},o.set(C.id,T)}(T.measured===void 0||T.measured.width===void 0||T.measured.height===void 0)&&!T.hidden&&(P=!1),C.parentId&&Ko(T,o,t,N)}return P}function Li(e,o){if(!e.parentId)return;let t=o.get(e.parentId);t?t.set(e.id,e):o.set(e.parentId,new Map([[e.id,e]]))}function Ko(e,o,t,N){let{elevateNodesOnSelect:S,nodeOrigin:P,nodeExtent:x}=dn(sn,N),b=e.parentId,C=o.get(b);if(!C)return;Li(e,t);let T=S?1e3:0,{x:v,y:E,z:w}=Hi(e,C,P,x,T),{positionAbsolute:I}=e.internals,D=v!==I.x||E!==I.y;(D||w!==e.internals.z)&&o.set(e.id,{...e,internals:{...e.internals,positionAbsolute:D?{x:v,y:E}:I,z:w}})}function $e(e,o){return(Ai(e.zIndex)?e.zIndex:0)+(e.selected?o:0)}function Hi(e,o,t,N,S){let{x:P,y:x}=o.internals.positionAbsolute,b=tn(e),C=nn(e,t),T=rn(e.extent)?Vo(C,e.extent,b):C,v=Vo({x:P+T.x,y:x+T.y},N,b);e.extent==="parent"&&(v=zi(v,b,o));let E=$e(e,S),w=o.internals.z??0;return{x:v.x,y:v.y,z:w>=E?w+1:E}}function Xo(e,o,t,N,S,P){let x=S,b=N.get(x)||new Map;N.set(x,b.set(t,o)),x=`${S}-${e}`;let C=N.get(x)||new Map;if(N.set(x,C.set(t,o)),P){x=`${S}-${e}-${P}`;let T=N.get(x)||new Map;N.set(x,T.set(t,o))}}function Fo(e,o,t,N,S){let P=N,x=t.get(P);x&&(x.delete(o),x.size===0&&t.delete(P)),P=`${N}-${e}`;let b=t.get(P);if(b&&(b.delete(o),b.size===0&&t.delete(P)),S){P=`${N}-${e}-${S}`;let C=t.get(P);C&&(C.delete(o),C.size===0&&t.delete(P))}}var is={input:_o,output:Bo,default:Ro,group:Ao},ss={straight:Oo,smoothstep:ko,default:To,step:Do},ds=(e,o,t,N,S,P)=>{if(o&&!t&&N&&S){let x=Zi(P,{filter:b=>!!((b.width||b.initialWidth)&&(b.height||b.initialHeight))});return Ji(x,N,S,.5,2,.1)}else return t??{x:0,y:0,zoom:1}},Je=e=>{let o=pn(we(),e),t=new ze,N=new ze,S=new ze,P=new ze,x=new ze,b=Ce(()=>an(o.nodes,t,N,{nodeExtent:o.nodeExtent,nodeOrigin:o.nodeOrigin,elevateNodesOnSelect:o.elevateNodesOnSelect,checkEquality:!0})),C=ds(b,o.fitView,o.initialViewport,o.width??0,o.height??0,t),T=Bi("(prefers-color-scheme: dark)",o.colorModeSSR==="dark"),[v,E]=re(o),[w,I]=se(()=>Qi(v().ariaLabelConfig)),[D,k]=se(()=>v().ariaLiveMessage),[R,Y]=re(void 0),[H,_]=re(Yo),[$,ee]=re(null),[ie,de]=re(!1),[U,G]=se(()=>v().elementsSelectable),[O,F]=se(()=>v().height),[K,Z]=se(()=>v().minZoom),[te,Ot]=se(()=>v().maxZoom),[Le,An]=se(()=>v().nodesDraggable),[_n,Ln]=se(()=>v().nodesDraggable),[bo,Hn]=re(null),[Bn,He]=re(),[Vn,Be]=re(),[Kn,Xn]=se(()=>v().snapGrid),[Fn,Cl]=se(()=>v().translateExtent??Gi),[Yn,Wn]=se(()=>v().width),[Zn,zt]=re(!1),[$n,Rt]=re(!1),[Un,At]=re(!1),[Jn,_t]=re(!1),[Gn,Lt]=re(!1),be=Fe(()=>v().nodes),Ve=Fe(()=>v().edges),Ee=Fe(()=>v().viewport??C),jn=Ue(()=>[Ee.get().x,Ee.get().y,Ee.get().zoom]),A=pn({width:0,height:0},v,{get _colorMode(){return v().colorMode},get _colorModeSSR(){return v().colorModeSSR},get _connection(){return H()},get _nodeTypes(){return v().nodeTypes},get _edgeTypes(){return v().edgeTypes},get ariaLabelConfig(){return w()},get ariaLiveMessage(){return D()},get clickConnectStartHandle(){return R()},get colorMode(){return this._colorMode==="system"?T()?"dark":"light":this._colorMode},get connection(){let M=H();return{...M,from:M.inProgress?ln(M.from,this.transform):M.from,to:M.inProgress?ln(M.to,this.transform):M.to}},get domNode(){return $()},get dragging(){return ie()},get edgeTypes(){return{...ss,...this._edgeTypes}},get elementsSelectable(){return U()},get height(){return O()},get lib(){return"solid"},get onError(){return v().onFlowError},get maxZoom(){return te()},get minZoom(){return K()},get nodes(){return be.get()},get nodesConnectable(){return Le()},get nodesDraggable(){return _n()},get nodeTypes(){return{...is,...this._nodeTypes}},get panZoom(){return bo()},get selectedNodes(){return v().nodes.filter(M=>M.selected)},get selectedEdges(){return v().edges.filter(M=>M.selected)},get selectionRect(){return Bn()},get selectionRectMode(){return Vn()},get snapGrid(){return Kn()},get viewport(){return Ee.get()},get viewportInitialized(){return bo()!==null},get visibleEdgeIds(){return Qn()},get visibleNodeIds(){return qn()},get visibleNodesMap(){return Ht()},get transform(){return jn()},get translateExtent(){return Fn()},get width(){return Yn()},get selectionKeyPressed(){return Zn()},get multiselectionKeyPressed(){return $n()},get deleteKeyPressed(){return Un()},get panActivationKeyPressed(){return Jn()},get zoomActivationKeyPressed(){return Gn()}}),Ht=Ue(()=>t),qn=Ue(()=>Array.from(Ht().values()).map(M=>M.id)),Qn=Ue(()=>Array.from(x.values()).map(M=>M.id)),er=M=>x.get(M),Bt=async M=>A.panZoom?Fi({nodes:t,width:A.width,height:A.height,panZoom:A.panZoom,minZoom:A.minZoom,maxZoom:A.maxZoom},M??v().fitViewOptions):!1,Vt=()=>{de(!1),He(void 0),Be(void 0),zt(!1),Rt(!1),At(!1),_t(!1),Lt(!1),_({...Yo}),Y(void 0),Ee.set(v().initialViewport??{x:0,y:0,zoom:1}),k(""),Xn(void 0)},or=M=>{Ve.set(L=>Vi(M,L))},Eo=!1,tr=M=>{Eo=!M},Kt=(M,L=!1)=>{be.set(X=>M.has(X.id),ve(X=>{X.dragging=L,X.position=M.get(X.id).position}))},Ie,nr=M=>{if(Ie){Ie.push(...M);return}Ie=M,requestIdleCallback(()=>{Ce(()=>{let L=new Map(Ie);Ie=void 0;let{changes:X,updatedInternals:B}=ns(L,t,N,A.domNode,A.nodeOrigin);if(!B)return;ts(t,N,{nodeOrigin:A.nodeOrigin,nodeExtent:A.nodeExtent});let V=X.reduce((W,ne)=>{let oe=t.get(ne.id)?.internals.userNode;return oe&&W.set(oe.id,ne),W},new Map);be.set(W=>V.has(W.id),ve(W=>{let ne=V.get(W.id);switch(ne.type){case"dimensions":{ne.setAttributes&&(W.width=ne.dimensions?.width??W.width,W.height=ne.dimensions?.height??W.height),W.measured={...W.measured,...ne.dimensions};break}case"position":W.position=ne.position??W.position;break}})),Eo||(Eo=!0,Bt())})})},Xt=async(M,L)=>A.panZoom?A.panZoom.scaleBy(M,L):!1,rr=M=>Xt(1.2,M),ir=M=>Xt(1/1.2,M),sr=async(M,L,X)=>{let B=typeof X?.zoom<"u"?X.zoom:A.maxZoom,V=A.panZoom;return V?(await V.setViewport({x:A.width/2-M*B,y:A.height/2-L*B,zoom:B},{duration:X?.duration,ease:X?.ease,interpolate:X?.interpolate}),Promise.resolve(!0)):Promise.resolve(!1)},dr=M=>{A.panZoom?.setClickDistance(M)},xe=({nodes:M,edges:L}={})=>{let X=new Set((M||A.nodes).map(({id:V})=>V));X.size&&be.set(V=>X.has(V.id),ve(V=>{V.selected=!1}));let B=new Set((L||A.edges).map(({id:V})=>V));B.size&&Ve.set(V=>B.has(V.id),ve(V=>{V.selected=!1}))},Ft=M=>{let L=A.multiselectionKeyPressed,X=new Map;be.set(B=>{let V=M.includes(B.id),W=L&&B.selected||V;return X.set(B.id,W),B.selected!==W},ve(B=>{let V=t.get(B.id);V&&(V.selected=X.get(B.id)),B.selected=X.get(B.id)})),L||xe({nodes:[]})},Yt=M=>{let L=A.multiselectionKeyPressed,X=new Map;Ve.set(B=>{let V=M.includes(B.id),W=L&&B.selected||V;return X.set(B.id,W),B.selected!==W},ve(B=>{B.selected=X.get(B.id)})),L||xe({edges:[]})},ar=(M,L,X)=>{let B=A.nodes.find(V=>V.id===M);B&&(Ce(()=>{He(void 0),Be(void 0)}),B.selected?(L||B.selected&&A.multiselectionKeyPressed)&&(xe({nodes:[B],edges:[]}),requestAnimationFrame(()=>X?.blur())):Ft([M]))},lr=M=>{let L=S.get(M);!L||!(L.selectable||A.elementsSelectable&&typeof L.selectable>"u")||(Ce(()=>{He(void 0),Be(void 0)}),L.selected?L.selected&&A.multiselectionKeyPressed&&xe({nodes:[],edges:[L]}):Yt([M]))},cr=(M,L)=>{let X=new Map,B=A.snapGrid?.[0]??5,V=A.snapGrid?.[1]??5,W=M.x*B*L,ne=M.y*V*L;for(let oe of t.values()){if(!(oe.selected&&(oe.draggable||A.nodesDraggable&&typeof oe.draggable>"u")))continue;let ae={x:oe.internals.positionAbsolute.x+W,y:oe.internals.positionAbsolute.y+ne};A.snapGrid&&(ae=os(ae,A.snapGrid));let{position:Ke,positionAbsolute:Wt}=Ki({nodeId:oe.id,nextPosition:ae,nodeLookup:t,nodeExtent:A.nodeExtent,nodeOrigin:A.nodeOrigin,onError:A.onError});oe.position=Ke,oe.internals.positionAbsolute=Wt,X.set(oe.id,oe)}Kt(X)},pr=M=>es({delta:M,panZoom:A.panZoom,transform:A.transform,translateExtent:A.translateExtent,width:A.width,height:A.height}),gr=()=>{_({...Yo})},mr=()=>{Vt(),xe()};return Te(()=>{A.panZoom?.syncViewport(A.viewport)}),Te(()=>{let M=bo();M&&(Te(()=>{M.setScaleExtent([A.minZoom,A.maxZoom])}),Te(()=>{M.setTranslateExtent(A.translateExtent)}))}),Re(cn(()=>A.nodes,M=>{Re(()=>{let L=rs(()=>t.get(M.id)),X=A.elevateNodesOnSelect?1e3:0,B=Xi(Ui(M,A.nodeOrigin),ji(M.extent)?M.extent:A.nodeExtent,$i(M)),V={width:M.measured?.width??L?.measured?.width,height:M.measured?.height??L?.measured?.height},W={...M,measured:V,internals:{positionAbsolute:B,handleBounds:!M.measured&&!L?.measured?void 0:L?.internals.handleBounds,z:$e(M,X),userNode:M}};t.set(M.id,W),M.parentId&&Ko(W,t,N,{nodeOrigin:A.nodeOrigin,nodeExtent:A.nodeExtent,elevateNodesOnSelect:A.elevateNodesOnSelect,checkEquality:!0})}),gn(()=>{})})),Te(()=>{let M=new Set(A.nodes.map(L=>L.id));for(let L of Array.from(t.keys()))M.has(L)||t.delete(L)}),Re(cn(()=>A.edges,M=>{let{source:L,target:X,sourceHandle:B=null,targetHandle:V=null}=M,W={edgeId:M.id,source:L,target:X,sourceHandle:B,targetHandle:V},ne=`${L}-${B}--${X}-${V}`,oe=`${X}-${V}--${L}-${B}`;Re(()=>{Ce(()=>{Xo("source",W,oe,P,L,B),Xo("target",W,ne,P,X,V),S.set(M.id,M)})}),Re(()=>{let ce=t.get(M.source),ae=t.get(M.target);if(!ce||!ae)return;if(A.onlyRenderVisibleElements){if(!qi({sourceNode:ce,targetNode:ae,width:A.width??0,height:A.height??0,transform:A.transform}))return;A.visibleNodesMap.set(ce.id,ce),A.visibleNodesMap.set(ae.id,ae)}let Ke=Yi({id:M.id,sourceNode:ce,targetNode:ae,sourceHandle:M.sourceHandle||null,targetHandle:M.targetHandle||null,connectionMode:A.connectionMode,onError:A.onError});Ke&&x.set(M.id,{...A.defaultEdgeOptions,...M,...Ke,zIndex:Wi({selected:M.selected,zIndex:M.zIndex??A.defaultEdgeOptions.zIndex,sourceNode:ce,targetNode:ae,elevateOnSelect:A.elevateEdgesOnSelect}),sourceNode:ce,targetNode:ae,edge:M})}),gn(()=>{Ce(()=>{S.delete(M.id),x.delete(M.id),Fo("source",oe,P,L,B),Fo("target",ne,P,X,V)})})})),Te(()=>{let M=new Set(A.edges.map(L=>L.id));for(let L of Array.from(S.keys()))M.has(L)||(S.delete(L),P.delete(L),x.delete(L))}),{store:A,nodeLookup:t,edgeLookup:S,parentLookup:N,connectionLookup:P,actions:{getEdge:er,applyInitialFitView:tr,resetStoreValues:Vt,requestUpdateNodeInternals:nr,setAriaLabelConfig:I,setAriaLiveMessage:k,setClickConnectStartHandle:Y,setConfig:E,setConnection:_,setDeleteKeyPressed:At,setDomNode:ee,setDragging:de,get setEdges(){return Ve.set},setElementsSelectable:G,setHeight:F,setMultiselectionKeyPressed:Rt,get setNodes(){return be.set},setNodesConnectable:An,setNodesDraggable:Ln,setPanActivationKeyPressed:_t,setPanZoom:Hn,setSelectionKeyPressed:zt,setSelectionRect:He,setSelectionRectMode:Be,get setViewport(){return Ee.set},setWidth:Wn,setZoomActivationKeyPressed:Lt,addEdge:or,updateNodePositions:Kt,zoomIn:rr,zoomOut:ir,fitView:Bt,setCenter:sr,setPaneClickDistance:dr,unselectNodesAndEdges:xe,addSelectedNodes:Ft,addSelectedEdges:Yt,handleNodeSelection:ar,handleEdgeSelection:lr,moveSelectedNodes:cr,panBy:pr,cancelConnection:gr,reset:mr}}};var Ae=as();function z(){let e=ls(Ae);if(!e)throw new Error("solid-flow: Your application must be wrapped with <SolidFlow> in order to invoke useInternalSolidFlow within your components");return e}import{mergeProps as cs,Show as Ss}from"solid-js";var Wo=e=>{let o=cs({markerUnits:"strokeWidth",orient:"auto-start-reverse",width:12.5,height:12.5,color:"none"},e),t=()=>o.color??"var(--xy-edge-stroke)";return<marker class="solid-flow__arrowhead"id={o.id}markerWidth={o.width}markerHeight={o.height}viewBox="-10 -10 20 20"markerUnits={o.markerUnits}orient={o.orient}refX="0"refY="0">
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
1215
|
+
</Show6>;
|
|
1216
|
+
};
|
|
1217
|
+
|
|
1218
|
+
// src/components/graph/node/OutputNode.tsx
|
|
1219
|
+
import { mergeProps as mergeProps7 } from "solid-js";
|
|
1220
|
+
var OutputNode = (props) => {
|
|
1221
|
+
const _props = mergeProps7(
|
|
1222
|
+
{
|
|
1223
|
+
targetPosition: "top"
|
|
1224
|
+
},
|
|
1225
|
+
props
|
|
1226
|
+
);
|
|
1227
|
+
return <>
|
|
1228
|
+
<Handle type="target" position={_props.targetPosition} isConnectable={_props.isConnectable} />
|
|
1229
|
+
{props.data?.label}
|
|
1230
|
+
</>;
|
|
1231
|
+
};
|
|
1232
|
+
|
|
1233
|
+
// src/data/defaults.ts
|
|
1234
|
+
import {
|
|
1235
|
+
devWarn,
|
|
1236
|
+
infiniteExtent
|
|
1237
|
+
} from "@xyflow/system";
|
|
1238
|
+
var getDefaultFlowStateProps = () => ({
|
|
1239
|
+
id: "1",
|
|
1240
|
+
nodes: [],
|
|
1241
|
+
edges: [],
|
|
1242
|
+
nodeOrigin: [0, 0],
|
|
1243
|
+
nodeExtent: infiniteExtent,
|
|
1244
|
+
defaultEdgeOptions: {},
|
|
1245
|
+
colorMode: "system",
|
|
1246
|
+
colorModeSSR: "light",
|
|
1247
|
+
connectionMode: "strict",
|
|
1248
|
+
connectionLineType: "default",
|
|
1249
|
+
connectionRadius: 20,
|
|
1250
|
+
nodeDragThreshold: 1,
|
|
1251
|
+
minZoom: 0.5,
|
|
1252
|
+
maxZoom: 2,
|
|
1253
|
+
selectionMode: "partial",
|
|
1254
|
+
fitView: false,
|
|
1255
|
+
noPanClass: "nopan",
|
|
1256
|
+
noDragClass: "nodrag",
|
|
1257
|
+
noWheelClass: "nowheel",
|
|
1258
|
+
autoPanOnNodeDrag: true,
|
|
1259
|
+
autoPanOnConnect: true,
|
|
1260
|
+
autoPanOnNodeFocus: true,
|
|
1261
|
+
autoPanSpeed: 15,
|
|
1262
|
+
elevateEdgesOnSelect: true,
|
|
1263
|
+
nodesDraggable: true,
|
|
1264
|
+
nodesConnectable: true,
|
|
1265
|
+
nodesFocusable: true,
|
|
1266
|
+
edgesFocusable: true,
|
|
1267
|
+
elementsSelectable: true,
|
|
1268
|
+
selectNodesOnDrag: true,
|
|
1269
|
+
elevateNodesOnSelect: true,
|
|
1270
|
+
onlyRenderVisibleElements: false,
|
|
1271
|
+
disableKeyboardA11y: false,
|
|
1272
|
+
defaultMarkerColor: "#b1b1b7",
|
|
1273
|
+
ariaLiveMessage: "",
|
|
1274
|
+
style: {},
|
|
1275
|
+
isValidConnection: () => true,
|
|
1276
|
+
onFlowError: devWarn
|
|
1277
|
+
});
|
|
1278
|
+
|
|
1279
|
+
// src/data/xyflow.ts
|
|
1280
|
+
import {
|
|
1281
|
+
clampPosition,
|
|
1282
|
+
clampPositionToParent,
|
|
1283
|
+
getBoundsOfRects,
|
|
1284
|
+
getDimensions,
|
|
1285
|
+
getHandleBounds,
|
|
1286
|
+
getNodeDimensions,
|
|
1287
|
+
getNodePositionWithOrigin,
|
|
1288
|
+
infiniteExtent as infiniteExtent2,
|
|
1289
|
+
isCoordinateExtent,
|
|
1290
|
+
isNumeric,
|
|
1291
|
+
nodeToRect
|
|
1292
|
+
} from "@xyflow/system";
|
|
1293
|
+
var defaultOptions = {
|
|
1294
|
+
nodeOrigin: [0, 0],
|
|
1295
|
+
nodeExtent: infiniteExtent2,
|
|
1296
|
+
elevateNodesOnSelect: true,
|
|
1297
|
+
defaults: {}
|
|
1298
|
+
};
|
|
1299
|
+
var adoptUserNodesDefaultOptions = {
|
|
1300
|
+
...defaultOptions,
|
|
1301
|
+
checkEquality: true
|
|
1302
|
+
};
|
|
1303
|
+
function mergeObjects(base, incoming) {
|
|
1304
|
+
const result = { ...base };
|
|
1305
|
+
for (const key in incoming) {
|
|
1306
|
+
if (incoming[key] !== void 0) {
|
|
1307
|
+
result[key] = incoming[key];
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
return result;
|
|
1311
|
+
}
|
|
1312
|
+
function adoptUserNodes(nodes, nodeLookup, parentLookup, options) {
|
|
1313
|
+
const _options = mergeObjects(adoptUserNodesDefaultOptions, options);
|
|
1314
|
+
let nodesInitialized = nodes.length > 0;
|
|
1315
|
+
const tmpLookup = new Map(nodeLookup);
|
|
1316
|
+
const selectedNodeZ = _options?.elevateNodesOnSelect ? 1e3 : 0;
|
|
1317
|
+
nodeLookup.clear();
|
|
1318
|
+
parentLookup.clear();
|
|
1319
|
+
for (const userNode of nodes) {
|
|
1320
|
+
let internalNode = tmpLookup.get(userNode.id);
|
|
1321
|
+
if (_options.checkEquality && userNode === internalNode?.internals.userNode) {
|
|
1322
|
+
nodeLookup.set(userNode.id, internalNode);
|
|
1323
|
+
} else {
|
|
1324
|
+
const positionWithOrigin = getNodePositionWithOrigin(userNode, _options.nodeOrigin);
|
|
1325
|
+
const extent = isCoordinateExtent(userNode.extent) ? userNode.extent : _options.nodeExtent;
|
|
1326
|
+
const clampedPosition = clampPosition(
|
|
1327
|
+
positionWithOrigin,
|
|
1328
|
+
extent,
|
|
1329
|
+
getNodeDimensions(userNode)
|
|
1330
|
+
);
|
|
1331
|
+
internalNode = {
|
|
1332
|
+
..._options.defaults,
|
|
1333
|
+
...userNode,
|
|
1334
|
+
measured: {
|
|
1335
|
+
width: userNode.measured?.width,
|
|
1336
|
+
height: userNode.measured?.height
|
|
1337
|
+
},
|
|
1338
|
+
internals: {
|
|
1339
|
+
positionAbsolute: clampedPosition,
|
|
1340
|
+
// if user re-initializes the node or removes `measured` for whatever reason, we reset the handleBounds so that the node gets re-measured
|
|
1341
|
+
handleBounds: !userNode.measured ? void 0 : internalNode?.internals.handleBounds,
|
|
1342
|
+
z: calculateZ(userNode, selectedNodeZ),
|
|
1343
|
+
userNode
|
|
1344
|
+
}
|
|
1345
|
+
};
|
|
1346
|
+
nodeLookup.set(userNode.id, internalNode);
|
|
1347
|
+
}
|
|
1348
|
+
if ((internalNode.measured === void 0 || internalNode.measured.width === void 0 || internalNode.measured.height === void 0) && !internalNode.hidden) {
|
|
1349
|
+
nodesInitialized = false;
|
|
1350
|
+
}
|
|
1351
|
+
if (userNode.parentId) {
|
|
1352
|
+
updateChildNode(internalNode, nodeLookup, parentLookup, options);
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
return nodesInitialized;
|
|
1356
|
+
}
|
|
1357
|
+
function updateParentLookup(node, parentLookup) {
|
|
1358
|
+
if (!node.parentId) {
|
|
1359
|
+
return;
|
|
1360
|
+
}
|
|
1361
|
+
const childNodes = parentLookup.get(node.parentId);
|
|
1362
|
+
if (childNodes) {
|
|
1363
|
+
childNodes.set(node.id, node);
|
|
1364
|
+
} else {
|
|
1365
|
+
parentLookup.set(node.parentId, /* @__PURE__ */ new Map([[node.id, node]]));
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
function updateChildNode(node, nodeLookup, parentLookup, options) {
|
|
1369
|
+
const { elevateNodesOnSelect, nodeOrigin, nodeExtent } = mergeObjects(defaultOptions, options);
|
|
1370
|
+
const parentId = node.parentId;
|
|
1371
|
+
const parentNode = nodeLookup.get(parentId);
|
|
1372
|
+
if (!parentNode) {
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
updateParentLookup(node, parentLookup);
|
|
1376
|
+
const selectedNodeZ = elevateNodesOnSelect ? 1e3 : 0;
|
|
1377
|
+
const { x, y, z } = calculateChildXYZ(node, parentNode, nodeOrigin, nodeExtent, selectedNodeZ);
|
|
1378
|
+
const { positionAbsolute } = node.internals;
|
|
1379
|
+
const positionChanged = x !== positionAbsolute.x || y !== positionAbsolute.y;
|
|
1380
|
+
if (positionChanged || z !== node.internals.z) {
|
|
1381
|
+
nodeLookup.set(node.id, {
|
|
1382
|
+
...node,
|
|
1383
|
+
internals: {
|
|
1384
|
+
...node.internals,
|
|
1385
|
+
positionAbsolute: positionChanged ? { x, y } : positionAbsolute,
|
|
1386
|
+
z
|
|
1387
|
+
}
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
function calculateZ(node, selectedNodeZ) {
|
|
1392
|
+
return (isNumeric(node.zIndex) ? node.zIndex : 0) + (node.selected ? selectedNodeZ : 0);
|
|
1393
|
+
}
|
|
1394
|
+
function calculateChildXYZ(childNode, parentNode, nodeOrigin, nodeExtent, selectedNodeZ) {
|
|
1395
|
+
const { x: parentX, y: parentY } = parentNode.internals.positionAbsolute;
|
|
1396
|
+
const childDimensions = getNodeDimensions(childNode);
|
|
1397
|
+
const positionWithOrigin = getNodePositionWithOrigin(childNode, nodeOrigin);
|
|
1398
|
+
const clampedPosition = isCoordinateExtent(childNode.extent) ? clampPosition(positionWithOrigin, childNode.extent, childDimensions) : positionWithOrigin;
|
|
1399
|
+
let absolutePosition = clampPosition(
|
|
1400
|
+
{ x: parentX + clampedPosition.x, y: parentY + clampedPosition.y },
|
|
1401
|
+
nodeExtent,
|
|
1402
|
+
childDimensions
|
|
1403
|
+
);
|
|
1404
|
+
if (childNode.extent === "parent") {
|
|
1405
|
+
absolutePosition = clampPositionToParent(absolutePosition, childDimensions, parentNode);
|
|
1406
|
+
}
|
|
1407
|
+
const childZ = calculateZ(childNode, selectedNodeZ);
|
|
1408
|
+
const parentZ = parentNode.internals.z ?? 0;
|
|
1409
|
+
return {
|
|
1410
|
+
x: absolutePosition.x,
|
|
1411
|
+
y: absolutePosition.y,
|
|
1412
|
+
z: parentZ >= childZ ? parentZ + 1 : childZ
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1415
|
+
function addConnectionToLookup(type, connection, connectionKey, connectionLookup, nodeId, handleId) {
|
|
1416
|
+
let key = nodeId;
|
|
1417
|
+
const nodeMap = connectionLookup.get(key) || /* @__PURE__ */ new Map();
|
|
1418
|
+
connectionLookup.set(key, nodeMap.set(connectionKey, connection));
|
|
1419
|
+
key = `${nodeId}-${type}`;
|
|
1420
|
+
const typeMap = connectionLookup.get(key) || /* @__PURE__ */ new Map();
|
|
1421
|
+
connectionLookup.set(key, typeMap.set(connectionKey, connection));
|
|
1422
|
+
if (handleId) {
|
|
1423
|
+
key = `${nodeId}-${type}-${handleId}`;
|
|
1424
|
+
const handleMap = connectionLookup.get(key) || /* @__PURE__ */ new Map();
|
|
1425
|
+
connectionLookup.set(key, handleMap.set(connectionKey, connection));
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
function removeConnectionFromLookup(type, connectionKey, connectionLookup, nodeId, handleId) {
|
|
1429
|
+
let key = nodeId;
|
|
1430
|
+
const nodeMap = connectionLookup.get(key);
|
|
1431
|
+
if (nodeMap) {
|
|
1432
|
+
nodeMap.delete(connectionKey);
|
|
1433
|
+
if (nodeMap.size === 0) connectionLookup.delete(key);
|
|
1434
|
+
}
|
|
1435
|
+
key = `${nodeId}-${type}`;
|
|
1436
|
+
const typeMap = connectionLookup.get(key);
|
|
1437
|
+
if (typeMap) {
|
|
1438
|
+
typeMap.delete(connectionKey);
|
|
1439
|
+
if (typeMap.size === 0) connectionLookup.delete(key);
|
|
1440
|
+
}
|
|
1441
|
+
if (handleId) {
|
|
1442
|
+
key = `${nodeId}-${type}-${handleId}`;
|
|
1443
|
+
const handleMap = connectionLookup.get(key);
|
|
1444
|
+
if (handleMap) {
|
|
1445
|
+
handleMap.delete(connectionKey);
|
|
1446
|
+
if (handleMap.size === 0) connectionLookup.delete(key);
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
// src/data/createSolidFlow.tsx
|
|
1452
|
+
var InitialNodeTypesMap = {
|
|
1453
|
+
input: InputNode,
|
|
1454
|
+
output: OutputNode,
|
|
1455
|
+
default: DefaultNode,
|
|
1456
|
+
group: GroupNode
|
|
1457
|
+
};
|
|
1458
|
+
var InitialEdgeTypesMap = {
|
|
1459
|
+
straight: StraightEdgeInternal,
|
|
1460
|
+
smoothstep: SmoothStepEdgeInternal,
|
|
1461
|
+
default: BezierEdgeInternal,
|
|
1462
|
+
step: StepEdgeInternal
|
|
1463
|
+
};
|
|
1464
|
+
var getInitialViewport = (_nodesInitialized, fitView, initialViewport, width, height, nodeLookup) => {
|
|
1465
|
+
if (fitView && !initialViewport && width && height) {
|
|
1466
|
+
const bounds = getInternalNodesBounds(nodeLookup, {
|
|
1467
|
+
filter: (node) => !!((node.width || node.initialWidth) && (node.height || node.initialHeight))
|
|
1468
|
+
});
|
|
1469
|
+
return getViewportForBounds(bounds, width, height, 0.5, 2, 0.1);
|
|
1470
|
+
} else {
|
|
1471
|
+
return initialViewport ?? { x: 0, y: 0, zoom: 1 };
|
|
1472
|
+
}
|
|
1473
|
+
};
|
|
1474
|
+
var createSolidFlow = (props) => {
|
|
1475
|
+
const _props = mergeProps8(getDefaultFlowStateProps(), props);
|
|
1476
|
+
const nodeLookup = new ReactiveMap();
|
|
1477
|
+
const parentLookup = new ReactiveMap();
|
|
1478
|
+
const edgeLookup = new ReactiveMap();
|
|
1479
|
+
const connectionLookup = new ReactiveMap();
|
|
1480
|
+
const layoutedEdgesMap = new ReactiveMap();
|
|
1481
|
+
const startNodesInitialized = batch2(() => {
|
|
1482
|
+
return adoptUserNodes(_props.nodes, nodeLookup, parentLookup, {
|
|
1483
|
+
// eslint-disable-next-line solid/reactivity
|
|
1484
|
+
nodeExtent: _props.nodeExtent,
|
|
1485
|
+
// eslint-disable-next-line solid/reactivity
|
|
1486
|
+
nodeOrigin: _props.nodeOrigin,
|
|
1487
|
+
// eslint-disable-next-line solid/reactivity
|
|
1488
|
+
elevateNodesOnSelect: _props.elevateNodesOnSelect,
|
|
1489
|
+
checkEquality: true
|
|
1490
|
+
});
|
|
1491
|
+
});
|
|
1492
|
+
const initialViewport = getInitialViewport(
|
|
1493
|
+
startNodesInitialized,
|
|
1494
|
+
// eslint-disable-next-line solid/reactivity
|
|
1495
|
+
_props.fitView,
|
|
1496
|
+
_props.initialViewport,
|
|
1497
|
+
// eslint-disable-next-line solid/reactivity
|
|
1498
|
+
_props.width ?? 0,
|
|
1499
|
+
// eslint-disable-next-line solid/reactivity
|
|
1500
|
+
_props.height ?? 0,
|
|
1501
|
+
nodeLookup
|
|
1502
|
+
);
|
|
1503
|
+
const mediaPrefersDark = createMediaQuery(
|
|
1504
|
+
"(prefers-color-scheme: dark)",
|
|
1505
|
+
// NOTE: should mediaPrefersDark be reactive to config-changes?
|
|
1506
|
+
_props.colorModeSSR === "dark"
|
|
1507
|
+
);
|
|
1508
|
+
const [config, setConfig] = createSignal5(_props);
|
|
1509
|
+
const [ariaLabelConfig, setAriaLabelConfig] = createWritable(
|
|
1510
|
+
() => mergeAriaLabelConfig(config().ariaLabelConfig)
|
|
1511
|
+
);
|
|
1512
|
+
const [ariaLiveMessage, setAriaLiveMessage] = createWritable(() => config().ariaLiveMessage);
|
|
1513
|
+
const [clickConnectStartHandle, setClickConnectStartHandle] = createSignal5(void 0);
|
|
1514
|
+
const [connection, setConnection] = createSignal5(initialConnection);
|
|
1515
|
+
const [domNode, setDomNode] = createSignal5(null);
|
|
1516
|
+
const [dragging, setDragging] = createSignal5(false);
|
|
1517
|
+
const [elementsSelectable, setElementsSelectable] = createWritable(
|
|
1518
|
+
() => config().elementsSelectable
|
|
1519
|
+
);
|
|
1520
|
+
const [height, setHeight] = createWritable(() => config().height);
|
|
1521
|
+
const [minZoom, _setMinZoom] = createWritable(() => config().minZoom);
|
|
1522
|
+
const [maxZoom, _setMaxZoom] = createWritable(() => config().maxZoom);
|
|
1523
|
+
const [nodesConnectable, setNodesConnectable] = createWritable(() => config().nodesDraggable);
|
|
1524
|
+
const [nodesDraggable, setNodesDraggable] = createWritable(() => config().nodesDraggable);
|
|
1525
|
+
const [panZoom, setPanZoom] = createSignal5(null);
|
|
1526
|
+
const [selectionRect, setSelectionRect] = createSignal5();
|
|
1527
|
+
const [selectionRectMode, setSelectionRectMode] = createSignal5();
|
|
1528
|
+
const [snapGrid, setSnapGrid] = createWritable(() => config().snapGrid);
|
|
1529
|
+
const [translateExtent, _setTranslateExtent] = createWritable(
|
|
1530
|
+
() => config().translateExtent ?? infiniteExtent3
|
|
1531
|
+
);
|
|
1532
|
+
const [width, setWidth] = createWritable(() => config().width);
|
|
1533
|
+
const [selectionKeyPressed, setSelectionKeyPressed] = createSignal5(false);
|
|
1534
|
+
const [multiselectionKeyPressed, setMultiselectionKeyPressed] = createSignal5(false);
|
|
1535
|
+
const [deleteKeyPressed, setDeleteKeyPressed] = createSignal5(false);
|
|
1536
|
+
const [panActivationKeyPressed, setPanActivationKeyPressed] = createSignal5(false);
|
|
1537
|
+
const [zoomActivationKeyPressed, setZoomActivationKeyPressed] = createSignal5(false);
|
|
1538
|
+
const nodesMemo = createWritableStore(() => config().nodes);
|
|
1539
|
+
const edgesMemo = createWritableStore(() => config().edges);
|
|
1540
|
+
const viewportMemo = createWritableStore(() => config().viewport ?? initialViewport);
|
|
1541
|
+
const transform = createMemo5(
|
|
1542
|
+
() => [viewportMemo.get().x, viewportMemo.get().y, viewportMemo.get().zoom]
|
|
1543
|
+
);
|
|
1544
|
+
const store = mergeProps8({ width: 0, height: 0 }, config, {
|
|
1545
|
+
get _colorMode() {
|
|
1546
|
+
return config().colorMode;
|
|
1547
|
+
},
|
|
1548
|
+
get _colorModeSSR() {
|
|
1549
|
+
return config().colorModeSSR;
|
|
1550
|
+
},
|
|
1551
|
+
get _connection() {
|
|
1552
|
+
return connection();
|
|
1553
|
+
},
|
|
1554
|
+
get _nodeTypes() {
|
|
1555
|
+
return config().nodeTypes;
|
|
1556
|
+
},
|
|
1557
|
+
get _edgeTypes() {
|
|
1558
|
+
return config().edgeTypes;
|
|
1559
|
+
},
|
|
1560
|
+
get ariaLabelConfig() {
|
|
1561
|
+
return ariaLabelConfig();
|
|
1562
|
+
},
|
|
1563
|
+
get ariaLiveMessage() {
|
|
1564
|
+
return ariaLiveMessage();
|
|
1565
|
+
},
|
|
1566
|
+
get clickConnectStartHandle() {
|
|
1567
|
+
return clickConnectStartHandle();
|
|
1568
|
+
},
|
|
1569
|
+
get colorMode() {
|
|
1570
|
+
return this._colorMode === "system" ? mediaPrefersDark() ? "dark" : "light" : this._colorMode;
|
|
1571
|
+
},
|
|
1572
|
+
get connection() {
|
|
1573
|
+
const state = connection();
|
|
1574
|
+
return {
|
|
1575
|
+
...state,
|
|
1576
|
+
from: state.inProgress ? pointToRendererPoint(state.from, this.transform) : state.from,
|
|
1577
|
+
to: state.inProgress ? pointToRendererPoint(state.to, this.transform) : state.to
|
|
1578
|
+
};
|
|
1579
|
+
},
|
|
1580
|
+
get domNode() {
|
|
1581
|
+
return domNode();
|
|
1582
|
+
},
|
|
1583
|
+
get dragging() {
|
|
1584
|
+
return dragging();
|
|
1585
|
+
},
|
|
1586
|
+
get edgeTypes() {
|
|
1587
|
+
return { ...InitialEdgeTypesMap, ...this._edgeTypes };
|
|
1588
|
+
},
|
|
1589
|
+
get elementsSelectable() {
|
|
1590
|
+
return elementsSelectable();
|
|
1591
|
+
},
|
|
1592
|
+
get height() {
|
|
1593
|
+
return height();
|
|
1594
|
+
},
|
|
1595
|
+
get lib() {
|
|
1596
|
+
return "solid";
|
|
1597
|
+
},
|
|
1598
|
+
get onError() {
|
|
1599
|
+
return config().onFlowError;
|
|
1600
|
+
},
|
|
1601
|
+
get maxZoom() {
|
|
1602
|
+
return maxZoom();
|
|
1603
|
+
},
|
|
1604
|
+
get minZoom() {
|
|
1605
|
+
return minZoom();
|
|
1606
|
+
},
|
|
1607
|
+
get nodes() {
|
|
1608
|
+
return nodesMemo.get();
|
|
1609
|
+
},
|
|
1610
|
+
get nodesConnectable() {
|
|
1611
|
+
return nodesConnectable();
|
|
1612
|
+
},
|
|
1613
|
+
get nodesDraggable() {
|
|
1614
|
+
return nodesDraggable();
|
|
1615
|
+
},
|
|
1616
|
+
get nodeTypes() {
|
|
1617
|
+
return { ...InitialNodeTypesMap, ...this._nodeTypes };
|
|
1618
|
+
},
|
|
1619
|
+
get panZoom() {
|
|
1620
|
+
return panZoom();
|
|
1621
|
+
},
|
|
1622
|
+
get selectedNodes() {
|
|
1623
|
+
return config().nodes.filter((node) => node.selected);
|
|
1624
|
+
},
|
|
1625
|
+
get selectedEdges() {
|
|
1626
|
+
return config().edges.filter((edge) => edge.selected);
|
|
1627
|
+
},
|
|
1628
|
+
get selectionRect() {
|
|
1629
|
+
return selectionRect();
|
|
1630
|
+
},
|
|
1631
|
+
get selectionRectMode() {
|
|
1632
|
+
return selectionRectMode();
|
|
1633
|
+
},
|
|
1634
|
+
get snapGrid() {
|
|
1635
|
+
return snapGrid();
|
|
1636
|
+
},
|
|
1637
|
+
get viewport() {
|
|
1638
|
+
return viewportMemo.get();
|
|
1639
|
+
},
|
|
1640
|
+
get viewportInitialized() {
|
|
1641
|
+
return panZoom() !== null;
|
|
1642
|
+
},
|
|
1643
|
+
get visibleEdgeIds() {
|
|
1644
|
+
return visibleEdgeIds();
|
|
1645
|
+
},
|
|
1646
|
+
get visibleNodeIds() {
|
|
1647
|
+
return visibleNodeIds();
|
|
1648
|
+
},
|
|
1649
|
+
get visibleNodesMap() {
|
|
1650
|
+
return visibleNodesMap();
|
|
1651
|
+
},
|
|
1652
|
+
get transform() {
|
|
1653
|
+
return transform();
|
|
1654
|
+
},
|
|
1655
|
+
get translateExtent() {
|
|
1656
|
+
return translateExtent();
|
|
1657
|
+
},
|
|
1658
|
+
get width() {
|
|
1659
|
+
return width();
|
|
1660
|
+
},
|
|
1661
|
+
// key press flags
|
|
1662
|
+
get selectionKeyPressed() {
|
|
1663
|
+
return selectionKeyPressed();
|
|
1664
|
+
},
|
|
1665
|
+
get multiselectionKeyPressed() {
|
|
1666
|
+
return multiselectionKeyPressed();
|
|
1667
|
+
},
|
|
1668
|
+
get deleteKeyPressed() {
|
|
1669
|
+
return deleteKeyPressed();
|
|
1670
|
+
},
|
|
1671
|
+
get panActivationKeyPressed() {
|
|
1672
|
+
return panActivationKeyPressed();
|
|
1673
|
+
},
|
|
1674
|
+
get zoomActivationKeyPressed() {
|
|
1675
|
+
return zoomActivationKeyPressed();
|
|
1676
|
+
}
|
|
1677
|
+
});
|
|
1678
|
+
const visibleNodesMap = createMemo5(() => {
|
|
1679
|
+
return nodeLookup;
|
|
1680
|
+
});
|
|
1681
|
+
const visibleNodeIds = createMemo5(() => {
|
|
1682
|
+
return Array.from(visibleNodesMap().values()).map((edge) => edge.id);
|
|
1683
|
+
});
|
|
1684
|
+
const visibleEdgeIds = createMemo5(() => {
|
|
1685
|
+
return Array.from(layoutedEdgesMap.values()).map((edge) => edge.id);
|
|
1686
|
+
});
|
|
1687
|
+
const getEdge = (id) => layoutedEdgesMap.get(id);
|
|
1688
|
+
const fitView = async (options) => {
|
|
1689
|
+
if (!store.panZoom) return false;
|
|
1690
|
+
return fitViewport(
|
|
1691
|
+
{
|
|
1692
|
+
nodes: nodeLookup,
|
|
1693
|
+
width: store.width,
|
|
1694
|
+
height: store.height,
|
|
1695
|
+
panZoom: store.panZoom,
|
|
1696
|
+
minZoom: store.minZoom,
|
|
1697
|
+
maxZoom: store.maxZoom
|
|
1698
|
+
},
|
|
1699
|
+
options ?? config().fitViewOptions
|
|
1700
|
+
);
|
|
1701
|
+
};
|
|
1702
|
+
const resetStoreValues = () => {
|
|
1703
|
+
setDragging(false);
|
|
1704
|
+
setSelectionRect(void 0);
|
|
1705
|
+
setSelectionRectMode(void 0);
|
|
1706
|
+
setSelectionKeyPressed(false);
|
|
1707
|
+
setMultiselectionKeyPressed(false);
|
|
1708
|
+
setDeleteKeyPressed(false);
|
|
1709
|
+
setPanActivationKeyPressed(false);
|
|
1710
|
+
setZoomActivationKeyPressed(false);
|
|
1711
|
+
setConnection({ ...initialConnection });
|
|
1712
|
+
setClickConnectStartHandle(void 0);
|
|
1713
|
+
viewportMemo.set(config().initialViewport ?? { x: 0, y: 0, zoom: 1 });
|
|
1714
|
+
setAriaLiveMessage("");
|
|
1715
|
+
setSnapGrid(void 0);
|
|
1716
|
+
};
|
|
1717
|
+
const addEdge2 = (edgeParams) => {
|
|
1718
|
+
edgesMemo.set((edges) => systemAddEdge(edgeParams, edges));
|
|
1719
|
+
};
|
|
1720
|
+
let initialFitViewApplied = false;
|
|
1721
|
+
const applyInitialFitView = (initialFitView) => {
|
|
1722
|
+
initialFitViewApplied = !initialFitView;
|
|
1723
|
+
};
|
|
1724
|
+
const updateNodePositions = (nodeDragItems, dragging2 = false) => {
|
|
1725
|
+
nodesMemo.set(
|
|
1726
|
+
(node) => nodeDragItems.has(node.id),
|
|
1727
|
+
produce((node) => {
|
|
1728
|
+
node.dragging = dragging2;
|
|
1729
|
+
node.position = nodeDragItems.get(node.id).position;
|
|
1730
|
+
})
|
|
1731
|
+
);
|
|
1732
|
+
};
|
|
1733
|
+
let pendingEntries = void 0;
|
|
1734
|
+
const requestUpdateNodeInternals = (updateEntries) => {
|
|
1735
|
+
if (pendingEntries) {
|
|
1736
|
+
pendingEntries.push(...updateEntries);
|
|
1737
|
+
return;
|
|
1738
|
+
}
|
|
1739
|
+
pendingEntries = updateEntries;
|
|
1740
|
+
requestIdleCallback(() => {
|
|
1741
|
+
batch2(() => {
|
|
1742
|
+
const updates = new Map(pendingEntries);
|
|
1743
|
+
pendingEntries = void 0;
|
|
1744
|
+
const { changes, updatedInternals } = systemUpdateNodeInternals(
|
|
1745
|
+
updates,
|
|
1746
|
+
nodeLookup,
|
|
1747
|
+
parentLookup,
|
|
1748
|
+
store.domNode,
|
|
1749
|
+
store.nodeOrigin
|
|
1750
|
+
);
|
|
1751
|
+
if (!updatedInternals) return;
|
|
1752
|
+
updateAbsolutePositions(nodeLookup, parentLookup, {
|
|
1753
|
+
nodeOrigin: store.nodeOrigin,
|
|
1754
|
+
nodeExtent: store.nodeExtent
|
|
1755
|
+
});
|
|
1756
|
+
const nodeToChange = changes.reduce(
|
|
1757
|
+
(acc, change) => {
|
|
1758
|
+
const node = nodeLookup.get(change.id)?.internals.userNode;
|
|
1759
|
+
if (!node) return acc;
|
|
1760
|
+
acc.set(node.id, change);
|
|
1761
|
+
return acc;
|
|
1762
|
+
},
|
|
1763
|
+
/* @__PURE__ */ new Map()
|
|
1764
|
+
);
|
|
1765
|
+
nodesMemo.set(
|
|
1766
|
+
(node) => nodeToChange.has(node.id),
|
|
1767
|
+
produce((node) => {
|
|
1768
|
+
const change = nodeToChange.get(node.id);
|
|
1769
|
+
switch (change.type) {
|
|
1770
|
+
case "dimensions": {
|
|
1771
|
+
if (change.setAttributes) {
|
|
1772
|
+
node.width = change.dimensions?.width ?? node.width;
|
|
1773
|
+
node.height = change.dimensions?.height ?? node.height;
|
|
1774
|
+
}
|
|
1775
|
+
node.measured = { ...node.measured, ...change.dimensions };
|
|
1776
|
+
break;
|
|
1777
|
+
}
|
|
1778
|
+
case "position":
|
|
1779
|
+
node.position = change.position ?? node.position;
|
|
1780
|
+
break;
|
|
1781
|
+
}
|
|
1782
|
+
})
|
|
1783
|
+
);
|
|
1784
|
+
if (!initialFitViewApplied) {
|
|
1785
|
+
initialFitViewApplied = true;
|
|
1786
|
+
void fitView();
|
|
1787
|
+
}
|
|
1788
|
+
});
|
|
1789
|
+
});
|
|
1790
|
+
};
|
|
1791
|
+
const zoomBy = async (factor, options) => {
|
|
1792
|
+
return store.panZoom ? store.panZoom.scaleBy(factor, options) : false;
|
|
1793
|
+
};
|
|
1794
|
+
const zoomIn = (options) => zoomBy(1.2, options);
|
|
1795
|
+
const zoomOut = (options) => zoomBy(1 / 1.2, options);
|
|
1796
|
+
const setCenter = async (x, y, options) => {
|
|
1797
|
+
const nextZoom = typeof options?.zoom !== "undefined" ? options.zoom : store.maxZoom;
|
|
1798
|
+
const currentPanZoom = store.panZoom;
|
|
1799
|
+
if (!currentPanZoom) {
|
|
1800
|
+
return Promise.resolve(false);
|
|
1801
|
+
}
|
|
1802
|
+
await currentPanZoom.setViewport(
|
|
1803
|
+
{
|
|
1804
|
+
x: store.width / 2 - x * nextZoom,
|
|
1805
|
+
y: store.height / 2 - y * nextZoom,
|
|
1806
|
+
zoom: nextZoom
|
|
1807
|
+
},
|
|
1808
|
+
{ duration: options?.duration, ease: options?.ease, interpolate: options?.interpolate }
|
|
1809
|
+
);
|
|
1810
|
+
return Promise.resolve(true);
|
|
1811
|
+
};
|
|
1812
|
+
const setPaneClickDistance = (distance) => {
|
|
1813
|
+
store.panZoom?.setClickDistance(distance);
|
|
1814
|
+
};
|
|
1815
|
+
const unselectNodesAndEdges = ({
|
|
1816
|
+
nodes: _nodes,
|
|
1817
|
+
edges
|
|
1818
|
+
} = {}) => {
|
|
1819
|
+
const nodesToUnselect = new Set((_nodes ? _nodes : store.nodes).map(({ id }) => id));
|
|
1820
|
+
if (nodesToUnselect.size) {
|
|
1821
|
+
nodesMemo.set(
|
|
1822
|
+
(node) => nodesToUnselect.has(node.id),
|
|
1823
|
+
produce((node) => {
|
|
1824
|
+
node.selected = false;
|
|
1825
|
+
})
|
|
1826
|
+
);
|
|
1827
|
+
}
|
|
1828
|
+
const edgesToUnselect = new Set((edges ? edges : store.edges).map(({ id }) => id));
|
|
1829
|
+
if (edgesToUnselect.size) {
|
|
1830
|
+
edgesMemo.set(
|
|
1831
|
+
(edge) => edgesToUnselect.has(edge.id),
|
|
1832
|
+
produce((edge) => {
|
|
1833
|
+
edge.selected = false;
|
|
1834
|
+
})
|
|
1835
|
+
);
|
|
1836
|
+
}
|
|
1837
|
+
};
|
|
1838
|
+
const addSelectedNodes = (ids) => {
|
|
1839
|
+
const isMultiSelection = store.multiselectionKeyPressed;
|
|
1840
|
+
const selectState = /* @__PURE__ */ new Map();
|
|
1841
|
+
nodesMemo.set(
|
|
1842
|
+
(node) => {
|
|
1843
|
+
const nodeWillBeSelected = ids.includes(node.id);
|
|
1844
|
+
const selected = isMultiSelection ? node.selected || nodeWillBeSelected : nodeWillBeSelected;
|
|
1845
|
+
selectState.set(node.id, selected);
|
|
1846
|
+
return node.selected !== selected;
|
|
1847
|
+
},
|
|
1848
|
+
produce((node) => {
|
|
1849
|
+
const internalNode = nodeLookup.get(node.id);
|
|
1850
|
+
if (internalNode) internalNode.selected = selectState.get(node.id);
|
|
1851
|
+
node.selected = selectState.get(node.id);
|
|
1852
|
+
})
|
|
1853
|
+
);
|
|
1854
|
+
if (!isMultiSelection) {
|
|
1855
|
+
unselectNodesAndEdges({ nodes: [] });
|
|
1856
|
+
}
|
|
1857
|
+
};
|
|
1858
|
+
const addSelectedEdges = (ids) => {
|
|
1859
|
+
const isMultiSelection = store.multiselectionKeyPressed;
|
|
1860
|
+
const edgeSelectState = /* @__PURE__ */ new Map();
|
|
1861
|
+
edgesMemo.set(
|
|
1862
|
+
(edge) => {
|
|
1863
|
+
const edgeWillBeSelected = ids.includes(edge.id);
|
|
1864
|
+
const selected = isMultiSelection ? edge.selected || edgeWillBeSelected : edgeWillBeSelected;
|
|
1865
|
+
edgeSelectState.set(edge.id, selected);
|
|
1866
|
+
return edge.selected !== selected;
|
|
1867
|
+
},
|
|
1868
|
+
produce((edge) => {
|
|
1869
|
+
edge.selected = edgeSelectState.get(edge.id);
|
|
1870
|
+
})
|
|
1871
|
+
);
|
|
1872
|
+
if (!isMultiSelection) {
|
|
1873
|
+
unselectNodesAndEdges({ edges: [] });
|
|
1874
|
+
}
|
|
1875
|
+
};
|
|
1876
|
+
const handleNodeSelection = (id, unselect, nodeRef) => {
|
|
1877
|
+
const node = store.nodes.find((n) => n.id === id);
|
|
1878
|
+
if (!node) {
|
|
1879
|
+
return;
|
|
1880
|
+
}
|
|
1881
|
+
batch2(() => {
|
|
1882
|
+
setSelectionRect(void 0);
|
|
1883
|
+
setSelectionRectMode(void 0);
|
|
1884
|
+
});
|
|
1885
|
+
if (!node.selected) {
|
|
1886
|
+
addSelectedNodes([id]);
|
|
1887
|
+
} else if (unselect || node.selected && store.multiselectionKeyPressed) {
|
|
1888
|
+
unselectNodesAndEdges({ nodes: [node], edges: [] });
|
|
1889
|
+
requestAnimationFrame(() => nodeRef?.blur());
|
|
1890
|
+
}
|
|
1891
|
+
};
|
|
1892
|
+
const handleEdgeSelection = (id) => {
|
|
1893
|
+
const edge = edgeLookup.get(id);
|
|
1894
|
+
if (!edge) {
|
|
1895
|
+
return;
|
|
1896
|
+
}
|
|
1897
|
+
const selectable = edge.selectable || store.elementsSelectable && typeof edge.selectable === "undefined";
|
|
1898
|
+
if (!selectable) return;
|
|
1899
|
+
batch2(() => {
|
|
1900
|
+
setSelectionRect(void 0);
|
|
1901
|
+
setSelectionRectMode(void 0);
|
|
1902
|
+
});
|
|
1903
|
+
if (!edge.selected) {
|
|
1904
|
+
addSelectedEdges([id]);
|
|
1905
|
+
} else if (edge.selected && store.multiselectionKeyPressed) {
|
|
1906
|
+
unselectNodesAndEdges({ nodes: [], edges: [edge] });
|
|
1907
|
+
}
|
|
1908
|
+
};
|
|
1909
|
+
const moveSelectedNodes = (direction, factor) => {
|
|
1910
|
+
const nodeUpdates = /* @__PURE__ */ new Map();
|
|
1911
|
+
const xVelo = store.snapGrid?.[0] ?? 5;
|
|
1912
|
+
const yVelo = store.snapGrid?.[1] ?? 5;
|
|
1913
|
+
const xDiff = direction.x * xVelo * factor;
|
|
1914
|
+
const yDiff = direction.y * yVelo * factor;
|
|
1915
|
+
for (const node of nodeLookup.values()) {
|
|
1916
|
+
const isSelected = node.selected && (node.draggable || store.nodesDraggable && typeof node.draggable === "undefined");
|
|
1917
|
+
if (!isSelected) {
|
|
1918
|
+
continue;
|
|
1919
|
+
}
|
|
1920
|
+
let nextPosition = {
|
|
1921
|
+
x: node.internals.positionAbsolute.x + xDiff,
|
|
1922
|
+
y: node.internals.positionAbsolute.y + yDiff
|
|
1923
|
+
};
|
|
1924
|
+
if (store.snapGrid) {
|
|
1925
|
+
nextPosition = snapPosition(nextPosition, store.snapGrid);
|
|
1926
|
+
}
|
|
1927
|
+
const { position, positionAbsolute } = calculateNodePosition({
|
|
1928
|
+
nodeId: node.id,
|
|
1929
|
+
nextPosition,
|
|
1930
|
+
nodeLookup,
|
|
1931
|
+
nodeExtent: store.nodeExtent,
|
|
1932
|
+
nodeOrigin: store.nodeOrigin,
|
|
1933
|
+
onError: store.onError
|
|
1934
|
+
});
|
|
1935
|
+
node.position = position;
|
|
1936
|
+
node.internals.positionAbsolute = positionAbsolute;
|
|
1937
|
+
nodeUpdates.set(node.id, node);
|
|
1938
|
+
}
|
|
1939
|
+
updateNodePositions(nodeUpdates);
|
|
1940
|
+
};
|
|
1941
|
+
const panBy = (delta) => {
|
|
1942
|
+
return panBySystem({
|
|
1943
|
+
delta,
|
|
1944
|
+
panZoom: store.panZoom,
|
|
1945
|
+
transform: store.transform,
|
|
1946
|
+
translateExtent: store.translateExtent,
|
|
1947
|
+
width: store.width,
|
|
1948
|
+
height: store.height
|
|
1949
|
+
});
|
|
1950
|
+
};
|
|
1951
|
+
const cancelConnection = () => {
|
|
1952
|
+
setConnection({ ...initialConnection });
|
|
1953
|
+
};
|
|
1954
|
+
const reset = () => {
|
|
1955
|
+
resetStoreValues();
|
|
1956
|
+
unselectNodesAndEdges();
|
|
1957
|
+
};
|
|
1958
|
+
createEffect4(() => {
|
|
1959
|
+
store.panZoom?.syncViewport(store.viewport);
|
|
1960
|
+
});
|
|
1961
|
+
createEffect4(() => {
|
|
1962
|
+
const _panZoom = panZoom();
|
|
1963
|
+
if (!_panZoom) return;
|
|
1964
|
+
createEffect4(() => {
|
|
1965
|
+
_panZoom.setScaleExtent([store.minZoom, store.maxZoom]);
|
|
1966
|
+
});
|
|
1967
|
+
createEffect4(() => {
|
|
1968
|
+
_panZoom.setTranslateExtent(store.translateExtent);
|
|
1969
|
+
});
|
|
1970
|
+
});
|
|
1971
|
+
createComputed(
|
|
1972
|
+
mapArray(
|
|
1973
|
+
() => store.nodes,
|
|
1974
|
+
(userNode) => {
|
|
1975
|
+
createComputed(() => {
|
|
1976
|
+
const internalNode = untrack(() => nodeLookup.get(userNode.id));
|
|
1977
|
+
const selectedNodeZ = store.elevateNodesOnSelect ? 1e3 : 0;
|
|
1978
|
+
const clampedPosition = clampPosition2(
|
|
1979
|
+
getNodePositionWithOrigin2(userNode, store.nodeOrigin),
|
|
1980
|
+
isCoordinateExtent2(userNode.extent) ? userNode.extent : store.nodeExtent,
|
|
1981
|
+
getNodeDimensions2(userNode)
|
|
1982
|
+
);
|
|
1983
|
+
const preservedMeasured = {
|
|
1984
|
+
width: userNode.measured?.width ?? internalNode?.measured?.width,
|
|
1985
|
+
height: userNode.measured?.height ?? internalNode?.measured?.height
|
|
1986
|
+
};
|
|
1987
|
+
const updatedNodeInternals = {
|
|
1988
|
+
...userNode,
|
|
1989
|
+
measured: preservedMeasured,
|
|
1990
|
+
internals: {
|
|
1991
|
+
positionAbsolute: clampedPosition,
|
|
1992
|
+
// If there is neither a user-provided nor a previously measured size,
|
|
1993
|
+
// reset handleBounds so that the node gets re-measured.
|
|
1994
|
+
handleBounds: !userNode.measured && !internalNode?.measured ? void 0 : internalNode?.internals.handleBounds,
|
|
1995
|
+
z: calculateZ(userNode, selectedNodeZ),
|
|
1996
|
+
userNode
|
|
1997
|
+
}
|
|
1998
|
+
};
|
|
1999
|
+
nodeLookup.set(userNode.id, updatedNodeInternals);
|
|
2000
|
+
if (userNode.parentId) {
|
|
2001
|
+
updateChildNode(updatedNodeInternals, nodeLookup, parentLookup, {
|
|
2002
|
+
nodeOrigin: store.nodeOrigin,
|
|
2003
|
+
nodeExtent: store.nodeExtent,
|
|
2004
|
+
elevateNodesOnSelect: store.elevateNodesOnSelect,
|
|
2005
|
+
checkEquality: true
|
|
2006
|
+
});
|
|
2007
|
+
}
|
|
2008
|
+
});
|
|
2009
|
+
onCleanup2(() => {
|
|
2010
|
+
});
|
|
2011
|
+
}
|
|
2012
|
+
)
|
|
2013
|
+
);
|
|
2014
|
+
createEffect4(() => {
|
|
2015
|
+
const currentIds = new Set(store.nodes.map((n) => n.id));
|
|
2016
|
+
for (const id of Array.from(nodeLookup.keys())) {
|
|
2017
|
+
if (!currentIds.has(id)) {
|
|
2018
|
+
nodeLookup.delete(id);
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
});
|
|
2022
|
+
createComputed(
|
|
2023
|
+
mapArray(
|
|
2024
|
+
() => store.edges,
|
|
2025
|
+
(edge) => {
|
|
2026
|
+
const {
|
|
2027
|
+
source: sourceNodeId,
|
|
2028
|
+
target: targetNodeId,
|
|
2029
|
+
sourceHandle = null,
|
|
2030
|
+
targetHandle = null
|
|
2031
|
+
} = edge;
|
|
2032
|
+
const connection2 = {
|
|
2033
|
+
edgeId: edge.id,
|
|
2034
|
+
source: sourceNodeId,
|
|
2035
|
+
target: targetNodeId,
|
|
2036
|
+
sourceHandle,
|
|
2037
|
+
targetHandle
|
|
2038
|
+
};
|
|
2039
|
+
const sourceKey = `${sourceNodeId}-${sourceHandle}--${targetNodeId}-${targetHandle}`;
|
|
2040
|
+
const targetKey = `${targetNodeId}-${targetHandle}--${sourceNodeId}-${sourceHandle}`;
|
|
2041
|
+
createComputed(() => {
|
|
2042
|
+
batch2(() => {
|
|
2043
|
+
addConnectionToLookup(
|
|
2044
|
+
"source",
|
|
2045
|
+
connection2,
|
|
2046
|
+
targetKey,
|
|
2047
|
+
connectionLookup,
|
|
2048
|
+
sourceNodeId,
|
|
2049
|
+
sourceHandle
|
|
2050
|
+
);
|
|
2051
|
+
addConnectionToLookup(
|
|
2052
|
+
"target",
|
|
2053
|
+
connection2,
|
|
2054
|
+
sourceKey,
|
|
2055
|
+
connectionLookup,
|
|
2056
|
+
targetNodeId,
|
|
2057
|
+
targetHandle
|
|
2058
|
+
);
|
|
2059
|
+
edgeLookup.set(edge.id, edge);
|
|
2060
|
+
});
|
|
2061
|
+
});
|
|
2062
|
+
createComputed(() => {
|
|
2063
|
+
const sourceNode = nodeLookup.get(edge.source);
|
|
2064
|
+
const targetNode = nodeLookup.get(edge.target);
|
|
2065
|
+
if (!sourceNode || !targetNode) return;
|
|
2066
|
+
if (store.onlyRenderVisibleElements) {
|
|
2067
|
+
const edgeVisible = isEdgeVisible({
|
|
2068
|
+
sourceNode,
|
|
2069
|
+
targetNode,
|
|
2070
|
+
width: store.width ?? 0,
|
|
2071
|
+
height: store.height ?? 0,
|
|
2072
|
+
transform: store.transform
|
|
2073
|
+
});
|
|
2074
|
+
if (!edgeVisible) return;
|
|
2075
|
+
store.visibleNodesMap.set(sourceNode.id, sourceNode);
|
|
2076
|
+
store.visibleNodesMap.set(targetNode.id, targetNode);
|
|
2077
|
+
}
|
|
2078
|
+
const edgePosition = getEdgePosition({
|
|
2079
|
+
id: edge.id,
|
|
2080
|
+
sourceNode,
|
|
2081
|
+
targetNode,
|
|
2082
|
+
sourceHandle: edge.sourceHandle || null,
|
|
2083
|
+
targetHandle: edge.targetHandle || null,
|
|
2084
|
+
connectionMode: store.connectionMode,
|
|
2085
|
+
onError: store.onError
|
|
2086
|
+
});
|
|
2087
|
+
if (!edgePosition) return;
|
|
2088
|
+
layoutedEdgesMap.set(edge.id, {
|
|
2089
|
+
...store.defaultEdgeOptions,
|
|
2090
|
+
...edge,
|
|
2091
|
+
...edgePosition,
|
|
2092
|
+
zIndex: getElevatedEdgeZIndex({
|
|
2093
|
+
selected: edge.selected,
|
|
2094
|
+
zIndex: edge.zIndex ?? store.defaultEdgeOptions.zIndex,
|
|
2095
|
+
sourceNode,
|
|
2096
|
+
targetNode,
|
|
2097
|
+
elevateOnSelect: store.elevateEdgesOnSelect
|
|
2098
|
+
}),
|
|
2099
|
+
sourceNode,
|
|
2100
|
+
targetNode,
|
|
2101
|
+
edge
|
|
2102
|
+
});
|
|
2103
|
+
});
|
|
2104
|
+
onCleanup2(() => {
|
|
2105
|
+
batch2(() => {
|
|
2106
|
+
edgeLookup.delete(edge.id);
|
|
2107
|
+
layoutedEdgesMap.delete(edge.id);
|
|
2108
|
+
removeConnectionFromLookup(
|
|
2109
|
+
"source",
|
|
2110
|
+
targetKey,
|
|
2111
|
+
connectionLookup,
|
|
2112
|
+
sourceNodeId,
|
|
2113
|
+
sourceHandle
|
|
2114
|
+
);
|
|
2115
|
+
removeConnectionFromLookup(
|
|
2116
|
+
"target",
|
|
2117
|
+
sourceKey,
|
|
2118
|
+
connectionLookup,
|
|
2119
|
+
targetNodeId,
|
|
2120
|
+
targetHandle
|
|
2121
|
+
);
|
|
2122
|
+
});
|
|
2123
|
+
});
|
|
2124
|
+
}
|
|
2125
|
+
)
|
|
2126
|
+
);
|
|
2127
|
+
createEffect4(() => {
|
|
2128
|
+
const currentIds = new Set(store.edges.map((e) => e.id));
|
|
2129
|
+
for (const id of Array.from(edgeLookup.keys())) {
|
|
2130
|
+
if (!currentIds.has(id)) {
|
|
2131
|
+
edgeLookup.delete(id);
|
|
2132
|
+
connectionLookup.delete(id);
|
|
2133
|
+
layoutedEdgesMap.delete(id);
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
});
|
|
2137
|
+
return {
|
|
2138
|
+
store,
|
|
2139
|
+
nodeLookup,
|
|
2140
|
+
edgeLookup,
|
|
2141
|
+
parentLookup,
|
|
2142
|
+
connectionLookup,
|
|
2143
|
+
actions: {
|
|
2144
|
+
getEdge,
|
|
2145
|
+
applyInitialFitView,
|
|
2146
|
+
resetStoreValues,
|
|
2147
|
+
requestUpdateNodeInternals,
|
|
2148
|
+
setAriaLabelConfig,
|
|
2149
|
+
setAriaLiveMessage,
|
|
2150
|
+
setClickConnectStartHandle,
|
|
2151
|
+
setConfig,
|
|
2152
|
+
setConnection,
|
|
2153
|
+
setDeleteKeyPressed,
|
|
2154
|
+
setDomNode,
|
|
2155
|
+
setDragging,
|
|
2156
|
+
get setEdges() {
|
|
2157
|
+
return edgesMemo.set;
|
|
2158
|
+
},
|
|
2159
|
+
setElementsSelectable,
|
|
2160
|
+
setHeight,
|
|
2161
|
+
setMultiselectionKeyPressed,
|
|
2162
|
+
get setNodes() {
|
|
2163
|
+
return nodesMemo.set;
|
|
2164
|
+
},
|
|
2165
|
+
setNodesConnectable,
|
|
2166
|
+
setNodesDraggable,
|
|
2167
|
+
setPanActivationKeyPressed,
|
|
2168
|
+
setPanZoom,
|
|
2169
|
+
setSelectionKeyPressed,
|
|
2170
|
+
setSelectionRect,
|
|
2171
|
+
setSelectionRectMode,
|
|
2172
|
+
get setViewport() {
|
|
2173
|
+
return viewportMemo.set;
|
|
2174
|
+
},
|
|
2175
|
+
setWidth,
|
|
2176
|
+
setZoomActivationKeyPressed,
|
|
2177
|
+
// Port Svelte Flow Actions to Solid Flow
|
|
2178
|
+
addEdge: addEdge2,
|
|
2179
|
+
updateNodePositions,
|
|
2180
|
+
zoomIn,
|
|
2181
|
+
zoomOut,
|
|
2182
|
+
fitView,
|
|
2183
|
+
setCenter,
|
|
2184
|
+
setPaneClickDistance,
|
|
2185
|
+
unselectNodesAndEdges,
|
|
2186
|
+
addSelectedNodes,
|
|
2187
|
+
addSelectedEdges,
|
|
2188
|
+
handleNodeSelection,
|
|
2189
|
+
handleEdgeSelection,
|
|
2190
|
+
moveSelectedNodes,
|
|
2191
|
+
panBy,
|
|
2192
|
+
cancelConnection,
|
|
2193
|
+
reset
|
|
2194
|
+
}
|
|
2195
|
+
};
|
|
2196
|
+
};
|
|
2197
|
+
|
|
2198
|
+
// src/components/contexts/flow.tsx
|
|
2199
|
+
var SolidFlowContext = createContext4();
|
|
2200
|
+
function useInternalSolidFlow() {
|
|
2201
|
+
const ctx = useContext4(SolidFlowContext);
|
|
2202
|
+
if (!ctx) {
|
|
2203
|
+
throw new Error(
|
|
2204
|
+
"solid-flow: Your application must be wrapped with <SolidFlow> in order to invoke useInternalSolidFlow within your components"
|
|
2205
|
+
);
|
|
2206
|
+
}
|
|
2207
|
+
return ctx;
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2210
|
+
// src/components/graph/marker/Marker.tsx
|
|
2211
|
+
import { mergeProps as mergeProps9, Show as Show7 } from "solid-js";
|
|
2212
|
+
var Marker = (props) => {
|
|
2213
|
+
const _props = mergeProps9(
|
|
2214
|
+
{
|
|
2215
|
+
markerUnits: "strokeWidth",
|
|
2216
|
+
orient: "auto-start-reverse",
|
|
2217
|
+
width: 12.5,
|
|
2218
|
+
height: 12.5,
|
|
2219
|
+
color: "none"
|
|
2220
|
+
},
|
|
2221
|
+
props
|
|
2222
|
+
);
|
|
2223
|
+
const color = () => _props.color ?? "var(--xy-edge-stroke)";
|
|
2224
|
+
return <marker
|
|
2225
|
+
class="solid-flow__arrowhead"
|
|
2226
|
+
id={_props.id}
|
|
2227
|
+
markerWidth={_props.width}
|
|
2228
|
+
markerHeight={_props.height}
|
|
2229
|
+
viewBox="-10 -10 20 20"
|
|
2230
|
+
markerUnits={_props.markerUnits}
|
|
2231
|
+
orient={_props.orient}
|
|
2232
|
+
refX="0"
|
|
2233
|
+
refY="0"
|
|
2234
|
+
>
|
|
2235
|
+
<Show7
|
|
2236
|
+
when={_props.type === "arrow"}
|
|
2237
|
+
fallback={<polyline
|
|
2238
|
+
class="arrowclosed"
|
|
2239
|
+
stroke={color()}
|
|
2240
|
+
fill={color()}
|
|
2241
|
+
stroke-linecap="round"
|
|
2242
|
+
stroke-linejoin="round"
|
|
2243
|
+
stroke-width={_props.strokeWidth}
|
|
2244
|
+
points="-5,-4 0,0 -5,4 -5,-4"
|
|
2245
|
+
/>}
|
|
2246
|
+
>
|
|
2247
|
+
<polyline
|
|
2248
|
+
class="arrow"
|
|
2249
|
+
stroke={color()}
|
|
2250
|
+
fill="none"
|
|
2251
|
+
stroke-linecap="round"
|
|
2252
|
+
stroke-linejoin="round"
|
|
2253
|
+
stroke-width={_props.strokeWidth}
|
|
2254
|
+
points="-5,-4 0,0 -5,4"
|
|
2255
|
+
/>
|
|
2256
|
+
</Show7>
|
|
2257
|
+
</marker>;
|
|
2258
|
+
};
|
|
2259
|
+
|
|
2260
|
+
// src/components/graph/marker/MarkerDefinition.tsx
|
|
2261
|
+
import { createMarkerIds } from "@xyflow/system";
|
|
2262
|
+
import { createMemo as createMemo6, For, Show as Show8 } from "solid-js";
|
|
2263
|
+
var MarkerDefinition = () => {
|
|
2264
|
+
const { store } = useInternalSolidFlow();
|
|
2265
|
+
const markers = createMemo6(() => {
|
|
2266
|
+
return createMarkerIds(store.edges, {
|
|
2267
|
+
id: store.id,
|
|
2268
|
+
defaultColor: store.defaultMarkerColor,
|
|
2269
|
+
defaultMarkerStart: store.defaultEdgeOptions.markerStart,
|
|
2270
|
+
defaultMarkerEnd: store.defaultEdgeOptions.markerEnd
|
|
2271
|
+
});
|
|
2272
|
+
});
|
|
2273
|
+
return <Show8 when={markers().length > 0}>
|
|
67
2274
|
<svg class="solid-flow__marker">
|
|
68
2275
|
<defs>
|
|
69
|
-
<
|
|
2276
|
+
<For each={markers()}>{(marker) => <Marker {...marker} />}</For>
|
|
70
2277
|
</defs>
|
|
71
2278
|
</svg>
|
|
72
|
-
</
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
{
|
|
86
|
-
|
|
87
|
-
{
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
</
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
2279
|
+
</Show8>;
|
|
2280
|
+
};
|
|
2281
|
+
|
|
2282
|
+
// src/components/container/EdgeRenderer.tsx
|
|
2283
|
+
var EdgeRenderer = (props) => {
|
|
2284
|
+
const { store } = useInternalSolidFlow();
|
|
2285
|
+
return <div class="solid-flow__edges">
|
|
2286
|
+
<MarkerDefinition />
|
|
2287
|
+
|
|
2288
|
+
<For2 each={store.visibleEdgeIds}>
|
|
2289
|
+
{(edgeId) => {
|
|
2290
|
+
return <EdgeWrapper
|
|
2291
|
+
edgeId={edgeId}
|
|
2292
|
+
onEdgeClick={props.onEdgeClick}
|
|
2293
|
+
onEdgeContextMenu={props.onEdgeContextMenu}
|
|
2294
|
+
onEdgePointerEnter={props.onEdgePointerEnter}
|
|
2295
|
+
onEdgePointerLeave={props.onEdgePointerLeave}
|
|
2296
|
+
/>;
|
|
2297
|
+
}}
|
|
2298
|
+
</For2>
|
|
2299
|
+
</div>;
|
|
2300
|
+
};
|
|
2301
|
+
|
|
2302
|
+
// src/components/container/NodeRenderer.tsx
|
|
2303
|
+
import { For as For3, onCleanup as onCleanup3 } from "solid-js";
|
|
2304
|
+
var NodeRenderer = (props) => {
|
|
2305
|
+
const { actions, store } = useInternalSolidFlow();
|
|
2306
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
2307
|
+
actions.requestUpdateNodeInternals(
|
|
2308
|
+
entries.map((entry) => {
|
|
2309
|
+
const id = entry.target.getAttribute("data-id");
|
|
2310
|
+
return [
|
|
2311
|
+
id,
|
|
2312
|
+
{
|
|
2313
|
+
id,
|
|
2314
|
+
nodeElement: entry.target,
|
|
2315
|
+
force: true
|
|
2316
|
+
}
|
|
2317
|
+
];
|
|
2318
|
+
})
|
|
2319
|
+
);
|
|
2320
|
+
});
|
|
2321
|
+
onCleanup3(() => {
|
|
2322
|
+
resizeObserver.disconnect();
|
|
2323
|
+
});
|
|
2324
|
+
return <div class="solid-flow__container solid-flow__nodes">
|
|
2325
|
+
<For3 each={store.visibleNodeIds}>
|
|
2326
|
+
{(nodeId) => {
|
|
2327
|
+
return <NodeWrapper
|
|
2328
|
+
nodeId={nodeId}
|
|
2329
|
+
resizeObserver={resizeObserver}
|
|
2330
|
+
nodeClickDistance={props.nodeClickDistance}
|
|
2331
|
+
onNodeClick={props.onNodeClick}
|
|
2332
|
+
onNodePointerEnter={props.onNodePointerEnter}
|
|
2333
|
+
onNodePointerMove={props.onNodePointerMove}
|
|
2334
|
+
onNodePointerLeave={props.onNodePointerLeave}
|
|
2335
|
+
onNodeDrag={props.onNodeDrag}
|
|
2336
|
+
onNodeDragStart={props.onNodeDragStart}
|
|
2337
|
+
onNodeDragStop={props.onNodeDragStop}
|
|
2338
|
+
onNodeContextMenu={props.onNodeContextMenu}
|
|
2339
|
+
/>;
|
|
2340
|
+
}}
|
|
2341
|
+
</For3>
|
|
2342
|
+
</div>;
|
|
2343
|
+
};
|
|
2344
|
+
|
|
2345
|
+
// src/components/container/Pane.tsx
|
|
2346
|
+
import { getEventPosition, getNodesInside as getNodesInside3, SelectionMode } from "@xyflow/system";
|
|
2347
|
+
import clsx7 from "clsx";
|
|
2348
|
+
import { batch as batch3 } from "solid-js";
|
|
2349
|
+
import { produce as produce2 } from "solid-js/store";
|
|
2350
|
+
var isSetEqual = (a, b) => {
|
|
2351
|
+
if (a.size !== b.size) return false;
|
|
2352
|
+
for (const item of a) {
|
|
2353
|
+
if (!b.has(item)) {
|
|
2354
|
+
return false;
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
return true;
|
|
2358
|
+
};
|
|
2359
|
+
var Pane = (props) => {
|
|
2360
|
+
const { store, nodeLookup, edgeLookup, connectionLookup, actions } = useInternalSolidFlow();
|
|
2361
|
+
let container;
|
|
2362
|
+
let containerBounds = null;
|
|
2363
|
+
let selectionInProgress = false;
|
|
2364
|
+
let selectedNodeIds = /* @__PURE__ */ new Set();
|
|
2365
|
+
let selectedEdgeIds = /* @__PURE__ */ new Set();
|
|
2366
|
+
const _panOnDrag = () => store.panActivationKeyPressed || props.panOnDrag;
|
|
2367
|
+
const isSelecting = () => store.selectionKeyPressed || store.selectionRect || props.selectionOnDrag && _panOnDrag() !== true;
|
|
2368
|
+
const hasActiveSelection = () => store.elementsSelectable && (isSelecting() || store.selectionRectMode === "user");
|
|
2369
|
+
const onClick = (event) => {
|
|
2370
|
+
if (event.target !== container) return;
|
|
2371
|
+
if (selectionInProgress) {
|
|
2372
|
+
selectionInProgress = false;
|
|
2373
|
+
return;
|
|
2374
|
+
}
|
|
2375
|
+
props.onPaneClick?.({ event });
|
|
2376
|
+
batch3(() => {
|
|
2377
|
+
actions.unselectNodesAndEdges();
|
|
2378
|
+
actions.setSelectionRectMode(void 0);
|
|
2379
|
+
});
|
|
2380
|
+
};
|
|
2381
|
+
const onPointerDown = (event) => {
|
|
2382
|
+
containerBounds = container?.getBoundingClientRect() ?? null;
|
|
2383
|
+
if (!store.elementsSelectable || !isSelecting() || event.button !== 0 || event.target !== container || !containerBounds) {
|
|
2384
|
+
return;
|
|
2385
|
+
}
|
|
2386
|
+
event.target?.setPointerCapture?.(event.pointerId);
|
|
2387
|
+
const { x, y } = getEventPosition(event, containerBounds);
|
|
2388
|
+
batch3(() => {
|
|
2389
|
+
actions.unselectNodesAndEdges();
|
|
2390
|
+
actions.setSelectionRect({
|
|
2391
|
+
width: 0,
|
|
2392
|
+
height: 0,
|
|
2393
|
+
startX: x,
|
|
2394
|
+
startY: y,
|
|
2395
|
+
x,
|
|
2396
|
+
y
|
|
2397
|
+
});
|
|
2398
|
+
});
|
|
2399
|
+
};
|
|
2400
|
+
const onPointerMove = (event) => {
|
|
2401
|
+
if (!isSelecting() || !containerBounds || !store.selectionRect) {
|
|
2402
|
+
return;
|
|
2403
|
+
}
|
|
2404
|
+
selectionInProgress = true;
|
|
2405
|
+
const mousePos = getEventPosition(event, containerBounds);
|
|
2406
|
+
const { startX = 0, startY = 0 } = store.selectionRect;
|
|
2407
|
+
const nextUserSelectRect = {
|
|
2408
|
+
...store.selectionRect,
|
|
2409
|
+
x: mousePos.x < startX ? mousePos.x : startX,
|
|
2410
|
+
y: mousePos.y < startY ? mousePos.y : startY,
|
|
2411
|
+
width: Math.abs(mousePos.x - startX),
|
|
2412
|
+
height: Math.abs(mousePos.y - startY)
|
|
2413
|
+
};
|
|
2414
|
+
const prevSelectedNodeIds = selectedNodeIds;
|
|
2415
|
+
const prevSelectedEdgeIds = selectedEdgeIds;
|
|
2416
|
+
selectedNodeIds = new Set(
|
|
2417
|
+
getNodesInside3(
|
|
2418
|
+
nodeLookup,
|
|
2419
|
+
nextUserSelectRect,
|
|
2420
|
+
store.transform,
|
|
2421
|
+
store.selectionMode === SelectionMode.Partial,
|
|
2422
|
+
true
|
|
2423
|
+
).map((n) => n.id)
|
|
2424
|
+
);
|
|
2425
|
+
const edgesSelectable = store.defaultEdgeOptions.selectable ?? true;
|
|
2426
|
+
selectedEdgeIds = /* @__PURE__ */ new Set();
|
|
2427
|
+
for (const nodeId of selectedNodeIds) {
|
|
2428
|
+
const connections = connectionLookup.get(nodeId);
|
|
2429
|
+
if (!connections) continue;
|
|
2430
|
+
for (const { edgeId } of connections.values()) {
|
|
2431
|
+
const edge = edgeLookup.get(edgeId);
|
|
2432
|
+
if (edge && (edge.selectable ?? edgesSelectable)) {
|
|
2433
|
+
selectedEdgeIds.add(edgeId);
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
batch3(() => {
|
|
2438
|
+
if (!isSetEqual(prevSelectedNodeIds, selectedNodeIds)) {
|
|
2439
|
+
const selectionMap = /* @__PURE__ */ new Map();
|
|
2440
|
+
actions.setNodes(
|
|
2441
|
+
(node) => {
|
|
2442
|
+
const isSelected = selectedNodeIds.has(node.id);
|
|
2443
|
+
selectionMap.set(node.id, isSelected);
|
|
2444
|
+
return !!node.selected !== isSelected;
|
|
2445
|
+
},
|
|
2446
|
+
produce2((node) => {
|
|
2447
|
+
node.selected = selectionMap.get(node.id);
|
|
2448
|
+
})
|
|
2449
|
+
);
|
|
2450
|
+
}
|
|
2451
|
+
if (!isSetEqual(prevSelectedEdgeIds, selectedEdgeIds)) {
|
|
2452
|
+
const selectionMap = /* @__PURE__ */ new Map();
|
|
2453
|
+
actions.setEdges(
|
|
2454
|
+
(edge) => {
|
|
2455
|
+
const isSelected = selectedEdgeIds.has(edge.id);
|
|
2456
|
+
selectionMap.set(edge.id, isSelected);
|
|
2457
|
+
return !!edge.selected !== isSelected;
|
|
2458
|
+
},
|
|
2459
|
+
produce2((edge) => {
|
|
2460
|
+
edge.selected = selectionMap.get(edge.id);
|
|
2461
|
+
})
|
|
2462
|
+
);
|
|
2463
|
+
}
|
|
2464
|
+
actions.setSelectionRectMode("user");
|
|
2465
|
+
actions.setSelectionRect(nextUserSelectRect);
|
|
2466
|
+
});
|
|
2467
|
+
};
|
|
2468
|
+
const onPointerUp = (event) => {
|
|
2469
|
+
if (event.button !== 0) return;
|
|
2470
|
+
event.target?.releasePointerCapture?.(event.pointerId);
|
|
2471
|
+
if (!isSelecting() && store.selectionRectMode === "user" && event.target === container) {
|
|
2472
|
+
onClick(event);
|
|
2473
|
+
}
|
|
2474
|
+
batch3(() => {
|
|
2475
|
+
actions.setSelectionRect(void 0);
|
|
2476
|
+
if (selectedNodeIds.size > 0) {
|
|
2477
|
+
actions.setSelectionRectMode("nodes");
|
|
2478
|
+
}
|
|
2479
|
+
});
|
|
2480
|
+
if (store.selectionKeyPressed) {
|
|
2481
|
+
selectionInProgress = false;
|
|
2482
|
+
}
|
|
2483
|
+
props.onSelectionEnd?.(event);
|
|
2484
|
+
};
|
|
2485
|
+
const onContextMenu = (event) => {
|
|
2486
|
+
if (event.target !== container) return;
|
|
2487
|
+
const result = _panOnDrag();
|
|
2488
|
+
if (Array.isArray(result) && result.includes(2)) {
|
|
2489
|
+
event.preventDefault();
|
|
2490
|
+
return;
|
|
2491
|
+
}
|
|
2492
|
+
props.onPaneContextMenu?.({ event });
|
|
2493
|
+
};
|
|
2494
|
+
return <div
|
|
2495
|
+
ref={container}
|
|
2496
|
+
class={clsx7("solid-flow__container solid-flow__pane", {
|
|
2497
|
+
selection: isSelecting(),
|
|
2498
|
+
dragging: store.dragging,
|
|
2499
|
+
draggable: props.panOnDrag === true || Array.isArray(props.panOnDrag) && props.panOnDrag.includes(0)
|
|
2500
|
+
})}
|
|
2501
|
+
onClick={(e) => hasActiveSelection() ? void 0 : onClick(e)}
|
|
2502
|
+
onPointerDown={(e) => hasActiveSelection() ? onPointerDown(e) : void 0}
|
|
2503
|
+
onPointerMove={(e) => hasActiveSelection() ? onPointerMove(e) : void 0}
|
|
2504
|
+
onPointerUp={(e) => hasActiveSelection() ? onPointerUp(e) : void 0}
|
|
2505
|
+
onContextMenu={onContextMenu}
|
|
2506
|
+
>
|
|
2507
|
+
{props.children}
|
|
2508
|
+
</div>;
|
|
2509
|
+
};
|
|
2510
|
+
|
|
2511
|
+
// src/components/container/Panel.tsx
|
|
2512
|
+
import clsx8 from "clsx";
|
|
2513
|
+
import { mergeProps as mergeProps10, splitProps as splitProps5 } from "solid-js";
|
|
2514
|
+
var Panel = (props) => {
|
|
2515
|
+
const { store } = useInternalSolidFlow();
|
|
2516
|
+
const _props = mergeProps10(
|
|
2517
|
+
{
|
|
2518
|
+
position: "top-right",
|
|
2519
|
+
style: {}
|
|
2520
|
+
},
|
|
2521
|
+
props
|
|
2522
|
+
);
|
|
2523
|
+
const [local, rest] = splitProps5(_props, ["class", "position", "style", "children"]);
|
|
2524
|
+
return <div
|
|
2525
|
+
class={clsx8(["solid-flow__panel", ...local.position.split("-"), local.class])}
|
|
2526
|
+
style={{
|
|
2527
|
+
"pointer-events": store.selectionRectMode ? "none" : void 0,
|
|
2528
|
+
...local.style
|
|
2529
|
+
}}
|
|
2530
|
+
{...rest}
|
|
2531
|
+
>
|
|
2532
|
+
{local.children}
|
|
2533
|
+
</div>;
|
|
2534
|
+
};
|
|
2535
|
+
|
|
2536
|
+
// src/components/container/Viewport.tsx
|
|
2537
|
+
var Viewport = (props) => {
|
|
2538
|
+
const { store } = useInternalSolidFlow();
|
|
2539
|
+
return <div
|
|
2540
|
+
class="solid-flow__container solid-flow__viewport xyflow__viewport"
|
|
2541
|
+
style={{
|
|
2542
|
+
transform: `translate(${store.viewport.x}px, ${store.viewport.y}px) scale(${store.viewport.zoom})`
|
|
2543
|
+
}}
|
|
2544
|
+
>
|
|
2545
|
+
{props.children}
|
|
2546
|
+
</div>;
|
|
2547
|
+
};
|
|
2548
|
+
|
|
2549
|
+
// src/components/container/ViewportPortal.tsx
|
|
2550
|
+
import { Show as Show9 } from "solid-js";
|
|
2551
|
+
import { Portal as Portal2 } from "solid-js/web";
|
|
2552
|
+
var ViewportPortal = (props) => {
|
|
2553
|
+
const { store } = useInternalSolidFlow();
|
|
2554
|
+
return <Show9 when={store.domNode}>
|
|
2555
|
+
{(domNode) => <Portal2 mount={domNode().querySelector(".solid-flow__viewport-portal") ?? void 0}>
|
|
2556
|
+
{props.children}
|
|
2557
|
+
</Portal2>}
|
|
2558
|
+
</Show9>;
|
|
2559
|
+
};
|
|
2560
|
+
|
|
2561
|
+
// src/components/container/Zoom.tsx
|
|
2562
|
+
import {
|
|
2563
|
+
XYPanZoom
|
|
2564
|
+
} from "@xyflow/system";
|
|
2565
|
+
import { batch as batch4, createEffect as createEffect5, onMount as onMount2 } from "solid-js";
|
|
2566
|
+
var Zoom = (props) => {
|
|
2567
|
+
let ref;
|
|
2568
|
+
const { store, actions } = useInternalSolidFlow();
|
|
2569
|
+
const viewPort = () => props.initialViewport || { x: 0, y: 0, zoom: 1 };
|
|
2570
|
+
const panOnDrag = () => store.panActivationKeyPressed || props.panOnDrag;
|
|
2571
|
+
const panOnScroll = () => store.panActivationKeyPressed || props.panOnScroll;
|
|
2572
|
+
const onTransformChange = (transform) => {
|
|
2573
|
+
const [x, y, zoom] = transform;
|
|
2574
|
+
actions.setViewport({ x, y, zoom });
|
|
2575
|
+
};
|
|
2576
|
+
onMount2(() => {
|
|
2577
|
+
const panZoomInstance = XYPanZoom({
|
|
2578
|
+
domNode: ref,
|
|
2579
|
+
minZoom: store.minZoom,
|
|
2580
|
+
maxZoom: store.maxZoom,
|
|
2581
|
+
translateExtent: store.translateExtent,
|
|
2582
|
+
viewport: viewPort(),
|
|
2583
|
+
paneClickDistance: props.paneClickDistance,
|
|
2584
|
+
onDraggingChange: actions.setDragging,
|
|
2585
|
+
onPanZoomStart: props.onMoveStart,
|
|
2586
|
+
onPanZoom: props.onMove,
|
|
2587
|
+
onPanZoomEnd: props.onMoveEnd
|
|
2588
|
+
});
|
|
2589
|
+
const vp = panZoomInstance.getViewport();
|
|
2590
|
+
if (viewPort().x !== vp.x || viewPort().y !== vp.y || viewPort().zoom !== vp.zoom) {
|
|
2591
|
+
onTransformChange([vp.x, vp.y, vp.zoom]);
|
|
2592
|
+
}
|
|
2593
|
+
batch4(() => {
|
|
2594
|
+
actions.setViewport(vp);
|
|
2595
|
+
actions.setPanZoom(panZoomInstance);
|
|
2596
|
+
});
|
|
2597
|
+
props.onViewportInitialized?.();
|
|
2598
|
+
createEffect5(() => {
|
|
2599
|
+
panZoomInstance.update({
|
|
2600
|
+
lib: store.lib,
|
|
2601
|
+
zoomActivationKeyPressed: store.zoomActivationKeyPressed,
|
|
2602
|
+
noPanClassName: store.noPanClass,
|
|
2603
|
+
noWheelClassName: store.noWheelClass,
|
|
2604
|
+
userSelectionActive: !!store.selectionRect,
|
|
2605
|
+
panOnScrollSpeed: 0.5,
|
|
2606
|
+
panOnDrag: panOnDrag(),
|
|
2607
|
+
panOnScroll: panOnScroll(),
|
|
2608
|
+
zoomOnScroll: props.zoomOnScroll,
|
|
2609
|
+
zoomOnDoubleClick: props.zoomOnDoubleClick,
|
|
2610
|
+
zoomOnPinch: props.zoomOnPinch,
|
|
2611
|
+
panOnScrollMode: props.panOnScrollMode,
|
|
2612
|
+
preventScrolling: typeof props.preventScrolling === "boolean" ? props.preventScrolling : true,
|
|
2613
|
+
onTransformChange
|
|
2614
|
+
});
|
|
2615
|
+
});
|
|
2616
|
+
});
|
|
2617
|
+
return <div ref={ref} class="solid-flow__container solid-flow__zoom">
|
|
2618
|
+
{props.children}
|
|
2619
|
+
</div>;
|
|
2620
|
+
};
|
|
2621
|
+
|
|
2622
|
+
// src/components/graph/connection/ConnectionLine.tsx
|
|
2623
|
+
import {
|
|
2624
|
+
getBezierPath as getBezierPath3,
|
|
2625
|
+
getConnectionStatus,
|
|
2626
|
+
getSmoothStepPath as getSmoothStepPath5,
|
|
2627
|
+
getStraightPath as getStraightPath3
|
|
2628
|
+
} from "@xyflow/system";
|
|
2629
|
+
import clsx9 from "clsx";
|
|
2630
|
+
import { Show as Show10 } from "solid-js";
|
|
2631
|
+
var ConnectionLine = (props) => {
|
|
2632
|
+
const { store } = useInternalSolidFlow();
|
|
2633
|
+
const connectionStatus = () => getConnectionStatus(store.connection.isValid);
|
|
2634
|
+
return <Show10 when={store.connection.inProgress}>
|
|
2635
|
+
<svg
|
|
2636
|
+
class="solid-flow__container solid-flow__connectionline"
|
|
2637
|
+
width={store.width}
|
|
2638
|
+
height={store.height}
|
|
2639
|
+
style={props.containerStyle}
|
|
2640
|
+
>
|
|
2641
|
+
<g class={clsx9(["solid-flow__connection", connectionStatus()])}>
|
|
2642
|
+
<Show10 when={props.component} fallback={<InternalConnectionLine style={props.style} />}>
|
|
2643
|
+
{(CustomComponent) => {
|
|
2644
|
+
const UserConnectionLine = CustomComponent();
|
|
2645
|
+
return <UserConnectionLine
|
|
2646
|
+
connectionLineType={store.connectionLineType}
|
|
2647
|
+
connectionLineStyle={props.style}
|
|
2648
|
+
fromNode={store.connection.fromNode}
|
|
2649
|
+
fromHandle={store.connection.fromHandle}
|
|
2650
|
+
fromX={store.connection.from.x}
|
|
2651
|
+
fromY={store.connection.from.y}
|
|
2652
|
+
toX={store.connection.to.x}
|
|
2653
|
+
toY={store.connection.to.y}
|
|
2654
|
+
fromPosition={store.connection.fromPosition}
|
|
2655
|
+
toPosition={store.connection.toPosition}
|
|
2656
|
+
connectionStatus={connectionStatus()}
|
|
2657
|
+
toNode={store.connection.toNode}
|
|
2658
|
+
toHandle={store.connection.toHandle}
|
|
2659
|
+
/>;
|
|
2660
|
+
}}
|
|
2661
|
+
</Show10>
|
|
100
2662
|
</g>
|
|
101
2663
|
</svg>
|
|
102
|
-
</
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
2664
|
+
</Show10>;
|
|
2665
|
+
};
|
|
2666
|
+
var InternalConnectionLine = (props) => {
|
|
2667
|
+
const { store } = useInternalSolidFlow();
|
|
2668
|
+
const path = () => {
|
|
2669
|
+
if (!store.connection.inProgress) return void 0;
|
|
2670
|
+
const pathParams = {
|
|
2671
|
+
sourceX: store.connection.from.x,
|
|
2672
|
+
sourceY: store.connection.from.y,
|
|
2673
|
+
sourcePosition: store.connection.fromPosition,
|
|
2674
|
+
targetX: store.connection.to.x,
|
|
2675
|
+
targetY: store.connection.to.y,
|
|
2676
|
+
targetPosition: store.connection.toPosition
|
|
2677
|
+
};
|
|
2678
|
+
switch (store.connectionLineType) {
|
|
2679
|
+
case "default": {
|
|
2680
|
+
const [path2] = getBezierPath3(pathParams);
|
|
2681
|
+
return path2;
|
|
2682
|
+
}
|
|
2683
|
+
case "straight": {
|
|
2684
|
+
const [path2] = getStraightPath3(pathParams);
|
|
2685
|
+
return path2;
|
|
2686
|
+
}
|
|
2687
|
+
case "step":
|
|
2688
|
+
case "smoothstep": {
|
|
2689
|
+
const [path2] = getSmoothStepPath5({
|
|
2690
|
+
...pathParams,
|
|
2691
|
+
borderRadius: store.connectionLineType === "step" ? 0 : void 0
|
|
2692
|
+
});
|
|
2693
|
+
return path2;
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
};
|
|
2697
|
+
return <path class="solid-flow__connection-path" fill="none" style={props.style} d={path()} />;
|
|
2698
|
+
};
|
|
2699
|
+
var ConnectionLine_default = ConnectionLine;
|
|
2700
|
+
|
|
2701
|
+
// src/components/graph/plugins/background/Background.tsx
|
|
2702
|
+
import clsx12 from "clsx";
|
|
2703
|
+
import { mergeProps as mergeProps13, Show as Show11 } from "solid-js";
|
|
2704
|
+
|
|
2705
|
+
// src/components/graph/plugins/background/DotPattern.tsx
|
|
2706
|
+
import clsx10 from "clsx";
|
|
2707
|
+
import { mergeProps as mergeProps11 } from "solid-js";
|
|
2708
|
+
var DotPattern = (props) => {
|
|
2709
|
+
const _props = mergeProps11({ radius: 5 }, props);
|
|
2710
|
+
return <circle
|
|
2711
|
+
class={clsx10("solid-flow__background-pattern", "dots", _props.class)}
|
|
2712
|
+
cx={_props.radius}
|
|
2713
|
+
cy={_props.radius}
|
|
2714
|
+
r={_props.radius}
|
|
2715
|
+
/>;
|
|
2716
|
+
};
|
|
2717
|
+
|
|
2718
|
+
// src/components/graph/plugins/background/LinePattern.tsx
|
|
2719
|
+
import { clsx as clsx11 } from "clsx";
|
|
2720
|
+
import { mergeProps as mergeProps12 } from "solid-js";
|
|
2721
|
+
var LinePattern = (props) => {
|
|
2722
|
+
const _props = mergeProps12({ lineWidth: 1 }, props);
|
|
2723
|
+
return <path
|
|
2724
|
+
stroke-width={_props.lineWidth}
|
|
2725
|
+
d={`M${_props.dimensions[0] / 2} 0 V${_props.dimensions[1]} M0 ${_props.dimensions[1] / 2} H${_props.dimensions[0]}`}
|
|
2726
|
+
class={clsx11("solid-flow__background-pattern", _props.variant, _props.class)}
|
|
2727
|
+
/>;
|
|
2728
|
+
};
|
|
2729
|
+
|
|
2730
|
+
// src/components/graph/plugins/background/Background.tsx
|
|
2731
|
+
var DEFAULT_SIZE = {
|
|
2732
|
+
dots: 1,
|
|
2733
|
+
lines: 1,
|
|
2734
|
+
cross: 6
|
|
2735
|
+
};
|
|
2736
|
+
var Background = (props) => {
|
|
2737
|
+
const _props = mergeProps13(
|
|
2738
|
+
{
|
|
2739
|
+
variant: "dots",
|
|
2740
|
+
gap: 20,
|
|
2741
|
+
size: 1,
|
|
2742
|
+
lineWidth: 1,
|
|
2743
|
+
style: {}
|
|
2744
|
+
},
|
|
2745
|
+
props
|
|
2746
|
+
);
|
|
2747
|
+
const { store } = useInternalSolidFlow();
|
|
2748
|
+
const isDots = () => _props.variant === "dots";
|
|
2749
|
+
const isCross = () => _props.variant === "cross";
|
|
2750
|
+
const patternId = () => `background-pattern-${store.id}-${_props.id ?? ""}`;
|
|
2751
|
+
const scaledSize = () => (_props.size ?? DEFAULT_SIZE[_props.variant]) * store.viewport.zoom;
|
|
2752
|
+
const gapXY = () => Array.isArray(_props.gap) ? _props.gap : [_props.gap, _props.gap];
|
|
2753
|
+
const scaledGap = () => [gapXY()[0] * store.viewport.zoom || 1, gapXY()[1] * store.viewport.zoom || 1];
|
|
2754
|
+
const patternDimensions = () => isCross() ? [scaledSize(), scaledSize()] : scaledGap();
|
|
2755
|
+
const patternOffset = () => isDots() ? [scaledSize() / 2, scaledSize() / 2] : [patternDimensions()[0] / 2, patternDimensions()[1] / 2];
|
|
2756
|
+
return <svg
|
|
2757
|
+
data-testid="solid-flow__background"
|
|
2758
|
+
class={clsx12("solid-flow__container solid-flow__background", _props.class)}
|
|
2759
|
+
style={{
|
|
2760
|
+
"--xy-background-color-props": _props.bgColor,
|
|
2761
|
+
"--xy-background-pattern-color-props": _props.patternColor,
|
|
2762
|
+
..._props.style
|
|
2763
|
+
}}
|
|
2764
|
+
>
|
|
2765
|
+
<pattern
|
|
2766
|
+
id={patternId()}
|
|
2767
|
+
x={store.viewport.x % scaledGap()[0]}
|
|
2768
|
+
y={store.viewport.y % scaledGap()[1]}
|
|
2769
|
+
width={scaledGap()[0]}
|
|
2770
|
+
height={scaledGap()[1]}
|
|
2771
|
+
patternUnits="userSpaceOnUse"
|
|
2772
|
+
patternTransform={`translate(-${patternOffset()[0]},-${patternOffset()[1]})`}
|
|
2773
|
+
>
|
|
2774
|
+
<Show11
|
|
2775
|
+
when={!isDots()}
|
|
2776
|
+
fallback={<DotPattern radius={scaledSize() / 2} class={_props.patternClass} />}
|
|
2777
|
+
>
|
|
2778
|
+
<LinePattern
|
|
2779
|
+
class={_props.patternClass}
|
|
2780
|
+
dimensions={patternDimensions()}
|
|
2781
|
+
variant={_props.variant}
|
|
2782
|
+
lineWidth={_props.lineWidth}
|
|
2783
|
+
/>
|
|
2784
|
+
</Show11>
|
|
107
2785
|
</pattern>
|
|
108
|
-
<rect x="0"y="0"width="100%"height="100%"fill={`url(#${
|
|
109
|
-
</svg
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
2786
|
+
<rect x="0" y="0" width="100%" height="100%" fill={`url(#${patternId()})`} />
|
|
2787
|
+
</svg>;
|
|
2788
|
+
};
|
|
2789
|
+
|
|
2790
|
+
// src/components/graph/plugins/controls/ControlButton.tsx
|
|
2791
|
+
import clsx13 from "clsx";
|
|
2792
|
+
import { splitProps as splitProps6 } from "solid-js";
|
|
2793
|
+
var ControlButton = (props) => {
|
|
2794
|
+
const [local, rest] = splitProps6(props, [
|
|
2795
|
+
"class",
|
|
2796
|
+
"bgColor",
|
|
2797
|
+
"bgColorHover",
|
|
2798
|
+
"color",
|
|
2799
|
+
"colorHover",
|
|
2800
|
+
"borderColor",
|
|
2801
|
+
"onClick",
|
|
2802
|
+
"children"
|
|
2803
|
+
]);
|
|
2804
|
+
const style = () => Object.entries({
|
|
2805
|
+
"--xy-controls-button-background-color-props": local.bgColor,
|
|
2806
|
+
"--xy-controls-button-background-color-hover-props": local.bgColorHover,
|
|
2807
|
+
"--xy-controls-button-color-props": local.color,
|
|
2808
|
+
"--xy-controls-button-color-hover-props": local.colorHover,
|
|
2809
|
+
"--xy-controls-button-border-color-props": local.borderColor
|
|
2810
|
+
}).filter(([_, value]) => value !== void 0).reduce((acc, [key, value]) => {
|
|
2811
|
+
acc[key] = value;
|
|
2812
|
+
return acc;
|
|
2813
|
+
}, {});
|
|
2814
|
+
return <button
|
|
2815
|
+
type="button"
|
|
2816
|
+
class={clsx13("solid-flow__controls-button", local.class)}
|
|
2817
|
+
onClick={(e) => local.onClick?.(e)}
|
|
2818
|
+
style={style()}
|
|
2819
|
+
{...rest}
|
|
2820
|
+
>
|
|
2821
|
+
{local.children}
|
|
2822
|
+
</button>;
|
|
2823
|
+
};
|
|
2824
|
+
|
|
2825
|
+
// src/components/graph/plugins/controls/Controls.tsx
|
|
2826
|
+
import clsx14 from "clsx";
|
|
2827
|
+
import { batch as batch5, mergeProps as mergeProps14, Show as Show12, splitProps as splitProps7 } from "solid-js";
|
|
2828
|
+
|
|
2829
|
+
// src/components/graph/plugins/controls/icons/Fit.tsx
|
|
2830
|
+
var Fit = () => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 30">
|
|
2831
|
+
<path d="M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z" />
|
|
2832
|
+
</svg>;
|
|
2833
|
+
|
|
2834
|
+
// src/components/graph/plugins/controls/icons/Lock.tsx
|
|
2835
|
+
var Lock = () => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 32">
|
|
2836
|
+
<path d="M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z" />
|
|
2837
|
+
</svg>;
|
|
2838
|
+
|
|
2839
|
+
// src/components/graph/plugins/controls/icons/Minus.tsx
|
|
2840
|
+
var Minus = () => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 5">
|
|
2841
|
+
<path d="M0 0h32v4.2H0z" />
|
|
2842
|
+
</svg>;
|
|
2843
|
+
|
|
2844
|
+
// src/components/graph/plugins/controls/icons/Plus.tsx
|
|
2845
|
+
var Plus = () => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
2846
|
+
<path d="M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z" />
|
|
2847
|
+
</svg>;
|
|
2848
|
+
|
|
2849
|
+
// src/components/graph/plugins/controls/icons/Unlock.tsx
|
|
2850
|
+
var Unlock = () => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 32">
|
|
2851
|
+
<path d="M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z" />
|
|
2852
|
+
</svg>;
|
|
2853
|
+
|
|
2854
|
+
// src/components/graph/plugins/controls/Controls.tsx
|
|
2855
|
+
var Controls = (props) => {
|
|
2856
|
+
const { store, actions } = useInternalSolidFlow();
|
|
2857
|
+
const _props = mergeProps14(
|
|
2858
|
+
{
|
|
2859
|
+
position: "bottom-left",
|
|
2860
|
+
showZoom: true,
|
|
2861
|
+
showFitView: true,
|
|
2862
|
+
showLock: true,
|
|
2863
|
+
orientation: "vertical"
|
|
2864
|
+
},
|
|
2865
|
+
props
|
|
2866
|
+
);
|
|
2867
|
+
const [local, rest] = splitProps7(_props, [
|
|
2868
|
+
"class",
|
|
2869
|
+
"position",
|
|
2870
|
+
"showZoom",
|
|
2871
|
+
"showFitView",
|
|
2872
|
+
"showLock",
|
|
2873
|
+
"orientation",
|
|
2874
|
+
"fitViewOptions",
|
|
2875
|
+
"beforeControls",
|
|
2876
|
+
"afterControls",
|
|
2877
|
+
"buttonBgColor",
|
|
2878
|
+
"buttonBgColorHover",
|
|
2879
|
+
"buttonColor",
|
|
2880
|
+
"buttonColorHover",
|
|
2881
|
+
"buttonBorderColor",
|
|
2882
|
+
"style",
|
|
2883
|
+
"children"
|
|
2884
|
+
]);
|
|
2885
|
+
const getMinZoomReached = () => store.viewport.zoom <= store.minZoom;
|
|
2886
|
+
const getMaxZoomReached = () => store.viewport.zoom >= store.maxZoom;
|
|
2887
|
+
const getIsInteractive = () => store.nodesDraggable || store.nodesConnectable || store.elementsSelectable;
|
|
2888
|
+
const onZoomInHandler = () => {
|
|
2889
|
+
void actions.zoomIn();
|
|
2890
|
+
};
|
|
2891
|
+
const onZoomOutHandler = () => {
|
|
2892
|
+
void actions.zoomOut();
|
|
2893
|
+
};
|
|
2894
|
+
const onFitViewHandler = () => {
|
|
2895
|
+
void actions.fitView(local.fitViewOptions);
|
|
2896
|
+
};
|
|
2897
|
+
const onToggleInteractivity = () => {
|
|
2898
|
+
const newValue = !getIsInteractive();
|
|
2899
|
+
batch5(() => {
|
|
2900
|
+
actions.setNodesDraggable(newValue);
|
|
2901
|
+
actions.setNodesConnectable(newValue);
|
|
2902
|
+
actions.setElementsSelectable(newValue);
|
|
2903
|
+
});
|
|
2904
|
+
};
|
|
2905
|
+
const buttonProps = () => ({
|
|
2906
|
+
bgColor: local.buttonBgColor,
|
|
2907
|
+
bgColorHover: local.buttonBgColorHover,
|
|
2908
|
+
color: local.buttonColor,
|
|
2909
|
+
colorHover: local.buttonColorHover,
|
|
2910
|
+
borderColor: local.buttonBorderColor
|
|
2911
|
+
});
|
|
2912
|
+
return <Panel
|
|
2913
|
+
class={clsx14(["solid-flow__controls", local.orientation, local.class])}
|
|
2914
|
+
position={local.position}
|
|
2915
|
+
data-testid="solid-flow__controls"
|
|
2916
|
+
aria-label={store.ariaLabelConfig["controls.ariaLabel"]}
|
|
2917
|
+
style={local.style}
|
|
2918
|
+
{...rest}
|
|
2919
|
+
>
|
|
2920
|
+
{local.beforeControls}
|
|
2921
|
+
<Show12 when={local.showZoom}>
|
|
124
2922
|
<>
|
|
125
|
-
<
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
2923
|
+
<ControlButton
|
|
2924
|
+
onClick={onZoomInHandler}
|
|
2925
|
+
class="solid-flow__controls-zoomin"
|
|
2926
|
+
title={store.ariaLabelConfig["controls.zoomIn.ariaLabel"]}
|
|
2927
|
+
aria-label={store.ariaLabelConfig["controls.zoomIn.ariaLabel"]}
|
|
2928
|
+
disabled={getMaxZoomReached()}
|
|
2929
|
+
{...buttonProps()}
|
|
2930
|
+
>
|
|
2931
|
+
<Plus />
|
|
2932
|
+
</ControlButton>
|
|
2933
|
+
<ControlButton
|
|
2934
|
+
onClick={onZoomOutHandler}
|
|
2935
|
+
class="solid-flow__controls-zoomout"
|
|
2936
|
+
title={store.ariaLabelConfig["controls.zoomOut.ariaLabel"]}
|
|
2937
|
+
aria-label={store.ariaLabelConfig["controls.zoomOut.ariaLabel"]}
|
|
2938
|
+
disabled={getMinZoomReached()}
|
|
2939
|
+
{...buttonProps()}
|
|
2940
|
+
>
|
|
2941
|
+
<Minus />
|
|
2942
|
+
</ControlButton>
|
|
131
2943
|
</>
|
|
132
|
-
</
|
|
133
|
-
<
|
|
134
|
-
<
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
2944
|
+
</Show12>
|
|
2945
|
+
<Show12 when={local.showFitView}>
|
|
2946
|
+
<ControlButton
|
|
2947
|
+
class="solid-flow__controls-fitview"
|
|
2948
|
+
onClick={onFitViewHandler}
|
|
2949
|
+
title={store.ariaLabelConfig["controls.fitView.ariaLabel"]}
|
|
2950
|
+
aria-label={store.ariaLabelConfig["controls.fitView.ariaLabel"]}
|
|
2951
|
+
{...buttonProps()}
|
|
2952
|
+
>
|
|
2953
|
+
<Fit />
|
|
2954
|
+
</ControlButton>
|
|
2955
|
+
</Show12>
|
|
2956
|
+
<Show12 when={local.showLock}>
|
|
2957
|
+
<ControlButton
|
|
2958
|
+
class="solid-flow__controls-interactive"
|
|
2959
|
+
onClick={onToggleInteractivity}
|
|
2960
|
+
title={store.ariaLabelConfig["controls.interactive.ariaLabel"]}
|
|
2961
|
+
aria-label={store.ariaLabelConfig["controls.interactive.ariaLabel"]}
|
|
2962
|
+
{...buttonProps()}
|
|
2963
|
+
>
|
|
2964
|
+
<Show12 when={getIsInteractive()} fallback={<Lock />}>
|
|
2965
|
+
<Unlock />
|
|
2966
|
+
</Show12>
|
|
2967
|
+
</ControlButton>
|
|
2968
|
+
</Show12>
|
|
2969
|
+
{local.children}
|
|
2970
|
+
{local.afterControls}
|
|
2971
|
+
</Panel>;
|
|
2972
|
+
};
|
|
2973
|
+
|
|
2974
|
+
// src/components/graph/plugins/minimap/MiniMap.tsx
|
|
2975
|
+
import {
|
|
2976
|
+
getBoundsOfRects as getBoundsOfRects2,
|
|
2977
|
+
getInternalNodesBounds as getInternalNodesBounds2,
|
|
2978
|
+
getNodeDimensions as getNodeDimensions3,
|
|
2979
|
+
nodeHasDimensions as nodeHasDimensions2,
|
|
2980
|
+
XYMinimap
|
|
2981
|
+
} from "@xyflow/system";
|
|
2982
|
+
import clsx16 from "clsx";
|
|
2983
|
+
import {
|
|
2984
|
+
createEffect as createEffect6,
|
|
2985
|
+
createMemo as createMemo7,
|
|
2986
|
+
createSignal as createSignal6,
|
|
2987
|
+
Index,
|
|
2988
|
+
mergeProps as mergeProps16,
|
|
2989
|
+
onCleanup as onCleanup4,
|
|
2990
|
+
onMount as onMount3,
|
|
2991
|
+
Show as Show13,
|
|
2992
|
+
splitProps as splitProps8
|
|
2993
|
+
} from "solid-js";
|
|
2994
|
+
|
|
2995
|
+
// src/components/graph/plugins/minimap/MiniMapNode.tsx
|
|
2996
|
+
import clsx15 from "clsx";
|
|
2997
|
+
import { mergeProps as mergeProps15 } from "solid-js";
|
|
2998
|
+
var MiniMapNode = (props) => {
|
|
2999
|
+
const _props = mergeProps15(
|
|
3000
|
+
{
|
|
3001
|
+
borderRadius: 5,
|
|
3002
|
+
width: 0,
|
|
3003
|
+
height: 0
|
|
3004
|
+
},
|
|
3005
|
+
props
|
|
3006
|
+
);
|
|
3007
|
+
const style = () => Object.entries({
|
|
3008
|
+
fill: _props.color,
|
|
3009
|
+
stroke: _props.strokeColor,
|
|
3010
|
+
"stroke-width": _props.strokeWidth
|
|
3011
|
+
}).filter(([_, value]) => value !== void 0).reduce((acc, [key, value]) => {
|
|
3012
|
+
acc[key] = value;
|
|
3013
|
+
return acc;
|
|
3014
|
+
}, {});
|
|
3015
|
+
return <rect
|
|
3016
|
+
class={clsx15("solid-flow__minimap-node", { selected: _props.selected }, _props.class)}
|
|
3017
|
+
x={_props.x}
|
|
3018
|
+
y={_props.y}
|
|
3019
|
+
rx={_props.borderRadius}
|
|
3020
|
+
ry={_props.borderRadius}
|
|
3021
|
+
width={_props.width}
|
|
3022
|
+
height={_props.height}
|
|
3023
|
+
shape-rendering={_props.shapeRendering}
|
|
3024
|
+
style={style()}
|
|
3025
|
+
/>;
|
|
3026
|
+
};
|
|
3027
|
+
|
|
3028
|
+
// src/components/graph/plugins/minimap/MiniMap.tsx
|
|
3029
|
+
var getAttrFunction = (func) => func instanceof Function ? func : () => func;
|
|
3030
|
+
var MiniMap = (props) => {
|
|
3031
|
+
const { store, nodeLookup } = useInternalSolidFlow();
|
|
3032
|
+
const _props = mergeProps16(
|
|
3033
|
+
{
|
|
3034
|
+
position: "bottom-right",
|
|
3035
|
+
nodeClass: "",
|
|
3036
|
+
nodeStrokeColor: "transparent",
|
|
3037
|
+
pannable: true,
|
|
3038
|
+
zoomable: true,
|
|
3039
|
+
width: 200,
|
|
3040
|
+
height: 150,
|
|
3041
|
+
nodeBorderRadius: 5,
|
|
3042
|
+
nodeStrokeWidth: 2,
|
|
3043
|
+
style: {}
|
|
3044
|
+
},
|
|
3045
|
+
props
|
|
3046
|
+
);
|
|
3047
|
+
const [local, paneProps] = splitProps8(_props, [
|
|
3048
|
+
"class",
|
|
3049
|
+
"style",
|
|
3050
|
+
"position",
|
|
3051
|
+
"nodeClass",
|
|
3052
|
+
"nodeStrokeColor",
|
|
3053
|
+
"nodeColor",
|
|
3054
|
+
"pannable",
|
|
3055
|
+
"zoomable",
|
|
3056
|
+
"inversePan",
|
|
3057
|
+
"zoomStep",
|
|
3058
|
+
"bgColor",
|
|
3059
|
+
"width",
|
|
3060
|
+
"height",
|
|
3061
|
+
"maskColor",
|
|
3062
|
+
"maskStrokeColor",
|
|
3063
|
+
"maskStrokeWidth",
|
|
3064
|
+
"nodeBorderRadius",
|
|
3065
|
+
"nodeStrokeWidth"
|
|
3066
|
+
]);
|
|
3067
|
+
const nodeColorFunc = () => local.nodeColor === void 0 ? void 0 : getAttrFunction(local.nodeColor);
|
|
3068
|
+
const nodeStrokeColorFunc = () => getAttrFunction(local.nodeStrokeColor);
|
|
3069
|
+
const nodeClassFunc = () => getAttrFunction(local.nodeClass);
|
|
3070
|
+
const shapeRendering = () => (
|
|
3071
|
+
// @ts-expect-error - TS doesn't know about chrome
|
|
3072
|
+
typeof window === "undefined" || !!window.chrome ? "crispEdges" : "geometricPrecision"
|
|
3073
|
+
);
|
|
3074
|
+
const labelledBy = createMemo7(() => `solid-flow__minimap-desc-${store.id}`);
|
|
3075
|
+
const getViewBB = () => ({
|
|
3076
|
+
x: -store.viewport.x / store.viewport.zoom,
|
|
3077
|
+
y: -store.viewport.y / store.viewport.zoom,
|
|
3078
|
+
width: store.width / store.viewport.zoom,
|
|
3079
|
+
height: store.height / store.viewport.zoom
|
|
3080
|
+
});
|
|
3081
|
+
const getBoundingRect = () => {
|
|
3082
|
+
const viewBB = getViewBB();
|
|
3083
|
+
return nodeLookup.size > 0 ? getBoundsOfRects2(getInternalNodesBounds2(nodeLookup), viewBB) : viewBB;
|
|
3084
|
+
};
|
|
3085
|
+
const getScaledWidth = () => getBoundingRect().width / local.width;
|
|
3086
|
+
const getScaledHeight = () => getBoundingRect().height / local.height;
|
|
3087
|
+
const getViewScale = () => Math.max(getScaledWidth(), getScaledHeight());
|
|
3088
|
+
const getViewWidth = () => getViewScale() * local.width;
|
|
3089
|
+
const getViewHeight = () => getViewScale() * local.height;
|
|
3090
|
+
const getOffset = () => 5 * getViewScale();
|
|
3091
|
+
const getX = () => {
|
|
3092
|
+
const boundingRect = getBoundingRect();
|
|
3093
|
+
return boundingRect.x - (getViewWidth() - boundingRect.width) / 2 - getOffset();
|
|
3094
|
+
};
|
|
3095
|
+
const getY = () => {
|
|
3096
|
+
const boundingRect = getBoundingRect();
|
|
3097
|
+
return boundingRect.y - (getViewHeight() - boundingRect.height) / 2 - getOffset();
|
|
3098
|
+
};
|
|
3099
|
+
const getViewboxWidth = () => getViewWidth() + getOffset() * 2;
|
|
3100
|
+
const getViewboxHeight = () => getViewHeight() + getOffset() * 2;
|
|
3101
|
+
const strokeWidth = () => local.maskStrokeWidth ? local.maskStrokeWidth * getViewScale() : void 0;
|
|
3102
|
+
let prevNodeIds = [];
|
|
3103
|
+
const nodeIds = () => {
|
|
3104
|
+
const currentNodeIds = store.nodes.map((node) => node.id);
|
|
3105
|
+
const currentSet = new Set(currentNodeIds);
|
|
3106
|
+
if (prevNodeIds.length !== currentNodeIds.length || !prevNodeIds.every((id) => currentSet.has(id))) {
|
|
3107
|
+
prevNodeIds = currentNodeIds;
|
|
3108
|
+
}
|
|
3109
|
+
return prevNodeIds;
|
|
3110
|
+
};
|
|
3111
|
+
return <Panel
|
|
3112
|
+
position={local.position}
|
|
3113
|
+
data-testid="solid-flow__minimap"
|
|
3114
|
+
class={clsx16(["solid-flow__minimap", local.class])}
|
|
3115
|
+
style={{
|
|
3116
|
+
"--xy-minimap-background-color-props": local.bgColor,
|
|
3117
|
+
...local.style
|
|
3118
|
+
}}
|
|
3119
|
+
{...paneProps}
|
|
3120
|
+
>
|
|
3121
|
+
<Show13 when={store.panZoom}>
|
|
3122
|
+
{(panZoom) => {
|
|
3123
|
+
const [ref, setRef] = createSignal6();
|
|
3124
|
+
onMount3(() => {
|
|
3125
|
+
const minimap = XYMinimap({
|
|
3126
|
+
domNode: ref(),
|
|
3127
|
+
panZoom: panZoom(),
|
|
3128
|
+
getTransform: () => store.transform,
|
|
3129
|
+
getViewScale
|
|
3130
|
+
});
|
|
3131
|
+
createEffect6(() => {
|
|
3132
|
+
minimap.update({
|
|
3133
|
+
translateExtent: store.translateExtent,
|
|
3134
|
+
width: store.width,
|
|
3135
|
+
height: store.height,
|
|
3136
|
+
inversePan: local.inversePan,
|
|
3137
|
+
zoomStep: local.zoomStep,
|
|
3138
|
+
pannable: local.pannable,
|
|
3139
|
+
zoomable: local.zoomable
|
|
3140
|
+
});
|
|
3141
|
+
});
|
|
3142
|
+
onCleanup4(() => {
|
|
3143
|
+
minimap.destroy();
|
|
3144
|
+
});
|
|
3145
|
+
});
|
|
3146
|
+
return <svg
|
|
3147
|
+
ref={setRef}
|
|
3148
|
+
width={local.width}
|
|
3149
|
+
height={local.height}
|
|
3150
|
+
viewBox={`${getX()} ${getY()} ${getViewboxWidth()} ${getViewboxHeight()}`}
|
|
3151
|
+
class="solid-flow__minimap-svg"
|
|
3152
|
+
role="img"
|
|
3153
|
+
aria-labelledby={labelledBy()}
|
|
3154
|
+
style={{
|
|
3155
|
+
"--xy-minimap-mask-background-color-props": local.maskColor,
|
|
3156
|
+
"--xy-minimap-mask-stroke-color-props": local.maskStrokeColor,
|
|
3157
|
+
"--xy-minimap-mask-stroke-width-props": strokeWidth()
|
|
3158
|
+
}}
|
|
3159
|
+
>
|
|
3160
|
+
<title id={labelledBy()}>{store.ariaLabelConfig["minimap.ariaLabel"]}</title>
|
|
3161
|
+
<Index each={nodeIds()}>
|
|
3162
|
+
{(nodeId) => {
|
|
3163
|
+
const node = createMemo7(() => nodeLookup.get(nodeId()));
|
|
3164
|
+
const nodeVisible = () => Boolean(node() && nodeHasDimensions2(node()) && !node().hidden);
|
|
3165
|
+
return <Show13 when={nodeVisible() && getNodeDimensions3(node())}>
|
|
3166
|
+
{(nodeDimensions) => <MiniMapNode
|
|
3167
|
+
x={node().internals.positionAbsolute.x}
|
|
3168
|
+
y={node().internals.positionAbsolute.y}
|
|
3169
|
+
borderRadius={local.nodeBorderRadius}
|
|
3170
|
+
strokeWidth={local.nodeStrokeWidth}
|
|
3171
|
+
shapeRendering={shapeRendering()}
|
|
3172
|
+
width={nodeDimensions().width}
|
|
3173
|
+
height={nodeDimensions().height}
|
|
3174
|
+
selected={node().selected}
|
|
3175
|
+
color={nodeColorFunc()?.call(null, node())}
|
|
3176
|
+
strokeColor={nodeStrokeColorFunc().call(null, node())}
|
|
3177
|
+
class={nodeClassFunc().call(null, node())}
|
|
3178
|
+
/>}
|
|
3179
|
+
</Show13>;
|
|
3180
|
+
}}
|
|
3181
|
+
</Index>
|
|
3182
|
+
<path
|
|
3183
|
+
class="solid-flow__minimap-mask"
|
|
3184
|
+
d={`M${getX() - getOffset()},${getY() - getOffset()}h${getViewboxWidth() + getOffset() * 2}v${getViewboxHeight() + getOffset() * 2}h${-getViewboxWidth() - getOffset() * 2}z
|
|
3185
|
+
M${getViewBB().x},${getViewBB().y}h${getViewBB().width}v${getViewBB().height}h${-getViewBB().width}z`}
|
|
3186
|
+
fill-rule="evenodd"
|
|
3187
|
+
pointer-events="none"
|
|
3188
|
+
/>
|
|
3189
|
+
</svg>;
|
|
3190
|
+
}}
|
|
3191
|
+
</Show13>
|
|
3192
|
+
</Panel>;
|
|
3193
|
+
};
|
|
3194
|
+
|
|
3195
|
+
// src/components/graph/plugins/nodeResizer/NodeResizer.tsx
|
|
3196
|
+
import {
|
|
3197
|
+
XY_RESIZER_HANDLE_POSITIONS,
|
|
3198
|
+
XY_RESIZER_LINE_POSITIONS
|
|
3199
|
+
} from "@xyflow/system";
|
|
3200
|
+
import { For as For4, mergeProps as mergeProps18, Show as Show14, splitProps as splitProps10 } from "solid-js";
|
|
3201
|
+
|
|
3202
|
+
// src/components/graph/plugins/nodeResizer/ResizeControl.tsx
|
|
3203
|
+
import {
|
|
3204
|
+
XYResizer
|
|
3205
|
+
} from "@xyflow/system";
|
|
3206
|
+
import clsx17 from "clsx";
|
|
3207
|
+
import {
|
|
3208
|
+
createEffect as createEffect7,
|
|
3209
|
+
mergeProps as mergeProps17,
|
|
3210
|
+
onCleanup as onCleanup5,
|
|
3211
|
+
onMount as onMount4,
|
|
3212
|
+
splitProps as splitProps9
|
|
3213
|
+
} from "solid-js";
|
|
3214
|
+
import { produce as produce3 } from "solid-js/store";
|
|
3215
|
+
var ResizeControl = (props) => {
|
|
3216
|
+
const _props = mergeProps17(
|
|
3217
|
+
{
|
|
3218
|
+
variant: "handle",
|
|
3219
|
+
minWidth: 10,
|
|
3220
|
+
minHeight: 10,
|
|
3221
|
+
maxWidth: Number.MAX_VALUE,
|
|
3222
|
+
maxHeight: Number.MAX_VALUE,
|
|
3223
|
+
keepAspectRatio: false,
|
|
3224
|
+
autoScale: true,
|
|
3225
|
+
style: {}
|
|
3226
|
+
},
|
|
3227
|
+
props
|
|
3228
|
+
);
|
|
3229
|
+
const [local, rest] = splitProps9(_props, [
|
|
3230
|
+
"nodeId",
|
|
3231
|
+
"variant",
|
|
3232
|
+
"position",
|
|
3233
|
+
"minWidth",
|
|
3234
|
+
"minHeight",
|
|
3235
|
+
"maxWidth",
|
|
3236
|
+
"maxHeight",
|
|
3237
|
+
"keepAspectRatio",
|
|
3238
|
+
"autoScale",
|
|
3239
|
+
"onResizeStart",
|
|
3240
|
+
"onResize",
|
|
3241
|
+
"onResizeEnd",
|
|
3242
|
+
"shouldResize",
|
|
3243
|
+
"class",
|
|
3244
|
+
"children",
|
|
3245
|
+
"color",
|
|
3246
|
+
"style"
|
|
3247
|
+
]);
|
|
3248
|
+
let resizeControlRef;
|
|
3249
|
+
const { store, nodeLookup, actions } = useInternalSolidFlow();
|
|
3250
|
+
const ctxNodeId = useNodeId();
|
|
3251
|
+
const nodeId = () => local.nodeId ?? ctxNodeId();
|
|
3252
|
+
const isLineVariant = () => local.variant === "line";
|
|
3253
|
+
const controlPosition = () => local.position ?? (isLineVariant() ? "right" : "bottom-right");
|
|
3254
|
+
const positionClassNames = () => controlPosition().split("-");
|
|
3255
|
+
onMount4(() => {
|
|
3256
|
+
const resizer = XYResizer({
|
|
3257
|
+
domNode: resizeControlRef,
|
|
3258
|
+
nodeId: nodeId(),
|
|
3259
|
+
getStoreItems: () => ({
|
|
3260
|
+
nodeLookup,
|
|
3261
|
+
transform: store.transform,
|
|
3262
|
+
snapGrid: store.snapGrid,
|
|
3263
|
+
snapToGrid: !!store.snapGrid,
|
|
3264
|
+
nodeOrigin: store.nodeOrigin,
|
|
3265
|
+
paneDomNode: store.domNode
|
|
3266
|
+
}),
|
|
3267
|
+
onChange: (change, childChanges) => {
|
|
3268
|
+
const changes = /* @__PURE__ */ new Map();
|
|
3269
|
+
const position = change.x && change.y ? { x: change.x, y: change.y } : void 0;
|
|
3270
|
+
changes.set(nodeId(), { ...change, position });
|
|
3271
|
+
for (const childChange of childChanges) {
|
|
3272
|
+
changes.set(childChange.id, {
|
|
3273
|
+
position: childChange.position
|
|
3274
|
+
});
|
|
3275
|
+
}
|
|
3276
|
+
actions.setNodes(
|
|
3277
|
+
(node) => changes.has(node.id),
|
|
3278
|
+
produce3((node) => {
|
|
3279
|
+
const nodeChange = changes.get(node.id);
|
|
3280
|
+
node.width = nodeChange.width;
|
|
3281
|
+
node.height = nodeChange.height;
|
|
3282
|
+
node.position = {
|
|
3283
|
+
x: nodeChange.position?.x ?? node.position.x,
|
|
3284
|
+
y: nodeChange.position?.y ?? node.position.y
|
|
3285
|
+
};
|
|
3286
|
+
})
|
|
3287
|
+
);
|
|
3288
|
+
}
|
|
3289
|
+
});
|
|
3290
|
+
createEffect7(() => {
|
|
3291
|
+
resizer.update({
|
|
3292
|
+
controlPosition: controlPosition(),
|
|
3293
|
+
boundaries: {
|
|
3294
|
+
minWidth: local.minWidth,
|
|
3295
|
+
minHeight: local.minHeight,
|
|
3296
|
+
maxWidth: local.maxWidth,
|
|
3297
|
+
maxHeight: local.maxHeight
|
|
3298
|
+
},
|
|
3299
|
+
keepAspectRatio: !!local.keepAspectRatio,
|
|
3300
|
+
onResizeStart: local.onResizeStart,
|
|
3301
|
+
onResize: local.onResize,
|
|
3302
|
+
onResizeEnd: local.onResizeEnd,
|
|
3303
|
+
shouldResize: local.shouldResize
|
|
3304
|
+
});
|
|
3305
|
+
});
|
|
3306
|
+
onCleanup5(() => {
|
|
3307
|
+
resizer.destroy();
|
|
3308
|
+
});
|
|
3309
|
+
});
|
|
3310
|
+
return <div
|
|
3311
|
+
ref={resizeControlRef}
|
|
3312
|
+
class={clsx17([
|
|
3313
|
+
"solid-flow__resize-control",
|
|
3314
|
+
local.variant,
|
|
3315
|
+
store.noDragClass,
|
|
3316
|
+
...positionClassNames(),
|
|
3317
|
+
local.class
|
|
3318
|
+
])}
|
|
3319
|
+
style={{
|
|
3320
|
+
"border-color": isLineVariant() ? local.color : void 0,
|
|
3321
|
+
"background-color": isLineVariant() ? void 0 : local.color,
|
|
3322
|
+
scale: isLineVariant() || !local.autoScale ? void 0 : Math.max(1 / store.viewport.zoom, 1),
|
|
3323
|
+
...local.style
|
|
3324
|
+
}}
|
|
3325
|
+
{...rest}
|
|
3326
|
+
>
|
|
3327
|
+
{local.children}
|
|
3328
|
+
</div>;
|
|
3329
|
+
};
|
|
3330
|
+
|
|
3331
|
+
// src/components/graph/plugins/nodeResizer/NodeResizer.tsx
|
|
3332
|
+
var NodeResizer = (props) => {
|
|
3333
|
+
const _props = mergeProps18(
|
|
3334
|
+
{
|
|
3335
|
+
autoScale: true,
|
|
3336
|
+
visible: true
|
|
3337
|
+
},
|
|
3338
|
+
props
|
|
3339
|
+
);
|
|
3340
|
+
const [local, rest] = splitProps10(props, ["handleClass", "handleStyle", "lineClass", "lineStyle"]);
|
|
3341
|
+
return <Show14 when={_props.visible}>
|
|
3342
|
+
<For4 each={XY_RESIZER_LINE_POSITIONS}>
|
|
3343
|
+
{(position) => <ResizeControl
|
|
3344
|
+
variant="line"
|
|
3345
|
+
position={position}
|
|
3346
|
+
class={local.lineClass}
|
|
3347
|
+
style={local.lineStyle}
|
|
3348
|
+
{...rest}
|
|
3349
|
+
/>}
|
|
3350
|
+
</For4>
|
|
3351
|
+
<For4 each={XY_RESIZER_HANDLE_POSITIONS}>
|
|
3352
|
+
{(position) => <ResizeControl
|
|
3353
|
+
position={position}
|
|
3354
|
+
class={local.handleClass}
|
|
3355
|
+
style={local.handleStyle}
|
|
3356
|
+
{...rest}
|
|
3357
|
+
/>}
|
|
3358
|
+
</For4>
|
|
3359
|
+
</Show14>;
|
|
3360
|
+
};
|
|
3361
|
+
|
|
3362
|
+
// src/components/graph/plugins/NodeToolbar.tsx
|
|
3363
|
+
import { getNodeToolbarTransform } from "@xyflow/system";
|
|
3364
|
+
import { mergeProps as mergeProps19, Show as Show15, splitProps as splitProps11, useContext as useContext6 } from "solid-js";
|
|
3365
|
+
import { Portal as Portal3 } from "solid-js/web";
|
|
3366
|
+
|
|
3367
|
+
// src/hooks/useConnection.tsx
|
|
3368
|
+
function useConnection() {
|
|
3369
|
+
const { store } = useInternalSolidFlow();
|
|
3370
|
+
const connection = () => store.connection;
|
|
3371
|
+
return connection;
|
|
3372
|
+
}
|
|
3373
|
+
|
|
3374
|
+
// src/hooks/useGraph.ts
|
|
3375
|
+
function useNodes() {
|
|
3376
|
+
const { store } = useInternalSolidFlow();
|
|
3377
|
+
return () => store.nodes;
|
|
3378
|
+
}
|
|
3379
|
+
function useEdges() {
|
|
3380
|
+
const { store } = useInternalSolidFlow();
|
|
3381
|
+
return () => store.edges;
|
|
3382
|
+
}
|
|
3383
|
+
function useViewport() {
|
|
3384
|
+
const { store } = useInternalSolidFlow();
|
|
3385
|
+
return () => store.viewport;
|
|
3386
|
+
}
|
|
3387
|
+
|
|
3388
|
+
// src/hooks/useHandleEdgeSelect.tsx
|
|
3389
|
+
import "@xyflow/system";
|
|
3390
|
+
import { batch as batch6 } from "solid-js";
|
|
3391
|
+
function useHandleEdgeSelect() {
|
|
3392
|
+
const { store, edgeLookup, actions } = useInternalSolidFlow();
|
|
3393
|
+
return (id) => {
|
|
3394
|
+
const edge = edgeLookup.get(id);
|
|
3395
|
+
if (!edge) {
|
|
3396
|
+
return;
|
|
3397
|
+
}
|
|
3398
|
+
const selectable = edge.selectable || store.elementsSelectable && typeof edge.selectable === "undefined";
|
|
3399
|
+
if (selectable) {
|
|
3400
|
+
batch6(() => {
|
|
3401
|
+
actions.setSelectionRect(void 0);
|
|
3402
|
+
actions.setSelectionRectMode(void 0);
|
|
3403
|
+
if (!edge.selected) {
|
|
3404
|
+
actions.addSelectedEdges([id]);
|
|
3405
|
+
} else if (edge.selected && store.multiselectionKeyPressed) {
|
|
3406
|
+
actions.unselectNodesAndEdges({ nodes: [], edges: [edge] });
|
|
3407
|
+
}
|
|
3408
|
+
});
|
|
3409
|
+
}
|
|
3410
|
+
};
|
|
3411
|
+
}
|
|
3412
|
+
|
|
3413
|
+
// src/hooks/useInternalNode.tsx
|
|
3414
|
+
function useInternalNode(id) {
|
|
3415
|
+
const { nodeLookup } = useInternalSolidFlow();
|
|
3416
|
+
return () => nodeLookup.get(id());
|
|
3417
|
+
}
|
|
3418
|
+
|
|
3419
|
+
// src/hooks/useNodeConnections.ts
|
|
3420
|
+
import { areConnectionMapsEqual as areConnectionMapsEqual2 } from "@xyflow/system";
|
|
3421
|
+
import { createEffect as createEffect8, createSignal as createSignal7, useContext as useContext5 } from "solid-js";
|
|
3422
|
+
var useNodeConnections = (params) => {
|
|
3423
|
+
const { connectionLookup } = useInternalSolidFlow();
|
|
3424
|
+
const ctxNodeId = () => {
|
|
3425
|
+
const id2 = useContext5(NodeIdContext);
|
|
3426
|
+
return id2 ? id2() : "";
|
|
3427
|
+
};
|
|
3428
|
+
const id = () => params().handleId;
|
|
3429
|
+
const type = () => params().handleType;
|
|
3430
|
+
const nodeId = () => params().id ?? ctxNodeId();
|
|
3431
|
+
const [connections, setConnections] = createSignal7([]);
|
|
3432
|
+
const lookupKey = () => `${nodeId()}${type() ? id() ? `-${type()}-${id()}` : `-${type()}` : ""}`;
|
|
3433
|
+
createEffect8((prevConnections) => {
|
|
3434
|
+
const nextConnections = connectionLookup.get(lookupKey());
|
|
3435
|
+
if (!areConnectionMapsEqual2(nextConnections, prevConnections)) {
|
|
3436
|
+
prevConnections = nextConnections;
|
|
3437
|
+
setConnections(Array.from(prevConnections?.values() ?? []));
|
|
3438
|
+
}
|
|
3439
|
+
return nextConnections;
|
|
3440
|
+
});
|
|
3441
|
+
return connections;
|
|
3442
|
+
};
|
|
3443
|
+
|
|
3444
|
+
// src/hooks/useNodesData.ts
|
|
3445
|
+
import { shallowNodeData } from "@xyflow/system";
|
|
3446
|
+
import { createMemo as createMemo8 } from "solid-js";
|
|
3447
|
+
function useNodesData(nodeIds) {
|
|
3448
|
+
const { nodeLookup } = useInternalSolidFlow();
|
|
3449
|
+
let prevNodesData = [];
|
|
3450
|
+
const result = createMemo8(() => {
|
|
3451
|
+
const nodesData = [];
|
|
3452
|
+
const idValues = nodeIds();
|
|
3453
|
+
if (!idValues) return void 0;
|
|
3454
|
+
const ids = Array.isArray(idValues) ? idValues : [idValues];
|
|
3455
|
+
for (const nodeId of ids) {
|
|
3456
|
+
const node = nodeLookup.get(nodeId)?.internals.userNode;
|
|
3457
|
+
if (!node) continue;
|
|
3458
|
+
nodesData.push({
|
|
3459
|
+
id: node.id,
|
|
3460
|
+
type: node.type,
|
|
3461
|
+
data: node.data
|
|
3462
|
+
});
|
|
3463
|
+
}
|
|
3464
|
+
if (!shallowNodeData(nodesData, prevNodesData)) {
|
|
3465
|
+
prevNodesData = nodesData;
|
|
3466
|
+
}
|
|
3467
|
+
return Array.isArray(idValues) ? nodesData : nodesData[0];
|
|
3468
|
+
});
|
|
3469
|
+
return result;
|
|
3470
|
+
}
|
|
3471
|
+
|
|
3472
|
+
// src/hooks/useSolidFlow.tsx
|
|
3473
|
+
import {
|
|
3474
|
+
evaluateAbsolutePosition,
|
|
3475
|
+
getElementsToRemove,
|
|
3476
|
+
getNodesBounds,
|
|
3477
|
+
getOverlappingArea,
|
|
3478
|
+
getViewportForBounds as getViewportForBounds2,
|
|
3479
|
+
isRectObject,
|
|
3480
|
+
nodeToRect as nodeToRect2,
|
|
3481
|
+
pointToRendererPoint as pointToRendererPoint2,
|
|
3482
|
+
rendererPointToPoint
|
|
3483
|
+
} from "@xyflow/system";
|
|
3484
|
+
import { batch as batch7 } from "solid-js";
|
|
3485
|
+
import { unwrap as unwrap2 } from "solid-js/store";
|
|
3486
|
+
function useSolidFlow() {
|
|
3487
|
+
const { store, actions, nodeLookup, edgeLookup, connectionLookup } = useInternalSolidFlow();
|
|
3488
|
+
const getNodeRect = (node) => {
|
|
3489
|
+
const nodeToUse = isNode(node) ? node : nodeLookup.get(node.id);
|
|
3490
|
+
const position = nodeToUse.parentId ? evaluateAbsolutePosition(
|
|
3491
|
+
nodeToUse.position,
|
|
3492
|
+
nodeToUse.measured,
|
|
3493
|
+
nodeToUse.parentId,
|
|
3494
|
+
nodeLookup,
|
|
3495
|
+
store.nodeOrigin
|
|
3496
|
+
) : nodeToUse.position;
|
|
3497
|
+
const nodeWithPosition = {
|
|
3498
|
+
...nodeToUse,
|
|
3499
|
+
position,
|
|
3500
|
+
width: nodeToUse.measured?.width ?? nodeToUse.width,
|
|
3501
|
+
height: nodeToUse.measured?.height ?? nodeToUse.height
|
|
3502
|
+
};
|
|
3503
|
+
return nodeToRect2(nodeWithPosition);
|
|
3504
|
+
};
|
|
3505
|
+
const updateNode = (id, nodeUpdate, options = { replace: false }) => {
|
|
3506
|
+
actions.setNodes(
|
|
3507
|
+
(node) => node.id === id,
|
|
3508
|
+
(node) => {
|
|
3509
|
+
const nextNode = typeof nodeUpdate === "function" ? nodeUpdate(node) : nodeUpdate;
|
|
3510
|
+
return options?.replace && isNode(nextNode) ? nextNode : { ...node, ...nextNode };
|
|
3511
|
+
}
|
|
3512
|
+
);
|
|
3513
|
+
};
|
|
3514
|
+
const updateEdge = (id, edgeUpdate, options = { replace: false }) => {
|
|
3515
|
+
actions.setEdges(
|
|
3516
|
+
(edge) => edge.id === id,
|
|
3517
|
+
(edge) => {
|
|
3518
|
+
const nextEdge = typeof edgeUpdate === "function" ? edgeUpdate(edge) : edgeUpdate;
|
|
3519
|
+
return options.replace && isEdge(nextEdge) ? nextEdge : { ...edge, ...nextEdge };
|
|
3520
|
+
}
|
|
3521
|
+
);
|
|
3522
|
+
};
|
|
3523
|
+
const getInternalNode = (id) => nodeLookup.get(id);
|
|
3524
|
+
const addNodes = (payload) => {
|
|
3525
|
+
const newNodes = Array.isArray(payload) ? payload : [payload];
|
|
3526
|
+
actions.setNodes((nodes) => [...nodes, ...newNodes]);
|
|
3527
|
+
};
|
|
3528
|
+
const addEdges = (payload) => {
|
|
3529
|
+
const newEdges = Array.isArray(payload) ? payload : [payload];
|
|
3530
|
+
actions.setEdges((edges) => [...edges, ...newEdges]);
|
|
3531
|
+
};
|
|
3532
|
+
return {
|
|
3533
|
+
zoomIn: actions.zoomIn,
|
|
3534
|
+
zoomOut: actions.zoomOut,
|
|
3535
|
+
getInternalNode,
|
|
3536
|
+
setCenter: actions.setCenter,
|
|
3537
|
+
fitView: actions.fitView,
|
|
3538
|
+
getNode: (id) => getInternalNode(id)?.internals.userNode,
|
|
3539
|
+
getNodes: (ids) => !ids ? store.nodes : getElements(nodeLookup, ids),
|
|
3540
|
+
getEdge: (id) => edgeLookup.get(id),
|
|
3541
|
+
getEdges: (ids) => !ids ? store.edges : getElements(edgeLookup, ids),
|
|
3542
|
+
addNodes,
|
|
3543
|
+
addEdges,
|
|
3544
|
+
getViewport: () => unwrap2(store.viewport),
|
|
3545
|
+
setViewport: async (nextViewport, options) => {
|
|
3546
|
+
const currentViewport = store.viewport;
|
|
3547
|
+
if (!store.panZoom) {
|
|
3548
|
+
return Promise.resolve(false);
|
|
3549
|
+
}
|
|
3550
|
+
await store.panZoom.setViewport(
|
|
3551
|
+
{
|
|
3552
|
+
x: nextViewport.x ?? currentViewport.x,
|
|
3553
|
+
y: nextViewport.y ?? currentViewport.y,
|
|
3554
|
+
zoom: nextViewport.zoom ?? currentViewport.zoom
|
|
3555
|
+
},
|
|
3556
|
+
options
|
|
3557
|
+
);
|
|
3558
|
+
return Promise.resolve(true);
|
|
3559
|
+
},
|
|
3560
|
+
getZoom: () => store.viewport.zoom,
|
|
3561
|
+
setZoom: (zoomLevel, options) => {
|
|
3562
|
+
const panZoom = store.panZoom;
|
|
3563
|
+
return panZoom ? panZoom.scaleTo(zoomLevel, { duration: options?.duration }) : Promise.resolve(false);
|
|
3564
|
+
},
|
|
3565
|
+
fitBounds: async (bounds, options) => {
|
|
3566
|
+
if (!store.panZoom) {
|
|
3567
|
+
return Promise.resolve(false);
|
|
3568
|
+
}
|
|
3569
|
+
const viewport = getViewportForBounds2(
|
|
3570
|
+
bounds,
|
|
3571
|
+
store.width,
|
|
3572
|
+
store.height,
|
|
3573
|
+
store.minZoom,
|
|
3574
|
+
store.maxZoom,
|
|
3575
|
+
options?.padding ?? 0.1
|
|
3576
|
+
);
|
|
3577
|
+
await store.panZoom.setViewport(viewport, {
|
|
3578
|
+
duration: options?.duration,
|
|
3579
|
+
ease: options?.ease,
|
|
3580
|
+
interpolate: options?.interpolate
|
|
3581
|
+
});
|
|
3582
|
+
return Promise.resolve(true);
|
|
3583
|
+
},
|
|
3584
|
+
getIntersectingNodes: (nodeOrRect, partially = true, nodesToIntersect) => {
|
|
3585
|
+
const isRect = isRectObject(nodeOrRect);
|
|
3586
|
+
const nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
|
|
3587
|
+
if (!nodeRect) {
|
|
3588
|
+
return [];
|
|
3589
|
+
}
|
|
3590
|
+
return (nodesToIntersect || store.nodes).filter((n) => {
|
|
3591
|
+
const internalNode = nodeLookup.get(n.id);
|
|
3592
|
+
if (!internalNode || !isRect && n.id === nodeOrRect.id) {
|
|
3593
|
+
return false;
|
|
3594
|
+
}
|
|
3595
|
+
const currNodeRect = nodeToRect2(internalNode);
|
|
3596
|
+
const overlappingArea = getOverlappingArea(currNodeRect, nodeRect);
|
|
3597
|
+
const partiallyVisible = partially && overlappingArea > 0;
|
|
3598
|
+
return partiallyVisible || overlappingArea >= nodeRect.width * nodeRect.height;
|
|
3599
|
+
});
|
|
3600
|
+
},
|
|
3601
|
+
isNodeIntersecting: (nodeOrRect, area, partially = true) => {
|
|
3602
|
+
const isRect = isRectObject(nodeOrRect);
|
|
3603
|
+
const nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect);
|
|
3604
|
+
if (!nodeRect) {
|
|
3605
|
+
return false;
|
|
3606
|
+
}
|
|
3607
|
+
const overlappingArea = getOverlappingArea(nodeRect, area);
|
|
3608
|
+
const partiallyVisible = partially && overlappingArea > 0;
|
|
3609
|
+
return partiallyVisible || overlappingArea >= nodeRect.width * nodeRect.height;
|
|
3610
|
+
},
|
|
3611
|
+
deleteElements: async ({ nodes: nodesToRemove = [], edges: edgesToRemove = [] }) => {
|
|
3612
|
+
const { nodes: matchingNodes, edges: matchingEdges } = await getElementsToRemove({
|
|
3613
|
+
nodesToRemove,
|
|
3614
|
+
edgesToRemove,
|
|
3615
|
+
nodes: store.nodes,
|
|
3616
|
+
edges: store.edges,
|
|
3617
|
+
onBeforeDelete: store.onBeforeDelete
|
|
3618
|
+
});
|
|
3619
|
+
batch7(() => {
|
|
3620
|
+
if (matchingEdges) {
|
|
3621
|
+
const remmainingEdges = store.edges.filter(
|
|
3622
|
+
(edge) => !matchingEdges.some(({ id }) => id === edge.id)
|
|
3623
|
+
);
|
|
3624
|
+
store.onEdgesDelete?.(matchingEdges);
|
|
3625
|
+
actions.setEdges(remmainingEdges);
|
|
3626
|
+
}
|
|
3627
|
+
if (matchingNodes) {
|
|
3628
|
+
const remmainingNodes = store.nodes.filter(
|
|
3629
|
+
(node) => !matchingNodes.some(({ id }) => id === node.id)
|
|
3630
|
+
);
|
|
3631
|
+
store.onNodesDelete?.(matchingNodes);
|
|
3632
|
+
actions.setNodes(remmainingNodes);
|
|
3633
|
+
}
|
|
3634
|
+
});
|
|
3635
|
+
return {
|
|
3636
|
+
deletedNodes: matchingNodes,
|
|
3637
|
+
deletedEdges: matchingEdges
|
|
3638
|
+
};
|
|
3639
|
+
},
|
|
3640
|
+
screenToFlowPosition: (position, options = { snapToGrid: true }) => {
|
|
3641
|
+
if (!store.domNode) {
|
|
3642
|
+
return position;
|
|
3643
|
+
}
|
|
3644
|
+
const _snapGrid = options.snapToGrid ? store.snapGrid : false;
|
|
3645
|
+
const { x, y, zoom } = store.viewport;
|
|
3646
|
+
const { x: domX, y: domY } = store.domNode.getBoundingClientRect();
|
|
3647
|
+
const correctedPosition = {
|
|
3648
|
+
x: position.x - domX,
|
|
3649
|
+
y: position.y - domY
|
|
3650
|
+
};
|
|
3651
|
+
return pointToRendererPoint2(
|
|
3652
|
+
correctedPosition,
|
|
3653
|
+
[x, y, zoom],
|
|
3654
|
+
_snapGrid !== null,
|
|
3655
|
+
_snapGrid || [1, 1]
|
|
3656
|
+
);
|
|
3657
|
+
},
|
|
3658
|
+
/**
|
|
3659
|
+
*
|
|
3660
|
+
* @param position
|
|
3661
|
+
* @returns
|
|
3662
|
+
*/
|
|
3663
|
+
flowToScreenPosition: (position) => {
|
|
3664
|
+
if (!store.domNode) {
|
|
3665
|
+
return position;
|
|
3666
|
+
}
|
|
3667
|
+
const { x, y, zoom } = store.viewport;
|
|
3668
|
+
const { x: domX, y: domY } = store.domNode.getBoundingClientRect();
|
|
3669
|
+
const rendererPosition = rendererPointToPoint(position, [x, y, zoom]);
|
|
3670
|
+
return {
|
|
3671
|
+
x: rendererPosition.x + domX,
|
|
3672
|
+
y: rendererPosition.y + domY
|
|
3673
|
+
};
|
|
3674
|
+
},
|
|
3675
|
+
toObject: () => {
|
|
3676
|
+
return structuredClone({
|
|
3677
|
+
nodes: [...unwrap2(store.nodes)],
|
|
3678
|
+
edges: [...unwrap2(store.edges)],
|
|
3679
|
+
viewport: { ...unwrap2(store.viewport) }
|
|
3680
|
+
});
|
|
3681
|
+
},
|
|
3682
|
+
updateNode,
|
|
3683
|
+
updateNodeData: (id, dataUpdate, options) => {
|
|
3684
|
+
const node = nodeLookup.get(id)?.internals.userNode;
|
|
3685
|
+
if (!node) {
|
|
3686
|
+
return;
|
|
3687
|
+
}
|
|
3688
|
+
const nextData = typeof dataUpdate === "function" ? dataUpdate(node) : dataUpdate;
|
|
3689
|
+
updateNode(id, (node2) => ({
|
|
3690
|
+
...node2,
|
|
3691
|
+
data: options?.replace ? nextData : { ...node2.data, ...nextData }
|
|
3692
|
+
}));
|
|
3693
|
+
},
|
|
3694
|
+
updateEdge,
|
|
3695
|
+
getNodesBounds: (nodes) => {
|
|
3696
|
+
return getNodesBounds(nodes, { nodeLookup, nodeOrigin: store.nodeOrigin });
|
|
3697
|
+
},
|
|
3698
|
+
getHandleConnections: ({ type, id, nodeId }) => Array.from(connectionLookup.get(`${nodeId}-${type}-${id ?? null}`)?.values() ?? [])
|
|
3699
|
+
};
|
|
3700
|
+
}
|
|
3701
|
+
function getElements(lookup, ids) {
|
|
3702
|
+
const result = [];
|
|
3703
|
+
for (const id of ids) {
|
|
3704
|
+
const item = lookup.get(id);
|
|
3705
|
+
if (item) {
|
|
3706
|
+
const element = "internals" in item ? item.internals?.userNode : item;
|
|
3707
|
+
result.push(element);
|
|
3708
|
+
}
|
|
3709
|
+
}
|
|
3710
|
+
return result;
|
|
3711
|
+
}
|
|
3712
|
+
|
|
3713
|
+
// src/hooks/useUpdateNodeInternals.ts
|
|
3714
|
+
function useUpdateNodeInternals() {
|
|
3715
|
+
const { store, actions } = useInternalSolidFlow();
|
|
3716
|
+
const updateInternals = (id) => {
|
|
3717
|
+
const updateIds = Array.isArray(id) ? id : [id];
|
|
3718
|
+
const updates = [];
|
|
3719
|
+
for (const updateId of updateIds) {
|
|
3720
|
+
const nodeElement = store.domNode?.querySelector(
|
|
3721
|
+
`.solid-flow__node[data-id="${updateId}"]`
|
|
3722
|
+
);
|
|
3723
|
+
if (!nodeElement) continue;
|
|
3724
|
+
updates.push([updateId, { id: updateId, nodeElement, force: true }]);
|
|
3725
|
+
}
|
|
3726
|
+
actions.requestUpdateNodeInternals(updates);
|
|
3727
|
+
};
|
|
3728
|
+
return updateInternals;
|
|
3729
|
+
}
|
|
3730
|
+
|
|
3731
|
+
// src/components/graph/plugins/NodeToolbar.tsx
|
|
3732
|
+
var NodeToolbar = (props) => {
|
|
3733
|
+
const { store } = useInternalSolidFlow();
|
|
3734
|
+
const { getNodes, getNodesBounds: getNodesBounds3, getInternalNode } = useSolidFlow();
|
|
3735
|
+
const _props = mergeProps19(
|
|
3736
|
+
{
|
|
3737
|
+
offset: 10,
|
|
3738
|
+
position: "top",
|
|
3739
|
+
align: "center",
|
|
3740
|
+
style: {}
|
|
3741
|
+
},
|
|
3742
|
+
props
|
|
3743
|
+
);
|
|
3744
|
+
const [local, divProps] = splitProps11(_props, [
|
|
3745
|
+
"nodeId",
|
|
3746
|
+
"position",
|
|
3747
|
+
"align",
|
|
3748
|
+
"offset",
|
|
3749
|
+
"isVisible",
|
|
3750
|
+
"style",
|
|
3751
|
+
"children"
|
|
3752
|
+
]);
|
|
3753
|
+
const ctxNodeId = () => {
|
|
3754
|
+
const id = useContext6(NodeIdContext);
|
|
3755
|
+
return id ? id() : "";
|
|
3756
|
+
};
|
|
3757
|
+
const toolbarNodes = () => {
|
|
3758
|
+
const nodeIds = Array.isArray(local.nodeId) ? local.nodeId : [local.nodeId ?? ctxNodeId()];
|
|
3759
|
+
return nodeIds.reduce((res, nodeId) => {
|
|
3760
|
+
const node = getInternalNode(nodeId);
|
|
3761
|
+
if (node) res.push(node);
|
|
3762
|
+
return res;
|
|
3763
|
+
}, []);
|
|
3764
|
+
};
|
|
3765
|
+
const transform = () => {
|
|
3766
|
+
const nodeRect = getNodesBounds3(toolbarNodes());
|
|
3767
|
+
return !nodeRect ? "" : getNodeToolbarTransform(
|
|
3768
|
+
nodeRect,
|
|
3769
|
+
store.viewport,
|
|
3770
|
+
local.position,
|
|
3771
|
+
local.offset,
|
|
3772
|
+
local.align
|
|
3773
|
+
);
|
|
3774
|
+
};
|
|
3775
|
+
const zIndex = () => {
|
|
3776
|
+
const nodes = toolbarNodes();
|
|
3777
|
+
return nodes.length === 0 ? 1 : Math.max(...nodes.map((node) => (node.internals.z || 5) + 1));
|
|
3778
|
+
};
|
|
3779
|
+
const selectedNodesCount = () => getNodes().filter((node) => node.selected).length;
|
|
3780
|
+
const isActive = () => {
|
|
3781
|
+
const nodes = toolbarNodes();
|
|
3782
|
+
return typeof local.isVisible === "boolean" ? local.isVisible : nodes.length === 1 && Boolean(nodes[0].selected) && selectedNodesCount() === 1;
|
|
3783
|
+
};
|
|
3784
|
+
const showPortal = () => Boolean(store.domNode && isActive() && toolbarNodes().length > 0);
|
|
3785
|
+
return <Show15 when={showPortal()}>
|
|
3786
|
+
<Portal3 mount={store.domNode}>
|
|
3787
|
+
<div
|
|
3788
|
+
class="solid-flow__node-toolbar"
|
|
3789
|
+
data-id={toolbarNodes().reduce((acc, node) => `${acc}${node.id} `, "").trim()}
|
|
3790
|
+
style={{
|
|
3791
|
+
// TODO: Add hideOnSSR display style from Svelte implementation
|
|
3792
|
+
position: "absolute",
|
|
3793
|
+
transform: transform(),
|
|
3794
|
+
"z-index": zIndex(),
|
|
3795
|
+
...local.style
|
|
3796
|
+
}}
|
|
3797
|
+
{...divProps}
|
|
3798
|
+
>
|
|
3799
|
+
{local.children}
|
|
173
3800
|
</div>
|
|
174
|
-
</
|
|
175
|
-
</
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
3801
|
+
</Portal3>
|
|
3802
|
+
</Show15>;
|
|
3803
|
+
};
|
|
3804
|
+
|
|
3805
|
+
// src/components/graph/selection/NodeSelection.tsx
|
|
3806
|
+
import { getInternalNodesBounds as getInternalNodesBounds3, isNumeric as isNumeric2 } from "@xyflow/system";
|
|
3807
|
+
import clsx18 from "clsx";
|
|
3808
|
+
import { createEffect as createEffect9, createSignal as createSignal8, Show as Show17 } from "solid-js";
|
|
3809
|
+
|
|
3810
|
+
// src/components/graph/selection/Selection.tsx
|
|
3811
|
+
import { mergeProps as mergeProps20, Show as Show16 } from "solid-js";
|
|
3812
|
+
var Selection = (props) => {
|
|
3813
|
+
const _props = mergeProps20({ isVisible: true }, props);
|
|
3814
|
+
const styles = () => ({
|
|
3815
|
+
..._props.width != null && {
|
|
3816
|
+
width: typeof _props.width === "string" ? _props.width : toPxString(_props.width)
|
|
3817
|
+
},
|
|
3818
|
+
..._props.height != null && {
|
|
3819
|
+
height: typeof _props.height === "string" ? _props.height : toPxString(_props.height)
|
|
3820
|
+
},
|
|
3821
|
+
..._props.x != null && _props.y != null && {
|
|
3822
|
+
transform: `translate(${props.x}px, ${props.y}px)`
|
|
3823
|
+
}
|
|
3824
|
+
});
|
|
3825
|
+
return <Show16 when={_props.isVisible}>
|
|
3826
|
+
<div class="solid-flow__selection" style={styles()} />
|
|
3827
|
+
</Show16>;
|
|
3828
|
+
};
|
|
3829
|
+
|
|
3830
|
+
// src/components/graph/selection/NodeSelection.tsx
|
|
3831
|
+
var NodeSelection = (props) => {
|
|
3832
|
+
const { store, nodeLookup, actions } = useInternalSolidFlow();
|
|
3833
|
+
const [ref, setRef] = createSignal8();
|
|
3834
|
+
const bounds = () => {
|
|
3835
|
+
if (store.selectionRectMode === "nodes") {
|
|
3836
|
+
return getInternalNodesBounds3(nodeLookup, {
|
|
3837
|
+
filter: (node) => !!node.selected
|
|
3838
|
+
});
|
|
3839
|
+
}
|
|
3840
|
+
return null;
|
|
3841
|
+
};
|
|
3842
|
+
createEffect9(() => {
|
|
3843
|
+
if (!store.disableKeyboardA11y) {
|
|
3844
|
+
ref()?.focus({ preventScroll: true });
|
|
3845
|
+
}
|
|
3846
|
+
});
|
|
3847
|
+
const onContextMenu = (event) => {
|
|
3848
|
+
const selectedNodes = store.nodes.filter((n) => n.selected);
|
|
3849
|
+
props.onSelectionContextMenu?.({ nodes: selectedNodes, event });
|
|
3850
|
+
};
|
|
3851
|
+
const onClick = (event) => {
|
|
3852
|
+
const selectedNodes = store.nodes.filter((n) => n.selected);
|
|
3853
|
+
props.onSelectionClick?.({ nodes: selectedNodes, event });
|
|
3854
|
+
};
|
|
3855
|
+
createDraggable_default(ref, () => ({
|
|
3856
|
+
disabled: false,
|
|
3857
|
+
onDrag: (event, _, __, nodes) => {
|
|
3858
|
+
props.onNodeDrag?.({ event, targetNode: null, nodes });
|
|
3859
|
+
},
|
|
3860
|
+
onDragStart: (event, _, __, nodes) => {
|
|
3861
|
+
props.onNodeDragStart?.({ event, targetNode: null, nodes });
|
|
3862
|
+
},
|
|
3863
|
+
onDragStop: (event, _, __, nodes) => {
|
|
3864
|
+
props.onNodeDragStop?.({ event, targetNode: null, nodes });
|
|
3865
|
+
}
|
|
3866
|
+
}));
|
|
3867
|
+
const onKeyDown = (event) => {
|
|
3868
|
+
const diff = ARROW_KEY_DIFFS[event.key];
|
|
3869
|
+
if (!diff) return;
|
|
3870
|
+
event.preventDefault();
|
|
3871
|
+
actions.moveSelectedNodes(diff, event.shiftKey ? 4 : 1);
|
|
3872
|
+
};
|
|
3873
|
+
return <Show17
|
|
3874
|
+
when={store.selectionRectMode === "nodes" && bounds() && isNumeric2(bounds()?.x) && isNumeric2(bounds()?.y)}
|
|
3875
|
+
>
|
|
3876
|
+
<div
|
|
3877
|
+
ref={setRef}
|
|
3878
|
+
class={clsx18("solid-flow__selection-wrapper", store.noPanClass)}
|
|
3879
|
+
style={{
|
|
3880
|
+
width: toPxString(bounds()?.width),
|
|
3881
|
+
height: toPxString(bounds()?.height),
|
|
3882
|
+
transform: `translate(${bounds()?.x}px, ${bounds()?.y}px)`
|
|
3883
|
+
}}
|
|
3884
|
+
onClick={onClick}
|
|
3885
|
+
onContextMenu={onContextMenu}
|
|
3886
|
+
role={store.disableKeyboardA11y ? void 0 : "button"}
|
|
3887
|
+
tabIndex={store.disableKeyboardA11y ? void 0 : -1}
|
|
3888
|
+
onKeyDown={store.disableKeyboardA11y ? void 0 : onKeyDown}
|
|
3889
|
+
>
|
|
3890
|
+
<Selection width="100%" height="100%" x={0} y={0} />
|
|
180
3891
|
</div>
|
|
181
|
-
</
|
|
182
|
-
|
|
183
|
-
|
|
3892
|
+
</Show17>;
|
|
3893
|
+
};
|
|
3894
|
+
|
|
3895
|
+
// src/components/SolidFlow/component.tsx
|
|
3896
|
+
import { createResizeObserver } from "@solid-primitives/resize-observer";
|
|
3897
|
+
import { infiniteExtent as infiniteExtent4, isMacOs as isMacOs2 } from "@xyflow/system";
|
|
3898
|
+
import clsx19 from "clsx";
|
|
3899
|
+
import {
|
|
3900
|
+
batch as batch9,
|
|
3901
|
+
createEffect as createEffect10,
|
|
3902
|
+
mergeProps as mergeProps22,
|
|
3903
|
+
onCleanup as onCleanup7,
|
|
3904
|
+
onMount as onMount6,
|
|
3905
|
+
splitProps as splitProps12,
|
|
3906
|
+
useContext as useContext7
|
|
3907
|
+
} from "solid-js";
|
|
3908
|
+
|
|
3909
|
+
// src/components/utility/Attribution.tsx
|
|
3910
|
+
import { Show as Show18 } from "solid-js";
|
|
3911
|
+
var Attribution = (props) => {
|
|
3912
|
+
return <Show18 when={!props.proOptions?.hideAttribution}>
|
|
3913
|
+
<Panel
|
|
3914
|
+
position={props.position ?? "bottom-right"}
|
|
3915
|
+
class="solid-flow__attribution"
|
|
3916
|
+
data-message="Feel free to remove the attribution or check out how you could support us: https://solidflow.dev/support-us"
|
|
3917
|
+
>
|
|
3918
|
+
<a
|
|
3919
|
+
href="https://solidflow.dev"
|
|
3920
|
+
target="_blank"
|
|
3921
|
+
rel="noopener noreferrer"
|
|
3922
|
+
aria-label="Solid Flow attribution"
|
|
3923
|
+
>
|
|
184
3924
|
Solid Flow
|
|
185
3925
|
</a>
|
|
186
|
-
</
|
|
187
|
-
</
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
3926
|
+
</Panel>
|
|
3927
|
+
</Show18>;
|
|
3928
|
+
};
|
|
3929
|
+
|
|
3930
|
+
// src/components/utility/KeyHandler.tsx
|
|
3931
|
+
import { isInputDOMNode as isInputDOMNode2, isMacOs } from "@xyflow/system";
|
|
3932
|
+
import { batch as batch8, mergeProps as mergeProps21, onCleanup as onCleanup6, onMount as onMount5 } from "solid-js";
|
|
3933
|
+
function isKeyObject(key) {
|
|
3934
|
+
return key !== null && typeof key === "object";
|
|
3935
|
+
}
|
|
3936
|
+
function getModifier(key) {
|
|
3937
|
+
return isKeyObject(key) ? key.modifier || [] : [];
|
|
3938
|
+
}
|
|
3939
|
+
function getKeyString(key) {
|
|
3940
|
+
if (key === null || key === void 0) {
|
|
3941
|
+
return "";
|
|
3942
|
+
}
|
|
3943
|
+
return isKeyObject(key) ? key.key : key;
|
|
3944
|
+
}
|
|
3945
|
+
function matchesKey(event, keyDef) {
|
|
3946
|
+
if (!keyDef) return false;
|
|
3947
|
+
const keyString = getKeyString(keyDef);
|
|
3948
|
+
if (!keyString) return false;
|
|
3949
|
+
const modifiers = getModifier(keyDef);
|
|
3950
|
+
if (Array.isArray(modifiers)) {
|
|
3951
|
+
const modifierMatch = modifiers.flatMap((mod) => mod).every((mod) => {
|
|
3952
|
+
switch (mod.toLowerCase()) {
|
|
3953
|
+
case "meta":
|
|
3954
|
+
return event.metaKey;
|
|
3955
|
+
case "ctrl":
|
|
3956
|
+
return event.ctrlKey;
|
|
3957
|
+
case "alt":
|
|
3958
|
+
return event.altKey;
|
|
3959
|
+
case "shift":
|
|
3960
|
+
return event.shiftKey;
|
|
3961
|
+
default:
|
|
3962
|
+
return false;
|
|
3963
|
+
}
|
|
3964
|
+
});
|
|
3965
|
+
return event.key === keyString && modifierMatch;
|
|
3966
|
+
}
|
|
3967
|
+
return event.key === keyString;
|
|
3968
|
+
}
|
|
3969
|
+
function matchesKeyArray(event, keyDefs) {
|
|
3970
|
+
if (!keyDefs) return false;
|
|
3971
|
+
const keys = Array.isArray(keyDefs) ? keyDefs : [keyDefs];
|
|
3972
|
+
return keys.some((keyDef) => matchesKey(event, keyDef));
|
|
3973
|
+
}
|
|
3974
|
+
var KeyHandler = (props) => {
|
|
3975
|
+
const { store, actions } = useInternalSolidFlow();
|
|
3976
|
+
const { deleteElements } = useSolidFlow();
|
|
3977
|
+
const _props = mergeProps21(
|
|
3978
|
+
{
|
|
3979
|
+
selectionKey: "Shift",
|
|
3980
|
+
multiSelectionKey: isMacOs() ? "Meta" : "Control",
|
|
3981
|
+
deleteKey: "Backspace",
|
|
3982
|
+
panActivationKey: " ",
|
|
3983
|
+
zoomActivationKey: isMacOs() ? "Meta" : "Control"
|
|
3984
|
+
},
|
|
3985
|
+
props
|
|
3986
|
+
);
|
|
3987
|
+
const resetKeysAndSelection = () => {
|
|
3988
|
+
batch8(() => {
|
|
3989
|
+
actions.setSelectionRect(void 0);
|
|
3990
|
+
actions.setSelectionKeyPressed(false);
|
|
3991
|
+
actions.setMultiselectionKeyPressed(false);
|
|
3992
|
+
actions.setDeleteKeyPressed(false);
|
|
3993
|
+
actions.setPanActivationKeyPressed(false);
|
|
3994
|
+
actions.setZoomActivationKeyPressed(false);
|
|
3995
|
+
});
|
|
3996
|
+
};
|
|
3997
|
+
const handleDelete = async () => {
|
|
3998
|
+
const selectedNodes = store.nodes.filter((node) => node.selected);
|
|
3999
|
+
const selectedEdges = store.edges.filter((edge) => edge.selected);
|
|
4000
|
+
const { deletedNodes, deletedEdges } = await deleteElements({
|
|
4001
|
+
nodes: selectedNodes,
|
|
4002
|
+
edges: selectedEdges
|
|
4003
|
+
});
|
|
4004
|
+
if (deletedNodes.length > 0 || deletedEdges.length > 0) {
|
|
4005
|
+
store.onDelete?.({
|
|
4006
|
+
nodes: deletedNodes,
|
|
4007
|
+
edges: deletedEdges
|
|
4008
|
+
});
|
|
4009
|
+
}
|
|
4010
|
+
};
|
|
4011
|
+
const handleKeyDown = (event) => {
|
|
4012
|
+
batch8(() => {
|
|
4013
|
+
if (matchesKeyArray(event, _props.selectionKey)) {
|
|
4014
|
+
actions.setSelectionKeyPressed(true);
|
|
4015
|
+
}
|
|
4016
|
+
if (matchesKeyArray(event, _props.multiSelectionKey)) {
|
|
4017
|
+
actions.setMultiselectionKeyPressed(true);
|
|
4018
|
+
}
|
|
4019
|
+
if (matchesKeyArray(event, _props.deleteKey) && !isInputDOMNode2(event)) {
|
|
4020
|
+
const isModifierKey = event.ctrlKey || event.metaKey || event.shiftKey;
|
|
4021
|
+
if (!isModifierKey) {
|
|
4022
|
+
actions.setDeleteKeyPressed(true);
|
|
4023
|
+
void handleDelete();
|
|
4024
|
+
}
|
|
4025
|
+
}
|
|
4026
|
+
if (matchesKeyArray(event, _props.panActivationKey)) {
|
|
4027
|
+
actions.setPanActivationKeyPressed(true);
|
|
4028
|
+
}
|
|
4029
|
+
if (matchesKeyArray(event, _props.zoomActivationKey)) {
|
|
4030
|
+
actions.setZoomActivationKeyPressed(true);
|
|
4031
|
+
}
|
|
4032
|
+
});
|
|
4033
|
+
};
|
|
4034
|
+
const handleKeyUp = (event) => {
|
|
4035
|
+
batch8(() => {
|
|
4036
|
+
if (matchesKeyArray(event, _props.selectionKey)) {
|
|
4037
|
+
actions.setSelectionKeyPressed(false);
|
|
4038
|
+
}
|
|
4039
|
+
if (matchesKeyArray(event, _props.multiSelectionKey)) {
|
|
4040
|
+
actions.setMultiselectionKeyPressed(false);
|
|
4041
|
+
}
|
|
4042
|
+
if (matchesKeyArray(event, _props.deleteKey)) {
|
|
4043
|
+
actions.setDeleteKeyPressed(false);
|
|
4044
|
+
}
|
|
4045
|
+
if (matchesKeyArray(event, _props.panActivationKey)) {
|
|
4046
|
+
actions.setPanActivationKeyPressed(false);
|
|
4047
|
+
}
|
|
4048
|
+
if (matchesKeyArray(event, _props.zoomActivationKey)) {
|
|
4049
|
+
actions.setZoomActivationKeyPressed(false);
|
|
4050
|
+
}
|
|
4051
|
+
});
|
|
4052
|
+
};
|
|
4053
|
+
onMount5(() => {
|
|
4054
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
4055
|
+
window.addEventListener("keyup", handleKeyUp);
|
|
4056
|
+
window.addEventListener("blur", resetKeysAndSelection);
|
|
4057
|
+
window.addEventListener("contextmenu", resetKeysAndSelection);
|
|
4058
|
+
onCleanup6(() => {
|
|
4059
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
4060
|
+
window.removeEventListener("keyup", handleKeyUp);
|
|
4061
|
+
window.removeEventListener("blur", resetKeysAndSelection);
|
|
4062
|
+
window.removeEventListener("contextmenu", resetKeysAndSelection);
|
|
4063
|
+
});
|
|
4064
|
+
});
|
|
4065
|
+
return null;
|
|
4066
|
+
};
|
|
4067
|
+
|
|
4068
|
+
// src/components/SolidFlow/component.tsx
|
|
4069
|
+
var SolidFlow = (props) => {
|
|
4070
|
+
let domNode;
|
|
4071
|
+
const _props = mergeProps22(
|
|
4072
|
+
{
|
|
4073
|
+
...getDefaultFlowStateProps(),
|
|
4074
|
+
colorMode: "light",
|
|
4075
|
+
deleteKeyCode: "Backspace",
|
|
4076
|
+
defaultViewport: { x: 0, y: 0, zoom: 1 },
|
|
4077
|
+
multiSelectionKeyCode: isMacOs2() ? "Meta" : "Control",
|
|
4078
|
+
nodeClickDistance: 0,
|
|
4079
|
+
panOnScroll: false,
|
|
4080
|
+
panActivationKeyCode: "Space",
|
|
4081
|
+
preventScrolling: true,
|
|
4082
|
+
panOnDrag: true,
|
|
4083
|
+
panOnScrollSpeed: 0.5,
|
|
4084
|
+
panOnScrollMode: "free",
|
|
4085
|
+
paneClickDistance: 0,
|
|
4086
|
+
reconnectRadius: 10,
|
|
4087
|
+
selectionKeyCode: "Shift",
|
|
4088
|
+
selectionOnDrag: false,
|
|
4089
|
+
translateExtent: infiniteExtent4,
|
|
4090
|
+
zoomActivationKeyCode: isMacOs2() ? "Meta" : "Control",
|
|
4091
|
+
zoomOnPinch: true,
|
|
4092
|
+
zoomOnDoubleClick: true,
|
|
4093
|
+
zoomOnScroll: true
|
|
4094
|
+
},
|
|
4095
|
+
props
|
|
4096
|
+
);
|
|
4097
|
+
const [flowProps, htmlProps] = splitProps12(_props, [
|
|
4098
|
+
// Core flow props
|
|
4099
|
+
"nodes",
|
|
4100
|
+
"edges",
|
|
4101
|
+
"nodeTypes",
|
|
4102
|
+
"edgeTypes",
|
|
4103
|
+
// Layout and viewport
|
|
4104
|
+
"width",
|
|
4105
|
+
"height",
|
|
4106
|
+
"fitView",
|
|
4107
|
+
"fitViewOptions",
|
|
4108
|
+
"nodeOrigin",
|
|
4109
|
+
"nodeDragThreshold",
|
|
4110
|
+
"paneClickDistance",
|
|
4111
|
+
"nodeClickDistance",
|
|
4112
|
+
"minZoom",
|
|
4113
|
+
"maxZoom",
|
|
4114
|
+
"initialViewport",
|
|
4115
|
+
"viewport",
|
|
4116
|
+
"translateExtent",
|
|
4117
|
+
"nodeExtent",
|
|
4118
|
+
// Interaction and behavior
|
|
4119
|
+
"selectionKey",
|
|
4120
|
+
"panActivationKey",
|
|
4121
|
+
"deleteKey",
|
|
4122
|
+
"multiSelectionKey",
|
|
4123
|
+
"zoomActivationKey",
|
|
4124
|
+
"panOnDrag",
|
|
4125
|
+
"panOnScroll",
|
|
4126
|
+
"panOnScrollMode",
|
|
4127
|
+
"panOnScrollSpeed",
|
|
4128
|
+
"selectionOnDrag",
|
|
4129
|
+
"selectNodesOnDrag",
|
|
4130
|
+
"preventScrolling",
|
|
4131
|
+
"zoomOnScroll",
|
|
4132
|
+
"zoomOnDoubleClick",
|
|
4133
|
+
"zoomOnPinch",
|
|
4134
|
+
"onlyRenderVisibleElements",
|
|
4135
|
+
"autoPanOnConnect",
|
|
4136
|
+
"autoPanOnNodeDrag",
|
|
4137
|
+
"autoPanOnNodeFocus",
|
|
4138
|
+
"autoPanSpeed",
|
|
4139
|
+
// Connection and validation
|
|
4140
|
+
"connectionRadius",
|
|
4141
|
+
"connectionMode",
|
|
4142
|
+
"connectionLineType",
|
|
4143
|
+
"connectionLineComponent",
|
|
4144
|
+
"connectionLineStyle",
|
|
4145
|
+
"connectionLineContainerStyle",
|
|
4146
|
+
"connectionDragThreshold",
|
|
4147
|
+
"isValidConnection",
|
|
4148
|
+
"clickConnect",
|
|
4149
|
+
"reconnectRadius",
|
|
4150
|
+
// Selection and accessibility
|
|
4151
|
+
"selectionMode",
|
|
4152
|
+
"elementsSelectable",
|
|
4153
|
+
"nodesDraggable",
|
|
4154
|
+
"nodesConnectable",
|
|
4155
|
+
"nodesFocusable",
|
|
4156
|
+
"edgesFocusable",
|
|
4157
|
+
"disableKeyboardA11y",
|
|
4158
|
+
"ariaLabelConfig",
|
|
4159
|
+
"ariaLiveMessage",
|
|
4160
|
+
// Styling and theming
|
|
4161
|
+
"colorMode",
|
|
4162
|
+
"colorModeSSR",
|
|
4163
|
+
"class",
|
|
4164
|
+
"style",
|
|
4165
|
+
"snapGrid",
|
|
4166
|
+
"defaultMarkerColor",
|
|
4167
|
+
"defaultEdgeOptions",
|
|
4168
|
+
"elevateNodesOnSelect",
|
|
4169
|
+
"elevateEdgesOnSelect",
|
|
4170
|
+
"noDragClass",
|
|
4171
|
+
"noPanClass",
|
|
4172
|
+
"noWheelClass",
|
|
4173
|
+
// Attribution and pro features
|
|
4174
|
+
"attributionPosition",
|
|
4175
|
+
"proOptions",
|
|
4176
|
+
// Event handlers - Flow lifecycle
|
|
4177
|
+
"onInit",
|
|
4178
|
+
"onMoveStart",
|
|
4179
|
+
"onMove",
|
|
4180
|
+
"onMoveEnd",
|
|
4181
|
+
"onFlowError",
|
|
4182
|
+
// Event handlers - Node events
|
|
4183
|
+
"onNodeClick",
|
|
4184
|
+
"onNodeContextMenu",
|
|
4185
|
+
"onNodeDrag",
|
|
4186
|
+
"onNodeDragStart",
|
|
4187
|
+
"onNodeDragStop",
|
|
4188
|
+
"onNodePointerEnter",
|
|
4189
|
+
"onNodePointerMove",
|
|
4190
|
+
"onNodePointerLeave",
|
|
4191
|
+
// Event handlers - Edge events
|
|
4192
|
+
"onEdgeClick",
|
|
4193
|
+
"onEdgeContextMenu",
|
|
4194
|
+
"onEdgePointerEnter",
|
|
4195
|
+
"onEdgePointerLeave",
|
|
4196
|
+
// Event handlers - Pane events
|
|
4197
|
+
"onPaneClick",
|
|
4198
|
+
"onPaneContextMenu",
|
|
4199
|
+
// Event handlers - Selection events
|
|
4200
|
+
"onSelectionChange",
|
|
4201
|
+
"onSelectionClick",
|
|
4202
|
+
"onSelectionContextMenu",
|
|
4203
|
+
"onSelectionDrag",
|
|
4204
|
+
"onSelectionDragStart",
|
|
4205
|
+
"onSelectionDragStop",
|
|
4206
|
+
"onSelectionStart",
|
|
4207
|
+
"onSelectionEnd",
|
|
4208
|
+
// Event handlers - Connection events
|
|
4209
|
+
"onConnect",
|
|
4210
|
+
"onConnectStart",
|
|
4211
|
+
"onConnectEnd",
|
|
4212
|
+
"onReconnect",
|
|
4213
|
+
"onReconnectStart",
|
|
4214
|
+
"onReconnectEnd",
|
|
4215
|
+
"onClickConnectStart",
|
|
4216
|
+
"onClickConnectEnd",
|
|
4217
|
+
"onBeforeConnect",
|
|
4218
|
+
"onBeforeReconnect",
|
|
4219
|
+
// Event handlers - Delete events
|
|
4220
|
+
"onDelete",
|
|
4221
|
+
"onBeforeDelete",
|
|
4222
|
+
// Legacy/deprecated props
|
|
4223
|
+
"deleteKeyCode",
|
|
4224
|
+
"selectionKeyCode",
|
|
4225
|
+
"panActivationKeyCode",
|
|
4226
|
+
"multiSelectionKeyCode",
|
|
4227
|
+
"zoomActivationKeyCode",
|
|
4228
|
+
// Special props that conflict with HTML
|
|
4229
|
+
"children"
|
|
4230
|
+
]);
|
|
4231
|
+
const TypedSolidFlowContext = SolidFlowContext;
|
|
4232
|
+
const solidFlow = useContext7(TypedSolidFlowContext) ?? createSolidFlow(_props);
|
|
4233
|
+
const { store, actions } = solidFlow;
|
|
4234
|
+
onMount6(() => {
|
|
4235
|
+
actions.applyInitialFitView(flowProps.fitView);
|
|
4236
|
+
batch9(() => {
|
|
4237
|
+
actions.setConfig(_props);
|
|
4238
|
+
actions.setDomNode(domNode);
|
|
4239
|
+
});
|
|
4240
|
+
createResizeObserver(domNode, () => {
|
|
4241
|
+
actions.setWidth(domNode.clientWidth);
|
|
4242
|
+
actions.setHeight(domNode.clientHeight);
|
|
4243
|
+
});
|
|
4244
|
+
createEffect10(() => {
|
|
4245
|
+
actions.setPaneClickDistance(flowProps.paneClickDistance);
|
|
4246
|
+
});
|
|
4247
|
+
onCleanup7(() => {
|
|
4248
|
+
actions.reset();
|
|
4249
|
+
});
|
|
4250
|
+
});
|
|
4251
|
+
const rootStyle = () => ({
|
|
4252
|
+
width: toPxString(flowProps.width),
|
|
4253
|
+
height: toPxString(flowProps.height),
|
|
4254
|
+
...flowProps.style
|
|
4255
|
+
});
|
|
4256
|
+
return <div
|
|
4257
|
+
role="application"
|
|
4258
|
+
data-testid="solid-flow__wrapper"
|
|
4259
|
+
ref={domNode}
|
|
4260
|
+
class={clsx19(["solid-flow", "solid-flow__container", flowProps.class, store.colorMode])}
|
|
4261
|
+
style={rootStyle()}
|
|
4262
|
+
onScroll={(e) => {
|
|
4263
|
+
e.currentTarget.scrollTo({ top: 0, left: 0, behavior: "auto" });
|
|
4264
|
+
}}
|
|
4265
|
+
{...htmlProps}
|
|
4266
|
+
>
|
|
4267
|
+
<TypedSolidFlowContext.Provider value={solidFlow}>
|
|
4268
|
+
<KeyHandler
|
|
4269
|
+
selectionKey={flowProps.selectionKey}
|
|
4270
|
+
deleteKey={flowProps.deleteKey}
|
|
4271
|
+
panActivationKey={flowProps.panActivationKey}
|
|
4272
|
+
multiSelectionKey={flowProps.multiSelectionKey}
|
|
4273
|
+
zoomActivationKey={flowProps.zoomActivationKey}
|
|
4274
|
+
/>
|
|
4275
|
+
<Zoom
|
|
4276
|
+
panOnScrollMode={flowProps.panOnScrollMode}
|
|
4277
|
+
preventScrolling={flowProps.preventScrolling}
|
|
4278
|
+
zoomOnScroll={flowProps.zoomOnScroll}
|
|
4279
|
+
zoomOnDoubleClick={flowProps.zoomOnDoubleClick}
|
|
4280
|
+
zoomOnPinch={flowProps.zoomOnPinch}
|
|
4281
|
+
panOnScroll={flowProps.panOnScroll}
|
|
4282
|
+
panOnDrag={flowProps.panOnDrag}
|
|
4283
|
+
paneClickDistance={flowProps.paneClickDistance}
|
|
4284
|
+
onMoveStart={flowProps.onMoveStart}
|
|
4285
|
+
onMove={flowProps.onMove}
|
|
4286
|
+
onMoveEnd={flowProps.onMoveEnd}
|
|
4287
|
+
onViewportInitialized={flowProps.onInit}
|
|
4288
|
+
initialViewport={flowProps.viewport || flowProps.initialViewport}
|
|
4289
|
+
>
|
|
4290
|
+
<Pane
|
|
4291
|
+
onPaneClick={flowProps.onPaneClick}
|
|
4292
|
+
onPaneContextMenu={flowProps.onPaneContextMenu}
|
|
4293
|
+
onSelectionStart={flowProps.onSelectionStart}
|
|
4294
|
+
onSelectionEnd={flowProps.onSelectionEnd}
|
|
4295
|
+
panOnDrag={flowProps.panOnDrag}
|
|
4296
|
+
selectionOnDrag={flowProps.selectionOnDrag}
|
|
4297
|
+
>
|
|
4298
|
+
<Viewport>
|
|
4299
|
+
<div class="solid-flow__container solid-flow__viewport-back" />
|
|
4300
|
+
<EdgeRenderer
|
|
4301
|
+
reconnectRadius={flowProps.reconnectRadius}
|
|
4302
|
+
onEdgeClick={flowProps.onEdgeClick}
|
|
4303
|
+
onEdgeContextMenu={flowProps.onEdgeContextMenu}
|
|
4304
|
+
onEdgePointerEnter={flowProps.onEdgePointerEnter}
|
|
4305
|
+
onEdgePointerLeave={flowProps.onEdgePointerLeave}
|
|
4306
|
+
defaultEdgeOptions={flowProps.defaultEdgeOptions}
|
|
4307
|
+
/>
|
|
4308
|
+
<div class="solid-flow__container solid-flow__edge-labels" />
|
|
4309
|
+
<ConnectionLine_default
|
|
4310
|
+
type={flowProps.connectionLineType}
|
|
4311
|
+
component={flowProps.connectionLineComponent}
|
|
4312
|
+
containerStyle={flowProps.connectionLineContainerStyle}
|
|
4313
|
+
style={flowProps.connectionLineStyle}
|
|
4314
|
+
/>
|
|
4315
|
+
<NodeRenderer
|
|
4316
|
+
nodeClickDistance={flowProps.nodeClickDistance}
|
|
4317
|
+
onNodeClick={flowProps.onNodeClick}
|
|
4318
|
+
onNodeContextMenu={flowProps.onNodeContextMenu}
|
|
4319
|
+
onNodePointerEnter={flowProps.onNodePointerEnter}
|
|
4320
|
+
onNodePointerMove={flowProps.onNodePointerMove}
|
|
4321
|
+
onNodePointerLeave={flowProps.onNodePointerLeave}
|
|
4322
|
+
onNodeDrag={flowProps.onNodeDrag}
|
|
4323
|
+
onNodeDragStart={flowProps.onNodeDragStart}
|
|
4324
|
+
onNodeDragStop={flowProps.onNodeDragStop}
|
|
4325
|
+
/>
|
|
4326
|
+
<NodeSelection
|
|
4327
|
+
onSelectionClick={flowProps.onSelectionClick}
|
|
4328
|
+
onSelectionContextMenu={flowProps.onSelectionContextMenu}
|
|
4329
|
+
onNodeDrag={flowProps.onNodeDrag}
|
|
4330
|
+
onNodeDragStart={flowProps.onNodeDragStart}
|
|
4331
|
+
onNodeDragStop={flowProps.onNodeDragStop}
|
|
4332
|
+
/>
|
|
4333
|
+
</Viewport>
|
|
4334
|
+
<Selection
|
|
4335
|
+
isVisible={!!store.selectionRect && store.selectionRectMode === "user"}
|
|
4336
|
+
width={store.selectionRect?.width}
|
|
4337
|
+
height={store.selectionRect?.height}
|
|
4338
|
+
x={store.selectionRect?.x}
|
|
4339
|
+
y={store.selectionRect?.y}
|
|
4340
|
+
/>
|
|
4341
|
+
</Pane>
|
|
4342
|
+
</Zoom>
|
|
4343
|
+
<Attribution proOptions={flowProps.proOptions} position={flowProps.attributionPosition} />
|
|
4344
|
+
<A11yDescriptions />
|
|
4345
|
+
{flowProps.children}
|
|
4346
|
+
</TypedSolidFlowContext.Provider>
|
|
4347
|
+
</div>;
|
|
4348
|
+
};
|
|
4349
|
+
|
|
4350
|
+
// src/components/SolidFlow/provider.tsx
|
|
4351
|
+
import { mergeProps as mergeProps23, onCleanup as onCleanup8 } from "solid-js";
|
|
4352
|
+
var SolidFlowProvider = (props) => {
|
|
4353
|
+
const _props = mergeProps23(getDefaultFlowStateProps(), props);
|
|
4354
|
+
const solidFlow = createSolidFlow(_props);
|
|
4355
|
+
onCleanup8(() => {
|
|
4356
|
+
solidFlow.actions.reset();
|
|
4357
|
+
});
|
|
4358
|
+
const ContextProvider = SolidFlowContext.Provider;
|
|
4359
|
+
return <ContextProvider value={solidFlow}>{props.children}</ContextProvider>;
|
|
4360
|
+
};
|
|
4361
|
+
|
|
4362
|
+
// src/data/createEdgeStore.tsx
|
|
4363
|
+
import { createStore as createStore2 } from "solid-js/store";
|
|
4364
|
+
var createEdgeStore = (edges) => {
|
|
4365
|
+
const [store, setStore] = createStore2(edges);
|
|
4366
|
+
return [store, setStore];
|
|
4367
|
+
};
|
|
4368
|
+
|
|
4369
|
+
// src/data/createNodeStore.tsx
|
|
4370
|
+
import { createStore as createStore3 } from "solid-js/store";
|
|
4371
|
+
var createNodeStore = (nodes) => {
|
|
4372
|
+
const [store, setStore] = createStore3(nodes);
|
|
4373
|
+
return [store, setStore];
|
|
4374
|
+
};
|
|
4375
|
+
|
|
4376
|
+
// src/index.tsx
|
|
4377
|
+
import {
|
|
4378
|
+
addEdge,
|
|
4379
|
+
getBezierEdgeCenter,
|
|
4380
|
+
getBezierPath as getBezierPath4,
|
|
4381
|
+
getConnectedEdges,
|
|
4382
|
+
getEdgeCenter,
|
|
4383
|
+
getIncomers,
|
|
4384
|
+
getNodesBounds as getNodesBounds2,
|
|
4385
|
+
getOutgoers,
|
|
4386
|
+
getSmoothStepPath as getSmoothStepPath6,
|
|
4387
|
+
getStraightPath as getStraightPath4,
|
|
4388
|
+
getViewportForBounds as getViewportForBounds3
|
|
4389
|
+
} from "@xyflow/system";
|
|
4390
|
+
import {
|
|
4391
|
+
ConnectionLineType,
|
|
4392
|
+
ConnectionMode as ConnectionMode4,
|
|
4393
|
+
MarkerType,
|
|
4394
|
+
PanOnScrollMode,
|
|
4395
|
+
Position as Position2,
|
|
4396
|
+
ResizeControlVariant,
|
|
4397
|
+
SelectionMode as SelectionMode2
|
|
4398
|
+
} from "@xyflow/system";
|
|
4399
|
+
export {
|
|
4400
|
+
Background,
|
|
4401
|
+
BaseEdge,
|
|
4402
|
+
BezierEdge,
|
|
4403
|
+
BezierEdgeInternal,
|
|
4404
|
+
ConnectionLine_default as ConnectionLine,
|
|
4405
|
+
ConnectionLineType,
|
|
4406
|
+
ConnectionMode4 as ConnectionMode,
|
|
4407
|
+
ControlButton,
|
|
4408
|
+
Controls,
|
|
4409
|
+
DefaultNode,
|
|
4410
|
+
EdgeLabel,
|
|
4411
|
+
EdgeLabelRenderer,
|
|
4412
|
+
EdgeReconnectAnchor,
|
|
4413
|
+
EdgeRenderer,
|
|
4414
|
+
EdgeWrapper,
|
|
4415
|
+
GroupNode,
|
|
4416
|
+
Handle,
|
|
4417
|
+
InputNode,
|
|
4418
|
+
Marker,
|
|
4419
|
+
MarkerDefinition,
|
|
4420
|
+
MarkerType,
|
|
4421
|
+
MiniMap,
|
|
4422
|
+
NodeRenderer,
|
|
4423
|
+
NodeResizer,
|
|
4424
|
+
NodeSelection,
|
|
4425
|
+
NodeToolbar,
|
|
4426
|
+
NodeWrapper,
|
|
4427
|
+
OutputNode,
|
|
4428
|
+
PanOnScrollMode,
|
|
4429
|
+
Pane,
|
|
4430
|
+
Panel,
|
|
4431
|
+
Position2 as Position,
|
|
4432
|
+
ResizeControl,
|
|
4433
|
+
ResizeControlVariant,
|
|
4434
|
+
Selection,
|
|
4435
|
+
SelectionMode2 as SelectionMode,
|
|
4436
|
+
SmoothStepEdge,
|
|
4437
|
+
SmoothStepEdgeInternal,
|
|
4438
|
+
SolidFlow,
|
|
4439
|
+
SolidFlowProvider,
|
|
4440
|
+
StepEdge,
|
|
4441
|
+
StepEdgeInternal,
|
|
4442
|
+
StraightEdge,
|
|
4443
|
+
StraightEdgeInternal,
|
|
4444
|
+
Viewport,
|
|
4445
|
+
ViewportPortal,
|
|
4446
|
+
Zoom,
|
|
4447
|
+
addEdge,
|
|
4448
|
+
createEdgeStore,
|
|
4449
|
+
createNodeStore,
|
|
4450
|
+
getBezierEdgeCenter,
|
|
4451
|
+
getBezierPath4 as getBezierPath,
|
|
4452
|
+
getConnectedEdges,
|
|
4453
|
+
getEdgeCenter,
|
|
4454
|
+
getIncomers,
|
|
4455
|
+
getNodesBounds2 as getNodesBounds,
|
|
4456
|
+
getOutgoers,
|
|
4457
|
+
getSmoothStepPath6 as getSmoothStepPath,
|
|
4458
|
+
getStraightPath4 as getStraightPath,
|
|
4459
|
+
getViewportForBounds3 as getViewportForBounds,
|
|
4460
|
+
useConnection,
|
|
4461
|
+
useEdges,
|
|
4462
|
+
useHandleEdgeSelect,
|
|
4463
|
+
useInternalNode,
|
|
4464
|
+
useNodeConnections,
|
|
4465
|
+
useNodes,
|
|
4466
|
+
useNodesData,
|
|
4467
|
+
useSolidFlow,
|
|
4468
|
+
useUpdateNodeInternals,
|
|
4469
|
+
useViewport
|
|
4470
|
+
};
|