orcasvn-react-diagrams 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.md +22 -1
  2. package/ai/api-contract.json +57 -5
  3. package/ai/invariants.json +5 -3
  4. package/ai/manifest.json +1 -1
  5. package/dist/cjs/examples.js +11775 -0
  6. package/dist/cjs/index.js +3889 -1112
  7. package/dist/cjs/types/api/createDiagramEditor.d.ts +7 -2
  8. package/dist/cjs/types/api/types.d.ts +178 -0
  9. package/dist/cjs/types/displaybox/demos/DeletionEventsDemoTab.d.ts +3 -0
  10. package/dist/cjs/types/displaybox/demos/ShapeHoverControlsDemoTab.d.ts +3 -0
  11. package/dist/cjs/types/displaybox/demos/TextLayoutDemoTab.d.ts +3 -0
  12. package/dist/cjs/types/displaybox/demos/deletionEventsDemo.d.ts +2 -0
  13. package/dist/cjs/types/displaybox/demos/rotatedCreationDemo.d.ts +2 -0
  14. package/dist/cjs/types/displaybox/demos/roundedRectRadiusDemo.d.ts +2 -0
  15. package/dist/cjs/types/displaybox/demos/shapeBorderMovementDemo.d.ts +2 -0
  16. package/dist/cjs/types/displaybox/demos/shapeHoverControlsDemo.d.ts +10 -0
  17. package/dist/cjs/types/displaybox/demos/textDemo.d.ts +4 -0
  18. package/dist/cjs/types/displaybox/useDemoEditor.d.ts +5 -2
  19. package/dist/cjs/types/engine/AutoLayoutService.d.ts +24 -0
  20. package/dist/cjs/types/engine/DiagramEngine.d.ts +32 -14
  21. package/dist/cjs/types/engine/EngineCommands.d.ts +4 -1
  22. package/dist/cjs/types/engine/LinkRoutingService.d.ts +35 -0
  23. package/dist/cjs/types/engine/MutationPipeline.d.ts +23 -0
  24. package/dist/cjs/types/engine/TextLayoutService.d.ts +40 -0
  25. package/dist/cjs/types/examples/index.d.ts +2 -0
  26. package/dist/cjs/types/measure/textStyleDefaults.d.ts +9 -0
  27. package/dist/cjs/types/models/DiagramModel.d.ts +1 -0
  28. package/dist/cjs/types/models/ElementModel.d.ts +1 -0
  29. package/dist/cjs/types/models/PortModel.d.ts +3 -0
  30. package/dist/cjs/types/models/TextModel.d.ts +8 -0
  31. package/dist/cjs/types/renderer/RenderTypes.d.ts +34 -1
  32. package/dist/cjs/types/renderer/konva/KonvaHitTester.d.ts +1 -1
  33. package/dist/cjs/types/renderer/konva/KonvaInteraction.d.ts +53 -3
  34. package/dist/cjs/types/renderer/konva/KonvaNodeFactory.d.ts +18 -1
  35. package/dist/cjs/types/renderer/konva/KonvaRenderer.d.ts +49 -2
  36. package/dist/cjs/types/shapes/BuiltInShapes.d.ts +107 -0
  37. package/dist/cjs/types/shapes/__tests__/BuiltInShapes.test.d.ts +1 -0
  38. package/dist/cjs/types/shapes/index.d.ts +1 -0
  39. package/dist/cjs/types/utils/__tests__/borderGeometry.test.d.ts +1 -0
  40. package/dist/cjs/types/utils/borderGeometry.d.ts +6 -0
  41. package/dist/cjs/types/utils/geometry.d.ts +22 -0
  42. package/dist/esm/examples.js +11767 -0
  43. package/dist/esm/examples.js.map +1 -0
  44. package/dist/esm/index.js +3890 -1113
  45. package/dist/esm/index.js.map +1 -1
  46. package/dist/esm/types/api/createDiagramEditor.d.ts +7 -2
  47. package/dist/esm/types/api/types.d.ts +178 -0
  48. package/dist/esm/types/displaybox/demos/DeletionEventsDemoTab.d.ts +3 -0
  49. package/dist/esm/types/displaybox/demos/ShapeHoverControlsDemoTab.d.ts +3 -0
  50. package/dist/esm/types/displaybox/demos/TextLayoutDemoTab.d.ts +3 -0
  51. package/dist/esm/types/displaybox/demos/deletionEventsDemo.d.ts +2 -0
  52. package/dist/esm/types/displaybox/demos/rotatedCreationDemo.d.ts +2 -0
  53. package/dist/esm/types/displaybox/demos/roundedRectRadiusDemo.d.ts +2 -0
  54. package/dist/esm/types/displaybox/demos/shapeBorderMovementDemo.d.ts +2 -0
  55. package/dist/esm/types/displaybox/demos/shapeHoverControlsDemo.d.ts +10 -0
  56. package/dist/esm/types/displaybox/demos/textDemo.d.ts +4 -0
  57. package/dist/esm/types/displaybox/useDemoEditor.d.ts +5 -2
  58. package/dist/esm/types/engine/AutoLayoutService.d.ts +24 -0
  59. package/dist/esm/types/engine/DiagramEngine.d.ts +32 -14
  60. package/dist/esm/types/engine/EngineCommands.d.ts +4 -1
  61. package/dist/esm/types/engine/LinkRoutingService.d.ts +35 -0
  62. package/dist/esm/types/engine/MutationPipeline.d.ts +23 -0
  63. package/dist/esm/types/engine/TextLayoutService.d.ts +40 -0
  64. package/dist/esm/types/examples/index.d.ts +2 -0
  65. package/dist/esm/types/measure/textStyleDefaults.d.ts +9 -0
  66. package/dist/esm/types/models/DiagramModel.d.ts +1 -0
  67. package/dist/esm/types/models/ElementModel.d.ts +1 -0
  68. package/dist/esm/types/models/PortModel.d.ts +3 -0
  69. package/dist/esm/types/models/TextModel.d.ts +8 -0
  70. package/dist/esm/types/renderer/RenderTypes.d.ts +34 -1
  71. package/dist/esm/types/renderer/konva/KonvaHitTester.d.ts +1 -1
  72. package/dist/esm/types/renderer/konva/KonvaInteraction.d.ts +53 -3
  73. package/dist/esm/types/renderer/konva/KonvaNodeFactory.d.ts +18 -1
  74. package/dist/esm/types/renderer/konva/KonvaRenderer.d.ts +49 -2
  75. package/dist/esm/types/shapes/BuiltInShapes.d.ts +107 -0
  76. package/dist/esm/types/shapes/__tests__/BuiltInShapes.test.d.ts +1 -0
  77. package/dist/esm/types/shapes/index.d.ts +1 -0
  78. package/dist/esm/types/utils/__tests__/borderGeometry.test.d.ts +1 -0
  79. package/dist/esm/types/utils/borderGeometry.d.ts +6 -0
  80. package/dist/esm/types/utils/geometry.d.ts +22 -0
  81. package/dist/examples.d.ts +532 -0
  82. package/dist/index.d.ts +233 -2
  83. package/docs/API_CONTRACT.md +59 -3
  84. package/docs/ARCHITECTURE.md +1 -0
  85. package/docs/CAPABILITIES.md +3 -1
  86. package/docs/COMMANDS_EVENTS.md +5 -0
  87. package/docs/DOCUMENTATION_WORKFLOW.md +6 -8
  88. package/docs/INTEGRATION_PLAYBOOK.md +2 -0
  89. package/docs/PORTING_CHECKLIST.md +1 -0
  90. package/docs/STATE_INVARIANTS.md +4 -0
  91. package/package.json +20 -10
  92. package/src/displaybox/demos/AutoLayoutDemoTab.tsx +501 -0
  93. package/src/displaybox/demos/DeletionEventsDemoTab.tsx +147 -0
  94. package/src/displaybox/demos/EngineEventsDemoTab.tsx +151 -0
  95. package/src/displaybox/demos/EventHandlersDemoTab.tsx +110 -0
  96. package/src/displaybox/demos/ExternalDragDropDemoTab.tsx +261 -0
  97. package/src/displaybox/demos/LinkCancelDemoTab.tsx +238 -0
  98. package/src/displaybox/demos/ObstacleRoutingDemoTab.tsx +30 -0
  99. package/src/displaybox/demos/ShapeHoverControlsDemoTab.tsx +558 -0
  100. package/src/displaybox/demos/SimpleDemo.tsx +73 -0
  101. package/src/displaybox/demos/SvgPathDemoTab.tsx +327 -0
  102. package/src/displaybox/demos/TextLayoutDemoTab.tsx +386 -0
  103. package/src/displaybox/demos/autoLayoutDemo.ts +111 -0
  104. package/src/displaybox/demos/basicDemo.ts +131 -0
  105. package/src/displaybox/demos/childConstraintsDemo.ts +65 -0
  106. package/src/displaybox/demos/customDemo.ts +59 -0
  107. package/src/displaybox/demos/deletionEventsDemo.ts +91 -0
  108. package/src/displaybox/demos/engineEventsDemo.ts +64 -0
  109. package/src/displaybox/demos/eventHandlersDemo.ts +41 -0
  110. package/src/displaybox/demos/externalDragDropDemo.ts +28 -0
  111. package/src/displaybox/demos/gridOverlayDemo.ts +50 -0
  112. package/src/displaybox/demos/index.tsx +217 -0
  113. package/src/displaybox/demos/linkBendHandlesDemo.ts +143 -0
  114. package/src/displaybox/demos/linkCancelDemo.ts +56 -0
  115. package/src/displaybox/demos/linkPortCreationDemo.ts +46 -0
  116. package/src/displaybox/demos/multiLevelTreeDemo.ts +120 -0
  117. package/src/displaybox/demos/multipleElementsDemo.ts +62 -0
  118. package/src/displaybox/demos/nestedDemo.ts +78 -0
  119. package/src/displaybox/demos/obstacleRoutingDemo.ts +176 -0
  120. package/src/displaybox/demos/portBorderDemo.ts +98 -0
  121. package/src/displaybox/demos/portConstraintsDemo.ts +175 -0
  122. package/src/displaybox/demos/rotatedCreationDemo.ts +185 -0
  123. package/src/displaybox/demos/roundedRectRadiusDemo.ts +93 -0
  124. package/src/displaybox/demos/routingDemo.ts +57 -0
  125. package/src/displaybox/demos/selectionDemo.ts +49 -0
  126. package/src/displaybox/demos/shapeBorderMovementDemo.ts +126 -0
  127. package/src/displaybox/demos/shapeGalleryDemo.ts +73 -0
  128. package/src/displaybox/demos/shapeHoverControlsDemo.ts +172 -0
  129. package/src/displaybox/demos/shared.ts +161 -0
  130. package/src/displaybox/demos/svgPathDemo.ts +71 -0
  131. package/src/displaybox/demos/textDemo.ts +62 -0
  132. package/src/displaybox/types.ts +66 -0
  133. package/src/examples/index.ts +21 -0
@@ -0,0 +1,56 @@
1
+ import type { DiagramState } from '../../api';
2
+ import type { DemoConfig } from '../types';
3
+ import { baseElementShapes, basePortShapes } from './shared';
4
+
5
+ const createLinkCancelState = (): DiagramState => ({
6
+ elements: [
7
+ {
8
+ id: 'cancel-source',
9
+ position: { x: 140, y: 180 },
10
+ size: { width: 200, height: 120 },
11
+ shapeId: 'default',
12
+ },
13
+ {
14
+ id: 'cancel-target',
15
+ position: { x: 480, y: 200 },
16
+ size: { width: 200, height: 120 },
17
+ shapeId: 'panel',
18
+ },
19
+ ],
20
+ ports: [
21
+ {
22
+ id: 'cancel-source-port',
23
+ elementId: 'cancel-source',
24
+ position: { x: 30, y: 60 },
25
+ shapeId: 'port-circle',
26
+ anchorCenter: true,
27
+ },
28
+ {
29
+ id: 'cancel-target-port',
30
+ elementId: 'cancel-target',
31
+ position: { x: 170, y: 50 },
32
+ shapeId: 'port-circle',
33
+ anchorCenter: true,
34
+ },
35
+ ],
36
+ links: [],
37
+ texts: [
38
+ {
39
+ id: 'cancel-tip',
40
+ content: 'Start a link from the left port. Drop on empty space to cancel, or on the right port to create.',
41
+ position: { x: 120, y: 140 },
42
+ },
43
+ ],
44
+ });
45
+
46
+ export const linkCancelDemoConfig: DemoConfig = ({
47
+ id: 'link-cancel',
48
+ title: 'Link Hover Complete',
49
+ description: 'Watch immediate link completion on destination-port hover and host cancellation behavior.',
50
+ createState: createLinkCancelState,
51
+ elementShapes: baseElementShapes,
52
+ portShapes: basePortShapes,
53
+ defaultElementShapeId: 'default',
54
+ defaultPortShapeId: 'port-circle',
55
+ actions: [],
56
+ });
@@ -0,0 +1,46 @@
1
+ import type { DiagramState } from '../../api';
2
+ import type { DemoConfig } from '../types';
3
+ import { baseElementShapes, basePortShapes } from './shared';
4
+
5
+ const createLinkPortCreationState = (): DiagramState => ({
6
+ elements: [
7
+ {
8
+ id: 'link-source',
9
+ position: { x: 140, y: 160 },
10
+ size: { width: 220, height: 140 },
11
+ shapeId: 'default',
12
+ },
13
+ {
14
+ id: 'link-target',
15
+ position: { x: 440, y: 200 },
16
+ size: { width: 220, height: 140 },
17
+ shapeId: 'panel',
18
+ },
19
+ ],
20
+ ports: [
21
+ {
22
+ id: 'link-source-port',
23
+ elementId: 'link-source',
24
+ position: { x: 30, y: 30 },
25
+ shapeId: 'port-circle',
26
+ anchorCenter: true,
27
+ },
28
+ ],
29
+ links: [],
30
+ texts: [
31
+ { id: 'link-source-label', content: 'Drag from the port', position: { x: 12, y: -12 }, ownerId: 'link-source' },
32
+ { id: 'link-target-label', content: 'Drop on me to create a port', position: { x: 12, y: -12 }, ownerId: 'link-target' },
33
+ ],
34
+ });
35
+
36
+ export const linkPortCreationDemoConfig: DemoConfig = ({
37
+ id: 'link-port-creation',
38
+ title: 'Link Creates Port',
39
+ description: 'Drag from a port to an element to auto-create a target port.',
40
+ createState: createLinkPortCreationState,
41
+ elementShapes: baseElementShapes,
42
+ portShapes: basePortShapes,
43
+ defaultElementShapeId: 'default',
44
+ defaultPortShapeId: 'port-circle',
45
+ actions: [],
46
+ });
@@ -0,0 +1,120 @@
1
+ import type { DiagramState } from '../../api';
2
+ import type { DemoConfig } from '../types';
3
+ import { baseElementShapes, basePortShapes } from './shared';
4
+
5
+ const createMultiLevelTreeState = (): DiagramState => ({
6
+ elements: [
7
+ {
8
+ id: 'tree-root',
9
+ position: { x: 120, y: 120 },
10
+ size: { width: 300, height: 220 },
11
+ shapeId: 'panel',
12
+ },
13
+ {
14
+ id: 'tree-child-1',
15
+ position: { x: 40, y: 40 },
16
+ size: { width: 200, height: 140 },
17
+ shapeId: 'default',
18
+ parentId: 'tree-root',
19
+ },
20
+ {
21
+ id: 'tree-child-2',
22
+ position: { x: 30, y: 30 },
23
+ size: { width: 150, height: 100 },
24
+ shapeId: 'default',
25
+ parentId: 'tree-child-1',
26
+ },
27
+ {
28
+ id: 'tree-child-3',
29
+ position: { x: 20, y: 20 },
30
+ size: { width: 110, height: 70 },
31
+ shapeId: 'default',
32
+ parentId: 'tree-child-2',
33
+ },
34
+ {
35
+ id: 'tree-root-2',
36
+ position: { x: 520, y: 140 },
37
+ size: { width: 260, height: 200 },
38
+ shapeId: 'panel',
39
+ },
40
+ {
41
+ id: 'tree2-child-1',
42
+ position: { x: 30, y: 40 },
43
+ size: { width: 170, height: 120 },
44
+ shapeId: 'default',
45
+ parentId: 'tree-root-2',
46
+ },
47
+ {
48
+ id: 'tree2-child-2',
49
+ position: { x: 20, y: 20 },
50
+ size: { width: 120, height: 80 },
51
+ shapeId: 'default',
52
+ parentId: 'tree2-child-1',
53
+ },
54
+ ],
55
+ ports: [
56
+ {
57
+ id: 'tree-root-port',
58
+ elementId: 'tree-root',
59
+ position: { x: 150, y: 0 },
60
+ shapeId: 'port-circle',
61
+ anchorCenter: true,
62
+ },
63
+ {
64
+ id: 'tree-child-3-port',
65
+ elementId: 'tree-child-3',
66
+ position: { x: 55, y: 35 },
67
+ shapeId: 'port-circle',
68
+ anchorCenter: true,
69
+ },
70
+ {
71
+ id: 'tree-root-2-port',
72
+ elementId: 'tree-root-2',
73
+ position: { x: 130, y: 200 },
74
+ shapeId: 'port-circle',
75
+ anchorCenter: true,
76
+ },
77
+ {
78
+ id: 'tree2-child-2-port',
79
+ elementId: 'tree2-child-2',
80
+ position: { x: 60, y: 40 },
81
+ shapeId: 'port-circle',
82
+ anchorCenter: true,
83
+ },
84
+ ],
85
+ links: [
86
+ {
87
+ id: 'tree-link-1',
88
+ sourcePortId: 'tree-root-port',
89
+ targetPortId: 'tree-root-2-port',
90
+ points: [],
91
+ },
92
+ {
93
+ id: 'tree-link-2',
94
+ sourcePortId: 'tree-child-3-port',
95
+ targetPortId: 'tree2-child-2-port',
96
+ points: [],
97
+ },
98
+ ],
99
+ texts: [
100
+ { id: 'tree-root-label', content: 'Root A', position: { x: 12, y: -16 }, ownerId: 'tree-root' },
101
+ { id: 'tree-child-1-label', content: 'Level 1', position: { x: 12, y: -16 }, ownerId: 'tree-child-1' },
102
+ { id: 'tree-child-2-label', content: 'Level 2', position: { x: 12, y: -16 }, ownerId: 'tree-child-2' },
103
+ { id: 'tree-child-3-label', content: 'Level 3', position: { x: 12, y: -16 }, ownerId: 'tree-child-3' },
104
+ { id: 'tree-root-2-label', content: 'Root B', position: { x: 12, y: -16 }, ownerId: 'tree-root-2' },
105
+ { id: 'tree2-child-1-label', content: 'Level 1', position: { x: 12, y: -16 }, ownerId: 'tree2-child-1' },
106
+ { id: 'tree2-child-2-label', content: 'Level 2', position: { x: 12, y: -16 }, ownerId: 'tree2-child-2' },
107
+ ],
108
+ });
109
+
110
+ export const multiLevelTreeDemoConfig: DemoConfig = ({
111
+ id: 'multi-level-tree',
112
+ title: 'Multi-level Tree',
113
+ description: 'Three-level and two-level nested trees with default links.',
114
+ createState: createMultiLevelTreeState,
115
+ elementShapes: baseElementShapes,
116
+ portShapes: basePortShapes,
117
+ defaultElementShapeId: 'default',
118
+ defaultPortShapeId: 'port-circle',
119
+ actions: [],
120
+ });
@@ -0,0 +1,62 @@
1
+ import type { DiagramState } from '../../api';
2
+ import type { DemoConfig } from '../types';
3
+ import { baseElementShapes, basePortShapes } from './shared';
4
+
5
+ const createMultipleElementsState = (): DiagramState => ({
6
+ elements: [
7
+ {
8
+ id: 'multi-1',
9
+ position: { x: 120, y: 120 },
10
+ size: { width: 220, height: 140 },
11
+ shapeId: 'default',
12
+ },
13
+ {
14
+ id: 'multi-2',
15
+ position: { x: 420, y: 160 },
16
+ size: { width: 220, height: 140 },
17
+ shapeId: 'panel',
18
+ },
19
+ {
20
+ id: 'multi-3',
21
+ position: { x: 260, y: 360 },
22
+ size: { width: 240, height: 160 },
23
+ shapeId: 'default',
24
+ },
25
+ ],
26
+ ports: [
27
+ { id: 'm1p1', elementId: 'multi-1', position: { x: 30, y: 30 }, shapeId: 'port-circle', anchorCenter: true },
28
+ { id: 'm2p1', elementId: 'multi-2', position: { x: 40, y: 30 }, shapeId: 'port-circle', anchorCenter: true },
29
+ { id: 'm3p1', elementId: 'multi-3', position: { x: 40, y: 40 }, shapeId: 'port-circle', anchorCenter: true },
30
+ ],
31
+ links: [
32
+ {
33
+ id: 'link-12',
34
+ sourcePortId: 'm1p1',
35
+ targetPortId: 'm2p1',
36
+ points: [],
37
+ },
38
+ {
39
+ id: 'link-23',
40
+ sourcePortId: 'm2p1',
41
+ targetPortId: 'm3p1',
42
+ points: [],
43
+ },
44
+ ],
45
+ texts: [
46
+ { id: 'm1-label', content: 'Multi 1', position: { x: 12, y: -12 }, ownerId: 'multi-1' },
47
+ { id: 'm2-label', content: 'Multi 2', position: { x: 12, y: -12 }, ownerId: 'multi-2' },
48
+ { id: 'm3-label', content: 'Multi 3', position: { x: 12, y: -12 }, ownerId: 'multi-3' },
49
+ ],
50
+ });
51
+
52
+ export const multipleElementsDemoConfig: DemoConfig = ({
53
+ id: 'multiple',
54
+ title: 'Multiple Elements + Links',
55
+ description: 'Three elements with ports, links, and labels.',
56
+ createState: createMultipleElementsState,
57
+ elementShapes: baseElementShapes,
58
+ portShapes: basePortShapes,
59
+ defaultElementShapeId: 'default',
60
+ defaultPortShapeId: 'port-circle',
61
+ actions: [],
62
+ });
@@ -0,0 +1,78 @@
1
+ import type { DiagramState } from '../../api';
2
+ import { createId } from '../../utils/ids';
3
+ import type { DemoConfig } from '../types';
4
+ import { baseElementShapes, basePortShapes } from './shared';
5
+
6
+ const createNestedState = (): DiagramState => ({
7
+ elements: [
8
+ {
9
+ id: 'parent-1',
10
+ position: { x: 140, y: 140 },
11
+ size: { width: 320, height: 240 },
12
+ shapeId: 'panel',
13
+ },
14
+ {
15
+ id: 'child-1',
16
+ position: { x: 40, y: 60 },
17
+ size: { width: 160, height: 100 },
18
+ shapeId: 'default',
19
+ parentId: 'parent-1',
20
+ },
21
+ ],
22
+ ports: [
23
+ {
24
+ id: 'child-port',
25
+ elementId: 'child-1',
26
+ position: { x: 20, y: 20 },
27
+ shapeId: 'port-circle',
28
+ anchorCenter: true,
29
+ },
30
+ ],
31
+ links: [],
32
+ texts: [
33
+ {
34
+ id: 'child-label',
35
+ content: 'Child',
36
+ position: { x: 6, y: -16 },
37
+ ownerId: 'child-1',
38
+ },
39
+ ],
40
+ });
41
+
42
+ export const nestedDemoConfig: DemoConfig = ({
43
+ id: 'nested',
44
+ title: 'Nested Elements',
45
+ description: 'Parent/child elements with world positioning.',
46
+ createState: createNestedState,
47
+ elementShapes: baseElementShapes,
48
+ portShapes: basePortShapes,
49
+ defaultElementShapeId: 'default',
50
+ defaultPortShapeId: 'port-circle',
51
+ actions: [
52
+ {
53
+ id: 'move-parent',
54
+ label: 'Move parent',
55
+ run: (editor, state) => {
56
+ const parent = state.elements.find((element) => element.id === 'parent-1');
57
+ if (!parent) return;
58
+ editor.moveElementTo(parent.id, parent.position.x + 40, parent.position.y + 20);
59
+ },
60
+ },
61
+ {
62
+ id: 'add-child',
63
+ label: 'Add child',
64
+ run: (editor, state, demo, helpers) => {
65
+ const parent = state.elements.find((element) => element.id === 'parent-1');
66
+ if (!parent) return;
67
+ const offset = helpers.nextOffset();
68
+ editor.addElement({
69
+ id: `child-${createId()}`,
70
+ position: { x: 30 + offset, y: 50 + offset },
71
+ size: { width: 140, height: 90 },
72
+ shapeId: demo.defaultElementShapeId ?? 'default',
73
+ parentId: parent.id,
74
+ });
75
+ },
76
+ },
77
+ ],
78
+ });
@@ -0,0 +1,176 @@
1
+ import type { DiagramState, LinkData } from '../../api';
2
+ import type { DemoAction, DemoConfig } from '../types';
3
+ import { baseElementShapes, basePortShapes } from './shared';
4
+
5
+ const obstacleRoutingLinks: LinkData[] = [
6
+ {
7
+ id: 'block-link',
8
+ sourcePortId: 'block-source-port',
9
+ targetPortId: 'block-target-port',
10
+ points: [],
11
+ routing: 'auto',
12
+ },
13
+ {
14
+ id: 'shared-sibling-link',
15
+ sourcePortId: 'shared-child-a-port',
16
+ targetPortId: 'shared-child-b-port',
17
+ points: [],
18
+ routing: 'auto',
19
+ },
20
+ {
21
+ id: 'parent-child-link',
22
+ sourcePortId: 'parent-host-port',
23
+ targetPortId: 'edge-child-port',
24
+ points: [],
25
+ routing: 'auto',
26
+ },
27
+ {
28
+ id: 'grandchild-link',
29
+ sourcePortId: 'grandchild-a-port',
30
+ targetPortId: 'grandchild-b-port',
31
+ points: [],
32
+ routing: 'auto',
33
+ },
34
+ ];
35
+
36
+ const createObstacleRoutingState = (): DiagramState => ({
37
+ elements: [
38
+ {
39
+ id: 'block-source',
40
+ position: { x: 60, y: 40 },
41
+ size: { width: 140, height: 90 },
42
+ shapeId: 'default',
43
+ },
44
+ {
45
+ id: 'block-target',
46
+ position: { x: 380, y: 40 },
47
+ size: { width: 140, height: 90 },
48
+ shapeId: 'panel',
49
+ },
50
+ {
51
+ id: 'block-obstacle',
52
+ position: { x: 250, y: 30 },
53
+ size: { width: 80, height: 110 },
54
+ shapeId: 'default',
55
+ },
56
+ {
57
+ id: 'shared-parent',
58
+ position: { x: 40, y: 180 },
59
+ size: { width: 420, height: 220 },
60
+ shapeId: 'panel',
61
+ style: { fill: '#fafafa' },
62
+ },
63
+ {
64
+ id: 'shared-child-a',
65
+ position: { x: 40, y: 40 },
66
+ size: { width: 140, height: 90 },
67
+ shapeId: 'default',
68
+ parentId: 'shared-parent',
69
+ },
70
+ {
71
+ id: 'shared-child-b',
72
+ position: { x: 220, y: 40 },
73
+ size: { width: 140, height: 90 },
74
+ shapeId: 'default',
75
+ parentId: 'shared-parent',
76
+ },
77
+ {
78
+ id: 'parent-host',
79
+ position: { x: 500, y: 180 },
80
+ size: { width: 320, height: 220 },
81
+ shapeId: 'panel',
82
+ style: { fill: '#fafafa' },
83
+ },
84
+ {
85
+ id: 'edge-child',
86
+ position: { x: 40, y: 60 },
87
+ size: { width: 160, height: 90 },
88
+ shapeId: 'default',
89
+ parentId: 'parent-host',
90
+ },
91
+ {
92
+ id: 'grandparent',
93
+ position: { x: 40, y: 380 },
94
+ size: { width: 780, height: 160 },
95
+ shapeId: 'panel',
96
+ style: { fill: '#fafafa' },
97
+ },
98
+ {
99
+ id: 'mid-parent-a',
100
+ position: { x: 40, y: 30 },
101
+ size: { width: 300, height: 100 },
102
+ shapeId: 'panel',
103
+ parentId: 'grandparent',
104
+ },
105
+ {
106
+ id: 'mid-parent-b',
107
+ position: { x: 420, y: 30 },
108
+ size: { width: 300, height: 100 },
109
+ shapeId: 'panel',
110
+ parentId: 'grandparent',
111
+ },
112
+ {
113
+ id: 'grandchild-a',
114
+ position: { x: 40, y: 20 },
115
+ size: { width: 120, height: 60 },
116
+ shapeId: 'default',
117
+ parentId: 'mid-parent-a',
118
+ },
119
+ {
120
+ id: 'grandchild-b',
121
+ position: { x: 40, y: 20 },
122
+ size: { width: 120, height: 60 },
123
+ shapeId: 'default',
124
+ parentId: 'mid-parent-b',
125
+ },
126
+ ],
127
+ ports: [
128
+ { id: 'block-source-port', elementId: 'block-source', position: { x: 70, y: 45 }, shapeId: 'port-circle' },
129
+ { id: 'block-target-port', elementId: 'block-target', position: { x: 70, y: 45 }, shapeId: 'port-circle' },
130
+ { id: 'shared-child-a-port', elementId: 'shared-child-a', position: { x: 70, y: 45 }, shapeId: 'port-circle' },
131
+ { id: 'shared-child-b-port', elementId: 'shared-child-b', position: { x: 70, y: 45 }, shapeId: 'port-circle' },
132
+ { id: 'parent-host-port', elementId: 'parent-host', position: { x: 250, y: 110 }, shapeId: 'port-circle' },
133
+ { id: 'edge-child-port', elementId: 'edge-child', position: { x: 0, y: 45 }, shapeId: 'port-circle' },
134
+ { id: 'grandchild-a-port', elementId: 'grandchild-a', position: { x: 60, y: 30 }, shapeId: 'port-circle' },
135
+ { id: 'grandchild-b-port', elementId: 'grandchild-b', position: { x: 60, y: 30 }, shapeId: 'port-circle' },
136
+ ],
137
+ links: obstacleRoutingLinks,
138
+ texts: [
139
+ { id: 'block-label', content: 'Blocking obstacle', position: { x: 60, y: 16 } },
140
+ { id: 'shared-label', content: 'Shared parent (siblings)', position: { x: 40, y: 158 } },
141
+ { id: 'parent-label', content: 'Parent-child (stay inside)', position: { x: 500, y: 158 } },
142
+ { id: 'grand-label', content: 'Grandchildren (shared ancestors)', position: { x: 40, y: 358 } },
143
+ ],
144
+ });
145
+
146
+ const addLinksAction: DemoAction = {
147
+ id: 'add-links',
148
+ label: 'Add Links (Auto)',
149
+ run: (editor, state) => {
150
+ const existing = new Set(state.links.map((link) => link.id));
151
+ obstacleRoutingLinks.forEach((link) => {
152
+ if (existing.has(link.id)) return;
153
+ editor.addLink({ ...link });
154
+ });
155
+ },
156
+ };
157
+
158
+ const rerouteAllAction: DemoAction = {
159
+ id: 'reroute-links',
160
+ label: 'Reroute All Links',
161
+ run: (editor) => {
162
+ editor.rerouteAllLinks();
163
+ },
164
+ };
165
+
166
+ export const obstacleRoutingDemoConfig: DemoConfig = ({
167
+ id: 'obstacle-routing',
168
+ title: 'Obstacle Routing',
169
+ description: 'Auto routing avoids obstacles and respects ancestor/edge rules.',
170
+ createState: createObstacleRoutingState,
171
+ elementShapes: baseElementShapes,
172
+ portShapes: basePortShapes,
173
+ defaultElementShapeId: 'default',
174
+ defaultPortShapeId: 'port-circle',
175
+ actions: [addLinksAction, rerouteAllAction],
176
+ });
@@ -0,0 +1,98 @@
1
+ import type { DiagramState } from '../../api';
2
+ import type { DemoConfig } from '../types';
3
+ import { baseElementShapes, basePortShapes } from './shared';
4
+
5
+ const createPortBorderState = (): DiagramState => ({
6
+ elements: [
7
+ {
8
+ id: 'border-host-orient-on',
9
+ position: { x: 120, y: 150 },
10
+ size: { width: 260, height: 180 },
11
+ shapeId: 'default',
12
+ },
13
+ {
14
+ id: 'border-host-orient-off',
15
+ position: { x: 460, y: 150 },
16
+ size: { width: 260, height: 180 },
17
+ shapeId: 'default',
18
+ },
19
+ ],
20
+ ports: [
21
+ {
22
+ id: 'border-port-orient-on',
23
+ elementId: 'border-host-orient-on',
24
+ position: { x: 130, y: 0 },
25
+ shapeId: 'port-triangle',
26
+ moveMode: 'border',
27
+ anchorCenter: true,
28
+ orientToHostBorder: true,
29
+ },
30
+ {
31
+ id: 'border-port-orient-off',
32
+ elementId: 'border-host-orient-off',
33
+ position: { x: 130, y: 0 },
34
+ shapeId: 'port-triangle',
35
+ moveMode: 'border',
36
+ anchorCenter: true,
37
+ orientToHostBorder: false,
38
+ },
39
+ ],
40
+ links: [
41
+ {
42
+ id: 'border-link',
43
+ sourcePortId: 'border-port-orient-on',
44
+ targetPortId: 'border-port-orient-off',
45
+ points: [],
46
+ },
47
+ ],
48
+ texts: [
49
+ {
50
+ id: 'border-host-orient-on-label',
51
+ content: 'Orientation ON',
52
+ position: { x: 12, y: -14 },
53
+ ownerId: 'border-host-orient-on',
54
+ },
55
+ {
56
+ id: 'border-host-orient-off-label',
57
+ content: 'Orientation OFF',
58
+ position: { x: 12, y: -14 },
59
+ ownerId: 'border-host-orient-off',
60
+ },
61
+ {
62
+ id: 'border-port-orient-on-label',
63
+ content: 'Drag around border',
64
+ position: { x: 8, y: -18 },
65
+ ownerId: 'border-port-orient-on',
66
+ },
67
+ {
68
+ id: 'border-port-orient-off-label',
69
+ content: 'Drag around border',
70
+ position: { x: 8, y: -18 },
71
+ ownerId: 'border-port-orient-off',
72
+ },
73
+ ],
74
+ });
75
+
76
+ export const portBorderDemoConfig: DemoConfig = ({
77
+ id: 'port-border',
78
+ title: 'Port Border Orientation',
79
+ description: 'Directional ports rotate toward host interior by default (left: on, right: opt-out).',
80
+ createState: createPortBorderState,
81
+ elementShapes: baseElementShapes,
82
+ portShapes: [
83
+ ...basePortShapes,
84
+ {
85
+ id: 'port-triangle',
86
+ kind: 'triangle',
87
+ style: {
88
+ fill: '#ffffff',
89
+ stroke: '#1f4d99',
90
+ strokeWidth: 2,
91
+ name: 'port',
92
+ },
93
+ },
94
+ ],
95
+ defaultElementShapeId: 'default',
96
+ defaultPortShapeId: 'port-triangle',
97
+ actions: [],
98
+ });