likec4 0.40.1-build.4 → 0.42.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.
Files changed (52) hide show
  1. package/dist/@likec4/core/{colors.js → colors/element.js} +1 -23
  2. package/dist/@likec4/core/colors/index.js +9 -0
  3. package/dist/@likec4/core/colors/relationships.js +64 -0
  4. package/dist/@likec4/core/index.js +1 -3
  5. package/dist/@likec4/core/types/relation.js +3 -0
  6. package/dist/@likec4/core/types/view.js +1 -1
  7. package/dist/@likec4/core/utils/fqn.js +16 -4
  8. package/dist/@likec4/core/utils/guards.js +1 -0
  9. package/dist/@likec4/core/utils/index.js +0 -1
  10. package/dist/@likec4/diagrams/diagram/Diagram.js +2 -2
  11. package/dist/@likec4/diagrams/diagram/Edges.js +54 -49
  12. package/dist/@likec4/diagrams/diagram/Nodes.js +6 -7
  13. package/dist/@likec4/diagrams/diagram/icons/ExternalLink.js +1 -1
  14. package/dist/@likec4/diagrams/diagram/shapes/Browser.js +1 -2
  15. package/dist/@likec4/diagrams/diagram/shapes/Cylinder.js +0 -1
  16. package/dist/@likec4/diagrams/diagram/shapes/Edge.js +124 -35
  17. package/dist/@likec4/diagrams/diagram/shapes/Mobile.js +1 -1
  18. package/dist/@likec4/diagrams/diagram/shapes/NodeIcon.js +2 -1
  19. package/dist/@likec4/diagrams/diagram/shapes/NodeLabel.js +1 -1
  20. package/dist/@likec4/diagrams/diagram/shapes/Queue.js +0 -1
  21. package/dist/@likec4/diagrams/diagram/shapes/Rectangle.js +1 -1
  22. package/dist/@likec4/diagrams/diagram/springs.js +3 -3
  23. package/dist/@likec4/diagrams/diagram/state/atoms.js +4 -4
  24. package/dist/@likec4/diagrams/diagram/state/hooks.js +0 -11
  25. package/dist/@likec4/diagrams/konva.js +12 -1
  26. package/dist/__app__/likec4.css +1 -1
  27. package/dist/__app__/src/App.jsx +1 -1
  28. package/dist/__app__/src/components/view-page/ExportDiagram.jsx +72 -0
  29. package/dist/__app__/src/components/view-page/ShareDialog.jsx +2 -1
  30. package/dist/__app__/src/components/view-page/ViewActionsToolbar.jsx +38 -12
  31. package/dist/__app__/src/const.js +5 -0
  32. package/dist/__app__/src/likec4-views.js +15 -0
  33. package/dist/__app__/src/pages/export.page.jsx +6 -3
  34. package/dist/__app__/src/router.js +21 -21
  35. package/dist/__app__/tsconfig.json +2 -1
  36. package/dist/cli/index.js +203 -201
  37. package/package.json +25 -20
  38. package/dist/@likec4/core/compute-view/EdgeBuilder.js +0 -30
  39. package/dist/@likec4/core/compute-view/compute-ctx.js +0 -100
  40. package/dist/@likec4/core/compute-view/compute-element-view.js +0 -98
  41. package/dist/@likec4/core/compute-view/compute-predicates.js +0 -324
  42. package/dist/@likec4/core/compute-view/compute.js +0 -36
  43. package/dist/@likec4/core/compute-view/index.js +0 -4
  44. package/dist/@likec4/core/compute-view/resolve-extended-views.js +0 -41
  45. package/dist/@likec4/core/compute-view/resolve-relative-paths.js +0 -76
  46. package/dist/@likec4/core/compute-view/utils/anyPossibleRelations.js +0 -12
  47. package/dist/@likec4/core/compute-view/utils/applyViewRuleStyles.js +0 -50
  48. package/dist/@likec4/core/compute-view/utils/sortNodes.js +0 -37
  49. package/dist/@likec4/core/model-index/ModelIndex.js +0 -127
  50. package/dist/@likec4/core/model-index/index.js +0 -1
  51. package/dist/@likec4/core/utils/compute-node-levels.js +0 -31
  52. package/dist/@likec4/diagrams/hooks/useDiagramRef.js +0 -21
@@ -1,38 +1,22 @@
1
1
  const blue = {
2
- // fill: colors.blue[500],
3
- // stroke: colors.blue[600],
4
- // hiContrast: colors.blue[50],
5
- // loContrast: colors.blue[200],
6
2
  fill: "#3b82f6",
7
3
  stroke: "#2563eb",
8
4
  hiContrast: "#eff6ff",
9
5
  loContrast: "#bfdbfe"
10
6
  };
11
7
  const sky = {
12
- // fill: colors.sky[600],
13
- // stroke: colors.sky[700],
14
- // hiContrast: colors.sky[50],
15
- // loContrast: colors.sky[100],
16
8
  fill: "#0284c7",
17
9
  stroke: "#0369a1",
18
10
  hiContrast: "#f0f9ff",
19
11
  loContrast: "#e0f2fe"
20
12
  };
21
13
  const slate = {
22
- // fill: colors.slate[500],
23
- // stroke: colors.slate[600],
24
- // hiContrast: colors.slate[50],
25
- // loContrast: colors.slate[200],
26
14
  fill: "#64748b",
27
15
  stroke: "#475569",
28
16
  hiContrast: "#f8fafc",
29
17
  loContrast: "#e2e8f0"
30
18
  };
31
- export const RelationColors = {
32
- lineColor: "#b1b1b1",
33
- labelColor: "#b1b1b1"
34
- };
35
- export const Colors = {
19
+ export const ElementColors = {
36
20
  primary: blue,
37
21
  blue,
38
22
  secondary: sky,
@@ -96,9 +80,3 @@ export const Colors = {
96
80
  loContrast: "#c7d2fe"
97
81
  }
98
82
  };
99
- export const defaultTheme = {
100
- font: "Helvetica",
101
- shadow: "#0a0a0a",
102
- relation: RelationColors,
103
- colors: Colors
104
- };
@@ -0,0 +1,9 @@
1
+ import { ElementColors } from "./element.js";
2
+ import { RelationshipColors } from "./relationships.js";
3
+ export const defaultTheme = {
4
+ elements: ElementColors,
5
+ relationships: RelationshipColors,
6
+ font: "Helvetica",
7
+ shadow: "#0a0a0a"
8
+ };
9
+ export { ElementColors, RelationshipColors };
@@ -0,0 +1,64 @@
1
+ const gray = {
2
+ lineColor: "#6E6E6E",
3
+ labelBgColor: "#18191b",
4
+ labelColor: "#C6C6C6"
5
+ };
6
+ const slate = {
7
+ lineColor: "#64748b",
8
+ // 500
9
+ labelBgColor: "#0f172a",
10
+ // 900
11
+ labelColor: "#cbd5e1"
12
+ // 300
13
+ };
14
+ const blue = {
15
+ lineColor: "#3b82f6",
16
+ // 500
17
+ labelBgColor: "#172554",
18
+ // 950
19
+ labelColor: "#60a5fa"
20
+ // 400
21
+ };
22
+ const sky = {
23
+ lineColor: "#0ea5e9",
24
+ // 500
25
+ labelBgColor: "#082f49",
26
+ // 950
27
+ labelColor: "#38bdf8"
28
+ // 400
29
+ };
30
+ export const RelationshipColors = {
31
+ amber: {
32
+ lineColor: "#b45309",
33
+ labelBgColor: "#78350f",
34
+ labelColor: "#f59e0b"
35
+ },
36
+ blue,
37
+ gray,
38
+ green: {
39
+ lineColor: "#15803d",
40
+ // 700
41
+ labelBgColor: "#052e16",
42
+ //950
43
+ labelColor: "#22c55e"
44
+ // 500
45
+ },
46
+ indigo: {
47
+ lineColor: "#6366f1",
48
+ // 500
49
+ labelBgColor: "#1e1b4b",
50
+ // 950
51
+ labelColor: "#818cf8"
52
+ // 400
53
+ },
54
+ muted: slate,
55
+ primary: blue,
56
+ red: {
57
+ lineColor: "#b91c1c",
58
+ labelBgColor: "#b91c1c",
59
+ labelColor: "#dc2626"
60
+ },
61
+ secondary: sky,
62
+ sky,
63
+ slate
64
+ };
@@ -1,6 +1,4 @@
1
- export * from "./colors.js";
2
- export * from "./compute-view/index.js";
1
+ export * from "./colors/index.js";
3
2
  export * from "./errors/index.js";
4
- export * from "./model-index/index.js";
5
3
  export * from "./types/index.js";
6
4
  export * from "./utils/index.js";
@@ -0,0 +1,3 @@
1
+ export const DefaultLineStyle = "dashed";
2
+ export const DefaultArrowType = "normal";
3
+ export const DefaultRelationshipColor = "gray";
@@ -1,5 +1,5 @@
1
1
  export function isViewRuleExpression(rule) {
2
- return "exprs" in rule && "isInclude" in rule;
2
+ return "include" in rule && Array.isArray(rule.include) || "exclude" in rule && Array.isArray(rule.exclude);
3
3
  }
4
4
  export function isViewRuleStyle(rule) {
5
5
  return "style" in rule && "targets" in rule;
@@ -13,10 +13,10 @@ export function isAncestor(...args) {
13
13
  const another = isString(args[1]) ? args[1] : args[1].id;
14
14
  return another.startsWith(ancestor + ".");
15
15
  }
16
- export function isSameHierarchy(...args) {
17
- const one = isString(args[0]) ? args[0] : args[0].id;
18
- const another = isString(args[1]) ? args[1] : args[1].id;
19
- return one === another || another.startsWith(one + ".") || one.startsWith(another + ".");
16
+ export function isSameHierarchy(one, another) {
17
+ const first = isString(one) ? one : one.id;
18
+ const second = isString(another) ? another : another.id;
19
+ return first === second || second.startsWith(first + ".") || first.startsWith(second + ".");
20
20
  }
21
21
  export function isDescendantOf(ancestors) {
22
22
  const predicates = ancestors.flatMap((a) => [(e) => e.id === a.id, (e) => isAncestor(a, e)]);
@@ -52,6 +52,18 @@ export function parentFqn(fqn) {
52
52
  }
53
53
  return null;
54
54
  }
55
+ export function ancestorsFqn(fqn) {
56
+ const path = fqn.split(".");
57
+ path.pop();
58
+ if (path.length === 0) {
59
+ return [];
60
+ }
61
+ return path.reduce((acc, _, idx) => {
62
+ const ancestor = path.slice(0, idx + 1).join(".");
63
+ acc.unshift(ancestor);
64
+ return acc;
65
+ }, []);
66
+ }
55
67
  export function compareFqnHierarchically(a, b) {
56
68
  const depthA = a.split(".").length;
57
69
  const depthB = b.split(".").length;
@@ -1,3 +1,4 @@
1
+ export { hasAtLeast } from "remeda";
1
2
  export function isString(value) {
2
3
  return value != null && typeof value === "string";
3
4
  }
@@ -1,4 +1,3 @@
1
1
  export * from "./fqn.js";
2
2
  export * from "./guards.js";
3
- export * from "./compute-node-levels.js";
4
3
  export * from "./relations.js";
@@ -62,7 +62,7 @@ export const Diagram = /* @__PURE__ */ forwardRef(
62
62
  const viewRect = {
63
63
  width: Math.min(container?.clientWidth ?? width, width) - paddingLeft - paddingRight,
64
64
  height: Math.min(container?.clientHeight ?? height, height) - paddingTop - paddingBottom
65
- }, viewScale = Math.min(viewRect.width / centerTo.width, viewRect.height / centerTo.height), scale = clamp(0.1, 1, viewScale), centeringAjustment = {
65
+ }, viewScale = Math.min(viewRect.width / centerTo.width, viewRect.height / centerTo.height), scale = clamp(0.1, 1.1, viewScale), centeringAjustment = {
66
66
  x: ((width - centerTo.width) * scale + viewRect.width) / 2,
67
67
  y: ((height - centerTo.height) * scale + viewRect.height) / 2
68
68
  }, finalPosition = {
@@ -226,7 +226,7 @@ export const Diagram = /* @__PURE__ */ forwardRef(
226
226
  touch: true
227
227
  },
228
228
  enabled: zoomable,
229
- scaleBounds: { min: 0.2, max: 1.15 },
229
+ scaleBounds: { min: 0.1, max: 1.4 },
230
230
  rubberband: 0.05,
231
231
  pinchOnWheel: true
232
232
  }
@@ -1,72 +1,74 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { useMemo } from "react";
2
+ import { DefaultRelationshipColor } from "@likec4/core";
3
+ import { useTransition } from "@react-spring/konva";
4
+ import { scale, toHex } from "khroma";
5
+ import { memoize } from "rambdax";
6
+ import { useCallback } from "react";
3
7
  import { Group } from "../konva.js";
4
8
  import { EdgeShape } from "./shapes/Edge.js";
5
9
  import { mouseDefault, mousePointer } from "./shapes/utils.js";
6
10
  import { DiagramGesture, useHoveredEdgeId, useSetHoveredEdge } from "./state/index.js";
7
- import { useTransition } from "@react-spring/konva";
8
- import { scale, toHex } from "khroma";
9
- const edgeColors = ({ relation: { lineColor, labelColor } }, isHovered = false) => {
10
- if (Array.isArray(lineColor)) {
11
- lineColor = isHovered ? lineColor[1].onHover : lineColor[0];
12
- } else if (isHovered) {
13
- lineColor = toHex(
14
- scale(lineColor, {
15
- l: 35,
16
- s: -5
17
- })
18
- );
19
- }
20
- if (Array.isArray(labelColor)) {
21
- labelColor = isHovered ? labelColor[1].onHover : labelColor[0];
22
- } else if (isHovered) {
23
- labelColor = toHex(
24
- scale(labelColor, {
25
- l: 50
26
- })
27
- );
11
+ const edgeColors = memoize((colors, isHovered) => {
12
+ if (isHovered) {
13
+ return {
14
+ lineColor: toHex(
15
+ scale(colors.lineColor, {
16
+ l: 25,
17
+ s: -5
18
+ })
19
+ ),
20
+ labelColor: toHex(
21
+ scale(colors.labelColor, {
22
+ l: 40
23
+ })
24
+ ),
25
+ labelBgColor: toHex(
26
+ scale(colors.labelBgColor, {
27
+ l: -10
28
+ })
29
+ )
30
+ };
31
+ } else {
32
+ return colors;
28
33
  }
29
- return {
30
- lineColor,
31
- labelColor
32
- };
33
- };
34
+ });
34
35
  export function Edges({ animate, theme, diagram, onEdgeClick }) {
35
36
  const hoveredEdgeId = useHoveredEdgeId();
36
37
  const setHoveredEdge = useSetHoveredEdge();
37
- const colors = useMemo(
38
- () => ({
39
- base: edgeColors(theme),
40
- onHover: edgeColors(theme, true)
41
- }),
38
+ const edgeSprings = useCallback(
39
+ (edge, isHovered = false) => {
40
+ return {
41
+ opacity: 1,
42
+ lineWidth: 2,
43
+ ...edgeColors(theme.relationships[edge.color ?? DefaultRelationshipColor], isHovered)
44
+ };
45
+ },
42
46
  [theme]
43
47
  );
44
48
  const edgeTransitions = useTransition(diagram.edges, {
45
- initial: {
46
- opacity: 1,
47
- lineWidth: 2,
48
- ...colors.base
49
- },
50
- from: {
49
+ from: (edge) => ({
50
+ ...edgeSprings(edge),
51
51
  opacity: 0.15,
52
- lineWidth: 2,
53
- ...colors.base
54
- },
52
+ lineWidth: 2
53
+ }),
54
+ initial: (edge) => edgeSprings(edge),
55
55
  update: (edge) => {
56
56
  const isHovered = hoveredEdgeId === edge.id;
57
57
  return {
58
+ ...edgeSprings(edge, isHovered),
58
59
  opacity: 1,
59
- lineWidth: isHovered ? 3 : 2,
60
- ...isHovered ? colors.onHover : colors.base
60
+ lineWidth: isHovered ? 3 : 2
61
61
  };
62
62
  },
63
63
  enter: {
64
64
  opacity: 1
65
65
  },
66
- leave: {
67
- opacity: 0.05,
68
- lineWidth: 2,
69
- ...colors.base
66
+ leave: (edge) => {
67
+ return {
68
+ ...edgeSprings(edge),
69
+ opacity: 0.05,
70
+ lineWidth: 2
71
+ };
70
72
  },
71
73
  expires: true,
72
74
  exitBeforeEnter: true,
@@ -92,8 +94,10 @@ export function Edges({ animate, theme, diagram, onEdgeClick }) {
92
94
  onEdgeClick(edge, e);
93
95
  },
94
96
  onPointerEnter: (e) => {
95
- setHoveredEdge(edge);
96
- mousePointer(e);
97
+ if (animate) {
98
+ setHoveredEdge(edge);
99
+ mousePointer(e);
100
+ }
97
101
  },
98
102
  onPointerLeave: (e) => {
99
103
  setHoveredEdge(null);
@@ -103,6 +107,7 @@ export function Edges({ animate, theme, diagram, onEdgeClick }) {
103
107
  children: /* @__PURE__ */ jsx(
104
108
  EdgeShape,
105
109
  {
110
+ animate,
106
111
  edge,
107
112
  isHovered: hoveredEdgeId === edge.id,
108
113
  theme,
@@ -8,7 +8,7 @@ import { CylinderShape, MobileShape, PersonShape, QueueShape, RectangleShape } f
8
8
  import { BrowserShape } from "./shapes/Browser.js";
9
9
  import { CompoundShape } from "./shapes/Compound.js";
10
10
  import { mouseDefault, mousePointer } from "./shapes/utils.js";
11
- import { useNodeSpringsFn } from "./springs.js";
11
+ import { isCompound, useNodeSpringsFn } from "./springs.js";
12
12
  import { DiagramGesture, useHoveredNodeId, useSetHoveredNode } from "./state/index.js";
13
13
  function nodeShape({ shape }) {
14
14
  switch (shape) {
@@ -36,9 +36,6 @@ function nodeShape({ shape }) {
36
36
  }
37
37
  }
38
38
  }
39
- const isCompound = (node) => {
40
- return node.children.length > 0;
41
- };
42
39
  const keyOf = (node) => {
43
40
  const key = (node.parent ? node.parent + "-" : "") + node.id;
44
41
  if (isCompound(node)) {
@@ -79,7 +76,7 @@ export function Nodes({ animate, theme, diagram, onNodeClick }) {
79
76
  },
80
77
  // update: nodeSprings(),
81
78
  update: (node) => {
82
- const scale = !isCompound(node) && hoveredNodeId === node.id && animate ? 1.08 : 1;
79
+ const scale = animate && !isCompound(node) && hoveredNodeId === node.id ? 1.08 : 1;
83
80
  return {
84
81
  ...nodeSprings(node),
85
82
  scaleX: scale,
@@ -145,8 +142,10 @@ function NodeSnape({
145
142
  name: node.id,
146
143
  visible: expired !== true,
147
144
  onPointerEnter: (e) => {
148
- setHoveredNode(node);
149
- onNodeClick && animate && mousePointer(e);
145
+ if (animate) {
146
+ setHoveredNode(node);
147
+ onNodeClick && mousePointer(e);
148
+ }
150
149
  },
151
150
  onPointerLeave: (e) => {
152
151
  setHoveredNode(null);
@@ -4,7 +4,7 @@ import { defaultTheme as theme } from "@likec4/core";
4
4
  export const ExternalLink = ({
5
5
  visible = true,
6
6
  fill,
7
- fillIcon = theme.colors.primary.loContrast,
7
+ fillIcon = theme.elements.primary.loContrast,
8
8
  opacity = 1,
9
9
  scale = 1,
10
10
  x = 0,
@@ -3,14 +3,13 @@ import { useShadowSprings } from "../springs.js";
3
3
  import { AnimatedRect, Circle } from "../../konva.js";
4
4
  import { NodeLabels } from "./NodeLabel.js";
5
5
  export function BrowserShape({ node, theme, springs, isHovered }) {
6
- const colors = theme.colors[node.color];
6
+ const colors = theme.elements[node.color];
7
7
  return /* @__PURE__ */ jsxs(Fragment, { children: [
8
8
  /* @__PURE__ */ jsx(
9
9
  AnimatedRect,
10
10
  {
11
11
  ...useShadowSprings(isHovered, theme, springs),
12
12
  cornerRadius: 6,
13
- perfectDrawEnabled: false,
14
13
  strokeEnabled: false,
15
14
  width: springs.width,
16
15
  height: springs.height,
@@ -37,7 +37,6 @@ export function CylinderShape({ node, theme, springs, isHovered }) {
37
37
  {
38
38
  ...useShadowSprings(isHovered, theme, springs),
39
39
  data: path,
40
- perfectDrawEnabled: false,
41
40
  shadowForStrokeEnabled: false,
42
41
  fill: springs.fill
43
42
  }
@@ -1,61 +1,150 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { AnimatedCircle, AnimatedLine, AnimatedText } from "../../konva.js";
3
- import { invariant, nonNullable } from "@likec4/core";
4
- export function EdgeShape({ edge, theme, isHovered, springs }) {
5
- const { points, headArrow, labels } = edge;
6
- invariant(points[0], "Edge must have at least one point");
7
- const [x, y] = nonNullable(points[0]);
2
+ import { useSpring } from "@react-spring/konva";
3
+ import { AnimatedLine, AnimatedRect, AnimatedText } from "../../konva.js";
4
+ import {
5
+ DefaultArrowType,
6
+ DefaultLineStyle,
7
+ DefaultRelationshipColor
8
+ } from "@likec4/core";
9
+ function EdgeArrow({
10
+ arrowType,
11
+ points,
12
+ springs,
13
+ globalCompositeOperation
14
+ }) {
15
+ const isOutline = arrowType === "odiamond" || arrowType === "onormal";
16
+ return /* @__PURE__ */ jsx(
17
+ AnimatedLine,
18
+ {
19
+ opacity: springs.opacity,
20
+ points: points.flat(),
21
+ closed: true,
22
+ fill: isOutline ? void 0 : springs.lineColor,
23
+ stroke: springs.lineColor,
24
+ strokeWidth: 1.6,
25
+ hitStrokeWidth: 5,
26
+ lineCap: "round",
27
+ lineJoin: "miter",
28
+ globalCompositeOperation
29
+ }
30
+ );
31
+ }
32
+ function EdgeLabelBg({
33
+ animate,
34
+ labelBBox,
35
+ isHovered,
36
+ springs
37
+ }) {
38
+ const padding = 4;
39
+ const props = useSpring({
40
+ to: {
41
+ x: labelBBox.x - padding,
42
+ y: labelBBox.y - padding,
43
+ width: labelBBox.width + padding * 2,
44
+ height: labelBBox.height + padding * 2,
45
+ opacity: isHovered ? 0.25 : 0.1
46
+ },
47
+ immediate: !animate
48
+ });
49
+ return /* @__PURE__ */ jsx(
50
+ AnimatedRect,
51
+ {
52
+ ...props,
53
+ fill: springs.labelBgColor,
54
+ cornerRadius: 2,
55
+ globalCompositeOperation: "darken",
56
+ hitStrokeWidth: 5
57
+ }
58
+ );
59
+ }
60
+ export function EdgeShape({ animate = true, edge, theme, isHovered, springs }) {
61
+ const {
62
+ points,
63
+ head,
64
+ color,
65
+ line = DefaultLineStyle,
66
+ headArrow,
67
+ tail,
68
+ tailArrow,
69
+ labelBBox,
70
+ labels
71
+ } = edge;
72
+ const globalCompositeOperation = !color || color === DefaultRelationshipColor ? "luminosity" : "lighten";
73
+ const isDotted = line === "dotted";
74
+ const isDashed = isDotted || line === "dashed";
75
+ let dash;
76
+ if (isDotted) {
77
+ dash = [1, 5];
78
+ } else if (isDashed) {
79
+ dash = [10, 8];
80
+ }
8
81
  return /* @__PURE__ */ jsxs(Fragment, { children: [
9
- /* @__PURE__ */ jsx(
10
- AnimatedCircle,
11
- {
12
- opacity: springs.opacity,
13
- x,
14
- y,
15
- radius: springs.lineWidth.to((v) => v + 1),
16
- fill: springs.lineColor,
17
- visible: isHovered
18
- }
19
- ),
20
82
  /* @__PURE__ */ jsx(
21
83
  AnimatedLine,
22
84
  {
23
85
  opacity: springs.opacity,
24
86
  bezier: true,
25
- dashEnabled: true,
87
+ dashEnabled: isDashed,
88
+ dashOffset: 1,
26
89
  points: points.flat(),
90
+ dash,
27
91
  stroke: springs.lineColor,
28
92
  strokeWidth: springs.lineWidth,
29
- hitStrokeWidth: 20
93
+ hitStrokeWidth: 20,
94
+ lineCap: "round",
95
+ lineJoin: "round",
96
+ globalCompositeOperation
30
97
  }
31
98
  ),
32
- headArrow && /* @__PURE__ */ jsx(
33
- AnimatedLine,
99
+ head !== "none" && headArrow && /* @__PURE__ */ jsx(
100
+ EdgeArrow,
34
101
  {
35
- opacity: springs.opacity,
36
- points: headArrow.flat(),
37
- closed: true,
38
- fill: springs.lineColor,
39
- stroke: springs.lineColor,
40
- strokeWidth: 2,
41
- hitStrokeWidth: 5
102
+ arrowType: head ?? DefaultArrowType,
103
+ points: headArrow,
104
+ springs,
105
+ globalCompositeOperation
106
+ },
107
+ "head"
108
+ ),
109
+ tail !== "none" && tailArrow && /* @__PURE__ */ jsx(
110
+ EdgeArrow,
111
+ {
112
+ arrowType: tail ?? DefaultArrowType,
113
+ points: tailArrow,
114
+ springs,
115
+ globalCompositeOperation
116
+ },
117
+ "tail"
118
+ ),
119
+ labelBBox && labelBBox.width > 0 && /* @__PURE__ */ jsx(
120
+ EdgeLabelBg,
121
+ {
122
+ animate,
123
+ labelBBox,
124
+ isHovered,
125
+ springs
42
126
  }
43
127
  ),
44
- labels.map((label, i) => /* @__PURE__ */ jsx(
128
+ labels && labels.map((label, i) => /* @__PURE__ */ jsx(
45
129
  AnimatedText,
46
130
  {
47
- x: label.pt[0] - 4,
48
- y: label.pt[1] - label.fontSize / 2 - 4,
131
+ x: label.pt[0],
132
+ y: label.pt[1],
133
+ offsetY: label.fontSize / 2,
49
134
  opacity: springs.opacity,
50
- padding: 4,
51
135
  fill: springs.labelColor,
52
136
  fontFamily: theme.font,
53
137
  fontSize: label.fontSize,
54
138
  fontStyle: label.fontStyle ?? "normal",
55
- align: label.align,
56
139
  text: label.text,
57
- perfectDrawEnabled: false,
58
- hitStrokeWidth: 10
140
+ listening: false,
141
+ globalCompositeOperation,
142
+ shadowEnabled: springs.opacity.to((o) => o > 0.5),
143
+ shadowColor: "#222",
144
+ shadowOpacity: 0.15,
145
+ shadowOffsetX: 1,
146
+ shadowOffsetY: 2,
147
+ shadowBlur: 2
59
148
  },
60
149
  i
61
150
  ))
@@ -3,7 +3,7 @@ import { AnimatedRect, Circle } from "../../konva.js";
3
3
  import { NodeLabels } from "./NodeLabel.js";
4
4
  import { useShadowSprings } from "../springs.js";
5
5
  export function MobileShape({ node, theme, springs, isHovered }) {
6
- const colors = theme.colors[node.color];
6
+ const colors = theme.elements[node.color];
7
7
  return /* @__PURE__ */ jsxs(Fragment, { children: [
8
8
  /* @__PURE__ */ jsx(
9
9
  AnimatedRect,
@@ -22,7 +22,8 @@ export function NodeIcon({ icon, maxWidth, maxHeight, offsetX = 0, offsetY = 0 }
22
22
  offsetY,
23
23
  width: iconWidth,
24
24
  height: iconHeight,
25
- listening: false
25
+ listening: false,
26
+ globalCompositeOperation: "hard-light"
26
27
  }
27
28
  );
28
29
  }
@@ -8,7 +8,7 @@ export function NodeLabels({
8
8
  offsetY = 0,
9
9
  maxWidth
10
10
  }) {
11
- const colors = theme.colors[color];
11
+ const colors = theme.elements[color];
12
12
  const width = maxWidth ?? size.width;
13
13
  const firstLabel = labels[0];
14
14
  const titleFontSize = firstLabel?.fontSize ?? 12;
@@ -39,7 +39,6 @@ export function QueueShape({ node, theme, springs, isHovered }) {
39
39
  {
40
40
  ...useShadowSprings(isHovered, theme, springs),
41
41
  data: path,
42
- perfectDrawEnabled: false,
43
42
  fill: springs.fill
44
43
  }
45
44
  ),
@@ -1,7 +1,7 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { AnimatedRect } from "../../konva.js";
3
- import { NodeLabels } from "./NodeLabel.js";
4
3
  import { useShadowSprings } from "../springs.js";
4
+ import { NodeLabels } from "./NodeLabel.js";
5
5
  export function RectangleShape({ node, theme, springs, isHovered }) {
6
6
  return /* @__PURE__ */ jsxs(Fragment, { children: [
7
7
  /* @__PURE__ */ jsx(