@dschz/solid-flow 0.3.0-next.3 → 0.3.0-next.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,9 +5,18 @@ import { createMediaQuery } from "@solid-primitives/media";
5
5
  import { createEventListener, createEventListenerMap } from "@solid-primitives/event-listener";
6
6
  //#region src/contexts/edgeId.ts
7
7
  const EdgeIdContext = createContext(null);
8
+ /**
9
+ * Returns the id of the edge this component is rendered inside. Available
10
+ * anywhere in a custom edge's subtree (provided by the edge wrapper), so
11
+ * nested components — like a custom edge label — can learn their host edge
12
+ * without prop drilling.
13
+ *
14
+ * @public
15
+ * @returns a reactive accessor for the surrounding edge's id
16
+ */
8
17
  function useEdgeId() {
9
18
  let ctx = useContext(EdgeIdContext);
10
- if (!ctx) throw Error("solid-flow: Your application must be wrapped with <SolidFlow> in order to invoke useEdgeId");
19
+ if (!ctx) throw Error("solid-flow: useEdgeId must be called inside an edge component (anywhere under a custom edge's subtree)");
11
20
  return ctx;
12
21
  }
13
22
  //#endregion
@@ -281,11 +290,13 @@ const EdgeReconnectAnchor = (props) => {
281
290
  size: 25,
282
291
  reconnecting: !1,
283
292
  style: {}
284
- }), rest = omit(_props, "type", "class", "style", "position", "size", "reconnecting", "children"), { store, nodeLookup, edgeLookup, actions } = useInternalSolidFlow(), edgeId = useEdgeId(), [reconnecting, setReconnecting] = createSignal(!1);
293
+ }), rest = omit(_props, "type", "class", "style", "position", "size", "reconnecting", "onReconnectingChange", "children"), { store, nodeLookup, edgeLookup, actions } = useInternalSolidFlow(), edgeId = useEdgeId(), [reconnecting, setReconnecting] = createSignal(!1);
285
294
  if (!edgeId()) throw Error("[solid-flow]: EdgeReconnectAnchor must be used within an Edge component");
286
- let edge = () => edgeLookup[edgeId()], onPointerDown = (event) => {
295
+ let edge = () => edgeLookup[edgeId()], isReconnecting = () => _props.reconnecting || reconnecting(), setReconnectingState = (next) => {
296
+ setReconnecting(next), _props.onReconnectingChange?.(next);
297
+ }, onPointerDown = (event) => {
287
298
  if (event.button !== 0) return;
288
- setReconnecting(!0), store.onReconnectStart?.(event, edge(), _props.type);
299
+ setReconnectingState(!0), store.onReconnectStart?.(event, edge(), _props.type);
289
300
  let opposite = _props.type === "target" ? {
290
301
  nodeId: edge().source,
291
302
  handleId: edge().sourceHandle ?? null,
@@ -309,7 +320,9 @@ const EdgeReconnectAnchor = (props) => {
309
320
  edgeUpdaterType: opposite.type,
310
321
  cancelConnection: actions.cancelConnection,
311
322
  panBy: actions.panBy,
312
- updateConnection: actions.setConnection,
323
+ updateConnection: (connection) => {
324
+ actions.setConnection(connection), flush();
325
+ },
313
326
  isValidConnection: store.isValidConnection,
314
327
  onConnectStart: store.onConnectStart,
315
328
  onConnectEnd: store.onConnectEnd,
@@ -321,7 +334,7 @@ const EdgeReconnectAnchor = (props) => {
321
334
  newEdge = store.onBeforeReconnect?.(newEdge, edge()) ?? newEdge, newEdge && actions.setEdges((edges) => edges.map((e) => e.id === edge().id ? newEdge : e)), store.onReconnect?.(edge(), connection);
322
335
  },
323
336
  onReconnectEnd: (event, connectionState) => {
324
- setReconnecting(!1), store.onReconnectEnd?.(event, edge(), opposite.type, connectionState);
337
+ setReconnectingState(!1), store.onReconnectEnd?.(event, edge(), opposite.type, connectionState);
325
338
  },
326
339
  getTransform: () => store.transform,
327
340
  getFromHandle: () => store.connection.fromHandle,
@@ -344,7 +357,7 @@ const EdgeReconnectAnchor = (props) => {
344
357
  var _el$ = _tmpl$$32();
345
358
  return _el$.$$pointerdown = onPointerDown, insert(_el$, createComponent(Show, {
346
359
  get when() {
347
- return !reconnecting();
360
+ return !isReconnecting();
348
361
  },
349
362
  get children() {
350
363
  return _props.children;
@@ -407,7 +420,6 @@ const A11yDescriptions = () => {
407
420
  let [store, setStore] = createStore(edges);
408
421
  return [store, setStore];
409
422
  }, STEP = .5 / 2, rectsEqual = (a, b) => a === b || !!a && !!b && a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height, rectsOverlap = (a, b) => a.x <= b.x + b.width && a.x + a.width >= b.x && a.y <= b.y + b.height && a.y + a.height >= b.y, createCullingViewport = (source) => createMemo(() => {
410
- if (!source.onlyRenderVisibleElements) return null;
411
423
  let { width, height } = source;
412
424
  if (!width || !height) return null;
413
425
  let [tx, ty, zoom] = source.transform, zoomBucket = 2 ** Math.floor(Math.log2(zoom)), bucketWidth = width / zoomBucket, bucketHeight = height / zoomBucket, stepX = bucketWidth * STEP, stepY = bucketHeight * STEP, centerX = (width / 2 - tx) / zoom, centerY = (height / 2 - ty) / zoom, quantizedX = Math.round(centerX / stepX) * stepX, quantizedY = Math.round(centerY / stepY) * stepY, halfWidth = bucketWidth * 1, halfHeight = bucketHeight * 1;
@@ -471,7 +483,7 @@ const A11yDescriptions = () => {
471
483
  selectNodesOnDrag: !0,
472
484
  elevateNodesOnSelect: !0,
473
485
  zIndexMode: "basic",
474
- onlyRenderVisibleElements: !0,
486
+ onlyRenderVisibleElements: !1,
475
487
  disableKeyboardA11y: !1,
476
488
  defaultMarkerColor: "#b1b1b7",
477
489
  ariaLiveMessage: "",
@@ -761,9 +773,17 @@ const createLayoutedEdges = (source) => {
761
773
  return config().zIndexMode;
762
774
  }
763
775
  }), nodeLookup = new RecordMapFacade(internalNodes), initialViewport = getInitialViewport(_props.fitView, _props.initialViewport, _props.width ?? 0, _props.height ?? 0, nodeLookup), [viewportStore, setViewportStore] = createStore(_props.viewport ?? initialViewport);
764
- createEffect(() => config().nodes, (next) => {
776
+ createEffect(() => {
777
+ let next = config().nodes;
778
+ for (let node of next);
779
+ return { next };
780
+ }, ({ next }) => {
765
781
  setNodesStore(() => next);
766
- }, { defer: !0 }), createEffect(() => config().edges, (next) => {
782
+ }, { defer: !0 }), createEffect(() => {
783
+ let next = config().edges;
784
+ for (let edge of next);
785
+ return { next };
786
+ }, ({ next }) => {
767
787
  setEdgesStore(() => next);
768
788
  }, { defer: !0 }), createEffect(() => config().viewport, (next) => {
769
789
  next && setViewportStore(() => next);
@@ -924,9 +944,6 @@ const createLayoutedEdges = (source) => {
924
944
  return zoomActivationKeyPressed();
925
945
  }
926
946
  }), cullingViewport = createCullingViewport({
927
- get onlyRenderVisibleElements() {
928
- return store.onlyRenderVisibleElements;
929
- },
930
947
  get width() {
931
948
  return store.width;
932
949
  },
@@ -2095,9 +2112,18 @@ const GroupNode = (props) => (() => {
2095
2112
  };
2096
2113
  }), dragging;
2097
2114
  }, NodeIdContext = createContext(null);
2115
+ /**
2116
+ * Returns the id of the node this component is rendered inside. Available
2117
+ * anywhere in a custom node's subtree (provided by the node wrapper), so
2118
+ * nested components — like a custom `Handle` — can learn their host node
2119
+ * without prop drilling.
2120
+ *
2121
+ * @public
2122
+ * @returns a reactive accessor for the surrounding node's id
2123
+ */
2098
2124
  function useNodeId() {
2099
2125
  let ctx = useContext(NodeIdContext);
2100
- if (!ctx) throw Error("solid-flow: Your application must be wrapped with <SolidFlow> in order to invoke useNodeId");
2126
+ if (!ctx) throw Error("solid-flow: useNodeId must be called inside a node component (anywhere under a custom node's subtree)");
2101
2127
  return ctx;
2102
2128
  }
2103
2129
  //#endregion
@@ -2105,7 +2131,12 @@ function useNodeId() {
2105
2131
  var _tmpl$$27 = /* @__PURE__ */ template("<div>");
2106
2132
  /** Internal per-node wrapper: dragging, selection, a11y, measurement, viewport culling, and the dynamic node component. */
2107
2133
  const NodeWrapper = (props) => {
2108
- let { store, nodeLookup, parentIds, actions } = useInternalSolidFlow(), [nodeRef, setNodeRef] = createSignal(), node = () => nodeLookup.get(props.nodeId), nodeId = () => node().id, nodeType = () => node().type ?? "default", deletable = () => node().deletable ?? !0, selectable = () => node().selectable ?? store.elementsSelectable, focusable = () => node().focusable ?? store.nodesFocusable, draggable = () => node().draggable ?? store.nodesDraggable, connectable = () => node().connectable ?? store.nodesConnectable, userNode = () => node().internals.userNode, nodeTypeValid = () => nodeType() in store.nodeTypes, nodeComponent = () => store.nodeTypes[nodeType()], isParentNode = () => !!parentIds[node().id], transform = () => {
2134
+ let { store, nodeLookup, parentIds, actions } = useInternalSolidFlow(), [nodeRef, setNodeRef] = createSignal(), node = () => nodeLookup.get(props.nodeId);
2135
+ onCleanup(() => {
2136
+ let el = nodeRef();
2137
+ el && props.resizeObserver?.unobserve(el);
2138
+ });
2139
+ let nodeId = () => node().id, nodeType = () => node().type ?? "default", deletable = () => node().deletable ?? !0, selectable = () => node().selectable ?? store.elementsSelectable, focusable = () => node().focusable ?? store.nodesFocusable, draggable = () => node().draggable ?? store.nodesDraggable, connectable = () => node().connectable ?? store.nodesConnectable, userNode = () => node().internals.userNode, nodeTypeValid = () => nodeType() in store.nodeTypes, nodeComponent = () => store.nodeTypes[nodeType()], isParentNode = () => !!parentIds[node().id], transform = () => {
2109
2140
  let { x, y } = node().internals.positionAbsolute;
2110
2141
  return `translate(${x}px, ${y}px)`;
2111
2142
  }, sizeStyle = () => {
@@ -2688,35 +2719,53 @@ const MarkerDefinition = () => {
2688
2719
  var _tmpl$$23 = /* @__PURE__ */ template("<div class=solid-flow__edges><!><!>");
2689
2720
  /** Internal renderer iterating the edge id list into `EdgeWrapper`s. */
2690
2721
  const EdgeRenderer = (props) => {
2691
- let { store } = useInternalSolidFlow();
2722
+ let { store, actions } = useInternalSolidFlow(), [focusedEdgeId, setFocusedEdgeId] = createSignal(null), onFocusIn = (event) => {
2723
+ let edgeElement = event.target.closest("[data-id]");
2724
+ setFocusedEdgeId(edgeElement?.getAttribute("data-id") ?? null);
2725
+ };
2692
2726
  var _el$ = _tmpl$$23(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
2693
- return insert(_el$, createComponent(MarkerDefinition, {}), _el$2), insert(_el$, createComponent(For, {
2727
+ return _el$.$$focusout = () => setFocusedEdgeId(null), _el$.$$focusin = onFocusIn, insert(_el$, createComponent(MarkerDefinition, {}), _el$2), insert(_el$, createComponent(For, {
2694
2728
  get each() {
2695
2729
  return store.visibleEdgeIds;
2696
2730
  },
2697
- children: (edgeId) => createComponent(EdgeWrapper, {
2698
- edgeId,
2699
- get onEdgeClick() {
2700
- return props.onEdgeClick;
2701
- },
2702
- get onEdgeContextMenu() {
2703
- return props.onEdgeContextMenu;
2704
- },
2705
- get onEdgePointerEnter() {
2706
- return props.onEdgePointerEnter;
2707
- },
2708
- get onEdgePointerLeave() {
2709
- return props.onEdgePointerLeave;
2710
- }
2711
- })
2731
+ children: (edgeId) => {
2732
+ let unmounted = createMemo(() => {
2733
+ if (!store.onlyRenderVisibleElements || focusedEdgeId() === edgeId) return !1;
2734
+ let edge = actions.getEdge(edgeId);
2735
+ return !!edge && isEdgeCulled(edge, store.cullingViewport);
2736
+ });
2737
+ return createComponent(Show, {
2738
+ get when() {
2739
+ return !unmounted();
2740
+ },
2741
+ get children() {
2742
+ return createComponent(EdgeWrapper, {
2743
+ edgeId,
2744
+ get onEdgeClick() {
2745
+ return props.onEdgeClick;
2746
+ },
2747
+ get onEdgeContextMenu() {
2748
+ return props.onEdgeContextMenu;
2749
+ },
2750
+ get onEdgePointerEnter() {
2751
+ return props.onEdgePointerEnter;
2752
+ },
2753
+ get onEdgePointerLeave() {
2754
+ return props.onEdgePointerLeave;
2755
+ }
2756
+ });
2757
+ }
2758
+ });
2759
+ }
2712
2760
  }), _el$3), _el$;
2713
2761
  };
2762
+ delegateEvents(["focusin", "focusout"]);
2714
2763
  //#endregion
2715
2764
  //#region src/components/container/NodeRenderer.tsx
2716
2765
  var _tmpl$$22 = /* @__PURE__ */ template("<div class=\"solid-flow__container solid-flow__nodes\">");
2717
2766
  /** Internal renderer iterating the node id list into `NodeWrapper`s; owns the shared measurement `ResizeObserver`. */
2718
2767
  const NodeRenderer = (props) => {
2719
- let { actions, store } = useInternalSolidFlow(), resizeObserver = isServer ? void 0 : new ResizeObserver((entries) => {
2768
+ let { actions, store, nodeLookup } = useInternalSolidFlow(), resizeObserver = isServer ? void 0 : new ResizeObserver((entries) => {
2720
2769
  actions.requestUpdateNodeInternals(entries.map((entry) => {
2721
2770
  let id = entry.target.getAttribute("data-id");
2722
2771
  return [id, {
@@ -2729,44 +2778,63 @@ const NodeRenderer = (props) => {
2729
2778
  onCleanup(() => {
2730
2779
  resizeObserver?.disconnect();
2731
2780
  });
2781
+ let [focusedNodeId, setFocusedNodeId] = createSignal(null), onFocusIn = (event) => {
2782
+ let nodeElement = event.target.closest("[data-id]");
2783
+ setFocusedNodeId(nodeElement?.getAttribute("data-id") ?? null);
2784
+ };
2732
2785
  var _el$ = _tmpl$$22();
2733
- return insert(_el$, createComponent(For, {
2786
+ return _el$.$$focusout = () => setFocusedNodeId(null), _el$.$$focusin = onFocusIn, insert(_el$, createComponent(For, {
2734
2787
  get each() {
2735
2788
  return store.visibleNodeIds;
2736
2789
  },
2737
- children: (nodeId) => createComponent(NodeWrapper, {
2738
- nodeId,
2739
- resizeObserver,
2740
- get nodeClickDistance() {
2741
- return props.nodeClickDistance;
2742
- },
2743
- get onNodeClick() {
2744
- return props.onNodeClick;
2745
- },
2746
- get onNodePointerEnter() {
2747
- return props.onNodePointerEnter;
2748
- },
2749
- get onNodePointerMove() {
2750
- return props.onNodePointerMove;
2751
- },
2752
- get onNodePointerLeave() {
2753
- return props.onNodePointerLeave;
2754
- },
2755
- get onNodeDrag() {
2756
- return props.onNodeDrag;
2757
- },
2758
- get onNodeDragStart() {
2759
- return props.onNodeDragStart;
2760
- },
2761
- get onNodeDragStop() {
2762
- return props.onNodeDragStop;
2763
- },
2764
- get onNodeContextMenu() {
2765
- return props.onNodeContextMenu;
2766
- }
2767
- })
2790
+ children: (nodeId) => {
2791
+ let unmounted = createMemo(() => {
2792
+ if (!store.onlyRenderVisibleElements || focusedNodeId() === nodeId) return !1;
2793
+ let node = nodeLookup.get(nodeId);
2794
+ return !!node && isNodeCulled(node, store.cullingViewport);
2795
+ });
2796
+ return createComponent(Show, {
2797
+ get when() {
2798
+ return !unmounted();
2799
+ },
2800
+ get children() {
2801
+ return createComponent(NodeWrapper, {
2802
+ nodeId,
2803
+ resizeObserver,
2804
+ get nodeClickDistance() {
2805
+ return props.nodeClickDistance;
2806
+ },
2807
+ get onNodeClick() {
2808
+ return props.onNodeClick;
2809
+ },
2810
+ get onNodePointerEnter() {
2811
+ return props.onNodePointerEnter;
2812
+ },
2813
+ get onNodePointerMove() {
2814
+ return props.onNodePointerMove;
2815
+ },
2816
+ get onNodePointerLeave() {
2817
+ return props.onNodePointerLeave;
2818
+ },
2819
+ get onNodeDrag() {
2820
+ return props.onNodeDrag;
2821
+ },
2822
+ get onNodeDragStart() {
2823
+ return props.onNodeDragStart;
2824
+ },
2825
+ get onNodeDragStop() {
2826
+ return props.onNodeDragStop;
2827
+ },
2828
+ get onNodeContextMenu() {
2829
+ return props.onNodeContextMenu;
2830
+ }
2831
+ });
2832
+ }
2833
+ });
2834
+ }
2768
2835
  })), _el$;
2769
2836
  };
2837
+ delegateEvents(["focusin", "focusout"]);
2770
2838
  //#endregion
2771
2839
  //#region src/components/container/Pane.tsx
2772
2840
  var _tmpl$$21 = /* @__PURE__ */ template("<div class=\"solid-flow__container solid-flow__pane\">");
@@ -3167,25 +3235,14 @@ const Attribution = (props) => createComponent(Show, {
3167
3235
  * `const { flow, commands } = useSolidFlow()`.
3168
3236
  *
3169
3237
  * @public
3170
- * @returns the flow's read struct, write surface, and deprecated aliases
3238
+ * @returns the flow's read struct and write surface
3171
3239
  */
3172
3240
  function useSolidFlow() {
3173
- let { flow, commands, store, edgeLookup } = useInternalSolidFlow(), getInternalNode = (id) => flow.internalNodes[id];
3241
+ let { flow, commands } = useInternalSolidFlow();
3174
3242
  return {
3175
3243
  ...commands,
3176
3244
  flow,
3177
- commands,
3178
- getInternalNode,
3179
- getNode: (id) => getInternalNode(id)?.internals.userNode,
3180
- getNodes: (ids) => ids ? ids.flatMap((id) => {
3181
- let userNode = flow.internalNodes[id]?.internals.userNode;
3182
- return userNode ? [userNode] : [];
3183
- }) : [...flow.nodes],
3184
- getEdge: (id) => edgeLookup[id],
3185
- getEdges: (ids) => ids ? ids.flatMap((id) => edgeLookup[id] ? [edgeLookup[id]] : []) : [...flow.edges],
3186
- getViewport: () => snapshot(store.viewport),
3187
- getZoom: () => flow.viewport.zoom,
3188
- getHandleConnections: ({ type, id, nodeId }) => Object.values(flow.connections[connectionKey(nodeId, type, id ?? null)] ?? {})
3245
+ commands
3189
3246
  };
3190
3247
  }
3191
3248
  //#endregion
@@ -3262,7 +3319,7 @@ const KeyHandler = (props) => {
3262
3319
  }), null;
3263
3320
  };
3264
3321
  //#endregion
3265
- //#region src/components/SolidFlow/component.tsx
3322
+ //#region src/components/SolidFlow.tsx
3266
3323
  var _tmpl$$14 = /* @__PURE__ */ template("<div class=\"solid-flow__container solid-flow__viewport-back\">"), _tmpl$2 = /* @__PURE__ */ template("<div class=\"solid-flow__container solid-flow__edge-labels\">"), _tmpl$3 = /* @__PURE__ */ template("<div>");
3267
3324
  /** The flow canvas component: renders nodes and edges and wires up viewport and interactions. */
3268
3325
  const SolidFlow = (props) => {
@@ -3627,19 +3684,6 @@ function useViewport() {
3627
3684
  return () => flow.viewport;
3628
3685
  }
3629
3686
  //#endregion
3630
- //#region src/hooks/useHandleEdgeSelect.ts
3631
- /** Returns a callback applying edge-selection semantics for the given edge id. */
3632
- function useHandleEdgeSelect() {
3633
- let { store, edgeLookup, actions } = useInternalSolidFlow();
3634
- return (id) => {
3635
- let edge = edgeLookup[id];
3636
- 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({
3637
- nodes: [],
3638
- edges: [edge]
3639
- }) : actions.addSelectedEdges([id]));
3640
- };
3641
- }
3642
- //#endregion
3643
3687
  //#region src/hooks/useInitialized.ts
3644
3688
  /**
3645
3689
  * Hook for seeing if all nodes have been measured.
@@ -3669,11 +3713,16 @@ function useViewportInitialized() {
3669
3713
  //#endregion
3670
3714
  //#region src/hooks/useInternalNode.ts
3671
3715
  /**
3672
- * Hook to get an internal node by id.
3716
+ * Hook to get an internal node (the node enriched with measured dimensions,
3717
+ * absolute position, and z-order) by id.
3718
+ *
3719
+ * The id is an accessor (not a plain string) on purpose: passing a raw
3720
+ * reactive read like `props.nodeId` would capture the value once and silently
3721
+ * lose reactivity — `useInternalNode(() => props.nodeId)` keeps it live.
3673
3722
  *
3674
3723
  * @public
3675
- * @param id - the node id
3676
- * @returns an accessor with an internal node or undefined
3724
+ * @param id - a reactive accessor for the node id
3725
+ * @returns an accessor with the internal node, or undefined while absent
3677
3726
  */
3678
3727
  function useInternalNode(id) {
3679
3728
  let { flow } = useInternalSolidFlow();
@@ -3784,7 +3833,6 @@ const DEFAULT_SIZE = {
3784
3833
  let _props = propDefaults(props, {
3785
3834
  variant: "dots",
3786
3835
  gap: 20,
3787
- size: 1,
3788
3836
  lineWidth: 1,
3789
3837
  style: {}
3790
3838
  }), { 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];
@@ -4016,18 +4064,19 @@ const Unlock = () => _tmpl$$5(), Controls = (props) => {
4016
4064
  //#endregion
4017
4065
  //#region src/plugins/minimap/MiniMapNode.tsx
4018
4066
  var _tmpl$$4 = /* @__PURE__ */ template("<svg><rect></svg>", 2);
4067
+ /** The default minimap node: a rounded rect. Custom `nodeComponent`s can wrap it. */
4019
4068
  const MiniMapNode = (props) => {
4020
4069
  let _props = propDefaults(props, {
4021
4070
  borderRadius: 5,
4022
4071
  width: 0,
4023
4072
  height: 0
4024
- }), style$1 = () => Object.entries({
4025
- fill: _props.color,
4073
+ }), fill = () => _props.color ?? _props.style?.background ?? _props.style?.["background-color"], style$1 = () => Object.entries({
4074
+ fill: fill(),
4026
4075
  stroke: _props.strokeColor,
4027
4076
  "stroke-width": _props.strokeWidth
4028
4077
  }).filter(([_, value]) => value !== void 0).reduce((acc, [key, value]) => (acc[key] = value, acc), {});
4029
4078
  var _el$ = _tmpl$$4();
4030
- return effect(() => ({
4079
+ return addEvent(_el$, "click", _props.onClick ? (event) => _props.onClick(event, _props.id) : void 0, !0), effect(() => ({
4031
4080
  e: [
4032
4081
  "solid-flow__minimap-node",
4033
4082
  { selected: !!_props.selected },
@@ -4045,6 +4094,7 @@ const MiniMapNode = (props) => {
4045
4094
  className(_el$, e, _p$?.e), t !== _p$?.t && setAttribute(_el$, "x", t), a !== _p$?.a && setAttribute(_el$, "y", a), o !== _p$?.o && setAttribute(_el$, "rx", o), i !== _p$?.i && setAttribute(_el$, "ry", i), n !== _p$?.n && setAttribute(_el$, "width", n), s !== _p$?.s && setAttribute(_el$, "height", s), h !== _p$?.h && setAttribute(_el$, "shape-rendering", h), style(_el$, r, _p$?.r);
4046
4095
  }), _el$;
4047
4096
  };
4097
+ delegateEvents(["click"]);
4048
4098
  //#endregion
4049
4099
  //#region src/plugins/minimap/MiniMap.tsx
4050
4100
  var _tmpl$$3 = /* @__PURE__ */ template("<svg class=solid-flow__minimap-svg role=img><title></title><path class=solid-flow__minimap-mask fill-rule=evenodd pointer-events=none>");
@@ -4060,7 +4110,7 @@ const getAttrFunction = (func) => func instanceof Function ? func : () => func,
4060
4110
  nodeBorderRadius: 5,
4061
4111
  nodeStrokeWidth: 2,
4062
4112
  style: {}
4063
- }), 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 = () => ({
4113
+ }), paneProps = omit(_props, "class", "style", "position", "nodeClass", "nodeStrokeColor", "nodeColor", "pannable", "zoomable", "inversePan", "zoomStep", "bgColor", "width", "height", "maskColor", "maskStrokeColor", "maskStrokeWidth", "nodeBorderRadius", "nodeStrokeWidth", "nodeComponent", "onClick", "onNodeClick"), 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 = () => ({
4064
4114
  x: -store.viewport.x / store.viewport.zoom,
4065
4115
  y: -store.viewport.y / store.viewport.zoom,
4066
4116
  width: store.width / store.viewport.zoom,
@@ -4127,8 +4177,19 @@ const getAttrFunction = (func) => func instanceof Function ? func : () => func,
4127
4177
  }), ({ instance, options }) => {
4128
4178
  instance?.update(options);
4129
4179
  });
4180
+ let onSvgClick = (event) => {
4181
+ if (!_props.onClick) return;
4182
+ let [x, y] = minimap()?.pointer(event) ?? [0, 0];
4183
+ _props.onClick(event, {
4184
+ x,
4185
+ y
4186
+ });
4187
+ }, onSvgNodeClick = (event, nodeId) => {
4188
+ let node = nodeLookup.get(nodeId)?.internals.userNode;
4189
+ node && _props.onNodeClick?.(event, node);
4190
+ };
4130
4191
  var _el$ = _tmpl$$3(), _el$2 = _el$.firstChild, _el$3 = _el$2.nextSibling;
4131
- return ref(() => setRef, _el$), insert(_el$2, () => store.ariaLabelConfig["minimap.ariaLabel"]), insert(_el$, createComponent(For, {
4192
+ return addEvent(_el$, "click", _props.onClick ? onSvgClick : void 0, !0), ref(() => setRef, _el$), insert(_el$2, () => store.ariaLabelConfig["minimap.ariaLabel"]), insert(_el$, createComponent(For, {
4132
4193
  keyed: !1,
4133
4194
  get each() {
4134
4195
  return nodeIds();
@@ -4139,7 +4200,13 @@ const getAttrFunction = (func) => func instanceof Function ? func : () => func,
4139
4200
  get when() {
4140
4201
  return memo(() => !!nodeVisible())() ? getNodeDimensions(node()) : nodeVisible();
4141
4202
  },
4142
- children: (nodeDimensions) => createComponent(MiniMapNode, {
4203
+ children: (nodeDimensions) => createComponent(Dynamic, {
4204
+ get component() {
4205
+ return _props.nodeComponent ?? MiniMapNode;
4206
+ },
4207
+ get id() {
4208
+ return nodeId();
4209
+ },
4143
4210
  get x() {
4144
4211
  return node().internals.positionAbsolute.x;
4145
4212
  },
@@ -4172,6 +4239,12 @@ const getAttrFunction = (func) => func instanceof Function ? func : () => func,
4172
4239
  },
4173
4240
  get class() {
4174
4241
  return nodeClassFunc().call(null, node());
4242
+ },
4243
+ get style() {
4244
+ return node().style;
4245
+ },
4246
+ get onClick() {
4247
+ return _props.onNodeClick ? onSvgNodeClick : void 0;
4175
4248
  }
4176
4249
  })
4177
4250
  });
@@ -4194,6 +4267,7 @@ const getAttrFunction = (func) => func instanceof Function ? func : () => func,
4194
4267
  });
4195
4268
  } }));
4196
4269
  };
4270
+ delegateEvents(["click"]);
4197
4271
  //#endregion
4198
4272
  //#region src/plugins/nodeResizer/ResizeControl.tsx
4199
4273
  var _tmpl$$2 = /* @__PURE__ */ template("<div>");
@@ -4371,7 +4445,7 @@ const EdgeToolbar = (props) => {
4371
4445
  var _tmpl$ = /* @__PURE__ */ template("<div>");
4372
4446
  /** Toolbar attached to a node, rendered above the graph so it does not scale with zoom. */
4373
4447
  const NodeToolbar = (props) => {
4374
- let { store } = useInternalSolidFlow(), { getNodes, getNodesBounds, getInternalNode } = useSolidFlow(), _props = propDefaults(props, {
4448
+ let { store } = useInternalSolidFlow(), { flow, getNodesBounds } = useSolidFlow(), _props = propDefaults(props, {
4375
4449
  offset: 10,
4376
4450
  position: "top",
4377
4451
  align: "center",
@@ -4380,7 +4454,7 @@ const NodeToolbar = (props) => {
4380
4454
  let id = useContext(NodeIdContext);
4381
4455
  return id ? id() : "";
4382
4456
  }, toolbarNodes = () => (Array.isArray(_props.nodeId) ? _props.nodeId : [_props.nodeId ?? ctxNodeId()]).reduce((res, nodeId) => {
4383
- let node = getInternalNode(nodeId);
4457
+ let node = flow.internalNodes[nodeId];
4384
4458
  return node && res.push(node), res;
4385
4459
  }, []), transform = () => {
4386
4460
  let nodeRect = getNodesBounds(toolbarNodes());
@@ -4388,7 +4462,7 @@ const NodeToolbar = (props) => {
4388
4462
  }, zIndex = () => {
4389
4463
  let nodes = toolbarNodes();
4390
4464
  return nodes.length === 0 ? 1 : Math.max(...nodes.map((node) => (node.internals.z || 5) + 1));
4391
- }, selectedNodesCount = () => getNodes().filter((node) => node.selected).length, isActive = () => {
4465
+ }, selectedNodesCount = () => flow.selection.nodes.length, isActive = () => {
4392
4466
  let nodes = toolbarNodes();
4393
4467
  return typeof _props.isVisible == "boolean" ? _props.isVisible : nodes.length === 1 && !!nodes[0].selected && selectedNodesCount() === 1;
4394
4468
  }, showPortal = () => !!(store.domNode && isActive() && toolbarNodes().length > 0);
@@ -4423,4 +4497,4 @@ const NodeToolbar = (props) => {
4423
4497
  });
4424
4498
  }, SelectionMode = SelectionMode$1, getEdgeCenter = getEdgeCenter$1, getBezierEdgeCenter = getBezierEdgeCenter$1;
4425
4499
  //#endregion
4426
- export { Background, BaseEdge, BezierEdge, BezierEdgeInternal, ConnectionLine, ConnectionLineType, ConnectionMode, ControlButton, Controls, DefaultNode, EdgeLabel, EdgeLabelRenderer, EdgeReconnectAnchor, EdgeRenderer, EdgeToolbar, EdgeWrapper, GroupNode, Handle, InputNode, Marker, MarkerDefinition, MarkerType, MiniMap, NodeRenderer, NodeResizer, NodeSelection, NodeToolbar, NodeWrapper, OutputNode, PanOnScrollMode, Pane, Panel, Position, ResizeControl, ResizeControlVariant, Selection, SelectionMode, SmoothStepEdge, SmoothStepEdgeInternal, SolidFlow, SolidFlowProvider, StepEdge, StepEdgeInternal, StraightEdge, StraightEdgeInternal, Viewport, ViewportPortal, Zoom, addEdge, connectionKey, createEdgeStore, createNodeStore, getBezierEdgeCenter, getBezierPath, getConnectedEdges, getEdgeCenter, getIncomers, getNodesBounds, getOutgoers, getSmoothStepPath, getStraightPath, getViewportForBounds, useColorMode, useConnection, useEdges, useHandleEdgeSelect, useInternalNode, useNodeConnections, useNodes, useNodesData, useNodesInitialized, useSolidFlow, useUpdateNodeInternals, useViewport, useViewportInitialized };
4500
+ export { Background, BaseEdge, BezierEdge, BezierEdgeInternal, ConnectionLine, ConnectionLineType, ConnectionMode, ControlButton, Controls, DefaultNode, EdgeLabel, EdgeLabelRenderer, EdgeReconnectAnchor, EdgeRenderer, EdgeToolbar, EdgeWrapper, GroupNode, Handle, InputNode, Marker, MarkerDefinition, MarkerType, MiniMap, MiniMapNode, NodeRenderer, NodeResizer, NodeSelection, NodeToolbar, NodeWrapper, OutputNode, PanOnScrollMode, Pane, Panel, Position, ResizeControl, ResizeControlVariant, Selection, SelectionMode, SmoothStepEdge, SmoothStepEdgeInternal, SolidFlow, SolidFlowProvider, StepEdge, StepEdgeInternal, StraightEdge, StraightEdgeInternal, Viewport, ViewportPortal, Zoom, addEdge, connectionKey, createEdgeStore, createNodeStore, getBezierEdgeCenter, getBezierPath, getConnectedEdges, getEdgeCenter, getIncomers, getNodesBounds, getOutgoers, getSmoothStepPath, getStraightPath, getViewportForBounds, useColorMode, useConnection, useEdgeId, useEdges, useInternalNode, useNodeConnections, useNodeId, useNodes, useNodesData, useNodesInitialized, useSolidFlow, useUpdateNodeInternals, useViewport, useViewportInitialized };