@likec4/diagram 1.2.2 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/LikeC4Diagram.d.ts +1 -1
  2. package/dist/LikeC4Diagram.props.d.ts +27 -4
  3. package/dist/index.mjs +1543 -1346
  4. package/dist/state/DiagramContext.d.ts +2353 -264
  5. package/dist/state/diagramStore.d.ts +2360 -268
  6. package/dist/state/index.d.ts +0 -1
  7. package/dist/state/useDiagramStore.d.ts +3 -2534
  8. package/dist/state/useNavigationHistory.d.ts +5 -0
  9. package/dist/style.css +194 -131
  10. package/dist/theme.css.d.ts +5 -1
  11. package/dist/ui/BackwardForwardPanel.css.d.ts +1 -0
  12. package/dist/ui/BackwardForwardPanel.d.ts +1 -0
  13. package/dist/ui/DiagramTitlePanel.css.d.ts +1 -1
  14. package/dist/xyflow/XYFlow.d.ts +2 -1
  15. package/dist/xyflow/XYFlowEvents.d.ts +4 -4
  16. package/dist/xyflow/XYFlowInner.d.ts +2 -1
  17. package/dist/xyflow/const.d.ts +1 -1
  18. package/dist/xyflow/diagram-to-xyflow.d.ts +1 -1
  19. package/dist/xyflow/edges/RelationshipEdge.d.ts +4 -5
  20. package/dist/xyflow/edges/utils.d.ts +4 -2
  21. package/dist/xyflow/hooks/useXYFlow.d.ts +9 -9
  22. package/dist/xyflow/nodes/compound/CompoundNode.css.d.ts +3 -1
  23. package/dist/xyflow/nodes/element/ElementNode.d.ts +1 -1
  24. package/dist/xyflow/nodes/element/element.css.d.ts +1 -0
  25. package/dist/xyflow/nodes/element/index.d.ts +1 -1
  26. package/dist/xyflow/types.d.ts +3 -3
  27. package/dist/xyflow/utils.d.ts +3 -0
  28. package/package.json +18 -17
  29. package/src/LikeC4Diagram.css.ts +15 -5
  30. package/src/LikeC4Diagram.props.ts +33 -5
  31. package/src/LikeC4Diagram.tsx +103 -32
  32. package/src/globals.css.ts +1 -2
  33. package/src/mantine/theme.ts +1 -0
  34. package/src/state/DiagramContext.tsx +3 -4
  35. package/src/state/diagramStore.ts +177 -103
  36. package/src/state/index.ts +0 -1
  37. package/src/state/useDiagramStore.ts +6 -13
  38. package/src/state/useNavigationHistory.ts +39 -0
  39. package/src/theme.css.ts +5 -1
  40. package/src/ui/BackwardForwardPanel.css.ts +22 -0
  41. package/src/ui/BackwardForwardPanel.tsx +59 -0
  42. package/src/ui/DiagramTitlePanel.css.ts +11 -5
  43. package/src/ui/DiagramTitlePanel.tsx +108 -96
  44. package/src/ui/DynamicViewWalkthrough.css.ts +3 -2
  45. package/src/ui/DynamicViewWalkthrough.tsx +36 -17
  46. package/src/ui/OptionsPanel.tsx +28 -19
  47. package/src/ui/options/NodeOptions.tsx +16 -19
  48. package/src/xyflow/FitviewOnDiagramChange.tsx +15 -23
  49. package/src/xyflow/SelectEdgesOnNodeFocus.tsx +3 -6
  50. package/src/xyflow/SyncWithDiagram.tsx +21 -2
  51. package/src/xyflow/XYFlow.tsx +20 -23
  52. package/src/xyflow/XYFlowEvents.tsx +26 -8
  53. package/src/xyflow/XYFlowInner.tsx +10 -6
  54. package/src/xyflow/const.ts +1 -1
  55. package/src/xyflow/diagram-to-xyflow.ts +4 -41
  56. package/src/xyflow/edges/RelationshipEdge.tsx +160 -111
  57. package/src/xyflow/edges/edges.css.ts +41 -26
  58. package/src/xyflow/edges/utils.ts +5 -2
  59. package/src/xyflow/hooks/useLayoutConstraints.ts +19 -4
  60. package/src/xyflow/nodes/compound/CompoundNode.css.ts +45 -37
  61. package/src/xyflow/nodes/compound/CompoundNode.tsx +36 -26
  62. package/src/xyflow/nodes/element/ElementNode.tsx +27 -14
  63. package/src/xyflow/nodes/element/element.css.ts +31 -18
  64. package/src/xyflow/nodes/element/index.ts +1 -1
  65. package/src/xyflow/nodes/shared/NavigateToBtn.tsx +7 -3
  66. package/src/xyflow/types.ts +5 -2
  67. package/src/xyflow/utils.ts +48 -0
  68. package/dist/ui/index.d.ts +0 -2
  69. package/src/ui/index.ts +0 -3
package/dist/index.mjs CHANGED
@@ -2,21 +2,22 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key != "symbol" ? key + "" : key, value);
4
4
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
5
- import { createContext, memo, useState, forwardRef, useCallback, useMemo, useEffect, useRef, useContext, useLayoutEffect, useId } from "react";
5
+ import { createContext, memo, useState, forwardRef, useCallback, useMemo, useRef, useEffect, useContext, useLayoutEffect, useId } from "react";
6
6
  import { createWithEqualityFn, useStoreWithEqualityFn } from "zustand/traditional";
7
7
  import { shallow } from "zustand/shallow";
8
8
  import { createPortal } from "react-dom";
9
- import { Box, MantineContext, ActionIcon, Text, HoverCard, HoverCardTarget, UnstyledButton, HoverCardDropdown, Stack, Group, Anchor, CopyButton, Button, useMantineColorScheme, Divider, TooltipGroup, Flex, Tooltip, ColorSwatch, CheckIcon, rem, Select, Slider, SegmentedControl, Card, Paper, Spoiler } from "@mantine/core";
10
- import { isNullish, entries, hasSubObject, hasAtLeast, first, last, zip, clamp as clamp$1, isNumber, keys, takeWhile, isNonNull } from "remeda";
11
- import { invariant, isAncestor, nonNullable, StepEdgeId, nonexhaustive, extractStep, defaultTheme, ElementShapes } from "@likec4/core";
12
9
  import { DEV } from "esm-env";
13
10
  import { shallowEqual, deepEqual } from "fast-equals";
11
+ import { m, AnimatePresence, LazyMotion, domAnimation } from "framer-motion";
12
+ import { Box, MantineContext, ActionIcon, Text, HoverCard, HoverCardTarget, UnstyledButton, HoverCardDropdown, Stack, Group, Anchor, CopyButton, Button, Card, CardSection, Spoiler, Divider, TooltipGroup, Flex, Tooltip, ColorSwatch, CheckIcon, rem, Select, Slider, SegmentedControl } from "@mantine/core";
13
+ import { isArray, isNullish, entries, reduce, isEmpty, hasSubObject, hasAtLeast as hasAtLeast$1, isTruthy, first, last, clamp as clamp$1, isNumber, keys, takeWhile, isNonNull } from "remeda";
14
+ import { invariant, hasAtLeast, isAncestor, nonNullable, StepEdgeId, nonexhaustive, extractStep, defaultTheme, ElementShapes } from "@likec4/core";
14
15
  import { subscribeWithSelector, devtools } from "zustand/middleware";
15
- import { useFirstMountState, useCustomCompareEffect, useDebouncedEffect } from "@react-hookz/web";
16
+ import { useFirstMountState, useCustomCompareEffect, useDebouncedEffect, useIsomorphicLayoutEffect as useIsomorphicLayoutEffect$1 } from "@react-hookz/web";
17
+ import { assignInlineVars } from "@vanilla-extract/dynamic";
16
18
  import { line, curveCatmullRomOpen } from "d3-shape";
17
- import { motion, AnimatePresence } from "framer-motion";
18
- import { useLocalStorage } from "@mantine/hooks";
19
- import { IconPlayerPlayFilled, IconPlayerSkipBackFilled, IconPlayerStopFilled, IconPlayerSkipForwardFilled } from "@tabler/icons-react";
19
+ import { IconZoomScan, IconChevronLeft, IconChevronRight, IconMenu, IconPlayerPlayFilled, IconPlayerSkipBackFilled, IconPlayerStopFilled, IconPlayerSkipForwardFilled } from "@tabler/icons-react";
20
+ import { useStateHistory, useLocalStorage, useHotkeys } from "@mantine/hooks";
20
21
  function cc(names) {
21
22
  if (typeof names == "string" || typeof names == "number") return "" + names;
22
23
  let out = "";
@@ -52,7 +53,7 @@ Dispatch.prototype = dispatch.prototype = {
52
53
  on: function(typename, callback) {
53
54
  var _ = this._, T = parseTypenames$1(typename + "", _), t2, i = -1, n = T.length;
54
55
  if (arguments.length < 2) {
55
- for (; ++i < n; ) if ((t2 = (typename = T[i]).type) && (t2 = get$2(_[t2], typename.name))) return t2;
56
+ for (; ++i < n; ) if ((t2 = (typename = T[i]).type) && (t2 = get$1(_[t2], typename.name))) return t2;
56
57
  return;
57
58
  }
58
59
  if (callback != null && typeof callback != "function") throw new Error("invalid callback: " + callback);
@@ -76,7 +77,7 @@ Dispatch.prototype = dispatch.prototype = {
76
77
  for (var t2 = this._[type], i = 0, n = t2.length; i < n; ++i) t2[i].value.apply(that, args);
77
78
  }
78
79
  };
79
- function get$2(type, name) {
80
+ function get$1(type, name) {
80
81
  for (var i = 0, n = type.length, c; i < n; ++i)
81
82
  if ((c = type[i]).name === name)
82
83
  return c.value;
@@ -125,7 +126,7 @@ function selector$5(selector2) {
125
126
  }
126
127
  function selection_select(select2) {
127
128
  typeof select2 != "function" && (select2 = selector$5(select2));
128
- for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j)
129
+ for (var groups = this._groups, m2 = groups.length, subgroups = new Array(m2), j = 0; j < m2; ++j)
129
130
  for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i)
130
131
  (node = group[i]) && (subnode = select2.call(node, node.__data__, i, group)) && ("__data__" in node && (subnode.__data__ = node.__data__), subgroup[i] = subnode);
131
132
  return new Selection$1(subgroups, this._parents);
@@ -148,7 +149,7 @@ function arrayAll(select2) {
148
149
  }
149
150
  function selection_selectAll(select2) {
150
151
  typeof select2 == "function" ? select2 = arrayAll(select2) : select2 = selectorAll(select2);
151
- for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j)
152
+ for (var groups = this._groups, m2 = groups.length, subgroups = [], parents = [], j = 0; j < m2; ++j)
152
153
  for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i)
153
154
  (node = group[i]) && (subgroups.push(select2.call(node, node.__data__, i, group)), parents.push(node));
154
155
  return new Selection$1(subgroups, parents);
@@ -189,7 +190,7 @@ function selection_selectChildren(match) {
189
190
  }
190
191
  function selection_filter(match) {
191
192
  typeof match != "function" && (match = matcher(match));
192
- for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j)
193
+ for (var groups = this._groups, m2 = groups.length, subgroups = new Array(m2), j = 0; j < m2; ++j)
193
194
  for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i)
194
195
  (node = group[i]) && match.call(node, node.__data__, i, group) && subgroup.push(node);
195
196
  return new Selection$1(subgroups, this._parents);
@@ -245,7 +246,7 @@ function selection_data(value, key) {
245
246
  if (!arguments.length) return Array.from(this, datum);
246
247
  var bind = key ? bindKey : bindIndex, parents = this._parents, groups = this._groups;
247
248
  typeof value != "function" && (value = constant$3(value));
248
- for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
249
+ for (var m2 = groups.length, update = new Array(m2), enter = new Array(m2), exit = new Array(m2), j = 0; j < m2; ++j) {
249
250
  var parent = parents[j], group = groups[j], groupLength = group.length, data = arraylike(value.call(parent, parent && parent.__data__, j, parents)), dataLength = data.length, enterGroup = enter[j] = new Array(dataLength), updateGroup = update[j] = new Array(dataLength), exitGroup = exit[j] = new Array(groupLength);
250
251
  bind(parent, group, enterGroup, updateGroup, exitGroup, data, key);
251
252
  for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0)
@@ -267,7 +268,7 @@ function selection_join(onenter, onupdate, onexit) {
267
268
  return typeof onenter == "function" ? (enter = onenter(enter), enter && (enter = enter.selection())) : enter = enter.append(onenter + ""), onupdate != null && (update = onupdate(update), update && (update = update.selection())), onexit == null ? exit.remove() : onexit(exit), enter && update ? enter.merge(update).order() : update;
268
269
  }
269
270
  function selection_merge(context) {
270
- for (var selection2 = context.selection ? context.selection() : context, groups0 = this._groups, groups1 = selection2._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j)
271
+ for (var selection2 = context.selection ? context.selection() : context, groups0 = this._groups, groups1 = selection2._groups, m0 = groups0.length, m1 = groups1.length, m2 = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m2; ++j)
271
272
  for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i)
272
273
  (node = group0[i] || group1[i]) && (merge[i] = node);
273
274
  for (; j < m0; ++j)
@@ -275,7 +276,7 @@ function selection_merge(context) {
275
276
  return new Selection$1(merges, this._parents);
276
277
  }
277
278
  function selection_order() {
278
- for (var groups = this._groups, j = -1, m = groups.length; ++j < m; )
279
+ for (var groups = this._groups, j = -1, m2 = groups.length; ++j < m2; )
279
280
  for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0; )
280
281
  (node = group[i]) && (next && node.compareDocumentPosition(next) ^ 4 && next.parentNode.insertBefore(node, next), next = node);
281
282
  return this;
@@ -285,7 +286,7 @@ function selection_sort(compare) {
285
286
  function compareNode(a, b) {
286
287
  return a && b ? compare(a.__data__, b.__data__) : !a - !b;
287
288
  }
288
- for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
289
+ for (var groups = this._groups, m2 = groups.length, sortgroups = new Array(m2), j = 0; j < m2; ++j) {
289
290
  for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i)
290
291
  (node = group[i]) && (sortgroup[i] = node);
291
292
  sortgroup.sort(compareNode);
@@ -303,7 +304,7 @@ function selection_nodes() {
303
304
  return Array.from(this);
304
305
  }
305
306
  function selection_node() {
306
- for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j)
307
+ for (var groups = this._groups, j = 0, m2 = groups.length; j < m2; ++j)
307
308
  for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
308
309
  var node = group[i];
309
310
  if (node) return node;
@@ -319,7 +320,7 @@ function selection_empty() {
319
320
  return !this.node();
320
321
  }
321
322
  function selection_each(callback) {
322
- for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j)
323
+ for (var groups = this._groups, j = 0, m2 = groups.length; j < m2; ++j)
323
324
  for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i)
324
325
  (node = group[i]) && callback.call(node, node.__data__, i, group);
325
326
  return this;
@@ -556,7 +557,7 @@ function onRemove(typename) {
556
557
  return function() {
557
558
  var on = this.__on;
558
559
  if (on) {
559
- for (var j = 0, i = -1, m = on.length, o; j < m; ++j)
560
+ for (var j = 0, i = -1, m2 = on.length, o; j < m2; ++j)
560
561
  o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name ? this.removeEventListener(o.type, o.listener, o.options) : on[++i] = o;
561
562
  ++i ? on.length = i : delete this.__on;
562
563
  }
@@ -566,7 +567,7 @@ function onAdd(typename, value, options) {
566
567
  return function() {
567
568
  var on = this.__on, o, listener = contextListener(value);
568
569
  if (on) {
569
- for (var j = 0, m = on.length; j < m; ++j)
570
+ for (var j = 0, m2 = on.length; j < m2; ++j)
570
571
  if ((o = on[j]).type === typename.type && o.name === typename.name) {
571
572
  this.removeEventListener(o.type, o.listener, o.options), this.addEventListener(o.type, o.listener = listener, o.options = options), o.value = value;
572
573
  return;
@@ -580,7 +581,7 @@ function selection_on(typename, value, options) {
580
581
  if (arguments.length < 2) {
581
582
  var on = this.node().__on;
582
583
  if (on) {
583
- for (var j = 0, m = on.length, o; j < m; ++j)
584
+ for (var j = 0, m2 = on.length, o; j < m2; ++j)
584
585
  for (i = 0, o = on[j]; i < n; ++i)
585
586
  if ((t2 = typenames[i]).type === o.type && t2.name === o.name)
586
587
  return o.value;
@@ -608,7 +609,7 @@ function selection_dispatch(type, params) {
608
609
  return this.each((typeof params == "function" ? dispatchFunction : dispatchConstant)(type, params));
609
610
  }
610
611
  function* selection_iterator() {
611
- for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j)
612
+ for (var groups = this._groups, j = 0, m2 = groups.length; j < m2; ++j)
612
613
  for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i)
613
614
  (node = group[i]) && (yield node);
614
615
  }
@@ -1029,8 +1030,8 @@ function color_formatRgb() {
1029
1030
  return this.rgb().formatRgb();
1030
1031
  }
1031
1032
  function color(format) {
1032
- var m, l;
1033
- return format = (format + "").trim().toLowerCase(), (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) : l === 3 ? new Rgb(m >> 8 & 15 | m >> 4 & 240, m >> 4 & 15 | m & 240, (m & 15) << 4 | m & 15, 1) : l === 8 ? rgba(m >> 24 & 255, m >> 16 & 255, m >> 8 & 255, (m & 255) / 255) : l === 4 ? rgba(m >> 12 & 15 | m >> 8 & 240, m >> 8 & 15 | m >> 4 & 240, m >> 4 & 15 | m & 240, ((m & 15) << 4 | m & 15) / 255) : null) : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) : named.hasOwnProperty(format) ? rgbn(named[format]) : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) : null;
1033
+ var m2, l;
1034
+ return format = (format + "").trim().toLowerCase(), (m2 = reHex.exec(format)) ? (l = m2[1].length, m2 = parseInt(m2[1], 16), l === 6 ? rgbn(m2) : l === 3 ? new Rgb(m2 >> 8 & 15 | m2 >> 4 & 240, m2 >> 4 & 15 | m2 & 240, (m2 & 15) << 4 | m2 & 15, 1) : l === 8 ? rgba(m2 >> 24 & 255, m2 >> 16 & 255, m2 >> 8 & 255, (m2 & 255) / 255) : l === 4 ? rgba(m2 >> 12 & 15 | m2 >> 8 & 240, m2 >> 8 & 15 | m2 >> 4 & 240, m2 >> 4 & 15 | m2 & 240, ((m2 & 15) << 4 | m2 & 15) / 255) : null) : (m2 = reRgbInteger.exec(format)) ? new Rgb(m2[1], m2[2], m2[3], 1) : (m2 = reRgbPercent.exec(format)) ? new Rgb(m2[1] * 255 / 100, m2[2] * 255 / 100, m2[3] * 255 / 100, 1) : (m2 = reRgbaInteger.exec(format)) ? rgba(m2[1], m2[2], m2[3], m2[4]) : (m2 = reRgbaPercent.exec(format)) ? rgba(m2[1] * 255 / 100, m2[2] * 255 / 100, m2[3] * 255 / 100, m2[4]) : (m2 = reHslPercent.exec(format)) ? hsla(m2[1], m2[2] / 100, m2[3] / 100, 1) : (m2 = reHslaPercent.exec(format)) ? hsla(m2[1], m2[2] / 100, m2[3] / 100, m2[4]) : named.hasOwnProperty(format) ? rgbn(named[format]) : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) : null;
1034
1035
  }
1035
1036
  function rgbn(n) {
1036
1037
  return new Rgb(n >> 16 & 255, n >> 8 & 255, n & 255, 1);
@@ -1218,8 +1219,8 @@ function decompose(a, b, c, d, e, f) {
1218
1219
  }
1219
1220
  var svgNode;
1220
1221
  function parseCss(value) {
1221
- const m = new (typeof DOMMatrix == "function" ? DOMMatrix : WebKitCSSMatrix)(value + "");
1222
- return m.isIdentity ? identity$1 : decompose(m.a, m.b, m.c, m.d, m.e, m.f);
1222
+ const m2 = new (typeof DOMMatrix == "function" ? DOMMatrix : WebKitCSSMatrix)(value + "");
1223
+ return m2.isIdentity ? identity$1 : decompose(m2.a, m2.b, m2.c, m2.d, m2.e, m2.f);
1223
1224
  }
1224
1225
  function parseSvg(value) {
1225
1226
  return value == null || (svgNode || (svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g")), svgNode.setAttribute("transform", value), !(value = svgNode.transform.baseVal.consolidate())) ? identity$1 : (value = value.matrix, decompose(value.a, value.b, value.c, value.d, value.e, value.f));
@@ -1377,16 +1378,16 @@ function schedule(node, name, id2, index2, group, timing) {
1377
1378
  });
1378
1379
  }
1379
1380
  function init(node, id2) {
1380
- var schedule2 = get$1(node, id2);
1381
+ var schedule2 = get(node, id2);
1381
1382
  if (schedule2.state > CREATED) throw new Error("too late; already scheduled");
1382
1383
  return schedule2;
1383
1384
  }
1384
1385
  function set(node, id2) {
1385
- var schedule2 = get$1(node, id2);
1386
+ var schedule2 = get(node, id2);
1386
1387
  if (schedule2.state > STARTED) throw new Error("too late; already running");
1387
1388
  return schedule2;
1388
1389
  }
1389
- function get$1(node, id2) {
1390
+ function get(node, id2) {
1390
1391
  var schedule2 = node.__transition;
1391
1392
  if (!schedule2 || !(schedule2 = schedule2[id2])) throw new Error("transition not found");
1392
1393
  return schedule2;
@@ -1478,7 +1479,7 @@ function tweenFunction(id2, name, value) {
1478
1479
  function transition_tween(name, value) {
1479
1480
  var id2 = this._id;
1480
1481
  if (name += "", arguments.length < 2) {
1481
- for (var tween = get$1(this.node(), id2).tween, i = 0, n = tween.length, t2; i < n; ++i)
1482
+ for (var tween = get(this.node(), id2).tween, i = 0, n = tween.length, t2; i < n; ++i)
1482
1483
  if ((t2 = tween[i]).name === name)
1483
1484
  return t2.value;
1484
1485
  return null;
@@ -1491,7 +1492,7 @@ function tweenValue(transition, name, value) {
1491
1492
  var schedule2 = set(this, id2);
1492
1493
  (schedule2.value || (schedule2.value = {}))[name] = value.apply(this, arguments);
1493
1494
  }), function(node) {
1494
- return get$1(node, id2).value[name];
1495
+ return get(node, id2).value[name];
1495
1496
  };
1496
1497
  }
1497
1498
  function interpolate(a, b) {
@@ -1586,7 +1587,7 @@ function delayConstant(id2, value) {
1586
1587
  }
1587
1588
  function transition_delay(value) {
1588
1589
  var id2 = this._id;
1589
- return arguments.length ? this.each((typeof value == "function" ? delayFunction : delayConstant)(id2, value)) : get$1(this.node(), id2).delay;
1590
+ return arguments.length ? this.each((typeof value == "function" ? delayFunction : delayConstant)(id2, value)) : get(this.node(), id2).delay;
1590
1591
  }
1591
1592
  function durationFunction(id2, value) {
1592
1593
  return function() {
@@ -1600,7 +1601,7 @@ function durationConstant(id2, value) {
1600
1601
  }
1601
1602
  function transition_duration(value) {
1602
1603
  var id2 = this._id;
1603
- return arguments.length ? this.each((typeof value == "function" ? durationFunction : durationConstant)(id2, value)) : get$1(this.node(), id2).duration;
1604
+ return arguments.length ? this.each((typeof value == "function" ? durationFunction : durationConstant)(id2, value)) : get(this.node(), id2).duration;
1604
1605
  }
1605
1606
  function easeConstant(id2, value) {
1606
1607
  if (typeof value != "function") throw new Error();
@@ -1610,7 +1611,7 @@ function easeConstant(id2, value) {
1610
1611
  }
1611
1612
  function transition_ease(value) {
1612
1613
  var id2 = this._id;
1613
- return arguments.length ? this.each(easeConstant(id2, value)) : get$1(this.node(), id2).ease;
1614
+ return arguments.length ? this.each(easeConstant(id2, value)) : get(this.node(), id2).ease;
1614
1615
  }
1615
1616
  function easeVarying(id2, value) {
1616
1617
  return function() {
@@ -1625,14 +1626,14 @@ function transition_easeVarying(value) {
1625
1626
  }
1626
1627
  function transition_filter(match) {
1627
1628
  typeof match != "function" && (match = matcher(match));
1628
- for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j)
1629
+ for (var groups = this._groups, m2 = groups.length, subgroups = new Array(m2), j = 0; j < m2; ++j)
1629
1630
  for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i)
1630
1631
  (node = group[i]) && match.call(node, node.__data__, i, group) && subgroup.push(node);
1631
1632
  return new Transition(subgroups, this._parents, this._name, this._id);
1632
1633
  }
1633
1634
  function transition_merge(transition) {
1634
1635
  if (transition._id !== this._id) throw new Error();
1635
- for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j)
1636
+ for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m2 = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m2; ++j)
1636
1637
  for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i)
1637
1638
  (node = group0[i] || group1[i]) && (merge[i] = node);
1638
1639
  for (; j < m0; ++j)
@@ -1654,7 +1655,7 @@ function onFunction(id2, name, listener) {
1654
1655
  }
1655
1656
  function transition_on(name, listener) {
1656
1657
  var id2 = this._id;
1657
- return arguments.length < 2 ? get$1(this.node(), id2).on.on(name) : this.each(onFunction(id2, name, listener));
1658
+ return arguments.length < 2 ? get(this.node(), id2).on.on(name) : this.each(onFunction(id2, name, listener));
1658
1659
  }
1659
1660
  function removeFunction(id2) {
1660
1661
  return function() {
@@ -1669,18 +1670,18 @@ function transition_remove() {
1669
1670
  function transition_select(select2) {
1670
1671
  var name = this._name, id2 = this._id;
1671
1672
  typeof select2 != "function" && (select2 = selector$5(select2));
1672
- for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j)
1673
+ for (var groups = this._groups, m2 = groups.length, subgroups = new Array(m2), j = 0; j < m2; ++j)
1673
1674
  for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i)
1674
- (node = group[i]) && (subnode = select2.call(node, node.__data__, i, group)) && ("__data__" in node && (subnode.__data__ = node.__data__), subgroup[i] = subnode, schedule(subgroup[i], name, id2, i, subgroup, get$1(node, id2)));
1675
+ (node = group[i]) && (subnode = select2.call(node, node.__data__, i, group)) && ("__data__" in node && (subnode.__data__ = node.__data__), subgroup[i] = subnode, schedule(subgroup[i], name, id2, i, subgroup, get(node, id2)));
1675
1676
  return new Transition(subgroups, this._parents, name, id2);
1676
1677
  }
1677
1678
  function transition_selectAll(select2) {
1678
1679
  var name = this._name, id2 = this._id;
1679
1680
  typeof select2 != "function" && (select2 = selectorAll(select2));
1680
- for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j)
1681
+ for (var groups = this._groups, m2 = groups.length, subgroups = [], parents = [], j = 0; j < m2; ++j)
1681
1682
  for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i)
1682
1683
  if (node = group[i]) {
1683
- for (var children2 = select2.call(node, node.__data__, i, group), child, inherit2 = get$1(node, id2), k = 0, l = children2.length; k < l; ++k)
1684
+ for (var children2 = select2.call(node, node.__data__, i, group), child, inherit2 = get(node, id2), k = 0, l = children2.length; k < l; ++k)
1684
1685
  (child = children2[k]) && schedule(child, name, id2, k, children2, inherit2);
1685
1686
  subgroups.push(children2), parents.push(node);
1686
1687
  }
@@ -1782,10 +1783,10 @@ function transition_textTween(value) {
1782
1783
  return this.tween(key, textTween(value));
1783
1784
  }
1784
1785
  function transition_transition() {
1785
- for (var name = this._name, id0 = this._id, id1 = newId(), groups = this._groups, m = groups.length, j = 0; j < m; ++j)
1786
+ for (var name = this._name, id0 = this._id, id1 = newId(), groups = this._groups, m2 = groups.length, j = 0; j < m2; ++j)
1786
1787
  for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i)
1787
1788
  if (node = group[i]) {
1788
- var inherit2 = get$1(node, id0);
1789
+ var inherit2 = get(node, id0);
1789
1790
  schedule(node, name, id1, i, group, {
1790
1791
  time: inherit2.time + inherit2.delay + inherit2.duration,
1791
1792
  delay: 0,
@@ -1866,7 +1867,7 @@ function inherit(node, id2) {
1866
1867
  function selection_transition(name) {
1867
1868
  var id2, timing;
1868
1869
  name instanceof Transition ? (id2 = name._id, name = name._name) : (id2 = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + "");
1869
- for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j)
1870
+ for (var groups = this._groups, m2 = groups.length, j = 0; j < m2; ++j)
1870
1871
  for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i)
1871
1872
  (node = group[i]) && schedule(node, name, id2, i, group, timing || inherit(node, id2));
1872
1873
  return new Transition(groups, this._parents, name, id2);
@@ -2401,7 +2402,7 @@ function evaluateAbsolutePosition(position, parentId, nodeLookup, nodeOrigin = [
2401
2402
  let nextParentId = parentId;
2402
2403
  const positionAbsolute = { ...position };
2403
2404
  for (; nextParentId; ) {
2404
- const parent = nodeLookup.get(parentId);
2405
+ const parent = nodeLookup.get(nextParentId);
2405
2406
  if (nextParentId = parent == null ? void 0 : parent.parentId, parent) {
2406
2407
  const origin = parent.origin || nodeOrigin, xOffset = (parent.measured.width ?? 0) * origin[0], yOffset = (parent.measured.height ?? 0) * origin[1];
2407
2408
  positionAbsolute.x += parent.position.x - xOffset, positionAbsolute.y += parent.position.y - yOffset;
@@ -2436,21 +2437,21 @@ const isMouseEvent = (event) => "clientX" in event, getEventPosition = (event, b
2436
2437
  x: evtX - ((bounds == null ? void 0 : bounds.left) ?? 0),
2437
2438
  y: evtY - ((bounds == null ? void 0 : bounds.top) ?? 0)
2438
2439
  };
2439
- }, getHandleBounds = (selector2, nodeElement, zoom2, nodeOrigin = [0, 0]) => {
2440
+ }, getHandleBounds = (selector2, nodeElement, nodeBounds, zoom2, nodeOrigin = [0, 0]) => {
2440
2441
  const handles = nodeElement.querySelectorAll(selector2);
2441
2442
  if (!handles || !handles.length)
2442
2443
  return null;
2443
- const handlesArray = Array.from(handles), nodeBounds = nodeElement.getBoundingClientRect(), nodeOffset = {
2444
- x: nodeBounds.width * nodeOrigin[0],
2445
- y: nodeBounds.height * nodeOrigin[1]
2444
+ const handlesArray = Array.from(handles), nodeOffset = {
2445
+ x: nodeBounds.left + nodeBounds.width * nodeOrigin[0],
2446
+ y: nodeBounds.top + nodeBounds.height * nodeOrigin[1]
2446
2447
  };
2447
2448
  return handlesArray.map((handle) => {
2448
2449
  const handleBounds = handle.getBoundingClientRect();
2449
2450
  return {
2450
2451
  id: handle.getAttribute("data-handleid"),
2451
2452
  position: handle.getAttribute("data-handlepos"),
2452
- x: (handleBounds.left - nodeBounds.left - nodeOffset.x) / zoom2,
2453
- y: (handleBounds.top - nodeBounds.top - nodeOffset.y) / zoom2,
2453
+ x: (handleBounds.left - nodeOffset.x) / zoom2,
2454
+ y: (handleBounds.top - nodeOffset.y) / zoom2,
2454
2455
  ...getDimensions(handle)
2455
2456
  };
2456
2457
  });
@@ -2637,14 +2638,14 @@ function getEdgePosition(params) {
2637
2638
  // when connection type is loose we can define all handles as sources and connect source -> source
2638
2639
  params.connectionMode === ConnectionMode.Strict ? (targetHandleBounds == null ? void 0 : targetHandleBounds.target) ?? [] : ((targetHandleBounds == null ? void 0 : targetHandleBounds.target) ?? []).concat((targetHandleBounds == null ? void 0 : targetHandleBounds.source) ?? []),
2639
2640
  params.targetHandle
2640
- ), sourcePosition = (sourceHandle == null ? void 0 : sourceHandle.position) || Position.Bottom, targetPosition = (targetHandle == null ? void 0 : targetHandle.position) || Position.Top;
2641
+ );
2641
2642
  if (!sourceHandle || !targetHandle)
2642
2643
  return (_a = params.onError) == null || _a.call(params, "008", errorMessages.error008(sourceHandle ? "target" : "source", {
2643
2644
  id: params.id,
2644
2645
  sourceHandle: params.sourceHandle,
2645
2646
  targetHandle: params.targetHandle
2646
2647
  })), null;
2647
- const [sourceX, sourceY] = getHandlePosition(sourcePosition, sourceNode, sourceHandle), [targetX, targetY] = getHandlePosition(targetPosition, targetNode, targetHandle);
2648
+ const sourcePosition = (sourceHandle == null ? void 0 : sourceHandle.position) || Position.Bottom, targetPosition = (targetHandle == null ? void 0 : targetHandle.position) || Position.Top, [sourceX, sourceY] = getHandlePosition(sourceNode, sourceHandle, sourcePosition), [targetX, targetY] = getHandlePosition(targetNode, targetHandle, targetPosition);
2648
2649
  return {
2649
2650
  sourceX,
2650
2651
  sourceY,
@@ -2665,9 +2666,9 @@ function toHandleBounds(handles) {
2665
2666
  target
2666
2667
  };
2667
2668
  }
2668
- function getHandlePosition(position, node, handle = null) {
2669
+ function getHandlePosition(node, handle, fallbackPosition = Position.Left) {
2669
2670
  const x = ((handle == null ? void 0 : handle.x) ?? 0) + node.internals.positionAbsolute.x, y = ((handle == null ? void 0 : handle.y) ?? 0) + node.internals.positionAbsolute.y, { width, height } = handle ?? getNodeDimensions(node);
2670
- switch (position) {
2671
+ switch ((handle == null ? void 0 : handle.position) ?? fallbackPosition) {
2671
2672
  case Position.Top:
2672
2673
  return [x + width / 2, y];
2673
2674
  case Position.Right:
@@ -2816,21 +2817,24 @@ function updateNodeInternals(updates, nodeLookup, parentLookup, domNode, nodeOri
2816
2817
  }, updatedInternals = !0;
2817
2818
  else if (node) {
2818
2819
  const dimensions = getDimensions(update.nodeElement), dimensionChanged = node.measured.width !== dimensions.width || node.measured.height !== dimensions.height;
2819
- !!(dimensions.width && dimensions.height && (dimensionChanged || !node.internals.handleBounds || update.force)) && (node.measured = dimensions, node.internals = {
2820
- ...node.internals,
2821
- handleBounds: {
2822
- source: getHandleBounds(".source", update.nodeElement, zoom2, node.origin || nodeOrigin),
2823
- target: getHandleBounds(".target", update.nodeElement, zoom2, node.origin || nodeOrigin)
2824
- }
2825
- }, updatedInternals = !0, dimensionChanged && (changes.push({
2826
- id: node.id,
2827
- type: "dimensions",
2828
- dimensions
2829
- }), node.expandParent && node.parentId && parentExpandChildren.push({
2830
- id: node.id,
2831
- parentId: node.parentId,
2832
- rect: nodeToRect(node, nodeOrigin)
2833
- })));
2820
+ if (!!(dimensions.width && dimensions.height && (dimensionChanged || !node.internals.handleBounds || update.force))) {
2821
+ const nodeBounds = update.nodeElement.getBoundingClientRect();
2822
+ node.measured = dimensions, node.internals = {
2823
+ ...node.internals,
2824
+ handleBounds: {
2825
+ source: getHandleBounds(".source", update.nodeElement, nodeBounds, zoom2, node.origin || nodeOrigin),
2826
+ target: getHandleBounds(".target", update.nodeElement, nodeBounds, zoom2, node.origin || nodeOrigin)
2827
+ }
2828
+ }, updatedInternals = !0, dimensionChanged && (changes.push({
2829
+ id: node.id,
2830
+ type: "dimensions",
2831
+ dimensions
2832
+ }), node.expandParent && node.parentId && parentExpandChildren.push({
2833
+ id: node.id,
2834
+ parentId: node.parentId,
2835
+ rect: nodeToRect(node, nodeOrigin)
2836
+ }));
2837
+ }
2834
2838
  }
2835
2839
  }), parentExpandChildren.length > 0) {
2836
2840
  const parentExpandChanges = handleExpandParent(parentExpandChildren, nodeLookup, parentLookup, nodeOrigin);
@@ -2935,7 +2939,7 @@ function getEventHandlerParams({ nodeId, dragItems, nodeLookup }) {
2935
2939
  ];
2936
2940
  }
2937
2941
  function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragStop }) {
2938
- let lastPos = { x: null, y: null }, autoPanId = 0, dragItems = /* @__PURE__ */ new Map(), autoPanStarted = !1, mousePosition = { x: 0, y: 0 }, containerBounds = null, dragStarted = !1, d3Selection = null;
2942
+ let lastPos = { x: null, y: null }, autoPanId = 0, dragItems = /* @__PURE__ */ new Map(), autoPanStarted = !1, mousePosition = { x: 0, y: 0 }, containerBounds = null, dragStarted = !1, d3Selection = null, abortDrag = !1;
2939
2943
  function update({ noDragClassName, handleSelector, domNode, isSelectable, nodeId }) {
2940
2944
  d3Selection = select(domNode);
2941
2945
  function updateNodes({ x, y }, dragEvent) {
@@ -3005,16 +3009,18 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
3005
3009
  }
3006
3010
  const d3DragInstance = drag().on("start", (event) => {
3007
3011
  const { domNode: domNode2, nodeDragThreshold, transform: transform2, snapGrid, snapToGrid } = getStoreItems();
3008
- nodeDragThreshold === 0 && startDrag(event), lastPos = getPointerPosition(event.sourceEvent, { transform: transform2, snapGrid, snapToGrid }), containerBounds = (domNode2 == null ? void 0 : domNode2.getBoundingClientRect()) || null, mousePosition = getEventPosition(event.sourceEvent, containerBounds);
3012
+ abortDrag = !1, nodeDragThreshold === 0 && startDrag(event), lastPos = getPointerPosition(event.sourceEvent, { transform: transform2, snapGrid, snapToGrid }), containerBounds = (domNode2 == null ? void 0 : domNode2.getBoundingClientRect()) || null, mousePosition = getEventPosition(event.sourceEvent, containerBounds);
3009
3013
  }).on("drag", (event) => {
3010
3014
  const { autoPanOnNodeDrag, transform: transform2, snapGrid, snapToGrid, nodeDragThreshold } = getStoreItems(), pointerPos = getPointerPosition(event.sourceEvent, { transform: transform2, snapGrid, snapToGrid });
3011
- if (!autoPanStarted && autoPanOnNodeDrag && dragStarted && (autoPanStarted = !0, autoPan()), !dragStarted) {
3012
- const x = pointerPos.xSnapped - (lastPos.x ?? 0), y = pointerPos.ySnapped - (lastPos.y ?? 0);
3013
- Math.sqrt(x * x + y * y) > nodeDragThreshold && startDrag(event);
3015
+ if (event.sourceEvent.type === "touchmove" && event.sourceEvent.touches.length > 1 && (abortDrag = !0), !abortDrag) {
3016
+ if (!autoPanStarted && autoPanOnNodeDrag && dragStarted && (autoPanStarted = !0, autoPan()), !dragStarted) {
3017
+ const x = pointerPos.xSnapped - (lastPos.x ?? 0), y = pointerPos.ySnapped - (lastPos.y ?? 0);
3018
+ Math.sqrt(x * x + y * y) > nodeDragThreshold && startDrag(event);
3019
+ }
3020
+ (lastPos.x !== pointerPos.xSnapped || lastPos.y !== pointerPos.ySnapped) && dragItems && dragStarted && (mousePosition = getEventPosition(event.sourceEvent, containerBounds), updateNodes(pointerPos, event.sourceEvent));
3014
3021
  }
3015
- (lastPos.x !== pointerPos.xSnapped || lastPos.y !== pointerPos.ySnapped) && dragItems && dragStarted && (mousePosition = getEventPosition(event.sourceEvent, containerBounds), updateNodes(pointerPos, event.sourceEvent));
3016
3022
  }).on("end", (event) => {
3017
- if (dragStarted && (autoPanStarted = !1, dragStarted = !1, cancelAnimationFrame(autoPanId), dragItems.size > 0)) {
3023
+ if (!(!dragStarted || abortDrag) && (autoPanStarted = !1, dragStarted = !1, cancelAnimationFrame(autoPanId), dragItems.size > 0)) {
3018
3024
  const { nodeLookup, updateNodePositions, onNodeDragStop, onSelectionDragStop } = getStoreItems();
3019
3025
  if (updateNodePositions(dragItems, !1), onDragStop || onNodeDragStop || !nodeId && onSelectionDragStop) {
3020
3026
  const [currentNode, currentNodes] = getEventHandlerParams({
@@ -3040,13 +3046,19 @@ function XYDrag({ onNodeMouseDown, getStoreItems, onDragStart, onDrag, onDragSto
3040
3046
  };
3041
3047
  }
3042
3048
  function getHandles(node, handleBounds, type, currentHandle) {
3043
- return (handleBounds[type] || []).reduce((res, h) => (`${node.id}-${h.id}-${type}` !== currentHandle && res.push({
3044
- id: h.id || null,
3045
- type,
3046
- nodeId: node.id,
3047
- x: node.internals.positionAbsolute.x + h.x + h.width / 2,
3048
- y: node.internals.positionAbsolute.y + h.y + h.height / 2
3049
- }), res), []);
3049
+ return (handleBounds[type] || []).reduce((res, handle) => {
3050
+ if (`${node.id}-${handle.id}-${type}` !== currentHandle) {
3051
+ const [x, y] = getHandlePosition(node, handle);
3052
+ res.push({
3053
+ id: handle.id || null,
3054
+ type,
3055
+ nodeId: node.id,
3056
+ x,
3057
+ y
3058
+ });
3059
+ }
3060
+ return res;
3061
+ }, []);
3050
3062
  }
3051
3063
  function getClosestHandle(pos, connectionRadius, handles) {
3052
3064
  let closestHandles = [], minDistance = 1 / 0;
@@ -3077,7 +3089,7 @@ function getConnectionStatus(isInsideConnectionRadius, isHandleValid) {
3077
3089
  }
3078
3090
  const alwaysValid = () => !0;
3079
3091
  let connectionStartHandle = null;
3080
- function onPointerDown(event, { connectionMode, connectionRadius, handleId, nodeId, edgeUpdaterType, isTarget, domNode, nodeLookup, lib, autoPanOnConnect, flowId, panBy: panBy2, cancelConnection, onConnectStart, onConnect, onConnectEnd, isValidConnection = alwaysValid, onEdgeUpdateEnd, updateConnection, getTransform, getConnectionStartHandle }) {
3092
+ 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, getConnectionStartHandle }) {
3081
3093
  const doc = getHostForElement(event.target);
3082
3094
  let autoPanId = 0, closestHandle;
3083
3095
  const { x, y } = getEventPosition(event), clickedHandle = doc == null ? void 0 : doc.elementFromPoint(x, y), handleType = getHandleType(edgeUpdaterType, clickedHandle), containerBounds = domNode == null ? void 0 : domNode.getBoundingClientRect();
@@ -3099,11 +3111,11 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
3099
3111
  connectionStartHandle = {
3100
3112
  nodeId,
3101
3113
  handleId,
3102
- type: handleType
3114
+ type: handleType,
3115
+ position: (clickedHandle == null ? void 0 : clickedHandle.getAttribute("data-handlepos")) || Position.Top
3103
3116
  }, updateConnection({
3104
3117
  connectionPosition,
3105
3118
  connectionStatus: null,
3106
- // connectionNodeId etc will be removed in the next major in favor of connectionStartHandle
3107
3119
  connectionStartHandle,
3108
3120
  connectionEndHandle: null
3109
3121
  }), onConnectStart == null || onConnectStart(event, { nodeId, handleId, handleType });
@@ -3133,7 +3145,7 @@ function onPointerDown(event, { connectionMode, connectionRadius, handleId, node
3133
3145
  });
3134
3146
  }
3135
3147
  function onPointerUp(event2) {
3136
- (closestHandle || handleDomNode) && connection && isValid && (onConnect == null || onConnect(connection)), onConnectEnd == null || onConnectEnd(event2), edgeUpdaterType && (onEdgeUpdateEnd == null || onEdgeUpdateEnd(event2)), cancelConnection(), cancelAnimationFrame(autoPanId), autoPanStarted = !1, isValid = !1, connection = null, handleDomNode = null, connectionStartHandle = null, doc.removeEventListener("mousemove", onPointerMove), doc.removeEventListener("mouseup", onPointerUp), doc.removeEventListener("touchmove", onPointerMove), doc.removeEventListener("touchend", onPointerUp);
3148
+ (closestHandle || handleDomNode) && connection && isValid && (onConnect == null || onConnect(connection)), onConnectEnd == null || onConnectEnd(event2), edgeUpdaterType && (onReconnectEnd == null || onReconnectEnd(event2)), cancelConnection(), cancelAnimationFrame(autoPanId), autoPanStarted = !1, isValid = !1, connection = null, handleDomNode = null, connectionStartHandle = null, doc.removeEventListener("mousemove", onPointerMove), doc.removeEventListener("mouseup", onPointerUp), doc.removeEventListener("touchmove", onPointerMove), doc.removeEventListener("touchend", onPointerUp);
3137
3149
  }
3138
3150
  doc.addEventListener("mousemove", onPointerMove), doc.addEventListener("mouseup", onPointerUp), doc.addEventListener("touchmove", onPointerMove), doc.addEventListener("touchend", onPointerUp);
3139
3151
  }
@@ -3154,11 +3166,14 @@ function isValidHandle(event, { handle, connectionMode, fromNodeId, fromHandleId
3154
3166
  target: isTarget ? fromNodeId : handleNodeId,
3155
3167
  targetHandle: isTarget ? fromHandleId : handleId
3156
3168
  };
3157
- result.connection = connection, connectable && connectableEnd && (connectionMode === ConnectionMode.Strict ? isTarget && handleType === "source" || !isTarget && handleType === "target" : handleNodeId !== fromNodeId || handleId !== fromHandleId) && (result.endHandle = {
3169
+ result.connection = connection;
3170
+ const isValid = connectable && connectableEnd && (connectionMode === ConnectionMode.Strict ? isTarget && handleType === "source" || !isTarget && handleType === "target" : handleNodeId !== fromNodeId || handleId !== fromHandleId);
3171
+ result.isValid = isValid && isValidConnection(connection), result.endHandle = {
3158
3172
  nodeId: handleNodeId,
3159
3173
  handleId,
3160
- type: handleType
3161
- }, result.isValid = isValidConnection(connection));
3174
+ type: handleType,
3175
+ position: handleToCheck.getAttribute("data-handlepos")
3176
+ };
3162
3177
  }
3163
3178
  return result;
3164
3179
  }
@@ -3288,10 +3303,15 @@ function createPanZoomEndHandler({ zoomPanValues, panOnDrag, panOnScroll, onDrag
3288
3303
  }
3289
3304
  function createFilter({ zoomActivationKeyPressed, zoomOnScroll, zoomOnPinch, panOnDrag, panOnScroll, zoomOnDoubleClick, userSelectionActive, noWheelClassName, noPanClassName, lib }) {
3290
3305
  return (event) => {
3306
+ var _a;
3291
3307
  const zoomScroll = zoomActivationKeyPressed || zoomOnScroll, pinchZoom = zoomOnPinch && event.ctrlKey;
3292
3308
  if (event.button === 1 && event.type === "mousedown" && (isWrappedWithClass(event, `${lib}-flow__node`) || isWrappedWithClass(event, `${lib}-flow__edge`)))
3293
3309
  return !0;
3294
- if (!panOnDrag && !zoomScroll && !panOnScroll && !zoomOnDoubleClick && !zoomOnPinch || userSelectionActive || isWrappedWithClass(event, noWheelClassName) && event.type === "wheel" || isWrappedWithClass(event, noPanClassName) && (event.type !== "wheel" || panOnScroll && event.type === "wheel" && !zoomActivationKeyPressed) || !zoomOnPinch && event.ctrlKey && event.type === "wheel" || !zoomScroll && !panOnScroll && !pinchZoom && event.type === "wheel" || !panOnDrag && (event.type === "mousedown" || event.type === "touchstart") || Array.isArray(panOnDrag) && !panOnDrag.includes(event.button) && event.type === "mousedown")
3310
+ if (!panOnDrag && !zoomScroll && !panOnScroll && !zoomOnDoubleClick && !zoomOnPinch || userSelectionActive || isWrappedWithClass(event, noWheelClassName) && event.type === "wheel" || isWrappedWithClass(event, noPanClassName) && (event.type !== "wheel" || panOnScroll && event.type === "wheel" && !zoomActivationKeyPressed) || !zoomOnPinch && event.ctrlKey && event.type === "wheel")
3311
+ return !1;
3312
+ if (!zoomOnPinch && event.type === "touchstart" && ((_a = event.touches) == null ? void 0 : _a.length) > 1)
3313
+ return event.preventDefault(), !1;
3314
+ if (!zoomScroll && !panOnScroll && !pinchZoom && event.type === "wheel" || !panOnDrag && (event.type === "mousedown" || event.type === "touchstart") || Array.isArray(panOnDrag) && !panOnDrag.includes(event.button) && event.type === "mousedown")
3295
3315
  return !1;
3296
3316
  const buttonAllowed = Array.isArray(panOnDrag) && panOnDrag.includes(event.button) || !event.button || event.button <= 1;
3297
3317
  return (!event.ctrlKey || event.type === "wheel") && buttonAllowed;
@@ -3672,7 +3692,7 @@ const defaultNodeOrigin = [0, 0], defaultViewport = { x: 0, y: 0, zoom: 1 }, rea
3672
3692
  "nodesConnectable",
3673
3693
  "nodesFocusable",
3674
3694
  "edgesFocusable",
3675
- "edgesUpdatable",
3695
+ "edgesReconnectable",
3676
3696
  "elevateNodesOnSelect",
3677
3697
  "elevateEdgesOnSelect",
3678
3698
  "minZoom",
@@ -3964,7 +3984,7 @@ function elementToRemoveChange(item) {
3964
3984
  type: "remove"
3965
3985
  };
3966
3986
  }
3967
- const isNode = (element2) => isNodeBase(element2);
3987
+ const isNode = (element2) => isNodeBase(element2), isEdge = (element2) => isEdgeBase(element2);
3968
3988
  function fixedForwardRef(render) {
3969
3989
  return forwardRef(render);
3970
3990
  }
@@ -4026,6 +4046,8 @@ function useReactFlow() {
4026
4046
  const viewportHelper = useViewportHelper(), store = useStoreApi(), batchContext = useBatchContext(), viewportInitialized = useStore(selector$m), generalHelper = useMemo(() => {
4027
4047
  const getInternalNode = (id2) => store.getState().nodeLookup.get(id2), setNodes = (payload) => {
4028
4048
  batchContext.nodeQueue.push(payload);
4049
+ }, setEdges = (payload) => {
4050
+ batchContext.edgeQueue.push(payload);
4029
4051
  }, getNodeRect = (node) => {
4030
4052
  var _a, _b;
4031
4053
  const { nodeLookup, nodeOrigin } = store.getState(), nodeToUse = isNode(node) ? node : nodeLookup.get(node.id), position = nodeToUse.parentId ? evaluateAbsolutePosition(nodeToUse.position, nodeToUse.parentId, nodeLookup, nodeOrigin) : nodeToUse.position, nodeWithPosition = {
@@ -4044,6 +4066,14 @@ function useReactFlow() {
4044
4066
  }
4045
4067
  return node;
4046
4068
  }));
4069
+ }, updateEdge = (id2, edgeUpdate, options = { replace: !1 }) => {
4070
+ setEdges((prevEdges) => prevEdges.map((edge) => {
4071
+ if (edge.id === id2) {
4072
+ const nextEdge = typeof edgeUpdate == "function" ? edgeUpdate(edge) : edgeUpdate;
4073
+ return options.replace && isEdge(nextEdge) ? nextEdge : { ...edge, ...nextEdge };
4074
+ }
4075
+ return edge;
4076
+ }));
4047
4077
  };
4048
4078
  return {
4049
4079
  getNodes: () => store.getState().nodes.map((n) => ({ ...n })),
@@ -4058,9 +4088,7 @@ function useReactFlow() {
4058
4088
  },
4059
4089
  getEdge: (id2) => store.getState().edgeLookup.get(id2),
4060
4090
  setNodes,
4061
- setEdges: (payload) => {
4062
- batchContext.edgeQueue.push(payload);
4063
- },
4091
+ setEdges,
4064
4092
  addNodes: (payload) => {
4065
4093
  const newNodes = Array.isArray(payload) ? payload : [payload];
4066
4094
  batchContext.nodeQueue.push((nodes) => [...nodes, ...newNodes]);
@@ -4122,6 +4150,13 @@ function useReactFlow() {
4122
4150
  const nextData = typeof dataUpdate == "function" ? dataUpdate(node) : dataUpdate;
4123
4151
  return options.replace ? { ...node, data: nextData } : { ...node, data: { ...node.data, ...nextData } };
4124
4152
  }, options);
4153
+ },
4154
+ updateEdge,
4155
+ updateEdgeData: (id2, dataUpdate, options = { replace: !1 }) => {
4156
+ updateEdge(id2, (edge) => {
4157
+ const nextData = typeof dataUpdate == "function" ? dataUpdate(edge) : dataUpdate;
4158
+ return options.replace ? { ...edge, data: nextData } : { ...edge, data: { ...edge.data, ...nextData } };
4159
+ }, options);
4125
4160
  }
4126
4161
  };
4127
4162
  }, []);
@@ -4131,9 +4166,9 @@ function useReactFlow() {
4131
4166
  viewportInitialized
4132
4167
  }), [viewportInitialized]);
4133
4168
  }
4134
- const selected = (item) => item.selected, deleteKeyOptions = { actInsideInputWithModifier: !1 };
4169
+ const selected = (item) => item.selected, deleteKeyOptions = { actInsideInputWithModifier: !1 }, win$1 = typeof window < "u" ? window : void 0;
4135
4170
  function useGlobalKeyHandler({ deleteKeyCode, multiSelectionKeyCode }) {
4136
- const store = useStoreApi(), { deleteElements } = useReactFlow(), deleteKeyPressed = useKeyPress(deleteKeyCode, deleteKeyOptions), multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode);
4171
+ const store = useStoreApi(), { deleteElements } = useReactFlow(), deleteKeyPressed = useKeyPress(deleteKeyCode, deleteKeyOptions), multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode, { target: win$1 });
4137
4172
  useEffect(() => {
4138
4173
  if (deleteKeyPressed) {
4139
4174
  const { edges, nodes } = store.getState();
@@ -4263,10 +4298,14 @@ const wrapHandler = (handler, containerRef) => (event) => {
4263
4298
  elementsSelectable: s.elementsSelectable,
4264
4299
  dragging: s.paneDragging
4265
4300
  });
4266
- function Pane({ isSelecting, selectionMode = SelectionMode.Full, panOnDrag, onSelectionStart, onSelectionEnd, onPaneClick, onPaneContextMenu, onPaneScroll, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, children: children2 }) {
4267
- const container2 = useRef(null), store = useStoreApi(), prevSelectedNodesCount = useRef(0), prevSelectedEdgesCount = useRef(0), containerBounds = useRef(), edgeIdLookup = useRef(/* @__PURE__ */ new Map()), { userSelectionActive, elementsSelectable, dragging } = useStore(selector$j, shallow), resetUserSelection = () => {
4301
+ function Pane({ isSelecting, selectionKeyPressed, selectionMode = SelectionMode.Full, panOnDrag, onSelectionStart, onSelectionEnd, onPaneClick, onPaneContextMenu, onPaneScroll, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, children: children2 }) {
4302
+ const container2 = useRef(null), store = useStoreApi(), prevSelectedNodesCount = useRef(0), prevSelectedEdgesCount = useRef(0), containerBounds = useRef(), edgeIdLookup = useRef(/* @__PURE__ */ new Map()), { userSelectionActive, elementsSelectable, dragging } = useStore(selector$j, shallow), hasActiveSelection = elementsSelectable && (isSelecting || userSelectionActive), selectionInProgress = useRef(!1), resetUserSelection = () => {
4268
4303
  store.setState({ userSelectionActive: !1, userSelectionRect: null }), prevSelectedNodesCount.current = 0, prevSelectedEdgesCount.current = 0;
4269
4304
  }, onClick = (event) => {
4305
+ if (selectionInProgress.current) {
4306
+ selectionInProgress.current = !1;
4307
+ return;
4308
+ }
4270
4309
  onPaneClick == null || onPaneClick(event), store.getState().resetSelectedElements(), store.setState({ nodesSelectionActive: !1 });
4271
4310
  }, onContextMenu = (event) => {
4272
4311
  if (Array.isArray(panOnDrag) && (panOnDrag != null && panOnDrag.includes(2))) {
@@ -4274,14 +4313,14 @@ function Pane({ isSelecting, selectionMode = SelectionMode.Full, panOnDrag, onSe
4274
4313
  return;
4275
4314
  }
4276
4315
  onPaneContextMenu == null || onPaneContextMenu(event);
4277
- }, onWheel = onPaneScroll ? (event) => onPaneScroll(event) : void 0, onMouseDown = (event) => {
4278
- var _a, _b;
4316
+ }, onWheel = onPaneScroll ? (event) => onPaneScroll(event) : void 0, onPointerDown2 = (event) => {
4317
+ var _a, _b, _c;
4279
4318
  const { resetSelectedElements, domNode, edgeLookup } = store.getState();
4280
- if (containerBounds.current = domNode == null ? void 0 : domNode.getBoundingClientRect(), !elementsSelectable || !isSelecting || event.button !== 0 || event.target !== container2.current || !containerBounds.current)
4319
+ if (containerBounds.current = domNode == null ? void 0 : domNode.getBoundingClientRect(), (_a = container2.current) == null || _a.setPointerCapture(event.pointerId), !elementsSelectable || !isSelecting || event.button !== 0 || event.target !== container2.current || !containerBounds.current)
4281
4320
  return;
4282
4321
  edgeIdLookup.current = /* @__PURE__ */ new Map();
4283
4322
  for (const [id2, edge] of edgeLookup)
4284
- edgeIdLookup.current.set(edge.source, ((_a = edgeIdLookup.current.get(edge.source)) == null ? void 0 : _a.add(id2)) || /* @__PURE__ */ new Set([id2])), edgeIdLookup.current.set(edge.target, ((_b = edgeIdLookup.current.get(edge.target)) == null ? void 0 : _b.add(id2)) || /* @__PURE__ */ new Set([id2]));
4323
+ edgeIdLookup.current.set(edge.source, ((_b = edgeIdLookup.current.get(edge.source)) == null ? void 0 : _b.add(id2)) || /* @__PURE__ */ new Set([id2])), edgeIdLookup.current.set(edge.target, ((_c = edgeIdLookup.current.get(edge.target)) == null ? void 0 : _c.add(id2)) || /* @__PURE__ */ new Set([id2]));
4285
4324
  const { x, y } = getEventPosition(event.nativeEvent, containerBounds.current);
4286
4325
  resetSelectedElements(), store.setState({
4287
4326
  userSelectionRect: {
@@ -4293,10 +4332,11 @@ function Pane({ isSelecting, selectionMode = SelectionMode.Full, panOnDrag, onSe
4293
4332
  y
4294
4333
  }
4295
4334
  }), onSelectionStart == null || onSelectionStart(event);
4296
- }, onMouseMove = (event) => {
4335
+ }, onPointerMove = (event) => {
4297
4336
  const { userSelectionRect, edgeLookup, transform: transform2, nodeOrigin, nodeLookup, triggerNodeChanges, triggerEdgeChanges } = store.getState();
4298
- if (!isSelecting || !containerBounds.current || !userSelectionRect)
4337
+ if (!containerBounds.current || !userSelectionRect)
4299
4338
  return;
4339
+ selectionInProgress.current = !0;
4300
4340
  const { x: mouseX, y: mouseY } = getEventPosition(event.nativeEvent, containerBounds.current), { startX, startY } = userSelectionRect, nextUserSelectRect = {
4301
4341
  startX,
4302
4342
  startY,
@@ -4327,15 +4367,15 @@ function Pane({ isSelecting, selectionMode = SelectionMode.Full, panOnDrag, onSe
4327
4367
  userSelectionActive: !0,
4328
4368
  nodesSelectionActive: !1
4329
4369
  });
4330
- }, onMouseUp = (event) => {
4370
+ }, onPointerUp = (event) => {
4371
+ var _a;
4331
4372
  if (event.button !== 0)
4332
4373
  return;
4374
+ (_a = container2.current) == null || _a.releasePointerCapture(event.pointerId);
4333
4375
  const { userSelectionRect } = store.getState();
4334
- !userSelectionActive && userSelectionRect && event.target === container2.current && (onClick == null || onClick(event)), store.setState({ nodesSelectionActive: prevSelectedNodesCount.current > 0 }), resetUserSelection(), onSelectionEnd == null || onSelectionEnd(event);
4335
- }, onMouseLeave = (event) => {
4336
- userSelectionActive && (store.setState({ nodesSelectionActive: prevSelectedNodesCount.current > 0 }), onSelectionEnd == null || onSelectionEnd(event)), resetUserSelection();
4337
- }, hasActiveSelection = elementsSelectable && (isSelecting || userSelectionActive);
4338
- return jsxs("div", { className: cc(["react-flow__pane", { draggable: panOnDrag, dragging, selection: isSelecting }]), onClick: hasActiveSelection ? void 0 : wrapHandler(onClick, container2), onContextMenu: wrapHandler(onContextMenu, container2), onWheel: wrapHandler(onWheel, container2), onMouseEnter: hasActiveSelection ? void 0 : onPaneMouseEnter, onMouseDown: hasActiveSelection ? onMouseDown : void 0, onMouseMove: hasActiveSelection ? onMouseMove : onPaneMouseMove, onMouseUp: hasActiveSelection ? onMouseUp : void 0, onMouseLeave: hasActiveSelection ? onMouseLeave : onPaneMouseLeave, ref: container2, style: containerStyle, children: [children2, jsx(UserSelection, {})] });
4376
+ !userSelectionActive && userSelectionRect && event.target === container2.current && (onClick == null || onClick(event)), store.setState({ nodesSelectionActive: prevSelectedNodesCount.current > 0 }), resetUserSelection(), onSelectionEnd == null || onSelectionEnd(event), selectionKeyPressed && (selectionInProgress.current = !1);
4377
+ };
4378
+ return jsxs("div", { className: cc(["react-flow__pane", { draggable: panOnDrag, dragging, selection: isSelecting }]), onClick: hasActiveSelection ? void 0 : wrapHandler(onClick, container2), onContextMenu: wrapHandler(onContextMenu, container2), onWheel: wrapHandler(onWheel, container2), onPointerEnter: hasActiveSelection ? void 0 : onPaneMouseEnter, onPointerDown: hasActiveSelection ? onPointerDown2 : onPaneMouseMove, onPointerMove: hasActiveSelection ? onPointerMove : onPaneMouseMove, onPointerUp: hasActiveSelection ? onPointerUp : void 0, onPointerLeave: onPaneMouseLeave, ref: container2, style: containerStyle, children: [children2, jsx(UserSelection, {})] });
4339
4379
  }
4340
4380
  function handleNodeClick({ id: id2, store, unselect = !1, nodeRef }) {
4341
4381
  const { addSelectedNodes, unselectNodesAndEdges, multiSelectionActive, nodeLookup, onError } = store.getState(), node = nodeLookup.get(id2);
@@ -4590,10 +4630,10 @@ function NodesSelection({ onSelectionContextMenu, noPanClassName, disableKeyboar
4590
4630
  height
4591
4631
  } }) });
4592
4632
  }
4593
- const selector$g = (s) => ({ nodesSelectionActive: s.nodesSelectionActive, userSelectionActive: s.userSelectionActive });
4633
+ const win = typeof window < "u" ? window : void 0, selector$g = (s) => ({ nodesSelectionActive: s.nodesSelectionActive, userSelectionActive: s.userSelectionActive });
4594
4634
  function FlowRendererComponent({ children: children2, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneContextMenu, onPaneScroll, deleteKeyCode, selectionKeyCode, selectionOnDrag, selectionMode, onSelectionStart, onSelectionEnd, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, elementsSelectable, zoomOnScroll, zoomOnPinch, panOnScroll: _panOnScroll, panOnScrollSpeed, panOnScrollMode, zoomOnDoubleClick, panOnDrag: _panOnDrag, defaultViewport: defaultViewport2, translateExtent, minZoom, maxZoom, preventScrolling, onSelectionContextMenu, noWheelClassName, noPanClassName, disableKeyboardA11y, onViewportChange, isControlledViewport }) {
4595
- const { nodesSelectionActive, userSelectionActive } = useStore(selector$g), selectionKeyPressed = useKeyPress(selectionKeyCode), panActivationKeyPressed = useKeyPress(panActivationKeyCode), panOnDrag = panActivationKeyPressed || _panOnDrag, panOnScroll = panActivationKeyPressed || _panOnScroll, isSelecting = selectionKeyPressed || userSelectionActive || selectionOnDrag && panOnDrag !== !0;
4596
- return useGlobalKeyHandler({ deleteKeyCode, multiSelectionKeyCode }), jsx(ZoomPane, { onPaneContextMenu, elementsSelectable, zoomOnScroll, zoomOnPinch, panOnScroll, panOnScrollSpeed, panOnScrollMode, zoomOnDoubleClick, panOnDrag: !selectionKeyPressed && panOnDrag, defaultViewport: defaultViewport2, translateExtent, minZoom, maxZoom, zoomActivationKeyCode, preventScrolling, noWheelClassName, noPanClassName, onViewportChange, isControlledViewport, children: jsxs(Pane, { onSelectionStart, onSelectionEnd, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneContextMenu, onPaneScroll, panOnDrag, isSelecting: !!isSelecting, selectionMode, children: [children2, nodesSelectionActive && jsx(NodesSelection, { onSelectionContextMenu, noPanClassName, disableKeyboardA11y })] }) });
4635
+ const { nodesSelectionActive, userSelectionActive } = useStore(selector$g), selectionKeyPressed = useKeyPress(selectionKeyCode, { target: win }), panActivationKeyPressed = useKeyPress(panActivationKeyCode, { target: win }), panOnDrag = panActivationKeyPressed || _panOnDrag, panOnScroll = panActivationKeyPressed || _panOnScroll, isSelecting = selectionKeyPressed || userSelectionActive || selectionOnDrag && panOnDrag !== !0;
4636
+ return useGlobalKeyHandler({ deleteKeyCode, multiSelectionKeyCode }), jsx(ZoomPane, { onPaneContextMenu, elementsSelectable, zoomOnScroll, zoomOnPinch, panOnScroll, panOnScrollSpeed, panOnScrollMode, zoomOnDoubleClick, panOnDrag: !selectionKeyPressed && panOnDrag, defaultViewport: defaultViewport2, translateExtent, minZoom, maxZoom, zoomActivationKeyCode, preventScrolling, noWheelClassName, noPanClassName, onViewportChange, isControlledViewport, children: jsxs(Pane, { onSelectionStart, onSelectionEnd, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneContextMenu, onPaneScroll, panOnDrag, isSelecting: !!isSelecting, selectionMode, selectionKeyPressed, children: [children2, nodesSelectionActive && jsx(NodesSelection, { onSelectionContextMenu, noPanClassName, disableKeyboardA11y })] }) });
4597
4637
  }
4598
4638
  FlowRendererComponent.displayName = "FlowRenderer";
4599
4639
  const FlowRenderer = memo(FlowRendererComponent), selector$f = (onlyRenderVisible) => (s) => onlyRenderVisible ? getNodesInside(s.nodeLookup, { x: 0, y: 0, width: s.width, height: s.height }, s.transform, !0).map((node) => node.id) : Array.from(s.nodeLookup.keys());
@@ -4608,7 +4648,8 @@ function useResizeObserver() {
4608
4648
  const id2 = entry.target.getAttribute("data-id");
4609
4649
  updates.set(id2, {
4610
4650
  id: id2,
4611
- nodeElement: entry.target
4651
+ nodeElement: entry.target,
4652
+ force: !0
4612
4653
  });
4613
4654
  }), updateNodeInternals2(updates);
4614
4655
  }));
@@ -4617,10 +4658,10 @@ function useResizeObserver() {
4617
4658
  }, [resizeObserver]), resizeObserver;
4618
4659
  }
4619
4660
  function useNodeObserver({ node, nodeType, hasDimensions, resizeObserver }) {
4620
- const store = useStoreApi(), nodeRef = useRef(null), observedNode = useRef(null), prevSourcePosition = useRef(node.sourcePosition), prevTargetPosition = useRef(node.targetPosition), prevType = useRef(nodeType), isInitialized = hasDimensions && !!node.internals.handleBounds && !node.hidden;
4661
+ const store = useStoreApi(), nodeRef = useRef(null), observedNode = useRef(null), prevSourcePosition = useRef(node.sourcePosition), prevTargetPosition = useRef(node.targetPosition), prevType = useRef(nodeType), isInitialized = hasDimensions && !!node.internals.handleBounds;
4621
4662
  return useEffect(() => {
4622
- nodeRef.current && (!isInitialized || observedNode.current !== nodeRef.current) && (observedNode.current && (resizeObserver == null || resizeObserver.unobserve(observedNode.current)), resizeObserver == null || resizeObserver.observe(nodeRef.current), observedNode.current = nodeRef.current);
4623
- }, [isInitialized]), useEffect(() => () => {
4663
+ nodeRef.current && !node.hidden && (!isInitialized || observedNode.current !== nodeRef.current) && (observedNode.current && (resizeObserver == null || resizeObserver.unobserve(observedNode.current)), resizeObserver == null || resizeObserver.observe(nodeRef.current), observedNode.current = nodeRef.current);
4664
+ }, [isInitialized, node.hidden]), useEffect(() => () => {
4624
4665
  observedNode.current && (resizeObserver == null || resizeObserver.unobserve(observedNode.current), observedNode.current = null);
4625
4666
  }, []), useEffect(() => {
4626
4667
  if (nodeRef.current) {
@@ -4700,7 +4741,7 @@ function NodeWrapper({ id: id2, onClick, onMouseEnter, onMouseMove, onMouseLeave
4700
4741
  visibility: hasDimensions ? "visible" : "hidden",
4701
4742
  ...node.style,
4702
4743
  ...inlineDimensions
4703
- }, "data-id": id2, "data-testid": `rf__node-${id2}`, onMouseEnter: onMouseEnterHandler, onMouseMove: onMouseMoveHandler, onMouseLeave: onMouseLeaveHandler, onContextMenu: onContextMenuHandler, onClick: onSelectNodeHandler, onDoubleClick: onDoubleClickHandler, onKeyDown: isFocusable ? onKeyDown : void 0, tabIndex: isFocusable ? 0 : void 0, role: isFocusable ? "button" : void 0, "aria-describedby": disableKeyboardA11y ? void 0 : `${ARIA_NODE_DESC_KEY}-${rfId}`, "aria-label": node.ariaLabel, children: jsx(Provider, { value: id2, children: jsx(NodeComponent, { id: id2, data: node.data, type: nodeType, positionAbsoluteX: clampedPosition.x, positionAbsoluteY: clampedPosition.y, selected: node.selected, isConnectable, sourcePosition: node.sourcePosition, targetPosition: node.targetPosition, dragging, dragHandle: node.dragHandle, zIndex: internals.z, ...nodeDimensions }) }) });
4744
+ }, "data-id": id2, "data-testid": `rf__node-${id2}`, onMouseEnter: onMouseEnterHandler, onMouseMove: onMouseMoveHandler, onMouseLeave: onMouseLeaveHandler, onContextMenu: onContextMenuHandler, onClick: onSelectNodeHandler, onDoubleClick: onDoubleClickHandler, onKeyDown: isFocusable ? onKeyDown : void 0, tabIndex: isFocusable ? 0 : void 0, role: isFocusable ? "button" : void 0, "aria-describedby": disableKeyboardA11y ? void 0 : `${ARIA_NODE_DESC_KEY}-${rfId}`, "aria-label": node.ariaLabel, children: jsx(Provider, { value: id2, children: jsx(NodeComponent, { id: id2, data: node.data, type: nodeType, positionAbsoluteX: clampedPosition.x, positionAbsoluteY: clampedPosition.y, selected: node.selected, selectable: isSelectable, draggable: isDraggable, deletable: node.deletable ?? !0, isConnectable, sourcePosition: node.sourcePosition, targetPosition: node.targetPosition, dragging, dragHandle: node.dragHandle, zIndex: internals.z, parentId: node.parentId, ...nodeDimensions }) }) });
4704
4745
  }
4705
4746
  const selector$d = (s) => ({
4706
4747
  nodesDraggable: s.nodesDraggable,
@@ -4792,18 +4833,18 @@ const Marker = ({ id: id2, type, color: color2, width = 12.5, height = 12.5, mar
4792
4833
  MarkerDefinitions.displayName = "MarkerDefinitions";
4793
4834
  var MarkerDefinitions$1 = memo(MarkerDefinitions);
4794
4835
  function EdgeTextComponent({ x, y, label, labelStyle = {}, labelShowBg = !0, labelBgStyle = {}, labelBgPadding = [2, 4], labelBgBorderRadius = 2, children: children2, className, ...rest }) {
4795
- const [edgeTextBbox, setEdgeTextBbox] = useState({ x: 1, y: 0, width: 0, height: 0 }), edgeTextClasses = cc(["react-flow__edge-textwrapper", className]), onEdgeTextRefChange = useCallback((edgeRef) => {
4796
- if (edgeRef === null)
4797
- return;
4798
- const textBbox = edgeRef.getBBox();
4799
- setEdgeTextBbox({
4800
- x: textBbox.x,
4801
- y: textBbox.y,
4802
- width: textBbox.width,
4803
- height: textBbox.height
4804
- });
4805
- }, []);
4806
- return typeof label > "u" || !label ? null : jsxs("g", { transform: `translate(${x - edgeTextBbox.width / 2} ${y - edgeTextBbox.height / 2})`, className: edgeTextClasses, visibility: edgeTextBbox.width ? "visible" : "hidden", ...rest, children: [labelShowBg && jsx("rect", { width: edgeTextBbox.width + 2 * labelBgPadding[0], x: -labelBgPadding[0], y: -labelBgPadding[1], height: edgeTextBbox.height + 2 * labelBgPadding[1], className: "react-flow__edge-textbg", style: labelBgStyle, rx: labelBgBorderRadius, ry: labelBgBorderRadius }), jsx("text", { className: "react-flow__edge-text", y: edgeTextBbox.height / 2, dy: "0.3em", ref: onEdgeTextRefChange, style: labelStyle, children: label }), children2] });
4836
+ const [edgeTextBbox, setEdgeTextBbox] = useState({ x: 1, y: 0, width: 0, height: 0 }), edgeTextClasses = cc(["react-flow__edge-textwrapper", className]), edgeTextRef = useRef(null);
4837
+ return useEffect(() => {
4838
+ if (edgeTextRef.current) {
4839
+ const textBbox = edgeTextRef.current.getBBox();
4840
+ setEdgeTextBbox({
4841
+ x: textBbox.x,
4842
+ y: textBbox.y,
4843
+ width: textBbox.width,
4844
+ height: textBbox.height
4845
+ });
4846
+ }
4847
+ }, [label]), typeof label > "u" || !label ? null : jsxs("g", { transform: `translate(${x - edgeTextBbox.width / 2} ${y - edgeTextBbox.height / 2})`, className: edgeTextClasses, visibility: edgeTextBbox.width ? "visible" : "hidden", ...rest, children: [labelShowBg && jsx("rect", { width: edgeTextBbox.width + 2 * labelBgPadding[0], x: -labelBgPadding[0], y: -labelBgPadding[1], height: edgeTextBbox.height + 2 * labelBgPadding[1], className: "react-flow__edge-textbg", style: labelBgStyle, rx: labelBgBorderRadius, ry: labelBgBorderRadius }), jsx("text", { className: "react-flow__edge-text", y: edgeTextBbox.height / 2, dy: "0.3em", ref: edgeTextRef, style: labelStyle, children: label }), children2] });
4807
4848
  }
4808
4849
  EdgeTextComponent.displayName = "EdgeText";
4809
4850
  const EdgeText = memo(EdgeTextComponent);
@@ -4934,15 +4975,15 @@ const builtinEdgeTypes = {
4934
4975
  function EdgeAnchor({ position, centerX, centerY, radius = 10, onMouseDown, onMouseEnter, onMouseOut, type }) {
4935
4976
  return jsx("circle", { onMouseDown, onMouseEnter, onMouseOut, className: cc([EdgeUpdaterClassName, `${EdgeUpdaterClassName}-${type}`]), cx: shiftX(centerX, radius, position), cy: shiftY(centerY, radius, position), r: radius, stroke: "transparent", fill: "transparent" });
4936
4977
  }
4937
- function EdgeUpdateAnchors({ isUpdatable, edgeUpdaterRadius, edge, targetHandleId, sourceHandleId, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, setUpdating, setUpdateHover }) {
4978
+ function EdgeUpdateAnchors({ isReconnectable, reconnectRadius, edge, targetHandleId, sourceHandleId, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, onReconnect, onReconnectStart, onReconnectEnd, setReconnecting, setUpdateHover }) {
4938
4979
  const store = useStoreApi(), handleEdgeUpdater = (event, isSourceHandle) => {
4939
4980
  if (event.button !== 0)
4940
4981
  return;
4941
4982
  const { autoPanOnConnect, domNode, isValidConnection, connectionMode, connectionRadius, lib, onConnectStart, onConnectEnd, cancelConnection, nodeLookup, rfId: flowId, panBy: panBy2, updateConnection } = store.getState(), nodeId = isSourceHandle ? edge.target : edge.source, handleId = (isSourceHandle ? targetHandleId : sourceHandleId) || null, handleType = isSourceHandle ? "target" : "source", isTarget = isSourceHandle;
4942
- setUpdating(!0), onEdgeUpdateStart == null || onEdgeUpdateStart(event, edge, handleType);
4943
- const _onEdgeUpdateEnd = (evt) => {
4944
- setUpdating(!1), onEdgeUpdateEnd == null || onEdgeUpdateEnd(evt, edge, handleType);
4945
- }, onConnectEdge = (connection) => onEdgeUpdate == null ? void 0 : onEdgeUpdate(edge, connection);
4983
+ setReconnecting(!0), onReconnectStart == null || onReconnectStart(event, edge, handleType);
4984
+ const _onReconnectEnd = (evt) => {
4985
+ setReconnecting(!1), onReconnectEnd == null || onReconnectEnd(evt, edge, handleType);
4986
+ }, onConnectEdge = (connection) => onReconnect == null ? void 0 : onReconnect(edge, connection);
4946
4987
  XYHandle.onPointerDown(event.nativeEvent, {
4947
4988
  autoPanOnConnect,
4948
4989
  connectionMode,
@@ -4961,21 +5002,21 @@ function EdgeUpdateAnchors({ isUpdatable, edgeUpdaterRadius, edge, targetHandleI
4961
5002
  onConnect: onConnectEdge,
4962
5003
  onConnectStart,
4963
5004
  onConnectEnd,
4964
- onEdgeUpdateEnd: _onEdgeUpdateEnd,
5005
+ onReconnectEnd: _onReconnectEnd,
4965
5006
  updateConnection,
4966
5007
  getTransform: () => store.getState().transform,
4967
5008
  getConnectionStartHandle: () => store.getState().connectionStartHandle
4968
5009
  });
4969
- }, onEdgeUpdaterSourceMouseDown = (event) => handleEdgeUpdater(event, !0), onEdgeUpdaterTargetMouseDown = (event) => handleEdgeUpdater(event, !1), onEdgeUpdaterMouseEnter = () => setUpdateHover(!0), onEdgeUpdaterMouseOut = () => setUpdateHover(!1);
4970
- return jsxs(Fragment, { children: [(isUpdatable === "source" || isUpdatable === !0) && jsx(EdgeAnchor, { position: sourcePosition, centerX: sourceX, centerY: sourceY, radius: edgeUpdaterRadius, onMouseDown: onEdgeUpdaterSourceMouseDown, onMouseEnter: onEdgeUpdaterMouseEnter, onMouseOut: onEdgeUpdaterMouseOut, type: "source" }), (isUpdatable === "target" || isUpdatable === !0) && jsx(EdgeAnchor, { position: targetPosition, centerX: targetX, centerY: targetY, radius: edgeUpdaterRadius, onMouseDown: onEdgeUpdaterTargetMouseDown, onMouseEnter: onEdgeUpdaterMouseEnter, onMouseOut: onEdgeUpdaterMouseOut, type: "target" })] });
5010
+ }, onReconnectSourceMouseDown = (event) => handleEdgeUpdater(event, !0), onReconnectTargetMouseDown = (event) => handleEdgeUpdater(event, !1), onReconnectMouseEnter = () => setUpdateHover(!0), onReconnectMouseOut = () => setUpdateHover(!1);
5011
+ return jsxs(Fragment, { children: [(isReconnectable === "source" || isReconnectable === !0) && jsx(EdgeAnchor, { position: sourcePosition, centerX: sourceX, centerY: sourceY, radius: reconnectRadius, onMouseDown: onReconnectSourceMouseDown, onMouseEnter: onReconnectMouseEnter, onMouseOut: onReconnectMouseOut, type: "source" }), (isReconnectable === "target" || isReconnectable === !0) && jsx(EdgeAnchor, { position: targetPosition, centerX: targetX, centerY: targetY, radius: reconnectRadius, onMouseDown: onReconnectTargetMouseDown, onMouseEnter: onReconnectMouseEnter, onMouseOut: onReconnectMouseOut, type: "target" })] });
4971
5012
  }
4972
- function EdgeWrapper({ id: id2, edgesFocusable, edgesUpdatable, elementsSelectable, onClick, onDoubleClick, onContextMenu, onMouseEnter, onMouseMove, onMouseLeave, edgeUpdaterRadius, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, rfId, edgeTypes: edgeTypes2, noPanClassName, onError, disableKeyboardA11y }) {
5013
+ function EdgeWrapper({ id: id2, edgesFocusable, edgesReconnectable, elementsSelectable, onClick, onDoubleClick, onContextMenu, onMouseEnter, onMouseMove, onMouseLeave, reconnectRadius, onReconnect, onReconnectStart, onReconnectEnd, rfId, edgeTypes: edgeTypes2, noPanClassName, onError, disableKeyboardA11y }) {
4973
5014
  let edge = useStore((s) => s.edgeLookup.get(id2));
4974
5015
  const defaultEdgeOptions = useStore((s) => s.defaultEdgeOptions);
4975
5016
  edge = defaultEdgeOptions ? { ...defaultEdgeOptions, ...edge } : edge;
4976
5017
  let edgeType = edge.type || "default", EdgeComponent = (edgeTypes2 == null ? void 0 : edgeTypes2[edgeType]) || builtinEdgeTypes[edgeType];
4977
5018
  EdgeComponent === void 0 && (onError == null || onError("011", errorMessages.error011(edgeType)), edgeType = "default", EdgeComponent = builtinEdgeTypes.default);
4978
- const isFocusable = !!(edge.focusable || edgesFocusable && typeof edge.focusable > "u"), isUpdatable = typeof onEdgeUpdate < "u" && (edge.updatable || edgesUpdatable && typeof edge.updatable > "u"), isSelectable = !!(edge.selectable || elementsSelectable && typeof edge.selectable > "u"), edgeRef = useRef(null), [updateHover, setUpdateHover] = useState(!1), [updating, setUpdating] = useState(!1), store = useStoreApi(), { zIndex, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition } = useStore(useCallback((store2) => {
5019
+ const isFocusable = !!(edge.focusable || edgesFocusable && typeof edge.focusable > "u"), isReconnectable = typeof onReconnect < "u" && (edge.reconnectable || edgesReconnectable && typeof edge.reconnectable > "u"), isSelectable = !!(edge.selectable || elementsSelectable && typeof edge.selectable > "u"), edgeRef = useRef(null), [updateHover, setUpdateHover] = useState(!1), [reconnecting, setReconnecting] = useState(!1), store = useStoreApi(), { zIndex, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition } = useStore(useCallback((store2) => {
4979
5020
  const sourceNode = store2.nodeLookup.get(edge.source), targetNode = store2.nodeLookup.get(edge.target);
4980
5021
  if (!sourceNode || !targetNode)
4981
5022
  return {
@@ -5037,20 +5078,20 @@ function EdgeWrapper({ id: id2, edgesFocusable, edgesUpdatable, elementsSelectab
5037
5078
  updating: updateHover,
5038
5079
  selectable: isSelectable
5039
5080
  }
5040
- ]), onClick: onEdgeClick, onDoubleClick: onEdgeDoubleClick, onContextMenu: onEdgeContextMenu, onMouseEnter: onEdgeMouseEnter, onMouseMove: onEdgeMouseMove, onMouseLeave: onEdgeMouseLeave, onKeyDown: isFocusable ? onKeyDown : void 0, tabIndex: isFocusable ? 0 : void 0, role: isFocusable ? "button" : "img", "data-id": id2, "data-testid": `rf__edge-${id2}`, "aria-label": edge.ariaLabel === null ? void 0 : edge.ariaLabel || `Edge from ${edge.source} to ${edge.target}`, "aria-describedby": isFocusable ? `${ARIA_EDGE_DESC_KEY}-${rfId}` : void 0, ref: edgeRef, children: [!updating && jsx(EdgeComponent, { id: id2, source: edge.source, target: edge.target, type: edge.type, selected: edge.selected, animated: edge.animated, label: edge.label, labelStyle: edge.labelStyle, labelShowBg: edge.labelShowBg, labelBgStyle: edge.labelBgStyle, labelBgPadding: edge.labelBgPadding, labelBgBorderRadius: edge.labelBgBorderRadius, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data: edge.data, style: edge.style, sourceHandleId: edge.sourceHandle, targetHandleId: edge.targetHandle, markerStart: markerStartUrl, markerEnd: markerEndUrl, pathOptions: "pathOptions" in edge ? edge.pathOptions : void 0, interactionWidth: edge.interactionWidth }), isUpdatable && jsx(EdgeUpdateAnchors, { edge, isUpdatable, edgeUpdaterRadius, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, setUpdateHover, setUpdating, sourceHandleId: edge.sourceHandle, targetHandleId: edge.targetHandle })] }) });
5081
+ ]), onClick: onEdgeClick, onDoubleClick: onEdgeDoubleClick, onContextMenu: onEdgeContextMenu, onMouseEnter: onEdgeMouseEnter, onMouseMove: onEdgeMouseMove, onMouseLeave: onEdgeMouseLeave, onKeyDown: isFocusable ? onKeyDown : void 0, tabIndex: isFocusable ? 0 : void 0, role: isFocusable ? "button" : "img", "data-id": id2, "data-testid": `rf__edge-${id2}`, "aria-label": edge.ariaLabel === null ? void 0 : edge.ariaLabel || `Edge from ${edge.source} to ${edge.target}`, "aria-describedby": isFocusable ? `${ARIA_EDGE_DESC_KEY}-${rfId}` : void 0, ref: edgeRef, children: [!reconnecting && jsx(EdgeComponent, { id: id2, source: edge.source, target: edge.target, type: edge.type, selected: edge.selected, animated: edge.animated, selectable: isSelectable, deletable: edge.deletable ?? !0, label: edge.label, labelStyle: edge.labelStyle, labelShowBg: edge.labelShowBg, labelBgStyle: edge.labelBgStyle, labelBgPadding: edge.labelBgPadding, labelBgBorderRadius: edge.labelBgBorderRadius, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data: edge.data, style: edge.style, sourceHandleId: edge.sourceHandle, targetHandleId: edge.targetHandle, markerStart: markerStartUrl, markerEnd: markerEndUrl, pathOptions: "pathOptions" in edge ? edge.pathOptions : void 0, interactionWidth: edge.interactionWidth }), isReconnectable && jsx(EdgeUpdateAnchors, { edge, isReconnectable, reconnectRadius, onReconnect, onReconnectStart, onReconnectEnd, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, setUpdateHover, setReconnecting, sourceHandleId: edge.sourceHandle, targetHandleId: edge.targetHandle })] }) });
5041
5082
  }
5042
5083
  const selector$c = (s) => ({
5043
5084
  width: s.width,
5044
5085
  height: s.height,
5045
5086
  edgesFocusable: s.edgesFocusable,
5046
- edgesUpdatable: s.edgesUpdatable,
5087
+ edgesReconnectable: s.edgesReconnectable,
5047
5088
  elementsSelectable: s.elementsSelectable,
5048
5089
  connectionMode: s.connectionMode,
5049
5090
  onError: s.onError
5050
5091
  });
5051
- function EdgeRendererComponent({ defaultMarkerColor, onlyRenderVisibleElements, rfId, edgeTypes: edgeTypes2, noPanClassName, onEdgeUpdate, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeClick, edgeUpdaterRadius, onEdgeDoubleClick, onEdgeUpdateStart, onEdgeUpdateEnd, disableKeyboardA11y }) {
5052
- const { edgesFocusable, edgesUpdatable, elementsSelectable, onError } = useStore(selector$c, shallow), edgeIds = useVisibleEdgeIds(onlyRenderVisibleElements);
5053
- return jsxs("div", { className: "react-flow__edges", children: [jsx(MarkerDefinitions$1, { defaultColor: defaultMarkerColor, rfId }), edgeIds.map((id2) => jsx(EdgeWrapper, { id: id2, edgesFocusable, edgesUpdatable, elementsSelectable, noPanClassName, onEdgeUpdate, onContextMenu: onEdgeContextMenu, onMouseEnter: onEdgeMouseEnter, onMouseMove: onEdgeMouseMove, onMouseLeave: onEdgeMouseLeave, onClick: onEdgeClick, edgeUpdaterRadius, onDoubleClick: onEdgeDoubleClick, onEdgeUpdateStart, onEdgeUpdateEnd, rfId, onError, edgeTypes: edgeTypes2, disableKeyboardA11y }, id2))] });
5092
+ function EdgeRendererComponent({ defaultMarkerColor, onlyRenderVisibleElements, rfId, edgeTypes: edgeTypes2, noPanClassName, onReconnect, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeClick, reconnectRadius, onEdgeDoubleClick, onReconnectStart, onReconnectEnd, disableKeyboardA11y }) {
5093
+ const { edgesFocusable, edgesReconnectable, elementsSelectable, onError } = useStore(selector$c, shallow), edgeIds = useVisibleEdgeIds(onlyRenderVisibleElements);
5094
+ return jsxs("div", { className: "react-flow__edges", children: [jsx(MarkerDefinitions$1, { defaultColor: defaultMarkerColor, rfId }), edgeIds.map((id2) => jsx(EdgeWrapper, { id: id2, edgesFocusable, edgesReconnectable, elementsSelectable, noPanClassName, onReconnect, onContextMenu: onEdgeContextMenu, onMouseEnter: onEdgeMouseEnter, onMouseMove: onEdgeMouseMove, onMouseLeave: onEdgeMouseLeave, onClick: onEdgeClick, reconnectRadius, onDoubleClick: onEdgeDoubleClick, onReconnectStart, onReconnectEnd, rfId, onError, edgeTypes: edgeTypes2, disableKeyboardA11y }, id2))] });
5054
5095
  }
5055
5096
  EdgeRendererComponent.displayName = "EdgeRenderer";
5056
5097
  const EdgeRenderer = memo(EdgeRendererComponent), selector$b = (s) => `translate(${s.transform[0]}px,${s.transform[1]}px) scale(${s.transform[2]})`;
@@ -5080,20 +5121,22 @@ const oppositePosition = {
5080
5121
  [Position.Top]: Position.Bottom,
5081
5122
  [Position.Bottom]: Position.Top
5082
5123
  }, ConnectionLine = ({ nodeId, handleType, style: style2, type = ConnectionLineType.Bezier, CustomComponent, connectionStatus }) => {
5083
- const { fromNode, handleId, toX, toY, connectionMode } = useStore(useCallback((s) => {
5084
- var _a;
5124
+ const { fromNode, handleId, toX, toY, connectionMode, endPosition, isValid } = useStore(useCallback((s) => {
5125
+ var _a, _b;
5085
5126
  return {
5086
5127
  fromNode: s.nodeLookup.get(nodeId),
5087
5128
  handleId: (_a = s.connectionStartHandle) == null ? void 0 : _a.handleId,
5088
5129
  toX: (s.connectionPosition.x - s.transform[0]) / s.transform[2],
5089
5130
  toY: (s.connectionPosition.y - s.transform[1]) / s.transform[2],
5090
- connectionMode: s.connectionMode
5131
+ connectionMode: s.connectionMode,
5132
+ endPosition: (_b = s.connectionEndHandle) == null ? void 0 : _b.position,
5133
+ isValid: s.connectionStatus === "valid"
5091
5134
  };
5092
5135
  }, [nodeId]), shallow), fromHandleBounds = fromNode == null ? void 0 : fromNode.internals.handleBounds;
5093
5136
  let handleBounds = fromHandleBounds == null ? void 0 : fromHandleBounds[handleType];
5094
5137
  if (connectionMode === ConnectionMode.Loose && (handleBounds = handleBounds || (fromHandleBounds == null ? void 0 : fromHandleBounds[handleType === "source" ? "target" : "source"])), !fromNode || !handleBounds)
5095
5138
  return null;
5096
- const fromHandle = handleId ? handleBounds.find((d) => d.id === handleId) : handleBounds[0], fromHandleX = fromHandle ? fromHandle.x + fromHandle.width / 2 : (fromNode.measured.width ?? 0) / 2, fromHandleY = fromHandle ? fromHandle.y + fromHandle.height / 2 : fromNode.measured.height ?? 0, fromX = fromNode.internals.positionAbsolute.x + fromHandleX, fromY = fromNode.internals.positionAbsolute.y + fromHandleY, fromPosition = fromHandle == null ? void 0 : fromHandle.position, toPosition = fromPosition ? oppositePosition[fromPosition] : null;
5139
+ const fromHandle = handleId ? handleBounds.find((d) => d.id === handleId) : handleBounds[0], fromHandleX = fromHandle ? fromHandle.x + fromHandle.width / 2 : (fromNode.measured.width ?? 0) / 2, fromHandleY = fromHandle ? fromHandle.y + fromHandle.height / 2 : fromNode.measured.height ?? 0, fromX = fromNode.internals.positionAbsolute.x + fromHandleX, fromY = fromNode.internals.positionAbsolute.y + fromHandleY, fromPosition = fromHandle == null ? void 0 : fromHandle.position, toPosition = isValid && endPosition ? endPosition : fromPosition ? oppositePosition[fromPosition] : null;
5097
5140
  if (!fromPosition || !toPosition)
5098
5141
  return null;
5099
5142
  if (CustomComponent)
@@ -5137,8 +5180,8 @@ function useStylesLoadedWarning() {
5137
5180
  useStoreApi(), useRef(!1), useEffect(() => {
5138
5181
  }, []);
5139
5182
  }
5140
- function GraphViewComponent({ nodeTypes: nodeTypes2, edgeTypes: edgeTypes2, onInit, onNodeClick, onEdgeClick, onNodeDoubleClick, onEdgeDoubleClick, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onSelectionContextMenu, onSelectionStart, onSelectionEnd, connectionLineType, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, selectionKeyCode, selectionOnDrag, selectionMode, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, deleteKeyCode, onlyRenderVisibleElements, elementsSelectable, defaultViewport: defaultViewport2, translateExtent, minZoom, maxZoom, preventScrolling, defaultMarkerColor, zoomOnScroll, zoomOnPinch, panOnScroll, panOnScrollSpeed, panOnScrollMode, zoomOnDoubleClick, panOnDrag, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, onEdgeUpdate, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, edgeUpdaterRadius, onEdgeUpdateStart, onEdgeUpdateEnd, noDragClassName, noWheelClassName, noPanClassName, disableKeyboardA11y, nodeOrigin, nodeExtent, rfId, viewport, onViewportChange }) {
5141
- return useNodeOrEdgeTypesWarning(nodeTypes2), useNodeOrEdgeTypesWarning(edgeTypes2), useStylesLoadedWarning(), useOnInitHandler(onInit), useViewportSync(viewport), jsx(FlowRenderer, { onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneContextMenu, onPaneScroll, deleteKeyCode, selectionKeyCode, selectionOnDrag, selectionMode, onSelectionStart, onSelectionEnd, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, elementsSelectable, zoomOnScroll, zoomOnPinch, zoomOnDoubleClick, panOnScroll, panOnScrollSpeed, panOnScrollMode, panOnDrag, defaultViewport: defaultViewport2, translateExtent, minZoom, maxZoom, onSelectionContextMenu, preventScrolling, noDragClassName, noWheelClassName, noPanClassName, disableKeyboardA11y, onViewportChange, isControlledViewport: !!viewport, children: jsxs(Viewport, { children: [jsx(EdgeRenderer, { edgeTypes: edgeTypes2, onEdgeClick, onEdgeDoubleClick, onEdgeUpdate, onlyRenderVisibleElements, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdateStart, onEdgeUpdateEnd, edgeUpdaterRadius, defaultMarkerColor, noPanClassName, disableKeyboardA11y, rfId }), jsx(ConnectionLineWrapper, { style: connectionLineStyle, type: connectionLineType, component: connectionLineComponent, containerStyle: connectionLineContainerStyle }), jsx("div", { className: "react-flow__edgelabel-renderer" }), jsx(NodeRenderer, { nodeTypes: nodeTypes2, onNodeClick, onNodeDoubleClick, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onlyRenderVisibleElements, noPanClassName, noDragClassName, disableKeyboardA11y, nodeOrigin, nodeExtent, rfId }), jsx("div", { className: "react-flow__viewport-portal" })] }) });
5183
+ function GraphViewComponent({ nodeTypes: nodeTypes2, edgeTypes: edgeTypes2, onInit, onNodeClick, onEdgeClick, onNodeDoubleClick, onEdgeDoubleClick, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onSelectionContextMenu, onSelectionStart, onSelectionEnd, connectionLineType, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, selectionKeyCode, selectionOnDrag, selectionMode, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, deleteKeyCode, onlyRenderVisibleElements, elementsSelectable, defaultViewport: defaultViewport2, translateExtent, minZoom, maxZoom, preventScrolling, defaultMarkerColor, zoomOnScroll, zoomOnPinch, panOnScroll, panOnScrollSpeed, panOnScrollMode, zoomOnDoubleClick, panOnDrag, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, reconnectRadius, onReconnect, onReconnectStart, onReconnectEnd, noDragClassName, noWheelClassName, noPanClassName, disableKeyboardA11y, nodeOrigin, nodeExtent, rfId, viewport, onViewportChange }) {
5184
+ return useNodeOrEdgeTypesWarning(nodeTypes2), useNodeOrEdgeTypesWarning(edgeTypes2), useStylesLoadedWarning(), useOnInitHandler(onInit), useViewportSync(viewport), jsx(FlowRenderer, { onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneContextMenu, onPaneScroll, deleteKeyCode, selectionKeyCode, selectionOnDrag, selectionMode, onSelectionStart, onSelectionEnd, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, elementsSelectable, zoomOnScroll, zoomOnPinch, zoomOnDoubleClick, panOnScroll, panOnScrollSpeed, panOnScrollMode, panOnDrag, defaultViewport: defaultViewport2, translateExtent, minZoom, maxZoom, onSelectionContextMenu, preventScrolling, noDragClassName, noWheelClassName, noPanClassName, disableKeyboardA11y, onViewportChange, isControlledViewport: !!viewport, children: jsxs(Viewport, { children: [jsx(EdgeRenderer, { edgeTypes: edgeTypes2, onEdgeClick, onEdgeDoubleClick, onReconnect, onReconnectStart, onReconnectEnd, onlyRenderVisibleElements, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, reconnectRadius, defaultMarkerColor, noPanClassName, disableKeyboardA11y, rfId }), jsx(ConnectionLineWrapper, { style: connectionLineStyle, type: connectionLineType, component: connectionLineComponent, containerStyle: connectionLineContainerStyle }), jsx("div", { className: "react-flow__edgelabel-renderer" }), jsx(NodeRenderer, { nodeTypes: nodeTypes2, onNodeClick, onNodeDoubleClick, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onlyRenderVisibleElements, noPanClassName, noDragClassName, disableKeyboardA11y, nodeOrigin, nodeExtent, rfId }), jsx("div", { className: "react-flow__viewport-portal" })] }) });
5142
5185
  }
5143
5186
  GraphViewComponent.displayName = "GraphView";
5144
5187
  const GraphView = memo(GraphViewComponent), getInitialState = ({ nodes, edges, defaultNodes, defaultEdges, width, height, fitView: fitView2 } = {}) => {
@@ -5192,7 +5235,7 @@ const GraphView = memo(GraphViewComponent), getInitialState = ({ nodes, edges, d
5192
5235
  nodesConnectable: !0,
5193
5236
  nodesFocusable: !0,
5194
5237
  edgesFocusable: !0,
5195
- edgesUpdatable: !0,
5238
+ edgesReconnectable: !0,
5196
5239
  elementsSelectable: !0,
5197
5240
  elevateNodesOnSelect: !0,
5198
5241
  elevateEdgesOnSelect: !1,
@@ -5400,9 +5443,9 @@ const wrapperStyle = {
5400
5443
  position: "relative",
5401
5444
  zIndex: 0
5402
5445
  };
5403
- function ReactFlow({ nodes, edges, defaultNodes, defaultEdges, className, nodeTypes: nodeTypes2, edgeTypes: edgeTypes2, onNodeClick, onEdgeClick, onInit, onMove, onMoveStart, onMoveEnd, onConnect, onConnectStart, onConnectEnd, onClickConnectStart, onClickConnectEnd, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onNodeDoubleClick, onNodeDragStart, onNodeDrag, onNodeDragStop, onNodesDelete, onEdgesDelete, onDelete, onSelectionChange, onSelectionDragStart, onSelectionDrag, onSelectionDragStop, onSelectionContextMenu, onSelectionStart, onSelectionEnd, onBeforeDelete, connectionMode, connectionLineType = ConnectionLineType.Bezier, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, deleteKeyCode = "Backspace", selectionKeyCode = "Shift", selectionOnDrag = !1, selectionMode = SelectionMode.Full, panActivationKeyCode = "Space", multiSelectionKeyCode = isMacOs() ? "Meta" : "Control", zoomActivationKeyCode = isMacOs() ? "Meta" : "Control", snapToGrid, snapGrid, onlyRenderVisibleElements = !1, selectNodesOnDrag, nodesDraggable, nodesConnectable, nodesFocusable, nodeOrigin = defaultNodeOrigin, edgesFocusable, edgesUpdatable, elementsSelectable = !0, defaultViewport: defaultViewport$1 = defaultViewport, minZoom = 0.5, maxZoom = 2, translateExtent = infiniteExtent, preventScrolling = !0, nodeExtent, defaultMarkerColor = "#b1b1b7", zoomOnScroll = !0, zoomOnPinch = !0, panOnScroll = !1, panOnScrollSpeed = 0.5, panOnScrollMode = PanOnScrollMode.Free, zoomOnDoubleClick = !0, panOnDrag = !0, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, children: children2, onEdgeUpdate, onEdgeContextMenu, onEdgeDoubleClick, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdateStart, onEdgeUpdateEnd, edgeUpdaterRadius = 10, onNodesChange, onEdgesChange, noDragClassName = "nodrag", noWheelClassName = "nowheel", noPanClassName = "nopan", fitView: fitView2, fitViewOptions, connectOnClick, attributionPosition, proOptions, defaultEdgeOptions, elevateNodesOnSelect, elevateEdgesOnSelect, disableKeyboardA11y = !1, autoPanOnConnect, autoPanOnNodeDrag, connectionRadius, isValidConnection, onError, style: style2, id: id2, nodeDragThreshold, viewport, onViewportChange, width, height, colorMode = "light", debug, ...rest }, ref) {
5446
+ function ReactFlow({ nodes, edges, defaultNodes, defaultEdges, className, nodeTypes: nodeTypes2, edgeTypes: edgeTypes2, onNodeClick, onEdgeClick, onInit, onMove, onMoveStart, onMoveEnd, onConnect, onConnectStart, onConnectEnd, onClickConnectStart, onClickConnectEnd, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onNodeDoubleClick, onNodeDragStart, onNodeDrag, onNodeDragStop, onNodesDelete, onEdgesDelete, onDelete, onSelectionChange, onSelectionDragStart, onSelectionDrag, onSelectionDragStop, onSelectionContextMenu, onSelectionStart, onSelectionEnd, onBeforeDelete, connectionMode, connectionLineType = ConnectionLineType.Bezier, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, deleteKeyCode = "Backspace", selectionKeyCode = "Shift", selectionOnDrag = !1, selectionMode = SelectionMode.Full, panActivationKeyCode = "Space", multiSelectionKeyCode = isMacOs() ? "Meta" : "Control", zoomActivationKeyCode = isMacOs() ? "Meta" : "Control", snapToGrid, snapGrid, onlyRenderVisibleElements = !1, selectNodesOnDrag, nodesDraggable, nodesConnectable, nodesFocusable, nodeOrigin = defaultNodeOrigin, edgesFocusable, edgesReconnectable, elementsSelectable = !0, defaultViewport: defaultViewport$1 = defaultViewport, minZoom = 0.5, maxZoom = 2, translateExtent = infiniteExtent, preventScrolling = !0, nodeExtent, defaultMarkerColor = "#b1b1b7", zoomOnScroll = !0, zoomOnPinch = !0, panOnScroll = !1, panOnScrollSpeed = 0.5, panOnScrollMode = PanOnScrollMode.Free, zoomOnDoubleClick = !0, panOnDrag = !0, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, children: children2, onReconnect, onReconnectStart, onReconnectEnd, onEdgeContextMenu, onEdgeDoubleClick, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, reconnectRadius = 10, onNodesChange, onEdgesChange, noDragClassName = "nodrag", noWheelClassName = "nowheel", noPanClassName = "nopan", fitView: fitView2, fitViewOptions, connectOnClick, attributionPosition, proOptions, defaultEdgeOptions, elevateNodesOnSelect, elevateEdgesOnSelect, disableKeyboardA11y = !1, autoPanOnConnect, autoPanOnNodeDrag, connectionRadius, isValidConnection, onError, style: style2, id: id2, nodeDragThreshold, viewport, onViewportChange, width, height, colorMode = "light", debug, ...rest }, ref) {
5404
5447
  const rfId = id2 || "1", colorModeClassName = useColorModeClass(colorMode);
5405
- return jsx("div", { ...rest, style: { ...style2, ...wrapperStyle }, ref, className: cc(["react-flow", className, colorModeClassName]), "data-testid": "rf__wrapper", id: id2, children: jsxs(Wrapper, { nodes, edges, width, height, fitView: fitView2, children: [jsx(GraphView, { onInit, onNodeClick, onEdgeClick, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onNodeDoubleClick, nodeTypes: nodeTypes2, edgeTypes: edgeTypes2, connectionLineType, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, selectionKeyCode, selectionOnDrag, selectionMode, deleteKeyCode, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, onlyRenderVisibleElements, defaultViewport: defaultViewport$1, translateExtent, minZoom, maxZoom, preventScrolling, zoomOnScroll, zoomOnPinch, zoomOnDoubleClick, panOnScroll, panOnScrollSpeed, panOnScrollMode, panOnDrag, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, onSelectionContextMenu, onSelectionStart, onSelectionEnd, onEdgeUpdate, onEdgeContextMenu, onEdgeDoubleClick, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdateStart, onEdgeUpdateEnd, edgeUpdaterRadius, defaultMarkerColor, noDragClassName, noWheelClassName, noPanClassName, rfId, disableKeyboardA11y, nodeOrigin, nodeExtent, viewport, onViewportChange }), jsx(StoreUpdater, { nodes, edges, defaultNodes, defaultEdges, onConnect, onConnectStart, onConnectEnd, onClickConnectStart, onClickConnectEnd, nodesDraggable, nodesConnectable, nodesFocusable, edgesFocusable, edgesUpdatable, elementsSelectable, elevateNodesOnSelect, elevateEdgesOnSelect, minZoom, maxZoom, nodeExtent, onNodesChange, onEdgesChange, snapToGrid, snapGrid, connectionMode, translateExtent, connectOnClick, defaultEdgeOptions, fitView: fitView2, fitViewOptions, onNodesDelete, onEdgesDelete, onDelete, onNodeDragStart, onNodeDrag, onNodeDragStop, onSelectionDrag, onSelectionDragStart, onSelectionDragStop, onMove, onMoveStart, onMoveEnd, noPanClassName, nodeOrigin, rfId, autoPanOnConnect, autoPanOnNodeDrag, onError, connectionRadius, isValidConnection, selectNodesOnDrag, nodeDragThreshold, onBeforeDelete, debug }), jsx(SelectionListener, { onSelectionChange }), children2, jsx(Attribution, { proOptions, position: attributionPosition }), jsx(A11yDescriptions, { rfId, disableKeyboardA11y })] }) });
5448
+ return jsx("div", { ...rest, style: { ...style2, ...wrapperStyle }, ref, className: cc(["react-flow", className, colorModeClassName]), "data-testid": "rf__wrapper", id: id2, children: jsxs(Wrapper, { nodes, edges, width, height, fitView: fitView2, children: [jsx(GraphView, { onInit, onNodeClick, onEdgeClick, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onNodeDoubleClick, nodeTypes: nodeTypes2, edgeTypes: edgeTypes2, connectionLineType, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, selectionKeyCode, selectionOnDrag, selectionMode, deleteKeyCode, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, onlyRenderVisibleElements, defaultViewport: defaultViewport$1, translateExtent, minZoom, maxZoom, preventScrolling, zoomOnScroll, zoomOnPinch, zoomOnDoubleClick, panOnScroll, panOnScrollSpeed, panOnScrollMode, panOnDrag, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, onSelectionContextMenu, onSelectionStart, onSelectionEnd, onReconnect, onReconnectStart, onReconnectEnd, onEdgeContextMenu, onEdgeDoubleClick, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, reconnectRadius, defaultMarkerColor, noDragClassName, noWheelClassName, noPanClassName, rfId, disableKeyboardA11y, nodeOrigin, nodeExtent, viewport, onViewportChange }), jsx(StoreUpdater, { nodes, edges, defaultNodes, defaultEdges, onConnect, onConnectStart, onConnectEnd, onClickConnectStart, onClickConnectEnd, nodesDraggable, nodesConnectable, nodesFocusable, edgesFocusable, edgesReconnectable, elementsSelectable, elevateNodesOnSelect, elevateEdgesOnSelect, minZoom, maxZoom, nodeExtent, onNodesChange, onEdgesChange, snapToGrid, snapGrid, connectionMode, translateExtent, connectOnClick, defaultEdgeOptions, fitView: fitView2, fitViewOptions, onNodesDelete, onEdgesDelete, onDelete, onNodeDragStart, onNodeDrag, onNodeDragStop, onSelectionDrag, onSelectionDragStart, onSelectionDragStop, onMove, onMoveStart, onMoveEnd, noPanClassName, nodeOrigin, rfId, autoPanOnConnect, autoPanOnNodeDrag, onError, connectionRadius, isValidConnection, selectNodesOnDrag, nodeDragThreshold, onBeforeDelete, debug }), jsx(SelectionListener, { onSelectionChange }), children2, jsx(Attribution, { proOptions, position: attributionPosition }), jsx(A11yDescriptions, { rfId, disableKeyboardA11y })] }) });
5406
5449
  }
5407
5450
  var index = fixedForwardRef(ReactFlow);
5408
5451
  const selector$8 = (s) => {
@@ -5423,16 +5466,6 @@ function useOnViewportChange({ onStart, onChange, onEnd }) {
5423
5466
  store.setState({ onViewportChangeEnd: onEnd });
5424
5467
  }, [onEnd]);
5425
5468
  }
5426
- function useOnSelectionChange({ onChange }) {
5427
- const store = useStoreApi();
5428
- useEffect(() => {
5429
- const nextOnSelectionChangeHandlers = [...store.getState().onSelectionChangeHandlers, onChange];
5430
- return store.setState({ onSelectionChangeHandlers: nextOnSelectionChangeHandlers }), () => {
5431
- const nextHandlers = store.getState().onSelectionChangeHandlers.filter((fn) => fn !== onChange);
5432
- store.setState({ onSelectionChangeHandlers: nextHandlers });
5433
- };
5434
- }, [onChange]);
5435
- }
5436
5469
  function useNodesData(nodeIds) {
5437
5470
  return useStore(useCallback((s) => {
5438
5471
  const data = [], isArrayOfIds = Array.isArray(nodeIds), _nodeIds = isArrayOfIds ? nodeIds : [nodeIds];
@@ -5781,6 +5814,31 @@ function clsx() {
5781
5814
  for (var e, t2, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t2 = r(e)) && (n && (n += " "), n += t2);
5782
5815
  return n;
5783
5816
  }
5817
+ function getDefaultExportFromCjs(x) {
5818
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x.default : x;
5819
+ }
5820
+ var tilg = { exports: {} }, __defProp2 = Object.defineProperty, __getOwnPropDesc = Object.getOwnPropertyDescriptor, __getOwnPropNames = Object.getOwnPropertyNames, __hasOwnProp = Object.prototype.hasOwnProperty, __export = (target, all) => {
5821
+ for (var name in all)
5822
+ __defProp2(target, name, { get: all[name], enumerable: !0 });
5823
+ }, __copyProps = (to, from, except, desc) => {
5824
+ if (from && typeof from == "object" || typeof from == "function")
5825
+ for (let key of __getOwnPropNames(from))
5826
+ !__hasOwnProp.call(to, key) && key !== except && __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
5827
+ return to;
5828
+ }, __toCommonJS = (mod) => __copyProps(__defProp2({}, "__esModule", { value: !0 }), mod), production_exports = {};
5829
+ __export(production_exports, {
5830
+ default: () => useTilg$1
5831
+ });
5832
+ var production = __toCommonJS(production_exports);
5833
+ function useTilg$1(...args) {
5834
+ return args.length ? args[0] : (_strings, ...innerArgs) => {
5835
+ if (innerArgs && innerArgs.length)
5836
+ return innerArgs[0];
5837
+ };
5838
+ }
5839
+ tilg.exports = production;
5840
+ var tilgExports = tilg.exports;
5841
+ const useTilg = /* @__PURE__ */ getDefaultExportFromCjs(tilgExports);
5784
5842
  var rootClassName = "likec4-diagram-root", keepAspectRatioContainer = "_2h8g8h0", cssReactFlow = "_2h8g8h1", cssDisablePan = "_2h8g8h2", cssTransparentBg = "_2h8g8h3", cssNoControls = "_2h8g8h4";
5785
5843
  function KeepAspectRatioContainer({
5786
5844
  children: children2,
@@ -6959,592 +7017,89 @@ function useDiagramStoreApi() {
6959
7017
  const store = useContext(DiagramContext);
6960
7018
  if (store === null)
6961
7019
  throw new Error("useDiagramStoreApi could be used only inside DiagramContext");
6962
- return useMemo(
6963
- () => ({
6964
- getState: store.getState,
6965
- setState: store.setState,
6966
- subscribe: store.subscribe
6967
- }),
6968
- [store]
6969
- );
6970
- }
6971
- function WhenInitialized({ children: children2 }) {
6972
- const diagramApi = useDiagramStoreApi(), [isInitialized, setIsInitialized] = useState(diagramApi.getState().initialized);
6973
- return useEffect(() => {
6974
- if (!isInitialized)
6975
- return diagramApi.subscribe(
6976
- (s) => s.initialized,
6977
- setIsInitialized
6978
- );
6979
- }, [isInitialized]), isInitialized ? /* @__PURE__ */ jsx(Fragment, { children: children2 }) : null;
6980
- }
6981
- const useXYFlow = useReactFlow, useXYNodesData = useNodesData;
6982
- function useXYStore(selector2, equalityFn) {
6983
- return useStore(
6984
- // @ts-expect-error - types are not correct
6985
- selector2,
6986
- equalityFn ?? shallowEqual
6987
- );
6988
- }
6989
- const useXYStoreApi = useStoreApi;
6990
- class Rect {
6991
- constructor() {
6992
- __publicField(this, "id");
6993
- __publicField(this, "minX", new Variable());
6994
- __publicField(this, "minY", new Variable());
6995
- __publicField(this, "maxX", new Variable());
6996
- __publicField(this, "maxY", new Variable());
6997
- }
6998
- get x() {
6999
- return this.minX;
7000
- }
7001
- get y() {
7002
- return this.minY;
7003
- }
7004
- get positionAbsolute() {
7005
- return {
7006
- x: this.x.value(),
7007
- y: this.y.value()
7008
- };
7009
- }
7010
- get dimensions() {
7011
- return {
7012
- width: this.maxX.value() - this.minX.value(),
7013
- height: this.maxY.value() - this.minY.value()
7014
- };
7015
- }
7016
- // Position relative to parent
7017
- get position() {
7018
- const positionAbsolute = this.positionAbsolute;
7019
- if (!this.parent)
7020
- return positionAbsolute;
7021
- const parentPosition = this.parent.positionAbsolute;
7022
- return {
7023
- x: positionAbsolute.x - parentPosition.x,
7024
- y: positionAbsolute.y - parentPosition.y
7025
- };
7026
- }
7020
+ return store;
7027
7021
  }
7028
- class Compound extends Rect {
7029
- constructor(solver, xynode, parent = null) {
7030
- super();
7031
- __publicField(this, "children", []);
7032
- this.solver = solver, this.parent = parent, this.id = xynode.id, solver.createConstraint(this.maxX, Operator.Ge, this.minX), solver.createConstraint(this.maxY, Operator.Ge, this.minY), parent && parent.addChild(this);
7033
- }
7034
- addChild(rect) {
7035
- this.children.push(rect);
7036
- const leftPadding = new Expression(
7037
- rect.minX,
7038
- [-1, this.minX]
7039
- ), { weak } = Strength;
7040
- this.solver.createConstraint(leftPadding, Operator.Ge, 40), this.solver.createConstraint(leftPadding, Operator.Eq, 40, weak);
7041
- const topPadding = new Expression(
7042
- rect.minY,
7043
- [-1, this.minY]
7044
- );
7045
- this.solver.createConstraint(topPadding, Operator.Ge, 60), this.solver.createConstraint(topPadding, Operator.Eq, 60, weak);
7046
- const rightPadding = new Expression(
7047
- this.maxX,
7048
- [-1, rect.maxX]
7049
- );
7050
- this.solver.createConstraint(rightPadding, Operator.Ge, 40), this.solver.createConstraint(rightPadding, Operator.Eq, 40, weak);
7051
- const bottomPadding = new Expression(
7052
- this.maxY,
7053
- [-1, rect.maxY]
7054
- );
7055
- this.solver.createConstraint(bottomPadding, Operator.Ge, 40), this.solver.createConstraint(bottomPadding, Operator.Eq, 40, weak);
7056
- }
7022
+ const { abs: abs$1, cos: cos$1, sin: sin$1, acos: acos$1, atan2, sqrt: sqrt$1, pow } = Math;
7023
+ function crt(v) {
7024
+ return v < 0 ? -pow(-v, 1 / 3) : pow(v, 1 / 3);
7057
7025
  }
7058
- class Leaf extends Rect {
7059
- constructor(solver, xynode, parent = null, isEditing = !1) {
7060
- super(), this.parent = parent, this.isEditing = isEditing, this.id = xynode.id;
7061
- const x = Math.ceil(xynode.internals.positionAbsolute.x), y = Math.ceil(xynode.internals.positionAbsolute.y), { width, height } = getNodeDimensions(xynode);
7062
- if (this.maxX = new Expression(this.minX, Math.ceil(width)), this.maxY = new Expression(this.minY, Math.ceil(height)), isEditing) {
7063
- const superStrong = Strength.create(100, 0, 0);
7064
- solver.addEditVariable(this.minX, superStrong), solver.addEditVariable(this.minY, superStrong), solver.suggestValue(this.minX, x), solver.suggestValue(this.minY, y);
7065
- } else {
7066
- const halfMedium = Strength.create(0, 1, 0, 0.5);
7067
- solver.createConstraint(this.minX, Operator.Eq, x, halfMedium), solver.createConstraint(this.minY, Operator.Eq, y, halfMedium);
7068
- }
7069
- parent && parent.addChild(this);
7070
- }
7071
- }
7072
- function createLayoutConstraints(xyflow, xyflowApi, draggingNodeId) {
7073
- var _a;
7074
- const { parentLookup, nodeLookup } = xyflowApi.getState(), solver = new Solver(), rects = /* @__PURE__ */ new Map(), traverse = new Array();
7075
- for (const [, xynode] of nodeLookup)
7076
- isNullish(xynode.parentId) && traverse.push({
7077
- xynode,
7078
- parent: null
7079
- });
7080
- for (; traverse.length > 0; ) {
7081
- const { xynode, parent } = traverse.shift(), isDragging = xynode.dragging === !0 || xynode.id === draggingNodeId, shouldTraverse = !isDragging && xynode.type === "compound" && isAncestor(xynode.id, draggingNodeId), rect = shouldTraverse ? new Compound(solver, xynode, parent) : new Leaf(solver, xynode, parent, isDragging);
7082
- rects.set(xynode.id, rect), shouldTraverse && ((_a = parentLookup.get(xynode.id)) == null || _a.forEach((child) => {
7083
- traverse.push({
7084
- xynode: child,
7085
- parent: rect
7086
- });
7087
- }));
7088
- }
7089
- solver.updateVariables(), solver.maxIterations = 1e3;
7090
- function updateXYFlowNodes() {
7091
- solver.updateVariables(), xyflow.setNodes(
7092
- (nodes) => nodes.map((n) => {
7093
- if (n.id === draggingNodeId || n.dragging === !0)
7094
- return n;
7095
- const rect = rects.get(n.id);
7096
- if (!rect)
7097
- return n;
7098
- const dimensions = rect.dimensions, newXY = rect.position;
7099
- return newXY.x !== n.position.x || newXY.y !== n.position.y ? {
7100
- ...n,
7101
- position: rect.position,
7102
- width: dimensions.width,
7103
- height: dimensions.height,
7104
- measured: dimensions
7105
- } : dimensions.width !== n.width || dimensions.height !== n.height ? {
7106
- ...n,
7107
- width: dimensions.width,
7108
- height: dimensions.height,
7109
- measured: dimensions
7110
- } : n;
7111
- })
7112
- );
7113
- }
7114
- let animationFrameId = null;
7115
- function onNodeDrag(xynode) {
7116
- const pos = nodeLookup.get(xynode.id).internals.positionAbsolute, rect = nonNullable(rects.get(xynode.id));
7117
- solver.suggestValue(rect.minX, Math.ceil(pos.x)), solver.suggestValue(rect.minY, Math.ceil(pos.y)), animationFrameId ?? (animationFrameId = requestAnimationFrame(() => {
7118
- updateXYFlowNodes(), animationFrameId = null;
7119
- }));
7120
- }
7121
- return {
7122
- onNodeDrag,
7123
- updateXYFlowNodes
7124
- };
7125
- }
7126
- function useLayoutConstraints() {
7127
- const diagramApi = useDiagramStoreApi(), xyflowApi = useXYStoreApi(), solverRef = useRef();
7128
- return useMemo(() => ({
7129
- onNodeDragStart: (_event, xynode) => {
7130
- const { xyflow } = diagramApi.getState();
7131
- solverRef.current = createLayoutConstraints(xyflow, xyflowApi, xynode.id);
7132
- },
7133
- onNodeDrag: (_event, xynode) => {
7134
- var _a;
7135
- invariant(solverRef.current, "solverRef.current should be defined"), (_a = solverRef.current) == null || _a.onNodeDrag(xynode);
7136
- },
7137
- onNodeDragStop: (_event, _xynode) => {
7138
- solverRef.current = void 0;
7139
- }
7140
- }), [xyflowApi]);
7141
- }
7142
- const ZIndexes = {
7143
- Compound: 1,
7144
- Edge: 2,
7145
- Element: 3
7146
- }, MinZoom = 0.05, StringSet = Set, DEFAULT_PROPS = {
7147
- initialized: !1,
7148
- xyflowSynced: !1,
7149
- previousViews: [],
7150
- viewportChanged: !1,
7151
- activeDynamicViewStep: null,
7152
- focusedNodeId: null,
7153
- hoveredNodeId: null,
7154
- hoveredEdgeId: null,
7155
- lastClickedNodeId: null,
7156
- lastClickedEdgeId: null,
7157
- dimmed: new StringSet(),
7158
- lastOnNavigate: null,
7159
- onChange: null,
7160
- onNavigateTo: null,
7161
- onNodeClick: null,
7162
- onNodeContextMenu: null,
7163
- onCanvasContextMenu: null,
7164
- onEdgeClick: null,
7165
- onEdgeContextMenu: null,
7166
- onCanvasClick: null,
7167
- onCanvasDblClick: null
7168
- }, noReplace = !1;
7169
- let storeDevId = 1;
7170
- const EmptyStringSet = new StringSet();
7171
- function createDiagramStore(props) {
7172
- return createWithEqualityFn(
7173
- subscribeWithSelector(
7174
- devtools(
7175
- (set2, get2) => ({
7176
- ...DEFAULT_PROPS,
7177
- ...props,
7178
- isDynamicView: () => {
7179
- var _a;
7180
- return ((_a = get2().view) == null ? void 0 : _a.__) === "dynamic";
7181
- },
7182
- updateView: (nextView) => {
7183
- let {
7184
- dimmed: dimmed2,
7185
- xyflowSynced,
7186
- view: current,
7187
- lastOnNavigate,
7188
- previousViews,
7189
- focusedNodeId,
7190
- lastClickedNodeId,
7191
- lastClickedEdgeId,
7192
- activeDynamicViewStep,
7193
- hoveredEdgeId,
7194
- hoveredNodeId
7195
- } = get2();
7196
- if (shallowEqual(current, nextView)) {
7197
- xyflowSynced || set2({ xyflowSynced: !0 }, noReplace, "updateView: xyflow synced"), DEV && console.debug("store: skip updateView");
7198
- return;
7199
- }
7200
- if (current.id === nextView.id) {
7201
- const nodeIds = new StringSet(nextView.nodes.map((n) => n.id)), edgeIds = new StringSet(nextView.edges.map((e) => e.id));
7202
- if (lastClickedNodeId && !nodeIds.has(lastClickedNodeId) && (lastClickedNodeId = null), hoveredNodeId && !nodeIds.has(hoveredNodeId) && (hoveredNodeId = null), focusedNodeId && !nodeIds.has(focusedNodeId) && (focusedNodeId = null), lastClickedEdgeId && !edgeIds.has(lastClickedEdgeId) && (lastClickedEdgeId = null), hoveredEdgeId && !edgeIds.has(hoveredEdgeId) && (hoveredEdgeId = null), activeDynamicViewStep && !edgeIds.has(StepEdgeId(activeDynamicViewStep)) && (activeDynamicViewStep = null), xyflowSynced = deepEqual(current.nodes, nextView.nodes) && deepEqual(current.edges, nextView.edges), !xyflowSynced) {
7203
- let nextDimmed = new StringSet([...dimmed2].filter((id2) => nodeIds.has(id2) || edgeIds.has(id2)));
7204
- nextDimmed.size !== dimmed2.size && (dimmed2 = nextDimmed);
7205
- }
7206
- } else
7207
- lastOnNavigate && lastOnNavigate.toView !== nextView.id && lastOnNavigate.fromView !== nextView.id && (lastOnNavigate = null), lastClickedEdgeId = null, lastClickedNodeId = null, hoveredEdgeId = null, hoveredNodeId = null, focusedNodeId = null, activeDynamicViewStep = null, dimmed2 = EmptyStringSet, previousViews = [
7208
- current,
7209
- ...previousViews.filter((v) => v.id !== nextView.id && v.id !== current.id)
7210
- ], xyflowSynced = !1;
7211
- set2(
7212
- {
7213
- view: nextView,
7214
- activeDynamicViewStep,
7215
- xyflowSynced,
7216
- lastOnNavigate,
7217
- previousViews,
7218
- lastClickedNodeId,
7219
- lastClickedEdgeId,
7220
- focusedNodeId,
7221
- hoveredEdgeId,
7222
- hoveredNodeId,
7223
- dimmed: dimmed2
7224
- },
7225
- noReplace,
7226
- "update-view"
7227
- );
7228
- },
7229
- focusOnNode: (nodeId) => {
7230
- const { focusedNodeId, view } = get2();
7231
- if (nodeId !== focusedNodeId) {
7232
- const notDimmed = new StringSet([nodeId]), dimmed2 = new StringSet();
7233
- for (const edge of view.edges)
7234
- edge.source === nodeId || edge.target === nodeId ? (notDimmed.add(edge.source), notDimmed.add(edge.target)) : dimmed2.add(edge.id);
7235
- for (const node of view.nodes)
7236
- notDimmed.has(node.id) || dimmed2.add(node.id);
7237
- set2(
7238
- {
7239
- activeDynamicViewStep: null,
7240
- focusedNodeId: nodeId,
7241
- dimmed: dimmed2
7242
- },
7243
- noReplace,
7244
- `focus on node: ${nodeId}`
7245
- );
7246
- }
7247
- },
7248
- setHoveredNode: (nodeId) => {
7249
- nodeId !== get2().hoveredNodeId && set2({ hoveredNodeId: nodeId }, noReplace, nodeId ? "setHoveredNode" : "unsetHoveredNode");
7250
- },
7251
- setHoveredEdge: (edgeId) => {
7252
- edgeId !== get2().hoveredEdgeId && set2({ hoveredEdgeId: edgeId }, noReplace, edgeId ? "setHoveredEdge" : "unsetHoveredEdge");
7253
- },
7254
- setLastClickedNode: (nodeId) => {
7255
- nodeId !== get2().lastClickedNodeId && set2({ lastClickedNodeId: nodeId }, noReplace, nodeId ? "setLastClickedNode" : "unsetLastClickedNode");
7256
- },
7257
- setLastClickedEdge: (edgeId) => {
7258
- edgeId !== get2().lastClickedEdgeId && set2({ lastClickedEdgeId: edgeId }, noReplace, edgeId ? "setLastClickedEdge" : "unsetLastClickedEdge");
7259
- },
7260
- resetLastClicked: () => {
7261
- let {
7262
- focusedNodeId,
7263
- lastClickedNodeId,
7264
- lastClickedEdgeId
7265
- } = get2();
7266
- (focusedNodeId || lastClickedNodeId || lastClickedEdgeId) && set2(
7267
- {
7268
- focusedNodeId: null,
7269
- lastClickedNodeId: null,
7270
- lastClickedEdgeId: null,
7271
- dimmed: EmptyStringSet
7272
- },
7273
- noReplace,
7274
- "resetLastClicked"
7275
- );
7276
- },
7277
- getElement: (fqn) => {
7278
- const { view } = get2();
7279
- return view.nodes.find(({ id: id2 }) => id2 === fqn) ?? null;
7280
- },
7281
- triggerOnChange: (changes) => {
7282
- var _a, _b;
7283
- DEV && console.debug("triggerOnChange", changes);
7284
- const newShapes = /* @__PURE__ */ new Map(), newColor = /* @__PURE__ */ new Map(), newOpacity = /* @__PURE__ */ new Map(), newBorder = /* @__PURE__ */ new Map();
7285
- for (const change of changes) {
7286
- change.op !== "change-element-style" && nonexhaustive(change.op);
7287
- for (const target of change.targets)
7288
- for (const [key, value] of entries.strict(change.style))
7289
- switch (key) {
7290
- case "shape":
7291
- newShapes.set(target, value);
7292
- break;
7293
- case "color":
7294
- newColor.set(target, value);
7295
- break;
7296
- case "opacity":
7297
- newOpacity.set(target, value);
7298
- break;
7299
- case "border":
7300
- newBorder.set(target, value);
7301
- break;
7302
- default:
7303
- nonexhaustive(key);
7304
- }
7305
- }
7306
- get2().xyflow.setNodes(
7307
- (nodes) => nodes.map((node) => {
7308
- var _a2, _b2;
7309
- let element2 = node.data.element;
7310
- const shape = newShapes.get(element2.id);
7311
- shape && shape !== element2.shape && (element2 = {
7312
- ...element2,
7313
- shape
7314
- });
7315
- const color2 = newColor.get(element2.id);
7316
- color2 && color2 !== element2.color && (element2 = {
7317
- ...element2,
7318
- color: color2
7319
- });
7320
- const opacity = newOpacity.get(element2.id);
7321
- opacity && opacity !== ((_a2 = element2.style) == null ? void 0 : _a2.opacity) && (element2 = {
7322
- ...element2,
7323
- style: {
7324
- ...element2.style,
7325
- opacity
7326
- }
7327
- });
7328
- const border = newBorder.get(element2.id);
7329
- return border && border !== ((_b2 = element2.style) == null ? void 0 : _b2.border) && (element2 = {
7330
- ...element2,
7331
- style: {
7332
- ...element2.style,
7333
- border
7334
- }
7335
- }), element2 === node.data.element ? node : {
7336
- ...node,
7337
- data: {
7338
- ...node.data,
7339
- element: element2
7340
- }
7341
- };
7342
- })
7343
- ), (_b = (_a = get2()).onChange) == null || _b.call(_a, { changes });
7344
- },
7345
- triggerOnNavigateTo: (xynodeId, event) => {
7346
- var _a, _b;
7347
- const { xyflow, view } = get2(), xynode = xyflow.getInternalNode(xynodeId), element2 = xynode == null ? void 0 : xynode.data.element;
7348
- invariant(!!xynode && (element2 == null ? void 0 : element2.navigateTo), `node is not navigable: ${xynodeId}`);
7349
- const dimensions = getNodeDimensions(xynode);
7350
- set2(
7351
- {
7352
- lastClickedNodeId: xynodeId,
7353
- lastOnNavigate: {
7354
- fromView: view.id,
7355
- toView: element2.navigateTo,
7356
- element: element2,
7357
- elementCenterScreenPosition: xyflow.flowToScreenPosition({
7358
- x: xynode.internals.positionAbsolute.x + dimensions.width / 2,
7359
- y: xynode.internals.positionAbsolute.y + dimensions.height / 2
7360
- }),
7361
- positionCorrected: !1
7362
- }
7363
- },
7364
- noReplace,
7365
- "triggerOnNavigateTo"
7366
- ), (_b = (_a = get2()).onNavigateTo) == null || _b.call(
7367
- _a,
7368
- element2.navigateTo,
7369
- event,
7370
- element2,
7371
- xynode.internals.userNode
7372
- );
7373
- },
7374
- fitDiagram: (xyStore) => {
7375
- const { width, height, panZoom } = xyStore.getState(), { fitViewPadding, view, focusedNodeId } = get2(), bounds = {
7376
- x: 0,
7377
- y: 0,
7378
- width: view.width,
7379
- height: view.height
7380
- }, viewport = getViewportForBounds(bounds, width, height, MinZoom, 1, fitViewPadding);
7381
- panZoom == null || panZoom.setViewport(viewport, { duration: 400 }), focusedNodeId && set2(
7382
- {
7383
- focusedNodeId: null,
7384
- dimmed: EmptyStringSet
7385
- },
7386
- noReplace,
7387
- "unfocus"
7388
- );
7389
- },
7390
- nextDynamicStep: (increment = 1) => {
7391
- const { view, activeDynamicViewStep, xyflow, fitViewPadding } = get2();
7392
- invariant(view.__ === "dynamic", "view is not dynamic");
7393
- const nextStep = (activeDynamicViewStep ?? 0) + increment, edgeId = StepEdgeId(nextStep), dimmed2 = new StringSet();
7394
- let edge = null;
7395
- for (const e of xyflow.getEdges()) {
7396
- if (e.id === edgeId) {
7397
- edge = e;
7398
- continue;
7399
- }
7400
- dimmed2.add(e.id);
7401
- }
7402
- invariant(!!edge, `edge not found: ${edgeId}`);
7403
- const selected2 = [];
7404
- for (const n of xyflow.getNodes()) {
7405
- if (n.id === edge.source || n.id === edge.target) {
7406
- selected2.push(n);
7407
- continue;
7408
- }
7409
- dimmed2.add(n.id);
7410
- }
7411
- xyflow.fitView({
7412
- duration: 400,
7413
- maxZoom: 1,
7414
- minZoom: MinZoom,
7415
- padding: fitViewPadding,
7416
- nodes: selected2
7417
- }), set2({
7418
- focusedNodeId: null,
7419
- activeDynamicViewStep: nextStep,
7420
- dimmed: dimmed2
7421
- });
7422
- },
7423
- stopDynamicView: () => {
7424
- const { xyflow, fitViewPadding } = get2();
7425
- set2({
7426
- activeDynamicViewStep: null,
7427
- dimmed: EmptyStringSet
7428
- }), xyflow.fitView({
7429
- duration: 400,
7430
- maxZoom: 1,
7431
- minZoom: MinZoom,
7432
- padding: fitViewPadding
7433
- });
7434
- }
7435
- }),
7436
- {
7437
- name: `DiagramStore ${storeDevId++} - ${props.view.id}`,
7438
- enabled: DEV
7439
- }
7440
- )
7441
- ),
7442
- shallow
7443
- );
7444
- }
7445
- const DiagramContext = createContext(null);
7446
- function DiagramContextProvider({ children: children2, view, ...props }) {
7447
- const xyflow = useXYFlow(), store = useRef();
7448
- return store.current || (store.current = createDiagramStore({
7449
- xyflow,
7450
- view,
7451
- ...props
7452
- })), useEffect(
7453
- () => {
7454
- var _a, _b;
7455
- ((_a = store.current) == null ? void 0 : _a.getState().xyflow) !== xyflow && ((_b = store.current) == null || _b.setState({ xyflow }, !1, "update xyflow"));
7456
- },
7457
- [xyflow]
7458
- ), useUpdateEffect(
7459
- () => {
7460
- if (!store.current) return;
7461
- const state = store.current.getState();
7462
- state.view !== view && state.updateView(view), hasSubObject(state, props) || store.current.setState(props, !1, "update incoming props");
7463
- },
7464
- [view, props]
7465
- ), /* @__PURE__ */ jsx(DiagramContext.Provider, { value: store.current, children: children2 });
7466
- }
7467
- const { abs: abs$1, cos: cos$1, sin: sin$1, acos: acos$1, atan2, sqrt: sqrt$1, pow } = Math;
7468
- function crt(v) {
7469
- return v < 0 ? -pow(-v, 1 / 3) : pow(v, 1 / 3);
7470
- }
7471
- const pi$1 = Math.PI, tau = 2 * pi$1, quart = pi$1 / 2, epsilon = 1e-6, nMax = Number.MAX_SAFE_INTEGER || 9007199254740991, nMin = Number.MIN_SAFE_INTEGER || -9007199254740991, ZERO = { x: 0, y: 0, z: 0 }, utils = {
7472
- // Legendre-Gauss abscissae with n=24 (x_i values, defined at i=n as the roots of the nth order Legendre polynomial Pn(x))
7473
- Tvalues: [
7474
- -0.06405689286260563,
7475
- 0.06405689286260563,
7476
- -0.1911188674736163,
7477
- 0.1911188674736163,
7478
- -0.3150426796961634,
7479
- 0.3150426796961634,
7480
- -0.4337935076260451,
7481
- 0.4337935076260451,
7482
- -0.5454214713888396,
7483
- 0.5454214713888396,
7484
- -0.6480936519369755,
7485
- 0.6480936519369755,
7486
- -0.7401241915785544,
7487
- 0.7401241915785544,
7488
- -0.820001985973903,
7489
- 0.820001985973903,
7490
- -0.8864155270044011,
7491
- 0.8864155270044011,
7492
- -0.9382745520027328,
7493
- 0.9382745520027328,
7494
- -0.9747285559713095,
7495
- 0.9747285559713095,
7496
- -0.9951872199970213,
7497
- 0.9951872199970213
7498
- ],
7499
- // Legendre-Gauss weights with n=24 (w_i values, defined by a function linked to in the Bezier primer article)
7500
- Cvalues: [
7501
- 0.12793819534675216,
7502
- 0.12793819534675216,
7503
- 0.1258374563468283,
7504
- 0.1258374563468283,
7505
- 0.12167047292780339,
7506
- 0.12167047292780339,
7507
- 0.1155056680537256,
7508
- 0.1155056680537256,
7509
- 0.10744427011596563,
7510
- 0.10744427011596563,
7511
- 0.09761865210411388,
7512
- 0.09761865210411388,
7513
- 0.08619016153195327,
7514
- 0.08619016153195327,
7515
- 0.0733464814110803,
7516
- 0.0733464814110803,
7517
- 0.05929858491543678,
7518
- 0.05929858491543678,
7519
- 0.04427743881741981,
7520
- 0.04427743881741981,
7521
- 0.028531388628933663,
7522
- 0.028531388628933663,
7523
- 0.0123412297999872,
7524
- 0.0123412297999872
7525
- ],
7526
- arcfn: function(t2, derivativeFn) {
7527
- const d = derivativeFn(t2);
7528
- let l = d.x * d.x + d.y * d.y;
7529
- return typeof d.z < "u" && (l += d.z * d.z), sqrt$1(l);
7530
- },
7531
- compute: function(t2, points, _3d) {
7532
- if (t2 === 0)
7533
- return points[0].t = 0, points[0];
7534
- const order = points.length - 1;
7535
- if (t2 === 1)
7536
- return points[order].t = 1, points[order];
7537
- const mt = 1 - t2;
7538
- let p = points;
7539
- if (order === 0)
7540
- return points[0].t = t2, points[0];
7541
- if (order === 1) {
7542
- const ret = {
7543
- x: mt * p[0].x + t2 * p[1].x,
7544
- y: mt * p[0].y + t2 * p[1].y,
7545
- t: t2
7546
- };
7547
- return _3d && (ret.z = mt * p[0].z + t2 * p[1].z), ret;
7026
+ const pi$1 = Math.PI, tau = 2 * pi$1, quart = pi$1 / 2, epsilon = 1e-6, nMax = Number.MAX_SAFE_INTEGER || 9007199254740991, nMin = Number.MIN_SAFE_INTEGER || -9007199254740991, ZERO = { x: 0, y: 0, z: 0 }, utils = {
7027
+ // Legendre-Gauss abscissae with n=24 (x_i values, defined at i=n as the roots of the nth order Legendre polynomial Pn(x))
7028
+ Tvalues: [
7029
+ -0.06405689286260563,
7030
+ 0.06405689286260563,
7031
+ -0.1911188674736163,
7032
+ 0.1911188674736163,
7033
+ -0.3150426796961634,
7034
+ 0.3150426796961634,
7035
+ -0.4337935076260451,
7036
+ 0.4337935076260451,
7037
+ -0.5454214713888396,
7038
+ 0.5454214713888396,
7039
+ -0.6480936519369755,
7040
+ 0.6480936519369755,
7041
+ -0.7401241915785544,
7042
+ 0.7401241915785544,
7043
+ -0.820001985973903,
7044
+ 0.820001985973903,
7045
+ -0.8864155270044011,
7046
+ 0.8864155270044011,
7047
+ -0.9382745520027328,
7048
+ 0.9382745520027328,
7049
+ -0.9747285559713095,
7050
+ 0.9747285559713095,
7051
+ -0.9951872199970213,
7052
+ 0.9951872199970213
7053
+ ],
7054
+ // Legendre-Gauss weights with n=24 (w_i values, defined by a function linked to in the Bezier primer article)
7055
+ Cvalues: [
7056
+ 0.12793819534675216,
7057
+ 0.12793819534675216,
7058
+ 0.1258374563468283,
7059
+ 0.1258374563468283,
7060
+ 0.12167047292780339,
7061
+ 0.12167047292780339,
7062
+ 0.1155056680537256,
7063
+ 0.1155056680537256,
7064
+ 0.10744427011596563,
7065
+ 0.10744427011596563,
7066
+ 0.09761865210411388,
7067
+ 0.09761865210411388,
7068
+ 0.08619016153195327,
7069
+ 0.08619016153195327,
7070
+ 0.0733464814110803,
7071
+ 0.0733464814110803,
7072
+ 0.05929858491543678,
7073
+ 0.05929858491543678,
7074
+ 0.04427743881741981,
7075
+ 0.04427743881741981,
7076
+ 0.028531388628933663,
7077
+ 0.028531388628933663,
7078
+ 0.0123412297999872,
7079
+ 0.0123412297999872
7080
+ ],
7081
+ arcfn: function(t2, derivativeFn) {
7082
+ const d = derivativeFn(t2);
7083
+ let l = d.x * d.x + d.y * d.y;
7084
+ return typeof d.z < "u" && (l += d.z * d.z), sqrt$1(l);
7085
+ },
7086
+ compute: function(t2, points, _3d) {
7087
+ if (t2 === 0)
7088
+ return points[0].t = 0, points[0];
7089
+ const order = points.length - 1;
7090
+ if (t2 === 1)
7091
+ return points[order].t = 1, points[order];
7092
+ const mt = 1 - t2;
7093
+ let p = points;
7094
+ if (order === 0)
7095
+ return points[0].t = t2, points[0];
7096
+ if (order === 1) {
7097
+ const ret = {
7098
+ x: mt * p[0].x + t2 * p[1].x,
7099
+ y: mt * p[0].y + t2 * p[1].y,
7100
+ t: t2
7101
+ };
7102
+ return _3d && (ret.z = mt * p[0].z + t2 * p[1].z), ret;
7548
7103
  }
7549
7104
  if (order < 4) {
7550
7105
  let mt2 = mt * mt, t22 = t2 * t2, a, b, c, d = 0;
@@ -7605,8 +7160,8 @@ const pi$1 = Math.PI, tau = 2 * pi$1, quart = pi$1 / 2, epsilon = 1e-6, nMax = N
7605
7160
  }
7606
7161
  return dpoints;
7607
7162
  },
7608
- between: function(v, m, M) {
7609
- return m <= v && v <= M || utils.approximately(v, m) || utils.approximately(v, M);
7163
+ between: function(v, m2, M) {
7164
+ return m2 <= v && v <= M || utils.approximately(v, m2) || utils.approximately(v, M);
7610
7165
  },
7611
7166
  approximately: function(a, b, precision) {
7612
7167
  return abs$1(a - b) <= (precision || epsilon);
@@ -7757,38 +7312,38 @@ const pi$1 = Math.PI, tau = 2 * pi$1, quart = pi$1 / 2, epsilon = 1e-6, nMax = N
7757
7312
  },
7758
7313
  roots: function(points, line2) {
7759
7314
  line2 = line2 || { p1: { x: 0, y: 0 }, p2: { x: 1, y: 0 } };
7760
- const order = points.length - 1, aligned = utils.align(points, line2), reduce = function(t2) {
7315
+ const order = points.length - 1, aligned = utils.align(points, line2), reduce2 = function(t2) {
7761
7316
  return 0 <= t2 && t2 <= 1;
7762
7317
  };
7763
7318
  if (order === 2) {
7764
7319
  const a2 = aligned[0].y, b2 = aligned[1].y, c2 = aligned[2].y, d2 = a2 - 2 * b2 + c2;
7765
7320
  if (d2 !== 0) {
7766
7321
  const m1 = -sqrt$1(b2 * b2 - a2 * c2), m2 = -a2 + b2, v12 = -(m1 + m2) / d2, v2 = -(-m1 + m2) / d2;
7767
- return [v12, v2].filter(reduce);
7322
+ return [v12, v2].filter(reduce2);
7768
7323
  } else if (b2 !== c2 && d2 === 0)
7769
- return [(2 * b2 - c2) / (2 * b2 - 2 * c2)].filter(reduce);
7324
+ return [(2 * b2 - c2) / (2 * b2 - 2 * c2)].filter(reduce2);
7770
7325
  return [];
7771
7326
  }
7772
7327
  const pa = aligned[0].y, pb = aligned[1].y, pc = aligned[2].y, pd = aligned[3].y;
7773
7328
  let d = -pa + 3 * pb - 3 * pc + pd, a = 3 * pa - 6 * pb + 3 * pc, b = -3 * pa + 3 * pb, c = pa;
7774
7329
  if (utils.approximately(d, 0)) {
7775
7330
  if (utils.approximately(a, 0))
7776
- return utils.approximately(b, 0) ? [] : [-c / b].filter(reduce);
7331
+ return utils.approximately(b, 0) ? [] : [-c / b].filter(reduce2);
7777
7332
  const q3 = sqrt$1(b * b - 4 * a * c), a2 = 2 * a;
7778
- return [(q3 - b) / a2, (-b - q3) / a2].filter(reduce);
7333
+ return [(q3 - b) / a2, (-b - q3) / a2].filter(reduce2);
7779
7334
  }
7780
7335
  a /= d, b /= d, c /= d;
7781
7336
  const p = (3 * b - a * a) / 3, p3 = p / 3, q = (2 * a * a * a - 9 * a * b + 27 * c) / 27, q2 = q / 2, discriminant = q2 * q2 + p3 * p3 * p3;
7782
7337
  let u1, v1, x1, x2, x3;
7783
7338
  if (discriminant < 0) {
7784
7339
  const mp3 = -p / 3, mp33 = mp3 * mp3 * mp3, r2 = sqrt$1(mp33), t2 = -q / (2 * r2), cosphi = t2 < -1 ? -1 : t2 > 1 ? 1 : t2, phi = acos$1(cosphi), crtr = crt(r2), t1 = 2 * crtr;
7785
- return x1 = t1 * cos$1(phi / 3) - a / 3, x2 = t1 * cos$1((phi + tau) / 3) - a / 3, x3 = t1 * cos$1((phi + 2 * tau) / 3) - a / 3, [x1, x2, x3].filter(reduce);
7340
+ return x1 = t1 * cos$1(phi / 3) - a / 3, x2 = t1 * cos$1((phi + tau) / 3) - a / 3, x3 = t1 * cos$1((phi + 2 * tau) / 3) - a / 3, [x1, x2, x3].filter(reduce2);
7786
7341
  } else {
7787
7342
  if (discriminant === 0)
7788
- return u1 = q2 < 0 ? crt(-q2) : -crt(q2), x1 = 2 * u1 - a / 3, x2 = -u1 - a / 3, [x1, x2].filter(reduce);
7343
+ return u1 = q2 < 0 ? crt(-q2) : -crt(q2), x1 = 2 * u1 - a / 3, x2 = -u1 - a / 3, [x1, x2].filter(reduce2);
7789
7344
  {
7790
7345
  const sd = sqrt$1(discriminant);
7791
- return u1 = crt(-q2 + sd), v1 = crt(q2 + sd), [u1 - v1 - a / 3].filter(reduce);
7346
+ return u1 = crt(-q2 + sd), v1 = crt(q2 + sd), [u1 - v1 - a / 3].filter(reduce2);
7792
7347
  }
7793
7348
  }
7794
7349
  },
@@ -7875,8 +7430,8 @@ const pi$1 = Math.PI, tau = 2 * pi$1, quart = pi$1 / 2, epsilon = 1e-6, nMax = N
7875
7430
  },
7876
7431
  getccenter: function(p1, p2, p3) {
7877
7432
  const dx1 = p2.x - p1.x, dy1 = p2.y - p1.y, dx2 = p3.x - p2.x, dy2 = p3.y - p2.y, dx1p = dx1 * cos$1(quart) - dy1 * sin$1(quart), dy1p = dx1 * sin$1(quart) + dy1 * cos$1(quart), dx2p = dx2 * cos$1(quart) - dy2 * sin$1(quart), dy2p = dx2 * sin$1(quart) + dy2 * cos$1(quart), mx1 = (p1.x + p2.x) / 2, my1 = (p1.y + p2.y) / 2, mx2 = (p2.x + p3.x) / 2, my2 = (p2.y + p3.y) / 2, mx1n = mx1 + dx1p, my1n = my1 + dy1p, mx2n = mx2 + dx2p, my2n = my2 + dy2p, arc = utils.lli8(mx1, my1, mx1n, my1n, mx2, my2, mx2n, my2n), r2 = utils.dist(arc, p1);
7878
- let s = atan2(p1.y - arc.y, p1.x - arc.x), m = atan2(p2.y - arc.y, p2.x - arc.x), e = atan2(p3.y - arc.y, p3.x - arc.x), _;
7879
- return s < e ? ((s > m || m > e) && (s += tau), s > e && (_ = e, e = s, s = _)) : e < m && m < s ? (_ = e, e = s, s = _) : e += tau, arc.s = s, arc.e = e, arc.r = r2, arc;
7433
+ let s = atan2(p1.y - arc.y, p1.x - arc.x), m2 = atan2(p2.y - arc.y, p2.x - arc.x), e = atan2(p3.y - arc.y, p3.x - arc.x), _;
7434
+ return s < e ? ((s > m2 || m2 > e) && (s += tau), s > e && (_ = e, e = s, s = _)) : e < m2 && m2 < s ? (_ = e, e = s, s = _) : e += tau, arc.s = s, arc.e = e, arc.r = r2, arc;
7880
7435
  },
7881
7436
  numberSort: function(a, b) {
7882
7437
  return a - b;
@@ -8110,8 +7665,8 @@ class Bezier {
8110
7665
  x: r2.y * r1.z - r2.z * r1.y,
8111
7666
  y: r2.z * r1.x - r2.x * r1.z,
8112
7667
  z: r2.x * r1.y - r2.y * r1.x
8113
- }, m = sqrt(c.x * c.x + c.y * c.y + c.z * c.z);
8114
- c.x /= m, c.y /= m, c.z /= m;
7668
+ }, m2 = sqrt(c.x * c.x + c.y * c.y + c.z * c.z);
7669
+ c.x /= m2, c.y /= m2, c.z /= m2;
8115
7670
  const R = [
8116
7671
  c.x * c.x,
8117
7672
  c.x * c.y - c.z,
@@ -8265,8 +7820,8 @@ class Bezier {
8265
7820
  y: p.y - o.y
8266
7821
  }, rc = distanceFn ? distanceFn((t2 + 1) / order) : d;
8267
7822
  distanceFn && !clockwise && (rc = -rc);
8268
- var m = sqrt(ov.x * ov.x + ov.y * ov.y);
8269
- ov.x /= m, ov.y /= m, np[t2 + 1] = {
7823
+ var m2 = sqrt(ov.x * ov.x + ov.y * ov.y);
7824
+ ov.x /= m2, ov.y /= m2, np[t2 + 1] = {
8270
7825
  x: p.x + rc * ov.x,
8271
7826
  y: p.y + rc * ov.y
8272
7827
  };
@@ -8382,38 +7937,589 @@ class Bezier {
8382
7937
  x: arc.x + arc.r * cos(arc.e),
8383
7938
  y: arc.y + arc.r * sin(arc.e)
8384
7939
  };
8385
- arc.e += utils.angle({ x: arc.x, y: arc.y }, d, this.get(1));
7940
+ arc.e += utils.angle({ x: arc.x, y: arc.y }, d, this.get(1));
7941
+ }
7942
+ break;
7943
+ }
7944
+ t_e = t_e + (t_e - t_s) / 2;
7945
+ } else
7946
+ t_e = t_m;
7947
+ while (!done && safety++ < 100);
7948
+ if (safety >= 100)
7949
+ break;
7950
+ prev_arc = prev_arc || arc, circles.push(prev_arc), t_s = prev_e;
7951
+ } while (t_e < 1);
7952
+ return circles;
7953
+ }
7954
+ }
7955
+ function toDomPrecision(v) {
7956
+ return v === null ? 0.01 : Math.round(v * 100) / 100;
7957
+ }
7958
+ function bezierControlPoints(diagramEdge) {
7959
+ let [start2, ...bezierPoints] = diagramEdge.points;
7960
+ invariant(start2, "start should be defined");
7961
+ const handles = [
7962
+ // start
7963
+ ];
7964
+ for (; hasAtLeast(bezierPoints, 3); ) {
7965
+ const [cp1, cp2, end, ...rest] = bezierPoints, bezier = new Bezier(start2[0], start2[1], cp1[0], cp1[1], cp2[0], cp2[1], end[0], end[1]), inflections = bezier.inflections();
7966
+ inflections.length === 0 && inflections.push(0.5), inflections.forEach((t2) => {
7967
+ const { x, y } = bezier.get(t2);
7968
+ handles.push({
7969
+ x: toDomPrecision(x),
7970
+ y: toDomPrecision(y)
7971
+ });
7972
+ }), bezierPoints = rest, start2 = end;
7973
+ }
7974
+ return invariant(bezierPoints.length === 0, "all points should be consumed"), diagramEdge.dir === "back" && handles.length > 0 && handles.reverse(), handles;
7975
+ }
7976
+ const isClose = (a, b) => Math.abs(a - b) < 3.1;
7977
+ function isSamePoint$1(a, b) {
7978
+ const [ax, ay] = isArray(a) ? a : [a.x, a.y], [bx, by] = isArray(b) ? b : [b.x, b.y];
7979
+ return isClose(ax, bx) && isClose(ay, by);
7980
+ }
7981
+ const useXYFlow = useReactFlow, useXYNodesData = useNodesData;
7982
+ function useXYStore(selector2, equalityFn) {
7983
+ return useStore(
7984
+ // @ts-expect-error - types are not correct
7985
+ selector2,
7986
+ equalityFn ?? shallowEqual
7987
+ );
7988
+ }
7989
+ const useXYStoreApi = useStoreApi;
7990
+ class Rect {
7991
+ constructor() {
7992
+ __publicField(this, "id");
7993
+ __publicField(this, "minX", new Variable());
7994
+ __publicField(this, "minY", new Variable());
7995
+ __publicField(this, "maxX", new Variable());
7996
+ __publicField(this, "maxY", new Variable());
7997
+ }
7998
+ get x() {
7999
+ return this.minX;
8000
+ }
8001
+ get y() {
8002
+ return this.minY;
8003
+ }
8004
+ get positionAbsolute() {
8005
+ return {
8006
+ x: this.x.value(),
8007
+ y: this.y.value()
8008
+ };
8009
+ }
8010
+ get dimensions() {
8011
+ return {
8012
+ width: this.maxX.value() - this.minX.value(),
8013
+ height: this.maxY.value() - this.minY.value()
8014
+ };
8015
+ }
8016
+ // Position relative to parent
8017
+ get position() {
8018
+ const positionAbsolute = this.positionAbsolute;
8019
+ if (!this.parent)
8020
+ return positionAbsolute;
8021
+ const parentPosition = this.parent.positionAbsolute;
8022
+ return {
8023
+ x: positionAbsolute.x - parentPosition.x,
8024
+ y: positionAbsolute.y - parentPosition.y
8025
+ };
8026
+ }
8027
+ }
8028
+ class Compound extends Rect {
8029
+ constructor(solver, xynode, parent = null) {
8030
+ super();
8031
+ __publicField(this, "children", []);
8032
+ this.solver = solver, this.parent = parent, this.id = xynode.id, solver.createConstraint(this.maxX, Operator.Ge, this.minX), solver.createConstraint(this.maxY, Operator.Ge, this.minY), parent && parent.addChild(this);
8033
+ }
8034
+ addChild(rect) {
8035
+ this.children.push(rect);
8036
+ const leftPadding = new Expression(
8037
+ rect.minX,
8038
+ [-1, this.minX]
8039
+ ), { weak } = Strength;
8040
+ this.solver.createConstraint(leftPadding, Operator.Ge, 40), this.solver.createConstraint(leftPadding, Operator.Eq, 40, weak);
8041
+ const topPadding = new Expression(
8042
+ rect.minY,
8043
+ [-1, this.minY]
8044
+ );
8045
+ this.solver.createConstraint(topPadding, Operator.Ge, 60), this.solver.createConstraint(topPadding, Operator.Eq, 60, weak);
8046
+ const rightPadding = new Expression(
8047
+ this.maxX,
8048
+ [-1, rect.maxX]
8049
+ );
8050
+ this.solver.createConstraint(rightPadding, Operator.Ge, 40), this.solver.createConstraint(rightPadding, Operator.Eq, 40, weak);
8051
+ const bottomPadding = new Expression(
8052
+ this.maxY,
8053
+ [-1, rect.maxY]
8054
+ );
8055
+ this.solver.createConstraint(bottomPadding, Operator.Ge, 40), this.solver.createConstraint(bottomPadding, Operator.Eq, 40, weak);
8056
+ }
8057
+ }
8058
+ class Leaf extends Rect {
8059
+ constructor(solver, xynode, parent = null, isEditing = !1) {
8060
+ super(), this.parent = parent, this.isEditing = isEditing, this.id = xynode.id;
8061
+ const x = Math.ceil(xynode.internals.positionAbsolute.x), y = Math.ceil(xynode.internals.positionAbsolute.y), { width, height } = getNodeDimensions(xynode);
8062
+ if (this.maxX = new Expression(this.minX, Math.ceil(width)), this.maxY = new Expression(this.minY, Math.ceil(height)), isEditing) {
8063
+ const superStrong = Strength.create(100, 0, 0);
8064
+ solver.addEditVariable(this.minX, superStrong), solver.addEditVariable(this.minY, superStrong), solver.suggestValue(this.minX, x), solver.suggestValue(this.minY, y);
8065
+ } else {
8066
+ const halfMedium = Strength.create(0, 1, 0, 0.5);
8067
+ solver.createConstraint(this.minX, Operator.Eq, x, halfMedium), solver.createConstraint(this.minY, Operator.Eq, y, halfMedium);
8068
+ }
8069
+ parent && parent.addChild(this);
8070
+ }
8071
+ }
8072
+ function createLayoutConstraints(xyflow, xyflowApi, draggingNodeId) {
8073
+ var _a;
8074
+ const { parentLookup, nodeLookup } = xyflowApi.getState(), solver = new Solver(), rects = /* @__PURE__ */ new Map(), traverse = new Array();
8075
+ for (const [, xynode] of nodeLookup)
8076
+ isNullish(xynode.parentId) && traverse.push({
8077
+ xynode,
8078
+ parent: null
8079
+ });
8080
+ for (; traverse.length > 0; ) {
8081
+ const { xynode, parent } = traverse.shift(), isDragging = xynode.dragging === !0 || xynode.id === draggingNodeId, shouldTraverse = !isDragging && xynode.type === "compound" && isAncestor(xynode.id, draggingNodeId), rect = shouldTraverse ? new Compound(solver, xynode, parent) : new Leaf(solver, xynode, parent, isDragging);
8082
+ rects.set(xynode.id, rect), shouldTraverse && ((_a = parentLookup.get(xynode.id)) == null || _a.forEach((child) => {
8083
+ traverse.push({
8084
+ xynode: child,
8085
+ parent: rect
8086
+ });
8087
+ }));
8088
+ }
8089
+ solver.updateVariables(), solver.maxIterations = 1e3;
8090
+ function updateXYFlowNodes() {
8091
+ solver.updateVariables(), xyflow.setNodes(
8092
+ (nodes) => nodes.map((n) => {
8093
+ if (n.id === draggingNodeId || n.dragging === !0)
8094
+ return n;
8095
+ const rect = rects.get(n.id);
8096
+ if (!rect)
8097
+ return n;
8098
+ const dimensions = rect.dimensions, newXY = rect.position;
8099
+ return newXY.x !== n.position.x || newXY.y !== n.position.y ? {
8100
+ ...n,
8101
+ position: rect.position,
8102
+ width: dimensions.width,
8103
+ height: dimensions.height,
8104
+ measured: dimensions
8105
+ } : dimensions.width !== n.width || dimensions.height !== n.height ? {
8106
+ ...n,
8107
+ width: dimensions.width,
8108
+ height: dimensions.height,
8109
+ measured: dimensions
8110
+ } : n;
8111
+ })
8112
+ );
8113
+ }
8114
+ let animationFrameId = null;
8115
+ function onNodeDrag(xynode) {
8116
+ const pos = nodeLookup.get(xynode.id).internals.positionAbsolute, rect = nonNullable(rects.get(xynode.id));
8117
+ solver.suggestValue(rect.minX, Math.ceil(pos.x)), solver.suggestValue(rect.minY, Math.ceil(pos.y)), animationFrameId ?? (animationFrameId = requestAnimationFrame(() => {
8118
+ updateXYFlowNodes(), animationFrameId = null;
8119
+ }));
8120
+ }
8121
+ return {
8122
+ onNodeDrag,
8123
+ updateXYFlowNodes
8124
+ };
8125
+ }
8126
+ function useLayoutConstraints() {
8127
+ const diagramApi = useDiagramStoreApi(), xyflowApi = useXYStoreApi(), solverRef = useRef(), dragStartedAt = useRef({
8128
+ x: 0,
8129
+ y: 0
8130
+ });
8131
+ return useMemo(() => ({
8132
+ onNodeDragStart: (event, xynode) => {
8133
+ dragStartedAt.current = {
8134
+ x: event.clientX,
8135
+ y: event.clientY
8136
+ };
8137
+ const { xyflow, cancelSaveManualLayout } = diagramApi.getState();
8138
+ cancelSaveManualLayout(), solverRef.current = createLayoutConstraints(xyflow, xyflowApi, xynode.id);
8139
+ },
8140
+ onNodeDrag: (_event, xynode) => {
8141
+ var _a;
8142
+ invariant(solverRef.current, "solverRef.current should be defined"), (_a = solverRef.current) == null || _a.onNodeDrag(xynode);
8143
+ },
8144
+ onNodeDragStop: (event, _xynode) => {
8145
+ isSamePoint$1(dragStartedAt.current, { x: event.clientX, y: event.clientY }) || diagramApi.getState().triggerSaveManualLayout(xyflowApi), solverRef.current = void 0;
8146
+ }
8147
+ }), [xyflowApi, diagramApi]);
8148
+ }
8149
+ const ZIndexes = {
8150
+ Compound: 1,
8151
+ Edge: 2,
8152
+ Element: 3
8153
+ }, MinZoom = 0.1, StringSet = Set, DEFAULT_PROPS = {
8154
+ viewSyncDebounceTimeout: null,
8155
+ initialized: !1,
8156
+ xyflowSynced: !1,
8157
+ previousViews: [],
8158
+ viewportChanged: !1,
8159
+ activeDynamicViewStep: null,
8160
+ focusedNodeId: null,
8161
+ hoveredNodeId: null,
8162
+ hoveredEdgeId: null,
8163
+ lastClickedNodeId: null,
8164
+ lastClickedEdgeId: null,
8165
+ dimmed: new StringSet(),
8166
+ lastOnNavigate: null,
8167
+ onChange: null,
8168
+ onNavigateTo: null,
8169
+ onNodeClick: null,
8170
+ onNodeContextMenu: null,
8171
+ onCanvasContextMenu: null,
8172
+ onEdgeClick: null,
8173
+ onEdgeContextMenu: null,
8174
+ onCanvasClick: null,
8175
+ onCanvasDblClick: null
8176
+ }, noReplace = !1;
8177
+ let storeDevId = 1;
8178
+ const EmptyStringSet = new StringSet();
8179
+ function createDiagramStore(props) {
8180
+ return createWithEqualityFn(
8181
+ subscribeWithSelector(
8182
+ devtools(
8183
+ (set2, get2) => ({
8184
+ ...DEFAULT_PROPS,
8185
+ ...props,
8186
+ isDynamicView: () => {
8187
+ var _a;
8188
+ return ((_a = get2().view) == null ? void 0 : _a.__) === "dynamic";
8189
+ },
8190
+ updateView: (nextView) => {
8191
+ let {
8192
+ viewSyncDebounceTimeout,
8193
+ xyflow,
8194
+ dimmed: dimmed2,
8195
+ xyflowSynced,
8196
+ view: current,
8197
+ lastOnNavigate,
8198
+ previousViews,
8199
+ focusedNodeId,
8200
+ lastClickedNodeId,
8201
+ lastClickedEdgeId,
8202
+ activeDynamicViewStep,
8203
+ hoveredEdgeId,
8204
+ hoveredNodeId
8205
+ } = get2();
8206
+ if (viewSyncDebounceTimeout !== null && (clearTimeout(viewSyncDebounceTimeout), viewSyncDebounceTimeout = null), shallowEqual(current, nextView)) {
8207
+ DEV && console.debug("store: skip updateView");
8208
+ return;
8209
+ }
8210
+ if (current.id === nextView.id) {
8211
+ const nodeIds = new StringSet(nextView.nodes.map((n) => n.id)), edgeIds = new StringSet(nextView.edges.map((e) => e.id));
8212
+ if (lastClickedNodeId && !nodeIds.has(lastClickedNodeId) && (lastClickedNodeId = null), hoveredNodeId && !nodeIds.has(hoveredNodeId) && (hoveredNodeId = null), focusedNodeId && !nodeIds.has(focusedNodeId) && (focusedNodeId = null), lastClickedEdgeId && !edgeIds.has(lastClickedEdgeId) && (lastClickedEdgeId = null), hoveredEdgeId && !edgeIds.has(hoveredEdgeId) && (hoveredEdgeId = null), activeDynamicViewStep && !edgeIds.has(StepEdgeId(activeDynamicViewStep)) && (activeDynamicViewStep = null), xyflowSynced = deepEqual([current.nodes, current.edges], [nextView.nodes, nextView.edges]), dimmed2.size > 0) {
8213
+ let nextDimmed = new StringSet([...dimmed2].filter((id2) => nodeIds.has(id2) || edgeIds.has(id2)));
8214
+ nextDimmed.size !== dimmed2.size && (dimmed2 = nextDimmed);
8215
+ }
8216
+ } else {
8217
+ if (lastOnNavigate && lastOnNavigate.toView !== nextView.id && lastOnNavigate.fromView !== nextView.id && (lastOnNavigate = null), !lastOnNavigate) {
8218
+ const zoom2 = xyflow.getZoom();
8219
+ xyflow.setCenter(nextView.width / 2, nextView.height / 2, { zoom: zoom2 });
8220
+ }
8221
+ lastClickedEdgeId = null, lastClickedNodeId = null, hoveredEdgeId = null, hoveredNodeId = null, focusedNodeId = null, activeDynamicViewStep = null, dimmed2 = EmptyStringSet, previousViews = [
8222
+ current,
8223
+ ...previousViews.filter((v) => v.id !== nextView.id && v.id !== current.id)
8224
+ ], xyflowSynced = !1;
8225
+ }
8226
+ set2(
8227
+ {
8228
+ viewSyncDebounceTimeout,
8229
+ view: nextView,
8230
+ activeDynamicViewStep,
8231
+ xyflowSynced,
8232
+ lastOnNavigate,
8233
+ previousViews,
8234
+ lastClickedNodeId,
8235
+ lastClickedEdgeId,
8236
+ focusedNodeId,
8237
+ hoveredEdgeId,
8238
+ hoveredNodeId,
8239
+ dimmed: dimmed2
8240
+ },
8241
+ noReplace,
8242
+ "update-view"
8243
+ );
8244
+ },
8245
+ focusOnNode: (nodeId) => {
8246
+ const { focusedNodeId, view } = get2();
8247
+ if (nodeId !== focusedNodeId) {
8248
+ const notDimmed = new StringSet([nodeId]), dimmed2 = new StringSet();
8249
+ for (const edge of view.edges)
8250
+ edge.source === nodeId || edge.target === nodeId ? (notDimmed.add(edge.source), notDimmed.add(edge.target)) : dimmed2.add(edge.id);
8251
+ for (const node of view.nodes)
8252
+ notDimmed.has(node.id) || dimmed2.add(node.id);
8253
+ set2(
8254
+ {
8255
+ activeDynamicViewStep: null,
8256
+ focusedNodeId: nodeId,
8257
+ dimmed: dimmed2
8258
+ },
8259
+ noReplace,
8260
+ `focus on node: ${nodeId}`
8261
+ );
8262
+ }
8263
+ },
8264
+ setHoveredNode: (nodeId) => {
8265
+ nodeId !== get2().hoveredNodeId && set2({ hoveredNodeId: nodeId });
8266
+ },
8267
+ setHoveredEdge: (edgeId) => {
8268
+ edgeId !== get2().hoveredEdgeId && set2({ hoveredEdgeId: edgeId });
8269
+ },
8270
+ setLastClickedNode: (nodeId) => {
8271
+ nodeId !== get2().lastClickedNodeId && set2({ lastClickedNodeId: nodeId });
8272
+ },
8273
+ setLastClickedEdge: (edgeId) => {
8274
+ edgeId !== get2().lastClickedEdgeId && set2({ lastClickedEdgeId: edgeId });
8275
+ },
8276
+ resetLastClicked: () => {
8277
+ let {
8278
+ activeDynamicViewStep,
8279
+ focusedNodeId,
8280
+ lastClickedNodeId,
8281
+ lastClickedEdgeId
8282
+ } = get2();
8283
+ (activeDynamicViewStep || focusedNodeId || lastClickedNodeId || lastClickedEdgeId) && set2(
8284
+ {
8285
+ activeDynamicViewStep: null,
8286
+ focusedNodeId: null,
8287
+ lastClickedNodeId: null,
8288
+ lastClickedEdgeId: null,
8289
+ dimmed: EmptyStringSet
8290
+ },
8291
+ noReplace,
8292
+ "resetLastClicked"
8293
+ );
8294
+ },
8295
+ getElement: (fqn) => {
8296
+ const { view } = get2();
8297
+ return view.nodes.find(({ id: id2 }) => id2 === fqn) ?? null;
8298
+ },
8299
+ triggerChangeElementStyle: (change) => {
8300
+ DEV && console.debug("triggerChangeElementStyle", change);
8301
+ const { view, updateView, onChange } = get2();
8302
+ let hasChanges = !1;
8303
+ const nodes = view.nodes.map((origin) => {
8304
+ var _a, _b;
8305
+ if (!change.targets.includes(origin.id))
8306
+ return origin;
8307
+ let element2 = origin;
8308
+ for (const [key, value] of entries.strict(change.style))
8309
+ switch (key) {
8310
+ case "shape":
8311
+ value !== element2.shape && (element2 = {
8312
+ ...element2,
8313
+ shape: value
8314
+ });
8315
+ break;
8316
+ case "color":
8317
+ value !== element2.color && (element2 = {
8318
+ ...element2,
8319
+ color: value
8320
+ });
8321
+ break;
8322
+ case "opacity":
8323
+ value !== ((_a = element2.style) == null ? void 0 : _a.opacity) && (element2 = {
8324
+ ...element2,
8325
+ style: {
8326
+ ...element2.style,
8327
+ opacity: value
8328
+ }
8329
+ });
8330
+ break;
8331
+ case "border":
8332
+ value !== ((_b = element2.style) == null ? void 0 : _b.border) && (element2 = {
8333
+ ...element2,
8334
+ style: {
8335
+ ...element2.style,
8336
+ border: value
8337
+ }
8338
+ });
8339
+ break;
8340
+ default:
8341
+ nonexhaustive(key);
8342
+ }
8343
+ return element2 !== origin ? (hasChanges = !0, element2) : origin;
8344
+ });
8345
+ hasChanges && updateView({
8346
+ ...view,
8347
+ nodes
8348
+ }), onChange == null || onChange({ change });
8349
+ },
8350
+ cancelSaveManualLayout: () => {
8351
+ let { viewSyncDebounceTimeout } = get2();
8352
+ viewSyncDebounceTimeout !== null && (clearTimeout(viewSyncDebounceTimeout), set2({ viewSyncDebounceTimeout: null }));
8353
+ },
8354
+ triggerSaveManualLayout: (xystore) => {
8355
+ let { viewSyncDebounceTimeout: debounced, onChange } = get2();
8356
+ if (!onChange) {
8357
+ DEV && console.debug("ignore triggerSaveManualLayout, as no onChange handler is set");
8358
+ return;
8359
+ }
8360
+ debounced && clearTimeout(debounced), debounced = setTimeout(() => {
8361
+ const { nodeLookup } = xystore.getState(), { xyflow, onChange: onChange2 } = get2();
8362
+ set2({ viewSyncDebounceTimeout: null });
8363
+ const movedNodes = new StringSet(), nodes = reduce([...nodeLookup.values()], (acc, node) => {
8364
+ const dimensions = getNodeDimensions(node);
8365
+ return isSamePoint$1(node.internals.positionAbsolute, node.data.element.position) || movedNodes.add(node.id), acc[node.data.fqn] = {
8366
+ x: node.internals.positionAbsolute.x,
8367
+ y: node.internals.positionAbsolute.y,
8368
+ width: dimensions.width,
8369
+ height: dimensions.height
8370
+ }, acc;
8371
+ }, {}), edges = reduce(xyflow.getEdges(), (acc, { source, target, data }) => {
8372
+ let controlPoints = data.controlPoints;
8373
+ return !controlPoints && (movedNodes.has(source) || movedNodes.has(target)) && (controlPoints = bezierControlPoints(data.edge)), controlPoints && (acc[data.edge.id] = {
8374
+ controlPoints
8375
+ }), acc;
8376
+ }, {});
8377
+ if (movedNodes.size === 0 && isEmpty(edges)) {
8378
+ DEV && console.debug("ignore triggerSaveManualLayout, as no changes detected");
8379
+ return;
8380
+ }
8381
+ const change = {
8382
+ op: "save-manual-layout",
8383
+ nodes,
8384
+ edges
8385
+ };
8386
+ DEV && console.debug("triggerSaveManualLayout", change), onChange2 == null || onChange2({ change });
8387
+ }, 2e3), set2(
8388
+ {
8389
+ viewSyncDebounceTimeout: debounced
8390
+ },
8391
+ noReplace,
8392
+ "debounce sync state"
8393
+ );
8394
+ },
8395
+ triggerOnNavigateTo: (xynodeId, event) => {
8396
+ var _a, _b;
8397
+ const { xyflow, view } = get2(), xynode = xyflow.getInternalNode(xynodeId), element2 = xynode == null ? void 0 : xynode.data.element;
8398
+ invariant(!!xynode && (element2 == null ? void 0 : element2.navigateTo), `node is not navigable: ${xynodeId}`), set2(
8399
+ {
8400
+ lastClickedNodeId: xynodeId,
8401
+ lastOnNavigate: {
8402
+ fromView: view.id,
8403
+ toView: element2.navigateTo,
8404
+ element: element2,
8405
+ elementScreenPosition: xyflow.flowToScreenPosition({
8406
+ x: xynode.internals.positionAbsolute.x,
8407
+ // + dimensions.width / 2,
8408
+ y: xynode.internals.positionAbsolute.y
8409
+ // + dimensions.height / 2
8410
+ }),
8411
+ positionCorrected: !1
8412
+ }
8413
+ },
8414
+ noReplace,
8415
+ "triggerOnNavigateTo"
8416
+ ), (_b = (_a = get2()).onNavigateTo) == null || _b.call(
8417
+ _a,
8418
+ element2.navigateTo,
8419
+ event,
8420
+ element2,
8421
+ xynode.internals.userNode
8422
+ );
8423
+ },
8424
+ fitDiagram: (xyStore) => {
8425
+ const { width, height, panZoom } = xyStore.getState(), { fitViewPadding, view, focusedNodeId } = get2(), bounds = {
8426
+ x: 0,
8427
+ y: 0,
8428
+ width: view.width,
8429
+ height: view.height
8430
+ }, viewport = getViewportForBounds(bounds, width, height, MinZoom, 1, fitViewPadding);
8431
+ panZoom == null || panZoom.setViewport(viewport, { duration: 500 }), focusedNodeId && set2(
8432
+ {
8433
+ focusedNodeId: null,
8434
+ dimmed: EmptyStringSet
8435
+ },
8436
+ noReplace,
8437
+ "unfocus"
8438
+ );
8439
+ },
8440
+ nextDynamicStep: (increment = 1) => {
8441
+ const { view, activeDynamicViewStep, xyflow, fitViewPadding } = get2();
8442
+ invariant(view.__ === "dynamic", "view is not dynamic");
8443
+ const nextStep = (activeDynamicViewStep ?? 0) + increment;
8444
+ if (nextStep <= 0 || nextStep > view.edges.length)
8445
+ return;
8446
+ const edgeId = StepEdgeId(nextStep), dimmed2 = new StringSet();
8447
+ let edge = null;
8448
+ for (const e of xyflow.getEdges()) {
8449
+ if (e.id === edgeId) {
8450
+ edge = e;
8451
+ continue;
8452
+ }
8453
+ dimmed2.add(e.id);
8386
8454
  }
8387
- break;
8455
+ invariant(!!edge, `edge not found: ${edgeId}`);
8456
+ const selected2 = [];
8457
+ for (const n of xyflow.getNodes()) {
8458
+ if (n.id === edge.source || n.id === edge.target) {
8459
+ selected2.push(n);
8460
+ continue;
8461
+ }
8462
+ dimmed2.add(n.id);
8463
+ }
8464
+ xyflow.fitView({
8465
+ duration: 400,
8466
+ maxZoom: 1,
8467
+ minZoom: MinZoom,
8468
+ padding: fitViewPadding,
8469
+ nodes: selected2
8470
+ }), set2({
8471
+ focusedNodeId: null,
8472
+ activeDynamicViewStep: nextStep,
8473
+ dimmed: dimmed2
8474
+ });
8475
+ },
8476
+ stopDynamicView: () => {
8477
+ const { xyflow, fitViewPadding } = get2();
8478
+ set2({
8479
+ activeDynamicViewStep: null,
8480
+ dimmed: EmptyStringSet
8481
+ }), xyflow.fitView({
8482
+ duration: 400,
8483
+ maxZoom: 1,
8484
+ minZoom: MinZoom,
8485
+ padding: fitViewPadding
8486
+ });
8388
8487
  }
8389
- t_e = t_e + (t_e - t_s) / 2;
8390
- } else
8391
- t_e = t_m;
8392
- while (!done && safety++ < 100);
8393
- if (safety >= 100)
8394
- break;
8395
- prev_arc = prev_arc || arc, circles.push(prev_arc), t_s = prev_e;
8396
- } while (t_e < 1);
8397
- return circles;
8398
- }
8488
+ }),
8489
+ {
8490
+ name: `DiagramStore ${storeDevId++} - ${props.view.id}`,
8491
+ enabled: DEV
8492
+ }
8493
+ )
8494
+ ),
8495
+ shallow
8496
+ );
8399
8497
  }
8400
- function deriveEdgePoints(bezierSpline) {
8401
- let [start2, ...bezierPoints] = bezierSpline;
8402
- invariant(start2, "start should be defined");
8403
- const handles = [
8404
- // start
8405
- ];
8406
- for (; hasAtLeast(bezierPoints, 3); ) {
8407
- const [cp1, cp2, end, ...rest] = bezierPoints, bezier = new Bezier(start2[0], start2[1], cp1[0], cp1[1], cp2[0], cp2[1], end[0], end[1]), inflections = bezier.inflections();
8408
- inflections.length === 0 && inflections.push(0.5), inflections.forEach((t2) => {
8409
- const { x, y } = bezier.get(t2);
8410
- handles.push([x, y]);
8411
- }), bezierPoints = rest, start2 = end;
8412
- }
8413
- return invariant(bezierPoints.length === 0, "all points should be consumed"), handles;
8498
+ const DiagramContext = createContext(null);
8499
+ function DiagramContextProvider({ children: children2, view, ...props }) {
8500
+ const xyflow = useXYFlow(), store = useRef();
8501
+ return store.current || (store.current = createDiagramStore({
8502
+ xyflow,
8503
+ view,
8504
+ ...props
8505
+ })), useEffect(
8506
+ () => {
8507
+ var _a, _b;
8508
+ ((_a = store.current) == null ? void 0 : _a.getState().xyflow) !== xyflow && ((_b = store.current) == null || _b.setState({ xyflow }, !1, "update xyflow"));
8509
+ },
8510
+ [xyflow]
8511
+ ), useUpdateEffect(
8512
+ () => {
8513
+ if (!store.current) return;
8514
+ const state = store.current.getState();
8515
+ state.view !== view && state.updateView(view), hasSubObject(state, props) || store.current.setState(props, !1, "update incoming props");
8516
+ },
8517
+ [view, props]
8518
+ ), /* @__PURE__ */ jsx(DiagramContext.Provider, { value: store.current, children: children2 });
8414
8519
  }
8415
8520
  const nodeZIndex = (node) => node.level + 1;
8416
8521
  function diagramViewToXYFlowData(view, opts) {
8522
+ var _a, _b;
8417
8523
  const isDynamicView = view.__ === "dynamic", editor = {
8418
8524
  nodes: [],
8419
8525
  edges: []
@@ -8425,7 +8531,7 @@ function diagramViewToXYFlowData(view, opts) {
8425
8531
  for (; next = traverse.pop(); ) {
8426
8532
  const { node, parent } = next;
8427
8533
  node.children.length > 0 && traverse.unshift(...node.children.map((child) => ({ node: nodeById(child), parent: node })));
8428
- const isCompound = hasAtLeast(node.children, 1), position = {
8534
+ const isCompound = hasAtLeast$1(node.children, 1), position = {
8429
8535
  x: node.position[0],
8430
8536
  y: node.position[1]
8431
8537
  };
@@ -8478,8 +8584,8 @@ function diagramViewToXYFlowData(view, opts) {
8478
8584
  });
8479
8585
  }
8480
8586
  for (const edge of view.edges) {
8481
- const source = edge.source, target = edge.target, id2 = ns + edge.id, controlPoints = deriveEdgePoints(edge.points);
8482
- invariant(hasAtLeast(edge.points, 2), "edge should have at least 2 points");
8587
+ const source = edge.source, target = edge.target, id2 = ns + edge.id;
8588
+ invariant(hasAtLeast$1(edge.points, 2), "edge should have at least 2 points");
8483
8589
  const level = Math.max(nodeZIndex(nodeById(source)), nodeZIndex(nodeById(target)));
8484
8590
  editor.edges.push({
8485
8591
  id: id2,
@@ -8491,7 +8597,7 @@ function diagramViewToXYFlowData(view, opts) {
8491
8597
  data: {
8492
8598
  edge,
8493
8599
  type: "bezier",
8494
- controlPoints,
8600
+ controlPoints: ((_b = (_a = view.manualLayout) == null ? void 0 : _a.edges[edge.id]) == null ? void 0 : _b.controlPoints) || null,
8495
8601
  headPoint: edge.headArrowPoint ?? null,
8496
8602
  tailPoint: edge.tailArrowPoint ?? null,
8497
8603
  stepNum: isDynamicView ? extractStep(edge.id) : null,
@@ -8509,9 +8615,6 @@ function diagramViewToXYFlowData(view, opts) {
8509
8615
  }
8510
8616
  return editor;
8511
8617
  }
8512
- function toDomPrecision(v) {
8513
- return v === null ? 0.01 : Math.round(v * 100) / 100;
8514
- }
8515
8618
  function selectDimensions(state) {
8516
8619
  return `${Math.round(state.width)}:${Math.round(state.height)}`;
8517
8620
  }
@@ -8523,8 +8626,8 @@ function FitViewOnViewportResize({ diagramApi, xyflowApi }) {
8523
8626
  focusedNodeId || prevDimensionsRef.current === dimensions || (fitDiagram(xyflowApi), prevDimensionsRef.current = dimensions);
8524
8627
  },
8525
8628
  [dimensions, diagramApi, xyflowApi],
8526
- 200,
8527
- 800
8629
+ 250,
8630
+ 1e3
8528
8631
  ), null;
8529
8632
  }
8530
8633
  function selector$2({ view, xyflowSynced, viewportChanged, lastOnNavigate, ...s }) {
@@ -8553,25 +8656,21 @@ function FitViewOnDiagramChange() {
8553
8656
  waitCorrection,
8554
8657
  elFrom,
8555
8658
  elTo
8556
- } = useDiagramState(selector$2), diagramApi = useDiagramStoreApi(), processedRef = useRef(pendingViewId);
8659
+ } = useDiagramState(selector$2, shallowEqual), diagramApi = useDiagramStoreApi(), processedRef = useRef(pendingViewId);
8557
8660
  return useEffect(() => {
8558
8661
  if (!(!xyflowSynced || pendingViewId === processedRef.current)) {
8559
- if (waitCorrection && elTo && elFrom) {
8560
- const [x, y, zoom2] = xyflowApi.getState().transform, { xyflow, lastOnNavigate } = diagramApi.getState(), nextZoom = Math.min(
8561
- elFrom.width / elTo.width,
8562
- elFrom.height / elTo.height
8563
- ), centerFrom = lastOnNavigate.elementCenterScreenPosition;
8564
- nextZoom !== 1 && nextZoom < zoom2 && (xyflowApi.setState({ transform: [x, y, nextZoom] }), xyflow.setViewport({
8565
- x,
8566
- y,
8567
- zoom: nextZoom
8568
- }));
8569
- const centerTo = xyflow.flowToScreenPosition({
8570
- x: elTo.position[0] + elTo.width / 2,
8571
- y: elTo.position[1] + elTo.height / 2
8662
+ if (waitCorrection) {
8663
+ invariant(elTo, "elTo should be defined"), invariant(elFrom, "elFrom should be defined");
8664
+ const { xyflow, lastOnNavigate } = diagramApi.getState();
8665
+ invariant(lastOnNavigate, "lastOnNavigate should be defined");
8666
+ const fromPos = lastOnNavigate.elementScreenPosition, toPos = xyflow.flowToScreenPosition({
8667
+ x: elTo.position[0],
8668
+ // + elFrom.width / 2,
8669
+ y: elTo.position[1]
8670
+ // + elFrom.height / 2
8572
8671
  }), diff = {
8573
- x: toDomPrecision(centerFrom.x - centerTo.x),
8574
- y: toDomPrecision(centerFrom.y - centerTo.y)
8672
+ x: toDomPrecision(fromPos.x - toPos.x),
8673
+ y: toDomPrecision(fromPos.y - toPos.y)
8575
8674
  };
8576
8675
  xyflowApi.getState().panBy(diff), diagramApi.setState({ lastOnNavigate: null });
8577
8676
  return;
@@ -8596,8 +8695,8 @@ function SelectEdgesOnNodeFocus() {
8596
8695
  type: "select",
8597
8696
  selected: !0
8598
8697
  });
8599
- const anotherNode = nodeLookup.get(edge.source === focusedNodeId ? edge.target : edge.source);
8600
- anotherNode && fitViewNodes.add(anotherNode);
8698
+ const anotherNode = nonNullable(nodeLookup.get(edge.source === focusedNodeId ? edge.target : edge.source));
8699
+ fitViewNodes.add(anotherNode);
8601
8700
  } else edge.selected && edgeChanges.push({
8602
8701
  id: edge.id,
8603
8702
  type: "select",
@@ -8614,8 +8713,7 @@ function SelectEdgesOnNodeFocus() {
8614
8713
  type: "select",
8615
8714
  selected: !0
8616
8715
  }), edgeChanges.length > 0 && triggerEdgeChanges(edgeChanges), triggerNodeChanges(nodeChanges), fitView2({
8617
- includeHiddenNodes: !0,
8618
- duration: 300,
8716
+ duration: 350,
8619
8717
  padding: 0.1,
8620
8718
  minZoom: MinZoom,
8621
8719
  maxZoom: Math.max(1, transform2[2]),
@@ -8651,9 +8749,13 @@ function SyncWithDiagram() {
8651
8749
  } : update;
8652
8750
  })), setEdges(updates.edges.map((update) => {
8653
8751
  const existing = edgeLookup.get(update.id);
8654
- return existing ? deepEqual(existing.data.edge, update.data.edge) ? existing : {
8752
+ return existing ? deepEqual(existing.data.controlPoints, update.data.controlPoints) && deepEqual(existing.data.edge, update.data.edge) ? existing : {
8655
8753
  ...existing,
8656
- ...update
8754
+ ...update,
8755
+ data: {
8756
+ ...existing.data,
8757
+ ...update.data
8758
+ }
8657
8759
  } : update;
8658
8760
  })), diagramStoreApi.setState(
8659
8761
  {
@@ -8661,126 +8763,31 @@ function SyncWithDiagram() {
8661
8763
  },
8662
8764
  !1,
8663
8765
  "xyflowSynced"
8664
- );
8665
- }, [xyflowSynced, xyflowApi, diagramStoreApi]), null;
8666
- }
8667
- function getVarName(variable) {
8668
- var matches = variable.match(/^var\((.*)\)$/);
8669
- return matches ? matches[1] : variable;
8670
- }
8671
- function get(obj, path) {
8672
- var result = obj;
8673
- for (var key of path) {
8674
- if (!(key in result))
8675
- throw new Error("Path ".concat(path.join(" -> "), " does not exist in object"));
8676
- result = result[key];
8677
- }
8678
- return result;
8679
- }
8680
- function walkObject(obj, fn) {
8681
- var path = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : [], clone = {};
8682
- for (var key in obj) {
8683
- var _value = obj[key], currentPath = [...path, key];
8684
- typeof _value == "string" || typeof _value == "number" || _value == null ? clone[key] = fn(_value, currentPath) : typeof _value == "object" && !Array.isArray(_value) ? clone[key] = walkObject(_value, fn, currentPath) : console.warn('Skipping invalid key "'.concat(currentPath.join("."), '". Should be a string, number, null or object. Received: "').concat(Array.isArray(_value) ? "Array" : typeof _value, '"'));
8685
- }
8686
- return clone;
8687
- }
8688
- function assignInlineVars(varsOrContract, tokens) {
8689
- var styles = {};
8690
- if (typeof tokens == "object") {
8691
- var _contract = varsOrContract;
8692
- walkObject(tokens, (value2, path) => {
8693
- if (value2 != null) {
8694
- var varName2 = get(_contract, path);
8695
- styles[getVarName(varName2)] = String(value2);
8696
- }
8697
- });
8698
- } else {
8699
- var _vars = varsOrContract;
8700
- for (var varName in _vars) {
8701
- var value = _vars[varName];
8702
- value != null && (styles[getVarName(varName)] = value);
8703
- }
8704
- }
8705
- return Object.defineProperty(styles, "toString", {
8706
- value: function() {
8707
- return Object.keys(this).map((key) => "".concat(key, ":").concat(this[key])).join(";");
8708
- },
8709
- writable: !1
8710
- }), styles;
8766
+ );
8767
+ }, [xyflowSynced, xyflowApi, diagramStoreApi]), null;
8711
8768
  }
8712
8769
  var container$4 = "bexn7q1", dimmed$2 = "bexn7q2", edgePathBg = "bexn7q3", markerContext = "bexn7q4", controlPoint = "bexn7q5", cssEdgePath = "bexn7q7", varLabelX = "var(--bexn7q8)", varLabelY = "var(--bexn7q9)", edgeLabel = "bexn7qb", stepEdgeNumber = "bexn7qc", edgeLabelText = "bexn7qd";
8713
- function getNodeIntersectionFromCenterToPoint(intersectionNode, [x1, y1]) {
8770
+ function getNodeIntersectionFromCenterToPoint(intersectionNode, { x: x1, y: y1 }) {
8714
8771
  const {
8715
8772
  width: intersectionNodeWidth,
8716
8773
  height: intersectionNodeHeight
8717
8774
  } = getNodeDimensions(intersectionNode), intersectionNodePosition = intersectionNode.internals.positionAbsolute, w = intersectionNodeWidth / 2, h = intersectionNodeHeight / 2, x2 = intersectionNodePosition.x + w, y2 = intersectionNodePosition.y + h, xx1 = (x1 - x2) / (2 * w) - (y1 - y2) / (2 * h), yy1 = (x1 - x2) / (2 * w) + (y1 - y2) / (2 * h), a = 1 / (Math.abs(xx1) + Math.abs(yy1)), xx3 = a * xx1, yy3 = a * yy1, x = w * (xx3 + yy3) + x2, y = h * (-xx3 + yy3) + y2;
8718
- return [x, y];
8719
- }
8720
- function getNodeIntersection(intersectionNode, targetNode) {
8721
- const {
8722
- width: intersectionNodeWidth,
8723
- height: intersectionNodeHeight
8724
- } = getNodeDimensions(intersectionNode), {
8725
- width: targetNodeWidth,
8726
- height: targetNodeHeight
8727
- } = getNodeDimensions(targetNode), intersectionNodePosition = intersectionNode.internals.positionAbsolute, targetPosition = targetNode.internals.positionAbsolute, w = intersectionNodeWidth / 2, h = intersectionNodeHeight / 2, x2 = intersectionNodePosition.x + w, y2 = intersectionNodePosition.y + h, x1 = targetPosition.x + targetNodeWidth / 2, y1 = targetPosition.y + targetNodeHeight / 2, xx1 = (x1 - x2) / (2 * w) - (y1 - y2) / (2 * h), yy1 = (x1 - x2) / (2 * w) + (y1 - y2) / (2 * h), a = 1 / (Math.abs(xx1) + Math.abs(yy1)), xx3 = a * xx1, yy3 = a * yy1, x = w * (xx3 + yy3) + x2, y = h * (-xx3 + yy3) + y2;
8728
8775
  return { x, y };
8729
8776
  }
8730
- function getPointPosition(node, intersectionPoint) {
8731
- const n = {
8732
- // x: node.data.element.position[0],
8733
- // y: node.data.element.position[1],
8734
- ...node.internals.positionAbsolute,
8735
- ...getNodeDimensions(node)
8736
- }, nx = Math.round(n.x), ny = Math.round(n.y), px = Math.round(intersectionPoint.x), py = Math.round(intersectionPoint.y);
8737
- let handlePosition = Position.Top;
8738
- px <= nx + 1 ? handlePosition = Position.Left : px >= nx + n.width - 1 ? handlePosition = Position.Right : py <= ny + 1 ? handlePosition = Position.Top : py >= n.y + n.height - 1 && (handlePosition = Position.Bottom);
8739
- let handleWidth = 8, handleHeight = 8, offsetX = 0, offsetY = 0;
8740
- switch (handlePosition) {
8741
- case Position.Left:
8742
- offsetX = -handleWidth;
8743
- break;
8744
- case Position.Right:
8745
- offsetX = handleWidth;
8746
- break;
8747
- case Position.Top:
8748
- offsetY = -handleHeight;
8749
- break;
8750
- case Position.Bottom:
8751
- offsetY = handleHeight;
8752
- break;
8753
- }
8754
- return [
8755
- intersectionPoint.x + offsetX,
8756
- intersectionPoint.y + offsetY,
8757
- handlePosition
8758
- ];
8759
- }
8760
- function getEdgeParams(source, target) {
8761
- const sourceIntersectionPoint = getNodeIntersection(source, target), targetIntersectionPoint = getNodeIntersection(target, source), [sx, sy, sourcePos] = getPointPosition(source, sourceIntersectionPoint), [tx, ty, targetPos] = getPointPosition(target, targetIntersectionPoint);
8762
- return {
8763
- sx,
8764
- sy,
8765
- tx,
8766
- ty,
8767
- sourcePos,
8768
- targetPos
8769
- };
8770
- }
8771
8777
  function bezierPath(bezierSpline) {
8772
8778
  let [start2, ...points] = bezierSpline;
8773
8779
  invariant(start2, "start should be defined");
8774
8780
  let path = `M ${start2[0]},${start2[1]}`;
8775
- for (; hasAtLeast(points, 3); ) {
8781
+ for (; hasAtLeast$1(points, 3); ) {
8776
8782
  const [cp1, cp2, end, ...rest] = points;
8777
8783
  path = path + ` C ${cp1[0]},${cp1[1]} ${cp2[0]},${cp2[1]} ${end[0]},${end[1]}`, points = rest;
8778
8784
  }
8779
8785
  return invariant(points.length === 0, "all points should be consumed"), path;
8780
8786
  }
8781
- const isSamePoint = (a, b) => Math.abs(a - b) < 3.1, isSamePosition = (a, [bx, by]) => isSamePoint(a.x, bx) && isSamePoint(a.y, by), isEqualProps = (prev, next) => prev.id === next.id && prev.source === next.source && prev.target === next.target && deepEqual(prev.selected ?? !1, next.selected ?? !1) && isSamePoint(prev.sourceX, next.sourceX) && isSamePoint(prev.sourceY, next.sourceY) && isSamePoint(prev.targetX, next.targetX) && isSamePoint(prev.targetY, next.targetY) && deepEqual(prev.data.stepNum, next.data.stepNum) && deepEqual(prev.data.edge, next.data.edge) && zip(prev.data.controlPoints, next.data.controlPoints).every(
8782
- ([a, b]) => isSamePoint(a[0], b[0]) && isSamePoint(a[1], b[1])
8783
- ), curve = line().curve(curveCatmullRomOpen), RelationshipEdge = /* @__PURE__ */ memo(function({
8787
+ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
8788
+ const [ax, ay] = isArray(a) ? a : [a.x, a.y], [bx, by] = isArray(b) ? b : [b.x, b.y];
8789
+ return isSame(ax, bx) && isSame(ay, by);
8790
+ }, sameControlPoints = (a, b) => a === b ? !0 : !a || !b || a.length !== b.length ? !1 : a.every((ap, i) => isSamePoint(ap, b[i])), isEqualProps$2 = (prev, next) => prev.id === next.id && prev.source === next.source && prev.target === next.target && deepEqual(prev.selected ?? !1, next.selected ?? !1) && isSame(prev.sourceX, next.sourceX) && isSame(prev.sourceY, next.sourceY) && isSame(prev.targetX, next.targetX) && isSame(prev.targetY, next.targetY) && deepEqual(prev.data.stepNum, next.data.stepNum) && sameControlPoints(prev.data.controlPoints, next.data.controlPoints) && deepEqual(prev.data.edge, next.data.edge), curve = line().curve(curveCatmullRomOpen).x((d) => d.x).y((d) => d.y), RelationshipEdge = /* @__PURE__ */ memo(function({
8784
8791
  id: id2,
8785
8792
  data,
8786
8793
  selected: _selected,
@@ -8789,38 +8796,76 @@ const isSamePoint = (a, b) => Math.abs(a - b) < 3.1, isSamePosition = (a, [bx, b
8789
8796
  target,
8790
8797
  interactionWidth
8791
8798
  }) {
8792
- var _a, _b, _c, _d;
8793
- const { nodeLookup, edgeLookup } = useXYStoreApi().getState(), sourceNode = nonNullable(nodeLookup.get(source), `source node ${source} not found`), targetNode = nonNullable(nodeLookup.get(target), `target node ${target} not found`), isModified = !isSamePosition(sourceNode.internals.positionAbsolute, sourceNode.data.element.position) || !isSamePosition(targetNode.internals.positionAbsolute, targetNode.data.element.position), { edge: diagramEdge, controlPoints } = data, color2 = diagramEdge.color ?? "gray", isStepEdge = data.stepNum !== null, { isActive, isHovered, isDimmed } = useDiagramState((s) => ({
8794
- isActive: s.activeDynamicViewStep !== null && s.activeDynamicViewStep === data.stepNum,
8799
+ var _a, _b;
8800
+ const diagramStore = useDiagramStoreApi(), xyflowStore = useXYStoreApi(), { isActive, isEditable, isEdgePathEditable, isHovered, isDimmed } = useDiagramState((s) => ({
8801
+ isEditable: s.readonly !== !0,
8802
+ isEdgePathEditable: s.readonly !== !0 && s.experimentalEdgeEditing === !0,
8803
+ isActive: s.focusedNodeId === source || s.focusedNodeId === target || s.activeDynamicViewStep !== null && s.activeDynamicViewStep === data.stepNum,
8795
8804
  isHovered: s.hoveredEdgeId === id2,
8796
8805
  isDimmed: s.dimmed.has(id2)
8797
- })), line2 = diagramEdge.line ?? "dashed", isDotted = line2 === "dotted", isDashed = isDotted || line2 === "dashed";
8806
+ })), { nodeLookup, edgeLookup } = xyflowStore.getState(), sourceNode = nonNullable(nodeLookup.get(source), `source node ${source} not found`), targetNode = nonNullable(nodeLookup.get(target), `target node ${target} not found`), isModified = isEditable && (isTruthy(data.controlPoints) || !isSamePoint(sourceNode.internals.positionAbsolute, sourceNode.data.element.position) || !isSamePoint(targetNode.internals.positionAbsolute, targetNode.data.element.position)), {
8807
+ label,
8808
+ edge: {
8809
+ points: diagramEdgePoints,
8810
+ line: line2 = "dashed",
8811
+ color: color2 = "gray",
8812
+ ...diagramEdge
8813
+ }
8814
+ } = data;
8815
+ let controlPoints = data.controlPoints ?? bezierControlPoints(data.edge);
8816
+ const isStepEdge = data.stepNum !== null, isDotted = line2 === "dotted", isDashed = isDotted || line2 === "dashed";
8798
8817
  let strokeDasharray;
8799
8818
  isDotted ? strokeDasharray = "1,8" : isDashed && (strokeDasharray = "8,10");
8800
- const marker = `url(#arrow-${id2})`;
8801
- let edgePath, labelX, labelY;
8802
- if (!isModified)
8803
- edgePath = bezierPath(diagramEdge.points), labelX = ((_a = data.label) == null ? void 0 : _a.bbox.x) ?? 0, labelY = ((_b = data.label) == null ? void 0 : _b.bbox.y) ?? 0;
8804
- else {
8805
- const { sx, sy, tx, ty, sourcePos, targetPos } = getEdgeParams(sourceNode, targetNode), [_edgePath, _labelX, _labelY] = getBezierPath({
8806
- sourceX: sx,
8807
- sourceY: sy,
8808
- sourcePosition: sourcePos,
8809
- targetPosition: targetPos,
8810
- targetX: tx,
8811
- targetY: ty
8812
- });
8813
- edgePath = _edgePath, labelX = _labelX, labelY = _labelY;
8814
- const sourceCenterPos = getNodePositionWithOrigin(sourceNode, [-0.5, -0.5]), targetCenterPos = getNodePositionWithOrigin(targetNode, [-0.5, -0.5]);
8815
- edgePath = curve([
8816
- [sourceCenterPos.positionAbsolute.x, sourceCenterPos.positionAbsolute.y],
8819
+ let labelX = (label == null ? void 0 : label.bbox.x) ?? 0, labelY = (label == null ? void 0 : label.bbox.y) ?? 0;
8820
+ const [labelPos, setLabelPosition] = useState({
8821
+ x: labelX,
8822
+ y: labelY
8823
+ });
8824
+ let edgePath;
8825
+ if (isModified) {
8826
+ labelX = labelPos.x, labelY = labelPos.y;
8827
+ const sourceCenterPos = getNodePositionWithOrigin(sourceNode, [-0.5, -0.5]), targetCenterPos = getNodePositionWithOrigin(targetNode, [-0.5, -0.5]), points = [
8828
+ sourceCenterPos.positionAbsolute,
8817
8829
  getNodeIntersectionFromCenterToPoint(sourceNode, first(controlPoints)),
8818
8830
  ...controlPoints,
8819
8831
  getNodeIntersectionFromCenterToPoint(targetNode, last(controlPoints)),
8820
- [targetCenterPos.positionAbsolute.x, targetCenterPos.positionAbsolute.y]
8821
- ]);
8822
- }
8823
- return /* @__PURE__ */ jsxs(
8832
+ targetCenterPos.positionAbsolute
8833
+ ];
8834
+ edgePath = nonNullable(curve(points));
8835
+ } else
8836
+ edgePath = bezierPath(diagramEdgePoints);
8837
+ const svgPathRef = useRef(null);
8838
+ useIsomorphicLayoutEffect$1(() => {
8839
+ const path = svgPathRef.current;
8840
+ if (!path) return;
8841
+ const dompoint = path.getPointAtLength(path.getTotalLength() * 0.5), point = {
8842
+ x: Math.round(dompoint.x),
8843
+ y: Math.round(dompoint.y)
8844
+ };
8845
+ setLabelPosition((current) => isSamePoint(current, point) ? current : point);
8846
+ }, [edgePath]);
8847
+ const onControlPointerDown = (index2, e) => {
8848
+ const { domNode } = xyflowStore.getState();
8849
+ if (!domNode) return;
8850
+ const { xyflow } = diagramStore.getState();
8851
+ e.stopPropagation();
8852
+ let hasMoved = !1, pointer2 = { x: e.clientX, y: e.clientY };
8853
+ const onPointerMove = (e2) => {
8854
+ if (!isSamePoint(pointer2, [e2.clientX, e2.clientY])) {
8855
+ hasMoved || diagramStore.getState().cancelSaveManualLayout(), hasMoved = !0, pointer2 = { x: e2.clientX, y: e2.clientY };
8856
+ const { x, y } = xyflow.screenToFlowPosition(pointer2, { snapToGrid: !1 }), newControlPoints = controlPoints.slice();
8857
+ newControlPoints[index2] = {
8858
+ x: toDomPrecision(x),
8859
+ y: toDomPrecision(y)
8860
+ }, xyflow.updateEdgeData(id2, { controlPoints: newControlPoints });
8861
+ }
8862
+ }, onPointerUp = () => {
8863
+ domNode.removeEventListener("pointermove", onPointerMove), domNode.removeEventListener("pointerup", onPointerUp), hasMoved && diagramStore.getState().triggerSaveManualLayout(xyflowStore);
8864
+ };
8865
+ domNode.addEventListener("pointermove", onPointerMove), domNode.addEventListener("pointerup", onPointerUp, { once: !0 });
8866
+ }, marker = `url(#arrow-${id2})`;
8867
+ let markerStart = diagramEdge.tailArrow ? marker : void 0, markerEnd = diagramEdge.headArrow ? marker : void 0;
8868
+ return isModified && diagramEdge.dir === "back" && ([markerStart, markerEnd] = [markerEnd, markerStart]), /* @__PURE__ */ jsxs(
8824
8869
  "g",
8825
8870
  {
8826
8871
  className: clsx([
@@ -8832,38 +8877,62 @@ const isSamePoint = (a, b) => Math.abs(a - b) < 3.1, isSamePosition = (a, [bx, b
8832
8877
  "data-edge-active": isActive,
8833
8878
  "data-edge-hovered": isHovered,
8834
8879
  children: [
8835
- /* @__PURE__ */ jsx("g", { className: markerContext, children: /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
8836
- "marker",
8837
- {
8838
- id: `arrow-${id2}`,
8839
- viewBox: "0 0 16 10",
8840
- refX: isModified ? "12" : "10",
8841
- refY: "5",
8842
- markerWidth: "5",
8843
- markerHeight: "4",
8844
- markerUnits: "strokeWidth",
8845
- preserveAspectRatio: "xMaxYMid meet",
8846
- orient: "auto-start-reverse",
8847
- children: /* @__PURE__ */ jsx("path", { d: "M 0 0 L 16 5 L 0 10 z", stroke: "context-stroke", fill: "context-stroke" })
8848
- }
8849
- ) }) }),
8850
8880
  /* @__PURE__ */ jsx(
8851
- RelationshipPath,
8881
+ "path",
8852
8882
  {
8853
- edgePath,
8854
- interactionWidth: interactionWidth ?? 10,
8855
- strokeDasharray,
8856
- markerStart: diagramEdge.tailArrow ? marker : void 0,
8857
- markerEnd: diagramEdge.headArrow ? marker : void 0,
8858
- style: style2
8883
+ className: clsx("react-flow__edge-interaction"),
8884
+ d: edgePath,
8885
+ fill: "none",
8886
+ stroke: "transparent",
8887
+ strokeWidth: interactionWidth ?? 10
8859
8888
  }
8860
8889
  ),
8861
- isModified && controlPoints.map((p, i) => /* @__PURE__ */ jsx(
8890
+ /* @__PURE__ */ jsxs("g", { className: markerContext, children: [
8891
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
8892
+ "marker",
8893
+ {
8894
+ id: `arrow-${id2}`,
8895
+ viewBox: "0 0 16 10",
8896
+ refX: isModified ? "15" : "1",
8897
+ refY: "5",
8898
+ markerWidth: "5",
8899
+ markerHeight: "4",
8900
+ markerUnits: "strokeWidth",
8901
+ preserveAspectRatio: "xMaxYMid meet",
8902
+ orient: "auto-start-reverse",
8903
+ children: /* @__PURE__ */ jsx("path", { d: "M 0 0 L 16 5 L 0 10 z", stroke: "context-stroke", fill: "context-stroke" })
8904
+ }
8905
+ ) }),
8906
+ /* @__PURE__ */ jsx(
8907
+ "path",
8908
+ {
8909
+ className: clsx("react-flow__edge-path", edgePathBg),
8910
+ d: edgePath,
8911
+ style: style2,
8912
+ strokeLinecap: "round"
8913
+ }
8914
+ ),
8915
+ /* @__PURE__ */ jsx(
8916
+ "path",
8917
+ {
8918
+ ref: svgPathRef,
8919
+ className: clsx("react-flow__edge-path", cssEdgePath),
8920
+ d: edgePath,
8921
+ style: style2,
8922
+ strokeLinecap: "round",
8923
+ strokeDasharray,
8924
+ markerStart,
8925
+ markerEnd
8926
+ }
8927
+ )
8928
+ ] }),
8929
+ isEdgePathEditable && controlPoints.map((p, i) => /* @__PURE__ */ jsx(
8862
8930
  "circle",
8863
8931
  {
8932
+ onPointerDown: (e) => onControlPointerDown(i, e),
8864
8933
  className: controlPoint,
8865
- cx: p[0],
8866
- cy: p[1],
8934
+ cx: p.x,
8935
+ cy: p.y,
8867
8936
  r: 3
8868
8937
  },
8869
8938
  i
@@ -8879,13 +8948,16 @@ const isSamePoint = (a, b) => Math.abs(a - b) < 3.1, isSamePosition = (a, [bx, b
8879
8948
  "data-likec4-color": color2,
8880
8949
  style: {
8881
8950
  ...assignInlineVars({
8882
- [varLabelX]: Math.floor(labelX) + "px",
8883
- [varLabelY]: Math.floor(labelY) + "px"
8951
+ [varLabelX]: isModified ? `calc(${labelX}px - 10%)` : `${labelX}px`,
8952
+ [varLabelY]: isModified ? `${labelY - 5}px` : `${labelY}px`
8884
8953
  }),
8954
+ ...isEdgePathEditable && {
8955
+ pointerEvents: "none"
8956
+ },
8885
8957
  ...data.label && {
8886
8958
  maxWidth: data.label.bbox.width + 12
8887
8959
  },
8888
- zIndex: ((_c = edgeLookup.get(id2)) == null ? void 0 : _c.zIndex) ?? ZIndexes.Edge
8960
+ zIndex: ((_a = edgeLookup.get(id2)) == null ? void 0 : _a.zIndex) ?? ZIndexes.Edge
8889
8961
  },
8890
8962
  mod: {
8891
8963
  "data-edge-hovered": isHovered,
@@ -8893,148 +8965,71 @@ const isSamePoint = (a, b) => Math.abs(a - b) < 3.1, isSamePosition = (a, [bx, b
8893
8965
  },
8894
8966
  children: [
8895
8967
  isStepEdge && /* @__PURE__ */ jsx(Box, { className: stepEdgeNumber, children: data.stepNum }),
8896
- ((_d = data.label) == null ? void 0 : _d.text) && /* @__PURE__ */ jsx(Box, { className: edgeLabelText, children: data.label.text })
8968
+ ((_b = data.label) == null ? void 0 : _b.text) && /* @__PURE__ */ jsx(Box, { className: edgeLabelText, children: data.label.text })
8897
8969
  ]
8898
8970
  }
8899
8971
  ) })
8900
8972
  ]
8901
8973
  }
8902
8974
  );
8903
- }, isEqualProps), RelationshipPath = ({
8904
- edgePath,
8905
- interactionWidth,
8906
- strokeDasharray,
8907
- markerStart,
8908
- markerEnd,
8909
- style: style2
8910
- }) => /* @__PURE__ */ jsxs(Fragment, { children: [
8911
- /* @__PURE__ */ jsx(
8912
- "path",
8913
- {
8914
- className: clsx("react-flow__edge-path", edgePathBg),
8915
- d: edgePath,
8916
- style: style2,
8917
- strokeLinecap: "round"
8918
- }
8919
- ),
8920
- /* @__PURE__ */ jsx(
8921
- "path",
8922
- {
8923
- className: clsx("react-flow__edge-path", cssEdgePath),
8924
- d: edgePath,
8925
- style: style2,
8926
- strokeLinecap: "round",
8927
- strokeDasharray,
8928
- markerStart,
8929
- markerEnd
8930
- }
8931
- ),
8932
- /* @__PURE__ */ jsx(
8933
- "path",
8934
- {
8935
- className: clsx("react-flow__edge-interaction"),
8936
- d: edgePath,
8937
- fill: "none",
8938
- strokeOpacity: 0,
8939
- strokeWidth: interactionWidth
8940
- }
8941
- )
8942
- ] }), Link = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
8943
- "svg",
8944
- {
8945
- ref,
8946
- className: clsx("icon icon-tabler", className),
8947
- stroke: "currentColor",
8948
- fill: "currentColor",
8949
- strokeWidth: "0",
8950
- viewBox: "0 0 20 20",
8951
- height: "20",
8952
- width: "20",
8953
- xmlns: "http://www.w3.org/2000/svg",
8954
- ...props,
8955
- children: /* @__PURE__ */ jsx(
8956
- "path",
8957
- {
8958
- fillRule: "evenodd",
8959
- d: "M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 00-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l1.5-1.5zm-5 5a2 2 0 012.828 0 1 1 0 101.414-1.414 4 4 0 00-5.656 0l-3 3a4 4 0 105.656 5.656l1.5-1.5a1 1 0 10-1.414-1.414l-1.5 1.5a2 2 0 11-2.828-2.828l3-3z",
8960
- clipRule: "evenodd"
8961
- }
8962
- )
8963
- }
8964
- )), ZoomIn = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs(
8965
- "svg",
8966
- {
8967
- ref,
8968
- xmlns: "http://www.w3.org/2000/svg",
8969
- className: clsx("icon icon-tabler icon-tabler-zoom-in", className),
8970
- width: "24",
8971
- height: "24",
8972
- viewBox: "0 0 24 24",
8973
- strokeWidth: "1.5",
8974
- stroke: "currentColor",
8975
- fill: "none",
8976
- strokeLinecap: "round",
8977
- strokeLinejoin: "round",
8978
- ...props,
8979
- children: [
8980
- /* @__PURE__ */ jsx("path", { stroke: "none", d: "M0 0h24v24H0z", fill: "none" }),
8981
- /* @__PURE__ */ jsx("path", { d: "M10 10m-7 0a7 7 0 1 0 14 0a7 7 0 1 0 -14 0" }),
8982
- /* @__PURE__ */ jsx("path", { d: "M7 10l6 0" }),
8983
- /* @__PURE__ */ jsx("path", { d: "M10 7l0 6" }),
8984
- /* @__PURE__ */ jsx("path", { d: "M21 21l-6 -6" })
8985
- ]
8986
- }
8987
- ));
8975
+ }, isEqualProps$2);
8988
8976
  function NavigateToBtn({ xynodeId, className }) {
8989
8977
  const diagramApi = useDiagramStoreApi();
8990
8978
  return /* @__PURE__ */ jsx(
8991
8979
  ActionIcon,
8992
8980
  {
8993
8981
  className: clsx("nodrag nopan", className),
8994
- radius: "xl",
8982
+ radius: "md",
8995
8983
  onPointerDownCapture: (e) => e.stopPropagation(),
8996
8984
  onClick: (event) => {
8997
8985
  event.stopPropagation(), diagramApi.getState().triggerOnNavigateTo(xynodeId, event);
8998
8986
  },
8999
8987
  onDoubleClick: (event) => event.stopPropagation(),
9000
- children: /* @__PURE__ */ jsx(ZoomIn, {})
8988
+ children: /* @__PURE__ */ jsx(
8989
+ IconZoomScan,
8990
+ {
8991
+ style: {
8992
+ width: "75%",
8993
+ height: "75%"
8994
+ }
8995
+ }
8996
+ )
9001
8997
  }
9002
8998
  );
9003
8999
  }
9004
- var container$3 = "lbtzdo0", dimmed$1 = "lbtzdo1", varTransparency = "var(--lbtzdo2)", compoundBody = "lbtzdo3", transparent = "lbtzdo6", title$2 = "lbtzdo7", indicator$1 = "lbtzdob", navigateBtn = "lbtzdod";
9005
- const CompoundNodeMemo = /* @__PURE__ */ memo(function({
9000
+ var container$3 = "lbtzdo0", dimmed$1 = "lbtzdo1", varOpacity = "var(--lbtzdo2)", varBorderTransparency = "var(--lbtzdo3)", compoundBody = "lbtzdo4", transparent = "lbtzdo6", title$2 = "lbtzdo7", titleWithNavigation = "lbtzdo8", indicator$1 = "lbtzdoc", navigateBtn = "lbtzdoe";
9001
+ const isEqualProps$1 = (prev, next) => prev.id === next.id && deepEqual(prev.data.element, next.data.element), CompoundNodeMemo = /* @__PURE__ */ memo(function({
9006
9002
  id: id2,
9007
9003
  data: {
9008
9004
  element: element2
9009
9005
  }
9010
9006
  }) {
9011
- const { color: color2, style: style2, depth = 1, ...compound } = element2, opacity = style2.opacity ?? 100, { isHovered, isDimmed, hasOnNavigateTo } = useDiagramState((s) => ({
9007
+ DEV && useTilg();
9008
+ const { color: color2, style: style2, depth = 1, ...compound } = element2, opacity = clamp$1((style2.opacity ?? 100) / 100, {
9009
+ min: 0,
9010
+ max: 1
9011
+ }), borderTransparency = clamp$1(50 - opacity * 50, {
9012
+ min: 0,
9013
+ max: 50
9014
+ }), { isHovered, isDimmed, hasOnNavigateTo } = useDiagramState((s) => ({
9012
9015
  isHovered: s.hoveredNodeId === id2,
9013
9016
  isDimmed: s.dimmed.has(id2),
9014
9017
  hasOnNavigateTo: !!s.onNavigateTo
9015
- })), isnavigable = !!compound.navigateTo && hasOnNavigateTo, transparency = clamp$1(100 - opacity, {
9016
- min: 0,
9017
- max: 99
9018
- });
9018
+ })), isnavigable = !!compound.navigateTo && hasOnNavigateTo;
9019
9019
  return /* @__PURE__ */ jsxs(
9020
9020
  Box,
9021
9021
  {
9022
9022
  className: clsx(
9023
9023
  container$3,
9024
9024
  "likec4-compound-node",
9025
- opacity < 100 && "likec4-compound-transparent",
9025
+ opacity < 1 && "likec4-compound-transparent",
9026
9026
  isDimmed && dimmed$1
9027
9027
  ),
9028
9028
  mod: {
9029
9029
  "compound-depth": depth,
9030
9030
  "likec4-color": color2,
9031
- "likec4-shape": compound.shape,
9032
- "likec4-navigable": isnavigable,
9033
9031
  hovered: isHovered
9034
9032
  },
9035
- style: assignInlineVars({
9036
- [varTransparency]: transparency + "%"
9037
- }),
9038
9033
  children: [
9039
9034
  /* @__PURE__ */ jsx(
9040
9035
  Handle,
@@ -9057,15 +9052,27 @@ const CompoundNodeMemo = /* @__PURE__ */ memo(function({
9057
9052
  /* @__PURE__ */ jsx(
9058
9053
  "div",
9059
9054
  {
9060
- className: clsx(compoundBody, opacity < 100 && transparent, "likec4-compound"),
9061
- style: {
9062
- borderStyle: opacity < 100 ? style2.border : void 0
9063
- },
9055
+ className: clsx(
9056
+ compoundBody,
9057
+ opacity < 1 && transparent,
9058
+ "likec4-compound"
9059
+ ),
9060
+ style: opacity < 1 ? {
9061
+ ...assignInlineVars({
9062
+ [varBorderTransparency]: `${borderTransparency}%`,
9063
+ [varOpacity]: opacity.toFixed(2)
9064
+ }),
9065
+ borderStyle: style2.border ?? "dashed"
9066
+ } : void 0,
9064
9067
  children: /* @__PURE__ */ jsx(
9065
9068
  Text,
9066
9069
  {
9067
9070
  component: "div",
9068
- className: clsx(title$2, "likec4-compound-title"),
9071
+ className: clsx(
9072
+ title$2,
9073
+ isnavigable && titleWithNavigation,
9074
+ "likec4-compound-title"
9075
+ ),
9069
9076
  children: compound.title
9070
9077
  }
9071
9078
  )
@@ -9083,8 +9090,8 @@ const CompoundNodeMemo = /* @__PURE__ */ memo(function({
9083
9090
  ]
9084
9091
  }
9085
9092
  );
9086
- });
9087
- var container$2 = "_1b6tkn2", dimmed = "_1b6tkn3", indicator = "_1b6tkn5", fillElementFill = "_1b6tkn6", fillMixStroke = "_1b6tkn8", title$1 = "_1b6tkn9", description$1 = "_1b6tkna", technology = "_1b6tknb", element = "_1b6tknc", iconMaxH = "var(--_1b6tknd)", elementIcon = "_1b6tkne", cssShapeSvg = "_1b6tknh", cssNavigateBtn = "_1b6tkni";
9093
+ }, isEqualProps$1);
9094
+ var container$2 = "_1b6tkn2", containerAnimated = "_1b6tkn3", dimmed = "_1b6tkn4", indicator = "_1b6tkn6", fillElementFill = "_1b6tkn7", fillMixStroke = "_1b6tkn9", title$1 = "_1b6tkna", description$1 = "_1b6tknb", technology = "_1b6tknc", element = "_1b6tknd", iconMaxH = "var(--_1b6tkne)", elementIcon = "_1b6tknf", cssShapeSvg = "_1b6tkni", cssNavigateBtn = "_1b6tknj";
9088
9095
  function ElementIcon({
9089
9096
  node,
9090
9097
  paddingY = 32
@@ -9112,6 +9119,29 @@ function ElementIcon({
9112
9119
  }
9113
9120
  );
9114
9121
  }
9122
+ const Link = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
9123
+ "svg",
9124
+ {
9125
+ ref,
9126
+ className: clsx("icon icon-tabler", className),
9127
+ stroke: "currentColor",
9128
+ fill: "currentColor",
9129
+ strokeWidth: "0",
9130
+ viewBox: "0 0 20 20",
9131
+ height: "20",
9132
+ width: "20",
9133
+ xmlns: "http://www.w3.org/2000/svg",
9134
+ ...props,
9135
+ children: /* @__PURE__ */ jsx(
9136
+ "path",
9137
+ {
9138
+ fillRule: "evenodd",
9139
+ d: "M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 00-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l1.5-1.5zm-5 5a2 2 0 012.828 0 1 1 0 101.414-1.414 4 4 0 00-5.656 0l-3 3a4 4 0 105.656 5.656l1.5-1.5a1 1 0 10-1.414-1.414l-1.5 1.5a2 2 0 11-2.828-2.828l3-3z",
9140
+ clipRule: "evenodd"
9141
+ }
9142
+ )
9143
+ }
9144
+ ));
9115
9145
  var elementLink = "_4ysv0o0", trigger = "_4ysv0o1";
9116
9146
  function ElementLink({
9117
9147
  element: element2
@@ -9330,13 +9360,13 @@ const selectedScale = 1.015, variants = {
9330
9360
  idle: (_, { scale }) => ({
9331
9361
  scale: 1,
9332
9362
  transition: {
9333
- delay: isNumber(scale) && scale > selectedScale ? 0.075 : 0
9363
+ delay: isNumber(scale) && scale > selectedScale ? 0.09 : 0
9334
9364
  }
9335
9365
  }),
9336
9366
  selected: (_, { scale }) => ({
9337
9367
  scale: selectedScale,
9338
9368
  transition: {
9339
- delay: isNumber(scale) && scale > selectedScale ? 0.075 : 0
9369
+ delay: isNumber(scale) && scale > selectedScale ? 0.09 : 0
9340
9370
  }
9341
9371
  }),
9342
9372
  // dimmed: {
@@ -9360,20 +9390,16 @@ const selectedScale = 1.015, variants = {
9360
9390
  // delay: 1
9361
9391
  // }
9362
9392
  // }),
9363
- hovered: (_, { scale }) => ({
9364
- scale: 1.06,
9365
- transition: {
9366
- delay: isNumber(scale) && scale !== 1 && scale !== selectedScale ? 0 : 0.15
9367
- }
9368
- }),
9393
+ hovered: {
9394
+ scale: 1.06
9395
+ },
9369
9396
  tap: {
9370
9397
  scale: 0.975
9371
9398
  }
9372
9399
  // tap: {
9373
9400
  // scale: 0.9
9374
9401
  // }
9375
- };
9376
- function ElementNode({
9402
+ }, isEqualProps = (prev, next) => prev.id === next.id && deepEqual(prev.selected ?? !1, next.selected ?? !1) && deepEqual(prev.dragging ?? !1, next.dragging ?? !1) && deepEqual(prev.width ?? 0, next.width ?? 0) && deepEqual(prev.height ?? 0, next.height ?? 0) && deepEqual(prev.data.element, next.data.element), ElementNodeMemo = memo(function({
9377
9403
  id: id2,
9378
9404
  data: {
9379
9405
  element: element$1
@@ -9383,6 +9409,7 @@ function ElementNode({
9383
9409
  width,
9384
9410
  height
9385
9411
  }) {
9412
+ DEV && useTilg();
9386
9413
  const { isHovered, isDimmed, hasOnNavigateTo, isHovercards, isInteractive } = useDiagramState((s) => ({
9387
9414
  isHovered: s.hoveredNodeId === id2,
9388
9415
  isDimmed: s.dimmed.has(id2),
@@ -9406,14 +9433,16 @@ function ElementNode({
9406
9433
  break;
9407
9434
  }
9408
9435
  return /* @__PURE__ */ jsxs(
9409
- motion.div,
9436
+ m.div,
9410
9437
  {
9411
9438
  id: id2,
9412
9439
  className: clsx([
9413
9440
  container$2,
9414
9441
  isDimmed && dimmed,
9442
+ animate !== "idle" && containerAnimated,
9415
9443
  "likec4-element-node"
9416
9444
  ]),
9445
+ "data-hovered": !dragging && isHovered,
9417
9446
  "data-likec4-color": element$1.color,
9418
9447
  "data-likec4-shape": element$1.shape,
9419
9448
  variants,
@@ -9500,29 +9529,11 @@ function ElementNode({
9500
9529
  ]
9501
9530
  }
9502
9531
  );
9503
- }
9504
- function literalToEnum(value) {
9505
- switch (value) {
9506
- case "dots":
9507
- return BackgroundVariant.Dots;
9508
- case "lines":
9509
- return BackgroundVariant.Lines;
9510
- case "cross":
9511
- return BackgroundVariant.Cross;
9512
- default:
9513
- nonexhaustive(value);
9514
- }
9515
- }
9516
- function XYFlowBackground({ background }) {
9517
- if (typeof background == "string")
9518
- return /* @__PURE__ */ jsx(Background, { variant: literalToEnum(background) });
9519
- const { variant, ...rest } = background;
9520
- return /* @__PURE__ */ jsx(Background, { variant: literalToEnum(variant), ...rest });
9521
- }
9532
+ }, isEqualProps);
9522
9533
  function useXYFlowEvents() {
9523
- const diagramApi = useDiagramStoreApi(), xyflowApi = useXYStoreApi(), dblclickTimeout = useRef(), dbclickLock = () => dblclickTimeout.current !== void 0 ? !0 : (dblclickTimeout.current = window.setTimeout(() => {
9534
+ const diagramApi = useDiagramStoreApi(), xyflowApi = useXYStoreApi(), lastClickTimestamp = useRef(), dblclickTimeout = useRef(), dbclickLock = () => dblclickTimeout.current !== void 0 ? !0 : (dblclickTimeout.current = window.setTimeout(() => {
9524
9535
  dblclickTimeout.current = void 0;
9525
- }, 250), !1), hoveredNodeFromOnEdgeEnterRef = useRef("");
9536
+ }, 250), !1), lastClickWasRecent = (ms = 1500) => lastClickTimestamp.current && Date.now() - lastClickTimestamp.current < ms, hoveredNodeFromOnEdgeEnterRef = useRef("");
9526
9537
  return useMemo(() => ({
9527
9538
  onDoubleClick: (event) => {
9528
9539
  const {
@@ -9536,8 +9547,14 @@ function useXYFlowEvents() {
9536
9547
  onPaneClick: (event) => {
9537
9548
  if (dbclickLock())
9538
9549
  return;
9539
- const { focusedNodeId, fitDiagram, onCanvasClick, resetLastClicked } = diagramApi.getState();
9540
- focusedNodeId && (fitDiagram(xyflowApi), onCanvasClick || event.stopPropagation()), resetLastClicked(), onCanvasClick == null || onCanvasClick(event);
9550
+ const {
9551
+ focusedNodeId,
9552
+ activeDynamicViewStep,
9553
+ fitDiagram,
9554
+ onCanvasClick,
9555
+ resetLastClicked
9556
+ } = diagramApi.getState();
9557
+ (focusedNodeId || activeDynamicViewStep) && (fitDiagram(xyflowApi), onCanvasClick || event.stopPropagation()), resetLastClicked(), onCanvasClick == null || onCanvasClick(event);
9541
9558
  },
9542
9559
  onNodeContextMenu: (event, xynode) => {
9543
9560
  var _a, _b;
@@ -9561,12 +9578,17 @@ function useXYFlowEvents() {
9561
9578
  },
9562
9579
  onNodeClick: (event, xynode) => {
9563
9580
  const {
9581
+ zoomable,
9582
+ fitViewEnabled,
9564
9583
  focusedNodeId,
9565
9584
  focusOnNode,
9566
9585
  onNodeClick,
9586
+ lastClickedNodeId,
9567
9587
  setLastClickedNode
9568
9588
  } = diagramApi.getState();
9569
- setLastClickedNode(xynode.id), focusedNodeId && focusedNodeId !== xynode.id && (focusOnNode(xynode.id), onNodeClick || event.stopPropagation()), onNodeClick == null || onNodeClick({
9589
+ setLastClickedNode(xynode.id);
9590
+ const focusPossible = zoomable && fitViewEnabled, shallChangeFocus = !!focusedNodeId && focusedNodeId !== xynode.id, clickedRecently = isNullish(focusedNodeId) && lastClickedNodeId === xynode.id && lastClickWasRecent();
9591
+ focusPossible && (shallChangeFocus || clickedRecently) && (focusOnNode(xynode.id), onNodeClick || event.stopPropagation()), lastClickTimestamp.current = Date.now(), onNodeClick == null || onNodeClick({
9570
9592
  element: xynode.data.element,
9571
9593
  xynode,
9572
9594
  event
@@ -9597,9 +9619,7 @@ function useXYFlowEvents() {
9597
9619
  viewportChanged !== diagramApi.getState().viewportChanged && diagramApi.setState({ viewportChanged }, !1, `viewport-changed: ${viewportChanged}`);
9598
9620
  },
9599
9621
  onNodeMouseEnter: (_event, xynode) => {
9600
- hoveredNodeFromOnEdgeEnterRef.current = "";
9601
- const { hoveredNodeId, setHoveredNode } = diagramApi.getState();
9602
- hoveredNodeId !== xynode.id && setHoveredNode(xynode.id);
9622
+ hoveredNodeFromOnEdgeEnterRef.current = "", diagramApi.getState().setHoveredNode(xynode.id);
9603
9623
  },
9604
9624
  onNodeMouseLeave: (_event, xynode) => {
9605
9625
  const { hoveredNodeId, setHoveredNode } = diagramApi.getState();
@@ -9614,12 +9634,12 @@ function useXYFlowEvents() {
9614
9634
  },
9615
9635
  onEdgeMouseLeave: (_event, xyedge) => {
9616
9636
  const { hoveredEdgeId, setHoveredEdge, hoveredNodeId, setHoveredNode } = diagramApi.getState();
9617
- hoveredEdgeId === xyedge.id && setHoveredEdge(null), hoveredNodeId === hoveredNodeFromOnEdgeEnterRef.current && (hoveredNodeFromOnEdgeEnterRef.current = "", setHoveredNode(null));
9637
+ hoveredEdgeId === xyedge.id && setHoveredEdge(null), hoveredNodeId === hoveredNodeFromOnEdgeEnterRef.current && setHoveredNode(null), hoveredNodeFromOnEdgeEnterRef.current = "";
9618
9638
  }
9619
9639
  }), [diagramApi, xyflowApi]);
9620
9640
  }
9621
9641
  const nodeTypes = {
9622
- element: ElementNode,
9642
+ element: ElementNodeMemo,
9623
9643
  compound: CompoundNodeMemo
9624
9644
  }, edgeTypes = {
9625
9645
  relationship: RelationshipEdge
@@ -9627,7 +9647,12 @@ const nodeTypes = {
9627
9647
  nodesSelectable: s.nodesSelectable || s.focusedNodeId !== null,
9628
9648
  nodesDraggable: s.nodesDraggable,
9629
9649
  fitView: s.fitViewEnabled,
9630
- fitViewPadding: s.fitViewPadding,
9650
+ fitViewOptions: {
9651
+ minZoom: MinZoom,
9652
+ maxZoom: 1,
9653
+ padding: s.fitViewPadding,
9654
+ includeHiddenNodes: !0
9655
+ },
9631
9656
  hasOnNavigateTo: !!s.onNavigateTo,
9632
9657
  hasOnNodeClick: !!s.onNodeClick,
9633
9658
  hasOnNodeContextMenu: !!s.onNodeContextMenu,
@@ -9638,17 +9663,19 @@ const nodeTypes = {
9638
9663
  pannable: s.pannable
9639
9664
  });
9640
9665
  function XYFlow({
9666
+ colorMode = "system",
9641
9667
  className,
9642
9668
  children: children2,
9643
9669
  defaultNodes,
9644
9670
  defaultEdges,
9645
9671
  style: style2
9646
9672
  }) {
9673
+ DEV && useTilg();
9647
9674
  const xyflowApi = useXYStoreApi(), diagramApi = useDiagramStoreApi(), {
9648
9675
  nodesSelectable,
9649
9676
  nodesDraggable,
9650
9677
  fitView: fitView2,
9651
- fitViewPadding,
9678
+ fitViewOptions,
9652
9679
  pannable,
9653
9680
  zoomable,
9654
9681
  hasOnNodeClick,
@@ -9657,7 +9684,7 @@ function XYFlow({
9657
9684
  hasOnCanvasContextMenu,
9658
9685
  hasOnEdgeContextMenu,
9659
9686
  hasOnEdgeClick
9660
- } = useDiagramState(selector$1), layoutConstraints = useLayoutConstraints(), handlers = useXYFlowEvents(), { colorScheme } = useMantineColorScheme(), colorMode = colorScheme !== "auto" ? colorScheme : void 0;
9687
+ } = useDiagramState(selector$1, deepEqual), layoutConstraints = useLayoutConstraints(), handlers = useXYFlowEvents();
9661
9688
  return useOnViewportChange({
9662
9689
  onEnd: ({ x, y, zoom: zoom2 }) => {
9663
9690
  const rounded = {
@@ -9684,12 +9711,7 @@ function XYFlow({
9684
9711
  maxZoom: zoomable ? 1.9 : 1,
9685
9712
  minZoom: zoomable ? MinZoom : 1,
9686
9713
  fitView: fitView2,
9687
- fitViewOptions: {
9688
- minZoom: MinZoom,
9689
- maxZoom: 1,
9690
- padding: fitViewPadding,
9691
- includeHiddenNodes: !0
9692
- },
9714
+ fitViewOptions,
9693
9715
  preventScrolling: zoomable || pannable,
9694
9716
  defaultMarkerColor: "var(--xy-edge-stroke)",
9695
9717
  noDragClassName: "nodrag",
@@ -9721,9 +9743,9 @@ function XYFlow({
9721
9743
  onNodeClick: handlers.onNodeClick,
9722
9744
  onNodeDoubleClick: handlers.onNodeDoubleClick,
9723
9745
  onEdgeClick: handlers.onEdgeClick,
9724
- onInit: () => {
9746
+ onInit: useCallback(() => {
9725
9747
  diagramApi.setState({ initialized: !0 }, !1, "initialized");
9726
- },
9748
+ }, [diagramApi]),
9727
9749
  ...hasOnNodeContextMenu && {
9728
9750
  onNodeContextMenu: handlers.onNodeContextMenu
9729
9751
  },
@@ -9737,9 +9759,242 @@ function XYFlow({
9737
9759
  }
9738
9760
  );
9739
9761
  }
9740
- var container$1 = "_2jkb2y0", buttons = "_2jkb2y1", btn = "_2jkb2y3";
9762
+ function useNavigationHistory() {
9763
+ const store = useDiagramStoreApi(), viewId = useDiagramState((s) => s.view.id), [historyViewId, historyOps, {
9764
+ history,
9765
+ current: historyIndex
9766
+ }] = useStateHistory(viewId), hasBack = historyIndex > 0, hasForward = historyIndex < history.length - 1;
9767
+ return useUpdateEffect(() => {
9768
+ viewId !== historyViewId && historyOps.set(viewId);
9769
+ }, [viewId]), useUpdateEffect(() => {
9770
+ var _a, _b;
9771
+ viewId !== historyViewId && ((_b = (_a = store.getState()).onNavigateTo) == null || _b.call(_a, historyViewId));
9772
+ }, [historyViewId]), useMemo(() => ({
9773
+ hasBack,
9774
+ hasForward,
9775
+ ops: historyOps
9776
+ }), [
9777
+ hasBack,
9778
+ hasForward,
9779
+ historyOps
9780
+ ]);
9781
+ }
9782
+ var panel$1 = "_19mimxc0";
9783
+ function BackwardForwardPanel() {
9784
+ const { hasBack, hasForward, ops } = useNavigationHistory();
9785
+ return /* @__PURE__ */ jsx(
9786
+ Group,
9787
+ {
9788
+ className: clsx(
9789
+ "react-flow__panel",
9790
+ panel$1,
9791
+ "likec4-navigation-panel"
9792
+ ),
9793
+ gap: "xs",
9794
+ children: /* @__PURE__ */ jsxs(AnimatePresence, { children: [
9795
+ hasBack && /* @__PURE__ */ jsx(
9796
+ m.div,
9797
+ {
9798
+ layout: !0,
9799
+ initial: { opacity: 0.05, transform: "translateX(-10px)" },
9800
+ animate: { opacity: 1, transform: "translateX(0)" },
9801
+ exit: {
9802
+ opacity: 0.05,
9803
+ transform: "translateX(-10px)"
9804
+ },
9805
+ children: /* @__PURE__ */ jsx(
9806
+ ActionIcon,
9807
+ {
9808
+ variant: "light",
9809
+ color: "gray",
9810
+ onClick: () => ops.back(),
9811
+ children: /* @__PURE__ */ jsx(IconChevronLeft, {})
9812
+ }
9813
+ )
9814
+ },
9815
+ "back"
9816
+ ),
9817
+ hasForward && /* @__PURE__ */ jsx(
9818
+ m.div,
9819
+ {
9820
+ layout: !0,
9821
+ initial: { opacity: 0.05, transform: "translateX(10px)" },
9822
+ animate: { opacity: 1, transform: "translateX(0)" },
9823
+ exit: {
9824
+ opacity: 0,
9825
+ transform: "translateX(10px)"
9826
+ },
9827
+ children: /* @__PURE__ */ jsx(
9828
+ ActionIcon,
9829
+ {
9830
+ variant: "light",
9831
+ color: "gray",
9832
+ onClick: () => ops.forward(),
9833
+ children: /* @__PURE__ */ jsx(IconChevronRight, {})
9834
+ }
9835
+ )
9836
+ },
9837
+ "forward"
9838
+ )
9839
+ ] })
9840
+ }
9841
+ );
9842
+ }
9843
+ var container$1 = "hbkbtj0", card = "hbkbtj1", title = "hbkbtj2", description = "hbkbtj3";
9844
+ const selector = (s) => ({
9845
+ id: s.view.id,
9846
+ title: s.view.title ?? "untitled",
9847
+ description: s.view.description,
9848
+ links: s.view.links
9849
+ });
9850
+ function DiagramTitlePanel() {
9851
+ const { id: id2, title: title$12, description: description$12, links } = useDiagramState(selector), [isCollapsed, setCollapsed] = useLocalStorage({
9852
+ key: "diagram-title-panel-collapsed",
9853
+ defaultValue: !1
9854
+ }), toggle = () => setCollapsed((v) => !v);
9855
+ return /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
9856
+ m.div,
9857
+ {
9858
+ initial: { opacity: 0.05, scale: 0.7 },
9859
+ animate: { opacity: 1, scale: 1 },
9860
+ exit: {
9861
+ opacity: 0.05,
9862
+ scale: 0.6
9863
+ },
9864
+ className: clsx("react-flow__panel", container$1),
9865
+ style: {
9866
+ transformOrigin: "left center"
9867
+ },
9868
+ children: /* @__PURE__ */ jsxs(
9869
+ Card,
9870
+ {
9871
+ radius: "sm",
9872
+ className: card,
9873
+ p: "md",
9874
+ onDoubleClick: (e) => e.stopPropagation(),
9875
+ children: [
9876
+ /* @__PURE__ */ jsx(CardSection, { mb: 4, children: /* @__PURE__ */ jsx(
9877
+ Button,
9878
+ {
9879
+ fullWidth: !0,
9880
+ size: "xs",
9881
+ h: "sm",
9882
+ py: 2,
9883
+ radius: "0",
9884
+ variant: "subtle",
9885
+ color: "gray",
9886
+ onClick: toggle,
9887
+ children: /* @__PURE__ */ jsx(IconMenu, { size: 11, opacity: 0.7 })
9888
+ }
9889
+ ) }),
9890
+ /* @__PURE__ */ jsxs(Group, { justify: "stretch", wrap: "nowrap", mb: isCollapsed ? 0 : "sm", children: [
9891
+ /* @__PURE__ */ jsx(
9892
+ Text,
9893
+ {
9894
+ component: "div",
9895
+ flex: "1",
9896
+ size: isCollapsed ? "sm" : "lg",
9897
+ fw: 500,
9898
+ lh: 1.1,
9899
+ className: title,
9900
+ children: title$12
9901
+ }
9902
+ ),
9903
+ /* @__PURE__ */ jsxs(
9904
+ Text,
9905
+ {
9906
+ hidden: isCollapsed,
9907
+ component: "div",
9908
+ flex: "0 0 auto",
9909
+ inline: !0,
9910
+ size: "xs",
9911
+ fz: 9,
9912
+ fw: 500,
9913
+ c: "dimmed",
9914
+ style: {
9915
+ userSelect: "all"
9916
+ },
9917
+ children: [
9918
+ /* @__PURE__ */ jsxs("span", { style: { userSelect: "none" }, children: [
9919
+ "id:",
9920
+ " "
9921
+ ] }),
9922
+ id2
9923
+ ]
9924
+ }
9925
+ )
9926
+ ] }),
9927
+ !isCollapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
9928
+ description$12 && /* @__PURE__ */ jsx(
9929
+ Spoiler,
9930
+ {
9931
+ maxHeight: 42,
9932
+ showLabel: /* @__PURE__ */ jsx(Button, { color: "gray", variant: "light", fz: "10", size: "compact-xs", children: "show more" }),
9933
+ hideLabel: /* @__PURE__ */ jsx(Button, { color: "gray", variant: "light", fz: "10", size: "compact-xs", children: "hide" }),
9934
+ children: /* @__PURE__ */ jsx(
9935
+ Text,
9936
+ {
9937
+ component: "div",
9938
+ size: "sm",
9939
+ className: description,
9940
+ children: description$12 || "no description"
9941
+ }
9942
+ )
9943
+ }
9944
+ ),
9945
+ !description$12 && /* @__PURE__ */ jsx(
9946
+ Text,
9947
+ {
9948
+ component: "div",
9949
+ size: "xs",
9950
+ c: "dimmed",
9951
+ children: "no description"
9952
+ }
9953
+ ),
9954
+ links && /* @__PURE__ */ jsx(
9955
+ Stack,
9956
+ {
9957
+ gap: 3,
9958
+ justify: "stretch",
9959
+ align: "stretch",
9960
+ children: links.map((link) => /* @__PURE__ */ jsxs(Group, { wrap: "nowrap", align: "center", gap: "sm", children: [
9961
+ /* @__PURE__ */ jsx(Box, { flex: "1", style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx(
9962
+ Anchor,
9963
+ {
9964
+ href: link,
9965
+ target: "_blank",
9966
+ fz: "xs",
9967
+ truncate: "end",
9968
+ display: "inline-block",
9969
+ w: "100%",
9970
+ children: link
9971
+ }
9972
+ ) }),
9973
+ /* @__PURE__ */ jsx(CopyButton, { value: link, children: ({ copied, copy }) => /* @__PURE__ */ jsx(
9974
+ Button,
9975
+ {
9976
+ size: "compact-xs",
9977
+ fz: "10",
9978
+ variant: "light",
9979
+ onClick: copy,
9980
+ color: copied ? "teal" : "gray",
9981
+ children: copied ? "copied" : "copy"
9982
+ }
9983
+ ) })
9984
+ ] }, link))
9985
+ }
9986
+ )
9987
+ ] })
9988
+ ]
9989
+ }
9990
+ )
9991
+ },
9992
+ id2
9993
+ ) });
9994
+ }
9995
+ var container = "_2jkb2y0", buttons = "_2jkb2y1", btn = "_2jkb2y3";
9741
9996
  function DynamicViewWalkthrough() {
9742
- const {
9997
+ const isMobile = useXYStore((s) => s.width <= 750), {
9743
9998
  nextDynamicStep,
9744
9999
  stopDynamicView,
9745
10000
  activeDynamicViewStep,
@@ -9749,17 +10004,30 @@ function DynamicViewWalkthrough() {
9749
10004
  stopDynamicView: s.stopDynamicView,
9750
10005
  activeDynamicViewStep: s.activeDynamicViewStep,
9751
10006
  hasNextSteps: (s.activeDynamicViewStep ?? 1) < s.view.edges.length
9752
- })), buttonProps = {
10007
+ })), isActive = isNumber(activeDynamicViewStep);
10008
+ useHotkeys(
10009
+ isActive ? [
10010
+ ["ArrowLeft", () => nextDynamicStep(-1)],
10011
+ ["ArrowRight", () => nextDynamicStep()],
10012
+ ["Escape", (e) => {
10013
+ e.stopImmediatePropagation(), stopDynamicView();
10014
+ }, { preventDefault: !0 }]
10015
+ ] : [
10016
+ ["ArrowLeft", () => nextDynamicStep()],
10017
+ ["ArrowRight", () => nextDynamicStep()]
10018
+ ]
10019
+ );
10020
+ const buttonProps = {
9753
10021
  className: btn,
9754
- size: "compact-xl",
9755
- radius: "xl"
10022
+ size: isMobile ? "compact-md" : "lg",
10023
+ radius: isMobile ? "lg" : "xl"
9756
10024
  }, nextStep = (increment = 1) => (e) => {
9757
10025
  e.stopPropagation(), nextDynamicStep(increment);
9758
10026
  };
9759
10027
  return /* @__PURE__ */ jsxs(
9760
10028
  Box,
9761
10029
  {
9762
- className: clsx("react-flow__panel", container$1),
10030
+ className: clsx("react-flow__panel", container),
9763
10031
  children: [
9764
10032
  isNullish(activeDynamicViewStep) && /* @__PURE__ */ jsx(
9765
10033
  Button,
@@ -9783,23 +10051,25 @@ function DynamicViewWalkthrough() {
9783
10051
  children: /* @__PURE__ */ jsx(IconPlayerSkipBackFilled, {})
9784
10052
  }
9785
10053
  ),
9786
- /* @__PURE__ */ jsx(
10054
+ /* @__PURE__ */ jsxs(
9787
10055
  Button,
9788
10056
  {
9789
10057
  ...buttonProps,
9790
- px: "sm",
10058
+ px: hasNextSteps ? "md" : "xl",
9791
10059
  onClick: (e) => {
9792
10060
  e.stopPropagation(), stopDynamicView();
9793
10061
  },
9794
- children: /* @__PURE__ */ jsx(IconPlayerStopFilled, {})
10062
+ children: [
10063
+ hasNextSteps && /* @__PURE__ */ jsx(IconPlayerStopFilled, {}),
10064
+ !hasNextSteps && "End"
10065
+ ]
9795
10066
  }
9796
10067
  ),
9797
- /* @__PURE__ */ jsx(
10068
+ hasNextSteps && /* @__PURE__ */ jsx(
9798
10069
  Button,
9799
10070
  {
9800
10071
  ...buttonProps,
9801
10072
  pr: "lg",
9802
- disabled: !hasNextSteps,
9803
10073
  onClick: nextStep(),
9804
10074
  children: /* @__PURE__ */ jsx(IconPlayerSkipForwardFilled, {})
9805
10075
  }
@@ -9824,20 +10094,20 @@ const {
9824
10094
  }));
9825
10095
  function NodeOptions({ selectedNodeIds }) {
9826
10096
  const diagramApi = useDiagramStoreApi(), nodes = useXYNodesData(selectedNodeIds);
9827
- if (!hasAtLeast(nodes, 1))
10097
+ if (!hasAtLeast$1(nodes, 1))
9828
10098
  return null;
9829
10099
  if (nodes.length !== selectedNodeIds.length)
9830
10100
  throw new Error("NodeOptions: nodes and props.nodes should have the same length");
9831
10101
  const showShapeOption = nodes.some((node) => node.type === "element"), [firstNode, ...rest] = nodes, showOpacityOption = rest.length === 0 && firstNode.type === "compound", triggerChange = (style2) => {
9832
10102
  const targets = nodes.map((node) => node.data.element.id);
9833
- invariant(hasAtLeast(targets, 1), "At least one target is required"), diagramApi.getState().triggerOnChange([{
10103
+ invariant(hasAtLeast$1(targets, 1), "At least one target is required"), diagramApi.getState().triggerChangeElementStyle({
9834
10104
  op: "change-element-style",
9835
10105
  style: style2,
9836
10106
  targets
9837
- }]);
10107
+ });
9838
10108
  };
9839
10109
  return /* @__PURE__ */ jsxs(Stack, { children: [
9840
- /* @__PURE__ */ jsx(Box, { maw: 200, children: /* @__PURE__ */ jsx(Text, { size: "xs", c: rest.length > 0 ? "dimmed" : "", truncate: !0, children: rest.length === 0 ? firstNode.data.element.title : "[ multiple ]" }) }),
10110
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Text, { size: "xs", c: rest.length > 0 ? "dimmed" : "", truncate: !0, children: rest.length === 0 ? firstNode.data.element.title : "[ multiple ]" }) }),
9841
10111
  showShapeOption && /* @__PURE__ */ jsx(
9842
10112
  ShapeOption,
9843
10113
  {
@@ -9856,7 +10126,7 @@ function NodeOptions({ selectedNodeIds }) {
9856
10126
  }
9857
10127
  }
9858
10128
  ),
9859
- showOpacityOption && /* @__PURE__ */ jsxs(Box, { children: [
10129
+ showOpacityOption && /* @__PURE__ */ jsxs("div", { children: [
9860
10130
  /* @__PURE__ */ jsx(Divider, { label: "opacity and border", labelPosition: "left" }),
9861
10131
  /* @__PURE__ */ jsx(
9862
10132
  OpacityOption,
@@ -9889,7 +10159,7 @@ function Colors({
9889
10159
  const changeColor = (color2) => () => {
9890
10160
  selectedColor !== color2 && onColorChange(color2);
9891
10161
  };
9892
- return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(TooltipGroup, { openDelay: 400, closeDelay: 300, children: [
10162
+ return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(TooltipGroup, { openDelay: 400, closeDelay: 300, children: [
9893
10163
  /* @__PURE__ */ jsx(Divider, { label: "color", labelPosition: "left" }),
9894
10164
  /* @__PURE__ */ jsx(Flex, { mt: "xs", maw: 150, gap: "xs", justify: "flex-start", align: "flex-start", direction: "row", wrap: "wrap", children: themedColors.map(({ key, value }) => /* @__PURE__ */ jsx(
9895
10165
  Tooltip,
@@ -9941,7 +10211,7 @@ function ShapeOption({
9941
10211
  onShapeChange
9942
10212
  }) {
9943
10213
  let selectedShape = firstNode.data.element.shape;
9944
- return takeWhile(nodes, (node) => node.data.element.shape !== selectedShape ? (selectedShape = null, !1) : !0), /* @__PURE__ */ jsxs(Box, { children: [
10214
+ return takeWhile(nodes, (node) => node.data.element.shape !== selectedShape ? (selectedShape = null, !1) : !0), /* @__PURE__ */ jsxs("div", { children: [
9945
10215
  /* @__PURE__ */ jsx(Divider, { label: "shape", labelPosition: "left" }),
9946
10216
  /* @__PURE__ */ jsx(
9947
10217
  Select,
@@ -9965,7 +10235,7 @@ function NavigateToOption({
9965
10235
  nodes: [node, ...nodes]
9966
10236
  }) {
9967
10237
  const isMultiple = nodes.length >= 1;
9968
- return /* @__PURE__ */ jsxs(Box, { children: [
10238
+ return /* @__PURE__ */ jsxs("div", { children: [
9969
10239
  /* @__PURE__ */ jsx(Divider, { label: "navigate to", labelPosition: "left" }),
9970
10240
  /* @__PURE__ */ jsx(
9971
10241
  Select,
@@ -9989,7 +10259,7 @@ function OpacityOption({
9989
10259
  }) {
9990
10260
  let selectedOpacity = node.data.element.style.opacity ?? 100;
9991
10261
  const [value, setValue] = useState(selectedOpacity);
9992
- return useEffect(() => {
10262
+ return useUpdateEffect(() => {
9993
10263
  setValue(selectedOpacity);
9994
10264
  }, [selectedOpacity]), /* @__PURE__ */ jsx(
9995
10265
  Slider,
@@ -10009,7 +10279,7 @@ function BorderStyleOption({
10009
10279
  }) {
10010
10280
  let selecteBorderStyle = node.data.element.style.border ?? "dashed";
10011
10281
  const [value, setValue] = useState(selecteBorderStyle);
10012
- return useEffect(() => {
10282
+ return useUpdateEffect(() => {
10013
10283
  setValue(selecteBorderStyle);
10014
10284
  }, [selecteBorderStyle]), /* @__PURE__ */ jsx(Box, { mt: "md", children: /* @__PURE__ */ jsx(
10015
10285
  SegmentedControl,
@@ -10031,15 +10301,17 @@ function BorderStyleOption({
10031
10301
  ) });
10032
10302
  }
10033
10303
  var panel = "_1lmzt1h0";
10304
+ const Empty = [];
10034
10305
  function OptionsPanel() {
10035
- const isFocusDisabled = useDiagramState((s) => isNullish(s.focusedNodeId)), [selectedNodes, setSelectedNodes] = useState([]);
10036
- return useOnSelectionChange({
10037
- onChange: ({ nodes }) => {
10038
- const next = nodes.map((n) => n.id).sort();
10039
- setSelectedNodes((prev) => shallowEqual(prev, next) ? prev : next);
10040
- }
10041
- }), /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: isFocusDisabled && selectedNodes.length > 0 && /* @__PURE__ */ jsx(
10042
- motion.div,
10306
+ const { isFocusDisabled, viewId } = useDiagramState((s) => ({
10307
+ viewId: s.view.id,
10308
+ isFocusDisabled: s.focusedNodeId === null && s.activeDynamicViewStep === null
10309
+ })), selectedNodes = useXYStore(
10310
+ useCallback((s) => s.elementsSelectable && isFocusDisabled ? reduce(s.nodes, (acc, n) => (n.selected && acc.push(n.id), acc), []) : Empty, [isFocusDisabled]),
10311
+ shallowEqual
10312
+ );
10313
+ return DEV && useTilg(), /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: selectedNodes.length > 0 && /* @__PURE__ */ jsx(
10314
+ m.div,
10043
10315
  {
10044
10316
  initial: { opacity: 0, scale: 0.85 },
10045
10317
  animate: { opacity: 1, scale: 1 },
@@ -10053,157 +10325,38 @@ function OptionsPanel() {
10053
10325
  transformOrigin: "center right"
10054
10326
  },
10055
10327
  children: /* @__PURE__ */ jsx(Card, { shadow: "sm", children: /* @__PURE__ */ jsx(NodeOptions, { selectedNodeIds: selectedNodes }) })
10056
- }
10057
- ) });
10058
- }
10059
- var container = "hbkbtj0", paper = "hbkbtj1", title = "hbkbtj2", description = "hbkbtj3";
10060
- const selector = (s) => ({
10061
- id: s.view.id,
10062
- title: s.view.title ?? "untitled",
10063
- description: s.view.description,
10064
- links: s.view.links
10065
- });
10066
- function DiagramTitlePanel() {
10067
- const { id: id2, title: title$12, description: description$12, links } = useDiagramState(selector), [isCollapsed, setCollapsed] = useLocalStorage({
10068
- key: "diagram-title-panel-collapsed",
10069
- defaultValue: !1
10070
- }), toggle = () => setCollapsed((v) => !v);
10071
- return /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
10072
- motion.div,
10073
- {
10074
- initial: { opacity: 0.05, scale: 0.7 },
10075
- animate: { opacity: 1, scale: 1 },
10076
- exit: {
10077
- opacity: 0.05,
10078
- scale: 0.6
10079
- },
10080
- className: clsx("react-flow__panel", container),
10081
- style: {
10082
- transformOrigin: "left center"
10083
- },
10084
- children: /* @__PURE__ */ jsx(
10085
- Paper,
10086
- {
10087
- radius: "sm",
10088
- withBorder: !isCollapsed,
10089
- className: paper,
10090
- p: isCollapsed ? "xs" : "lg",
10091
- onDoubleClick: (e) => e.stopPropagation(),
10092
- children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", justify: "stretch", align: "stretch", children: [
10093
- /* @__PURE__ */ jsxs(Group, { justify: "stretch", wrap: "nowrap", onClick: toggle, style: { cursor: "pointer" }, children: [
10094
- /* @__PURE__ */ jsx(
10095
- Text,
10096
- {
10097
- component: "div",
10098
- flex: "1",
10099
- size: isCollapsed ? "sm" : "lg",
10100
- fw: 500,
10101
- lh: 1.1,
10102
- className: title,
10103
- children: title$12
10104
- }
10105
- ),
10106
- /* @__PURE__ */ jsxs(
10107
- Text,
10108
- {
10109
- hidden: isCollapsed,
10110
- component: "div",
10111
- flex: "0 0 auto",
10112
- inline: !0,
10113
- size: "xs",
10114
- fz: 9,
10115
- fw: 500,
10116
- c: "dimmed",
10117
- style: {
10118
- userSelect: "all"
10119
- },
10120
- children: [
10121
- /* @__PURE__ */ jsxs("span", { style: { userSelect: "none" }, children: [
10122
- "id:",
10123
- " "
10124
- ] }),
10125
- id2
10126
- ]
10127
- }
10128
- )
10129
- ] }),
10130
- !isCollapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
10131
- description$12 && /* @__PURE__ */ jsx(
10132
- Spoiler,
10133
- {
10134
- maxHeight: 42,
10135
- showLabel: /* @__PURE__ */ jsx(Button, { color: "gray", variant: "light", fz: "10", size: "compact-xs", children: "show more" }),
10136
- hideLabel: /* @__PURE__ */ jsx(Button, { color: "gray", variant: "light", fz: "10", size: "compact-xs", children: "hide" }),
10137
- children: /* @__PURE__ */ jsx(
10138
- Text,
10139
- {
10140
- component: "div",
10141
- size: "sm",
10142
- className: description,
10143
- children: description$12 || "no description"
10144
- }
10145
- )
10146
- }
10147
- ),
10148
- !description$12 && /* @__PURE__ */ jsx(
10149
- Text,
10150
- {
10151
- component: "div",
10152
- size: "xs",
10153
- c: "dimmed",
10154
- children: "no description"
10155
- }
10156
- ),
10157
- links && /* @__PURE__ */ jsx(
10158
- Stack,
10159
- {
10160
- gap: 3,
10161
- justify: "stretch",
10162
- align: "stretch",
10163
- children: links.map((link) => /* @__PURE__ */ jsxs(Group, { wrap: "nowrap", align: "center", gap: "sm", children: [
10164
- /* @__PURE__ */ jsx(Box, { flex: "1", style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx(
10165
- Anchor,
10166
- {
10167
- href: link,
10168
- target: "_blank",
10169
- fz: "xs",
10170
- truncate: "end",
10171
- display: "inline-block",
10172
- w: "100%",
10173
- children: link
10174
- }
10175
- ) }),
10176
- /* @__PURE__ */ jsx(CopyButton, { value: link, children: ({ copied, copy }) => /* @__PURE__ */ jsx(
10177
- Button,
10178
- {
10179
- size: "compact-xs",
10180
- fz: "10",
10181
- variant: "light",
10182
- onClick: copy,
10183
- color: copied ? "teal" : "gray",
10184
- children: copied ? "copied" : "copy"
10185
- }
10186
- ) })
10187
- ] }, link))
10188
- }
10189
- )
10190
- ] })
10191
- ] })
10192
- }
10193
- )
10194
10328
  },
10195
- id2
10329
+ viewId
10196
10330
  ) });
10197
10331
  }
10198
- function XYFlowInner({
10332
+ function literalToEnum(value) {
10333
+ switch (value) {
10334
+ case "dots":
10335
+ return BackgroundVariant.Dots;
10336
+ case "lines":
10337
+ return BackgroundVariant.Lines;
10338
+ case "cross":
10339
+ return BackgroundVariant.Cross;
10340
+ default:
10341
+ nonexhaustive(value);
10342
+ }
10343
+ }
10344
+ function XYFlowBackground({ background }) {
10345
+ if (typeof background == "string")
10346
+ return /* @__PURE__ */ jsx(Background, { variant: literalToEnum(background) });
10347
+ const { variant, ...rest } = background;
10348
+ return /* @__PURE__ */ jsx(Background, { variant: literalToEnum(variant), ...rest });
10349
+ }
10350
+ const XYFlowInner = memo(function({
10199
10351
  children: children2,
10200
10352
  background,
10201
10353
  controls,
10202
10354
  showDiagramTitle,
10355
+ showNavigationButtons,
10203
10356
  enableDynamicViewWalkthrough
10204
10357
  }) {
10205
10358
  const {
10206
- isDynamicView: isDynamicView2,
10359
+ isDynamicView,
10207
10360
  isDynamicViewActive,
10208
10361
  readonly
10209
10362
  } = useDiagramState((s) => ({
@@ -10216,10 +10369,11 @@ function XYFlowInner({
10216
10369
  controls && /* @__PURE__ */ jsx(Controls, { position: "bottom-right" }),
10217
10370
  readonly === !1 && /* @__PURE__ */ jsx(OptionsPanel, {}),
10218
10371
  !isDynamicViewActive && showDiagramTitle === !0 && /* @__PURE__ */ jsx(DiagramTitlePanel, {}),
10219
- isDynamicView2 && enableDynamicViewWalkthrough && /* @__PURE__ */ jsx(DynamicViewWalkthrough, {}),
10372
+ isDynamicView && enableDynamicViewWalkthrough && /* @__PURE__ */ jsx(DynamicViewWalkthrough, {}),
10373
+ showNavigationButtons && /* @__PURE__ */ jsx(BackwardForwardPanel, {}),
10220
10374
  children2
10221
10375
  ] });
10222
- }
10376
+ }, shallowEqual);
10223
10377
  function LikeC4Diagram({
10224
10378
  view,
10225
10379
  className,
@@ -10231,13 +10385,15 @@ function LikeC4Diagram({
10231
10385
  nodesSelectable = !readonly,
10232
10386
  nodesDraggable = !readonly,
10233
10387
  background = "dots",
10234
- controls = !readonly,
10388
+ controls = !1,
10235
10389
  showElementLinks = !0,
10236
10390
  showDiagramTitle = !0,
10391
+ showNavigationButtons = !1,
10237
10392
  enableDynamicViewWalkthrough = !0,
10238
10393
  initialWidth,
10239
10394
  initialHeight,
10240
10395
  keepAspectRatio = !1,
10396
+ experimentalEdgeEditing = !1,
10241
10397
  onCanvasClick,
10242
10398
  onCanvasContextMenu,
10243
10399
  onCanvasDblClick,
@@ -10248,7 +10404,7 @@ function LikeC4Diagram({
10248
10404
  onNodeClick,
10249
10405
  onNodeContextMenu
10250
10406
  }) {
10251
- console.log("LikeC4Diagram");
10407
+ DEV && useTilg();
10252
10408
  const initialRef = useRef();
10253
10409
  if (!initialRef.current) {
10254
10410
  const initial = diagramViewToXYFlowData(view, {
@@ -10279,6 +10435,7 @@ function LikeC4Diagram({
10279
10435
  showElementLinks,
10280
10436
  nodesDraggable,
10281
10437
  nodesSelectable,
10438
+ experimentalEdgeEditing,
10282
10439
  onCanvasClick,
10283
10440
  onCanvasContextMenu,
10284
10441
  onEdgeClick,
@@ -10288,50 +10445,90 @@ function LikeC4Diagram({
10288
10445
  onChange,
10289
10446
  onNavigateTo,
10290
10447
  onCanvasDblClick,
10291
- children: /* @__PURE__ */ jsxs(
10448
+ children: /* @__PURE__ */ jsx(LazyMotion, { features: domAnimation, strict: !0, children: /* @__PURE__ */ jsx(
10292
10449
  KeepAspectRatioContainer,
10293
10450
  {
10294
10451
  className: clsx(rootClassName, className),
10295
10452
  enabled: keepAspectRatio,
10296
10453
  width: view.width,
10297
10454
  height: view.height,
10298
- children: [
10299
- /* @__PURE__ */ jsx(
10300
- XYFlow,
10301
- {
10302
- className: clsx(
10303
- "likec4-diagram",
10304
- cssReactFlow,
10305
- controls === !1 && cssNoControls,
10306
- pannable !== !0 && cssDisablePan,
10307
- background === "transparent" && cssTransparentBg
10308
- ),
10309
- defaultNodes: initialRef.current.defaultNodes,
10310
- defaultEdges: initialRef.current.defaultEdges,
10311
- children: /* @__PURE__ */ jsx(
10312
- XYFlowInner,
10313
- {
10314
- showDiagramTitle,
10315
- enableDynamicViewWalkthrough,
10316
- background,
10317
- controls
10318
- }
10319
- )
10320
- }
10321
- ),
10322
- /* @__PURE__ */ jsxs(WhenInitialized, { children: [
10323
- /* @__PURE__ */ jsx(SyncWithDiagram, {}),
10324
- fitView2 && /* @__PURE__ */ jsx(FitViewOnDiagramChange, {}),
10325
- fitView2 && zoomable && /* @__PURE__ */ jsx(SelectEdgesOnNodeFocus, {})
10326
- ] })
10327
- ]
10455
+ children: /* @__PURE__ */ jsx(
10456
+ LikeC4DiagramInnerMemo,
10457
+ {
10458
+ defaultNodes: initialRef.current.defaultNodes,
10459
+ defaultEdges: initialRef.current.defaultEdges,
10460
+ fitView: fitView2,
10461
+ zoomable,
10462
+ background,
10463
+ controls,
10464
+ pannable,
10465
+ showDiagramTitle,
10466
+ showNavigationButtons,
10467
+ enableDynamicViewWalkthrough
10468
+ }
10469
+ )
10328
10470
  }
10329
- )
10471
+ ) })
10330
10472
  }
10331
10473
  )
10332
10474
  }
10333
10475
  ) });
10334
10476
  }
10477
+ const LikeC4DiagramInnerMemo = memo(function({
10478
+ background,
10479
+ fitView: fitView2,
10480
+ zoomable,
10481
+ controls,
10482
+ pannable,
10483
+ defaultNodes,
10484
+ defaultEdges,
10485
+ showDiagramTitle,
10486
+ showNavigationButtons,
10487
+ enableDynamicViewWalkthrough
10488
+ }) {
10489
+ DEV && useTilg();
10490
+ const diagramApi = useDiagramStoreApi(), [isInitialized, setIsInitialized] = useState(diagramApi.getState().initialized);
10491
+ return useEffect(() => {
10492
+ if (!isInitialized)
10493
+ return diagramApi.subscribe(
10494
+ (s) => s.initialized,
10495
+ setIsInitialized,
10496
+ {
10497
+ fireImmediately: !0
10498
+ }
10499
+ );
10500
+ }, [isInitialized]), /* @__PURE__ */ jsxs(Fragment, { children: [
10501
+ /* @__PURE__ */ jsx(
10502
+ XYFlow,
10503
+ {
10504
+ defaultNodes,
10505
+ defaultEdges,
10506
+ className: clsx(
10507
+ "likec4-diagram",
10508
+ cssReactFlow,
10509
+ controls === !1 && cssNoControls,
10510
+ pannable !== !0 && cssDisablePan,
10511
+ background === "transparent" && cssTransparentBg
10512
+ ),
10513
+ children: /* @__PURE__ */ jsx(
10514
+ XYFlowInner,
10515
+ {
10516
+ showNavigationButtons,
10517
+ showDiagramTitle,
10518
+ enableDynamicViewWalkthrough,
10519
+ background,
10520
+ controls
10521
+ }
10522
+ )
10523
+ }
10524
+ ),
10525
+ isInitialized && /* @__PURE__ */ jsxs(Fragment, { children: [
10526
+ /* @__PURE__ */ jsx(SyncWithDiagram, {}),
10527
+ fitView2 && /* @__PURE__ */ jsx(FitViewOnDiagramChange, {}),
10528
+ fitView2 && zoomable && /* @__PURE__ */ jsx(SelectEdgesOnNodeFocus, {})
10529
+ ] })
10530
+ ] });
10531
+ }, shallowEqual);
10335
10532
  function StaticLikeC4Diagram({
10336
10533
  view,
10337
10534
  fitView: fitView2 = !0,