@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.
- package/bundle/index.js +1548 -595
- package/dist/LikeC4Diagram.d.ts +1 -1
- package/dist/LikeC4Diagram.js +2 -2
- package/dist/LikeC4Diagram.props.d.ts +1 -1
- package/dist/LikeC4ProjectsOverview.d.ts +7 -0
- package/dist/LikeC4ProjectsOverview.js +32 -0
- package/dist/base-primitives/Markdown.d.ts +1 -1
- package/dist/base-primitives/compound/CompoundNodeContainer.d.ts +4 -3
- package/dist/base-primitives/compound/actionbtns.css.d.ts +1 -1
- package/dist/base-primitives/element/ElementNodeContainer.js +2 -3
- package/dist/base-primitives/element/ElementShape.js +109 -20
- package/dist/components/NavigationPanel.d.ts +11 -0
- package/dist/components/NavigationPanel.js +69 -0
- package/dist/context/DiagramEventHandlers.js +1 -1
- package/dist/context/IconRenderer.js +4 -1
- package/dist/hooks/useLikeC4Project.js +10 -2
- package/dist/hooks/useLikeC4Styles.js +0 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/likec4diagram/DiagramXYFlow.js +1 -0
- package/dist/likec4diagram/custom/nodes/toolbar/ColorButton.js +3 -3
- package/dist/likec4diagram/custom/nodes/toolbar/CompoundToolbar.js +1 -38
- package/dist/likec4diagram/custom/nodes/toolbar/ElementToolbar.js +29 -14
- package/dist/likec4diagram/custom/nodes/toolbar/Toolbar.js +9 -5
- package/dist/likec4diagram/custom/nodes/toolbar/_shared.d.ts +6 -1
- package/dist/likec4diagram/custom/nodes/toolbar/_shared.js +44 -8
- package/dist/likec4diagram/xyflow-sequence/utils.d.ts +1 -1
- package/dist/navigationpanel/NavigationPanelControls.js +2 -2
- package/dist/navigationpanel/_common.d.ts +1 -1
- package/dist/navigationpanel/controls/LogoButton.d.ts +1 -0
- package/dist/navigationpanel/controls/{BurgerButton.js → LogoButton.js} +5 -5
- package/dist/navigationpanel/controls/index.d.ts +1 -1
- package/dist/navigationpanel/styles.css.d.ts +1 -1
- 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
- package/dist/overlays/relationships-browser/custom/edgeTypes.js +0 -1
- package/dist/projects-overview/ProjectsOverview.d.ts +13 -0
- package/dist/projects-overview/ProjectsOverview.js +57 -0
- package/dist/projects-overview/ProjectsOverviewXY.d.ts +17 -0
- package/dist/projects-overview/ProjectsOverviewXY.js +98 -0
- package/dist/projects-overview/_types.d.ts +34 -0
- package/dist/projects-overview/actor.d.ts +121 -0
- package/dist/projects-overview/actor.js +382 -0
- package/dist/projects-overview/context.d.ts +4 -0
- package/dist/projects-overview/context.js +9 -0
- package/dist/projects-overview/custom/edgeTypes.d.ts +3 -0
- package/dist/projects-overview/custom/edgeTypes.js +23 -0
- package/dist/projects-overview/custom/index.d.ts +2 -0
- package/dist/projects-overview/custom/nodeTypes.d.ts +2 -0
- package/dist/projects-overview/custom/nodeTypes.js +45 -0
- package/dist/projects-overview/custom/styles.css.d.ts +1 -0
- package/dist/projects-overview/hooks.d.ts +5 -0
- package/dist/projects-overview/hooks.js +14 -0
- package/dist/projects-overview/index.d.ts +1 -0
- package/dist/projects-overview/layouted-to-xyflow.d.ts +6 -0
- package/dist/projects-overview/layouted-to-xyflow.js +49 -0
- package/dist/projects-overview/panel/ProjectsOverviewPanel.d.ts +1 -0
- package/dist/projects-overview/panel/ProjectsOverviewPanel.js +11 -0
- package/dist/projects-overview/persistence.d.ts +5 -0
- package/dist/projects-overview/persistence.js +24 -0
- package/dist/search/components/_shared.css.d.ts +1 -1
- package/dist/styles.css2.js +1 -1
- package/package.json +8 -8
- package/panda.buildinfo.json +62 -29
- package/styles-min.css +1 -1
- package/styles.css +1 -1
- package/dist/base-primitives/element/ElementNodeContainer.css.d.ts +0 -1
- package/dist/base-primitives/element/ElementNodeContainer.css.js +0 -39
- 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
|
-
|
|
46
|
+
BorderStyleOption,
|
|
38
47
|
{
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
92
|
+
BorderStyleOption,
|
|
77
93
|
{
|
|
78
|
-
|
|
79
|
-
|
|
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: "
|
|
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 {
|
|
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(
|
|
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(
|
|
60
|
-
/* @__PURE__ */ jsx(Box, { px: "
|
|
61
|
-
/* @__PURE__ */ jsx(
|
|
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: "
|
|
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: "
|
|
39
|
-
height: "
|
|
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: "
|
|
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: "
|
|
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:
|
|
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 {
|
|
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(
|
|
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 '
|
|
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
|
|
10
|
+
const LogoButton = () => {
|
|
11
11
|
const actor = useNavigationActor();
|
|
12
|
-
const {
|
|
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 (
|
|
24
|
+
if (onLogoClick && actor.isOpened()) {
|
|
25
25
|
setTimeout(() => {
|
|
26
|
-
|
|
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 {
|
|
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';
|
|
@@ -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 };
|
|
@@ -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
|
+
};
|