@likec4/diagram 1.0.1 → 1.1.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 (33) hide show
  1. package/dist/KeepAspectRatioContainer.d.ts +9 -0
  2. package/dist/LikeC4Diagram.css.d.ts +1 -0
  3. package/dist/index.mjs +243 -678
  4. package/dist/state/DiagramContext.d.ts +36 -9
  5. package/dist/state/diagramStore.d.ts +42 -12
  6. package/dist/state/useDiagramStore.d.ts +36 -9
  7. package/dist/style.css +600 -53
  8. package/dist/ui/index.d.ts +0 -1
  9. package/dist/xyflow/{XYFlowWrapper.d.ts → XYFlow.d.ts} +2 -2
  10. package/dist/xyflow/XYFlowEvents.d.ts +127 -13
  11. package/dist/xyflow/edges/RelationshipEdge.d.ts +2 -2
  12. package/dist/xyflow/hooks/useXYFlow.d.ts +20 -20
  13. package/dist/xyflow/nodes/compound/CompoundNode.css.d.ts +7 -5
  14. package/dist/xyflow/types.d.ts +2 -2
  15. package/package.json +9 -9
  16. package/src/{ui/KeepAspectRatio.tsx → KeepAspectRatioContainer.tsx} +7 -6
  17. package/src/LikeC4Diagram.css.ts +6 -0
  18. package/src/LikeC4Diagram.tsx +6 -6
  19. package/src/globals.css.ts +42 -37
  20. package/src/state/diagramStore.ts +26 -7
  21. package/src/ui/index.ts +0 -1
  22. package/src/xyflow/FitviewOnDiagramChange.tsx +24 -18
  23. package/src/xyflow/SyncWithDiagram.tsx +16 -10
  24. package/src/xyflow/{XYFlowWrapper.tsx → XYFlow.tsx} +17 -24
  25. package/src/xyflow/XYFlowEvents.tsx +96 -43
  26. package/src/xyflow/diagram-to-xyflow.ts +4 -4
  27. package/src/xyflow/nodes/compound/CompoundNode.css.ts +85 -39
  28. package/src/xyflow/nodes/compound/CompoundNode.tsx +29 -31
  29. package/src/xyflow/nodes/element/ElementNode.tsx +2 -2
  30. package/src/xyflow/nodes/shared/NavigateToBtn.tsx +2 -1
  31. package/dist/ui/KeepAspectRatio.css.d.ts +0 -1
  32. package/dist/ui/KeepAspectRatio.d.ts +0 -9
  33. package/src/ui/KeepAspectRatio.css.ts +0 -7
@@ -1,2 +1 @@
1
- export { KeepAspectRatio } from './KeepAspectRatio';
2
1
  export { default as OptionsPanel } from './OptionsPanel';
@@ -3,12 +3,12 @@ import { LikeC4DiagramProperties } from '../LikeC4Diagram.props';
3
3
  import { SetNonNullable, Simplify } from 'type-fest';
4
4
  import { CSSProperties, PropsWithChildren } from 'react';
5
5
 
6
- type OnlyExpectedProps = Required<Pick<LikeC4DiagramProperties, 'className' | 'controls' | 'pannable' | 'zoomable' | 'background'>>;
6
+ type OnlyExpectedProps = Required<Pick<LikeC4DiagramProperties, 'className' | 'controls' | 'background'>>;
7
7
  type XYFlowWrapperProps = Simplify<PropsWithChildren<SetNonNullable<OnlyExpectedProps> & {
8
8
  defaultNodes: XYFlowNode[];
9
9
  defaultEdges: XYFlowEdge[];
10
10
  style?: CSSProperties | undefined;
11
11
  }>>;
12
- declare function XYFlowWrapper({ className, children, defaultNodes, defaultEdges, pannable, zoomable, controls, background, style }: XYFlowWrapperProps): JSX.Element;
12
+ declare function XYFlowWrapper({ className, children, defaultNodes, defaultEdges, controls, background, style }: XYFlowWrapperProps): JSX.Element;
13
13
  export declare const XYFlow: typeof XYFlowWrapper;
14
14
  export {};
@@ -1,15 +1,129 @@
1
- import { XYFlowEdge, XYFlowNode } from './types';
2
- import { MouseEvent as ReactMouseEvent } from 'react';
3
- import { EdgeMouseHandler, NodeMouseHandler, OnMoveEnd } from '@xyflow/react';
1
+ import { XYFlowNode } from './types';
4
2
 
5
- type XYFlowEventHandlers = {
6
- onPaneClick: (event: ReactMouseEvent) => void;
7
- onNodeContextMenu: NodeMouseHandler<XYFlowNode>;
8
- onEdgeContextMenu: EdgeMouseHandler<XYFlowEdge>;
9
- onPaneContextMenu: (event: ReactMouseEvent | MouseEvent) => void;
10
- onNodeClick: NodeMouseHandler<XYFlowNode>;
11
- onEdgeClick: EdgeMouseHandler<XYFlowEdge>;
12
- onMoveEnd: OnMoveEnd;
3
+ export declare function useXYFlowEvents(): {
4
+ onDoubleClick: import('react').MouseEventHandler<HTMLDivElement> | undefined;
5
+ onNodeClick: import('@xyflow/react').NodeMouseHandler<XYFlowNode>;
6
+ onNodeContextMenu: import('@xyflow/react').NodeMouseHandler<XYFlowNode>;
7
+ onEdgeClick: (event: import('react').MouseEvent<Element, MouseEvent>, edge: {
8
+ source: string;
9
+ target: string;
10
+ style?: import('react').CSSProperties;
11
+ id: string;
12
+ zIndex?: number;
13
+ markerEnd?: import('@xyflow/react').EdgeMarkerType;
14
+ markerStart?: import('@xyflow/react').EdgeMarkerType;
15
+ hidden?: boolean;
16
+ className?: string;
17
+ label?: import('react').ReactNode;
18
+ selected?: boolean;
19
+ selectable?: boolean;
20
+ deletable?: boolean;
21
+ ariaLabel?: string;
22
+ focusable?: boolean;
23
+ sourceHandle?: string | null;
24
+ targetHandle?: string | null;
25
+ animated?: boolean;
26
+ interactionWidth?: number;
27
+ labelStyle?: import('react').CSSProperties;
28
+ labelShowBg?: boolean;
29
+ labelBgStyle?: import('react').CSSProperties;
30
+ labelBgPadding?: [number, number];
31
+ labelBgBorderRadius?: number;
32
+ updatable?: import('@xyflow/react').EdgeUpdatable;
33
+ data: import('./types').RelationshipData;
34
+ type: "relationship";
35
+ }) => void;
36
+ onEdgeContextMenu: import('@xyflow/react').EdgeMouseHandler<{
37
+ source: string;
38
+ target: string;
39
+ style?: import("react").CSSProperties;
40
+ id: string;
41
+ zIndex?: number;
42
+ markerEnd?: import("@xyflow/react").EdgeMarkerType;
43
+ markerStart?: import("@xyflow/react").EdgeMarkerType;
44
+ hidden?: boolean;
45
+ className?: string;
46
+ label?: import("react").ReactNode;
47
+ selected?: boolean;
48
+ selectable?: boolean;
49
+ deletable?: boolean;
50
+ ariaLabel?: string;
51
+ focusable?: boolean;
52
+ sourceHandle?: string | null;
53
+ targetHandle?: string | null;
54
+ animated?: boolean;
55
+ interactionWidth?: number;
56
+ labelStyle?: import("react").CSSProperties;
57
+ labelShowBg?: boolean;
58
+ labelBgStyle?: import("react").CSSProperties;
59
+ labelBgPadding?: [number, number];
60
+ labelBgBorderRadius?: number;
61
+ updatable?: import("@xyflow/react").EdgeUpdatable;
62
+ data: import("./types").RelationshipData;
63
+ type: "relationship";
64
+ }>;
65
+ onMoveEnd: import('@xyflow/react').OnMove;
66
+ onNodeDoubleClick: import('@xyflow/react').NodeMouseHandler<XYFlowNode>;
67
+ onNodeMouseEnter: import('@xyflow/react').NodeMouseHandler<XYFlowNode>;
68
+ onNodeMouseLeave: import('@xyflow/react').NodeMouseHandler<XYFlowNode>;
69
+ onEdgeMouseEnter: import('@xyflow/react').EdgeMouseHandler<{
70
+ source: string;
71
+ target: string;
72
+ style?: import("react").CSSProperties;
73
+ id: string;
74
+ zIndex?: number;
75
+ markerEnd?: import("@xyflow/react").EdgeMarkerType;
76
+ markerStart?: import("@xyflow/react").EdgeMarkerType;
77
+ hidden?: boolean;
78
+ className?: string;
79
+ label?: import("react").ReactNode;
80
+ selected?: boolean;
81
+ selectable?: boolean;
82
+ deletable?: boolean;
83
+ ariaLabel?: string;
84
+ focusable?: boolean;
85
+ sourceHandle?: string | null;
86
+ targetHandle?: string | null;
87
+ animated?: boolean;
88
+ interactionWidth?: number;
89
+ labelStyle?: import("react").CSSProperties;
90
+ labelShowBg?: boolean;
91
+ labelBgStyle?: import("react").CSSProperties;
92
+ labelBgPadding?: [number, number];
93
+ labelBgBorderRadius?: number;
94
+ updatable?: import("@xyflow/react").EdgeUpdatable;
95
+ data: import("./types").RelationshipData;
96
+ type: "relationship";
97
+ }>;
98
+ onEdgeMouseLeave: import('@xyflow/react').EdgeMouseHandler<{
99
+ source: string;
100
+ target: string;
101
+ style?: import("react").CSSProperties;
102
+ id: string;
103
+ zIndex?: number;
104
+ markerEnd?: import("@xyflow/react").EdgeMarkerType;
105
+ markerStart?: import("@xyflow/react").EdgeMarkerType;
106
+ hidden?: boolean;
107
+ className?: string;
108
+ label?: import("react").ReactNode;
109
+ selected?: boolean;
110
+ selectable?: boolean;
111
+ deletable?: boolean;
112
+ ariaLabel?: string;
113
+ focusable?: boolean;
114
+ sourceHandle?: string | null;
115
+ targetHandle?: string | null;
116
+ animated?: boolean;
117
+ interactionWidth?: number;
118
+ labelStyle?: import("react").CSSProperties;
119
+ labelShowBg?: boolean;
120
+ labelBgStyle?: import("react").CSSProperties;
121
+ labelBgPadding?: [number, number];
122
+ labelBgBorderRadius?: number;
123
+ updatable?: import("@xyflow/react").EdgeUpdatable;
124
+ data: import("./types").RelationshipData;
125
+ type: "relationship";
126
+ }>;
127
+ onPaneClick: (event: import('react').MouseEvent<Element, MouseEvent>) => void;
128
+ onPaneContextMenu: (event: MouseEvent | import('react').MouseEvent<Element, MouseEvent>) => void;
13
129
  };
14
- export declare function useXYFlowEvents(): XYFlowEventHandlers;
15
- export {};
@@ -10,13 +10,13 @@ export declare const RelationshipEdge: import('react').NamedExoticComponent<Edge
10
10
  markerEnd?: import("@xyflow/react").EdgeMarkerType;
11
11
  markerStart?: import("@xyflow/react").EdgeMarkerType;
12
12
  hidden?: boolean;
13
+ className?: string;
14
+ label?: import("react").ReactNode;
13
15
  selected?: boolean;
14
16
  selectable?: boolean;
15
17
  deletable?: boolean;
16
18
  ariaLabel?: string;
17
- className?: string;
18
19
  focusable?: boolean;
19
- label?: import("react").ReactNode;
20
20
  sourceHandle?: string | null;
21
21
  targetHandle?: string | null;
22
22
  animated?: boolean;
@@ -9,13 +9,13 @@ export declare const useXYFlow: () => import('@xyflow/react').ReactFlowInstance<
9
9
  markerEnd?: import("@xyflow/react").EdgeMarkerType;
10
10
  markerStart?: import("@xyflow/react").EdgeMarkerType;
11
11
  hidden?: boolean;
12
+ className?: string;
13
+ label?: import("react").ReactNode;
12
14
  selected?: boolean;
13
15
  selectable?: boolean;
14
16
  deletable?: boolean;
15
17
  ariaLabel?: string;
16
- className?: string;
17
18
  focusable?: boolean;
18
- label?: import("react").ReactNode;
19
19
  sourceHandle?: string | null;
20
20
  targetHandle?: string | null;
21
21
  animated?: boolean;
@@ -30,8 +30,8 @@ export declare const useXYFlow: () => import('@xyflow/react').ReactFlowInstance<
30
30
  type: "relationship";
31
31
  }>;
32
32
  export declare const useXYNodesData: {
33
- (nodeId: string): Pick<XYFlowNode, "id" | "type" | "data"> | null;
34
- (nodeIds: string[]): Pick<XYFlowNode, "id" | "type" | "data">[];
33
+ (nodeId: string): Pick<XYFlowNode, "id" | "data" | "type"> | null;
34
+ (nodeIds: string[]): Pick<XYFlowNode, "id" | "data" | "type">[];
35
35
  };
36
36
  export declare function useXYStore<StateSlice = unknown>(selector: (state: XYFlowState) => StateSlice, equalityFn?: (a: StateSlice, b: StateSlice) => boolean): StateSlice;
37
37
  export declare const useXYStoreApi: () => {
@@ -44,13 +44,13 @@ export declare const useXYStoreApi: () => {
44
44
  markerEnd?: import("@xyflow/react").EdgeMarkerType;
45
45
  markerStart?: import("@xyflow/react").EdgeMarkerType;
46
46
  hidden?: boolean;
47
+ className?: string;
48
+ label?: import("react").ReactNode;
47
49
  selected?: boolean;
48
50
  selectable?: boolean;
49
51
  deletable?: boolean;
50
52
  ariaLabel?: string;
51
- className?: string;
52
53
  focusable?: boolean;
53
- label?: import("react").ReactNode;
54
54
  sourceHandle?: string | null;
55
55
  targetHandle?: string | null;
56
56
  animated?: boolean;
@@ -73,13 +73,13 @@ export declare const useXYStoreApi: () => {
73
73
  markerEnd?: import("@xyflow/react").EdgeMarkerType;
74
74
  markerStart?: import("@xyflow/react").EdgeMarkerType;
75
75
  hidden?: boolean;
76
+ className?: string;
77
+ label?: import("react").ReactNode;
76
78
  selected?: boolean;
77
79
  selectable?: boolean;
78
80
  deletable?: boolean;
79
81
  ariaLabel?: string;
80
- className?: string;
81
82
  focusable?: boolean;
82
- label?: import("react").ReactNode;
83
83
  sourceHandle?: string | null;
84
84
  targetHandle?: string | null;
85
85
  animated?: boolean;
@@ -101,13 +101,13 @@ export declare const useXYStoreApi: () => {
101
101
  markerEnd?: import("@xyflow/react").EdgeMarkerType;
102
102
  markerStart?: import("@xyflow/react").EdgeMarkerType;
103
103
  hidden?: boolean;
104
+ className?: string;
105
+ label?: import("react").ReactNode;
104
106
  selected?: boolean;
105
107
  selectable?: boolean;
106
108
  deletable?: boolean;
107
109
  ariaLabel?: string;
108
- className?: string;
109
110
  focusable?: boolean;
110
- label?: import("react").ReactNode;
111
111
  sourceHandle?: string | null;
112
112
  targetHandle?: string | null;
113
113
  animated?: boolean;
@@ -129,13 +129,13 @@ export declare const useXYStoreApi: () => {
129
129
  markerEnd?: import("@xyflow/react").EdgeMarkerType;
130
130
  markerStart?: import("@xyflow/react").EdgeMarkerType;
131
131
  hidden?: boolean;
132
+ className?: string;
133
+ label?: import("react").ReactNode;
132
134
  selected?: boolean;
133
135
  selectable?: boolean;
134
136
  deletable?: boolean;
135
137
  ariaLabel?: string;
136
- className?: string;
137
138
  focusable?: boolean;
138
- label?: import("react").ReactNode;
139
139
  sourceHandle?: string | null;
140
140
  targetHandle?: string | null;
141
141
  animated?: boolean;
@@ -157,13 +157,13 @@ export declare const useXYStoreApi: () => {
157
157
  markerEnd?: import("@xyflow/react").EdgeMarkerType;
158
158
  markerStart?: import("@xyflow/react").EdgeMarkerType;
159
159
  hidden?: boolean;
160
+ className?: string;
161
+ label?: import("react").ReactNode;
160
162
  selected?: boolean;
161
163
  selectable?: boolean;
162
164
  deletable?: boolean;
163
165
  ariaLabel?: string;
164
- className?: string;
165
166
  focusable?: boolean;
166
- label?: import("react").ReactNode;
167
167
  sourceHandle?: string | null;
168
168
  targetHandle?: string | null;
169
169
  animated?: boolean;
@@ -185,13 +185,13 @@ export declare const useXYStoreApi: () => {
185
185
  markerEnd?: import("@xyflow/react").EdgeMarkerType;
186
186
  markerStart?: import("@xyflow/react").EdgeMarkerType;
187
187
  hidden?: boolean;
188
+ className?: string;
189
+ label?: import("react").ReactNode;
188
190
  selected?: boolean;
189
191
  selectable?: boolean;
190
192
  deletable?: boolean;
191
193
  ariaLabel?: string;
192
- className?: string;
193
194
  focusable?: boolean;
194
- label?: import("react").ReactNode;
195
195
  sourceHandle?: string | null;
196
196
  targetHandle?: string | null;
197
197
  animated?: boolean;
@@ -214,13 +214,13 @@ export declare const useXYStoreApi: () => {
214
214
  markerEnd?: import("@xyflow/react").EdgeMarkerType;
215
215
  markerStart?: import("@xyflow/react").EdgeMarkerType;
216
216
  hidden?: boolean;
217
+ className?: string;
218
+ label?: import("react").ReactNode;
217
219
  selected?: boolean;
218
220
  selectable?: boolean;
219
221
  deletable?: boolean;
220
222
  ariaLabel?: string;
221
- className?: string;
222
223
  focusable?: boolean;
223
- label?: import("react").ReactNode;
224
224
  sourceHandle?: string | null;
225
225
  targetHandle?: string | null;
226
226
  animated?: boolean;
@@ -242,13 +242,13 @@ export declare const useXYStoreApi: () => {
242
242
  markerEnd?: import("@xyflow/react").EdgeMarkerType;
243
243
  markerStart?: import("@xyflow/react").EdgeMarkerType;
244
244
  hidden?: boolean;
245
+ className?: string;
246
+ label?: import("react").ReactNode;
245
247
  selected?: boolean;
246
248
  selectable?: boolean;
247
249
  deletable?: boolean;
248
250
  ariaLabel?: string;
249
- className?: string;
250
251
  focusable?: boolean;
251
- label?: import("react").ReactNode;
252
252
  sourceHandle?: string | null;
253
253
  targetHandle?: string | null;
254
254
  animated?: boolean;
@@ -1,5 +1,7 @@
1
- export declare const cssContainer: string;
2
- export declare const cssCompound: string;
3
- export declare const cssTitle: string;
4
- export declare const cssIndicator: string;
5
- export declare const cssNavigateBtn: string;
1
+ export declare const container: string;
2
+ export declare const varTransparency: `var(--${string})` | `var(--${string}, ${string})` | `var(--${string}, ${number})`;
3
+ export declare const compoundBody: string;
4
+ export declare const transparent: string;
5
+ export declare const title: string;
6
+ export declare const indicator: string;
7
+ export declare const navigateBtn: string;
@@ -48,13 +48,13 @@ export declare namespace XYFlowEdge {
48
48
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
49
49
  markerStart?: import('@xyflow/react').EdgeMarkerType;
50
50
  hidden?: boolean;
51
+ className?: string;
52
+ label?: import('react').ReactNode;
51
53
  selected?: boolean;
52
54
  selectable?: boolean;
53
55
  deletable?: boolean;
54
56
  ariaLabel?: string;
55
- className?: string;
56
57
  focusable?: boolean;
57
- label?: import('react').ReactNode;
58
58
  sourceHandle?: string | null;
59
59
  targetHandle?: string | null;
60
60
  animated?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@likec4/diagram",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "license": "MIT",
5
5
  "bugs": "https://github.com/likec4/likec4/issues",
6
6
  "homepage": "https://likec4.dev",
@@ -50,25 +50,25 @@
50
50
  "clean": "run -T rimraf -v -g 'dist/*' .tsbuildinfo"
51
51
  },
52
52
  "dependencies": {
53
- "@likec4/core": "1.0.1",
53
+ "@likec4/core": "1.1.0",
54
54
  "@react-hookz/web": "^24.0.4",
55
55
  "esm-env": "^1.0.0",
56
56
  "fast-equals": "^5.0.1",
57
- "framer-motion": "^11.1.7",
57
+ "framer-motion": "^11.2.2",
58
58
  "remeda": "^1.61.0",
59
59
  "zustand": "^4.5.2"
60
60
  },
61
61
  "peerDependencies": {
62
- "@mantine/core": "^7.9.0",
63
- "@mantine/hooks": "^7.9.0",
62
+ "@mantine/core": "^7.9.2",
63
+ "@mantine/hooks": "^7.9.2",
64
64
  "react": "^18.3.1",
65
65
  "react-dom": "^18.3.1"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@lume/kiwi": "^0.4.3",
69
- "@mantine/core": "^7.9.0",
70
- "@mantine/hooks": "^7.9.0",
71
- "@mantine/vanilla-extract": "^7.9.0",
69
+ "@mantine/core": "^7.9.2",
70
+ "@mantine/hooks": "^7.9.2",
71
+ "@mantine/vanilla-extract": "^7.9.2",
72
72
  "@total-typescript/ts-reset": "^0.5.1",
73
73
  "@types/react": "18.2.0",
74
74
  "@types/react-dom": "18.2.4",
@@ -78,7 +78,7 @@
78
78
  "@vitejs/plugin-react": "^4.2.1",
79
79
  "@xyflow/react": "^12.0.0-next",
80
80
  "clsx": "^2.1.1",
81
- "execa": "^8.0.1",
81
+ "execa": "^9.1.0",
82
82
  "khroma": "^2.1.0",
83
83
  "react": "^18.2.0",
84
84
  "react-dom": "^18.2.0",
@@ -1,15 +1,16 @@
1
1
  import { Box } from '@mantine/core'
2
2
  import clsx from 'clsx'
3
- import type { HTMLAttributes } from 'react'
4
- import { wrapper } from './KeepAspectRatio.css'
3
+ import { type HTMLAttributes, useId } from 'react'
4
+ import * as css from './LikeC4Diagram.css'
5
5
 
6
- type KeepAspectRatioProps = HTMLAttributes<HTMLDivElement> & {
6
+ type KeepAspectRatioContainerProps = HTMLAttributes<HTMLDivElement> & {
7
+ // Whether to keep the aspect ratio
7
8
  enabled: boolean
8
9
  width: number
9
10
  height: number
10
11
  }
11
12
 
12
- export function KeepAspectRatio({
13
+ export function KeepAspectRatioContainer({
13
14
  children,
14
15
  width,
15
16
  height,
@@ -17,11 +18,11 @@ export function KeepAspectRatio({
17
18
  className,
18
19
  style,
19
20
  ...rest
20
- }: KeepAspectRatioProps) {
21
+ }: KeepAspectRatioContainerProps) {
21
22
  return (
22
23
  <Box
23
24
  {...rest}
24
- className={clsx(wrapper, className)}
25
+ className={clsx(css.keepAspectRatioContainer, className)}
25
26
  style={enabled
26
27
  ? {
27
28
  ...style,
@@ -1,6 +1,12 @@
1
1
  import { globalStyle, style } from '@vanilla-extract/css'
2
2
  import { vars, xyvars } from './theme.css'
3
3
 
4
+ export const keepAspectRatioContainer = style({
5
+ width: '100%',
6
+ height: '100%',
7
+ padding: 0
8
+ })
9
+
4
10
  export const cssReactFlow = style({})
5
11
 
6
12
  globalStyle(`.react-flow${cssReactFlow}`, {
@@ -2,18 +2,18 @@ import { ReactFlowProvider as XYFlowProvider } from '@xyflow/react'
2
2
  import clsx from 'clsx'
3
3
  import { useRef } from 'react'
4
4
  import { rootClassName } from './globals.css'
5
+ import { KeepAspectRatioContainer } from './KeepAspectRatioContainer'
5
6
  import { cssDisablePan, cssNoControls, cssReactFlow, cssTransparentBg } from './LikeC4Diagram.css'
6
7
  import { type LikeC4DiagramEventHandlers, type LikeC4DiagramProperties } from './LikeC4Diagram.props'
7
8
  import { EnsureMantine } from './mantine/EnsureMantine'
8
9
  import { DiagramContextProvider } from './state/DiagramContext'
9
10
  import { WhenInitialized } from './state/WhenInitialized'
10
- import { KeepAspectRatio } from './ui/KeepAspectRatio'
11
11
  import OptionsPanel from './ui/OptionsPanel'
12
12
  import { diagramViewToXYFlowData } from './xyflow/diagram-to-xyflow'
13
13
  import { FitViewOnDiagramChange } from './xyflow/FitviewOnDiagramChange'
14
14
  import { SyncWithDiagram } from './xyflow/SyncWithDiagram'
15
15
  import type { XYFlowData } from './xyflow/types'
16
- import { XYFlow } from './xyflow/XYFlowWrapper'
16
+ import { XYFlow } from './xyflow/XYFlow'
17
17
 
18
18
  export type LikeC4DiagramProps = LikeC4DiagramProperties & LikeC4DiagramEventHandlers
19
19
  export function LikeC4Diagram({
@@ -69,6 +69,8 @@ export function LikeC4Diagram({
69
69
  <DiagramContextProvider
70
70
  view={view}
71
71
  readonly={readonly}
72
+ pannable={pannable}
73
+ zoomable={zoomable}
72
74
  fitViewEnabled={fitView}
73
75
  fitViewPadding={fitViewPadding}
74
76
  showElementLinks={showElementLinks}
@@ -84,7 +86,7 @@ export function LikeC4Diagram({
84
86
  onNavigateTo={onNavigateTo}
85
87
  onCanvasDblClick={onCanvasDblClick}
86
88
  >
87
- <KeepAspectRatio
89
+ <KeepAspectRatioContainer
88
90
  className={clsx(rootClassName, className)}
89
91
  enabled={keepAspectRatio}
90
92
  width={view.width}
@@ -102,12 +104,10 @@ export function LikeC4Diagram({
102
104
  controls={controls}
103
105
  defaultNodes={initialRef.current.defaultNodes}
104
106
  defaultEdges={initialRef.current.defaultEdges}
105
- pannable={pannable}
106
- zoomable={zoomable}
107
107
  >
108
108
  {readonly !== true && <OptionsPanel />}
109
109
  </XYFlow>
110
- </KeepAspectRatio>
110
+ </KeepAspectRatioContainer>
111
111
  <WhenInitialized>
112
112
  <SyncWithDiagram />
113
113
  <FitViewOnDiagramChange />
@@ -1,7 +1,7 @@
1
- import type { ThemeColor } from '@likec4/core'
2
1
  import { defaultTheme } from '@likec4/core'
3
2
  import { createGlobalTheme } from '@vanilla-extract/css'
4
- import { omit } from 'remeda'
3
+ import { scale, toHex } from 'khroma'
4
+ import { keys, omit } from 'remeda'
5
5
  import { mantine } from './mantine.css'
6
6
  import { vars } from './theme.css'
7
7
 
@@ -75,38 +75,7 @@ createGlobalTheme(`:where([data-mantine-color-scheme='light']) .${rootClassName}
75
75
  }
76
76
  })
77
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
- }
78
+ for (const color of keys.strict(defaultTheme.elements)) {
110
79
  createGlobalTheme(`:where([data-likec4-color='${color}'])`, {
111
80
  element: {
112
81
  fill: vars.element.fill,
@@ -119,10 +88,46 @@ for (const color of Object.keys(defaultTheme.elements)) {
119
88
  },
120
89
  relation: vars.relation
121
90
  }, {
122
- element: defaultTheme.elements[color as ThemeColor],
91
+ element: defaultTheme.elements[color],
123
92
  compound: {
124
- titleColor: defaultTheme.elements[color as ThemeColor].loContrast
93
+ titleColor: defaultTheme.elements[color].loContrast
125
94
  },
126
- relation: defaultTheme.relationships[color as ThemeColor]
95
+ relation: defaultTheme.relationships[color]
127
96
  })
97
+
98
+ const compoundDarkColor = (color: string, depth: number) =>
99
+ toHex(
100
+ scale(color, {
101
+ l: -22 - 5 * depth,
102
+ s: -10 - 6 * depth
103
+ })
104
+ )
105
+ const compoundLightColor = (color: string, depth: number) =>
106
+ toHex(
107
+ scale(color, {
108
+ l: -20 - 3 * depth,
109
+ s: -3 - 6 * depth
110
+ })
111
+ )
112
+
113
+ const compounds = {
114
+ fill: vars.element.fill,
115
+ stroke: vars.element.stroke
116
+ }
117
+
118
+ for (let depth = 1; depth <= 6; depth++) {
119
+ createGlobalTheme(`:where([data-likec4-color='${color}'][data-compound-depth='${depth}'])`, compounds, {
120
+ fill: compoundDarkColor(defaultTheme.elements[color].fill, depth),
121
+ stroke: compoundDarkColor(defaultTheme.elements[color].stroke, depth)
122
+ })
123
+
124
+ createGlobalTheme(
125
+ `:where([data-mantine-color-scheme='light']) :where([data-likec4-color='${color}'][data-compound-depth='${depth}'])`,
126
+ compounds,
127
+ {
128
+ fill: compoundLightColor(defaultTheme.elements[color].fill, depth),
129
+ stroke: compoundLightColor(defaultTheme.elements[color].stroke, depth)
130
+ }
131
+ )
132
+ }
128
133
  }