@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.
- package/dist/base.css +8 -4
- package/dist/esm/additional-components/Background/types.d.ts +20 -4
- package/dist/esm/additional-components/Background/types.d.ts.map +1 -1
- package/dist/esm/additional-components/Controls/types.d.ts +33 -9
- package/dist/esm/additional-components/Controls/types.d.ts.map +1 -1
- package/dist/esm/additional-components/MiniMap/MiniMap.d.ts.map +1 -1
- package/dist/esm/additional-components/NodeToolbar/types.d.ts +8 -2
- package/dist/esm/additional-components/NodeToolbar/types.d.ts.map +1 -1
- package/dist/esm/components/EdgeLabelRenderer/index.d.ts +31 -29
- package/dist/esm/components/EdgeLabelRenderer/index.d.ts.map +1 -1
- package/dist/esm/components/Edges/BezierEdge.d.ts +26 -0
- package/dist/esm/components/Edges/BezierEdge.d.ts.map +1 -1
- package/dist/esm/components/Edges/EdgeAnchor.d.ts +3 -0
- package/dist/esm/components/Edges/EdgeAnchor.d.ts.map +1 -1
- package/dist/esm/components/Edges/EdgeText.d.ts +18 -18
- package/dist/esm/components/Edges/EdgeText.d.ts.map +1 -1
- package/dist/esm/components/Edges/SmoothStepEdge.d.ts +26 -0
- package/dist/esm/components/Edges/SmoothStepEdge.d.ts.map +1 -1
- package/dist/esm/components/Edges/StepEdge.d.ts +26 -0
- package/dist/esm/components/Edges/StepEdge.d.ts.map +1 -1
- package/dist/esm/components/Edges/StraightEdge.d.ts +24 -0
- package/dist/esm/components/Edges/StraightEdge.d.ts.map +1 -1
- package/dist/esm/container/Pane/index.d.ts.map +1 -1
- package/dist/esm/hooks/useKeyPress.d.ts +1 -0
- package/dist/esm/hooks/useKeyPress.d.ts.map +1 -1
- package/dist/esm/hooks/useReactFlow.d.ts.map +1 -1
- package/dist/esm/hooks/useViewportHelper.d.ts.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +418 -336
- package/dist/esm/index.mjs +418 -336
- package/dist/esm/store/index.d.ts +9 -9
- package/dist/esm/store/index.d.ts.map +1 -1
- package/dist/esm/store/initialState.d.ts +9 -9
- package/dist/esm/store/initialState.d.ts.map +1 -1
- package/dist/esm/types/edges.d.ts +23 -3
- package/dist/esm/types/edges.d.ts.map +1 -1
- package/dist/esm/types/general.d.ts +1 -12
- package/dist/esm/types/general.d.ts.map +1 -1
- package/dist/esm/types/instance.d.ts +2 -1
- package/dist/esm/types/instance.d.ts.map +1 -1
- package/dist/esm/types/store.d.ts +3 -5
- package/dist/esm/types/store.d.ts.map +1 -1
- package/dist/style.css +8 -4
- package/dist/umd/additional-components/Background/types.d.ts +20 -4
- package/dist/umd/additional-components/Background/types.d.ts.map +1 -1
- package/dist/umd/additional-components/Controls/types.d.ts +33 -9
- package/dist/umd/additional-components/Controls/types.d.ts.map +1 -1
- package/dist/umd/additional-components/MiniMap/MiniMap.d.ts.map +1 -1
- package/dist/umd/additional-components/NodeToolbar/types.d.ts +8 -2
- package/dist/umd/additional-components/NodeToolbar/types.d.ts.map +1 -1
- package/dist/umd/components/EdgeLabelRenderer/index.d.ts +31 -29
- package/dist/umd/components/EdgeLabelRenderer/index.d.ts.map +1 -1
- package/dist/umd/components/Edges/BezierEdge.d.ts +26 -0
- package/dist/umd/components/Edges/BezierEdge.d.ts.map +1 -1
- package/dist/umd/components/Edges/EdgeAnchor.d.ts +3 -0
- package/dist/umd/components/Edges/EdgeAnchor.d.ts.map +1 -1
- package/dist/umd/components/Edges/EdgeText.d.ts +18 -18
- package/dist/umd/components/Edges/EdgeText.d.ts.map +1 -1
- package/dist/umd/components/Edges/SmoothStepEdge.d.ts +26 -0
- package/dist/umd/components/Edges/SmoothStepEdge.d.ts.map +1 -1
- package/dist/umd/components/Edges/StepEdge.d.ts +26 -0
- package/dist/umd/components/Edges/StepEdge.d.ts.map +1 -1
- package/dist/umd/components/Edges/StraightEdge.d.ts +24 -0
- package/dist/umd/components/Edges/StraightEdge.d.ts.map +1 -1
- package/dist/umd/container/Pane/index.d.ts.map +1 -1
- package/dist/umd/hooks/useKeyPress.d.ts +1 -0
- package/dist/umd/hooks/useKeyPress.d.ts.map +1 -1
- package/dist/umd/hooks/useReactFlow.d.ts.map +1 -1
- package/dist/umd/hooks/useViewportHelper.d.ts.map +1 -1
- package/dist/umd/index.d.ts +1 -1
- package/dist/umd/index.d.ts.map +1 -1
- package/dist/umd/index.js +2 -2
- package/dist/umd/store/index.d.ts +9 -9
- package/dist/umd/store/index.d.ts.map +1 -1
- package/dist/umd/store/initialState.d.ts +9 -9
- package/dist/umd/store/initialState.d.ts.map +1 -1
- package/dist/umd/types/edges.d.ts +23 -3
- package/dist/umd/types/edges.d.ts.map +1 -1
- package/dist/umd/types/general.d.ts +1 -12
- package/dist/umd/types/general.d.ts.map +1 -1
- package/dist/umd/types/instance.d.ts +2 -1
- package/dist/umd/types/instance.d.ts.map +1 -1
- package/dist/umd/types/store.d.ts +3 -5
- package/dist/umd/types/store.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/esm/index.js
CHANGED
|
@@ -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,
|
|
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({
|
|
301
|
+
store.setState({ fitViewQueued: fieldValue });
|
|
302
302
|
else if (fieldName === 'fitViewOptions')
|
|
303
|
-
store.setState({
|
|
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.
|
|
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
|
-
|
|
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
|
|
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 (
|
|
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
|
-
|
|
2332
|
+
* @public
|
|
2339
2333
|
*
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
*import { EdgeText } from '@xyflow/react';
|
|
2334
|
+
* @example
|
|
2335
|
+
* ```jsx
|
|
2336
|
+
* import { EdgeText } from '@xyflow/react';
|
|
2343
2337
|
*
|
|
2344
|
-
*export function CustomEdgeLabel({ label }) {
|
|
2345
|
-
*
|
|
2346
|
-
*
|
|
2347
|
-
*
|
|
2348
|
-
*
|
|
2349
|
-
*
|
|
2350
|
-
*
|
|
2351
|
-
*
|
|
2352
|
-
*
|
|
2353
|
-
*
|
|
2354
|
-
*
|
|
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
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
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
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
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
|
-
*
|
|
3077
|
-
*
|
|
3078
|
-
*
|
|
3079
|
-
*
|
|
3080
|
-
*
|
|
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
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
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
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
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
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
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
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
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
|
-
|
|
3142
|
-
|
|
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
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
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
|
-
|
|
3155
|
-
|
|
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
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
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
|
-
|
|
3166
|
-
}
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
const
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
}
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
const
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
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
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
*
|
|
3481
|
+
* export function CustomEdge({ id, data, ...props }) {
|
|
3482
|
+
* const [edgePath, labelX, labelY] = getBezierPath(props);
|
|
3404
3483
|
*
|
|
3405
|
-
*
|
|
3406
|
-
*
|
|
3407
|
-
*
|
|
3408
|
-
*
|
|
3409
|
-
*
|
|
3410
|
-
*
|
|
3411
|
-
*
|
|
3412
|
-
*
|
|
3413
|
-
*
|
|
3414
|
-
*
|
|
3415
|
-
*
|
|
3416
|
-
*
|
|
3417
|
-
*
|
|
3418
|
-
*
|
|
3419
|
-
*
|
|
3420
|
-
*
|
|
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
|
|
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,
|