@likec4/diagram 1.7.4 → 1.8.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.
@@ -1,4 +1,4 @@
1
1
  import { LikeC4DiagramEventHandlers, LikeC4DiagramProperties } from './LikeC4Diagram.props';
2
2
 
3
3
  export type LikeC4DiagramProps = LikeC4DiagramProperties & LikeC4DiagramEventHandlers;
4
- export declare function LikeC4Diagram({ view, className, fitView, fitViewPadding, readonly, pannable, zoomable, nodesSelectable, nodesDraggable, background, controls, showElementLinks, showDiagramTitle, enableDynamicViewWalkthrough, enableFocusMode, initialWidth, initialHeight, keepAspectRatio, experimentalEdgeEditing, onCanvasClick, onCanvasContextMenu, onCanvasDblClick, onEdgeClick, onChange, onEdgeContextMenu, onNavigateTo, onNodeClick, onNodeContextMenu, onOpenSourceElement, onOpenSourceView, onOpenSourceRelation, onBurgerMenuClick, renderIcon, where, showNavigationButtons }: LikeC4DiagramProps): import("react/jsx-runtime").JSX.Element;
4
+ export declare function LikeC4Diagram({ view, className, fitView, fitViewPadding, readonly, pannable, zoomable, nodesSelectable, nodesDraggable, background, controls, showElementLinks, showDiagramTitle, showNotations, enableDynamicViewWalkthrough, enableFocusMode, initialWidth, initialHeight, keepAspectRatio, experimentalEdgeEditing, onCanvasClick, onCanvasContextMenu, onCanvasDblClick, onEdgeClick, onChange, onEdgeContextMenu, onNavigateTo, onNodeClick, onNodeContextMenu, onOpenSourceElement, onOpenSourceView, onOpenSourceRelation, onBurgerMenuClick, renderIcon, where, showNavigationButtons }: LikeC4DiagramProps): import("react/jsx-runtime").JSX.Element;
@@ -140,6 +140,11 @@ export interface LikeC4DiagramProperties {
140
140
  * @default false
141
141
  */
142
142
  showNavigationButtons?: undefined | boolean;
143
+ /**
144
+ * Display notations of the view
145
+ * @default true
146
+ */
147
+ showNotations?: boolean | undefined;
143
148
  /**
144
149
  * If double click on a node should enable focus mode, i.e. highlight incoming/outgoing edges
145
150
  * @default true
package/dist/index.mjs CHANGED
@@ -12,16 +12,16 @@ import { invariant, hasAtLeast, whereOperatorAsPredicate, extractStep, nonNullab
12
12
  import { useFirstMountState, useCustomCompareEffect, useDebouncedEffect } from "@react-hookz/web";
13
13
  import { getNodeDimensions, getBoundsOfRects, boxToRect, getViewportForBounds as getViewportForBounds$1 } from "@xyflow/system";
14
14
  import { DEV } from "esm-env";
15
- import { isArray, hasAtLeast as hasAtLeast$1, isNullish, entries, reduce, isTruthy, first, last, clamp, isNumber, isNonNullish, keys, takeWhile } from "remeda";
15
+ import { isArray, hasAtLeast as hasAtLeast$1, isNullish, entries, reduce, map, prop, isTruthy, first, last, clamp, isNumber, isNonNullish, ceil, keys, takeWhile } from "remeda";
16
16
  import { subscribeWithSelector, devtools } from "zustand/middleware";
17
17
  import { shallow } from "zustand/shallow";
18
18
  import { Bezier } from "bezier-js";
19
- import { MantineContext, Box, ActionIcon as ActionIcon$2, Text as Text$1, HoverCard, HoverCardTarget, UnstyledButton, HoverCardDropdown, Stack, Group, Anchor, CopyButton, Button, Card, CardSection, Spoiler, ButtonGroup, rem, Divider, Space, TooltipGroup, Flex, Tooltip as Tooltip$2, ColorSwatch, CheckIcon, Select, Slider, SegmentedControl, Popover, PopoverTarget, PopoverDropdown, FloatingIndicator, Notification, Code } from "@mantine/core";
19
+ import { MantineContext, Box, ActionIcon as ActionIcon$2, Text as Text$1, HoverCard, HoverCardTarget, UnstyledButton, HoverCardDropdown, Stack, Group, Anchor, CopyButton, Button, Card, CardSection, Spoiler, ButtonGroup, Tooltip as Tooltip$2, ThemeIcon, Paper, Tabs, TabsList, TabsTab, TabsPanel, ScrollAreaAutosize, Badge, rem, Divider, Space, TooltipGroup, Flex, ColorSwatch, CheckIcon, Select, Slider, SegmentedControl, Popover, PopoverTarget, PopoverDropdown, FloatingIndicator, Notification, Code } from "@mantine/core";
20
20
  import { useHotkeys, useLocalStorage } from "@mantine/hooks";
21
21
  import { assignInlineVars } from "@vanilla-extract/dynamic";
22
22
  import { line, curveCatmullRomOpen } from "d3-shape";
23
23
  import { Solver, Operator, Expression, Strength, Variable } from "@lume/kiwi";
24
- import { IconZoomScan, IconLink, IconMenu, IconPlayerPlayFilled, IconPlayerSkipBackFilled, IconPlayerStopFilled, IconPlayerSkipForwardFilled, IconFileSymlink, IconLayoutDashboard, IconArrowBigDownLines, IconFocusCentered, IconMenu2, IconChevronLeft, IconChevronRight, IconAlertTriangle } from "@tabler/icons-react";
24
+ import { IconZoomScan, IconLink, IconMenu, IconPlayerPlayFilled, IconPlayerSkipBackFilled, IconPlayerStopFilled, IconPlayerSkipForwardFilled, IconAlertTriangle, IconHelpCircle, IconArrowDownRight, IconFileSymlink, IconLayoutDashboard, IconArrowBigDownLines, IconFocusCentered, IconMenu2, IconChevronLeft, IconChevronRight } from "@tabler/icons-react";
25
25
  var rootClassName = "likec4-diagram-root";
26
26
  const noop = () => {
27
27
  }, depsShallowEqual = (d1, d2) => {
@@ -103,9 +103,9 @@ function diagramViewToXYFlowData(view, opts) {
103
103
  const ns = "", nodeById = (id) => nonNullable(nodeLookup.get(id), `Node not found: ${id}`);
104
104
  let next;
105
105
  for (; next = traverse.shift(); ) {
106
- const { node, parent } = next;
107
- node.children.length > 0 && traverse.push(...node.children.map((child) => ({ node: nodeById(child), parent: node })));
108
- const isCompound = hasAtLeast$1(node.children, 1), position = {
106
+ const { node, parent } = next, isCompound = hasAtLeast$1(node.children, 1);
107
+ isCompound && traverse.push(...node.children.map((child) => ({ node: nodeById(child), parent: node })));
108
+ const position = {
109
109
  x: node.position[0],
110
110
  y: node.position[1]
111
111
  };
@@ -120,6 +120,7 @@ function diagramViewToXYFlowData(view, opts) {
120
120
  },
121
121
  draggable,
122
122
  selectable: opts.selectable,
123
+ focusable: opts.selectable && !isCompound,
123
124
  deletable: !1,
124
125
  position,
125
126
  zIndex: isCompound ? ZIndexes.Compound : ZIndexes.Element,
@@ -137,7 +138,11 @@ function diagramViewToXYFlowData(view, opts) {
137
138
  }
138
139
  for (const edge of view.edges) {
139
140
  const source = edge.source, target = edge.target, id = ns + edge.id;
140
- invariant(hasAtLeast$1(edge.points, 2), "edge should have at least 2 points"), xyedges.push({
141
+ if (!hasAtLeast$1(edge.points, 2)) {
142
+ console.error("edge should have at least 2 points", edge);
143
+ continue;
144
+ }
145
+ xyedges.push({
141
146
  id,
142
147
  type: "relationship",
143
148
  source: ns + source,
@@ -650,6 +655,13 @@ function createDiagramStore(props) {
650
655
  noReplace,
651
656
  "onInit"
652
657
  );
658
+ },
659
+ highlightByElementNotation: (notation, onlyOfKind) => {
660
+ const { xynodes: xynodes2, xyedges: xyedges2 } = get(), dimmed2 = new StringSet(map(xyedges2, prop("id")));
661
+ xynodes2.forEach(({ id, data }) => {
662
+ const node = data.element;
663
+ (node.shape !== notation.shape || node.color !== notation.color || !notation.kinds.includes(node.kind) || onlyOfKind && node.kind !== onlyOfKind) && dimmed2.add(id);
664
+ }), set({ dimmed: dimmed2 }, noReplace, "highlightByElementNotation");
653
665
  }
654
666
  }),
655
667
  {
@@ -754,7 +766,7 @@ function FitViewOnViewportResize({ diagramApi }) {
754
766
  1e3
755
767
  ), null;
756
768
  }
757
- function selector$3({ view, viewportChanged, fitViewPadding }) {
769
+ function selector$4({ view, viewportChanged, fitViewPadding }) {
758
770
  return {
759
771
  layoutId: view.id + "_" + view.autoLayout + "_" + fitViewPadding,
760
772
  viewportNotMoved: !viewportChanged
@@ -764,7 +776,7 @@ function FitViewOnDiagramChange() {
764
776
  const {
765
777
  layoutId,
766
778
  viewportNotMoved
767
- } = useDiagramState(selector$3, shallowEqual), diagramApi = useDiagramStoreApi(), [currentLayoutId, setCurrent] = useState(layoutId), requiresFit = layoutId !== currentLayoutId;
779
+ } = useDiagramState(selector$4, shallowEqual), diagramApi = useDiagramStoreApi(), [currentLayoutId, setCurrent] = useState(layoutId), requiresFit = layoutId !== currentLayoutId;
768
780
  return useDebouncedEffect(
769
781
  () => {
770
782
  layoutId !== currentLayoutId && (setCurrent(layoutId), diagramApi.getState().fitDiagram(450));
@@ -1012,7 +1024,7 @@ const Open = (props) => /* @__PURE__ */ jsx(
1012
1024
  Dot,
1013
1025
  ODot
1014
1026
  };
1015
- var container$4 = "bexn7q1", dimmed$2 = "bexn7q2", edgePathBg = "bexn7q3", markerContext = "bexn7q4", controlPoint = "bexn7q5", controlDragging = "bexn7q6", cssEdgePath = "bexn7q8", stepEdgeNumber = "bexn7q9", varLabelX = "var(--bexn7qa)", varLabelY = "var(--bexn7qb)", edgeLabel = "bexn7qd", edgeLabelText = "bexn7qe";
1027
+ var container$5 = "bexn7q1", dimmed$2 = "bexn7q2", edgePathBg = "bexn7q3", markerContext = "bexn7q4", controlPoint = "bexn7q5", controlDragging = "bexn7q6", cssEdgePath = "bexn7q8", stepEdgeNumber = "bexn7q9", varLabelX = "var(--bexn7qa)", varLabelY = "var(--bexn7qb)", edgeLabel = "bexn7qd", edgeLabelText = "bexn7qe";
1016
1028
  function getNodeIntersectionFromCenterToPoint(intersectionNode, { x: x1, y: y1 }) {
1017
1029
  const {
1018
1030
  width: intersectionNodeWidth,
@@ -1188,7 +1200,7 @@ const isSame = (a, b) => Math.abs(a - b) < 2.5, isSamePoint = (a, b) => {
1188
1200
  "g",
1189
1201
  {
1190
1202
  className: clsx(
1191
- container$4,
1203
+ container$5,
1192
1204
  isDimmed && dimmed$2,
1193
1205
  isControlPointDragging && controlDragging
1194
1206
  ),
@@ -1298,7 +1310,7 @@ const isSame = (a, b) => Math.abs(a - b) < 2.5, isSamePoint = (a, b) => {
1298
1310
  {
1299
1311
  className: clsx([
1300
1312
  "nodrag nopan",
1301
- container$4,
1313
+ container$5,
1302
1314
  edgeLabel,
1303
1315
  isDimmed && dimmed$2
1304
1316
  ]),
@@ -1338,6 +1350,7 @@ function NavigateToBtn({ xynodeId, className }) {
1338
1350
  onClick: (event) => {
1339
1351
  event.stopPropagation(), diagramApi.getState().triggerOnNavigateTo(xynodeId, event);
1340
1352
  },
1353
+ role: "button",
1341
1354
  onDoubleClick: (event) => event.stopPropagation(),
1342
1355
  children: /* @__PURE__ */ jsx(
1343
1356
  IconZoomScan,
@@ -1351,7 +1364,7 @@ function NavigateToBtn({ xynodeId, className }) {
1351
1364
  }
1352
1365
  );
1353
1366
  }
1354
- var container$3 = "lbtzdo0", nodeHandlerInCenter = "lbtzdo1", dimmed$1 = "lbtzdo2", varOpacity = "var(--lbtzdo3)", varBorderTransparency = "var(--lbtzdo4)", compoundBody = "lbtzdo5", transparent = "lbtzdo7", title$2 = "lbtzdo8", titleWithNavigation = "lbtzdo9", indicator$1 = "lbtzdod", navigateBtn = "lbtzdof";
1367
+ var container$4 = "lbtzdo0", nodeHandlerInCenter = "lbtzdo1", dimmed$1 = "lbtzdo2", varOpacity = "var(--lbtzdo3)", varBorderTransparency = "var(--lbtzdo4)", compoundBody = "lbtzdo5", transparent = "lbtzdo7", title$2 = "lbtzdo8", titleWithNavigation = "lbtzdo9", indicator$1 = "lbtzdod", navigateBtn = "lbtzdof";
1355
1368
  const isEqualProps$1 = (prev, next) => prev.id === next.id && deepEqual(prev.data.element, next.data.element), CompoundNodeMemo = /* @__PURE__ */ memo(function({
1356
1369
  id,
1357
1370
  data: {
@@ -1382,7 +1395,7 @@ const isEqualProps$1 = (prev, next) => prev.id === next.id && deepEqual(prev.dat
1382
1395
  Box,
1383
1396
  {
1384
1397
  className: clsx(
1385
- container$3,
1398
+ container$4,
1386
1399
  "likec4-compound-node",
1387
1400
  opacity < 1 && "likec4-compound-transparent",
1388
1401
  isDimmed && dimmed$1
@@ -1446,8 +1459,8 @@ const isEqualProps$1 = (prev, next) => prev.id === next.id && deepEqual(prev.dat
1446
1459
  )
1447
1460
  ] });
1448
1461
  }, isEqualProps$1);
1449
- var container$2 = "_1b6tkn1", handleCenter = "_1b6tkn2", containerAnimated = "_1b6tkn3", dimmed = "_1b6tkn4", indicator = "_1b6tkn7", fillElementFill = "_1b6tkn8", fillMixStroke = "_1b6tkna", hasIcon = "_1b6tknb", title$1 = "_1b6tkne", description$1 = "_1b6tknf", technology = "_1b6tkng", elementDataContainer = "_1b6tknh", elementTextData = "_1b6tkni", elementIcon = "_1b6tknj", cssShapeSvg = "_1b6tknm", cssNavigateBtn = "_1b6tknn", elementLink = "_4ysv0o0", trigger = "_4ysv0o1";
1450
- const selector$2 = (s) => {
1462
+ var container$3 = "_1b6tkn1", handleCenter = "_1b6tkn2", containerAnimated = "_1b6tkn3", dimmed = "_1b6tkn4", indicator = "_1b6tkn7", fillElementFill = "_1b6tkn8", fillMixStroke = "_1b6tkna", hasIcon = "_1b6tknb", title$1 = "_1b6tkne", description$1 = "_1b6tknf", technology = "_1b6tkng", elementDataContainer = "_1b6tknh", elementTextData = "_1b6tkni", elementIcon = "_1b6tknj", cssShapeSvg = "_1b6tknm", cssNavigateBtn = "_1b6tknn", elementLink = "_4ysv0o0", trigger = "_4ysv0o1";
1463
+ const selector$3 = (s) => {
1451
1464
  const target = s.getContainer();
1452
1465
  return target ? { target } : null;
1453
1466
  };
@@ -1455,7 +1468,7 @@ function ElementLink({
1455
1468
  element
1456
1469
  }) {
1457
1470
  invariant(element.links, "ElementLink: links are required");
1458
- const id = useId(), portalProps = useDiagramState(selector$2);
1471
+ const id = useId(), portalProps = useDiagramState(selector$3);
1459
1472
  return /* @__PURE__ */ jsx("div", { className: elementLink, "data-likec4-linkid": id, children: /* @__PURE__ */ jsxs(
1460
1473
  HoverCard,
1461
1474
  {
@@ -1495,8 +1508,8 @@ function ElementLink({
1495
1508
  onClick: (e) => e.stopPropagation(),
1496
1509
  p: "xs",
1497
1510
  children: /* @__PURE__ */ jsx(Stack, { gap: "xs", children: element.links.map((link) => /* @__PURE__ */ jsxs(Group, { wrap: "nowrap", gap: "sm", children: [
1498
- /* @__PURE__ */ jsx(Box, { flex: "1", style: { overflow: "clip", maxWidth: clamp(element.width, { min: 200, max: 400 }) }, children: /* @__PURE__ */ jsx(Anchor, { href: link, target: "_blank", fz: "13", truncate: "end", children: link }) }),
1499
- /* @__PURE__ */ jsx(CopyButton, { value: link, children: ({ copied, copy }) => /* @__PURE__ */ jsx(
1511
+ /* @__PURE__ */ jsx(Box, { flex: "1", style: { overflow: "clip", maxWidth: clamp(element.width, { min: 200, max: 400 }) }, children: /* @__PURE__ */ jsx(Anchor, { href: link.url, target: "_blank", fz: "13", truncate: "end", children: link.title || link.url }) }),
1512
+ /* @__PURE__ */ jsx(CopyButton, { value: link.url, children: ({ copied, copy }) => /* @__PURE__ */ jsx(
1500
1513
  Button,
1501
1514
  {
1502
1515
  size: "compact-xs",
@@ -1507,7 +1520,7 @@ function ElementLink({
1507
1520
  children: copied ? "copied" : "copy"
1508
1521
  }
1509
1522
  ) })
1510
- ] }, link)) })
1523
+ ] }, link.url)) })
1511
1524
  }
1512
1525
  )
1513
1526
  ]
@@ -1758,7 +1771,7 @@ const Text = Text$1.withProps({
1758
1771
  {
1759
1772
  id,
1760
1773
  className: clsx([
1761
- container$2,
1774
+ container$3,
1762
1775
  isDimmed && dimmed,
1763
1776
  animate !== "idle" && containerAnimated,
1764
1777
  "likec4-element-node"
@@ -2188,7 +2201,7 @@ const nodeTypes = {
2188
2201
  compound: CompoundNodeMemo
2189
2202
  }, edgeTypes = {
2190
2203
  relationship: RelationshipEdge
2191
- }, selector$1 = (s) => ({
2204
+ }, selector$2 = (s) => ({
2192
2205
  nodes: s.xynodes,
2193
2206
  edges: s.xyedges,
2194
2207
  onInit: s.onInit,
@@ -2236,7 +2249,7 @@ function XYFlow({
2236
2249
  hasOnEdgeContextMenu,
2237
2250
  translateX,
2238
2251
  translateY
2239
- } = useDiagramState(selector$1, shallowEqual), [zoomOnDoubleClick, setZoomOnDoubleClick] = useState(zoomable), layoutConstraints = useLayoutConstraints(), handlers = useXYFlowEvents();
2252
+ } = useDiagramState(selector$2, shallowEqual), [zoomOnDoubleClick, setZoomOnDoubleClick] = useState(zoomable), layoutConstraints = useLayoutConstraints(), handlers = useXYFlowEvents();
2240
2253
  return useOnViewportChange({
2241
2254
  onEnd: ({ x, y, zoom }) => {
2242
2255
  const roundedX = Math.round(x), roundedY = Math.round(y);
@@ -2322,15 +2335,15 @@ function XYFlow({
2322
2335
  }
2323
2336
  );
2324
2337
  }
2325
- var container$1 = "hbkbtj0", card = "hbkbtj1", title = "hbkbtj2", description = "hbkbtj3";
2326
- const selector = (s) => ({
2338
+ var container$2 = "hbkbtj0", card$1 = "hbkbtj1", title = "hbkbtj2", description = "hbkbtj3";
2339
+ const selector$1 = (s) => ({
2327
2340
  id: s.view.id,
2328
2341
  title: s.view.title ?? "untitled",
2329
2342
  description: s.view.description,
2330
2343
  links: s.view.links
2331
2344
  });
2332
2345
  function DiagramTitlePanel() {
2333
- const { id, title: title$12, description: description$12, links } = useDiagramState(selector), [isCollapsed, setCollapsed] = useLocalStorage({
2346
+ const { id, title: title$12, description: description$12, links } = useDiagramState(selector$1), [isCollapsed, setCollapsed] = useLocalStorage({
2334
2347
  key: "diagram-title-panel-collapsed",
2335
2348
  defaultValue: !1
2336
2349
  }), toggle = () => setCollapsed((v) => !v);
@@ -2343,7 +2356,7 @@ function DiagramTitlePanel() {
2343
2356
  opacity: 0.05,
2344
2357
  scale: 0.6
2345
2358
  },
2346
- className: clsx("react-flow__panel", container$1),
2359
+ className: clsx("react-flow__panel", container$2),
2347
2360
  style: {
2348
2361
  transformOrigin: "left center"
2349
2362
  },
@@ -2351,8 +2364,8 @@ function DiagramTitlePanel() {
2351
2364
  Card,
2352
2365
  {
2353
2366
  radius: "sm",
2354
- className: card,
2355
- withBorder: !0,
2367
+ className: card$1,
2368
+ withBorder: !isCollapsed,
2356
2369
  p: isCollapsed ? "sm" : "md",
2357
2370
  onDoubleClick: (e) => e.stopPropagation(),
2358
2371
  children: [
@@ -2361,17 +2374,18 @@ function DiagramTitlePanel() {
2361
2374
  {
2362
2375
  fullWidth: !0,
2363
2376
  justify: "stretch",
2364
- size: "sm",
2365
- py: 2,
2377
+ size: "md",
2366
2378
  radius: "0",
2367
2379
  variant: "subtle",
2368
- color: "dark",
2380
+ color: "gray",
2369
2381
  onClick: toggle,
2370
- children: /* @__PURE__ */ jsx(Text$1, { inline: !0, fw: 500, fz: "xs", c: "gray", children: title$12 })
2382
+ fw: 500,
2383
+ fz: "sm",
2384
+ children: title$12
2371
2385
  }
2372
2386
  ) }),
2373
2387
  !isCollapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
2374
- /* @__PURE__ */ jsx(CardSection, { mb: "sm", children: /* @__PURE__ */ jsx(
2388
+ /* @__PURE__ */ jsx(CardSection, { mb: "xs", children: /* @__PURE__ */ jsx(
2375
2389
  Button,
2376
2390
  {
2377
2391
  fullWidth: !0,
@@ -2458,16 +2472,16 @@ function DiagramTitlePanel() {
2458
2472
  /* @__PURE__ */ jsx(Box, { flex: "1", style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx(
2459
2473
  Anchor,
2460
2474
  {
2461
- href: link,
2475
+ href: link.url,
2462
2476
  target: "_blank",
2463
2477
  fz: "xs",
2464
2478
  truncate: "end",
2465
2479
  display: "inline-block",
2466
2480
  w: "100%",
2467
- children: link
2481
+ children: link.title || link.url
2468
2482
  }
2469
2483
  ) }),
2470
- /* @__PURE__ */ jsx(CopyButton, { value: link, children: ({ copied, copy }) => /* @__PURE__ */ jsx(
2484
+ /* @__PURE__ */ jsx(CopyButton, { value: link.url, children: ({ copied, copy }) => /* @__PURE__ */ jsx(
2471
2485
  Button,
2472
2486
  {
2473
2487
  size: "compact-xs",
@@ -2478,7 +2492,7 @@ function DiagramTitlePanel() {
2478
2492
  children: copied ? "copied" : "copy"
2479
2493
  }
2480
2494
  ) })
2481
- ] }, link))
2495
+ ] }, link.url))
2482
2496
  }
2483
2497
  )
2484
2498
  ] })
@@ -2489,7 +2503,7 @@ function DiagramTitlePanel() {
2489
2503
  id
2490
2504
  ) });
2491
2505
  }
2492
- var container = "_2jkb2y0", buttons = "_2jkb2y1", btn = "_2jkb2y3";
2506
+ var container$1 = "_2jkb2y0", buttons = "_2jkb2y1", btn = "_2jkb2y3";
2493
2507
  function DynamicViewWalkthrough() {
2494
2508
  const isMobile = useXYStore((s) => s.width <= 750), {
2495
2509
  nextDynamicStep,
@@ -2524,7 +2538,7 @@ function DynamicViewWalkthrough() {
2524
2538
  return /* @__PURE__ */ jsxs(
2525
2539
  Box,
2526
2540
  {
2527
- className: clsx("react-flow__panel", container),
2541
+ className: clsx("react-flow__panel", container$1),
2528
2542
  onClick: (e) => e.stopPropagation(),
2529
2543
  onDoubleClick: (e) => e.stopPropagation(),
2530
2544
  children: [
@@ -2578,6 +2592,230 @@ function DynamicViewWalkthrough() {
2578
2592
  }
2579
2593
  );
2580
2594
  }
2595
+ var vars = { safariAnimationHook: "var(--likec4-safari-animation-hook)", 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)" }, navigationPanel: { top: "var(--likec4-navigation-panel-top)", left: "var(--likec4-navigation-panel-left)" } }, container = "_1ncdyfa0", card = "_1ncdyfa1", tabPanel = "_1ncdyfa2", elementNotation = "_1ncdyfa3", shapeSvg = "_1ncdyfa4", shapeBadge = "_1ncdyfa5";
2596
+ const ElementNotation = ({ value }) => {
2597
+ const {
2598
+ title: title2,
2599
+ color = "primary",
2600
+ shape = "rectangle"
2601
+ } = value, [onlyKind, setOnlyKind] = useState(null), diagramStore = useDiagramStoreApi(), w = 300, h = 200;
2602
+ return /* @__PURE__ */ jsx(
2603
+ Card,
2604
+ {
2605
+ shadow: "none",
2606
+ px: "xs",
2607
+ py: "sm",
2608
+ className: elementNotation,
2609
+ mod: {
2610
+ "data-likec4-color": color
2611
+ },
2612
+ onMouseEnter: () => {
2613
+ setOnlyKind(null), diagramStore.getState().highlightByElementNotation(value);
2614
+ },
2615
+ onMouseLeave: () => {
2616
+ setOnlyKind(null), diagramStore.setState({ dimmed: /* @__PURE__ */ new Set() });
2617
+ },
2618
+ children: /* @__PURE__ */ jsxs(
2619
+ Group,
2620
+ {
2621
+ gap: "sm",
2622
+ align: "stretch",
2623
+ wrap: "nowrap",
2624
+ children: [
2625
+ /* @__PURE__ */ jsx(
2626
+ Box,
2627
+ {
2628
+ flex: "0 0 70px",
2629
+ style: {
2630
+ width: 70,
2631
+ height: ceil(70 * (h / w), 0)
2632
+ },
2633
+ children: /* @__PURE__ */ jsx(
2634
+ "svg",
2635
+ {
2636
+ className: clsx(
2637
+ shapeSvg
2638
+ ),
2639
+ viewBox: `0 0 ${w} ${h}`,
2640
+ children: /* @__PURE__ */ jsx(
2641
+ ElementShapeSvg,
2642
+ {
2643
+ shape,
2644
+ w,
2645
+ h
2646
+ }
2647
+ )
2648
+ }
2649
+ )
2650
+ }
2651
+ ),
2652
+ /* @__PURE__ */ jsxs(Stack, { gap: 4, flex: 1, children: [
2653
+ /* @__PURE__ */ jsx(Group, { gap: 4, flex: "0 0 auto", children: value.kinds.map((kind) => /* @__PURE__ */ jsx(
2654
+ Badge,
2655
+ {
2656
+ className: shapeBadge,
2657
+ onMouseEnter: () => {
2658
+ setOnlyKind(kind), diagramStore.getState().highlightByElementNotation(value, kind);
2659
+ },
2660
+ onMouseLeave: () => {
2661
+ setOnlyKind(null), diagramStore.getState().highlightByElementNotation(value);
2662
+ },
2663
+ opacity: isNonNullish(onlyKind) && onlyKind !== kind ? 0.25 : 1,
2664
+ color: isNonNullish(onlyKind) && onlyKind !== kind ? "gray" : vars.element.fill,
2665
+ children: kind
2666
+ },
2667
+ kind
2668
+ )) }),
2669
+ /* @__PURE__ */ jsx(
2670
+ Text$1,
2671
+ {
2672
+ component: "div",
2673
+ fz: "sm",
2674
+ fw: 500,
2675
+ lh: "1.25",
2676
+ style: {
2677
+ textWrap: "pretty"
2678
+ },
2679
+ children: title2
2680
+ }
2681
+ )
2682
+ ] })
2683
+ ]
2684
+ }
2685
+ )
2686
+ }
2687
+ );
2688
+ }, selector = (s) => {
2689
+ var _a;
2690
+ return {
2691
+ id: s.view.id,
2692
+ notations: ((_a = s.view.notation) == null ? void 0 : _a.elements) ?? [],
2693
+ height: s.xystore.getState().height,
2694
+ isVisible: isNullish(s.focusedNodeId ?? s.activeDynamicViewStep),
2695
+ target: s.getContainer()
2696
+ };
2697
+ };
2698
+ function NotationPanel() {
2699
+ const {
2700
+ id,
2701
+ notations,
2702
+ isVisible,
2703
+ height,
2704
+ target
2705
+ } = useDiagramState(selector), [isCollapsed, setCollapsed] = useLocalStorage({
2706
+ key: "notation-panel-collapsed",
2707
+ defaultValue: !0
2708
+ }), hasNotations = notations.length > 0, portalProps = target ? { portalProps: { target } } : { withinPortal: !1 };
2709
+ return /* @__PURE__ */ jsxs(AnimatePresence, { children: [
2710
+ !hasNotations && /* @__PURE__ */ jsx(
2711
+ m.div,
2712
+ {
2713
+ initial: { opacity: 0.75, translateX: "50%" },
2714
+ animate: { opacity: 1, translateX: 0 },
2715
+ exit: {
2716
+ translateX: "100%",
2717
+ opacity: 0.6
2718
+ },
2719
+ className: clsx("react-flow__panel", container),
2720
+ children: /* @__PURE__ */ jsx(Tooltip$2, { label: "Diagram has no notations", color: "orange", ...portalProps, children: /* @__PURE__ */ jsx(
2721
+ ThemeIcon,
2722
+ {
2723
+ size: "xl",
2724
+ variant: "light",
2725
+ color: "orange",
2726
+ radius: "md",
2727
+ children: /* @__PURE__ */ jsx(IconAlertTriangle, {})
2728
+ }
2729
+ ) })
2730
+ },
2731
+ "empty"
2732
+ ),
2733
+ hasNotations && isVisible && isCollapsed && /* @__PURE__ */ jsx(
2734
+ m.div,
2735
+ {
2736
+ initial: { opacity: 0.75, translateX: "50%" },
2737
+ animate: { opacity: 1, translateX: 0 },
2738
+ exit: {
2739
+ translateX: "100%",
2740
+ opacity: 0.6
2741
+ },
2742
+ className: clsx("react-flow__panel", container),
2743
+ children: /* @__PURE__ */ jsx(Tooltip$2, { label: "Show notation", color: "dark", fz: "xs", ...portalProps, children: /* @__PURE__ */ jsx(
2744
+ ActionIcon$2,
2745
+ {
2746
+ size: "xl",
2747
+ variant: "light",
2748
+ color: "gray",
2749
+ radius: "md",
2750
+ onClick: () => setCollapsed(!1),
2751
+ children: /* @__PURE__ */ jsx(IconHelpCircle, { stroke: 1.5 })
2752
+ }
2753
+ ) })
2754
+ },
2755
+ "collapsed"
2756
+ ),
2757
+ hasNotations && isVisible && !isCollapsed && /* @__PURE__ */ jsx(
2758
+ m.div,
2759
+ {
2760
+ initial: {
2761
+ opacity: 0.75,
2762
+ // translateX: '50%',
2763
+ scale: 0.2
2764
+ },
2765
+ animate: { opacity: 1, scale: 1 },
2766
+ exit: {
2767
+ opacity: 0,
2768
+ scale: 0.25
2769
+ },
2770
+ className: clsx("react-flow__panel", container),
2771
+ style: {
2772
+ transformOrigin: "bottom right"
2773
+ },
2774
+ children: /* @__PURE__ */ jsx(
2775
+ Paper,
2776
+ {
2777
+ radius: "sm",
2778
+ withBorder: !0,
2779
+ shadow: "lg",
2780
+ className: card,
2781
+ children: /* @__PURE__ */ jsxs(Tabs, { defaultValue: "first", radius: "xs", children: [
2782
+ /* @__PURE__ */ jsxs(TabsList, { children: [
2783
+ /* @__PURE__ */ jsx(
2784
+ ActionIcon$2,
2785
+ {
2786
+ size: "md",
2787
+ variant: "subtle",
2788
+ color: "gray",
2789
+ ml: 2,
2790
+ style: {
2791
+ alignSelf: "center"
2792
+ },
2793
+ onClick: () => setCollapsed(!0),
2794
+ children: /* @__PURE__ */ jsx(IconArrowDownRight, { stroke: 2 })
2795
+ }
2796
+ ),
2797
+ /* @__PURE__ */ jsx(TabsTab, { value: "first", fz: "xs", children: "Elements" }),
2798
+ /* @__PURE__ */ jsx(TabsTab, { value: "second", fz: "xs", disabled: !0, children: "Relationships" })
2799
+ ] }),
2800
+ /* @__PURE__ */ jsx(TabsPanel, { value: "first", className: tabPanel, hidden: isCollapsed, children: /* @__PURE__ */ jsx(
2801
+ ScrollAreaAutosize,
2802
+ {
2803
+ viewportProps: {
2804
+ style: {
2805
+ maxHeight: height > 50 ? `min(40vh, ${height - 20}px)` : "40vh"
2806
+ }
2807
+ },
2808
+ children: /* @__PURE__ */ jsx(Stack, { gap: 0, children: notations.map((n, i) => /* @__PURE__ */ jsx(ElementNotation, { value: n }, i)) })
2809
+ }
2810
+ ) })
2811
+ ] })
2812
+ }
2813
+ )
2814
+ },
2815
+ id
2816
+ )
2817
+ ] });
2818
+ }
2581
2819
  const {
2582
2820
  primary,
2583
2821
  secondary,
@@ -3108,19 +3346,19 @@ const ActionIcon = ActionIcon$2.withProps({
3108
3346
  showFitDiagram,
3109
3347
  showLayoutDriftWarning,
3110
3348
  showChangeAutoLayout,
3111
- portalProps: _portalProps,
3349
+ target,
3112
3350
  showGoToSource
3113
3351
  } = useDiagramState((s) => {
3114
- const isNotActive = s.activeDynamicViewStep === null && s.focusedNodeId === null, target = s.getContainer();
3352
+ const isNotActive = s.activeDynamicViewStep === null && s.focusedNodeId === null;
3115
3353
  return {
3116
3354
  showNavigationButtons: !!s.onBurgerMenuClick || s.showNavigationButtons && !!s.onNavigateTo,
3117
3355
  showFitDiagram: s.fitViewEnabled && s.zoomable && s.viewportChanged,
3118
3356
  showLayoutDriftWarning: s.readonly !== !0 && s.view.hasLayoutDrift === !0 && isNotActive,
3119
3357
  showChangeAutoLayout: s.readonly !== !0 && !!s.onChange && isNotActive,
3120
3358
  showGoToSource: !!s.onOpenSourceView,
3121
- portalProps: target ? { target } : void 0
3359
+ target: s.getContainer()
3122
3360
  };
3123
- }), portalProps = _portalProps ? { portalProps: _portalProps } : void 0;
3361
+ }), portalProps = target ? { portalProps: { target } } : void 0;
3124
3362
  return /* @__PURE__ */ jsxs(
3125
3363
  Stack,
3126
3364
  {
@@ -3201,7 +3439,7 @@ function literalToEnum(value) {
3201
3439
  }
3202
3440
  function XYFlowBackground({ background }) {
3203
3441
  if (typeof background == "string")
3204
- return /* @__PURE__ */ jsx(Background, { variant: literalToEnum(background) });
3442
+ return /* @__PURE__ */ jsx(Background, { variant: literalToEnum(background), size: 2, gap: 20 });
3205
3443
  const { variant, ...rest } = background;
3206
3444
  return /* @__PURE__ */ jsx(Background, { variant: literalToEnum(variant), ...rest });
3207
3445
  }
@@ -3212,11 +3450,13 @@ const XYFlowInner = memo(function({
3212
3450
  showDiagramTitle
3213
3451
  }) {
3214
3452
  const {
3453
+ showNotations,
3215
3454
  isDynamicView,
3216
3455
  isDynamicViewActive,
3217
3456
  readonly,
3218
3457
  enableDynamicViewWalkthrough
3219
3458
  } = useDiagramState((s) => ({
3459
+ showNotations: s.showNotations,
3220
3460
  isDynamicView: s.isDynamicView,
3221
3461
  readonly: s.readonly,
3222
3462
  enableDynamicViewWalkthrough: s.enableDynamicViewWalkthrough,
@@ -3229,6 +3469,7 @@ const XYFlowInner = memo(function({
3229
3469
  readonly !== !0 && /* @__PURE__ */ jsx(OptionsPanel, {}),
3230
3470
  showDiagramTitle === !0 && !isDynamicViewActive && /* @__PURE__ */ jsx(DiagramTitlePanel, {}),
3231
3471
  isDynamicView && enableDynamicViewWalkthrough && /* @__PURE__ */ jsx(DynamicViewWalkthrough, {}),
3472
+ showNotations && /* @__PURE__ */ jsx(NotationPanel, {}),
3232
3473
  children
3233
3474
  ] });
3234
3475
  }, shallowEqual);
@@ -3247,6 +3488,7 @@ function LikeC4Diagram({
3247
3488
  controls = !1,
3248
3489
  showElementLinks = !0,
3249
3490
  showDiagramTitle = !0,
3491
+ showNotations = !0,
3250
3492
  enableDynamicViewWalkthrough = !1,
3251
3493
  enableFocusMode = !1,
3252
3494
  initialWidth,
@@ -3294,6 +3536,7 @@ function LikeC4Diagram({
3294
3536
  fitViewPadding,
3295
3537
  showElementLinks,
3296
3538
  showNavigationButtons,
3539
+ showNotations,
3297
3540
  nodesDraggable,
3298
3541
  nodesSelectable,
3299
3542
  experimentalEdgeEditing,
@@ -3391,6 +3634,7 @@ function StaticLikeC4Diagram({
3391
3634
  background,
3392
3635
  showElementLinks: !0,
3393
3636
  showDiagramTitle: !1,
3637
+ showNotations: !1,
3394
3638
  enableDynamicViewWalkthrough: !1,
3395
3639
  enableFocusMode: !1,
3396
3640
  nodesSelectable: !1,
@@ -1 +1,3 @@
1
+ export declare const whereLight = ":where([data-mantine-color-scheme=\"light\"])";
2
+ export declare const whereDark = ":where([data-mantine-color-scheme=\"dark\"])";
1
3
  export declare const mantine: import('@mantine/vanilla-extract').MantineVars;