@likec4/diagram 1.21.0 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/dist/LikeC4Diagram.js +9 -13
  2. package/dist/base/BaseXYFlow.js +0 -1
  3. package/dist/base/index.d.ts +0 -1
  4. package/dist/base/primitives/compound/CompoundNodeContainer.js +2 -2
  5. package/dist/base/primitives/edge/EdgeLabel.js +2 -2
  6. package/dist/base/primitives/element/ElementNodeContainer.d.ts +6 -1
  7. package/dist/base/primitives/element/ElementNodeContainer.js +31 -13
  8. package/dist/base/primitives/element/ElementTitle.js +7 -3
  9. package/dist/base/primitives/element/styles.css.js +1 -1
  10. package/dist/{base → components}/Link.css.js +3 -3
  11. package/dist/components/SearchControl.css.d.ts +2 -0
  12. package/dist/components/SearchControl.css.js +7 -0
  13. package/dist/components/SearchControl.d.ts +5 -0
  14. package/dist/components/SearchControl.js +17 -0
  15. package/dist/context/IconRenderer.d.ts +10 -0
  16. package/dist/context/IconRenderer.js +34 -0
  17. package/dist/hooks/index.d.ts +0 -1
  18. package/dist/hooks/useDiagram.d.ts +4 -4
  19. package/dist/index.d.ts +1 -1
  20. package/dist/likec4diagram/DiagramUI.js +1 -4
  21. package/dist/likec4diagram/XYFlow.d.ts +6 -1
  22. package/dist/likec4diagram/XYFlow.js +28 -29
  23. package/dist/likec4diagram/custom/edges/RelationshipsDropdownMenu.js +3 -1
  24. package/dist/likec4diagram/state/actorContext.d.ts +16 -16
  25. package/dist/likec4diagram/state/assign.js +1 -1
  26. package/dist/likec4diagram/state/machine.d.ts +7 -7
  27. package/dist/likec4diagram/state/machine.js +10 -7
  28. package/dist/likec4diagram/ui/controls/Controls.js +63 -48
  29. package/dist/likec4diagram/ui/controls/NavigationButtons.js +44 -69
  30. package/dist/likec4diagram/ui/controls/_shared.js +1 -1
  31. package/dist/likec4diagram/ui/diagram-title/DiagramTitlePanel.js +5 -4
  32. package/dist/likec4diagram/ui/index.d.ts +2 -0
  33. package/dist/likec4diagram/ui/search/ElementsColumn.css.d.ts +15 -0
  34. package/dist/likec4diagram/ui/search/ElementsColumn.css.js +30 -0
  35. package/dist/likec4diagram/ui/search/ElementsColumn.d.ts +1 -0
  36. package/dist/likec4diagram/ui/search/ElementsColumn.js +243 -0
  37. package/dist/likec4diagram/ui/search/LikeC4Search.css.d.ts +8 -0
  38. package/dist/likec4diagram/ui/search/LikeC4Search.css.js +20 -0
  39. package/dist/likec4diagram/ui/search/LikeC4Search.d.ts +1 -0
  40. package/dist/likec4diagram/ui/search/LikeC4Search.js +265 -0
  41. package/dist/likec4diagram/ui/search/SearchInput.d.ts +1 -0
  42. package/dist/likec4diagram/ui/search/SearchInput.js +196 -0
  43. package/dist/likec4diagram/ui/search/ViewsColum.d.ts +9 -0
  44. package/dist/likec4diagram/ui/search/ViewsColum.js +130 -0
  45. package/dist/likec4diagram/ui/search/ViewsColumn.css.d.ts +5 -0
  46. package/dist/likec4diagram/ui/search/ViewsColumn.css.js +12 -0
  47. package/dist/likec4diagram/ui/search/_shared.css.d.ts +16 -0
  48. package/dist/likec4diagram/ui/search/_shared.css.js +5 -0
  49. package/dist/likec4diagram/ui/search/state.d.ts +19 -0
  50. package/dist/likec4diagram/ui/search/state.js +72 -0
  51. package/dist/likec4diagram/ui/search/utils.d.ts +3 -0
  52. package/dist/likec4diagram/ui/search/utils.js +23 -0
  53. package/dist/likec4diagram/useLayoutConstraints.js +4 -5
  54. package/dist/likec4model/useLikeC4ElementsTree.d.ts +1 -0
  55. package/dist/likec4model/useLikeC4ElementsTree.js +1 -0
  56. package/dist/overlays/Overlays.js +10 -10
  57. package/dist/overlays/element-details/ElementDetailsCard.js +20 -13
  58. package/dist/overlays/element-details/TabPanelDeployments.js +4 -2
  59. package/dist/overlays/overlay/Overlay.d.ts +6 -2
  60. package/dist/overlays/overlay/Overlay.js +18 -29
  61. package/dist/overlays/relationship-details/SelectEdge.js +1 -3
  62. package/dist/overlays/relationships-browser/RelationshipsBrowser.js +6 -5
  63. package/dist/overlays/relationships-browser/SelectElement.js +10 -6
  64. package/dist/overlays/relationships-browser/actor.d.ts +2 -2
  65. package/dist/overlays/relationships-browser/actor.js +8 -8
  66. package/dist/overlays/relationships-browser/custom/nodeTypes.js +2 -2
  67. package/dist/style.css +1 -1
  68. package/package.json +15 -14
  69. package/src/LikeC4Diagram.tsx +0 -1
  70. package/src/base/BaseXYFlow.tsx +0 -1
  71. package/src/base/index.ts +0 -2
  72. package/src/base/primitives/element/ElementNodeContainer.css.ts +4 -7
  73. package/src/base/primitives/element/ElementNodeContainer.tsx +36 -16
  74. package/src/base/primitives/element/ElementTitle.css.ts +12 -9
  75. package/src/base/primitives/element/ElementTitle.tsx +6 -2
  76. package/src/base/primitives/element/styles.css.ts +18 -40
  77. package/src/{base → components}/Link.css.ts +3 -3
  78. package/src/components/SearchControl.css.ts +69 -0
  79. package/src/components/SearchControl.tsx +33 -0
  80. package/src/context/IconRenderer.tsx +54 -1
  81. package/src/hooks/index.ts +0 -1
  82. package/src/index.ts +15 -1
  83. package/src/likec4diagram/DiagramUI.tsx +1 -8
  84. package/src/likec4diagram/XYFlow.tsx +30 -30
  85. package/src/likec4diagram/custom/edges/RelationshipEdge.tsx +0 -1
  86. package/src/likec4diagram/custom/edges/RelationshipsDropdownMenu.css.ts +1 -0
  87. package/src/likec4diagram/custom/edges/RelationshipsDropdownMenu.tsx +3 -1
  88. package/src/likec4diagram/state/assign.ts +1 -1
  89. package/src/likec4diagram/state/machine.ts +12 -10
  90. package/src/likec4diagram/ui/controls/Controls.tsx +35 -25
  91. package/src/likec4diagram/ui/controls/NavigationButtons.tsx +36 -58
  92. package/src/likec4diagram/ui/controls/styles.css.ts +3 -1
  93. package/src/likec4diagram/ui/diagram-title/DiagramTitlePanel.tsx +111 -108
  94. package/src/likec4diagram/ui/index.ts +2 -0
  95. package/src/likec4diagram/ui/notation/NotationPanel.tsx +2 -3
  96. package/src/likec4diagram/ui/search/ElementsColumn.css.ts +119 -0
  97. package/src/likec4diagram/ui/search/ElementsColumn.tsx +291 -0
  98. package/src/likec4diagram/ui/search/LikeC4Search.css.ts +117 -0
  99. package/src/likec4diagram/ui/search/LikeC4Search.tsx +312 -0
  100. package/src/likec4diagram/ui/search/SearchInput.tsx +235 -0
  101. package/src/likec4diagram/ui/search/ViewsColum.tsx +158 -0
  102. package/src/likec4diagram/ui/search/ViewsColumn.css.ts +37 -0
  103. package/src/likec4diagram/ui/search/_shared.css.ts +104 -0
  104. package/src/likec4diagram/ui/search/state.ts +76 -0
  105. package/src/likec4diagram/ui/search/utils.ts +20 -0
  106. package/src/likec4diagram/useLayoutConstraints.ts +4 -5
  107. package/src/likec4model/useLikeC4ElementsTree.ts +4 -4
  108. package/src/overlays/Overlays.tsx +32 -26
  109. package/src/overlays/element-details/ElementDetailsCard.css.ts +4 -4
  110. package/src/overlays/element-details/ElementDetailsCard.tsx +246 -244
  111. package/src/overlays/element-details/TabPanelDeployments.tsx +4 -4
  112. package/src/overlays/overlay/Overlay.css.ts +10 -9
  113. package/src/overlays/overlay/Overlay.tsx +38 -26
  114. package/src/overlays/relationship-details/SelectEdge.css.ts +1 -0
  115. package/src/overlays/relationship-details/SelectEdge.tsx +2 -4
  116. package/src/overlays/relationships-browser/RelationshipsBrowser.tsx +10 -5
  117. package/src/overlays/relationships-browser/SelectElement.tsx +88 -82
  118. package/src/overlays/relationships-browser/actor.ts +10 -10
  119. package/src/overlays/relationships-browser/custom/nodeTypes.tsx +2 -2
  120. package/dist/LikeC4Search.css.d.ts +0 -1
  121. package/dist/LikeC4Search.css.js +0 -5
  122. package/dist/LikeC4Search.d.ts +0 -2
  123. package/dist/LikeC4Search.js +0 -88
  124. package/src/LikeC4Search.css.ts +0 -12
  125. package/src/LikeC4Search.tsx +0 -91
  126. /package/dist/{base → components}/Link.css.d.ts +0 -0
  127. /package/dist/{base → components}/Link.d.ts +0 -0
  128. /package/dist/{base → components}/Link.js +0 -0
  129. /package/src/{base → components}/Link.tsx +0 -0
@@ -2,7 +2,7 @@ import { Box, Button, Code, Group, Notification } from '@mantine/core'
2
2
  import { useCallbackRef } from '@mantine/hooks'
3
3
  import { IconX } from '@tabler/icons-react'
4
4
  import { deepEqual } from 'fast-equals'
5
- import { useReducedMotion } from 'framer-motion'
5
+ import { AnimatePresence, useReducedMotion } from 'framer-motion'
6
6
  import { animate } from 'framer-motion/dom'
7
7
  import { memo, useEffect, useMemo } from 'react'
8
8
  import { type FallbackProps, ErrorBoundary } from 'react-error-boundary'
@@ -73,7 +73,7 @@ export const Overlays = memo(() => {
73
73
 
74
74
  const isMotionReduced = useReducedMotion() ?? false
75
75
 
76
- const isActiveOverlay = !!activeElementDetailsOf
76
+ const isActiveOverlay = !!activeElementDetailsOf || !!relationshipsBrowserActor || !!relationshipDetailsActor
77
77
 
78
78
  useEffect(() => {
79
79
  if (!xyflowRendererDom || isMotionReduced) return
@@ -96,32 +96,38 @@ export const Overlays = memo(() => {
96
96
  return (
97
97
  <DiagramFeatures.Overlays>
98
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
- )}
99
+ <AnimatePresence onExitComplete={onClose}>
100
+ {relationshipsBrowserActor && (
101
+ <Overlay
102
+ key={'relationships-browser'}
103
+ onClose={() => relationshipsBrowserActor.send({ type: 'close' })}>
104
+ <RelationshipsBrowser actorRef={relationshipsBrowserActor} />
105
+ </Overlay>
106
+ )}
107
+ </AnimatePresence>
108
+ <AnimatePresence onExitComplete={onClose}>
109
+ {relationshipDetailsActor && (
110
+ <Overlay
111
+ key={'relationship-details'}
112
+ onClose={() => relationshipDetailsActor.send({ type: 'close' })}>
113
+ <RelationshipDetails actorRef={relationshipDetailsActor} />
114
+ </Overlay>
115
+ )}
116
+ </AnimatePresence>
113
117
 
114
118
  {/* 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
- )}
119
+ <AnimatePresence>
120
+ {!!activeElementDetailsOf && (
121
+ <ElementDetailsCard
122
+ key={'element-details'}
123
+ fqn={activeElementDetailsOf}
124
+ viewId={viewId}
125
+ fromNode={fromNode}
126
+ rectFromNode={rectFromNode}
127
+ onClose={onClose}
128
+ />
129
+ )}
130
+ </AnimatePresence>
125
131
  </ErrorBoundary>
126
132
  </DiagramFeatures.Overlays>
127
133
  )
@@ -11,10 +11,10 @@ export const dialog = style({
11
11
  padding: 0,
12
12
  position: 'fixed',
13
13
  inset: 0,
14
- width: '100%',
15
- height: '100%',
16
- maxWidth: '100%',
17
- maxHeight: '100%',
14
+ width: '100vw',
15
+ height: '100vh',
16
+ maxWidth: '100vw',
17
+ maxHeight: '100vh',
18
18
  background: 'transparent',
19
19
  border: '0 solid transparent',
20
20
  vars: {
@@ -21,7 +21,6 @@ import {
21
21
  Divider as MantineDivider,
22
22
  Flex,
23
23
  Group,
24
- RemoveScroll,
25
24
  ScrollArea,
26
25
  Stack,
27
26
  Tabs,
@@ -34,13 +33,13 @@ import {
34
33
  UnstyledButton,
35
34
  } from '@mantine/core'
36
35
  import { useSessionStorage, useViewportSize } from '@mantine/hooks'
37
- import { useDebouncedCallback, useSyncedRef } from '@react-hookz/web'
36
+ import { useDebouncedCallback, useSyncedRef, useTimeoutEffect } from '@react-hookz/web'
38
37
  import { IconExternalLink, IconFileSymlink, IconStack2, IconZoomScan } from '@tabler/icons-react'
39
38
  import type { Rect } from '@xyflow/system'
40
39
  import { type PanInfo, m, useDragControls, useMotionValue } from 'framer-motion'
41
- import { type PropsWithChildren, useCallback, useRef } from 'react'
40
+ import { type PropsWithChildren, useCallback, useRef, useState } from 'react'
42
41
  import { clamp, isNullish, map, only, partition, pipe } from 'remeda'
43
- import { Link } from '../../base'
42
+ import { Link } from '../../components/Link'
44
43
  import { DiagramFeatures, IconRenderer, IfEnabled } from '../../context'
45
44
  import { useUpdateEffect } from '../../hooks'
46
45
  import { useDiagram } from '../../hooks/useDiagram'
@@ -101,6 +100,7 @@ export function ElementDetailsCard({
101
100
  fqn,
102
101
  onClose,
103
102
  }: ElementDetailsCardProps) {
103
+ const [opened, setOpened] = useState(false)
104
104
  const windowSize = useViewportSize()
105
105
  const windowWidth = windowSize.width || window.innerWidth || 1200,
106
106
  windowHeight = windowSize.height || window.innerHeight || 800
@@ -112,11 +112,8 @@ export function ElementDetailsCard({
112
112
  const diagram = useDiagram()
113
113
  const likec4model = useLikeC4Model(true)
114
114
  const viewModel = likec4model.view(viewId)
115
- // const currentView = diagram.currentView()
116
- // const diagramNode = currentView.nodes.find(n => n.id === fqn)
117
- // invariant(diagramNode, `DiagramNode with fqn ${fqn} not found`)
118
115
  const nodeModel = fromNode ? viewModel.findNode(fromNode) : viewModel.findNodeWithElement(fqn)
119
- // invariant(nodeModel && nodeModel.hasElement(), `NodeModel with fqn ${fqn} not found`)
116
+
120
117
  const elementModel = viewModel.$model.element(fqn)
121
118
 
122
119
  // const incoming = elementModel.incoming().map(r => r.id).toArray()
@@ -217,10 +214,21 @@ export function ElementDetailsCard({
217
214
  className: css.elementIcon,
218
215
  })
219
216
 
217
+ useTimeoutEffect(() => {
218
+ if (!ref.current?.open) {
219
+ ref.current?.showModal()
220
+ }
221
+ }, 30)
222
+
223
+ useTimeoutEffect(() => {
224
+ setOpened(true)
225
+ }, 120)
226
+
220
227
  return (
221
228
  <m.dialog
222
229
  ref={ref}
223
230
  className={css.dialog}
231
+ layout
224
232
  initial={{
225
233
  '--backdrop-blur': '0px',
226
234
  '--backdrop-opacity': '10%',
@@ -236,13 +244,10 @@ export function ElementDetailsCard({
236
244
  duration: 0.1,
237
245
  },
238
246
  }}
239
- onAnimationStart={() => {
240
- ref.current?.showModal()
241
- }}
242
247
  onClick={e => {
243
248
  if ((e.target as any)?.nodeName?.toUpperCase() === 'DIALOG') {
244
249
  e.stopPropagation()
245
- close()
250
+ ref.current?.close()
246
251
  }
247
252
  }}
248
253
  onClose={e => {
@@ -250,248 +255,245 @@ export function ElementDetailsCard({
250
255
  close()
251
256
  }}
252
257
  >
253
- <RemoveScroll forwardProps>
254
- <Card
255
- drag
256
- dragElastic={0}
257
- dragMomentum={false}
258
- dragListener={false}
259
- dragControls={controls}
260
- withBorder
261
- shadow="md"
262
- component={m.div}
263
- className={css.card}
264
- initial={{
265
- top,
266
- left,
267
- width: _width,
268
- height: _height,
269
- opacity: 0,
270
- originX,
271
- originY,
272
- scale: Math.max(fromScale, 0.7),
273
- }}
274
- animate={{
275
- opacity: 1,
276
- scale: 1,
277
- }}
278
- exit={{
279
- opacity: 0,
280
- scale: 0.9,
281
- translateY: -10,
282
- transition: {
283
- duration: 0.1,
284
- },
285
- }}
286
- style={{
287
- // `style` prop in Mantine doesn't accept motion values
288
- width: width as any,
289
- height: height as any,
290
- }}
291
- data-likec4-color={nodeModel?.color ?? elementModel.color}>
292
- <Box
293
- className={css.cardHeader}
294
- onPointerDown={e => controls.start(e)}>
295
- <Group align="start" justify="space-between" gap={'sm'} mb={'sm'} wrap="nowrap">
296
- <Group align="start" gap={'sm'} style={{ cursor: 'default' }} wrap="nowrap">
297
- {elementIcon}
298
- <Box>
299
- <Text
300
- component={m.div}
301
- layout="position"
302
- layoutId={`${viewId}:element:title:${fqn}`}
303
- className={css.title}>
304
- {elementModel.title}
305
- </Text>
306
- {notation && (
307
- <Text component="div" c={'dimmed'} fz={'sm'} fw={500} lh={1.3} lineClamp={1}>
308
- {notation}
309
- </Text>
310
- )}
311
- </Box>
312
- </Group>
313
- <CloseButton
314
- size={'lg'}
315
- onClick={e => {
316
- e.stopPropagation()
317
- close()
318
- }} />
319
- </Group>
320
- <Group align="baseline" gap={'sm'} wrap="nowrap">
258
+ <Card
259
+ drag
260
+ dragElastic={0}
261
+ dragMomentum={false}
262
+ dragListener={false}
263
+ dragControls={controls}
264
+ withBorder
265
+ shadow="md"
266
+ component={m.div}
267
+ className={css.card}
268
+ initial={{
269
+ top,
270
+ left,
271
+ width: _width,
272
+ height: _height,
273
+ opacity: 0,
274
+ originX,
275
+ originY,
276
+ scale: Math.max(fromScale, 0.7),
277
+ }}
278
+ animate={{
279
+ opacity: 1,
280
+ scale: 1,
281
+ }}
282
+ exit={{
283
+ opacity: 0,
284
+ scale: 0.9,
285
+ translateY: -10,
286
+ transition: {
287
+ duration: 0.1,
288
+ },
289
+ }}
290
+ style={{
291
+ // `style` prop in Mantine doesn't accept motion values
292
+ width: width as any,
293
+ height: height as any,
294
+ }}
295
+ data-likec4-color={nodeModel?.color ?? elementModel.color}>
296
+ <Box
297
+ className={css.cardHeader}
298
+ onPointerDown={e => controls.start(e)}>
299
+ <Group align="start" justify="space-between" gap={'sm'} mb={'sm'} wrap="nowrap">
300
+ <Group align="start" gap={'sm'} style={{ cursor: 'default' }} wrap="nowrap">
301
+ {elementIcon}
321
302
  <Box>
322
- <SmallLabel>kind</SmallLabel>
323
- <Badge radius={'sm'} size="sm" fw={600} color="gray">{elementModel.kind}</Badge>
324
- </Box>
325
- <Box flex={1}>
326
- <SmallLabel>tags</SmallLabel>
327
- <Flex gap={4} flex={1} mt={6}>
328
- {elementModel.tags.map((tag) => (
329
- <Badge key={tag} radius={'sm'} size="sm" fw={600} variant="gradient">#{tag}</Badge>
330
- ))}
331
- {elementModel.tags.length === 0 && <Badge radius={'sm'} size="sm" fw={600} color="gray">—</Badge>}
332
- </Flex>
303
+ <Text
304
+ component={m.div}
305
+ layout="position"
306
+ layoutId={`${viewId}:element:title:${fqn}`}
307
+ className={css.title}>
308
+ {elementModel.title}
309
+ </Text>
310
+ {notation && (
311
+ <Text component="div" c={'dimmed'} fz={'sm'} fw={500} lh={1.3} lineClamp={1}>
312
+ {notation}
313
+ </Text>
314
+ )}
333
315
  </Box>
334
- <ActionIconGroup
335
- style={{
336
- alignSelf: 'flex-end',
337
- }}>
338
- {defaultLink && (
316
+ </Group>
317
+ <CloseButton
318
+ size={'lg'}
319
+ onClick={e => {
320
+ e.stopPropagation()
321
+ close()
322
+ }} />
323
+ </Group>
324
+ <Group align="baseline" gap={'sm'} wrap="nowrap">
325
+ <Box>
326
+ <SmallLabel>kind</SmallLabel>
327
+ <Badge radius={'sm'} size="sm" fw={600} color="gray">{elementModel.kind}</Badge>
328
+ </Box>
329
+ <Box flex={1}>
330
+ <SmallLabel>tags</SmallLabel>
331
+ <Flex gap={4} flex={1} mt={6}>
332
+ {elementModel.tags.map((tag) => (
333
+ <Badge key={tag} radius={'sm'} size="sm" fw={600} variant="gradient">#{tag}</Badge>
334
+ ))}
335
+ {elementModel.tags.length === 0 && <Badge radius={'sm'} size="sm" fw={600} color="gray">—</Badge>}
336
+ </Flex>
337
+ </Box>
338
+ <ActionIconGroup
339
+ style={{
340
+ alignSelf: 'flex-end',
341
+ }}>
342
+ {defaultLink && (
343
+ <ActionIcon
344
+ component="a"
345
+ href={defaultLink.url}
346
+ target="_blank"
347
+ size="lg"
348
+ variant="default"
349
+ radius="sm"
350
+ >
351
+ <IconExternalLink stroke={1.6} style={{ width: '65%' }} />
352
+ </ActionIcon>
353
+ )}
354
+ <IfEnabled feature="Vscode">
355
+ <Tooltip label="Open source">
356
+ <ActionIcon
357
+ size="lg"
358
+ variant="default"
359
+ radius="sm"
360
+ onClick={e => {
361
+ e.stopPropagation()
362
+ diagram.openSource({
363
+ element: elementModel.id,
364
+ })
365
+ }}>
366
+ <IconFileSymlink stroke={1.8} style={{ width: '62%' }} />
367
+ </ActionIcon>
368
+ </Tooltip>
369
+ </IfEnabled>
370
+ {defaultView && (
371
+ <Tooltip label="Open default view">
339
372
  <ActionIcon
340
- component="a"
341
- href={defaultLink.url}
342
- target="_blank"
343
373
  size="lg"
344
374
  variant="default"
345
375
  radius="sm"
346
- >
347
- <IconExternalLink stroke={1.6} style={{ width: '65%' }} />
376
+ onClick={e => {
377
+ e.stopPropagation()
378
+ diagram.navigateTo(defaultView.id, fromNode ?? undefined)
379
+ }}>
380
+ <IconZoomScan style={{ width: '70%' }} />
348
381
  </ActionIcon>
382
+ </Tooltip>
383
+ )}
384
+ </ActionIconGroup>
385
+ </Group>
386
+ </Box>
387
+ <Tabs
388
+ value={activeTab}
389
+ onChange={v => setActiveTab(v as any)}
390
+ variant="none"
391
+ classNames={{
392
+ root: css.tabsRoot,
393
+ list: css.tabsList,
394
+ tab: css.tabsTab,
395
+ panel: css.tabsPanel,
396
+ }}>
397
+ <TabsList>
398
+ {TABS.map(tab => (
399
+ <TabsTab key={tab} value={tab}>
400
+ {tab}
401
+ </TabsTab>
402
+ ))}
403
+ </TabsList>
404
+
405
+ <TabsPanel value="Properties">
406
+ <ScrollArea scrollbars="y" type="auto">
407
+ <Box className={css.propertiesGrid} pt={'xs'}>
408
+ <ElementProperty title="description" emptyValue="no description">
409
+ {elementModel.description}
410
+ </ElementProperty>
411
+ {elementModel.technology && (
412
+ <ElementProperty title="technology">
413
+ {elementModel.technology}
414
+ </ElementProperty>
349
415
  )}
350
- <IfEnabled feature="Vscode">
351
- <Tooltip label="Open source">
352
- <ActionIcon
353
- size="lg"
354
- variant="default"
355
- radius="sm"
356
- onClick={e => {
357
- e.stopPropagation()
358
- diagram.openSource({
359
- element: elementModel.id,
360
- })
361
- }}>
362
- <IconFileSymlink stroke={1.8} style={{ width: '62%' }} />
363
- </ActionIcon>
364
- </Tooltip>
365
- </IfEnabled>
366
- {defaultView && (
367
- <Tooltip label="Open default view">
368
- <ActionIcon
369
- size="lg"
370
- variant="default"
371
- radius="sm"
372
- onClick={e => {
373
- e.stopPropagation()
374
- diagram.navigateTo(defaultView.id, fromNode ?? undefined)
375
- }}>
376
- <IconZoomScan style={{ width: '70%' }} />
377
- </ActionIcon>
378
- </Tooltip>
416
+ {elementModel.links.length > 0 && (
417
+ <>
418
+ <PropertyLabel>links</PropertyLabel>
419
+ <Stack gap={'xs'} align="flex-start">
420
+ {elementModel.links.map((link, i) => <Link key={i} value={link} />)}
421
+ </Stack>
422
+ </>
379
423
  )}
380
- </ActionIconGroup>
381
- </Group>
382
- </Box>
383
-
384
- <Tabs
385
- value={activeTab}
386
- onChange={v => setActiveTab(v as any)}
387
- variant="none"
388
- classNames={{
389
- root: css.tabsRoot,
390
- list: css.tabsList,
391
- tab: css.tabsTab,
392
- panel: css.tabsPanel,
393
- }}>
394
- <TabsList>
395
- {TABS.map(tab => (
396
- <TabsTab key={tab} value={tab}>
397
- {tab}
398
- </TabsTab>
399
- ))}
400
- </TabsList>
401
-
402
- <TabsPanel value="Properties">
403
- <ScrollArea scrollbars="y" type="auto">
404
- <Box className={css.propertiesGrid} pt={'xs'}>
405
- <ElementProperty title="description" emptyValue="no description">
406
- {elementModel.description}
407
- </ElementProperty>
408
- {elementModel.technology && (
409
- <ElementProperty title="technology">
410
- {elementModel.technology}
411
- </ElementProperty>
412
- )}
413
- {elementModel.links.length > 0 && (
414
- <>
415
- <PropertyLabel>links</PropertyLabel>
416
- <Stack gap={'xs'} align="flex-start">
417
- {elementModel.links.map((link, i) => <Link key={i} value={link} />)}
418
- </Stack>
419
- </>
420
- )}
421
- {elementModel.$element.metadata && <ElementMetata value={elementModel.$element.metadata} />}
422
- </Box>
423
- </ScrollArea>
424
- </TabsPanel>
425
-
426
- <TabsPanel value="Relationships">
427
- <DiagramFeatures
428
- overrides={{
429
- enableRelationshipBrowser: false,
430
- enableNavigateTo: false,
431
- }}>
432
- {!!nodeModel && activeTab === 'Relationships' && (
433
- <TabPanelRelationships
434
- element={elementModel}
435
- node={nodeModel}
436
- currentView={diagram.currentView()} />
424
+ {elementModel.$element.metadata && <ElementMetata value={elementModel.$element.metadata} />}
425
+ </Box>
426
+ </ScrollArea>
427
+ </TabsPanel>
428
+
429
+ <TabsPanel value="Relationships">
430
+ <DiagramFeatures
431
+ overrides={{
432
+ enableRelationshipBrowser: false,
433
+ enableNavigateTo: false,
434
+ }}>
435
+ {opened && !!nodeModel && activeTab === 'Relationships' && (
436
+ <TabPanelRelationships
437
+ element={elementModel}
438
+ node={nodeModel}
439
+ currentView={diagram.currentView()} />
440
+ )}
441
+ </DiagramFeatures>
442
+ </TabsPanel>
443
+
444
+ <TabsPanel value="Views">
445
+ <ScrollArea scrollbars="y" type="auto">
446
+ <Stack gap={'lg'}>
447
+ {viewsOf.length > 0 && (
448
+ <Box>
449
+ <Divider label="views of the element (scoped)" />
450
+ <Stack gap={'sm'}>
451
+ {viewsOf.map((view) => (
452
+ <ViewButton
453
+ key={view.id}
454
+ view={view}
455
+ onNavigateTo={to => diagram.navigateTo(to, fromNode ?? undefined)} />
456
+ ))}
457
+ </Stack>
458
+ </Box>
437
459
  )}
438
- </DiagramFeatures>
439
- </TabsPanel>
440
-
441
- <TabsPanel value="Views">
442
- <ScrollArea scrollbars="y" type="auto">
443
- <Stack gap={'lg'}>
444
- {viewsOf.length > 0 && (
445
- <Box>
446
- <Divider label="views of the element (scoped)" />
447
- <Stack gap={'sm'}>
448
- {viewsOf.map((view) => (
449
- <ViewButton
450
- key={view.id}
451
- view={view}
452
- onNavigateTo={to => diagram.navigateTo(to, fromNode ?? undefined)} />
453
- ))}
454
- </Stack>
455
- </Box>
456
- )}
457
- {otherViews.length > 0 && (
458
- <Box>
459
- <Divider label="views including this element" />
460
- <Stack gap={'sm'}>
461
- {otherViews.map((view) => (
462
- <ViewButton
463
- key={view.id}
464
- view={view}
465
- onNavigateTo={to => diagram.navigateTo(to, fromNode ?? undefined)} />
466
- ))}
467
- </Stack>
468
- </Box>
469
- )}
470
- </Stack>
471
- </ScrollArea>
472
- </TabsPanel>
473
-
474
- <TabsPanel value="Structure">
475
- <ScrollArea scrollbars="y" type="auto">
476
- <TabPanelStructure element={elementModel} />
477
- </ScrollArea>
478
- </TabsPanel>
479
-
480
- <TabsPanel value="Deployments">
481
- <ScrollArea scrollbars="y" type="auto">
482
- <TabPanelDeployments elementFqn={elementModel.id} />
483
- </ScrollArea>
484
- </TabsPanel>
485
- </Tabs>
486
- <m.div
487
- className={css.resizeHandle}
488
- drag
489
- dragElastic={0}
490
- dragMomentum={false}
491
- onDrag={handleDrag}
492
- dragConstraints={{ top: 0, left: 0, right: 0, bottom: 0 }} />
493
- </Card>
494
- </RemoveScroll>
460
+ {otherViews.length > 0 && (
461
+ <Box>
462
+ <Divider label="views including this element" />
463
+ <Stack gap={'sm'}>
464
+ {otherViews.map((view) => (
465
+ <ViewButton
466
+ key={view.id}
467
+ view={view}
468
+ onNavigateTo={to => diagram.navigateTo(to, fromNode ?? undefined)} />
469
+ ))}
470
+ </Stack>
471
+ </Box>
472
+ )}
473
+ </Stack>
474
+ </ScrollArea>
475
+ </TabsPanel>
476
+
477
+ <TabsPanel value="Structure">
478
+ <ScrollArea scrollbars="y" type="auto">
479
+ <TabPanelStructure element={elementModel} />
480
+ </ScrollArea>
481
+ </TabsPanel>
482
+
483
+ <TabsPanel value="Deployments">
484
+ <ScrollArea scrollbars="y" type="auto">
485
+ <TabPanelDeployments elementFqn={elementModel.id} />
486
+ </ScrollArea>
487
+ </TabsPanel>
488
+ </Tabs>
489
+ <m.div
490
+ className={css.resizeHandle}
491
+ drag
492
+ dragElastic={0}
493
+ dragMomentum={false}
494
+ onDrag={handleDrag}
495
+ dragConstraints={{ top: 0, left: 0, right: 0, bottom: 0 }} />
496
+ </Card>
495
497
  </m.dialog>
496
498
  )
497
499
  }