@likec4/diagram 1.0.2 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/KeepAspectRatioContainer.d.ts +9 -0
  2. package/dist/LikeC4Diagram.css.d.ts +1 -0
  3. package/dist/LikeC4Diagram.d.ts +1 -1
  4. package/dist/LikeC4Diagram.props.d.ts +16 -11
  5. package/dist/index.mjs +639 -762
  6. package/dist/state/DiagramContext.d.ts +54 -18
  7. package/dist/state/diagramStore.d.ts +61 -21
  8. package/dist/state/useDiagramStore.d.ts +54 -18
  9. package/dist/style.css +690 -79
  10. package/dist/ui/DiagramTitlePanel.css.d.ts +4 -0
  11. package/dist/ui/DiagramTitlePanel.d.ts +2 -0
  12. package/dist/ui/OptionsPanel.d.ts +1 -2
  13. package/dist/ui/index.d.ts +0 -1
  14. package/dist/xyflow/SelectEdgesOnNodeFocus.d.ts +1 -0
  15. package/dist/xyflow/{XYFlowWrapper.d.ts → XYFlow.d.ts} +2 -2
  16. package/dist/xyflow/XYFlowEvents.d.ts +133 -13
  17. package/dist/xyflow/edges/RelationshipEdge.d.ts +2 -2
  18. package/dist/xyflow/edges/edges.css.d.ts +1 -0
  19. package/dist/xyflow/hooks/useXYFlow.d.ts +20 -20
  20. package/dist/xyflow/nodes/compound/CompoundNode.css.d.ts +7 -5
  21. package/dist/xyflow/types.d.ts +2 -2
  22. package/package.json +5 -3
  23. package/src/{ui/KeepAspectRatio.tsx → KeepAspectRatioContainer.tsx} +7 -6
  24. package/src/LikeC4Diagram.css.ts +8 -1
  25. package/src/LikeC4Diagram.props.ts +17 -12
  26. package/src/LikeC4Diagram.tsx +9 -6
  27. package/src/StaticLikeC4Diagram.tsx +1 -0
  28. package/src/globals.css.ts +48 -38
  29. package/src/state/diagramStore.ts +125 -68
  30. package/src/ui/DiagramTitlePanel.css.ts +32 -0
  31. package/src/ui/DiagramTitlePanel.tsx +139 -0
  32. package/src/ui/OptionsPanel.tsx +4 -23
  33. package/src/ui/index.ts +0 -1
  34. package/src/ui/options/NodeOptions.tsx +107 -30
  35. package/src/xyflow/FitviewOnDiagramChange.tsx +26 -20
  36. package/src/xyflow/SelectEdgesOnNodeFocus.tsx +57 -0
  37. package/src/xyflow/SyncWithDiagram.tsx +35 -26
  38. package/src/xyflow/{XYFlowWrapper.tsx → XYFlow.tsx} +24 -27
  39. package/src/xyflow/XYFlowEvents.tsx +175 -81
  40. package/src/xyflow/diagram-to-xyflow.ts +4 -4
  41. package/src/xyflow/edges/RelationshipEdge.tsx +43 -47
  42. package/src/xyflow/edges/edges.css.ts +77 -36
  43. package/src/xyflow/nodes/compound/CompoundNode.css.ts +94 -44
  44. package/src/xyflow/nodes/compound/CompoundNode.tsx +29 -31
  45. package/src/xyflow/nodes/element/ElementNode.tsx +2 -2
  46. package/src/xyflow/nodes/element/element.css.ts +1 -0
  47. package/src/xyflow/nodes/shared/NavigateToBtn.tsx +2 -1
  48. package/dist/ui/KeepAspectRatio.css.d.ts +0 -1
  49. package/dist/ui/KeepAspectRatio.d.ts +0 -9
  50. package/src/ui/KeepAspectRatio.css.ts +0 -7
package/dist/index.mjs CHANGED
@@ -2,18 +2,20 @@ 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), 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, useEffect, useContext, useMemo, forwardRef, useCallback, useRef, 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 { MantineContext, Box, Stack, Text, TooltipGroup, Divider, Flex, Tooltip, ColorSwatch, CheckIcon, rem, Select, Card, ActionIcon, HoverCard, HoverCardTarget, UnstyledButton, HoverCardDropdown, Group, Anchor, CopyButton, Button, useMantineColorScheme } from "@mantine/core";
9
+ import { Box, MantineContext, Paper, Stack, Group, Text, Spoiler, Button, Anchor, CopyButton, Divider, TooltipGroup, Flex, Tooltip, ColorSwatch, CheckIcon, rem, Select, Slider, SegmentedControl, Card, ActionIcon, HoverCard, HoverCardTarget, UnstyledButton, HoverCardDropdown, useMantineColorScheme } from "@mantine/core";
10
10
  import { invariant, isAncestor, nonNullable, nonexhaustive, defaultTheme, ElementShapes } from "@likec4/core";
11
11
  import { DEV } from "esm-env";
12
12
  import { shallowEqual, deepEqual } from "fast-equals";
13
+ import { isNullish, entries, keys, hasAtLeast, takeWhile, clamp as clamp$1, isNumber } from "remeda";
13
14
  import { subscribeWithSelector, devtools } from "zustand/middleware";
14
- import { useFirstMountState, useCustomCompareEffect, useDebouncedState, useRafEffect, useDebouncedEffect } from "@react-hookz/web";
15
+ import { useFirstMountState, useCustomCompareEffect, useDebouncedCallback, useRafEffect, useDebouncedEffect } from "@react-hookz/web";
15
16
  import { AnimatePresence, motion } from "framer-motion";
16
- import { isNullish, keys, hasAtLeast, takeWhile, clamp as clamp$1, isNumber } from "remeda";
17
+ import { useLocalStorage } from "@mantine/hooks";
18
+ import { line, curveCatmullRomOpen } from "d3-shape";
17
19
  var rootClassName = "likec4-diagram-root";
18
20
  function cc(names) {
19
21
  if (typeof names == "string" || typeof names == "number")
@@ -874,7 +876,7 @@ function extend(parent, definition) {
874
876
  prototype[key] = definition[key];
875
877
  return prototype;
876
878
  }
877
- function Color$1() {
879
+ function Color() {
878
880
  }
879
881
  var darker = 0.7, brighter = 1 / darker, reI = "\\s*([+-]?\\d+)\\s*", reN = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*", reP = "\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*", reHex = /^#([0-9a-f]{3,8})$/, reRgbInteger = new RegExp(`^rgb\\(${reI},${reI},${reI}\\)$`), reRgbPercent = new RegExp(`^rgb\\(${reP},${reP},${reP}\\)$`), reRgbaInteger = new RegExp(`^rgba\\(${reI},${reI},${reI},${reN}\\)$`), reRgbaPercent = new RegExp(`^rgba\\(${reP},${reP},${reP},${reN}\\)$`), reHslPercent = new RegExp(`^hsl\\(${reN},${reP},${reP}\\)$`), reHslaPercent = new RegExp(`^hsla\\(${reN},${reP},${reP},${reN}\\)$`), named = {
880
882
  aliceblue: 15792383,
@@ -1026,9 +1028,9 @@ var darker = 0.7, brighter = 1 / darker, reI = "\\s*([+-]?\\d+)\\s*", reN = "\\s
1026
1028
  yellow: 16776960,
1027
1029
  yellowgreen: 10145074
1028
1030
  };
1029
- define(Color$1, color, {
1030
- copy(channels2) {
1031
- return Object.assign(new this.constructor(), this, channels2);
1031
+ define(Color, color, {
1032
+ copy(channels) {
1033
+ return Object.assign(new this.constructor(), this, channels);
1032
1034
  },
1033
1035
  displayable() {
1034
1036
  return this.rgb().displayable();
@@ -1064,7 +1066,7 @@ function rgba(r2, g, b, a) {
1064
1066
  return a <= 0 && (r2 = g = b = NaN), new Rgb(r2, g, b, a);
1065
1067
  }
1066
1068
  function rgbConvert(o) {
1067
- return o instanceof Color$1 || (o = color(o)), o ? (o = o.rgb(), new Rgb(o.r, o.g, o.b, o.opacity)) : new Rgb();
1069
+ return o instanceof Color || (o = color(o)), o ? (o = o.rgb(), new Rgb(o.r, o.g, o.b, o.opacity)) : new Rgb();
1068
1070
  }
1069
1071
  function rgb(r2, g, b, opacity) {
1070
1072
  return arguments.length === 1 ? rgbConvert(r2) : new Rgb(r2, g, b, opacity ?? 1);
@@ -1072,7 +1074,7 @@ function rgb(r2, g, b, opacity) {
1072
1074
  function Rgb(r2, g, b, opacity) {
1073
1075
  this.r = +r2, this.g = +g, this.b = +b, this.opacity = +opacity;
1074
1076
  }
1075
- define(Rgb, rgb, extend(Color$1, {
1077
+ define(Rgb, rgb, extend(Color, {
1076
1078
  brighter(k) {
1077
1079
  return k = k == null ? brighter : Math.pow(brighter, k), new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
1078
1080
  },
@@ -1120,7 +1122,7 @@ function hsla(h, s, l, a) {
1120
1122
  function hslConvert(o) {
1121
1123
  if (o instanceof Hsl)
1122
1124
  return new Hsl(o.h, o.s, o.l, o.opacity);
1123
- if (o instanceof Color$1 || (o = color(o)), !o)
1125
+ if (o instanceof Color || (o = color(o)), !o)
1124
1126
  return new Hsl();
1125
1127
  if (o instanceof Hsl)
1126
1128
  return o;
@@ -1134,7 +1136,7 @@ function hsl(h, s, l, opacity) {
1134
1136
  function Hsl(h, s, l, opacity) {
1135
1137
  this.h = +h, this.s = +s, this.l = +l, this.opacity = +opacity;
1136
1138
  }
1137
- define(Hsl, hsl, extend(Color$1, {
1139
+ define(Hsl, hsl, extend(Color, {
1138
1140
  brighter(k) {
1139
1141
  return k = k == null ? brighter : Math.pow(brighter, k), new Hsl(this.h, this.s, this.l * k, this.opacity);
1140
1142
  },
@@ -1270,7 +1272,7 @@ function interpolateTransform(parse, pxComma, pxParen, degParen) {
1270
1272
  function skewX(a, b, s, q) {
1271
1273
  a !== b ? q.push({ i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: interpolateNumber(a, b) }) : b && s.push(pop(s) + "skewX(" + b + degParen);
1272
1274
  }
1273
- function scale2(xa, ya, xb, yb, s, q) {
1275
+ function scale(xa, ya, xb, yb, s, q) {
1274
1276
  if (xa !== xb || ya !== yb) {
1275
1277
  var i = s.push(pop(s) + "scale(", null, ",", null, ")");
1276
1278
  q.push({ i: i - 4, x: interpolateNumber(xa, xb) }, { i: i - 2, x: interpolateNumber(ya, yb) });
@@ -1279,7 +1281,7 @@ function interpolateTransform(parse, pxComma, pxParen, degParen) {
1279
1281
  }
1280
1282
  return function(a, b) {
1281
1283
  var s = [], q = [];
1282
- return a = parse(a), b = parse(b), translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q), rotate(a.rotate, b.rotate, s, q), skewX(a.skewX, b.skewX, s, q), scale2(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q), a = b = null, function(t) {
1284
+ return a = parse(a), b = parse(b), translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q), rotate(a.rotate, b.rotate, s, q), skewX(a.skewX, b.skewX, s, q), scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q), a = b = null, function(t) {
1283
1285
  for (var i = -1, n = q.length, o; ++i < n; )
1284
1286
  s[(o = q[i]).i] = o.x(t);
1285
1287
  return s.join("");
@@ -2039,7 +2041,7 @@ function zoom() {
2039
2041
  }, zoom2.scaleTo = function(selection2, k, p, event) {
2040
2042
  zoom2.transform(selection2, function() {
2041
2043
  var e = extent.apply(this, arguments), t0 = this.__zoom, p0 = p == null ? centroid(e) : typeof p == "function" ? p.apply(this, arguments) : p, p1 = t0.invert(p0), k1 = typeof k == "function" ? k.apply(this, arguments) : k;
2042
- return constrain(translate(scale2(t0, k1), p0, p1), e, translateExtent);
2044
+ return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent);
2043
2045
  }, p, event);
2044
2046
  }, zoom2.translateBy = function(selection2, x, y, event) {
2045
2047
  zoom2.transform(selection2, function() {
@@ -2057,7 +2059,7 @@ function zoom() {
2057
2059
  ), e, translateExtent);
2058
2060
  }, p, event);
2059
2061
  };
2060
- function scale2(transform2, k) {
2062
+ function scale(transform2, k) {
2061
2063
  return k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k)), k === transform2.k ? transform2 : new Transform(k, transform2.x, transform2.y);
2062
2064
  }
2063
2065
  function translate(transform2, p0, p1) {
@@ -2131,7 +2133,7 @@ function zoom() {
2131
2133
  return;
2132
2134
  g.mouse = [p, t.invert(p)], interrupt(this), g.start();
2133
2135
  }
2134
- noevent(event), g.wheel = setTimeout(wheelidled, wheelDelay), g.zoom("mouse", constrain(translate(scale2(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent));
2136
+ noevent(event), g.wheel = setTimeout(wheelidled, wheelDelay), g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent));
2135
2137
  function wheelidled() {
2136
2138
  g.wheel = null, g.end();
2137
2139
  }
@@ -2154,7 +2156,7 @@ function zoom() {
2154
2156
  }
2155
2157
  function dblclicked(event, ...args) {
2156
2158
  if (filter2.apply(this, arguments)) {
2157
- var t0 = this.__zoom, p0 = pointer(event.changedTouches ? event.changedTouches[0] : event, this), p1 = t0.invert(p0), k1 = t0.k * (event.shiftKey ? 0.5 : 2), t1 = constrain(translate(scale2(t0, k1), p0, p1), extent.apply(this, args), translateExtent);
2159
+ var t0 = this.__zoom, p0 = pointer(event.changedTouches ? event.changedTouches[0] : event, this), p1 = t0.invert(p0), k1 = t0.k * (event.shiftKey ? 0.5 : 2), t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, args), translateExtent);
2158
2160
  noevent(event), duration > 0 ? select(this).transition().duration(duration).call(schedule2, t1, p0, event) : select(this).call(zoom2.transform, t1, p0, event);
2159
2161
  }
2160
2162
  }
@@ -2175,7 +2177,7 @@ function zoom() {
2175
2177
  t = touches[i], p = pointer(t, this), g.touch0 && g.touch0[2] === t.identifier ? g.touch0[0] = p : g.touch1 && g.touch1[2] === t.identifier && (g.touch1[0] = p);
2176
2178
  if (t = g.that.__zoom, g.touch1) {
2177
2179
  var p0 = g.touch0[0], l0 = g.touch0[1], p1 = g.touch1[0], l1 = g.touch1[1], dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp, dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
2178
- t = scale2(t, Math.sqrt(dp / dl)), p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2], l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
2180
+ t = scale(t, Math.sqrt(dp / dl)), p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2], l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
2179
2181
  } else if (g.touch0)
2180
2182
  p = g.touch0[0], l = g.touch0[1];
2181
2183
  else
@@ -3625,10 +3627,10 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
3625
3627
  const { transform: transform2, snapGrid, snapToGrid, nodeOrigin: storeNodeOrigin } = getStoreItems(), pointerPosition = getPointerPosition(event.sourceEvent, { transform: transform2, snapGrid, snapToGrid }), childChanges = [];
3626
3628
  if (!node)
3627
3629
  return;
3628
- const { x: prevX, y: prevY, width: prevWidth, height: prevHeight } = prevValues, change2 = {}, nodeOrigin = node.origin ?? storeNodeOrigin, { width, height, x, y } = getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio, nodeOrigin, parentExtent, childExtent), isWidthChange = width !== prevWidth, isHeightChange = height !== prevHeight, isXPosChange = x !== prevX && isWidthChange, isYPosChange = y !== prevY && isHeightChange;
3630
+ const { x: prevX, y: prevY, width: prevWidth, height: prevHeight } = prevValues, change = {}, nodeOrigin = node.origin ?? storeNodeOrigin, { width, height, x, y } = getDimensionsAfterResize(startValues, controlDirection, pointerPosition, boundaries, keepAspectRatio, nodeOrigin, parentExtent, childExtent), isWidthChange = width !== prevWidth, isHeightChange = height !== prevHeight, isXPosChange = x !== prevX && isWidthChange, isYPosChange = y !== prevY && isHeightChange;
3629
3631
  if (!isXPosChange && !isYPosChange && !isWidthChange && !isHeightChange)
3630
3632
  return;
3631
- if ((isXPosChange || isYPosChange || nodeOrigin[0] === 1 || nodeOrigin[1] == 1) && (change2.x = isXPosChange ? x : prevValues.x, change2.y = isYPosChange ? y : prevValues.y, prevValues.x = change2.x, prevValues.y = change2.y, parentNode && node.expandParent && (change2.x && change2.x < 0 && (prevValues.x = 0, startValues.x = startValues.x - change2.x), change2.y && change2.y < 0 && (prevValues.y = 0, startValues.y = startValues.y - change2.y)), childNodes.length > 0)) {
3633
+ if ((isXPosChange || isYPosChange || nodeOrigin[0] === 1 || nodeOrigin[1] == 1) && (change.x = isXPosChange ? x : prevValues.x, change.y = isYPosChange ? y : prevValues.y, prevValues.x = change.x, prevValues.y = change.y, parentNode && node.expandParent && (change.x && change.x < 0 && (prevValues.x = 0, startValues.x = startValues.x - change.x), change.y && change.y < 0 && (prevValues.y = 0, startValues.y = startValues.y - change.y)), childNodes.length > 0)) {
3632
3634
  const xChange = x - prevX, yChange = y - prevY;
3633
3635
  for (const childNode of childNodes)
3634
3636
  childNode.position = {
@@ -3636,7 +3638,7 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
3636
3638
  y: childNode.position.y - yChange + nodeOrigin[1] * (height - prevHeight)
3637
3639
  }, childChanges.push(childNode);
3638
3640
  }
3639
- (isWidthChange || isHeightChange) && (change2.width = isWidthChange ? width : prevValues.width, change2.height = isHeightChange ? height : prevValues.height, prevValues.width = change2.width, prevValues.height = change2.height);
3641
+ (isWidthChange || isHeightChange) && (change.width = isWidthChange ? width : prevValues.width, change.height = isHeightChange ? height : prevValues.height, prevValues.width = change.width, prevValues.height = change.height);
3640
3642
  const direction = getResizeDirection({
3641
3643
  width: prevValues.width,
3642
3644
  prevWidth,
@@ -3645,7 +3647,7 @@ function XYResizer({ domNode, nodeId, getStoreItems, onChange, onEnd }) {
3645
3647
  affectsX: controlDirection.affectsX,
3646
3648
  affectsY: controlDirection.affectsY
3647
3649
  }), nextValues = { ...prevValues, direction };
3648
- (shouldResize == null ? void 0 : shouldResize(event, nextValues)) !== !1 && (onResize == null || onResize(event, nextValues), onChange(change2, childChanges));
3650
+ (shouldResize == null ? void 0 : shouldResize(event, nextValues)) !== !1 && (onResize == null || onResize(event, nextValues), onChange(change, childChanges));
3649
3651
  }).on("end", (event) => {
3650
3652
  onResizeEnd == null || onResizeEnd(event, { ...prevValues }), onEnd == null || onEnd();
3651
3653
  });
@@ -3948,15 +3950,15 @@ const useViewportHelper = () => {
3948
3950
  };
3949
3951
  function applyChanges(changes, elements) {
3950
3952
  const updatedElements = [], changesMap = /* @__PURE__ */ new Map();
3951
- for (const change2 of changes)
3952
- if (change2.type === "add") {
3953
- updatedElements.push(change2.item);
3953
+ for (const change of changes)
3954
+ if (change.type === "add") {
3955
+ updatedElements.push(change.item);
3954
3956
  continue;
3955
- } else if (change2.type === "remove" || change2.type === "replace")
3956
- changesMap.set(change2.id, [change2]);
3957
+ } else if (change.type === "remove" || change.type === "replace")
3958
+ changesMap.set(change.id, [change]);
3957
3959
  else {
3958
- const elementChanges = changesMap.get(change2.id);
3959
- elementChanges ? elementChanges.push(change2) : changesMap.set(change2.id, [change2]);
3960
+ const elementChanges = changesMap.get(change.id);
3961
+ elementChanges ? elementChanges.push(change) : changesMap.set(change.id, [change]);
3960
3962
  }
3961
3963
  for (const element of elements) {
3962
3964
  const changes2 = changesMap.get(element.id);
@@ -3971,24 +3973,24 @@ function applyChanges(changes, elements) {
3971
3973
  continue;
3972
3974
  }
3973
3975
  const updatedElement = { ...element };
3974
- for (const change2 of changes2)
3975
- applyChange(change2, updatedElement);
3976
+ for (const change of changes2)
3977
+ applyChange(change, updatedElement);
3976
3978
  updatedElements.push(updatedElement);
3977
3979
  }
3978
3980
  return updatedElements;
3979
3981
  }
3980
- function applyChange(change2, element) {
3981
- switch (change2.type) {
3982
+ function applyChange(change, element) {
3983
+ switch (change.type) {
3982
3984
  case "select": {
3983
- element.selected = change2.selected;
3985
+ element.selected = change.selected;
3984
3986
  break;
3985
3987
  }
3986
3988
  case "position": {
3987
- typeof change2.position < "u" && (element.position = change2.position), typeof change2.dragging < "u" && (element.dragging = change2.dragging);
3989
+ typeof change.position < "u" && (element.position = change.position), typeof change.dragging < "u" && (element.dragging = change.dragging);
3988
3990
  break;
3989
3991
  }
3990
3992
  case "dimensions": {
3991
- typeof change2.dimensions < "u" && (element.measured ?? (element.measured = {}), element.measured.width = change2.dimensions.width, element.measured.height = change2.dimensions.height, change2.setAttributes && (element.width = change2.dimensions.width, element.height = change2.dimensions.height)), typeof change2.resizing == "boolean" && (element.resizing = change2.resizing);
3993
+ typeof change.dimensions < "u" && (element.measured ?? (element.measured = {}), element.measured.width = change.dimensions.width, element.measured.height = change.dimensions.height, change.setAttributes && (element.width = change.dimensions.width, element.height = change.dimensions.height)), typeof change.resizing == "boolean" && (element.resizing = change.resizing);
3992
3994
  break;
3993
3995
  }
3994
3996
  }
@@ -4669,9 +4671,9 @@ function useVisibleNodeIds(onlyRenderVisible) {
4669
4671
  }
4670
4672
  const selector$e = (s) => s.updateNodeInternals;
4671
4673
  function useResizeObserver() {
4672
- const updateNodeInternals2 = useStore(selector$e), [resizeObserver] = useState(() => typeof ResizeObserver > "u" ? null : new ResizeObserver((entries) => {
4674
+ const updateNodeInternals2 = useStore(selector$e), [resizeObserver] = useState(() => typeof ResizeObserver > "u" ? null : new ResizeObserver((entries2) => {
4673
4675
  const updates = /* @__PURE__ */ new Map();
4674
- entries.forEach((entry) => {
4676
+ entries2.forEach((entry) => {
4675
4677
  const id2 = entry.target.getAttribute("data-id");
4676
4678
  updates.set(id2, {
4677
4679
  id: id2,
@@ -5320,13 +5322,13 @@ const GraphView = memo(GraphViewComponent), getInitialState = ({ nodes, edges, d
5320
5322
  updateNodePositions: (nodeDragItems, dragging = !1) => {
5321
5323
  const parentExpandChildren = [], changes = [];
5322
5324
  for (const [id2, dragItem] of nodeDragItems) {
5323
- const change2 = {
5325
+ const change = {
5324
5326
  id: id2,
5325
5327
  type: "position",
5326
5328
  position: dragItem.position,
5327
5329
  dragging
5328
5330
  };
5329
- dragItem != null && dragItem.expandParent && (dragItem != null && dragItem.parentId) && change2.position && (parentExpandChildren.push({
5331
+ dragItem != null && dragItem.expandParent && (dragItem != null && dragItem.parentId) && change.position && (parentExpandChildren.push({
5330
5332
  id: id2,
5331
5333
  parentId: dragItem.parentId,
5332
5334
  rect: {
@@ -5334,7 +5336,7 @@ const GraphView = memo(GraphViewComponent), getInitialState = ({ nodes, edges, d
5334
5336
  width: dragItem.measured.width,
5335
5337
  height: dragItem.measured.height
5336
5338
  }
5337
- }), change2.position.x = Math.max(0, change2.position.x), change2.position.y = Math.max(0, change2.position.y)), changes.push(change2);
5339
+ }), change.position.x = Math.max(0, change.position.x), change.position.y = Math.max(0, change.position.y)), changes.push(change);
5338
5340
  }
5339
5341
  if (parentExpandChildren.length > 0) {
5340
5342
  const { nodeLookup, parentLookup } = get2(), parentExpandChanges = handleExpandParent(parentExpandChildren, nodeLookup, parentLookup);
@@ -5645,7 +5647,7 @@ function NodeComponentWrapperInner({ id: id2, nodeOrigin, nodeColorFunc, nodeStr
5645
5647
  }
5646
5648
  const NodeComponentWrapper = memo(NodeComponentWrapperInner);
5647
5649
  var MiniMapNodes$1 = memo(MiniMapNodes);
5648
- const defaultWidth = 200, defaultHeight = 150, selector$1 = (s) => {
5650
+ const defaultWidth = 200, defaultHeight = 150, selector$1$1 = (s) => {
5649
5651
  const viewBB = {
5650
5652
  x: -s.transform[0] / s.transform[2],
5651
5653
  y: -s.transform[1] / s.transform[2],
@@ -5688,7 +5690,7 @@ function MiniMapComponent({
5688
5690
  zoomStep = 10,
5689
5691
  offsetScale = 5
5690
5692
  }) {
5691
- const store = useStoreApi(), svg = useRef(null), { boundingRect, viewBB, rfId, panZoom, translateExtent, flowWidth, flowHeight } = useStore(selector$1, shallow), elementWidth = (style2 == null ? void 0 : style2.width) ?? defaultWidth, elementHeight = (style2 == null ? void 0 : style2.height) ?? defaultHeight, scaledWidth = boundingRect.width / elementWidth, scaledHeight = boundingRect.height / elementHeight, viewScale = Math.max(scaledWidth, scaledHeight), viewWidth = viewScale * elementWidth, viewHeight = viewScale * elementHeight, offset = offsetScale * viewScale, x = boundingRect.x - (viewWidth - boundingRect.width) / 2 - offset, y = boundingRect.y - (viewHeight - boundingRect.height) / 2 - offset, width = viewWidth + offset * 2, height = viewHeight + offset * 2, labelledBy = `${ARIA_LABEL_KEY}-${rfId}`, viewScaleRef = useRef(0), minimapInstance = useRef();
5693
+ const store = useStoreApi(), svg = useRef(null), { boundingRect, viewBB, rfId, panZoom, translateExtent, flowWidth, flowHeight } = useStore(selector$1$1, shallow), elementWidth = (style2 == null ? void 0 : style2.width) ?? defaultWidth, elementHeight = (style2 == null ? void 0 : style2.height) ?? defaultHeight, scaledWidth = boundingRect.width / elementWidth, scaledHeight = boundingRect.height / elementHeight, viewScale = Math.max(scaledWidth, scaledHeight), viewWidth = viewScale * elementWidth, viewHeight = viewScale * elementHeight, offset = offsetScale * viewScale, x = boundingRect.x - (viewWidth - boundingRect.width) / 2 - offset, y = boundingRect.y - (viewHeight - boundingRect.height) / 2 - offset, width = viewWidth + offset * 2, height = viewHeight + offset * 2, labelledBy = `${ARIA_LABEL_KEY}-${rfId}`, viewScaleRef = useRef(0), minimapInstance = useRef();
5692
5694
  viewScaleRef.current = viewScale, useEffect(() => {
5693
5695
  if (svg.current && panZoom)
5694
5696
  return minimapInstance.current = XYMinimap({
@@ -5751,22 +5753,22 @@ function ResizeControl({ nodeId, position, variant = ResizeControlVariant.Handle
5751
5753
  nodeOrigin
5752
5754
  };
5753
5755
  },
5754
- onChange: (change2, childChanges) => {
5755
- const { triggerNodeChanges, nodeLookup, parentLookup, nodeOrigin } = store.getState(), changes = [], nextPosition = { x: change2.x, y: change2.y }, node = nodeLookup.get(id2);
5756
+ onChange: (change, childChanges) => {
5757
+ const { triggerNodeChanges, nodeLookup, parentLookup, nodeOrigin } = store.getState(), changes = [], nextPosition = { x: change.x, y: change.y }, node = nodeLookup.get(id2);
5756
5758
  if (node && node.expandParent && node.parentId) {
5757
5759
  const child = {
5758
5760
  id: node.id,
5759
5761
  parentId: node.parentId,
5760
5762
  rect: {
5761
- width: change2.width ?? node.measured.width,
5762
- height: change2.height ?? node.measured.height,
5763
+ width: change.width ?? node.measured.width,
5764
+ height: change.height ?? node.measured.height,
5763
5765
  ...evaluateAbsolutePosition({
5764
- x: change2.x ?? node.position.x,
5765
- y: change2.y ?? node.position.y
5766
+ x: change.x ?? node.position.x,
5767
+ y: change.y ?? node.position.y
5766
5768
  }, node.parentId, nodeLookup, node.origin ?? nodeOrigin)
5767
5769
  }
5768
5770
  }, parentExpandChanges = handleExpandParent([child], nodeLookup, parentLookup, nodeOrigin);
5769
- changes.push(...parentExpandChanges), nextPosition.x = change2.x ? Math.max(0, change2.x) : void 0, nextPosition.y = change2.y ? Math.max(0, change2.y) : void 0;
5771
+ changes.push(...parentExpandChanges), nextPosition.x = change.x ? Math.max(0, change.x) : void 0, nextPosition.y = change.y ? Math.max(0, change.y) : void 0;
5770
5772
  }
5771
5773
  if (nextPosition.x !== void 0 && nextPosition.y !== void 0) {
5772
5774
  const positionChange = {
@@ -5776,15 +5778,15 @@ function ResizeControl({ nodeId, position, variant = ResizeControlVariant.Handle
5776
5778
  };
5777
5779
  changes.push(positionChange);
5778
5780
  }
5779
- if (change2.width !== void 0 && change2.height !== void 0) {
5781
+ if (change.width !== void 0 && change.height !== void 0) {
5780
5782
  const dimensionChange = {
5781
5783
  id: id2,
5782
5784
  type: "dimensions",
5783
5785
  resizing: !0,
5784
5786
  setAttributes: !0,
5785
5787
  dimensions: {
5786
- width: change2.width,
5787
- height: change2.height
5788
+ width: change.width,
5789
+ height: change.height
5788
5790
  }
5789
5791
  };
5790
5792
  changes.push(dimensionChange);
@@ -5858,7 +5860,30 @@ function clsx() {
5858
5860
  (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
5859
5861
  return n;
5860
5862
  }
5861
- var cssReactFlow = "_2h8g8h0", cssDisablePan = "_2h8g8h1", cssTransparentBg = "_2h8g8h2", cssNoControls = "_2h8g8h3";
5863
+ var keepAspectRatioContainer = "_2h8g8h0", cssReactFlow = "_2h8g8h1", cssDisablePan = "_2h8g8h2", cssTransparentBg = "_2h8g8h3", cssNoControls = "_2h8g8h4";
5864
+ function KeepAspectRatioContainer({
5865
+ children: children2,
5866
+ width,
5867
+ height,
5868
+ enabled,
5869
+ className,
5870
+ style: style2,
5871
+ ...rest
5872
+ }) {
5873
+ return /* @__PURE__ */ jsx(
5874
+ Box,
5875
+ {
5876
+ ...rest,
5877
+ className: clsx(keepAspectRatioContainer, className),
5878
+ style: enabled ? {
5879
+ ...style2,
5880
+ aspectRatio: `${Math.ceil(width)}/${Math.ceil(height)}`,
5881
+ maxHeight: Math.ceil(height)
5882
+ } : style2,
5883
+ children: children2
5884
+ }
5885
+ );
5886
+ }
5862
5887
  function EnsureMantine({ children: children2 }) {
5863
5888
  if (!useContext(MantineContext))
5864
5889
  throw new Error("LikeC4Diagram must be a child of MantineProvider");
@@ -6481,9 +6506,9 @@ class Solver {
6481
6506
  * Update the values of the variables.
6482
6507
  */
6483
6508
  updateVariables() {
6484
- let vars2 = this._varMap, rows = this._rowMap;
6485
- for (let i = 0, n = vars2.size(); i < n; ++i) {
6486
- let pair = vars2.itemAt(i), rowPair = rows.find(pair.second);
6509
+ let vars = this._varMap, rows = this._rowMap;
6510
+ for (let i = 0, n = vars.size(); i < n; ++i) {
6511
+ let pair = vars.itemAt(i), rowPair = rows.find(pair.second);
6487
6512
  rowPair !== void 0 ? pair.first.setValue(rowPair.second.constant()) : pair.first.setValue(0);
6488
6513
  }
6489
6514
  }
@@ -7201,6 +7226,7 @@ const ZIndexes = {
7201
7226
  initialized: !1,
7202
7227
  previousViews: [],
7203
7228
  viewportChanged: !1,
7229
+ focusedNodeId: null,
7204
7230
  hoveredNodeId: null,
7205
7231
  hoveredEdgeId: null,
7206
7232
  lastClickedNodeId: null,
@@ -7230,6 +7256,7 @@ function createDiagramStore(props) {
7230
7256
  view: currentView,
7231
7257
  lastOnNavigate,
7232
7258
  previousViews,
7259
+ focusedNodeId,
7233
7260
  lastClickedNodeId,
7234
7261
  lastClickedEdgeId,
7235
7262
  hoveredEdgeId,
@@ -7239,7 +7266,7 @@ function createDiagramStore(props) {
7239
7266
  DEV && console.debug("store: skip updateView");
7240
7267
  return;
7241
7268
  }
7242
- lastOnNavigate && lastOnNavigate.toView !== view.id && lastOnNavigate.fromView !== view.id && (lastOnNavigate = null), currentView.id === view.id ? (lastClickedNodeId && !containsWithId(view.nodes, lastClickedNodeId) && (lastClickedNodeId = null), hoveredNodeId && !containsWithId(view.nodes, hoveredNodeId) && (hoveredNodeId = null), lastClickedEdgeId && !containsWithId(view.edges, lastClickedEdgeId) && (lastClickedEdgeId = null), hoveredEdgeId && !containsWithId(view.edges, hoveredEdgeId) && (hoveredEdgeId = null)) : (lastClickedEdgeId = null, lastClickedNodeId = null, hoveredEdgeId = null, hoveredNodeId = null, previousViews = [
7269
+ lastOnNavigate && lastOnNavigate.toView !== view.id && lastOnNavigate.fromView !== view.id && (lastOnNavigate = null), currentView.id === view.id ? (lastClickedNodeId && !containsWithId(view.nodes, lastClickedNodeId) && (lastClickedNodeId = null), hoveredNodeId && !containsWithId(view.nodes, hoveredNodeId) && (hoveredNodeId = null), focusedNodeId && !containsWithId(view.nodes, focusedNodeId) && (focusedNodeId = null), lastClickedEdgeId && !containsWithId(view.edges, lastClickedEdgeId) && (lastClickedEdgeId = null), hoveredEdgeId && !containsWithId(view.edges, hoveredEdgeId) && (hoveredEdgeId = null)) : (lastClickedEdgeId = null, lastClickedNodeId = null, hoveredEdgeId = null, hoveredNodeId = null, focusedNodeId = null, previousViews = [
7243
7270
  currentView,
7244
7271
  ...previousViews.filter((v) => v.id !== view.id && v.id !== currentView.id)
7245
7272
  ]), set2(
@@ -7249,6 +7276,7 @@ function createDiagramStore(props) {
7249
7276
  previousViews,
7250
7277
  lastClickedNodeId,
7251
7278
  lastClickedEdgeId,
7279
+ focusedNodeId,
7252
7280
  hoveredEdgeId,
7253
7281
  hoveredNodeId
7254
7282
  },
@@ -7268,51 +7296,87 @@ function createDiagramStore(props) {
7268
7296
  setLastClickedEdge: (edgeId) => {
7269
7297
  edgeId !== get2().lastClickedEdgeId && set2({ lastClickedEdgeId: edgeId }, noReplace, edgeId ? "setLastClickedEdge" : "unsetLastClickedEdge");
7270
7298
  },
7299
+ resetLastClicked: () => {
7300
+ let {
7301
+ focusedNodeId,
7302
+ lastClickedNodeId,
7303
+ lastClickedEdgeId
7304
+ } = get2();
7305
+ (focusedNodeId || lastClickedNodeId || lastClickedEdgeId) && set2(
7306
+ {
7307
+ focusedNodeId: null,
7308
+ lastClickedNodeId: null,
7309
+ lastClickedEdgeId: null
7310
+ },
7311
+ noReplace,
7312
+ "resetLastClicked"
7313
+ );
7314
+ },
7271
7315
  getElement: (fqn) => {
7272
7316
  const { view } = get2();
7273
7317
  return view.nodes.find(({ id: id2 }) => id2 === fqn) ?? null;
7274
7318
  },
7275
7319
  triggerOnChange: (changes) => {
7276
7320
  var _a, _b;
7277
- const newShapes = /* @__PURE__ */ new Map(), newColor = /* @__PURE__ */ new Map();
7278
- for (const change2 of changes) {
7279
- if (change2.op === "change-shape") {
7280
- for (const target of change2.targets)
7281
- newShapes.set(target, change2.shape);
7282
- continue;
7283
- }
7284
- if (change2.op === "change-color") {
7285
- for (const target of change2.targets)
7286
- newColor.set(target, change2.color);
7287
- continue;
7288
- }
7289
- nonexhaustive(change2);
7321
+ DEV && console.debug("triggerOnChange", changes);
7322
+ const newShapes = /* @__PURE__ */ new Map(), newColor = /* @__PURE__ */ new Map(), newOpacity = /* @__PURE__ */ new Map(), newBorder = /* @__PURE__ */ new Map();
7323
+ for (const change of changes) {
7324
+ change.op !== "change-element-style" && nonexhaustive(change.op);
7325
+ for (const target of change.targets)
7326
+ for (const [key, value] of entries.strict(change.style))
7327
+ switch (key) {
7328
+ case "shape":
7329
+ newShapes.set(target, value);
7330
+ break;
7331
+ case "color":
7332
+ newColor.set(target, value);
7333
+ break;
7334
+ case "opacity":
7335
+ newOpacity.set(target, value);
7336
+ break;
7337
+ case "border":
7338
+ newBorder.set(target, value);
7339
+ break;
7340
+ default:
7341
+ nonexhaustive(key);
7342
+ }
7290
7343
  }
7291
7344
  get2().xyflow.setNodes(
7292
7345
  (nodes) => nodes.map((node) => {
7293
- let { data } = node;
7294
- const shape = newShapes.get(data.fqn);
7295
- shape && shape !== data.element.shape && (node = {
7296
- ...node,
7297
- data: {
7298
- ...data,
7299
- element: {
7300
- ...data.element,
7301
- shape
7302
- }
7346
+ var _a2, _b2;
7347
+ let element = node.data.element;
7348
+ const shape = newShapes.get(element.id);
7349
+ shape && shape !== element.shape && (element = {
7350
+ ...element,
7351
+ shape
7352
+ });
7353
+ const color2 = newColor.get(element.id);
7354
+ color2 && color2 !== element.color && (element = {
7355
+ ...element,
7356
+ color: color2
7357
+ });
7358
+ const opacity = newOpacity.get(element.id);
7359
+ opacity && opacity !== ((_a2 = element.style) == null ? void 0 : _a2.opacity) && (element = {
7360
+ ...element,
7361
+ style: {
7362
+ ...element.style,
7363
+ opacity
7303
7364
  }
7304
- }, data = node.data);
7305
- const color2 = newColor.get(data.fqn);
7306
- return color2 && color2 !== data.element.color && (node = {
7365
+ });
7366
+ const border = newBorder.get(element.id);
7367
+ return border && border !== ((_b2 = element.style) == null ? void 0 : _b2.border) && (element = {
7368
+ ...element,
7369
+ style: {
7370
+ ...element.style,
7371
+ border
7372
+ }
7373
+ }), element === node.data.element ? node : {
7307
7374
  ...node,
7308
7375
  data: {
7309
- ...data,
7310
- element: {
7311
- ...data.element,
7312
- color: color2
7313
- }
7376
+ ...node.data,
7377
+ element
7314
7378
  }
7315
- }), node;
7379
+ };
7316
7380
  })
7317
7381
  ), (_b = (_a = get2()).onChange) == null || _b.call(_a, { changes });
7318
7382
  },
@@ -7345,15 +7409,16 @@ function createDiagramStore(props) {
7345
7409
  xynode.internals.userNode
7346
7410
  );
7347
7411
  },
7348
- fitDiagram: () => {
7349
- const { fitViewPadding, xyflow } = get2();
7412
+ fitDiagram: (centerNode) => {
7413
+ const { fitViewPadding, xyflow, focusedNodeId } = get2();
7350
7414
  xyflow.fitView({
7351
7415
  includeHiddenNodes: !0,
7352
- duration: 400,
7416
+ duration: centerNode && focusedNodeId ? 300 : 400,
7353
7417
  padding: fitViewPadding,
7354
7418
  minZoom: MinZoom,
7355
- maxZoom: 1
7356
- });
7419
+ maxZoom: 1,
7420
+ ...centerNode && { nodes: [centerNode] }
7421
+ }), centerNode && focusedNodeId !== centerNode.id && set2({ focusedNodeId: centerNode.id }, noReplace, "focus node"), !centerNode && focusedNodeId && set2({ focusedNodeId: null }, noReplace, "unfocus");
7357
7422
  }
7358
7423
  }),
7359
7424
  {
@@ -7393,30 +7458,146 @@ function DiagramContextProvider({ children: children2, view, ...props }) {
7393
7458
  [props]
7394
7459
  ), /* @__PURE__ */ jsx(DiagramContext.Provider, { value: store.current, children: children2 });
7395
7460
  }
7396
- var wrapper = "_14qhjro0";
7397
- function KeepAspectRatio({
7398
- children: children2,
7399
- width,
7400
- height,
7401
- enabled,
7402
- className,
7403
- style: style2,
7404
- ...rest
7405
- }) {
7406
- return /* @__PURE__ */ jsx(
7407
- Box,
7461
+ var container$3 = "hbkbtj0", paper = "hbkbtj1", title$2 = "hbkbtj2", description$1 = "hbkbtj3";
7462
+ const selector$1 = (s) => ({
7463
+ id: s.view.id,
7464
+ title: s.view.title ?? "untitled",
7465
+ description: s.view.description,
7466
+ links: s.view.links
7467
+ });
7468
+ function DiagramTitlePanel() {
7469
+ const { id: id2, title: title2, description: description2, links } = useDiagramState(selector$1), [isCollapsed, setCollapsed] = useLocalStorage({
7470
+ key: "diagram-title-panel-collapsed",
7471
+ defaultValue: !1
7472
+ }), toggle = () => setCollapsed((v) => !v);
7473
+ return /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
7474
+ motion.div,
7408
7475
  {
7409
- ...rest,
7410
- className: clsx(wrapper, className),
7411
- style: enabled ? {
7412
- ...style2,
7413
- aspectRatio: `${Math.ceil(width)}/${Math.ceil(height)}`,
7414
- maxHeight: Math.ceil(height)
7415
- } : style2,
7416
- children: children2
7417
- }
7418
- );
7476
+ initial: { opacity: 0.05, scale: 0.7 },
7477
+ animate: { opacity: 1, scale: 1 },
7478
+ exit: {
7479
+ opacity: 0.05,
7480
+ scale: 0.6
7481
+ },
7482
+ className: clsx("react-flow__panel", container$3),
7483
+ style: {
7484
+ transformOrigin: "left center"
7485
+ },
7486
+ children: /* @__PURE__ */ jsx(
7487
+ Paper,
7488
+ {
7489
+ radius: "sm",
7490
+ withBorder: !isCollapsed,
7491
+ className: paper,
7492
+ p: isCollapsed ? "sm" : "md",
7493
+ onDoubleClick: (e) => e.stopPropagation(),
7494
+ children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", justify: "stretch", align: "stretch", children: [
7495
+ /* @__PURE__ */ jsxs(Group, { justify: "stretch", wrap: "nowrap", onClick: toggle, style: { cursor: "pointer" }, children: [
7496
+ /* @__PURE__ */ jsx(
7497
+ Text,
7498
+ {
7499
+ component: "div",
7500
+ flex: "1",
7501
+ size: isCollapsed ? "sm" : "lg",
7502
+ fw: 500,
7503
+ lh: 1.1,
7504
+ className: title$2,
7505
+ children: title2
7506
+ }
7507
+ ),
7508
+ /* @__PURE__ */ jsxs(
7509
+ Text,
7510
+ {
7511
+ hidden: isCollapsed,
7512
+ component: "div",
7513
+ flex: "0 0 auto",
7514
+ inline: !0,
7515
+ size: "xs",
7516
+ fz: 9,
7517
+ fw: 500,
7518
+ c: "dimmed",
7519
+ style: {
7520
+ userSelect: "all"
7521
+ },
7522
+ children: [
7523
+ /* @__PURE__ */ jsxs("span", { style: { userSelect: "none" }, children: [
7524
+ "id:",
7525
+ " "
7526
+ ] }),
7527
+ id2
7528
+ ]
7529
+ }
7530
+ )
7531
+ ] }),
7532
+ !isCollapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
7533
+ description2 && /* @__PURE__ */ jsx(
7534
+ Spoiler,
7535
+ {
7536
+ maxHeight: 42,
7537
+ showLabel: /* @__PURE__ */ jsx(Button, { color: "gray", variant: "light", fz: "10", size: "compact-xs", children: "show more" }),
7538
+ hideLabel: /* @__PURE__ */ jsx(Button, { color: "gray", variant: "light", fz: "10", size: "compact-xs", children: "hide" }),
7539
+ children: /* @__PURE__ */ jsx(
7540
+ Text,
7541
+ {
7542
+ component: "div",
7543
+ size: "sm",
7544
+ className: description$1,
7545
+ children: description2 || "no description"
7546
+ }
7547
+ )
7548
+ }
7549
+ ),
7550
+ !description2 && /* @__PURE__ */ jsx(
7551
+ Text,
7552
+ {
7553
+ component: "div",
7554
+ size: "xs",
7555
+ c: "dimmed",
7556
+ children: "no description"
7557
+ }
7558
+ ),
7559
+ links && /* @__PURE__ */ jsx(
7560
+ Stack,
7561
+ {
7562
+ gap: 3,
7563
+ justify: "stretch",
7564
+ align: "stretch",
7565
+ children: links.map((link) => /* @__PURE__ */ jsxs(Group, { wrap: "nowrap", align: "center", gap: "sm", children: [
7566
+ /* @__PURE__ */ jsx(Box, { flex: "1", style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx(
7567
+ Anchor,
7568
+ {
7569
+ href: link,
7570
+ target: "_blank",
7571
+ fz: "xs",
7572
+ truncate: "end",
7573
+ display: "inline-block",
7574
+ w: "100%",
7575
+ children: link
7576
+ }
7577
+ ) }),
7578
+ /* @__PURE__ */ jsx(CopyButton, { value: link, children: ({ copied, copy }) => /* @__PURE__ */ jsx(
7579
+ Button,
7580
+ {
7581
+ size: "compact-xs",
7582
+ fz: "10",
7583
+ variant: "light",
7584
+ onClick: copy,
7585
+ color: copied ? "teal" : "gray",
7586
+ children: copied ? "copied" : "copy"
7587
+ }
7588
+ ) })
7589
+ ] }, link))
7590
+ }
7591
+ )
7592
+ ] })
7593
+ ] })
7594
+ }
7595
+ )
7596
+ },
7597
+ id2
7598
+ ) });
7419
7599
  }
7600
+ var panel = "_1lmzt1h0";
7420
7601
  const {
7421
7602
  primary,
7422
7603
  secondary,
@@ -7434,7 +7615,16 @@ function NodeOptions({ selectedNodeIds }) {
7434
7615
  const diagramApi = useDiagramStoreApi(), nodes = useXYNodesData(selectedNodeIds);
7435
7616
  if (!hasAtLeast(nodes, 1))
7436
7617
  return null;
7437
- const showShapeOption = nodes.some((node) => node.type === "element"), [firstNode, ...rest] = nodes;
7618
+ if (nodes.length !== selectedNodeIds.length)
7619
+ throw new Error("NodeOptions: nodes and props.nodes should have the same length");
7620
+ const showShapeOption = nodes.some((node) => node.type === "element"), [firstNode, ...rest] = nodes, showOpacityOption = rest.length === 0 && firstNode.type === "compound", triggerChange = (style2) => {
7621
+ const targets = nodes.map((node) => node.data.element.id);
7622
+ invariant(hasAtLeast(targets, 1), "At least one target is required"), diagramApi.getState().triggerOnChange([{
7623
+ op: "change-element-style",
7624
+ style: style2,
7625
+ targets
7626
+ }]);
7627
+ };
7438
7628
  return /* @__PURE__ */ jsxs(Stack, { children: [
7439
7629
  /* @__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 ]" }) }),
7440
7630
  showShapeOption && /* @__PURE__ */ jsx(
@@ -7442,14 +7632,7 @@ function NodeOptions({ selectedNodeIds }) {
7442
7632
  {
7443
7633
  nodes,
7444
7634
  onShapeChange: (shape) => {
7445
- const targets = [];
7446
- for (const nd of nodes)
7447
- nd.data.element.shape !== shape && targets.push(nd.data.element.id);
7448
- hasAtLeast(targets, 1) && diagramApi.getState().triggerOnChange([{
7449
- op: "change-shape",
7450
- shape,
7451
- targets
7452
- }]);
7635
+ triggerChange({ shape });
7453
7636
  }
7454
7637
  }
7455
7638
  ),
@@ -7458,18 +7641,32 @@ function NodeOptions({ selectedNodeIds }) {
7458
7641
  {
7459
7642
  nodes,
7460
7643
  onColorChange: (color2) => {
7461
- const targets = [];
7462
- for (const nd of nodes)
7463
- nd.data.element.color !== color2 && targets.push(nd.data.element.id);
7464
- hasAtLeast(targets, 1) && diagramApi.getState().triggerOnChange([{
7465
- op: "change-color",
7466
- color: color2,
7467
- targets
7468
- }]);
7644
+ triggerChange({ color: color2 });
7469
7645
  }
7470
7646
  }
7471
7647
  ),
7472
- /* @__PURE__ */ jsx(NavigateToOption, { nodes })
7648
+ /* @__PURE__ */ jsx(NavigateToOption, { nodes }),
7649
+ /* @__PURE__ */ jsx(Box, { children: showOpacityOption && /* @__PURE__ */ jsxs(Fragment, { children: [
7650
+ /* @__PURE__ */ jsx(Divider, { label: "opacity and border", labelPosition: "left" }),
7651
+ /* @__PURE__ */ jsx(
7652
+ OpacityOption,
7653
+ {
7654
+ node: firstNode,
7655
+ onOpacityChange: (opacity) => {
7656
+ triggerChange({ opacity });
7657
+ }
7658
+ }
7659
+ ),
7660
+ /* @__PURE__ */ jsx(
7661
+ BorderStyleOption,
7662
+ {
7663
+ node: firstNode,
7664
+ onChange: (border) => {
7665
+ triggerChange({ border });
7666
+ }
7667
+ }
7668
+ )
7669
+ ] }) }, firstNode.id)
7473
7670
  ] });
7474
7671
  }
7475
7672
  function Colors({
@@ -7575,8 +7772,54 @@ function NavigateToOption({
7575
7772
  )
7576
7773
  ] });
7577
7774
  }
7578
- var panel = "_1lmzt1h0";
7579
- const OptionsPanelMemo = /* @__PURE__ */ memo(function() {
7775
+ function OpacityOption({
7776
+ node,
7777
+ onOpacityChange
7778
+ }) {
7779
+ let selectedOpacity = node.data.element.style.opacity ?? 100;
7780
+ const [value, setValue] = useState(selectedOpacity);
7781
+ return useEffect(() => {
7782
+ setValue(selectedOpacity);
7783
+ }, [selectedOpacity]), /* @__PURE__ */ jsx(
7784
+ Slider,
7785
+ {
7786
+ mt: "xs",
7787
+ size: "sm",
7788
+ color: "dark",
7789
+ value,
7790
+ onChange: setValue,
7791
+ onChangeEnd: onOpacityChange
7792
+ }
7793
+ );
7794
+ }
7795
+ function BorderStyleOption({
7796
+ node,
7797
+ onChange
7798
+ }) {
7799
+ let selecteBorderStyle = node.data.element.style.border ?? "dashed";
7800
+ const [value, setValue] = useState(selecteBorderStyle);
7801
+ return useEffect(() => {
7802
+ setValue(selecteBorderStyle);
7803
+ }, [selecteBorderStyle]), /* @__PURE__ */ jsx(Box, { mt: "md", children: /* @__PURE__ */ jsx(
7804
+ SegmentedControl,
7805
+ {
7806
+ size: "xs",
7807
+ fullWidth: !0,
7808
+ withItemsBorders: !1,
7809
+ value,
7810
+ onChange: (v) => {
7811
+ setValue(v), onChange(v);
7812
+ },
7813
+ data: [
7814
+ { label: "Solid", value: "solid" },
7815
+ { label: "Dashed", value: "dashed" },
7816
+ { label: "Dotted", value: "dotted" },
7817
+ { label: "None", value: "none" }
7818
+ ]
7819
+ }
7820
+ ) });
7821
+ }
7822
+ function OptionsPanel() {
7580
7823
  const [selectedNodes, setSelectedNodes] = useState([]);
7581
7824
  return useOnSelectionChange({
7582
7825
  onChange: ({ nodes }) => {
@@ -7600,7 +7843,7 @@ const OptionsPanelMemo = /* @__PURE__ */ memo(function() {
7600
7843
  children: /* @__PURE__ */ jsx(Card, { shadow: "sm", children: /* @__PURE__ */ jsx(NodeOptions, { selectedNodeIds: selectedNodes }) })
7601
7844
  }
7602
7845
  ) });
7603
- }), OptionsPanel2 = OptionsPanelMemo;
7846
+ }
7604
7847
  function deriveEdgePoints(bezierSpline) {
7605
7848
  let [start2, ...bezierPoints] = bezierSpline;
7606
7849
  invariant(start2, "start should be defined");
@@ -7660,10 +7903,10 @@ function diagramViewToXYFlowData(view, opts) {
7660
7903
  initialHeight: node.height, */
7661
7904
  width: node.width,
7662
7905
  height: node.height,
7663
- measured: {
7664
- width: node.width,
7665
- height: node.height
7666
- },
7906
+ // measured: {
7907
+ // width: node.width,
7908
+ // height: node.height
7909
+ // },
7667
7910
  ...parent && {
7668
7911
  parentId: ns + parent.id
7669
7912
  }
@@ -7735,28 +7978,32 @@ function FitViewOnViewportResize({ diagramApi }) {
7735
7978
  }
7736
7979
  const diagramChangeId = (s) => s.view.id + "_" + s.view.autoLayout + "_" + s.fitViewPadding;
7737
7980
  function FitViewOnDiagramChanges() {
7738
- const diagramApi = useDiagramStoreApi(), [viewportMoved, setViewportMoved] = useState(diagramApi.getState().viewportChanged), [processedChangeId, setProcessed] = useState(diagramChangeId(diagramApi.getState())), [pendingChangeId, setPending] = useDebouncedState(processedChangeId, 100), isReady = useNodesInitialized({
7981
+ const diagramApi = useDiagramStoreApi(), [viewportMoved, setViewportMoved] = useState(diagramApi.getState().viewportChanged), [processedChangeId, setProcessed] = useState(diagramChangeId(diagramApi.getState())), [pendingChangeId, setPending] = useState(processedChangeId), isReady = useNodesInitialized({
7739
7982
  includeHiddenNodes: !0
7740
- });
7983
+ }), schedulePending = useDebouncedCallback(
7984
+ (pendingChangeId2) => {
7985
+ setPending(pendingChangeId2);
7986
+ },
7987
+ [setPending],
7988
+ 75
7989
+ );
7741
7990
  return useEffect(
7742
7991
  () => diagramApi.subscribe(
7743
- (s) => ({
7744
- viewportMoved: s.viewportChanged,
7745
- changeid: diagramChangeId(s)
7746
- }),
7747
- ({ viewportMoved: viewportMoved2, changeid }) => {
7748
- setPending(changeid), setViewportMoved(viewportMoved2);
7749
- },
7750
- {
7751
- equalityFn: shallowEqual
7752
- }
7992
+ (s) => diagramChangeId(s),
7993
+ schedulePending
7753
7994
  ),
7754
- [diagramApi]
7995
+ [diagramApi, schedulePending]
7996
+ ), useEffect(
7997
+ () => diagramApi.subscribe(
7998
+ (s) => s.viewportChanged,
7999
+ setViewportMoved
8000
+ ),
8001
+ [diagramApi, setViewportMoved]
7755
8002
  ), useRafEffect(
7756
8003
  () => {
7757
8004
  !isReady || processedChangeId === pendingChangeId || (diagramApi.getState().fitDiagram(), setProcessed(pendingChangeId));
7758
8005
  },
7759
- [isReady, processedChangeId, pendingChangeId]
8006
+ [isReady, processedChangeId, pendingChangeId, diagramApi]
7760
8007
  ), !viewportMoved && isReady ? /* @__PURE__ */ jsx(FitViewOnViewportResize, { diagramApi }) : null;
7761
8008
  }
7762
8009
  const selectFitViewFlag = (s) => s.fitViewEnabled, FitViewOnDiagramChange = memo(() => useDiagramState(selectFitViewFlag) ? /* @__PURE__ */ jsx(FitViewOnDiagramChanges, {}) : null);
@@ -7772,13 +8019,19 @@ const isSameNode = (a) => (b) => a.id === b.id && a.type === b.type && Object.is
7772
8019
  (state) => ({
7773
8020
  viewId: state.view.id,
7774
8021
  nodes: state.view.nodes,
7775
- edges: state.view.edges,
7776
- draggable: state.nodesDraggable,
7777
- selectable: state.nodesSelectable
8022
+ edges: state.view.edges
7778
8023
  }),
7779
8024
  // listener
7780
- ({ viewId, nodes, edges, ...opts }) => {
7781
- const { lastOnNavigate } = diagramStoreApi.getState(), updates = diagramViewToXYFlowData({ nodes, edges }, opts);
8025
+ ({ viewId, nodes, edges }) => {
8026
+ const {
8027
+ lastOnNavigate,
8028
+ nodesDraggable,
8029
+ nodesSelectable,
8030
+ focusedNodeId
8031
+ } = diagramStoreApi.getState(), updates = diagramViewToXYFlowData({ nodes, edges }, {
8032
+ draggable: nodesDraggable,
8033
+ selectable: nodesSelectable || focusedNodeId !== null
8034
+ });
7782
8035
  if (xyflowRef.current.setNodes(
7783
8036
  (prev) => updates.nodes.map((update) => {
7784
8037
  const existing = prev.find(isSameNode(update));
@@ -7795,25 +8048,28 @@ const isSameNode = (a) => (b) => a.id === b.id && a.type === b.type && Object.is
7795
8048
  ...update
7796
8049
  } : update;
7797
8050
  })
7798
- ), (lastOnNavigate == null ? void 0 : lastOnNavigate.toView) === viewId && !lastOnNavigate.positionCorrected) {
8051
+ ), (lastOnNavigate == null ? void 0 : lastOnNavigate.toView) === viewId && lastOnNavigate.positionCorrected !== !0) {
7799
8052
  const elFrom = lastOnNavigate.element, elTo = nodes.find((n) => n.id === elFrom.id);
7800
8053
  if (elTo) {
7801
- const centerFrom = lastOnNavigate.elementCenterScreenPosition, nextZoom = Math.min(elFrom.width / elTo.width, elFrom.height / elTo.height);
8054
+ const centerFrom = lastOnNavigate.elementCenterScreenPosition;
8055
+ let nextZoom = Math.min(elFrom.width / elTo.width, elFrom.height / elTo.height);
7802
8056
  requestAnimationFrame(() => {
7803
- const v = xyflowRef.current.getViewport();
7804
- nextZoom < v.zoom && xyflowRef.current.setViewport({
7805
- x: v.x,
7806
- y: v.y,
7807
- zoom: nextZoom
8057
+ requestAnimationFrame(() => {
8058
+ const v = xyflowRef.current.getViewport();
8059
+ nextZoom < v.zoom && (nextZoom = Math.max(nextZoom, v.zoom * 0.5), xyflowRef.current.setViewport({
8060
+ x: v.x,
8061
+ y: v.y,
8062
+ zoom: nextZoom
8063
+ }));
8064
+ const centerTo = xyflowRef.current.flowToScreenPosition({
8065
+ x: elTo.position[0] + elTo.width / 2,
8066
+ y: elTo.position[1] + elTo.height / 2
8067
+ }), diff = {
8068
+ x: toDomPrecision(centerFrom.x - centerTo.x),
8069
+ y: toDomPrecision(centerFrom.y - centerTo.y)
8070
+ };
8071
+ xyflowApi.getState().panBy(diff);
7808
8072
  });
7809
- const centerTo = xyflowRef.current.flowToScreenPosition({
7810
- x: elTo.position[0] + elTo.width / 2,
7811
- y: elTo.position[1] + elTo.height / 2
7812
- }), diff = {
7813
- x: toDomPrecision(centerFrom.x - centerTo.x),
7814
- y: toDomPrecision(centerFrom.y - centerTo.y)
7815
- };
7816
- xyflowApi.getState().panBy(diff);
7817
8073
  });
7818
8074
  }
7819
8075
  diagramStoreApi.setState(
@@ -7878,7 +8134,7 @@ function assignInlineVars(varsOrContract, tokens) {
7878
8134
  writable: !1
7879
8135
  }), styles;
7880
8136
  }
7881
- var container$1 = "bexn7q0", edgePathBg = "bexn7q1", fillStrokeCtx = "bexn7q2", cssEdgePath = "bexn7q3", varLabelX = "var(--bexn7q4)", varLabelY = "var(--bexn7q5)", edgeLabel = "bexn7q7", edgeLabelBody = "bexn7q8";
8137
+ var container$2 = "bexn7q1", edgePathBg = "bexn7q2", fillStrokeCtx = "bexn7q3", cssEdgePath = "bexn7q6", varLabelX = "var(--bexn7q7)", varLabelY = "var(--bexn7q8)", edgeLabel = "bexn7qa", edgeLabelBody = "bexn7qb";
7882
8138
  function getNodeIntersection(intersectionNode, targetNode) {
7883
8139
  const {
7884
8140
  width: intersectionNodeWidth,
@@ -7940,28 +8196,23 @@ function bezierPath(bezierSpline) {
7940
8196
  }
7941
8197
  return invariant(points.length === 0, "all points should be consumed"), path;
7942
8198
  }
7943
- const isSamePoint = (a, b) => Math.abs(a - b) < 2.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 && isSamePoint(prev.sourceX, next.sourceX) && isSamePoint(prev.sourceY, next.sourceY) && isSamePoint(prev.targetX, next.targetX) && isSamePoint(prev.targetY, next.targetY) && deepEqual(prev.data, next.data), RelationshipEdge = /* @__PURE__ */ memo(function({
8199
+ const isSamePoint = (a, b) => Math.abs(a - b) < 2.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, next.data), curve = line().curve(curveCatmullRomOpen.alpha(1)), RelationshipEdge = /* @__PURE__ */ memo(function({
7944
8200
  id: id2,
7945
8201
  data,
7946
8202
  selected: _selected,
7947
- markerEnd: _markerEnd,
7948
8203
  style: style2,
7949
8204
  source,
7950
8205
  target,
7951
8206
  interactionWidth
7952
8207
  }) {
7953
8208
  var _a, _b, _c;
7954
- 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`), isNotModified = isSamePosition(sourceNode.internals.positionAbsolute, sourceNode.data.element.position) && isSamePosition(targetNode.internals.positionAbsolute, targetNode.data.element.position);
7955
- invariant(data, "data is required");
7956
- const {
7957
- edge
7958
- } = data, color2 = edge.color ?? "gray", isHovered = useDiagramState((s) => s.hoveredEdgeId === id2), line = edge.line ?? "dashed", isDotted = line === "dotted", isDashed = isDotted || line === "dashed";
8209
+ 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`), isNotModified = isSamePosition(sourceNode.internals.positionAbsolute, sourceNode.data.element.position) && isSamePosition(targetNode.internals.positionAbsolute, targetNode.data.element.position), { edge: diagramEdge, controlPoints } = data, color2 = diagramEdge.color ?? "gray", isHovered = useDiagramState((s) => s.hoveredEdgeId === id2), line2 = diagramEdge.line ?? "dashed", isDotted = line2 === "dotted", isDashed = isDotted || line2 === "dashed";
7959
8210
  let strokeDasharray;
7960
8211
  isDotted ? strokeDasharray = "1,8" : isDashed && (strokeDasharray = "8,10");
7961
8212
  const marker = `url(#arrow-${id2})`;
7962
8213
  let edgePath, labelX, labelY;
7963
8214
  if (isNotModified)
7964
- edgePath = bezierPath(edge.points), labelX = ((_a = data.label) == null ? void 0 : _a.bbox.x) ?? 0, labelY = ((_b = data.label) == null ? void 0 : _b.bbox.y) ?? 0;
8215
+ 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;
7965
8216
  else {
7966
8217
  const { sx, sy, tx, ty, sourcePos, targetPos } = getEdgeParams(sourceNode, targetNode), [_edgePath, _labelX, _labelY] = getBezierPath({
7967
8218
  sourceX: sx,
@@ -7972,8 +8223,16 @@ const isSamePoint = (a, b) => Math.abs(a - b) < 2.1, isSamePosition = (a, [bx, b
7972
8223
  targetY: ty
7973
8224
  });
7974
8225
  edgePath = _edgePath, labelX = _labelX, labelY = _labelY;
8226
+ const sourceCenterPos = getNodePositionWithOrigin(sourceNode, [-0.5, -0.5]), targetCenterPos = getNodePositionWithOrigin(targetNode, [-0.5, -0.5]);
8227
+ edgePath = curve([
8228
+ [sourceCenterPos.positionAbsolute.x, sourceCenterPos.positionAbsolute.y],
8229
+ [sx, sy],
8230
+ ...controlPoints,
8231
+ [tx, ty],
8232
+ [targetCenterPos.positionAbsolute.x, targetCenterPos.positionAbsolute.y]
8233
+ ]);
7975
8234
  }
7976
- return /* @__PURE__ */ jsxs("g", { className: clsx(container$1), "data-likec4-color": color2, "data-edge-hovered": isHovered, children: [
8235
+ return /* @__PURE__ */ jsxs("g", { className: clsx(container$2), "data-likec4-color": color2, "data-edge-hovered": isHovered, children: [
7977
8236
  /* @__PURE__ */ jsx("g", { className: clsx(fillStrokeCtx), children: /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
7978
8237
  "marker",
7979
8238
  {
@@ -7995,15 +8254,15 @@ const isSamePoint = (a, b) => Math.abs(a - b) < 2.1, isSamePosition = (a, [bx, b
7995
8254
  edgePath,
7996
8255
  interactionWidth: interactionWidth ?? 10,
7997
8256
  strokeDasharray,
7998
- markerStart: edge.tailArrow ? marker : void 0,
7999
- markerEnd: edge.headArrow ? marker : void 0,
8257
+ markerStart: diagramEdge.tailArrow ? marker : void 0,
8258
+ markerEnd: diagramEdge.headArrow ? marker : void 0,
8000
8259
  style: style2
8001
8260
  }
8002
8261
  ),
8003
8262
  data.label && /* @__PURE__ */ jsx(EdgeLabelRenderer, { children: /* @__PURE__ */ jsx(
8004
8263
  Box,
8005
8264
  {
8006
- className: clsx(container$1, edgeLabel),
8265
+ className: clsx(container$2, edgeLabel),
8007
8266
  "data-likec4-color": color2,
8008
8267
  style: {
8009
8268
  ...assignInlineVars({
@@ -8020,7 +8279,7 @@ const isSamePoint = (a, b) => Math.abs(a - b) < 2.1, isSamePosition = (a, [bx, b
8020
8279
  }
8021
8280
  ) })
8022
8281
  ] });
8023
- }, isEqualProps), RelationshipPath = memo(({
8282
+ }, isEqualProps), RelationshipPath = ({
8024
8283
  edgePath,
8025
8284
  interactionWidth,
8026
8285
  strokeDasharray,
@@ -8059,475 +8318,7 @@ const isSamePoint = (a, b) => Math.abs(a - b) < 2.1, isSamePosition = (a, [bx, b
8059
8318
  strokeWidth: interactionWidth
8060
8319
  }
8061
8320
  )
8062
- ] })), Channel = {
8063
- /* CLAMP */
8064
- min: {
8065
- r: 0,
8066
- g: 0,
8067
- b: 0,
8068
- s: 0,
8069
- l: 0,
8070
- a: 0
8071
- },
8072
- max: {
8073
- r: 255,
8074
- g: 255,
8075
- b: 255,
8076
- h: 360,
8077
- s: 100,
8078
- l: 100,
8079
- a: 1
8080
- },
8081
- clamp: {
8082
- r: (r2) => r2 >= 255 ? 255 : r2 < 0 ? 0 : r2,
8083
- g: (g) => g >= 255 ? 255 : g < 0 ? 0 : g,
8084
- b: (b) => b >= 255 ? 255 : b < 0 ? 0 : b,
8085
- h: (h) => h % 360,
8086
- s: (s) => s >= 100 ? 100 : s < 0 ? 0 : s,
8087
- l: (l) => l >= 100 ? 100 : l < 0 ? 0 : l,
8088
- a: (a) => a >= 1 ? 1 : a < 0 ? 0 : a
8089
- },
8090
- /* CONVERSION */
8091
- //SOURCE: https://planetcalc.com/7779
8092
- toLinear: (c) => {
8093
- const n = c / 255;
8094
- return c > 0.03928 ? Math.pow((n + 0.055) / 1.055, 2.4) : n / 12.92;
8095
- },
8096
- //SOURCE: https://gist.github.com/mjackson/5311256
8097
- hue2rgb: (p, q, t) => (t < 0 && (t += 1), t > 1 && (t -= 1), t < 1 / 6 ? p + (q - p) * 6 * t : t < 1 / 2 ? q : t < 2 / 3 ? p + (q - p) * (2 / 3 - t) * 6 : p),
8098
- hsl2rgb: ({ h, s, l }, channel) => {
8099
- if (!s)
8100
- return l * 2.55;
8101
- h /= 360, s /= 100, l /= 100;
8102
- const q = l < 0.5 ? l * (1 + s) : l + s - l * s, p = 2 * l - q;
8103
- switch (channel) {
8104
- case "r":
8105
- return Channel.hue2rgb(p, q, h + 1 / 3) * 255;
8106
- case "g":
8107
- return Channel.hue2rgb(p, q, h) * 255;
8108
- case "b":
8109
- return Channel.hue2rgb(p, q, h - 1 / 3) * 255;
8110
- }
8111
- },
8112
- rgb2hsl: ({ r: r2, g, b }, channel) => {
8113
- r2 /= 255, g /= 255, b /= 255;
8114
- const max = Math.max(r2, g, b), min = Math.min(r2, g, b), l = (max + min) / 2;
8115
- if (channel === "l")
8116
- return l * 100;
8117
- if (max === min)
8118
- return 0;
8119
- const d = max - min, s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
8120
- if (channel === "s")
8121
- return s * 100;
8122
- switch (max) {
8123
- case r2:
8124
- return ((g - b) / d + (g < b ? 6 : 0)) * 60;
8125
- case g:
8126
- return ((b - r2) / d + 2) * 60;
8127
- case b:
8128
- return ((r2 - g) / d + 4) * 60;
8129
- default:
8130
- return -1;
8131
- }
8132
- }
8133
- }, Lang = {
8134
- /* API */
8135
- clamp: (number, lower2, upper) => lower2 > upper ? Math.min(lower2, Math.max(upper, number)) : Math.min(upper, Math.max(lower2, number)),
8136
- round: (number) => Math.round(number * 1e10) / 1e10
8137
- }, lang = Lang, Unit = {
8138
- /* API */
8139
- dec2hex: (dec) => {
8140
- const hex2 = Math.round(dec).toString(16);
8141
- return hex2.length > 1 ? hex2 : `0${hex2}`;
8142
- }
8143
- }, unit = Unit, Utils = {
8144
- channel: Channel,
8145
- lang,
8146
- unit
8147
- }, DEC2HEX = {};
8148
- for (let i = 0; i <= 255; i++)
8149
- DEC2HEX[i] = Utils.unit.dec2hex(i);
8150
- const TYPE = {
8151
- ALL: 0,
8152
- RGB: 1,
8153
- HSL: 2
8154
- };
8155
- class Type {
8156
- constructor() {
8157
- this.type = TYPE.ALL;
8158
- }
8159
- /* API */
8160
- get() {
8161
- return this.type;
8162
- }
8163
- set(type) {
8164
- if (this.type && this.type !== type)
8165
- throw new Error("Cannot change both RGB and HSL channels at the same time");
8166
- this.type = type;
8167
- }
8168
- reset() {
8169
- this.type = TYPE.ALL;
8170
- }
8171
- is(type) {
8172
- return this.type === type;
8173
- }
8174
- }
8175
- class Channels {
8176
- /* CONSTRUCTOR */
8177
- constructor(data, color2) {
8178
- this.color = color2, this.changed = !1, this.data = data, this.type = new Type();
8179
- }
8180
- /* API */
8181
- set(data, color2) {
8182
- return this.color = color2, this.changed = !1, this.data = data, this.type.type = TYPE.ALL, this;
8183
- }
8184
- /* HELPERS */
8185
- _ensureHSL() {
8186
- const data = this.data, { h, s, l } = data;
8187
- h === void 0 && (data.h = Utils.channel.rgb2hsl(data, "h")), s === void 0 && (data.s = Utils.channel.rgb2hsl(data, "s")), l === void 0 && (data.l = Utils.channel.rgb2hsl(data, "l"));
8188
- }
8189
- _ensureRGB() {
8190
- const data = this.data, { r: r2, g, b } = data;
8191
- r2 === void 0 && (data.r = Utils.channel.hsl2rgb(data, "r")), g === void 0 && (data.g = Utils.channel.hsl2rgb(data, "g")), b === void 0 && (data.b = Utils.channel.hsl2rgb(data, "b"));
8192
- }
8193
- /* GETTERS */
8194
- get r() {
8195
- const data = this.data, r2 = data.r;
8196
- return !this.type.is(TYPE.HSL) && r2 !== void 0 ? r2 : (this._ensureHSL(), Utils.channel.hsl2rgb(data, "r"));
8197
- }
8198
- get g() {
8199
- const data = this.data, g = data.g;
8200
- return !this.type.is(TYPE.HSL) && g !== void 0 ? g : (this._ensureHSL(), Utils.channel.hsl2rgb(data, "g"));
8201
- }
8202
- get b() {
8203
- const data = this.data, b = data.b;
8204
- return !this.type.is(TYPE.HSL) && b !== void 0 ? b : (this._ensureHSL(), Utils.channel.hsl2rgb(data, "b"));
8205
- }
8206
- get h() {
8207
- const data = this.data, h = data.h;
8208
- return !this.type.is(TYPE.RGB) && h !== void 0 ? h : (this._ensureRGB(), Utils.channel.rgb2hsl(data, "h"));
8209
- }
8210
- get s() {
8211
- const data = this.data, s = data.s;
8212
- return !this.type.is(TYPE.RGB) && s !== void 0 ? s : (this._ensureRGB(), Utils.channel.rgb2hsl(data, "s"));
8213
- }
8214
- get l() {
8215
- const data = this.data, l = data.l;
8216
- return !this.type.is(TYPE.RGB) && l !== void 0 ? l : (this._ensureRGB(), Utils.channel.rgb2hsl(data, "l"));
8217
- }
8218
- get a() {
8219
- return this.data.a;
8220
- }
8221
- /* SETTERS */
8222
- set r(r2) {
8223
- this.type.set(TYPE.RGB), this.changed = !0, this.data.r = r2;
8224
- }
8225
- set g(g) {
8226
- this.type.set(TYPE.RGB), this.changed = !0, this.data.g = g;
8227
- }
8228
- set b(b) {
8229
- this.type.set(TYPE.RGB), this.changed = !0, this.data.b = b;
8230
- }
8231
- set h(h) {
8232
- this.type.set(TYPE.HSL), this.changed = !0, this.data.h = h;
8233
- }
8234
- set s(s) {
8235
- this.type.set(TYPE.HSL), this.changed = !0, this.data.s = s;
8236
- }
8237
- set l(l) {
8238
- this.type.set(TYPE.HSL), this.changed = !0, this.data.l = l;
8239
- }
8240
- set a(a) {
8241
- this.changed = !0, this.data.a = a;
8242
- }
8243
- }
8244
- const Channels$1 = Channels, channels = new Channels$1({ r: 0, g: 0, b: 0, a: 0 }, "transparent"), Hex = {
8245
- /* VARIABLES */
8246
- re: /^#((?:[a-f0-9]{2}){2,4}|[a-f0-9]{3})$/i,
8247
- /* API */
8248
- parse: (color2) => {
8249
- if (color2.charCodeAt(0) !== 35)
8250
- return;
8251
- const match = color2.match(Hex.re);
8252
- if (!match)
8253
- return;
8254
- const hex2 = match[1], dec = parseInt(hex2, 16), length = hex2.length, hasAlpha = length % 4 === 0, isFullLength = length > 4, multiplier = isFullLength ? 1 : 17, bits = isFullLength ? 8 : 4, bitsOffset = hasAlpha ? 0 : -1, mask = isFullLength ? 255 : 15;
8255
- return channels.set({
8256
- r: (dec >> bits * (bitsOffset + 3) & mask) * multiplier,
8257
- g: (dec >> bits * (bitsOffset + 2) & mask) * multiplier,
8258
- b: (dec >> bits * (bitsOffset + 1) & mask) * multiplier,
8259
- a: hasAlpha ? (dec & mask) * multiplier / 255 : 1
8260
- }, color2);
8261
- },
8262
- stringify: (channels2) => {
8263
- const { r: r2, g, b, a } = channels2;
8264
- return a < 1 ? `#${DEC2HEX[Math.round(r2)]}${DEC2HEX[Math.round(g)]}${DEC2HEX[Math.round(b)]}${DEC2HEX[Math.round(a * 255)]}` : `#${DEC2HEX[Math.round(r2)]}${DEC2HEX[Math.round(g)]}${DEC2HEX[Math.round(b)]}`;
8265
- }
8266
- }, HSL = {
8267
- /* VARIABLES */
8268
- re: /^hsla?\(\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?(?:deg|grad|rad|turn)?)\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?%)\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?%)(?:\s*?(?:,|\/)\s*?\+?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?(%)?))?\s*?\)$/i,
8269
- hueRe: /^(.+?)(deg|grad|rad|turn)$/i,
8270
- /* HELPERS */
8271
- _hue2deg: (hue) => {
8272
- const match = hue.match(HSL.hueRe);
8273
- if (match) {
8274
- const [, number, unit2] = match;
8275
- switch (unit2) {
8276
- case "grad":
8277
- return Utils.channel.clamp.h(parseFloat(number) * 0.9);
8278
- case "rad":
8279
- return Utils.channel.clamp.h(parseFloat(number) * 180 / Math.PI);
8280
- case "turn":
8281
- return Utils.channel.clamp.h(parseFloat(number) * 360);
8282
- }
8283
- }
8284
- return Utils.channel.clamp.h(parseFloat(hue));
8285
- },
8286
- /* API */
8287
- parse: (color2) => {
8288
- const charCode = color2.charCodeAt(0);
8289
- if (charCode !== 104 && charCode !== 72)
8290
- return;
8291
- const match = color2.match(HSL.re);
8292
- if (!match)
8293
- return;
8294
- const [, h, s, l, a, isAlphaPercentage] = match;
8295
- return channels.set({
8296
- h: HSL._hue2deg(h),
8297
- s: Utils.channel.clamp.s(parseFloat(s)),
8298
- l: Utils.channel.clamp.l(parseFloat(l)),
8299
- a: a ? Utils.channel.clamp.a(isAlphaPercentage ? parseFloat(a) / 100 : parseFloat(a)) : 1
8300
- }, color2);
8301
- },
8302
- stringify: (channels2) => {
8303
- const { h, s, l, a } = channels2;
8304
- return a < 1 ? `hsla(${Utils.lang.round(h)}, ${Utils.lang.round(s)}%, ${Utils.lang.round(l)}%, ${a})` : `hsl(${Utils.lang.round(h)}, ${Utils.lang.round(s)}%, ${Utils.lang.round(l)}%)`;
8305
- }
8306
- }, Keyword = {
8307
- /* VARIABLES */
8308
- colors: {
8309
- aliceblue: "#f0f8ff",
8310
- antiquewhite: "#faebd7",
8311
- aqua: "#00ffff",
8312
- aquamarine: "#7fffd4",
8313
- azure: "#f0ffff",
8314
- beige: "#f5f5dc",
8315
- bisque: "#ffe4c4",
8316
- black: "#000000",
8317
- blanchedalmond: "#ffebcd",
8318
- blue: "#0000ff",
8319
- blueviolet: "#8a2be2",
8320
- brown: "#a52a2a",
8321
- burlywood: "#deb887",
8322
- cadetblue: "#5f9ea0",
8323
- chartreuse: "#7fff00",
8324
- chocolate: "#d2691e",
8325
- coral: "#ff7f50",
8326
- cornflowerblue: "#6495ed",
8327
- cornsilk: "#fff8dc",
8328
- crimson: "#dc143c",
8329
- cyanaqua: "#00ffff",
8330
- darkblue: "#00008b",
8331
- darkcyan: "#008b8b",
8332
- darkgoldenrod: "#b8860b",
8333
- darkgray: "#a9a9a9",
8334
- darkgreen: "#006400",
8335
- darkgrey: "#a9a9a9",
8336
- darkkhaki: "#bdb76b",
8337
- darkmagenta: "#8b008b",
8338
- darkolivegreen: "#556b2f",
8339
- darkorange: "#ff8c00",
8340
- darkorchid: "#9932cc",
8341
- darkred: "#8b0000",
8342
- darksalmon: "#e9967a",
8343
- darkseagreen: "#8fbc8f",
8344
- darkslateblue: "#483d8b",
8345
- darkslategray: "#2f4f4f",
8346
- darkslategrey: "#2f4f4f",
8347
- darkturquoise: "#00ced1",
8348
- darkviolet: "#9400d3",
8349
- deeppink: "#ff1493",
8350
- deepskyblue: "#00bfff",
8351
- dimgray: "#696969",
8352
- dimgrey: "#696969",
8353
- dodgerblue: "#1e90ff",
8354
- firebrick: "#b22222",
8355
- floralwhite: "#fffaf0",
8356
- forestgreen: "#228b22",
8357
- fuchsia: "#ff00ff",
8358
- gainsboro: "#dcdcdc",
8359
- ghostwhite: "#f8f8ff",
8360
- gold: "#ffd700",
8361
- goldenrod: "#daa520",
8362
- gray: "#808080",
8363
- green: "#008000",
8364
- greenyellow: "#adff2f",
8365
- grey: "#808080",
8366
- honeydew: "#f0fff0",
8367
- hotpink: "#ff69b4",
8368
- indianred: "#cd5c5c",
8369
- indigo: "#4b0082",
8370
- ivory: "#fffff0",
8371
- khaki: "#f0e68c",
8372
- lavender: "#e6e6fa",
8373
- lavenderblush: "#fff0f5",
8374
- lawngreen: "#7cfc00",
8375
- lemonchiffon: "#fffacd",
8376
- lightblue: "#add8e6",
8377
- lightcoral: "#f08080",
8378
- lightcyan: "#e0ffff",
8379
- lightgoldenrodyellow: "#fafad2",
8380
- lightgray: "#d3d3d3",
8381
- lightgreen: "#90ee90",
8382
- lightgrey: "#d3d3d3",
8383
- lightpink: "#ffb6c1",
8384
- lightsalmon: "#ffa07a",
8385
- lightseagreen: "#20b2aa",
8386
- lightskyblue: "#87cefa",
8387
- lightslategray: "#778899",
8388
- lightslategrey: "#778899",
8389
- lightsteelblue: "#b0c4de",
8390
- lightyellow: "#ffffe0",
8391
- lime: "#00ff00",
8392
- limegreen: "#32cd32",
8393
- linen: "#faf0e6",
8394
- magenta: "#ff00ff",
8395
- maroon: "#800000",
8396
- mediumaquamarine: "#66cdaa",
8397
- mediumblue: "#0000cd",
8398
- mediumorchid: "#ba55d3",
8399
- mediumpurple: "#9370db",
8400
- mediumseagreen: "#3cb371",
8401
- mediumslateblue: "#7b68ee",
8402
- mediumspringgreen: "#00fa9a",
8403
- mediumturquoise: "#48d1cc",
8404
- mediumvioletred: "#c71585",
8405
- midnightblue: "#191970",
8406
- mintcream: "#f5fffa",
8407
- mistyrose: "#ffe4e1",
8408
- moccasin: "#ffe4b5",
8409
- navajowhite: "#ffdead",
8410
- navy: "#000080",
8411
- oldlace: "#fdf5e6",
8412
- olive: "#808000",
8413
- olivedrab: "#6b8e23",
8414
- orange: "#ffa500",
8415
- orangered: "#ff4500",
8416
- orchid: "#da70d6",
8417
- palegoldenrod: "#eee8aa",
8418
- palegreen: "#98fb98",
8419
- paleturquoise: "#afeeee",
8420
- palevioletred: "#db7093",
8421
- papayawhip: "#ffefd5",
8422
- peachpuff: "#ffdab9",
8423
- peru: "#cd853f",
8424
- pink: "#ffc0cb",
8425
- plum: "#dda0dd",
8426
- powderblue: "#b0e0e6",
8427
- purple: "#800080",
8428
- rebeccapurple: "#663399",
8429
- red: "#ff0000",
8430
- rosybrown: "#bc8f8f",
8431
- royalblue: "#4169e1",
8432
- saddlebrown: "#8b4513",
8433
- salmon: "#fa8072",
8434
- sandybrown: "#f4a460",
8435
- seagreen: "#2e8b57",
8436
- seashell: "#fff5ee",
8437
- sienna: "#a0522d",
8438
- silver: "#c0c0c0",
8439
- skyblue: "#87ceeb",
8440
- slateblue: "#6a5acd",
8441
- slategray: "#708090",
8442
- slategrey: "#708090",
8443
- snow: "#fffafa",
8444
- springgreen: "#00ff7f",
8445
- tan: "#d2b48c",
8446
- teal: "#008080",
8447
- thistle: "#d8bfd8",
8448
- transparent: "#00000000",
8449
- turquoise: "#40e0d0",
8450
- violet: "#ee82ee",
8451
- wheat: "#f5deb3",
8452
- white: "#ffffff",
8453
- whitesmoke: "#f5f5f5",
8454
- yellow: "#ffff00",
8455
- yellowgreen: "#9acd32"
8456
- },
8457
- /* API */
8458
- parse: (color2) => {
8459
- color2 = color2.toLowerCase();
8460
- const hex2 = Keyword.colors[color2];
8461
- if (hex2)
8462
- return Hex.parse(hex2);
8463
- },
8464
- stringify: (channels2) => {
8465
- const hex2 = Hex.stringify(channels2);
8466
- for (const name in Keyword.colors)
8467
- if (Keyword.colors[name] === hex2)
8468
- return name;
8469
- }
8470
- }, RGB = {
8471
- /* VARIABLES */
8472
- re: /^rgba?\(\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))(?:\s*?(?:,|\/)\s*?\+?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?)))?\s*?\)$/i,
8473
- /* API */
8474
- parse: (color2) => {
8475
- const charCode = color2.charCodeAt(0);
8476
- if (charCode !== 114 && charCode !== 82)
8477
- return;
8478
- const match = color2.match(RGB.re);
8479
- if (!match)
8480
- return;
8481
- const [, r2, isRedPercentage, g, isGreenPercentage, b, isBluePercentage, a, isAlphaPercentage] = match;
8482
- return channels.set({
8483
- r: Utils.channel.clamp.r(isRedPercentage ? parseFloat(r2) * 2.55 : parseFloat(r2)),
8484
- g: Utils.channel.clamp.g(isGreenPercentage ? parseFloat(g) * 2.55 : parseFloat(g)),
8485
- b: Utils.channel.clamp.b(isBluePercentage ? parseFloat(b) * 2.55 : parseFloat(b)),
8486
- a: a ? Utils.channel.clamp.a(isAlphaPercentage ? parseFloat(a) / 100 : parseFloat(a)) : 1
8487
- }, color2);
8488
- },
8489
- stringify: (channels2) => {
8490
- const { r: r2, g, b, a } = channels2;
8491
- return a < 1 ? `rgba(${Utils.lang.round(r2)}, ${Utils.lang.round(g)}, ${Utils.lang.round(b)}, ${Utils.lang.round(a)})` : `rgb(${Utils.lang.round(r2)}, ${Utils.lang.round(g)}, ${Utils.lang.round(b)})`;
8492
- }
8493
- }, Color = {
8494
- /* VARIABLES */
8495
- format: {
8496
- keyword: Keyword,
8497
- hex: Hex,
8498
- rgb: RGB,
8499
- rgba: RGB,
8500
- hsl: HSL,
8501
- hsla: HSL
8502
- },
8503
- /* API */
8504
- parse: (color2) => {
8505
- if (typeof color2 != "string")
8506
- return color2;
8507
- const channels2 = Hex.parse(color2) || RGB.parse(color2) || HSL.parse(color2) || Keyword.parse(color2);
8508
- if (channels2)
8509
- return channels2;
8510
- throw new Error(`Unsupported color format: "${color2}"`);
8511
- },
8512
- stringify: (channels2) => !channels2.changed && channels2.color ? channels2.color : channels2.type.is(TYPE.HSL) || channels2.data.r === void 0 ? HSL.stringify(channels2) : channels2.a < 1 || !Number.isInteger(channels2.r) || !Number.isInteger(channels2.g) || !Number.isInteger(channels2.b) ? RGB.stringify(channels2) : Hex.stringify(channels2)
8513
- }, change = (color2, channels2) => {
8514
- const ch = Color.parse(color2);
8515
- for (const c in channels2)
8516
- ch[c] = Utils.channel.clamp[c](channels2[c]);
8517
- return Color.stringify(ch);
8518
- }, toHex = (color2) => Color.format.hex.stringify(Color.parse(color2)), adjust = (color2, channels2) => {
8519
- const ch = Color.parse(color2), changes = {};
8520
- for (const c in channels2)
8521
- channels2[c] && (changes[c] = ch[c] + channels2[c]);
8522
- return change(color2, changes);
8523
- }, scale = (color2, channels2) => {
8524
- const ch = Color.parse(color2), adjustments = {}, delta = (amount, weight, max) => weight > 0 ? (max - amount) * weight / 100 : amount * weight / 100;
8525
- for (const c in channels2)
8526
- adjustments[c] = delta(ch[c], channels2[c], Utils.channel.max[c]);
8527
- return adjust(color2, adjustments);
8528
- };
8529
- var vars = { default: { font: "var(--likec4-default-font-family)" }, likec4: { font: "var(--likec4-font-family)", background: { color: "var(--likec4-background-color)", pattern: { color: "var(--likec4-background-pattern-color)" } } }, compound: { font: "var(--likec4-compound-font-family)", titleColor: "var(--likec4-compound-title-color)" }, element: { font: "var(--likec4-element-font-family)", fill: "var(--likec4-element-fill)", stroke: "var(--likec4-element-stroke)", hiContrast: "var(--likec4-element-hiContrast)", loContrast: "var(--likec4-element-loContrast)" }, relation: { lineColor: "var(--likec4-relation-lineColor)", labelColor: "var(--likec4-relation-labelColor)", labelBgColor: "var(--likec4-relation-labelBg)" }, optionsPanel: { top: "var(--likec4-options-panel-top)", right: "var(--likec4-options-panel-right)" } };
8530
- const Link = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
8321
+ ] }), Link = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
8531
8322
  "svg",
8532
8323
  {
8533
8324
  ref,
@@ -8581,48 +8372,45 @@ function NavigateToBtn({ xynodeId, className }) {
8581
8372
  className: clsx("nodrag nopan", className),
8582
8373
  radius: "xl",
8583
8374
  onClick: (event) => {
8584
- diagramApi.getState().triggerOnNavigateTo(xynodeId, event), event.stopPropagation();
8375
+ event.stopPropagation(), diagramApi.getState().triggerOnNavigateTo(xynodeId, event);
8585
8376
  },
8377
+ onDoubleClick: (event) => event.stopPropagation(),
8586
8378
  children: /* @__PURE__ */ jsx(ZoomIn, {})
8587
8379
  }
8588
8380
  );
8589
8381
  }
8590
- var cssContainer = "lbtzdo0", cssCompound = "lbtzdo2", cssTitle = "lbtzdo4", cssIndicator = "lbtzdo6", cssNavigateBtn$1 = "lbtzdo7";
8591
- const compoundColor = (color2, depth) => toHex(
8592
- scale(color2, {
8593
- l: -35 - 5 * depth,
8594
- s: -15 - 5 * depth
8595
- })
8596
- ), CompoundNodeMemo = /* @__PURE__ */ memo(function({
8382
+ var container$1 = "lbtzdo0", varTransparency = "var(--lbtzdo1)", compoundBody = "lbtzdo2", transparent = "lbtzdo5", title$1 = "lbtzdo6", indicator$1 = "lbtzdoa", navigateBtn = "lbtzdoc";
8383
+ const CompoundNodeMemo = /* @__PURE__ */ memo(function({
8597
8384
  id: id2,
8598
8385
  data: {
8599
8386
  element
8600
8387
  }
8601
8388
  }) {
8602
- const { color: color2, depth = 0, ...compound } = element, colors2 = useMemo(() => {
8603
- const colors22 = defaultTheme.elements[color2];
8604
- return {
8605
- fill: compoundColor(colors22.fill, depth),
8606
- stroke: compoundColor(colors22.stroke, depth)
8607
- };
8608
- }, [color2, depth]), { isHovered, hasOnNavigateTo } = useDiagramState((s) => ({
8389
+ const { color: color2, style: style2, depth = 1, ...compound } = element, opacity = style2.opacity ?? 100, { isHovered, hasOnNavigateTo } = useDiagramState((s) => ({
8609
8390
  isHovered: s.hoveredNodeId === id2,
8610
8391
  hasOnNavigateTo: !!s.onNavigateTo
8611
- })), isnavigable = !!compound.navigateTo && hasOnNavigateTo;
8392
+ })), isnavigable = !!compound.navigateTo && hasOnNavigateTo, transparency = clamp$1(100 - opacity, {
8393
+ min: 0,
8394
+ max: 98
8395
+ });
8612
8396
  return /* @__PURE__ */ jsxs(
8613
8397
  Box,
8614
8398
  {
8615
- className: clsx(cssContainer, "likec4-compound-node"),
8616
- style: assignInlineVars({ fill: vars.element.fill, stroke: vars.element.stroke }, {
8617
- fill: colors2.fill,
8618
- stroke: colors2.stroke
8619
- }),
8399
+ className: clsx(
8400
+ container$1,
8401
+ "likec4-compound-node",
8402
+ opacity < 100 && "likec4-compound-transparent"
8403
+ ),
8620
8404
  mod: {
8405
+ "compound-depth": depth,
8621
8406
  "likec4-color": color2,
8622
8407
  "likec4-shape": compound.shape,
8623
8408
  "likec4-navigable": isnavigable,
8624
8409
  hovered: isHovered
8625
8410
  },
8411
+ style: assignInlineVars({
8412
+ [varTransparency]: transparency + "%"
8413
+ }),
8626
8414
  children: [
8627
8415
  /* @__PURE__ */ jsx(
8628
8416
  Handle,
@@ -8632,7 +8420,7 @@ const compoundColor = (color2, depth) => toHex(
8632
8420
  style: { visibility: "hidden" }
8633
8421
  }
8634
8422
  ),
8635
- /* @__PURE__ */ jsx("svg", { className: cssIndicator, children: /* @__PURE__ */ jsx(
8423
+ /* @__PURE__ */ jsx("svg", { className: indicator$1, children: /* @__PURE__ */ jsx(
8636
8424
  "rect",
8637
8425
  {
8638
8426
  x: 0,
@@ -8642,15 +8430,24 @@ const compoundColor = (color2, depth) => toHex(
8642
8430
  rx: 6
8643
8431
  }
8644
8432
  ) }),
8645
- /* @__PURE__ */ jsx("div", { className: clsx(cssCompound, "likec4-compound"), children: /* @__PURE__ */ jsx(
8646
- Text,
8433
+ /* @__PURE__ */ jsx(
8434
+ "div",
8647
8435
  {
8648
- component: "div",
8649
- className: clsx(cssTitle, "likec4-compound-title"),
8650
- children: compound.title
8436
+ className: clsx(compoundBody, opacity < 100 && transparent, "likec4-compound"),
8437
+ style: {
8438
+ borderStyle: opacity < 100 ? style2.border : void 0
8439
+ },
8440
+ children: /* @__PURE__ */ jsx(
8441
+ Text,
8442
+ {
8443
+ component: "div",
8444
+ className: clsx(title$1, "likec4-compound-title"),
8445
+ children: compound.title
8446
+ }
8447
+ )
8651
8448
  }
8652
- ) }),
8653
- isnavigable && /* @__PURE__ */ jsx(NavigateToBtn, { xynodeId: id2, className: cssNavigateBtn$1 }),
8449
+ ),
8450
+ isnavigable && /* @__PURE__ */ jsx(NavigateToBtn, { xynodeId: id2, className: navigateBtn }),
8654
8451
  /* @__PURE__ */ jsx(
8655
8452
  Handle,
8656
8453
  {
@@ -8888,16 +8685,16 @@ function SelectedIndicator({ shape, w, h }) {
8888
8685
  }
8889
8686
  }
8890
8687
  const selectedScale = 1.015, variants = {
8891
- idle: (_, { scale: scale2 }) => ({
8688
+ idle: (_, { scale }) => ({
8892
8689
  scale: 1,
8893
8690
  transition: {
8894
- delay: isNumber(scale2) && scale2 > selectedScale ? 0.075 : 0
8691
+ delay: isNumber(scale) && scale > selectedScale ? 0.075 : 0
8895
8692
  }
8896
8693
  }),
8897
- selected: (_, { scale: scale2 }) => ({
8694
+ selected: (_, { scale }) => ({
8898
8695
  scale: selectedScale,
8899
8696
  transition: {
8900
- delay: isNumber(scale2) && scale2 > selectedScale ? 0.075 : 0
8697
+ delay: isNumber(scale) && scale > selectedScale ? 0.075 : 0
8901
8698
  }
8902
8699
  }),
8903
8700
  // dragging: {
@@ -8914,10 +8711,10 @@ const selectedScale = 1.015, variants = {
8914
8711
  // delay: 1
8915
8712
  // }
8916
8713
  // }),
8917
- hovered: (_, { scale: scale2 }) => ({
8714
+ hovered: (_, { scale }) => ({
8918
8715
  scale: 1.06,
8919
8716
  transition: {
8920
- delay: isNumber(scale2) && scale2 !== 1 && scale2 !== selectedScale ? 0 : 0.15
8717
+ delay: isNumber(scale) && scale !== 1 && scale !== selectedScale ? 0 : 0.15
8921
8718
  }
8922
8719
  }),
8923
8720
  tap: {
@@ -8939,7 +8736,7 @@ function ElementNode({
8939
8736
  }) {
8940
8737
  const { isHovered, hasOnNavigateTo, isHovercards, isInteractive } = useDiagramState((s) => ({
8941
8738
  isHovered: s.hoveredNodeId === id2,
8942
- isInteractive: s.nodesDraggable || s.nodesSelectable,
8739
+ isInteractive: s.nodesDraggable || s.nodesSelectable || !!s.onNavigateTo,
8943
8740
  isHovercards: s.showElementLinks,
8944
8741
  hasOnNavigateTo: !!s.onNavigateTo
8945
8742
  })), isNavigable = hasOnNavigateTo && !!element.navigateTo, w = toDomPrecision(width ?? element.width), h = toDomPrecision(height ?? element.height);
@@ -8951,7 +8748,7 @@ function ElementNode({
8951
8748
  case dragging:
8952
8749
  animate = "idle";
8953
8750
  break;
8954
- case ((isInteractive || hasOnNavigateTo) && isHovered):
8751
+ case (isInteractive && isHovered):
8955
8752
  animate = "hovered";
8956
8753
  break;
8957
8754
  case selected2:
@@ -9048,6 +8845,36 @@ function ElementNode({
9048
8845
  }
9049
8846
  );
9050
8847
  }
8848
+ function SelectEdgesOnNodeFocus() {
8849
+ const focusedNodeId = useDiagramState((s) => s.focusedNodeId), xyflowApi = useXYStoreApi();
8850
+ return useUpdateEffect(() => {
8851
+ const edgeChanges = [], nodeChanges = [], { edges, nodes, triggerNodeChanges, triggerEdgeChanges } = xyflowApi.getState();
8852
+ if (focusedNodeId) {
8853
+ for (const edge of edges)
8854
+ edge.source === focusedNodeId || edge.target === focusedNodeId ? edgeChanges.push({
8855
+ id: edge.id,
8856
+ type: "select",
8857
+ selected: !0
8858
+ }) : edge.selected && edgeChanges.push({
8859
+ id: edge.id,
8860
+ type: "select",
8861
+ selected: !1
8862
+ });
8863
+ for (const node of nodes)
8864
+ node.selected && node.id !== focusedNodeId && nodeChanges.push({
8865
+ id: node.id,
8866
+ type: "select",
8867
+ selected: !1
8868
+ });
8869
+ nodeChanges.push({
8870
+ id: focusedNodeId,
8871
+ type: "select",
8872
+ selected: !0
8873
+ }), edgeChanges.length > 0 && triggerEdgeChanges(edgeChanges), nodeChanges.length > 0 && triggerNodeChanges(nodeChanges);
8874
+ } else
8875
+ xyflowApi.getState().resetSelectedElements();
8876
+ }, [focusedNodeId]), null;
8877
+ }
9051
8878
  function literalToEnum(value) {
9052
8879
  switch (value) {
9053
8880
  case "dots":
@@ -9065,33 +8892,38 @@ const XYFlowBackground = memo(({ background }) => {
9065
8892
  return /* @__PURE__ */ jsx(Background, { variant: literalToEnum(background) });
9066
8893
  const { variant, ...rest } = background;
9067
8894
  return /* @__PURE__ */ jsx(Background, { variant: literalToEnum(variant), ...rest });
9068
- }, deepEqual);
8895
+ }, deepEqual), viewportDomNode = (state) => {
8896
+ var _a;
8897
+ return ((_a = state.domNode) == null ? void 0 : _a.querySelector(".react-flow__viewport")) ?? null;
8898
+ };
9069
8899
  function useXYFlowEvents() {
9070
- const diagramApi = useDiagramStoreApi(), xyflowApi = useXYStoreApi(), dblclickTimeout = useRef();
9071
- return useMemo(() => ({
9072
- onPaneClick: (event) => {
9073
- var _a;
9074
- diagramApi.setState(
9075
- {
9076
- lastClickedNodeId: null,
9077
- lastClickedEdgeId: null
9078
- },
9079
- !1,
9080
- "onPaneClick"
9081
- );
8900
+ const diagramApi = useDiagramStoreApi(), xyflowApi = useXYStoreApi(), dblclickTimeout = useRef(), viewportRef = useRef(viewportDomNode(xyflowApi.getState())), dbclickGuarg = () => dblclickTimeout.current !== void 0 ? !0 : (dblclickTimeout.current = window.setTimeout(() => {
8901
+ dblclickTimeout.current = void 0;
8902
+ }, 250), !1), transformRef = useRef(""), cbRef = useRef();
8903
+ return useEffect(() => xyflowApi.subscribe((state, prev) => {
8904
+ (state.domNode !== prev.domNode || state.domNode && !viewportRef.current) && (viewportRef.current = viewportDomNode(state));
8905
+ }), [xyflowApi]), useMemo(() => ({
8906
+ onDoubleClick: (event) => {
8907
+ diagramApi.getState().resetLastClicked();
9082
8908
  const diagramState = diagramApi.getState();
9083
- if (dblclickTimeout.current) {
9084
- if (window.clearTimeout(dblclickTimeout.current), dblclickTimeout.current = void 0, diagramState.onCanvasDblClick) {
9085
- diagramState.onCanvasDblClick(event);
9086
- return;
9087
- }
9088
- (_a = diagramState.onCanvasClick) == null || _a.call(diagramState, event), diagramState.fitViewEnabled && diagramState.viewportChanged && diagramState.fitDiagram();
8909
+ if (diagramState.onCanvasDblClick) {
8910
+ diagramState.onCanvasDblClick(event);
8911
+ return;
8912
+ }
8913
+ if (diagramState.fitViewEnabled && diagramState.zoomable) {
8914
+ diagramState.fitDiagram(), event.stopPropagation();
9089
8915
  return;
9090
8916
  }
9091
- dblclickTimeout.current = window.setTimeout(() => {
9092
- var _a2, _b;
9093
- dblclickTimeout.current = void 0, (_b = (_a2 = diagramApi.getState()).onCanvasClick) == null || _b.call(_a2, event);
9094
- }, 300);
8917
+ },
8918
+ onPaneClick: (event) => {
8919
+ if (dbclickGuarg())
8920
+ return;
8921
+ const { focusedNodeId, fitDiagram, onCanvasClick, resetLastClicked } = diagramApi.getState();
8922
+ if (resetLastClicked(), onCanvasClick) {
8923
+ onCanvasClick(event);
8924
+ return;
8925
+ }
8926
+ focusedNodeId && (fitDiagram(), event.stopPropagation());
9095
8927
  },
9096
8928
  onNodeContextMenu: (event, xynode) => {
9097
8929
  var _a, _b;
@@ -9103,7 +8935,7 @@ function useXYFlowEvents() {
9103
8935
  },
9104
8936
  onPaneContextMenu: (event) => {
9105
8937
  var _a, _b;
9106
- diagramApi.getState().setLastClickedNode(null), diagramApi.getState().setLastClickedEdge(null), (_b = (_a = diagramApi.getState()).onCanvasContextMenu) == null || _b.call(_a, event);
8938
+ diagramApi.getState().resetLastClicked(), (_b = (_a = diagramApi.getState()).onCanvasContextMenu) == null || _b.call(_a, event);
9107
8939
  },
9108
8940
  onEdgeContextMenu: (event, xyedge) => {
9109
8941
  var _a, _b;
@@ -9114,24 +8946,67 @@ function useXYFlowEvents() {
9114
8946
  });
9115
8947
  },
9116
8948
  onNodeClick: (event, xynode) => {
9117
- var _a, _b;
9118
- diagramApi.getState().setLastClickedNode(xynode.id), (_b = (_a = diagramApi.getState()).onNodeClick) == null || _b.call(_a, {
9119
- element: xynode.data.element,
9120
- xynode,
9121
- event
9122
- });
8949
+ diagramApi.getState().setLastClickedNode(xynode.id);
8950
+ const { focusedNodeId, fitDiagram, onNodeClick } = diagramApi.getState();
8951
+ if (onNodeClick) {
8952
+ onNodeClick({
8953
+ element: xynode.data.element,
8954
+ xynode,
8955
+ event
8956
+ });
8957
+ return;
8958
+ }
8959
+ focusedNodeId && focusedNodeId !== xynode.id && (fitDiagram(xynode), event.stopPropagation());
8960
+ },
8961
+ onNodeDoubleClick: (event, xynode) => {
8962
+ diagramApi.getState().setLastClickedNode(xynode.id);
8963
+ const { zoomable, fitViewEnabled, fitDiagram, onNodeClick } = diagramApi.getState();
8964
+ onNodeClick || zoomable && fitViewEnabled && (fitDiagram(xynode), event.stopPropagation());
9123
8965
  },
9124
8966
  onEdgeClick: (event, xyedge) => {
9125
- var _a, _b;
9126
- diagramApi.getState().setLastClickedEdge(xyedge.id), (_b = (_a = diagramApi.getState()).onEdgeClick) == null || _b.call(_a, {
9127
- relation: xyedge.data.edge,
9128
- xyedge,
9129
- event
9130
- });
8967
+ diagramApi.getState().setLastClickedEdge(xyedge.id);
8968
+ const { focusedNodeId, fitDiagram, onEdgeClick, xyflow } = diagramApi.getState();
8969
+ if (onEdgeClick) {
8970
+ onEdgeClick({
8971
+ relation: xyedge.data.edge,
8972
+ xyedge,
8973
+ event
8974
+ });
8975
+ return;
8976
+ }
8977
+ if (focusedNodeId && (focusedNodeId === xyedge.source || focusedNodeId === xyedge.target)) {
8978
+ const nextFocus = focusedNodeId === xyedge.source ? xyedge.target : xyedge.source;
8979
+ fitDiagram(xyflow.getNode(nextFocus)), event.stopPropagation();
8980
+ }
9131
8981
  },
9132
8982
  onMoveEnd: (event, _viewport) => {
9133
8983
  const viewportChanged = !!event;
9134
8984
  viewportChanged !== diagramApi.getState().viewportChanged && diagramApi.setState({ viewportChanged }, !1, `viewport-changed: ${viewportChanged}`);
8985
+ },
8986
+ onNodeMouseEnter: (event, xynode) => {
8987
+ diagramApi.getState().setHoveredNode(xynode.id);
8988
+ },
8989
+ onNodeMouseLeave: (event, xynode) => {
8990
+ diagramApi.getState().setHoveredNode(null);
8991
+ },
8992
+ onEdgeMouseEnter: (event, xyedge) => {
8993
+ diagramApi.getState().setHoveredEdge(xyedge.id);
8994
+ },
8995
+ onEdgeMouseLeave: (event, xyedge) => {
8996
+ diagramApi.getState().setHoveredEdge(null);
8997
+ },
8998
+ /**
8999
+ * WOKAROUND:
9000
+ * Viewport transform is not rounded to integers which results in blurry nodes on some resolution
9001
+ * https://github.com/xyflow/xyflow/issues/3282
9002
+ */
9003
+ onViewportChange: ({ x, y, zoom: zoom2 }) => {
9004
+ const scale = zoom2 != 1 ? zoom2.toFixed(6) : "1";
9005
+ transformRef.current = `translate(${Math.round(x)}px, ${Math.round(y)}px) scale(${scale})`, cbRef.current ?? (cbRef.current = requestIdleCallback(() => {
9006
+ cbRef.current = void 0, viewportRef.current && viewportRef.current.style.transform !== transformRef.current && (viewportRef.current.style.transform = transformRef.current);
9007
+ }, {
9008
+ timeout: 1e3
9009
+ }));
9135
9010
  }
9136
9011
  }), [diagramApi, xyflowApi]);
9137
9012
  }
@@ -9141,7 +9016,7 @@ const nodeTypes = {
9141
9016
  }, edgeTypes = {
9142
9017
  relationship: RelationshipEdge
9143
9018
  }, selector = (s) => ({
9144
- nodesSelectable: s.nodesSelectable,
9019
+ nodesSelectable: s.nodesSelectable || s.focusedNodeId !== null,
9145
9020
  nodesDraggable: s.nodesDraggable,
9146
9021
  fitView: s.fitViewEnabled,
9147
9022
  fitViewPadding: s.fitViewPadding,
@@ -9151,15 +9026,14 @@ const nodeTypes = {
9151
9026
  hasOnCanvasContextMenu: !!s.onCanvasContextMenu,
9152
9027
  hasOnEdgeContextMenu: !!s.onEdgeContextMenu,
9153
9028
  hasOnEdgeClick: !!s.onEdgeClick,
9154
- hasOnCanvasClick: !!s.onCanvasClick || !!s.onCanvasDblClick
9029
+ zoomable: s.zoomable,
9030
+ pannable: s.pannable
9155
9031
  });
9156
9032
  function XYFlowWrapper({
9157
9033
  className,
9158
9034
  children: children2,
9159
9035
  defaultNodes,
9160
9036
  defaultEdges,
9161
- pannable,
9162
- zoomable,
9163
9037
  controls,
9164
9038
  background,
9165
9039
  style: style2
@@ -9169,6 +9043,8 @@ function XYFlowWrapper({
9169
9043
  nodesDraggable,
9170
9044
  fitView: fitView2,
9171
9045
  fitViewPadding,
9046
+ pannable,
9047
+ zoomable,
9172
9048
  ...editor
9173
9049
  } = useDiagramState(selector), layoutConstraints = useLayoutConstraints(), handlers = useXYFlowEvents(), isBgWithPattern = background !== "transparent" && background !== "solid", { colorScheme } = useMantineColorScheme(), colorMode = colorScheme !== "auto" ? colorScheme : void 0;
9174
9050
  return /* @__PURE__ */ jsxs(
@@ -9208,33 +9084,28 @@ function XYFlowWrapper({
9208
9084
  selectionKeyCode: null
9209
9085
  },
9210
9086
  nodesDraggable,
9211
- ...nodesDraggable && layoutConstraints,
9087
+ ...nodesDraggable && {
9088
+ onNodeDragStart: layoutConstraints.onNodeDragStart,
9089
+ onNodeDrag: layoutConstraints.onNodeDrag,
9090
+ onNodeDragStop: layoutConstraints.onNodeDragStop
9091
+ },
9212
9092
  zoomOnDoubleClick: !1,
9213
9093
  elevateNodesOnSelect: !1,
9214
9094
  selectNodesOnDrag: !1,
9095
+ onDoubleClick: handlers.onDoubleClick,
9215
9096
  onPaneClick: handlers.onPaneClick,
9216
- ...editor.hasOnNodeClick && {
9217
- onNodeClick: handlers.onNodeClick
9218
- },
9219
- ...editor.hasOnEdgeClick && {
9220
- onEdgeClick: handlers.onEdgeClick
9221
- },
9222
9097
  onMoveEnd: handlers.onMoveEnd,
9098
+ onNodeMouseEnter: handlers.onNodeMouseEnter,
9099
+ onNodeMouseLeave: handlers.onNodeMouseLeave,
9100
+ onEdgeMouseEnter: handlers.onEdgeMouseEnter,
9101
+ onEdgeMouseLeave: handlers.onEdgeMouseLeave,
9102
+ onNodeClick: handlers.onNodeClick,
9103
+ onNodeDoubleClick: handlers.onNodeDoubleClick,
9104
+ onEdgeClick: handlers.onEdgeClick,
9105
+ onViewportChange: handlers.onViewportChange,
9223
9106
  onInit: () => {
9224
9107
  diagramApi.setState({ initialized: !0 }, !1, "initialized");
9225
9108
  },
9226
- onNodeMouseEnter: (_event, node) => {
9227
- diagramApi.getState().setHoveredNode(node.id);
9228
- },
9229
- onNodeMouseLeave: () => {
9230
- diagramApi.getState().setHoveredNode(null);
9231
- },
9232
- onEdgeMouseEnter: (_event, edge) => {
9233
- diagramApi.getState().setHoveredEdge(edge.id);
9234
- },
9235
- onEdgeMouseLeave: () => {
9236
- diagramApi.getState().setHoveredEdge(null);
9237
- },
9238
9109
  ...editor.hasOnNodeContextMenu && {
9239
9110
  onNodeContextMenu: handlers.onNodeContextMenu
9240
9111
  },
@@ -9246,7 +9117,8 @@ function XYFlowWrapper({
9246
9117
  },
9247
9118
  children: [
9248
9119
  isBgWithPattern && /* @__PURE__ */ jsx(XYFlowBackground, { background }),
9249
- controls && /* @__PURE__ */ jsx(Controls, {}),
9120
+ controls && /* @__PURE__ */ jsx(Controls, { position: "bottom-right" }),
9121
+ zoomable && !editor.hasOnNodeClick && /* @__PURE__ */ jsx(SelectEdgesOnNodeFocus, {}),
9250
9122
  children2
9251
9123
  ]
9252
9124
  }
@@ -9266,6 +9138,7 @@ function LikeC4Diagram({
9266
9138
  background = "dots",
9267
9139
  controls = !1,
9268
9140
  showElementLinks = !0,
9141
+ showDiagramTitle = !0,
9269
9142
  initialWidth,
9270
9143
  initialHeight,
9271
9144
  keepAspectRatio = !1,
@@ -9302,6 +9175,8 @@ function LikeC4Diagram({
9302
9175
  {
9303
9176
  view,
9304
9177
  readonly,
9178
+ pannable,
9179
+ zoomable,
9305
9180
  fitViewEnabled: fitView2,
9306
9181
  fitViewPadding,
9307
9182
  showElementLinks,
@@ -9318,13 +9193,13 @@ function LikeC4Diagram({
9318
9193
  onCanvasDblClick,
9319
9194
  children: [
9320
9195
  /* @__PURE__ */ jsx(
9321
- KeepAspectRatio,
9196
+ KeepAspectRatioContainer,
9322
9197
  {
9323
9198
  className: clsx(rootClassName, className),
9324
9199
  enabled: keepAspectRatio,
9325
9200
  width: view.width,
9326
9201
  height: view.height,
9327
- children: /* @__PURE__ */ jsx(
9202
+ children: /* @__PURE__ */ jsxs(
9328
9203
  XYFlow,
9329
9204
  {
9330
9205
  className: clsx(
@@ -9338,9 +9213,10 @@ function LikeC4Diagram({
9338
9213
  controls,
9339
9214
  defaultNodes: initialRef.current.defaultNodes,
9340
9215
  defaultEdges: initialRef.current.defaultEdges,
9341
- pannable,
9342
- zoomable,
9343
- children: readonly !== !0 && /* @__PURE__ */ jsx(OptionsPanel2, {})
9216
+ children: [
9217
+ readonly !== !0 && /* @__PURE__ */ jsx(OptionsPanel, {}),
9218
+ showDiagramTitle === !0 && /* @__PURE__ */ jsx(DiagramTitlePanel, {})
9219
+ ]
9344
9220
  }
9345
9221
  )
9346
9222
  }
@@ -9374,6 +9250,7 @@ function StaticLikeC4Diagram({
9374
9250
  controls: !1,
9375
9251
  background,
9376
9252
  showElementLinks: !0,
9253
+ showDiagramTitle: !1,
9377
9254
  nodesSelectable: !1,
9378
9255
  nodesDraggable: !1,
9379
9256
  ...rest