@likec4/diagram 1.7.4 → 1.8.1
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 +5 -0
- package/dist/index.mjs +289 -45
- package/dist/mantine.css.d.ts +2 -0
- package/dist/state/DiagramContext.d.ts +18 -0
- package/dist/state/diagramStore.d.ts +23 -3
- package/dist/style.css +154 -81
- package/dist/ui/notation/NotationPanel.css.d.ts +6 -0
- package/dist/ui/notation/NotationPanel.d.ts +1 -0
- package/dist/ui/notation/index.d.ts +1 -0
- package/package.json +15 -15
- package/src/LikeC4Diagram.props.ts +6 -0
- package/src/LikeC4Diagram.tsx +2 -0
- package/src/StaticLikeC4Diagram.tsx +1 -0
- package/src/globals.css.ts +9 -29
- package/src/mantine.css.ts +3 -0
- package/src/state/diagram-to-xyflow.ts +8 -13
- package/src/state/diagramStore.ts +31 -4
- package/src/ui/DiagramTitlePanel.css.ts +8 -6
- package/src/ui/DiagramTitlePanel.tsx +11 -12
- package/src/ui/notation/NotationPanel.css.ts +103 -0
- package/src/ui/notation/NotationPanel.tsx +253 -0
- package/src/ui/notation/index.ts +1 -0
- package/src/ui/top-left/TopLeftPanel.tsx +3 -4
- package/src/xyflow/XYFlowBackground.tsx +1 -1
- package/src/xyflow/XYFlowInner.tsx +4 -1
- package/src/xyflow/edges/edges.css.ts +1 -1
- package/src/xyflow/nodes/element/ElementLink.tsx +4 -4
- package/src/xyflow/nodes/element/element.css.ts +2 -2
- package/src/xyflow/nodes/shared/NavigateToBtn.tsx +1 -0
package/dist/LikeC4Diagram.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { LikeC4DiagramEventHandlers, LikeC4DiagramProperties } from './LikeC4Diagram.props';
|
|
2
2
|
|
|
3
3
|
export type LikeC4DiagramProps = LikeC4DiagramProperties & LikeC4DiagramEventHandlers;
|
|
4
|
-
export declare function LikeC4Diagram({ view, className, fitView, fitViewPadding, readonly, pannable, zoomable, nodesSelectable, nodesDraggable, background, controls, showElementLinks, showDiagramTitle, enableDynamicViewWalkthrough, enableFocusMode, initialWidth, initialHeight, keepAspectRatio, experimentalEdgeEditing, onCanvasClick, onCanvasContextMenu, onCanvasDblClick, onEdgeClick, onChange, onEdgeContextMenu, onNavigateTo, onNodeClick, onNodeContextMenu, onOpenSourceElement, onOpenSourceView, onOpenSourceRelation, onBurgerMenuClick, renderIcon, where, showNavigationButtons }: LikeC4DiagramProps): import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export declare function LikeC4Diagram({ view, className, fitView, fitViewPadding, readonly, pannable, zoomable, nodesSelectable, nodesDraggable, background, controls, showElementLinks, showDiagramTitle, showNotations, enableDynamicViewWalkthrough, enableFocusMode, initialWidth, initialHeight, keepAspectRatio, experimentalEdgeEditing, onCanvasClick, onCanvasContextMenu, onCanvasDblClick, onEdgeClick, onChange, onEdgeContextMenu, onNavigateTo, onNodeClick, onNodeContextMenu, onOpenSourceElement, onOpenSourceView, onOpenSourceRelation, onBurgerMenuClick, renderIcon, where, showNavigationButtons }: LikeC4DiagramProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -140,6 +140,11 @@ export interface LikeC4DiagramProperties {
|
|
|
140
140
|
* @default false
|
|
141
141
|
*/
|
|
142
142
|
showNavigationButtons?: undefined | boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Display notations of the view
|
|
145
|
+
* @default true
|
|
146
|
+
*/
|
|
147
|
+
showNotations?: boolean | undefined;
|
|
143
148
|
/**
|
|
144
149
|
* If double click on a node should enable focus mode, i.e. highlight incoming/outgoing edges
|
|
145
150
|
* @default true
|
package/dist/index.mjs
CHANGED
|
@@ -12,16 +12,16 @@ import { invariant, hasAtLeast, whereOperatorAsPredicate, extractStep, nonNullab
|
|
|
12
12
|
import { useFirstMountState, useCustomCompareEffect, useDebouncedEffect } from "@react-hookz/web";
|
|
13
13
|
import { getNodeDimensions, getBoundsOfRects, boxToRect, getViewportForBounds as getViewportForBounds$1 } from "@xyflow/system";
|
|
14
14
|
import { DEV } from "esm-env";
|
|
15
|
-
import { isArray, hasAtLeast as hasAtLeast$1, isNullish, entries, reduce, isTruthy, first, last, clamp, isNumber, isNonNullish, keys, takeWhile } from "remeda";
|
|
15
|
+
import { isArray, hasAtLeast as hasAtLeast$1, isNullish, entries, reduce, map, prop, isTruthy, first, last, clamp, isNumber, isNonNullish, ceil, keys, takeWhile } from "remeda";
|
|
16
16
|
import { subscribeWithSelector, devtools } from "zustand/middleware";
|
|
17
17
|
import { shallow } from "zustand/shallow";
|
|
18
18
|
import { Bezier } from "bezier-js";
|
|
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,
|
|
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, Tooltip as Tooltip$2, ThemeIcon, Paper, Tabs, TabsList, TabsTab, TabsPanel, ScrollAreaAutosize, Badge, rem, Divider, Space, TooltipGroup, Flex, ColorSwatch, CheckIcon, Select, Slider, SegmentedControl, Popover, PopoverTarget, PopoverDropdown, FloatingIndicator, Notification, Code } from "@mantine/core";
|
|
20
20
|
import { useHotkeys, useLocalStorage } from "@mantine/hooks";
|
|
21
21
|
import { assignInlineVars } from "@vanilla-extract/dynamic";
|
|
22
22
|
import { line, curveCatmullRomOpen } from "d3-shape";
|
|
23
23
|
import { Solver, Operator, Expression, Strength, Variable } from "@lume/kiwi";
|
|
24
|
-
import { IconZoomScan, IconLink, IconMenu, IconPlayerPlayFilled, IconPlayerSkipBackFilled, IconPlayerStopFilled, IconPlayerSkipForwardFilled, IconFileSymlink, IconLayoutDashboard, IconArrowBigDownLines, IconFocusCentered, IconMenu2, IconChevronLeft, IconChevronRight
|
|
24
|
+
import { IconZoomScan, IconLink, IconMenu, IconPlayerPlayFilled, IconPlayerSkipBackFilled, IconPlayerStopFilled, IconPlayerSkipForwardFilled, IconAlertTriangle, IconHelpCircle, IconArrowDownRight, IconFileSymlink, IconLayoutDashboard, IconArrowBigDownLines, IconFocusCentered, IconMenu2, IconChevronLeft, IconChevronRight } from "@tabler/icons-react";
|
|
25
25
|
var rootClassName = "likec4-diagram-root";
|
|
26
26
|
const noop = () => {
|
|
27
27
|
}, depsShallowEqual = (d1, d2) => {
|
|
@@ -103,9 +103,9 @@ function diagramViewToXYFlowData(view, opts) {
|
|
|
103
103
|
const ns = "", nodeById = (id) => nonNullable(nodeLookup.get(id), `Node not found: ${id}`);
|
|
104
104
|
let next;
|
|
105
105
|
for (; next = traverse.shift(); ) {
|
|
106
|
-
const { node, parent } = next;
|
|
107
|
-
|
|
108
|
-
const
|
|
106
|
+
const { node, parent } = next, isCompound = hasAtLeast$1(node.children, 1);
|
|
107
|
+
isCompound && traverse.push(...node.children.map((child) => ({ node: nodeById(child), parent: node })));
|
|
108
|
+
const position = {
|
|
109
109
|
x: node.position[0],
|
|
110
110
|
y: node.position[1]
|
|
111
111
|
};
|
|
@@ -120,6 +120,7 @@ function diagramViewToXYFlowData(view, opts) {
|
|
|
120
120
|
},
|
|
121
121
|
draggable,
|
|
122
122
|
selectable: opts.selectable,
|
|
123
|
+
focusable: opts.selectable && !isCompound,
|
|
123
124
|
deletable: !1,
|
|
124
125
|
position,
|
|
125
126
|
zIndex: isCompound ? ZIndexes.Compound : ZIndexes.Element,
|
|
@@ -137,7 +138,11 @@ function diagramViewToXYFlowData(view, opts) {
|
|
|
137
138
|
}
|
|
138
139
|
for (const edge of view.edges) {
|
|
139
140
|
const source = edge.source, target = edge.target, id = ns + edge.id;
|
|
140
|
-
|
|
141
|
+
if (!hasAtLeast$1(edge.points, 2)) {
|
|
142
|
+
console.error("edge should have at least 2 points", edge);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
xyedges.push({
|
|
141
146
|
id,
|
|
142
147
|
type: "relationship",
|
|
143
148
|
source: ns + source,
|
|
@@ -650,6 +655,13 @@ function createDiagramStore(props) {
|
|
|
650
655
|
noReplace,
|
|
651
656
|
"onInit"
|
|
652
657
|
);
|
|
658
|
+
},
|
|
659
|
+
highlightByElementNotation: (notation, onlyOfKind) => {
|
|
660
|
+
const { xynodes: xynodes2, xyedges: xyedges2 } = get(), dimmed2 = new StringSet(map(xyedges2, prop("id")));
|
|
661
|
+
xynodes2.forEach(({ id, data }) => {
|
|
662
|
+
const node = data.element;
|
|
663
|
+
(node.shape !== notation.shape || node.color !== notation.color || !notation.kinds.includes(node.kind) || onlyOfKind && node.kind !== onlyOfKind) && dimmed2.add(id);
|
|
664
|
+
}), set({ dimmed: dimmed2 }, noReplace, "highlightByElementNotation");
|
|
653
665
|
}
|
|
654
666
|
}),
|
|
655
667
|
{
|
|
@@ -754,7 +766,7 @@ function FitViewOnViewportResize({ diagramApi }) {
|
|
|
754
766
|
1e3
|
|
755
767
|
), null;
|
|
756
768
|
}
|
|
757
|
-
function selector$
|
|
769
|
+
function selector$4({ view, viewportChanged, fitViewPadding }) {
|
|
758
770
|
return {
|
|
759
771
|
layoutId: view.id + "_" + view.autoLayout + "_" + fitViewPadding,
|
|
760
772
|
viewportNotMoved: !viewportChanged
|
|
@@ -764,7 +776,7 @@ function FitViewOnDiagramChange() {
|
|
|
764
776
|
const {
|
|
765
777
|
layoutId,
|
|
766
778
|
viewportNotMoved
|
|
767
|
-
} = useDiagramState(selector$
|
|
779
|
+
} = useDiagramState(selector$4, shallowEqual), diagramApi = useDiagramStoreApi(), [currentLayoutId, setCurrent] = useState(layoutId), requiresFit = layoutId !== currentLayoutId;
|
|
768
780
|
return useDebouncedEffect(
|
|
769
781
|
() => {
|
|
770
782
|
layoutId !== currentLayoutId && (setCurrent(layoutId), diagramApi.getState().fitDiagram(450));
|
|
@@ -1012,7 +1024,7 @@ const Open = (props) => /* @__PURE__ */ jsx(
|
|
|
1012
1024
|
Dot,
|
|
1013
1025
|
ODot
|
|
1014
1026
|
};
|
|
1015
|
-
var container$
|
|
1027
|
+
var container$5 = "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";
|
|
1016
1028
|
function getNodeIntersectionFromCenterToPoint(intersectionNode, { x: x1, y: y1 }) {
|
|
1017
1029
|
const {
|
|
1018
1030
|
width: intersectionNodeWidth,
|
|
@@ -1188,7 +1200,7 @@ const isSame = (a, b) => Math.abs(a - b) < 2.5, isSamePoint = (a, b) => {
|
|
|
1188
1200
|
"g",
|
|
1189
1201
|
{
|
|
1190
1202
|
className: clsx(
|
|
1191
|
-
container$
|
|
1203
|
+
container$5,
|
|
1192
1204
|
isDimmed && dimmed$2,
|
|
1193
1205
|
isControlPointDragging && controlDragging
|
|
1194
1206
|
),
|
|
@@ -1298,7 +1310,7 @@ const isSame = (a, b) => Math.abs(a - b) < 2.5, isSamePoint = (a, b) => {
|
|
|
1298
1310
|
{
|
|
1299
1311
|
className: clsx([
|
|
1300
1312
|
"nodrag nopan",
|
|
1301
|
-
container$
|
|
1313
|
+
container$5,
|
|
1302
1314
|
edgeLabel,
|
|
1303
1315
|
isDimmed && dimmed$2
|
|
1304
1316
|
]),
|
|
@@ -1338,6 +1350,7 @@ function NavigateToBtn({ xynodeId, className }) {
|
|
|
1338
1350
|
onClick: (event) => {
|
|
1339
1351
|
event.stopPropagation(), diagramApi.getState().triggerOnNavigateTo(xynodeId, event);
|
|
1340
1352
|
},
|
|
1353
|
+
role: "button",
|
|
1341
1354
|
onDoubleClick: (event) => event.stopPropagation(),
|
|
1342
1355
|
children: /* @__PURE__ */ jsx(
|
|
1343
1356
|
IconZoomScan,
|
|
@@ -1351,7 +1364,7 @@ function NavigateToBtn({ xynodeId, className }) {
|
|
|
1351
1364
|
}
|
|
1352
1365
|
);
|
|
1353
1366
|
}
|
|
1354
|
-
var container$
|
|
1367
|
+
var container$4 = "lbtzdo0", nodeHandlerInCenter = "lbtzdo1", dimmed$1 = "lbtzdo2", varOpacity = "var(--lbtzdo3)", varBorderTransparency = "var(--lbtzdo4)", compoundBody = "lbtzdo5", transparent = "lbtzdo7", title$2 = "lbtzdo8", titleWithNavigation = "lbtzdo9", indicator$1 = "lbtzdod", navigateBtn = "lbtzdof";
|
|
1355
1368
|
const isEqualProps$1 = (prev, next) => prev.id === next.id && deepEqual(prev.data.element, next.data.element), CompoundNodeMemo = /* @__PURE__ */ memo(function({
|
|
1356
1369
|
id,
|
|
1357
1370
|
data: {
|
|
@@ -1382,7 +1395,7 @@ const isEqualProps$1 = (prev, next) => prev.id === next.id && deepEqual(prev.dat
|
|
|
1382
1395
|
Box,
|
|
1383
1396
|
{
|
|
1384
1397
|
className: clsx(
|
|
1385
|
-
container$
|
|
1398
|
+
container$4,
|
|
1386
1399
|
"likec4-compound-node",
|
|
1387
1400
|
opacity < 1 && "likec4-compound-transparent",
|
|
1388
1401
|
isDimmed && dimmed$1
|
|
@@ -1446,8 +1459,8 @@ const isEqualProps$1 = (prev, next) => prev.id === next.id && deepEqual(prev.dat
|
|
|
1446
1459
|
)
|
|
1447
1460
|
] });
|
|
1448
1461
|
}, isEqualProps$1);
|
|
1449
|
-
var container$
|
|
1450
|
-
const selector$
|
|
1462
|
+
var container$3 = "_1b6tkn1", handleCenter = "_1b6tkn2", containerAnimated = "_1b6tkn3", dimmed = "_1b6tkn4", indicator = "_1b6tkn7", fillElementFill = "_1b6tkn8", fillMixStroke = "_1b6tkna", hasIcon = "_1b6tknb", title$1 = "_1b6tkne", description$1 = "_1b6tknf", technology = "_1b6tkng", elementDataContainer = "_1b6tknh", elementTextData = "_1b6tkni", elementIcon = "_1b6tknj", cssShapeSvg = "_1b6tknm", cssNavigateBtn = "_1b6tknn", elementLink = "_4ysv0o0", trigger = "_4ysv0o1";
|
|
1463
|
+
const selector$3 = (s) => {
|
|
1451
1464
|
const target = s.getContainer();
|
|
1452
1465
|
return target ? { target } : null;
|
|
1453
1466
|
};
|
|
@@ -1455,7 +1468,7 @@ function ElementLink({
|
|
|
1455
1468
|
element
|
|
1456
1469
|
}) {
|
|
1457
1470
|
invariant(element.links, "ElementLink: links are required");
|
|
1458
|
-
const id = useId(), portalProps = useDiagramState(selector$
|
|
1471
|
+
const id = useId(), portalProps = useDiagramState(selector$3);
|
|
1459
1472
|
return /* @__PURE__ */ jsx("div", { className: elementLink, "data-likec4-linkid": id, children: /* @__PURE__ */ jsxs(
|
|
1460
1473
|
HoverCard,
|
|
1461
1474
|
{
|
|
@@ -1495,8 +1508,8 @@ function ElementLink({
|
|
|
1495
1508
|
onClick: (e) => e.stopPropagation(),
|
|
1496
1509
|
p: "xs",
|
|
1497
1510
|
children: /* @__PURE__ */ jsx(Stack, { gap: "xs", children: element.links.map((link) => /* @__PURE__ */ jsxs(Group, { wrap: "nowrap", gap: "sm", children: [
|
|
1498
|
-
/* @__PURE__ */ jsx(Box, { flex: "1", style: { overflow: "clip", maxWidth: clamp(element.width, { min: 200, max: 400 }) }, children: /* @__PURE__ */ jsx(Anchor, { href: link, target: "_blank", fz: "13", truncate: "end", children: link }) }),
|
|
1499
|
-
/* @__PURE__ */ jsx(CopyButton, { value: link, children: ({ copied, copy }) => /* @__PURE__ */ jsx(
|
|
1511
|
+
/* @__PURE__ */ jsx(Box, { flex: "1", style: { overflow: "clip", maxWidth: clamp(element.width, { min: 200, max: 400 }) }, children: /* @__PURE__ */ jsx(Anchor, { href: link.url, target: "_blank", fz: "13", truncate: "end", children: link.title || link.url }) }),
|
|
1512
|
+
/* @__PURE__ */ jsx(CopyButton, { value: link.url, children: ({ copied, copy }) => /* @__PURE__ */ jsx(
|
|
1500
1513
|
Button,
|
|
1501
1514
|
{
|
|
1502
1515
|
size: "compact-xs",
|
|
@@ -1507,7 +1520,7 @@ function ElementLink({
|
|
|
1507
1520
|
children: copied ? "copied" : "copy"
|
|
1508
1521
|
}
|
|
1509
1522
|
) })
|
|
1510
|
-
] }, link)) })
|
|
1523
|
+
] }, link.url)) })
|
|
1511
1524
|
}
|
|
1512
1525
|
)
|
|
1513
1526
|
]
|
|
@@ -1758,7 +1771,7 @@ const Text = Text$1.withProps({
|
|
|
1758
1771
|
{
|
|
1759
1772
|
id,
|
|
1760
1773
|
className: clsx([
|
|
1761
|
-
container$
|
|
1774
|
+
container$3,
|
|
1762
1775
|
isDimmed && dimmed,
|
|
1763
1776
|
animate !== "idle" && containerAnimated,
|
|
1764
1777
|
"likec4-element-node"
|
|
@@ -2188,7 +2201,7 @@ const nodeTypes = {
|
|
|
2188
2201
|
compound: CompoundNodeMemo
|
|
2189
2202
|
}, edgeTypes = {
|
|
2190
2203
|
relationship: RelationshipEdge
|
|
2191
|
-
}, selector$
|
|
2204
|
+
}, selector$2 = (s) => ({
|
|
2192
2205
|
nodes: s.xynodes,
|
|
2193
2206
|
edges: s.xyedges,
|
|
2194
2207
|
onInit: s.onInit,
|
|
@@ -2236,7 +2249,7 @@ function XYFlow({
|
|
|
2236
2249
|
hasOnEdgeContextMenu,
|
|
2237
2250
|
translateX,
|
|
2238
2251
|
translateY
|
|
2239
|
-
} = useDiagramState(selector$
|
|
2252
|
+
} = useDiagramState(selector$2, shallowEqual), [zoomOnDoubleClick, setZoomOnDoubleClick] = useState(zoomable), layoutConstraints = useLayoutConstraints(), handlers = useXYFlowEvents();
|
|
2240
2253
|
return useOnViewportChange({
|
|
2241
2254
|
onEnd: ({ x, y, zoom }) => {
|
|
2242
2255
|
const roundedX = Math.round(x), roundedY = Math.round(y);
|
|
@@ -2322,15 +2335,15 @@ function XYFlow({
|
|
|
2322
2335
|
}
|
|
2323
2336
|
);
|
|
2324
2337
|
}
|
|
2325
|
-
var container$
|
|
2326
|
-
const selector = (s) => ({
|
|
2338
|
+
var container$2 = "hbkbtj0", card$1 = "hbkbtj1", title = "hbkbtj2", description = "hbkbtj3";
|
|
2339
|
+
const selector$1 = (s) => ({
|
|
2327
2340
|
id: s.view.id,
|
|
2328
2341
|
title: s.view.title ?? "untitled",
|
|
2329
2342
|
description: s.view.description,
|
|
2330
2343
|
links: s.view.links
|
|
2331
2344
|
});
|
|
2332
2345
|
function DiagramTitlePanel() {
|
|
2333
|
-
const { id, title: title$12, description: description$12, links } = useDiagramState(selector), [isCollapsed, setCollapsed] = useLocalStorage({
|
|
2346
|
+
const { id, title: title$12, description: description$12, links } = useDiagramState(selector$1), [isCollapsed, setCollapsed] = useLocalStorage({
|
|
2334
2347
|
key: "diagram-title-panel-collapsed",
|
|
2335
2348
|
defaultValue: !1
|
|
2336
2349
|
}), toggle = () => setCollapsed((v) => !v);
|
|
@@ -2343,7 +2356,7 @@ function DiagramTitlePanel() {
|
|
|
2343
2356
|
opacity: 0.05,
|
|
2344
2357
|
scale: 0.6
|
|
2345
2358
|
},
|
|
2346
|
-
className: clsx("react-flow__panel", container$
|
|
2359
|
+
className: clsx("react-flow__panel", container$2),
|
|
2347
2360
|
style: {
|
|
2348
2361
|
transformOrigin: "left center"
|
|
2349
2362
|
},
|
|
@@ -2351,8 +2364,8 @@ function DiagramTitlePanel() {
|
|
|
2351
2364
|
Card,
|
|
2352
2365
|
{
|
|
2353
2366
|
radius: "sm",
|
|
2354
|
-
className: card,
|
|
2355
|
-
withBorder: !
|
|
2367
|
+
className: card$1,
|
|
2368
|
+
withBorder: !isCollapsed,
|
|
2356
2369
|
p: isCollapsed ? "sm" : "md",
|
|
2357
2370
|
onDoubleClick: (e) => e.stopPropagation(),
|
|
2358
2371
|
children: [
|
|
@@ -2361,17 +2374,18 @@ function DiagramTitlePanel() {
|
|
|
2361
2374
|
{
|
|
2362
2375
|
fullWidth: !0,
|
|
2363
2376
|
justify: "stretch",
|
|
2364
|
-
size: "
|
|
2365
|
-
py: 2,
|
|
2377
|
+
size: "md",
|
|
2366
2378
|
radius: "0",
|
|
2367
2379
|
variant: "subtle",
|
|
2368
|
-
color: "
|
|
2380
|
+
color: "gray",
|
|
2369
2381
|
onClick: toggle,
|
|
2370
|
-
|
|
2382
|
+
fw: 500,
|
|
2383
|
+
fz: "sm",
|
|
2384
|
+
children: title$12
|
|
2371
2385
|
}
|
|
2372
2386
|
) }),
|
|
2373
2387
|
!isCollapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2374
|
-
/* @__PURE__ */ jsx(CardSection, { mb: "
|
|
2388
|
+
/* @__PURE__ */ jsx(CardSection, { mb: "xs", children: /* @__PURE__ */ jsx(
|
|
2375
2389
|
Button,
|
|
2376
2390
|
{
|
|
2377
2391
|
fullWidth: !0,
|
|
@@ -2458,16 +2472,16 @@ function DiagramTitlePanel() {
|
|
|
2458
2472
|
/* @__PURE__ */ jsx(Box, { flex: "1", style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx(
|
|
2459
2473
|
Anchor,
|
|
2460
2474
|
{
|
|
2461
|
-
href: link,
|
|
2475
|
+
href: link.url,
|
|
2462
2476
|
target: "_blank",
|
|
2463
2477
|
fz: "xs",
|
|
2464
2478
|
truncate: "end",
|
|
2465
2479
|
display: "inline-block",
|
|
2466
2480
|
w: "100%",
|
|
2467
|
-
children: link
|
|
2481
|
+
children: link.title || link.url
|
|
2468
2482
|
}
|
|
2469
2483
|
) }),
|
|
2470
|
-
/* @__PURE__ */ jsx(CopyButton, { value: link, children: ({ copied, copy }) => /* @__PURE__ */ jsx(
|
|
2484
|
+
/* @__PURE__ */ jsx(CopyButton, { value: link.url, children: ({ copied, copy }) => /* @__PURE__ */ jsx(
|
|
2471
2485
|
Button,
|
|
2472
2486
|
{
|
|
2473
2487
|
size: "compact-xs",
|
|
@@ -2478,7 +2492,7 @@ function DiagramTitlePanel() {
|
|
|
2478
2492
|
children: copied ? "copied" : "copy"
|
|
2479
2493
|
}
|
|
2480
2494
|
) })
|
|
2481
|
-
] }, link))
|
|
2495
|
+
] }, link.url))
|
|
2482
2496
|
}
|
|
2483
2497
|
)
|
|
2484
2498
|
] })
|
|
@@ -2489,7 +2503,7 @@ function DiagramTitlePanel() {
|
|
|
2489
2503
|
id
|
|
2490
2504
|
) });
|
|
2491
2505
|
}
|
|
2492
|
-
var container = "_2jkb2y0", buttons = "_2jkb2y1", btn = "_2jkb2y3";
|
|
2506
|
+
var container$1 = "_2jkb2y0", buttons = "_2jkb2y1", btn = "_2jkb2y3";
|
|
2493
2507
|
function DynamicViewWalkthrough() {
|
|
2494
2508
|
const isMobile = useXYStore((s) => s.width <= 750), {
|
|
2495
2509
|
nextDynamicStep,
|
|
@@ -2524,7 +2538,7 @@ function DynamicViewWalkthrough() {
|
|
|
2524
2538
|
return /* @__PURE__ */ jsxs(
|
|
2525
2539
|
Box,
|
|
2526
2540
|
{
|
|
2527
|
-
className: clsx("react-flow__panel", container),
|
|
2541
|
+
className: clsx("react-flow__panel", container$1),
|
|
2528
2542
|
onClick: (e) => e.stopPropagation(),
|
|
2529
2543
|
onDoubleClick: (e) => e.stopPropagation(),
|
|
2530
2544
|
children: [
|
|
@@ -2578,6 +2592,230 @@ function DynamicViewWalkthrough() {
|
|
|
2578
2592
|
}
|
|
2579
2593
|
);
|
|
2580
2594
|
}
|
|
2595
|
+
var vars = { safariAnimationHook: "var(--likec4-safari-animation-hook)", default: { font: "var(--likec4-default-font-family)" }, likec4: { font: "var(--likec4-font-family)", background: { color: "var(--likec4-background-color)", pattern: { color: "var(--likec4-background-pattern-color)" } } }, compound: { font: "var(--likec4-compound-font-family)", titleColor: "var(--likec4-compound-title-color)" }, element: { font: "var(--likec4-element-font-family)", fill: "var(--likec4-element-fill)", stroke: "var(--likec4-element-stroke)", hiContrast: "var(--likec4-element-hiContrast)", loContrast: "var(--likec4-element-loContrast)" }, relation: { lineColor: "var(--likec4-relation-lineColor)", labelColor: "var(--likec4-relation-labelColor)", labelBgColor: "var(--likec4-relation-labelBg)" }, optionsPanel: { top: "var(--likec4-options-panel-top)", right: "var(--likec4-options-panel-right)" }, navigationPanel: { top: "var(--likec4-navigation-panel-top)", left: "var(--likec4-navigation-panel-left)" } }, container = "_1ncdyfa0", card = "_1ncdyfa1", tabPanel = "_1ncdyfa2", elementNotation = "_1ncdyfa3", shapeSvg = "_1ncdyfa4", shapeBadge = "_1ncdyfa5";
|
|
2596
|
+
const ElementNotation = ({ value }) => {
|
|
2597
|
+
const {
|
|
2598
|
+
title: title2,
|
|
2599
|
+
color = "primary",
|
|
2600
|
+
shape = "rectangle"
|
|
2601
|
+
} = value, [onlyKind, setOnlyKind] = useState(null), diagramStore = useDiagramStoreApi(), w = 300, h = 200;
|
|
2602
|
+
return /* @__PURE__ */ jsx(
|
|
2603
|
+
Card,
|
|
2604
|
+
{
|
|
2605
|
+
shadow: "none",
|
|
2606
|
+
px: "xs",
|
|
2607
|
+
py: "sm",
|
|
2608
|
+
className: elementNotation,
|
|
2609
|
+
mod: {
|
|
2610
|
+
"data-likec4-color": color
|
|
2611
|
+
},
|
|
2612
|
+
onMouseEnter: () => {
|
|
2613
|
+
setOnlyKind(null), diagramStore.getState().highlightByElementNotation(value);
|
|
2614
|
+
},
|
|
2615
|
+
onMouseLeave: () => {
|
|
2616
|
+
setOnlyKind(null), diagramStore.setState({ dimmed: /* @__PURE__ */ new Set() });
|
|
2617
|
+
},
|
|
2618
|
+
children: /* @__PURE__ */ jsxs(
|
|
2619
|
+
Group,
|
|
2620
|
+
{
|
|
2621
|
+
gap: "sm",
|
|
2622
|
+
align: "stretch",
|
|
2623
|
+
wrap: "nowrap",
|
|
2624
|
+
children: [
|
|
2625
|
+
/* @__PURE__ */ jsx(
|
|
2626
|
+
Box,
|
|
2627
|
+
{
|
|
2628
|
+
flex: "0 0 70px",
|
|
2629
|
+
style: {
|
|
2630
|
+
width: 70,
|
|
2631
|
+
height: ceil(70 * (h / w), 0)
|
|
2632
|
+
},
|
|
2633
|
+
children: /* @__PURE__ */ jsx(
|
|
2634
|
+
"svg",
|
|
2635
|
+
{
|
|
2636
|
+
className: clsx(
|
|
2637
|
+
shapeSvg
|
|
2638
|
+
),
|
|
2639
|
+
viewBox: `0 0 ${w} ${h}`,
|
|
2640
|
+
children: /* @__PURE__ */ jsx(
|
|
2641
|
+
ElementShapeSvg,
|
|
2642
|
+
{
|
|
2643
|
+
shape,
|
|
2644
|
+
w,
|
|
2645
|
+
h
|
|
2646
|
+
}
|
|
2647
|
+
)
|
|
2648
|
+
}
|
|
2649
|
+
)
|
|
2650
|
+
}
|
|
2651
|
+
),
|
|
2652
|
+
/* @__PURE__ */ jsxs(Stack, { gap: 4, flex: 1, children: [
|
|
2653
|
+
/* @__PURE__ */ jsx(Group, { gap: 4, flex: "0 0 auto", children: value.kinds.map((kind) => /* @__PURE__ */ jsx(
|
|
2654
|
+
Badge,
|
|
2655
|
+
{
|
|
2656
|
+
className: shapeBadge,
|
|
2657
|
+
onMouseEnter: () => {
|
|
2658
|
+
setOnlyKind(kind), diagramStore.getState().highlightByElementNotation(value, kind);
|
|
2659
|
+
},
|
|
2660
|
+
onMouseLeave: () => {
|
|
2661
|
+
setOnlyKind(null), diagramStore.getState().highlightByElementNotation(value);
|
|
2662
|
+
},
|
|
2663
|
+
opacity: isNonNullish(onlyKind) && onlyKind !== kind ? 0.25 : 1,
|
|
2664
|
+
color: isNonNullish(onlyKind) && onlyKind !== kind ? "gray" : vars.element.fill,
|
|
2665
|
+
children: kind
|
|
2666
|
+
},
|
|
2667
|
+
kind
|
|
2668
|
+
)) }),
|
|
2669
|
+
/* @__PURE__ */ jsx(
|
|
2670
|
+
Text$1,
|
|
2671
|
+
{
|
|
2672
|
+
component: "div",
|
|
2673
|
+
fz: "sm",
|
|
2674
|
+
fw: 500,
|
|
2675
|
+
lh: "1.25",
|
|
2676
|
+
style: {
|
|
2677
|
+
textWrap: "pretty"
|
|
2678
|
+
},
|
|
2679
|
+
children: title2
|
|
2680
|
+
}
|
|
2681
|
+
)
|
|
2682
|
+
] })
|
|
2683
|
+
]
|
|
2684
|
+
}
|
|
2685
|
+
)
|
|
2686
|
+
}
|
|
2687
|
+
);
|
|
2688
|
+
}, selector = (s) => {
|
|
2689
|
+
var _a;
|
|
2690
|
+
return {
|
|
2691
|
+
id: s.view.id,
|
|
2692
|
+
notations: ((_a = s.view.notation) == null ? void 0 : _a.elements) ?? [],
|
|
2693
|
+
height: s.xystore.getState().height,
|
|
2694
|
+
isVisible: isNullish(s.focusedNodeId ?? s.activeDynamicViewStep),
|
|
2695
|
+
target: s.getContainer()
|
|
2696
|
+
};
|
|
2697
|
+
};
|
|
2698
|
+
function NotationPanel() {
|
|
2699
|
+
const {
|
|
2700
|
+
id,
|
|
2701
|
+
notations,
|
|
2702
|
+
isVisible,
|
|
2703
|
+
height,
|
|
2704
|
+
target
|
|
2705
|
+
} = useDiagramState(selector), [isCollapsed, setCollapsed] = useLocalStorage({
|
|
2706
|
+
key: "notation-panel-collapsed",
|
|
2707
|
+
defaultValue: !0
|
|
2708
|
+
}), hasNotations = notations.length > 0, portalProps = target ? { portalProps: { target } } : { withinPortal: !1 };
|
|
2709
|
+
return /* @__PURE__ */ jsxs(AnimatePresence, { children: [
|
|
2710
|
+
!hasNotations && /* @__PURE__ */ jsx(
|
|
2711
|
+
m.div,
|
|
2712
|
+
{
|
|
2713
|
+
initial: { opacity: 0.75, translateX: "50%" },
|
|
2714
|
+
animate: { opacity: 1, translateX: 0 },
|
|
2715
|
+
exit: {
|
|
2716
|
+
translateX: "100%",
|
|
2717
|
+
opacity: 0.6
|
|
2718
|
+
},
|
|
2719
|
+
className: clsx("react-flow__panel", container),
|
|
2720
|
+
children: /* @__PURE__ */ jsx(Tooltip$2, { label: "Diagram has no notations", color: "orange", ...portalProps, children: /* @__PURE__ */ jsx(
|
|
2721
|
+
ThemeIcon,
|
|
2722
|
+
{
|
|
2723
|
+
size: "xl",
|
|
2724
|
+
variant: "light",
|
|
2725
|
+
color: "orange",
|
|
2726
|
+
radius: "md",
|
|
2727
|
+
children: /* @__PURE__ */ jsx(IconAlertTriangle, {})
|
|
2728
|
+
}
|
|
2729
|
+
) })
|
|
2730
|
+
},
|
|
2731
|
+
"empty"
|
|
2732
|
+
),
|
|
2733
|
+
hasNotations && isVisible && isCollapsed && /* @__PURE__ */ jsx(
|
|
2734
|
+
m.div,
|
|
2735
|
+
{
|
|
2736
|
+
initial: { opacity: 0.75, translateX: "50%" },
|
|
2737
|
+
animate: { opacity: 1, translateX: 0 },
|
|
2738
|
+
exit: {
|
|
2739
|
+
translateX: "100%",
|
|
2740
|
+
opacity: 0.6
|
|
2741
|
+
},
|
|
2742
|
+
className: clsx("react-flow__panel", container),
|
|
2743
|
+
children: /* @__PURE__ */ jsx(Tooltip$2, { label: "Show notation", color: "dark", fz: "xs", ...portalProps, children: /* @__PURE__ */ jsx(
|
|
2744
|
+
ActionIcon$2,
|
|
2745
|
+
{
|
|
2746
|
+
size: "xl",
|
|
2747
|
+
variant: "light",
|
|
2748
|
+
color: "gray",
|
|
2749
|
+
radius: "md",
|
|
2750
|
+
onClick: () => setCollapsed(!1),
|
|
2751
|
+
children: /* @__PURE__ */ jsx(IconHelpCircle, { stroke: 1.5 })
|
|
2752
|
+
}
|
|
2753
|
+
) })
|
|
2754
|
+
},
|
|
2755
|
+
"collapsed"
|
|
2756
|
+
),
|
|
2757
|
+
hasNotations && isVisible && !isCollapsed && /* @__PURE__ */ jsx(
|
|
2758
|
+
m.div,
|
|
2759
|
+
{
|
|
2760
|
+
initial: {
|
|
2761
|
+
opacity: 0.75,
|
|
2762
|
+
// translateX: '50%',
|
|
2763
|
+
scale: 0.2
|
|
2764
|
+
},
|
|
2765
|
+
animate: { opacity: 1, scale: 1 },
|
|
2766
|
+
exit: {
|
|
2767
|
+
opacity: 0,
|
|
2768
|
+
scale: 0.25
|
|
2769
|
+
},
|
|
2770
|
+
className: clsx("react-flow__panel", container),
|
|
2771
|
+
style: {
|
|
2772
|
+
transformOrigin: "bottom right"
|
|
2773
|
+
},
|
|
2774
|
+
children: /* @__PURE__ */ jsx(
|
|
2775
|
+
Paper,
|
|
2776
|
+
{
|
|
2777
|
+
radius: "sm",
|
|
2778
|
+
withBorder: !0,
|
|
2779
|
+
shadow: "lg",
|
|
2780
|
+
className: card,
|
|
2781
|
+
children: /* @__PURE__ */ jsxs(Tabs, { defaultValue: "first", radius: "xs", children: [
|
|
2782
|
+
/* @__PURE__ */ jsxs(TabsList, { children: [
|
|
2783
|
+
/* @__PURE__ */ jsx(
|
|
2784
|
+
ActionIcon$2,
|
|
2785
|
+
{
|
|
2786
|
+
size: "md",
|
|
2787
|
+
variant: "subtle",
|
|
2788
|
+
color: "gray",
|
|
2789
|
+
ml: 2,
|
|
2790
|
+
style: {
|
|
2791
|
+
alignSelf: "center"
|
|
2792
|
+
},
|
|
2793
|
+
onClick: () => setCollapsed(!0),
|
|
2794
|
+
children: /* @__PURE__ */ jsx(IconArrowDownRight, { stroke: 2 })
|
|
2795
|
+
}
|
|
2796
|
+
),
|
|
2797
|
+
/* @__PURE__ */ jsx(TabsTab, { value: "first", fz: "xs", children: "Elements" }),
|
|
2798
|
+
/* @__PURE__ */ jsx(TabsTab, { value: "second", fz: "xs", disabled: !0, children: "Relationships" })
|
|
2799
|
+
] }),
|
|
2800
|
+
/* @__PURE__ */ jsx(TabsPanel, { value: "first", className: tabPanel, hidden: isCollapsed, children: /* @__PURE__ */ jsx(
|
|
2801
|
+
ScrollAreaAutosize,
|
|
2802
|
+
{
|
|
2803
|
+
viewportProps: {
|
|
2804
|
+
style: {
|
|
2805
|
+
maxHeight: height > 50 ? `min(40vh, ${height - 20}px)` : "40vh"
|
|
2806
|
+
}
|
|
2807
|
+
},
|
|
2808
|
+
children: /* @__PURE__ */ jsx(Stack, { gap: 0, children: notations.map((n, i) => /* @__PURE__ */ jsx(ElementNotation, { value: n }, i)) })
|
|
2809
|
+
}
|
|
2810
|
+
) })
|
|
2811
|
+
] })
|
|
2812
|
+
}
|
|
2813
|
+
)
|
|
2814
|
+
},
|
|
2815
|
+
id
|
|
2816
|
+
)
|
|
2817
|
+
] });
|
|
2818
|
+
}
|
|
2581
2819
|
const {
|
|
2582
2820
|
primary,
|
|
2583
2821
|
secondary,
|
|
@@ -3108,19 +3346,19 @@ const ActionIcon = ActionIcon$2.withProps({
|
|
|
3108
3346
|
showFitDiagram,
|
|
3109
3347
|
showLayoutDriftWarning,
|
|
3110
3348
|
showChangeAutoLayout,
|
|
3111
|
-
|
|
3349
|
+
target,
|
|
3112
3350
|
showGoToSource
|
|
3113
3351
|
} = useDiagramState((s) => {
|
|
3114
|
-
const isNotActive = s.activeDynamicViewStep === null && s.focusedNodeId === null
|
|
3352
|
+
const isNotActive = s.activeDynamicViewStep === null && s.focusedNodeId === null;
|
|
3115
3353
|
return {
|
|
3116
3354
|
showNavigationButtons: !!s.onBurgerMenuClick || s.showNavigationButtons && !!s.onNavigateTo,
|
|
3117
3355
|
showFitDiagram: s.fitViewEnabled && s.zoomable && s.viewportChanged,
|
|
3118
3356
|
showLayoutDriftWarning: s.readonly !== !0 && s.view.hasLayoutDrift === !0 && isNotActive,
|
|
3119
3357
|
showChangeAutoLayout: s.readonly !== !0 && !!s.onChange && isNotActive,
|
|
3120
3358
|
showGoToSource: !!s.onOpenSourceView,
|
|
3121
|
-
|
|
3359
|
+
target: s.getContainer()
|
|
3122
3360
|
};
|
|
3123
|
-
}), portalProps =
|
|
3361
|
+
}), portalProps = target ? { portalProps: { target } } : void 0;
|
|
3124
3362
|
return /* @__PURE__ */ jsxs(
|
|
3125
3363
|
Stack,
|
|
3126
3364
|
{
|
|
@@ -3201,7 +3439,7 @@ function literalToEnum(value) {
|
|
|
3201
3439
|
}
|
|
3202
3440
|
function XYFlowBackground({ background }) {
|
|
3203
3441
|
if (typeof background == "string")
|
|
3204
|
-
return /* @__PURE__ */ jsx(Background, { variant: literalToEnum(background) });
|
|
3442
|
+
return /* @__PURE__ */ jsx(Background, { variant: literalToEnum(background), size: 2, gap: 20 });
|
|
3205
3443
|
const { variant, ...rest } = background;
|
|
3206
3444
|
return /* @__PURE__ */ jsx(Background, { variant: literalToEnum(variant), ...rest });
|
|
3207
3445
|
}
|
|
@@ -3212,11 +3450,13 @@ const XYFlowInner = memo(function({
|
|
|
3212
3450
|
showDiagramTitle
|
|
3213
3451
|
}) {
|
|
3214
3452
|
const {
|
|
3453
|
+
showNotations,
|
|
3215
3454
|
isDynamicView,
|
|
3216
3455
|
isDynamicViewActive,
|
|
3217
3456
|
readonly,
|
|
3218
3457
|
enableDynamicViewWalkthrough
|
|
3219
3458
|
} = useDiagramState((s) => ({
|
|
3459
|
+
showNotations: s.showNotations,
|
|
3220
3460
|
isDynamicView: s.isDynamicView,
|
|
3221
3461
|
readonly: s.readonly,
|
|
3222
3462
|
enableDynamicViewWalkthrough: s.enableDynamicViewWalkthrough,
|
|
@@ -3229,6 +3469,7 @@ const XYFlowInner = memo(function({
|
|
|
3229
3469
|
readonly !== !0 && /* @__PURE__ */ jsx(OptionsPanel, {}),
|
|
3230
3470
|
showDiagramTitle === !0 && !isDynamicViewActive && /* @__PURE__ */ jsx(DiagramTitlePanel, {}),
|
|
3231
3471
|
isDynamicView && enableDynamicViewWalkthrough && /* @__PURE__ */ jsx(DynamicViewWalkthrough, {}),
|
|
3472
|
+
showNotations && /* @__PURE__ */ jsx(NotationPanel, {}),
|
|
3232
3473
|
children
|
|
3233
3474
|
] });
|
|
3234
3475
|
}, shallowEqual);
|
|
@@ -3247,6 +3488,7 @@ function LikeC4Diagram({
|
|
|
3247
3488
|
controls = !1,
|
|
3248
3489
|
showElementLinks = !0,
|
|
3249
3490
|
showDiagramTitle = !0,
|
|
3491
|
+
showNotations = !0,
|
|
3250
3492
|
enableDynamicViewWalkthrough = !1,
|
|
3251
3493
|
enableFocusMode = !1,
|
|
3252
3494
|
initialWidth,
|
|
@@ -3294,6 +3536,7 @@ function LikeC4Diagram({
|
|
|
3294
3536
|
fitViewPadding,
|
|
3295
3537
|
showElementLinks,
|
|
3296
3538
|
showNavigationButtons,
|
|
3539
|
+
showNotations,
|
|
3297
3540
|
nodesDraggable,
|
|
3298
3541
|
nodesSelectable,
|
|
3299
3542
|
experimentalEdgeEditing,
|
|
@@ -3391,6 +3634,7 @@ function StaticLikeC4Diagram({
|
|
|
3391
3634
|
background,
|
|
3392
3635
|
showElementLinks: !0,
|
|
3393
3636
|
showDiagramTitle: !1,
|
|
3637
|
+
showNotations: !1,
|
|
3394
3638
|
enableDynamicViewWalkthrough: !1,
|
|
3395
3639
|
enableFocusMode: !1,
|
|
3396
3640
|
nodesSelectable: !1,
|
package/dist/mantine.css.d.ts
CHANGED