likec4 0.44.2 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/@likec4/core/utils/relations.js +11 -2
- package/dist/@likec4/diagrams/components/primitives/fullscreen/FullscreenDiagram.js +8 -7
- package/dist/@likec4/diagrams/diagram/Diagram.js +63 -45
- package/dist/@likec4/diagrams/diagram/Edges.js +32 -16
- package/dist/@likec4/diagrams/diagram/Nodes.js +66 -70
- package/dist/@likec4/diagrams/diagram/icons/ZoomIn.js +2 -3
- package/dist/@likec4/diagrams/diagram/shapes/Browser.js +43 -9
- package/dist/@likec4/diagrams/diagram/shapes/Compound.js +8 -10
- package/dist/@likec4/diagrams/diagram/shapes/Cylinder.js +3 -1
- package/dist/@likec4/diagrams/diagram/shapes/Edge.js +10 -10
- package/dist/@likec4/diagrams/diagram/shapes/Mobile.js +19 -4
- package/dist/@likec4/diagrams/diagram/shapes/NodeIcon.js +47 -9
- package/dist/@likec4/diagrams/diagram/shapes/NodeLabel.js +31 -54
- package/dist/@likec4/diagrams/diagram/shapes/Person.js +3 -1
- package/dist/@likec4/diagrams/diagram/shapes/Queue.js +3 -1
- package/dist/@likec4/diagrams/diagram/shapes/Rectangle.js +3 -1
- package/dist/@likec4/diagrams/diagram/shapes/index.js +1 -1
- package/dist/@likec4/diagrams/diagram/shapes/utils.js +1 -1
- package/dist/@likec4/diagrams/diagram/state/atoms.js +6 -0
- package/dist/@likec4/diagrams/diagram/state/hooks.js +10 -1
- package/dist/@likec4/diagrams/hooks/useDiagramApi.js +19 -22
- package/dist/@likec4/diagrams/hooks/useImageLoader.js +7 -1
- package/dist/__app__/index.html +1 -1
- package/dist/__app__/likec4.css +23 -0
- package/dist/__app__/src/App.jsx +27 -5
- package/dist/__app__/src/components/DiagramNotFound.jsx +10 -4
- package/dist/__app__/src/components/sidebar/Sidebar.jsx +1 -1
- package/dist/__app__/src/components/view-page/DisplayModeSelector.jsx +1 -1
- package/dist/__app__/src/components/view-page/ExportDiagram.jsx +13 -7
- package/dist/__app__/src/components/view-page/ViewActionsToolbar.jsx +12 -3
- package/dist/__app__/src/data/atoms.js +0 -11
- package/dist/__app__/src/pages/embed.page.jsx +14 -0
- package/dist/__app__/src/pages/export.page.jsx +4 -13
- package/dist/__app__/src/pages/index.js +1 -0
- package/dist/__app__/src/pages/useTransparentBackground.js +16 -0
- package/dist/__app__/src/pages/view-page.module.css +30 -0
- package/dist/__app__/src/pages/view.page.jsx +44 -8
- package/dist/__app__/src/router.js +14 -12
- package/dist/__app__/tailwind.config.cjs +1 -3
- package/dist/__app__/tsconfig.json +1 -7
- package/dist/cli/index.js +199 -206
- package/package.json +9 -10
- package/dist/@likec4/diagrams/hooks/useDarkMode.js +0 -5
- package/dist/@likec4/diagrams/index.mjs +0 -1927
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import { compareFqnHierarchically, isAncestor } from "./fqn.js";
|
|
1
|
+
import { commonAncestor, compareFqnHierarchically, isAncestor } from "./fqn.js";
|
|
2
2
|
import { either } from "rambdax";
|
|
3
3
|
export const compareRelations = (a, b) => {
|
|
4
|
-
|
|
4
|
+
const parentA = commonAncestor(a.source, a.target);
|
|
5
|
+
const parentB = commonAncestor(b.source, b.target);
|
|
6
|
+
if (parentA && !parentB) {
|
|
7
|
+
return 1;
|
|
8
|
+
}
|
|
9
|
+
if (!parentA && parentB) {
|
|
10
|
+
return -1;
|
|
11
|
+
}
|
|
12
|
+
const compareParents = parentA && parentB ? compareFqnHierarchically(parentA, parentB) : 0;
|
|
13
|
+
return compareParents || compareFqnHierarchically(a.source, b.source) || compareFqnHierarchically(a.target, b.target);
|
|
5
14
|
};
|
|
6
15
|
const isInside = (parent) => {
|
|
7
16
|
const prefix = parent + ".";
|
|
@@ -12,23 +12,24 @@ const StyleOverlay = {
|
|
|
12
12
|
left: 0,
|
|
13
13
|
right: 0,
|
|
14
14
|
bottom: 0,
|
|
15
|
-
backgroundColor: "var(--likec4-browser-overlay-bg, rgba(18,18,18,0.
|
|
15
|
+
backgroundColor: "var(--likec4-browser-overlay-bg, rgba(18,18,18,0.9))",
|
|
16
16
|
backdropFilter: "var(--likec4-browser-backdrop, blur(4px))",
|
|
17
17
|
zIndex: "var(--likec4-overlay-z-index, 100)",
|
|
18
|
-
display: "flex",
|
|
19
|
-
placeContent: "strech",
|
|
20
|
-
placeItems: "strech",
|
|
21
|
-
touchAction: "pan-x pan-y pinch-zoom",
|
|
22
18
|
boxSizing: "border-box",
|
|
23
19
|
margin: 0,
|
|
24
20
|
padding: 0,
|
|
25
21
|
border: "0 solid transparent"
|
|
26
22
|
};
|
|
27
23
|
const StyleContainer = {
|
|
24
|
+
position: "absolute",
|
|
25
|
+
top: 0,
|
|
26
|
+
left: 0,
|
|
27
|
+
right: 0,
|
|
28
|
+
bottom: 0,
|
|
28
29
|
margin: 0,
|
|
29
30
|
padding: 0,
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
overflow: "hidden",
|
|
32
|
+
touchAction: "pan-x pan-y pinch-zoom"
|
|
32
33
|
};
|
|
33
34
|
export function FullscreenDiagram({
|
|
34
35
|
diagram,
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { nonNullable, defaultTheme as theme } from "@likec4/core";
|
|
3
3
|
import { useHookableRef, useUpdateEffect } from "@react-hookz/web/esm";
|
|
4
|
-
import {
|
|
4
|
+
import { useSpring } from "@react-spring/konva";
|
|
5
5
|
import { clamp } from "rambdax";
|
|
6
6
|
import { forwardRef, useEffect, useImperativeHandle, useRef } from "react";
|
|
7
7
|
import { AnimatedStage, Layer } from "../konva.js";
|
|
8
8
|
import { Edges } from "./Edges.js";
|
|
9
9
|
import { createUseGesture, dragAction, pinchAction } from "@use-gesture/react";
|
|
10
10
|
import { Nodes } from "./Nodes.js";
|
|
11
|
-
import { DiagramGesture } from "./state/index.js";
|
|
11
|
+
import { DiagramGesture, useResetHoveredStates } from "./state/index.js";
|
|
12
12
|
const useGesture = createUseGesture([dragAction, pinchAction]);
|
|
13
13
|
const useSyncedRef = (value) => {
|
|
14
14
|
const ref = useRef(value);
|
|
@@ -30,7 +30,7 @@ function diagramNodeId(konvaNode) {
|
|
|
30
30
|
export const Diagram = /* @__PURE__ */ forwardRef(
|
|
31
31
|
({
|
|
32
32
|
diagram,
|
|
33
|
-
padding
|
|
33
|
+
padding = NoPadding,
|
|
34
34
|
pannable = true,
|
|
35
35
|
zoomable = true,
|
|
36
36
|
animate = true,
|
|
@@ -42,6 +42,8 @@ export const Diagram = /* @__PURE__ */ forwardRef(
|
|
|
42
42
|
onStageContextMenu,
|
|
43
43
|
width: _width,
|
|
44
44
|
height: _height,
|
|
45
|
+
minZoom = 0.2,
|
|
46
|
+
maxZoom = 1.1,
|
|
45
47
|
...props
|
|
46
48
|
}, ref) => {
|
|
47
49
|
const immediate = !animate;
|
|
@@ -54,15 +56,15 @@ export const Diagram = /* @__PURE__ */ forwardRef(
|
|
|
54
56
|
}
|
|
55
57
|
return value;
|
|
56
58
|
});
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
+
const [paddingTop, paddingRight, paddingBottom, paddingLeft] = Array.isArray(padding) ? padding : [padding, padding, padding, padding];
|
|
60
|
+
const width = _width ?? diagram.width + paddingLeft + paddingRight;
|
|
61
|
+
const height = _height ?? diagram.height + paddingTop + paddingBottom;
|
|
59
62
|
const toCenterOnRect = (centerTo) => {
|
|
60
|
-
const
|
|
61
|
-
const container = stageRef.current?.container();
|
|
63
|
+
const container = containerRef.current;
|
|
62
64
|
const viewRect = {
|
|
63
65
|
width: Math.min(container?.clientWidth ?? width, width) - paddingLeft - paddingRight,
|
|
64
66
|
height: Math.min(container?.clientHeight ?? height, height) - paddingTop - paddingBottom
|
|
65
|
-
}, viewScale = Math.min(viewRect.width / centerTo.width, viewRect.height / centerTo.height), scale = clamp(
|
|
67
|
+
}, viewScale = Math.min(viewRect.width / centerTo.width, viewRect.height / centerTo.height), scale = clamp(minZoom, maxZoom, viewScale), centeringAjustment = {
|
|
66
68
|
x: ((width - centerTo.width) * scale + viewRect.width) / 2,
|
|
67
69
|
y: ((height - centerTo.height) * scale + viewRect.height) / 2
|
|
68
70
|
}, finalPosition = {
|
|
@@ -78,11 +80,13 @@ export const Diagram = /* @__PURE__ */ forwardRef(
|
|
|
78
80
|
const [stageProps, stageSpringApi] = useSpring(
|
|
79
81
|
() => initialPosition ? {
|
|
80
82
|
from: initialPosition,
|
|
81
|
-
to: toFitDiagram()
|
|
83
|
+
to: toFitDiagram(),
|
|
84
|
+
immediate
|
|
82
85
|
} : {
|
|
83
|
-
|
|
86
|
+
to: toFitDiagram(),
|
|
84
87
|
immediate
|
|
85
|
-
}
|
|
88
|
+
},
|
|
89
|
+
[]
|
|
86
90
|
);
|
|
87
91
|
const centerOnRect = (centerTo) => {
|
|
88
92
|
stageSpringApi.start({
|
|
@@ -91,14 +95,10 @@ export const Diagram = /* @__PURE__ */ forwardRef(
|
|
|
91
95
|
});
|
|
92
96
|
return;
|
|
93
97
|
};
|
|
94
|
-
const centerAndFit = (delay =
|
|
98
|
+
const centerAndFit = (delay = 0) => {
|
|
95
99
|
stageSpringApi.start({
|
|
96
100
|
to: toFitDiagram(),
|
|
97
101
|
delay,
|
|
98
|
-
config: durationMs ? {
|
|
99
|
-
duration: durationMs,
|
|
100
|
-
easing: easings.easeInOutCubic
|
|
101
|
-
} : {},
|
|
102
102
|
immediate
|
|
103
103
|
});
|
|
104
104
|
return;
|
|
@@ -126,13 +126,13 @@ export const Diagram = /* @__PURE__ */ forwardRef(
|
|
|
126
126
|
ref,
|
|
127
127
|
() => ({
|
|
128
128
|
get stage() {
|
|
129
|
-
return
|
|
129
|
+
return stageRef.current;
|
|
130
130
|
},
|
|
131
131
|
get diagramView() {
|
|
132
132
|
return refs.current.diagram;
|
|
133
133
|
},
|
|
134
134
|
get container() {
|
|
135
|
-
return
|
|
135
|
+
return stageRef.current?.container() ?? null;
|
|
136
136
|
},
|
|
137
137
|
resetStageZoom: (_immediate) => {
|
|
138
138
|
refs.current.resetStageZoom(_immediate);
|
|
@@ -145,11 +145,18 @@ export const Diagram = /* @__PURE__ */ forwardRef(
|
|
|
145
145
|
}),
|
|
146
146
|
centerAndFit: () => refs.current.centerAndFit()
|
|
147
147
|
}),
|
|
148
|
-
[refs,
|
|
148
|
+
[refs, stageRef]
|
|
149
149
|
);
|
|
150
|
+
const resetHoveredStates = useResetHoveredStates();
|
|
150
151
|
useUpdateEffect(() => {
|
|
151
|
-
|
|
152
|
-
}, [id
|
|
152
|
+
resetHoveredStates();
|
|
153
|
+
}, [id]);
|
|
154
|
+
useUpdateEffect(() => {
|
|
155
|
+
refs.current.centerAndFit(200);
|
|
156
|
+
}, [id]);
|
|
157
|
+
useUpdateEffect(() => {
|
|
158
|
+
refs.current.centerAndFit(50);
|
|
159
|
+
}, [height, width]);
|
|
153
160
|
useEffect(() => {
|
|
154
161
|
if (!zoomable) {
|
|
155
162
|
return;
|
|
@@ -164,39 +171,41 @@ export const Diagram = /* @__PURE__ */ forwardRef(
|
|
|
164
171
|
}, [zoomable]);
|
|
165
172
|
useGesture(
|
|
166
173
|
{
|
|
167
|
-
onDragEnd: () => {
|
|
168
|
-
DiagramGesture.isDragging = false;
|
|
169
|
-
},
|
|
170
174
|
onDrag: (state) => {
|
|
171
175
|
const {
|
|
172
|
-
|
|
176
|
+
first,
|
|
177
|
+
last,
|
|
173
178
|
down,
|
|
174
|
-
cancel,
|
|
175
179
|
intentional,
|
|
176
180
|
offset: [x, y]
|
|
177
181
|
} = state;
|
|
178
|
-
if (
|
|
179
|
-
return
|
|
182
|
+
if (!intentional) {
|
|
183
|
+
return;
|
|
180
184
|
}
|
|
181
|
-
if (
|
|
182
|
-
DiagramGesture.isDragging =
|
|
183
|
-
stageSpringApi.start({
|
|
184
|
-
to: {
|
|
185
|
-
x,
|
|
186
|
-
y
|
|
187
|
-
},
|
|
188
|
-
immediate: immediate || down
|
|
189
|
-
});
|
|
185
|
+
if (first || last) {
|
|
186
|
+
DiagramGesture.isDragging = first && !last;
|
|
190
187
|
}
|
|
188
|
+
stageSpringApi.start({
|
|
189
|
+
to: {
|
|
190
|
+
x,
|
|
191
|
+
y
|
|
192
|
+
},
|
|
193
|
+
delay: 0,
|
|
194
|
+
immediate: immediate || down && !last
|
|
195
|
+
});
|
|
191
196
|
},
|
|
192
197
|
onPinch: ({ memo, first, last, origin: [ox, oy], movement: [ms], offset: [scale] }) => {
|
|
193
198
|
if (first) {
|
|
199
|
+
DiagramGesture.isDragging = true;
|
|
194
200
|
const stage = nonNullable(stageRef.current);
|
|
195
201
|
const { x: x2, y: y2 } = stage.getAbsolutePosition();
|
|
196
202
|
const tx = Math.round(ox - x2);
|
|
197
203
|
const ty = Math.round(oy - y2);
|
|
198
204
|
memo = [stage.x(), stage.y(), tx, ty];
|
|
199
205
|
}
|
|
206
|
+
if (last) {
|
|
207
|
+
DiagramGesture.isDragging = false;
|
|
208
|
+
}
|
|
200
209
|
const x = Math.round(memo[0] - (ms - 1) * memo[2]);
|
|
201
210
|
const y = Math.round(memo[1] - (ms - 1) * memo[3]);
|
|
202
211
|
stageSpringApi.start({
|
|
@@ -205,7 +214,7 @@ export const Diagram = /* @__PURE__ */ forwardRef(
|
|
|
205
214
|
y,
|
|
206
215
|
scale
|
|
207
216
|
},
|
|
208
|
-
|
|
217
|
+
delay: 0
|
|
209
218
|
});
|
|
210
219
|
return memo;
|
|
211
220
|
}
|
|
@@ -213,21 +222,30 @@ export const Diagram = /* @__PURE__ */ forwardRef(
|
|
|
213
222
|
{
|
|
214
223
|
target: containerRef,
|
|
215
224
|
drag: {
|
|
225
|
+
target: containerRef,
|
|
216
226
|
enabled: pannable,
|
|
217
227
|
threshold: 4,
|
|
218
|
-
from: () => [
|
|
219
|
-
pointer:
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
228
|
+
from: () => [stageRef.current?.x() ?? 0, stageRef.current?.y() ?? 0],
|
|
229
|
+
pointer: Object.assign(
|
|
230
|
+
{
|
|
231
|
+
keys: false,
|
|
232
|
+
mouse: true,
|
|
233
|
+
capture: true
|
|
234
|
+
},
|
|
235
|
+
!onNodeContextMenu && !onStageContextMenu && {
|
|
236
|
+
buttons: -1
|
|
237
|
+
}
|
|
238
|
+
)
|
|
223
239
|
},
|
|
224
240
|
pinch: {
|
|
241
|
+
target: containerRef,
|
|
225
242
|
pointer: {
|
|
226
243
|
touch: true
|
|
227
244
|
},
|
|
245
|
+
from: () => [stageRef.current?.scaleX() ?? 1, 0],
|
|
228
246
|
enabled: zoomable,
|
|
229
|
-
scaleBounds: { min:
|
|
230
|
-
rubberband: 0.
|
|
247
|
+
scaleBounds: { min: minZoom, max: maxZoom + 0.4 },
|
|
248
|
+
rubberband: 0.045,
|
|
231
249
|
pinchOnWheel: true
|
|
232
250
|
}
|
|
233
251
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { DefaultRelationshipColor } from "@likec4/core";
|
|
3
|
+
import { isEqualSimple } from "@react-hookz/deep-equal/esnext";
|
|
3
4
|
import { useTransition } from "@react-spring/konva";
|
|
4
5
|
import { scale, toHex } from "khroma";
|
|
5
6
|
import { memoize } from "rambdax";
|
|
6
|
-
import { useCallback } from "react";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { memo, useCallback } from "react";
|
|
8
|
+
import { AnimatedGroup } from "../konva.js";
|
|
9
|
+
import { Edge } from "./shapes/Edge.js";
|
|
9
10
|
import { mouseDefault, mousePointer } from "./shapes/utils.js";
|
|
10
11
|
import { DiagramGesture, useHoveredEdgeId, useSetHoveredEdge } from "./state/index.js";
|
|
11
12
|
const edgeColors = memoize((colors, isHovered) => {
|
|
@@ -13,13 +14,13 @@ const edgeColors = memoize((colors, isHovered) => {
|
|
|
13
14
|
return {
|
|
14
15
|
lineColor: toHex(
|
|
15
16
|
scale(colors.lineColor, {
|
|
16
|
-
l:
|
|
17
|
-
s: -5
|
|
17
|
+
l: 30
|
|
18
18
|
})
|
|
19
19
|
),
|
|
20
20
|
labelColor: toHex(
|
|
21
21
|
scale(colors.labelColor, {
|
|
22
|
-
l: 40
|
|
22
|
+
l: 40,
|
|
23
|
+
s: 5
|
|
23
24
|
})
|
|
24
25
|
),
|
|
25
26
|
labelBgColor: toHex(
|
|
@@ -34,7 +35,6 @@ const edgeColors = memoize((colors, isHovered) => {
|
|
|
34
35
|
});
|
|
35
36
|
export function Edges({ animate, theme, diagram, onEdgeClick }) {
|
|
36
37
|
const hoveredEdgeId = useHoveredEdgeId();
|
|
37
|
-
const setHoveredEdge = useSetHoveredEdge();
|
|
38
38
|
const edgeSprings = useCallback(
|
|
39
39
|
(edge, isHovered = false) => {
|
|
40
40
|
return {
|
|
@@ -83,9 +83,25 @@ export function Edges({ animate, theme, diagram, onEdgeClick }) {
|
|
|
83
83
|
// to avoid any issues with diagram-to-diagram transitions
|
|
84
84
|
keys: (e) => e.id + diagram.id
|
|
85
85
|
});
|
|
86
|
-
return edgeTransitions((
|
|
87
|
-
|
|
86
|
+
return edgeTransitions((_, edge, { key, ctrl }) => /* @__PURE__ */ jsx(
|
|
87
|
+
EdgeShape,
|
|
88
|
+
{
|
|
89
|
+
animate,
|
|
90
|
+
edge,
|
|
91
|
+
isHovered: hoveredEdgeId === edge.id,
|
|
92
|
+
theme,
|
|
93
|
+
ctrl,
|
|
94
|
+
onEdgeClick
|
|
95
|
+
},
|
|
96
|
+
key
|
|
97
|
+
));
|
|
98
|
+
}
|
|
99
|
+
const EdgeShape = memo(({ animate, edge, ctrl, theme, isHovered, onEdgeClick }) => {
|
|
100
|
+
const setHoveredEdge = useSetHoveredEdge();
|
|
101
|
+
return /* @__PURE__ */ jsx(
|
|
102
|
+
AnimatedGroup,
|
|
88
103
|
{
|
|
104
|
+
opacity: ctrl.springs.opacity,
|
|
89
105
|
onPointerClick: (e) => {
|
|
90
106
|
if (!onEdgeClick || DiagramGesture.isDragging || e.evt.button !== 0) {
|
|
91
107
|
return;
|
|
@@ -104,16 +120,16 @@ export function Edges({ animate, theme, diagram, onEdgeClick }) {
|
|
|
104
120
|
mouseDefault(e);
|
|
105
121
|
},
|
|
106
122
|
children: /* @__PURE__ */ jsx(
|
|
107
|
-
|
|
123
|
+
Edge,
|
|
108
124
|
{
|
|
109
125
|
animate,
|
|
110
126
|
edge,
|
|
111
|
-
isHovered
|
|
127
|
+
isHovered,
|
|
112
128
|
theme,
|
|
113
|
-
springs
|
|
129
|
+
springs: ctrl.springs
|
|
114
130
|
}
|
|
115
131
|
)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
}, isEqualSimple);
|
|
135
|
+
EdgeShape.displayName = "EdgeShape";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { nonexhaustive } from "@likec4/core";
|
|
3
|
+
import { isEqualSimple } from "@react-hookz/deep-equal/esnext";
|
|
3
4
|
import { useTransition } from "@react-spring/konva";
|
|
4
|
-
import { useRef } from "react";
|
|
5
|
+
import { memo, useRef } from "react";
|
|
5
6
|
import { AnimatedGroup } from "../konva.js";
|
|
6
7
|
import { Portal } from "../konva-portal.js";
|
|
7
8
|
import { ZoomInIcon } from "./icons/index.js";
|
|
@@ -115,7 +116,7 @@ export function Nodes({ animate, theme, diagram, onNodeClick }) {
|
|
|
115
116
|
keys: keyOf
|
|
116
117
|
});
|
|
117
118
|
return nodeTransitions((_, node, { key, ctrl, expired }) => /* @__PURE__ */ jsx(
|
|
118
|
-
|
|
119
|
+
NodeShape,
|
|
119
120
|
{
|
|
120
121
|
animate,
|
|
121
122
|
node,
|
|
@@ -128,26 +129,27 @@ export function Nodes({ animate, theme, diagram, onNodeClick }) {
|
|
|
128
129
|
key
|
|
129
130
|
));
|
|
130
131
|
}
|
|
131
|
-
|
|
132
|
-
animate,
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
{
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
132
|
+
const NodeShape = memo(
|
|
133
|
+
({ animate, node, ctrl, theme, isHovered, expired, onNodeClick }) => {
|
|
134
|
+
const setHoveredNode = useSetHoveredNode();
|
|
135
|
+
const _isCompound = isCompound(node);
|
|
136
|
+
const isNavigatable = animate && !!node.navigateTo && !!onNodeClick;
|
|
137
|
+
const Shape = nodeShape(node);
|
|
138
|
+
const springs = ctrl.springs;
|
|
139
|
+
let zoomInIconY;
|
|
140
|
+
switch (node.shape) {
|
|
141
|
+
case "browser":
|
|
142
|
+
case "mobile":
|
|
143
|
+
zoomInIconY = node.size.height - 20;
|
|
144
|
+
break;
|
|
145
|
+
default:
|
|
146
|
+
zoomInIconY = node.size.height - 16;
|
|
147
|
+
}
|
|
148
|
+
return /* @__PURE__ */ jsx(Portal, { selector: ".top", enabled: isHovered && !_isCompound, children: /* @__PURE__ */ jsxs(
|
|
149
|
+
AnimatedGroup,
|
|
150
|
+
{
|
|
151
|
+
name: node.id,
|
|
152
|
+
visible: expired !== true,
|
|
151
153
|
onPointerEnter: (e) => {
|
|
152
154
|
setHoveredNode(node);
|
|
153
155
|
if (isNavigatable) {
|
|
@@ -157,52 +159,46 @@ function NodeSnape({
|
|
|
157
159
|
onPointerLeave: (e) => {
|
|
158
160
|
setHoveredNode(null);
|
|
159
161
|
mouseDefault(e);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
e.cancelBubble = true;
|
|
168
|
-
onNodeClick(node, e);
|
|
169
|
-
}
|
|
170
|
-
},
|
|
171
|
-
x: springs.x,
|
|
172
|
-
y: springs.y,
|
|
173
|
-
offsetX: springs.offsetX,
|
|
174
|
-
offsetY: springs.offsetY,
|
|
175
|
-
width: springs.width,
|
|
176
|
-
height: springs.height,
|
|
177
|
-
scaleX: springs.scaleX,
|
|
178
|
-
scaleY: springs.scaleY,
|
|
179
|
-
opacity: springs.opacity,
|
|
180
|
-
children: [
|
|
181
|
-
_isCompound && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
182
|
-
/* @__PURE__ */ jsx(
|
|
183
|
-
CompoundShape,
|
|
184
|
-
{
|
|
185
|
-
node,
|
|
186
|
-
theme,
|
|
187
|
-
springs,
|
|
188
|
-
labelOffsetX: isNavigatable ? -12 : 4
|
|
189
|
-
}
|
|
190
|
-
),
|
|
191
|
-
isNavigatable && /* @__PURE__ */ jsx(ZoomInIcon, { fill: "#BABABA", opacity: 0.9, size: 16, x: 16, y: 17 })
|
|
192
|
-
] }),
|
|
193
|
-
!_isCompound && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
194
|
-
/* @__PURE__ */ jsx(Shape, { node, theme, springs, isHovered }),
|
|
195
|
-
isNavigatable && /* @__PURE__ */ jsx(
|
|
196
|
-
ZoomInIcon,
|
|
197
|
-
{
|
|
198
|
-
fill: "#BABABA",
|
|
199
|
-
size: 16,
|
|
200
|
-
x: node.size.width / 2,
|
|
201
|
-
y: node.size.height - 20
|
|
162
|
+
},
|
|
163
|
+
...onNodeClick && {
|
|
164
|
+
onPointerClick: (e) => {
|
|
165
|
+
if (DiagramGesture.isDragging || e.evt.button !== 0) {
|
|
166
|
+
return;
|
|
202
167
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
168
|
+
e.cancelBubble = true;
|
|
169
|
+
onNodeClick(node, e);
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
x: springs.x,
|
|
173
|
+
y: springs.y,
|
|
174
|
+
offsetX: springs.offsetX,
|
|
175
|
+
offsetY: springs.offsetY,
|
|
176
|
+
width: springs.width,
|
|
177
|
+
height: springs.height,
|
|
178
|
+
scaleX: springs.scaleX,
|
|
179
|
+
scaleY: springs.scaleY,
|
|
180
|
+
opacity: springs.opacity,
|
|
181
|
+
children: [
|
|
182
|
+
_isCompound && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
183
|
+
/* @__PURE__ */ jsx(
|
|
184
|
+
CompoundShape,
|
|
185
|
+
{
|
|
186
|
+
node,
|
|
187
|
+
theme,
|
|
188
|
+
springs,
|
|
189
|
+
labelOffsetX: isNavigatable ? -18 : 0
|
|
190
|
+
}
|
|
191
|
+
),
|
|
192
|
+
isNavigatable && /* @__PURE__ */ jsx(ZoomInIcon, { opacity: 0.9, size: 18, x: 18, y: 22 })
|
|
193
|
+
] }),
|
|
194
|
+
!_isCompound && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
195
|
+
/* @__PURE__ */ jsx(Shape, { node, theme, springs, isHovered }),
|
|
196
|
+
isNavigatable && /* @__PURE__ */ jsx(ZoomInIcon, { size: 16, x: node.size.width / 2, y: zoomInIconY })
|
|
197
|
+
] })
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
) });
|
|
201
|
+
},
|
|
202
|
+
isEqualSimple
|
|
203
|
+
);
|
|
204
|
+
NodeShape.displayName = "NodeShape";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Path } from "../../konva.js";
|
|
3
|
-
export const ZoomInIcon = ({ fill, opacity = 1, size = 20, x, y }) => {
|
|
3
|
+
export const ZoomInIcon = ({ fill = "#BABABA", opacity = 1, size = 20, x, y }) => {
|
|
4
4
|
const originalSize = 15;
|
|
5
5
|
const scale = size / originalSize;
|
|
6
6
|
const offsetIcon = originalSize / 2;
|
|
@@ -20,8 +20,7 @@ export const ZoomInIcon = ({ fill, opacity = 1, size = 20, x, y }) => {
|
|
|
20
20
|
width: originalSize,
|
|
21
21
|
height: originalSize,
|
|
22
22
|
opacity,
|
|
23
|
-
globalCompositeOperation: "luminosity"
|
|
24
|
-
hitStrokeWidth: 5
|
|
23
|
+
globalCompositeOperation: "luminosity"
|
|
25
24
|
}
|
|
26
25
|
);
|
|
27
26
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { AnimatedCircle, AnimatedRect } from "../../konva.js";
|
|
2
3
|
import { useShadowSprings } from "../springs.js";
|
|
3
|
-
import {
|
|
4
|
+
import { NodeIcon } from "./NodeIcon.js";
|
|
4
5
|
import { NodeLabels } from "./NodeLabel.js";
|
|
5
6
|
export function BrowserShape({ node, theme, springs, isHovered }) {
|
|
6
|
-
const colors = theme.elements[node.color];
|
|
7
7
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8
8
|
/* @__PURE__ */ jsx(
|
|
9
9
|
AnimatedRect,
|
|
@@ -13,12 +13,43 @@ export function BrowserShape({ node, theme, springs, isHovered }) {
|
|
|
13
13
|
strokeEnabled: false,
|
|
14
14
|
width: springs.width,
|
|
15
15
|
height: springs.height,
|
|
16
|
-
fill: springs.stroke
|
|
16
|
+
fill: springs.stroke,
|
|
17
|
+
perfectDrawEnabled: false
|
|
18
|
+
}
|
|
19
|
+
),
|
|
20
|
+
/* @__PURE__ */ jsx(
|
|
21
|
+
AnimatedCircle,
|
|
22
|
+
{
|
|
23
|
+
x: 16,
|
|
24
|
+
y: 15,
|
|
25
|
+
radius: 7,
|
|
26
|
+
fill: springs.fill,
|
|
27
|
+
listening: false,
|
|
28
|
+
perfectDrawEnabled: false
|
|
29
|
+
}
|
|
30
|
+
),
|
|
31
|
+
/* @__PURE__ */ jsx(
|
|
32
|
+
AnimatedCircle,
|
|
33
|
+
{
|
|
34
|
+
x: 36,
|
|
35
|
+
y: 15,
|
|
36
|
+
radius: 7,
|
|
37
|
+
fill: springs.fill,
|
|
38
|
+
listening: false,
|
|
39
|
+
perfectDrawEnabled: false
|
|
40
|
+
}
|
|
41
|
+
),
|
|
42
|
+
/* @__PURE__ */ jsx(
|
|
43
|
+
AnimatedCircle,
|
|
44
|
+
{
|
|
45
|
+
x: 56,
|
|
46
|
+
y: 15,
|
|
47
|
+
radius: 7,
|
|
48
|
+
fill: springs.fill,
|
|
49
|
+
listening: false,
|
|
50
|
+
perfectDrawEnabled: false
|
|
17
51
|
}
|
|
18
52
|
),
|
|
19
|
-
/* @__PURE__ */ jsx(Circle, { x: 16, y: 15, radius: 7, fill: colors.fill, listening: false }),
|
|
20
|
-
/* @__PURE__ */ jsx(Circle, { x: 36, y: 15, radius: 7, fill: colors.fill, listening: false }),
|
|
21
|
-
/* @__PURE__ */ jsx(Circle, { x: 56, y: 15, radius: 7, fill: colors.fill, listening: false }),
|
|
22
53
|
/* @__PURE__ */ jsx(
|
|
23
54
|
AnimatedRect,
|
|
24
55
|
{
|
|
@@ -28,7 +59,8 @@ export function BrowserShape({ node, theme, springs, isHovered }) {
|
|
|
28
59
|
width: springs.width.to((w) => w - 80),
|
|
29
60
|
height: 16,
|
|
30
61
|
fill: springs.fill,
|
|
31
|
-
listening: false
|
|
62
|
+
listening: false,
|
|
63
|
+
perfectDrawEnabled: false
|
|
32
64
|
}
|
|
33
65
|
),
|
|
34
66
|
/* @__PURE__ */ jsx(
|
|
@@ -40,9 +72,11 @@ export function BrowserShape({ node, theme, springs, isHovered }) {
|
|
|
40
72
|
width: springs.width.to((w) => w - 18),
|
|
41
73
|
height: springs.height.to((h) => h - 40),
|
|
42
74
|
fill: springs.fill,
|
|
43
|
-
listening: false
|
|
75
|
+
listening: false,
|
|
76
|
+
perfectDrawEnabled: false
|
|
44
77
|
}
|
|
45
78
|
),
|
|
46
|
-
/* @__PURE__ */ jsx(NodeLabels, { node, theme, offsetY: -
|
|
79
|
+
/* @__PURE__ */ jsx(NodeLabels, { node, theme, offsetY: -6 }),
|
|
80
|
+
/* @__PURE__ */ jsx(NodeIcon, { node, paddingY: 42 })
|
|
47
81
|
] });
|
|
48
82
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { AnimatedRect,
|
|
3
|
-
export function CompoundShape({ node, theme, springs, labelOffsetX =
|
|
2
|
+
import { AnimatedRect, Text } from "../../konva.js";
|
|
3
|
+
export function CompoundShape({ node, theme, springs, labelOffsetX = 0 }) {
|
|
4
4
|
const { labels } = node;
|
|
5
5
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
6
6
|
/* @__PURE__ */ jsx(
|
|
@@ -21,25 +21,23 @@ export function CompoundShape({ node, theme, springs, labelOffsetX = 4 }) {
|
|
|
21
21
|
}
|
|
22
22
|
),
|
|
23
23
|
labels.map(({ pt: [x, y], ...label }, i) => /* @__PURE__ */ jsx(
|
|
24
|
-
|
|
24
|
+
Text,
|
|
25
25
|
{
|
|
26
|
-
x,
|
|
27
|
-
y: y -
|
|
26
|
+
x: x - 6,
|
|
27
|
+
y: y - 8,
|
|
28
28
|
offsetX: labelOffsetX,
|
|
29
|
-
|
|
30
|
-
width: springs.width.to((v) => v - x - 4),
|
|
29
|
+
width: node.size.width - x - 8 - 6 + labelOffsetX,
|
|
31
30
|
fill: "#BABABA",
|
|
32
31
|
fontFamily: theme.font,
|
|
33
32
|
fontSize: label.fontSize,
|
|
34
33
|
fontStyle: label.fontStyle ?? "normal",
|
|
35
|
-
letterSpacing: 0.
|
|
34
|
+
letterSpacing: 0.75,
|
|
36
35
|
align: label.align,
|
|
37
36
|
text: label.text,
|
|
38
37
|
wrap: "none",
|
|
39
38
|
ellipsis: true,
|
|
40
39
|
perfectDrawEnabled: false,
|
|
41
|
-
padding:
|
|
42
|
-
hitStrokeWidth: 3,
|
|
40
|
+
padding: 8,
|
|
43
41
|
globalCompositeOperation: "luminosity"
|
|
44
42
|
},
|
|
45
43
|
i
|