@likec4/diagram 1.6.0 → 1.7.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 (49) hide show
  1. package/dist/LikeC4Diagram.d.ts +1 -1
  2. package/dist/LikeC4Diagram.props.d.ts +10 -11
  3. package/dist/hooks/useUpdateEffect.d.ts +1 -0
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.mjs +769 -8587
  6. package/dist/state/DiagramContext.d.ts +746 -181
  7. package/dist/state/diagram-to-xyflow.d.ts +10 -0
  8. package/dist/state/diagramStore.d.ts +782 -202
  9. package/dist/style.css +273 -275
  10. package/dist/types.d.ts +20 -0
  11. package/dist/xyflow/EdgeMarkers.d.ts +1 -0
  12. package/dist/xyflow/FitviewOnDiagramChange.d.ts +1 -1
  13. package/dist/xyflow/XYFlow.d.ts +1 -4
  14. package/dist/xyflow/XYFlowEvents.d.ts +41 -12
  15. package/dist/xyflow/XYFlowInner.d.ts +0 -1
  16. package/dist/xyflow/edges/RelationshipEdge.d.ts +3 -3
  17. package/dist/xyflow/hooks/index.d.ts +0 -1
  18. package/dist/xyflow/hooks/useXYFlow.d.ts +27 -27
  19. package/dist/xyflow/types.d.ts +11 -19
  20. package/dist/xyflow/utils.d.ts +1 -0
  21. package/package.json +11 -11
  22. package/src/LikeC4Diagram.props.ts +17 -13
  23. package/src/LikeC4Diagram.tsx +67 -106
  24. package/src/globals.css.ts +10 -6
  25. package/src/hooks/useUpdateEffect.ts +16 -1
  26. package/src/index.ts +3 -0
  27. package/src/state/DiagramContext.tsx +19 -27
  28. package/src/{xyflow → state}/diagram-to-xyflow.ts +19 -18
  29. package/src/state/diagramStore.ts +404 -192
  30. package/src/types.ts +22 -0
  31. package/src/ui/BackwardForwardPanel.tsx +24 -7
  32. package/src/xyflow/EdgeMarkers.tsx +2 -0
  33. package/src/xyflow/FitviewOnDiagramChange.tsx +42 -75
  34. package/src/xyflow/SelectEdgesOnNodeFocus.tsx +1 -1
  35. package/src/xyflow/XYFlow.tsx +57 -35
  36. package/src/xyflow/XYFlowEvents.tsx +58 -10
  37. package/src/xyflow/XYFlowInner.tsx +9 -8
  38. package/src/xyflow/edges/RelationshipEdge.tsx +43 -29
  39. package/src/xyflow/edges/edges.css.ts +3 -3
  40. package/src/xyflow/edges/utils.ts +0 -1
  41. package/src/xyflow/hooks/index.ts +0 -1
  42. package/src/xyflow/hooks/useLayoutConstraints.ts +42 -65
  43. package/src/xyflow/nodes/element/ElementNode.tsx +8 -11
  44. package/src/xyflow/nodes/element/element.css.ts +8 -6
  45. package/src/xyflow/types.ts +14 -32
  46. package/src/xyflow/utils.ts +4 -0
  47. package/dist/xyflow/SyncWithDiagram.d.ts +0 -4
  48. package/dist/xyflow/diagram-to-xyflow.d.ts +0 -7
  49. package/src/xyflow/SyncWithDiagram.tsx +0 -85
@@ -0,0 +1,20 @@
1
+ import { Fqn, RelationID, ViewID } from '@likec4/core';
2
+ import { Simplify } from 'type-fest';
3
+
4
+ type TaggedUnion<TagKey extends string, UnionMembers extends Record<string, Record<string, unknown>>> = {
5
+ [Name in keyof UnionMembers]: Simplify<{
6
+ [Key in TagKey]: Name;
7
+ } & UnionMembers[Name]>;
8
+ }[keyof UnionMembers];
9
+ export type DiagramEditorCommand = TaggedUnion<'type', {
10
+ showElement: {
11
+ element: Fqn;
12
+ };
13
+ showRelation: {
14
+ relation: RelationID;
15
+ };
16
+ showView: {
17
+ view: ViewID;
18
+ };
19
+ }>;
20
+ export {};
@@ -9,3 +9,4 @@ export declare const EdgeMarkers: {
9
9
  Dot: (props: SVGProps<SVGMarkerElement>) => import("react/jsx-runtime").JSX.Element;
10
10
  ODot: (props: SVGProps<SVGMarkerElement>) => import("react/jsx-runtime").JSX.Element;
11
11
  };
12
+ export type EdgeMarkerType = keyof typeof EdgeMarkers;
@@ -1,4 +1,4 @@
1
1
  /**
2
- * Fits the view when the view changes and nodes are initialized
2
+ * Fits the view when diagram changes
3
3
  */
4
4
  export declare function FitViewOnDiagramChange(): import("react/jsx-runtime").JSX.Element | null;
@@ -1,12 +1,9 @@
1
1
  import { CSSProperties, PropsWithChildren } from 'react';
2
- import { XYFlowEdge, XYFlowNode } from './types';
3
2
 
4
3
  type XYFlowWrapperProps = PropsWithChildren<{
5
4
  colorMode?: 'system' | 'light' | 'dark';
6
5
  className?: string | undefined;
7
- defaultNodes: XYFlowNode[];
8
- defaultEdges: XYFlowEdge[];
9
6
  style?: CSSProperties | undefined;
10
7
  }>;
11
- export declare function XYFlow({ colorMode, className, children, defaultNodes, defaultEdges, style }: XYFlowWrapperProps): import("react/jsx-runtime").JSX.Element;
8
+ export declare function XYFlow({ colorMode, className, children, style }: XYFlowWrapperProps): import("react/jsx-runtime").JSX.Element;
12
9
  export {};
@@ -2,13 +2,15 @@ import { ReactFlowProps } from '@xyflow/react';
2
2
  import { Simplify } from 'type-fest';
3
3
  import { XYFlowEdge, XYFlowNode } from './types';
4
4
 
5
- export type XYFlowEventHandlers = Simplify<Required<Pick<ReactFlowProps<XYFlowNode, XYFlowEdge>, 'onDoubleClick' | 'onPaneClick' | 'onNodeClick' | 'onNodeDoubleClick' | 'onEdgeClick' | 'onMoveEnd' | 'onNodeContextMenu' | 'onEdgeContextMenu' | 'onPaneContextMenu' | 'onNodeMouseEnter' | 'onNodeMouseLeave' | 'onEdgeMouseEnter' | 'onEdgeMouseLeave'>>>;
5
+ export type XYFlowEventHandlers = Simplify<Required<Pick<ReactFlowProps<XYFlowNode, XYFlowEdge>, 'onDoubleClick' | 'onPaneClick' | 'onNodeClick' | 'onNodeDoubleClick' | 'onEdgeClick' | 'onEdgeDoubleClick' | 'onMoveEnd' | 'onNodeContextMenu' | 'onEdgeContextMenu' | 'onPaneContextMenu' | 'onNodeMouseEnter' | 'onNodeMouseLeave' | 'onEdgeMouseEnter' | 'onEdgeMouseLeave'>>>;
6
6
  export declare function useXYFlowEvents(): {
7
7
  onDoubleClick: (event: import('react').MouseEvent<HTMLDivElement, MouseEvent>) => void;
8
8
  onPaneClick: (event: import('react').MouseEvent<Element, MouseEvent>) => void;
9
9
  onNodeContextMenu: (event: import('react').MouseEvent<Element, MouseEvent>, xynode: XYFlowNode) => void;
10
10
  onPaneContextMenu: (event: MouseEvent | import('react').MouseEvent<Element, MouseEvent>) => void;
11
11
  onEdgeContextMenu: (event: import('react').MouseEvent<Element, MouseEvent>, xyedge: {
12
+ id: string;
13
+ type: "relationship";
12
14
  source: string;
13
15
  target: string;
14
16
  sourceHandle?: string | null;
@@ -17,6 +19,7 @@ export declare function useXYFlowEvents(): {
17
19
  hidden?: boolean;
18
20
  deletable?: boolean;
19
21
  selectable?: boolean;
22
+ data: import('./types').RelationshipData;
20
23
  selected?: boolean;
21
24
  markerStart?: import('@xyflow/react').EdgeMarkerType;
22
25
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
@@ -33,13 +36,12 @@ export declare function useXYFlowEvents(): {
33
36
  className?: string;
34
37
  reconnectable?: boolean | import('@xyflow/react').HandleType;
35
38
  focusable?: boolean;
36
- data: import('./types').RelationshipData;
37
- readonly id: string;
38
- readonly type: "relationship";
39
39
  }) => void;
40
40
  onNodeClick: (event: import('react').MouseEvent<Element, MouseEvent>, xynode: XYFlowNode) => void;
41
41
  onNodeDoubleClick: (event: import('react').MouseEvent<Element, MouseEvent>, xynode: XYFlowNode) => void;
42
42
  onEdgeClick: (event: import('react').MouseEvent<Element, MouseEvent>, xyedge: {
43
+ id: string;
44
+ type: "relationship";
43
45
  source: string;
44
46
  target: string;
45
47
  sourceHandle?: string | null;
@@ -48,6 +50,7 @@ export declare function useXYFlowEvents(): {
48
50
  hidden?: boolean;
49
51
  deletable?: boolean;
50
52
  selectable?: boolean;
53
+ data: import('./types').RelationshipData;
51
54
  selected?: boolean;
52
55
  markerStart?: import('@xyflow/react').EdgeMarkerType;
53
56
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
@@ -64,14 +67,42 @@ export declare function useXYFlowEvents(): {
64
67
  className?: string;
65
68
  reconnectable?: boolean | import('@xyflow/react').HandleType;
66
69
  focusable?: boolean;
70
+ }) => void;
71
+ onEdgeDoubleClick: (event: import('react').MouseEvent<Element, MouseEvent>, xyedge: {
72
+ id: string;
73
+ type: "relationship";
74
+ source: string;
75
+ target: string;
76
+ sourceHandle?: string | null;
77
+ targetHandle?: string | null;
78
+ animated?: boolean;
79
+ hidden?: boolean;
80
+ deletable?: boolean;
81
+ selectable?: boolean;
67
82
  data: import('./types').RelationshipData;
68
- readonly id: string;
69
- readonly type: "relationship";
83
+ selected?: boolean;
84
+ markerStart?: import('@xyflow/react').EdgeMarkerType;
85
+ markerEnd?: import('@xyflow/react').EdgeMarkerType;
86
+ zIndex?: number;
87
+ ariaLabel?: string;
88
+ interactionWidth?: number;
89
+ label?: string | import('react').ReactNode;
90
+ labelStyle?: import('react').CSSProperties;
91
+ labelShowBg?: boolean;
92
+ labelBgStyle?: import('react').CSSProperties;
93
+ labelBgPadding?: [number, number];
94
+ labelBgBorderRadius?: number;
95
+ style?: import('react').CSSProperties;
96
+ className?: string;
97
+ reconnectable?: boolean | import('@xyflow/react').HandleType;
98
+ focusable?: boolean;
70
99
  }) => void;
71
100
  onMoveEnd: (event: MouseEvent | TouchEvent | null, _viewport: import('@xyflow/react').Viewport) => void;
72
101
  onNodeMouseEnter: (_event: import('react').MouseEvent<Element, MouseEvent>, xynode: XYFlowNode) => void;
73
102
  onNodeMouseLeave: (_event: import('react').MouseEvent<Element, MouseEvent>, xynode: XYFlowNode) => void;
74
103
  onEdgeMouseEnter: (_event: import('react').MouseEvent<Element, MouseEvent>, { id, source, target }: {
104
+ id: string;
105
+ type: "relationship";
75
106
  source: string;
76
107
  target: string;
77
108
  sourceHandle?: string | null;
@@ -80,6 +111,7 @@ export declare function useXYFlowEvents(): {
80
111
  hidden?: boolean;
81
112
  deletable?: boolean;
82
113
  selectable?: boolean;
114
+ data: import('./types').RelationshipData;
83
115
  selected?: boolean;
84
116
  markerStart?: import('@xyflow/react').EdgeMarkerType;
85
117
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
@@ -96,11 +128,10 @@ export declare function useXYFlowEvents(): {
96
128
  className?: string;
97
129
  reconnectable?: boolean | import('@xyflow/react').HandleType;
98
130
  focusable?: boolean;
99
- data: import('./types').RelationshipData;
100
- readonly id: string;
101
- readonly type: "relationship";
102
131
  }) => void;
103
132
  onEdgeMouseLeave: (_event: import('react').MouseEvent<Element, MouseEvent>, xyedge: {
133
+ id: string;
134
+ type: "relationship";
104
135
  source: string;
105
136
  target: string;
106
137
  sourceHandle?: string | null;
@@ -109,6 +140,7 @@ export declare function useXYFlowEvents(): {
109
140
  hidden?: boolean;
110
141
  deletable?: boolean;
111
142
  selectable?: boolean;
143
+ data: import('./types').RelationshipData;
112
144
  selected?: boolean;
113
145
  markerStart?: import('@xyflow/react').EdgeMarkerType;
114
146
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
@@ -125,8 +157,5 @@ export declare function useXYFlowEvents(): {
125
157
  className?: string;
126
158
  reconnectable?: boolean | import('@xyflow/react').HandleType;
127
159
  focusable?: boolean;
128
- data: import('./types').RelationshipData;
129
- readonly id: string;
130
- readonly type: "relationship";
131
160
  }) => void;
132
161
  };
@@ -6,7 +6,6 @@ type XYFlowInnerProps = PropsWithChildren<{
6
6
  controls: boolean;
7
7
  showDiagramTitle: boolean;
8
8
  showNavigationButtons: boolean;
9
- enableDynamicViewWalkthrough: boolean;
10
9
  }>;
11
10
  export declare const XYFlowInner: import('react').NamedExoticComponent<XYFlowInnerProps>;
12
11
  export {};
@@ -2,6 +2,8 @@ import { EdgeProps } from '@xyflow/react';
2
2
  import { RelationshipData } from '../types';
3
3
 
4
4
  export declare const RelationshipEdge: import('react').NamedExoticComponent<EdgeProps<{
5
+ id: string;
6
+ type: "relationship";
5
7
  source: string;
6
8
  target: string;
7
9
  sourceHandle?: string | null;
@@ -10,6 +12,7 @@ export declare const RelationshipEdge: import('react').NamedExoticComponent<Edge
10
12
  hidden?: boolean;
11
13
  deletable?: boolean;
12
14
  selectable?: boolean;
15
+ data: RelationshipData;
13
16
  selected?: boolean;
14
17
  markerStart?: import('@xyflow/react').EdgeMarkerType;
15
18
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
@@ -26,7 +29,4 @@ export declare const RelationshipEdge: import('react').NamedExoticComponent<Edge
26
29
  className?: string;
27
30
  reconnectable?: boolean | import('@xyflow/react').HandleType;
28
31
  focusable?: boolean;
29
- data: RelationshipData;
30
- readonly id: string;
31
- readonly type: "relationship";
32
32
  }>>;
@@ -1,3 +1,2 @@
1
- export { useLayoutConstraints } from './useLayoutConstraints';
2
1
  export { useXYFlow, useXYNodesData, useXYStore, useXYStoreApi } from './useXYFlow';
3
2
  export type * from './useXYFlow';
@@ -1,6 +1,8 @@
1
1
  import { XYFlowEdge, XYFlowNode, XYFlowState } from '../types';
2
2
 
3
3
  export declare const useXYFlow: () => import('@xyflow/react').ReactFlowInstance<XYFlowNode, {
4
+ id: string;
5
+ type: "relationship";
4
6
  source: string;
5
7
  target: string;
6
8
  sourceHandle?: string | null;
@@ -9,6 +11,7 @@ export declare const useXYFlow: () => import('@xyflow/react').ReactFlowInstance<
9
11
  hidden?: boolean;
10
12
  deletable?: boolean;
11
13
  selectable?: boolean;
14
+ data: import('../types').RelationshipData;
12
15
  selected?: boolean;
13
16
  markerStart?: import('@xyflow/react').EdgeMarkerType;
14
17
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
@@ -25,9 +28,6 @@ export declare const useXYFlow: () => import('@xyflow/react').ReactFlowInstance<
25
28
  className?: string;
26
29
  reconnectable?: boolean | import('@xyflow/react').HandleType;
27
30
  focusable?: boolean;
28
- data: import('../types').RelationshipData;
29
- readonly id: string;
30
- readonly type: "relationship";
31
31
  }>;
32
32
  export declare const useXYNodesData: {
33
33
  (nodeId: string): Pick<XYFlowNode, "id" | "type" | "data"> | null;
@@ -36,6 +36,8 @@ export declare const useXYNodesData: {
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: () => {
38
38
  getState: () => import('@xyflow/react').ReactFlowState<XYFlowNode, {
39
+ id: string;
40
+ type: "relationship";
39
41
  source: string;
40
42
  target: string;
41
43
  sourceHandle?: string | null;
@@ -44,6 +46,7 @@ export declare const useXYStoreApi: () => {
44
46
  hidden?: boolean;
45
47
  deletable?: boolean;
46
48
  selectable?: boolean;
49
+ data: import('../types').RelationshipData;
47
50
  selected?: boolean;
48
51
  markerStart?: import('@xyflow/react').EdgeMarkerType;
49
52
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
@@ -60,11 +63,10 @@ export declare const useXYStoreApi: () => {
60
63
  className?: string;
61
64
  reconnectable?: boolean | import('@xyflow/react').HandleType;
62
65
  focusable?: boolean;
63
- data: import('../types').RelationshipData;
64
- readonly id: string;
65
- readonly type: "relationship";
66
66
  }>;
67
67
  setState: (partial: import('@xyflow/react').ReactFlowState<XYFlowNode, {
68
+ id: string;
69
+ type: "relationship";
68
70
  source: string;
69
71
  target: string;
70
72
  sourceHandle?: string | null;
@@ -73,6 +75,7 @@ export declare const useXYStoreApi: () => {
73
75
  hidden?: boolean;
74
76
  deletable?: boolean;
75
77
  selectable?: boolean;
78
+ data: import('../types').RelationshipData;
76
79
  selected?: boolean;
77
80
  markerStart?: import('@xyflow/react').EdgeMarkerType;
78
81
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
@@ -89,10 +92,9 @@ export declare const useXYStoreApi: () => {
89
92
  className?: string;
90
93
  reconnectable?: boolean | import('@xyflow/react').HandleType;
91
94
  focusable?: boolean;
92
- data: import('../types').RelationshipData;
93
- readonly id: string;
94
- readonly type: "relationship";
95
95
  }> | Partial<import('@xyflow/react').ReactFlowState<XYFlowNode, {
96
+ id: string;
97
+ type: "relationship";
96
98
  source: string;
97
99
  target: string;
98
100
  sourceHandle?: string | null;
@@ -101,6 +103,7 @@ export declare const useXYStoreApi: () => {
101
103
  hidden?: boolean;
102
104
  deletable?: boolean;
103
105
  selectable?: boolean;
106
+ data: import('../types').RelationshipData;
104
107
  selected?: boolean;
105
108
  markerStart?: import('@xyflow/react').EdgeMarkerType;
106
109
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
@@ -117,10 +120,9 @@ export declare const useXYStoreApi: () => {
117
120
  className?: string;
118
121
  reconnectable?: boolean | import('@xyflow/react').HandleType;
119
122
  focusable?: boolean;
120
- data: import('../types').RelationshipData;
121
- readonly id: string;
122
- readonly type: "relationship";
123
123
  }>> | ((state: import('@xyflow/react').ReactFlowState<XYFlowNode, {
124
+ id: string;
125
+ type: "relationship";
124
126
  source: string;
125
127
  target: string;
126
128
  sourceHandle?: string | null;
@@ -129,6 +131,7 @@ export declare const useXYStoreApi: () => {
129
131
  hidden?: boolean;
130
132
  deletable?: boolean;
131
133
  selectable?: boolean;
134
+ data: import('../types').RelationshipData;
132
135
  selected?: boolean;
133
136
  markerStart?: import('@xyflow/react').EdgeMarkerType;
134
137
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
@@ -145,10 +148,9 @@ export declare const useXYStoreApi: () => {
145
148
  className?: string;
146
149
  reconnectable?: boolean | import('@xyflow/react').HandleType;
147
150
  focusable?: boolean;
148
- data: import('../types').RelationshipData;
149
- readonly id: string;
150
- readonly type: "relationship";
151
151
  }>) => import('@xyflow/react').ReactFlowState<XYFlowNode, {
152
+ id: string;
153
+ type: "relationship";
152
154
  source: string;
153
155
  target: string;
154
156
  sourceHandle?: string | null;
@@ -157,6 +159,7 @@ export declare const useXYStoreApi: () => {
157
159
  hidden?: boolean;
158
160
  deletable?: boolean;
159
161
  selectable?: boolean;
162
+ data: import('../types').RelationshipData;
160
163
  selected?: boolean;
161
164
  markerStart?: import('@xyflow/react').EdgeMarkerType;
162
165
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
@@ -173,10 +176,9 @@ export declare const useXYStoreApi: () => {
173
176
  className?: string;
174
177
  reconnectable?: boolean | import('@xyflow/react').HandleType;
175
178
  focusable?: boolean;
176
- data: import('../types').RelationshipData;
177
- readonly id: string;
178
- readonly type: "relationship";
179
179
  }> | Partial<import('@xyflow/react').ReactFlowState<XYFlowNode, {
180
+ id: string;
181
+ type: "relationship";
180
182
  source: string;
181
183
  target: string;
182
184
  sourceHandle?: string | null;
@@ -185,6 +187,7 @@ export declare const useXYStoreApi: () => {
185
187
  hidden?: boolean;
186
188
  deletable?: boolean;
187
189
  selectable?: boolean;
190
+ data: import('../types').RelationshipData;
188
191
  selected?: boolean;
189
192
  markerStart?: import('@xyflow/react').EdgeMarkerType;
190
193
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
@@ -201,11 +204,10 @@ export declare const useXYStoreApi: () => {
201
204
  className?: string;
202
205
  reconnectable?: boolean | import('@xyflow/react').HandleType;
203
206
  focusable?: boolean;
204
- data: import('../types').RelationshipData;
205
- readonly id: string;
206
- readonly type: "relationship";
207
207
  }>>), replace?: boolean | undefined) => void;
208
208
  subscribe: (listener: (state: import('@xyflow/react').ReactFlowState<XYFlowNode, {
209
+ id: string;
210
+ type: "relationship";
209
211
  source: string;
210
212
  target: string;
211
213
  sourceHandle?: string | null;
@@ -214,6 +216,7 @@ export declare const useXYStoreApi: () => {
214
216
  hidden?: boolean;
215
217
  deletable?: boolean;
216
218
  selectable?: boolean;
219
+ data: import('../types').RelationshipData;
217
220
  selected?: boolean;
218
221
  markerStart?: import('@xyflow/react').EdgeMarkerType;
219
222
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
@@ -230,10 +233,9 @@ export declare const useXYStoreApi: () => {
230
233
  className?: string;
231
234
  reconnectable?: boolean | import('@xyflow/react').HandleType;
232
235
  focusable?: boolean;
233
- data: import('../types').RelationshipData;
234
- readonly id: string;
235
- readonly type: "relationship";
236
236
  }>, prevState: import('@xyflow/react').ReactFlowState<XYFlowNode, {
237
+ id: string;
238
+ type: "relationship";
237
239
  source: string;
238
240
  target: string;
239
241
  sourceHandle?: string | null;
@@ -242,6 +244,7 @@ export declare const useXYStoreApi: () => {
242
244
  hidden?: boolean;
243
245
  deletable?: boolean;
244
246
  selectable?: boolean;
247
+ data: import('../types').RelationshipData;
245
248
  selected?: boolean;
246
249
  markerStart?: import('@xyflow/react').EdgeMarkerType;
247
250
  markerEnd?: import('@xyflow/react').EdgeMarkerType;
@@ -258,9 +261,6 @@ export declare const useXYStoreApi: () => {
258
261
  className?: string;
259
262
  reconnectable?: boolean | import('@xyflow/react').HandleType;
260
263
  focusable?: boolean;
261
- data: import('../types').RelationshipData;
262
- readonly id: string;
263
- readonly type: "relationship";
264
264
  }>) => void) => () => void;
265
265
  };
266
266
  export type XYStoreApi = ReturnType<typeof useXYStoreApi>;
@@ -1,39 +1,36 @@
1
- import { BBox, DiagramEdge, DiagramNode, Fqn, XYPosition } from '@likec4/core';
1
+ import { BBox, DiagramEdge, DiagramNode, Fqn, XYPoint } from '@likec4/core';
2
2
  import { Edge, EdgeMouseHandler, InternalNode, Node, NodeMouseHandler, OnMoveEnd, OnMoveStart, ReactFlowInstance, ReactFlowState } from '@xyflow/react';
3
3
  import { MouseEvent as ReactMouseEvent } from 'react';
4
- import { SetReadonly, SetRequired } from 'type-fest';
4
+ import { Simplify } from 'type-fest';
5
5
 
6
- export type ElementNodeData = {
6
+ export type ElementXYFlowNode = Node<{
7
7
  fqn: Fqn;
8
8
  element: DiagramNode;
9
- };
10
- type TypedXYFlowNode<D extends Record<string, unknown>, T extends string> = SetReadonly<SetRequired<Node<D, T>, 'type'>, 'id' | 'type'>;
11
- type TypedXYFlowEdge<D extends Record<string, unknown>, T extends string> = SetReadonly<SetRequired<Edge<D, T>, 'type' | 'data'>, 'id' | 'type'>;
12
- export type ElementXYFlowNode = TypedXYFlowNode<ElementNodeData, 'element'>;
13
- export type CompoundNodeData = {
9
+ }, 'element'>;
10
+ export type CompoundXYFlowNode = Node<{
14
11
  fqn: Fqn;
15
12
  element: DiagramNode;
16
- };
17
- export type CompoundXYFlowNode = TypedXYFlowNode<CompoundNodeData, 'compound'>;
13
+ }, 'compound'>;
18
14
  export type XYFlowNode = ElementXYFlowNode | CompoundXYFlowNode;
19
15
  export type InternalXYFlowNode = InternalNode<XYFlowNode>;
20
16
  export declare namespace XYFlowNode {
21
- type Data = ElementNodeData | CompoundNodeData;
22
17
  function isCompound(node: unknown): node is CompoundXYFlowNode;
23
18
  function isElement(node: Node): node is ElementXYFlowNode;
24
19
  const is: (node: Node) => node is XYFlowNode;
25
20
  }
26
21
  export type RelationshipData = {
27
22
  edge: DiagramEdge;
28
- controlPoints: XYPosition[] | null;
29
- type: 'bezier' | 'poly';
23
+ controlPoints: XYPoint[] | null;
30
24
  stepNum: number | null;
31
25
  label: null | {
32
26
  bbox: BBox;
33
27
  text: string;
34
28
  };
35
29
  };
36
- export type RelationshipEdge = TypedXYFlowEdge<RelationshipData, 'relationship'>;
30
+ export type RelationshipEdge = Simplify<Edge<RelationshipData, 'relationship'> & {
31
+ type: 'relationship';
32
+ data: RelationshipData;
33
+ }>;
37
34
  export type XYFlowEdge = RelationshipEdge;
38
35
  export declare namespace XYFlowEdge {
39
36
  type Data = RelationshipData;
@@ -41,10 +38,6 @@ export declare namespace XYFlowEdge {
41
38
  }
42
39
  export type XYFlowInstance = ReactFlowInstance<XYFlowNode, XYFlowEdge>;
43
40
  export type XYFlowState = ReactFlowState<XYFlowNode, XYFlowEdge>;
44
- export type XYFlowData = {
45
- nodes: XYFlowNode[];
46
- edges: XYFlowEdge[];
47
- };
48
41
  export type XYFlowEventHandlers = {
49
42
  onPanelClick: (event: ReactMouseEvent) => void;
50
43
  onNodeContextMenu: NodeMouseHandler<XYFlowNode>;
@@ -55,4 +48,3 @@ export type XYFlowEventHandlers = {
55
48
  onMoveStart: OnMoveStart;
56
49
  onMoveEnd: OnMoveEnd;
57
50
  };
58
- export {};
@@ -5,3 +5,4 @@ export declare function toDomPrecision(v: number | null): number;
5
5
  export declare function distance(a: XYPosition, b: XYPosition): number;
6
6
  export declare function bezierControlPoints(diagramEdge: DiagramEdge): XYPosition[];
7
7
  export declare function isSamePoint(a: XYPosition | Point, b: XYPosition | Point): boolean;
8
+ export declare function distanceBetweenPoints(a: XYPosition, b: XYPosition): number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@likec4/diagram",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "license": "MIT",
5
5
  "bugs": "https://github.com/likec4/likec4/issues",
6
6
  "homepage": "https://likec4.dev",
@@ -48,28 +48,33 @@
48
48
  "clean": "run -T rimraf -v -g 'dist/*' .tsbuildinfo"
49
49
  },
50
50
  "dependencies": {
51
- "@likec4/core": "1.6.0",
51
+ "@lume/kiwi": "^0.4.3",
52
52
  "@react-hookz/web": "^24.0.4",
53
53
  "@tabler/icons-react": "^3.11.0",
54
54
  "@vanilla-extract/css": "^1.15.3",
55
55
  "@vanilla-extract/css-utils": "^0.1.4",
56
56
  "@vanilla-extract/dynamic": "^2.1.1",
57
+ "@xyflow/react": "12.0.3",
58
+ "@xyflow/system": "0.0.37",
59
+ "bezier-js": "^6.1.4",
60
+ "clsx": "^2.1.1",
57
61
  "d3-shape": "^3.2.0",
58
62
  "esm-env": "^1.0.0",
59
63
  "fast-equals": "^5.0.1",
60
- "framer-motion": "^11.3.8",
64
+ "framer-motion": "^11.3.19",
61
65
  "remeda": "^2.3.0",
62
66
  "zustand": "^4.5.4"
63
67
  },
64
68
  "peerDependencies": {
69
+ "@likec4/core": "1.7.0",
65
70
  "@mantine/core": "^7.11.2",
66
71
  "@mantine/hooks": "^7.11.2",
67
72
  "react": "^18.3.1",
68
73
  "react-dom": "^18.3.1"
69
74
  },
70
75
  "devDependencies": {
71
- "@likec4/tsconfig": "1.6.0",
72
- "@lume/kiwi": "^0.4.3",
76
+ "@likec4/core": "1.7.0",
77
+ "@likec4/tsconfig": "1.7.0",
73
78
  "@mantine/core": "7.11.2",
74
79
  "@mantine/hooks": "7.11.2",
75
80
  "@mantine/vanilla-extract": "7.11.2",
@@ -80,17 +85,12 @@
80
85
  "@types/react-dom": "^18.3.0",
81
86
  "@vanilla-extract/esbuild-plugin": "^2.3.8",
82
87
  "@vitejs/plugin-react": "^4.3.1",
83
- "@xyflow/react": "12.0.3",
84
- "@xyflow/system": "0.0.37",
85
- "bezier-js": "^6.1.4",
86
- "clsx": "^2.1.1",
87
88
  "execa": "^9.3.0",
88
89
  "khroma": "^2.1.0",
89
90
  "react": "^18.3.1",
90
91
  "react-dom": "^18.3.1",
91
- "tilg": "^0.1.1",
92
92
  "type-fest": "^4.21.0",
93
- "typescript": "^5.5.3",
93
+ "typescript": "^5.5.4",
94
94
  "vite": "5.3.4",
95
95
  "vite-plugin-dts": "^3.9.1"
96
96
  }
@@ -3,16 +3,15 @@ import type {
3
3
  DiagramEdge,
4
4
  DiagramNode,
5
5
  DiagramView,
6
- EdgeId,
7
6
  ElementShape,
8
7
  Fqn,
9
- IconUrl,
10
8
  NonEmptyArray,
11
9
  ThemeColor,
12
- ViewID
10
+ ViewID,
11
+ ViewManualLayout
13
12
  } from '@likec4/core'
14
- import type { XYPosition } from '@xyflow/system'
15
13
  import type { MouseEvent as ReactMouseEvent, ReactNode } from 'react'
14
+ import type { DiagramEditorCommand } from './types'
16
15
  import type { XYFlowEdge, XYFlowNode } from './xyflow/types'
17
16
  import type { XYBackground } from './xyflow/XYFlowBackground'
18
17
 
@@ -54,6 +53,10 @@ export type OnEdgeClick = (
54
53
  }
55
54
  ) => void
56
55
 
56
+ export type OnEditorCommand = (
57
+ cmd: DiagramEditorCommand
58
+ ) => void
59
+
57
60
  /**
58
61
  * On pane/canvas click (not on any node or edge)
59
62
  */
@@ -73,15 +76,7 @@ export namespace Changes {
73
76
 
74
77
  export interface SaveManualLayout {
75
78
  op: 'save-manual-layout'
76
- nodes: Record<Fqn, {
77
- x: number
78
- y: number
79
- width: number
80
- height: number
81
- }>
82
- edges: Record<EdgeId, {
83
- controlPoints: XYPosition[]
84
- }>
79
+ layout: ViewManualLayout
85
80
  }
86
81
  }
87
82
 
@@ -138,6 +133,7 @@ export interface LikeC4DiagramProperties {
138
133
  * @default 0
139
134
  */
140
135
  fitViewPadding?: number | undefined
136
+
141
137
  nodesSelectable?: boolean | undefined
142
138
 
143
139
  /**
@@ -178,6 +174,12 @@ export interface LikeC4DiagramProperties {
178
174
  */
179
175
  showNavigationButtons?: undefined | boolean
180
176
 
177
+ /**
178
+ * If double click on a node should enable focus mode, i.e. highlight incoming/outgoing edges
179
+ * @default true
180
+ */
181
+ enableFocusMode?: boolean | undefined
182
+
181
183
  /**
182
184
  * If Walkthrough for dynamic views should be enabled
183
185
  * @default false
@@ -207,4 +209,6 @@ export interface LikeC4DiagramEventHandlers {
207
209
  onEdgeContextMenu?: OnEdgeClick | null | undefined
208
210
  onCanvasClick?: OnCanvasClick | null | undefined
209
211
  onCanvasDblClick?: OnCanvasClick | null | undefined
212
+
213
+ onEditorCommand?: OnEditorCommand | null | undefined
210
214
  }