@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.
@@ -1,13 +1,11 @@
1
- import { For, Index, Show, batch, createComputed, createContext, createEffect, createMemo, createSignal, mapArray, mergeProps, onCleanup, onMount, splitProps, untrack, useContext } from "solid-js";
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 { createStore, produce, unwrap } from "solid-js/store";
6
- import clsx$1, { clsx } from "clsx";
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
- * Creates a signal that can also be updated if the accessor updates.
45
- * @param accessor - A function that returns the initial value for the signal
46
- * @returns A tuple of [getter, setter] similar to createSignal, but the signal is recreated when the accessor's value changes
47
- * @remarks This is useful when you need a signal that can be manually set but also updates when its source value changes
48
- * @example
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 createWritable(accessor) {
57
- let signal = createMemo(() => createSignal(accessor()));
58
- return [() => signal()[0](), (v) => signal()[1](v)];
59
- }
60
- function createWritableStore(accessor) {
61
- let storeMemo = createMemo(() => {
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
- * Schedules a callback during idle time, falling back to a macrotask where
79
- * `requestIdleCallback` is unavailable (Safari, jsdom).
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 = mergeProps({
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
- }, props), [local, rest] = splitProps(_props, [
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" tabIndex={-1} class={clsx$1("solid-flow__edge-label", { transparent: local.transparent }, local.class)} style={{
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(local.width),
106
- height: toPxString(local.height),
107
- transform: `translate(-50%, -50%) translate(${local.x}px,${local.y}px)`,
108
- cursor: local.selectEdgeOnClick ? "pointer" : void 0,
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
- ...local.style
82
+ ..._props.style
111
83
  }} onClick={() => {
112
- local.selectEdgeOnClick && actions.handleEdgeSelection(id());
84
+ _props.selectEdgeOnClick && actions.handleEdgeSelection(id());
113
85
  }} {...rest}>
114
- {local.children}
86
+ {_props.children}
115
87
  </div>
116
88
  </EdgeLabelRenderer>;
117
89
  }, BaseEdge = (props) => {
118
- let _props = mergeProps({ interactionWidth: 20 }, props), [local, rest] = splitProps(_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={local.path} class={clsx$1(["solid-flow__edge-path", local.class])} marker-start={local.markerStart} marker-end={local.markerEnd} fill="none" style={local.style} {...rest} />
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={local.interactionWidth > 0}>
134
- <path d={local.path} stroke-opacity={0} stroke-width={local.interactionWidth} fill="none" class="solid-flow__edge-interaction" />
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={local.label}>
138
- <EdgeLabel x={local.labelX} y={local.labelY} style={local.labelStyle}>
139
- {local.label}
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 = mergeProps({
140
+ let _props = propDefaults(props, {
180
141
  size: 25,
181
142
  reconnecting: !1,
182
143
  style: {}
183
- }, props), [local, rest] = splitProps(_props, [
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(), local.type);
196
- let opposite = local.type === "target" ? {
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={local.position?.x} y={local.position?.y} style={local.style} {...rest}>
241
- <div onPointerDown={onPointerDown} class={clsx$1("solid-flow__edgeupdater", `solid-flow__edgeupdater-${local.type}`, store.noPanClass, local.class)} style={{
242
- width: toPxString(local.size),
243
- height: toPxString(local.size),
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
- ...local.style
205
+ ..._props.style
248
206
  }}>
249
- <Show when={!reconnecting()}>{local.children}</Show>
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.Provider value={edgeId}>
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} 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={clsx$1("solid-flow__edge", `solid-flow__edge-${edgeType()}`, {
290
- animated: edge().animated,
291
- selected: edge().selected,
292
- selectable: selectable()
293
- }, edge().class)} onClick={onClick} onKeyDown={(e) => focusable() && onKeyDown(e)} onContextMenu={(e) => onPointerEvent(e, "contextmenu")} onPointerEnter={(e) => onPointerEvent(e, "pointerenter")} onPointerLeave={(e) => onPointerEvent(e, "pointerleave")} {...edge().domAttributes}>
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.Provider>;
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 = mergeProps({
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
- }, props), { store, nodeLookup, connectionLookup, actions } = useInternalSolidFlow(), [local, rest] = splitProps(_props, [
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 (!local.onConnect && !local.onDisconnect) return;
436
- let conectionKey = `${nodeId()}-${local.type}${local.id ? `-${local.id}` : ""}`;
437
- if (connections = connectionLookup.get(conectionKey), prevConnections && !areConnectionMapsEqual(connections, prevConnections)) {
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: local.isValidConnection ?? store.isValidConnection,
462
- updateConnection: actions.setConnection,
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 && !local.isConnectableStart) return;
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: local.type
441
+ handleType: _props.type
487
442
  }), actions.setClickConnectStartHandle({
488
443
  nodeId: nodeId(),
489
- type: local.type,
444
+ type: _props.type,
490
445
  id: handleId()
491
446
  });
492
447
  return;
493
448
  }
494
- let doc = getHostForElement(event.target), isValidConnectionHandler = local.isValidConnection ?? store.isValidConnection, { connection, isValid } = XYHandle.isValid(event, {
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: local.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(unwrap(store.connection));
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 ? local.isConnectableEnd : local.isConnectableStart);
514
- return <div role="button" aria-label={store.ariaLabelConfig["handle.ariaLabel"]} tabIndex={-1} data-handleid={handleId()} data-nodeid={nodeId()} data-handlepos={local.position} data-id={`${store.id}-${nodeId()}-${local.id || null}-${local.type}`} onClick={store.clickConnect ? onClick : void 0} onPointerDown={onPointerDown} style={local.style} class={clsx$1("solid-flow__handle", `solid-flow__handle-${local.position}`, store.noDragClass, store.noPanClass, local.class, {
515
- valid: valid(),
516
- connectingto: connectingTo(),
517
- connectingfrom: connectingFrom(),
518
- source: !isTarget(),
519
- target: isTarget(),
520
- connectablestart: _props.isConnectableStart,
521
- connectableend: _props.isConnectableEnd,
522
- connectable: connectable(),
523
- connectionindicator: connectionIndicator()
524
- })} {...rest}>
525
- {local.children}
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 = mergeProps({
529
- targetPosition: "top",
530
- sourcePosition: "bottom"
531
- }, props);
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 = mergeProps({ sourcePosition: "bottom" }, 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 onMount(() => {
552
- let { onDrag, onDragStart, onDragStop, onNodeMouseDown } = params(), dragInstance = XYDrag({
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
- function updateDrag(elem, params) {
583
- if (params.disabled) {
584
- dragInstance.destroy();
585
- return;
586
- }
587
- dragInstance.update({
588
- domNode: elem,
589
- nodeId: params.nodeId,
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
- }), createEffect((prev) => prev && prev.sourcePosition === node().sourcePosition && prev.targetPosition === node().targetPosition && prev.nodeType === nodeType() ? prev : (actions.requestUpdateNodeInternals([[node().id, {
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
- })), createEffect((prevNodeRef) => {
639
- let currentNodeRef = nodeRef();
640
- return currentNodeRef === prevNodeRef && nodeHasDimensions(node()) ? prevNodeRef : (prevNodeRef && props.resizeObserver?.unobserve(prevNodeRef), currentNodeRef && props.resizeObserver?.observe(currentNodeRef), currentNodeRef);
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 && batch(() => {
655
- event.preventDefault(), actions.setAriaLiveMessage(store.ariaLabelConfig["node.a11yDescription.ariaLiveMessage"]({
656
- direction: event.key.replace("Arrow", "").toLowerCase(),
657
- x: ~~node().internals.positionAbsolute.x,
658
- y: ~~node().internals.positionAbsolute.y
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={clsx$1("solid-flow__node", `solid-flow__node-${nodeType()}`, {
706
- connectable: connectable(),
707
- draggable: draggable(),
708
- dragging: dragging(),
709
- nopan: draggable(),
710
- parent: isParentNode(),
711
- selectable: selectable(),
712
- selected: node().selected
713
- }, node().class)} style={style()} onClick={onSelectNodeHandler} onPointerEnter={(event) => props.onNodePointerEnter?.({
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()} 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}>
726
- <NodeIdContext.Provider value={nodeId}>
727
- <NodeConnectableContext.Provider value={connectable}>
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.Provider>
730
- </NodeIdContext.Provider>
697
+ </NodeConnectableContext>
698
+ </NodeIdContext>
731
699
  </div>
732
700
  </Show>;
733
701
  }, OutputNode = (props) => {
734
- let _props = mergeProps({ targetPosition: "top" }, 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 key = nodeId, nodeMap = connectionLookup.get(key) || /* @__PURE__ */ new Map();
880
- connectionLookup.set(key, nodeMap.set(connectionKey, connection)), key = `${nodeId}-${type}`;
881
- let typeMap = connectionLookup.get(key) || /* @__PURE__ */ new Map();
882
- if (connectionLookup.set(key, typeMap.set(connectionKey, connection)), handleId) {
883
- key = `${nodeId}-${type}-${handleId}`;
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 key = nodeId, nodeMap = connectionLookup.get(key);
890
- nodeMap && (nodeMap.delete(connectionKey), nodeMap.size === 0 && connectionLookup.delete(key)), key = `${nodeId}-${type}`;
891
- let typeMap = connectionLookup.get(key);
892
- if (typeMap && (typeMap.delete(connectionKey), typeMap.size === 0 && connectionLookup.delete(key)), handleId) {
893
- key = `${nodeId}-${type}-${handleId}`;
894
- let handleMap = connectionLookup.get(key);
895
- handleMap && (handleMap.delete(connectionKey), handleMap.size === 0 && connectionLookup.delete(key));
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 = mergeProps(getDefaultFlowStateProps(), props), nodeLookup = new ReactiveMap(), parentLookup = new ReactiveMap(), edgeLookup = new ReactiveMap(), connectionLookup = new ReactiveMap(), layoutedEdgesMap = new ReactiveMap(), startNodesInitialized = batch(() => adoptUserNodes(_props.nodes, nodeLookup, parentLookup, {
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] = createWritable(() => mergeAriaLabelConfig(config().ariaLabelConfig)), [ariaLiveMessage, setAriaLiveMessage] = createWritable(() => config().ariaLiveMessage), [clickConnectStartHandle, setClickConnectStartHandle] = createSignal(void 0), [connection, setConnection] = createSignal(initialConnection), [domNode, setDomNode] = createSignal(null), [dragging, setDragging] = createSignal(!1), [elementsSelectable, setElementsSelectable] = createWritable(() => config().elementsSelectable), [height, setHeight] = createWritable(() => config().height), [minZoom, _setMinZoom] = createWritable(() => config().minZoom), [maxZoom, _setMaxZoom] = createWritable(() => config().maxZoom), [nodesConnectable, setNodesConnectable] = createWritable(() => config().nodesDraggable), [nodesDraggable, setNodesDraggable] = createWritable(() => config().nodesDraggable), [panZoom, setPanZoom] = createSignal(null), [selectionRect, setSelectionRect] = createSignal(), [selectionRectMode, setSelectionRectMode] = createSignal(), [snapGrid, setSnapGrid] = createWritable(() => config().snapGrid), [translateExtent, _setTranslateExtent] = createWritable(() => config().translateExtent ?? infiniteExtent), [width, setWidth] = createWritable(() => config().width), [selectionKeyPressed, setSelectionKeyPressed] = createSignal(!1), [multiselectionKeyPressed, setMultiselectionKeyPressed] = createSignal(!1), [deleteKeyPressed, setDeleteKeyPressed] = createSignal(!1), [panActivationKeyPressed, setPanActivationKeyPressed] = createSignal(!1), [zoomActivationKeyPressed, setZoomActivationKeyPressed] = createSignal(!1), nodesMemo = createWritableStore(() => config().nodes), edgesMemo = createWritableStore(() => config().edges), viewportMemo = createWritableStore(() => config().viewport ?? initialViewport), transform = createMemo(() => [
928
- viewportMemo.get().x,
929
- viewportMemo.get().y,
930
- viewportMemo.get().zoom
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 = nodesMemo.get();
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 = mergeProps({
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 nodesMemo.get();
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 nodesMemo.get().filter((node) => node.selected);
998
+ return nodesStore.filter((node) => node.selected);
1024
999
  },
1025
1000
  get selectedEdges() {
1026
- return edgesMemo.get().filter((edge) => edge.selected);
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 viewportMemo.get();
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), viewportMemo.set(config().initialViewport ?? {
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
- edgesMemo.set((edges) => addEdge$1(edgeParams, edges));
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
- nodesMemo.set((node) => nodeDragItems.has(node.id), produce((node) => {
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
- batch(() => {
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
- nodesMemo.set((node) => nodeToChange.has(node.id), produce((node) => {
1123
- let change = nodeToChange.get(node.id);
1124
- switch (change.type) {
1125
- case "dimensions":
1126
- change.setAttributes && (node.width = change.dimensions?.width ?? node.width, node.height = change.dimensions?.height ?? node.height), node.measured = {
1127
- ...node.measured,
1128
- ...change.dimensions
1129
- };
1130
- break;
1131
- case "position": node.position = change.position ?? node.position;
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 && nodesMemo.set((node) => nodesToUnselect.has(node.id), produce((node) => {
1152
- node.selected = !1;
1153
- }));
1154
- let edgesToUnselect = new Set((edges || store.edges).map(({ id }) => id));
1155
- edgesToUnselect.size && edgesMemo.set((edge) => edgesToUnselect.has(edge.id), produce((edge) => {
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
- nodesMemo.set((node) => {
1161
- let nodeWillBeSelected = ids.includes(node.id), selected = isMultiSelection && node.selected || nodeWillBeSelected;
1162
- return selectState.set(node.id, selected), node.selected !== selected;
1163
- }, produce((node) => {
1164
- let internalNode = nodeLookup.get(node.id);
1165
- internalNode && (internalNode.selected = selectState.get(node.id)), node.selected = selectState.get(node.id);
1166
- })), isMultiSelection || unselectNodesAndEdges({ nodes: [] });
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
- edgesMemo.set((edge) => {
1170
- let edgeWillBeSelected = ids.includes(edge.id), selected = isMultiSelection && edge.selected || edgeWillBeSelected;
1171
- return edgeSelectState.set(edge.id, selected), edge.selected !== selected;
1172
- }, produce((edge) => {
1173
- edge.selected = edgeSelectState.get(edge.id);
1174
- })), isMultiSelection || unselectNodesAndEdges({ edges: [] });
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
- width() && height() && panZoom() && tryInitialFitView();
1178
- }), createEffect(() => {
1179
- store.panZoom?.syncViewport(store.viewport);
1180
- }), createEffect(() => {
1181
- let _panZoom = panZoom();
1182
- _panZoom && (createEffect(() => {
1183
- _panZoom.setScaleExtent([store.minZoom, store.maxZoom]);
1184
- }), createEffect(() => {
1185
- _panZoom.setTranslateExtent(store.translateExtent);
1186
- }));
1187
- }), createComputed(mapArray(() => store.nodes, (userNode) => {
1188
- createComputed(() => {
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 currentIds = new Set(store.nodes.map((n) => n.id));
1212
- for (let id of Array.from(nodeLookup.keys())) currentIds.has(id) || nodeLookup.delete(id);
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
- createComputed(() => {
1222
- batch(() => {
1223
- addConnectionToLookup("source", connection, targetKey, connectionLookup, sourceNodeId, sourceHandle), addConnectionToLookup("target", connection, sourceKey, connectionLookup, targetNodeId, targetHandle), edgeLookup.set(edge.id, edge);
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
- batch(() => {
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 currentIds = new Set(store.edges.map((e) => e.id));
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 edgesMemo.set;
1276
+ return setEdgesStore;
1292
1277
  },
1293
1278
  setElementsSelectable,
1294
1279
  setHeight,
1295
1280
  setMultiselectionKeyPressed,
1296
1281
  get setNodes() {
1297
- return nodesMemo.set;
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 viewportMemo.set;
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 && (batch(() => {
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) && (batch(() => {
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 = mergeProps({
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
- }, props), color = () => _props.color ?? "var(--xy-edge-stroke)";
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 }), batch(() => {
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
- batch(() => {
1498
- if (!isSetEqual(prevSelectedNodeIds, selectedNodeIds)) {
1499
- let selectionMap = /* @__PURE__ */ new Map();
1500
- actions.setNodes((node) => {
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
- if (!isSetEqual(prevSelectedEdgeIds, selectedEdgeIds)) {
1508
- let selectionMap = /* @__PURE__ */ new Map();
1509
- actions.setEdges((edge) => {
1510
- let isSelected = selectedEdgeIds.has(edge.id);
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
- actions.setSelectionRectMode("user"), actions.setSelectionRect(nextUserSelectRect);
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), batch(() => {
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
- }, onContextMenu = (event) => {
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.addEventListener("click", (e) => {
1577
- isSelectionEnabled() && onClickCapture(e);
1578
- }, { capture: !0 });
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
- })} onClick={(e) => isSelectionEnabled() ? void 0 : onClick(e)} on:pointerdown={{
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 = mergeProps({
1558
+ let { store } = useInternalSolidFlow(), _props = propDefaults(props, {
1593
1559
  position: "top-right",
1594
1560
  style: {}
1595
- }, props), [local, rest] = splitProps(_props, [
1596
- "class",
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
- ...local.position.split("-"),
1604
- local.class
1605
- ])} style={{
1564
+ ..._props.position.split("-"),
1565
+ _props.class
1566
+ ]} style={{
1606
1567
  "pointer-events": store.selectionRectMode ? "none" : void 0,
1607
- ...local.style
1568
+ ..._props.style
1608
1569
  }} {...rest}>
1609
- {local.children}
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 onMount(() => {
1637
- let panZoomInstance = XYPanZoom({
1638
- domNode: ref,
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
- (viewPort().x !== vp.x || viewPort().y !== vp.y || viewPort().zoom !== vp.zoom) && onTransformChange([
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
- ]), batch(() => {
1653
- actions.setViewport(vp), actions.setPanZoom(panZoomInstance);
1654
- }), props.onViewportInitialized?.(), createEffect(() => {
1655
- panZoomInstance.update({
1656
- lib: store.lib,
1657
- panActivationKeyPressed: store.panActivationKeyPressed,
1658
- zoomActivationKeyPressed: store.zoomActivationKeyPressed,
1659
- noPanClassName: store.noPanClass,
1660
- noWheelClassName: store.noWheelClass,
1661
- userSelectionActive: !!store.selectionRect,
1662
- panOnScrollSpeed: props.panOnScrollSpeed,
1663
- panOnDrag: panOnDrag(),
1664
- panOnScroll: panOnScroll(),
1665
- zoomOnScroll: props.zoomOnScroll,
1666
- zoomOnDoubleClick: props.zoomOnDoubleClick,
1667
- zoomOnPinch: props.zoomOnPinch,
1668
- panOnScrollMode: props.panOnScrollMode,
1669
- preventScrolling: typeof props.preventScrolling != "boolean" || props.preventScrolling,
1670
- paneClickDistance: props.paneClickDistance,
1671
- selectionOnDrag: props.selectionOnDrag,
1672
- connectionInProgress: store.connection.inProgress,
1673
- onTransformChange
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={ref} class="solid-flow__container solid-flow__zoom">
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={clsx$1(["solid-flow__connection", connectionStatus()])}>
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 = mergeProps({ radius: 5 }, props);
1726
- return <circle class={clsx$1("solid-flow__background-pattern", "dots", _props.class)} cx={_props.radius} cy={_props.radius} r={_props.radius} />;
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 = mergeProps({ lineWidth: 1 }, 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={clsx("solid-flow__background-pattern", _props.variant, _props.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 = mergeProps({
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
- }, props), { 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];
1742
- return <svg data-testid="solid-flow__background" class={clsx$1("solid-flow__container solid-flow__background", _props.class)} style={{
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 [local, rest] = splitProps(props, [
1756
- "class",
1757
- "bgColor",
1758
- "bgColorHover",
1759
- "color",
1760
- "colorHover",
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={clsx$1("solid-flow__controls-button", local.class)} onClick={(e) => local.onClick?.(e)} style={style()} {...rest}>
1772
- {local.children}
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 = mergeProps({
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
- }, props), [local, rest] = splitProps(_props, [
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(local.fitViewOptions);
1760
+ actions.fitView(_props.fitViewOptions);
1814
1761
  }, onToggleInteractivity = () => {
1815
1762
  let newValue = !getIsInteractive();
1816
- batch(() => {
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: local.buttonBgColor,
1821
- bgColorHover: local.buttonBgColorHover,
1822
- color: local.buttonColor,
1823
- colorHover: local.buttonColorHover,
1824
- borderColor: local.buttonBorderColor
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={clsx$1([
1771
+ return <Panel class={[
1827
1772
  "solid-flow__controls",
1828
- local.orientation,
1829
- local.class
1830
- ])} position={local.position} data-testid="solid-flow__controls" aria-label={store.ariaLabelConfig["controls.ariaLabel"]} style={local.style} {...rest}>
1831
- {local.beforeControls}
1832
- <Show when={local.showZoom}>
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={local.showFitView}>
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={local.showLock}>
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
- {local.children}
1855
- {local.afterControls}
1799
+ {_props.children}
1800
+ {_props.afterControls}
1856
1801
  </Panel>;
1857
1802
  }, EdgeToolbar = (props) => {
1858
- let [local, rest] = splitProps(props, [
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={local.selectEdgeOnClick} transparent>
1870
- <div class={clsx$1("solid-flow__edge-toolbar", local.class)} style={{
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
- {local.children}
1811
+ {props.children}
1876
1812
  </div>
1877
1813
  </EdgeLabel>
1878
1814
  </Show>;
1879
1815
  }, MiniMapNode = (props) => {
1880
- let _props = mergeProps({
1816
+ let _props = propDefaults(props, {
1881
1817
  borderRadius: 5,
1882
1818
  width: 0,
1883
1819
  height: 0
1884
- }, props), style = () => Object.entries({
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={clsx$1("solid-flow__minimap-node", { selected: _props.selected }, _props.class)} x={_props.x} y={_props.y} rx={_props.borderRadius} ry={_props.borderRadius} width={_props.width} height={_props.height} shape-rendering={_props.shapeRendering} style={style()} />;
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 = mergeProps({
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
- }, props), [local, paneProps] = splitProps(_props, [
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 / local.width, getScaledHeight = () => getBoundingRect().height / local.height, getViewScale = () => Math.max(getScaledWidth(), getScaledHeight()), getViewWidth = () => getViewScale() * local.width, getViewHeight = () => getViewScale() * local.height, getOffset = () => 5 * getViewScale(), getX = () => {
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 = () => local.maskStrokeWidth ? local.maskStrokeWidth * getViewScale() : void 0, prevNodeIds = [], nodeIds = () => {
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={local.position} data-testid="solid-flow__minimap" class={clsx$1(["solid-flow__minimap", local.class])} style={{
1940
- "--xy-minimap-background-color-props": local.bgColor,
1941
- ...local.style
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 onMount(() => {
1947
- let minimap = XYMinimap({
1948
- domNode: ref(),
1949
- panZoom: panZoom(),
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
- createEffect(() => {
1954
- minimap.update({
1955
- translateExtent: store.translateExtent,
1956
- width: store.width,
1957
- height: store.height,
1958
- inversePan: local.inversePan,
1959
- zoomStep: local.zoomStep,
1960
- pannable: local.pannable,
1961
- zoomable: local.zoomable
1962
- });
1963
- }), onCleanup(() => {
1964
- minimap.destroy();
1965
- });
1966
- }), <svg ref={setRef} width={local.width} height={local.height} viewBox={`${getX()} ${getY()} ${getViewboxWidth()} ${getViewboxHeight()}`} class="solid-flow__minimap-svg" role="img" aria-labelledby={labelledBy()} style={{
1967
- "--xy-minimap-mask-background-color-props": local.maskColor,
1968
- "--xy-minimap-mask-stroke-color-props": local.maskStrokeColor,
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
- <Index each={nodeIds()}>
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={local.nodeBorderRadius} strokeWidth={local.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())} />}
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
- </Index>
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 = mergeProps({
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
- }, props), [local, rest] = splitProps(_props, [
1997
- "nodeId",
1998
- "variant",
1999
- "position",
2000
- "minWidth",
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((node) => changes.has(node.id), produce((node) => {
2038
- let nodeChange = changes.get(node.id);
2039
- node.width = nodeChange.width, node.height = nodeChange.height, node.position = {
2040
- x: nodeChange.position?.x ?? node.position.x,
2041
- y: nodeChange.position?.y ?? node.position.y
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
- createEffect(() => {
2047
- resizer.update({
2048
- controlPosition: controlPosition(),
2049
- boundaries: {
2050
- minWidth: local.minWidth,
2051
- minHeight: local.minHeight,
2052
- maxWidth: local.maxWidth,
2053
- maxHeight: local.maxHeight
2054
- },
2055
- keepAspectRatio: !!local.keepAspectRatio,
2056
- onResizeStart: local.onResizeStart,
2057
- onResize: local.onResize,
2058
- onResizeEnd: local.onResizeEnd,
2059
- shouldResize: local.shouldResize
2060
- });
2061
- }), onCleanup(() => {
2062
- resizer.destroy();
2063
- });
2064
- }), <div ref={resizeControlRef} class={clsx$1([
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
- local.variant,
1982
+ _props.variant,
2067
1983
  store.noDragClass,
2068
1984
  ...positionClassNames(),
2069
- local.class
2070
- ])} style={{
2071
- "border-color": isLineVariant() ? local.color : void 0,
2072
- "background-color": isLineVariant() ? void 0 : local.color,
2073
- scale: isLineVariant() || !local.autoScale ? void 0 : Math.max(1 / store.viewport.zoom, 1),
2074
- ...local.style
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
- {local.children}
1992
+ {_props.children}
2077
1993
  </div>;
2078
1994
  }, NodeResizer = (props) => {
2079
- let _props = mergeProps({
1995
+ let _props = propDefaults(props, {
2080
1996
  autoScale: !0,
2081
1997
  visible: !0
2082
- }, props), [local, rest] = splitProps(props, [
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={local.lineClass} style={local.lineStyle} {...rest} />}
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={local.handleClass} style={local.handleStyle} {...rest} />}
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) && batch(() => {
2163
- actions.setSelectionRect(void 0), actions.setSelectionRectMode(void 0), edge.selected ? edge.selected && store.multiselectionKeyPressed && actions.unselectNodesAndEdges({
2164
- nodes: [],
2165
- edges: [edge]
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((prevConnections) => {
2229
- let nextConnections = connectionLookup.get(lookupKey());
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((node) => node.id === id, (node) => {
2271
- let nextNode = typeof nodeUpdate == "function" ? nodeUpdate(node) : nodeUpdate;
2272
- return options?.replace && isNode(nextNode) ? nextNode : {
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((edge) => edge.id === id, (edge) => {
2279
- let nextEdge = typeof edgeUpdate == "function" ? edgeUpdate(edge) : edgeUpdate;
2280
- return options.replace && isEdge(nextEdge) ? nextEdge : {
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: () => unwrap(store.viewport),
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
- return batch(() => {
2351
- if (matchingEdges) {
2352
- let remmainingEdges = store.edges.filter((edge) => !matchingEdges.some(({ id }) => id === edge.id));
2353
- store.onEdgesDelete?.(matchingEdges), actions.setEdges(remmainingEdges);
2354
- }
2355
- if (matchingNodes) {
2356
- let remmainingNodes = store.nodes.filter((node) => !matchingNodes.some(({ id }) => id === node.id));
2357
- store.onNodesDelete?.(matchingNodes), actions.setNodes(remmainingNodes);
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: [...unwrap(store.nodes)],
2395
- edges: [...unwrap(store.edges)],
2396
- viewport: { ...unwrap(store.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 = mergeProps({
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
- }, props), [local, divProps] = splitProps(_props, [
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(local.nodeId) ? local.nodeId : [local.nodeId ?? ctxNodeId()]).reduce((res, nodeId) => {
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, local.position, local.offset, local.align) : "";
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 local.isVisible == "boolean" ? local.isVisible : nodes.length === 1 && !!nodes[0].selected && selectedNodesCount() === 1;
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
- ...local.style
2394
+ ..._props.style
2492
2395
  }} {...divProps}>
2493
- {local.children}
2396
+ {_props.children}
2494
2397
  </div>
2495
2398
  </Portal>
2496
2399
  </Show>;
2497
2400
  }, Selection = (props) => {
2498
- let _props = mergeProps({ isVisible: !0 }, props), styles = () => ({
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
- store.disableKeyboardA11y || ref()?.focus({ preventScroll: !0 });
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={clsx$1("solid-flow__selection-wrapper", store.noPanClass)} style={{
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"} tabIndex={store.disableKeyboardA11y ? void 0 : -1} onKeyDown={store.disableKeyboardA11y ? void 0 : onKeyDown}>
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 = mergeProps({
2603
- selectionKey: "Shift",
2604
- multiSelectionKey: isMacOs() ? "Meta" : "Control",
2605
- deleteKey: "Backspace",
2606
- panActivationKey: " ",
2607
- zoomActivationKey: isMacOs() ? "Meta" : "Control"
2608
- }, props), resetKeysAndSelection = () => {
2609
- batch(() => {
2610
- actions.setSelectionRect(void 0), actions.setSelectionKeyPressed(!1), actions.setMultiselectionKeyPressed(!1), actions.setDeleteKeyPressed(!1), actions.setPanActivationKeyPressed(!1), actions.setZoomActivationKeyPressed(!1);
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 onMount(() => {
2631
- window.addEventListener("keydown", handleKeyDown), window.addEventListener("keyup", handleKeyUp), window.addEventListener("blur", resetKeysAndSelection), window.addEventListener("contextmenu", resetKeysAndSelection), onCleanup(() => {
2632
- window.removeEventListener("keydown", handleKeyDown), window.removeEventListener("keyup", handleKeyUp), window.removeEventListener("blur", resetKeysAndSelection), window.removeEventListener("contextmenu", resetKeysAndSelection);
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 = mergeProps({
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), [flowProps, htmlProps] = splitProps(_props, /* @__PURE__ */ "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".split(".")), TypedSolidFlowContext = SolidFlowContext, solidFlow = useContext(TypedSolidFlowContext) ?? createSolidFlow(_props), { store, actions } = solidFlow;
2663
- onMount(() => {
2664
- actions.applyInitialFitView(flowProps.fitView), batch(() => {
2665
- actions.setConfig(_props), actions.setDomNode(domNode);
2666
- }), createResizeObserver(domNode, () => {
2667
- actions.setWidth(domNode.clientWidth), actions.setHeight(domNode.clientHeight);
2668
- }), createEffect(() => {
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
- }), void 0, { 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) });
2678
- createEffect(() => {
2679
- let params = selectedElements();
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(flowProps.width),
2684
- height: toPxString(flowProps.height),
2685
- ...flowProps.style
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={domNode} class={clsx$1([
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
- flowProps.class,
2605
+ _props.class,
2691
2606
  store.colorMode
2692
- ])} style={rootStyle()} onScroll={(e) => {
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.Provider value={solidFlow}>
2700
- <KeyHandler selectionKey={flowProps.selectionKey} deleteKey={flowProps.deleteKey} panActivationKey={flowProps.panActivationKey} multiSelectionKey={flowProps.multiSelectionKey} zoomActivationKey={flowProps.zoomActivationKey} />
2701
- <Zoom panOnScrollMode={flowProps.panOnScrollMode} preventScrolling={flowProps.preventScrolling} zoomOnScroll={flowProps.zoomOnScroll} zoomOnDoubleClick={flowProps.zoomOnDoubleClick} zoomOnPinch={flowProps.zoomOnPinch} panOnScroll={flowProps.panOnScroll} panOnScrollSpeed={flowProps.panOnScrollSpeed} panOnDrag={flowProps.panOnDrag} paneClickDistance={flowProps.paneClickDistance} selectionOnDrag={flowProps.selectionOnDrag} onMoveStart={flowProps.onMoveStart} onMove={flowProps.onMove} onMoveEnd={flowProps.onMoveEnd} onViewportInitialized={flowProps.onInit} initialViewport={flowProps.viewport || flowProps.initialViewport}>
2702
- <Pane onPaneClick={flowProps.onPaneClick} onPaneContextMenu={flowProps.onPaneContextMenu} onSelectionStart={flowProps.onSelectionStart} onSelectionEnd={flowProps.onSelectionEnd} panOnDrag={flowProps.panOnDrag} selectionOnDrag={flowProps.selectionOnDrag} paneClickDistance={flowProps.paneClickDistance} autoPanOnSelection={flowProps.autoPanOnSelection}>
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={flowProps.reconnectRadius} onEdgeClick={flowProps.onEdgeClick} onEdgeContextMenu={flowProps.onEdgeContextMenu} onEdgePointerEnter={flowProps.onEdgePointerEnter} onEdgePointerLeave={flowProps.onEdgePointerLeave} defaultEdgeOptions={flowProps.defaultEdgeOptions} />
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={flowProps.connectionLineType} component={flowProps.connectionLineComponent} containerStyle={flowProps.connectionLineContainerStyle} style={flowProps.connectionLineStyle} />
2708
- <NodeRenderer nodeClickDistance={flowProps.nodeClickDistance} onNodeClick={flowProps.onNodeClick} onNodeContextMenu={flowProps.onNodeContextMenu} onNodePointerEnter={flowProps.onNodePointerEnter} onNodePointerMove={flowProps.onNodePointerMove} onNodePointerLeave={flowProps.onNodePointerLeave} onNodeDrag={flowProps.onNodeDrag} onNodeDragStart={flowProps.onNodeDragStart} onNodeDragStop={flowProps.onNodeDragStop} />
2709
- <NodeSelection onSelectionClick={flowProps.onSelectionClick} onSelectionContextMenu={flowProps.onSelectionContextMenu} onNodeDrag={flowProps.onNodeDrag} onNodeDragStart={flowProps.onNodeDragStart} onNodeDragStop={flowProps.onNodeDragStop} />
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={flowProps.proOptions} position={flowProps.attributionPosition} />
2629
+ <Attribution proOptions={_props.proOptions} position={_props.attributionPosition} />
2715
2630
  <A11yDescriptions />
2716
- {flowProps.children}
2717
- </TypedSolidFlowContext.Provider>
2631
+ {_props.children}
2632
+ </TypedSolidFlowContext>
2718
2633
  </div>;
2719
2634
  }, SolidFlowProvider = (props) => {
2720
- let _props = mergeProps(getDefaultFlowStateProps(), props), solidFlow = createSolidFlow(_props);
2635
+ let _props = merge(getDefaultFlowStateProps(), props), solidFlow = createSolidFlow(_props);
2721
2636
  onCleanup(() => {
2722
2637
  solidFlow.actions.reset();
2723
2638
  });
2724
- let ContextProvider = SolidFlowContext.Provider;
2639
+ let ContextProvider = SolidFlowContext;
2725
2640
  return <ContextProvider value={solidFlow}>{props.children}</ContextProvider>;
2726
2641
  }, createEdgeStore = (edges) => {
2727
2642
  let [store, setStore] = createStore(edges);