@likec4/diagram 1.7.2 → 1.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +755 -401
- 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 +56 -35
- 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/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.tsx +1 -1
- 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 +7 -8
- package/src/xyflow/XYFlowEvents.tsx +39 -19
- package/src/xyflow/XYFlowInner.tsx +5 -7
- 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)
|
|
@@ -77,6 +59,12 @@ const useXYStoreApi = useStoreApi, ZIndexes = {
|
|
|
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,179 @@ 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
|
+
xystore,
|
|
2020
|
+
resetLastClicked
|
|
2021
|
+
} = diagramApi.getState();
|
|
2022
|
+
resetLastClicked(), xystore.getState().resetSelectedElements(), onCanvasDblClick || event.stopPropagation(), onCanvasDblClick == null || onCanvasDblClick(event);
|
|
2023
|
+
},
|
|
2024
|
+
onPaneClick: (event) => {
|
|
2025
|
+
if (dbclickLock())
|
|
2026
|
+
return;
|
|
2027
|
+
const {
|
|
2028
|
+
focusedNodeId,
|
|
1960
2029
|
activeDynamicViewStep,
|
|
1961
2030
|
fitDiagram,
|
|
1962
2031
|
onCanvasClick,
|
|
2032
|
+
xystore,
|
|
1963
2033
|
resetLastClicked
|
|
1964
2034
|
} = diagramApi.getState();
|
|
1965
|
-
(focusedNodeId ?? activeDynamicViewStep) !== null && (fitDiagram(), onCanvasClick || event.stopPropagation()), resetLastClicked(), onCanvasClick == null || onCanvasClick(event);
|
|
2035
|
+
(focusedNodeId ?? activeDynamicViewStep) !== null && (fitDiagram(), onCanvasClick || event.stopPropagation()), resetLastClicked(), xystore.getState().resetSelectedElements(), onCanvasClick == null || onCanvasClick(event);
|
|
1966
2036
|
},
|
|
1967
2037
|
onNodeContextMenu: (event, xynode) => {
|
|
1968
2038
|
var _a, _b;
|
|
@@ -1990,22 +2060,33 @@ function useXYFlowEvents() {
|
|
|
1990
2060
|
fitDiagram,
|
|
1991
2061
|
focusOnNode,
|
|
1992
2062
|
onNodeClick,
|
|
2063
|
+
xystore,
|
|
1993
2064
|
enableFocusMode,
|
|
1994
2065
|
lastClickedNodeId,
|
|
1995
|
-
|
|
2066
|
+
nodesSelectable,
|
|
2067
|
+
setLastClickedNode,
|
|
2068
|
+
onOpenSourceElement
|
|
1996
2069
|
} = diagramApi.getState();
|
|
1997
2070
|
setLastClickedNode(xynode.id);
|
|
1998
2071
|
const shallChangeFocus = !!focusedNodeId && focusedNodeId !== xynode.id, clickedRecently = lastClickedNodeId === xynode.id && lastClickWasRecent();
|
|
1999
|
-
if (enableFocusMode) {
|
|
2000
|
-
let stopPropagation = !
|
|
2072
|
+
if (clickedRecently && onOpenSourceElement && onOpenSourceElement(xynode.data.element.id), enableFocusMode || nodesSelectable) {
|
|
2073
|
+
let stopPropagation = !0;
|
|
2001
2074
|
switch (!0) {
|
|
2002
|
-
case (!focusedNodeId && clickedRecently):
|
|
2003
|
-
case shallChangeFocus:
|
|
2004
|
-
|
|
2075
|
+
case (enableFocusMode && !focusedNodeId && clickedRecently):
|
|
2076
|
+
case (enableFocusMode && shallChangeFocus): {
|
|
2077
|
+
focusOnNode(xynode.id);
|
|
2005
2078
|
break;
|
|
2006
|
-
|
|
2007
|
-
|
|
2079
|
+
}
|
|
2080
|
+
case (enableFocusMode && focusedNodeId === xynode.id && clickedRecently): {
|
|
2081
|
+
fitDiagram();
|
|
2082
|
+
break;
|
|
2083
|
+
}
|
|
2084
|
+
case nodesSelectable: {
|
|
2085
|
+
xystore.getState().addSelectedNodes([xynode.id]);
|
|
2008
2086
|
break;
|
|
2087
|
+
}
|
|
2088
|
+
default:
|
|
2089
|
+
stopPropagation = !1;
|
|
2009
2090
|
}
|
|
2010
2091
|
!onNodeClick && stopPropagation && event.stopPropagation();
|
|
2011
2092
|
}
|
|
@@ -2033,6 +2114,8 @@ function useXYFlowEvents() {
|
|
|
2033
2114
|
activateDynamicStep,
|
|
2034
2115
|
activeDynamicViewStep,
|
|
2035
2116
|
focusedNodeId,
|
|
2117
|
+
xystore,
|
|
2118
|
+
nodesSelectable,
|
|
2036
2119
|
focusOnNode,
|
|
2037
2120
|
onEdgeClick,
|
|
2038
2121
|
setLastClickedEdge
|
|
@@ -2046,7 +2129,7 @@ function useXYFlowEvents() {
|
|
|
2046
2129
|
return;
|
|
2047
2130
|
}
|
|
2048
2131
|
}
|
|
2049
|
-
isEdgeOfFocusedNode
|
|
2132
|
+
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
2133
|
edge: xyedge.data.edge,
|
|
2051
2134
|
xyedge,
|
|
2052
2135
|
event
|
|
@@ -2206,7 +2289,7 @@ function XYFlow({
|
|
|
2206
2289
|
onNodeDragStop: layoutConstraints.onNodeDragStop
|
|
2207
2290
|
},
|
|
2208
2291
|
nodeDragThreshold: 3,
|
|
2209
|
-
zoomOnDoubleClick:
|
|
2292
|
+
zoomOnDoubleClick: zoomable,
|
|
2210
2293
|
elevateNodesOnSelect: !1,
|
|
2211
2294
|
selectNodesOnDrag: !1,
|
|
2212
2295
|
onNodesChange,
|
|
@@ -2236,82 +2319,6 @@ function XYFlow({
|
|
|
2236
2319
|
}
|
|
2237
2320
|
);
|
|
2238
2321
|
}
|
|
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
2322
|
var container$1 = "hbkbtj0", card = "hbkbtj1", title = "hbkbtj2", description = "hbkbtj3";
|
|
2316
2323
|
const selector = (s) => ({
|
|
2317
2324
|
id: s.view.id,
|
|
@@ -2573,7 +2580,7 @@ const {
|
|
|
2573
2580
|
return null;
|
|
2574
2581
|
if (nodes.length !== selectedNodeIds.length)
|
|
2575
2582
|
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) => {
|
|
2583
|
+
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
2584
|
const targets = nodes.map((node) => node.data.element.id);
|
|
2578
2585
|
invariant(hasAtLeast$1(targets, 1), "At least one target is required"), diagramApi.getState().triggerChangeElementStyle({
|
|
2579
2586
|
op: "change-element-style",
|
|
@@ -2582,12 +2589,36 @@ const {
|
|
|
2582
2589
|
});
|
|
2583
2590
|
};
|
|
2584
2591
|
return /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
|
|
2585
|
-
/* @__PURE__ */ jsxs("
|
|
2586
|
-
/* @__PURE__ */ jsxs(
|
|
2587
|
-
"
|
|
2588
|
-
|
|
2592
|
+
/* @__PURE__ */ jsxs(Group, { wrap: "nowrap", align: "flex-start", children: [
|
|
2593
|
+
/* @__PURE__ */ jsxs(Box, { flex: 1, children: [
|
|
2594
|
+
/* @__PURE__ */ jsxs(Text$1, { fz: rem(9), fw: "500", c: "dimmed", children: [
|
|
2595
|
+
"ELEMENT",
|
|
2596
|
+
rest.length > 0 ? "S" : ""
|
|
2597
|
+
] }),
|
|
2598
|
+
/* @__PURE__ */ jsx(Text$1, { size: "xs", c: rest.length > 0 ? "dimmed" : "", truncate: !0, children: rest.length === 0 ? firstNode.data.element.title : "[ multiple ]" })
|
|
2589
2599
|
] }),
|
|
2590
|
-
/* @__PURE__ */ jsx(
|
|
2600
|
+
showGoToSource && /* @__PURE__ */ jsx(Box, { flex: 0, children: /* @__PURE__ */ jsx(
|
|
2601
|
+
ActionIcon$2,
|
|
2602
|
+
{
|
|
2603
|
+
size: "sm",
|
|
2604
|
+
variant: "light",
|
|
2605
|
+
color: "gray",
|
|
2606
|
+
onClick: (e) => {
|
|
2607
|
+
var _a, _b;
|
|
2608
|
+
e.stopPropagation(), (_b = (_a = diagramApi.getState()).onOpenSourceElement) == null || _b.call(_a, firstNode.data.element.id);
|
|
2609
|
+
},
|
|
2610
|
+
children: /* @__PURE__ */ jsx(
|
|
2611
|
+
IconFileSymlink,
|
|
2612
|
+
{
|
|
2613
|
+
stroke: 1.2,
|
|
2614
|
+
style: {
|
|
2615
|
+
width: "70%",
|
|
2616
|
+
height: "70%"
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
)
|
|
2620
|
+
}
|
|
2621
|
+
) })
|
|
2591
2622
|
] }),
|
|
2592
2623
|
showShapeOption && /* @__PURE__ */ jsx(
|
|
2593
2624
|
ShapeOption,
|
|
@@ -2645,7 +2676,7 @@ function Colors({
|
|
|
2645
2676
|
return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(TooltipGroup, { openDelay: 400, closeDelay: 300, children: [
|
|
2646
2677
|
/* @__PURE__ */ jsx(Divider, { label: "color", labelPosition: "left" }),
|
|
2647
2678
|
/* @__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,
|
|
2679
|
+
Tooltip$2,
|
|
2649
2680
|
{
|
|
2650
2681
|
label: key,
|
|
2651
2682
|
fz: "xs",
|
|
@@ -2667,7 +2698,7 @@ function Colors({
|
|
|
2667
2698
|
key
|
|
2668
2699
|
)) }),
|
|
2669
2700
|
/* @__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,
|
|
2701
|
+
Tooltip$2,
|
|
2671
2702
|
{
|
|
2672
2703
|
label: key,
|
|
2673
2704
|
fz: "xs",
|
|
@@ -2784,7 +2815,7 @@ function BorderStyleOption({
|
|
|
2784
2815
|
}
|
|
2785
2816
|
) });
|
|
2786
2817
|
}
|
|
2787
|
-
var panel = "_1lmzt1h0";
|
|
2818
|
+
var panel$1 = "_1lmzt1h0";
|
|
2788
2819
|
function OptionsPanel() {
|
|
2789
2820
|
const { isFocused, viewId } = useDiagramState((s) => ({
|
|
2790
2821
|
viewId: s.view.id,
|
|
@@ -2813,7 +2844,7 @@ function OptionsPanel() {
|
|
|
2813
2844
|
scale: 0.85
|
|
2814
2845
|
},
|
|
2815
2846
|
transition: { duration: 0.14 },
|
|
2816
|
-
className: clsx("react-flow__panel", panel),
|
|
2847
|
+
className: clsx("react-flow__panel", panel$1),
|
|
2817
2848
|
style: {
|
|
2818
2849
|
transformOrigin: "center right",
|
|
2819
2850
|
maxWidth: "320px"
|
|
@@ -2823,6 +2854,323 @@ function OptionsPanel() {
|
|
|
2823
2854
|
viewId
|
|
2824
2855
|
) });
|
|
2825
2856
|
}
|
|
2857
|
+
const Tooltip$1 = Tooltip$2.withProps({
|
|
2858
|
+
color: "gray",
|
|
2859
|
+
fz: "xs",
|
|
2860
|
+
position: "right",
|
|
2861
|
+
openDelay: 400,
|
|
2862
|
+
closeDelay: 100,
|
|
2863
|
+
label: "",
|
|
2864
|
+
children: null,
|
|
2865
|
+
offset: 8,
|
|
2866
|
+
transitionProps: { transition: "fade-right", duration: 200 }
|
|
2867
|
+
}), ActionIcon$1 = ActionIcon$2.withProps({
|
|
2868
|
+
className: "action-icon",
|
|
2869
|
+
variant: "light",
|
|
2870
|
+
color: "gray"
|
|
2871
|
+
});
|
|
2872
|
+
var panel = "_1snasyb0", autolayoutIcon = "_1snasyb1", autolayoutIndicator = "_1snasyb2";
|
|
2873
|
+
const ActionIcon = ActionIcon$2.withProps({
|
|
2874
|
+
size: "md",
|
|
2875
|
+
variant: "subtle",
|
|
2876
|
+
color: "gray"
|
|
2877
|
+
}), Tooltip = Tooltip$2.withProps({
|
|
2878
|
+
color: "gray",
|
|
2879
|
+
fz: "xs",
|
|
2880
|
+
position: "right",
|
|
2881
|
+
openDelay: 300,
|
|
2882
|
+
label: "",
|
|
2883
|
+
children: null,
|
|
2884
|
+
offset: 5,
|
|
2885
|
+
transitionProps: { transition: "fade", duration: 200 }
|
|
2886
|
+
}), ChangeAutoLayoutButton = (props) => {
|
|
2887
|
+
const store = useDiagramStoreApi(), [rootRef, setRootRef] = useState(null), [controlsRefs, setControlsRefs] = useState({}), autoLayout = useDiagramState((s) => s.view.autoLayout), setControlRef = (name) => (node) => {
|
|
2888
|
+
controlsRefs[name] = node, setControlsRefs(controlsRefs);
|
|
2889
|
+
}, setAutoLayout = (layout) => (event) => {
|
|
2890
|
+
var _a, _b;
|
|
2891
|
+
event.stopPropagation(), (_b = (_a = store.getState()).onChange) == null || _b.call(_a, {
|
|
2892
|
+
change: {
|
|
2893
|
+
op: "change-autolayout",
|
|
2894
|
+
layout
|
|
2895
|
+
}
|
|
2896
|
+
});
|
|
2897
|
+
};
|
|
2898
|
+
return /* @__PURE__ */ jsxs(
|
|
2899
|
+
Popover,
|
|
2900
|
+
{
|
|
2901
|
+
position: "right-start",
|
|
2902
|
+
clickOutsideEvents: [
|
|
2903
|
+
"pointerdown"
|
|
2904
|
+
],
|
|
2905
|
+
radius: "xs",
|
|
2906
|
+
shadow: "lg",
|
|
2907
|
+
offset: {
|
|
2908
|
+
mainAxis: 10
|
|
2909
|
+
},
|
|
2910
|
+
...props,
|
|
2911
|
+
children: [
|
|
2912
|
+
/* @__PURE__ */ jsx(PopoverTarget, { children: /* @__PURE__ */ jsx(
|
|
2913
|
+
ActionIcon$2,
|
|
2914
|
+
{
|
|
2915
|
+
className: "action-icon",
|
|
2916
|
+
variant: "light",
|
|
2917
|
+
color: "gray",
|
|
2918
|
+
children: /* @__PURE__ */ jsx(IconLayoutDashboard, { stroke: 1.3 })
|
|
2919
|
+
}
|
|
2920
|
+
) }),
|
|
2921
|
+
/* @__PURE__ */ jsx(PopoverDropdown, { className: "likec4-top-left-panel", p: 8, pt: 4, children: /* @__PURE__ */ jsxs(Box, { pos: "relative", ref: setRootRef, children: [
|
|
2922
|
+
/* @__PURE__ */ jsx(
|
|
2923
|
+
FloatingIndicator,
|
|
2924
|
+
{
|
|
2925
|
+
target: controlsRefs[autoLayout],
|
|
2926
|
+
parent: rootRef,
|
|
2927
|
+
className: autolayoutIndicator
|
|
2928
|
+
}
|
|
2929
|
+
),
|
|
2930
|
+
/* @__PURE__ */ jsx(Box, { mb: 10, children: /* @__PURE__ */ jsx(Text$1, { inline: !0, fz: "xs", c: "dimmed", fw: 500, children: "Auto layout:" }) }),
|
|
2931
|
+
/* @__PURE__ */ jsx(TooltipGroup, { openDelay: 100, children: /* @__PURE__ */ jsxs(Stack, { align: "center", gap: 1, children: [
|
|
2932
|
+
/* @__PURE__ */ jsx(Tooltip, { label: "Top to Bottom", children: /* @__PURE__ */ jsx(
|
|
2933
|
+
ActionIcon,
|
|
2934
|
+
{
|
|
2935
|
+
className: autolayoutIcon,
|
|
2936
|
+
ref: setControlRef("TB"),
|
|
2937
|
+
onClick: setAutoLayout("TB"),
|
|
2938
|
+
children: /* @__PURE__ */ jsx(IconArrowBigDownLines, { stroke: 1.3 })
|
|
2939
|
+
}
|
|
2940
|
+
) }),
|
|
2941
|
+
/* @__PURE__ */ jsxs(Group, { gap: 30, children: [
|
|
2942
|
+
/* @__PURE__ */ jsx(Tooltip, { label: "Left to Right", children: /* @__PURE__ */ jsx(
|
|
2943
|
+
ActionIcon,
|
|
2944
|
+
{
|
|
2945
|
+
className: autolayoutIcon,
|
|
2946
|
+
ref: setControlRef("LR"),
|
|
2947
|
+
onClick: setAutoLayout("LR"),
|
|
2948
|
+
children: /* @__PURE__ */ jsx(IconArrowBigDownLines, { stroke: 1.3, style: { rotate: "270deg" } })
|
|
2949
|
+
}
|
|
2950
|
+
) }),
|
|
2951
|
+
/* @__PURE__ */ jsx(Tooltip, { label: "Right to Left", children: /* @__PURE__ */ jsx(
|
|
2952
|
+
ActionIcon,
|
|
2953
|
+
{
|
|
2954
|
+
className: autolayoutIcon,
|
|
2955
|
+
ref: setControlRef("RL"),
|
|
2956
|
+
onClick: setAutoLayout("RL"),
|
|
2957
|
+
children: /* @__PURE__ */ jsx(IconArrowBigDownLines, { stroke: 1.3, style: { rotate: "90deg" } })
|
|
2958
|
+
}
|
|
2959
|
+
) })
|
|
2960
|
+
] }),
|
|
2961
|
+
/* @__PURE__ */ jsx(Tooltip, { label: "Bottom to Top", children: /* @__PURE__ */ jsx(
|
|
2962
|
+
ActionIcon,
|
|
2963
|
+
{
|
|
2964
|
+
className: autolayoutIcon,
|
|
2965
|
+
ref: setControlRef("BT"),
|
|
2966
|
+
onClick: setAutoLayout("BT"),
|
|
2967
|
+
children: /* @__PURE__ */ jsx(IconArrowBigDownLines, { stroke: 1.3, style: { rotate: "180deg" } })
|
|
2968
|
+
}
|
|
2969
|
+
) })
|
|
2970
|
+
] }) })
|
|
2971
|
+
] }) })
|
|
2972
|
+
]
|
|
2973
|
+
}
|
|
2974
|
+
);
|
|
2975
|
+
}, historySelector = (s) => ({
|
|
2976
|
+
showBurgerMenu: !!s.onBurgerMenuClick,
|
|
2977
|
+
hasStepBack: s.navigationHistoryIndex > 0,
|
|
2978
|
+
hasStepForward: s.navigationHistoryIndex < s.navigationHistory.length - 1
|
|
2979
|
+
}), BackwardForwardButtons = () => {
|
|
2980
|
+
const store = useDiagramStoreApi(), {
|
|
2981
|
+
showBurgerMenu,
|
|
2982
|
+
hasStepBack,
|
|
2983
|
+
hasStepForward
|
|
2984
|
+
} = useDiagramState(historySelector);
|
|
2985
|
+
return /* @__PURE__ */ jsxs(
|
|
2986
|
+
Group,
|
|
2987
|
+
{
|
|
2988
|
+
className: "likec4-navigation-panel",
|
|
2989
|
+
gap: "xs",
|
|
2990
|
+
children: [
|
|
2991
|
+
showBurgerMenu && /* @__PURE__ */ jsx(
|
|
2992
|
+
ActionIcon$1,
|
|
2993
|
+
{
|
|
2994
|
+
onClick: (e) => {
|
|
2995
|
+
var _a, _b;
|
|
2996
|
+
e.stopPropagation(), (_b = (_a = store.getState()).onBurgerMenuClick) == null || _b.call(_a);
|
|
2997
|
+
},
|
|
2998
|
+
children: /* @__PURE__ */ jsx(IconMenu2, {})
|
|
2999
|
+
}
|
|
3000
|
+
),
|
|
3001
|
+
/* @__PURE__ */ jsxs(AnimatePresence, { children: [
|
|
3002
|
+
hasStepBack && /* @__PURE__ */ jsx(
|
|
3003
|
+
m.div,
|
|
3004
|
+
{
|
|
3005
|
+
layout: !0,
|
|
3006
|
+
initial: { opacity: 0.05, transform: "translateX(-10px)" },
|
|
3007
|
+
animate: { opacity: 1, transform: "translateX(0)" },
|
|
3008
|
+
exit: {
|
|
3009
|
+
opacity: 0.05,
|
|
3010
|
+
transform: "translateX(-10px)"
|
|
3011
|
+
},
|
|
3012
|
+
children: /* @__PURE__ */ jsx(
|
|
3013
|
+
ActionIcon$1,
|
|
3014
|
+
{
|
|
3015
|
+
onClick: (e) => {
|
|
3016
|
+
e.stopPropagation(), store.getState().goBack();
|
|
3017
|
+
},
|
|
3018
|
+
children: /* @__PURE__ */ jsx(IconChevronLeft, {})
|
|
3019
|
+
}
|
|
3020
|
+
)
|
|
3021
|
+
},
|
|
3022
|
+
"back"
|
|
3023
|
+
),
|
|
3024
|
+
hasStepForward && /* @__PURE__ */ jsx(
|
|
3025
|
+
m.div,
|
|
3026
|
+
{
|
|
3027
|
+
layout: !0,
|
|
3028
|
+
initial: { opacity: 0.05, transform: "translateX(10px)" },
|
|
3029
|
+
animate: { opacity: 1, transform: "translateX(0)" },
|
|
3030
|
+
exit: {
|
|
3031
|
+
opacity: 0,
|
|
3032
|
+
transform: "translateX(10px)"
|
|
3033
|
+
},
|
|
3034
|
+
children: /* @__PURE__ */ jsx(
|
|
3035
|
+
ActionIcon$1,
|
|
3036
|
+
{
|
|
3037
|
+
onClick: (e) => {
|
|
3038
|
+
e.stopPropagation(), store.getState().goForward();
|
|
3039
|
+
},
|
|
3040
|
+
children: /* @__PURE__ */ jsx(IconChevronRight, {})
|
|
3041
|
+
}
|
|
3042
|
+
)
|
|
3043
|
+
},
|
|
3044
|
+
"forward"
|
|
3045
|
+
)
|
|
3046
|
+
] })
|
|
3047
|
+
]
|
|
3048
|
+
}
|
|
3049
|
+
);
|
|
3050
|
+
}, LayoutDriftNotification = (props) => /* @__PURE__ */ jsxs(
|
|
3051
|
+
HoverCard,
|
|
3052
|
+
{
|
|
3053
|
+
position: "right-start",
|
|
3054
|
+
openDelay: 200,
|
|
3055
|
+
closeDelay: 100,
|
|
3056
|
+
...props,
|
|
3057
|
+
children: [
|
|
3058
|
+
/* @__PURE__ */ jsx(HoverCardTarget, { children: /* @__PURE__ */ jsx(
|
|
3059
|
+
ActionIcon$1,
|
|
3060
|
+
{
|
|
3061
|
+
className: "action-icon",
|
|
3062
|
+
variant: "light",
|
|
3063
|
+
color: "orange",
|
|
3064
|
+
children: /* @__PURE__ */ jsx(IconAlertTriangle, {})
|
|
3065
|
+
}
|
|
3066
|
+
) }),
|
|
3067
|
+
/* @__PURE__ */ jsx(HoverCardDropdown, { p: "0", children: /* @__PURE__ */ jsxs(
|
|
3068
|
+
Notification,
|
|
3069
|
+
{
|
|
3070
|
+
color: "orange",
|
|
3071
|
+
withBorder: !1,
|
|
3072
|
+
withCloseButton: !1,
|
|
3073
|
+
title: "Manual layout issues",
|
|
3074
|
+
children: [
|
|
3075
|
+
/* @__PURE__ */ jsxs(Text$1, { mt: 2, size: "sm", lh: "xs", children: [
|
|
3076
|
+
"View contains new elements or their sizes have changed,",
|
|
3077
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
3078
|
+
"last manual layout can not be applied."
|
|
3079
|
+
] }),
|
|
3080
|
+
/* @__PURE__ */ jsxs(Text$1, { mt: "xs", size: "sm", lh: "xs", children: [
|
|
3081
|
+
"Update view predicates or remove ",
|
|
3082
|
+
/* @__PURE__ */ jsx(Code, { children: "@likec4-generated" })
|
|
3083
|
+
] })
|
|
3084
|
+
]
|
|
3085
|
+
}
|
|
3086
|
+
) })
|
|
3087
|
+
]
|
|
3088
|
+
}
|
|
3089
|
+
), TopLeftPanel = () => {
|
|
3090
|
+
const store = useDiagramStoreApi(), {
|
|
3091
|
+
showNavigationButtons,
|
|
3092
|
+
showFitDiagram,
|
|
3093
|
+
showLayoutDriftWarning,
|
|
3094
|
+
showChangeAutoLayout,
|
|
3095
|
+
portalProps: _portalProps,
|
|
3096
|
+
showGoToSource
|
|
3097
|
+
} = useDiagramState((s) => {
|
|
3098
|
+
const isNotActive = s.activeDynamicViewStep === null && s.focusedNodeId === null, target = s.getContainer();
|
|
3099
|
+
return {
|
|
3100
|
+
showNavigationButtons: !!s.onBurgerMenuClick || s.showNavigationButtons && !!s.onNavigateTo,
|
|
3101
|
+
showFitDiagram: s.fitViewEnabled && s.zoomable && s.viewportChanged,
|
|
3102
|
+
showLayoutDriftWarning: s.readonly !== !0 && s.view.hasLayoutDrift === !0 && isNotActive,
|
|
3103
|
+
showChangeAutoLayout: s.readonly !== !0 && !!s.onChange && isNotActive,
|
|
3104
|
+
showGoToSource: !!s.onOpenSourceView,
|
|
3105
|
+
portalProps: target ? { target } : void 0
|
|
3106
|
+
};
|
|
3107
|
+
}), portalProps = _portalProps ? { portalProps: _portalProps } : void 0;
|
|
3108
|
+
return /* @__PURE__ */ jsxs(
|
|
3109
|
+
Stack,
|
|
3110
|
+
{
|
|
3111
|
+
className: clsx(
|
|
3112
|
+
"react-flow__panel",
|
|
3113
|
+
panel,
|
|
3114
|
+
"likec4-top-left-panel"
|
|
3115
|
+
),
|
|
3116
|
+
onClick: (e) => e.stopPropagation(),
|
|
3117
|
+
gap: "xs",
|
|
3118
|
+
children: [
|
|
3119
|
+
showNavigationButtons && /* @__PURE__ */ jsx(BackwardForwardButtons, {}),
|
|
3120
|
+
showGoToSource && /* @__PURE__ */ jsx(Tooltip$1, { label: "Go to source", ...portalProps, children: /* @__PURE__ */ jsx(
|
|
3121
|
+
ActionIcon$1,
|
|
3122
|
+
{
|
|
3123
|
+
className: "action-icon",
|
|
3124
|
+
onClick: (e) => {
|
|
3125
|
+
var _a, _b;
|
|
3126
|
+
e.stopPropagation(), (_b = (_a = store.getState()).onOpenSourceView) == null || _b.call(_a);
|
|
3127
|
+
},
|
|
3128
|
+
children: /* @__PURE__ */ jsx(IconFileSymlink, { stroke: 1.5 })
|
|
3129
|
+
}
|
|
3130
|
+
) }),
|
|
3131
|
+
showChangeAutoLayout && /* @__PURE__ */ jsx(ChangeAutoLayoutButton, { ...portalProps }),
|
|
3132
|
+
/* @__PURE__ */ jsxs(AnimatePresence, { children: [
|
|
3133
|
+
showLayoutDriftWarning && /* @__PURE__ */ jsx(
|
|
3134
|
+
m.div,
|
|
3135
|
+
{
|
|
3136
|
+
initial: { opacity: 0.05, transform: "translateX(-40%)" },
|
|
3137
|
+
animate: { opacity: 1, transform: "translateX(0)" },
|
|
3138
|
+
exit: {
|
|
3139
|
+
opacity: 0,
|
|
3140
|
+
transform: "translateX(-40%)"
|
|
3141
|
+
},
|
|
3142
|
+
children: /* @__PURE__ */ jsx(LayoutDriftNotification, { ...portalProps })
|
|
3143
|
+
},
|
|
3144
|
+
"layout"
|
|
3145
|
+
),
|
|
3146
|
+
showFitDiagram && /* @__PURE__ */ jsx(
|
|
3147
|
+
m.div,
|
|
3148
|
+
{
|
|
3149
|
+
initial: { opacity: 0.05, transform: "translateX(-20%)" },
|
|
3150
|
+
animate: { opacity: 1, transform: "translateX(0)" },
|
|
3151
|
+
exit: {
|
|
3152
|
+
opacity: 0,
|
|
3153
|
+
transform: "translateX(-30%)"
|
|
3154
|
+
},
|
|
3155
|
+
children: /* @__PURE__ */ jsx(Tooltip$1, { label: "Center diagram", ...portalProps, children: /* @__PURE__ */ jsx(
|
|
3156
|
+
ActionIcon$1,
|
|
3157
|
+
{
|
|
3158
|
+
className: "action-icon",
|
|
3159
|
+
onClick: (e) => {
|
|
3160
|
+
e.stopPropagation(), store.getState().fitDiagram();
|
|
3161
|
+
},
|
|
3162
|
+
children: /* @__PURE__ */ jsx(IconFocusCentered, {})
|
|
3163
|
+
}
|
|
3164
|
+
) })
|
|
3165
|
+
},
|
|
3166
|
+
"fit-view"
|
|
3167
|
+
)
|
|
3168
|
+
] })
|
|
3169
|
+
]
|
|
3170
|
+
}
|
|
3171
|
+
);
|
|
3172
|
+
};
|
|
3173
|
+
TopLeftPanel.displayName = "TopLeftPanel";
|
|
2826
3174
|
function literalToEnum(value) {
|
|
2827
3175
|
switch (value) {
|
|
2828
3176
|
case "dots":
|
|
@@ -2845,8 +3193,7 @@ const XYFlowInner = memo(function({
|
|
|
2845
3193
|
children,
|
|
2846
3194
|
background,
|
|
2847
3195
|
controls,
|
|
2848
|
-
showDiagramTitle
|
|
2849
|
-
showNavigationButtons
|
|
3196
|
+
showDiagramTitle
|
|
2850
3197
|
}) {
|
|
2851
3198
|
const {
|
|
2852
3199
|
isDynamicView,
|
|
@@ -2862,10 +3209,10 @@ const XYFlowInner = memo(function({
|
|
|
2862
3209
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2863
3210
|
background !== "transparent" && background !== "solid" && /* @__PURE__ */ jsx(XYFlowBackground, { background }),
|
|
2864
3211
|
controls && /* @__PURE__ */ jsx(Controls, { position: "bottom-right" }),
|
|
2865
|
-
|
|
3212
|
+
/* @__PURE__ */ jsx(TopLeftPanel, {}),
|
|
3213
|
+
readonly !== !0 && /* @__PURE__ */ jsx(OptionsPanel, {}),
|
|
2866
3214
|
showDiagramTitle === !0 && !isDynamicViewActive && /* @__PURE__ */ jsx(DiagramTitlePanel, {}),
|
|
2867
3215
|
isDynamicView && enableDynamicViewWalkthrough && /* @__PURE__ */ jsx(DynamicViewWalkthrough, {}),
|
|
2868
|
-
showNavigationButtons && /* @__PURE__ */ jsx(BackwardForwardPanel, {}),
|
|
2869
3216
|
children
|
|
2870
3217
|
] });
|
|
2871
3218
|
}, shallowEqual);
|
|
@@ -2884,9 +3231,8 @@ function LikeC4Diagram({
|
|
|
2884
3231
|
controls = !1,
|
|
2885
3232
|
showElementLinks = !0,
|
|
2886
3233
|
showDiagramTitle = !0,
|
|
2887
|
-
showNavigationButtons = !1,
|
|
2888
3234
|
enableDynamicViewWalkthrough = !1,
|
|
2889
|
-
enableFocusMode =
|
|
3235
|
+
enableFocusMode = !1,
|
|
2890
3236
|
initialWidth,
|
|
2891
3237
|
initialHeight,
|
|
2892
3238
|
keepAspectRatio = !1,
|
|
@@ -2900,8 +3246,13 @@ function LikeC4Diagram({
|
|
|
2900
3246
|
onNavigateTo,
|
|
2901
3247
|
onNodeClick,
|
|
2902
3248
|
onNodeContextMenu,
|
|
2903
|
-
|
|
2904
|
-
|
|
3249
|
+
onOpenSourceElement,
|
|
3250
|
+
onOpenSourceView,
|
|
3251
|
+
onOpenSourceRelation,
|
|
3252
|
+
onBurgerMenuClick,
|
|
3253
|
+
renderIcon,
|
|
3254
|
+
where,
|
|
3255
|
+
showNavigationButtons = !!onNavigateTo
|
|
2905
3256
|
}) {
|
|
2906
3257
|
const initialRef = useRef({
|
|
2907
3258
|
defaultNodes: [],
|
|
@@ -2909,7 +3260,7 @@ function LikeC4Diagram({
|
|
|
2909
3260
|
initialWidth: initialWidth ?? view.bounds.width,
|
|
2910
3261
|
initialHeight: initialHeight ?? view.bounds.height
|
|
2911
3262
|
});
|
|
2912
|
-
return /* @__PURE__ */ jsx(EnsureMantine, { children: /* @__PURE__ */ jsx(LazyMotion, { features: domAnimation, strict: !0, children: /* @__PURE__ */ jsx(
|
|
3263
|
+
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
3264
|
ReactFlowProvider,
|
|
2914
3265
|
{
|
|
2915
3266
|
fitView,
|
|
@@ -2926,11 +3277,13 @@ function LikeC4Diagram({
|
|
|
2926
3277
|
fitViewEnabled: fitView,
|
|
2927
3278
|
fitViewPadding,
|
|
2928
3279
|
showElementLinks,
|
|
3280
|
+
showNavigationButtons,
|
|
2929
3281
|
nodesDraggable,
|
|
2930
3282
|
nodesSelectable,
|
|
2931
3283
|
experimentalEdgeEditing,
|
|
2932
3284
|
enableDynamicViewWalkthrough,
|
|
2933
3285
|
enableFocusMode,
|
|
3286
|
+
whereFilter: where ?? null,
|
|
2934
3287
|
renderIcon: renderIcon ?? null,
|
|
2935
3288
|
onCanvasClick: onCanvasClick ?? null,
|
|
2936
3289
|
onCanvasContextMenu: onCanvasContextMenu ?? null,
|
|
@@ -2941,14 +3294,16 @@ function LikeC4Diagram({
|
|
|
2941
3294
|
onChange: onChange ?? null,
|
|
2942
3295
|
onNavigateTo: onNavigateTo ?? null,
|
|
2943
3296
|
onCanvasDblClick: onCanvasDblClick ?? null,
|
|
2944
|
-
|
|
3297
|
+
onOpenSourceView: onOpenSourceView ?? null,
|
|
3298
|
+
onOpenSourceElement: onOpenSourceElement ?? null,
|
|
3299
|
+
onOpenSourceRelation: onOpenSourceRelation ?? null,
|
|
3300
|
+
onBurgerMenuClick: onBurgerMenuClick ?? null,
|
|
2945
3301
|
children: /* @__PURE__ */ jsx(
|
|
2946
3302
|
LikeC4DiagramInnerMemo,
|
|
2947
3303
|
{
|
|
2948
3304
|
controls,
|
|
2949
3305
|
background,
|
|
2950
|
-
showDiagramTitle
|
|
2951
|
-
showNavigationButtons
|
|
3306
|
+
showDiagramTitle
|
|
2952
3307
|
}
|
|
2953
3308
|
)
|
|
2954
3309
|
}
|
|
@@ -2959,8 +3314,7 @@ function LikeC4Diagram({
|
|
|
2959
3314
|
const LikeC4DiagramInnerMemo = memo(function({
|
|
2960
3315
|
background,
|
|
2961
3316
|
controls,
|
|
2962
|
-
showDiagramTitle
|
|
2963
|
-
showNavigationButtons
|
|
3317
|
+
showDiagramTitle
|
|
2964
3318
|
}) {
|
|
2965
3319
|
const {
|
|
2966
3320
|
isInitialized,
|
|
@@ -2988,7 +3342,6 @@ const LikeC4DiagramInnerMemo = memo(function({
|
|
|
2988
3342
|
children: /* @__PURE__ */ jsx(
|
|
2989
3343
|
XYFlowInner,
|
|
2990
3344
|
{
|
|
2991
|
-
showNavigationButtons,
|
|
2992
3345
|
showDiagramTitle,
|
|
2993
3346
|
background,
|
|
2994
3347
|
controls
|
|
@@ -3023,6 +3376,7 @@ function StaticLikeC4Diagram({
|
|
|
3023
3376
|
showElementLinks: !0,
|
|
3024
3377
|
showDiagramTitle: !1,
|
|
3025
3378
|
enableDynamicViewWalkthrough: !1,
|
|
3379
|
+
enableFocusMode: !1,
|
|
3026
3380
|
nodesSelectable: !1,
|
|
3027
3381
|
nodesDraggable: !1,
|
|
3028
3382
|
...rest
|