@likec4/diagram 1.7.2 → 1.7.4
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 +38 -22
- package/dist/StaticLikeC4Diagram.d.ts +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/{state/useDiagramStore.d.ts → hooks/useDiagramState.d.ts} +2 -3
- package/dist/{xyflow/hooks → hooks}/useXYFlow.d.ts +10 -10
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +818 -448
- package/dist/state/DiagramContext.d.ts +74 -30
- package/dist/state/diagram-to-xyflow.d.ts +2 -0
- package/dist/state/diagramStore.d.ts +71 -22
- package/dist/style.css +58 -37
- package/dist/ui/top-left/ChangeAutoLayoutButton.d.ts +3 -0
- package/dist/ui/top-left/TopLeftPanel.d.ts +4 -0
- package/dist/ui/top-left/_shared.d.ts +5 -0
- package/dist/ui/top-left/styles.css.d.ts +3 -0
- package/dist/xyflow/XYFlowInner.d.ts +0 -1
- package/dist/xyflow/const.d.ts +1 -0
- package/dist/xyflow/edges/edges.css.d.ts +1 -1
- package/dist/xyflow/{hooks/useLayoutConstraints.d.ts → useLayoutConstraints.d.ts} +1 -1
- package/dist/xyflow/utils.d.ts +11 -1
- package/package.json +6 -6
- package/src/LikeC4Diagram.props.ts +66 -32
- package/src/LikeC4Diagram.tsx +19 -12
- package/src/StaticLikeC4Diagram.tsx +2 -0
- package/src/hooks/index.ts +2 -0
- package/src/{state/useDiagramStore.ts → hooks/useDiagramState.ts} +3 -4
- package/src/{xyflow/hooks → hooks}/useXYFlow.ts +1 -1
- package/src/index.ts +2 -2
- package/src/state/DiagramContext.tsx +15 -7
- package/src/state/diagram-to-xyflow.ts +17 -3
- package/src/state/diagramStore.ts +73 -38
- package/src/ui/DiagramTitlePanel.css.ts +2 -2
- package/src/ui/DiagramTitlePanel.tsx +62 -44
- package/src/ui/DynamicViewWalkthrough.tsx +1 -2
- package/src/ui/OptionsPanel.tsx +1 -1
- package/src/ui/options/EdgeOptions.tsx +1 -16
- package/src/ui/options/NodeOptions.tsx +38 -13
- package/src/ui/top-left/ChangeAutoLayoutButton.tsx +131 -0
- package/src/ui/top-left/TopLeftPanel.tsx +213 -0
- package/src/ui/top-left/_shared.ts +19 -0
- package/src/ui/top-left/styles.css.ts +38 -0
- package/src/xyflow/FitviewOnDiagramChange.tsx +2 -2
- package/src/xyflow/SelectEdgesOnNodeFocus.tsx +87 -59
- package/src/xyflow/XYFlow.tsx +11 -10
- package/src/xyflow/XYFlowEvents.tsx +44 -18
- package/src/xyflow/XYFlowInner.tsx +5 -7
- package/src/xyflow/const.ts +1 -0
- package/src/xyflow/edges/RelationshipEdge.tsx +60 -27
- package/src/xyflow/edges/edges.css.ts +29 -25
- package/src/xyflow/nodes/compound/CompoundNode.tsx +1 -1
- package/src/xyflow/nodes/element/ElementLink.tsx +1 -2
- package/src/xyflow/nodes/element/ElementNode.tsx +7 -5
- package/src/xyflow/nodes/shared/NavigateToBtn.tsx +1 -1
- package/src/xyflow/{hooks/useLayoutConstraints.ts → useLayoutConstraints.ts} +3 -3
- package/src/xyflow/utils.ts +25 -1
- package/dist/state/hooks.d.ts +0 -4
- package/dist/state/index.d.ts +0 -2
- package/dist/state/useNavigationHistory.d.ts +0 -5
- package/dist/types.d.ts +0 -20
- package/dist/ui/BackwardForwardPanel.css.d.ts +0 -1
- package/dist/ui/BackwardForwardPanel.d.ts +0 -1
- package/dist/xyflow/hooks/index.d.ts +0 -2
- package/src/state/hooks.ts +0 -5
- package/src/state/index.ts +0 -2
- package/src/state/useNavigationHistory.ts +0 -39
- package/src/types.ts +0 -22
- package/src/ui/BackwardForwardPanel.css.ts +0 -22
- package/src/ui/BackwardForwardPanel.tsx +0 -76
- package/src/xyflow/hooks/index.ts +0 -3
package/dist/index.mjs
CHANGED
|
@@ -6,41 +6,23 @@ import { useReactFlow, useStoreApi, useNodesData, useStore, applyNodeChanges, ap
|
|
|
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 {
|
|
10
|
-
import {
|
|
11
|
-
import { invariant, hasAtLeast, extractStep, nonNullable, StepEdgeId, getBBoxCenter, nonexhaustive, isAncestor, defaultTheme, ElementShapes } from "@likec4/core";
|
|
12
|
-
import {
|
|
9
|
+
import { createContext, useRef, useCallback, useContext, useState, memo, useEffect, useId, useMemo } from "react";
|
|
10
|
+
import { createWithEqualityFn, useStoreWithEqualityFn } from "zustand/traditional";
|
|
11
|
+
import { invariant, hasAtLeast, whereOperatorAsPredicate, extractStep, nonNullable, StepEdgeId, getBBoxCenter, nonexhaustive, isAncestor, defaultTheme, ElementShapes } from "@likec4/core";
|
|
12
|
+
import { useFirstMountState, useCustomCompareEffect, useDebouncedEffect } from "@react-hookz/web";
|
|
13
|
+
import { getNodeDimensions, getBoundsOfRects, boxToRect, getViewportForBounds as getViewportForBounds$1 } from "@xyflow/system";
|
|
13
14
|
import { DEV } from "esm-env";
|
|
14
15
|
import { isArray, hasAtLeast as hasAtLeast$1, isNullish, entries, reduce, isTruthy, first, last, clamp, isNumber, isNonNullish, keys, takeWhile } from "remeda";
|
|
15
16
|
import { subscribeWithSelector, devtools } from "zustand/middleware";
|
|
16
17
|
import { shallow } from "zustand/shallow";
|
|
17
|
-
import { createWithEqualityFn, useStoreWithEqualityFn } from "zustand/traditional";
|
|
18
18
|
import { Bezier } from "bezier-js";
|
|
19
|
-
import {
|
|
19
|
+
import { MantineContext, Box, ActionIcon as ActionIcon$2, Text as Text$1, HoverCard, HoverCardTarget, UnstyledButton, HoverCardDropdown, Stack, Group, Anchor, CopyButton, Button, Card, CardSection, Spoiler, ButtonGroup, rem, Divider, Space, TooltipGroup, Flex, Tooltip as Tooltip$2, ColorSwatch, CheckIcon, Select, Slider, SegmentedControl, Popover, PopoverTarget, PopoverDropdown, FloatingIndicator, Notification, Code } from "@mantine/core";
|
|
20
|
+
import { useHotkeys, useLocalStorage } from "@mantine/hooks";
|
|
20
21
|
import { assignInlineVars } from "@vanilla-extract/dynamic";
|
|
21
22
|
import { line, curveCatmullRomOpen } from "d3-shape";
|
|
22
23
|
import { Solver, Operator, Expression, Strength, Variable } from "@lume/kiwi";
|
|
23
|
-
import { IconZoomScan, IconLink,
|
|
24
|
-
|
|
25
|
-
var rootClassName = "likec4-diagram-root", cssReactFlow = "_2h8g8h0", cssDisablePan = "_2h8g8h1", cssTransparentBg = "_2h8g8h2", cssNoControls = "_2h8g8h3";
|
|
26
|
-
function EnsureMantine({ children }) {
|
|
27
|
-
if (!useContext(MantineContext))
|
|
28
|
-
throw new Error("LikeC4Diagram must be a child of MantineProvider");
|
|
29
|
-
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
30
|
-
}
|
|
31
|
-
function useSetState(initialState) {
|
|
32
|
-
const [state, _setState] = useState(initialState), setState = useCallback(
|
|
33
|
-
(statePartial) => _setState((current) => {
|
|
34
|
-
const next = {
|
|
35
|
-
...current,
|
|
36
|
-
...typeof statePartial == "function" ? statePartial(current) : statePartial
|
|
37
|
-
};
|
|
38
|
-
return shallowEqual(current, next) ? current : next;
|
|
39
|
-
}),
|
|
40
|
-
[]
|
|
41
|
-
);
|
|
42
|
-
return [state, setState];
|
|
43
|
-
}
|
|
24
|
+
import { IconZoomScan, IconLink, IconMenu, IconPlayerPlayFilled, IconPlayerSkipBackFilled, IconPlayerStopFilled, IconPlayerSkipForwardFilled, IconFileSymlink, IconLayoutDashboard, IconArrowBigDownLines, IconFocusCentered, IconMenu2, IconChevronLeft, IconChevronRight, IconAlertTriangle } from "@tabler/icons-react";
|
|
25
|
+
var rootClassName = "likec4-diagram-root";
|
|
44
26
|
const noop = () => {
|
|
45
27
|
}, depsShallowEqual = (d1, d2) => {
|
|
46
28
|
if (d1 === d2)
|
|
@@ -73,10 +55,16 @@ const useXYStoreApi = useStoreApi, ZIndexes = {
|
|
|
73
55
|
Compound: 2,
|
|
74
56
|
Edge: 4,
|
|
75
57
|
Element: 6
|
|
76
|
-
}, MinZoom = 0.1;
|
|
58
|
+
}, MinZoom = 0.1, MaxZoom = 2;
|
|
77
59
|
function toDomPrecision(v) {
|
|
78
60
|
return v === null ? 0.01 : Math.round(v * 100) / 100;
|
|
79
61
|
}
|
|
62
|
+
const nodeToRect = (nd) => ({
|
|
63
|
+
x: nd.internals.positionAbsolute.x,
|
|
64
|
+
y: nd.internals.positionAbsolute.y,
|
|
65
|
+
width: nd.width ?? nd.data.element.width,
|
|
66
|
+
height: nd.height ?? nd.data.element.height
|
|
67
|
+
}), isInside = (test, target) => test.x >= target.x && test.y >= target.y && test.x + test.width <= target.x + target.width && test.y + test.height <= target.y + target.height;
|
|
80
68
|
function bezierControlPoints(diagramEdge) {
|
|
81
69
|
let [start, ...bezierPoints] = diagramEdge.points;
|
|
82
70
|
invariant(start, "start should be defined");
|
|
@@ -104,7 +92,15 @@ function diagramViewToXYFlowData(view, opts) {
|
|
|
104
92
|
const isDynamicView = view.__ === "dynamic", xynodes = [], xyedges = [], nodeLookup = /* @__PURE__ */ new Map(), traverse = view.nodes.reduce(
|
|
105
93
|
(acc, node) => (nodeLookup.set(node.id, node), node.parent || acc.push({ node, parent: null }), acc),
|
|
106
94
|
new Array()
|
|
107
|
-
)
|
|
95
|
+
);
|
|
96
|
+
let visiblePredicate = (_nodeOrEdge) => !0;
|
|
97
|
+
if (opts.where)
|
|
98
|
+
try {
|
|
99
|
+
visiblePredicate = whereOperatorAsPredicate(opts.where);
|
|
100
|
+
} catch (e) {
|
|
101
|
+
console.error("Error in where filter:", e);
|
|
102
|
+
}
|
|
103
|
+
const ns = "", nodeById = (id) => nonNullable(nodeLookup.get(id), `Node not found: ${id}`);
|
|
108
104
|
let next;
|
|
109
105
|
for (; next = traverse.shift(); ) {
|
|
110
106
|
const { node, parent } = next;
|
|
@@ -127,9 +123,9 @@ function diagramViewToXYFlowData(view, opts) {
|
|
|
127
123
|
deletable: !1,
|
|
128
124
|
position,
|
|
129
125
|
zIndex: isCompound ? ZIndexes.Compound : ZIndexes.Element,
|
|
130
|
-
hidden: !1,
|
|
131
126
|
width: node.width,
|
|
132
127
|
height: node.height,
|
|
128
|
+
hidden: !visiblePredicate(node),
|
|
133
129
|
// parentId: parent ? ns + parent.id : null,
|
|
134
130
|
...parent && {
|
|
135
131
|
parentId: ns + parent.id
|
|
@@ -148,6 +144,7 @@ function diagramViewToXYFlowData(view, opts) {
|
|
|
148
144
|
target: ns + target,
|
|
149
145
|
zIndex: ZIndexes.Edge,
|
|
150
146
|
selectable: opts.selectable,
|
|
147
|
+
hidden: !visiblePredicate(edge),
|
|
151
148
|
deletable: !1,
|
|
152
149
|
data: {
|
|
153
150
|
edge,
|
|
@@ -190,6 +187,7 @@ function createDiagramStore(props) {
|
|
|
190
187
|
xynodes,
|
|
191
188
|
xyedges
|
|
192
189
|
} = diagramViewToXYFlowData(props.view, {
|
|
190
|
+
where: props.whereFilter,
|
|
193
191
|
draggable: props.nodesDraggable,
|
|
194
192
|
selectable: props.nodesSelectable
|
|
195
193
|
});
|
|
@@ -224,6 +222,7 @@ function createDiagramStore(props) {
|
|
|
224
222
|
xyflow,
|
|
225
223
|
xystore,
|
|
226
224
|
dimmed: dimmed2,
|
|
225
|
+
whereFilter,
|
|
227
226
|
view: current,
|
|
228
227
|
lastOnNavigate,
|
|
229
228
|
navigationHistory,
|
|
@@ -239,10 +238,6 @@ function createDiagramStore(props) {
|
|
|
239
238
|
xyedges: xyedges2,
|
|
240
239
|
xynodes: xynodes2
|
|
241
240
|
} = get();
|
|
242
|
-
if (shallowEqual(current, nextView)) {
|
|
243
|
-
DEV && console.debug("store: skip updateView");
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
241
|
viewSyncDebounceTimeout !== null && (clearTimeout(viewSyncDebounceTimeout), viewSyncDebounceTimeout = null);
|
|
247
242
|
const isSameView = current.id === nextView.id;
|
|
248
243
|
if (isSameView) {
|
|
@@ -289,24 +284,27 @@ function createDiagramStore(props) {
|
|
|
289
284
|
lastClickedEdgeId = null, lastClickedNodeId = null, hoveredEdgeId = null, hoveredNodeId = null, focusedNodeId = null, activeDynamicViewStep = null, dimmed2 = EmptyStringSet;
|
|
290
285
|
}
|
|
291
286
|
const update = diagramViewToXYFlowData(nextView, {
|
|
287
|
+
where: whereFilter,
|
|
292
288
|
draggable: nodesDraggable,
|
|
293
289
|
selectable: nodesSelectable
|
|
294
290
|
});
|
|
295
291
|
update.xynodes = update.xynodes.map((update2) => {
|
|
296
292
|
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 : {
|
|
293
|
+
return existing && existing.type === update2.type && deepEqual(existing.parentId ?? null, update2.parentId ?? null) ? existing.hidden === update2.hidden && existing.width === update2.width && existing.height === update2.height && deepEqual(existing.position, update2.position) && deepEqual(existing.data.element, update2.data.element) ? existing : {
|
|
298
294
|
...existing,
|
|
299
295
|
...update2
|
|
300
296
|
} : update2;
|
|
301
297
|
}), isSameView && !nextView.hasLayoutDrift && (update.xyedges = update.xyedges.map((update2) => {
|
|
302
298
|
const existing = xyedges2.find((n) => n.id === update2.id);
|
|
303
|
-
return existing ? deepEqual(existing.data, update2.data) ? existing : {
|
|
299
|
+
return existing ? existing.hidden === update2.hidden && deepEqual(existing.data.label, update2.data.label) && deepEqual(existing.data.controlPoints, update2.data.controlPoints) && deepEqual(existing.data.edge, update2.data.edge) ? existing : {
|
|
304
300
|
...existing,
|
|
305
|
-
...update2
|
|
301
|
+
...update2,
|
|
302
|
+
data: {
|
|
303
|
+
...existing.data,
|
|
304
|
+
...update2.data
|
|
305
|
+
}
|
|
306
306
|
} : update2;
|
|
307
|
-
}))
|
|
308
|
-
const hasChanges = !isSameView || !shallowEqual(update.xynodes, xynodes2) || !shallowEqual(update.xyedges, xyedges2);
|
|
309
|
-
set(
|
|
307
|
+
})), set(
|
|
310
308
|
{
|
|
311
309
|
isDynamicView: nextView.__ === "dynamic",
|
|
312
310
|
viewSyncDebounceTimeout,
|
|
@@ -321,8 +319,8 @@ function createDiagramStore(props) {
|
|
|
321
319
|
navigationHistory,
|
|
322
320
|
navigationHistoryIndex,
|
|
323
321
|
dimmed: dimmed2,
|
|
324
|
-
xynodes:
|
|
325
|
-
xyedges:
|
|
322
|
+
xynodes: !isSameView || !shallowEqual(update.xynodes, xynodes2) ? update.xynodes : xynodes2,
|
|
323
|
+
xyedges: !isSameView || !shallowEqual(update.xyedges, xyedges2) ? update.xyedges : xyedges2
|
|
326
324
|
},
|
|
327
325
|
noReplace,
|
|
328
326
|
isSameView ? "update-view [same]" : "update-view [another]"
|
|
@@ -439,10 +437,7 @@ function createDiagramStore(props) {
|
|
|
439
437
|
},
|
|
440
438
|
triggerSaveManualLayout: () => {
|
|
441
439
|
const { xyflow, view, onChange, xystore, viewSyncDebounceTimeout } = get();
|
|
442
|
-
|
|
443
|
-
DEV && console.debug("ignore triggerSaveManualLayout, as no onChange handler is set");
|
|
444
|
-
return;
|
|
445
|
-
}
|
|
440
|
+
viewSyncDebounceTimeout !== null && (clearTimeout(viewSyncDebounceTimeout), set({ viewSyncDebounceTimeout: null }));
|
|
446
441
|
const { nodeLookup } = xystore.getState(), movedNodes = new StringSet();
|
|
447
442
|
let bounds = {
|
|
448
443
|
x: 0,
|
|
@@ -471,7 +466,15 @@ function createDiagramStore(props) {
|
|
|
471
466
|
points: data.edge.points
|
|
472
467
|
};
|
|
473
468
|
(_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 = [
|
|
469
|
+
const allX = [
|
|
470
|
+
...data.edge.points.map((p) => p[0]),
|
|
471
|
+
...(controlPoints ?? []).map((p) => p.x),
|
|
472
|
+
..._updated.labelBBox ? [_updated.labelBBox.x, _updated.labelBBox.x + _updated.labelBBox.width] : []
|
|
473
|
+
], allY = [
|
|
474
|
+
...data.edge.points.map((p) => p[1]),
|
|
475
|
+
...(controlPoints ?? []).map((p) => p.y),
|
|
476
|
+
..._updated.labelBBox ? [_updated.labelBBox.y, _updated.labelBBox.y + _updated.labelBBox.height] : []
|
|
477
|
+
], rect = boxToRect({
|
|
475
478
|
x: Math.floor(Math.min(...allX)),
|
|
476
479
|
y: Math.floor(Math.min(...allY)),
|
|
477
480
|
x2: Math.ceil(Math.max(...allX)),
|
|
@@ -488,14 +491,19 @@ function createDiagramStore(props) {
|
|
|
488
491
|
...bounds
|
|
489
492
|
}
|
|
490
493
|
};
|
|
491
|
-
DEV && console.debug("triggerSaveManualLayout", change),
|
|
494
|
+
DEV && console.debug("triggerSaveManualLayout", change), isInside(bounds, view.bounds) || set(
|
|
495
|
+
{
|
|
496
|
+
view: {
|
|
497
|
+
...view,
|
|
498
|
+
bounds
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
noReplace,
|
|
502
|
+
"update view bounds"
|
|
503
|
+
), onChange == null || onChange({ change });
|
|
492
504
|
},
|
|
493
505
|
scheduleSaveManualLayout: () => {
|
|
494
|
-
let { viewSyncDebounceTimeout
|
|
495
|
-
if (!onChange) {
|
|
496
|
-
DEV && console.debug("ignore triggerSaveManualLayout, as no onChange handler is set");
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
506
|
+
let { viewSyncDebounceTimeout } = get();
|
|
499
507
|
viewSyncDebounceTimeout && clearTimeout(viewSyncDebounceTimeout), set(
|
|
500
508
|
{
|
|
501
509
|
viewSyncDebounceTimeout: setTimeout(() => {
|
|
@@ -508,13 +516,13 @@ function createDiagramStore(props) {
|
|
|
508
516
|
);
|
|
509
517
|
},
|
|
510
518
|
triggerOnNavigateTo: (xynodeId, event) => {
|
|
511
|
-
const { view, xynodes: xynodes2, onNavigateTo } = get();
|
|
519
|
+
const { view, xynodes: xynodes2, onNavigateTo, cancelSaveManualLayout } = get();
|
|
512
520
|
if (!onNavigateTo)
|
|
513
521
|
return;
|
|
514
522
|
const xynode = xynodes2.find(({ id }) => id === xynodeId);
|
|
515
523
|
invariant(xynode, `xynode not found: ${xynodeId}`);
|
|
516
524
|
const element = view.nodes.find(({ id }) => id === xynodeId);
|
|
517
|
-
invariant(element == null ? void 0 : element.navigateTo, `node is not navigable: ${xynodeId}`), set(
|
|
525
|
+
invariant(element == null ? void 0 : element.navigateTo, `node is not navigable: ${xynodeId}`), cancelSaveManualLayout(), set(
|
|
518
526
|
{
|
|
519
527
|
lastClickedNodeId: xynodeId,
|
|
520
528
|
lastOnNavigate: {
|
|
@@ -659,6 +667,7 @@ function DiagramContextProvider({
|
|
|
659
667
|
view,
|
|
660
668
|
className,
|
|
661
669
|
keepAspectRatio,
|
|
670
|
+
whereFilter,
|
|
662
671
|
...props
|
|
663
672
|
}) {
|
|
664
673
|
const containerRef = useRef(null), xystore = useXYStoreApi(), xyflow = useXYFlow(), store = useRef(), getContainer = useCallback(() => containerRef.current, [containerRef]);
|
|
@@ -667,6 +676,7 @@ function DiagramContextProvider({
|
|
|
667
676
|
xyflow,
|
|
668
677
|
view,
|
|
669
678
|
getContainer,
|
|
679
|
+
whereFilter: structuredClone(whereFilter),
|
|
670
680
|
...props
|
|
671
681
|
})), useUpdateEffect(
|
|
672
682
|
() => {
|
|
@@ -682,10 +692,11 @@ function DiagramContextProvider({
|
|
|
682
692
|
[props]
|
|
683
693
|
), useUpdateEffect(
|
|
684
694
|
() => {
|
|
685
|
-
|
|
686
|
-
(
|
|
695
|
+
const current = store.current;
|
|
696
|
+
invariant(current, "DiagramContext.store.current is not defined"), deepEqual(whereFilter, current.getState().whereFilter) || current.setState({ whereFilter: structuredClone(whereFilter) }, !1, "update where filter"), current.getState().updateView(view);
|
|
687
697
|
},
|
|
688
|
-
[view]
|
|
698
|
+
[view, whereFilter],
|
|
699
|
+
(a, b) => shallowEqual(a[0], b[0]) && deepEqual(a[1], b[1])
|
|
689
700
|
), /* @__PURE__ */ jsx(
|
|
690
701
|
"div",
|
|
691
702
|
{
|
|
@@ -713,6 +724,12 @@ function useDiagramStoreApi() {
|
|
|
713
724
|
throw new Error("useDiagramStoreApi could be used only inside DiagramContext");
|
|
714
725
|
return store;
|
|
715
726
|
}
|
|
727
|
+
var cssReactFlow = "_2h8g8h0", cssDisablePan = "_2h8g8h1", cssTransparentBg = "_2h8g8h2", cssNoControls = "_2h8g8h3";
|
|
728
|
+
function EnsureMantine({ children }) {
|
|
729
|
+
if (!useContext(MantineContext))
|
|
730
|
+
throw new Error("LikeC4Diagram must be a child of MantineProvider");
|
|
731
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
732
|
+
}
|
|
716
733
|
function selectXYFlowSize(state) {
|
|
717
734
|
return `${Math.round(state.width)}:${Math.round(state.height)}`;
|
|
718
735
|
}
|
|
@@ -756,51 +773,84 @@ function FitViewOnDiagramChange() {
|
|
|
756
773
|
50
|
|
757
774
|
), viewportNotMoved && !requiresFit ? /* @__PURE__ */ jsx(FitViewOnViewportResize, { diagramApi }) : null;
|
|
758
775
|
}
|
|
776
|
+
function useSetState(initialState) {
|
|
777
|
+
const [state, _setState] = useState(initialState), setState = useCallback(
|
|
778
|
+
(statePartial) => _setState((current) => {
|
|
779
|
+
const next = {
|
|
780
|
+
...current,
|
|
781
|
+
...typeof statePartial == "function" ? statePartial(current) : statePartial
|
|
782
|
+
};
|
|
783
|
+
return shallowEqual(current, next) ? current : next;
|
|
784
|
+
}),
|
|
785
|
+
[]
|
|
786
|
+
);
|
|
787
|
+
return [state, setState];
|
|
788
|
+
}
|
|
759
789
|
function SelectEdgesOnNodeFocus() {
|
|
760
|
-
const diagramStore = useDiagramStoreApi();
|
|
761
|
-
return
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
id: edge.id,
|
|
783
|
-
type: "select",
|
|
784
|
-
selected: !1
|
|
785
|
-
});
|
|
790
|
+
const diagramStore = useDiagramStoreApi(), focusedNodeId = useDiagramState((s) => s.focusedNodeId);
|
|
791
|
+
return useUpdateEffect(() => {
|
|
792
|
+
if (!focusedNodeId) {
|
|
793
|
+
diagramStore.getState().xystore.getState().resetSelectedElements();
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
const container2 = diagramStore.getState().getContainer();
|
|
797
|
+
if (!container2)
|
|
798
|
+
return;
|
|
799
|
+
const { width, height } = container2.getBoundingClientRect(), edgeChanges = [], nodeChanges = [], {
|
|
800
|
+
edgeLookup,
|
|
801
|
+
nodeLookup,
|
|
802
|
+
panZoom,
|
|
803
|
+
transform,
|
|
804
|
+
triggerNodeChanges,
|
|
805
|
+
triggerEdgeChanges
|
|
806
|
+
} = diagramStore.getState().xystore.getState();
|
|
807
|
+
let focusBounds = nodeToRect(nonNullable(nodeLookup.get(focusedNodeId)));
|
|
808
|
+
for (const [, edge] of edgeLookup) {
|
|
809
|
+
if (edge.source === focusedNodeId || edge.target === focusedNodeId) {
|
|
810
|
+
const anotherNodeId = edge.source === focusedNodeId ? edge.target : edge.source, nd = nonNullable(nodeLookup.get(anotherNodeId));
|
|
811
|
+
focusBounds = getBoundsOfRects(focusBounds, nodeToRect(nd));
|
|
786
812
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
id: node.id,
|
|
790
|
-
type: "select",
|
|
791
|
-
selected: !1
|
|
792
|
-
});
|
|
793
|
-
nodeChanges.push({
|
|
794
|
-
id: focusedNodeId,
|
|
813
|
+
edge.selected && edgeChanges.push({
|
|
814
|
+
id: edge.id,
|
|
795
815
|
type: "select",
|
|
796
|
-
selected: !
|
|
797
|
-
}), edgeChanges.length > 0 && triggerEdgeChanges(edgeChanges), triggerNodeChanges(nodeChanges);
|
|
798
|
-
const maxZoom = Math.max(1, transform[2]), viewport = getViewportForBounds$1(focusBounds, width, height, MinZoom, maxZoom, 0.2);
|
|
799
|
-
panZoom == null || panZoom.setViewport(viewport, {
|
|
800
|
-
duration: 350
|
|
816
|
+
selected: !1
|
|
801
817
|
});
|
|
802
|
-
}
|
|
803
|
-
[
|
|
818
|
+
}
|
|
819
|
+
for (const [, node] of nodeLookup)
|
|
820
|
+
node.selected && node.id !== focusedNodeId && nodeChanges.push({
|
|
821
|
+
id: node.id,
|
|
822
|
+
type: "select",
|
|
823
|
+
selected: !1
|
|
824
|
+
});
|
|
825
|
+
nodeChanges.push({
|
|
826
|
+
id: focusedNodeId,
|
|
827
|
+
type: "select",
|
|
828
|
+
selected: !0
|
|
829
|
+
}), edgeChanges.length > 0 && triggerEdgeChanges(edgeChanges), triggerNodeChanges(nodeChanges);
|
|
830
|
+
const maxZoom = Math.max(1, transform[2]), viewport = getViewportForBounds$1(
|
|
831
|
+
{
|
|
832
|
+
x: focusBounds.x - 16,
|
|
833
|
+
y: focusBounds.y - 16,
|
|
834
|
+
width: focusBounds.width + 32,
|
|
835
|
+
height: focusBounds.height + 32
|
|
836
|
+
},
|
|
837
|
+
width,
|
|
838
|
+
height,
|
|
839
|
+
0.1,
|
|
840
|
+
maxZoom,
|
|
841
|
+
0
|
|
842
|
+
);
|
|
843
|
+
panZoom == null || panZoom.setViewport(viewport, {
|
|
844
|
+
duration: 350
|
|
845
|
+
});
|
|
846
|
+
}, [focusedNodeId]), useHotkeys(
|
|
847
|
+
focusedNodeId !== null ? [
|
|
848
|
+
["Escape", (e) => {
|
|
849
|
+
e.stopImmediatePropagation();
|
|
850
|
+
const { xystore, fitDiagram } = diagramStore.getState();
|
|
851
|
+
fitDiagram(), xystore.getState().resetSelectedElements();
|
|
852
|
+
}, { preventDefault: !0 }]
|
|
853
|
+
] : []
|
|
804
854
|
), null;
|
|
805
855
|
}
|
|
806
856
|
const Open = (props) => /* @__PURE__ */ jsx(
|
|
@@ -962,7 +1012,7 @@ const Open = (props) => /* @__PURE__ */ jsx(
|
|
|
962
1012
|
Dot,
|
|
963
1013
|
ODot
|
|
964
1014
|
};
|
|
965
|
-
var container$4 = "bexn7q1", dimmed$2 = "bexn7q2", edgePathBg = "bexn7q3", markerContext = "bexn7q4", controlPoint = "bexn7q5", controlDragging = "bexn7q6", cssEdgePath = "bexn7q8",
|
|
1015
|
+
var container$4 = "bexn7q1", dimmed$2 = "bexn7q2", edgePathBg = "bexn7q3", markerContext = "bexn7q4", controlPoint = "bexn7q5", controlDragging = "bexn7q6", cssEdgePath = "bexn7q8", stepEdgeNumber = "bexn7q9", varLabelX = "var(--bexn7qa)", varLabelY = "var(--bexn7qb)", edgeLabel = "bexn7qd", edgeLabelText = "bexn7qe";
|
|
966
1016
|
function getNodeIntersectionFromCenterToPoint(intersectionNode, { x: x1, y: y1 }) {
|
|
967
1017
|
const {
|
|
968
1018
|
width: intersectionNodeWidth,
|
|
@@ -1003,7 +1053,7 @@ function bezierPath(bezierSpline) {
|
|
|
1003
1053
|
}
|
|
1004
1054
|
return invariant(points.length === 0, "all points should be consumed"), path;
|
|
1005
1055
|
}
|
|
1006
|
-
const isSame = (a, b) => Math.abs(a - b) <
|
|
1056
|
+
const isSame = (a, b) => Math.abs(a - b) < 2.5, isSamePoint = (a, b) => {
|
|
1007
1057
|
const [ax, ay] = isArray(a) ? a : [a.x, a.y], [bx, by] = isArray(b) ? b : [b.x, b.y];
|
|
1008
1058
|
return isSame(ax, bx) && isSame(ay, by);
|
|
1009
1059
|
}, 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({
|
|
@@ -1019,11 +1069,12 @@ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
|
1019
1069
|
target,
|
|
1020
1070
|
interactionWidth
|
|
1021
1071
|
}) {
|
|
1022
|
-
const [isControlPointDragging, setIsControlPointDragging] = useState(!1), diagramStore = useDiagramStoreApi(), xyflowStore = useXYStoreApi(), { isActive, isEdgePathEditable, isHovered, isDimmed } = useDiagramState((s) => ({
|
|
1023
|
-
isEdgePathEditable: s.readonly !== !0 && s.experimentalEdgeEditing === !0,
|
|
1072
|
+
const [isControlPointDragging, setIsControlPointDragging] = useState(!1), diagramStore = useDiagramStoreApi(), xyflowStore = useXYStoreApi(), { isActive, isEdgePathEditable, isHovered, isDimmed, hasOpenSourceRelation } = useDiagramState((s) => ({
|
|
1073
|
+
isEdgePathEditable: s.readonly !== !0 && s.experimentalEdgeEditing === !0 && s.focusedNodeId === null && s.activeDynamicViewStep === null,
|
|
1024
1074
|
isActive: s.focusedNodeId === source || s.focusedNodeId === target || s.activeDynamicViewStep !== null && s.activeDynamicViewStep === data.stepNum,
|
|
1025
1075
|
isHovered: s.hoveredEdgeId === id,
|
|
1026
|
-
isDimmed: s.dimmed.has(id)
|
|
1076
|
+
isDimmed: s.dimmed.has(id),
|
|
1077
|
+
hasOpenSourceRelation: !!s.onOpenSourceRelation
|
|
1027
1078
|
})), { 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), {
|
|
1028
1079
|
label,
|
|
1029
1080
|
edge: {
|
|
@@ -1045,7 +1096,6 @@ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
|
1045
1096
|
});
|
|
1046
1097
|
let edgePath;
|
|
1047
1098
|
if (isModified) {
|
|
1048
|
-
labelX = labelPos.x, labelY = labelPos.y;
|
|
1049
1099
|
const sourceCenterPos = { x: sourceX, y: sourceY }, targetCenterPos = { x: targetX, y: targetY }, points = diagramEdge.dir === "back" ? [
|
|
1050
1100
|
targetCenterPos,
|
|
1051
1101
|
getNodeIntersectionFromCenterToPoint(targetNode, first(controlPoints) ?? sourceCenterPos),
|
|
@@ -1084,9 +1134,9 @@ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
|
1084
1134
|
});
|
|
1085
1135
|
},
|
|
1086
1136
|
[labelPos],
|
|
1087
|
-
|
|
1137
|
+
50,
|
|
1088
1138
|
300
|
|
1089
|
-
);
|
|
1139
|
+
), (isModified || isControlPointDragging) && (labelX = labelPos.x, labelY = labelPos.y);
|
|
1090
1140
|
const onControlPointerDown = (index, e) => {
|
|
1091
1141
|
const { domNode } = xyflowStore.getState();
|
|
1092
1142
|
if (!domNode || e.pointerType !== "mouse")
|
|
@@ -1105,22 +1155,35 @@ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
|
1105
1155
|
e.stopPropagation();
|
|
1106
1156
|
let hasMoved = !1, pointer = { x: e.clientX, y: e.clientY };
|
|
1107
1157
|
const onPointerMove = (e2) => {
|
|
1108
|
-
if (!isSamePoint(pointer, [e2.clientX, e2.clientY])) {
|
|
1158
|
+
if (hasMoved || !isSamePoint(pointer, [e2.clientX, e2.clientY])) {
|
|
1109
1159
|
setIsControlPointDragging(!0), hasMoved = !0, pointer = { x: e2.clientX, y: e2.clientY };
|
|
1110
|
-
const { x, y } = xyflow.screenToFlowPosition(pointer, { snapToGrid: !1 })
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1160
|
+
const { x, y } = xyflow.screenToFlowPosition(pointer, { snapToGrid: !1 });
|
|
1161
|
+
xyflow.updateEdgeData(id, (xyedge) => {
|
|
1162
|
+
const cp = (xyedge.data.controlPoints ?? controlPoints).slice();
|
|
1163
|
+
return cp[index] = {
|
|
1164
|
+
x: Math.round(x),
|
|
1165
|
+
y: Math.round(y)
|
|
1166
|
+
}, {
|
|
1167
|
+
controlPoints: cp
|
|
1168
|
+
};
|
|
1169
|
+
});
|
|
1115
1170
|
}
|
|
1116
|
-
|
|
1117
|
-
|
|
1171
|
+
e2.stopPropagation();
|
|
1172
|
+
}, onPointerUp = (e2) => {
|
|
1173
|
+
domNode.removeEventListener("pointermove", onPointerMove, {
|
|
1174
|
+
capture: !0
|
|
1175
|
+
}), hasMoved && e2.stopPropagation(), (hasMoved || wasCanceled) && diagramStore.getState().scheduleSaveManualLayout(), setIsControlPointDragging(!1);
|
|
1118
1176
|
};
|
|
1119
|
-
domNode.addEventListener("pointermove", onPointerMove
|
|
1177
|
+
domNode.addEventListener("pointermove", onPointerMove, {
|
|
1178
|
+
capture: !0
|
|
1179
|
+
}), domNode.addEventListener("pointerup", onPointerUp, {
|
|
1180
|
+
once: !0,
|
|
1181
|
+
capture: !0
|
|
1182
|
+
});
|
|
1120
1183
|
};
|
|
1121
1184
|
let markerStartName = toMarker(diagramEdge.tail), markerEndName = toMarker(diagramEdge.head ?? "normal");
|
|
1122
1185
|
diagramEdge.dir === "back" && ([markerStartName, markerEndName] = [markerEndName, markerStartName]);
|
|
1123
|
-
const MarkerStart = markerStartName ? EdgeMarkers[markerStartName] : null, MarkerEnd = markerEndName ? EdgeMarkers[markerEndName] : null, labelZIndex = 1 + (isHovered ? ZIndexes.Element : edgeLookup.get(id).zIndex ?? ZIndexes.Edge);
|
|
1186
|
+
const MarkerStart = markerStartName ? EdgeMarkers[markerStartName] : null, MarkerEnd = markerEndName ? EdgeMarkers[markerEndName] : null, labelZIndex = 1 + (isHovered ? ZIndexes.Element : edgeLookup.get(id).zIndex ?? ZIndexes.Edge), relationId = first(data.edge.relations), showOpenSourceRelation = hasOpenSourceRelation && relationId !== void 0;
|
|
1124
1187
|
return /* @__PURE__ */ jsxs(
|
|
1125
1188
|
"g",
|
|
1126
1189
|
{
|
|
@@ -1206,13 +1269,17 @@ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
|
1206
1269
|
zIndex: labelZIndex,
|
|
1207
1270
|
isHovered,
|
|
1208
1271
|
isActive,
|
|
1209
|
-
isStepEdge
|
|
1272
|
+
isStepEdge,
|
|
1273
|
+
onClick: showOpenSourceRelation && ((e) => {
|
|
1274
|
+
var _a, _b;
|
|
1275
|
+
e.stopPropagation(), (_b = (_a = diagramStore.getState()).onOpenSourceRelation) == null || _b.call(_a, relationId);
|
|
1276
|
+
})
|
|
1210
1277
|
}
|
|
1211
1278
|
)
|
|
1212
1279
|
]
|
|
1213
1280
|
}
|
|
1214
1281
|
);
|
|
1215
|
-
}, isEqualProps$2), EdgeLabel =
|
|
1282
|
+
}, isEqualProps$2), EdgeLabel = ({
|
|
1216
1283
|
isDimmed,
|
|
1217
1284
|
color,
|
|
1218
1285
|
isModified,
|
|
@@ -1224,7 +1291,8 @@ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
|
1224
1291
|
stepNum,
|
|
1225
1292
|
isHovered,
|
|
1226
1293
|
isActive,
|
|
1227
|
-
zIndex
|
|
1294
|
+
zIndex,
|
|
1295
|
+
onClick
|
|
1228
1296
|
}) => /* @__PURE__ */ jsx(EdgeLabelRenderer, { children: /* @__PURE__ */ jsxs(
|
|
1229
1297
|
Box,
|
|
1230
1298
|
{
|
|
@@ -1252,162 +1320,17 @@ const isSame = (a, b) => Math.abs(a - b) < 3.1, isSamePoint = (a, b) => {
|
|
|
1252
1320
|
"data-edge-hovered": isHovered,
|
|
1253
1321
|
"data-edge-active": isActive
|
|
1254
1322
|
},
|
|
1323
|
+
onClick: onClick || void 0,
|
|
1255
1324
|
children: [
|
|
1256
1325
|
stepNum !== null && /* @__PURE__ */ jsx(Box, { className: stepEdgeNumber, children: stepNum }),
|
|
1257
1326
|
isTruthy(label == null ? void 0 : label.text) && /* @__PURE__ */ jsx(Box, { className: edgeLabelText, children: label.text })
|
|
1258
1327
|
]
|
|
1259
1328
|
}
|
|
1260
|
-
) })
|
|
1261
|
-
class Rect {
|
|
1262
|
-
constructor() {
|
|
1263
|
-
__publicField(this, "id");
|
|
1264
|
-
__publicField(this, "minX", new Variable());
|
|
1265
|
-
__publicField(this, "minY", new Variable());
|
|
1266
|
-
__publicField(this, "maxX", new Variable());
|
|
1267
|
-
__publicField(this, "maxY", new Variable());
|
|
1268
|
-
}
|
|
1269
|
-
get x() {
|
|
1270
|
-
return this.minX;
|
|
1271
|
-
}
|
|
1272
|
-
get y() {
|
|
1273
|
-
return this.minY;
|
|
1274
|
-
}
|
|
1275
|
-
get positionAbsolute() {
|
|
1276
|
-
return {
|
|
1277
|
-
x: this.x.value(),
|
|
1278
|
-
y: this.y.value()
|
|
1279
|
-
};
|
|
1280
|
-
}
|
|
1281
|
-
get dimensions() {
|
|
1282
|
-
return {
|
|
1283
|
-
width: this.maxX.value() - this.minX.value(),
|
|
1284
|
-
height: this.maxY.value() - this.minY.value()
|
|
1285
|
-
};
|
|
1286
|
-
}
|
|
1287
|
-
// Position relative to parent
|
|
1288
|
-
get position() {
|
|
1289
|
-
const positionAbsolute = this.positionAbsolute;
|
|
1290
|
-
if (!this.parent)
|
|
1291
|
-
return positionAbsolute;
|
|
1292
|
-
const parentPosition = this.parent.positionAbsolute;
|
|
1293
|
-
return {
|
|
1294
|
-
x: positionAbsolute.x - parentPosition.x,
|
|
1295
|
-
y: positionAbsolute.y - parentPosition.y
|
|
1296
|
-
};
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
class Compound extends Rect {
|
|
1300
|
-
constructor(solver, xynode, parent = null) {
|
|
1301
|
-
super();
|
|
1302
|
-
__publicField(this, "children", []);
|
|
1303
|
-
this.solver = solver, this.parent = parent, this.id = xynode.id, solver.createConstraint(this.maxX, Operator.Ge, this.minX), solver.createConstraint(this.maxY, Operator.Ge, this.minY), parent && parent.addChild(this);
|
|
1304
|
-
}
|
|
1305
|
-
addChild(rect) {
|
|
1306
|
-
this.children.push(rect);
|
|
1307
|
-
const leftPadding = new Expression(
|
|
1308
|
-
rect.minX,
|
|
1309
|
-
[-1, this.minX]
|
|
1310
|
-
), { weak } = Strength;
|
|
1311
|
-
this.solver.createConstraint(leftPadding, Operator.Ge, 40), this.solver.createConstraint(leftPadding, Operator.Eq, 41, weak);
|
|
1312
|
-
const topPadding = new Expression(
|
|
1313
|
-
rect.minY,
|
|
1314
|
-
[-1, this.minY]
|
|
1315
|
-
);
|
|
1316
|
-
this.solver.createConstraint(topPadding, Operator.Ge, 54), this.solver.createConstraint(topPadding, Operator.Eq, 55, weak);
|
|
1317
|
-
const rightPadding = new Expression(
|
|
1318
|
-
this.maxX,
|
|
1319
|
-
[-1, rect.maxX]
|
|
1320
|
-
);
|
|
1321
|
-
this.solver.createConstraint(rightPadding, Operator.Ge, 40), this.solver.createConstraint(rightPadding, Operator.Eq, 41, weak);
|
|
1322
|
-
const bottomPadding = new Expression(
|
|
1323
|
-
this.maxY,
|
|
1324
|
-
[-1, rect.maxY]
|
|
1325
|
-
);
|
|
1326
|
-
this.solver.createConstraint(bottomPadding, Operator.Ge, 40), this.solver.createConstraint(bottomPadding, Operator.Eq, 41, weak);
|
|
1327
|
-
}
|
|
1328
|
-
}
|
|
1329
|
-
class Leaf extends Rect {
|
|
1330
|
-
constructor(solver, xynode, parent = null, isEditing = !1) {
|
|
1331
|
-
super(), this.parent = parent, this.isEditing = isEditing, this.id = xynode.id;
|
|
1332
|
-
const x = Math.ceil(xynode.internals.positionAbsolute.x), y = Math.ceil(xynode.internals.positionAbsolute.y), { width, height } = getNodeDimensions(xynode);
|
|
1333
|
-
if (this.maxX = new Expression(this.minX, Math.ceil(width)), this.maxY = new Expression(this.minY, Math.ceil(height)), isEditing) {
|
|
1334
|
-
const superStrong = Strength.create(100, 0, 0);
|
|
1335
|
-
solver.addEditVariable(this.minX, superStrong), solver.addEditVariable(this.minY, superStrong), solver.suggestValue(this.minX, x), solver.suggestValue(this.minY, y);
|
|
1336
|
-
} else {
|
|
1337
|
-
const halfMedium = Strength.create(0, 1, 0, 0.5);
|
|
1338
|
-
solver.createConstraint(this.minX, Operator.Eq, x, halfMedium), solver.createConstraint(this.minY, Operator.Eq, y, halfMedium);
|
|
1339
|
-
}
|
|
1340
|
-
parent && parent.addChild(this);
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
function createLayoutConstraints(xyflowApi, draggingNodeId) {
|
|
1344
|
-
var _a;
|
|
1345
|
-
const { parentLookup, nodeLookup } = xyflowApi.getState(), solver = new Solver(), rects = /* @__PURE__ */ new Map(), traverse = new Array();
|
|
1346
|
-
for (const [, xynode] of nodeLookup)
|
|
1347
|
-
isNullish(xynode.parentId) && traverse.push({
|
|
1348
|
-
xynode,
|
|
1349
|
-
parent: null
|
|
1350
|
-
});
|
|
1351
|
-
for (; traverse.length > 0; ) {
|
|
1352
|
-
const { xynode, parent } = traverse.shift(), isDragging = xynode.dragging === !0 || xynode.id === draggingNodeId, shouldTraverse = !isDragging && xynode.type === "compound" && isAncestor(xynode.id, draggingNodeId), rect = shouldTraverse ? new Compound(solver, xynode, parent) : new Leaf(solver, xynode, parent, isDragging);
|
|
1353
|
-
rects.set(xynode.id, rect), shouldTraverse && ((_a = parentLookup.get(xynode.id)) == null || _a.forEach((child) => {
|
|
1354
|
-
traverse.push({
|
|
1355
|
-
xynode: child,
|
|
1356
|
-
parent: rect
|
|
1357
|
-
});
|
|
1358
|
-
}));
|
|
1359
|
-
}
|
|
1360
|
-
solver.updateVariables(), solver.maxIterations = 1e3;
|
|
1361
|
-
const rectsToUpdate = [...rects.values()].filter((r) => r.id !== draggingNodeId);
|
|
1362
|
-
function updateXYFlowNodes() {
|
|
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), [])
|
|
1376
|
-
);
|
|
1377
|
-
}
|
|
1378
|
-
let animationFrameId = null;
|
|
1379
|
-
function onNodeDrag(xynode) {
|
|
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
|
-
})));
|
|
1385
|
-
}
|
|
1386
|
-
return {
|
|
1387
|
-
onNodeDrag,
|
|
1388
|
-
updateXYFlowNodes
|
|
1389
|
-
};
|
|
1390
|
-
}
|
|
1391
|
-
function useLayoutConstraints() {
|
|
1392
|
-
const diagramApi = useDiagramStoreApi(), solverRef = useRef();
|
|
1393
|
-
return useMemo(() => ({
|
|
1394
|
-
onNodeDragStart: (_event, xynode) => {
|
|
1395
|
-
const { cancelSaveManualLayout, xystore } = diagramApi.getState();
|
|
1396
|
-
cancelSaveManualLayout(), solverRef.current = createLayoutConstraints(xystore, xynode.id);
|
|
1397
|
-
},
|
|
1398
|
-
onNodeDrag: (_event, xynode) => {
|
|
1399
|
-
var _a;
|
|
1400
|
-
invariant(solverRef.current, "solverRef.current should be defined"), (_a = solverRef.current) == null || _a.onNodeDrag(xynode);
|
|
1401
|
-
},
|
|
1402
|
-
onNodeDragStop: (_event, _xynode) => {
|
|
1403
|
-
diagramApi.getState().scheduleSaveManualLayout(), solverRef.current = void 0;
|
|
1404
|
-
}
|
|
1405
|
-
}), [diagramApi]);
|
|
1406
|
-
}
|
|
1329
|
+
) });
|
|
1407
1330
|
function NavigateToBtn({ xynodeId, className }) {
|
|
1408
1331
|
const diagramApi = useDiagramStoreApi();
|
|
1409
1332
|
return /* @__PURE__ */ jsx(
|
|
1410
|
-
ActionIcon,
|
|
1333
|
+
ActionIcon$2,
|
|
1411
1334
|
{
|
|
1412
1335
|
className: clsx("nodrag nopan", className),
|
|
1413
1336
|
radius: "md",
|
|
@@ -1797,12 +1720,13 @@ const Text = Text$1.withProps({
|
|
|
1797
1720
|
width,
|
|
1798
1721
|
height
|
|
1799
1722
|
}) {
|
|
1800
|
-
const store = useDiagramStoreApi(), { isHovered, isDimmed, hasOnNavigateTo, isHovercards, isInteractive } = useDiagramState((s) => ({
|
|
1723
|
+
const store = useDiagramStoreApi(), { isHovered, isDimmed, hasOnNavigateTo, isHovercards, isInteractive, hasGoToSource } = useDiagramState((s) => ({
|
|
1801
1724
|
isHovered: s.hoveredNodeId === id,
|
|
1802
1725
|
isDimmed: s.dimmed.has(id),
|
|
1803
1726
|
isInteractive: s.nodesDraggable || s.nodesSelectable || !!s.onNavigateTo,
|
|
1804
1727
|
isHovercards: s.showElementLinks,
|
|
1805
|
-
hasOnNavigateTo: !!s.onNavigateTo
|
|
1728
|
+
hasOnNavigateTo: !!s.onNavigateTo,
|
|
1729
|
+
hasGoToSource: !!s.onOpenSourceElement
|
|
1806
1730
|
})), isNavigable = hasOnNavigateTo && !!element.navigateTo, w = toDomPrecision(width ?? element.width), h = toDomPrecision(height ?? element.height);
|
|
1807
1731
|
let animate = "idle";
|
|
1808
1732
|
switch (!0) {
|
|
@@ -1936,33 +1860,182 @@ const Text = Text$1.withProps({
|
|
|
1936
1860
|
const RenderIcon = store.getState().renderIcon, icon = RenderIcon ? /* @__PURE__ */ jsx(RenderIcon, { node }) : null;
|
|
1937
1861
|
return icon ? /* @__PURE__ */ jsx("div", { className: clsx(elementIcon, "likec4-element-icon"), children: icon }) : null;
|
|
1938
1862
|
};
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1863
|
+
class Rect {
|
|
1864
|
+
constructor() {
|
|
1865
|
+
__publicField(this, "id");
|
|
1866
|
+
__publicField(this, "minX", new Variable());
|
|
1867
|
+
__publicField(this, "minY", new Variable());
|
|
1868
|
+
__publicField(this, "maxX", new Variable());
|
|
1869
|
+
__publicField(this, "maxY", new Variable());
|
|
1870
|
+
}
|
|
1871
|
+
get x() {
|
|
1872
|
+
return this.minX;
|
|
1873
|
+
}
|
|
1874
|
+
get y() {
|
|
1875
|
+
return this.minY;
|
|
1876
|
+
}
|
|
1877
|
+
get positionAbsolute() {
|
|
1945
1878
|
return {
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1879
|
+
x: this.x.value(),
|
|
1880
|
+
y: this.y.value()
|
|
1881
|
+
};
|
|
1882
|
+
}
|
|
1883
|
+
get dimensions() {
|
|
1884
|
+
return {
|
|
1885
|
+
width: this.maxX.value() - this.minX.value(),
|
|
1886
|
+
height: this.maxY.value() - this.minY.value()
|
|
1887
|
+
};
|
|
1888
|
+
}
|
|
1889
|
+
// Position relative to parent
|
|
1890
|
+
get position() {
|
|
1891
|
+
const positionAbsolute = this.positionAbsolute;
|
|
1892
|
+
if (!this.parent)
|
|
1893
|
+
return positionAbsolute;
|
|
1894
|
+
const parentPosition = this.parent.positionAbsolute;
|
|
1895
|
+
return {
|
|
1896
|
+
x: positionAbsolute.x - parentPosition.x,
|
|
1897
|
+
y: positionAbsolute.y - parentPosition.y
|
|
1898
|
+
};
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
class Compound extends Rect {
|
|
1902
|
+
constructor(solver, xynode, parent = null) {
|
|
1903
|
+
super();
|
|
1904
|
+
__publicField(this, "children", []);
|
|
1905
|
+
this.solver = solver, this.parent = parent, this.id = xynode.id, solver.createConstraint(this.maxX, Operator.Ge, this.minX), solver.createConstraint(this.maxY, Operator.Ge, this.minY), parent && parent.addChild(this);
|
|
1906
|
+
}
|
|
1907
|
+
addChild(rect) {
|
|
1908
|
+
this.children.push(rect);
|
|
1909
|
+
const leftPadding = new Expression(
|
|
1910
|
+
rect.minX,
|
|
1911
|
+
[-1, this.minX]
|
|
1912
|
+
), { weak } = Strength;
|
|
1913
|
+
this.solver.createConstraint(leftPadding, Operator.Ge, 40), this.solver.createConstraint(leftPadding, Operator.Eq, 41, weak);
|
|
1914
|
+
const topPadding = new Expression(
|
|
1915
|
+
rect.minY,
|
|
1916
|
+
[-1, this.minY]
|
|
1917
|
+
);
|
|
1918
|
+
this.solver.createConstraint(topPadding, Operator.Ge, 54), this.solver.createConstraint(topPadding, Operator.Eq, 55, weak);
|
|
1919
|
+
const rightPadding = new Expression(
|
|
1920
|
+
this.maxX,
|
|
1921
|
+
[-1, rect.maxX]
|
|
1922
|
+
);
|
|
1923
|
+
this.solver.createConstraint(rightPadding, Operator.Ge, 40), this.solver.createConstraint(rightPadding, Operator.Eq, 41, weak);
|
|
1924
|
+
const bottomPadding = new Expression(
|
|
1925
|
+
this.maxY,
|
|
1926
|
+
[-1, rect.maxY]
|
|
1927
|
+
);
|
|
1928
|
+
this.solver.createConstraint(bottomPadding, Operator.Ge, 40), this.solver.createConstraint(bottomPadding, Operator.Eq, 41, weak);
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
class Leaf extends Rect {
|
|
1932
|
+
constructor(solver, xynode, parent = null, isEditing = !1) {
|
|
1933
|
+
super(), this.parent = parent, this.isEditing = isEditing, this.id = xynode.id;
|
|
1934
|
+
const x = Math.ceil(xynode.internals.positionAbsolute.x), y = Math.ceil(xynode.internals.positionAbsolute.y), { width, height } = getNodeDimensions(xynode);
|
|
1935
|
+
if (this.maxX = new Expression(this.minX, Math.ceil(width)), this.maxY = new Expression(this.minY, Math.ceil(height)), isEditing) {
|
|
1936
|
+
const superStrong = Strength.create(100, 0, 0);
|
|
1937
|
+
solver.addEditVariable(this.minX, superStrong), solver.addEditVariable(this.minY, superStrong), solver.suggestValue(this.minX, x), solver.suggestValue(this.minY, y);
|
|
1938
|
+
} else {
|
|
1939
|
+
const halfMedium = Strength.create(0, 1, 0, 0.5);
|
|
1940
|
+
solver.createConstraint(this.minX, Operator.Eq, x, halfMedium), solver.createConstraint(this.minY, Operator.Eq, y, halfMedium);
|
|
1941
|
+
}
|
|
1942
|
+
parent && parent.addChild(this);
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
function createLayoutConstraints(xyflowApi, draggingNodeId) {
|
|
1946
|
+
var _a;
|
|
1947
|
+
const { parentLookup, nodeLookup } = xyflowApi.getState(), solver = new Solver(), rects = /* @__PURE__ */ new Map(), traverse = new Array();
|
|
1948
|
+
for (const [, xynode] of nodeLookup)
|
|
1949
|
+
isNullish(xynode.parentId) && traverse.push({
|
|
1950
|
+
xynode,
|
|
1951
|
+
parent: null
|
|
1952
|
+
});
|
|
1953
|
+
for (; traverse.length > 0; ) {
|
|
1954
|
+
const { xynode, parent } = traverse.shift(), isDragging = xynode.dragging === !0 || xynode.id === draggingNodeId, shouldTraverse = !isDragging && xynode.type === "compound" && isAncestor(xynode.id, draggingNodeId), rect = shouldTraverse ? new Compound(solver, xynode, parent) : new Leaf(solver, xynode, parent, isDragging);
|
|
1955
|
+
rects.set(xynode.id, rect), shouldTraverse && ((_a = parentLookup.get(xynode.id)) == null || _a.forEach((child) => {
|
|
1956
|
+
traverse.push({
|
|
1957
|
+
xynode: child,
|
|
1958
|
+
parent: rect
|
|
1959
|
+
});
|
|
1960
|
+
}));
|
|
1961
|
+
}
|
|
1962
|
+
solver.updateVariables(), solver.maxIterations = 1e3;
|
|
1963
|
+
const rectsToUpdate = [...rects.values()].filter((r) => r.id !== draggingNodeId);
|
|
1964
|
+
function updateXYFlowNodes() {
|
|
1965
|
+
solver.updateVariables(), xyflowApi.getState().triggerNodeChanges(
|
|
1966
|
+
rectsToUpdate.reduce((acc, r) => (acc.push({
|
|
1967
|
+
id: r.id,
|
|
1968
|
+
type: "position",
|
|
1969
|
+
dragging: !1,
|
|
1970
|
+
position: r.position,
|
|
1971
|
+
positionAbsolute: r.positionAbsolute
|
|
1972
|
+
}), r instanceof Compound && acc.push({
|
|
1973
|
+
id: r.id,
|
|
1974
|
+
type: "dimensions",
|
|
1975
|
+
setAttributes: !0,
|
|
1976
|
+
dimensions: r.dimensions
|
|
1977
|
+
}), acc), [])
|
|
1978
|
+
);
|
|
1979
|
+
}
|
|
1980
|
+
let animationFrameId = null;
|
|
1981
|
+
function onNodeDrag(xynode) {
|
|
1982
|
+
rectsToUpdate.length !== 0 && (animationFrameId ?? (animationFrameId = requestAnimationFrame(() => {
|
|
1983
|
+
animationFrameId = null;
|
|
1984
|
+
const pos = nodeLookup.get(xynode.id).internals.positionAbsolute, rect = nonNullable(rects.get(xynode.id));
|
|
1985
|
+
solver.suggestValue(rect.minX, Math.ceil(pos.x)), solver.suggestValue(rect.minY, Math.ceil(pos.y)), updateXYFlowNodes();
|
|
1986
|
+
})));
|
|
1987
|
+
}
|
|
1988
|
+
return {
|
|
1989
|
+
onNodeDrag,
|
|
1990
|
+
updateXYFlowNodes
|
|
1991
|
+
};
|
|
1992
|
+
}
|
|
1993
|
+
function useLayoutConstraints() {
|
|
1994
|
+
const diagramApi = useDiagramStoreApi(), solverRef = useRef();
|
|
1995
|
+
return useMemo(() => ({
|
|
1996
|
+
onNodeDragStart: (_event, xynode) => {
|
|
1997
|
+
const { cancelSaveManualLayout, xystore } = diagramApi.getState();
|
|
1998
|
+
cancelSaveManualLayout(), solverRef.current = createLayoutConstraints(xystore, xynode.id);
|
|
1999
|
+
},
|
|
2000
|
+
onNodeDrag: (_event, xynode) => {
|
|
2001
|
+
var _a;
|
|
2002
|
+
invariant(solverRef.current, "solverRef.current should be defined"), (_a = solverRef.current) == null || _a.onNodeDrag(xynode);
|
|
2003
|
+
},
|
|
2004
|
+
onNodeDragStop: (_event, _xynode) => {
|
|
2005
|
+
diagramApi.getState().scheduleSaveManualLayout(), solverRef.current = void 0;
|
|
2006
|
+
}
|
|
2007
|
+
}), [diagramApi]);
|
|
2008
|
+
}
|
|
2009
|
+
function useXYFlowEvents() {
|
|
2010
|
+
const diagramApi = useDiagramStoreApi(), lastClickTimestamp = useRef(), dblclickTimeout = useRef(), hoveredNodeFromOnEdgeEnterRef = useRef("");
|
|
2011
|
+
return useMemo(() => {
|
|
2012
|
+
const dbclickLock = () => dblclickTimeout.current !== void 0 ? !0 : (dblclickTimeout.current = window.setTimeout(() => {
|
|
2013
|
+
dblclickTimeout.current = void 0;
|
|
2014
|
+
}, 250), !1), lastClickWasRecent = (ms = 1500) => lastClickTimestamp.current && Date.now() - lastClickTimestamp.current < ms;
|
|
2015
|
+
return {
|
|
2016
|
+
onDoubleClick: (event) => {
|
|
2017
|
+
const {
|
|
2018
|
+
onCanvasDblClick,
|
|
2019
|
+
zoomable,
|
|
2020
|
+
xystore,
|
|
2021
|
+
viewportChanged,
|
|
2022
|
+
fitDiagram,
|
|
2023
|
+
resetLastClicked
|
|
2024
|
+
} = diagramApi.getState();
|
|
2025
|
+
resetLastClicked(), xystore.getState().resetSelectedElements(), onCanvasDblClick || event.stopPropagation(), zoomable && viewportChanged && fitDiagram(), onCanvasDblClick == null || onCanvasDblClick(event);
|
|
2026
|
+
},
|
|
2027
|
+
onPaneClick: (event) => {
|
|
2028
|
+
if (dbclickLock())
|
|
2029
|
+
return;
|
|
2030
|
+
const {
|
|
2031
|
+
focusedNodeId,
|
|
1960
2032
|
activeDynamicViewStep,
|
|
1961
2033
|
fitDiagram,
|
|
1962
2034
|
onCanvasClick,
|
|
2035
|
+
xystore,
|
|
1963
2036
|
resetLastClicked
|
|
1964
2037
|
} = diagramApi.getState();
|
|
1965
|
-
(focusedNodeId ?? activeDynamicViewStep) !== null && (fitDiagram(), onCanvasClick || event.stopPropagation()), resetLastClicked(), onCanvasClick == null || onCanvasClick(event);
|
|
2038
|
+
(focusedNodeId ?? activeDynamicViewStep) !== null && (fitDiagram(), onCanvasClick || event.stopPropagation()), resetLastClicked(), xystore.getState().resetSelectedElements(), onCanvasClick == null || onCanvasClick(event);
|
|
1966
2039
|
},
|
|
1967
2040
|
onNodeContextMenu: (event, xynode) => {
|
|
1968
2041
|
var _a, _b;
|
|
@@ -1990,22 +2063,33 @@ function useXYFlowEvents() {
|
|
|
1990
2063
|
fitDiagram,
|
|
1991
2064
|
focusOnNode,
|
|
1992
2065
|
onNodeClick,
|
|
2066
|
+
xystore,
|
|
1993
2067
|
enableFocusMode,
|
|
1994
2068
|
lastClickedNodeId,
|
|
1995
|
-
|
|
2069
|
+
nodesSelectable,
|
|
2070
|
+
setLastClickedNode,
|
|
2071
|
+
onOpenSourceElement
|
|
1996
2072
|
} = diagramApi.getState();
|
|
1997
2073
|
setLastClickedNode(xynode.id);
|
|
1998
2074
|
const shallChangeFocus = !!focusedNodeId && focusedNodeId !== xynode.id, clickedRecently = lastClickedNodeId === xynode.id && lastClickWasRecent();
|
|
1999
|
-
if (enableFocusMode) {
|
|
2000
|
-
let stopPropagation = !
|
|
2075
|
+
if (clickedRecently && onOpenSourceElement && onOpenSourceElement(xynode.data.element.id), enableFocusMode || nodesSelectable) {
|
|
2076
|
+
let stopPropagation = !0;
|
|
2001
2077
|
switch (!0) {
|
|
2002
|
-
case (!focusedNodeId && clickedRecently):
|
|
2003
|
-
case shallChangeFocus:
|
|
2004
|
-
|
|
2078
|
+
case (enableFocusMode && !focusedNodeId && clickedRecently):
|
|
2079
|
+
case (enableFocusMode && shallChangeFocus): {
|
|
2080
|
+
focusOnNode(xynode.id);
|
|
2005
2081
|
break;
|
|
2006
|
-
|
|
2007
|
-
|
|
2082
|
+
}
|
|
2083
|
+
case (enableFocusMode && focusedNodeId === xynode.id && clickedRecently): {
|
|
2084
|
+
fitDiagram();
|
|
2085
|
+
break;
|
|
2086
|
+
}
|
|
2087
|
+
case nodesSelectable: {
|
|
2088
|
+
xystore.getState().addSelectedNodes([xynode.id]);
|
|
2008
2089
|
break;
|
|
2090
|
+
}
|
|
2091
|
+
default:
|
|
2092
|
+
stopPropagation = !1;
|
|
2009
2093
|
}
|
|
2010
2094
|
!onNodeClick && stopPropagation && event.stopPropagation();
|
|
2011
2095
|
}
|
|
@@ -2033,6 +2117,8 @@ function useXYFlowEvents() {
|
|
|
2033
2117
|
activateDynamicStep,
|
|
2034
2118
|
activeDynamicViewStep,
|
|
2035
2119
|
focusedNodeId,
|
|
2120
|
+
xystore,
|
|
2121
|
+
nodesSelectable,
|
|
2036
2122
|
focusOnNode,
|
|
2037
2123
|
onEdgeClick,
|
|
2038
2124
|
setLastClickedEdge
|
|
@@ -2046,7 +2132,7 @@ function useXYFlowEvents() {
|
|
|
2046
2132
|
return;
|
|
2047
2133
|
}
|
|
2048
2134
|
}
|
|
2049
|
-
isEdgeOfFocusedNode
|
|
2135
|
+
isEdgeOfFocusedNode ? (focusOnNode(focusedNodeId === xyedge.source ? xyedge.target : xyedge.source), onEdgeClick || event.stopPropagation()) : nodesSelectable && (xystore.getState().addSelectedEdges([xyedge.id]), onEdgeClick || event.stopPropagation()), onEdgeClick == null || onEdgeClick({
|
|
2050
2136
|
edge: xyedge.data.edge,
|
|
2051
2137
|
xyedge,
|
|
2052
2138
|
event
|
|
@@ -2150,11 +2236,11 @@ function XYFlow({
|
|
|
2150
2236
|
hasOnEdgeContextMenu,
|
|
2151
2237
|
translateX,
|
|
2152
2238
|
translateY
|
|
2153
|
-
} = useDiagramState(selector$1, shallowEqual), layoutConstraints = useLayoutConstraints(), handlers = useXYFlowEvents();
|
|
2239
|
+
} = useDiagramState(selector$1, shallowEqual), [zoomOnDoubleClick, setZoomOnDoubleClick] = useState(zoomable), layoutConstraints = useLayoutConstraints(), handlers = useXYFlowEvents();
|
|
2154
2240
|
return useOnViewportChange({
|
|
2155
2241
|
onEnd: ({ x, y, zoom }) => {
|
|
2156
2242
|
const roundedX = Math.round(x), roundedY = Math.round(y);
|
|
2157
|
-
(x !== roundedX || y !== roundedY) && xyflowApi.setState({ transform: [roundedX, roundedY, zoom] });
|
|
2243
|
+
(x !== roundedX || y !== roundedY) && xyflowApi.setState({ transform: [roundedX, roundedY, zoom] }), setZoomOnDoubleClick(zoomable && zoom < 1.1);
|
|
2158
2244
|
}
|
|
2159
2245
|
}), /* @__PURE__ */ jsx(
|
|
2160
2246
|
ReactFlow,
|
|
@@ -2171,7 +2257,7 @@ function XYFlow({
|
|
|
2171
2257
|
...!zoomable && {
|
|
2172
2258
|
zoomActivationKeyCode: null
|
|
2173
2259
|
},
|
|
2174
|
-
maxZoom: zoomable ?
|
|
2260
|
+
maxZoom: zoomable ? MaxZoom : 1,
|
|
2175
2261
|
minZoom: zoomable ? MinZoom : 1,
|
|
2176
2262
|
fitView,
|
|
2177
2263
|
fitViewOptions: useMemo(() => ({
|
|
@@ -2206,7 +2292,7 @@ function XYFlow({
|
|
|
2206
2292
|
onNodeDragStop: layoutConstraints.onNodeDragStop
|
|
2207
2293
|
},
|
|
2208
2294
|
nodeDragThreshold: 3,
|
|
2209
|
-
zoomOnDoubleClick
|
|
2295
|
+
zoomOnDoubleClick,
|
|
2210
2296
|
elevateNodesOnSelect: !1,
|
|
2211
2297
|
selectNodesOnDrag: !1,
|
|
2212
2298
|
onNodesChange,
|
|
@@ -2236,82 +2322,6 @@ function XYFlow({
|
|
|
2236
2322
|
}
|
|
2237
2323
|
);
|
|
2238
2324
|
}
|
|
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
|
-
});
|
|
2246
|
-
function BackwardForwardPanel() {
|
|
2247
|
-
const {
|
|
2248
|
-
hasStepBack,
|
|
2249
|
-
hasStepForward,
|
|
2250
|
-
goBack,
|
|
2251
|
-
goForward
|
|
2252
|
-
} = useDiagramState(historySelector);
|
|
2253
|
-
return /* @__PURE__ */ jsx(
|
|
2254
|
-
Group,
|
|
2255
|
-
{
|
|
2256
|
-
className: clsx(
|
|
2257
|
-
"react-flow__panel",
|
|
2258
|
-
panel$1,
|
|
2259
|
-
"likec4-navigation-panel"
|
|
2260
|
-
),
|
|
2261
|
-
gap: "xs",
|
|
2262
|
-
children: /* @__PURE__ */ jsxs(AnimatePresence, { children: [
|
|
2263
|
-
hasStepBack && /* @__PURE__ */ jsx(
|
|
2264
|
-
m.div,
|
|
2265
|
-
{
|
|
2266
|
-
layout: !0,
|
|
2267
|
-
initial: { opacity: 0.05, transform: "translateX(-10px)" },
|
|
2268
|
-
animate: { opacity: 1, transform: "translateX(0)" },
|
|
2269
|
-
exit: {
|
|
2270
|
-
opacity: 0.05,
|
|
2271
|
-
transform: "translateX(-10px)"
|
|
2272
|
-
},
|
|
2273
|
-
children: /* @__PURE__ */ jsx(
|
|
2274
|
-
ActionIcon,
|
|
2275
|
-
{
|
|
2276
|
-
variant: "light",
|
|
2277
|
-
color: "gray",
|
|
2278
|
-
onClick: (e) => {
|
|
2279
|
-
e.stopPropagation(), goBack();
|
|
2280
|
-
},
|
|
2281
|
-
children: /* @__PURE__ */ jsx(IconChevronLeft, {})
|
|
2282
|
-
}
|
|
2283
|
-
)
|
|
2284
|
-
},
|
|
2285
|
-
"back"
|
|
2286
|
-
),
|
|
2287
|
-
hasStepForward && /* @__PURE__ */ jsx(
|
|
2288
|
-
m.div,
|
|
2289
|
-
{
|
|
2290
|
-
layout: !0,
|
|
2291
|
-
initial: { opacity: 0.05, transform: "translateX(10px)" },
|
|
2292
|
-
animate: { opacity: 1, transform: "translateX(0)" },
|
|
2293
|
-
exit: {
|
|
2294
|
-
opacity: 0,
|
|
2295
|
-
transform: "translateX(10px)"
|
|
2296
|
-
},
|
|
2297
|
-
children: /* @__PURE__ */ jsx(
|
|
2298
|
-
ActionIcon,
|
|
2299
|
-
{
|
|
2300
|
-
variant: "light",
|
|
2301
|
-
color: "gray",
|
|
2302
|
-
onClick: (e) => {
|
|
2303
|
-
e.stopPropagation(), goForward();
|
|
2304
|
-
},
|
|
2305
|
-
children: /* @__PURE__ */ jsx(IconChevronRight, {})
|
|
2306
|
-
}
|
|
2307
|
-
)
|
|
2308
|
-
},
|
|
2309
|
-
"forward"
|
|
2310
|
-
)
|
|
2311
|
-
] })
|
|
2312
|
-
}
|
|
2313
|
-
);
|
|
2314
|
-
}
|
|
2315
2325
|
var container$1 = "hbkbtj0", card = "hbkbtj1", title = "hbkbtj2", description = "hbkbtj3";
|
|
2316
2326
|
const selector = (s) => ({
|
|
2317
2327
|
id: s.view.id,
|
|
@@ -2343,62 +2353,75 @@ function DiagramTitlePanel() {
|
|
|
2343
2353
|
radius: "sm",
|
|
2344
2354
|
className: card,
|
|
2345
2355
|
withBorder: !0,
|
|
2346
|
-
p: "md",
|
|
2347
|
-
pb: isCollapsed ? "sm" : "md",
|
|
2356
|
+
p: isCollapsed ? "sm" : "md",
|
|
2348
2357
|
onDoubleClick: (e) => e.stopPropagation(),
|
|
2349
2358
|
children: [
|
|
2350
|
-
/* @__PURE__ */ jsx(CardSection, {
|
|
2359
|
+
isCollapsed && /* @__PURE__ */ jsx(CardSection, { children: /* @__PURE__ */ jsx(
|
|
2351
2360
|
Button,
|
|
2352
2361
|
{
|
|
2353
2362
|
fullWidth: !0,
|
|
2354
|
-
|
|
2355
|
-
|
|
2363
|
+
justify: "stretch",
|
|
2364
|
+
size: "sm",
|
|
2356
2365
|
py: 2,
|
|
2357
2366
|
radius: "0",
|
|
2358
|
-
variant:
|
|
2359
|
-
color: "
|
|
2367
|
+
variant: "subtle",
|
|
2368
|
+
color: "dark",
|
|
2360
2369
|
onClick: toggle,
|
|
2361
|
-
children: /* @__PURE__ */ jsx(
|
|
2370
|
+
children: /* @__PURE__ */ jsx(Text$1, { inline: !0, fw: 500, fz: "xs", c: "gray", children: title$12 })
|
|
2362
2371
|
}
|
|
2363
2372
|
) }),
|
|
2364
|
-
/* @__PURE__ */ jsxs(
|
|
2365
|
-
/* @__PURE__ */ jsx(
|
|
2366
|
-
|
|
2367
|
-
{
|
|
2368
|
-
component: "div",
|
|
2369
|
-
flex: "1",
|
|
2370
|
-
size: isCollapsed ? "sm" : "lg",
|
|
2371
|
-
fw: 500,
|
|
2372
|
-
lh: 1.1,
|
|
2373
|
-
className: title,
|
|
2374
|
-
children: title$12
|
|
2375
|
-
}
|
|
2376
|
-
),
|
|
2377
|
-
/* @__PURE__ */ jsxs(
|
|
2378
|
-
Text$1,
|
|
2373
|
+
!isCollapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2374
|
+
/* @__PURE__ */ jsx(CardSection, { mb: "sm", children: /* @__PURE__ */ jsx(
|
|
2375
|
+
Button,
|
|
2379
2376
|
{
|
|
2380
|
-
|
|
2381
|
-
component: "div",
|
|
2382
|
-
flex: "0 0 auto",
|
|
2383
|
-
inline: !0,
|
|
2377
|
+
fullWidth: !0,
|
|
2384
2378
|
size: "xs",
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
children:
|
|
2392
|
-
/* @__PURE__ */ jsxs("span", { style: { userSelect: "none" }, children: [
|
|
2393
|
-
"id:",
|
|
2394
|
-
" "
|
|
2395
|
-
] }),
|
|
2396
|
-
id
|
|
2397
|
-
]
|
|
2379
|
+
h: "sm",
|
|
2380
|
+
py: 2,
|
|
2381
|
+
radius: "0",
|
|
2382
|
+
variant: "subtle",
|
|
2383
|
+
color: "gray",
|
|
2384
|
+
onClick: toggle,
|
|
2385
|
+
children: /* @__PURE__ */ jsx(IconMenu, { size: 11, opacity: 0.7 })
|
|
2398
2386
|
}
|
|
2399
|
-
)
|
|
2400
|
-
|
|
2401
|
-
|
|
2387
|
+
) }),
|
|
2388
|
+
/* @__PURE__ */ jsxs(Group, { justify: "stretch", wrap: "nowrap", mb: "sm", children: [
|
|
2389
|
+
/* @__PURE__ */ jsx(
|
|
2390
|
+
Text$1,
|
|
2391
|
+
{
|
|
2392
|
+
component: "div",
|
|
2393
|
+
flex: "1",
|
|
2394
|
+
size: "md",
|
|
2395
|
+
fw: 500,
|
|
2396
|
+
lh: 1.1,
|
|
2397
|
+
className: title,
|
|
2398
|
+
children: title$12
|
|
2399
|
+
}
|
|
2400
|
+
),
|
|
2401
|
+
/* @__PURE__ */ jsxs(
|
|
2402
|
+
Text$1,
|
|
2403
|
+
{
|
|
2404
|
+
hidden: isCollapsed,
|
|
2405
|
+
component: "div",
|
|
2406
|
+
flex: "0 0 auto",
|
|
2407
|
+
inline: !0,
|
|
2408
|
+
size: "xs",
|
|
2409
|
+
fz: 9,
|
|
2410
|
+
fw: 500,
|
|
2411
|
+
c: "dimmed",
|
|
2412
|
+
style: {
|
|
2413
|
+
userSelect: "all"
|
|
2414
|
+
},
|
|
2415
|
+
children: [
|
|
2416
|
+
/* @__PURE__ */ jsxs("span", { style: { userSelect: "none" }, children: [
|
|
2417
|
+
"id:",
|
|
2418
|
+
" "
|
|
2419
|
+
] }),
|
|
2420
|
+
id
|
|
2421
|
+
]
|
|
2422
|
+
}
|
|
2423
|
+
)
|
|
2424
|
+
] }),
|
|
2402
2425
|
description$12 && /* @__PURE__ */ jsx(
|
|
2403
2426
|
Spoiler,
|
|
2404
2427
|
{
|
|
@@ -2573,7 +2596,7 @@ const {
|
|
|
2573
2596
|
return null;
|
|
2574
2597
|
if (nodes.length !== selectedNodeIds.length)
|
|
2575
2598
|
throw new Error("NodeOptions: nodes and props.nodes should have the same length");
|
|
2576
|
-
const showShapeOption = nodes.some((node) => node.type === "element"), [firstNode, ...rest] = nodes, showOpacityOption = firstNode.type === "compound" && (rest.length === 0 || rest.every((node) => node.type === "compound")), triggerChange = (style) => {
|
|
2599
|
+
const showShapeOption = nodes.some((node) => node.type === "element"), [firstNode, ...rest] = nodes, showGoToSource = rest.length === 0 && diagramApi.getState().onOpenSourceElement, showOpacityOption = firstNode.type === "compound" && (rest.length === 0 || rest.every((node) => node.type === "compound")), triggerChange = (style) => {
|
|
2577
2600
|
const targets = nodes.map((node) => node.data.element.id);
|
|
2578
2601
|
invariant(hasAtLeast$1(targets, 1), "At least one target is required"), diagramApi.getState().triggerChangeElementStyle({
|
|
2579
2602
|
op: "change-element-style",
|
|
@@ -2582,12 +2605,36 @@ const {
|
|
|
2582
2605
|
});
|
|
2583
2606
|
};
|
|
2584
2607
|
return /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
2585
|
-
/* @__PURE__ */ jsxs("
|
|
2586
|
-
/* @__PURE__ */ jsxs(
|
|
2587
|
-
"
|
|
2588
|
-
|
|
2608
|
+
/* @__PURE__ */ jsxs(Group, { wrap: "nowrap", align: "flex-start", children: [
|
|
2609
|
+
/* @__PURE__ */ jsxs(Box, { flex: 1, children: [
|
|
2610
|
+
/* @__PURE__ */ jsxs(Text$1, { fz: rem(9), fw: "500", c: "dimmed", children: [
|
|
2611
|
+
"ELEMENT",
|
|
2612
|
+
rest.length > 0 ? "S" : ""
|
|
2613
|
+
] }),
|
|
2614
|
+
/* @__PURE__ */ jsx(Text$1, { size: "xs", c: rest.length > 0 ? "dimmed" : "", truncate: !0, children: rest.length === 0 ? firstNode.data.element.title : "[ multiple ]" })
|
|
2589
2615
|
] }),
|
|
2590
|
-
/* @__PURE__ */ jsx(
|
|
2616
|
+
showGoToSource && /* @__PURE__ */ jsx(Box, { flex: 0, children: /* @__PURE__ */ jsx(
|
|
2617
|
+
ActionIcon$2,
|
|
2618
|
+
{
|
|
2619
|
+
size: "sm",
|
|
2620
|
+
variant: "light",
|
|
2621
|
+
color: "gray",
|
|
2622
|
+
onClick: (e) => {
|
|
2623
|
+
var _a, _b;
|
|
2624
|
+
e.stopPropagation(), (_b = (_a = diagramApi.getState()).onOpenSourceElement) == null || _b.call(_a, firstNode.data.element.id);
|
|
2625
|
+
},
|
|
2626
|
+
children: /* @__PURE__ */ jsx(
|
|
2627
|
+
IconFileSymlink,
|
|
2628
|
+
{
|
|
2629
|
+
stroke: 1.2,
|
|
2630
|
+
style: {
|
|
2631
|
+
width: "70%",
|
|
2632
|
+
height: "70%"
|
|
2633
|
+
}
|
|
2634
|
+
}
|
|
2635
|
+
)
|
|
2636
|
+
}
|
|
2637
|
+
) })
|
|
2591
2638
|
] }),
|
|
2592
2639
|
showShapeOption && /* @__PURE__ */ jsx(
|
|
2593
2640
|
ShapeOption,
|
|
@@ -2645,7 +2692,7 @@ function Colors({
|
|
|
2645
2692
|
return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(TooltipGroup, { openDelay: 400, closeDelay: 300, children: [
|
|
2646
2693
|
/* @__PURE__ */ jsx(Divider, { label: "color", labelPosition: "left" }),
|
|
2647
2694
|
/* @__PURE__ */ jsx(Flex, { mt: "xs", maw: 150, gap: "xs", justify: "flex-start", align: "flex-start", direction: "row", wrap: "wrap", children: themedColors.map(({ key, value }) => /* @__PURE__ */ jsx(
|
|
2648
|
-
Tooltip,
|
|
2695
|
+
Tooltip$2,
|
|
2649
2696
|
{
|
|
2650
2697
|
label: key,
|
|
2651
2698
|
fz: "xs",
|
|
@@ -2667,7 +2714,7 @@ function Colors({
|
|
|
2667
2714
|
key
|
|
2668
2715
|
)) }),
|
|
2669
2716
|
/* @__PURE__ */ jsx(Flex, { mt: "sm", maw: 150, gap: "xs", justify: "flex-start", align: "flex-start", direction: "row", wrap: "wrap", children: colors.map(({ key, value }) => /* @__PURE__ */ jsx(
|
|
2670
|
-
Tooltip,
|
|
2717
|
+
Tooltip$2,
|
|
2671
2718
|
{
|
|
2672
2719
|
label: key,
|
|
2673
2720
|
fz: "xs",
|
|
@@ -2784,7 +2831,7 @@ function BorderStyleOption({
|
|
|
2784
2831
|
}
|
|
2785
2832
|
) });
|
|
2786
2833
|
}
|
|
2787
|
-
var panel = "_1lmzt1h0";
|
|
2834
|
+
var panel$1 = "_1lmzt1h0";
|
|
2788
2835
|
function OptionsPanel() {
|
|
2789
2836
|
const { isFocused, viewId } = useDiagramState((s) => ({
|
|
2790
2837
|
viewId: s.view.id,
|
|
@@ -2813,7 +2860,7 @@ function OptionsPanel() {
|
|
|
2813
2860
|
scale: 0.85
|
|
2814
2861
|
},
|
|
2815
2862
|
transition: { duration: 0.14 },
|
|
2816
|
-
className: clsx("react-flow__panel", panel),
|
|
2863
|
+
className: clsx("react-flow__panel", panel$1),
|
|
2817
2864
|
style: {
|
|
2818
2865
|
transformOrigin: "center right",
|
|
2819
2866
|
maxWidth: "320px"
|
|
@@ -2823,6 +2870,323 @@ function OptionsPanel() {
|
|
|
2823
2870
|
viewId
|
|
2824
2871
|
) });
|
|
2825
2872
|
}
|
|
2873
|
+
const Tooltip$1 = Tooltip$2.withProps({
|
|
2874
|
+
color: "gray",
|
|
2875
|
+
fz: "xs",
|
|
2876
|
+
position: "right",
|
|
2877
|
+
openDelay: 400,
|
|
2878
|
+
closeDelay: 100,
|
|
2879
|
+
label: "",
|
|
2880
|
+
children: null,
|
|
2881
|
+
offset: 8,
|
|
2882
|
+
transitionProps: { transition: "fade-right", duration: 200 }
|
|
2883
|
+
}), ActionIcon$1 = ActionIcon$2.withProps({
|
|
2884
|
+
className: "action-icon",
|
|
2885
|
+
variant: "light",
|
|
2886
|
+
color: "gray"
|
|
2887
|
+
});
|
|
2888
|
+
var panel = "_1snasyb0", autolayoutIcon = "_1snasyb1", autolayoutIndicator = "_1snasyb2";
|
|
2889
|
+
const ActionIcon = ActionIcon$2.withProps({
|
|
2890
|
+
size: "md",
|
|
2891
|
+
variant: "subtle",
|
|
2892
|
+
color: "gray"
|
|
2893
|
+
}), Tooltip = Tooltip$2.withProps({
|
|
2894
|
+
color: "gray",
|
|
2895
|
+
fz: "xs",
|
|
2896
|
+
position: "right",
|
|
2897
|
+
openDelay: 300,
|
|
2898
|
+
label: "",
|
|
2899
|
+
children: null,
|
|
2900
|
+
offset: 5,
|
|
2901
|
+
transitionProps: { transition: "fade", duration: 200 }
|
|
2902
|
+
}), ChangeAutoLayoutButton = (props) => {
|
|
2903
|
+
const store = useDiagramStoreApi(), [rootRef, setRootRef] = useState(null), [controlsRefs, setControlsRefs] = useState({}), autoLayout = useDiagramState((s) => s.view.autoLayout), setControlRef = (name) => (node) => {
|
|
2904
|
+
controlsRefs[name] = node, setControlsRefs(controlsRefs);
|
|
2905
|
+
}, setAutoLayout = (layout) => (event) => {
|
|
2906
|
+
var _a, _b;
|
|
2907
|
+
event.stopPropagation(), (_b = (_a = store.getState()).onChange) == null || _b.call(_a, {
|
|
2908
|
+
change: {
|
|
2909
|
+
op: "change-autolayout",
|
|
2910
|
+
layout
|
|
2911
|
+
}
|
|
2912
|
+
});
|
|
2913
|
+
};
|
|
2914
|
+
return /* @__PURE__ */ jsxs(
|
|
2915
|
+
Popover,
|
|
2916
|
+
{
|
|
2917
|
+
position: "right-start",
|
|
2918
|
+
clickOutsideEvents: [
|
|
2919
|
+
"pointerdown"
|
|
2920
|
+
],
|
|
2921
|
+
radius: "xs",
|
|
2922
|
+
shadow: "lg",
|
|
2923
|
+
offset: {
|
|
2924
|
+
mainAxis: 10
|
|
2925
|
+
},
|
|
2926
|
+
...props,
|
|
2927
|
+
children: [
|
|
2928
|
+
/* @__PURE__ */ jsx(PopoverTarget, { children: /* @__PURE__ */ jsx(
|
|
2929
|
+
ActionIcon$2,
|
|
2930
|
+
{
|
|
2931
|
+
className: "action-icon",
|
|
2932
|
+
variant: "light",
|
|
2933
|
+
color: "gray",
|
|
2934
|
+
children: /* @__PURE__ */ jsx(IconLayoutDashboard, { stroke: 1.3 })
|
|
2935
|
+
}
|
|
2936
|
+
) }),
|
|
2937
|
+
/* @__PURE__ */ jsx(PopoverDropdown, { className: "likec4-top-left-panel", p: 8, pt: 4, children: /* @__PURE__ */ jsxs(Box, { pos: "relative", ref: setRootRef, children: [
|
|
2938
|
+
/* @__PURE__ */ jsx(
|
|
2939
|
+
FloatingIndicator,
|
|
2940
|
+
{
|
|
2941
|
+
target: controlsRefs[autoLayout],
|
|
2942
|
+
parent: rootRef,
|
|
2943
|
+
className: autolayoutIndicator
|
|
2944
|
+
}
|
|
2945
|
+
),
|
|
2946
|
+
/* @__PURE__ */ jsx(Box, { mb: 10, children: /* @__PURE__ */ jsx(Text$1, { inline: !0, fz: "xs", c: "dimmed", fw: 500, children: "Auto layout:" }) }),
|
|
2947
|
+
/* @__PURE__ */ jsx(TooltipGroup, { openDelay: 100, children: /* @__PURE__ */ jsxs(Stack, { align: "center", gap: 1, children: [
|
|
2948
|
+
/* @__PURE__ */ jsx(Tooltip, { label: "Top to Bottom", children: /* @__PURE__ */ jsx(
|
|
2949
|
+
ActionIcon,
|
|
2950
|
+
{
|
|
2951
|
+
className: autolayoutIcon,
|
|
2952
|
+
ref: setControlRef("TB"),
|
|
2953
|
+
onClick: setAutoLayout("TB"),
|
|
2954
|
+
children: /* @__PURE__ */ jsx(IconArrowBigDownLines, { stroke: 1.3 })
|
|
2955
|
+
}
|
|
2956
|
+
) }),
|
|
2957
|
+
/* @__PURE__ */ jsxs(Group, { gap: 30, children: [
|
|
2958
|
+
/* @__PURE__ */ jsx(Tooltip, { label: "Left to Right", children: /* @__PURE__ */ jsx(
|
|
2959
|
+
ActionIcon,
|
|
2960
|
+
{
|
|
2961
|
+
className: autolayoutIcon,
|
|
2962
|
+
ref: setControlRef("LR"),
|
|
2963
|
+
onClick: setAutoLayout("LR"),
|
|
2964
|
+
children: /* @__PURE__ */ jsx(IconArrowBigDownLines, { stroke: 1.3, style: { rotate: "270deg" } })
|
|
2965
|
+
}
|
|
2966
|
+
) }),
|
|
2967
|
+
/* @__PURE__ */ jsx(Tooltip, { label: "Right to Left", children: /* @__PURE__ */ jsx(
|
|
2968
|
+
ActionIcon,
|
|
2969
|
+
{
|
|
2970
|
+
className: autolayoutIcon,
|
|
2971
|
+
ref: setControlRef("RL"),
|
|
2972
|
+
onClick: setAutoLayout("RL"),
|
|
2973
|
+
children: /* @__PURE__ */ jsx(IconArrowBigDownLines, { stroke: 1.3, style: { rotate: "90deg" } })
|
|
2974
|
+
}
|
|
2975
|
+
) })
|
|
2976
|
+
] }),
|
|
2977
|
+
/* @__PURE__ */ jsx(Tooltip, { label: "Bottom to Top", children: /* @__PURE__ */ jsx(
|
|
2978
|
+
ActionIcon,
|
|
2979
|
+
{
|
|
2980
|
+
className: autolayoutIcon,
|
|
2981
|
+
ref: setControlRef("BT"),
|
|
2982
|
+
onClick: setAutoLayout("BT"),
|
|
2983
|
+
children: /* @__PURE__ */ jsx(IconArrowBigDownLines, { stroke: 1.3, style: { rotate: "180deg" } })
|
|
2984
|
+
}
|
|
2985
|
+
) })
|
|
2986
|
+
] }) })
|
|
2987
|
+
] }) })
|
|
2988
|
+
]
|
|
2989
|
+
}
|
|
2990
|
+
);
|
|
2991
|
+
}, historySelector = (s) => ({
|
|
2992
|
+
showBurgerMenu: !!s.onBurgerMenuClick,
|
|
2993
|
+
hasStepBack: s.navigationHistoryIndex > 0,
|
|
2994
|
+
hasStepForward: s.navigationHistoryIndex < s.navigationHistory.length - 1
|
|
2995
|
+
}), BackwardForwardButtons = () => {
|
|
2996
|
+
const store = useDiagramStoreApi(), {
|
|
2997
|
+
showBurgerMenu,
|
|
2998
|
+
hasStepBack,
|
|
2999
|
+
hasStepForward
|
|
3000
|
+
} = useDiagramState(historySelector);
|
|
3001
|
+
return /* @__PURE__ */ jsxs(
|
|
3002
|
+
Group,
|
|
3003
|
+
{
|
|
3004
|
+
className: "likec4-navigation-panel",
|
|
3005
|
+
gap: "xs",
|
|
3006
|
+
children: [
|
|
3007
|
+
showBurgerMenu && /* @__PURE__ */ jsx(
|
|
3008
|
+
ActionIcon$1,
|
|
3009
|
+
{
|
|
3010
|
+
onClick: (e) => {
|
|
3011
|
+
var _a, _b;
|
|
3012
|
+
e.stopPropagation(), (_b = (_a = store.getState()).onBurgerMenuClick) == null || _b.call(_a);
|
|
3013
|
+
},
|
|
3014
|
+
children: /* @__PURE__ */ jsx(IconMenu2, {})
|
|
3015
|
+
}
|
|
3016
|
+
),
|
|
3017
|
+
/* @__PURE__ */ jsxs(AnimatePresence, { children: [
|
|
3018
|
+
hasStepBack && /* @__PURE__ */ jsx(
|
|
3019
|
+
m.div,
|
|
3020
|
+
{
|
|
3021
|
+
layout: !0,
|
|
3022
|
+
initial: { opacity: 0.05, transform: "translateX(-10px)" },
|
|
3023
|
+
animate: { opacity: 1, transform: "translateX(0)" },
|
|
3024
|
+
exit: {
|
|
3025
|
+
opacity: 0.05,
|
|
3026
|
+
transform: "translateX(-10px)"
|
|
3027
|
+
},
|
|
3028
|
+
children: /* @__PURE__ */ jsx(
|
|
3029
|
+
ActionIcon$1,
|
|
3030
|
+
{
|
|
3031
|
+
onClick: (e) => {
|
|
3032
|
+
e.stopPropagation(), store.getState().goBack();
|
|
3033
|
+
},
|
|
3034
|
+
children: /* @__PURE__ */ jsx(IconChevronLeft, {})
|
|
3035
|
+
}
|
|
3036
|
+
)
|
|
3037
|
+
},
|
|
3038
|
+
"back"
|
|
3039
|
+
),
|
|
3040
|
+
hasStepForward && /* @__PURE__ */ jsx(
|
|
3041
|
+
m.div,
|
|
3042
|
+
{
|
|
3043
|
+
layout: !0,
|
|
3044
|
+
initial: { opacity: 0.05, transform: "translateX(10px)" },
|
|
3045
|
+
animate: { opacity: 1, transform: "translateX(0)" },
|
|
3046
|
+
exit: {
|
|
3047
|
+
opacity: 0,
|
|
3048
|
+
transform: "translateX(10px)"
|
|
3049
|
+
},
|
|
3050
|
+
children: /* @__PURE__ */ jsx(
|
|
3051
|
+
ActionIcon$1,
|
|
3052
|
+
{
|
|
3053
|
+
onClick: (e) => {
|
|
3054
|
+
e.stopPropagation(), store.getState().goForward();
|
|
3055
|
+
},
|
|
3056
|
+
children: /* @__PURE__ */ jsx(IconChevronRight, {})
|
|
3057
|
+
}
|
|
3058
|
+
)
|
|
3059
|
+
},
|
|
3060
|
+
"forward"
|
|
3061
|
+
)
|
|
3062
|
+
] })
|
|
3063
|
+
]
|
|
3064
|
+
}
|
|
3065
|
+
);
|
|
3066
|
+
}, LayoutDriftNotification = (props) => /* @__PURE__ */ jsxs(
|
|
3067
|
+
HoverCard,
|
|
3068
|
+
{
|
|
3069
|
+
position: "right-start",
|
|
3070
|
+
openDelay: 200,
|
|
3071
|
+
closeDelay: 100,
|
|
3072
|
+
...props,
|
|
3073
|
+
children: [
|
|
3074
|
+
/* @__PURE__ */ jsx(HoverCardTarget, { children: /* @__PURE__ */ jsx(
|
|
3075
|
+
ActionIcon$1,
|
|
3076
|
+
{
|
|
3077
|
+
className: "action-icon",
|
|
3078
|
+
variant: "light",
|
|
3079
|
+
color: "orange",
|
|
3080
|
+
children: /* @__PURE__ */ jsx(IconAlertTriangle, {})
|
|
3081
|
+
}
|
|
3082
|
+
) }),
|
|
3083
|
+
/* @__PURE__ */ jsx(HoverCardDropdown, { p: "0", children: /* @__PURE__ */ jsxs(
|
|
3084
|
+
Notification,
|
|
3085
|
+
{
|
|
3086
|
+
color: "orange",
|
|
3087
|
+
withBorder: !1,
|
|
3088
|
+
withCloseButton: !1,
|
|
3089
|
+
title: "Manual layout issues",
|
|
3090
|
+
children: [
|
|
3091
|
+
/* @__PURE__ */ jsxs(Text$1, { mt: 2, size: "sm", lh: "xs", children: [
|
|
3092
|
+
"View contains new elements or their sizes have changed,",
|
|
3093
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
3094
|
+
"last manual layout can not be applied."
|
|
3095
|
+
] }),
|
|
3096
|
+
/* @__PURE__ */ jsxs(Text$1, { mt: "xs", size: "sm", lh: "xs", children: [
|
|
3097
|
+
"Update view predicates or remove ",
|
|
3098
|
+
/* @__PURE__ */ jsx(Code, { children: "@likec4-generated" })
|
|
3099
|
+
] })
|
|
3100
|
+
]
|
|
3101
|
+
}
|
|
3102
|
+
) })
|
|
3103
|
+
]
|
|
3104
|
+
}
|
|
3105
|
+
), TopLeftPanel = () => {
|
|
3106
|
+
const store = useDiagramStoreApi(), {
|
|
3107
|
+
showNavigationButtons,
|
|
3108
|
+
showFitDiagram,
|
|
3109
|
+
showLayoutDriftWarning,
|
|
3110
|
+
showChangeAutoLayout,
|
|
3111
|
+
portalProps: _portalProps,
|
|
3112
|
+
showGoToSource
|
|
3113
|
+
} = useDiagramState((s) => {
|
|
3114
|
+
const isNotActive = s.activeDynamicViewStep === null && s.focusedNodeId === null, target = s.getContainer();
|
|
3115
|
+
return {
|
|
3116
|
+
showNavigationButtons: !!s.onBurgerMenuClick || s.showNavigationButtons && !!s.onNavigateTo,
|
|
3117
|
+
showFitDiagram: s.fitViewEnabled && s.zoomable && s.viewportChanged,
|
|
3118
|
+
showLayoutDriftWarning: s.readonly !== !0 && s.view.hasLayoutDrift === !0 && isNotActive,
|
|
3119
|
+
showChangeAutoLayout: s.readonly !== !0 && !!s.onChange && isNotActive,
|
|
3120
|
+
showGoToSource: !!s.onOpenSourceView,
|
|
3121
|
+
portalProps: target ? { target } : void 0
|
|
3122
|
+
};
|
|
3123
|
+
}), portalProps = _portalProps ? { portalProps: _portalProps } : void 0;
|
|
3124
|
+
return /* @__PURE__ */ jsxs(
|
|
3125
|
+
Stack,
|
|
3126
|
+
{
|
|
3127
|
+
className: clsx(
|
|
3128
|
+
"react-flow__panel",
|
|
3129
|
+
panel,
|
|
3130
|
+
"likec4-top-left-panel"
|
|
3131
|
+
),
|
|
3132
|
+
onClick: (e) => e.stopPropagation(),
|
|
3133
|
+
gap: "xs",
|
|
3134
|
+
children: [
|
|
3135
|
+
showNavigationButtons && /* @__PURE__ */ jsx(BackwardForwardButtons, {}),
|
|
3136
|
+
showGoToSource && /* @__PURE__ */ jsx(Tooltip$1, { label: "Go to source", ...portalProps, children: /* @__PURE__ */ jsx(
|
|
3137
|
+
ActionIcon$1,
|
|
3138
|
+
{
|
|
3139
|
+
className: "action-icon",
|
|
3140
|
+
onClick: (e) => {
|
|
3141
|
+
var _a, _b;
|
|
3142
|
+
e.stopPropagation(), (_b = (_a = store.getState()).onOpenSourceView) == null || _b.call(_a);
|
|
3143
|
+
},
|
|
3144
|
+
children: /* @__PURE__ */ jsx(IconFileSymlink, { stroke: 1.5 })
|
|
3145
|
+
}
|
|
3146
|
+
) }),
|
|
3147
|
+
showChangeAutoLayout && /* @__PURE__ */ jsx(ChangeAutoLayoutButton, { ...portalProps }),
|
|
3148
|
+
/* @__PURE__ */ jsxs(AnimatePresence, { children: [
|
|
3149
|
+
showLayoutDriftWarning && /* @__PURE__ */ jsx(
|
|
3150
|
+
m.div,
|
|
3151
|
+
{
|
|
3152
|
+
initial: { opacity: 0.05, transform: "translateX(-40%)" },
|
|
3153
|
+
animate: { opacity: 1, transform: "translateX(0)" },
|
|
3154
|
+
exit: {
|
|
3155
|
+
opacity: 0,
|
|
3156
|
+
transform: "translateX(-40%)"
|
|
3157
|
+
},
|
|
3158
|
+
children: /* @__PURE__ */ jsx(LayoutDriftNotification, { ...portalProps })
|
|
3159
|
+
},
|
|
3160
|
+
"layout"
|
|
3161
|
+
),
|
|
3162
|
+
showFitDiagram && /* @__PURE__ */ jsx(
|
|
3163
|
+
m.div,
|
|
3164
|
+
{
|
|
3165
|
+
initial: { opacity: 0.05, transform: "translateX(-20%)" },
|
|
3166
|
+
animate: { opacity: 1, transform: "translateX(0)" },
|
|
3167
|
+
exit: {
|
|
3168
|
+
opacity: 0,
|
|
3169
|
+
transform: "translateX(-30%)"
|
|
3170
|
+
},
|
|
3171
|
+
children: /* @__PURE__ */ jsx(Tooltip$1, { label: "Center diagram", ...portalProps, children: /* @__PURE__ */ jsx(
|
|
3172
|
+
ActionIcon$1,
|
|
3173
|
+
{
|
|
3174
|
+
className: "action-icon",
|
|
3175
|
+
onClick: (e) => {
|
|
3176
|
+
e.stopPropagation(), store.getState().fitDiagram();
|
|
3177
|
+
},
|
|
3178
|
+
children: /* @__PURE__ */ jsx(IconFocusCentered, {})
|
|
3179
|
+
}
|
|
3180
|
+
) })
|
|
3181
|
+
},
|
|
3182
|
+
"fit-view"
|
|
3183
|
+
)
|
|
3184
|
+
] })
|
|
3185
|
+
]
|
|
3186
|
+
}
|
|
3187
|
+
);
|
|
3188
|
+
};
|
|
3189
|
+
TopLeftPanel.displayName = "TopLeftPanel";
|
|
2826
3190
|
function literalToEnum(value) {
|
|
2827
3191
|
switch (value) {
|
|
2828
3192
|
case "dots":
|
|
@@ -2845,8 +3209,7 @@ const XYFlowInner = memo(function({
|
|
|
2845
3209
|
children,
|
|
2846
3210
|
background,
|
|
2847
3211
|
controls,
|
|
2848
|
-
showDiagramTitle
|
|
2849
|
-
showNavigationButtons
|
|
3212
|
+
showDiagramTitle
|
|
2850
3213
|
}) {
|
|
2851
3214
|
const {
|
|
2852
3215
|
isDynamicView,
|
|
@@ -2862,10 +3225,10 @@ const XYFlowInner = memo(function({
|
|
|
2862
3225
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2863
3226
|
background !== "transparent" && background !== "solid" && /* @__PURE__ */ jsx(XYFlowBackground, { background }),
|
|
2864
3227
|
controls && /* @__PURE__ */ jsx(Controls, { position: "bottom-right" }),
|
|
2865
|
-
|
|
3228
|
+
/* @__PURE__ */ jsx(TopLeftPanel, {}),
|
|
3229
|
+
readonly !== !0 && /* @__PURE__ */ jsx(OptionsPanel, {}),
|
|
2866
3230
|
showDiagramTitle === !0 && !isDynamicViewActive && /* @__PURE__ */ jsx(DiagramTitlePanel, {}),
|
|
2867
3231
|
isDynamicView && enableDynamicViewWalkthrough && /* @__PURE__ */ jsx(DynamicViewWalkthrough, {}),
|
|
2868
|
-
showNavigationButtons && /* @__PURE__ */ jsx(BackwardForwardPanel, {}),
|
|
2869
3232
|
children
|
|
2870
3233
|
] });
|
|
2871
3234
|
}, shallowEqual);
|
|
@@ -2884,9 +3247,8 @@ function LikeC4Diagram({
|
|
|
2884
3247
|
controls = !1,
|
|
2885
3248
|
showElementLinks = !0,
|
|
2886
3249
|
showDiagramTitle = !0,
|
|
2887
|
-
showNavigationButtons = !1,
|
|
2888
3250
|
enableDynamicViewWalkthrough = !1,
|
|
2889
|
-
enableFocusMode =
|
|
3251
|
+
enableFocusMode = !1,
|
|
2890
3252
|
initialWidth,
|
|
2891
3253
|
initialHeight,
|
|
2892
3254
|
keepAspectRatio = !1,
|
|
@@ -2900,8 +3262,13 @@ function LikeC4Diagram({
|
|
|
2900
3262
|
onNavigateTo,
|
|
2901
3263
|
onNodeClick,
|
|
2902
3264
|
onNodeContextMenu,
|
|
2903
|
-
|
|
2904
|
-
|
|
3265
|
+
onOpenSourceElement,
|
|
3266
|
+
onOpenSourceView,
|
|
3267
|
+
onOpenSourceRelation,
|
|
3268
|
+
onBurgerMenuClick,
|
|
3269
|
+
renderIcon,
|
|
3270
|
+
where,
|
|
3271
|
+
showNavigationButtons = !!onNavigateTo
|
|
2905
3272
|
}) {
|
|
2906
3273
|
const initialRef = useRef({
|
|
2907
3274
|
defaultNodes: [],
|
|
@@ -2909,7 +3276,7 @@ function LikeC4Diagram({
|
|
|
2909
3276
|
initialWidth: initialWidth ?? view.bounds.width,
|
|
2910
3277
|
initialHeight: initialHeight ?? view.bounds.height
|
|
2911
3278
|
});
|
|
2912
|
-
return /* @__PURE__ */ jsx(EnsureMantine, { children: /* @__PURE__ */ jsx(LazyMotion, { features: domAnimation, strict: !0, children: /* @__PURE__ */ jsx(
|
|
3279
|
+
return readonly !== !0 && where && console.warn("where filter is only supported in readonly mode"), /* @__PURE__ */ jsx(EnsureMantine, { children: /* @__PURE__ */ jsx(LazyMotion, { features: domAnimation, strict: !0, children: /* @__PURE__ */ jsx(
|
|
2913
3280
|
ReactFlowProvider,
|
|
2914
3281
|
{
|
|
2915
3282
|
fitView,
|
|
@@ -2926,11 +3293,13 @@ function LikeC4Diagram({
|
|
|
2926
3293
|
fitViewEnabled: fitView,
|
|
2927
3294
|
fitViewPadding,
|
|
2928
3295
|
showElementLinks,
|
|
3296
|
+
showNavigationButtons,
|
|
2929
3297
|
nodesDraggable,
|
|
2930
3298
|
nodesSelectable,
|
|
2931
3299
|
experimentalEdgeEditing,
|
|
2932
3300
|
enableDynamicViewWalkthrough,
|
|
2933
3301
|
enableFocusMode,
|
|
3302
|
+
whereFilter: where ?? null,
|
|
2934
3303
|
renderIcon: renderIcon ?? null,
|
|
2935
3304
|
onCanvasClick: onCanvasClick ?? null,
|
|
2936
3305
|
onCanvasContextMenu: onCanvasContextMenu ?? null,
|
|
@@ -2941,14 +3310,16 @@ function LikeC4Diagram({
|
|
|
2941
3310
|
onChange: onChange ?? null,
|
|
2942
3311
|
onNavigateTo: onNavigateTo ?? null,
|
|
2943
3312
|
onCanvasDblClick: onCanvasDblClick ?? null,
|
|
2944
|
-
|
|
3313
|
+
onOpenSourceView: onOpenSourceView ?? null,
|
|
3314
|
+
onOpenSourceElement: onOpenSourceElement ?? null,
|
|
3315
|
+
onOpenSourceRelation: onOpenSourceRelation ?? null,
|
|
3316
|
+
onBurgerMenuClick: onBurgerMenuClick ?? null,
|
|
2945
3317
|
children: /* @__PURE__ */ jsx(
|
|
2946
3318
|
LikeC4DiagramInnerMemo,
|
|
2947
3319
|
{
|
|
2948
3320
|
controls,
|
|
2949
3321
|
background,
|
|
2950
|
-
showDiagramTitle
|
|
2951
|
-
showNavigationButtons
|
|
3322
|
+
showDiagramTitle
|
|
2952
3323
|
}
|
|
2953
3324
|
)
|
|
2954
3325
|
}
|
|
@@ -2959,8 +3330,7 @@ function LikeC4Diagram({
|
|
|
2959
3330
|
const LikeC4DiagramInnerMemo = memo(function({
|
|
2960
3331
|
background,
|
|
2961
3332
|
controls,
|
|
2962
|
-
showDiagramTitle
|
|
2963
|
-
showNavigationButtons
|
|
3333
|
+
showDiagramTitle
|
|
2964
3334
|
}) {
|
|
2965
3335
|
const {
|
|
2966
3336
|
isInitialized,
|
|
@@ -2988,7 +3358,6 @@ const LikeC4DiagramInnerMemo = memo(function({
|
|
|
2988
3358
|
children: /* @__PURE__ */ jsx(
|
|
2989
3359
|
XYFlowInner,
|
|
2990
3360
|
{
|
|
2991
|
-
showNavigationButtons,
|
|
2992
3361
|
showDiagramTitle,
|
|
2993
3362
|
background,
|
|
2994
3363
|
controls
|
|
@@ -3023,6 +3392,7 @@ function StaticLikeC4Diagram({
|
|
|
3023
3392
|
showElementLinks: !0,
|
|
3024
3393
|
showDiagramTitle: !1,
|
|
3025
3394
|
enableDynamicViewWalkthrough: !1,
|
|
3395
|
+
enableFocusMode: !1,
|
|
3026
3396
|
nodesSelectable: !1,
|
|
3027
3397
|
nodesDraggable: !1,
|
|
3028
3398
|
...rest
|