@likec4/diagram 1.28.1 → 1.29.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/bundle/index.js +292 -258
  2. package/dist/_virtual/index.js +1 -1
  3. package/dist/base/primitives/customEdge.js +1 -1
  4. package/dist/base/primitives/edge/EdgeLabel.css.d.ts +3 -0
  5. package/dist/base/primitives/edge/EdgeLabel.css.js +3 -0
  6. package/dist/base/primitives/edge/EdgeLabel.d.ts +1 -1
  7. package/dist/base/primitives/edge/EdgeLabel.js +2 -1
  8. package/dist/components/SearchControl.css.js +8 -2
  9. package/dist/hooks/safeContext.d.ts +2 -5
  10. package/dist/hooks/safeContext.js +2 -1
  11. package/dist/hooks/useDiagram.d.ts +711 -146
  12. package/dist/likec4diagram/ui/controls/Controls.js +3 -3
  13. package/dist/node_modules/.pnpm/{react@19.0.0 → react@19.1.0}/node_modules/react/cjs/react.production.js +14 -6
  14. package/dist/overlays/element-details/ElementDetails.js +1 -1
  15. package/dist/state/DiagramActorProvider.js +2 -2
  16. package/dist/state/diagram-machine.d.ts +715 -142
  17. package/dist/state/diagram-machine.js +48 -6
  18. package/dist/styles.css.js +1 -1
  19. package/package.json +15 -15
  20. package/src/LikeC4Diagram.tsx +0 -1
  21. package/src/base/primitives/customEdge.ts +1 -0
  22. package/src/base/primitives/edge/EdgeLabel.css.ts +3 -0
  23. package/src/base/primitives/edge/EdgeLabel.tsx +2 -1
  24. package/src/components/SearchControl.css.ts +7 -1
  25. package/src/hooks/safeContext.tsx +3 -1
  26. package/src/likec4diagram/ui/controls/Controls.tsx +3 -3
  27. package/src/overlays/element-details/ElementDetails.tsx +2 -2
  28. package/src/state/DiagramActorProvider.tsx +3 -3
  29. package/src/state/diagram-machine.ts +48 -5
  30. /package/dist/node_modules/.pnpm/{react@19.0.0 → react@19.1.0}/node_modules/react/index.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@likec4/diagram",
3
- "version": "1.28.1",
3
+ "version": "1.29.1",
4
4
  "license": "MIT",
5
5
  "bugs": "https://github.com/likec4/likec4/issues",
6
6
  "homepage": "https://likec4.dev",
@@ -44,7 +44,7 @@
44
44
  "@dagrejs/dagre": "1.1.4",
45
45
  "@mantine/core": "7.17.4",
46
46
  "@mantine/hooks": "7.17.4",
47
- "@nanostores/react": "0.8.4",
47
+ "@nanostores/react": "1.0.0",
48
48
  "@react-hookz/web": "^25.1.1",
49
49
  "@tabler/icons-react": "3.31.0",
50
50
  "@xstate/react": "^5.0.3",
@@ -54,38 +54,38 @@
54
54
  "clsx": "^2.1.1",
55
55
  "d3-shape": "^3.2.0",
56
56
  "fast-equals": "^5.2.2",
57
- "motion": "^12.6.3",
58
- "nanostores": "0.11.4",
57
+ "motion": "^12.7.4",
58
+ "nanostores": "1.0.1",
59
59
  "react-error-boundary": "^5.0.0",
60
60
  "react-shadow": "^20.6.0",
61
61
  "remeda": "^2.21.2",
62
62
  "type-fest": "^4.39.1",
63
63
  "xstate": "^5.19.2",
64
- "@likec4/core": "1.28.1",
65
- "@likec4/styles": "1.28.1"
64
+ "@likec4/core": "1.29.1",
65
+ "@likec4/styles": "1.29.1"
66
66
  },
67
67
  "peerDependencies": {
68
68
  "react": "^18.x || ^19.x",
69
69
  "react-dom": "^18.x || ^19.x"
70
70
  },
71
71
  "devDependencies": {
72
- "@pandacss/dev": "^0.53.3",
72
+ "@pandacss/dev": "^0.53.4",
73
73
  "@statelyai/inspect": "^0.4.0",
74
74
  "@types/bezier-js": "^4.1.3",
75
75
  "@types/d3-shape": "^3.1.7",
76
- "@types/react": "^19.0.12",
77
- "@types/react-dom": "^19.0.4",
76
+ "@types/react": "^19.1.1",
77
+ "@types/react-dom": "^19.1.2",
78
78
  "@types/node": "^20.17.30",
79
- "@vitejs/plugin-react": "^4.3.4",
79
+ "@vitejs/plugin-react": "^4.4.0",
80
80
  "postcss": "^8.5.3",
81
- "react": "^19.0.0",
82
- "react-dom": "^19.0.0",
81
+ "react": "^19.1.0",
82
+ "react-dom": "^19.1.0",
83
83
  "typescript": "^5.8.3",
84
- "vite": "^6.2.5",
84
+ "vite": "^6.3.1",
85
85
  "vite-plugin-dts": "^4.5.3",
86
86
  "vitest": "^3.1.1",
87
- "wireit": "^0.14.11",
88
- "@likec4/tsconfig": "1.28.1"
87
+ "wireit": "^0.14.12",
88
+ "@likec4/tsconfig": "1.29.1"
89
89
  },
90
90
  "scripts": {
91
91
  "generate": "panda codegen",
@@ -15,7 +15,6 @@ import { LikeC4CustomColors } from './LikeC4CustomColors'
15
15
  import { type LikeC4DiagramEventHandlers, type LikeC4DiagramProperties } from './LikeC4Diagram.props'
16
16
  import { LikeC4DiagramXYFlow } from './likec4diagram/DiagramXYFlow'
17
17
  import type { Types } from './likec4diagram/types'
18
- import { useViewToNodesEdges } from './likec4diagram/useViewToNodesEdges'
19
18
  import { useLikeC4Model } from './likec4model'
20
19
  import { DiagramActorProvider } from './state/DiagramActorProvider'
21
20
 
@@ -13,6 +13,7 @@ export const edgePropsEqual = <P extends Record<string, unknown> = Base.EdgeData
13
13
  ) => (
14
14
  prev.id === next.id
15
15
  && eq(prev.selected ?? false, next.selected ?? false)
16
+ && eq(prev.animated ?? false, next.animated ?? false)
16
17
  && eq(prev.source, next.source)
17
18
  && eq(prev.sourceHandleId ?? null, next.sourceHandleId ?? null)
18
19
  && eq(prev.sourcePosition, next.sourcePosition)
@@ -125,6 +125,9 @@ export const labelsva = sva({
125
125
  padding: '0px',
126
126
  },
127
127
  labelContents: {
128
+ display: 'flex',
129
+ flexDirection: 'column',
130
+ alignItems: 'center',
128
131
  padding: '2px 5px 4px 0px',
129
132
  },
130
133
  labelText: {
@@ -1,6 +1,7 @@
1
1
  import { type DiagramEdge, extractStep, isStepEdgeId } from '@likec4/core'
2
2
  import { cx } from '@likec4/styles/css'
3
- import { type BoxProps, Box, Text } from '@mantine/core'
3
+ import { type BoxProps, Box } from '@likec4/styles/jsx'
4
+ import { Text } from '@mantine/core'
4
5
  import { type PropsWithChildren } from 'react'
5
6
  import { isTruthy } from 'remeda'
6
7
  import type { UndefinedOnPartialDeep } from 'type-fest'
@@ -41,9 +41,15 @@ export const root = css({
41
41
  export const placeholder = css({
42
42
  fontSize: 'sm', // mantine.fontSizes.sm,
43
43
  fontWeight: 500,
44
- paddingRight: '50px',
44
+ paddingRight: '10px',
45
45
  color: 'mantine.colors.placeholder',
46
46
  flex: '1',
47
+ sm: {
48
+ paddingRight: '30px',
49
+ },
50
+ md: {
51
+ paddingRight: '50px',
52
+ },
47
53
  })
48
54
 
49
55
  export const shortcut = css({
@@ -4,9 +4,11 @@ import type { DiagramActorRef } from '../state/types'
4
4
  /**
5
5
  * To improve experience with HMR, we use `createSafeContext` as a boundary for hoooks
6
6
  */
7
- export const DiagramActorSafeContext = createContext<DiagramActorRef>(null as any)
7
+ const DiagramActorSafeContext = createContext<DiagramActorRef>(null as any)
8
8
  DiagramActorSafeContext.displayName = 'DiagramActorSafeContext'
9
9
 
10
+ export const DiagramActorContextProvider = DiagramActorSafeContext.Provider
11
+
10
12
  export const useDiagramActorRef = () => {
11
13
  const ctx = useContext(DiagramActorSafeContext)
12
14
  if (ctx === null) {
@@ -1,6 +1,6 @@
1
+ import { cx } from '@likec4/styles/css'
1
2
  import { ActionIconGroup, Badge, Box, Group, Loader, Stack } from '@mantine/core'
2
3
  import { IconFileSymlink, IconFocusCentered, IconMenu2 } from '@tabler/icons-react'
3
- import { clsx } from 'clsx'
4
4
  import { LayoutGroup, m } from 'motion/react'
5
5
  import { memo } from 'react'
6
6
  import { useDiagramEventHandlers, useEnabledFeatures } from '../../../context'
@@ -42,7 +42,7 @@ const ControlsDefaultLayout: ControlsCustomLayout = ({
42
42
  translateY: -10,
43
43
  }}
44
44
  align="flex-start"
45
- className={clsx(
45
+ className={cx(
46
46
  'react-flow__panel',
47
47
  css.panel,
48
48
  'likec4-top-left-panel',
@@ -53,7 +53,7 @@ const ControlsDefaultLayout: ControlsCustomLayout = ({
53
53
  <Stack align="flex-start" gap="xs">
54
54
  <LayoutGroup>
55
55
  <Group
56
- className={clsx(css.navigationButtons, 'likec4-navigation-webview')}
56
+ className={cx(css.navigationButtons, 'likec4-navigation-webview')}
57
57
  gap={'xs'}>
58
58
  {burgerMenu}
59
59
  {navigationButtons}
@@ -24,10 +24,10 @@ export function ElementDetails({
24
24
  shallowEqual,
25
25
  )
26
26
  return (
27
- <ElementDetailsActorContext value={actorRef}>
27
+ <ElementDetailsActorContext.Provider value={actorRef}>
28
28
  <ElementDetailsCard
29
29
  onClose={onClose}
30
30
  {...props} />
31
- </ElementDetailsActorContext>
31
+ </ElementDetailsActorContext.Provider>
32
32
  )
33
33
  }
@@ -6,7 +6,7 @@ import { shallowEqual } from 'fast-equals'
6
6
  import { type PropsWithChildren, useEffect } from 'react'
7
7
  import { useDiagramEventHandlersRef } from '../context/DiagramEventHandlers'
8
8
  import { DiagramFeatures, useEnabledFeatures } from '../context/DiagramFeatures'
9
- import { DiagramActorSafeContext } from '../hooks/safeContext'
9
+ import { DiagramActorContextProvider } from '../hooks/safeContext'
10
10
  import { useUpdateEffect } from '../hooks/useUpdateEffect'
11
11
  import type { Types } from '../likec4diagram/types'
12
12
  import { useViewToNodesEdges } from '../likec4diagram/useViewToNodesEdges'
@@ -92,10 +92,10 @@ export function DiagramActorProvider({
92
92
  const toggledFeatures = useSelector(actorRef, selectToggledFeatures, shallowEqual)
93
93
 
94
94
  return (
95
- <DiagramActorSafeContext value={actorRef}>
95
+ <DiagramActorContextProvider value={actorRef}>
96
96
  <DiagramFeatures overrides={toggledFeatures}>
97
97
  {children}
98
98
  </DiagramFeatures>
99
- </DiagramActorSafeContext>
99
+ </DiagramActorContextProvider>
100
100
  )
101
101
  }
@@ -13,6 +13,7 @@ import {
13
13
  getBBoxCenter,
14
14
  getParallelStepsPrefix,
15
15
  invariant,
16
+ isStepEdgeId,
16
17
  nonexhaustive,
17
18
  nonNullable,
18
19
  } from '@likec4/core'
@@ -24,7 +25,7 @@ import {
24
25
  useStoreApi,
25
26
  } from '@xyflow/react'
26
27
  import { type EdgeChange, type NodeChange, type Rect, type Viewport, nodeToRect } from '@xyflow/system'
27
- import { clamp, first, hasAtLeast, prop, reduce } from 'remeda'
28
+ import { clamp, first, hasAtLeast, prop } from 'remeda'
28
29
  import {
29
30
  type ActorLogicFrom,
30
31
  type ActorRef,
@@ -199,6 +200,7 @@ export const diagramMachine = setup({
199
200
  'enabled: FitView': ({ context }) => context.features.enableFitView,
200
201
  'enabled: FocusMode': ({ context }) => context.features.enableFocusMode,
201
202
  'enabled: Readonly': ({ context }) => context.features.enableReadOnly,
203
+ 'enabled: RelationshipDetails': ({ context }) => context.features.enableRelationshipDetails,
202
204
  'not readonly': ({ context }) => !context.features.enableReadOnly,
203
205
  'is dynamic view': ({ context }) => context.view.__ === 'dynamic',
204
206
  'is another view': ({ context, event }) => {
@@ -227,6 +229,10 @@ export const diagramMachine = setup({
227
229
  assertEvent(event, 'xyflow.nodeClick')
228
230
  return context.xyedges.some(e => e.source === event.node.id || e.target === event.node.id)
229
231
  },
232
+ 'click: selected edge': ({ event }) => {
233
+ assertEvent(event, 'xyflow.edgeClick')
234
+ return event.edge.selected === true || event.edge.data.active === true
235
+ },
230
236
  },
231
237
  actions: {
232
238
  'trigger:NavigateTo': (_, _params: { viewId: ViewId }) => {
@@ -767,6 +773,26 @@ export const diagramMachine = setup({
767
773
  }),
768
774
  target: 'focused',
769
775
  },
776
+ 'xyflow.edgeClick': [{
777
+ guard: and([
778
+ 'is dynamic view',
779
+ 'click: selected edge',
780
+ ]) as any,
781
+ actions: raise(({ event }) => ({
782
+ type: 'walkthrough.start',
783
+ stepId: event.edge.id as StepEdgeId,
784
+ })),
785
+ }, {
786
+ guard: and([
787
+ 'enabled: RelationshipDetails',
788
+ 'click: selected edge',
789
+ ]) as any,
790
+ actions: sendTo(({ system }) => typedSystem(system).overlaysActorRef!, ({ context, event }) => ({
791
+ type: 'open.relationshipDetails',
792
+ viewId: context.view.id,
793
+ edgeId: event.edge.id as EdgeId,
794
+ })),
795
+ }],
770
796
  },
771
797
  },
772
798
  focused: {
@@ -779,18 +805,18 @@ export const diagramMachine = setup({
779
805
  spawnChild('hotkeyActorLogic', { id: 'hotkey' }),
780
806
  'xyflow:fitFocusedBounds',
781
807
  ],
782
- exit: enqueueActions(({ enqueue, context }) => {
808
+ exit: enqueueActions(({ enqueue, context, event }) => {
783
809
  enqueue.stopChild('hotkey')
784
810
  if (context.viewportBeforeFocus) {
785
811
  enqueue({ type: 'xyflow:setViewport', params: { viewport: context.viewportBeforeFocus } })
786
812
  } else {
787
813
  enqueue({ type: 'xyflow:fitDiagram' })
788
814
  }
789
- enqueue.assign((s) => ({
790
- ...unfocusNodesEdges(s),
815
+ enqueue.assign({
816
+ ...unfocusNodesEdges({ context, event }),
791
817
  viewportBeforeFocus: null,
792
818
  focusedNode: null,
793
- }))
819
+ })
794
820
  }),
795
821
  on: {
796
822
  'xyflow.nodeClick': [
@@ -885,6 +911,23 @@ export const diagramMachine = setup({
885
911
  enqueue('xyflow:fitFocusedBounds')
886
912
  }),
887
913
  },
914
+ 'xyflow.edgeClick': {
915
+ actions: [
916
+ assign(({ event, context }) => {
917
+ if (!isStepEdgeId(event.edge.id) || event.edge.id === context.activeWalkthrough?.stepId) {
918
+ return {}
919
+ }
920
+ return {
921
+ activeWalkthrough: {
922
+ stepId: event.edge.id,
923
+ parallelPrefix: getParallelStepsPrefix(event.edge.id),
924
+ },
925
+ }
926
+ }),
927
+ assign(updateActiveWalkthrough),
928
+ 'xyflow:fitFocusedBounds',
929
+ ],
930
+ },
888
931
  'notations.unhighlight': {
889
932
  actions: assign(s => ({
890
933
  ...updateActiveWalkthrough(s),