@likec4/diagram 1.27.1 → 1.27.3
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 +2152 -6757
- package/dist/LikeC4Diagram.js +1 -1
- package/dist/LikeC4Diagram.props.d.ts +5 -3
- package/dist/StaticLikeC4Diagram.js +1 -1
- package/dist/_virtual/set.js +5 -0
- package/dist/_virtual/set2.js +3 -0
- package/dist/base/BaseXYFlow.d.ts +2 -1
- package/dist/base/primitives/compound/CompoundNodeContainer.d.ts +1 -1
- package/dist/base/primitives/compound/CompoundNodeContainer.js +0 -1
- package/dist/base/primitives/edge/EdgeLabelContainer.js +3 -2
- package/dist/base/primitives/element/ElementActionButtons.js +8 -11
- package/dist/base/primitives/element/ElementNodeContainer.css.js +4 -4
- package/dist/base/updateEdges.js +1 -9
- package/dist/base/updateNodes.js +1 -12
- package/dist/bundle/LikeC4View.js +2 -2
- package/dist/bundle/LikeC4View.props.d.ts +7 -7
- package/dist/hooks/useCurrentViewId.js +8 -2
- package/dist/hooks/useDiagram.d.ts +1522 -685
- package/dist/hooks/useDiagram.js +21 -24
- package/dist/likec4diagram/DiagramXYFlow.js +6 -6
- package/dist/likec4diagram/ui/notation/NotationPanel.css.js +3 -3
- package/dist/likec4diagram/ui/notation/NotationPanel.js +10 -4
- package/dist/node_modules/.pnpm/mnemonist@0.40.3_patch_hash_5c12abb43fcff6fd81e53021b89075d53249640d165a2556cc1e58d71201a13a/node_modules/mnemonist/set.js +369 -0
- package/dist/overlays/Overlays.js +3 -1
- package/dist/overlays/element-details/actor.d.ts +2769 -173
- package/dist/overlays/overlay/Overlay.css.d.ts +26 -2
- package/dist/overlays/overlay/Overlay.css.js +66 -18
- package/dist/overlays/overlay/Overlay.d.ts +7 -6
- package/dist/overlays/overlay/Overlay.js +12 -10
- package/dist/overlays/overlaysActor.js +2 -2
- package/dist/overlays/relationship-details/RelationshipDetails.js +113 -70
- package/dist/overlays/relationship-details/SelectEdge.d.ts +1 -1
- package/dist/overlays/relationship-details/SelectEdge.js +15 -9
- package/dist/overlays/relationship-details/_types.d.ts +4 -1
- package/dist/overlays/relationship-details/actor.d.ts +425 -128
- package/dist/overlays/relationship-details/actor.js +157 -53
- package/dist/overlays/relationship-details/compute.d.ts +12 -0
- package/dist/overlays/relationship-details/compute.js +139 -0
- package/dist/overlays/relationship-details/custom/ElementActions.js +27 -5
- package/dist/overlays/relationship-details/custom/edgeTypes.js +1 -1
- package/dist/overlays/relationship-details/custom/nodeTypes.d.ts +2 -1
- package/dist/overlays/relationship-details/hooks.d.ts +336 -6
- package/dist/overlays/relationship-details/hooks.js +11 -12
- package/dist/overlays/relationship-details/layout-to-xyflow.d.ts +12 -0
- package/dist/overlays/relationship-details/layout-to-xyflow.js +145 -0
- package/dist/overlays/relationship-details/layout.d.ts +22 -0
- package/dist/overlays/relationship-details/layout.js +314 -0
- package/dist/overlays/relationships-browser/RelationshipsBrowser.d.ts +3 -1
- package/dist/overlays/relationships-browser/RelationshipsBrowser.js +2 -2
- package/dist/overlays/relationships-browser/_types.d.ts +2 -0
- package/dist/overlays/relationships-browser/actor.d.ts +130 -14
- package/dist/overlays/relationships-browser/actor.js +30 -16
- package/dist/overlays/relationships-browser/custom/ElementActions.js +5 -3
- package/dist/overlays/relationships-browser/custom/edgeTypes.d.ts +3 -1
- package/dist/overlays/relationships-browser/custom/edgeTypes.js +1 -1
- package/dist/overlays/relationships-browser/hooks.d.ts +3 -1
- package/dist/overlays/relationships-browser/hooks.js +6 -9
- package/dist/overlays/relationships-browser/{-useRelationshipsView.d.ts → layout.d.ts} +3 -1
- package/dist/overlays/relationships-browser/{-useRelationshipsView.js → layout.js} +21 -8
- package/dist/overlays/relationships-browser/useViewToNodesEdges.d.ts +1 -1
- package/dist/overlays/relationships-browser/useViewToNodesEdges.js +3 -1
- package/dist/packages/core/src/compute-view/relationships-view/compute.js +1 -1
- package/dist/packages/core/src/model/connection/model/ConnectionModel.js +121 -0
- package/dist/packages/core/src/model/connection/model/find.js +39 -0
- package/dist/packages/core/src/model/connection/ops.js +7 -0
- package/dist/packages/core/src/utils/const.js +3 -0
- package/dist/packages/core/src/utils/fqn.js +9 -1
- package/dist/packages/core/src/utils/iterable/find.js +21 -0
- package/dist/packages/core/src/utils/iterable/some.js +21 -0
- package/dist/packages/core/src/utils/set.js +48 -0
- package/dist/packages/core/src/utils/string-hash.js +13 -0
- package/dist/state/diagram-machine.d.ts +1552 -703
- package/dist/state/diagram-machine.js +39 -3
- package/dist/state/syncManualLayoutActor.d.ts +1 -1
- package/dist/styles.css.js +1 -1
- package/dist/utils/index.d.ts +0 -1
- package/package.json +11 -11
- package/src/LikeC4Diagram.props.ts +7 -3
- package/src/LikeC4Diagram.tsx +1 -1
- package/src/StaticLikeC4Diagram.tsx +1 -1
- package/src/base/BaseXYFlow.tsx +2 -1
- package/src/base/primitives/compound/CompoundNodeContainer.tsx +0 -2
- package/src/base/primitives/edge/EdgeLabelContainer.tsx +7 -5
- package/src/base/primitives/element/ElementActionButtons.tsx +10 -11
- package/src/base/primitives/element/ElementNodeContainer.css.ts +4 -4
- package/src/base/updateEdges.ts +8 -8
- package/src/base/updateNodes.ts +11 -11
- package/src/bundle/LikeC4View.props.ts +7 -7
- package/src/bundle/LikeC4View.tsx +2 -2
- package/src/hooks/useCurrentViewId.ts +4 -2
- package/src/hooks/useDiagram.ts +22 -24
- package/src/likec4diagram/DiagramXYFlow.tsx +6 -6
- package/src/likec4diagram/ui/notation/NotationPanel.css.ts +2 -2
- package/src/likec4diagram/ui/notation/NotationPanel.tsx +8 -6
- package/src/overlays/Overlays.tsx +4 -2
- package/src/overlays/overlay/Overlay.css.ts +67 -17
- package/src/overlays/overlay/Overlay.tsx +27 -24
- package/src/overlays/overlaysActor.ts +1 -1
- package/src/overlays/relationship-details/RelationshipDetails.tsx +131 -68
- package/src/overlays/relationship-details/SelectEdge.tsx +19 -12
- package/src/overlays/relationship-details/_types.ts +3 -1
- package/src/overlays/relationship-details/actor.ts +212 -68
- package/src/overlays/relationship-details/compute.ts +186 -0
- package/src/overlays/relationship-details/custom/ElementActions.tsx +27 -18
- package/src/overlays/relationship-details/custom/edgeTypes.tsx +1 -1
- package/src/overlays/relationship-details/hooks.ts +12 -13
- package/src/overlays/relationship-details/layout-to-xyflow.ts +172 -0
- package/src/overlays/relationship-details/layout.ts +470 -0
- package/src/overlays/relationships-browser/RelationshipsBrowser.tsx +2 -2
- package/src/overlays/relationships-browser/_types.ts +2 -0
- package/src/overlays/relationships-browser/actor.ts +39 -14
- package/src/overlays/relationships-browser/custom/ElementActions.tsx +5 -3
- package/src/overlays/relationships-browser/custom/edgeTypes.tsx +1 -1
- package/src/overlays/relationships-browser/hooks.ts +7 -10
- package/src/overlays/relationships-browser/{-useRelationshipsView.ts → layout.ts} +26 -33
- package/src/overlays/relationships-browser/useViewToNodesEdges.ts +3 -1
- package/src/state/diagram-machine.ts +51 -6
- package/src/utils/index.ts +0 -1
- package/dist/overlays/relationship-details/useLayoutedDetails.d.ts +0 -19
- package/dist/overlays/relationship-details/useLayoutedDetails.js +0 -267
- package/dist/utils/types.d.ts +0 -8
- package/src/overlays/relationship-details/useLayoutedDetails.ts +0 -376
- package/src/utils/types.ts +0 -6
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import dagre from '@dagrejs/dagre';
|
|
2
|
+
import { invariant } from '@likec4/core';
|
|
3
|
+
import { pipe, filter, mapToObj, find, map, tap, reduce, sortBy, prop } from 'remeda';
|
|
4
|
+
import { ifind } from '../../packages/core/src/utils/iterable/find.js';
|
|
5
|
+
import DefaultMap from '../../_virtual/default-map.js';
|
|
6
|
+
import { treeFromElements } from '../../packages/core/src/compute-view/relationships-view/utils.js';
|
|
7
|
+
|
|
8
|
+
const Sizes = {
|
|
9
|
+
dagre: {
|
|
10
|
+
ranksep: 60,
|
|
11
|
+
nodesep: 35,
|
|
12
|
+
edgesep: 25
|
|
13
|
+
},
|
|
14
|
+
edgeLabel: {
|
|
15
|
+
width: 220,
|
|
16
|
+
height: 14
|
|
17
|
+
// minlen: 1,
|
|
18
|
+
},
|
|
19
|
+
nodeWidth: 330,
|
|
20
|
+
nodeHeight: 180,
|
|
21
|
+
compound: {
|
|
22
|
+
labelHeight: 2,
|
|
23
|
+
paddingTop: 50,
|
|
24
|
+
paddingBottom: 32
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
function createGraph() {
|
|
28
|
+
const g = new dagre.graphlib.Graph({
|
|
29
|
+
directed: true,
|
|
30
|
+
compound: true,
|
|
31
|
+
multigraph: true
|
|
32
|
+
});
|
|
33
|
+
g.setGraph({
|
|
34
|
+
...Sizes.dagre,
|
|
35
|
+
rankdir: "LR"
|
|
36
|
+
});
|
|
37
|
+
g.setDefaultEdgeLabel(() => ({ ...Sizes.edgeLabel }));
|
|
38
|
+
g.setDefaultNodeLabel(() => ({}));
|
|
39
|
+
return g;
|
|
40
|
+
}
|
|
41
|
+
const PortSuffix = "-port";
|
|
42
|
+
function createNodes(column, elements, g) {
|
|
43
|
+
const graphNodes = new DefaultMap((key) => ({
|
|
44
|
+
id: `${column}-${key}`,
|
|
45
|
+
portId: `${column}-${key}`
|
|
46
|
+
}));
|
|
47
|
+
const tree = treeFromElements(elements);
|
|
48
|
+
for (const element of tree.sorted) {
|
|
49
|
+
const isCompound = tree.children(element).length > 0;
|
|
50
|
+
const fqn = element.id;
|
|
51
|
+
const id = `${column}-${fqn}`;
|
|
52
|
+
const portId = isCompound ? `${id}${PortSuffix}` : id;
|
|
53
|
+
graphNodes.set(fqn, {
|
|
54
|
+
id,
|
|
55
|
+
portId
|
|
56
|
+
});
|
|
57
|
+
g.setNode(id, {
|
|
58
|
+
column,
|
|
59
|
+
element,
|
|
60
|
+
isCompound,
|
|
61
|
+
portId,
|
|
62
|
+
inPorts: [],
|
|
63
|
+
outPorts: [],
|
|
64
|
+
width: Sizes.nodeWidth,
|
|
65
|
+
height: Sizes.nodeHeight
|
|
66
|
+
});
|
|
67
|
+
if (isCompound) {
|
|
68
|
+
g.setNode(portId, {
|
|
69
|
+
element,
|
|
70
|
+
portId,
|
|
71
|
+
isCompound,
|
|
72
|
+
inPorts: [],
|
|
73
|
+
outPorts: [],
|
|
74
|
+
width: Sizes.nodeWidth - Sizes.dagre.ranksep,
|
|
75
|
+
height: Sizes.compound.labelHeight
|
|
76
|
+
});
|
|
77
|
+
g.setParent(portId, id);
|
|
78
|
+
}
|
|
79
|
+
const parent = tree.parent(element);
|
|
80
|
+
if (parent) {
|
|
81
|
+
g.setParent(id, `${column}-${parent.id}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
...tree,
|
|
86
|
+
byId: (id) => {
|
|
87
|
+
const element = tree.byId(id);
|
|
88
|
+
const graph = graphNodes.get(element.id);
|
|
89
|
+
return {
|
|
90
|
+
element,
|
|
91
|
+
graph
|
|
92
|
+
};
|
|
93
|
+
},
|
|
94
|
+
graphNodes
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function applyDagreLayout(g) {
|
|
98
|
+
dagre.layout(g, {
|
|
99
|
+
// disableOptimalOrderHeuristic: true,
|
|
100
|
+
});
|
|
101
|
+
return (nodeId) => {
|
|
102
|
+
const node = g.node(nodeId);
|
|
103
|
+
const { x, y, width, height } = node;
|
|
104
|
+
return {
|
|
105
|
+
position: {
|
|
106
|
+
x: x - Math.round(width / 2),
|
|
107
|
+
y: y - Math.round(height / 2)
|
|
108
|
+
},
|
|
109
|
+
width,
|
|
110
|
+
height
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function layoutRelationshipDetails(data, scope) {
|
|
115
|
+
const g = createGraph();
|
|
116
|
+
const sources = createNodes("sources", data.sources, g), targets = createNodes("targets", data.targets, g);
|
|
117
|
+
const edges = Array.from(data.relationships).map((r) => {
|
|
118
|
+
const source = sources.byId(r.source.id).graph;
|
|
119
|
+
const target = targets.byId(r.target.id).graph;
|
|
120
|
+
const name = r.id;
|
|
121
|
+
g.node(source.id).outPorts.push(target.id);
|
|
122
|
+
g.node(target.id).inPorts.push(source.id);
|
|
123
|
+
g.setEdge(source.portId, target.portId, {
|
|
124
|
+
...Sizes.edgeLabel
|
|
125
|
+
}, name);
|
|
126
|
+
return {
|
|
127
|
+
name,
|
|
128
|
+
source: source.id,
|
|
129
|
+
sourceHandle: source.id + "_out" + (g.node(source.id).outPorts.length - 1),
|
|
130
|
+
target: target.id,
|
|
131
|
+
targetHandle: target.id + "_in" + (g.node(target.id).inPorts.length - 1),
|
|
132
|
+
relationship: r
|
|
133
|
+
};
|
|
134
|
+
});
|
|
135
|
+
const nodeIds = [
|
|
136
|
+
...sources.graphNodes.values(),
|
|
137
|
+
...targets.graphNodes.values()
|
|
138
|
+
];
|
|
139
|
+
for (const { id: nodeId } of nodeIds) {
|
|
140
|
+
const node = g.node(nodeId);
|
|
141
|
+
if (node.isCompound) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const edgeCount2 = Math.max(g.inEdges(nodeId)?.length ?? 0, g.outEdges(nodeId)?.length ?? 0);
|
|
145
|
+
if (edgeCount2 > 3) {
|
|
146
|
+
node.height = node.height + (edgeCount2 - 4) * 14;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const edgeCount = g.edgeCount();
|
|
150
|
+
if (edgeCount > 5) {
|
|
151
|
+
for (const edge of g.edges()) {
|
|
152
|
+
g.setEdge(edge, {
|
|
153
|
+
...Sizes.edgeLabel,
|
|
154
|
+
width: edgeCount > 10 ? 800 : 400
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const dagreBounds = applyDagreLayout(g);
|
|
159
|
+
const _calculatedNodeBounds = pipe(
|
|
160
|
+
nodeIds,
|
|
161
|
+
// Compound nodes have different portId
|
|
162
|
+
filter((n) => n.id === n.portId),
|
|
163
|
+
mapToObj((n) => [n.id, dagreBounds(n.id)])
|
|
164
|
+
);
|
|
165
|
+
function nodeBounds(nodeId) {
|
|
166
|
+
return _calculatedNodeBounds[nodeId] ??= pipe(
|
|
167
|
+
g.children(nodeId) ?? [],
|
|
168
|
+
filter((id) => !id.endsWith(PortSuffix)),
|
|
169
|
+
map((id) => nodeBounds(id)),
|
|
170
|
+
tap((bounds) => {
|
|
171
|
+
invariant(bounds.length > 0, `Node ${nodeId} has no nested nodes`);
|
|
172
|
+
}),
|
|
173
|
+
reduce((acc, bounds) => {
|
|
174
|
+
return {
|
|
175
|
+
minY: Math.min(acc.minY, bounds.position.y),
|
|
176
|
+
maxY: Math.max(acc.maxY, bounds.position.y + bounds.height)
|
|
177
|
+
};
|
|
178
|
+
}, { minY: Infinity, maxY: -Infinity }),
|
|
179
|
+
({ minY: minY2, maxY }) => {
|
|
180
|
+
const {
|
|
181
|
+
position: { x },
|
|
182
|
+
width
|
|
183
|
+
} = dagreBounds(nodeId);
|
|
184
|
+
minY2 = minY2 - Sizes.compound.paddingTop;
|
|
185
|
+
maxY = maxY + Sizes.compound.paddingBottom;
|
|
186
|
+
return {
|
|
187
|
+
position: {
|
|
188
|
+
x,
|
|
189
|
+
y: minY2
|
|
190
|
+
},
|
|
191
|
+
width,
|
|
192
|
+
height: maxY - minY2
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
function nodeLevel(nodeId) {
|
|
198
|
+
const parent = g.parent(nodeId);
|
|
199
|
+
if (parent) {
|
|
200
|
+
return nodeLevel(parent) + 1;
|
|
201
|
+
}
|
|
202
|
+
return 0;
|
|
203
|
+
}
|
|
204
|
+
function nodeDepth(nodeId) {
|
|
205
|
+
const children = g.children(nodeId) ?? [];
|
|
206
|
+
if (children.length === 0) {
|
|
207
|
+
return 0;
|
|
208
|
+
}
|
|
209
|
+
return 1 + Math.max(...children.map(nodeDepth));
|
|
210
|
+
}
|
|
211
|
+
const sortedPorts = (nodeId, type, ports) => {
|
|
212
|
+
return pipe(
|
|
213
|
+
ports,
|
|
214
|
+
map((port, index) => {
|
|
215
|
+
return {
|
|
216
|
+
port: nodeId + "_" + type + index,
|
|
217
|
+
topY: nodeBounds(port).position.y
|
|
218
|
+
};
|
|
219
|
+
}),
|
|
220
|
+
sortBy(prop("topY")),
|
|
221
|
+
map(prop("port"))
|
|
222
|
+
);
|
|
223
|
+
};
|
|
224
|
+
let minX = 0;
|
|
225
|
+
let minY = 0;
|
|
226
|
+
const nodes = nodeIds.map(({ id }) => {
|
|
227
|
+
const { element, inPorts, outPorts, column } = g.node(id);
|
|
228
|
+
let { position, width, height } = nodeBounds(id);
|
|
229
|
+
const parentId = g.parent(id);
|
|
230
|
+
const children = (g.children(id) ?? []).filter((c) => !c.endsWith(PortSuffix));
|
|
231
|
+
minX = Math.min(minX, position.x);
|
|
232
|
+
minY = Math.min(minY, position.y);
|
|
233
|
+
const navigateTo = scope ? ifind(element.scopedViews(), (v) => v.id !== scope.id)?.id ?? null : null;
|
|
234
|
+
const inheritFromNode = scope?.findNodeWithElement(element.id);
|
|
235
|
+
const scopedAncestor = scope && !inheritFromNode ? ifind(element.ancestors(), (a) => !!scope.findNodeWithElement(a.id))?.id : null;
|
|
236
|
+
const inheritFromNodeOrAncestor = inheritFromNode ?? (scopedAncestor && scope?.findNodeWithElement(scopedAncestor));
|
|
237
|
+
return {
|
|
238
|
+
id,
|
|
239
|
+
parent: parentId ?? null,
|
|
240
|
+
position: [position.x, position.y],
|
|
241
|
+
title: element.title,
|
|
242
|
+
description: element.description,
|
|
243
|
+
technology: element.technology,
|
|
244
|
+
tags: null,
|
|
245
|
+
links: null,
|
|
246
|
+
color: inheritFromNodeOrAncestor?.color ?? element.color,
|
|
247
|
+
shape: inheritFromNode?.shape ?? element.shape,
|
|
248
|
+
icon: inheritFromNode?.icon ?? element.icon ?? "none",
|
|
249
|
+
modelRef: element.id,
|
|
250
|
+
kind: element.kind,
|
|
251
|
+
level: nodeLevel(id),
|
|
252
|
+
labelBBox: {
|
|
253
|
+
x: position.x,
|
|
254
|
+
y: position.y,
|
|
255
|
+
width,
|
|
256
|
+
height
|
|
257
|
+
},
|
|
258
|
+
style: {
|
|
259
|
+
...(inheritFromNode ?? inheritFromNodeOrAncestor)?.style,
|
|
260
|
+
...element.$element.style
|
|
261
|
+
},
|
|
262
|
+
navigateTo,
|
|
263
|
+
...children.length > 0 && { depth: nodeDepth(id) },
|
|
264
|
+
children,
|
|
265
|
+
width,
|
|
266
|
+
height,
|
|
267
|
+
column,
|
|
268
|
+
ports: {
|
|
269
|
+
in: sortedPorts(id, "in", inPorts),
|
|
270
|
+
out: sortedPorts(id, "out", outPorts)
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
});
|
|
274
|
+
return {
|
|
275
|
+
bounds: {
|
|
276
|
+
x: Math.min(minX, 0),
|
|
277
|
+
y: Math.min(minY, 0),
|
|
278
|
+
width: g.graph().width ?? 100,
|
|
279
|
+
height: g.graph().height ?? 100
|
|
280
|
+
},
|
|
281
|
+
nodes,
|
|
282
|
+
edges: g.edges().reduce((acc, e) => {
|
|
283
|
+
const edge = g.edge(e);
|
|
284
|
+
const ename = e.name;
|
|
285
|
+
if (!ename) {
|
|
286
|
+
return acc;
|
|
287
|
+
}
|
|
288
|
+
const { name, source, target, relationship, sourceHandle, targetHandle } = find(edges, (e2) => e2.name === ename);
|
|
289
|
+
const label = relationship.title ?? "untitled";
|
|
290
|
+
const navigateTo = relationship.navigateTo?.id ?? null;
|
|
291
|
+
const description = relationship.description ?? null;
|
|
292
|
+
const technology = relationship.technology ?? null;
|
|
293
|
+
acc.push({
|
|
294
|
+
id: name,
|
|
295
|
+
source,
|
|
296
|
+
sourceHandle,
|
|
297
|
+
target,
|
|
298
|
+
targetHandle,
|
|
299
|
+
label,
|
|
300
|
+
color: relationship.color,
|
|
301
|
+
...navigateTo && { navigateTo },
|
|
302
|
+
...description && { description },
|
|
303
|
+
...technology && { technology },
|
|
304
|
+
points: edge.points.map((p) => [p.x, p.y]),
|
|
305
|
+
line: relationship.line,
|
|
306
|
+
relationId: relationship.id,
|
|
307
|
+
parent: null
|
|
308
|
+
});
|
|
309
|
+
return acc;
|
|
310
|
+
}, [])
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export { layoutRelationshipDetails };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RelationshipsBrowserActorRef } from './actor';
|
|
2
2
|
import { NamedExoticComponent, CSSProperties, ReactNode } from 'react';
|
|
3
3
|
import { Position } from '@xyflow/system';
|
|
4
|
-
import { NonEmptyArray, RelationId, Color, ViewId, RelationshipLineType } from '@likec4/core';
|
|
4
|
+
import { Fqn, NonEmptyArray, RelationId, Color, ViewId, RelationshipLineType } from '@likec4/core';
|
|
5
5
|
export declare const edgeTypes: {
|
|
6
6
|
relationship: NamedExoticComponent<{
|
|
7
7
|
id: string;
|
|
@@ -35,6 +35,8 @@ export declare const edgeTypes: {
|
|
|
35
35
|
active?: boolean;
|
|
36
36
|
dimmed?: import("../../base").Base.Dimmed;
|
|
37
37
|
} & {
|
|
38
|
+
sourceFqn: Fqn;
|
|
39
|
+
targetFqn: Fqn;
|
|
38
40
|
relations: NonEmptyArray<RelationId>;
|
|
39
41
|
color: Color | undefined;
|
|
40
42
|
label: string | null;
|
|
@@ -8,9 +8,9 @@ import { shallowEqual } from 'fast-equals';
|
|
|
8
8
|
import { LayoutGroup, AnimatePresence, m } from 'framer-motion';
|
|
9
9
|
import { useRef, memo, useEffect } from 'react';
|
|
10
10
|
import { BaseXYFlow } from '../../base/BaseXYFlow.js';
|
|
11
|
-
import { useRelationshipsView } from './-useRelationshipsView.js';
|
|
12
11
|
import { ViewPadding } from './const.js';
|
|
13
12
|
import { RelationshipsBrowserActorContext, useRelationshipsBrowser, useRelationshipsBrowserState } from './hooks.js';
|
|
13
|
+
import { useRelationshipsView } from './layout.js';
|
|
14
14
|
import { SelectElement } from './SelectElement.js';
|
|
15
15
|
import { RelationshipEdge } from './custom/edgeTypes.js';
|
|
16
16
|
import { EmptyNode, CompoundNode, ElementNode } from './custom/nodeTypes.js';
|
|
@@ -124,7 +124,7 @@ const RelationshipsBrowserInner = memo(() => {
|
|
|
124
124
|
if (instance.viewportInitialized) {
|
|
125
125
|
browser.send({ type: "xyflow.init", instance, store });
|
|
126
126
|
}
|
|
127
|
-
}, [store, instance, browser]);
|
|
127
|
+
}, [store, instance.viewportInitialized, browser]);
|
|
128
128
|
const layouted = useRelationshipsView(subjectId, viewId, scope);
|
|
129
129
|
const [historySubjectId, historyOps, { history, current }] = useStateHistory(subjectId);
|
|
130
130
|
useEffect(() => {
|
|
@@ -33,6 +33,8 @@ export declare namespace RelationshipsBrowserTypes {
|
|
|
33
33
|
type Node = ElementNode | CompoundNode | EmptyNode;
|
|
34
34
|
type NodeData = Node['data'];
|
|
35
35
|
type EdgeData = Base.EdgeData<{
|
|
36
|
+
sourceFqn: Fqn;
|
|
37
|
+
targetFqn: Fqn;
|
|
36
38
|
relations: NonEmptyArray<RelationId>;
|
|
37
39
|
color: Color | undefined;
|
|
38
40
|
label: string | null;
|
|
@@ -2,8 +2,8 @@ import { BBox, Fqn, ViewId, NonEmptyArray, RelationId, Color, RelationshipLineTy
|
|
|
2
2
|
import { EdgeChange, NodeChange, ReactFlowInstance, useStoreApi, GeneralHelpers, ViewportHelperFunctions, ReactFlowState } from '@xyflow/react';
|
|
3
3
|
import { ActorLogicFrom, ActorRefFromLogic, SnapshotFrom, PromiseActorLogic, EventObject, StateMachine, Values, NonReducibleUnknown, MetaObject, ConditionalRequired, InputFrom, RequiredActorOptions, IsNotNever, GetConcreteByKey, AnyActorLogic, RequiredLogicInput, ActorRef, MachineSnapshot, AnyActorRef, StateValue, AnyEventObject, ActionFunction, CancelAction, DoneActorEvent } from 'xstate';
|
|
4
4
|
import { Base } from '../../base';
|
|
5
|
-
import { LayoutRelationshipsViewResult } from './-useRelationshipsView';
|
|
6
5
|
import { RelationshipsBrowserTypes } from './_types';
|
|
6
|
+
import { LayoutRelationshipsViewResult } from './layout';
|
|
7
7
|
import { EdgeMarkerType, HandleType } from '@xyflow/system';
|
|
8
8
|
import { ReactNode, CSSProperties } from 'react';
|
|
9
9
|
type XYFLowInstance = ReactFlowInstance<RelationshipsBrowserTypes.Node, RelationshipsBrowserTypes.Edge>;
|
|
@@ -156,10 +156,6 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
156
156
|
type: "update.view";
|
|
157
157
|
params: NonReducibleUnknown;
|
|
158
158
|
};
|
|
159
|
-
"xyflow:updateNodeInternals": {
|
|
160
|
-
type: "xyflow:updateNodeInternals";
|
|
161
|
-
params: unknown;
|
|
162
|
-
};
|
|
163
159
|
"xyflow:fitDiagram": {
|
|
164
160
|
type: "xyflow:fitDiagram";
|
|
165
161
|
params: {
|
|
@@ -167,16 +163,24 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
167
163
|
bounds?: BBox;
|
|
168
164
|
} | undefined;
|
|
169
165
|
};
|
|
166
|
+
"xyflow:updateNodeInternals": {
|
|
167
|
+
type: "xyflow:updateNodeInternals";
|
|
168
|
+
params: unknown;
|
|
169
|
+
};
|
|
170
170
|
}>, Values<{
|
|
171
171
|
isReady: {
|
|
172
172
|
type: "isReady";
|
|
173
173
|
params: unknown;
|
|
174
174
|
};
|
|
175
|
+
hasViewId: {
|
|
176
|
+
type: "hasViewId";
|
|
177
|
+
params: unknown;
|
|
178
|
+
};
|
|
175
179
|
anotherSubject: {
|
|
176
180
|
type: "anotherSubject";
|
|
177
181
|
params: unknown;
|
|
178
182
|
};
|
|
179
|
-
}>, never, "
|
|
183
|
+
}>, never, "closed" | "isReady" | "initializing" | {
|
|
180
184
|
active: "idle" | "layouting";
|
|
181
185
|
}, "active", Input, NonReducibleUnknown, EventObject, MetaObject, {
|
|
182
186
|
readonly id: "relationships-browser";
|
|
@@ -213,6 +217,8 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
213
217
|
focusable?: boolean;
|
|
214
218
|
type: "relationship";
|
|
215
219
|
data: {
|
|
220
|
+
sourceFqn: Fqn;
|
|
221
|
+
targetFqn: Fqn;
|
|
216
222
|
relations: NonEmptyArray<RelationId>;
|
|
217
223
|
color: Color | undefined;
|
|
218
224
|
label: string | null;
|
|
@@ -264,6 +270,8 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
264
270
|
focusable?: boolean;
|
|
265
271
|
type: "relationship";
|
|
266
272
|
data: {
|
|
273
|
+
sourceFqn: Fqn;
|
|
274
|
+
targetFqn: Fqn;
|
|
267
275
|
relations: NonEmptyArray<RelationId>;
|
|
268
276
|
color: Color | undefined;
|
|
269
277
|
label: string | null;
|
|
@@ -322,6 +330,8 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
322
330
|
focusable?: boolean;
|
|
323
331
|
type: "relationship";
|
|
324
332
|
data: {
|
|
333
|
+
sourceFqn: Fqn;
|
|
334
|
+
targetFqn: Fqn;
|
|
325
335
|
relations: NonEmptyArray<RelationId>;
|
|
326
336
|
color: Color | undefined;
|
|
327
337
|
label: string | null;
|
|
@@ -481,10 +491,80 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
481
491
|
type: "update.view";
|
|
482
492
|
params: NonReducibleUnknown;
|
|
483
493
|
};
|
|
494
|
+
"xyflow:fitDiagram": {
|
|
495
|
+
type: "xyflow:fitDiagram";
|
|
496
|
+
params: {
|
|
497
|
+
duration?: number;
|
|
498
|
+
bounds?: BBox;
|
|
499
|
+
} | undefined;
|
|
500
|
+
};
|
|
484
501
|
"xyflow:updateNodeInternals": {
|
|
485
502
|
type: "xyflow:updateNodeInternals";
|
|
486
503
|
params: unknown;
|
|
487
504
|
};
|
|
505
|
+
}>, Values<{
|
|
506
|
+
isReady: {
|
|
507
|
+
type: "isReady";
|
|
508
|
+
params: unknown;
|
|
509
|
+
};
|
|
510
|
+
hasViewId: {
|
|
511
|
+
type: "hasViewId";
|
|
512
|
+
params: unknown;
|
|
513
|
+
};
|
|
514
|
+
anotherSubject: {
|
|
515
|
+
type: "anotherSubject";
|
|
516
|
+
params: unknown;
|
|
517
|
+
};
|
|
518
|
+
}>, never, EventObject>;
|
|
519
|
+
};
|
|
520
|
+
readonly 'xyflow.edgeClick': {
|
|
521
|
+
readonly guard: "hasViewId";
|
|
522
|
+
readonly actions: ActionFunction<Readonly<{
|
|
523
|
+
subject: Fqn;
|
|
524
|
+
viewId: ViewId | null;
|
|
525
|
+
scope: "global" | "view";
|
|
526
|
+
closeable: boolean;
|
|
527
|
+
enableSelectSubject: boolean;
|
|
528
|
+
enableChangeScope: boolean;
|
|
529
|
+
xyflow: XYFLowInstance | null;
|
|
530
|
+
xystore: XYStoreApi | null;
|
|
531
|
+
layouted: LayoutRelationshipsViewResult | null;
|
|
532
|
+
navigateFromNode: string | null;
|
|
533
|
+
xynodes: RelationshipsBrowserTypes.Node[];
|
|
534
|
+
xyedges: RelationshipsBrowserTypes.Edge[];
|
|
535
|
+
}>, {
|
|
536
|
+
type: "xyflow.edgeClick";
|
|
537
|
+
edge: RelationshipsBrowserTypes.Edge;
|
|
538
|
+
}, Events, undefined, {
|
|
539
|
+
src: "layouter";
|
|
540
|
+
logic: PromiseActorLogic<{
|
|
541
|
+
xyedges: RelationshipsBrowserTypes.Edge[];
|
|
542
|
+
xynodes: RelationshipsBrowserTypes.Node[];
|
|
543
|
+
}, {
|
|
544
|
+
subjectId: Fqn;
|
|
545
|
+
navigateFromNode: string | null;
|
|
546
|
+
xyflow: XYFLowInstance;
|
|
547
|
+
xystore: XYStoreApi;
|
|
548
|
+
update: LayoutRelationshipsViewResult;
|
|
549
|
+
}, EventObject>;
|
|
550
|
+
id: "layouter";
|
|
551
|
+
}, Values<{
|
|
552
|
+
"xyflow.init": {
|
|
553
|
+
type: "xyflow.init";
|
|
554
|
+
params: NonReducibleUnknown;
|
|
555
|
+
};
|
|
556
|
+
"xyflow.applyNodeChanges": {
|
|
557
|
+
type: "xyflow.applyNodeChanges";
|
|
558
|
+
params: NonReducibleUnknown;
|
|
559
|
+
};
|
|
560
|
+
"xyflow.applyEdgeChanges": {
|
|
561
|
+
type: "xyflow.applyEdgeChanges";
|
|
562
|
+
params: NonReducibleUnknown;
|
|
563
|
+
};
|
|
564
|
+
"update.view": {
|
|
565
|
+
type: "update.view";
|
|
566
|
+
params: NonReducibleUnknown;
|
|
567
|
+
};
|
|
488
568
|
"xyflow:fitDiagram": {
|
|
489
569
|
type: "xyflow:fitDiagram";
|
|
490
570
|
params: {
|
|
@@ -492,11 +572,19 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
492
572
|
bounds?: BBox;
|
|
493
573
|
} | undefined;
|
|
494
574
|
};
|
|
575
|
+
"xyflow:updateNodeInternals": {
|
|
576
|
+
type: "xyflow:updateNodeInternals";
|
|
577
|
+
params: unknown;
|
|
578
|
+
};
|
|
495
579
|
}>, Values<{
|
|
496
580
|
isReady: {
|
|
497
581
|
type: "isReady";
|
|
498
582
|
params: unknown;
|
|
499
583
|
};
|
|
584
|
+
hasViewId: {
|
|
585
|
+
type: "hasViewId";
|
|
586
|
+
params: unknown;
|
|
587
|
+
};
|
|
500
588
|
anotherSubject: {
|
|
501
589
|
type: "anotherSubject";
|
|
502
590
|
params: unknown;
|
|
@@ -623,6 +711,8 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
623
711
|
focusable?: boolean;
|
|
624
712
|
type: "relationship";
|
|
625
713
|
data: {
|
|
714
|
+
sourceFqn: Fqn;
|
|
715
|
+
targetFqn: Fqn;
|
|
626
716
|
relations: NonEmptyArray<RelationId>;
|
|
627
717
|
color: Color | undefined;
|
|
628
718
|
label: string | null;
|
|
@@ -945,10 +1035,6 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
945
1035
|
type: "update.view";
|
|
946
1036
|
params: NonReducibleUnknown;
|
|
947
1037
|
};
|
|
948
|
-
"xyflow:updateNodeInternals": {
|
|
949
|
-
type: "xyflow:updateNodeInternals";
|
|
950
|
-
params: unknown;
|
|
951
|
-
};
|
|
952
1038
|
"xyflow:fitDiagram": {
|
|
953
1039
|
type: "xyflow:fitDiagram";
|
|
954
1040
|
params: {
|
|
@@ -956,11 +1042,19 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
956
1042
|
bounds?: BBox;
|
|
957
1043
|
} | undefined;
|
|
958
1044
|
};
|
|
1045
|
+
"xyflow:updateNodeInternals": {
|
|
1046
|
+
type: "xyflow:updateNodeInternals";
|
|
1047
|
+
params: unknown;
|
|
1048
|
+
};
|
|
959
1049
|
}>, Values<{
|
|
960
1050
|
isReady: {
|
|
961
1051
|
type: "isReady";
|
|
962
1052
|
params: unknown;
|
|
963
1053
|
};
|
|
1054
|
+
hasViewId: {
|
|
1055
|
+
type: "hasViewId";
|
|
1056
|
+
params: unknown;
|
|
1057
|
+
};
|
|
964
1058
|
anotherSubject: {
|
|
965
1059
|
type: "anotherSubject";
|
|
966
1060
|
params: unknown;
|
|
@@ -1034,6 +1128,8 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
1034
1128
|
focusable?: boolean;
|
|
1035
1129
|
type: "relationship";
|
|
1036
1130
|
data: {
|
|
1131
|
+
sourceFqn: Fqn;
|
|
1132
|
+
targetFqn: Fqn;
|
|
1037
1133
|
relations: NonEmptyArray<RelationId>;
|
|
1038
1134
|
color: Color | undefined;
|
|
1039
1135
|
label: string | null;
|
|
@@ -1076,6 +1172,8 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
1076
1172
|
focusable?: boolean;
|
|
1077
1173
|
type: "relationship";
|
|
1078
1174
|
data: {
|
|
1175
|
+
sourceFqn: Fqn;
|
|
1176
|
+
targetFqn: Fqn;
|
|
1079
1177
|
relations: NonEmptyArray<RelationId>;
|
|
1080
1178
|
color: Color | undefined;
|
|
1081
1179
|
label: string | null;
|
|
@@ -1115,6 +1213,8 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
1115
1213
|
focusable?: boolean;
|
|
1116
1214
|
type: "relationship";
|
|
1117
1215
|
data: {
|
|
1216
|
+
sourceFqn: Fqn;
|
|
1217
|
+
targetFqn: Fqn;
|
|
1118
1218
|
relations: NonEmptyArray<RelationId>;
|
|
1119
1219
|
color: Color | undefined;
|
|
1120
1220
|
label: string | null;
|
|
@@ -1153,6 +1253,8 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
1153
1253
|
focusable?: boolean;
|
|
1154
1254
|
type: "relationship";
|
|
1155
1255
|
data: {
|
|
1256
|
+
sourceFqn: Fqn;
|
|
1257
|
+
targetFqn: Fqn;
|
|
1156
1258
|
relations: NonEmptyArray<RelationId>;
|
|
1157
1259
|
color: Color | undefined;
|
|
1158
1260
|
label: string | null;
|
|
@@ -1191,6 +1293,8 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
1191
1293
|
focusable?: boolean;
|
|
1192
1294
|
type: "relationship";
|
|
1193
1295
|
data: {
|
|
1296
|
+
sourceFqn: Fqn;
|
|
1297
|
+
targetFqn: Fqn;
|
|
1194
1298
|
relations: NonEmptyArray<RelationId>;
|
|
1195
1299
|
color: Color | undefined;
|
|
1196
1300
|
label: string | null;
|
|
@@ -1229,6 +1333,8 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
1229
1333
|
focusable?: boolean;
|
|
1230
1334
|
type: "relationship";
|
|
1231
1335
|
data: {
|
|
1336
|
+
sourceFqn: Fqn;
|
|
1337
|
+
targetFqn: Fqn;
|
|
1232
1338
|
relations: NonEmptyArray<RelationId>;
|
|
1233
1339
|
color: Color | undefined;
|
|
1234
1340
|
label: string | null;
|
|
@@ -1267,6 +1373,8 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
1267
1373
|
focusable?: boolean;
|
|
1268
1374
|
type: "relationship";
|
|
1269
1375
|
data: {
|
|
1376
|
+
sourceFqn: Fqn;
|
|
1377
|
+
targetFqn: Fqn;
|
|
1270
1378
|
relations: NonEmptyArray<RelationId>;
|
|
1271
1379
|
color: Color | undefined;
|
|
1272
1380
|
label: string | null;
|
|
@@ -1306,6 +1414,8 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
1306
1414
|
focusable?: boolean;
|
|
1307
1415
|
type: "relationship";
|
|
1308
1416
|
data: {
|
|
1417
|
+
sourceFqn: Fqn;
|
|
1418
|
+
targetFqn: Fqn;
|
|
1309
1419
|
relations: NonEmptyArray<RelationId>;
|
|
1310
1420
|
color: Color | undefined;
|
|
1311
1421
|
label: string | null;
|
|
@@ -1344,6 +1454,8 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
1344
1454
|
focusable?: boolean;
|
|
1345
1455
|
type: "relationship";
|
|
1346
1456
|
data: {
|
|
1457
|
+
sourceFqn: Fqn;
|
|
1458
|
+
targetFqn: Fqn;
|
|
1347
1459
|
relations: NonEmptyArray<RelationId>;
|
|
1348
1460
|
color: Color | undefined;
|
|
1349
1461
|
label: string | null;
|
|
@@ -1406,10 +1518,6 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
1406
1518
|
type: "update.view";
|
|
1407
1519
|
params: NonReducibleUnknown;
|
|
1408
1520
|
};
|
|
1409
|
-
"xyflow:updateNodeInternals": {
|
|
1410
|
-
type: "xyflow:updateNodeInternals";
|
|
1411
|
-
params: unknown;
|
|
1412
|
-
};
|
|
1413
1521
|
"xyflow:fitDiagram": {
|
|
1414
1522
|
type: "xyflow:fitDiagram";
|
|
1415
1523
|
params: {
|
|
@@ -1417,11 +1525,19 @@ export declare const relationshipsBrowserLogic: StateMachine<Readonly<{
|
|
|
1417
1525
|
bounds?: BBox;
|
|
1418
1526
|
} | undefined;
|
|
1419
1527
|
};
|
|
1528
|
+
"xyflow:updateNodeInternals": {
|
|
1529
|
+
type: "xyflow:updateNodeInternals";
|
|
1530
|
+
params: unknown;
|
|
1531
|
+
};
|
|
1420
1532
|
}>, Values<{
|
|
1421
1533
|
isReady: {
|
|
1422
1534
|
type: "isReady";
|
|
1423
1535
|
params: unknown;
|
|
1424
1536
|
};
|
|
1537
|
+
hasViewId: {
|
|
1538
|
+
type: "hasViewId";
|
|
1539
|
+
params: unknown;
|
|
1540
|
+
};
|
|
1425
1541
|
anotherSubject: {
|
|
1426
1542
|
type: "anotherSubject";
|
|
1427
1543
|
params: unknown;
|