@likec4/diagram 1.40.0 → 1.41.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.
- package/bundle/{chunk-CDr-4Ymp.js → chunk-FGcODVxo.js} +232 -229
- package/bundle/custom.js +59 -59
- package/bundle/index.js +140 -100
- package/dist/base/primitives/MarkdownBlock.js +2 -0
- package/dist/components/Link.js +28 -20
- package/dist/likec4diagram/custom/edges/RelationshipEdge.d.ts +1 -1
- package/dist/navigationpanel/controls/ViewDetailsCard.js +22 -10
- package/dist/overlays/element-details/ElementDetailsCard.css.js +7 -1
- package/dist/overlays/element-details/ElementDetailsCard.js +17 -19
- package/dist/overlays/relationship-details/layout.d.ts +3 -2
- package/dist/overlays/relationship-details/layout.js +1 -2
- package/dist/overlays/relationships-browser/RelationshipsBrowser.js +2 -1
- package/dist/overlays/relationships-browser/layout.js +1 -1
- package/dist/search/components/ElementsColumn.js +1 -1
- package/dist/state/DiagramActorProvider.js +23 -32
- package/dist/styles-min.css +1 -1
- package/dist/styles.css +1 -1
- package/dist/styles.css2.js +1 -1
- package/package.json +4 -4
- package/panda.buildinfo.json +15 -15
- package/src/base/primitives/MarkdownBlock.tsx +2 -0
- package/src/components/Link.tsx +21 -18
- package/src/navigationpanel/controls/ViewDetailsCard.tsx +24 -10
- package/src/overlays/element-details/ElementDetailsCard.css.ts +7 -1
- package/src/overlays/element-details/ElementDetailsCard.tsx +24 -25
- package/src/overlays/relationship-details/layout.ts +4 -3
- package/src/overlays/relationships-browser/RelationshipsBrowser.tsx +2 -1
- package/src/overlays/relationships-browser/layout.ts +1 -1
- package/src/search/components/ElementsColumn.tsx +1 -1
- package/src/state/DiagramActorProvider.tsx +29 -45
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@likec4/diagram",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.41.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
6
6
|
"homepage": "https://likec4.dev",
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
"remeda": "^2.30.0",
|
|
90
90
|
"type-fest": "^4.41.0",
|
|
91
91
|
"xstate": "^5.20.2",
|
|
92
|
-
"@likec4/core": "1.
|
|
93
|
-
"@likec4/styles": "1.
|
|
92
|
+
"@likec4/core": "1.41.0",
|
|
93
|
+
"@likec4/styles": "1.41.0"
|
|
94
94
|
},
|
|
95
95
|
"peerDependencies": {
|
|
96
96
|
"@pandacss/dev": "^1.3.0",
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
"vite-plugin-dts": "^4.5.4",
|
|
121
121
|
"vitest": "3.2.4",
|
|
122
122
|
"wireit": "0.14.12",
|
|
123
|
-
"@likec4/tsconfig": "1.
|
|
123
|
+
"@likec4/tsconfig": "1.41.0"
|
|
124
124
|
},
|
|
125
125
|
"scripts": {
|
|
126
126
|
"typecheck": "tsc --build --verbose",
|
package/panda.buildinfo.json
CHANGED
|
@@ -37,16 +37,12 @@
|
|
|
37
37
|
"color]___[value:mantine.colors.dimmed]___[cond:&:is([data-position=\"left\"])",
|
|
38
38
|
"userSelect]___[value:none]___[cond:&:is([data-position=\"left\"])",
|
|
39
39
|
"pointerEvents]___[value:none]___[cond:&:is([data-position=\"left\"])",
|
|
40
|
-
"color]___[value:[
|
|
40
|
+
"color]___[value:[var(--badge-color)]]___[cond:&:is([data-position=\"left\"])<___>_groupHover",
|
|
41
41
|
"opacity]___[value:0.7]___[cond:&:is([data-position=\"left\"])<___>_groupHover",
|
|
42
|
-
"color]___[value:[inherit]]___[cond:& > a",
|
|
43
|
-
"cursor]___[value:pointer]___[cond:& > a",
|
|
44
|
-
"transition]___[value:fast]___[cond:& > a",
|
|
45
|
-
"opacity]___[value:0.7]___[cond:& > a",
|
|
46
|
-
"opacity]___[value:1]___[cond:& > a<___>_hover",
|
|
47
|
-
"textDecoration]___[value:none]___[cond:& > a",
|
|
48
|
-
"textDecoration]___[value:underline]___[cond:& > a<___>_hover",
|
|
49
42
|
"stroke]___[value:2.5",
|
|
43
|
+
"opacity]___[value:0.7",
|
|
44
|
+
"textDecoration]___[value:none",
|
|
45
|
+
"textDecoration]___[value:underline]___[cond:_hover",
|
|
50
46
|
"height]___[value:12",
|
|
51
47
|
"width]___[value:12",
|
|
52
48
|
"height]___[value:30px",
|
|
@@ -249,16 +245,17 @@
|
|
|
249
245
|
"gap]___[value:md",
|
|
250
246
|
"margin]___[value:xs",
|
|
251
247
|
"padding]___[value:md",
|
|
252
|
-
"
|
|
253
|
-
"
|
|
248
|
+
"paddingBottom]___[value:lg",
|
|
249
|
+
"maxWidth]___[value:calc(100cqw - 52px)",
|
|
250
|
+
"minWidth]___[value:200px",
|
|
254
251
|
"maxHeight]___[value:calc(100cqh - 100px)",
|
|
255
252
|
"overflow]___[value:auto",
|
|
256
253
|
"overscrollBehavior]___[value:contain",
|
|
257
254
|
"minWidth]___[value:400]___[cond:@/sm",
|
|
258
255
|
"maxWidth]___[value:550]___[cond:@/sm",
|
|
259
256
|
"maxWidth]___[value:700]___[cond:@/lg",
|
|
260
|
-
"marginBlock]___[value:md",
|
|
261
257
|
"overflow]___[value:visible",
|
|
258
|
+
"color]___[value:mantine.colors.gray[4]]___[cond:_dark",
|
|
262
259
|
"color]___[value:mantine.colors.gray[8]]___[cond:_light",
|
|
263
260
|
"opacity]___[value:0.5",
|
|
264
261
|
"marginInlineEnd]___[value:0.5",
|
|
@@ -331,6 +328,8 @@
|
|
|
331
328
|
"--text-fz]___[value:{fontSizes.sm}",
|
|
332
329
|
"--text-fz]___[value:{fontSizes.md}]___[cond:md",
|
|
333
330
|
"paddingTop]___[value:xxs",
|
|
331
|
+
"maxWidth]___[value:calc(100cqw - 32px)",
|
|
332
|
+
"minWidth]___[value:calc(100cqw - 50px)",
|
|
334
333
|
"boxSizing]___[value:border-box",
|
|
335
334
|
"inset]___[value:0",
|
|
336
335
|
"width]___[value:100vw",
|
|
@@ -341,6 +340,7 @@
|
|
|
341
340
|
"backdropBlur]___[value:var(--_blur)]___[cond:_backdrop",
|
|
342
341
|
"backgroundColor]___[value:[rgb(36 36 36 / var(--_opacity, 5%))]]___[cond:_backdrop",
|
|
343
342
|
"gap]___[value:lg",
|
|
343
|
+
"color]___[value:mantine.colors.text",
|
|
344
344
|
"backgroundColor]___[value:mantine.colors.body",
|
|
345
345
|
"backgroundColor]___[value:mantine.colors.dark[6]]___[cond:_dark",
|
|
346
346
|
"border]___[value:none",
|
|
@@ -424,13 +424,15 @@
|
|
|
424
424
|
"cursor]___[value:se-resize",
|
|
425
425
|
"borderWidth]___[value:4px]___[cond:_hover",
|
|
426
426
|
"borderColor]___[value:mantine.colors.dark[1]]___[cond:_hover",
|
|
427
|
+
"alignItems]___[value:start",
|
|
428
|
+
"justifyContent]___[value:space-between",
|
|
427
429
|
"marginBottom]___[value:sm",
|
|
428
|
-
"gap]___[value:6",
|
|
429
430
|
"lineClamp]___[value:1",
|
|
430
431
|
"gap]___[value:4",
|
|
431
432
|
"marginTop]___[value:6",
|
|
432
433
|
"stroke]___[value:1.6",
|
|
433
434
|
"paddingTop]___[value:xs",
|
|
435
|
+
"gap]___[value:6",
|
|
434
436
|
"gap]___[value:[4px 4px]",
|
|
435
437
|
"paddingRight]___[value:xxs",
|
|
436
438
|
"transitionProperty]___[value:all",
|
|
@@ -441,7 +443,7 @@
|
|
|
441
443
|
"color]___[value:mantine.colors.defaultColor]___[cond:_groupHover",
|
|
442
444
|
"background]___[value:mantine.colors.defaultHover]___[cond:_groupHover",
|
|
443
445
|
"whiteSpace]___[value:pre",
|
|
444
|
-
"fontFamily]___[value:
|
|
446
|
+
"fontFamily]___[value:mono",
|
|
445
447
|
"overscrollBehavior]___[value:none",
|
|
446
448
|
"marginBottom]___[value:sm]___[cond:&[data-level='1']",
|
|
447
449
|
"marginBottom]___[value:0",
|
|
@@ -665,7 +667,6 @@
|
|
|
665
667
|
"top]___[value:[2rem]",
|
|
666
668
|
"left]___[value:[50%]",
|
|
667
669
|
"maxWidth]___[value:600px",
|
|
668
|
-
"minWidth]___[value:200px",
|
|
669
670
|
"transform]___[value:translateX(-50%)",
|
|
670
671
|
"zIndex]___[value:903",
|
|
671
672
|
"marginTop]___[value:[32px]]___[cond:& + &",
|
|
@@ -795,7 +796,6 @@
|
|
|
795
796
|
"marginBottom]___[value:xs",
|
|
796
797
|
"height]___[value:sm",
|
|
797
798
|
"paddingBlock]___[value:2",
|
|
798
|
-
"opacity]___[value:0.7",
|
|
799
799
|
"flex]___[value:0 0 auto",
|
|
800
800
|
"maxHeight]___[value:60",
|
|
801
801
|
"right]___[value:0",
|
|
@@ -45,6 +45,7 @@ export const MarkdownBlock = forwardRef<HTMLDivElement, MarkdownBlockProps>(({
|
|
|
45
45
|
hideIfEmpty = false,
|
|
46
46
|
emptyText = 'no content',
|
|
47
47
|
className,
|
|
48
|
+
style,
|
|
48
49
|
...props
|
|
49
50
|
}, ref) => {
|
|
50
51
|
if (value.isEmpty && hideIfEmpty) {
|
|
@@ -67,6 +68,7 @@ export const MarkdownBlock = forwardRef<HTMLDivElement, MarkdownBlockProps>(({
|
|
|
67
68
|
className,
|
|
68
69
|
)}
|
|
69
70
|
style={{
|
|
71
|
+
...style,
|
|
70
72
|
...props.fontSize && {
|
|
71
73
|
'--text-fz': `var(--font-sizes-${props.fontSize}, var(--font-sizes-md))`,
|
|
72
74
|
},
|
package/src/components/Link.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Link as LinkData } from '@likec4/core'
|
|
2
2
|
import { css, cx } from '@likec4/styles/css'
|
|
3
|
+
import { styled } from '@likec4/styles/jsx'
|
|
3
4
|
import { type BadgeProps, ActionIcon, Badge, CopyButton } from '@mantine/core'
|
|
4
5
|
import { IconCheck, IconCopy } from '@tabler/icons-react'
|
|
5
6
|
import { forwardRef } from 'react'
|
|
@@ -72,29 +73,31 @@ export const Link = forwardRef<HTMLDivElement, Omit<BadgeProps, 'children' | 'cl
|
|
|
72
73
|
userSelect: 'none',
|
|
73
74
|
pointerEvents: 'none',
|
|
74
75
|
_groupHover: {
|
|
75
|
-
color: '[
|
|
76
|
+
color: '[var(--badge-color)]',
|
|
76
77
|
opacity: .7,
|
|
77
78
|
},
|
|
78
79
|
},
|
|
79
80
|
}),
|
|
80
|
-
label: css({
|
|
81
|
-
'& > a': {
|
|
82
|
-
color: '[inherit]',
|
|
83
|
-
cursor: 'pointer',
|
|
84
|
-
transition: 'fast',
|
|
85
|
-
opacity: {
|
|
86
|
-
base: 0.7,
|
|
87
|
-
_hover: 1,
|
|
88
|
-
},
|
|
89
|
-
textDecoration: {
|
|
90
|
-
base: 'none',
|
|
91
|
-
_hover: 'underline',
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
}),
|
|
95
81
|
}}
|
|
96
82
|
>
|
|
97
|
-
<a
|
|
83
|
+
<styled.a
|
|
84
|
+
href={url}
|
|
85
|
+
target="_blank"
|
|
86
|
+
style={{
|
|
87
|
+
color: 'var(--badge-color)',
|
|
88
|
+
cursor: 'pointer',
|
|
89
|
+
}}
|
|
90
|
+
css={{
|
|
91
|
+
transition: 'fast',
|
|
92
|
+
opacity: {
|
|
93
|
+
base: 0.7,
|
|
94
|
+
_hover: 1,
|
|
95
|
+
},
|
|
96
|
+
textDecoration: {
|
|
97
|
+
base: 'none',
|
|
98
|
+
_hover: 'underline',
|
|
99
|
+
},
|
|
100
|
+
}}>
|
|
98
101
|
{isGithub && (
|
|
99
102
|
<GithubIcon
|
|
100
103
|
height="12"
|
|
@@ -102,7 +105,7 @@ export const Link = forwardRef<HTMLDivElement, Omit<BadgeProps, 'children' | 'cl
|
|
|
102
105
|
style={{ verticalAlign: 'middle', marginRight: '4px' }} />
|
|
103
106
|
)}
|
|
104
107
|
{isGithub ? url.replace(GITHUB_PREFIX, '') : url}
|
|
105
|
-
</a>
|
|
108
|
+
</styled.a>
|
|
106
109
|
</Badge>
|
|
107
110
|
)
|
|
108
111
|
},
|
|
@@ -10,9 +10,10 @@ import {
|
|
|
10
10
|
} from '@mantine/core'
|
|
11
11
|
import { IconId, IconLink } from '@tabler/icons-react'
|
|
12
12
|
import * as m from 'motion/react-m'
|
|
13
|
+
import { useState } from 'react'
|
|
13
14
|
import { ElementTag, MarkdownBlock } from '../../base/primitives'
|
|
14
15
|
import { Link } from '../../components/Link'
|
|
15
|
-
import { useDiagram } from '../../hooks/useDiagram'
|
|
16
|
+
import { useDiagram, useOnDiagramEvent } from '../../hooks/useDiagram'
|
|
16
17
|
import { useMantinePortalProps } from '../../hooks/useMantinePortalProps'
|
|
17
18
|
import type { NavigationPanelActorSnapshot } from '../actor'
|
|
18
19
|
import { useNavigationActorSnapshot } from '../hooks'
|
|
@@ -32,6 +33,7 @@ const selector = ({ context }: NavigationPanelActorSnapshot) => {
|
|
|
32
33
|
type ViewDetailsCardData = ReturnType<typeof selector>
|
|
33
34
|
|
|
34
35
|
export const ViewDetailsCard = (props: PopoverProps) => {
|
|
36
|
+
const [opened, setOpened] = useState(false)
|
|
35
37
|
const data = useNavigationActorSnapshot(selector)
|
|
36
38
|
const portalProps = useMantinePortalProps()
|
|
37
39
|
|
|
@@ -40,20 +42,21 @@ export const ViewDetailsCard = (props: PopoverProps) => {
|
|
|
40
42
|
position="bottom-end"
|
|
41
43
|
shadow="xl"
|
|
42
44
|
clickOutsideEvents={['pointerdown', 'mousedown', 'click']}
|
|
43
|
-
trapFocus
|
|
44
45
|
offset={{
|
|
45
46
|
mainAxis: 4,
|
|
46
47
|
}}
|
|
48
|
+
opened={opened}
|
|
49
|
+
onChange={setOpened}
|
|
47
50
|
{...portalProps}
|
|
48
51
|
{...props}
|
|
49
52
|
>
|
|
50
|
-
<ViewDetailsCardTrigger linksCount={data.links.length} />
|
|
51
|
-
<ViewDetailsCardDropdown data={data} />
|
|
53
|
+
<ViewDetailsCardTrigger linksCount={data.links.length} onOpen={() => setOpened(true)} />
|
|
54
|
+
{opened && <ViewDetailsCardDropdown data={data} onClose={() => setOpened(false)} />}
|
|
52
55
|
</Popover>
|
|
53
56
|
)
|
|
54
57
|
}
|
|
55
58
|
|
|
56
|
-
const ViewDetailsCardTrigger = ({ linksCount }: { linksCount: number }) => (
|
|
59
|
+
const ViewDetailsCardTrigger = ({ linksCount, onOpen }: { linksCount: number; onOpen: () => void }) => (
|
|
57
60
|
<Popover.Target>
|
|
58
61
|
<UnstyledButton
|
|
59
62
|
component={m.button}
|
|
@@ -62,6 +65,10 @@ const ViewDetailsCardTrigger = ({ linksCount }: { linksCount: number }) => (
|
|
|
62
65
|
scale: 0.95,
|
|
63
66
|
translateY: 1,
|
|
64
67
|
}}
|
|
68
|
+
onClick={e => {
|
|
69
|
+
e.stopPropagation()
|
|
70
|
+
onOpen()
|
|
71
|
+
}}
|
|
65
72
|
className={cx(
|
|
66
73
|
'group',
|
|
67
74
|
hstack({
|
|
@@ -123,8 +130,13 @@ const ViewDetailsCardDropdown = ({
|
|
|
123
130
|
links,
|
|
124
131
|
relativePath,
|
|
125
132
|
},
|
|
126
|
-
|
|
133
|
+
onClose,
|
|
134
|
+
}: { data: ViewDetailsCardData; onClose: () => void }) => {
|
|
127
135
|
const diagram = useDiagram()
|
|
136
|
+
|
|
137
|
+
useOnDiagramEvent('paneClick', onClose)
|
|
138
|
+
useOnDiagramEvent('nodeClick', onClose)
|
|
139
|
+
|
|
128
140
|
return (
|
|
129
141
|
<Popover.Dropdown
|
|
130
142
|
className={cx(
|
|
@@ -134,9 +146,10 @@ const ViewDetailsCardDropdown = ({
|
|
|
134
146
|
layerStyle: 'likec4.dropdown',
|
|
135
147
|
gap: 'md',
|
|
136
148
|
padding: 'md',
|
|
149
|
+
paddingBottom: 'lg',
|
|
137
150
|
pointerEvents: 'all',
|
|
138
|
-
maxWidth: 'calc(100cqw -
|
|
139
|
-
minWidth: '
|
|
151
|
+
maxWidth: 'calc(100cqw - 52px)',
|
|
152
|
+
minWidth: '200px',
|
|
140
153
|
maxHeight: 'calc(100cqh - 100px)',
|
|
141
154
|
width: 'max-content',
|
|
142
155
|
cursor: 'default',
|
|
@@ -152,7 +165,7 @@ const ViewDetailsCardDropdown = ({
|
|
|
152
165
|
}),
|
|
153
166
|
)}>
|
|
154
167
|
<section>
|
|
155
|
-
<Text component="div" fw={500} size="xl">{title}</Text>
|
|
168
|
+
<Text component="div" fw={500} size="xl" lh={'sm'}>{title}</Text>
|
|
156
169
|
<HStack alignItems={'flex-start'} mt="1">
|
|
157
170
|
<ViewBadge label="id" value={id} />
|
|
158
171
|
{/* {relativePath && <ViewBadge label="source" value={relativePath} />} */}
|
|
@@ -179,7 +192,7 @@ const ViewDetailsCardDropdown = ({
|
|
|
179
192
|
</section>
|
|
180
193
|
)}
|
|
181
194
|
{description.isEmpty && (
|
|
182
|
-
<Text component="div" fw={500} size="xs" c="dimmed"
|
|
195
|
+
<Text component="div" fw={500} size="xs" c="dimmed" style={{ userSelect: 'none' }}>No description</Text>
|
|
183
196
|
)}
|
|
184
197
|
{description.nonEmpty && (
|
|
185
198
|
<section>
|
|
@@ -221,6 +234,7 @@ const ViewBadge = ({
|
|
|
221
234
|
overflow: 'visible',
|
|
222
235
|
px: '1',
|
|
223
236
|
color: {
|
|
237
|
+
_dark: 'mantine.colors.gray[4]',
|
|
224
238
|
_light: 'mantine.colors.gray[8]',
|
|
225
239
|
},
|
|
226
240
|
}),
|
|
@@ -25,13 +25,19 @@ export const dialog = css({
|
|
|
25
25
|
export const card = css({
|
|
26
26
|
position: 'absolute',
|
|
27
27
|
pointerEvents: 'all',
|
|
28
|
+
display: 'flex',
|
|
29
|
+
flexDirection: 'column',
|
|
30
|
+
padding: '4',
|
|
28
31
|
gap: 'lg',
|
|
29
32
|
justifyContent: 'stretch',
|
|
33
|
+
color: 'mantine.colors.text',
|
|
30
34
|
backgroundColor: {
|
|
31
35
|
base: 'mantine.colors.body',
|
|
32
36
|
_dark: 'mantine.colors.dark[6]',
|
|
33
37
|
},
|
|
34
|
-
|
|
38
|
+
boxShadow: 'md',
|
|
39
|
+
overflow: 'hidden',
|
|
40
|
+
border: 'none',
|
|
35
41
|
backgroundImage: `
|
|
36
42
|
linear-gradient(180deg,
|
|
37
43
|
color-mix(in srgb, var(--likec4-palette-fill) 60%, transparent),
|
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
ActionIconGroup,
|
|
17
17
|
Badge,
|
|
18
18
|
Box,
|
|
19
|
-
Card,
|
|
20
19
|
CloseButton,
|
|
21
20
|
Divider as MantineDivider,
|
|
22
21
|
Flex,
|
|
@@ -48,7 +47,7 @@ import { DiagramFeatures, IconRenderer, IfEnabled } from '../../context'
|
|
|
48
47
|
import { useUpdateEffect } from '../../hooks'
|
|
49
48
|
import { useDiagram } from '../../hooks/useDiagram'
|
|
50
49
|
import type { OnNavigateTo } from '../../LikeC4Diagram.props'
|
|
51
|
-
import {
|
|
50
|
+
import { useCurrentViewModel } from '../../likec4model'
|
|
52
51
|
import { stopPropagation } from '../../utils'
|
|
53
52
|
import * as styles from './ElementDetailsCard.css'
|
|
54
53
|
import { TabPanelDeployments } from './TabPanelDeployments'
|
|
@@ -115,8 +114,7 @@ export function ElementDetailsCard({
|
|
|
115
114
|
defaultValue: 'Properties',
|
|
116
115
|
})
|
|
117
116
|
const diagram = useDiagram()
|
|
118
|
-
const
|
|
119
|
-
const viewModel = likec4model.view(viewId)
|
|
117
|
+
const viewModel = useCurrentViewModel()
|
|
120
118
|
const nodeModel = fromNode ? viewModel.findNode(fromNode) : viewModel.findNodeWithElement(fqn)
|
|
121
119
|
|
|
122
120
|
const elementModel = viewModel.$model.element(fqn)
|
|
@@ -221,7 +219,7 @@ export function ElementDetailsCard({
|
|
|
221
219
|
*/
|
|
222
220
|
useTimeoutEffect(() => {
|
|
223
221
|
setOpened(true)
|
|
224
|
-
},
|
|
222
|
+
}, 220)
|
|
225
223
|
|
|
226
224
|
return (
|
|
227
225
|
<m.dialog
|
|
@@ -257,9 +255,7 @@ export function ElementDetailsCard({
|
|
|
257
255
|
}}
|
|
258
256
|
>
|
|
259
257
|
<RemoveScroll forwardProps removeScrollBar={false}>
|
|
260
|
-
<
|
|
261
|
-
shadow="md"
|
|
262
|
-
component={m.div}
|
|
258
|
+
<m.div
|
|
263
259
|
layout
|
|
264
260
|
layoutRoot
|
|
265
261
|
drag
|
|
@@ -292,13 +288,12 @@ export function ElementDetailsCard({
|
|
|
292
288
|
},
|
|
293
289
|
}}
|
|
294
290
|
style={{
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
height: height as any,
|
|
291
|
+
width,
|
|
292
|
+
height,
|
|
298
293
|
}}>
|
|
299
294
|
<div className={styles.cardHeader} onPointerDown={e => controls.start(e)}>
|
|
300
|
-
<
|
|
301
|
-
<
|
|
295
|
+
<HStack alignItems="start" justify="space-between" gap={'sm'} mb={'sm'} flexWrap="nowrap">
|
|
296
|
+
<HStack alignItems="start" gap={'sm'} style={{ cursor: 'default' }} flexWrap="nowrap">
|
|
302
297
|
{elementIcon}
|
|
303
298
|
<div>
|
|
304
299
|
<Text
|
|
@@ -312,15 +307,15 @@ export function ElementDetailsCard({
|
|
|
312
307
|
</Text>
|
|
313
308
|
)}
|
|
314
309
|
</div>
|
|
315
|
-
</
|
|
310
|
+
</HStack>
|
|
316
311
|
<CloseButton
|
|
317
312
|
size={'lg'}
|
|
318
313
|
onClick={e => {
|
|
319
314
|
e.stopPropagation()
|
|
320
315
|
close()
|
|
321
316
|
}} />
|
|
322
|
-
</
|
|
323
|
-
<
|
|
317
|
+
</HStack>
|
|
318
|
+
<HStack alignItems="baseline" gap={'sm'} flexWrap="nowrap">
|
|
324
319
|
<div>
|
|
325
320
|
<SmallLabel>kind</SmallLabel>
|
|
326
321
|
<Badge
|
|
@@ -403,7 +398,7 @@ export function ElementDetailsCard({
|
|
|
403
398
|
</Tooltip>
|
|
404
399
|
)}
|
|
405
400
|
</ActionIconGroup>
|
|
406
|
-
</
|
|
401
|
+
</HStack>
|
|
407
402
|
</div>
|
|
408
403
|
<Tabs
|
|
409
404
|
value={activeTab}
|
|
@@ -426,6 +421,12 @@ export function ElementDetailsCard({
|
|
|
426
421
|
<TabsPanel value="Properties">
|
|
427
422
|
<ScrollArea scrollbars="y" type="scroll" offsetScrollbars>
|
|
428
423
|
<Box className={styles.propertiesGrid} pt={'xs'}>
|
|
424
|
+
{elementModel.hasSummary && (
|
|
425
|
+
<>
|
|
426
|
+
<PropertyLabel>summary</PropertyLabel>
|
|
427
|
+
<MarkdownBlock value={elementModel.summary} />
|
|
428
|
+
</>
|
|
429
|
+
)}
|
|
429
430
|
<>
|
|
430
431
|
<PropertyLabel>description</PropertyLabel>
|
|
431
432
|
<MarkdownBlock
|
|
@@ -517,7 +518,7 @@ export function ElementDetailsCard({
|
|
|
517
518
|
dragMomentum={false}
|
|
518
519
|
onDrag={handleDrag}
|
|
519
520
|
dragConstraints={{ top: 0, left: 0, right: 0, bottom: 0 }} />
|
|
520
|
-
</
|
|
521
|
+
</m.div>
|
|
521
522
|
</RemoveScroll>
|
|
522
523
|
</m.dialog>
|
|
523
524
|
)
|
|
@@ -609,12 +610,10 @@ function ElementMetata({
|
|
|
609
610
|
{entries(metadata).map(([key, value]) => (
|
|
610
611
|
<div
|
|
611
612
|
key={key}
|
|
612
|
-
|
|
613
|
-
'
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
}),
|
|
617
|
-
)}
|
|
613
|
+
style={{
|
|
614
|
+
display: 'contents',
|
|
615
|
+
}}
|
|
616
|
+
className={'group'}
|
|
618
617
|
>
|
|
619
618
|
<div
|
|
620
619
|
className={css({
|
|
@@ -651,7 +650,7 @@ function ElementMetata({
|
|
|
651
650
|
fontSize: 'sm',
|
|
652
651
|
padding: 'xxs',
|
|
653
652
|
whiteSpace: 'pre',
|
|
654
|
-
fontFamily: '
|
|
653
|
+
fontFamily: 'mono',
|
|
655
654
|
userSelect: 'all',
|
|
656
655
|
})}>
|
|
657
656
|
{value}
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
sortBy,
|
|
35
35
|
tap,
|
|
36
36
|
} from 'remeda'
|
|
37
|
+
import type { Except } from 'type-fest'
|
|
37
38
|
import type { RelationshipDetailsTypes } from './_types'
|
|
38
39
|
import type { RelationshipDetailsViewData } from './compute'
|
|
39
40
|
|
|
@@ -218,14 +219,14 @@ export type LayoutResult = {
|
|
|
218
219
|
}
|
|
219
220
|
|
|
220
221
|
export namespace LayoutResult {
|
|
221
|
-
export type Node =
|
|
222
|
+
export type Node = Except<DiagramNode, 'modelRef' | 'description' | 'deploymentRef' | 'inEdges' | 'outEdges'> & {
|
|
222
223
|
description: RichTextOrEmpty
|
|
223
224
|
modelRef: Fqn
|
|
224
225
|
column: RelationshipDetailsTypes.Column
|
|
225
226
|
ports: RelationshipDetailsTypes.Ports
|
|
226
227
|
// existsInCurrentView: boolean
|
|
227
228
|
}
|
|
228
|
-
export type Edge =
|
|
229
|
+
export type Edge = Except<DiagramEdge, 'relations' | 'description'> & {
|
|
229
230
|
relationId: RelationId
|
|
230
231
|
sourceHandle: string
|
|
231
232
|
targetHandle: string
|
|
@@ -402,7 +403,7 @@ export function layoutRelationshipDetails(
|
|
|
402
403
|
y: position.y,
|
|
403
404
|
position: [position.x, position.y],
|
|
404
405
|
title: element.title,
|
|
405
|
-
description:
|
|
406
|
+
description: element.summary,
|
|
406
407
|
technology: element.technology,
|
|
407
408
|
tags: [...element.tags],
|
|
408
409
|
links: null,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { cx } from '@likec4/styles/css'
|
|
2
2
|
import { ActionIcon, Group } from '@mantine/core'
|
|
3
3
|
import { useCallbackRef, useStateHistory } from '@mantine/hooks'
|
|
4
|
+
import { useRafEffect } from '@react-hookz/web'
|
|
4
5
|
import { IconChevronLeft, IconChevronRight, IconX } from '@tabler/icons-react'
|
|
5
6
|
import { Panel, ReactFlowProvider, useReactFlow, useStoreApi } from '@xyflow/react'
|
|
6
7
|
import { shallowEqual } from 'fast-equals'
|
|
@@ -183,7 +184,7 @@ const RelationshipsBrowserInner = memo(() => {
|
|
|
183
184
|
}
|
|
184
185
|
}, [historySubjectId, browser])
|
|
185
186
|
|
|
186
|
-
|
|
187
|
+
useRafEffect(() => {
|
|
187
188
|
browser.updateView(layouted)
|
|
188
189
|
}, [layouted, browser])
|
|
189
190
|
|
|
@@ -518,7 +518,7 @@ export function layoutRelationshipsView(
|
|
|
518
518
|
y: position.y,
|
|
519
519
|
position: [position.x, position.y],
|
|
520
520
|
title: element.title,
|
|
521
|
-
description:
|
|
521
|
+
description: element.summary,
|
|
522
522
|
technology: element.technology,
|
|
523
523
|
tags: [...element.tags],
|
|
524
524
|
links: null,
|
|
@@ -279,7 +279,7 @@ function ElementTreeNode(
|
|
|
279
279
|
</Tooltip>
|
|
280
280
|
</Group>
|
|
281
281
|
<Highlight component="div" highlight={searchTerms} className={btn.description!} lineClamp={1}>
|
|
282
|
-
{element.
|
|
282
|
+
{element.summary.text || 'No description'}
|
|
283
283
|
</Highlight>
|
|
284
284
|
</Box>
|
|
285
285
|
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import type { DiagramView, DynamicViewDisplayVariant, WhereOperator } from '@likec4/core/types'
|
|
2
|
-
import { useCustomCompareEffect } from '@react-hookz/web'
|
|
2
|
+
import { useCustomCompareEffect, useRafEffect } 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,
|
|
6
|
+
import { type PropsWithChildren, 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'
|
|
10
10
|
import { useOnDiagramEvent } from '../custom'
|
|
11
11
|
import { DiagramActorContextProvider } from '../hooks/safeContext'
|
|
12
|
-
import { useCurrentViewId } from '../hooks/useCurrentViewId'
|
|
13
12
|
import type { ViewPadding } from '../LikeC4Diagram.props'
|
|
14
13
|
import { convertToXYFlow } from '../likec4diagram/convert-to-xyflow'
|
|
15
14
|
import type { Types } from '../likec4diagram/types'
|
|
@@ -19,16 +18,6 @@ import { type DiagramMachine, diagramMachine } from './diagram-machine'
|
|
|
19
18
|
import { syncManualLayoutActorLogic } from './syncManualLayoutActor'
|
|
20
19
|
import type { DiagramActorRef, DiagramActorSnapshot } from './types'
|
|
21
20
|
|
|
22
|
-
const selectToggledFeatures = (state: DiagramActorSnapshot) => {
|
|
23
|
-
if (state.context.features.enableReadOnly || state.context.activeWalkthrough) {
|
|
24
|
-
return {
|
|
25
|
-
...state.context.toggledFeatures,
|
|
26
|
-
enableReadOnly: true,
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
return state.context.toggledFeatures
|
|
30
|
-
}
|
|
31
|
-
|
|
32
21
|
const selectDynamicViewVariant = (state: DiagramActorSnapshot) => {
|
|
33
22
|
return state.context.dynamicViewVariant
|
|
34
23
|
}
|
|
@@ -111,36 +100,49 @@ export function DiagramActorProvider({
|
|
|
111
100
|
[view, where, nodesSelectable, dynamicViewVariant],
|
|
112
101
|
)
|
|
113
102
|
|
|
114
|
-
|
|
103
|
+
useRafEffect(() => {
|
|
115
104
|
actorRef.send({
|
|
116
105
|
type: 'update.view',
|
|
117
106
|
...update,
|
|
118
107
|
})
|
|
119
108
|
}, [actorRef, update])
|
|
120
109
|
|
|
121
|
-
const toggledFeatures = useSelector(actorRef, selectToggledFeatures, shallowEqual)
|
|
122
|
-
|
|
123
110
|
return (
|
|
124
111
|
<DiagramActorContextProvider value={actorRef}>
|
|
125
|
-
<
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
</ErrorBoundary>
|
|
131
|
-
</DiagramFeatures>
|
|
112
|
+
<ErrorBoundary>
|
|
113
|
+
<CurrentViewModelProvider actorRef={actorRef}>
|
|
114
|
+
{children}
|
|
115
|
+
</CurrentViewModelProvider>
|
|
116
|
+
</ErrorBoundary>
|
|
132
117
|
<DiagramActorEventListener actorRef={actorRef} />
|
|
133
118
|
</DiagramActorContextProvider>
|
|
134
119
|
)
|
|
135
120
|
}
|
|
136
121
|
|
|
137
|
-
|
|
138
|
-
|
|
122
|
+
const selectViewIdAndToggledFeatures = (state: DiagramActorSnapshot) => {
|
|
123
|
+
if (state.context.features.enableReadOnly || state.context.activeWalkthrough) {
|
|
124
|
+
return {
|
|
125
|
+
viewId: state.context.view.id,
|
|
126
|
+
toggledFeatures: {
|
|
127
|
+
...state.context.toggledFeatures,
|
|
128
|
+
enableReadOnly: true,
|
|
129
|
+
},
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
viewId: state.context.view.id,
|
|
134
|
+
toggledFeatures: state.context.toggledFeatures,
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function CurrentViewModelProvider({ children, actorRef }: PropsWithChildren<{ actorRef: DiagramActorRef }>) {
|
|
138
|
+
const { viewId, toggledFeatures } = useSelector(actorRef, selectViewIdAndToggledFeatures, deepEqual)
|
|
139
139
|
const likec4model = useLikeC4Model()
|
|
140
140
|
const viewmodel = likec4model.findView(viewId)
|
|
141
141
|
return (
|
|
142
142
|
<CurrentViewModelContext.Provider value={viewmodel}>
|
|
143
|
-
{
|
|
143
|
+
<DiagramFeatures overrides={toggledFeatures}>
|
|
144
|
+
{children}
|
|
145
|
+
</DiagramFeatures>
|
|
144
146
|
</CurrentViewModelContext.Provider>
|
|
145
147
|
)
|
|
146
148
|
}
|
|
@@ -152,25 +154,7 @@ function DiagramActorEventListener({ actorRef }: { actorRef: DiagramActorRef })
|
|
|
152
154
|
} = useDiagramEventHandlers()
|
|
153
155
|
|
|
154
156
|
useOnDiagramEvent('openSource', ({ params }) => onOpenSource?.(params))
|
|
155
|
-
|
|
156
|
-
// onNavigateTo we defer the callback for better responsiveness
|
|
157
|
-
// (allowing animation to finish)
|
|
158
|
-
useEffect(() => {
|
|
159
|
-
if (!onNavigateTo) return
|
|
160
|
-
let frame: number
|
|
161
|
-
|
|
162
|
-
const subscription = actorRef.on('navigateTo', ({ viewId }) => {
|
|
163
|
-
cancelAnimationFrame(frame)
|
|
164
|
-
// Slightly defer callback for better responsiveness
|
|
165
|
-
frame = requestAnimationFrame(() => {
|
|
166
|
-
onNavigateTo(viewId)
|
|
167
|
-
})
|
|
168
|
-
})
|
|
169
|
-
return () => {
|
|
170
|
-
cancelAnimationFrame(frame)
|
|
171
|
-
subscription.unsubscribe()
|
|
172
|
-
}
|
|
173
|
-
}, [actorRef, onNavigateTo])
|
|
157
|
+
useOnDiagramEvent('navigateTo', ({ viewId }) => onNavigateTo?.(viewId))
|
|
174
158
|
|
|
175
159
|
return null
|
|
176
160
|
}
|