@likec4/diagram 1.4.0 → 1.6.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 (87) hide show
  1. package/LICENSE +1 -1
  2. package/dist/LikeC4Diagram.css.d.ts +0 -1
  3. package/dist/LikeC4Diagram.d.ts +1 -1
  4. package/dist/LikeC4Diagram.props.d.ts +19 -4
  5. package/dist/StaticLikeC4Diagram.d.ts +1 -1
  6. package/dist/index.d.ts +1 -1
  7. package/dist/index.mjs +3937 -3646
  8. package/dist/state/DiagramContext.d.ts +95 -4159
  9. package/dist/state/diagramStore.d.ts +100 -4164
  10. package/dist/state/hooks.d.ts +4 -0
  11. package/dist/state/index.d.ts +1 -2
  12. package/dist/style.css +281 -191
  13. package/dist/ui/options/EdgeOptions.d.ts +19 -0
  14. package/dist/ui/options/NodeOptions.d.ts +2 -2
  15. package/dist/xyflow/EdgeMarkers.d.ts +11 -0
  16. package/dist/xyflow/XYFlowEvents.d.ts +8 -5
  17. package/dist/xyflow/const.d.ts +3 -3
  18. package/dist/xyflow/diagram-to-xyflow.d.ts +1 -1
  19. package/dist/xyflow/edges/RelationshipEdge.d.ts +3 -2
  20. package/dist/xyflow/edges/edges.css.d.ts +1 -0
  21. package/dist/xyflow/edges/utils.d.ts +1 -0
  22. package/dist/xyflow/hooks/index.d.ts +3 -2
  23. package/dist/xyflow/hooks/useXYFlow.d.ts +13 -12
  24. package/dist/xyflow/nodes/compound/CompoundNode.css.d.ts +1 -0
  25. package/dist/xyflow/nodes/element/ElementShapeSvg.d.ts +5 -0
  26. package/dist/xyflow/nodes/element/element.css.d.ts +5 -2
  27. package/dist/xyflow/types.d.ts +2 -32
  28. package/package.json +19 -19
  29. package/src/LikeC4Diagram.css.ts +0 -8
  30. package/src/LikeC4Diagram.props.ts +23 -5
  31. package/src/LikeC4Diagram.tsx +18 -21
  32. package/src/StaticLikeC4Diagram.tsx +1 -0
  33. package/src/globals.css.ts +10 -3
  34. package/src/index.ts +1 -1
  35. package/src/mantine.css.ts +2 -2
  36. package/src/state/DiagramContext.tsx +44 -13
  37. package/src/state/diagramStore.ts +72 -53
  38. package/src/state/hooks.ts +5 -0
  39. package/src/state/index.ts +1 -2
  40. package/src/ui/BackwardForwardPanel.css.ts +9 -9
  41. package/src/ui/DiagramTitlePanel.css.ts +7 -2
  42. package/src/ui/DiagramTitlePanel.tsx +5 -3
  43. package/src/ui/DynamicViewWalkthrough.tsx +6 -4
  44. package/src/ui/OptionsPanel.tsx +37 -27
  45. package/src/ui/options/EdgeOptions.tsx +157 -0
  46. package/src/ui/options/NodeOptions.tsx +37 -29
  47. package/src/xyflow/EdgeMarkers.tsx +148 -0
  48. package/src/xyflow/FitviewOnDiagramChange.tsx +9 -5
  49. package/src/xyflow/SelectEdgesOnNodeFocus.tsx +59 -55
  50. package/src/xyflow/SyncWithDiagram.tsx +13 -20
  51. package/src/xyflow/XYFlow.tsx +3 -4
  52. package/src/xyflow/XYFlowEvents.tsx +48 -33
  53. package/src/xyflow/const.ts +3 -3
  54. package/src/xyflow/diagram-to-xyflow.ts +17 -41
  55. package/src/xyflow/edges/RelationshipEdge.tsx +208 -119
  56. package/src/xyflow/edges/edges.css.ts +40 -26
  57. package/src/xyflow/edges/utils.ts +10 -0
  58. package/src/xyflow/hooks/index.ts +4 -2
  59. package/src/xyflow/hooks/useLayoutConstraints.ts +3 -4
  60. package/src/xyflow/hooks/useXYFlow.ts +28 -1
  61. package/src/xyflow/nodes/compound/CompoundNode.css.ts +34 -24
  62. package/src/xyflow/nodes/compound/CompoundNode.tsx +52 -53
  63. package/src/xyflow/nodes/element/ElementLink.tsx +12 -16
  64. package/src/xyflow/nodes/element/ElementNode.tsx +118 -114
  65. package/src/xyflow/nodes/element/ElementShapeSvg.tsx +2 -2
  66. package/src/xyflow/nodes/element/element.css.ts +147 -55
  67. package/src/xyflow/nodes/shared/NavigateToBtn.tsx +1 -1
  68. package/src/xyflow/types.ts +2 -4
  69. package/src/xyflow/utils.ts +3 -6
  70. package/dist/KeepAspectRatioContainer.d.ts +0 -9
  71. package/dist/icons/Clipboard.d.ts +0 -3
  72. package/dist/icons/Link.d.ts +0 -3
  73. package/dist/icons/ZoomIn.d.ts +0 -3
  74. package/dist/icons/index.d.ts +0 -3
  75. package/dist/mantine/theme.d.ts +0 -3
  76. package/dist/state/WhenInitialized.d.ts +0 -3
  77. package/dist/ui/Camera.d.ts +0 -3
  78. package/dist/xyflow/nodes/element/ElementIcon.d.ts +0 -10
  79. package/src/KeepAspectRatioContainer.tsx +0 -36
  80. package/src/icons/Clipboard.tsx +0 -24
  81. package/src/icons/Link.tsx +0 -23
  82. package/src/icons/ZoomIn.tsx +0 -25
  83. package/src/icons/index.ts +0 -3
  84. package/src/mantine/theme.ts +0 -20
  85. package/src/state/WhenInitialized.tsx +0 -24
  86. package/src/ui/Camera.tsx +0 -174
  87. package/src/xyflow/nodes/element/ElementIcon.tsx +0 -44
@@ -4,16 +4,16 @@ import { mantine } from '../../../mantine.css'
4
4
  import { vars } from '../../../theme.css'
5
5
 
6
6
  export const stokeFillMix = createVar('stroke-fill-mix')
7
- const elPadding = createVar('el-padding')
8
- // assignVars
9
7
 
10
8
  export const container = style({
11
9
  width: '100%',
12
10
  height: '100%',
13
11
  padding: 0,
14
12
  margin: 0,
13
+ flex: '1',
15
14
  display: 'flex',
16
- alignItems: 'stretch',
15
+ alignItems: 'center',
16
+ justifyContent: 'center',
17
17
  vars: {
18
18
  [stokeFillMix]: `color-mix(in srgb, ${vars.element.stroke} 90%, ${vars.element.fill})`
19
19
  },
@@ -27,6 +27,12 @@ export const container = style({
27
27
  }
28
28
  })
29
29
 
30
+ export const handleCenter = style({
31
+ top: '50%',
32
+ left: '50%',
33
+ visibility: 'hidden'
34
+ })
35
+
30
36
  export const containerAnimated = style({
31
37
  willChange: 'transform'
32
38
  })
@@ -43,10 +49,10 @@ globalStyle(`.react-flow__node-element:has(${dimmed})`, {
43
49
 
44
50
  const indicatorKeyframes = keyframes({
45
51
  'from': {
46
- opacity: 0.6
52
+ strokeOpacity: 0.8
47
53
  },
48
54
  'to': {
49
- opacity: 0.4
55
+ strokeOpacity: 0.5
50
56
  }
51
57
  })
52
58
 
@@ -56,15 +62,21 @@ const outlineColor = fallbackVar(
56
62
  vars.element.stroke
57
63
  )
58
64
 
65
+ const indicatorStroke = createVar('indicator-stroke')
66
+
59
67
  export const indicator = style({
60
- stroke: vars.element.loContrast,
68
+ stroke: indicatorStroke,
69
+ fill: 'none',
61
70
  transformOrigin: 'center center',
62
71
  strokeWidth: 6,
63
- animationDuration: '800ms',
72
+ animationDuration: '1s',
64
73
  animationIterationCount: 'infinite',
65
74
  animationDirection: 'alternate',
66
- opacity: 0.6,
75
+ strokeOpacity: 0.8,
67
76
  visibility: 'hidden',
77
+ vars: {
78
+ [indicatorStroke]: vars.element.loContrast
79
+ },
68
80
  selectors: {
69
81
  ':where(.react-flow__node.selected) &': {
70
82
  visibility: 'visible',
@@ -78,6 +90,11 @@ export const indicator = style({
78
90
  ':where([data-likec4-shape="queue"], [data-likec4-shape="cylinder"], [data-likec4-shape="storage"]) &': {
79
91
  strokeWidth: 10
80
92
  },
93
+ [`:where([data-mantine-color-scheme='light']) &`]: {
94
+ vars: {
95
+ [indicatorStroke]: `color-mix(in srgb, ${vars.element.fill} 50%, #3c3c3c)`
96
+ }
97
+ },
81
98
  [`${dimmed} &`]: {
82
99
  visibility: 'hidden',
83
100
  display: 'none'
@@ -97,15 +114,20 @@ export const fillMixStroke = style({
97
114
  fill: stokeFillMix
98
115
  })
99
116
 
117
+ export const hasIcon = style({})
118
+
119
+ const textAlign = createVar('text-align')
120
+ const iconSize = createVar('icon-size')
121
+
100
122
  export const title = style({
101
123
  flex: '0 0 auto',
102
124
  fontFamily: vars.element.font,
103
125
  fontOpticalSizing: 'auto',
104
126
  fontStyle: 'normal',
105
- textAlign: 'center',
127
+ textAlign: textAlign,
106
128
  fontWeight: 500,
107
- fontSize: rem(19),
108
- lineHeight: 1.2,
129
+ fontSize: 19,
130
+ lineHeight: 1.15,
109
131
  textWrap: 'balance',
110
132
  color: vars.element.hiContrast
111
133
  })
@@ -116,14 +138,19 @@ export const description = style({
116
138
  fontOpticalSizing: 'auto',
117
139
  fontStyle: 'normal',
118
140
  fontWeight: 400,
119
- fontSize: rem(14),
120
- lineHeight: 1.25,
121
- textAlign: 'center',
141
+ fontSize: 14,
142
+ lineHeight: 1.2,
143
+ textAlign: textAlign,
122
144
  textWrap: 'pretty',
123
145
  color: vars.element.loContrast,
124
146
  whiteSpaceCollapse: 'preserve-breaks',
125
147
  textOverflow: 'ellipsis',
126
- overflow: 'hidden'
148
+ overflow: 'hidden',
149
+ selectors: {
150
+ [`:where(${hasIcon}) &`]: {
151
+ textWrap: 'wrap'
152
+ }
153
+ }
127
154
  })
128
155
 
129
156
  export const technology = style({
@@ -132,9 +159,9 @@ export const technology = style({
132
159
  fontOpticalSizing: 'auto',
133
160
  fontStyle: 'normal',
134
161
  fontWeight: 400,
135
- fontSize: rem(12),
162
+ fontSize: 12,
136
163
  lineHeight: 1.125,
137
- textAlign: 'center',
164
+ textAlign: textAlign,
138
165
  textWrap: 'balance',
139
166
  opacity: 0.92,
140
167
  color: vars.element.loContrast,
@@ -145,74 +172,137 @@ export const technology = style({
145
172
  }
146
173
  })
147
174
 
148
- export const element = style({
175
+ export const elementDataContainer = style({
149
176
  flex: '1',
150
- padding: elPadding,
177
+ height: 'fit-content',
151
178
  display: 'flex',
152
- flexDirection: 'column',
153
- alignItems: 'stretch',
179
+ alignItems: 'center',
154
180
  justifyContent: 'center',
181
+ flexDirection: 'row',
182
+ padding: rem(24),
155
183
  overflow: 'hidden',
156
- gap: rem(8),
157
- 'vars': {
158
- [elPadding]: rem(24)
184
+ gap: rem(10),
185
+ vars: {
186
+ [iconSize]: '48px'
159
187
  },
160
188
  selectors: {
161
- [`&:has(${description}):has(${technology})`]: {
162
- gap: rem(6)
163
- },
164
189
  ':where([data-likec4-shape="queue"], [data-likec4-shape="mobile"]) &': {
165
- paddingLeft: rem(40),
166
- paddingRight: rem(20)
190
+ paddingLeft: 40,
191
+ paddingRight: 20
167
192
  },
168
193
  ':where([data-likec4-shape="cylinder"], [data-likec4-shape="storage"]) &': {
169
- paddingTop: rem(34)
194
+ paddingTop: 30
170
195
  },
171
196
  ':where([data-likec4-shape="browser"]) &': {
172
- paddingTop: rem(32),
173
- paddingBottom: rem(28)
197
+ paddingTop: 32,
198
+ paddingBottom: 28
199
+ },
200
+ [`&:is(${hasIcon})`]: {
201
+ paddingRight: 20
202
+ },
203
+ [`${container}:not(:is([data-likec4-shape="queue"],[data-likec4-shape="mobile"])) &:is(${hasIcon})`]: {
204
+ paddingLeft: 20
205
+ },
206
+ [`&:has(${description}, ${technology})`]: {
207
+ alignItems: 'flex-start',
208
+ gap: rem(16),
209
+ vars: {
210
+ [iconSize]: '60px'
211
+ }
174
212
  }
175
213
  }
176
214
  })
177
215
 
178
- export const iconMaxH = createVar('max-h')
179
-
180
- export const elementIcon = style({
181
- flex: `0 1 ${iconMaxH}`,
182
- maxHeight: iconMaxH,
183
- marginTop: -8,
184
- position: 'relative',
185
- userSelect: 'none',
186
- pointerEvents: 'none',
187
- overflow: 'visible',
188
- mixBlendMode: 'hard-light',
216
+ export const elementTextData = style({
217
+ height: 'fit-content',
218
+ width: 'max-content',
219
+ display: 'flex',
220
+ flexDirection: 'column',
221
+ alignItems: 'stretch',
222
+ justifyContent: 'center',
223
+ flexWrap: 'nowrap',
224
+ overflow: 'hidden',
225
+ gap: rem(8),
189
226
  'vars': {
190
- [iconMaxH]: '30px'
227
+ [textAlign]: 'center'
228
+ },
229
+ selectors: {
230
+ [`&:has(${description}):has(${technology})`]: {
231
+ gap: rem(6)
232
+ },
233
+ [`:where(${hasIcon}) &`]: {
234
+ minWidth: 'calc(100% - 160px)',
235
+ alignItems: 'flex-start',
236
+ 'vars': {
237
+ [textAlign]: 'left'
238
+ }
239
+ }
191
240
  }
192
241
  })
193
242
 
194
- globalStyle(`${elementIcon} img`, {
195
- position: 'absolute',
196
- left: 0,
197
- bottom: 0,
243
+ export const elementIcon = style({
244
+ flex: `0 0 ${iconSize}`,
245
+ height: iconSize,
246
+ width: iconSize,
247
+ display: 'flex',
248
+ alignItems: 'center',
249
+ justifyContent: 'center',
250
+ mixBlendMode: 'hard-light'
251
+ })
252
+ globalStyle(`${elementIcon} svg, ${elementIcon} img`, {
198
253
  width: '100%',
199
254
  height: 'auto',
200
- objectFit: 'contain',
201
- maxHeight: `calc(${iconMaxH} + 16px)`
255
+ maxHeight: '100%',
256
+ pointerEvents: 'none',
257
+ filter: `
258
+ drop-shadow(0 0 3px rgb(0 0 0 / 12%))
259
+ drop-shadow(0 1px 8px rgb(0 0 0 / 8%))
260
+ drop-shadow(1px 1px 16px rgb(0 0 0 / 3%))
261
+ `
262
+ })
263
+ globalStyle(`${elementIcon} img`, {
264
+ objectFit: 'contain'
202
265
  })
203
266
 
204
267
  const filterShadow = createVar('filter-shadow')
205
- const filterShadowHovered = createVar('filter-shadow-hovered')
206
268
 
269
+ export const cssShapeSvgMultiple = style({
270
+ top: 0,
271
+ left: 0,
272
+ position: 'absolute',
273
+ pointerEvents: 'none',
274
+ transformOrigin: '50% 50%',
275
+ fill: vars.element.fill,
276
+ stroke: 'none',
277
+ zIndex: -1,
278
+ transition: 'opacity 500ms ease-out',
279
+ transform: 'translate(8px,10px)',
280
+ opacity: 0.5,
281
+ selectors: {
282
+ [`:where(.react-flow__node.selected, .react-flow__node:focus-visible, ${container}:focus-visible) &`]: {
283
+ visibility: 'hidden'
284
+ },
285
+ ':where([data-likec4-shape="cylinder"], [data-likec4-shape="storage"]) &': {
286
+ transform: 'translate(8px,8px)'
287
+ },
288
+ ':where([data-likec4-shape="queue"]) &': {
289
+ transform: 'translate(-10px,8px)'
290
+ },
291
+ ':where([data-hovered="true"]) &': {
292
+ transition: 'opacity 300ms ease-in',
293
+ opacity: 0.2
294
+ }
295
+ }
296
+ })
207
297
  export const cssShapeSvg = style({
208
- top: '0px',
209
- left: '0px',
298
+ top: 0,
299
+ left: 0,
210
300
  position: 'absolute',
211
301
  pointerEvents: 'none',
212
302
  fill: vars.element.fill,
213
303
  stroke: vars.element.stroke,
214
304
  overflow: 'visible',
215
- filter: fallbackVar(filterShadowHovered, filterShadow),
305
+ filter: filterShadow,
216
306
  transition: 'filter 300ms ease-out',
217
307
  transitionDelay: '0ms',
218
308
  zIndex: -1,
@@ -225,7 +315,9 @@ export const cssShapeSvg = style({
225
315
  },
226
316
  selectors: {
227
317
  [`:where(.react-flow__node.selected, .react-flow__node:focus-visible, ${container}:focus-visible) &`]: {
228
- filter: 'none'
318
+ vars: {
319
+ [filterShadow]: `none`
320
+ }
229
321
  }
230
322
  }
231
323
  })
@@ -1,7 +1,7 @@
1
1
  import { ActionIcon } from '@mantine/core'
2
2
  import { IconZoomScan } from '@tabler/icons-react'
3
3
  import clsx from 'clsx'
4
- import { useDiagramStoreApi } from '../../../state'
4
+ import { useDiagramStoreApi } from '../../../state/useDiagramStore'
5
5
 
6
6
  export type NavigateToBtnProps = {
7
7
  xynodeId: string
@@ -1,4 +1,4 @@
1
- import type { BBox, DiagramEdge, DiagramNode, Fqn, Point, ViewID, XYPosition } from '@likec4/core'
1
+ import type { BBox, DiagramEdge, DiagramNode, Fqn, XYPosition } from '@likec4/core'
2
2
  import type {
3
3
  Edge,
4
4
  EdgeMouseHandler,
@@ -13,7 +13,7 @@ import type {
13
13
  import { isNode } from '@xyflow/react'
14
14
  import type { MouseEvent as ReactMouseEvent } from 'react'
15
15
  import { isTruthy } from 'remeda'
16
- import type { SetReadonly, SetRequired, Simplify } from 'type-fest'
16
+ import type { SetReadonly, SetRequired } from 'type-fest'
17
17
 
18
18
  export type ElementNodeData = {
19
19
  fqn: Fqn
@@ -61,8 +61,6 @@ export type RelationshipData = {
61
61
  // viewId: ViewID
62
62
  // if set - edge was changed by user
63
63
  controlPoints: XYPosition[] | null
64
- headPoint: Point | null
65
- tailPoint: Point | null
66
64
  type: 'bezier' | 'poly'
67
65
  // if dynamic view
68
66
  stepNum: number | null
@@ -1,5 +1,5 @@
1
1
  import { hasAtLeast, invariant } from '@likec4/core'
2
- import type { DiagramEdge, NonEmptyArray, Point } from '@likec4/core/types'
2
+ import type { DiagramEdge, Point } from '@likec4/core/types'
3
3
  import type { XYPosition } from '@xyflow/react'
4
4
  import { Bezier } from 'bezier-js'
5
5
  import { isArray } from 'remeda'
@@ -33,17 +33,14 @@ export function bezierControlPoints(diagramEdge: DiagramEdge) {
33
33
  inflections.forEach(t => {
34
34
  const { x, y } = bezier.get(t)
35
35
  handles.push({
36
- x: toDomPrecision(x),
37
- y: toDomPrecision(y)
36
+ x: Math.round(x),
37
+ y: Math.round(y)
38
38
  })
39
39
  })
40
40
  bezierPoints = rest
41
41
  start = end
42
42
  }
43
43
  invariant(bezierPoints.length === 0, 'all points should be consumed')
44
- if (diagramEdge.dir === 'back' && handles.length > 0) {
45
- handles.reverse()
46
- }
47
44
 
48
45
  return handles
49
46
  }
@@ -1,9 +0,0 @@
1
- import { HTMLAttributes } from 'react';
2
-
3
- type KeepAspectRatioContainerProps = HTMLAttributes<HTMLDivElement> & {
4
- enabled: boolean;
5
- width: number;
6
- height: number;
7
- };
8
- export declare function KeepAspectRatioContainer({ children, width, height, enabled, className, style, ...rest }: KeepAspectRatioContainerProps): import("react/jsx-runtime").JSX.Element;
9
- export {};
@@ -1,3 +0,0 @@
1
- import { SVGProps } from 'react';
2
-
3
- export declare const ClipboardCopy: import('react').ForwardRefExoticComponent<Omit<SVGProps<SVGSVGElement>, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
@@ -1,3 +0,0 @@
1
- import { SVGProps } from 'react';
2
-
3
- export declare const Link: import('react').ForwardRefExoticComponent<Omit<SVGProps<SVGSVGElement>, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
@@ -1,3 +0,0 @@
1
- import { SVGProps } from 'react';
2
-
3
- export declare const ZoomIn: import('react').ForwardRefExoticComponent<Omit<SVGProps<SVGSVGElement>, "ref"> & import('react').RefAttributes<SVGSVGElement>>;
@@ -1,3 +0,0 @@
1
- export * from './Clipboard';
2
- export * from './Link';
3
- export * from './ZoomIn';
@@ -1,3 +0,0 @@
1
- import { MantineTheme } from '@mantine/core';
2
-
3
- export declare const theme: MantineTheme;
@@ -1,3 +0,0 @@
1
- import { PropsWithChildren } from 'react';
2
-
3
- export declare function WhenInitialized({ children }: PropsWithChildren): import("react/jsx-runtime").JSX.Element | null;
@@ -1,3 +0,0 @@
1
- /// <reference types="react" />
2
- declare const CameraMemo: import('react').NamedExoticComponent<object>;
3
- export default CameraMemo;
@@ -1,10 +0,0 @@
1
- import { XYFlowNode } from '../../types';
2
-
3
- type ElementIconProps = {
4
- node: XYFlowNode['data']['element'];
5
- maxWidth?: number | undefined;
6
- paddingX?: number | undefined;
7
- paddingY?: number | undefined;
8
- };
9
- export declare function ElementIcon({ node, paddingY }: ElementIconProps): import("react/jsx-runtime").JSX.Element | null;
10
- export {};
@@ -1,36 +0,0 @@
1
- import { Box } from '@mantine/core'
2
- import clsx from 'clsx'
3
- import { type HTMLAttributes, useId } from 'react'
4
- import * as css from './LikeC4Diagram.css'
5
-
6
- type KeepAspectRatioContainerProps = HTMLAttributes<HTMLDivElement> & {
7
- // Whether to keep the aspect ratio
8
- enabled: boolean
9
- width: number
10
- height: number
11
- }
12
-
13
- export function KeepAspectRatioContainer({
14
- children,
15
- width,
16
- height,
17
- enabled,
18
- className,
19
- style,
20
- ...rest
21
- }: KeepAspectRatioContainerProps) {
22
- return (
23
- <Box
24
- {...rest}
25
- className={clsx(css.keepAspectRatioContainer, className)}
26
- style={enabled
27
- ? {
28
- ...style,
29
- aspectRatio: `${Math.ceil(width)}/${Math.ceil(height)}`,
30
- maxHeight: `var(--likec4-view-max-height, ${Math.ceil(height)}px)`
31
- }
32
- : style}>
33
- {children}
34
- </Box>
35
- )
36
- }
@@ -1,24 +0,0 @@
1
- import clsx from 'clsx'
2
- import { forwardRef, type SVGProps } from 'react'
3
-
4
- export const ClipboardCopy = forwardRef<SVGSVGElement, SVGProps<SVGSVGElement>>(({ className, ...props }, ref) => (
5
- <svg
6
- ref={ref}
7
- xmlns="http://www.w3.org/2000/svg"
8
- className={clsx('icon icon-tabler icon-tabler-zoom-in', className)}
9
- width="24"
10
- height="24"
11
- viewBox="0 0 24 24"
12
- strokeWidth="1.5"
13
- stroke="currentColor"
14
- fill="none"
15
- strokeLinecap="round"
16
- strokeLinejoin="round"
17
- {...props}
18
- >
19
- <path stroke="none" d="M0 0h24v24H0z" fill="none" />
20
- <path d="M9 5h-2a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h3m9 -9v-5a2 2 0 0 0 -2 -2h-2" />
21
- <path d="M13 17v-1a1 1 0 0 1 1 -1h1m3 0h1a1 1 0 0 1 1 1v1m0 3v1a1 1 0 0 1 -1 1h-1m-3 0h-1a1 1 0 0 1 -1 -1v-1" />
22
- <path d="M9 3m0 2a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v0a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2z" />
23
- </svg>
24
- ))
@@ -1,23 +0,0 @@
1
- import clsx from 'clsx'
2
- import { forwardRef, type SVGProps } from 'react'
3
-
4
- export const Link = forwardRef<SVGSVGElement, SVGProps<SVGSVGElement>>(({ className, ...props }, ref) => (
5
- <svg
6
- ref={ref}
7
- className={clsx('icon icon-tabler', className)}
8
- stroke="currentColor"
9
- fill="currentColor"
10
- strokeWidth="0"
11
- viewBox="0 0 20 20"
12
- height="20"
13
- width="20"
14
- xmlns="http://www.w3.org/2000/svg"
15
- {...props}
16
- >
17
- <path
18
- fillRule="evenodd"
19
- d="M12.586 4.586a2 2 0 112.828 2.828l-3 3a2 2 0 01-2.828 0 1 1 0 00-1.414 1.414 4 4 0 005.656 0l3-3a4 4 0 00-5.656-5.656l-1.5 1.5a1 1 0 101.414 1.414l1.5-1.5zm-5 5a2 2 0 012.828 0 1 1 0 101.414-1.414 4 4 0 00-5.656 0l-3 3a4 4 0 105.656 5.656l1.5-1.5a1 1 0 10-1.414-1.414l-1.5 1.5a2 2 0 11-2.828-2.828l3-3z"
20
- clipRule="evenodd">
21
- </path>
22
- </svg>
23
- ))
@@ -1,25 +0,0 @@
1
- import clsx from 'clsx'
2
- import { forwardRef, type SVGProps } from 'react'
3
-
4
- export const ZoomIn = forwardRef<SVGSVGElement, SVGProps<SVGSVGElement>>(({ className, ...props }, ref) => (
5
- <svg
6
- ref={ref}
7
- xmlns="http://www.w3.org/2000/svg"
8
- className={clsx('icon icon-tabler icon-tabler-zoom-in', className)}
9
- width="24"
10
- height="24"
11
- viewBox="0 0 24 24"
12
- strokeWidth="1.5"
13
- stroke="currentColor"
14
- fill="none"
15
- strokeLinecap="round"
16
- strokeLinejoin="round"
17
- {...props}
18
- >
19
- <path stroke="none" d="M0 0h24v24H0z" fill="none" />
20
- <path d="M10 10m-7 0a7 7 0 1 0 14 0a7 7 0 1 0 -14 0" />
21
- <path d="M7 10l6 0" />
22
- <path d="M10 7l0 6" />
23
- <path d="M21 21l-6 -6" />
24
- </svg>
25
- ))
@@ -1,3 +0,0 @@
1
- export * from './Clipboard'
2
- export * from './Link'
3
- export * from './ZoomIn'
@@ -1,20 +0,0 @@
1
- import { createTheme, type MantineTheme } from '@mantine/core'
2
-
3
- export const theme = createTheme({
4
- primaryColor: 'indigo',
5
- cursorType: 'pointer',
6
- defaultRadius: 'sm',
7
- respectReducedMotion: true,
8
- headings: {
9
- fontWeight: '500',
10
- sizes: {
11
- h1: {
12
- // fontSize: '2rem',
13
- fontWeight: '600'
14
- },
15
- h2: {
16
- // fontSize: '1.85rem',
17
- }
18
- }
19
- }
20
- }) as MantineTheme
@@ -1,24 +0,0 @@
1
- import { type PropsWithChildren, useEffect, useState } from 'react'
2
- import { useDiagramStoreApi } from './useDiagramStore'
3
-
4
- export function WhenInitialized({ children }: PropsWithChildren) {
5
- const diagramApi = useDiagramStoreApi()
6
-
7
- const [isInitialized, setIsInitialized] = useState(diagramApi.getState().initialized)
8
-
9
- useEffect(() => {
10
- if (isInitialized) {
11
- return
12
- }
13
- return diagramApi.subscribe(
14
- s => s.initialized,
15
- setIsInitialized
16
- )
17
- }, [isInitialized])
18
-
19
- if (!isInitialized) {
20
- return null
21
- }
22
-
23
- return <>{children}</>
24
- }