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.
Files changed (37) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +7 -12
  3. package/ai/api-contract.json +16 -0
  4. package/ai/invariants.json +8 -0
  5. package/ai/manifest.json +1 -1
  6. package/dist/cjs/examples.js +604 -39
  7. package/dist/cjs/index.js +227 -28
  8. package/dist/cjs/types/api/types.d.ts +2 -0
  9. package/dist/cjs/types/displaybox/demos/elementVisibilitySelectionDemo.d.ts +4 -0
  10. package/dist/cjs/types/engine/DiagramEngine.d.ts +8 -0
  11. package/dist/cjs/types/models/DiagramModel.d.ts +5 -0
  12. package/dist/cjs/types/models/ElementModel.d.ts +2 -0
  13. package/dist/esm/examples.js +604 -39
  14. package/dist/esm/examples.js.map +1 -1
  15. package/dist/esm/index.js +227 -28
  16. package/dist/esm/index.js.map +1 -1
  17. package/dist/esm/types/api/types.d.ts +2 -0
  18. package/dist/esm/types/displaybox/demos/elementVisibilitySelectionDemo.d.ts +4 -0
  19. package/dist/esm/types/engine/DiagramEngine.d.ts +8 -0
  20. package/dist/esm/types/models/DiagramModel.d.ts +5 -0
  21. package/dist/esm/types/models/ElementModel.d.ts +2 -0
  22. package/dist/examples.d.ts +2 -0
  23. package/dist/index.d.ts +9 -0
  24. package/docs/API_CONTRACT.md +16 -1
  25. package/docs/CAPABILITIES.md +1 -0
  26. package/docs/COMMANDS_EVENTS.md +3 -1
  27. package/docs/DOCUMENTATION_WORKFLOW.md +3 -1
  28. package/docs/INTEGRATION_PLAYBOOK.md +1 -0
  29. package/docs/PORTING_CHECKLIST.md +1 -0
  30. package/docs/STATE_INVARIANTS.md +9 -1
  31. package/package.json +1 -1
  32. package/src/displaybox/demos/AutoLayoutDemoTab.tsx +11 -5
  33. package/src/displaybox/demos/autoLayoutDemo.ts +233 -0
  34. package/src/displaybox/demos/basicDemo.ts +6 -6
  35. package/src/displaybox/demos/elementVisibilitySelectionDemo.ts +128 -0
  36. package/src/displaybox/demos/index.tsx +14 -7
  37. package/src/displaybox/demos/selectionDemo.ts +12 -12
@@ -743,7 +743,7 @@ var createBasicState = function () { return ({
743
743
  var basicDemoConfig = ({
744
744
  id: 'basic',
745
745
  title: 'Basic Diagram',
746
- description: 'Elements, ports, link, and labels.',
746
+ description: 'Elements, ports, link, and labels. Drag empty paper to pan; use Shift + drag for marquee selection.',
747
747
  createState: createBasicState,
748
748
  elementShapes: baseElementShapes,
749
749
  portShapes: basePortShapes,
@@ -1121,7 +1121,7 @@ var createSelectionState = function () { return ({
1121
1121
  texts: [
1122
1122
  {
1123
1123
  id: 'select-tip',
1124
- content: 'Click to select, drag to move, Delete/Backspace to remove.',
1124
+ content: 'Click to select, drag to move, drag empty paper to pan, Shift + drag to marquee-select.',
1125
1125
  position: { x: 80, y: 80 },
1126
1126
  },
1127
1127
  ],
@@ -1129,7 +1129,7 @@ var createSelectionState = function () { return ({
1129
1129
  var selectionDemoConfig = ({
1130
1130
  id: 'selection',
1131
1131
  title: 'Selection + Interaction',
1132
- description: 'Click to select, drag to move, marquee-select on empty space, delete to remove.',
1132
+ description: 'Click to select, drag to move, drag empty paper to pan, Shift + drag to marquee-select, delete to remove.',
1133
1133
  createState: createSelectionState,
1134
1134
  elementShapes: baseElementShapes,
1135
1135
  portShapes: basePortShapes,
@@ -1146,6 +1146,128 @@ var selectionDemoConfig = ({
1146
1146
  ],
1147
1147
  });
1148
1148
 
1149
+ var createElementVisibilitySelectionState = function () { return ({
1150
+ elements: [
1151
+ {
1152
+ id: 'policy-normal',
1153
+ position: { x: 120, y: 160 },
1154
+ size: { width: 180, height: 120 },
1155
+ shapeId: 'default',
1156
+ style: { fill: '#dbeafe', stroke: '#1d4ed8', strokeWidth: 2 },
1157
+ },
1158
+ {
1159
+ id: 'policy-unselectable',
1160
+ position: { x: 410, y: 160 },
1161
+ size: { width: 180, height: 120 },
1162
+ shapeId: 'default',
1163
+ selectable: false,
1164
+ style: { fill: '#e2e8f0', stroke: '#334155', strokeWidth: 2 },
1165
+ },
1166
+ {
1167
+ id: 'policy-hidden',
1168
+ position: { x: 700, y: 140 },
1169
+ size: { width: 180, height: 120 },
1170
+ shapeId: 'default',
1171
+ visible: false,
1172
+ style: { fill: '#fee2e2', stroke: '#dc2626', strokeWidth: 2 },
1173
+ },
1174
+ ],
1175
+ ports: [
1176
+ {
1177
+ id: 'policy-normal-port',
1178
+ elementId: 'policy-normal',
1179
+ position: { x: 180, y: 60 },
1180
+ shapeId: 'port-circle',
1181
+ },
1182
+ {
1183
+ id: 'policy-unselectable-port',
1184
+ elementId: 'policy-unselectable',
1185
+ position: { x: 0, y: 60 },
1186
+ shapeId: 'port-circle',
1187
+ },
1188
+ {
1189
+ id: 'policy-hidden-port',
1190
+ elementId: 'policy-hidden',
1191
+ position: { x: 0, y: 60 },
1192
+ shapeId: 'port-circle',
1193
+ },
1194
+ ],
1195
+ links: [
1196
+ {
1197
+ id: 'policy-visible-link',
1198
+ sourcePortId: 'policy-normal-port',
1199
+ targetPortId: 'policy-unselectable-port',
1200
+ points: [
1201
+ { x: 300, y: 220 },
1202
+ { x: 410, y: 220 },
1203
+ ],
1204
+ style: { stroke: '#2563eb', strokeWidth: 3 },
1205
+ },
1206
+ {
1207
+ id: 'policy-hidden-link',
1208
+ sourcePortId: 'policy-normal-port',
1209
+ targetPortId: 'policy-hidden-port',
1210
+ points: [
1211
+ { x: 300, y: 220 },
1212
+ { x: 700, y: 200 },
1213
+ ],
1214
+ style: { stroke: '#dc2626', strokeWidth: 3 },
1215
+ },
1216
+ ],
1217
+ texts: [
1218
+ {
1219
+ id: 'policy-tip',
1220
+ content: 'Blue node is normal. Slate node is visible but its body ignores click and marquee. Its port stays interactive. Hidden node, its port, and its attached red link stay in state but are suppressed from scene, selection, zoom-to-fit, and fit-to-content export.',
1221
+ position: { x: 80, y: 72 },
1222
+ size: { width: 760, height: 44 },
1223
+ style: { fontSize: 14, fill: '#0f172a' },
1224
+ },
1225
+ {
1226
+ id: 'policy-normal-label',
1227
+ content: 'Normal selectable element',
1228
+ position: { x: 16, y: 14 },
1229
+ ownerId: 'policy-normal',
1230
+ },
1231
+ {
1232
+ id: 'policy-unselectable-label',
1233
+ content: 'Visible but body is unselectable',
1234
+ position: { x: 16, y: 14 },
1235
+ ownerId: 'policy-unselectable',
1236
+ },
1237
+ {
1238
+ id: 'policy-hidden-label',
1239
+ content: 'Hidden in state',
1240
+ position: { x: 16, y: 14 },
1241
+ ownerId: 'policy-hidden',
1242
+ },
1243
+ ],
1244
+ }); };
1245
+ var elementVisibilitySelectionDemoConfig = {
1246
+ id: 'element-visibility-selection',
1247
+ title: 'Element Visibility + Selectability',
1248
+ description: 'QA scene for visible-but-unselectable element bodies, hidden-in-state elements, and port/link propagation. Shift + drag marquee to confirm only eligible items are collected.',
1249
+ createState: createElementVisibilitySelectionState,
1250
+ elementShapes: baseElementShapes,
1251
+ portShapes: basePortShapes,
1252
+ defaultElementShapeId: 'default',
1253
+ defaultPortShapeId: 'port-circle',
1254
+ actions: [
1255
+ {
1256
+ id: 'policy-filtered-selection',
1257
+ label: 'Try filtered API selection',
1258
+ run: function (editor) {
1259
+ editor.setSelection([
1260
+ 'policy-normal',
1261
+ 'policy-unselectable',
1262
+ 'policy-hidden',
1263
+ 'policy-unselectable-port',
1264
+ 'policy-hidden-link',
1265
+ ]);
1266
+ },
1267
+ },
1268
+ ],
1269
+ };
1270
+
1149
1271
  var createEventHandlersState = function () { return ({
1150
1272
  elements: [
1151
1273
  {
@@ -1429,6 +1551,192 @@ var createAutoLayoutState = function (lockComparisonChildren) {
1429
1551
  { id: 'deep-grid-b', position: { x: 0, y: 0 }, size: { width: 40, height: 28 }, shapeId: 'default', parentId: 'deep-grid-nested-parent' },
1430
1552
  { id: 'deep-grid-c', position: { x: 0, y: 0 }, size: { width: 52, height: 24 }, shapeId: 'default', parentId: 'deep-grid-nested-parent' },
1431
1553
  { id: 'deep-grid-d', position: { x: 0, y: 0 }, size: { width: 28, height: 30 }, shapeId: 'default', parentId: 'deep-grid-nested-parent' },
1554
+ {
1555
+ id: 'layout-grid-empty-compare',
1556
+ position: { x: 930, y: 70 },
1557
+ size: { width: 280, height: 190 },
1558
+ shapeId: 'panel',
1559
+ layout: {
1560
+ mode: 'grid',
1561
+ padding: { x: 12, y: 12 },
1562
+ gap: 12,
1563
+ align: 'center',
1564
+ autoResize: 'grow-shrink',
1565
+ gridTemplate: [4, 4, 4],
1566
+ gridChildWidthResizeEnabled: true,
1567
+ childMinWidth: 44,
1568
+ childMinHeight: 52,
1569
+ },
1570
+ },
1571
+ {
1572
+ id: 'empty-grid-slot',
1573
+ position: { x: 0, y: 0 },
1574
+ size: { width: 28, height: 18 },
1575
+ shapeId: 'default',
1576
+ parentId: 'layout-grid-empty-compare',
1577
+ layout: {
1578
+ mode: 'grid',
1579
+ padding: { x: 8, y: 8 },
1580
+ gap: 8,
1581
+ align: 'center',
1582
+ autoResize: 'grow-shrink',
1583
+ gridTemplate: [6, 6],
1584
+ gridChildWidthResizeEnabled: true,
1585
+ },
1586
+ },
1587
+ {
1588
+ id: 'filled-grid-slot',
1589
+ position: { x: 0, y: 0 },
1590
+ size: { width: 92, height: 88 },
1591
+ shapeId: 'default',
1592
+ parentId: 'layout-grid-empty-compare',
1593
+ layout: {
1594
+ mode: 'grid',
1595
+ padding: { x: 8, y: 8 },
1596
+ gap: 8,
1597
+ align: 'center',
1598
+ autoResize: 'grow-shrink',
1599
+ gridTemplate: [6, 6],
1600
+ gridChildWidthResizeEnabled: true,
1601
+ childMinWidth: 18,
1602
+ childMinHeight: 18,
1603
+ },
1604
+ },
1605
+ {
1606
+ id: 'empty-grid-compare-leaf',
1607
+ position: { x: 0, y: 0 },
1608
+ size: { width: 60, height: 70 },
1609
+ shapeId: 'default',
1610
+ parentId: 'layout-grid-empty-compare',
1611
+ },
1612
+ { id: 'filled-grid-slot-a', position: { x: 0, y: 0 }, size: { width: 34, height: 22 }, shapeId: 'default', parentId: 'filled-grid-slot' },
1613
+ { id: 'filled-grid-slot-b', position: { x: 0, y: 0 }, size: { width: 40, height: 24 }, shapeId: 'default', parentId: 'filled-grid-slot' },
1614
+ { id: 'filled-grid-slot-c', position: { x: 0, y: 0 }, size: { width: 48, height: 22 }, shapeId: 'default', parentId: 'filled-grid-slot' },
1615
+ {
1616
+ id: 'layout-grid-mixed-modes',
1617
+ position: { x: 930, y: 320 },
1618
+ size: { width: 340, height: 240 },
1619
+ shapeId: 'panel',
1620
+ layout: {
1621
+ mode: 'grid',
1622
+ padding: { x: 12, y: 12 },
1623
+ gap: 12,
1624
+ align: 'center',
1625
+ autoResize: 'grow-shrink',
1626
+ gridTemplate: [4, 4, 4],
1627
+ gridChildWidthResizeEnabled: true,
1628
+ childMinWidth: 52,
1629
+ childMinHeight: 64,
1630
+ },
1631
+ },
1632
+ {
1633
+ id: 'mixed-grid-child',
1634
+ position: { x: 0, y: 0 },
1635
+ size: { width: 88, height: 88 },
1636
+ shapeId: 'default',
1637
+ parentId: 'layout-grid-mixed-modes',
1638
+ layout: {
1639
+ mode: 'grid',
1640
+ padding: { x: 8, y: 8 },
1641
+ gap: 8,
1642
+ align: 'center',
1643
+ autoResize: 'grow-shrink',
1644
+ gridTemplate: [6, 6],
1645
+ gridChildWidthResizeEnabled: true,
1646
+ childMinWidth: 18,
1647
+ childMinHeight: 18,
1648
+ },
1649
+ },
1650
+ {
1651
+ id: 'mixed-column-child',
1652
+ position: { x: 0, y: 0 },
1653
+ size: { width: 92, height: 96 },
1654
+ shapeId: 'default',
1655
+ parentId: 'layout-grid-mixed-modes',
1656
+ layout: {
1657
+ mode: 'vertical',
1658
+ padding: { x: 8, y: 8 },
1659
+ gap: 8,
1660
+ align: 'center',
1661
+ autoResize: 'grow-shrink',
1662
+ },
1663
+ },
1664
+ {
1665
+ id: 'mixed-row-child',
1666
+ position: { x: 0, y: 0 },
1667
+ size: { width: 104, height: 84 },
1668
+ shapeId: 'default',
1669
+ parentId: 'layout-grid-mixed-modes',
1670
+ layout: {
1671
+ mode: 'horizontal',
1672
+ padding: { x: 8, y: 8 },
1673
+ gap: 8,
1674
+ align: 'center',
1675
+ autoResize: 'grow-shrink',
1676
+ },
1677
+ },
1678
+ { id: 'mixed-grid-a', position: { x: 0, y: 0 }, size: { width: 34, height: 22 }, shapeId: 'default', parentId: 'mixed-grid-child' },
1679
+ { id: 'mixed-grid-b', position: { x: 0, y: 0 }, size: { width: 44, height: 24 }, shapeId: 'default', parentId: 'mixed-grid-child' },
1680
+ { id: 'mixed-column-a', position: { x: 0, y: 0 }, size: { width: 60, height: 20 }, shapeId: 'default', parentId: 'mixed-column-child' },
1681
+ { id: 'mixed-column-b', position: { x: 0, y: 0 }, size: { width: 68, height: 24 }, shapeId: 'default', parentId: 'mixed-column-child' },
1682
+ { id: 'mixed-row-a', position: { x: 0, y: 0 }, size: { width: 32, height: 28 }, shapeId: 'default', parentId: 'mixed-row-child' },
1683
+ { id: 'mixed-row-b', position: { x: 0, y: 0 }, size: { width: 44, height: 24 }, shapeId: 'default', parentId: 'mixed-row-child' },
1684
+ {
1685
+ id: 'layout-column-grid-tree',
1686
+ position: { x: 40, y: 520 },
1687
+ size: { width: 340, height: 220 },
1688
+ shapeId: 'panel',
1689
+ layout: { mode: 'vertical', padding: { x: 12, y: 12 }, gap: 12, align: 'start', autoResize: 'grow-shrink' },
1690
+ },
1691
+ {
1692
+ id: 'column-grid-tree-top',
1693
+ position: { x: 0, y: 0 },
1694
+ size: { width: 180, height: 88 },
1695
+ shapeId: 'default',
1696
+ parentId: 'layout-column-grid-tree',
1697
+ layout: {
1698
+ mode: 'grid',
1699
+ padding: { x: 8, y: 8 },
1700
+ gap: 8,
1701
+ align: 'center',
1702
+ autoResize: 'grow-shrink',
1703
+ gridTemplate: [6, 6],
1704
+ gridChildWidthResizeEnabled: true,
1705
+ childMinWidth: 18,
1706
+ childMinHeight: 18,
1707
+ },
1708
+ },
1709
+ {
1710
+ id: 'column-grid-tree-branch',
1711
+ position: { x: 0, y: 0 },
1712
+ size: { width: 220, height: 96 },
1713
+ shapeId: 'default',
1714
+ parentId: 'layout-column-grid-tree',
1715
+ layout: { mode: 'horizontal', padding: { x: 8, y: 8 }, gap: 8, align: 'center', autoResize: 'grow-shrink' },
1716
+ },
1717
+ { id: 'column-grid-top-a', position: { x: 0, y: 0 }, size: { width: 52, height: 22 }, shapeId: 'default', parentId: 'column-grid-tree-top' },
1718
+ { id: 'column-grid-top-b', position: { x: 0, y: 0 }, size: { width: 44, height: 24 }, shapeId: 'default', parentId: 'column-grid-tree-top' },
1719
+ {
1720
+ id: 'column-grid-tree-inner-grid',
1721
+ position: { x: 0, y: 0 },
1722
+ size: { width: 120, height: 84 },
1723
+ shapeId: 'default',
1724
+ parentId: 'column-grid-tree-branch',
1725
+ layout: {
1726
+ mode: 'grid',
1727
+ padding: { x: 8, y: 8 },
1728
+ gap: 8,
1729
+ align: 'center',
1730
+ autoResize: 'grow-shrink',
1731
+ gridTemplate: [6, 6],
1732
+ gridChildWidthResizeEnabled: true,
1733
+ childMinWidth: 18,
1734
+ childMinHeight: 18,
1735
+ },
1736
+ },
1737
+ { id: 'column-grid-tree-leaf', position: { x: 0, y: 0 }, size: { width: 58, height: 62 }, shapeId: 'default', parentId: 'column-grid-tree-branch' },
1738
+ { id: 'column-grid-inner-a', position: { x: 0, y: 0 }, size: { width: 30, height: 22 }, shapeId: 'default', parentId: 'column-grid-tree-inner-grid' },
1739
+ { id: 'column-grid-inner-b', position: { x: 0, y: 0 }, size: { width: 42, height: 24 }, shapeId: 'default', parentId: 'column-grid-tree-inner-grid' },
1432
1740
  {
1433
1741
  id: 'layout-lock-compare',
1434
1742
  position: { x: 420, y: 410 },
@@ -1526,6 +1834,50 @@ var createAutoLayoutState = function (lockComparisonChildren) {
1526
1834
  { id: 'label-deep-grid-b', content: 'grid-b', position: { x: 6, y: -14 }, ownerId: 'deep-grid-b' },
1527
1835
  { id: 'label-deep-grid-c', content: 'grid-c', position: { x: 6, y: -14 }, ownerId: 'deep-grid-c' },
1528
1836
  { id: 'label-deep-grid-d', content: 'grid-d', position: { x: 6, y: -14 }, ownerId: 'deep-grid-d' },
1837
+ {
1838
+ id: 'label-layout-grid-empty-compare',
1839
+ content: 'Grid owner: empty vs filled nested grids',
1840
+ position: { x: 8, y: 6 },
1841
+ ownerId: 'layout-grid-empty-compare',
1842
+ layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
1843
+ },
1844
+ { id: 'label-empty-grid-slot', content: 'empty nested grid', position: { x: 6, y: -16 }, ownerId: 'empty-grid-slot' },
1845
+ { id: 'label-filled-grid-slot', content: 'nested grid with children', position: { x: 6, y: -16 }, ownerId: 'filled-grid-slot' },
1846
+ { id: 'label-empty-grid-compare-leaf', content: 'leaf sibling', position: { x: 6, y: -16 }, ownerId: 'empty-grid-compare-leaf' },
1847
+ { id: 'label-filled-grid-slot-a', content: 'slot-a', position: { x: 6, y: -14 }, ownerId: 'filled-grid-slot-a' },
1848
+ { id: 'label-filled-grid-slot-b', content: 'slot-b', position: { x: 6, y: -14 }, ownerId: 'filled-grid-slot-b' },
1849
+ { id: 'label-filled-grid-slot-c', content: 'slot-c', position: { x: 6, y: -14 }, ownerId: 'filled-grid-slot-c' },
1850
+ {
1851
+ id: 'label-layout-grid-mixed-modes',
1852
+ content: 'Grid owner: mixed child layout modes',
1853
+ position: { x: 8, y: 6 },
1854
+ ownerId: 'layout-grid-mixed-modes',
1855
+ layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
1856
+ },
1857
+ { id: 'label-mixed-grid-child', content: 'grid child', position: { x: 6, y: -16 }, ownerId: 'mixed-grid-child' },
1858
+ { id: 'label-mixed-column-child', content: 'vertical child', position: { x: 6, y: -16 }, ownerId: 'mixed-column-child' },
1859
+ { id: 'label-mixed-row-child', content: 'horizontal child', position: { x: 6, y: -16 }, ownerId: 'mixed-row-child' },
1860
+ { id: 'label-mixed-grid-a', content: 'grid-a', position: { x: 6, y: -14 }, ownerId: 'mixed-grid-a' },
1861
+ { id: 'label-mixed-grid-b', content: 'grid-b', position: { x: 6, y: -14 }, ownerId: 'mixed-grid-b' },
1862
+ { id: 'label-mixed-column-a', content: 'col-a', position: { x: 6, y: -14 }, ownerId: 'mixed-column-a' },
1863
+ { id: 'label-mixed-column-b', content: 'col-b', position: { x: 6, y: -14 }, ownerId: 'mixed-column-b' },
1864
+ { id: 'label-mixed-row-a', content: 'row-a', position: { x: 6, y: -14 }, ownerId: 'mixed-row-a' },
1865
+ { id: 'label-mixed-row-b', content: 'row-b', position: { x: 6, y: -14 }, ownerId: 'mixed-row-b' },
1866
+ {
1867
+ id: 'label-layout-column-grid-tree',
1868
+ content: 'Vertical owner with grid descendants',
1869
+ position: { x: 8, y: 6 },
1870
+ ownerId: 'layout-column-grid-tree',
1871
+ layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
1872
+ },
1873
+ { id: 'label-column-grid-tree-top', content: 'top-level grid child', position: { x: 6, y: -16 }, ownerId: 'column-grid-tree-top' },
1874
+ { id: 'label-column-grid-tree-branch', content: 'row branch with inner grid', position: { x: 6, y: -16 }, ownerId: 'column-grid-tree-branch' },
1875
+ { id: 'label-column-grid-top-a', content: 'top-a', position: { x: 6, y: -14 }, ownerId: 'column-grid-top-a' },
1876
+ { id: 'label-column-grid-top-b', content: 'top-b', position: { x: 6, y: -14 }, ownerId: 'column-grid-top-b' },
1877
+ { id: 'label-column-grid-tree-inner-grid', content: 'nested grid descendant', position: { x: 6, y: -16 }, ownerId: 'column-grid-tree-inner-grid' },
1878
+ { id: 'label-column-grid-tree-leaf', content: 'branch leaf', position: { x: 6, y: -14 }, ownerId: 'column-grid-tree-leaf' },
1879
+ { id: 'label-column-grid-inner-a', content: 'inner-a', position: { x: 6, y: -14 }, ownerId: 'column-grid-inner-a' },
1880
+ { id: 'label-column-grid-inner-b', content: 'inner-b', position: { x: 6, y: -14 }, ownerId: 'column-grid-inner-b' },
1529
1881
  {
1530
1882
  id: 'label-layout-lock-compare',
1531
1883
  content: 'Child drag lock comparison',
@@ -4382,6 +4734,8 @@ var ElementModel = /** @class */ (function () {
4382
4734
  this.style = data.style;
4383
4735
  this.portIds = data.portIds ? __spreadArray([], data.portIds, true) : [];
4384
4736
  this.textIds = data.textIds ? __spreadArray([], data.textIds, true) : [];
4737
+ this.visible = data.visible;
4738
+ this.selectable = data.selectable;
4385
4739
  this.parentId = (_a = data.parentId) !== null && _a !== void 0 ? _a : null;
4386
4740
  this.moveMode = data.moveMode;
4387
4741
  this.anchorCenter = data.anchorCenter;
@@ -4420,6 +4774,8 @@ var ElementModel = /** @class */ (function () {
4420
4774
  style: this.style,
4421
4775
  portIds: __spreadArray([], this.portIds, true),
4422
4776
  textIds: __spreadArray([], this.textIds, true),
4777
+ visible: this.visible,
4778
+ selectable: this.selectable,
4423
4779
  parentId: this.parentId,
4424
4780
  moveMode: this.moveMode,
4425
4781
  anchorCenter: this.anchorCenter,
@@ -4823,6 +5179,29 @@ var DiagramModel = /** @class */ (function () {
4823
5179
  DiagramModel.prototype.getElement = function (id) {
4824
5180
  return this.elements.get(id);
4825
5181
  };
5182
+ DiagramModel.prototype.isElementVisible = function (id) {
5183
+ var element = this.elements.get(id);
5184
+ if (!element)
5185
+ return false;
5186
+ if (element.visible === false)
5187
+ return false;
5188
+ var currentParentId = element.parentId;
5189
+ while (currentParentId) {
5190
+ var parent_1 = this.elements.get(currentParentId);
5191
+ if (!parent_1)
5192
+ break;
5193
+ if (parent_1.visible === false)
5194
+ return false;
5195
+ currentParentId = parent_1.parentId;
5196
+ }
5197
+ return true;
5198
+ };
5199
+ DiagramModel.prototype.isElementSelectable = function (id) {
5200
+ var element = this.elements.get(id);
5201
+ if (!element)
5202
+ return false;
5203
+ return this.isElementVisible(id) && element.selectable !== false;
5204
+ };
4826
5205
  DiagramModel.prototype.setElementLayout = function (id, layout) {
4827
5206
  var element = this.elements.get(id);
4828
5207
  if (!element)
@@ -4841,6 +5220,12 @@ var DiagramModel = /** @class */ (function () {
4841
5220
  DiagramModel.prototype.getPort = function (id) {
4842
5221
  return this.ports.get(id);
4843
5222
  };
5223
+ DiagramModel.prototype.isPortVisible = function (id) {
5224
+ var port = this.ports.get(id);
5225
+ if (!port)
5226
+ return false;
5227
+ return this.isElementVisible(port.elementId);
5228
+ };
4844
5229
  DiagramModel.prototype.getPortWorldPosition = function (id) {
4845
5230
  var port = this.ports.get(id);
4846
5231
  if (!port)
@@ -4856,6 +5241,16 @@ var DiagramModel = /** @class */ (function () {
4856
5241
  DiagramModel.prototype.getLink = function (id) {
4857
5242
  return this.links.get(id);
4858
5243
  };
5244
+ DiagramModel.prototype.isLinkVisible = function (id) {
5245
+ var link = this.links.get(id);
5246
+ if (!link)
5247
+ return false;
5248
+ var sourcePort = this.ports.get(link.sourcePortId);
5249
+ var targetPort = this.ports.get(link.targetPortId);
5250
+ var sourceVisible = sourcePort ? this.isPortVisible(sourcePort.id) : true;
5251
+ var targetVisible = targetPort ? this.isPortVisible(targetPort.id) : true;
5252
+ return sourceVisible && targetVisible;
5253
+ };
4859
5254
  DiagramModel.prototype.getLinkMidpoint = function (id) {
4860
5255
  var link = this.links.get(id);
4861
5256
  if (!link)
@@ -4865,6 +5260,23 @@ var DiagramModel = /** @class */ (function () {
4865
5260
  DiagramModel.prototype.getText = function (id) {
4866
5261
  return this.texts.get(id);
4867
5262
  };
5263
+ DiagramModel.prototype.isTextVisible = function (id) {
5264
+ var text = this.texts.get(id);
5265
+ if (!text)
5266
+ return false;
5267
+ if (!text.ownerId)
5268
+ return true;
5269
+ if (this.elements.has(text.ownerId)) {
5270
+ return this.isElementVisible(text.ownerId);
5271
+ }
5272
+ if (this.ports.has(text.ownerId)) {
5273
+ return this.isPortVisible(text.ownerId);
5274
+ }
5275
+ if (this.links.has(text.ownerId)) {
5276
+ return this.isLinkVisible(text.ownerId);
5277
+ }
5278
+ return true;
5279
+ };
4868
5280
  DiagramModel.prototype.getTextWorldPosition = function (id) {
4869
5281
  var text = this.texts.get(id);
4870
5282
  if (!text)
@@ -5053,18 +5465,18 @@ var DiagramModel = /** @class */ (function () {
5053
5465
  }
5054
5466
  var current = element;
5055
5467
  while (current === null || current === void 0 ? void 0 : current.parentId) {
5056
- var parent_1 = this.elements.get(current.parentId);
5057
- if (!parent_1)
5468
+ var parent_2 = this.elements.get(current.parentId);
5469
+ if (!parent_2)
5058
5470
  break;
5059
- var parentX = parent_1.position.x;
5060
- var parentY = parent_1.position.y;
5061
- if (parent_1.anchorCenter) {
5062
- parentX -= parent_1.size.width / 2;
5063
- parentY -= parent_1.size.height / 2;
5471
+ var parentX = parent_2.position.x;
5472
+ var parentY = parent_2.position.y;
5473
+ if (parent_2.anchorCenter) {
5474
+ parentX -= parent_2.size.width / 2;
5475
+ parentY -= parent_2.size.height / 2;
5064
5476
  }
5065
5477
  x += parentX;
5066
5478
  y += parentY;
5067
- current = parent_1;
5479
+ current = parent_2;
5068
5480
  }
5069
5481
  return { x: x, y: y };
5070
5482
  };
@@ -6288,6 +6700,8 @@ var AutoLayoutService = /** @class */ (function () {
6288
6700
  return this.applyResolvedLayout(parentId, parent, desiredPositions, desiredSizes, {
6289
6701
  width: newParentWidth,
6290
6702
  height: newParentHeight,
6703
+ }, {
6704
+ preserveResizedLayoutParentSize: true,
6291
6705
  });
6292
6706
  };
6293
6707
  AutoLayoutService.prototype.resolveGridCellWidths = function (rowInnerWidth, weights) {
@@ -6297,7 +6711,7 @@ var AutoLayoutService = /** @class */ (function () {
6297
6711
  var safeWeights = weights.map(function (weight) { return _this.clampGridUnits(weight); });
6298
6712
  return this.distributeWeightedSizes(Math.max(0, rowInnerWidth), safeWeights);
6299
6713
  };
6300
- AutoLayoutService.prototype.applyResolvedLayout = function (parentId, parent, desiredPositions, desiredSizes, parentSize) {
6714
+ AutoLayoutService.prototype.applyResolvedLayout = function (parentId, parent, desiredPositions, desiredSizes, parentSize, options) {
6301
6715
  var _this = this;
6302
6716
  var _a;
6303
6717
  var patches = [];
@@ -6316,7 +6730,7 @@ var AutoLayoutService = /** @class */ (function () {
6316
6730
  var resizePatches = _this.commandQueue.run(createResizeElementCommand(childId, fittedSize), _this.model);
6317
6731
  patches.push.apply(patches, resizePatches);
6318
6732
  movedPortIds.push.apply(movedPortIds, _this.collectElementPortIds(childId));
6319
- var nested = _this.applyLayoutForParent(childId);
6733
+ var nested = _this.applyLayoutForParent(childId, (options === null || options === void 0 ? void 0 : options.preserveResizedLayoutParentSize) ? { preserveParentSize: true } : undefined);
6320
6734
  patches.push.apply(patches, nested.patches);
6321
6735
  movedPortIds.push.apply(movedPortIds, nested.movedPortIds);
6322
6736
  }
@@ -8177,16 +8591,38 @@ var DiagramEngine = /** @class */ (function () {
8177
8591
  this.emitEntityDeletionEvents(removal.removed);
8178
8592
  };
8179
8593
  DiagramEngine.prototype.setSelection = function (ids) {
8180
- this.selection.set(ids);
8594
+ this.selection.set(this.normalizeSelectionIds(ids));
8181
8595
  this.emitSelection();
8182
8596
  };
8183
8597
  DiagramEngine.prototype.toggleSelection = function (id) {
8184
- this.selection.toggle(id);
8598
+ var current = new Set(this.selection.get());
8599
+ if (current.has(id)) {
8600
+ current.delete(id);
8601
+ }
8602
+ else if (this.isSelectableId(id)) {
8603
+ current.add(id);
8604
+ }
8605
+ this.selection.set(Array.from(current));
8185
8606
  this.emitSelection();
8186
8607
  };
8187
8608
  DiagramEngine.prototype.getSelection = function () {
8188
8609
  return this.selection.get();
8189
8610
  };
8611
+ DiagramEngine.prototype.isElementVisible = function (id) {
8612
+ return this.model.isElementVisible(id);
8613
+ };
8614
+ DiagramEngine.prototype.isElementSelectable = function (id) {
8615
+ return this.model.isElementSelectable(id);
8616
+ };
8617
+ DiagramEngine.prototype.isPortVisible = function (id) {
8618
+ return this.model.isPortVisible(id);
8619
+ };
8620
+ DiagramEngine.prototype.isLinkVisible = function (id) {
8621
+ return this.model.isLinkVisible(id);
8622
+ };
8623
+ DiagramEngine.prototype.isTextVisible = function (id) {
8624
+ return this.model.isTextVisible(id);
8625
+ };
8190
8626
  DiagramEngine.prototype.getElementWorldPosition = function (id) {
8191
8627
  return this.model.getElementWorldPosition(id);
8192
8628
  };
@@ -8448,11 +8884,15 @@ var DiagramEngine = /** @class */ (function () {
8448
8884
  var _this = this;
8449
8885
  var _a;
8450
8886
  var allPatches = this.appendTextLayoutPatches(patches, (_a = options === null || options === void 0 ? void 0 : options.emitTextUpdated) !== null && _a !== void 0 ? _a : true);
8887
+ var selectionChanged = this.syncSelectionToPolicies();
8451
8888
  var state = this.model.toState();
8452
8889
  this.events.emit('change', { patches: allPatches, state: state });
8453
- if ((options === null || options === void 0 ? void 0 : options.render) === false)
8454
- return;
8455
- this.scheduler.requestRender(function () { return _this.renderer.render(_this.model); });
8890
+ if ((options === null || options === void 0 ? void 0 : options.render) !== false) {
8891
+ this.scheduler.requestRender(function () { return _this.renderer.render(_this.model); });
8892
+ }
8893
+ if (selectionChanged) {
8894
+ this.emitSelection();
8895
+ }
8456
8896
  };
8457
8897
  DiagramEngine.prototype.appendTextLayoutPatches = function (patches, emitTextUpdated) {
8458
8898
  var _this = this;
@@ -8898,6 +9338,31 @@ var DiagramEngine = /** @class */ (function () {
8898
9338
  });
8899
9339
  this.renderer.renderSelection(selectedIds);
8900
9340
  };
9341
+ DiagramEngine.prototype.normalizeSelectionIds = function (ids) {
9342
+ var _this = this;
9343
+ return ids.filter(function (id, index) { return ids.indexOf(id) === index && _this.isSelectableId(id); });
9344
+ };
9345
+ DiagramEngine.prototype.isSelectableId = function (id) {
9346
+ if (this.model.getElement(id))
9347
+ return this.model.isElementSelectable(id);
9348
+ if (this.model.getPort(id))
9349
+ return this.model.isPortVisible(id);
9350
+ if (this.model.getLink(id))
9351
+ return this.model.isLinkVisible(id);
9352
+ if (this.model.getText(id))
9353
+ return this.model.isTextVisible(id);
9354
+ return false;
9355
+ };
9356
+ DiagramEngine.prototype.syncSelectionToPolicies = function () {
9357
+ var current = this.selection.get();
9358
+ var normalized = this.normalizeSelectionIds(current);
9359
+ if (current.length === normalized.length &&
9360
+ current.every(function (id, index) { return id === normalized[index]; })) {
9361
+ return false;
9362
+ }
9363
+ this.selection.set(normalized);
9364
+ return true;
9365
+ };
8901
9366
  DiagramEngine.prototype.applyLayoutForParent = function (parentId, options) {
8902
9367
  return this.autoLayoutService.applyLayoutForParent(parentId, options);
8903
9368
  };
@@ -9815,7 +10280,9 @@ var KonvaRenderer = /** @class */ (function () {
9815
10280
  };
9816
10281
  KonvaRenderer.prototype.syncElements = function (model) {
9817
10282
  var _this = this;
9818
- var elements = Array.from(model.elements.values()).map(function (element, index) { return ({
10283
+ var elements = Array.from(model.elements.values())
10284
+ .filter(function (element) { return model.isElementVisible(element.id); })
10285
+ .map(function (element, index) { return ({
9819
10286
  element: element,
9820
10287
  depth: _this.getElementDepth(model, element),
9821
10288
  order: index,
@@ -9848,6 +10315,10 @@ var KonvaRenderer = /** @class */ (function () {
9848
10315
  node.setAttrs({ __depth: depth });
9849
10316
  }
9850
10317
  });
10318
+ var visibleElementIds = new Set(elements.map(function (_a) {
10319
+ var element = _a.element;
10320
+ return element.id;
10321
+ }));
9851
10322
  elements.forEach(function (_a) {
9852
10323
  var _b;
9853
10324
  var element = _a.element;
@@ -9856,7 +10327,7 @@ var KonvaRenderer = /** @class */ (function () {
9856
10327
  });
9857
10328
  Array.from(this.elementNodes.keys()).forEach(function (id) {
9858
10329
  var _a;
9859
- if (!model.elements.has(id)) {
10330
+ if (!visibleElementIds.has(id)) {
9860
10331
  var node = _this.elementNodes.get(id);
9861
10332
  (_a = node === null || node === void 0 ? void 0 : node.destroy) === null || _a === void 0 ? void 0 : _a.call(node);
9862
10333
  _this.elementNodes.delete(id);
@@ -9879,7 +10350,7 @@ var KonvaRenderer = /** @class */ (function () {
9879
10350
  };
9880
10351
  KonvaRenderer.prototype.syncPorts = function (model) {
9881
10352
  var _this = this;
9882
- var ports = Array.from(model.ports.values());
10353
+ var ports = Array.from(model.ports.values()).filter(function (port) { return model.isPortVisible(port.id); });
9883
10354
  ports.forEach(function (port) {
9884
10355
  var _a, _b, _c, _d, _e;
9885
10356
  var data = port.toData();
@@ -9897,9 +10368,10 @@ var KonvaRenderer = /** @class */ (function () {
9897
10368
  _this.updatePosition(node, position);
9898
10369
  _this.applyPortOrientation(node, data, position, model);
9899
10370
  });
10371
+ var visiblePortIds = new Set(ports.map(function (port) { return port.id; }));
9900
10372
  Array.from(this.portNodes.keys()).forEach(function (id) {
9901
10373
  var _a;
9902
- if (!model.ports.has(id)) {
10374
+ if (!visiblePortIds.has(id)) {
9903
10375
  var node = _this.portNodes.get(id);
9904
10376
  (_a = node === null || node === void 0 ? void 0 : node.destroy) === null || _a === void 0 ? void 0 : _a.call(node);
9905
10377
  _this.portNodes.delete(id);
@@ -9910,7 +10382,7 @@ var KonvaRenderer = /** @class */ (function () {
9910
10382
  };
9911
10383
  KonvaRenderer.prototype.syncLinks = function (model) {
9912
10384
  var _this = this;
9913
- var links = Array.from(model.links.values());
10385
+ var links = Array.from(model.links.values()).filter(function (link) { return model.isLinkVisible(link.id); });
9914
10386
  links.forEach(function (link) {
9915
10387
  var _a, _b;
9916
10388
  var node = _this.linkNodes.get(link.id);
@@ -9921,9 +10393,10 @@ var KonvaRenderer = /** @class */ (function () {
9921
10393
  }
9922
10394
  _this.updateLine(node, link.toData());
9923
10395
  });
10396
+ var visibleLinkIds = new Set(links.map(function (link) { return link.id; }));
9924
10397
  Array.from(this.linkNodes.keys()).forEach(function (id) {
9925
10398
  var _a;
9926
- if (!model.links.has(id)) {
10399
+ if (!visibleLinkIds.has(id)) {
9927
10400
  var node = _this.linkNodes.get(id);
9928
10401
  (_a = node === null || node === void 0 ? void 0 : node.destroy) === null || _a === void 0 ? void 0 : _a.call(node);
9929
10402
  _this.linkNodes.delete(id);
@@ -9934,7 +10407,7 @@ var KonvaRenderer = /** @class */ (function () {
9934
10407
  };
9935
10408
  KonvaRenderer.prototype.syncTexts = function (model) {
9936
10409
  var _this = this;
9937
- var texts = Array.from(model.texts.values());
10410
+ var texts = Array.from(model.texts.values()).filter(function (text) { return model.isTextVisible(text.id); });
9938
10411
  texts.forEach(function (text) {
9939
10412
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
9940
10413
  var node = _this.textNodes.get(text.id);
@@ -10023,9 +10496,10 @@ var KonvaRenderer = /** @class */ (function () {
10023
10496
  _this.textBackgroundNodes.delete(text.id);
10024
10497
  }
10025
10498
  });
10499
+ var visibleTextIds = new Set(texts.map(function (text) { return text.id; }));
10026
10500
  Array.from(this.textNodes.keys()).forEach(function (id) {
10027
10501
  var _a, _b;
10028
- if (!model.texts.has(id)) {
10502
+ if (!visibleTextIds.has(id)) {
10029
10503
  var backgroundNode = _this.textBackgroundNodes.get(id);
10030
10504
  (_a = backgroundNode === null || backgroundNode === void 0 ? void 0 : backgroundNode.destroy) === null || _a === void 0 ? void 0 : _a.call(backgroundNode);
10031
10505
  _this.textBackgroundNodes.delete(id);
@@ -11017,15 +11491,21 @@ var KonvaInteraction = /** @class */ (function () {
11017
11491
  KonvaInteraction.prototype.normalizeHit = function (hit) {
11018
11492
  if (!hit || hit.type === 'none')
11019
11493
  return null;
11020
- if (hit.type === 'port' ||
11021
- hit.type === 'link' ||
11022
- hit.type === 'text' ||
11023
- hit.type === 'resize-handle' ||
11494
+ if (hit.type === 'port') {
11495
+ return this.engine.isPortVisible(hit.id) ? hit : null;
11496
+ }
11497
+ if (hit.type === 'link') {
11498
+ return this.engine.isLinkVisible(hit.id) ? hit : null;
11499
+ }
11500
+ if (hit.type === 'text') {
11501
+ return this.engine.isTextVisible(hit.id) ? hit : null;
11502
+ }
11503
+ if (hit.type === 'resize-handle' ||
11024
11504
  hit.type === 'link-handle' ||
11025
11505
  hit.type === 'shape-hover-control') {
11026
11506
  return hit;
11027
11507
  }
11028
- return __assign(__assign({}, hit), { type: 'element' });
11508
+ return this.engine.isElementSelectable(hit.id) ? __assign(__assign({}, hit), { type: 'element' }) : null;
11029
11509
  };
11030
11510
  KonvaInteraction.prototype.resolveHit = function (point) {
11031
11511
  var _this = this;
@@ -11091,6 +11571,8 @@ var KonvaInteraction = /** @class */ (function () {
11091
11571
  var best = null;
11092
11572
  state.elements.forEach(function (element) {
11093
11573
  var _a, _b, _c;
11574
+ if (!_this.engine.isElementSelectable(element.id))
11575
+ return;
11094
11576
  var world = (_a = _this.engine.getElementWorldPosition(element.id)) !== null && _a !== void 0 ? _a : element.position;
11095
11577
  var rotation = _this.engine.getElementRotation(element.id);
11096
11578
  if (!pointInRotatedRect(point, world, element.size, rotation, (_b = element.anchorCenter) !== null && _b !== void 0 ? _b : false))
@@ -11120,6 +11602,8 @@ var KonvaInteraction = /** @class */ (function () {
11120
11602
  var bestDistance = Number.POSITIVE_INFINITY;
11121
11603
  links.forEach(function (link) {
11122
11604
  var _a, _b;
11605
+ if (!_this.engine.isLinkVisible(link.id))
11606
+ return;
11123
11607
  if (link.points.length < 2)
11124
11608
  return;
11125
11609
  var tolerance = ((_b = (_a = link.style) === null || _a === void 0 ? void 0 : _a.hitStrokeWidth) !== null && _b !== void 0 ? _b : 15) / 2;
@@ -12134,6 +12618,8 @@ var KonvaInteraction = /** @class */ (function () {
12134
12618
  };
12135
12619
  state.elements.forEach(function (element) {
12136
12620
  var _a, _b;
12621
+ if (!_this.engine.isElementSelectable(element.id))
12622
+ return;
12137
12623
  var position = (_a = _this.engine.getElementWorldPosition(element.id)) !== null && _a !== void 0 ? _a : element.position;
12138
12624
  var rotation = _this.engine.getElementRotation(element.id);
12139
12625
  var anchorCenter = (_b = element.anchorCenter) !== null && _b !== void 0 ? _b : false;
@@ -12151,6 +12637,8 @@ var KonvaInteraction = /** @class */ (function () {
12151
12637
  });
12152
12638
  state.ports.forEach(function (port) {
12153
12639
  var _a;
12640
+ if (!_this.engine.isPortVisible(port.id))
12641
+ return;
12154
12642
  var position = (_a = _this.engine.getPortWorldPosition(port.id)) !== null && _a !== void 0 ? _a : port.position;
12155
12643
  if (containsPoint(position)) {
12156
12644
  selected.add(port.id);
@@ -12158,6 +12646,8 @@ var KonvaInteraction = /** @class */ (function () {
12158
12646
  });
12159
12647
  state.texts.forEach(function (text) {
12160
12648
  var _a, _b, _c, _d, _e;
12649
+ if (!_this.engine.isTextVisible(text.id))
12650
+ return;
12161
12651
  var position = (_a = _this.engine.getTextWorldPosition(text.id)) !== null && _a !== void 0 ? _a : text.position;
12162
12652
  var width = (_c = (_b = text.size) === null || _b === void 0 ? void 0 : _b.width) !== null && _c !== void 0 ? _c : 0;
12163
12653
  var height = (_e = (_d = text.size) === null || _d === void 0 ? void 0 : _d.height) !== null && _e !== void 0 ? _e : 0;
@@ -12167,6 +12657,8 @@ var KonvaInteraction = /** @class */ (function () {
12167
12657
  }
12168
12658
  });
12169
12659
  state.links.forEach(function (link) {
12660
+ if (!_this.engine.isLinkVisible(link.id))
12661
+ return;
12170
12662
  if (link.points.length === 0)
12171
12663
  return;
12172
12664
  var xs = link.points.map(function (point) { return point.x; });
@@ -13098,13 +13590,65 @@ var resolveViewportFitOptions = function (options) {
13098
13590
  return { padding: padding, minZoom: minZoom, maxZoom: maxZoom };
13099
13591
  };
13100
13592
  var clamp = function (value, min, max) { return Math.max(min, Math.min(max, value)); };
13593
+ var isElementVisibleInState = function (elementId, elementsById) {
13594
+ var _a, _b;
13595
+ var element = elementsById.get(elementId);
13596
+ if (!element)
13597
+ return false;
13598
+ if (element.visible === false)
13599
+ return false;
13600
+ var currentParentId = (_a = element.parentId) !== null && _a !== void 0 ? _a : null;
13601
+ while (currentParentId) {
13602
+ var parent_1 = elementsById.get(currentParentId);
13603
+ if (!parent_1)
13604
+ break;
13605
+ if (parent_1.visible === false)
13606
+ return false;
13607
+ currentParentId = (_b = parent_1.parentId) !== null && _b !== void 0 ? _b : null;
13608
+ }
13609
+ return true;
13610
+ };
13611
+ var isPortVisibleInState = function (portId, portsById, elementsById) {
13612
+ var port = portsById.get(portId);
13613
+ if (!port)
13614
+ return false;
13615
+ return isElementVisibleInState(port.elementId, elementsById);
13616
+ };
13617
+ var isLinkVisibleInState = function (linkId, linksById, portsById, elementsById) {
13618
+ var link = linksById.get(linkId);
13619
+ if (!link)
13620
+ return false;
13621
+ var sourcePort = portsById.get(link.sourcePortId);
13622
+ var targetPort = portsById.get(link.targetPortId);
13623
+ var sourceVisible = sourcePort ? isPortVisibleInState(sourcePort.id, portsById, elementsById) : true;
13624
+ var targetVisible = targetPort ? isPortVisibleInState(targetPort.id, portsById, elementsById) : true;
13625
+ return sourceVisible && targetVisible;
13626
+ };
13627
+ var isTextVisibleInState = function (text, elementsById, portsById, linksById) {
13628
+ if (!text.ownerId)
13629
+ return true;
13630
+ if (elementsById.has(text.ownerId))
13631
+ return isElementVisibleInState(text.ownerId, elementsById);
13632
+ if (portsById.has(text.ownerId))
13633
+ return isPortVisibleInState(text.ownerId, portsById, elementsById);
13634
+ if (linksById.has(text.ownerId))
13635
+ return isLinkVisibleInState(text.ownerId, linksById, portsById, elementsById);
13636
+ return true;
13637
+ };
13101
13638
  var resolveStateWorldBounds = function (state) {
13102
13639
  var bounds = createBounds();
13640
+ var elementsById = new Map(state.elements.map(function (element) { return [element.id, element]; }));
13641
+ var portsById = new Map(state.ports.map(function (port) { return [port.id, port]; }));
13642
+ var linksById = new Map(state.links.map(function (link) { return [link.id, link]; }));
13103
13643
  state.elements.forEach(function (element) {
13644
+ if (!isElementVisibleInState(element.id, elementsById))
13645
+ return;
13104
13646
  includeRect(bounds, element.position.x, element.position.y, element.size.width, element.size.height);
13105
13647
  });
13106
13648
  state.ports.forEach(function (port) {
13107
13649
  var _a;
13650
+ if (!isPortVisibleInState(port.id, portsById, elementsById))
13651
+ return;
13108
13652
  var size = port.size;
13109
13653
  if (!size) {
13110
13654
  expandBounds(bounds, port.position.x, port.position.y);
@@ -13116,12 +13660,16 @@ var resolveStateWorldBounds = function (state) {
13116
13660
  includeRect(bounds, x, y, size.width, size.height);
13117
13661
  });
13118
13662
  state.links.forEach(function (link) {
13663
+ if (!isLinkVisibleInState(link.id, linksById, portsById, elementsById))
13664
+ return;
13119
13665
  link.points.forEach(function (point) {
13120
13666
  expandBounds(bounds, point.x, point.y);
13121
13667
  });
13122
13668
  });
13123
13669
  state.texts.forEach(function (text) {
13124
13670
  var _a;
13671
+ if (!isTextVisibleInState(text, elementsById, portsById, linksById))
13672
+ return;
13125
13673
  var offset = (_a = text.displayOffset) !== null && _a !== void 0 ? _a : { x: 0, y: 0 };
13126
13674
  var position = { x: text.position.x + offset.x, y: text.position.y + offset.y };
13127
13675
  var clipSize = text.displayClipSize;
@@ -13136,7 +13684,10 @@ var resolveStateWorldBounds = function (state) {
13136
13684
  };
13137
13685
  var resolveElementWorldBounds = function (state) {
13138
13686
  var bounds = createBounds();
13687
+ var elementsById = new Map(state.elements.map(function (element) { return [element.id, element]; }));
13139
13688
  state.elements.forEach(function (element) {
13689
+ if (!isElementVisibleInState(element.id, elementsById))
13690
+ return;
13140
13691
  includeRect(bounds, element.position.x, element.position.y, element.size.width, element.size.height);
13141
13692
  });
13142
13693
  return hasBounds(bounds) ? bounds : null;
@@ -13894,6 +14445,9 @@ var parentOptions = [
13894
14445
  { id: 'layout-grid', label: 'Grid layout' },
13895
14446
  { id: 'layout-nested', label: 'Nested layout' },
13896
14447
  { id: 'layout-grid-deep', label: 'Nested grid' },
14448
+ { id: 'layout-grid-empty-compare', label: 'Grid empty vs filled' },
14449
+ { id: 'layout-grid-mixed-modes', label: 'Grid mixed child modes' },
14450
+ { id: 'layout-column-grid-tree', label: 'Non-grid with grid descendants' },
13897
14451
  { id: 'layout-lock-compare', label: 'Child lock compare' },
13898
14452
  { id: 'layout-manual', label: 'Manual (compare)' },
13899
14453
  ];
@@ -14222,15 +14776,17 @@ var AutoLayoutDemo = function () {
14222
14776
  React.createElement("p", { style: { marginTop: 0 } }, "Try horizontal, vertical, grid, nested, and manual layout containers. Select a layout parent directly on the canvas or pick it from the list; the controls below always act on the current selection. Drag, resize, add, or remove children to see automatic reflow. Use fit controls, explicit child min/max constraints, auto-resize policy, 12-unit grid templates, and the optional grid child width-resize capability to validate current behavior."),
14223
14777
  React.createElement("p", { style: { marginTop: 0, fontSize: 13, color: '#333' } }, "Grid child width resize starts enabled for the seeded grid parents in this demo. With the capability on, horizontal drag can wrap rows automatically from a flat 12-unit slot array, resize direct grid children in 1/12 steps, and reorder peers by drag position. That now includes nested layout parents as well as leaf children. Turn the checkbox off on a selected grid parent to compare the older locked-width behavior where a mostly downward drag keeps width stable while height changes."),
14224
14778
  React.createElement("p", { style: { marginTop: 0, marginBottom: 0, fontSize: 13, color: '#333' } },
14225
- "The ",
14779
+ "The seeded scenarios now cover empty nested grids, mixed child layout modes under one grid owner, and grid descendants inside a non-grid tree. Use ",
14226
14780
  React.createElement("code", null, "layout-grid-deep"),
14227
- " scenario now keeps the outer container focused on grid behavior with three direct grid children, including one nested grid parent that also follows the enabled 12-unit resize path. The child drag lock comparison lives beside it in ",
14228
- React.createElement("code", null, " layout-lock-compare"),
14229
- "; toggle the lock, try dragging",
14230
- React.createElement("code", null, " deep-lock-child-a"),
14231
- " versus ",
14232
- React.createElement("code", null, " deep-free-child-a"),
14233
- ", then use the API move shortcut to confirm the policy suppresses built-in drag without freezing geometry.")),
14781
+ " for enabled 12-unit nested-child resize,",
14782
+ React.createElement("code", null, "layout-grid-empty-compare"),
14783
+ " for empty-versus-filled nested grid comparison, ",
14784
+ React.createElement("code", null, "layout-grid-mixed-modes"),
14785
+ "for direct-child layout mixing, and ",
14786
+ React.createElement("code", null, "layout-column-grid-tree"),
14787
+ " for a non-grid owner that still contains grid-layout descendants. The child drag lock comparison lives beside them in ",
14788
+ React.createElement("code", null, "layout-lock-compare"),
14789
+ ".")),
14234
14790
  React.createElement(DisplayBoxControls, { actions: demo.actions, snapEnabled: controls.snapEnabled, selectedLinkRouting: controls.selectedLinkRouting, canToggleLinkRouting: controls.canToggleLinkRouting, onReload: controls.handleReload, onZoomIn: controls.handleZoomIn, onZoomOut: controls.handleZoomOut, onResetViewport: controls.handleResetViewport, onToggleSnap: controls.handleToggleSnap, onManualRender: controls.handleManualRender, onToggleLinkRouting: controls.handleToggleLinkRouting, onAction: controls.handleAction, onExportImage: controls.handleExportImage, onClearExportPreview: controls.handleClearExportPreview, exportPreviewDataUrl: controls.exportPreviewDataUrl, exportError: controls.exportError }),
14235
14791
  React.createElement("div", { style: { display: 'grid', gap: 12, marginBottom: 12 } },
14236
14792
  React.createElement("div", { style: { display: 'flex', flexWrap: 'wrap', gap: 12, alignItems: 'center' } },
@@ -14346,6 +14902,9 @@ var AutoLayoutDemo = function () {
14346
14902
  React.createElement("ul", { style: { marginTop: 0, paddingLeft: 18, fontSize: 13 } },
14347
14903
  React.createElement("li", null, "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."),
14348
14904
  React.createElement("li", null, "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."),
14905
+ React.createElement("li", null, "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."),
14906
+ React.createElement("li", null, "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."),
14907
+ React.createElement("li", null, "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."),
14349
14908
  React.createElement("li", null, "Lock comparison: target layout-lock-compare, toggle Lock comparison child drag, then compare deep-lock-child-a and deep-free-child-a."),
14350
14909
  React.createElement("li", null, "Use Move lock target via API after locking; the child should still reposition because the policy only suppresses built-in drag."),
14351
14910
  React.createElement("li", null, "Resize lock: with grid child width resize off, select grid-b and drag diagonally; width should stay fixed."),
@@ -16280,6 +16839,12 @@ var demoTabs = [
16280
16839
  description: selectionDemoConfig.description,
16281
16840
  Component: wrapSimpleDemo(selectionDemoConfig),
16282
16841
  },
16842
+ {
16843
+ id: elementVisibilitySelectionDemoConfig.id,
16844
+ title: elementVisibilitySelectionDemoConfig.title,
16845
+ description: elementVisibilitySelectionDemoConfig.description,
16846
+ Component: wrapSimpleDemo(elementVisibilitySelectionDemoConfig),
16847
+ },
16283
16848
  {
16284
16849
  id: eventHandlersDemoConfig.id,
16285
16850
  title: eventHandlersDemoConfig.title,