@xyflow᜵system

A UMD build of @xyflow/system

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/520289/1500120/%40xyflow%E1%9C%B5system.js

  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-drag'), require('d3-selection'), require('d3-zoom')) :
  3. typeof define === 'function' && define.amd ? define(['exports', 'd3-drag', 'd3-selection', 'd3-zoom'], factory) :
  4. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.myBundle = {}, global.d3, global.d3, global.d3));
  5. })(this, (function (exports, d3Drag, d3Selection, d3Zoom) { 'use strict';
  6. var errorMessages = {
  7. error001: () => "[React Flow]: Seems like you have not used zustand provider as an ancestor. Help: https://reactflow.dev/error#001",
  8. error002: () => "It looks like you've created a new nodeTypes or edgeTypes object. If this wasn't on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them.",
  9. error003: (nodeType) => `Node type "${nodeType}" not found. Using fallback type "default".`,
  10. error004: () => "The React Flow parent container needs a width and a height to render the graph.",
  11. error005: () => "Only child nodes can use a parent extent.",
  12. error006: () => "Can't create edge. An edge needs a source and a target.",
  13. error007: (id) => `The old edge with id=${id} does not exist.`,
  14. error009: (type) => `Marker type "${type}" doesn't exist.`,
  15. error008: (handleType, { id, sourceHandle, targetHandle }) => `Couldn't create edge for ${handleType} handle id: "${handleType === "source" ? sourceHandle : targetHandle}", edge id: ${id}.`,
  16. error010: () => "Handle: No node id found. Make sure to only use a Handle inside a custom Node.",
  17. error011: (edgeType) => `Edge type "${edgeType}" not found. Using fallback type "default".`,
  18. error012: (id) => `Node with id "${id}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,
  19. error013: (lib = "react") => `It seems that you haven't loaded the styles. Please import '@xyflow/${lib}/dist/style.css' or base.css to make sure everything is working properly.`
  20. };
  21. var infiniteExtent = [
  22. [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],
  23. [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY]
  24. ];
  25. var elementSelectionKeys = ["Enter", " ", "Escape"];
  26. exports.ConnectionMode = void 0;
  27. (function(ConnectionMode2) {
  28. ConnectionMode2["Strict"] = "strict";
  29. ConnectionMode2["Loose"] = "loose";
  30. })(exports.ConnectionMode || (exports.ConnectionMode = {}));
  31. exports.PanOnScrollMode = void 0;
  32. (function(PanOnScrollMode2) {
  33. PanOnScrollMode2["Free"] = "free";
  34. PanOnScrollMode2["Vertical"] = "vertical";
  35. PanOnScrollMode2["Horizontal"] = "horizontal";
  36. })(exports.PanOnScrollMode || (exports.PanOnScrollMode = {}));
  37. exports.SelectionMode = void 0;
  38. (function(SelectionMode2) {
  39. SelectionMode2["Partial"] = "partial";
  40. SelectionMode2["Full"] = "full";
  41. })(exports.SelectionMode || (exports.SelectionMode = {}));
  42. var initialConnection = {
  43. inProgress: false,
  44. isValid: null,
  45. from: null,
  46. fromHandle: null,
  47. fromPosition: null,
  48. fromNode: null,
  49. to: null,
  50. toHandle: null,
  51. toPosition: null,
  52. toNode: null
  53. };
  54. exports.ConnectionLineType = void 0;
  55. (function(ConnectionLineType2) {
  56. ConnectionLineType2["Bezier"] = "default";
  57. ConnectionLineType2["Straight"] = "straight";
  58. ConnectionLineType2["Step"] = "step";
  59. ConnectionLineType2["SmoothStep"] = "smoothstep";
  60. ConnectionLineType2["SimpleBezier"] = "simplebezier";
  61. })(exports.ConnectionLineType || (exports.ConnectionLineType = {}));
  62. exports.MarkerType = void 0;
  63. (function(MarkerType2) {
  64. MarkerType2["Arrow"] = "arrow";
  65. MarkerType2["ArrowClosed"] = "arrowclosed";
  66. })(exports.MarkerType || (exports.MarkerType = {}));
  67. exports.Position = void 0;
  68. (function(Position2) {
  69. Position2["Left"] = "left";
  70. Position2["Top"] = "top";
  71. Position2["Right"] = "right";
  72. Position2["Bottom"] = "bottom";
  73. })(exports.Position || (exports.Position = {}));
  74. var oppositePosition = {
  75. [exports.Position.Left]: exports.Position.Right,
  76. [exports.Position.Right]: exports.Position.Left,
  77. [exports.Position.Top]: exports.Position.Bottom,
  78. [exports.Position.Bottom]: exports.Position.Top
  79. };
  80. function areConnectionMapsEqual(a, b) {
  81. if (!a && !b) {
  82. return true;
  83. }
  84. if (!a || !b || a.size !== b.size) {
  85. return false;
  86. }
  87. if (!a.size && !b.size) {
  88. return true;
  89. }
  90. for (const key of a.keys()) {
  91. if (!b.has(key)) {
  92. return false;
  93. }
  94. }
  95. return true;
  96. }
  97. function handleConnectionChange(a, b, cb) {
  98. if (!cb) {
  99. return;
  100. }
  101. const diff = [];
  102. a.forEach((connection, key) => {
  103. if (!b?.has(key)) {
  104. diff.push(connection);
  105. }
  106. });
  107. if (diff.length) {
  108. cb(diff);
  109. }
  110. }
  111. function getConnectionStatus(isValid) {
  112. return isValid === null ? null : isValid ? "valid" : "invalid";
  113. }
  114. var isEdgeBase = (element) => "id" in element && "source" in element && "target" in element;
  115. var isNodeBase = (element) => "id" in element && "position" in element && !("source" in element) && !("target" in element);
  116. var isInternalNodeBase = (element) => "id" in element && "internals" in element && !("source" in element) && !("target" in element);
  117. var getOutgoers = (node, nodes, edges) => {
  118. if (!node.id) {
  119. return [];
  120. }
  121. const outgoerIds = new Set();
  122. edges.forEach((edge) => {
  123. if (edge.source === node.id) {
  124. outgoerIds.add(edge.target);
  125. }
  126. });
  127. return nodes.filter((n) => outgoerIds.has(n.id));
  128. };
  129. var getIncomers = (node, nodes, edges) => {
  130. if (!node.id) {
  131. return [];
  132. }
  133. const incomersIds = new Set();
  134. edges.forEach((edge) => {
  135. if (edge.target === node.id) {
  136. incomersIds.add(edge.source);
  137. }
  138. });
  139. return nodes.filter((n) => incomersIds.has(n.id));
  140. };
  141. var getNodePositionWithOrigin = (node, nodeOrigin = [0, 0]) => {
  142. const { width, height } = getNodeDimensions(node);
  143. const origin = node.origin ?? nodeOrigin;
  144. const offsetX = width * origin[0];
  145. const offsetY = height * origin[1];
  146. return {
  147. x: node.position.x - offsetX,
  148. y: node.position.y - offsetY
  149. };
  150. };
  151. var getNodesBounds = (nodes, params = { nodeOrigin: [0, 0], nodeLookup: void 0 }) => {
  152. if (!params.nodeLookup) {
  153. console.warn("Please use `getNodesBounds` from `useReactFlow`/`useSvelteFlow` hook to ensure correct values for sub flows. If not possible, you have to provide a nodeLookup to support sub flows.");
  154. }
  155. if (nodes.length === 0) {
  156. return { x: 0, y: 0, width: 0, height: 0 };
  157. }
  158. const box = nodes.reduce((currBox, nodeOrId) => {
  159. const isId = typeof nodeOrId === "string";
  160. let currentNode = !params.nodeLookup && !isId ? nodeOrId : void 0;
  161. if (params.nodeLookup) {
  162. currentNode = isId ? params.nodeLookup.get(nodeOrId) : !isInternalNodeBase(nodeOrId) ? params.nodeLookup.get(nodeOrId.id) : nodeOrId;
  163. }
  164. const nodeBox = currentNode ? nodeToBox(currentNode, params.nodeOrigin) : { x: 0, y: 0, x2: 0, y2: 0 };
  165. return getBoundsOfBoxes(currBox, nodeBox);
  166. }, { x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity });
  167. return boxToRect(box);
  168. };
  169. var getInternalNodesBounds = (nodeLookup, params = {}) => {
  170. if (nodeLookup.size === 0) {
  171. return { x: 0, y: 0, width: 0, height: 0 };
  172. }
  173. let box = { x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity };
  174. nodeLookup.forEach((node) => {
  175. if (params.filter === void 0 || params.filter(node)) {
  176. const nodeBox = nodeToBox(node);
  177. box = getBoundsOfBoxes(box, nodeBox);
  178. }
  179. });
  180. return boxToRect(box);
  181. };
  182. var getNodesInside = (nodes, rect, [tx, ty, tScale] = [0, 0, 1], partially = false, excludeNonSelectableNodes = false) => {
  183. const paneRect = {
  184. ...pointToRendererPoint(rect, [tx, ty, tScale]),
  185. width: rect.width / tScale,
  186. height: rect.height / tScale
  187. };
  188. const visibleNodes = [];
  189. for (const node of nodes.values()) {
  190. const { measured, selectable = true, hidden = false } = node;
  191. if (excludeNonSelectableNodes && !selectable || hidden) {
  192. continue;
  193. }
  194. const width = measured.width ?? node.width ?? node.initialWidth ?? null;
  195. const height = measured.height ?? node.height ?? node.initialHeight ?? null;
  196. const overlappingArea = getOverlappingArea(paneRect, nodeToRect(node));
  197. const area = (width ?? 0) * (height ?? 0);
  198. const partiallyVisible = partially && overlappingArea > 0;
  199. const forceInitialRender = !node.internals.handleBounds;
  200. const isVisible = forceInitialRender || partiallyVisible || overlappingArea >= area;
  201. if (isVisible || node.dragging) {
  202. visibleNodes.push(node);
  203. }
  204. }
  205. return visibleNodes;
  206. };
  207. var getConnectedEdges = (nodes, edges) => {
  208. const nodeIds = new Set();
  209. nodes.forEach((node) => {
  210. nodeIds.add(node.id);
  211. });
  212. return edges.filter((edge) => nodeIds.has(edge.source) || nodeIds.has(edge.target));
  213. };
  214. function getFitViewNodes(nodeLookup, options) {
  215. const fitViewNodes = new Map();
  216. const optionNodeIds = options?.nodes ? new Set(options.nodes.map((node) => node.id)) : null;
  217. nodeLookup.forEach((n) => {
  218. const isVisible = n.measured.width && n.measured.height && (options?.includeHiddenNodes || !n.hidden);
  219. if (isVisible && (!optionNodeIds || optionNodeIds.has(n.id))) {
  220. fitViewNodes.set(n.id, n);
  221. }
  222. });
  223. return fitViewNodes;
  224. }
  225. async function fitView({ nodes, width, height, panZoom, minZoom, maxZoom }, options) {
  226. if (nodes.size === 0) {
  227. return Promise.resolve(false);
  228. }
  229. const bounds = getInternalNodesBounds(nodes);
  230. const viewport = getViewportForBounds(bounds, width, height, options?.minZoom ?? minZoom, options?.maxZoom ?? maxZoom, options?.padding ?? 0.1);
  231. await panZoom.setViewport(viewport, { duration: options?.duration });
  232. return Promise.resolve(true);
  233. }
  234. function calculateNodePosition({ nodeId, nextPosition, nodeLookup, nodeOrigin = [0, 0], nodeExtent, onError }) {
  235. const node = nodeLookup.get(nodeId);
  236. const parentNode = node.parentId ? nodeLookup.get(node.parentId) : void 0;
  237. const { x: parentX, y: parentY } = parentNode ? parentNode.internals.positionAbsolute : { x: 0, y: 0 };
  238. const origin = node.origin ?? nodeOrigin;
  239. let extent = nodeExtent;
  240. if (node.extent === "parent" && !node.expandParent) {
  241. if (!parentNode) {
  242. onError?.("005", errorMessages["error005"]());
  243. } else {
  244. const parentWidth = parentNode.measured.width;
  245. const parentHeight = parentNode.measured.height;
  246. if (parentWidth && parentHeight) {
  247. extent = [
  248. [parentX, parentY],
  249. [parentX + parentWidth, parentY + parentHeight]
  250. ];
  251. }
  252. }
  253. } else if (parentNode && isCoordinateExtent(node.extent)) {
  254. extent = [
  255. [node.extent[0][0] + parentX, node.extent[0][1] + parentY],
  256. [node.extent[1][0] + parentX, node.extent[1][1] + parentY]
  257. ];
  258. }
  259. const positionAbsolute = isCoordinateExtent(extent) ? clampPosition(nextPosition, extent, node.measured) : nextPosition;
  260. return {
  261. position: {
  262. x: positionAbsolute.x - parentX + node.measured.width * origin[0],
  263. y: positionAbsolute.y - parentY + node.measured.height * origin[1]
  264. },
  265. positionAbsolute
  266. };
  267. }
  268. async function getElementsToRemove({ nodesToRemove = [], edgesToRemove = [], nodes, edges, onBeforeDelete }) {
  269. const nodeIds = new Set(nodesToRemove.map((node) => node.id));
  270. const matchingNodes = [];
  271. for (const node of nodes) {
  272. if (node.deletable === false) {
  273. continue;
  274. }
  275. const isIncluded = nodeIds.has(node.id);
  276. const parentHit = !isIncluded && node.parentId && matchingNodes.find((n) => n.id === node.parentId);
  277. if (isIncluded || parentHit) {
  278. matchingNodes.push(node);
  279. }
  280. }
  281. const edgeIds = new Set(edgesToRemove.map((edge) => edge.id));
  282. const deletableEdges = edges.filter((edge) => edge.deletable !== false);
  283. const connectedEdges = getConnectedEdges(matchingNodes, deletableEdges);
  284. const matchingEdges = connectedEdges;
  285. for (const edge of deletableEdges) {
  286. const isIncluded = edgeIds.has(edge.id);
  287. if (isIncluded && !matchingEdges.find((e) => e.id === edge.id)) {
  288. matchingEdges.push(edge);
  289. }
  290. }
  291. if (!onBeforeDelete) {
  292. return {
  293. edges: matchingEdges,
  294. nodes: matchingNodes
  295. };
  296. }
  297. const onBeforeDeleteResult = await onBeforeDelete({
  298. nodes: matchingNodes,
  299. edges: matchingEdges
  300. });
  301. if (typeof onBeforeDeleteResult === "boolean") {
  302. return onBeforeDeleteResult ? { edges: matchingEdges, nodes: matchingNodes } : { edges: [], nodes: [] };
  303. }
  304. return onBeforeDeleteResult;
  305. }
  306. var clamp = (val, min = 0, max = 1) => Math.min(Math.max(val, min), max);
  307. var clampPosition = (position = { x: 0, y: 0 }, extent, dimensions) => ({
  308. x: clamp(position.x, extent[0][0], extent[1][0] - (dimensions?.width ?? 0)),
  309. y: clamp(position.y, extent[0][1], extent[1][1] - (dimensions?.height ?? 0))
  310. });
  311. function clampPositionToParent(childPosition, childDimensions, parent) {
  312. const { width: parentWidth, height: parentHeight } = getNodeDimensions(parent);
  313. const { x: parentX, y: parentY } = parent.internals.positionAbsolute;
  314. return clampPosition(childPosition, [
  315. [parentX, parentY],
  316. [parentX + parentWidth, parentY + parentHeight]
  317. ], childDimensions);
  318. }
  319. var calcAutoPanVelocity = (value, min, max) => {
  320. if (value < min) {
  321. return clamp(Math.abs(value - min), 1, min) / min;
  322. } else if (value > max) {
  323. return -clamp(Math.abs(value - max), 1, min) / min;
  324. }
  325. return 0;
  326. };
  327. var calcAutoPan = (pos, bounds, speed = 15, distance2 = 40) => {
  328. const xMovement = calcAutoPanVelocity(pos.x, distance2, bounds.width - distance2) * speed;
  329. const yMovement = calcAutoPanVelocity(pos.y, distance2, bounds.height - distance2) * speed;
  330. return [xMovement, yMovement];
  331. };
  332. var getBoundsOfBoxes = (box1, box2) => ({
  333. x: Math.min(box1.x, box2.x),
  334. y: Math.min(box1.y, box2.y),
  335. x2: Math.max(box1.x2, box2.x2),
  336. y2: Math.max(box1.y2, box2.y2)
  337. });
  338. var rectToBox = ({ x, y, width, height }) => ({
  339. x,
  340. y,
  341. x2: x + width,
  342. y2: y + height
  343. });
  344. var boxToRect = ({ x, y, x2, y2 }) => ({
  345. x,
  346. y,
  347. width: x2 - x,
  348. height: y2 - y
  349. });
  350. var nodeToRect = (node, nodeOrigin = [0, 0]) => {
  351. const { x, y } = isInternalNodeBase(node) ? node.internals.positionAbsolute : getNodePositionWithOrigin(node, nodeOrigin);
  352. return {
  353. x,
  354. y,
  355. width: node.measured?.width ?? node.width ?? node.initialWidth ?? 0,
  356. height: node.measured?.height ?? node.height ?? node.initialHeight ?? 0
  357. };
  358. };
  359. var nodeToBox = (node, nodeOrigin = [0, 0]) => {
  360. const { x, y } = isInternalNodeBase(node) ? node.internals.positionAbsolute : getNodePositionWithOrigin(node, nodeOrigin);
  361. return {
  362. x,
  363. y,
  364. x2: x + (node.measured?.width ?? node.width ?? node.initialWidth ?? 0),
  365. y2: y + (node.measured?.height ?? node.height ?? node.initialHeight ?? 0)
  366. };
  367. };
  368. var getBoundsOfRects = (rect1, rect2) => boxToRect(getBoundsOfBoxes(rectToBox(rect1), rectToBox(rect2)));
  369. var getOverlappingArea = (rectA, rectB) => {
  370. const xOverlap = Math.max(0, Math.min(rectA.x + rectA.width, rectB.x + rectB.width) - Math.max(rectA.x, rectB.x));
  371. const yOverlap = Math.max(0, Math.min(rectA.y + rectA.height, rectB.y + rectB.height) - Math.max(rectA.y, rectB.y));
  372. return Math.ceil(xOverlap * yOverlap);
  373. };
  374. var isRectObject = (obj) => isNumeric(obj.width) && isNumeric(obj.height) && isNumeric(obj.x) && isNumeric(obj.y);
  375. var isNumeric = (n) => !isNaN(n) && isFinite(n);
  376. var devWarn = (id, message) => {
  377. {
  378. console.warn(`[React Flow]: ${message} Help: https://reactflow.dev/error#${id}`);
  379. }
  380. };
  381. var snapPosition = (position, snapGrid = [1, 1]) => {
  382. return {
  383. x: snapGrid[0] * Math.round(position.x / snapGrid[0]),
  384. y: snapGrid[1] * Math.round(position.y / snapGrid[1])
  385. };
  386. };
  387. var pointToRendererPoint = ({ x, y }, [tx, ty, tScale], snapToGrid = false, snapGrid = [1, 1]) => {
  388. const position = {
  389. x: (x - tx) / tScale,
  390. y: (y - ty) / tScale
  391. };
  392. return snapToGrid ? snapPosition(position, snapGrid) : position;
  393. };
  394. var rendererPointToPoint = ({ x, y }, [tx, ty, tScale]) => {
  395. return {
  396. x: x * tScale + tx,
  397. y: y * tScale + ty
  398. };
  399. };
  400. var getViewportForBounds = (bounds, width, height, minZoom, maxZoom, padding) => {
  401. const xZoom = width / (bounds.width * (1 + padding));
  402. const yZoom = height / (bounds.height * (1 + padding));
  403. const zoom2 = Math.min(xZoom, yZoom);
  404. const clampedZoom = clamp(zoom2, minZoom, maxZoom);
  405. const boundsCenterX = bounds.x + bounds.width / 2;
  406. const boundsCenterY = bounds.y + bounds.height / 2;
  407. const x = width / 2 - boundsCenterX * clampedZoom;
  408. const y = height / 2 - boundsCenterY * clampedZoom;
  409. return { x, y, zoom: clampedZoom };
  410. };
  411. var isMacOs = () => typeof navigator !== "undefined" && navigator?.userAgent?.indexOf("Mac") >= 0;
  412. function isCoordinateExtent(extent) {
  413. return extent !== void 0 && extent !== "parent";
  414. }
  415. function getNodeDimensions(node) {
  416. return {
  417. width: node.measured?.width ?? node.width ?? node.initialWidth ?? 0,
  418. height: node.measured?.height ?? node.height ?? node.initialHeight ?? 0
  419. };
  420. }
  421. function nodeHasDimensions(node) {
  422. return (node.measured?.width ?? node.width ?? node.initialWidth) !== void 0 && (node.measured?.height ?? node.height ?? node.initialHeight) !== void 0;
  423. }
  424. function evaluateAbsolutePosition(position, dimensions = { width: 0, height: 0 }, parentId, nodeLookup, nodeOrigin) {
  425. const positionAbsolute = { ...position };
  426. const parent = nodeLookup.get(parentId);
  427. if (parent) {
  428. const origin = parent.origin || nodeOrigin;
  429. positionAbsolute.x += parent.internals.positionAbsolute.x - (dimensions.width ?? 0) * origin[0];
  430. positionAbsolute.y += parent.internals.positionAbsolute.y - (dimensions.height ?? 0) * origin[1];
  431. }
  432. return positionAbsolute;
  433. }
  434. function getPointerPosition(event, { snapGrid = [0, 0], snapToGrid = false, transform, containerBounds }) {
  435. const { x, y } = getEventPosition(event);
  436. const pointerPos = pointToRendererPoint({ x: x - (containerBounds?.left ?? 0), y: y - (containerBounds?.top ?? 0) }, transform);
  437. const { x: xSnapped, y: ySnapped } = snapToGrid ? snapPosition(pointerPos, snapGrid) : pointerPos;
  438. return {
  439. xSnapped,
  440. ySnapped,
  441. ...pointerPos
  442. };
  443. }
  444. var getDimensions = (node) => ({
  445. width: node.offsetWidth,
  446. height: node.offsetHeight
  447. });
  448. var getHostForElement = (element) => element.getRootNode?.() || window?.document;
  449. var inputTags = ["INPUT", "SELECT", "TEXTAREA"];
  450. function isInputDOMNode(event) {
  451. const target = event.composedPath?.()?.[0] || event.target;
  452. const isInput = inputTags.includes(target?.nodeName) || target?.hasAttribute?.("contenteditable");
  453. return isInput || !!target?.closest(".nokey");
  454. }
  455. var isMouseEvent = (event) => "clientX" in event;
  456. var getEventPosition = (event, bounds) => {
  457. const isMouse = isMouseEvent(event);
  458. const evtX = isMouse ? event.clientX : event.touches?.[0].clientX;
  459. const evtY = isMouse ? event.clientY : event.touches?.[0].clientY;
  460. return {
  461. x: evtX - (bounds?.left ?? 0),
  462. y: evtY - (bounds?.top ?? 0)
  463. };
  464. };
  465. var getHandleBounds = (type, nodeElement, nodeBounds, zoom2, nodeId) => {
  466. const handles = nodeElement.querySelectorAll(`.${type}`);
  467. if (!handles || !handles.length) {
  468. return null;
  469. }
  470. return Array.from(handles).map((handle) => {
  471. const handleBounds = handle.getBoundingClientRect();
  472. return {
  473. id: handle.getAttribute("data-handleid"),
  474. type,
  475. nodeId,
  476. position: handle.getAttribute("data-handlepos"),
  477. x: (handleBounds.left - nodeBounds.left) / zoom2,
  478. y: (handleBounds.top - nodeBounds.top) / zoom2,
  479. ...getDimensions(handle)
  480. };
  481. });
  482. };
  483. function getBezierEdgeCenter({ sourceX, sourceY, targetX, targetY, sourceControlX, sourceControlY, targetControlX, targetControlY }) {
  484. const centerX = sourceX * 0.125 + sourceControlX * 0.375 + targetControlX * 0.375 + targetX * 0.125;
  485. const centerY = sourceY * 0.125 + sourceControlY * 0.375 + targetControlY * 0.375 + targetY * 0.125;
  486. const offsetX = Math.abs(centerX - sourceX);
  487. const offsetY = Math.abs(centerY - sourceY);
  488. return [centerX, centerY, offsetX, offsetY];
  489. }
  490. function calculateControlOffset(distance2, curvature) {
  491. if (distance2 >= 0) {
  492. return 0.5 * distance2;
  493. }
  494. return curvature * 25 * Math.sqrt(-distance2);
  495. }
  496. function getControlWithCurvature({ pos, x1, y1, x2, y2, c }) {
  497. switch (pos) {
  498. case exports.Position.Left:
  499. return [x1 - calculateControlOffset(x1 - x2, c), y1];
  500. case exports.Position.Right:
  501. return [x1 + calculateControlOffset(x2 - x1, c), y1];
  502. case exports.Position.Top:
  503. return [x1, y1 - calculateControlOffset(y1 - y2, c)];
  504. case exports.Position.Bottom:
  505. return [x1, y1 + calculateControlOffset(y2 - y1, c)];
  506. }
  507. }
  508. function getBezierPath({ sourceX, sourceY, sourcePosition = exports.Position.Bottom, targetX, targetY, targetPosition = exports.Position.Top, curvature = 0.25 }) {
  509. const [sourceControlX, sourceControlY] = getControlWithCurvature({
  510. pos: sourcePosition,
  511. x1: sourceX,
  512. y1: sourceY,
  513. x2: targetX,
  514. y2: targetY,
  515. c: curvature
  516. });
  517. const [targetControlX, targetControlY] = getControlWithCurvature({
  518. pos: targetPosition,
  519. x1: targetX,
  520. y1: targetY,
  521. x2: sourceX,
  522. y2: sourceY,
  523. c: curvature
  524. });
  525. const [labelX, labelY, offsetX, offsetY] = getBezierEdgeCenter({
  526. sourceX,
  527. sourceY,
  528. targetX,
  529. targetY,
  530. sourceControlX,
  531. sourceControlY,
  532. targetControlX,
  533. targetControlY
  534. });
  535. return [
  536. `M${sourceX},${sourceY} C${sourceControlX},${sourceControlY} ${targetControlX},${targetControlY} ${targetX},${targetY}`,
  537. labelX,
  538. labelY,
  539. offsetX,
  540. offsetY
  541. ];
  542. }
  543. function getEdgeCenter({ sourceX, sourceY, targetX, targetY }) {
  544. const xOffset = Math.abs(targetX - sourceX) / 2;
  545. const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;
  546. const yOffset = Math.abs(targetY - sourceY) / 2;
  547. const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;
  548. return [centerX, centerY, xOffset, yOffset];
  549. }
  550. function getElevatedEdgeZIndex({ sourceNode, targetNode, selected = false, zIndex = 0, elevateOnSelect = false }) {
  551. if (!elevateOnSelect) {
  552. return zIndex;
  553. }
  554. const edgeOrConnectedNodeSelected = selected || targetNode.selected || sourceNode.selected;
  555. const selectedZIndex = Math.max(sourceNode.internals.z || 0, targetNode.internals.z || 0, 1e3);
  556. return zIndex + (edgeOrConnectedNodeSelected ? selectedZIndex : 0);
  557. }
  558. function isEdgeVisible({ sourceNode, targetNode, width, height, transform }) {
  559. const edgeBox = getBoundsOfBoxes(nodeToBox(sourceNode), nodeToBox(targetNode));
  560. if (edgeBox.x === edgeBox.x2) {
  561. edgeBox.x2 += 1;
  562. }
  563. if (edgeBox.y === edgeBox.y2) {
  564. edgeBox.y2 += 1;
  565. }
  566. const viewRect = {
  567. x: -transform[0] / transform[2],
  568. y: -transform[1] / transform[2],
  569. width: width / transform[2],
  570. height: height / transform[2]
  571. };
  572. return getOverlappingArea(viewRect, boxToRect(edgeBox)) > 0;
  573. }
  574. var getEdgeId = ({ source, sourceHandle, target, targetHandle }) => `xy-edge__${source}${sourceHandle || ""}-${target}${targetHandle || ""}`;
  575. var connectionExists = (edge, edges) => {
  576. return edges.some((el) => el.source === edge.source && el.target === edge.target && (el.sourceHandle === edge.sourceHandle || !el.sourceHandle && !edge.sourceHandle) && (el.targetHandle === edge.targetHandle || !el.targetHandle && !edge.targetHandle));
  577. };
  578. var addEdge = (edgeParams, edges) => {
  579. if (!edgeParams.source || !edgeParams.target) {
  580. devWarn("006", errorMessages["error006"]());
  581. return edges;
  582. }
  583. let edge;
  584. if (isEdgeBase(edgeParams)) {
  585. edge = { ...edgeParams };
  586. } else {
  587. edge = {
  588. ...edgeParams,
  589. id: getEdgeId(edgeParams)
  590. };
  591. }
  592. if (connectionExists(edge, edges)) {
  593. return edges;
  594. }
  595. if (edge.sourceHandle === null) {
  596. delete edge.sourceHandle;
  597. }
  598. if (edge.targetHandle === null) {
  599. delete edge.targetHandle;
  600. }
  601. return edges.concat(edge);
  602. };
  603. var reconnectEdge = (oldEdge, newConnection, edges, options = { shouldReplaceId: true }) => {
  604. const { id: oldEdgeId, ...rest } = oldEdge;
  605. if (!newConnection.source || !newConnection.target) {
  606. devWarn("006", errorMessages["error006"]());
  607. return edges;
  608. }
  609. const foundEdge = edges.find((e) => e.id === oldEdge.id);
  610. if (!foundEdge) {
  611. devWarn("007", errorMessages["error007"](oldEdgeId));
  612. return edges;
  613. }
  614. const edge = {
  615. ...rest,
  616. id: options.shouldReplaceId ? getEdgeId(newConnection) : oldEdgeId,
  617. source: newConnection.source,
  618. target: newConnection.target,
  619. sourceHandle: newConnection.sourceHandle,
  620. targetHandle: newConnection.targetHandle
  621. };
  622. return edges.filter((e) => e.id !== oldEdgeId).concat(edge);
  623. };
  624. function getStraightPath({ sourceX, sourceY, targetX, targetY }) {
  625. const [labelX, labelY, offsetX, offsetY] = getEdgeCenter({
  626. sourceX,
  627. sourceY,
  628. targetX,
  629. targetY
  630. });
  631. return [`M ${sourceX},${sourceY}L ${targetX},${targetY}`, labelX, labelY, offsetX, offsetY];
  632. }
  633. var handleDirections = {
  634. [exports.Position.Left]: { x: -1, y: 0 },
  635. [exports.Position.Right]: { x: 1, y: 0 },
  636. [exports.Position.Top]: { x: 0, y: -1 },
  637. [exports.Position.Bottom]: { x: 0, y: 1 }
  638. };
  639. var getDirection = ({ source, sourcePosition = exports.Position.Bottom, target }) => {
  640. if (sourcePosition === exports.Position.Left || sourcePosition === exports.Position.Right) {
  641. return source.x < target.x ? { x: 1, y: 0 } : { x: -1, y: 0 };
  642. }
  643. return source.y < target.y ? { x: 0, y: 1 } : { x: 0, y: -1 };
  644. };
  645. var distance = (a, b) => Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));
  646. function getPoints({ source, sourcePosition = exports.Position.Bottom, target, targetPosition = exports.Position.Top, center, offset }) {
  647. const sourceDir = handleDirections[sourcePosition];
  648. const targetDir = handleDirections[targetPosition];
  649. const sourceGapped = { x: source.x + sourceDir.x * offset, y: source.y + sourceDir.y * offset };
  650. const targetGapped = { x: target.x + targetDir.x * offset, y: target.y + targetDir.y * offset };
  651. const dir = getDirection({
  652. source: sourceGapped,
  653. sourcePosition,
  654. target: targetGapped
  655. });
  656. const dirAccessor = dir.x !== 0 ? "x" : "y";
  657. const currDir = dir[dirAccessor];
  658. let points = [];
  659. let centerX, centerY;
  660. const sourceGapOffset = { x: 0, y: 0 };
  661. const targetGapOffset = { x: 0, y: 0 };
  662. const [defaultCenterX, defaultCenterY, defaultOffsetX, defaultOffsetY] = getEdgeCenter({
  663. sourceX: source.x,
  664. sourceY: source.y,
  665. targetX: target.x,
  666. targetY: target.y
  667. });
  668. if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) {
  669. centerX = center.x ?? defaultCenterX;
  670. centerY = center.y ?? defaultCenterY;
  671. const verticalSplit = [
  672. { x: centerX, y: sourceGapped.y },
  673. { x: centerX, y: targetGapped.y }
  674. ];
  675. const horizontalSplit = [
  676. { x: sourceGapped.x, y: centerY },
  677. { x: targetGapped.x, y: centerY }
  678. ];
  679. if (sourceDir[dirAccessor] === currDir) {
  680. points = dirAccessor === "x" ? verticalSplit : horizontalSplit;
  681. } else {
  682. points = dirAccessor === "x" ? horizontalSplit : verticalSplit;
  683. }
  684. } else {
  685. const sourceTarget = [{ x: sourceGapped.x, y: targetGapped.y }];
  686. const targetSource = [{ x: targetGapped.x, y: sourceGapped.y }];
  687. if (dirAccessor === "x") {
  688. points = sourceDir.x === currDir ? targetSource : sourceTarget;
  689. } else {
  690. points = sourceDir.y === currDir ? sourceTarget : targetSource;
  691. }
  692. if (sourcePosition === targetPosition) {
  693. const diff = Math.abs(source[dirAccessor] - target[dirAccessor]);
  694. if (diff <= offset) {
  695. const gapOffset = Math.min(offset - 1, offset - diff);
  696. if (sourceDir[dirAccessor] === currDir) {
  697. sourceGapOffset[dirAccessor] = (sourceGapped[dirAccessor] > source[dirAccessor] ? -1 : 1) * gapOffset;
  698. } else {
  699. targetGapOffset[dirAccessor] = (targetGapped[dirAccessor] > target[dirAccessor] ? -1 : 1) * gapOffset;
  700. }
  701. }
  702. }
  703. if (sourcePosition !== targetPosition) {
  704. const dirAccessorOpposite = dirAccessor === "x" ? "y" : "x";
  705. const isSameDir = sourceDir[dirAccessor] === targetDir[dirAccessorOpposite];
  706. const sourceGtTargetOppo = sourceGapped[dirAccessorOpposite] > targetGapped[dirAccessorOpposite];
  707. const sourceLtTargetOppo = sourceGapped[dirAccessorOpposite] < targetGapped[dirAccessorOpposite];
  708. const flipSourceTarget = sourceDir[dirAccessor] === 1 && (!isSameDir && sourceGtTargetOppo || isSameDir && sourceLtTargetOppo) || sourceDir[dirAccessor] !== 1 && (!isSameDir && sourceLtTargetOppo || isSameDir && sourceGtTargetOppo);
  709. if (flipSourceTarget) {
  710. points = dirAccessor === "x" ? sourceTarget : targetSource;
  711. }
  712. }
  713. const sourceGapPoint = { x: sourceGapped.x + sourceGapOffset.x, y: sourceGapped.y + sourceGapOffset.y };
  714. const targetGapPoint = { x: targetGapped.x + targetGapOffset.x, y: targetGapped.y + targetGapOffset.y };
  715. const maxXDistance = Math.max(Math.abs(sourceGapPoint.x - points[0].x), Math.abs(targetGapPoint.x - points[0].x));
  716. const maxYDistance = Math.max(Math.abs(sourceGapPoint.y - points[0].y), Math.abs(targetGapPoint.y - points[0].y));
  717. if (maxXDistance >= maxYDistance) {
  718. centerX = (sourceGapPoint.x + targetGapPoint.x) / 2;
  719. centerY = points[0].y;
  720. } else {
  721. centerX = points[0].x;
  722. centerY = (sourceGapPoint.y + targetGapPoint.y) / 2;
  723. }
  724. }
  725. const pathPoints = [
  726. source,
  727. { x: sourceGapped.x + sourceGapOffset.x, y: sourceGapped.y + sourceGapOffset.y },
  728. ...points,
  729. { x: targetGapped.x + targetGapOffset.x, y: targetGapped.y + targetGapOffset.y },
  730. target
  731. ];
  732. return [pathPoints, centerX, centerY, defaultOffsetX, defaultOffsetY];
  733. }
  734. function getBend(a, b, c, size) {
  735. const bendSize = Math.min(distance(a, b) / 2, distance(b, c) / 2, size);
  736. const { x, y } = b;
  737. if (a.x === x && x === c.x || a.y === y && y === c.y) {
  738. return `L${x} ${y}`;
  739. }
  740. if (a.y === y) {
  741. const xDir2 = a.x < c.x ? -1 : 1;
  742. const yDir2 = a.y < c.y ? 1 : -1;
  743. return `L ${x + bendSize * xDir2},${y}Q ${x},${y} ${x},${y + bendSize * yDir2}`;
  744. }
  745. const xDir = a.x < c.x ? 1 : -1;
  746. const yDir = a.y < c.y ? -1 : 1;
  747. return `L ${x},${y + bendSize * yDir}Q ${x},${y} ${x + bendSize * xDir},${y}`;
  748. }
  749. function getSmoothStepPath({ sourceX, sourceY, sourcePosition = exports.Position.Bottom, targetX, targetY, targetPosition = exports.Position.Top, borderRadius = 5, centerX, centerY, offset = 20 }) {
  750. const [points, labelX, labelY, offsetX, offsetY] = getPoints({
  751. source: { x: sourceX, y: sourceY },
  752. sourcePosition,
  753. target: { x: targetX, y: targetY },
  754. targetPosition,
  755. center: { x: centerX, y: centerY },
  756. offset
  757. });
  758. const path = points.reduce((res, p, i) => {
  759. let segment = "";
  760. if (i > 0 && i < points.length - 1) {
  761. segment = getBend(points[i - 1], p, points[i + 1], borderRadius);
  762. } else {
  763. segment = `${i === 0 ? "M" : "L"}${p.x} ${p.y}`;
  764. }
  765. res += segment;
  766. return res;
  767. }, "");
  768. return [path, labelX, labelY, offsetX, offsetY];
  769. }
  770. function isNodeInitialized(node) {
  771. return node && !!(node.internals.handleBounds || node.handles?.length) && !!(node.measured.width || node.width || node.initialWidth);
  772. }
  773. function getEdgePosition(params) {
  774. const { sourceNode, targetNode } = params;
  775. if (!isNodeInitialized(sourceNode) || !isNodeInitialized(targetNode)) {
  776. return null;
  777. }
  778. const sourceHandleBounds = sourceNode.internals.handleBounds || toHandleBounds(sourceNode.handles);
  779. const targetHandleBounds = targetNode.internals.handleBounds || toHandleBounds(targetNode.handles);
  780. const sourceHandle = getHandle$1(sourceHandleBounds?.source ?? [], params.sourceHandle);
  781. const targetHandle = getHandle$1(
  782. // when connection type is loose we can define all handles as sources and connect source -> source
  783. params.connectionMode === exports.ConnectionMode.Strict ? targetHandleBounds?.target ?? [] : (targetHandleBounds?.target ?? []).concat(targetHandleBounds?.source ?? []),
  784. params.targetHandle
  785. );
  786. if (!sourceHandle || !targetHandle) {
  787. params.onError?.("008", errorMessages["error008"](!sourceHandle ? "source" : "target", {
  788. id: params.id,
  789. sourceHandle: params.sourceHandle,
  790. targetHandle: params.targetHandle
  791. }));
  792. return null;
  793. }
  794. const sourcePosition = sourceHandle?.position || exports.Position.Bottom;
  795. const targetPosition = targetHandle?.position || exports.Position.Top;
  796. const source = getHandlePosition(sourceNode, sourceHandle, sourcePosition);
  797. const target = getHandlePosition(targetNode, targetHandle, targetPosition);
  798. return {
  799. sourceX: source.x,
  800. sourceY: source.y,
  801. targetX: target.x,
  802. targetY: target.y,
  803. sourcePosition,
  804. targetPosition
  805. };
  806. }
  807. function toHandleBounds(handles) {
  808. if (!handles) {
  809. return null;
  810. }
  811. const source = [];
  812. const target = [];
  813. for (const handle of handles) {
  814. handle.width = handle.width ?? 1;
  815. handle.height = handle.height ?? 1;
  816. if (handle.type === "source") {
  817. source.push(handle);
  818. } else if (handle.type === "target") {
  819. target.push(handle);
  820. }
  821. }
  822. return {
  823. source,
  824. target
  825. };
  826. }
  827. function getHandlePosition(node, handle, fallbackPosition = exports.Position.Left, center = false) {
  828. const x = (handle?.x ?? 0) + node.internals.positionAbsolute.x;
  829. const y = (handle?.y ?? 0) + node.internals.positionAbsolute.y;
  830. const { width, height } = handle ?? getNodeDimensions(node);
  831. if (center) {
  832. return { x: x + width / 2, y: y + height / 2 };
  833. }
  834. const position = handle?.position ?? fallbackPosition;
  835. switch (position) {
  836. case exports.Position.Top:
  837. return { x: x + width / 2, y };
  838. case exports.Position.Right:
  839. return { x: x + width, y: y + height / 2 };
  840. case exports.Position.Bottom:
  841. return { x: x + width / 2, y: y + height };
  842. case exports.Position.Left:
  843. return { x, y: y + height / 2 };
  844. }
  845. }
  846. function getHandle$1(bounds, handleId) {
  847. if (!bounds) {
  848. return null;
  849. }
  850. return (!handleId ? bounds[0] : bounds.find((d) => d.id === handleId)) || null;
  851. }
  852. function getMarkerId(marker, id) {
  853. if (!marker) {
  854. return "";
  855. }
  856. if (typeof marker === "string") {
  857. return marker;
  858. }
  859. const idPrefix = id ? `${id}__` : "";
  860. return `${idPrefix}${Object.keys(marker).sort().map((key) => `${key}=${marker[key]}`).join("&")}`;
  861. }
  862. function createMarkerIds(edges, { id, defaultColor, defaultMarkerStart, defaultMarkerEnd }) {
  863. const ids = new Set();
  864. return edges.reduce((markers, edge) => {
  865. [edge.markerStart || defaultMarkerStart, edge.markerEnd || defaultMarkerEnd].forEach((marker) => {
  866. if (marker && typeof marker === "object") {
  867. const markerId = getMarkerId(marker, id);
  868. if (!ids.has(markerId)) {
  869. markers.push({ id: markerId, color: marker.color || defaultColor, ...marker });
  870. ids.add(markerId);
  871. }
  872. }
  873. });
  874. return markers;
  875. }, []).sort((a, b) => a.id.localeCompare(b.id));
  876. }
  877. function getNodeToolbarTransform(nodeRect, viewport, position, offset, align) {
  878. let alignmentOffset = 0.5;
  879. if (align === "start") {
  880. alignmentOffset = 0;
  881. } else if (align === "end") {
  882. alignmentOffset = 1;
  883. }
  884. let pos = [
  885. (nodeRect.x + nodeRect.width * alignmentOffset) * viewport.zoom + viewport.x,
  886. nodeRect.y * viewport.zoom + viewport.y - offset
  887. ];
  888. let shift = [-100 * alignmentOffset, -100];
  889. switch (position) {
  890. case exports.Position.Right:
  891. pos = [
  892. (nodeRect.x + nodeRect.width) * viewport.zoom + viewport.x + offset,
  893. (nodeRect.y + nodeRect.height * alignmentOffset) * viewport.zoom + viewport.y
  894. ];
  895. shift = [0, -100 * alignmentOffset];
  896. break;
  897. case exports.Position.Bottom:
  898. pos[1] = (nodeRect.y + nodeRect.height) * viewport.zoom + viewport.y + offset;
  899. shift[1] = 0;
  900. break;
  901. case exports.Position.Left:
  902. pos = [
  903. nodeRect.x * viewport.zoom + viewport.x - offset,
  904. (nodeRect.y + nodeRect.height * alignmentOffset) * viewport.zoom + viewport.y
  905. ];
  906. shift = [-100, -100 * alignmentOffset];
  907. break;
  908. }
  909. return `translate(${pos[0]}px, ${pos[1]}px) translate(${shift[0]}%, ${shift[1]}%)`;
  910. }
  911. var defaultOptions = {
  912. nodeOrigin: [0, 0],
  913. nodeExtent: infiniteExtent,
  914. elevateNodesOnSelect: true,
  915. defaults: {}
  916. };
  917. var adoptUserNodesDefaultOptions = {
  918. ...defaultOptions,
  919. checkEquality: true
  920. };
  921. function mergeObjects(base, incoming) {
  922. const result = { ...base };
  923. for (const key in incoming) {
  924. if (incoming[key] !== void 0) {
  925. result[key] = incoming[key];
  926. }
  927. }
  928. return result;
  929. }
  930. function updateAbsolutePositions(nodeLookup, parentLookup, options) {
  931. const _options = mergeObjects(defaultOptions, options);
  932. for (const node of nodeLookup.values()) {
  933. if (node.parentId) {
  934. updateChildNode(node, nodeLookup, parentLookup, _options);
  935. } else {
  936. const positionWithOrigin = getNodePositionWithOrigin(node, _options.nodeOrigin);
  937. const extent = isCoordinateExtent(node.extent) ? node.extent : _options.nodeExtent;
  938. const clampedPosition = clampPosition(positionWithOrigin, extent, getNodeDimensions(node));
  939. node.internals.positionAbsolute = clampedPosition;
  940. }
  941. }
  942. }
  943. function adoptUserNodes(nodes, nodeLookup, parentLookup, options) {
  944. const _options = mergeObjects(adoptUserNodesDefaultOptions, options);
  945. const tmpLookup = new Map(nodeLookup);
  946. const selectedNodeZ = _options?.elevateNodesOnSelect ? 1e3 : 0;
  947. nodeLookup.clear();
  948. parentLookup.clear();
  949. for (const userNode of nodes) {
  950. let internalNode = tmpLookup.get(userNode.id);
  951. if (_options.checkEquality && userNode === internalNode?.internals.userNode) {
  952. nodeLookup.set(userNode.id, internalNode);
  953. } else {
  954. const positionWithOrigin = getNodePositionWithOrigin(userNode, _options.nodeOrigin);
  955. const extent = isCoordinateExtent(userNode.extent) ? userNode.extent : _options.nodeExtent;
  956. const clampedPosition = clampPosition(positionWithOrigin, extent, getNodeDimensions(userNode));
  957. internalNode = {
  958. ..._options.defaults,
  959. ...userNode,
  960. measured: {
  961. width: userNode.measured?.width,
  962. height: userNode.measured?.height
  963. },
  964. internals: {
  965. positionAbsolute: clampedPosition,
  966. // if user re-initializes the node or removes `measured` for whatever reason, we reset the handleBounds so that the node gets re-measured
  967. handleBounds: !userNode.measured ? void 0 : internalNode?.internals.handleBounds,
  968. z: calculateZ(userNode, selectedNodeZ),
  969. userNode
  970. }
  971. };
  972. nodeLookup.set(userNode.id, internalNode);
  973. }
  974. if (userNode.parentId) {
  975. updateChildNode(internalNode, nodeLookup, parentLookup, options);
  976. }
  977. }
  978. }
  979. function updateParentLookup(node, parentLookup) {
  980. if (!node.parentId) {
  981. return;
  982. }
  983. const childNodes = parentLookup.get(node.parentId);
  984. if (childNodes) {
  985. childNodes.set(node.id, node);
  986. } else {
  987. parentLookup.set(node.parentId, new Map([[node.id, node]]));
  988. }
  989. }
  990. function updateChildNode(node, nodeLookup, parentLookup, options) {
  991. const { elevateNodesOnSelect, nodeOrigin, nodeExtent } = mergeObjects(defaultOptions, options);
  992. const parentId = node.parentId;
  993. const parentNode = nodeLookup.get(parentId);
  994. if (!parentNode) {
  995. console.warn(`Parent node ${parentId} not found. Please make sure that parent nodes are in front of their child nodes in the nodes array.`);
  996. return;
  997. }
  998. updateParentLookup(node, parentLookup);
  999. const selectedNodeZ = elevateNodesOnSelect ? 1e3 : 0;
  1000. const { x, y, z } = calculateChildXYZ(node, parentNode, nodeOrigin, nodeExtent, selectedNodeZ);
  1001. const { positionAbsolute } = node.internals;
  1002. const positionChanged = x !== positionAbsolute.x || y !== positionAbsolute.y;
  1003. if (positionChanged || z !== node.internals.z) {
  1004. node.internals = {
  1005. ...node.internals,
  1006. positionAbsolute: positionChanged ? { x, y } : positionAbsolute,
  1007. z
  1008. };
  1009. }
  1010. }
  1011. function calculateZ(node, selectedNodeZ) {
  1012. return (isNumeric(node.zIndex) ? node.zIndex : 0) + (node.selected ? selectedNodeZ : 0);
  1013. }
  1014. function calculateChildXYZ(childNode, parentNode, nodeOrigin, nodeExtent, selectedNodeZ) {
  1015. const { x: parentX, y: parentY } = parentNode.internals.positionAbsolute;
  1016. const childDimensions = getNodeDimensions(childNode);
  1017. const positionWithOrigin = getNodePositionWithOrigin(childNode, nodeOrigin);
  1018. const clampedPosition = isCoordinateExtent(childNode.extent) ? clampPosition(positionWithOrigin, childNode.extent, childDimensions) : positionWithOrigin;
  1019. let absolutePosition = clampPosition({ x: parentX + clampedPosition.x, y: parentY + clampedPosition.y }, nodeExtent, childDimensions);
  1020. if (childNode.extent === "parent") {
  1021. absolutePosition = clampPositionToParent(absolutePosition, childDimensions, parentNode);
  1022. }
  1023. const childZ = calculateZ(childNode, selectedNodeZ);
  1024. const parentZ = parentNode.internals.z ?? 0;
  1025. return {
  1026. x: absolutePosition.x,
  1027. y: absolutePosition.y,
  1028. z: parentZ > childZ ? parentZ : childZ
  1029. };
  1030. }
  1031. function handleExpandParent(children, nodeLookup, parentLookup, nodeOrigin = [0, 0]) {
  1032. const changes = [];
  1033. const parentExpansions = new Map();
  1034. for (const child of children) {
  1035. const parent = nodeLookup.get(child.parentId);
  1036. if (!parent) {
  1037. continue;
  1038. }
  1039. const parentRect = parentExpansions.get(child.parentId)?.expandedRect ?? nodeToRect(parent);
  1040. const expandedRect = getBoundsOfRects(parentRect, child.rect);
  1041. parentExpansions.set(child.parentId, { expandedRect, parent });
  1042. }
  1043. if (parentExpansions.size > 0) {
  1044. parentExpansions.forEach(({ expandedRect, parent }, parentId) => {
  1045. const positionAbsolute = parent.internals.positionAbsolute;
  1046. const dimensions = getNodeDimensions(parent);
  1047. const origin = parent.origin ?? nodeOrigin;
  1048. const xChange = expandedRect.x < positionAbsolute.x ? Math.round(Math.abs(positionAbsolute.x - expandedRect.x)) : 0;
  1049. const yChange = expandedRect.y < positionAbsolute.y ? Math.round(Math.abs(positionAbsolute.y - expandedRect.y)) : 0;
  1050. const newWidth = Math.max(dimensions.width, Math.round(expandedRect.width));
  1051. const newHeight = Math.max(dimensions.height, Math.round(expandedRect.height));
  1052. const widthChange = (newWidth - dimensions.width) * origin[0];
  1053. const heightChange = (newHeight - dimensions.height) * origin[1];
  1054. if (xChange > 0 || yChange > 0 || widthChange || heightChange) {
  1055. changes.push({
  1056. id: parentId,
  1057. type: "position",
  1058. position: {
  1059. x: parent.position.x - xChange + widthChange,
  1060. y: parent.position.y - yChange + heightChange
  1061. }
  1062. });
  1063. parentLookup.get(parentId)?.forEach((childNode) => {
  1064. if (!children.some((child) => child.id === childNode.id)) {
  1065. changes.push({
  1066. id: childNode.id,
  1067. type: "position",
  1068. position: {
  1069. x: childNode.position.x + xChange,
  1070. y: childNode.position.y + yChange
  1071. }
  1072. });
  1073. }
  1074. });
  1075. }
  1076. if (dimensions.width < expandedRect.width || dimensions.height < expandedRect.height || xChange || yChange) {
  1077. changes.push({
  1078. id: parentId,
  1079. type: "dimensions",
  1080. setAttributes: true,
  1081. dimensions: {
  1082. width: newWidth + (xChange ? origin[0] * xChange - widthChange : 0),
  1083. height: newHeight + (yChange ? origin[1] * yChange - heightChange : 0)
  1084. }
  1085. });
  1086. }
  1087. });
  1088. }
  1089. return changes;
  1090. }
  1091. function updateNodeInternals(updates, nodeLookup, parentLookup, domNode, nodeOrigin, nodeExtent) {
  1092. const viewportNode = domNode?.querySelector(".xyflow__viewport");
  1093. let updatedInternals = false;
  1094. if (!viewportNode) {
  1095. return { changes: [], updatedInternals };
  1096. }
  1097. const changes = [];
  1098. const style = window.getComputedStyle(viewportNode);
  1099. const { m22: zoom2 } = new window.DOMMatrixReadOnly(style.transform);
  1100. const parentExpandChildren = [];
  1101. for (const update of updates.values()) {
  1102. const node = nodeLookup.get(update.id);
  1103. if (!node) {
  1104. continue;
  1105. }
  1106. if (node.hidden) {
  1107. node.internals = {
  1108. ...node.internals,
  1109. handleBounds: void 0
  1110. };
  1111. updatedInternals = true;
  1112. } else {
  1113. const dimensions = getDimensions(update.nodeElement);
  1114. const dimensionChanged = node.measured.width !== dimensions.width || node.measured.height !== dimensions.height;
  1115. const doUpdate = !!(dimensions.width && dimensions.height && (dimensionChanged || !node.internals.handleBounds || update.force));
  1116. if (doUpdate) {
  1117. const nodeBounds = update.nodeElement.getBoundingClientRect();
  1118. const extent = isCoordinateExtent(node.extent) ? node.extent : nodeExtent;
  1119. let { positionAbsolute } = node.internals;
  1120. if (node.parentId && node.extent === "parent") {
  1121. positionAbsolute = clampPositionToParent(positionAbsolute, dimensions, nodeLookup.get(node.parentId));
  1122. } else if (extent) {
  1123. positionAbsolute = clampPosition(positionAbsolute, extent, dimensions);
  1124. }
  1125. node.measured = dimensions;
  1126. node.internals = {
  1127. ...node.internals,
  1128. positionAbsolute,
  1129. handleBounds: {
  1130. source: getHandleBounds("source", update.nodeElement, nodeBounds, zoom2, node.id),
  1131. target: getHandleBounds("target", update.nodeElement, nodeBounds, zoom2, node.id)
  1132. }
  1133. };
  1134. if (node.parentId) {
  1135. updateChildNode(node, nodeLookup, parentLookup, { nodeOrigin });
  1136. }
  1137. updatedInternals = true;
  1138. if (dimensionChanged) {
  1139. changes.push({
  1140. id: node.id,
  1141. type: "dimensions",
  1142. dimensions
  1143. });
  1144. if (node.expandParent && node.parentId) {
  1145. parentExpandChildren.push({
  1146. id: node.id,
  1147. parentId: node.parentId,
  1148. rect: nodeToRect(node, nodeOrigin)
  1149. });
  1150. }
  1151. }
  1152. }
  1153. }
  1154. }
  1155. if (parentExpandChildren.length > 0) {
  1156. const parentExpandChanges = handleExpandParent(parentExpandChildren, nodeLookup, parentLookup, nodeOrigin);
  1157. changes.push(...parentExpandChanges);
  1158. }
  1159. return { changes, updatedInternals };
  1160. }
  1161. async function panBy({ delta, panZoom, transform, translateExtent, width, height }) {
  1162. if (!panZoom || !delta.x && !delta.y) {
  1163. return Promise.resolve(false);
  1164. }
  1165. const nextViewport = await panZoom.setViewportConstrained({
  1166. x: transform[0] + delta.x,
  1167. y: transform[1] + delta.y,
  1168. zoom: transform[2]
  1169. }, [
  1170. [0, 0],
  1171. [width, height]
  1172. ], translateExtent);
  1173. const transformChanged = !!nextViewport && (nextViewport.x !== transform[0] || nextViewport.y !== transform[1] || nextViewport.k !== transform[2]);
  1174. return Promise.resolve(transformChanged);
  1175. }
  1176. function updateConnectionLookup(connectionLookup, edgeLookup, edges) {
  1177. connectionLookup.clear();
  1178. edgeLookup.clear();
  1179. for (const edge of edges) {
  1180. const { source, target, sourceHandle = null, targetHandle = null } = edge;
  1181. const sourceKey = `${source}-source-${sourceHandle}`;
  1182. const targetKey = `${target}-target-${targetHandle}`;
  1183. const prevSource = connectionLookup.get(sourceKey) || new Map();
  1184. const prevTarget = connectionLookup.get(targetKey) || new Map();
  1185. const connection = { edgeId: edge.id, source, target, sourceHandle, targetHandle };
  1186. edgeLookup.set(edge.id, edge);
  1187. connectionLookup.set(sourceKey, prevSource.set(`${target}-${targetHandle}`, connection));
  1188. connectionLookup.set(targetKey, prevTarget.set(`${source}-${sourceHandle}`, connection));
  1189. }
  1190. }
  1191. function shallowNodeData(a, b) {
  1192. if (a === null || b === null) {
  1193. return false;
  1194. }
  1195. const _a = Array.isArray(a) ? a : [a];
  1196. const _b = Array.isArray(b) ? b : [b];
  1197. if (_a.length !== _b.length) {
  1198. return false;
  1199. }
  1200. for (let i = 0; i < _a.length; i++) {
  1201. if (_a[i].id !== _b[i].id || _a[i].type !== _b[i].type || !Object.is(_a[i].data, _b[i].data)) {
  1202. return false;
  1203. }
  1204. }
  1205. return true;
  1206. }
  1207. function isParentSelected(node, nodeLookup) {
  1208. if (!node.parentId) {
  1209. return false;
  1210. }
  1211. const parentNode = nodeLookup.get(node.parentId);
  1212. if (!parentNode) {
  1213. return false;
  1214. }
  1215. if (parentNode.selected) {
  1216. return true;
  1217. }
  1218. return isParentSelected(parentNode, nodeLookup);
  1219. }
  1220. function hasSelector(target, selector, domNode) {
  1221. let current = target;
  1222. do {
  1223. if (current?.matches(selector))
  1224. return true;
  1225. if (current === domNode)
  1226. return false;
  1227. current = current.parentElement;
  1228. } while (current);
  1229. return false;
  1230. }
  1231. function getDragItems(nodeLookup, nodesDraggable, mousePos, nodeId) {
  1232. const dragItems = new Map();
  1233. for (const [id, node] of nodeLookup) {
  1234. if ((node.selected || node.id === nodeId) && (!node.parentId || !isParentSelected(node, nodeLookup)) && (node.draggable || nodesDraggable && typeof node.draggable === "undefined")) {
  1235. const internalNode = nodeLookup.get(id);
  1236. if (internalNode) {
  1237. dragItems.set(id, {
  1238. id,
  1239. position: internalNode.position || { x: 0, y: 0 },
  1240. distance: {
  1241. x: mousePos.x - internalNode.internals.positionAbsolute.x,
  1242. y: mousePos.y - internalNode.internals.positionAbsolute.y
  1243. },
  1244. extent: internalNode.extent,
  1245. parentId: internalNode.parentId,
  1246. origin: internalNode.origin,
  1247. expandParent: internalNode.expandParent,
  1248. internals: {
  1249. positionAbsolute: internalNode.internals.positionAbsolute || { x: 0, y: 0 }
  1250. },
  1251. measured: {
  1252. width: internalNode.measured.width ?? 0,
  1253. height: internalNode.measured.height ?? 0
  1254. }
  1255. });
  1256. }
  1257. }
  1258. }
  1259. return dragItems;
  1260. }
  1261. function getEventHandlerParams({ nodeId, dragItems, nodeLookup, dragging = true }) {
  1262. const nodesFromDragItems = [];
  1263. for (const [id, dragItem] of dragItems) {
  1264. const node2 = nodeLookup.get(id)?.internals.userNode;
  1265. if (node2) {
  1266. nodesFromDragItems.push({
  1267. ...node2,
  1268. position: dragItem.position,
  1269. dragging
  1270. });
  1271. }
  1272. }
  1273. if (!nodeId) {
  1274. return [nodesFromDragItems[0], nodesFromDragItems];
  1275. }
  1276. const node = nodeLookup.get(nodeId)?.internals.userNode;
  1277. return [
  1278. !node ? nodesFromDragItems[0] : {
  1279. ...node,
  1280. position: dragItems.get(nodeId)?.position || node.position,
  1281. dragging
  1282. },
  1283. nodesFromDragItems
  1284. ];
  1285. }
  1286. function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragStop }) {
  1287. let lastPos = { x: null, y: null };
  1288. let autoPanId = 0;
  1289. let dragItems = new Map();
  1290. let autoPanStarted = false;
  1291. let mousePosition = { x: 0, y: 0 };
  1292. let containerBounds = null;
  1293. let dragStarted = false;
  1294. let d3Selection$1 = null;
  1295. let abortDrag = false;
  1296. function update({ noDragClassName, handleSelector, domNode, isSelectable, nodeId, nodeClickDistance = 0 }) {
  1297. d3Selection$1 = d3Selection.select(domNode);
  1298. function updateNodes({ x, y }, dragEvent) {
  1299. const { nodeLookup, nodeExtent, snapGrid, snapToGrid, nodeOrigin, onNodeDrag, onSelectionDrag, onError, updateNodePositions } = getStoreItems();
  1300. lastPos = { x, y };
  1301. let hasChange = false;
  1302. let nodesBox = { x: 0, y: 0, x2: 0, y2: 0 };
  1303. if (dragItems.size > 1 && nodeExtent) {
  1304. const rect = getInternalNodesBounds(dragItems);
  1305. nodesBox = rectToBox(rect);
  1306. }
  1307. for (const [id, dragItem] of dragItems) {
  1308. if (!nodeLookup.has(id)) {
  1309. continue;
  1310. }
  1311. let nextPosition = { x: x - dragItem.distance.x, y: y - dragItem.distance.y };
  1312. if (snapToGrid) {
  1313. nextPosition = snapPosition(nextPosition, snapGrid);
  1314. }
  1315. let adjustedNodeExtent = [
  1316. [nodeExtent[0][0], nodeExtent[0][1]],
  1317. [nodeExtent[1][0], nodeExtent[1][1]]
  1318. ];
  1319. if (dragItems.size > 1 && nodeExtent && !dragItem.extent) {
  1320. const { positionAbsolute: positionAbsolute2 } = dragItem.internals;
  1321. const x1 = positionAbsolute2.x - nodesBox.x + nodeExtent[0][0];
  1322. const x2 = positionAbsolute2.x + dragItem.measured.width - nodesBox.x2 + nodeExtent[1][0];
  1323. const y1 = positionAbsolute2.y - nodesBox.y + nodeExtent[0][1];
  1324. const y2 = positionAbsolute2.y + dragItem.measured.height - nodesBox.y2 + nodeExtent[1][1];
  1325. adjustedNodeExtent = [
  1326. [x1, y1],
  1327. [x2, y2]
  1328. ];
  1329. }
  1330. const { position, positionAbsolute } = calculateNodePosition({
  1331. nodeId: id,
  1332. nextPosition,
  1333. nodeLookup,
  1334. nodeExtent: adjustedNodeExtent,
  1335. nodeOrigin,
  1336. onError
  1337. });
  1338. hasChange = hasChange || dragItem.position.x !== position.x || dragItem.position.y !== position.y;
  1339. dragItem.position = position;
  1340. dragItem.internals.positionAbsolute = positionAbsolute;
  1341. }
  1342. if (!hasChange) {
  1343. return;
  1344. }
  1345. updateNodePositions(dragItems, true);
  1346. if (dragEvent && (onDrag || onNodeDrag || !nodeId && onSelectionDrag)) {
  1347. const [currentNode, currentNodes] = getEventHandlerParams({
  1348. nodeId,
  1349. dragItems,
  1350. nodeLookup
  1351. });
  1352. onDrag?.(dragEvent, dragItems, currentNode, currentNodes);
  1353. onNodeDrag?.(dragEvent, currentNode, currentNodes);
  1354. if (!nodeId) {
  1355. onSelectionDrag?.(dragEvent, currentNodes);
  1356. }
  1357. }
  1358. }
  1359. async function autoPan() {
  1360. if (!containerBounds) {
  1361. return;
  1362. }
  1363. const { transform, panBy: panBy2, autoPanSpeed } = getStoreItems();
  1364. const [xMovement, yMovement] = calcAutoPan(mousePosition, containerBounds, autoPanSpeed);
  1365. if (xMovement !== 0 || yMovement !== 0) {
  1366. lastPos.x = (lastPos.x ?? 0) - xMovement / transform[2];
  1367. lastPos.y = (lastPos.y ?? 0) - yMovement / transform[2];
  1368. if (await panBy2({ x: xMovement, y: yMovement })) {
  1369. updateNodes(lastPos, null);
  1370. }
  1371. }
  1372. autoPanId = requestAnimationFrame(autoPan);
  1373. }
  1374. function startDrag(event) {
  1375. const { nodeLookup, multiSelectionActive, nodesDraggable, transform, snapGrid, snapToGrid, selectNodesOnDrag, onNodeDragStart, onSelectionDragStart, unselectNodesAndEdges } = getStoreItems();
  1376. dragStarted = true;
  1377. if ((!selectNodesOnDrag || !isSelectable) && !multiSelectionActive && nodeId) {
  1378. if (!nodeLookup.get(nodeId)?.selected) {
  1379. unselectNodesAndEdges();
  1380. }
  1381. }
  1382. if (isSelectable && selectNodesOnDrag && nodeId) {
  1383. onNodeMouseDown?.(nodeId);
  1384. }
  1385. const pointerPos = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid, containerBounds });
  1386. lastPos = pointerPos;
  1387. dragItems = getDragItems(nodeLookup, nodesDraggable, pointerPos, nodeId);
  1388. if (dragItems.size > 0 && (onDragStart || onNodeDragStart || !nodeId && onSelectionDragStart)) {
  1389. const [currentNode, currentNodes] = getEventHandlerParams({
  1390. nodeId,
  1391. dragItems,
  1392. nodeLookup
  1393. });
  1394. onDragStart?.(event.sourceEvent, dragItems, currentNode, currentNodes);
  1395. onNodeDragStart?.(event.sourceEvent, currentNode, currentNodes);
  1396. if (!nodeId) {
  1397. onSelectionDragStart?.(event.sourceEvent, currentNodes);
  1398. }
  1399. }
  1400. }
  1401. const d3DragInstance = d3Drag.drag().clickDistance(nodeClickDistance).on("start", (event) => {
  1402. const { domNode: domNode2, nodeDragThreshold, transform, snapGrid, snapToGrid } = getStoreItems();
  1403. containerBounds = domNode2?.getBoundingClientRect() || null;
  1404. abortDrag = false;
  1405. if (nodeDragThreshold === 0) {
  1406. startDrag(event);
  1407. }
  1408. const pointerPos = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid, containerBounds });
  1409. lastPos = pointerPos;
  1410. mousePosition = getEventPosition(event.sourceEvent, containerBounds);
  1411. }).on("drag", (event) => {
  1412. const { autoPanOnNodeDrag, transform, snapGrid, snapToGrid, nodeDragThreshold, nodeLookup } = getStoreItems();
  1413. const pointerPos = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid, containerBounds });
  1414. if (event.sourceEvent.type === "touchmove" && event.sourceEvent.touches.length > 1 || // if user deletes a node while dragging, we need to abort the drag to prevent errors
  1415. nodeId && !nodeLookup.has(nodeId)) {
  1416. abortDrag = true;
  1417. }
  1418. if (abortDrag) {
  1419. return;
  1420. }
  1421. if (!autoPanStarted && autoPanOnNodeDrag && dragStarted) {
  1422. autoPanStarted = true;
  1423. autoPan();
  1424. }
  1425. if (!dragStarted) {
  1426. const x = pointerPos.xSnapped - (lastPos.x ?? 0);
  1427. const y = pointerPos.ySnapped - (lastPos.y ?? 0);
  1428. const distance2 = Math.sqrt(x * x + y * y);
  1429. if (distance2 > nodeDragThreshold) {
  1430. startDrag(event);
  1431. }
  1432. }
  1433. if ((lastPos.x !== pointerPos.xSnapped || lastPos.y !== pointerPos.ySnapped) && dragItems && dragStarted) {
  1434. mousePosition = getEventPosition(event.sourceEvent, containerBounds);
  1435. updateNodes(pointerPos, event.sourceEvent);
  1436. }
  1437. }).on("end", (event) => {
  1438. if (!dragStarted || abortDrag) {
  1439. return;
  1440. }
  1441. autoPanStarted = false;
  1442. dragStarted = false;
  1443. cancelAnimationFrame(autoPanId);
  1444. if (dragItems.size > 0) {
  1445. const { nodeLookup, updateNodePositions, onNodeDragStop, onSelectionDragStop } = getStoreItems();
  1446. updateNodePositions(dragItems, false);
  1447. if (onDragStop || onNodeDragStop || !nodeId && onSelectionDragStop) {
  1448. const [currentNode, currentNodes] = getEventHandlerParams({
  1449. nodeId,
  1450. dragItems,
  1451. nodeLookup,
  1452. dragging: false
  1453. });
  1454. onDragStop?.(event.sourceEvent, dragItems, currentNode, currentNodes);
  1455. onNodeDragStop?.(event.sourceEvent, currentNode, currentNodes);
  1456. if (!nodeId) {
  1457. onSelectionDragStop?.(event.sourceEvent, currentNodes);
  1458. }
  1459. }
  1460. }
  1461. }).filter((event) => {
  1462. const target = event.target;
  1463. const isDraggable = !event.button && (!noDragClassName || !hasSelector(target, `.${noDragClassName}`, domNode)) && (!handleSelector || hasSelector(target, handleSelector, domNode));
  1464. return isDraggable;
  1465. });
  1466. d3Selection$1.call(d3DragInstance);
  1467. }
  1468. function destroy() {
  1469. d3Selection$1?.on(".drag", null);
  1470. }
  1471. return {
  1472. update,
  1473. destroy
  1474. };
  1475. }
  1476. function getNodesWithinDistance(position, nodeLookup, distance2) {
  1477. const nodes = [];
  1478. const rect = {
  1479. x: position.x - distance2,
  1480. y: position.y - distance2,
  1481. width: distance2 * 2,
  1482. height: distance2 * 2
  1483. };
  1484. for (const node of nodeLookup.values()) {
  1485. if (getOverlappingArea(rect, nodeToRect(node)) > 0) {
  1486. nodes.push(node);
  1487. }
  1488. }
  1489. return nodes;
  1490. }
  1491. var ADDITIONAL_DISTANCE = 250;
  1492. function getClosestHandle(position, connectionRadius, nodeLookup, fromHandle) {
  1493. let closestHandles = [];
  1494. let minDistance = Infinity;
  1495. const closeNodes = getNodesWithinDistance(position, nodeLookup, connectionRadius + ADDITIONAL_DISTANCE);
  1496. for (const node of closeNodes) {
  1497. const allHandles = [...node.internals.handleBounds?.source ?? [], ...node.internals.handleBounds?.target ?? []];
  1498. for (const handle of allHandles) {
  1499. if (fromHandle.nodeId === handle.nodeId && fromHandle.type === handle.type && fromHandle.id === handle.id) {
  1500. continue;
  1501. }
  1502. const { x, y } = getHandlePosition(node, handle, handle.position, true);
  1503. const distance2 = Math.sqrt(Math.pow(x - position.x, 2) + Math.pow(y - position.y, 2));
  1504. if (distance2 > connectionRadius) {
  1505. continue;
  1506. }
  1507. if (distance2 < minDistance) {
  1508. closestHandles = [{ ...handle, x, y }];
  1509. minDistance = distance2;
  1510. } else if (distance2 === minDistance) {
  1511. closestHandles.push({ ...handle, x, y });
  1512. }
  1513. }
  1514. }
  1515. if (!closestHandles.length) {
  1516. return null;
  1517. }
  1518. if (closestHandles.length > 1) {
  1519. const oppositeHandleType = fromHandle.type === "source" ? "target" : "source";
  1520. return closestHandles.find((handle) => handle.type === oppositeHandleType) ?? closestHandles[0];
  1521. }
  1522. return closestHandles[0];
  1523. }
  1524. function getHandle(nodeId, handleType, handleId, nodeLookup, connectionMode, withAbsolutePosition = false) {
  1525. const node = nodeLookup.get(nodeId);
  1526. if (!node) {
  1527. return null;
  1528. }
  1529. const handles = connectionMode === "strict" ? node.internals.handleBounds?.[handleType] : [...node.internals.handleBounds?.source ?? [], ...node.internals.handleBounds?.target ?? []];
  1530. const handle = (handleId ? handles?.find((h) => h.id === handleId) : handles?.[0]) ?? null;
  1531. return handle && withAbsolutePosition ? { ...handle, ...getHandlePosition(node, handle, handle.position, true) } : handle;
  1532. }
  1533. function getHandleType(edgeUpdaterType, handleDomNode) {
  1534. if (edgeUpdaterType) {
  1535. return edgeUpdaterType;
  1536. } else if (handleDomNode?.classList.contains("target")) {
  1537. return "target";
  1538. } else if (handleDomNode?.classList.contains("source")) {
  1539. return "source";
  1540. }
  1541. return null;
  1542. }
  1543. function isConnectionValid(isInsideConnectionRadius, isHandleValid) {
  1544. let isValid = null;
  1545. if (isHandleValid) {
  1546. isValid = true;
  1547. } else if (isInsideConnectionRadius && !isHandleValid) {
  1548. isValid = false;
  1549. }
  1550. return isValid;
  1551. }
  1552. var alwaysValid = () => true;
  1553. function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode, nodeLookup, lib, autoPanOnConnect, flowId, panBy: panBy2, cancelConnection, onConnectStart, onConnect, onConnectEnd, isValidConnection = alwaysValid, onReconnectEnd, updateConnection, getTransform, getFromHandle, autoPanSpeed }) {
  1554. const doc = getHostForElement(event.target);
  1555. let autoPanId = 0;
  1556. let closestHandle;
  1557. const { x, y } = getEventPosition(event);
  1558. const clickedHandle = doc?.elementFromPoint(x, y);
  1559. const handleType = getHandleType(edgeUpdaterType, clickedHandle);
  1560. const containerBounds = domNode?.getBoundingClientRect();
  1561. if (!containerBounds || !handleType) {
  1562. return;
  1563. }
  1564. const fromHandleInternal = getHandle(nodeId, handleType, handleId, nodeLookup, connectionMode);
  1565. if (!fromHandleInternal) {
  1566. return;
  1567. }
  1568. let position = getEventPosition(event, containerBounds);
  1569. let autoPanStarted = false;
  1570. let connection = null;
  1571. let isValid = false;
  1572. let handleDomNode = null;
  1573. function autoPan() {
  1574. if (!autoPanOnConnect || !containerBounds) {
  1575. return;
  1576. }
  1577. const [x2, y2] = calcAutoPan(position, containerBounds, autoPanSpeed);
  1578. panBy2({ x: x2, y: y2 });
  1579. autoPanId = requestAnimationFrame(autoPan);
  1580. }
  1581. const fromHandle = {
  1582. ...fromHandleInternal,
  1583. nodeId,
  1584. type: handleType,
  1585. position: fromHandleInternal.position
  1586. };
  1587. const fromNodeInternal = nodeLookup.get(nodeId);
  1588. const from = getHandlePosition(fromNodeInternal, fromHandle, exports.Position.Left, true);
  1589. const newConnection = {
  1590. inProgress: true,
  1591. isValid: null,
  1592. from,
  1593. fromHandle,
  1594. fromPosition: fromHandle.position,
  1595. fromNode: fromNodeInternal,
  1596. to: position,
  1597. toHandle: null,
  1598. toPosition: oppositePosition[fromHandle.position],
  1599. toNode: null
  1600. };
  1601. updateConnection(newConnection);
  1602. let previousConnection = newConnection;
  1603. onConnectStart?.(event, { nodeId, handleId, handleType });
  1604. function onPointerMove(event2) {
  1605. if (!getFromHandle() || !fromHandle) {
  1606. onPointerUp(event2);
  1607. return;
  1608. }
  1609. const transform = getTransform();
  1610. position = getEventPosition(event2, containerBounds);
  1611. closestHandle = getClosestHandle(pointToRendererPoint(position, transform, false, [1, 1]), connectionRadius, nodeLookup, fromHandle);
  1612. if (!autoPanStarted) {
  1613. autoPan();
  1614. autoPanStarted = true;
  1615. }
  1616. const result = isValidHandle(event2, {
  1617. handle: closestHandle,
  1618. connectionMode,
  1619. fromNodeId: nodeId,
  1620. fromHandleId: handleId,
  1621. fromType: isTarget ? "target" : "source",
  1622. isValidConnection,
  1623. doc,
  1624. lib,
  1625. flowId,
  1626. nodeLookup
  1627. });
  1628. handleDomNode = result.handleDomNode;
  1629. connection = result.connection;
  1630. isValid = isConnectionValid(!!closestHandle, result.isValid);
  1631. const newConnection2 = {
  1632. // from stays the same
  1633. ...previousConnection,
  1634. isValid,
  1635. to: closestHandle && isValid ? rendererPointToPoint({ x: closestHandle.x, y: closestHandle.y }, transform) : position,
  1636. toHandle: result.toHandle,
  1637. toPosition: isValid && result.toHandle ? result.toHandle.position : oppositePosition[fromHandle.position],
  1638. toNode: result.toHandle ? nodeLookup.get(result.toHandle.nodeId) : null
  1639. };
  1640. if (isValid && closestHandle && previousConnection.toHandle && newConnection2.toHandle && previousConnection.toHandle.type === newConnection2.toHandle.type && previousConnection.toHandle.nodeId === newConnection2.toHandle.nodeId && previousConnection.toHandle.id === newConnection2.toHandle.id && previousConnection.to.x === newConnection2.to.x && previousConnection.to.y === newConnection2.to.y) {
  1641. return;
  1642. }
  1643. updateConnection(newConnection2);
  1644. previousConnection = newConnection2;
  1645. }
  1646. function onPointerUp(event2) {
  1647. if ((closestHandle || handleDomNode) && connection && isValid) {
  1648. onConnect?.(connection);
  1649. }
  1650. const { inProgress, ...connectionState } = previousConnection;
  1651. const finalConnectionState = {
  1652. ...connectionState,
  1653. toPosition: previousConnection.toHandle ? previousConnection.toPosition : null
  1654. };
  1655. onConnectEnd?.(event2, finalConnectionState);
  1656. if (edgeUpdaterType) {
  1657. onReconnectEnd?.(event2, finalConnectionState);
  1658. }
  1659. cancelConnection();
  1660. cancelAnimationFrame(autoPanId);
  1661. autoPanStarted = false;
  1662. isValid = false;
  1663. connection = null;
  1664. handleDomNode = null;
  1665. doc.removeEventListener("mousemove", onPointerMove);
  1666. doc.removeEventListener("mouseup", onPointerUp);
  1667. doc.removeEventListener("touchmove", onPointerMove);
  1668. doc.removeEventListener("touchend", onPointerUp);
  1669. }
  1670. doc.addEventListener("mousemove", onPointerMove);
  1671. doc.addEventListener("mouseup", onPointerUp);
  1672. doc.addEventListener("touchmove", onPointerMove);
  1673. doc.addEventListener("touchend", onPointerUp);
  1674. }
  1675. function isValidHandle(event, { handle, connectionMode, fromNodeId, fromHandleId, fromType, doc, lib, flowId, isValidConnection = alwaysValid, nodeLookup }) {
  1676. const isTarget = fromType === "target";
  1677. const handleDomNode = handle ? doc.querySelector(`.${lib}-flow__handle[data-id="${flowId}-${handle?.nodeId}-${handle?.id}-${handle?.type}"]`) : null;
  1678. const { x, y } = getEventPosition(event);
  1679. const handleBelow = doc.elementFromPoint(x, y);
  1680. const handleToCheck = handleBelow?.classList.contains(`${lib}-flow__handle`) ? handleBelow : handleDomNode;
  1681. const result = {
  1682. handleDomNode: handleToCheck,
  1683. isValid: false,
  1684. connection: null,
  1685. toHandle: null
  1686. };
  1687. if (handleToCheck) {
  1688. const handleType = getHandleType(void 0, handleToCheck);
  1689. const handleNodeId = handleToCheck.getAttribute("data-nodeid");
  1690. const handleId = handleToCheck.getAttribute("data-handleid");
  1691. const connectable = handleToCheck.classList.contains("connectable");
  1692. const connectableEnd = handleToCheck.classList.contains("connectableend");
  1693. if (!handleNodeId || !handleType) {
  1694. return result;
  1695. }
  1696. const connection = {
  1697. source: isTarget ? handleNodeId : fromNodeId,
  1698. sourceHandle: isTarget ? handleId : fromHandleId,
  1699. target: isTarget ? fromNodeId : handleNodeId,
  1700. targetHandle: isTarget ? fromHandleId : handleId
  1701. };
  1702. result.connection = connection;
  1703. const isConnectable = connectable && connectableEnd;
  1704. const isValid = isConnectable && (connectionMode === exports.ConnectionMode.Strict ? isTarget && handleType === "source" || !isTarget && handleType === "target" : handleNodeId !== fromNodeId || handleId !== fromHandleId);
  1705. result.isValid = isValid && isValidConnection(connection);
  1706. result.toHandle = getHandle(handleNodeId, handleType, handleId, nodeLookup, connectionMode, false);
  1707. }
  1708. return result;
  1709. }
  1710. var XYHandle = {
  1711. onPointerDown,
  1712. isValid: isValidHandle
  1713. };
  1714. function XYMinimap({ domNode, panZoom, getTransform, getViewScale }) {
  1715. const selection = d3Selection.select(domNode);
  1716. function update({ translateExtent, width, height, zoomStep = 10, pannable = true, zoomable = true, inversePan = false }) {
  1717. const zoomHandler = (event) => {
  1718. const transform = getTransform();
  1719. if (event.sourceEvent.type !== "wheel" || !panZoom) {
  1720. return;
  1721. }
  1722. const pinchDelta = -event.sourceEvent.deltaY * (event.sourceEvent.deltaMode === 1 ? 0.05 : event.sourceEvent.deltaMode ? 1 : 2e-3) * zoomStep;
  1723. const nextZoom = transform[2] * Math.pow(2, pinchDelta);
  1724. panZoom.scaleTo(nextZoom);
  1725. };
  1726. let panStart = [0, 0];
  1727. const panStartHandler = (event) => {
  1728. if (event.sourceEvent.type === "mousedown" || event.sourceEvent.type === "touchstart") {
  1729. panStart = [
  1730. event.sourceEvent.clientX ?? event.sourceEvent.touches[0].clientX,
  1731. event.sourceEvent.clientY ?? event.sourceEvent.touches[0].clientY
  1732. ];
  1733. }
  1734. };
  1735. const panHandler = (event) => {
  1736. const transform = getTransform();
  1737. if (event.sourceEvent.type !== "mousemove" && event.sourceEvent.type !== "touchmove" || !panZoom) {
  1738. return;
  1739. }
  1740. const panCurrent = [
  1741. event.sourceEvent.clientX ?? event.sourceEvent.touches[0].clientX,
  1742. event.sourceEvent.clientY ?? event.sourceEvent.touches[0].clientY
  1743. ];
  1744. const panDelta = [panCurrent[0] - panStart[0], panCurrent[1] - panStart[1]];
  1745. panStart = panCurrent;
  1746. const moveScale = getViewScale() * Math.max(transform[2], Math.log(transform[2])) * (inversePan ? -1 : 1);
  1747. const position = {
  1748. x: transform[0] - panDelta[0] * moveScale,
  1749. y: transform[1] - panDelta[1] * moveScale
  1750. };
  1751. const extent = [
  1752. [0, 0],
  1753. [width, height]
  1754. ];
  1755. panZoom.setViewportConstrained({
  1756. x: position.x,
  1757. y: position.y,
  1758. zoom: transform[2]
  1759. }, extent, translateExtent);
  1760. };
  1761. const zoomAndPanHandler = d3Zoom.zoom().on("start", panStartHandler).on("zoom", pannable ? panHandler : null).on("zoom.wheel", zoomable ? zoomHandler : null);
  1762. selection.call(zoomAndPanHandler, {});
  1763. }
  1764. function destroy() {
  1765. selection.on("zoom", null);
  1766. }
  1767. return {
  1768. update,
  1769. destroy,
  1770. pointer: d3Selection.pointer
  1771. };
  1772. }
  1773. var viewChanged = (prevViewport, eventViewport) => prevViewport.x !== eventViewport.x || prevViewport.y !== eventViewport.y || prevViewport.zoom !== eventViewport.k;
  1774. var transformToViewport = (transform) => ({
  1775. x: transform.x,
  1776. y: transform.y,
  1777. zoom: transform.k
  1778. });
  1779. var viewportToTransform = ({ x, y, zoom: zoom2 }) => d3Zoom.zoomIdentity.translate(x, y).scale(zoom2);
  1780. var isWrappedWithClass = (event, className) => event.target.closest(`.${className}`);
  1781. var isRightClickPan = (panOnDrag, usedButton) => usedButton === 2 && Array.isArray(panOnDrag) && panOnDrag.includes(2);
  1782. var getD3Transition = (selection, duration = 0, onEnd = () => {
  1783. }) => {
  1784. const hasDuration = typeof duration === "number" && duration > 0;
  1785. if (!hasDuration) {
  1786. onEnd();
  1787. }
  1788. return hasDuration ? selection.transition().duration(duration).on("end", onEnd) : selection;
  1789. };
  1790. var wheelDelta = (event) => {
  1791. const factor = event.ctrlKey && isMacOs() ? 10 : 1;
  1792. return -event.deltaY * (event.deltaMode === 1 ? 0.05 : event.deltaMode ? 1 : 2e-3) * factor;
  1793. };
  1794. function createPanOnScrollHandler({ zoomPanValues, noWheelClassName, d3Selection: d3Selection$1, d3Zoom, panOnScrollMode, panOnScrollSpeed, zoomOnPinch, onPanZoomStart, onPanZoom, onPanZoomEnd }) {
  1795. return (event) => {
  1796. if (isWrappedWithClass(event, noWheelClassName)) {
  1797. return false;
  1798. }
  1799. event.preventDefault();
  1800. event.stopImmediatePropagation();
  1801. const currentZoom = d3Selection$1.property("__zoom").k || 1;
  1802. if (event.ctrlKey && zoomOnPinch) {
  1803. const point = d3Selection.pointer(event);
  1804. const pinchDelta = wheelDelta(event);
  1805. const zoom2 = currentZoom * Math.pow(2, pinchDelta);
  1806. d3Zoom.scaleTo(d3Selection$1, zoom2, point, event);
  1807. return;
  1808. }
  1809. const deltaNormalize = event.deltaMode === 1 ? 20 : 1;
  1810. let deltaX = panOnScrollMode === exports.PanOnScrollMode.Vertical ? 0 : event.deltaX * deltaNormalize;
  1811. let deltaY = panOnScrollMode === exports.PanOnScrollMode.Horizontal ? 0 : event.deltaY * deltaNormalize;
  1812. if (!isMacOs() && event.shiftKey && panOnScrollMode !== exports.PanOnScrollMode.Vertical) {
  1813. deltaX = event.deltaY * deltaNormalize;
  1814. deltaY = 0;
  1815. }
  1816. d3Zoom.translateBy(
  1817. d3Selection$1,
  1818. -(deltaX / currentZoom) * panOnScrollSpeed,
  1819. -(deltaY / currentZoom) * panOnScrollSpeed,
  1820. // @ts-ignore
  1821. { internal: true }
  1822. );
  1823. const nextViewport = transformToViewport(d3Selection$1.property("__zoom"));
  1824. clearTimeout(zoomPanValues.panScrollTimeout);
  1825. if (!zoomPanValues.isPanScrolling) {
  1826. zoomPanValues.isPanScrolling = true;
  1827. onPanZoomStart?.(event, nextViewport);
  1828. }
  1829. if (zoomPanValues.isPanScrolling) {
  1830. onPanZoom?.(event, nextViewport);
  1831. zoomPanValues.panScrollTimeout = setTimeout(() => {
  1832. onPanZoomEnd?.(event, nextViewport);
  1833. zoomPanValues.isPanScrolling = false;
  1834. }, 150);
  1835. }
  1836. };
  1837. }
  1838. function createZoomOnScrollHandler({ noWheelClassName, preventScrolling, d3ZoomHandler }) {
  1839. return function(event, d) {
  1840. const preventZoom = !preventScrolling && event.type === "wheel" && !event.ctrlKey;
  1841. if (preventZoom || isWrappedWithClass(event, noWheelClassName)) {
  1842. return null;
  1843. }
  1844. event.preventDefault();
  1845. d3ZoomHandler.call(this, event, d);
  1846. };
  1847. }
  1848. function createPanZoomStartHandler({ zoomPanValues, onDraggingChange, onPanZoomStart }) {
  1849. return (event) => {
  1850. if (event.sourceEvent?.internal) {
  1851. return;
  1852. }
  1853. const viewport = transformToViewport(event.transform);
  1854. zoomPanValues.mouseButton = event.sourceEvent?.button || 0;
  1855. zoomPanValues.isZoomingOrPanning = true;
  1856. zoomPanValues.prevViewport = viewport;
  1857. if (event.sourceEvent?.type === "mousedown") {
  1858. onDraggingChange(true);
  1859. }
  1860. if (onPanZoomStart) {
  1861. onPanZoomStart?.(event.sourceEvent, viewport);
  1862. }
  1863. };
  1864. }
  1865. function createPanZoomHandler({ zoomPanValues, panOnDrag, onPaneContextMenu, onTransformChange, onPanZoom }) {
  1866. return (event) => {
  1867. zoomPanValues.usedRightMouseButton = !!(onPaneContextMenu && isRightClickPan(panOnDrag, zoomPanValues.mouseButton ?? 0));
  1868. if (!event.sourceEvent?.sync) {
  1869. onTransformChange([event.transform.x, event.transform.y, event.transform.k]);
  1870. }
  1871. if (onPanZoom && !event.sourceEvent?.internal) {
  1872. onPanZoom?.(event.sourceEvent, transformToViewport(event.transform));
  1873. }
  1874. };
  1875. }
  1876. function createPanZoomEndHandler({ zoomPanValues, panOnDrag, panOnScroll, onDraggingChange, onPanZoomEnd, onPaneContextMenu }) {
  1877. return (event) => {
  1878. if (event.sourceEvent?.internal) {
  1879. return;
  1880. }
  1881. zoomPanValues.isZoomingOrPanning = false;
  1882. if (onPaneContextMenu && isRightClickPan(panOnDrag, zoomPanValues.mouseButton ?? 0) && !zoomPanValues.usedRightMouseButton && event.sourceEvent) {
  1883. onPaneContextMenu(event.sourceEvent);
  1884. }
  1885. zoomPanValues.usedRightMouseButton = false;
  1886. onDraggingChange(false);
  1887. if (onPanZoomEnd && viewChanged(zoomPanValues.prevViewport, event.transform)) {
  1888. const viewport = transformToViewport(event.transform);
  1889. zoomPanValues.prevViewport = viewport;
  1890. clearTimeout(zoomPanValues.timerId);
  1891. zoomPanValues.timerId = setTimeout(
  1892. () => {
  1893. onPanZoomEnd?.(event.sourceEvent, viewport);
  1894. },
  1895. // we need a setTimeout for panOnScroll to supress multiple end events fired during scroll
  1896. panOnScroll ? 150 : 0
  1897. );
  1898. }
  1899. };
  1900. }
  1901. function createFilter({ zoomActivationKeyPressed, zoomOnScroll, zoomOnPinch, panOnDrag, panOnScroll, zoomOnDoubleClick, userSelectionActive, noWheelClassName, noPanClassName, lib }) {
  1902. return (event) => {
  1903. const zoomScroll = zoomActivationKeyPressed || zoomOnScroll;
  1904. const pinchZoom = zoomOnPinch && event.ctrlKey;
  1905. if (event.button === 1 && event.type === "mousedown" && (isWrappedWithClass(event, `${lib}-flow__node`) || isWrappedWithClass(event, `${lib}-flow__edge`))) {
  1906. return true;
  1907. }
  1908. if (!panOnDrag && !zoomScroll && !panOnScroll && !zoomOnDoubleClick && !zoomOnPinch) {
  1909. return false;
  1910. }
  1911. if (userSelectionActive) {
  1912. return false;
  1913. }
  1914. if (isWrappedWithClass(event, noWheelClassName) && event.type === "wheel") {
  1915. return false;
  1916. }
  1917. if (isWrappedWithClass(event, noPanClassName) && (event.type !== "wheel" || panOnScroll && event.type === "wheel" && !zoomActivationKeyPressed)) {
  1918. return false;
  1919. }
  1920. if (!zoomOnPinch && event.ctrlKey && event.type === "wheel") {
  1921. return false;
  1922. }
  1923. if (!zoomOnPinch && event.type === "touchstart" && event.touches?.length > 1) {
  1924. event.preventDefault();
  1925. return false;
  1926. }
  1927. if (!zoomScroll && !panOnScroll && !pinchZoom && event.type === "wheel") {
  1928. return false;
  1929. }
  1930. if (!panOnDrag && (event.type === "mousedown" || event.type === "touchstart")) {
  1931. return false;
  1932. }
  1933. if (Array.isArray(panOnDrag) && !panOnDrag.includes(event.button) && event.type === "mousedown") {
  1934. return false;
  1935. }
  1936. const buttonAllowed = Array.isArray(panOnDrag) && panOnDrag.includes(event.button) || !event.button || event.button <= 1;
  1937. return (!event.ctrlKey || event.type === "wheel") && buttonAllowed;
  1938. };
  1939. }
  1940. function XYPanZoom({ domNode, minZoom, maxZoom, paneClickDistance, translateExtent, viewport, onPanZoom, onPanZoomStart, onPanZoomEnd, onDraggingChange }) {
  1941. const zoomPanValues = {
  1942. isZoomingOrPanning: false,
  1943. usedRightMouseButton: false,
  1944. prevViewport: { x: 0, y: 0, zoom: 0 },
  1945. mouseButton: 0,
  1946. timerId: void 0,
  1947. panScrollTimeout: void 0,
  1948. isPanScrolling: false
  1949. };
  1950. const bbox = domNode.getBoundingClientRect();
  1951. const d3ZoomInstance = d3Zoom.zoom().clickDistance(!isNumeric(paneClickDistance) || paneClickDistance < 0 ? 0 : paneClickDistance).scaleExtent([minZoom, maxZoom]).translateExtent(translateExtent);
  1952. const d3Selection$1 = d3Selection.select(domNode).call(d3ZoomInstance);
  1953. setViewportConstrained({
  1954. x: viewport.x,
  1955. y: viewport.y,
  1956. zoom: clamp(viewport.zoom, minZoom, maxZoom)
  1957. }, [
  1958. [0, 0],
  1959. [bbox.width, bbox.height]
  1960. ], translateExtent);
  1961. const d3ZoomHandler = d3Selection$1.on("wheel.zoom");
  1962. const d3DblClickZoomHandler = d3Selection$1.on("dblclick.zoom");
  1963. d3ZoomInstance.wheelDelta(wheelDelta);
  1964. function setTransform(transform, options) {
  1965. if (d3Selection$1) {
  1966. return new Promise((resolve) => {
  1967. d3ZoomInstance?.transform(getD3Transition(d3Selection$1, options?.duration, () => resolve(true)), transform);
  1968. });
  1969. }
  1970. return Promise.resolve(false);
  1971. }
  1972. function update({ noWheelClassName, noPanClassName, onPaneContextMenu, userSelectionActive, panOnScroll, panOnDrag, panOnScrollMode, panOnScrollSpeed, preventScrolling, zoomOnPinch, zoomOnScroll, zoomOnDoubleClick, zoomActivationKeyPressed, lib, onTransformChange }) {
  1973. if (userSelectionActive && !zoomPanValues.isZoomingOrPanning) {
  1974. destroy();
  1975. }
  1976. const isPanOnScroll = panOnScroll && !zoomActivationKeyPressed && !userSelectionActive;
  1977. const wheelHandler = isPanOnScroll ? createPanOnScrollHandler({
  1978. zoomPanValues,
  1979. noWheelClassName,
  1980. d3Selection: d3Selection$1,
  1981. d3Zoom: d3ZoomInstance,
  1982. panOnScrollMode,
  1983. panOnScrollSpeed,
  1984. zoomOnPinch,
  1985. onPanZoomStart,
  1986. onPanZoom,
  1987. onPanZoomEnd
  1988. }) : createZoomOnScrollHandler({
  1989. noWheelClassName,
  1990. preventScrolling,
  1991. d3ZoomHandler
  1992. });
  1993. d3Selection$1.on("wheel.zoom", wheelHandler, { passive: false });
  1994. if (!userSelectionActive) {
  1995. const startHandler = createPanZoomStartHandler({
  1996. zoomPanValues,
  1997. onDraggingChange,
  1998. onPanZoomStart
  1999. });
  2000. d3ZoomInstance.on("start", startHandler);
  2001. const panZoomHandler = createPanZoomHandler({
  2002. zoomPanValues,
  2003. panOnDrag,
  2004. onPaneContextMenu: !!onPaneContextMenu,
  2005. onPanZoom,
  2006. onTransformChange
  2007. });
  2008. d3ZoomInstance.on("zoom", panZoomHandler);
  2009. const panZoomEndHandler = createPanZoomEndHandler({
  2010. zoomPanValues,
  2011. panOnDrag,
  2012. panOnScroll,
  2013. onPaneContextMenu,
  2014. onPanZoomEnd,
  2015. onDraggingChange
  2016. });
  2017. d3ZoomInstance.on("end", panZoomEndHandler);
  2018. }
  2019. const filter = createFilter({
  2020. zoomActivationKeyPressed,
  2021. panOnDrag,
  2022. zoomOnScroll,
  2023. panOnScroll,
  2024. zoomOnDoubleClick,
  2025. zoomOnPinch,
  2026. userSelectionActive,
  2027. noPanClassName,
  2028. noWheelClassName,
  2029. lib
  2030. });
  2031. d3ZoomInstance.filter(filter);
  2032. if (zoomOnDoubleClick) {
  2033. d3Selection$1.on("dblclick.zoom", d3DblClickZoomHandler);
  2034. } else {
  2035. d3Selection$1.on("dblclick.zoom", null);
  2036. }
  2037. }
  2038. function destroy() {
  2039. d3ZoomInstance.on("zoom", null);
  2040. }
  2041. async function setViewportConstrained(viewport2, extent, translateExtent2) {
  2042. const nextTransform = viewportToTransform(viewport2);
  2043. const contrainedTransform = d3ZoomInstance?.constrain()(nextTransform, extent, translateExtent2);
  2044. if (contrainedTransform) {
  2045. await setTransform(contrainedTransform);
  2046. }
  2047. return new Promise((resolve) => resolve(contrainedTransform));
  2048. }
  2049. async function setViewport(viewport2, options) {
  2050. const nextTransform = viewportToTransform(viewport2);
  2051. await setTransform(nextTransform, options);
  2052. return new Promise((resolve) => resolve(nextTransform));
  2053. }
  2054. function syncViewport(viewport2) {
  2055. if (d3Selection$1) {
  2056. const nextTransform = viewportToTransform(viewport2);
  2057. const currentTransform = d3Selection$1.property("__zoom");
  2058. if (currentTransform.k !== viewport2.zoom || currentTransform.x !== viewport2.x || currentTransform.y !== viewport2.y) {
  2059. d3ZoomInstance?.transform(d3Selection$1, nextTransform, null, { sync: true });
  2060. }
  2061. }
  2062. }
  2063. function getViewport() {
  2064. const transform = d3Selection$1 ? d3Zoom.zoomTransform(d3Selection$1.node()) : { x: 0, y: 0, k: 1 };
  2065. return { x: transform.x, y: transform.y, zoom: transform.k };
  2066. }
  2067. function scaleTo(zoom2, options) {
  2068. if (d3Selection$1) {
  2069. return new Promise((resolve) => {
  2070. d3ZoomInstance?.scaleTo(getD3Transition(d3Selection$1, options?.duration, () => resolve(true)), zoom2);
  2071. });
  2072. }
  2073. return Promise.resolve(false);
  2074. }
  2075. function scaleBy(factor, options) {
  2076. if (d3Selection$1) {
  2077. return new Promise((resolve) => {
  2078. d3ZoomInstance?.scaleBy(getD3Transition(d3Selection$1, options?.duration, () => resolve(true)), factor);
  2079. });
  2080. }
  2081. return Promise.resolve(false);
  2082. }
  2083. function setScaleExtent(scaleExtent) {
  2084. d3ZoomInstance?.scaleExtent(scaleExtent);
  2085. }
  2086. function setTranslateExtent(translateExtent2) {
  2087. d3ZoomInstance?.translateExtent(translateExtent2);
  2088. }
  2089. function setClickDistance(distance2) {
  2090. const validDistance = !isNumeric(distance2) || distance2 < 0 ? 0 : distance2;
  2091. d3ZoomInstance?.clickDistance(validDistance);
  2092. }
  2093. return {
  2094. update,
  2095. destroy,
  2096. setViewport,
  2097. setViewportConstrained,
  2098. getViewport,
  2099. scaleTo,
  2100. scaleBy,
  2101. setScaleExtent,
  2102. setTranslateExtent,
  2103. syncViewport,
  2104. setClickDistance
  2105. };
  2106. }
  2107. exports.ResizeControlVariant = void 0;
  2108. (function(ResizeControlVariant2) {
  2109. ResizeControlVariant2["Line"] = "line";
  2110. ResizeControlVariant2["Handle"] = "handle";
  2111. })(exports.ResizeControlVariant || (exports.ResizeControlVariant = {}));
  2112. var XY_RESIZER_HANDLE_POSITIONS = ["top-left", "top-right", "bottom-left", "bottom-right"];
  2113. var XY_RESIZER_LINE_POSITIONS = ["top", "right", "bottom", "left"];
  2114. function getResizeDirection({ width, prevWidth, height, prevHeight, affectsX, affectsY }) {
  2115. const deltaWidth = width - prevWidth;
  2116. const deltaHeight = height - prevHeight;
  2117. const direction = [deltaWidth > 0 ? 1 : deltaWidth < 0 ? -1 : 0, deltaHeight > 0 ? 1 : deltaHeight < 0 ? -1 : 0];
  2118. if (deltaWidth && affectsX) {
  2119. direction[0] = direction[0] * -1;
  2120. }
  2121. if (deltaHeight && affectsY) {
  2122. direction[1] = direction[1] * -1;
  2123. }
  2124. return direction;
  2125. }
  2126. function getControlDirection(controlPosition) {
  2127. const isHorizontal = controlPosition.includes("right") || controlPosition.includes("left");
  2128. const isVertical = controlPosition.includes("bottom") || controlPosition.includes("top");
  2129. const affectsX = controlPosition.includes("left");
  2130. const affectsY = controlPosition.includes("top");
  2131. return {
  2132. isHorizontal,
  2133. isVertical,
  2134. affectsX,
  2135. affectsY
  2136. };
  2137. }
  2138. function getLowerExtentClamp(lowerExtent, lowerBound) {
  2139. return Math.max(0, lowerBound - lowerExtent);
  2140. }
  2141. function getUpperExtentClamp(upperExtent, upperBound) {
  2142. return Math.max(0, upperExtent - upperBound);
  2143. }
  2144. function getSizeClamp(size, minSize, maxSize) {
  2145. return Math.max(0, minSize - size, size - maxSize);
  2146. }
  2147. function xor(a, b) {
  2148. return a ? !b : b;
  2149. }
  2150. function getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio, nodeOrigin, extent, childExtent) {
  2151. let { affectsX, affectsY } = controlDirection;
  2152. const { isHorizontal, isVertical } = controlDirection;
  2153. const isDiagonal = isHorizontal && isVertical;
  2154. const { xSnapped, ySnapped } = pointerPosition;
  2155. const { minWidth, maxWidth, minHeight, maxHeight } = boundaries;
  2156. const { x: startX, y: startY, width: startWidth, height: startHeight, aspectRatio } = startValues;
  2157. let distX = Math.floor(isHorizontal ? xSnapped - startValues.pointerX : 0);
  2158. let distY = Math.floor(isVertical ? ySnapped - startValues.pointerY : 0);
  2159. const newWidth = startWidth + (affectsX ? -distX : distX);
  2160. const newHeight = startHeight + (affectsY ? -distY : distY);
  2161. const originOffsetX = -nodeOrigin[0] * startWidth;
  2162. const originOffsetY = -nodeOrigin[1] * startHeight;
  2163. let clampX = getSizeClamp(newWidth, minWidth, maxWidth);
  2164. let clampY = getSizeClamp(newHeight, minHeight, maxHeight);
  2165. if (extent) {
  2166. let xExtentClamp = 0;
  2167. let yExtentClamp = 0;
  2168. if (affectsX && distX < 0) {
  2169. xExtentClamp = getLowerExtentClamp(startX + distX + originOffsetX, extent[0][0]);
  2170. } else if (!affectsX && distX > 0) {
  2171. xExtentClamp = getUpperExtentClamp(startX + newWidth + originOffsetX, extent[1][0]);
  2172. }
  2173. if (affectsY && distY < 0) {
  2174. yExtentClamp = getLowerExtentClamp(startY + distY + originOffsetY, extent[0][1]);
  2175. } else if (!affectsY && distY > 0) {
  2176. yExtentClamp = getUpperExtentClamp(startY + newHeight + originOffsetY, extent[1][1]);
  2177. }
  2178. clampX = Math.max(clampX, xExtentClamp);
  2179. clampY = Math.max(clampY, yExtentClamp);
  2180. }
  2181. if (childExtent) {
  2182. let xExtentClamp = 0;
  2183. let yExtentClamp = 0;
  2184. if (affectsX && distX > 0) {
  2185. xExtentClamp = getUpperExtentClamp(startX + distX, childExtent[0][0]);
  2186. } else if (!affectsX && distX < 0) {
  2187. xExtentClamp = getLowerExtentClamp(startX + newWidth, childExtent[1][0]);
  2188. }
  2189. if (affectsY && distY > 0) {
  2190. yExtentClamp = getUpperExtentClamp(startY + distY, childExtent[0][1]);
  2191. } else if (!affectsY && distY < 0) {
  2192. yExtentClamp = getLowerExtentClamp(startY + newHeight, childExtent[1][1]);
  2193. }
  2194. clampX = Math.max(clampX, xExtentClamp);
  2195. clampY = Math.max(clampY, yExtentClamp);
  2196. }
  2197. if (keepAspectRatio) {
  2198. if (isHorizontal) {
  2199. const aspectHeightClamp = getSizeClamp(newWidth / aspectRatio, minHeight, maxHeight) * aspectRatio;
  2200. clampX = Math.max(clampX, aspectHeightClamp);
  2201. if (extent) {
  2202. let aspectExtentClamp = 0;
  2203. if (!affectsX && !affectsY || affectsX && !affectsY && isDiagonal) {
  2204. aspectExtentClamp = getUpperExtentClamp(startY + originOffsetY + newWidth / aspectRatio, extent[1][1]) * aspectRatio;
  2205. } else {
  2206. aspectExtentClamp = getLowerExtentClamp(startY + originOffsetY + (affectsX ? distX : -distX) / aspectRatio, extent[0][1]) * aspectRatio;
  2207. }
  2208. clampX = Math.max(clampX, aspectExtentClamp);
  2209. }
  2210. if (childExtent) {
  2211. let aspectExtentClamp = 0;
  2212. if (!affectsX && !affectsY || affectsX && !affectsY && isDiagonal) {
  2213. aspectExtentClamp = getLowerExtentClamp(startY + newWidth / aspectRatio, childExtent[1][1]) * aspectRatio;
  2214. } else {
  2215. aspectExtentClamp = getUpperExtentClamp(startY + (affectsX ? distX : -distX) / aspectRatio, childExtent[0][1]) * aspectRatio;
  2216. }
  2217. clampX = Math.max(clampX, aspectExtentClamp);
  2218. }
  2219. }
  2220. if (isVertical) {
  2221. const aspectWidthClamp = getSizeClamp(newHeight * aspectRatio, minWidth, maxWidth) / aspectRatio;
  2222. clampY = Math.max(clampY, aspectWidthClamp);
  2223. if (extent) {
  2224. let aspectExtentClamp = 0;
  2225. if (!affectsX && !affectsY || affectsY && !affectsX && isDiagonal) {
  2226. aspectExtentClamp = getUpperExtentClamp(startX + newHeight * aspectRatio + originOffsetX, extent[1][0]) / aspectRatio;
  2227. } else {
  2228. aspectExtentClamp = getLowerExtentClamp(startX + (affectsY ? distY : -distY) * aspectRatio + originOffsetX, extent[0][0]) / aspectRatio;
  2229. }
  2230. clampY = Math.max(clampY, aspectExtentClamp);
  2231. }
  2232. if (childExtent) {
  2233. let aspectExtentClamp = 0;
  2234. if (!affectsX && !affectsY || affectsY && !affectsX && isDiagonal) {
  2235. aspectExtentClamp = getLowerExtentClamp(startX + newHeight * aspectRatio, childExtent[1][0]) / aspectRatio;
  2236. } else {
  2237. aspectExtentClamp = getUpperExtentClamp(startX + (affectsY ? distY : -distY) * aspectRatio, childExtent[0][0]) / aspectRatio;
  2238. }
  2239. clampY = Math.max(clampY, aspectExtentClamp);
  2240. }
  2241. }
  2242. }
  2243. distY = distY + (distY < 0 ? clampY : -clampY);
  2244. distX = distX + (distX < 0 ? clampX : -clampX);
  2245. if (keepAspectRatio) {
  2246. if (isDiagonal) {
  2247. if (newWidth > newHeight * aspectRatio) {
  2248. distY = (xor(affectsX, affectsY) ? -distX : distX) / aspectRatio;
  2249. } else {
  2250. distX = (xor(affectsX, affectsY) ? -distY : distY) * aspectRatio;
  2251. }
  2252. } else {
  2253. if (isHorizontal) {
  2254. distY = distX / aspectRatio;
  2255. affectsY = affectsX;
  2256. } else {
  2257. distX = distY * aspectRatio;
  2258. affectsX = affectsY;
  2259. }
  2260. }
  2261. }
  2262. const x = affectsX ? startX + distX : startX;
  2263. const y = affectsY ? startY + distY : startY;
  2264. return {
  2265. width: startWidth + (affectsX ? -distX : distX),
  2266. height: startHeight + (affectsY ? -distY : distY),
  2267. x: nodeOrigin[0] * distX * (!affectsX ? 1 : -1) + x,
  2268. y: nodeOrigin[1] * distY * (!affectsY ? 1 : -1) + y
  2269. };
  2270. }
  2271. var initPrevValues = { width: 0, height: 0, x: 0, y: 0 };
  2272. var initStartValues = {
  2273. ...initPrevValues,
  2274. pointerX: 0,
  2275. pointerY: 0,
  2276. aspectRatio: 1
  2277. };
  2278. function nodeToParentExtent(node) {
  2279. return [
  2280. [0, 0],
  2281. [node.measured.width, node.measured.height]
  2282. ];
  2283. }
  2284. function nodeToChildExtent(child, parent, nodeOrigin) {
  2285. const x = parent.position.x + child.position.x;
  2286. const y = parent.position.y + child.position.y;
  2287. const width = child.measured.width ?? 0;
  2288. const height = child.measured.height ?? 0;
  2289. const originOffsetX = nodeOrigin[0] * width;
  2290. const originOffsetY = nodeOrigin[1] * height;
  2291. return [
  2292. [x - originOffsetX, y - originOffsetY],
  2293. [x + width - originOffsetX, y + height - originOffsetY]
  2294. ];
  2295. }
  2296. function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
  2297. const selection = d3Selection.select(domNode);
  2298. function update({ controlPosition, boundaries, keepAspectRatio, onResizeStart, onResize, onResizeEnd, shouldResize }) {
  2299. let prevValues = { ...initPrevValues };
  2300. let startValues = { ...initStartValues };
  2301. const controlDirection = getControlDirection(controlPosition);
  2302. let node = void 0;
  2303. let containerBounds = null;
  2304. let childNodes = [];
  2305. let parentNode = void 0;
  2306. let parentExtent = void 0;
  2307. let childExtent = void 0;
  2308. const dragHandler = d3Drag.drag().on("start", (event) => {
  2309. const { nodeLookup, transform, snapGrid, snapToGrid, nodeOrigin, paneDomNode } = getStoreItems();
  2310. node = nodeLookup.get(nodeId);
  2311. if (!node) {
  2312. return;
  2313. }
  2314. containerBounds = paneDomNode?.getBoundingClientRect() ?? null;
  2315. const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, {
  2316. transform,
  2317. snapGrid,
  2318. snapToGrid,
  2319. containerBounds
  2320. });
  2321. prevValues = {
  2322. width: node.measured.width ?? 0,
  2323. height: node.measured.height ?? 0,
  2324. x: node.position.x ?? 0,
  2325. y: node.position.y ?? 0
  2326. };
  2327. startValues = {
  2328. ...prevValues,
  2329. pointerX: xSnapped,
  2330. pointerY: ySnapped,
  2331. aspectRatio: prevValues.width / prevValues.height
  2332. };
  2333. parentNode = void 0;
  2334. if (node.parentId && (node.extent === "parent" || node.expandParent)) {
  2335. parentNode = nodeLookup.get(node.parentId);
  2336. parentExtent = parentNode && node.extent === "parent" ? nodeToParentExtent(parentNode) : void 0;
  2337. }
  2338. childNodes = [];
  2339. childExtent = void 0;
  2340. for (const [childId, child] of nodeLookup) {
  2341. if (child.parentId === nodeId) {
  2342. childNodes.push({
  2343. id: childId,
  2344. position: { ...child.position },
  2345. extent: child.extent
  2346. });
  2347. if (child.extent === "parent" || child.expandParent) {
  2348. const extent = nodeToChildExtent(child, node, child.origin ?? nodeOrigin);
  2349. if (childExtent) {
  2350. childExtent = [
  2351. [Math.min(extent[0][0], childExtent[0][0]), Math.min(extent[0][1], childExtent[0][1])],
  2352. [Math.max(extent[1][0], childExtent[1][0]), Math.max(extent[1][1], childExtent[1][1])]
  2353. ];
  2354. } else {
  2355. childExtent = extent;
  2356. }
  2357. }
  2358. }
  2359. }
  2360. onResizeStart?.(event, { ...prevValues });
  2361. }).on("drag", (event) => {
  2362. const { transform, snapGrid, snapToGrid, nodeOrigin: storeNodeOrigin } = getStoreItems();
  2363. const pointerPosition = getPointerPosition(event.sourceEvent, {
  2364. transform,
  2365. snapGrid,
  2366. snapToGrid,
  2367. containerBounds
  2368. });
  2369. const childChanges = [];
  2370. if (!node) {
  2371. return;
  2372. }
  2373. const { x: prevX, y: prevY, width: prevWidth, height: prevHeight } = prevValues;
  2374. const change = {};
  2375. const nodeOrigin = node.origin ?? storeNodeOrigin;
  2376. const { width, height, x, y } = getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio, nodeOrigin, parentExtent, childExtent);
  2377. const isWidthChange = width !== prevWidth;
  2378. const isHeightChange = height !== prevHeight;
  2379. const isXPosChange = x !== prevX && isWidthChange;
  2380. const isYPosChange = y !== prevY && isHeightChange;
  2381. if (!isXPosChange && !isYPosChange && !isWidthChange && !isHeightChange) {
  2382. return;
  2383. }
  2384. if (isXPosChange || isYPosChange || nodeOrigin[0] === 1 || nodeOrigin[1] === 1) {
  2385. change.x = isXPosChange ? x : prevValues.x;
  2386. change.y = isYPosChange ? y : prevValues.y;
  2387. prevValues.x = change.x;
  2388. prevValues.y = change.y;
  2389. if (childNodes.length > 0) {
  2390. const xChange = x - prevX;
  2391. const yChange = y - prevY;
  2392. for (const childNode of childNodes) {
  2393. childNode.position = {
  2394. x: childNode.position.x - xChange + nodeOrigin[0] * (width - prevWidth),
  2395. y: childNode.position.y - yChange + nodeOrigin[1] * (height - prevHeight)
  2396. };
  2397. childChanges.push(childNode);
  2398. }
  2399. }
  2400. }
  2401. if (isWidthChange || isHeightChange) {
  2402. change.width = isWidthChange ? width : prevValues.width;
  2403. change.height = isHeightChange ? height : prevValues.height;
  2404. prevValues.width = change.width;
  2405. prevValues.height = change.height;
  2406. }
  2407. if (parentNode && node.expandParent) {
  2408. const xLimit = nodeOrigin[0] * (change.width ?? 0);
  2409. if (change.x && change.x < xLimit) {
  2410. prevValues.x = xLimit;
  2411. startValues.x = startValues.x - (change.x - xLimit);
  2412. }
  2413. const yLimit = nodeOrigin[1] * (change.height ?? 0);
  2414. if (change.y && change.y < yLimit) {
  2415. prevValues.y = yLimit;
  2416. startValues.y = startValues.y - (change.y - yLimit);
  2417. }
  2418. }
  2419. const direction = getResizeDirection({
  2420. width: prevValues.width,
  2421. prevWidth,
  2422. height: prevValues.height,
  2423. prevHeight,
  2424. affectsX: controlDirection.affectsX,
  2425. affectsY: controlDirection.affectsY
  2426. });
  2427. const nextValues = { ...prevValues, direction };
  2428. const callResize = shouldResize?.(event, nextValues);
  2429. if (callResize === false) {
  2430. return;
  2431. }
  2432. onResize?.(event, nextValues);
  2433. onChange(change, childChanges);
  2434. }).on("end", (event) => {
  2435. onResizeEnd?.(event, { ...prevValues });
  2436. onEnd?.();
  2437. });
  2438. selection.call(dragHandler);
  2439. }
  2440. function destroy() {
  2441. selection.on(".drag", null);
  2442. }
  2443. return {
  2444. update,
  2445. destroy
  2446. };
  2447. }
  2448. exports.XYDrag = XYDrag;
  2449. exports.XYHandle = XYHandle;
  2450. exports.XYMinimap = XYMinimap;
  2451. exports.XYPanZoom = XYPanZoom;
  2452. exports.XYResizer = XYResizer;
  2453. exports.XY_RESIZER_HANDLE_POSITIONS = XY_RESIZER_HANDLE_POSITIONS;
  2454. exports.XY_RESIZER_LINE_POSITIONS = XY_RESIZER_LINE_POSITIONS;
  2455. exports.addEdge = addEdge;
  2456. exports.adoptUserNodes = adoptUserNodes;
  2457. exports.areConnectionMapsEqual = areConnectionMapsEqual;
  2458. exports.boxToRect = boxToRect;
  2459. exports.calcAutoPan = calcAutoPan;
  2460. exports.calculateNodePosition = calculateNodePosition;
  2461. exports.clamp = clamp;
  2462. exports.clampPosition = clampPosition;
  2463. exports.clampPositionToParent = clampPositionToParent;
  2464. exports.createMarkerIds = createMarkerIds;
  2465. exports.devWarn = devWarn;
  2466. exports.elementSelectionKeys = elementSelectionKeys;
  2467. exports.errorMessages = errorMessages;
  2468. exports.evaluateAbsolutePosition = evaluateAbsolutePosition;
  2469. exports.fitView = fitView;
  2470. exports.getBezierEdgeCenter = getBezierEdgeCenter;
  2471. exports.getBezierPath = getBezierPath;
  2472. exports.getBoundsOfBoxes = getBoundsOfBoxes;
  2473. exports.getBoundsOfRects = getBoundsOfRects;
  2474. exports.getConnectedEdges = getConnectedEdges;
  2475. exports.getConnectionStatus = getConnectionStatus;
  2476. exports.getDimensions = getDimensions;
  2477. exports.getEdgeCenter = getEdgeCenter;
  2478. exports.getEdgePosition = getEdgePosition;
  2479. exports.getElementsToRemove = getElementsToRemove;
  2480. exports.getElevatedEdgeZIndex = getElevatedEdgeZIndex;
  2481. exports.getEventPosition = getEventPosition;
  2482. exports.getFitViewNodes = getFitViewNodes;
  2483. exports.getHandleBounds = getHandleBounds;
  2484. exports.getHandlePosition = getHandlePosition;
  2485. exports.getHostForElement = getHostForElement;
  2486. exports.getIncomers = getIncomers;
  2487. exports.getInternalNodesBounds = getInternalNodesBounds;
  2488. exports.getMarkerId = getMarkerId;
  2489. exports.getNodeDimensions = getNodeDimensions;
  2490. exports.getNodePositionWithOrigin = getNodePositionWithOrigin;
  2491. exports.getNodeToolbarTransform = getNodeToolbarTransform;
  2492. exports.getNodesBounds = getNodesBounds;
  2493. exports.getNodesInside = getNodesInside;
  2494. exports.getOutgoers = getOutgoers;
  2495. exports.getOverlappingArea = getOverlappingArea;
  2496. exports.getPointerPosition = getPointerPosition;
  2497. exports.getSmoothStepPath = getSmoothStepPath;
  2498. exports.getStraightPath = getStraightPath;
  2499. exports.getViewportForBounds = getViewportForBounds;
  2500. exports.handleConnectionChange = handleConnectionChange;
  2501. exports.handleExpandParent = handleExpandParent;
  2502. exports.infiniteExtent = infiniteExtent;
  2503. exports.initialConnection = initialConnection;
  2504. exports.isCoordinateExtent = isCoordinateExtent;
  2505. exports.isEdgeBase = isEdgeBase;
  2506. exports.isEdgeVisible = isEdgeVisible;
  2507. exports.isInputDOMNode = isInputDOMNode;
  2508. exports.isInternalNodeBase = isInternalNodeBase;
  2509. exports.isMacOs = isMacOs;
  2510. exports.isMouseEvent = isMouseEvent;
  2511. exports.isNodeBase = isNodeBase;
  2512. exports.isNumeric = isNumeric;
  2513. exports.isRectObject = isRectObject;
  2514. exports.nodeHasDimensions = nodeHasDimensions;
  2515. exports.nodeToBox = nodeToBox;
  2516. exports.nodeToRect = nodeToRect;
  2517. exports.oppositePosition = oppositePosition;
  2518. exports.panBy = panBy;
  2519. exports.pointToRendererPoint = pointToRendererPoint;
  2520. exports.reconnectEdge = reconnectEdge;
  2521. exports.rectToBox = rectToBox;
  2522. exports.rendererPointToPoint = rendererPointToPoint;
  2523. exports.shallowNodeData = shallowNodeData;
  2524. exports.snapPosition = snapPosition;
  2525. exports.updateAbsolutePositions = updateAbsolutePositions;
  2526. exports.updateConnectionLookup = updateConnectionLookup;
  2527. exports.updateNodeInternals = updateNodeInternals;
  2528. }));

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址