@likec4/diagram 1.20.3 → 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 (90) 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/useViewToNodesEdges.js +1 -1
  44. package/dist/overlays/Overlays.js +42 -21
  45. package/dist/overlays/element-details/ElementDetailsCard.d.ts +7 -3
  46. package/dist/overlays/element-details/ElementDetailsCard.js +38 -39
  47. package/dist/overlays/element-details/TabPanelDeployments.js +1 -1
  48. package/dist/overlays/element-details/TabPanelRelationships.js +14 -30
  49. package/dist/overlays/overlay/Overlay.css.js +2 -1
  50. package/dist/overlays/overlay/Overlay.js +2 -2
  51. package/dist/overlays/relationship-details/SelectEdge.js +1 -1
  52. package/dist/overlays/relationship-details/_types.d.ts +3 -3
  53. package/dist/overlays/relationship-details/actor.js +1 -1
  54. package/dist/overlays/relationship-details/custom/nodeTypes.d.ts +3 -3
  55. package/dist/overlays/relationship-details/custom/nodeTypes.js +2 -2
  56. package/dist/overlays/relationship-details/useLayoutedDetails.js +1 -4
  57. package/dist/overlays/relationships-browser/-useRelationshipsView.js +0 -3
  58. package/dist/overlays/relationships-browser/RelationshipsBrowser.js +3 -3
  59. package/dist/overlays/relationships-browser/_types.d.ts +3 -3
  60. package/dist/overlays/relationships-browser/actor.js +16 -16
  61. package/dist/overlays/relationships-browser/custom/nodeTypes.d.ts +3 -2
  62. package/dist/overlays/relationships-browser/custom/nodeTypes.js +3 -3
  63. package/dist/overlays/relationships-browser/useViewToNodesEdges.js +3 -2
  64. package/dist/style.css +1 -1
  65. package/package.json +12 -12
  66. package/src/base/example/_types.ts +3 -2
  67. package/src/base/example/useViewToNodesEdges.ts +2 -1
  68. package/src/base/primitives/compound/CompoundTitle.css.ts +27 -1
  69. package/src/base/primitives/compound/CompoundTitle.tsx +12 -2
  70. package/src/base/primitives/element/ElementNodeContainer.tsx +21 -1
  71. package/src/base/primitives/element/ElementShape.css.ts +5 -0
  72. package/src/base/primitives/element/ElementTitle.css.ts +17 -24
  73. package/src/base/primitives/element/ElementTitle.tsx +4 -2
  74. package/src/base/primitives/element/styles.css.ts +74 -0
  75. package/src/hooks/useDiagram.ts +1 -1
  76. package/src/likec4diagram/DiagramUI.tsx +2 -2
  77. package/src/likec4diagram/XYFlow.tsx +2 -2
  78. package/src/likec4diagram/custom/edges/RelationshipsDropdownMenu.tsx +3 -2
  79. package/src/likec4diagram/types.ts +2 -2
  80. package/src/likec4diagram/useViewToNodesEdges.ts +1 -1
  81. package/src/overlays/Overlays.tsx +61 -281
  82. package/src/overlays/element-details/ElementDetailsCard.tsx +213 -257
  83. package/src/overlays/element-details/TabPanelRelationships.tsx +13 -75
  84. package/src/overlays/overlay/Overlay.tsx +1 -1
  85. package/src/overlays/relationship-details/_types.ts +3 -3
  86. package/src/overlays/relationship-details/useLayoutedDetails.ts +1 -1
  87. package/src/overlays/relationships-browser/RelationshipsBrowser.tsx +44 -55
  88. package/src/overlays/relationships-browser/_types.ts +12 -2
  89. package/src/overlays/relationships-browser/actor.ts +11 -10
  90. package/src/overlays/relationships-browser/useViewToNodesEdges.ts +2 -1
@@ -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,23 +1,19 @@
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
19
  const incomingInView = unique([...node.incoming()].flatMap((e) => e.$edge.relations));
@@ -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,
@@ -1,4 +1,4 @@
1
- import { Color, DiagramNode, Fqn, NonEmptyArray, RelationId, RelationshipLineType, ViewId } from '@likec4/core';
1
+ import { Color, DiagramNode, Fqn, IconUrl, NonEmptyArray, RelationId, RelationshipLineType, ViewId } from '@likec4/core';
2
2
  import { Base, NonOptional, ReactFlowEdge, ReactFlowNode } from '../../base/types';
3
3
  export declare namespace RelationshipsBrowserTypes {
4
4
  type Column = 'incomers' | 'subjects' | 'outgoers';
@@ -9,7 +9,7 @@ export declare namespace RelationshipsBrowserTypes {
9
9
  in: string[];
10
10
  out: string[];
11
11
  };
12
- type ElementNodeData = Base.NodeData<NonOptional<Pick<DiagramNode, 'title' | 'technology' | 'description' | 'color' | 'shape' | 'width' | 'height' | 'navigateTo'>> & {
12
+ type ElementNodeData = Base.NodeData<NonOptional<Pick<DiagramNode, 'title' | 'technology' | 'description' | 'color' | 'shape' | 'style' | 'width' | 'height' | 'navigateTo'>> & {
13
13
  column: Column;
14
14
  fqn: Fqn;
15
15
  icon: string | null;
@@ -19,7 +19,7 @@ export declare namespace RelationshipsBrowserTypes {
19
19
  column: Column;
20
20
  fqn: Fqn;
21
21
  depth: number;
22
- icon: string | null;
22
+ icon: IconUrl;
23
23
  ports: Ports;
24
24
  }>;
25
25
  type ElementNode = ReactFlowNode<ElementNodeData, 'element'>;
@@ -1,8 +1,8 @@
1
- import { invariant, nonNullable, delay } from "@likec4/core";
2
- import { applyNodeChanges, applyEdgeChanges } from "@xyflow/react";
1
+ import { nonNullable, delay, invariant } from "@likec4/core";
2
+ import { applyEdgeChanges, applyNodeChanges } from "@xyflow/react";
3
3
  import { getViewportForBounds, getNodeDimensions } from "@xyflow/system";
4
4
  import { omit, prop, isNullish } from "remeda";
5
- import { setup, fromPromise, assign, raise, enqueueActions, cancel } from "xstate";
5
+ import { setup, fromPromise, assign, stopChild, cancel, raise, enqueueActions } from "xstate";
6
6
  import { MinZoom, ZIndexes } from "../../base/const.js";
7
7
  import { updateEdges } from "../../base/updateEdges.js";
8
8
  import { updateNodes } from "../../base/updateNodes.js";
@@ -65,8 +65,7 @@ const relationshipsBrowserActor = setup({
65
65
  }
66
66
  },
67
67
  guards: {
68
- "enable: navigate.to": () => true,
69
- "closeable": ({ context }) => context.closeable
68
+ "enable: navigate.to": () => true
70
69
  },
71
70
  actors: {
72
71
  layouter: fromPromise(async ({ input, self, signal }) => {
@@ -79,8 +78,6 @@ const relationshipsBrowserActor = setup({
79
78
  } = input;
80
79
  let {
81
80
  nodes: currentNodes,
82
- setNodes,
83
- setEdges,
84
81
  width,
85
82
  height
86
83
  } = xystore.getState();
@@ -165,7 +162,7 @@ const relationshipsBrowserActor = setup({
165
162
  zoom,
166
163
  nextviewport.zoom
167
164
  );
168
- await delay(180);
165
+ await delay(175);
169
166
  next.xynodes = next.xynodes.map(Base.setDimmed(false));
170
167
  if (signal.aborted) {
171
168
  return updateXYData();
@@ -320,18 +317,21 @@ const relationshipsBrowserActor = setup({
320
317
  ]
321
318
  },
322
319
  "close": {
323
- guard: "closeable",
324
320
  target: "closed"
325
321
  }
326
- },
327
- exit: assign({
328
- initialized: false,
329
- xyflow: null,
330
- xystore: null
331
- })
322
+ }
332
323
  },
333
324
  "closed": {
334
- type: "final"
325
+ id: "closed",
326
+ type: "final",
327
+ entry: [
328
+ stopChild("layouter"),
329
+ assign({
330
+ initialized: false,
331
+ xyflow: null,
332
+ xystore: null
333
+ })
334
+ ]
335
335
  }
336
336
  },
337
337
  on: {