@likec4/diagram 1.20.2 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.md +2 -2
  2. package/dist/base/BaseXYFlow.js +1 -1
  3. package/dist/base/example/_types.d.ts +3 -3
  4. package/dist/base/example/custom.d.ts +3 -2
  5. package/dist/base/primitives/compound/CompoundActionButton.js +1 -1
  6. package/dist/base/primitives/compound/CompoundDetailsButton.js +1 -1
  7. package/dist/base/primitives/compound/CompoundNodeContainer.js +1 -1
  8. package/dist/base/primitives/compound/CompoundTitle.css.d.ts +1 -0
  9. package/dist/base/primitives/compound/CompoundTitle.css.js +2 -0
  10. package/dist/base/primitives/compound/CompoundTitle.d.ts +2 -2
  11. package/dist/base/primitives/compound/CompoundTitle.js +17 -6
  12. package/dist/base/primitives/edge/EdgeLabel.js +1 -1
  13. package/dist/base/primitives/element/ElementActionButtons.js +1 -1
  14. package/dist/base/primitives/element/ElementDetailsButton.js +1 -1
  15. package/dist/base/primitives/element/ElementNodeContainer.d.ts +1 -1
  16. package/dist/base/primitives/element/ElementNodeContainer.js +15 -0
  17. package/dist/base/primitives/element/ElementShape.js +1 -1
  18. package/dist/base/primitives/element/ElementTitle.css.d.ts +0 -1
  19. package/dist/base/primitives/element/ElementTitle.css.js +8 -8
  20. package/dist/base/primitives/element/ElementTitle.d.ts +1 -1
  21. package/dist/base/primitives/element/ElementTitle.js +4 -2
  22. package/dist/base/primitives/element/styles.css.d.ts +3 -0
  23. package/dist/base/primitives/element/styles.css.js +6 -0
  24. package/dist/context/DiagramEventHandlers.js +1 -1
  25. package/dist/context/DiagramFeatures.js +1 -1
  26. package/dist/context/RootContainer.js +1 -1
  27. package/dist/hooks/useDiagram.d.ts +1 -2
  28. package/dist/hooks/useXYFlow.js +1 -1
  29. package/dist/likec4diagram/DiagramUI.d.ts +1 -2
  30. package/dist/likec4diagram/DiagramUI.js +3 -3
  31. package/dist/likec4diagram/XYFlow.js +1 -1
  32. package/dist/likec4diagram/custom/edges/NotePopover.js +1 -1
  33. package/dist/likec4diagram/custom/edges/RelationshipEdge.js +1 -1
  34. package/dist/likec4diagram/custom/edges/RelationshipsDropdownMenu.js +4 -4
  35. package/dist/likec4diagram/custom/nodes/nodeTypes.js +8 -8
  36. package/dist/likec4diagram/custom/nodes/toolbar/_shared.js +2 -2
  37. package/dist/likec4diagram/state/assign.js +1 -1
  38. package/dist/likec4diagram/state/machine.js +5 -5
  39. package/dist/likec4diagram/types.d.ts +2 -2
  40. package/dist/likec4diagram/ui/controls/Controls.js +1 -1
  41. package/dist/likec4diagram/ui/diagram-title/DiagramTitlePanel.js +1 -1
  42. package/dist/likec4diagram/ui/walkthrough/DynamicViewWalkthrough.js +2 -2
  43. package/dist/likec4diagram/useLayoutConstraints.d.ts +2 -1
  44. package/dist/likec4diagram/useLayoutConstraints.js +14 -15
  45. package/dist/likec4diagram/useViewToNodesEdges.js +1 -1
  46. package/dist/overlays/Overlays.js +42 -21
  47. package/dist/overlays/element-details/ElementDetailsCard.d.ts +7 -3
  48. package/dist/overlays/element-details/ElementDetailsCard.js +38 -39
  49. package/dist/overlays/element-details/TabPanelDeployments.js +1 -1
  50. package/dist/overlays/element-details/TabPanelRelationships.js +16 -32
  51. package/dist/overlays/overlay/Overlay.css.js +2 -1
  52. package/dist/overlays/overlay/Overlay.js +2 -2
  53. package/dist/overlays/relationship-details/SelectEdge.js +1 -1
  54. package/dist/overlays/relationship-details/_types.d.ts +3 -3
  55. package/dist/overlays/relationship-details/actor.js +1 -1
  56. package/dist/overlays/relationship-details/custom/nodeTypes.d.ts +3 -3
  57. package/dist/overlays/relationship-details/custom/nodeTypes.js +2 -2
  58. package/dist/overlays/relationship-details/useLayoutedDetails.js +1 -4
  59. package/dist/overlays/relationships-browser/-useRelationshipsView.js +0 -3
  60. package/dist/overlays/relationships-browser/RelationshipsBrowser.js +3 -3
  61. package/dist/overlays/relationships-browser/_types.d.ts +3 -3
  62. package/dist/overlays/relationships-browser/actor.js +16 -16
  63. package/dist/overlays/relationships-browser/custom/ElementActions.js +12 -2
  64. package/dist/overlays/relationships-browser/custom/nodeTypes.d.ts +3 -2
  65. package/dist/overlays/relationships-browser/custom/nodeTypes.js +3 -3
  66. package/dist/overlays/relationships-browser/useViewToNodesEdges.js +3 -2
  67. package/dist/style.css +1 -1
  68. package/package.json +14 -14
  69. package/src/base/example/_types.ts +3 -2
  70. package/src/base/example/useViewToNodesEdges.ts +2 -1
  71. package/src/base/primitives/compound/CompoundTitle.css.ts +27 -1
  72. package/src/base/primitives/compound/CompoundTitle.tsx +12 -2
  73. package/src/base/primitives/element/ElementNodeContainer.tsx +21 -1
  74. package/src/base/primitives/element/ElementShape.css.ts +5 -0
  75. package/src/base/primitives/element/ElementTitle.css.ts +17 -24
  76. package/src/base/primitives/element/ElementTitle.tsx +4 -2
  77. package/src/base/primitives/element/styles.css.ts +74 -0
  78. package/src/hooks/useDiagram.ts +1 -1
  79. package/src/likec4diagram/DiagramUI.tsx +2 -2
  80. package/src/likec4diagram/XYFlow.tsx +2 -2
  81. package/src/likec4diagram/custom/edges/RelationshipsDropdownMenu.tsx +3 -2
  82. package/src/likec4diagram/types.ts +2 -2
  83. package/src/likec4diagram/useLayoutConstraints.ts +23 -19
  84. package/src/likec4diagram/useViewToNodesEdges.ts +1 -1
  85. package/src/overlays/Overlays.tsx +61 -281
  86. package/src/overlays/element-details/ElementDetailsCard.tsx +213 -257
  87. package/src/overlays/element-details/TabPanelRelationships.tsx +15 -77
  88. package/src/overlays/overlay/Overlay.tsx +1 -1
  89. package/src/overlays/relationship-details/_types.ts +3 -3
  90. package/src/overlays/relationship-details/useLayoutedDetails.ts +1 -1
  91. package/src/overlays/relationships-browser/RelationshipsBrowser.tsx +44 -55
  92. package/src/overlays/relationships-browser/_types.ts +12 -2
  93. package/src/overlays/relationships-browser/actor.ts +11 -10
  94. package/src/overlays/relationships-browser/custom/ElementActions.tsx +12 -2
  95. package/src/overlays/relationships-browser/useViewToNodesEdges.ts +2 -1
@@ -10,12 +10,23 @@ import { useSyncedRef } from "@react-hookz/web";
10
10
  import { useDiagram } from "../hooks/useDiagram.js";
11
11
  import { useXYStoreApi } from "../hooks/useXYFlow.js";
12
12
  class Rect {
13
- constructor() {
13
+ constructor(xynode, parent = null) {
14
14
  __publicField(this, "id");
15
15
  __publicField(this, "minX", Infinity);
16
16
  __publicField(this, "minY", Infinity);
17
17
  __publicField(this, "maxX", -Infinity);
18
18
  __publicField(this, "maxY", -Infinity);
19
+ this.id = xynode.id;
20
+ this.positionAbsolute = !parent ? xynode.position : {
21
+ x: xynode.position.x + parent.minX,
22
+ y: xynode.position.y + parent.minY
23
+ };
24
+ const { width, height } = getNodeDimensions(xynode);
25
+ this.maxX = this.minX + Math.ceil(width);
26
+ this.maxY = this.minY + Math.ceil(height);
27
+ if (parent) {
28
+ parent.children.push(this);
29
+ }
19
30
  }
20
31
  get positionAbsolute() {
21
32
  return {
@@ -56,27 +67,15 @@ __publicField(Rect, "TopPadding", 55);
56
67
  __publicField(Rect, "BottomPadding", 40);
57
68
  class Compound extends Rect {
58
69
  constructor(xynode, parent = null) {
59
- super();
70
+ super(xynode, parent);
60
71
  __publicField(this, "children", []);
61
72
  this.parent = parent;
62
- this.id = xynode.id;
63
- if (parent) {
64
- parent.children.push(this);
65
- }
66
73
  }
67
74
  }
68
75
  class Leaf extends Rect {
69
76
  constructor(xynode, parent = null) {
70
- super();
77
+ super(xynode, parent);
71
78
  this.parent = parent;
72
- this.id = xynode.id;
73
- this.positionAbsolute = xynode.internals.positionAbsolute;
74
- const { width, height } = getNodeDimensions(xynode);
75
- this.maxX = this.minX + Math.ceil(width);
76
- this.maxY = this.minY + Math.ceil(height);
77
- if (parent) {
78
- parent.children.push(this);
79
- }
80
79
  }
81
80
  }
82
81
  function createLayoutConstraints(xyflowApi, editingNodeIds) {
@@ -80,7 +80,7 @@ function viewToNodesEdge(opts) {
80
80
  shape: node.shape,
81
81
  style: node.style,
82
82
  depth: node.depth ?? 0,
83
- icon: node.icon ?? null,
83
+ icon: node.icon ?? "none",
84
84
  position: node.position
85
85
  };
86
86
  const leafNodeData = {
@@ -1,11 +1,14 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Box, Notification, Code, Group, Button } from "@mantine/core";
3
+ import { useCallbackRef } from "@mantine/hooks";
3
4
  import { IconX } from "@tabler/icons-react";
4
- import { useReducedMotion, AnimatePresence } from "framer-motion";
5
+ import { deepEqual } from "fast-equals";
6
+ import { useReducedMotion } from "framer-motion";
5
7
  import { animate } from "framer-motion/dom";
6
8
  import { memo, useMemo, useEffect } from "react";
7
9
  import { ErrorBoundary } from "react-error-boundary";
8
- import { useDiagramActor, useDiagramActorState } from "../hooks/useDiagramActor.js";
10
+ import { useDiagram } from "../hooks/useDiagram.js";
11
+ import { useDiagramActorState } from "../hooks/useDiagramActor.js";
9
12
  import { ElementDetailsCard } from "./element-details/ElementDetailsCard.js";
10
13
  import { Overlay } from "./overlay/Overlay.js";
11
14
  import { RelationshipDetails } from "./relationship-details/RelationshipDetails.js";
@@ -34,24 +37,32 @@ function Fallback({ error, resetErrorBoundary }) {
34
37
  }
35
38
  ) });
36
39
  }
40
+ const selector = (s) => {
41
+ var _a, _b, _c;
42
+ return {
43
+ relationshipsBrowserActor: s.children.relationshipsBrowser,
44
+ relationshipDetailsActor: s.children.relationshipDetails,
45
+ viewId: s.context.view.id,
46
+ activeElementDetailsOf: ((_a = s.context.activeElementDetails) == null ? void 0 : _a.fqn) ?? null,
47
+ fromNode: ((_b = s.context.activeElementDetails) == null ? void 0 : _b.fromNode) ?? null,
48
+ rectFromNode: ((_c = s.context.activeElementDetails) == null ? void 0 : _c.nodeRectScreen) ?? null
49
+ };
50
+ };
51
+ const equals = (a, b) => a.relationshipDetailsActor == b.relationshipDetailsActor && a.relationshipsBrowserActor == b.relationshipsBrowserActor && a.activeElementDetailsOf === b.activeElementDetailsOf && a.viewId === b.viewId && a.fromNode === b.fromNode && deepEqual(a.rectFromNode, b.rectFromNode);
37
52
  const Overlays = memo(() => {
38
53
  const xyflowDomNode = useXYStore((s) => s.domNode);
39
54
  const xyflowRendererDom = useMemo(() => (xyflowDomNode == null ? void 0 : xyflowDomNode.querySelector(".react-flow__renderer")) ?? null, [
40
55
  xyflowDomNode
41
56
  ]);
42
- const { send } = useDiagramActor();
57
+ const diagram = useDiagram();
43
58
  const {
44
59
  relationshipsBrowserActor,
45
60
  relationshipDetailsActor,
46
- activeElementDetailsOf
47
- } = useDiagramActorState((s) => {
48
- var _a;
49
- return {
50
- relationshipsBrowserActor: s.children.relationshipsBrowser,
51
- relationshipDetailsActor: s.children.relationshipDetails,
52
- activeElementDetailsOf: ((_a = s.context.activeElementDetails) == null ? void 0 : _a.fqn) ?? null
53
- };
54
- });
61
+ activeElementDetailsOf,
62
+ viewId,
63
+ fromNode,
64
+ rectFromNode
65
+ } = useDiagramActorState(selector, equals);
55
66
  const isMotionReduced = useReducedMotion() ?? false;
56
67
  const isActiveOverlay = !!activeElementDetailsOf;
57
68
  useEffect(() => {
@@ -64,13 +75,14 @@ const Overlays = memo(() => {
64
75
  duration: isActiveOverlay ? 0.35 : 0.17
65
76
  });
66
77
  }, [isActiveOverlay, xyflowRendererDom]);
67
- return /* @__PURE__ */ jsx(DiagramFeatures.Overlays, { children: /* @__PURE__ */ jsx(ErrorBoundary, { FallbackComponent: Fallback, onReset: () => send({ type: "close.overlay" }), children: /* @__PURE__ */ jsxs(AnimatePresence, { children: [
78
+ const onClose = useCallbackRef(() => {
79
+ diagram.closeOverlay();
80
+ });
81
+ return /* @__PURE__ */ jsx(DiagramFeatures.Overlays, { children: /* @__PURE__ */ jsxs(ErrorBoundary, { FallbackComponent: Fallback, onReset: onClose, children: [
68
82
  relationshipsBrowserActor && /* @__PURE__ */ jsx(
69
83
  Overlay,
70
84
  {
71
- onClose: () => {
72
- relationshipsBrowserActor.send({ type: "close" });
73
- },
85
+ onClose,
74
86
  children: /* @__PURE__ */ jsx(RelationshipsBrowser, { actorRef: relationshipsBrowserActor })
75
87
  },
76
88
  "relationships-browser"
@@ -78,16 +90,25 @@ const Overlays = memo(() => {
78
90
  relationshipDetailsActor && /* @__PURE__ */ jsx(
79
91
  Overlay,
80
92
  {
81
- onClose: () => {
82
- relationshipDetailsActor.send({ type: "close" });
83
- },
93
+ onClose,
84
94
  children: /* @__PURE__ */ jsx(RelationshipDetails, { actorRef: relationshipDetailsActor })
85
95
  },
86
96
  "relationship-details"
87
97
  ),
88
- activeElementDetailsOf && /* @__PURE__ */ jsx(ElementDetailsCard, { fqn: activeElementDetailsOf })
89
- ] }) }) });
98
+ !!activeElementDetailsOf && /* @__PURE__ */ jsx(
99
+ ElementDetailsCard,
100
+ {
101
+ fqn: activeElementDetailsOf,
102
+ viewId,
103
+ fromNode,
104
+ rectFromNode,
105
+ onClose
106
+ },
107
+ "element-details"
108
+ )
109
+ ] }) });
90
110
  });
111
+ Overlays.displayName = "Overlays";
91
112
  export {
92
113
  Overlays
93
114
  };
@@ -1,7 +1,11 @@
1
- import { Fqn } from '@likec4/core';
2
- import { MemoExoticComponent } from 'react';
1
+ import { Fqn, NodeId, ViewId } from '@likec4/core';
2
+ import { Rect } from '@xyflow/system';
3
3
  type ElementDetailsCardProps = {
4
+ viewId: ViewId;
5
+ fromNode: NodeId | null;
6
+ rectFromNode: Rect | null;
7
+ onClose: () => void;
4
8
  fqn: Fqn;
5
9
  };
6
- export declare const ElementDetailsCard: MemoExoticComponent<({ fqn }: ElementDetailsCardProps) => import("react/jsx-runtime").JSX.Element>;
10
+ export declare function ElementDetailsCard({ viewId, fromNode, rectFromNode, fqn, onClose, }: ElementDetailsCardProps): import("react/jsx-runtime").JSX.Element;
7
11
  export {};
@@ -1,22 +1,21 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { isScopedElementView, isDeploymentView } from "@likec4/core";
3
- import { Divider as Divider$1, Tooltip as Tooltip$1, Text, RemoveScroll, Card, FocusTrap, FocusTrapInitialFocus, Box, Group, CloseButton, Badge, Flex, ActionIconGroup, ActionIcon, Tabs, TabsList, TabsTab, TabsPanel, ScrollArea, Stack, UnstyledButton, ThemeIcon, Code } from "@mantine/core";
4
- import { useViewportSize, useSessionStorage, useDebouncedCallback } from "@mantine/hooks";
3
+ import { RemoveScroll, Card, Box, Group, Text, CloseButton, Badge, Flex, ActionIconGroup, ActionIcon, Tooltip as Tooltip$1, Tabs, TabsList, TabsTab, TabsPanel, ScrollArea, Stack, Divider as Divider$1, Code, UnstyledButton, ThemeIcon } from "@mantine/core";
4
+ import { useViewportSize, useSessionStorage } from "@mantine/hooks";
5
+ import { useSyncedRef, useDebouncedCallback } from "@react-hookz/web";
5
6
  import { IconExternalLink, IconFileSymlink, IconZoomScan, IconStack2 } from "@tabler/icons-react";
6
- import "clsx";
7
7
  import { useDragControls, useMotionValue, m } from "framer-motion";
8
- import { memo, useCallback, useRef, useLayoutEffect } from "react";
8
+ import { useCallback, useRef } from "react";
9
9
  import { pipe, map, partition, only, clamp, isNullish } from "remeda";
10
10
  import { useDiagram } from "../../hooks/useDiagram.js";
11
- import { useDiagramContext } from "../../hooks/useDiagramContext.js";
12
- import { propertyLabel, elementIcon, dialog, card, cardHeader, title, tabsRoot, tabsList, tabsTab, tabsPanel, propertiesGrid, resizeHandle, viewButton, viewButtonTitle } from "./ElementDetailsCard.css.js";
11
+ import { dialog, card, cardHeader, title, tabsPanel, tabsTab, tabsList, tabsRoot, propertiesGrid, resizeHandle, elementIcon, propertyLabel, viewButton, viewButtonTitle } from "./ElementDetailsCard.css.js";
13
12
  import { TabPanelDeployments } from "./TabPanelDeployments.js";
14
13
  import { TabPanelRelationships } from "./TabPanelRelationships.js";
15
14
  import { TabPanelStructure } from "./TabPanelStructure.js";
16
15
  import { useLikeC4Model } from "../../likec4model/useLikeC4Model.js";
17
16
  import { useUpdateEffect } from "../../hooks/useUpdateEffect.js";
18
17
  import { IconRenderer } from "../../context/IconRenderer.js";
19
- import { IfEnabled } from "../../context/DiagramFeatures.js";
18
+ import { IfEnabled, DiagramFeatures } from "../../context/DiagramFeatures.js";
20
19
  import { Link } from "../../base/Link.js";
21
20
  const Divider = Divider$1.withProps({
22
21
  mb: 8,
@@ -47,20 +46,14 @@ const PropertyLabel = Text.withProps({
47
46
  });
48
47
  const MIN_PADDING = 24;
49
48
  const TABS = ["Properties", "Relationships", "Views", "Structure", "Deployments"];
50
- const ElementDetailsCard = memo(({ fqn }) => {
49
+ function ElementDetailsCard({
50
+ viewId,
51
+ fromNode,
52
+ rectFromNode,
53
+ fqn,
54
+ onClose
55
+ }) {
51
56
  var _a, _b, _c;
52
- const {
53
- viewId,
54
- fromNode,
55
- rectFromNode
56
- } = useDiagramContext((s) => {
57
- var _a2, _b2;
58
- return {
59
- viewId: s.view.id,
60
- fromNode: ((_a2 = s.activeElementDetails) == null ? void 0 : _a2.fromNode) ?? null,
61
- rectFromNode: ((_b2 = s.activeElementDetails) == null ? void 0 : _b2.nodeRectScreen) ?? null
62
- };
63
- });
64
57
  const windowSize = useViewportSize();
65
58
  const windowWidth = windowSize.width || window.innerWidth || 1200, windowHeight = windowSize.height || window.innerHeight || 800;
66
59
  const [activeTab, setActiveTab] = useSessionStorage({
@@ -128,15 +121,12 @@ const ElementDetailsCard = memo(({ fqn }) => {
128
121
  height.set(Math.max(height.get() + info.delta.y, 300));
129
122
  }, []);
130
123
  const ref = useRef(null);
131
- useLayoutEffect(() => {
132
- var _a2;
133
- (_a2 = ref.current) == null ? void 0 : _a2.showModal();
134
- }, []);
135
- const diagramApi = useDiagram();
124
+ const onCloseRef = useSyncedRef(onClose);
136
125
  const close = useDebouncedCallback(
137
126
  () => {
138
- diagramApi.closeOverlay();
127
+ onCloseRef.current();
139
128
  },
129
+ [],
140
130
  50
141
131
  );
142
132
  const notation = (nodeModel == null ? void 0 : nodeModel.$node.notation) ?? null;
@@ -153,7 +143,6 @@ const ElementDetailsCard = memo(({ fqn }) => {
153
143
  {
154
144
  ref,
155
145
  className: dialog,
156
- layoutRoot: true,
157
146
  initial: {
158
147
  "--backdrop-blur": "0px",
159
148
  "--backdrop-opacity": "10%"
@@ -169,6 +158,10 @@ const ElementDetailsCard = memo(({ fqn }) => {
169
158
  duration: 0.1
170
159
  }
171
160
  },
161
+ onAnimationStart: () => {
162
+ var _a2;
163
+ (_a2 = ref.current) == null ? void 0 : _a2.showModal();
164
+ },
172
165
  onClick: (e) => {
173
166
  var _a2, _b2;
174
167
  if (((_b2 = (_a2 = e.target) == null ? void 0 : _a2.nodeName) == null ? void 0 : _b2.toUpperCase()) === "DIALOG") {
@@ -180,7 +173,7 @@ const ElementDetailsCard = memo(({ fqn }) => {
180
173
  e.stopPropagation();
181
174
  close();
182
175
  },
183
- children: /* @__PURE__ */ jsx(RemoveScroll, { forwardProps: true, children: /* @__PURE__ */ jsx(
176
+ children: /* @__PURE__ */ jsx(RemoveScroll, { forwardProps: true, children: /* @__PURE__ */ jsxs(
184
177
  Card,
185
178
  {
186
179
  drag: true,
@@ -192,7 +185,6 @@ const ElementDetailsCard = memo(({ fqn }) => {
192
185
  shadow: "md",
193
186
  component: m.div,
194
187
  className: card,
195
- layoutId: fqn,
196
188
  initial: {
197
189
  top,
198
190
  left,
@@ -221,8 +213,7 @@ const ElementDetailsCard = memo(({ fqn }) => {
221
213
  height
222
214
  },
223
215
  "data-likec4-color": (nodeModel == null ? void 0 : nodeModel.color) ?? elementModel.color,
224
- children: /* @__PURE__ */ jsxs(FocusTrap, { children: [
225
- /* @__PURE__ */ jsx(FocusTrapInitialFocus, {}),
216
+ children: [
226
217
  /* @__PURE__ */ jsxs(
227
218
  Box,
228
219
  {
@@ -349,12 +340,21 @@ const ElementDetailsCard = memo(({ fqn }) => {
349
340
  ] }),
350
341
  elementModel.$element.metadata && /* @__PURE__ */ jsx(ElementMetata, { value: elementModel.$element.metadata })
351
342
  ] }) }) }),
352
- /* @__PURE__ */ jsx(TabsPanel, { value: "Relationships", children: nodeModel && activeTab === "Relationships" && /* @__PURE__ */ jsx(
353
- TabPanelRelationships,
343
+ /* @__PURE__ */ jsx(TabsPanel, { value: "Relationships", children: /* @__PURE__ */ jsx(
344
+ DiagramFeatures,
354
345
  {
355
- element: elementModel,
356
- node: nodeModel,
357
- currentView: diagram.currentView()
346
+ overrides: {
347
+ enableRelationshipBrowser: false,
348
+ enableNavigateTo: false
349
+ },
350
+ children: !!nodeModel && activeTab === "Relationships" && /* @__PURE__ */ jsx(
351
+ TabPanelRelationships,
352
+ {
353
+ element: elementModel,
354
+ node: nodeModel,
355
+ currentView: diagram.currentView()
356
+ }
357
+ )
358
358
  }
359
359
  ) }),
360
360
  /* @__PURE__ */ jsx(TabsPanel, { value: "Views", children: /* @__PURE__ */ jsx(ScrollArea, { scrollbars: "y", type: "auto", children: /* @__PURE__ */ jsxs(Stack, { gap: "lg", children: [
@@ -397,13 +397,12 @@ const ElementDetailsCard = memo(({ fqn }) => {
397
397
  dragConstraints: { top: 0, left: 0, right: 0, bottom: 0 }
398
398
  }
399
399
  )
400
- ] })
400
+ ]
401
401
  }
402
402
  ) })
403
403
  }
404
404
  );
405
- });
406
- ElementDetailsCard.displayName = "ElementDetailsCard";
405
+ }
407
406
  const ViewButton = ({
408
407
  view,
409
408
  onNavigateTo
@@ -4,7 +4,7 @@ import { IconInfoCircle, IconTarget, IconZoomScan } from "@tabler/icons-react";
4
4
  import { memo, useMemo, useEffect } from "react";
5
5
  import { useCurrentViewId } from "../../hooks/useCurrentViewId.js";
6
6
  import { useLikeC4Model } from "../../likec4model/useLikeC4Model.js";
7
- import { treeNode, treeNodeLabel, nodeLabel, instanceLabel } from "./TabPanelDeployments.css.js";
7
+ import { treeNodeLabel, treeNode, nodeLabel, instanceLabel } from "./TabPanelDeployments.css.js";
8
8
  import { stopPropagation } from "../../utils/xyflow.js";
9
9
  const DeploymentNodeRenderer = ({
10
10
  node
@@ -1,27 +1,23 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import { nameFromFqn } from "@likec4/core";
3
3
  import { Stack, Group, Box, ThemeIcon, Text, Paper } from "@mantine/core";
4
- import { useId } from "@mantine/hooks";
5
4
  import { IconArrowRight, IconInfoCircle } from "@tabler/icons-react";
6
5
  import { useActorRef } from "@xstate/react";
7
- import { LayoutGroup } from "framer-motion";
8
- import { useState, memo } from "react";
6
+ import { useState } from "react";
9
7
  import { unique } from "remeda";
10
8
  import { relationshipsBrowserActor } from "../relationships-browser/actor.js";
11
9
  import { RelationshipsBrowser } from "../relationships-browser/RelationshipsBrowser.js";
12
10
  import { fqn, xyflow, relationshipStat } from "./TabPanelRelationships.css.js";
13
- import { DiagramFeatures } from "../../context/DiagramFeatures.js";
14
11
  function TabPanelRelationships({
15
12
  currentView,
16
13
  node,
17
14
  element
18
15
  }) {
19
- const layoutId = useId();
20
- useState("view");
16
+ const [scope, setScope] = useState("view");
21
17
  const incoming = [...element.incoming()].map((r) => r.id);
22
18
  const outgoing = [...element.outgoing()].map((r) => r.id);
23
- const incomingInView = unique(node.incoming().flatMap((e) => e.$edge.relations).toArray());
24
- const outgoingInView = unique(node.outgoing().flatMap((e) => e.$edge.relations).toArray());
19
+ const incomingInView = unique([...node.incoming()].flatMap((e) => e.$edge.relations));
20
+ const outgoingInView = unique([...node.outgoing()].flatMap((e) => e.$edge.relations));
25
21
  const notIncludedRelations = [
26
22
  ...incoming,
27
23
  ...outgoing
@@ -68,7 +64,7 @@ function TabPanelRelationships({
68
64
  }
69
65
  )
70
66
  ] }),
71
- /* @__PURE__ */ jsx(Box, { className: xyflow, children: /* @__PURE__ */ jsx(LayoutGroup, { id: layoutId, children: /* @__PURE__ */ jsx(EmbeddedRelationshipsBrowser, { subjectId: element.id, currentView }) }) })
67
+ /* @__PURE__ */ jsx(Box, { className: xyflow, children: /* @__PURE__ */ jsx(EmbeddedRelationshipsBrowser, { subjectId: element.id, currentView }) })
72
68
  ] });
73
69
  }
74
70
  function RelationshipsStat({
@@ -100,29 +96,17 @@ function RelationshipsStat({
100
96
  }
101
97
  );
102
98
  }
103
- const EmbeddedRelationshipsBrowser = memo(
104
- ({ subjectId, currentView }) => {
105
- const actor = useActorRef(relationshipsBrowserActor, {
106
- input: {
107
- subject: subjectId,
108
- scope: currentView,
109
- closeable: false,
110
- enableNavigationMenu: false
111
- }
112
- });
113
- return /* @__PURE__ */ jsx(
114
- DiagramFeatures,
115
- {
116
- overrides: {
117
- enableRelationshipBrowser: false,
118
- enableNavigateTo: false
119
- },
120
- children: /* @__PURE__ */ jsx(RelationshipsBrowser, { actorRef: actor })
121
- }
122
- );
123
- },
124
- (prev, next) => prev.subjectId === next.subjectId
125
- );
99
+ const EmbeddedRelationshipsBrowser = ({ subjectId, currentView }) => {
100
+ const actor = useActorRef(relationshipsBrowserActor, {
101
+ input: {
102
+ subject: subjectId,
103
+ scope: currentView,
104
+ closeable: false,
105
+ enableNavigationMenu: false
106
+ }
107
+ });
108
+ return /* @__PURE__ */ jsx(RelationshipsBrowser, { actorRef: actor });
109
+ };
126
110
  export {
127
111
  TabPanelRelationships
128
112
  };
@@ -2,12 +2,12 @@ import "../../node_modules/@mantine/core/esm/components/ScrollArea/ScrollArea.mo
2
2
  import "../../node_modules/@mantine/core/esm/components/UnstyledButton/UnstyledButton.module.css.mjs.vanilla.css.js";
3
3
  import "../../node_modules/@mantine/core/esm/components/VisuallyHidden/VisuallyHidden.module.css.mjs.vanilla.css.js";
4
4
  import "../../node_modules/@mantine/core/esm/components/Paper/Paper.module.css.mjs.vanilla.css.js";
5
+ import "../../node_modules/@mantine/core/esm/components/Overlay/Overlay.module.css.mjs.vanilla.css.js";
5
6
  import "../../node_modules/@mantine/core/esm/components/Popover/Popover.module.css.mjs.vanilla.css.js";
6
7
  import "../../node_modules/@mantine/core/esm/components/Loader/Loader.module.css.mjs.vanilla.css.js";
7
8
  import "../../node_modules/@mantine/core/esm/components/ActionIcon/ActionIcon.module.css.mjs.vanilla.css.js";
8
9
  import "../../node_modules/@mantine/core/esm/components/CloseButton/CloseButton.module.css.mjs.vanilla.css.js";
9
10
  import "../../node_modules/@mantine/core/esm/components/Group/Group.module.css.mjs.vanilla.css.js";
10
- import "../../node_modules/@mantine/core/esm/components/Overlay/Overlay.module.css.mjs.vanilla.css.js";
11
11
  import "../../node_modules/@mantine/core/esm/components/ModalBase/ModalBase.module.css.mjs.vanilla.css.js";
12
12
  import "../../node_modules/@mantine/core/esm/components/Input/Input.module.css.mjs.vanilla.css.js";
13
13
  import "../../node_modules/@mantine/core/esm/components/Flex/Flex.module.css.mjs.vanilla.css.js";
@@ -78,6 +78,7 @@ import "../../node_modules/@mantine/core/esm/components/Stack/Stack.module.css.m
78
78
  import "../../node_modules/@mantine/core/esm/components/Stepper/Stepper.module.css.mjs.vanilla.css.js";
79
79
  import "../../node_modules/@mantine/core/esm/components/Switch/Switch.module.css.mjs.vanilla.css.js";
80
80
  import "../../node_modules/@mantine/core/esm/components/Table/Table.module.css.mjs.vanilla.css.js";
81
+ import "../../node_modules/@mantine/core/esm/components/TableOfContents/TableOfContents.module.css.mjs.vanilla.css.js";
81
82
  import "../../node_modules/@mantine/core/esm/components/Tabs/Tabs.module.css.mjs.vanilla.css.js";
82
83
  import "../../node_modules/@mantine/core/esm/components/ThemeIcon/ThemeIcon.module.css.mjs.vanilla.css.js";
83
84
  import "../../node_modules/@mantine/core/esm/components/Timeline/Timeline.module.css.mjs.vanilla.css.js";
@@ -5,7 +5,7 @@ import { useSyncedRef, useDebouncedCallback } from "@react-hookz/web";
5
5
  import clsx from "clsx";
6
6
  import { m } from "framer-motion";
7
7
  import { forwardRef, useState, useRef, useLayoutEffect } from "react";
8
- import { dialog, body } from "./Overlay.css.js";
8
+ import { body, dialog } from "./Overlay.css.js";
9
9
  const Overlay = forwardRef(({ children, onClose, className, ...rest }, ref) => {
10
10
  const [opened, setOpened] = useState(false);
11
11
  const dialogRef = useRef(null);
@@ -21,7 +21,7 @@ const Overlay = forwardRef(({ children, onClose, className, ...rest }, ref) => {
21
21
  var _a;
22
22
  const cancel = (e) => {
23
23
  e.preventDefault();
24
- close();
24
+ onCloseRef.current();
25
25
  };
26
26
  (_a = dialogRef.current) == null ? void 0 : _a.addEventListener("cancel", cancel, { capture: true });
27
27
  return () => {
@@ -1,7 +1,7 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import "@likec4/core";
3
3
  import { useComputedColorScheme, Popover, PopoverTarget, Button, Box, Text, ThemeIcon, PopoverDropdown, ScrollAreaAutosize } from "@mantine/core";
4
- import { IconSelector, IconArrowRight } from "@tabler/icons-react";
4
+ import { IconArrowRight, IconSelector } from "@tabler/icons-react";
5
5
  import { useRef } from "react";
6
6
  import { useRelationshipDetails } from "./hooks.js";
7
7
  import { edgeSource, edgeTarget, scrollArea, edgeGrid, edgeRow, edgeArrow, edgeLabel } from "./SelectEdge.css.js";
@@ -1,4 +1,4 @@
1
- import { Color, DiagramNode, Fqn, RelationId, RelationshipLineType, ViewId } from '@likec4/core';
1
+ import { Color, DiagramNode, Fqn, IconUrl, RelationId, RelationshipLineType, ViewId } from '@likec4/core';
2
2
  import { Base, NonOptional, ReactFlowEdge, ReactFlowNode } from '../../base/types';
3
3
  export declare namespace RelationshipDetailsTypes {
4
4
  /**
@@ -10,13 +10,13 @@ export declare namespace RelationshipDetailsTypes {
10
10
  };
11
11
  type ElementNodeData = Base.NodeData<NonOptional<Pick<DiagramNode, 'title' | 'technology' | 'description' | 'color' | 'shape' | 'width' | 'height' | 'navigateTo' | 'style'>> & {
12
12
  fqn: Fqn;
13
- icon: string | null;
13
+ icon: IconUrl;
14
14
  ports: Ports;
15
15
  }>;
16
16
  type CompoundNodeData = Base.NodeData<NonOptional<Pick<DiagramNode, 'title' | 'color' | 'shape' | 'style'>> & {
17
17
  fqn: Fqn;
18
18
  depth: number;
19
- icon: string | null;
19
+ icon?: IconUrl;
20
20
  ports: Ports;
21
21
  }>;
22
22
  type ElementNode = ReactFlowNode<ElementNodeData, 'element'>;
@@ -1,7 +1,7 @@
1
1
  import { invariant } from "@likec4/core";
2
2
  import "@xyflow/react";
3
3
  import { prop } from "remeda";
4
- import { setup, assign, raise, cancel } from "xstate";
4
+ import { setup, cancel, raise, assign } from "xstate";
5
5
  import { MinZoom } from "../../base/const.js";
6
6
  const relationshipDetailsActor = setup({
7
7
  types: {
@@ -1,7 +1,7 @@
1
1
  import { NodeProps } from '../../../base';
2
2
  import { RelationshipDetailsTypes } from '../_types';
3
3
  import { NamedExoticComponent } from 'react';
4
- import { ElementStyle, Color, ViewId, Fqn } from '@likec4/core';
4
+ import { ElementStyle, Color, ViewId, Fqn, IconUrl } from '@likec4/core';
5
5
  export declare const nodeTypes: {
6
6
  element: NamedExoticComponent<NodeProps<{
7
7
  style: ElementStyle;
@@ -14,7 +14,7 @@ export declare const nodeTypes: {
14
14
  color: Color;
15
15
  navigateTo: ViewId<string> | null | undefined;
16
16
  fqn: Fqn;
17
- icon: string | null;
17
+ icon: IconUrl;
18
18
  ports: RelationshipDetailsTypes.Ports;
19
19
  hovered?: boolean;
20
20
  dimmed?: import("../../../base").Base.Dimmed;
@@ -26,7 +26,7 @@ export declare const nodeTypes: {
26
26
  color: Color;
27
27
  fqn: Fqn;
28
28
  depth: number;
29
- icon: string | null;
29
+ icon?: IconUrl;
30
30
  ports: RelationshipDetailsTypes.Ports;
31
31
  hovered?: boolean;
32
32
  dimmed?: import("../../../base").Base.Dimmed;
@@ -3,11 +3,11 @@ import { ElementActions } from "./ElementActions.js";
3
3
  import { Handle } from "@xyflow/react";
4
4
  import { Position } from "@xyflow/system";
5
5
  import { customNode } from "../../../base/primitives/customNode.js";
6
+ import { CompoundNodeContainer } from "../../../base/primitives/compound/CompoundNodeContainer.js";
7
+ import { CompoundTitle } from "../../../base/primitives/compound/CompoundTitle.js";
6
8
  import { ElementNodeContainer } from "../../../base/primitives/element/ElementNodeContainer.js";
7
9
  import { ElementShape } from "../../../base/primitives/element/ElementShape.js";
8
10
  import { ElementTitle } from "../../../base/primitives/element/ElementTitle.js";
9
- import { CompoundNodeContainer } from "../../../base/primitives/compound/CompoundNodeContainer.js";
10
- import { CompoundTitle } from "../../../base/primitives/compound/CompoundTitle.js";
11
11
  const nodeTypes = {
12
12
  element: customNode((props) => {
13
13
  return /* @__PURE__ */ jsxs(ElementNodeContainer, { nodeProps: props, children: [
@@ -16,9 +16,6 @@ const Sizes = {
16
16
  },
17
17
  nodeWidth: 330,
18
18
  hodeHeight: 180,
19
- // Spacer between elements in a compound node
20
- // 0 means no spacer
21
- spacerHeight: 0,
22
19
  compoundLabelHeight: 5
23
20
  };
24
21
  const ZIndexes = {
@@ -64,7 +61,7 @@ function nodeData(element, ctx) {
64
61
  description: (diagramNode == null ? void 0 : diagramNode.description) ?? element.description,
65
62
  color: (diagramNode == null ? void 0 : diagramNode.color) ?? (ancestor == null ? void 0 : ancestor.color) ?? element.color,
66
63
  shape: (diagramNode == null ? void 0 : diagramNode.shape) ?? element.shape,
67
- icon: (diagramNode == null ? void 0 : diagramNode.icon) ?? element.icon,
64
+ icon: (diagramNode == null ? void 0 : diagramNode.icon) ?? element.icon ?? "none",
68
65
  style: (diagramNode == null ? void 0 : diagramNode.style) ?? element.$element.style ?? {},
69
66
  navigateTo: (diagramNode == null ? void 0 : diagramNode.navigateTo) ?? ((_a = first(element.scopedViews().take(1).toArray())) == null ? void 0 : _a.id) ?? null,
70
67
  width: 0,
@@ -18,9 +18,6 @@ const Sizes = {
18
18
  emptyNodeOffset: 120,
19
19
  nodeWidth: 330,
20
20
  nodeHeight: 180,
21
- // Spacer between elements in a compound node
22
- // 0 means no spacer
23
- spacerHeight: 0,
24
21
  compound: {
25
22
  labelHeight: 2,
26
23
  paddingTop: 50,
@@ -5,7 +5,7 @@ import { IconX, IconChevronLeft, IconChevronRight } from "@tabler/icons-react";
5
5
  import { ReactFlowProvider, useStoreApi, Panel } from "@xyflow/react";
6
6
  import clsx from "clsx";
7
7
  import { shallowEqual } from "fast-equals";
8
- import { LayoutGroup, AnimatePresence, m } from "framer-motion";
8
+ import { AnimatePresence, m } from "framer-motion";
9
9
  import { useRef, memo, useEffect } from "react";
10
10
  import { BaseXYFlow } from "../../base/BaseXYFlow.js";
11
11
  import { useRelationshipsView } from "./-useRelationshipsView.js";
@@ -43,7 +43,7 @@ const RelationshipsBrowserXYFlow = memo(() => {
43
43
  selector,
44
44
  selectorEq
45
45
  );
46
- return /* @__PURE__ */ jsx(LayoutGroup, { children: /* @__PURE__ */ jsx(
46
+ return /* @__PURE__ */ jsx(
47
47
  BaseXYFlow,
48
48
  {
49
49
  id: "relationships-browser",
@@ -87,7 +87,7 @@ const RelationshipsBrowserXYFlow = memo(() => {
87
87
  zoomable: true,
88
88
  children: initialized && /* @__PURE__ */ jsx(RelationshipsBrowserInner, {})
89
89
  }
90
- ) });
90
+ );
91
91
  });
92
92
  const selector2 = (state) => ({
93
93
  subjectId: state.context.subject,