@likec4/diagram 1.20.3 → 1.21.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 (90) hide show
  1. package/README.md +2 -2
  2. package/dist/base/BaseXYFlow.js +1 -1
  3. package/dist/base/example/_types.d.ts +3 -3
  4. package/dist/base/example/custom.d.ts +3 -2
  5. package/dist/base/primitives/compound/CompoundActionButton.js +1 -1
  6. package/dist/base/primitives/compound/CompoundDetailsButton.js +1 -1
  7. package/dist/base/primitives/compound/CompoundNodeContainer.js +1 -1
  8. package/dist/base/primitives/compound/CompoundTitle.css.d.ts +1 -0
  9. package/dist/base/primitives/compound/CompoundTitle.css.js +2 -0
  10. package/dist/base/primitives/compound/CompoundTitle.d.ts +2 -2
  11. package/dist/base/primitives/compound/CompoundTitle.js +17 -6
  12. package/dist/base/primitives/edge/EdgeLabel.js +1 -1
  13. package/dist/base/primitives/element/ElementActionButtons.js +1 -1
  14. package/dist/base/primitives/element/ElementDetailsButton.js +1 -1
  15. package/dist/base/primitives/element/ElementNodeContainer.d.ts +1 -1
  16. package/dist/base/primitives/element/ElementNodeContainer.js +15 -0
  17. package/dist/base/primitives/element/ElementShape.js +1 -1
  18. package/dist/base/primitives/element/ElementTitle.css.d.ts +0 -1
  19. package/dist/base/primitives/element/ElementTitle.css.js +8 -8
  20. package/dist/base/primitives/element/ElementTitle.d.ts +1 -1
  21. package/dist/base/primitives/element/ElementTitle.js +4 -2
  22. package/dist/base/primitives/element/styles.css.d.ts +3 -0
  23. package/dist/base/primitives/element/styles.css.js +6 -0
  24. package/dist/context/DiagramEventHandlers.js +1 -1
  25. package/dist/context/DiagramFeatures.js +1 -1
  26. package/dist/context/RootContainer.js +1 -1
  27. package/dist/hooks/useDiagram.d.ts +1 -2
  28. package/dist/hooks/useXYFlow.js +1 -1
  29. package/dist/likec4diagram/DiagramUI.d.ts +1 -2
  30. package/dist/likec4diagram/DiagramUI.js +3 -3
  31. package/dist/likec4diagram/XYFlow.js +1 -1
  32. package/dist/likec4diagram/custom/edges/NotePopover.js +1 -1
  33. package/dist/likec4diagram/custom/edges/RelationshipEdge.js +1 -1
  34. package/dist/likec4diagram/custom/edges/RelationshipsDropdownMenu.js +4 -4
  35. package/dist/likec4diagram/custom/nodes/nodeTypes.js +8 -8
  36. package/dist/likec4diagram/custom/nodes/toolbar/_shared.js +2 -2
  37. package/dist/likec4diagram/state/assign.js +1 -1
  38. package/dist/likec4diagram/state/machine.js +5 -5
  39. package/dist/likec4diagram/types.d.ts +2 -2
  40. package/dist/likec4diagram/ui/controls/Controls.js +1 -1
  41. package/dist/likec4diagram/ui/diagram-title/DiagramTitlePanel.js +1 -1
  42. package/dist/likec4diagram/ui/walkthrough/DynamicViewWalkthrough.js +2 -2
  43. package/dist/likec4diagram/useViewToNodesEdges.js +1 -1
  44. package/dist/overlays/Overlays.js +42 -21
  45. package/dist/overlays/element-details/ElementDetailsCard.d.ts +7 -3
  46. package/dist/overlays/element-details/ElementDetailsCard.js +38 -39
  47. package/dist/overlays/element-details/TabPanelDeployments.js +1 -1
  48. package/dist/overlays/element-details/TabPanelRelationships.js +14 -30
  49. package/dist/overlays/overlay/Overlay.css.js +2 -1
  50. package/dist/overlays/overlay/Overlay.js +2 -2
  51. package/dist/overlays/relationship-details/SelectEdge.js +1 -1
  52. package/dist/overlays/relationship-details/_types.d.ts +3 -3
  53. package/dist/overlays/relationship-details/actor.js +1 -1
  54. package/dist/overlays/relationship-details/custom/nodeTypes.d.ts +3 -3
  55. package/dist/overlays/relationship-details/custom/nodeTypes.js +2 -2
  56. package/dist/overlays/relationship-details/useLayoutedDetails.js +1 -4
  57. package/dist/overlays/relationships-browser/-useRelationshipsView.js +0 -3
  58. package/dist/overlays/relationships-browser/RelationshipsBrowser.js +3 -3
  59. package/dist/overlays/relationships-browser/_types.d.ts +3 -3
  60. package/dist/overlays/relationships-browser/actor.js +16 -16
  61. package/dist/overlays/relationships-browser/custom/nodeTypes.d.ts +3 -2
  62. package/dist/overlays/relationships-browser/custom/nodeTypes.js +3 -3
  63. package/dist/overlays/relationships-browser/useViewToNodesEdges.js +3 -2
  64. package/dist/style.css +1 -1
  65. package/package.json +12 -12
  66. package/src/base/example/_types.ts +3 -2
  67. package/src/base/example/useViewToNodesEdges.ts +2 -1
  68. package/src/base/primitives/compound/CompoundTitle.css.ts +27 -1
  69. package/src/base/primitives/compound/CompoundTitle.tsx +12 -2
  70. package/src/base/primitives/element/ElementNodeContainer.tsx +21 -1
  71. package/src/base/primitives/element/ElementShape.css.ts +5 -0
  72. package/src/base/primitives/element/ElementTitle.css.ts +17 -24
  73. package/src/base/primitives/element/ElementTitle.tsx +4 -2
  74. package/src/base/primitives/element/styles.css.ts +74 -0
  75. package/src/hooks/useDiagram.ts +1 -1
  76. package/src/likec4diagram/DiagramUI.tsx +2 -2
  77. package/src/likec4diagram/XYFlow.tsx +2 -2
  78. package/src/likec4diagram/custom/edges/RelationshipsDropdownMenu.tsx +3 -2
  79. package/src/likec4diagram/types.ts +2 -2
  80. package/src/likec4diagram/useViewToNodesEdges.ts +1 -1
  81. package/src/overlays/Overlays.tsx +61 -281
  82. package/src/overlays/element-details/ElementDetailsCard.tsx +213 -257
  83. package/src/overlays/element-details/TabPanelRelationships.tsx +13 -75
  84. package/src/overlays/overlay/Overlay.tsx +1 -1
  85. package/src/overlays/relationship-details/_types.ts +3 -3
  86. package/src/overlays/relationship-details/useLayoutedDetails.ts +1 -1
  87. package/src/overlays/relationships-browser/RelationshipsBrowser.tsx +44 -55
  88. package/src/overlays/relationships-browser/_types.ts +12 -2
  89. package/src/overlays/relationships-browser/actor.ts +11 -10
  90. package/src/overlays/relationships-browser/useViewToNodesEdges.ts +2 -1
@@ -1,21 +1,20 @@
1
1
  import { Box, Button, Code, Group, Notification } from '@mantine/core'
2
+ import { useCallbackRef } from '@mantine/hooks'
2
3
  import { IconX } from '@tabler/icons-react'
3
- import { AnimatePresence, useReducedMotion } from 'framer-motion'
4
+ import { deepEqual } from 'fast-equals'
5
+ import { useReducedMotion } from 'framer-motion'
4
6
  import { animate } from 'framer-motion/dom'
5
7
  import { memo, useEffect, useMemo } from 'react'
6
8
  import { type FallbackProps, ErrorBoundary } from 'react-error-boundary'
7
9
  import { DiagramFeatures } from '../context'
8
10
  import { useXYStore } from '../hooks'
9
- import { useDiagramActor, useDiagramActorState } from '../hooks/useDiagramActor'
11
+ import { useDiagram } from '../hooks/useDiagram'
12
+ import { useDiagramActorState } from '../hooks/useDiagramActor'
13
+ import type { MachineSnapshot } from '../likec4diagram/state/machine'
10
14
  import { ElementDetailsCard } from './element-details/ElementDetailsCard'
11
15
  import { Overlay } from './overlay/Overlay'
12
16
  import { RelationshipDetails } from './relationship-details/RelationshipDetails'
13
17
  import { RelationshipsBrowser } from './relationships-browser/RelationshipsBrowser'
14
- // import { EdgeDetailsXYFlow } from './edge-details/EdgeDetailsXYFlow'
15
- // import { ElementDetailsCard } from './element-details/ElementDetailsCard'
16
- // import { OverlayContext, useOverlayDialog } from './OverlayContext'
17
- // import * as css from './Overlays.css'
18
- // import { RelationshipsOverlay } from './relationships-of/RelationshipsOverlay'
19
18
 
20
19
  function Fallback({ error, resetErrorBoundary }: FallbackProps) {
21
20
  const errorString = error instanceof Error ? error.message : 'Unknown error'
@@ -41,21 +40,36 @@ function Fallback({ error, resetErrorBoundary }: FallbackProps) {
41
40
  )
42
41
  }
43
42
 
43
+ const selector = (s: MachineSnapshot) => ({
44
+ relationshipsBrowserActor: s.children.relationshipsBrowser,
45
+ relationshipDetailsActor: s.children.relationshipDetails,
46
+ viewId: s.context.view.id,
47
+ activeElementDetailsOf: s.context.activeElementDetails?.fqn ?? null,
48
+ fromNode: s.context.activeElementDetails?.fromNode ?? null,
49
+ rectFromNode: s.context.activeElementDetails?.nodeRectScreen ?? null,
50
+ })
51
+ const equals = (a: ReturnType<typeof selector>, b: ReturnType<typeof selector>) =>
52
+ a.relationshipDetailsActor == b.relationshipDetailsActor &&
53
+ a.relationshipsBrowserActor == b.relationshipsBrowserActor &&
54
+ a.activeElementDetailsOf === b.activeElementDetailsOf &&
55
+ a.viewId === b.viewId &&
56
+ a.fromNode === b.fromNode &&
57
+ deepEqual(a.rectFromNode, b.rectFromNode)
58
+
44
59
  export const Overlays = memo(() => {
45
60
  const xyflowDomNode = useXYStore(s => s.domNode)
46
61
  const xyflowRendererDom = useMemo(() => xyflowDomNode?.querySelector('.react-flow__renderer') ?? null, [
47
62
  xyflowDomNode,
48
63
  ])
49
- const { send } = useDiagramActor()
64
+ const diagram = useDiagram()
50
65
  const {
51
66
  relationshipsBrowserActor,
52
67
  relationshipDetailsActor,
53
68
  activeElementDetailsOf,
54
- } = useDiagramActorState(s => ({
55
- relationshipsBrowserActor: s.children.relationshipsBrowser,
56
- relationshipDetailsActor: s.children.relationshipDetails,
57
- activeElementDetailsOf: s.context.activeElementDetails?.fqn ?? null,
58
- }))
69
+ viewId,
70
+ fromNode,
71
+ rectFromNode,
72
+ } = useDiagramActorState(selector, equals)
59
73
 
60
74
  const isMotionReduced = useReducedMotion() ?? false
61
75
 
@@ -72,278 +86,44 @@ export const Overlays = memo(() => {
72
86
  })
73
87
  }, [isActiveOverlay, xyflowRendererDom])
74
88
 
75
- // )
76
- // const diagramStore = useDiagramStoreApi()
77
- // const {
78
- // activeOverlay,
79
- // viewId,
80
- // } = useDiagramState(s => ({
81
- // activeOverlay: s.activeOverlay,
82
- // viewId: s.view.id,
83
- // }))
84
-
85
- // const onCloseCbRef = useRef<(() => void)>(undefined)
86
-
87
- // const ctxValue = useMemo(() => ({
88
- // openOverlay: ((overlay) => {
89
- // diagramStore.getState().openOverlay(overlay)
90
- // }) as DiagramState['openOverlay'],
91
- // close: (cb?: () => void) => {
92
- // onCloseCbRef.current = cb
93
- // diagramStore.getState().closeOverlay()
94
- // },
95
- // }), [diagramStore])
96
-
97
- // const onExitComplete = () => {
98
- // onCloseCbRef.current?.()
99
- // onCloseCbRef.current = undefined
100
- // }
101
-
102
- // const isActive = !!activeOverlay
103
- // useHotkeys(
104
- // isActive
105
- // ? [
106
- // ['Escape', (e) => {
107
- // e.stopPropagation()
108
- // ctxValue.close()
109
- // }, { preventDefault: true }],
110
- // ]
111
- // : [],
112
- // )
89
+ const onClose = useCallbackRef(() => {
90
+ diagram.closeOverlay()
91
+ // relationshipsBrowserActor?.send({ type: 'close' })
92
+ // relationshipDetailsActor?.send({ type: 'close' })
93
+ // send({ type: 'close.overlay' })
94
+ })
113
95
 
114
96
  return (
115
97
  <DiagramFeatures.Overlays>
116
- <ErrorBoundary FallbackComponent={Fallback} onReset={() => send({ type: 'close.overlay' })}>
117
- <AnimatePresence>
118
- {relationshipsBrowserActor && (
119
- <Overlay
120
- key={'relationships-browser'}
121
- onClose={() => {
122
- relationshipsBrowserActor.send({ type: 'close' })
123
- }}>
124
- <RelationshipsBrowser actorRef={relationshipsBrowserActor} />
125
- </Overlay>
126
- )}
127
- {relationshipDetailsActor && (
128
- <Overlay
129
- key={'relationship-details'}
130
- onClose={() => {
131
- relationshipDetailsActor.send({ type: 'close' })
132
- }}>
133
- <RelationshipDetails actorRef={relationshipDetailsActor} />
134
- </Overlay>
135
- )}
136
- {activeElementDetailsOf && <ElementDetailsCard fqn={activeElementDetailsOf} />}
137
- </AnimatePresence>
98
+ <ErrorBoundary FallbackComponent={Fallback} onReset={onClose}>
99
+ {relationshipsBrowserActor && (
100
+ <Overlay
101
+ key={'relationships-browser'}
102
+ onClose={onClose}>
103
+ <RelationshipsBrowser actorRef={relationshipsBrowserActor} />
104
+ </Overlay>
105
+ )}
106
+ {relationshipDetailsActor && (
107
+ <Overlay
108
+ key={'relationship-details'}
109
+ onClose={onClose}>
110
+ <RelationshipDetails actorRef={relationshipDetailsActor} />
111
+ </Overlay>
112
+ )}
113
+
114
+ {/* TODO: Somehow ElementDetailsCard does not work properly inside AnimatePresence} */}
115
+ {!!activeElementDetailsOf && (
116
+ <ElementDetailsCard
117
+ key={'element-details'}
118
+ fqn={activeElementDetailsOf}
119
+ viewId={viewId}
120
+ fromNode={fromNode}
121
+ rectFromNode={rectFromNode}
122
+ onClose={onClose}
123
+ />
124
+ )}
138
125
  </ErrorBoundary>
139
126
  </DiagramFeatures.Overlays>
140
- // <OverlayContext.Provider value={ctxValue}>
141
- // <ErrorBoundary FallbackComponent={Fallback} onReset={() => ctxValue.close()}>
142
- // <AnimatePresence initial={false} key={viewId} onExitComplete={onExitComplete}>
143
- // {activeOverlay?.elementDetails && (
144
- // <ElementDetailsCard key={'details card'} fqn={activeOverlay.elementDetails} />
145
- // )}
146
- // </AnimatePresence>
147
- // <AnimatePresence initial={false} onExitComplete={onExitComplete}>
148
- // {activeOverlay && isNullish(activeOverlay.elementDetails) && (
149
- // <RemoveScroll forwardProps>
150
- // <Box
151
- // component={m.div}
152
- // className={css.container}
153
- // data-likec4-color="gray"
154
- // initial={{
155
- // '--backdrop-blur': '0px',
156
- // '--backdrop-opacity': '0%',
157
- // opacity: 0,
158
- // translateY: -15,
159
- // }}
160
- // animate={{
161
- // '--backdrop-blur': '10px',
162
- // '--backdrop-opacity': '70%',
163
- // opacity: 1,
164
- // translateY: 0,
165
- // }}
166
- // exit={{
167
- // '--backdrop-blur': '1px',
168
- // '--backdrop-opacity': '0%',
169
- // translateY: -5,
170
- // opacity: 0,
171
- // transition: {
172
- // duration: .2,
173
- // },
174
- // }}
175
- // >
176
- // <FocusTrap>
177
- // {activeOverlay.relationshipsOf && <RelationshipsOverlay subjectId={activeOverlay.relationshipsOf} />}
178
- // {activeOverlay.edgeDetails && (
179
- // <XYFlowProvider
180
- // defaultNodes={[]}
181
- // defaultEdges={[]}>
182
- // <EdgeDetailsXYFlow edgeId={activeOverlay.edgeDetails} />
183
- // </XYFlowProvider>
184
- // )}
185
- // <Box pos={'absolute'} top={'1rem'} right={'1rem'}>
186
- // <ActionIcon
187
- // variant="default"
188
- // // color="gray"
189
- // size={'lg'}
190
- // // data-autofocus
191
- // // autoFocus
192
- // onClick={(e) => {
193
- // e.stopPropagation()
194
- // ctxValue.close()
195
- // }}>
196
- // <IconX />
197
- // </ActionIcon>
198
- // </Box>
199
- // </FocusTrap>
200
- // </Box>
201
- // </RemoveScroll>
202
- // )}
203
- // </AnimatePresence>
204
- // </ErrorBoundary>
205
- // </OverlayContext.Provider>
206
127
  )
207
128
  })
208
-
209
- // const OverlayDialogCloseButton = () => {
210
- // const { close } = useOverlayDialog()
211
- // return (
212
- // <Box pos={'absolute'} top={'1rem'} right={'1rem'}>
213
- // <ActionIcon
214
- // variant="default"
215
- // // color="gray"
216
- // size={'lg'}
217
- // autoFocus
218
- // onClick={(e) => {
219
- // e.stopPropagation()
220
- // close()
221
- // }}>
222
- // <IconX />
223
- // </ActionIcon>
224
- // </Box>
225
- // )
226
- // }
227
-
228
- // type OverlayDialogProps = Pick<HTMLAttributes<HTMLDialogElement>, 'style' | 'className'> & {
229
- // onClose?: (() => void) | undefined
230
- // children: (renderProps: {
231
- // opened: boolean
232
- // close: () => void
233
- // }) => ReactNode
234
- // }
235
-
236
- // const OverlayDialog = forwardRef<HTMLDialogElement, OverlayDialogProps>(({
237
- // className,
238
- // children,
239
- // onClose,
240
- // ...props
241
- // }, forwardedRef) => {
242
- // const onCloseRef = useSyncedRef(onClose)
243
- // const api = useDiagramStoreApi()
244
- // const [opened, setOpened] = useState(false)
245
- // const dialogRef = useRef<HTMLDialogElement>(null)
246
- // const ref = useMergedRef(dialogRef, forwardedRef)
247
-
248
- // // useDebouncedEffect(
249
- // // () => {
250
- // // dialogRef.current?.showModal()
251
- // // },
252
- // // [],
253
- // // 30
254
- // // )
255
-
256
- // useDebouncedEffect(
257
- // () => {
258
- // setOpened(true)
259
- // },
260
- // [],
261
- // 80
262
- // )
263
-
264
- // const { start: triggerOnClose } = useTimeout(() => {
265
- // onCloseRef.current?.()
266
- // }, 300)
267
-
268
- // const ctxValue = useMemo(() => ({
269
- // openOverlay: api.getState().openOverlay,
270
- // close: () => {
271
- // dialogRef.current?.close()
272
- // }
273
- // }), [api])
274
-
275
- // return (
276
- // <OverlayContext.Provider value={ctxValue}>
277
- // <div
278
- // aria-modal="true"
279
- // ref={ref}
280
- // className={clsx(css.dialog, className)}
281
- // onClick={e => {
282
- // if ((e.target as any)?.nodeName?.toUpperCase() === 'DIALOG') {
283
- // e.stopPropagation()
284
- // dialogRef.current?.close()
285
- // }
286
- // }}
287
- // onClose={e => {
288
- // e.stopPropagation()
289
- // triggerOnClose()
290
- // }}
291
- // {...props}
292
- // >
293
- // {children({
294
- // opened,
295
- // ...ctxValue
296
- // })}
297
- // </div>
298
- // </OverlayContext.Provider>
299
- // )
300
- // })
301
-
302
- // const OverlayDialogCloseButton = () => {
303
- // const { close } = useOverlayDialog()
304
- // return (
305
- // <Box pos={'absolute'} top={'1rem'} right={'1rem'}>
306
- // <ActionIcon
307
- // variant="default"
308
- // // color="gray"
309
- // size={'lg'}
310
- // autoFocus
311
- // onClick={(e) => {
312
- // e.stopPropagation()
313
- // close()
314
- // }}>
315
- // <IconX />
316
- // </ActionIcon>
317
- // </Box>
318
- // )
319
- // }
320
- // const OverlayDialog = ({ children }: PropsWithChildren) => {
321
- // const overlay = useOverlayDialog()
322
- // const ref = useRef<HTMLDialogElement>(null)
323
- // useEffect(() => {
324
- // ref.current?.showModal()
325
- // }, [])
326
- // return (
327
- // <m.dialog
328
- // ref={ref}
329
- // exit={{
330
- // opacity: 0,
331
- // transition: {
332
- // duration: .15,
333
- // },
334
- // }}
335
- // onClick={e => {
336
- // if ((e.target as any)?.nodeName?.toUpperCase() === 'DIALOG') {
337
- // e.stopPropagation()
338
- // ref.current?.close()
339
- // }
340
- // }}
341
- // onClose={e => {
342
- // e.stopPropagation()
343
- // overlay.close()
344
- // }}
345
- // >
346
- // {children}
347
- // </m.dialog>
348
- // )
349
- // }
129
+ Overlays.displayName = 'Overlays'