@likec4/diagram 1.0.0-next.2 → 1.0.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 (124) hide show
  1. package/dist/LikeC4Diagram.css.d.ts +0 -1
  2. package/dist/LikeC4Diagram.d.ts +1 -2
  3. package/dist/LikeC4Diagram.props.d.ts +24 -25
  4. package/dist/StaticLikeC4Diagram.d.ts +1 -2
  5. package/dist/globals.css.d.ts +1 -0
  6. package/dist/hooks/index.d.ts +2 -3
  7. package/dist/hooks/useSetState.d.ts +3 -0
  8. package/dist/hooks/useUpdateEffect.d.ts +4 -0
  9. package/dist/icons/Clipboard.d.ts +0 -1
  10. package/dist/icons/Link.d.ts +0 -1
  11. package/dist/icons/ZoomIn.d.ts +0 -1
  12. package/dist/icons/index.d.ts +0 -1
  13. package/dist/index.d.ts +1 -4
  14. package/dist/index.mjs +9388 -0
  15. package/dist/mantine/EnsureMantine.d.ts +2 -4
  16. package/dist/mantine/theme.d.ts +3 -0
  17. package/dist/mantine.css.d.ts +1 -0
  18. package/dist/state/DiagramContext.d.ts +386 -0
  19. package/dist/state/WhenInitialized.d.ts +3 -0
  20. package/dist/state/diagramStore.d.ts +428 -0
  21. package/dist/state/index.d.ts +4 -2
  22. package/dist/state/useDiagramStore.d.ts +387 -0
  23. package/dist/style.css +1212 -1
  24. package/dist/theme.css.d.ts +16 -2
  25. package/dist/ui/Camera.d.ts +0 -1
  26. package/dist/ui/KeepAspectRatio.css.d.ts +0 -1
  27. package/dist/ui/KeepAspectRatio.d.ts +0 -1
  28. package/dist/ui/OptionsPanel.css.d.ts +0 -1
  29. package/dist/ui/OptionsPanel.d.ts +0 -1
  30. package/dist/ui/index.d.ts +0 -1
  31. package/dist/ui/options/NodeOptions.d.ts +0 -1
  32. package/dist/xyflow/FitviewOnDiagramChange.d.ts +1 -5
  33. package/dist/xyflow/SyncWithDiagram.d.ts +5 -0
  34. package/dist/xyflow/XYFlowBackground.d.ts +0 -1
  35. package/dist/xyflow/XYFlowEvents.d.ts +5 -15
  36. package/dist/xyflow/XYFlowWrapper.d.ts +4 -5
  37. package/dist/xyflow/const.d.ts +1 -2
  38. package/dist/xyflow/diagram-to-xyflow.d.ts +4 -2
  39. package/dist/xyflow/edges/RelationshipEdge.d.ts +7 -7
  40. package/dist/xyflow/edges/edges.css.d.ts +2 -1
  41. package/dist/xyflow/edges/utils.d.ts +3 -4
  42. package/dist/xyflow/hooks/index.d.ts +2 -37
  43. package/dist/xyflow/hooks/{use-layout-/321/201onstraints.d.ts → useLayoutConstraints.d.ts} +2 -4
  44. package/dist/xyflow/hooks/useXYFlow.d.ts +266 -0
  45. package/dist/xyflow/nodes/compound/CompoundNode.css.d.ts +0 -1
  46. package/dist/xyflow/nodes/compound/CompoundNode.d.ts +0 -1
  47. package/dist/xyflow/nodes/compound/index.d.ts +0 -1
  48. package/dist/xyflow/nodes/element/ElementIcon.d.ts +1 -2
  49. package/dist/xyflow/nodes/element/ElementLink.css.d.ts +0 -1
  50. package/dist/xyflow/nodes/element/ElementLink.d.ts +1 -2
  51. package/dist/xyflow/nodes/element/ElementNode.d.ts +1 -3
  52. package/dist/xyflow/nodes/element/ElementShapeSvg.d.ts +2 -3
  53. package/dist/xyflow/nodes/element/element.css.d.ts +0 -1
  54. package/dist/xyflow/nodes/element/index.d.ts +1 -2
  55. package/dist/xyflow/nodes/shared/NavigateToBtn.d.ts +0 -1
  56. package/dist/xyflow/types.d.ts +20 -8
  57. package/dist/xyflow/utils.d.ts +0 -1
  58. package/package.json +36 -34
  59. package/src/LikeC4Diagram.css.ts +31 -0
  60. package/src/LikeC4Diagram.props.ts +154 -0
  61. package/src/LikeC4Diagram.tsx +119 -0
  62. package/src/StaticLikeC4Diagram.tsx +39 -0
  63. package/src/globals.css.ts +128 -0
  64. package/src/hooks/index.ts +2 -0
  65. package/src/hooks/useSetState.ts +19 -0
  66. package/src/hooks/useUpdateEffect.ts +28 -0
  67. package/src/icons/Clipboard.tsx +24 -0
  68. package/src/icons/Link.tsx +23 -0
  69. package/src/icons/ZoomIn.tsx +25 -0
  70. package/src/icons/index.ts +3 -0
  71. package/src/index.ts +11 -0
  72. package/src/mantine/EnsureMantine.tsx +14 -0
  73. package/src/mantine/theme.ts +19 -0
  74. package/src/mantine.css.ts +4 -0
  75. package/src/reset.d.ts +2 -0
  76. package/src/state/DiagramContext.tsx +42 -0
  77. package/src/state/WhenInitialized.tsx +24 -0
  78. package/src/state/diagramStore.ts +358 -0
  79. package/src/state/index.ts +4 -0
  80. package/src/state/useDiagramStore.ts +39 -0
  81. package/src/theme.css.ts +64 -0
  82. package/src/ui/Camera.tsx +174 -0
  83. package/src/ui/KeepAspectRatio.css.ts +7 -0
  84. package/src/ui/KeepAspectRatio.tsx +35 -0
  85. package/src/ui/OptionsPanel.css.ts +10 -0
  86. package/src/ui/OptionsPanel.tsx +65 -0
  87. package/src/ui/index.ts +3 -0
  88. package/src/ui/options/NodeOptions.tsx +253 -0
  89. package/src/xyflow/FitviewOnDiagramChange.tsx +93 -0
  90. package/src/xyflow/SyncWithDiagram.tsx +113 -0
  91. package/src/xyflow/XYFlowBackground.tsx +33 -0
  92. package/src/xyflow/XYFlowEvents.tsx +100 -0
  93. package/src/xyflow/XYFlowWrapper.tsx +166 -0
  94. package/src/xyflow/const.ts +7 -0
  95. package/src/xyflow/diagram-to-xyflow.ts +197 -0
  96. package/src/xyflow/edges/RelationshipEdge.tsx +288 -0
  97. package/src/xyflow/edges/edges.css.ts +124 -0
  98. package/src/xyflow/edges/utils.ts +110 -0
  99. package/src/xyflow/hooks/index.ts +2 -0
  100. package/src/xyflow/hooks/useLayoutConstraints.ts +289 -0
  101. package/src/xyflow/hooks/useXYFlow.ts +20 -0
  102. package/src/xyflow/nodes/compound/CompoundNode.css.ts +191 -0
  103. package/src/xyflow/nodes/compound/CompoundNode.tsx +105 -0
  104. package/src/xyflow/nodes/compound/index.ts +1 -0
  105. package/src/xyflow/nodes/element/ElementIcon.tsx +44 -0
  106. package/src/xyflow/nodes/element/ElementLink.css.ts +67 -0
  107. package/src/xyflow/nodes/element/ElementLink.tsx +94 -0
  108. package/src/xyflow/nodes/element/ElementNode.tsx +225 -0
  109. package/src/xyflow/nodes/element/ElementShapeSvg.tsx +181 -0
  110. package/src/xyflow/nodes/element/element.css.ts +261 -0
  111. package/src/xyflow/nodes/element/index.ts +1 -0
  112. package/src/xyflow/nodes/shared/NavigateToBtn.tsx +25 -0
  113. package/src/xyflow/types.ts +100 -0
  114. package/src/xyflow/utils.ts +12 -0
  115. package/dist/EmbeddedLikeC4Diagram.css.d.ts +0 -6
  116. package/dist/EmbeddedLikeC4Diagram.d.ts +0 -18
  117. package/dist/bundle.d.ts +0 -3
  118. package/dist/hooks/use-set-state.d.ts +0 -2
  119. package/dist/hooks/use-update-effect.d.ts +0 -4
  120. package/dist/index.css.d.ts +0 -2
  121. package/dist/index.js +0 -13043
  122. package/dist/mantine/index.d.ts +0 -3
  123. package/dist/state/DiagramState.d.ts +0 -162
  124. package/dist/xyflow/UpdateOnDiagramChange.d.ts +0 -10
@@ -0,0 +1,181 @@
1
+ import { type ElementShape, nonexhaustive } from '@likec4/core'
2
+ import { toDomPrecision } from '../../utils'
3
+ import { fillElementFill, fillMixStroke } from './element.css'
4
+
5
+ function cylinderSVGPath(diameter: number, height: number, tilt = 0.0725) {
6
+ const radius = Math.round(diameter / 2)
7
+ // const tiltAdjustedHeight = height * Math.cos((tilt * Math.PI) / 2)
8
+ const rx = radius
9
+ const ry = toDomPrecision(tilt * radius)
10
+ const tiltAdjustedHeight = height - 2 * ry
11
+
12
+ const path = ` M ${diameter},${ry}
13
+ a ${rx},${ry} 0,0,0 ${-diameter} 0
14
+ l 0,${tiltAdjustedHeight}
15
+ a ${rx},${ry} 0,0,0 ${diameter} 0
16
+ l 0,${-tiltAdjustedHeight}
17
+ z
18
+ `
19
+ .replace(/\s+/g, ' ')
20
+ .trim()
21
+ return {
22
+ path,
23
+ ry,
24
+ rx
25
+ }
26
+ }
27
+
28
+ function queueSVGPath(width: number, height: number, tilt = 0.2) {
29
+ const diameter = height
30
+ const radius = Math.round(diameter / 2)
31
+ const ry = radius
32
+ const rx = toDomPrecision((diameter / 2) * tilt)
33
+ const tiltAdjustedWidth = width - 2 * rx
34
+
35
+ const path = `
36
+ M ${rx},0
37
+ a ${rx},${ry} 0,0,0 0 ${diameter}
38
+ l ${tiltAdjustedWidth},0
39
+ a ${rx},${ry} 0,0,0 0 ${-diameter}
40
+ z`
41
+ .replace(/\s+/g, ' ')
42
+ .trim()
43
+ return {
44
+ path,
45
+ ry,
46
+ rx
47
+ }
48
+ }
49
+
50
+ const PersonIcon = {
51
+ width: 115,
52
+ height: 120,
53
+ path:
54
+ `M57.9197 0C10.9124 0 33.5766 54.75 33.5766 54.75C38.6131 62.25 45.3285 60.75 45.3285 66C45.3285 70.5 39.4526 72 33.5766 72.75C24.3431 72.75 15.9489 71.25 7.55474 84.75C2.51825 93 0 120 0 120H115C115 120 112.482 93 108.285 84.75C99.8905 70.5 91.4963 72.75 82.2628 72C76.3869 71.25 70.5109 69.75 70.5109 65.25C70.5109 60.75 77.2263 62.25 82.2628 54C82.2628 54.75 104.927 0 57.9197 0V0Z`
55
+ } as const
56
+
57
+ type ElementShapeSvgProps = {
58
+ shape: ElementShape
59
+ w: number
60
+ h: number
61
+ }
62
+
63
+ export function ElementShapeSvg({ shape, w, h }: ElementShapeSvgProps) {
64
+ switch (shape) {
65
+ case 'mobile': {
66
+ return (
67
+ <>
68
+ <rect
69
+ width={w}
70
+ height={h}
71
+ rx={6}
72
+ className={fillMixStroke}
73
+ strokeWidth={0}
74
+ />
75
+ <g className={fillElementFill} strokeWidth={0}>
76
+ <circle cx={17} cy={h / 2} r={12} />
77
+ <rect x={33} y={12} width={w - 44} height={h - 24} rx={5} />
78
+ </g>
79
+ </>
80
+ )
81
+ }
82
+ case 'browser': {
83
+ return (
84
+ <>
85
+ <rect
86
+ width={w}
87
+ height={h}
88
+ rx={6}
89
+ className={fillMixStroke}
90
+ strokeWidth={0}
91
+ />
92
+ <g className={fillElementFill} strokeWidth={0}>
93
+ <circle cx={16} cy={17} r={7} />
94
+ <circle cx={36} cy={17} r={7} />
95
+ <circle cx={56} cy={17} r={7} />
96
+ <rect x={70} y={8} width={w - 80} height={17} rx={4} />
97
+ <rect x={10} y={32} width={w - 20} height={h - 42} rx={4} />
98
+ </g>
99
+ </>
100
+ )
101
+ }
102
+ case 'person': {
103
+ return (
104
+ <>
105
+ <rect
106
+ width={w}
107
+ height={h}
108
+ rx={6}
109
+ strokeWidth={0} />
110
+ <svg
111
+ x={w - PersonIcon.width - 6}
112
+ y={h - PersonIcon.height}
113
+ width={PersonIcon.width}
114
+ height={PersonIcon.height}
115
+ viewBox={`0 0 ${PersonIcon.width} ${PersonIcon.height}`}
116
+ className={fillMixStroke}
117
+ >
118
+ <path
119
+ strokeWidth={0}
120
+ d={PersonIcon.path} />
121
+ </svg>
122
+ </>
123
+ )
124
+ }
125
+ case 'queue': {
126
+ const { path, rx, ry } = queueSVGPath(w, h)
127
+ return (
128
+ <>
129
+ <path d={path} strokeWidth={2} />
130
+ <ellipse cx={rx} cy={ry} ry={ry - 0.75} rx={rx} className={fillMixStroke} strokeWidth={2} />
131
+ </>
132
+ )
133
+ }
134
+ case 'storage':
135
+ case 'cylinder': {
136
+ const { path, rx, ry } = cylinderSVGPath(w, h)
137
+ return (
138
+ <>
139
+ <path d={path} strokeWidth={2} />
140
+ <ellipse cx={rx} cy={ry} ry={ry} rx={rx - 0.75} className={fillMixStroke} strokeWidth={2} />
141
+ </>
142
+ )
143
+ }
144
+ case 'rectangle': {
145
+ return (
146
+ <rect
147
+ width={w}
148
+ height={h}
149
+ rx={6}
150
+ strokeWidth={0} />
151
+ )
152
+ }
153
+ default: {
154
+ return nonexhaustive(shape)
155
+ }
156
+ }
157
+ }
158
+
159
+ /**
160
+ * When element is selected, this component is used to render the indicator
161
+ */
162
+ export function SelectedIndicator({ shape, w, h }: ElementShapeSvgProps) {
163
+ switch (shape) {
164
+ case 'queue':
165
+ return <path d={queueSVGPath(w, h).path} />
166
+ case 'storage':
167
+ case 'cylinder': {
168
+ return <path d={cylinderSVGPath(w, h).path} />
169
+ }
170
+ default: {
171
+ return (
172
+ <rect
173
+ x={-1}
174
+ y={-1}
175
+ width={w + 2}
176
+ height={h + 2}
177
+ rx={6} />
178
+ )
179
+ }
180
+ }
181
+ }
@@ -0,0 +1,261 @@
1
+ import { rem } from '@mantine/core'
2
+ import { createVar, fallbackVar, generateIdentifier, globalKeyframes, globalStyle, style } from '@vanilla-extract/css'
3
+ import { mantine } from '../../../mantine.css'
4
+ import { vars } from '../../../theme.css'
5
+
6
+ export const stokeFillMix = createVar('stroke-fill-mix')
7
+ const elPadding = createVar('el-padding')
8
+ // assignVars
9
+
10
+ export const container = style({
11
+ position: 'relative',
12
+ width: '100%',
13
+ height: '100%',
14
+ padding: 0,
15
+ margin: 0,
16
+ vars: {
17
+ [stokeFillMix]: `color-mix(in srgb, ${vars.element.stroke} 90%, ${vars.element.fill})`
18
+ }
19
+ })
20
+
21
+ const indicatorKeyframes = generateIdentifier('indicator')
22
+ globalKeyframes(indicatorKeyframes, {
23
+ 'from': {
24
+ opacity: 0.6
25
+ },
26
+ 'to': {
27
+ opacity: 0.4
28
+ }
29
+ })
30
+
31
+ const outlineColor = fallbackVar(
32
+ mantine.colors.primaryColors.outline,
33
+ mantine.colors.primaryColors.filled,
34
+ vars.element.stroke
35
+ )
36
+
37
+ export const indicator = style({
38
+ stroke: vars.element.loContrast,
39
+ transformOrigin: 'center center',
40
+ strokeWidth: 6,
41
+ animationDuration: '800ms',
42
+ animationName: indicatorKeyframes,
43
+ animationIterationCount: 'infinite',
44
+ animationDirection: 'alternate',
45
+ visibility: 'hidden',
46
+ selectors: {
47
+ ':where(.react-flow__node.selected) &': {
48
+ visibility: 'visible'
49
+ },
50
+ [`:where(.react-flow__node:focus-visible, ${container}:focus-visible) &`]: {
51
+ animationName: 'none',
52
+ strokeWidth: 10,
53
+ stroke: outlineColor,
54
+ visibility: 'visible'
55
+ },
56
+ ':where([data-likec4-shape="queue"], [data-likec4-shape="cylinder"], [data-likec4-shape="storage"]) &': {
57
+ strokeWidth: 10
58
+ }
59
+ }
60
+ })
61
+
62
+ export const fillElementFill = style({
63
+ fill: vars.element.fill
64
+ })
65
+
66
+ export const fillElementStroke = style({
67
+ fill: vars.element.stroke
68
+ })
69
+
70
+ export const fillMixStroke = style({
71
+ fill: stokeFillMix
72
+ })
73
+
74
+ export const title = style({
75
+ flex: '0 0 auto',
76
+ fontFamily: vars.element.font,
77
+ fontOpticalSizing: 'auto',
78
+ fontStyle: 'normal',
79
+ textAlign: 'center',
80
+ fontWeight: 500,
81
+ fontSize: rem(19),
82
+ lineHeight: 1.2,
83
+ textWrap: 'balance',
84
+ color: vars.element.hiContrast
85
+ })
86
+
87
+ export const description = style({
88
+ flex: '0 1 auto',
89
+ fontFamily: vars.element.font,
90
+ fontOpticalSizing: 'auto',
91
+ fontStyle: 'normal',
92
+ fontWeight: 400,
93
+ fontSize: rem(14),
94
+ lineHeight: 1.125,
95
+ textAlign: 'center',
96
+ textWrap: 'pretty',
97
+ color: vars.element.loContrast,
98
+ whiteSpaceCollapse: 'preserve-breaks',
99
+ textOverflow: 'ellipsis',
100
+ overflow: 'hidden'
101
+ })
102
+
103
+ export const technology = style({
104
+ flex: '0 0 auto',
105
+ fontFamily: vars.element.font,
106
+ fontOpticalSizing: 'auto',
107
+ fontStyle: 'normal',
108
+ fontWeight: 400,
109
+ fontSize: rem(12),
110
+ lineHeight: 1.125,
111
+ textAlign: 'center',
112
+ textWrap: 'balance',
113
+ opacity: 0.92,
114
+ color: vars.element.loContrast,
115
+ selectors: {
116
+ [`${container}:hover &`]: {
117
+ opacity: 1
118
+ }
119
+ }
120
+ })
121
+
122
+ export const cssElement = style({
123
+ position: 'relative',
124
+ width: '100%',
125
+ height: '100%',
126
+ padding: elPadding,
127
+ display: 'flex',
128
+ flexDirection: 'column',
129
+ alignItems: 'stretch',
130
+ justifyContent: 'center',
131
+ overflow: 'hidden',
132
+ gap: rem(8),
133
+ 'vars': {
134
+ [elPadding]: rem(24)
135
+ },
136
+ selectors: {
137
+ [`&:has(${description}):has(${technology})`]: {
138
+ gap: rem(6)
139
+ },
140
+ ':where([data-likec4-shape="queue"], [data-likec4-shape="mobile"]) &': {
141
+ paddingLeft: rem(40),
142
+ paddingRight: rem(20)
143
+ },
144
+ ':where([data-likec4-shape="cylinder"], [data-likec4-shape="storage"]) &': {
145
+ paddingTop: rem(34)
146
+ },
147
+ ':where([data-likec4-shape="browser"]) &': {
148
+ paddingTop: rem(32),
149
+ paddingBottom: rem(28)
150
+ }
151
+ }
152
+ })
153
+
154
+ export const iconMaxH = createVar('max-h')
155
+
156
+ export const elementIcon = style({
157
+ flex: `0 1 ${iconMaxH}`,
158
+ maxHeight: iconMaxH,
159
+ marginTop: -8,
160
+ // display: 'flex',
161
+ // justifyContent: 'flex-end',
162
+ // flexDirection: 'column',
163
+ // alignItems: 'center',
164
+ position: 'relative',
165
+ userSelect: 'none',
166
+ pointerEvents: 'none',
167
+ overflow: 'visible',
168
+ mixBlendMode: 'hard-light',
169
+ 'vars': {
170
+ [iconMaxH]: '30px'
171
+ }
172
+ })
173
+
174
+ globalStyle(`${elementIcon} img`, {
175
+ position: 'absolute',
176
+ left: 0,
177
+ bottom: 0,
178
+ width: '100%',
179
+ height: 'auto',
180
+ objectFit: 'contain',
181
+ maxHeight: `calc(${iconMaxH} + 16px)`
182
+ })
183
+
184
+ const filterShadow = createVar('filter-shadow')
185
+ const filterShadowHovered = createVar('filter-shadow-hovered')
186
+
187
+ export const cssShapeSvg = style({
188
+ top: '0px',
189
+ left: '0px',
190
+ position: 'absolute',
191
+ pointerEvents: 'none',
192
+ fill: vars.element.fill,
193
+ stroke: vars.element.stroke,
194
+ overflow: 'visible',
195
+ filter: fallbackVar(filterShadowHovered, filterShadow),
196
+ transition: 'filter 300ms ease-out',
197
+ transitionDelay: '0ms',
198
+ vars: {
199
+ [filterShadow]: `
200
+ drop-shadow(0 2px 1px rgba(0, 0, 0, 0.21))
201
+ drop-shadow(0 1px 1px color-mix(in srgb, ${vars.element.stroke} 40%, transparent))
202
+ drop-shadow(0 5px 3px rgba(0, 0, 0, 0.1))
203
+ `
204
+ },
205
+ selectors: {
206
+ [`:where(.react-flow__node.selected, .react-flow__node:focus-visible, ${container}:focus-visible) &`]: {
207
+ filter: 'none'
208
+ }
209
+ }
210
+ })
211
+
212
+ export const cssNavigateBtn = style({
213
+ zIndex: 'calc(var(--layer-overlays, 1) + 1)',
214
+ position: 'absolute',
215
+ pointerEvents: 'all',
216
+ left: '50%',
217
+ bottom: 0,
218
+ color: vars.element.loContrast,
219
+ cursor: 'pointer',
220
+ transformOrigin: '50% 65%',
221
+ opacity: 0.75,
222
+ transition: 'all 150ms ease-out',
223
+ transform: 'translate(-50%, 0)',
224
+ transitionDelay: '0ms',
225
+ backgroundColor: 'var(--ai-bg)',
226
+ 'vars': {
227
+ '--ai-bg': `color-mix(in srgb , ${vars.element.fill}, transparent 99%)`,
228
+ '--ai-bg-hover': `color-mix(in srgb , ${vars.element.fill} 65%, ${vars.element.stroke})`,
229
+ '--ai-hover': `color-mix(in srgb , ${vars.element.fill} 50%, ${vars.element.stroke})`
230
+ },
231
+ selectors: {
232
+ [`:where([data-likec4-shape='browser']) &`]: {
233
+ bottom: 3
234
+ },
235
+ [`:where(.react-flow__node:not(.dragging) ${container}:hover) &:not(:hover)`]: {
236
+ boxShadow: mantine.shadows.lg,
237
+ transform: 'translate(-50%, 0) scale(1.185)',
238
+ opacity: 1,
239
+ transitionDelay: '250ms',
240
+ vars: {
241
+ '--ai-bg': 'var(--ai-bg-hover)'
242
+ }
243
+ }
244
+ },
245
+ ':hover': {
246
+ boxShadow: mantine.shadows.lg,
247
+ transform: 'translate(-50%, 0) scale(1.35)',
248
+ opacity: 1,
249
+ transitionDelay: '0'
250
+ },
251
+ ':active': {
252
+ transform: 'translate(-50%, 0) scale(1.02)',
253
+ opacity: 1,
254
+ transitionDelay: '0'
255
+ }
256
+ })
257
+ globalStyle(`${cssNavigateBtn} svg.icon`, {
258
+ width: '65%',
259
+ height: '65%',
260
+ strokeWidth: '1.5'
261
+ })
@@ -0,0 +1 @@
1
+ export { ElementNode } from './ElementNode'
@@ -0,0 +1,25 @@
1
+ import { ActionIcon } from '@mantine/core'
2
+ import clsx from 'clsx'
3
+ import { ZoomIn } from '../../../icons'
4
+ import { useDiagramStoreApi } from '../../../state'
5
+
6
+ export type NavigateToBtnProps = {
7
+ xynodeId: string
8
+ className?: string
9
+ }
10
+
11
+ export function NavigateToBtn({ xynodeId, className }: NavigateToBtnProps) {
12
+ const diagramApi = useDiagramStoreApi()
13
+ return (
14
+ <ActionIcon
15
+ className={clsx('nodrag nopan', className)}
16
+ radius="xl"
17
+ onClick={event => {
18
+ diagramApi.getState().triggerOnNavigateTo(xynodeId, event)
19
+ event.stopPropagation()
20
+ }}
21
+ >
22
+ <ZoomIn />
23
+ </ActionIcon>
24
+ )
25
+ }
@@ -0,0 +1,100 @@
1
+ import type { BBox, DiagramEdge, DiagramNode, Fqn, Point } from '@likec4/core'
2
+ import type {
3
+ Edge,
4
+ EdgeMouseHandler,
5
+ InternalNode,
6
+ Node,
7
+ NodeMouseHandler,
8
+ OnMoveEnd,
9
+ OnMoveStart,
10
+ ReactFlowInstance,
11
+ ReactFlowState
12
+ } from '@xyflow/react'
13
+ import { isNode } from '@xyflow/react'
14
+ import type { MouseEvent as ReactMouseEvent } from 'react'
15
+ import { isTruthy } from 'remeda'
16
+ import type { SetReadonly, SetRequired, Simplify } from 'type-fest'
17
+
18
+ export type ElementNodeData = {
19
+ fqn: Fqn
20
+ element: DiagramNode
21
+ }
22
+
23
+ type TypedXYFlowNode<D extends Record<string, unknown>, T extends string> = SetReadonly<
24
+ SetRequired<Node<D, T>, 'type'>,
25
+ 'id' | 'type'
26
+ >
27
+
28
+ export type ElementXYFlowNode = TypedXYFlowNode<ElementNodeData, 'element'>
29
+
30
+ export type CompoundNodeData = {
31
+ fqn: Fqn
32
+ element: DiagramNode
33
+ }
34
+
35
+ export type CompoundXYFlowNode = TypedXYFlowNode<CompoundNodeData, 'compound'>
36
+
37
+ export type XYFlowNode = ElementXYFlowNode | CompoundXYFlowNode
38
+
39
+ export type InternalXYFlowNode = InternalNode<XYFlowNode>
40
+
41
+ export namespace XYFlowNode {
42
+ export type Data = ElementNodeData | CompoundNodeData
43
+
44
+ export function isCompound(node: unknown): node is CompoundXYFlowNode {
45
+ return isNode(node) && node.type === 'compound'
46
+ }
47
+ export function isElement(node: Node): node is ElementXYFlowNode {
48
+ return isNode(node) && node.type === 'element'
49
+ }
50
+
51
+ export const is = (node: Node): node is XYFlowNode => isCompound(node) || isElement(node)
52
+ }
53
+
54
+ export type RelationshipData = {
55
+ edge: DiagramEdge
56
+ controlPoints: Point[]
57
+ headPoint: Point | null
58
+ tailPoint: Point | null
59
+ type: 'bezier' | 'poly'
60
+ label: null | {
61
+ bbox: BBox
62
+ text: string
63
+ }
64
+ }
65
+
66
+ export type RelationshipEdge = Simplify<
67
+ SetRequired<
68
+ Omit<Edge<RelationshipData>, 'type'>,
69
+ 'data'
70
+ > & {
71
+ type: 'relationship'
72
+ }
73
+ >
74
+
75
+ export type XYFlowEdge = RelationshipEdge
76
+
77
+ export namespace XYFlowEdge {
78
+ export type Data = RelationshipData
79
+
80
+ export const isRelationship = (e: Edge): e is RelationshipEdge => e.type === 'relationship' && isTruthy(e.data)
81
+ }
82
+
83
+ export type XYFlowInstance = ReactFlowInstance<XYFlowNode, XYFlowEdge>
84
+ export type XYFlowState = ReactFlowState<XYFlowNode, XYFlowEdge>
85
+
86
+ export type XYFlowData = {
87
+ nodes: XYFlowNode[]
88
+ edges: XYFlowEdge[]
89
+ }
90
+
91
+ export type XYFlowEventHandlers = {
92
+ onPanelClick: (event: ReactMouseEvent) => void
93
+ onNodeContextMenu: NodeMouseHandler<XYFlowNode>
94
+ onEdgeContextMenu: EdgeMouseHandler<XYFlowEdge>
95
+ onPaneContextMenu: (event: ReactMouseEvent | MouseEvent) => void
96
+ onNodeClick: NodeMouseHandler<XYFlowNode>
97
+ onEdgeClick: EdgeMouseHandler<XYFlowEdge>
98
+ onMoveStart: OnMoveStart
99
+ onMoveEnd: OnMoveEnd
100
+ }
@@ -0,0 +1,12 @@
1
+ import type { XYPosition } from '@xyflow/react'
2
+
3
+ export function toDomPrecision(v: number | null) {
4
+ if (v === null) {
5
+ return 0.01
6
+ }
7
+ return Math.round(v * 100) / 100
8
+ }
9
+
10
+ export function distance(a: XYPosition, b: XYPosition) {
11
+ return Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2))
12
+ }
@@ -1,6 +0,0 @@
1
- export declare const modalContent: string;
2
- export declare const modalBody: string;
3
- export declare const modalHeader: string;
4
- export declare const modalCloseButtonBox: string;
5
- export declare const modalCloseButton: string;
6
- //# sourceMappingURL=EmbeddedLikeC4Diagram.css.d.ts.map
@@ -1,18 +0,0 @@
1
- import { LikeC4ColorMode } from './LikeC4Diagram.props';
2
- import { DiagramView } from '@likec4/core';
3
-
4
- export type EmbeddedLikeC4DiagramProps = {
5
- viewId: string;
6
- views: Record<string, DiagramView>;
7
- /**
8
- * Controls color scheme used for styling the flow
9
- * By default inherits from system or surrounding MantineProvider
10
- *
11
- * @example 'light' | 'dark'
12
- */
13
- colorMode?: LikeC4ColorMode | undefined;
14
- };
15
- declare function EmbeddedLikeC4DiagramCmp({ viewId, views, colorMode }: EmbeddedLikeC4DiagramProps): JSX.Element;
16
- export declare const EmbeddedLikeC4Diagram: typeof EmbeddedLikeC4DiagramCmp;
17
- export {};
18
- //# sourceMappingURL=EmbeddedLikeC4Diagram.d.ts.map
package/dist/bundle.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export declare function Styles(): string;
2
- export declare function useInjectStyles(): void;
3
- //# sourceMappingURL=bundle.d.ts.map
@@ -1,2 +0,0 @@
1
- export declare function useSetState<T extends Record<string, any>>(initialState: T | (() => T)): readonly [T, (statePartial: Partial<T> | ((current: T) => Partial<T>)) => void];
2
- //# sourceMappingURL=use-set-state.d.ts.map
@@ -1,4 +0,0 @@
1
- import { useEffect } from 'react';
2
-
3
- export declare function useUpdateEffect(callback: React.EffectCallback, deps: React.DependencyList, effectFn?: typeof useEffect): void;
4
- //# sourceMappingURL=use-update-effect.d.ts.map
@@ -1,2 +0,0 @@
1
- export declare const scope: string;
2
- //# sourceMappingURL=index.css.d.ts.map