@likec4/diagram 1.20.1 → 1.20.3
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.
- package/dist/LikeC4Diagram.css.d.ts +1 -0
- package/dist/LikeC4Diagram.css.js +3 -1
- package/dist/base/BaseXYFlow.js +15 -14
- package/dist/base/Link.css.d.ts +3 -0
- package/dist/base/Link.css.js +9 -0
- package/dist/base/Link.d.ts +5 -0
- package/dist/base/Link.js +58 -0
- package/dist/base/const.d.ts +1 -0
- package/dist/base/const.js +2 -1
- package/dist/base/example/custom.d.ts +1 -1
- package/dist/base/index.d.ts +1 -0
- package/dist/base/primitives/compound/CompoundActionButton.js +2 -1
- package/dist/base/primitives/compound/CompoundDetailsButton.js +2 -1
- package/dist/base/primitives/compound/CompoundNodeContainer.css.d.ts +0 -1
- package/dist/base/primitives/compound/CompoundNodeContainer.css.js +4 -6
- package/dist/base/primitives/compound/CompoundNodeContainer.js +2 -2
- package/dist/base/primitives/customEdge.d.ts +1 -1
- package/dist/base/primitives/customEdge.js +1 -1
- package/dist/base/primitives/customNode.js +1 -1
- package/dist/base/primitives/edge/EdgeLabel.js +3 -1
- package/dist/base/primitives/edge/EdgePath.d.ts +2 -1
- package/dist/base/primitives/edge/EdgePath.js +2 -0
- package/dist/base/primitives/element/ElementActionButtons.js +2 -1
- package/dist/base/primitives/element/ElementDetailsButton.js +2 -1
- package/dist/base/primitives/element/ElementNodeContainer.css.d.ts +0 -1
- package/dist/base/primitives/element/ElementNodeContainer.css.js +1 -3
- package/dist/base/primitives/element/ElementNodeContainer.js +2 -3
- package/dist/base/primitives/element/ElementShape.js +4 -2
- package/dist/base/primitives/element/ElementTitle.js +2 -1
- package/dist/base/updateEdges.js +3 -3
- package/dist/base/updateNodes.js +2 -2
- package/dist/context/FramerMotionConfig.js +1 -1
- package/dist/hooks/useDiagram.d.ts +313 -90
- package/dist/hooks/useDiagramActor.d.ts +2 -2
- package/dist/hooks/useDiagramContext.d.ts +1 -1
- package/dist/hooks/useXYFlow.d.ts +2 -1
- package/dist/hooks/useXYFlow.js +5 -0
- package/dist/likec4diagram/XYFlow.js +12 -10
- package/dist/likec4diagram/custom/edges/RelationshipEdge.d.ts +1 -1
- package/dist/likec4diagram/custom/edges/RelationshipsDropdownMenu.js +2 -2
- package/dist/likec4diagram/custom/index.d.ts +1 -1
- package/dist/likec4diagram/custom/nodes/nodeTypes.js +2 -2
- package/dist/likec4diagram/state/actorContext.d.ts +1438 -364
- package/dist/likec4diagram/state/assign.js +2 -2
- package/dist/likec4diagram/state/machine.d.ts +321 -93
- package/dist/likec4diagram/state/syncManualLayoutActor.d.ts +1 -1
- package/dist/likec4diagram/types.d.ts +1 -0
- package/dist/likec4diagram/ui/diagram-title/DiagramTitlePanel.js +4 -3
- package/dist/likec4diagram/useLayoutConstraints.d.ts +2 -1
- package/dist/likec4diagram/useLayoutConstraints.js +14 -15
- package/dist/likec4diagram/useViewToNodesEdges.js +3 -1
- package/dist/overlays/element-details/ElementDetailsCard.css.d.ts +0 -1
- package/dist/overlays/element-details/ElementDetailsCard.css.js +1 -3
- package/dist/overlays/element-details/ElementDetailsCard.js +5 -30
- package/dist/overlays/element-details/TabPanelRelationships.js +2 -2
- package/dist/overlays/relationship-details/RelationshipDetails.js +4 -4
- package/dist/overlays/relationship-details/custom/ElementActions.js +1 -3
- package/dist/overlays/relationship-details/custom/edgeTypes.d.ts +1 -1
- package/dist/overlays/relationship-details/hooks.d.ts +2 -2
- package/dist/overlays/relationship-details/hooks.js +7 -7
- package/dist/overlays/relationship-details/useLayoutedDetails.js +7 -10
- package/dist/overlays/relationships-browser/-useRelationshipsView.d.ts +4 -1
- package/dist/overlays/relationships-browser/-useRelationshipsView.js +12 -11
- package/dist/overlays/relationships-browser/RelationshipsBrowser.js +81 -66
- package/dist/overlays/relationships-browser/_types.d.ts +2 -1
- package/dist/overlays/relationships-browser/actor.d.ts +15 -2
- package/dist/overlays/relationships-browser/actor.js +262 -65
- package/dist/overlays/relationships-browser/const.d.ts +1 -0
- package/dist/overlays/relationships-browser/const.js +4 -0
- package/dist/overlays/relationships-browser/custom/ElementActions.js +13 -3
- package/dist/overlays/relationships-browser/custom/edgeTypes.d.ts +3 -2
- package/dist/overlays/relationships-browser/custom/edgeTypes.js +24 -6
- package/dist/overlays/relationships-browser/custom/nodeTypes.js +3 -2
- package/dist/overlays/relationships-browser/hooks.d.ts +6 -3
- package/dist/overlays/relationships-browser/hooks.js +4 -2
- package/dist/overlays/relationships-browser/useViewToNodesEdges.js +7 -2
- package/dist/style.css +1 -1
- package/dist/utils/xyflow.js +9 -1
- package/package.json +10 -10
- package/src/LikeC4Diagram.css.ts +8 -0
- package/src/base/BaseXYFlow.tsx +23 -14
- package/src/base/Link.css.ts +49 -0
- package/src/base/Link.tsx +66 -0
- package/src/base/const.ts +1 -0
- package/src/base/index.ts +2 -0
- package/src/base/primitives/compound/CompoundActionButton.tsx +2 -1
- package/src/base/primitives/compound/CompoundDetailsButton.tsx +2 -1
- package/src/base/primitives/compound/CompoundNodeContainer.css.ts +16 -10
- package/src/base/primitives/compound/CompoundNodeContainer.tsx +1 -1
- package/src/base/primitives/customEdge.ts +2 -0
- package/src/base/primitives/customNode.ts +3 -0
- package/src/base/primitives/edge/EdgeLabel.tsx +3 -1
- package/src/base/primitives/edge/EdgePath.tsx +3 -0
- package/src/base/primitives/element/ElementActionButtons.tsx +2 -1
- package/src/base/primitives/element/ElementDetailsButton.tsx +2 -1
- package/src/base/primitives/element/ElementNodeContainer.css.ts +9 -4
- package/src/base/primitives/element/ElementNodeContainer.tsx +1 -2
- package/src/base/primitives/element/ElementShape.tsx +4 -3
- package/src/base/primitives/element/ElementTitle.tsx +2 -1
- package/src/base/updateEdges.ts +3 -2
- package/src/base/updateNodes.ts +3 -2
- package/src/context/DiagramFeatures.tsx +1 -0
- package/src/context/FramerMotionConfig.tsx +1 -1
- package/src/hooks/useDiagramActor.ts +7 -5
- package/src/hooks/useDiagramContext.ts +4 -1
- package/src/hooks/useXYFlow.ts +6 -1
- package/src/likec4diagram/XYFlow.tsx +20 -9
- package/src/likec4diagram/custom/edges/RelationshipsDropdownMenu.tsx +2 -2
- package/src/likec4diagram/custom/nodes/nodeTypes.tsx +2 -2
- package/src/likec4diagram/types.ts +1 -0
- package/src/likec4diagram/ui/diagram-title/DiagramTitlePanel.tsx +4 -3
- package/src/likec4diagram/useLayoutConstraints.ts +23 -19
- package/src/likec4diagram/useViewToNodesEdges.ts +1 -0
- package/src/overlays/element-details/ElementDetailsCard.css.ts +0 -28
- package/src/overlays/element-details/ElementDetailsCard.tsx +2 -50
- package/src/overlays/element-details/TabPanelRelationships.tsx +2 -2
- package/src/overlays/relationship-details/RelationshipDetails.tsx +4 -4
- package/src/overlays/relationship-details/custom/ElementActions.tsx +1 -2
- package/src/overlays/relationship-details/custom/edgeTypes.tsx +0 -5
- package/src/overlays/relationship-details/hooks.ts +6 -6
- package/src/overlays/relationship-details/useLayoutedDetails.ts +7 -10
- package/src/overlays/relationships-browser/-useRelationshipsView.ts +16 -12
- package/src/overlays/relationships-browser/RelationshipsBrowser.tsx +105 -68
- package/src/overlays/relationships-browser/_types.ts +2 -1
- package/src/overlays/relationships-browser/actor.ts +321 -62
- package/src/overlays/relationships-browser/const.ts +1 -0
- package/src/overlays/relationships-browser/custom/ElementActions.tsx +13 -3
- package/src/overlays/relationships-browser/custom/edgeTypes.tsx +25 -6
- package/src/overlays/relationships-browser/custom/nodeTypes.tsx +3 -2
- package/src/overlays/relationships-browser/hooks.ts +3 -1
- package/src/overlays/relationships-browser/useViewToNodesEdges.ts +8 -2
- package/dist/likec4diagram/ui/diagram-title/Link.js +0 -36
- package/dist/ui/Link.d.ts +0 -4
- package/src/ui/Link.tsx +0 -40
|
@@ -39,7 +39,7 @@ const ElementDetailsButtonWithHandler = ({ fqn, ...props }: NodeProps<Types.Node
|
|
|
39
39
|
export const nodeTypes = {
|
|
40
40
|
element: customNode<Types.ElementNodeData>((props) => (
|
|
41
41
|
<ElementNodeContainer nodeProps={props}>
|
|
42
|
-
<ElementShape {...props} />
|
|
42
|
+
<ElementShape {...props} isMultiple={props.data.isMultiple} />
|
|
43
43
|
<ElementTitle {...props} />
|
|
44
44
|
<ElementActions {...props} />
|
|
45
45
|
<ElementDetailsButtonWithHandler
|
|
@@ -53,7 +53,7 @@ export const nodeTypes = {
|
|
|
53
53
|
)),
|
|
54
54
|
deployment: customNode<Types.DeploymentElementNodeData>((props) => (
|
|
55
55
|
<ElementNodeContainer nodeProps={props}>
|
|
56
|
-
<ElementShape {...props} />
|
|
56
|
+
<ElementShape {...props} isMultiple={props.data.isMultiple} />
|
|
57
57
|
<ElementTitle {...props} />
|
|
58
58
|
<DeploymentElementActions {...props} />
|
|
59
59
|
{!!props.data.modelFqn && (
|
|
@@ -3,10 +3,10 @@ import { useLocalStorage } from '@mantine/hooks'
|
|
|
3
3
|
import { IconMenu } from '@tabler/icons-react'
|
|
4
4
|
import clsx from 'clsx'
|
|
5
5
|
import { AnimatePresence, m } from 'framer-motion'
|
|
6
|
+
import { Link } from '../../../base'
|
|
6
7
|
import { useDiagramContext } from '../../../hooks/useDiagramContext'
|
|
7
8
|
import type { DiagramContext } from '../../state/machine'
|
|
8
9
|
import * as css from './DiagramTitlePanel.css'
|
|
9
|
-
import { Link } from './Link'
|
|
10
10
|
|
|
11
11
|
const selector = (s: DiagramContext) => ({
|
|
12
12
|
id: s.view.id,
|
|
@@ -150,10 +150,11 @@ export function DiagramTitlePanel() {
|
|
|
150
150
|
)}
|
|
151
151
|
{links && (
|
|
152
152
|
<Stack
|
|
153
|
-
|
|
153
|
+
mt={'xs'}
|
|
154
|
+
gap={4}
|
|
154
155
|
justify="stretch"
|
|
155
156
|
align="stretch">
|
|
156
|
-
{links.map((link) => <Link
|
|
157
|
+
{links.map((link) => <Link value={link} key={link.url} />)}
|
|
157
158
|
</Stack>
|
|
158
159
|
)}
|
|
159
160
|
</>
|
|
@@ -60,42 +60,46 @@ abstract class Rect {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
protected abstract parent: Compound | null
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
class Compound extends Rect {
|
|
66
|
-
public readonly children = [] as Rect[]
|
|
67
63
|
|
|
68
64
|
constructor(
|
|
69
65
|
xynode: InternalNode,
|
|
70
|
-
|
|
66
|
+
parent: Compound | null = null,
|
|
71
67
|
) {
|
|
72
|
-
super()
|
|
73
68
|
this.id = xynode.id
|
|
74
69
|
|
|
70
|
+
this.positionAbsolute = !parent ? xynode.position : {
|
|
71
|
+
x: xynode.position.x + parent.minX,
|
|
72
|
+
y: xynode.position.y + parent.minY,
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const { width, height } = getNodeDimensions(xynode)
|
|
76
|
+
|
|
77
|
+
this.maxX = this.minX + Math.ceil(width)
|
|
78
|
+
this.maxY = this.minY + Math.ceil(height)
|
|
79
|
+
|
|
75
80
|
if (parent) {
|
|
76
81
|
parent.children.push(this)
|
|
77
82
|
}
|
|
78
83
|
}
|
|
79
84
|
}
|
|
80
85
|
|
|
81
|
-
class
|
|
86
|
+
class Compound extends Rect {
|
|
87
|
+
public readonly children = [] as Rect[]
|
|
88
|
+
|
|
82
89
|
constructor(
|
|
83
90
|
xynode: InternalNode,
|
|
84
91
|
public readonly parent: Compound | null = null,
|
|
85
92
|
) {
|
|
86
|
-
super()
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
this.positionAbsolute = xynode.internals.positionAbsolute
|
|
90
|
-
|
|
91
|
-
const { width, height } = getNodeDimensions(xynode)
|
|
92
|
-
|
|
93
|
-
this.maxX = this.minX + Math.ceil(width)
|
|
94
|
-
this.maxY = this.minY + Math.ceil(height)
|
|
93
|
+
super(xynode, parent)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
class Leaf extends Rect {
|
|
98
|
+
constructor(
|
|
99
|
+
xynode: InternalNode,
|
|
100
|
+
public readonly parent: Compound | null = null,
|
|
101
|
+
) {
|
|
102
|
+
super(xynode, parent)
|
|
99
103
|
}
|
|
100
104
|
}
|
|
101
105
|
|
|
@@ -275,34 +275,6 @@ export const propertyLabel = style({
|
|
|
275
275
|
justifySelf: 'end',
|
|
276
276
|
})
|
|
277
277
|
|
|
278
|
-
export const elementLink = style({
|
|
279
|
-
transition: transitions.fast,
|
|
280
|
-
border: `1px dashed ${mantine.colors.defaultBorder}`,
|
|
281
|
-
borderRadius: mantine.radius.sm,
|
|
282
|
-
minHeight: 30,
|
|
283
|
-
padding: '3px 16px 3px 3px',
|
|
284
|
-
cursor: 'pointer',
|
|
285
|
-
color: mantine.colors.gray[7],
|
|
286
|
-
':hover': {
|
|
287
|
-
transitionTimingFunction: easings.out,
|
|
288
|
-
borderStyle: 'solid',
|
|
289
|
-
color: mantine.colors.defaultColor,
|
|
290
|
-
background: mantine.colors.defaultHover,
|
|
291
|
-
},
|
|
292
|
-
selectors: {
|
|
293
|
-
[`${whereDark} &`]: {
|
|
294
|
-
color: mantine.colors.dark[1],
|
|
295
|
-
},
|
|
296
|
-
},
|
|
297
|
-
})
|
|
298
|
-
globalStyle(`${elementLink} > *`, {
|
|
299
|
-
transition: transitions.fast,
|
|
300
|
-
})
|
|
301
|
-
globalStyle(`${elementLink}:hover > *`, {
|
|
302
|
-
transitionTimingFunction: easings.out,
|
|
303
|
-
transform: 'translateX(1px)',
|
|
304
|
-
})
|
|
305
|
-
|
|
306
278
|
export const resizeHandle = style({
|
|
307
279
|
position: 'absolute',
|
|
308
280
|
width: 14,
|
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
type Element,
|
|
4
4
|
type Fqn,
|
|
5
5
|
type LikeC4View,
|
|
6
|
-
type Link,
|
|
7
6
|
ComputedNode,
|
|
8
7
|
ComputedView,
|
|
9
8
|
isDeploymentView,
|
|
@@ -43,6 +42,7 @@ import clsx from 'clsx'
|
|
|
43
42
|
import { type PanInfo, m, useDragControls, useMotionValue } from 'framer-motion'
|
|
44
43
|
import { type PropsWithChildren, memo, useCallback, useLayoutEffect, useRef } from 'react'
|
|
45
44
|
import { clamp, isNullish, map, only, partition, pipe } from 'remeda'
|
|
45
|
+
import { Link } from '../../base'
|
|
46
46
|
import { IconRenderer, IfEnabled } from '../../context'
|
|
47
47
|
import { useUpdateEffect } from '../../hooks'
|
|
48
48
|
import { useDiagram } from '../../hooks/useDiagram'
|
|
@@ -424,7 +424,7 @@ export const ElementDetailsCard = memo(({ fqn }: ElementDetailsCardProps) => {
|
|
|
424
424
|
<>
|
|
425
425
|
<PropertyLabel>links</PropertyLabel>
|
|
426
426
|
<Stack gap={'xs'} align="flex-start">
|
|
427
|
-
{elementModel.links.map((link, i) => <
|
|
427
|
+
{elementModel.links.map((link, i) => <Link key={i} value={link} />)}
|
|
428
428
|
</Stack>
|
|
429
429
|
</>
|
|
430
430
|
)}
|
|
@@ -601,54 +601,6 @@ function ElementProperty({
|
|
|
601
601
|
)
|
|
602
602
|
}
|
|
603
603
|
|
|
604
|
-
function ElementLink({
|
|
605
|
-
value,
|
|
606
|
-
}: {
|
|
607
|
-
value: Link
|
|
608
|
-
}) {
|
|
609
|
-
const url = new URL(value.url, window.location.href).toString()
|
|
610
|
-
return (
|
|
611
|
-
<CopyButton value={url}>
|
|
612
|
-
{({ copied, copy }) => (
|
|
613
|
-
<Anchor href={url} target="_blank" underline="never" className={css.elementLink}>
|
|
614
|
-
<Group gap={4} align="center" wrap="nowrap">
|
|
615
|
-
<ActionIcon
|
|
616
|
-
tabIndex={-1}
|
|
617
|
-
size={24}
|
|
618
|
-
variant={copied ? 'light' : 'subtle'}
|
|
619
|
-
color={copied ? 'teal' : 'gray'}
|
|
620
|
-
onClick={e => {
|
|
621
|
-
e.stopPropagation()
|
|
622
|
-
e.preventDefault()
|
|
623
|
-
copy()
|
|
624
|
-
}}
|
|
625
|
-
>
|
|
626
|
-
{copied ? <IconCheck /> : <IconCopy style={{ width: '65%', opacity: 0.8 }} />}
|
|
627
|
-
</ActionIcon>
|
|
628
|
-
<Box flex={1}>
|
|
629
|
-
<Text fz={'sm'} truncate lh={1.3} fw={value.title ? 500 : 400}>
|
|
630
|
-
{value.title || url}
|
|
631
|
-
</Text>
|
|
632
|
-
{value.title && (
|
|
633
|
-
<Text component="div" fz={10} c={'dimmed'} lh={1.2} truncate>
|
|
634
|
-
{url}
|
|
635
|
-
</Text>
|
|
636
|
-
)}
|
|
637
|
-
</Box>
|
|
638
|
-
</Group>
|
|
639
|
-
</Anchor>
|
|
640
|
-
)}
|
|
641
|
-
</CopyButton>
|
|
642
|
-
)
|
|
643
|
-
// <Anchor href={value.url} fz={'sm'}>
|
|
644
|
-
// {value.title || url}
|
|
645
|
-
// </Anchor><Button variant='default' size='sm'>
|
|
646
|
-
// {value.title || value.url}
|
|
647
|
-
// </Button>
|
|
648
|
-
// </Box>
|
|
649
|
-
// )
|
|
650
|
-
}
|
|
651
|
-
|
|
652
604
|
function ElementMetata({
|
|
653
605
|
value,
|
|
654
606
|
}: {
|
|
@@ -28,8 +28,8 @@ export function TabPanelRelationships({
|
|
|
28
28
|
const incoming = [...element.incoming()].map(r => r.id)
|
|
29
29
|
const outgoing = [...element.outgoing()].map(r => r.id)
|
|
30
30
|
|
|
31
|
-
const incomingInView = unique(node.incoming().flatMap(e => e.$edge.relations)
|
|
32
|
-
const outgoingInView = unique(node.outgoing().flatMap(e => e.$edge.relations)
|
|
31
|
+
const incomingInView = unique([...node.incoming()].flatMap(e => e.$edge.relations))
|
|
32
|
+
const outgoingInView = unique([...node.outgoing()].flatMap(e => e.$edge.relations))
|
|
33
33
|
|
|
34
34
|
const notIncludedRelations = [
|
|
35
35
|
...incoming,
|
|
@@ -17,7 +17,7 @@ import { nodeTypes } from './custom/nodeTypes'
|
|
|
17
17
|
import {
|
|
18
18
|
RelationshipDetailsActorContext,
|
|
19
19
|
useRelationshipDetails,
|
|
20
|
-
|
|
20
|
+
useRelationshipDetailsState,
|
|
21
21
|
} from './hooks'
|
|
22
22
|
import { SelectEdge } from './SelectEdge'
|
|
23
23
|
import { useLayoutedDetails } from './useLayoutedDetails'
|
|
@@ -63,7 +63,7 @@ const RelationshipDetailsInner = memo(() => {
|
|
|
63
63
|
edgeId,
|
|
64
64
|
view,
|
|
65
65
|
initialized,
|
|
66
|
-
} =
|
|
66
|
+
} = useRelationshipDetailsState(selector)
|
|
67
67
|
|
|
68
68
|
const {
|
|
69
69
|
edge,
|
|
@@ -123,9 +123,9 @@ const RelationshipDetailsInner = memo(() => {
|
|
|
123
123
|
e.stopPropagation()
|
|
124
124
|
browser.send({ type: 'xyflow.paneClick' })
|
|
125
125
|
})}
|
|
126
|
-
onViewportResize={() => {
|
|
126
|
+
onViewportResize={useCallbackRef(() => {
|
|
127
127
|
browser.send({ type: 'xyflow.resized' })
|
|
128
|
-
}}
|
|
128
|
+
})}
|
|
129
129
|
nodesDraggable={false}
|
|
130
130
|
fitView={false}
|
|
131
131
|
pannable
|
|
@@ -11,11 +11,10 @@ type ElementActionsProps = NodeProps<Types.ElementNodeData>
|
|
|
11
11
|
export const ElementActions = (props: ElementActionsProps) => {
|
|
12
12
|
const { enableNavigateTo } = useEnabledFeature('NavigateTo')
|
|
13
13
|
const diagram = useDiagram()
|
|
14
|
-
const browser = useRelationshipDetails()
|
|
15
14
|
|
|
16
15
|
const buttons = [] as ElementActionButtons.Item[]
|
|
17
16
|
|
|
18
|
-
const { navigateTo
|
|
17
|
+
const { navigateTo } = props.data
|
|
19
18
|
if (navigateTo && enableNavigateTo) {
|
|
20
19
|
buttons.push({
|
|
21
20
|
key: 'navigate',
|
|
@@ -7,21 +7,21 @@ import type { RelationshipDetailsActorRef, RelationshipDetailsSnapshot } from '.
|
|
|
7
7
|
|
|
8
8
|
export const RelationshipDetailsActorContext = createContext<RelationshipDetailsActorRef | null>(null)
|
|
9
9
|
|
|
10
|
-
export function
|
|
11
|
-
return nonNullable(useContext(RelationshipDetailsActorContext), 'No
|
|
10
|
+
export function useRelationshipDetailsActor() {
|
|
11
|
+
return nonNullable(useContext(RelationshipDetailsActorContext), 'No RelationshipDetailsActorContext')
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export function
|
|
14
|
+
export function useRelationshipDetailsState<T = unknown>(
|
|
15
15
|
selector: (state: RelationshipDetailsSnapshot) => T,
|
|
16
|
-
compare: (a: T
|
|
16
|
+
compare: (a: NoInfer<T>, b: NoInfer<T>) => boolean = shallowEqual,
|
|
17
17
|
) {
|
|
18
18
|
const select = useCallbackRef(selector)
|
|
19
|
-
const actor =
|
|
19
|
+
const actor = useRelationshipDetailsActor()
|
|
20
20
|
return useSelector(actor, select, compare)
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export function useRelationshipDetails() {
|
|
24
|
-
const actor =
|
|
24
|
+
const actor = useRelationshipDetailsActor()
|
|
25
25
|
const [, startTransition] = useTransition()
|
|
26
26
|
return useMemo(() => ({
|
|
27
27
|
getState: () => actor.getSnapshot().context,
|
|
@@ -290,8 +290,8 @@ function layout(
|
|
|
290
290
|
type: 'relationship',
|
|
291
291
|
source: source.id,
|
|
292
292
|
target: target.id,
|
|
293
|
-
sourceHandle:
|
|
294
|
-
targetHandle:
|
|
293
|
+
sourceHandle: source.id + '_out' + (source.data.ports.out.length - 1),
|
|
294
|
+
targetHandle: target.id + '_in' + (target.data.ports.in.length - 1),
|
|
295
295
|
data: {
|
|
296
296
|
relationId: relation.id,
|
|
297
297
|
color: relation.color,
|
|
@@ -309,15 +309,12 @@ function layout(
|
|
|
309
309
|
const nodebounds = applyDagreLayout(ctx.g)
|
|
310
310
|
|
|
311
311
|
// Sort ports
|
|
312
|
-
const sortedPorts = (ports: string[]) => {
|
|
313
|
-
if (ports.length < 2) {
|
|
314
|
-
return ports
|
|
315
|
-
}
|
|
312
|
+
const sortedPorts = (nodeId: string, type: 'in' | 'out', ports: string[]) => {
|
|
316
313
|
return pipe(
|
|
317
314
|
ports,
|
|
318
|
-
map(port => {
|
|
315
|
+
map((port, index) => {
|
|
319
316
|
return {
|
|
320
|
-
port,
|
|
317
|
+
port: nodeId + '_' + type + index,
|
|
321
318
|
topY: nodebounds(port).position.y,
|
|
322
319
|
}
|
|
323
320
|
}),
|
|
@@ -328,8 +325,8 @@ function layout(
|
|
|
328
325
|
|
|
329
326
|
const xynodes = [...ctx.xynodes.values()].map((node) => {
|
|
330
327
|
const { position, width, height } = nodebounds(node.id, node.parentId)
|
|
331
|
-
node.data.ports.in = sortedPorts(node.data.ports.in)
|
|
332
|
-
node.data.ports.out = sortedPorts(node.data.ports.out)
|
|
328
|
+
node.data.ports.in = sortedPorts(node.id, 'in', node.data.ports.in)
|
|
329
|
+
node.data.ports.out = sortedPorts(node.id, 'out', node.data.ports.out)
|
|
333
330
|
if (node.type === 'element') {
|
|
334
331
|
node.data.width = width
|
|
335
332
|
node.data.height = height
|
|
@@ -256,6 +256,8 @@ export namespace LayoutRelationshipsViewResult {
|
|
|
256
256
|
ports: RelationshipsBrowserTypes.Ports
|
|
257
257
|
}
|
|
258
258
|
export type Edge = DiagramEdge & {
|
|
259
|
+
sourceHandle: string
|
|
260
|
+
targetHandle: string
|
|
259
261
|
// column: RelationshipsBrowserTypes.Column
|
|
260
262
|
}
|
|
261
263
|
}
|
|
@@ -271,6 +273,8 @@ export function layoutRelationshipsView(data: RelationshipsViewData): LayoutRela
|
|
|
271
273
|
name: string
|
|
272
274
|
source: string // node id
|
|
273
275
|
target: string // node id
|
|
276
|
+
sourceHandle: string
|
|
277
|
+
targetHandle: string
|
|
274
278
|
relations: RelationshipModel[]
|
|
275
279
|
}>
|
|
276
280
|
|
|
@@ -319,7 +323,9 @@ export function layoutRelationshipsView(data: RelationshipsViewData): LayoutRela
|
|
|
319
323
|
edges.push({
|
|
320
324
|
name,
|
|
321
325
|
source: source.id,
|
|
326
|
+
sourceHandle: source.id + '_out' + (g.node(source.id).outPorts.length - 1),
|
|
322
327
|
target: target.id,
|
|
328
|
+
targetHandle: target.id + '_in' + (g.node(target.id).inPorts.length - 1),
|
|
323
329
|
relations: map(grouped, prop('relation')),
|
|
324
330
|
})
|
|
325
331
|
}),
|
|
@@ -446,15 +452,12 @@ export function layoutRelationshipsView(data: RelationshipsViewData): LayoutRela
|
|
|
446
452
|
}
|
|
447
453
|
|
|
448
454
|
// Sort ports in subject vertically
|
|
449
|
-
const sortedPorts = (ports: string[]) => {
|
|
450
|
-
if (ports.length < 2) {
|
|
451
|
-
return ports
|
|
452
|
-
}
|
|
455
|
+
const sortedPorts = (nodeId: string, type: 'in' | 'out', ports: string[]) => {
|
|
453
456
|
return pipe(
|
|
454
457
|
ports,
|
|
455
|
-
map(port => {
|
|
458
|
+
map((port, index) => {
|
|
456
459
|
return {
|
|
457
|
-
port,
|
|
460
|
+
port: nodeId + '_' + type + index,
|
|
458
461
|
topY: nodeBounds(port).position.y,
|
|
459
462
|
}
|
|
460
463
|
}),
|
|
@@ -462,7 +465,6 @@ export function layoutRelationshipsView(data: RelationshipsViewData): LayoutRela
|
|
|
462
465
|
map(prop('port')),
|
|
463
466
|
)
|
|
464
467
|
}
|
|
465
|
-
|
|
466
468
|
// In case we got negative positions
|
|
467
469
|
let minX = 0
|
|
468
470
|
let minY = 0
|
|
@@ -573,16 +575,16 @@ export function layoutRelationshipsView(data: RelationshipsViewData): LayoutRela
|
|
|
573
575
|
height,
|
|
574
576
|
column,
|
|
575
577
|
ports: {
|
|
576
|
-
in: sortedPorts(inPorts),
|
|
577
|
-
out: sortedPorts(outPorts),
|
|
578
|
+
in: sortedPorts(id, 'in', inPorts),
|
|
579
|
+
out: sortedPorts(id, 'out', outPorts),
|
|
578
580
|
},
|
|
579
581
|
}
|
|
580
582
|
})
|
|
581
583
|
|
|
582
584
|
return {
|
|
583
585
|
bounds: {
|
|
584
|
-
x: minX,
|
|
585
|
-
y: minY,
|
|
586
|
+
x: Math.min(minX, 0),
|
|
587
|
+
y: Math.min(minY, 0),
|
|
586
588
|
width: g.graph().width ?? 100,
|
|
587
589
|
height: g.graph().height ?? 100,
|
|
588
590
|
},
|
|
@@ -593,7 +595,7 @@ export function layoutRelationshipsView(data: RelationshipsViewData): LayoutRela
|
|
|
593
595
|
if (!ename) {
|
|
594
596
|
return acc
|
|
595
597
|
}
|
|
596
|
-
const { name, source, target, relations } = find(edges, e => e.name === ename)!
|
|
598
|
+
const { name, source, target, relations, sourceHandle, targetHandle } = find(edges, e => e.name === ename)!
|
|
597
599
|
const onlyRelation = only(relations)
|
|
598
600
|
const label = onlyRelation?.title ?? 'untitled'
|
|
599
601
|
const isMultiple = relations.length > 1
|
|
@@ -607,7 +609,9 @@ export function layoutRelationshipsView(data: RelationshipsViewData): LayoutRela
|
|
|
607
609
|
acc.push({
|
|
608
610
|
id: name as EdgeId,
|
|
609
611
|
source: source as NodeId,
|
|
612
|
+
sourceHandle,
|
|
610
613
|
target: target as NodeId,
|
|
614
|
+
targetHandle,
|
|
611
615
|
label: isMultiple ? `${relations.length} relationships` : label,
|
|
612
616
|
relations: relations.map(r => r.id),
|
|
613
617
|
parent: null,
|