@likec4/diagram 1.46.4 → 1.47.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 (68) hide show
  1. package/bundle/index.js +1548 -595
  2. package/dist/LikeC4Diagram.d.ts +1 -1
  3. package/dist/LikeC4Diagram.js +2 -2
  4. package/dist/LikeC4Diagram.props.d.ts +1 -1
  5. package/dist/LikeC4ProjectsOverview.d.ts +7 -0
  6. package/dist/LikeC4ProjectsOverview.js +32 -0
  7. package/dist/base-primitives/Markdown.d.ts +1 -1
  8. package/dist/base-primitives/compound/CompoundNodeContainer.d.ts +4 -3
  9. package/dist/base-primitives/compound/actionbtns.css.d.ts +1 -1
  10. package/dist/base-primitives/element/ElementNodeContainer.js +2 -3
  11. package/dist/base-primitives/element/ElementShape.js +109 -20
  12. package/dist/components/NavigationPanel.d.ts +11 -0
  13. package/dist/components/NavigationPanel.js +69 -0
  14. package/dist/context/DiagramEventHandlers.js +1 -1
  15. package/dist/context/IconRenderer.js +4 -1
  16. package/dist/hooks/useLikeC4Project.js +10 -2
  17. package/dist/hooks/useLikeC4Styles.js +0 -3
  18. package/dist/index.d.ts +2 -1
  19. package/dist/index.js +2 -1
  20. package/dist/likec4diagram/DiagramXYFlow.js +1 -0
  21. package/dist/likec4diagram/custom/nodes/toolbar/ColorButton.js +3 -3
  22. package/dist/likec4diagram/custom/nodes/toolbar/CompoundToolbar.js +1 -38
  23. package/dist/likec4diagram/custom/nodes/toolbar/ElementToolbar.js +29 -14
  24. package/dist/likec4diagram/custom/nodes/toolbar/Toolbar.js +9 -5
  25. package/dist/likec4diagram/custom/nodes/toolbar/_shared.d.ts +6 -1
  26. package/dist/likec4diagram/custom/nodes/toolbar/_shared.js +44 -8
  27. package/dist/likec4diagram/xyflow-sequence/utils.d.ts +1 -1
  28. package/dist/navigationpanel/NavigationPanelControls.js +2 -2
  29. package/dist/navigationpanel/_common.d.ts +1 -1
  30. package/dist/navigationpanel/controls/LogoButton.d.ts +1 -0
  31. package/dist/navigationpanel/controls/{BurgerButton.js → LogoButton.js} +5 -5
  32. package/dist/navigationpanel/controls/index.d.ts +1 -1
  33. package/dist/navigationpanel/styles.css.d.ts +1 -1
  34. package/dist/node_modules/.pnpm/@tabler_icons-react@3.36.0_react@19.2.3/node_modules/@tabler/icons-react/dist/esm/icons/IconFileText.js +14 -0
  35. package/dist/overlays/relationships-browser/custom/edgeTypes.js +0 -1
  36. package/dist/projects-overview/ProjectsOverview.d.ts +13 -0
  37. package/dist/projects-overview/ProjectsOverview.js +57 -0
  38. package/dist/projects-overview/ProjectsOverviewXY.d.ts +17 -0
  39. package/dist/projects-overview/ProjectsOverviewXY.js +98 -0
  40. package/dist/projects-overview/_types.d.ts +34 -0
  41. package/dist/projects-overview/actor.d.ts +121 -0
  42. package/dist/projects-overview/actor.js +382 -0
  43. package/dist/projects-overview/context.d.ts +4 -0
  44. package/dist/projects-overview/context.js +9 -0
  45. package/dist/projects-overview/custom/edgeTypes.d.ts +3 -0
  46. package/dist/projects-overview/custom/edgeTypes.js +23 -0
  47. package/dist/projects-overview/custom/index.d.ts +2 -0
  48. package/dist/projects-overview/custom/nodeTypes.d.ts +2 -0
  49. package/dist/projects-overview/custom/nodeTypes.js +45 -0
  50. package/dist/projects-overview/custom/styles.css.d.ts +1 -0
  51. package/dist/projects-overview/hooks.d.ts +5 -0
  52. package/dist/projects-overview/hooks.js +14 -0
  53. package/dist/projects-overview/index.d.ts +1 -0
  54. package/dist/projects-overview/layouted-to-xyflow.d.ts +6 -0
  55. package/dist/projects-overview/layouted-to-xyflow.js +49 -0
  56. package/dist/projects-overview/panel/ProjectsOverviewPanel.d.ts +1 -0
  57. package/dist/projects-overview/panel/ProjectsOverviewPanel.js +11 -0
  58. package/dist/projects-overview/persistence.d.ts +5 -0
  59. package/dist/projects-overview/persistence.js +24 -0
  60. package/dist/search/components/_shared.css.d.ts +1 -1
  61. package/dist/styles.css2.js +1 -1
  62. package/package.json +8 -8
  63. package/panda.buildinfo.json +62 -29
  64. package/styles-min.css +1 -1
  65. package/styles.css +1 -1
  66. package/dist/base-primitives/element/ElementNodeContainer.css.d.ts +0 -1
  67. package/dist/base-primitives/element/ElementNodeContainer.css.js +0 -39
  68. package/dist/navigationpanel/controls/BurgerButton.d.ts +0 -1
@@ -3,7 +3,7 @@ import { ElementShapes } from '@likec4/core/styles';
3
3
  import { Menu, MenuTarget, Button, MenuDropdown, MenuItem } from '@mantine/core';
4
4
  import { useEnabledFeatures } from '../../../../context/DiagramFeatures.js';
5
5
  import { stopPropagation } from '../../../../utils/xyflow.js';
6
- import { GoToSourceButton, BrowseRelationshipsButton } from './_shared.js';
6
+ import { BorderStyleOption, GoToSourceButton, BrowseRelationshipsButton } from './_shared.js';
7
7
  import { ColorButton } from './ColorButton.js';
8
8
  import { Toolbar } from './Toolbar.js';
9
9
  import { useHandlers } from './useHandlers.js';
@@ -15,7 +15,8 @@ function ElementToolbar(props) {
15
15
  const {
16
16
  data: {
17
17
  shape,
18
- modelFqn
18
+ modelFqn,
19
+ style
19
20
  }
20
21
  } = props;
21
22
  const { elementColor, onColorPreview, onChange } = useHandlers(modelFqn, props);
@@ -26,6 +27,14 @@ function ElementToolbar(props) {
26
27
  title: modelFqn,
27
28
  align: "start",
28
29
  children: [
30
+ /* @__PURE__ */ jsx(
31
+ ColorButton,
32
+ {
33
+ elementColor,
34
+ onColorPreview,
35
+ onChange
36
+ }
37
+ ),
29
38
  /* @__PURE__ */ jsx(
30
39
  ElementShapeButton,
31
40
  {
@@ -34,12 +43,10 @@ function ElementToolbar(props) {
34
43
  }
35
44
  ),
36
45
  /* @__PURE__ */ jsx(
37
- ColorButton,
46
+ BorderStyleOption,
38
47
  {
39
- elementColor,
40
- onColorPreview,
41
- onChange,
42
- position: "right-end"
48
+ elementBorderStyle: style?.border ?? "none",
49
+ onChange
43
50
  }
44
51
  ),
45
52
  enableVscode && /* @__PURE__ */ jsx(GoToSourceButton, { elementId: modelFqn }),
@@ -54,7 +61,8 @@ function DeploymentElementToolbar(props) {
54
61
  data: {
55
62
  shape,
56
63
  deploymentFqn,
57
- modelFqn
64
+ modelFqn,
65
+ style
58
66
  }
59
67
  } = props;
60
68
  const { elementColor, onColorPreview, onChange } = useHandlers(deploymentFqn, props);
@@ -65,6 +73,14 @@ function DeploymentElementToolbar(props) {
65
73
  title: deploymentFqn,
66
74
  align: "start",
67
75
  children: [
76
+ /* @__PURE__ */ jsx(
77
+ ColorButton,
78
+ {
79
+ elementColor,
80
+ onColorPreview,
81
+ onChange
82
+ }
83
+ ),
68
84
  /* @__PURE__ */ jsx(
69
85
  ElementShapeButton,
70
86
  {
@@ -73,12 +89,10 @@ function DeploymentElementToolbar(props) {
73
89
  }
74
90
  ),
75
91
  /* @__PURE__ */ jsx(
76
- ColorButton,
92
+ BorderStyleOption,
77
93
  {
78
- elementColor,
79
- onColorPreview,
80
- onChange,
81
- position: "right-end"
94
+ elementBorderStyle: style?.border ?? "none",
95
+ onChange
82
96
  }
83
97
  ),
84
98
  enableVscode && /* @__PURE__ */ jsx(GoToSourceButton, { deploymentId: deploymentFqn }),
@@ -115,7 +129,8 @@ function ElementShapeButton({
115
129
  {
116
130
  variant: "light",
117
131
  color: "gray",
118
- size: "compact-xs",
132
+ size: "xs",
133
+ px: 8,
119
134
  rightSection: /* @__PURE__ */ jsx(IconSelector, { size: 12 }),
120
135
  children: elementShape
121
136
  }
@@ -1,14 +1,18 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import { cx } from '@likec4/styles/css';
3
- import { Paper, Stack, Box, Text, Group } from '@mantine/core';
3
+ import { VStack, Box, HStack } from '@likec4/styles/jsx';
4
+ import { Paper, Text } from '@mantine/core';
4
5
  import { useDebouncedValue } from '@mantine/hooks';
5
6
  import { NodeToolbar } from '@xyflow/react';
6
7
  import { useDiagramContext } from '../../../../hooks/useDiagram.js';
7
8
  import { stopPropagation } from '../../../../utils/xyflow.js';
8
9
  import { toolbarTitle } from './styles.css.js';
9
10
 
11
+ const selectSelectedNodesCount = (context) => {
12
+ return context.xynodes.filter((x) => x.selected).length;
13
+ };
10
14
  const useSelectedNodesCount = () => {
11
- return useDiagramContext((s) => s.xynodes.filter((x) => x.selected).length);
15
+ return useDiagramContext(selectSelectedNodesCount);
12
16
  };
13
17
  function Toolbar({ title, children, nodeProps, ...props }) {
14
18
  const selectedNodesCount = useSelectedNodesCount();
@@ -56,9 +60,9 @@ function Toolbar({ title, children, nodeProps, ...props }) {
56
60
  onClick: stopPropagation,
57
61
  onDoubleClick: stopPropagation,
58
62
  withBorder: true,
59
- children: /* @__PURE__ */ jsxs(Stack, { gap: "6px", children: [
60
- /* @__PURE__ */ jsx(Box, { px: "4px", children: /* @__PURE__ */ jsx(Text, { className: toolbarTitle, children: title }) }),
61
- /* @__PURE__ */ jsx(Group, { gap: 4, children })
63
+ children: /* @__PURE__ */ jsxs(VStack, { gap: "2", children: [
64
+ /* @__PURE__ */ jsx(Box, { px: "1", children: /* @__PURE__ */ jsx(Text, { className: toolbarTitle, children: title }) }),
65
+ /* @__PURE__ */ jsx(HStack, { gap: "1", children })
62
66
  ] })
63
67
  }
64
68
  )
@@ -1,5 +1,6 @@
1
- import { DeploymentFqn, Fqn } from '@likec4/core/types';
1
+ import { BorderStyle, DeploymentFqn, Fqn } from '@likec4/core/types';
2
2
  import { MergeExclusive } from 'type-fest';
3
+ import { OnStyleChange } from './types';
3
4
  import { ForwardRefExoticComponent, RefAttributes } from 'react';
4
5
  import { TooltipProps } from '@mantine/core';
5
6
  export declare const Tooltip: ForwardRefExoticComponent< TooltipProps & RefAttributes<HTMLDivElement> & {
@@ -14,3 +15,7 @@ export declare function GoToSourceButton(props: MergeExclusive<{
14
15
  }, {
15
16
  deploymentId: DeploymentFqn;
16
17
  }>): import("react/jsx-runtime").JSX.Element | null;
18
+ export declare function BorderStyleOption({ elementBorderStyle, onChange, }: {
19
+ elementBorderStyle: BorderStyle | undefined;
20
+ onChange: OnStyleChange;
21
+ }): import("react/jsx-runtime").JSX.Element;
@@ -1,8 +1,8 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { Tooltip as Tooltip$1, ActionIcon } from '@mantine/core';
2
+ import { SegmentedControl, Tooltip as Tooltip$1, ActionIcon } from '@mantine/core';
3
+ import { useState, useEffect } from 'react';
3
4
  import '@xstate/react';
4
5
  import 'fast-equals';
5
- import 'react';
6
6
  import { useDiagram } from '../../../../hooks/safeContext.js';
7
7
  import { useDiagramEventHandlers } from '../../../../context/DiagramEventHandlers.js';
8
8
  import IconFileSymlink from '../../../../node_modules/.pnpm/@tabler_icons-react@3.36.0_react@19.2.3/node_modules/@tabler/icons-react/dist/esm/icons/IconFileSymlink.js';
@@ -23,7 +23,7 @@ function BrowseRelationshipsButton({ fqn }) {
23
23
  return /* @__PURE__ */ jsx(Tooltip, { label: "Browse relationships", children: /* @__PURE__ */ jsx(
24
24
  ActionIcon,
25
25
  {
26
- size: "sm",
26
+ size: "md",
27
27
  variant: "subtle",
28
28
  color: "gray",
29
29
  onClick: (e) => {
@@ -35,8 +35,8 @@ function BrowseRelationshipsButton({ fqn }) {
35
35
  {
36
36
  stroke: 2,
37
37
  style: {
38
- width: "72%",
39
- height: "72%"
38
+ width: "65%",
39
+ height: "65%"
40
40
  }
41
41
  }
42
42
  )
@@ -49,7 +49,7 @@ function GoToSourceButton(props) {
49
49
  return /* @__PURE__ */ jsx(Tooltip, { label: "Open source", children: /* @__PURE__ */ jsx(
50
50
  ActionIcon,
51
51
  {
52
- size: "sm",
52
+ size: "md",
53
53
  variant: "subtle",
54
54
  color: "gray",
55
55
  onClick: (e) => {
@@ -64,9 +64,45 @@ function GoToSourceButton(props) {
64
64
  });
65
65
  }
66
66
  },
67
- children: /* @__PURE__ */ jsx(IconFileSymlink, { stroke: 1.8, style: { width: "70%" } })
67
+ children: /* @__PURE__ */ jsx(IconFileSymlink, { stroke: 1.8, style: { width: "65%" } })
68
68
  }
69
69
  ) });
70
70
  }
71
+ function BorderStyleOption({
72
+ elementBorderStyle = "none",
73
+ onChange
74
+ }) {
75
+ const [value, setValue] = useState(elementBorderStyle);
76
+ useEffect(() => {
77
+ setValue(elementBorderStyle);
78
+ }, [elementBorderStyle]);
79
+ return /* @__PURE__ */ jsx(
80
+ SegmentedControl,
81
+ {
82
+ size: "xs",
83
+ fz: 9,
84
+ fullWidth: true,
85
+ withItemsBorders: false,
86
+ value,
87
+ onChange: (v) => {
88
+ const border = v;
89
+ setValue(border);
90
+ onChange({ border });
91
+ },
92
+ styles: {
93
+ label: {
94
+ paddingTop: 2,
95
+ paddingBottom: 2
96
+ }
97
+ },
98
+ data: [
99
+ { label: "Solid", value: "solid" },
100
+ { label: "Dashed", value: "dashed" },
101
+ { label: "Dotted", value: "dotted" },
102
+ { label: "None", value: "none" }
103
+ ]
104
+ }
105
+ );
106
+ }
71
107
 
72
- export { BrowseRelationshipsButton, GoToSourceButton, Tooltip };
108
+ export { BorderStyleOption, BrowseRelationshipsButton, GoToSourceButton, Tooltip };
@@ -11,4 +11,4 @@ export declare function findParallelRects(steps: Array<Step>): Array<ParallelRec
11
11
  * @returns an array of compounds where each compound is a node in the sequence view
12
12
  * that is an ancestor of one of the actors
13
13
  */
14
- export declare function buildCompounds(actors: Array<DiagramNode>, nodes: Array<DiagramNode>): Array<Compound>;
14
+ export declare function buildCompounds(actors: ReadonlyArray<DiagramNode>, nodes: ReadonlyArray<DiagramNode>): Array<Compound>;
@@ -12,7 +12,7 @@ import { useEnabledFeatures } from '../context/DiagramFeatures.js';
12
12
  import { BreadcrumbsSeparator } from './_common.js';
13
13
  import { useNavigationActor } from './hooks.js';
14
14
  import { breadcrumbTitle } from './styles.css.js';
15
- import { BurgerButton } from './controls/BurgerButton.js';
15
+ import { LogoButton } from './controls/LogoButton.js';
16
16
  import { NavigationButtons } from './controls/NavigationButtons.js';
17
17
  import { DetailsControls } from './controls/DetailsControls.js';
18
18
  import { OpenSource } from './controls/OpenSource.js';
@@ -104,7 +104,7 @@ const NavigationPanelControls = memo(() => {
104
104
  "view-title"
105
105
  );
106
106
  return /* @__PURE__ */ jsxs(AnimatePresence, { propagate: true, mode: "popLayout", children: [
107
- /* @__PURE__ */ jsx(BurgerButton, {}, "burger-button"),
107
+ /* @__PURE__ */ jsx(LogoButton, {}, "logo-button"),
108
108
  enableNavigationButtons && /* @__PURE__ */ jsx(NavigationButtons, {}, "nav-buttons"),
109
109
  /* @__PURE__ */ jsxs(
110
110
  m.div,
@@ -1,4 +1,4 @@
1
- import { NavigationPanelActionIconVariant } from '@likec4/styles/recipes';
1
+ import { NavigationPanelActionIconVariant } from '../../styled-system/recipes';
2
2
  import { ActionIconProps, TooltipProps, BreadcrumbsProps } from '@mantine/core';
3
3
  import { HTMLMotionProps } from 'motion/react';
4
4
  import { ForwardRefExoticComponent, RefAttributes } from 'react';
@@ -0,0 +1 @@
1
+ export declare const LogoButton: () => import("react/jsx-runtime").JSX.Element;
@@ -7,9 +7,9 @@ import { Logo, LogoIcon } from '../../components/Logo.js';
7
7
  import { useDiagramEventHandlers } from '../../context/DiagramEventHandlers.js';
8
8
  import { useNavigationActor } from '../hooks.js';
9
9
 
10
- const BurgerButton = () => {
10
+ const LogoButton = () => {
11
11
  const actor = useNavigationActor();
12
- const { onBurgerMenuClick } = useDiagramEventHandlers();
12
+ const { onLogoClick } = useDiagramEventHandlers();
13
13
  return /* @__PURE__ */ jsx(m.div, { layout: "position", children: /* @__PURE__ */ jsxs(
14
14
  UnstyledButton,
15
15
  {
@@ -21,9 +21,9 @@ const BurgerButton = () => {
21
21
  },
22
22
  onClick: (e) => {
23
23
  e.stopPropagation();
24
- if (onBurgerMenuClick && actor.isOpened()) {
24
+ if (onLogoClick && actor.isOpened()) {
25
25
  setTimeout(() => {
26
- onBurgerMenuClick();
26
+ onLogoClick();
27
27
  }, 100);
28
28
  }
29
29
  actor.send({ type: "breadcrumbs.click.root" });
@@ -69,4 +69,4 @@ const BurgerButton = () => {
69
69
  ) });
70
70
  };
71
71
 
72
- export { BurgerButton };
72
+ export { LogoButton };
@@ -1,6 +1,6 @@
1
- export { BurgerButton } from './BurgerButton';
2
1
  export { DetailsControls } from './DetailsControls';
3
2
  export { LayoutWarning } from './LayoutWarning';
3
+ export { LogoButton } from './LogoButton';
4
4
  export { NavigationButtons } from './NavigationButtons';
5
5
  export { OpenSource } from './OpenSource';
6
6
  export { SearchControl } from './SearchControl';
@@ -1,4 +1,4 @@
1
- import { RecipeRuntimeFn } from '@likec4/styles';
1
+ import { RecipeRuntimeFn } from '../../styled-system';
2
2
  export declare const breadcrumbTitle: RecipeRuntimeFn<{
3
3
  truncate: {
4
4
  true: {
@@ -0,0 +1,14 @@
1
+ import createReactComponent from '../createReactComponent.js';
2
+
3
+ /**
4
+ * @license @tabler/icons-react v3.36.0 - MIT
5
+ *
6
+ * This source code is licensed under the MIT license.
7
+ * See the LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+
11
+ const __iconNode = [["path", { "d": "M14 3v4a1 1 0 0 0 1 1h4", "key": "svg-0" }], ["path", { "d": "M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z", "key": "svg-1" }], ["path", { "d": "M9 9l1 0", "key": "svg-2" }], ["path", { "d": "M9 13l6 0", "key": "svg-3" }], ["path", { "d": "M9 17l6 0", "key": "svg-4" }]];
12
+ const IconFileText = createReactComponent("outline", "file-text", "FileText", __iconNode);
13
+
14
+ export { __iconNode, IconFileText as default };
@@ -32,7 +32,6 @@ const RelationshipEdge = memoEdge((props) => {
32
32
  ...props,
33
33
  data: {
34
34
  ...props.data,
35
- line: "solid",
36
35
  color: "amber"
37
36
  }
38
37
  } : props;
@@ -0,0 +1,13 @@
1
+ import { ProjectId } from '@likec4/core';
2
+ import { LayoutedProjectsView } from '@likec4/core/compute-view';
3
+ import { ViewPadding } from '../LikeC4Diagram.props';
4
+ import { ProjectsOverviewXYProps } from './ProjectsOverviewXY';
5
+ export type ProjectsOverviewProps = {
6
+ view: LayoutedProjectsView;
7
+ /**
8
+ * Callback when project is selected (e.g. clicked)
9
+ */
10
+ onNavigateToProject?: undefined | ((projectId: ProjectId) => void);
11
+ fitViewPadding?: ViewPadding | undefined;
12
+ } & ProjectsOverviewXYProps;
13
+ export declare function ProjectsOverview({ view, onNavigateToProject, fitViewPadding, ...props }: ProjectsOverviewProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,57 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useSyncedRef } from '@react-hookz/web';
3
+ import { useActorRef } from '@xstate/react';
4
+ import { ReactFlowProvider } from '@xyflow/react';
5
+ import { LayoutGroup } from 'motion/react';
6
+ import { useEffect, useRef } from 'react';
7
+ import { projectOverviewLogic } from './actor.js';
8
+ import { ProjectsOverviewActorContext } from './context.js';
9
+ import { ProjectsOverviewPanel } from './panel/ProjectsOverviewPanel.js';
10
+ import { ProjectsOverviewXY } from './ProjectsOverviewXY.js';
11
+
12
+ function ProjectsOverview({
13
+ view,
14
+ onNavigateToProject,
15
+ fitViewPadding = {
16
+ top: "50px",
17
+ bottom: "32px",
18
+ left: "32px",
19
+ right: "32px"
20
+ },
21
+ ...props
22
+ }) {
23
+ const actorRef = useActorRef(
24
+ projectOverviewLogic,
25
+ {
26
+ input: { view, fitViewPadding }
27
+ }
28
+ );
29
+ useEffect(() => {
30
+ actorRef.send({ type: "update.view", view });
31
+ }, [actorRef, view]);
32
+ const onNavigateToProjectRef = useSyncedRef(onNavigateToProject);
33
+ useEffect(() => {
34
+ const subs = [
35
+ actorRef.on("navigate.to", ({ projectId }) => {
36
+ onNavigateToProjectRef.current?.(projectId);
37
+ })
38
+ ];
39
+ return () => {
40
+ subs.forEach((sub) => sub.unsubscribe());
41
+ };
42
+ }, [actorRef]);
43
+ const bounds = view.bounds;
44
+ const initialRef = useRef({
45
+ initialNodes: [],
46
+ initialEdges: [],
47
+ initialWidth: bounds.width,
48
+ initialHeight: bounds.height,
49
+ fitView: false
50
+ });
51
+ return /* @__PURE__ */ jsx(ProjectsOverviewActorContext.Provider, { value: actorRef, children: /* @__PURE__ */ jsxs(ReactFlowProvider, { ...initialRef.current, children: [
52
+ /* @__PURE__ */ jsx(LayoutGroup, { id: actorRef.sessionId, inherit: false, children: /* @__PURE__ */ jsx(ProjectsOverviewXY, { ...props }) }),
53
+ /* @__PURE__ */ jsx(ProjectsOverviewPanel, {})
54
+ ] }) });
55
+ }
56
+
57
+ export { ProjectsOverview };
@@ -0,0 +1,17 @@
1
+ import { ProjectsOverviewTypes } from './_types';
2
+ import { FunctionComponent, NamedExoticComponent } from 'react';
3
+ export declare const edgeTypes: {
4
+ relationship: FunctionComponent<ProjectsOverviewTypes.EdgeProps>;
5
+ };
6
+ export type ProjectsOverviewXYProps = {
7
+ /**
8
+ * Background pattern
9
+ * @default 'dots'
10
+ */
11
+ background?: 'dots' | 'lines' | 'cross' | 'transparent' | 'solid' | undefined;
12
+ /**
13
+ * @default - determined by the user's system preferences.
14
+ */
15
+ colorScheme?: 'light' | 'dark' | undefined;
16
+ };
17
+ export declare const ProjectsOverviewXY: NamedExoticComponent<ProjectsOverviewXYProps>;
@@ -0,0 +1,98 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { cx } from '@likec4/styles/css';
3
+ import { shallowEqual } from 'fast-equals';
4
+ import { memo } from 'react';
5
+ import { BaseXYFlow } from '../base/BaseXYFlow.js';
6
+ import { useCallbackRef } from '../hooks/useCallbackRef.js';
7
+ import { useProjectsOverviewActor } from './context.js';
8
+ import { useProjectsOverviewState, useProjectsOverviewXYStoreApi } from './hooks.js';
9
+ import { RelationshipEdge } from './custom/edgeTypes.js';
10
+ import { ProjectNode } from './custom/nodeTypes.js';
11
+
12
+ const nodeTypes = {
13
+ project: ProjectNode
14
+ };
15
+ const edgeTypes = {
16
+ relationship: RelationshipEdge
17
+ };
18
+ const selector = (state) => ({
19
+ isActive: state.hasTag("active"),
20
+ nodes: state.context.xynodes,
21
+ edges: state.context.xyedges
22
+ });
23
+ const selectorEq = (a, b) => a.isActive === b.isActive && shallowEqual(a.nodes, b.nodes) && shallowEqual(a.edges, b.edges);
24
+ const ProjectsOverviewXY = memo(({
25
+ background = "dots",
26
+ ...props
27
+ }) => {
28
+ const actorRef = useProjectsOverviewActor();
29
+ const {
30
+ isActive,
31
+ nodes,
32
+ edges
33
+ } = useProjectsOverviewState(
34
+ selector,
35
+ selectorEq
36
+ );
37
+ const xystore = useProjectsOverviewXYStoreApi();
38
+ return /* @__PURE__ */ jsx(
39
+ BaseXYFlow,
40
+ {
41
+ nodes,
42
+ edges,
43
+ className: cx(
44
+ isActive ? "initialized" : "not-initialized",
45
+ "projects-overview"
46
+ ),
47
+ nodeTypes,
48
+ edgeTypes,
49
+ fitView: false,
50
+ onNodeClick: useCallbackRef((_e, node) => {
51
+ _e.stopPropagation();
52
+ actorRef.send({ type: "xyflow.click.node", node });
53
+ }),
54
+ onEdgeClick: useCallbackRef((_e, edge) => {
55
+ _e.stopPropagation();
56
+ actorRef.send({ type: "xyflow.click.edge", edge });
57
+ }),
58
+ onPaneClick: useCallbackRef((_e) => {
59
+ _e.stopPropagation();
60
+ actorRef.send({ type: "xyflow.click.pane" });
61
+ }),
62
+ onDoubleClick: useCallbackRef((_e) => {
63
+ _e.stopPropagation();
64
+ actorRef.send({ type: "xyflow.click.double" });
65
+ }),
66
+ onNodesChange: useCallbackRef((changes) => {
67
+ actorRef.send({ type: "xyflow.applyNodeChanges", changes });
68
+ }),
69
+ onEdgesChange: useCallbackRef((changes) => {
70
+ actorRef.send({ type: "xyflow.applyEdgeChanges", changes });
71
+ }),
72
+ onEdgeMouseEnter: useCallbackRef((event, edge) => {
73
+ actorRef.send({ type: "xyflow.mouse.enter.edge", edge, event });
74
+ }),
75
+ onEdgeMouseLeave: useCallbackRef((event, edge) => {
76
+ actorRef.send({ type: "xyflow.mouse.leave.edge", edge, event });
77
+ }),
78
+ onNodeMouseEnter: useCallbackRef((event, node) => {
79
+ actorRef.send({ type: "xyflow.mouse.enter.node", node });
80
+ }),
81
+ onNodeMouseLeave: useCallbackRef((event, node) => {
82
+ actorRef.send({ type: "xyflow.mouse.leave.node", node });
83
+ }),
84
+ onInit: useCallbackRef((xyflow) => {
85
+ actorRef.send({ type: "xyflow.init", xyflow, xystore });
86
+ }),
87
+ nodesDraggable: false,
88
+ nodesSelectable: true,
89
+ pannable: true,
90
+ zoomable: true,
91
+ background,
92
+ ...props
93
+ }
94
+ );
95
+ });
96
+ ProjectsOverviewXY.displayName = "ProjectsOverviewXY";
97
+
98
+ export { ProjectsOverviewXY, edgeTypes };
@@ -0,0 +1,34 @@
1
+ import { LayoutedProjectEdge } from '@likec4/core/compute-view';
2
+ import { DiagramNode, ExclusiveUnion, ProjectId } from '@likec4/core/types';
3
+ import { ReactFlowInstance, ReactFlowState } from '@xyflow/react';
4
+ import { FunctionComponent } from 'react';
5
+ import { Simplify } from 'type-fest';
6
+ import { BaseEdge, BaseEdgeData, BaseEdgeProps, BaseNode, BaseNodeData, BaseNodeProps, NonOptional } from '../base/types';
7
+ export declare namespace ProjectsOverviewTypes {
8
+ type ProjectNodeData = Simplify<BaseNodeData & NonOptional<Pick<DiagramNode, 'id' | 'title' | 'color' | 'shape' | 'style' | 'width' | 'height'>> & {
9
+ projectId: ProjectId;
10
+ }>;
11
+ type ProjectNode = BaseNode<ProjectNodeData, 'project'>;
12
+ type AnyNode = ProjectNode;
13
+ type NodeType = AnyNode['type'];
14
+ type Node<T extends NodeType = NodeType> = Extract<AnyNode, {
15
+ type: T;
16
+ }>;
17
+ type NodeProps<T extends NodeType = NodeType> = BaseNodeProps<Node<T>>;
18
+ type NodeData = ExclusiveUnion<{
19
+ ProjectNodeData: ProjectNodeData;
20
+ }>;
21
+ type NodeRenderer<T extends NodeType = NodeType> = FunctionComponent<NodeProps<T>>;
22
+ type NodeRenderers = {
23
+ [T in NodeType]: NodeRenderer<T>;
24
+ };
25
+ type EdgeData = Simplify<BaseEdgeData & NonOptional<Pick<LayoutedProjectEdge, 'id' | 'label' | 'labelBBox' | 'technology' | 'projectId' | 'points' | 'color' | 'line'>>>;
26
+ type Edge = BaseEdge<EdgeData, 'relationship'>;
27
+ type EdgeProps = BaseEdgeProps<Edge>;
28
+ }
29
+ export type ProjectsOverviewXYFLowInstance = ReactFlowInstance<ProjectsOverviewTypes.Node, ProjectsOverviewTypes.Edge>;
30
+ export type ProjectsOverviewXYStoreState = ReactFlowState<ProjectsOverviewTypes.Node, ProjectsOverviewTypes.Edge>;
31
+ export type ProjectsOverviewXYStoreApi = {
32
+ getState: () => ProjectsOverviewXYStoreState;
33
+ setState: (state: ProjectsOverviewXYStoreState) => void;
34
+ };