@likec4/diagram 1.21.0 → 1.22.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/dist/LikeC4Diagram.js +9 -13
- package/dist/base/BaseXYFlow.js +0 -1
- package/dist/base/index.d.ts +0 -1
- package/dist/base/primitives/compound/CompoundNodeContainer.js +2 -2
- package/dist/base/primitives/edge/EdgeLabel.js +2 -2
- package/dist/base/primitives/element/ElementNodeContainer.d.ts +6 -1
- package/dist/base/primitives/element/ElementNodeContainer.js +31 -13
- package/dist/base/primitives/element/ElementTitle.js +7 -3
- package/dist/base/primitives/element/styles.css.js +1 -1
- package/dist/{base → components}/Link.css.js +3 -3
- package/dist/components/SearchControl.css.d.ts +2 -0
- package/dist/components/SearchControl.css.js +7 -0
- package/dist/components/SearchControl.d.ts +5 -0
- package/dist/components/SearchControl.js +17 -0
- package/dist/context/IconRenderer.d.ts +10 -0
- package/dist/context/IconRenderer.js +34 -0
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/useDiagram.d.ts +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/likec4diagram/DiagramUI.js +1 -4
- package/dist/likec4diagram/XYFlow.d.ts +6 -1
- package/dist/likec4diagram/XYFlow.js +28 -29
- package/dist/likec4diagram/custom/edges/RelationshipsDropdownMenu.js +3 -1
- package/dist/likec4diagram/state/actorContext.d.ts +16 -16
- package/dist/likec4diagram/state/assign.js +1 -1
- package/dist/likec4diagram/state/machine.d.ts +7 -7
- package/dist/likec4diagram/state/machine.js +10 -7
- package/dist/likec4diagram/ui/controls/Controls.js +63 -48
- package/dist/likec4diagram/ui/controls/NavigationButtons.js +44 -69
- package/dist/likec4diagram/ui/controls/_shared.js +1 -1
- package/dist/likec4diagram/ui/diagram-title/DiagramTitlePanel.js +5 -4
- package/dist/likec4diagram/ui/index.d.ts +2 -0
- package/dist/likec4diagram/ui/search/ElementsColumn.css.d.ts +15 -0
- package/dist/likec4diagram/ui/search/ElementsColumn.css.js +30 -0
- package/dist/likec4diagram/ui/search/ElementsColumn.d.ts +1 -0
- package/dist/likec4diagram/ui/search/ElementsColumn.js +243 -0
- package/dist/likec4diagram/ui/search/LikeC4Search.css.d.ts +8 -0
- package/dist/likec4diagram/ui/search/LikeC4Search.css.js +20 -0
- package/dist/likec4diagram/ui/search/LikeC4Search.d.ts +1 -0
- package/dist/likec4diagram/ui/search/LikeC4Search.js +265 -0
- package/dist/likec4diagram/ui/search/SearchInput.d.ts +1 -0
- package/dist/likec4diagram/ui/search/SearchInput.js +196 -0
- package/dist/likec4diagram/ui/search/ViewsColum.d.ts +9 -0
- package/dist/likec4diagram/ui/search/ViewsColum.js +130 -0
- package/dist/likec4diagram/ui/search/ViewsColumn.css.d.ts +5 -0
- package/dist/likec4diagram/ui/search/ViewsColumn.css.js +12 -0
- package/dist/likec4diagram/ui/search/_shared.css.d.ts +16 -0
- package/dist/likec4diagram/ui/search/_shared.css.js +5 -0
- package/dist/likec4diagram/ui/search/state.d.ts +19 -0
- package/dist/likec4diagram/ui/search/state.js +72 -0
- package/dist/likec4diagram/ui/search/utils.d.ts +3 -0
- package/dist/likec4diagram/ui/search/utils.js +23 -0
- package/dist/likec4diagram/useLayoutConstraints.js +4 -5
- package/dist/likec4model/useLikeC4ElementsTree.d.ts +1 -0
- package/dist/likec4model/useLikeC4ElementsTree.js +1 -0
- package/dist/overlays/Overlays.js +10 -10
- package/dist/overlays/element-details/ElementDetailsCard.js +20 -13
- package/dist/overlays/element-details/TabPanelDeployments.js +4 -2
- package/dist/overlays/overlay/Overlay.d.ts +6 -2
- package/dist/overlays/overlay/Overlay.js +18 -29
- package/dist/overlays/relationship-details/SelectEdge.js +1 -3
- package/dist/overlays/relationships-browser/RelationshipsBrowser.js +6 -5
- package/dist/overlays/relationships-browser/SelectElement.js +10 -6
- package/dist/overlays/relationships-browser/actor.d.ts +2 -2
- package/dist/overlays/relationships-browser/actor.js +8 -8
- package/dist/overlays/relationships-browser/custom/nodeTypes.js +2 -2
- package/dist/style.css +1 -1
- package/package.json +15 -14
- package/src/LikeC4Diagram.tsx +0 -1
- package/src/base/BaseXYFlow.tsx +0 -1
- package/src/base/index.ts +0 -2
- package/src/base/primitives/element/ElementNodeContainer.css.ts +4 -7
- package/src/base/primitives/element/ElementNodeContainer.tsx +36 -16
- package/src/base/primitives/element/ElementTitle.css.ts +12 -9
- package/src/base/primitives/element/ElementTitle.tsx +6 -2
- package/src/base/primitives/element/styles.css.ts +18 -40
- package/src/{base → components}/Link.css.ts +3 -3
- package/src/components/SearchControl.css.ts +69 -0
- package/src/components/SearchControl.tsx +33 -0
- package/src/context/IconRenderer.tsx +54 -1
- package/src/hooks/index.ts +0 -1
- package/src/index.ts +15 -1
- package/src/likec4diagram/DiagramUI.tsx +1 -8
- package/src/likec4diagram/XYFlow.tsx +30 -30
- package/src/likec4diagram/custom/edges/RelationshipEdge.tsx +0 -1
- package/src/likec4diagram/custom/edges/RelationshipsDropdownMenu.css.ts +1 -0
- package/src/likec4diagram/custom/edges/RelationshipsDropdownMenu.tsx +3 -1
- package/src/likec4diagram/state/assign.ts +1 -1
- package/src/likec4diagram/state/machine.ts +12 -10
- package/src/likec4diagram/ui/controls/Controls.tsx +35 -25
- package/src/likec4diagram/ui/controls/NavigationButtons.tsx +36 -58
- package/src/likec4diagram/ui/controls/styles.css.ts +3 -1
- package/src/likec4diagram/ui/diagram-title/DiagramTitlePanel.tsx +111 -108
- package/src/likec4diagram/ui/index.ts +2 -0
- package/src/likec4diagram/ui/notation/NotationPanel.tsx +2 -3
- package/src/likec4diagram/ui/search/ElementsColumn.css.ts +119 -0
- package/src/likec4diagram/ui/search/ElementsColumn.tsx +291 -0
- package/src/likec4diagram/ui/search/LikeC4Search.css.ts +117 -0
- package/src/likec4diagram/ui/search/LikeC4Search.tsx +312 -0
- package/src/likec4diagram/ui/search/SearchInput.tsx +235 -0
- package/src/likec4diagram/ui/search/ViewsColum.tsx +158 -0
- package/src/likec4diagram/ui/search/ViewsColumn.css.ts +37 -0
- package/src/likec4diagram/ui/search/_shared.css.ts +104 -0
- package/src/likec4diagram/ui/search/state.ts +76 -0
- package/src/likec4diagram/ui/search/utils.ts +20 -0
- package/src/likec4diagram/useLayoutConstraints.ts +4 -5
- package/src/likec4model/useLikeC4ElementsTree.ts +4 -4
- package/src/overlays/Overlays.tsx +32 -26
- package/src/overlays/element-details/ElementDetailsCard.css.ts +4 -4
- package/src/overlays/element-details/ElementDetailsCard.tsx +246 -244
- package/src/overlays/element-details/TabPanelDeployments.tsx +4 -4
- package/src/overlays/overlay/Overlay.css.ts +10 -9
- package/src/overlays/overlay/Overlay.tsx +38 -26
- package/src/overlays/relationship-details/SelectEdge.css.ts +1 -0
- package/src/overlays/relationship-details/SelectEdge.tsx +2 -4
- package/src/overlays/relationships-browser/RelationshipsBrowser.tsx +10 -5
- package/src/overlays/relationships-browser/SelectElement.tsx +88 -82
- package/src/overlays/relationships-browser/actor.ts +10 -10
- package/src/overlays/relationships-browser/custom/nodeTypes.tsx +2 -2
- package/dist/LikeC4Search.css.d.ts +0 -1
- package/dist/LikeC4Search.css.js +0 -5
- package/dist/LikeC4Search.d.ts +0 -2
- package/dist/LikeC4Search.js +0 -88
- package/src/LikeC4Search.css.ts +0 -12
- package/src/LikeC4Search.tsx +0 -91
- /package/dist/{base → components}/Link.css.d.ts +0 -0
- /package/dist/{base → components}/Link.d.ts +0 -0
- /package/dist/{base → components}/Link.js +0 -0
- /package/src/{base → components}/Link.tsx +0 -0
|
@@ -37,10 +37,7 @@ export const description = style({
|
|
|
37
37
|
textOverflow: 'ellipsis',
|
|
38
38
|
overflow: 'hidden',
|
|
39
39
|
selectors: {
|
|
40
|
-
[`:where(
|
|
41
|
-
textWrap: 'wrap',
|
|
42
|
-
},
|
|
43
|
-
[`:where([data-likec4-shape-size="xs"], [data-likec4-shape-size="sm"]) &`]: {
|
|
40
|
+
[`:where([data-likec4-shape-size="xs"]) &`]: {
|
|
44
41
|
display: 'none',
|
|
45
42
|
},
|
|
46
43
|
},
|
|
@@ -71,17 +68,22 @@ export const technology = style({
|
|
|
71
68
|
export const elementDataContainer = style({
|
|
72
69
|
flex: '1',
|
|
73
70
|
height: 'fit-content',
|
|
71
|
+
width: 'fit-content',
|
|
72
|
+
margin: '0 auto',
|
|
74
73
|
display: 'flex',
|
|
75
74
|
alignItems: 'center',
|
|
76
75
|
justifyContent: 'center',
|
|
77
76
|
flexDirection: 'row',
|
|
78
|
-
|
|
77
|
+
paddingTop: paddingSize,
|
|
78
|
+
paddingBottom: paddingSize,
|
|
79
|
+
paddingLeft: calc(paddingSize).add('8px').toString(),
|
|
80
|
+
paddingRight: calc(paddingSize).add('8px').toString(),
|
|
79
81
|
overflow: 'hidden',
|
|
80
82
|
gap: rem(12),
|
|
81
83
|
selectors: {
|
|
82
84
|
':where([data-likec4-shape="queue"], [data-likec4-shape="mobile"]) &': {
|
|
83
|
-
paddingLeft:
|
|
84
|
-
paddingRight:
|
|
85
|
+
paddingLeft: 46,
|
|
86
|
+
paddingRight: 16,
|
|
85
87
|
},
|
|
86
88
|
':where([data-likec4-shape="cylinder"], [data-likec4-shape="storage"]) &': {
|
|
87
89
|
paddingTop: 30,
|
|
@@ -98,7 +100,8 @@ globalStyle(`:where([data-likec4-shape-size="lg"], [data-likec4-shape-size="xl"]
|
|
|
98
100
|
|
|
99
101
|
export const elementTextData = style({
|
|
100
102
|
height: 'fit-content',
|
|
101
|
-
width: '
|
|
103
|
+
width: 'fit-content',
|
|
104
|
+
flex: '0 1 auto',
|
|
102
105
|
display: 'flex',
|
|
103
106
|
flexDirection: 'column',
|
|
104
107
|
alignItems: 'stretch',
|
|
@@ -114,7 +117,7 @@ export const elementTextData = style({
|
|
|
114
117
|
gap: rem(6),
|
|
115
118
|
},
|
|
116
119
|
[`:where(${hasIcon}) &`]: {
|
|
117
|
-
minWidth: `calc(
|
|
120
|
+
minWidth: `calc(50% + ${iconSize})`,
|
|
118
121
|
alignItems: 'flex-start',
|
|
119
122
|
'vars': {
|
|
120
123
|
[textAlign]: 'left',
|
|
@@ -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
|
)}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { defaultTheme } from '@likec4/core'
|
|
2
2
|
import { rem } from '@mantine/core'
|
|
3
|
-
import { createVar, globalStyle } from '@vanilla-extract/css'
|
|
3
|
+
import { createGlobalVar, createVar, globalStyle } from '@vanilla-extract/css'
|
|
4
4
|
import { container } from './ElementNodeContainer.css'
|
|
5
5
|
|
|
6
6
|
export const textSize = createVar('text-size')
|
|
7
7
|
export const paddingSize = createVar('padding-size')
|
|
8
|
-
export const iconSize =
|
|
8
|
+
export const iconSize = createGlobalVar('likec4-icon-size')
|
|
9
9
|
|
|
10
10
|
globalStyle(`${container}`, {
|
|
11
11
|
vars: {
|
|
@@ -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"]
|
|
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
|
-
[
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { style } from '@vanilla-extract/css'
|
|
2
2
|
import { mantine } from '../theme-vars'
|
|
3
|
-
import { easings, whereDark } from '../theme-vars.css'
|
|
3
|
+
import { easings, transitions, whereDark } from '../theme-vars.css'
|
|
4
4
|
|
|
5
5
|
export const elementLink = style({
|
|
6
6
|
display: 'flex',
|
|
@@ -8,7 +8,7 @@ export const elementLink = style({
|
|
|
8
8
|
alignItems: 'center',
|
|
9
9
|
gap: 3,
|
|
10
10
|
justifyContent: 'stretch',
|
|
11
|
-
|
|
11
|
+
transition: transitions.fast,
|
|
12
12
|
border: `1px dashed ${mantine.colors.defaultBorder}`,
|
|
13
13
|
borderRadius: mantine.radius.sm,
|
|
14
14
|
minHeight: 30,
|
|
@@ -38,7 +38,7 @@ export const linkIcon = style({
|
|
|
38
38
|
|
|
39
39
|
export const linkTitleBox = style({
|
|
40
40
|
flex: '1 1 100%',
|
|
41
|
-
transition: `transform
|
|
41
|
+
transition: `transform 100ms ${easings.inOut}`,
|
|
42
42
|
selectors: {
|
|
43
43
|
[`${elementLink}:hover &`]: {
|
|
44
44
|
transitionTimingFunction: easings.out,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { createVar, fallbackVar, globalStyle, style } from '@vanilla-extract/css'
|
|
2
|
+
import { mantine, transitions, vars, whereDark, whereLight } from '../theme-vars'
|
|
3
|
+
|
|
4
|
+
const transparent = createVar('transparent')
|
|
5
|
+
const bgColor = createVar('bgcolor')
|
|
6
|
+
export const root = style({
|
|
7
|
+
height: '32px',
|
|
8
|
+
paddingLeft: mantine.spacing.sm,
|
|
9
|
+
paddingRight: '4px',
|
|
10
|
+
borderRadius: mantine.radius.sm,
|
|
11
|
+
color: mantine.colors.placeholder,
|
|
12
|
+
boxShadow: mantine.shadows.xs,
|
|
13
|
+
border: '1px solid',
|
|
14
|
+
cursor: 'pointer',
|
|
15
|
+
transition: transitions.fast,
|
|
16
|
+
WebkitBackdropFilter: fallbackVar(vars.safariAnimationHook, 'blur(8px)'),
|
|
17
|
+
backdropFilter: fallbackVar(vars.safariAnimationHook, 'blur(8px)'),
|
|
18
|
+
backgroundColor: `color-mix(in srgb, ${bgColor}, transparent ${transparent})`,
|
|
19
|
+
vars: {
|
|
20
|
+
[transparent]: '20%',
|
|
21
|
+
[bgColor]: mantine.colors.default,
|
|
22
|
+
},
|
|
23
|
+
selectors: {
|
|
24
|
+
[`${whereLight} &`]: {
|
|
25
|
+
borderColor: mantine.colors.gray[4],
|
|
26
|
+
vars: {
|
|
27
|
+
[bgColor]: mantine.colors.white,
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
[`${whereDark} &`]: {
|
|
31
|
+
borderColor: mantine.colors.dark[4],
|
|
32
|
+
vars: {
|
|
33
|
+
[bgColor]: mantine.colors.dark[6],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
':hover': {
|
|
38
|
+
borderColor: mantine.colors.defaultBorder,
|
|
39
|
+
boxShadow: mantine.shadows.sm,
|
|
40
|
+
vars: {
|
|
41
|
+
[transparent]: '10%',
|
|
42
|
+
[bgColor]: mantine.colors.defaultHover,
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
globalStyle(`${root} .tabler-icon`, {
|
|
47
|
+
color: mantine.colors.text,
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
export const shortcut = style({
|
|
51
|
+
fontSize: '11px',
|
|
52
|
+
lineHeight: 1,
|
|
53
|
+
padding: '4px 7px',
|
|
54
|
+
borderRadius: mantine.radius.sm,
|
|
55
|
+
border: '1px solid',
|
|
56
|
+
fontWeight: 'bold',
|
|
57
|
+
selectors: {
|
|
58
|
+
[`${whereLight} &`]: {
|
|
59
|
+
color: mantine.colors.gray[7],
|
|
60
|
+
borderColor: mantine.colors.gray[2],
|
|
61
|
+
backgroundColor: `color-mix(in srgb, ${mantine.colors.gray[2]}, transparent 20%)`,
|
|
62
|
+
},
|
|
63
|
+
[`${whereDark} &`]: {
|
|
64
|
+
color: mantine.colors.dark[0],
|
|
65
|
+
borderColor: mantine.colors.dark[7],
|
|
66
|
+
backgroundColor: mantine.colors.dark[8],
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type BoxProps,
|
|
3
|
+
type ElementProps,
|
|
4
|
+
type UnstyledButtonProps,
|
|
5
|
+
Box,
|
|
6
|
+
Group,
|
|
7
|
+
rem,
|
|
8
|
+
Text,
|
|
9
|
+
UnstyledButton,
|
|
10
|
+
} from '@mantine/core'
|
|
11
|
+
import { IconSearch } from '@tabler/icons-react'
|
|
12
|
+
import { isMacOs } from '@xyflow/system'
|
|
13
|
+
import cx from 'clsx'
|
|
14
|
+
import * as classes from './SearchControl.css'
|
|
15
|
+
|
|
16
|
+
interface SearchControlProps extends UnstyledButtonProps, ElementProps<'button'> {}
|
|
17
|
+
|
|
18
|
+
export function SearchControl({ className, ...others }: SearchControlProps) {
|
|
19
|
+
const isMac = isMacOs()
|
|
20
|
+
return (
|
|
21
|
+
<UnstyledButton {...others} className={cx(classes.root, className)}>
|
|
22
|
+
<Group gap="xs">
|
|
23
|
+
<IconSearch style={{ width: rem(15), height: rem(15) }} stroke={2} />
|
|
24
|
+
<Text fz="sm" fw="500" pr={50}>
|
|
25
|
+
Search
|
|
26
|
+
</Text>
|
|
27
|
+
<Text fw={700} className={classes.shortcut}>
|
|
28
|
+
{isMac ? '⌘ + K' : 'Ctrl + K'}
|
|
29
|
+
</Text>
|
|
30
|
+
</Group>
|
|
31
|
+
</UnstyledButton>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
import type { ElementShape } from '@likec4/core'
|
|
2
|
+
import {
|
|
3
|
+
type Icon,
|
|
4
|
+
type IconProps,
|
|
5
|
+
IconBrowser,
|
|
6
|
+
IconCylinder,
|
|
7
|
+
IconDeviceMobile,
|
|
8
|
+
IconRectangularPrism,
|
|
9
|
+
IconReorder,
|
|
10
|
+
IconUser,
|
|
11
|
+
} from '@tabler/icons-react'
|
|
1
12
|
import clsx from 'clsx'
|
|
2
|
-
import { type ReactNode, createContext, useContext } from 'react'
|
|
13
|
+
import { type ForwardRefExoticComponent, type ReactNode, type RefAttributes, createContext, useContext } from 'react'
|
|
3
14
|
import type { ElementIconRenderer } from '../LikeC4Diagram.props'
|
|
4
15
|
|
|
5
16
|
const IconRendererContext = createContext<ElementIconRenderer | null>(null)
|
|
@@ -43,3 +54,45 @@ export function IconRenderer({
|
|
|
43
54
|
</div>
|
|
44
55
|
)
|
|
45
56
|
}
|
|
57
|
+
|
|
58
|
+
const ShapeIcons = {
|
|
59
|
+
browser: IconBrowser,
|
|
60
|
+
cylinder: IconCylinder,
|
|
61
|
+
mobile: IconDeviceMobile,
|
|
62
|
+
person: IconUser,
|
|
63
|
+
queue: IconReorder,
|
|
64
|
+
rectangle: IconRectangularPrism,
|
|
65
|
+
storage: IconCylinder,
|
|
66
|
+
} satisfies Record<ElementShape, ForwardRefExoticComponent<IconProps & RefAttributes<Icon>>>
|
|
67
|
+
|
|
68
|
+
export function IconOrShapeRenderer({
|
|
69
|
+
element,
|
|
70
|
+
className,
|
|
71
|
+
}: {
|
|
72
|
+
element: {
|
|
73
|
+
id: string
|
|
74
|
+
title: string
|
|
75
|
+
shape: ElementShape
|
|
76
|
+
icon?: string | null | undefined
|
|
77
|
+
}
|
|
78
|
+
className: string
|
|
79
|
+
}) {
|
|
80
|
+
const icon = IconRenderer({
|
|
81
|
+
element,
|
|
82
|
+
className,
|
|
83
|
+
})
|
|
84
|
+
if (icon) {
|
|
85
|
+
return icon
|
|
86
|
+
}
|
|
87
|
+
const ShapeIcon = ShapeIcons[element.shape]
|
|
88
|
+
return (
|
|
89
|
+
<div
|
|
90
|
+
className={clsx(
|
|
91
|
+
className,
|
|
92
|
+
'likec4-shape-icon',
|
|
93
|
+
)}
|
|
94
|
+
>
|
|
95
|
+
<ShapeIcon />
|
|
96
|
+
</div>
|
|
97
|
+
)
|
|
98
|
+
}
|
package/src/hooks/index.ts
CHANGED
|
@@ -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
|
|
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,19 +1,12 @@
|
|
|
1
|
-
import { memo } from 'react'
|
|
2
1
|
import { IfEnabled } from '../context'
|
|
3
|
-
import { LikeC4Search } from '../LikeC4Search'
|
|
4
2
|
import { Overlays } from '../overlays/Overlays'
|
|
5
|
-
import { Controls, DiagramTitlePanel } from './ui'
|
|
6
|
-
import NotationPanel from './ui/notation'
|
|
7
|
-
import { DynamicViewWalkthrough } from './ui/walkthrough/DynamicViewWalkthrough'
|
|
3
|
+
import { Controls, DiagramTitlePanel, DynamicViewWalkthrough, NotationPanel } from './ui'
|
|
8
4
|
|
|
9
5
|
export function DiagramUI() {
|
|
10
6
|
return (
|
|
11
7
|
<>
|
|
12
8
|
<Controls />
|
|
13
9
|
<Overlays />
|
|
14
|
-
<IfEnabled feature="Search">
|
|
15
|
-
<LikeC4Search />
|
|
16
|
-
</IfEnabled>
|
|
17
10
|
<IfEnabled feature="ViewTitle">
|
|
18
11
|
<DiagramTitlePanel />
|
|
19
12
|
</IfEnabled>
|
|
@@ -2,6 +2,7 @@ import { type EdgeId, type NodeId, nonNullable } from '@likec4/core'
|
|
|
2
2
|
import { useCallbackRef } from '@mantine/hooks'
|
|
3
3
|
import clsx from 'clsx'
|
|
4
4
|
import { shallowEqual } from 'fast-equals'
|
|
5
|
+
import { memo } from 'react'
|
|
5
6
|
import type { EnforceOptional } from 'type-fest/source/enforce-optional'
|
|
6
7
|
import { BaseXYFlow } from '../base/BaseXYFlow'
|
|
7
8
|
import { useDiagramEventHandlers } from '../context'
|
|
@@ -9,6 +10,7 @@ import { useDiagram } from '../hooks/useDiagram'
|
|
|
9
10
|
import { useDiagramContext } from '../hooks/useDiagramContext'
|
|
10
11
|
import type { LikeC4DiagramProperties } from '../LikeC4Diagram.props'
|
|
11
12
|
import { edgeTypes, nodeTypes } from './custom'
|
|
13
|
+
import { DiagramUI } from './DiagramUI'
|
|
12
14
|
import type { DiagramContext } from './state/machine'
|
|
13
15
|
import type { Types } from './types'
|
|
14
16
|
import { useLayoutConstraints } from './useLayoutConstraints'
|
|
@@ -43,7 +45,7 @@ type Picked = EnforceOptional<
|
|
|
43
45
|
>
|
|
44
46
|
export type LikeC4DiagramXYFlowProps = Required<Picked>
|
|
45
47
|
|
|
46
|
-
export const LikeC4DiagramXYFlow = ({ background,
|
|
48
|
+
export const LikeC4DiagramXYFlow = memo<LikeC4DiagramXYFlowProps>(({ background, nodesDraggable, nodesSelectable }) => {
|
|
47
49
|
const diagram = useDiagram()
|
|
48
50
|
const {
|
|
49
51
|
initialized,
|
|
@@ -80,10 +82,10 @@ export const LikeC4DiagramXYFlow = ({ background, ...rest }: LikeC4DiagramXYFlow
|
|
|
80
82
|
nodeTypes={nodeTypes}
|
|
81
83
|
edgeTypes={edgeTypes}
|
|
82
84
|
onNodesChange={useCallbackRef((changes) => {
|
|
83
|
-
diagram.send({ type: 'xyflow.
|
|
85
|
+
diagram.send({ type: 'xyflow.applyNodeChanges', changes })
|
|
84
86
|
})}
|
|
85
87
|
onEdgesChange={useCallbackRef((changes) => {
|
|
86
|
-
diagram.send({ type: 'xyflow.
|
|
88
|
+
diagram.send({ type: 'xyflow.applyEdgeChanges', changes })
|
|
87
89
|
})}
|
|
88
90
|
background={initialized ? background : 'transparent'}
|
|
89
91
|
// Fitview is handled in onInit
|
|
@@ -105,6 +107,7 @@ export const LikeC4DiagramXYFlow = ({ background, ...rest }: LikeC4DiagramXYFlow
|
|
|
105
107
|
})}
|
|
106
108
|
onDoubleClick={useCallbackRef(e => {
|
|
107
109
|
e.stopPropagation()
|
|
110
|
+
e.preventDefault()
|
|
108
111
|
diagram.send({ type: 'xyflow.paneDblClick' })
|
|
109
112
|
onCanvasDblClick?.(e as any)
|
|
110
113
|
})}
|
|
@@ -115,34 +118,31 @@ export const LikeC4DiagramXYFlow = ({ background, ...rest }: LikeC4DiagramXYFlow
|
|
|
115
118
|
onInit={useCallbackRef((instance) => {
|
|
116
119
|
diagram.send({ type: 'xyflow.init', instance })
|
|
117
120
|
})}
|
|
118
|
-
{
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}}
|
|
136
|
-
{...onCanvasContextMenu && {
|
|
137
|
-
onPaneContextMenu: useCallbackRef((event) => {
|
|
138
|
-
onCanvasContextMenu(event as any)
|
|
139
|
-
}),
|
|
140
|
-
}}
|
|
121
|
+
onNodeContextMenu={useCallbackRef((event, node) => {
|
|
122
|
+
const diagramNode = nonNullable(
|
|
123
|
+
diagram.findDiagramNode(node.id as NodeId),
|
|
124
|
+
`diagramNode ${node.id} not found`,
|
|
125
|
+
)
|
|
126
|
+
onNodeContextMenu?.(diagramNode, event)
|
|
127
|
+
})}
|
|
128
|
+
onEdgeContextMenu={useCallbackRef((event, edge) => {
|
|
129
|
+
const diagramEdge = nonNullable(
|
|
130
|
+
diagram.findDiagramEdge(edge.id as EdgeId),
|
|
131
|
+
`diagramEdge ${edge.id} not found`,
|
|
132
|
+
)
|
|
133
|
+
onEdgeContextMenu?.(diagramEdge, event)
|
|
134
|
+
})}
|
|
135
|
+
onPaneContextMenu={useCallbackRef((event) => {
|
|
136
|
+
onCanvasContextMenu?.(event as any)
|
|
137
|
+
})}
|
|
141
138
|
{...enableFitView && {
|
|
142
139
|
onViewportResize,
|
|
143
140
|
}}
|
|
144
|
-
{
|
|
145
|
-
{
|
|
146
|
-
{...
|
|
141
|
+
nodesDraggable={nodesDraggable}
|
|
142
|
+
nodesSelectable={nodesSelectable}
|
|
143
|
+
{...(notReadOnly && nodesDraggable && layoutConstraints)}
|
|
144
|
+
{...props}>
|
|
145
|
+
<DiagramUI />
|
|
146
|
+
</BaseXYFlow>
|
|
147
147
|
)
|
|
148
|
-
}
|
|
148
|
+
}, shallowEqual)
|
|
@@ -27,7 +27,7 @@ import { IconArrowRight, IconFileSymlink, IconInfoCircle, IconZoomScan } from '@
|
|
|
27
27
|
import clsx from 'clsx'
|
|
28
28
|
import { type MouseEventHandler, type PropsWithChildren, forwardRef, Fragment, useCallback } from 'react'
|
|
29
29
|
import { filter, isTruthy, map, partition, pipe } from 'remeda'
|
|
30
|
-
import { Link } from '../../../
|
|
30
|
+
import { Link } from '../../../components/Link'
|
|
31
31
|
import { IfEnabled, useDiagramEventHandlers, useEnabledFeature } from '../../../context'
|
|
32
32
|
import { useMantinePortalProps } from '../../../hooks'
|
|
33
33
|
import { useDiagram } from '../../../hooks/useDiagram'
|
|
@@ -127,9 +127,11 @@ export function RelationshipsDropdownMenu({
|
|
|
127
127
|
closeOnClickOutside
|
|
128
128
|
clickOutsideEvents={['pointerdown', 'mousedown', 'click']}
|
|
129
129
|
closeOnEscape
|
|
130
|
+
keepMounted={false}
|
|
130
131
|
closeOnItemClick={false}
|
|
131
132
|
disabled={disabled}
|
|
132
133
|
position="bottom-start"
|
|
134
|
+
middlewares={{ size: { padding: 8 } }}
|
|
133
135
|
{...portalProps}
|
|
134
136
|
>
|
|
135
137
|
<MenuTarget>
|
|
@@ -321,7 +321,7 @@ export function resetEdgeControlPoints({ context }: ActionArg): Partial<DiagramC
|
|
|
321
321
|
}
|
|
322
322
|
|
|
323
323
|
// Edge is a loop
|
|
324
|
-
if (source
|
|
324
|
+
if (source === target) {
|
|
325
325
|
const loopSize = 80
|
|
326
326
|
const centerOfTopBoundary = new VectorImpl(0, source.height || 0)
|
|
327
327
|
.mul(-0.5)
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
type EdgeId,
|
|
5
5
|
type Fqn,
|
|
6
6
|
type NodeId,
|
|
7
|
-
type RelationId,
|
|
8
7
|
type StepEdgeId,
|
|
9
8
|
type ViewChange,
|
|
10
9
|
type ViewId,
|
|
@@ -136,8 +135,8 @@ export namespace DiagramContext {
|
|
|
136
135
|
export type Events =
|
|
137
136
|
| HotKeyEvent
|
|
138
137
|
| { type: 'xyflow.init'; instance: ReactFlowInstance<Types.Node, Types.Edge> }
|
|
139
|
-
| { type: 'xyflow.
|
|
140
|
-
| { type: 'xyflow.
|
|
138
|
+
| { type: 'xyflow.applyNodeChanges'; changes: NodeChange<Types.Node>[] }
|
|
139
|
+
| { type: 'xyflow.applyEdgeChanges'; changes: EdgeChange<Types.Edge>[] }
|
|
141
140
|
| { type: 'xyflow.viewportMoved'; viewport: Viewport; manually: boolean }
|
|
142
141
|
| { type: 'xyflow.nodeClick'; node: Types.Node }
|
|
143
142
|
| { type: 'xyflow.edgeClick'; edge: Types.Edge }
|
|
@@ -634,7 +633,7 @@ export const diagramMachine = setup({
|
|
|
634
633
|
pending: {
|
|
635
634
|
entry: enqueueActions(({ enqueue }) => {
|
|
636
635
|
enqueue.sendTo(c => c.context.syncLayoutActorRef, { type: 'stop' })
|
|
637
|
-
enqueue.stopChild('
|
|
636
|
+
enqueue.stopChild('syncLayout')
|
|
638
637
|
enqueue({
|
|
639
638
|
type: 'trigger:NavigateTo',
|
|
640
639
|
params: ({ context }) => ({
|
|
@@ -657,15 +656,16 @@ export const diagramMachine = setup({
|
|
|
657
656
|
},
|
|
658
657
|
},
|
|
659
658
|
})
|
|
659
|
+
enqueue.raise({ type: 'fitDiagram' }, { id: 'fitDiagram', delay: 80 })
|
|
660
660
|
} else {
|
|
661
661
|
enqueue({
|
|
662
662
|
type: 'xyflow:setViewportCenter',
|
|
663
663
|
params: getBBoxCenter(event.view.bounds),
|
|
664
664
|
})
|
|
665
|
+
enqueue.raise({ type: 'fitDiagram', duration: 200 }, { id: 'fitDiagram', delay: 25 })
|
|
665
666
|
}
|
|
666
667
|
enqueue.assign(updateNavigationHistory)
|
|
667
668
|
enqueue.assign(mergeXYNodesEdges)
|
|
668
|
-
enqueue.raise({ type: 'fitDiagram' }, { id: 'fitDiagram', delay: 75 })
|
|
669
669
|
}),
|
|
670
670
|
target: 'done',
|
|
671
671
|
},
|
|
@@ -765,12 +765,12 @@ export const diagramMachine = setup({
|
|
|
765
765
|
},
|
|
766
766
|
},
|
|
767
767
|
on: {
|
|
768
|
-
'xyflow.
|
|
768
|
+
'xyflow.applyNodeChanges': {
|
|
769
769
|
actions: assign({
|
|
770
770
|
xynodes: ({ context, event }) => applyNodeChanges(event.changes, context.xynodes),
|
|
771
771
|
}),
|
|
772
772
|
},
|
|
773
|
-
'xyflow.
|
|
773
|
+
'xyflow.applyEdgeChanges': {
|
|
774
774
|
actions: assign({
|
|
775
775
|
xyedges: ({ context, event }) => applyEdgeChanges(event.changes, context.xyedges),
|
|
776
776
|
}),
|
|
@@ -838,17 +838,19 @@ export const diagramMachine = setup({
|
|
|
838
838
|
},
|
|
839
839
|
},
|
|
840
840
|
})
|
|
841
|
+
enqueue.raise({ type: 'fitDiagram' }, { id: 'fitDiagram', delay: 80 })
|
|
841
842
|
} else {
|
|
842
843
|
enqueue({
|
|
843
844
|
type: 'xyflow:setViewportCenter',
|
|
844
845
|
params: getBBoxCenter(event.view.bounds),
|
|
845
846
|
})
|
|
847
|
+
enqueue.raise({ type: 'fitDiagram', duration: 200 }, { id: 'fitDiagram', delay: 25 })
|
|
846
848
|
}
|
|
847
849
|
} else {
|
|
848
850
|
enqueue.sendTo(c => c.context.syncLayoutActorRef, { type: 'synced' })
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
851
|
+
if (!context.viewportChangedManually) {
|
|
852
|
+
enqueue.raise({ type: 'fitDiagram' }, { id: 'fitDiagram', delay: 50 })
|
|
853
|
+
}
|
|
852
854
|
}
|
|
853
855
|
enqueue.assign(mergeXYNodesEdges)
|
|
854
856
|
enqueue.assign({
|