orcasvn-react-diagrams 0.2.5 → 0.2.7

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 (58) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +12 -34
  3. package/ai/api-contract.json +45 -1
  4. package/ai/manifest.json +1 -1
  5. package/dist/cjs/examples.js +1724 -321
  6. package/dist/cjs/index.js +929 -108
  7. package/dist/cjs/types/api/createDiagramEditor.d.ts +2 -1
  8. package/dist/cjs/types/api/types.d.ts +30 -1
  9. package/dist/cjs/types/displaybox/demos/OffsetAnchorAvoidanceDemoTab.d.ts +3 -0
  10. package/dist/cjs/types/displaybox/demos/ZoomToFitElementsDemoTab.d.ts +3 -0
  11. package/dist/cjs/types/displaybox/demos/autoLayoutDemo.d.ts +2 -0
  12. package/dist/cjs/types/displaybox/demos/offsetAnchorAvoidanceDemo.d.ts +4 -0
  13. package/dist/cjs/types/displaybox/demos/textDemo.d.ts +3 -0
  14. package/dist/cjs/types/displaybox/demos/zoomToFitElementsDemo.d.ts +4 -0
  15. package/dist/cjs/types/engine/AutoLayoutService.d.ts +44 -1
  16. package/dist/cjs/types/engine/DiagramEngine.d.ts +14 -0
  17. package/dist/cjs/types/engine/LinkRoutingService.d.ts +1 -0
  18. package/dist/cjs/types/models/ElementModel.d.ts +1 -0
  19. package/dist/cjs/types/models/TextModel.d.ts +1 -0
  20. package/dist/cjs/types/renderer/konva/KonvaInteraction.d.ts +3 -2
  21. package/dist/esm/examples.js +1724 -321
  22. package/dist/esm/examples.js.map +1 -1
  23. package/dist/esm/index.js +929 -108
  24. package/dist/esm/index.js.map +1 -1
  25. package/dist/esm/types/api/createDiagramEditor.d.ts +2 -1
  26. package/dist/esm/types/api/types.d.ts +30 -1
  27. package/dist/esm/types/displaybox/demos/OffsetAnchorAvoidanceDemoTab.d.ts +3 -0
  28. package/dist/esm/types/displaybox/demos/ZoomToFitElementsDemoTab.d.ts +3 -0
  29. package/dist/esm/types/displaybox/demos/autoLayoutDemo.d.ts +2 -0
  30. package/dist/esm/types/displaybox/demos/offsetAnchorAvoidanceDemo.d.ts +4 -0
  31. package/dist/esm/types/displaybox/demos/textDemo.d.ts +3 -0
  32. package/dist/esm/types/displaybox/demos/zoomToFitElementsDemo.d.ts +4 -0
  33. package/dist/esm/types/engine/AutoLayoutService.d.ts +44 -1
  34. package/dist/esm/types/engine/DiagramEngine.d.ts +14 -0
  35. package/dist/esm/types/engine/LinkRoutingService.d.ts +1 -0
  36. package/dist/esm/types/models/ElementModel.d.ts +1 -0
  37. package/dist/esm/types/models/TextModel.d.ts +1 -0
  38. package/dist/esm/types/renderer/konva/KonvaInteraction.d.ts +3 -2
  39. package/dist/examples.d.ts +31 -1
  40. package/dist/index.d.ts +34 -2
  41. package/docs/API_CONTRACT.md +51 -5
  42. package/docs/CAPABILITIES.md +4 -0
  43. package/docs/COMMANDS_EVENTS.md +9 -0
  44. package/docs/DOCUMENTATION_WORKFLOW.md +3 -1
  45. package/docs/INTEGRATION_PLAYBOOK.md +4 -0
  46. package/docs/STATE_INVARIANTS.md +4 -0
  47. package/package.json +1 -1
  48. package/src/displaybox/demos/AutoLayoutDemoTab.tsx +426 -327
  49. package/src/displaybox/demos/EngineEventsDemoTab.tsx +12 -11
  50. package/src/displaybox/demos/OffsetAnchorAvoidanceDemoTab.tsx +30 -0
  51. package/src/displaybox/demos/TextLayoutDemoTab.tsx +18 -1
  52. package/src/displaybox/demos/ZoomToFitElementsDemoTab.tsx +29 -0
  53. package/src/displaybox/demos/autoLayoutDemo.ts +203 -83
  54. package/src/displaybox/demos/index.tsx +80 -64
  55. package/src/displaybox/demos/nestedDemo.ts +122 -69
  56. package/src/displaybox/demos/offsetAnchorAvoidanceDemo.ts +211 -0
  57. package/src/displaybox/demos/textDemo.ts +6 -2
  58. package/src/displaybox/demos/zoomToFitElementsDemo.ts +83 -0
@@ -180,7 +180,7 @@ var pathLength = function (points) {
180
180
  }
181
181
  return total;
182
182
  };
183
- var clamp$1 = function (value, min, max) { return Math.max(min, Math.min(max, value)); };
183
+ var clamp$2 = function (value, min, max) { return Math.max(min, Math.min(max, value)); };
184
184
  var ObstacleRouter = /** @class */ (function () {
185
185
  function ObstacleRouter(options) {
186
186
  var _a, _b, _c;
@@ -460,7 +460,7 @@ var ObstacleRouter = /** @class */ (function () {
460
460
  return null;
461
461
  if (corridor.axis === 'horizontal') {
462
462
  var direction_1 = source.x <= target.x ? 1 : -1;
463
- var corridorY = clamp$1((source.y + target.y) / 2, corridor.bounds.y + this.padding, corridor.bounds.y + corridor.bounds.height - this.padding);
463
+ var corridorY = clamp$2((source.y + target.y) / 2, corridor.bounds.y + this.padding, corridor.bounds.y + corridor.bounds.height - this.padding);
464
464
  var sourceExitX = direction_1 > 0
465
465
  ? corridor.sourceBranchRect.x + corridor.sourceBranchRect.width + this.padding
466
466
  : corridor.sourceBranchRect.x - this.padding;
@@ -477,7 +477,7 @@ var ObstacleRouter = /** @class */ (function () {
477
477
  ]);
478
478
  }
479
479
  var direction = source.y <= target.y ? 1 : -1;
480
- var corridorX = clamp$1((source.x + target.x) / 2, corridor.bounds.x + this.padding, corridor.bounds.x + corridor.bounds.width - this.padding);
480
+ var corridorX = clamp$2((source.x + target.x) / 2, corridor.bounds.x + this.padding, corridor.bounds.x + corridor.bounds.width - this.padding);
481
481
  var sourceExitY = direction > 0
482
482
  ? corridor.sourceBranchRect.y + corridor.sourceBranchRect.height + this.padding
483
483
  : corridor.sourceBranchRect.y - this.padding;
@@ -860,23 +860,44 @@ var linkPortCreationDemoConfig = ({
860
860
  var createNestedState = function () { return ({
861
861
  elements: [
862
862
  {
863
- id: 'parent-1',
864
- position: { x: 140, y: 140 },
865
- size: { width: 320, height: 240 },
863
+ id: 'parent-locked',
864
+ position: { x: 110, y: 140 },
865
+ size: { width: 300, height: 240 },
866
+ shapeId: 'panel',
867
+ childElementInteraction: { movable: false },
868
+ },
869
+ {
870
+ id: 'child-locked',
871
+ position: { x: 40, y: 60 },
872
+ size: { width: 160, height: 100 },
873
+ shapeId: 'default',
874
+ parentId: 'parent-locked',
875
+ },
876
+ {
877
+ id: 'parent-free',
878
+ position: { x: 470, y: 140 },
879
+ size: { width: 300, height: 240 },
866
880
  shapeId: 'panel',
867
881
  },
868
882
  {
869
- id: 'child-1',
883
+ id: 'child-free',
870
884
  position: { x: 40, y: 60 },
871
885
  size: { width: 160, height: 100 },
872
886
  shapeId: 'default',
873
- parentId: 'parent-1',
887
+ parentId: 'parent-free',
874
888
  },
875
889
  ],
876
890
  ports: [
877
891
  {
878
- id: 'child-port',
879
- elementId: 'child-1',
892
+ id: 'child-port-locked',
893
+ elementId: 'child-locked',
894
+ position: { x: 20, y: 20 },
895
+ shapeId: 'port-circle',
896
+ anchorCenter: true,
897
+ },
898
+ {
899
+ id: 'child-port-free',
900
+ elementId: 'child-free',
880
901
  position: { x: 20, y: 20 },
881
902
  shapeId: 'port-circle',
882
903
  anchorCenter: true,
@@ -885,28 +906,61 @@ var createNestedState = function () { return ({
885
906
  links: [],
886
907
  texts: [
887
908
  {
888
- id: 'child-label',
889
- content: 'Child',
890
- position: { x: 6, y: -16 },
891
- ownerId: 'child-1',
909
+ id: 'parent-locked-label',
910
+ content: 'Locked child drag',
911
+ position: { x: 12, y: 12 },
912
+ ownerId: 'parent-locked',
913
+ interaction: { movable: false, editable: false },
914
+ },
915
+ {
916
+ id: 'child-locked-label',
917
+ content: 'Drag disabled',
918
+ position: { x: 10, y: 10 },
919
+ ownerId: 'child-locked',
920
+ interaction: { movable: false, editable: false },
921
+ },
922
+ {
923
+ id: 'parent-free-label',
924
+ content: 'Movable child drag',
925
+ position: { x: 12, y: 12 },
926
+ ownerId: 'parent-free',
927
+ interaction: { movable: false, editable: false },
928
+ },
929
+ {
930
+ id: 'child-free-label',
931
+ content: 'Drag enabled',
932
+ position: { x: 10, y: 10 },
933
+ ownerId: 'child-free',
934
+ interaction: { movable: false, editable: false },
892
935
  },
893
936
  ],
894
937
  }); };
895
938
  var nestedDemoConfig = ({
896
939
  id: 'nested',
897
940
  title: 'Nested Elements',
898
- description: 'Parent/child elements with world positioning.',
941
+ description: 'Compare locked and movable child drag; locked children still move through API actions.',
899
942
  createState: createNestedState,
900
943
  elementShapes: baseElementShapes,
901
944
  portShapes: basePortShapes,
902
945
  defaultElementShapeId: 'default',
903
946
  defaultPortShapeId: 'port-circle',
904
947
  actions: [
948
+ {
949
+ id: 'move-locked-child-api',
950
+ label: 'Move locked child (API)',
951
+ run: function (editor, state) {
952
+ var child = state.elements.find(function (element) { return element.id === 'child-locked'; });
953
+ var parent = state.elements.find(function (element) { return element.id === 'parent-locked'; });
954
+ if (!child || !parent)
955
+ return;
956
+ editor.moveElementTo(child.id, parent.position.x + child.position.x + 30, parent.position.y + child.position.y + 10);
957
+ },
958
+ },
905
959
  {
906
960
  id: 'move-parent',
907
- label: 'Move parent',
961
+ label: 'Move locked parent',
908
962
  run: function (editor, state) {
909
- var parent = state.elements.find(function (element) { return element.id === 'parent-1'; });
963
+ var parent = state.elements.find(function (element) { return element.id === 'parent-locked'; });
910
964
  if (!parent)
911
965
  return;
912
966
  editor.moveElementTo(parent.id, parent.position.x + 40, parent.position.y + 20);
@@ -914,15 +968,15 @@ var nestedDemoConfig = ({
914
968
  },
915
969
  {
916
970
  id: 'add-child',
917
- label: 'Add child',
971
+ label: 'Add movable child',
918
972
  run: function (editor, state, demo, helpers) {
919
973
  var _a;
920
- var parent = state.elements.find(function (element) { return element.id === 'parent-1'; });
974
+ var parent = state.elements.find(function (element) { return element.id === 'parent-free'; });
921
975
  if (!parent)
922
976
  return;
923
977
  var offset = helpers.nextOffset();
924
978
  editor.addElement({
925
- id: "child-".concat(createId()),
979
+ id: "child-free-".concat(createId()),
926
980
  position: { x: 30 + offset, y: 50 + offset },
927
981
  size: { width: 140, height: 90 },
928
982
  shapeId: (_a = demo.defaultElementShapeId) !== null && _a !== void 0 ? _a : 'default',
@@ -992,6 +1046,8 @@ var textDemoOwnerId = 'text-layout-owner';
992
1046
  var textDemoOwnedTextId = 'text-owned-overflow';
993
1047
  var textDemoFloatingTextId = 'text-floating-overflow';
994
1048
  var textDemoLongSample = 'Long diagram label: middle ellipsis should keep the beginning and end visible while preserving the full canonical content in model state.';
1049
+ var textDemoOwnedInteraction = { movable: false, editable: false };
1050
+ var textDemoFloatingInteraction = { movable: true, editable: true };
995
1051
  var createTextOwnershipState = function () { return ({
996
1052
  elements: [
997
1053
  {
@@ -1009,6 +1065,7 @@ var createTextOwnershipState = function () { return ({
1009
1065
  content: textDemoLongSample,
1010
1066
  position: { x: 12, y: 12 },
1011
1067
  ownerId: textDemoOwnerId,
1068
+ interaction: textDemoOwnedInteraction,
1012
1069
  layout: {
1013
1070
  boundsMode: 'owner-width',
1014
1071
  wrap: 'none',
@@ -1020,6 +1077,7 @@ var createTextOwnershipState = function () { return ({
1020
1077
  id: textDemoFloatingTextId,
1021
1078
  content: textDemoLongSample,
1022
1079
  position: { x: 470, y: 120 },
1080
+ interaction: textDemoFloatingInteraction,
1023
1081
  layout: {
1024
1082
  boundsMode: 'fixed',
1025
1083
  fixedSize: { width: 240, height: 90 },
@@ -1034,7 +1092,7 @@ var createTextOwnershipState = function () { return ({
1034
1092
  var textDemoConfig = ({
1035
1093
  id: 'text',
1036
1094
  title: 'Text Layout + Overflow',
1037
- description: 'Owner-constrained and fixed-bounds text with wrap and ellipsis behavior. Full content is preserved in model state; truncation is visual-only.',
1095
+ description: 'Owner-constrained and fixed-bounds text with wrap, ellipsis, and per-text interaction behavior. Full content is preserved in model state; truncation is visual-only.',
1038
1096
  createState: createTextOwnershipState,
1039
1097
  elementShapes: baseElementShapes,
1040
1098
  portShapes: basePortShapes,
@@ -1237,146 +1295,266 @@ var linkCancelDemoConfig = ({
1237
1295
  actions: [],
1238
1296
  });
1239
1297
 
1240
- var createAutoLayoutState = function () { return ({
1241
- elements: [
1242
- {
1243
- id: 'layout-row',
1244
- position: { x: 60, y: 80 },
1245
- size: { width: 180, height: 96 },
1246
- shapeId: 'panel',
1247
- layout: { mode: 'horizontal', padding: { x: 14, y: 12 }, gap: 14, align: 'center' },
1248
- },
1249
- { id: 'row-a', position: { x: 0, y: 0 }, size: { width: 62, height: 44 }, shapeId: 'default', parentId: 'layout-row' },
1250
- { id: 'row-b', position: { x: 0, y: 0 }, size: { width: 96, height: 32 }, shapeId: 'default', parentId: 'layout-row' },
1251
- { id: 'row-c', position: { x: 0, y: 0 }, size: { width: 54, height: 56 }, shapeId: 'default', parentId: 'layout-row' },
1252
- {
1253
- id: 'row-nested-owner',
1254
- position: { x: 0, y: 0 },
1255
- size: { width: 82, height: 82 },
1256
- shapeId: 'default',
1257
- parentId: 'layout-row',
1258
- layout: { mode: 'vertical', padding: { x: 8, y: 6 }, gap: 6, align: 'start' },
1259
- },
1260
- { id: 'row-nested-child-a', position: { x: 0, y: 0 }, size: { width: 60, height: 20 }, shapeId: 'default', parentId: 'row-nested-owner' },
1261
- { id: 'row-nested-child-b', position: { x: 0, y: 0 }, size: { width: 76, height: 22 }, shapeId: 'default', parentId: 'row-nested-owner' },
1262
- {
1263
- id: 'layout-column',
1264
- position: { x: 400, y: 70 },
1265
- size: { width: 120, height: 140 },
1266
- shapeId: 'panel',
1267
- layout: { mode: 'vertical', padding: { x: 12, y: 10 }, gap: 16, align: 'end' },
1268
- },
1269
- { id: 'col-a', position: { x: 0, y: 0 }, size: { width: 44, height: 28 }, shapeId: 'default', parentId: 'layout-column' },
1270
- { id: 'col-b', position: { x: 0, y: 0 }, size: { width: 70, height: 36 }, shapeId: 'default', parentId: 'layout-column' },
1271
- { id: 'col-c', position: { x: 0, y: 0 }, size: { width: 92, height: 44 }, shapeId: 'default', parentId: 'layout-column' },
1272
- {
1273
- id: 'layout-grid',
1274
- position: { x: 620, y: 70 },
1275
- size: { width: 160, height: 110 },
1276
- shapeId: 'panel',
1277
- layout: {
1278
- mode: 'grid',
1279
- padding: { x: 10, y: 10 },
1280
- gap: 10,
1281
- align: 'center',
1282
- autoResize: 'grow-shrink',
1283
- gridTemplate: [[3], [1, 2]],
1284
- childMinWidth: 24,
1285
- childMinHeight: 18,
1298
+ var createAutoLayoutState = function (lockComparisonChildren) {
1299
+ if (lockComparisonChildren === void 0) { lockComparisonChildren = true; }
1300
+ return ({
1301
+ elements: [
1302
+ {
1303
+ id: 'layout-row',
1304
+ position: { x: 60, y: 80 },
1305
+ size: { width: 180, height: 96 },
1306
+ shapeId: 'panel',
1307
+ layout: { mode: 'horizontal', padding: { x: 14, y: 12 }, gap: 14, align: 'center' },
1286
1308
  },
1287
- },
1288
- { id: 'grid-a', position: { x: 0, y: 0 }, size: { width: 36, height: 26 }, shapeId: 'default', parentId: 'layout-grid' },
1289
- { id: 'grid-b', position: { x: 0, y: 0 }, size: { width: 44, height: 24 }, shapeId: 'default', parentId: 'layout-grid' },
1290
- { id: 'grid-c', position: { x: 0, y: 0 }, size: { width: 50, height: 20 }, shapeId: 'default', parentId: 'layout-grid' },
1291
- { id: 'grid-d', position: { x: 0, y: 0 }, size: { width: 28, height: 30 }, shapeId: 'default', parentId: 'layout-grid' },
1292
- { id: 'grid-e', position: { x: 0, y: 0 }, size: { width: 52, height: 28 }, shapeId: 'default', parentId: 'layout-grid' },
1293
- {
1294
- id: 'layout-nested',
1295
- position: { x: 120, y: 260 },
1296
- size: { width: 190, height: 130 },
1297
- shapeId: 'panel',
1298
- layout: { mode: 'horizontal', padding: { x: 12, y: 12 }, gap: 12, align: 'start' },
1299
- },
1300
- {
1301
- id: 'nested-stack',
1302
- position: { x: 0, y: 0 },
1303
- size: { width: 90, height: 92 },
1304
- shapeId: 'default',
1305
- parentId: 'layout-nested',
1306
- layout: { mode: 'vertical', padding: { x: 8, y: 8 }, gap: 8, align: 'center' },
1307
- },
1308
- { id: 'stack-a', position: { x: 0, y: 0 }, size: { width: 60, height: 24 }, shapeId: 'default', parentId: 'nested-stack' },
1309
- { id: 'stack-b', position: { x: 0, y: 0 }, size: { width: 90, height: 30 }, shapeId: 'default', parentId: 'nested-stack' },
1310
- {
1311
- id: 'stack-overflow',
1312
- position: { x: 0, y: 0 },
1313
- size: { width: 110, height: 26 },
1314
- shapeId: 'default',
1315
- parentId: 'nested-stack',
1316
- },
1317
- { id: 'nested-peer', position: { x: 0, y: 0 }, size: { width: 50, height: 90 }, shapeId: 'default', parentId: 'layout-nested' },
1318
- {
1319
- id: 'layout-manual',
1320
- position: { x: 420, y: 260 },
1321
- size: { width: 190, height: 120 },
1322
- shapeId: 'panel',
1323
- },
1324
- { id: 'manual-a', position: { x: 12, y: 18 }, size: { width: 60, height: 30 }, shapeId: 'default', parentId: 'layout-manual' },
1325
- { id: 'manual-b', position: { x: 90, y: 60 }, size: { width: 68, height: 32 }, shapeId: 'default', parentId: 'layout-manual' },
1326
- ],
1327
- ports: [],
1328
- links: [],
1329
- texts: [
1330
- {
1331
- id: 'label-layout-row',
1332
- content: 'Row parent label lane',
1333
- position: { x: 8, y: 6 },
1334
- ownerId: 'layout-row',
1335
- layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
1336
- },
1337
- { id: 'label-row-a', content: 'row-a', position: { x: 6, y: -14 }, ownerId: 'row-a' },
1338
- { id: 'label-row-b', content: 'row-b', position: { x: 6, y: -14 }, ownerId: 'row-b' },
1339
- { id: 'label-row-c', content: 'row-c', position: { x: 6, y: -14 }, ownerId: 'row-c' },
1340
- { id: 'label-row-nested-owner', content: 'owns children', position: { x: 6, y: -16 }, ownerId: 'row-nested-owner' },
1341
- {
1342
- id: 'label-layout-column',
1343
- content: 'Column parent label lane',
1344
- position: { x: 8, y: 6 },
1345
- ownerId: 'layout-column',
1346
- layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
1347
- },
1348
- { id: 'label-col-a', content: 'col-a', position: { x: 6, y: -14 }, ownerId: 'col-a' },
1349
- { id: 'label-col-b', content: 'col-b', position: { x: 6, y: -14 }, ownerId: 'col-b' },
1350
- { id: 'label-col-c', content: 'col-c', position: { x: 6, y: -14 }, ownerId: 'col-c' },
1351
- {
1352
- id: 'label-layout-grid',
1353
- content: 'Grid template [[3],[1,2]]',
1354
- position: { x: 8, y: 6 },
1355
- ownerId: 'layout-grid',
1356
- layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
1357
- },
1358
- { id: 'label-grid-a', content: 'grid-a', position: { x: 6, y: -14 }, ownerId: 'grid-a' },
1359
- { id: 'label-grid-b', content: 'grid-b', position: { x: 6, y: -14 }, ownerId: 'grid-b' },
1360
- { id: 'label-grid-c', content: 'grid-c', position: { x: 6, y: -14 }, ownerId: 'grid-c' },
1361
- { id: 'label-grid-d', content: 'grid-d', position: { x: 6, y: -14 }, ownerId: 'grid-d' },
1362
- { id: 'label-grid-e', content: 'grid-e', position: { x: 6, y: -14 }, ownerId: 'grid-e' },
1363
- {
1364
- id: 'label-layout-nested',
1365
- content: 'Row + nested column lane',
1366
- position: { x: 6, y: 6 },
1367
- ownerId: 'layout-nested',
1368
- layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
1369
- },
1370
- { id: 'label-nested-stack', content: 'nested stack', position: { x: 6, y: -16 }, ownerId: 'nested-stack' },
1371
- { id: 'label-stack-a', content: 'stack-a', position: { x: 6, y: -14 }, ownerId: 'stack-a' },
1372
- { id: 'label-stack-b', content: 'stack-b', position: { x: 6, y: -14 }, ownerId: 'stack-b' },
1373
- { id: 'label-stack-overflow', content: 'stack-overflow', position: { x: 6, y: -14 }, ownerId: 'stack-overflow' },
1374
- { id: 'label-nested-peer', content: 'nested-peer', position: { x: 6, y: -14 }, ownerId: 'nested-peer' },
1375
- { id: 'label-layout-manual', content: 'Manual (no layout)', position: { x: 6, y: -18 }, ownerId: 'layout-manual' },
1376
- { id: 'label-manual-a', content: 'manual-a', position: { x: 6, y: -14 }, ownerId: 'manual-a' },
1377
- { id: 'label-manual-b', content: 'manual-b', position: { x: 6, y: -14 }, ownerId: 'manual-b' },
1378
- ],
1379
- }); };
1309
+ { id: 'row-a', position: { x: 0, y: 0 }, size: { width: 62, height: 44 }, shapeId: 'default', parentId: 'layout-row' },
1310
+ { id: 'row-b', position: { x: 0, y: 0 }, size: { width: 96, height: 32 }, shapeId: 'default', parentId: 'layout-row' },
1311
+ { id: 'row-c', position: { x: 0, y: 0 }, size: { width: 54, height: 56 }, shapeId: 'default', parentId: 'layout-row' },
1312
+ {
1313
+ id: 'row-nested-owner',
1314
+ position: { x: 0, y: 0 },
1315
+ size: { width: 82, height: 82 },
1316
+ shapeId: 'default',
1317
+ parentId: 'layout-row',
1318
+ layout: { mode: 'vertical', padding: { x: 8, y: 6 }, gap: 6, align: 'start' },
1319
+ },
1320
+ { id: 'row-nested-child-a', position: { x: 0, y: 0 }, size: { width: 60, height: 20 }, shapeId: 'default', parentId: 'row-nested-owner' },
1321
+ { id: 'row-nested-child-b', position: { x: 0, y: 0 }, size: { width: 76, height: 22 }, shapeId: 'default', parentId: 'row-nested-owner' },
1322
+ {
1323
+ id: 'layout-column',
1324
+ position: { x: 400, y: 70 },
1325
+ size: { width: 120, height: 140 },
1326
+ shapeId: 'panel',
1327
+ layout: { mode: 'vertical', padding: { x: 12, y: 10 }, gap: 16, align: 'end' },
1328
+ },
1329
+ { id: 'col-a', position: { x: 0, y: 0 }, size: { width: 44, height: 28 }, shapeId: 'default', parentId: 'layout-column' },
1330
+ { id: 'col-b', position: { x: 0, y: 0 }, size: { width: 70, height: 36 }, shapeId: 'default', parentId: 'layout-column' },
1331
+ { id: 'col-c', position: { x: 0, y: 0 }, size: { width: 92, height: 44 }, shapeId: 'default', parentId: 'layout-column' },
1332
+ {
1333
+ id: 'layout-grid',
1334
+ position: { x: 620, y: 70 },
1335
+ size: { width: 160, height: 110 },
1336
+ shapeId: 'panel',
1337
+ layout: {
1338
+ mode: 'grid',
1339
+ padding: { x: 10, y: 10 },
1340
+ gap: 10,
1341
+ align: 'center',
1342
+ autoResize: 'grow-shrink',
1343
+ gridTemplate: [12, 4, 8],
1344
+ gridChildWidthResizeEnabled: true,
1345
+ childMinWidth: 24,
1346
+ childMinHeight: 18,
1347
+ },
1348
+ },
1349
+ { id: 'grid-a', position: { x: 0, y: 0 }, size: { width: 36, height: 26 }, shapeId: 'default', parentId: 'layout-grid' },
1350
+ { id: 'grid-b', position: { x: 0, y: 0 }, size: { width: 44, height: 24 }, shapeId: 'default', parentId: 'layout-grid' },
1351
+ { id: 'grid-c', position: { x: 0, y: 0 }, size: { width: 50, height: 20 }, shapeId: 'default', parentId: 'layout-grid' },
1352
+ { id: 'grid-d', position: { x: 0, y: 0 }, size: { width: 28, height: 30 }, shapeId: 'default', parentId: 'layout-grid' },
1353
+ { id: 'grid-e', position: { x: 0, y: 0 }, size: { width: 52, height: 28 }, shapeId: 'default', parentId: 'layout-grid' },
1354
+ {
1355
+ id: 'layout-nested',
1356
+ position: { x: 120, y: 260 },
1357
+ size: { width: 190, height: 130 },
1358
+ shapeId: 'panel',
1359
+ layout: { mode: 'horizontal', padding: { x: 12, y: 12 }, gap: 12, align: 'start' },
1360
+ },
1361
+ {
1362
+ id: 'nested-stack',
1363
+ position: { x: 0, y: 0 },
1364
+ size: { width: 90, height: 92 },
1365
+ shapeId: 'default',
1366
+ parentId: 'layout-nested',
1367
+ layout: { mode: 'vertical', padding: { x: 8, y: 8 }, gap: 8, align: 'center' },
1368
+ },
1369
+ { id: 'stack-a', position: { x: 0, y: 0 }, size: { width: 60, height: 24 }, shapeId: 'default', parentId: 'nested-stack' },
1370
+ { id: 'stack-b', position: { x: 0, y: 0 }, size: { width: 90, height: 30 }, shapeId: 'default', parentId: 'nested-stack' },
1371
+ {
1372
+ id: 'stack-overflow',
1373
+ position: { x: 0, y: 0 },
1374
+ size: { width: 110, height: 26 },
1375
+ shapeId: 'default',
1376
+ parentId: 'nested-stack',
1377
+ },
1378
+ { id: 'nested-peer', position: { x: 0, y: 0 }, size: { width: 50, height: 90 }, shapeId: 'default', parentId: 'layout-nested' },
1379
+ {
1380
+ id: 'layout-grid-deep',
1381
+ position: { x: 640, y: 250 },
1382
+ size: { width: 250, height: 180 },
1383
+ shapeId: 'panel',
1384
+ layout: {
1385
+ mode: 'grid',
1386
+ padding: { x: 12, y: 12 },
1387
+ gap: 12,
1388
+ align: 'center',
1389
+ autoResize: 'grow-shrink',
1390
+ gridTemplate: [4, 4, 4],
1391
+ gridChildWidthResizeEnabled: true,
1392
+ childMinWidth: 48,
1393
+ childMinHeight: 60,
1394
+ },
1395
+ },
1396
+ {
1397
+ id: 'deep-grid-leaf-left',
1398
+ position: { x: 0, y: 0 },
1399
+ size: { width: 58, height: 72 },
1400
+ shapeId: 'default',
1401
+ parentId: 'layout-grid-deep',
1402
+ },
1403
+ {
1404
+ id: 'deep-grid-nested-parent',
1405
+ position: { x: 0, y: 0 },
1406
+ size: { width: 108, height: 90 },
1407
+ shapeId: 'default',
1408
+ parentId: 'layout-grid-deep',
1409
+ layout: {
1410
+ mode: 'grid',
1411
+ padding: { x: 8, y: 8 },
1412
+ gap: 8,
1413
+ align: 'center',
1414
+ autoResize: 'grow-shrink',
1415
+ gridTemplate: [6, 6],
1416
+ gridChildWidthResizeEnabled: true,
1417
+ childMinWidth: 18,
1418
+ childMinHeight: 18,
1419
+ },
1420
+ },
1421
+ {
1422
+ id: 'deep-grid-leaf-right',
1423
+ position: { x: 0, y: 0 },
1424
+ size: { width: 52, height: 78 },
1425
+ shapeId: 'default',
1426
+ parentId: 'layout-grid-deep',
1427
+ },
1428
+ { id: 'deep-grid-a', position: { x: 0, y: 0 }, size: { width: 34, height: 24 }, shapeId: 'default', parentId: 'deep-grid-nested-parent' },
1429
+ { id: 'deep-grid-b', position: { x: 0, y: 0 }, size: { width: 40, height: 28 }, shapeId: 'default', parentId: 'deep-grid-nested-parent' },
1430
+ { id: 'deep-grid-c', position: { x: 0, y: 0 }, size: { width: 52, height: 24 }, shapeId: 'default', parentId: 'deep-grid-nested-parent' },
1431
+ { id: 'deep-grid-d', position: { x: 0, y: 0 }, size: { width: 28, height: 30 }, shapeId: 'default', parentId: 'deep-grid-nested-parent' },
1432
+ {
1433
+ id: 'layout-lock-compare',
1434
+ position: { x: 420, y: 410 },
1435
+ size: { width: 240, height: 160 },
1436
+ shapeId: 'panel',
1437
+ layout: { mode: 'horizontal', padding: { x: 12, y: 12 }, gap: 12, align: 'start' },
1438
+ },
1439
+ {
1440
+ id: 'deep-lock-parent',
1441
+ position: { x: 0, y: 0 },
1442
+ size: { width: 110, height: 92 },
1443
+ shapeId: 'default',
1444
+ parentId: 'layout-lock-compare',
1445
+ childElementInteraction: lockComparisonChildren ? { movable: false } : undefined,
1446
+ },
1447
+ { id: 'deep-lock-child-a', position: { x: 12, y: 24 }, size: { width: 38, height: 24 }, shapeId: 'default', parentId: 'deep-lock-parent' },
1448
+ { id: 'deep-lock-child-b', position: { x: 56, y: 54 }, size: { width: 42, height: 24 }, shapeId: 'default', parentId: 'deep-lock-parent' },
1449
+ {
1450
+ id: 'deep-free-parent',
1451
+ position: { x: 0, y: 0 },
1452
+ size: { width: 110, height: 92 },
1453
+ shapeId: 'default',
1454
+ parentId: 'layout-lock-compare',
1455
+ },
1456
+ { id: 'deep-free-child-a', position: { x: 12, y: 24 }, size: { width: 38, height: 24 }, shapeId: 'default', parentId: 'deep-free-parent' },
1457
+ { id: 'deep-free-child-b', position: { x: 56, y: 54 }, size: { width: 42, height: 24 }, shapeId: 'default', parentId: 'deep-free-parent' },
1458
+ {
1459
+ id: 'layout-manual',
1460
+ position: { x: 420, y: 260 },
1461
+ size: { width: 190, height: 120 },
1462
+ shapeId: 'panel',
1463
+ },
1464
+ { id: 'manual-a', position: { x: 12, y: 18 }, size: { width: 60, height: 30 }, shapeId: 'default', parentId: 'layout-manual' },
1465
+ { id: 'manual-b', position: { x: 90, y: 60 }, size: { width: 68, height: 32 }, shapeId: 'default', parentId: 'layout-manual' },
1466
+ ],
1467
+ ports: [],
1468
+ links: [],
1469
+ texts: [
1470
+ {
1471
+ id: 'label-layout-row',
1472
+ content: 'Row parent label lane',
1473
+ position: { x: 8, y: 6 },
1474
+ ownerId: 'layout-row',
1475
+ layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
1476
+ },
1477
+ { id: 'label-row-a', content: 'row-a', position: { x: 6, y: -14 }, ownerId: 'row-a' },
1478
+ { id: 'label-row-b', content: 'row-b', position: { x: 6, y: -14 }, ownerId: 'row-b' },
1479
+ { id: 'label-row-c', content: 'row-c', position: { x: 6, y: -14 }, ownerId: 'row-c' },
1480
+ { id: 'label-row-nested-owner', content: 'owns children', position: { x: 6, y: -16 }, ownerId: 'row-nested-owner' },
1481
+ {
1482
+ id: 'label-layout-column',
1483
+ content: 'Column parent label lane',
1484
+ position: { x: 8, y: 6 },
1485
+ ownerId: 'layout-column',
1486
+ layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
1487
+ },
1488
+ { id: 'label-col-a', content: 'col-a', position: { x: 6, y: -14 }, ownerId: 'col-a' },
1489
+ { id: 'label-col-b', content: 'col-b', position: { x: 6, y: -14 }, ownerId: 'col-b' },
1490
+ { id: 'label-col-c', content: 'col-c', position: { x: 6, y: -14 }, ownerId: 'col-c' },
1491
+ {
1492
+ id: 'label-layout-grid',
1493
+ content: 'Grid template [12,4,8]',
1494
+ position: { x: 8, y: 6 },
1495
+ ownerId: 'layout-grid',
1496
+ layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
1497
+ },
1498
+ { id: 'label-grid-a', content: 'grid-a', position: { x: 6, y: -14 }, ownerId: 'grid-a' },
1499
+ { id: 'label-grid-b', content: 'grid-b', position: { x: 6, y: -14 }, ownerId: 'grid-b' },
1500
+ { id: 'label-grid-c', content: 'grid-c', position: { x: 6, y: -14 }, ownerId: 'grid-c' },
1501
+ { id: 'label-grid-d', content: 'grid-d', position: { x: 6, y: -14 }, ownerId: 'grid-d' },
1502
+ { id: 'label-grid-e', content: 'grid-e', position: { x: 6, y: -14 }, ownerId: 'grid-e' },
1503
+ {
1504
+ id: 'label-layout-nested',
1505
+ content: 'Row + nested column lane',
1506
+ position: { x: 6, y: 6 },
1507
+ ownerId: 'layout-nested',
1508
+ layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
1509
+ },
1510
+ { id: 'label-nested-stack', content: 'nested stack', position: { x: 6, y: -16 }, ownerId: 'nested-stack' },
1511
+ { id: 'label-stack-a', content: 'stack-a', position: { x: 6, y: -14 }, ownerId: 'stack-a' },
1512
+ { id: 'label-stack-b', content: 'stack-b', position: { x: 6, y: -14 }, ownerId: 'stack-b' },
1513
+ { id: 'label-stack-overflow', content: 'stack-overflow', position: { x: 6, y: -14 }, ownerId: 'stack-overflow' },
1514
+ { id: 'label-nested-peer', content: 'nested-peer', position: { x: 6, y: -14 }, ownerId: 'nested-peer' },
1515
+ {
1516
+ id: 'label-layout-grid-deep',
1517
+ content: 'Outer grid: all direct children snap',
1518
+ position: { x: 8, y: 6 },
1519
+ ownerId: 'layout-grid-deep',
1520
+ layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
1521
+ },
1522
+ { id: 'label-deep-grid-leaf-left', content: 'leaf resize/reorder', position: { x: 6, y: -16 }, ownerId: 'deep-grid-leaf-left' },
1523
+ { id: 'label-deep-grid-nested-parent', content: 'nested grid 12-unit child', position: { x: 6, y: -16 }, ownerId: 'deep-grid-nested-parent' },
1524
+ { id: 'label-deep-grid-leaf-right', content: 'leaf resize/reorder', position: { x: 6, y: -16 }, ownerId: 'deep-grid-leaf-right' },
1525
+ { id: 'label-deep-grid-a', content: 'grid-a', position: { x: 6, y: -14 }, ownerId: 'deep-grid-a' },
1526
+ { id: 'label-deep-grid-b', content: 'grid-b', position: { x: 6, y: -14 }, ownerId: 'deep-grid-b' },
1527
+ { id: 'label-deep-grid-c', content: 'grid-c', position: { x: 6, y: -14 }, ownerId: 'deep-grid-c' },
1528
+ { id: 'label-deep-grid-d', content: 'grid-d', position: { x: 6, y: -14 }, ownerId: 'deep-grid-d' },
1529
+ {
1530
+ id: 'label-layout-lock-compare',
1531
+ content: 'Child drag lock comparison',
1532
+ position: { x: 8, y: 6 },
1533
+ ownerId: 'layout-lock-compare',
1534
+ layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
1535
+ },
1536
+ {
1537
+ id: 'label-deep-lock-parent',
1538
+ content: lockComparisonChildren ? 'parent lock: on' : 'parent lock: off',
1539
+ position: { x: 6, y: -16 },
1540
+ ownerId: 'deep-lock-parent',
1541
+ },
1542
+ {
1543
+ id: 'label-deep-lock-child-a',
1544
+ content: lockComparisonChildren ? 'drag target (locked)' : 'drag target (unlocked)',
1545
+ position: { x: 4, y: -14 },
1546
+ ownerId: 'deep-lock-child-a',
1547
+ },
1548
+ { id: 'label-deep-lock-child-b', content: 'api move still works', position: { x: 4, y: -14 }, ownerId: 'deep-lock-child-b' },
1549
+ { id: 'label-deep-free-parent', content: 'movable reference', position: { x: 6, y: -16 }, ownerId: 'deep-free-parent' },
1550
+ { id: 'label-deep-free-child-a', content: 'drag target', position: { x: 4, y: -14 }, ownerId: 'deep-free-child-a' },
1551
+ { id: 'label-deep-free-child-b', content: 'free sibling', position: { x: 4, y: -14 }, ownerId: 'deep-free-child-b' },
1552
+ { id: 'label-layout-manual', content: 'Manual (no layout)', position: { x: 6, y: -18 }, ownerId: 'layout-manual' },
1553
+ { id: 'label-manual-a', content: 'manual-a', position: { x: 6, y: -14 }, ownerId: 'manual-a' },
1554
+ { id: 'label-manual-b', content: 'manual-b', position: { x: 6, y: -14 }, ownerId: 'manual-b' },
1555
+ ],
1556
+ });
1557
+ };
1380
1558
  var autoLayoutDemoConfig = ({
1381
1559
  id: 'auto-layout',
1382
1560
  title: 'Element Auto-Layout + Label Lane',
@@ -3393,7 +3571,7 @@ var addLinksAction = {
3393
3571
  });
3394
3572
  },
3395
3573
  };
3396
- var rerouteAllAction = {
3574
+ var rerouteAllAction$1 = {
3397
3575
  id: 'reroute-links',
3398
3576
  label: 'Reroute All Links',
3399
3577
  run: function (editor) {
@@ -3409,7 +3587,7 @@ var obstacleRoutingDemoConfig = {
3409
3587
  portShapes: basePortShapes,
3410
3588
  defaultElementShapeId: 'default',
3411
3589
  defaultPortShapeId: 'port-circle',
3412
- actions: [addLinksAction, rerouteAllAction],
3590
+ actions: [addLinksAction, rerouteAllAction$1],
3413
3591
  };
3414
3592
 
3415
3593
  var createLinkBendHandlesState = function () { return ({
@@ -4208,6 +4386,7 @@ var ElementModel = /** @class */ (function () {
4208
4386
  this.moveMode = data.moveMode;
4209
4387
  this.anchorCenter = data.anchorCenter;
4210
4388
  this.layout = data.layout;
4389
+ this.childElementInteraction = data.childElementInteraction;
4211
4390
  this.portMovement = data.portMovement;
4212
4391
  }
4213
4392
  ElementModel.prototype.setPosition = function (position) {
@@ -4245,6 +4424,7 @@ var ElementModel = /** @class */ (function () {
4245
4424
  moveMode: this.moveMode,
4246
4425
  anchorCenter: this.anchorCenter,
4247
4426
  layout: this.layout,
4427
+ childElementInteraction: this.childElementInteraction,
4248
4428
  portMovement: this.portMovement,
4249
4429
  };
4250
4430
  };
@@ -4387,6 +4567,7 @@ var TextModel = /** @class */ (function () {
4387
4567
  this.size = data.size ? __assign({}, data.size) : undefined;
4388
4568
  this.style = data.style;
4389
4569
  this.ownerId = (_a = data.ownerId) !== null && _a !== void 0 ? _a : null;
4570
+ this.interaction = data.interaction ? __assign({}, data.interaction) : undefined;
4390
4571
  this.layout = data.layout ? __assign({}, data.layout) : undefined;
4391
4572
  this.displayContent = (_b = data.displayContent) !== null && _b !== void 0 ? _b : data.content;
4392
4573
  this.displayOffset = data.displayOffset ? __assign({}, data.displayOffset) : undefined;
@@ -4423,6 +4604,7 @@ var TextModel = /** @class */ (function () {
4423
4604
  size: this.size ? __assign({}, this.size) : undefined,
4424
4605
  style: this.style,
4425
4606
  ownerId: this.ownerId,
4607
+ interaction: this.interaction ? __assign({}, this.interaction) : undefined,
4426
4608
  layout: this.layout ? __assign({}, this.layout) : undefined,
4427
4609
  displayContent: (_a = this.displayContent) !== null && _a !== void 0 ? _a : this.content,
4428
4610
  displayOffset: this.displayOffset ? __assign({}, this.displayOffset) : undefined,
@@ -4437,7 +4619,7 @@ var distance = function (a, b) {
4437
4619
  var dy = a.y - b.y;
4438
4620
  return Math.sqrt(dx * dx + dy * dy);
4439
4621
  };
4440
- var clamp = function (value, min, max) {
4622
+ var clamp$1 = function (value, min, max) {
4441
4623
  if (value < min)
4442
4624
  return min;
4443
4625
  if (value > max)
@@ -5685,6 +5867,7 @@ var TextLayoutService = /** @class */ (function () {
5685
5867
  return TextLayoutService;
5686
5868
  }());
5687
5869
 
5870
+ var GRID_ROW_UNITS = 12;
5688
5871
  var AutoLayoutService = /** @class */ (function () {
5689
5872
  function AutoLayoutService(config) {
5690
5873
  this.model = config.model;
@@ -5699,11 +5882,24 @@ var AutoLayoutService = /** @class */ (function () {
5699
5882
  if (!layout || layout.mode === 'manual')
5700
5883
  return { patches: [], movedPortIds: [] };
5701
5884
  var preserveParentSize = Boolean(options === null || options === void 0 ? void 0 : options.preserveParentSize);
5885
+ var preserveParentWidth = preserveParentSize || Boolean(options === null || options === void 0 ? void 0 : options.preserveParentWidth);
5886
+ var preserveParentHeight = preserveParentSize || Boolean(options === null || options === void 0 ? void 0 : options.preserveParentHeight);
5702
5887
  var padding = this.resolveLayoutPadding(layout);
5703
5888
  var labelReservedTopLane = this.resolveLabelReservedTopLane(parentId, layout);
5704
5889
  var autoResize = this.resolveAutoResizeMode(layout);
5705
5890
  var children = this.model.getChildren(parentId);
5706
5891
  if (children.length === 0) {
5892
+ if (preserveParentWidth || preserveParentHeight) {
5893
+ var targetWidth_1 = preserveParentWidth ? parent.size.width : Math.max(0, Math.round(padding.x * 2));
5894
+ var targetHeight_1 = preserveParentHeight
5895
+ ? parent.size.height
5896
+ : Math.max(0, Math.round(padding.y * 2 + labelReservedTopLane));
5897
+ if (parent.size.width === targetWidth_1 && parent.size.height === targetHeight_1) {
5898
+ return { patches: [], movedPortIds: [] };
5899
+ }
5900
+ var resizePatches_1 = this.commandQueue.run(createResizeElementCommand(parentId, { width: targetWidth_1, height: targetHeight_1 }), this.model);
5901
+ return { patches: resizePatches_1, movedPortIds: __spreadArray([], parent.portIds, true) };
5902
+ }
5707
5903
  if (preserveParentSize) {
5708
5904
  return { patches: [], movedPortIds: [] };
5709
5905
  }
@@ -5718,9 +5914,17 @@ var AutoLayoutService = /** @class */ (function () {
5718
5914
  return { patches: resizePatches, movedPortIds: __spreadArray([], parent.portIds, true) };
5719
5915
  }
5720
5916
  if (layout.mode === 'grid') {
5721
- return this.applyGridLayoutForParent(parentId, parent, children, preserveParentSize);
5917
+ return this.applyGridLayoutForParent(parentId, parent, children, {
5918
+ preserveParentSize: preserveParentSize,
5919
+ preserveParentWidth: preserveParentWidth,
5920
+ preserveParentHeight: preserveParentHeight,
5921
+ });
5722
5922
  }
5723
- return this.applyAxisLayoutForParent(parentId, parent, children, layout.mode, preserveParentSize);
5923
+ return this.applyAxisLayoutForParent(parentId, parent, children, layout.mode, {
5924
+ preserveParentSize: preserveParentSize,
5925
+ preserveParentWidth: preserveParentWidth,
5926
+ preserveParentHeight: preserveParentHeight,
5927
+ });
5724
5928
  };
5725
5929
  AutoLayoutService.prototype.applyLayoutCascade = function (startParentId) {
5726
5930
  var _a;
@@ -5763,11 +5967,102 @@ var AutoLayoutService = /** @class */ (function () {
5763
5967
  });
5764
5968
  return { patches: patches, movedPortIds: Array.from(new Set(movedPortIds)) };
5765
5969
  };
5766
- AutoLayoutService.prototype.applyAxisLayoutForParent = function (parentId, parent, children, axis, preserveParentSize) {
5970
+ AutoLayoutService.prototype.describeGridRows = function (parentId) {
5971
+ var _a;
5972
+ var parent = this.model.getElement(parentId);
5973
+ if (!parent || ((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.mode) !== 'grid')
5974
+ return [];
5975
+ return this.resolveAssignedGridRows(parent).map(function (row) { return ({ childIds: __spreadArray([], row.childIds, true) }); });
5976
+ };
5977
+ AutoLayoutService.prototype.describeGridSlotState = function (parentId) {
5978
+ var _this = this;
5979
+ var _a;
5980
+ var parent = this.model.getElement(parentId);
5981
+ if (!parent || ((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.mode) !== 'grid')
5982
+ return null;
5983
+ var assignedRows = this.resolveAssignedGridRows(parent);
5984
+ return {
5985
+ orderedChildIds: assignedRows.flatMap(function (row) { return row.childIds; }),
5986
+ slotWeights: assignedRows.flatMap(function (row) { return row.weights.slice(0, row.childIds.length).map(function (weight) { return _this.clampGridUnits(weight); }); }),
5987
+ };
5988
+ };
5989
+ AutoLayoutService.prototype.resolveGridReorderedLayout = function (parentId, previousState) {
5990
+ var _this = this;
5991
+ var _a;
5992
+ var parent = this.model.getElement(parentId);
5993
+ if (!parent || ((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.mode) !== 'grid' || !parent.layout)
5994
+ return null;
5995
+ var sortedChildren = this.sortGridChildrenForLayout(this.model.getChildren(parentId));
5996
+ var orderedChildIds = sortedChildren.map(function (child) { return child.id; });
5997
+ if (orderedChildIds.length === previousState.orderedChildIds.length &&
5998
+ orderedChildIds.every(function (childId, index) { return childId === previousState.orderedChildIds[index]; })) {
5999
+ return null;
6000
+ }
6001
+ var weightByChildId = new Map();
6002
+ previousState.orderedChildIds.forEach(function (childId, index) {
6003
+ var _a;
6004
+ weightByChildId.set(childId, _this.clampGridUnits((_a = previousState.slotWeights[index]) !== null && _a !== void 0 ? _a : GRID_ROW_UNITS));
6005
+ });
6006
+ var reorderedTemplate = orderedChildIds.map(function (childId) { var _a; return (_a = weightByChildId.get(childId)) !== null && _a !== void 0 ? _a : GRID_ROW_UNITS; });
6007
+ return __assign(__assign({}, parent.layout), { gridTemplate: reorderedTemplate });
6008
+ };
6009
+ AutoLayoutService.prototype.resolveGridChildResizeTopologyChange = function (parentId, childId, requestedWidth) {
6010
+ var _a;
6011
+ var parent = this.model.getElement(parentId);
6012
+ if (!parent || ((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.mode) !== 'grid' || !parent.layout)
6013
+ return null;
6014
+ var slotState = this.resolveGridChildSlotState(parentId, childId);
6015
+ if (!slotState)
6016
+ return null;
6017
+ var assignedRows = slotState.assignedRows, orderedChildIds = slotState.orderedChildIds, slotWeights = slotState.slotWeights, childFlatIndex = slotState.childFlatIndex, rowIndex = slotState.rowIndex;
6018
+ var currentUnits = slotWeights[childFlatIndex];
6019
+ var requestedUnits = this.resolveRequestedGridUnits(parent, assignedRows[rowIndex], requestedWidth);
6020
+ if (requestedUnits === currentUnits)
6021
+ return null;
6022
+ var nextSlotWeights = __spreadArray([], slotWeights, true);
6023
+ nextSlotWeights[childFlatIndex] = requestedUnits;
6024
+ var nextRows = this.packGridRowsFromSlots(orderedChildIds, nextSlotWeights);
6025
+ var beforeRows = assignedRows.map(function (row) { return ({ childIds: __spreadArray([], row.childIds, true) }); });
6026
+ var afterRows = nextRows.map(function (row) { return ({ childIds: __spreadArray([], row.childIds, true) }); });
6027
+ var rowsChanged = !this.gridRowSnapshotsEqual(beforeRows, afterRows);
6028
+ var reason = requestedUnits < currentUnits && rowsChanged ? 'child-resize-split' : 'child-resize-redistribute';
6029
+ return {
6030
+ parentId: parentId,
6031
+ triggerChildId: childId,
6032
+ reason: reason,
6033
+ beforeRows: beforeRows,
6034
+ afterRows: afterRows,
6035
+ nextLayout: __assign(__assign({}, parent.layout), { gridTemplate: nextSlotWeights }),
6036
+ };
6037
+ };
6038
+ AutoLayoutService.prototype.snapGridChildRequestedWidth = function (parentId, childId, requestedWidth) {
6039
+ var _a, _b;
6040
+ var parent = this.model.getElement(parentId);
6041
+ if (!parent || ((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.mode) !== 'grid' || !parent.layout)
6042
+ return requestedWidth;
6043
+ var slotState = this.resolveGridChildSlotState(parentId, childId);
6044
+ if (!slotState)
6045
+ return requestedWidth;
6046
+ var requestedUnits = this.resolveRequestedGridUnits(parent, slotState.assignedRows[slotState.rowIndex], requestedWidth);
6047
+ var rowUnitWidth = this.resolveGridRowUnitWidth(Math.max(0, parent.size.width - this.resolveLayoutPadding(parent.layout).x * 2), slotState.assignedRows[slotState.rowIndex].childIds.length, (_b = parent.layout.gap) !== null && _b !== void 0 ? _b : 12);
6048
+ return Math.max(1, Math.round(requestedUnits * rowUnitWidth));
6049
+ };
6050
+ AutoLayoutService.prototype.canGridChildGrowRightward = function (parentId, childId) {
6051
+ var _a;
6052
+ var parent = this.model.getElement(parentId);
6053
+ if (!parent || ((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.mode) !== 'grid' || !parent.layout)
6054
+ return false;
6055
+ var orderedIds = this.resolveAssignedGridRows(parent).flatMap(function (row) { return row.childIds; });
6056
+ var childIndex = orderedIds.indexOf(childId);
6057
+ return childIndex >= 0 && childIndex < orderedIds.length - 1;
6058
+ };
6059
+ AutoLayoutService.prototype.applyAxisLayoutForParent = function (parentId, parent, children, axis, options) {
5767
6060
  var _a, _b;
5768
6061
  var _this = this;
5769
6062
  var _c, _d, _e, _f;
5770
- if (preserveParentSize === void 0) { preserveParentSize = false; }
6063
+ var preserveParentSize = Boolean(options === null || options === void 0 ? void 0 : options.preserveParentSize);
6064
+ var preserveParentWidth = preserveParentSize || Boolean(options === null || options === void 0 ? void 0 : options.preserveParentWidth);
6065
+ var preserveParentHeight = preserveParentSize || Boolean(options === null || options === void 0 ? void 0 : options.preserveParentHeight);
5771
6066
  var layout = parent.layout;
5772
6067
  var padding = this.resolveLayoutPadding(layout);
5773
6068
  var gap = (_c = layout === null || layout === void 0 ? void 0 : layout.gap) !== null && _c !== void 0 ? _c : 12;
@@ -5850,8 +6145,16 @@ var AutoLayoutService = /** @class */ (function () {
5850
6145
  }
5851
6146
  else {
5852
6147
  (_a = resolveParentSize(fittedSizes), newParentWidth = _a.width, newParentHeight = _a.height);
6148
+ if (preserveParentWidth)
6149
+ newParentWidth = preservedParentWidth;
6150
+ if (preserveParentHeight)
6151
+ newParentHeight = preservedParentHeight;
5853
6152
  fittedSizes = calculateFittedSizes(newParentWidth, newParentHeight);
5854
6153
  (_b = resolveParentSize(fittedSizes), newParentWidth = _b.width, newParentHeight = _b.height);
6154
+ if (preserveParentWidth)
6155
+ newParentWidth = preservedParentWidth;
6156
+ if (preserveParentHeight)
6157
+ newParentHeight = preservedParentHeight;
5855
6158
  }
5856
6159
  var availableWidth = Math.max(0, newParentWidth - padding.x * 2);
5857
6160
  var availableHeight = Math.max(0, newParentHeight - padding.y * 2 - labelReservedTopLane);
@@ -5886,10 +6189,12 @@ var AutoLayoutService = /** @class */ (function () {
5886
6189
  height: newParentHeight,
5887
6190
  });
5888
6191
  };
5889
- AutoLayoutService.prototype.applyGridLayoutForParent = function (parentId, parent, children, preserveParentSize) {
6192
+ AutoLayoutService.prototype.applyGridLayoutForParent = function (parentId, parent, children, options) {
5890
6193
  var _this = this;
5891
6194
  var _a, _b;
5892
- if (preserveParentSize === void 0) { preserveParentSize = false; }
6195
+ var preserveParentSize = Boolean(options === null || options === void 0 ? void 0 : options.preserveParentSize);
6196
+ var preserveParentWidth = preserveParentSize || Boolean(options === null || options === void 0 ? void 0 : options.preserveParentWidth);
6197
+ var preserveParentHeight = preserveParentSize || Boolean(options === null || options === void 0 ? void 0 : options.preserveParentHeight);
5893
6198
  var layout = parent.layout;
5894
6199
  var padding = this.resolveLayoutPadding(layout);
5895
6200
  var gap = (_a = layout === null || layout === void 0 ? void 0 : layout.gap) !== null && _a !== void 0 ? _a : 12;
@@ -5897,9 +6202,7 @@ var AutoLayoutService = /** @class */ (function () {
5897
6202
  var labelReservedTopLane = this.resolveLabelReservedTopLane(parentId, layout);
5898
6203
  var constraints = this.resolveChildSizeConstraints(layout);
5899
6204
  var autoResize = this.resolveAutoResizeMode(layout);
5900
- // Keep grid child ordering stable across resize/layout cycles.
5901
- // Grid slot assignment should not depend on transient child positions produced during drag.
5902
- var sorted = __spreadArray([], children, true);
6205
+ var sorted = this.sortGridChildrenForLayout(children);
5903
6206
  var templateRows = this.normalizeGridTemplate(layout === null || layout === void 0 ? void 0 : layout.gridTemplate);
5904
6207
  var assignedRows = this.assignChildrenToGridRows(sorted.map(function (child) { return child.id; }), templateRows);
5905
6208
  var rowMetrics = assignedRows.map(function (row) {
@@ -5914,20 +6217,33 @@ var AutoLayoutService = /** @class */ (function () {
5914
6217
  };
5915
6218
  });
5916
6219
  var rowHeight = clampedSizes.reduce(function (max, size) { return Math.max(max, size.height); }, 0);
5917
- var rowWidth = clampedSizes.reduce(function (sum, size) { return sum + size.width; }, 0) + Math.max(0, clampedSizes.length - 1) * gap;
6220
+ var totalGap = Math.max(0, clampedSizes.length - 1) * gap;
6221
+ var usedUnits = effectiveWeights.reduce(function (sum, weight) { return sum + _this.clampGridUnits(weight); }, 0);
6222
+ var requiredUnitWidth = effectiveWeights.reduce(function (max, weight, index) {
6223
+ var _a, _b;
6224
+ var slotUnits = Math.max(1, weight !== null && weight !== void 0 ? weight : 1);
6225
+ var width = (_b = (_a = clampedSizes[index]) === null || _a === void 0 ? void 0 : _a.width) !== null && _b !== void 0 ? _b : 0;
6226
+ return Math.max(max, width / slotUnits);
6227
+ }, 0);
6228
+ var rowWidth = usedUnits >= GRID_ROW_UNITS
6229
+ ? autoResize === 'grow-shrink'
6230
+ ? Math.round(requiredUnitWidth * GRID_ROW_UNITS) + totalGap
6231
+ : clampedSizes.reduce(function (sum, size) { return sum + size.width; }, 0) + totalGap
6232
+ : Math.round(requiredUnitWidth * Math.max(1, usedUnits)) + totalGap;
5918
6233
  return {
5919
6234
  row: row,
5920
6235
  rowHeight: rowHeight,
5921
6236
  rowWidth: rowWidth,
6237
+ usedUnits: usedUnits,
5922
6238
  effectiveWeights: effectiveWeights,
5923
6239
  };
5924
6240
  });
5925
6241
  var requiredInnerWidth = rowMetrics.reduce(function (max, metric) { return Math.max(max, metric.rowWidth); }, 0);
5926
6242
  var requiredInnerHeight = rowMetrics.reduce(function (sum, metric) { return sum + metric.rowHeight; }, 0) + Math.max(0, rowMetrics.length - 1) * gap;
5927
- var newParentWidth = preserveParentSize
6243
+ var newParentWidth = preserveParentWidth
5928
6244
  ? Math.max(0, Math.round(parent.size.width))
5929
6245
  : this.resolveAutoResizedDimension(parent.size.width, padding.x * 2 + requiredInnerWidth, autoResize);
5930
- var newParentHeight = preserveParentSize
6246
+ var newParentHeight = preserveParentHeight
5931
6247
  ? Math.max(0, Math.round(parent.size.height))
5932
6248
  : this.resolveAutoResizedDimension(parent.size.height, padding.y * 2 + labelReservedTopLane + requiredInnerHeight, autoResize);
5933
6249
  var availableWidth = Math.max(0, newParentWidth - padding.x * 2);
@@ -5946,8 +6262,11 @@ var AutoLayoutService = /** @class */ (function () {
5946
6262
  if (childCount <= 0)
5947
6263
  return;
5948
6264
  var totalGap = Math.max(0, childCount - 1) * gap;
5949
- var rowInnerWidth = Math.max(0, availableWidth - totalGap);
5950
- var cellWidths = _this.distributeWeightedSizes(rowInnerWidth, metric.effectiveWeights);
6265
+ var rowOuterWidth = metric.usedUnits >= GRID_ROW_UNITS
6266
+ ? availableWidth
6267
+ : Math.min(availableWidth, metric.rowWidth);
6268
+ var rowInnerWidth = Math.max(0, rowOuterWidth - totalGap);
6269
+ var cellWidths = _this.resolveGridCellWidths(rowInnerWidth, metric.effectiveWeights);
5951
6270
  var rowHeight = metric.rowHeight;
5952
6271
  var cursorX = padding.x;
5953
6272
  metric.row.childIds.forEach(function (childId, index) {
@@ -5971,6 +6290,13 @@ var AutoLayoutService = /** @class */ (function () {
5971
6290
  height: newParentHeight,
5972
6291
  });
5973
6292
  };
6293
+ AutoLayoutService.prototype.resolveGridCellWidths = function (rowInnerWidth, weights) {
6294
+ var _this = this;
6295
+ if (weights.length === 0)
6296
+ return [];
6297
+ var safeWeights = weights.map(function (weight) { return _this.clampGridUnits(weight); });
6298
+ return this.distributeWeightedSizes(Math.max(0, rowInnerWidth), safeWeights);
6299
+ };
5974
6300
  AutoLayoutService.prototype.applyResolvedLayout = function (parentId, parent, desiredPositions, desiredSizes, parentSize) {
5975
6301
  var _this = this;
5976
6302
  var _a;
@@ -6033,43 +6359,96 @@ var AutoLayoutService = /** @class */ (function () {
6033
6359
  : Number.POSITIVE_INFINITY;
6034
6360
  return { minWidth: minWidth, maxWidth: maxWidth, minHeight: minHeight, maxHeight: maxHeight };
6035
6361
  };
6362
+ AutoLayoutService.prototype.resolveAssignedGridRows = function (parent) {
6363
+ var _a;
6364
+ var children = this.model.getChildren(parent.id);
6365
+ var sorted = this.sortGridChildrenForLayout(children);
6366
+ var templateRows = this.normalizeGridTemplate((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.gridTemplate);
6367
+ return this.assignChildrenToGridRows(sorted.map(function (child) { return child.id; }), templateRows);
6368
+ };
6369
+ AutoLayoutService.prototype.repartitionAssignedGridRows = function (assignedRows, rowIndex, nextCurrentRowCount) {
6370
+ var _a, _b;
6371
+ var allChildIds = assignedRows.flatMap(function (row) { return row.childIds; });
6372
+ var prefixRows = assignedRows.slice(0, rowIndex).map(function (row) { return ({
6373
+ weights: __spreadArray([], row.weights.slice(0, row.childIds.length), true),
6374
+ childIds: __spreadArray([], row.childIds, true),
6375
+ }); });
6376
+ var prefixCount = prefixRows.reduce(function (sum, row) { return sum + row.childIds.length; }, 0);
6377
+ var nextRows = __spreadArray([], prefixRows, true);
6378
+ var currentChildIds = allChildIds.slice(prefixCount, prefixCount + nextCurrentRowCount);
6379
+ if (currentChildIds.length > 0) {
6380
+ nextRows.push({
6381
+ weights: this.fitGridRowWeights((_a = assignedRows[rowIndex]) === null || _a === void 0 ? void 0 : _a.weights, currentChildIds.length),
6382
+ childIds: currentChildIds,
6383
+ });
6384
+ }
6385
+ var cursor = prefixCount + currentChildIds.length;
6386
+ var trailingRowIndex = rowIndex + 1;
6387
+ while (cursor < allChildIds.length) {
6388
+ var sourceRow = assignedRows[Math.min(trailingRowIndex, assignedRows.length - 1)];
6389
+ var sourceCapacity = Math.max(1, (_b = sourceRow === null || sourceRow === void 0 ? void 0 : sourceRow.childIds.length) !== null && _b !== void 0 ? _b : 1);
6390
+ var rowChildIds = allChildIds.slice(cursor, cursor + sourceCapacity);
6391
+ nextRows.push({
6392
+ weights: this.fitGridRowWeights(sourceRow === null || sourceRow === void 0 ? void 0 : sourceRow.weights, rowChildIds.length),
6393
+ childIds: rowChildIds,
6394
+ });
6395
+ cursor += rowChildIds.length;
6396
+ trailingRowIndex += 1;
6397
+ }
6398
+ return nextRows;
6399
+ };
6400
+ AutoLayoutService.prototype.fitGridRowWeights = function (sourceWeights, childCount) {
6401
+ if (childCount <= 0)
6402
+ return [];
6403
+ var base = Array.isArray(sourceWeights) && sourceWeights.length > 0 ? sourceWeights : [1];
6404
+ var normalizedBase = this.normalizeRowWeightsToTwelveUnits(base);
6405
+ if (normalizedBase.length === childCount) {
6406
+ return normalizedBase;
6407
+ }
6408
+ if (normalizedBase.length > childCount) {
6409
+ return this.normalizeRowWeightsToTwelveUnits(normalizedBase.slice(0, childCount));
6410
+ }
6411
+ return this.buildEqualGridUnits(childCount);
6412
+ };
6413
+ AutoLayoutService.prototype.gridRowSnapshotsEqual = function (a, b) {
6414
+ var _a, _b, _c, _d;
6415
+ if (a.length !== b.length)
6416
+ return false;
6417
+ for (var index = 0; index < a.length; index += 1) {
6418
+ var left = (_b = (_a = a[index]) === null || _a === void 0 ? void 0 : _a.childIds) !== null && _b !== void 0 ? _b : [];
6419
+ var right = (_d = (_c = b[index]) === null || _c === void 0 ? void 0 : _c.childIds) !== null && _d !== void 0 ? _d : [];
6420
+ if (left.length !== right.length)
6421
+ return false;
6422
+ for (var childIndex = 0; childIndex < left.length; childIndex += 1) {
6423
+ if (left[childIndex] !== right[childIndex])
6424
+ return false;
6425
+ }
6426
+ }
6427
+ return true;
6428
+ };
6036
6429
  AutoLayoutService.prototype.normalizeGridTemplate = function (template) {
6430
+ var slots = this.normalizeGridSlotUnits(template);
6037
6431
  var rows = [];
6038
- (template !== null && template !== void 0 ? template : []).forEach(function (entry) {
6039
- if (typeof entry === 'number') {
6040
- var count = Math.max(0, Math.floor(entry));
6041
- if (count > 0) {
6042
- rows.push({ weights: Array.from({ length: count }, function () { return 1; }) });
6043
- }
6044
- return;
6045
- }
6046
- if (!Array.isArray(entry))
6047
- return;
6048
- if (entry.length === 1 && Number.isFinite(entry[0]) && entry[0] > 1) {
6049
- var count = Math.max(0, Math.floor(entry[0]));
6050
- if (count > 0) {
6051
- rows.push({ weights: Array.from({ length: count }, function () { return 1; }) });
6052
- }
6053
- return;
6054
- }
6055
- var weights = entry
6056
- .map(function (value) {
6057
- if (!Number.isFinite(value) || value <= 0)
6058
- return 1;
6059
- return value;
6060
- })
6061
- .filter(function (value) { return value > 0; });
6062
- if (weights.length > 0) {
6063
- rows.push({ weights: weights });
6432
+ var currentRow = [];
6433
+ var currentUnits = 0;
6434
+ slots.forEach(function (slotUnits) {
6435
+ if (currentRow.length > 0 && currentUnits + slotUnits > GRID_ROW_UNITS) {
6436
+ rows.push({ weights: __spreadArray([], currentRow, true) });
6437
+ currentRow = [];
6438
+ currentUnits = 0;
6064
6439
  }
6440
+ currentRow.push(slotUnits);
6441
+ currentUnits += slotUnits;
6065
6442
  });
6443
+ if (currentRow.length > 0) {
6444
+ rows.push({ weights: __spreadArray([], currentRow, true) });
6445
+ }
6066
6446
  if (rows.length === 0) {
6067
- rows.push({ weights: [1] });
6447
+ rows.push({ weights: [GRID_ROW_UNITS] });
6068
6448
  }
6069
6449
  return rows;
6070
6450
  };
6071
6451
  AutoLayoutService.prototype.assignChildrenToGridRows = function (childIds, templateRows) {
6072
- var _a;
6073
6452
  var assigned = [];
6074
6453
  var cursor = 0;
6075
6454
  templateRows.forEach(function (rowTemplate) {
@@ -6085,19 +6464,348 @@ var AutoLayoutService = /** @class */ (function () {
6085
6464
  cursor += rowChildren.length;
6086
6465
  });
6087
6466
  while (cursor < childIds.length) {
6088
- var remaining = childIds.length - cursor;
6089
- var lastRow = templateRows[templateRows.length - 1];
6090
- var fallbackColumns = (_a = lastRow === null || lastRow === void 0 ? void 0 : lastRow.weights.length) !== null && _a !== void 0 ? _a : 1;
6091
- var fallbackCount = Math.max(1, Math.min(remaining, fallbackColumns));
6092
- var rowChildren = childIds.slice(cursor, cursor + fallbackCount);
6467
+ var rowChildren = childIds.slice(cursor, cursor + 1);
6093
6468
  assigned.push({
6094
- weights: Array.from({ length: rowChildren.length }, function () { return 1; }),
6469
+ weights: [GRID_ROW_UNITS],
6095
6470
  childIds: rowChildren,
6096
6471
  });
6097
6472
  cursor += rowChildren.length;
6098
6473
  }
6099
6474
  return assigned;
6100
6475
  };
6476
+ AutoLayoutService.prototype.resolveGridChildSlotState = function (parentId, childId) {
6477
+ var _this = this;
6478
+ var _a;
6479
+ var parent = this.model.getElement(parentId);
6480
+ if (!parent || ((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.mode) !== 'grid')
6481
+ return null;
6482
+ var assignedRows = this.resolveAssignedGridRows(parent);
6483
+ if (assignedRows.length === 0)
6484
+ return null;
6485
+ var orderedChildIds = assignedRows.flatMap(function (row) { return row.childIds; });
6486
+ var slotWeights = assignedRows.flatMap(function (row) { return row.weights.slice(0, row.childIds.length).map(function (weight) { return _this.clampGridUnits(weight); }); });
6487
+ var childFlatIndex = orderedChildIds.indexOf(childId);
6488
+ if (childFlatIndex < 0)
6489
+ return null;
6490
+ var rowIndex = assignedRows.findIndex(function (row) { return row.childIds.includes(childId); });
6491
+ if (rowIndex < 0)
6492
+ return null;
6493
+ return { assignedRows: assignedRows, orderedChildIds: orderedChildIds, slotWeights: slotWeights, childFlatIndex: childFlatIndex, rowIndex: rowIndex };
6494
+ };
6495
+ AutoLayoutService.prototype.packGridRowsFromSlots = function (childIds, slotWeights) {
6496
+ var _this = this;
6497
+ var rows = [];
6498
+ var currentChildIds = [];
6499
+ var currentWeights = [];
6500
+ var currentUnits = 0;
6501
+ childIds.forEach(function (childId, index) {
6502
+ var _a;
6503
+ var slotUnits = _this.clampGridUnits((_a = slotWeights[index]) !== null && _a !== void 0 ? _a : GRID_ROW_UNITS);
6504
+ if (currentChildIds.length > 0 && currentUnits + slotUnits > GRID_ROW_UNITS) {
6505
+ rows.push({ childIds: __spreadArray([], currentChildIds, true), weights: __spreadArray([], currentWeights, true) });
6506
+ currentChildIds = [];
6507
+ currentWeights = [];
6508
+ currentUnits = 0;
6509
+ }
6510
+ currentChildIds.push(childId);
6511
+ currentWeights.push(slotUnits);
6512
+ currentUnits += slotUnits;
6513
+ });
6514
+ if (currentChildIds.length > 0) {
6515
+ rows.push({ childIds: __spreadArray([], currentChildIds, true), weights: __spreadArray([], currentWeights, true) });
6516
+ }
6517
+ return rows;
6518
+ };
6519
+ AutoLayoutService.prototype.resolveRequestedGridUnits = function (parent, currentRow, requestedWidth) {
6520
+ var _a;
6521
+ if (!parent.layout || parent.layout.mode !== 'grid' || !currentRow)
6522
+ return GRID_ROW_UNITS;
6523
+ var rowUnitWidth = this.resolveGridRowUnitWidth(Math.max(0, parent.size.width - this.resolveLayoutPadding(parent.layout).x * 2), currentRow.childIds.length, (_a = parent.layout.gap) !== null && _a !== void 0 ? _a : 12);
6524
+ if (rowUnitWidth <= 0)
6525
+ return GRID_ROW_UNITS;
6526
+ return this.clampGridUnits(Math.round(requestedWidth / rowUnitWidth));
6527
+ };
6528
+ AutoLayoutService.prototype.sortGridChildrenForLayout = function (children) {
6529
+ return __spreadArray([], children, true).sort(function (a, b) {
6530
+ if (a.position.y === b.position.y) {
6531
+ if (a.position.x === b.position.x)
6532
+ return a.id.localeCompare(b.id);
6533
+ return a.position.x - b.position.x;
6534
+ }
6535
+ return a.position.y - b.position.y;
6536
+ });
6537
+ };
6538
+ AutoLayoutService.prototype.resolveRightwardGridOverflowChange = function (params) {
6539
+ var _a, _b;
6540
+ var assignedRows = params.assignedRows, rowIndex = params.rowIndex, childIndex = params.childIndex, requestedWidth = params.requestedWidth, availableWidth = params.availableWidth, gap = params.gap, parentLayout = params.parentLayout, parentId = params.parentId, childId = params.childId;
6541
+ var currentRow = assignedRows[rowIndex];
6542
+ if (!currentRow || childIndex < 0 || childIndex >= currentRow.childIds.length - 1)
6543
+ return null;
6544
+ var rowUnitWidth = this.resolveGridRowUnitWidth(availableWidth, currentRow.childIds.length, gap);
6545
+ if (rowUnitWidth <= 0)
6546
+ return null;
6547
+ var currentUnits = (_b = (_a = currentRow.weights[childIndex]) !== null && _a !== void 0 ? _a : this.normalizeRowWeightsToTwelveUnits(currentRow.weights)[childIndex]) !== null && _b !== void 0 ? _b : 1;
6548
+ var requestedUnits = this.clampLayoutSize(Math.round(requestedWidth / rowUnitWidth), currentUnits + 1, GRID_ROW_UNITS - 1);
6549
+ var leftWeights = currentRow.weights.slice(0, childIndex);
6550
+ var leftSum = leftWeights.reduce(function (sum, value) { return sum + value; }, 0);
6551
+ var rightWeights = currentRow.weights.slice(childIndex + 1);
6552
+ var rightIds = currentRow.childIds.slice(childIndex + 1);
6553
+ var followingRows = assignedRows.slice(rowIndex + 1);
6554
+ for (var retainCount = rightIds.length - 1; retainCount >= 0; retainCount -= 1) {
6555
+ var maxTargetUnits = GRID_ROW_UNITS - leftSum - retainCount;
6556
+ if (requestedUnits > maxTargetUnits)
6557
+ continue;
6558
+ var retainedIds = rightIds.slice(0, retainCount);
6559
+ var retainedWeights = rightWeights.slice(0, retainCount);
6560
+ var overflowIds = __spreadArray(__spreadArray([], rightIds.slice(retainCount), true), followingRows.flatMap(function (row) { return row.childIds; }), true);
6561
+ var remainingUnits = GRID_ROW_UNITS - leftSum - requestedUnits;
6562
+ var nextCurrentWeights = __spreadArray(__spreadArray(__spreadArray([], leftWeights, true), [
6563
+ requestedUnits
6564
+ ], false), this.distributeUnitsWithMinimums(remainingUnits, retainedWeights), true);
6565
+ var nextRows = assignedRows.slice(0, rowIndex).map(function (row) { return ({
6566
+ weights: __spreadArray([], row.weights, true),
6567
+ childIds: __spreadArray([], row.childIds, true),
6568
+ }); });
6569
+ nextRows.push({
6570
+ weights: nextCurrentWeights,
6571
+ childIds: __spreadArray(__spreadArray([], currentRow.childIds.slice(0, childIndex + 1), true), retainedIds, true),
6572
+ });
6573
+ var trailingRows = this.reflowTrailingGridRows(overflowIds, followingRows, currentRow.weights.length);
6574
+ var allRows = __spreadArray(__spreadArray([], nextRows, true), trailingRows, true);
6575
+ var beforeRows = assignedRows.map(function (row) { return ({ childIds: __spreadArray([], row.childIds, true) }); });
6576
+ var afterRows = allRows.map(function (row) { return ({ childIds: __spreadArray([], row.childIds, true) }); });
6577
+ if (this.gridRowSnapshotsEqual(beforeRows, afterRows) && this.gridWeightsEqual(assignedRows, allRows)) {
6578
+ return null;
6579
+ }
6580
+ return {
6581
+ parentId: parentId,
6582
+ triggerChildId: childId,
6583
+ reason: 'child-resize-redistribute',
6584
+ beforeRows: beforeRows,
6585
+ afterRows: afterRows,
6586
+ nextLayout: __assign(__assign({}, parentLayout), { gridTemplate: this.flattenAssignedRowsToGridTemplate(allRows) }),
6587
+ };
6588
+ }
6589
+ return null;
6590
+ };
6591
+ AutoLayoutService.prototype.resolveSameRowGridUnitResizeChange = function (params) {
6592
+ var _this = this;
6593
+ var _a, _b, _c, _d;
6594
+ var assignedRows = params.assignedRows, rowIndex = params.rowIndex, childIndex = params.childIndex, requestedWidth = params.requestedWidth, availableWidth = params.availableWidth, gap = params.gap, parentLayout = params.parentLayout, parentId = params.parentId, childId = params.childId;
6595
+ var currentRow = assignedRows[rowIndex];
6596
+ if (!currentRow || currentRow.childIds.length <= 1)
6597
+ return null;
6598
+ var donorIndices = Array.from({ length: Math.max(0, currentRow.childIds.length - childIndex - 1) }, function (_, index) { return childIndex + 1 + index; });
6599
+ if (donorIndices.length === 0)
6600
+ return null;
6601
+ var rowUnitWidth = this.resolveGridRowUnitWidth(availableWidth, currentRow.childIds.length, gap);
6602
+ if (rowUnitWidth <= 0)
6603
+ return null;
6604
+ var currentUnits = (_b = (_a = currentRow.weights[childIndex]) !== null && _a !== void 0 ? _a : this.normalizeRowWeightsToTwelveUnits(currentRow.weights)[childIndex]) !== null && _b !== void 0 ? _b : 1;
6605
+ var requestedUnits = this.clampLayoutSize(Math.round(requestedWidth / rowUnitWidth), 1, GRID_ROW_UNITS - 1);
6606
+ if (requestedUnits === currentUnits)
6607
+ return null;
6608
+ var nextWeights = __spreadArray([], currentRow.weights, true);
6609
+ var delta = requestedUnits - currentUnits;
6610
+ if (delta > 0) {
6611
+ for (var _i = 0, donorIndices_1 = donorIndices; _i < donorIndices_1.length; _i++) {
6612
+ var donorIndex = donorIndices_1[_i];
6613
+ if (delta <= 0)
6614
+ break;
6615
+ var donorCapacity = Math.max(0, ((_c = nextWeights[donorIndex]) !== null && _c !== void 0 ? _c : 1) - 1);
6616
+ var transfer = Math.min(delta, donorCapacity);
6617
+ nextWeights[donorIndex] -= transfer;
6618
+ nextWeights[childIndex] += transfer;
6619
+ delta -= transfer;
6620
+ }
6621
+ }
6622
+ else {
6623
+ var release = Math.abs(delta);
6624
+ for (var _e = 0, donorIndices_2 = donorIndices; _e < donorIndices_2.length; _e++) {
6625
+ var donorIndex = donorIndices_2[_e];
6626
+ if (release <= 0)
6627
+ break;
6628
+ var transfer = release;
6629
+ nextWeights[donorIndex] += transfer;
6630
+ nextWeights[childIndex] -= transfer;
6631
+ release -= transfer;
6632
+ }
6633
+ }
6634
+ if (delta > 0)
6635
+ return null;
6636
+ if (((_d = nextWeights[childIndex]) !== null && _d !== void 0 ? _d : currentUnits) === currentUnits)
6637
+ return null;
6638
+ var nextRows = assignedRows.map(function (row, index) {
6639
+ return index === rowIndex
6640
+ ? {
6641
+ weights: _this.normalizeRowWeightsToTwelveUnits(nextWeights),
6642
+ childIds: __spreadArray([], row.childIds, true),
6643
+ }
6644
+ : { weights: __spreadArray([], row.weights, true), childIds: __spreadArray([], row.childIds, true) };
6645
+ });
6646
+ return {
6647
+ parentId: parentId,
6648
+ triggerChildId: childId,
6649
+ reason: 'child-resize-redistribute',
6650
+ beforeRows: assignedRows.map(function (row) { return ({ childIds: __spreadArray([], row.childIds, true) }); }),
6651
+ afterRows: nextRows.map(function (row) { return ({ childIds: __spreadArray([], row.childIds, true) }); }),
6652
+ nextLayout: __assign(__assign({}, parentLayout), { gridTemplate: this.flattenAssignedRowsToGridTemplate(nextRows) }),
6653
+ };
6654
+ };
6655
+ AutoLayoutService.prototype.splitGridRowIntoTwelveUnits = function (assignedRows, rowIndex, childId, requestedWidth, availableWidth, gap) {
6656
+ var _a;
6657
+ var currentRow = assignedRows[rowIndex];
6658
+ var nextRow = assignedRows[rowIndex + 1];
6659
+ if (!currentRow || !nextRow || currentRow.childIds.length !== 1 || nextRow.childIds.length === 0) {
6660
+ return [];
6661
+ }
6662
+ var rowUnitWidth = this.resolveGridRowUnitWidth(availableWidth, 2, gap);
6663
+ var requestedUnits = this.clampLayoutSize(Math.round(requestedWidth / rowUnitWidth), 1, GRID_ROW_UNITS - 1);
6664
+ var nextRows = assignedRows.slice(0, rowIndex).map(function (row) { return ({
6665
+ weights: __spreadArray([], row.weights, true),
6666
+ childIds: __spreadArray([], row.childIds, true),
6667
+ }); });
6668
+ nextRows.push({
6669
+ weights: [requestedUnits, GRID_ROW_UNITS - requestedUnits],
6670
+ childIds: [childId, nextRow.childIds[0]],
6671
+ });
6672
+ var trailingRows = [];
6673
+ var remainingChildIds = __spreadArray(__spreadArray([], nextRow.childIds.slice(1), true), assignedRows.slice(rowIndex + 2).flatMap(function (row) { return row.childIds; }), true);
6674
+ var cursor = 0;
6675
+ var seedRows = assignedRows.slice(rowIndex + 1);
6676
+ var seedIndex = 0;
6677
+ while (cursor < remainingChildIds.length) {
6678
+ var seed = seedRows[Math.min(seedIndex, seedRows.length - 1)];
6679
+ var capacity = Math.max(1, (_a = seed === null || seed === void 0 ? void 0 : seed.childIds.length) !== null && _a !== void 0 ? _a : 1);
6680
+ var rowChildIds = remainingChildIds.slice(cursor, cursor + capacity);
6681
+ trailingRows.push({
6682
+ weights: this.fitGridRowWeights(seed === null || seed === void 0 ? void 0 : seed.weights, rowChildIds.length),
6683
+ childIds: rowChildIds,
6684
+ });
6685
+ cursor += rowChildIds.length;
6686
+ seedIndex += 1;
6687
+ }
6688
+ return __spreadArray(__spreadArray([], nextRows, true), trailingRows, true);
6689
+ };
6690
+ AutoLayoutService.prototype.reflowTrailingGridRows = function (childIds, seedRows, fallbackColumnCount) {
6691
+ var _a;
6692
+ if (childIds.length === 0)
6693
+ return [];
6694
+ var trailingRows = [];
6695
+ var cursor = 0;
6696
+ var seedIndex = 0;
6697
+ var normalizedSeedRows = seedRows.length > 0 ? seedRows : [{ weights: this.buildEqualGridUnits(Math.max(1, fallbackColumnCount)), childIds: [] }];
6698
+ while (cursor < childIds.length) {
6699
+ var seed = normalizedSeedRows[Math.min(seedIndex, normalizedSeedRows.length - 1)];
6700
+ var capacity = Math.max(1, (_a = seed === null || seed === void 0 ? void 0 : seed.weights.length) !== null && _a !== void 0 ? _a : fallbackColumnCount);
6701
+ var rowChildIds = childIds.slice(cursor, cursor + capacity);
6702
+ trailingRows.push({
6703
+ weights: this.fitGridRowWeights(seed === null || seed === void 0 ? void 0 : seed.weights, rowChildIds.length),
6704
+ childIds: rowChildIds,
6705
+ });
6706
+ cursor += rowChildIds.length;
6707
+ seedIndex += 1;
6708
+ }
6709
+ return trailingRows;
6710
+ };
6711
+ AutoLayoutService.prototype.flattenAssignedRowsToGridTemplate = function (rows) {
6712
+ var _this = this;
6713
+ return rows.flatMap(function (row) { return _this.normalizeRowWeightsToTwelveUnits(row.weights.slice(0, row.childIds.length)); });
6714
+ };
6715
+ AutoLayoutService.prototype.buildEqualGridUnits = function (count) {
6716
+ if (count <= 0)
6717
+ return [];
6718
+ var base = Math.floor(GRID_ROW_UNITS / count);
6719
+ var remainder = GRID_ROW_UNITS - base * count;
6720
+ return Array.from({ length: count }, function (_, index) { return base + (index < remainder ? 1 : 0); });
6721
+ };
6722
+ AutoLayoutService.prototype.normalizeRowWeightsToTwelveUnits = function (weights) {
6723
+ var safeWeights = weights.map(function (weight) { return (Number.isFinite(weight) && weight > 0 ? weight : 1); });
6724
+ if (safeWeights.length === 0)
6725
+ return [GRID_ROW_UNITS];
6726
+ if (safeWeights.length === 1)
6727
+ return [GRID_ROW_UNITS];
6728
+ var distributed = this.distributeWeightedSizes(GRID_ROW_UNITS, safeWeights);
6729
+ var normalized = distributed.map(function (value) { return Math.max(1, value); });
6730
+ var total = normalized.reduce(function (sum, value) { return sum + value; }, 0);
6731
+ if (total === GRID_ROW_UNITS)
6732
+ return normalized;
6733
+ if (total < GRID_ROW_UNITS) {
6734
+ var cursor_1 = 0;
6735
+ while (total < GRID_ROW_UNITS) {
6736
+ normalized[cursor_1 % normalized.length] += 1;
6737
+ total += 1;
6738
+ cursor_1 += 1;
6739
+ }
6740
+ return normalized;
6741
+ }
6742
+ var cursor = normalized.length - 1;
6743
+ while (total > GRID_ROW_UNITS && cursor >= 0) {
6744
+ if (normalized[cursor] > 1) {
6745
+ normalized[cursor] -= 1;
6746
+ total -= 1;
6747
+ }
6748
+ else {
6749
+ cursor -= 1;
6750
+ }
6751
+ if (cursor < 0 && total > GRID_ROW_UNITS) {
6752
+ cursor = normalized.length - 1;
6753
+ }
6754
+ }
6755
+ return normalized;
6756
+ };
6757
+ AutoLayoutService.prototype.normalizeGridSlotUnits = function (template) {
6758
+ var _this = this;
6759
+ var slots = [];
6760
+ (template !== null && template !== void 0 ? template : []).forEach(function (entry) {
6761
+ if (typeof entry === 'number') {
6762
+ if (Number.isFinite(entry) && entry > 0) {
6763
+ slots.push(_this.clampGridUnits(entry));
6764
+ }
6765
+ return;
6766
+ }
6767
+ if (!Array.isArray(entry))
6768
+ return;
6769
+ entry.forEach(function (value) {
6770
+ if (Number.isFinite(value) && value > 0) {
6771
+ slots.push(_this.clampGridUnits(value));
6772
+ }
6773
+ });
6774
+ });
6775
+ return slots;
6776
+ };
6777
+ AutoLayoutService.prototype.clampGridUnits = function (value) {
6778
+ return Math.max(1, Math.min(GRID_ROW_UNITS, Math.round(value)));
6779
+ };
6780
+ AutoLayoutService.prototype.distributeUnitsWithMinimums = function (totalUnits, seedWeights) {
6781
+ if (seedWeights.length === 0)
6782
+ return [];
6783
+ var minimumTotal = seedWeights.length;
6784
+ var clampedTotal = Math.max(minimumTotal, totalUnits);
6785
+ var distributed = this.distributeWeightedSizes(clampedTotal - minimumTotal, seedWeights).map(function (value) { return value + 1; });
6786
+ return distributed;
6787
+ };
6788
+ AutoLayoutService.prototype.gridWeightsEqual = function (leftRows, rightRows) {
6789
+ var _a, _b, _c, _d;
6790
+ if (leftRows.length !== rightRows.length)
6791
+ return false;
6792
+ for (var rowIndex = 0; rowIndex < leftRows.length; rowIndex += 1) {
6793
+ var left = (_b = (_a = leftRows[rowIndex]) === null || _a === void 0 ? void 0 : _a.weights) !== null && _b !== void 0 ? _b : [];
6794
+ var right = (_d = (_c = rightRows[rowIndex]) === null || _c === void 0 ? void 0 : _c.weights) !== null && _d !== void 0 ? _d : [];
6795
+ if (left.length !== right.length)
6796
+ return false;
6797
+ for (var index = 0; index < left.length; index += 1) {
6798
+ if (left[index] !== right[index])
6799
+ return false;
6800
+ }
6801
+ }
6802
+ return true;
6803
+ };
6804
+ AutoLayoutService.prototype.resolveGridRowUnitWidth = function (availableWidth, childCount, gap) {
6805
+ var totalGap = Math.max(0, childCount - 1) * gap;
6806
+ var rowInnerWidth = Math.max(0, availableWidth - totalGap);
6807
+ return rowInnerWidth / GRID_ROW_UNITS;
6808
+ };
6101
6809
  AutoLayoutService.prototype.resolveLabelReservedTopLane = function (parentId, layout) {
6102
6810
  var _a, _b, _c, _d;
6103
6811
  var policy = layout === null || layout === void 0 ? void 0 : layout.labelReservedSpace;
@@ -6632,11 +7340,18 @@ var LinkRoutingService = /** @class */ (function () {
6632
7340
  var onEdge = (shape === null || shape === void 0 ? void 0 : shape.projectToBorder)
6633
7341
  ? this.isPointOnProjectedBorder(point, rect, shape.projectToBorder, EDGE_TOLERANCE)
6634
7342
  : this.isPointOnRectEdge(point, rect, EDGE_TOLERANCE);
6635
- var onEdgeSide = onEdge ? (_b = (_a = shape === null || shape === void 0 ? void 0 : shape.resolveBorderSide) === null || _a === void 0 ? void 0 : _a.call(shape, point, rect)) !== null && _b !== void 0 ? _b : this.resolveEdgeSide(point, rect) : undefined;
7343
+ var projectedBorderPoint = (shape === null || shape === void 0 ? void 0 : shape.projectToBorder)
7344
+ ? shape.projectToBorder(point, rect)
7345
+ : projectPointToBoundary(point, rect, 'rect');
7346
+ var projectedBoundaryEquivalent = !onEdge && !this.isPointInsideRect(point, rect, EDGE_TOLERANCE);
7347
+ var sidePoint = projectedBoundaryEquivalent ? projectedBorderPoint : point;
7348
+ var onEdgeSide = onEdge || projectedBoundaryEquivalent
7349
+ ? (_b = (_a = shape === null || shape === void 0 ? void 0 : shape.resolveBorderSide) === null || _a === void 0 ? void 0 : _a.call(shape, sidePoint, rect)) !== null && _b !== void 0 ? _b : this.resolveEdgeSide(sidePoint, rect)
7350
+ : undefined;
6636
7351
  if (onEdgeSide && oppositePoint) {
6637
7352
  onEdgeSide = this.resolveCornerTieBreakSide(point, rect, oppositePoint, onEdgeSide);
6638
7353
  }
6639
- return { onEdge: onEdge, onEdgeSide: onEdgeSide };
7354
+ return { onEdge: onEdge || projectedBoundaryEquivalent, onEdgeSide: onEdgeSide };
6640
7355
  };
6641
7356
  LinkRoutingService.prototype.resolveCornerTieBreakSide = function (point, rect, oppositePoint, currentSide) {
6642
7357
  var onLeft = Math.abs(point.x - rect.x) <= EDGE_TOLERANCE;
@@ -6798,6 +7513,12 @@ var LinkRoutingService = /** @class */ (function () {
6798
7513
  var onBottom = Math.abs(point.y - (rect.y + rect.height)) <= tolerance;
6799
7514
  return onLeft || onRight || onTop || onBottom;
6800
7515
  };
7516
+ LinkRoutingService.prototype.isPointInsideRect = function (point, rect, tolerance) {
7517
+ return (point.x >= rect.x - tolerance &&
7518
+ point.x <= rect.x + rect.width + tolerance &&
7519
+ point.y >= rect.y - tolerance &&
7520
+ point.y <= rect.y + rect.height + tolerance);
7521
+ };
6801
7522
  LinkRoutingService.prototype.resolveEdgeSide = function (point, rect) {
6802
7523
  var distances = [
6803
7524
  { side: 'left', value: Math.abs(point.x - rect.x) },
@@ -6842,8 +7563,8 @@ var MutationPipeline = /** @class */ (function () {
6842
7563
  }());
6843
7564
 
6844
7565
  var clampToRect = function (point, rect) { return ({
6845
- x: clamp(point.x, rect.x, rect.x + rect.width),
6846
- y: clamp(point.y, rect.y, rect.y + rect.height),
7566
+ x: clamp$1(point.x, rect.x, rect.x + rect.width),
7567
+ y: clamp$1(point.y, rect.y, rect.y + rect.height),
6847
7568
  }); };
6848
7569
  var snapToRectBorder = function (point, rect) {
6849
7570
  var clamped = clampToRect(point, rect);
@@ -6980,9 +7701,7 @@ var DiagramEngine = /** @class */ (function () {
6980
7701
  });
6981
7702
  this.emitChange(allPatches);
6982
7703
  };
6983
- DiagramEngine.prototype.moveElementTo = function (id, x, y) {
6984
- var _this = this;
6985
- var oldWorld = this.model.getElementWorldPosition(id);
7704
+ DiagramEngine.prototype.resolveElementMovePosition = function (id, x, y) {
6986
7705
  var snapped = this.snapper.snap({ x: x, y: y });
6987
7706
  var element = this.model.getElement(id);
6988
7707
  var position = snapped;
@@ -7022,14 +7741,46 @@ var DiagramEngine = /** @class */ (function () {
7022
7741
  }
7023
7742
  }
7024
7743
  }
7744
+ return { element: element === null || element === void 0 ? void 0 : element.toData(), position: position };
7745
+ };
7746
+ DiagramEngine.prototype.buildChildMutationLayoutSteps = function (parentId, options) {
7747
+ var _this = this;
7748
+ var _a;
7749
+ if (!parentId) {
7750
+ return [function () { return _this.applyLayoutCascade(null); }];
7751
+ }
7752
+ var parent = this.model.getElement(parentId);
7753
+ if ((options === null || options === void 0 ? void 0 : options.preserveGridParentWidth) && ((_a = parent === null || parent === void 0 ? void 0 : parent.layout) === null || _a === void 0 ? void 0 : _a.mode) === 'grid') {
7754
+ return [
7755
+ function () { return _this.applyLayoutForParent(parentId, { preserveParentWidth: true }); },
7756
+ function () { var _a; return _this.applyLayoutCascade((_a = parent.parentId) !== null && _a !== void 0 ? _a : null); },
7757
+ ];
7758
+ }
7759
+ return [function () { return _this.applyLayoutCascade(parentId); }];
7760
+ };
7761
+ DiagramEngine.prototype.moveElementTo = function (id, x, y) {
7762
+ var _a;
7763
+ var oldWorld = this.model.getElementWorldPosition(id);
7764
+ var _b = this.resolveElementMovePosition(id, x, y), element = _b.element, position = _b.position;
7765
+ var beforeGridSlotState = (element === null || element === void 0 ? void 0 : element.parentId)
7766
+ ? this.autoLayoutService.describeGridSlotState(element.parentId)
7767
+ : null;
7025
7768
  var patches = this.commandQueue.run(createMoveElementCommand(id, position), this.model);
7769
+ if ((element === null || element === void 0 ? void 0 : element.parentId) && beforeGridSlotState) {
7770
+ var reorderedLayout = this.autoLayoutService.resolveGridReorderedLayout(element.parentId, beforeGridSlotState);
7771
+ if (reorderedLayout) {
7772
+ patches.push.apply(patches, this.commandQueue.run(createSetElementLayoutCommand(element.parentId, reorderedLayout), this.model));
7773
+ }
7774
+ }
7026
7775
  var movedPortIds = [];
7027
7776
  if (element) {
7028
7777
  movedPortIds.push.apply(movedPortIds, this.collectElementPortIds(element.id));
7029
7778
  }
7030
7779
  var allPatches = this.mutationPipeline.run({
7031
7780
  basePatches: patches,
7032
- layoutSteps: [function () { var _a; return _this.applyLayoutCascade((_a = element === null || element === void 0 ? void 0 : element.parentId) !== null && _a !== void 0 ? _a : null); }],
7781
+ layoutSteps: this.buildChildMutationLayoutSteps((_a = element === null || element === void 0 ? void 0 : element.parentId) !== null && _a !== void 0 ? _a : null, {
7782
+ preserveGridParentWidth: true,
7783
+ }),
7033
7784
  movedPortIds: movedPortIds,
7034
7785
  });
7035
7786
  this.emitChange(allPatches);
@@ -7046,24 +7797,106 @@ var DiagramEngine = /** @class */ (function () {
7046
7797
  }
7047
7798
  }
7048
7799
  };
7800
+ DiagramEngine.prototype.resizeElementBounds = function (id, bounds) {
7801
+ var _this = this;
7802
+ var _a, _b, _c, _d;
7803
+ var _e = this.resolveElementMovePosition(id, bounds.x, bounds.y), element = _e.element, position = _e.position;
7804
+ if (!element)
7805
+ return;
7806
+ var oldSize = __assign({}, element.size);
7807
+ var preserveParentSize = Boolean(element.layout && element.layout.mode !== 'manual');
7808
+ var gridLayoutChange = this.resolveGridChildWidthResizeTopologyChange(element, bounds.width);
7809
+ var patches = [];
7810
+ if (gridLayoutChange) {
7811
+ patches.push.apply(patches, this.commandQueue.run(createSetElementLayoutCommand(gridLayoutChange.parentId, gridLayoutChange.afterLayout), this.model));
7812
+ }
7813
+ var positionChanged = element.position.x !== position.x || element.position.y !== position.y;
7814
+ if (positionChanged) {
7815
+ patches.push.apply(patches, this.commandQueue.run(createMoveElementCommand(id, position), this.model));
7816
+ }
7817
+ patches.push.apply(patches, this.commandQueue.run(createResizeElementCommand(id, { width: bounds.width, height: bounds.height }), this.model));
7818
+ var movedPortIds = this.collectElementPortIds(element.id);
7819
+ var layoutSteps = [function () { return _this.applyLayoutForParent(id, { preserveParentSize: preserveParentSize }); }];
7820
+ if (gridLayoutChange && element.parentId) {
7821
+ var grandParentId_1 = (_b = (_a = this.model.getElement(element.parentId)) === null || _a === void 0 ? void 0 : _a.parentId) !== null && _b !== void 0 ? _b : null;
7822
+ layoutSteps.push(function () { var _a; return _this.applyLayoutForParent((_a = element.parentId) !== null && _a !== void 0 ? _a : '', { preserveParentWidth: true }); });
7823
+ if (grandParentId_1) {
7824
+ layoutSteps.push(function () { return _this.applyLayoutCascade(grandParentId_1); });
7825
+ }
7826
+ }
7827
+ else {
7828
+ layoutSteps.push.apply(layoutSteps, this.buildChildMutationLayoutSteps((_c = element.parentId) !== null && _c !== void 0 ? _c : null, {
7829
+ preserveGridParentWidth: true,
7830
+ }));
7831
+ }
7832
+ var allPatches = this.mutationPipeline.run({
7833
+ basePatches: patches,
7834
+ layoutSteps: layoutSteps,
7835
+ movedPortIds: movedPortIds,
7836
+ });
7837
+ if (gridLayoutChange) {
7838
+ this.events.emit('gridLayoutChanged', {
7839
+ parentId: gridLayoutChange.parentId,
7840
+ triggerChildId: gridLayoutChange.triggerChildId,
7841
+ reason: gridLayoutChange.reason,
7842
+ beforeRows: gridLayoutChange.beforeRows,
7843
+ afterRows: gridLayoutChange.afterRows,
7844
+ beforeGridTemplate: gridLayoutChange.beforeGridTemplate,
7845
+ afterGridTemplate: gridLayoutChange.afterGridTemplate,
7846
+ });
7847
+ }
7848
+ this.emitChange(allPatches);
7849
+ var newSize = (_d = this.model.getElement(id)) === null || _d === void 0 ? void 0 : _d.size;
7850
+ if (newSize && (oldSize.width !== newSize.width || oldSize.height !== newSize.height)) {
7851
+ this.events.emit('elementResized', { elementId: id, oldSize: oldSize, newSize: __assign({}, newSize) });
7852
+ }
7853
+ };
7049
7854
  DiagramEngine.prototype.resizeElement = function (id, width, height) {
7050
7855
  var _this = this;
7051
- var _a;
7856
+ var _a, _b, _c, _d;
7052
7857
  var element = this.model.getElement(id);
7053
7858
  var oldSize = element === null || element === void 0 ? void 0 : element.size;
7054
7859
  var preserveParentSize = Boolean((element === null || element === void 0 ? void 0 : element.layout) && element.layout.mode !== 'manual');
7055
- var patches = this.commandQueue.run(createResizeElementCommand(id, { width: width, height: height }), this.model);
7860
+ var gridLayoutChange = element
7861
+ ? this.resolveGridChildWidthResizeTopologyChange(element, width)
7862
+ : null;
7863
+ var patches = [];
7864
+ if (gridLayoutChange) {
7865
+ patches.push.apply(patches, this.commandQueue.run(createSetElementLayoutCommand(gridLayoutChange.parentId, gridLayoutChange.afterLayout), this.model));
7866
+ }
7867
+ patches.push.apply(patches, this.commandQueue.run(createResizeElementCommand(id, { width: width, height: height }), this.model));
7056
7868
  var movedPortIds = element ? this.collectElementPortIds(element.id) : [];
7869
+ var layoutSteps = [function () { return _this.applyLayoutForParent(id, { preserveParentSize: preserveParentSize }); }];
7870
+ if (gridLayoutChange && (element === null || element === void 0 ? void 0 : element.parentId)) {
7871
+ var grandParentId_2 = (_b = (_a = this.model.getElement(element.parentId)) === null || _a === void 0 ? void 0 : _a.parentId) !== null && _b !== void 0 ? _b : null;
7872
+ layoutSteps.push(function () { var _a; return _this.applyLayoutForParent((_a = element.parentId) !== null && _a !== void 0 ? _a : '', { preserveParentWidth: true }); });
7873
+ if (grandParentId_2) {
7874
+ layoutSteps.push(function () { return _this.applyLayoutCascade(grandParentId_2); });
7875
+ }
7876
+ }
7877
+ else {
7878
+ layoutSteps.push.apply(layoutSteps, this.buildChildMutationLayoutSteps((_c = element === null || element === void 0 ? void 0 : element.parentId) !== null && _c !== void 0 ? _c : null, {
7879
+ preserveGridParentWidth: true,
7880
+ }));
7881
+ }
7057
7882
  var allPatches = this.mutationPipeline.run({
7058
7883
  basePatches: patches,
7059
- layoutSteps: [
7060
- function () { return _this.applyLayoutForParent(id, { preserveParentSize: preserveParentSize }); },
7061
- function () { var _a; return _this.applyLayoutCascade((_a = element === null || element === void 0 ? void 0 : element.parentId) !== null && _a !== void 0 ? _a : null); },
7062
- ],
7884
+ layoutSteps: layoutSteps,
7063
7885
  movedPortIds: movedPortIds,
7064
7886
  });
7887
+ if (gridLayoutChange) {
7888
+ this.events.emit('gridLayoutChanged', {
7889
+ parentId: gridLayoutChange.parentId,
7890
+ triggerChildId: gridLayoutChange.triggerChildId,
7891
+ reason: gridLayoutChange.reason,
7892
+ beforeRows: gridLayoutChange.beforeRows,
7893
+ afterRows: gridLayoutChange.afterRows,
7894
+ beforeGridTemplate: gridLayoutChange.beforeGridTemplate,
7895
+ afterGridTemplate: gridLayoutChange.afterGridTemplate,
7896
+ });
7897
+ }
7065
7898
  this.emitChange(allPatches);
7066
- var newSize = (_a = this.model.getElement(id)) === null || _a === void 0 ? void 0 : _a.size;
7899
+ var newSize = (_d = this.model.getElement(id)) === null || _d === void 0 ? void 0 : _d.size;
7067
7900
  if (oldSize && newSize && (oldSize.width !== newSize.width || oldSize.height !== newSize.height)) {
7068
7901
  this.events.emit('elementResized', { elementId: id, oldSize: __assign({}, oldSize), newSize: __assign({}, newSize) });
7069
7902
  }
@@ -7368,6 +8201,7 @@ var DiagramEngine = /** @class */ (function () {
7368
8201
  return baseRotation + instanceRotation;
7369
8202
  };
7370
8203
  DiagramEngine.prototype.normalizeElementResize = function (id, proposal, handle, minSize) {
8204
+ var _a, _b;
7371
8205
  if (minSize === void 0) { minSize = 20; }
7372
8206
  var clamped = {
7373
8207
  x: proposal.x,
@@ -7379,13 +8213,19 @@ var DiagramEngine = /** @class */ (function () {
7379
8213
  if (!element)
7380
8214
  return clamped;
7381
8215
  var lockHorizontalResize = this.shouldLockAutoLayoutChildHorizontalResize(element);
8216
+ var currentWorldPosition = this.model.getElementWorldPosition(id);
8217
+ var anchorGridWidthToLeft = this.shouldAnchorAutoLayoutGridChildWidthToLeft(element);
8218
+ var freezeGridLeftEdge = anchorGridWidthToLeft || lockHorizontalResize;
8219
+ var snappedGridWidth = this.resolveSnappedGridChildWidth(element, clamped.width);
7382
8220
  var shape = this.shapeRegistry.get(element.shapeId);
7383
8221
  if (!(shape === null || shape === void 0 ? void 0 : shape.normalizeResize)) {
7384
- if (!lockHorizontalResize)
8222
+ if (!lockHorizontalResize && !anchorGridWidthToLeft)
7385
8223
  return clamped;
7386
- var width_1 = Math.max(minSize, element.size.width);
7387
- var x_1 = clamped.x;
7388
- if (handle === 'sw' || handle === 'nw') {
8224
+ var width_1 = lockHorizontalResize
8225
+ ? Math.max(minSize, element.size.width)
8226
+ : Math.max(minSize, snappedGridWidth);
8227
+ var x_1 = freezeGridLeftEdge ? ((_a = currentWorldPosition === null || currentWorldPosition === void 0 ? void 0 : currentWorldPosition.x) !== null && _a !== void 0 ? _a : clamped.x) : clamped.x;
8228
+ if (!freezeGridLeftEdge && (handle === 'sw' || handle === 'nw')) {
7389
8229
  x_1 += clamped.width - width_1;
7390
8230
  }
7391
8231
  return { x: x_1, y: clamped.y, width: width_1, height: clamped.height };
@@ -7396,11 +8236,15 @@ var DiagramEngine = /** @class */ (function () {
7396
8236
  minSize: minSize,
7397
8237
  proposal: { width: clamped.width, height: clamped.height },
7398
8238
  });
7399
- var width = lockHorizontalResize ? Math.max(minSize, element.size.width) : Math.max(minSize, normalized.width);
8239
+ var width = lockHorizontalResize
8240
+ ? Math.max(minSize, element.size.width)
8241
+ : anchorGridWidthToLeft
8242
+ ? Math.max(minSize, snappedGridWidth)
8243
+ : Math.max(minSize, normalized.width);
7400
8244
  var height = Math.max(minSize, normalized.height);
7401
- var x = clamped.x;
8245
+ var x = freezeGridLeftEdge ? ((_b = currentWorldPosition === null || currentWorldPosition === void 0 ? void 0 : currentWorldPosition.x) !== null && _b !== void 0 ? _b : clamped.x) : clamped.x;
7402
8246
  var y = clamped.y;
7403
- if (handle === 'sw' || handle === 'nw') {
8247
+ if (!freezeGridLeftEdge && (handle === 'sw' || handle === 'nw')) {
7404
8248
  x += clamped.width - width;
7405
8249
  }
7406
8250
  if (handle === 'ne' || handle === 'nw') {
@@ -7413,12 +8257,72 @@ var DiagramEngine = /** @class */ (function () {
7413
8257
  var parentId = (_a = element.parentId) !== null && _a !== void 0 ? _a : null;
7414
8258
  if (!parentId)
7415
8259
  return false;
8260
+ if (!this.isLeafGridChildResizeCandidate(element))
8261
+ return false;
8262
+ var parent = this.model.getElement(parentId);
8263
+ if (((_b = parent === null || parent === void 0 ? void 0 : parent.layout) === null || _b === void 0 ? void 0 : _b.mode) !== 'grid')
8264
+ return false;
8265
+ return !Boolean(parent.layout.gridChildWidthResizeEnabled);
8266
+ };
8267
+ DiagramEngine.prototype.shouldAnchorAutoLayoutGridChildWidthToLeft = function (element) {
8268
+ return this.isEnabledGridChildWidthResizeCandidate(element);
8269
+ };
8270
+ DiagramEngine.prototype.shouldRestrictAutoLayoutChildRightGrowth = function (element, handle, requestedWidth) {
8271
+ return false;
8272
+ };
8273
+ DiagramEngine.prototype.resolveSnappedGridChildWidth = function (element, requestedWidth) {
8274
+ var _a;
8275
+ var parentId = (_a = element.parentId) !== null && _a !== void 0 ? _a : null;
8276
+ if (!parentId)
8277
+ return requestedWidth;
8278
+ if (!this.isEnabledGridChildWidthResizeCandidate(element))
8279
+ return requestedWidth;
8280
+ return this.autoLayoutService.snapGridChildRequestedWidth(parentId, element.id, requestedWidth);
8281
+ };
8282
+ DiagramEngine.prototype.resolveGridChildWidthResizeTopologyChange = function (element, requestedWidth) {
8283
+ var _a, _b;
8284
+ var parentId = (_a = element.parentId) !== null && _a !== void 0 ? _a : null;
8285
+ if (!parentId)
8286
+ return null;
8287
+ if (!this.isEnabledGridChildWidthResizeCandidate(element))
8288
+ return null;
8289
+ var parent = this.model.getElement(parentId);
8290
+ if (!parent)
8291
+ return null;
8292
+ var topologyChange = this.autoLayoutService.resolveGridChildResizeTopologyChange(parentId, element.id, requestedWidth);
8293
+ if (!topologyChange)
8294
+ return null;
8295
+ var parentLayout = parent.layout;
8296
+ if (!parentLayout)
8297
+ return null;
8298
+ return {
8299
+ parentId: topologyChange.parentId,
8300
+ triggerChildId: topologyChange.triggerChildId,
8301
+ reason: topologyChange.reason,
8302
+ beforeRows: topologyChange.beforeRows,
8303
+ afterRows: topologyChange.afterRows,
8304
+ beforeGridTemplate: parentLayout.gridTemplate ? __spreadArray([], parentLayout.gridTemplate, true) : undefined,
8305
+ afterGridTemplate: __spreadArray([], ((_b = topologyChange.nextLayout.gridTemplate) !== null && _b !== void 0 ? _b : []), true),
8306
+ afterLayout: topologyChange.nextLayout,
8307
+ };
8308
+ };
8309
+ DiagramEngine.prototype.isLeafGridChildResizeCandidate = function (element) {
7416
8310
  if (this.model.getChildren(element.id).length > 0)
7417
8311
  return false;
7418
8312
  if (element.layout && element.layout.mode !== 'manual')
7419
8313
  return false;
8314
+ return true;
8315
+ };
8316
+ DiagramEngine.prototype.isEnabledGridChildWidthResizeCandidate = function (element) {
8317
+ var _a;
8318
+ var parentId = (_a = element.parentId) !== null && _a !== void 0 ? _a : null;
8319
+ if (!parentId)
8320
+ return false;
7420
8321
  var parent = this.model.getElement(parentId);
7421
- return ((_b = parent === null || parent === void 0 ? void 0 : parent.layout) === null || _b === void 0 ? void 0 : _b.mode) === 'grid';
8322
+ var layout = parent === null || parent === void 0 ? void 0 : parent.layout;
8323
+ if (!layout || layout.mode !== 'grid')
8324
+ return false;
8325
+ return Boolean(layout.gridChildWidthResizeEnabled);
7422
8326
  };
7423
8327
  DiagramEngine.prototype.getPortWorldPosition = function (id) {
7424
8328
  return this.model.getPortWorldPosition(id);
@@ -7701,8 +8605,8 @@ var DiagramEngine = /** @class */ (function () {
7701
8605
  }
7702
8606
  if (style === null || style === void 0 ? void 0 : style.moveBounds) {
7703
8607
  var bounds = style.moveBounds;
7704
- position.x = clamp(position.x, bounds.x, bounds.x + bounds.width);
7705
- position.y = clamp(position.y, bounds.y, bounds.y + bounds.height);
8608
+ position.x = clamp$1(position.x, bounds.x, bounds.x + bounds.width);
8609
+ position.y = clamp$1(position.y, bounds.y, bounds.y + bounds.height);
7706
8610
  }
7707
8611
  if (effectiveMoveMode === 'border') {
7708
8612
  var resolvedBorder = this.resolveBorderPositionWithLimits(position, element, (_e = element.portMovement) === null || _e === void 0 ? void 0 : _e.positionLimits);
@@ -9280,7 +10184,7 @@ var ellipseMidPointToIndex = function (value) {
9280
10184
  var KonvaInteraction = /** @class */ (function () {
9281
10185
  function KonvaInteraction(engine, config) {
9282
10186
  if (config === void 0) { config = {}; }
9283
- var _a, _b;
10187
+ var _a;
9284
10188
  this.linkDragContext = null;
9285
10189
  this.programmaticLinkSession = null;
9286
10190
  this.bound = false;
@@ -9304,7 +10208,6 @@ var KonvaInteraction = /** @class */ (function () {
9304
10208
  this.stage = config.stage;
9305
10209
  this.hitTester = (_a = config.hitTester) !== null && _a !== void 0 ? _a : new KonvaHitTester();
9306
10210
  this.renderer = config.renderer;
9307
- this.panKey = (_b = config.panKey) !== null && _b !== void 0 ? _b : 'Control';
9308
10211
  this.shapeRegistry = config.shapeRegistry;
9309
10212
  this.shapeHoverControls = this.normalizeShapeHoverControls(config.shapeHoverControls);
9310
10213
  this.onShapeHoverControlInteracted = config.onShapeHoverControlInteracted;
@@ -9472,7 +10375,10 @@ var KonvaInteraction = /** @class */ (function () {
9472
10375
  var hit = _this.resolveHit(point);
9473
10376
  var nativeEvent = event === null || event === void 0 ? void 0 : event.evt;
9474
10377
  var isMulti = Boolean(nativeEvent && (nativeEvent.ctrlKey || nativeEvent.metaKey || nativeEvent.shiftKey));
9475
- var isPanGesture = Boolean(nativeEvent && _this.isPanKeyPressed(nativeEvent) && nativeEvent.button === 0);
10378
+ var isPrimaryButton = !nativeEvent || nativeEvent.button === 0;
10379
+ var isEmptyPaper = !hit || hit.type === 'none';
10380
+ var isMarqueeGesture = Boolean(isPrimaryButton && isEmptyPaper && (nativeEvent === null || nativeEvent === void 0 ? void 0 : nativeEvent.shiftKey));
10381
+ var isPanGesture = Boolean(isPrimaryButton && isEmptyPaper && !(nativeEvent === null || nativeEvent === void 0 ? void 0 : nativeEvent.shiftKey));
9476
10382
  var pointerInfo = _this.buildPointerInfo(point, nativeEvent);
9477
10383
  if ((hit === null || hit === void 0 ? void 0 : hit.type) === 'shape-hover-control') {
9478
10384
  var resolvedControl = _this.resolveShapeHoverControlFromHit(hit.id, point);
@@ -9530,11 +10436,14 @@ var KonvaInteraction = /** @class */ (function () {
9530
10436
  }
9531
10437
  return;
9532
10438
  }
9533
- if (!hit || hit.type === 'none') {
10439
+ if (isMarqueeGesture) {
9534
10440
  _this.dragState = { mode: 'marquee', start: point, isMulti: isMulti, hasMoved: false };
9535
10441
  (_d = _this.renderer) === null || _d === void 0 ? void 0 : _d.renderMarquee({ x: point.x, y: point.y, width: 0, height: 0 });
9536
10442
  return;
9537
10443
  }
10444
+ if (isEmptyPaper) {
10445
+ return;
10446
+ }
9538
10447
  if (hit.type === 'port') {
9539
10448
  var elementId = _this.engine.getPortElementId(hit.id);
9540
10449
  if (!elementId)
@@ -9577,6 +10486,10 @@ var KonvaInteraction = /** @class */ (function () {
9577
10486
  return;
9578
10487
  }
9579
10488
  if (hit.type === 'text') {
10489
+ if (!_this.isTextMovable(hit.id)) {
10490
+ _this.setCursor('default');
10491
+ return;
10492
+ }
9580
10493
  var base = _this.engine.getTextWorldPosition(hit.id);
9581
10494
  if (base) {
9582
10495
  _this.dragState = {
@@ -9595,6 +10508,7 @@ var KonvaInteraction = /** @class */ (function () {
9595
10508
  var element = _this.getElementById(hit.id);
9596
10509
  if (!element)
9597
10510
  return;
10511
+ var movable = _this.isElementMovable(hit.id);
9598
10512
  var anchor = element.anchorCenter ? 'center' : 'top-left';
9599
10513
  var base = element.anchorCenter
9600
10514
  ? {
@@ -9609,12 +10523,13 @@ var KonvaInteraction = /** @class */ (function () {
9609
10523
  offset: { x: point.x - base.x, y: point.y - base.y },
9610
10524
  start: __assign({}, base),
9611
10525
  anchor: anchor,
10526
+ movable: movable,
9612
10527
  startParentId: (_e = element.parentId) !== null && _e !== void 0 ? _e : null,
9613
10528
  selectionIds: _this.engine.getSelection(),
9614
10529
  isMulti: isMulti,
9615
10530
  hasMoved: false,
9616
10531
  };
9617
- _this.setCursor('grabbing');
10532
+ _this.setCursor(movable ? 'grabbing' : 'pointer');
9618
10533
  }
9619
10534
  }
9620
10535
  };
@@ -9672,6 +10587,9 @@ var KonvaInteraction = /** @class */ (function () {
9672
10587
  var dy = target.y - _this.dragState.start.y;
9673
10588
  var moved = Math.hypot(dx, dy) >= _this.dragThreshold;
9674
10589
  _this.dragState.hasMoved = _this.dragState.hasMoved || moved;
10590
+ if (!_this.dragState.movable) {
10591
+ return;
10592
+ }
9675
10593
  _this.engine.moveElementTo(_this.dragState.id, target.x, target.y);
9676
10594
  if (_this.renderer && _this.engine.getSelection().includes(_this.dragState.id)) {
9677
10595
  var element = _this.getElementById(_this.dragState.id);
@@ -9797,15 +10715,15 @@ var KonvaInteraction = /** @class */ (function () {
9797
10715
  var dx = point.x - _this.dragState.start.x;
9798
10716
  var dy = point.y - _this.dragState.start.y;
9799
10717
  _this.pan = {
9800
- x: _this.dragState.origin.x - dx * _this.panSpeed,
9801
- y: _this.dragState.origin.y - dy * _this.panSpeed,
10718
+ x: _this.dragState.origin.x + dx * _this.panSpeed,
10719
+ y: _this.dragState.origin.y + dy * _this.panSpeed,
9802
10720
  };
9803
10721
  _this.applyStageTransform();
9804
10722
  _this.engine.setViewport(_this.pan, _this.zoom);
9805
10723
  }
9806
10724
  };
9807
10725
  var pointerUp = function () {
9808
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
10726
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
9809
10727
  var args = [];
9810
10728
  for (var _i = 0; _i < arguments.length; _i++) {
9811
10729
  args[_i] = arguments[_i];
@@ -9899,10 +10817,21 @@ var KonvaInteraction = /** @class */ (function () {
9899
10817
  _this.engine.emitPaperClick(pointerInfo);
9900
10818
  }
9901
10819
  }
9902
- if (((_h = _this.dragState) === null || _h === void 0 ? void 0 : _h.mode) === 'move' && _this.dragState.type === 'element') {
10820
+ if (((_h = _this.dragState) === null || _h === void 0 ? void 0 : _h.mode) === 'pan') {
10821
+ var point = pointerPoint !== null && pointerPoint !== void 0 ? pointerPoint : _this.dragState.start;
10822
+ var dx = point.x - _this.dragState.start.x;
10823
+ var dy = point.y - _this.dragState.start.y;
10824
+ var moved = Math.hypot(dx, dy) >= _this.dragThreshold;
10825
+ if (!moved) {
10826
+ _this.engine.setSelection([]);
10827
+ var pointerInfo = _this.buildPointerInfo(point, nativeEvent);
10828
+ _this.engine.emitPaperClick(pointerInfo);
10829
+ }
10830
+ }
10831
+ if (((_j = _this.dragState) === null || _j === void 0 ? void 0 : _j.mode) === 'move' && _this.dragState.type === 'element') {
9903
10832
  var element = _this.getElementById(_this.dragState.id);
9904
10833
  if (element) {
9905
- var endTopLeft = (_j = _this.engine.getElementWorldPosition(_this.dragState.id)) !== null && _j !== void 0 ? _j : element.position;
10834
+ var endTopLeft = (_k = _this.engine.getElementWorldPosition(_this.dragState.id)) !== null && _k !== void 0 ? _k : element.position;
9906
10835
  var endWorld = _this.dragState.anchor === 'center'
9907
10836
  ? {
9908
10837
  x: endTopLeft.x + element.size.width / 2,
@@ -9913,7 +10842,8 @@ var KonvaInteraction = /** @class */ (function () {
9913
10842
  x: endWorld.x - _this.dragState.start.x,
9914
10843
  y: endWorld.y - _this.dragState.start.y,
9915
10844
  };
9916
- var moved = _this.dragState.hasMoved || Math.hypot(delta.x, delta.y) > 0;
10845
+ var moved = _this.dragState.movable &&
10846
+ (_this.dragState.hasMoved || Math.hypot(delta.x, delta.y) > 0);
9917
10847
  if (moved) {
9918
10848
  _this.engine.emitElementDrop({
9919
10849
  elementId: _this.dragState.id,
@@ -9925,16 +10855,16 @@ var KonvaInteraction = /** @class */ (function () {
9925
10855
  anchor: _this.dragState.anchor,
9926
10856
  });
9927
10857
  }
9928
- else {
10858
+ else if (!_this.dragState.hasMoved) {
9929
10859
  var pointerInfo = _this.buildPointerInfo(pointerPoint !== null && pointerPoint !== void 0 ? pointerPoint : _this.dragState.start, nativeEvent);
9930
10860
  _this.engine.emitElementClick(_this.dragState.id, pointerInfo, _this.dragState.isMulti);
9931
10861
  }
9932
10862
  }
9933
10863
  }
9934
- if (((_k = _this.dragState) === null || _k === void 0 ? void 0 : _k.mode) === 'move' && _this.dragState.type === 'port') {
10864
+ if (((_l = _this.dragState) === null || _l === void 0 ? void 0 : _l.mode) === 'move' && _this.dragState.type === 'port') {
9935
10865
  var elementId = _this.engine.getPortElementId(_this.dragState.id);
9936
10866
  if (elementId) {
9937
- var pointerInfo = _this.buildPointerInfo((_l = pointerPoint !== null && pointerPoint !== void 0 ? pointerPoint : _this.engine.getPortWorldPosition(_this.dragState.id)) !== null && _l !== void 0 ? _l : { x: 0, y: 0 }, nativeEvent);
10867
+ var pointerInfo = _this.buildPointerInfo((_m = pointerPoint !== null && pointerPoint !== void 0 ? pointerPoint : _this.engine.getPortWorldPosition(_this.dragState.id)) !== null && _m !== void 0 ? _m : { x: 0, y: 0 }, nativeEvent);
9938
10868
  _this.engine.emitPortMouseUp({ portId: _this.dragState.id, elementId: elementId, pointer: pointerInfo });
9939
10869
  }
9940
10870
  }
@@ -9966,6 +10896,8 @@ var KonvaInteraction = /** @class */ (function () {
9966
10896
  var hit = _this.resolveHit(point);
9967
10897
  if (!hit || hit.type !== 'text')
9968
10898
  return;
10899
+ if (!_this.isTextEditable(hit.id))
10900
+ return;
9969
10901
  _this.startTextEdit(hit.id);
9970
10902
  };
9971
10903
  this.stage.on('dblclick dbltap', doubleClick);
@@ -10238,6 +11170,10 @@ var KonvaInteraction = /** @class */ (function () {
10238
11170
  this.setCursor('pointer');
10239
11171
  return;
10240
11172
  }
11173
+ if (hit.type === 'element' && !this.isElementMovable(hit.id)) {
11174
+ this.setCursor('pointer');
11175
+ return;
11176
+ }
10241
11177
  this.setCursor('grab');
10242
11178
  };
10243
11179
  KonvaInteraction.prototype.normalizeShapeHoverControls = function (controls) {
@@ -11118,8 +12054,12 @@ var KonvaInteraction = /** @class */ (function () {
11118
12054
  y: normalized.y + normalized.height / 2,
11119
12055
  }
11120
12056
  : { x: normalized.x, y: normalized.y };
11121
- this.engine.moveElementTo(state.elementId, moveTarget.x, moveTarget.y);
11122
- this.engine.resizeElement(state.elementId, normalized.width, normalized.height);
12057
+ this.engine.resizeElementBounds(state.elementId, {
12058
+ x: moveTarget.x,
12059
+ y: moveTarget.y,
12060
+ width: normalized.width,
12061
+ height: normalized.height,
12062
+ });
11123
12063
  this.updateSelectionOverlays();
11124
12064
  };
11125
12065
  KonvaInteraction.prototype.parseResizeHandle = function (id) {
@@ -11455,6 +12395,22 @@ var KonvaInteraction = /** @class */ (function () {
11455
12395
  KonvaInteraction.prototype.getTextById = function (id) {
11456
12396
  return this.engine.getState().texts.find(function (text) { return text.id === id; });
11457
12397
  };
12398
+ KonvaInteraction.prototype.isTextMovable = function (id) {
12399
+ var _a, _b;
12400
+ return ((_b = (_a = this.getTextById(id)) === null || _a === void 0 ? void 0 : _a.interaction) === null || _b === void 0 ? void 0 : _b.movable) !== false;
12401
+ };
12402
+ KonvaInteraction.prototype.isElementMovable = function (id) {
12403
+ var _a;
12404
+ var element = this.getElementById(id);
12405
+ if (!(element === null || element === void 0 ? void 0 : element.parentId))
12406
+ return true;
12407
+ var parent = this.getElementById(element.parentId);
12408
+ return ((_a = parent === null || parent === void 0 ? void 0 : parent.childElementInteraction) === null || _a === void 0 ? void 0 : _a.movable) !== false;
12409
+ };
12410
+ KonvaInteraction.prototype.isTextEditable = function (id) {
12411
+ var _a, _b;
12412
+ return ((_b = (_a = this.getTextById(id)) === null || _a === void 0 ? void 0 : _a.interaction) === null || _b === void 0 ? void 0 : _b.editable) !== false;
12413
+ };
11458
12414
  KonvaInteraction.prototype.getLinkById = function (id) {
11459
12415
  return this.engine.getState().links.find(function (link) { return link.id === id; });
11460
12416
  };
@@ -11569,19 +12525,6 @@ var KonvaInteraction = /** @class */ (function () {
11569
12525
  var tag = target.tagName.toLowerCase();
11570
12526
  return tag === 'input' || tag === 'textarea' || tag === 'select';
11571
12527
  };
11572
- KonvaInteraction.prototype.isPanKeyPressed = function (event) {
11573
- switch (this.panKey) {
11574
- case 'Shift':
11575
- return event.shiftKey;
11576
- case 'Alt':
11577
- return event.altKey;
11578
- case 'Meta':
11579
- return event.metaKey;
11580
- case 'Control':
11581
- default:
11582
- return event.ctrlKey;
11583
- }
11584
- };
11585
12528
  return KonvaInteraction;
11586
12529
  }());
11587
12530
 
@@ -12137,6 +13080,24 @@ var hasBounds = function (bounds) {
12137
13080
  bounds.maxX >= bounds.minX &&
12138
13081
  bounds.maxY >= bounds.minY;
12139
13082
  };
13083
+ var DEFAULT_VIEWPORT_FIT_PADDING = 24;
13084
+ var DEFAULT_VIEWPORT_FIT_MIN_ZOOM = 0.2;
13085
+ var DEFAULT_VIEWPORT_FIT_MAX_ZOOM = 3;
13086
+ var resolveViewportFitOptions = function (options) {
13087
+ var padding = typeof (options === null || options === void 0 ? void 0 : options.padding) === 'number' && Number.isFinite(options.padding)
13088
+ ? Math.max(0, options.padding)
13089
+ : DEFAULT_VIEWPORT_FIT_PADDING;
13090
+ var requestedMinZoom = typeof (options === null || options === void 0 ? void 0 : options.minZoom) === 'number' && Number.isFinite(options.minZoom)
13091
+ ? Math.max(0.000001, options.minZoom)
13092
+ : DEFAULT_VIEWPORT_FIT_MIN_ZOOM;
13093
+ var requestedMaxZoom = typeof (options === null || options === void 0 ? void 0 : options.maxZoom) === 'number' && Number.isFinite(options.maxZoom)
13094
+ ? Math.max(0.000001, options.maxZoom)
13095
+ : DEFAULT_VIEWPORT_FIT_MAX_ZOOM;
13096
+ var minZoom = Math.min(requestedMinZoom, requestedMaxZoom);
13097
+ var maxZoom = Math.max(requestedMinZoom, requestedMaxZoom);
13098
+ return { padding: padding, minZoom: minZoom, maxZoom: maxZoom };
13099
+ };
13100
+ var clamp = function (value, min, max) { return Math.max(min, Math.min(max, value)); };
12140
13101
  var resolveStateWorldBounds = function (state) {
12141
13102
  var bounds = createBounds();
12142
13103
  state.elements.forEach(function (element) {
@@ -12173,6 +13134,34 @@ var resolveStateWorldBounds = function (state) {
12173
13134
  });
12174
13135
  return hasBounds(bounds) ? bounds : null;
12175
13136
  };
13137
+ var resolveElementWorldBounds = function (state) {
13138
+ var bounds = createBounds();
13139
+ state.elements.forEach(function (element) {
13140
+ includeRect(bounds, element.position.x, element.position.y, element.size.width, element.size.height);
13141
+ });
13142
+ return hasBounds(bounds) ? bounds : null;
13143
+ };
13144
+ var resolveViewportFitTransform = function (state, viewportSize, options) {
13145
+ var bounds = resolveElementWorldBounds(state);
13146
+ if (!bounds)
13147
+ return null;
13148
+ var safeWidth = Math.max(1, viewportSize.width);
13149
+ var safeHeight = Math.max(1, viewportSize.height);
13150
+ var _a = resolveViewportFitOptions(options), padding = _a.padding, minZoom = _a.minZoom, maxZoom = _a.maxZoom;
13151
+ var availableWidth = Math.max(1, safeWidth - padding * 2);
13152
+ var availableHeight = Math.max(1, safeHeight - padding * 2);
13153
+ var contentWidth = Math.max(1, bounds.maxX - bounds.minX);
13154
+ var contentHeight = Math.max(1, bounds.maxY - bounds.minY);
13155
+ var rawZoom = Math.min(availableWidth / contentWidth, availableHeight / contentHeight);
13156
+ var zoom = clamp(rawZoom, minZoom, maxZoom);
13157
+ var centerX = (bounds.minX + bounds.maxX) / 2;
13158
+ var centerY = (bounds.minY + bounds.maxY) / 2;
13159
+ var pan = {
13160
+ x: safeWidth / 2 - centerX * zoom,
13161
+ y: safeHeight / 2 - centerY * zoom,
13162
+ };
13163
+ return { pan: pan, zoom: zoom };
13164
+ };
12176
13165
  var resolveFitToContentPadding = function (fitToContent) {
12177
13166
  if (typeof fitToContent === 'object' && typeof fitToContent.padding === 'number') {
12178
13167
  return Math.max(0, fitToContent.padding);
@@ -12248,10 +13237,12 @@ var registerSimpleShapes = function (registry, shapes, isPort) {
12248
13237
  var createDiagramEditor = function (config) {
12249
13238
  var _a, _b;
12250
13239
  var Konva = getKonva();
13240
+ var stageWidth = (_a = config.width) !== null && _a !== void 0 ? _a : 900;
13241
+ var stageHeight = (_b = config.height) !== null && _b !== void 0 ? _b : 560;
12251
13242
  var stage = new Konva.Stage({
12252
13243
  container: config.container,
12253
- width: (_a = config.width) !== null && _a !== void 0 ? _a : 900,
12254
- height: (_b = config.height) !== null && _b !== void 0 ? _b : 560,
13244
+ width: stageWidth,
13245
+ height: stageHeight,
12255
13246
  });
12256
13247
  var stageContainer = typeof stage.container === 'function' ? stage.container() : stage.container;
12257
13248
  if (stageContainer && stageContainer.tabIndex < 0) {
@@ -12398,6 +13389,12 @@ var createDiagramEditor = function (config) {
12398
13389
  completeLinkToPort: function (targetPortId) { return interaction.completeLinkToPort(targetPortId); },
12399
13390
  completeLinkToElement: function (targetElementId, pointer) { return interaction.completeLinkToElement(targetElementId, pointer); },
12400
13391
  cancelLink: function () { return interaction.cancelLink(); },
13392
+ zoomToFitElements: function (options) {
13393
+ var transform = resolveViewportFitTransform(engine.getState(), { width: stageWidth, height: stageHeight }, options);
13394
+ if (!transform)
13395
+ return;
13396
+ engine.setViewport(transform.pan, transform.zoom);
13397
+ },
12401
13398
  exportImage: function (options) {
12402
13399
  engine.render();
12403
13400
  if (typeof stage.toDataURL !== 'function') {
@@ -12424,6 +13421,8 @@ var createDiagramEditor = function (config) {
12424
13421
  return stage.toDataURL(__assign(__assign({}, baseOptions), { x: cropX, y: cropY, width: cropWidth, height: cropHeight }));
12425
13422
  },
12426
13423
  resize: function (width, height) {
13424
+ stageWidth = width;
13425
+ stageHeight = height;
12427
13426
  stage.width(width);
12428
13427
  stage.height(height);
12429
13428
  engine.render();
@@ -12643,6 +13642,7 @@ var engineEventOptions = [
12643
13642
  'elementDragged',
12644
13643
  'elementMoved',
12645
13644
  'elementResized',
13645
+ 'gridLayoutChanged',
12646
13646
  'elementDeleted',
12647
13647
  'portDeleted',
12648
13648
  'linkDeleted',
@@ -12893,11 +13893,16 @@ var parentOptions = [
12893
13893
  { id: 'layout-column', label: 'Vertical layout' },
12894
13894
  { id: 'layout-grid', label: 'Grid layout' },
12895
13895
  { id: 'layout-nested', label: 'Nested layout' },
13896
+ { id: 'layout-grid-deep', label: 'Nested grid' },
13897
+ { id: 'layout-lock-compare', label: 'Child lock compare' },
12896
13898
  { id: 'layout-manual', label: 'Manual (compare)' },
12897
13899
  ];
12898
13900
  var shortLabel = 'Parent label lane demo';
12899
13901
  var longLabel = 'Parent label lane demo with longer content to increase flexible reserved space and push children downward.';
12900
- var defaultGridTemplateText = '[[3],[1,2]]';
13902
+ var defaultGridTemplateText = '[12,4,8]';
13903
+ var lockComparisonContainerId = 'layout-lock-compare';
13904
+ var lockParentId = 'deep-lock-parent';
13905
+ var lockTargetId = 'deep-lock-child-a';
12901
13906
  var serializeGridTemplate = function (template) {
12902
13907
  return Array.isArray(template) && template.length > 0 ? JSON.stringify(template) : defaultGridTemplateText;
12903
13908
  };
@@ -12916,33 +13921,33 @@ var parseGridTemplate = function (value) {
12916
13921
  return null;
12917
13922
  var normalized = [];
12918
13923
  for (var i = 0; i < parsed.length; i += 1) {
12919
- var row = parsed[i];
12920
- if (typeof row === 'number') {
12921
- if (!Number.isFinite(row) || row <= 0)
13924
+ var entry = parsed[i];
13925
+ if (typeof entry === 'number') {
13926
+ if (!Number.isFinite(entry) || entry <= 0)
12922
13927
  return null;
12923
- normalized.push(Math.floor(row));
13928
+ normalized.push(Math.floor(entry));
12924
13929
  continue;
12925
13930
  }
12926
- if (!Array.isArray(row) || row.length === 0)
13931
+ if (!Array.isArray(entry) || entry.length === 0)
12927
13932
  return null;
12928
- var weights = [];
12929
- for (var j = 0; j < row.length; j += 1) {
12930
- var cell = row[j];
13933
+ for (var j = 0; j < entry.length; j += 1) {
13934
+ var cell = entry[j];
12931
13935
  if (typeof cell !== 'number' || !Number.isFinite(cell) || cell <= 0)
12932
13936
  return null;
12933
- weights.push(cell);
13937
+ normalized.push(Math.floor(cell));
12934
13938
  }
12935
- normalized.push(weights);
12936
13939
  }
12937
13940
  return normalized;
12938
13941
  };
12939
13942
  var AutoLayoutDemo = function () {
12940
13943
  var demo = autoLayoutDemoConfig;
12941
- var _a = useDemoEditor({
12942
- createState: demo.createState,
13944
+ var _a = React.useState(true), lockComparisonChildren = _a[0], setLockComparisonChildren = _a[1];
13945
+ var createState = React.useCallback(function () { return createAutoLayoutState(lockComparisonChildren); }, [lockComparisonChildren]);
13946
+ var _b = useDemoEditor({
13947
+ createState: createState,
12943
13948
  elementShapes: demo.elementShapes,
12944
13949
  portShapes: demo.portShapes,
12945
- }), containerRef = _a.containerRef, editorRef = _a.editorRef, diagramState = _a.diagramState, selection = _a.selection, snapEnabled = _a.snapEnabled, setSnapEnabled = _a.setSnapEnabled;
13950
+ }), containerRef = _b.containerRef, editorRef = _b.editorRef, diagramState = _b.diagramState, selection = _b.selection, snapEnabled = _b.snapEnabled, setSnapEnabled = _b.setSnapEnabled;
12946
13951
  var nextOffset = useOffsetSequence();
12947
13952
  var actionHelpers = React.useMemo(function () { return ({ nextOffset: nextOffset }); }, [nextOffset]);
12948
13953
  var controls = useDemoControls({
@@ -12954,24 +13959,25 @@ var AutoLayoutDemo = function () {
12954
13959
  setSnapEnabled: setSnapEnabled,
12955
13960
  actionHelpers: actionHelpers,
12956
13961
  });
12957
- var _b = React.useState(parentOptions[0].id), targetId = _b[0], setTargetId = _b[1];
12958
- var _c = React.useState('horizontal'), mode = _c[0], setMode = _c[1];
12959
- var _d = React.useState('center'), align = _d[0], setAlign = _d[1];
12960
- var _e = React.useState('grow'), autoResize = _e[0], setAutoResize = _e[1];
12961
- var _f = React.useState(12), padding = _f[0], setPadding = _f[1];
12962
- var _g = React.useState(12), gap = _g[0], setGap = _g[1];
12963
- var _h = React.useState('none'), childFitMainAxis = _h[0], setChildFitMainAxis = _h[1];
12964
- var _j = React.useState('none'), childFitCrossAxis = _j[0], setChildFitCrossAxis = _j[1];
12965
- var _k = React.useState(''), childMinWidth = _k[0], setChildMinWidth = _k[1];
12966
- var _l = React.useState(''), childMinHeight = _l[0], setChildMinHeight = _l[1];
12967
- var _m = React.useState(''), childMaxWidth = _m[0], setChildMaxWidth = _m[1];
12968
- var _o = React.useState(''), childMaxHeight = _o[0], setChildMaxHeight = _o[1];
12969
- var _p = React.useState(defaultGridTemplateText), gridTemplateText = _p[0], setGridTemplateText = _p[1];
12970
- var _q = React.useState('none'), labelReservedMode = _q[0], setLabelReservedMode = _q[1];
12971
- var _r = React.useState(32), labelReservedFixedSize = _r[0], setLabelReservedFixedSize = _r[1];
12972
- var _s = React.useState(''), labelReservedMinSize = _s[0], setLabelReservedMinSize = _s[1];
12973
- var _t = React.useState(''), labelReservedMaxSize = _t[0], setLabelReservedMaxSize = _t[1];
12974
- var _u = React.useState('None yet'), lastTrigger = _u[0], setLastTrigger = _u[1];
13962
+ var _c = React.useState(parentOptions[0].id), targetId = _c[0], setTargetId = _c[1];
13963
+ var _d = React.useState('horizontal'), mode = _d[0], setMode = _d[1];
13964
+ var _e = React.useState('center'), align = _e[0], setAlign = _e[1];
13965
+ var _f = React.useState('grow'), autoResize = _f[0], setAutoResize = _f[1];
13966
+ var _g = React.useState(12), padding = _g[0], setPadding = _g[1];
13967
+ var _h = React.useState(12), gap = _h[0], setGap = _h[1];
13968
+ var _j = React.useState('none'), childFitMainAxis = _j[0], setChildFitMainAxis = _j[1];
13969
+ var _k = React.useState('none'), childFitCrossAxis = _k[0], setChildFitCrossAxis = _k[1];
13970
+ var _l = React.useState(''), childMinWidth = _l[0], setChildMinWidth = _l[1];
13971
+ var _m = React.useState(''), childMinHeight = _m[0], setChildMinHeight = _m[1];
13972
+ var _o = React.useState(''), childMaxWidth = _o[0], setChildMaxWidth = _o[1];
13973
+ var _p = React.useState(''), childMaxHeight = _p[0], setChildMaxHeight = _p[1];
13974
+ var _q = React.useState(defaultGridTemplateText), gridTemplateText = _q[0], setGridTemplateText = _q[1];
13975
+ var _r = React.useState(false), gridChildWidthResizeEnabled = _r[0], setGridChildWidthResizeEnabled = _r[1];
13976
+ var _s = React.useState('none'), labelReservedMode = _s[0], setLabelReservedMode = _s[1];
13977
+ var _t = React.useState(32), labelReservedFixedSize = _t[0], setLabelReservedFixedSize = _t[1];
13978
+ var _u = React.useState(''), labelReservedMinSize = _u[0], setLabelReservedMinSize = _u[1];
13979
+ var _v = React.useState(''), labelReservedMaxSize = _v[0], setLabelReservedMaxSize = _v[1];
13980
+ var _w = React.useState('None yet'), lastTrigger = _w[0], setLastTrigger = _w[1];
12975
13981
  React.useEffect(function () {
12976
13982
  var editor = editorRef.current;
12977
13983
  if (!editor)
@@ -12979,6 +13985,7 @@ var AutoLayoutDemo = function () {
12979
13985
  var disposers = [
12980
13986
  editor.on('elementMoved', function () { return setLastTrigger('child moved'); }),
12981
13987
  editor.on('elementResized', function () { return setLastTrigger('child resized'); }),
13988
+ editor.on('gridLayoutChanged', function (event) { return setLastTrigger("grid layout changed (".concat(event.reason, ")")); }),
12982
13989
  editor.on('elementDeleted', function () { return setLastTrigger('child removed'); }),
12983
13990
  editor.on('change', function () { return setLastTrigger(function (prev) { return prev; }); }),
12984
13991
  ];
@@ -13004,6 +14011,36 @@ var AutoLayoutDemo = function () {
13004
14011
  }
13005
14012
  }, [diagramState, targetId]);
13006
14013
  var targetElement = React.useMemo(function () { return diagramState === null || diagramState === void 0 ? void 0 : diagramState.elements.find(function (el) { return el.id === targetId; }); }, [diagramState, targetId]);
14014
+ var resolveElementWorldPosition = React.useCallback(function (elementId) {
14015
+ if (!diagramState)
14016
+ return null;
14017
+ var byId = new Map(diagramState.elements.map(function (element) { return [element.id, element]; }));
14018
+ var current = byId.get(elementId);
14019
+ if (!current)
14020
+ return null;
14021
+ var x = 0;
14022
+ var y = 0;
14023
+ while (current) {
14024
+ x += current.position.x;
14025
+ y += current.position.y;
14026
+ current = current.parentId ? byId.get(current.parentId) : undefined;
14027
+ }
14028
+ return { x: x, y: y };
14029
+ }, [diagramState]);
14030
+ var lockDemoContext = React.useMemo(function () {
14031
+ var _a;
14032
+ if (!diagramState)
14033
+ return null;
14034
+ var outer = diagramState.elements.find(function (el) { return el.id === lockComparisonContainerId; });
14035
+ var parent = diagramState.elements.find(function (el) { return el.id === lockParentId; });
14036
+ if (!outer || !parent)
14037
+ return null;
14038
+ return {
14039
+ outer: outer,
14040
+ parent: parent,
14041
+ isLocked: ((_a = parent.childElementInteraction) === null || _a === void 0 ? void 0 : _a.movable) === false,
14042
+ };
14043
+ }, [diagramState]);
13007
14044
  var targetOptions = React.useMemo(function () {
13008
14045
  var seen = new Set();
13009
14046
  var options = [];
@@ -13053,6 +14090,7 @@ var AutoLayoutDemo = function () {
13053
14090
  setChildMaxWidth((_s = (_q = layout === null || layout === void 0 ? void 0 : layout.childMaxWidth) !== null && _q !== void 0 ? _q : (_r = layout === null || layout === void 0 ? void 0 : layout.childFitMaxSize) === null || _r === void 0 ? void 0 : _r.width) !== null && _s !== void 0 ? _s : '');
13054
14091
  setChildMaxHeight((_v = (_t = layout === null || layout === void 0 ? void 0 : layout.childMaxHeight) !== null && _t !== void 0 ? _t : (_u = layout === null || layout === void 0 ? void 0 : layout.childFitMaxSize) === null || _u === void 0 ? void 0 : _u.height) !== null && _v !== void 0 ? _v : '');
13055
14092
  setGridTemplateText(serializeGridTemplate(layout === null || layout === void 0 ? void 0 : layout.gridTemplate));
14093
+ setGridChildWidthResizeEnabled(Boolean(layout === null || layout === void 0 ? void 0 : layout.gridChildWidthResizeEnabled));
13056
14094
  setLabelReservedMode((_x = (_w = layout === null || layout === void 0 ? void 0 : layout.labelReservedSpace) === null || _w === void 0 ? void 0 : _w.mode) !== null && _x !== void 0 ? _x : 'none');
13057
14095
  setLabelReservedFixedSize((_z = (_y = layout === null || layout === void 0 ? void 0 : layout.labelReservedSpace) === null || _y === void 0 ? void 0 : _y.size) !== null && _z !== void 0 ? _z : 32);
13058
14096
  setLabelReservedMinSize((_1 = (_0 = layout === null || layout === void 0 ? void 0 : layout.labelReservedSpace) === null || _0 === void 0 ? void 0 : _0.minSize) !== null && _1 !== void 0 ? _1 : '');
@@ -13106,7 +14144,7 @@ var AutoLayoutDemo = function () {
13106
14144
  : __assign(__assign(__assign({ mode: labelReservedMode, placement: 'top' }, (labelReservedMode === 'fixed' ? { size: labelReservedFixedSize } : {})), (labelReservedMinSize === '' ? {} : { minSize: labelReservedMinSize })), (labelReservedMaxSize === '' ? {} : { maxSize: labelReservedMaxSize }));
13107
14145
  var layout = mode === 'manual'
13108
14146
  ? { mode: 'manual' }
13109
- : __assign(__assign(__assign(__assign(__assign(__assign({ mode: mode, autoResize: autoResize, padding: padding, gap: gap, align: align !== null && align !== void 0 ? align : 'center', childFitMainAxis: childFitMainAxis, childFitCrossAxis: childFitCrossAxis }, (childMinWidth === '' ? {} : { childMinWidth: childMinWidth })), (childMinHeight === '' ? {} : { childMinHeight: childMinHeight })), (childMaxWidth === '' ? {} : { childMaxWidth: childMaxWidth })), (childMaxHeight === '' ? {} : { childMaxHeight: childMaxHeight })), (mode === 'grid' && parsedGridTemplate ? { gridTemplate: parsedGridTemplate } : {})), { labelReservedSpace: labelReservedSpace });
14147
+ : __assign(__assign(__assign(__assign(__assign(__assign(__assign({ mode: mode, autoResize: autoResize, padding: padding, gap: gap, align: align !== null && align !== void 0 ? align : 'center', childFitMainAxis: childFitMainAxis, childFitCrossAxis: childFitCrossAxis }, (childMinWidth === '' ? {} : { childMinWidth: childMinWidth })), (childMinHeight === '' ? {} : { childMinHeight: childMinHeight })), (childMaxWidth === '' ? {} : { childMaxWidth: childMaxWidth })), (childMaxHeight === '' ? {} : { childMaxHeight: childMaxHeight })), (mode === 'grid' && parsedGridTemplate ? { gridTemplate: parsedGridTemplate } : {})), (mode === 'grid' ? { gridChildWidthResizeEnabled: gridChildWidthResizeEnabled } : {})), { labelReservedSpace: labelReservedSpace });
13110
14148
  editor.setElementLayout(targetElement.id, layout);
13111
14149
  setLastTrigger("layout applied (".concat(mode, ")"));
13112
14150
  };
@@ -13149,21 +14187,29 @@ var AutoLayoutDemo = function () {
13149
14187
  setLastTrigger('child removed');
13150
14188
  }
13151
14189
  };
13152
- var handleFocusResizeLockChild = function () {
14190
+ var handleFocusLockTarget = function () {
13153
14191
  var editor = editorRef.current;
13154
14192
  if (!editor)
13155
14193
  return;
13156
- setTargetId('layout-grid');
13157
- editor.setSelection(['grid-b']);
13158
- setLastTrigger('focus resize-lock child');
14194
+ setTargetId(lockParentId);
14195
+ editor.setSelection([lockTargetId]);
14196
+ setLastTrigger(lockComparisonChildren ? 'focus locked child' : 'focus unlocked comparison child');
13159
14197
  };
13160
- var handleFocusResizeLockParent = function () {
14198
+ var handleFocusLockParent = function () {
13161
14199
  var editor = editorRef.current;
13162
14200
  if (!editor)
13163
14201
  return;
13164
- setTargetId('layout-grid');
13165
- editor.setSelection(['layout-grid']);
13166
- setLastTrigger('focus resize-lock parent');
14202
+ setTargetId(lockParentId);
14203
+ editor.setSelection([lockParentId]);
14204
+ setLastTrigger('focus lock parent');
14205
+ };
14206
+ var handleMoveLockTargetViaApi = function () {
14207
+ var editor = editorRef.current;
14208
+ var parentWorld = resolveElementWorldPosition(lockParentId);
14209
+ if (!editor || !lockDemoContext || !parentWorld)
14210
+ return;
14211
+ editor.moveElementTo(lockTargetId, parentWorld.x + 56, parentWorld.y + 18);
14212
+ setLastTrigger(lockDemoContext.isLocked ? 'locked child moved by api' : 'comparison child moved by api');
13167
14213
  };
13168
14214
  var alignmentLabel = mode === 'horizontal'
13169
14215
  ? 'Vertical align (top/center/bottom)'
@@ -13173,13 +14219,18 @@ var AutoLayoutDemo = function () {
13173
14219
  return (React.createElement("section", null,
13174
14220
  React.createElement("div", { style: { marginBottom: 12 } },
13175
14221
  React.createElement("h2", { style: { marginTop: 0, marginBottom: 4 } }, demo.title),
13176
- 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, and grid templates to validate v0.2.5 behavior."),
14222
+ 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
+ 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."),
13177
14224
  React.createElement("p", { style: { marginTop: 0, marginBottom: 0, fontSize: 13, color: '#333' } },
13178
- "Resize-lock check: select ",
13179
- React.createElement("code", null, "grid-b"),
13180
- " and drag a corner mostly downward. Width should stay stable while height changes. Then select ",
13181
- React.createElement("code", null, "layout-grid"),
13182
- " and drag a corner to verify parent width and height both follow pointer movement.")),
14225
+ "The ",
14226
+ 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.")),
13183
14234
  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 }),
13184
14235
  React.createElement("div", { style: { display: 'grid', gap: 12, marginBottom: 12 } },
13185
14236
  React.createElement("div", { style: { display: 'flex', flexWrap: 'wrap', gap: 12, alignItems: 'center' } },
@@ -13227,7 +14278,19 @@ var AutoLayoutDemo = function () {
13227
14278
  React.createElement("input", { id: "fit-max-width-input", type: "number", value: childMaxWidth, onChange: function (event) { return setChildMaxWidth(event.target.value === '' ? '' : Math.max(0, Number(event.target.value) || 0)); }, style: { width: 64, padding: '6px 8px' }, min: 0, placeholder: "w" }),
13228
14279
  React.createElement("input", { type: "number", value: childMaxHeight, onChange: function (event) { return setChildMaxHeight(event.target.value === '' ? '' : Math.max(0, Number(event.target.value) || 0)); }, style: { width: 64, padding: '6px 8px' }, min: 0, placeholder: "h" })),
13229
14280
  React.createElement("label", { htmlFor: "grid-template-input", style: { fontWeight: 600 } }, "Grid template"),
13230
- React.createElement("input", { id: "grid-template-input", type: "text", value: gridTemplateText, onChange: function (event) { return setGridTemplateText(event.target.value); }, style: { minWidth: 220, padding: '6px 8px' }, placeholder: "[[3],[1,2]] or [[1,1,1,1],[3,1]]", disabled: mode !== 'grid' }),
14281
+ React.createElement("input", { id: "grid-template-input", type: "text", value: gridTemplateText, onChange: function (event) { return setGridTemplateText(event.target.value); }, style: { minWidth: 220, padding: '6px 8px' }, placeholder: "[12,4,8] or [3,3,6,9]", disabled: mode !== 'grid' }),
14282
+ React.createElement("label", { htmlFor: "grid-child-width-resize-enabled", style: { fontWeight: 600 } }, "Grid child width resize"),
14283
+ React.createElement("label", { style: { display: 'inline-flex', alignItems: 'center', gap: 6 } },
14284
+ React.createElement("input", { id: "grid-child-width-resize-enabled", type: "checkbox", checked: gridChildWidthResizeEnabled, onChange: function (event) { return setGridChildWidthResizeEnabled(event.target.checked); }, disabled: mode !== 'grid' }),
14285
+ "Enable 12-unit resize on child width drag"),
14286
+ React.createElement("label", { htmlFor: "lock-comparison-child-drag", style: { fontWeight: 600 } }, "Lock comparison child drag"),
14287
+ React.createElement("label", { style: { display: 'inline-flex', alignItems: 'center', gap: 6 } },
14288
+ React.createElement("input", { id: "lock-comparison-child-drag", type: "checkbox", checked: lockComparisonChildren, onChange: function (event) {
14289
+ setLockComparisonChildren(event.target.checked);
14290
+ setTargetId(lockComparisonContainerId);
14291
+ setLastTrigger(event.target.checked ? 'comparison child drag locked' : 'comparison child drag unlocked');
14292
+ } }),
14293
+ "Reload parent-owned lock demo"),
13231
14294
  React.createElement("label", { htmlFor: "label-reserved-mode-select", style: { fontWeight: 600 } }, "Label lane"),
13232
14295
  React.createElement("select", { id: "label-reserved-mode-select", value: labelReservedMode, onChange: function (event) { return setLabelReservedMode(event.target.value); }, style: { padding: '6px 10px', minWidth: 120 }, disabled: mode === 'manual' },
13233
14296
  React.createElement("option", { value: "none" }, "None"),
@@ -13258,8 +14321,9 @@ var AutoLayoutDemo = function () {
13258
14321
  React.createElement("strong", null, lastTrigger)),
13259
14322
  React.createElement("button", { type: "button", onClick: function () { return handleSetLabelContent(shortLabel); }, style: { padding: '6px 10px' }, disabled: !targetElement || mode === 'manual' }, "Label short"),
13260
14323
  React.createElement("button", { type: "button", onClick: function () { return handleSetLabelContent(longLabel); }, style: { padding: '6px 10px' }, disabled: !targetElement || mode === 'manual' }, "Label long"),
13261
- React.createElement("button", { type: "button", onClick: handleFocusResizeLockChild, style: { padding: '6px 10px' } }, "Focus lock child"),
13262
- React.createElement("button", { type: "button", onClick: handleFocusResizeLockParent, style: { padding: '6px 10px' } }, "Focus lock parent")),
14324
+ React.createElement("button", { type: "button", onClick: handleFocusLockTarget, style: { padding: '6px 10px' } }, "Focus lock target"),
14325
+ React.createElement("button", { type: "button", onClick: handleFocusLockParent, style: { padding: '6px 10px' } }, "Focus lock parent"),
14326
+ React.createElement("button", { type: "button", onClick: handleMoveLockTargetViaApi, style: { padding: '6px 10px' } }, "Move lock target via API")),
13263
14327
  React.createElement("div", { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 } },
13264
14328
  React.createElement("div", null,
13265
14329
  React.createElement("div", { style: { fontWeight: 600, marginBottom: 6 } }, "Child order (axis or grid row-major)"),
@@ -13280,11 +14344,20 @@ var AutoLayoutDemo = function () {
13280
14344
  React.createElement("div", null,
13281
14345
  React.createElement("div", { style: { fontWeight: 600, marginBottom: 6 } }, "Scenario tips"),
13282
14346
  React.createElement("ul", { style: { marginTop: 0, paddingLeft: 18, fontSize: 13 } },
13283
- React.createElement("li", null, "Resize lock: select grid-b, drag corner diagonally; width should stay fixed while height changes."),
14347
+ 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
+ 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."),
14349
+ 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
+ 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
+ React.createElement("li", null, "Resize lock: with grid child width resize off, select grid-b and drag diagonally; width should stay fixed."),
14352
+ React.createElement("li", null, "Enable grid child width resize, then shrink a full-width grid child; it should snap smaller without flashing, and later siblings should keep their own widths."),
14353
+ React.createElement("li", null, "Enable grid child width resize, then grow a child; siblings on the right should keep their own widths and only move down when they no longer fit."),
14354
+ React.createElement("li", null, "Try dragging a left resize handle on the first child in a row; the child should still grow, but only to the right."),
14355
+ React.createElement("li", null, "Try dragging a grid child across a sibling; the row-major order should swap to match the drag position."),
14356
+ React.createElement("li", null, "Whenever enabled child width resize changes row allocation, the last-trigger badge should report grid layout changed."),
13284
14357
  React.createElement("li", null, "Parent resize: select layout-grid, drag corner; parent width and height should both track drag."),
13285
14358
  React.createElement("li", null, "Horizontal: try center vs bottom alignment and larger padding."),
13286
14359
  React.createElement("li", null, "Vertical: see parent grow taller as children stack."),
13287
- React.createElement("li", null, "Grid: apply templates like [[3],[1,2]] and [[1,1,1,1],[3,1]]."),
14360
+ React.createElement("li", null, "Grid: apply templates like [12,4,8] and [3,3,6,9]. Rows wrap automatically when the next item cannot fit."),
13288
14361
  React.createElement("li", null, "Auto resize: compare grow-only vs grow-shrink while adding/removing children."),
13289
14362
  React.createElement("li", null, "Label lane: compare none/fixed/flexible and observe children start below the reserved lane."),
13290
14363
  React.createElement("li", null, "Fit main-axis distribute fills inner layout space across siblings."),
@@ -13716,10 +14789,15 @@ var TextLayoutDemo = function () {
13716
14789
  var selectedText = diagramState === null || diagramState === void 0 ? void 0 : diagramState.texts.find(function (text) { return text.id === selectedTextId; });
13717
14790
  var selectedDisplayContent = (_b = (_a = selectedText === null || selectedText === void 0 ? void 0 : selectedText.displayContent) !== null && _a !== void 0 ? _a : selectedText === null || selectedText === void 0 ? void 0 : selectedText.content) !== null && _b !== void 0 ? _b : '';
13718
14791
  var ownerElement = diagramState === null || diagramState === void 0 ? void 0 : diagramState.elements.find(function (element) { return element.id === textDemoOwnerId; });
14792
+ var selectedInteraction = selectedText === null || selectedText === void 0 ? void 0 : selectedText.interaction;
14793
+ var getInteractionForTarget = function (nextTarget) {
14794
+ return nextTarget === 'owned' ? textDemoOwnedInteraction : textDemoFloatingInteraction;
14795
+ };
13719
14796
  var applyLayoutToTarget = function (nextTarget, nextLayout) {
13720
14797
  var editor = editorRef.current;
13721
14798
  if (!editor)
13722
14799
  return;
14800
+ var interaction = getInteractionForTarget(nextTarget);
13723
14801
  if (nextTarget === 'owned') {
13724
14802
  editor.removeText(textDemoOwnedTextId);
13725
14803
  editor.addText({
@@ -13727,6 +14805,7 @@ var TextLayoutDemo = function () {
13727
14805
  content: textDemoLongSample,
13728
14806
  ownerId: textDemoOwnerId,
13729
14807
  position: { x: 12, y: 12 },
14808
+ interaction: interaction,
13730
14809
  layout: nextLayout,
13731
14810
  });
13732
14811
  editor.setSelection([textDemoOwnedTextId]);
@@ -13737,6 +14816,7 @@ var TextLayoutDemo = function () {
13737
14816
  id: textDemoFloatingTextId,
13738
14817
  content: textDemoLongSample,
13739
14818
  position: { x: 470, y: 120 },
14819
+ interaction: interaction,
13740
14820
  layout: nextLayout,
13741
14821
  });
13742
14822
  editor.setSelection([textDemoFloatingTextId]);
@@ -13804,7 +14884,8 @@ var TextLayoutDemo = function () {
13804
14884
  return (React.createElement("section", null,
13805
14885
  React.createElement("div", { style: { marginBottom: 12 } },
13806
14886
  React.createElement("h2", { style: { marginTop: 0, marginBottom: 4 } }, demo.title),
13807
- React.createElement("p", { style: { marginTop: 0 } }, "Full text content is preserved in state. Overflow and ellipsis settings only change visual output (`displayContent`) for rendering.")),
14887
+ React.createElement("p", { style: { marginTop: 0 } }, "Full text content is preserved in state. Overflow and ellipsis settings only change visual output (`displayContent`) for rendering."),
14888
+ React.createElement("p", { style: { marginTop: 0, marginBottom: 0, fontSize: 13 } }, "Owned text is fixed and read-only. Floating text remains draggable and editable. Try drag and double-click on each label to compare built-in interaction policy behavior.")),
13808
14889
  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 }),
13809
14890
  React.createElement("div", { style: { display: 'grid', gap: 10, marginBottom: 12 } },
13810
14891
  React.createElement("div", { style: { display: 'flex', flexWrap: 'wrap', gap: 10, alignItems: 'center' } },
@@ -13892,7 +14973,12 @@ var TextLayoutDemo = function () {
13892
14973
  ' ',
13893
14974
  Number.isFinite(selectedWorldX) && Number.isFinite(selectedWorldY)
13894
14975
  ? "".concat(selectedWorldX.toFixed(1), ", ").concat(selectedWorldY.toFixed(1))
13895
- : 'n/a')),
14976
+ : 'n/a'),
14977
+ React.createElement("div", null,
14978
+ "interaction: movable=",
14979
+ (selectedInteraction === null || selectedInteraction === void 0 ? void 0 : selectedInteraction.movable) === false ? 'false' : 'true',
14980
+ " | editable=",
14981
+ (selectedInteraction === null || selectedInteraction === void 0 ? void 0 : selectedInteraction.editable) === false ? 'false' : 'true')),
13896
14982
  React.createElement("div", { style: { display: 'grid', gap: 6 } },
13897
14983
  React.createElement("div", { style: { fontSize: 12 } },
13898
14984
  React.createElement("strong", null, "Canonical content:"),
@@ -13962,6 +15048,311 @@ var ObstacleRoutingDemo = function () {
13962
15048
  "Enable redraw refresh on two-endpoint change")) }));
13963
15049
  };
13964
15050
 
15051
+ var offsetAnchorShapes = __spreadArray(__spreadArray([], baseElementShapes, true), [
15052
+ {
15053
+ id: 'offset-anchor-ellipse',
15054
+ kind: 'ellipse',
15055
+ style: {
15056
+ fill: '#eef8ff',
15057
+ stroke: '#2563eb',
15058
+ strokeWidth: 2,
15059
+ },
15060
+ },
15061
+ ], false);
15062
+ var createOffsetAnchorAvoidanceState = function () { return ({
15063
+ elements: [
15064
+ {
15065
+ id: 'offset-sibling-parent',
15066
+ position: { x: 40, y: 110 },
15067
+ size: { width: 520, height: 250 },
15068
+ shapeId: 'panel',
15069
+ style: { fill: '#faf7ef' },
15070
+ },
15071
+ {
15072
+ id: 'offset-sibling-a',
15073
+ position: { x: 60, y: 78 },
15074
+ size: { width: 130, height: 96 },
15075
+ shapeId: 'offset-anchor-ellipse',
15076
+ parentId: 'offset-sibling-parent',
15077
+ portMovement: { moveMode: 'anchors', anchorConstraint: { preset: 'cardinal' } },
15078
+ },
15079
+ {
15080
+ id: 'offset-sibling-b',
15081
+ position: { x: 320, y: 78 },
15082
+ size: { width: 130, height: 96 },
15083
+ shapeId: 'offset-anchor-ellipse',
15084
+ parentId: 'offset-sibling-parent',
15085
+ portMovement: { moveMode: 'anchors', anchorConstraint: { preset: 'cardinal' } },
15086
+ },
15087
+ {
15088
+ id: 'offset-direction-parent',
15089
+ position: { x: 620, y: 110 },
15090
+ size: { width: 330, height: 250 },
15091
+ shapeId: 'offset-anchor-ellipse',
15092
+ portMovement: { moveMode: 'anchors', anchorConstraint: { preset: 'cardinal' } },
15093
+ },
15094
+ {
15095
+ id: 'offset-direction-child',
15096
+ position: { x: 48, y: 74 },
15097
+ size: { width: 128, height: 92 },
15098
+ shapeId: 'default',
15099
+ parentId: 'offset-direction-parent',
15100
+ portMovement: { moveMode: 'anchors', anchorConstraint: { preset: 'cardinal' } },
15101
+ },
15102
+ {
15103
+ id: 'offset-direction-sibling',
15104
+ position: { x: 190, y: 126 },
15105
+ size: { width: 96, height: 70 },
15106
+ shapeId: 'default',
15107
+ parentId: 'offset-direction-parent',
15108
+ style: { fill: '#fff6e8', stroke: '#b45309', strokeWidth: 2 },
15109
+ },
15110
+ ],
15111
+ ports: [
15112
+ {
15113
+ id: 'offset-sibling-a-port',
15114
+ elementId: 'offset-sibling-a',
15115
+ position: { x: 0, y: 48 },
15116
+ shapeId: 'port-dark',
15117
+ anchorCenter: true,
15118
+ currentAnchorId: 'left',
15119
+ moveMode: 'border',
15120
+ externalLinkAttachPoint: { x: 0, y: 24 },
15121
+ },
15122
+ {
15123
+ id: 'offset-sibling-b-port',
15124
+ elementId: 'offset-sibling-b',
15125
+ position: { x: 130, y: 48 },
15126
+ shapeId: 'port-dark',
15127
+ anchorCenter: true,
15128
+ currentAnchorId: 'right',
15129
+ moveMode: 'border',
15130
+ externalLinkAttachPoint: { x: 0, y: 24 },
15131
+ },
15132
+ {
15133
+ id: 'offset-parent-port',
15134
+ elementId: 'offset-direction-parent',
15135
+ position: { x: 18, y: 125 },
15136
+ shapeId: 'port-circle',
15137
+ anchorCenter: true,
15138
+ currentAnchorId: 'left',
15139
+ moveMode: 'border',
15140
+ externalLinkAttachPoint: { x: 0, y: 18 },
15141
+ internalLinkAttachPoint: { x: 0, y: -18 },
15142
+ },
15143
+ {
15144
+ id: 'offset-child-port',
15145
+ elementId: 'offset-direction-child',
15146
+ position: { x: 128, y: 46 },
15147
+ shapeId: 'port-circle',
15148
+ anchorCenter: true,
15149
+ currentAnchorId: 'right',
15150
+ moveMode: 'border',
15151
+ externalLinkAttachPoint: { x: 0, y: 18 },
15152
+ internalLinkAttachPoint: { x: 0, y: -18 },
15153
+ },
15154
+ ],
15155
+ links: [
15156
+ {
15157
+ id: 'offset-sibling-link',
15158
+ sourcePortId: 'offset-sibling-a-port',
15159
+ targetPortId: 'offset-sibling-b-port',
15160
+ points: [],
15161
+ routing: 'auto',
15162
+ },
15163
+ {
15164
+ id: 'offset-parent-child-link',
15165
+ sourcePortId: 'offset-parent-port',
15166
+ targetPortId: 'offset-child-port',
15167
+ points: [],
15168
+ routing: 'auto',
15169
+ },
15170
+ {
15171
+ id: 'offset-child-parent-link',
15172
+ sourcePortId: 'offset-child-port',
15173
+ targetPortId: 'offset-parent-port',
15174
+ points: [],
15175
+ routing: 'auto',
15176
+ },
15177
+ ],
15178
+ texts: [
15179
+ {
15180
+ id: 'offset-anchor-intro',
15181
+ content: 'Offset attach anchors now keep endpoint hosts forbidden during auto routing. Inspect that routes exit from projected border sides instead of cutting through the source or target host interior.',
15182
+ position: { x: 40, y: 28 },
15183
+ },
15184
+ {
15185
+ id: 'offset-sibling-label',
15186
+ content: 'Scenario A: sibling children use external attach points offset beyond left/right edges.',
15187
+ position: { x: 52, y: 82 },
15188
+ },
15189
+ {
15190
+ id: 'offset-direction-label',
15191
+ content: 'Scenario B: parent/child links reuse the same offset anchors but resolve internal vs external semantics by direction.',
15192
+ position: { x: 620, y: 82 },
15193
+ },
15194
+ {
15195
+ id: 'offset-sibling-a-text',
15196
+ content: 'Child A\nexternal offset 24',
15197
+ ownerId: 'offset-sibling-a',
15198
+ position: { x: 14, y: -20 },
15199
+ },
15200
+ {
15201
+ id: 'offset-sibling-b-text',
15202
+ content: 'Child B\nexternal offset 24',
15203
+ ownerId: 'offset-sibling-b',
15204
+ position: { x: 14, y: -20 },
15205
+ },
15206
+ {
15207
+ id: 'offset-direction-parent-text',
15208
+ content: 'Parent port\ninternal 18 / external 18',
15209
+ ownerId: 'offset-direction-parent',
15210
+ position: { x: 48, y: -20 },
15211
+ },
15212
+ {
15213
+ id: 'offset-direction-child-text',
15214
+ content: 'Child port\nexternal 18 / internal 18',
15215
+ ownerId: 'offset-direction-child',
15216
+ position: { x: 6, y: -18 },
15217
+ },
15218
+ {
15219
+ id: 'offset-direction-links-text',
15220
+ content: 'Blue links: parent→child and child→parent should keep the host border side semantics even with offset attach coordinates.',
15221
+ position: { x: 620, y: 378 },
15222
+ },
15223
+ ],
15224
+ }); };
15225
+ var rerouteAllAction = {
15226
+ id: 'offset-reroute-links',
15227
+ label: 'Reroute All Links',
15228
+ run: function (editor) {
15229
+ editor.rerouteAllLinks();
15230
+ },
15231
+ };
15232
+ var shiftTargetsAction = {
15233
+ id: 'offset-shift-targets',
15234
+ label: 'Shift targets + reroute',
15235
+ run: function (editor) {
15236
+ editor.moveElementTo('offset-sibling-b', 320, 96);
15237
+ editor.moveElementTo('offset-direction-child', 74, 96);
15238
+ editor.rerouteAllLinks();
15239
+ },
15240
+ };
15241
+ var offsetAnchorAvoidanceDemoConfig = {
15242
+ id: 'offset-anchor-avoidance',
15243
+ title: 'Offset Anchor Avoidance',
15244
+ description: 'Visual QA for projected-boundary-equivalent offset attach anchors that must still keep endpoint host interiors forbidden.',
15245
+ createState: createOffsetAnchorAvoidanceState,
15246
+ elementShapes: offsetAnchorShapes,
15247
+ portShapes: basePortShapes,
15248
+ defaultElementShapeId: 'default',
15249
+ defaultPortShapeId: 'port-circle',
15250
+ actions: [rerouteAllAction, shiftTargetsAction],
15251
+ };
15252
+
15253
+ var OffsetAnchorAvoidanceDemo = function () { return (React.createElement(SimpleDemo, { demo: offsetAnchorAvoidanceDemoConfig, beforeStage: React.createElement("div", { style: {
15254
+ marginBottom: 12,
15255
+ padding: '10px 12px',
15256
+ borderRadius: 8,
15257
+ border: '1px solid #2d2d2d',
15258
+ background: '#f4f4f4',
15259
+ } },
15260
+ React.createElement("strong", null, "Visual checks"),
15261
+ React.createElement("ul", { style: { margin: '6px 0 0 16px' } },
15262
+ React.createElement("li", null, "Sibling link should route around both child interiors even though attach coordinates are offset outside the host edges."),
15263
+ React.createElement("li", null, "`parent\u2192child` should use the parent's internal side and the child's external side."),
15264
+ React.createElement("li", null, "`child\u2192parent` should invert the same endpoint semantics without crossing either endpoint host interior."),
15265
+ React.createElement("li", null, "Use `Shift targets + reroute` and `Reroute All Links` to verify stable behavior after layout changes."))) })); };
15266
+
15267
+ var createZoomToFitElementsState = function () { return ({
15268
+ elements: [
15269
+ {
15270
+ id: 'fit-node-a',
15271
+ position: { x: 40, y: 60 },
15272
+ size: { width: 140, height: 90 },
15273
+ shapeId: 'default',
15274
+ style: { fill: '#eef6ff', stroke: '#1d4ed8', strokeWidth: 2 },
15275
+ },
15276
+ {
15277
+ id: 'fit-node-b',
15278
+ position: { x: 760, y: 120 },
15279
+ size: { width: 170, height: 110 },
15280
+ shapeId: 'panel',
15281
+ style: { fill: '#fef3c7', stroke: '#b45309', strokeWidth: 2 },
15282
+ },
15283
+ {
15284
+ id: 'fit-node-c',
15285
+ position: { x: 140, y: 420 },
15286
+ size: { width: 220, height: 120 },
15287
+ shapeId: 'default',
15288
+ style: { fill: '#ecfdf5', stroke: '#047857', strokeWidth: 2 },
15289
+ },
15290
+ {
15291
+ id: 'fit-node-d',
15292
+ position: { x: 860, y: 430 },
15293
+ size: { width: 150, height: 90 },
15294
+ shapeId: 'default',
15295
+ style: { fill: '#f5f3ff', stroke: '#6d28d9', strokeWidth: 2 },
15296
+ },
15297
+ ],
15298
+ ports: [],
15299
+ links: [],
15300
+ texts: [
15301
+ {
15302
+ id: 'fit-text-intro',
15303
+ content: 'Use actions to spread nodes and run the zoom-to-fit viewport command.',
15304
+ position: { x: 40, y: 24 },
15305
+ },
15306
+ ],
15307
+ }); };
15308
+ var zoomFitAction = {
15309
+ id: 'fit-zoom-default',
15310
+ label: 'Run Zoom-To-Fit',
15311
+ run: function (editor) {
15312
+ editor.zoomToFitElements();
15313
+ },
15314
+ };
15315
+ var zoomFitPaddingAction = {
15316
+ id: 'fit-zoom-padding',
15317
+ label: 'Run Zoom-To-Fit (Padding 48)',
15318
+ run: function (editor) {
15319
+ editor.zoomToFitElements({ padding: 48 });
15320
+ },
15321
+ };
15322
+ var spreadSceneAction = {
15323
+ id: 'fit-spread-scene',
15324
+ label: 'Spread Scene',
15325
+ run: function (editor) {
15326
+ editor.moveElementTo('fit-node-b', 880, 80);
15327
+ editor.moveElementTo('fit-node-d', 980, 500);
15328
+ editor.moveElementTo('fit-node-c', 80, 520);
15329
+ },
15330
+ };
15331
+ var zoomToFitElementsDemoConfig = {
15332
+ id: 'zoom-to-fit-elements',
15333
+ title: 'Zoom To Fit Elements',
15334
+ description: 'Calls a viewport command that zooms and centers so all elements are visible.',
15335
+ createState: createZoomToFitElementsState,
15336
+ elementShapes: baseElementShapes,
15337
+ portShapes: basePortShapes,
15338
+ defaultElementShapeId: 'default',
15339
+ defaultPortShapeId: 'port-circle',
15340
+ actions: [zoomFitAction, zoomFitPaddingAction, spreadSceneAction],
15341
+ };
15342
+
15343
+ var ZoomToFitElementsDemo = function () { return (React.createElement(SimpleDemo, { demo: zoomToFitElementsDemoConfig, beforeStage: (React.createElement("div", { style: {
15344
+ marginBottom: 12,
15345
+ padding: '10px 12px',
15346
+ borderRadius: 8,
15347
+ border: '1px solid #2d2d2d',
15348
+ background: '#f4f4f4',
15349
+ } },
15350
+ React.createElement("strong", null, "Visual checks"),
15351
+ React.createElement("ul", { style: { margin: '6px 0 0 16px' } },
15352
+ React.createElement("li", null, "Click `Run Zoom-To-Fit` and ensure every node is visible and centered."),
15353
+ React.createElement("li", null, "Run `Spread Scene` then fit again to verify viewport recomputes from the updated layout."),
15354
+ React.createElement("li", null, "Use `Run Zoom-To-Fit (Padding 48)` to confirm optional padding keeps extra breathing room around content.")))) })); };
15355
+
13965
15356
  var initialPayloads = {
13966
15357
  elementDeleted: null,
13967
15358
  portDeleted: null,
@@ -15039,6 +16430,18 @@ var demoTabs = [
15039
16430
  description: obstacleRoutingDemoConfig.description,
15040
16431
  Component: ObstacleRoutingDemo,
15041
16432
  },
16433
+ {
16434
+ id: offsetAnchorAvoidanceDemoConfig.id,
16435
+ title: offsetAnchorAvoidanceDemoConfig.title,
16436
+ description: offsetAnchorAvoidanceDemoConfig.description,
16437
+ Component: OffsetAnchorAvoidanceDemo,
16438
+ },
16439
+ {
16440
+ id: zoomToFitElementsDemoConfig.id,
16441
+ title: zoomToFitElementsDemoConfig.title,
16442
+ description: zoomToFitElementsDemoConfig.description,
16443
+ Component: ZoomToFitElementsDemo,
16444
+ },
15042
16445
  {
15043
16446
  id: linkBendHandlesDemoConfig.id,
15044
16447
  title: linkBendHandlesDemoConfig.title,