@xyflow/react 12.4.4 → 12.5.1

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.
Files changed (86) hide show
  1. package/dist/base.css +8 -4
  2. package/dist/esm/additional-components/Background/types.d.ts +20 -4
  3. package/dist/esm/additional-components/Background/types.d.ts.map +1 -1
  4. package/dist/esm/additional-components/Controls/types.d.ts +33 -9
  5. package/dist/esm/additional-components/Controls/types.d.ts.map +1 -1
  6. package/dist/esm/additional-components/MiniMap/MiniMap.d.ts.map +1 -1
  7. package/dist/esm/additional-components/NodeToolbar/types.d.ts +8 -2
  8. package/dist/esm/additional-components/NodeToolbar/types.d.ts.map +1 -1
  9. package/dist/esm/components/EdgeLabelRenderer/index.d.ts +31 -29
  10. package/dist/esm/components/EdgeLabelRenderer/index.d.ts.map +1 -1
  11. package/dist/esm/components/Edges/BezierEdge.d.ts +26 -0
  12. package/dist/esm/components/Edges/BezierEdge.d.ts.map +1 -1
  13. package/dist/esm/components/Edges/EdgeAnchor.d.ts +3 -0
  14. package/dist/esm/components/Edges/EdgeAnchor.d.ts.map +1 -1
  15. package/dist/esm/components/Edges/EdgeText.d.ts +18 -18
  16. package/dist/esm/components/Edges/EdgeText.d.ts.map +1 -1
  17. package/dist/esm/components/Edges/SmoothStepEdge.d.ts +26 -0
  18. package/dist/esm/components/Edges/SmoothStepEdge.d.ts.map +1 -1
  19. package/dist/esm/components/Edges/StepEdge.d.ts +26 -0
  20. package/dist/esm/components/Edges/StepEdge.d.ts.map +1 -1
  21. package/dist/esm/components/Edges/StraightEdge.d.ts +24 -0
  22. package/dist/esm/components/Edges/StraightEdge.d.ts.map +1 -1
  23. package/dist/esm/container/Pane/index.d.ts.map +1 -1
  24. package/dist/esm/hooks/useKeyPress.d.ts +1 -0
  25. package/dist/esm/hooks/useKeyPress.d.ts.map +1 -1
  26. package/dist/esm/hooks/useReactFlow.d.ts.map +1 -1
  27. package/dist/esm/hooks/useViewportHelper.d.ts.map +1 -1
  28. package/dist/esm/index.d.ts +1 -1
  29. package/dist/esm/index.d.ts.map +1 -1
  30. package/dist/esm/index.js +418 -336
  31. package/dist/esm/index.mjs +418 -336
  32. package/dist/esm/store/index.d.ts +9 -9
  33. package/dist/esm/store/index.d.ts.map +1 -1
  34. package/dist/esm/store/initialState.d.ts +9 -9
  35. package/dist/esm/store/initialState.d.ts.map +1 -1
  36. package/dist/esm/types/edges.d.ts +23 -3
  37. package/dist/esm/types/edges.d.ts.map +1 -1
  38. package/dist/esm/types/general.d.ts +1 -12
  39. package/dist/esm/types/general.d.ts.map +1 -1
  40. package/dist/esm/types/instance.d.ts +2 -1
  41. package/dist/esm/types/instance.d.ts.map +1 -1
  42. package/dist/esm/types/store.d.ts +3 -5
  43. package/dist/esm/types/store.d.ts.map +1 -1
  44. package/dist/style.css +8 -4
  45. package/dist/umd/additional-components/Background/types.d.ts +20 -4
  46. package/dist/umd/additional-components/Background/types.d.ts.map +1 -1
  47. package/dist/umd/additional-components/Controls/types.d.ts +33 -9
  48. package/dist/umd/additional-components/Controls/types.d.ts.map +1 -1
  49. package/dist/umd/additional-components/MiniMap/MiniMap.d.ts.map +1 -1
  50. package/dist/umd/additional-components/NodeToolbar/types.d.ts +8 -2
  51. package/dist/umd/additional-components/NodeToolbar/types.d.ts.map +1 -1
  52. package/dist/umd/components/EdgeLabelRenderer/index.d.ts +31 -29
  53. package/dist/umd/components/EdgeLabelRenderer/index.d.ts.map +1 -1
  54. package/dist/umd/components/Edges/BezierEdge.d.ts +26 -0
  55. package/dist/umd/components/Edges/BezierEdge.d.ts.map +1 -1
  56. package/dist/umd/components/Edges/EdgeAnchor.d.ts +3 -0
  57. package/dist/umd/components/Edges/EdgeAnchor.d.ts.map +1 -1
  58. package/dist/umd/components/Edges/EdgeText.d.ts +18 -18
  59. package/dist/umd/components/Edges/EdgeText.d.ts.map +1 -1
  60. package/dist/umd/components/Edges/SmoothStepEdge.d.ts +26 -0
  61. package/dist/umd/components/Edges/SmoothStepEdge.d.ts.map +1 -1
  62. package/dist/umd/components/Edges/StepEdge.d.ts +26 -0
  63. package/dist/umd/components/Edges/StepEdge.d.ts.map +1 -1
  64. package/dist/umd/components/Edges/StraightEdge.d.ts +24 -0
  65. package/dist/umd/components/Edges/StraightEdge.d.ts.map +1 -1
  66. package/dist/umd/container/Pane/index.d.ts.map +1 -1
  67. package/dist/umd/hooks/useKeyPress.d.ts +1 -0
  68. package/dist/umd/hooks/useKeyPress.d.ts.map +1 -1
  69. package/dist/umd/hooks/useReactFlow.d.ts.map +1 -1
  70. package/dist/umd/hooks/useViewportHelper.d.ts.map +1 -1
  71. package/dist/umd/index.d.ts +1 -1
  72. package/dist/umd/index.d.ts.map +1 -1
  73. package/dist/umd/index.js +2 -2
  74. package/dist/umd/store/index.d.ts +9 -9
  75. package/dist/umd/store/index.d.ts.map +1 -1
  76. package/dist/umd/store/initialState.d.ts +9 -9
  77. package/dist/umd/store/initialState.d.ts.map +1 -1
  78. package/dist/umd/types/edges.d.ts +23 -3
  79. package/dist/umd/types/edges.d.ts.map +1 -1
  80. package/dist/umd/types/general.d.ts +1 -12
  81. package/dist/umd/types/general.d.ts.map +1 -1
  82. package/dist/umd/types/instance.d.ts +2 -1
  83. package/dist/umd/types/instance.d.ts.map +1 -1
  84. package/dist/umd/types/store.d.ts +3 -5
  85. package/dist/umd/types/store.d.ts.map +1 -1
  86. package/package.json +5 -5
@@ -2,7 +2,7 @@
2
2
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
3
  import { createContext, useContext, useMemo, forwardRef, useEffect, useRef, useState, useLayoutEffect, useCallback, memo } from 'react';
4
4
  import cc from 'classcat';
5
- import { errorMessages, infiniteExtent, isInputDOMNode, getFitViewNodes, getDimensions, fitView, getViewportForBounds, pointToRendererPoint, rendererPointToPoint, isNodeBase, isEdgeBase, getElementsToRemove, isRectObject, nodeToRect, getOverlappingArea, getNodesBounds, evaluateAbsolutePosition, XYPanZoom, PanOnScrollMode, SelectionMode, getEventPosition, getNodesInside, areSetsEqual, XYDrag, snapPosition, calculateNodePosition, Position, ConnectionMode, isMouseEvent, XYHandle, getHostForElement, addEdge, getInternalNodesBounds, isNumeric, nodeHasDimensions, getNodeDimensions, elementSelectionKeys, isEdgeVisible, MarkerType, createMarkerIds, getBezierEdgeCenter, getSmoothStepPath, getStraightPath, getBezierPath, getEdgePosition, getElevatedEdgeZIndex, getMarkerId, getConnectionStatus, ConnectionLineType, updateConnectionLookup, adoptUserNodes, initialConnection, devWarn, updateNodeInternals, updateAbsolutePositions, handleExpandParent, panBy, isMacOs, areConnectionMapsEqual, handleConnectionChange, shallowNodeData, XYMinimap, getBoundsOfRects, ResizeControlVariant, XYResizer, XY_RESIZER_LINE_POSITIONS, XY_RESIZER_HANDLE_POSITIONS, getNodeToolbarTransform } from '@xyflow/system';
5
+ import { errorMessages, infiniteExtent, isInputDOMNode, getViewportForBounds, pointToRendererPoint, rendererPointToPoint, isNodeBase, isEdgeBase, getElementsToRemove, isRectObject, nodeToRect, getOverlappingArea, getNodesBounds, evaluateAbsolutePosition, getDimensions, XYPanZoom, PanOnScrollMode, SelectionMode, getEventPosition, getNodesInside, areSetsEqual, XYDrag, snapPosition, calculateNodePosition, Position, ConnectionMode, isMouseEvent, XYHandle, getHostForElement, addEdge, getInternalNodesBounds, isNumeric, nodeHasDimensions, getNodeDimensions, elementSelectionKeys, isEdgeVisible, MarkerType, createMarkerIds, getBezierEdgeCenter, getSmoothStepPath, getStraightPath, getBezierPath, getEdgePosition, getElevatedEdgeZIndex, getMarkerId, getConnectionStatus, ConnectionLineType, updateConnectionLookup, adoptUserNodes, initialConnection, devWarn, updateNodeInternals, updateAbsolutePositions, handleExpandParent, panBy, fitViewport, isMacOs, areConnectionMapsEqual, handleConnectionChange, shallowNodeData, XYMinimap, getBoundsOfRects, ResizeControlVariant, XYResizer, XY_RESIZER_LINE_POSITIONS, XY_RESIZER_HANDLE_POSITIONS, getNodeToolbarTransform } from '@xyflow/system';
6
6
  export { ConnectionLineType, ConnectionMode, MarkerType, PanOnScrollMode, Position, ResizeControlVariant, SelectionMode, addEdge, getBezierEdgeCenter, getBezierPath, getConnectedEdges, getEdgeCenter, getIncomers, getNodesBounds, getOutgoers, getSmoothStepPath, getStraightPath, getViewportForBounds, reconnectEdge } from '@xyflow/system';
7
7
  import { useStoreWithEqualityFn, createWithEqualityFn } from 'zustand/traditional';
8
8
  import { shallow } from 'zustand/shallow';
@@ -298,9 +298,9 @@ function StoreUpdater(props) {
298
298
  setPaneClickDistance(fieldValue);
299
299
  // Renamed fields
300
300
  else if (fieldName === 'fitView')
301
- store.setState({ fitViewOnInit: fieldValue });
301
+ store.setState({ fitViewQueued: fieldValue });
302
302
  else if (fieldName === 'fitViewOptions')
303
- store.setState({ fitViewOnInitOptions: fieldValue });
303
+ store.setState({ fitViewOptions: fieldValue });
304
304
  // General case
305
305
  else
306
306
  store.setState({ [fieldName]: fieldValue });
@@ -410,7 +410,7 @@ keyCode = null, options = { target: defaultDoc, actInsideInputWithModifier: true
410
410
  const target = options?.target || defaultDoc;
411
411
  if (keyCode !== null) {
412
412
  const downHandler = (event) => {
413
- modifierPressed.current = event.ctrlKey || event.metaKey || event.shiftKey;
413
+ modifierPressed.current = event.ctrlKey || event.metaKey || event.shiftKey || event.altKey;
414
414
  const preventAction = (!modifierPressed.current || (modifierPressed.current && !options.actInsideInputWithModifier)) &&
415
415
  isInputDOMNode(event);
416
416
  if (preventAction) {
@@ -419,16 +419,15 @@ keyCode = null, options = { target: defaultDoc, actInsideInputWithModifier: true
419
419
  const keyOrCode = useKeyOrCode(event.code, keysToWatch);
420
420
  pressedKeys.current.add(event[keyOrCode]);
421
421
  if (isMatchingKey(keyCodes, pressedKeys.current, false)) {
422
- event.preventDefault();
422
+ const target = (event.composedPath?.()?.[0] || event.target);
423
+ const isInteractiveElement = target?.nodeName === 'BUTTON' || target?.nodeName === 'A';
424
+ if (options.preventDefault !== false && (modifierPressed.current || !isInteractiveElement)) {
425
+ event.preventDefault();
426
+ }
423
427
  setKeyPressed(true);
424
428
  }
425
429
  };
426
430
  const upHandler = (event) => {
427
- const preventAction = (!modifierPressed.current || (modifierPressed.current && !options.actInsideInputWithModifier)) &&
428
- isInputDOMNode(event);
429
- if (preventAction) {
430
- return false;
431
- }
432
431
  const keyOrCode = useKeyOrCode(event.code, keysToWatch);
433
432
  if (isMatchingKey(keyCodes, pressedKeys.current, true)) {
434
433
  setKeyPressed(false);
@@ -519,22 +518,6 @@ const useViewportHelper = () => {
519
518
  const [x, y, zoom] = store.getState().transform;
520
519
  return { x, y, zoom };
521
520
  },
522
- fitView: (options) => {
523
- const { nodeLookup, minZoom, maxZoom, panZoom, domNode } = store.getState();
524
- if (!panZoom || !domNode) {
525
- return Promise.resolve(false);
526
- }
527
- const fitViewNodes = getFitViewNodes(nodeLookup, options);
528
- const { width, height } = getDimensions(domNode);
529
- return fitView({
530
- nodes: fitViewNodes,
531
- width,
532
- height,
533
- minZoom,
534
- maxZoom,
535
- panZoom,
536
- }, options);
537
- },
538
521
  setCenter: async (x, y, options) => {
539
522
  const { width, height, maxZoom, panZoom } = store.getState();
540
523
  const nextZoom = typeof options?.zoom !== 'undefined' ? options.zoom : maxZoom;
@@ -1174,6 +1157,15 @@ function useReactFlow() {
1174
1157
  .getState()
1175
1158
  .connectionLookup.get(`${nodeId}${type ? (handleId ? `-${type}-${handleId}` : `-${type}`) : ''}`)
1176
1159
  ?.values() ?? []),
1160
+ fitView: async (options) => {
1161
+ // We either create a new Promise or reuse the existing one
1162
+ // Even if fitView is called multiple times in a row, we only end up with a single Promise
1163
+ const fitViewResolver = store.getState().fitViewResolver ?? Promise.withResolvers();
1164
+ // We schedule a fitView by setting fitViewQueued and triggering a setNodes
1165
+ store.setState({ fitViewQueued: true, fitViewOptions: options, fitViewResolver });
1166
+ batchContext.nodeQueue.push((nodes) => [...nodes]);
1167
+ return fitViewResolver.promise;
1168
+ },
1177
1169
  };
1178
1170
  }, []);
1179
1171
  return useMemo(() => {
@@ -1371,11 +1363,12 @@ const wrapHandler = (handler, containerRef) => {
1371
1363
  const selector$h = (s) => ({
1372
1364
  userSelectionActive: s.userSelectionActive,
1373
1365
  elementsSelectable: s.elementsSelectable,
1366
+ connectionInProgress: s.connection.inProgress,
1374
1367
  dragging: s.paneDragging,
1375
1368
  });
1376
1369
  function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.Full, panOnDrag, selectionOnDrag, onSelectionStart, onSelectionEnd, onPaneClick, onPaneContextMenu, onPaneScroll, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, children, }) {
1377
1370
  const store = useStoreApi();
1378
- const { userSelectionActive, elementsSelectable, dragging } = useStore(selector$h, shallow);
1371
+ const { userSelectionActive, elementsSelectable, dragging, connectionInProgress } = useStore(selector$h, shallow);
1379
1372
  const hasActiveSelection = elementsSelectable && (isSelecting || userSelectionActive);
1380
1373
  const container = useRef(null);
1381
1374
  const containerBounds = useRef();
@@ -1386,7 +1379,8 @@ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.
1386
1379
  const selectionStarted = useRef(false);
1387
1380
  const onClick = (event) => {
1388
1381
  // We prevent click events when the user let go of the selectionKey during a selection
1389
- if (selectionInProgress.current) {
1382
+ // We also prevent click events when a connection is in progress
1383
+ if (selectionInProgress.current || connectionInProgress) {
1390
1384
  selectionInProgress.current = false;
1391
1385
  return;
1392
1386
  }
@@ -2310,7 +2304,7 @@ const MarkerDefinitions = ({ defaultColor, rfId }) => {
2310
2304
  MarkerDefinitions.displayName = 'MarkerDefinitions';
2311
2305
  var MarkerDefinitions$1 = memo(MarkerDefinitions);
2312
2306
 
2313
- function EdgeTextComponent({ x, y, label, labelStyle = {}, labelShowBg = true, labelBgStyle = {}, labelBgPadding = [2, 4], labelBgBorderRadius = 2, children, className, ...rest }) {
2307
+ function EdgeTextComponent({ x, y, label, labelStyle, labelShowBg = true, labelBgStyle, labelBgPadding = [2, 4], labelBgBorderRadius = 2, children, className, ...rest }) {
2314
2308
  const [edgeTextBbox, setEdgeTextBbox] = useState({ x: 1, y: 0, width: 0, height: 0 });
2315
2309
  const edgeTextClasses = cc(['react-flow__edge-textwrapper', className]);
2316
2310
  const edgeTextRef = useRef(null);
@@ -2325,7 +2319,7 @@ function EdgeTextComponent({ x, y, label, labelStyle = {}, labelShowBg = true, l
2325
2319
  });
2326
2320
  }
2327
2321
  }, [label]);
2328
- if (typeof label === 'undefined' || !label) {
2322
+ if (!label) {
2329
2323
  return null;
2330
2324
  }
2331
2325
  return (jsxs("g", { transform: `translate(${x - edgeTextBbox.width / 2} ${y - edgeTextBbox.height / 2})`, className: edgeTextClasses, visibility: edgeTextBbox.width ? 'visible' : 'hidden', ...rest, children: [labelShowBg && (jsx("rect", { width: edgeTextBbox.width + 2 * labelBgPadding[0], x: -labelBgPadding[0], y: -labelBgPadding[1], height: edgeTextBbox.height + 2 * labelBgPadding[1], className: "react-flow__edge-textbg", style: labelBgStyle, rx: labelBgBorderRadius, ry: labelBgBorderRadius })), jsx("text", { className: "react-flow__edge-text", y: edgeTextBbox.height / 2, dy: "0.3em", ref: edgeTextRef, style: labelStyle, children: label }), children] }));
@@ -2335,26 +2329,26 @@ EdgeTextComponent.displayName = 'EdgeText';
2335
2329
  * You can use the `<EdgeText />` component as a helper component to display text
2336
2330
  * within your custom edges.
2337
2331
  *
2338
- *@public
2332
+ * @public
2339
2333
  *
2340
- *@example
2341
- *```jsx
2342
- *import { EdgeText } from '@xyflow/react';
2334
+ * @example
2335
+ * ```jsx
2336
+ * import { EdgeText } from '@xyflow/react';
2343
2337
  *
2344
- *export function CustomEdgeLabel({ label }) {
2345
- * return (
2346
- * <EdgeText
2347
- * x={100}
2348
- * y={100}
2349
- * label={label}
2350
- * labelStyle={{ fill: 'white' }}
2351
- * labelShowBg
2352
- * labelBgStyle={{ fill: 'red' }}
2353
- * labelBgPadding={[2, 4]}
2354
- * labelBgBorderRadius={2}
2355
- * />
2356
- * );
2357
- *}
2338
+ * export function CustomEdgeLabel({ label }) {
2339
+ * return (
2340
+ * <EdgeText
2341
+ * x={100}
2342
+ * y={100}
2343
+ * label={label}
2344
+ * labelStyle={{ fill: 'white' }}
2345
+ * labelShowBg
2346
+ * labelBgStyle={{ fill: 'red' }}
2347
+ * labelBgPadding={[2, 4]}
2348
+ * labelBgBorderRadius={2}
2349
+ * />
2350
+ * );
2351
+ * }
2358
2352
  *```
2359
2353
  */
2360
2354
  const EdgeText = memo(EdgeTextComponent);
@@ -2471,7 +2465,33 @@ function createSmoothStepEdge(params) {
2471
2465
  return (jsx(BaseEdge, { id: _id, path: path, labelX: labelX, labelY: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius, style: style, markerEnd: markerEnd, markerStart: markerStart, interactionWidth: interactionWidth }));
2472
2466
  });
2473
2467
  }
2468
+ /**
2469
+ * Component that can be used inside a custom edge to render a smooth step edge.
2470
+ *
2471
+ * @public
2472
+ * @example
2473
+ *
2474
+ * ```tsx
2475
+ * import { SmoothStepEdge } from '@xyflow/react';
2476
+ *
2477
+ * function CustomEdge({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition }) {
2478
+ * return (
2479
+ * <SmoothStepEdge
2480
+ * sourceX={sourceX}
2481
+ * sourceY={sourceY}
2482
+ * targetX={targetX}
2483
+ * targetY={targetY}
2484
+ * sourcePosition={sourcePosition}
2485
+ * targetPosition={targetPosition}
2486
+ * />
2487
+ * );
2488
+ * }
2489
+ * ```
2490
+ */
2474
2491
  const SmoothStepEdge = createSmoothStepEdge({ isInternal: false });
2492
+ /**
2493
+ * @internal
2494
+ */
2475
2495
  const SmoothStepEdgeInternal = createSmoothStepEdge({ isInternal: true });
2476
2496
  SmoothStepEdge.displayName = 'SmoothStepEdge';
2477
2497
  SmoothStepEdgeInternal.displayName = 'SmoothStepEdgeInternal';
@@ -2483,7 +2503,33 @@ function createStepEdge(params) {
2483
2503
  return (jsx(SmoothStepEdge, { ...props, id: _id, pathOptions: useMemo(() => ({ borderRadius: 0, offset: props.pathOptions?.offset }), [props.pathOptions?.offset]) }));
2484
2504
  });
2485
2505
  }
2506
+ /**
2507
+ * Component that can be used inside a custom edge to render a step edge.
2508
+ *
2509
+ * @public
2510
+ * @example
2511
+ *
2512
+ * ```tsx
2513
+ * import { StepEdge } from '@xyflow/react';
2514
+ *
2515
+ * function CustomEdge({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition }) {
2516
+ * return (
2517
+ * <StepEdge
2518
+ * sourceX={sourceX}
2519
+ * sourceY={sourceY}
2520
+ * targetX={targetX}
2521
+ * targetY={targetY}
2522
+ * sourcePosition={sourcePosition}
2523
+ * targetPosition={targetPosition}
2524
+ * />
2525
+ * );
2526
+ * }
2527
+ * ```
2528
+ */
2486
2529
  const StepEdge = createStepEdge({ isInternal: false });
2530
+ /**
2531
+ * @internal
2532
+ */
2487
2533
  const StepEdgeInternal = createStepEdge({ isInternal: true });
2488
2534
  StepEdge.displayName = 'StepEdge';
2489
2535
  StepEdgeInternal.displayName = 'StepEdgeInternal';
@@ -2496,7 +2542,31 @@ function createStraightEdge(params) {
2496
2542
  return (jsx(BaseEdge, { id: _id, path: path, labelX: labelX, labelY: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius, style: style, markerEnd: markerEnd, markerStart: markerStart, interactionWidth: interactionWidth }));
2497
2543
  });
2498
2544
  }
2545
+ /**
2546
+ * Component that can be used inside a custom edge to render a straight line.
2547
+ *
2548
+ * @public
2549
+ * @example
2550
+ *
2551
+ * ```tsx
2552
+ * import { StraightEdge } from '@xyflow/react';
2553
+ *
2554
+ * function CustomEdge({ sourceX, sourceY, targetX, targetY }) {
2555
+ * return (
2556
+ * <StraightEdge
2557
+ * sourceX={sourceX}
2558
+ * sourceY={sourceY}
2559
+ * targetX={targetX}
2560
+ * targetY={targetY}
2561
+ * />
2562
+ * );
2563
+ * }
2564
+ * ```
2565
+ */
2499
2566
  const StraightEdge = createStraightEdge({ isInternal: false });
2567
+ /**
2568
+ * @internal
2569
+ */
2500
2570
  const StraightEdgeInternal = createStraightEdge({ isInternal: true });
2501
2571
  StraightEdge.displayName = 'StraightEdge';
2502
2572
  StraightEdgeInternal.displayName = 'StraightEdgeInternal';
@@ -2517,7 +2587,33 @@ function createBezierEdge(params) {
2517
2587
  return (jsx(BaseEdge, { id: _id, path: path, labelX: labelX, labelY: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius, style: style, markerEnd: markerEnd, markerStart: markerStart, interactionWidth: interactionWidth }));
2518
2588
  });
2519
2589
  }
2590
+ /**
2591
+ * Component that can be used inside a custom edge to render a bezier curve.
2592
+ *
2593
+ * @public
2594
+ * @example
2595
+ *
2596
+ * ```tsx
2597
+ * import { BezierEdge } from '@xyflow/react';
2598
+ *
2599
+ * function CustomEdge({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition }) {
2600
+ * return (
2601
+ * <BezierEdge
2602
+ * sourceX={sourceX}
2603
+ * sourceY={sourceY}
2604
+ * targetX={targetX}
2605
+ * targetY={targetY}
2606
+ * sourcePosition={sourcePosition}
2607
+ * targetPosition={targetPosition}
2608
+ * />
2609
+ * );
2610
+ * }
2611
+ * ```
2612
+ */
2520
2613
  const BezierEdge = createBezierEdge({ isInternal: false });
2614
+ /**
2615
+ * @internal
2616
+ */
2521
2617
  const BezierEdgeInternal = createBezierEdge({ isInternal: true });
2522
2618
  BezierEdge.displayName = 'BezierEdge';
2523
2619
  BezierEdgeInternal.displayName = 'BezierEdgeInternal';
@@ -2553,6 +2649,9 @@ const shiftY = (y, shift, position) => {
2553
2649
  return y;
2554
2650
  };
2555
2651
  const EdgeUpdaterClassName = 'react-flow__edgeupdater';
2652
+ /**
2653
+ * @internal
2654
+ */
2556
2655
  function EdgeAnchor({ position, centerX, centerY, radius = 10, onMouseDown, onMouseEnter, onMouseOut, type, }) {
2557
2656
  return (jsx("circle", { onMouseDown: onMouseDown, onMouseEnter: onMouseEnter, onMouseOut: onMouseOut, className: cc([EdgeUpdaterClassName, `${EdgeUpdaterClassName}-${type}`]), cx: shiftX(centerX, radius, position), cy: shiftY(centerY, radius, position), r: radius, stroke: "transparent", fill: "transparent" }));
2558
2657
  }
@@ -2993,11 +3092,11 @@ const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, heig
2993
3092
  elementsSelectable: true,
2994
3093
  elevateNodesOnSelect: true,
2995
3094
  elevateEdgesOnSelect: false,
2996
- fitViewOnInit: false,
2997
- fitViewDone: false,
2998
- fitViewOnInitOptions: undefined,
2999
3095
  selectNodesOnDrag: true,
3000
3096
  multiSelectionActive: false,
3097
+ fitViewQueued: fitView ?? false,
3098
+ fitViewOptions: undefined,
3099
+ fitViewResolver: null,
3001
3100
  connection: { ...initialConnection },
3002
3101
  connectionClickStartHandle: null,
3003
3102
  connectOnClick: true,
@@ -3014,277 +3113,256 @@ const getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, heig
3014
3113
  };
3015
3114
  };
3016
3115
 
3017
- const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height, fitView: fitView$1, nodeOrigin, nodeExtent, }) => createWithEqualityFn((set, get) => ({
3018
- ...getInitialState({ nodes, edges, width, height, fitView: fitView$1, nodeOrigin, nodeExtent, defaultNodes, defaultEdges }),
3019
- setNodes: (nodes) => {
3020
- const { nodeLookup, parentLookup, nodeOrigin, elevateNodesOnSelect } = get();
3021
- /*
3022
- * setNodes() is called exclusively in response to user actions:
3023
- * - either when the `<ReactFlow nodes>` prop is updated in the controlled ReactFlow setup,
3024
- * - or when the user calls something like `reactFlowInstance.setNodes()` in an uncontrolled ReactFlow setup.
3025
- *
3026
- * When this happens, we take the note objects passed by the user and extend them with fields
3027
- * relevant for internal React Flow operations.
3028
- */
3029
- adoptUserNodes(nodes, nodeLookup, parentLookup, {
3030
- nodeOrigin,
3031
- nodeExtent,
3032
- elevateNodesOnSelect,
3033
- checkEquality: true,
3034
- });
3035
- set({ nodes });
3036
- },
3037
- setEdges: (edges) => {
3038
- const { connectionLookup, edgeLookup } = get();
3039
- updateConnectionLookup(connectionLookup, edgeLookup, edges);
3040
- set({ edges });
3041
- },
3042
- setDefaultNodesAndEdges: (nodes, edges) => {
3043
- if (nodes) {
3044
- const { setNodes } = get();
3045
- setNodes(nodes);
3046
- set({ hasDefaultNodes: true });
3047
- }
3048
- if (edges) {
3049
- const { setEdges } = get();
3050
- setEdges(edges);
3051
- set({ hasDefaultEdges: true });
3052
- }
3053
- },
3054
- /*
3055
- * Every node gets registerd at a ResizeObserver. Whenever a node
3056
- * changes its dimensions, this function is called to measure the
3057
- * new dimensions and update the nodes.
3058
- */
3059
- updateNodeInternals: (updates, params = { triggerFitView: true }) => {
3060
- const { triggerNodeChanges, nodeLookup, parentLookup, fitViewOnInit, fitViewDone, fitViewOnInitOptions, domNode, nodeOrigin, nodeExtent, debug, fitViewSync, } = get();
3061
- const { changes, updatedInternals } = updateNodeInternals(updates, nodeLookup, parentLookup, domNode, nodeOrigin, nodeExtent);
3062
- if (!updatedInternals) {
3116
+ const createStore = ({ nodes, edges, defaultNodes, defaultEdges, width, height, fitView, nodeOrigin, nodeExtent, }) => createWithEqualityFn((set, get) => {
3117
+ async function resolveFitView() {
3118
+ const { nodeLookup, panZoom, fitViewOptions, fitViewResolver, width, height, minZoom, maxZoom } = get();
3119
+ if (!panZoom) {
3063
3120
  return;
3064
3121
  }
3065
- updateAbsolutePositions(nodeLookup, parentLookup, { nodeOrigin, nodeExtent });
3066
- if (params.triggerFitView) {
3067
- // we call fitView once initially after all dimensions are set
3068
- let nextFitViewDone = fitViewDone;
3069
- if (!fitViewDone && fitViewOnInit) {
3070
- nextFitViewDone = fitViewSync({
3071
- ...fitViewOnInitOptions,
3072
- nodes: fitViewOnInitOptions?.nodes,
3073
- });
3074
- }
3122
+ await fitViewport({
3123
+ nodes: nodeLookup,
3124
+ width,
3125
+ height,
3126
+ panZoom,
3127
+ minZoom,
3128
+ maxZoom,
3129
+ }, fitViewOptions);
3130
+ fitViewResolver?.resolve(true);
3131
+ /**
3132
+ * wait for the fitViewport to resolve before deleting the resolver,
3133
+ * we want to reuse the old resolver if the user calls fitView again in the mean time
3134
+ */
3135
+ set({ fitViewResolver: null });
3136
+ }
3137
+ return {
3138
+ ...getInitialState({ nodes, edges, width, height, fitView, nodeOrigin, nodeExtent, defaultNodes, defaultEdges }),
3139
+ setNodes: (nodes) => {
3140
+ const { nodeLookup, parentLookup, nodeOrigin, elevateNodesOnSelect, fitViewQueued } = get();
3075
3141
  /*
3076
- * here we are cirmumventing the onNodesChange handler
3077
- * in order to be able to display nodes even if the user
3078
- * has not provided an onNodesChange handler.
3079
- * Nodes are only rendered if they have a width and height
3080
- * attribute which they get from this handler.
3142
+ * setNodes() is called exclusively in response to user actions:
3143
+ * - either when the `<ReactFlow nodes>` prop is updated in the controlled ReactFlow setup,
3144
+ * - or when the user calls something like `reactFlowInstance.setNodes()` in an uncontrolled ReactFlow setup.
3145
+ *
3146
+ * When this happens, we take the note objects passed by the user and extend them with fields
3147
+ * relevant for internal React Flow operations.
3081
3148
  */
3082
- set({ fitViewDone: nextFitViewDone });
3083
- }
3084
- else {
3085
- // we always want to trigger useStore calls whenever updateNodeInternals is called
3086
- set({});
3087
- }
3088
- if (changes?.length > 0) {
3089
- if (debug) {
3090
- console.log('React Flow: trigger node changes', changes);
3149
+ const nodesInitialized = adoptUserNodes(nodes, nodeLookup, parentLookup, {
3150
+ nodeOrigin,
3151
+ nodeExtent,
3152
+ elevateNodesOnSelect,
3153
+ checkEquality: true,
3154
+ });
3155
+ if (fitViewQueued && nodesInitialized) {
3156
+ resolveFitView();
3157
+ set({ nodes, fitViewQueued: false, fitViewOptions: undefined });
3091
3158
  }
3092
- triggerNodeChanges?.(changes);
3093
- }
3094
- },
3095
- updateNodePositions: (nodeDragItems, dragging = false) => {
3096
- const parentExpandChildren = [];
3097
- const changes = [];
3098
- const { nodeLookup, triggerNodeChanges } = get();
3099
- for (const [id, dragItem] of nodeDragItems) {
3100
- // we are using the nodelookup to be sure to use the current expandParent and parentId value
3101
- const node = nodeLookup.get(id);
3102
- const expandParent = !!(node?.expandParent && node?.parentId && dragItem?.position);
3103
- const change = {
3104
- id,
3105
- type: 'position',
3106
- position: expandParent
3107
- ? {
3108
- x: Math.max(0, dragItem.position.x),
3109
- y: Math.max(0, dragItem.position.y),
3110
- }
3111
- : dragItem.position,
3112
- dragging,
3113
- };
3114
- if (expandParent && node.parentId) {
3115
- parentExpandChildren.push({
3159
+ else {
3160
+ set({ nodes });
3161
+ }
3162
+ },
3163
+ setEdges: (edges) => {
3164
+ const { connectionLookup, edgeLookup } = get();
3165
+ updateConnectionLookup(connectionLookup, edgeLookup, edges);
3166
+ set({ edges });
3167
+ },
3168
+ setDefaultNodesAndEdges: (nodes, edges) => {
3169
+ if (nodes) {
3170
+ const { setNodes } = get();
3171
+ setNodes(nodes);
3172
+ set({ hasDefaultNodes: true });
3173
+ }
3174
+ if (edges) {
3175
+ const { setEdges } = get();
3176
+ setEdges(edges);
3177
+ set({ hasDefaultEdges: true });
3178
+ }
3179
+ },
3180
+ /*
3181
+ * Every node gets registerd at a ResizeObserver. Whenever a node
3182
+ * changes its dimensions, this function is called to measure the
3183
+ * new dimensions and update the nodes.
3184
+ */
3185
+ updateNodeInternals: (updates) => {
3186
+ const { triggerNodeChanges, nodeLookup, parentLookup, domNode, nodeOrigin, nodeExtent, debug, fitViewQueued } = get();
3187
+ const { changes, updatedInternals } = updateNodeInternals(updates, nodeLookup, parentLookup, domNode, nodeOrigin, nodeExtent);
3188
+ if (!updatedInternals) {
3189
+ return;
3190
+ }
3191
+ updateAbsolutePositions(nodeLookup, parentLookup, { nodeOrigin, nodeExtent });
3192
+ if (fitViewQueued) {
3193
+ resolveFitView();
3194
+ set({ fitViewQueued: false, fitViewOptions: undefined });
3195
+ }
3196
+ else {
3197
+ // we always want to trigger useStore calls whenever updateNodeInternals is called
3198
+ set({});
3199
+ }
3200
+ if (changes?.length > 0) {
3201
+ if (debug) {
3202
+ console.log('React Flow: trigger node changes', changes);
3203
+ }
3204
+ triggerNodeChanges?.(changes);
3205
+ }
3206
+ },
3207
+ updateNodePositions: (nodeDragItems, dragging = false) => {
3208
+ const parentExpandChildren = [];
3209
+ const changes = [];
3210
+ const { nodeLookup, triggerNodeChanges } = get();
3211
+ for (const [id, dragItem] of nodeDragItems) {
3212
+ // we are using the nodelookup to be sure to use the current expandParent and parentId value
3213
+ const node = nodeLookup.get(id);
3214
+ const expandParent = !!(node?.expandParent && node?.parentId && dragItem?.position);
3215
+ const change = {
3116
3216
  id,
3117
- parentId: node.parentId,
3118
- rect: {
3119
- ...dragItem.internals.positionAbsolute,
3120
- width: dragItem.measured.width ?? 0,
3121
- height: dragItem.measured.height ?? 0,
3122
- },
3123
- });
3217
+ type: 'position',
3218
+ position: expandParent
3219
+ ? {
3220
+ x: Math.max(0, dragItem.position.x),
3221
+ y: Math.max(0, dragItem.position.y),
3222
+ }
3223
+ : dragItem.position,
3224
+ dragging,
3225
+ };
3226
+ if (expandParent && node.parentId) {
3227
+ parentExpandChildren.push({
3228
+ id,
3229
+ parentId: node.parentId,
3230
+ rect: {
3231
+ ...dragItem.internals.positionAbsolute,
3232
+ width: dragItem.measured.width ?? 0,
3233
+ height: dragItem.measured.height ?? 0,
3234
+ },
3235
+ });
3236
+ }
3237
+ changes.push(change);
3124
3238
  }
3125
- changes.push(change);
3126
- }
3127
- if (parentExpandChildren.length > 0) {
3128
- const { parentLookup, nodeOrigin } = get();
3129
- const parentExpandChanges = handleExpandParent(parentExpandChildren, nodeLookup, parentLookup, nodeOrigin);
3130
- changes.push(...parentExpandChanges);
3131
- }
3132
- triggerNodeChanges(changes);
3133
- },
3134
- triggerNodeChanges: (changes) => {
3135
- const { onNodesChange, setNodes, nodes, hasDefaultNodes, debug } = get();
3136
- if (changes?.length) {
3137
- if (hasDefaultNodes) {
3138
- const updatedNodes = applyNodeChanges(changes, nodes);
3139
- setNodes(updatedNodes);
3239
+ if (parentExpandChildren.length > 0) {
3240
+ const { parentLookup, nodeOrigin } = get();
3241
+ const parentExpandChanges = handleExpandParent(parentExpandChildren, nodeLookup, parentLookup, nodeOrigin);
3242
+ changes.push(...parentExpandChanges);
3140
3243
  }
3141
- if (debug) {
3142
- console.log('React Flow: trigger node changes', changes);
3244
+ triggerNodeChanges(changes);
3245
+ },
3246
+ triggerNodeChanges: (changes) => {
3247
+ const { onNodesChange, setNodes, nodes, hasDefaultNodes, debug } = get();
3248
+ if (changes?.length) {
3249
+ if (hasDefaultNodes) {
3250
+ const updatedNodes = applyNodeChanges(changes, nodes);
3251
+ setNodes(updatedNodes);
3252
+ }
3253
+ if (debug) {
3254
+ console.log('React Flow: trigger node changes', changes);
3255
+ }
3256
+ onNodesChange?.(changes);
3143
3257
  }
3144
- onNodesChange?.(changes);
3145
- }
3146
- },
3147
- triggerEdgeChanges: (changes) => {
3148
- const { onEdgesChange, setEdges, edges, hasDefaultEdges, debug } = get();
3149
- if (changes?.length) {
3150
- if (hasDefaultEdges) {
3151
- const updatedEdges = applyEdgeChanges(changes, edges);
3152
- setEdges(updatedEdges);
3258
+ },
3259
+ triggerEdgeChanges: (changes) => {
3260
+ const { onEdgesChange, setEdges, edges, hasDefaultEdges, debug } = get();
3261
+ if (changes?.length) {
3262
+ if (hasDefaultEdges) {
3263
+ const updatedEdges = applyEdgeChanges(changes, edges);
3264
+ setEdges(updatedEdges);
3265
+ }
3266
+ if (debug) {
3267
+ console.log('React Flow: trigger edge changes', changes);
3268
+ }
3269
+ onEdgesChange?.(changes);
3153
3270
  }
3154
- if (debug) {
3155
- console.log('React Flow: trigger edge changes', changes);
3271
+ },
3272
+ addSelectedNodes: (selectedNodeIds) => {
3273
+ const { multiSelectionActive, edgeLookup, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = get();
3274
+ if (multiSelectionActive) {
3275
+ const nodeChanges = selectedNodeIds.map((nodeId) => createSelectionChange(nodeId, true));
3276
+ triggerNodeChanges(nodeChanges);
3277
+ return;
3156
3278
  }
3157
- onEdgesChange?.(changes);
3158
- }
3159
- },
3160
- addSelectedNodes: (selectedNodeIds) => {
3161
- const { multiSelectionActive, edgeLookup, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = get();
3162
- if (multiSelectionActive) {
3163
- const nodeChanges = selectedNodeIds.map((nodeId) => createSelectionChange(nodeId, true));
3279
+ triggerNodeChanges(getSelectionChanges(nodeLookup, new Set([...selectedNodeIds]), true));
3280
+ triggerEdgeChanges(getSelectionChanges(edgeLookup));
3281
+ },
3282
+ addSelectedEdges: (selectedEdgeIds) => {
3283
+ const { multiSelectionActive, edgeLookup, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = get();
3284
+ if (multiSelectionActive) {
3285
+ const changedEdges = selectedEdgeIds.map((edgeId) => createSelectionChange(edgeId, true));
3286
+ triggerEdgeChanges(changedEdges);
3287
+ return;
3288
+ }
3289
+ triggerEdgeChanges(getSelectionChanges(edgeLookup, new Set([...selectedEdgeIds])));
3290
+ triggerNodeChanges(getSelectionChanges(nodeLookup, new Set(), true));
3291
+ },
3292
+ unselectNodesAndEdges: ({ nodes, edges } = {}) => {
3293
+ const { edges: storeEdges, nodes: storeNodes, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = get();
3294
+ const nodesToUnselect = nodes ? nodes : storeNodes;
3295
+ const edgesToUnselect = edges ? edges : storeEdges;
3296
+ const nodeChanges = nodesToUnselect.map((n) => {
3297
+ const internalNode = nodeLookup.get(n.id);
3298
+ if (internalNode) {
3299
+ /*
3300
+ * we need to unselect the internal node that was selected previously before we
3301
+ * send the change to the user to prevent it to be selected while dragging the new node
3302
+ */
3303
+ internalNode.selected = false;
3304
+ }
3305
+ return createSelectionChange(n.id, false);
3306
+ });
3307
+ const edgeChanges = edgesToUnselect.map((edge) => createSelectionChange(edge.id, false));
3164
3308
  triggerNodeChanges(nodeChanges);
3165
- return;
3166
- }
3167
- triggerNodeChanges(getSelectionChanges(nodeLookup, new Set([...selectedNodeIds]), true));
3168
- triggerEdgeChanges(getSelectionChanges(edgeLookup));
3169
- },
3170
- addSelectedEdges: (selectedEdgeIds) => {
3171
- const { multiSelectionActive, edgeLookup, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = get();
3172
- if (multiSelectionActive) {
3173
- const changedEdges = selectedEdgeIds.map((edgeId) => createSelectionChange(edgeId, true));
3174
- triggerEdgeChanges(changedEdges);
3175
- return;
3176
- }
3177
- triggerEdgeChanges(getSelectionChanges(edgeLookup, new Set([...selectedEdgeIds])));
3178
- triggerNodeChanges(getSelectionChanges(nodeLookup, new Set(), true));
3179
- },
3180
- unselectNodesAndEdges: ({ nodes, edges } = {}) => {
3181
- const { edges: storeEdges, nodes: storeNodes, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = get();
3182
- const nodesToUnselect = nodes ? nodes : storeNodes;
3183
- const edgesToUnselect = edges ? edges : storeEdges;
3184
- const nodeChanges = nodesToUnselect.map((n) => {
3185
- const internalNode = nodeLookup.get(n.id);
3186
- if (internalNode) {
3187
- /*
3188
- * we need to unselect the internal node that was selected previously before we
3189
- * send the change to the user to prevent it to be selected while dragging the new node
3190
- */
3191
- internalNode.selected = false;
3309
+ triggerEdgeChanges(edgeChanges);
3310
+ },
3311
+ setMinZoom: (minZoom) => {
3312
+ const { panZoom, maxZoom } = get();
3313
+ panZoom?.setScaleExtent([minZoom, maxZoom]);
3314
+ set({ minZoom });
3315
+ },
3316
+ setMaxZoom: (maxZoom) => {
3317
+ const { panZoom, minZoom } = get();
3318
+ panZoom?.setScaleExtent([minZoom, maxZoom]);
3319
+ set({ maxZoom });
3320
+ },
3321
+ setTranslateExtent: (translateExtent) => {
3322
+ get().panZoom?.setTranslateExtent(translateExtent);
3323
+ set({ translateExtent });
3324
+ },
3325
+ setPaneClickDistance: (clickDistance) => {
3326
+ get().panZoom?.setClickDistance(clickDistance);
3327
+ },
3328
+ resetSelectedElements: () => {
3329
+ const { edges, nodes, triggerNodeChanges, triggerEdgeChanges } = get();
3330
+ const nodeChanges = nodes.reduce((res, node) => (node.selected ? [...res, createSelectionChange(node.id, false)] : res), []);
3331
+ const edgeChanges = edges.reduce((res, edge) => (edge.selected ? [...res, createSelectionChange(edge.id, false)] : res), []);
3332
+ triggerNodeChanges(nodeChanges);
3333
+ triggerEdgeChanges(edgeChanges);
3334
+ },
3335
+ setNodeExtent: (nextNodeExtent) => {
3336
+ const { nodes, nodeLookup, parentLookup, nodeOrigin, elevateNodesOnSelect, nodeExtent } = get();
3337
+ if (nextNodeExtent[0][0] === nodeExtent[0][0] &&
3338
+ nextNodeExtent[0][1] === nodeExtent[0][1] &&
3339
+ nextNodeExtent[1][0] === nodeExtent[1][0] &&
3340
+ nextNodeExtent[1][1] === nodeExtent[1][1]) {
3341
+ return;
3192
3342
  }
3193
- return createSelectionChange(n.id, false);
3194
- });
3195
- const edgeChanges = edgesToUnselect.map((edge) => createSelectionChange(edge.id, false));
3196
- triggerNodeChanges(nodeChanges);
3197
- triggerEdgeChanges(edgeChanges);
3198
- },
3199
- setMinZoom: (minZoom) => {
3200
- const { panZoom, maxZoom } = get();
3201
- panZoom?.setScaleExtent([minZoom, maxZoom]);
3202
- set({ minZoom });
3203
- },
3204
- setMaxZoom: (maxZoom) => {
3205
- const { panZoom, minZoom } = get();
3206
- panZoom?.setScaleExtent([minZoom, maxZoom]);
3207
- set({ maxZoom });
3208
- },
3209
- setTranslateExtent: (translateExtent) => {
3210
- get().panZoom?.setTranslateExtent(translateExtent);
3211
- set({ translateExtent });
3212
- },
3213
- setPaneClickDistance: (clickDistance) => {
3214
- get().panZoom?.setClickDistance(clickDistance);
3215
- },
3216
- resetSelectedElements: () => {
3217
- const { edges, nodes, triggerNodeChanges, triggerEdgeChanges } = get();
3218
- const nodeChanges = nodes.reduce((res, node) => (node.selected ? [...res, createSelectionChange(node.id, false)] : res), []);
3219
- const edgeChanges = edges.reduce((res, edge) => (edge.selected ? [...res, createSelectionChange(edge.id, false)] : res), []);
3220
- triggerNodeChanges(nodeChanges);
3221
- triggerEdgeChanges(edgeChanges);
3222
- },
3223
- setNodeExtent: (nextNodeExtent) => {
3224
- const { nodes, nodeLookup, parentLookup, nodeOrigin, elevateNodesOnSelect, nodeExtent } = get();
3225
- if (nextNodeExtent[0][0] === nodeExtent[0][0] &&
3226
- nextNodeExtent[0][1] === nodeExtent[0][1] &&
3227
- nextNodeExtent[1][0] === nodeExtent[1][0] &&
3228
- nextNodeExtent[1][1] === nodeExtent[1][1]) {
3229
- return;
3230
- }
3231
- adoptUserNodes(nodes, nodeLookup, parentLookup, {
3232
- nodeOrigin,
3233
- nodeExtent: nextNodeExtent,
3234
- elevateNodesOnSelect,
3235
- checkEquality: false,
3236
- });
3237
- set({ nodeExtent: nextNodeExtent });
3238
- },
3239
- panBy: (delta) => {
3240
- const { transform, width, height, panZoom, translateExtent } = get();
3241
- return panBy({ delta, panZoom, transform, translateExtent, width, height });
3242
- },
3243
- fitView: (options) => {
3244
- const { panZoom, width, height, minZoom, maxZoom, nodeLookup } = get();
3245
- if (!panZoom) {
3246
- return Promise.resolve(false);
3247
- }
3248
- const fitViewNodes = getFitViewNodes(nodeLookup, options);
3249
- return fitView({
3250
- nodes: fitViewNodes,
3251
- width,
3252
- height,
3253
- panZoom,
3254
- minZoom,
3255
- maxZoom,
3256
- }, options);
3257
- },
3258
- /*
3259
- * we can't call an asnychronous function in updateNodeInternals
3260
- * for that we created this sync version of fitView
3261
- */
3262
- fitViewSync: (options) => {
3263
- const { panZoom, width, height, minZoom, maxZoom, nodeLookup } = get();
3264
- if (!panZoom) {
3265
- return false;
3266
- }
3267
- const fitViewNodes = getFitViewNodes(nodeLookup, options);
3268
- fitView({
3269
- nodes: fitViewNodes,
3270
- width,
3271
- height,
3272
- panZoom,
3273
- minZoom,
3274
- maxZoom,
3275
- }, options);
3276
- return fitViewNodes.size > 0;
3277
- },
3278
- cancelConnection: () => {
3279
- set({
3280
- connection: { ...initialConnection },
3281
- });
3282
- },
3283
- updateConnection: (connection) => {
3284
- set({ connection });
3285
- },
3286
- reset: () => set({ ...getInitialState() }),
3287
- }), Object.is);
3343
+ adoptUserNodes(nodes, nodeLookup, parentLookup, {
3344
+ nodeOrigin,
3345
+ nodeExtent: nextNodeExtent,
3346
+ elevateNodesOnSelect,
3347
+ checkEquality: false,
3348
+ });
3349
+ set({ nodeExtent: nextNodeExtent });
3350
+ },
3351
+ panBy: (delta) => {
3352
+ const { transform, width, height, panZoom, translateExtent } = get();
3353
+ return panBy({ delta, panZoom, transform, translateExtent, width, height });
3354
+ },
3355
+ cancelConnection: () => {
3356
+ set({
3357
+ connection: { ...initialConnection },
3358
+ });
3359
+ },
3360
+ updateConnection: (connection) => {
3361
+ set({ connection });
3362
+ },
3363
+ reset: () => set({ ...getInitialState() }),
3364
+ };
3365
+ }, Object.is);
3288
3366
 
3289
3367
  /**
3290
3368
  * The `<ReactFlowProvider />` component is a [context provider](https://react.dev/learn/passing-data-deeply-with-context#)
@@ -3391,37 +3469,38 @@ const selector$6 = (s) => s.domNode?.querySelector('.react-flow__edgelabel-rende
3391
3469
  * Edges are SVG-based. If you want to render more complex labels you can use the
3392
3470
  * `<EdgeLabelRenderer />` component to access a div based renderer. This component
3393
3471
  * is a portal that renders the label in a `<div />` that is positioned on top of
3394
- * the edges. You can see an example usage of the component in the [edge label renderer](/examples/edges/edge-label-renderer) example.
3472
+ * the edges. You can see an example usage of the component in the
3473
+ * [edge label renderer example](/examples/edges/edge-label-renderer).
3395
3474
  * @public
3396
3475
  *
3397
3476
  * @example
3398
- *```jsx
3399
- *import React from 'react';
3400
- *import { getBezierPath, EdgeLabelRenderer, BaseEdge } from '@xyflow/react';
3477
+ * ```jsx
3478
+ * import React from 'react';
3479
+ * import { getBezierPath, EdgeLabelRenderer, BaseEdge } from '@xyflow/react';
3401
3480
  *
3402
- *export function CustomEdge({ id, data, ...props }) {
3403
- * const [edgePath, labelX, labelY] = getBezierPath(props);
3481
+ * export function CustomEdge({ id, data, ...props }) {
3482
+ * const [edgePath, labelX, labelY] = getBezierPath(props);
3404
3483
  *
3405
- * return (
3406
- * <>
3407
- * <BaseEdge id={id} path={edgePath} />
3408
- * <EdgeLabelRenderer>
3409
- * <div
3410
- * style={{
3411
- * position: 'absolute',
3412
- * transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
3413
- * background: '#ffcc00',
3414
- * padding: 10,
3415
- * }}
3416
- * className="nodrag nopan"
3417
- * >
3418
- * {data.label}
3419
- * </div>
3420
- * </EdgeLabelRenderer>
3421
- * </>
3422
- * );
3423
- *};
3424
- *```
3484
+ * return (
3485
+ * <>
3486
+ * <BaseEdge id={id} path={edgePath} />
3487
+ * <EdgeLabelRenderer>
3488
+ * <div
3489
+ * style={{
3490
+ * position: 'absolute',
3491
+ * transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
3492
+ * background: '#ffcc00',
3493
+ * padding: 10,
3494
+ * }}
3495
+ * className="nodrag nopan"
3496
+ * >
3497
+ * {data.label}
3498
+ * </div>
3499
+ * </EdgeLabelRenderer>
3500
+ * </>
3501
+ * );
3502
+ * };
3503
+ * ```
3425
3504
  *
3426
3505
  * @remarks The `<EdgeLabelRenderer />` has no pointer events by default. If you want to
3427
3506
  * add mouse interactions you need to set the style `pointerEvents: all` and add
@@ -4244,6 +4323,7 @@ var MiniMapNodes$1 = memo(MiniMapNodes);
4244
4323
 
4245
4324
  const defaultWidth = 200;
4246
4325
  const defaultHeight = 150;
4326
+ const filterHidden = (node) => !node.hidden;
4247
4327
  const selector$1 = (s) => {
4248
4328
  const viewBB = {
4249
4329
  x: -s.transform[0] / s.transform[2],
@@ -4253,7 +4333,9 @@ const selector$1 = (s) => {
4253
4333
  };
4254
4334
  return {
4255
4335
  viewBB,
4256
- boundingRect: s.nodeLookup.size > 0 ? getBoundsOfRects(getInternalNodesBounds(s.nodeLookup), viewBB) : viewBB,
4336
+ boundingRect: s.nodeLookup.size > 0
4337
+ ? getBoundsOfRects(getInternalNodesBounds(s.nodeLookup, { filter: filterHidden }), viewBB)
4338
+ : viewBB,
4257
4339
  rfId: s.rfId,
4258
4340
  panZoom: s.panZoom,
4259
4341
  translateExtent: s.translateExtent,