@likec4/diagram 1.27.0 → 1.27.2

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 (151) hide show
  1. package/bundle/index.js +2343 -6880
  2. package/dist/LikeC4Diagram.js +3 -9
  3. package/dist/LikeC4Diagram.props.d.ts +5 -3
  4. package/dist/StaticLikeC4Diagram.js +1 -1
  5. package/dist/_virtual/set.js +5 -0
  6. package/dist/_virtual/set2.js +3 -0
  7. package/dist/base/BaseXYFlow.d.ts +2 -1
  8. package/dist/base/primitives/compound/CompoundNodeContainer.d.ts +1 -1
  9. package/dist/base/primitives/compound/CompoundNodeContainer.js +1 -2
  10. package/dist/base/primitives/edge/EdgeLabel.css.js +1 -4
  11. package/dist/base/primitives/edge/EdgeLabelContainer.js +1 -1
  12. package/dist/base/primitives/edge/EdgePath.js +0 -3
  13. package/dist/base/primitives/edge/edge.css.js +2 -0
  14. package/dist/base/primitives/element/ElementActionButtons.js +5 -10
  15. package/dist/base/primitives/element/ElementNodeContainer.css.js +5 -4
  16. package/dist/base/primitives/element/ElementShape.css.js +1 -12
  17. package/dist/base/primitives/element/ElementTitle.css.js +3 -2
  18. package/dist/base/types.js +2 -2
  19. package/dist/base/updateEdges.js +1 -9
  20. package/dist/base/updateNodes.js +1 -12
  21. package/dist/bundle/LikeC4View.js +2 -2
  22. package/dist/bundle/LikeC4View.props.d.ts +7 -7
  23. package/dist/components/Link.js +1 -1
  24. package/dist/hooks/useCurrentViewId.js +8 -2
  25. package/dist/hooks/useDiagram.d.ts +2659 -1996
  26. package/dist/hooks/useDiagram.js +16 -8
  27. package/dist/likec4diagram/DiagramXYFlow.js +10 -9
  28. package/dist/likec4diagram/custom/edges/RelationshipEdge.js +30 -41
  29. package/dist/likec4diagram/custom/nodes/toolbar/Toolbar.js +1 -1
  30. package/dist/likec4diagram/custom/nodes/toolbar/styles.css.js +6 -1
  31. package/dist/likec4diagram/ui/controls/LayoutDriftNotification.js +13 -5
  32. package/dist/likec4diagram/ui/notation/NotationPanel.css.js +3 -3
  33. package/dist/likec4diagram/ui/notation/NotationPanel.js +10 -4
  34. package/dist/likec4diagram/useLayoutConstraints.d.ts +11 -10
  35. package/dist/likec4diagram/useLayoutConstraints.js +64 -61
  36. package/dist/node_modules/.pnpm/mnemonist@0.40.3_patch_hash_5c12abb43fcff6fd81e53021b89075d53249640d165a2556cc1e58d71201a13a/node_modules/mnemonist/set.js +369 -0
  37. package/dist/overlays/Overlays.js +5 -3
  38. package/dist/overlays/element-details/actor.d.ts +2769 -173
  39. package/dist/overlays/overlay/Overlay.css.d.ts +26 -2
  40. package/dist/overlays/overlay/Overlay.css.js +83 -16
  41. package/dist/overlays/overlay/Overlay.d.ts +7 -6
  42. package/dist/overlays/overlay/Overlay.js +39 -32
  43. package/dist/overlays/overlaysActor.js +2 -2
  44. package/dist/overlays/relationship-details/RelationshipDetails.js +113 -70
  45. package/dist/overlays/relationship-details/SelectEdge.d.ts +1 -1
  46. package/dist/overlays/relationship-details/SelectEdge.js +15 -9
  47. package/dist/overlays/relationship-details/_types.d.ts +4 -1
  48. package/dist/overlays/relationship-details/actor.d.ts +415 -128
  49. package/dist/overlays/relationship-details/actor.js +162 -53
  50. package/dist/overlays/relationship-details/compute.d.ts +12 -0
  51. package/dist/overlays/relationship-details/compute.js +139 -0
  52. package/dist/overlays/relationship-details/custom/ElementActions.js +27 -5
  53. package/dist/overlays/relationship-details/custom/edgeTypes.js +1 -1
  54. package/dist/overlays/relationship-details/custom/nodeTypes.d.ts +2 -1
  55. package/dist/overlays/relationship-details/hooks.d.ts +336 -6
  56. package/dist/overlays/relationship-details/hooks.js +9 -7
  57. package/dist/overlays/relationship-details/layout-to-xyflow.d.ts +12 -0
  58. package/dist/overlays/relationship-details/layout-to-xyflow.js +149 -0
  59. package/dist/overlays/relationship-details/layout.d.ts +22 -0
  60. package/dist/overlays/relationship-details/layout.js +314 -0
  61. package/dist/overlays/relationships-browser/RelationshipsBrowser.d.ts +3 -1
  62. package/dist/overlays/relationships-browser/RelationshipsBrowser.js +2 -2
  63. package/dist/overlays/relationships-browser/SelectElement.js +4 -4
  64. package/dist/overlays/relationships-browser/_types.d.ts +2 -0
  65. package/dist/overlays/relationships-browser/actor.d.ts +130 -14
  66. package/dist/overlays/relationships-browser/actor.js +30 -16
  67. package/dist/overlays/relationships-browser/custom/ElementActions.js +5 -3
  68. package/dist/overlays/relationships-browser/custom/edgeTypes.d.ts +3 -1
  69. package/dist/overlays/relationships-browser/custom/edgeTypes.js +1 -1
  70. package/dist/overlays/relationships-browser/hooks.d.ts +3 -1
  71. package/dist/overlays/relationships-browser/hooks.js +1 -1
  72. package/dist/overlays/relationships-browser/{-useRelationshipsView.d.ts → layout.d.ts} +2 -0
  73. package/dist/overlays/relationships-browser/{-useRelationshipsView.js → layout.js} +19 -2
  74. package/dist/overlays/relationships-browser/useViewToNodesEdges.d.ts +1 -1
  75. package/dist/overlays/relationships-browser/useViewToNodesEdges.js +3 -1
  76. package/dist/packages/core/src/compute-view/relationships-view/compute.js +1 -1
  77. package/dist/packages/core/src/model/connection/model/ConnectionModel.js +121 -0
  78. package/dist/packages/core/src/model/connection/model/find.js +39 -0
  79. package/dist/packages/core/src/model/connection/ops.js +7 -0
  80. package/dist/packages/core/src/utils/const.js +3 -0
  81. package/dist/packages/core/src/utils/fqn.js +9 -1
  82. package/dist/packages/core/src/utils/iterable/find.js +21 -0
  83. package/dist/packages/core/src/utils/iterable/some.js +21 -0
  84. package/dist/packages/core/src/utils/set.js +48 -0
  85. package/dist/packages/core/src/utils/string-hash.js +13 -0
  86. package/dist/state/DiagramActorProvider.d.ts +4 -2
  87. package/dist/state/DiagramActorProvider.js +30 -37
  88. package/dist/state/assign.js +2 -2
  89. package/dist/state/diagram-machine.d.ts +1731 -1040
  90. package/dist/state/diagram-machine.js +126 -60
  91. package/dist/state/syncManualLayoutActor.d.ts +1 -1
  92. package/dist/styles.css.js +1 -1
  93. package/package.json +11 -11
  94. package/src/LikeC4Diagram.props.ts +7 -3
  95. package/src/LikeC4Diagram.tsx +2 -8
  96. package/src/StaticLikeC4Diagram.tsx +1 -1
  97. package/src/base/BaseXYFlow.tsx +2 -1
  98. package/src/base/primitives/compound/CompoundNodeContainer.tsx +1 -3
  99. package/src/base/primitives/edge/EdgeLabel.css.ts +1 -4
  100. package/src/base/primitives/edge/EdgeLabelContainer.tsx +1 -1
  101. package/src/base/primitives/edge/EdgePath.tsx +0 -3
  102. package/src/base/primitives/edge/edge.css.ts +2 -0
  103. package/src/base/primitives/element/ElementActionButtons.tsx +6 -7
  104. package/src/base/primitives/element/ElementNodeContainer.css.ts +5 -4
  105. package/src/base/primitives/element/ElementShape.css.ts +1 -12
  106. package/src/base/primitives/element/ElementTitle.css.ts +3 -2
  107. package/src/base/types.ts +2 -7
  108. package/src/base/updateEdges.ts +8 -8
  109. package/src/base/updateNodes.ts +11 -11
  110. package/src/bundle/LikeC4View.props.ts +7 -7
  111. package/src/bundle/LikeC4View.tsx +2 -2
  112. package/src/components/Link.tsx +3 -1
  113. package/src/hooks/useCurrentViewId.ts +4 -2
  114. package/src/hooks/useDiagram.ts +18 -9
  115. package/src/likec4diagram/DiagramXYFlow.tsx +11 -9
  116. package/src/likec4diagram/custom/edges/RelationshipEdge.tsx +39 -48
  117. package/src/likec4diagram/custom/nodes/toolbar/Toolbar.tsx +2 -2
  118. package/src/likec4diagram/custom/nodes/toolbar/styles.css.ts +5 -0
  119. package/src/likec4diagram/ui/controls/LayoutDriftNotification.tsx +8 -4
  120. package/src/likec4diagram/ui/notation/NotationPanel.css.ts +2 -2
  121. package/src/likec4diagram/ui/notation/NotationPanel.tsx +8 -6
  122. package/src/likec4diagram/useLayoutConstraints.ts +84 -89
  123. package/src/overlays/Overlays.tsx +5 -3
  124. package/src/overlays/overlay/Overlay.css.ts +83 -15
  125. package/src/overlays/overlay/Overlay.tsx +52 -41
  126. package/src/overlays/overlaysActor.ts +1 -1
  127. package/src/overlays/relationship-details/RelationshipDetails.tsx +131 -68
  128. package/src/overlays/relationship-details/SelectEdge.tsx +19 -12
  129. package/src/overlays/relationship-details/_types.ts +3 -1
  130. package/src/overlays/relationship-details/actor.ts +217 -68
  131. package/src/overlays/relationship-details/compute.ts +186 -0
  132. package/src/overlays/relationship-details/custom/ElementActions.tsx +27 -18
  133. package/src/overlays/relationship-details/custom/edgeTypes.tsx +1 -1
  134. package/src/overlays/relationship-details/hooks.ts +10 -8
  135. package/src/overlays/relationship-details/layout-to-xyflow.ts +195 -0
  136. package/src/overlays/relationship-details/layout.ts +470 -0
  137. package/src/overlays/relationships-browser/RelationshipsBrowser.tsx +2 -2
  138. package/src/overlays/relationships-browser/SelectElement.tsx +5 -5
  139. package/src/overlays/relationships-browser/_types.ts +2 -0
  140. package/src/overlays/relationships-browser/actor.ts +39 -14
  141. package/src/overlays/relationships-browser/custom/ElementActions.tsx +5 -3
  142. package/src/overlays/relationships-browser/custom/edgeTypes.tsx +1 -1
  143. package/src/overlays/relationships-browser/hooks.ts +2 -2
  144. package/src/overlays/relationships-browser/{-useRelationshipsView.ts → layout.ts} +23 -13
  145. package/src/overlays/relationships-browser/useViewToNodesEdges.ts +3 -1
  146. package/src/state/DiagramActorProvider.tsx +40 -50
  147. package/src/state/assign.ts +2 -2
  148. package/src/state/diagram-machine.ts +151 -75
  149. package/dist/overlays/relationship-details/useLayoutedDetails.d.ts +0 -19
  150. package/dist/overlays/relationship-details/useLayoutedDetails.js +0 -267
  151. package/src/overlays/relationship-details/useLayoutedDetails.ts +0 -376
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@likec4/diagram",
3
- "version": "1.27.0",
3
+ "version": "1.27.2",
4
4
  "license": "MIT",
5
5
  "bugs": "https://github.com/likec4/likec4/issues",
6
6
  "homepage": "https://likec4.dev",
@@ -42,19 +42,19 @@
42
42
  },
43
43
  "dependencies": {
44
44
  "@dagrejs/dagre": "1.1.4",
45
- "@mantine/core": "7.17.2",
46
- "@mantine/hooks": "7.17.2",
45
+ "@mantine/core": "7.17.3",
46
+ "@mantine/hooks": "7.17.3",
47
47
  "@nanostores/react": "0.8.4",
48
48
  "@react-hookz/web": "^25.1.0",
49
49
  "@tabler/icons-react": "3.31.0",
50
50
  "@xstate/react": "^5.0.3",
51
- "@xyflow/react": "^12.4.4",
52
- "@xyflow/system": "^0.0.52",
51
+ "@xyflow/react": "^12.5.2",
52
+ "@xyflow/system": "^0.0.53",
53
53
  "bezier-js": "^6.1.4",
54
54
  "clsx": "^2.1.1",
55
55
  "d3-shape": "^3.2.0",
56
56
  "fast-equals": "^5.2.2",
57
- "framer-motion": "^12.5.0",
57
+ "framer-motion": "^12.6.2",
58
58
  "nanostores": "0.11.4",
59
59
  "react": "^19.0.0",
60
60
  "react-dom": "^19.0.0",
@@ -63,8 +63,8 @@
63
63
  "remeda": "^2.21.2",
64
64
  "type-fest": "^4.38.0",
65
65
  "xstate": "^5.19.2",
66
- "@likec4/styles": "1.27.0",
67
- "@likec4/core": "1.27.0"
66
+ "@likec4/core": "1.27.2",
67
+ "@likec4/styles": "1.27.2"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@pandacss/dev": "^0.53.3",
@@ -73,15 +73,15 @@
73
73
  "@types/d3-shape": "^3.1.7",
74
74
  "@types/react": "^19.0.12",
75
75
  "@types/react-dom": "^19.0.4",
76
- "@types/node": "^20.17.25",
76
+ "@types/node": "^20.17.28",
77
77
  "@vitejs/plugin-react": "^4.3.4",
78
78
  "postcss": "^8.5.3",
79
79
  "typescript": "^5.8.2",
80
- "vite": "^6.2.3",
80
+ "vite": "^6.2.4",
81
81
  "vite-plugin-dts": "^4.5.3",
82
82
  "vitest": "^3.0.9",
83
83
  "wireit": "^0.14.11",
84
- "@likec4/tsconfig": "1.27.0"
84
+ "@likec4/tsconfig": "1.27.2"
85
85
  },
86
86
  "scripts": {
87
87
  "generate": "panda codegen",
@@ -83,6 +83,9 @@ export type OverrideReactFlowProps = Pick<
83
83
  | 'nodeDragThreshold'
84
84
  >
85
85
 
86
+ export type PaddingUnit = 'px' | '%'
87
+ export type PaddingWithUnit = `${number}${PaddingUnit}` | number
88
+
86
89
  export interface LikeC4DiagramProperties {
87
90
  view: DiagramView
88
91
 
@@ -114,11 +117,12 @@ export interface LikeC4DiagramProperties {
114
117
  * @default true
115
118
  */
116
119
  fitView?: boolean | undefined
120
+
117
121
  /**
118
- * Seems like this is percentage of the view size
119
- * @default 0
122
+ * Padding around the diagram
123
+ * @default '8px'
120
124
  */
121
- fitViewPadding?: number | undefined
125
+ fitViewPadding?: PaddingWithUnit | undefined
122
126
 
123
127
  /**
124
128
  * @default false if readonly
@@ -35,7 +35,7 @@ export function LikeC4Diagram({
35
35
  view,
36
36
  className,
37
37
  fitView = true,
38
- fitViewPadding = 0,
38
+ fitViewPadding = '8px',
39
39
  readonly = true,
40
40
  pannable = true,
41
41
  zoomable = true,
@@ -70,12 +70,6 @@ export function LikeC4Diagram({
70
70
  initialHeight: number
71
71
  }>(null)
72
72
 
73
- const xyNodesEdges = useViewToNodesEdges({
74
- view,
75
- where,
76
- nodesSelectable,
77
- })
78
-
79
73
  const isDynamicView = view.__ === 'dynamic'
80
74
 
81
75
  if (initialRef.current == null) {
@@ -147,8 +141,8 @@ export function LikeC4Diagram({
147
141
  view,
148
142
  pannable,
149
143
  zoomable,
144
+ nodesSelectable,
150
145
  fitViewPadding,
151
- ...xyNodesEdges,
152
146
  }}>
153
147
  <ControlsCustomLayoutProvider value={renderControls ?? null}>
154
148
  <LikeC4DiagramXYFlow
@@ -21,7 +21,7 @@ export type StaticLikeC4DiagramProps = Pick<
21
21
  export function StaticLikeC4Diagram({
22
22
  view,
23
23
  fitView = true,
24
- fitViewPadding = 0,
24
+ fitViewPadding = '8px',
25
25
  enableElementDetails = false,
26
26
  enableRelationshipDetails = false,
27
27
  enableRelationshipBrowser = enableRelationshipDetails,
@@ -10,6 +10,7 @@ import { Fragment, useMemo } from 'react'
10
10
  import type { SetRequired, Simplify } from 'type-fest'
11
11
  import { useUpdateEffect } from '../hooks/useUpdateEffect'
12
12
  import { useIsZoomTooSmall, useXYStoreApi } from '../hooks/useXYFlow'
13
+ import type { PaddingWithUnit } from '../LikeC4Diagram.props'
13
14
  import { stopPropagation } from '../utils/xyflow'
14
15
  import { type XYBackground, Background } from './Background'
15
16
  import { MaxZoom, MinZoom } from './const'
@@ -22,7 +23,7 @@ export type BaseXYFlowProps<NodeType extends Base.Node, EdgeType extends Base.Ed
22
23
  nodesSelectable?: boolean
23
24
  nodesDraggable?: boolean
24
25
  background?: 'transparent' | 'solid' | XYBackground
25
- fitViewPadding?: number
26
+ fitViewPadding?: PaddingWithUnit | undefined
26
27
  onViewportResize?: undefined | (() => void)
27
28
  }
28
29
  & SetRequired<
@@ -11,7 +11,6 @@ type RequiredData = Pick<
11
11
  DiagramNode,
12
12
  | 'color'
13
13
  | 'depth'
14
- | 'shape'
15
14
  | 'style'
16
15
  >
17
16
 
@@ -73,13 +72,12 @@ export function CompoundNodeContainer({
73
72
  data-likec4-hovered={isHovered}
74
73
  data-likec4-color={data.color}
75
74
  data-compound-depth={depth}
76
- data-likec4-shape={data.shape}
77
75
  {...isTransparent && {
78
76
  'data-compound-transparent': true,
79
77
  'data-compound-title-inverse': opacity < 0.5,
80
78
  }}
81
79
  {...isDimmed !== false && {
82
- 'likec4-dimmed': isDimmed,
80
+ 'data-likec4-dimmed': isDimmed,
83
81
  }}
84
82
  style={{
85
83
  ...style,
@@ -50,7 +50,7 @@ export const edgeLabelContainer = css({
50
50
 
51
51
  _noReduceGraphics: {
52
52
  mixBlendMode: {
53
- base: 'plus-lighter',
53
+ _dark: 'plus-lighter',
54
54
  _light: 'screen',
55
55
  },
56
56
  },
@@ -61,9 +61,6 @@ export const edgeLabelContainer = css({
61
61
  _reduceGraphicsOnPan: {
62
62
  display: 'none',
63
63
  },
64
- _whenPanning: {
65
- mixBlendMode: 'normal',
66
- },
67
64
  })
68
65
 
69
66
  export const labelsva = sva({
@@ -32,7 +32,7 @@ type EdgeLabelContainerProps = HTMLAttributes<HTMLDivElement> & {
32
32
 
33
33
  const toCssVarValue = (value: number | string | undefined) => {
34
34
  if (value === undefined) return undefined
35
- return isNumber(value) ? `${value}px` : value
35
+ return isNumber(value) ? `${Math.round(value)}px` : value
36
36
  }
37
37
 
38
38
  export function EdgeLabelContainer({
@@ -92,9 +92,6 @@ export const EdgePath = forwardRef<SVGPathElement, EdgePathProps>(({
92
92
  'react-flow__edge-path',
93
93
  'react-flow__edge-interaction',
94
94
  cssEdgePath,
95
- // css({
96
- // strokeDasharray: strokeDasharray,
97
- // }),
98
95
  )}
99
96
  d={svgPath}
100
97
  style={style}
@@ -44,6 +44,7 @@ const _hideOnReducedGraphics = css.raw({
44
44
  export const hideOnReducedGraphics = css(_hideOnReducedGraphics)
45
45
 
46
46
  export const edgePathBg = css(_hideOnReducedGraphics, {
47
+ fill: '[none]',
47
48
  strokeWidth: 'calc(var(--xy-edge-stroke-width) + 2)',
48
49
  strokeOpacity: 0.08,
49
50
  transitionProperty: 'stroke-width, stroke-opacity',
@@ -70,6 +71,7 @@ export const markerContext = css({
70
71
  })
71
72
 
72
73
  export const cssEdgePath = css({
74
+ fill: '[none]',
73
75
  strokeDashoffset: 10,
74
76
  _noReduceGraphics: {
75
77
  transition: 'stroke 130ms ease-out,stroke-width 130ms ease-out',
@@ -68,15 +68,14 @@ export function ElementActionButtons({
68
68
  initial={false}
69
69
  whileTap={{ scale: 1 }}
70
70
  whileHover={{
71
- scale: 1.35,
71
+ scale: 1.3,
72
72
  }}
73
+ onTap={e => button.onClick(e as unknown as React.MouseEvent)}
74
+ // Otherwise node receives click event and is selected
75
+ onClick={stopPropagation}
76
+ onDoubleClick={stopPropagation}
73
77
  >
74
- <ActionIcon
75
- className={actionBtn({})}
76
- onClick={button.onClick}
77
- // Otherwise node receives click event and is selected
78
- onDoubleClick={stopPropagation}
79
- >
78
+ <ActionIcon className={actionBtn({})}>
80
79
  {button.icon}
81
80
  </ActionIcon>
82
81
  </m.div>
@@ -12,12 +12,13 @@ export const container = style({
12
12
  display: 'flex',
13
13
  alignItems: 'center',
14
14
  justifyContent: 'center',
15
- _after: {
15
+ pointerEvents: 'none',
16
+ _before: {
16
17
  content: '" "',
17
18
  position: 'absolute',
18
- top: '100%',
19
+ top: 'calc(100% - 4px)',
19
20
  left: 0,
20
- right: 0,
21
+ width: '100%',
21
22
  height: '24px',
22
23
  background: '[transparent]',
23
24
  pointerEvents: 'all',
@@ -42,7 +43,7 @@ export const container = style({
42
43
  // // filter: `grayscale(0.85) ${fallbackVar(vars.safariAnimationHook, 'blur(2px)')}`,
43
44
  // },
44
45
  _reduceGraphicsOnPan: {
45
- _after: {
46
+ _before: {
46
47
  display: 'none',
47
48
  },
48
49
  },
@@ -7,7 +7,7 @@ export const indicator = css({
7
7
  stroke: 'likec4.palette.loContrast',
8
8
  fill: '[none]',
9
9
 
10
- strokeWidth: 6,
10
+ strokeWidth: 8,
11
11
  strokeOpacity: 0.8,
12
12
  visibility: 'hidden',
13
13
  pointerEvents: 'none',
@@ -15,26 +15,15 @@ export const indicator = css({
15
15
  stroke: `[color-mix(in srgb, {colors.likec4.palette.fill} 50%,rgb(121, 121, 121))]`,
16
16
  },
17
17
  _whenFocused: {
18
- strokeWidth: 12,
19
18
  visibility: 'visible',
20
19
  },
21
20
  _groupFocusVisible: {
22
- strokeWidth: 12,
23
21
  visibility: 'visible',
24
22
  },
25
23
  _whenSelected: {
26
24
  animationStyle: 'indicator',
27
25
  visibility: 'visible',
28
26
  },
29
- _shapeQueue: {
30
- strokeWidth: 8,
31
- },
32
- _shapeCylinder: {
33
- strokeWidth: 8,
34
- },
35
- _shapeStorage: {
36
- strokeWidth: 8,
37
- },
38
27
  })
39
28
 
40
29
  export const fillElementFill = css({
@@ -20,7 +20,7 @@ const description = css.raw({
20
20
  display: 'none',
21
21
  },
22
22
  _smallZoom: {
23
- visibility: 'hidden',
23
+ display: 'none',
24
24
  },
25
25
  })
26
26
 
@@ -43,7 +43,7 @@ const technology = css.raw({
43
43
  display: 'none',
44
44
  },
45
45
  _smallZoom: {
46
- visibility: 'hidden',
46
+ display: 'none',
47
47
  },
48
48
  })
49
49
 
@@ -97,6 +97,7 @@ export const elementTitle = sva({
97
97
  paddingLeft: 'calc(var(--likec4-spacing) + 8px)',
98
98
  paddingRight: 'calc(var(--likec4-spacing) + 8px)',
99
99
  overflow: 'hidden',
100
+ pointerEvents: 'none',
100
101
  gap: '12px',
101
102
  _shapeQueue: {
102
103
  paddingLeft: '46px',
package/src/base/types.ts CHANGED
@@ -111,7 +111,7 @@ export namespace Base {
111
111
  type WithHovered = { data: { hovered?: boolean } }
112
112
 
113
113
  const _setDimmed = <T extends WithDimmed>(v: T, dimmed: Dimmed): T =>
114
- v.data.dimmed === dimmed ? v : ({
114
+ (v.data.dimmed ?? false) === dimmed ? v : ({
115
115
  ...v,
116
116
  data: {
117
117
  ...v.data,
@@ -129,7 +129,7 @@ export namespace Base {
129
129
  }
130
130
 
131
131
  const _setHovered = <T extends WithHovered>(v: T, hovered: boolean): T =>
132
- v.data.hovered === hovered ? v : ({
132
+ (v.data.hovered ?? false) === hovered ? v : ({
133
133
  ...v,
134
134
  data: {
135
135
  ...v.data,
@@ -167,8 +167,3 @@ export namespace Base {
167
167
  return (edge: E) => _setData(edge, arg1 as Partial<EdgeData>)
168
168
  }
169
169
  }
170
-
171
- // import type { ThemeColor } from '@likec4/core'
172
- // import type { ColorPalette as AllColorPalette } from '@likec4/styles/tokens'
173
-
174
- // export type ColorPalette = Extract<AllColorPalette, `likec4.${ThemeColor}` | `likec4.compound${number}.${ThemeColor}`>
@@ -17,14 +17,14 @@ function _update<E extends Base.Edge>(current: E[], update: E[]): E[] {
17
17
  ) {
18
18
  return existing
19
19
  }
20
- return {
21
- ...omit(existing, ['hidden', 'zIndex']),
22
- ...next,
23
- data: {
24
- ...existing.data,
25
- ...next.data,
26
- },
27
- }
20
+ // return {
21
+ // ...omit(existing, ['hidden', 'zIndex']),
22
+ // ...next,
23
+ // data: {
24
+ // ...existing.data,
25
+ // ...next.data,
26
+ // },
27
+ // }
28
28
  }
29
29
  return next
30
30
  })
@@ -20,17 +20,17 @@ function _update<N extends Base.Node>(current: N[], updated: N[]): N[] {
20
20
  ) {
21
21
  return existing
22
22
  }
23
- return {
24
- ...omit(existing, ['measured', 'parentId', 'hidden', 'zIndex']),
25
- ...update,
26
- // Force dimensions from update
27
- width: update.initialWidth,
28
- height: update.initialHeight,
29
- data: {
30
- ...existing.data,
31
- ...update.data,
32
- },
33
- } as N
23
+ // return {
24
+ // ...omit(existing, ['measured', 'parentId', 'hidden', 'zIndex']),
25
+ // ...update,
26
+ // // Force dimensions from update
27
+ // width: update.initialWidth,
28
+ // height: update.initialHeight,
29
+ // data: {
30
+ // ...existing.data,
31
+ // ...update.data,
32
+ // },
33
+ // } as N
34
34
  }
35
35
  return update
36
36
  })
@@ -1,6 +1,6 @@
1
1
  import type { WhereOperator } from '@likec4/core'
2
2
  import type { CSSProperties } from 'react'
3
- import type { ElementIconRenderer, OverrideReactFlowProps } from '../LikeC4Diagram.props'
3
+ import type { ElementIconRenderer, OverrideReactFlowProps, PaddingWithUnit } from '../LikeC4Diagram.props'
4
4
 
5
5
  export interface LikeC4ViewProps<ViewId = string, Tag = string, Kind = string> {
6
6
  /**
@@ -66,10 +66,10 @@ export interface LikeC4ViewProps<ViewId = string, Tag = string, Kind = string> {
66
66
  fitView?: boolean | undefined
67
67
 
68
68
  /**
69
- * Seems like this is percentage of the view size
70
- * @default 0.1
69
+ * Padding around the diagram
70
+ * @default '8px'
71
71
  */
72
- fitViewPadding?: number | undefined
72
+ fitViewPadding?: PaddingWithUnit | undefined
73
73
 
74
74
  /**
75
75
  * Display diagram title / description
@@ -163,10 +163,10 @@ export interface LikeC4BrowserProps {
163
163
  background?: 'dots' | 'lines' | 'cross' | 'transparent' | 'solid' | undefined
164
164
 
165
165
  /**
166
- * Seems like this is percentage of the view size
167
- * @default 0.1
166
+ * Padding around the diagram
167
+ * @default '16px'
168
168
  */
169
- fitViewPadding?: number | undefined
169
+ fitViewPadding?: PaddingWithUnit | undefined
170
170
 
171
171
  /**
172
172
  * Show/hide panel with top left controls,
@@ -61,7 +61,7 @@ const LikeC4ViewInner = memo<LikeC4ViewInnerProps>(({
61
61
  injectFontCss = true,
62
62
  controls = false,
63
63
  fitView = true,
64
- fitViewPadding = 0.1,
64
+ fitViewPadding = '8px',
65
65
  background = 'transparent',
66
66
  browser = true,
67
67
  showDiagramTitle = false,
@@ -169,7 +169,7 @@ const LikeC4ViewInner = memo<LikeC4ViewInnerProps>(({
169
169
  controls
170
170
  readonly
171
171
  fitView
172
- fitViewPadding={fitViewPadding}
172
+ fitViewPadding={'16px'}
173
173
  {...props}
174
174
  {...browserProps}
175
175
  showNotations={(browserProps.showNotations ?? true) &&
@@ -59,7 +59,9 @@ export function Link({
59
59
  value: LinkData
60
60
  }) {
61
61
  const isNormalSize = size === 'md'
62
- const url = new URL(value.url, window.location.href).toString()
62
+ // If the url is already a full url, use it as is.
63
+ // Otherwise, it's a relative url and we need to make it absolute.
64
+ const url = value.url.includes('://') ? value.url : new window.URL(value.url, window.location.href).toString()
63
65
  return (
64
66
  <CopyButton value={url}>
65
67
  {({ copied, copy }) => (
@@ -1,8 +1,10 @@
1
1
  import type { ViewId } from '@likec4/core'
2
+ import { useSelector } from '@xstate/react'
2
3
  import type { DiagramActorSnapshot } from '../state/types'
3
- import { useDiagramActorSnapshot } from './useDiagram'
4
+ import { useDiagramActorRef } from './useDiagram'
4
5
 
5
6
  const selectViewId = (s: DiagramActorSnapshot) => s.context.view.id
6
7
  export function useCurrentViewId(): ViewId {
7
- return useDiagramActorSnapshot(selectViewId)
8
+ const actorRef = useDiagramActorRef()
9
+ return useSelector(actorRef, selectViewId)
8
10
  }
@@ -1,4 +1,4 @@
1
- import { type DiagramView, type EdgeId, type Fqn, type NodeId, type ViewId } from '@likec4/core'
1
+ import { type DiagramView, type EdgeId, type ElementNotation, type Fqn, type NodeId, type ViewId } from '@likec4/core'
2
2
  import { useCallbackRef } from '@mantine/hooks'
3
3
  import { useSelector as useXstateSelector } from '@xstate/react'
4
4
  import { shallowEqual } from 'fast-equals'
@@ -45,17 +45,19 @@ export function useDiagram() {
45
45
  })
46
46
  },
47
47
  openSource: (params: OpenSourceParams) => {
48
- actor.send({ type: 'open.source', ...params })
49
- },
50
- openElementDetails: (fqn: Fqn, fromNode?: NodeId) => {
51
48
  startTransition(() => {
52
- actor.send({ type: 'open.elementDetails', fqn, fromNode })
49
+ actor.send({ type: 'open.source', ...params })
53
50
  })
54
51
  },
55
- openRelationshipDetails: (edgeId: EdgeId) => {
56
- startTransition(() => {
57
- actor.send({ type: 'open.relationshipDetails', edgeId })
58
- })
52
+ openElementDetails: (fqn: Fqn, fromNode?: NodeId) => {
53
+ actor.send({ type: 'open.elementDetails', fqn, fromNode })
54
+ },
55
+ openRelationshipDetails: (...params: [edgeId: EdgeId] | [source: Fqn, target: Fqn]) => {
56
+ if (params.length === 1) {
57
+ actor.send({ type: 'open.relationshipDetails', params: { edgeId: params[0] } })
58
+ } else {
59
+ actor.send({ type: 'open.relationshipDetails', params: { source: params[0], target: params[1] } })
60
+ }
59
61
  },
60
62
 
61
63
  updateNodeData: (nodeId: NodeId, data: PartialDeep<Types.NodeData>) => {
@@ -135,6 +137,13 @@ export function useDiagram() {
135
137
  toggleFeature: (feature: FeatureName, forceValue?: boolean) => {
136
138
  actor.send({ type: 'toggle.feature', feature, ...(forceValue !== undefined && { forceValue }) })
137
139
  },
140
+
141
+ highlightNotation: (notation: ElementNotation, kind?: string) => {
142
+ actor.send({ type: 'notations.highlight', notation, ...(kind && { kind }) })
143
+ },
144
+ unhighlightNotation: () => {
145
+ actor.send({ type: 'notations.unhighlight' })
146
+ },
138
147
  }), [actor])
139
148
  }
140
149
 
@@ -1,12 +1,12 @@
1
1
  import { type EdgeId, type NodeId, nonNullable } from '@likec4/core'
2
2
  import { cx } from '@likec4/styles/css'
3
- import { useCallbackRef, useTimeout } from '@mantine/hooks'
3
+ import { useCallbackRef, useDebouncedCallback, useTimeout } from '@mantine/hooks'
4
4
  import type { OnMove, OnMoveEnd } from '@xyflow/system'
5
5
  import { deepEqual, shallowEqual } from 'fast-equals'
6
6
  import { type PropsWithChildren, memo } from 'react'
7
7
  import { BaseXYFlow } from '../base/BaseXYFlow'
8
8
  import { useDiagramEventHandlers } from '../context'
9
- import { usePanningAtom } from '../context/ReduceGraphics'
9
+ import { useIsReducedGraphics, usePanningAtom } from '../context/ReduceGraphics'
10
10
  import { useDiagram, useDiagramContext } from '../hooks/useDiagram'
11
11
  import type { LikeC4DiagramProperties } from '../LikeC4Diagram.props'
12
12
  import type { DiagramContext } from '../state/types'
@@ -16,7 +16,7 @@ import type { Types } from './types'
16
16
  import { useLayoutConstraints } from './useLayoutConstraints'
17
17
 
18
18
  const selectXYProps = (ctx: DiagramContext) => ({
19
- initialized: ctx.initialized,
19
+ initialized: ctx.initialized.xydata && ctx.initialized.xyflow,
20
20
  nodes: ctx.xynodes,
21
21
  edges: ctx.xyedges,
22
22
  pannable: ctx.pannable,
@@ -87,12 +87,15 @@ export const LikeC4DiagramXYFlow = memo<LikeC4DiagramXYFlowProps>(({
87
87
  } = useDiagramEventHandlers()
88
88
 
89
89
  const notReadOnly = !enableReadOnly,
90
+ isReducedGraphics = useIsReducedGraphics(),
90
91
  layoutConstraints = useLayoutConstraints(),
91
92
  $isPanning = usePanningAtom(),
92
93
  isPanning = useTimeout(() => {
93
- $isPanning.set(true)
94
- }, 160),
95
- notPanning = useTimeout(() => {
94
+ if (!$isPanning.get()) {
95
+ $isPanning.set(true)
96
+ }
97
+ }, isReducedGraphics ? 150 : 350),
98
+ notPanning = useDebouncedCallback(() => {
96
99
  isPanning.clear()
97
100
  if ($isPanning.get()) {
98
101
  $isPanning.set(false)
@@ -105,11 +108,10 @@ export const LikeC4DiagramXYFlow = memo<LikeC4DiagramXYFlowProps>(({
105
108
  if (!$isPanning.get()) {
106
109
  isPanning.start()
107
110
  }
108
- notPanning.clear()
109
- notPanning.start()
111
+ notPanning()
110
112
  }),
111
113
  onMoveEnd: OnMoveEnd = useCallbackRef((event, viewport) => {
112
- notPanning.start()
114
+ notPanning.flush()
113
115
  diagram.send({ type: 'xyflow.viewportMoved', viewport, manually: !!event })
114
116
  }),
115
117
  onViewportResize = useCallbackRef(() => {