@likec4/diagram 1.3.0 → 1.5.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 (95) hide show
  1. package/dist/LikeC4Diagram.css.d.ts +0 -1
  2. package/dist/LikeC4Diagram.d.ts +1 -1
  3. package/dist/LikeC4Diagram.props.d.ts +7 -2
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.mjs +1580 -1194
  6. package/dist/state/DiagramContext.d.ts +97 -4169
  7. package/dist/state/diagramStore.d.ts +98 -4172
  8. package/dist/state/hooks.d.ts +4 -0
  9. package/dist/state/index.d.ts +1 -3
  10. package/dist/state/useDiagramStore.d.ts +3 -4622
  11. package/dist/state/useNavigationHistory.d.ts +5 -0
  12. package/dist/style.css +217 -159
  13. package/dist/theme.css.d.ts +5 -0
  14. package/dist/ui/BackwardForwardPanel.css.d.ts +1 -0
  15. package/dist/ui/BackwardForwardPanel.d.ts +1 -0
  16. package/dist/ui/DiagramTitlePanel.css.d.ts +1 -1
  17. package/dist/ui/OptionsPanel.d.ts +1 -3
  18. package/dist/ui/options/EdgeOptions.d.ts +19 -0
  19. package/dist/ui/options/NodeOptions.d.ts +2 -2
  20. package/dist/xyflow/EdgeMarkers.d.ts +11 -0
  21. package/dist/xyflow/XYFlowEvents.d.ts +12 -9
  22. package/dist/xyflow/XYFlowInner.d.ts +1 -0
  23. package/dist/xyflow/const.d.ts +3 -3
  24. package/dist/xyflow/diagram-to-xyflow.d.ts +1 -1
  25. package/dist/xyflow/edges/RelationshipEdge.d.ts +4 -3
  26. package/dist/xyflow/edges/edges.css.d.ts +1 -0
  27. package/dist/xyflow/edges/utils.d.ts +1 -0
  28. package/dist/xyflow/hooks/index.d.ts +3 -2
  29. package/dist/xyflow/hooks/useXYFlow.d.ts +22 -21
  30. package/dist/xyflow/nodes/compound/CompoundNode.css.d.ts +1 -0
  31. package/dist/xyflow/nodes/element/ElementIcon.d.ts +1 -4
  32. package/dist/xyflow/nodes/element/element.css.d.ts +3 -1
  33. package/dist/xyflow/types.d.ts +2 -32
  34. package/package.json +21 -21
  35. package/src/LikeC4Diagram.css.ts +10 -8
  36. package/src/LikeC4Diagram.props.ts +12 -5
  37. package/src/LikeC4Diagram.tsx +43 -26
  38. package/src/globals.css.ts +11 -4
  39. package/src/index.ts +1 -1
  40. package/src/mantine.css.ts +2 -2
  41. package/src/state/DiagramContext.tsx +47 -16
  42. package/src/state/diagramStore.ts +89 -80
  43. package/src/state/hooks.ts +5 -0
  44. package/src/state/index.ts +1 -3
  45. package/src/state/useDiagramStore.ts +6 -13
  46. package/src/state/useNavigationHistory.ts +39 -0
  47. package/src/theme.css.ts +5 -0
  48. package/src/ui/BackwardForwardPanel.css.ts +22 -0
  49. package/src/ui/BackwardForwardPanel.tsx +59 -0
  50. package/src/ui/DiagramTitlePanel.css.ts +17 -6
  51. package/src/ui/DiagramTitlePanel.tsx +108 -94
  52. package/src/ui/DynamicViewWalkthrough.tsx +6 -4
  53. package/src/ui/OptionsPanel.tsx +37 -18
  54. package/src/ui/options/EdgeOptions.tsx +157 -0
  55. package/src/ui/options/NodeOptions.tsx +37 -29
  56. package/src/xyflow/EdgeMarkers.tsx +148 -0
  57. package/src/xyflow/FitviewOnDiagramChange.tsx +8 -4
  58. package/src/xyflow/SelectEdgesOnNodeFocus.tsx +59 -55
  59. package/src/xyflow/SyncWithDiagram.tsx +13 -20
  60. package/src/xyflow/XYFlow.tsx +2 -4
  61. package/src/xyflow/XYFlowEvents.tsx +48 -33
  62. package/src/xyflow/XYFlowInner.tsx +6 -3
  63. package/src/xyflow/const.ts +3 -3
  64. package/src/xyflow/diagram-to-xyflow.ts +18 -53
  65. package/src/xyflow/edges/RelationshipEdge.tsx +218 -126
  66. package/src/xyflow/edges/edges.css.ts +44 -26
  67. package/src/xyflow/edges/utils.ts +10 -0
  68. package/src/xyflow/hooks/index.ts +4 -2
  69. package/src/xyflow/hooks/useLayoutConstraints.ts +5 -5
  70. package/src/xyflow/hooks/useXYFlow.ts +28 -1
  71. package/src/xyflow/nodes/compound/CompoundNode.css.ts +41 -31
  72. package/src/xyflow/nodes/compound/CompoundNode.tsx +52 -53
  73. package/src/xyflow/nodes/element/ElementIcon.tsx +11 -22
  74. package/src/xyflow/nodes/element/ElementLink.tsx +11 -16
  75. package/src/xyflow/nodes/element/ElementNode.tsx +69 -114
  76. package/src/xyflow/nodes/element/element.css.ts +48 -15
  77. package/src/xyflow/nodes/shared/NavigateToBtn.tsx +1 -1
  78. package/src/xyflow/types.ts +2 -4
  79. package/src/xyflow/utils.ts +3 -6
  80. package/dist/KeepAspectRatioContainer.d.ts +0 -9
  81. package/dist/icons/Clipboard.d.ts +0 -3
  82. package/dist/icons/Link.d.ts +0 -3
  83. package/dist/icons/ZoomIn.d.ts +0 -3
  84. package/dist/icons/index.d.ts +0 -3
  85. package/dist/mantine/theme.d.ts +0 -3
  86. package/dist/state/WhenInitialized.d.ts +0 -3
  87. package/dist/ui/Camera.d.ts +0 -3
  88. package/src/KeepAspectRatioContainer.tsx +0 -36
  89. package/src/icons/Clipboard.tsx +0 -24
  90. package/src/icons/Link.tsx +0 -23
  91. package/src/icons/ZoomIn.tsx +0 -25
  92. package/src/icons/index.ts +0 -3
  93. package/src/mantine/theme.ts +0 -20
  94. package/src/state/WhenInitialized.tsx +0 -24
  95. package/src/ui/Camera.tsx +0 -174
@@ -7,14 +7,16 @@ import {
7
7
  Group,
8
8
  HoverCard,
9
9
  HoverCardDropdown,
10
+ type HoverCardProps,
10
11
  HoverCardTarget,
11
12
  Stack,
12
13
  UnstyledButton
13
14
  } from '@mantine/core'
15
+ import { IconLink } from '@tabler/icons-react'
14
16
  import clsx from 'clsx'
15
17
  import { useId } from 'react'
16
18
  import { clamp } from 'remeda'
17
- import { Link } from '../../../icons'
19
+ import { type DiagramState, useDiagramState } from '../../../state/hooks'
18
20
  import type { XYFlowNode } from '../../types'
19
21
  import { elementLink, trigger } from './ElementLink.css'
20
22
 
@@ -22,23 +24,17 @@ type ElementLinkProps = {
22
24
  element: XYFlowNode['data']['element']
23
25
  }
24
26
 
27
+ const selector = (s: DiagramState) => {
28
+ const target = s.getContainer()
29
+ return target ? { target } : null
30
+ }
31
+
25
32
  export function ElementLink({
26
33
  element
27
34
  }: ElementLinkProps) {
28
35
  invariant(element.links, 'ElementLink: links are required')
29
36
  const id = useId()
30
- // const mantineCtx = useMantineContext()
31
- // const root = mantineCtx.getRootElement()
32
-
33
- // const targetSelector = `.react-flow:has([data-likec4-linkid="${id}"])`
34
- // // const target = root?.querySelector<HTMLDivElement>(targetSelector) ?? targetSelector
35
-
36
- // const portalProps = useMemo(() => ({
37
- // get target(): HTMLElement | string {
38
- // const root = mantineCtx.getRootElement()
39
- // return root?.querySelector<HTMLDivElement>(targetSelector) ?? targetSelector
40
- // }
41
- // }), [targetSelector])
37
+ const portalProps = useDiagramState(selector)
42
38
  return (
43
39
  <div className={elementLink} data-likec4-linkid={id}>
44
40
  <HoverCard
@@ -51,8 +47,7 @@ export function ElementLink({
51
47
  transitionProps={{
52
48
  transition: 'pop'
53
49
  }}
54
- // portalProps={portalProps}
55
- withinPortal={false}
50
+ {...(portalProps ? { portalProps } : { withinPortal: false })}
56
51
  floatingStrategy={'fixed'}
57
52
  openDelay={350}
58
53
  closeDelay={800}
@@ -64,7 +59,7 @@ export function ElementLink({
64
59
  <UnstyledButton
65
60
  className={clsx('nodrag nopan', trigger)}
66
61
  autoFocus={false}>
67
- <Link />
62
+ <IconLink size={12} />
68
63
  <span>links</span>
69
64
  </UnstyledButton>
70
65
  </HoverCardTarget>
@@ -1,13 +1,11 @@
1
1
  import { Text } from '@mantine/core'
2
2
  import { Handle, type NodeProps, Position } from '@xyflow/react'
3
3
  import clsx from 'clsx'
4
- import { DEV } from 'esm-env'
5
4
  import { deepEqual as eq } from 'fast-equals'
6
5
  import { m, type Variants } from 'framer-motion'
7
6
  import { memo } from 'react'
8
7
  import { isNumber } from 'remeda'
9
- import useTilg from 'tilg'
10
- import { useDiagramState } from '../../../state'
8
+ import { useDiagramState } from '../../../state/hooks'
11
9
  import type { ElementXYFlowNode } from '../../types'
12
10
  import { toDomPrecision } from '../../utils'
13
11
  import { NavigateToBtn } from '../shared/NavigateToBtn'
@@ -24,13 +22,13 @@ const variants = {
24
22
  idle: (_, { scale }) => ({
25
23
  scale: 1,
26
24
  transition: {
27
- delay: isNumber(scale) && scale > selectedScale ? 0.075 : 0
25
+ delay: isNumber(scale) && scale > selectedScale ? 0.09 : 0
28
26
  }
29
27
  }),
30
28
  selected: (_, { scale }) => ({
31
29
  scale: selectedScale,
32
30
  transition: {
33
- delay: isNumber(scale) && scale > selectedScale ? 0.075 : 0
31
+ delay: isNumber(scale) && scale > selectedScale ? 0.09 : 0
34
32
  }
35
33
  }),
36
34
  // dimmed: {
@@ -54,12 +52,9 @@ const variants = {
54
52
  // delay: 1
55
53
  // }
56
54
  // }),
57
- hovered: (_, { scale }) => ({
58
- scale: 1.06,
59
- transition: {
60
- delay: isNumber(scale) && scale !== 1 && scale !== selectedScale ? 0 : 0.15
61
- }
62
- }),
55
+ hovered: {
56
+ scale: 1.06
57
+ },
63
58
  tap: {
64
59
  scale: 0.975
65
60
  }
@@ -72,6 +67,7 @@ const isEqualProps = (prev: ElementNodeProps, next: ElementNodeProps) => (
72
67
  prev.id === next.id
73
68
  && eq(prev.selected ?? false, next.selected ?? false)
74
69
  && eq(prev.dragging ?? false, next.dragging ?? false)
70
+ && eq(prev.draggable ?? false, next.draggable ?? false)
75
71
  && eq(prev.width ?? 0, next.width ?? 0)
76
72
  && eq(prev.height ?? 0, next.height ?? 0)
77
73
  && eq(prev.data.element, next.data.element)
@@ -83,11 +79,11 @@ export const ElementNodeMemo = memo<ElementNodeProps>(function ElementNode({
83
79
  element
84
80
  },
85
81
  dragging,
82
+ // draggable = false,
86
83
  selected = false,
87
84
  width,
88
85
  height
89
86
  }) {
90
- DEV && useTilg()
91
87
  const { isHovered, isDimmed, hasOnNavigateTo, isHovercards, isInteractive } = useDiagramState(s => ({
92
88
  isHovered: s.hoveredNodeId === id,
93
89
  isDimmed: s.dimmed.has(id),
@@ -123,122 +119,81 @@ export const ElementNodeMemo = memo<ElementNodeProps>(function ElementNode({
123
119
  // useTilg(animate, isHovered, isInteractive)
124
120
 
125
121
  return (
126
- <m.div
127
- id={id}
128
- className={clsx([
129
- css.container,
130
- isDimmed && css.dimmed,
131
- 'likec4-element-node'
132
- ])}
133
- data-likec4-color={element.color}
134
- data-likec4-shape={element.shape}
135
- variants={variants}
136
- initial={false}
137
- animate={animate}
138
- {...(isInteractive && {
139
- whileTap: dragging ? animate : 'tap'
140
- })}
141
- >
142
- {
143
- /* <NodeToolbar
144
- position={Position.Bottom}
145
- align={'start'}
146
- offset={-10}
147
- isVisible={selected || isHovered}>
148
- <Button>editggg</Button>
149
- </NodeToolbar> */
150
- }
151
- {
152
- /* <NodeResizer minWidth={100} minHeight={30} />
153
- <NodeToolbar
154
- position={Position.Right}
155
- align={'start'}
156
- style={{
157
- background: 'blue'
158
- }}>
159
- <Stack>
160
- <Button>edit</Button>
161
-
162
- </Stack>
163
- </NodeToolbar>*/
164
- }
165
- {
166
- /* {element.inEdges.map((edge) => (
167
- <Handle
168
- key={edge}
169
- id={edge}
170
- type="target"
171
- position={Position.Top}
172
- style={{ visibility: 'hidden' }}
173
- />
174
- ))} */
175
- }
122
+ <>
176
123
  <Handle
177
124
  type="target"
178
125
  position={Position.Top}
179
- style={{ visibility: 'hidden' }}
126
+ className={css.handleCenter}
180
127
  />
181
- <svg
182
- className={clsx(
183
- css.cssShapeSvg
184
- )}
185
- viewBox={`0 0 ${w} ${h}`}
186
- width={w}
187
- height={h}
128
+ <m.div
129
+ id={id}
130
+ className={clsx([
131
+ css.container,
132
+ isDimmed && css.dimmed,
133
+ animate !== 'idle' && css.containerAnimated,
134
+ 'likec4-element-node'
135
+ ])}
136
+ data-hovered={!dragging && isHovered}
137
+ data-likec4-color={element.color}
138
+ data-likec4-shape={element.shape}
139
+ variants={variants}
140
+ initial={false}
141
+ animate={animate}
142
+ {...(isInteractive && {
143
+ whileTap: dragging ? animate : 'tap'
144
+ })}
188
145
  >
189
- <g className={css.indicator}>
190
- <SelectedIndicator
146
+ <svg
147
+ className={clsx(
148
+ css.cssShapeSvg
149
+ )}
150
+ viewBox={`0 0 ${w} ${h}`}
151
+ width={w}
152
+ height={h}
153
+ >
154
+ <g className={css.indicator}>
155
+ <SelectedIndicator
156
+ shape={element.shape}
157
+ w={w}
158
+ h={h}
159
+ />
160
+ </g>
161
+ <ElementShapeSvg
191
162
  shape={element.shape}
192
163
  w={w}
193
164
  h={h}
194
165
  />
195
- </g>
196
- <ElementShapeSvg
197
- shape={element.shape}
198
- w={w}
199
- h={h}
200
- />
201
- </svg>
202
- <div className={clsx(css.element, 'likec4-element')}>
203
- {element.icon && <ElementIcon node={element} />}
204
- <Text
205
- component="div"
206
- className={clsx(css.title, 'likec4-element-title')}>
207
- {element.title}
208
- </Text>
209
- {element.technology && (
166
+ </svg>
167
+ <div className={clsx(css.element, 'likec4-element')}>
168
+ <ElementIcon node={element} />
210
169
  <Text
211
170
  component="div"
212
- className={clsx(css.technology, 'likec4-element-technology')}>
213
- {element.technology}
171
+ className={clsx(css.title, 'likec4-element-title')}>
172
+ {element.title}
214
173
  </Text>
215
- )}
216
- {element.description && (
217
- <Text
218
- component="div"
219
- className={clsx(css.description, 'likec4-element-description')}>
220
- {element.description}
221
- </Text>
222
- )}
223
- </div>
174
+ {element.technology && (
175
+ <Text
176
+ component="div"
177
+ className={clsx(css.technology, 'likec4-element-technology')}>
178
+ {element.technology}
179
+ </Text>
180
+ )}
181
+ {element.description && (
182
+ <Text
183
+ component="div"
184
+ className={clsx(css.description, 'likec4-element-description')}>
185
+ {element.description}
186
+ </Text>
187
+ )}
188
+ </div>
189
+ {isHovercards && element.links && <ElementLink element={element} />}
190
+ {isNavigable && <NavigateToBtn xynodeId={id} className={css.cssNavigateBtn} />}
191
+ </m.div>
224
192
  <Handle
225
193
  type="source"
226
- position={Position.Bottom}
227
- style={{ visibility: 'hidden' }}
194
+ position={Position.Top}
195
+ className={css.handleCenter}
228
196
  />
229
- {
230
- /* {element.outEdges.map((edge) => (
231
- <Handle
232
- key={edge}
233
- id={edge}
234
- type="source"
235
- position={Position.Bottom}
236
- style={{ visibility: 'hidden' }}
237
- />
238
- ))} */
239
- }
240
- {isHovercards && element.links && <ElementLink element={element} />}
241
- {isNavigable && <NavigateToBtn xynodeId={id} className={css.cssNavigateBtn} />}
242
- </m.div>
197
+ </>
243
198
  )
244
199
  }, isEqualProps)
@@ -1,5 +1,6 @@
1
1
  import { rem } from '@mantine/core'
2
2
  import { createVar, fallbackVar, globalStyle, keyframes, style } from '@vanilla-extract/css'
3
+ import { calc } from '@vanilla-extract/css-utils'
3
4
  import { mantine } from '../../../mantine.css'
4
5
  import { vars } from '../../../theme.css'
5
6
 
@@ -16,16 +17,34 @@ export const container = style({
16
17
  alignItems: 'stretch',
17
18
  vars: {
18
19
  [stokeFillMix]: `color-mix(in srgb, ${vars.element.stroke} 90%, ${vars.element.fill})`
20
+ },
21
+ selectors: {
22
+ ':where(.react-flow__node.selected) &': {
23
+ willChange: 'transform'
24
+ },
25
+ '&[data-hovered="true"]': {
26
+ willChange: 'transform'
27
+ }
19
28
  }
20
29
  })
21
30
 
31
+ export const handleCenter = style({
32
+ top: '50%',
33
+ left: '50%',
34
+ visibility: 'hidden'
35
+ })
36
+
37
+ export const containerAnimated = style({
38
+ willChange: 'transform'
39
+ })
40
+
22
41
  export const dimmed = style({})
23
42
 
24
43
  globalStyle(`.react-flow__node-element:has(${dimmed})`, {
25
44
  opacity: 0.25,
26
45
  transition: 'opacity 600ms ease-in-out, filter 600ms ease-in-out',
27
46
  transitionDelay: '200ms',
28
- filter: 'grayscale(0.85) blur(2px)',
47
+ filter: `grayscale(0.85) ${fallbackVar(vars.safariAnimationHook, 'blur(2px)')}`,
29
48
  willChange: 'opacity, filter'
30
49
  })
31
50
 
@@ -44,21 +63,27 @@ const outlineColor = fallbackVar(
44
63
  vars.element.stroke
45
64
  )
46
65
 
66
+ const indicatorStroke = createVar('indicator-stroke')
67
+
47
68
  export const indicator = style({
48
- stroke: vars.element.loContrast,
69
+ stroke: indicatorStroke,
70
+ fill: 'none',
49
71
  transformOrigin: 'center center',
50
72
  strokeWidth: 6,
51
73
  animationDuration: '800ms',
52
- animationName: indicatorKeyframes,
53
74
  animationIterationCount: 'infinite',
54
75
  animationDirection: 'alternate',
76
+ opacity: 0.6,
55
77
  visibility: 'hidden',
78
+ vars: {
79
+ [indicatorStroke]: vars.element.loContrast
80
+ },
56
81
  selectors: {
57
82
  ':where(.react-flow__node.selected) &': {
58
- visibility: 'visible'
83
+ visibility: 'visible',
84
+ animationName: fallbackVar(vars.safariAnimationHook, indicatorKeyframes)
59
85
  },
60
86
  [`:where(.react-flow__node:focus-visible, ${container}:focus-visible) &`]: {
61
- animationName: 'none',
62
87
  strokeWidth: 10,
63
88
  stroke: outlineColor,
64
89
  visibility: 'visible'
@@ -66,8 +91,14 @@ export const indicator = style({
66
91
  ':where([data-likec4-shape="queue"], [data-likec4-shape="cylinder"], [data-likec4-shape="storage"]) &': {
67
92
  strokeWidth: 10
68
93
  },
94
+ [`:where([data-mantine-color-scheme='light']) &`]: {
95
+ vars: {
96
+ [indicatorStroke]: `color-mix(in srgb, ${vars.element.fill} 60%, ${vars.element.loContrast})`
97
+ }
98
+ },
69
99
  [`${dimmed} &`]: {
70
- visibility: 'hidden'
100
+ visibility: 'hidden',
101
+ display: 'none'
71
102
  }
72
103
  }
73
104
  })
@@ -91,7 +122,7 @@ export const title = style({
91
122
  fontStyle: 'normal',
92
123
  textAlign: 'center',
93
124
  fontWeight: 500,
94
- fontSize: rem(19),
125
+ fontSize: rem(19.5),
95
126
  lineHeight: 1.2,
96
127
  textWrap: 'balance',
97
128
  color: vars.element.hiContrast
@@ -162,34 +193,34 @@ export const element = style({
162
193
  }
163
194
  })
164
195
 
165
- export const iconMaxH = createVar('max-h')
196
+ export const iconOffsetY = createVar('offset-y')
197
+
198
+ const iconMaxH = createVar('max-h')
166
199
 
167
200
  export const elementIcon = style({
168
201
  flex: `0 1 ${iconMaxH}`,
169
202
  maxHeight: iconMaxH,
170
- marginTop: -8,
171
203
  position: 'relative',
172
204
  userSelect: 'none',
173
205
  pointerEvents: 'none',
174
206
  overflow: 'visible',
175
207
  mixBlendMode: 'hard-light',
176
208
  'vars': {
177
- [iconMaxH]: '30px'
209
+ [iconMaxH]: calc(iconOffsetY).subtract('12px').toString()
178
210
  }
179
211
  })
180
212
 
181
213
  globalStyle(`${elementIcon} img`, {
182
214
  position: 'absolute',
183
215
  left: 0,
184
- bottom: 0,
216
+ bottom: 4,
185
217
  width: '100%',
186
218
  height: 'auto',
187
219
  objectFit: 'contain',
188
- maxHeight: `calc(${iconMaxH} + 16px)`
220
+ maxHeight: iconOffsetY
189
221
  })
190
222
 
191
223
  const filterShadow = createVar('filter-shadow')
192
- const filterShadowHovered = createVar('filter-shadow-hovered')
193
224
 
194
225
  export const cssShapeSvg = style({
195
226
  top: '0px',
@@ -199,7 +230,7 @@ export const cssShapeSvg = style({
199
230
  fill: vars.element.fill,
200
231
  stroke: vars.element.stroke,
201
232
  overflow: 'visible',
202
- filter: fallbackVar(filterShadowHovered, filterShadow),
233
+ filter: filterShadow,
203
234
  transition: 'filter 300ms ease-out',
204
235
  transitionDelay: '0ms',
205
236
  zIndex: -1,
@@ -212,7 +243,9 @@ export const cssShapeSvg = style({
212
243
  },
213
244
  selectors: {
214
245
  [`:where(.react-flow__node.selected, .react-flow__node:focus-visible, ${container}:focus-visible) &`]: {
215
- filter: 'none'
246
+ vars: {
247
+ [filterShadow]: `none`
248
+ }
216
249
  }
217
250
  }
218
251
  })
@@ -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/hooks'
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,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
- ))