@likec4/diagram 1.21.0 → 1.21.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 (36) hide show
  1. package/dist/base/BaseXYFlow.js +0 -1
  2. package/dist/base/primitives/compound/CompoundNodeContainer.js +2 -2
  3. package/dist/base/primitives/edge/EdgeLabel.js +2 -2
  4. package/dist/base/primitives/element/ElementNodeContainer.d.ts +6 -1
  5. package/dist/base/primitives/element/ElementNodeContainer.js +31 -13
  6. package/dist/base/primitives/element/ElementTitle.js +7 -3
  7. package/dist/hooks/index.d.ts +0 -1
  8. package/dist/index.d.ts +1 -1
  9. package/dist/likec4diagram/DiagramUI.js +1 -2
  10. package/dist/likec4diagram/custom/edges/RelationshipsDropdownMenu.js +1 -0
  11. package/dist/likec4diagram/ui/diagram-title/DiagramTitlePanel.js +4 -3
  12. package/dist/likec4diagram/ui/index.d.ts +2 -0
  13. package/dist/overlays/Overlays.js +1 -1
  14. package/dist/overlays/element-details/TabPanelDeployments.js +4 -2
  15. package/dist/style.css +1 -1
  16. package/package.json +5 -5
  17. package/src/base/BaseXYFlow.tsx +0 -1
  18. package/src/base/primitives/element/ElementNodeContainer.css.ts +4 -7
  19. package/src/base/primitives/element/ElementNodeContainer.tsx +36 -16
  20. package/src/base/primitives/element/ElementTitle.css.ts +12 -9
  21. package/src/base/primitives/element/ElementTitle.tsx +6 -2
  22. package/src/base/primitives/element/styles.css.ts +16 -38
  23. package/src/globals.css.ts +2 -0
  24. package/src/hooks/index.ts +0 -1
  25. package/src/index.ts +15 -1
  26. package/src/likec4diagram/DiagramUI.tsx +1 -4
  27. package/src/likec4diagram/custom/edges/RelationshipEdge.tsx +0 -1
  28. package/src/likec4diagram/custom/edges/RelationshipsDropdownMenu.css.ts +1 -0
  29. package/src/likec4diagram/custom/edges/RelationshipsDropdownMenu.tsx +1 -0
  30. package/src/likec4diagram/ui/diagram-title/DiagramTitlePanel.tsx +110 -107
  31. package/src/likec4diagram/ui/index.ts +2 -0
  32. package/src/likec4diagram/ui/notation/NotationPanel.tsx +2 -3
  33. package/src/overlays/Overlays.tsx +1 -1
  34. package/src/overlays/element-details/ElementDetailsCard.tsx +1 -4
  35. package/src/overlays/element-details/TabPanelDeployments.tsx +4 -4
  36. package/dist/hooks/useCurrentViewId.js +0 -8
@@ -6,6 +6,7 @@ import { isNumber, isTruthy } from 'remeda'
6
6
  import { IconRenderer } from '../../../context/IconRenderer'
7
7
  import { hiddenIfZoomTooSmall } from '../../../LikeC4Diagram.css'
8
8
  import type { NodeProps } from '../../types'
9
+ import { nodeSizes } from './ElementNodeContainer'
9
10
  import * as css from './ElementTitle.css'
10
11
  import { iconSize as varIconSize } from './styles.css'
11
12
 
@@ -35,6 +36,9 @@ export function ElementTitle({ id, data, iconSize }: ElementTitleProps) {
35
36
  },
36
37
  className: css.elementIcon,
37
38
  })
39
+ const size = nodeSizes(data.style).size
40
+ const isSm = size === 'sm'
41
+ const isSmOrXs = isSm || size === 'xs'
38
42
  return (
39
43
  <Box
40
44
  className={clsx(
@@ -53,7 +57,7 @@ export function ElementTitle({ id, data, iconSize }: ElementTitleProps) {
53
57
  <Text
54
58
  component="h3"
55
59
  className={clsx(css.title, 'likec4-element-title')}
56
- lineClamp={3}>
60
+ lineClamp={isSmOrXs ? 2 : 3}>
57
61
  {data.title}
58
62
  </Text>
59
63
 
@@ -69,7 +73,7 @@ export function ElementTitle({ id, data, iconSize }: ElementTitleProps) {
69
73
  <Text
70
74
  component="div"
71
75
  className={clsx(css.description, 'likec4-element-description')}
72
- lineClamp={5}>
76
+ lineClamp={isSmOrXs ? 3 : 5}>
73
77
  {data.description}
74
78
  </Text>
75
79
  )}
@@ -25,50 +25,28 @@ globalStyle(`${container}[data-likec4-shape-size="sm"]`, {
25
25
  [iconSize]: '36px',
26
26
  },
27
27
  })
28
- globalStyle(`${container}[data-likec4-shape-size="lg"], ${container}[data-likec4-shape-size="xl"]`, {
28
+ globalStyle(`${container}[data-likec4-shape-size="lg"]`, {
29
29
  vars: {
30
30
  [iconSize]: '82px',
31
31
  },
32
32
  })
33
-
34
- globalStyle(`${container}[data-likec4-text-size="xs"]`, {
35
- vars: {
36
- [textSize]: rem(defaultTheme.textSizes.xs),
37
- },
38
- })
39
- globalStyle(`${container}[data-likec4-text-size="sm"]`, {
33
+ globalStyle(`${container}[data-likec4-shape-size="xl"]`, {
40
34
  vars: {
41
- [textSize]: rem(defaultTheme.textSizes.sm),
42
- },
43
- })
44
- globalStyle(`${container}[data-likec4-text-size="lg"]`, {
45
- vars: {
46
- [textSize]: rem(defaultTheme.textSizes.lg),
47
- },
48
- })
49
- globalStyle(`${container}[data-likec4-text-size="xl"]`, {
50
- vars: {
51
- [textSize]: rem(defaultTheme.textSizes.xl),
35
+ [iconSize]: '90px',
52
36
  },
53
37
  })
54
38
 
55
- globalStyle(`${container}[data-likec4-padding="xs"]`, {
56
- vars: {
57
- [paddingSize]: rem(defaultTheme.spacing.xs),
58
- },
59
- })
60
- globalStyle(`${container}[data-likec4-padding="sm"]`, {
61
- vars: {
62
- [paddingSize]: rem(defaultTheme.spacing.sm),
63
- },
64
- })
65
- globalStyle(`${container}[data-likec4-padding="lg"]`, {
66
- vars: {
67
- [paddingSize]: rem(defaultTheme.spacing.lg),
68
- },
69
- })
70
- globalStyle(`${container}[data-likec4-padding="xl"]`, {
71
- vars: {
72
- [paddingSize]: rem(defaultTheme.spacing.xl),
73
- },
39
+ const sizes = ['xs', 'sm', 'lg', 'xl'] as const
40
+ sizes.forEach((size) => {
41
+ globalStyle(`${container}[data-likec4-text-size="${size}"]`, {
42
+ vars: {
43
+ [textSize]: rem(defaultTheme.textSizes[size]),
44
+ },
45
+ })
46
+
47
+ globalStyle(`${container}[data-likec4-padding="${size}"]`, {
48
+ vars: {
49
+ [paddingSize]: rem(defaultTheme.spacing[size]),
50
+ },
51
+ })
74
52
  })
@@ -7,6 +7,8 @@ import { mantine, vars, whereDark } from './theme-vars'
7
7
  export const rootClassName = 'likec4-diagram-root'
8
8
 
9
9
  globalStyle(`.${rootClassName}`, {
10
+ containerName: 'likec4-diagram-root',
11
+ containerType: 'size',
10
12
  overflow: 'hidden',
11
13
  position: 'relative',
12
14
  width: '100%',
@@ -1,5 +1,4 @@
1
1
  export { useCurrentViewId } from './useCurrentViewId'
2
- export type { DiagramContext } from './useDiagramContext'
3
2
  export { useMantinePortalProps } from './useMantinePortalProps'
4
3
  export { useSetState } from './useSetState'
5
4
  export { useUpdateEffect } from './useUpdateEffect'
package/src/index.ts CHANGED
@@ -16,7 +16,21 @@ export { useSetState } from './hooks/useSetState'
16
16
  export { useUpdateEffect } from './hooks/useUpdateEffect'
17
17
  export { vars, xyvars } from './theme-vars'
18
18
 
19
- export type * from './LikeC4Diagram.props'
19
+ export type {
20
+ ChangeEvent,
21
+ DiagramNodeWithNavigate,
22
+ ElementIconRenderer,
23
+ LikeC4ColorScheme,
24
+ LikeC4DiagramEventHandlers,
25
+ LikeC4DiagramProperties,
26
+ OnCanvasClick,
27
+ OnChange,
28
+ OnEdgeClick,
29
+ OnNavigateTo,
30
+ OnNodeClick,
31
+ OpenSourceParams,
32
+ WhereOperator,
33
+ } from './LikeC4Diagram.props'
20
34
 
21
35
  export { StaticLikeC4Diagram } from './StaticLikeC4Diagram'
22
36
  export type { StaticLikeC4DiagramProps } from './StaticLikeC4Diagram'
@@ -1,10 +1,7 @@
1
- import { memo } from 'react'
2
1
  import { IfEnabled } from '../context'
3
2
  import { LikeC4Search } from '../LikeC4Search'
4
3
  import { Overlays } from '../overlays/Overlays'
5
- import { Controls, DiagramTitlePanel } from './ui'
6
- import NotationPanel from './ui/notation'
7
- import { DynamicViewWalkthrough } from './ui/walkthrough/DynamicViewWalkthrough'
4
+ import { Controls, DiagramTitlePanel, DynamicViewWalkthrough, NotationPanel } from './ui'
8
5
 
9
6
  export function DiagramUI() {
10
7
  return (
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  type EdgeId,
3
- type NodeId,
4
3
  isStepEdgeId,
5
4
  nonNullable,
6
5
  } from '@likec4/core'
@@ -2,6 +2,7 @@ import { style } from '@vanilla-extract/css'
2
2
  import { mantine, vars } from '../../../theme-vars'
3
3
 
4
4
  export const menuDropdown = style({
5
+ overflowY: 'scroll',
5
6
  minWidth: 250,
6
7
  maxWidth: 'min(90vw, 500px)',
7
8
  })
@@ -130,6 +130,7 @@ export function RelationshipsDropdownMenu({
130
130
  closeOnItemClick={false}
131
131
  disabled={disabled}
132
132
  position="bottom-start"
133
+ middlewares={{ size: { padding: 8 } }}
133
134
  {...portalProps}
134
135
  >
135
136
  <MenuTarget>
@@ -13,10 +13,11 @@ const selector = (s: DiagramContext) => ({
13
13
  title: s.view.title ?? 'untitled',
14
14
  description: s.view.description,
15
15
  links: s.view.links,
16
+ isNotActiveWalkthrough: s.activeWalkthrough === null,
16
17
  })
17
18
 
18
19
  export function DiagramTitlePanel() {
19
- const { id, title, description, links } = useDiagramContext(selector)
20
+ const { id, title, description, links, isNotActiveWalkthrough } = useDiagramContext(selector)
20
21
  const [isCollapsed, setCollapsed] = useLocalStorage({
21
22
  key: 'diagram-title-webview-collapsed',
22
23
  defaultValue: false,
@@ -41,126 +42,128 @@ export function DiagramTitlePanel() {
41
42
  </div>
42
43
  </ViewportPortal> */
43
44
  }
44
- <m.div
45
- key={id}
46
- initial={{ opacity: 0.05, scale: 0.7 }}
47
- animate={{ opacity: 1, scale: 1 }}
48
- exit={{
49
- opacity: 0.05,
50
- scale: 0.6,
51
- }}
52
- className={clsx('react-flow__panel', css.container)}
53
- style={{
54
- transformOrigin: 'left center',
55
- }}
56
- >
57
- <Card
58
- radius="sm"
59
- className={css.card}
60
- withBorder={!isCollapsed}
61
- p={isCollapsed ? 'sm' : 'md'}
62
- onDoubleClick={e => e.stopPropagation()}>
63
- {isCollapsed && (
64
- <CardSection>
65
- <Button
66
- fullWidth
67
- justify="stretch"
68
- size="md"
69
- radius={'0'}
70
- variant={'subtle'}
71
- color="gray"
72
- onClick={toggle}
73
- fw={500}
74
- fz={'sm'}
75
- tabIndex={-1}
76
- >
77
- {title}
78
- </Button>
79
- </CardSection>
80
- )}
81
- {!isCollapsed && (
82
- <>
83
- <CardSection mb={'xs'}>
45
+ {isNotActiveWalkthrough && (
46
+ <m.div
47
+ key={id}
48
+ initial={{ opacity: 0.05, scale: 0.7 }}
49
+ animate={{ opacity: 1, scale: 1 }}
50
+ exit={{
51
+ opacity: 0.05,
52
+ scale: 0.6,
53
+ }}
54
+ className={clsx('react-flow__panel', css.container)}
55
+ style={{
56
+ transformOrigin: 'left center',
57
+ }}
58
+ >
59
+ <Card
60
+ radius="sm"
61
+ className={css.card}
62
+ withBorder={!isCollapsed}
63
+ p={isCollapsed ? 'sm' : 'md'}
64
+ onDoubleClick={e => e.stopPropagation()}>
65
+ {isCollapsed && (
66
+ <CardSection>
84
67
  <Button
85
68
  fullWidth
86
- size="xs"
87
- h={'sm'}
88
- py={2}
69
+ justify="stretch"
70
+ size="md"
89
71
  radius={'0'}
90
72
  variant={'subtle'}
91
73
  color="gray"
92
74
  onClick={toggle}
75
+ fw={500}
76
+ fz={'sm'}
93
77
  tabIndex={-1}
94
78
  >
95
- <IconMenu size={11} opacity={0.7} />
79
+ {title}
96
80
  </Button>
97
81
  </CardSection>
82
+ )}
83
+ {!isCollapsed && (
84
+ <>
85
+ <CardSection mb={'xs'}>
86
+ <Button
87
+ fullWidth
88
+ size="xs"
89
+ h={'sm'}
90
+ py={2}
91
+ radius={'0'}
92
+ variant={'subtle'}
93
+ color="gray"
94
+ onClick={toggle}
95
+ tabIndex={-1}
96
+ >
97
+ <IconMenu size={11} opacity={0.7} />
98
+ </Button>
99
+ </CardSection>
98
100
 
99
- <Group justify="stretch" wrap="nowrap" mb={'sm'}>
100
- <Text
101
- component={'div'}
102
- flex={'1'}
103
- size={'md'}
104
- fw={500}
105
- lh={1.1}
106
- className={css.title}
107
- >
108
- {title}
109
- </Text>
110
- <Text
111
- hidden={isCollapsed}
112
- component={'div'}
113
- flex={'0 0 auto'}
114
- inline
115
- size="xs"
116
- fz={9}
117
- fw={500}
118
- c={'dimmed'}
119
- style={{
120
- userSelect: 'all',
121
- }}>
122
- <span style={{ userSelect: 'none' }}>id:{' '}</span>
123
- {id}
124
- </Text>
125
- </Group>
126
- {description && (
127
- <Spoiler
128
- maxHeight={42}
129
- showLabel={
130
- <Button color="gray" variant="light" fz={'10'} size="compact-xs" tabIndex={-1}>show more</Button>
131
- }
132
- hideLabel={
133
- <Button color="gray" variant="light" fz={'10'} size="compact-xs" tabIndex={-1}>hide</Button>
134
- }>
101
+ <Group justify="stretch" wrap="nowrap" mb={'sm'}>
135
102
  <Text
136
103
  component={'div'}
137
- size="sm"
138
- className={css.description}>
139
- {description || 'no description'}
104
+ flex={'1'}
105
+ size={'md'}
106
+ fw={500}
107
+ lh={1.1}
108
+ className={css.title}
109
+ >
110
+ {title}
140
111
  </Text>
141
- </Spoiler>
142
- )}
143
- {!description && (
144
- <Text
145
- component={'div'}
146
- size="xs"
147
- c={'dimmed'}>
148
- no description
149
- </Text>
150
- )}
151
- {links && (
152
- <Stack
153
- mt={'xs'}
154
- gap={4}
155
- justify="stretch"
156
- align="stretch">
157
- {links.map((link) => <Link value={link} key={link.url} />)}
158
- </Stack>
159
- )}
160
- </>
161
- )}
162
- </Card>
163
- </m.div>
112
+ <Text
113
+ hidden={isCollapsed}
114
+ component={'div'}
115
+ flex={'0 0 auto'}
116
+ inline
117
+ size="xs"
118
+ fz={9}
119
+ fw={500}
120
+ c={'dimmed'}
121
+ style={{
122
+ userSelect: 'all',
123
+ }}>
124
+ <span style={{ userSelect: 'none' }}>id:{' '}</span>
125
+ {id}
126
+ </Text>
127
+ </Group>
128
+ {description && (
129
+ <Spoiler
130
+ maxHeight={42}
131
+ showLabel={
132
+ <Button color="gray" variant="light" fz={'10'} size="compact-xs" tabIndex={-1}>show more</Button>
133
+ }
134
+ hideLabel={
135
+ <Button color="gray" variant="light" fz={'10'} size="compact-xs" tabIndex={-1}>hide</Button>
136
+ }>
137
+ <Text
138
+ component={'div'}
139
+ size="sm"
140
+ className={css.description}>
141
+ {description || 'no description'}
142
+ </Text>
143
+ </Spoiler>
144
+ )}
145
+ {!description && (
146
+ <Text
147
+ component={'div'}
148
+ size="xs"
149
+ c={'dimmed'}>
150
+ no description
151
+ </Text>
152
+ )}
153
+ {links && (
154
+ <Stack
155
+ mt={'xs'}
156
+ gap={4}
157
+ justify="stretch"
158
+ align="stretch">
159
+ {links.map((link) => <Link value={link} key={link.url} />)}
160
+ </Stack>
161
+ )}
162
+ </>
163
+ )}
164
+ </Card>
165
+ </m.div>
166
+ )}
164
167
  </AnimatePresence>
165
168
  )
166
169
  }
@@ -1,2 +1,4 @@
1
1
  export { Controls } from './controls/Controls'
2
2
  export { DiagramTitlePanel } from './diagram-title/DiagramTitlePanel'
3
+ export { NotationPanel } from './notation/NotationPanel'
4
+ export { DynamicViewWalkthrough } from './walkthrough/DynamicViewWalkthrough'
@@ -1,4 +1,3 @@
1
- // @ts-ignore
2
1
  import { type ComputedNode, type ElementNotation as ElementNotationData } from '@likec4/core'
3
2
  import {
4
3
  ActionIcon,
@@ -23,12 +22,12 @@ import clsx from 'clsx'
23
22
  import { AnimatePresence, m } from 'framer-motion'
24
23
  import { memo, useState } from 'react'
25
24
  import { ceil, isNonNullish } from 'remeda'
26
- // import { ElementShapeSvg } from '../../xyflow/nodes/element/ElementShapeSvg'
27
25
  import { ElementShape } from '../../../base/primitives'
28
- import { type DiagramContext, useMantinePortalProps } from '../../../hooks'
26
+ import { useMantinePortalProps } from '../../../hooks'
29
27
  import { useDiagram } from '../../../hooks/useDiagram'
30
28
  import { useDiagramContext } from '../../../hooks/useDiagramContext'
31
29
  import { useXYStore } from '../../../hooks/useXYFlow'
30
+ import { DiagramContext } from '../../../likec4diagram/state/machine'
32
31
  import { vars } from '../../../theme-vars'
33
32
  import * as css from './NotationPanel.css'
34
33
 
@@ -73,7 +73,7 @@ export const Overlays = memo(() => {
73
73
 
74
74
  const isMotionReduced = useReducedMotion() ?? false
75
75
 
76
- const isActiveOverlay = !!activeElementDetailsOf
76
+ const isActiveOverlay = !!activeElementDetailsOf || !!relationshipsBrowserActor || !!relationshipDetailsActor
77
77
 
78
78
  useEffect(() => {
79
79
  if (!xyflowRendererDom || isMotionReduced) return
@@ -112,11 +112,8 @@ export function ElementDetailsCard({
112
112
  const diagram = useDiagram()
113
113
  const likec4model = useLikeC4Model(true)
114
114
  const viewModel = likec4model.view(viewId)
115
- // const currentView = diagram.currentView()
116
- // const diagramNode = currentView.nodes.find(n => n.id === fqn)
117
- // invariant(diagramNode, `DiagramNode with fqn ${fqn} not found`)
118
115
  const nodeModel = fromNode ? viewModel.findNode(fromNode) : viewModel.findNodeWithElement(fqn)
119
- // invariant(nodeModel && nodeModel.hasElement(), `NodeModel with fqn ${fqn} not found`)
116
+
120
117
  const elementModel = viewModel.$model.element(fqn)
121
118
 
122
119
  // const incoming = elementModel.incoming().map(r => r.id).toArray()
@@ -2,7 +2,7 @@ import type { Fqn, LikeC4Model } from '@likec4/core'
2
2
  import { Alert, Box, Button, Group, Menu, rem, Text, ThemeIcon, Tree, useTree } from '@mantine/core'
3
3
  import { IconInfoCircle, IconTarget, IconZoomScan } from '@tabler/icons-react'
4
4
  import { type ReactNode, memo, useEffect, useMemo } from 'react'
5
- import { useCurrentViewId } from '../../hooks/useCurrentViewId'
5
+ import { useDiagram } from '../../hooks/useDiagram'
6
6
  import { useLikeC4Model } from '../../likec4model/useLikeC4Model'
7
7
  import { stopPropagation } from '../../utils'
8
8
  import * as css from './TabPanelDeployments.css'
@@ -36,8 +36,8 @@ const DeployedInstanceRenderer = (
36
36
  instance: LikeC4Model.DeployedInstance
37
37
  },
38
38
  ) => {
39
- const currentViewId = useCurrentViewId()
40
- // const diagramApi = useDiagramStoreApi()
39
+ const diagram = useDiagram()
40
+ const currentViewId = diagram.currentView().id
41
41
  const views = [...instance.views()]
42
42
  return (
43
43
  (
@@ -91,7 +91,7 @@ const DeployedInstanceRenderer = (
91
91
  }}
92
92
  onClick={e => {
93
93
  e.stopPropagation()
94
- // diagramApi.getState().onNavigateTo?.(view.id)
94
+ diagram.navigateTo(view.id)
95
95
  }}>
96
96
  {view.title}
97
97
  </Menu.Item>
@@ -1,8 +0,0 @@
1
- import { useDiagramContext } from "./useDiagramContext.js";
2
- const selectViewId = (state) => state.view.id;
3
- function useCurrentViewId() {
4
- return useDiagramContext(selectViewId);
5
- }
6
- export {
7
- useCurrentViewId
8
- };