@likec4/diagram 1.0.0-next.2 → 1.0.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/dist/LikeC4Diagram.css.d.ts +0 -1
- package/dist/LikeC4Diagram.d.ts +1 -2
- package/dist/LikeC4Diagram.props.d.ts +24 -25
- package/dist/StaticLikeC4Diagram.d.ts +1 -2
- package/dist/globals.css.d.ts +1 -0
- package/dist/hooks/index.d.ts +2 -3
- package/dist/hooks/useSetState.d.ts +3 -0
- package/dist/hooks/useUpdateEffect.d.ts +4 -0
- package/dist/icons/Clipboard.d.ts +0 -1
- package/dist/icons/Link.d.ts +0 -1
- package/dist/icons/ZoomIn.d.ts +0 -1
- package/dist/icons/index.d.ts +0 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.mjs +9388 -0
- package/dist/mantine/EnsureMantine.d.ts +2 -4
- package/dist/mantine/theme.d.ts +3 -0
- package/dist/mantine.css.d.ts +1 -0
- package/dist/state/DiagramContext.d.ts +386 -0
- package/dist/state/WhenInitialized.d.ts +3 -0
- package/dist/state/diagramStore.d.ts +428 -0
- package/dist/state/index.d.ts +4 -2
- package/dist/state/useDiagramStore.d.ts +387 -0
- package/dist/style.css +1212 -1
- package/dist/theme.css.d.ts +16 -2
- package/dist/ui/Camera.d.ts +0 -1
- package/dist/ui/KeepAspectRatio.css.d.ts +0 -1
- package/dist/ui/KeepAspectRatio.d.ts +0 -1
- package/dist/ui/OptionsPanel.css.d.ts +0 -1
- package/dist/ui/OptionsPanel.d.ts +0 -1
- package/dist/ui/index.d.ts +0 -1
- package/dist/ui/options/NodeOptions.d.ts +0 -1
- package/dist/xyflow/FitviewOnDiagramChange.d.ts +1 -5
- package/dist/xyflow/SyncWithDiagram.d.ts +5 -0
- package/dist/xyflow/XYFlowBackground.d.ts +0 -1
- package/dist/xyflow/XYFlowEvents.d.ts +5 -15
- package/dist/xyflow/XYFlowWrapper.d.ts +4 -5
- package/dist/xyflow/const.d.ts +1 -2
- package/dist/xyflow/diagram-to-xyflow.d.ts +4 -2
- package/dist/xyflow/edges/RelationshipEdge.d.ts +7 -7
- package/dist/xyflow/edges/edges.css.d.ts +2 -1
- package/dist/xyflow/edges/utils.d.ts +3 -4
- package/dist/xyflow/hooks/index.d.ts +2 -37
- package/dist/xyflow/hooks/{use-layout-/321/201onstraints.d.ts → useLayoutConstraints.d.ts} +2 -4
- package/dist/xyflow/hooks/useXYFlow.d.ts +266 -0
- package/dist/xyflow/nodes/compound/CompoundNode.css.d.ts +0 -1
- package/dist/xyflow/nodes/compound/CompoundNode.d.ts +0 -1
- package/dist/xyflow/nodes/compound/index.d.ts +0 -1
- package/dist/xyflow/nodes/element/ElementIcon.d.ts +1 -2
- package/dist/xyflow/nodes/element/ElementLink.css.d.ts +0 -1
- package/dist/xyflow/nodes/element/ElementLink.d.ts +1 -2
- package/dist/xyflow/nodes/element/ElementNode.d.ts +1 -3
- package/dist/xyflow/nodes/element/ElementShapeSvg.d.ts +2 -3
- package/dist/xyflow/nodes/element/element.css.d.ts +0 -1
- package/dist/xyflow/nodes/element/index.d.ts +1 -2
- package/dist/xyflow/nodes/shared/NavigateToBtn.d.ts +0 -1
- package/dist/xyflow/types.d.ts +20 -8
- package/dist/xyflow/utils.d.ts +0 -1
- package/package.json +36 -34
- package/src/LikeC4Diagram.css.ts +31 -0
- package/src/LikeC4Diagram.props.ts +154 -0
- package/src/LikeC4Diagram.tsx +119 -0
- package/src/StaticLikeC4Diagram.tsx +39 -0
- package/src/globals.css.ts +128 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useSetState.ts +19 -0
- package/src/hooks/useUpdateEffect.ts +28 -0
- package/src/icons/Clipboard.tsx +24 -0
- package/src/icons/Link.tsx +23 -0
- package/src/icons/ZoomIn.tsx +25 -0
- package/src/icons/index.ts +3 -0
- package/src/index.ts +11 -0
- package/src/mantine/EnsureMantine.tsx +14 -0
- package/src/mantine/theme.ts +19 -0
- package/src/mantine.css.ts +4 -0
- package/src/reset.d.ts +2 -0
- package/src/state/DiagramContext.tsx +42 -0
- package/src/state/WhenInitialized.tsx +24 -0
- package/src/state/diagramStore.ts +358 -0
- package/src/state/index.ts +4 -0
- package/src/state/useDiagramStore.ts +39 -0
- package/src/theme.css.ts +64 -0
- package/src/ui/Camera.tsx +174 -0
- package/src/ui/KeepAspectRatio.css.ts +7 -0
- package/src/ui/KeepAspectRatio.tsx +35 -0
- package/src/ui/OptionsPanel.css.ts +10 -0
- package/src/ui/OptionsPanel.tsx +65 -0
- package/src/ui/index.ts +3 -0
- package/src/ui/options/NodeOptions.tsx +253 -0
- package/src/xyflow/FitviewOnDiagramChange.tsx +93 -0
- package/src/xyflow/SyncWithDiagram.tsx +113 -0
- package/src/xyflow/XYFlowBackground.tsx +33 -0
- package/src/xyflow/XYFlowEvents.tsx +100 -0
- package/src/xyflow/XYFlowWrapper.tsx +166 -0
- package/src/xyflow/const.ts +7 -0
- package/src/xyflow/diagram-to-xyflow.ts +197 -0
- package/src/xyflow/edges/RelationshipEdge.tsx +288 -0
- package/src/xyflow/edges/edges.css.ts +124 -0
- package/src/xyflow/edges/utils.ts +110 -0
- package/src/xyflow/hooks/index.ts +2 -0
- package/src/xyflow/hooks/useLayoutConstraints.ts +289 -0
- package/src/xyflow/hooks/useXYFlow.ts +20 -0
- package/src/xyflow/nodes/compound/CompoundNode.css.ts +191 -0
- package/src/xyflow/nodes/compound/CompoundNode.tsx +105 -0
- package/src/xyflow/nodes/compound/index.ts +1 -0
- package/src/xyflow/nodes/element/ElementIcon.tsx +44 -0
- package/src/xyflow/nodes/element/ElementLink.css.ts +67 -0
- package/src/xyflow/nodes/element/ElementLink.tsx +94 -0
- package/src/xyflow/nodes/element/ElementNode.tsx +225 -0
- package/src/xyflow/nodes/element/ElementShapeSvg.tsx +181 -0
- package/src/xyflow/nodes/element/element.css.ts +261 -0
- package/src/xyflow/nodes/element/index.ts +1 -0
- package/src/xyflow/nodes/shared/NavigateToBtn.tsx +25 -0
- package/src/xyflow/types.ts +100 -0
- package/src/xyflow/utils.ts +12 -0
- package/dist/EmbeddedLikeC4Diagram.css.d.ts +0 -6
- package/dist/EmbeddedLikeC4Diagram.d.ts +0 -18
- package/dist/bundle.d.ts +0 -3
- package/dist/hooks/use-set-state.d.ts +0 -2
- package/dist/hooks/use-update-effect.d.ts +0 -4
- package/dist/index.css.d.ts +0 -2
- package/dist/index.js +0 -13043
- package/dist/mantine/index.d.ts +0 -3
- package/dist/state/DiagramState.d.ts +0 -162
- package/dist/xyflow/UpdateOnDiagramChange.d.ts +0 -10
package/dist/xyflow/types.d.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { SetReadonly, SetRequired, Simplify } from 'type-fest';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { MouseEvent as ReactMouseEvent } from 'react';
|
|
3
|
+
import { Edge, EdgeMouseHandler, InternalNode, Node, NodeMouseHandler, OnMoveEnd, OnMoveStart, ReactFlowInstance, ReactFlowState } from '@xyflow/react';
|
|
4
|
+
import { BBox, DiagramEdge, DiagramNode, Fqn, Point } from '@likec4/core';
|
|
4
5
|
|
|
5
6
|
export type ElementNodeData = {
|
|
6
|
-
|
|
7
|
+
fqn: Fqn;
|
|
7
8
|
element: DiagramNode;
|
|
8
9
|
};
|
|
9
10
|
type TypedXYFlowNode<D extends Record<string, unknown>, T extends string> = SetReadonly<SetRequired<Node<D, T>, 'type'>, 'id' | 'type'>;
|
|
10
11
|
export type ElementXYFlowNode = TypedXYFlowNode<ElementNodeData, 'element'>;
|
|
11
12
|
export type CompoundNodeData = {
|
|
12
|
-
|
|
13
|
+
fqn: Fqn;
|
|
13
14
|
element: DiagramNode;
|
|
14
15
|
};
|
|
15
16
|
export type CompoundXYFlowNode = TypedXYFlowNode<CompoundNodeData, 'compound'>;
|
|
16
17
|
export type XYFlowNode = ElementXYFlowNode | CompoundXYFlowNode;
|
|
18
|
+
export type InternalXYFlowNode = InternalNode<XYFlowNode>;
|
|
17
19
|
export declare namespace XYFlowNode {
|
|
18
20
|
type Data = ElementNodeData | CompoundNodeData;
|
|
19
21
|
function isCompound(node: unknown): node is CompoundXYFlowNode;
|
|
@@ -42,11 +44,13 @@ export declare namespace XYFlowEdge {
|
|
|
42
44
|
target: string;
|
|
43
45
|
style?: import('react').CSSProperties;
|
|
44
46
|
id: string;
|
|
47
|
+
zIndex?: number;
|
|
48
|
+
markerEnd?: import('@xyflow/react').EdgeMarkerType;
|
|
49
|
+
markerStart?: import('@xyflow/react').EdgeMarkerType;
|
|
45
50
|
hidden?: boolean;
|
|
46
51
|
selected?: boolean;
|
|
47
52
|
selectable?: boolean;
|
|
48
53
|
deletable?: boolean;
|
|
49
|
-
zIndex?: number;
|
|
50
54
|
ariaLabel?: string;
|
|
51
55
|
className?: string;
|
|
52
56
|
focusable?: boolean;
|
|
@@ -54,8 +58,6 @@ export declare namespace XYFlowEdge {
|
|
|
54
58
|
sourceHandle?: string | null;
|
|
55
59
|
targetHandle?: string | null;
|
|
56
60
|
animated?: boolean;
|
|
57
|
-
markerStart?: import('@xyflow/react').EdgeMarkerType;
|
|
58
|
-
markerEnd?: import('@xyflow/react').EdgeMarkerType;
|
|
59
61
|
interactionWidth?: number;
|
|
60
62
|
labelStyle?: import('react').CSSProperties;
|
|
61
63
|
labelShowBg?: boolean;
|
|
@@ -68,9 +70,19 @@ export declare namespace XYFlowEdge {
|
|
|
68
70
|
};
|
|
69
71
|
}
|
|
70
72
|
export type XYFlowInstance = ReactFlowInstance<XYFlowNode, XYFlowEdge>;
|
|
73
|
+
export type XYFlowState = ReactFlowState<XYFlowNode, XYFlowEdge>;
|
|
71
74
|
export type XYFlowData = {
|
|
72
75
|
nodes: XYFlowNode[];
|
|
73
76
|
edges: XYFlowEdge[];
|
|
74
77
|
};
|
|
78
|
+
export type XYFlowEventHandlers = {
|
|
79
|
+
onPanelClick: (event: ReactMouseEvent) => void;
|
|
80
|
+
onNodeContextMenu: NodeMouseHandler<XYFlowNode>;
|
|
81
|
+
onEdgeContextMenu: EdgeMouseHandler<XYFlowEdge>;
|
|
82
|
+
onPaneContextMenu: (event: ReactMouseEvent | MouseEvent) => void;
|
|
83
|
+
onNodeClick: NodeMouseHandler<XYFlowNode>;
|
|
84
|
+
onEdgeClick: EdgeMouseHandler<XYFlowEdge>;
|
|
85
|
+
onMoveStart: OnMoveStart;
|
|
86
|
+
onMoveEnd: OnMoveEnd;
|
|
87
|
+
};
|
|
75
88
|
export {};
|
|
76
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/xyflow/utils.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@likec4/diagram",
|
|
3
|
-
"version": "1.0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
6
6
|
"homepage": "https://likec4.dev",
|
|
@@ -15,43 +15,50 @@
|
|
|
15
15
|
"LICENSE",
|
|
16
16
|
"README.md",
|
|
17
17
|
"dist",
|
|
18
|
+
"src",
|
|
19
|
+
"!dist/src",
|
|
18
20
|
"!**/*.spec.*",
|
|
19
|
-
"!**/*.map"
|
|
20
|
-
],
|
|
21
|
-
"sideEffects": [
|
|
22
|
-
"**/*.css"
|
|
21
|
+
"!**/*.d.ts.map"
|
|
23
22
|
],
|
|
23
|
+
"sideEffects": false,
|
|
24
24
|
"type": "module",
|
|
25
25
|
"exports": {
|
|
26
26
|
".": {
|
|
27
27
|
"types": "./dist/index.d.ts",
|
|
28
|
-
"
|
|
29
|
-
"default": "./dist/index.js"
|
|
28
|
+
"default": "./dist/index.mjs"
|
|
30
29
|
},
|
|
31
|
-
"./style.css": "./dist/style.css"
|
|
32
|
-
"./dist/style.css": "./dist/style.css"
|
|
30
|
+
"./style.css": "./dist/style.css"
|
|
33
31
|
},
|
|
34
32
|
"publishConfig": {
|
|
35
33
|
"registry": "https://registry.npmjs.org",
|
|
36
|
-
"access": "public"
|
|
34
|
+
"access": "public",
|
|
35
|
+
"exports": {
|
|
36
|
+
".": {
|
|
37
|
+
"types": "./dist/index.d.ts",
|
|
38
|
+
"default": "./dist/index.mjs"
|
|
39
|
+
},
|
|
40
|
+
"./style.css": "./dist/style.css"
|
|
41
|
+
}
|
|
37
42
|
},
|
|
38
43
|
"packageManager": "yarn@4.1.1",
|
|
39
44
|
"scripts": {
|
|
40
|
-
"typecheck": "tsc
|
|
45
|
+
"typecheck": "tsc",
|
|
46
|
+
"prepack": "vite build --mode production",
|
|
41
47
|
"build:turbo": "run -T turbo build --filter='diagram'",
|
|
42
|
-
"build": "vite build &&
|
|
48
|
+
"build": "vite build --mode development && tsc -b",
|
|
43
49
|
"lint": "run -T eslint src/ --fix",
|
|
44
|
-
"clean": "run -T rimraf dist
|
|
50
|
+
"clean": "run -T rimraf -v dist/* .tsbuildinfo"
|
|
45
51
|
},
|
|
46
52
|
"dependencies": {
|
|
47
|
-
"@likec4/core": "1.0.0
|
|
48
|
-
"@mantine/core": "^7.
|
|
49
|
-
"@mantine/hooks": "^7.
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
53
|
+
"@likec4/core": "1.0.0",
|
|
54
|
+
"@mantine/core": "^7.9.0",
|
|
55
|
+
"@mantine/hooks": "^7.9.0",
|
|
56
|
+
"@react-hookz/web": "^24.0.4",
|
|
57
|
+
"esm-env": "^1.0.0",
|
|
58
|
+
"fast-equals": "^5.0.1",
|
|
59
|
+
"framer-motion": "^11.1.7",
|
|
60
|
+
"remeda": "^1.61.0",
|
|
61
|
+
"zustand": "^4.5.2"
|
|
55
62
|
},
|
|
56
63
|
"peerDependencies": {
|
|
57
64
|
"react": "^18.2.0",
|
|
@@ -59,30 +66,25 @@
|
|
|
59
66
|
},
|
|
60
67
|
"devDependencies": {
|
|
61
68
|
"@lume/kiwi": "^0.4.3",
|
|
62
|
-
"@mantine/vanilla-extract": "^7.
|
|
63
|
-
"@react-hookz/deep-equal": "^2.0.2",
|
|
64
|
-
"@react-hookz/web": "^24.0.4",
|
|
69
|
+
"@mantine/vanilla-extract": "^7.9.0",
|
|
65
70
|
"@total-typescript/ts-reset": "^0.5.1",
|
|
66
71
|
"@types/react": "^18.2.0",
|
|
67
72
|
"@types/react-dom": "^18.2.0",
|
|
68
|
-
"@vanilla-extract/css": "^1.
|
|
73
|
+
"@vanilla-extract/css": "^1.15.1",
|
|
69
74
|
"@vanilla-extract/dynamic": "^2.1.0",
|
|
70
75
|
"@vanilla-extract/esbuild-plugin": "^2.3.5",
|
|
71
|
-
"@vanilla-extract/recipes": "^0.5.2",
|
|
72
76
|
"@vitejs/plugin-react": "^4.2.1",
|
|
73
|
-
"@xyflow/react": "^12.0.0-next
|
|
74
|
-
"clsx": "^2.1.
|
|
77
|
+
"@xyflow/react": "^12.0.0-next",
|
|
78
|
+
"clsx": "^2.1.1",
|
|
75
79
|
"execa": "^8.0.1",
|
|
76
|
-
"fast-equals": "^5.0.1",
|
|
77
80
|
"khroma": "^2.1.0",
|
|
78
81
|
"react": "^18.2.0",
|
|
79
82
|
"react-dom": "^18.2.0",
|
|
80
|
-
"terser": "^5.30.0",
|
|
81
83
|
"tilg": "^0.1.1",
|
|
82
|
-
"
|
|
84
|
+
"type-fest": "^4.18.2",
|
|
85
|
+
"typescript": "^5.4.5",
|
|
83
86
|
"unbuild": "^2.0.0",
|
|
84
|
-
"vite": "^5.2.
|
|
85
|
-
"vite-plugin-dts": "^3.8.1"
|
|
86
|
-
"vite-plugin-shadow-style": "^1.1.0"
|
|
87
|
+
"vite": "^5.2.11",
|
|
88
|
+
"vite-plugin-dts": "^3.8.1"
|
|
87
89
|
}
|
|
88
90
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { globalStyle, style } from '@vanilla-extract/css'
|
|
2
|
+
import { vars, xyvars } from './theme.css'
|
|
3
|
+
|
|
4
|
+
export const cssReactFlow = style({})
|
|
5
|
+
|
|
6
|
+
globalStyle(`.react-flow${cssReactFlow}`, {
|
|
7
|
+
vars: {
|
|
8
|
+
[xyvars.background.color]: vars.likec4.background.color,
|
|
9
|
+
[xyvars.background.pattern.color]: vars.likec4.background.pattern.color
|
|
10
|
+
}
|
|
11
|
+
})
|
|
12
|
+
globalStyle(`.react-flow${cssReactFlow} .react-flow__viewport`, {
|
|
13
|
+
willChange: 'transform'
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
export const cssDisablePan = style({})
|
|
17
|
+
|
|
18
|
+
export const cssTransparentBg = style({})
|
|
19
|
+
|
|
20
|
+
globalStyle(`.react-flow${cssReactFlow}${cssTransparentBg}`, {
|
|
21
|
+
backgroundColor: 'transparent !important',
|
|
22
|
+
vars: {
|
|
23
|
+
[vars.likec4.background.color]: 'transparent !important',
|
|
24
|
+
[xyvars.background.color]: 'transparent !important'
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
export const cssNoControls = style({})
|
|
29
|
+
globalStyle(`:where(${cssNoControls}, ${cssTransparentBg}) .react-flow__attribution`, {
|
|
30
|
+
display: 'none'
|
|
31
|
+
})
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DiagramEdge,
|
|
3
|
+
DiagramNode,
|
|
4
|
+
DiagramView,
|
|
5
|
+
ElementShape,
|
|
6
|
+
Fqn,
|
|
7
|
+
NonEmptyArray,
|
|
8
|
+
ThemeColor,
|
|
9
|
+
ViewID
|
|
10
|
+
} from '@likec4/core'
|
|
11
|
+
import type { MouseEvent as ReactMouseEvent } from 'react'
|
|
12
|
+
import type { SetRequired, Simplify } from 'type-fest'
|
|
13
|
+
import type { XYFlowEdge, XYFlowNode } from './xyflow/types'
|
|
14
|
+
import type { XYBackgroundProps } from './xyflow/XYFlowBackground'
|
|
15
|
+
|
|
16
|
+
export type DiagramNodeWithNavigate = Simplify<SetRequired<DiagramNode, 'navigateTo'>>
|
|
17
|
+
|
|
18
|
+
export type OnNavigateTo = {
|
|
19
|
+
(
|
|
20
|
+
to: ViewID,
|
|
21
|
+
event: ReactMouseEvent,
|
|
22
|
+
element: DiagramNodeWithNavigate,
|
|
23
|
+
xynode: XYFlowNode
|
|
24
|
+
): void
|
|
25
|
+
}
|
|
26
|
+
export type OnNodeClick = (
|
|
27
|
+
event: {
|
|
28
|
+
element: DiagramNode
|
|
29
|
+
xynode: XYFlowNode
|
|
30
|
+
event: ReactMouseEvent
|
|
31
|
+
}
|
|
32
|
+
) => void
|
|
33
|
+
export type OnEdgeClick = (
|
|
34
|
+
event: {
|
|
35
|
+
relation: DiagramEdge
|
|
36
|
+
xyedge: XYFlowEdge
|
|
37
|
+
event: ReactMouseEvent
|
|
38
|
+
}
|
|
39
|
+
) => void
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* On pane/canvas click (not on any node or edge)
|
|
43
|
+
*/
|
|
44
|
+
export type OnCanvasClick = (event: ReactMouseEvent) => void
|
|
45
|
+
|
|
46
|
+
export namespace Changes {
|
|
47
|
+
export interface ChangeColor {
|
|
48
|
+
op: 'change-color'
|
|
49
|
+
color: ThemeColor
|
|
50
|
+
targets: NonEmptyArray<Fqn>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface ChangeShape {
|
|
54
|
+
op: 'change-shape'
|
|
55
|
+
shape: ElementShape
|
|
56
|
+
targets: NonEmptyArray<Fqn>
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type Change =
|
|
61
|
+
| Changes.ChangeColor
|
|
62
|
+
| Changes.ChangeShape
|
|
63
|
+
|
|
64
|
+
export type ChangeEvent = {
|
|
65
|
+
changes: NonEmptyArray<Change>
|
|
66
|
+
}
|
|
67
|
+
export type OnChange = {
|
|
68
|
+
(event: ChangeEvent): void
|
|
69
|
+
}
|
|
70
|
+
export type LikeC4ColorScheme = 'light' | 'dark'
|
|
71
|
+
|
|
72
|
+
export interface LikeC4DiagramProperties {
|
|
73
|
+
view: DiagramView
|
|
74
|
+
|
|
75
|
+
className?: string | undefined
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Controls color scheme used for styling the flow
|
|
79
|
+
* By default inherits from system or surrounding MantineProvider
|
|
80
|
+
*
|
|
81
|
+
* @example 'light' | 'dark'
|
|
82
|
+
*/
|
|
83
|
+
// colorScheme?: LikeC4ColorScheme | undefined
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Show/hide controls menu
|
|
87
|
+
* @default false
|
|
88
|
+
*/
|
|
89
|
+
controls?: boolean | undefined
|
|
90
|
+
/**
|
|
91
|
+
* Enable/disable panning
|
|
92
|
+
* @default true
|
|
93
|
+
*/
|
|
94
|
+
pannable?: boolean | undefined
|
|
95
|
+
/**
|
|
96
|
+
* Enable/disable zooming
|
|
97
|
+
* @default true
|
|
98
|
+
*/
|
|
99
|
+
zoomable?: boolean | undefined
|
|
100
|
+
/**
|
|
101
|
+
* Disable any editing (dragging still can be enabled with `nodesDraggable`)
|
|
102
|
+
* @default true
|
|
103
|
+
*/
|
|
104
|
+
readonly?: boolean | undefined
|
|
105
|
+
/**
|
|
106
|
+
* If set, initial viewport will show all nodes & edges
|
|
107
|
+
* @default true
|
|
108
|
+
*/
|
|
109
|
+
fitView?: boolean | undefined
|
|
110
|
+
/**
|
|
111
|
+
* Seems like this is percentage of the view size
|
|
112
|
+
* @default 0
|
|
113
|
+
*/
|
|
114
|
+
fitViewPadding?: number | undefined
|
|
115
|
+
nodesSelectable?: boolean | undefined
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @default false
|
|
119
|
+
*/
|
|
120
|
+
nodesDraggable?: boolean | undefined
|
|
121
|
+
|
|
122
|
+
initialWidth?: number | undefined
|
|
123
|
+
initialHeight?: number | undefined
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Keep aspect ratio of the diagram
|
|
127
|
+
* @default false
|
|
128
|
+
*/
|
|
129
|
+
keepAspectRatio?: boolean | undefined
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Background pattern
|
|
133
|
+
* @default 'dots'
|
|
134
|
+
*/
|
|
135
|
+
background?: 'transparent' | 'solid' | XYBackgroundProps | undefined
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Display hovercards with element links
|
|
139
|
+
* @default true
|
|
140
|
+
*/
|
|
141
|
+
showElementLinks?: boolean | undefined
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface LikeC4DiagramEventHandlers {
|
|
145
|
+
onChange?: OnChange | null | undefined
|
|
146
|
+
onNavigateTo?: OnNavigateTo | null | undefined
|
|
147
|
+
onNodeClick?: OnNodeClick | null | undefined
|
|
148
|
+
onNodeContextMenu?: OnNodeClick | null | undefined
|
|
149
|
+
onCanvasContextMenu?: OnCanvasClick | null | undefined
|
|
150
|
+
onEdgeClick?: OnEdgeClick | null | undefined
|
|
151
|
+
onEdgeContextMenu?: OnEdgeClick | null | undefined
|
|
152
|
+
onCanvasClick?: OnCanvasClick | null | undefined
|
|
153
|
+
onCanvasDblClick?: OnCanvasClick | null | undefined
|
|
154
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { ReactFlowProvider as XYFlowProvider } from '@xyflow/react'
|
|
2
|
+
import clsx from 'clsx'
|
|
3
|
+
import { useRef } from 'react'
|
|
4
|
+
import { rootClassName } from './globals.css'
|
|
5
|
+
import { cssDisablePan, cssNoControls, cssReactFlow, cssTransparentBg } from './LikeC4Diagram.css'
|
|
6
|
+
import { type LikeC4DiagramEventHandlers, type LikeC4DiagramProperties } from './LikeC4Diagram.props'
|
|
7
|
+
import { EnsureMantine } from './mantine/EnsureMantine'
|
|
8
|
+
import { DiagramContextProvider } from './state/DiagramContext'
|
|
9
|
+
import { WhenInitialized } from './state/WhenInitialized'
|
|
10
|
+
import { KeepAspectRatio } from './ui/KeepAspectRatio'
|
|
11
|
+
import OptionsPanel from './ui/OptionsPanel'
|
|
12
|
+
import { diagramViewToXYFlowData } from './xyflow/diagram-to-xyflow'
|
|
13
|
+
import { FitViewOnDiagramChange } from './xyflow/FitviewOnDiagramChange'
|
|
14
|
+
import { SyncWithDiagram } from './xyflow/SyncWithDiagram'
|
|
15
|
+
import type { XYFlowData } from './xyflow/types'
|
|
16
|
+
import { XYFlow } from './xyflow/XYFlowWrapper'
|
|
17
|
+
|
|
18
|
+
export type LikeC4DiagramProps = LikeC4DiagramProperties & LikeC4DiagramEventHandlers
|
|
19
|
+
export function LikeC4Diagram({
|
|
20
|
+
view,
|
|
21
|
+
className,
|
|
22
|
+
fitView = true,
|
|
23
|
+
fitViewPadding = 0,
|
|
24
|
+
readonly = true,
|
|
25
|
+
pannable = true,
|
|
26
|
+
zoomable = true,
|
|
27
|
+
nodesSelectable = !readonly,
|
|
28
|
+
nodesDraggable = !readonly,
|
|
29
|
+
background = 'dots',
|
|
30
|
+
controls = false,
|
|
31
|
+
showElementLinks = true,
|
|
32
|
+
initialWidth,
|
|
33
|
+
initialHeight,
|
|
34
|
+
keepAspectRatio = false,
|
|
35
|
+
onCanvasClick,
|
|
36
|
+
onCanvasContextMenu,
|
|
37
|
+
onCanvasDblClick,
|
|
38
|
+
onEdgeClick,
|
|
39
|
+
onChange,
|
|
40
|
+
onEdgeContextMenu,
|
|
41
|
+
onNavigateTo,
|
|
42
|
+
onNodeClick,
|
|
43
|
+
onNodeContextMenu
|
|
44
|
+
}: LikeC4DiagramProps) {
|
|
45
|
+
const initialRef = useRef<{
|
|
46
|
+
defaultNodes: XYFlowData['nodes']
|
|
47
|
+
defaultEdges: XYFlowData['edges']
|
|
48
|
+
initialWidth: number
|
|
49
|
+
initialHeight: number
|
|
50
|
+
}>()
|
|
51
|
+
if (!initialRef.current) {
|
|
52
|
+
const initial = diagramViewToXYFlowData(view, {
|
|
53
|
+
selectable: nodesSelectable,
|
|
54
|
+
draggable: nodesDraggable
|
|
55
|
+
})
|
|
56
|
+
initialRef.current = {
|
|
57
|
+
defaultNodes: initial.nodes,
|
|
58
|
+
defaultEdges: initial.edges,
|
|
59
|
+
initialWidth: initialWidth ?? view.width,
|
|
60
|
+
initialHeight: initialHeight ?? view.height
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return (
|
|
64
|
+
<EnsureMantine>
|
|
65
|
+
<XYFlowProvider
|
|
66
|
+
fitView={fitView}
|
|
67
|
+
{...initialRef.current}
|
|
68
|
+
>
|
|
69
|
+
<DiagramContextProvider
|
|
70
|
+
view={view}
|
|
71
|
+
readonly={readonly}
|
|
72
|
+
fitViewEnabled={fitView}
|
|
73
|
+
fitViewPadding={fitViewPadding}
|
|
74
|
+
showElementLinks={showElementLinks}
|
|
75
|
+
nodesDraggable={nodesDraggable}
|
|
76
|
+
nodesSelectable={nodesSelectable}
|
|
77
|
+
onCanvasClick={onCanvasClick}
|
|
78
|
+
onCanvasContextMenu={onCanvasContextMenu}
|
|
79
|
+
onEdgeClick={onEdgeClick}
|
|
80
|
+
onEdgeContextMenu={onEdgeContextMenu}
|
|
81
|
+
onNodeClick={onNodeClick}
|
|
82
|
+
onNodeContextMenu={onNodeContextMenu}
|
|
83
|
+
onChange={onChange}
|
|
84
|
+
onNavigateTo={onNavigateTo}
|
|
85
|
+
onCanvasDblClick={onCanvasDblClick}
|
|
86
|
+
>
|
|
87
|
+
<KeepAspectRatio
|
|
88
|
+
className={clsx(rootClassName, className)}
|
|
89
|
+
enabled={keepAspectRatio}
|
|
90
|
+
width={view.width}
|
|
91
|
+
height={view.height}
|
|
92
|
+
>
|
|
93
|
+
<XYFlow
|
|
94
|
+
className={clsx(
|
|
95
|
+
'likec4-diagram',
|
|
96
|
+
cssReactFlow,
|
|
97
|
+
controls === false && cssNoControls,
|
|
98
|
+
pannable !== true && cssDisablePan,
|
|
99
|
+
background === 'transparent' && cssTransparentBg
|
|
100
|
+
)}
|
|
101
|
+
background={background}
|
|
102
|
+
controls={controls}
|
|
103
|
+
defaultNodes={initialRef.current.defaultNodes}
|
|
104
|
+
defaultEdges={initialRef.current.defaultEdges}
|
|
105
|
+
pannable={pannable}
|
|
106
|
+
zoomable={zoomable}
|
|
107
|
+
>
|
|
108
|
+
{readonly !== true && <OptionsPanel />}
|
|
109
|
+
</XYFlow>
|
|
110
|
+
</KeepAspectRatio>
|
|
111
|
+
<WhenInitialized>
|
|
112
|
+
<SyncWithDiagram />
|
|
113
|
+
<FitViewOnDiagramChange />
|
|
114
|
+
</WhenInitialized>
|
|
115
|
+
</DiagramContextProvider>
|
|
116
|
+
</XYFlowProvider>
|
|
117
|
+
</EnsureMantine>
|
|
118
|
+
)
|
|
119
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { LikeC4Diagram } from './LikeC4Diagram'
|
|
2
|
+
import type { LikeC4DiagramProperties } from './LikeC4Diagram.props'
|
|
3
|
+
|
|
4
|
+
export type StaticLikeC4DiagramProps = Pick<
|
|
5
|
+
LikeC4DiagramProperties,
|
|
6
|
+
| 'view'
|
|
7
|
+
| 'keepAspectRatio'
|
|
8
|
+
| 'className'
|
|
9
|
+
| 'fitView'
|
|
10
|
+
| 'fitViewPadding'
|
|
11
|
+
| 'background'
|
|
12
|
+
| 'initialWidth'
|
|
13
|
+
| 'initialHeight'
|
|
14
|
+
>
|
|
15
|
+
|
|
16
|
+
export function StaticLikeC4Diagram({
|
|
17
|
+
view,
|
|
18
|
+
fitView = true,
|
|
19
|
+
fitViewPadding = 0,
|
|
20
|
+
background = 'transparent',
|
|
21
|
+
...rest
|
|
22
|
+
}: StaticLikeC4DiagramProps) {
|
|
23
|
+
return (
|
|
24
|
+
<LikeC4Diagram
|
|
25
|
+
view={view}
|
|
26
|
+
readonly
|
|
27
|
+
fitView={fitView}
|
|
28
|
+
fitViewPadding={fitViewPadding}
|
|
29
|
+
pannable={false}
|
|
30
|
+
zoomable={false}
|
|
31
|
+
controls={false}
|
|
32
|
+
background={background}
|
|
33
|
+
showElementLinks
|
|
34
|
+
nodesSelectable={false}
|
|
35
|
+
nodesDraggable={false}
|
|
36
|
+
{...rest}
|
|
37
|
+
/>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type { ThemeColor } from '@likec4/core'
|
|
2
|
+
import { defaultTheme } from '@likec4/core'
|
|
3
|
+
import { createGlobalTheme } from '@vanilla-extract/css'
|
|
4
|
+
import { omit } from 'remeda'
|
|
5
|
+
import { mantine } from './mantine.css'
|
|
6
|
+
import { vars } from './theme.css'
|
|
7
|
+
|
|
8
|
+
export const rootClassName = 'likec4-diagram-root'
|
|
9
|
+
|
|
10
|
+
createGlobalTheme(`.${rootClassName}`, {
|
|
11
|
+
...omit(vars, ['optionsPanel', 'default'])
|
|
12
|
+
}, {
|
|
13
|
+
likec4: {
|
|
14
|
+
font:
|
|
15
|
+
`var(--likec4-default-font-family,'ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"')`,
|
|
16
|
+
background: {
|
|
17
|
+
color: mantine.colors.body,
|
|
18
|
+
pattern: {
|
|
19
|
+
color: mantine.colors.dimmed
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
compound: {
|
|
24
|
+
font: vars.likec4.font,
|
|
25
|
+
titleColor: vars.element.loContrast
|
|
26
|
+
},
|
|
27
|
+
element: {
|
|
28
|
+
font: vars.likec4.font,
|
|
29
|
+
...defaultTheme.elements.primary
|
|
30
|
+
},
|
|
31
|
+
relation: {
|
|
32
|
+
...defaultTheme.relationships.slate
|
|
33
|
+
}
|
|
34
|
+
// likec4: {
|
|
35
|
+
// font: `var(--likec4-font-family,'ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"')`,
|
|
36
|
+
// backgroundColor: fallbackVar(globalvars.likec4.backgroundColor, mantine.colors.body)
|
|
37
|
+
// },
|
|
38
|
+
// compound: {
|
|
39
|
+
// font: fallbackVar(vars.compound.font, vars.likec4.font),
|
|
40
|
+
// titleColor: fallbackVar(globalvars.compound.titleColor, globalvars.element.loContrast),
|
|
41
|
+
// },
|
|
42
|
+
// element: {
|
|
43
|
+
// font: fallbackVar(globalvars.element.font, vars.likec4.font),
|
|
44
|
+
// fill: fallbackVar(globalvars.element.fill, defaultTheme.elements.primary.fill),
|
|
45
|
+
// stroke: fallbackVar(globalvars.element.stroke, defaultTheme.elements.primary.stroke),
|
|
46
|
+
// hiContrast: fallbackVar(globalvars.element.hiContrast, defaultTheme.elements.primary.hiContrast),
|
|
47
|
+
// loContrast: fallbackVar(globalvars.element.loContrast, defaultTheme.elements.primary.loContrast),
|
|
48
|
+
// },
|
|
49
|
+
// relation: {
|
|
50
|
+
// lineColor: fallbackVar(globalvars.relation.lineColor, defaultTheme.relationships.slate.lineColor),
|
|
51
|
+
// labelColor: fallbackVar(globalvars.relation.labelColor, defaultTheme.relationships.slate.labelColor),
|
|
52
|
+
// labelBgColor: fallbackVar(globalvars.relation.labelBgColor, defaultTheme.relationships.slate.labelBgColor),
|
|
53
|
+
// },
|
|
54
|
+
// optionsPanel: {
|
|
55
|
+
// top: globalvars.optionsPanel.top,
|
|
56
|
+
// right: globalvars.optionsPanel.right
|
|
57
|
+
// }
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
createGlobalTheme(`:where([data-mantine-color-scheme='light']) .${rootClassName}`, {
|
|
61
|
+
likec4: {
|
|
62
|
+
background: {
|
|
63
|
+
pattern: {
|
|
64
|
+
color: vars.likec4.background.pattern.color
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}, {
|
|
69
|
+
likec4: {
|
|
70
|
+
background: {
|
|
71
|
+
pattern: {
|
|
72
|
+
color: mantine.colors.dark[3]
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
// globalStyle(`${scope} *, ${scope} *::before, ${scope} *::after`, {
|
|
79
|
+
// boxSizing: 'border-box',
|
|
80
|
+
// outline: 'none',
|
|
81
|
+
// borderWidth: 0,
|
|
82
|
+
// borderStyle: 'solid',
|
|
83
|
+
// borderColor: 'transparent',
|
|
84
|
+
// })
|
|
85
|
+
|
|
86
|
+
// createGlobalTheme(':where(.likec4-diagram-root)', {
|
|
87
|
+
// ...omit(vars, ['optionsPanel', 'defaults']),
|
|
88
|
+
// }, {
|
|
89
|
+
// likec4: {
|
|
90
|
+
// font: `var(--likec4-default-font-family,'ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"')`,
|
|
91
|
+
// backgroundColor: mantine.colors.body
|
|
92
|
+
// },
|
|
93
|
+
// compound: {
|
|
94
|
+
// font: vars.likec4.font,
|
|
95
|
+
// titleColor: vars.element.loContrast
|
|
96
|
+
// },
|
|
97
|
+
// element: {
|
|
98
|
+
// font: vars.likec4.font,
|
|
99
|
+
// ...defaultTheme.elements.primary
|
|
100
|
+
// },
|
|
101
|
+
// relation: {
|
|
102
|
+
// ...defaultTheme.relationships.slate
|
|
103
|
+
// }
|
|
104
|
+
// })
|
|
105
|
+
|
|
106
|
+
for (const color of Object.keys(defaultTheme.elements)) {
|
|
107
|
+
if (!(color in defaultTheme.elements) || !(color in defaultTheme.relationships)) {
|
|
108
|
+
continue
|
|
109
|
+
}
|
|
110
|
+
createGlobalTheme(`:where([data-likec4-color='${color}'])`, {
|
|
111
|
+
element: {
|
|
112
|
+
fill: vars.element.fill,
|
|
113
|
+
stroke: vars.element.stroke,
|
|
114
|
+
hiContrast: vars.element.hiContrast,
|
|
115
|
+
loContrast: vars.element.loContrast
|
|
116
|
+
},
|
|
117
|
+
compound: {
|
|
118
|
+
titleColor: vars.compound.titleColor
|
|
119
|
+
},
|
|
120
|
+
relation: vars.relation
|
|
121
|
+
}, {
|
|
122
|
+
element: defaultTheme.elements[color as ThemeColor],
|
|
123
|
+
compound: {
|
|
124
|
+
titleColor: defaultTheme.elements[color as ThemeColor].loContrast
|
|
125
|
+
},
|
|
126
|
+
relation: defaultTheme.relationships[color as ThemeColor]
|
|
127
|
+
})
|
|
128
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { shallowEqual } from 'fast-equals'
|
|
2
|
+
import { useCallback, useState } from 'react'
|
|
3
|
+
import type { NonEmptyObject } from 'type-fest'
|
|
4
|
+
|
|
5
|
+
export function useSetState<T extends object>(initialState: T | (() => T)) {
|
|
6
|
+
const [state, _setState] = useState(initialState)
|
|
7
|
+
const setState = useCallback(
|
|
8
|
+
(statePartial: NonEmptyObject<Partial<T>> | ((current: T) => NonEmptyObject<Partial<T>>)) =>
|
|
9
|
+
_setState((current) => {
|
|
10
|
+
const next = {
|
|
11
|
+
...current,
|
|
12
|
+
...typeof statePartial === 'function' ? statePartial(current) : statePartial
|
|
13
|
+
}
|
|
14
|
+
return shallowEqual(current, next) ? current : next
|
|
15
|
+
}),
|
|
16
|
+
[]
|
|
17
|
+
)
|
|
18
|
+
return [state, setState] as const
|
|
19
|
+
}
|