@likec4/diagram 1.27.1 → 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 (115) hide show
  1. package/bundle/index.js +2147 -6730
  2. package/dist/LikeC4Diagram.js +1 -1
  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 +0 -1
  10. package/dist/base/primitives/element/ElementActionButtons.js +5 -10
  11. package/dist/base/primitives/element/ElementNodeContainer.css.js +4 -4
  12. package/dist/base/updateEdges.js +1 -9
  13. package/dist/base/updateNodes.js +1 -12
  14. package/dist/bundle/LikeC4View.js +2 -2
  15. package/dist/bundle/LikeC4View.props.d.ts +7 -7
  16. package/dist/hooks/useCurrentViewId.js +8 -2
  17. package/dist/hooks/useDiagram.d.ts +1517 -684
  18. package/dist/hooks/useDiagram.js +16 -8
  19. package/dist/likec4diagram/ui/notation/NotationPanel.css.js +3 -3
  20. package/dist/likec4diagram/ui/notation/NotationPanel.js +10 -4
  21. package/dist/node_modules/.pnpm/mnemonist@0.40.3_patch_hash_5c12abb43fcff6fd81e53021b89075d53249640d165a2556cc1e58d71201a13a/node_modules/mnemonist/set.js +369 -0
  22. package/dist/overlays/Overlays.js +3 -1
  23. package/dist/overlays/element-details/actor.d.ts +2769 -173
  24. package/dist/overlays/overlay/Overlay.css.d.ts +26 -2
  25. package/dist/overlays/overlay/Overlay.css.js +66 -18
  26. package/dist/overlays/overlay/Overlay.d.ts +7 -6
  27. package/dist/overlays/overlay/Overlay.js +12 -8
  28. package/dist/overlays/overlaysActor.js +2 -2
  29. package/dist/overlays/relationship-details/RelationshipDetails.js +113 -70
  30. package/dist/overlays/relationship-details/SelectEdge.d.ts +1 -1
  31. package/dist/overlays/relationship-details/SelectEdge.js +15 -9
  32. package/dist/overlays/relationship-details/_types.d.ts +4 -1
  33. package/dist/overlays/relationship-details/actor.d.ts +415 -128
  34. package/dist/overlays/relationship-details/actor.js +162 -53
  35. package/dist/overlays/relationship-details/compute.d.ts +12 -0
  36. package/dist/overlays/relationship-details/compute.js +139 -0
  37. package/dist/overlays/relationship-details/custom/ElementActions.js +27 -5
  38. package/dist/overlays/relationship-details/custom/edgeTypes.js +1 -1
  39. package/dist/overlays/relationship-details/custom/nodeTypes.d.ts +2 -1
  40. package/dist/overlays/relationship-details/hooks.d.ts +336 -6
  41. package/dist/overlays/relationship-details/hooks.js +9 -7
  42. package/dist/overlays/relationship-details/layout-to-xyflow.d.ts +12 -0
  43. package/dist/overlays/relationship-details/layout-to-xyflow.js +149 -0
  44. package/dist/overlays/relationship-details/layout.d.ts +22 -0
  45. package/dist/overlays/relationship-details/layout.js +314 -0
  46. package/dist/overlays/relationships-browser/RelationshipsBrowser.d.ts +3 -1
  47. package/dist/overlays/relationships-browser/RelationshipsBrowser.js +2 -2
  48. package/dist/overlays/relationships-browser/_types.d.ts +2 -0
  49. package/dist/overlays/relationships-browser/actor.d.ts +130 -14
  50. package/dist/overlays/relationships-browser/actor.js +30 -16
  51. package/dist/overlays/relationships-browser/custom/ElementActions.js +5 -3
  52. package/dist/overlays/relationships-browser/custom/edgeTypes.d.ts +3 -1
  53. package/dist/overlays/relationships-browser/custom/edgeTypes.js +1 -1
  54. package/dist/overlays/relationships-browser/hooks.d.ts +3 -1
  55. package/dist/overlays/relationships-browser/hooks.js +1 -1
  56. package/dist/overlays/relationships-browser/{-useRelationshipsView.d.ts → layout.d.ts} +2 -0
  57. package/dist/overlays/relationships-browser/{-useRelationshipsView.js → layout.js} +19 -2
  58. package/dist/overlays/relationships-browser/useViewToNodesEdges.d.ts +1 -1
  59. package/dist/overlays/relationships-browser/useViewToNodesEdges.js +3 -1
  60. package/dist/packages/core/src/compute-view/relationships-view/compute.js +1 -1
  61. package/dist/packages/core/src/model/connection/model/ConnectionModel.js +121 -0
  62. package/dist/packages/core/src/model/connection/model/find.js +39 -0
  63. package/dist/packages/core/src/model/connection/ops.js +7 -0
  64. package/dist/packages/core/src/utils/const.js +3 -0
  65. package/dist/packages/core/src/utils/fqn.js +9 -1
  66. package/dist/packages/core/src/utils/iterable/find.js +21 -0
  67. package/dist/packages/core/src/utils/iterable/some.js +21 -0
  68. package/dist/packages/core/src/utils/set.js +48 -0
  69. package/dist/packages/core/src/utils/string-hash.js +13 -0
  70. package/dist/state/diagram-machine.d.ts +1552 -703
  71. package/dist/state/diagram-machine.js +39 -3
  72. package/dist/state/syncManualLayoutActor.d.ts +1 -1
  73. package/dist/styles.css.js +1 -1
  74. package/package.json +11 -11
  75. package/src/LikeC4Diagram.props.ts +7 -3
  76. package/src/LikeC4Diagram.tsx +1 -1
  77. package/src/StaticLikeC4Diagram.tsx +1 -1
  78. package/src/base/BaseXYFlow.tsx +2 -1
  79. package/src/base/primitives/compound/CompoundNodeContainer.tsx +0 -2
  80. package/src/base/primitives/element/ElementActionButtons.tsx +6 -7
  81. package/src/base/primitives/element/ElementNodeContainer.css.ts +4 -4
  82. package/src/base/updateEdges.ts +8 -8
  83. package/src/base/updateNodes.ts +11 -11
  84. package/src/bundle/LikeC4View.props.ts +7 -7
  85. package/src/bundle/LikeC4View.tsx +2 -2
  86. package/src/hooks/useCurrentViewId.ts +4 -2
  87. package/src/hooks/useDiagram.ts +18 -9
  88. package/src/likec4diagram/ui/notation/NotationPanel.css.ts +2 -2
  89. package/src/likec4diagram/ui/notation/NotationPanel.tsx +8 -6
  90. package/src/overlays/Overlays.tsx +3 -1
  91. package/src/overlays/overlay/Overlay.css.ts +67 -17
  92. package/src/overlays/overlay/Overlay.tsx +26 -21
  93. package/src/overlays/overlaysActor.ts +1 -1
  94. package/src/overlays/relationship-details/RelationshipDetails.tsx +131 -68
  95. package/src/overlays/relationship-details/SelectEdge.tsx +19 -12
  96. package/src/overlays/relationship-details/_types.ts +3 -1
  97. package/src/overlays/relationship-details/actor.ts +217 -68
  98. package/src/overlays/relationship-details/compute.ts +186 -0
  99. package/src/overlays/relationship-details/custom/ElementActions.tsx +27 -18
  100. package/src/overlays/relationship-details/custom/edgeTypes.tsx +1 -1
  101. package/src/overlays/relationship-details/hooks.ts +10 -8
  102. package/src/overlays/relationship-details/layout-to-xyflow.ts +195 -0
  103. package/src/overlays/relationship-details/layout.ts +470 -0
  104. package/src/overlays/relationships-browser/RelationshipsBrowser.tsx +2 -2
  105. package/src/overlays/relationships-browser/_types.ts +2 -0
  106. package/src/overlays/relationships-browser/actor.ts +39 -14
  107. package/src/overlays/relationships-browser/custom/ElementActions.tsx +5 -3
  108. package/src/overlays/relationships-browser/custom/edgeTypes.tsx +1 -1
  109. package/src/overlays/relationships-browser/hooks.ts +2 -2
  110. package/src/overlays/relationships-browser/{-useRelationshipsView.ts → layout.ts} +23 -13
  111. package/src/overlays/relationships-browser/useViewToNodesEdges.ts +3 -1
  112. package/src/state/diagram-machine.ts +51 -6
  113. package/dist/overlays/relationship-details/useLayoutedDetails.d.ts +0 -19
  114. package/dist/overlays/relationship-details/useLayoutedDetails.js +0 -267
  115. 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.1",
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.1",
67
- "@likec4/core": "1.27.1"
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.27",
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.1"
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,
@@ -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,7 +72,6 @@ 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,
@@ -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>
@@ -13,12 +13,12 @@ export const container = style({
13
13
  alignItems: 'center',
14
14
  justifyContent: 'center',
15
15
  pointerEvents: 'none',
16
- _after: {
16
+ _before: {
17
17
  content: '" "',
18
18
  position: 'absolute',
19
- top: '100%',
19
+ top: 'calc(100% - 4px)',
20
20
  left: 0,
21
- right: 0,
21
+ width: '100%',
22
22
  height: '24px',
23
23
  background: '[transparent]',
24
24
  pointerEvents: 'all',
@@ -43,7 +43,7 @@ export const container = style({
43
43
  // // filter: `grayscale(0.85) ${fallbackVar(vars.safariAnimationHook, 'blur(2px)')}`,
44
44
  // },
45
45
  _reduceGraphicsOnPan: {
46
- _after: {
46
+ _before: {
47
47
  display: 'none',
48
48
  },
49
49
  },
@@ -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) &&
@@ -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
 
@@ -98,6 +98,6 @@ export const shapeBadge = css({
98
98
  ['--badge-padding-x']: '3px',
99
99
  ['--badge-height']: '13.5px',
100
100
  ['--badge-lh']: '1',
101
- // ['--badge-bg']: vars.element.fill,
102
- // ['--badge-color']: vars.element.hiContrast
101
+ ['--badge-bg']: '{colors.likec4.palette.fill}',
102
+ ['--badge-color']: '{colors.likec4.palette.hiContrast}',
103
103
  })
@@ -54,13 +54,14 @@ const ElementNotation = ({ value }: { value: ElementNotationData }) => {
54
54
  likec4Palette: color,
55
55
  }),
56
56
  )}
57
+ data-likec4-color={color}
57
58
  onMouseEnter={() => {
58
59
  setOnlyKind(null)
59
- // diagramStore.getState().highlightByElementNotation(value)
60
+ diagram.highlightNotation(value)
60
61
  }}
61
62
  onMouseLeave={() => {
62
63
  setOnlyKind(null)
63
- // diagramStore.setState({ dimmed: new Set() })
64
+ diagram.unhighlightNotation()
64
65
  }}
65
66
  >
66
67
  <Group
@@ -88,17 +89,18 @@ const ElementNotation = ({ value }: { value: ElementNotationData }) => {
88
89
  {value.kinds.map((kind) => (
89
90
  <Badge
90
91
  key={kind}
91
- className={styles.shapeBadge}
92
+ className={cx(
93
+ styles.shapeBadge,
94
+ )}
92
95
  onMouseEnter={() => {
93
96
  setOnlyKind(kind)
94
- // diagramStore.getState().highlightByElementNotation(value, kind)
97
+ diagram.highlightNotation(value, kind)
95
98
  }}
96
99
  onMouseLeave={() => {
97
100
  setOnlyKind(null)
98
- // diagramStore.getState().highlightByElementNotation(value)
101
+ diagram.highlightNotation(value)
99
102
  }}
100
103
  opacity={isNonNullish(onlyKind) && onlyKind !== kind ? 0.25 : 1}
101
- color={isNonNullish(onlyKind) && onlyKind !== kind ? 'gray' : token('colors.likec4.palette.fill')}
102
104
  >
103
105
  {kind}
104
106
  </Badge>
@@ -102,12 +102,13 @@ export const Overlays = memo(({ overlaysActorRef }: { overlaysActorRef: Overlays
102
102
  overlaysActorRef.send({ type: 'close', actorId: actorRef.id })
103
103
  }
104
104
 
105
- const overlaysReact = overlays.map((overlay) => {
105
+ const overlaysReact = overlays.map((overlay, index) => {
106
106
  switch (overlay.type) {
107
107
  case 'relationshipsBrowser':
108
108
  return (
109
109
  <Overlay
110
110
  key={overlay.actorRef.sessionId}
111
+ overlayLevel={Math.min(index, 3) as 0 | 1 | 2 | 3}
111
112
  onClose={() => close(overlay.actorRef)}>
112
113
  <RelationshipsBrowser actorRef={overlay.actorRef} />
113
114
  </Overlay>
@@ -115,6 +116,7 @@ export const Overlays = memo(({ overlaysActorRef }: { overlaysActorRef: Overlays
115
116
  case 'relationshipDetails':
116
117
  return (
117
118
  <Overlay
119
+ overlayLevel={Math.min(index, 3) as 0 | 1 | 2 | 3}
118
120
  key={overlay.actorRef.sessionId}
119
121
  onClose={() => close(overlay.actorRef)}>
120
122
  <RelationshipDetails actorRef={overlay.actorRef} />
@@ -1,10 +1,14 @@
1
- import { css } from '@likec4/styles/css'
1
+ import { css, sva } from '@likec4/styles/css'
2
2
 
3
3
  export const backdropBlur = '--_blur'
4
4
  export const backdropOpacity = '--_opacity'
5
5
 
6
+ export const level = '--_level'
7
+ const offset = '--_offset'
8
+ const inset = '--_inset'
9
+
6
10
  const borderRadius = '--_border-radius'
7
- export const dialog = css({
11
+ const dialog = css.raw({
8
12
  boxSizing: 'border-box',
9
13
  margin: 0,
10
14
  position: 'fixed',
@@ -18,6 +22,9 @@ export const dialog = css({
18
22
  outline: 'none',
19
23
  borderRadius: `var(${borderRadius})`,
20
24
  [backdropBlur]: '0px',
25
+ [level]: '0',
26
+ [offset]: '0px',
27
+ [inset]: 'calc((1 + var(--_level) * 0.5) * var(--_offset))',
21
28
  [backdropOpacity]: '0%',
22
29
  _backdrop: {
23
30
  cursor: 'zoom-out',
@@ -32,36 +39,47 @@ export const dialog = css({
32
39
  border: 'none',
33
40
  inset: 0,
34
41
  padding: 0,
42
+ // [offset]: '0px',
43
+ // [inset]: '0px',
35
44
  width: '100vw',
36
45
  height: '100vh',
37
46
  },
38
47
  sm: {
48
+ inset: '[var(--_inset) var(--_offset) var(--_offset) var(--_inset)]',
49
+ width: 'calc(100vw - var(--_offset) - var(--_inset))',
50
+ height: 'calc(100vh - var(--_offset) - var(--_inset))',
39
51
  [borderRadius]: '6px',
40
52
  padding: '6px',
41
- inset: '1rem',
42
- width: 'calc(100vw - 2rem)',
43
- height: 'calc(100vh - 2rem)',
53
+ [offset]: '1rem',
44
54
  },
45
55
  md: {
46
- inset: '2rem',
47
- width: 'calc(100vw - 4rem)',
48
- height: 'calc(100vh - 4rem)',
56
+ [offset]: '1rem',
49
57
  },
50
58
  lg: {
51
- inset: '4rem',
52
- width: 'calc(100vw - 8rem)',
53
- height: 'calc(100vh - 8rem)',
59
+ [offset]: '2rem',
54
60
  },
55
61
  xl: {
56
- [borderRadius]: '8px',
57
- padding: '8px',
58
- inset: '5rem',
59
- width: 'calc(100vw - 10rem)',
60
- height: 'calc(100vh - 10rem)',
62
+ [offset]: '4rem',
61
63
  },
64
+ // inset: '[calc(2rem + var(--_level, 0) * 1rem), 2rem, 2rem, 2rem]',
65
+ // width: 'calc(100vw - 4rem)',
66
+ // height: 'calc(100vh - 4rem - var(--_level, 0) * 1rem)',
67
+ // },
68
+ // lg: {
69
+ // inset: '[calc(4rem + var(--_level, 0) * 1rem), 4rem, 4rem, 4rem]',
70
+ // width: 'calc(100vw - 8rem)',
71
+ // height: 'calc(100vh - 8rem)',
72
+ // },
73
+ // xl: {
74
+ // [borderRadius]: '8px',
75
+ // padding: '8px',
76
+ // inset: '[calc(5rem + var(--_level, 0) * 1rem), 5rem, 5rem, 5rem]',
77
+ // width: 'calc(100vw - 10rem)',
78
+ // height: 'calc(100vh - 10rem - var(--_level, 0) * 1rem)',
79
+ // },
62
80
  })
63
81
 
64
- export const body = css({
82
+ const body = css.raw({
65
83
  position: 'relative',
66
84
  containerName: 'overlay-dialog',
67
85
  containerType: 'size',
@@ -74,3 +92,35 @@ export const body = css({
74
92
  borderRadius: `calc(var(${borderRadius}) - 2px)`,
75
93
  },
76
94
  })
95
+
96
+ export const overlay = sva({
97
+ slots: ['dialog', 'body'],
98
+ base: {
99
+ dialog: dialog,
100
+ body: body,
101
+ },
102
+ variants: {
103
+ level: {
104
+ 0: {
105
+ dialog: {
106
+ [level]: '0',
107
+ },
108
+ },
109
+ 1: {
110
+ dialog: {
111
+ [level]: '1',
112
+ },
113
+ },
114
+ 2: {
115
+ dialog: {
116
+ [level]: '2',
117
+ },
118
+ },
119
+ 3: {
120
+ dialog: {
121
+ [level]: '3',
122
+ },
123
+ },
124
+ },
125
+ },
126
+ })
@@ -8,21 +8,21 @@ import { useDebouncedCallback, useSyncedRef, useTimeoutEffect } from '@react-hoo
8
8
  import { type HTMLMotionProps, m, useReducedMotionConfig } from 'framer-motion'
9
9
  import { type PropsWithChildren, forwardRef, useLayoutEffect, useRef, useState } from 'react'
10
10
  import { stopPropagation } from '../../utils'
11
- import * as styles from './Overlay.css'
11
+ import { backdropBlur, backdropOpacity, overlay as overlayCVA } from './Overlay.css'
12
12
 
13
- type OverlayProps = PropsWithChildren<
14
- HTMLMotionProps<'dialog'> & {
15
- classes?: {
16
- dialog?: string
17
- body?: string
18
- }
19
- onClose: () => void
20
- onClick?: never
13
+ type OverlayProps = PropsWithChildren<{
14
+ overlayLevel?: 0 | 1 | 2 | 3
15
+ className?: string
16
+ classes?: {
17
+ dialog?: string
18
+ body?: string
21
19
  }
22
- >
20
+ onClose: () => void
21
+ onClick?: never
22
+ }>
23
23
 
24
24
  export const Overlay = forwardRef<HTMLDialogElement, OverlayProps>(
25
- ({ children, onClose, className, classes, ...rest }, ref) => {
25
+ ({ children, onClose, className, classes, overlayLevel = 0, ...rest }, ref) => {
26
26
  const [opened, setOpened] = useState(false)
27
27
  const dialogRef = useRef<HTMLDialogElement>(null)
28
28
  const isClosingRef = useRef(false)
@@ -56,12 +56,16 @@ export const Overlay = forwardRef<HTMLDialogElement, OverlayProps>(
56
56
  // Move dialog to the top of the DOM
57
57
  dialogRef.current?.showModal()
58
58
  }
59
- }, 10)
59
+ }, 20)
60
60
 
61
61
  useTimeoutEffect(() => {
62
62
  setOpened(true)
63
63
  }, 120)
64
64
 
65
+ const styles = overlayCVA({
66
+ level: overlayLevel as 0 | 1 | 2 | 3,
67
+ })
68
+
65
69
  return (
66
70
  <m.dialog
67
71
  ref={useMergedRef(dialogRef, ref)}
@@ -70,16 +74,17 @@ export const Overlay = forwardRef<HTMLDialogElement, OverlayProps>(
70
74
  {...motionNotReduced
71
75
  ? ({
72
76
  initial: {
73
- [styles.backdropBlur]: '0px',
74
- [styles.backdropOpacity]: '0%',
75
- scale: 1.075,
77
+ [backdropBlur]: '0px',
78
+ [backdropOpacity]: '0%',
79
+ scale: overlayLevel > 0 ? 0.9 : 1.075,
76
80
  opacity: 0,
77
81
  },
78
82
  animate: {
79
- [styles.backdropBlur]: '8px',
80
- [styles.backdropOpacity]: '60%',
83
+ [backdropBlur]: overlayLevel > 0 ? '4px' : '8px',
84
+ [backdropOpacity]: overlayLevel > 0 ? '50%' : '60%',
81
85
  scale: 1,
82
86
  opacity: 1,
87
+ translateY: 0,
83
88
  transition: {
84
89
  delay: 0.075,
85
90
  },
@@ -88,14 +93,14 @@ export const Overlay = forwardRef<HTMLDialogElement, OverlayProps>(
88
93
  scale: 1.3,
89
94
  opacity: 0,
90
95
  translateY: -10,
91
- [styles.backdropBlur]: '0px',
92
- [styles.backdropOpacity]: '0%',
96
+ [backdropBlur]: '0px',
97
+ [backdropOpacity]: '0%',
93
98
  },
94
99
  })
95
100
  : {
96
101
  initial: {
97
- [styles.backdropBlur]: '8px',
98
- [styles.backdropOpacity]: '60%',
102
+ [backdropBlur]: '8px',
103
+ [backdropOpacity]: '60%',
99
104
  },
100
105
  }}
101
106
  onClick={e => {
@@ -133,8 +133,8 @@ export const overlaysActorLogic = setup({
133
133
  const currentOverlay = last(context.overlays)
134
134
  if (currentOverlay?.type === 'relationshipDetails') {
135
135
  enqueue.sendTo(currentOverlay.id, {
136
+ ...event,
136
137
  type: 'navigate.to',
137
- edgeId: event.edgeId,
138
138
  })
139
139
  return
140
140
  }