@likec4/diagram 1.6.1 → 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.
- package/dist/LikeC4Diagram.d.ts +1 -1
- package/dist/LikeC4Diagram.props.d.ts +10 -11
- package/dist/hooks/useUpdateEffect.d.ts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +572 -464
- package/dist/state/DiagramContext.d.ts +746 -181
- package/dist/state/diagram-to-xyflow.d.ts +10 -0
- package/dist/state/diagramStore.d.ts +782 -202
- package/dist/style.css +273 -275
- package/dist/types.d.ts +20 -0
- package/dist/xyflow/EdgeMarkers.d.ts +1 -0
- package/dist/xyflow/FitviewOnDiagramChange.d.ts +1 -1
- package/dist/xyflow/XYFlow.d.ts +1 -4
- package/dist/xyflow/XYFlowEvents.d.ts +41 -12
- package/dist/xyflow/XYFlowInner.d.ts +0 -1
- package/dist/xyflow/edges/RelationshipEdge.d.ts +3 -3
- package/dist/xyflow/hooks/index.d.ts +0 -1
- package/dist/xyflow/hooks/useXYFlow.d.ts +27 -27
- package/dist/xyflow/types.d.ts +11 -19
- package/dist/xyflow/utils.d.ts +1 -0
- package/package.json +6 -6
- package/src/LikeC4Diagram.props.ts +17 -13
- package/src/LikeC4Diagram.tsx +62 -96
- package/src/globals.css.ts +10 -6
- package/src/hooks/useUpdateEffect.ts +16 -1
- package/src/index.ts +1 -0
- package/src/state/DiagramContext.tsx +19 -27
- package/src/{xyflow → state}/diagram-to-xyflow.ts +19 -18
- package/src/state/diagramStore.ts +404 -192
- package/src/types.ts +22 -0
- package/src/ui/BackwardForwardPanel.tsx +24 -7
- package/src/xyflow/EdgeMarkers.tsx +2 -0
- package/src/xyflow/FitviewOnDiagramChange.tsx +42 -75
- package/src/xyflow/SelectEdgesOnNodeFocus.tsx +1 -1
- package/src/xyflow/XYFlow.tsx +57 -32
- package/src/xyflow/XYFlowEvents.tsx +58 -10
- package/src/xyflow/XYFlowInner.tsx +8 -8
- package/src/xyflow/edges/RelationshipEdge.tsx +43 -29
- package/src/xyflow/edges/edges.css.ts +3 -3
- package/src/xyflow/edges/utils.ts +0 -1
- package/src/xyflow/hooks/index.ts +0 -1
- package/src/xyflow/hooks/useLayoutConstraints.ts +42 -65
- package/src/xyflow/nodes/element/ElementNode.tsx +0 -4
- package/src/xyflow/nodes/element/element.css.ts +8 -6
- package/src/xyflow/types.ts +14 -32
- package/src/xyflow/utils.ts +4 -0
- package/dist/xyflow/SyncWithDiagram.d.ts +0 -4
- package/dist/xyflow/diagram-to-xyflow.d.ts +0 -7
- package/src/xyflow/SyncWithDiagram.tsx +0 -85
package/dist/index.mjs
CHANGED
|
@@ -2,26 +2,26 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: !0, configurable: !0, writable: !0, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key != "symbol" ? key + "" : key, value);
|
|
4
4
|
import { jsx, Fragment, jsxs } from "react/jsx-runtime";
|
|
5
|
-
import { useReactFlow, useStoreApi, useNodesData, useStore, getViewportForBounds, EdgeLabelRenderer, Handle, Position, useOnViewportChange, ReactFlow, useOnSelectionChange, Background, BackgroundVariant, Controls, ReactFlowProvider } from "@xyflow/react";
|
|
5
|
+
import { useReactFlow, useStoreApi, useNodesData, useStore, applyNodeChanges, applyEdgeChanges, getViewportForBounds, EdgeLabelRenderer, Handle, Position, useOnViewportChange, ReactFlow, useOnSelectionChange, Background, BackgroundVariant, Controls, ReactFlowProvider } from "@xyflow/react";
|
|
6
6
|
import clsx from "clsx";
|
|
7
7
|
import { shallowEqual, deepEqual } from "fast-equals";
|
|
8
8
|
import { m, AnimatePresence, LazyMotion, domAnimation } from "framer-motion";
|
|
9
|
-
import { useContext, useState, useCallback, createContext, useRef, useEffect,
|
|
9
|
+
import { useContext, useState, useCallback, createContext, useRef, useEffect, memo, useMemo, useId } from "react";
|
|
10
10
|
import { MantineContext, Box, ActionIcon, Text as Text$1, HoverCard, HoverCardTarget, UnstyledButton, HoverCardDropdown, Stack, Group, Anchor, CopyButton, Button, Card, CardSection, Spoiler, ButtonGroup, rem, Divider, Space, TooltipGroup, Flex, Tooltip, ColorSwatch, CheckIcon, Select, Slider, SegmentedControl } from "@mantine/core";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { getNodeDimensions, nodeToRect, getBoundsOfRects, getViewportForBounds as getViewportForBounds$1 } from "@xyflow/system";
|
|
11
|
+
import { invariant, hasAtLeast, extractStep, nonNullable, StepEdgeId, getBBoxCenter, nonexhaustive, isAncestor, defaultTheme, ElementShapes } from "@likec4/core";
|
|
12
|
+
import { getNodeDimensions, getBoundsOfRects, boxToRect, nodeToRect, getViewportForBounds as getViewportForBounds$1 } from "@xyflow/system";
|
|
14
13
|
import { DEV } from "esm-env";
|
|
14
|
+
import { isArray, hasAtLeast as hasAtLeast$1, isNullish, entries, reduce, isTruthy, first, last, clamp, isNumber, isNonNullish, keys, takeWhile } from "remeda";
|
|
15
15
|
import { subscribeWithSelector, devtools } from "zustand/middleware";
|
|
16
16
|
import { shallow } from "zustand/shallow";
|
|
17
17
|
import { createWithEqualityFn, useStoreWithEqualityFn } from "zustand/traditional";
|
|
18
18
|
import { Bezier } from "bezier-js";
|
|
19
|
-
import { useFirstMountState, useCustomCompareEffect, useDebouncedEffect
|
|
19
|
+
import { useFirstMountState, useCustomCompareEffect, useDebouncedEffect } from "@react-hookz/web";
|
|
20
20
|
import { assignInlineVars } from "@vanilla-extract/dynamic";
|
|
21
21
|
import { line, curveCatmullRomOpen } from "d3-shape";
|
|
22
22
|
import { Solver, Operator, Expression, Strength, Variable } from "@lume/kiwi";
|
|
23
23
|
import { IconZoomScan, IconLink, IconChevronLeft, IconChevronRight, IconMenu, IconPlayerPlayFilled, IconPlayerSkipBackFilled, IconPlayerStopFilled, IconPlayerSkipForwardFilled } from "@tabler/icons-react";
|
|
24
|
-
import {
|
|
24
|
+
import { useLocalStorage, useHotkeys } from "@mantine/hooks";
|
|
25
25
|
var rootClassName = "likec4-diagram-root", cssReactFlow = "_2h8g8h0", cssDisablePan = "_2h8g8h1", cssTransparentBg = "_2h8g8h2", cssNoControls = "_2h8g8h3";
|
|
26
26
|
function EnsureMantine({ children }) {
|
|
27
27
|
if (!useContext(MantineContext))
|
|
@@ -42,13 +42,22 @@ function useSetState(initialState) {
|
|
|
42
42
|
return [state, setState];
|
|
43
43
|
}
|
|
44
44
|
const noop = () => {
|
|
45
|
+
}, depsShallowEqual = (d1, d2) => {
|
|
46
|
+
if (d1 === d2)
|
|
47
|
+
return !0;
|
|
48
|
+
if (d1.length !== d2.length)
|
|
49
|
+
return !1;
|
|
50
|
+
for (const [i, element] of d1.entries())
|
|
51
|
+
if (!shallowEqual(element, d2[i]))
|
|
52
|
+
return !1;
|
|
53
|
+
return !0;
|
|
45
54
|
};
|
|
46
55
|
function useUpdateEffect(callback, deps, equalityFn, effectHook) {
|
|
47
56
|
const isFirstMount = useFirstMountState();
|
|
48
57
|
useCustomCompareEffect(
|
|
49
58
|
isFirstMount ? noop : callback,
|
|
50
59
|
deps,
|
|
51
|
-
equalityFn ??
|
|
60
|
+
equalityFn ?? depsShallowEqual,
|
|
52
61
|
effectHook
|
|
53
62
|
);
|
|
54
63
|
}
|
|
@@ -91,11 +100,79 @@ function isSamePoint$1(a, b) {
|
|
|
91
100
|
const [ax, ay] = isArray(a) ? a : [a.x, a.y], [bx, by] = isArray(b) ? b : [b.x, b.y];
|
|
92
101
|
return isClose(ax, bx) && isClose(ay, by);
|
|
93
102
|
}
|
|
103
|
+
function diagramViewToXYFlowData(view, opts) {
|
|
104
|
+
const isDynamicView = view.__ === "dynamic", xynodes = [], xyedges = [], nodeLookup = /* @__PURE__ */ new Map(), traverse = view.nodes.reduce(
|
|
105
|
+
(acc, node) => (nodeLookup.set(node.id, node), node.parent || acc.push({ node, parent: null }), acc),
|
|
106
|
+
new Array()
|
|
107
|
+
), ns = "", nodeById = (id) => nonNullable(nodeLookup.get(id), `Node not found: ${id}`);
|
|
108
|
+
let next;
|
|
109
|
+
for (; next = traverse.shift(); ) {
|
|
110
|
+
const { node, parent } = next;
|
|
111
|
+
node.children.length > 0 && traverse.push(...node.children.map((child) => ({ node: nodeById(child), parent: node })));
|
|
112
|
+
const isCompound = hasAtLeast$1(node.children, 1), position = {
|
|
113
|
+
x: node.position[0],
|
|
114
|
+
y: node.position[1]
|
|
115
|
+
};
|
|
116
|
+
parent && (position.x -= parent.position[0], position.y -= parent.position[1]);
|
|
117
|
+
const id = ns + node.id, draggable = opts.draggable && (!parent || parent.children.length > 1);
|
|
118
|
+
xynodes.push({
|
|
119
|
+
id,
|
|
120
|
+
type: isCompound ? "compound" : "element",
|
|
121
|
+
data: {
|
|
122
|
+
fqn: node.id,
|
|
123
|
+
element: node
|
|
124
|
+
},
|
|
125
|
+
draggable,
|
|
126
|
+
selectable: opts.selectable,
|
|
127
|
+
deletable: !1,
|
|
128
|
+
position,
|
|
129
|
+
zIndex: isCompound ? ZIndexes.Compound : ZIndexes.Element,
|
|
130
|
+
hidden: !1,
|
|
131
|
+
width: node.width,
|
|
132
|
+
height: node.height,
|
|
133
|
+
// parentId: parent ? ns + parent.id : null,
|
|
134
|
+
...parent && {
|
|
135
|
+
parentId: ns + parent.id
|
|
136
|
+
},
|
|
137
|
+
...isCompound && {
|
|
138
|
+
dragHandle: ".likec4-compound-title"
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
for (const edge of view.edges) {
|
|
143
|
+
const source = edge.source, target = edge.target, id = ns + edge.id;
|
|
144
|
+
invariant(hasAtLeast$1(edge.points, 2), "edge should have at least 2 points"), xyedges.push({
|
|
145
|
+
id,
|
|
146
|
+
type: "relationship",
|
|
147
|
+
source: ns + source,
|
|
148
|
+
target: ns + target,
|
|
149
|
+
zIndex: ZIndexes.Edge,
|
|
150
|
+
selectable: opts.selectable,
|
|
151
|
+
deletable: !1,
|
|
152
|
+
data: {
|
|
153
|
+
edge,
|
|
154
|
+
controlPoints: edge.controlPoints || null,
|
|
155
|
+
stepNum: isDynamicView ? extractStep(edge.id) : null,
|
|
156
|
+
label: edge.labelBBox ? {
|
|
157
|
+
bbox: edge.labelBBox,
|
|
158
|
+
text: edge.label ?? ""
|
|
159
|
+
} : null
|
|
160
|
+
},
|
|
161
|
+
interactionWidth: 20
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
xynodes,
|
|
166
|
+
xyedges
|
|
167
|
+
};
|
|
168
|
+
}
|
|
94
169
|
const StringSet = Set, DEFAULT_PROPS = {
|
|
170
|
+
xyedges: [],
|
|
171
|
+
xynodes: [],
|
|
172
|
+
isDynamicView: !1,
|
|
95
173
|
viewSyncDebounceTimeout: null,
|
|
96
174
|
initialized: !1,
|
|
97
|
-
|
|
98
|
-
previousViews: [],
|
|
175
|
+
navigationHistoryIndex: 0,
|
|
99
176
|
viewportChanged: !1,
|
|
100
177
|
activeDynamicViewStep: null,
|
|
101
178
|
focusedNodeId: null,
|
|
@@ -104,47 +181,63 @@ const StringSet = Set, DEFAULT_PROPS = {
|
|
|
104
181
|
lastClickedNodeId: null,
|
|
105
182
|
lastClickedEdgeId: null,
|
|
106
183
|
dimmed: new StringSet(),
|
|
107
|
-
lastOnNavigate: null
|
|
108
|
-
onChange: null,
|
|
109
|
-
onNavigateTo: null,
|
|
110
|
-
onNodeClick: null,
|
|
111
|
-
onNodeContextMenu: null,
|
|
112
|
-
onCanvasContextMenu: null,
|
|
113
|
-
onEdgeClick: null,
|
|
114
|
-
onEdgeContextMenu: null,
|
|
115
|
-
onCanvasClick: null,
|
|
116
|
-
onCanvasDblClick: null
|
|
184
|
+
lastOnNavigate: null
|
|
117
185
|
}, noReplace = !1;
|
|
118
186
|
let StoreDevId = 1;
|
|
119
187
|
const EmptyStringSet = new StringSet();
|
|
120
188
|
function createDiagramStore(props) {
|
|
121
|
-
const storeDevId = "DiagramStore" + String(StoreDevId++).padStart(2, "0")
|
|
189
|
+
const storeDevId = "DiagramStore" + String(StoreDevId++).padStart(2, "0"), {
|
|
190
|
+
xynodes,
|
|
191
|
+
xyedges
|
|
192
|
+
} = diagramViewToXYFlowData(props.view, {
|
|
193
|
+
draggable: props.nodesDraggable,
|
|
194
|
+
selectable: props.nodesSelectable
|
|
195
|
+
});
|
|
122
196
|
return createWithEqualityFn(
|
|
123
197
|
subscribeWithSelector(
|
|
124
198
|
devtools(
|
|
125
199
|
(set, get) => ({
|
|
126
|
-
storeDevId,
|
|
127
200
|
...DEFAULT_PROPS,
|
|
128
201
|
...props,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
202
|
+
storeDevId,
|
|
203
|
+
isDynamicView: props.view.__ === "dynamic",
|
|
204
|
+
xynodes,
|
|
205
|
+
xyedges,
|
|
206
|
+
navigationHistory: [{
|
|
207
|
+
viewId: props.view.id,
|
|
208
|
+
nodeId: null
|
|
209
|
+
}],
|
|
210
|
+
navigationHistoryIndex: 0,
|
|
211
|
+
onNodesChange: (changes) => {
|
|
212
|
+
set({
|
|
213
|
+
xynodes: applyNodeChanges(changes, get().xynodes)
|
|
214
|
+
});
|
|
215
|
+
},
|
|
216
|
+
onEdgesChange: (changes) => {
|
|
217
|
+
set({
|
|
218
|
+
xyedges: applyEdgeChanges(changes, get().xyedges)
|
|
219
|
+
});
|
|
132
220
|
},
|
|
133
221
|
updateView: (nextView) => {
|
|
134
222
|
let {
|
|
135
223
|
viewSyncDebounceTimeout,
|
|
136
224
|
xyflow,
|
|
225
|
+
xystore,
|
|
137
226
|
dimmed: dimmed2,
|
|
138
|
-
xyflowSynced,
|
|
139
227
|
view: current,
|
|
140
228
|
lastOnNavigate,
|
|
141
|
-
|
|
229
|
+
navigationHistory,
|
|
230
|
+
navigationHistoryIndex,
|
|
142
231
|
focusedNodeId,
|
|
143
232
|
lastClickedNodeId,
|
|
144
233
|
lastClickedEdgeId,
|
|
145
234
|
activeDynamicViewStep,
|
|
235
|
+
nodesDraggable,
|
|
236
|
+
nodesSelectable,
|
|
146
237
|
hoveredEdgeId,
|
|
147
|
-
hoveredNodeId
|
|
238
|
+
hoveredNodeId,
|
|
239
|
+
xyedges: xyedges2,
|
|
240
|
+
xynodes: xynodes2
|
|
148
241
|
} = get();
|
|
149
242
|
if (shallowEqual(current, nextView)) {
|
|
150
243
|
DEV && console.debug("store: skip updateView");
|
|
@@ -154,42 +247,90 @@ function createDiagramStore(props) {
|
|
|
154
247
|
const isSameView = current.id === nextView.id;
|
|
155
248
|
if (isSameView) {
|
|
156
249
|
const nodeIds = new StringSet(nextView.nodes.map((n) => n.id)), edgeIds = new StringSet(nextView.edges.map((e) => e.id));
|
|
157
|
-
if (lastClickedNodeId && !nodeIds.has(lastClickedNodeId) && (lastClickedNodeId = null), hoveredNodeId && !nodeIds.has(hoveredNodeId) && (hoveredNodeId = null), focusedNodeId && !nodeIds.has(focusedNodeId) && (focusedNodeId = null), lastClickedEdgeId && !edgeIds.has(lastClickedEdgeId) && (lastClickedEdgeId = null), hoveredEdgeId && !edgeIds.has(hoveredEdgeId) && (hoveredEdgeId = null), activeDynamicViewStep && !edgeIds.has(StepEdgeId(activeDynamicViewStep)) && (activeDynamicViewStep = null),
|
|
250
|
+
if (lastClickedNodeId && !nodeIds.has(lastClickedNodeId) && (lastClickedNodeId = null), hoveredNodeId && !nodeIds.has(hoveredNodeId) && (hoveredNodeId = null), focusedNodeId && !nodeIds.has(focusedNodeId) && (focusedNodeId = null), lastClickedEdgeId && !edgeIds.has(lastClickedEdgeId) && (lastClickedEdgeId = null), hoveredEdgeId && !edgeIds.has(hoveredEdgeId) && (hoveredEdgeId = null), activeDynamicViewStep && !edgeIds.has(StepEdgeId(activeDynamicViewStep)) && (activeDynamicViewStep = null), dimmed2.size > 0) {
|
|
158
251
|
let nextDimmed = new StringSet([...dimmed2].filter((id) => nodeIds.has(id) || edgeIds.has(id)));
|
|
159
252
|
nextDimmed.size !== dimmed2.size && (dimmed2 = nextDimmed);
|
|
160
253
|
}
|
|
161
254
|
} else {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
255
|
+
const stepCurrent = nonNullable(navigationHistory[navigationHistoryIndex]);
|
|
256
|
+
stepCurrent.viewId !== nextView.id ? (navigationHistory = [
|
|
257
|
+
...navigationHistory.slice(0, navigationHistoryIndex + 1),
|
|
258
|
+
{
|
|
259
|
+
viewId: nextView.id,
|
|
260
|
+
nodeId: (lastOnNavigate == null ? void 0 : lastOnNavigate.fromNode) || null
|
|
261
|
+
}
|
|
262
|
+
], navigationHistoryIndex = navigationHistory.length - 1) : stepCurrent.nodeId && (lastOnNavigate ?? (lastOnNavigate = {
|
|
263
|
+
fromView: current.id,
|
|
264
|
+
toView: nextView.id,
|
|
265
|
+
fromNode: stepCurrent.nodeId
|
|
266
|
+
})), lastOnNavigate && lastOnNavigate.toView !== nextView.id && (lastOnNavigate = null);
|
|
267
|
+
const elTo = lastOnNavigate && nextView.nodes.find((n) => n.id === (lastOnNavigate == null ? void 0 : lastOnNavigate.fromNode)), xynodeFrom = elTo && xyflow.getInternalNode(elTo.id);
|
|
268
|
+
if (!lastOnNavigate || isNullish(elTo) || isNullish(xynodeFrom)) {
|
|
269
|
+
const zoom = xyflow.getZoom(), { x, y } = getBBoxCenter(nextView.bounds);
|
|
270
|
+
xyflow.setCenter(x, y, { zoom }), lastOnNavigate = null;
|
|
271
|
+
}
|
|
272
|
+
if (lastOnNavigate && elTo && xynodeFrom) {
|
|
273
|
+
const fromPos = xyflow.flowToScreenPosition({
|
|
274
|
+
x: xynodeFrom.internals.positionAbsolute.x,
|
|
275
|
+
// + dimensions.width / 2,
|
|
276
|
+
y: xynodeFrom.internals.positionAbsolute.y
|
|
277
|
+
// + dimensions.height / 2
|
|
278
|
+
}), toPos = xyflow.flowToScreenPosition({
|
|
279
|
+
x: elTo.position[0],
|
|
280
|
+
// + elFrom.width / 2,
|
|
281
|
+
y: elTo.position[1]
|
|
282
|
+
// + elFrom.height / 2
|
|
283
|
+
}), diff = {
|
|
284
|
+
x: toDomPrecision(fromPos.x - toPos.x),
|
|
285
|
+
y: toDomPrecision(fromPos.y - toPos.y)
|
|
286
|
+
};
|
|
287
|
+
xystore.getState().panBy(diff), lastOnNavigate = null;
|
|
165
288
|
}
|
|
166
|
-
lastClickedEdgeId = null, lastClickedNodeId = null, hoveredEdgeId = null, hoveredNodeId = null, focusedNodeId = null, activeDynamicViewStep = null, dimmed2 = EmptyStringSet
|
|
167
|
-
current,
|
|
168
|
-
...previousViews.filter((v) => v.id !== nextView.id && v.id !== current.id)
|
|
169
|
-
], xyflowSynced = !1;
|
|
289
|
+
lastClickedEdgeId = null, lastClickedNodeId = null, hoveredEdgeId = null, hoveredNodeId = null, focusedNodeId = null, activeDynamicViewStep = null, dimmed2 = EmptyStringSet;
|
|
170
290
|
}
|
|
291
|
+
const update = diagramViewToXYFlowData(nextView, {
|
|
292
|
+
draggable: nodesDraggable,
|
|
293
|
+
selectable: nodesSelectable
|
|
294
|
+
});
|
|
295
|
+
update.xynodes = update.xynodes.map((update2) => {
|
|
296
|
+
const existing = xynodes2.find((n) => n.id === update2.id);
|
|
297
|
+
return existing && existing.type === update2.type && deepEqual(existing.parentId ?? null, update2.parentId ?? null) ? deepEqual(existing.data.element, update2.data.element) ? existing : {
|
|
298
|
+
...existing,
|
|
299
|
+
...update2
|
|
300
|
+
} : update2;
|
|
301
|
+
}), isSameView && !nextView.hasLayoutDrift && (update.xyedges = update.xyedges.map((update2) => {
|
|
302
|
+
const existing = xyedges2.find((n) => n.id === update2.id);
|
|
303
|
+
return existing ? deepEqual(existing.data, update2.data) ? existing : {
|
|
304
|
+
...existing,
|
|
305
|
+
...update2
|
|
306
|
+
} : update2;
|
|
307
|
+
}));
|
|
308
|
+
const hasChanges = !isSameView || !shallowEqual(update.xynodes, xynodes2) || !shallowEqual(update.xyedges, xyedges2);
|
|
171
309
|
set(
|
|
172
310
|
{
|
|
311
|
+
isDynamicView: nextView.__ === "dynamic",
|
|
173
312
|
viewSyncDebounceTimeout,
|
|
174
313
|
view: nextView,
|
|
175
314
|
activeDynamicViewStep,
|
|
176
|
-
xyflowSynced,
|
|
177
315
|
lastOnNavigate,
|
|
178
|
-
previousViews,
|
|
179
316
|
lastClickedNodeId,
|
|
180
317
|
lastClickedEdgeId,
|
|
181
318
|
focusedNodeId,
|
|
182
319
|
hoveredEdgeId,
|
|
183
320
|
hoveredNodeId,
|
|
184
|
-
|
|
321
|
+
navigationHistory,
|
|
322
|
+
navigationHistoryIndex,
|
|
323
|
+
dimmed: dimmed2,
|
|
324
|
+
xynodes: hasChanges ? update.xynodes : xynodes2,
|
|
325
|
+
xyedges: hasChanges ? update.xyedges : xyedges2
|
|
185
326
|
},
|
|
186
327
|
noReplace,
|
|
187
328
|
isSameView ? "update-view [same]" : "update-view [another]"
|
|
188
329
|
);
|
|
189
330
|
},
|
|
190
331
|
focusOnNode: (nodeId) => {
|
|
191
|
-
const { focusedNodeId, view } = get();
|
|
192
|
-
if (nodeId !== focusedNodeId) {
|
|
332
|
+
const { focusedNodeId, view, enableFocusMode } = get();
|
|
333
|
+
if (invariant(enableFocusMode, "focus mode is not enabled"), nodeId !== focusedNodeId) {
|
|
193
334
|
const notDimmed = new StringSet([nodeId]), dimmed2 = new StringSet();
|
|
194
335
|
for (const edge of view.edges)
|
|
195
336
|
edge.source === nodeId || edge.target === nodeId ? (notDimmed.add(edge.source), notDimmed.add(edge.target)) : dimmed2.add(edge.id);
|
|
@@ -294,87 +435,139 @@ function createDiagramStore(props) {
|
|
|
294
435
|
},
|
|
295
436
|
cancelSaveManualLayout: () => {
|
|
296
437
|
let { viewSyncDebounceTimeout } = get();
|
|
297
|
-
viewSyncDebounceTimeout !== null
|
|
438
|
+
return viewSyncDebounceTimeout !== null ? (clearTimeout(viewSyncDebounceTimeout), set({ viewSyncDebounceTimeout: null }), !0) : !1;
|
|
298
439
|
},
|
|
299
440
|
triggerSaveManualLayout: () => {
|
|
300
|
-
|
|
301
|
-
if (!onChange) {
|
|
441
|
+
const { xyflow, view, onChange, xystore, viewSyncDebounceTimeout } = get();
|
|
442
|
+
if (viewSyncDebounceTimeout !== null && (clearTimeout(viewSyncDebounceTimeout), set({ viewSyncDebounceTimeout: null })), !onChange) {
|
|
302
443
|
DEV && console.debug("ignore triggerSaveManualLayout, as no onChange handler is set");
|
|
303
444
|
return;
|
|
304
445
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
446
|
+
const { nodeLookup } = xystore.getState(), movedNodes = new StringSet();
|
|
447
|
+
let bounds = {
|
|
448
|
+
x: 0,
|
|
449
|
+
y: 0,
|
|
450
|
+
width: 1,
|
|
451
|
+
height: 1
|
|
452
|
+
};
|
|
453
|
+
const nodes = reduce([...nodeLookup.values()], (acc, node) => {
|
|
454
|
+
const dimensions = getNodeDimensions(node);
|
|
455
|
+
isSamePoint$1(node.internals.positionAbsolute, node.data.element.position) || movedNodes.add(node.id);
|
|
456
|
+
const rect = acc[node.data.fqn] = {
|
|
457
|
+
isCompound: node.data.element.children.length > 0,
|
|
458
|
+
x: Math.floor(node.internals.positionAbsolute.x),
|
|
459
|
+
y: Math.floor(node.internals.positionAbsolute.y),
|
|
460
|
+
width: Math.ceil(dimensions.width),
|
|
461
|
+
height: Math.ceil(dimensions.height)
|
|
462
|
+
};
|
|
463
|
+
return bounds = getBoundsOfRects(bounds, rect), acc;
|
|
464
|
+
}, {}), edges = reduce(xyflow.getEdges(), (acc, { source, target, data }) => {
|
|
465
|
+
var _a, _b;
|
|
466
|
+
let controlPoints = data.controlPoints;
|
|
467
|
+
const sourceOrTargetMoved = movedNodes.has(source) || movedNodes.has(target);
|
|
468
|
+
if ((!controlPoints || controlPoints.length === 0) && sourceOrTargetMoved && (controlPoints = bezierControlPoints(data.edge)), data.edge.points.length === 0 && (!controlPoints || controlPoints.length === 0))
|
|
469
|
+
return acc;
|
|
470
|
+
const _updated = acc[data.edge.id] = {
|
|
471
|
+
points: data.edge.points
|
|
330
472
|
};
|
|
331
|
-
|
|
332
|
-
|
|
473
|
+
(_a = data.label) != null && _a.bbox && (_updated.labelBBox = (_b = data.label) == null ? void 0 : _b.bbox), data.edge.labelBBox && (_updated.labelBBox ?? (_updated.labelBBox = data.edge.labelBBox)), controlPoints && hasAtLeast$1(controlPoints, 1) && (_updated.controlPoints = controlPoints), !sourceOrTargetMoved && data.edge.dotpos && (_updated.dotpos = data.edge.dotpos);
|
|
474
|
+
const allX = [...data.edge.points.map((p) => p[0]), ...(controlPoints ?? []).map((p) => p.x)], allY = [...data.edge.points.map((p) => p[1]), ...(controlPoints ?? []).map((p) => p.y)], rect = boxToRect({
|
|
475
|
+
x: Math.floor(Math.min(...allX)),
|
|
476
|
+
y: Math.floor(Math.min(...allY)),
|
|
477
|
+
x2: Math.ceil(Math.max(...allX)),
|
|
478
|
+
y2: Math.ceil(Math.max(...allY))
|
|
479
|
+
});
|
|
480
|
+
return bounds = getBoundsOfRects(bounds, rect), acc;
|
|
481
|
+
}, {}), change = {
|
|
482
|
+
op: "save-manual-layout",
|
|
483
|
+
layout: {
|
|
484
|
+
hash: view.hash,
|
|
485
|
+
autoLayout: view.autoLayout,
|
|
486
|
+
nodes,
|
|
487
|
+
edges,
|
|
488
|
+
...bounds
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
DEV && console.debug("triggerSaveManualLayout", change), onChange({ change });
|
|
492
|
+
},
|
|
493
|
+
scheduleSaveManualLayout: () => {
|
|
494
|
+
let { viewSyncDebounceTimeout, onChange } = get();
|
|
495
|
+
if (!onChange) {
|
|
496
|
+
DEV && console.debug("ignore triggerSaveManualLayout, as no onChange handler is set");
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
viewSyncDebounceTimeout && clearTimeout(viewSyncDebounceTimeout), set(
|
|
333
500
|
{
|
|
334
|
-
viewSyncDebounceTimeout:
|
|
501
|
+
viewSyncDebounceTimeout: setTimeout(() => {
|
|
502
|
+
get().triggerSaveManualLayout();
|
|
503
|
+
}, 1e3)
|
|
504
|
+
// explicit typecast to number to suppress TS error in astro build
|
|
335
505
|
},
|
|
336
506
|
noReplace,
|
|
337
507
|
"debounce sync state"
|
|
338
508
|
);
|
|
339
509
|
},
|
|
340
510
|
triggerOnNavigateTo: (xynodeId, event) => {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
const
|
|
345
|
-
invariant(
|
|
511
|
+
const { view, xynodes: xynodes2, onNavigateTo } = get();
|
|
512
|
+
if (!onNavigateTo)
|
|
513
|
+
return;
|
|
514
|
+
const xynode = xynodes2.find(({ id }) => id === xynodeId);
|
|
515
|
+
invariant(xynode, `xynode not found: ${xynodeId}`);
|
|
516
|
+
const element = view.nodes.find(({ id }) => id === xynodeId);
|
|
517
|
+
invariant(element == null ? void 0 : element.navigateTo, `node is not navigable: ${xynodeId}`), set(
|
|
346
518
|
{
|
|
347
519
|
lastClickedNodeId: xynodeId,
|
|
348
520
|
lastOnNavigate: {
|
|
349
521
|
fromView: view.id,
|
|
350
522
|
toView: element.navigateTo,
|
|
351
|
-
element
|
|
352
|
-
elementScreenPosition: xyflow.flowToScreenPosition({
|
|
353
|
-
x: xynode.internals.positionAbsolute.x,
|
|
354
|
-
// + dimensions.width / 2,
|
|
355
|
-
y: xynode.internals.positionAbsolute.y
|
|
356
|
-
// + dimensions.height / 2
|
|
357
|
-
}),
|
|
358
|
-
positionCorrected: !1
|
|
523
|
+
fromNode: element.id
|
|
359
524
|
}
|
|
360
525
|
},
|
|
361
526
|
noReplace,
|
|
362
527
|
"triggerOnNavigateTo"
|
|
363
|
-
),
|
|
364
|
-
_a,
|
|
528
|
+
), onNavigateTo(
|
|
365
529
|
element.navigateTo,
|
|
366
530
|
event,
|
|
367
531
|
element,
|
|
368
|
-
xynode
|
|
532
|
+
xynode
|
|
369
533
|
);
|
|
370
534
|
},
|
|
535
|
+
goBack: () => {
|
|
536
|
+
const { navigationHistory, navigationHistoryIndex, onNavigateTo } = get(), { viewId, nodeId } = nonNullable(navigationHistory[navigationHistoryIndex]), stepBack = navigationHistoryIndex > 0 && navigationHistory[navigationHistoryIndex - 1] || null;
|
|
537
|
+
stepBack && onNavigateTo && (set(
|
|
538
|
+
{
|
|
539
|
+
lastClickedEdgeId: null,
|
|
540
|
+
lastClickedNodeId: null,
|
|
541
|
+
navigationHistoryIndex: navigationHistoryIndex - 1,
|
|
542
|
+
lastOnNavigate: nodeId ? {
|
|
543
|
+
fromView: viewId,
|
|
544
|
+
toView: stepBack.viewId,
|
|
545
|
+
fromNode: nodeId
|
|
546
|
+
} : null
|
|
547
|
+
},
|
|
548
|
+
noReplace,
|
|
549
|
+
"goBack"
|
|
550
|
+
), onNavigateTo(stepBack.viewId));
|
|
551
|
+
},
|
|
552
|
+
goForward: () => {
|
|
553
|
+
const { navigationHistory, navigationHistoryIndex, onNavigateTo } = get(), { viewId } = nonNullable(navigationHistory[navigationHistoryIndex]), stepForward = navigationHistoryIndex < navigationHistory.length - 1 ? navigationHistory[navigationHistoryIndex + 1] : null;
|
|
554
|
+
stepForward && onNavigateTo && (set(
|
|
555
|
+
{
|
|
556
|
+
lastClickedEdgeId: null,
|
|
557
|
+
lastClickedNodeId: null,
|
|
558
|
+
navigationHistoryIndex: navigationHistoryIndex + 1,
|
|
559
|
+
lastOnNavigate: stepForward.nodeId ? {
|
|
560
|
+
fromView: viewId,
|
|
561
|
+
toView: stepForward.viewId,
|
|
562
|
+
fromNode: stepForward.nodeId
|
|
563
|
+
} : null
|
|
564
|
+
},
|
|
565
|
+
noReplace,
|
|
566
|
+
"goForward"
|
|
567
|
+
), onNavigateTo(stepForward.viewId));
|
|
568
|
+
},
|
|
371
569
|
fitDiagram: (duration = 500) => {
|
|
372
|
-
const { fitViewPadding, view, focusedNodeId, activeDynamicViewStep, xystore } = get(), { width, height, panZoom, transform } = xystore.getState(), bounds =
|
|
373
|
-
x: 0,
|
|
374
|
-
y: 0,
|
|
375
|
-
width: view.width,
|
|
376
|
-
height: view.height
|
|
377
|
-
}, maxZoom = Math.max(1, transform[2]), viewport = getViewportForBounds(bounds, width, height, MinZoom, maxZoom, fitViewPadding);
|
|
570
|
+
const { fitViewPadding, view, focusedNodeId, activeDynamicViewStep, xystore } = get(), { width, height, panZoom, transform } = xystore.getState(), bounds = view.bounds, maxZoom = Math.max(1, transform[2]), viewport = getViewportForBounds(bounds, width, height, MinZoom, maxZoom, fitViewPadding);
|
|
378
571
|
panZoom == null || panZoom.setViewport(viewport, { duration }), (focusedNodeId ?? activeDynamicViewStep) !== null && set(
|
|
379
572
|
{
|
|
380
573
|
activeDynamicViewStep: null,
|
|
@@ -386,11 +579,12 @@ function createDiagramStore(props) {
|
|
|
386
579
|
);
|
|
387
580
|
},
|
|
388
581
|
nextDynamicStep: (increment = 1) => {
|
|
389
|
-
const {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
582
|
+
const { activeDynamicViewStep, activateDynamicStep } = get(), nextStep = (activeDynamicViewStep ?? 0) + increment;
|
|
583
|
+
nextStep <= 0 || nextStep !== activeDynamicViewStep && activateDynamicStep(nextStep);
|
|
584
|
+
},
|
|
585
|
+
activateDynamicStep: (nextStep) => {
|
|
586
|
+
const { isDynamicView, xyflow, xystore, fitViewPadding } = get();
|
|
587
|
+
invariant(isDynamicView, "view is not dynamic");
|
|
394
588
|
const edgeId = StepEdgeId(nextStep), dimmed2 = new StringSet();
|
|
395
589
|
let edge = null;
|
|
396
590
|
for (const e of xyflow.getEdges()) {
|
|
@@ -424,7 +618,7 @@ function createDiagramStore(props) {
|
|
|
424
618
|
dimmed: dimmed2
|
|
425
619
|
},
|
|
426
620
|
noReplace,
|
|
427
|
-
"
|
|
621
|
+
"activateDynamicStep"
|
|
428
622
|
);
|
|
429
623
|
},
|
|
430
624
|
stopDynamicView: () => {
|
|
@@ -437,6 +631,17 @@ function createDiagramStore(props) {
|
|
|
437
631
|
noReplace,
|
|
438
632
|
"stopDynamicView"
|
|
439
633
|
), get().fitDiagram());
|
|
634
|
+
},
|
|
635
|
+
onInit: (instance) => {
|
|
636
|
+
const { xyflow, initialized } = get();
|
|
637
|
+
(!initialized || xyflow !== instance) && set(
|
|
638
|
+
{
|
|
639
|
+
xyflow: instance,
|
|
640
|
+
initialized: !0
|
|
641
|
+
},
|
|
642
|
+
noReplace,
|
|
643
|
+
"onInit"
|
|
644
|
+
);
|
|
440
645
|
}
|
|
441
646
|
}),
|
|
442
647
|
{
|
|
@@ -456,28 +661,31 @@ function DiagramContextProvider({
|
|
|
456
661
|
keepAspectRatio,
|
|
457
662
|
...props
|
|
458
663
|
}) {
|
|
459
|
-
const containerRef = useRef(null), xystore = useXYStoreApi(), xyflow = useXYFlow(), store = useRef();
|
|
664
|
+
const containerRef = useRef(null), xystore = useXYStoreApi(), xyflow = useXYFlow(), store = useRef(), getContainer = useCallback(() => containerRef.current, [containerRef]);
|
|
460
665
|
return store.current || (store.current = createDiagramStore({
|
|
461
666
|
xystore,
|
|
462
667
|
xyflow,
|
|
463
668
|
view,
|
|
464
|
-
getContainer
|
|
669
|
+
getContainer,
|
|
465
670
|
...props
|
|
466
|
-
})),
|
|
671
|
+
})), useUpdateEffect(
|
|
672
|
+
() => {
|
|
673
|
+
var _a;
|
|
674
|
+
return (_a = store.current) == null ? void 0 : _a.setState({ xyflow, xystore, getContainer }, !1, "update xyflow and xystore");
|
|
675
|
+
},
|
|
676
|
+
[xyflow, xystore, getContainer]
|
|
677
|
+
), useUpdateEffect(
|
|
467
678
|
() => {
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
(state.xyflow !== xyflow || state.xystore !== xystore) && store.current.setState({ xyflow, xystore }, !1, "update xyflow and xystore");
|
|
679
|
+
var _a;
|
|
680
|
+
return (_a = store.current) == null ? void 0 : _a.setState(props, !1, "update incoming props");
|
|
471
681
|
},
|
|
472
|
-
[
|
|
682
|
+
[props]
|
|
473
683
|
), useUpdateEffect(
|
|
474
684
|
() => {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
hasSubObject(state, newProps) || store.current.setState(newProps, !1, "update incoming props"), state.view !== view && state.updateView(view);
|
|
685
|
+
var _a;
|
|
686
|
+
(_a = store.current) == null || _a.getState().updateView(view);
|
|
478
687
|
},
|
|
479
|
-
[view
|
|
480
|
-
(prev, next) => shallowEqual(prev[0], next[0]) && shallowEqual(prev[1], next[1])
|
|
688
|
+
[view]
|
|
481
689
|
), /* @__PURE__ */ jsx(
|
|
482
690
|
"div",
|
|
483
691
|
{
|
|
@@ -485,8 +693,8 @@ function DiagramContextProvider({
|
|
|
485
693
|
className,
|
|
486
694
|
...keepAspectRatio && {
|
|
487
695
|
style: {
|
|
488
|
-
aspectRatio: `${Math.ceil(view.width)}/${Math.ceil(view.height)}`,
|
|
489
|
-
maxHeight: Math.ceil(view.height)
|
|
696
|
+
aspectRatio: `${Math.ceil(view.bounds.width)}/${Math.ceil(view.bounds.height)}`,
|
|
697
|
+
maxHeight: Math.ceil(view.bounds.height)
|
|
490
698
|
}
|
|
491
699
|
},
|
|
492
700
|
children: /* @__PURE__ */ jsx(DiagramContext.Provider, { value: store.current, children })
|
|
@@ -505,158 +713,48 @@ function useDiagramStoreApi() {
|
|
|
505
713
|
throw new Error("useDiagramStoreApi could be used only inside DiagramContext");
|
|
506
714
|
return store;
|
|
507
715
|
}
|
|
508
|
-
function
|
|
509
|
-
var _a, _b;
|
|
510
|
-
const isDynamicView = view.__ === "dynamic", editor = {
|
|
511
|
-
nodes: [],
|
|
512
|
-
edges: []
|
|
513
|
-
}, nodeLookup = /* @__PURE__ */ new Map(), traverse = view.nodes.reduce(
|
|
514
|
-
(acc, node) => (nodeLookup.set(node.id, node), node.parent || acc.push({ node, parent: null }), acc),
|
|
515
|
-
new Array()
|
|
516
|
-
), ns = "", nodeById = (id) => nonNullable(nodeLookup.get(id), `Node not found: ${id}`);
|
|
517
|
-
let next;
|
|
518
|
-
for (; next = traverse.shift(); ) {
|
|
519
|
-
const { node, parent } = next;
|
|
520
|
-
node.children.length > 0 && traverse.push(...node.children.map((child) => ({ node: nodeById(child), parent: node })));
|
|
521
|
-
const isCompound = hasAtLeast$1(node.children, 1), position = {
|
|
522
|
-
x: node.position[0],
|
|
523
|
-
y: node.position[1]
|
|
524
|
-
};
|
|
525
|
-
parent && (position.x -= parent.position[0], position.y -= parent.position[1]);
|
|
526
|
-
const id = ns + node.id, draggable = opts.draggable && (!parent || parent.children.length > 1);
|
|
527
|
-
editor.nodes.push({
|
|
528
|
-
id,
|
|
529
|
-
type: isCompound ? "compound" : "element",
|
|
530
|
-
data: {
|
|
531
|
-
fqn: node.id,
|
|
532
|
-
element: node
|
|
533
|
-
},
|
|
534
|
-
draggable,
|
|
535
|
-
selectable: opts.selectable,
|
|
536
|
-
deletable: !1,
|
|
537
|
-
position,
|
|
538
|
-
zIndex: isCompound ? ZIndexes.Compound : ZIndexes.Element,
|
|
539
|
-
hidden: !1,
|
|
540
|
-
initialWidth: node.width,
|
|
541
|
-
initialHeight: node.height,
|
|
542
|
-
width: node.width,
|
|
543
|
-
height: node.height,
|
|
544
|
-
...parent && {
|
|
545
|
-
parentId: ns + parent.id
|
|
546
|
-
},
|
|
547
|
-
...isCompound && {
|
|
548
|
-
dragHandle: ".likec4-compound-title"
|
|
549
|
-
}
|
|
550
|
-
});
|
|
551
|
-
}
|
|
552
|
-
for (const edge of view.edges) {
|
|
553
|
-
const source = edge.source, target = edge.target, id = ns + edge.id;
|
|
554
|
-
invariant(hasAtLeast$1(edge.points, 2), "edge should have at least 2 points"), editor.edges.push({
|
|
555
|
-
id,
|
|
556
|
-
type: "relationship",
|
|
557
|
-
source: ns + source,
|
|
558
|
-
target: ns + target,
|
|
559
|
-
zIndex: ZIndexes.Edge,
|
|
560
|
-
selectable: opts.selectable,
|
|
561
|
-
deletable: !1,
|
|
562
|
-
data: {
|
|
563
|
-
edge,
|
|
564
|
-
type: "bezier",
|
|
565
|
-
controlPoints: ((_b = (_a = view.manualLayout) == null ? void 0 : _a.edges[edge.id]) == null ? void 0 : _b.controlPoints) || null,
|
|
566
|
-
stepNum: isDynamicView ? extractStep(edge.id) : null,
|
|
567
|
-
label: edge.labelBBox ? {
|
|
568
|
-
bbox: edge.labelBBox,
|
|
569
|
-
text: edge.label ?? ""
|
|
570
|
-
} : null
|
|
571
|
-
},
|
|
572
|
-
interactionWidth: 20
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
return editor;
|
|
576
|
-
}
|
|
577
|
-
function useNavigationHistory() {
|
|
578
|
-
const store = useDiagramStoreApi(), viewId = useDiagramState((s) => s.view.id), [historyViewId, historyOps, {
|
|
579
|
-
history,
|
|
580
|
-
current: historyIndex
|
|
581
|
-
}] = useStateHistory(viewId), hasBack = historyIndex > 0, hasForward = historyIndex < history.length - 1;
|
|
582
|
-
return useUpdateEffect(() => {
|
|
583
|
-
viewId !== historyViewId && historyOps.set(viewId);
|
|
584
|
-
}, [viewId]), useUpdateEffect(() => {
|
|
585
|
-
var _a, _b;
|
|
586
|
-
viewId !== historyViewId && ((_b = (_a = store.getState()).onNavigateTo) == null || _b.call(_a, historyViewId));
|
|
587
|
-
}, [historyViewId]), useMemo(() => ({
|
|
588
|
-
hasBack,
|
|
589
|
-
hasForward,
|
|
590
|
-
ops: historyOps
|
|
591
|
-
}), [
|
|
592
|
-
hasBack,
|
|
593
|
-
hasForward,
|
|
594
|
-
historyOps
|
|
595
|
-
]);
|
|
596
|
-
}
|
|
597
|
-
function selectDimensions(state) {
|
|
716
|
+
function selectXYFlowSize(state) {
|
|
598
717
|
return `${Math.round(state.width)}:${Math.round(state.height)}`;
|
|
599
718
|
}
|
|
600
|
-
function
|
|
601
|
-
|
|
719
|
+
function selectDiagramsize({ view, fitViewPadding }) {
|
|
720
|
+
return [
|
|
721
|
+
view.bounds.x,
|
|
722
|
+
view.bounds.y,
|
|
723
|
+
view.bounds.width,
|
|
724
|
+
view.bounds.height,
|
|
725
|
+
fitViewPadding
|
|
726
|
+
].map(Math.round).join(":");
|
|
727
|
+
}
|
|
728
|
+
function FitViewOnViewportResize({ diagramApi }) {
|
|
729
|
+
const xyflowsize = useXYStore(selectXYFlowSize), viewsize = useDiagramState(selectDiagramsize), dimensions = xyflowsize + viewsize, prevDimensionsRef = useRef(dimensions);
|
|
602
730
|
return useDebouncedEffect(
|
|
603
731
|
() => {
|
|
604
732
|
const { focusedNodeId, fitDiagram } = diagramApi.getState();
|
|
605
|
-
focusedNodeId || prevDimensionsRef.current === dimensions || (
|
|
733
|
+
focusedNodeId || prevDimensionsRef.current === dimensions || (prevDimensionsRef.current = dimensions, fitDiagram(250));
|
|
606
734
|
},
|
|
607
|
-
[dimensions, diagramApi
|
|
608
|
-
|
|
735
|
+
[dimensions, diagramApi],
|
|
736
|
+
250,
|
|
609
737
|
1e3
|
|
610
738
|
), null;
|
|
611
739
|
}
|
|
612
|
-
function selector$3({ view,
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
xyflowSynced,
|
|
617
|
-
viewportChanged,
|
|
618
|
-
waitCorrection: !0,
|
|
619
|
-
elFrom: lastOnNavigate.element,
|
|
620
|
-
elTo
|
|
621
|
-
} : {
|
|
622
|
-
viewId,
|
|
623
|
-
xyflowSynced,
|
|
624
|
-
viewportChanged,
|
|
625
|
-
waitCorrection: !1,
|
|
626
|
-
fromElement: null,
|
|
627
|
-
toElement: null
|
|
740
|
+
function selector$3({ view, viewportChanged, fitViewPadding }) {
|
|
741
|
+
return {
|
|
742
|
+
layoutId: view.id + "_" + view.autoLayout + "_" + fitViewPadding,
|
|
743
|
+
viewportNotMoved: !viewportChanged
|
|
628
744
|
};
|
|
629
745
|
}
|
|
630
746
|
function FitViewOnDiagramChange() {
|
|
631
|
-
const
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
invariant(elTo, "elTo should be defined"), invariant(elFrom, "elFrom should be defined");
|
|
643
|
-
const { xyflow, lastOnNavigate } = diagramApi.getState();
|
|
644
|
-
invariant(lastOnNavigate, "lastOnNavigate should be defined");
|
|
645
|
-
const fromPos = lastOnNavigate.elementScreenPosition, toPos = xyflow.flowToScreenPosition({
|
|
646
|
-
x: elTo.position[0],
|
|
647
|
-
// + elFrom.width / 2,
|
|
648
|
-
y: elTo.position[1]
|
|
649
|
-
// + elFrom.height / 2
|
|
650
|
-
}), diff = {
|
|
651
|
-
x: toDomPrecision(fromPos.x - toPos.x),
|
|
652
|
-
y: toDomPrecision(fromPos.y - toPos.y)
|
|
653
|
-
};
|
|
654
|
-
xyflowApi.getState().panBy(diff), durationRef.current = 500, diagramApi.setState({ lastOnNavigate: null });
|
|
655
|
-
return;
|
|
656
|
-
}
|
|
657
|
-
processedRef.current = pendingViewId, diagramApi.getState().fitDiagram(durationRef.current), durationRef.current = 300;
|
|
658
|
-
}
|
|
659
|
-
}, [pendingViewId, xyflowSynced, waitCorrection]), !viewportChanged && xyflowSynced ? /* @__PURE__ */ jsx(FitViewOnViewportResize, { xyflowApi, diagramApi }) : null;
|
|
747
|
+
const {
|
|
748
|
+
layoutId,
|
|
749
|
+
viewportNotMoved
|
|
750
|
+
} = useDiagramState(selector$3, shallowEqual), diagramApi = useDiagramStoreApi(), [currentLayoutId, setCurrent] = useState(layoutId), requiresFit = layoutId !== currentLayoutId;
|
|
751
|
+
return useDebouncedEffect(
|
|
752
|
+
() => {
|
|
753
|
+
layoutId !== currentLayoutId && (setCurrent(layoutId), diagramApi.getState().fitDiagram(450));
|
|
754
|
+
},
|
|
755
|
+
[requiresFit, diagramApi],
|
|
756
|
+
50
|
|
757
|
+
), viewportNotMoved && !requiresFit ? /* @__PURE__ */ jsx(FitViewOnViewportResize, { diagramApi }) : null;
|
|
660
758
|
}
|
|
661
759
|
function SelectEdgesOnNodeFocus() {
|
|
662
760
|
const diagramStore = useDiagramStoreApi();
|
|
@@ -705,52 +803,6 @@ function SelectEdgesOnNodeFocus() {
|
|
|
705
803
|
[diagramStore]
|
|
706
804
|
), null;
|
|
707
805
|
}
|
|
708
|
-
function SyncWithDiagram() {
|
|
709
|
-
const xyflowSynced = useDiagramState((s) => s.xyflowSynced), diagramStoreApi = useDiagramStoreApi();
|
|
710
|
-
return useEffect(() => {
|
|
711
|
-
if (xyflowSynced)
|
|
712
|
-
return;
|
|
713
|
-
const {
|
|
714
|
-
view,
|
|
715
|
-
nodesDraggable,
|
|
716
|
-
nodesSelectable,
|
|
717
|
-
focusedNodeId,
|
|
718
|
-
xystore
|
|
719
|
-
} = diagramStoreApi.getState(), updates = diagramViewToXYFlowData(view, {
|
|
720
|
-
draggable: nodesDraggable,
|
|
721
|
-
selectable: nodesSelectable || focusedNodeId !== null
|
|
722
|
-
}), {
|
|
723
|
-
nodeLookup,
|
|
724
|
-
edgeLookup,
|
|
725
|
-
setNodes,
|
|
726
|
-
setEdges
|
|
727
|
-
} = xystore.getState();
|
|
728
|
-
setNodes(updates.nodes.map((update) => {
|
|
729
|
-
var _a;
|
|
730
|
-
const existing = (_a = nodeLookup.get(update.id)) == null ? void 0 : _a.internals.userNode;
|
|
731
|
-
return existing && existing.type === update.type && deepEqual(existing.parentId, update.parentId) ? deepEqual(existing.data.element, update.data.element) ? existing : {
|
|
732
|
-
...existing,
|
|
733
|
-
...update
|
|
734
|
-
} : update;
|
|
735
|
-
})), setEdges(updates.edges.map((update) => {
|
|
736
|
-
const existing = edgeLookup.get(update.id);
|
|
737
|
-
return existing ? deepEqual(existing.data.controlPoints, update.data.controlPoints) && deepEqual(existing.markerStart, update.markerStart) && deepEqual(existing.markerEnd, update.markerEnd) && deepEqual(existing.data.edge, update.data.edge) ? existing : {
|
|
738
|
-
...omit(existing, ["data", "markerStart", "markerEnd"]),
|
|
739
|
-
...update,
|
|
740
|
-
data: {
|
|
741
|
-
...existing.data,
|
|
742
|
-
...update.data
|
|
743
|
-
}
|
|
744
|
-
} : update;
|
|
745
|
-
})), diagramStoreApi.setState(
|
|
746
|
-
{
|
|
747
|
-
xyflowSynced: !0
|
|
748
|
-
},
|
|
749
|
-
!1,
|
|
750
|
-
"xyflowSynced"
|
|
751
|
-
);
|
|
752
|
-
}, [xyflowSynced, diagramStoreApi]), null;
|
|
753
|
-
}
|
|
754
806
|
const Open = (props) => /* @__PURE__ */ jsx(
|
|
755
807
|
"marker",
|
|
756
808
|
{
|
|
@@ -954,7 +1006,7 @@ function bezierPath(bezierSpline) {
|
|
|
954
1006
|
const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
955
1007
|
const [ax, ay] = isArray(a) ? a : [a.x, a.y], [bx, by] = isArray(b) ? b : [b.x, b.y];
|
|
956
1008
|
return isSame(ax, bx) && isSame(ay, by);
|
|
957
|
-
}, sameControlPoints = (a, b) => a === b ? !0 : !a || !b || a.length !== b.length ? !1 : a.every((ap, i) => isSamePoint(ap, b[i])), isEqualProps$2 = (prev, next) => prev.id === next.id && deepEqual(prev.source, next.source) && deepEqual(prev.target, next.target) && deepEqual(prev.selected ?? !1, next.selected ?? !1) && isSame(prev.sourceX, next.sourceX) && isSame(prev.sourceY, next.sourceY) && isSame(prev.targetX, next.targetX) && isSame(prev.targetY, next.targetY) && deepEqual(prev.data.stepNum, next.data.stepNum) && sameControlPoints(prev.data.controlPoints, next.data.controlPoints) && deepEqual(prev.data.edge, next.data.edge), curve = line().curve(curveCatmullRomOpen).x((d) => d.x).y((d) => d.y), RelationshipEdge = /* @__PURE__ */ memo(function({
|
|
1009
|
+
}, sameControlPoints = (a, b) => a === b ? !0 : !a || !b || a.length !== b.length ? !1 : a.every((ap, i) => isSamePoint(ap, b[i])), isEqualProps$2 = (prev, next) => prev.id === next.id && deepEqual(prev.source, next.source) && deepEqual(prev.target, next.target) && deepEqual(prev.selected ?? !1, next.selected ?? !1) && isSame(prev.sourceX, next.sourceX) && isSame(prev.sourceY, next.sourceY) && isSame(prev.targetX, next.targetX) && isSame(prev.targetY, next.targetY) && deepEqual(prev.data.stepNum, next.data.stepNum) && deepEqual(prev.data.label, next.data.label) && sameControlPoints(prev.data.controlPoints, next.data.controlPoints) && deepEqual(prev.data.edge, next.data.edge), curve = line().curve(curveCatmullRomOpen).x((d) => d.x).y((d) => d.y), RelationshipEdge = /* @__PURE__ */ memo(function({
|
|
958
1010
|
id,
|
|
959
1011
|
data,
|
|
960
1012
|
selected,
|
|
@@ -967,18 +1019,18 @@ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
|
967
1019
|
target,
|
|
968
1020
|
interactionWidth
|
|
969
1021
|
}) {
|
|
970
|
-
const [isControlPointDragging, setIsControlPointDragging] = useState(!1), diagramStore = useDiagramStoreApi(), xyflowStore = useXYStoreApi(), { isActive,
|
|
971
|
-
isEditable: s.readonly !== !0,
|
|
1022
|
+
const [isControlPointDragging, setIsControlPointDragging] = useState(!1), diagramStore = useDiagramStoreApi(), xyflowStore = useXYStoreApi(), { isActive, isEdgePathEditable, isHovered, isDimmed } = useDiagramState((s) => ({
|
|
972
1023
|
isEdgePathEditable: s.readonly !== !0 && s.experimentalEdgeEditing === !0,
|
|
973
1024
|
isActive: s.focusedNodeId === source || s.focusedNodeId === target || s.activeDynamicViewStep !== null && s.activeDynamicViewStep === data.stepNum,
|
|
974
1025
|
isHovered: s.hoveredEdgeId === id,
|
|
975
1026
|
isDimmed: s.dimmed.has(id)
|
|
976
|
-
})), { nodeLookup, edgeLookup } = xyflowStore.getState(), sourceNode = nonNullable(nodeLookup.get(source), `source node ${source} not found`), targetNode = nonNullable(nodeLookup.get(target), `target node ${target} not found`), isModified =
|
|
1027
|
+
})), { nodeLookup, edgeLookup } = xyflowStore.getState(), sourceNode = nonNullable(nodeLookup.get(source), `source node ${source} not found`), targetNode = nonNullable(nodeLookup.get(target), `target node ${target} not found`), isModified = isTruthy(data.controlPoints) || !isSamePoint(sourceNode.internals.positionAbsolute, sourceNode.data.element.position) || !isSamePoint(targetNode.internals.positionAbsolute, targetNode.data.element.position), {
|
|
977
1028
|
label,
|
|
978
1029
|
edge: {
|
|
979
1030
|
points: diagramEdgePoints,
|
|
980
1031
|
line: line2 = "dashed",
|
|
981
1032
|
color = "gray",
|
|
1033
|
+
labelBBox,
|
|
982
1034
|
...diagramEdge
|
|
983
1035
|
}
|
|
984
1036
|
} = data;
|
|
@@ -986,10 +1038,10 @@ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
|
986
1038
|
const isStepEdge = data.stepNum !== null, isDotted = line2 === "dotted", isDashed = isDotted || line2 === "dashed";
|
|
987
1039
|
let strokeDasharray;
|
|
988
1040
|
isDotted ? strokeDasharray = "1,8" : isDashed && (strokeDasharray = "8,10");
|
|
989
|
-
let labelX = (
|
|
1041
|
+
let labelX = (labelBBox == null ? void 0 : labelBBox.x) ?? 0, labelY = (labelBBox == null ? void 0 : labelBBox.y) ?? 0;
|
|
990
1042
|
const [labelPos, setLabelPosition] = useState({
|
|
991
|
-
x: labelX,
|
|
992
|
-
y: labelY
|
|
1043
|
+
x: (label == null ? void 0 : label.bbox.x) ?? labelX,
|
|
1044
|
+
y: (label == null ? void 0 : label.bbox.y) ?? labelY
|
|
993
1045
|
});
|
|
994
1046
|
let edgePath;
|
|
995
1047
|
if (isModified) {
|
|
@@ -1011,7 +1063,7 @@ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
|
1011
1063
|
} else
|
|
1012
1064
|
edgePath = bezierPath(diagramEdgePoints);
|
|
1013
1065
|
const svgPathRef = useRef(null);
|
|
1014
|
-
|
|
1066
|
+
useEffect(() => {
|
|
1015
1067
|
const path = svgPathRef.current;
|
|
1016
1068
|
if (!path) return;
|
|
1017
1069
|
const dompoint = path.getPointAtLength(path.getTotalLength() * 0.5), point = {
|
|
@@ -1019,7 +1071,22 @@ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
|
1019
1071
|
y: Math.round(dompoint.y)
|
|
1020
1072
|
};
|
|
1021
1073
|
setLabelPosition((current) => isSamePoint(current, point) ? current : point);
|
|
1022
|
-
}, [edgePath])
|
|
1074
|
+
}, [edgePath]), useDebouncedEffect(
|
|
1075
|
+
() => {
|
|
1076
|
+
!label || label.bbox.x === labelPos.x && label.bbox.y === labelPos.y || diagramStore.getState().xyflow.updateEdgeData(id, {
|
|
1077
|
+
label: {
|
|
1078
|
+
...label,
|
|
1079
|
+
bbox: {
|
|
1080
|
+
...label.bbox,
|
|
1081
|
+
...labelPos
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
});
|
|
1085
|
+
},
|
|
1086
|
+
[labelPos],
|
|
1087
|
+
100,
|
|
1088
|
+
300
|
|
1089
|
+
);
|
|
1023
1090
|
const onControlPointerDown = (index, e) => {
|
|
1024
1091
|
const { domNode } = xyflowStore.getState();
|
|
1025
1092
|
if (!domNode || e.pointerType !== "mouse")
|
|
@@ -1034,11 +1101,12 @@ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
|
1034
1101
|
}
|
|
1035
1102
|
if (e.button !== 0)
|
|
1036
1103
|
return;
|
|
1104
|
+
const wasCanceled = diagramStore.getState().cancelSaveManualLayout();
|
|
1037
1105
|
e.stopPropagation();
|
|
1038
1106
|
let hasMoved = !1, pointer = { x: e.clientX, y: e.clientY };
|
|
1039
1107
|
const onPointerMove = (e2) => {
|
|
1040
1108
|
if (!isSamePoint(pointer, [e2.clientX, e2.clientY])) {
|
|
1041
|
-
setIsControlPointDragging(!0), hasMoved
|
|
1109
|
+
setIsControlPointDragging(!0), hasMoved = !0, pointer = { x: e2.clientX, y: e2.clientY };
|
|
1042
1110
|
const { x, y } = xyflow.screenToFlowPosition(pointer, { snapToGrid: !1 }), newControlPoints = controlPoints.slice();
|
|
1043
1111
|
newControlPoints[index] = {
|
|
1044
1112
|
x: Math.round(x),
|
|
@@ -1046,21 +1114,21 @@ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
|
1046
1114
|
}, xyflow.updateEdgeData(id, { controlPoints: newControlPoints });
|
|
1047
1115
|
}
|
|
1048
1116
|
}, onPointerUp = () => {
|
|
1049
|
-
|
|
1117
|
+
domNode.removeEventListener("pointermove", onPointerMove), domNode.removeEventListener("pointerup", onPointerUp), (hasMoved || wasCanceled) && diagramStore.getState().scheduleSaveManualLayout(), setIsControlPointDragging(!1);
|
|
1050
1118
|
};
|
|
1051
1119
|
domNode.addEventListener("pointermove", onPointerMove), domNode.addEventListener("pointerup", onPointerUp, { once: !0 });
|
|
1052
1120
|
};
|
|
1053
1121
|
let markerStartName = toMarker(diagramEdge.tail), markerEndName = toMarker(diagramEdge.head ?? "normal");
|
|
1054
1122
|
diagramEdge.dir === "back" && ([markerStartName, markerEndName] = [markerEndName, markerStartName]);
|
|
1055
|
-
const MarkerStart = markerStartName ? EdgeMarkers[markerStartName] : null, MarkerEnd = markerEndName ? EdgeMarkers[markerEndName] : null;
|
|
1123
|
+
const MarkerStart = markerStartName ? EdgeMarkers[markerStartName] : null, MarkerEnd = markerEndName ? EdgeMarkers[markerEndName] : null, labelZIndex = 1 + (isHovered ? ZIndexes.Element : edgeLookup.get(id).zIndex ?? ZIndexes.Edge);
|
|
1056
1124
|
return /* @__PURE__ */ jsxs(
|
|
1057
1125
|
"g",
|
|
1058
1126
|
{
|
|
1059
|
-
className: clsx(
|
|
1127
|
+
className: clsx(
|
|
1060
1128
|
container$4,
|
|
1061
1129
|
isDimmed && dimmed$2,
|
|
1062
1130
|
isControlPointDragging && controlDragging
|
|
1063
|
-
|
|
1131
|
+
),
|
|
1064
1132
|
"data-likec4-color": color,
|
|
1065
1133
|
"data-edge-dir": diagramEdge.dir,
|
|
1066
1134
|
"data-edge-active": isActive,
|
|
@@ -1135,7 +1203,7 @@ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
|
1135
1203
|
selected: selected ?? !1,
|
|
1136
1204
|
stepNum: data.stepNum,
|
|
1137
1205
|
label: data.label,
|
|
1138
|
-
zIndex:
|
|
1206
|
+
zIndex: labelZIndex,
|
|
1139
1207
|
isHovered,
|
|
1140
1208
|
isActive,
|
|
1141
1209
|
isStepEdge
|
|
@@ -1240,22 +1308,22 @@ class Compound extends Rect {
|
|
|
1240
1308
|
rect.minX,
|
|
1241
1309
|
[-1, this.minX]
|
|
1242
1310
|
), { weak } = Strength;
|
|
1243
|
-
this.solver.createConstraint(leftPadding, Operator.Ge, 40), this.solver.createConstraint(leftPadding, Operator.Eq,
|
|
1311
|
+
this.solver.createConstraint(leftPadding, Operator.Ge, 40), this.solver.createConstraint(leftPadding, Operator.Eq, 41, weak);
|
|
1244
1312
|
const topPadding = new Expression(
|
|
1245
1313
|
rect.minY,
|
|
1246
1314
|
[-1, this.minY]
|
|
1247
1315
|
);
|
|
1248
|
-
this.solver.createConstraint(topPadding, Operator.Ge,
|
|
1316
|
+
this.solver.createConstraint(topPadding, Operator.Ge, 54), this.solver.createConstraint(topPadding, Operator.Eq, 55, weak);
|
|
1249
1317
|
const rightPadding = new Expression(
|
|
1250
1318
|
this.maxX,
|
|
1251
1319
|
[-1, rect.maxX]
|
|
1252
1320
|
);
|
|
1253
|
-
this.solver.createConstraint(rightPadding, Operator.Ge, 40), this.solver.createConstraint(rightPadding, Operator.Eq,
|
|
1321
|
+
this.solver.createConstraint(rightPadding, Operator.Ge, 40), this.solver.createConstraint(rightPadding, Operator.Eq, 41, weak);
|
|
1254
1322
|
const bottomPadding = new Expression(
|
|
1255
1323
|
this.maxY,
|
|
1256
1324
|
[-1, rect.maxY]
|
|
1257
1325
|
);
|
|
1258
|
-
this.solver.createConstraint(bottomPadding, Operator.Ge, 40), this.solver.createConstraint(bottomPadding, Operator.Eq,
|
|
1326
|
+
this.solver.createConstraint(bottomPadding, Operator.Ge, 40), this.solver.createConstraint(bottomPadding, Operator.Eq, 41, weak);
|
|
1259
1327
|
}
|
|
1260
1328
|
}
|
|
1261
1329
|
class Leaf extends Rect {
|
|
@@ -1272,7 +1340,7 @@ class Leaf extends Rect {
|
|
|
1272
1340
|
parent && parent.addChild(this);
|
|
1273
1341
|
}
|
|
1274
1342
|
}
|
|
1275
|
-
function createLayoutConstraints(
|
|
1343
|
+
function createLayoutConstraints(xyflowApi, draggingNodeId) {
|
|
1276
1344
|
var _a;
|
|
1277
1345
|
const { parentLookup, nodeLookup } = xyflowApi.getState(), solver = new Solver(), rects = /* @__PURE__ */ new Map(), traverse = new Array();
|
|
1278
1346
|
for (const [, xynode] of nodeLookup)
|
|
@@ -1290,36 +1358,30 @@ function createLayoutConstraints(xyflow, xyflowApi, draggingNodeId) {
|
|
|
1290
1358
|
}));
|
|
1291
1359
|
}
|
|
1292
1360
|
solver.updateVariables(), solver.maxIterations = 1e3;
|
|
1361
|
+
const rectsToUpdate = [...rects.values()].filter((r) => r.id !== draggingNodeId);
|
|
1293
1362
|
function updateXYFlowNodes() {
|
|
1294
|
-
solver.updateVariables(),
|
|
1295
|
-
(
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
measured: dimensions
|
|
1308
|
-
} : dimensions.width !== n.width || dimensions.height !== n.height ? {
|
|
1309
|
-
...n,
|
|
1310
|
-
width: dimensions.width,
|
|
1311
|
-
height: dimensions.height,
|
|
1312
|
-
measured: dimensions
|
|
1313
|
-
} : n;
|
|
1314
|
-
})
|
|
1363
|
+
solver.updateVariables(), xyflowApi.getState().triggerNodeChanges(
|
|
1364
|
+
rectsToUpdate.reduce((acc, r) => (acc.push({
|
|
1365
|
+
id: r.id,
|
|
1366
|
+
type: "position",
|
|
1367
|
+
dragging: !1,
|
|
1368
|
+
position: r.position,
|
|
1369
|
+
positionAbsolute: r.positionAbsolute
|
|
1370
|
+
}), r instanceof Compound && acc.push({
|
|
1371
|
+
id: r.id,
|
|
1372
|
+
type: "dimensions",
|
|
1373
|
+
setAttributes: !0,
|
|
1374
|
+
dimensions: r.dimensions
|
|
1375
|
+
}), acc), [])
|
|
1315
1376
|
);
|
|
1316
1377
|
}
|
|
1317
1378
|
let animationFrameId = null;
|
|
1318
1379
|
function onNodeDrag(xynode) {
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1380
|
+
rectsToUpdate.length !== 0 && (animationFrameId ?? (animationFrameId = requestAnimationFrame(() => {
|
|
1381
|
+
animationFrameId = null;
|
|
1382
|
+
const pos = nodeLookup.get(xynode.id).internals.positionAbsolute, rect = nonNullable(rects.get(xynode.id));
|
|
1383
|
+
solver.suggestValue(rect.minX, Math.ceil(pos.x)), solver.suggestValue(rect.minY, Math.ceil(pos.y)), updateXYFlowNodes();
|
|
1384
|
+
})));
|
|
1323
1385
|
}
|
|
1324
1386
|
return {
|
|
1325
1387
|
onNodeDrag,
|
|
@@ -1327,27 +1389,20 @@ function createLayoutConstraints(xyflow, xyflowApi, draggingNodeId) {
|
|
|
1327
1389
|
};
|
|
1328
1390
|
}
|
|
1329
1391
|
function useLayoutConstraints() {
|
|
1330
|
-
const diagramApi = useDiagramStoreApi(),
|
|
1331
|
-
x: 0,
|
|
1332
|
-
y: 0
|
|
1333
|
-
});
|
|
1392
|
+
const diagramApi = useDiagramStoreApi(), solverRef = useRef();
|
|
1334
1393
|
return useMemo(() => ({
|
|
1335
|
-
onNodeDragStart: (
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
y: event.clientY
|
|
1339
|
-
};
|
|
1340
|
-
const { xyflow, cancelSaveManualLayout } = diagramApi.getState();
|
|
1341
|
-
cancelSaveManualLayout(), solverRef.current = createLayoutConstraints(xyflow, xyflowApi, xynode.id);
|
|
1394
|
+
onNodeDragStart: (_event, xynode) => {
|
|
1395
|
+
const { cancelSaveManualLayout, xystore } = diagramApi.getState();
|
|
1396
|
+
cancelSaveManualLayout(), solverRef.current = createLayoutConstraints(xystore, xynode.id);
|
|
1342
1397
|
},
|
|
1343
1398
|
onNodeDrag: (_event, xynode) => {
|
|
1344
1399
|
var _a;
|
|
1345
1400
|
invariant(solverRef.current, "solverRef.current should be defined"), (_a = solverRef.current) == null || _a.onNodeDrag(xynode);
|
|
1346
1401
|
},
|
|
1347
|
-
onNodeDragStop: (
|
|
1348
|
-
|
|
1402
|
+
onNodeDragStop: (_event, _xynode) => {
|
|
1403
|
+
diagramApi.getState().scheduleSaveManualLayout(), solverRef.current = void 0;
|
|
1349
1404
|
}
|
|
1350
|
-
}), [
|
|
1405
|
+
}), [diagramApi]);
|
|
1351
1406
|
}
|
|
1352
1407
|
function NavigateToBtn({ xynodeId, className }) {
|
|
1353
1408
|
const diagramApi = useDiagramStoreApi();
|
|
@@ -1931,18 +1986,17 @@ function useXYFlowEvents() {
|
|
|
1931
1986
|
},
|
|
1932
1987
|
onNodeClick: (event, xynode) => {
|
|
1933
1988
|
const {
|
|
1934
|
-
zoomable,
|
|
1935
|
-
fitViewEnabled,
|
|
1936
1989
|
focusedNodeId,
|
|
1937
1990
|
fitDiagram,
|
|
1938
1991
|
focusOnNode,
|
|
1939
1992
|
onNodeClick,
|
|
1993
|
+
enableFocusMode,
|
|
1940
1994
|
lastClickedNodeId,
|
|
1941
1995
|
setLastClickedNode
|
|
1942
1996
|
} = diagramApi.getState();
|
|
1943
1997
|
setLastClickedNode(xynode.id);
|
|
1944
|
-
const
|
|
1945
|
-
if (
|
|
1998
|
+
const shallChangeFocus = !!focusedNodeId && focusedNodeId !== xynode.id, clickedRecently = lastClickedNodeId === xynode.id && lastClickWasRecent();
|
|
1999
|
+
if (enableFocusMode) {
|
|
1946
2000
|
let stopPropagation = !1;
|
|
1947
2001
|
switch (!0) {
|
|
1948
2002
|
case (!focusedNodeId && clickedRecently):
|
|
@@ -1964,27 +2018,60 @@ function useXYFlowEvents() {
|
|
|
1964
2018
|
onNodeDoubleClick: (event, xynode) => {
|
|
1965
2019
|
const {
|
|
1966
2020
|
focusedNodeId,
|
|
1967
|
-
|
|
1968
|
-
fitViewEnabled,
|
|
2021
|
+
enableFocusMode,
|
|
1969
2022
|
fitDiagram,
|
|
1970
2023
|
focusOnNode,
|
|
1971
2024
|
setLastClickedNode
|
|
1972
2025
|
} = diagramApi.getState();
|
|
1973
|
-
setLastClickedNode(xynode.id), lastClickTimestamp.current = Date.now(), (focusedNodeId ||
|
|
2026
|
+
setLastClickedNode(xynode.id), lastClickTimestamp.current = Date.now(), (isNonNullish(focusedNodeId) || enableFocusMode) && (focusedNodeId === xynode.id ? fitDiagram() : focusOnNode(xynode.id), event.stopPropagation());
|
|
1974
2027
|
},
|
|
1975
2028
|
onEdgeClick: (event, xyedge) => {
|
|
1976
|
-
diagramApi.getState().setLastClickedEdge(xyedge.id);
|
|
1977
2029
|
const {
|
|
2030
|
+
lastClickedEdgeId,
|
|
2031
|
+
isDynamicView,
|
|
2032
|
+
enableDynamicViewWalkthrough,
|
|
2033
|
+
activateDynamicStep,
|
|
2034
|
+
activeDynamicViewStep,
|
|
1978
2035
|
focusedNodeId,
|
|
1979
2036
|
focusOnNode,
|
|
1980
|
-
onEdgeClick
|
|
2037
|
+
onEdgeClick,
|
|
2038
|
+
setLastClickedEdge
|
|
1981
2039
|
} = diagramApi.getState();
|
|
1982
|
-
|
|
2040
|
+
lastClickedEdgeId !== xyedge.id && setLastClickedEdge(xyedge.id);
|
|
2041
|
+
const isNotAFirstClick = lastClickedEdgeId === xyedge.id, isEdgeOfFocusedNode = isTruthy(focusedNodeId) && (focusedNodeId === xyedge.source || focusedNodeId === xyedge.target);
|
|
2042
|
+
if (isDynamicView && enableDynamicViewWalkthrough && (isEdgeOfFocusedNode || isNotAFirstClick || isNonNullish(activeDynamicViewStep))) {
|
|
2043
|
+
const nextStep = extractStep(xyedge.data.edge.id);
|
|
2044
|
+
if (activeDynamicViewStep !== nextStep) {
|
|
2045
|
+
activateDynamicStep(nextStep), event.stopPropagation();
|
|
2046
|
+
return;
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
isEdgeOfFocusedNode && (focusOnNode(focusedNodeId === xyedge.source ? xyedge.target : xyedge.source), onEdgeClick || event.stopPropagation()), onEdgeClick == null || onEdgeClick({
|
|
1983
2050
|
edge: xyedge.data.edge,
|
|
1984
2051
|
xyedge,
|
|
1985
2052
|
event
|
|
1986
2053
|
});
|
|
1987
2054
|
},
|
|
2055
|
+
onEdgeDoubleClick: (event, xyedge) => {
|
|
2056
|
+
diagramApi.getState().setLastClickedEdge(xyedge.id);
|
|
2057
|
+
const {
|
|
2058
|
+
enableFocusMode,
|
|
2059
|
+
isDynamicView,
|
|
2060
|
+
enableDynamicViewWalkthrough,
|
|
2061
|
+
focusOnNode,
|
|
2062
|
+
activateDynamicStep,
|
|
2063
|
+
activeDynamicViewStep
|
|
2064
|
+
} = diagramApi.getState();
|
|
2065
|
+
if (isDynamicView && enableDynamicViewWalkthrough) {
|
|
2066
|
+
const nextStep = extractStep(xyedge.data.edge.id);
|
|
2067
|
+
activeDynamicViewStep !== nextStep && (activateDynamicStep(extractStep(xyedge.data.edge.id)), event.stopPropagation());
|
|
2068
|
+
return;
|
|
2069
|
+
}
|
|
2070
|
+
if (enableFocusMode) {
|
|
2071
|
+
focusOnNode(xyedge.source), event.stopPropagation();
|
|
2072
|
+
return;
|
|
2073
|
+
}
|
|
2074
|
+
},
|
|
1988
2075
|
onMoveEnd: (event, _viewport) => {
|
|
1989
2076
|
const viewportChanged = !!event;
|
|
1990
2077
|
viewportChanged !== diagramApi.getState().viewportChanged && diagramApi.setState({ viewportChanged }, !1, `viewport-changed: ${viewportChanged}`);
|
|
@@ -2016,15 +2103,15 @@ const nodeTypes = {
|
|
|
2016
2103
|
}, edgeTypes = {
|
|
2017
2104
|
relationship: RelationshipEdge
|
|
2018
2105
|
}, selector$1 = (s) => ({
|
|
2106
|
+
nodes: s.xynodes,
|
|
2107
|
+
edges: s.xyedges,
|
|
2108
|
+
onInit: s.onInit,
|
|
2109
|
+
onNodesChange: s.onNodesChange,
|
|
2110
|
+
onEdgesChange: s.onEdgesChange,
|
|
2019
2111
|
nodesSelectable: s.nodesSelectable || s.focusedNodeId !== null,
|
|
2020
2112
|
nodesDraggable: s.nodesDraggable,
|
|
2021
2113
|
fitView: s.fitViewEnabled,
|
|
2022
|
-
|
|
2023
|
-
minZoom: MinZoom,
|
|
2024
|
-
maxZoom: 1,
|
|
2025
|
-
padding: s.fitViewPadding,
|
|
2026
|
-
includeHiddenNodes: !0
|
|
2027
|
-
},
|
|
2114
|
+
fitViewPadding: s.fitViewPadding,
|
|
2028
2115
|
hasOnNavigateTo: !!s.onNavigateTo,
|
|
2029
2116
|
hasOnNodeClick: !!s.onNodeClick,
|
|
2030
2117
|
hasOnNodeContextMenu: !!s.onNodeContextMenu,
|
|
@@ -2032,21 +2119,28 @@ const nodeTypes = {
|
|
|
2032
2119
|
hasOnEdgeContextMenu: !!s.onEdgeContextMenu,
|
|
2033
2120
|
hasOnEdgeClick: !!s.onEdgeClick,
|
|
2034
2121
|
zoomable: s.zoomable,
|
|
2035
|
-
pannable: s.pannable
|
|
2122
|
+
pannable: s.pannable,
|
|
2123
|
+
// If fitView is not enabled
|
|
2124
|
+
// And diagram starts with a negative x or y - we need to translate viewprot
|
|
2125
|
+
translateX: s.fitViewEnabled ? 0 : -Math.min(s.view.bounds.x, 0),
|
|
2126
|
+
translateY: s.fitViewEnabled ? 0 : -Math.min(s.view.bounds.y, 0)
|
|
2036
2127
|
});
|
|
2037
2128
|
function XYFlow({
|
|
2038
2129
|
colorMode = "system",
|
|
2039
2130
|
className,
|
|
2040
2131
|
children,
|
|
2041
|
-
defaultNodes,
|
|
2042
|
-
defaultEdges,
|
|
2043
2132
|
style
|
|
2044
2133
|
}) {
|
|
2045
|
-
const xyflowApi = useXYStoreApi(),
|
|
2134
|
+
const xyflowApi = useXYStoreApi(), {
|
|
2135
|
+
nodes,
|
|
2136
|
+
edges,
|
|
2137
|
+
onInit,
|
|
2138
|
+
onNodesChange,
|
|
2139
|
+
onEdgesChange,
|
|
2046
2140
|
nodesSelectable,
|
|
2047
2141
|
nodesDraggable,
|
|
2048
2142
|
fitView,
|
|
2049
|
-
|
|
2143
|
+
fitViewPadding,
|
|
2050
2144
|
pannable,
|
|
2051
2145
|
zoomable,
|
|
2052
2146
|
hasOnNodeClick,
|
|
@@ -2054,15 +2148,13 @@ function XYFlow({
|
|
|
2054
2148
|
hasOnNodeContextMenu,
|
|
2055
2149
|
hasOnCanvasContextMenu,
|
|
2056
2150
|
hasOnEdgeContextMenu,
|
|
2057
|
-
|
|
2058
|
-
|
|
2151
|
+
translateX,
|
|
2152
|
+
translateY
|
|
2153
|
+
} = useDiagramState(selector$1, shallowEqual), layoutConstraints = useLayoutConstraints(), handlers = useXYFlowEvents();
|
|
2059
2154
|
return useOnViewportChange({
|
|
2060
2155
|
onEnd: ({ x, y, zoom }) => {
|
|
2061
|
-
const
|
|
2062
|
-
|
|
2063
|
-
y: Math.round(y)
|
|
2064
|
-
};
|
|
2065
|
-
(x !== rounded.x || y !== rounded.y) && xyflowApi.setState({ transform: [rounded.x, rounded.y, zoom] });
|
|
2156
|
+
const roundedX = Math.round(x), roundedY = Math.round(y);
|
|
2157
|
+
(x !== roundedX || y !== roundedY) && xyflowApi.setState({ transform: [roundedX, roundedY, zoom] });
|
|
2066
2158
|
}
|
|
2067
2159
|
}), /* @__PURE__ */ jsx(
|
|
2068
2160
|
ReactFlow,
|
|
@@ -2070,8 +2162,8 @@ function XYFlow({
|
|
|
2070
2162
|
className,
|
|
2071
2163
|
style,
|
|
2072
2164
|
...colorMode && { colorMode },
|
|
2073
|
-
|
|
2074
|
-
|
|
2165
|
+
nodes,
|
|
2166
|
+
edges,
|
|
2075
2167
|
nodeTypes,
|
|
2076
2168
|
edgeTypes,
|
|
2077
2169
|
zoomOnPinch: zoomable,
|
|
@@ -2082,26 +2174,43 @@ function XYFlow({
|
|
|
2082
2174
|
maxZoom: zoomable ? 1.9 : 1,
|
|
2083
2175
|
minZoom: zoomable ? MinZoom : 1,
|
|
2084
2176
|
fitView,
|
|
2085
|
-
fitViewOptions
|
|
2177
|
+
fitViewOptions: useMemo(() => ({
|
|
2178
|
+
minZoom: MinZoom,
|
|
2179
|
+
maxZoom: 1,
|
|
2180
|
+
padding: fitViewPadding,
|
|
2181
|
+
includeHiddenNodes: !0
|
|
2182
|
+
}), [fitViewPadding]),
|
|
2183
|
+
...!fitView && {
|
|
2184
|
+
viewport: {
|
|
2185
|
+
x: translateX,
|
|
2186
|
+
y: translateY,
|
|
2187
|
+
zoom: 1
|
|
2188
|
+
}
|
|
2189
|
+
},
|
|
2086
2190
|
preventScrolling: zoomable || pannable,
|
|
2087
2191
|
defaultMarkerColor: "var(--xy-edge-stroke)",
|
|
2088
2192
|
noDragClassName: "nodrag",
|
|
2089
2193
|
noPanClassName: "nopan",
|
|
2090
2194
|
panOnScroll: pannable,
|
|
2091
2195
|
panOnDrag: pannable,
|
|
2196
|
+
...!pannable && {
|
|
2197
|
+
selectionKeyCode: null
|
|
2198
|
+
},
|
|
2092
2199
|
elementsSelectable: nodesSelectable,
|
|
2093
2200
|
nodesFocusable: nodesDraggable || nodesSelectable || hasOnNodeClick || hasOnNavigateTo,
|
|
2094
|
-
edgesFocusable:
|
|
2201
|
+
edgesFocusable: !1,
|
|
2095
2202
|
nodesDraggable,
|
|
2096
2203
|
...nodesDraggable && {
|
|
2097
2204
|
onNodeDragStart: layoutConstraints.onNodeDragStart,
|
|
2098
2205
|
onNodeDrag: layoutConstraints.onNodeDrag,
|
|
2099
2206
|
onNodeDragStop: layoutConstraints.onNodeDragStop
|
|
2100
2207
|
},
|
|
2208
|
+
nodeDragThreshold: 3,
|
|
2101
2209
|
zoomOnDoubleClick: !1,
|
|
2102
2210
|
elevateNodesOnSelect: !1,
|
|
2103
2211
|
selectNodesOnDrag: !1,
|
|
2104
|
-
|
|
2212
|
+
onNodesChange,
|
|
2213
|
+
onEdgesChange,
|
|
2105
2214
|
onDoubleClick: handlers.onDoubleClick,
|
|
2106
2215
|
onPaneClick: handlers.onPaneClick,
|
|
2107
2216
|
onMoveEnd: handlers.onMoveEnd,
|
|
@@ -2112,9 +2221,8 @@ function XYFlow({
|
|
|
2112
2221
|
onNodeClick: handlers.onNodeClick,
|
|
2113
2222
|
onNodeDoubleClick: handlers.onNodeDoubleClick,
|
|
2114
2223
|
onEdgeClick: handlers.onEdgeClick,
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
}, [diagramApi]),
|
|
2224
|
+
onEdgeDoubleClick: handlers.onEdgeDoubleClick,
|
|
2225
|
+
onInit,
|
|
2118
2226
|
...hasOnNodeContextMenu && {
|
|
2119
2227
|
onNodeContextMenu: handlers.onNodeContextMenu
|
|
2120
2228
|
},
|
|
@@ -2129,8 +2237,19 @@ function XYFlow({
|
|
|
2129
2237
|
);
|
|
2130
2238
|
}
|
|
2131
2239
|
var panel$1 = "_19mimxc0";
|
|
2240
|
+
const historySelector = (s) => ({
|
|
2241
|
+
hasStepBack: s.navigationHistoryIndex > 0,
|
|
2242
|
+
hasStepForward: s.navigationHistoryIndex < s.navigationHistory.length - 1,
|
|
2243
|
+
goBack: s.goBack,
|
|
2244
|
+
goForward: s.goForward
|
|
2245
|
+
});
|
|
2132
2246
|
function BackwardForwardPanel() {
|
|
2133
|
-
const {
|
|
2247
|
+
const {
|
|
2248
|
+
hasStepBack,
|
|
2249
|
+
hasStepForward,
|
|
2250
|
+
goBack,
|
|
2251
|
+
goForward
|
|
2252
|
+
} = useDiagramState(historySelector);
|
|
2134
2253
|
return /* @__PURE__ */ jsx(
|
|
2135
2254
|
Group,
|
|
2136
2255
|
{
|
|
@@ -2141,7 +2260,7 @@ function BackwardForwardPanel() {
|
|
|
2141
2260
|
),
|
|
2142
2261
|
gap: "xs",
|
|
2143
2262
|
children: /* @__PURE__ */ jsxs(AnimatePresence, { children: [
|
|
2144
|
-
|
|
2263
|
+
hasStepBack && /* @__PURE__ */ jsx(
|
|
2145
2264
|
m.div,
|
|
2146
2265
|
{
|
|
2147
2266
|
layout: !0,
|
|
@@ -2156,14 +2275,16 @@ function BackwardForwardPanel() {
|
|
|
2156
2275
|
{
|
|
2157
2276
|
variant: "light",
|
|
2158
2277
|
color: "gray",
|
|
2159
|
-
onClick: () =>
|
|
2278
|
+
onClick: (e) => {
|
|
2279
|
+
e.stopPropagation(), goBack();
|
|
2280
|
+
},
|
|
2160
2281
|
children: /* @__PURE__ */ jsx(IconChevronLeft, {})
|
|
2161
2282
|
}
|
|
2162
2283
|
)
|
|
2163
2284
|
},
|
|
2164
2285
|
"back"
|
|
2165
2286
|
),
|
|
2166
|
-
|
|
2287
|
+
hasStepForward && /* @__PURE__ */ jsx(
|
|
2167
2288
|
m.div,
|
|
2168
2289
|
{
|
|
2169
2290
|
layout: !0,
|
|
@@ -2178,7 +2299,9 @@ function BackwardForwardPanel() {
|
|
|
2178
2299
|
{
|
|
2179
2300
|
variant: "light",
|
|
2180
2301
|
color: "gray",
|
|
2181
|
-
onClick: () =>
|
|
2302
|
+
onClick: (e) => {
|
|
2303
|
+
e.stopPropagation(), goForward();
|
|
2304
|
+
},
|
|
2182
2305
|
children: /* @__PURE__ */ jsx(IconChevronRight, {})
|
|
2183
2306
|
}
|
|
2184
2307
|
)
|
|
@@ -2723,23 +2846,24 @@ const XYFlowInner = memo(function({
|
|
|
2723
2846
|
background,
|
|
2724
2847
|
controls,
|
|
2725
2848
|
showDiagramTitle,
|
|
2726
|
-
showNavigationButtons
|
|
2727
|
-
enableDynamicViewWalkthrough
|
|
2849
|
+
showNavigationButtons
|
|
2728
2850
|
}) {
|
|
2729
2851
|
const {
|
|
2730
2852
|
isDynamicView,
|
|
2731
2853
|
isDynamicViewActive,
|
|
2732
|
-
readonly
|
|
2854
|
+
readonly,
|
|
2855
|
+
enableDynamicViewWalkthrough
|
|
2733
2856
|
} = useDiagramState((s) => ({
|
|
2734
|
-
isDynamicView: s.isDynamicView
|
|
2857
|
+
isDynamicView: s.isDynamicView,
|
|
2735
2858
|
readonly: s.readonly,
|
|
2736
|
-
|
|
2859
|
+
enableDynamicViewWalkthrough: s.enableDynamicViewWalkthrough,
|
|
2860
|
+
isDynamicViewActive: isNonNullish(s.activeDynamicViewStep)
|
|
2737
2861
|
}));
|
|
2738
2862
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2739
2863
|
background !== "transparent" && background !== "solid" && /* @__PURE__ */ jsx(XYFlowBackground, { background }),
|
|
2740
2864
|
controls && /* @__PURE__ */ jsx(Controls, { position: "bottom-right" }),
|
|
2741
2865
|
readonly === !1 && /* @__PURE__ */ jsx(OptionsPanel, {}),
|
|
2742
|
-
|
|
2866
|
+
showDiagramTitle === !0 && !isDynamicViewActive && /* @__PURE__ */ jsx(DiagramTitlePanel, {}),
|
|
2743
2867
|
isDynamicView && enableDynamicViewWalkthrough && /* @__PURE__ */ jsx(DynamicViewWalkthrough, {}),
|
|
2744
2868
|
showNavigationButtons && /* @__PURE__ */ jsx(BackwardForwardPanel, {}),
|
|
2745
2869
|
children
|
|
@@ -2761,7 +2885,8 @@ function LikeC4Diagram({
|
|
|
2761
2885
|
showElementLinks = !0,
|
|
2762
2886
|
showDiagramTitle = !0,
|
|
2763
2887
|
showNavigationButtons = !1,
|
|
2764
|
-
enableDynamicViewWalkthrough = !
|
|
2888
|
+
enableDynamicViewWalkthrough = !1,
|
|
2889
|
+
enableFocusMode = readonly,
|
|
2765
2890
|
initialWidth,
|
|
2766
2891
|
initialHeight,
|
|
2767
2892
|
keepAspectRatio = !1,
|
|
@@ -2775,22 +2900,16 @@ function LikeC4Diagram({
|
|
|
2775
2900
|
onNavigateTo,
|
|
2776
2901
|
onNodeClick,
|
|
2777
2902
|
onNodeContextMenu,
|
|
2903
|
+
onEditorCommand,
|
|
2778
2904
|
renderIcon
|
|
2779
2905
|
}) {
|
|
2780
|
-
const initialRef = useRef(
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
defaultNodes: initial.nodes,
|
|
2788
|
-
defaultEdges: initial.edges,
|
|
2789
|
-
initialWidth: initialWidth ?? view.width,
|
|
2790
|
-
initialHeight: initialHeight ?? view.height
|
|
2791
|
-
};
|
|
2792
|
-
}
|
|
2793
|
-
return /* @__PURE__ */ jsx(EnsureMantine, { children: /* @__PURE__ */ jsx(
|
|
2906
|
+
const initialRef = useRef({
|
|
2907
|
+
defaultNodes: [],
|
|
2908
|
+
defaultEdges: [],
|
|
2909
|
+
initialWidth: initialWidth ?? view.bounds.width,
|
|
2910
|
+
initialHeight: initialHeight ?? view.bounds.height
|
|
2911
|
+
});
|
|
2912
|
+
return /* @__PURE__ */ jsx(EnsureMantine, { children: /* @__PURE__ */ jsx(LazyMotion, { features: domAnimation, strict: !0, children: /* @__PURE__ */ jsx(
|
|
2794
2913
|
ReactFlowProvider,
|
|
2795
2914
|
{
|
|
2796
2915
|
fitView,
|
|
@@ -2810,64 +2929,55 @@ function LikeC4Diagram({
|
|
|
2810
2929
|
nodesDraggable,
|
|
2811
2930
|
nodesSelectable,
|
|
2812
2931
|
experimentalEdgeEditing,
|
|
2932
|
+
enableDynamicViewWalkthrough,
|
|
2933
|
+
enableFocusMode,
|
|
2813
2934
|
renderIcon: renderIcon ?? null,
|
|
2814
|
-
onCanvasClick,
|
|
2815
|
-
onCanvasContextMenu,
|
|
2816
|
-
onEdgeClick,
|
|
2817
|
-
onEdgeContextMenu,
|
|
2818
|
-
onNodeClick,
|
|
2819
|
-
onNodeContextMenu,
|
|
2820
|
-
onChange,
|
|
2821
|
-
onNavigateTo,
|
|
2822
|
-
onCanvasDblClick,
|
|
2823
|
-
|
|
2935
|
+
onCanvasClick: onCanvasClick ?? null,
|
|
2936
|
+
onCanvasContextMenu: onCanvasContextMenu ?? null,
|
|
2937
|
+
onEdgeClick: onEdgeClick ?? null,
|
|
2938
|
+
onEdgeContextMenu: onEdgeContextMenu ?? null,
|
|
2939
|
+
onNodeClick: onNodeClick ?? null,
|
|
2940
|
+
onNodeContextMenu: onNodeContextMenu ?? null,
|
|
2941
|
+
onChange: onChange ?? null,
|
|
2942
|
+
onNavigateTo: onNavigateTo ?? null,
|
|
2943
|
+
onCanvasDblClick: onCanvasDblClick ?? null,
|
|
2944
|
+
onEditorCommand: onEditorCommand ?? null,
|
|
2945
|
+
children: /* @__PURE__ */ jsx(
|
|
2824
2946
|
LikeC4DiagramInnerMemo,
|
|
2825
2947
|
{
|
|
2826
|
-
defaultNodes: initialRef.current.defaultNodes,
|
|
2827
|
-
defaultEdges: initialRef.current.defaultEdges,
|
|
2828
|
-
fitView,
|
|
2829
|
-
zoomable,
|
|
2830
|
-
background,
|
|
2831
2948
|
controls,
|
|
2832
|
-
|
|
2949
|
+
background,
|
|
2833
2950
|
showDiagramTitle,
|
|
2834
|
-
showNavigationButtons
|
|
2835
|
-
enableDynamicViewWalkthrough
|
|
2951
|
+
showNavigationButtons
|
|
2836
2952
|
}
|
|
2837
|
-
)
|
|
2953
|
+
)
|
|
2838
2954
|
}
|
|
2839
2955
|
)
|
|
2840
2956
|
}
|
|
2841
|
-
) });
|
|
2957
|
+
) }) });
|
|
2842
2958
|
}
|
|
2843
2959
|
const LikeC4DiagramInnerMemo = memo(function({
|
|
2844
2960
|
background,
|
|
2845
|
-
fitView,
|
|
2846
|
-
zoomable,
|
|
2847
2961
|
controls,
|
|
2848
|
-
pannable,
|
|
2849
|
-
defaultNodes,
|
|
2850
|
-
defaultEdges,
|
|
2851
2962
|
showDiagramTitle,
|
|
2852
|
-
showNavigationButtons
|
|
2853
|
-
enableDynamicViewWalkthrough
|
|
2963
|
+
showNavigationButtons
|
|
2854
2964
|
}) {
|
|
2855
|
-
const
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2965
|
+
const {
|
|
2966
|
+
isInitialized,
|
|
2967
|
+
pannable,
|
|
2968
|
+
fitView,
|
|
2969
|
+
enableFocusMode
|
|
2970
|
+
} = useDiagramState((s) => ({
|
|
2971
|
+
isInitialized: s.initialized,
|
|
2972
|
+
zoomable: s.zoomable,
|
|
2973
|
+
pannable: s.pannable,
|
|
2974
|
+
fitView: s.fitViewEnabled,
|
|
2975
|
+
enableFocusMode: s.enableFocusMode
|
|
2976
|
+
}));
|
|
2977
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2866
2978
|
/* @__PURE__ */ jsx(
|
|
2867
2979
|
XYFlow,
|
|
2868
2980
|
{
|
|
2869
|
-
defaultNodes,
|
|
2870
|
-
defaultEdges,
|
|
2871
2981
|
className: clsx(
|
|
2872
2982
|
"likec4-diagram",
|
|
2873
2983
|
cssReactFlow,
|
|
@@ -2880,7 +2990,6 @@ const LikeC4DiagramInnerMemo = memo(function({
|
|
|
2880
2990
|
{
|
|
2881
2991
|
showNavigationButtons,
|
|
2882
2992
|
showDiagramTitle,
|
|
2883
|
-
enableDynamicViewWalkthrough,
|
|
2884
2993
|
background,
|
|
2885
2994
|
controls
|
|
2886
2995
|
}
|
|
@@ -2888,9 +2997,8 @@ const LikeC4DiagramInnerMemo = memo(function({
|
|
|
2888
2997
|
}
|
|
2889
2998
|
),
|
|
2890
2999
|
isInitialized && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2891
|
-
/* @__PURE__ */ jsx(SyncWithDiagram, {}),
|
|
2892
3000
|
fitView && /* @__PURE__ */ jsx(FitViewOnDiagramChange, {}),
|
|
2893
|
-
|
|
3001
|
+
enableFocusMode && /* @__PURE__ */ jsx(SelectEdgesOnNodeFocus, {})
|
|
2894
3002
|
] })
|
|
2895
3003
|
] });
|
|
2896
3004
|
}, shallowEqual);
|