1"use strict"; 2(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([[540],{ 3 4/***/ 22935: 5/***/ (function(__unused_webpack_module, __webpack_exports__, __webpack_require__) { 6 7/* harmony export */ __webpack_require__.d(__webpack_exports__, { 8/* harmony export */ Aq: function() { return /* binding */ Background; }, 9/* harmony export */ Bn: function() { return /* binding */ useUpdateNodeInternals; }, 10/* harmony export */ Fb: function() { return /* binding */ applyNodeChanges; }, 11/* harmony export */ HH: function() { return /* binding */ Handle; }, 12/* harmony export */ Ly: function() { return /* reexport safe */ _xyflow_system__WEBPACK_IMPORTED_MODULE_3__.Ly; }, 13/* harmony export */ OQ: function() { return /* reexport safe */ _xyflow_system__WEBPACK_IMPORTED_MODULE_3__.OQ; }, 14/* harmony export */ XQ: function() { return /* binding */ EdgeLabelRenderer; }, 15/* harmony export */ ZX: function() { return /* binding */ Controls; }, 16/* harmony export */ Z_: function() { return /* binding */ addEdge; }, 17/* harmony export */ _K: function() { return /* binding */ useReactFlow; }, 18/* harmony export */ a9: function() { return /* binding */ MiniMap; }, 19/* harmony export */ x$: function() { return /* binding */ index; }, 20/* harmony export */ yn: function() { return /* binding */ applyEdgeChanges; } 21/* harmony export */ }); 22/* unused harmony exports BackgroundVariant, BaseEdge, BezierEdge, ControlButton, EdgeText, EdgeToolbar, MiniMapNode, NodeResizeControl, NodeResizer, NodeToolbar, Panel, ReactFlowProvider, SimpleBezierEdge, SmoothStepEdge, StepEdge, StraightEdge, ViewportPortal, experimental_useOnEdgesChangeMiddleware, experimental_useOnNodesChangeMiddleware, getSimpleBezierPath, isEdge, isNode, reconnectEdge, useConnection, useEdges, useEdgesState, useHandleConnections, useInternalNode, useKeyPress, useNodeConnections, useNodeId, useNodes, useNodesData, useNodesInitialized, useNodesState, useOnSelectionChange, useOnViewportChange, useStore, useStoreApi, useViewport */ 23/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(44951); 24/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(25529); 25/* harmony import */ var classcat__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(69552); 26/* harmony import */ var _xyflow_system__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(83531); 27/* harmony import */ var zustand_traditional__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(71171); 28/* harmony import */ var zustand_shallow__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(19977); 29/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(98652); 30/* __next_internal_client_entry_do_not_use__ ConnectionLineType,ConnectionMode,MarkerType,PanOnScrollMode,Position,ResizeControlVariant,SelectionMode,getBezierEdgeCenter,getBezierPath,getConnectedEdges,getEdgeCenter,getIncomers,getNodesBounds,getOutgoers,getSmoothStepPath,getStraightPath,getViewportForBounds,Background,Backgroun
30dVariant,BaseEdge,BezierEdge,ControlButton,Controls,EdgeLabelRenderer,EdgeText,EdgeToolbar,Handle,MiniMap,MiniMapNode,NodeResizeControl,NodeResizer,NodeToolbar,Panel,ReactFlow,ReactFlowProvider,SimpleBezierEdge,SmoothStepEdge,StepEdge,StraightEdge,ViewportPortal,addEdge,applyEdgeChanges,applyNodeChanges,experimental_useOnEdgesChangeMiddleware,experimental_useOnNodesChangeMiddleware,getSimpleBezierPath,isEdge,isNode,reconnectEdge,useConnection,useEdges,useEdgesState,useHandleConnections,useInternalNode,useKeyPress,useNodeConnections,useNodeId,useNodes,useNodesData,useNodesInitialized,useNodesState,useOnSelectionChange,useOnViewportChange,useReactFlow,useStore,useStoreApi,useUpdateNodeInternals,useViewport auto */ 31 32 33 34 35 36 37 38const StoreContext = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.createContext)(null); 39const Provider$1 = StoreContext.Provider; 40const zustandErrorMessage = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .errorMessages */ .Qj["error001"]("react"); 41/** 42 * This hook can be used to subscribe to internal state changes of the React Flow 43 * component. The `useStore` hook is re-exported from the [Zustand](https://github.com/pmndrs/zustand) 44 * state management library, so you should check out their docs for more details. 45 * 46 * @public 47 * @param selector - A selector function that returns a slice of the flow's internal state. 48 * Extracting or transforming just the state you need is a good practice to avoid unnecessary 49 * re-renders. 50 * @param equalityFn - A function to compare the previous and next value. This is incredibly useful 51 * for preventing unnecessary re-renders. Good sensible defaults are using `Object.is` or importing 52 * `zustand/shallow`, but you can be as granular as you like. 53 * @returns The selected state slice. 54 * 55 * @example 56 * ```ts 57 * const nodes = useStore((state) => state.nodes); 58 * ``` 59 * 60 * @remarks This hook should only be used if there is no other way to access the internal 61 * state. For many of the common use cases, there are dedicated hooks available 62 * such as {@link useReactFlow}, {@link useViewport}, etc. 63 */ function useStore(selector, equalityFn) { 64 const store = (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(StoreContext); 65 if (store === null) { 66 throw new Error(zustandErrorMessage); 67 } 68 return (0,zustand_traditional__WEBPACK_IMPORTED_MODULE_4__/* .useStoreWithEqualityFn */ .s)(store, selector, equalityFn); 69} 70/** 71 * In some cases, you might need to access the store directly. This hook returns the store object which can be used on demand to access the state or dispatch actions. 72 * 73 * @returns The store object. 74 * @example 75 * ```ts 76 * const store = useStoreApi(); 77 * ``` 78 * 79 * @remarks This hook should only be used if there is no other way to access the internal 80 * state. For many of the common use cases, there are dedicated hooks available 81 * such as {@link useReactFlow}, {@link useViewport}, etc. 82 */ function useStoreApi() { 83 const store = (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(StoreContext); 84 if (store === null) { 85 throw new Error(zustandErrorMessage); 86 } 87 return (0,react__WEBPACK_IMPORTED_MODULE_1__.useMemo)(()=>({ 88 getState: store.getState, 89 setState: store.setState, 90 subscribe: store.subscribe 91 }), [ 92 store 93 ]); 94} 95const style = { 96 display: "none" 97}; 98const ariaLiveStyle = { 99 position: "absolute", 100 width: 1, 101 height: 1, 102 margin: -1, 103 border: 0, 104 padding: 0, 105 overflow: "hidden", 106 clip: "rect(0px, 0px, 0px, 0px)", 107 clipPath: "inset(100%)" 108}; 109const ARIA_NODE_DESC_KEY = "react-flow__node-desc"; 110const ARIA_EDGE_DESC_KEY = "react-flow__edge-desc"; 111const ARIA_LIVE_MESSAGE = "react-flow__aria-live"; 112const ariaLiveSelector = (s)=>s.ariaLiveMessage; 113const ariaLabelConfigSelector = (s)=>s.ariaLabelConfig; 114function AriaLiveMessage(param) { 115 let { rfId } = param; 116 const ariaLiveMessage = useStore(ariaLiveSelector); 117 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 118 id: "".concat(ARIA_LIVE_MESSAGE, "-").concat(rfId), 119 "aria-live": "assertive", 120 "aria-atomic": "true", 121 style: ariaLiveStyle, 122 children: ariaLiveMessage 123 }); 124} 125function A11yDescriptions(param) { 126 let { rfId, disableKeyboardA11y } = param; 127 const ariaLabelConfig = useStore(ariaLabelConfigSelector); 128 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, { 129 children: [ 130 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 131 id: "".concat(ARIA_NODE_DESC_KEY, "-").concat(rfId), 132 style: style, 133 children: disableKeyboardA11y ? ariaLabelConfig["node.a11yDescription.default"] : ariaLabelConfig["node.a11yDescription.keyboardDisabled"] 134 }), 135 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 136 id: "".concat(ARIA_EDGE_DESC_KEY, "-").concat(rfId), 137 style: style, 138 children: ariaLabelConfig["edge.a11yDescription.default"] 139 }), 140 !disableKeyboardA11y && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(AriaLiveMessage, { 141 rfId: rfId 142 }) 143 ] 144 }); 145} 146/** 147 * The `<Panel />` component helps you position content above the viewport. 148 * It is used internally by the [`<MiniMap />`](/api-reference/components/minimap)
149 * and [`<Controls />`](/api-reference/components/controls) components. 150 * 151 * @public 152 * 153 * @example 154 * ```jsx 155 *import { ReactFlow, Background, Panel } from '@xyflow/react'; 156 * 157 *export default function Flow() { 158 * return ( 159 * <ReactFlow nodes={[]} fitView> 160 * <Panel position="top-left">top-left</Panel> 161 * <Panel position="top-center">top-center</Panel> 162 * <Panel position="top-right">top-right</Panel> 163 * <Panel position="bottom-left">bottom-left</Panel> 164 * <Panel position="bottom-center">bottom-center</Panel> 165 * <Panel position="bottom-right">bottom-right</Panel> 166 * </ReactFlow> 167 * ); 168 *} 169 *``` 170 */ const Panel = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.forwardRef)((param, ref)=>{ 171 let { position = "top-left", children, className, style, ...rest } = param; 172 const positionClasses = "".concat(position).split("-"); 173 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 174 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 175 "react-flow__panel", 176 className, 177 ...positionClasses 178 ]), 179 style: style, 180 ref: ref, 181 ...rest, 182 children: children 183 }); 184}); 185Panel.displayName = "Panel"; 186const link = "https://reactflow.dev".concat( true ? "?utm_source=attribution" : 0); 187function Attribution(param) { 188 let { proOptions, position = "bottom-right" } = param; 189 if (proOptions === null || proOptions === void 0 ? void 0 : proOptions.hideAttribution) { 190 return null; 191 } 192 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(Panel, { 193 position: position, 194 className: "react-flow__attribution", 195 "data-message": "Please only hide this attribution when you are subscribed to React Flow Pro: ".concat(link), 196 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("a", { 197 href: link, 198 target: "_blank", 199 rel: "noopener noreferrer", 200 "aria-label": "React Flow attribution", 201 children: "React Flow" 202 }) 203 }); 204} 205const selector$l = (s)=>{ 206 const selectedNodes = []; 207 const selectedEdges = []; 208 for (const [, node] of s.nodeLookup){ 209 if (node.selected) { 210 selectedNodes.push(node.internals.userNode); 211 } 212 } 213 for (const [, edge] of s.edgeLookup){ 214 if (edge.selected) { 215 selectedEdges.push(edge); 216 } 217 } 218 return { 219 selectedNodes, 220 selectedEdges 221 }; 222}; 223const selectId = (obj)=>obj.id; 224function areEqual$1(a, b) { 225 return (0,zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X)(a.selectedNodes.map(selectId), b.selectedNodes.map(selectId)) && (0,zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X)(a.selectedEdges.map(selectId), b.selectedEdges.map(selectId)); 226} 227function SelectionListenerInner(param) { 228 let { onSelectionChange } = param; 229 const store = useStoreApi(); 230 const { selectedNodes, selectedEdges } = useStore(selector$l, areEqual$1); 231 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 232 const params = { 233 nodes: selectedNodes, 234 edges: selectedEdges 235 }; 236 onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(params); 237 store.getState().onSelectionChangeHandlers.forEach((fn)=>fn(params)); 238 }, [ 239 selectedNodes, 240 selectedEdges, 241 onSelectionChange 242 ]); 243 return null; 244} 245const changeSelector = (s)=>!!s.onSelectionChangeHandlers; 246function SelectionListener(param) { 247 let { onSelectionChange } = param; 248 const storeHasSelectionChangeHandlers = useStore(changeSelector); 249 if (onSelectionChange || storeHasSelectionChangeHandlers) { 250 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(SelectionListenerInner, { 251 onSelectionChange: onSelectionChange 252 }); 253 } 254 return null; 255} 256const defaultNodeOrigin = [ 257 0, 258 0 259]; 260const defaultViewport = { 261 x: 0, 262 y: 0, 263 zoom: 1 264}; 265/* 266 * This component helps us to update the store with the values coming from the user. 267 * We distinguish between values we can update directly with `useDirectStoreUpdater` (like `snapGrid`) 268 * and values that have a dedicated setter function in the store (like `setNodes`). 269 */ // These fields exist in the global store, and we need to keep them up to date 270const reactFlowFieldsToTrack = [ 271 "nodes", 272 "edges", 273 "defaultNodes", 274 "defaultEdges", 275 "onConnect", 276 "onConnectStart", 277 "onConnectEnd", 278 "onClickConnectStart", 279 "onClickConnectEnd", 280 "nodesDraggable", 281 "autoPanOnNodeFocus", 282 "nodesConnectable", 283 "nodesFocusable", 284 "edgesFocusable", 285 "edgesReconnectable", 286 "elevateNodesOnSelect", 287 "elevateEdgesOnSelect", 288 "minZoom", 289 "maxZoom", 290 "nodeExtent", 291 "onNodesChange", 292 "onEdgesChange", 293 "elementsSelectable", 294 "connectionMode", 295 "snapGrid",
296 "snapToGrid", 297 "translateExtent", 298 "connectOnClick", 299 "defaultEdgeOptions", 300 "fitView", 301 "fitViewOptions", 302 "onNodesDelete", 303 "onEdgesDelete", 304 "onDelete", 305 "onNodeDrag", 306 "onNodeDragStart", 307 "onNodeDragStop", 308 "onSelectionDrag", 309 "onSelectionDragStart", 310 "onSelectionDragStop", 311 "onMoveStart", 312 "onMove", 313 "onMoveEnd", 314 "noPanClassName", 315 "nodeOrigin", 316 "autoPanOnConnect", 317 "autoPanOnNodeDrag", 318 "onError", 319 "connectionRadius", 320 "isValidConnection", 321 "selectNodesOnDrag", 322 "nodeDragThreshold", 323 "connectionDragThreshold", 324 "onBeforeDelete", 325 "debug", 326 "autoPanSpeed", 327 "ariaLabelConfig", 328 "zIndexMode" 329]; 330// rfId doesn't exist in ReactFlowProps, but it's one of the fields we want to update 331const fieldsToTrack = [ 332 ...reactFlowFieldsToTrack, 333 "rfId" 334]; 335const selector$k = (s)=>({ 336 setNodes: s.setNodes, 337 setEdges: s.setEdges, 338 setMinZoom: s.setMinZoom, 339 setMaxZoom: s.setMaxZoom, 340 setTranslateExtent: s.setTranslateExtent, 341 setNodeExtent: s.setNodeExtent, 342 reset: s.reset, 343 setDefaultNodesAndEdges: s.setDefaultNodesAndEdges 344 }); 345const initPrevValues = { 346 /* 347 * these are values that are also passed directly to other components 348 * than the StoreUpdater. We can reduce the number of setStore calls 349 * by setting the same values here as prev fields. 350 */ translateExtent: _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .infiniteExtent */ .k5, 351 nodeOrigin: defaultNodeOrigin, 352 minZoom: 0.5, 353 maxZoom: 2, 354 elementsSelectable: true, 355 noPanClassName: "nopan", 356 rfId: "1" 357}; 358function StoreUpdater(props) { 359 const { setNodes, setEdges, setMinZoom, setMaxZoom, setTranslateExtent, setNodeExtent, reset, setDefaultNodesAndEdges } = useStore(selector$k, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 360 const store = useStoreApi(); 361 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 362 setDefaultNodesAndEdges(props.defaultNodes, props.defaultEdges); 363 return ()=>{ 364 // when we reset the store we also need to reset the previous fields 365 previousFields.current = initPrevValues; 366 reset(); 367 }; 368 }, []); 369 const previousFields = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(initPrevValues); 370 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 371 for (const fieldName of fieldsToTrack){ 372 const fieldValue = props[fieldName]; 373 const previousFieldValue = previousFields.current[fieldName]; 374 if (fieldValue === previousFieldValue) continue; 375 if (typeof props[fieldName] === "undefined") continue; 376 // Custom handling with dedicated setters for some fields 377 if (fieldName === "nodes") setNodes(fieldValue); 378 else if (fieldName === "edges") setEdges(fieldValue); 379 else if (fieldName === "minZoom") setMinZoom(fieldValue); 380 else if (fieldName === "maxZoom") setMaxZoom(fieldValue); 381 else if (fieldName === "translateExtent") setTranslateExtent(fieldValue); 382 else if (fieldName === "nodeExtent") setNodeExtent(fieldValue); 383 else if (fieldName === "ariaLabelConfig") store.setState({ 384 ariaLabelConfig: (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .mergeAriaLabelConfig */ .AL)(fieldValue) 385 }); 386 else if (fieldName === "fitView") store.setState({ 387 fitViewQueued: fieldValue 388 }); 389 else if (fieldName === "fitViewOptions") store.setState({ 390 fitViewOptions: fieldValue 391 }); 392 else store.setState({ 393 [fieldName]: fieldValue 394 }); 395 } 396 previousFields.current = props; 397 }, // Only re-run the effect if one of the fields we track changes 398 fieldsToTrack.map((fieldName)=>props[fieldName])); 399 return null; 400} 401function getMediaQuery() { 402 if (typeof window === "undefined" || !window.matchMedia) { 403 return null; 404 } 405 return window.matchMedia("(prefers-color-scheme: dark)"); 406} 407/** 408 * Hook for receiving the current color mode class 'dark' or 'light'. 409 * 410 * @internal 411 * @param colorMode - The color mode to use ('dark', 'light' or 'system') 412 */ function useColorModeClass(colorMode) { 413 var _getMediaQuery; 414 const [colorModeClass, setColorModeClass] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(colorMode === "system" ? null : colorMode); 415 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 416 if (colorMode !== "system") { 417 setColorModeClass(colorMode); 418 return; 419 } 420 const mediaQuery = getMediaQuery(); 421 const updateColorModeClass = ()=>setColorModeClass((mediaQuery === null || mediaQuery === void 0 ? void 0 : mediaQuery.matches) ? "dark" : "light"); 422 updateColorModeClass(); 423 mediaQuery === null || mediaQuery === void 0 ? void 0 : mediaQuery.addEventListener("change", updateColorModeClass); 424 return ()=>{ 425 mediaQuery === null || mediaQuery === void 0 ? void 0 : mediaQuery.removeEventListener("change", updateColorModeClass); 426 }; 427 }, [ 428 colorMode 429 ]); 430 return colorModeClass !== null ? colorModeClass : ((_getMediaQuery = getMediaQuery()) === null || _getMediaQuery === void 0 ? void 0 : _getMediaQuery.matches) ? "dark" : "light"; 431} 432const defaultDoc = typeof document !== "undefined" ? document : null; 433/** 434 * This hook lets you listen for specific key codes and tells you whether they are 435 * currently pressed or not. 436 * 437 * @public 438 * @param options - Options 439 * 440 * @example 441 * ```tsx 442 *import { useKeyPress } from '@xyflow/react'; 443 * 444 *export default function () { 445 * const spacePressed = useKeyPress('Space'); 446 * const cmdAndSPressed = useKeyPress(['Meta+s', 'Strg+s']); 447 * 448 * return ( 449 * <div> 450 * {spacePressed && <p>Space pressed!</p>} 451 * {cmdAndSPressed && <p>Cmd + S pressed!</p>} 452 * </div> 453 * ); 454 *} 455 *``` 456 */ function useKeyPress() { 457 let /**
458 * The key code (string or array of strings) specifies which key(s) should trigger 459 * an action. 460 * 461 * A **string** can represent: 462 * - A **single key**, e.g. `'a'` 463 * - A **key combination**, using `'+'` to separate keys, e.g. `'a+d'` 464 * 465 * An **array of strings** represents **multiple possible key inputs**. For example, `['a', 'd+s']` 466 * means the user can press either the single key `'a'` or the combination of `'d'` and `'s'`. 467 * @default null 468 */ keyCode = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : null, options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : { 469 target: defaultDoc, 470 actInsideInputWithModifier: true 471 }; 472 const [keyPressed, setKeyPressed] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(false); 473 // we need to remember if a modifier key is pressed in order to track it 474 const modifierPressed = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(false); 475 // we need to remember the pressed keys in order to support combinations 476 const pressedKeys = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(new Set([])); 477 /* 478 * keyCodes = array with single keys [['a']] or key combinations [['a', 's']] 479 * keysToWatch = array with all keys flattened ['a', 'd', 'ShiftLeft'] 480 * used to check if we store event.code or event.key. When the code is in the list of keysToWatch 481 * we use the code otherwise the key. Explainer: When you press the left "command" key, the code is "MetaLeft" 482 * and the key is "Meta". We want users to be able to pass keys and codes so we assume that the key is meant when 483 * we can't find it in the list of keysToWatch. 484 */ const [keyCodes, keysToWatch] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useMemo)(()=>{ 485 if (keyCode !== null) { 486 const keyCodeArr = Array.isArray(keyCode) ? keyCode : [ 487 keyCode 488 ]; 489 const keys = keyCodeArr.filter((kc)=>typeof kc === "string")/* 490 * we first replace all '+' with '\n' which we will use to split the keys on 491 * then we replace '\n\n' with '\n+', this way we can also support the combination 'key++' 492 * in the end we simply split on '\n' to get the key array 493 */ .map((kc)=>kc.replace("+", "\n").replace("\n\n", "\n+").split("\n")); 494 const keysFlat = keys.reduce((res, item)=>res.concat(...item), []); 495 return [ 496 keys, 497 keysFlat 498 ]; 499 } 500 return [ 501 [], 502 [] 503 ]; 504 }, [ 505 keyCode 506 ]); 507 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 508 var _options_target; 509 const target = (_options_target = options === null || options === void 0 ? void 0 : options.target) !== null && _options_target !== void 0 ? _options_target : defaultDoc; 510 var _options_actInsideInputWithModifier; 511 const actInsideInputWithModifier = (_options_actInsideInputWithModifier = options === null || options === void 0 ? void 0 : options.actInsideInputWithModifier) !== null && _options_actInsideInputWithModifier !== void 0 ? _options_actInsideInputWithModifier : true; 512 if (keyCode !== null) { 513 const downHandler = (event)=>{ 514 modifierPressed.current = event.ctrlKey || event.metaKey || event.shiftKey || event.altKey; 515 const preventAction = (!modifierPressed.current || modifierPressed.current && !actInsideInputWithModifier) && (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .isInputDOMNode */ .s$)(event); 516 if (preventAction) { 517 return false; 518 } 519 const keyOrCode = useKeyOrCode(event.code, keysToWatch); 520 pressedKeys.current.add(event[keyOrCode]); 521 if (isMatchingKey(keyCodes, pressedKeys.current, false)) { 522 var _event_composedPath, _event_composedPath1; 523 const target = ((_event_composedPath1 = event.composedPath) === null || _event_composedPath1 === void 0 ? void 0 : (_event_composedPath = _event_composedPath1.call(event)) === null || _event_composedPath === void 0 ? void 0 : _event_composedPath[0]) || event.target; 524 const isInteractiveElement = (target === null || target === void 0 ? void 0 : target.nodeName) === "BUTTON" || (target === null || target === void 0 ? void 0 : target.nodeName) === "A"; 525 if (options.preventDefault !== false && (modifierPressed.current || !isInteractiveElement)) { 526 event.preventDefault(); 527 } 528 setKeyPressed(true); 529 } 530 }; 531 const upHandler = (event)=>{
532 const keyOrCode = useKeyOrCode(event.code, keysToWatch); 533 if (isMatchingKey(keyCodes, pressedKeys.current, true)) { 534 setKeyPressed(false); 535 pressedKeys.current.clear(); 536 } else { 537 pressedKeys.current.delete(event[keyOrCode]); 538 } 539 // fix for Mac: when cmd key is pressed, keyup is not triggered for any other key, see: https://stackoverflow.com/questions/27380018/when-cmd-key-is-kept-pressed-keyup-is-not-triggered-for-any-other-key 540 if (event.key === "Meta") { 541 pressedKeys.current.clear(); 542 } 543 modifierPressed.current = false; 544 }; 545 const resetHandler = ()=>{ 546 pressedKeys.current.clear(); 547 setKeyPressed(false); 548 }; 549 target === null || target === void 0 ? void 0 : target.addEventListener("keydown", downHandler); 550 target === null || target === void 0 ? void 0 : target.addEventListener("keyup", upHandler); 551 window.addEventListener("blur", resetHandler); 552 window.addEventListener("contextmenu", resetHandler); 553 return ()=>{ 554 target === null || target === void 0 ? void 0 : target.removeEventListener("keydown", downHandler); 555 target === null || target === void 0 ? void 0 : target.removeEventListener("keyup", upHandler); 556 window.removeEventListener("blur", resetHandler); 557 window.removeEventListener("contextmenu", resetHandler); 558 }; 559 } 560 }, [ 561 keyCode, 562 setKeyPressed 563 ]); 564 return keyPressed; 565} 566// utils 567function isMatchingKey(keyCodes, pressedKeys, isUp) { 568 return keyCodes/* 569 * we only want to compare same sizes of keyCode definitions 570 * and pressed keys. When the user specified 'Meta' as a key somewhere 571 * this would also be truthy without this filter when user presses 'Meta' + 'r' 572 */ .filter((keys)=>isUp || keys.length === pressedKeys.size)/* 573 * since we want to support multiple possibilities only one of the 574 * combinations need to be part of the pressed keys 575 */ .some((keys)=>keys.every((k)=>pressedKeys.has(k))); 576} 577function useKeyOrCode(eventCode, keysToWatch) { 578 return keysToWatch.includes(eventCode) ? "code" : "key"; 579} 580/** 581 * Hook for getting viewport helper functions. 582 * 583 * @internal 584 * @returns viewport helper functions 585 */ const useViewportHelper = ()=>{ 586 const store = useStoreApi(); 587 return (0,react__WEBPACK_IMPORTED_MODULE_1__.useMemo)(()=>{ 588 return { 589 zoomIn: async (options)=>{ 590 const { panZoom } = store.getState(); 591 return panZoom ? panZoom.scaleBy(1.2, options) : false; 592 }, 593 zoomOut: async (options)=>{ 594 const { panZoom } = store.getState(); 595 return panZoom ? panZoom.scaleBy(1 / 1.2, options) : false; 596 }, 597 zoomTo: async (zoomLevel, options)=>{ 598 const { panZoom } = store.getState(); 599 return panZoom ? panZoom.scaleTo(zoomLevel, options) : false; 600 }, 601 getZoom: ()=>store.getState().transform[2], 602 setViewport: async (viewport, options)=>{ 603 const { transform: [tX, tY, tZoom], panZoom } = store.getState(); 604 if (!panZoom) { 605 return false; 606 } 607 var _viewport_x, _viewport_y, _viewport_zoom; 608 await panZoom.setViewport({ 609 x: (_viewport_x = viewport.x) !== null && _viewport_x !== void 0 ? _viewport_x : tX, 610 y: (_viewport_y = viewport.y) !== null && _viewport_y !== void 0 ? _viewport_y : tY, 611 zoom: (_viewport_zoom = viewport.zoom) !== null && _viewport_zoom !== void 0 ? _viewport_zoom : tZoom 612 }, options); 613 return true; 614 }, 615 getViewport: ()=>{ 616 const [x, y, zoom] = store.getState().transform; 617 return { 618 x, 619 y, 620 zoom 621 }; 622 }, 623 setCenter: async (x, y, options)=>{ 624 return store.getState().setCenter(x, y, options); 625 }, 626 fitBounds: async (bounds, options)=>{ 627 const { width, height, minZoom, maxZoom, panZoom } = store.getState(); 628 var _options_padding; 629 const viewport = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getViewportForBounds */ .$i)(bounds, width, height, minZoom, maxZoom, (_options_padding = options === null || options === void 0 ? void 0 : options.padding) !== null && _options_padding !== void 0 ? _options_padding : 0.1); 630 if (!panZoom) { 631 return false;
632 } 633 await panZoom.setViewport(viewport, { 634 duration: options === null || options === void 0 ? void 0 : options.duration, 635 ease: options === null || options === void 0 ? void 0 : options.ease, 636 interpolate: options === null || options === void 0 ? void 0 : options.interpolate 637 }); 638 return true; 639 }, 640 screenToFlowPosition: function(clientPosition) { 641 let options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {}; 642 const { transform, snapGrid, snapToGrid, domNode } = store.getState(); 643 if (!domNode) { 644 return clientPosition; 645 } 646 const { x: domX, y: domY } = domNode.getBoundingClientRect(); 647 const correctedPosition = { 648 x: clientPosition.x - domX, 649 y: clientPosition.y - domY 650 }; 651 var _options_snapGrid; 652 const _snapGrid = (_options_snapGrid = options.snapGrid) !== null && _options_snapGrid !== void 0 ? _options_snapGrid : snapGrid; 653 var _options_snapToGrid; 654 const _snapToGrid = (_options_snapToGrid = options.snapToGrid) !== null && _options_snapToGrid !== void 0 ? _options_snapToGrid : snapToGrid; 655 return (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .pointToRendererPoint */ .m)(correctedPosition, transform, _snapToGrid, _snapGrid); 656 }, 657 flowToScreenPosition: (flowPosition)=>{ 658 const { transform, domNode } = store.getState(); 659 if (!domNode) { 660 return flowPosition; 661 } 662 const { x: domX, y: domY } = domNode.getBoundingClientRect(); 663 const rendererPosition = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .rendererPointToPoint */ .oj)(flowPosition, transform); 664 return { 665 x: rendererPosition.x + domX, 666 y: rendererPosition.y + domY 667 }; 668 } 669 }; 670 }, []); 671}; 672/* 673 * This function applies changes to nodes or edges that are triggered by React Flow internally. 674 * When you drag a node for example, React Flow will send a position change update. 675 * This function then applies the changes and returns the updated elements. 676 */ function applyChanges(changes, elements) { 677 const updatedElements = []; 678 /* 679 * By storing a map of changes for each element, we can a quick lookup as we 680 * iterate over the elements array! 681 */ const changesMap = new Map(); 682 const addItemChanges = []; 683 for (const change of changes){ 684 if (change.type === "add") { 685 addItemChanges.push(change); 686 continue; 687 } else if (change.type === "remove" || change.type === "replace") { 688 /* 689 * For a 'remove' change we can safely ignore any other changes queued for 690 * the same element, it's going to be removed anyway! 691 */ changesMap.set(change.id, [ 692 change 693 ]); 694 } else { 695 const elementChanges = changesMap.get(change.id); 696 if (elementChanges) { 697 /* 698 * If we have some changes queued already, we can do a mutable update of 699 * that array and save ourselves some copying. 700 */ elementChanges.push(change); 701 } else { 702 changesMap.set(change.id, [ 703 change 704 ]); 705 } 706 } 707 } 708 for (const element of elements){ 709 const changes = changesMap.get(element.id); 710 /* 711 * When there are no changes for an element we can just push it unmodified, 712 * no need to copy it. 713 */ if (!changes) { 714 updatedElements.push(element); 715 continue; 716 } 717 // If we have a 'remove' change queued, it'll be the only change in the array 718 if (changes[0].type === "remove") { 719 continue; 720 } 721 if (changes[0].type === "replace") { 722 updatedElements.push({ 723 ...changes[0].item 724 }); 725 continue; 726 } 727 /** 728 * For other types of changes, we want to start with a shallow copy of the 729 * object so React knows this element has changed. Sequential changes will 730 * each _mutate_ this object, so there's only ever one copy. 731 */ const updatedElement = { 732 ...element 733 }; 734 for (const change of changes){
vendor: 4,109 bytes, lines 735-855
735 applyChange(change, updatedElement); 736 } 737 updatedElements.push(updatedElement); 738 } 739 /* 740 * we need to wait for all changes to be applied before adding new items 741 * to be able to add them at the correct index 742 */ if (addItemChanges.length) { 743 addItemChanges.forEach((change)=>{ 744 if (change.index !== undefined) { 745 updatedElements.splice(change.index, 0, { 746 ...change.item 747 }); 748 } else { 749 updatedElements.push({ 750 ...change.item 751 }); 752 } 753 }); 754 } 755 return updatedElements; 756} 757// Applies a single change to an element. This is a *mutable* update. 758function applyChange(change, element) { 759 switch(change.type){ 760 case "select": 761 { 762 element.selected = change.selected; 763 break; 764 } 765 case "position": 766 { 767 if (typeof change.position !== "undefined") { 768 element.position = change.position; 769 } 770 if (typeof change.dragging !== "undefined") { 771 element.dragging = change.dragging; 772 } 773 break; 774 } 775 case "dimensions": 776 { 777 if (typeof change.dimensions !== "undefined") { 778 element.measured = { 779 ...change.dimensions 780 }; 781 if (change.setAttributes) { 782 if (change.setAttributes === true || change.setAttributes === "width") { 783 element.width = change.dimensions.width; 784 } 785 if (change.setAttributes === true || change.setAttributes === "height") { 786 element.height = change.dimensions.height; 787 } 788 } 789 } 790 if (typeof change.resizing === "boolean") { 791 element.resizing = change.resizing; 792 } 793 break; 794 } 795 } 796} 797/** 798 * Drop in function that applies node changes to an array of nodes. 799 * @public 800 * @param changes - Array of changes to apply. 801 * @param nodes - Array of nodes to apply the changes to. 802 * @returns Array of updated nodes. 803 * @example 804 *```tsx 805 *import { useState, useCallback } from 'react'; 806 *import { ReactFlow, applyNodeChanges, type Node, type Edge, type OnNodesChange } from '@xyflow/react'; 807 * 808 *export default function Flow() { 809 * const [nodes, setNodes] = useState<Node[]>([]); 810 * const [edges, setEdges] = useState<Edge[]>([]); 811 * const onNodesChange: OnNodesChange = useCallback( 812 * (changes) => { 813 * setNodes((oldNodes) => applyNodeChanges(changes, oldNodes)); 814 * }, 815 * [setNodes], 816 * ); 817 * 818 * return ( 819 * <ReactFlow nodes={nodes} edges={edges} onNodesChange={onNodesChange} /> 820 * ); 821 *} 822 *``` 823 * @remarks Various events on the <ReactFlow /> component can produce an {@link NodeChange} 824 * that describes how to update the edges of your flow in some way. 825 * If you don't need any custom behaviour, this util can be used to take an array 826 * of these changes and apply them to your edges. 827 */ function applyNodeChanges(changes, nodes) { 828 return applyChanges(changes, nodes); 829} 830/** 831 * Drop in function that applies edge changes to an array of edges. 832 * @public 833 * @param changes - Array of changes to apply. 834 * @param edges - Array of edge to apply the changes to. 835 * @returns Array of updated edges. 836 * @example 837 * ```tsx 838 *import { useState, useCallback } from 'react'; 839 *import { ReactFlow, applyEdgeChanges } from '@xyflow/react'; 840 * 841 *export default function Flow() { 842 * const [nodes, setNodes] = useState([]); 843 * const [edges, setEdges] = useState([]); 844 * const onEdgesChange = useCallback( 845 * (changes) => { 846 * setEdges((oldEdges) => applyEdgeChanges(changes, oldEdges)); 847 * }, 848 * [setEdges], 849 * ); 850 * 851 * return ( 852 * <ReactFlow nodes={nodes} edges={edges} onEdgesChange={onEdgesChange} /> 853 * ); 854 *} 855 *```
856 * @remarks Various events on the <ReactFlow /> component can produce an {@link EdgeChange} 857 * that describes how to update the edges of your flow in some way. 858 * If you don't need any custom behaviour, this util can be used to take an array 859 * of these changes and apply them to your edges. 860 */ function applyEdgeChanges(changes, edges) { 861 return applyChanges(changes, edges); 862} 863function createSelectionChange(id, selected) { 864 return { 865 id, 866 type: "select", 867 selected 868 }; 869} 870function getSelectionChanges(items) { 871 let selectedIds = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : new Set(), mutateItem = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : false; 872 const changes = []; 873 for (const [id, item] of items){ 874 const willBeSelected = selectedIds.has(id); 875 // we don't want to set all items to selected=false on the first selection 876 if (!(item.selected === undefined && !willBeSelected) && item.selected !== willBeSelected) { 877 if (mutateItem) { 878 /* 879 * this hack is needed for nodes. When the user dragged a node, it's selected. 880 * When another node gets dragged, we need to deselect the previous one, 881 * in order to have only one selected node at a time - the onNodesChange callback comes too late here :/ 882 */ item.selected = willBeSelected; 883 } 884 changes.push(createSelectionChange(item.id, willBeSelected)); 885 } 886 } 887 return changes; 888} 889function getElementsDiffChanges(param) { 890 let { items = [], lookup } = param; 891 const changes = []; 892 const itemsLookup = new Map(items.map((item)=>[ 893 item.id, 894 item 895 ])); 896 for (const [index, item] of items.entries()){ 897 var _lookupItem_internals; 898 const lookupItem = lookup.get(item.id); 899 var _lookupItem_internals_userNode; 900 const storeItem = (_lookupItem_internals_userNode = lookupItem === null || lookupItem === void 0 ? void 0 : (_lookupItem_internals = lookupItem.internals) === null || _lookupItem_internals === void 0 ? void 0 : _lookupItem_internals.userNode) !== null && _lookupItem_internals_userNode !== void 0 ? _lookupItem_internals_userNode : lookupItem; 901 if (storeItem !== undefined && storeItem !== item) { 902 changes.push({ 903 id: item.id, 904 item: item, 905 type: "replace" 906 }); 907 } 908 if (storeItem === undefined) { 909 changes.push({ 910 item: item, 911 type: "add", 912 index 913 }); 914 } 915 } 916 for (const [id] of lookup){ 917 const nextNode = itemsLookup.get(id); 918 if (nextNode === undefined) { 919 changes.push({ 920 id, 921 type: "remove" 922 }); 923 } 924 } 925 return changes; 926} 927function elementToRemoveChange(item) { 928 return { 929 id: item.id, 930 type: "remove" 931 }; 932} 933const defaultOnError = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .createDevWarn */ .F1)("React Flow", "https://reactflow.dev/"); 934function addEdge(edgeParams, edges) { 935 let options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {}; 936 var _options_onError; 937 return (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .addEdge */ .Z_)(edgeParams, edges, { 938 ...options, 939 onError: (_options_onError = options.onError) !== null && _options_onError !== void 0 ? _options_onError : defaultOnError 940 }); 941} 942function reconnectEdge(oldEdge, newConnection, edges) { 943 let options = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : { 944 shouldReplaceId: true 945 }; 946 var _options_onError; 947 return reconnectEdge$1(oldEdge, newConnection, edges, { 948 ...options, 949 onError: (_options_onError = options.onError) !== null && _options_onError !== void 0 ? _options_onError : defaultOnError 950 }); 951} 952/** 953 * Test whether an object is usable as an [`Node`](/api-reference/types/node). 954 * In TypeScript this is a type guard that will narrow the type of whatever you pass in to 955 * [`Node`](/api-reference/types/node) if it returns `true`. 956 * 957 * @public 958 * @remarks In TypeScript this is a type guard that will narrow the type of whatever you pass in to Node if it returns true 959 * @param element - The element to test. 960 * @returns Tests whether the provided value can be used as a `Node`. If you're using TypeScript, 961 * this function acts as a type guard and will narrow the type of the value to `Node` if it returns 962 * `true`. 963 * 964 * @example 965 * ```js 966 *import { isNode } from '@xyflow/react'; 967 * 968 *if (isNode(node)) { 969 * // ... 970 *} 971 *``` 972 */ const isNode = (element)=>(0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .isNodeBase */ .Vt)(element); 973/** 974 * Test whether an object is usable as an [`Edge`](/api-reference/types/edge). 975 * In TypeScript this is a type guard that will narrow the type of whatever you pass in to 976 * [`Edge`](/api-reference/types/edge) if it returns `true`. 977 * 978 * @public 979 * @remarks In TypeScript this is a type guard that will narrow the type of whatever you pass in to Edge if it returns true 980 * @param element - The element to test 981 * @returns Tests whether the provided value can be used as an `Edge`. If you're using TypeScript, 982 * this function acts as a type guard and will narrow the type of the value to `Edge` if it returns 983 * `true`. 984 * 985 * @example 986 * ```js 987 *import { isEdge } from '@xyflow/react'; 988 * 989 *if (isEdge(edge)) { 990 * // ... 991 *} 992 *``` 993 */ const isEdge = (element)=>(0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .isEdgeBase */ .J3)(element); 994// eslint-disable-next-line @typescript-eslint/no-empty-object-type 995function fixedForwardRef(render) { 996 // eslint-disable-next-line @typescript-eslint/no-explicit-any 997 return /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.forwardRef)(render); 998} 999// we need this hook to prevent a warning when using react-flow in SSR 1000const useIsomorphicLayoutEffect = typeof window !== "undefined" ? react__WEBPACK_IMPORTED_MODULE_1__.useLayoutEffect : react__WEBPACK_IMPORTED_MODULE_1__.useEffect; 1001/** 1002 * This hook returns a queue that can be used to batch updates. 1003 * 1004 * @param runQueue - a function that gets called when the queue is flushed 1005 * @internal 1006 * 1007 * @returns a Queue object 1008 */ function useQueue(runQueue) { 1009 /* 1010 * Because we're using a ref above, we need some way to let React know when to 1011 * actually process the queue. We increment this number any time we mutate the 1012 * queue, creating a new state to trigger the layout effect below.
1013 * Using a boolean dirty flag here instead would lead to issues related to 1014 * automatic batching. (https://github.com/xyflow/xyflow/issues/4779) 1015 */ const [serial, setSerial] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(BigInt(0)); 1016 /* 1017 * A reference of all the batched updates to process before the next render. We 1018 * want a reference here so multiple synchronous calls to `setNodes` etc can be 1019 * batched together. 1020 */ const [queue] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(()=>createQueue(()=>setSerial((n)=>n + BigInt(1)))); 1021 /* 1022 * Layout effects are guaranteed to run before the next render which means we 1023 * shouldn't run into any issues with stale state or weird issues that come from 1024 * rendering things one frame later than expected (we used to use `setTimeout`). 1025 */ useIsomorphicLayoutEffect(()=>{ 1026 const queueItems = queue.get(); 1027 if (queueItems.length) { 1028 runQueue(queueItems); 1029 queue.reset(); 1030 } 1031 }, [ 1032 serial 1033 ]); 1034 return queue; 1035} 1036function createQueue(cb) { 1037 let queue = []; 1038 return { 1039 get: ()=>queue, 1040 reset: ()=>{ 1041 queue = []; 1042 }, 1043 push: (item)=>{ 1044 queue.push(item); 1045 cb(); 1046 } 1047 }; 1048} 1049const BatchContext = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.createContext)(null); 1050/** 1051 * This is a context provider that holds and processes the node and edge update queues 1052 * that are needed to handle setNodes, addNodes, setEdges and addEdges. 1053 * 1054 * @internal 1055 */ function BatchProvider(param) { 1056 let { children } = param; 1057 const store = useStoreApi(); 1058 const nodeQueueHandler = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)((queueItems)=>{ 1059 const { nodes = [], setNodes, hasDefaultNodes, onNodesChange, nodeLookup, fitViewQueued, onNodesChangeMiddlewareMap } = store.getState(); 1060 /* 1061 * This is essentially an `Array.reduce` in imperative clothing. Processing 1062 * this queue is a relatively hot path so we'd like to avoid the overhead of 1063 * array methods where we can. 1064 */ let next = nodes; 1065 for (const payload of queueItems){ 1066 next = typeof payload === "function" ? payload(next) : payload; 1067 } 1068 let changes = getElementsDiffChanges({ 1069 items: next, 1070 lookup: nodeLookup 1071 }); 1072 for (const middleware of onNodesChangeMiddlewareMap.values()){ 1073 changes = middleware(changes); 1074 } 1075 if (hasDefaultNodes) { 1076 setNodes(next); 1077 } 1078 // We only want to fire onNodesChange if there are changes to the nodes 1079 if (changes.length > 0) { 1080 onNodesChange === null || onNodesChange === void 0 ? void 0 : onNodesChange(changes); 1081 } else if (fitViewQueued) { 1082 // If there are no changes to the nodes, we still need to call setNodes 1083 // to trigger a re-render and fitView. 1084 window.requestAnimationFrame(()=>{ 1085 const { fitViewQueued, nodes, setNodes } = store.getState(); 1086 if (fitViewQueued) { 1087 setNodes(nodes); 1088 } 1089 }); 1090 } 1091 }, []); 1092 const nodeQueue = useQueue(nodeQueueHandler); 1093 const edgeQueueHandler = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)((queueItems)=>{ 1094 const { edges = [], setEdges, hasDefaultEdges, onEdgesChange, edgeLookup } = store.getState(); 1095 let next = edges; 1096 for (const payload of queueItems){ 1097 next = typeof payload === "function" ? payload(next) : payload; 1098 } 1099 if (hasDefaultEdges) { 1100 setEdges(next); 1101 } else if (onEdgesChange) { 1102 onEdgesChange(getElementsDiffChanges({ 1103 items: next, 1104 lookup: edgeLookup 1105 })); 1106 } 1107 }, []); 1108 const edgeQueue = useQueue(edgeQueueHandler); 1109 const value = (0,react__WEBPACK_IMPORTED_MODULE_1__.useMemo)(()=>({ 1110 nodeQueue, 1111 edgeQueue 1112 }), []); 1113 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(BatchContext.Provider, { 1114 value: value, 1115 children: children 1116 }); 1117} 1118function useBatchContext() { 1119 const batchContext = (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(BatchContext); 1120 if (!batchContext) { 1121 throw new Error("useBatchContext must be used within a BatchProvider"); 1122 } 1123 return batchContext; 1124} 1125const selector$j = (s)=>
1125!!s.panZoom; 1126/** 1127 * This hook returns a ReactFlowInstance that can be used to update nodes and edges, manipulate the viewport, or query the current state of the flow. 1128 * 1129 * @public 1130 * @example 1131 * ```jsx 1132 *import { useCallback, useState } from 'react'; 1133 *import { useReactFlow } from '@xyflow/react'; 1134 * 1135 *export function NodeCounter() { 1136 * const reactFlow = useReactFlow(); 1137 * const [count, setCount] = useState(0); 1138 * const countNodes = useCallback(() => { 1139 * setCount(reactFlow.getNodes().length); 1140 * // you need to pass it as a dependency if you are using it with useEffect or useCallback 1141 * // because at the first render, it's not initialized yet and some functions might not work. 1142 * }, [reactFlow]); 1143 * 1144 * return ( 1145 * <div> 1146 * <button onClick={countNodes}>Update count</button> 1147 * <p>There are {count} nodes in the flow.</p> 1148 * </div> 1149 * ); 1150 *} 1151 *``` 1152 */ function useReactFlow() { 1153 const viewportHelper = useViewportHelper(); 1154 const store = useStoreApi(); 1155 const batchContext = useBatchContext(); 1156 const viewportInitialized = useStore(selector$j); 1157 const generalHelper = (0,react__WEBPACK_IMPORTED_MODULE_1__.useMemo)(()=>{ 1158 const getInternalNode = (id)=>store.getState().nodeLookup.get(id); 1159 const setNodes = (payload)=>{ 1160 batchContext.nodeQueue.push(payload); 1161 }; 1162 const setEdges = (payload)=>{ 1163 batchContext.edgeQueue.push(payload); 1164 }; 1165 const getNodeRect = (node)=>{ 1166 var _nodeToUse_measured, _nodeToUse_measured1; 1167 const { nodeLookup, nodeOrigin } = store.getState(); 1168 const nodeToUse = isNode(node) ? node : nodeLookup.get(node.id); 1169 const position = nodeToUse.parentId ? (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .evaluateAbsolutePosition */ .ZB)(nodeToUse.position, nodeToUse.measured, nodeToUse.parentId, nodeLookup, nodeOrigin) : nodeToUse.position; 1170 var _nodeToUse_measured_width, _nodeToUse_measured_height; 1171 const nodeWithPosition = { 1172 ...nodeToUse, 1173 position, 1174 width: (_nodeToUse_measured_width = (_nodeToUse_measured = nodeToUse.measured) === null || _nodeToUse_measured === void 0 ? void 0 : _nodeToUse_measured.width) !== null && _nodeToUse_measured_width !== void 0 ? _nodeToUse_measured_width : nodeToUse.width, 1175 height: (_nodeToUse_measured_height = (_nodeToUse_measured1 = nodeToUse.measured) === null || _nodeToUse_measured1 === void 0 ? void 0 : _nodeToUse_measured1.height) !== null && _nodeToUse_measured_height !== void 0 ? _nodeToUse_measured_height : nodeToUse.height 1176 }; 1177 return (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .nodeToRect */ .PS)(nodeWithPosition); 1178 }; 1179 const updateNode = function(id, nodeUpdate) { 1180 let options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : { 1181 replace: false 1182 }; 1183 setNodes((prevNodes)=>prevNodes.map((node)=>{ 1184 if (node.id === id) { 1185 const nextNode = typeof nodeUpdate === "function" ? nodeUpdate(node) : nodeUpdate; 1186 return options.replace && isNode(nextNode) ? nextNode : { 1187 ...node, 1188 ...nextNode 1189 }; 1190 } 1191 return node; 1192 })); 1193 }; 1194 const updateEdge = function(id, edgeUpdate) { 1195 let options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : { 1196 replace: false 1197 }; 1198 setEdges((prevEdges)=>prevEdges.map((edge)=>{ 1199 if (edge.id === id) { 1200 const nextEdge = typeof edgeUpdate === "function" ? edgeUpdate(edge) : edgeUpdate; 1201 return options.replace && isEdge(nextEdge) ? nextEdge : { 1202 ...edge, 1203 ...nextEdge 1204 }; 1205 } 1206 return edge; 1207 })); 1208 }; 1209 return { 1210 getNodes: ()=>store.getState().nodes.map((n)=>({ 1211 ...n 1212 })), 1213 getNode: (id)=>{ 1214 var _getInternalNode; 1215 return (_getInternalNode = getInternalNode(id)) === null || _getInternalNode === void 0 ? void 0 : _getInternalNode.internals.userNode;
1216 }, 1217 getInternalNode, 1218 getEdges: ()=>{ 1219 const { edges = [] } = store.getState(); 1220 return edges.map((e)=>({ 1221 ...e 1222 })); 1223 }, 1224 getEdge: (id)=>store.getState().edgeLookup.get(id), 1225 setNodes, 1226 setEdges, 1227 addNodes: (payload)=>{ 1228 const newNodes = Array.isArray(payload) ? payload : [ 1229 payload 1230 ]; 1231 batchContext.nodeQueue.push((nodes)=>[ 1232 ...nodes, 1233 ...newNodes 1234 ]); 1235 }, 1236 addEdges: (payload)=>{ 1237 const newEdges = Array.isArray(payload) ? payload : [ 1238 payload 1239 ]; 1240 batchContext.edgeQueue.push((edges)=>[ 1241 ...edges, 1242 ...newEdges 1243 ]); 1244 }, 1245 toObject: ()=>{ 1246 const { nodes = [], edges = [], transform } = store.getState(); 1247 const [x, y, zoom] = transform; 1248 return { 1249 nodes: nodes.map((n)=>({ 1250 ...n 1251 })), 1252 edges: edges.map((e)=>({ 1253 ...e 1254 })), 1255 viewport: { 1256 x, 1257 y, 1258 zoom 1259 } 1260 }; 1261 }, 1262 deleteElements: async (param)=>{ 1263 let { nodes: nodesToRemove = [], edges: edgesToRemove = [] } = param; 1264 const { nodes, edges, onNodesDelete, onEdgesDelete, triggerNodeChanges, triggerEdgeChanges, onDelete, onBeforeDelete } = store.getState(); 1265 const { nodes: matchingNodes, edges: matchingEdges } = await (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getElementsToRemove */ .WD)({ 1266 nodesToRemove, 1267 edgesToRemove, 1268 nodes, 1269 edges, 1270 onBeforeDelete 1271 }); 1272 const hasMatchingEdges = matchingEdges.length > 0; 1273 const hasMatchingNodes = matchingNodes.length > 0; 1274 if (hasMatchingEdges) { 1275 const edgeChanges = matchingEdges.map(elementToRemoveChange); 1276 onEdgesDelete === null || onEdgesDelete === void 0 ? void 0 : onEdgesDelete(matchingEdges); 1277 triggerEdgeChanges(edgeChanges); 1278 } 1279 if (hasMatchingNodes) { 1280 const nodeChanges = matchingNodes.map(elementToRemoveChange); 1281 onNodesDelete === null || onNodesDelete === void 0 ? void 0 : onNodesDelete(matchingNodes); 1282 triggerNodeChanges(nodeChanges); 1283 } 1284 if (hasMatchingNodes || hasMatchingEdges) { 1285 onDelete === null || onDelete === void 0 ? void 0 : onDelete({ 1286 nodes: matchingNodes, 1287 edges: matchingEdges 1288 }); 1289 } 1290 return { 1291 deletedNodes: matchingNodes, 1292 deletedEdges: matchingEdges 1293 }; 1294 }, 1295 /** 1296 * Partial is defined as "the 2 nodes/areas are intersecting partially". 1297 * If a is contained in b or b is contained in a, they are both 1298 * considered fully intersecting. 1299 */ getIntersectingNodes: function(nodeOrRect) { 1300 let partially = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : true, nodes = arguments.length > 2 ? arguments[2] : void 0; 1301 const isRect = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .isRectObject */ .J$)(nodeOrRect); 1302 const nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect); 1303 const hasNodesOption = nodes !== undefined; 1304 if (!nodeRect) { 1305 return []; 1306 } 1307 return (nodes || store.getState().nodes).filter((n)=>{ 1308 const internalNode = store.getState().nodeLookup.get(n.id); 1309 if (internalNode && !isRect && (n.id === nodeOrRect.id || !internalNode.internals.positionAbsolute)) { 1310 return false;
1311 } 1312 const currNodeRect = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .nodeToRect */ .PS)(hasNodesOption ? n : internalNode); 1313 const overlappingArea = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getOverlappingArea */ .lp)(currNodeRect, nodeRect); 1314 const partiallyVisible = partially && overlappingArea > 0; 1315 return partiallyVisible || overlappingArea >= currNodeRect.width * currNodeRect.height || overlappingArea >= nodeRect.width * nodeRect.height; 1316 }); 1317 }, 1318 isNodeIntersecting: function(nodeOrRect, area) { 1319 let partially = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : true; 1320 const isRect = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .isRectObject */ .J$)(nodeOrRect); 1321 const nodeRect = isRect ? nodeOrRect : getNodeRect(nodeOrRect); 1322 if (!nodeRect) { 1323 return false; 1324 } 1325 const overlappingArea = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getOverlappingArea */ .lp)(nodeRect, area); 1326 const partiallyVisible = partially && overlappingArea > 0; 1327 return partiallyVisible || overlappingArea >= area.width * area.height || overlappingArea >= nodeRect.width * nodeRect.height; 1328 }, 1329 updateNode, 1330 updateNodeData: function(id, dataUpdate) { 1331 let options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : { 1332 replace: false 1333 }; 1334 updateNode(id, (node)=>{ 1335 const nextData = typeof dataUpdate === "function" ? dataUpdate(node) : dataUpdate; 1336 return options.replace ? { 1337 ...node, 1338 data: nextData 1339 } : { 1340 ...node, 1341 data: { 1342 ...node.data, 1343 ...nextData 1344 } 1345 }; 1346 }, options); 1347 }, 1348 updateEdge, 1349 updateEdgeData: function(id, dataUpdate) { 1350 let options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : { 1351 replace: false 1352 }; 1353 updateEdge(id, (edge)=>{ 1354 const nextData = typeof dataUpdate === "function" ? dataUpdate(edge) : dataUpdate; 1355 return options.replace ? { 1356 ...edge, 1357 data: nextData 1358 } : { 1359 ...edge, 1360 data: { 1361 ...edge.data, 1362 ...nextData 1363 } 1364 }; 1365 }, options); 1366 }, 1367 getNodesBounds: (nodes)=>{ 1368 const { nodeLookup, nodeOrigin } = store.getState(); 1369 return (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getNodesBounds */ .RX)(nodes, { 1370 nodeLookup, 1371 nodeOrigin 1372 }); 1373 }, 1374 getHandleConnections: (param)=>{ 1375 let { type, id, nodeId } = param; 1376 var _store_getState_connectionLookup_get; 1377 var _store_getState_connectionLookup_get_values; 1378 return Array.from((_store_getState_connectionLookup_get_values = (_store_getState_connectionLookup_get = store.getState().connectionLookup.get("".concat(nodeId, "-").concat(type).concat(id ? "-".concat(id) : ""))) === null || _store_getState_connectionLookup_get === void 0 ? void 0 : _store_getState_connectionLookup_get.values()) !== null && _store_getState_connectionLookup_get_values !== void 0 ? _store_getState_connectionLookup_get_values : []); 1379 }, 1380 getNodeConnections: (param)=>{ 1381 let { type, handleId, nodeId } = param; 1382 var _store_getState_connectionLookup_get; 1383 var _store_getState_connectionLookup_get_values; 1384 return Array.from((_store_getState_connectionLookup_get_values = (_store_getState_connectionLookup_get = store.getState().connectionLookup.get("".concat(nodeId).concat(type ? handleId ? "-".concat(type, "-").concat(handleId) : "-".concat(type) : ""))) === null || _store_getState_connectionLookup_get === void 0 ? void 0 : _store_getState_connectionLookup_get.values()) !== null && _store_getState_connectionLookup_get_values !== void 0 ? _store_getState_connectionLookup_get_values : []); 1385 }, 1386 fitView: async (options)=>{ 1387 var _store_getState_fitViewResolver; 1388 // We either create a new Promise or reuse the existing one 1389 // Even if fitView is called multiple times in a row, we only end up with a single Promise 1390 const fitViewResolver = (_store_getState_fitViewResolver = store.getState().fitViewResolver) !== null && _store_getState_fitViewResolver !== void 0 ? _store_getState_fitViewResolver : (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .withResolvers */ .nu)(); 1391 // We schedule a fitView by setting fitViewQueued and triggering a setNodes 1392 store.setState({ 1393 fitViewQueued: true, 1394 fitViewOptions: options, 1395 fitViewResolver 1396 }); 1397 batchContext.nodeQueue.push((nodes)=>[ 1398 ...nodes 1399 ]); 1400 return fitViewResolver.promise; 1401 } 1402 }; 1403 }, []); 1404 return (0,react__WEBPACK_IMPORTED_MODULE_1__.useMemo)(()=>{ 1405 return { 1406 ...generalHelper, 1407 ...viewportHelper, 1408 viewportInitialized 1409 }; 1410 }, [ 1411 viewportInitialized 1412 ]); 1413} 1414const selected = (item)=>item.selected; 1415const win$1 = typeof window !== "undefined" ? window : undefined; 1416/** 1417 * Hook for handling global key events. 1418 * 1419 * @internal 1420 */ function useGlobalKeyHandler(param) { 1421 let { deleteKeyCode, multiSelectionKeyCode } = param; 1422 const store = useStoreApi(); 1423 const { deleteElements } = useReactFlow(); 1424 const deleteKeyPressed = useKeyPress(deleteKeyCode, { 1425 actInsideInputWithModifier: false 1426 }); 1427 const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode, { 1428 target: win$1 1429 }); 1430 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 1431 if (deleteKeyPressed) { 1432 const { edges, nodes } = store.getState(); 1433 deleteElements({ 1434 nodes: nodes.filter(selected), 1435 edges: edges.filter(selected) 1436 }); 1437 store.setState({ 1438 nodesSelectionActive: false 1439 }); 1440 } 1441 }, [ 1442 deleteKeyPressed 1443 ]); 1444 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 1445 store.setState({ 1446 multiSelectionActive: multiSelectionKeyPressed 1447 }); 1448 }, [ 1449 multiSelectionKeyPressed 1450 ]); 1451} 1452/** 1453 * Hook for handling resize events. 1454 * 1455 * @internal 1456 */ function useResizeHandler(domNode) { 1457 const store = useStoreApi(); 1458 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 1459 const updateDimensions = ()=>{ 1460 var _domNode_current_checkVisibility, _domNode_current; 1461 var _domNode_current_checkVisibility1; 1462 if (!domNode.current || !((_domNode_current_checkVisibility1 = (_domNode_current_checkVisibility = (_domNode_current = domNode.current).checkVisibility) === null || _domNode_current_checkVisibility === void 0 ? void 0 : _domNode_current_checkVisibility.call(_domNode_current)) !== null && _domNode_current_checkVisibility1 !== void 0 ? _domNode_current_checkVisibility1 : true)) { 1463 return false;
1464 } 1465 const size = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getDimensions */ .t_)(domNode.current); 1466 if (size.height === 0 || size.width === 0) { 1467 var _store_getState_onError, _store_getState; 1468 (_store_getState_onError = (_store_getState = store.getState()).onError) === null || _store_getState_onError === void 0 ? void 0 : _store_getState_onError.call(_store_getState, "004", _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .errorMessages */ .Qj["error004"]()); 1469 } 1470 store.setState({ 1471 width: size.width || 500, 1472 height: size.height || 500 1473 }); 1474 }; 1475 if (domNode.current) { 1476 updateDimensions(); 1477 window.addEventListener("resize", updateDimensions); 1478 const resizeObserver = new ResizeObserver(()=>updateDimensions()); 1479 resizeObserver.observe(domNode.current); 1480 return ()=>{ 1481 window.removeEventListener("resize", updateDimensions); 1482 if (resizeObserver && domNode.current) { 1483 resizeObserver.unobserve(domNode.current); 1484 } 1485 }; 1486 } 1487 }, []); 1488} 1489const containerStyle = { 1490 position: "absolute", 1491 width: "100%", 1492 height: "100%", 1493 top: 0, 1494 left: 0 1495}; 1496const selector$i = (s)=>({ 1497 userSelectionActive: s.userSelectionActive, 1498 lib: s.lib, 1499 connectionInProgress: s.connection.inProgress 1500 }); 1501function ZoomPane(param) { 1502 let { onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true, panOnScroll = false, panOnScrollSpeed = 0.5, panOnScrollMode = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .PanOnScrollMode */ .IY.Free, zoomOnDoubleClick = true, panOnDrag = true, defaultViewport, translateExtent, minZoom, maxZoom, zoomActivationKeyCode, preventScrolling = true, children, noWheelClassName, noPanClassName, onViewportChange, isControlledViewport, paneClickDistance, selectionOnDrag } = param; 1503 const store = useStoreApi(); 1504 const zoomPane = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null); 1505 const { userSelectionActive, lib, connectionInProgress } = useStore(selector$i, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 1506 const zoomActivationKeyPressed = useKeyPress(zoomActivationKeyCode); 1507 const panZoom = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(); 1508 useResizeHandler(zoomPane); 1509 const onTransformChange = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)((transform)=>{ 1510 onViewportChange === null || onViewportChange === void 0 ? void 0 : onViewportChange({ 1511 x: transform[0], 1512 y: transform[1], 1513 zoom: transform[2] 1514 }); 1515 if (!isControlledViewport) { 1516 store.setState({ 1517 transform 1518 }); 1519 } 1520 }, [ 1521 onViewportChange, 1522 isControlledViewport 1523 ]); 1524 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 1525 if (zoomPane.current) { 1526 panZoom.current = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .XYPanZoom */ .X6)({ 1527 domNode: zoomPane.current, 1528 minZoom, 1529 maxZoom, 1530 translateExtent, 1531 viewport: defaultViewport, 1532 onDraggingChange: (paneDragging)=>store.setState((prevState)=>prevState.paneDragging === paneDragging ? prevState : { 1533 paneDragging 1534 }), 1535 onPanZoomStart: (event, vp)=>{ 1536 const { onViewportChangeStart, onMoveStart } = store.getState(); 1537 onMoveStart === null || onMoveStart === void 0 ? void 0 : onMoveStart(event, vp); 1538 onViewportChangeStart === null || onViewportChangeStart === void 0 ? void 0 : onViewportChangeStart(vp); 1539 }, 1540 onPanZoom: (event, vp)=>{ 1541 const { onViewportChange, onMove } = store.getState(); 1542 onMove === null || onMove === void 0 ? void 0 : onMove(event, vp); 1543 onViewportChange === null || onViewportChange === void 0 ? void 0 : onViewportChange(vp); 1544 }, 1545 onPanZoomEnd: (event, vp)=>{ 1546 const { onViewportChangeEnd, onMoveEnd } = store.getState(); 1547 onMoveEnd === null || onMoveEnd === void 0 ? void 0 : onMoveEnd(event, vp); 1548 onViewportChangeEnd === null || onViewportChangeEnd === void 0 ? void 0 : onViewportChangeEnd(vp); 1549 } 1550 }); 1551 const { x, y, zoom } = panZoom.current.getViewport(); 1552 store.setState({ 1553 panZoom: panZoom.current, 1554 transform: [ 1555 x, 1556 y, 1557 zoom 1558 ], 1559 domNode: zoomPane.current.closest(".react-flow") 1560 }); 1561 return ()=>{ 1562 var _panZoom_current; 1563 (_panZoom_current = panZoom.current) === null || _panZoom_current === void 0 ? void 0 : _panZ
1563oom_current.destroy(); 1564 }; 1565 } 1566 }, []); 1567 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 1568 var _panZoom_current; 1569 (_panZoom_current = panZoom.current) === null || _panZoom_current === void 0 ? void 0 : _panZoom_current.update({ 1570 onPaneContextMenu, 1571 zoomOnScroll, 1572 zoomOnPinch, 1573 panOnScroll, 1574 panOnScrollSpeed, 1575 panOnScrollMode, 1576 zoomOnDoubleClick, 1577 panOnDrag, 1578 zoomActivationKeyPressed, 1579 preventScrolling, 1580 noPanClassName, 1581 userSelectionActive, 1582 noWheelClassName, 1583 lib, 1584 onTransformChange, 1585 connectionInProgress, 1586 selectionOnDrag, 1587 paneClickDistance 1588 }); 1589 }, [ 1590 onPaneContextMenu, 1591 zoomOnScroll, 1592 zoomOnPinch, 1593 panOnScroll, 1594 panOnScrollSpeed, 1595 panOnScrollMode, 1596 zoomOnDoubleClick, 1597 panOnDrag, 1598 zoomActivationKeyPressed, 1599 preventScrolling, 1600 noPanClassName, 1601 userSelectionActive, 1602 noWheelClassName, 1603 lib, 1604 onTransformChange, 1605 connectionInProgress, 1606 selectionOnDrag, 1607 paneClickDistance 1608 ]); 1609 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 1610 className: "react-flow__renderer", 1611 ref: zoomPane, 1612 style: containerStyle, 1613 children: children 1614 }); 1615} 1616const selector$h = (s)=>({ 1617 userSelectionActive: s.userSelectionActive, 1618 userSelectionRect: s.userSelectionRect 1619 }); 1620function UserSelection() { 1621 const { userSelectionActive, userSelectionRect } = useStore(selector$h, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 1622 const isActive = userSelectionActive && userSelectionRect; 1623 if (!isActive) { 1624 return null; 1625 } 1626 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 1627 className: "react-flow__selection react-flow__container", 1628 style: { 1629 width: userSelectionRect.width, 1630 height: userSelectionRect.height, 1631 transform: "translate(".concat(userSelectionRect.x, "px, ").concat(userSelectionRect.y, "px)") 1632 } 1633 }); 1634} 1635const wrapHandler = (handler, containerRef)=>{ 1636 return (event)=>{ 1637 if (event.target !== containerRef.current) { 1638 return; 1639 } 1640 handler === null || handler === void 0 ? void 0 : handler(event); 1641 }; 1642}; 1643const selector$g = (s)=>({ 1644 userSelectionActive: s.userSelectionActive, 1645 elementsSelectable: s.elementsSelectable, 1646 dragging: s.paneDragging, 1647 panBy: s.panBy, 1648 autoPanSpeed: s.autoPanSpeed 1649 }); 1650function Pane(param) { 1651 let { isSelecting, selectionKeyPressed, selectionMode = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .SelectionMode */ .oW.Full, panOnDrag, autoPanOnSelection, paneClickDistance, selectionOnDrag, onSelectionStart, onSelectionEnd, onPaneClick, onPaneContextMenu, onPaneScroll, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, children } = param; 1652 const autoPanId = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(0); 1653 const store = useStoreApi(); 1654 const { userSelectionActive, elementsSelectable, dragging, panBy, autoPanSpeed } = useStore(selector$g, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 1655 const isSelectionEnabled = elementsSelectable && (isSelecting || userSelectionActive); 1656 const container = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null); 1657 const containerBounds = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(); 1658 const selectedNodeIds = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(new Set()); 1659 const selectedEdgeIds = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(new Set()); 1660 const connectionEndedOnPane = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(false); 1661 // Used to prevent click events when the user lets go of the selectionKey during a selection 1662 const selectionInProgress = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(false); 1663 // Used for auto pan when approaching the edges of the container during selection 1664 const position = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)({ 1665 x: 0, 1666 y: 0 1667 }); 1668 const autoPanStarted = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(false); 1669 const onClick = (event)=>{ 1670 // We prevent click events when the user let go of the selectionKey during a selection 1671 // We also prevent click events when a connection is in progress 1672 if (selectionInProgress.current || connectionEndedOnPane.current || store.getState().connection.inProgress) { 1673 selectionInProgress.current = false;
1674 connectionEndedOnPane.current = false; 1675 return; 1676 } 1677 onPaneClick === null || onPaneClick === void 0 ? void 0 : onPaneClick(event); 1678 store.getState().resetSelectedElements(); 1679 store.setState({ 1680 nodesSelectionActive: false 1681 }); 1682 }; 1683 const onContextMenu = (event)=>{ 1684 if (Array.isArray(panOnDrag) && (panOnDrag === null || panOnDrag === void 0 ? void 0 : panOnDrag.includes(2))) { 1685 event.preventDefault(); 1686 return; 1687 } 1688 onPaneContextMenu === null || onPaneContextMenu === void 0 ? void 0 : onPaneContextMenu(event); 1689 }; 1690 const onWheel = onPaneScroll ? (event)=>onPaneScroll(event) : undefined; 1691 const onClickCapture = (event)=>{ 1692 if (selectionInProgress.current) { 1693 event.stopPropagation(); 1694 selectionInProgress.current = false; 1695 } 1696 }; 1697 // We are using capture here in order to prevent other pointer events 1698 // to be able to create a selection above a node or an edge 1699 const onPointerDownCapture = (event)=>{ 1700 var _event_target_setPointerCapture, _event_target; 1701 const { domNode, transform } = store.getState(); 1702 containerBounds.current = domNode === null || domNode === void 0 ? void 0 : domNode.getBoundingClientRect(); 1703 if (!containerBounds.current) return; 1704 const eventTargetIsContainer = event.target === container.current; 1705 // if a child element has the 'nokey' class, we don't want to swallow the event and don't start a selection 1706 const isNoKeyEvent = !eventTargetIsContainer && !!event.target.closest(".nokey"); 1707 const isSelectionActive = selectionOnDrag && eventTargetIsContainer || selectionKeyPressed; 1708 if (isNoKeyEvent || !isSelecting || !isSelectionActive || event.button !== 0 || !event.isPrimary) { 1709 return; 1710 } 1711 (_event_target = event.target) === null || _event_target === void 0 ? void 0 : (_event_target_setPointerCapture = _event_target.setPointerCapture) === null || _event_target_setPointerCapture === void 0 ? void 0 : _event_target_setPointerCapture.call(_event_target, event.pointerId); 1712 selectionInProgress.current = false; 1713 const { x, y } = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getEventPosition */ .wv)(event.nativeEvent, containerBounds.current); 1714 const userSelectionStartPosition = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .pointToRendererPoint */ .m)({ 1715 x, 1716 y 1717 }, transform); 1718 store.setState({ 1719 userSelectionRect: { 1720 width: 0, 1721 height: 0, 1722 startX: userSelectionStartPosition.x, 1723 startY: userSelectionStartPosition.y, 1724 x, 1725 y 1726 } 1727 }); 1728 if (!eventTargetIsContainer) { 1729 event.stopPropagation(); 1730 event.preventDefault(); 1731 } 1732 }; 1733 // We commit the user selection rectangle to the store on auto-panning or pointer move during selection. 1734 function commitUserSelectionRect(mouseX, mouseY) { 1735 const { userSelectionRect } = store.getState(); 1736 if (!userSelectionRect) { 1737 return; 1738 } 1739 const { transform, nodeLookup, edgeLookup, connectionLookup, triggerNodeChanges, triggerEdgeChanges, defaultEdgeOptions } = store.getState(); 1740 const userStartPosition = { 1741 x: userSelectionRect.startX, 1742 y: userSelectionRect.startY 1743 }; 1744 const { x: screenStartX, y: screenStartY } = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .rendererPointToPoint */ .oj)(userStartPosition, transform); 1745 // This has to be in screen coordinates, not in flow coordinates. 1746 // We store the selection rectangle in userSelectionStartPosition coordinates to be able to 1747 // fix the start position of the selection rectangle when we are auto-panning. 1748 const nextUserSelectRect = { 1749 startX: userStartPosition.x, 1750 startY: userStartPosition.y, 1751 x: mouseX < screenStartX ? mouseX : screenStartX, 1752 y: mouseY < screenStartY ? mouseY : screenStartY, 1753 width: Math.abs(mouseX - screenStartX), 1754 height: Math.abs(mouseY - screenStartY) 1755 }; 1756 const prevSelectedNodeIds = selectedNodeIds.current; 1757 const prevSelectedEdgeIds = selectedEdgeIds.current; 1758 selectedNodeIds.current = new Set((0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getNodesInside */ .f5)(nodeLookup, nextUserSelectRect, transform, selectionMode === _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .SelectionMode */ .oW.Partial, true).map((node)=>node.id)); 1759 selectedEdgeIds.current = new Set(); 1760 var _defaultEdgeOptions_selectable; 1761 const edgesSelectable = (_defaultEdgeOptions_selectable = defaultEdgeOptions === null || defaultEdgeOptions === void 0 ? void 0 : defaultEdgeOptions.selectable) !== null && _defaultEdgeOptions_selectable !== void 0 ? _defaultEdgeOptions_selectable : true; 1762 // We look for all edges connected to the selected nodes 1763 for (const nodeId of selectedNodeIds.current){ 1764 const connections = connectionLookup.get(nodeId); 1765 if (!connections) continue; 1766 for (const { edgeId } of connections.values()){ 1767 const edge = edgeLookup.get(edgeId); 1768 var _edge_selectable; 1769 if (edge && ((_edge_selectable = edge.selectable) !== null && _edge_selectable !== void 0 ? _edge_selectable : edgesSelectable)) { 1770 selectedEdgeIds.current.add(edgeId); 1771 } 1772 } 1773 } 1774 if (!(0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .areSetsEqual */ .OL)(prevSelectedNodeIds, selectedNodeIds.current)) { 1775 const changes = getSelectionChanges(nodeLookup, selectedNodeIds.current, true); 1776 triggerNodeChanges(changes); 1777 } 1778 if (!(0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .areSetsEqual */ .OL)(prevSelectedEdgeIds, selectedEdgeIds.current)) { 1779 const changes = getSelectionChanges(edgeLookup, selectedEdgeIds.current); 1780 triggerEdgeChanges(changes); 1781 } 1782 store.setState({ 1783 userSelectionRect: nextUserSelectRect, 1784 userSelectionActive: true, 1785 nodesSelectionActive: false 1786 }); 1787 } 1788 function autoPan() { 1789 if (!autoPanOnSelection || !containerBounds.current) { 1790 return; 1791 } 1792 const [x, y] = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .calcAutoPan */ .U)(position.current, containerBounds.current, autoPanSpeed); 1793 panBy({ 1794 x, 1795 y 1796 }).then((panned)=>{ 1797 if (!selectionInProgress.current || !panned) { 1798 autoPanId.current = requestAnimationFrame(autoPan); 1799 return; 1800 } 1801 const { x: mx, y: my } = position.current; 1802 commitUserSelectionRect(mx, my); 1803 autoPanId.current = requestAnimationFrame(autoPan); 1804 }); 1805 } 1806 const cleanupAutoPan = ()=>{ 1807 cancelAnimationFrame(autoPanId.current); 1808 autoPanId.current = 0; 1809 autoPanStarted.current = false;
1810 }; 1811 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 1812 return ()=>cleanupAutoPan(); 1813 }, []); 1814 const onPointerMove = (event)=>{ 1815 const { userSelectionRect, transform, resetSelectedElements } = store.getState(); 1816 if (!containerBounds.current || !userSelectionRect) { 1817 return; 1818 } 1819 const { x: mouseX, y: mouseY } = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getEventPosition */ .wv)(event.nativeEvent, containerBounds.current); 1820 position.current = { 1821 x: mouseX, 1822 y: mouseY 1823 }; 1824 const screenStart = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .rendererPointToPoint */ .oj)({ 1825 x: userSelectionRect.startX, 1826 y: userSelectionRect.startY 1827 }, transform); 1828 if (!selectionInProgress.current) { 1829 const requiredDistance = selectionKeyPressed ? 0 : paneClickDistance; 1830 const distance = Math.hypot(mouseX - screenStart.x, mouseY - screenStart.y); 1831 if (distance <= requiredDistance) { 1832 return; 1833 } 1834 resetSelectedElements(); 1835 onSelectionStart === null || onSelectionStart === void 0 ? void 0 : onSelectionStart(event); 1836 } 1837 selectionInProgress.current = true; 1838 if (!autoPanStarted.current) { 1839 autoPan(); 1840 autoPanStarted.current = true; 1841 } 1842 commitUserSelectionRect(mouseX, mouseY); 1843 }; 1844 const onPointerUp = (event)=>{ 1845 var _event_target_releasePointerCapture, _event_target; 1846 if (!isSelectionEnabled) { 1847 if (event.target === container.current && store.getState().connection.inProgress) { 1848 connectionEndedOnPane.current = true; 1849 } 1850 return; 1851 } 1852 if (event.button !== 0) { 1853 return; 1854 } 1855 (_event_target = event.target) === null || _event_target === void 0 ? void 0 : (_event_target_releasePointerCapture = _event_target.releasePointerCapture) === null || _event_target_releasePointerCapture === void 0 ? void 0 : _event_target_releasePointerCapture.call(_event_target, event.pointerId); 1856 /* 1857 * We only want to trigger click functions when in selection mode if 1858 * the user did not move the mouse. 1859 */ if (!userSelectionActive && event.target === container.current && store.getState().userSelectionRect) { 1860 onClick === null || onClick === void 0 ? void 0 : onClick(event); 1861 } 1862 store.setState({ 1863 userSelectionActive: false, 1864 userSelectionRect: null 1865 }); 1866 if (selectionInProgress.current) { 1867 onSelectionEnd === null || onSelectionEnd === void 0 ? void 0 : onSelectionEnd(event); 1868 store.setState({ 1869 nodesSelectionActive: selectedNodeIds.current.size > 0 1870 }); 1871 } 1872 cleanupAutoPan(); 1873 }; 1874 const onPointerCancel = (event)=>{ 1875 var _event_target_releasePointerCapture, _event_target; 1876 (_event_target = event.target) === null || _event_target === void 0 ? void 0 : (_event_target_releasePointerCapture = _event_target.releasePointerCapture) === null || _event_target_releasePointerCapture === void 0 ? void 0 : _event_target_releasePointerCapture.call(_event_target, event.pointerId); 1877 cleanupAutoPan(); 1878 }; 1879 const draggable = panOnDrag === true || Array.isArray(panOnDrag) && panOnDrag.includes(0); 1880 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", { 1881 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 1882 "react-flow__pane", 1883 { 1884 draggable, 1885 dragging, 1886 selection: isSelecting 1887 } 1888 ]), 1889 onClick: isSelectionEnabled ? undefined : wrapHandler(onClick, container), 1890 onContextMenu: wrapHandler(onContextMenu, container), 1891 onWheel: wrapHandler(onWheel, container), 1892 onPointerEnter: isSelectionEnabled ? undefined : onPaneMouseEnter, 1893 onPointerMove: isSelectionEnabled ? onPointerMove : onPaneMouseMove, 1894 onPointerUp: onPointerUp, 1895 onPointerCancel: isSelectionEnabled ? onPointerCancel : undefined, 1896 onPointerDownCapture: isSelectionEnabled ? onPointerDownCapture : undefined, 1897 onClickCapture: isSelectionEnabled ? onClickCapture : undefined, 1898 onPointerLeave: onPaneMouseLeave, 1899 ref: container, 1900 style: containerStyle, 1901 children: [ 1902 children, 1903 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(UserSelection, {}) 1904 ] 1905 }); 1906} 1907/* 1908 * this handler is called by 1909 * 1. the click handler when node is not draggable or selectNodesOnDrag = false 1910 * or 1911 * 2. the on drag start handler when node is draggable and selectNodesOnDrag = true 1912 */ function handleNodeClick(param) { 1913 let { id, store, unselect = false, nodeRef } = param; 1914 const { addSelectedNodes, unselectNodesAndEdges, multiSelectionActive, nodeLookup, onError } = store.getState(); 1915 const node = nodeLookup.get(id); 1916 if (!node) { 1917 onError === null || onError === void 0 ? void 0 : onError("012", _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .errorMessages */ .Qj["error012"](id)); 1918 return; 1919 } 1920 store.setState({ 1921 nodesSelectionActive: false 1922 }); 1923 if (!node.selected) { 1924 addSelectedNodes([ 1925 id 1926 ]); 1927 } else if (unselect || node.selected && multiSelectionActive) { 1928 unselectNodesAndEdges({ 1929 nodes: [ 1930 node 1931 ], 1932 edges: [] 1933 }); 1934 requestAnimationFrame(()=>{ 1935 var _nodeRef_current; 1936 return nodeRef === null || nodeRef === void 0 ? void 0 : (_nodeRef_current = nodeRef.current) === null || _nodeRef_current === void 0 ? void 0 : _nodeRef_current.blur(); 1937 }); 1938 } 1939} 1940/** 1941 * Hook for calling XYDrag helper from @xyflow/system. 1942 * 1943 * @internal 1944 */ function useDrag(param) { 1945 let { nodeRef, disabled = false, noDragClassName, handleSelector, nodeId, isSelectable, nodeClickDistance } = param; 1946 const store = useStoreApi(); 1947 const [dragging, setDragging] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(false); 1948 const xyDrag = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(); 1949 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 1950 if (disabled) { 1951 return; 1952 } 1953 xyDrag.current = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .XYDrag */ .oC)({ 1954 getStoreItems: ()=>store.getState(), 1955 onNodeMouseDown: (id)=>{ 1956 handleNodeClick({ 1957 id, 1958 store, 1959 nodeRef 1960 }); 1961 }, 1962 onDragStart: ()=>{ 1963 setDragging(true); 1964 }, 1965 onDragStop: ()=>{ 1966 setDragging(false); 1967 } 1968 }); 1969 return ()=>{ 1970 var _xyDrag_current; 1971 (_xyDrag_current = xyDrag.current) === null || _xyDrag_current === void 0 ? void 0 : _xyDrag_current.destroy(); 1972 xyDrag.current = undefined; 1973 }; 1974 }, [ 1975 disabled, 1976 store, 1977 nodeRef 1978 ]); 1979 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 1980 if (disabled || !nodeRef.current || !xyDrag.current) { 1981 return; 1982 } 1983 xyDrag.current.update({ 1984 noDragClassName, 1985 handleSelector, 1986 domNode: nodeRef.current, 1987 isSelectable, 1988 nodeId, 1989 nodeClickDistance 1990 }); 1991 }, [ 1992 noDragClassName, 1993 handleSelector, 1994 disabled, 1995 isSelectable, 1996 nodeRef, 1997 nodeId, 1998 nodeClickDistance 1999 ]); 2000 return dragging; 2001} 2002const selectedAndDraggable = (nodesDraggable)=>(n)=>n.selected && (n.draggable || nodesDraggable && typeof n.draggable === "undefined"); 2003/** 2004 * Hook for updating node positions by passing a direction and factor 2005 * 2006 * @internal 2007 * @returns function for updating node positions 2008 */ function useMoveSelectedNodes() { 2009 const store = useStoreApi(); 2010 const moveSelectedNodes = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)((params)=>{
2011 const { nodeExtent, snapToGrid, snapGrid, nodesDraggable, onError, updateNodePositions, nodeLookup, nodeOrigin } = store.getState(); 2012 const nodeUpdates = new Map(); 2013 const isSelected = selectedAndDraggable(nodesDraggable); 2014 /* 2015 * by default a node moves 5px on each key press 2016 * if snap grid is enabled, we use that for the velocity 2017 */ const xVelo = snapToGrid ? snapGrid[0] : 5; 2018 const yVelo = snapToGrid ? snapGrid[1] : 5; 2019 const xDiff = params.direction.x * xVelo * params.factor; 2020 const yDiff = params.direction.y * yVelo * params.factor; 2021 for (const [, node] of nodeLookup){ 2022 if (!isSelected(node)) { 2023 continue; 2024 } 2025 let nextPosition = { 2026 x: node.internals.positionAbsolute.x + xDiff, 2027 y: node.internals.positionAbsolute.y + yDiff 2028 }; 2029 if (snapToGrid) { 2030 nextPosition = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .snapPosition */ ._2)(nextPosition, snapGrid); 2031 } 2032 const { position, positionAbsolute } = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .calculateNodePosition */ .q7)({ 2033 nodeId: node.id, 2034 nextPosition, 2035 nodeLookup, 2036 nodeExtent, 2037 nodeOrigin, 2038 onError 2039 }); 2040 node.position = position; 2041 node.internals.positionAbsolute = positionAbsolute; 2042 nodeUpdates.set(node.id, node); 2043 } 2044 updateNodePositions(nodeUpdates); 2045 }, []); 2046 return moveSelectedNodes; 2047} 2048const NodeIdContext = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.createContext)(null); 2049const Provider = NodeIdContext.Provider; 2050NodeIdContext.Consumer; 2051/** 2052 * You can use this hook to get the id of the node it is used inside. It is useful 2053 * if you need the node's id deeper in the render tree but don't want to manually 2054 * drill down the id as a prop. 2055 * 2056 * @public 2057 * @returns The id for a node in the flow. 2058 * 2059 * @example 2060 *```jsx 2061 *import { useNodeId } from '@xyflow/react'; 2062 * 2063 *export default function CustomNode() { 2064 * return ( 2065 * <div> 2066 * <span>This node has an id of </span> 2067 * <NodeIdDisplay /> 2068 * </div> 2069 * ); 2070 *} 2071 * 2072 *function NodeIdDisplay() { 2073 * const nodeId = useNodeId(); 2074 * 2075 * return <span>{nodeId}</span>; 2076 *} 2077 *``` 2078 */ const useNodeId = ()=>{ 2079 const nodeId = (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(NodeIdContext); 2080 return nodeId; 2081}; 2082const selector$f = (s)=>({ 2083 connectOnClick: s.connectOnClick, 2084 noPanClassName: s.noPanClassName, 2085 rfId: s.rfId 2086 }); 2087const HandleConfigContext = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.createContext)(null); 2088/* 2089 * `connectOnClick`, `noPanClassName` and `rfId` are the same for every handle, so they are 2090 * shared through context from a single store subscription. 2091 */ function HandleConfigProvider(param) { 2092 let { children } = param; 2093 const config = useStore(selector$f, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 2094 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(HandleConfigContext.Provider, { 2095 value: config, 2096 children: children 2097 }); 2098} 2099function useHandleConfig() { 2100 const config = (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(HandleConfigContext); 2101 if (!config) { 2102 throw new Error("useHandleConfig must be used within a HandleConfigProvider"); 2103 } 2104 return config; 2105} 2106/* 2107 * While no connection is in progress every handle has this same state, so we return a 2108 * shared reference rather than allocating + shallow-comparing one per handle on every 2109 * store update. `isPossibleEndHandle` matches what the selector computes when idle. 2110 */ const idleConnectingState = { 2111 connectingFrom: false, 2112 connectingTo: false, 2113 clickConnecting: false, 2114 isPossibleEndHandle: true, 2115 connectionInProcess: false, 2116 clickConnectionInProcess: false, 2117 valid: false 2118}; 2119const connectingSelector = (nodeId, handleId, type)=>(state)=>{ 2120 const { connectionClickStartHandle: clickHandle, connectionMode, connection } = state;
2121 const { fromHandle, toHandle, isValid } = connection; 2122 if (!fromHandle && !clickHandle) { 2123 return idleConnectingState; 2124 } 2125 const connectingTo = (toHandle === null || toHandle === void 0 ? void 0 : toHandle.nodeId) === nodeId && (toHandle === null || toHandle === void 0 ? void 0 : toHandle.id) === handleId && (toHandle === null || toHandle === void 0 ? void 0 : toHandle.type) === type; 2126 return { 2127 connectingFrom: (fromHandle === null || fromHandle === void 0 ? void 0 : fromHandle.nodeId) === nodeId && (fromHandle === null || fromHandle === void 0 ? void 0 : fromHandle.id) === handleId && (fromHandle === null || fromHandle === void 0 ? void 0 : fromHandle.type) === type, 2128 connectingTo, 2129 clickConnecting: (clickHandle === null || clickHandle === void 0 ? void 0 : clickHandle.nodeId) === nodeId && (clickHandle === null || clickHandle === void 0 ? void 0 : clickHandle.id) === handleId && (clickHandle === null || clickHandle === void 0 ? void 0 : clickHandle.type) === type, 2130 isPossibleEndHandle: connectionMode === _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .ConnectionMode */ .jD.Strict ? (fromHandle === null || fromHandle === void 0 ? void 0 : fromHandle.type) !== type : nodeId !== (fromHandle === null || fromHandle === void 0 ? void 0 : fromHandle.nodeId) || handleId !== (fromHandle === null || fromHandle === void 0 ? void 0 : fromHandle.id), 2131 connectionInProcess: !!fromHandle, 2132 clickConnectionInProcess: !!clickHandle, 2133 valid: connectingTo && isValid 2134 }; 2135 }; 2136function HandleComponent(param, ref) { 2137 let { type = "source", position = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Top, isValidConnection, isConnectable = true, isConnectableStart = true, isConnectableEnd = true, id, onConnect, children, className, onMouseDown, onTouchStart, ...rest } = param; 2138 const handleId = id || null; 2139 const isTarget = type === "target"; 2140 const store = useStoreApi(); 2141 const nodeId = useNodeId(); 2142 const { connectOnClick, noPanClassName, rfId } = useHandleConfig(); 2143 const { connectingFrom, connectingTo, clickConnecting, isPossibleEndHandle, connectionInProcess, clickConnectionInProcess, valid } = useStore(connectingSelector(nodeId, handleId, type), zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 2144 if (!nodeId) { 2145 var _store_getState_onError, _store_getState; 2146 (_store_getState_onError = (_store_getState = store.getState()).onError) === null || _store_getState_onError === void 0 ? void 0 : _store_getState_onError.call(_store_getState, "010", _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .errorMessages */ .Qj["error010"]()); 2147 } 2148 const onConnectExtended = (params)=>{ 2149 const { defaultEdgeOptions, onConnect: onConnectAction, hasDefaultEdges } = store.getState(); 2150 const edgeParams = { 2151 ...defaultEdgeOptions, 2152 ...params 2153 }; 2154 if (hasDefaultEdges) { 2155 const { edges, setEdges, onError } = store.getState(); 2156 setEdges(addEdge(edgeParams, edges, { 2157 onError 2158 })); 2159 } 2160 onConnectAction === null || onConnectAction === void 0 ? void 0 : onConnectAction(edgeParams); 2161 onConnect === null || onConnect === void 0 ? void 0 : onConnect(edgeParams); 2162 }; 2163 const onPointerDown = (event)=>{ 2164 if (!nodeId) { 2165 return; 2166 } 2167 const isMouseTriggered = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .isMouseEvent */ .N5)(event.nativeEvent); 2168 if (isConnectableStart && (isMouseTriggered && event.button === 0 || !isMouseTriggered)) { 2169 const currentStore = store.getState(); 2170 _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .XYHandle */ .Ql.onPointerDown(event.nativeEvent, { 2171 handleDomNode: event.currentTarget, 2172 autoPanOnConnect: currentStore.autoPanOnConnect, 2173 connectionMode: currentStore.connectionMode, 2174 connectionRadius: currentStore.connectionRadius, 2175 domNode: currentStore.domNode, 2176 nodeLookup: currentStore.nodeLookup, 2177 lib: currentStore.lib, 2178 isTarget, 2179 handleId, 2180 nodeId, 2181 flowId: currentStore.rfId, 2182 panBy: currentStore.panBy, 2183 cancelConnection: currentStore.cancelConnection, 2184 onConnectStart: currentStore.onConnectStart, 2185 onConnectEnd: function() { 2186 for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){ 2187 args[_key] = arguments[_key]; 2188 } 2189 var _store_getState_onConnectEnd, _store_getState; 2190 return (_store_getState_onConnectEnd = (_store_getState = store.getState()).onConnectEnd) === null || _store_getState_onConnectEnd === void 0 ? void 0 : _store_getState_onConnectEnd.call(_store_getState, ...args); 2191 }, 2192 updateConnection: currentStore.updateConnection, 2193 onConnect: onConnectExtended, 2194 isValidConnection: isValidConnection || function() { 2195 for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){ 2196 args[_key] = arguments[_key]; 2197 } 2198 var _store_getState_isValidConnection, _store_getState; 2199 var _store_getState_isValidConnection1; 2200 return (_store_getState_isValidConnection1 = (_store_getState_isValidConnection = (_store_getState = store.getState()).isValidConnection) === null || _store_getState_isValidConnection === void 0 ? void 0 : _store_getState_isValidConnection.call(_store_getState, ...args)) !== null && _store_getState_isValidConnection1 !== void 0 ? _store_getState_isValidConnection1 : true; 2201 }, 2202 getTransform: ()=>store.getState().transform, 2203 getFromHandle: ()=>store.getState().connection.fromHandle, 2204 autoPanSpeed: currentStore.autoPanSpeed, 2205 dragThreshold: currentStore.connectionDragThreshold 2206 }); 2207 } 2208 if (isMouseTriggered) { 2209 onMouseDown === null || onMouseDown === void 0 ? void 0 : onMouseDown(event); 2210 } else { 2211 onTouchStart === null || onTouchStart === void 0 ? void 0 : onTouchStart(event); 2212 } 2213 }; 2214 const onClick = (event)=>{ 2215 const { onClickConnectStart, onClickConnectEnd, connectionClickStartHandle, connectionMode, isValidConnection: isValidConnectionStore, lib, rfId: flowId, nodeLookup, connection: connectionState } = store.getState(); 2216 if (!nodeId || !connectionClickStartHandle && !isConnectableStart) { 2217 return; 2218 } 2219 if (!connectionClickStartHandle) { 2220 onClickConnectStart === null || onClickConnectStart === void 0 ? void 0 : onClickConnectStart(event.nativeEvent, { 2221 nodeId, 2222 handleId, 2223 handleType: type 2224 }); 2225 store.setState({ 2226 connectionClickStartHandle: { 2227 nodeId, 2228 type, 2229 id: handleId 2230 } 2231 }); 2232 return; 2233 } 2234 const doc = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getHostForElement */ .S2)(event.target); 2235 const isValidConnectionHandler = isValidConnection || isValidConnectionStore; 2236 const { connection, isValid } = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .XYHandle */ .Ql.isValid(event.nativeEvent, { 2237 handle: { 2238 nodeId, 2239 id: handleId, 2240 type 2241 }, 2242 connectionMode, 2243 fromNodeId: connectionClickStartHandle.nodeId, 2244 fromHandleId: connectionClickStartHandle.id || null, 2245 fromType: connectionClickStartHandle.type, 2246 isValidConnection: isValidConnectionHandler, 2247 flowId, 2248 doc, 2249 lib, 2250 nodeLookup 2251 }); 2252 if (isValid && connection) { 2253 onConnectExtended(connection); 2254 } 2255 const connectionClone = structuredClone(connectionState); 2256 delete connectionClone.inProgress; 2257 connectionClone.toPosition = connectionClone.toHandle ? connectionClone.toHandle.position : null; 2258 onClickConnectEnd === null || onClickConnectEnd === void 0 ? void 0 : onClickConnectEnd(event, connectionClone); 2259 store.setState({ 2260 connectionClickStartHandle: null 2261 }); 2262 }; 2263 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 2264 "data-handleid": handleId, 2265 "data-nodeid": nodeId, 2266 "data-handlepos": position, 2267 "data-id": "".concat(rfId, "-").concat(nodeId, "-").concat(handleId, "-").concat(type), 2268 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 2269 "react-flow__handle", 2270 "react-flow__handle-".concat(position), 2271 "nodrag", 2272 noPanClassName, 2273 className, 2274 { 2275 source: !isTarget, 2276 target: isTarget, 2277 connectable: isConnectable, 2278 connectablestart: isConnectableStart, 2279 connectableend: isConnectableEnd, 2280 clickconnecting: clickConnecting, 2281 connectingfrom: connectingFrom, 2282 connectingto: connectingTo, 2283 valid, 2284 /* 2285 * shows where you can start a connection from 2286 * and where you can end it while connecting 2287 */ connectionindicator: isConnectable && (!connectionInProcess || isPossibleEndHandle) && (connectionInProcess || clickConnectionInProcess ? isConnectableEnd : isConnectableStart) 2288 } 2289 ]), 2290 onMouseDown: onPointerDown, 2291 onTouchStart: onPointerDown, 2292 onClick: connectOnClick ? onClick : undefined, 2293 ref: ref, 2294 ...rest, 2295 children: children 2296 }); 2297} 2298/** 2299 * The `<Handle />` component is used in your [custom nodes](/learn/customization/custom-nodes) 2300 * to define connection points. 2301 * 2302 *@public 2303 * 2304 *@example 2305 * 2306 *```jsx 2307 *import { Handle, Position } from '@xyflow/react'; 2308 * 2309 *export function CustomNode({ data }) { 2310 * return ( 2311 * <> 2312 * <div style={{ padding: '10px 20px' }}> 2313 * {data.label} 2314 * </div> 2315 * 2316 * <Handle type="target" position={Position.Left} /> 2317 * <Handle type="source" position={Position.Right} /> 2318 * </> 2319 * ); 2320 *}; 2321 *``` 2322 */ const Handle = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(fixedForwardRef(HandleComponent)); 2323function InputNode(param) { 2324 let { data, isConnectable, sourcePosition = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Bottom } = param; 2325 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, { 2326 children: [ 2327 data === null || data === void 0 ? void 0 : data.label, 2328 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(Handle, { 2329 type: "source", 2330 position: sourcePosition, 2331 isConnectable: isConnectable 2332 }) 2333 ] 2334 }); 2335} 2336function DefaultNode(param) { 2337 let { data, isConnectable, targetPosition = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Top, sourcePosition = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Bottom } = param; 2338 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, { 2339 children: [ 2340 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(Handle, { 2341 type: "target", 2342 position: targetPosition, 2343 isConnectable: isConnectable 2344 }), 2345 data === null || data === void 0 ? void 0 : data.label, 2346 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(Handle, { 2347 type: "source", 2348 position: sourcePosition, 2349 isConnectable: isConnectable 2350 }) 2351 ] 2352 }); 2353} 2354function GroupNode() { 2355 return null; 2356} 2357function OutputNode(param) { 2358 let { data, isConnectable, targetPosition = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Top } = param; 2359 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, { 2360 children: [ 2361 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(Handle, { 2362 type: "target", 2363 position: targetPosition, 2364 isConnectable: isConnectable 2365 }), 2366 data === null || data === void 0 ? void 0 : data.label 2367 ] 2368 }); 2369} 2370const arrowKeyDiffs = { 2371 ArrowUp: { 2372 x: 0, 2373 y: -1 2374 }, 2375 ArrowDown: { 2376 x: 0, 2377 y: 1 2378 }, 2379 ArrowLeft: { 2380 x: -1, 2381 y: 0 2382 }, 2383 ArrowRight: { 2384 x: 1, 2385 y: 0 2386 } 2387}; 2388const builtinNodeTypes = { 2389 input: InputNode, 2390 default: DefaultNode, 2391 output: OutputNode, 2392 group: GroupNode 2393}; 2394function getNodeInlineStyleDimensions(node) { 2395 var _node_style, _node_style1; 2396 if (node.internals.handleBounds === undefined) { 2397 var _node_style2, _node_style3; 2398 var _node_width, _ref, _node_height, _ref1; 2399 return { 2400 width: (_ref = (_node_width = node.width) !== null && _node_width !== void 0 ? _node_width : node.initialWidth) !== null && _ref !== void 0 ? _ref : (_node_style2 = node.style) === null || _node_style2 === void 0 ? void 0 : _node_style2.width, 2401 height: (_ref1 = (_node_height = node.height) !== null && _node_height !== void 0 ? _node_height : node.initialHeight) !== null && _ref1 !== void 0 ? _ref1 : (_node_style3 = node.style) === null || _node_style3 === void 0 ? void 0 : _node_style3.height 2402 }; 2403 } 2404 var _node_width1, _node_height1; 2405 return { 2406 width: (_node_width1 = node.width) !== null && _node_width1 !== void 0 ? _node_width1 : (_node_style = node.style) === null || _node_style === void 0 ? void 0 : _node_style.width, 2407 height: (_node_height1 = node.height) !== null && _node_height1 !== void 0 ? _node_height1 : (_node_style1 = node.style) === null || _node_style1 === void 0 ? void 0 : _node_style1.height 2408 }; 2409} 2410const selector$e = (s)=>{ 2411 const { width, height, x, y } = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getInternalNodesB
2411ounds */ .W0)(s.nodeLookup, { 2412 filter: (node)=>!!node.selected 2413 }); 2414 return { 2415 width: (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .isNumeric */ .kE)(width) ? width : null, 2416 height: (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .isNumeric */ .kE)(height) ? height : null, 2417 userSelectionActive: s.userSelectionActive, 2418 transformString: "translate(".concat(s.transform[0], "px,").concat(s.transform[1], "px) scale(").concat(s.transform[2], ") translate(").concat(x, "px,").concat(y, "px)") 2419 }; 2420}; 2421function NodesSelection(param) { 2422 let { onSelectionContextMenu, noPanClassName, disableKeyboardA11y } = param; 2423 const store = useStoreApi(); 2424 const { width, height, transformString, userSelectionActive } = useStore(selector$e, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 2425 const moveSelectedNodes = useMoveSelectedNodes(); 2426 const nodeRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null); 2427 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 2428 if (!disableKeyboardA11y) { 2429 var _nodeRef_current; 2430 (_nodeRef_current = nodeRef.current) === null || _nodeRef_current === void 0 ? void 0 : _nodeRef_current.focus({ 2431 preventScroll: true 2432 }); 2433 } 2434 }, [ 2435 disableKeyboardA11y 2436 ]); 2437 const shouldRender = !userSelectionActive && width !== null && height !== null; 2438 useDrag({ 2439 nodeRef, 2440 disabled: !shouldRender 2441 }); 2442 if (!shouldRender) { 2443 return null; 2444 } 2445 const onContextMenu = onSelectionContextMenu ? (event)=>{ 2446 const selectedNodes = store.getState().nodes.filter((n)=>n.selected); 2447 onSelectionContextMenu(event, selectedNodes); 2448 } : undefined; 2449 const onKeyDown = (event)=>{ 2450 if (Object.prototype.hasOwnProperty.call(arrowKeyDiffs, event.key)) { 2451 event.preventDefault(); 2452 moveSelectedNodes({ 2453 direction: arrowKeyDiffs[event.key], 2454 factor: event.shiftKey ? 4 : 1 2455 }); 2456 } 2457 }; 2458 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 2459 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 2460 "react-flow__nodesselection", 2461 "react-flow__container", 2462 noPanClassName 2463 ]), 2464 style: { 2465 transform: transformString 2466 }, 2467 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 2468 ref: nodeRef, 2469 className: "react-flow__nodesselection-rect", 2470 onContextMenu: onContextMenu, 2471 tabIndex: disableKeyboardA11y ? undefined : -1, 2472 onKeyDown: disableKeyboardA11y ? undefined : onKeyDown, 2473 style: { 2474 width, 2475 height 2476 } 2477 }) 2478 }); 2479} 2480const win = typeof window !== "undefined" ? window : undefined; 2481const selector$d = (s)=>{ 2482 return { 2483 nodesSelectionActive: s.nodesSelectionActive, 2484 userSelectionActive: s.userSelectionActive 2485 }; 2486}; 2487function FlowRendererComponent(param) { 2488 let { children, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneContextMenu, onPaneScroll, paneClickDistance, deleteKeyCode, selectionKeyCode, selectionOnDrag, selectionMode, onSelectionStart, onSelectionEnd, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, elementsSelectable, zoomOnScroll, zoomOnPinch, panOnScroll: _panOnScroll, panOnScrollSpeed, panOnScrollMode, zoomOnDoubleClick, panOnDrag: _panOnDrag, autoPanOnSelection, defaultViewport, translateExtent, minZoom, maxZoom, preventScrolling, onSelectionContextMenu, noWheelClassName, noPanClassName, disableKeyboardA11y, onViewportChange, isControlledViewport } = param; 2489 const { nodesSelectionActive, userSelectionActive } = useStore(selector$d, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 2490 const selectionKeyPressed = useKeyPress(selectionKeyCode, { 2491 target: win 2492 }); 2493 const panActivationKeyPressed = useKeyPress(panActivationKeyCode, { 2494 target: win 2495 }); 2496 const panOnDrag = panActivationKeyPressed || _panOnDrag; 2497 const panOnScroll = panActivationKeyPressed || _panOnScroll; 2498 const _selectionOnDrag = selectionOnDrag && panOnDrag !== true; 2499 const isSelecting = selectionKeyPressed || userSelectionActive || _selectionOnDrag; 2500 useGlobalKeyHandler({ 2501 deleteKeyCode, 2502 multiSelectionKeyCode 2503 }); 2504 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ZoomPane, { 2505 onPaneContextMenu: onPaneContextMenu, 2506 elementsSelectable: elementsSelectable, 2507 zoomOnScroll: zoomOnScroll, 2508 zoomOnPinch: zoomOnPinch, 2509 panOnScroll: panOnScroll, 2510 panOnScrollSpeed: panOnScrollSpeed, 2511 panOnScrollMode: panOnScrollMode, 2512 zoomOnDoubleClick: zoomOnDoubleClick, 2513 panOnDrag: !selectionKeyPressed && panOnDrag, 2514 defaultViewport: defaultViewport, 2515 translateExtent: translateExtent, 2516 minZoom: minZoom, 2517 maxZoom: maxZoom, 2518 zoomActivationKeyCode: zoomActivationKeyCode, 2519 preventScrolling: preventScrolling, 2520 noWheelClassName: noWheelClassName, 2521 noPanClassName: noPanClassName, 2522 onViewportChange: onViewportChange, 2523 isControlledViewport: isControlledViewport, 2524 paneClickDistance: paneClickDistance, 2525 selectionOnDrag: _selectionOnDrag, 2526 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(Pane, { 2527 onSelectionStart: onSelectionStart, 2528 onSelectionEnd: onSelectionEnd, 2529 onPaneClick: onPaneClick, 2530 onPaneMouseEnter: onPaneMouseEnter, 2531 onPaneMouseMove: onPaneMouseMove, 2532 onPaneMouseLeave: onPaneMouseLeave, 2533 onPaneContextMenu: onPaneContextMenu, 2534 onPaneScroll: onPaneScroll, 2535 panOnDrag: panOnDrag, 2536 autoPanOnSelection: autoPanOnSelection, 2537 isSelecting: !!isSelecting, 2538 selectionMode: selectionMode, 2539 selectionKeyPressed: selectionKeyPressed, 2540 paneClickDistance: paneClickDistance, 2541 selectionOnDrag: _selectionOnDrag, 2542 children: [ 2543 children, 2544 nodesSelectionActive && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(NodesSelection, { 2545 onSelectionContextMenu: onSelectionContextMenu, 2546 noPanClassName: noPanClassName, 2547 disableKeyboardA11y: disableKeyboardA11y 2548 }) 2549 ] 2550 }) 2551 }); 2552} 2553FlowRendererComponent.displayName = "FlowRenderer"; 2554const FlowRenderer = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(FlowRendererComponent); 2555const selector$c = (onlyRenderVisible)=>(s)=>{ 2556 return onlyRenderVisible ? (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getNodesInside */ .f5)(s.nodeLookup, { 2557 x: 0, 2558 y: 0, 2559 width: s.width, 2560 height: s.height 2561 }, s.transform, true).map((node)=>node.id) : Array.from(s.nodeLookup.keys()); 2562 }; 2563/** 2564 * Hook for getting the visible node ids from the store. 2565 * 2566 * @internal 2567 * @param onlyRenderVisible 2568 * @returns array with visible node ids 2569 */ function useVisibleNodeIds(onlyRenderVisible) { 2570 const nodeIds = useStore((0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)(selector$c(onlyRenderVisible), [ 2571 onlyRenderVisible 2572 ]), zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 2573 return nodeIds; 2574} 2575const selector$b = (s)=>s.updateNodeInternals; 2576function useResizeObserver() { 2577 const updateNodeInternals = useStore(selector$b); 2578 const [resizeObserver] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(()=>{ 2579 if (typeof ResizeObserver === "undefined") { 2580 return null; 2581 } 2582 return new ResizeObserver((entries)=>{ 2583 const updates = new Map();
2584 entries.forEach((entry)=>{ 2585 const id = entry.target.getAttribute("data-id"); 2586 updates.set(id, { 2587 id, 2588 nodeElement: entry.target, 2589 force: true 2590 }); 2591 }); 2592 updateNodeInternals(updates); 2593 }); 2594 }); 2595 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 2596 return ()=>{ 2597 resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect(); 2598 }; 2599 }, [ 2600 resizeObserver 2601 ]); 2602 return resizeObserver; 2603} 2604/** 2605 * Hook to handle the resize observation + internal updates for the passed node. 2606 * 2607 * @internal 2608 * @returns nodeRef - reference to the node element 2609 */ function useNodeObserver(param) { 2610 let { node, nodeType, hasDimensions, resizeObserver } = param; 2611 const store = useStoreApi(); 2612 const nodeRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null); 2613 const observedNode = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null); 2614 const prevSourcePosition = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(node.sourcePosition); 2615 const prevTargetPosition = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(node.targetPosition); 2616 const prevType = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(nodeType); 2617 const isInitialized = hasDimensions && !!node.internals.handleBounds; 2618 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 2619 if (nodeRef.current && !node.hidden && (!isInitialized || observedNode.current !== nodeRef.current)) { 2620 if (observedNode.current) { 2621 resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.unobserve(observedNode.current); 2622 } 2623 resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.observe(nodeRef.current); 2624 observedNode.current = nodeRef.current; 2625 } 2626 }, [ 2627 isInitialized, 2628 node.hidden 2629 ]); 2630 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 2631 return ()=>{ 2632 if (observedNode.current) { 2633 resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.unobserve(observedNode.current); 2634 observedNode.current = null; 2635 } 2636 }; 2637 }, []); 2638 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 2639 if (nodeRef.current) { 2640 /* 2641 * when the user programmatically changes the source or handle position, we need to update the internals 2642 * to make sure the edges are updated correctly 2643 */ const typeChanged = prevType.current !== nodeType; 2644 const sourcePosChanged = prevSourcePosition.current !== node.sourcePosition; 2645 const targetPosChanged = prevTargetPosition.current !== node.targetPosition; 2646 if (typeChanged || sourcePosChanged || targetPosChanged) { 2647 prevType.current = nodeType; 2648 prevSourcePosition.current = node.sourcePosition; 2649 prevTargetPosition.current = node.targetPosition; 2650 store.getState().updateNodeInternals(new Map([ 2651 [ 2652 node.id, 2653 { 2654 id: node.id, 2655 nodeElement: nodeRef.current, 2656 force: true 2657 } 2658 ] 2659 ])); 2660 } 2661 } 2662 }, [ 2663 node.id, 2664 nodeType, 2665 node.sourcePosition, 2666 node.targetPosition 2667 ]); 2668 return nodeRef; 2669} 2670function NodeWrapper(param) { 2671 let { id, onClick, onMouseEnter, onMouseMove, onMouseLeave, onContextMenu, onDoubleClick, nodesDraggable, elementsSelectable, nodesConnectable, nodesFocusable, resizeObserver, noDragClassName, noPanClassName, disableKeyboardA11y, rfId, nodeTypes, nodeClickDistance, onError } = param; 2672 const { node, internals, isParent } = useStore((s)=>{ 2673 const node = s.nodeLookup.get(id); 2674 const isParent = s.parentLookup.has(id); 2675 return { 2676 node, 2677 internals: node.internals, 2678 isParent 2679 }; 2680 }, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 2681 let nodeType = node.type || "default"; 2682 let NodeComponent = (nodeTypes === null || nodeTypes === void 0 ? void 0 : nodeTypes[nodeType]) || builtinNodeTypes[nodeType]; 2683 if (NodeComponent === undefined) { 2684 onError === null || onError === void 0 ? void 0 : onError("003", _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .errorMessages */ .Qj["error003"](nodeType)); 2685 nodeType = "default"; 2686 NodeComponent = (nodeTypes === null || nodeTypes === void 0 ? void 0 : nodeTypes["default"]) || builtinNodeTypes.default; 2687 } 2688 const isDraggable = !!(node.draggable || nodesDraggable && typeof node.draggable === "undefined"); 2689 const isSelectable = !!(node.selectable || elementsSelectable && typeof node.selectable === "undefined"); 2690 const isConnectable = !!(node.connectable || nodesConnectable && typeof node.connectable === "undefined"); 2691 const isFocusable = !!(node.focusable || nodesFocusable && typeof node.focusable === "undefined"); 2692 const store = useStoreApi(); 2693 const hasDimensions = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .nodeHasDimensions */ .nb)(node); 2694 const nodeRef = useNodeObserver({ 2695 node, 2696 nodeType, 2697 hasDimensions, 2698 resizeObserver 2699 }); 2700 const dragging = useDrag({ 2701 nodeRef, 2702 disabled: node.hidden || !isDraggable, 2703 noDragClassName, 2704 handleSelector: node.dragHandle, 2705 nodeId: id, 2706 isSelectable, 2707 nodeClickDistance 2708 }); 2709 const moveSelectedNodes = useMoveSelectedNodes(); 2710 if (node.hidden) { 2711 return null; 2712 } 2713 const nodeDimensions = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getNodeDimensions */ .Rf)(node); 2714 const inlineDimensions = getNodeInlineStyleDimensions(node); 2715 const hasPointerEvents = isSelectable || isDraggable || onClick || onMouseEnter || onMouseMove || onMouseLeave; 2716 const onMouseEnterHandler = onMouseEnter ? (event)=>onMouseEnter(event, { 2717 ...internals.userNode 2718 }) : undefined; 2719 const onMouseMoveHandler = onMouseMove ? (event)=>onMouseMove(event, { 2720 ...internals.userNode 2721 }) : undefined; 2722 const onMouseLeaveHandler = onMouseLeave ? (event)=>onMouseLeave(event, { 2723 ...internals.userNode 2724 }) : undefined; 2725 const onContextMenuHandler = onContextMenu ? (event)=>onContextMenu(event, { 2726 ...internals.userNode 2727 }) : undefined; 2728 const onDoubleClickHandler = onDoubleClick ? (event)=>onDoubleClick(event, { 2729 ...internals.userNode 2730 }) : undefined; 2731 const onSelectNodeHandler = (event)=>{ 2732 const { selectNodesOnDrag, nodeDragThreshold } = store.getState(); 2733 if (isSelectable && (!selectNodesOnDrag || !isDraggable || nodeDragThreshold > 0)) { 2734 /* 2735 * this handler gets called by XYDrag on drag start when selectNodesOnDrag=true 2736 * here we only need to call it when selectNodesOnDrag=false 2737 */ handleNodeClick({ 2738 id, 2739 store, 2740 nodeRef 2741 }); 2742 } 2743 if (onClick) { 2744 onClick(event, { 2745 ...internals.userNode 2746 }); 2747 } 2748 }; 2749 const onKeyDown = (event)=>{ 2750 if ((0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .isInputDOMNode */ .s$)(event.
2750nativeEvent) || disableKeyboardA11y) { 2751 return; 2752 } 2753 if (_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .elementSelectionKeys */ .wQ.includes(event.key) && isSelectable) { 2754 const unselect = event.key === "Escape"; 2755 handleNodeClick({ 2756 id, 2757 store, 2758 unselect, 2759 nodeRef 2760 }); 2761 } else if (isDraggable && node.selected && Object.prototype.hasOwnProperty.call(arrowKeyDiffs, event.key)) { 2762 // prevent default scrolling behavior on arrow key press when node is moved 2763 event.preventDefault(); 2764 const { ariaLabelConfig } = store.getState(); 2765 store.setState({ 2766 ariaLiveMessage: ariaLabelConfig["node.a11yDescription.ariaLiveMessage"]({ 2767 direction: event.key.replace("Arrow", "").toLowerCase(), 2768 x: ~~internals.positionAbsolute.x, 2769 y: ~~internals.positionAbsolute.y 2770 }) 2771 }); 2772 moveSelectedNodes({ 2773 direction: arrowKeyDiffs[event.key], 2774 factor: event.shiftKey ? 4 : 1 2775 }); 2776 } 2777 }; 2778 const onFocus = ()=>{ 2779 var _nodeRef_current; 2780 if (disableKeyboardA11y || !((_nodeRef_current = nodeRef.current) === null || _nodeRef_current === void 0 ? void 0 : _nodeRef_current.matches(":focus-visible"))) { 2781 return; 2782 } 2783 const { transform, width, height, autoPanOnNodeFocus, setCenter } = store.getState(); 2784 if (!autoPanOnNodeFocus) { 2785 return; 2786 } 2787 const withinViewport = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getNodesInside */ .f5)(new Map([ 2788 [ 2789 id, 2790 node 2791 ] 2792 ]), { 2793 x: 0, 2794 y: 0, 2795 width, 2796 height 2797 }, transform, true).length > 0; 2798 if (!withinViewport) { 2799 setCenter(node.position.x + nodeDimensions.width / 2, node.position.y + nodeDimensions.height / 2, { 2800 zoom: transform[2] 2801 }); 2802 } 2803 }; 2804 var _node_ariaRole, _node_selected, _node_deletable; 2805 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 2806 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 2807 "react-flow__node", 2808 "react-flow__node-".concat(nodeType), 2809 { 2810 // this is overwritable by passing `nopan` as a class name 2811 [noPanClassName]: isDraggable 2812 }, 2813 node.className, 2814 { 2815 selected: node.selected, 2816 selectable: isSelectable, 2817 parent: isParent, 2818 draggable: isDraggable, 2819 dragging 2820 } 2821 ]), 2822 ref: nodeRef, 2823 style: { 2824 zIndex: internals.z, 2825 transform: "translate(".concat(internals.positionAbsolute.x, "px,").concat(internals.positionAbsolute.y, "px)"), 2826 pointerEvents: hasPointerEvents ? "all" : "none", 2827 visibility: hasDimensions ? "visible" : "hidden", 2828 ...node.style, 2829 ...inlineDimensions 2830 }, 2831 "data-id": id, 2832 "data-testid": "rf__node-".concat(id), 2833 onMouseEnter: onMouseEnterHandler, 2834 onMouseMove: onMouseMoveHandler, 2835 onMouseLeave: onMouseLeaveHandler, 2836 onContextMenu: onContextMenuHandler, 2837 onClick: onSelectNodeHandler, 2838 onDoubleClick: onDoubleClickHandler, 2839 onKeyDown: isFocusable ? onKeyDown : undefined, 2840 tabIndex: isFocusable ? 0 : undefined, 2841 onFocus: isFocusable ? onFocus : undefined, 2842 role: (_node_ariaRole = node.ariaRole) !== null && _node_ariaRole !== void 0 ? _node_ariaRole : isFocusable ? "group" : undefined, 2843 "aria-roledescription": "node", 2844 "aria-describedby": disableKeyboardA11y ? undefined : "".concat(ARIA_NODE_DESC_KEY, "-").concat(rfId), 2845 "aria-label": node.ariaLabel, 2846 ...node.domAttributes, 2847 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(Provider, { 2848 value: id, 2849 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(NodeComponent, { 2850 id: id, 2851 data: node.data, 2852 type: nodeType, 2853 positionAbsoluteX: internals.positionAbsolute.x, 2854 positionAbsoluteY: internals.positionAbsolute.y, 2855 selected: (_node_selected = node.selected) !== null && _node_selected !== void 0 ? _node_selected : false, 2856 selectable: isSelectable, 2857 draggable: isDraggable, 2858 deletable: (_node_deletable = node.deletable) !== null && _node_deletable !== void 0 ? _node_deletable : true, 2859 isConnectable: isConnectable, 2860 sourcePosition: node.sourcePosition, 2861 targetPosition: node.targetPosition, 2862 dragging: dragging, 2863 dragHandle: node.dragHandle, 2864 zIndex: internals.z, 2865 parentId: node.parentId, 2866 ...nodeDimensions 2867 }) 2868 }) 2869 }); 2870} 2871var NodeWrapper$1 = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(NodeWrapper); 2872const selector$a = (s)=>({ 2873 nodesConnectable: s.nodesConnectable, 2874 nodesFocusable: s.nodesFocusable, 2875 elementsSelectable: s.elementsSelectable, 2876 onError: s.onError 2877 }); 2878function NodeRendererComponent(props) { 2879 const { nodesConnectable, nodesFocusable, elementsSelectable, onError } = useStore(selector$a, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 2880 const nodeIds = useVisibleNodeIds(props.onlyRenderVisibleElements); 2881 const resizeObserver = useResizeObserver(); 2882 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 2883 className: "react-flow__nodes", 2884 style: containerStyle, 2885 children: nodeIds.map((nodeId)=>{ 2886 var _props_nodesDraggable; 2887 return(/* 2888 * The split of responsibilities between NodeRenderer and 2889 * NodeComponentWrapper may appear weird. However, it’s designed to 2890 * minimize the cost of updates when individual nodes change. 2891 * 2892 * For example, when you’re dragging a single node, that node gets 2893 * updated multiple times per second. If `NodeRenderer` were to update 2894 * every time, it would have to re-run the `nodes.map()` loop every 2895 * time. This gets pricey with hundreds of nodes, especially if every 2896 * loop cycle does more than just rendering a JSX element! 2897 * 2898 * As a result of this choice, we took the following implementation 2899 * decisions: 2900 * - NodeRenderer subscribes *only* to node IDs – and therefore 2901 * rerender *only* when visible nodes are added or removed. 2902 * - NodeRenderer performs all operations the result of which can be 2903 * shared between nodes (such as creating the `ResizeObserver` 2904 * instance, or subscribing to `selector`). This means extra prop 2905 * drilling into `NodeComponentWrapper`, but it means we need to run 2906 * these operations only once – instead of once per node. 2907 * - Any operations that you’d normally write inside `nodes.map` are 2908 * moved into `NodeComponentWrapper`. This ensures they are 2909 * memorized – so if `NodeRenderer` *has* to rerender, it only 2910 * needs to regenerate the list of nodes, nothing else. 2911 */ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(NodeWrapper$1, { 2912 id: nodeId, 2913 nodeTypes: props.nodeTypes, 2914 nodeExtent: props.nodeExtent, 2915 onClick: props.onNodeClick, 2916 onMouseEnter: props.onNodeMouseEnter, 2917 onMouseMove: props.onNodeMouseMove, 2918 onMouseLeave: props.onNodeMouseLeave, 2919 onContextMenu: props.onNodeContextMenu, 2920 onDoubleClick: props.onNodeDoubleClick, 2921 noDragClassName: props.noDragClassName, 2922 noPanClassName: props.noPanClassName, 2923 rfId: props.rfId, 2924 disableKeyboardA11y: props.disableKeyboardA11y, 2925 resizeObserver: resizeObserver, 2926 nodesDraggable: (_props_nodesDraggable = props.nodesDraggable) !== null && _props_nodesDraggable !== void 0 ? _props_nodesDraggable : true, 2927 nodesConnectable: nodesConnectable, 2928 nodesFocusable: nodesFocusable, 2929 elementsSelectable: elementsSelectable, 2930 nodeClickDistance: props.nodeClickDistance, 2931 onError: onError 2932 }, nodeId)); 2933 }) 2934 }); 2935} 2936NodeRendererComponent.displayName = "NodeRenderer"; 2937const NodeRenderer = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(NodeRendererComponent); 2938/** 2939 * Hook for getting the visible edge ids from the store. 2940 * 2941 * @internal 2942 * @param onlyRenderVisible 2943 * @returns array with visible edge ids 2944 */ function useVisibleEdgeIds(onlyRenderVisible) { 2945 const edgeIds = useStore((0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)((s)=>{ 2946 if (!onlyRenderVisible) { 2947 return s.edges.map((edge)=>edge.id); 2948 } 2949 const visibleEdgeIds = []; 2950 if (s.width && s.height) { 2951 for (const edge of s.edges){ 2952 const sourceNode = s.nodeLookup.get(edge.source); 2953 const targetNode = s.nodeLookup.get(edge.target); 2954 if (sourceNode && targetNode && (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .isEdgeVisible */ .RY)({ 2955 sourceNode, 2956 targetNode, 2957 width: s.width, 2958 height: s.height, 2959 transform: s.transform 2960 })) { 2961 visibleEdgeIds.push(edge.id); 2962 } 2963 } 2964 } 2965 return visibleEdgeIds; 2966 }, [ 2967 onlyRenderVisible 2968 ]), zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 2969 return edgeIds; 2970} 2971const ArrowSymbol = (param)=>{ 2972 let { color = "none", strokeWidth = 1 } = param; 2973 const style = { 2974 strokeWidth, 2975 ...color && { 2976 stroke: color 2977 } 2978 }; 2979 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("polyline", { 2980 className: "arrow", 2981 style: style, 2982 strokeLinecap: "round", 2983 fill: "none", 2984 strokeLinejoin: "round", 2985 points: "-5,-4 0,0 -5,4" 2986 }); 2987}; 2988const ArrowClosedSymbol = (param)=>{ 2989 let { color = "none", strokeWidth = 1 } = param; 2990 const style = { 2991 strokeWidth, 2992 ...color && { 2993 stroke: color, 2994 fill: color 2995 } 2996 }; 2997 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("polyline", { 2998 className: "arrowclosed", 2999 style: style, 3000 strokeLinecap: "round", 3001 strokeLinejoin: "round", 3002 points: "-5,-4 0,0 -5,4 -5,-4" 3003 }); 3004}; 3005const MarkerSymbols = { 3006 [_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .MarkerType */ .QZ.Arrow]: ArrowSymbol, 3007 [_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .MarkerType */ .QZ.ArrowClosed]: ArrowClosedSymbol 3008}; 3009function useMarkerSymbol(type) { 3010 const store = useStoreApi(); 3011 const symbol = (0,react__WEBPACK_IMPORTED_MODULE_1__.useMemo)(()=>{ 3012 const symbolExists = Object.prototype.hasOwnProperty.call(MarkerSymbols, type); 3013 if (!symbolExists) { 3014 var _store_getState_onError, _store_getState; 3015 (_store_getState_onError = (_store_getState = store.getState()).onError) === null || _store_getState_onError === void 0 ? void 0 : _store_getState_onError.call(_store_getState, "009", _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .errorMessages */ .Qj["error009"](type)); 3016 return null; 3017 } 3018 return MarkerSymbols[type]; 3019 }, [ 3020 type 3021 ]); 3022 return symbol; 3023} 3024const Marker = (param)=>{ 3025 let { id, type, color, width = 12.5, height = 12.5, markerUnits = "strokeWidth", strokeWidth, orient = "auto-start-reverse" } = param; 3026 const Symbol1 = useMarkerSymbol(type); 3027 if (!Symbol1) { 3028 return null; 3029 } 3030 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("marker", { 3031 className: "react-flow__arrowhead", 3032 id: id, 3033 markerWidth: "".concat(width), 3034 markerHeight: "".concat(height),
3035 viewBox: "-10 -10 20 20", 3036 markerUnits: markerUnits, 3037 orient: orient, 3038 refX: "0", 3039 refY: "0", 3040 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(Symbol1, { 3041 color: color, 3042 strokeWidth: strokeWidth 3043 }) 3044 }); 3045}; 3046/* 3047 * when you have multiple flows on a page and you hide the first one, the other ones have no markers anymore 3048 * when they do have markers with the same ids. To prevent this the user can pass a unique id to the react flow wrapper 3049 * that we can then use for creating our unique marker ids 3050 */ const MarkerDefinitions = (param)=>{ 3051 let { defaultColor, rfId } = param; 3052 const edges = useStore((s)=>s.edges); 3053 const defaultEdgeOptions = useStore((s)=>s.defaultEdgeOptions); 3054 const markers = (0,react__WEBPACK_IMPORTED_MODULE_1__.useMemo)(()=>{ 3055 const markers = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .createMarkerIds */ .n3)(edges, { 3056 id: rfId, 3057 defaultColor, 3058 defaultMarkerStart: defaultEdgeOptions === null || defaultEdgeOptions === void 0 ? void 0 : defaultEdgeOptions.markerStart, 3059 defaultMarkerEnd: defaultEdgeOptions === null || defaultEdgeOptions === void 0 ? void 0 : defaultEdgeOptions.markerEnd 3060 }); 3061 return markers; 3062 }, [ 3063 edges, 3064 defaultEdgeOptions, 3065 rfId, 3066 defaultColor 3067 ]); 3068 if (!markers.length) { 3069 return null; 3070 } 3071 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("svg", { 3072 className: "react-flow__marker", 3073 "aria-hidden": "true", 3074 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("defs", { 3075 children: markers.map((marker)=>(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(Marker, { 3076 id: marker.id, 3077 type: marker.type, 3078 color: marker.color, 3079 width: marker.width, 3080 height: marker.height, 3081 markerUnits: marker.markerUnits, 3082 strokeWidth: marker.strokeWidth, 3083 orient: marker.orient 3084 }, marker.id)) 3085 }) 3086 }); 3087}; 3088MarkerDefinitions.displayName = "MarkerDefinitions"; 3089var MarkerDefinitions$1 = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(MarkerDefinitions); 3090function EdgeTextComponent(param) { 3091 let { x, y, label, labelStyle, labelShowBg = true, labelBgStyle, labelBgPadding = [ 3092 2, 3093 4 3094 ], labelBgBorderRadius = 2, children, className, ...rest } = param; 3095 const [edgeTextBbox, setEdgeTextBbox] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)({ 3096 x: 1, 3097 y: 0, 3098 width: 0, 3099 height: 0 3100 }); 3101 const edgeTextClasses = (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 3102 "react-flow__edge-textwrapper", 3103 className 3104 ]); 3105 const edgeTextRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null); 3106 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 3107 if (edgeTextRef.current) { 3108 const textBbox = edgeTextRef.current.getBBox(); 3109 setEdgeTextBbox({ 3110 x: textBbox.x, 3111 y: textBbox.y, 3112 width: textBbox.width, 3113 height: textBbox.height 3114 }); 3115 } 3116 }, [ 3117 label 3118 ]); 3119 if (!label) { 3120 return null; 3121 } 3122 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("g", { 3123 transform: "translate(".concat(x - edgeTextBbox.width / 2, " ").concat(y - edgeTextBbox.height / 2, ")"), 3124 className: edgeTextClasses, 3125 visibility: edgeTextBbox.width ? "visible" : "hidden", 3126 ...rest, 3127 children: [ 3128 labelShowBg && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("rect", { 3129 width: edgeTextBbox.width + 2 * labelBgPadding[0], 3130 x: -labelBgPadding[0], 3131 y: -labelBgPadding[1], 3132 height: edgeTextBbox.height + 2 * labelBgPadding[1], 3133 className: "react-flow__edge-textbg", 3134 style: labelBgStyle, 3135 rx: labelBgBorderRadius, 3136 ry: labelBgBorderRadius 3137 }), 3138 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("text", { 3139 className: "react-flow__edge-text", 3140 y: edgeTextBbox.height / 2, 3141 dy: "0.3em", 3142 ref: edgeTextRef, 3143 style: labelStyle, 3144 children: label 3145 }), 3146 children 3147 ] 3148 }); 3149} 3150EdgeTextComponent.displayName = "EdgeText"; 3151/** 3152 * You can use the `<EdgeText />` component as a helper component to display text 3153 * within your custom edges. 3154 * 3155 * @public 3156 * 3157 * @example 3158 * ```jsx 3159 * import { EdgeText } from '@xyflow/react'; 3160 * 3161 * export function CustomEdgeLabel({ label }) { 3162 * return ( 3163 * <EdgeText 3164 * x={100} 3165 * y={100} 3166 * label={label} 3167 * labelStyle={{ fill: 'white' }} 3168 * labelShowBg 3169 * labelBgStyle={{ fill: 'red' }} 3170 * labelBgPadding={[2, 4]} 3171 * labelBgBorderRadius={2} 3172 * /> 3173 * ); 3174 * } 3175 *``` 3176 */ const EdgeText = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(EdgeTextComponent); 3177/** 3178 * The `<BaseEdge />
3178` component gets used internally for all the edges. It can be 3179 * used inside a custom edge and handles the invisible helper edge and the edge label 3180 * for you. 3181 * 3182 * @public 3183 * @example 3184 * ```jsx 3185 *import { BaseEdge } from '@xyflow/react'; 3186 * 3187 *export function CustomEdge({ sourceX, sourceY, targetX, targetY, ...props }) { 3188 * const [edgePath] = getStraightPath({ 3189 * sourceX, 3190 * sourceY, 3191 * targetX, 3192 * targetY, 3193 * }); 3194 * 3195 * return <BaseEdge path={edgePath} {...props} />; 3196 *} 3197 *``` 3198 * 3199 * @remarks If you want to use an edge marker with the [`<BaseEdge />`](/api-reference/components/base-edge) component, 3200 * you can pass the `markerStart` or `markerEnd` props passed to your custom edge 3201 * through to the [`<BaseEdge />`](/api-reference/components/base-edge) component. 3202 * You can see all the props passed to a custom edge by looking at the [`EdgeProps`](/api-reference/types/edge-props) type. 3203 */ function BaseEdge(param) { 3204 let { path, labelX, labelY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, interactionWidth = 20, ...props } = param; 3205 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, { 3206 children: [ 3207 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("path", { 3208 ...props, 3209 d: path, 3210 fill: "none", 3211 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 3212 "react-flow__edge-path", 3213 props.className 3214 ]) 3215 }), 3216 interactionWidth ? (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("path", { 3217 d: path, 3218 fill: "none", 3219 strokeOpacity: 0, 3220 strokeWidth: interactionWidth, 3221 className: "react-flow__edge-interaction" 3222 }) : null, 3223 label && (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .isNumeric */ .kE)(labelX) && (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .isNumeric */ .kE)(labelY) ? (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(EdgeText, { 3224 x: labelX, 3225 y: labelY, 3226 label: label, 3227 labelStyle: labelStyle, 3228 labelShowBg: labelShowBg, 3229 labelBgStyle: labelBgStyle, 3230 labelBgPadding: labelBgPadding, 3231 labelBgBorderRadius: labelBgBorderRadius 3232 }) : null 3233 ] 3234 }); 3235} 3236function getControl(param) { 3237 let { pos, x1, y1, x2, y2 } = param; 3238 if (pos === _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Left || pos === _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Right) { 3239 return [ 3240 0.5 * (x1 + x2), 3241 y1 3242 ]; 3243 } 3244 return [ 3245 x1, 3246 0.5 * (y1 + y2) 3247 ]; 3248} 3249/** 3250 * The `getSimpleBezierPath` util returns everything you need to render a simple 3251 * bezier edge between two nodes. 3252 * @public 3253 * @returns 3254 * - `path`: the path to use in an SVG `<path>` element. 3255 * - `labelX`: the `x` position you can use to render a label for this edge. 3256 * - `labelY`: the `y` position you can use to render a label for this edge. 3257 * - `offsetX`: the absolute difference between the source `x` position and the `x` position of the 3258 * middle of this path. 3259 * - `offsetY`: the absolute difference between the source `y` position and the `y` position of the 3260 * middle of this path. 3261 */ function getSimpleBezierPath(param) { 3262 let { sourceX, sourceY, sourcePosition = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Bottom, targetX, targetY, targetPosition = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Top } = param; 3263 const [sourceControlX, sourceControlY] = getControl({ 3264 pos: sourcePosition, 3265 x1: sourceX, 3266 y1: sourceY, 3267 x2: targetX, 3268 y2: targetY 3269 }); 3270 const [targetControlX, targetControlY] = getControl({ 3271 pos: targetPosition, 3272 x1: targetX, 3273 y1: targetY, 3274 x2: sourceX, 3275 y2: sourceY 3276 }); 3277 const [labelX, labelY, offsetX, offsetY] = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getBezierEdgeCenter */ .lM)({ 3278 sourceX, 3279 sourceY, 3280 targetX, 3281 targetY, 3282 sourceControlX, 3283 sourceControlY, 3284 targetControlX, 3285 targetControlY 3286 }); 3287 return [ 3288 "M".concat(sourceX, ",").concat(sourceY, " C").concat(sourceControlX, ",").concat(sourceControlY, " ").concat(targetControlX, ",").concat(targetControlY, " ").concat(targetX, ",").concat(targetY), 3289 labelX, 3290 labelY, 3291 offsetX, 3292 offsetY 3293 ]; 3294} 3295function createSimpleBezierEdge(params) { 3296 // eslint-disable-next-line react/display-name 3297 return /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)((param)=>{ 3298 let { id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, interactionWidth } = param; 3299 const [path, labelX, labelY] = getSimpleBezierPath({ 3300 sourceX, 3301 sourceY, 3302 sourcePosition, 3303 targetX, 3304 targetY, 3305 targetPosition 3306 }); 3307 const _id = params.isInternal ? undefined : id; 3308 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(BaseEdge, { 3309 id: _id, 3310 path: path, 3311 labelX: labelX, 3312 labelY: labelY, 3313 label: label, 3314 labelStyle: labelStyle, 3315 labelShowBg: labelShowBg, 3316 labelBgStyle: labelBgStyle, 3317 labelBgPadding: labelBgPadding, 3318 labelBgBorderRadius: labelBgBorderRadius, 3319 style: style, 3320 markerEnd: markerEnd, 3321 markerStart: markerStart, 3322 interactionWidth: interactionWidth 3323 }); 3324 }); 3325} 3326const SimpleBezierEdge = createSimpleBezierEdge({ 3327 isInternal: false 3328}); 3329const SimpleBezierEdgeInternal = createSimpleBezierEdge({ 3330 isInternal: true 3331}); 3332SimpleBezierEdge.displayName = "SimpleBezierEdge"; 3333SimpleBezierEdgeInternal.displayName = "SimpleBezierEdgeInternal"; 3334function createSmoothStepEdge(params) { 3335 // eslint-disable-next-line react/display-name 3336 return /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)((param)=>{ 3337 let { id, sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, sourcePosition = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Bottom, targetPosition = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Top, markerEnd, markerStart, pathOptions, interactionWidth } = param; 3338 const [path, labelX, labelY] = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getSmoothStepPath */ .OW)({ 3339 sourceX, 3340 sourceY, 3341 sourcePosition, 3342 targetX, 3343 targetY, 3344 targetPosition, 3345 borderRadius: pathOptions === null || pathOptions === void 0 ? void 0 : pathOptions.borderRadius, 3346 offset: pathOptions === null || pathOptions === void 0 ? void 0 : pathOptions.offset, 3347 stepPosition: pathOptions === null || pathOptions === void 0 ? void 0 : pathOptions.stepPosition 3348 }); 3349 const _id = params.isInternal ? undefined : id; 3350 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(BaseEdge, { 3351 id: _id, 3352 path: path, 3353 labelX: labelX, 3354 labelY: labelY, 3355 label: label, 3356 labelStyle: labelStyle, 3357 labelShowBg: labelShowBg, 3358 labelBgStyle: labelBgStyle, 3359 labelBgPadding: labelBgPadding, 3360 labelBgBorderRadius: labelBgBorderRadius, 3361 style: style, 3362 markerEnd: markerEnd, 3363 markerStart: markerStart, 3364 interactionWidth: interactionWidth 3365 }); 3366 }); 3367} 3368/** 3369 * Component that can be used inside a custom edge to render a smooth step edge. 3370 * 3371 * @public 3372 * @example 3373 * 3374 * ```tsx 3375 * import { SmoothStepEdge } from '@xyflow/react'; 3376 * 3377 * function CustomEdge({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition }) { 3378 * return ( 3379 * <SmoothStepEdge 3380 * sourceX={sourceX} 3381 * sourceY={sourceY} 3382 * targetX={targetX} 3383 * targetY={targetY} 3384 * sourcePosition={sourcePosition} 3385 * targetPosition={targetPosition} 3386 * /> 3387 * ); 3388 * } 3389 * ``` 3390 */ const SmoothStepEdge = createSmoothStepEdge({ 3391 isInternal: false 3392}); 3393/** 3394 * @internal 3395 */ const SmoothStepEdgeInternal = createSmoothStepEdge({ 3396 isInternal: true 3397}); 3398SmoothStepEdge.displayName = "SmoothStepEdge"; 3399SmoothStepEdgeInternal.displayName = "SmoothStepEdgeInternal"; 3400function createStepEdge(params) { 3401 // eslint-disable-next-line react/display-name 3402 return /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)((param)=>{ 3403 let { id, ...props } = param; 3404 var _props_pathOptions; 3405 const _id = params.isInternal ? undefined : id; 3406 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(SmoothStepEdge, { 3407 ...props, 3408 id: _id, 3409 pathOptions: (0,react__WEBPACK_IMPORTED_MODULE_1__.useMemo)(()=>{ 3410 var _props_pathOptions; 3411 return { 3412 borderRadius: 0, 3413 offset: (_props_pathOptions = props.pathOptions) === null || _props_pathOptions === void 0 ? void 0 : _props_pathOptions.offset 3414 }; 3415 }, [ 3416 (_props_pathOptions = props.pathOptions) === null || _props_pathOptions === void 0 ? void 0 : _props_pathOptions.offset 3417 ]) 3418 }); 3419 }); 3420} 3421/** 3422 * Component that can be used inside a custom edge to render a step edge. 3423 * 3424 * @public 3425 * @example 3426 * 3427 * ```tsx 3428 * import { StepEdge } from '@xyflow/react'; 3429 * 3430 * function CustomEdge({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition }) { 3431 * return ( 3432 * <StepEdge 3433 * sourceX={sourceX} 3434 * sourceY={sourceY} 3435 * targetX={targetX} 3436 * targetY={targetY} 3437 * sourcePosition={sourcePosition} 3438 * targetPosition={targetPosition} 3439 * /> 3440 * ); 3441 * } 3442 * ``` 3443 */ const StepEdge = createStepEdge({ 3444 isInternal: false 3445}); 3446/** 3447 * @internal 3448 */ const StepEdgeInternal = createStepEdge({ 3449 isInternal: true 3450}); 3451StepEdge.displayName = "StepEdge"; 3452StepEdgeInternal.displayName = "StepEdgeInternal"; 3453function createStraightEdge(params) { 3454 // eslint-disable-next-line react/display-name 3455 return /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)((param)=>{ 3456 let { id, sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, interactionWidth } = param; 3457 const [path, labelX, labelY] = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getStraightPath */ .Hm)({ 3458 sourceX, 3459 sourceY, 3460 targetX, 3461 targetY 3462 }); 3463 const _id = params.isInternal ? undefined : id; 3464 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(BaseEdge, { 3465 id: _id, 3466 path: path, 3467 labelX: labelX, 3468 labelY: labelY, 3469 label: label, 3470 labelStyle: labelStyle, 3471 labelShowBg: labelShowBg, 3472 labelBgStyle: labelBgStyle, 3473 labelBgPadding: labelBgPadding, 3474 labelBgBorderRadius: labelBgBorderRadius, 3475 style: style, 3476 markerEnd: markerEnd, 3477 markerStart: markerStart, 3478 interactionWidth: interactionWidth 3479 }); 3480 }); 3481} 3482/** 3483 * Component that can be used inside a custom edge to render a straight line. 3484 * 3485 * @public 3486 * @example 3487 * 3488 * ```tsx 3489 * import { StraightEdge } from '@xyflow/react'; 3490 * 3491 * function CustomEdge({ sourceX, sourceY, targetX, targetY }) { 3492 * return ( 3493 * <StraightEdge 3494 * sourceX={sourceX} 3495 * sourceY={sourceY} 3496 * targetX={targetX} 3497 * targetY={targetY} 3498 * /> 3499 * ); 3500 * } 3501 * ``` 3502 */ const StraightEdge = createStraightEdge({ 3503 isInternal: false 3504}); 3505/** 3506 * @internal 3507 */ const StraightEdgeInternal = createStraightEdge({ 3508 isInternal: true 3509}); 3510StraightEdge.displayName = "StraightEdge"; 3511StraightEdgeInternal.displayName = "StraightEdgeInternal"; 3512function createBezierEdge(params) { 3513 // eslint-disable-next-line react/display-name 3514 return /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)((param)=>{ 3515 let { id, sourceX, sourceY, targetX, targetY, sourcePosition = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Bottom, targetPosition = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Top, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, pathOptions, interactionWidth } = param; 3516 const [path, labelX, labelY] = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getBezierPath */ .OQ)({ 3517 sourceX, 3518 sourceY, 3519 sourcePosition, 3520 targetX, 3521 targetY, 3522 targetPosition, 3523 curvature: pathOptions === null || pathOptions === void 0 ? void 0 : pathOptions.curvature 3524 }); 3525 const _id = params.isInternal ? undefined : id; 3526 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(BaseEdge, { 3527 id: _id, 3528 path: path, 3529 labelX: labelX, 3530 labelY: labelY, 3531 label: label, 3532 labelStyle: labelStyle, 3533 labelShowBg: labelShowBg, 3534 labelBgStyle: labelBgStyle, 3535 labelBgPadding: labelBgPadding, 3536 labelBgBorderRadius: labelBgBorderRadius, 3537 style: style, 3538 markerEnd: markerEnd, 3539 markerStart: markerStart, 3540 interactionWidth: interactionWidth 3541 }); 3542 }); 3543} 3544/** 3545 * Component that can be used inside a custom edge to render a bezier curve. 3546 * 3547 * @public 3548 * @example 3549 * 3550 * ```tsx 3551 * import { BezierEdge } from '@xyflow/react'; 3552 * 3553 * function CustomEdge({ sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition }) { 3554 * return ( 3555 * <BezierEdge 3556 * sourceX={sourceX} 3557 * sourceY={sourceY} 3558 * targetX={targetX} 3559 * targetY={targetY} 3560 * sourcePosition={sourcePosition} 3561 * targetPosition={targetPosition} 3562 * /> 3563 * ); 3564 * } 3565 * ``` 3566 */ const BezierEdge = createBezierEdge({ 3567 isInternal: false 3568}); 3569/** 3570 * @internal 3571 */ const BezierEdgeInternal = createBezierEdge({ 3572 isInternal: true 3573}); 3574BezierEdge.displayName = "BezierEdge"; 3575BezierEdgeInternal.displayName = "BezierEdgeInternal"; 3576const builtinEdgeTypes = { 3577 default: BezierEdgeInternal, 3578 straight: StraightEdgeInternal, 3579 step: StepEdgeInternal, 3580 smoothstep: SmoothStepEdgeInternal, 3581 simplebezier: SimpleBezierEdgeInternal 3582}; 3583const nullPosition = { 3584 sourceX: null, 3585 sourceY: null, 3586 targetX: null, 3587 targetY: null, 3588 sourcePosition: null, 3589 targetPosition: null, 3590 zIndex: undefined 3591}; 3592const shiftX = (x, shift, position)=>{ 3593 if (position === _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Left) return x - shift; 3594 if (position === _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Right) return x + shift; 3595 return x; 3596}; 3597const shiftY = (y, shift, position)=>{ 3598 if (position === _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Top) return y - shift; 3599 if (position === _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Bottom) return y + shift; 3600 return y; 3601}; 3602const EdgeUpdaterClassName = "react-flow__edgeupdater"; 3603/** 3604 * @internal 3605 */ function EdgeAnchor(param) { 3606 let { position, centerX, centerY, radius = 10, onMouseDown, onMouseEnter, onMouseOut, type }
3606 = param; 3607 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("circle", { 3608 onMouseDown: onMouseDown, 3609 onMouseEnter: onMouseEnter, 3610 onMouseOut: onMouseOut, 3611 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 3612 EdgeUpdaterClassName, 3613 "".concat(EdgeUpdaterClassName, "-").concat(type) 3614 ]), 3615 cx: shiftX(centerX, radius, position), 3616 cy: shiftY(centerY, radius, position), 3617 r: radius, 3618 stroke: "transparent", 3619 fill: "transparent" 3620 }); 3621} 3622function EdgeUpdateAnchors(param) { 3623 let { isReconnectable, reconnectRadius, edge, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, onReconnect, onReconnectStart, onReconnectEnd, setReconnecting, setUpdateHover } = param; 3624 const store = useStoreApi(); 3625 const handleEdgeUpdater = (event, oppositeHandle)=>{ 3626 // avoid triggering edge updater if mouse btn is not left 3627 if (event.button !== 0) { 3628 return; 3629 } 3630 const { autoPanOnConnect, domNode, connectionMode, connectionRadius, lib, onConnectStart, cancelConnection, nodeLookup, rfId: flowId, panBy, updateConnection } = store.getState(); 3631 const isTarget = oppositeHandle.type === "target"; 3632 const _onReconnectEnd = (evt, connectionState)=>{ 3633 setReconnecting(false); 3634 onReconnectEnd === null || onReconnectEnd === void 0 ? void 0 : onReconnectEnd(evt, edge, oppositeHandle.type, connectionState); 3635 }; 3636 const onConnectEdge = (connection)=>onReconnect === null || onReconnect === void 0 ? void 0 : onReconnect(edge, connection); 3637 const _onConnectStart = (_event, params)=>{ 3638 setReconnecting(true); 3639 onReconnectStart === null || onReconnectStart === void 0 ? void 0 : onReconnectStart(event, edge, oppositeHandle.type); 3640 onConnectStart === null || onConnectStart === void 0 ? void 0 : onConnectStart(_event, params); 3641 }; 3642 _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .XYHandle */ .Ql.onPointerDown(event.nativeEvent, { 3643 autoPanOnConnect, 3644 connectionMode, 3645 connectionRadius, 3646 domNode, 3647 handleId: oppositeHandle.id,
3648 nodeId: oppositeHandle.nodeId, 3649 nodeLookup, 3650 isTarget, 3651 edgeUpdaterType: oppositeHandle.type, 3652 lib, 3653 flowId, 3654 cancelConnection, 3655 panBy, 3656 isValidConnection: function() { 3657 for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){ 3658 args[_key] = arguments[_key]; 3659 } 3660 var _store_getState_isValidConnection, _store_getState; 3661 var _store_getState_isValidConnection1; 3662 return (_store_getState_isValidConnection1 = (_store_getState_isValidConnection = (_store_getState = store.getState()).isValidConnection) === null || _store_getState_isValidConnection === void 0 ? void 0 : _store_getState_isValidConnection.call(_store_getState, ...args)) !== null && _store_getState_isValidConnection1 !== void 0 ? _store_getState_isValidConnection1 : true; 3663 }, 3664 onConnect: onConnectEdge, 3665 onConnectStart: _onConnectStart, 3666 onConnectEnd: function() { 3667 for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){ 3668 args[_key] = arguments[_key]; 3669 } 3670 var _store_getState_onConnectEnd, _store_getState; 3671 return (_store_getState_onConnectEnd = (_store_getState = store.getState()).onConnectEnd) === null || _store_getState_onConnectEnd === void 0 ? void 0 : _store_getState_onConnectEnd.call(_store_getState, ...args); 3672 }, 3673 onReconnectEnd: _onReconnectEnd, 3674 updateConnection, 3675 getTransform: ()=>store.getState().transform, 3676 getFromHandle: ()=>store.getState().connection.fromHandle, 3677 dragThreshold: store.getState().connectionDragThreshold, 3678 handleDomNode: event.currentTarget 3679 }); 3680 }; 3681 const onReconnectSourceMouseDown = (event)=>{ 3682 var _edge_targetHandle; 3683 return handleEdgeUpdater(event, { 3684 nodeId: edge.target, 3685 id: (_edge_targetHandle = edge.targetHandle) !== null && _edge_targetHandle !== void 0 ? _edge_targetHandle : null, 3686 type: "target" 3687 }); 3688 }; 3689 const onReconnectTargetMouseDown = (event)=>{ 3690 var _edge_sourceHandle; 3691 return handleEdgeUpdater(event, { 3692 nodeId: edge.source, 3693 id: (_edge_sourceHandle = edge.sourceHandle) !== null && _edge_sourceHandle !== void 0 ? _edge_sourceHandle : null, 3694 type: "source" 3695 }); 3696 }; 3697 const onReconnectMouseEnter = ()=>setUpdateHover(true); 3698 const onReconnectMouseOut = ()=>setUpdateHover(false); 3699 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, { 3700 children: [ 3701 (isReconnectable === true || isReconnectable === "source") && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(EdgeAnchor, { 3702 position: sourcePosition, 3703 centerX: sourceX, 3704 centerY: sourceY, 3705 radius: reconnectRadius, 3706 onMouseDown: onReconnectSourceMouseDown, 3707 onMouseEnter: onReconnectMouseEnter, 3708 onMouseOut: onReconnectMouseOut, 3709 type: "source" 3710 }), 3711 (isReconnectable === true || isReconnectable === "target") && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(EdgeAnchor, { 3712 position: targetPosition, 3713 centerX: targetX, 3714 centerY: targetY, 3715 radius: reconnectRadius, 3716 onMouseDown: onReconnectTargetMouseDown, 3717 onMouseEnter: onReconnectMouseEnter, 3718 onMouseOut: onReconnectMouseOut, 3719 type: "target" 3720 }) 3721 ] 3722 }); 3723} 3724function EdgeWrapper(param) { 3725 let { id, edgesFocusable, edgesReconnectable, elementsSelectable, onClick, onDoubleClick, onContextMenu, onMouseEnter, onMouseMove, onMouseLeave, reconnectRadius, onReconnect, onReconnectStart, onReconnectEnd, rfId, edgeTypes, noPanClassName, onError, disableKeyboardA11y } = param; 3726 let edge = useStore((s)=>s.edgeLookup.get(id)); 3727 const defaultEdgeOptions = useStore((s)=>s.defaultEdgeOptions); 3728 edge = defaultEdgeOptions ? {
3729 ...defaultEdgeOptions, 3730 ...edge 3731 } : edge; 3732 let edgeType = edge.type || "default"; 3733 let EdgeComponent = (edgeTypes === null || edgeTypes === void 0 ? void 0 : edgeTypes[edgeType]) || builtinEdgeTypes[edgeType]; 3734 if (EdgeComponent === undefined) { 3735 onError === null || onError === void 0 ? void 0 : onError("011", _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .errorMessages */ .Qj["error011"](edgeType)); 3736 edgeType = "default"; 3737 EdgeComponent = (edgeTypes === null || edgeTypes === void 0 ? void 0 : edgeTypes["default"]) || builtinEdgeTypes.default; 3738 } 3739 const isFocusable = !!(edge.focusable || edgesFocusable && typeof edge.focusable === "undefined"); 3740 const isReconnectable = typeof onReconnect !== "undefined" && (edge.reconnectable || edgesReconnectable && typeof edge.reconnectable === "undefined"); 3741 const isSelectable = !!(edge.selectable || elementsSelectable && typeof edge.selectable === "undefined"); 3742 const edgeRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null); 3743 const [updateHover, setUpdateHover] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(false); 3744 const [reconnecting, setReconnecting] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(false); 3745 const store = useStoreApi(); 3746 const { zIndex = edge.zIndex, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition } = useStore((0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)((store)=>{ 3747 const sourceNode = store.nodeLookup.get(edge.source); 3748 const targetNode = store.nodeLookup.get(edge.target); 3749 if (!sourceNode || !targetNode) { 3750 return nullPosition; 3751 } 3752 const edgePosition = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getEdgePosition */ .JU)({ 3753 id, 3754 sourceNode, 3755 targetNode, 3756 sourceHandle: edge.sourceHandle || null, 3757 targetHandle: edge.targetHandle || null, 3758 connectionMode: store.connectionMode, 3759 onError 3760 }); 3761 const zIndex = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getElevatedEdgeZIndex */ .xx)({ 3762 selected: edge.selected, 3763 zIndex: edge.zIndex, 3764 sourceNode, 3765 targetNode, 3766 elevateOnSelect: store.elevateEdgesOnSelect, 3767 zIndexMode: store.zIndexMode 3768 }); 3769 return { 3770 ...edgePosition || nullPosition, 3771 zIndex 3772 }; 3773 }, [ 3774 edge.source, 3775 edge.target, 3776 edge.sourceHandle, 3777 edge.targetHandle, 3778 edge.selected, 3779 edge.zIndex 3780 ]), zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 3781 const markerStartUrl = (0,react__WEBPACK_IMPORTED_MODULE_1__.useMemo)(()=>edge.markerStart ? "url('#".concat((0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getMarkerId */ .dW)(edge.markerStart, rfId), "')") : undefined, [ 3782 edge.markerStart, 3783 rfId 3784 ]); 3785 const markerEndUrl = (0,react__WEBPACK_IMPORTED_MODULE_1__.useMemo)(()=>edge.markerEnd ? "url('#".concat((0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getMarkerId */ .dW)(edge.markerEnd, rfId), "')") : undefined, [ 3786 edge.markerEnd, 3787 rfId 3788 ]); 3789 if (edge.hidden || sourceX === null || sourceY === null || targetX === null || targetY === null) { 3790 return null; 3791 } 3792 const onEdgeClick = (event)=>{ 3793 const { addSelectedEdges, unselectNodesAndEdges, multiSelectionActive } = store.getState(); 3794 if (isSelectable) { 3795 store.setState({ 3796 nodesSelectionActive: false 3797 }); 3798 if (edge.selected && multiSelectionActive) { 3799 var _edgeRef_current; 3800 unselectNodesAndEdges({ 3801 nodes: [], 3802 edges: [ 3803 edge 3804 ] 3805 }); 3806 (_edgeRef_current = edgeRef.current) === null || _edgeRef_current === void 0 ? void 0 : _edgeRef_current.blur(); 3807 } else { 3808 addSelectedEdges([ 3809 id 3810 ]); 3811 } 3812 } 3813 if (onClick) { 3814 onClick(event, edge); 3815 } 3816 }; 3817 const onEdgeDoubleClick = onDoubleClick ? (event)=>{ 3818 onDoubleClick(event, { 3819 ...edge 3820 }); 3821 } : undefined; 3822 const onEdgeContextMenu = onContextMenu ? (event)=>{ 3823 onContextMenu(event, { 3824 ...edge 3825 }); 3826 } : undefined; 3827 const onEdgeMouseEnter = onMouseEnter ? (event)=>{ 3828 onMouseEnter(event, { 3829 ...edge 3830 }); 3831 } : undefined; 3832 const onEdgeMouseMove = onMouseMove ? (event)=>{ 3833 onMouseMove(event, { 3834 ...edge 3835 }); 3836 } : undefined; 3837 const onEdgeMouseLeave = onMouseLeave ? (event)=>{ 3838 onMouseLeave(event, { 3839 ...edge 3840 }); 3841 } : undefined; 3842 const onKeyDown = (event)=>{ 3843 if (!disableKeyboardA11y && _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .elementSelectionKeys */ .wQ.includes(event.key) && isSelectable) { 3844 const { unselectNodesAndEdges, addSelectedEdges } = store.getState(); 3845 const unselect = event.key === "Escape"; 3846 if (unselect) { 3847 var _edgeRef_current; 3848 (_edgeRef_current = edgeRef.current) === null || _edgeRef_current === void 0 ? void 0 : _edgeRef_current.blur(); 3849 unselectNodesAndEdges({ 3850 edges: [ 3851 edge 3852 ] 3853 }); 3854 } else { 3855 addSelectedEdges([ 3856 id 3857 ]); 3858 } 3859 } 3860 }; 3861 var _edge_ariaRole, _edge_deletable; 3862 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("svg", { 3863 style: { 3864 zIndex 3865 }, 3866 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("g", { 3867 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 3868 "react-flow__edge", 3869 "react-flow__edge-".concat(edgeType), 3870 edge.className, 3871 noPanClassName, 3872 { 3873 selected: edge.selected, 3874 animated: edge.animated, 3875 inactive: !isSelectable && !onClick, 3876 updating: updateHover, 3877 selectable: isSelectable 3878 } 3879 ]), 3880 onClick: onEdgeClick, 3881 onDoubleClick: onEdgeDoubleClick, 3882 onContextMenu: onEdgeContextMenu, 3883 onMouseEnter: onEdgeMouseEnter, 3884 onMouseMove: onEdgeMouseMove, 3885 onMouseLeave: onEdgeMouseLeave, 3886 onKeyDown: isFocusable ? onKeyDown : undefined,
3887 tabIndex: isFocusable ? 0 : undefined, 3888 role: (_edge_ariaRole = edge.ariaRole) !== null && _edge_ariaRole !== void 0 ? _edge_ariaRole : isFocusable ? "group" : "img", 3889 "aria-roledescription": "edge", 3890 "data-id": id, 3891 "data-testid": "rf__edge-".concat(id), 3892 "aria-label": edge.ariaLabel === null ? undefined : edge.ariaLabel || "Edge from ".concat(edge.source, " to ").concat(edge.target), 3893 "aria-describedby": isFocusable ? "".concat(ARIA_EDGE_DESC_KEY, "-").concat(rfId) : undefined, 3894 ref: edgeRef, 3895 ...edge.domAttributes, 3896 children: [ 3897 !reconnecting && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(EdgeComponent, { 3898 id: id, 3899 source: edge.source, 3900 target: edge.target, 3901 type: edge.type, 3902 selected: edge.selected, 3903 animated: edge.animated, 3904 selectable: isSelectable, 3905 deletable: (_edge_deletable = edge.deletable) !== null && _edge_deletable !== void 0 ? _edge_deletable : true, 3906 label: edge.label, 3907 labelStyle: edge.labelStyle, 3908 labelShowBg: edge.labelShowBg, 3909 labelBgStyle: edge.labelBgStyle, 3910 labelBgPadding: edge.labelBgPadding, 3911 labelBgBorderRadius: edge.labelBgBorderRadius, 3912 sourceX: sourceX, 3913 sourceY: sourceY, 3914 targetX: targetX, 3915 targetY: targetY, 3916 sourcePosition: sourcePosition, 3917 targetPosition: targetPosition, 3918 data: edge.data, 3919 style: edge.style, 3920 sourceHandleId: edge.sourceHandle, 3921 targetHandleId: edge.targetHandle, 3922 markerStart: markerStartUrl, 3923 markerEnd: markerEndUrl, 3924 pathOptions: "pathOptions" in edge ? edge.pathOptions : undefined, 3925 interactionWidth: edge.interactionWidth 3926 }), 3927 isReconnectable && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(EdgeUpdateAnchors, { 3928 edge: edge, 3929 isReconnectable: isReconnectable, 3930 reconnectRadius: reconnectRadius, 3931 onReconnect: onReconnect, 3932 onReconnectStart: onReconnectStart, 3933 onReconnectEnd: onReconnectEnd, 3934 sourceX: sourceX, 3935 sourceY: sourceY, 3936 targetX: targetX, 3937 targetY: targetY, 3938 sourcePosition: sourcePosition, 3939 targetPosition: targetPosition, 3940 setUpdateHover: setUpdateHover, 3941 setReconnecting: setReconnecting 3942 }) 3943 ] 3944 }) 3945 }); 3946} 3947var EdgeWrapper$1 = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(EdgeWrapper); 3948const selector$9 = (s)=>({ 3949 edgesFocusable: s.edgesFocusable, 3950 edgesReconnectable: s.edgesReconnectable, 3951 elementsSelectable: s.elementsSelectable, 3952 connectionMode: s.connectionMode, 3953 onError: s.onError 3954 }); 3955function EdgeRendererComponent(param) { 3956 let { defaultMarkerColor, onlyRenderVisibleElements, rfId, edgeTypes, noPanClassName, onReconnect, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeClick, reconnectRadius, onEdgeDoubleClick, onReconnectStart, onReconnectEnd, disableKeyboardA11y } = param; 3957 const { edgesFocusable, edgesReconnectable, elementsSelectable, onError } = useStore(selector$9, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 3958 const edgeIds = useVisibleEdgeIds(onlyRenderVisibleElements); 3959 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("div", { 3960 className: "react-flow__edges", 3961 children: [ 3962 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(MarkerDefinitions$1, { 3963 defaultColor: defaultMarkerColor, 3964 rfId: rfId 3965 }), 3966 edgeIds.map((id)=>{ 3967 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(EdgeWrapper$1, { 3968 id: id, 3969 edgesFocusable: edgesFocusable, 3970 edgesReconnectable: edgesReconnectable, 3971 elementsSelectable: elementsSelectable, 3972 noPanClassName: noPanClassName, 3973 onReconnect: onReconnect, 3974 onContextMenu: onEdgeContextMenu, 3975 onMouseEnter: onEdgeMouseEnter, 3976 onMouseMove: onEdgeMouseMove, 3977 onMouseLeave: onEdgeMouseLeave, 3978 onClick: onEdgeClick, 3979 reconnectRadius: reconnectRadius, 3980 onDoubleClick: onEdgeDoubleClick, 3981 onReconnectStart: onReconnectStart, 3982 onReconnectEnd: onReconnectEnd, 3983 rfId: rfId, 3984 onError: onError, 3985 edgeTypes: edgeTypes, 3986 disableKeyboardA11y: disableKeyboardA11y 3987 }, id); 3988 }) 3989 ] 3990 }); 3991} 3992EdgeRendererComponent.displayName = "EdgeRenderer"; 3993const EdgeRenderer = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(EdgeRendererComponent); 3994const toTransformString = (transform)=>"translate(".concat(transform[0], "px,").concat(transform[1], "px) scale(").concat(transform[2], ")"); 3995function Viewport(param) { 3996 let { children } = param; 3997 const store = useStoreApi(); 3998 const viewportRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null); 3999 // seed the transform for first paint and SSR without subscribing, so we don't re-render on pan/zoom 4000 const [initialTransform] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(()=>store.getState().transform); 4001 // transform changes every pan/zoom frame, so write it to the DOM directly to keep React out of the hot path 4002 useIsomorphicLayoutEffect(()=>{ 4003 let prevTransform = null; 4004 const applyTransform = ()=>{ 4005 const transform = store.getState().transform; 4006 // store.subscribe fires on every update, so only touch the DOM when x, y or zoom actually changed 4007 if (prevTransform && transform[0] === prevTransform[0] && transform[1] === prevTransform[1] && transform[2] === prevTransform[2]) { 4008 return; 4009 } 4010 prevTransform = transform; 4011 if (viewportRef.current) { 4012 viewportRef.current.style.transform = toTransformString(transform); 4013 } 4014 }; 4015 applyTransform();
4016 return store.subscribe(applyTransform); 4017 }, [ 4018 store 4019 ]); 4020 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 4021 ref: viewportRef, 4022 className: "react-flow__viewport xyflow__viewport react-flow__container", 4023 style: { 4024 transform: toTransformString(initialTransform) 4025 }, 4026 children: children 4027 }); 4028} 4029/** 4030 * Hook for calling onInit handler. 4031 * 4032 * @internal 4033 */ function useOnInitHandler(onInit) { 4034 const rfInstance = useReactFlow(); 4035 const isInitialized = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(false); 4036 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 4037 if (!isInitialized.current && rfInstance.viewportInitialized && onInit) { 4038 setTimeout(()=>onInit(rfInstance), 1); 4039 isInitialized.current = true; 4040 } 4041 }, [ 4042 onInit, 4043 rfInstance.viewportInitialized 4044 ]); 4045} 4046const selector$8 = (state)=>{ 4047 var _state_panZoom; 4048 return (_state_panZoom = state.panZoom) === null || _state_panZoom === void 0 ? void 0 : _state_panZoom.syncViewport; 4049}; 4050/** 4051 * Hook for syncing the viewport with the panzoom instance. 4052 * 4053 * @internal 4054 * @param viewport 4055 */ function useViewportSync(viewport) { 4056 const syncViewport = useStore(selector$8); 4057 const store = useStoreApi(); 4058 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 4059 if (viewport) { 4060 syncViewport === null || syncViewport === void 0 ? void 0 : syncViewport(viewport); 4061 store.setState({ 4062 transform: [ 4063 viewport.x, 4064 viewport.y, 4065 viewport.zoom 4066 ] 4067 }); 4068 } 4069 }, [ 4070 viewport, 4071 syncViewport 4072 ]); 4073 return null; 4074} 4075function storeSelector$1(s) { 4076 return s.connection.inProgress ? { 4077 ...s.connection, 4078 to: (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .pointToRendererPoint */ .m)(s.connection.to, s.transform) 4079 } : { 4080 ...s.connection 4081 }; 4082} 4083function getSelector(connectionSelector) { 4084 if (connectionSelector) { 4085 const combinedSelector = (s)=>{ 4086 const connection = storeSelector$1(s); 4087 return connectionSelector(connection); 4088 }; 4089 return combinedSelector; 4090 } 4091 return storeSelector$1; 4092} 4093/** 4094 * The `useConnection` hook returns the current connection when there is an active 4095 * connection interaction. If no connection interaction is active, it returns null 4096 * for every property. A typical use case for this hook is to colorize handles 4097 * based on a certain condition (e.g. if the connection is valid or not). 4098 * 4099 * @public 4100 * @param connectionSelector - An optional selector function used to extract a slice of the 4101 * `ConnectionState` data. Using a selector can prevent component re-renders where data you don't 4102 * otherwise care about might change. If a selector is not provided, the entire `ConnectionState` 4103 * object is returned unchanged. 4104 * @example 4105 * 4106 * ```tsx 4107 *import { useConnection } from '@xyflow/react'; 4108 * 4109 *function App() { 4110 * const connection = useConnection(); 4111 * 4112 * return ( 4113 * <div> {connection ? `Someone is trying to make a connection from ${connection.fromNode} to this one.` : 'There are currently no incoming connections!'} 4114 * 4115 * </div> 4116 * ); 4117 * } 4118 * ``` 4119 * 4120 * @returns ConnectionState 4121 */ function useConnection(connectionSelector) { 4122 const combinedSelector = getSelector(connectionSelector); 4123 return useStore(combinedSelector, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 4124} 4125const selector$7 = (s)=>({ 4126 nodesConnectable: s.nodesConnectable, 4127 isValid: s.connection.isValid, 4128 inProgress: s.connection.inProgress, 4129 width: s.width, 4130 height: s.height 4131 }); 4132function ConnectionLineWrapper(param) { 4133 let { containerStyle, style, type, component } = param; 4134 const { nodesConnectable, width, height, isValid, inProgress } = useStore(selector$7, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 4135 const renderConnection = !!(width && nodesConnectable && inProgress); 4136 if (!renderConnection) { 4137 return null; 4138 } 4139 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("svg", { 4140 style: containerStyle, 4141 width: width, 4142 height: height, 4143 className: "react-flow__connectionline react-flow__container", 4144 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("g", { 4145 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 4146 "react-flow__connection", 4147 (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getConnectionStatus */ .Zp)(isValid) 4148 ]), 4149 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ConnectionLine, { 4150 style: style, 4151 type: type, 4152 CustomComponent: component, 4153 isValid: isValid 4154 }) 4155 }) 4156 }); 4157} 4158const ConnectionLine = (param)=>{ 4159 let { style, type = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .ConnectionLineType */ .t8.Bezier, CustomComponent, isValid } = param; 4160 const { inProgress, from, fromNode, fromHandle, fromPosition, to, toNode, toHandle, toPosition, pointer } = useConnection(); 4161 if (!inProgress) { 4162 return; 4163 } 4164 if (CustomComponent) { 4165 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(CustomComponent, { 4166 connectionLineType: type, 4167 connectionLineStyle: style, 4168 fromNode: fromNode, 4169 fromHandle: fromHandle, 4170 fromX: from.x, 4171 fromY: from.y, 4172 toX: to.x, 4173 toY: to.y, 4174 fromPosition: fromPosition, 4175 toPosition: toPosition, 4176 connectionStatus: (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getConnectionStatus */ .Zp)(isValid), 4177 toNode: toNode, 4178 toHandle: toHandle, 4179 pointer: pointer 4180 }); 4181 } 4182 let path = ""; 4183 const pathParams = { 4184 sourceX: from.x, 4185 sourceY: from.y, 4186 sourcePosition: fromPosition, 4187 targetX: to.x, 4188 targetY: to.y, 4189 targetPosition: toPosition 4190 }; 4191 switch(type){ 4192 case _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .ConnectionLineType */ .t8.Bezier: 4193 [path] = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getBezierPath */ .OQ)(pathParams); 4194 break; 4195 case _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .ConnectionLineType */ .t8.SimpleBezier: 4196 [path] = getSimpleBezierPath(pathParams); 4197 break; 4198 case _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .ConnectionLineType */ .t8.Step: 4199 [path] = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getSmoothStepPath */ .OW)({ 4200 ...pathParams, 4201 borderRadius: 0 4202 }); 4203 break; 4204 case _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .ConnectionLineType */ .t8.SmoothStep: 4205 [path] = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getSmoothStepPath */ .OW)(pathParams); 4206 break; 4207 default: 4208 [path] = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getStraightPath */ .Hm)(pathParams); 4209 } 4210 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("path", { 4211 d: path, 4212 fill: "none", 4213 className: "react-flow__connection-path", 4214 style: style 4215 }); 4216}; 4217ConnectionLine.displayName = "ConnectionLine"; 4218const emptyTypes = {}; 4219// eslint-disable-next-line @typescript-eslint/no-explicit-any 4220function useNodeOrEdgeTypesWarning() { 4221 let nodeOrEdgeTypes = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : emptyTypes; 4222 const typesRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(nodeOrEdgeTypes); 4223 const store = useStoreApi(); 4224 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 4225 if (false) { var _store_getState_onError, _store_getState; } 4226 }, [ 4227 nodeOrEdgeTypes 4228 ]); 4229} 4230function useStylesLoadedWarning() { 4231 const store = useStoreApi(); 4232 const checked = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(false); 4233 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 4234 if (false) { var _store_getState_onError, _store_getState; } 4235 }, []); 4236} 4237function GraphViewComponent(param) { 4238 let { nodeTypes, edgeTypes, onInit, onNodeClick, onEdgeClick, onNodeDoubleClick, onEdgeDoubleClick, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onSelectionContextMenu, onSelectionStart, onSelectionEnd, connectionLineType, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, selectionKeyCode, selectionOnDrag, selectionMode, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, deleteKeyCode, onlyRenderVisibleElements, elementsSelectable, defaultViewport, translateExtent, minZoom, maxZoom, preventScrolling, defaultMarkerColor, zoomOnScroll, zoomOnPinch, panOnScroll, panOnScrollSpeed, panOnScrollMode, zoomOnDoubleClick, panOnDrag, autoPanOnSelection, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, paneClickDistance, nodeClickDistance, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, reconnectRadius, onReconnect, onReconnectStart, onReconnectEnd, noDragClassName, noWheelClassName, noPanClassName, disableKeyboardA11y, nodeExtent, rfId, viewport, onViewportChange, nodesDraggable } = param; 4239 useNodeOrEdgeTypesWarning(nodeTypes); 4240 useNodeOrEdgeTypesWarning(edgeTypes); 4241 useStylesLoadedWarning(); 4242 useOnInitHandler(onInit); 4243 useViewportSync(viewport); 4244 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(FlowRenderer, { 4245 onPaneClick: onPaneClick, 4246 onPaneMouseEnter: onPaneMouseEnter, 4247 onPaneMouseMove: onPaneMouseMove, 4248 onPaneMouseLeave: onPaneMouseLeave, 4249 onPaneContextMenu: onPaneContextMenu, 4250 onPaneScroll: onPaneScroll, 4251 paneClickDistance: paneClickDistance, 4252 deleteKeyCode: deleteKeyCode, 4253 selectionKeyCode: selectionKeyCode, 4254 selectionOnDrag: selectionOnDrag, 4255 selectionMode: selectionMode, 4256 onSelectionStart: onSelectionStart, 4257 onSelectionEnd: onSelectionEnd, 4258 multiSelectionKeyCode: multiSelectionKeyCode, 4259 panActivationKeyCode: panActivationKeyCode, 4260 zoomActivationKeyCode: zoomActivationKeyCode, 4261 elementsSelectable: elementsSelectable, 4262 zoomOnScroll: zoomOnScroll, 4263 zoomOnPinch: zoomOnPinch, 4264 zoomOnDoubleClick: zoomOnDoubleClick, 4265 panOnScroll: panOnScroll, 4266 panOnScrollSpeed: panOnScrollSpeed, 4267 panOnScrollMode: panOnScrollMode, 4268 panOnDrag: panOnDrag, 4269 autoPanOnSelection: autoPanOnSelection, 4270 defaultViewport: defaultViewport, 4271 translateExtent: translateExtent, 4272 minZoom: minZoom, 4273 maxZoom: maxZoom, 4274 onSelectionContextMenu: onSelectionContextMenu, 4275 preventScrolling: preventScrolling, 4276 noDragClassName: noDragClassName, 4277 noWheelClassName: noWheelClassName, 4278 noPanClassName: noPanClassName, 4279 disableKeyboardA11y: disableKeyboardA11y, 4280 onViewportChange: onViewportChange, 4281 isControlledViewport: !!viewport, 4282 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(Viewport, { 4283 children: [ 4284 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(EdgeRenderer, { 4285 edgeTypes: edgeTypes, 4286 onEdgeClick: onEdgeClick, 4287 onEdgeDoubleClick: onEdgeDoubleClick, 4288 onReconnect: onReconnect, 4289 onReconnectStart: onReconnectStart, 4290 onReconnectEnd: onReconnectEnd, 4291 onlyRenderVisibleElements: onlyRenderVisibleElements, 4292 onEdgeContextMenu: onEdgeContextMenu, 4293 onEdgeMouseEnter: onEdgeMouseEnter, 4294 onEdgeMouseMove: onEdgeMouseMove, 4295 onEdgeMouseLeave: onEdgeMouseLeave, 4296 reconnectRadius: reconnectRadius, 4297 defaultMarkerColor: defaultMarkerColor, 4298 noPanClassName: noPanClassName, 4299 disableKeyboardA11y: disableKeyboardA11y, 4300 rfId: rfId 4301 }), 4302 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ConnectionLineWrapper, { 4303 style: connectionLineStyle, 4304 type: connectionLineType, 4305 component: connectionLineComponent, 4306 containerStyle: connectionLineContainerStyle 4307 }), 4308 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 4309 className: "react-flow__edgelabel-renderer" 4310 }), 4311 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(NodeRenderer, { 4312 nodeTypes: nodeTypes, 4313 onNodeClick: onNodeClick, 4314 onNodeDoubleClick: onNodeDoubleClick, 4315 onNodeMouseEnter: onNodeMouseEnter, 4316 onNodeMouseMove: onNodeMouseMove, 4317 onNodeMouseLeave: onNodeMouseLeave, 4318 onNodeContextMenu: onNodeContextMenu, 4319 nodeClickDistance: nodeClickDistance, 4320 onlyRenderVisibleElements: onlyRenderVisibleElements, 4321 noPanClassName: noPanClassName, 4322 noDragClassName: noDragClassName, 4323 disableKeyboardA11y: disableKeyboardA11y, 4324 nodeExtent: nodeExtent, 4325 rfId: rfId, 4326 nodesDraggable: nodesDraggable 4327 }), 4328 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 4329 className: "react-flow__viewport-portal" 4330 }) 4331 ] 4332 }) 4333 }); 4334} 4335GraphViewComponent.displayName = "GraphView"; 4336const GraphView = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(GraphViewComponent); 4337const devWarn = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .createDevWarn */ .F1)("React Flow", "https://reactflow.dev/"); 4338const getInitialState = function() { 4339 let { nodes, edges, defaultNodes, defaultEdges, width, height, fitView, fitViewOptions, minZ
4339oom = 0.5, maxZoom = 2, nodeOrigin, nodeExtent, zIndexMode = "basic" } = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; 4340 const nodeLookup = new Map(); 4341 const parentLookup = new Map(); 4342 const connectionLookup = new Map(); 4343 const edgeLookup = new Map(); 4344 var _ref; 4345 const storeEdges = (_ref = defaultEdges !== null && defaultEdges !== void 0 ? defaultEdges : edges) !== null && _ref !== void 0 ? _ref : []; 4346 var _ref1; 4347 const storeNodes = (_ref1 = defaultNodes !== null && defaultNodes !== void 0 ? defaultNodes : nodes) !== null && _ref1 !== void 0 ? _ref1 : []; 4348 const storeNodeOrigin = nodeOrigin !== null && nodeOrigin !== void 0 ? nodeOrigin : [ 4349 0, 4350 0 4351 ]; 4352 const storeNodeExtent = nodeExtent !== null && nodeExtent !== void 0 ? nodeExtent : _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .infiniteExtent */ .k5; 4353 (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .updateConnectionLookup */ .be)(connectionLookup, edgeLookup, storeEdges); 4354 const { nodesInitialized } = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .adoptUserNodes */ .yF)(storeNodes, nodeLookup, parentLookup, { 4355 nodeOrigin: storeNodeOrigin, 4356 nodeExtent: storeNodeExtent, 4357 zIndexMode 4358 }); 4359 let transform = [ 4360 0, 4361 0, 4362 1 4363 ]; 4364 if (fitView && width && height) { 4365 const bounds = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getInternalNodesBounds */ .W0)(nodeLookup, { 4366 filter: (node)=>!!((node.width || node.initialWidth) && (node.height || node.initialHeight)) 4367 }); 4368 var _fitViewOptions_padding; 4369 const { x, y, zoom } = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getViewportForBounds */ .$i)(bounds, width, height, minZoom, maxZoom, (_fitViewOptions_padding = fitViewOptions === null || fitViewOptions === void 0 ? void 0 : fitViewOptions.padding) !== null && _fitViewOptions_padding !== void 0 ? _fitViewOptions_padding : 0.1); 4370 transform = [ 4371 x, 4372 y, 4373 zoom 4374 ]; 4375 } 4376 return { 4377 rfId: "1", 4378 width: width !== null && width !== void 0 ? width : 0, 4379 height: height !== null && height !== void 0 ? height : 0, 4380 transform, 4381 nodes: storeNodes, 4382 nodesInitialized, 4383 nodeLookup, 4384 parentLookup, 4385 edges: storeEdges, 4386 edgeLookup, 4387 connectionLookup, 4388 onNodesChange: null, 4389 onEdgesChange: null, 4390 hasDefaultNodes: defaultNodes !== undefined, 4391 hasDefaultEdges: defaultEdges !== undefined, 4392 panZoom: null, 4393 minZoom, 4394 maxZoom, 4395 translateExtent: _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .infiniteExtent */ .k5, 4396 nodeExtent: storeNodeExtent, 4397 nodesSelectionActive: false, 4398 userSelectionActive: false, 4399 userSelectionRect: null, 4400 connectionMode: _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .ConnectionMode */ .jD.Strict, 4401 domNode: null, 4402 paneDragging: false, 4403 noPanClassName: "nopan", 4404 nodeOrigin: storeNodeOrigin, 4405 nodeDragThreshold: 1, 4406 connectionDragThreshold: 1, 4407 snapGrid: [ 4408 15, 4409 15 4410 ], 4411 snapToGrid: false, 4412 nodesDraggable: true, 4413 nodesConnectable: true, 4414 nodesFocusable: true, 4415 edgesFocusable: true, 4416 edgesReconnectable: true, 4417 elementsSelectable: true, 4418 elevateNodesOnSelect: true, 4419 elevateEdgesOnSelect: true, 4420 selectNodesOnDrag: true, 4421 multiSelectionActive: false, 4422 fitViewQueued: fitView !== null && fitView !== void 0 ? fitView : false, 4423 fitViewOptions, 4424 fitViewResolver: null, 4425 connection: { 4426 ..._xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .initialConnection */ .Ky 4427 }, 4428 connectionClickStartHandle: null, 4429 connectOnClick: true, 4430 ariaLiveMessage: "", 4431 autoPanOnConnect: true, 4432 autoPanOnNodeDrag: true, 4433 autoPanOnNodeFocus: true, 4434 autoPanSpeed: 15, 4435 connectionRadius: 20, 4436 onError: devWarn, 4437 isValidConnection: undefined, 4438 onSelectionChangeHandlers: [], 4439 lib: "react", 4440 debug: false, 4441 ariaLabelConfig: _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .defaultAr
4441iaLabelConfig */ .Z, 4442 zIndexMode, 4443 onNodesChangeMiddlewareMap: new Map(), 4444 onEdgesChangeMiddlewareMap: new Map() 4445 }; 4446}; 4447const createStore = (param)=>{ 4448 let { nodes, edges, defaultNodes, defaultEdges, width, height, fitView, fitViewOptions, minZoom, maxZoom, nodeOrigin, nodeExtent, zIndexMode } = param; 4449 return (0,zustand_traditional__WEBPACK_IMPORTED_MODULE_4__/* .createWithEqualityFn */ .F)((set, get)=>{ 4450 async function resolveFitView() { 4451 const { nodeLookup, panZoom, fitViewOptions, fitViewResolver, width, height, minZoom, maxZoom } = get(); 4452 if (!panZoom) { 4453 return; 4454 } 4455 await (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .fitViewport */ .Eg)({ 4456 nodes: nodeLookup, 4457 width, 4458 height, 4459 panZoom, 4460 minZoom, 4461 maxZoom 4462 }, fitViewOptions); 4463 fitViewResolver === null || fitViewResolver === void 0 ? void 0 : fitViewResolver.resolve(true); 4464 /** 4465 * wait for the fitViewport to resolve before deleting the resolver, 4466 * we want to reuse the old resolver if the user calls fitView again in the mean time 4467 */ set({ 4468 fitViewResolver: null 4469 }); 4470 } 4471 return { 4472 ...getInitialState({ 4473 nodes, 4474 edges, 4475 width, 4476 height, 4477 fitView, 4478 fitViewOptions, 4479 minZoom, 4480 maxZoom, 4481 nodeOrigin, 4482 nodeExtent, 4483 defaultNodes, 4484 defaultEdges, 4485 zIndexMode 4486 }), 4487 setNodes: (nodes)=>{ 4488 const { nodeLookup, parentLookup, nodeOrigin, elevateNodesOnSelect, fitViewQueued, zIndexMode, nodesSelectionActive } = get(); 4489 /* 4490 * setNodes() is called exclusively in response to user actions: 4491 * - either when the `<ReactFlow nodes>` prop is updated in the controlled ReactFlow setup, 4492 * - or when the user calls something like `reactFlowInstance.setNodes()` in an uncontrolled ReactFlow setup. 4493 * 4494 * When this happens, we take the note objects passed by the user and extend them with fields 4495 * relevant for internal React Flow operations. 4496 */ const { nodesInitialized, hasSelectedNodes } = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .adoptUserNodes */ .yF)(nodes, nodeLookup, parentLookup, { 4497 nodeOrigin, 4498 nodeExtent, 4499 elevateNodesOnSelect, 4500 checkEquality: true, 4501 zIndexMode 4502 }); 4503 const nextNodesSelectionActive = nodesSelectionActive && hasSelectedNodes; 4504 if (fitViewQueued && nodesInitialized) { 4505 resolveFitView(); 4506 set({ 4507 nodes, 4508 nodesInitialized, 4509 fitViewQueued: false, 4510 fitViewOptions: undefined, 4511 nodesSelectionActive: nextNodesSelectionActive 4512 }); 4513 } else { 4514 set({ 4515 nodes, 4516 nodesInitialized, 4517 nodesSelectionActive: nextNodesSelectionActive 4518 }); 4519 } 4520 }, 4521 setEdges: (edges)=>{ 4522 const { connectionLookup, edgeLookup } = get(); 4523 (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .updateConnectionLookup */ .be)(connectionLookup, edgeLookup, edges); 4524 set({ 4525 edges 4526 }); 4527 }, 4528 setDefaultNodesAndEdges: (nodes, edges)=>{ 4529 if (nodes) { 4530 const { setNodes } = get(); 4531 setNodes(nodes); 4532 set({ 4533 hasDefaultNodes: true 4534 }); 4535 } 4536 if (edges) { 4537 const { setEdges } = get(); 4538 setEdges(edges); 4539 set({ 4540 hasDefaultEdges: true 4541 }); 4542 } 4543 }, 4544 /* 4545 * Every node gets registered at a ResizeObserver. Whenever a node 4546 * changes its dimensions, this function is called to measure the 4547 * new dimensions and update the nodes. 4548 */ updateNodeInternals: (updates)=>{ 4549 const { triggerNodeChanges, nodeLookup, parentLookup, domNo
4549de, nodeOrigin, nodeExtent, debug, fitViewQueued, zIndexMode } = get(); 4550 const { changes, updatedInternals } = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .updateNodeInternals */ .B1)(updates, nodeLookup, parentLookup, domNode, nodeOrigin, nodeExtent, zIndexMode); 4551 if (!updatedInternals) { 4552 return; 4553 } 4554 (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .updateAbsolutePositions */ .VV)(nodeLookup, parentLookup, { 4555 nodeOrigin, 4556 nodeExtent, 4557 zIndexMode 4558 }); 4559 if (fitViewQueued) { 4560 resolveFitView(); 4561 set({ 4562 fitViewQueued: false, 4563 fitViewOptions: undefined 4564 }); 4565 } else { 4566 // we always want to trigger useStore calls whenever updateNodeInternals is called 4567 set({}); 4568 } 4569 if ((changes === null || changes === void 0 ? void 0 : changes.length) > 0) { 4570 if (debug) { 4571 console.log("React Flow: trigger node changes", changes); 4572 } 4573 triggerNodeChanges === null || triggerNodeChanges === void 0 ? void 0 : triggerNodeChanges(changes); 4574 } 4575 }, 4576 updateNodePositions: function(nodeDragItems) { 4577 let dragging = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false; 4578 const parentExpandChildren = []; 4579 let changes = []; 4580 const { nodeLookup, triggerNodeChanges, connection, updateConnection, onNodesChangeMiddlewareMap } = get(); 4581 for (const [id, dragItem] of nodeDragItems){ 4582 // we are using the nodelookup to be sure to use the current expandParent and parentId value 4583 const node = nodeLookup.get(id); 4584 const expandParent = !!((node === null || node === void 0 ? void 0 : node.expandParent) && (node === null || node === void 0 ? void 0 : node.parentId) && (dragItem === null || dragItem === void 0 ? void 0 : dragItem.position)); 4585 const change = { 4586 id, 4587 type: "position", 4588 position: expandParent ? { 4589 x: Math.max(0, dragItem.position.x), 4590 y: Math.max(0, dragItem.position.y) 4591 } : dragItem.position, 4592 dragging 4593 }; 4594 if (node && connection.inProgress && connection.fromNode.id === node.id) { 4595 const updatedFrom = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getHandlePosition */ .OH)(node, connection.fromHandle, _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .Position */ .Ly.Left, true); 4596 updateConnection({ 4597 ...connection, 4598 from: updatedFrom 4599 }); 4600 } 4601 if (expandParent && node.parentId) { 4602 var _dragItem_measured_width, _dragItem_measured_height; 4603 parentExpandChildren.push({ 4604 id, 4605 parentId: node.parentId, 4606 rect: { 4607 ...dragItem.internals.positionAbsolute, 4608 width: (_dragItem_measured_width = dragItem.measured.width) !== null && _dragItem_measured_width !== void 0 ? _dragItem_measured_width : 0, 4609 height: (_dragItem_measured_height = dragItem.measured.height) !== null && _dragItem_measured_height !== void 0 ? _dragItem_measured_height : 0 4610 } 4611 }); 4612 } 4613 changes.push(change); 4614 } 4615 if (parentExpandChildren.length > 0) { 4616 const { parentLookup, nodeOrigin } = get(); 4617 const parentExpandChanges = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .handleExpandParent */ .so)(parentExpandChildren, nodeLookup, parentLookup, nodeOrigin); 4618 changes.push(...parentExpandChanges); 4619 } 4620 for (const middleware of onNodesChangeMiddlewareMap.values()){ 4621 changes = middleware(changes); 4622 } 4623 triggerNodeChanges(changes); 4624 }, 4625 triggerNodeChanges: (changes)=>{ 4626 const { onNodesChange, setNodes, nodes, hasDefaultNodes, debug } = get(); 4627 if (changes === null || changes === void 0 ? void 0 : changes.length) { 4628 if (hasDefaultNodes) { 4629 const updatedNodes = applyNodeChanges(changes, nodes); 4630 setNodes(updatedNodes); 4631 } 4632 if (debug) { 4633 console.log("React Flow: trigger node changes", changes); 4634 } 4635 onNodesChange === null || onNodesChange === void 0 ? void 0 : onNodesChange(c
4635hanges); 4636 } 4637 }, 4638 triggerEdgeChanges: (changes)=>{ 4639 const { onEdgesChange, setEdges, edges, hasDefaultEdges, debug } = get(); 4640 if (changes === null || changes === void 0 ? void 0 : changes.length) { 4641 if (hasDefaultEdges) { 4642 const updatedEdges = applyEdgeChanges(changes, edges); 4643 setEdges(updatedEdges); 4644 } 4645 if (debug) { 4646 console.log("React Flow: trigger edge changes", changes); 4647 } 4648 onEdgesChange === null || onEdgesChange === void 0 ? void 0 : onEdgesChange(changes); 4649 } 4650 }, 4651 addSelectedNodes: (selectedNodeIds)=>{ 4652 const { multiSelectionActive, edgeLookup, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = get(); 4653 if (multiSelectionActive) { 4654 const nodeChanges = selectedNodeIds.map((nodeId)=>createSelectionChange(nodeId, true)); 4655 triggerNodeChanges(nodeChanges); 4656 return; 4657 } 4658 triggerNodeChanges(getSelectionChanges(nodeLookup, new Set([ 4659 ...selectedNodeIds 4660 ]), true)); 4661 triggerEdgeChanges(getSelectionChanges(edgeLookup)); 4662 }, 4663 addSelectedEdges: (selectedEdgeIds)=>{ 4664 const { multiSelectionActive, edgeLookup, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = get(); 4665 if (multiSelectionActive) { 4666 const changedEdges = selectedEdgeIds.map((edgeId)=>createSelectionChange(edgeId, true)); 4667 triggerEdgeChanges(changedEdges); 4668 return; 4669 } 4670 triggerEdgeChanges(getSelectionChanges(edgeLookup, new Set([ 4671 ...selectedEdgeIds 4672 ]))); 4673 triggerNodeChanges(getSelectionChanges(nodeLookup, new Set(), true)); 4674 }, 4675 unselectNodesAndEdges: function() { 4676 let { nodes, edges } = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; 4677 const { edges: storeEdges, nodes: storeNodes, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = get(); 4678 const nodesToUnselect = nodes ? nodes : storeNodes; 4679 const edgesToUnselect = edges ? edges : storeEdges; 4680 const nodeChanges = []; 4681 for (const node of nodesToUnselect){ 4682 if (!node.selected) { 4683 continue; // skip changing nodes that are not selected 4684 } 4685 const internalNode = nodeLookup.get(node.id); 4686 if (internalNode) { 4687 /* 4688 * we need to unselect the internal node that was selected previously before we 4689 * send the change to the user to prevent it to be selected while dragging the new node 4690 */ internalNode.selected = false; 4691 } 4692 nodeChanges.push(createSelectionChange(node.id, false)); 4693 } 4694 const edgeChanges = []; 4695 for (const edge of edgesToUnselect){ 4696 if (!edge.selected) { 4697 continue; // skip changing edges that are not selected 4698 } 4699 edgeChanges.push(createSelectionChange(edge.id, false)); 4700 } 4701 triggerNodeChanges(nodeChanges); 4702 triggerEdgeChanges(edgeChanges); 4703 }, 4704 setMinZoom: (minZoom)=>{ 4705 const { panZoom, maxZoom } = get(); 4706 panZoom === null || panZoom === void 0 ? void 0 : panZoom.setScaleExtent([ 4707 minZoom, 4708 maxZoom 4709 ]); 4710 set({ 4711 minZoom 4712 }); 4713 }, 4714 setMaxZoom: (maxZoom)=>{ 4715 const { panZoom, minZoom } = get(); 4716 panZoom === null || panZoom === void 0 ? void 0 : panZoom.setScaleExtent([ 4717 minZoom, 4718 maxZoom 4719 ]); 4720 set({ 4721 maxZoom 4722 }); 4723 }, 4724 setTranslateExtent: (translateExtent)=>{ 4725 var _get_panZoom; 4726 (_get_panZoom = get().panZoom) === null || _get_panZoom === void 0 ? void 0 : _get_panZoom.setTranslateExtent(translateExtent); 4727 set({ 4728 translateExtent 4729 }); 4730 }, 4731 resetSelectedElements: ()=>{ 4732 const { edges, nodes, triggerNodeChanges, triggerEdgeChanges, elementsSelectable } = get(); 4733 if (!elementsSelectable) { 4734 return; 4735 } 4736 const nodeChanges = nodes.reduce((res, node)=>node.selected ? [ 4737 ...res, 4738 createSelectionChange(node.id, false) 4739 ] : res, []); 4740 const edgeChanges = edges.reduce((res, edge)=>edge.selected ? [ 4741 ...res, 4742 createSelectionChange(edge.id, false) 4743 ] : res, []); 4744 triggerNodeChanges(nodeChanges); 4745 triggerEdgeChanges(edgeChanges); 4746 }, 4747 setNodeExtent: (nextNodeExtent)=>{ 4748 const { nodes, nodeLookup, parentLookup, nodeOrigin, elevateNodesOnSelect, nodeExtent, zIndexMode } = get(); 4749 if (nextNodeExtent[0][0] === nodeExtent[0][0] && nextNodeExtent[0][1] === nodeExtent[0][1] && nextNodeExtent[1][0] === nodeExtent[1][0] && nextNodeExtent[1][1] === nodeExtent[1][1]) { 4750 return; 4751 } 4752 (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .adoptUserNodes */ .yF)(nodes, nodeLookup, parentLookup, { 4753 nodeOrigin, 4754 nodeExtent: nextNodeExtent, 4755 elevateNodesOnSelect, 4756 checkEquality: false, 4757 zIndexMode 4758 }); 4759 set({ 4760 nodeExtent: nextNodeExtent 4761 }); 4762 }, 4763 panBy: (delta)=>{ 4764 const { transform, width, height, panZoom, translateExtent } = get(); 4765 return (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .panBy */ .hO)({ 4766 delta, 4767 panZoom, 4768 transform, 4769 translateExtent, 4770 width, 4771 height 4772 }); 4773 }, 4774 setCenter: async (x, y, options)=>{ 4775 const { width, height, maxZoom, panZoom } = get(); 4776 if (!panZoom) { 4777 return false;
4778 } 4779 const nextZoom = typeof (options === null || options === void 0 ? void 0 : options.zoom) !== "undefined" ? options.zoom : maxZoom; 4780 await panZoom.setViewport({ 4781 x: width / 2 - x * nextZoom, 4782 y: height / 2 - y * nextZoom, 4783 zoom: nextZoom 4784 }, { 4785 duration: options === null || options === void 0 ? void 0 : options.duration, 4786 ease: options === null || options === void 0 ? void 0 : options.ease, 4787 interpolate: options === null || options === void 0 ? void 0 : options.interpolate 4788 }); 4789 return true; 4790 }, 4791 cancelConnection: ()=>{ 4792 set({ 4793 connection: { 4794 ..._xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .initialConnection */ .Ky 4795 } 4796 }); 4797 }, 4798 updateConnection: (connection)=>{ 4799 set({ 4800 connection 4801 }); 4802 }, 4803 reset: ()=>set({ 4804 ...getInitialState() 4805 }) 4806 }; 4807 }, Object.is); 4808}; 4809/** 4810 * The `<ReactFlowProvider />` component is a [context provider](https://react.dev/learn/passing-data-deeply-with-context#) 4811 * that makes it possible to access a flow's internal state outside of the 4812 * [`<ReactFlow />`](/api-reference/react-flow) component. Many of the hooks we 4813 * provide rely on this component to work. 4814 * @public 4815 * 4816 * @example 4817 * ```tsx 4818 *import { ReactFlow, ReactFlowProvider, useNodes } from '@xyflow/react' 4819 * 4820 *export default function Flow() { 4821 * return ( 4822 * <ReactFlowProvider> 4823 * <ReactFlow nodes={...} edges={...} /> 4824 * <Sidebar /> 4825 * </ReactFlowProvider> 4826 * ); 4827 *} 4828 * 4829 *function Sidebar() { 4830 * // This hook will only work if the component it's used in is a child of a 4831 * // <ReactFlowProvider />. 4832 * const nodes = useNodes() 4833 * 4834 * return <aside>do something with nodes</aside>; 4835 *} 4836 *``` 4837 * 4838 * @remarks If you're using a router and want your flow's state to persist across routes, 4839 * it's vital that you place the `<ReactFlowProvider />` component _outside_ of 4840 * your router. If you have multiple flows on the same page you will need to use a separate 4841 * `<ReactFlowProvider />` for each flow. 4842 */ function ReactFlowProvider(param) { 4843 let { initialNodes: nodes, initialEdges: edges, defaultNodes, defaultEdges, initialWidth: width, initialHeight: height, initialMinZoom: minZoom, initialMaxZoom: maxZoom, initialFitViewOptions: fitViewOptions, fitView, nodeOrigin, nodeExtent, zIndexMode, children } = param; 4844 const [store] = (0,react__WEBPACK_IMPORTED_MODULE_1__.useState)(()=>createStore({ 4845 nodes, 4846 edges, 4847 defaultNodes, 4848 defaultEdges, 4849 width, 4850 height, 4851 fitView, 4852 minZoom, 4853 maxZoom, 4854 fitViewOptions, 4855 nodeOrigin, 4856 nodeExtent, 4857 zIndexMode 4858 })); 4859 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(Provider$1, { 4860 value: store, 4861 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(BatchProvider, { 4862 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(HandleConfigProvider, { 4863 children: children 4864 }) 4865 }) 4866 }); 4867} 4868function Wrapper(param) { 4869 let { children, nodes, edges, defaultNodes, defaultEdges, width, height, fitView, fitViewOptions, minZoom, maxZoom, nodeOrigin, nodeExtent, zIndexMode } = param; 4870 const isWrapped = (0,react__WEBPACK_IMPORTED_MODULE_1__.useContext)(StoreContext); 4871 if (isWrapped) { 4872 /* 4873 * we need to wrap it with a fragment because it's not allowed for children to be a ReactNode 4874 * https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18051 4875 */ return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, { 4876 children: children 4877 }); 4878 } 4879 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ReactFlowProvider, { 4880 initialNodes: nodes, 4881 initialEdges: edges, 4882 defaultNodes: defaultNodes, 4883 defaultEdges: defaultEdges, 4884 initialWidth: width, 4885 initialHeight: height, 4886 fitView: fitView, 4887 initialFitViewOptions: fitViewOptions, 4888 initialMinZoom: minZoom, 4889 initialMaxZoom: maxZoom, 4890 nodeOrigin: nodeOrigin, 4891 nodeExtent: nodeExtent, 4892 zIndexMode: zIndexMode, 4893 children: children 4894 }); 4895} 4896const wrapperStyle = { 4897 width: "100%", 4898 height: "100%", 4899 overflow: "hidden", 4900 position: "relative", 4901 zIndex: 0 4902}; 4903function ReactFlow(param, ref) { 4904 let { nodes, edges, defaultNodes, defaultEdges, className, nodeTypes, edgeTypes, onNodeClick, onEdgeClick, onInit, onMove, onMoveStart, onMoveEnd, onConnect, onConnectStart, onConnectEnd, onClickConnectStart, onClickConnectEnd, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onNodeDoubleClick, onNodeDragStart, onNodeDrag, onNodeDragStop, onNodesDelete, onEdgesDelete, onDelete, onSelectionChange, onSelectionDragStart, onSelectionDrag, onSelectionDragStop, onSelectionContextMenu, onSelectionStart, onSelectionEnd, onBeforeDelete, connectionMode, connectionLineType = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .ConnectionLineType */ .t8.Bezier, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, deleteKeyCode = "Backspace", selectionKeyCode = "Shift", selectionOnDrag = false, selectionMode = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .SelectionMode */ .oW.Full, panActivationKeyCode = "Space", multiSelectionKeyCode = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .isMacOs */ .Q5)() ? "Meta" : "Control", zoomActivationKeyCode = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .isMacOs */ .Q5)() ? "Meta" : "Control", snapToGri
4904d, snapGrid, onlyRenderVisibleElements = false, selectNodesOnDrag, nodesDraggable, autoPanOnNodeFocus, nodesConnectable, nodesFocusable, nodeOrigin = defaultNodeOrigin, edgesFocusable, edgesReconnectable, elementsSelectable = true, defaultViewport: defaultViewport$1 = defaultViewport, minZoom = 0.5, maxZoom = 2, translateExtent = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .infiniteExtent */ .k5, preventScrolling = true, nodeExtent, defaultMarkerColor = "#b1b1b7", zoomOnScroll = true, zoomOnPinch = true, panOnScroll = false, panOnScrollSpeed = 0.5, panOnScrollMode = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .PanOnScrollMode */ .IY.Free, zoomOnDoubleClick = true, panOnDrag = true, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, paneClickDistance = 1, nodeClickDistance = 0, children, onReconnect, onReconnectStart, onReconnectEnd, onEdgeContextMenu, onEdgeDoubleClick, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, reconnectRadius = 10, onNodesChange, onEdgesChange, noDragClassName = "nodrag", noWheelClassName = "nowheel", noPanClassName = "nopan", fitView, fitViewOptions, connectOnClick, attributionPosition, proOptions, defaultEdgeOptions, elevateNodesOnSelect = true, elevateEdgesOnSelect = false, disableKeyboardA11y = false, autoPanOnConnect, autoPanOnNodeDrag, autoPanOnSelection = true, autoPanSpeed, connectionRadius, isValidConnection, onError, style, id, nodeDragThreshold, connectionDragThreshold, viewport, onViewportChange, width, height, colorMode = "light", debug, onScroll, ariaLabelConfig, zIndexMode = "basic", ...rest } = param; 4905 const rfId = id || "1"; 4906 const colorModeClassName = useColorModeClass(colorMode); 4907 // Undo scroll events, preventing viewport from shifting when nodes outside of it are focused 4908 const wrapperOnScroll = (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)((e)=>{ 4909 e.currentTarget.scrollTo({ 4910 top: 0, 4911 left: 0, 4912 behavior: "instant" 4913 }); 4914 onScroll === null || onScroll === void 0 ? void 0 : onScroll(e); 4915 }, [ 4916 onScroll 4917 ]); 4918 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("div", { 4919 "data-testid": "rf__wrapper", 4920 ...rest, 4921 onScroll: wrapperOnScroll, 4922 style: { 4923 ...style, 4924 ...wrapperStyle 4925 }, 4926 ref: ref, 4927 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 4928 "react-flow", 4929 className, 4930 colorModeClassName 4931 ]), 4932 id: id, 4933 role: "application", 4934 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(Wrapper, { 4935 nodes: nodes, 4936 edges: edges, 4937 width: width, 4938 height: height, 4939 fitView: fitView, 4940 fitViewOptions: fitViewOptions, 4941 minZoom: minZoom, 4942 maxZoom: maxZoom, 4943 nodeOrigin: nodeOrigin, 4944 nodeExtent: nodeExtent, 4945 zIndexMode: zIndexMode, 4946 children: [ 4947 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(StoreUpdater, { 4948 nodes: nodes, 4949 edges: edges, 4950 defaultNodes: defaultNodes, 4951 defaultEdges: defaultEdges, 4952 onConnect: onConnect, 4953 onConnectStart: onConnectStart, 4954 onConnectEnd: onConnectEnd, 4955 onClickConnectStart: onClickConnectStart, 4956 onClickConnectEnd: onClickConnectEnd, 4957 nodesDraggable: nodesDraggable, 4958 autoPanOnNodeFocus: autoPanOnNodeFocus, 4959 nodesConnectable: nodesConnectable, 4960 nodesFocusable: nodesFocusable, 4961 edgesFocusable: edgesFocusable, 4962 edgesReconnectable: edgesReconnectable, 4963 elementsSelectable: elementsSelectable, 4964 elevateNodesOnSelect: elevateNodesOnSelect, 4965 elevateEdgesOnSelect: elevateEdgesOnSelect, 4966 minZoom: minZoom, 4967 maxZoom: maxZoom, 4968 nodeExtent: nodeExtent, 4969 onNodesChange: onNodesChange, 4970 onEdgesChange: onEdgesChange,
4971 snapToGrid: snapToGrid, 4972 snapGrid: snapGrid, 4973 connectionMode: connectionMode, 4974 translateExtent: translateExtent, 4975 connectOnClick: connectOnClick, 4976 defaultEdgeOptions: defaultEdgeOptions, 4977 fitView: fitView, 4978 fitViewOptions: fitViewOptions, 4979 onNodesDelete: onNodesDelete, 4980 onEdgesDelete: onEdgesDelete, 4981 onDelete: onDelete, 4982 onNodeDragStart: onNodeDragStart, 4983 onNodeDrag: onNodeDrag, 4984 onNodeDragStop: onNodeDragStop, 4985 onSelectionDrag: onSelectionDrag, 4986 onSelectionDragStart: onSelectionDragStart, 4987 onSelectionDragStop: onSelectionDragStop, 4988 onMove: onMove, 4989 onMoveStart: onMoveStart, 4990 onMoveEnd: onMoveEnd, 4991 noPanClassName: noPanClassName, 4992 nodeOrigin: nodeOrigin, 4993 rfId: rfId, 4994 autoPanOnConnect: autoPanOnConnect, 4995 autoPanOnNodeDrag: autoPanOnNodeDrag, 4996 autoPanSpeed: autoPanSpeed, 4997 onError: onError, 4998 connectionRadius: connectionRadius, 4999 isValidConnection: isValidConnection, 5000 selectNodesOnDrag: selectNodesOnDrag, 5001 nodeDragThreshold: nodeDragThreshold, 5002 connectionDragThreshold: connectionDragThreshold, 5003 onBeforeDelete: onBeforeDelete, 5004 debug: debug, 5005 ariaLabelConfig: ariaLabelConfig, 5006 zIndexMode: zIndexMode 5007 }), 5008 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(GraphView, { 5009 onInit: onInit, 5010 onNodeClick: onNodeClick, 5011 onEdgeClick: onEdgeClick, 5012 onNodeMouseEnter: onNodeMouseEnter, 5013 onNodeMouseMove: onNodeMouseMove, 5014 onNodeMouseLeave: onNodeMouseLeave, 5015 onNodeContextMenu: onNodeContextMenu, 5016 onNodeDoubleClick: onNodeDoubleClick, 5017 nodeTypes: nodeTypes, 5018 edgeTypes: edgeTypes, 5019 connectionLineType: connectionLineType, 5020 connectionLineStyle: connectionLineStyle, 5021 connectionLineComponent: connectionLineComponent, 5022 connectionLineContainerStyle: connectionLineContainerStyle, 5023 selectionKeyCode: selectionKeyCode, 5024 selectionOnDrag: selectionOnDrag, 5025 selectionMode: selectionMode, 5026 deleteKeyCode: deleteKeyCode, 5027 multiSelectionKeyCode: multiSelectionKeyCode, 5028 panActivationKeyCode: panActivationKeyCode, 5029 zoomActivationKeyCode: zoomActivationKeyCode, 5030 onlyRenderVisibleElements: onlyRenderVisibleElements, 5031 defaultViewport: defaultViewport$1, 5032 translateExtent: translateExtent, 5033 minZoom: minZoom, 5034 maxZoom: maxZoom, 5035 preventScrolling: preventScrolling, 5036 zoomOnScroll: zoomOnScroll, 5037 zoomOnPinch: zoomOnPinch, 5038 zoomOnDoubleClick: zoomOnDoubleClick, 5039 panOnScroll: panOnScroll, 5040 panOnScrollSpeed: panOnScrollSpeed, 5041 panOnScrollMode: panOnScrollMode, 5042 panOnDrag: panOnDrag, 5043 autoPanOnSelection: autoPanOnSelection, 5044 onPaneClick: onPaneClick, 5045 onPaneMouseEnter: onPaneMouseEnter, 5046 onPaneMouseMove: onPaneMouseMove, 5047 onPaneMouseLeave: onPaneMouseLeave, 5048 onPaneScroll: onPaneScroll, 5049 onPaneContextMenu: onPaneContextMenu, 5050 paneClickDistance: paneClickDistance, 5051 nodeClickDistance: nodeClickDistance, 5052 onSelectionContextMenu: onSelectionContextMenu, 5053 onSelectionStart: onSelectionStart, 5054 onSelectionEnd: onSelectionEnd, 5055 onReconnect: onReconnect, 5056 onReconnectStart: onReconnectStart, 5057 onReconnectEnd: onReconnectEnd, 5058 onEdgeContextMenu: onEdgeContextMenu, 5059 onEdgeDoubleClick: onEdgeDoubleClick, 5060 onEdgeMouseEnter: onEdgeMouseEnter, 5061 onEdgeMouseMove: onEdgeMouseMove, 5062 onEdgeMouseLeave: onEdgeMouseLeave, 5063 reconnectRadius: reconnectRadius, 5064 defaultMarkerColor: defaultMarkerColor, 5065 noDragClassName: noDragClassName, 5066 noWheelClassName: noWheelClassName, 5067 noPanClassName: noPanClassName, 5068 rfId: rfId, 5069 disableKeyboardA11y: disableKeyboardA11y, 5070 nodeExtent: nodeExtent, 5071 viewport: viewport, 5072 onViewportChange: onViewportChange, 5073 nodesDraggable: nodesDraggable 5074 }), 5075 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(SelectionListener, { 5076 onSelectionChange: onSelectionChange 5077 }), 5078 children, 5079 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(Attribution, { 5080 proOptions: proOptions, 5081 position: attributionPosition 5082 }), 5083 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(A11yDescriptions, { 5084 rfId: rfId, 5085 disableKeyboardA11y: disableKeyboardA11y 5086 }) 5087 ] 5088 }) 5089 }); 5090} 5091/** 5092 * The `<ReactFlow />` component is the heart of your React Flow application. 5093 * It renders your nodes and edges and handles user interaction 5094 * 5095 * @public 5096 * 5097 * @example 5098 * ```tsx 5099 *import { ReactFlow } from '@xyflow/react' 5100 * 5101 *export default function Flow() { 5102 * return (<ReactFlow 5103 * nodes={...} 5104 * edges={...} 5105 * onNodesChange={...} 5106 * ... 5107 * />); 5108 *} 5109 *``` 5110 */ var index = fixedForwardRef(ReactFlow); 5111const selector$6 = (s)=>{ 5112 var _s_domNode; 5113 return (_s_domNode = s.domNode) === null || _s_domNode === void 0 ? void 0 : _s_domNode.querySelector(".react-flow__edgelabel-renderer"); 5114}; 5115/** 5116 * Edges are SVG-based. If you want to render more complex labels you can use the 5117 * `<EdgeLabelRenderer />
5117` component to access a div based renderer. This component 5118 * is a portal that renders the label in a `<div />` that is positioned on top of 5119 * the edges. You can see an example usage of the component in the 5120 * [edge label renderer example](/examples/edges/edge-label-renderer). 5121 * @public 5122 * 5123 * @example 5124 * ```jsx 5125 * import React from 'react'; 5126 * import { getBezierPath, EdgeLabelRenderer, BaseEdge } from '@xyflow/react'; 5127 * 5128 * export function CustomEdge({ id, data, ...props }) { 5129 * const [edgePath, labelX, labelY] = getBezierPath(props); 5130 * 5131 * return ( 5132 * <> 5133 * <BaseEdge id={id} path={edgePath} /> 5134 * <EdgeLabelRenderer> 5135 * <div 5136 * style={{ 5137 * position: 'absolute', 5138 * transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`, 5139 * background: '#ffcc00', 5140 * padding: 10, 5141 * }} 5142 * className="nodrag nopan" 5143 * > 5144 * {data.label} 5145 * </div> 5146 * </EdgeLabelRenderer> 5147 * </> 5148 * ); 5149 * }; 5150 * ``` 5151 * 5152 * @remarks The `<EdgeLabelRenderer />` has no pointer events by default. If you want to 5153 * add mouse interactions you need to set the style `pointerEvents: all` and add 5154 * the `nopan` class on the label or the element you want to interact with. 5155 */ function EdgeLabelRenderer(param) { 5156 let { children } = param; 5157 const edgeLabelRenderer = useStore(selector$6); 5158 if (!edgeLabelRenderer) { 5159 return null; 5160 } 5161 return /*#__PURE__*/ (0,react_dom__WEBPACK_IMPORTED_MODULE_6__.createPortal)(children, edgeLabelRenderer); 5162} 5163const selector$5 = (s)=>{ 5164 var _s_domNode; 5165 return (_s_domNode = s.domNode) === null || _s_domNode === void 0 ? void 0 : _s_domNode.querySelector(".react-flow__viewport-portal"); 5166}; 5167/** 5168 * The `<ViewportPortal />` component can be used to add components to the same viewport 5169 * of the flow where nodes and edges are rendered. This is useful when you want to render 5170 * your own components that are adhere to the same coordinate system as the nodes & edges 5171 * and are also affected by zooming and panning 5172 * @public 5173 * @example 5174 * 5175 * ```jsx 5176 *import React from 'react'; 5177 *import { ViewportPortal } from '@xyflow/react'; 5178 * 5179 *export default function () { 5180 * return ( 5181 * <ViewportPortal> 5182 * <div 5183 * style={{ transform: 'translate(100px, 100px)', position: 'absolute' }} 5184 * > 5185 * This div is positioned at [100, 100] on the flow. 5186 * </div> 5187 * </ViewportPortal> 5188 * ); 5189 *} 5190 *``` 5191 */ function ViewportPortal(param) { 5192 let { children } = param; 5193 const viewPortalDiv = useStore(selector$5); 5194 if (!viewPortalDiv) { 5195 return null; 5196 } 5197 return /*#__PURE__*/ createPortal(children, viewPortalDiv); 5198} 5199/** 5200 * When you programmatically add or remove handles to a node or update a node's 5201 * handle position, you need to let React Flow know about it using this hook. This 5202 * will update the internal dimensions of the node and properly reposition handles 5203 * on the canvas if necessary. 5204 * 5205 * @public 5206 * @returns Use this function to tell React Flow to update the internal state of one or more nodes 5207 * that you have changed programmatically. 5208 * 5209 * @example 5210 * ```jsx 5211 *import { useCallback, useState } from 'react'; 5212 *import { Handle, useUpdateNodeInternals } from '@xyflow/react'; 5213 * 5214 *export default function RandomHandleNode({ id }) { 5215 * const updateNodeInternals = useUpdateNodeInternals(); 5216 * const [handleCount, setHandleCount] = useState(0); 5217 * const randomizeHandleCount = useCallback(() => { 5218 * setHandleCount(Math.floor(Math.random() * 10)); 5219 * updateNodeInternals(id); 5220 * }, [id, updateNodeInternals]); 5221 * 5222 * return ( 5223 * <> 5224 * {Array.from({ length: handleCount }).map((_, index) => ( 5225 * <Handle 5226 * key={index} 5227 * type="target" 5228 * position="left" 5229 * id={`handle-${index}`} 5230 * /> 5231 * ))} 5232 * 5233 * <div> 5234 * <button onClick={randomizeHandleCount}>Randomize handle count</button> 5235 * <p>There are {handleCount} handles on this node.</p> 5236 * </div> 5237 * </> 5238 * ); 5239 *} 5240 *``` 5241 * @remarks This hook can only be used in a component that is a child of a 5242 *{@link ReactFlowProvider} or a {@link ReactFlow} component. 5243 */ function useUpdateNodeInternals() { 5244 const store = useStoreApi(); 5245 return (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)((id)=>{
5246 const { domNode, updateNodeInternals } = store.getState(); 5247 const updateIds = Array.isArray(id) ? id : [ 5248 id 5249 ]; 5250 const updates = new Map(); 5251 updateIds.forEach((updateId)=>{ 5252 const nodeElement = domNode === null || domNode === void 0 ? void 0 : domNode.querySelector('.react-flow__node[data-id="'.concat(updateId, '"]')); 5253 if (nodeElement) { 5254 updates.set(updateId, { 5255 id: updateId, 5256 nodeElement, 5257 force: true 5258 }); 5259 } 5260 }); 5261 requestAnimationFrame(()=>updateNodeInternals(updates, { 5262 triggerFitView: false 5263 })); 5264 }, []); 5265} 5266const nodesSelector = (state)=>state.nodes; 5267/** 5268 * This hook returns an array of the current nodes. Components that use this hook 5269 * will re-render **whenever any node changes**, including when a node is selected 5270 * or moved. 5271 * 5272 * @public 5273 * @returns An array of all nodes currently in the flow. 5274 * 5275 * @example 5276 * ```jsx 5277 *import { useNodes } from '@xyflow/react'; 5278 * 5279 *export default function() { 5280 * const nodes = useNodes(); 5281 * 5282 * return <div>There are currently {nodes.length} nodes!</div>; 5283 *} 5284 *``` 5285 */ function useNodes() { 5286 const nodes = useStore(nodesSelector, shallow); 5287 return nodes; 5288} 5289const edgesSelector = (state)=>state.edges; 5290/** 5291 * This hook returns an array of the current edges. Components that use this hook 5292 * will re-render **whenever any edge changes**. 5293 * 5294 * @public 5295 * @returns An array of all edges currently in the flow. 5296 * 5297 * @example 5298 * ```tsx 5299 *import { useEdges } from '@xyflow/react'; 5300 * 5301 *export default function () { 5302 * const edges = useEdges(); 5303 * 5304 * return <div>There are currently {edges.length} edges!</div>; 5305 *} 5306 *``` 5307 */ function useEdges() { 5308 const edges = useStore(edgesSelector, shallow); 5309 return edges; 5310} 5311const viewportSelector = (state)=>({ 5312 x: state.transform[0], 5313 y: state.transform[1], 5314 zoom: state.transform[2] 5315 }); 5316/** 5317 * The `useViewport` hook is a convenient way to read the current state of the 5318 * {@link Viewport} in a component. Components that use this hook 5319 * will re-render **whenever the viewport changes**. 5320 * 5321 * @public 5322 * @returns The current viewport. 5323 * 5324 * @example 5325 * 5326 *```jsx 5327 *import { useViewport } from '@xyflow/react'; 5328 * 5329 *export default function ViewportDisplay() { 5330 * const { x, y, zoom } = useViewport(); 5331 * 5332 * return ( 5333 * <div> 5334 * <p> 5335 * The viewport is currently at ({x}, {y}) and zoomed to {zoom}. 5336 * </p> 5337 * </div> 5338 * ); 5339 *} 5340 *``` 5341 * 5342 * @remarks This hook can only be used in a component that is a child of a 5343 *{@link ReactFlowProvider} or a {@link ReactFlow} component. 5344 */ function useViewport() { 5345 const viewport = useStore(viewportSelector, shallow); 5346 return viewport; 5347} 5348/** 5349 * This hook makes it easy to prototype a controlled flow where you manage the 5350 * state of nodes and edges outside the `ReactFlowInstance`. You can think of it 5351 * like React's `useState` hook with an additional helper callback. 5352 * 5353 * @public 5354 * @returns 5355 * - `nodes`: The current array of nodes. You might pass this directly to the `nodes` prop of your 5356 * `<ReactFlow />` component, or you may want to manipulate it first to perform some layouting, 5357 * for example. 5358 * - `setNodes`: A function that you can use to update the nodes. You can pass it a new array of 5359 * nodes or a callback that receives the current array of nodes and returns a new array of nodes. 5360 * This is the same as the second element of the tuple returned by React's `useState` hook. 5361 * - `onNodesChange`: A handy callback that can take an array of `NodeChanges` and update the nodes 5362 * state accordingly. You'll typically pass this directly to the `onNodesChange` prop of your 5363 * `<ReactFlow />` component. 5364 * @example 5365 * 5366 *```tsx 5367 *import { ReactFlow, useNodesState, useEdgesState } from '@xyflow/react'; 5368 * 5369 *const initialNodes = []; 5370 *const initialEdges = []; 5371 * 5372 *export default function () { 5373 * const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); 5374 * const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); 5375 * 5376 * return ( 5377 * <ReactFlow 5378 * nodes={nodes} 5379 * edges={edges} 5380 * onNodesChange={onNodesChange} 5381 * onEdgesChange={onEdgesChange} 5382 * /> 5383 * ); 5384 *} 5385 *``` 5386 * 5387 * @remarks This hook was created to make prototyping easier and our documentation 5388 * examples clearer. Although it is OK to use this hook in production, in 5389 * practice you may want to use a more sophisticated state management solution 5390 * like Zustand {@link https://reactflow.dev/docs/guides/state-management/} instead. 5391 * 5392 */ function useNodesState(initialNodes) { 5393 const [nodes, setNodes] = useState(initialNodes); 5394 const onNodesChange = useCallback((changes)=>setNodes((nds)=>applyNodeChanges(changes, nds)), []); 5395 return [ 5396 nodes, 5397 setNodes, 5398 onNodesChange 5399 ]; 5400} 5401/** 5402 * This hook makes it easy to prototype a controlled flow where you manage the 5403 * state of nodes and edges outside the `ReactFlowInstance`. You can think of it 5404 * like React's `useState` hook with an additional helper callback. 5405 * 5406 * @public 5407 * @returns 5408 * - `edges`: The current array of edges. You might pass this directly to the `edges` prop of your
5409 * `<ReactFlow />` component, or you may want to manipulate it first to perform some layouting, 5410 * for example. 5411 * 5412 * - `setEdges`: A function that you can use to update the edges. You can pass it a new array of 5413 * edges or a callback that receives the current array of edges and returns a new array of edges. 5414 * This is the same as the second element of the tuple returned by React's `useState` hook. 5415 * 5416 * - `onEdgesChange`: A handy callback that can take an array of `EdgeChanges` and update the edges 5417 * state accordingly. You'll typically pass this directly to the `onEdgesChange` prop of your 5418 * `<ReactFlow />` component. 5419 * @example 5420 * 5421 *```tsx 5422 *import { ReactFlow, useNodesState, useEdgesState } from '@xyflow/react'; 5423 * 5424 *const initialNodes = []; 5425 *const initialEdges = []; 5426 * 5427 *export default function () { 5428 * const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); 5429 * const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); 5430 * 5431 * return ( 5432 * <ReactFlow 5433 * nodes={nodes} 5434 * edges={edges} 5435 * onNodesChange={onNodesChange} 5436 * onEdgesChange={onEdgesChange} 5437 * /> 5438 * ); 5439 *} 5440 *``` 5441 * 5442 * @remarks This hook was created to make prototyping easier and our documentation 5443 * examples clearer. Although it is OK to use this hook in production, in 5444 * practice you may want to use a more sophisticated state management solution 5445 * like Zustand {@link https://reactflow.dev/docs/guides/state-management/} instead. 5446 * 5447 */ function useEdgesState(initialEdges) { 5448 const [edges, setEdges] = useState(initialEdges); 5449 const onEdgesChange = useCallback((changes)=>setEdges((eds)=>applyEdgeChanges(changes, eds)), []); 5450 return [ 5451 edges, 5452 setEdges, 5453 onEdgesChange 5454 ]; 5455} 5456/** 5457 * The `useOnViewportChange` hook lets you listen for changes to the viewport such 5458 * as panning and zooming. You can provide a callback for each phase of a viewport 5459 * change: `onStart`, `onChange`, and `onEnd`. 5460 * 5461 * @public 5462 * @example 5463 * ```jsx 5464 *import { useCallback } from 'react'; 5465 *import { useOnViewportChange } from '@xyflow/react'; 5466 * 5467 *function ViewportChangeLogger() { 5468 * useOnViewportChange({ 5469 * onStart: (viewport: Viewport) => console.log('start', viewport), 5470 * onChange: (viewport: Viewport) => console.log('change', viewport), 5471 * onEnd: (viewport: Viewport) => console.log('end', viewport), 5472 * }); 5473 * 5474 * return null; 5475 *} 5476 *``` 5477 */ function useOnViewportChange(param) { 5478 let { onStart, onChange, onEnd } = param; 5479 const store = useStoreApi(); 5480 useEffect(()=>{ 5481 store.setState({ 5482 onViewportChangeStart: onStart 5483 }); 5484 }, [ 5485 onStart 5486 ]); 5487 useEffect(()=>{ 5488 store.setState({ 5489 onViewportChange: onChange 5490 }); 5491 }, [ 5492 onChange 5493 ]); 5494 useEffect(()=>{ 5495 store.setState({ 5496 onViewportChangeEnd: onEnd 5497 }); 5498 }, [ 5499 onEnd 5500 ]); 5501} 5502/** 5503 * This hook lets you listen for changes to both node and edge selection. As the 5504 *name implies, the callback you provide will be called whenever the selection of 5505 *_either_ nodes or edges changes. 5506 * 5507 * @public 5508 * @example 5509 * ```jsx 5510 *import { useState } from 'react'; 5511 *import { ReactFlow, useOnSelectionChange } from '@xyflow/react'; 5512 * 5513 *function SelectionDisplay() { 5514 * const [selectedNodes, setSelectedNodes] = useState([]); 5515 * const [selectedEdges, setSelectedEdges] = useState([]); 5516 * 5517 * // the passed handler has to be memoized, otherwise the hook will not work correctly 5518 * const onChange = useCallback(({ nodes, edges }) => { 5519 * setSelectedNodes(nodes.map((node) => node.id)); 5520 * setSelectedEdges(edges.map((edge) => edge.id)); 5521 * }, []); 5522 * 5523 * useOnSelectionChange({ 5524 * onChange, 5525 * }); 5526 * 5527 * return ( 5528 * <div> 5529 * <p>Selected nodes: {selectedNodes.join(', ')}</p> 5530 * <p>Selected edges: {selectedEdges.join(', ')}</p> 5531 * </div> 5532 * ); 5533 *} 5534 *``` 5535 * 5536 * @remarks You need to memoize the passed `onChange` handler, otherwise the hook will not work correctly. 5537 */ function useOnSelectionChange(param) { 5538 let { onChange } = param; 5539 const store = useStoreApi(); 5540 useEffect(()=>{ 5541 const nextOnSelectionChangeHandlers = [ 5542 ...store.getState().onSelectionChangeHandlers, 5543 onChange 5544 ]; 5545 store.setState({ 5546 onSelectionChangeHandlers: nextOnSelectionChangeHandlers 5547 }); 5548 return ()=>{ 5549 const nextHandlers = store.getState().onSelectionChangeHandlers.filter((fn)=>fn !== onChange); 5550 store.setState({ 5551 onSelectionChangeHandlers: nextHandlers 5552 }); 5553 }; 5554 }, [ 5555 onChange 5556 ]); 5557} 5558const selector$4 = (options)=>(s)=>{ 5559 if (!options.includeHiddenNodes) { 5560 return s.nodesInitialized; 5561 } 5562 if (s.nodeLookup.size === 0) { 5563 return false;
5564 } 5565 for (const [, { internals }] of s.nodeLookup){ 5566 if (internals.handleBounds === undefined || !nodeHasDimensions(internals.userNode)) { 5567 return false; 5568 } 5569 } 5570 return true; 5571 }; 5572/** 5573 * This hook tells you whether all the nodes in a flow have been measured and given 5574 *a width and height. When you add a node to the flow, this hook will return 5575 *`false` and then `true` again once the node has been measured. 5576 * 5577 * @public 5578 * @returns Whether or not the nodes have been initialized by the `<ReactFlow />` component and 5579 * given a width and height. 5580 * 5581 * @example 5582 * ```jsx 5583 *import { useReactFlow, useNodesInitialized } from '@xyflow/react'; 5584 *import { useEffect, useState } from 'react'; 5585 * 5586 *const options = { 5587 * includeHiddenNodes: false, 5588 *}; 5589 * 5590 *export default function useLayout() { 5591 * const { getNodes } = useReactFlow(); 5592 * const nodesInitialized = useNodesInitialized(options); 5593 * const [layoutedNodes, setLayoutedNodes] = useState(getNodes()); 5594 * 5595 * useEffect(() => { 5596 * if (nodesInitialized) { 5597 * setLayoutedNodes(yourLayoutingFunction(getNodes())); 5598 * } 5599 * }, [nodesInitialized]); 5600 * 5601 * return layoutedNodes; 5602 *} 5603 *``` 5604 */ function useNodesInitialized() { 5605 let options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : { 5606 includeHiddenNodes: false 5607 }; 5608 const initialized = useStore(selector$4(options)); 5609 return initialized; 5610} 5611/** 5612 * Hook to check if a <Handle /> is connected to another <Handle /> and get the connections. 5613 * 5614 * @public 5615 * @deprecated Use `useNodeConnections` instead. 5616 * @returns An array with handle connections. 5617 */ function useHandleConnections(param) { 5618 let { type, id, nodeId, onConnect, onDisconnect } = param; 5619 console.warn("[DEPRECATED] `useHandleConnections` is deprecated. Instead use `useNodeConnections` https://reactflow.dev/api-reference/hooks/useNodeConnections"); 5620 const _nodeId = useNodeId(); 5621 const currentNodeId = nodeId !== null && nodeId !== void 0 ? nodeId : _nodeId; 5622 const prevConnections = useRef(null); 5623 const connections = useStore((state)=>state.connectionLookup.get("".concat(currentNodeId, "-").concat(type).concat(id ? "-".concat(id) : "")), areConnectionMapsEqual); 5624 useEffect(()=>{ 5625 // @todo discuss if onConnect/onDisconnect should be called when the component mounts/unmounts 5626 if (prevConnections.current && prevConnections.current !== connections) { 5627 const _connections = connections !== null && connections !== void 0 ? connections : new Map(); 5628 handleConnectionChange(prevConnections.current, _connections, onDisconnect); 5629 handleConnectionChange(_connections, prevConnections.current, onConnect); 5630 } 5631 prevConnections.current = connections !== null && connections !== void 0 ? connections : new Map(); 5632 }, [ 5633 connections, 5634 onConnect, 5635 onDisconnect 5636 ]); 5637 return useMemo(()=>{ 5638 var _connections_values; 5639 return Array.from((_connections_values = connections === null || connections === void 0 ? void 0 : connections.values()) !== null && _connections_values !== void 0 ? _connections_values : []); 5640 }, [ 5641 connections 5642 ]); 5643} 5644const error014 = _xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .errorMessages */ .Qj["error014"](); 5645/** 5646 * This hook returns an array of connections on a specific node, handle type ('source', 'target') or handle ID. 5647 * 5648 * @public 5649 * @returns An array with connections. 5650 * 5651 * @example 5652 * ```jsx 5653 *import { useNodeConnections } from '@xyflow/react'; 5654 * 5655 *export default function () { 5656 * const connections = useNodeConnections({ 5657 * handleType: 'target', 5658 * handleId: 'my-handle', 5659 * }); 5660 * 5661 * return ( 5662 * <div>There are currently {connections.length} incoming connections!</div> 5663 * ); 5664 *} 5665 *``` 5666 */ function useNodeConnections() { 5667 let { id, handleType, handleId, onConnect, onDisconnect } = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {}; 5668 const nodeId = useNodeId(); 5669 const currentNodeId = id !== null && id !== void 0 ? id : nodeId; 5670 if (!currentNodeId) { 5671 throw new Error(error014); 5672 } 5673 const prevConnections = useRef(null); 5674 const connections = useStore((state)=>state.connectionLookup.get("".concat(currentNodeId).concat(handleType ? handleId ? "-".concat(handleType, "-").concat(handleId) : "-".concat(handleType) : "")), areConnectionMapsEqual); 5675 useEffect(()=>{ 5676 // @todo discuss if onConnect/onDisconnect should be called when the component mounts/unmounts 5677 if (prevConnections.current && prevConnections.current !== connections) { 5678 const _connections = connections !== null && connections !== void 0 ? connections : new Map(); 5679 handleConnectionChange(prevConnections.current, _connections, onDisconnect); 5680 handleConnectionChange(_connections, prevConnections.current, onConnect); 5681 } 5682 prevConnections.current = connections !== null && connections !== void 0 ? connections : new Map(); 5683 }, [ 5684 connections, 5685 onConnect, 5686 onDisconnect 5687 ]); 5688 return useMemo(()=>{ 5689 var _connections_values; 5690 return Array.from((_connections_values = connections === null || connections === void 0 ? void 0 : connections.values()) !== null && _connections_values !== void 0 ? _connections_values : []); 5691 }, [ 5692 connections 5693 ]); 5694} 5695// eslint-disable-next-line @typescript-eslint/no-explicit-any 5696function useNodesData(nodeIds) { 5697 const nodesData = useStore(useCallback((s)=>{ 5698 const data = []; 5699 const isArrayOfIds = Array.isArray(nodeIds); 5700 const _nodeIds = isArrayOfIds ? nodeIds : [ 5701 nodeIds 5702 ]; 5703 for (const nodeId of _nodeIds){ 5704 const node = s.nodeLookup.get(nodeId); 5705 if (node) { 5706 data.push({ 5707 id: node.id, 5708 type: node.type, 5709 data: node.data 5710 }); 5711 } 5712 } 5713 var _data_; 5714 return isArrayOfIds ? data : (_data_ = data[0]) !== null && _data_ !== void 0 ? _data_ : null; 5715 }, [ 5716 nodeIds 5717 ]), shallowNodeData); 5718 return nodesData; 5719} 5720/** 5721 * This hook returns the internal representation of a specific node. 5722 * Components that use this hook will re-render **whenever the node changes**, 5723 * including when a node is selected or moved. 5724 * 5725 * @public 5726 * @param id - The ID of a node you want to observe. 5727 * @returns The `InternalNode` object for the node with the given ID. 5728 * 5729 * @example 5730 * ```tsx 5731 *import { useInternalNode } from '@xyflow/react'; 5732 * 5733 *export default function () { 5734 * const internalNode = useInternalNode('node-1'); 5735 * const absolutePosition = internalNode.internals.positionAbsolute; 5736 * 5737 * return ( 5738 * <div> 5739 * The absolute position of the node is at: 5740 * <p>x: {absolutePosition.x}</p> 5741 * <p>y: {absolutePosition.y}</p> 5742 * </div> 5743 * ); 5744 *} 5745 *``` 5746 */ function useInternalNode(id) { 5747 const node = useStore(useCallback((s)=>s.nodeLookup.get(id), [ 5748 id 5749 ]), shallow); 5750 return node; 5751} 5752/** 5753 * Registers a middleware function to transform node changes. 5754 * 5755 * @public 5756 * @param fn - Middleware function. Should be memoized with useCallback to avoid re-registration. 5757 */ function experimental_useOnNodesChangeMiddleware(fn) { 5758 const store = useStoreApi(); 5759 const [symbol] = useState(()=>Symbol()); 5760 useEffect(()=>{ 5761 const { onNodesChangeMiddlewareMap } = store.getState(); 5762 onNodesChangeMiddlewareMap.set(symbol, fn); 5763 }, [ 5764 fn 5765 ]); 5766 useEffect(()=>{ 5767 const { onNodesChangeMiddlewareMap } = store.getState(); 5768 return ()=>{ 5769 onNodesChangeMiddlewareMap.delete(symbol); 5770 }; 5771 }, []); 5772} 5773/** 5774 * Registers a middleware function to transform edge changes. 5775 * 5776 * @public 5777 * @param fn - Middleware function. Should be memoized with useCallback to avoid re-registration. 5778 */ function experimental_useOnEdgesChangeMiddleware(fn) { 5779 const store = useStoreApi(); 5780 const [symbol] = useState(()=>Symbol()); 5781 useEffect(()=>{ 5782 const { onEdgesChangeMiddlewareMap } = store.getState(); 5783 onEdgesChangeMiddlewareMap.set(symbol, fn); 5784 }, [ 5785 fn 5786 ]); 5787 useEffect(()=>{ 5788 const { onEdgesChangeMiddlewareMap } = store.getState(); 5789 return ()=>{ 5790 onEdgesChangeMiddlewareMap.delete(symbol); 5791 }; 5792 }, []); 5793} 5794function LinePattern(param) { 5795 let { dimensions, lineWidth, variant, className } = param; 5796 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("path", { 5797 strokeWidth: lineWidth, 5798 d: "M".concat(dimensions[0] / 2, " 0 V").concat(dimensions[1], " M0 ").concat(dimensions[1] / 2, " H").concat(dimensions[0]), 5799 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 5800 "react-flow__background-pattern", 5801 variant, 5802 className 5803 ]) 5804 }); 5805} 5806function DotPattern(param) { 5807 let { radius, className } = param; 5808 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("circle", { 5809 cx: radius, 5810 cy: radius,
5811 r: radius, 5812 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 5813 "react-flow__background-pattern", 5814 "dots", 5815 className 5816 ]) 5817 }); 5818} 5819/** 5820 * The three variants are exported as an enum for convenience. You can either import 5821 * the enum and use it like `BackgroundVariant.Lines` or you can use the raw string 5822 * value directly. 5823 * @public 5824 */ var BackgroundVariant; 5825(function(BackgroundVariant) { 5826 BackgroundVariant["Lines"] = "lines"; 5827 BackgroundVariant["Dots"] = "dots"; 5828 BackgroundVariant["Cross"] = "cross"; 5829})(BackgroundVariant || (BackgroundVariant = {})); 5830const defaultSize = { 5831 [BackgroundVariant.Dots]: 1, 5832 [BackgroundVariant.Lines]: 1, 5833 [BackgroundVariant.Cross]: 6 5834}; 5835const selector$3 = (s)=>({ 5836 transform: s.transform, 5837 patternId: "pattern-".concat(s.rfId) 5838 }); 5839function BackgroundComponent(param) { 5840 let { id, variant = BackgroundVariant.Dots, // only used for dots and cross 5841 gap = 20, // only used for lines and cross 5842 size, lineWidth = 1, offset = 0, color, bgColor, style, className, patternClassName } = param; 5843 const ref = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null); 5844 const { transform, patternId } = useStore(selector$3, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 5845 const patternSize = size || defaultSize[variant]; 5846 const isDots = variant === BackgroundVariant.Dots; 5847 const isCross = variant === BackgroundVariant.Cross; 5848 const gapXY = Array.isArray(gap) ? gap : [ 5849 gap, 5850 gap 5851 ]; 5852 const scaledGap = [ 5853 gapXY[0] * transform[2] || 1, 5854 gapXY[1] * transform[2] || 1 5855 ]; 5856 const scaledSize = patternSize * transform[2]; 5857 const offsetXY = Array.isArray(offset) ? offset : [ 5858 offset, 5859 offset 5860 ]; 5861 const patternDimensions = isCross ? [ 5862 scaledSize, 5863 scaledSize 5864 ] : scaledGap; 5865 const scaledOffset = [ 5866 offsetXY[0] * transform[2] || 1 + patternDimensions[0] / 2, 5867 offsetXY[1] * transform[2] || 1 + patternDimensions[1] / 2 5868 ]; 5869 const _patternId = "".concat(patternId).concat(id ? id : ""); 5870 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("svg", { 5871 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 5872 "react-flow__background", 5873 className 5874 ]), 5875 style: { 5876 ...style, 5877 ...containerStyle, 5878 "--xy-background-color-props": bgColor, 5879 "--xy-background-pattern-color-props": color 5880 }, 5881 ref: ref, 5882 "data-testid": "rf__background", 5883 children: [ 5884 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("pattern", { 5885 id: _patternId, 5886 x: transform[0] % scaledGap[0], 5887 y: transform[1] % scaledGap[1], 5888 width: scaledGap[0], 5889 height: scaledGap[1], 5890 patternUnits: "userSpaceOnUse", 5891 patternTransform: "translate(-".concat(scaledOffset[0], ",-").concat(scaledOffset[1], ")"), 5892 children: isDots ? (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(DotPattern, { 5893 radius: scaledSize / 2, 5894 className: patternClassName 5895 }) : (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(LinePattern, { 5896 dimensions: patternDimensions, 5897 lineWidth: lineWidth, 5898 variant: variant, 5899 className: patternClassName 5900 }) 5901 }), 5902 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("rect", { 5903 x: "0", 5904 y: "0", 5905 width: "100%", 5906 height: "100%", 5907 fill: "url(#".concat(_patternId, ")") 5908 }) 5909 ] 5910 }); 5911} 5912BackgroundComponent.displayName = "Background"; 5913/** 5914 * The `<Background />` component makes it convenient to render different types of backgrounds common in node-based UIs. It comes with three variants: lines, dots and cross. 5915 * 5916 * @example 5917 *
5918 * A simple example of how to use the Background component. 5919 * 5920 * ```tsx 5921 * import { useState } from 'react'; 5922 * import { ReactFlow, Background, BackgroundVariant } from '@xyflow/react'; 5923 * 5924 * export default function Flow() { 5925 * return ( 5926 * <ReactFlow defaultNodes={[...]} defaultEdges={[...]}> 5927 * <Background color="#ccc" variant={BackgroundVariant.Dots} /> 5928 * </ReactFlow> 5929 * ); 5930 * } 5931 * ``` 5932 * 5933 * @example 5934 * 5935 * In this example you can see how to combine multiple backgrounds 5936 * 5937 * ```tsx 5938 * import { ReactFlow, Background, BackgroundVariant } from '@xyflow/react'; 5939 * import '@xyflow/react/dist/style.css'; 5940 * 5941 * export default function Flow() { 5942 * return ( 5943 * <ReactFlow defaultNodes={[...]} defaultEdges={[...]}> 5944 * <Background 5945 * id="1" 5946 * gap={10} 5947 * color="#f1f1f1" 5948 * variant={BackgroundVariant.Lines} 5949 * /> 5950 * <Background 5951 * id="2" 5952 * gap={100} 5953 * color="#ccc" 5954 * variant={BackgroundVariant.Lines} 5955 * /> 5956 * </ReactFlow> 5957 * ); 5958 * } 5959 * ``` 5960 * 5961 * @remarks 5962 * 5963 * When combining multiple <Background /> components it’s important to give each of them a unique id prop! 5964 * 5965 */ const Background = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(BackgroundComponent); 5966function PlusIcon() { 5967 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("svg", { 5968 xmlns: "http://www.w3.org/2000/svg",
5969 viewBox: "0 0 32 32", 5970 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("path", { 5971 d: "M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z" 5972 }) 5973 }); 5974} 5975function MinusIcon() { 5976 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("svg", { 5977 xmlns: "http://www.w3.org/2000/svg", 5978 viewBox: "0 0 32 5", 5979 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("path", { 5980 d: "M0 0h32v4.2H0z" 5981 }) 5982 }); 5983} 5984function FitViewIcon() { 5985 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("svg", { 5986 xmlns: "http://www.w3.org/2000/svg", 5987 viewBox: "0 0 32 30", 5988 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("path", { 5989 d: "M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z" 5990 }) 5991 }); 5992} 5993function LockIcon() { 5994 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("svg", { 5995 xmlns: "http://www.w3.org/2000/svg",
5996 viewBox: "0 0 25 32", 5997 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("path", { 5998 d: "M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z" 5999 }) 6000 }); 6001} 6002function UnlockIcon() { 6003 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("svg", { 6004 xmlns: "http://www.w3.org/2000/svg", 6005 viewBox: "0 0 25 32", 6006 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("path", { 6007 d: "M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z" 6008 }) 6009 }); 6010} 6011/** 6012 * You can add buttons to the control panel by using the `<ControlButton />` component 6013 * and pass it as a child to the [`<Controls />`](/api-reference/components/controls) component. 6014 * 6015 * @public 6016 * @example 6017 *```jsx 6018 *import { MagicWand } from '@radix-ui/react-icons' 6019 *import { ReactFlow, Controls, ControlButton } from '@xyflow/react' 6020 * 6021 *export default function Flow() { 6022 * return ( 6023 * <ReactFlow nodes={[...]} edges={[...]}> 6024 * <Controls> 6025 * <ControlButton onClick={() => alert('Something magical just happened. ✨')}> 6026 * <MagicWand /> 6027 * </ControlButton> 6028 * </Controls> 6029 * </ReactFlow> 6030 * ) 6031 *} 6032 *``` 6033 */ function ControlButton(param) { 6034 let { children, className, ...rest } = param; 6035 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("button", { 6036 type: "button", 6037 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 6038 "react-flow__controls-button", 6039 className 6040 ]), 6041 ...rest, 6042 children: children 6043 }); 6044} 6045const selector$2 = (s)=>({ 6046 isInteractive: s.nodesDraggable || s.nodesConnectable || s.elementsSelectable, 6047 minZoomReached: s.transform[2] <= s.minZoom, 6048 maxZoomReached: s.transform[2] >= s.maxZoom, 6049 ariaLabelConfig: s.ariaLabelConfig 6050 }); 6051function ControlsComponent(param) { 6052 let { style, showZoom = true, showFitView = true, showInteractive = true, fitViewOptions, onZoomIn, onZoomOut, onFitView, onInteractiveChange, className, children, position = "bottom-left", orientation = "vertical", "aria-label": ariaLabel } = param; 6053 const store = useStoreApi(); 6054 const { isInteractive, minZoomReached, maxZoomReached, ariaLabelConfig } = useStore(selector$2, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 6055 const { zoomIn, zoomOut, fitView } = useReactFlow(); 6056 const onZoomInHandler = ()=>{ 6057 zoomIn(); 6058 onZoomIn === null || onZoomIn === void 0 ? void 0 : onZoomIn(); 6059 }; 6060 const onZoomOutHandler = ()=>{ 6061 zoomOut(); 6062 onZoomOut === null || onZoomOut === void 0 ? void 0 : onZoomOut(); 6063 }; 6064 const onFitViewHandler = ()=>{ 6065 fitView(fitViewOptions); 6066 onFitView === null || onFitView === void 0 ? void 0 : onFitView(); 6067 }; 6068 const onToggleInteractivity = ()=>{ 6069 store.setState({ 6070 nodesDraggable: !isInteractive, 6071 nodesConnectable: !isInteractive, 6072 elementsSelectable: !isInteractive 6073 }); 6074 onInteractiveChange === null || onInteractiveChange === void 0 ? void 0 : onInteractiveChange(!isInteractive); 6075 }; 6076 const orientationClass = orientation === "horizontal" ? "horizontal" : "vertical"; 6077 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(Panel, { 6078 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 6079 "react-flow__controls", 6080 orientationClass, 6081 className 6082 ]), 6083 position: position, 6084 style: style, 6085 "data-testid": "rf__controls", 6086 "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : ariaLabelConfig["controls.ariaLabel"], 6087 children: [ 6088 showZoom && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, { 6089 children: [ 6090 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ControlButton, { 6091 onClick: onZoomInHandler, 6092 className: "react-flow__controls-zoomin", 6093 title: ariaLabelConfig["controls.zoomIn.ariaLabel"], 6094 "aria-label": ariaLabelConfig["controls.zoomIn.ariaLabel"], 6095 disabled: maxZoomReached, 6096 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(PlusIcon, {}) 6097 }), 6098 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ControlButton, { 6099 onClick: onZoomOutHandler, 6100 className: "react-flow__controls-zoomout", 6101 title: ariaLabelConfig["controls.zoomOut.ariaLabel"], 6102 "aria-label": ariaLabelConfig["controls.zoomOut.ariaLabel"], 6103 disabled: minZoomReached, 6104 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(MinusIcon, {}) 6105 }) 6106 ] 6107 }), 6108 showFitView && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ControlButton, { 6109 className: "react-flow__controls-fitview", 6110 onClick: onFitViewHandler, 6111 title: ariaLabelConfig["controls.fitView.ariaLabel"], 6112 "aria-label": ariaLabelConfig["controls.fitView.ariaLabel"], 6113 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(FitViewIcon, {}) 6114 }), 6115 showInteractive && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(ControlButton, { 6116 className: "react-flow__controls-interactive", 6117 onClick: onToggleInteractivity, 6118 title: ariaLabelConfig["controls.interactive.ariaLabel"], 6119 "aria-label": ariaLabelConfig["controls.interactive.ariaLabel"], 6120 children: isInteractive ? (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(UnlockIcon, {}) : (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(LockIcon, {}) 6121 }), 6122 children 6123 ] 6124 }); 6125} 6126ControlsComponent.displayName = "Controls"; 6127/**
6128 * The `<Controls />` component renders a small panel that contains convenient 6129 * buttons to zoom in, zoom out, fit the view, and lock the viewport. 6130 * 6131 * @public 6132 * @example 6133 *```tsx 6134 *import { ReactFlow, Controls } from '@xyflow/react' 6135 * 6136 *export default function Flow() { 6137 * return ( 6138 * <ReactFlow nodes={[...]} edges={[...]}> 6139 * <Controls /> 6140 * </ReactFlow> 6141 * ) 6142 *} 6143 *``` 6144 * 6145 * @remarks To extend or customise the controls, you can use the [`<ControlButton />`](/api-reference/components/control-button) component 6146 * 6147 */ const Controls = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(ControlsComponent); 6148function MiniMapNodeComponent(param) { 6149 let { id, x, y, width, height, style, color, strokeColor, strokeWidth, className, borderRadius, shapeRendering, selected, onClick } = param; 6150 const { background, backgroundColor } = style || {}; 6151 const fill = color || background || backgroundColor; 6152 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("rect", { 6153 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 6154 "react-flow__minimap-node", 6155 { 6156 selected 6157 }, 6158 className 6159 ]), 6160 x: x, 6161 y: y, 6162 rx: borderRadius, 6163 ry: borderRadius, 6164 width: width, 6165 height: height, 6166 style: { 6167 fill, 6168 stroke: strokeColor, 6169 strokeWidth 6170 }, 6171 shapeRendering: shapeRendering, 6172 onClick: onClick ? (event)=>onClick(event, id) : undefined 6173 }); 6174} 6175const MiniMapNode = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(MiniMapNodeComponent); 6176const selectorNodeIds = (s)=>s.nodes.map((node)=>node.id); 6177const getAttrFunction = (func)=>func instanceof Function ? func : ()=>func; 6178function MiniMapNodes(param) { 6179 let { nodeStrokeColor, nodeColor, nodeClassName = "", nodeBorderRadius = 5, nodeStrokeWidth, /* 6180 * We need to rename the prop to be `CapitalCase` so that JSX will render it as 6181 * a component properly. 6182 */ nodeComponent: NodeComponent = MiniMapNode, onClick } = param; 6183 const nodeIds = useStore(selectorNodeIds, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 6184 const nodeColorFunc = getAttrFunction(nodeColor); 6185 const nodeStrokeColorFunc = getAttrFunction(nodeStrokeColor); 6186 const nodeClassNameFunc = getAttrFunction(nodeClassName); 6187 const shapeRendering = typeof window === "undefined" || !!window.chrome ? "crispEdges" : "geometricPrecision"; 6188 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.Fragment, { 6189 children: nodeIds.map((nodeId)=>/* 6190 * The split of responsibilities between MiniMapNodes and 6191 * NodeComponentWrapper may appear weird. However, it’s designed to 6192 * minimize the cost of updates when individual nodes change. 6193 * 6194 * For more details, see a similar commit in `NodeRenderer/index.tsx`. 6195 */ (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(NodeComponentWrapper, { 6196 id: nodeId, 6197 nodeColorFunc: nodeColorFunc, 6198 nodeStrokeColorFunc: nodeStrokeColorFunc, 6199 nodeClassNameFunc: nodeClassNameFunc, 6200 nodeBorderRadius: nodeBorderRadius, 6201 nodeStrokeWidth: nodeStrokeWidth, 6202 NodeComponent: NodeComponent, 6203 onClick: onClick, 6204 shapeRendering: shapeRendering 6205 }, nodeId)) 6206 }); 6207} 6208function NodeComponentWrapperInner(param) { 6209 let { id, nodeColorFunc, nodeStrokeColorFunc, nodeClassNameFunc, nodeBorderRadius, nodeStrokeWidth, shapeRendering, NodeComponent, onClick } = param; 6210 const { node, x, y, width, height } = useStore((s)=>{ 6211 const node = s.nodeLookup.get(id); 6212 if (!node) { 6213 return { 6214 node: undefined, 6215 x: 0, 6216 y: 0, 6217 width: 0, 6218 height: 0 6219 }; 6220 } 6221 const userNode = node.internals.userNode; 6222 const { x, y } = node.internals.positionAbsolute; 6223 const { width, height } = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getNodeDimensions */ .Rf)(userNode); 6224 return { 6225 node: userNode, 6226 x, 6227 y, 6228 width, 6229 height 6230 }; 6231 }, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__/* .shallow */ .X); 6232 if (!node || node.hidden || !(0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .nodeHasDimensions */ .nb)(node)) { 6233 return null; 6234 } 6235 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(NodeComponent, { 6236 x: x, 6237 y: y, 6238 width: width, 6239 height: height, 6240 style: node.style, 6241 selected: !!node.selected, 6242 className: nodeClassNameFunc(node), 6243 color: nodeColorFunc(node), 6244 borderRadius: nodeBorderRadius, 6245 strokeColor: nodeStrokeColorFunc(node), 6246 strokeWidth: nodeStrokeWidth, 6247 shapeRendering: shapeRendering, 6248 onClick: onClick, 6249 id: node.id 6250 }); 6251} 6252const NodeComponentWrapper = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(NodeComponentWrapperInner); 6253var MiniMapNodes$1 = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(MiniMapNodes); 6254const defaultWidth = 200; 6255const defaultHeight = 150; 6256const filterHidden = (node)=>!node.hidden; 6257const selector$1 = (s)=>{ 6258 const viewBB = { 6259 x: -s.transform[0] / s.transform[2], 6260 y: -s.transform[1] / s.transform[2], 6261 width: s.width / s.transform[2], 6262 height: s.height / s.transform[2] 6263 }; 6264 return { 6265 viewBB, 6266 boundingRect: s.nodeLookup.size > 0 ? (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getBoundsOfRects */ .oI)((0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .getInternalNodesB
6266ounds */ .W0)(s.nodeLookup, { 6267 filter: filterHidden 6268 }), viewBB) : viewBB, 6269 rfId: s.rfId, 6270 panZoom: s.panZoom, 6271 translateExtent: s.translateExtent, 6272 flowWidth: s.width, 6273 flowHeight: s.height, 6274 ariaLabelConfig: s.ariaLabelConfig 6275 }; 6276}; 6277const rectEqual = (a, b)=>a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height; 6278// the selector builds new viewBB/boundingRect objects every call, so the default shallow equality always 6279// treats them as changed; comparing the rects by value lets the minimap skip re-renders when nothing moved 6280const areEqual = (a, b)=>rectEqual(a.viewBB, b.viewBB) && rectEqual(a.boundingRect, b.boundingRect) && a.rfId === b.rfId && a.panZoom === b.panZoom && a.translateExtent === b.translateExtent && a.flowWidth === b.flowWidth && a.flowHeight === b.flowHeight && a.ariaLabelConfig === b.ariaLabelConfig; 6281const ARIA_LABEL_KEY = "react-flow__minimap-desc"; 6282function MiniMapComponent(param) { 6283 let { style, className, nodeStrokeColor, nodeColor, nodeClassName = "", nodeBorderRadius = 5, nodeStrokeWidth, /* 6284 * We need to rename the prop to be `CapitalCase` so that JSX will render it as 6285 * a component properly. 6286 */ nodeComponent, bgColor, maskColor, maskStrokeColor, maskStrokeWidth, position = "bottom-right", onClick, onNodeClick, pannable = false, zoomable = false, ariaLabel, inversePan, zoomStep = 1, offsetScale = 5 } = param; 6287 const store = useStoreApi(); 6288 const svg = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(null); 6289 const { boundingRect, viewBB, rfId, panZoom, translateExtent, flowWidth, flowHeight, ariaLabelConfig } = useStore(selector$1, areEqual); 6290 var _style_width; 6291 const elementWidth = (_style_width = style === null || style === void 0 ? void 0 : style.width) !== null && _style_width !== void 0 ? _style_width : defaultWidth; 6292 var _style_height; 6293 const elementHeight = (_style_height = style === null || style === void 0 ? void 0 : style.height) !== null && _style_height !== void 0 ? _style_height : defaultHeight; 6294 const scaledWidth = boundingRect.width / elementWidth; 6295 const scaledHeight = boundingRect.height / elementHeight; 6296 const viewScale = Math.max(scaledWidth, scaledHeight); 6297 const viewWidth = viewScale * elementWidth; 6298 const viewHeight = viewScale * elementHeight; 6299 const offset = offsetScale * viewScale; 6300 const x = boundingRect.x - (viewWidth - boundingRect.width) / 2 - offset; 6301 const y = boundingRect.y - (viewHeight - boundingRect.height) / 2 - offset; 6302 const width = viewWidth + offset * 2; 6303 const height = viewHeight + offset * 2; 6304 const labelledBy = "".concat(ARIA_LABEL_KEY, "-").concat(rfId); 6305 const viewScaleRef = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(0); 6306 const minimapInstance = (0,react__WEBPACK_IMPORTED_MODULE_1__.useRef)(); 6307 viewScaleRef.current = viewScale; 6308 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 6309 if (svg.current && panZoom) { 6310 minimapInstance.current = (0,_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .XYMinimap */ .FD)({ 6311 domNode: svg.current, 6312 panZoom, 6313 getTransform: ()=>store.getState().transform, 6314 getViewScale: ()=>viewScaleRef.current 6315 }); 6316 return ()=>{ 6317 var _minimapInstance_current; 6318 (_minimapInstance_current = minimapInstance.current) === null || _minimapInstance_current === void 0 ? void 0 : _minimapInstance_current.destroy(); 6319 }; 6320 } 6321 }, [ 6322 panZoom 6323 ]); 6324 (0,react__WEBPACK_IMPORTED_MODULE_1__.useEffect)(()=>{ 6325 var _minimapInstance_current; 6326 (_minimapInstance_current = minimapInstance.current) === null || _minimapInstance_current === void 0 ? void 0 : _minimapInstance_current.update({ 6327 translateExtent, 6328 width: flowWidth, 6329 height: flowHeight, 6330 inversePan, 6331 pannable, 6332 zoomStep, 6333 zoomable 6334 }); 6335 }, [ 6336 pannable, 6337 zoomable, 6338 inversePan, 6339 zoomStep, 6340 translateExtent, 6341 flowWidth, 6342 flowHeight 6343 ]); 6344 const onSvgClick = onClick ? (event)=>{ 6345 var _minimapInstance_current; 6346 const [x, y] = ((_minimapInstance_current = minimapInstance.current) === null || _minimapInstance_current === void 0 ? void 0 : _minimapInstance_current.pointer(event)) || [ 6347 0, 6348 0 6349 ]; 6350 onClick(event, { 6351 x, 6352 y 6353 }); 6354 } : undefined; 6355 const onSvgNodeClick = onNodeClick ? (0,react__WEBPACK_IMPORTED_MODULE_1__.useCallback)((event, nodeId)=>{ 6356 const node = store.getState().nodeLookup.get(nodeId).internals.userNode;
6357 onNodeClick(event, node); 6358 }, []) : undefined; 6359 const _ariaLabel = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : ariaLabelConfig["minimap.ariaLabel"]; 6360 return (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(Panel, { 6361 position: position, 6362 style: { 6363 ...style, 6364 "--xy-minimap-background-color-props": typeof bgColor === "string" ? bgColor : undefined, 6365 "--xy-minimap-mask-background-color-props": typeof maskColor === "string" ? maskColor : undefined, 6366 "--xy-minimap-mask-stroke-color-props": typeof maskStrokeColor === "string" ? maskStrokeColor : undefined, 6367 "--xy-minimap-mask-stroke-width-props": typeof maskStrokeWidth === "number" ? maskStrokeWidth * viewScale : undefined, 6368 "--xy-minimap-node-background-color-props": typeof nodeColor === "string" ? nodeColor : undefined, 6369 "--xy-minimap-node-stroke-color-props": typeof nodeStrokeColor === "string" ? nodeStrokeColor : undefined, 6370 "--xy-minimap-node-stroke-width-props": typeof nodeStrokeWidth === "number" ? nodeStrokeWidth : undefined 6371 }, 6372 className: (0,classcat__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .Z)([ 6373 "react-flow__minimap", 6374 className 6375 ]), 6376 "data-testid": "rf__minimap", 6377 children: (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxs)("svg", { 6378 width: elementWidth, 6379 height: elementHeight,
6380 viewBox: "".concat(x, " ").concat(y, " ").concat(width, " ").concat(height), 6381 className: "react-flow__minimap-svg", 6382 role: "img", 6383 "aria-labelledby": labelledBy, 6384 ref: svg, 6385 onClick: onSvgClick, 6386 children: [ 6387 _ariaLabel && (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("title", { 6388 id: labelledBy, 6389 children: _ariaLabel 6390 }), 6391 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)(MiniMapNodes$1, { 6392 onClick: onSvgNodeClick, 6393 nodeColor: nodeColor, 6394 nodeStrokeColor: nodeStrokeColor, 6395 nodeBorderRadius: nodeBorderRadius, 6396 nodeClassName: nodeClassName, 6397 nodeStrokeWidth: nodeStrokeWidth, 6398 nodeComponent: nodeComponent 6399 }), 6400 (0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__.jsx)("path", { 6401 className: "react-flow__minimap-mask", 6402 d: "M".concat(x - offset, ",").concat(y - offset, "h").concat(width + offset * 2, "v").concat(height + offset * 2, "h").concat(-width - offset * 2, "z\n M").concat(viewBB.x, ",").concat(viewBB.y, "h").concat(viewBB.width, "v").concat(viewBB.height, "h").concat(-viewBB.width, "z"), 6403 fillRule: "evenodd", 6404 pointerEvents: "none" 6405 }) 6406 ] 6407 }) 6408 }); 6409} 6410MiniMapComponent.displayName = "MiniMap"; 6411/** 6412 * The `<MiniMap />` component can be used to render an overview of your flow. It 6413 * renders each node as an SVG element and visualizes where the current viewport is 6414 * in relation to the rest of the flow. 6415 * 6416 * @public 6417 * @example 6418 * 6419 * ```jsx 6420 *import { ReactFlow, MiniMap } from '@xyflow/react'; 6421 * 6422 *export default function Flow() { 6423 * return ( 6424 * <ReactFlow nodes={[...]} edges={[...]}> 6425 * <MiniMap nodeStrokeWidth={3} /> 6426 * </ReactFlow> 6427 * ); 6428 *} 6429 *``` 6430 */ const MiniMap = /*#__PURE__*/ (0,react__WEBPACK_IMPORTED_MODULE_1__.memo)(MiniMapComponent); 6431const scaleSelector = (calculateScale)=>(store)=>calculateScale ? "".concat(Math.max(1 / store.transform[2], 1)) : undefined; 6432const defaultPositions = { 6433 [_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .ResizeControlVariant */ .pB.Line]: "right", 6434 [_xyflow_system__WEBPACK_IMPORTED_MODULE_3__/* .ResizeControlVariant */ .pB.Handle]: "bottom-right" 6435}; 6436function ResizeControl(param) { 6437 let { nodeId, position, variant = ResizeControlVariant.Handle, className, style = undefined, children, color, minWidth = 10, minHeight = 10, maxWidth = Number.MAX_VALUE, maxHeight = Number.MAX_VALUE, keepAspectRatio = false, resizeDirection, autoScale = true, shouldResize, onResizeStart, onResize, onResizeEnd } = param; 6438 const contextNodeId = useNodeId(); 6439 const id = typeof nodeId === "string" ? nodeId : contextNodeId; 6440 const store = useStoreApi(); 6441 const resizeControlRef = useRef(null); 6442 const isHandleControl = variant === ResizeControlVariant.Handle; 6443 const scale = useStore(useCallback(scaleSelector(isHandleControl && autoScale), [ 6444 isHandleControl, 6445 autoScale 6446 ]), shallow); 6447 const resizer = useRef(null); 6448 const controlPosition = position !== null && position !== void 0 ? position : defaultPositions[variant]; 6449 useEffect(()=>{ 6450 if (!resizeControlRef.current || !id) { 6451 return; 6452 } 6453 if (!resizer.current) { 6454 resizer.current = XYResizer({ 6455 domNode: resizeControlRef.current, 6456 nodeId: id, 6457 getStoreItems: ()=>{ 6458 const { nodeLookup, transform, snapGrid, snapToGrid, nodeOrigin, domNode } = store.getState(); 6459 return { 6460 nodeLookup, 6461 transform, 6462 snapGrid, 6463 snapToGrid, 6464 nodeOrigin, 6465 paneDomNode: domNode 6466 }; 6467 },
6468 onChange: (change, childChanges)=>{ 6469 const { triggerNodeChanges, nodeLookup, parentLookup, nodeOrigin } = store.getState(); 6470 const changes = []; 6471 const nextPosition = { 6472 x: change.x, 6473 y: change.y 6474 }; 6475 const node = nodeLookup.get(id); 6476 if (node && node.expandParent && node.parentId) { 6477 var _node_origin; 6478 const origin = (_node_origin = node.origin) !== null && _node_origin !== void 0 ? _node_origin : nodeOrigin; 6479 var _change_width, _ref; 6480 const width = (_ref = (_change_width = change.width) !== null && _change_width !== void 0 ? _change_width : node.measured.width) !== null && _ref !== void 0 ? _ref : 0; 6481 var _change_height, _ref1; 6482 const height = (_ref1 = (_change_height = change.height) !== null && _change_height !== void 0 ? _change_height : node.measured.height) !== null && _ref1 !== void 0 ? _ref1 : 0; 6483 var _change_x, _change_y; 6484 const child = { 6485 id: node.id, 6486 parentId: node.parentId, 6487 rect: { 6488 width, 6489 height, 6490 ...evaluateAbsolutePosition({ 6491 x: (_change_x = change.x) !== null && _change_x !== void 0 ? _change_x : node.position.x, 6492 y: (_change_y = change.y) !== null && _change_y !== void 0 ? _change_y : node.position.y 6493 }, { 6494 width, 6495 height 6496 }, node.parentId, nodeLookup, origin) 6497 } 6498 }; 6499 const parentExpandChanges = handleExpandParent([ 6500 child 6501 ], nodeLookup, parentLookup, nodeOrigin); 6502 changes.push(...parentExpandChanges); 6503 /* 6504 * when the parent was expanded by the child node, its position will be clamped at 6505 * 0,0 when node origin is 0,0 and to width, height if it's 1,1 6506 */ nextPosition.x = change.x ? Math.max(origin[0] * width, change.x) : undefined; 6507 nextPosition.y = change.y ? Math.max(origin[1] * height, change.y) : undefined; 6508 } 6509 if (nextPosition.x !== undefined && nextPosition.y !== undefined) { 6510 const positionChange = { 6511 id, 6512 type: "position", 6513 position: { 6514 ...nextPosition 6515 } 6516 }; 6517 changes.push(positionChange); 6518 } 6519 if (change.width !== undefined && change.height !== undefined) { 6520 const setAttributes = !resizeDirection ? true : resizeDirection === "horizontal" ? "width" : "height"; 6521 const dimensionChange = { 6522 id, 6523 type: "dimensions", 6524 resizing: true, 6525 setAttributes, 6526 dimensions: { 6527 width: change.width, 6528 height: change.height 6529 } 6530 }; 6531 changes.push(dimensionChange); 6532 } 6533 for (const childChange of childChanges){ 6534 const positionChange = { 6535 ...childChange, 6536 type: "position" 6537 }; 6538 changes.push(positionChange); 6539 } 6540 triggerNodeChanges(changes); 6541 }, 6542 onEnd: (param)=>{ 6543 let { width, height } = param; 6544 const dimensionChange = { 6545 id: id, 6546 type: "dimensions", 6547 resizing: false, 6548 dimensions: { 6549 width, 6550 height 6551 } 6552 }; 6553 store.getState().triggerNodeChanges([ 6554 dimensionChange 6555 ]); 6556 } 6557 }); 6558 } 6559 resizer.current.update({ 6560 controlPosition, 6561 boundaries: { 6562 minWidth, 6563 minHeight, 6564 maxWidth, 6565 maxHeight 6566 }, 6567 keepAspectRatio, 6568 resizeDirection, 6569 onResizeStart, 6570 onResize, 6571 onResizeEnd, 6572 shouldResize 6573 }); 6574 return ()=>{ 6575 var _resizer_current; 6576 (_resizer_current = resizer.current) === null || _resizer_current === void 0 ? void 0 : _resizer_current.destroy(); 6577 }; 6578 }, [ 6579 controlPosition, 6580 minWidth, 6581 minHeight, 6582 maxWidth, 6583 maxHeight, 6584 keepAspectRatio, 6585 onResizeStart, 6586 onResize, 6587 onResizeEnd, 6588 shouldResize 6589 ]); 6590 const positionClassNames = controlPosition.split("-"); 6591 return jsx("div", { 6592 className: cc([ 6593 "react-flow__resize-control", 6594 "nodrag", 6595 ...positionClassNames, 6596 variant, 6597 className 6598 ]), 6599 ref: resizeControlRef, 6600 style: { 6601 ...style, 6602 scale, 6603 ...color && { 6604 [isHandleControl ? "backgroundColor" : "borderColor"]: color 6605 } 6606 }, 6607 children: children 6608 }); 6609} 6610/** 6611 * To create your own resizing UI, you can use the `NodeResizeControl` component where you can pass children (such as icons). 6612 * @public 6613 * 6614 */ const NodeResizeControl = /*#__PURE__*/ (/* unused pure expression or super */ null && (memo(ResizeControl))); 6615/** 6616 * The `<NodeResizer />` component can be used to add a resize functionality to your 6617 * nodes. It renders draggable controls around the node to resize in all directions. 6618 * @public 6619 * 6620 * @example 6621 *```jsx 6622 *import { memo } from 'react'; 6623 *import { Handle, Position, NodeResizer } from '@xyflow/react'; 6624 * 6625 *function ResizableNode({ data }) { 6626 * return ( 6627 * <> 6628 * <NodeResizer minWidth={100} minHeight={30} /> 6629 * <Handle type="target" position={Position.Left} /> 6630 * <div style={{ padding: 10 }}>{data.label}</div> 6631 * <Handle type="source" position={Position.Right} /> 6632 * </> 6633 * ); 6634 *}; 6635 * 6636 *export default memo(ResizableNode); 6637 *``` 6638 */ function NodeResizer(param) { 6639 let { nodeId, isVisible = true, handleClassName, handleStyle, lineClassName, lineStyle, color, minWidth = 10, minHeight = 10, maxWidth = Number.MAX_VALUE, maxHeight = Number.MAX_VALUE, keepAspectRatio = false, autoScale = true, shouldResize, onResizeStart, onResize, onResizeEnd } = param; 6640 if (!isVisible) { 6641 return null; 6642 } 6643 return jsxs(Fragment, { 6644 children: [ 6645 XY_RESIZER_LINE_POSITIONS.map((position)=>jsx(NodeResizeControl, { 6646 className: lineClassName, 6647 style: lineStyle, 6648 nodeId: nodeId, 6649 position: position, 6650 variant: ResizeControlVariant.Line, 6651 color: color, 6652 minWidth: minWidth, 6653 minHeight: minHeight, 6654 maxWidth: maxWidth, 6655 maxHeight: maxHeight, 6656 onResizeStart: onResizeStart, 6657 keepAspectRatio: keepAspectRatio, 6658 autoScale: autoScale, 6659 shouldResize: shouldResize, 6660 onResize: onResize, 6661 onResizeEnd: onResizeEnd 6662 }, position)), 6663 XY_RESIZER_HANDLE_POSITIONS.map((position)=>jsx(NodeResizeControl, { 6664 className: handleClassName, 6665 style: handleStyle, 6666 nodeId: nodeId, 6667 position: position, 6668 color: color, 6669 minWidth: minWidth, 6670 minHeight: minHeight, 6671 maxWidth: maxWidth, 6672 maxHeight: maxHeight, 6673 onResizeStart: onResizeStart, 6674 keepAspectRatio: keepAspectRatio, 6675 autoScale: autoScale, 6676 shouldResize: shouldResize, 6677 onResize: onResize, 6678 onResizeEnd: onResizeEnd 6679 }, position)) 6680 ] 6681 }); 6682} 6683const selector = (state)=>{ 6684 var _state_domNode; 6685 return (_state_domNode = state.domNode) === null || _state_domNode === void 0 ? void 0 : _state_domNode.querySelector(".react-flow__renderer"); 6686}; 6687function NodeToolbarPortal(param) { 6688 let { children } = param; 6689 const wrapperRef = useStore(selector); 6690 if (!wrapperRef) { 6691 return null; 6692 } 6693 return /*#__PURE__*/ createPortal(children, wrapperRef); 6694} 6695const nodeEqualityFn = (a, b)=>(a === null || a === void 0 ? void 0 : a.internals.positionAbsolute.x) !== (b === null || b === void 0 ? void 0 : b.internals.positionAbsolute.x) || (a === null || a === void 0 ? void 0 : a.internals.positionAbsolute.y) !== (b === null || b === void 0 ? void 0 : b.internals.positionAbsolute.y) || (a === null || a === void 0 ? void 0 : a.measured.width) !== (b === null || b === void 0 ? void 0 : b.measured.width) || (a === null || a === void 0 ? void 0 : a.measured.height) !== (b === null || b === void 0 ? void 0 : b.measured.height) || (a === null || a === void 0 ? void 0 : a.selected) !== (b === null || b === void 0 ? void 0 : b.selected) || (a === null || a === void 0 ? void 0 : a.internals.z) !== (b === null || b === void 0 ? void 0 : b.internals.z); 6696const nodesEqualityFn = (a, b)=>{ 6697 if (a.size !== b.size) { 6698 return false;
6699 } 6700 for (const [key, node] of a){ 6701 if (nodeEqualityFn(node, b.get(key))) { 6702 return false; 6703 } 6704 } 6705 return true; 6706}; 6707const storeSelector = (state)=>({ 6708 x: state.transform[0], 6709 y: state.transform[1], 6710 zoom: state.transform[2], 6711 selectedNodesCount: state.nodes.filter((node)=>node.selected).length 6712 }); 6713/** 6714 * This component can render a toolbar or tooltip to one side of a custom node. This 6715 * toolbar doesn't scale with the viewport so that the content is always visible. 6716 * 6717 * @public 6718 * @example 6719 * ```jsx 6720 *import { memo } from 'react'; 6721 *import { Handle, Position, NodeToolbar } from '@xyflow/react'; 6722 * 6723 *function CustomNode({ data }) { 6724 * return ( 6725 * <> 6726 * <NodeToolbar isVisible={data.toolbarVisible} position={data.toolbarPosition}> 6727 * <button>delete</button> 6728 * <button>copy</button> 6729 * <button>expand</button> 6730 * </NodeToolbar> 6731 * 6732 * <div style={{ padding: '10px 20px' }}> 6733 * {data.label} 6734 * </div> 6735 * 6736 * <Handle type="target" position={Position.Left} /> 6737 * <Handle type="source" position={Position.Right} /> 6738 * </> 6739 * ); 6740 *}; 6741 * 6742 *export default memo(CustomNode); 6743 *``` 6744 * @remarks By default, the toolbar is only visible when a node is selected. If multiple 6745 * nodes are selected it will not be visible to prevent overlapping toolbars or 6746 * clutter. You can override this behavior by setting the `isVisible` prop to `true`. 6747 */ function NodeToolbar(param) { 6748 let { nodeId, children, className, style, isVisible, position = Position.Top, offset = 10, align = "center", ...rest } = param; 6749 var _nodes_values_next_value; 6750 const contextNodeId = useNodeId(); 6751 const nodesSelector = useCallback((state)=>{ 6752 const nodeIds = Array.isArray(nodeId) ? nodeId : [ 6753 nodeId || contextNodeId || "" 6754 ]; 6755 const internalNodes = nodeIds.reduce((res, id)=>{ 6756 const node = state.nodeLookup.get(id); 6757 if (node) { 6758 res.set(node.id, node); 6759 } 6760 return res; 6761 }, new Map()); 6762 return internalNodes; 6763 }, [ 6764 nodeId, 6765 contextNodeId 6766 ]); 6767 const nodes = useStore(nodesSelector, nodesEqualityFn); 6768 const { x, y, zoom, selectedNodesCount } = useStore(storeSelector, shallow); 6769 // if isVisible is not set, we show the toolbar only if its node is selected and no other node is selected 6770 const isActive = typeof isVisible === "boolean" ? isVisible : nodes.size === 1 && ((_nodes_values_next_value = nodes.values().next().value) === null || _nodes_values_next_value === void 0 ? void 0 : _nodes_values_next_value.selected) && selectedNodesCount === 1; 6771 if (!isActive || !nodes.size) { 6772 return null; 6773 } 6774 const nodeRect = getInternalNodesBounds(nodes); 6775 const nodesArray = Array.from(nodes.values()); 6776 const zIndex = Math.max(...nodesArray.map((node)=>node.internals.z + 1)); 6777 const wrapperStyle = { 6778 position: "absolute", 6779 transform: getNodeToolbarTransform(nodeRect, { 6780 x, 6781 y, 6782 zoom 6783 }, position, offset, align), 6784 zIndex, 6785 ...style 6786 }; 6787 return jsx(NodeToolbarPortal, { 6788 children: jsx("div", { 6789 style: wrapperStyle, 6790 className: cc([ 6791 "react-flow__node-toolbar", 6792 className 6793 ]), 6794 ...rest, 6795 "data-id": nodesArray.reduce((acc, node)=>"".concat(acc).concat(node.id, " "), "").trim(), 6796 children: children 6797 }) 6798 }); 6799} 6800const zoomSelector = (state)=>state.transform[2]; 6801/** 6802 * This component can render a toolbar or tooltip to one side of a custom edge. This 6803 * toolbar doesn't scale with the viewport so that the content stays the same size. 6804 * 6805 * @public 6806 * @example 6807 * ```jsx 6808 * import { EdgeToolbar, BaseEdge, getBezierPath, type EdgeProps } from "@xyflow/react"; 6809 * 6810 * export function CustomEdge({ id, data, ...props }: EdgeProps) { 6811 * const [edgePath, centerX, centerY] = getBezierPath(props); 6812 * 6813 * return ( 6814 * <> 6815 * <BaseEdge id={id} path={edgePath} /> 6816 * <EdgeToolbar edgeId={id} x={centerX} y={centerY} isVisible> 6817 * <button onClick={() => console.log('edge', id, 'click')}}>Click me</button> 6818 * </EdgeToolbar> 6819 * </> 6820 * ); 6821 * } 6822 * ``` 6823 */ function EdgeToolbar(param) { 6824 let { edgeId, x, y, children, className, style, isVisible, alignX = "center", alignY = "center", ...rest } = param; 6825 const edgeSelector = useCallback((state)=>state.edgeLookup.get(edgeId), [ 6826 edgeId 6827 ]); 6828 const edge = useStore(edgeSelector, shallow); 6829 const isActive = typeof isVisible === "boolean" ? isVisible : edge === null || edge === void 0 ? void 0 : edge.selected; 6830 const zoom = useStore(zoomSelector); 6831 if (!isActive) { 6832 return null; 6833 } 6834 var _edge_zIndex; 6835 const zIndex = ((_edge_zIndex = edge === null || edge === void 0 ? void 0 : edge.zIndex) !== null && _edge_zIndex !== void 0 ? _edge_zIndex : 0) + 1; 6836 const transform = getEdgeToolbarTransform(x, y, zoom, alignX, alignY); 6837 var _edge_id; 6838 return jsx(EdgeLabelRenderer, { 6839 children: jsx("div", { 6840 style: { 6841 position: "absolute", 6842 transform, 6843 zIndex, 6844 pointerEvents: "all", 6845 transformOrigin: "0 0", 6846 ...style 6847 }, 6848 className: cc([ 6849 "react-flow__edge-toolbar", 6850 className 6851 ]), 6852 "data-id": (_edge_id = edge === null || edge === void 0 ? void 0 : edge.id) !== null && _edge_id !== void 0 ? _edge_id : "", 6853 ...rest, 6854 children: children 6855 }) 6856 }); 6857} 6858 6859 6860 6861/***/ }) 6862 6863}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.