orcasvn-react-diagrams 0.2.2 → 0.2.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/CHANGELOG.md +51 -0
- package/README.md +11 -3
- package/dist/cjs/examples.js +1768 -161
- package/dist/cjs/index.js +786 -120
- package/dist/cjs/types/api/createDiagramEditor.d.ts +19 -1
- package/dist/cjs/types/api/index.d.ts +1 -1
- package/dist/cjs/types/api/types.d.ts +32 -0
- package/dist/cjs/types/displaybox/DisplayBoxControls.d.ts +5 -1
- package/dist/cjs/types/displaybox/demos/AsymmetricPortMultiAnchorDemoTab.d.ts +3 -0
- package/dist/cjs/types/displaybox/demos/LayoutLabelReservedSpaceDemoTab.d.ts +3 -0
- package/dist/cjs/types/displaybox/demos/VertexControlLinkSessionDemoTab.d.ts +3 -0
- package/dist/cjs/types/displaybox/demos/asymmetricPortMultiAnchorDemo.d.ts +31 -0
- package/dist/cjs/types/displaybox/demos/layoutLabelReservedSpaceDemo.d.ts +11 -0
- package/dist/cjs/types/displaybox/demos/vertexControlLinkSessionDemo.d.ts +12 -0
- package/dist/cjs/types/displaybox/useDemoControls.d.ts +4 -0
- package/dist/cjs/types/engine/AutoLayoutService.d.ts +2 -0
- package/dist/cjs/types/engine/DiagramEngine.d.ts +5 -0
- package/dist/cjs/types/engine/LinkRoutingService.d.ts +9 -1
- package/dist/cjs/types/models/PortModel.d.ts +5 -0
- package/dist/cjs/types/renderer/RenderTypes.d.ts +3 -1
- package/dist/cjs/types/renderer/konva/KonvaInteraction.d.ts +14 -0
- package/dist/cjs/types/renderer/konva/KonvaNodeFactory.d.ts +1 -0
- package/dist/cjs/types/renderer/konva/KonvaRenderer.d.ts +0 -1
- package/dist/cjs/types/shapes/BuiltInShapes.d.ts +3 -1
- package/dist/cjs/types/utils/__tests__/portGeometry.test.d.ts +1 -0
- package/dist/cjs/types/utils/portGeometry.d.ts +44 -0
- package/dist/esm/examples.js +1769 -162
- package/dist/esm/examples.js.map +1 -1
- package/dist/esm/index.js +786 -120
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/api/createDiagramEditor.d.ts +19 -1
- package/dist/esm/types/api/index.d.ts +1 -1
- package/dist/esm/types/api/types.d.ts +32 -0
- package/dist/esm/types/displaybox/DisplayBoxControls.d.ts +5 -1
- package/dist/esm/types/displaybox/demos/AsymmetricPortMultiAnchorDemoTab.d.ts +3 -0
- package/dist/esm/types/displaybox/demos/LayoutLabelReservedSpaceDemoTab.d.ts +3 -0
- package/dist/esm/types/displaybox/demos/VertexControlLinkSessionDemoTab.d.ts +3 -0
- package/dist/esm/types/displaybox/demos/asymmetricPortMultiAnchorDemo.d.ts +31 -0
- package/dist/esm/types/displaybox/demos/layoutLabelReservedSpaceDemo.d.ts +11 -0
- package/dist/esm/types/displaybox/demos/vertexControlLinkSessionDemo.d.ts +12 -0
- package/dist/esm/types/displaybox/useDemoControls.d.ts +4 -0
- package/dist/esm/types/engine/AutoLayoutService.d.ts +2 -0
- package/dist/esm/types/engine/DiagramEngine.d.ts +5 -0
- package/dist/esm/types/engine/LinkRoutingService.d.ts +9 -1
- package/dist/esm/types/models/PortModel.d.ts +5 -0
- package/dist/esm/types/renderer/RenderTypes.d.ts +3 -1
- package/dist/esm/types/renderer/konva/KonvaInteraction.d.ts +14 -0
- package/dist/esm/types/renderer/konva/KonvaNodeFactory.d.ts +1 -0
- package/dist/esm/types/renderer/konva/KonvaRenderer.d.ts +0 -1
- package/dist/esm/types/shapes/BuiltInShapes.d.ts +3 -1
- package/dist/esm/types/utils/__tests__/portGeometry.test.d.ts +1 -0
- package/dist/esm/types/utils/portGeometry.d.ts +44 -0
- package/dist/examples.d.ts +50 -0
- package/dist/index.d.ts +58 -1
- package/package.json +11 -10
- package/src/displaybox/demos/AsymmetricPortMultiAnchorDemoTab.tsx +269 -0
- package/src/displaybox/demos/AutoLayoutDemoTab.tsx +113 -11
- package/src/displaybox/demos/DeletionEventsDemoTab.tsx +6 -1
- package/src/displaybox/demos/EngineEventsDemoTab.tsx +5 -0
- package/src/displaybox/demos/EventHandlersDemoTab.tsx +5 -0
- package/src/displaybox/demos/ExternalDragDropDemoTab.tsx +5 -0
- package/src/displaybox/demos/LayoutLabelReservedSpaceDemoTab.tsx +291 -0
- package/src/displaybox/demos/LinkCancelDemoTab.tsx +5 -0
- package/src/displaybox/demos/ShapeHoverControlsDemoTab.tsx +6 -1
- package/src/displaybox/demos/SimpleDemo.tsx +5 -0
- package/src/displaybox/demos/SvgPathDemoTab.tsx +5 -0
- package/src/displaybox/demos/TextLayoutDemoTab.tsx +6 -1
- package/src/displaybox/demos/VertexControlLinkSessionDemoTab.tsx +302 -0
- package/src/displaybox/demos/asymmetricPortMultiAnchorDemo.ts +357 -0
- package/src/displaybox/demos/autoLayoutDemo.ts +23 -5
- package/src/displaybox/demos/index.tsx +91 -75
- package/src/displaybox/demos/layoutLabelReservedSpaceDemo.ts +121 -0
- package/src/displaybox/demos/vertexControlLinkSessionDemo.ts +145 -0
|
@@ -82,6 +82,10 @@ const EventHandlersDemo = () => {
|
|
|
82
82
|
onManualRender={controls.handleManualRender}
|
|
83
83
|
onToggleLinkRouting={controls.handleToggleLinkRouting}
|
|
84
84
|
onAction={controls.handleAction}
|
|
85
|
+
onExportImage={controls.handleExportImage}
|
|
86
|
+
onClearExportPreview={controls.handleClearExportPreview}
|
|
87
|
+
exportPreviewDataUrl={controls.exportPreviewDataUrl}
|
|
88
|
+
exportError={controls.exportError}
|
|
85
89
|
/>
|
|
86
90
|
<div style={{ display: 'flex', gap: 12, alignItems: 'center', marginBottom: 12 }}>
|
|
87
91
|
<label htmlFor="event-handler-select" style={{ fontWeight: 600 }}>
|
|
@@ -108,3 +112,4 @@ const EventHandlersDemo = () => {
|
|
|
108
112
|
};
|
|
109
113
|
|
|
110
114
|
export default EventHandlersDemo;
|
|
115
|
+
|
|
@@ -167,6 +167,10 @@ const ExternalDragDropDemo = () => {
|
|
|
167
167
|
onManualRender={controls.handleManualRender}
|
|
168
168
|
onToggleLinkRouting={controls.handleToggleLinkRouting}
|
|
169
169
|
onAction={controls.handleAction}
|
|
170
|
+
onExportImage={controls.handleExportImage}
|
|
171
|
+
onClearExportPreview={controls.handleClearExportPreview}
|
|
172
|
+
exportPreviewDataUrl={controls.exportPreviewDataUrl}
|
|
173
|
+
exportError={controls.exportError}
|
|
170
174
|
/>
|
|
171
175
|
<div style={{ display: 'flex', gap: 16, marginBottom: 12, alignItems: 'stretch' }}>
|
|
172
176
|
<div
|
|
@@ -259,3 +263,4 @@ const ExternalDragDropDemo = () => {
|
|
|
259
263
|
};
|
|
260
264
|
|
|
261
265
|
export default ExternalDragDropDemo;
|
|
266
|
+
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import React, { useMemo, useState } from 'react';
|
|
2
|
+
import type {
|
|
3
|
+
DiagramState,
|
|
4
|
+
ElementLayout,
|
|
5
|
+
ElementLayoutChildFitCrossAxis,
|
|
6
|
+
ElementLayoutChildFitMainAxis,
|
|
7
|
+
ElementLayoutLabelReservedSpaceMode,
|
|
8
|
+
} from '../../api';
|
|
9
|
+
import DisplayBoxControls from '../DisplayBoxControls';
|
|
10
|
+
import DisplayBoxStage from '../DisplayBoxStage';
|
|
11
|
+
import useDemoControls from '../useDemoControls';
|
|
12
|
+
import useDemoEditor from '../useDemoEditor';
|
|
13
|
+
import useOffsetSequence from '../useOffsetSequence';
|
|
14
|
+
import type { DemoActionHelpers } from '../types';
|
|
15
|
+
import { gridStageStyle } from './shared';
|
|
16
|
+
import { layoutLabelReservedSpaceDemoConfig, layoutReservedDemoIds } from './layoutLabelReservedSpaceDemo';
|
|
17
|
+
|
|
18
|
+
const shortLabel = 'Parent label lane demo';
|
|
19
|
+
const longLabel =
|
|
20
|
+
'Parent label lane demo with long wrapped content that expands height and pushes children lower in flexible mode.';
|
|
21
|
+
|
|
22
|
+
const clamp = (value: number, min: number, max: number): number => Math.max(min, Math.min(max, value));
|
|
23
|
+
|
|
24
|
+
const resolveLaneFromState = (state: DiagramState, parentId: string): number => {
|
|
25
|
+
const parent = state.elements.find((element) => element.id === parentId);
|
|
26
|
+
const policy = parent?.layout?.labelReservedSpace;
|
|
27
|
+
if (!parent || !policy) return 0;
|
|
28
|
+
const mode = policy.mode ?? 'none';
|
|
29
|
+
if (mode === 'none') return 0;
|
|
30
|
+
let lane = 0;
|
|
31
|
+
if (mode === 'fixed') {
|
|
32
|
+
lane = Math.max(0, policy.size ?? 0);
|
|
33
|
+
} else {
|
|
34
|
+
state.texts.forEach((text) => {
|
|
35
|
+
if (text.ownerId !== parentId) return;
|
|
36
|
+
const offsetY = text.displayOffset?.y ?? 0;
|
|
37
|
+
const height = text.displayClipSize?.height ?? text.size?.height ?? 0;
|
|
38
|
+
lane = Math.max(lane, text.position.y + offsetY + height);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
const minSize = Math.max(0, policy.minSize ?? 0);
|
|
42
|
+
const maxSize = policy.maxSize !== undefined ? Math.max(minSize, policy.maxSize) : Number.POSITIVE_INFINITY;
|
|
43
|
+
return clamp(lane, minSize, maxSize);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const LayoutLabelReservedSpaceDemo = () => {
|
|
47
|
+
const demo = layoutLabelReservedSpaceDemoConfig;
|
|
48
|
+
const { containerRef, editorRef, diagramState, selection, snapEnabled, setSnapEnabled } = useDemoEditor({
|
|
49
|
+
createState: demo.createState,
|
|
50
|
+
elementShapes: demo.elementShapes,
|
|
51
|
+
portShapes: demo.portShapes,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const nextOffset = useOffsetSequence();
|
|
55
|
+
const actionHelpers: DemoActionHelpers = useMemo(() => ({ nextOffset }), [nextOffset]);
|
|
56
|
+
const controls = useDemoControls({
|
|
57
|
+
demo,
|
|
58
|
+
editorRef,
|
|
59
|
+
diagramState,
|
|
60
|
+
selection,
|
|
61
|
+
snapEnabled,
|
|
62
|
+
setSnapEnabled,
|
|
63
|
+
actionHelpers,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const [mode, setMode] = useState<ElementLayoutLabelReservedSpaceMode>('none');
|
|
67
|
+
const [fixedSize, setFixedSize] = useState(32);
|
|
68
|
+
const [minSize, setMinSize] = useState<number | ''>('');
|
|
69
|
+
const [maxSize, setMaxSize] = useState<number | ''>('');
|
|
70
|
+
const [childFitMainAxis, setChildFitMainAxis] = useState<ElementLayoutChildFitMainAxis>('none');
|
|
71
|
+
const [childFitCrossAxis, setChildFitCrossAxis] = useState<ElementLayoutChildFitCrossAxis>('none');
|
|
72
|
+
|
|
73
|
+
const parent = useMemo(
|
|
74
|
+
() => diagramState?.elements.find((element) => element.id === layoutReservedDemoIds.parent),
|
|
75
|
+
[diagramState],
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const effectiveLane = useMemo(() => {
|
|
79
|
+
if (!diagramState) return 0;
|
|
80
|
+
return resolveLaneFromState(diagramState, layoutReservedDemoIds.parent);
|
|
81
|
+
}, [diagramState]);
|
|
82
|
+
|
|
83
|
+
const childBounds = useMemo(() => {
|
|
84
|
+
if (!parent) return { x: 0, y: 0, width: 0, height: 0 };
|
|
85
|
+
const paddingRaw = parent.layout?.padding ?? 12;
|
|
86
|
+
const padding = typeof paddingRaw === 'number' ? paddingRaw : Math.max(paddingRaw.x ?? 0, paddingRaw.y ?? 0);
|
|
87
|
+
return {
|
|
88
|
+
x: padding,
|
|
89
|
+
y: padding + effectiveLane,
|
|
90
|
+
width: Math.max(0, parent.size.width - padding * 2),
|
|
91
|
+
height: Math.max(0, parent.size.height - padding * 2 - effectiveLane),
|
|
92
|
+
};
|
|
93
|
+
}, [parent, effectiveLane]);
|
|
94
|
+
|
|
95
|
+
const applyLayout = () => {
|
|
96
|
+
if (!editorRef.current) return;
|
|
97
|
+
const labelReservedSpace: NonNullable<ElementLayout['labelReservedSpace']> = {
|
|
98
|
+
mode,
|
|
99
|
+
placement: 'top',
|
|
100
|
+
...(mode === 'fixed' ? { size: fixedSize } : {}),
|
|
101
|
+
...(minSize === '' ? {} : { minSize }),
|
|
102
|
+
...(maxSize === '' ? {} : { maxSize }),
|
|
103
|
+
};
|
|
104
|
+
editorRef.current.setElementLayout(layoutReservedDemoIds.parent, {
|
|
105
|
+
mode: 'horizontal',
|
|
106
|
+
padding: 12,
|
|
107
|
+
gap: 10,
|
|
108
|
+
align: 'start',
|
|
109
|
+
childFitMainAxis,
|
|
110
|
+
childFitCrossAxis,
|
|
111
|
+
labelReservedSpace,
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const setLabelContent = (value: string) => {
|
|
116
|
+
editorRef.current?.updateText(layoutReservedDemoIds.parentLabel, value);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const children = useMemo(() => {
|
|
120
|
+
if (!diagramState) return [];
|
|
121
|
+
return diagramState.elements.filter((element) => element.parentId === layoutReservedDemoIds.parent);
|
|
122
|
+
}, [diagramState]);
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<section>
|
|
126
|
+
<div style={{ marginBottom: 12 }}>
|
|
127
|
+
<h2 style={{ marginTop: 0, marginBottom: 4 }}>{demo.title}</h2>
|
|
128
|
+
<p style={{ marginTop: 0 }}>{demo.description}</p>
|
|
129
|
+
</div>
|
|
130
|
+
<DisplayBoxControls
|
|
131
|
+
actions={demo.actions}
|
|
132
|
+
snapEnabled={controls.snapEnabled}
|
|
133
|
+
selectedLinkRouting={controls.selectedLinkRouting}
|
|
134
|
+
canToggleLinkRouting={controls.canToggleLinkRouting}
|
|
135
|
+
onReload={controls.handleReload}
|
|
136
|
+
onZoomIn={controls.handleZoomIn}
|
|
137
|
+
onZoomOut={controls.handleZoomOut}
|
|
138
|
+
onResetViewport={controls.handleResetViewport}
|
|
139
|
+
onToggleSnap={controls.handleToggleSnap}
|
|
140
|
+
onManualRender={controls.handleManualRender}
|
|
141
|
+
onToggleLinkRouting={controls.handleToggleLinkRouting}
|
|
142
|
+
onAction={controls.handleAction}
|
|
143
|
+
onExportImage={controls.handleExportImage}
|
|
144
|
+
onClearExportPreview={controls.handleClearExportPreview}
|
|
145
|
+
exportPreviewDataUrl={controls.exportPreviewDataUrl}
|
|
146
|
+
exportError={controls.exportError}
|
|
147
|
+
/>
|
|
148
|
+
|
|
149
|
+
<div style={{ marginBottom: 12, padding: 12, border: '1px solid #d9e1ec', borderRadius: 8, background: '#fbfdff' }}>
|
|
150
|
+
<div style={{ fontWeight: 700, marginBottom: 8 }}>Scenario controls</div>
|
|
151
|
+
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 10, alignItems: 'center', marginBottom: 10 }}>
|
|
152
|
+
<label style={{ fontSize: 13 }}>
|
|
153
|
+
Mode
|
|
154
|
+
<select value={mode} onChange={(event) => setMode(event.target.value as ElementLayoutLabelReservedSpaceMode)} style={{ marginLeft: 8 }}>
|
|
155
|
+
<option value="none">none</option>
|
|
156
|
+
<option value="fixed">fixed</option>
|
|
157
|
+
<option value="flexible">flexible</option>
|
|
158
|
+
</select>
|
|
159
|
+
</label>
|
|
160
|
+
<label style={{ fontSize: 13 }}>
|
|
161
|
+
Fixed size
|
|
162
|
+
<input
|
|
163
|
+
type="number"
|
|
164
|
+
value={fixedSize}
|
|
165
|
+
onChange={(event) => setFixedSize(Math.max(0, Number(event.target.value) || 0))}
|
|
166
|
+
style={{ width: 74, marginLeft: 8 }}
|
|
167
|
+
min={0}
|
|
168
|
+
/>
|
|
169
|
+
</label>
|
|
170
|
+
<label style={{ fontSize: 13 }}>
|
|
171
|
+
Min
|
|
172
|
+
<input
|
|
173
|
+
type="number"
|
|
174
|
+
value={minSize}
|
|
175
|
+
onChange={(event) => setMinSize(event.target.value === '' ? '' : Math.max(0, Number(event.target.value) || 0))}
|
|
176
|
+
style={{ width: 74, marginLeft: 8 }}
|
|
177
|
+
min={0}
|
|
178
|
+
/>
|
|
179
|
+
</label>
|
|
180
|
+
<label style={{ fontSize: 13 }}>
|
|
181
|
+
Max
|
|
182
|
+
<input
|
|
183
|
+
type="number"
|
|
184
|
+
value={maxSize}
|
|
185
|
+
onChange={(event) => setMaxSize(event.target.value === '' ? '' : Math.max(0, Number(event.target.value) || 0))}
|
|
186
|
+
style={{ width: 74, marginLeft: 8 }}
|
|
187
|
+
min={0}
|
|
188
|
+
/>
|
|
189
|
+
</label>
|
|
190
|
+
<label style={{ fontSize: 13 }}>
|
|
191
|
+
Main-axis fit
|
|
192
|
+
<select
|
|
193
|
+
value={childFitMainAxis}
|
|
194
|
+
onChange={(event) => setChildFitMainAxis(event.target.value as ElementLayoutChildFitMainAxis)}
|
|
195
|
+
style={{ marginLeft: 8 }}
|
|
196
|
+
>
|
|
197
|
+
<option value="none">none</option>
|
|
198
|
+
<option value="distribute">distribute</option>
|
|
199
|
+
</select>
|
|
200
|
+
</label>
|
|
201
|
+
<label style={{ fontSize: 13 }}>
|
|
202
|
+
Cross-axis fit
|
|
203
|
+
<select
|
|
204
|
+
value={childFitCrossAxis}
|
|
205
|
+
onChange={(event) => setChildFitCrossAxis(event.target.value as ElementLayoutChildFitCrossAxis)}
|
|
206
|
+
style={{ marginLeft: 8 }}
|
|
207
|
+
>
|
|
208
|
+
<option value="none">none</option>
|
|
209
|
+
<option value="stretch">stretch</option>
|
|
210
|
+
</select>
|
|
211
|
+
</label>
|
|
212
|
+
<button type="button" onClick={applyLayout} style={{ padding: '6px 12px', fontWeight: 600 }}>
|
|
213
|
+
Apply
|
|
214
|
+
</button>
|
|
215
|
+
</div>
|
|
216
|
+
|
|
217
|
+
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginBottom: 10 }}>
|
|
218
|
+
<button type="button" onClick={() => setLabelContent(shortLabel)} style={{ padding: '6px 10px' }}>
|
|
219
|
+
Flexible label: short
|
|
220
|
+
</button>
|
|
221
|
+
<button type="button" onClick={() => setLabelContent(longLabel)} style={{ padding: '6px 10px' }}>
|
|
222
|
+
Flexible label: long
|
|
223
|
+
</button>
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
<div style={{ display: 'grid', gridTemplateColumns: 'minmax(300px, 1fr) minmax(260px, 1fr)', gap: 12 }}>
|
|
227
|
+
<div>
|
|
228
|
+
<div style={{ fontWeight: 600, marginBottom: 6 }}>Visual guide</div>
|
|
229
|
+
<svg width="320" height="180" viewBox="0 0 320 180" style={{ background: '#fff', border: '1px solid #e0e6ef', borderRadius: 6 }}>
|
|
230
|
+
<rect x="16" y="16" width="288" height="148" fill="#f5f8fd" stroke="#9fb6d6" strokeWidth="2" />
|
|
231
|
+
<rect
|
|
232
|
+
x={16 + (childBounds.x / Math.max(1, parent?.size.width ?? 1)) * 288}
|
|
233
|
+
y={16 + ((childBounds.y - effectiveLane) / Math.max(1, parent?.size.height ?? 1)) * 148}
|
|
234
|
+
width={(childBounds.width / Math.max(1, parent?.size.width ?? 1)) * 288}
|
|
235
|
+
height={(effectiveLane / Math.max(1, parent?.size.height ?? 1)) * 148}
|
|
236
|
+
fill="rgba(255,122,0,0.25)"
|
|
237
|
+
stroke="#ff7a00"
|
|
238
|
+
/>
|
|
239
|
+
<rect
|
|
240
|
+
x={16 + (childBounds.x / Math.max(1, parent?.size.width ?? 1)) * 288}
|
|
241
|
+
y={16 + (childBounds.y / Math.max(1, parent?.size.height ?? 1)) * 148}
|
|
242
|
+
width={(childBounds.width / Math.max(1, parent?.size.width ?? 1)) * 288}
|
|
243
|
+
height={(childBounds.height / Math.max(1, parent?.size.height ?? 1)) * 148}
|
|
244
|
+
fill="rgba(31,77,153,0.08)"
|
|
245
|
+
stroke="#1f4d99"
|
|
246
|
+
strokeDasharray="6 4"
|
|
247
|
+
/>
|
|
248
|
+
<text x="22" y="30" fontSize="11" fill="#24415f">
|
|
249
|
+
Parent bounds
|
|
250
|
+
</text>
|
|
251
|
+
<text x="22" y="46" fontSize="11" fill="#8a4a00">
|
|
252
|
+
Reserved lane
|
|
253
|
+
</text>
|
|
254
|
+
<text x="22" y="62" fontSize="11" fill="#1f4d99">
|
|
255
|
+
Child layout bounds
|
|
256
|
+
</text>
|
|
257
|
+
</svg>
|
|
258
|
+
</div>
|
|
259
|
+
<div>
|
|
260
|
+
<div style={{ fontWeight: 600, marginBottom: 6 }}>Verification</div>
|
|
261
|
+
<ol style={{ marginTop: 0, paddingLeft: 20, fontSize: 13 }}>
|
|
262
|
+
<li>Set mode none and apply: children can use the normal top area.</li>
|
|
263
|
+
<li>Set mode fixed (for example 32) and apply: children shift below lane.</li>
|
|
264
|
+
<li>Set mode flexible, apply, then switch label short/long to trigger relayout.</li>
|
|
265
|
+
<li>Enable distribute/stretch and apply to confirm fit options stay deterministic.</li>
|
|
266
|
+
<li>Inspect nested parent block on canvas to verify nested layout consistency.</li>
|
|
267
|
+
</ol>
|
|
268
|
+
<div style={{ fontSize: 13 }}>
|
|
269
|
+
Effective lane: <strong>{Math.round(effectiveLane)} px</strong>
|
|
270
|
+
</div>
|
|
271
|
+
<div style={{ fontSize: 12, marginTop: 4 }}>
|
|
272
|
+
Child bounds (relative): x {Math.round(childBounds.x)}, y {Math.round(childBounds.y)}, w {Math.round(childBounds.width)}, h {Math.round(childBounds.height)}
|
|
273
|
+
</div>
|
|
274
|
+
<div style={{ marginTop: 6, fontSize: 12 }}>
|
|
275
|
+
Children:
|
|
276
|
+
<pre style={{ marginTop: 4, background: '#fff', border: '1px solid #d9e1ec', borderRadius: 6, padding: 8, maxHeight: 120, overflow: 'auto' }}>
|
|
277
|
+
{children
|
|
278
|
+
.map((child) => `${child.id}: pos(${Math.round(child.position.x)}, ${Math.round(child.position.y)}) size(${child.size.width}x${child.size.height})`)
|
|
279
|
+
.join('\n') || 'No children'}
|
|
280
|
+
</pre>
|
|
281
|
+
</div>
|
|
282
|
+
</div>
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
|
|
286
|
+
<DisplayBoxStage containerRef={containerRef} stageStyle={gridStageStyle} />
|
|
287
|
+
</section>
|
|
288
|
+
);
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
export default LayoutLabelReservedSpaceDemo;
|
|
@@ -118,6 +118,10 @@ const LinkCancelDemo = () => {
|
|
|
118
118
|
onManualRender={controls.handleManualRender}
|
|
119
119
|
onToggleLinkRouting={controls.handleToggleLinkRouting}
|
|
120
120
|
onAction={controls.handleAction}
|
|
121
|
+
onExportImage={controls.handleExportImage}
|
|
122
|
+
onClearExportPreview={controls.handleClearExportPreview}
|
|
123
|
+
exportPreviewDataUrl={controls.exportPreviewDataUrl}
|
|
124
|
+
exportError={controls.exportError}
|
|
121
125
|
/>
|
|
122
126
|
<div style={{ display: 'grid', gap: 12, marginBottom: 12 }}>
|
|
123
127
|
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 12, alignItems: 'center' }}>
|
|
@@ -236,3 +240,4 @@ const LinkCancelDemo = () => {
|
|
|
236
240
|
};
|
|
237
241
|
|
|
238
242
|
export default LinkCancelDemo;
|
|
243
|
+
|
|
@@ -355,7 +355,11 @@ const ShapeHoverControlsDemo = () => {
|
|
|
355
355
|
onToggleSnap={controls.handleToggleSnap}
|
|
356
356
|
onManualRender={controls.handleManualRender}
|
|
357
357
|
onToggleLinkRouting={controls.handleToggleLinkRouting}
|
|
358
|
-
onAction={controls.handleAction}
|
|
358
|
+
onAction={controls.handleAction}
|
|
359
|
+
onExportImage={controls.handleExportImage}
|
|
360
|
+
onClearExportPreview={controls.handleClearExportPreview}
|
|
361
|
+
exportPreviewDataUrl={controls.exportPreviewDataUrl}
|
|
362
|
+
exportError={controls.exportError}
|
|
359
363
|
/>
|
|
360
364
|
<div
|
|
361
365
|
style={{
|
|
@@ -556,3 +560,4 @@ const EllipseMidPointControlSection = ({
|
|
|
556
560
|
);
|
|
557
561
|
|
|
558
562
|
export default ShapeHoverControlsDemo;
|
|
563
|
+
|
|
@@ -57,6 +57,10 @@ const SimpleDemo = ({ demo, beforeStage, stageHandlers }: SimpleDemoProps) => {
|
|
|
57
57
|
onManualRender={controls.handleManualRender}
|
|
58
58
|
onToggleLinkRouting={controls.handleToggleLinkRouting}
|
|
59
59
|
onAction={controls.handleAction}
|
|
60
|
+
onExportImage={controls.handleExportImage}
|
|
61
|
+
onClearExportPreview={controls.handleClearExportPreview}
|
|
62
|
+
exportPreviewDataUrl={controls.exportPreviewDataUrl}
|
|
63
|
+
exportError={controls.exportError}
|
|
60
64
|
/>
|
|
61
65
|
{beforeStage}
|
|
62
66
|
<DisplayBoxStage
|
|
@@ -71,3 +75,4 @@ const SimpleDemo = ({ demo, beforeStage, stageHandlers }: SimpleDemoProps) => {
|
|
|
71
75
|
};
|
|
72
76
|
|
|
73
77
|
export default SimpleDemo;
|
|
78
|
+
|
|
@@ -166,6 +166,10 @@ const SvgPathDemo = () => {
|
|
|
166
166
|
onManualRender={controls.handleManualRender}
|
|
167
167
|
onToggleLinkRouting={controls.handleToggleLinkRouting}
|
|
168
168
|
onAction={controls.handleAction}
|
|
169
|
+
onExportImage={controls.handleExportImage}
|
|
170
|
+
onClearExportPreview={controls.handleClearExportPreview}
|
|
171
|
+
exportPreviewDataUrl={controls.exportPreviewDataUrl}
|
|
172
|
+
exportError={controls.exportError}
|
|
169
173
|
/>
|
|
170
174
|
<div
|
|
171
175
|
style={{
|
|
@@ -325,3 +329,4 @@ const SvgPathDemo = () => {
|
|
|
325
329
|
};
|
|
326
330
|
|
|
327
331
|
export default SvgPathDemo;
|
|
332
|
+
|
|
@@ -176,7 +176,11 @@ const TextLayoutDemo = () => {
|
|
|
176
176
|
onToggleSnap={controls.handleToggleSnap}
|
|
177
177
|
onManualRender={controls.handleManualRender}
|
|
178
178
|
onToggleLinkRouting={controls.handleToggleLinkRouting}
|
|
179
|
-
onAction={controls.handleAction}
|
|
179
|
+
onAction={controls.handleAction}
|
|
180
|
+
onExportImage={controls.handleExportImage}
|
|
181
|
+
onClearExportPreview={controls.handleClearExportPreview}
|
|
182
|
+
exportPreviewDataUrl={controls.exportPreviewDataUrl}
|
|
183
|
+
exportError={controls.exportError}
|
|
180
184
|
/>
|
|
181
185
|
|
|
182
186
|
<div style={{ display: 'grid', gap: 10, marginBottom: 12 }}>
|
|
@@ -384,3 +388,4 @@ const TextLayoutDemo = () => {
|
|
|
384
388
|
};
|
|
385
389
|
|
|
386
390
|
export default TextLayoutDemo;
|
|
391
|
+
|