orcasvn-react-diagrams 0.2.5 → 0.2.6

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 (53) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +15 -34
  3. package/ai/api-contract.json +38 -1
  4. package/ai/manifest.json +1 -1
  5. package/dist/cjs/examples.js +1252 -113
  6. package/dist/cjs/index.js +876 -81
  7. package/dist/cjs/types/api/createDiagramEditor.d.ts +2 -1
  8. package/dist/cjs/types/api/types.d.ts +26 -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/offsetAnchorAvoidanceDemo.d.ts +4 -0
  12. package/dist/cjs/types/displaybox/demos/textDemo.d.ts +3 -0
  13. package/dist/cjs/types/displaybox/demos/zoomToFitElementsDemo.d.ts +4 -0
  14. package/dist/cjs/types/engine/AutoLayoutService.d.ts +44 -1
  15. package/dist/cjs/types/engine/DiagramEngine.d.ts +12 -0
  16. package/dist/cjs/types/engine/LinkRoutingService.d.ts +1 -0
  17. package/dist/cjs/types/models/TextModel.d.ts +1 -0
  18. package/dist/cjs/types/renderer/konva/KonvaInteraction.d.ts +2 -0
  19. package/dist/esm/examples.js +1252 -113
  20. package/dist/esm/examples.js.map +1 -1
  21. package/dist/esm/index.js +876 -81
  22. package/dist/esm/index.js.map +1 -1
  23. package/dist/esm/types/api/createDiagramEditor.d.ts +2 -1
  24. package/dist/esm/types/api/types.d.ts +26 -1
  25. package/dist/esm/types/displaybox/demos/OffsetAnchorAvoidanceDemoTab.d.ts +3 -0
  26. package/dist/esm/types/displaybox/demos/ZoomToFitElementsDemoTab.d.ts +3 -0
  27. package/dist/esm/types/displaybox/demos/offsetAnchorAvoidanceDemo.d.ts +4 -0
  28. package/dist/esm/types/displaybox/demos/textDemo.d.ts +3 -0
  29. package/dist/esm/types/displaybox/demos/zoomToFitElementsDemo.d.ts +4 -0
  30. package/dist/esm/types/engine/AutoLayoutService.d.ts +44 -1
  31. package/dist/esm/types/engine/DiagramEngine.d.ts +12 -0
  32. package/dist/esm/types/engine/LinkRoutingService.d.ts +1 -0
  33. package/dist/esm/types/models/TextModel.d.ts +1 -0
  34. package/dist/esm/types/renderer/konva/KonvaInteraction.d.ts +2 -0
  35. package/dist/examples.d.ts +27 -1
  36. package/dist/index.d.ts +29 -2
  37. package/docs/API_CONTRACT.md +38 -3
  38. package/docs/CAPABILITIES.md +3 -0
  39. package/docs/COMMANDS_EVENTS.md +8 -0
  40. package/docs/DOCUMENTATION_WORKFLOW.md +2 -1
  41. package/docs/INTEGRATION_PLAYBOOK.md +3 -0
  42. package/docs/STATE_INVARIANTS.md +4 -0
  43. package/package.json +1 -1
  44. package/src/displaybox/demos/AutoLayoutDemoTab.tsx +337 -316
  45. package/src/displaybox/demos/EngineEventsDemoTab.tsx +12 -11
  46. package/src/displaybox/demos/OffsetAnchorAvoidanceDemoTab.tsx +30 -0
  47. package/src/displaybox/demos/TextLayoutDemoTab.tsx +18 -1
  48. package/src/displaybox/demos/ZoomToFitElementsDemoTab.tsx +29 -0
  49. package/src/displaybox/demos/autoLayoutDemo.ts +74 -73
  50. package/src/displaybox/demos/index.tsx +80 -64
  51. package/src/displaybox/demos/offsetAnchorAvoidanceDemo.ts +211 -0
  52. package/src/displaybox/demos/textDemo.ts +6 -2
  53. 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;
@@ -992,6 +992,8 @@ var textDemoOwnerId = 'text-layout-owner';
992
992
  var textDemoOwnedTextId = 'text-owned-overflow';
993
993
  var textDemoFloatingTextId = 'text-floating-overflow';
994
994
  var textDemoLongSample = 'Long diagram label: middle ellipsis should keep the beginning and end visible while preserving the full canonical content in model state.';
995
+ var textDemoOwnedInteraction = { movable: false, editable: false };
996
+ var textDemoFloatingInteraction = { movable: true, editable: true };
995
997
  var createTextOwnershipState = function () { return ({
996
998
  elements: [
997
999
  {
@@ -1009,6 +1011,7 @@ var createTextOwnershipState = function () { return ({
1009
1011
  content: textDemoLongSample,
1010
1012
  position: { x: 12, y: 12 },
1011
1013
  ownerId: textDemoOwnerId,
1014
+ interaction: textDemoOwnedInteraction,
1012
1015
  layout: {
1013
1016
  boundsMode: 'owner-width',
1014
1017
  wrap: 'none',
@@ -1020,6 +1023,7 @@ var createTextOwnershipState = function () { return ({
1020
1023
  id: textDemoFloatingTextId,
1021
1024
  content: textDemoLongSample,
1022
1025
  position: { x: 470, y: 120 },
1026
+ interaction: textDemoFloatingInteraction,
1023
1027
  layout: {
1024
1028
  boundsMode: 'fixed',
1025
1029
  fixedSize: { width: 240, height: 90 },
@@ -1034,7 +1038,7 @@ var createTextOwnershipState = function () { return ({
1034
1038
  var textDemoConfig = ({
1035
1039
  id: 'text',
1036
1040
  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.',
1041
+ 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
1042
  createState: createTextOwnershipState,
1039
1043
  elementShapes: baseElementShapes,
1040
1044
  portShapes: basePortShapes,
@@ -1280,7 +1284,8 @@ var createAutoLayoutState = function () { return ({
1280
1284
  gap: 10,
1281
1285
  align: 'center',
1282
1286
  autoResize: 'grow-shrink',
1283
- gridTemplate: [[3], [1, 2]],
1287
+ gridTemplate: [12, 4, 8],
1288
+ gridChildWidthResizeEnabled: false,
1284
1289
  childMinWidth: 24,
1285
1290
  childMinHeight: 18,
1286
1291
  },
@@ -1350,7 +1355,7 @@ var createAutoLayoutState = function () { return ({
1350
1355
  { id: 'label-col-c', content: 'col-c', position: { x: 6, y: -14 }, ownerId: 'col-c' },
1351
1356
  {
1352
1357
  id: 'label-layout-grid',
1353
- content: 'Grid template [[3],[1,2]]',
1358
+ content: 'Grid template [12,4,8]',
1354
1359
  position: { x: 8, y: 6 },
1355
1360
  ownerId: 'layout-grid',
1356
1361
  layout: { boundsMode: 'owner-width', wrap: 'word', overflow: 'clip', padding: 0 },
@@ -3393,7 +3398,7 @@ var addLinksAction = {
3393
3398
  });
3394
3399
  },
3395
3400
  };
3396
- var rerouteAllAction = {
3401
+ var rerouteAllAction$1 = {
3397
3402
  id: 'reroute-links',
3398
3403
  label: 'Reroute All Links',
3399
3404
  run: function (editor) {
@@ -3409,7 +3414,7 @@ var obstacleRoutingDemoConfig = {
3409
3414
  portShapes: basePortShapes,
3410
3415
  defaultElementShapeId: 'default',
3411
3416
  defaultPortShapeId: 'port-circle',
3412
- actions: [addLinksAction, rerouteAllAction],
3417
+ actions: [addLinksAction, rerouteAllAction$1],
3413
3418
  };
3414
3419
 
3415
3420
  var createLinkBendHandlesState = function () { return ({
@@ -4387,6 +4392,7 @@ var TextModel = /** @class */ (function () {
4387
4392
  this.size = data.size ? __assign({}, data.size) : undefined;
4388
4393
  this.style = data.style;
4389
4394
  this.ownerId = (_a = data.ownerId) !== null && _a !== void 0 ? _a : null;
4395
+ this.interaction = data.interaction ? __assign({}, data.interaction) : undefined;
4390
4396
  this.layout = data.layout ? __assign({}, data.layout) : undefined;
4391
4397
  this.displayContent = (_b = data.displayContent) !== null && _b !== void 0 ? _b : data.content;
4392
4398
  this.displayOffset = data.displayOffset ? __assign({}, data.displayOffset) : undefined;
@@ -4423,6 +4429,7 @@ var TextModel = /** @class */ (function () {
4423
4429
  size: this.size ? __assign({}, this.size) : undefined,
4424
4430
  style: this.style,
4425
4431
  ownerId: this.ownerId,
4432
+ interaction: this.interaction ? __assign({}, this.interaction) : undefined,
4426
4433
  layout: this.layout ? __assign({}, this.layout) : undefined,
4427
4434
  displayContent: (_a = this.displayContent) !== null && _a !== void 0 ? _a : this.content,
4428
4435
  displayOffset: this.displayOffset ? __assign({}, this.displayOffset) : undefined,
@@ -4437,7 +4444,7 @@ var distance = function (a, b) {
4437
4444
  var dy = a.y - b.y;
4438
4445
  return Math.sqrt(dx * dx + dy * dy);
4439
4446
  };
4440
- var clamp = function (value, min, max) {
4447
+ var clamp$1 = function (value, min, max) {
4441
4448
  if (value < min)
4442
4449
  return min;
4443
4450
  if (value > max)
@@ -5685,6 +5692,7 @@ var TextLayoutService = /** @class */ (function () {
5685
5692
  return TextLayoutService;
5686
5693
  }());
5687
5694
 
5695
+ var GRID_ROW_UNITS = 12;
5688
5696
  var AutoLayoutService = /** @class */ (function () {
5689
5697
  function AutoLayoutService(config) {
5690
5698
  this.model = config.model;
@@ -5699,11 +5707,24 @@ var AutoLayoutService = /** @class */ (function () {
5699
5707
  if (!layout || layout.mode === 'manual')
5700
5708
  return { patches: [], movedPortIds: [] };
5701
5709
  var preserveParentSize = Boolean(options === null || options === void 0 ? void 0 : options.preserveParentSize);
5710
+ var preserveParentWidth = preserveParentSize || Boolean(options === null || options === void 0 ? void 0 : options.preserveParentWidth);
5711
+ var preserveParentHeight = preserveParentSize || Boolean(options === null || options === void 0 ? void 0 : options.preserveParentHeight);
5702
5712
  var padding = this.resolveLayoutPadding(layout);
5703
5713
  var labelReservedTopLane = this.resolveLabelReservedTopLane(parentId, layout);
5704
5714
  var autoResize = this.resolveAutoResizeMode(layout);
5705
5715
  var children = this.model.getChildren(parentId);
5706
5716
  if (children.length === 0) {
5717
+ if (preserveParentWidth || preserveParentHeight) {
5718
+ var targetWidth_1 = preserveParentWidth ? parent.size.width : Math.max(0, Math.round(padding.x * 2));
5719
+ var targetHeight_1 = preserveParentHeight
5720
+ ? parent.size.height
5721
+ : Math.max(0, Math.round(padding.y * 2 + labelReservedTopLane));
5722
+ if (parent.size.width === targetWidth_1 && parent.size.height === targetHeight_1) {
5723
+ return { patches: [], movedPortIds: [] };
5724
+ }
5725
+ var resizePatches_1 = this.commandQueue.run(createResizeElementCommand(parentId, { width: targetWidth_1, height: targetHeight_1 }), this.model);
5726
+ return { patches: resizePatches_1, movedPortIds: __spreadArray([], parent.portIds, true) };
5727
+ }
5707
5728
  if (preserveParentSize) {
5708
5729
  return { patches: [], movedPortIds: [] };
5709
5730
  }
@@ -5718,9 +5739,17 @@ var AutoLayoutService = /** @class */ (function () {
5718
5739
  return { patches: resizePatches, movedPortIds: __spreadArray([], parent.portIds, true) };
5719
5740
  }
5720
5741
  if (layout.mode === 'grid') {
5721
- return this.applyGridLayoutForParent(parentId, parent, children, preserveParentSize);
5742
+ return this.applyGridLayoutForParent(parentId, parent, children, {
5743
+ preserveParentSize: preserveParentSize,
5744
+ preserveParentWidth: preserveParentWidth,
5745
+ preserveParentHeight: preserveParentHeight,
5746
+ });
5722
5747
  }
5723
- return this.applyAxisLayoutForParent(parentId, parent, children, layout.mode, preserveParentSize);
5748
+ return this.applyAxisLayoutForParent(parentId, parent, children, layout.mode, {
5749
+ preserveParentSize: preserveParentSize,
5750
+ preserveParentWidth: preserveParentWidth,
5751
+ preserveParentHeight: preserveParentHeight,
5752
+ });
5724
5753
  };
5725
5754
  AutoLayoutService.prototype.applyLayoutCascade = function (startParentId) {
5726
5755
  var _a;
@@ -5763,11 +5792,102 @@ var AutoLayoutService = /** @class */ (function () {
5763
5792
  });
5764
5793
  return { patches: patches, movedPortIds: Array.from(new Set(movedPortIds)) };
5765
5794
  };
5766
- AutoLayoutService.prototype.applyAxisLayoutForParent = function (parentId, parent, children, axis, preserveParentSize) {
5795
+ AutoLayoutService.prototype.describeGridRows = function (parentId) {
5796
+ var _a;
5797
+ var parent = this.model.getElement(parentId);
5798
+ if (!parent || ((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.mode) !== 'grid')
5799
+ return [];
5800
+ return this.resolveAssignedGridRows(parent).map(function (row) { return ({ childIds: __spreadArray([], row.childIds, true) }); });
5801
+ };
5802
+ AutoLayoutService.prototype.describeGridSlotState = function (parentId) {
5803
+ var _this = this;
5804
+ var _a;
5805
+ var parent = this.model.getElement(parentId);
5806
+ if (!parent || ((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.mode) !== 'grid')
5807
+ return null;
5808
+ var assignedRows = this.resolveAssignedGridRows(parent);
5809
+ return {
5810
+ orderedChildIds: assignedRows.flatMap(function (row) { return row.childIds; }),
5811
+ slotWeights: assignedRows.flatMap(function (row) { return row.weights.slice(0, row.childIds.length).map(function (weight) { return _this.clampGridUnits(weight); }); }),
5812
+ };
5813
+ };
5814
+ AutoLayoutService.prototype.resolveGridReorderedLayout = function (parentId, previousState) {
5815
+ var _this = this;
5816
+ var _a;
5817
+ var parent = this.model.getElement(parentId);
5818
+ if (!parent || ((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.mode) !== 'grid' || !parent.layout)
5819
+ return null;
5820
+ var sortedChildren = this.sortGridChildrenForLayout(this.model.getChildren(parentId));
5821
+ var orderedChildIds = sortedChildren.map(function (child) { return child.id; });
5822
+ if (orderedChildIds.length === previousState.orderedChildIds.length &&
5823
+ orderedChildIds.every(function (childId, index) { return childId === previousState.orderedChildIds[index]; })) {
5824
+ return null;
5825
+ }
5826
+ var weightByChildId = new Map();
5827
+ previousState.orderedChildIds.forEach(function (childId, index) {
5828
+ var _a;
5829
+ weightByChildId.set(childId, _this.clampGridUnits((_a = previousState.slotWeights[index]) !== null && _a !== void 0 ? _a : GRID_ROW_UNITS));
5830
+ });
5831
+ var reorderedTemplate = orderedChildIds.map(function (childId) { var _a; return (_a = weightByChildId.get(childId)) !== null && _a !== void 0 ? _a : GRID_ROW_UNITS; });
5832
+ return __assign(__assign({}, parent.layout), { gridTemplate: reorderedTemplate });
5833
+ };
5834
+ AutoLayoutService.prototype.resolveGridChildResizeTopologyChange = function (parentId, childId, requestedWidth) {
5835
+ var _a;
5836
+ var parent = this.model.getElement(parentId);
5837
+ if (!parent || ((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.mode) !== 'grid' || !parent.layout)
5838
+ return null;
5839
+ var slotState = this.resolveGridChildSlotState(parentId, childId);
5840
+ if (!slotState)
5841
+ return null;
5842
+ var assignedRows = slotState.assignedRows, orderedChildIds = slotState.orderedChildIds, slotWeights = slotState.slotWeights, childFlatIndex = slotState.childFlatIndex, rowIndex = slotState.rowIndex;
5843
+ var currentUnits = slotWeights[childFlatIndex];
5844
+ var requestedUnits = this.resolveRequestedGridUnits(parent, assignedRows[rowIndex], requestedWidth);
5845
+ if (requestedUnits === currentUnits)
5846
+ return null;
5847
+ var nextSlotWeights = __spreadArray([], slotWeights, true);
5848
+ nextSlotWeights[childFlatIndex] = requestedUnits;
5849
+ var nextRows = this.packGridRowsFromSlots(orderedChildIds, nextSlotWeights);
5850
+ var beforeRows = assignedRows.map(function (row) { return ({ childIds: __spreadArray([], row.childIds, true) }); });
5851
+ var afterRows = nextRows.map(function (row) { return ({ childIds: __spreadArray([], row.childIds, true) }); });
5852
+ var rowsChanged = !this.gridRowSnapshotsEqual(beforeRows, afterRows);
5853
+ var reason = requestedUnits < currentUnits && rowsChanged ? 'child-resize-split' : 'child-resize-redistribute';
5854
+ return {
5855
+ parentId: parentId,
5856
+ triggerChildId: childId,
5857
+ reason: reason,
5858
+ beforeRows: beforeRows,
5859
+ afterRows: afterRows,
5860
+ nextLayout: __assign(__assign({}, parent.layout), { gridTemplate: nextSlotWeights }),
5861
+ };
5862
+ };
5863
+ AutoLayoutService.prototype.snapGridChildRequestedWidth = function (parentId, childId, requestedWidth) {
5864
+ var _a, _b;
5865
+ var parent = this.model.getElement(parentId);
5866
+ if (!parent || ((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.mode) !== 'grid' || !parent.layout)
5867
+ return requestedWidth;
5868
+ var slotState = this.resolveGridChildSlotState(parentId, childId);
5869
+ if (!slotState)
5870
+ return requestedWidth;
5871
+ var requestedUnits = this.resolveRequestedGridUnits(parent, slotState.assignedRows[slotState.rowIndex], requestedWidth);
5872
+ 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);
5873
+ return Math.max(1, Math.round(requestedUnits * rowUnitWidth));
5874
+ };
5875
+ AutoLayoutService.prototype.canGridChildGrowRightward = function (parentId, childId) {
5876
+ var _a;
5877
+ var parent = this.model.getElement(parentId);
5878
+ if (!parent || ((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.mode) !== 'grid' || !parent.layout)
5879
+ return false;
5880
+ var orderedIds = this.resolveAssignedGridRows(parent).flatMap(function (row) { return row.childIds; });
5881
+ var childIndex = orderedIds.indexOf(childId);
5882
+ return childIndex >= 0 && childIndex < orderedIds.length - 1;
5883
+ };
5884
+ AutoLayoutService.prototype.applyAxisLayoutForParent = function (parentId, parent, children, axis, options) {
5767
5885
  var _a, _b;
5768
5886
  var _this = this;
5769
5887
  var _c, _d, _e, _f;
5770
- if (preserveParentSize === void 0) { preserveParentSize = false; }
5888
+ var preserveParentSize = Boolean(options === null || options === void 0 ? void 0 : options.preserveParentSize);
5889
+ var preserveParentWidth = preserveParentSize || Boolean(options === null || options === void 0 ? void 0 : options.preserveParentWidth);
5890
+ var preserveParentHeight = preserveParentSize || Boolean(options === null || options === void 0 ? void 0 : options.preserveParentHeight);
5771
5891
  var layout = parent.layout;
5772
5892
  var padding = this.resolveLayoutPadding(layout);
5773
5893
  var gap = (_c = layout === null || layout === void 0 ? void 0 : layout.gap) !== null && _c !== void 0 ? _c : 12;
@@ -5850,8 +5970,16 @@ var AutoLayoutService = /** @class */ (function () {
5850
5970
  }
5851
5971
  else {
5852
5972
  (_a = resolveParentSize(fittedSizes), newParentWidth = _a.width, newParentHeight = _a.height);
5973
+ if (preserveParentWidth)
5974
+ newParentWidth = preservedParentWidth;
5975
+ if (preserveParentHeight)
5976
+ newParentHeight = preservedParentHeight;
5853
5977
  fittedSizes = calculateFittedSizes(newParentWidth, newParentHeight);
5854
5978
  (_b = resolveParentSize(fittedSizes), newParentWidth = _b.width, newParentHeight = _b.height);
5979
+ if (preserveParentWidth)
5980
+ newParentWidth = preservedParentWidth;
5981
+ if (preserveParentHeight)
5982
+ newParentHeight = preservedParentHeight;
5855
5983
  }
5856
5984
  var availableWidth = Math.max(0, newParentWidth - padding.x * 2);
5857
5985
  var availableHeight = Math.max(0, newParentHeight - padding.y * 2 - labelReservedTopLane);
@@ -5886,10 +6014,12 @@ var AutoLayoutService = /** @class */ (function () {
5886
6014
  height: newParentHeight,
5887
6015
  });
5888
6016
  };
5889
- AutoLayoutService.prototype.applyGridLayoutForParent = function (parentId, parent, children, preserveParentSize) {
6017
+ AutoLayoutService.prototype.applyGridLayoutForParent = function (parentId, parent, children, options) {
5890
6018
  var _this = this;
5891
6019
  var _a, _b;
5892
- if (preserveParentSize === void 0) { preserveParentSize = false; }
6020
+ var preserveParentSize = Boolean(options === null || options === void 0 ? void 0 : options.preserveParentSize);
6021
+ var preserveParentWidth = preserveParentSize || Boolean(options === null || options === void 0 ? void 0 : options.preserveParentWidth);
6022
+ var preserveParentHeight = preserveParentSize || Boolean(options === null || options === void 0 ? void 0 : options.preserveParentHeight);
5893
6023
  var layout = parent.layout;
5894
6024
  var padding = this.resolveLayoutPadding(layout);
5895
6025
  var gap = (_a = layout === null || layout === void 0 ? void 0 : layout.gap) !== null && _a !== void 0 ? _a : 12;
@@ -5897,9 +6027,7 @@ var AutoLayoutService = /** @class */ (function () {
5897
6027
  var labelReservedTopLane = this.resolveLabelReservedTopLane(parentId, layout);
5898
6028
  var constraints = this.resolveChildSizeConstraints(layout);
5899
6029
  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);
6030
+ var sorted = this.sortGridChildrenForLayout(children);
5903
6031
  var templateRows = this.normalizeGridTemplate(layout === null || layout === void 0 ? void 0 : layout.gridTemplate);
5904
6032
  var assignedRows = this.assignChildrenToGridRows(sorted.map(function (child) { return child.id; }), templateRows);
5905
6033
  var rowMetrics = assignedRows.map(function (row) {
@@ -5914,20 +6042,33 @@ var AutoLayoutService = /** @class */ (function () {
5914
6042
  };
5915
6043
  });
5916
6044
  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;
6045
+ var totalGap = Math.max(0, clampedSizes.length - 1) * gap;
6046
+ var usedUnits = effectiveWeights.reduce(function (sum, weight) { return sum + _this.clampGridUnits(weight); }, 0);
6047
+ var requiredUnitWidth = effectiveWeights.reduce(function (max, weight, index) {
6048
+ var _a, _b;
6049
+ var slotUnits = Math.max(1, weight !== null && weight !== void 0 ? weight : 1);
6050
+ var width = (_b = (_a = clampedSizes[index]) === null || _a === void 0 ? void 0 : _a.width) !== null && _b !== void 0 ? _b : 0;
6051
+ return Math.max(max, width / slotUnits);
6052
+ }, 0);
6053
+ var rowWidth = usedUnits >= GRID_ROW_UNITS
6054
+ ? autoResize === 'grow-shrink'
6055
+ ? Math.round(requiredUnitWidth * GRID_ROW_UNITS) + totalGap
6056
+ : clampedSizes.reduce(function (sum, size) { return sum + size.width; }, 0) + totalGap
6057
+ : Math.round(requiredUnitWidth * Math.max(1, usedUnits)) + totalGap;
5918
6058
  return {
5919
6059
  row: row,
5920
6060
  rowHeight: rowHeight,
5921
6061
  rowWidth: rowWidth,
6062
+ usedUnits: usedUnits,
5922
6063
  effectiveWeights: effectiveWeights,
5923
6064
  };
5924
6065
  });
5925
6066
  var requiredInnerWidth = rowMetrics.reduce(function (max, metric) { return Math.max(max, metric.rowWidth); }, 0);
5926
6067
  var requiredInnerHeight = rowMetrics.reduce(function (sum, metric) { return sum + metric.rowHeight; }, 0) + Math.max(0, rowMetrics.length - 1) * gap;
5927
- var newParentWidth = preserveParentSize
6068
+ var newParentWidth = preserveParentWidth
5928
6069
  ? Math.max(0, Math.round(parent.size.width))
5929
6070
  : this.resolveAutoResizedDimension(parent.size.width, padding.x * 2 + requiredInnerWidth, autoResize);
5930
- var newParentHeight = preserveParentSize
6071
+ var newParentHeight = preserveParentHeight
5931
6072
  ? Math.max(0, Math.round(parent.size.height))
5932
6073
  : this.resolveAutoResizedDimension(parent.size.height, padding.y * 2 + labelReservedTopLane + requiredInnerHeight, autoResize);
5933
6074
  var availableWidth = Math.max(0, newParentWidth - padding.x * 2);
@@ -5946,8 +6087,11 @@ var AutoLayoutService = /** @class */ (function () {
5946
6087
  if (childCount <= 0)
5947
6088
  return;
5948
6089
  var totalGap = Math.max(0, childCount - 1) * gap;
5949
- var rowInnerWidth = Math.max(0, availableWidth - totalGap);
5950
- var cellWidths = _this.distributeWeightedSizes(rowInnerWidth, metric.effectiveWeights);
6090
+ var rowOuterWidth = metric.usedUnits >= GRID_ROW_UNITS
6091
+ ? availableWidth
6092
+ : Math.min(availableWidth, metric.rowWidth);
6093
+ var rowInnerWidth = Math.max(0, rowOuterWidth - totalGap);
6094
+ var cellWidths = _this.resolveGridCellWidths(rowInnerWidth, metric.effectiveWeights);
5951
6095
  var rowHeight = metric.rowHeight;
5952
6096
  var cursorX = padding.x;
5953
6097
  metric.row.childIds.forEach(function (childId, index) {
@@ -5971,6 +6115,13 @@ var AutoLayoutService = /** @class */ (function () {
5971
6115
  height: newParentHeight,
5972
6116
  });
5973
6117
  };
6118
+ AutoLayoutService.prototype.resolveGridCellWidths = function (rowInnerWidth, weights) {
6119
+ var _this = this;
6120
+ if (weights.length === 0)
6121
+ return [];
6122
+ var safeWeights = weights.map(function (weight) { return _this.clampGridUnits(weight); });
6123
+ return this.distributeWeightedSizes(Math.max(0, rowInnerWidth), safeWeights);
6124
+ };
5974
6125
  AutoLayoutService.prototype.applyResolvedLayout = function (parentId, parent, desiredPositions, desiredSizes, parentSize) {
5975
6126
  var _this = this;
5976
6127
  var _a;
@@ -6033,43 +6184,96 @@ var AutoLayoutService = /** @class */ (function () {
6033
6184
  : Number.POSITIVE_INFINITY;
6034
6185
  return { minWidth: minWidth, maxWidth: maxWidth, minHeight: minHeight, maxHeight: maxHeight };
6035
6186
  };
6187
+ AutoLayoutService.prototype.resolveAssignedGridRows = function (parent) {
6188
+ var _a;
6189
+ var children = this.model.getChildren(parent.id);
6190
+ var sorted = this.sortGridChildrenForLayout(children);
6191
+ var templateRows = this.normalizeGridTemplate((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.gridTemplate);
6192
+ return this.assignChildrenToGridRows(sorted.map(function (child) { return child.id; }), templateRows);
6193
+ };
6194
+ AutoLayoutService.prototype.repartitionAssignedGridRows = function (assignedRows, rowIndex, nextCurrentRowCount) {
6195
+ var _a, _b;
6196
+ var allChildIds = assignedRows.flatMap(function (row) { return row.childIds; });
6197
+ var prefixRows = assignedRows.slice(0, rowIndex).map(function (row) { return ({
6198
+ weights: __spreadArray([], row.weights.slice(0, row.childIds.length), true),
6199
+ childIds: __spreadArray([], row.childIds, true),
6200
+ }); });
6201
+ var prefixCount = prefixRows.reduce(function (sum, row) { return sum + row.childIds.length; }, 0);
6202
+ var nextRows = __spreadArray([], prefixRows, true);
6203
+ var currentChildIds = allChildIds.slice(prefixCount, prefixCount + nextCurrentRowCount);
6204
+ if (currentChildIds.length > 0) {
6205
+ nextRows.push({
6206
+ weights: this.fitGridRowWeights((_a = assignedRows[rowIndex]) === null || _a === void 0 ? void 0 : _a.weights, currentChildIds.length),
6207
+ childIds: currentChildIds,
6208
+ });
6209
+ }
6210
+ var cursor = prefixCount + currentChildIds.length;
6211
+ var trailingRowIndex = rowIndex + 1;
6212
+ while (cursor < allChildIds.length) {
6213
+ var sourceRow = assignedRows[Math.min(trailingRowIndex, assignedRows.length - 1)];
6214
+ var sourceCapacity = Math.max(1, (_b = sourceRow === null || sourceRow === void 0 ? void 0 : sourceRow.childIds.length) !== null && _b !== void 0 ? _b : 1);
6215
+ var rowChildIds = allChildIds.slice(cursor, cursor + sourceCapacity);
6216
+ nextRows.push({
6217
+ weights: this.fitGridRowWeights(sourceRow === null || sourceRow === void 0 ? void 0 : sourceRow.weights, rowChildIds.length),
6218
+ childIds: rowChildIds,
6219
+ });
6220
+ cursor += rowChildIds.length;
6221
+ trailingRowIndex += 1;
6222
+ }
6223
+ return nextRows;
6224
+ };
6225
+ AutoLayoutService.prototype.fitGridRowWeights = function (sourceWeights, childCount) {
6226
+ if (childCount <= 0)
6227
+ return [];
6228
+ var base = Array.isArray(sourceWeights) && sourceWeights.length > 0 ? sourceWeights : [1];
6229
+ var normalizedBase = this.normalizeRowWeightsToTwelveUnits(base);
6230
+ if (normalizedBase.length === childCount) {
6231
+ return normalizedBase;
6232
+ }
6233
+ if (normalizedBase.length > childCount) {
6234
+ return this.normalizeRowWeightsToTwelveUnits(normalizedBase.slice(0, childCount));
6235
+ }
6236
+ return this.buildEqualGridUnits(childCount);
6237
+ };
6238
+ AutoLayoutService.prototype.gridRowSnapshotsEqual = function (a, b) {
6239
+ var _a, _b, _c, _d;
6240
+ if (a.length !== b.length)
6241
+ return false;
6242
+ for (var index = 0; index < a.length; index += 1) {
6243
+ var left = (_b = (_a = a[index]) === null || _a === void 0 ? void 0 : _a.childIds) !== null && _b !== void 0 ? _b : [];
6244
+ var right = (_d = (_c = b[index]) === null || _c === void 0 ? void 0 : _c.childIds) !== null && _d !== void 0 ? _d : [];
6245
+ if (left.length !== right.length)
6246
+ return false;
6247
+ for (var childIndex = 0; childIndex < left.length; childIndex += 1) {
6248
+ if (left[childIndex] !== right[childIndex])
6249
+ return false;
6250
+ }
6251
+ }
6252
+ return true;
6253
+ };
6036
6254
  AutoLayoutService.prototype.normalizeGridTemplate = function (template) {
6255
+ var slots = this.normalizeGridSlotUnits(template);
6037
6256
  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 });
6257
+ var currentRow = [];
6258
+ var currentUnits = 0;
6259
+ slots.forEach(function (slotUnits) {
6260
+ if (currentRow.length > 0 && currentUnits + slotUnits > GRID_ROW_UNITS) {
6261
+ rows.push({ weights: __spreadArray([], currentRow, true) });
6262
+ currentRow = [];
6263
+ currentUnits = 0;
6064
6264
  }
6265
+ currentRow.push(slotUnits);
6266
+ currentUnits += slotUnits;
6065
6267
  });
6268
+ if (currentRow.length > 0) {
6269
+ rows.push({ weights: __spreadArray([], currentRow, true) });
6270
+ }
6066
6271
  if (rows.length === 0) {
6067
- rows.push({ weights: [1] });
6272
+ rows.push({ weights: [GRID_ROW_UNITS] });
6068
6273
  }
6069
6274
  return rows;
6070
6275
  };
6071
6276
  AutoLayoutService.prototype.assignChildrenToGridRows = function (childIds, templateRows) {
6072
- var _a;
6073
6277
  var assigned = [];
6074
6278
  var cursor = 0;
6075
6279
  templateRows.forEach(function (rowTemplate) {
@@ -6085,19 +6289,348 @@ var AutoLayoutService = /** @class */ (function () {
6085
6289
  cursor += rowChildren.length;
6086
6290
  });
6087
6291
  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);
6292
+ var rowChildren = childIds.slice(cursor, cursor + 1);
6093
6293
  assigned.push({
6094
- weights: Array.from({ length: rowChildren.length }, function () { return 1; }),
6294
+ weights: [GRID_ROW_UNITS],
6095
6295
  childIds: rowChildren,
6096
6296
  });
6097
6297
  cursor += rowChildren.length;
6098
6298
  }
6099
6299
  return assigned;
6100
6300
  };
6301
+ AutoLayoutService.prototype.resolveGridChildSlotState = function (parentId, childId) {
6302
+ var _this = this;
6303
+ var _a;
6304
+ var parent = this.model.getElement(parentId);
6305
+ if (!parent || ((_a = parent.layout) === null || _a === void 0 ? void 0 : _a.mode) !== 'grid')
6306
+ return null;
6307
+ var assignedRows = this.resolveAssignedGridRows(parent);
6308
+ if (assignedRows.length === 0)
6309
+ return null;
6310
+ var orderedChildIds = assignedRows.flatMap(function (row) { return row.childIds; });
6311
+ var slotWeights = assignedRows.flatMap(function (row) { return row.weights.slice(0, row.childIds.length).map(function (weight) { return _this.clampGridUnits(weight); }); });
6312
+ var childFlatIndex = orderedChildIds.indexOf(childId);
6313
+ if (childFlatIndex < 0)
6314
+ return null;
6315
+ var rowIndex = assignedRows.findIndex(function (row) { return row.childIds.includes(childId); });
6316
+ if (rowIndex < 0)
6317
+ return null;
6318
+ return { assignedRows: assignedRows, orderedChildIds: orderedChildIds, slotWeights: slotWeights, childFlatIndex: childFlatIndex, rowIndex: rowIndex };
6319
+ };
6320
+ AutoLayoutService.prototype.packGridRowsFromSlots = function (childIds, slotWeights) {
6321
+ var _this = this;
6322
+ var rows = [];
6323
+ var currentChildIds = [];
6324
+ var currentWeights = [];
6325
+ var currentUnits = 0;
6326
+ childIds.forEach(function (childId, index) {
6327
+ var _a;
6328
+ var slotUnits = _this.clampGridUnits((_a = slotWeights[index]) !== null && _a !== void 0 ? _a : GRID_ROW_UNITS);
6329
+ if (currentChildIds.length > 0 && currentUnits + slotUnits > GRID_ROW_UNITS) {
6330
+ rows.push({ childIds: __spreadArray([], currentChildIds, true), weights: __spreadArray([], currentWeights, true) });
6331
+ currentChildIds = [];
6332
+ currentWeights = [];
6333
+ currentUnits = 0;
6334
+ }
6335
+ currentChildIds.push(childId);
6336
+ currentWeights.push(slotUnits);
6337
+ currentUnits += slotUnits;
6338
+ });
6339
+ if (currentChildIds.length > 0) {
6340
+ rows.push({ childIds: __spreadArray([], currentChildIds, true), weights: __spreadArray([], currentWeights, true) });
6341
+ }
6342
+ return rows;
6343
+ };
6344
+ AutoLayoutService.prototype.resolveRequestedGridUnits = function (parent, currentRow, requestedWidth) {
6345
+ var _a;
6346
+ if (!parent.layout || parent.layout.mode !== 'grid' || !currentRow)
6347
+ return GRID_ROW_UNITS;
6348
+ 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);
6349
+ if (rowUnitWidth <= 0)
6350
+ return GRID_ROW_UNITS;
6351
+ return this.clampGridUnits(Math.round(requestedWidth / rowUnitWidth));
6352
+ };
6353
+ AutoLayoutService.prototype.sortGridChildrenForLayout = function (children) {
6354
+ return __spreadArray([], children, true).sort(function (a, b) {
6355
+ if (a.position.y === b.position.y) {
6356
+ if (a.position.x === b.position.x)
6357
+ return a.id.localeCompare(b.id);
6358
+ return a.position.x - b.position.x;
6359
+ }
6360
+ return a.position.y - b.position.y;
6361
+ });
6362
+ };
6363
+ AutoLayoutService.prototype.resolveRightwardGridOverflowChange = function (params) {
6364
+ var _a, _b;
6365
+ 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;
6366
+ var currentRow = assignedRows[rowIndex];
6367
+ if (!currentRow || childIndex < 0 || childIndex >= currentRow.childIds.length - 1)
6368
+ return null;
6369
+ var rowUnitWidth = this.resolveGridRowUnitWidth(availableWidth, currentRow.childIds.length, gap);
6370
+ if (rowUnitWidth <= 0)
6371
+ return null;
6372
+ var currentUnits = (_b = (_a = currentRow.weights[childIndex]) !== null && _a !== void 0 ? _a : this.normalizeRowWeightsToTwelveUnits(currentRow.weights)[childIndex]) !== null && _b !== void 0 ? _b : 1;
6373
+ var requestedUnits = this.clampLayoutSize(Math.round(requestedWidth / rowUnitWidth), currentUnits + 1, GRID_ROW_UNITS - 1);
6374
+ var leftWeights = currentRow.weights.slice(0, childIndex);
6375
+ var leftSum = leftWeights.reduce(function (sum, value) { return sum + value; }, 0);
6376
+ var rightWeights = currentRow.weights.slice(childIndex + 1);
6377
+ var rightIds = currentRow.childIds.slice(childIndex + 1);
6378
+ var followingRows = assignedRows.slice(rowIndex + 1);
6379
+ for (var retainCount = rightIds.length - 1; retainCount >= 0; retainCount -= 1) {
6380
+ var maxTargetUnits = GRID_ROW_UNITS - leftSum - retainCount;
6381
+ if (requestedUnits > maxTargetUnits)
6382
+ continue;
6383
+ var retainedIds = rightIds.slice(0, retainCount);
6384
+ var retainedWeights = rightWeights.slice(0, retainCount);
6385
+ var overflowIds = __spreadArray(__spreadArray([], rightIds.slice(retainCount), true), followingRows.flatMap(function (row) { return row.childIds; }), true);
6386
+ var remainingUnits = GRID_ROW_UNITS - leftSum - requestedUnits;
6387
+ var nextCurrentWeights = __spreadArray(__spreadArray(__spreadArray([], leftWeights, true), [
6388
+ requestedUnits
6389
+ ], false), this.distributeUnitsWithMinimums(remainingUnits, retainedWeights), true);
6390
+ var nextRows = assignedRows.slice(0, rowIndex).map(function (row) { return ({
6391
+ weights: __spreadArray([], row.weights, true),
6392
+ childIds: __spreadArray([], row.childIds, true),
6393
+ }); });
6394
+ nextRows.push({
6395
+ weights: nextCurrentWeights,
6396
+ childIds: __spreadArray(__spreadArray([], currentRow.childIds.slice(0, childIndex + 1), true), retainedIds, true),
6397
+ });
6398
+ var trailingRows = this.reflowTrailingGridRows(overflowIds, followingRows, currentRow.weights.length);
6399
+ var allRows = __spreadArray(__spreadArray([], nextRows, true), trailingRows, true);
6400
+ var beforeRows = assignedRows.map(function (row) { return ({ childIds: __spreadArray([], row.childIds, true) }); });
6401
+ var afterRows = allRows.map(function (row) { return ({ childIds: __spreadArray([], row.childIds, true) }); });
6402
+ if (this.gridRowSnapshotsEqual(beforeRows, afterRows) && this.gridWeightsEqual(assignedRows, allRows)) {
6403
+ return null;
6404
+ }
6405
+ return {
6406
+ parentId: parentId,
6407
+ triggerChildId: childId,
6408
+ reason: 'child-resize-redistribute',
6409
+ beforeRows: beforeRows,
6410
+ afterRows: afterRows,
6411
+ nextLayout: __assign(__assign({}, parentLayout), { gridTemplate: this.flattenAssignedRowsToGridTemplate(allRows) }),
6412
+ };
6413
+ }
6414
+ return null;
6415
+ };
6416
+ AutoLayoutService.prototype.resolveSameRowGridUnitResizeChange = function (params) {
6417
+ var _this = this;
6418
+ var _a, _b, _c, _d;
6419
+ 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;
6420
+ var currentRow = assignedRows[rowIndex];
6421
+ if (!currentRow || currentRow.childIds.length <= 1)
6422
+ return null;
6423
+ var donorIndices = Array.from({ length: Math.max(0, currentRow.childIds.length - childIndex - 1) }, function (_, index) { return childIndex + 1 + index; });
6424
+ if (donorIndices.length === 0)
6425
+ return null;
6426
+ var rowUnitWidth = this.resolveGridRowUnitWidth(availableWidth, currentRow.childIds.length, gap);
6427
+ if (rowUnitWidth <= 0)
6428
+ return null;
6429
+ var currentUnits = (_b = (_a = currentRow.weights[childIndex]) !== null && _a !== void 0 ? _a : this.normalizeRowWeightsToTwelveUnits(currentRow.weights)[childIndex]) !== null && _b !== void 0 ? _b : 1;
6430
+ var requestedUnits = this.clampLayoutSize(Math.round(requestedWidth / rowUnitWidth), 1, GRID_ROW_UNITS - 1);
6431
+ if (requestedUnits === currentUnits)
6432
+ return null;
6433
+ var nextWeights = __spreadArray([], currentRow.weights, true);
6434
+ var delta = requestedUnits - currentUnits;
6435
+ if (delta > 0) {
6436
+ for (var _i = 0, donorIndices_1 = donorIndices; _i < donorIndices_1.length; _i++) {
6437
+ var donorIndex = donorIndices_1[_i];
6438
+ if (delta <= 0)
6439
+ break;
6440
+ var donorCapacity = Math.max(0, ((_c = nextWeights[donorIndex]) !== null && _c !== void 0 ? _c : 1) - 1);
6441
+ var transfer = Math.min(delta, donorCapacity);
6442
+ nextWeights[donorIndex] -= transfer;
6443
+ nextWeights[childIndex] += transfer;
6444
+ delta -= transfer;
6445
+ }
6446
+ }
6447
+ else {
6448
+ var release = Math.abs(delta);
6449
+ for (var _e = 0, donorIndices_2 = donorIndices; _e < donorIndices_2.length; _e++) {
6450
+ var donorIndex = donorIndices_2[_e];
6451
+ if (release <= 0)
6452
+ break;
6453
+ var transfer = release;
6454
+ nextWeights[donorIndex] += transfer;
6455
+ nextWeights[childIndex] -= transfer;
6456
+ release -= transfer;
6457
+ }
6458
+ }
6459
+ if (delta > 0)
6460
+ return null;
6461
+ if (((_d = nextWeights[childIndex]) !== null && _d !== void 0 ? _d : currentUnits) === currentUnits)
6462
+ return null;
6463
+ var nextRows = assignedRows.map(function (row, index) {
6464
+ return index === rowIndex
6465
+ ? {
6466
+ weights: _this.normalizeRowWeightsToTwelveUnits(nextWeights),
6467
+ childIds: __spreadArray([], row.childIds, true),
6468
+ }
6469
+ : { weights: __spreadArray([], row.weights, true), childIds: __spreadArray([], row.childIds, true) };
6470
+ });
6471
+ return {
6472
+ parentId: parentId,
6473
+ triggerChildId: childId,
6474
+ reason: 'child-resize-redistribute',
6475
+ beforeRows: assignedRows.map(function (row) { return ({ childIds: __spreadArray([], row.childIds, true) }); }),
6476
+ afterRows: nextRows.map(function (row) { return ({ childIds: __spreadArray([], row.childIds, true) }); }),
6477
+ nextLayout: __assign(__assign({}, parentLayout), { gridTemplate: this.flattenAssignedRowsToGridTemplate(nextRows) }),
6478
+ };
6479
+ };
6480
+ AutoLayoutService.prototype.splitGridRowIntoTwelveUnits = function (assignedRows, rowIndex, childId, requestedWidth, availableWidth, gap) {
6481
+ var _a;
6482
+ var currentRow = assignedRows[rowIndex];
6483
+ var nextRow = assignedRows[rowIndex + 1];
6484
+ if (!currentRow || !nextRow || currentRow.childIds.length !== 1 || nextRow.childIds.length === 0) {
6485
+ return [];
6486
+ }
6487
+ var rowUnitWidth = this.resolveGridRowUnitWidth(availableWidth, 2, gap);
6488
+ var requestedUnits = this.clampLayoutSize(Math.round(requestedWidth / rowUnitWidth), 1, GRID_ROW_UNITS - 1);
6489
+ var nextRows = assignedRows.slice(0, rowIndex).map(function (row) { return ({
6490
+ weights: __spreadArray([], row.weights, true),
6491
+ childIds: __spreadArray([], row.childIds, true),
6492
+ }); });
6493
+ nextRows.push({
6494
+ weights: [requestedUnits, GRID_ROW_UNITS - requestedUnits],
6495
+ childIds: [childId, nextRow.childIds[0]],
6496
+ });
6497
+ var trailingRows = [];
6498
+ var remainingChildIds = __spreadArray(__spreadArray([], nextRow.childIds.slice(1), true), assignedRows.slice(rowIndex + 2).flatMap(function (row) { return row.childIds; }), true);
6499
+ var cursor = 0;
6500
+ var seedRows = assignedRows.slice(rowIndex + 1);
6501
+ var seedIndex = 0;
6502
+ while (cursor < remainingChildIds.length) {
6503
+ var seed = seedRows[Math.min(seedIndex, seedRows.length - 1)];
6504
+ var capacity = Math.max(1, (_a = seed === null || seed === void 0 ? void 0 : seed.childIds.length) !== null && _a !== void 0 ? _a : 1);
6505
+ var rowChildIds = remainingChildIds.slice(cursor, cursor + capacity);
6506
+ trailingRows.push({
6507
+ weights: this.fitGridRowWeights(seed === null || seed === void 0 ? void 0 : seed.weights, rowChildIds.length),
6508
+ childIds: rowChildIds,
6509
+ });
6510
+ cursor += rowChildIds.length;
6511
+ seedIndex += 1;
6512
+ }
6513
+ return __spreadArray(__spreadArray([], nextRows, true), trailingRows, true);
6514
+ };
6515
+ AutoLayoutService.prototype.reflowTrailingGridRows = function (childIds, seedRows, fallbackColumnCount) {
6516
+ var _a;
6517
+ if (childIds.length === 0)
6518
+ return [];
6519
+ var trailingRows = [];
6520
+ var cursor = 0;
6521
+ var seedIndex = 0;
6522
+ var normalizedSeedRows = seedRows.length > 0 ? seedRows : [{ weights: this.buildEqualGridUnits(Math.max(1, fallbackColumnCount)), childIds: [] }];
6523
+ while (cursor < childIds.length) {
6524
+ var seed = normalizedSeedRows[Math.min(seedIndex, normalizedSeedRows.length - 1)];
6525
+ var capacity = Math.max(1, (_a = seed === null || seed === void 0 ? void 0 : seed.weights.length) !== null && _a !== void 0 ? _a : fallbackColumnCount);
6526
+ var rowChildIds = childIds.slice(cursor, cursor + capacity);
6527
+ trailingRows.push({
6528
+ weights: this.fitGridRowWeights(seed === null || seed === void 0 ? void 0 : seed.weights, rowChildIds.length),
6529
+ childIds: rowChildIds,
6530
+ });
6531
+ cursor += rowChildIds.length;
6532
+ seedIndex += 1;
6533
+ }
6534
+ return trailingRows;
6535
+ };
6536
+ AutoLayoutService.prototype.flattenAssignedRowsToGridTemplate = function (rows) {
6537
+ var _this = this;
6538
+ return rows.flatMap(function (row) { return _this.normalizeRowWeightsToTwelveUnits(row.weights.slice(0, row.childIds.length)); });
6539
+ };
6540
+ AutoLayoutService.prototype.buildEqualGridUnits = function (count) {
6541
+ if (count <= 0)
6542
+ return [];
6543
+ var base = Math.floor(GRID_ROW_UNITS / count);
6544
+ var remainder = GRID_ROW_UNITS - base * count;
6545
+ return Array.from({ length: count }, function (_, index) { return base + (index < remainder ? 1 : 0); });
6546
+ };
6547
+ AutoLayoutService.prototype.normalizeRowWeightsToTwelveUnits = function (weights) {
6548
+ var safeWeights = weights.map(function (weight) { return (Number.isFinite(weight) && weight > 0 ? weight : 1); });
6549
+ if (safeWeights.length === 0)
6550
+ return [GRID_ROW_UNITS];
6551
+ if (safeWeights.length === 1)
6552
+ return [GRID_ROW_UNITS];
6553
+ var distributed = this.distributeWeightedSizes(GRID_ROW_UNITS, safeWeights);
6554
+ var normalized = distributed.map(function (value) { return Math.max(1, value); });
6555
+ var total = normalized.reduce(function (sum, value) { return sum + value; }, 0);
6556
+ if (total === GRID_ROW_UNITS)
6557
+ return normalized;
6558
+ if (total < GRID_ROW_UNITS) {
6559
+ var cursor_1 = 0;
6560
+ while (total < GRID_ROW_UNITS) {
6561
+ normalized[cursor_1 % normalized.length] += 1;
6562
+ total += 1;
6563
+ cursor_1 += 1;
6564
+ }
6565
+ return normalized;
6566
+ }
6567
+ var cursor = normalized.length - 1;
6568
+ while (total > GRID_ROW_UNITS && cursor >= 0) {
6569
+ if (normalized[cursor] > 1) {
6570
+ normalized[cursor] -= 1;
6571
+ total -= 1;
6572
+ }
6573
+ else {
6574
+ cursor -= 1;
6575
+ }
6576
+ if (cursor < 0 && total > GRID_ROW_UNITS) {
6577
+ cursor = normalized.length - 1;
6578
+ }
6579
+ }
6580
+ return normalized;
6581
+ };
6582
+ AutoLayoutService.prototype.normalizeGridSlotUnits = function (template) {
6583
+ var _this = this;
6584
+ var slots = [];
6585
+ (template !== null && template !== void 0 ? template : []).forEach(function (entry) {
6586
+ if (typeof entry === 'number') {
6587
+ if (Number.isFinite(entry) && entry > 0) {
6588
+ slots.push(_this.clampGridUnits(entry));
6589
+ }
6590
+ return;
6591
+ }
6592
+ if (!Array.isArray(entry))
6593
+ return;
6594
+ entry.forEach(function (value) {
6595
+ if (Number.isFinite(value) && value > 0) {
6596
+ slots.push(_this.clampGridUnits(value));
6597
+ }
6598
+ });
6599
+ });
6600
+ return slots;
6601
+ };
6602
+ AutoLayoutService.prototype.clampGridUnits = function (value) {
6603
+ return Math.max(1, Math.min(GRID_ROW_UNITS, Math.round(value)));
6604
+ };
6605
+ AutoLayoutService.prototype.distributeUnitsWithMinimums = function (totalUnits, seedWeights) {
6606
+ if (seedWeights.length === 0)
6607
+ return [];
6608
+ var minimumTotal = seedWeights.length;
6609
+ var clampedTotal = Math.max(minimumTotal, totalUnits);
6610
+ var distributed = this.distributeWeightedSizes(clampedTotal - minimumTotal, seedWeights).map(function (value) { return value + 1; });
6611
+ return distributed;
6612
+ };
6613
+ AutoLayoutService.prototype.gridWeightsEqual = function (leftRows, rightRows) {
6614
+ var _a, _b, _c, _d;
6615
+ if (leftRows.length !== rightRows.length)
6616
+ return false;
6617
+ for (var rowIndex = 0; rowIndex < leftRows.length; rowIndex += 1) {
6618
+ var left = (_b = (_a = leftRows[rowIndex]) === null || _a === void 0 ? void 0 : _a.weights) !== null && _b !== void 0 ? _b : [];
6619
+ var right = (_d = (_c = rightRows[rowIndex]) === null || _c === void 0 ? void 0 : _c.weights) !== null && _d !== void 0 ? _d : [];
6620
+ if (left.length !== right.length)
6621
+ return false;
6622
+ for (var index = 0; index < left.length; index += 1) {
6623
+ if (left[index] !== right[index])
6624
+ return false;
6625
+ }
6626
+ }
6627
+ return true;
6628
+ };
6629
+ AutoLayoutService.prototype.resolveGridRowUnitWidth = function (availableWidth, childCount, gap) {
6630
+ var totalGap = Math.max(0, childCount - 1) * gap;
6631
+ var rowInnerWidth = Math.max(0, availableWidth - totalGap);
6632
+ return rowInnerWidth / GRID_ROW_UNITS;
6633
+ };
6101
6634
  AutoLayoutService.prototype.resolveLabelReservedTopLane = function (parentId, layout) {
6102
6635
  var _a, _b, _c, _d;
6103
6636
  var policy = layout === null || layout === void 0 ? void 0 : layout.labelReservedSpace;
@@ -6632,11 +7165,18 @@ var LinkRoutingService = /** @class */ (function () {
6632
7165
  var onEdge = (shape === null || shape === void 0 ? void 0 : shape.projectToBorder)
6633
7166
  ? this.isPointOnProjectedBorder(point, rect, shape.projectToBorder, EDGE_TOLERANCE)
6634
7167
  : 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;
7168
+ var projectedBorderPoint = (shape === null || shape === void 0 ? void 0 : shape.projectToBorder)
7169
+ ? shape.projectToBorder(point, rect)
7170
+ : projectPointToBoundary(point, rect, 'rect');
7171
+ var projectedBoundaryEquivalent = !onEdge && !this.isPointInsideRect(point, rect, EDGE_TOLERANCE);
7172
+ var sidePoint = projectedBoundaryEquivalent ? projectedBorderPoint : point;
7173
+ var onEdgeSide = onEdge || projectedBoundaryEquivalent
7174
+ ? (_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)
7175
+ : undefined;
6636
7176
  if (onEdgeSide && oppositePoint) {
6637
7177
  onEdgeSide = this.resolveCornerTieBreakSide(point, rect, oppositePoint, onEdgeSide);
6638
7178
  }
6639
- return { onEdge: onEdge, onEdgeSide: onEdgeSide };
7179
+ return { onEdge: onEdge || projectedBoundaryEquivalent, onEdgeSide: onEdgeSide };
6640
7180
  };
6641
7181
  LinkRoutingService.prototype.resolveCornerTieBreakSide = function (point, rect, oppositePoint, currentSide) {
6642
7182
  var onLeft = Math.abs(point.x - rect.x) <= EDGE_TOLERANCE;
@@ -6798,6 +7338,12 @@ var LinkRoutingService = /** @class */ (function () {
6798
7338
  var onBottom = Math.abs(point.y - (rect.y + rect.height)) <= tolerance;
6799
7339
  return onLeft || onRight || onTop || onBottom;
6800
7340
  };
7341
+ LinkRoutingService.prototype.isPointInsideRect = function (point, rect, tolerance) {
7342
+ return (point.x >= rect.x - tolerance &&
7343
+ point.x <= rect.x + rect.width + tolerance &&
7344
+ point.y >= rect.y - tolerance &&
7345
+ point.y <= rect.y + rect.height + tolerance);
7346
+ };
6801
7347
  LinkRoutingService.prototype.resolveEdgeSide = function (point, rect) {
6802
7348
  var distances = [
6803
7349
  { side: 'left', value: Math.abs(point.x - rect.x) },
@@ -6842,8 +7388,8 @@ var MutationPipeline = /** @class */ (function () {
6842
7388
  }());
6843
7389
 
6844
7390
  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),
7391
+ x: clamp$1(point.x, rect.x, rect.x + rect.width),
7392
+ y: clamp$1(point.y, rect.y, rect.y + rect.height),
6847
7393
  }); };
6848
7394
  var snapToRectBorder = function (point, rect) {
6849
7395
  var clamped = clampToRect(point, rect);
@@ -6980,9 +7526,7 @@ var DiagramEngine = /** @class */ (function () {
6980
7526
  });
6981
7527
  this.emitChange(allPatches);
6982
7528
  };
6983
- DiagramEngine.prototype.moveElementTo = function (id, x, y) {
6984
- var _this = this;
6985
- var oldWorld = this.model.getElementWorldPosition(id);
7529
+ DiagramEngine.prototype.resolveElementMovePosition = function (id, x, y) {
6986
7530
  var snapped = this.snapper.snap({ x: x, y: y });
6987
7531
  var element = this.model.getElement(id);
6988
7532
  var position = snapped;
@@ -7022,14 +7566,46 @@ var DiagramEngine = /** @class */ (function () {
7022
7566
  }
7023
7567
  }
7024
7568
  }
7569
+ return { element: element === null || element === void 0 ? void 0 : element.toData(), position: position };
7570
+ };
7571
+ DiagramEngine.prototype.buildChildMutationLayoutSteps = function (parentId, options) {
7572
+ var _this = this;
7573
+ var _a;
7574
+ if (!parentId) {
7575
+ return [function () { return _this.applyLayoutCascade(null); }];
7576
+ }
7577
+ var parent = this.model.getElement(parentId);
7578
+ 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') {
7579
+ return [
7580
+ function () { return _this.applyLayoutForParent(parentId, { preserveParentWidth: true }); },
7581
+ function () { var _a; return _this.applyLayoutCascade((_a = parent.parentId) !== null && _a !== void 0 ? _a : null); },
7582
+ ];
7583
+ }
7584
+ return [function () { return _this.applyLayoutCascade(parentId); }];
7585
+ };
7586
+ DiagramEngine.prototype.moveElementTo = function (id, x, y) {
7587
+ var _a;
7588
+ var oldWorld = this.model.getElementWorldPosition(id);
7589
+ var _b = this.resolveElementMovePosition(id, x, y), element = _b.element, position = _b.position;
7590
+ var beforeGridSlotState = (element === null || element === void 0 ? void 0 : element.parentId)
7591
+ ? this.autoLayoutService.describeGridSlotState(element.parentId)
7592
+ : null;
7025
7593
  var patches = this.commandQueue.run(createMoveElementCommand(id, position), this.model);
7594
+ if ((element === null || element === void 0 ? void 0 : element.parentId) && beforeGridSlotState) {
7595
+ var reorderedLayout = this.autoLayoutService.resolveGridReorderedLayout(element.parentId, beforeGridSlotState);
7596
+ if (reorderedLayout) {
7597
+ patches.push.apply(patches, this.commandQueue.run(createSetElementLayoutCommand(element.parentId, reorderedLayout), this.model));
7598
+ }
7599
+ }
7026
7600
  var movedPortIds = [];
7027
7601
  if (element) {
7028
7602
  movedPortIds.push.apply(movedPortIds, this.collectElementPortIds(element.id));
7029
7603
  }
7030
7604
  var allPatches = this.mutationPipeline.run({
7031
7605
  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); }],
7606
+ layoutSteps: this.buildChildMutationLayoutSteps((_a = element === null || element === void 0 ? void 0 : element.parentId) !== null && _a !== void 0 ? _a : null, {
7607
+ preserveGridParentWidth: true,
7608
+ }),
7033
7609
  movedPortIds: movedPortIds,
7034
7610
  });
7035
7611
  this.emitChange(allPatches);
@@ -7046,24 +7622,106 @@ var DiagramEngine = /** @class */ (function () {
7046
7622
  }
7047
7623
  }
7048
7624
  };
7625
+ DiagramEngine.prototype.resizeElementBounds = function (id, bounds) {
7626
+ var _this = this;
7627
+ var _a, _b, _c, _d;
7628
+ var _e = this.resolveElementMovePosition(id, bounds.x, bounds.y), element = _e.element, position = _e.position;
7629
+ if (!element)
7630
+ return;
7631
+ var oldSize = __assign({}, element.size);
7632
+ var preserveParentSize = Boolean(element.layout && element.layout.mode !== 'manual');
7633
+ var gridLayoutChange = this.resolveGridChildWidthResizeTopologyChange(element, bounds.width);
7634
+ var patches = [];
7635
+ if (gridLayoutChange) {
7636
+ patches.push.apply(patches, this.commandQueue.run(createSetElementLayoutCommand(gridLayoutChange.parentId, gridLayoutChange.afterLayout), this.model));
7637
+ }
7638
+ var positionChanged = element.position.x !== position.x || element.position.y !== position.y;
7639
+ if (positionChanged) {
7640
+ patches.push.apply(patches, this.commandQueue.run(createMoveElementCommand(id, position), this.model));
7641
+ }
7642
+ patches.push.apply(patches, this.commandQueue.run(createResizeElementCommand(id, { width: bounds.width, height: bounds.height }), this.model));
7643
+ var movedPortIds = this.collectElementPortIds(element.id);
7644
+ var layoutSteps = [function () { return _this.applyLayoutForParent(id, { preserveParentSize: preserveParentSize }); }];
7645
+ if (gridLayoutChange && element.parentId) {
7646
+ var grandParentId_1 = (_b = (_a = this.model.getElement(element.parentId)) === null || _a === void 0 ? void 0 : _a.parentId) !== null && _b !== void 0 ? _b : null;
7647
+ layoutSteps.push(function () { var _a; return _this.applyLayoutForParent((_a = element.parentId) !== null && _a !== void 0 ? _a : '', { preserveParentWidth: true }); });
7648
+ if (grandParentId_1) {
7649
+ layoutSteps.push(function () { return _this.applyLayoutCascade(grandParentId_1); });
7650
+ }
7651
+ }
7652
+ else {
7653
+ layoutSteps.push.apply(layoutSteps, this.buildChildMutationLayoutSteps((_c = element.parentId) !== null && _c !== void 0 ? _c : null, {
7654
+ preserveGridParentWidth: true,
7655
+ }));
7656
+ }
7657
+ var allPatches = this.mutationPipeline.run({
7658
+ basePatches: patches,
7659
+ layoutSteps: layoutSteps,
7660
+ movedPortIds: movedPortIds,
7661
+ });
7662
+ if (gridLayoutChange) {
7663
+ this.events.emit('gridLayoutChanged', {
7664
+ parentId: gridLayoutChange.parentId,
7665
+ triggerChildId: gridLayoutChange.triggerChildId,
7666
+ reason: gridLayoutChange.reason,
7667
+ beforeRows: gridLayoutChange.beforeRows,
7668
+ afterRows: gridLayoutChange.afterRows,
7669
+ beforeGridTemplate: gridLayoutChange.beforeGridTemplate,
7670
+ afterGridTemplate: gridLayoutChange.afterGridTemplate,
7671
+ });
7672
+ }
7673
+ this.emitChange(allPatches);
7674
+ var newSize = (_d = this.model.getElement(id)) === null || _d === void 0 ? void 0 : _d.size;
7675
+ if (newSize && (oldSize.width !== newSize.width || oldSize.height !== newSize.height)) {
7676
+ this.events.emit('elementResized', { elementId: id, oldSize: oldSize, newSize: __assign({}, newSize) });
7677
+ }
7678
+ };
7049
7679
  DiagramEngine.prototype.resizeElement = function (id, width, height) {
7050
7680
  var _this = this;
7051
- var _a;
7681
+ var _a, _b, _c, _d;
7052
7682
  var element = this.model.getElement(id);
7053
7683
  var oldSize = element === null || element === void 0 ? void 0 : element.size;
7054
7684
  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);
7685
+ var gridLayoutChange = element
7686
+ ? this.resolveGridChildWidthResizeTopologyChange(element, width)
7687
+ : null;
7688
+ var patches = [];
7689
+ if (gridLayoutChange) {
7690
+ patches.push.apply(patches, this.commandQueue.run(createSetElementLayoutCommand(gridLayoutChange.parentId, gridLayoutChange.afterLayout), this.model));
7691
+ }
7692
+ patches.push.apply(patches, this.commandQueue.run(createResizeElementCommand(id, { width: width, height: height }), this.model));
7056
7693
  var movedPortIds = element ? this.collectElementPortIds(element.id) : [];
7694
+ var layoutSteps = [function () { return _this.applyLayoutForParent(id, { preserveParentSize: preserveParentSize }); }];
7695
+ if (gridLayoutChange && (element === null || element === void 0 ? void 0 : element.parentId)) {
7696
+ var grandParentId_2 = (_b = (_a = this.model.getElement(element.parentId)) === null || _a === void 0 ? void 0 : _a.parentId) !== null && _b !== void 0 ? _b : null;
7697
+ layoutSteps.push(function () { var _a; return _this.applyLayoutForParent((_a = element.parentId) !== null && _a !== void 0 ? _a : '', { preserveParentWidth: true }); });
7698
+ if (grandParentId_2) {
7699
+ layoutSteps.push(function () { return _this.applyLayoutCascade(grandParentId_2); });
7700
+ }
7701
+ }
7702
+ else {
7703
+ layoutSteps.push.apply(layoutSteps, this.buildChildMutationLayoutSteps((_c = element === null || element === void 0 ? void 0 : element.parentId) !== null && _c !== void 0 ? _c : null, {
7704
+ preserveGridParentWidth: true,
7705
+ }));
7706
+ }
7057
7707
  var allPatches = this.mutationPipeline.run({
7058
7708
  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
- ],
7709
+ layoutSteps: layoutSteps,
7063
7710
  movedPortIds: movedPortIds,
7064
7711
  });
7712
+ if (gridLayoutChange) {
7713
+ this.events.emit('gridLayoutChanged', {
7714
+ parentId: gridLayoutChange.parentId,
7715
+ triggerChildId: gridLayoutChange.triggerChildId,
7716
+ reason: gridLayoutChange.reason,
7717
+ beforeRows: gridLayoutChange.beforeRows,
7718
+ afterRows: gridLayoutChange.afterRows,
7719
+ beforeGridTemplate: gridLayoutChange.beforeGridTemplate,
7720
+ afterGridTemplate: gridLayoutChange.afterGridTemplate,
7721
+ });
7722
+ }
7065
7723
  this.emitChange(allPatches);
7066
- var newSize = (_a = this.model.getElement(id)) === null || _a === void 0 ? void 0 : _a.size;
7724
+ var newSize = (_d = this.model.getElement(id)) === null || _d === void 0 ? void 0 : _d.size;
7067
7725
  if (oldSize && newSize && (oldSize.width !== newSize.width || oldSize.height !== newSize.height)) {
7068
7726
  this.events.emit('elementResized', { elementId: id, oldSize: __assign({}, oldSize), newSize: __assign({}, newSize) });
7069
7727
  }
@@ -7368,6 +8026,7 @@ var DiagramEngine = /** @class */ (function () {
7368
8026
  return baseRotation + instanceRotation;
7369
8027
  };
7370
8028
  DiagramEngine.prototype.normalizeElementResize = function (id, proposal, handle, minSize) {
8029
+ var _a, _b;
7371
8030
  if (minSize === void 0) { minSize = 20; }
7372
8031
  var clamped = {
7373
8032
  x: proposal.x,
@@ -7379,13 +8038,19 @@ var DiagramEngine = /** @class */ (function () {
7379
8038
  if (!element)
7380
8039
  return clamped;
7381
8040
  var lockHorizontalResize = this.shouldLockAutoLayoutChildHorizontalResize(element);
8041
+ var currentWorldPosition = this.model.getElementWorldPosition(id);
8042
+ var anchorGridWidthToLeft = this.shouldAnchorAutoLayoutGridChildWidthToLeft(element);
8043
+ var freezeGridLeftEdge = anchorGridWidthToLeft || lockHorizontalResize;
8044
+ var snappedGridWidth = this.resolveSnappedGridChildWidth(element, clamped.width);
7382
8045
  var shape = this.shapeRegistry.get(element.shapeId);
7383
8046
  if (!(shape === null || shape === void 0 ? void 0 : shape.normalizeResize)) {
7384
- if (!lockHorizontalResize)
8047
+ if (!lockHorizontalResize && !anchorGridWidthToLeft)
7385
8048
  return clamped;
7386
- var width_1 = Math.max(minSize, element.size.width);
7387
- var x_1 = clamped.x;
7388
- if (handle === 'sw' || handle === 'nw') {
8049
+ var width_1 = lockHorizontalResize
8050
+ ? Math.max(minSize, element.size.width)
8051
+ : Math.max(minSize, snappedGridWidth);
8052
+ var x_1 = freezeGridLeftEdge ? ((_a = currentWorldPosition === null || currentWorldPosition === void 0 ? void 0 : currentWorldPosition.x) !== null && _a !== void 0 ? _a : clamped.x) : clamped.x;
8053
+ if (!freezeGridLeftEdge && (handle === 'sw' || handle === 'nw')) {
7389
8054
  x_1 += clamped.width - width_1;
7390
8055
  }
7391
8056
  return { x: x_1, y: clamped.y, width: width_1, height: clamped.height };
@@ -7396,11 +8061,15 @@ var DiagramEngine = /** @class */ (function () {
7396
8061
  minSize: minSize,
7397
8062
  proposal: { width: clamped.width, height: clamped.height },
7398
8063
  });
7399
- var width = lockHorizontalResize ? Math.max(minSize, element.size.width) : Math.max(minSize, normalized.width);
8064
+ var width = lockHorizontalResize
8065
+ ? Math.max(minSize, element.size.width)
8066
+ : anchorGridWidthToLeft
8067
+ ? Math.max(minSize, snappedGridWidth)
8068
+ : Math.max(minSize, normalized.width);
7400
8069
  var height = Math.max(minSize, normalized.height);
7401
- var x = clamped.x;
8070
+ var x = freezeGridLeftEdge ? ((_b = currentWorldPosition === null || currentWorldPosition === void 0 ? void 0 : currentWorldPosition.x) !== null && _b !== void 0 ? _b : clamped.x) : clamped.x;
7402
8071
  var y = clamped.y;
7403
- if (handle === 'sw' || handle === 'nw') {
8072
+ if (!freezeGridLeftEdge && (handle === 'sw' || handle === 'nw')) {
7404
8073
  x += clamped.width - width;
7405
8074
  }
7406
8075
  if (handle === 'ne' || handle === 'nw') {
@@ -7418,7 +8087,64 @@ var DiagramEngine = /** @class */ (function () {
7418
8087
  if (element.layout && element.layout.mode !== 'manual')
7419
8088
  return false;
7420
8089
  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';
8090
+ if (((_b = parent === null || parent === void 0 ? void 0 : parent.layout) === null || _b === void 0 ? void 0 : _b.mode) !== 'grid')
8091
+ return false;
8092
+ return !Boolean(parent.layout.gridChildWidthResizeEnabled);
8093
+ };
8094
+ DiagramEngine.prototype.shouldAnchorAutoLayoutGridChildWidthToLeft = function (element) {
8095
+ var _a, _b;
8096
+ var parentId = (_a = element.parentId) !== null && _a !== void 0 ? _a : null;
8097
+ if (!parentId)
8098
+ return false;
8099
+ if (this.model.getChildren(element.id).length > 0)
8100
+ return false;
8101
+ if (element.layout && element.layout.mode !== 'manual')
8102
+ return false;
8103
+ var parent = this.model.getElement(parentId);
8104
+ return Boolean(((_b = parent === null || parent === void 0 ? void 0 : parent.layout) === null || _b === void 0 ? void 0 : _b.mode) === 'grid' && parent.layout.gridChildWidthResizeEnabled);
8105
+ };
8106
+ DiagramEngine.prototype.shouldRestrictAutoLayoutChildRightGrowth = function (element, handle, requestedWidth) {
8107
+ return false;
8108
+ };
8109
+ DiagramEngine.prototype.resolveSnappedGridChildWidth = function (element, requestedWidth) {
8110
+ var _a;
8111
+ var parentId = (_a = element.parentId) !== null && _a !== void 0 ? _a : null;
8112
+ if (!parentId)
8113
+ return requestedWidth;
8114
+ if (this.model.getChildren(element.id).length > 0)
8115
+ return requestedWidth;
8116
+ if (element.layout && element.layout.mode !== 'manual')
8117
+ return requestedWidth;
8118
+ var parent = this.model.getElement(parentId);
8119
+ if (!(parent === null || parent === void 0 ? void 0 : parent.layout) || parent.layout.mode !== 'grid' || !parent.layout.gridChildWidthResizeEnabled)
8120
+ return requestedWidth;
8121
+ return this.autoLayoutService.snapGridChildRequestedWidth(parentId, element.id, requestedWidth);
8122
+ };
8123
+ DiagramEngine.prototype.resolveGridChildWidthResizeTopologyChange = function (element, requestedWidth) {
8124
+ var _a, _b, _c;
8125
+ var parentId = (_a = element.parentId) !== null && _a !== void 0 ? _a : null;
8126
+ if (!parentId)
8127
+ return null;
8128
+ if (this.model.getChildren(element.id).length > 0)
8129
+ return null;
8130
+ if (element.layout && element.layout.mode !== 'manual')
8131
+ return null;
8132
+ var parent = this.model.getElement(parentId);
8133
+ if (!parent || ((_b = parent.layout) === null || _b === void 0 ? void 0 : _b.mode) !== 'grid' || !parent.layout.gridChildWidthResizeEnabled)
8134
+ return null;
8135
+ var topologyChange = this.autoLayoutService.resolveGridChildResizeTopologyChange(parentId, element.id, requestedWidth);
8136
+ if (!topologyChange)
8137
+ return null;
8138
+ return {
8139
+ parentId: topologyChange.parentId,
8140
+ triggerChildId: topologyChange.triggerChildId,
8141
+ reason: topologyChange.reason,
8142
+ beforeRows: topologyChange.beforeRows,
8143
+ afterRows: topologyChange.afterRows,
8144
+ beforeGridTemplate: parent.layout.gridTemplate ? __spreadArray([], parent.layout.gridTemplate, true) : undefined,
8145
+ afterGridTemplate: __spreadArray([], ((_c = topologyChange.nextLayout.gridTemplate) !== null && _c !== void 0 ? _c : []), true),
8146
+ afterLayout: topologyChange.nextLayout,
8147
+ };
7422
8148
  };
7423
8149
  DiagramEngine.prototype.getPortWorldPosition = function (id) {
7424
8150
  return this.model.getPortWorldPosition(id);
@@ -7701,8 +8427,8 @@ var DiagramEngine = /** @class */ (function () {
7701
8427
  }
7702
8428
  if (style === null || style === void 0 ? void 0 : style.moveBounds) {
7703
8429
  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);
8430
+ position.x = clamp$1(position.x, bounds.x, bounds.x + bounds.width);
8431
+ position.y = clamp$1(position.y, bounds.y, bounds.y + bounds.height);
7706
8432
  }
7707
8433
  if (effectiveMoveMode === 'border') {
7708
8434
  var resolvedBorder = this.resolveBorderPositionWithLimits(position, element, (_e = element.portMovement) === null || _e === void 0 ? void 0 : _e.positionLimits);
@@ -9577,6 +10303,10 @@ var KonvaInteraction = /** @class */ (function () {
9577
10303
  return;
9578
10304
  }
9579
10305
  if (hit.type === 'text') {
10306
+ if (!_this.isTextMovable(hit.id)) {
10307
+ _this.setCursor('default');
10308
+ return;
10309
+ }
9580
10310
  var base = _this.engine.getTextWorldPosition(hit.id);
9581
10311
  if (base) {
9582
10312
  _this.dragState = {
@@ -9966,6 +10696,8 @@ var KonvaInteraction = /** @class */ (function () {
9966
10696
  var hit = _this.resolveHit(point);
9967
10697
  if (!hit || hit.type !== 'text')
9968
10698
  return;
10699
+ if (!_this.isTextEditable(hit.id))
10700
+ return;
9969
10701
  _this.startTextEdit(hit.id);
9970
10702
  };
9971
10703
  this.stage.on('dblclick dbltap', doubleClick);
@@ -11118,8 +11850,12 @@ var KonvaInteraction = /** @class */ (function () {
11118
11850
  y: normalized.y + normalized.height / 2,
11119
11851
  }
11120
11852
  : { 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);
11853
+ this.engine.resizeElementBounds(state.elementId, {
11854
+ x: moveTarget.x,
11855
+ y: moveTarget.y,
11856
+ width: normalized.width,
11857
+ height: normalized.height,
11858
+ });
11123
11859
  this.updateSelectionOverlays();
11124
11860
  };
11125
11861
  KonvaInteraction.prototype.parseResizeHandle = function (id) {
@@ -11455,6 +12191,14 @@ var KonvaInteraction = /** @class */ (function () {
11455
12191
  KonvaInteraction.prototype.getTextById = function (id) {
11456
12192
  return this.engine.getState().texts.find(function (text) { return text.id === id; });
11457
12193
  };
12194
+ KonvaInteraction.prototype.isTextMovable = function (id) {
12195
+ var _a, _b;
12196
+ return ((_b = (_a = this.getTextById(id)) === null || _a === void 0 ? void 0 : _a.interaction) === null || _b === void 0 ? void 0 : _b.movable) !== false;
12197
+ };
12198
+ KonvaInteraction.prototype.isTextEditable = function (id) {
12199
+ var _a, _b;
12200
+ return ((_b = (_a = this.getTextById(id)) === null || _a === void 0 ? void 0 : _a.interaction) === null || _b === void 0 ? void 0 : _b.editable) !== false;
12201
+ };
11458
12202
  KonvaInteraction.prototype.getLinkById = function (id) {
11459
12203
  return this.engine.getState().links.find(function (link) { return link.id === id; });
11460
12204
  };
@@ -12137,6 +12881,24 @@ var hasBounds = function (bounds) {
12137
12881
  bounds.maxX >= bounds.minX &&
12138
12882
  bounds.maxY >= bounds.minY;
12139
12883
  };
12884
+ var DEFAULT_VIEWPORT_FIT_PADDING = 24;
12885
+ var DEFAULT_VIEWPORT_FIT_MIN_ZOOM = 0.2;
12886
+ var DEFAULT_VIEWPORT_FIT_MAX_ZOOM = 3;
12887
+ var resolveViewportFitOptions = function (options) {
12888
+ var padding = typeof (options === null || options === void 0 ? void 0 : options.padding) === 'number' && Number.isFinite(options.padding)
12889
+ ? Math.max(0, options.padding)
12890
+ : DEFAULT_VIEWPORT_FIT_PADDING;
12891
+ var requestedMinZoom = typeof (options === null || options === void 0 ? void 0 : options.minZoom) === 'number' && Number.isFinite(options.minZoom)
12892
+ ? Math.max(0.000001, options.minZoom)
12893
+ : DEFAULT_VIEWPORT_FIT_MIN_ZOOM;
12894
+ var requestedMaxZoom = typeof (options === null || options === void 0 ? void 0 : options.maxZoom) === 'number' && Number.isFinite(options.maxZoom)
12895
+ ? Math.max(0.000001, options.maxZoom)
12896
+ : DEFAULT_VIEWPORT_FIT_MAX_ZOOM;
12897
+ var minZoom = Math.min(requestedMinZoom, requestedMaxZoom);
12898
+ var maxZoom = Math.max(requestedMinZoom, requestedMaxZoom);
12899
+ return { padding: padding, minZoom: minZoom, maxZoom: maxZoom };
12900
+ };
12901
+ var clamp = function (value, min, max) { return Math.max(min, Math.min(max, value)); };
12140
12902
  var resolveStateWorldBounds = function (state) {
12141
12903
  var bounds = createBounds();
12142
12904
  state.elements.forEach(function (element) {
@@ -12173,6 +12935,34 @@ var resolveStateWorldBounds = function (state) {
12173
12935
  });
12174
12936
  return hasBounds(bounds) ? bounds : null;
12175
12937
  };
12938
+ var resolveElementWorldBounds = function (state) {
12939
+ var bounds = createBounds();
12940
+ state.elements.forEach(function (element) {
12941
+ includeRect(bounds, element.position.x, element.position.y, element.size.width, element.size.height);
12942
+ });
12943
+ return hasBounds(bounds) ? bounds : null;
12944
+ };
12945
+ var resolveViewportFitTransform = function (state, viewportSize, options) {
12946
+ var bounds = resolveElementWorldBounds(state);
12947
+ if (!bounds)
12948
+ return null;
12949
+ var safeWidth = Math.max(1, viewportSize.width);
12950
+ var safeHeight = Math.max(1, viewportSize.height);
12951
+ var _a = resolveViewportFitOptions(options), padding = _a.padding, minZoom = _a.minZoom, maxZoom = _a.maxZoom;
12952
+ var availableWidth = Math.max(1, safeWidth - padding * 2);
12953
+ var availableHeight = Math.max(1, safeHeight - padding * 2);
12954
+ var contentWidth = Math.max(1, bounds.maxX - bounds.minX);
12955
+ var contentHeight = Math.max(1, bounds.maxY - bounds.minY);
12956
+ var rawZoom = Math.min(availableWidth / contentWidth, availableHeight / contentHeight);
12957
+ var zoom = clamp(rawZoom, minZoom, maxZoom);
12958
+ var centerX = (bounds.minX + bounds.maxX) / 2;
12959
+ var centerY = (bounds.minY + bounds.maxY) / 2;
12960
+ var pan = {
12961
+ x: safeWidth / 2 - centerX * zoom,
12962
+ y: safeHeight / 2 - centerY * zoom,
12963
+ };
12964
+ return { pan: pan, zoom: zoom };
12965
+ };
12176
12966
  var resolveFitToContentPadding = function (fitToContent) {
12177
12967
  if (typeof fitToContent === 'object' && typeof fitToContent.padding === 'number') {
12178
12968
  return Math.max(0, fitToContent.padding);
@@ -12248,10 +13038,12 @@ var registerSimpleShapes = function (registry, shapes, isPort) {
12248
13038
  var createDiagramEditor = function (config) {
12249
13039
  var _a, _b;
12250
13040
  var Konva = getKonva();
13041
+ var stageWidth = (_a = config.width) !== null && _a !== void 0 ? _a : 900;
13042
+ var stageHeight = (_b = config.height) !== null && _b !== void 0 ? _b : 560;
12251
13043
  var stage = new Konva.Stage({
12252
13044
  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,
13045
+ width: stageWidth,
13046
+ height: stageHeight,
12255
13047
  });
12256
13048
  var stageContainer = typeof stage.container === 'function' ? stage.container() : stage.container;
12257
13049
  if (stageContainer && stageContainer.tabIndex < 0) {
@@ -12398,6 +13190,12 @@ var createDiagramEditor = function (config) {
12398
13190
  completeLinkToPort: function (targetPortId) { return interaction.completeLinkToPort(targetPortId); },
12399
13191
  completeLinkToElement: function (targetElementId, pointer) { return interaction.completeLinkToElement(targetElementId, pointer); },
12400
13192
  cancelLink: function () { return interaction.cancelLink(); },
13193
+ zoomToFitElements: function (options) {
13194
+ var transform = resolveViewportFitTransform(engine.getState(), { width: stageWidth, height: stageHeight }, options);
13195
+ if (!transform)
13196
+ return;
13197
+ engine.setViewport(transform.pan, transform.zoom);
13198
+ },
12401
13199
  exportImage: function (options) {
12402
13200
  engine.render();
12403
13201
  if (typeof stage.toDataURL !== 'function') {
@@ -12424,6 +13222,8 @@ var createDiagramEditor = function (config) {
12424
13222
  return stage.toDataURL(__assign(__assign({}, baseOptions), { x: cropX, y: cropY, width: cropWidth, height: cropHeight }));
12425
13223
  },
12426
13224
  resize: function (width, height) {
13225
+ stageWidth = width;
13226
+ stageHeight = height;
12427
13227
  stage.width(width);
12428
13228
  stage.height(height);
12429
13229
  engine.render();
@@ -12643,6 +13443,7 @@ var engineEventOptions = [
12643
13443
  'elementDragged',
12644
13444
  'elementMoved',
12645
13445
  'elementResized',
13446
+ 'gridLayoutChanged',
12646
13447
  'elementDeleted',
12647
13448
  'portDeleted',
12648
13449
  'linkDeleted',
@@ -12897,7 +13698,7 @@ var parentOptions = [
12897
13698
  ];
12898
13699
  var shortLabel = 'Parent label lane demo';
12899
13700
  var longLabel = 'Parent label lane demo with longer content to increase flexible reserved space and push children downward.';
12900
- var defaultGridTemplateText = '[[3],[1,2]]';
13701
+ var defaultGridTemplateText = '[12,4,8]';
12901
13702
  var serializeGridTemplate = function (template) {
12902
13703
  return Array.isArray(template) && template.length > 0 ? JSON.stringify(template) : defaultGridTemplateText;
12903
13704
  };
@@ -12916,23 +13717,21 @@ var parseGridTemplate = function (value) {
12916
13717
  return null;
12917
13718
  var normalized = [];
12918
13719
  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)
13720
+ var entry = parsed[i];
13721
+ if (typeof entry === 'number') {
13722
+ if (!Number.isFinite(entry) || entry <= 0)
12922
13723
  return null;
12923
- normalized.push(Math.floor(row));
13724
+ normalized.push(Math.floor(entry));
12924
13725
  continue;
12925
13726
  }
12926
- if (!Array.isArray(row) || row.length === 0)
13727
+ if (!Array.isArray(entry) || entry.length === 0)
12927
13728
  return null;
12928
- var weights = [];
12929
- for (var j = 0; j < row.length; j += 1) {
12930
- var cell = row[j];
13729
+ for (var j = 0; j < entry.length; j += 1) {
13730
+ var cell = entry[j];
12931
13731
  if (typeof cell !== 'number' || !Number.isFinite(cell) || cell <= 0)
12932
13732
  return null;
12933
- weights.push(cell);
13733
+ normalized.push(Math.floor(cell));
12934
13734
  }
12935
- normalized.push(weights);
12936
13735
  }
12937
13736
  return normalized;
12938
13737
  };
@@ -12967,11 +13766,12 @@ var AutoLayoutDemo = function () {
12967
13766
  var _m = React.useState(''), childMaxWidth = _m[0], setChildMaxWidth = _m[1];
12968
13767
  var _o = React.useState(''), childMaxHeight = _o[0], setChildMaxHeight = _o[1];
12969
13768
  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];
13769
+ var _q = React.useState(false), gridChildWidthResizeEnabled = _q[0], setGridChildWidthResizeEnabled = _q[1];
13770
+ var _r = React.useState('none'), labelReservedMode = _r[0], setLabelReservedMode = _r[1];
13771
+ var _s = React.useState(32), labelReservedFixedSize = _s[0], setLabelReservedFixedSize = _s[1];
13772
+ var _t = React.useState(''), labelReservedMinSize = _t[0], setLabelReservedMinSize = _t[1];
13773
+ var _u = React.useState(''), labelReservedMaxSize = _u[0], setLabelReservedMaxSize = _u[1];
13774
+ var _v = React.useState('None yet'), lastTrigger = _v[0], setLastTrigger = _v[1];
12975
13775
  React.useEffect(function () {
12976
13776
  var editor = editorRef.current;
12977
13777
  if (!editor)
@@ -12979,6 +13779,7 @@ var AutoLayoutDemo = function () {
12979
13779
  var disposers = [
12980
13780
  editor.on('elementMoved', function () { return setLastTrigger('child moved'); }),
12981
13781
  editor.on('elementResized', function () { return setLastTrigger('child resized'); }),
13782
+ editor.on('gridLayoutChanged', function (event) { return setLastTrigger("grid layout changed (".concat(event.reason, ")")); }),
12982
13783
  editor.on('elementDeleted', function () { return setLastTrigger('child removed'); }),
12983
13784
  editor.on('change', function () { return setLastTrigger(function (prev) { return prev; }); }),
12984
13785
  ];
@@ -13053,6 +13854,7 @@ var AutoLayoutDemo = function () {
13053
13854
  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
13855
  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
13856
  setGridTemplateText(serializeGridTemplate(layout === null || layout === void 0 ? void 0 : layout.gridTemplate));
13857
+ setGridChildWidthResizeEnabled(Boolean(layout === null || layout === void 0 ? void 0 : layout.gridChildWidthResizeEnabled));
13056
13858
  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
13859
  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
13860
  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 +13908,7 @@ var AutoLayoutDemo = function () {
13106
13908
  : __assign(__assign(__assign({ mode: labelReservedMode, placement: 'top' }, (labelReservedMode === 'fixed' ? { size: labelReservedFixedSize } : {})), (labelReservedMinSize === '' ? {} : { minSize: labelReservedMinSize })), (labelReservedMaxSize === '' ? {} : { maxSize: labelReservedMaxSize }));
13107
13909
  var layout = mode === 'manual'
13108
13910
  ? { 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 });
13911
+ : __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
13912
  editor.setElementLayout(targetElement.id, layout);
13111
13913
  setLastTrigger("layout applied (".concat(mode, ")"));
13112
13914
  };
@@ -13173,13 +13975,11 @@ var AutoLayoutDemo = function () {
13173
13975
  return (React.createElement("section", null,
13174
13976
  React.createElement("div", { style: { marginBottom: 12 } },
13175
13977
  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."),
13978
+ 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."),
13177
13979
  React.createElement("p", { style: { marginTop: 0, marginBottom: 0, fontSize: 13, color: '#333' } },
13178
- "Resize-lock check: select ",
13980
+ "Grid child width resize is disabled by default. With the capability off, select ",
13179
13981
  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.")),
13982
+ " and drag a corner mostly downward: width stays stable while height changes. Turn the capability on to let horizontal drag wrap rows automatically from a flat 12-unit slot array, then resize children in 1/12 steps. Any corner can drive width changes, width always grows or shrinks on the right, siblings keep their own widths, and dragging can swap grid item order.")),
13183
13983
  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
13984
  React.createElement("div", { style: { display: 'grid', gap: 12, marginBottom: 12 } },
13185
13985
  React.createElement("div", { style: { display: 'flex', flexWrap: 'wrap', gap: 12, alignItems: 'center' } },
@@ -13227,7 +14027,11 @@ var AutoLayoutDemo = function () {
13227
14027
  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
14028
  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
14029
  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' }),
14030
+ 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' }),
14031
+ React.createElement("label", { htmlFor: "grid-child-width-resize-enabled", style: { fontWeight: 600 } }, "Grid child width resize"),
14032
+ React.createElement("label", { style: { display: 'inline-flex', alignItems: 'center', gap: 6 } },
14033
+ React.createElement("input", { id: "grid-child-width-resize-enabled", type: "checkbox", checked: gridChildWidthResizeEnabled, onChange: function (event) { return setGridChildWidthResizeEnabled(event.target.checked); }, disabled: mode !== 'grid' }),
14034
+ "Enable 12-unit resize on child width drag"),
13231
14035
  React.createElement("label", { htmlFor: "label-reserved-mode-select", style: { fontWeight: 600 } }, "Label lane"),
13232
14036
  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
14037
  React.createElement("option", { value: "none" }, "None"),
@@ -13280,11 +14084,16 @@ var AutoLayoutDemo = function () {
13280
14084
  React.createElement("div", null,
13281
14085
  React.createElement("div", { style: { fontWeight: 600, marginBottom: 6 } }, "Scenario tips"),
13282
14086
  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."),
14087
+ React.createElement("li", null, "Resize lock: with grid child width resize off, select grid-b and drag diagonally; width should stay fixed."),
14088
+ 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."),
14089
+ 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."),
14090
+ 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."),
14091
+ React.createElement("li", null, "Try dragging a grid child across a sibling; the row-major order should swap to match the drag position."),
14092
+ React.createElement("li", null, "Whenever enabled child width resize changes row allocation, the last-trigger badge should report grid layout changed."),
13284
14093
  React.createElement("li", null, "Parent resize: select layout-grid, drag corner; parent width and height should both track drag."),
13285
14094
  React.createElement("li", null, "Horizontal: try center vs bottom alignment and larger padding."),
13286
14095
  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]]."),
14096
+ 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
14097
  React.createElement("li", null, "Auto resize: compare grow-only vs grow-shrink while adding/removing children."),
13289
14098
  React.createElement("li", null, "Label lane: compare none/fixed/flexible and observe children start below the reserved lane."),
13290
14099
  React.createElement("li", null, "Fit main-axis distribute fills inner layout space across siblings."),
@@ -13716,10 +14525,15 @@ var TextLayoutDemo = function () {
13716
14525
  var selectedText = diagramState === null || diagramState === void 0 ? void 0 : diagramState.texts.find(function (text) { return text.id === selectedTextId; });
13717
14526
  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
14527
  var ownerElement = diagramState === null || diagramState === void 0 ? void 0 : diagramState.elements.find(function (element) { return element.id === textDemoOwnerId; });
14528
+ var selectedInteraction = selectedText === null || selectedText === void 0 ? void 0 : selectedText.interaction;
14529
+ var getInteractionForTarget = function (nextTarget) {
14530
+ return nextTarget === 'owned' ? textDemoOwnedInteraction : textDemoFloatingInteraction;
14531
+ };
13719
14532
  var applyLayoutToTarget = function (nextTarget, nextLayout) {
13720
14533
  var editor = editorRef.current;
13721
14534
  if (!editor)
13722
14535
  return;
14536
+ var interaction = getInteractionForTarget(nextTarget);
13723
14537
  if (nextTarget === 'owned') {
13724
14538
  editor.removeText(textDemoOwnedTextId);
13725
14539
  editor.addText({
@@ -13727,6 +14541,7 @@ var TextLayoutDemo = function () {
13727
14541
  content: textDemoLongSample,
13728
14542
  ownerId: textDemoOwnerId,
13729
14543
  position: { x: 12, y: 12 },
14544
+ interaction: interaction,
13730
14545
  layout: nextLayout,
13731
14546
  });
13732
14547
  editor.setSelection([textDemoOwnedTextId]);
@@ -13737,6 +14552,7 @@ var TextLayoutDemo = function () {
13737
14552
  id: textDemoFloatingTextId,
13738
14553
  content: textDemoLongSample,
13739
14554
  position: { x: 470, y: 120 },
14555
+ interaction: interaction,
13740
14556
  layout: nextLayout,
13741
14557
  });
13742
14558
  editor.setSelection([textDemoFloatingTextId]);
@@ -13804,7 +14620,8 @@ var TextLayoutDemo = function () {
13804
14620
  return (React.createElement("section", null,
13805
14621
  React.createElement("div", { style: { marginBottom: 12 } },
13806
14622
  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.")),
14623
+ React.createElement("p", { style: { marginTop: 0 } }, "Full text content is preserved in state. Overflow and ellipsis settings only change visual output (`displayContent`) for rendering."),
14624
+ 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
14625
  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
14626
  React.createElement("div", { style: { display: 'grid', gap: 10, marginBottom: 12 } },
13810
14627
  React.createElement("div", { style: { display: 'flex', flexWrap: 'wrap', gap: 10, alignItems: 'center' } },
@@ -13892,7 +14709,12 @@ var TextLayoutDemo = function () {
13892
14709
  ' ',
13893
14710
  Number.isFinite(selectedWorldX) && Number.isFinite(selectedWorldY)
13894
14711
  ? "".concat(selectedWorldX.toFixed(1), ", ").concat(selectedWorldY.toFixed(1))
13895
- : 'n/a')),
14712
+ : 'n/a'),
14713
+ React.createElement("div", null,
14714
+ "interaction: movable=",
14715
+ (selectedInteraction === null || selectedInteraction === void 0 ? void 0 : selectedInteraction.movable) === false ? 'false' : 'true',
14716
+ " | editable=",
14717
+ (selectedInteraction === null || selectedInteraction === void 0 ? void 0 : selectedInteraction.editable) === false ? 'false' : 'true')),
13896
14718
  React.createElement("div", { style: { display: 'grid', gap: 6 } },
13897
14719
  React.createElement("div", { style: { fontSize: 12 } },
13898
14720
  React.createElement("strong", null, "Canonical content:"),
@@ -13962,6 +14784,311 @@ var ObstacleRoutingDemo = function () {
13962
14784
  "Enable redraw refresh on two-endpoint change")) }));
13963
14785
  };
13964
14786
 
14787
+ var offsetAnchorShapes = __spreadArray(__spreadArray([], baseElementShapes, true), [
14788
+ {
14789
+ id: 'offset-anchor-ellipse',
14790
+ kind: 'ellipse',
14791
+ style: {
14792
+ fill: '#eef8ff',
14793
+ stroke: '#2563eb',
14794
+ strokeWidth: 2,
14795
+ },
14796
+ },
14797
+ ], false);
14798
+ var createOffsetAnchorAvoidanceState = function () { return ({
14799
+ elements: [
14800
+ {
14801
+ id: 'offset-sibling-parent',
14802
+ position: { x: 40, y: 110 },
14803
+ size: { width: 520, height: 250 },
14804
+ shapeId: 'panel',
14805
+ style: { fill: '#faf7ef' },
14806
+ },
14807
+ {
14808
+ id: 'offset-sibling-a',
14809
+ position: { x: 60, y: 78 },
14810
+ size: { width: 130, height: 96 },
14811
+ shapeId: 'offset-anchor-ellipse',
14812
+ parentId: 'offset-sibling-parent',
14813
+ portMovement: { moveMode: 'anchors', anchorConstraint: { preset: 'cardinal' } },
14814
+ },
14815
+ {
14816
+ id: 'offset-sibling-b',
14817
+ position: { x: 320, y: 78 },
14818
+ size: { width: 130, height: 96 },
14819
+ shapeId: 'offset-anchor-ellipse',
14820
+ parentId: 'offset-sibling-parent',
14821
+ portMovement: { moveMode: 'anchors', anchorConstraint: { preset: 'cardinal' } },
14822
+ },
14823
+ {
14824
+ id: 'offset-direction-parent',
14825
+ position: { x: 620, y: 110 },
14826
+ size: { width: 330, height: 250 },
14827
+ shapeId: 'offset-anchor-ellipse',
14828
+ portMovement: { moveMode: 'anchors', anchorConstraint: { preset: 'cardinal' } },
14829
+ },
14830
+ {
14831
+ id: 'offset-direction-child',
14832
+ position: { x: 48, y: 74 },
14833
+ size: { width: 128, height: 92 },
14834
+ shapeId: 'default',
14835
+ parentId: 'offset-direction-parent',
14836
+ portMovement: { moveMode: 'anchors', anchorConstraint: { preset: 'cardinal' } },
14837
+ },
14838
+ {
14839
+ id: 'offset-direction-sibling',
14840
+ position: { x: 190, y: 126 },
14841
+ size: { width: 96, height: 70 },
14842
+ shapeId: 'default',
14843
+ parentId: 'offset-direction-parent',
14844
+ style: { fill: '#fff6e8', stroke: '#b45309', strokeWidth: 2 },
14845
+ },
14846
+ ],
14847
+ ports: [
14848
+ {
14849
+ id: 'offset-sibling-a-port',
14850
+ elementId: 'offset-sibling-a',
14851
+ position: { x: 0, y: 48 },
14852
+ shapeId: 'port-dark',
14853
+ anchorCenter: true,
14854
+ currentAnchorId: 'left',
14855
+ moveMode: 'border',
14856
+ externalLinkAttachPoint: { x: 0, y: 24 },
14857
+ },
14858
+ {
14859
+ id: 'offset-sibling-b-port',
14860
+ elementId: 'offset-sibling-b',
14861
+ position: { x: 130, y: 48 },
14862
+ shapeId: 'port-dark',
14863
+ anchorCenter: true,
14864
+ currentAnchorId: 'right',
14865
+ moveMode: 'border',
14866
+ externalLinkAttachPoint: { x: 0, y: 24 },
14867
+ },
14868
+ {
14869
+ id: 'offset-parent-port',
14870
+ elementId: 'offset-direction-parent',
14871
+ position: { x: 18, y: 125 },
14872
+ shapeId: 'port-circle',
14873
+ anchorCenter: true,
14874
+ currentAnchorId: 'left',
14875
+ moveMode: 'border',
14876
+ externalLinkAttachPoint: { x: 0, y: 18 },
14877
+ internalLinkAttachPoint: { x: 0, y: -18 },
14878
+ },
14879
+ {
14880
+ id: 'offset-child-port',
14881
+ elementId: 'offset-direction-child',
14882
+ position: { x: 128, y: 46 },
14883
+ shapeId: 'port-circle',
14884
+ anchorCenter: true,
14885
+ currentAnchorId: 'right',
14886
+ moveMode: 'border',
14887
+ externalLinkAttachPoint: { x: 0, y: 18 },
14888
+ internalLinkAttachPoint: { x: 0, y: -18 },
14889
+ },
14890
+ ],
14891
+ links: [
14892
+ {
14893
+ id: 'offset-sibling-link',
14894
+ sourcePortId: 'offset-sibling-a-port',
14895
+ targetPortId: 'offset-sibling-b-port',
14896
+ points: [],
14897
+ routing: 'auto',
14898
+ },
14899
+ {
14900
+ id: 'offset-parent-child-link',
14901
+ sourcePortId: 'offset-parent-port',
14902
+ targetPortId: 'offset-child-port',
14903
+ points: [],
14904
+ routing: 'auto',
14905
+ },
14906
+ {
14907
+ id: 'offset-child-parent-link',
14908
+ sourcePortId: 'offset-child-port',
14909
+ targetPortId: 'offset-parent-port',
14910
+ points: [],
14911
+ routing: 'auto',
14912
+ },
14913
+ ],
14914
+ texts: [
14915
+ {
14916
+ id: 'offset-anchor-intro',
14917
+ 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.',
14918
+ position: { x: 40, y: 28 },
14919
+ },
14920
+ {
14921
+ id: 'offset-sibling-label',
14922
+ content: 'Scenario A: sibling children use external attach points offset beyond left/right edges.',
14923
+ position: { x: 52, y: 82 },
14924
+ },
14925
+ {
14926
+ id: 'offset-direction-label',
14927
+ content: 'Scenario B: parent/child links reuse the same offset anchors but resolve internal vs external semantics by direction.',
14928
+ position: { x: 620, y: 82 },
14929
+ },
14930
+ {
14931
+ id: 'offset-sibling-a-text',
14932
+ content: 'Child A\nexternal offset 24',
14933
+ ownerId: 'offset-sibling-a',
14934
+ position: { x: 14, y: -20 },
14935
+ },
14936
+ {
14937
+ id: 'offset-sibling-b-text',
14938
+ content: 'Child B\nexternal offset 24',
14939
+ ownerId: 'offset-sibling-b',
14940
+ position: { x: 14, y: -20 },
14941
+ },
14942
+ {
14943
+ id: 'offset-direction-parent-text',
14944
+ content: 'Parent port\ninternal 18 / external 18',
14945
+ ownerId: 'offset-direction-parent',
14946
+ position: { x: 48, y: -20 },
14947
+ },
14948
+ {
14949
+ id: 'offset-direction-child-text',
14950
+ content: 'Child port\nexternal 18 / internal 18',
14951
+ ownerId: 'offset-direction-child',
14952
+ position: { x: 6, y: -18 },
14953
+ },
14954
+ {
14955
+ id: 'offset-direction-links-text',
14956
+ content: 'Blue links: parent→child and child→parent should keep the host border side semantics even with offset attach coordinates.',
14957
+ position: { x: 620, y: 378 },
14958
+ },
14959
+ ],
14960
+ }); };
14961
+ var rerouteAllAction = {
14962
+ id: 'offset-reroute-links',
14963
+ label: 'Reroute All Links',
14964
+ run: function (editor) {
14965
+ editor.rerouteAllLinks();
14966
+ },
14967
+ };
14968
+ var shiftTargetsAction = {
14969
+ id: 'offset-shift-targets',
14970
+ label: 'Shift targets + reroute',
14971
+ run: function (editor) {
14972
+ editor.moveElementTo('offset-sibling-b', 320, 96);
14973
+ editor.moveElementTo('offset-direction-child', 74, 96);
14974
+ editor.rerouteAllLinks();
14975
+ },
14976
+ };
14977
+ var offsetAnchorAvoidanceDemoConfig = {
14978
+ id: 'offset-anchor-avoidance',
14979
+ title: 'Offset Anchor Avoidance',
14980
+ description: 'Visual QA for projected-boundary-equivalent offset attach anchors that must still keep endpoint host interiors forbidden.',
14981
+ createState: createOffsetAnchorAvoidanceState,
14982
+ elementShapes: offsetAnchorShapes,
14983
+ portShapes: basePortShapes,
14984
+ defaultElementShapeId: 'default',
14985
+ defaultPortShapeId: 'port-circle',
14986
+ actions: [rerouteAllAction, shiftTargetsAction],
14987
+ };
14988
+
14989
+ var OffsetAnchorAvoidanceDemo = function () { return (React.createElement(SimpleDemo, { demo: offsetAnchorAvoidanceDemoConfig, beforeStage: React.createElement("div", { style: {
14990
+ marginBottom: 12,
14991
+ padding: '10px 12px',
14992
+ borderRadius: 8,
14993
+ border: '1px solid #2d2d2d',
14994
+ background: '#f4f4f4',
14995
+ } },
14996
+ React.createElement("strong", null, "Visual checks"),
14997
+ React.createElement("ul", { style: { margin: '6px 0 0 16px' } },
14998
+ React.createElement("li", null, "Sibling link should route around both child interiors even though attach coordinates are offset outside the host edges."),
14999
+ React.createElement("li", null, "`parent\u2192child` should use the parent's internal side and the child's external side."),
15000
+ React.createElement("li", null, "`child\u2192parent` should invert the same endpoint semantics without crossing either endpoint host interior."),
15001
+ React.createElement("li", null, "Use `Shift targets + reroute` and `Reroute All Links` to verify stable behavior after layout changes."))) })); };
15002
+
15003
+ var createZoomToFitElementsState = function () { return ({
15004
+ elements: [
15005
+ {
15006
+ id: 'fit-node-a',
15007
+ position: { x: 40, y: 60 },
15008
+ size: { width: 140, height: 90 },
15009
+ shapeId: 'default',
15010
+ style: { fill: '#eef6ff', stroke: '#1d4ed8', strokeWidth: 2 },
15011
+ },
15012
+ {
15013
+ id: 'fit-node-b',
15014
+ position: { x: 760, y: 120 },
15015
+ size: { width: 170, height: 110 },
15016
+ shapeId: 'panel',
15017
+ style: { fill: '#fef3c7', stroke: '#b45309', strokeWidth: 2 },
15018
+ },
15019
+ {
15020
+ id: 'fit-node-c',
15021
+ position: { x: 140, y: 420 },
15022
+ size: { width: 220, height: 120 },
15023
+ shapeId: 'default',
15024
+ style: { fill: '#ecfdf5', stroke: '#047857', strokeWidth: 2 },
15025
+ },
15026
+ {
15027
+ id: 'fit-node-d',
15028
+ position: { x: 860, y: 430 },
15029
+ size: { width: 150, height: 90 },
15030
+ shapeId: 'default',
15031
+ style: { fill: '#f5f3ff', stroke: '#6d28d9', strokeWidth: 2 },
15032
+ },
15033
+ ],
15034
+ ports: [],
15035
+ links: [],
15036
+ texts: [
15037
+ {
15038
+ id: 'fit-text-intro',
15039
+ content: 'Use actions to spread nodes and run the zoom-to-fit viewport command.',
15040
+ position: { x: 40, y: 24 },
15041
+ },
15042
+ ],
15043
+ }); };
15044
+ var zoomFitAction = {
15045
+ id: 'fit-zoom-default',
15046
+ label: 'Run Zoom-To-Fit',
15047
+ run: function (editor) {
15048
+ editor.zoomToFitElements();
15049
+ },
15050
+ };
15051
+ var zoomFitPaddingAction = {
15052
+ id: 'fit-zoom-padding',
15053
+ label: 'Run Zoom-To-Fit (Padding 48)',
15054
+ run: function (editor) {
15055
+ editor.zoomToFitElements({ padding: 48 });
15056
+ },
15057
+ };
15058
+ var spreadSceneAction = {
15059
+ id: 'fit-spread-scene',
15060
+ label: 'Spread Scene',
15061
+ run: function (editor) {
15062
+ editor.moveElementTo('fit-node-b', 880, 80);
15063
+ editor.moveElementTo('fit-node-d', 980, 500);
15064
+ editor.moveElementTo('fit-node-c', 80, 520);
15065
+ },
15066
+ };
15067
+ var zoomToFitElementsDemoConfig = {
15068
+ id: 'zoom-to-fit-elements',
15069
+ title: 'Zoom To Fit Elements',
15070
+ description: 'Calls a viewport command that zooms and centers so all elements are visible.',
15071
+ createState: createZoomToFitElementsState,
15072
+ elementShapes: baseElementShapes,
15073
+ portShapes: basePortShapes,
15074
+ defaultElementShapeId: 'default',
15075
+ defaultPortShapeId: 'port-circle',
15076
+ actions: [zoomFitAction, zoomFitPaddingAction, spreadSceneAction],
15077
+ };
15078
+
15079
+ var ZoomToFitElementsDemo = function () { return (React.createElement(SimpleDemo, { demo: zoomToFitElementsDemoConfig, beforeStage: (React.createElement("div", { style: {
15080
+ marginBottom: 12,
15081
+ padding: '10px 12px',
15082
+ borderRadius: 8,
15083
+ border: '1px solid #2d2d2d',
15084
+ background: '#f4f4f4',
15085
+ } },
15086
+ React.createElement("strong", null, "Visual checks"),
15087
+ React.createElement("ul", { style: { margin: '6px 0 0 16px' } },
15088
+ React.createElement("li", null, "Click `Run Zoom-To-Fit` and ensure every node is visible and centered."),
15089
+ React.createElement("li", null, "Run `Spread Scene` then fit again to verify viewport recomputes from the updated layout."),
15090
+ React.createElement("li", null, "Use `Run Zoom-To-Fit (Padding 48)` to confirm optional padding keeps extra breathing room around content.")))) })); };
15091
+
13965
15092
  var initialPayloads = {
13966
15093
  elementDeleted: null,
13967
15094
  portDeleted: null,
@@ -15039,6 +16166,18 @@ var demoTabs = [
15039
16166
  description: obstacleRoutingDemoConfig.description,
15040
16167
  Component: ObstacleRoutingDemo,
15041
16168
  },
16169
+ {
16170
+ id: offsetAnchorAvoidanceDemoConfig.id,
16171
+ title: offsetAnchorAvoidanceDemoConfig.title,
16172
+ description: offsetAnchorAvoidanceDemoConfig.description,
16173
+ Component: OffsetAnchorAvoidanceDemo,
16174
+ },
16175
+ {
16176
+ id: zoomToFitElementsDemoConfig.id,
16177
+ title: zoomToFitElementsDemoConfig.title,
16178
+ description: zoomToFitElementsDemoConfig.description,
16179
+ Component: ZoomToFitElementsDemo,
16180
+ },
15042
16181
  {
15043
16182
  id: linkBendHandlesDemoConfig.id,
15044
16183
  title: linkBendHandlesDemoConfig.title,