@likec4/diagram 1.1.0 → 1.1.1
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.d.ts +1 -1
- package/dist/LikeC4Diagram.props.d.ts +16 -11
- package/dist/index.mjs +413 -101
- package/dist/state/DiagramContext.d.ts +18 -9
- package/dist/state/diagramStore.d.ts +19 -9
- package/dist/state/useDiagramStore.d.ts +18 -9
- package/dist/style.css +99 -35
- package/dist/ui/DiagramTitlePanel.css.d.ts +4 -0
- package/dist/ui/DiagramTitlePanel.d.ts +2 -0
- package/dist/ui/OptionsPanel.d.ts +1 -2
- package/dist/xyflow/SelectEdgesOnNodeFocus.d.ts +1 -0
- package/dist/xyflow/XYFlowEvents.d.ts +46 -40
- package/dist/xyflow/edges/edges.css.d.ts +1 -0
- package/package.json +4 -2
- package/src/LikeC4Diagram.css.ts +2 -1
- package/src/LikeC4Diagram.props.ts +17 -12
- package/src/LikeC4Diagram.tsx +3 -0
- package/src/StaticLikeC4Diagram.tsx +1 -0
- package/src/globals.css.ts +6 -1
- package/src/state/diagramStore.ts +101 -63
- package/src/ui/DiagramTitlePanel.css.ts +32 -0
- package/src/ui/DiagramTitlePanel.tsx +139 -0
- package/src/ui/OptionsPanel.tsx +4 -23
- package/src/ui/options/NodeOptions.tsx +107 -30
- package/src/xyflow/FitviewOnDiagramChange.tsx +2 -2
- package/src/xyflow/SelectEdgesOnNodeFocus.tsx +57 -0
- package/src/xyflow/SyncWithDiagram.tsx +12 -6
- package/src/xyflow/XYFlow.tsx +7 -3
- package/src/xyflow/XYFlowEvents.tsx +145 -104
- package/src/xyflow/edges/RelationshipEdge.tsx +43 -47
- package/src/xyflow/edges/edges.css.ts +77 -36
- package/src/xyflow/nodes/compound/CompoundNode.css.ts +17 -13
- package/src/xyflow/nodes/element/element.css.ts +1 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { XYFlowNode } from './types';
|
|
2
2
|
|
|
3
3
|
export declare function useXYFlowEvents(): {
|
|
4
|
-
onDoubleClick: import('react').
|
|
5
|
-
|
|
6
|
-
onNodeContextMenu: import('
|
|
7
|
-
|
|
4
|
+
onDoubleClick: (event: import('react').MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
|
5
|
+
onPaneClick: (event: import('react').MouseEvent<Element, MouseEvent>) => void;
|
|
6
|
+
onNodeContextMenu: (event: import('react').MouseEvent<Element, MouseEvent>, xynode: XYFlowNode) => void;
|
|
7
|
+
onPaneContextMenu: (event: MouseEvent | import('react').MouseEvent<Element, MouseEvent>) => void;
|
|
8
|
+
onEdgeContextMenu: (event: import('react').MouseEvent<Element, MouseEvent>, xyedge: {
|
|
8
9
|
source: string;
|
|
9
10
|
target: string;
|
|
10
11
|
style?: import('react').CSSProperties;
|
|
@@ -33,17 +34,19 @@ export declare function useXYFlowEvents(): {
|
|
|
33
34
|
data: import('./types').RelationshipData;
|
|
34
35
|
type: "relationship";
|
|
35
36
|
}) => void;
|
|
36
|
-
|
|
37
|
+
onNodeClick: (event: import('react').MouseEvent<Element, MouseEvent>, xynode: XYFlowNode) => void;
|
|
38
|
+
onNodeDoubleClick: (event: import('react').MouseEvent<Element, MouseEvent>, xynode: XYFlowNode) => void;
|
|
39
|
+
onEdgeClick: (event: import('react').MouseEvent<Element, MouseEvent>, xyedge: {
|
|
37
40
|
source: string;
|
|
38
41
|
target: string;
|
|
39
|
-
style?: import(
|
|
42
|
+
style?: import('react').CSSProperties;
|
|
40
43
|
id: string;
|
|
41
44
|
zIndex?: number;
|
|
42
|
-
markerEnd?: import(
|
|
43
|
-
markerStart?: import(
|
|
45
|
+
markerEnd?: import('@xyflow/react').EdgeMarkerType;
|
|
46
|
+
markerStart?: import('@xyflow/react').EdgeMarkerType;
|
|
44
47
|
hidden?: boolean;
|
|
45
48
|
className?: string;
|
|
46
|
-
label?: import(
|
|
49
|
+
label?: import('react').ReactNode;
|
|
47
50
|
selected?: boolean;
|
|
48
51
|
selectable?: boolean;
|
|
49
52
|
deletable?: boolean;
|
|
@@ -53,30 +56,29 @@ export declare function useXYFlowEvents(): {
|
|
|
53
56
|
targetHandle?: string | null;
|
|
54
57
|
animated?: boolean;
|
|
55
58
|
interactionWidth?: number;
|
|
56
|
-
labelStyle?: import(
|
|
59
|
+
labelStyle?: import('react').CSSProperties;
|
|
57
60
|
labelShowBg?: boolean;
|
|
58
|
-
labelBgStyle?: import(
|
|
61
|
+
labelBgStyle?: import('react').CSSProperties;
|
|
59
62
|
labelBgPadding?: [number, number];
|
|
60
63
|
labelBgBorderRadius?: number;
|
|
61
|
-
updatable?: import(
|
|
62
|
-
data: import(
|
|
64
|
+
updatable?: import('@xyflow/react').EdgeUpdatable;
|
|
65
|
+
data: import('./types').RelationshipData;
|
|
63
66
|
type: "relationship";
|
|
64
|
-
}
|
|
65
|
-
onMoveEnd: import('@xyflow/react').
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
onEdgeMouseEnter: import('@xyflow/react').EdgeMouseHandler<{
|
|
67
|
+
}) => void;
|
|
68
|
+
onMoveEnd: (event: MouseEvent | TouchEvent | null, _viewport: import('@xyflow/react').Viewport) => void;
|
|
69
|
+
onNodeMouseEnter: (event: import('react').MouseEvent<Element, MouseEvent>, xynode: XYFlowNode) => void;
|
|
70
|
+
onNodeMouseLeave: (event: import('react').MouseEvent<Element, MouseEvent>, xynode: XYFlowNode) => void;
|
|
71
|
+
onEdgeMouseEnter: (event: import('react').MouseEvent<Element, MouseEvent>, xyedge: {
|
|
70
72
|
source: string;
|
|
71
73
|
target: string;
|
|
72
|
-
style?: import(
|
|
74
|
+
style?: import('react').CSSProperties;
|
|
73
75
|
id: string;
|
|
74
76
|
zIndex?: number;
|
|
75
|
-
markerEnd?: import(
|
|
76
|
-
markerStart?: import(
|
|
77
|
+
markerEnd?: import('@xyflow/react').EdgeMarkerType;
|
|
78
|
+
markerStart?: import('@xyflow/react').EdgeMarkerType;
|
|
77
79
|
hidden?: boolean;
|
|
78
80
|
className?: string;
|
|
79
|
-
label?: import(
|
|
81
|
+
label?: import('react').ReactNode;
|
|
80
82
|
selected?: boolean;
|
|
81
83
|
selectable?: boolean;
|
|
82
84
|
deletable?: boolean;
|
|
@@ -86,26 +88,26 @@ export declare function useXYFlowEvents(): {
|
|
|
86
88
|
targetHandle?: string | null;
|
|
87
89
|
animated?: boolean;
|
|
88
90
|
interactionWidth?: number;
|
|
89
|
-
labelStyle?: import(
|
|
91
|
+
labelStyle?: import('react').CSSProperties;
|
|
90
92
|
labelShowBg?: boolean;
|
|
91
|
-
labelBgStyle?: import(
|
|
93
|
+
labelBgStyle?: import('react').CSSProperties;
|
|
92
94
|
labelBgPadding?: [number, number];
|
|
93
95
|
labelBgBorderRadius?: number;
|
|
94
|
-
updatable?: import(
|
|
95
|
-
data: import(
|
|
96
|
+
updatable?: import('@xyflow/react').EdgeUpdatable;
|
|
97
|
+
data: import('./types').RelationshipData;
|
|
96
98
|
type: "relationship";
|
|
97
|
-
}
|
|
98
|
-
onEdgeMouseLeave: import('
|
|
99
|
+
}) => void;
|
|
100
|
+
onEdgeMouseLeave: (event: import('react').MouseEvent<Element, MouseEvent>, xyedge: {
|
|
99
101
|
source: string;
|
|
100
102
|
target: string;
|
|
101
|
-
style?: import(
|
|
103
|
+
style?: import('react').CSSProperties;
|
|
102
104
|
id: string;
|
|
103
105
|
zIndex?: number;
|
|
104
|
-
markerEnd?: import(
|
|
105
|
-
markerStart?: import(
|
|
106
|
+
markerEnd?: import('@xyflow/react').EdgeMarkerType;
|
|
107
|
+
markerStart?: import('@xyflow/react').EdgeMarkerType;
|
|
106
108
|
hidden?: boolean;
|
|
107
109
|
className?: string;
|
|
108
|
-
label?: import(
|
|
110
|
+
label?: import('react').ReactNode;
|
|
109
111
|
selected?: boolean;
|
|
110
112
|
selectable?: boolean;
|
|
111
113
|
deletable?: boolean;
|
|
@@ -115,15 +117,19 @@ export declare function useXYFlowEvents(): {
|
|
|
115
117
|
targetHandle?: string | null;
|
|
116
118
|
animated?: boolean;
|
|
117
119
|
interactionWidth?: number;
|
|
118
|
-
labelStyle?: import(
|
|
120
|
+
labelStyle?: import('react').CSSProperties;
|
|
119
121
|
labelShowBg?: boolean;
|
|
120
|
-
labelBgStyle?: import(
|
|
122
|
+
labelBgStyle?: import('react').CSSProperties;
|
|
121
123
|
labelBgPadding?: [number, number];
|
|
122
124
|
labelBgBorderRadius?: number;
|
|
123
|
-
updatable?: import(
|
|
124
|
-
data: import(
|
|
125
|
+
updatable?: import('@xyflow/react').EdgeUpdatable;
|
|
126
|
+
data: import('./types').RelationshipData;
|
|
125
127
|
type: "relationship";
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
128
|
+
}) => void;
|
|
129
|
+
/**
|
|
130
|
+
* WOKAROUND:
|
|
131
|
+
* Viewport transform is not rounded to integers which results in blurry nodes on some resolution
|
|
132
|
+
* https://github.com/xyflow/xyflow/issues/3282
|
|
133
|
+
*/
|
|
134
|
+
onViewportChange: ({ x, y, zoom }: import('@xyflow/react').Viewport) => void;
|
|
129
135
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare const container: string;
|
|
2
2
|
export declare const edgePathBg: string;
|
|
3
3
|
export declare const fillStrokeCtx: string;
|
|
4
|
+
export declare const controlPoint: string;
|
|
4
5
|
export declare const cssEdgePath: string;
|
|
5
6
|
export declare const varLabelX: `var(--${string})` | `var(--${string}, ${string})` | `var(--${string}, ${number})`;
|
|
6
7
|
export declare const varLabelY: `var(--${string})` | `var(--${string}, ${string})` | `var(--${string}, ${number})`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@likec4/diagram",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
6
6
|
"homepage": "https://likec4.dev",
|
|
@@ -50,8 +50,9 @@
|
|
|
50
50
|
"clean": "run -T rimraf -v -g 'dist/*' .tsbuildinfo"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@likec4/core": "1.1.
|
|
53
|
+
"@likec4/core": "1.1.1",
|
|
54
54
|
"@react-hookz/web": "^24.0.4",
|
|
55
|
+
"d3-shape": "^3.2.0",
|
|
55
56
|
"esm-env": "^1.0.0",
|
|
56
57
|
"fast-equals": "^5.0.1",
|
|
57
58
|
"framer-motion": "^11.2.2",
|
|
@@ -70,6 +71,7 @@
|
|
|
70
71
|
"@mantine/hooks": "^7.9.2",
|
|
71
72
|
"@mantine/vanilla-extract": "^7.9.2",
|
|
72
73
|
"@total-typescript/ts-reset": "^0.5.1",
|
|
74
|
+
"@types/d3-shape": "^3",
|
|
73
75
|
"@types/react": "18.2.0",
|
|
74
76
|
"@types/react-dom": "18.2.4",
|
|
75
77
|
"@vanilla-extract/css": "^1.15.1",
|
package/src/LikeC4Diagram.css.ts
CHANGED
|
@@ -16,7 +16,8 @@ globalStyle(`.react-flow${cssReactFlow}`, {
|
|
|
16
16
|
}
|
|
17
17
|
})
|
|
18
18
|
globalStyle(`.react-flow${cssReactFlow} .react-flow__viewport`, {
|
|
19
|
-
willChange: 'transform'
|
|
19
|
+
// willChange: 'transform'
|
|
20
|
+
backfaceVisibility: 'hidden'
|
|
20
21
|
})
|
|
21
22
|
|
|
22
23
|
export const cssDisablePan = style({})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
BorderStyle,
|
|
2
3
|
DiagramEdge,
|
|
3
4
|
DiagramNode,
|
|
4
5
|
DiagramView,
|
|
@@ -10,8 +11,8 @@ import type {
|
|
|
10
11
|
} from '@likec4/core'
|
|
11
12
|
import type { MouseEvent as ReactMouseEvent } from 'react'
|
|
12
13
|
import type { SetRequired, Simplify } from 'type-fest'
|
|
13
|
-
import type { XYFlowEdge, XYFlowNode } from './xyflow/types'
|
|
14
14
|
import type { XYBackgroundProps } from './xyflow/XYFlowBackground'
|
|
15
|
+
import type { XYFlowEdge, XYFlowNode } from './xyflow/types'
|
|
15
16
|
|
|
16
17
|
export type DiagramNodeWithNavigate = Simplify<SetRequired<DiagramNode, 'navigateTo'>>
|
|
17
18
|
|
|
@@ -44,22 +45,20 @@ export type OnEdgeClick = (
|
|
|
44
45
|
export type OnCanvasClick = (event: ReactMouseEvent) => void
|
|
45
46
|
|
|
46
47
|
export namespace Changes {
|
|
47
|
-
export interface
|
|
48
|
-
op: 'change-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
shape: ElementShape
|
|
48
|
+
export interface ChangeElementStyle {
|
|
49
|
+
op: 'change-element-style'
|
|
50
|
+
style: {
|
|
51
|
+
border?: BorderStyle
|
|
52
|
+
opacity?: number
|
|
53
|
+
shape?: ElementShape
|
|
54
|
+
color?: ThemeColor
|
|
55
|
+
}
|
|
56
56
|
targets: NonEmptyArray<Fqn>
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
export type Change =
|
|
61
|
-
| Changes.
|
|
62
|
-
| Changes.ChangeShape
|
|
61
|
+
| Changes.ChangeElementStyle
|
|
63
62
|
|
|
64
63
|
export type ChangeEvent = {
|
|
65
64
|
changes: NonEmptyArray<Change>
|
|
@@ -139,6 +138,12 @@ export interface LikeC4DiagramProperties {
|
|
|
139
138
|
* @default true
|
|
140
139
|
*/
|
|
141
140
|
showElementLinks?: boolean | undefined
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Display panel with diagram title / description
|
|
144
|
+
* @default true
|
|
145
|
+
*/
|
|
146
|
+
showDiagramTitle?: boolean | undefined
|
|
142
147
|
}
|
|
143
148
|
|
|
144
149
|
export interface LikeC4DiagramEventHandlers {
|
package/src/LikeC4Diagram.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import { type LikeC4DiagramEventHandlers, type LikeC4DiagramProperties } from '.
|
|
|
8
8
|
import { EnsureMantine } from './mantine/EnsureMantine'
|
|
9
9
|
import { DiagramContextProvider } from './state/DiagramContext'
|
|
10
10
|
import { WhenInitialized } from './state/WhenInitialized'
|
|
11
|
+
import DiagramTitlePanel from './ui/DiagramTitlePanel'
|
|
11
12
|
import OptionsPanel from './ui/OptionsPanel'
|
|
12
13
|
import { diagramViewToXYFlowData } from './xyflow/diagram-to-xyflow'
|
|
13
14
|
import { FitViewOnDiagramChange } from './xyflow/FitviewOnDiagramChange'
|
|
@@ -29,6 +30,7 @@ export function LikeC4Diagram({
|
|
|
29
30
|
background = 'dots',
|
|
30
31
|
controls = false,
|
|
31
32
|
showElementLinks = true,
|
|
33
|
+
showDiagramTitle = true,
|
|
32
34
|
initialWidth,
|
|
33
35
|
initialHeight,
|
|
34
36
|
keepAspectRatio = false,
|
|
@@ -106,6 +108,7 @@ export function LikeC4Diagram({
|
|
|
106
108
|
defaultEdges={initialRef.current.defaultEdges}
|
|
107
109
|
>
|
|
108
110
|
{readonly !== true && <OptionsPanel />}
|
|
111
|
+
{showDiagramTitle === true && <DiagramTitlePanel />}
|
|
109
112
|
</XYFlow>
|
|
110
113
|
</KeepAspectRatioContainer>
|
|
111
114
|
<WhenInitialized>
|
package/src/globals.css.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defaultTheme } from '@likec4/core'
|
|
2
|
-
import { createGlobalTheme } from '@vanilla-extract/css'
|
|
2
|
+
import { createGlobalTheme, globalStyle } from '@vanilla-extract/css'
|
|
3
3
|
import { scale, toHex } from 'khroma'
|
|
4
4
|
import { keys, omit } from 'remeda'
|
|
5
5
|
import { mantine } from './mantine.css'
|
|
@@ -7,6 +7,11 @@ import { vars } from './theme.css'
|
|
|
7
7
|
|
|
8
8
|
export const rootClassName = 'likec4-diagram-root'
|
|
9
9
|
|
|
10
|
+
globalStyle(`.${rootClassName}`, {
|
|
11
|
+
WebkitFontSmoothing: mantine.webkitFontSmoothing,
|
|
12
|
+
MozOsxFontSmoothing: mantine.mozFontSmoothing
|
|
13
|
+
})
|
|
14
|
+
|
|
10
15
|
createGlobalTheme(`.${rootClassName}`, {
|
|
11
16
|
...omit(vars, ['optionsPanel', 'default'])
|
|
12
17
|
}, {
|
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
BorderStyle,
|
|
3
|
+
DiagramNode,
|
|
4
|
+
DiagramView,
|
|
5
|
+
ElementShape,
|
|
6
|
+
Fqn,
|
|
7
|
+
NonEmptyArray,
|
|
8
|
+
ThemeColor,
|
|
9
|
+
ViewID
|
|
10
|
+
} from '@likec4/core'
|
|
2
11
|
import { invariant, nonexhaustive } from '@likec4/core'
|
|
3
12
|
import type { XYPosition } from '@xyflow/react'
|
|
4
13
|
import { getNodeDimensions } from '@xyflow/system'
|
|
5
14
|
import { DEV } from 'esm-env'
|
|
6
15
|
import { shallowEqual } from 'fast-equals'
|
|
7
16
|
import type { MouseEvent as ReactMouseEvent } from 'react'
|
|
17
|
+
import { entries } from 'remeda'
|
|
8
18
|
import type { Exact, Except, RequiredKeysOf, Simplify } from 'type-fest'
|
|
9
19
|
import { devtools, subscribeWithSelector } from 'zustand/middleware'
|
|
10
20
|
import { shallow } from 'zustand/shallow'
|
|
@@ -83,6 +93,8 @@ interface DiagramStoreActions {
|
|
|
83
93
|
setLastClickedNode: (nodeId: string | null) => void
|
|
84
94
|
setLastClickedEdge: (edgeId: string | null) => void
|
|
85
95
|
|
|
96
|
+
resetLastClicked: () => void
|
|
97
|
+
|
|
86
98
|
getElement(id: Fqn): DiagramNode | null
|
|
87
99
|
triggerOnChange: (changes: NonEmptyArray<Change>) => void
|
|
88
100
|
triggerOnNavigateTo: (xynodeId: string, event: ReactMouseEvent) => void
|
|
@@ -230,88 +242,114 @@ export function createDiagramStore<T extends Exact<CreateDiagramStore, T>>(props
|
|
|
230
242
|
}
|
|
231
243
|
},
|
|
232
244
|
|
|
245
|
+
resetLastClicked: () => {
|
|
246
|
+
let {
|
|
247
|
+
focusedNodeId,
|
|
248
|
+
lastClickedNodeId,
|
|
249
|
+
lastClickedEdgeId
|
|
250
|
+
} = get()
|
|
251
|
+
if (focusedNodeId || lastClickedNodeId || lastClickedEdgeId) {
|
|
252
|
+
set(
|
|
253
|
+
{
|
|
254
|
+
focusedNodeId: null,
|
|
255
|
+
lastClickedNodeId: null,
|
|
256
|
+
lastClickedEdgeId: null
|
|
257
|
+
},
|
|
258
|
+
noReplace,
|
|
259
|
+
'resetLastClicked'
|
|
260
|
+
)
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
|
|
233
264
|
getElement: (fqn) => {
|
|
234
265
|
const { view } = get()
|
|
235
266
|
return view.nodes.find(({ id }) => id === fqn) ?? null
|
|
236
267
|
},
|
|
237
268
|
|
|
238
269
|
triggerOnChange: (changes: NonEmptyArray<Change>) => {
|
|
270
|
+
if (DEV) {
|
|
271
|
+
console.debug('triggerOnChange', changes)
|
|
272
|
+
}
|
|
239
273
|
const newShapes = new Map<Fqn, ElementShape>()
|
|
240
274
|
const newColor = new Map<Fqn, ThemeColor>()
|
|
275
|
+
const newOpacity = new Map<Fqn, number>()
|
|
276
|
+
const newBorder = new Map<Fqn, BorderStyle>()
|
|
241
277
|
for (const change of changes) {
|
|
242
|
-
if (change.op
|
|
243
|
-
|
|
244
|
-
newShapes.set(target, change.shape)
|
|
245
|
-
}
|
|
246
|
-
continue
|
|
278
|
+
if (change.op !== 'change-element-style') {
|
|
279
|
+
nonexhaustive(change.op)
|
|
247
280
|
}
|
|
248
|
-
|
|
249
|
-
for (const
|
|
250
|
-
|
|
281
|
+
for (const target of change.targets) {
|
|
282
|
+
for (const [key, value] of entries.strict(change.style)) {
|
|
283
|
+
switch (key) {
|
|
284
|
+
case 'shape':
|
|
285
|
+
newShapes.set(target, value)
|
|
286
|
+
break
|
|
287
|
+
case 'color':
|
|
288
|
+
newColor.set(target, value)
|
|
289
|
+
break
|
|
290
|
+
case 'opacity':
|
|
291
|
+
newOpacity.set(target, value)
|
|
292
|
+
break
|
|
293
|
+
case 'border':
|
|
294
|
+
newBorder.set(target, value)
|
|
295
|
+
break
|
|
296
|
+
default:
|
|
297
|
+
nonexhaustive(key)
|
|
298
|
+
}
|
|
251
299
|
}
|
|
252
|
-
continue
|
|
253
300
|
}
|
|
254
|
-
nonexhaustive(change)
|
|
255
301
|
}
|
|
256
|
-
|
|
257
|
-
// const { view, updateView } = get()
|
|
258
|
-
// let hasChanges = false
|
|
259
|
-
// const nextNodes = view.nodes.map((node) => {
|
|
260
|
-
// const shape = newShapes.get(node.id)
|
|
261
|
-
// if (shape && shape !== node.shape) {
|
|
262
|
-
// hasChanges = true
|
|
263
|
-
// node = {
|
|
264
|
-
// ...node,
|
|
265
|
-
// shape
|
|
266
|
-
// }
|
|
267
|
-
// }
|
|
268
|
-
// const color = newColor.get(node.id)
|
|
269
|
-
// if (color && color !== node.color) {
|
|
270
|
-
// hasChanges = true
|
|
271
|
-
// node = {
|
|
272
|
-
// ...node,
|
|
273
|
-
// color
|
|
274
|
-
// }
|
|
275
|
-
// }
|
|
276
|
-
// return node
|
|
277
|
-
// })
|
|
278
|
-
// if (hasChanges) {
|
|
279
|
-
// updateView({
|
|
280
|
-
// ...view,
|
|
281
|
-
// nodes: nextNodes
|
|
282
|
-
// })
|
|
283
|
-
// }
|
|
302
|
+
|
|
284
303
|
get().xyflow.setNodes(nodes =>
|
|
285
304
|
nodes.map(node => {
|
|
286
|
-
let
|
|
287
|
-
const shape = newShapes.get(
|
|
288
|
-
if (shape && shape !==
|
|
289
|
-
|
|
290
|
-
...
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
305
|
+
let element = node.data.element
|
|
306
|
+
const shape = newShapes.get(element.id)
|
|
307
|
+
if (shape && shape !== element.shape) {
|
|
308
|
+
element = {
|
|
309
|
+
...element,
|
|
310
|
+
shape
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
const color = newColor.get(element.id)
|
|
314
|
+
if (color && color !== element.color) {
|
|
315
|
+
element = {
|
|
316
|
+
...element,
|
|
317
|
+
color
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const opacity = newOpacity.get(element.id)
|
|
322
|
+
if (!!opacity && opacity !== element.style?.opacity) {
|
|
323
|
+
element = {
|
|
324
|
+
...element,
|
|
325
|
+
style: {
|
|
326
|
+
...element.style,
|
|
327
|
+
opacity
|
|
297
328
|
}
|
|
298
329
|
}
|
|
299
|
-
data = node.data
|
|
300
330
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
element
|
|
308
|
-
|
|
309
|
-
color
|
|
310
|
-
}
|
|
331
|
+
|
|
332
|
+
const border = newBorder.get(element.id)
|
|
333
|
+
if (border && border !== element.style?.border) {
|
|
334
|
+
element = {
|
|
335
|
+
...element,
|
|
336
|
+
style: {
|
|
337
|
+
...element.style,
|
|
338
|
+
border
|
|
311
339
|
}
|
|
312
340
|
}
|
|
313
341
|
}
|
|
314
|
-
|
|
342
|
+
|
|
343
|
+
if (element === node.data.element) {
|
|
344
|
+
return node
|
|
345
|
+
}
|
|
346
|
+
return {
|
|
347
|
+
...node,
|
|
348
|
+
data: {
|
|
349
|
+
...node.data,
|
|
350
|
+
element
|
|
351
|
+
}
|
|
352
|
+
}
|
|
315
353
|
})
|
|
316
354
|
)
|
|
317
355
|
get().onChange?.({ changes })
|
|
@@ -353,7 +391,7 @@ export function createDiagramStore<T extends Exact<CreateDiagramStore, T>>(props
|
|
|
353
391
|
xyflow.fitView({
|
|
354
392
|
includeHiddenNodes: true,
|
|
355
393
|
duration: (centerNode && focusedNodeId) ? 300 : 400,
|
|
356
|
-
padding:
|
|
394
|
+
padding: fitViewPadding,
|
|
357
395
|
minZoom: MinZoom,
|
|
358
396
|
maxZoom: 1,
|
|
359
397
|
...(centerNode && { nodes: [centerNode] })
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { globalStyle, style } from '@vanilla-extract/css'
|
|
2
|
+
import { mantine } from '../mantine.css'
|
|
3
|
+
|
|
4
|
+
export const container = style({
|
|
5
|
+
bottom: 0,
|
|
6
|
+
left: 0,
|
|
7
|
+
padding: 8,
|
|
8
|
+
margin: 0
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
export const paper = style({
|
|
12
|
+
cursor: 'default',
|
|
13
|
+
minWidth: 200,
|
|
14
|
+
maxWidth: 'calc(100vw - 16px)',
|
|
15
|
+
backgroundColor: `color-mix(in srgb, ${mantine.colors.body}, transparent 20%)`,
|
|
16
|
+
backdropFilter: 'blur(8px)',
|
|
17
|
+
'@media': {
|
|
18
|
+
[mantine.largerThan('md')]: {
|
|
19
|
+
maxWidth: '45vw'
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
export const title = style({})
|
|
25
|
+
|
|
26
|
+
export const description = style({
|
|
27
|
+
whiteSpaceCollapse: 'preserve-breaks',
|
|
28
|
+
color: mantine.colors.gray[7]
|
|
29
|
+
})
|
|
30
|
+
globalStyle(`:where([data-mantine-color-scheme="dark"]) ${description}`, {
|
|
31
|
+
color: mantine.colors.gray[5]
|
|
32
|
+
})
|