@likec4/diagram 1.39.5 → 1.40.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 (123) hide show
  1. package/bundle/{chunk-CW_KClZe.js → chunk-CDr-4Ymp.js} +936 -903
  2. package/bundle/custom.js +61 -60
  3. package/bundle/index.js +2667 -539
  4. package/dist/LikeC4Diagram.d.ts +1 -1
  5. package/dist/LikeC4Diagram.js +7 -4
  6. package/dist/LikeC4Diagram.props.d.ts +6 -1
  7. package/dist/base/const.d.ts +9 -0
  8. package/dist/base/const.js +10 -1
  9. package/dist/base/index.d.ts +1 -0
  10. package/dist/base/primitives/edge/EdgeLabel.js +2 -1
  11. package/dist/base/primitives/edge/EdgeLabelContainer.js +10 -4
  12. package/dist/base/primitives/edge/EdgePath.js +17 -8
  13. package/dist/base/primitives/edge/edge.css.d.ts +0 -1
  14. package/dist/base/primitives/edge/edge.css.js +6 -14
  15. package/dist/base/primitives/element/ElementActionButtons.js +1 -3
  16. package/dist/base/primitives/element/ElementNodeContainer.d.ts +0 -6
  17. package/dist/base/primitives/element/ElementNodeContainer.js +3 -26
  18. package/dist/base/primitives/element/ElementTitle.js +2 -2
  19. package/dist/base/types.d.ts +3 -3
  20. package/dist/bundle/LikeC4View.js +4 -12
  21. package/dist/bundle/LikeC4View.props.d.ts +12 -3
  22. package/dist/bundle/custom.js +1 -1
  23. package/dist/custom/customNodes.d.ts +6 -0
  24. package/dist/custom/customNodes.js +2 -1
  25. package/dist/custom/index.js +1 -1
  26. package/dist/hooks/useDiagram.d.ts +5 -1
  27. package/dist/hooks/useDiagram.js +3 -0
  28. package/dist/hooks/useXYFlow.d.ts +4 -439
  29. package/dist/likec4diagram/DiagramUI.js +1 -1
  30. package/dist/likec4diagram/DiagramXYFlow.js +8 -4
  31. package/dist/likec4diagram/convert-to-xyflow.d.ts +14 -0
  32. package/dist/likec4diagram/convert-to-xyflow.js +29 -0
  33. package/dist/likec4diagram/custom/edges/RelationshipEdge.d.ts +3 -3
  34. package/dist/likec4diagram/custom/edges/RelationshipEdge.js +0 -1
  35. package/dist/likec4diagram/custom/edges/SequenceStepEdge.d.ts +3 -0
  36. package/dist/likec4diagram/custom/edges/SequenceStepEdge.js +71 -0
  37. package/dist/likec4diagram/custom/index.js +7 -2
  38. package/dist/likec4diagram/custom/nodes/ElementActions.d.ts +2 -1
  39. package/dist/likec4diagram/custom/nodes/SequenceActorNode.d.ts +4 -0
  40. package/dist/likec4diagram/custom/nodes/SequenceActorNode.js +157 -0
  41. package/dist/likec4diagram/custom/nodes/index.d.ts +1 -0
  42. package/dist/likec4diagram/custom/nodes/nodes.d.ts +1 -2
  43. package/dist/likec4diagram/relationship-popover/RelationshipPopover.js +31 -27
  44. package/dist/likec4diagram/types.d.ts +41 -7
  45. package/dist/likec4diagram/xyflow-diagram/diagram-view.d.ts +11 -0
  46. package/dist/likec4diagram/{useViewToNodesEdges.js → xyflow-diagram/diagram-view.js} +4 -13
  47. package/dist/likec4diagram/xyflow-sequence/_types.d.ts +41 -0
  48. package/dist/likec4diagram/xyflow-sequence/const.d.ts +17 -0
  49. package/dist/likec4diagram/xyflow-sequence/const.js +16 -0
  50. package/dist/likec4diagram/xyflow-sequence/layouter.d.ts +46 -0
  51. package/dist/likec4diagram/xyflow-sequence/layouter.js +408 -0
  52. package/dist/likec4diagram/xyflow-sequence/sequence-view.d.ts +7 -0
  53. package/dist/likec4diagram/xyflow-sequence/sequence-view.js +273 -0
  54. package/dist/likec4diagram/xyflow-sequence/utils.d.ts +14 -0
  55. package/dist/likec4diagram/xyflow-sequence/utils.js +92 -0
  56. package/dist/navigationpanel/NavigationPanelControls.js +2 -2
  57. package/dist/navigationpanel/controls/ViewDetailsCard.js +5 -2
  58. package/dist/navigationpanel/dropdown/ProjectsMenu.js +53 -44
  59. package/dist/navigationpanel/walkthrough/ActiveWalkthroughControls.d.ts +1 -2
  60. package/dist/navigationpanel/walkthrough/ActiveWalkthroughControls.js +10 -41
  61. package/dist/navigationpanel/walkthrough/DynamicViewControls.d.ts +292 -0
  62. package/dist/navigationpanel/walkthrough/DynamicViewControls.js +119 -0
  63. package/dist/navigationpanel/walkthrough/index.d.ts +2 -1
  64. package/dist/overlays/relationship-details/RelationshipDetails.js +4 -1
  65. package/dist/state/DiagramActorProvider.d.ts +3 -2
  66. package/dist/state/DiagramActorProvider.js +19 -11
  67. package/dist/state/assign.js +11 -4
  68. package/dist/state/diagram-machine.d.ts +224 -194
  69. package/dist/state/diagram-machine.js +170 -63
  70. package/dist/state/utils.d.ts +7 -1
  71. package/dist/state/utils.js +67 -7
  72. package/dist/styles-min.css +1 -1
  73. package/dist/styles.css +1 -1
  74. package/dist/styles.css2.js +1 -1
  75. package/package.json +8 -7
  76. package/panda.buildinfo.json +30 -9
  77. package/src/LikeC4Diagram.props.ts +14 -1
  78. package/src/LikeC4Diagram.tsx +7 -4
  79. package/src/base/const.ts +12 -0
  80. package/src/base/index.ts +2 -0
  81. package/src/base/primitives/edge/EdgeLabel.tsx +23 -19
  82. package/src/base/primitives/edge/EdgeLabelContainer.tsx +12 -7
  83. package/src/base/primitives/edge/EdgePath.tsx +25 -14
  84. package/src/base/primitives/edge/edge.css.ts +5 -14
  85. package/src/base/primitives/element/ElementActionButtons.tsx +1 -3
  86. package/src/base/primitives/element/ElementNodeContainer.tsx +3 -30
  87. package/src/base/primitives/element/ElementTitle.tsx +2 -3
  88. package/src/base/types.ts +7 -5
  89. package/src/bundle/LikeC4View.props.ts +14 -3
  90. package/src/bundle/LikeC4View.tsx +4 -14
  91. package/src/bundle/ReactLikeC4.tsx +1 -2
  92. package/src/custom/customNodes.ts +7 -0
  93. package/src/hooks/useDiagram.ts +10 -0
  94. package/src/likec4diagram/DiagramUI.tsx +1 -1
  95. package/src/likec4diagram/DiagramXYFlow.tsx +10 -5
  96. package/src/likec4diagram/convert-to-xyflow.ts +45 -0
  97. package/src/likec4diagram/custom/edges/RelationshipEdge.tsx +0 -1
  98. package/src/likec4diagram/custom/edges/SequenceStepEdge.tsx +65 -0
  99. package/src/likec4diagram/custom/index.ts +7 -1
  100. package/src/likec4diagram/custom/nodes/ElementActions.tsx +4 -2
  101. package/src/likec4diagram/custom/nodes/SequenceActorNode.tsx +175 -0
  102. package/src/likec4diagram/custom/nodes/index.ts +1 -0
  103. package/src/likec4diagram/custom/nodes/nodes.tsx +1 -1
  104. package/src/likec4diagram/relationship-popover/RelationshipPopover.tsx +36 -30
  105. package/src/likec4diagram/types.ts +96 -13
  106. package/src/likec4diagram/{useViewToNodesEdges.ts → xyflow-diagram/diagram-view.ts} +7 -28
  107. package/src/likec4diagram/xyflow-sequence/_types.ts +45 -0
  108. package/src/likec4diagram/xyflow-sequence/const.ts +37 -0
  109. package/src/likec4diagram/xyflow-sequence/layouter.ts +567 -0
  110. package/src/likec4diagram/xyflow-sequence/sequence-view.ts +337 -0
  111. package/src/likec4diagram/xyflow-sequence/utils.ts +112 -0
  112. package/src/navigationpanel/NavigationPanelControls.tsx +2 -2
  113. package/src/navigationpanel/controls/ViewDetailsCard.tsx +5 -2
  114. package/src/navigationpanel/dropdown/ProjectsMenu.tsx +5 -1
  115. package/src/navigationpanel/walkthrough/ActiveWalkthroughControls.tsx +5 -40
  116. package/src/navigationpanel/walkthrough/DynamicViewControls.tsx +125 -0
  117. package/src/navigationpanel/walkthrough/index.tsx +2 -1
  118. package/src/overlays/relationship-details/RelationshipDetails.tsx +5 -2
  119. package/src/state/DiagramActorProvider.tsx +21 -10
  120. package/src/state/assign.ts +18 -5
  121. package/src/state/diagram-machine.ts +207 -75
  122. package/src/state/utils.ts +81 -7
  123. package/dist/likec4diagram/useViewToNodesEdges.d.ts +0 -12
@@ -0,0 +1,125 @@
1
+ import { invariant } from '@likec4/core'
2
+ import type { DynamicViewDisplayVariant } from '@likec4/core/types'
3
+ import { css } from '@likec4/styles/css'
4
+ import { type ButtonProps, Button, SegmentedControl } from '@mantine/core'
5
+ import {
6
+ IconPlayerPlayFilled,
7
+ } from '@tabler/icons-react'
8
+ import { type HTMLMotionProps } from 'motion/react'
9
+ import * as m from 'motion/react-m'
10
+ import { forwardRef } from 'react'
11
+ import { useDiagram, useDiagramContext } from '../../hooks/useDiagram'
12
+ import { Tooltip } from '../_common'
13
+ import { useNavigationActor } from '../hooks'
14
+
15
+ export const TriggerWalkthroughButton = forwardRef<HTMLButtonElement, ButtonProps & HTMLMotionProps<'button'>>((
16
+ props,
17
+ ref,
18
+ ) => (
19
+ <Button
20
+ variant="filled"
21
+ size="xs"
22
+ fw="500"
23
+ {...props}
24
+ ref={ref}
25
+ component={m.button}
26
+ layoutId={'trigger-dynamic-walkthrough'}
27
+ className={css({
28
+ flexShrink: 0,
29
+ })}
30
+ />
31
+ ))
32
+
33
+ function StartWalkthroughButton({ onClick }: { onClick: () => void }) {
34
+ const diagram = useDiagram()
35
+ const actor = useNavigationActor()
36
+ return (
37
+ <Tooltip label="Start Dynamic View Walkthrough">
38
+ <TriggerWalkthroughButton
39
+ onClick={e => {
40
+ e.stopPropagation()
41
+ actor.closeDropdown()
42
+ diagram.startWalkthrough()
43
+ }}
44
+ size="compact-xs"
45
+ h={26}
46
+ classNames={{
47
+ label: css({
48
+ display: {
49
+ base: 'none',
50
+ '@/md': '[inherit]',
51
+ },
52
+ }),
53
+ section: css({
54
+ marginInlineStart: {
55
+ base: '0',
56
+ '@/md': '2',
57
+ },
58
+ }),
59
+ }}
60
+ rightSection={<IconPlayerPlayFilled size={10} />}
61
+ >
62
+ Start
63
+ </TriggerWalkthroughButton>
64
+ </Tooltip>
65
+ )
66
+ }
67
+
68
+ function DynamicViewModeSwitcher({
69
+ value,
70
+ onChange,
71
+ }: {
72
+ value: DynamicViewDisplayVariant
73
+ onChange: (variant: DynamicViewDisplayVariant) => void
74
+ }) {
75
+ return (
76
+ <m.div layout="position">
77
+ <SegmentedControl
78
+ size="xs"
79
+ value={value}
80
+ component={m.div}
81
+ onChange={variant => {
82
+ invariant(variant === 'diagram' || variant === 'sequence', 'Invalid dynamic view variant')
83
+ onChange(variant)
84
+ }}
85
+ classNames={{
86
+ label: css({
87
+ fontSize: 'xxs',
88
+ }),
89
+ }}
90
+ data={[
91
+ {
92
+ value: 'diagram',
93
+ label: 'Diagram',
94
+ },
95
+ {
96
+ value: 'sequence',
97
+ label: 'Sequence',
98
+ },
99
+ ]} />
100
+ </m.div>
101
+ )
102
+ }
103
+
104
+ export function DynamicViewControls() {
105
+ const dynamicViewVariant = useDiagramContext(c => c.dynamicViewVariant)
106
+ const diagram = useDiagram()
107
+ const actor = useNavigationActor()
108
+ return (
109
+ <>
110
+ <DynamicViewModeSwitcher
111
+ key="dynamic-view-mode-switcher"
112
+ value={dynamicViewVariant}
113
+ onChange={mode => {
114
+ diagram.switchDynamicViewVariant(mode)
115
+ }}
116
+ />
117
+ <StartWalkthroughButton
118
+ key="trigger-dynamic-walkthrough"
119
+ onClick={() => {
120
+ actor.closeDropdown()
121
+ diagram.startWalkthrough()
122
+ }} />
123
+ </>
124
+ )
125
+ }
@@ -1 +1,2 @@
1
- export { ActiveWalkthroughControls, StartWalkthroughButton } from './ActiveWalkthroughControls'
1
+ export { ActiveWalkthroughControls } from './ActiveWalkthroughControls'
2
+ export { DynamicViewControls } from './DynamicViewControls'
@@ -1,5 +1,5 @@
1
1
  import { type DiagramEdge, type DiagramView, invariant, isAncestor, nonNullable } from '@likec4/core'
2
- import { cx as clsx } from '@likec4/styles/css'
2
+ import { cx } from '@likec4/styles/css'
3
3
  import { ActionIcon, Group } from '@mantine/core'
4
4
  import { useCallbackRef, useStateHistory } from '@mantine/hooks'
5
5
  import { IconChevronLeft, IconChevronRight, IconX } from '@tabler/icons-react'
@@ -145,7 +145,10 @@ const RelationshipDetailsInner = memo(() => {
145
145
  id={browser.rootElementId}
146
146
  nodes={nodes}
147
147
  edges={edges}
148
- className={clsx(initialized ? 'initialized' : 'not-initialized')}
148
+ className={cx(
149
+ initialized ? 'initialized' : 'not-initialized',
150
+ 'likec4-relationship-details',
151
+ )}
149
152
  nodeTypes={nodeTypes}
150
153
  edgeTypes={edgeTypes}
151
154
  onNodesChange={useCallbackRef((changes) => {
@@ -1,9 +1,9 @@
1
- import type { DiagramView, WhereOperator } from '@likec4/core/types'
1
+ import type { DiagramView, DynamicViewDisplayVariant, WhereOperator } from '@likec4/core/types'
2
2
  import { useCustomCompareEffect } from '@react-hookz/web'
3
3
  import { useActorRef, useSelector } from '@xstate/react'
4
4
  import { useStoreApi } from '@xyflow/react'
5
5
  import { deepEqual, shallowEqual } from 'fast-equals'
6
- import { type PropsWithChildren, useEffect, useRef } from 'react'
6
+ import { type PropsWithChildren, useEffect, useMemo, useRef } from 'react'
7
7
  import { ErrorBoundary } from '../components/ErrorFallback'
8
8
  import { useDiagramEventHandlers } from '../context/DiagramEventHandlers'
9
9
  import { DiagramFeatures, useEnabledFeatures } from '../context/DiagramFeatures'
@@ -11,8 +11,8 @@ import { useOnDiagramEvent } from '../custom'
11
11
  import { DiagramActorContextProvider } from '../hooks/safeContext'
12
12
  import { useCurrentViewId } from '../hooks/useCurrentViewId'
13
13
  import type { ViewPadding } from '../LikeC4Diagram.props'
14
+ import { convertToXYFlow } from '../likec4diagram/convert-to-xyflow'
14
15
  import type { Types } from '../likec4diagram/types'
15
- import { useViewToNodesEdges } from '../likec4diagram/useViewToNodesEdges'
16
16
  import { CurrentViewModelContext } from '../likec4model/LikeC4ModelContext'
17
17
  import { useLikeC4Model } from '../likec4model/useLikeC4Model'
18
18
  import { type DiagramMachine, diagramMachine } from './diagram-machine'
@@ -29,6 +29,10 @@ const selectToggledFeatures = (state: DiagramActorSnapshot) => {
29
29
  return state.context.toggledFeatures
30
30
  }
31
31
 
32
+ const selectDynamicViewVariant = (state: DiagramActorSnapshot) => {
33
+ return state.context.dynamicViewVariant
34
+ }
35
+
32
36
  export function DiagramActorProvider({
33
37
  view,
34
38
  zoomable,
@@ -37,6 +41,7 @@ export function DiagramActorProvider({
37
41
  nodesSelectable,
38
42
  where,
39
43
  children,
44
+ dynamicViewVariant: _defaultVariant,
40
45
  }: PropsWithChildren<{
41
46
  view: DiagramView
42
47
  zoomable: boolean
@@ -44,6 +49,7 @@ export function DiagramActorProvider({
44
49
  fitViewPadding: ViewPadding
45
50
  nodesSelectable: boolean
46
51
  where: WhereOperator | null
52
+ dynamicViewVariant: DynamicViewDisplayVariant | undefined
47
53
  }>) {
48
54
  const { handlersRef } = useDiagramEventHandlers()
49
55
  const xystore = useStoreApi<Types.Node, Types.Edge>()
@@ -76,6 +82,7 @@ export function DiagramActorProvider({
76
82
  pannable,
77
83
  fitViewPadding,
78
84
  nodesSelectable,
85
+ dynamicViewVariant: _defaultVariant,
79
86
  },
80
87
  },
81
88
  )
@@ -97,15 +104,19 @@ export function DiagramActorProvider({
97
104
  deepEqual,
98
105
  )
99
106
 
100
- const { xyedges, xynodes } = useViewToNodesEdges({
101
- view,
102
- where,
103
- nodesSelectable,
104
- })
107
+ const dynamicViewVariant = useSelector(actorRef, selectDynamicViewVariant)
108
+
109
+ const update = useMemo(
110
+ () => convertToXYFlow({ view, where, nodesSelectable, dynamicViewVariant }),
111
+ [view, where, nodesSelectable, dynamicViewVariant],
112
+ )
105
113
 
106
114
  useEffect(() => {
107
- actorRef.send({ type: 'update.view', view, xyedges, xynodes })
108
- }, [view, xyedges, xynodes])
115
+ actorRef.send({
116
+ type: 'update.view',
117
+ ...update,
118
+ })
119
+ }, [actorRef, update])
109
120
 
110
121
  const toggledFeatures = useSelector(actorRef, selectToggledFeatures, shallowEqual)
111
122
 
@@ -5,6 +5,7 @@ import { isEmpty, mergeDeep, omit } from 'remeda'
5
5
  import { assertEvent } from 'xstate'
6
6
  import { Base } from '../base/types'
7
7
  import type { Types } from '../likec4diagram/types'
8
+ import { SeqParallelAreaColor } from '../likec4diagram/xyflow-sequence/const'
8
9
  import { type Vector, vector, VectorImpl } from '../utils/vector'
9
10
  import type { ActionArg, Context as DiagramContext } from './diagram-machine'
10
11
 
@@ -68,21 +69,25 @@ export function mergeXYNodesEdges({ context, event }: ActionArg): Partial<Diagra
68
69
  const currentEdges = context.xyedges
69
70
  xyedges = event.xyedges.map((update): Types.Edge => {
70
71
  const existing = currentEdges.find(n => n.id === update.id)
71
- if (existing) {
72
+ if (existing && existing.type === update.type) {
72
73
  if (
73
74
  eq(existing.hidden ?? false, update.hidden ?? false)
74
75
  && eq(existing.data, update.data)
76
+ && eq(existing.source, update.source)
77
+ && eq(existing.target, update.target)
78
+ && eq(existing.sourceHandle, update.sourceHandle)
79
+ && eq(existing.targetHandle, update.targetHandle)
75
80
  ) {
76
81
  return existing
77
82
  }
78
83
  return {
79
- ...existing,
84
+ ...omit(existing, ['sourceHandle', 'targetHandle']),
80
85
  ...update,
81
86
  data: {
82
87
  ...existing.data,
83
88
  ...update.data,
84
89
  },
85
- }
90
+ } as Types.Edge
86
91
  }
87
92
  return update
88
93
  })
@@ -388,7 +393,7 @@ export function resetEdgeControlPoints({ context }: ActionArg): Partial<DiagramC
388
393
  ...edge.data,
389
394
  controlPoints: getControlPointForEdge(edge),
390
395
  },
391
- })
396
+ } as Types.Edge)
392
397
  }),
393
398
  }
394
399
  }
@@ -401,11 +406,19 @@ export function updateActiveWalkthrough({ context }: ActionArg): Partial<Diagram
401
406
  const active = stepId === edge.id || (!!parallelPrefix && edge.id.startsWith(parallelPrefix))
402
407
  return Base.setData(edge, {
403
408
  active,
404
- dimmed: !active,
409
+ dimmed: stepId !== edge.id,
405
410
  })
406
411
  }),
407
412
  xynodes: context.xynodes.map(node => {
408
413
  const dimmed = step.source !== node.id && step.target !== node.id
414
+ if (node.type === 'seq-parallel') {
415
+ return Base.setData(node, {
416
+ color: parallelPrefix === node.data.parallelPrefix
417
+ ? SeqParallelAreaColor.active
418
+ : SeqParallelAreaColor.default,
419
+ dimmed,
420
+ })
421
+ }
409
422
  return Base.setDimmed(node, dimmed)
410
423
  }),
411
424
  }