orcasvn-react-diagrams 0.2.7 → 0.2.9
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 +24 -0
- package/README.md +7 -12
- package/ai/api-contract.json +16 -0
- package/ai/invariants.json +8 -0
- package/ai/manifest.json +1 -1
- package/dist/cjs/examples.js +604 -39
- package/dist/cjs/index.js +227 -28
- package/dist/cjs/types/api/types.d.ts +2 -0
- package/dist/cjs/types/displaybox/demos/elementVisibilitySelectionDemo.d.ts +4 -0
- package/dist/cjs/types/engine/DiagramEngine.d.ts +8 -0
- package/dist/cjs/types/models/DiagramModel.d.ts +5 -0
- package/dist/cjs/types/models/ElementModel.d.ts +2 -0
- package/dist/esm/examples.js +604 -39
- package/dist/esm/examples.js.map +1 -1
- package/dist/esm/index.js +227 -28
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/api/types.d.ts +2 -0
- package/dist/esm/types/displaybox/demos/elementVisibilitySelectionDemo.d.ts +4 -0
- package/dist/esm/types/engine/DiagramEngine.d.ts +8 -0
- package/dist/esm/types/models/DiagramModel.d.ts +5 -0
- package/dist/esm/types/models/ElementModel.d.ts +2 -0
- package/dist/examples.d.ts +2 -0
- package/dist/index.d.ts +9 -0
- package/docs/API_CONTRACT.md +16 -1
- package/docs/CAPABILITIES.md +1 -0
- package/docs/COMMANDS_EVENTS.md +3 -1
- package/docs/DOCUMENTATION_WORKFLOW.md +3 -1
- package/docs/INTEGRATION_PLAYBOOK.md +1 -0
- package/docs/PORTING_CHECKLIST.md +1 -0
- package/docs/STATE_INVARIANTS.md +9 -1
- package/package.json +1 -1
- package/src/displaybox/demos/AutoLayoutDemoTab.tsx +11 -5
- package/src/displaybox/demos/autoLayoutDemo.ts +233 -0
- package/src/displaybox/demos/basicDemo.ts +6 -6
- package/src/displaybox/demos/elementVisibilitySelectionDemo.ts +128 -0
- package/src/displaybox/demos/index.tsx +14 -7
- package/src/displaybox/demos/selectionDemo.ts +12 -12
|
@@ -76,6 +76,11 @@ export default class DiagramEngine {
|
|
|
76
76
|
setSelection(ids: string[]): void;
|
|
77
77
|
toggleSelection(id: string): void;
|
|
78
78
|
getSelection(): string[];
|
|
79
|
+
isElementVisible(id: string): boolean;
|
|
80
|
+
isElementSelectable(id: string): boolean;
|
|
81
|
+
isPortVisible(id: string): boolean;
|
|
82
|
+
isLinkVisible(id: string): boolean;
|
|
83
|
+
isTextVisible(id: string): boolean;
|
|
79
84
|
getElementWorldPosition(id: string): Point | null;
|
|
80
85
|
getElementRotation(id: string): number;
|
|
81
86
|
normalizeElementResize(id: string, proposal: {
|
|
@@ -146,6 +151,9 @@ export default class DiagramEngine {
|
|
|
146
151
|
private resolveTextPresentation;
|
|
147
152
|
private resolveAllTextPresentationPatches;
|
|
148
153
|
private emitSelection;
|
|
154
|
+
private normalizeSelectionIds;
|
|
155
|
+
private isSelectableId;
|
|
156
|
+
private syncSelectionToPolicies;
|
|
149
157
|
private applyLayoutForParent;
|
|
150
158
|
private applyLayoutCascade;
|
|
151
159
|
private applyAllLayouts;
|
|
@@ -13,14 +13,19 @@ export default class DiagramModel {
|
|
|
13
13
|
load(state: DiagramState): void;
|
|
14
14
|
toState(): DiagramState;
|
|
15
15
|
getElement(id: string): ElementModel | undefined;
|
|
16
|
+
isElementVisible(id: string): boolean;
|
|
17
|
+
isElementSelectable(id: string): boolean;
|
|
16
18
|
setElementLayout(id: string, layout: ElementData['layout']): void;
|
|
17
19
|
getChildren(parentId: string): ElementModel[];
|
|
18
20
|
getElementWorldPosition(id: string): Point | null;
|
|
19
21
|
getPort(id: string): PortModel | undefined;
|
|
22
|
+
isPortVisible(id: string): boolean;
|
|
20
23
|
getPortWorldPosition(id: string): Point | null;
|
|
21
24
|
getLink(id: string): LinkModel | undefined;
|
|
25
|
+
isLinkVisible(id: string): boolean;
|
|
22
26
|
getLinkMidpoint(id: string): Point | null;
|
|
23
27
|
getText(id: string): TextModel | undefined;
|
|
28
|
+
isTextVisible(id: string): boolean;
|
|
24
29
|
getTextWorldPosition(id: string): Point | null;
|
|
25
30
|
addElement(data: ElementData): ElementModel;
|
|
26
31
|
moveElement(id: string, position: Point): void;
|
package/dist/examples.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -269,6 +269,8 @@ type ElementData = {
|
|
|
269
269
|
style?: Record<string, unknown>;
|
|
270
270
|
portIds?: string[];
|
|
271
271
|
textIds?: string[];
|
|
272
|
+
visible?: boolean;
|
|
273
|
+
selectable?: boolean;
|
|
272
274
|
parentId?: string | null;
|
|
273
275
|
moveMode?: MoveConstraint;
|
|
274
276
|
anchorCenter?: boolean;
|
|
@@ -543,6 +545,8 @@ declare class ElementModel {
|
|
|
543
545
|
style?: Record<string, unknown>;
|
|
544
546
|
portIds: string[];
|
|
545
547
|
textIds: string[];
|
|
548
|
+
visible?: boolean;
|
|
549
|
+
selectable?: boolean;
|
|
546
550
|
parentId: string | null;
|
|
547
551
|
moveMode?: MoveConstraint;
|
|
548
552
|
anchorCenter?: boolean;
|
|
@@ -640,14 +644,19 @@ declare class DiagramModel {
|
|
|
640
644
|
load(state: DiagramState): void;
|
|
641
645
|
toState(): DiagramState;
|
|
642
646
|
getElement(id: string): ElementModel | undefined;
|
|
647
|
+
isElementVisible(id: string): boolean;
|
|
648
|
+
isElementSelectable(id: string): boolean;
|
|
643
649
|
setElementLayout(id: string, layout: ElementData['layout']): void;
|
|
644
650
|
getChildren(parentId: string): ElementModel[];
|
|
645
651
|
getElementWorldPosition(id: string): Point | null;
|
|
646
652
|
getPort(id: string): PortModel | undefined;
|
|
653
|
+
isPortVisible(id: string): boolean;
|
|
647
654
|
getPortWorldPosition(id: string): Point | null;
|
|
648
655
|
getLink(id: string): LinkModel | undefined;
|
|
656
|
+
isLinkVisible(id: string): boolean;
|
|
649
657
|
getLinkMidpoint(id: string): Point | null;
|
|
650
658
|
getText(id: string): TextModel | undefined;
|
|
659
|
+
isTextVisible(id: string): boolean;
|
|
651
660
|
getTextWorldPosition(id: string): Point | null;
|
|
652
661
|
addElement(data: ElementData): ElementModel;
|
|
653
662
|
moveElement(id: string, position: Point): void;
|
package/docs/API_CONTRACT.md
CHANGED
|
@@ -62,12 +62,22 @@ Defaults:
|
|
|
62
62
|
|
|
63
63
|
### `ElementData`
|
|
64
64
|
- Required: `id`, `position`, `size`, `shapeId`
|
|
65
|
-
- Optional: `style`, `portIds`, `textIds`, `parentId`, `moveMode`, `anchorCenter`, `layout`, `childElementInteraction`, `portMovement`
|
|
65
|
+
- Optional: `style`, `portIds`, `textIds`, `visible`, `selectable`, `parentId`, `moveMode`, `anchorCenter`, `layout`, `childElementInteraction`, `portMovement`
|
|
66
66
|
- Defaults at runtime/model:
|
|
67
67
|
- `portIds`: `[]`
|
|
68
68
|
- `textIds`: `[]`
|
|
69
69
|
- `parentId`: `null`
|
|
70
70
|
|
|
71
|
+
### `ElementData.visible` and `ElementData.selectable`
|
|
72
|
+
- Optional `visible?: boolean` (default behavior: `true`)
|
|
73
|
+
- Optional `selectable?: boolean` (default behavior: `true`)
|
|
74
|
+
- Semantics:
|
|
75
|
+
- `visible: false` removes the element body from built-in render, hit testing, marquee selection, persisted selection, `zoomToFitElements`, and `exportImage({ fitToContent })`
|
|
76
|
+
- hidden-scene propagation also hides owned ports, owned texts, and links whose source/target ports belong to hidden elements
|
|
77
|
+
- `selectable: false` prevents built-in element-body click selection, marquee selection, and programmatic `setSelection(...)` / `toggleSelection(...)` from retaining that element id
|
|
78
|
+
- `selectable: false` does not hide the element
|
|
79
|
+
- visible ports on a visible-but-unselectable element remain interactable/selectable unless separately constrained
|
|
80
|
+
|
|
71
81
|
### `ElementLayout`
|
|
72
82
|
- Required: `mode: 'manual' | 'horizontal' | 'vertical' | 'grid'`
|
|
73
83
|
- Optional: `padding?: number | { x: number; y: number }`, `gap?: number`, `align?: 'start' | 'center' | 'end'`
|
|
@@ -261,7 +271,9 @@ Defaults:
|
|
|
261
271
|
- Missing IDs in most mutators are no-op (non-throwing).
|
|
262
272
|
- `setViewport` emits a `change` patch with `entity: 'viewport'` and skips immediate render scheduling.
|
|
263
273
|
- `zoomToFitElements` computes bounds from `elements[]` only, ignores ports/links/texts for fit expansion, and no-ops when no elements exist.
|
|
274
|
+
- `zoomToFitElements` ignores hidden elements when computing fit bounds.
|
|
264
275
|
- `zoomToFitElements` applies its result through `setViewport`, so hosts observe the standard viewport patch/change path.
|
|
276
|
+
- `exportImage({ fitToContent })` derives crop bounds from visible scene entities only.
|
|
265
277
|
- Built-in empty-paper panning now starts from plain primary-button drag and no longer requires `panKey`; marquee selection uses `Shift + primary drag`.
|
|
266
278
|
- `clientToWorld` uses: `world = (client - containerRect - pan) / zoom`, with zoom fallback to `1` when zoom is `0`.
|
|
267
279
|
- `rerouteLinks(ids)` skips manual links unless `options.includeManual === true`.
|
|
@@ -269,6 +281,9 @@ Defaults:
|
|
|
269
281
|
- `updateLinkPoints` always marks the link as manual routing.
|
|
270
282
|
- `linkColorPoolPolicy` is opt-in and applies only to newly created links; explicitly provided non-empty `style.stroke` values are preserved.
|
|
271
283
|
- `gridLayoutChanged` is additive and does not replace standard `change` / `elementResized` flows.
|
|
284
|
+
- `ElementData.visible = false` hides the element plus owned ports/texts and endpoint-dependent links from built-in renderer sync, hit testing, marquee selection, persisted selection, and fit/export helpers.
|
|
285
|
+
- `ElementData.selectable = false` blocks built-in element-body selection while still allowing visible owned ports to participate in their normal interaction flows.
|
|
286
|
+
- `setSelection(...)` and `toggleSelection(...)` normalize away unknown IDs, hidden scene members, and unselectable elements before emitting `selection`.
|
|
272
287
|
- `ElementData.childElementInteraction.movable = false` suppresses built-in drag only for direct child elements; programmatic `moveElementTo(...)` and layout/ancestor-driven repositioning remain allowed.
|
|
273
288
|
- `TextData.interaction.movable = false` blocks built-in drag only; selection still works and programmatic movement remains allowed.
|
|
274
289
|
- `TextData.interaction.editable = false` blocks built-in textarea editing only; selection still works and programmatic text updates remain allowed.
|
package/docs/CAPABILITIES.md
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
- Auto-layout parent resize policy (`grow` / `grow-shrink`) and child size constraints.
|
|
18
18
|
- Optional grid-child width topology editing with `gridLayoutChanged` host events.
|
|
19
19
|
- Parent-owned direct-child drag suppression through `ElementData.childElementInteraction`.
|
|
20
|
+
- Element-level visibility/selectability policy through `ElementData.visible` and `ElementData.selectable`, including hidden-scene propagation to owned ports/texts and endpoint-dependent links.
|
|
20
21
|
- Element shape hover controls with edge/vertex/midpoint targets and interaction callbacks.
|
|
21
22
|
- Optional random link color assignment from configurable pools during link creation.
|
|
22
23
|
- Per-text interaction policy for suppressing built-in text drag and/or built-in text editing.
|
package/docs/COMMANDS_EVENTS.md
CHANGED
|
@@ -38,10 +38,11 @@
|
|
|
38
38
|
- Plus `textDeleted` on removal (including cascade removal)
|
|
39
39
|
- `setSelection/toggleSelection/deleteSelection`
|
|
40
40
|
- `selection` plus derived selected entity events
|
|
41
|
+
- hidden scene members and `selectable:false` element IDs are filtered out before selection persists/emits
|
|
41
42
|
- `setViewport`
|
|
42
43
|
- `change` with viewport patch (`render: false`)
|
|
43
44
|
- `zoomToFitElements`
|
|
44
|
-
- delegates to `setViewport` when at least one element exists
|
|
45
|
+
- delegates to `setViewport` when at least one visible element exists
|
|
45
46
|
- emits the same viewport `change` patch path
|
|
46
47
|
- `setRouting/setSnapping/registerShape`
|
|
47
48
|
- `config` events
|
|
@@ -64,6 +65,7 @@
|
|
|
64
65
|
## Failure Modes
|
|
65
66
|
- Unknown IDs do not emit entity-specific movement/selection events.
|
|
66
67
|
- Canceled link creation emits `elementLinkEnded` with `cancelled=true` and no link creation.
|
|
68
|
+
- Built-in element-body selection emits no persisted element selection when the target element is hidden or sets `selectable = false`.
|
|
67
69
|
- Built-in drag on a direct child element emits no move/drop mutation when its parent sets `childElementInteraction.movable = false`.
|
|
68
70
|
- `textUpdated` emits only when target text exists; missing IDs remain no-op.
|
|
69
71
|
|
|
@@ -59,7 +59,7 @@ When resuming later:
|
|
|
59
59
|
5. Re-run packaging verification.
|
|
60
60
|
|
|
61
61
|
## 6. Current Status
|
|
62
|
-
- Last updated: 2026-05-
|
|
62
|
+
- Last updated: 2026-05-27
|
|
63
63
|
- Last completed step: 10
|
|
64
64
|
- Next step: 7 (optional additional fixture coverage for deeper nested/manual-route scenarios)
|
|
65
65
|
- Owner: Codex (with repository maintainers)
|
|
@@ -86,3 +86,5 @@ When resuming later:
|
|
|
86
86
|
- 2026-05-10: Ran release validations: `npm run typecheck`, `npm test -- --watchAll=false`, `npm run build`, `npm run rollup-build-lib`, and `npm pack --dry-run`.
|
|
87
87
|
- 2026-05-14: Completed release-doc pass for `v0.2.6`; refreshed release highlights, API contract updates (`zoomToFitElements`, `ViewportFitOptions`, `gridChildWidthResizeEnabled`, `gridLayoutChanged`, `TextInteractionPolicy`), and machine-readable contract metadata.
|
|
88
88
|
- 2026-05-18: Completed release-doc pass for `v0.2.7`; refreshed release highlights, API contract updates (`ElementChildInteractionPolicy`, `childElementInteraction`, and built-in pan gesture behavior), and machine-readable contract metadata.
|
|
89
|
+
- 2026-05-24: Completed release-doc pass for `v0.2.8`; refreshed release highlights and publish-facing workflow metadata for the nested grid slot-preservation fix.
|
|
90
|
+
- 2026-05-27: Completed release-doc pass for `v0.2.9`; refreshed release highlights, visibility/selectability API docs, state/event integration notes, and machine-readable contract metadata.
|
|
@@ -19,6 +19,7 @@ Embed this library into another diagram host while preserving deterministic stat
|
|
|
19
19
|
6. Use `zoomToFitElements(options?)` when the host needs library-owned fit-to-elements navigation instead of recomputing viewport math externally.
|
|
20
20
|
7. Set `TextData.interaction` when some labels must remain read-only or fixed in place while still using library selection behavior.
|
|
21
21
|
8. Set `ElementData.childElementInteraction` on parent elements when direct child nodes should stay selectable but not be draggable through built-in interaction.
|
|
22
|
+
9. Set `ElementData.visible` and `ElementData.selectable` when hosts need hidden-but-retained nodes or visible-but-nonselectable element bodies; hidden elements also suppress owned ports/texts and endpoint-dependent links from built-in view helpers.
|
|
22
23
|
|
|
23
24
|
## Path B: Engine-Only Adapter
|
|
24
25
|
1. Implement `Renderer`:
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
- `PortData`
|
|
9
9
|
- `LinkData`
|
|
10
10
|
- `TextData`
|
|
11
|
+
- Confirm host mapping for `ElementData.visible` / `ElementData.selectable` if hidden or non-selectable nodes must retain state.
|
|
11
12
|
- Confirm owner-relative semantics for ports/texts.
|
|
12
13
|
|
|
13
14
|
## 2. Match Coordinate Semantics
|
package/docs/STATE_INVARIANTS.md
CHANGED
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
- Position is local to parent if `parentId` exists; otherwise world.
|
|
13
13
|
- World position resolves by summing ancestor positions.
|
|
14
14
|
- If `anchorCenter=true`, world top-left is shifted by half size.
|
|
15
|
+
- `visible` and `selectable` behave as enabled when omitted.
|
|
16
|
+
- `visible=false` excludes the element from the visible scene, and ancestor hidden state propagates to descendant elements.
|
|
17
|
+
- `selectable=false` prevents the element ID from persisting in engine selection state.
|
|
15
18
|
- Deleting an element cascades to:
|
|
16
19
|
- child ports
|
|
17
20
|
- links connected through removed ports
|
|
@@ -21,6 +24,7 @@
|
|
|
21
24
|
- Port position is local to owner element.
|
|
22
25
|
- Default `anchorCenter=true` in model constructor.
|
|
23
26
|
- Default `orientToHostBorder=true` in model constructor.
|
|
27
|
+
- Port visible-state is derived from owning element visibility.
|
|
24
28
|
- Moving ports can be constrained by:
|
|
25
29
|
- `moveMode: inside|border`
|
|
26
30
|
- element-level `portMovement.moveMode: free|inside|border|anchors`
|
|
@@ -34,11 +38,13 @@
|
|
|
34
38
|
- Auto routing recomputes from router strategy and normalized endpoints.
|
|
35
39
|
- Manual routing preserves interior bends on endpoint movement.
|
|
36
40
|
- Links with unresolved source/target world positions are skipped by reroute/update paths.
|
|
41
|
+
- Link visible-state requires both endpoint ports to remain visible.
|
|
37
42
|
|
|
38
43
|
## Text
|
|
39
44
|
- `ownerId` can reference element, port, or link.
|
|
40
45
|
- Owned text position is stored owner-relative.
|
|
41
46
|
- Text with missing owner behaves as standalone world-position text.
|
|
47
|
+
- Owned text visible-state follows its owner visibility when the owner resolves to an element, port, or link.
|
|
42
48
|
- Text interaction policy is persisted separately from style/layout metadata.
|
|
43
49
|
- `interaction.movable = false` suppresses built-in drag without blocking selection or programmatic movement.
|
|
44
50
|
- `interaction.editable = false` suppresses built-in editing without blocking selection or programmatic content updates.
|
|
@@ -49,8 +55,10 @@
|
|
|
49
55
|
- `setSelection` emits:
|
|
50
56
|
- `selection`
|
|
51
57
|
- plus derived `elementSelected`/`portSelected`/`textSelected`
|
|
58
|
+
- `setSelection` and `toggleSelection` normalize IDs against current visibility/selectability rules before persisting or emitting selection.
|
|
52
59
|
- `setViewport` emits `change` with `entity=viewport` and does not force render directly.
|
|
53
|
-
- `zoomToFitElements` derives viewport fit from `elements[]` bounds only and applies the result through `setViewport`.
|
|
60
|
+
- `zoomToFitElements` derives viewport fit from visible `elements[]` bounds only and applies the result through `setViewport`.
|
|
61
|
+
- `exportImage({ fitToContent })` derives crop bounds from visible scene entities only.
|
|
54
62
|
|
|
55
63
|
## Failure Modes
|
|
56
64
|
- Non-existent target IDs: operation is no-op.
|
package/package.json
CHANGED
|
@@ -22,6 +22,9 @@ const parentOptions = [
|
|
|
22
22
|
{ id: 'layout-grid', label: 'Grid layout' },
|
|
23
23
|
{ id: 'layout-nested', label: 'Nested layout' },
|
|
24
24
|
{ id: 'layout-grid-deep', label: 'Nested grid' },
|
|
25
|
+
{ id: 'layout-grid-empty-compare', label: 'Grid empty vs filled' },
|
|
26
|
+
{ id: 'layout-grid-mixed-modes', label: 'Grid mixed child modes' },
|
|
27
|
+
{ id: 'layout-column-grid-tree', label: 'Non-grid with grid descendants' },
|
|
25
28
|
{ id: 'layout-lock-compare', label: 'Child lock compare' },
|
|
26
29
|
{ id: 'layout-manual', label: 'Manual (compare)' },
|
|
27
30
|
];
|
|
@@ -391,11 +394,11 @@ const AutoLayoutDemo = () => {
|
|
|
391
394
|
stable while height changes.
|
|
392
395
|
</p>
|
|
393
396
|
<p style={{ marginTop: 0, marginBottom: 0, fontSize: 13, color: '#333' }}>
|
|
394
|
-
The
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
397
|
+
The seeded scenarios now cover empty nested grids, mixed child layout modes under one grid owner, and grid
|
|
398
|
+
descendants inside a non-grid tree. Use <code>layout-grid-deep</code> for enabled 12-unit nested-child resize,
|
|
399
|
+
<code>layout-grid-empty-compare</code> for empty-versus-filled nested grid comparison, <code>layout-grid-mixed-modes</code>
|
|
400
|
+
for direct-child layout mixing, and <code>layout-column-grid-tree</code> for a non-grid owner that still contains
|
|
401
|
+
grid-layout descendants. The child drag lock comparison lives beside them in <code>layout-lock-compare</code>.
|
|
399
402
|
</p>
|
|
400
403
|
</div>
|
|
401
404
|
<DisplayBoxControls
|
|
@@ -747,6 +750,9 @@ const AutoLayoutDemo = () => {
|
|
|
747
750
|
<ul style={{ marginTop: 0, paddingLeft: 18, fontSize: 13 }}>
|
|
748
751
|
<li>Nested grid: target layout-grid-deep to inspect an outer grid where all three direct children, including the nested grid parent, use enabled 12-unit resize.</li>
|
|
749
752
|
<li>Select deep-grid-nested-parent and drag a horizontal resize handle; it should snap in grid units and then reflow inner children inside the resized container.</li>
|
|
753
|
+
<li>Empty nested grid: target layout-grid-empty-compare and compare empty-grid-slot against filled-grid-slot. The empty nested grid should still occupy its assigned outer slot.</li>
|
|
754
|
+
<li>Mixed grid children: target layout-grid-mixed-modes to inspect one grid owner whose direct children use grid, vertical, and horizontal auto-layout modes side by side.</li>
|
|
755
|
+
<li>Non-grid with grid descendants: target layout-column-grid-tree to inspect a vertical parent that still contains grid-layout containers deeper in the subtree.</li>
|
|
750
756
|
<li>Lock comparison: target layout-lock-compare, toggle Lock comparison child drag, then compare deep-lock-child-a and deep-free-child-a.</li>
|
|
751
757
|
<li>Use Move lock target via API after locking; the child should still reposition because the policy only suppresses built-in drag.</li>
|
|
752
758
|
<li>Resize lock: with grid child width resize off, select grid-b and drag diagonally; width should stay fixed.</li>
|
|
@@ -139,6 +139,195 @@ export const createAutoLayoutState = (lockComparisonChildren = true): DiagramSta
|
|
|
139
139
|
{ id: 'deep-grid-c', position: { x: 0, y: 0 }, size: { width: 52, height: 24 }, shapeId: 'default', parentId: 'deep-grid-nested-parent' },
|
|
140
140
|
{ id: 'deep-grid-d', position: { x: 0, y: 0 }, size: { width: 28, height: 30 }, shapeId: 'default', parentId: 'deep-grid-nested-parent' },
|
|
141
141
|
|
|
142
|
+
{
|
|
143
|
+
id: 'layout-grid-empty-compare',
|
|
144
|
+
position: { x: 930, y: 70 },
|
|
145
|
+
size: { width: 280, height: 190 },
|
|
146
|
+
shapeId: 'panel',
|
|
147
|
+
layout: {
|
|
148
|
+
mode: 'grid',
|
|
149
|
+
padding: { x: 12, y: 12 },
|
|
150
|
+
gap: 12,
|
|
151
|
+
align: 'center',
|
|
152
|
+
autoResize: 'grow-shrink',
|
|
153
|
+
gridTemplate: [4, 4, 4],
|
|
154
|
+
gridChildWidthResizeEnabled: true,
|
|
155
|
+
childMinWidth: 44,
|
|
156
|
+
childMinHeight: 52,
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: 'empty-grid-slot',
|
|
161
|
+
position: { x: 0, y: 0 },
|
|
162
|
+
size: { width: 28, height: 18 },
|
|
163
|
+
shapeId: 'default',
|
|
164
|
+
parentId: 'layout-grid-empty-compare',
|
|
165
|
+
layout: {
|
|
166
|
+
mode: 'grid',
|
|
167
|
+
padding: { x: 8, y: 8 },
|
|
168
|
+
gap: 8,
|
|
169
|
+
align: 'center',
|
|
170
|
+
autoResize: 'grow-shrink',
|
|
171
|
+
gridTemplate: [6, 6],
|
|
172
|
+
gridChildWidthResizeEnabled: true,
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
id: 'filled-grid-slot',
|
|
177
|
+
position: { x: 0, y: 0 },
|
|
178
|
+
size: { width: 92, height: 88 },
|
|
179
|
+
shapeId: 'default',
|
|
180
|
+
parentId: 'layout-grid-empty-compare',
|
|
181
|
+
layout: {
|
|
182
|
+
mode: 'grid',
|
|
183
|
+
padding: { x: 8, y: 8 },
|
|
184
|
+
gap: 8,
|
|
185
|
+
align: 'center',
|
|
186
|
+
autoResize: 'grow-shrink',
|
|
187
|
+
gridTemplate: [6, 6],
|
|
188
|
+
gridChildWidthResizeEnabled: true,
|
|
189
|
+
childMinWidth: 18,
|
|
190
|
+
childMinHeight: 18,
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
id: 'empty-grid-compare-leaf',
|
|
195
|
+
position: { x: 0, y: 0 },
|
|
196
|
+
size: { width: 60, height: 70 },
|
|
197
|
+
shapeId: 'default',
|
|
198
|
+
parentId: 'layout-grid-empty-compare',
|
|
199
|
+
},
|
|
200
|
+
{ id: 'filled-grid-slot-a', position: { x: 0, y: 0 }, size: { width: 34, height: 22 }, shapeId: 'default', parentId: 'filled-grid-slot' },
|
|
201
|
+
{ id: 'filled-grid-slot-b', position: { x: 0, y: 0 }, size: { width: 40, height: 24 }, shapeId: 'default', parentId: 'filled-grid-slot' },
|
|
202
|
+
{ id: 'filled-grid-slot-c', position: { x: 0, y: 0 }, size: { width: 48, height: 22 }, shapeId: 'default', parentId: 'filled-grid-slot' },
|
|
203
|
+
|
|
204
|
+
{
|
|
205
|
+
id: 'layout-grid-mixed-modes',
|
|
206
|
+
position: { x: 930, y: 320 },
|
|
207
|
+
size: { width: 340, height: 240 },
|
|
208
|
+
shapeId: 'panel',
|
|
209
|
+
layout: {
|
|
210
|
+
mode: 'grid',
|
|
211
|
+
padding: { x: 12, y: 12 },
|
|
212
|
+
gap: 12,
|
|
213
|
+
align: 'center',
|
|
214
|
+
autoResize: 'grow-shrink',
|
|
215
|
+
gridTemplate: [4, 4, 4],
|
|
216
|
+
gridChildWidthResizeEnabled: true,
|
|
217
|
+
childMinWidth: 52,
|
|
218
|
+
childMinHeight: 64,
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
id: 'mixed-grid-child',
|
|
223
|
+
position: { x: 0, y: 0 },
|
|
224
|
+
size: { width: 88, height: 88 },
|
|
225
|
+
shapeId: 'default',
|
|
226
|
+
parentId: 'layout-grid-mixed-modes',
|
|
227
|
+
layout: {
|
|
228
|
+
mode: 'grid',
|
|
229
|
+
padding: { x: 8, y: 8 },
|
|
230
|
+
gap: 8,
|
|
231
|
+
align: 'center',
|
|
232
|
+
autoResize: 'grow-shrink',
|
|
233
|
+
gridTemplate: [6, 6],
|
|
234
|
+
gridChildWidthResizeEnabled: true,
|
|
235
|
+
childMinWidth: 18,
|
|
236
|
+
childMinHeight: 18,
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
id: 'mixed-column-child',
|
|
241
|
+
position: { x: 0, y: 0 },
|
|
242
|
+
size: { width: 92, height: 96 },
|
|
243
|
+
shapeId: 'default',
|
|
244
|
+
parentId: 'layout-grid-mixed-modes',
|
|
245
|
+
layout: {
|
|
246
|
+
mode: 'vertical',
|
|
247
|
+
padding: { x: 8, y: 8 },
|
|
248
|
+
gap: 8,
|
|
249
|
+
align: 'center',
|
|
250
|
+
autoResize: 'grow-shrink',
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
id: 'mixed-row-child',
|
|
255
|
+
position: { x: 0, y: 0 },
|
|
256
|
+
size: { width: 104, height: 84 },
|
|
257
|
+
shapeId: 'default',
|
|
258
|
+
parentId: 'layout-grid-mixed-modes',
|
|
259
|
+
layout: {
|
|
260
|
+
mode: 'horizontal',
|
|
261
|
+
padding: { x: 8, y: 8 },
|
|
262
|
+
gap: 8,
|
|
263
|
+
align: 'center',
|
|
264
|
+
autoResize: 'grow-shrink',
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
{ id: 'mixed-grid-a', position: { x: 0, y: 0 }, size: { width: 34, height: 22 }, shapeId: 'default', parentId: 'mixed-grid-child' },
|
|
268
|
+
{ id: 'mixed-grid-b', position: { x: 0, y: 0 }, size: { width: 44, height: 24 }, shapeId: 'default', parentId: 'mixed-grid-child' },
|
|
269
|
+
{ id: 'mixed-column-a', position: { x: 0, y: 0 }, size: { width: 60, height: 20 }, shapeId: 'default', parentId: 'mixed-column-child' },
|
|
270
|
+
{ id: 'mixed-column-b', position: { x: 0, y: 0 }, size: { width: 68, height: 24 }, shapeId: 'default', parentId: 'mixed-column-child' },
|
|
271
|
+
{ id: 'mixed-row-a', position: { x: 0, y: 0 }, size: { width: 32, height: 28 }, shapeId: 'default', parentId: 'mixed-row-child' },
|
|
272
|
+
{ id: 'mixed-row-b', position: { x: 0, y: 0 }, size: { width: 44, height: 24 }, shapeId: 'default', parentId: 'mixed-row-child' },
|
|
273
|
+
|
|
274
|
+
{
|
|
275
|
+
id: 'layout-column-grid-tree',
|
|
276
|
+
position: { x: 40, y: 520 },
|
|
277
|
+
size: { width: 340, height: 220 },
|
|
278
|
+
shapeId: 'panel',
|
|
279
|
+
layout: { mode: 'vertical', padding: { x: 12, y: 12 }, gap: 12, align: 'start', autoResize: 'grow-shrink' },
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
id: 'column-grid-tree-top',
|
|
283
|
+
position: { x: 0, y: 0 },
|
|
284
|
+
size: { width: 180, height: 88 },
|
|
285
|
+
shapeId: 'default',
|
|
286
|
+
parentId: 'layout-column-grid-tree',
|
|
287
|
+
layout: {
|
|
288
|
+
mode: 'grid',
|
|
289
|
+
padding: { x: 8, y: 8 },
|
|
290
|
+
gap: 8,
|
|
291
|
+
align: 'center',
|
|
292
|
+
autoResize: 'grow-shrink',
|
|
293
|
+
gridTemplate: [6, 6],
|
|
294
|
+
gridChildWidthResizeEnabled: true,
|
|
295
|
+
childMinWidth: 18,
|
|
296
|
+
childMinHeight: 18,
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
id: 'column-grid-tree-branch',
|
|
301
|
+
position: { x: 0, y: 0 },
|
|
302
|
+
size: { width: 220, height: 96 },
|
|
303
|
+
shapeId: 'default',
|
|
304
|
+
parentId: 'layout-column-grid-tree',
|
|
305
|
+
layout: { mode: 'horizontal', padding: { x: 8, y: 8 }, gap: 8, align: 'center', autoResize: 'grow-shrink' },
|
|
306
|
+
},
|
|
307
|
+
{ id: 'column-grid-top-a', position: { x: 0, y: 0 }, size: { width: 52, height: 22 }, shapeId: 'default', parentId: 'column-grid-tree-top' },
|
|
308
|
+
{ id: 'column-grid-top-b', position: { x: 0, y: 0 }, size: { width: 44, height: 24 }, shapeId: 'default', parentId: 'column-grid-tree-top' },
|
|
309
|
+
{
|
|
310
|
+
id: 'column-grid-tree-inner-grid',
|
|
311
|
+
position: { x: 0, y: 0 },
|
|
312
|
+
size: { width: 120, height: 84 },
|
|
313
|
+
shapeId: 'default',
|
|
314
|
+
parentId: 'column-grid-tree-branch',
|
|
315
|
+
layout: {
|
|
316
|
+
mode: 'grid',
|
|
317
|
+
padding: { x: 8, y: 8 },
|
|
318
|
+
gap: 8,
|
|
319
|
+
align: 'center',
|
|
320
|
+
autoResize: 'grow-shrink',
|
|
321
|
+
gridTemplate: [6, 6],
|
|
322
|
+
gridChildWidthResizeEnabled: true,
|
|
323
|
+
childMinWidth: 18,
|
|
324
|
+
childMinHeight: 18,
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
{ id: 'column-grid-tree-leaf', position: { x: 0, y: 0 }, size: { width: 58, height: 62 }, shapeId: 'default', parentId: 'column-grid-tree-branch' },
|
|
328
|
+
{ id: 'column-grid-inner-a', position: { x: 0, y: 0 }, size: { width: 30, height: 22 }, shapeId: 'default', parentId: 'column-grid-tree-inner-grid' },
|
|
329
|
+
{ id: 'column-grid-inner-b', position: { x: 0, y: 0 }, size: { width: 42, height: 24 }, shapeId: 'default', parentId: 'column-grid-tree-inner-grid' },
|
|
330
|
+
|
|
142
331
|
{
|
|
143
332
|
id: 'layout-lock-compare',
|
|
144
333
|
position: { x: 420, y: 410 },
|
|
@@ -241,6 +430,50 @@ export const createAutoLayoutState = (lockComparisonChildren = true): DiagramSta
|
|
|
241
430
|
{ id: 'label-deep-grid-b', content: 'grid-b', position: { x: 6, y: -14 }, ownerId: 'deep-grid-b' },
|
|
242
431
|
{ id: 'label-deep-grid-c', content: 'grid-c', position: { x: 6, y: -14 }, ownerId: 'deep-grid-c' },
|
|
243
432
|
{ id: 'label-deep-grid-d', content: 'grid-d', position: { x: 6, y: -14 }, ownerId: 'deep-grid-d' },
|
|
433
|
+
{
|
|
434
|
+
id: 'label-layout-grid-empty-compare',
|
|
435
|
+
content: 'Grid owner: empty vs filled nested grids',
|
|
436
|
+
position: { x: 8, y: 6 },
|
|
437
|
+
ownerId: 'layout-grid-empty-compare',
|
|
438
|
+
layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
|
|
439
|
+
},
|
|
440
|
+
{ id: 'label-empty-grid-slot', content: 'empty nested grid', position: { x: 6, y: -16 }, ownerId: 'empty-grid-slot' },
|
|
441
|
+
{ id: 'label-filled-grid-slot', content: 'nested grid with children', position: { x: 6, y: -16 }, ownerId: 'filled-grid-slot' },
|
|
442
|
+
{ id: 'label-empty-grid-compare-leaf', content: 'leaf sibling', position: { x: 6, y: -16 }, ownerId: 'empty-grid-compare-leaf' },
|
|
443
|
+
{ id: 'label-filled-grid-slot-a', content: 'slot-a', position: { x: 6, y: -14 }, ownerId: 'filled-grid-slot-a' },
|
|
444
|
+
{ id: 'label-filled-grid-slot-b', content: 'slot-b', position: { x: 6, y: -14 }, ownerId: 'filled-grid-slot-b' },
|
|
445
|
+
{ id: 'label-filled-grid-slot-c', content: 'slot-c', position: { x: 6, y: -14 }, ownerId: 'filled-grid-slot-c' },
|
|
446
|
+
{
|
|
447
|
+
id: 'label-layout-grid-mixed-modes',
|
|
448
|
+
content: 'Grid owner: mixed child layout modes',
|
|
449
|
+
position: { x: 8, y: 6 },
|
|
450
|
+
ownerId: 'layout-grid-mixed-modes',
|
|
451
|
+
layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
|
|
452
|
+
},
|
|
453
|
+
{ id: 'label-mixed-grid-child', content: 'grid child', position: { x: 6, y: -16 }, ownerId: 'mixed-grid-child' },
|
|
454
|
+
{ id: 'label-mixed-column-child', content: 'vertical child', position: { x: 6, y: -16 }, ownerId: 'mixed-column-child' },
|
|
455
|
+
{ id: 'label-mixed-row-child', content: 'horizontal child', position: { x: 6, y: -16 }, ownerId: 'mixed-row-child' },
|
|
456
|
+
{ id: 'label-mixed-grid-a', content: 'grid-a', position: { x: 6, y: -14 }, ownerId: 'mixed-grid-a' },
|
|
457
|
+
{ id: 'label-mixed-grid-b', content: 'grid-b', position: { x: 6, y: -14 }, ownerId: 'mixed-grid-b' },
|
|
458
|
+
{ id: 'label-mixed-column-a', content: 'col-a', position: { x: 6, y: -14 }, ownerId: 'mixed-column-a' },
|
|
459
|
+
{ id: 'label-mixed-column-b', content: 'col-b', position: { x: 6, y: -14 }, ownerId: 'mixed-column-b' },
|
|
460
|
+
{ id: 'label-mixed-row-a', content: 'row-a', position: { x: 6, y: -14 }, ownerId: 'mixed-row-a' },
|
|
461
|
+
{ id: 'label-mixed-row-b', content: 'row-b', position: { x: 6, y: -14 }, ownerId: 'mixed-row-b' },
|
|
462
|
+
{
|
|
463
|
+
id: 'label-layout-column-grid-tree',
|
|
464
|
+
content: 'Vertical owner with grid descendants',
|
|
465
|
+
position: { x: 8, y: 6 },
|
|
466
|
+
ownerId: 'layout-column-grid-tree',
|
|
467
|
+
layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
|
|
468
|
+
},
|
|
469
|
+
{ id: 'label-column-grid-tree-top', content: 'top-level grid child', position: { x: 6, y: -16 }, ownerId: 'column-grid-tree-top' },
|
|
470
|
+
{ id: 'label-column-grid-tree-branch', content: 'row branch with inner grid', position: { x: 6, y: -16 }, ownerId: 'column-grid-tree-branch' },
|
|
471
|
+
{ id: 'label-column-grid-top-a', content: 'top-a', position: { x: 6, y: -14 }, ownerId: 'column-grid-top-a' },
|
|
472
|
+
{ id: 'label-column-grid-top-b', content: 'top-b', position: { x: 6, y: -14 }, ownerId: 'column-grid-top-b' },
|
|
473
|
+
{ id: 'label-column-grid-tree-inner-grid', content: 'nested grid descendant', position: { x: 6, y: -16 }, ownerId: 'column-grid-tree-inner-grid' },
|
|
474
|
+
{ id: 'label-column-grid-tree-leaf', content: 'branch leaf', position: { x: 6, y: -14 }, ownerId: 'column-grid-tree-leaf' },
|
|
475
|
+
{ id: 'label-column-grid-inner-a', content: 'inner-a', position: { x: 6, y: -14 }, ownerId: 'column-grid-inner-a' },
|
|
476
|
+
{ id: 'label-column-grid-inner-b', content: 'inner-b', position: { x: 6, y: -14 }, ownerId: 'column-grid-inner-b' },
|
|
244
477
|
{
|
|
245
478
|
id: 'label-layout-lock-compare',
|
|
246
479
|
content: 'Child drag lock comparison',
|
|
@@ -60,12 +60,12 @@ const createBasicState = (): DiagramState => ({
|
|
|
60
60
|
],
|
|
61
61
|
});
|
|
62
62
|
|
|
63
|
-
export const basicDemoConfig: DemoConfig = ({
|
|
64
|
-
id: 'basic',
|
|
65
|
-
title: 'Basic Diagram',
|
|
66
|
-
description: 'Elements, ports, link, and labels.',
|
|
67
|
-
createState: createBasicState,
|
|
68
|
-
elementShapes: baseElementShapes,
|
|
63
|
+
export const basicDemoConfig: DemoConfig = ({
|
|
64
|
+
id: 'basic',
|
|
65
|
+
title: 'Basic Diagram',
|
|
66
|
+
description: 'Elements, ports, link, and labels. Drag empty paper to pan; use Shift + drag for marquee selection.',
|
|
67
|
+
createState: createBasicState,
|
|
68
|
+
elementShapes: baseElementShapes,
|
|
69
69
|
portShapes: basePortShapes,
|
|
70
70
|
defaultElementShapeId: 'default',
|
|
71
71
|
defaultPortShapeId: 'port-circle',
|