@dschz/solid-flow 0.2.3 → 0.3.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index/index.d.ts +5 -4
- package/dist/index/index.js +1258 -1375
- package/dist/index/index.jsx +608 -693
- package/package.json +15 -20
package/dist/index/index.jsx
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { For,
|
|
1
|
+
import { For, Show, createContext, createEffect, createMemo, createRenderEffect, createSignal, createStore, flush, mapArray, merge, omit, onCleanup, onSettled, snapshot, untrack, useContext } from "solid-js";
|
|
2
2
|
import { ReactiveMap } from "@solid-primitives/map";
|
|
3
3
|
import { createMediaQuery } from "@solid-primitives/media";
|
|
4
|
-
import { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, ResizeControlVariant, SelectionMode, SelectionMode as SelectionMode$1, XYDrag, XYHandle, XYMinimap, XYPanZoom, XYResizer, XY_RESIZER_HANDLE_POSITIONS, XY_RESIZER_LINE_POSITIONS, addEdge, addEdge as addEdge$1, areConnectionMapsEqual, calcAutoPan, calculateNodePosition, clampPosition, clampPositionToParent, createDevWarn, createMarkerIds, elementSelectionKeys, evaluateAbsolutePosition, fitViewport, getBezierEdgeCenter, getBezierPath, getBezierPath as getBezierPath$1, getBoundsOfRects, getConnectedEdges, getConnectionStatus, getEdgeCenter, getEdgePosition, getEdgeToolbarTransform, getElementsToRemove, getElevatedEdgeZIndex, getEventPosition, getHostForElement, getIncomers, getInternalNodesBounds, getMarkerId, getNodeDimensions, getNodePositionWithOrigin, getNodeToolbarTransform, getNodesBounds, getNodesBounds as getNodesBounds$1, getNodesInside, getOutgoers, getOverlappingArea, getSmoothStepPath, getSmoothStepPath as getSmoothStepPath$1, getStraightPath, getStraightPath as getStraightPath$1, getViewportForBounds, getViewportForBounds as getViewportForBounds$1, handleConnectionChange, infiniteExtent, initialConnection, isCoordinateExtent, isEdgeBase, isEdgeVisible, isInputDOMNode, isMacOs, isNodeBase, isNumeric, isRectObject, mergeAriaLabelConfig, nodeHasDimensions, nodeToRect, panBy, pointToRendererPoint, rendererPointToPoint, shallowNodeData, snapPosition, updateAbsolutePositions, updateNodeInternals } from "@xyflow/system";
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import { Dynamic, Portal, isServer } from "solid-js/web";
|
|
8
|
-
import { createResizeObserver } from "@solid-primitives/resize-observer";
|
|
4
|
+
import { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, Position as Position$1, ResizeControlVariant, SelectionMode, SelectionMode as SelectionMode$1, XYDrag, XYHandle, XYMinimap, XYPanZoom, XYResizer, XY_RESIZER_HANDLE_POSITIONS, XY_RESIZER_LINE_POSITIONS, addEdge, addEdge as addEdge$1, areConnectionMapsEqual, calcAutoPan, calculateNodePosition, clampPosition, clampPositionToParent, createDevWarn, createMarkerIds, elementSelectionKeys, evaluateAbsolutePosition, fitViewport, getBezierEdgeCenter, getBezierPath, getBezierPath as getBezierPath$1, getBoundsOfRects, getConnectedEdges, getConnectionStatus, getEdgeCenter, getEdgePosition, getEdgeToolbarTransform, getElementsToRemove, getElevatedEdgeZIndex, getEventPosition, getHostForElement, getIncomers, getInternalNodesBounds, getMarkerId, getNodeDimensions, getNodePositionWithOrigin, getNodeToolbarTransform, getNodesBounds, getNodesBounds as getNodesBounds$1, getNodesInside, getOutgoers, getOverlappingArea, getSmoothStepPath, getSmoothStepPath as getSmoothStepPath$1, getStraightPath, getStraightPath as getStraightPath$1, getViewportForBounds, getViewportForBounds as getViewportForBounds$1, handleConnectionChange, infiniteExtent, initialConnection, isCoordinateExtent, isEdgeBase, isEdgeVisible, isInputDOMNode, isMacOs, isNodeBase, isNumeric, isRectObject, mergeAriaLabelConfig, nodeHasDimensions, nodeToRect, panBy, pointToRendererPoint, rendererPointToPoint, shallowNodeData, snapPosition, updateAbsolutePositions, updateNodeInternals } from "@xyflow/system";
|
|
5
|
+
import { Dynamic, Portal, isServer } from "@solidjs/web";
|
|
6
|
+
import { createEventListener, createEventListenerMap } from "@solid-primitives/event-listener";
|
|
9
7
|
//#region src/components/contexts/edgeId.tsx
|
|
10
|
-
const EdgeIdContext = createContext();
|
|
8
|
+
const EdgeIdContext = createContext(null);
|
|
11
9
|
function useEdgeId() {
|
|
12
10
|
let ctx = useContext(EdgeIdContext);
|
|
13
11
|
if (!ctx) throw Error("solid-flow: Your application must be wrapped with <SolidFlow> in order to invoke useEdgeId");
|
|
@@ -39,104 +37,67 @@ const isNode = (element) => isNodeBase(element), isEdge = (element) => isEdgeBas
|
|
|
39
37
|
x: 1,
|
|
40
38
|
y: 0
|
|
41
39
|
}
|
|
42
|
-
};
|
|
40
|
+
}, scheduleIdleCallback = typeof requestIdleCallback == "function" ? requestIdleCallback : (callback) => setTimeout(callback, 0);
|
|
43
41
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* ```ts
|
|
50
|
-
* const [width, setWidth] = createWritable(() => config().width);
|
|
51
|
-
* // width() will return config().width initially
|
|
52
|
-
* // setWidth(100) will update the signal to 100
|
|
53
|
-
* // If config().width changes, a new signal width() is updated to the new value
|
|
54
|
-
* ```
|
|
42
|
+
* Reactive prop defaulting with skip-undefined semantics: a prop counts as
|
|
43
|
+
* "absent" when it reads `undefined`, so parents forwarding optional props
|
|
44
|
+
* (e.g. `<Handle position={props.targetPosition} />`) do not clobber defaults.
|
|
45
|
+
* This is deliberate policy on top of Solid 2.0's `merge`, where `undefined`
|
|
46
|
+
* is a real value that overrides.
|
|
55
47
|
*/
|
|
56
|
-
function
|
|
57
|
-
let
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
let [get, set] = createStore(accessor());
|
|
63
|
-
return {
|
|
64
|
-
get,
|
|
65
|
-
set
|
|
66
|
-
};
|
|
48
|
+
function propDefaults(props, defaults) {
|
|
49
|
+
let out = {}, keys = /* @__PURE__ */ new Set([...Object.keys(defaults), ...Object.keys(props)]);
|
|
50
|
+
for (let key of keys) Object.defineProperty(out, key, {
|
|
51
|
+
get: () => props[key] === void 0 ? defaults[key] : props[key],
|
|
52
|
+
enumerable: !0,
|
|
53
|
+
configurable: !0
|
|
67
54
|
});
|
|
68
|
-
return
|
|
69
|
-
get() {
|
|
70
|
-
return storeMemo().get;
|
|
71
|
-
},
|
|
72
|
-
get set() {
|
|
73
|
-
return storeMemo().set;
|
|
74
|
-
}
|
|
75
|
-
};
|
|
55
|
+
return out;
|
|
76
56
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
*/
|
|
81
|
-
const scheduleIdleCallback = typeof requestIdleCallback == "function" ? requestIdleCallback : (callback) => setTimeout(callback, 0), EdgeLabelRenderer = (props) => {
|
|
57
|
+
//#endregion
|
|
58
|
+
//#region src/components/graph/edge/EdgeLabelRenderer.tsx
|
|
59
|
+
const EdgeLabelRenderer = (props) => {
|
|
82
60
|
let { store } = useInternalSolidFlow(), labelNode = () => store.domNode?.querySelector(".solid-flow__edge-labels");
|
|
83
61
|
return <Show when={labelNode()}>{(root) => <Portal mount={root()}>{props.children}</Portal>}</Show>;
|
|
84
62
|
}, EdgeLabel = (props) => {
|
|
85
|
-
let _props =
|
|
63
|
+
let _props = propDefaults(props, {
|
|
86
64
|
x: 0,
|
|
87
65
|
y: 0,
|
|
88
66
|
selectEdgeOnClick: !1,
|
|
89
67
|
transparent: !1,
|
|
90
68
|
style: {}
|
|
91
|
-
},
|
|
92
|
-
"x",
|
|
93
|
-
"y",
|
|
94
|
-
"width",
|
|
95
|
-
"height",
|
|
96
|
-
"selectEdgeOnClick",
|
|
97
|
-
"transparent",
|
|
98
|
-
"children",
|
|
99
|
-
"class",
|
|
100
|
-
"style"
|
|
101
|
-
]), { actions } = useInternalSolidFlow(), id = useEdgeId(), zIndex = () => actions.getEdge(id())?.zIndex;
|
|
69
|
+
}), rest = omit(_props, "x", "y", "width", "height", "selectEdgeOnClick", "transparent", "children", "class", "style"), { actions } = useInternalSolidFlow(), id = useEdgeId(), zIndex = () => actions.getEdge(id())?.zIndex;
|
|
102
70
|
return <EdgeLabelRenderer>
|
|
103
|
-
<div role="button"
|
|
71
|
+
<div role="button" tabindex={-1} class={[
|
|
72
|
+
"solid-flow__edge-label",
|
|
73
|
+
{ transparent: _props.transparent },
|
|
74
|
+
_props.class
|
|
75
|
+
]} style={{
|
|
104
76
|
"pointer-events": "all",
|
|
105
|
-
width: toPxString(
|
|
106
|
-
height: toPxString(
|
|
107
|
-
transform: `translate(-50%, -50%) translate(${
|
|
108
|
-
cursor:
|
|
77
|
+
width: toPxString(_props.width),
|
|
78
|
+
height: toPxString(_props.height),
|
|
79
|
+
transform: `translate(-50%, -50%) translate(${_props.x}px,${_props.y}px)`,
|
|
80
|
+
cursor: _props.selectEdgeOnClick ? "pointer" : void 0,
|
|
109
81
|
"z-index": zIndex(),
|
|
110
|
-
...
|
|
82
|
+
..._props.style
|
|
111
83
|
}} onClick={() => {
|
|
112
|
-
|
|
84
|
+
_props.selectEdgeOnClick && actions.handleEdgeSelection(id());
|
|
113
85
|
}} {...rest}>
|
|
114
|
-
{
|
|
86
|
+
{_props.children}
|
|
115
87
|
</div>
|
|
116
88
|
</EdgeLabelRenderer>;
|
|
117
89
|
}, BaseEdge = (props) => {
|
|
118
|
-
let _props =
|
|
119
|
-
"class",
|
|
120
|
-
"style",
|
|
121
|
-
"path",
|
|
122
|
-
"interactionWidth",
|
|
123
|
-
"label",
|
|
124
|
-
"labelStyle",
|
|
125
|
-
"labelX",
|
|
126
|
-
"labelY",
|
|
127
|
-
"markerStart",
|
|
128
|
-
"markerEnd"
|
|
129
|
-
]);
|
|
90
|
+
let _props = propDefaults(props, { interactionWidth: 20 }), rest = omit(_props, "class", "style", "path", "interactionWidth", "label", "labelStyle", "labelX", "labelY", "markerStart", "markerEnd");
|
|
130
91
|
return <>
|
|
131
|
-
<path d={
|
|
92
|
+
<path d={_props.path} class={["solid-flow__edge-path", _props.class]} marker-start={_props.markerStart} marker-end={_props.markerEnd} fill="none" style={_props.style} {...rest} />
|
|
132
93
|
|
|
133
|
-
<Show when={
|
|
134
|
-
<path d={
|
|
94
|
+
<Show when={_props.interactionWidth > 0}>
|
|
95
|
+
<path d={_props.path} stroke-opacity={0} stroke-width={_props.interactionWidth} fill="none" class="solid-flow__edge-interaction" />
|
|
135
96
|
</Show>
|
|
136
97
|
|
|
137
|
-
<Show when={
|
|
138
|
-
<EdgeLabel x={
|
|
139
|
-
{
|
|
98
|
+
<Show when={_props.label}>
|
|
99
|
+
<EdgeLabel x={_props.labelX} y={_props.labelY} style={_props.labelStyle}>
|
|
100
|
+
{_props.label}
|
|
140
101
|
</EdgeLabel>
|
|
141
102
|
</Show>
|
|
142
103
|
</>;
|
|
@@ -176,24 +137,16 @@ const scheduleIdleCallback = typeof requestIdleCallback == "function" ? requestI
|
|
|
176
137
|
};
|
|
177
138
|
return <BaseEdge path={pathData().path} labelX={pathData().labelX} labelY={pathData().labelY} label={props.label} labelStyle={props.labelStyle} markerStart={props.markerStart} markerEnd={props.markerEnd} interactionWidth={props.interactionWidth} style={props.style} />;
|
|
178
139
|
}, EdgeReconnectAnchor = (props) => {
|
|
179
|
-
let _props =
|
|
140
|
+
let _props = propDefaults(props, {
|
|
180
141
|
size: 25,
|
|
181
142
|
reconnecting: !1,
|
|
182
143
|
style: {}
|
|
183
|
-
},
|
|
184
|
-
"type",
|
|
185
|
-
"class",
|
|
186
|
-
"style",
|
|
187
|
-
"position",
|
|
188
|
-
"size",
|
|
189
|
-
"reconnecting",
|
|
190
|
-
"children"
|
|
191
|
-
]), { store, nodeLookup, edgeLookup, actions } = useInternalSolidFlow(), edgeId = useEdgeId(), [reconnecting, setReconnecting] = createSignal(!1);
|
|
144
|
+
}), rest = omit(_props, "type", "class", "style", "position", "size", "reconnecting", "children"), { store, nodeLookup, edgeLookup, actions } = useInternalSolidFlow(), edgeId = useEdgeId(), [reconnecting, setReconnecting] = createSignal(!1);
|
|
192
145
|
if (!edgeId()) throw Error("[solid-flow]: EdgeReconnectAnchor must be used within an Edge component");
|
|
193
146
|
let edge = () => edgeLookup.get(edgeId()), onPointerDown = (event) => {
|
|
194
147
|
if (event.button !== 0) return;
|
|
195
|
-
setReconnecting(!0), store.onReconnectStart?.(event, edge(),
|
|
196
|
-
let opposite =
|
|
148
|
+
setReconnecting(!0), store.onReconnectStart?.(event, edge(), _props.type);
|
|
149
|
+
let opposite = _props.type === "target" ? {
|
|
197
150
|
nodeId: edge().source,
|
|
198
151
|
handleId: edge().sourceHandle ?? null,
|
|
199
152
|
type: "source"
|
|
@@ -237,16 +190,21 @@ const scheduleIdleCallback = typeof requestIdleCallback == "function" ? requestI
|
|
|
237
190
|
handleDomNode: event.currentTarget
|
|
238
191
|
});
|
|
239
192
|
};
|
|
240
|
-
return <EdgeLabel x={
|
|
241
|
-
<div onPointerDown={onPointerDown} class={
|
|
242
|
-
|
|
243
|
-
|
|
193
|
+
return <EdgeLabel x={_props.position?.x} y={_props.position?.y} style={_props.style} {...rest}>
|
|
194
|
+
<div onPointerDown={onPointerDown} class={[
|
|
195
|
+
"solid-flow__edgeupdater",
|
|
196
|
+
`solid-flow__edgeupdater-${_props.type}`,
|
|
197
|
+
store.noPanClass,
|
|
198
|
+
_props.class
|
|
199
|
+
]} style={{
|
|
200
|
+
width: toPxString(_props.size),
|
|
201
|
+
height: toPxString(_props.size),
|
|
244
202
|
background: "transparent",
|
|
245
203
|
border: "none",
|
|
246
204
|
cursor: "move",
|
|
247
|
-
...
|
|
205
|
+
..._props.style
|
|
248
206
|
}}>
|
|
249
|
-
<Show when={!reconnecting()}>{
|
|
207
|
+
<Show when={!reconnecting()}>{_props.children}</Show>
|
|
250
208
|
</div>
|
|
251
209
|
</EdgeLabel>;
|
|
252
210
|
}, ARIA_NODE_DESC_KEY = "solid-flow__node-desc", ARIA_EDGE_DESC_KEY = "solid-flow__edge-desc", A11yDescriptions = () => {
|
|
@@ -283,19 +241,24 @@ const scheduleIdleCallback = typeof requestIdleCallback == "function" ? requestI
|
|
|
283
241
|
}, onKeyDown = (event) => {
|
|
284
242
|
store.disableKeyboardA11y || !elementSelectionKeys.includes(event.key) || !selectable() || (event.key === "Escape" ? actions.unselectNodesAndEdges({ edges: [edge()] }) : actions.addSelectedEdges([edge().id]));
|
|
285
243
|
}, ariaLabel = () => edge().ariaLabel ?? `Edge from ${edge().source} to ${edge().target}`;
|
|
286
|
-
return <EdgeIdContext
|
|
244
|
+
return <EdgeIdContext value={edgeId}>
|
|
287
245
|
<Show when={!edge().hidden}>
|
|
288
246
|
<svg class="solid-flow__edge-wrapper" style={{ "z-index": edge().zIndex }}>
|
|
289
|
-
<g ref={edgeRef} data-id={edge().id}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
247
|
+
<g ref={edgeRef} data-id={edge().id} tabindex={focusable() ? 0 : void 0} role={edge().ariaRole ?? (focusable() ? "group" : "img")} aria-label={ariaLabel()} aria-roledescription="edge" aria-describedby={focusable() ? `${ARIA_EDGE_DESC_KEY}-${store.id}` : void 0} class={[
|
|
248
|
+
"solid-flow__edge",
|
|
249
|
+
`solid-flow__edge-${edgeType()}`,
|
|
250
|
+
{
|
|
251
|
+
animated: !!edge().animated,
|
|
252
|
+
selected: !!edge().selected,
|
|
253
|
+
selectable: !!selectable()
|
|
254
|
+
},
|
|
255
|
+
edge().class
|
|
256
|
+
]} onClick={onClick} onKeyDown={(e) => focusable() && onKeyDown(e)} onContextMenu={(e) => onPointerEvent(e, "contextmenu")} onPointerEnter={(e) => onPointerEvent(e, "pointerenter")} onPointerLeave={(e) => onPointerEvent(e, "pointerleave")} {...edge().domAttributes}>
|
|
294
257
|
<Dynamic component={edgeComponent()} id={edge().id} source={edge().source} target={edge().target} sourceX={edge().sourceX} sourceY={edge().sourceY} targetX={edge().targetX} targetY={edge().targetY} sourcePosition={edge().sourcePosition} targetPosition={edge().targetPosition} animated={edge().animated} selected={edge().selected} label={edge().label} labelStyle={edge().labelStyle} data={edge().data} style={edge().style} interactionWidth={edge().interactionWidth} selectable={selectable()} deletable={edge().deletable ?? !0} type={edgeType()} sourceHandleId={edge().sourceHandle} targetHandleId={edge().targetHandle} markerStart={markerStartUrl()} markerEnd={markerEndUrl()} />
|
|
295
258
|
</g>
|
|
296
259
|
</svg>
|
|
297
260
|
</Show>
|
|
298
|
-
</EdgeIdContext
|
|
261
|
+
</EdgeIdContext>;
|
|
299
262
|
}, SmoothStepEdge = (props) => {
|
|
300
263
|
let pathData = createMemo(() => {
|
|
301
264
|
let [path, labelX, labelY] = getSmoothStepPath$1({
|
|
@@ -402,7 +365,7 @@ const scheduleIdleCallback = typeof requestIdleCallback == "function" ? requestI
|
|
|
402
365
|
}, getEdgeId = (connection) => {
|
|
403
366
|
let { source, sourceHandle, target, targetHandle } = connection;
|
|
404
367
|
return `xy-edge__${source}${sourceHandle || ""}-${target}${targetHandle || ""}`;
|
|
405
|
-
}, NodeConnectableContext = createContext();
|
|
368
|
+
}, NodeConnectableContext = createContext(null);
|
|
406
369
|
function useNodeConnectable() {
|
|
407
370
|
let ctx = useContext(NodeConnectableContext);
|
|
408
371
|
if (!ctx) throw Error("solid-flow: Your application must be wrapped with <SolidFlow> in order to invoke useNodeConnectable");
|
|
@@ -411,30 +374,20 @@ function useNodeConnectable() {
|
|
|
411
374
|
//#endregion
|
|
412
375
|
//#region src/components/graph/handle/Handle.tsx
|
|
413
376
|
const Handle = (props) => {
|
|
414
|
-
let _props =
|
|
415
|
-
id: null,
|
|
377
|
+
let _props = propDefaults(props, {
|
|
416
378
|
type: "source",
|
|
417
379
|
position: "top",
|
|
418
380
|
isConnectableStart: !0,
|
|
419
381
|
isConnectableEnd: !0
|
|
420
|
-
}
|
|
421
|
-
"id",
|
|
422
|
-
"type",
|
|
423
|
-
"position",
|
|
424
|
-
"isConnectable",
|
|
425
|
-
"isConnectableStart",
|
|
426
|
-
"isConnectableEnd",
|
|
427
|
-
"isValidConnection",
|
|
428
|
-
"onConnect",
|
|
429
|
-
"onDisconnect",
|
|
430
|
-
"children",
|
|
431
|
-
"class",
|
|
432
|
-
"style"
|
|
433
|
-
]), nodeId = useNodeId(), nodeConnectable = useNodeConnectable(), connectable = () => local.isConnectable ?? nodeConnectable(), isTarget = () => local.type === "target", handleId = () => local.id ?? null, connectionInProcess = () => !!store.connection.fromHandle, connectingFrom = () => store.connection.fromHandle && store.connection.fromHandle.nodeId === nodeId() && store.connection.fromHandle.type === local.type && store.connection.fromHandle.id === handleId(), connectingTo = () => store.connection.toHandle && store.connection.toHandle.nodeId === nodeId() && store.connection.toHandle.type === local.type && store.connection.toHandle.id === handleId(), isPossibleTargetHandle = () => store.connectionMode === "strict" ? store.connection.fromHandle?.type !== local.type : nodeId() !== store.connection.fromHandle?.nodeId || handleId() !== store.connection.fromHandle?.id, valid = () => !!(connectingTo() && store.connection.isValid), prevConnections = null, connections;
|
|
382
|
+
}), { store, nodeLookup, connectionLookup, actions } = useInternalSolidFlow(), rest = omit(_props, "id", "type", "position", "isConnectable", "isConnectableStart", "isConnectableEnd", "isValidConnection", "onConnect", "onDisconnect", "children", "class", "style"), nodeId = useNodeId(), nodeConnectable = useNodeConnectable(), connectable = () => _props.isConnectable ?? nodeConnectable(), isTarget = () => _props.type === "target", handleId = () => _props.id ?? null, connectionInProcess = () => !!store.connection.fromHandle, connectingFrom = () => store.connection.fromHandle && store.connection.fromHandle.nodeId === nodeId() && store.connection.fromHandle.type === _props.type && store.connection.fromHandle.id === handleId(), connectingTo = () => store.connection.toHandle && store.connection.toHandle.nodeId === nodeId() && store.connection.toHandle.type === _props.type && store.connection.toHandle.id === handleId(), isPossibleTargetHandle = () => store.connectionMode === "strict" ? store.connection.fromHandle?.type !== _props.type : nodeId() !== store.connection.fromHandle?.nodeId || handleId() !== store.connection.fromHandle?.id, valid = () => !!(connectingTo() && store.connection.isValid), prevConnections = null;
|
|
434
383
|
createEffect(() => {
|
|
435
|
-
if (!
|
|
436
|
-
let
|
|
437
|
-
|
|
384
|
+
if (!_props.onConnect && !_props.onDisconnect) return null;
|
|
385
|
+
let connectionKey = `${nodeId()}-${_props.type}${_props.id ? `-${_props.id}` : ""}`;
|
|
386
|
+
return { connections: connectionLookup.get(connectionKey) };
|
|
387
|
+
}, (current) => {
|
|
388
|
+
if (!current) return;
|
|
389
|
+
let { connections } = current;
|
|
390
|
+
if (prevConnections && !areConnectionMapsEqual(connections, prevConnections)) {
|
|
438
391
|
let _connections = connections ?? /* @__PURE__ */ new Map();
|
|
439
392
|
handleConnectionChange(prevConnections, _connections, props.onDisconnect), handleConnectionChange(_connections, prevConnections, props.onConnect);
|
|
440
393
|
}
|
|
@@ -458,8 +411,10 @@ const Handle = (props) => {
|
|
|
458
411
|
lib: store.lib,
|
|
459
412
|
autoPanOnConnect: store.autoPanOnConnect,
|
|
460
413
|
flowId: store.id,
|
|
461
|
-
isValidConnection:
|
|
462
|
-
updateConnection:
|
|
414
|
+
isValidConnection: _props.isValidConnection ?? store.isValidConnection,
|
|
415
|
+
updateConnection: ((connection) => {
|
|
416
|
+
actions.setConnection(connection), flush();
|
|
417
|
+
}),
|
|
463
418
|
cancelConnection: actions.cancelConnection,
|
|
464
419
|
panBy: actions.panBy,
|
|
465
420
|
onConnect: onConnectExtended,
|
|
@@ -478,24 +433,24 @@ const Handle = (props) => {
|
|
|
478
433
|
handleDomNode: event.currentTarget
|
|
479
434
|
});
|
|
480
435
|
}, onClick = (event) => {
|
|
481
|
-
if (!nodeId() || !store.clickConnectStartHandle && !
|
|
436
|
+
if (!nodeId() || !store.clickConnectStartHandle && !_props.isConnectableStart) return;
|
|
482
437
|
if (!store.clickConnectStartHandle) {
|
|
483
438
|
store.onClickConnectStart?.(event, {
|
|
484
439
|
nodeId: nodeId(),
|
|
485
440
|
handleId: handleId(),
|
|
486
|
-
handleType:
|
|
441
|
+
handleType: _props.type
|
|
487
442
|
}), actions.setClickConnectStartHandle({
|
|
488
443
|
nodeId: nodeId(),
|
|
489
|
-
type:
|
|
444
|
+
type: _props.type,
|
|
490
445
|
id: handleId()
|
|
491
446
|
});
|
|
492
447
|
return;
|
|
493
448
|
}
|
|
494
|
-
let doc = getHostForElement(event.target), isValidConnectionHandler =
|
|
449
|
+
let doc = getHostForElement(event.target), isValidConnectionHandler = _props.isValidConnection ?? store.isValidConnection, { connection, isValid } = XYHandle.isValid(event, {
|
|
495
450
|
handle: {
|
|
496
451
|
nodeId: nodeId(),
|
|
497
452
|
id: handleId(),
|
|
498
|
-
type:
|
|
453
|
+
type: _props.type
|
|
499
454
|
},
|
|
500
455
|
connectionMode: store.connectionMode,
|
|
501
456
|
fromNodeId: store.clickConnectStartHandle.nodeId,
|
|
@@ -508,27 +463,34 @@ const Handle = (props) => {
|
|
|
508
463
|
nodeLookup
|
|
509
464
|
});
|
|
510
465
|
isValid && connection && onConnectExtended(connection);
|
|
511
|
-
let connectionClone = structuredClone(
|
|
466
|
+
let connectionClone = structuredClone(snapshot(store.connection));
|
|
512
467
|
delete connectionClone.inProgress, connectionClone.toPosition = connectionClone.toHandle ? connectionClone.toHandle.position : null, store.onClickConnectEnd?.(event, connectionClone), actions.setClickConnectStartHandle(void 0);
|
|
513
|
-
}, connectionIndicator = () => connectable() && (!connectionInProcess() || isPossibleTargetHandle()) && (connectionInProcess() || store.clickConnectStartHandle ?
|
|
514
|
-
return <div role="button" aria-label={store.ariaLabelConfig["handle.ariaLabel"]}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
468
|
+
}, connectionIndicator = () => connectable() && (!connectionInProcess() || isPossibleTargetHandle()) && (connectionInProcess() || store.clickConnectStartHandle ? _props.isConnectableEnd : _props.isConnectableStart);
|
|
469
|
+
return <div {...rest} role="button" aria-label={store.ariaLabelConfig["handle.ariaLabel"]} tabindex={-1} data-handleid={handleId()} data-nodeid={nodeId()} data-handlepos={_props.position} data-id={`${store.id}-${nodeId()}-${_props.id || null}-${_props.type}`} onClick={store.clickConnect ? onClick : void 0} onPointerDown={onPointerDown} style={_props.style} class={[
|
|
470
|
+
"solid-flow__handle",
|
|
471
|
+
`solid-flow__handle-${_props.position}`,
|
|
472
|
+
store.noDragClass,
|
|
473
|
+
store.noPanClass,
|
|
474
|
+
_props.class,
|
|
475
|
+
{
|
|
476
|
+
valid: valid(),
|
|
477
|
+
connectingto: !!connectingTo(),
|
|
478
|
+
connectingfrom: !!connectingFrom(),
|
|
479
|
+
source: !isTarget(),
|
|
480
|
+
target: isTarget(),
|
|
481
|
+
connectablestart: _props.isConnectableStart,
|
|
482
|
+
connectableend: _props.isConnectableEnd,
|
|
483
|
+
connectable: !!connectable(),
|
|
484
|
+
connectionindicator: connectionIndicator()
|
|
485
|
+
}
|
|
486
|
+
]}>
|
|
487
|
+
{_props.children}
|
|
526
488
|
</div>;
|
|
527
489
|
}, DefaultNode = (props) => {
|
|
528
|
-
let _props =
|
|
529
|
-
targetPosition:
|
|
530
|
-
sourcePosition:
|
|
531
|
-
}
|
|
490
|
+
let _props = propDefaults(props, {
|
|
491
|
+
targetPosition: Position$1.Top,
|
|
492
|
+
sourcePosition: Position$1.Bottom
|
|
493
|
+
});
|
|
532
494
|
return <>
|
|
533
495
|
<Handle type="target" position={_props.targetPosition} isConnectable={_props.isConnectable} />
|
|
534
496
|
{props.data.label}
|
|
@@ -541,15 +503,19 @@ const Handle = (props) => {
|
|
|
541
503
|
width: toPxString(props.width),
|
|
542
504
|
height: toPxString(props.height)
|
|
543
505
|
}} />, InputNode = (props) => {
|
|
544
|
-
let _props =
|
|
506
|
+
let _props = propDefaults(props, { sourcePosition: Position$1.Bottom });
|
|
545
507
|
return <>
|
|
546
508
|
{props.data?.label}
|
|
547
509
|
<Handle type="source" position={_props.sourcePosition} isConnectable={_props.isConnectable} />
|
|
548
510
|
</>;
|
|
549
511
|
}, createDraggable = (elem, params) => {
|
|
550
512
|
let { store, nodeLookup, actions } = useInternalSolidFlow(), [dragging, setDragging] = createSignal(!1);
|
|
551
|
-
return
|
|
552
|
-
|
|
513
|
+
return createEffect(() => ({
|
|
514
|
+
el: elem(),
|
|
515
|
+
current: params()
|
|
516
|
+
}), ({ el, current }) => {
|
|
517
|
+
if (!el || current.disabled) return;
|
|
518
|
+
let { onDrag, onDragStart, onDragStop, onNodeMouseDown } = current, dragInstance = XYDrag({
|
|
553
519
|
onDrag,
|
|
554
520
|
onDragStart: (event, dragItems, node, nodes) => {
|
|
555
521
|
setDragging(!0), onDragStart?.(event, dragItems, node, nodes);
|
|
@@ -579,27 +545,18 @@ const Handle = (props) => {
|
|
|
579
545
|
panBy: actions.panBy
|
|
580
546
|
})
|
|
581
547
|
});
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
noDragClassName: params.noDragClass,
|
|
591
|
-
handleSelector: params.handleSelector,
|
|
592
|
-
isSelectable: params.isSelectable,
|
|
593
|
-
nodeClickDistance: params.nodeClickDistance
|
|
594
|
-
});
|
|
595
|
-
}
|
|
596
|
-
createEffect(() => {
|
|
597
|
-
updateDrag(elem(), params());
|
|
598
|
-
}), onCleanup(() => {
|
|
548
|
+
return dragInstance.update({
|
|
549
|
+
domNode: el,
|
|
550
|
+
nodeId: current.nodeId,
|
|
551
|
+
noDragClassName: current.noDragClass,
|
|
552
|
+
handleSelector: current.handleSelector,
|
|
553
|
+
isSelectable: current.isSelectable,
|
|
554
|
+
nodeClickDistance: current.nodeClickDistance
|
|
555
|
+
}), () => {
|
|
599
556
|
dragInstance.destroy();
|
|
600
|
-
}
|
|
557
|
+
};
|
|
601
558
|
}), dragging;
|
|
602
|
-
}, NodeIdContext = createContext();
|
|
559
|
+
}, NodeIdContext = createContext(null);
|
|
603
560
|
function useNodeId() {
|
|
604
561
|
let ctx = useContext(NodeIdContext);
|
|
605
562
|
if (!ctx) throw Error("solid-flow: Your application must be wrapped with <SolidFlow> in order to invoke useNodeId");
|
|
@@ -625,19 +582,27 @@ const NodeWrapper = (props) => {
|
|
|
625
582
|
...sizeStyle(),
|
|
626
583
|
...node().style ?? {}
|
|
627
584
|
});
|
|
628
|
-
createEffect(() => {
|
|
629
|
-
nodeTypeValid()
|
|
630
|
-
|
|
585
|
+
createEffect(() => ({
|
|
586
|
+
valid: nodeTypeValid(),
|
|
587
|
+
nodeType: nodeType()
|
|
588
|
+
}), ({ valid, nodeType }) => {}), createEffect(() => ({
|
|
631
589
|
id: node().id,
|
|
632
590
|
nodeElement: nodeRef(),
|
|
633
|
-
force: !0
|
|
634
|
-
}]]), {
|
|
635
591
|
nodeType: nodeType(),
|
|
636
592
|
sourcePosition: node().sourcePosition,
|
|
637
593
|
targetPosition: node().targetPosition
|
|
638
|
-
})
|
|
639
|
-
|
|
640
|
-
|
|
594
|
+
}), (current, prev) => {
|
|
595
|
+
current.nodeElement && (prev && prev.nodeElement === current.nodeElement && prev.sourcePosition === current.sourcePosition && prev.targetPosition === current.targetPosition && prev.nodeType === current.nodeType || actions.requestUpdateNodeInternals([[current.id, {
|
|
596
|
+
id: current.id,
|
|
597
|
+
nodeElement: current.nodeElement,
|
|
598
|
+
force: !0
|
|
599
|
+
}]]));
|
|
600
|
+
}), createEffect(() => ({
|
|
601
|
+
nodeElement: nodeRef(),
|
|
602
|
+
hasDimensions: nodeHasDimensions(node()),
|
|
603
|
+
resizeObserver: props.resizeObserver
|
|
604
|
+
}), (current, prev) => {
|
|
605
|
+
current.nodeElement === prev?.nodeElement && current.resizeObserver === prev?.resizeObserver && current.hasDimensions || (prev?.nodeElement && prev.resizeObserver?.unobserve(prev.nodeElement), current.nodeElement && current.resizeObserver?.observe(current.nodeElement));
|
|
641
606
|
});
|
|
642
607
|
let onSelectNodeHandler = (event) => {
|
|
643
608
|
selectable() && (!store.selectNodesOnDrag || !draggable() || store.nodeDragThreshold > 0) && actions.handleNodeSelection(node().id), props.onNodeClick?.({
|
|
@@ -651,13 +616,11 @@ const NodeWrapper = (props) => {
|
|
|
651
616
|
return;
|
|
652
617
|
}
|
|
653
618
|
let arrowKeyDiff = ARROW_KEY_DIFFS[event.key];
|
|
654
|
-
draggable() && node().selected && arrowKeyDiff &&
|
|
655
|
-
event.
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
})), actions.moveSelectedNodes(arrowKeyDiff, event.shiftKey ? 4 : 1);
|
|
660
|
-
});
|
|
619
|
+
draggable() && node().selected && arrowKeyDiff && (event.preventDefault(), actions.setAriaLiveMessage(store.ariaLabelConfig["node.a11yDescription.ariaLiveMessage"]({
|
|
620
|
+
direction: event.key.replace("Arrow", "").toLowerCase(),
|
|
621
|
+
x: ~~node().internals.positionAbsolute.x,
|
|
622
|
+
y: ~~node().internals.positionAbsolute.y
|
|
623
|
+
})), actions.moveSelectedNodes(arrowKeyDiff, event.shiftKey ? 4 : 1));
|
|
661
624
|
}, onFocus = () => {
|
|
662
625
|
if (store.disableKeyboardA11y || !store.autoPanOnNodeFocus || !nodeRef()?.matches(":focus-visible")) return;
|
|
663
626
|
let { width, height, viewport } = store;
|
|
@@ -702,15 +665,20 @@ const NodeWrapper = (props) => {
|
|
|
702
665
|
}
|
|
703
666
|
}));
|
|
704
667
|
return <Show when={!node().hidden}>
|
|
705
|
-
<div ref={setNodeRef} data-id={node().id} class={
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
668
|
+
<div ref={setNodeRef} data-id={node().id} class={[
|
|
669
|
+
"solid-flow__node",
|
|
670
|
+
`solid-flow__node-${nodeType()}`,
|
|
671
|
+
{
|
|
672
|
+
connectable: !!connectable(),
|
|
673
|
+
draggable: !!draggable(),
|
|
674
|
+
dragging: dragging(),
|
|
675
|
+
nopan: !!draggable(),
|
|
676
|
+
parent: isParentNode(),
|
|
677
|
+
selectable: !!selectable(),
|
|
678
|
+
selected: !!node().selected
|
|
679
|
+
},
|
|
680
|
+
node().class
|
|
681
|
+
]} style={style()} onClick={onSelectNodeHandler} onPointerEnter={(event) => props.onNodePointerEnter?.({
|
|
714
682
|
node: userNode(),
|
|
715
683
|
event
|
|
716
684
|
})} onPointerLeave={(event) => props.onNodePointerLeave?.({
|
|
@@ -722,16 +690,16 @@ const NodeWrapper = (props) => {
|
|
|
722
690
|
})} onContextMenu={(event) => props.onNodeContextMenu?.({
|
|
723
691
|
node: userNode(),
|
|
724
692
|
event
|
|
725
|
-
})} onKeyDown={(e) => focusable() && onKeyDown(e)} onFocus={() => focusable() && onFocus()}
|
|
726
|
-
<NodeIdContext
|
|
727
|
-
<NodeConnectableContext
|
|
693
|
+
})} onKeyDown={(e) => focusable() && onKeyDown(e)} onFocus={() => focusable() && onFocus()} tabindex={focusable() ? 0 : void 0} role={node().ariaRole ?? (focusable() ? "group" : void 0)} aria-roledescription="node" aria-describedby={store.disableKeyboardA11y ? void 0 : `${ARIA_NODE_DESC_KEY}-${store.id}`} {...node().domAttributes}>
|
|
694
|
+
<NodeIdContext value={nodeId}>
|
|
695
|
+
<NodeConnectableContext value={connectable}>
|
|
728
696
|
<Dynamic component={nodeComponent()} data={node().data} id={node().id} selected={!!node().selected} selectable={selectable()} deletable={deletable()} sourcePosition={node().sourcePosition} targetPosition={node().targetPosition} zIndex={node().internals.z} dragging={dragging()} draggable={draggable()} dragHandle={node().dragHandle} parentId={node().parentId} type={nodeType()} isConnectable={connectable()} positionAbsoluteX={node().internals.positionAbsolute.x} positionAbsoluteY={node().internals.positionAbsolute.y} width={node().width} height={node().height} />
|
|
729
|
-
</NodeConnectableContext
|
|
730
|
-
</NodeIdContext
|
|
697
|
+
</NodeConnectableContext>
|
|
698
|
+
</NodeIdContext>
|
|
731
699
|
</div>
|
|
732
700
|
</Show>;
|
|
733
701
|
}, OutputNode = (props) => {
|
|
734
|
-
let _props =
|
|
702
|
+
let _props = propDefaults(props, { targetPosition: Position$1.Top });
|
|
735
703
|
return <>
|
|
736
704
|
<Handle type="target" position={_props.targetPosition} isConnectable={_props.isConnectable} />
|
|
737
705
|
{props.data?.label}
|
|
@@ -876,24 +844,20 @@ function calculateChildXYZ(childNode, parentNode, nodeOrigin, nodeExtent, select
|
|
|
876
844
|
* @param handleId handleId of the conneciton
|
|
877
845
|
*/
|
|
878
846
|
function addConnectionToLookup(type, connection, connectionKey, connectionLookup, nodeId, handleId) {
|
|
879
|
-
let
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
let handleMap = connectionLookup.get(key) || /* @__PURE__ */ new Map();
|
|
885
|
-
connectionLookup.set(key, handleMap.set(connectionKey, connection));
|
|
886
|
-
}
|
|
847
|
+
let add = (key) => {
|
|
848
|
+
let next = new Map(untrack(() => connectionLookup.get(key)));
|
|
849
|
+
next.set(connectionKey, connection), connectionLookup.set(key, next);
|
|
850
|
+
};
|
|
851
|
+
add(nodeId), add(`${nodeId}-${type}`), handleId && add(`${nodeId}-${type}-${handleId}`);
|
|
887
852
|
}
|
|
888
853
|
function removeConnectionFromLookup(type, connectionKey, connectionLookup, nodeId, handleId) {
|
|
889
|
-
let
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
key
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
}
|
|
854
|
+
let remove = (key) => {
|
|
855
|
+
let current = untrack(() => connectionLookup.get(key));
|
|
856
|
+
if (!current) return;
|
|
857
|
+
let next = new Map(current);
|
|
858
|
+
next.delete(connectionKey), next.size === 0 ? connectionLookup.delete(key) : connectionLookup.set(key, next);
|
|
859
|
+
};
|
|
860
|
+
remove(nodeId), remove(`${nodeId}-${type}`), handleId && remove(`${nodeId}-${type}-${handleId}`);
|
|
897
861
|
}
|
|
898
862
|
//#endregion
|
|
899
863
|
//#region src/data/createSolidFlow.tsx
|
|
@@ -918,22 +882,30 @@ const InitialNodeTypesMap = {
|
|
|
918
882
|
zoom: 1
|
|
919
883
|
};
|
|
920
884
|
}, createSolidFlow = (props) => {
|
|
921
|
-
let _props =
|
|
885
|
+
let _props = merge(getDefaultFlowStateProps(), props), nodeLookup = new ReactiveMap(), parentLookup = new ReactiveMap(), edgeLookup = new ReactiveMap(), connectionLookup = new ReactiveMap(), layoutedEdgesMap = new ReactiveMap(), startNodesInitialized = untrack(() => adoptUserNodes(_props.nodes, nodeLookup, parentLookup, {
|
|
922
886
|
nodeExtent: _props.nodeExtent,
|
|
923
887
|
nodeOrigin: _props.nodeOrigin,
|
|
924
888
|
elevateNodesOnSelect: _props.elevateNodesOnSelect,
|
|
925
889
|
zIndexMode: _props.zIndexMode,
|
|
926
890
|
checkEquality: !0
|
|
927
|
-
})), initialViewport = getInitialViewport(startNodesInitialized, _props.fitView, _props.initialViewport, _props.width ?? 0, _props.height ?? 0, nodeLookup), mediaPrefersDark = createMediaQuery("(prefers-color-scheme: dark)", _props.colorModeSSR === "dark"), [config, setConfig] = createSignal(_props), [ariaLabelConfig, setAriaLabelConfig] =
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
891
|
+
})), initialViewport = getInitialViewport(startNodesInitialized, _props.fitView, _props.initialViewport, _props.width ?? 0, _props.height ?? 0, nodeLookup), mediaPrefersDark = createMediaQuery("(prefers-color-scheme: dark)", _props.colorModeSSR === "dark"), [config, setConfig] = createSignal(_props), [ariaLabelConfig, setAriaLabelConfig] = createSignal(() => mergeAriaLabelConfig(config().ariaLabelConfig)), [ariaLiveMessage, setAriaLiveMessage] = createSignal(() => config().ariaLiveMessage), [clickConnectStartHandle, setClickConnectStartHandle] = createSignal(void 0), [connection, setConnection] = createSignal(initialConnection), [domNode, setDomNode] = createSignal(null), [dragging, setDragging] = createSignal(!1), [elementsSelectable, setElementsSelectable] = createSignal(() => config().elementsSelectable), [height, setHeight] = createSignal(() => config().height), [minZoom, _setMinZoom] = createSignal(() => config().minZoom), [maxZoom, _setMaxZoom] = createSignal(() => config().maxZoom), [nodesConnectable, setNodesConnectable] = createSignal(() => config().nodesDraggable), [nodesDraggable, setNodesDraggable] = createSignal(() => config().nodesDraggable), [panZoom, setPanZoom] = createSignal(null), [selectionRect, setSelectionRect] = createSignal(), [selectionRectMode, setSelectionRectMode] = createSignal(), [snapGrid, setSnapGrid] = createSignal(() => config().snapGrid), [translateExtent, _setTranslateExtent] = createSignal(() => config().translateExtent ?? infiniteExtent), [width, setWidth] = createSignal(() => config().width), [selectionKeyPressed, setSelectionKeyPressed] = createSignal(!1), [multiselectionKeyPressed, setMultiselectionKeyPressed] = createSignal(!1), [deleteKeyPressed, setDeleteKeyPressed] = createSignal(!1), [panActivationKeyPressed, setPanActivationKeyPressed] = createSignal(!1), [zoomActivationKeyPressed, setZoomActivationKeyPressed] = createSignal(!1), [nodesStore, setNodesStore] = createStore(_props.nodes), [edgesStore, setEdgesStore] = createStore(_props.edges), [viewportStore, setViewportStore] = createStore(_props.viewport ?? initialViewport);
|
|
892
|
+
createEffect(() => config().nodes, (next) => {
|
|
893
|
+
setNodesStore(() => next);
|
|
894
|
+
}, { defer: !0 }), createEffect(() => config().edges, (next) => {
|
|
895
|
+
setEdgesStore(() => next);
|
|
896
|
+
}, { defer: !0 }), createEffect(() => config().viewport, (next) => {
|
|
897
|
+
next && setViewportStore(() => next);
|
|
898
|
+
}, { defer: !0 });
|
|
899
|
+
let transform = createMemo(() => [
|
|
900
|
+
viewportStore.x,
|
|
901
|
+
viewportStore.y,
|
|
902
|
+
viewportStore.zoom
|
|
931
903
|
]), nodesInitialized = createMemo(() => {
|
|
932
|
-
let nodes =
|
|
904
|
+
let nodes = nodesStore;
|
|
933
905
|
if (nodes.length === 0) return !1;
|
|
934
906
|
for (let node of nodes) if (!node.hidden && (node.measured?.width === void 0 || node.measured?.height === void 0)) return !1;
|
|
935
907
|
return !0;
|
|
936
|
-
}), store =
|
|
908
|
+
}), store = merge({
|
|
937
909
|
width: 0,
|
|
938
910
|
height: 0
|
|
939
911
|
}, config, {
|
|
@@ -1001,8 +973,11 @@ const InitialNodeTypesMap = {
|
|
|
1001
973
|
get minZoom() {
|
|
1002
974
|
return minZoom();
|
|
1003
975
|
},
|
|
976
|
+
get edges() {
|
|
977
|
+
return edgesStore;
|
|
978
|
+
},
|
|
1004
979
|
get nodes() {
|
|
1005
|
-
return
|
|
980
|
+
return nodesStore;
|
|
1006
981
|
},
|
|
1007
982
|
get nodesConnectable() {
|
|
1008
983
|
return nodesConnectable();
|
|
@@ -1020,10 +995,10 @@ const InitialNodeTypesMap = {
|
|
|
1020
995
|
return panZoom();
|
|
1021
996
|
},
|
|
1022
997
|
get selectedNodes() {
|
|
1023
|
-
return
|
|
998
|
+
return nodesStore.filter((node) => node.selected);
|
|
1024
999
|
},
|
|
1025
1000
|
get selectedEdges() {
|
|
1026
|
-
return
|
|
1001
|
+
return edgesStore.filter((edge) => edge.selected);
|
|
1027
1002
|
},
|
|
1028
1003
|
get selectionRect() {
|
|
1029
1004
|
return selectionRect();
|
|
@@ -1035,7 +1010,7 @@ const InitialNodeTypesMap = {
|
|
|
1035
1010
|
return snapGrid();
|
|
1036
1011
|
},
|
|
1037
1012
|
get viewport() {
|
|
1038
|
-
return
|
|
1013
|
+
return viewportStore;
|
|
1039
1014
|
},
|
|
1040
1015
|
get viewportInitialized() {
|
|
1041
1016
|
return panZoom() !== null;
|
|
@@ -1084,28 +1059,31 @@ const InitialNodeTypesMap = {
|
|
|
1084
1059
|
minZoom: store.minZoom,
|
|
1085
1060
|
maxZoom: store.maxZoom
|
|
1086
1061
|
}, options ?? config().fitViewOptions) : !1, resetStoreValues = () => {
|
|
1087
|
-
setDragging(!1), setSelectionRect(void 0), setSelectionRectMode(void 0), setSelectionKeyPressed(!1), setMultiselectionKeyPressed(!1), setDeleteKeyPressed(!1), setPanActivationKeyPressed(!1), setZoomActivationKeyPressed(!1), setConnection({ ...initialConnection }), setClickConnectStartHandle(void 0),
|
|
1062
|
+
setDragging(!1), setSelectionRect(void 0), setSelectionRectMode(void 0), setSelectionKeyPressed(!1), setMultiselectionKeyPressed(!1), setDeleteKeyPressed(!1), setPanActivationKeyPressed(!1), setZoomActivationKeyPressed(!1), setConnection({ ...initialConnection }), setClickConnectStartHandle(void 0), setViewportStore(() => config().initialViewport ?? {
|
|
1088
1063
|
x: 0,
|
|
1089
1064
|
y: 0,
|
|
1090
1065
|
zoom: 1
|
|
1091
1066
|
}), setAriaLiveMessage(""), setSnapGrid(void 0);
|
|
1092
1067
|
}, addEdge = (edgeParams) => {
|
|
1093
|
-
|
|
1068
|
+
setEdgesStore((edges) => {
|
|
1069
|
+
let next = addEdge$1(edgeParams, edges);
|
|
1070
|
+
next !== edges && edges.push(next[next.length - 1]);
|
|
1071
|
+
});
|
|
1094
1072
|
}, initialFitViewApplied = !1, initialNodesMeasured = !1, applyInitialFitView = (initialFitView) => {
|
|
1095
1073
|
initialFitViewApplied = !initialFitView;
|
|
1096
1074
|
}, tryInitialFitView = () => {
|
|
1097
1075
|
initialFitViewApplied || !initialNodesMeasured || untrack(() => store.panZoom && store.width && store.height) && (initialFitViewApplied = !0, untrack(() => fitView()));
|
|
1098
1076
|
}, updateNodePositions = (nodeDragItems, dragging = !1) => {
|
|
1099
|
-
|
|
1100
|
-
node.dragging = dragging, node.position = nodeDragItems.get(node.id).position;
|
|
1101
|
-
})
|
|
1077
|
+
setNodesStore((nodes) => {
|
|
1078
|
+
for (let node of nodes) nodeDragItems.has(node.id) && (node.dragging = dragging, node.position = nodeDragItems.get(node.id).position);
|
|
1079
|
+
});
|
|
1102
1080
|
}, pendingEntries, requestUpdateNodeInternals = (updateEntries) => {
|
|
1103
1081
|
if (pendingEntries) {
|
|
1104
1082
|
pendingEntries.push(...updateEntries);
|
|
1105
1083
|
return;
|
|
1106
1084
|
}
|
|
1107
1085
|
pendingEntries = updateEntries, scheduleIdleCallback(() => {
|
|
1108
|
-
|
|
1086
|
+
{
|
|
1109
1087
|
let updates = new Map(pendingEntries);
|
|
1110
1088
|
pendingEntries = void 0;
|
|
1111
1089
|
let { changes, updatedInternals } = updateNodeInternals(updates, nodeLookup, parentLookup, store.domNode, store.nodeOrigin);
|
|
@@ -1119,19 +1097,21 @@ const InitialNodeTypesMap = {
|
|
|
1119
1097
|
let node = nodeLookup.get(change.id)?.internals.userNode;
|
|
1120
1098
|
return node && acc.set(node.id, change), acc;
|
|
1121
1099
|
}, /* @__PURE__ */ new Map());
|
|
1122
|
-
|
|
1123
|
-
let
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1100
|
+
setNodesStore((nodes) => {
|
|
1101
|
+
for (let node of nodes) {
|
|
1102
|
+
let change = nodeToChange.get(node.id);
|
|
1103
|
+
if (change) switch (change.type) {
|
|
1104
|
+
case "dimensions":
|
|
1105
|
+
change.setAttributes && (node.width = change.dimensions?.width ?? node.width, node.height = change.dimensions?.height ?? node.height), node.measured = {
|
|
1106
|
+
...node.measured,
|
|
1107
|
+
...change.dimensions
|
|
1108
|
+
};
|
|
1109
|
+
break;
|
|
1110
|
+
case "position": node.position = change.position ?? node.position;
|
|
1111
|
+
}
|
|
1132
1112
|
}
|
|
1133
|
-
})), initialNodesMeasured = !0, tryInitialFitView();
|
|
1134
|
-
}
|
|
1113
|
+
}), flush(), initialNodesMeasured = !0, tryInitialFitView();
|
|
1114
|
+
}
|
|
1135
1115
|
});
|
|
1136
1116
|
}, zoomBy = async (factor, options) => store.panZoom ? store.panZoom.scaleBy(factor, options) : !1, zoomIn = (options) => zoomBy(1.2, options), zoomOut = (options) => zoomBy(1 / 1.2, options), setCenter = async (x, y, options) => {
|
|
1137
1117
|
let nextZoom = options?.zoom === void 0 ? store.maxZoom : options.zoom, currentPanZoom = store.panZoom;
|
|
@@ -1148,44 +1128,55 @@ const InitialNodeTypesMap = {
|
|
|
1148
1128
|
store.panZoom?.setClickDistance(distance);
|
|
1149
1129
|
}, unselectNodesAndEdges = ({ nodes: _nodes, edges } = {}) => {
|
|
1150
1130
|
let nodesToUnselect = new Set((_nodes || store.nodes).map(({ id }) => id));
|
|
1151
|
-
nodesToUnselect.size &&
|
|
1152
|
-
node.selected = !1;
|
|
1153
|
-
})
|
|
1154
|
-
let edgesToUnselect = new Set((edges
|
|
1155
|
-
edgesToUnselect.size &&
|
|
1156
|
-
edge.selected = !1;
|
|
1157
|
-
})
|
|
1131
|
+
nodesToUnselect.size && setNodesStore((nodes) => {
|
|
1132
|
+
for (let node of nodes) nodesToUnselect.has(node.id) && (node.selected = !1);
|
|
1133
|
+
});
|
|
1134
|
+
let edgesToUnselect = new Set((edges ?? store.edges).map(({ id }) => id));
|
|
1135
|
+
edgesToUnselect.size && setEdgesStore((edges) => {
|
|
1136
|
+
for (let edge of edges) edgesToUnselect.has(edge.id) && (edge.selected = !1);
|
|
1137
|
+
});
|
|
1158
1138
|
}, addSelectedNodes = (ids) => {
|
|
1159
1139
|
let isMultiSelection = store.multiselectionKeyPressed, selectState = /* @__PURE__ */ new Map();
|
|
1160
|
-
|
|
1161
|
-
let
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1140
|
+
setNodesStore((nodes) => {
|
|
1141
|
+
for (let node of nodes) {
|
|
1142
|
+
let nodeWillBeSelected = ids.includes(node.id), selected = isMultiSelection && node.selected || nodeWillBeSelected;
|
|
1143
|
+
if (selectState.set(node.id, selected), node.selected === selected) continue;
|
|
1144
|
+
let internalNode = nodeLookup.get(node.id);
|
|
1145
|
+
internalNode && (internalNode.selected = selected), node.selected = selected;
|
|
1146
|
+
}
|
|
1147
|
+
}), isMultiSelection || unselectNodesAndEdges({ nodes: [] });
|
|
1167
1148
|
}, addSelectedEdges = (ids) => {
|
|
1168
1149
|
let isMultiSelection = store.multiselectionKeyPressed, edgeSelectState = /* @__PURE__ */ new Map();
|
|
1169
|
-
|
|
1170
|
-
let
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
})
|
|
1150
|
+
setEdgesStore((edges) => {
|
|
1151
|
+
for (let edge of edges) {
|
|
1152
|
+
let edgeWillBeSelected = ids.includes(edge.id), selected = isMultiSelection && edge.selected || edgeWillBeSelected;
|
|
1153
|
+
edgeSelectState.set(edge.id, selected), edge.selected !== selected && (edge.selected = selected);
|
|
1154
|
+
}
|
|
1155
|
+
}), isMultiSelection || unselectNodesAndEdges({ edges: [] });
|
|
1175
1156
|
};
|
|
1176
|
-
return createEffect(() => {
|
|
1177
|
-
|
|
1178
|
-
}), createEffect(() => {
|
|
1179
|
-
store.panZoom
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
}),
|
|
1188
|
-
|
|
1157
|
+
return createEffect(() => !!(width() && height() && panZoom()), (ready) => {
|
|
1158
|
+
ready && tryInitialFitView();
|
|
1159
|
+
}), createEffect(() => ({
|
|
1160
|
+
panZoom: store.panZoom,
|
|
1161
|
+
viewport: {
|
|
1162
|
+
x: store.viewport.x,
|
|
1163
|
+
y: store.viewport.y,
|
|
1164
|
+
zoom: store.viewport.zoom
|
|
1165
|
+
}
|
|
1166
|
+
}), ({ panZoom, viewport }) => {
|
|
1167
|
+
panZoom?.syncViewport(viewport);
|
|
1168
|
+
}), createEffect(() => ({
|
|
1169
|
+
panZoom: panZoom(),
|
|
1170
|
+
extent: [store.minZoom, store.maxZoom]
|
|
1171
|
+
}), ({ panZoom, extent }) => {
|
|
1172
|
+
panZoom?.setScaleExtent(extent);
|
|
1173
|
+
}), createEffect(() => ({
|
|
1174
|
+
panZoom: panZoom(),
|
|
1175
|
+
extent: store.translateExtent
|
|
1176
|
+
}), ({ panZoom, extent }) => {
|
|
1177
|
+
panZoom?.setTranslateExtent(extent);
|
|
1178
|
+
}), createRenderEffect(mapArray(() => store.nodes, (userNode) => {
|
|
1179
|
+
createRenderEffect(() => {
|
|
1189
1180
|
let internalNode = untrack(() => nodeLookup.get(userNode.id)), selectedNodeZ = store.elevateNodesOnSelect && store.zIndexMode !== "manual" ? 1e3 : 0, clampedPosition = clampPosition(getNodePositionWithOrigin(userNode, store.nodeOrigin), isCoordinateExtent(userNode.extent) ? userNode.extent : store.nodeExtent, getNodeDimensions(userNode)), preservedMeasured = {
|
|
1190
1181
|
width: userNode.measured?.width ?? internalNode?.measured?.width,
|
|
1191
1182
|
height: userNode.measured?.height ?? internalNode?.measured?.height
|
|
@@ -1206,11 +1197,10 @@ const InitialNodeTypesMap = {
|
|
|
1206
1197
|
zIndexMode: store.zIndexMode,
|
|
1207
1198
|
checkEquality: !0
|
|
1208
1199
|
});
|
|
1209
|
-
}), onCleanup(() => {});
|
|
1210
|
-
})), createEffect(() => {
|
|
1211
|
-
let
|
|
1212
|
-
|
|
1213
|
-
}), createComputed(mapArray(() => store.edges, (edge) => {
|
|
1200
|
+
}, () => {}), onCleanup(() => {});
|
|
1201
|
+
}), () => {}), createEffect(() => new Set(store.nodes.map((n) => n.id)), (currentIds) => {
|
|
1202
|
+
for (let id of untrack(() => Array.from(nodeLookup.keys()))) currentIds.has(id) || nodeLookup.delete(id);
|
|
1203
|
+
}), createRenderEffect(mapArray(() => store.edges, (edge) => {
|
|
1214
1204
|
let { source: sourceNodeId, target: targetNodeId, sourceHandle = null, targetHandle = null } = edge, connection = {
|
|
1215
1205
|
edgeId: edge.id,
|
|
1216
1206
|
source: sourceNodeId,
|
|
@@ -1218,11 +1208,9 @@ const InitialNodeTypesMap = {
|
|
|
1218
1208
|
sourceHandle,
|
|
1219
1209
|
targetHandle
|
|
1220
1210
|
}, sourceKey = `${sourceNodeId}-${sourceHandle}--${targetNodeId}-${targetHandle}`, targetKey = `${targetNodeId}-${targetHandle}--${sourceNodeId}-${sourceHandle}`;
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
});
|
|
1225
|
-
}), createComputed(() => {
|
|
1211
|
+
createRenderEffect(() => {
|
|
1212
|
+
addConnectionToLookup("source", connection, targetKey, connectionLookup, sourceNodeId, sourceHandle), addConnectionToLookup("target", connection, sourceKey, connectionLookup, targetNodeId, targetHandle), edgeLookup.set(edge.id, edge);
|
|
1213
|
+
}, () => {}), createRenderEffect(() => {
|
|
1226
1214
|
let sourceNode = nodeLookup.get(edge.source), targetNode = nodeLookup.get(edge.target);
|
|
1227
1215
|
if (!sourceNode || !targetNode) return;
|
|
1228
1216
|
if (store.onlyRenderVisibleElements) {
|
|
@@ -1260,14 +1248,11 @@ const InitialNodeTypesMap = {
|
|
|
1260
1248
|
targetNode,
|
|
1261
1249
|
edge
|
|
1262
1250
|
});
|
|
1263
|
-
}), onCleanup(() => {
|
|
1264
|
-
|
|
1265
|
-
edgeLookup.delete(edge.id), layoutedEdgesMap.delete(edge.id), removeConnectionFromLookup("source", targetKey, connectionLookup, sourceNodeId, sourceHandle), removeConnectionFromLookup("target", sourceKey, connectionLookup, targetNodeId, targetHandle);
|
|
1266
|
-
});
|
|
1251
|
+
}, () => {}), onCleanup(() => {
|
|
1252
|
+
edgeLookup.delete(edge.id), layoutedEdgesMap.delete(edge.id), removeConnectionFromLookup("source", targetKey, connectionLookup, sourceNodeId, sourceHandle), removeConnectionFromLookup("target", sourceKey, connectionLookup, targetNodeId, targetHandle);
|
|
1267
1253
|
});
|
|
1268
|
-
})), createEffect(() => {
|
|
1269
|
-
let
|
|
1270
|
-
for (let id of Array.from(edgeLookup.keys())) currentIds.has(id) || (edgeLookup.delete(id), connectionLookup.delete(id), layoutedEdgesMap.delete(id));
|
|
1254
|
+
}), () => {}), createEffect(() => new Set(store.edges.map((e) => e.id)), (currentIds) => {
|
|
1255
|
+
for (let id of untrack(() => Array.from(edgeLookup.keys()))) currentIds.has(id) || (edgeLookup.delete(id), connectionLookup.delete(id), layoutedEdgesMap.delete(id));
|
|
1271
1256
|
}), {
|
|
1272
1257
|
store,
|
|
1273
1258
|
nodeLookup,
|
|
@@ -1288,13 +1273,13 @@ const InitialNodeTypesMap = {
|
|
|
1288
1273
|
setDomNode,
|
|
1289
1274
|
setDragging,
|
|
1290
1275
|
get setEdges() {
|
|
1291
|
-
return
|
|
1276
|
+
return setEdgesStore;
|
|
1292
1277
|
},
|
|
1293
1278
|
setElementsSelectable,
|
|
1294
1279
|
setHeight,
|
|
1295
1280
|
setMultiselectionKeyPressed,
|
|
1296
1281
|
get setNodes() {
|
|
1297
|
-
return
|
|
1282
|
+
return setNodesStore;
|
|
1298
1283
|
},
|
|
1299
1284
|
setNodesConnectable,
|
|
1300
1285
|
setNodesDraggable,
|
|
@@ -1304,7 +1289,7 @@ const InitialNodeTypesMap = {
|
|
|
1304
1289
|
setSelectionRect,
|
|
1305
1290
|
setSelectionRectMode,
|
|
1306
1291
|
get setViewport() {
|
|
1307
|
-
return
|
|
1292
|
+
return (viewport) => setViewportStore(() => viewport);
|
|
1308
1293
|
},
|
|
1309
1294
|
setWidth,
|
|
1310
1295
|
setZoomActivationKeyPressed,
|
|
@@ -1320,18 +1305,14 @@ const InitialNodeTypesMap = {
|
|
|
1320
1305
|
addSelectedEdges,
|
|
1321
1306
|
handleNodeSelection: (id, unselect, nodeRef) => {
|
|
1322
1307
|
let node = store.nodes.find((n) => n.id === id);
|
|
1323
|
-
node && (
|
|
1324
|
-
setSelectionRect(void 0), setSelectionRectMode(void 0);
|
|
1325
|
-
}), node.selected ? (unselect || node.selected && store.multiselectionKeyPressed) && (unselectNodesAndEdges({
|
|
1308
|
+
node && (setSelectionRect(void 0), setSelectionRectMode(void 0), node.selected ? (unselect || node.selected && store.multiselectionKeyPressed) && (unselectNodesAndEdges({
|
|
1326
1309
|
nodes: [node],
|
|
1327
1310
|
edges: []
|
|
1328
1311
|
}), requestAnimationFrame(() => nodeRef?.blur())) : addSelectedNodes([id]));
|
|
1329
1312
|
},
|
|
1330
1313
|
handleEdgeSelection: (id) => {
|
|
1331
1314
|
let edge = edgeLookup.get(id);
|
|
1332
|
-
edge && (edge.selectable || store.elementsSelectable && edge.selectable === void 0) && (
|
|
1333
|
-
setSelectionRect(void 0), setSelectionRectMode(void 0);
|
|
1334
|
-
}), edge.selected ? edge.selected && store.multiselectionKeyPressed && unselectNodesAndEdges({
|
|
1315
|
+
edge && (edge.selectable || store.elementsSelectable && edge.selectable === void 0) && (setSelectionRect(void 0), setSelectionRectMode(void 0), edge.selected ? edge.selected && store.multiselectionKeyPressed && unselectNodesAndEdges({
|
|
1335
1316
|
nodes: [],
|
|
1336
1317
|
edges: [edge]
|
|
1337
1318
|
}) : addSelectedEdges([id]));
|
|
@@ -1373,7 +1354,7 @@ const InitialNodeTypesMap = {
|
|
|
1373
1354
|
}
|
|
1374
1355
|
}
|
|
1375
1356
|
};
|
|
1376
|
-
}, SolidFlowContext = createContext();
|
|
1357
|
+
}, SolidFlowContext = createContext(null);
|
|
1377
1358
|
function useInternalSolidFlow() {
|
|
1378
1359
|
let ctx = useContext(SolidFlowContext);
|
|
1379
1360
|
if (!ctx) throw Error("solid-flow: Your application must be wrapped with <SolidFlow> in order to invoke useInternalSolidFlow within your components");
|
|
@@ -1382,13 +1363,13 @@ function useInternalSolidFlow() {
|
|
|
1382
1363
|
//#endregion
|
|
1383
1364
|
//#region src/components/graph/marker/Marker.tsx
|
|
1384
1365
|
const Marker = (props) => {
|
|
1385
|
-
let _props =
|
|
1366
|
+
let _props = propDefaults(props, {
|
|
1386
1367
|
markerUnits: "strokeWidth",
|
|
1387
1368
|
orient: "auto-start-reverse",
|
|
1388
1369
|
width: 12.5,
|
|
1389
1370
|
height: 12.5,
|
|
1390
1371
|
color: "none"
|
|
1391
|
-
}
|
|
1372
|
+
}), color = () => _props.color ?? "var(--xy-edge-stroke)";
|
|
1392
1373
|
return <marker class="solid-flow__arrowhead" id={_props.id} markerWidth={_props.width} markerHeight={_props.height} viewBox="-10 -10 20 20" markerUnits={_props.markerUnits} orient={_props.orient} refX="0" refY="0">
|
|
1393
1374
|
<Show when={_props.type === "arrow"} fallback={<polyline class="arrowclosed" stroke={color()} fill={color()} stroke-linecap="round" stroke-linejoin="round" stroke-width={_props.strokeWidth} points="-5,-4 0,0 -5,4 -5,-4" />}>
|
|
1394
1375
|
<polyline class="arrow" stroke={color()} fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width={_props.strokeWidth} points="-5,-4 0,0 -5,4" />
|
|
@@ -1440,7 +1421,7 @@ const Marker = (props) => {
|
|
|
1440
1421
|
for (let item of a) if (!b.has(item)) return !1;
|
|
1441
1422
|
return !0;
|
|
1442
1423
|
}, Pane = (props) => {
|
|
1443
|
-
let { store, nodeLookup, edgeLookup, connectionLookup, actions } = useInternalSolidFlow(), container, containerBounds = null, connectionEndedOnPane = !1, selectionInProgress = !1, selectedNodeIds = /* @__PURE__ */ new Set(), selectedEdgeIds = /* @__PURE__ */ new Set(), autoPanId = 0, position = {
|
|
1424
|
+
let { store, nodeLookup, edgeLookup, connectionLookup, actions } = useInternalSolidFlow(), [containerRef, setContainerRef] = createSignal(), container, containerBounds = null, connectionEndedOnPane = !1, selectionInProgress = !1, selectedNodeIds = /* @__PURE__ */ new Set(), selectedEdgeIds = /* @__PURE__ */ new Set(), autoPanId = 0, position = {
|
|
1444
1425
|
x: 0,
|
|
1445
1426
|
y: 0
|
|
1446
1427
|
}, autoPanStarted = !1, autoPanOnSelection = () => props.autoPanOnSelection ?? !0, paneClickDistance = () => props.paneClickDistance ?? 1, _panOnDrag = () => store.panActivationKeyPressed || props.panOnDrag, isSelecting = () => store.selectionKeyPressed || !!store.selectionRect || props.selectionOnDrag && _panOnDrag() !== !0, isSelectionEnabled = () => store.elementsSelectable && (isSelecting() || store.selectionRectMode === "user"), onClick = (event) => {
|
|
@@ -1449,9 +1430,7 @@ const Marker = (props) => {
|
|
|
1449
1430
|
selectionInProgress = !1, connectionEndedOnPane = !1;
|
|
1450
1431
|
return;
|
|
1451
1432
|
}
|
|
1452
|
-
props.onPaneClick?.({ event }),
|
|
1453
|
-
actions.unselectNodesAndEdges(), actions.setSelectionRectMode(void 0), actions.setSelectionRect(void 0);
|
|
1454
|
-
});
|
|
1433
|
+
props.onPaneClick?.({ event }), actions.unselectNodesAndEdges(), actions.setSelectionRectMode(void 0), actions.setSelectionRect(void 0);
|
|
1455
1434
|
}
|
|
1456
1435
|
}, onPointerDownCapture = (event) => {
|
|
1457
1436
|
if (event.pointerType === "touch" && _panOnDrag() !== !1 && !store.selectionKeyPressed || (containerBounds = container?.getBoundingClientRect() ?? null, !containerBounds)) return;
|
|
@@ -1469,7 +1448,7 @@ const Marker = (props) => {
|
|
|
1469
1448
|
startY: userSelectionFlowOrigin.y,
|
|
1470
1449
|
x,
|
|
1471
1450
|
y
|
|
1472
|
-
}), eventTargetIsContainer || (event.stopPropagation(), event.preventDefault());
|
|
1451
|
+
}), flush(), eventTargetIsContainer || (event.stopPropagation(), event.preventDefault());
|
|
1473
1452
|
}, commitUserSelectionRect = (mouseX, mouseY) => {
|
|
1474
1453
|
let selectionRect = store.selectionRect;
|
|
1475
1454
|
if (selectionRect?.startX === void 0 || selectionRect.startY === void 0) return;
|
|
@@ -1494,27 +1473,17 @@ const Marker = (props) => {
|
|
|
1494
1473
|
edge && (edge.selectable ?? edgesSelectable) && selectedEdgeIds.add(edgeId);
|
|
1495
1474
|
}
|
|
1496
1475
|
}
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
let
|
|
1500
|
-
|
|
1501
|
-
let isSelected = selectedNodeIds.has(node.id);
|
|
1502
|
-
return selectionMap.set(node.id, isSelected), !!node.selected !== isSelected;
|
|
1503
|
-
}, produce((node) => {
|
|
1504
|
-
node.selected = selectionMap.get(node.id);
|
|
1505
|
-
}));
|
|
1476
|
+
isSetEqual(prevSelectedNodeIds, selectedNodeIds) || actions.setNodes((nodes) => {
|
|
1477
|
+
for (let node of nodes) {
|
|
1478
|
+
let isSelected = selectedNodeIds.has(node.id);
|
|
1479
|
+
!!node.selected !== isSelected && (node.selected = isSelected);
|
|
1506
1480
|
}
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
return selectionMap.set(edge.id, isSelected), !!edge.selected !== isSelected;
|
|
1512
|
-
}, produce((edge) => {
|
|
1513
|
-
edge.selected = selectionMap.get(edge.id);
|
|
1514
|
-
}));
|
|
1481
|
+
}), isSetEqual(prevSelectedEdgeIds, selectedEdgeIds) || actions.setEdges((edges) => {
|
|
1482
|
+
for (let edge of edges) {
|
|
1483
|
+
let isSelected = selectedEdgeIds.has(edge.id);
|
|
1484
|
+
!!edge.selected !== isSelected && (edge.selected = isSelected);
|
|
1515
1485
|
}
|
|
1516
|
-
|
|
1517
|
-
});
|
|
1486
|
+
}), actions.setSelectionRectMode("user"), actions.setSelectionRect(nextUserSelectRect), flush();
|
|
1518
1487
|
}, autoPan = () => {
|
|
1519
1488
|
if (!autoPanOnSelection() || !containerBounds) return;
|
|
1520
1489
|
let [x = 0, y = 0] = calcAutoPan(position, containerBounds, store.autoPanSpeed);
|
|
@@ -1556,14 +1525,18 @@ const Marker = (props) => {
|
|
|
1556
1525
|
event.target === container && store.connection.inProgress && (connectionEndedOnPane = !0);
|
|
1557
1526
|
return;
|
|
1558
1527
|
}
|
|
1559
|
-
event.button === 0 && (event.target?.releasePointerCapture?.(event.pointerId), !selectionInProgress && event.target === container && onClick(event),
|
|
1560
|
-
actions.setSelectionRect(void 0), selectionInProgress && actions.setSelectionRectMode(selectedNodeIds.size > 0 ? "nodes" : void 0);
|
|
1561
|
-
}), selectionInProgress && props.onSelectionEnd?.(event), cleanupAutoPan());
|
|
1528
|
+
event.button === 0 && (event.target?.releasePointerCapture?.(event.pointerId), !selectionInProgress && event.target === container && onClick(event), actions.setSelectionRect(void 0), selectionInProgress && actions.setSelectionRectMode(selectedNodeIds.size > 0 ? "nodes" : void 0), flush(), selectionInProgress && props.onSelectionEnd?.(event), cleanupAutoPan());
|
|
1562
1529
|
}, onPointerCancel = (event) => {
|
|
1563
1530
|
event.target?.releasePointerCapture?.(event.pointerId), cleanupAutoPan();
|
|
1564
1531
|
}, onClickCapture = (event) => {
|
|
1565
1532
|
selectionInProgress &&= (event.stopPropagation(), !1);
|
|
1566
|
-
}
|
|
1533
|
+
};
|
|
1534
|
+
createEventListener(containerRef, "pointerdown", (e) => {
|
|
1535
|
+
isSelectionEnabled() && onPointerDownCapture(e);
|
|
1536
|
+
}, { capture: !0 }), createEventListener(containerRef, "click", (e) => {
|
|
1537
|
+
isSelectionEnabled() && onClickCapture(e);
|
|
1538
|
+
}, { capture: !0 });
|
|
1539
|
+
let onContextMenu = (event) => {
|
|
1567
1540
|
if (event.target !== container) return;
|
|
1568
1541
|
let result = _panOnDrag();
|
|
1569
1542
|
if (Array.isArray(result) && result.includes(2)) {
|
|
@@ -1573,40 +1546,28 @@ const Marker = (props) => {
|
|
|
1573
1546
|
props.onPaneContextMenu?.({ event });
|
|
1574
1547
|
};
|
|
1575
1548
|
return <div ref={(el) => {
|
|
1576
|
-
container = el, el
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
}} class={clsx$1("solid-flow__container solid-flow__pane", {
|
|
1580
|
-
selection: isSelecting(),
|
|
1549
|
+
container = el, setContainerRef(el);
|
|
1550
|
+
}} class={["solid-flow__container solid-flow__pane", {
|
|
1551
|
+
selection: !!isSelecting(),
|
|
1581
1552
|
dragging: store.dragging,
|
|
1582
1553
|
draggable: props.panOnDrag === !0 || Array.isArray(props.panOnDrag) && props.panOnDrag.includes(0)
|
|
1583
|
-
}
|
|
1584
|
-
capture: !0,
|
|
1585
|
-
handleEvent: (e) => {
|
|
1586
|
-
isSelectionEnabled() && onPointerDownCapture(e);
|
|
1587
|
-
}
|
|
1588
|
-
}} onPointerMove={(e) => isSelectionEnabled() ? onPointerMove(e) : void 0} onPointerUp={onPointerUp} onPointerCancel={(e) => isSelectionEnabled() ? onPointerCancel(e) : void 0} onContextMenu={onContextMenu}>
|
|
1554
|
+
}]} onClick={(e) => isSelectionEnabled() ? void 0 : onClick(e)} onPointerMove={(e) => isSelectionEnabled() ? onPointerMove(e) : void 0} onPointerUp={onPointerUp} onPointerCancel={(e) => isSelectionEnabled() ? onPointerCancel(e) : void 0} onContextMenu={onContextMenu}>
|
|
1589
1555
|
{props.children}
|
|
1590
1556
|
</div>;
|
|
1591
1557
|
}, Panel = (props) => {
|
|
1592
|
-
let { store } = useInternalSolidFlow(), _props =
|
|
1558
|
+
let { store } = useInternalSolidFlow(), _props = propDefaults(props, {
|
|
1593
1559
|
position: "top-right",
|
|
1594
1560
|
style: {}
|
|
1595
|
-
}
|
|
1596
|
-
|
|
1597
|
-
"position",
|
|
1598
|
-
"style",
|
|
1599
|
-
"children"
|
|
1600
|
-
]);
|
|
1601
|
-
return <div class={clsx$1([
|
|
1561
|
+
}), rest = omit(_props, "class", "position", "style", "children");
|
|
1562
|
+
return <div class={[
|
|
1602
1563
|
"solid-flow__panel",
|
|
1603
|
-
...
|
|
1604
|
-
|
|
1605
|
-
]
|
|
1564
|
+
..._props.position.split("-"),
|
|
1565
|
+
_props.class
|
|
1566
|
+
]} style={{
|
|
1606
1567
|
"pointer-events": store.selectionRectMode ? "none" : void 0,
|
|
1607
|
-
...
|
|
1568
|
+
..._props.style
|
|
1608
1569
|
}} {...rest}>
|
|
1609
|
-
{
|
|
1570
|
+
{_props.children}
|
|
1610
1571
|
</div>;
|
|
1611
1572
|
}, Viewport = (props) => {
|
|
1612
1573
|
let { store } = useInternalSolidFlow();
|
|
@@ -1621,7 +1582,7 @@ const Marker = (props) => {
|
|
|
1621
1582
|
</Portal>}
|
|
1622
1583
|
</Show>;
|
|
1623
1584
|
}, Zoom = (props) => {
|
|
1624
|
-
let ref, { store, actions } = useInternalSolidFlow(), viewPort = () => props.initialViewport || {
|
|
1585
|
+
let [ref, setRef] = createSignal(), { store, actions } = useInternalSolidFlow(), viewPort = () => props.initialViewport || {
|
|
1625
1586
|
x: 0,
|
|
1626
1587
|
y: 0,
|
|
1627
1588
|
zoom: 1
|
|
@@ -1633,9 +1594,10 @@ const Marker = (props) => {
|
|
|
1633
1594
|
zoom
|
|
1634
1595
|
});
|
|
1635
1596
|
};
|
|
1636
|
-
return
|
|
1637
|
-
|
|
1638
|
-
|
|
1597
|
+
return createEffect(() => ref(), (el) => {
|
|
1598
|
+
if (!el) return;
|
|
1599
|
+
let panZoomInstance = untrack(() => XYPanZoom({
|
|
1600
|
+
domNode: el,
|
|
1639
1601
|
minZoom: store.minZoom,
|
|
1640
1602
|
maxZoom: store.maxZoom,
|
|
1641
1603
|
translateExtent: store.translateExtent,
|
|
@@ -1644,43 +1606,46 @@ const Marker = (props) => {
|
|
|
1644
1606
|
onPanZoomStart: props.onMoveStart,
|
|
1645
1607
|
onPanZoom: props.onMove,
|
|
1646
1608
|
onPanZoomEnd: props.onMoveEnd
|
|
1647
|
-
}), vp = panZoomInstance.getViewport();
|
|
1648
|
-
(
|
|
1609
|
+
})), vp = panZoomInstance.getViewport(), initial = untrack(() => viewPort());
|
|
1610
|
+
(initial.x !== vp.x || initial.y !== vp.y || initial.zoom !== vp.zoom) && onTransformChange([
|
|
1649
1611
|
vp.x,
|
|
1650
1612
|
vp.y,
|
|
1651
1613
|
vp.zoom
|
|
1652
|
-
]),
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1614
|
+
]), actions.setViewport(vp), actions.setPanZoom(panZoomInstance), props.onViewportInitialized?.();
|
|
1615
|
+
}), createEffect(() => ({
|
|
1616
|
+
panZoom: store.panZoom,
|
|
1617
|
+
options: {
|
|
1618
|
+
lib: store.lib,
|
|
1619
|
+
panActivationKeyPressed: store.panActivationKeyPressed,
|
|
1620
|
+
zoomActivationKeyPressed: store.zoomActivationKeyPressed,
|
|
1621
|
+
noPanClassName: store.noPanClass,
|
|
1622
|
+
noWheelClassName: store.noWheelClass,
|
|
1623
|
+
userSelectionActive: !!store.selectionRect,
|
|
1624
|
+
panOnScrollSpeed: props.panOnScrollSpeed,
|
|
1625
|
+
panOnDrag: panOnDrag(),
|
|
1626
|
+
panOnScroll: panOnScroll(),
|
|
1627
|
+
zoomOnScroll: props.zoomOnScroll,
|
|
1628
|
+
zoomOnDoubleClick: props.zoomOnDoubleClick,
|
|
1629
|
+
zoomOnPinch: props.zoomOnPinch,
|
|
1630
|
+
panOnScrollMode: props.panOnScrollMode,
|
|
1631
|
+
preventScrolling: typeof props.preventScrolling != "boolean" || props.preventScrolling,
|
|
1632
|
+
paneClickDistance: props.paneClickDistance,
|
|
1633
|
+
selectionOnDrag: props.selectionOnDrag,
|
|
1634
|
+
connectionInProgress: store.connection.inProgress
|
|
1635
|
+
}
|
|
1636
|
+
}), ({ panZoom, options }) => {
|
|
1637
|
+
panZoom?.update({
|
|
1638
|
+
...options,
|
|
1639
|
+
onTransformChange
|
|
1675
1640
|
});
|
|
1676
|
-
}), <div ref={
|
|
1641
|
+
}), <div ref={setRef} class="solid-flow__container solid-flow__zoom">
|
|
1677
1642
|
{props.children}
|
|
1678
1643
|
</div>;
|
|
1679
1644
|
}, ConnectionLine = (props) => {
|
|
1680
1645
|
let { store } = useInternalSolidFlow(), connectionStatus = () => getConnectionStatus(store.connection.isValid);
|
|
1681
1646
|
return <Show when={store.connection.inProgress}>
|
|
1682
1647
|
<svg class="solid-flow__container solid-flow__connectionline" width={store.width} height={store.height} style={props.containerStyle}>
|
|
1683
|
-
<g class={
|
|
1648
|
+
<g class={["solid-flow__connection", connectionStatus()]}>
|
|
1684
1649
|
<Show when={props.component} fallback={<InternalConnectionLine style={props.style} />}>
|
|
1685
1650
|
{(CustomComponent) => {
|
|
1686
1651
|
let UserConnectionLine = CustomComponent();
|
|
@@ -1722,24 +1687,32 @@ const Marker = (props) => {
|
|
|
1722
1687
|
};
|
|
1723
1688
|
return <path class="solid-flow__connection-path" fill="none" style={props.style} d={path()} />;
|
|
1724
1689
|
}, DotPattern = (props) => {
|
|
1725
|
-
let _props =
|
|
1726
|
-
return <circle class={
|
|
1690
|
+
let _props = propDefaults(props, { radius: 5 });
|
|
1691
|
+
return <circle class={[
|
|
1692
|
+
"solid-flow__background-pattern",
|
|
1693
|
+
"dots",
|
|
1694
|
+
_props.class
|
|
1695
|
+
]} cx={_props.radius} cy={_props.radius} r={_props.radius} />;
|
|
1727
1696
|
}, LinePattern = (props) => {
|
|
1728
|
-
let _props =
|
|
1729
|
-
return <path stroke-width={_props.lineWidth} d={`M${_props.dimensions[0] / 2} 0 V${_props.dimensions[1]} M0 ${_props.dimensions[1] / 2} H${_props.dimensions[0]}`} class={
|
|
1697
|
+
let _props = propDefaults(props, { lineWidth: 1 });
|
|
1698
|
+
return <path stroke-width={_props.lineWidth} d={`M${_props.dimensions[0] / 2} 0 V${_props.dimensions[1]} M0 ${_props.dimensions[1] / 2} H${_props.dimensions[0]}`} class={[
|
|
1699
|
+
"solid-flow__background-pattern",
|
|
1700
|
+
_props.variant,
|
|
1701
|
+
_props.class
|
|
1702
|
+
]} />;
|
|
1730
1703
|
}, DEFAULT_SIZE = {
|
|
1731
1704
|
dots: 1,
|
|
1732
1705
|
lines: 1,
|
|
1733
1706
|
cross: 6
|
|
1734
1707
|
}, Background = (props) => {
|
|
1735
|
-
let _props =
|
|
1708
|
+
let _props = propDefaults(props, {
|
|
1736
1709
|
variant: "dots",
|
|
1737
1710
|
gap: 20,
|
|
1738
1711
|
size: 1,
|
|
1739
1712
|
lineWidth: 1,
|
|
1740
1713
|
style: {}
|
|
1741
|
-
}
|
|
1742
|
-
return <svg data-testid="solid-flow__background" class={
|
|
1714
|
+
}), { store } = useInternalSolidFlow(), isDots = () => _props.variant === "dots", isCross = () => _props.variant === "cross", patternId = () => `background-pattern-${store.id}-${_props.id ?? ""}`, scaledSize = () => (_props.size ?? DEFAULT_SIZE[_props.variant]) * store.viewport.zoom, gapXY = () => Array.isArray(_props.gap) ? _props.gap : [_props.gap, _props.gap], scaledGap = () => [gapXY()[0] * store.viewport.zoom || 1, gapXY()[1] * store.viewport.zoom || 1], patternDimensions = () => isCross() ? [scaledSize(), scaledSize()] : scaledGap(), patternOffset = () => isDots() ? [scaledSize() / 2, scaledSize() / 2] : [patternDimensions()[0] / 2, patternDimensions()[1] / 2];
|
|
1715
|
+
return <svg data-testid="solid-flow__background" class={["solid-flow__container solid-flow__background", _props.class]} style={{
|
|
1743
1716
|
"--xy-background-color-props": _props.bgColor,
|
|
1744
1717
|
"--xy-background-pattern-color-props": _props.patternColor,
|
|
1745
1718
|
..._props.style
|
|
@@ -1752,24 +1725,15 @@ const Marker = (props) => {
|
|
|
1752
1725
|
<rect x="0" y="0" width="100%" height="100%" fill={`url(#${patternId()})`} />
|
|
1753
1726
|
</svg>;
|
|
1754
1727
|
}, ControlButton = (props) => {
|
|
1755
|
-
let
|
|
1756
|
-
"
|
|
1757
|
-
"
|
|
1758
|
-
"
|
|
1759
|
-
"color",
|
|
1760
|
-
"
|
|
1761
|
-
"borderColor",
|
|
1762
|
-
"onClick",
|
|
1763
|
-
"children"
|
|
1764
|
-
]), style = () => Object.entries({
|
|
1765
|
-
"--xy-controls-button-background-color-props": local.bgColor,
|
|
1766
|
-
"--xy-controls-button-background-color-hover-props": local.bgColorHover,
|
|
1767
|
-
"--xy-controls-button-color-props": local.color,
|
|
1768
|
-
"--xy-controls-button-color-hover-props": local.colorHover,
|
|
1769
|
-
"--xy-controls-button-border-color-props": local.borderColor
|
|
1728
|
+
let rest = omit(props, "class", "bgColor", "bgColorHover", "color", "colorHover", "borderColor", "onClick", "children"), style = () => Object.entries({
|
|
1729
|
+
"--xy-controls-button-background-color-props": props.bgColor,
|
|
1730
|
+
"--xy-controls-button-background-color-hover-props": props.bgColorHover,
|
|
1731
|
+
"--xy-controls-button-color-props": props.color,
|
|
1732
|
+
"--xy-controls-button-color-hover-props": props.colorHover,
|
|
1733
|
+
"--xy-controls-button-border-color-props": props.borderColor
|
|
1770
1734
|
}).filter(([_, value]) => value !== void 0).reduce((acc, [key, value]) => (acc[key] = value, acc), {});
|
|
1771
|
-
return <button type="button" class={
|
|
1772
|
-
{
|
|
1735
|
+
return <button type="button" class={["solid-flow__controls-button", props.class]} onClick={(e) => props.onClick?.(e)} style={style()} {...rest}>
|
|
1736
|
+
{props.children}
|
|
1773
1737
|
</button>;
|
|
1774
1738
|
}, Fit = () => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 30">
|
|
1775
1739
|
<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" />
|
|
@@ -1782,54 +1746,35 @@ const Marker = (props) => {
|
|
|
1782
1746
|
</svg>, Unlock = () => <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 32">
|
|
1783
1747
|
<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" />
|
|
1784
1748
|
</svg>, Controls = (props) => {
|
|
1785
|
-
let { store, actions } = useInternalSolidFlow(), _props =
|
|
1749
|
+
let { store, actions } = useInternalSolidFlow(), _props = propDefaults(props, {
|
|
1786
1750
|
position: "bottom-left",
|
|
1787
1751
|
showZoom: !0,
|
|
1788
1752
|
showFitView: !0,
|
|
1789
1753
|
showLock: !0,
|
|
1790
1754
|
orientation: "vertical"
|
|
1791
|
-
},
|
|
1792
|
-
"class",
|
|
1793
|
-
"position",
|
|
1794
|
-
"showZoom",
|
|
1795
|
-
"showFitView",
|
|
1796
|
-
"showLock",
|
|
1797
|
-
"orientation",
|
|
1798
|
-
"fitViewOptions",
|
|
1799
|
-
"beforeControls",
|
|
1800
|
-
"afterControls",
|
|
1801
|
-
"buttonBgColor",
|
|
1802
|
-
"buttonBgColorHover",
|
|
1803
|
-
"buttonColor",
|
|
1804
|
-
"buttonColorHover",
|
|
1805
|
-
"buttonBorderColor",
|
|
1806
|
-
"style",
|
|
1807
|
-
"children"
|
|
1808
|
-
]), getMinZoomReached = () => store.viewport.zoom <= store.minZoom, getMaxZoomReached = () => store.viewport.zoom >= store.maxZoom, getIsInteractive = () => store.nodesDraggable || store.nodesConnectable || store.elementsSelectable, onZoomInHandler = () => {
|
|
1755
|
+
}), rest = omit(_props, "class", "position", "showZoom", "showFitView", "showLock", "orientation", "fitViewOptions", "beforeControls", "afterControls", "buttonBgColor", "buttonBgColorHover", "buttonColor", "buttonColorHover", "buttonBorderColor", "style", "children"), getMinZoomReached = () => store.viewport.zoom <= store.minZoom, getMaxZoomReached = () => store.viewport.zoom >= store.maxZoom, getIsInteractive = () => store.nodesDraggable || store.nodesConnectable || store.elementsSelectable, onZoomInHandler = () => {
|
|
1809
1756
|
actions.zoomIn();
|
|
1810
1757
|
}, onZoomOutHandler = () => {
|
|
1811
1758
|
actions.zoomOut();
|
|
1812
1759
|
}, onFitViewHandler = () => {
|
|
1813
|
-
actions.fitView(
|
|
1760
|
+
actions.fitView(_props.fitViewOptions);
|
|
1814
1761
|
}, onToggleInteractivity = () => {
|
|
1815
1762
|
let newValue = !getIsInteractive();
|
|
1816
|
-
|
|
1817
|
-
actions.setNodesDraggable(newValue), actions.setNodesConnectable(newValue), actions.setElementsSelectable(newValue);
|
|
1818
|
-
});
|
|
1763
|
+
actions.setNodesDraggable(newValue), actions.setNodesConnectable(newValue), actions.setElementsSelectable(newValue);
|
|
1819
1764
|
}, buttonProps = () => ({
|
|
1820
|
-
bgColor:
|
|
1821
|
-
bgColorHover:
|
|
1822
|
-
color:
|
|
1823
|
-
colorHover:
|
|
1824
|
-
borderColor:
|
|
1765
|
+
bgColor: _props.buttonBgColor,
|
|
1766
|
+
bgColorHover: _props.buttonBgColorHover,
|
|
1767
|
+
color: _props.buttonColor,
|
|
1768
|
+
colorHover: _props.buttonColorHover,
|
|
1769
|
+
borderColor: _props.buttonBorderColor
|
|
1825
1770
|
});
|
|
1826
|
-
return <Panel class={
|
|
1771
|
+
return <Panel class={[
|
|
1827
1772
|
"solid-flow__controls",
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
]
|
|
1831
|
-
{
|
|
1832
|
-
<Show when={
|
|
1773
|
+
_props.orientation,
|
|
1774
|
+
_props.class
|
|
1775
|
+
]} position={_props.position} data-testid="solid-flow__controls" aria-label={store.ariaLabelConfig["controls.ariaLabel"]} style={_props.style} {...rest}>
|
|
1776
|
+
{_props.beforeControls}
|
|
1777
|
+
<Show when={_props.showZoom}>
|
|
1833
1778
|
<>
|
|
1834
1779
|
<ControlButton onClick={onZoomInHandler} class="solid-flow__controls-zoomin" title={store.ariaLabelConfig["controls.zoomIn.ariaLabel"]} aria-label={store.ariaLabelConfig["controls.zoomIn.ariaLabel"]} disabled={getMaxZoomReached()} {...buttonProps()}>
|
|
1835
1780
|
<Plus />
|
|
@@ -1839,56 +1784,51 @@ const Marker = (props) => {
|
|
|
1839
1784
|
</ControlButton>
|
|
1840
1785
|
</>
|
|
1841
1786
|
</Show>
|
|
1842
|
-
<Show when={
|
|
1787
|
+
<Show when={_props.showFitView}>
|
|
1843
1788
|
<ControlButton class="solid-flow__controls-fitview" onClick={onFitViewHandler} title={store.ariaLabelConfig["controls.fitView.ariaLabel"]} aria-label={store.ariaLabelConfig["controls.fitView.ariaLabel"]} {...buttonProps()}>
|
|
1844
1789
|
<Fit />
|
|
1845
1790
|
</ControlButton>
|
|
1846
1791
|
</Show>
|
|
1847
|
-
<Show when={
|
|
1792
|
+
<Show when={_props.showLock}>
|
|
1848
1793
|
<ControlButton class="solid-flow__controls-interactive" onClick={onToggleInteractivity} title={store.ariaLabelConfig["controls.interactive.ariaLabel"]} aria-label={store.ariaLabelConfig["controls.interactive.ariaLabel"]} {...buttonProps()}>
|
|
1849
1794
|
<Show when={getIsInteractive()} fallback={<Lock />}>
|
|
1850
1795
|
<Unlock />
|
|
1851
1796
|
</Show>
|
|
1852
1797
|
</ControlButton>
|
|
1853
1798
|
</Show>
|
|
1854
|
-
{
|
|
1855
|
-
{
|
|
1799
|
+
{_props.children}
|
|
1800
|
+
{_props.afterControls}
|
|
1856
1801
|
</Panel>;
|
|
1857
1802
|
}, EdgeToolbar = (props) => {
|
|
1858
|
-
let
|
|
1859
|
-
"x",
|
|
1860
|
-
"y",
|
|
1861
|
-
"alignX",
|
|
1862
|
-
"alignY",
|
|
1863
|
-
"isVisible",
|
|
1864
|
-
"selectEdgeOnClick",
|
|
1865
|
-
"class",
|
|
1866
|
-
"children"
|
|
1867
|
-
]), { store, edgeLookup } = useInternalSolidFlow(), edgeId = useEdgeId(), isActive = () => typeof local.isVisible == "boolean" ? local.isVisible : !!edgeLookup.get(edgeId())?.selected, transform = () => getEdgeToolbarTransform(local.x, local.y, store.viewport.zoom, local.alignX ?? "center", local.alignY ?? "center");
|
|
1803
|
+
let rest = omit(props, "x", "y", "alignX", "alignY", "isVisible", "selectEdgeOnClick", "class", "children"), { store, edgeLookup } = useInternalSolidFlow(), edgeId = useEdgeId(), isActive = () => typeof props.isVisible == "boolean" ? props.isVisible : !!edgeLookup.get(edgeId())?.selected, transform = () => getEdgeToolbarTransform(props.x, props.y, store.viewport.zoom, props.alignX ?? "center", props.alignY ?? "center");
|
|
1868
1804
|
return <Show when={isActive()}>
|
|
1869
|
-
<EdgeLabel selectEdgeOnClick={
|
|
1870
|
-
<div class={
|
|
1805
|
+
<EdgeLabel selectEdgeOnClick={props.selectEdgeOnClick} transparent>
|
|
1806
|
+
<div class={["solid-flow__edge-toolbar", props.class]} style={{
|
|
1871
1807
|
position: "absolute",
|
|
1872
1808
|
transform: transform(),
|
|
1873
1809
|
"transform-origin": "0 0"
|
|
1874
1810
|
}} data-id={edgeId()} {...rest}>
|
|
1875
|
-
{
|
|
1811
|
+
{props.children}
|
|
1876
1812
|
</div>
|
|
1877
1813
|
</EdgeLabel>
|
|
1878
1814
|
</Show>;
|
|
1879
1815
|
}, MiniMapNode = (props) => {
|
|
1880
|
-
let _props =
|
|
1816
|
+
let _props = propDefaults(props, {
|
|
1881
1817
|
borderRadius: 5,
|
|
1882
1818
|
width: 0,
|
|
1883
1819
|
height: 0
|
|
1884
|
-
}
|
|
1820
|
+
}), style = () => Object.entries({
|
|
1885
1821
|
fill: _props.color,
|
|
1886
1822
|
stroke: _props.strokeColor,
|
|
1887
1823
|
"stroke-width": _props.strokeWidth
|
|
1888
1824
|
}).filter(([_, value]) => value !== void 0).reduce((acc, [key, value]) => (acc[key] = value, acc), {});
|
|
1889
|
-
return <rect class={
|
|
1825
|
+
return <rect class={[
|
|
1826
|
+
"solid-flow__minimap-node",
|
|
1827
|
+
{ selected: !!_props.selected },
|
|
1828
|
+
_props.class
|
|
1829
|
+
]} x={_props.x} y={_props.y} rx={_props.borderRadius} ry={_props.borderRadius} width={_props.width} height={_props.height} shape-rendering={_props.shapeRendering} style={style()} />;
|
|
1890
1830
|
}, getAttrFunction = (func) => func instanceof Function ? func : () => func, MiniMap = (props) => {
|
|
1891
|
-
let { store, nodeLookup } = useInternalSolidFlow(), _props =
|
|
1831
|
+
let { store, nodeLookup } = useInternalSolidFlow(), _props = propDefaults(props, {
|
|
1892
1832
|
position: "bottom-right",
|
|
1893
1833
|
nodeClass: "",
|
|
1894
1834
|
nodeStrokeColor: "transparent",
|
|
@@ -1899,26 +1839,7 @@ const Marker = (props) => {
|
|
|
1899
1839
|
nodeBorderRadius: 5,
|
|
1900
1840
|
nodeStrokeWidth: 2,
|
|
1901
1841
|
style: {}
|
|
1902
|
-
},
|
|
1903
|
-
"class",
|
|
1904
|
-
"style",
|
|
1905
|
-
"position",
|
|
1906
|
-
"nodeClass",
|
|
1907
|
-
"nodeStrokeColor",
|
|
1908
|
-
"nodeColor",
|
|
1909
|
-
"pannable",
|
|
1910
|
-
"zoomable",
|
|
1911
|
-
"inversePan",
|
|
1912
|
-
"zoomStep",
|
|
1913
|
-
"bgColor",
|
|
1914
|
-
"width",
|
|
1915
|
-
"height",
|
|
1916
|
-
"maskColor",
|
|
1917
|
-
"maskStrokeColor",
|
|
1918
|
-
"maskStrokeWidth",
|
|
1919
|
-
"nodeBorderRadius",
|
|
1920
|
-
"nodeStrokeWidth"
|
|
1921
|
-
]), nodeColorFunc = () => local.nodeColor === void 0 ? void 0 : getAttrFunction(local.nodeColor), nodeStrokeColorFunc = () => getAttrFunction(local.nodeStrokeColor), nodeClassFunc = () => getAttrFunction(local.nodeClass), shapeRendering = () => typeof window > "u" || window.chrome ? "crispEdges" : "geometricPrecision", labelledBy = createMemo(() => `solid-flow__minimap-desc-${store.id}`), getViewBB = () => ({
|
|
1842
|
+
}), paneProps = omit(_props, "class", "style", "position", "nodeClass", "nodeStrokeColor", "nodeColor", "pannable", "zoomable", "inversePan", "zoomStep", "bgColor", "width", "height", "maskColor", "maskStrokeColor", "maskStrokeWidth", "nodeBorderRadius", "nodeStrokeWidth"), nodeColorFunc = () => _props.nodeColor === void 0 ? void 0 : getAttrFunction(_props.nodeColor), nodeStrokeColorFunc = () => getAttrFunction(_props.nodeStrokeColor), nodeClassFunc = () => getAttrFunction(_props.nodeClass), shapeRendering = () => typeof window > "u" || window.chrome ? "crispEdges" : "geometricPrecision", labelledBy = createMemo(() => `solid-flow__minimap-desc-${store.id}`), getViewBB = () => ({
|
|
1922
1843
|
x: -store.viewport.x / store.viewport.zoom,
|
|
1923
1844
|
y: -store.viewport.y / store.viewport.zoom,
|
|
1924
1845
|
width: store.width / store.viewport.zoom,
|
|
@@ -1926,57 +1847,64 @@ const Marker = (props) => {
|
|
|
1926
1847
|
}), getBoundingRect = () => {
|
|
1927
1848
|
let viewBB = getViewBB();
|
|
1928
1849
|
return nodeLookup.size > 0 ? getBoundsOfRects(getInternalNodesBounds(nodeLookup), viewBB) : viewBB;
|
|
1929
|
-
}, getScaledWidth = () => getBoundingRect().width /
|
|
1850
|
+
}, getScaledWidth = () => getBoundingRect().width / _props.width, getScaledHeight = () => getBoundingRect().height / _props.height, getViewScale = () => Math.max(getScaledWidth(), getScaledHeight()), getViewWidth = () => getViewScale() * _props.width, getViewHeight = () => getViewScale() * _props.height, getOffset = () => 5 * getViewScale(), getX = () => {
|
|
1930
1851
|
let boundingRect = getBoundingRect();
|
|
1931
1852
|
return boundingRect.x - (getViewWidth() - boundingRect.width) / 2 - getOffset();
|
|
1932
1853
|
}, getY = () => {
|
|
1933
1854
|
let boundingRect = getBoundingRect();
|
|
1934
1855
|
return boundingRect.y - (getViewHeight() - boundingRect.height) / 2 - getOffset();
|
|
1935
|
-
}, getViewboxWidth = () => getViewWidth() + getOffset() * 2, getViewboxHeight = () => getViewHeight() + getOffset() * 2, strokeWidth = () =>
|
|
1856
|
+
}, getViewboxWidth = () => getViewWidth() + getOffset() * 2, getViewboxHeight = () => getViewHeight() + getOffset() * 2, strokeWidth = () => _props.maskStrokeWidth ? _props.maskStrokeWidth * getViewScale() : void 0, prevNodeIds = [], nodeIds = () => {
|
|
1936
1857
|
let currentNodeIds = store.nodes.map((node) => node.id), currentSet = new Set(currentNodeIds);
|
|
1937
1858
|
return (prevNodeIds.length !== currentNodeIds.length || !prevNodeIds.every((id) => currentSet.has(id))) && (prevNodeIds = currentNodeIds), prevNodeIds;
|
|
1938
1859
|
};
|
|
1939
|
-
return <Panel position={
|
|
1940
|
-
"--xy-minimap-background-color-props":
|
|
1941
|
-
...
|
|
1860
|
+
return <Panel position={_props.position} data-testid="solid-flow__minimap" class={["solid-flow__minimap", _props.class]} style={{
|
|
1861
|
+
"--xy-minimap-background-color-props": _props.bgColor,
|
|
1862
|
+
..._props.style
|
|
1942
1863
|
}} {...paneProps}>
|
|
1943
1864
|
<Show when={store.panZoom}>
|
|
1944
1865
|
{(panZoom) => {
|
|
1945
|
-
let [ref, setRef] = createSignal();
|
|
1946
|
-
return
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1866
|
+
let [ref, setRef] = createSignal(), [minimap, setMinimap] = createSignal();
|
|
1867
|
+
return createEffect(() => ({
|
|
1868
|
+
el: ref(),
|
|
1869
|
+
panZoom: panZoom()
|
|
1870
|
+
}), ({ el, panZoom }) => {
|
|
1871
|
+
if (!el) return;
|
|
1872
|
+
let instance = XYMinimap({
|
|
1873
|
+
domNode: el,
|
|
1874
|
+
panZoom,
|
|
1950
1875
|
getTransform: () => store.transform,
|
|
1951
1876
|
getViewScale
|
|
1952
1877
|
});
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1878
|
+
return setMinimap(instance), () => {
|
|
1879
|
+
instance.destroy();
|
|
1880
|
+
};
|
|
1881
|
+
}), createEffect(() => ({
|
|
1882
|
+
instance: minimap(),
|
|
1883
|
+
options: {
|
|
1884
|
+
translateExtent: store.translateExtent,
|
|
1885
|
+
width: store.width,
|
|
1886
|
+
height: store.height,
|
|
1887
|
+
inversePan: _props.inversePan,
|
|
1888
|
+
zoomStep: _props.zoomStep,
|
|
1889
|
+
pannable: _props.pannable,
|
|
1890
|
+
zoomable: _props.zoomable
|
|
1891
|
+
}
|
|
1892
|
+
}), ({ instance, options }) => {
|
|
1893
|
+
instance?.update(options);
|
|
1894
|
+
}), <svg ref={setRef} width={_props.width} height={_props.height} viewBox={`${getX()} ${getY()} ${getViewboxWidth()} ${getViewboxHeight()}`} class="solid-flow__minimap-svg" role="img" aria-labelledby={labelledBy()} style={{
|
|
1895
|
+
"--xy-minimap-mask-background-color-props": _props.maskColor,
|
|
1896
|
+
"--xy-minimap-mask-stroke-color-props": _props.maskStrokeColor,
|
|
1969
1897
|
"--xy-minimap-mask-stroke-width-props": strokeWidth()
|
|
1970
1898
|
}}>
|
|
1971
1899
|
<title id={labelledBy()}>{store.ariaLabelConfig["minimap.ariaLabel"]}</title>
|
|
1972
|
-
<
|
|
1900
|
+
<For keyed={!1} each={nodeIds()}>
|
|
1973
1901
|
{(nodeId) => {
|
|
1974
1902
|
let node = createMemo(() => nodeLookup.get(nodeId())), nodeVisible = () => !!(node() && nodeHasDimensions(node()) && !node().hidden);
|
|
1975
1903
|
return <Show when={nodeVisible() && getNodeDimensions(node())}>
|
|
1976
|
-
{(nodeDimensions) => <MiniMapNode x={node().internals.positionAbsolute.x} y={node().internals.positionAbsolute.y} borderRadius={
|
|
1904
|
+
{(nodeDimensions) => <MiniMapNode x={node().internals.positionAbsolute.x} y={node().internals.positionAbsolute.y} borderRadius={_props.nodeBorderRadius} strokeWidth={_props.nodeStrokeWidth} shapeRendering={shapeRendering()} width={nodeDimensions().width} height={nodeDimensions().height} selected={node().selected} color={nodeColorFunc()?.call(null, node())} strokeColor={nodeStrokeColorFunc().call(null, node())} class={nodeClassFunc().call(null, node())} />}
|
|
1977
1905
|
</Show>;
|
|
1978
1906
|
}}
|
|
1979
|
-
</
|
|
1907
|
+
</For>
|
|
1980
1908
|
<path class="solid-flow__minimap-mask" d={`M${getX() - getOffset()},${getY() - getOffset()}h${getViewboxWidth() + getOffset() * 2}v${getViewboxHeight() + getOffset() * 2}h${-getViewboxWidth() - getOffset() * 2}z
|
|
1981
1909
|
M${getViewBB().x},${getViewBB().y}h${getViewBB().width}v${getViewBB().height}h${-getViewBB().width}z`} fill-rule="evenodd" pointer-events="none" />
|
|
1982
1910
|
</svg>;
|
|
@@ -1984,7 +1912,7 @@ const Marker = (props) => {
|
|
|
1984
1912
|
</Show>
|
|
1985
1913
|
</Panel>;
|
|
1986
1914
|
}, ResizeControl = (props) => {
|
|
1987
|
-
let _props =
|
|
1915
|
+
let _props = propDefaults(props, {
|
|
1988
1916
|
variant: "handle",
|
|
1989
1917
|
minWidth: 10,
|
|
1990
1918
|
minHeight: 10,
|
|
@@ -1993,28 +1921,11 @@ const Marker = (props) => {
|
|
|
1993
1921
|
keepAspectRatio: !1,
|
|
1994
1922
|
autoScale: !0,
|
|
1995
1923
|
style: {}
|
|
1996
|
-
},
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
"minHeight",
|
|
2002
|
-
"maxWidth",
|
|
2003
|
-
"maxHeight",
|
|
2004
|
-
"keepAspectRatio",
|
|
2005
|
-
"autoScale",
|
|
2006
|
-
"onResizeStart",
|
|
2007
|
-
"onResize",
|
|
2008
|
-
"onResizeEnd",
|
|
2009
|
-
"shouldResize",
|
|
2010
|
-
"class",
|
|
2011
|
-
"children",
|
|
2012
|
-
"color",
|
|
2013
|
-
"style"
|
|
2014
|
-
]), resizeControlRef, { store, nodeLookup, actions } = useInternalSolidFlow(), ctxNodeId = useNodeId(), nodeId = () => local.nodeId ?? ctxNodeId(), isLineVariant = () => local.variant === "line", controlPosition = () => local.position ?? (isLineVariant() ? "right" : "bottom-right"), positionClassNames = () => controlPosition().split("-");
|
|
2015
|
-
return onMount(() => {
|
|
2016
|
-
let resizer = XYResizer({
|
|
2017
|
-
domNode: resizeControlRef,
|
|
1924
|
+
}), rest = omit(_props, "nodeId", "variant", "position", "minWidth", "minHeight", "maxWidth", "maxHeight", "keepAspectRatio", "autoScale", "onResizeStart", "onResize", "onResizeEnd", "shouldResize", "class", "children", "color", "style"), [resizeControlRef, setResizeControlRef] = createSignal(), { store, nodeLookup, actions } = useInternalSolidFlow(), ctxNodeId = useNodeId(), nodeId = () => _props.nodeId ?? ctxNodeId(), isLineVariant = () => _props.variant === "line", controlPosition = () => _props.position ?? (isLineVariant() ? "right" : "bottom-right"), positionClassNames = () => controlPosition().split("-"), [resizer, setResizer] = createSignal();
|
|
1925
|
+
return createEffect(() => resizeControlRef(), (el) => {
|
|
1926
|
+
if (!el) return;
|
|
1927
|
+
let instance = XYResizer({
|
|
1928
|
+
domNode: el,
|
|
2018
1929
|
nodeId: nodeId(),
|
|
2019
1930
|
getStoreItems: () => ({
|
|
2020
1931
|
nodeLookup,
|
|
@@ -2034,63 +1945,63 @@ const Marker = (props) => {
|
|
|
2034
1945
|
position
|
|
2035
1946
|
});
|
|
2036
1947
|
for (let childChange of childChanges) changes.set(childChange.id, { position: childChange.position });
|
|
2037
|
-
actions.setNodes((
|
|
2038
|
-
let
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
1948
|
+
actions.setNodes((nodes) => {
|
|
1949
|
+
for (let node of nodes) {
|
|
1950
|
+
let nodeChange = changes.get(node.id);
|
|
1951
|
+
nodeChange && (node.width = nodeChange.width, node.height = nodeChange.height, node.position = {
|
|
1952
|
+
x: nodeChange.position?.x ?? node.position.x,
|
|
1953
|
+
y: nodeChange.position?.y ?? node.position.y
|
|
1954
|
+
});
|
|
1955
|
+
}
|
|
1956
|
+
});
|
|
2044
1957
|
}
|
|
2045
1958
|
});
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
1959
|
+
return setResizer(instance), () => {
|
|
1960
|
+
instance.destroy();
|
|
1961
|
+
};
|
|
1962
|
+
}), createEffect(() => ({
|
|
1963
|
+
instance: resizer(),
|
|
1964
|
+
options: {
|
|
1965
|
+
controlPosition: controlPosition(),
|
|
1966
|
+
boundaries: {
|
|
1967
|
+
minWidth: _props.minWidth,
|
|
1968
|
+
minHeight: _props.minHeight,
|
|
1969
|
+
maxWidth: _props.maxWidth,
|
|
1970
|
+
maxHeight: _props.maxHeight
|
|
1971
|
+
},
|
|
1972
|
+
keepAspectRatio: !!_props.keepAspectRatio,
|
|
1973
|
+
onResizeStart: _props.onResizeStart,
|
|
1974
|
+
onResize: _props.onResize,
|
|
1975
|
+
onResizeEnd: _props.onResizeEnd,
|
|
1976
|
+
shouldResize: _props.shouldResize
|
|
1977
|
+
}
|
|
1978
|
+
}), ({ instance, options }) => {
|
|
1979
|
+
instance?.update(options);
|
|
1980
|
+
}), <div ref={setResizeControlRef} class={[
|
|
2065
1981
|
"solid-flow__resize-control",
|
|
2066
|
-
|
|
1982
|
+
_props.variant,
|
|
2067
1983
|
store.noDragClass,
|
|
2068
1984
|
...positionClassNames(),
|
|
2069
|
-
|
|
2070
|
-
]
|
|
2071
|
-
"border-color": isLineVariant() ?
|
|
2072
|
-
"background-color": isLineVariant() ? void 0 :
|
|
2073
|
-
scale: isLineVariant() || !
|
|
2074
|
-
...
|
|
1985
|
+
_props.class
|
|
1986
|
+
]} style={{
|
|
1987
|
+
"border-color": isLineVariant() ? _props.color : void 0,
|
|
1988
|
+
"background-color": isLineVariant() ? void 0 : _props.color,
|
|
1989
|
+
scale: isLineVariant() || !_props.autoScale ? void 0 : Math.max(1 / store.viewport.zoom, 1),
|
|
1990
|
+
..._props.style
|
|
2075
1991
|
}} {...rest}>
|
|
2076
|
-
{
|
|
1992
|
+
{_props.children}
|
|
2077
1993
|
</div>;
|
|
2078
1994
|
}, NodeResizer = (props) => {
|
|
2079
|
-
let _props =
|
|
1995
|
+
let _props = propDefaults(props, {
|
|
2080
1996
|
autoScale: !0,
|
|
2081
1997
|
visible: !0
|
|
2082
|
-
}
|
|
2083
|
-
"handleClass",
|
|
2084
|
-
"handleStyle",
|
|
2085
|
-
"lineClass",
|
|
2086
|
-
"lineStyle"
|
|
2087
|
-
]);
|
|
1998
|
+
}), rest = omit(props, "handleClass", "handleStyle", "lineClass", "lineStyle");
|
|
2088
1999
|
return <Show when={_props.visible}>
|
|
2089
2000
|
<For each={XY_RESIZER_LINE_POSITIONS}>
|
|
2090
|
-
{(position) => <ResizeControl variant="line" position={position} class={
|
|
2001
|
+
{(position) => <ResizeControl variant="line" position={position} class={props.lineClass} style={props.lineStyle} {...rest} />}
|
|
2091
2002
|
</For>
|
|
2092
2003
|
<For each={XY_RESIZER_HANDLE_POSITIONS}>
|
|
2093
|
-
{(position) => <ResizeControl position={position} class={
|
|
2004
|
+
{(position) => <ResizeControl position={position} class={props.handleClass} style={props.handleStyle} {...rest} />}
|
|
2094
2005
|
</For>
|
|
2095
2006
|
</Show>;
|
|
2096
2007
|
};
|
|
@@ -2159,12 +2070,10 @@ function useHandleEdgeSelect() {
|
|
|
2159
2070
|
let { store, edgeLookup, actions } = useInternalSolidFlow();
|
|
2160
2071
|
return (id) => {
|
|
2161
2072
|
let edge = edgeLookup.get(id);
|
|
2162
|
-
edge && (edge.selectable || store.elementsSelectable && edge.selectable === void 0) &&
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
}) : actions.addSelectedEdges([id]);
|
|
2167
|
-
});
|
|
2073
|
+
edge && (edge.selectable || store.elementsSelectable && edge.selectable === void 0) && (actions.setSelectionRect(void 0), actions.setSelectionRectMode(void 0), edge.selected ? edge.selected && store.multiselectionKeyPressed && actions.unselectNodesAndEdges({
|
|
2074
|
+
nodes: [],
|
|
2075
|
+
edges: [edge]
|
|
2076
|
+
}) : actions.addSelectedEdges([id]));
|
|
2168
2077
|
};
|
|
2169
2078
|
}
|
|
2170
2079
|
//#endregion
|
|
@@ -2224,10 +2133,9 @@ const useNodeConnections = (params) => {
|
|
|
2224
2133
|
let { connectionLookup } = useInternalSolidFlow(), ctxNodeId = () => {
|
|
2225
2134
|
let id = useContext(NodeIdContext);
|
|
2226
2135
|
return id ? id() : "";
|
|
2227
|
-
}, id = () => params().handleId, type = () => params().handleType, nodeId = () => params().id ?? ctxNodeId(), [connections, setConnections] = createSignal([]), lookupKey = () => `${nodeId()}${type() ? id() ? `-${type()}-${id()}` : `-${type()}` : ""}
|
|
2228
|
-
return createEffect((
|
|
2229
|
-
|
|
2230
|
-
return areConnectionMapsEqual(nextConnections, prevConnections) || (prevConnections = nextConnections, setConnections(Array.from(prevConnections?.values() ?? []))), nextConnections;
|
|
2136
|
+
}, id = () => params().handleId, type = () => params().handleType, nodeId = () => params().id ?? ctxNodeId(), [connections, setConnections] = createSignal([]), lookupKey = () => `${nodeId()}${type() ? id() ? `-${type()}-${id()}` : `-${type()}` : ""}`, prevConnections;
|
|
2137
|
+
return createEffect(() => ({ connections: connectionLookup.get(lookupKey()) }), ({ connections: nextConnections }) => {
|
|
2138
|
+
areConnectionMapsEqual(nextConnections, prevConnections) || (prevConnections = nextConnections, setConnections(Array.from(nextConnections?.values() ?? [])));
|
|
2231
2139
|
}), connections;
|
|
2232
2140
|
};
|
|
2233
2141
|
//#endregion
|
|
@@ -2267,17 +2175,21 @@ function useSolidFlow() {
|
|
|
2267
2175
|
};
|
|
2268
2176
|
return nodeToRect(nodeWithPosition);
|
|
2269
2177
|
}, updateNode = (id, nodeUpdate, options = { replace: !1 }) => {
|
|
2270
|
-
actions.setNodes((
|
|
2271
|
-
let
|
|
2272
|
-
|
|
2178
|
+
actions.setNodes((nodes) => {
|
|
2179
|
+
let index = nodes.findIndex((node) => node.id === id);
|
|
2180
|
+
if (index === -1) return;
|
|
2181
|
+
let node = nodes[index], nextNode = typeof nodeUpdate == "function" ? nodeUpdate(node) : nodeUpdate;
|
|
2182
|
+
nodes[index] = options?.replace && isNode(nextNode) ? nextNode : {
|
|
2273
2183
|
...node,
|
|
2274
2184
|
...nextNode
|
|
2275
2185
|
};
|
|
2276
2186
|
});
|
|
2277
2187
|
}, updateEdge = (id, edgeUpdate, options = { replace: !1 }) => {
|
|
2278
|
-
actions.setEdges((
|
|
2279
|
-
let
|
|
2280
|
-
|
|
2188
|
+
actions.setEdges((edges) => {
|
|
2189
|
+
let index = edges.findIndex((edge) => edge.id === id);
|
|
2190
|
+
if (index === -1) return;
|
|
2191
|
+
let edge = edges[index], nextEdge = typeof edgeUpdate == "function" ? edgeUpdate(edge) : edgeUpdate;
|
|
2192
|
+
edges[index] = options.replace && isEdge(nextEdge) ? nextEdge : {
|
|
2281
2193
|
...edge,
|
|
2282
2194
|
...nextEdge
|
|
2283
2195
|
};
|
|
@@ -2301,7 +2213,7 @@ function useSolidFlow() {
|
|
|
2301
2213
|
let newEdges = Array.isArray(payload) ? payload : [payload];
|
|
2302
2214
|
actions.setEdges((edges) => [...edges, ...newEdges]);
|
|
2303
2215
|
},
|
|
2304
|
-
getViewport: () =>
|
|
2216
|
+
getViewport: () => snapshot(store.viewport),
|
|
2305
2217
|
setViewport: async (nextViewport, options) => {
|
|
2306
2218
|
let currentViewport = store.viewport;
|
|
2307
2219
|
return store.panZoom ? (await store.panZoom.setViewport({
|
|
@@ -2347,16 +2259,15 @@ function useSolidFlow() {
|
|
|
2347
2259
|
edges: store.edges,
|
|
2348
2260
|
onBeforeDelete: store.onBeforeDelete
|
|
2349
2261
|
});
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
}), {
|
|
2262
|
+
if (matchingEdges) {
|
|
2263
|
+
let remmainingEdges = store.edges.filter((edge) => !matchingEdges.some(({ id }) => id === edge.id));
|
|
2264
|
+
store.onEdgesDelete?.(matchingEdges), actions.setEdges(() => remmainingEdges);
|
|
2265
|
+
}
|
|
2266
|
+
if (matchingNodes) {
|
|
2267
|
+
let remmainingNodes = store.nodes.filter((node) => !matchingNodes.some(({ id }) => id === node.id));
|
|
2268
|
+
store.onNodesDelete?.(matchingNodes), actions.setNodes(() => remmainingNodes);
|
|
2269
|
+
}
|
|
2270
|
+
return {
|
|
2360
2271
|
deletedNodes: matchingNodes,
|
|
2361
2272
|
deletedEdges: matchingEdges
|
|
2362
2273
|
};
|
|
@@ -2391,9 +2302,9 @@ function useSolidFlow() {
|
|
|
2391
2302
|
};
|
|
2392
2303
|
},
|
|
2393
2304
|
toObject: () => structuredClone({
|
|
2394
|
-
nodes: [...
|
|
2395
|
-
edges: [...
|
|
2396
|
-
viewport: { ...
|
|
2305
|
+
nodes: [...snapshot(store.nodes)],
|
|
2306
|
+
edges: [...snapshot(store.edges)],
|
|
2307
|
+
viewport: { ...snapshot(store.viewport) }
|
|
2397
2308
|
}),
|
|
2398
2309
|
updateNode,
|
|
2399
2310
|
updateNodeData: (id, dataUpdate, options) => {
|
|
@@ -2453,34 +2364,26 @@ function useUpdateNodeInternals() {
|
|
|
2453
2364
|
//#endregion
|
|
2454
2365
|
//#region src/components/graph/plugins/NodeToolbar.tsx
|
|
2455
2366
|
const NodeToolbar = (props) => {
|
|
2456
|
-
let { store } = useInternalSolidFlow(), { getNodes, getNodesBounds, getInternalNode } = useSolidFlow(), _props =
|
|
2367
|
+
let { store } = useInternalSolidFlow(), { getNodes, getNodesBounds, getInternalNode } = useSolidFlow(), _props = propDefaults(props, {
|
|
2457
2368
|
offset: 10,
|
|
2458
2369
|
position: "top",
|
|
2459
2370
|
align: "center",
|
|
2460
2371
|
style: {}
|
|
2461
|
-
}
|
|
2462
|
-
"nodeId",
|
|
2463
|
-
"position",
|
|
2464
|
-
"align",
|
|
2465
|
-
"offset",
|
|
2466
|
-
"isVisible",
|
|
2467
|
-
"style",
|
|
2468
|
-
"children"
|
|
2469
|
-
]), ctxNodeId = () => {
|
|
2372
|
+
}), divProps = omit(_props, "nodeId", "position", "align", "offset", "isVisible", "style", "children"), ctxNodeId = () => {
|
|
2470
2373
|
let id = useContext(NodeIdContext);
|
|
2471
2374
|
return id ? id() : "";
|
|
2472
|
-
}, toolbarNodes = () => (Array.isArray(
|
|
2375
|
+
}, toolbarNodes = () => (Array.isArray(_props.nodeId) ? _props.nodeId : [_props.nodeId ?? ctxNodeId()]).reduce((res, nodeId) => {
|
|
2473
2376
|
let node = getInternalNode(nodeId);
|
|
2474
2377
|
return node && res.push(node), res;
|
|
2475
2378
|
}, []), transform = () => {
|
|
2476
2379
|
let nodeRect = getNodesBounds(toolbarNodes());
|
|
2477
|
-
return nodeRect ? getNodeToolbarTransform(nodeRect, store.viewport,
|
|
2380
|
+
return nodeRect ? getNodeToolbarTransform(nodeRect, store.viewport, _props.position, _props.offset, _props.align) : "";
|
|
2478
2381
|
}, zIndex = () => {
|
|
2479
2382
|
let nodes = toolbarNodes();
|
|
2480
2383
|
return nodes.length === 0 ? 1 : Math.max(...nodes.map((node) => (node.internals.z || 5) + 1));
|
|
2481
2384
|
}, selectedNodesCount = () => getNodes().filter((node) => node.selected).length, isActive = () => {
|
|
2482
2385
|
let nodes = toolbarNodes();
|
|
2483
|
-
return typeof
|
|
2386
|
+
return typeof _props.isVisible == "boolean" ? _props.isVisible : nodes.length === 1 && !!nodes[0].selected && selectedNodesCount() === 1;
|
|
2484
2387
|
}, showPortal = () => !!(store.domNode && isActive() && toolbarNodes().length > 0);
|
|
2485
2388
|
return <Show when={showPortal()}>
|
|
2486
2389
|
<Portal mount={store.domNode}>
|
|
@@ -2488,14 +2391,14 @@ const NodeToolbar = (props) => {
|
|
|
2488
2391
|
position: "absolute",
|
|
2489
2392
|
transform: transform(),
|
|
2490
2393
|
"z-index": zIndex(),
|
|
2491
|
-
...
|
|
2394
|
+
..._props.style
|
|
2492
2395
|
}} {...divProps}>
|
|
2493
|
-
{
|
|
2396
|
+
{_props.children}
|
|
2494
2397
|
</div>
|
|
2495
2398
|
</Portal>
|
|
2496
2399
|
</Show>;
|
|
2497
2400
|
}, Selection = (props) => {
|
|
2498
|
-
let _props =
|
|
2401
|
+
let _props = propDefaults(props, { isVisible: !0 }), styles = () => ({
|
|
2499
2402
|
..._props.width != null && { width: typeof _props.width == "string" ? _props.width : toPxString(_props.width) },
|
|
2500
2403
|
..._props.height != null && { height: typeof _props.height == "string" ? _props.height : toPxString(_props.height) },
|
|
2501
2404
|
..._props.x != null && _props.y != null && { transform: `translate(${props.x}px, ${props.y}px)` }
|
|
@@ -2505,8 +2408,11 @@ const NodeToolbar = (props) => {
|
|
|
2505
2408
|
</Show>;
|
|
2506
2409
|
}, NodeSelection = (props) => {
|
|
2507
2410
|
let { store, nodeLookup, actions } = useInternalSolidFlow(), [ref, setRef] = createSignal(), bounds = () => store.selectionRectMode === "nodes" ? getInternalNodesBounds(nodeLookup, { filter: (node) => !!node.selected }) : null;
|
|
2508
|
-
createEffect(() => {
|
|
2509
|
-
|
|
2411
|
+
createEffect(() => ({
|
|
2412
|
+
el: ref(),
|
|
2413
|
+
focusable: !store.disableKeyboardA11y
|
|
2414
|
+
}), ({ el, focusable }) => {
|
|
2415
|
+
focusable && el?.focus({ preventScroll: !0 });
|
|
2510
2416
|
});
|
|
2511
2417
|
let onContextMenu = (event) => {
|
|
2512
2418
|
let selectedNodes = store.nodes.filter((n) => n.selected);
|
|
@@ -2550,11 +2456,11 @@ const NodeToolbar = (props) => {
|
|
|
2550
2456
|
diff && (event.preventDefault(), actions.moveSelectedNodes(diff, event.shiftKey ? 4 : 1));
|
|
2551
2457
|
};
|
|
2552
2458
|
return <Show when={store.selectionRectMode === "nodes" && bounds() && isNumeric(bounds()?.x) && isNumeric(bounds()?.y)}>
|
|
2553
|
-
<div ref={setRef} class={
|
|
2459
|
+
<div ref={setRef} class={["solid-flow__selection-wrapper", store.noPanClass]} style={{
|
|
2554
2460
|
width: toPxString(bounds()?.width),
|
|
2555
2461
|
height: toPxString(bounds()?.height),
|
|
2556
2462
|
transform: `translate(${bounds()?.x}px, ${bounds()?.y}px)`
|
|
2557
|
-
}} onClick={onClick} onContextMenu={onContextMenu} role={store.disableKeyboardA11y ? void 0 : "button"}
|
|
2463
|
+
}} onClick={onClick} onContextMenu={onContextMenu} role={store.disableKeyboardA11y ? void 0 : "button"} tabindex={store.disableKeyboardA11y ? void 0 : -1} onKeyDown={store.disableKeyboardA11y ? void 0 : onKeyDown}>
|
|
2558
2464
|
<Selection width="100%" height="100%" x={0} y={0} />
|
|
2559
2465
|
</div>
|
|
2560
2466
|
</Show>;
|
|
@@ -2599,16 +2505,24 @@ function matchesKeyArray(event, keyDefs) {
|
|
|
2599
2505
|
return keyDefs ? (Array.isArray(keyDefs) ? keyDefs : [keyDefs]).some((keyDef) => matchesKey(event, keyDef)) : !1;
|
|
2600
2506
|
}
|
|
2601
2507
|
const KeyHandler = (props) => {
|
|
2602
|
-
let { store, actions } = useInternalSolidFlow(), { deleteElements } = useSolidFlow(), _props =
|
|
2603
|
-
selectionKey
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
}
|
|
2508
|
+
let { store, actions } = useInternalSolidFlow(), { deleteElements } = useSolidFlow(), _props = {
|
|
2509
|
+
get selectionKey() {
|
|
2510
|
+
return props.selectionKey ?? "Shift";
|
|
2511
|
+
},
|
|
2512
|
+
get multiSelectionKey() {
|
|
2513
|
+
return props.multiSelectionKey ?? (isMacOs() ? "Meta" : "Control");
|
|
2514
|
+
},
|
|
2515
|
+
get deleteKey() {
|
|
2516
|
+
return props.deleteKey ?? "Backspace";
|
|
2517
|
+
},
|
|
2518
|
+
get panActivationKey() {
|
|
2519
|
+
return props.panActivationKey ?? " ";
|
|
2520
|
+
},
|
|
2521
|
+
get zoomActivationKey() {
|
|
2522
|
+
return props.zoomActivationKey ?? (isMacOs() ? "Meta" : "Control");
|
|
2523
|
+
}
|
|
2524
|
+
}, resetKeysAndSelection = () => {
|
|
2525
|
+
actions.setSelectionRect(void 0), actions.setSelectionKeyPressed(!1), actions.setMultiselectionKeyPressed(!1), actions.setDeleteKeyPressed(!1), actions.setPanActivationKeyPressed(!1), actions.setZoomActivationKeyPressed(!1);
|
|
2612
2526
|
}, handleDelete = async () => {
|
|
2613
2527
|
let selectedNodes = store.nodes.filter((node) => node.selected), selectedEdges = store.edges.filter((edge) => edge.selected), { deletedNodes, deletedEdges } = await deleteElements({
|
|
2614
2528
|
nodes: selectedNodes,
|
|
@@ -2618,22 +2532,19 @@ const KeyHandler = (props) => {
|
|
|
2618
2532
|
nodes: deletedNodes,
|
|
2619
2533
|
edges: deletedEdges
|
|
2620
2534
|
});
|
|
2621
|
-
}, handleKeyDown = (event) => {
|
|
2622
|
-
batch(() => {
|
|
2623
|
-
matchesKeyArray(event, _props.selectionKey) && actions.setSelectionKeyPressed(!0), matchesKeyArray(event, _props.multiSelectionKey) && actions.setMultiselectionKeyPressed(!0), matchesKeyArray(event, _props.deleteKey) && !isInputDOMNode(event) && (event.ctrlKey || event.metaKey || event.shiftKey || (actions.setDeleteKeyPressed(!0), handleDelete())), matchesKeyArray(event, _props.panActivationKey) && actions.setPanActivationKeyPressed(!0), matchesKeyArray(event, _props.zoomActivationKey) && actions.setZoomActivationKeyPressed(!0);
|
|
2624
|
-
});
|
|
2625
|
-
}, handleKeyUp = (event) => {
|
|
2626
|
-
batch(() => {
|
|
2627
|
-
matchesKeyArray(event, _props.selectionKey) && actions.setSelectionKeyPressed(!1), matchesKeyArray(event, _props.multiSelectionKey) && actions.setMultiselectionKeyPressed(!1), matchesKeyArray(event, _props.deleteKey) && actions.setDeleteKeyPressed(!1), matchesKeyArray(event, _props.panActivationKey) && actions.setPanActivationKeyPressed(!1), matchesKeyArray(event, _props.zoomActivationKey) && actions.setZoomActivationKeyPressed(!1);
|
|
2628
|
-
});
|
|
2629
2535
|
};
|
|
2630
|
-
return
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
}
|
|
2536
|
+
return isServer || createEventListenerMap(window, {
|
|
2537
|
+
keydown: (event) => {
|
|
2538
|
+
matchesKeyArray(event, _props.selectionKey) && actions.setSelectionKeyPressed(!0), matchesKeyArray(event, _props.multiSelectionKey) && actions.setMultiselectionKeyPressed(!0), matchesKeyArray(event, _props.deleteKey) && !isInputDOMNode(event) && (event.ctrlKey || event.metaKey || event.shiftKey || (actions.setDeleteKeyPressed(!0), handleDelete())), matchesKeyArray(event, _props.panActivationKey) && actions.setPanActivationKeyPressed(!0), matchesKeyArray(event, _props.zoomActivationKey) && actions.setZoomActivationKeyPressed(!0), flush();
|
|
2539
|
+
},
|
|
2540
|
+
keyup: (event) => {
|
|
2541
|
+
matchesKeyArray(event, _props.selectionKey) && actions.setSelectionKeyPressed(!1), matchesKeyArray(event, _props.multiSelectionKey) && actions.setMultiselectionKeyPressed(!1), matchesKeyArray(event, _props.deleteKey) && actions.setDeleteKeyPressed(!1), matchesKeyArray(event, _props.panActivationKey) && actions.setPanActivationKeyPressed(!1), matchesKeyArray(event, _props.zoomActivationKey) && actions.setZoomActivationKeyPressed(!1), flush();
|
|
2542
|
+
},
|
|
2543
|
+
blur: resetKeysAndSelection,
|
|
2544
|
+
contextmenu: resetKeysAndSelection
|
|
2634
2545
|
}), null;
|
|
2635
2546
|
}, SolidFlow = (props) => {
|
|
2636
|
-
let domNode, _props =
|
|
2547
|
+
let [domNodeRef, setDomNodeRef] = createSignal(), domNode, _props = merge({
|
|
2637
2548
|
...getDefaultFlowStateProps(),
|
|
2638
2549
|
colorMode: "light",
|
|
2639
2550
|
deleteKeyCode: "Backspace",
|
|
@@ -2659,69 +2570,73 @@ const KeyHandler = (props) => {
|
|
|
2659
2570
|
zoomOnPinch: !0,
|
|
2660
2571
|
zoomOnDoubleClick: !0,
|
|
2661
2572
|
zoomOnScroll: !0
|
|
2662
|
-
}, props),
|
|
2663
|
-
|
|
2664
|
-
actions.
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
actions.setPaneClickDistance(flowProps.paneClickDistance);
|
|
2670
|
-
}), onCleanup(() => {
|
|
2671
|
-
actions.reset();
|
|
2573
|
+
}, props), htmlProps = omit(_props, "nodes", "edges", "nodeTypes", "edgeTypes", "width", "height", "fitView", "fitViewOptions", "nodeOrigin", "nodeDragThreshold", "paneClickDistance", "nodeClickDistance", "minZoom", "maxZoom", "zIndexMode", "initialViewport", "viewport", "translateExtent", "nodeExtent", "selectionKey", "panActivationKey", "deleteKey", "multiSelectionKey", "zoomActivationKey", "panOnDrag", "panOnScroll", "panOnScrollMode", "panOnScrollSpeed", "selectionOnDrag", "selectNodesOnDrag", "preventScrolling", "zoomOnScroll", "zoomOnDoubleClick", "zoomOnPinch", "onlyRenderVisibleElements", "autoPanOnConnect", "autoPanOnNodeDrag", "autoPanOnNodeFocus", "autoPanOnSelection", "autoPanSpeed", "connectionRadius", "connectionMode", "connectionLineType", "connectionLineComponent", "connectionLineStyle", "connectionLineContainerStyle", "connectionDragThreshold", "isValidConnection", "clickConnect", "reconnectRadius", "selectionMode", "elementsSelectable", "nodesDraggable", "nodesConnectable", "nodesFocusable", "edgesFocusable", "disableKeyboardA11y", "ariaLabelConfig", "ariaLiveMessage", "colorMode", "colorModeSSR", "class", "style", "snapGrid", "defaultMarkerColor", "defaultEdgeOptions", "elevateNodesOnSelect", "elevateEdgesOnSelect", "noDragClass", "noPanClass", "noWheelClass", "attributionPosition", "proOptions", "onInit", "onMoveStart", "onMove", "onMoveEnd", "onFlowError", "onNodeClick", "onNodeContextMenu", "onNodeDrag", "onNodeDragStart", "onNodeDragStop", "onNodePointerEnter", "onNodePointerMove", "onNodePointerLeave", "onEdgeClick", "onEdgeContextMenu", "onEdgePointerEnter", "onEdgePointerLeave", "onPaneClick", "onPaneContextMenu", "onSelectionChange", "onSelectionClick", "onSelectionContextMenu", "onSelectionDrag", "onSelectionDragStart", "onSelectionDragStop", "onSelectionStart", "onSelectionEnd", "onConnect", "onConnectStart", "onConnectEnd", "onReconnect", "onReconnectStart", "onReconnectEnd", "onClickConnectStart", "onClickConnectEnd", "onBeforeConnect", "onBeforeReconnect", "onDelete", "onBeforeDelete", "deleteKeyCode", "selectionKeyCode", "panActivationKeyCode", "multiSelectionKeyCode", "zoomActivationKeyCode", "children"), TypedSolidFlowContext = SolidFlowContext, solidFlow = useContext(TypedSolidFlowContext) ?? createSolidFlow(_props), { store, actions } = solidFlow;
|
|
2574
|
+
onSettled(() => (actions.applyInitialFitView(_props.fitView), actions.setConfig(_props), actions.setDomNode(domNode), () => {
|
|
2575
|
+
actions.reset();
|
|
2576
|
+
})), createEffect(() => domNodeRef(), (el) => {
|
|
2577
|
+
if (!el) return;
|
|
2578
|
+
let observer = new ResizeObserver(() => {
|
|
2579
|
+
actions.setWidth(el.clientWidth), actions.setHeight(el.clientHeight);
|
|
2672
2580
|
});
|
|
2581
|
+
return observer.observe(el), () => observer.disconnect();
|
|
2582
|
+
}), createEffect(() => ({
|
|
2583
|
+
panZoom: store.panZoom,
|
|
2584
|
+
distance: _props.paneClickDistance
|
|
2585
|
+
}), ({ panZoom, distance }) => {
|
|
2586
|
+
panZoom?.setClickDistance(distance);
|
|
2673
2587
|
});
|
|
2674
2588
|
let selectedElements = createMemo(() => ({
|
|
2675
2589
|
nodes: store.selectedNodes,
|
|
2676
2590
|
edges: store.selectedEdges
|
|
2677
|
-
}),
|
|
2678
|
-
createEffect(() => {
|
|
2679
|
-
|
|
2680
|
-
untrack(() => flowProps.onSelectionChange)?.(params);
|
|
2591
|
+
}), { equals: (a, b) => a.nodes.length === b.nodes.length && a.edges.length === b.edges.length && a.nodes.every((node, i) => node.id === b.nodes[i].id) && a.edges.every((edge, i) => edge.id === b.edges[i].id) });
|
|
2592
|
+
createEffect(() => selectedElements(), (params) => {
|
|
2593
|
+
untrack(() => _props.onSelectionChange)?.(params);
|
|
2681
2594
|
});
|
|
2682
2595
|
let rootStyle = () => ({
|
|
2683
|
-
width: toPxString(
|
|
2684
|
-
height: toPxString(
|
|
2685
|
-
...
|
|
2596
|
+
width: toPxString(_props.width),
|
|
2597
|
+
height: toPxString(_props.height),
|
|
2598
|
+
..._props.style
|
|
2686
2599
|
});
|
|
2687
|
-
return <div role="application" data-testid="solid-flow__wrapper" ref={
|
|
2600
|
+
return <div role="application" data-testid="solid-flow__wrapper" ref={(el) => {
|
|
2601
|
+
domNode = el, setDomNodeRef(el);
|
|
2602
|
+
}} class={[
|
|
2688
2603
|
"solid-flow",
|
|
2689
2604
|
"solid-flow__container",
|
|
2690
|
-
|
|
2605
|
+
_props.class,
|
|
2691
2606
|
store.colorMode
|
|
2692
|
-
]
|
|
2607
|
+
]} style={rootStyle()} onScroll={(e) => {
|
|
2693
2608
|
e.currentTarget.scrollTo({
|
|
2694
2609
|
top: 0,
|
|
2695
2610
|
left: 0,
|
|
2696
2611
|
behavior: "auto"
|
|
2697
2612
|
});
|
|
2698
2613
|
}} {...htmlProps}>
|
|
2699
|
-
<TypedSolidFlowContext
|
|
2700
|
-
<KeyHandler selectionKey={
|
|
2701
|
-
<Zoom panOnScrollMode={
|
|
2702
|
-
<Pane onPaneClick={
|
|
2614
|
+
<TypedSolidFlowContext value={solidFlow}>
|
|
2615
|
+
<KeyHandler selectionKey={_props.selectionKey} deleteKey={_props.deleteKey} panActivationKey={_props.panActivationKey} multiSelectionKey={_props.multiSelectionKey} zoomActivationKey={_props.zoomActivationKey} />
|
|
2616
|
+
<Zoom panOnScrollMode={_props.panOnScrollMode} preventScrolling={_props.preventScrolling} zoomOnScroll={_props.zoomOnScroll} zoomOnDoubleClick={_props.zoomOnDoubleClick} zoomOnPinch={_props.zoomOnPinch} panOnScroll={_props.panOnScroll} panOnScrollSpeed={_props.panOnScrollSpeed} panOnDrag={_props.panOnDrag} paneClickDistance={_props.paneClickDistance} selectionOnDrag={_props.selectionOnDrag} onMoveStart={_props.onMoveStart} onMove={_props.onMove} onMoveEnd={_props.onMoveEnd} onViewportInitialized={_props.onInit} initialViewport={_props.viewport || _props.initialViewport}>
|
|
2617
|
+
<Pane onPaneClick={_props.onPaneClick} onPaneContextMenu={_props.onPaneContextMenu} onSelectionStart={_props.onSelectionStart} onSelectionEnd={_props.onSelectionEnd} panOnDrag={_props.panOnDrag} selectionOnDrag={_props.selectionOnDrag} paneClickDistance={_props.paneClickDistance} autoPanOnSelection={_props.autoPanOnSelection}>
|
|
2703
2618
|
<Viewport>
|
|
2704
2619
|
<div class="solid-flow__container solid-flow__viewport-back" />
|
|
2705
|
-
<EdgeRenderer reconnectRadius={
|
|
2620
|
+
<EdgeRenderer reconnectRadius={_props.reconnectRadius} onEdgeClick={_props.onEdgeClick} onEdgeContextMenu={_props.onEdgeContextMenu} onEdgePointerEnter={_props.onEdgePointerEnter} onEdgePointerLeave={_props.onEdgePointerLeave} defaultEdgeOptions={_props.defaultEdgeOptions} />
|
|
2706
2621
|
<div class="solid-flow__container solid-flow__edge-labels" />
|
|
2707
|
-
<ConnectionLine type={
|
|
2708
|
-
<NodeRenderer nodeClickDistance={
|
|
2709
|
-
<NodeSelection onSelectionClick={
|
|
2622
|
+
<ConnectionLine type={_props.connectionLineType} component={_props.connectionLineComponent} containerStyle={_props.connectionLineContainerStyle} style={_props.connectionLineStyle} />
|
|
2623
|
+
<NodeRenderer nodeClickDistance={_props.nodeClickDistance} onNodeClick={_props.onNodeClick} onNodeContextMenu={_props.onNodeContextMenu} onNodePointerEnter={_props.onNodePointerEnter} onNodePointerMove={_props.onNodePointerMove} onNodePointerLeave={_props.onNodePointerLeave} onNodeDrag={_props.onNodeDrag} onNodeDragStart={_props.onNodeDragStart} onNodeDragStop={_props.onNodeDragStop} />
|
|
2624
|
+
<NodeSelection onSelectionClick={_props.onSelectionClick} onSelectionContextMenu={_props.onSelectionContextMenu} onNodeDrag={_props.onNodeDrag} onNodeDragStart={_props.onNodeDragStart} onNodeDragStop={_props.onNodeDragStop} />
|
|
2710
2625
|
</Viewport>
|
|
2711
2626
|
<Selection isVisible={!!store.selectionRect && store.selectionRectMode === "user"} width={store.selectionRect?.width} height={store.selectionRect?.height} x={store.selectionRect?.x} y={store.selectionRect?.y} />
|
|
2712
2627
|
</Pane>
|
|
2713
2628
|
</Zoom>
|
|
2714
|
-
<Attribution proOptions={
|
|
2629
|
+
<Attribution proOptions={_props.proOptions} position={_props.attributionPosition} />
|
|
2715
2630
|
<A11yDescriptions />
|
|
2716
|
-
{
|
|
2717
|
-
</TypedSolidFlowContext
|
|
2631
|
+
{_props.children}
|
|
2632
|
+
</TypedSolidFlowContext>
|
|
2718
2633
|
</div>;
|
|
2719
2634
|
}, SolidFlowProvider = (props) => {
|
|
2720
|
-
let _props =
|
|
2635
|
+
let _props = merge(getDefaultFlowStateProps(), props), solidFlow = createSolidFlow(_props);
|
|
2721
2636
|
onCleanup(() => {
|
|
2722
2637
|
solidFlow.actions.reset();
|
|
2723
2638
|
});
|
|
2724
|
-
let ContextProvider = SolidFlowContext
|
|
2639
|
+
let ContextProvider = SolidFlowContext;
|
|
2725
2640
|
return <ContextProvider value={solidFlow}>{props.children}</ContextProvider>;
|
|
2726
2641
|
}, createEdgeStore = (edges) => {
|
|
2727
2642
|
let [store, setStore] = createStore(edges);
|