orcasvn-react-diagrams 0.2.11 → 0.2.13

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 (55) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +15 -7
  3. package/ai/api-contract.json +90 -1
  4. package/ai/invariants.json +6 -2
  5. package/ai/manifest.json +1 -1
  6. package/dist/cjs/examples.js +916 -331
  7. package/dist/cjs/index.js +406 -97
  8. package/dist/cjs/types/api/createDiagramEditor.d.ts +3 -1
  9. package/dist/cjs/types/api/types.d.ts +64 -0
  10. package/dist/cjs/types/displaybox/demos/LinkPortCreationDemoTab.d.ts +3 -0
  11. package/dist/cjs/types/displaybox/demos/deletionEventsDemo.d.ts +2 -0
  12. package/dist/cjs/types/displaybox/demos/focusElementDemo.d.ts +4 -0
  13. package/dist/cjs/types/displaybox/demos/linkLabelsDemo.d.ts +4 -0
  14. package/dist/cjs/types/displaybox/types.d.ts +3 -0
  15. package/dist/cjs/types/displaybox/useDemoEditor.d.ts +3 -2
  16. package/dist/cjs/types/engine/DiagramEngine.d.ts +11 -1
  17. package/dist/cjs/types/engine/TextLayoutService.d.ts +1 -0
  18. package/dist/cjs/types/examples/index.d.ts +1 -1
  19. package/dist/cjs/types/renderer/konva/KonvaInteraction.d.ts +10 -1
  20. package/dist/esm/examples.js +916 -331
  21. package/dist/esm/examples.js.map +1 -1
  22. package/dist/esm/index.js +406 -97
  23. package/dist/esm/index.js.map +1 -1
  24. package/dist/esm/types/api/createDiagramEditor.d.ts +3 -1
  25. package/dist/esm/types/api/types.d.ts +64 -0
  26. package/dist/esm/types/displaybox/demos/LinkPortCreationDemoTab.d.ts +3 -0
  27. package/dist/esm/types/displaybox/demos/deletionEventsDemo.d.ts +2 -0
  28. package/dist/esm/types/displaybox/demos/focusElementDemo.d.ts +4 -0
  29. package/dist/esm/types/displaybox/demos/linkLabelsDemo.d.ts +4 -0
  30. package/dist/esm/types/displaybox/types.d.ts +3 -0
  31. package/dist/esm/types/displaybox/useDemoEditor.d.ts +3 -2
  32. package/dist/esm/types/engine/DiagramEngine.d.ts +11 -1
  33. package/dist/esm/types/engine/TextLayoutService.d.ts +1 -0
  34. package/dist/esm/types/examples/index.d.ts +1 -1
  35. package/dist/esm/types/renderer/konva/KonvaInteraction.d.ts +10 -1
  36. package/dist/examples.d.ts +55 -1
  37. package/dist/index.d.ts +67 -1
  38. package/docs/API_CONTRACT.md +88 -1
  39. package/docs/ARCHITECTURE.md +9 -7
  40. package/docs/CAPABILITIES.md +5 -0
  41. package/docs/COMMANDS_EVENTS.md +16 -6
  42. package/docs/DOCUMENTATION_WORKFLOW.md +5 -1
  43. package/docs/INTEGRATION_PLAYBOOK.md +8 -0
  44. package/docs/PORTING_CHECKLIST.md +4 -1
  45. package/docs/STATE_INVARIANTS.md +3 -0
  46. package/package.json +1 -1
  47. package/src/displaybox/demos/DeletionEventsDemoTab.tsx +167 -9
  48. package/src/displaybox/demos/LinkPortCreationDemoTab.tsx +98 -0
  49. package/src/displaybox/demos/deletionEventsDemo.ts +2 -2
  50. package/src/displaybox/demos/focusElementDemo.ts +91 -0
  51. package/src/displaybox/demos/index.tsx +124 -221
  52. package/src/displaybox/demos/linkLabelsDemo.ts +164 -0
  53. package/src/displaybox/demos/linkPortCreationDemo.ts +7 -7
  54. package/src/displaybox/types.ts +21 -11
  55. package/src/examples/index.ts +1 -0
@@ -2,17 +2,6 @@
2
2
 
3
3
  var React = require('react');
4
4
 
5
- var fallbackId = function () {
6
- return "id-".concat(Math.random().toString(36).slice(2, 10), "-").concat(Date.now().toString(36));
7
- };
8
- var createId = function () {
9
- var cryptoApi = globalThis.crypto;
10
- if (cryptoApi === null || cryptoApi === void 0 ? void 0 : cryptoApi.randomUUID) {
11
- return cryptoApi.randomUUID();
12
- }
13
- return fallbackId();
14
- };
15
-
16
5
  /******************************************************************************
17
6
  Copyright (c) Microsoft Corporation.
18
7
 
@@ -82,6 +71,17 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
82
71
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
83
72
  };
84
73
 
74
+ var fallbackId = function () {
75
+ return "id-".concat(Math.random().toString(36).slice(2, 10), "-").concat(Date.now().toString(36));
76
+ };
77
+ var createId = function () {
78
+ var cryptoApi = globalThis.crypto;
79
+ if (cryptoApi === null || cryptoApi === void 0 ? void 0 : cryptoApi.randomUUID) {
80
+ return cryptoApi.randomUUID();
81
+ }
82
+ return fallbackId();
83
+ };
84
+
85
85
  var DEFAULT_PADDING = 12;
86
86
  var DEFAULT_TOLERANCE = 0.5;
87
87
  var DEFAULT_STUB_LENGTH = 12;
@@ -848,7 +848,7 @@ var createLinkPortCreationState = function () { return ({
848
848
  var linkPortCreationDemoConfig = ({
849
849
  id: 'link-port-creation',
850
850
  title: 'Link Creates Port',
851
- description: 'Drag from a port to an element to auto-create a target port.',
851
+ description: 'Drag from a port to an element to auto-create a target port, then compare default and host-customized target-port creation.',
852
852
  createState: createLinkPortCreationState,
853
853
  elementShapes: baseElementShapes,
854
854
  portShapes: basePortShapes,
@@ -3634,6 +3634,163 @@ var linkColorPoolDemoConfig = {
3634
3634
  ],
3635
3635
  };
3636
3636
 
3637
+ var linkLabelDemoSourceId = 'link-label-source';
3638
+ var linkLabelDemoTargetId = 'link-label-target';
3639
+ var linkLabelDemoLinkId = 'link-label-link';
3640
+ var linkLabelDemoTextId = 'link-label-text';
3641
+ var resolveLinkMidpoint = function (points) {
3642
+ if (points.length === 0)
3643
+ return { x: 0, y: 0 };
3644
+ if (points.length === 1)
3645
+ return __assign({}, points[0]);
3646
+ var total = 0;
3647
+ for (var index = 1; index < points.length; index += 1) {
3648
+ total += Math.hypot(points[index].x - points[index - 1].x, points[index].y - points[index - 1].y);
3649
+ }
3650
+ var halfway = total / 2;
3651
+ var travelled = 0;
3652
+ for (var index = 1; index < points.length; index += 1) {
3653
+ var segment = Math.hypot(points[index].x - points[index - 1].x, points[index].y - points[index - 1].y);
3654
+ if (travelled + segment >= halfway) {
3655
+ var ratio = segment === 0 ? 0 : (halfway - travelled) / segment;
3656
+ return {
3657
+ x: points[index - 1].x + (points[index].x - points[index - 1].x) * ratio,
3658
+ y: points[index - 1].y + (points[index].y - points[index - 1].y) * ratio,
3659
+ };
3660
+ }
3661
+ travelled += segment;
3662
+ }
3663
+ return __assign({}, points[points.length - 1]);
3664
+ };
3665
+ var nudgeLinkLabel = function (editor, state) {
3666
+ var link = state.links.find(function (item) { return item.id === linkLabelDemoLinkId; });
3667
+ var label = state.texts.find(function (item) { return item.id === linkLabelDemoTextId; });
3668
+ if (!link || !label)
3669
+ return;
3670
+ var midpoint = resolveLinkMidpoint(link.points);
3671
+ editor.moveTextTo(linkLabelDemoTextId, midpoint.x + 72, midpoint.y - 24);
3672
+ };
3673
+ var createLinkLabelsState = function () { return ({
3674
+ elements: [
3675
+ {
3676
+ id: linkLabelDemoSourceId,
3677
+ position: { x: 120, y: 180 },
3678
+ size: { width: 220, height: 120 },
3679
+ shapeId: 'default',
3680
+ },
3681
+ {
3682
+ id: linkLabelDemoTargetId,
3683
+ position: { x: 500, y: 220 },
3684
+ size: { width: 220, height: 140 },
3685
+ shapeId: 'panel',
3686
+ },
3687
+ ],
3688
+ ports: [
3689
+ {
3690
+ id: 'link-label-source-port',
3691
+ elementId: linkLabelDemoSourceId,
3692
+ position: { x: 220, y: 60 },
3693
+ shapeId: 'port-circle',
3694
+ moveMode: 'border',
3695
+ anchorCenter: true,
3696
+ },
3697
+ {
3698
+ id: 'link-label-target-port',
3699
+ elementId: linkLabelDemoTargetId,
3700
+ position: { x: 0, y: 70 },
3701
+ shapeId: 'port-circle',
3702
+ moveMode: 'border',
3703
+ anchorCenter: true,
3704
+ },
3705
+ ],
3706
+ links: [
3707
+ {
3708
+ id: linkLabelDemoLinkId,
3709
+ sourcePortId: 'link-label-source-port',
3710
+ targetPortId: 'link-label-target-port',
3711
+ points: [],
3712
+ },
3713
+ ],
3714
+ texts: [
3715
+ {
3716
+ id: "".concat(linkLabelDemoSourceId, "-label"),
3717
+ content: 'Source node',
3718
+ position: { x: 12, y: -14 },
3719
+ ownerId: linkLabelDemoSourceId,
3720
+ },
3721
+ {
3722
+ id: "".concat(linkLabelDemoTargetId, "-label"),
3723
+ content: 'Move me, reroute me',
3724
+ position: { x: 12, y: -14 },
3725
+ ownerId: linkLabelDemoTargetId,
3726
+ },
3727
+ {
3728
+ id: linkLabelDemoTextId,
3729
+ content: 'I am just owned text',
3730
+ position: { x: 0, y: -24 },
3731
+ ownerId: linkLabelDemoLinkId,
3732
+ layout: {
3733
+ boundsMode: 'fixed',
3734
+ fixedSize: { width: 160, height: 24 },
3735
+ wrap: 'none',
3736
+ overflow: 'ellipsis-end',
3737
+ },
3738
+ style: {
3739
+ fill: '#1f2937',
3740
+ backgroundFill: '#fef3c7',
3741
+ padding: 4,
3742
+ },
3743
+ },
3744
+ {
3745
+ id: 'link-label-tip',
3746
+ content: 'This label is TextData owned by the link. Drag or edit it, reroute the link, then delete the link to confirm the label follows and cascades away.',
3747
+ position: { x: 120, y: 110 },
3748
+ layout: {
3749
+ boundsMode: 'fixed',
3750
+ fixedSize: { width: 620, height: 44 },
3751
+ wrap: 'word',
3752
+ overflow: 'clip',
3753
+ padding: 0,
3754
+ },
3755
+ style: {
3756
+ fill: '#475569',
3757
+ },
3758
+ },
3759
+ ],
3760
+ }); };
3761
+ var linkLabelsDemoConfig = {
3762
+ id: 'link-labels',
3763
+ title: 'Link Labels',
3764
+ description: 'Link-owned text stays anchored to the route midpoint. Drag or edit the label, reroute the link, then delete the link to watch the owned text disappear with it.',
3765
+ createState: createLinkLabelsState,
3766
+ elementShapes: baseElementShapes,
3767
+ portShapes: basePortShapes,
3768
+ defaultElementShapeId: 'default',
3769
+ defaultPortShapeId: 'port-circle',
3770
+ actions: [
3771
+ {
3772
+ id: 'link-label-offset',
3773
+ label: 'Offset label via API',
3774
+ run: function (editor, state) { return nudgeLinkLabel(editor, state); },
3775
+ },
3776
+ {
3777
+ id: 'link-label-reroute',
3778
+ label: 'Move target + reroute',
3779
+ run: function (editor) {
3780
+ editor.moveElementTo(linkLabelDemoTargetId, 660, 320);
3781
+ editor.rerouteAllLinks();
3782
+ },
3783
+ },
3784
+ {
3785
+ id: 'link-label-delete',
3786
+ label: 'Delete labeled link',
3787
+ run: function (editor) {
3788
+ editor.removeLink(linkLabelDemoLinkId);
3789
+ },
3790
+ },
3791
+ ],
3792
+ };
3793
+
3637
3794
  var createGridOverlayState = function () { return ({
3638
3795
  elements: [
3639
3796
  {
@@ -4229,7 +4386,7 @@ var createDeletionEventsState = function () { return ({
4229
4386
  var deletionEventsDemoConfig = {
4230
4387
  id: 'deletion-events',
4231
4388
  title: 'Deletion Events',
4232
- description: 'Inspect elementDeleted, portDeleted, linkDeleted, and textDeleted payloads for direct and cascade removals.',
4389
+ description: 'Inspect cancellable delete lifecycle events, post-delete payloads, and element double click in one integration-focused scenario.',
4233
4390
  createState: createDeletionEventsState,
4234
4391
  elementShapes: baseElementShapes,
4235
4392
  portShapes: basePortShapes,
@@ -6150,21 +6307,20 @@ var TextLayoutService = /** @class */ (function () {
6150
6307
  return ids;
6151
6308
  };
6152
6309
  TextLayoutService.prototype.shouldTrackOwnerBoundLayout = function (text) {
6153
- var _a;
6154
6310
  if (!text.layout)
6155
6311
  return false;
6156
- var boundsMode = (_a = text.layout.boundsMode) !== null && _a !== void 0 ? _a : (text.ownerId ? 'owner-width' : undefined);
6312
+ var boundsMode = this.resolveDefaultBoundsMode(text);
6157
6313
  return boundsMode === 'owner-width' || boundsMode === 'owner-box';
6158
6314
  };
6159
6315
  TextLayoutService.prototype.resolveTextLayoutBounds = function (text, padding) {
6160
- var _a, _b, _c;
6316
+ var _a, _b;
6161
6317
  var layout = text.layout;
6162
6318
  if (!layout)
6163
6319
  return {};
6164
- var boundsMode = (_a = layout.boundsMode) !== null && _a !== void 0 ? _a : (text.ownerId ? 'owner-width' : undefined);
6320
+ var boundsMode = this.resolveDefaultBoundsMode(text);
6165
6321
  if (boundsMode === 'fixed') {
6166
- var width = (_b = layout.fixedSize) === null || _b === void 0 ? void 0 : _b.width;
6167
- var height = (_c = layout.fixedSize) === null || _c === void 0 ? void 0 : _c.height;
6322
+ var width = (_a = layout.fixedSize) === null || _a === void 0 ? void 0 : _a.width;
6323
+ var height = (_b = layout.fixedSize) === null || _b === void 0 ? void 0 : _b.height;
6168
6324
  return {
6169
6325
  width: typeof width === 'number' ? Math.max(0, width - padding * 2) : undefined,
6170
6326
  height: typeof height === 'number' ? Math.max(0, height - padding * 2) : undefined,
@@ -6184,6 +6340,14 @@ var TextLayoutService = /** @class */ (function () {
6184
6340
  }
6185
6341
  return {};
6186
6342
  };
6343
+ TextLayoutService.prototype.resolveDefaultBoundsMode = function (text) {
6344
+ var _a;
6345
+ if ((_a = text.layout) === null || _a === void 0 ? void 0 : _a.boundsMode)
6346
+ return text.layout.boundsMode;
6347
+ if (!text.ownerId)
6348
+ return undefined;
6349
+ return this.model.getElement(text.ownerId) ? 'owner-width' : undefined;
6350
+ };
6187
6351
  TextLayoutService.prototype.wrapText = function (content, maxWidth, mode, text) {
6188
6352
  var _this = this;
6189
6353
  if (maxWidth === undefined || !Number.isFinite(maxWidth)) {
@@ -8399,8 +8563,15 @@ var DiagramEngine = /** @class */ (function () {
8399
8563
  var _this = this;
8400
8564
  var _a;
8401
8565
  var existing = this.model.getElement(id);
8402
- var parentId = (_a = existing === null || existing === void 0 ? void 0 : existing.parentId) !== null && _a !== void 0 ? _a : null;
8566
+ if (!existing)
8567
+ return;
8568
+ var parentId = (_a = existing.parentId) !== null && _a !== void 0 ? _a : null;
8403
8569
  var before = this.model.toState();
8570
+ var root = { entity: 'element', id: id };
8571
+ var plannedRemoval = this.planRemoval(before, root);
8572
+ if (!plannedRemoval || this.emitDeletionLifecycleEvents(plannedRemoval.removed, root, 'direct')) {
8573
+ return;
8574
+ }
8404
8575
  this.commandQueue.run(createRemoveElementCommand(id), this.model);
8405
8576
  var removal = this.computeRemovalDiff(before);
8406
8577
  var allPatches = this.mutationPipeline.run({
@@ -8408,9 +8579,6 @@ var DiagramEngine = /** @class */ (function () {
8408
8579
  layoutSteps: [function () { return _this.applyLayoutCascade(parentId); }],
8409
8580
  });
8410
8581
  this.emitChange(allPatches);
8411
- if (existing) {
8412
- this.events.emit('elementDeleted', { elementId: id });
8413
- }
8414
8582
  this.emitEntityDeletionEvents(removal.removed);
8415
8583
  };
8416
8584
  DiagramEngine.prototype.addPortToElement = function (elementId, port) {
@@ -8425,6 +8593,24 @@ var DiagramEngine = /** @class */ (function () {
8425
8593
  var patches = this.commandQueue.run(createAddPortCommand(nextPort), this.model);
8426
8594
  this.emitChange(patches);
8427
8595
  };
8596
+ DiagramEngine.prototype.normalizePortDraftForElement = function (elementId, draft) {
8597
+ var _a;
8598
+ var element = this.model.getElement(elementId);
8599
+ if (!element)
8600
+ return null;
8601
+ var nextDraft = __assign(__assign({}, draft), { position: __assign({}, draft.position), size: draft.size ? __assign({}, draft.size) : undefined, style: draft.style ? __assign({}, draft.style) : undefined, textIds: draft.textIds ? __spreadArray([], draft.textIds, true) : undefined, placementPoint: draft.placementPoint ? __assign({}, draft.placementPoint) : undefined, linkAttachPoint: draft.linkAttachPoint ? __assign({}, draft.linkAttachPoint) : undefined, externalLinkAttachPoint: draft.externalLinkAttachPoint ? __assign({}, draft.externalLinkAttachPoint) : undefined, internalLinkAttachPoint: draft.internalLinkAttachPoint ? __assign({}, draft.internalLinkAttachPoint) : undefined, rotationPivot: draft.rotationPivot ? __assign({}, draft.rotationPivot) : undefined });
8602
+ var constrained = this.resolveConstrainedPortRelativePosition({
8603
+ position: nextDraft.position,
8604
+ size: nextDraft.size,
8605
+ style: nextDraft.style,
8606
+ moveMode: nextDraft.moveMode,
8607
+ anchorCenter: nextDraft.anchorCenter,
8608
+ currentAnchorId: nextDraft.currentAnchorId,
8609
+ }, element, nextDraft.position);
8610
+ nextDraft.position = constrained.position;
8611
+ nextDraft.currentAnchorId = (_a = constrained.currentAnchorId) !== null && _a !== void 0 ? _a : undefined;
8612
+ return nextDraft;
8613
+ };
8428
8614
  DiagramEngine.prototype.movePortTo = function (id, x, y) {
8429
8615
  var snapped = this.snapper.snap({ x: x, y: y });
8430
8616
  var port = this.model.getPort(id);
@@ -8473,7 +8659,14 @@ var DiagramEngine = /** @class */ (function () {
8473
8659
  }
8474
8660
  };
8475
8661
  DiagramEngine.prototype.removePort = function (id) {
8662
+ if (!this.model.getPort(id))
8663
+ return;
8476
8664
  var before = this.model.toState();
8665
+ var root = { entity: 'port', id: id };
8666
+ var plannedRemoval = this.planRemoval(before, root);
8667
+ if (!plannedRemoval || this.emitDeletionLifecycleEvents(plannedRemoval.removed, root, 'direct')) {
8668
+ return;
8669
+ }
8477
8670
  this.commandQueue.run(createRemovePortCommand(id), this.model);
8478
8671
  var removal = this.computeRemovalDiff(before);
8479
8672
  this.emitChange(removal.patches);
@@ -8567,7 +8760,14 @@ var DiagramEngine = /** @class */ (function () {
8567
8760
  }
8568
8761
  };
8569
8762
  DiagramEngine.prototype.removeLink = function (id) {
8763
+ if (!this.model.getLink(id))
8764
+ return;
8570
8765
  var before = this.model.toState();
8766
+ var root = { entity: 'link', id: id };
8767
+ var plannedRemoval = this.planRemoval(before, root);
8768
+ if (!plannedRemoval || this.emitDeletionLifecycleEvents(plannedRemoval.removed, root, 'direct')) {
8769
+ return;
8770
+ }
8571
8771
  this.commandQueue.run(createRemoveLinkCommand(id), this.model);
8572
8772
  var removal = this.computeRemovalDiff(before);
8573
8773
  this.emitChange(removal.patches);
@@ -8652,7 +8852,14 @@ var DiagramEngine = /** @class */ (function () {
8652
8852
  this.emitChange(patches);
8653
8853
  };
8654
8854
  DiagramEngine.prototype.removeText = function (id) {
8855
+ if (!this.model.getText(id))
8856
+ return;
8655
8857
  var before = this.model.toState();
8858
+ var root = { entity: 'text', id: id };
8859
+ var plannedRemoval = this.planRemoval(before, root);
8860
+ if (!plannedRemoval || this.emitDeletionLifecycleEvents(plannedRemoval.removed, root, 'direct')) {
8861
+ return;
8862
+ }
8656
8863
  this.commandQueue.run(createRemoveTextCommand(id), this.model);
8657
8864
  var removal = this.computeRemovalDiff(before);
8658
8865
  this.emitChange(removal.patches);
@@ -8847,40 +9054,22 @@ var DiagramEngine = /** @class */ (function () {
8847
9054
  if (selected.length === 0)
8848
9055
  return;
8849
9056
  var before = this.model.toState();
8850
- var elementIds = [];
8851
9057
  selected.forEach(function (id) {
8852
- if (_this.model.getElement(id))
8853
- elementIds.push(id);
8854
- else if (_this.model.getPort(id))
8855
- ;
8856
- else if (_this.model.getLink(id))
8857
- ;
8858
- else if (_this.model.getText(id))
8859
- ;
8860
- });
8861
- selected.forEach(function (id) {
8862
- if (_this.model.getElement(id)) {
8863
- _this.commandQueue.run(createRemoveElementCommand(id), _this.model);
8864
- return;
8865
- }
8866
- if (_this.model.getPort(id)) {
8867
- _this.commandQueue.run(createRemovePortCommand(id), _this.model);
9058
+ var root = _this.resolveDeletionRoot(id);
9059
+ if (!root)
8868
9060
  return;
8869
- }
8870
- if (_this.model.getLink(id)) {
8871
- _this.commandQueue.run(createRemoveLinkCommand(id), _this.model);
9061
+ var currentState = _this.model.toState();
9062
+ var plannedRemoval = _this.planRemoval(currentState, root);
9063
+ if (!plannedRemoval || _this.emitDeletionLifecycleEvents(plannedRemoval.removed, root, 'selection')) {
8872
9064
  return;
8873
9065
  }
8874
- if (_this.model.getText(id)) {
8875
- _this.commandQueue.run(createRemoveTextCommand(id), _this.model);
8876
- }
9066
+ _this.applyRemovalCommand(root);
8877
9067
  });
8878
9068
  var removal = this.computeRemovalDiff(before);
9069
+ if (removal.patches.length === 0)
9070
+ return;
8879
9071
  this.emitChange(removal.patches);
8880
9072
  this.emitEntityDeletionEvents(removal.removed);
8881
- elementIds.forEach(function (elementId) { return _this.events.emit('elementDeleted', { elementId: elementId }); });
8882
- this.selection.clear();
8883
- this.emitSelection();
8884
9073
  };
8885
9074
  DiagramEngine.prototype.setViewport = function (pan, zoom) {
8886
9075
  var hasPanChange = this.viewport.pan.x !== pan.x || this.viewport.pan.y !== pan.y;
@@ -8933,6 +9122,9 @@ var DiagramEngine = /** @class */ (function () {
8933
9122
  DiagramEngine.prototype.emitElementClick = function (elementId, pointer, isMulti) {
8934
9123
  this.events.emit('elementClick', { elementId: elementId, pointer: pointer, isMulti: isMulti });
8935
9124
  };
9125
+ DiagramEngine.prototype.emitElementDoubleClick = function (elementId, pointer, isMulti) {
9126
+ this.events.emit('elementDoubleClick', { elementId: elementId, pointer: pointer, isMulti: isMulti });
9127
+ };
8936
9128
  DiagramEngine.prototype.emitElementLinkStarted = function (event) {
8937
9129
  this.events.emit('elementLinkStarted', event);
8938
9130
  };
@@ -9576,8 +9768,8 @@ var DiagramEngine = /** @class */ (function () {
9576
9768
  });
9577
9769
  return { patches: normalizedPatches, movedPortIds: Array.from(movedPortIds) };
9578
9770
  };
9579
- DiagramEngine.prototype.computeRemovalDiff = function (before) {
9580
- var after = this.model.toState();
9771
+ DiagramEngine.prototype.computeRemovalDiff = function (before, after) {
9772
+ if (after === void 0) { after = this.model.toState(); }
9581
9773
  var removedPatches = [];
9582
9774
  var beforeElements = new Set(before.elements.map(function (element) { return element.id; }));
9583
9775
  var beforePorts = new Set(before.ports.map(function (port) { return port.id; }));
@@ -9587,9 +9779,13 @@ var DiagramEngine = /** @class */ (function () {
9587
9779
  var afterPorts = new Set(after.ports.map(function (port) { return port.id; }));
9588
9780
  var afterLinks = new Set(after.links.map(function (link) { return link.id; }));
9589
9781
  var afterTexts = new Set(after.texts.map(function (text) { return text.id; }));
9782
+ var removedElements = [];
9590
9783
  beforeElements.forEach(function (id) {
9591
9784
  if (!afterElements.has(id))
9592
9785
  removedPatches.push(patchRemove('element', id));
9786
+ var removedElement = before.elements.find(function (element) { return element.id === id; });
9787
+ if (!afterElements.has(id) && removedElement)
9788
+ removedElements.push(removedElement);
9593
9789
  });
9594
9790
  var removedPorts = [];
9595
9791
  beforePorts.forEach(function (id) {
@@ -9620,11 +9816,144 @@ var DiagramEngine = /** @class */ (function () {
9620
9816
  });
9621
9817
  return {
9622
9818
  patches: removedPatches,
9623
- removed: { ports: removedPorts, links: removedLinks, texts: removedTexts },
9819
+ removed: { elements: removedElements, ports: removedPorts, links: removedLinks, texts: removedTexts },
9624
9820
  };
9625
9821
  };
9822
+ DiagramEngine.prototype.resolveDeletionRoot = function (id) {
9823
+ if (this.model.getElement(id))
9824
+ return { entity: 'element', id: id };
9825
+ if (this.model.getPort(id))
9826
+ return { entity: 'port', id: id };
9827
+ if (this.model.getLink(id))
9828
+ return { entity: 'link', id: id };
9829
+ if (this.model.getText(id))
9830
+ return { entity: 'text', id: id };
9831
+ return null;
9832
+ };
9833
+ DiagramEngine.prototype.applyRemovalCommand = function (root) {
9834
+ if (root.entity === 'element') {
9835
+ this.commandQueue.run(createRemoveElementCommand(root.id), this.model);
9836
+ return;
9837
+ }
9838
+ if (root.entity === 'port') {
9839
+ this.commandQueue.run(createRemovePortCommand(root.id), this.model);
9840
+ return;
9841
+ }
9842
+ if (root.entity === 'link') {
9843
+ this.commandQueue.run(createRemoveLinkCommand(root.id), this.model);
9844
+ return;
9845
+ }
9846
+ this.commandQueue.run(createRemoveTextCommand(root.id), this.model);
9847
+ };
9848
+ DiagramEngine.prototype.planRemoval = function (before, root) {
9849
+ var tempModel = new DiagramModel();
9850
+ tempModel.load(before);
9851
+ if (root.entity === 'element') {
9852
+ tempModel.removeElement(root.id);
9853
+ }
9854
+ else if (root.entity === 'port') {
9855
+ tempModel.removePort(root.id);
9856
+ }
9857
+ else if (root.entity === 'link') {
9858
+ tempModel.removeLink(root.id);
9859
+ }
9860
+ else {
9861
+ tempModel.removeText(root.id);
9862
+ }
9863
+ return this.computeRemovalDiff(before, tempModel.toState());
9864
+ };
9865
+ DiagramEngine.prototype.emitDeletionLifecycleEvents = function (removed, root, rootTrigger) {
9866
+ for (var _i = 0, _a = removed.elements; _i < _a.length; _i++) {
9867
+ var element = _a[_i];
9868
+ var trigger = root.entity === 'element' && element.id === root.id ? rootTrigger : 'cascade';
9869
+ if (this.emitElementDeleting({
9870
+ elementId: element.id,
9871
+ trigger: trigger,
9872
+ root: root,
9873
+ })) {
9874
+ return true;
9875
+ }
9876
+ }
9877
+ for (var _b = 0, _c = removed.ports; _b < _c.length; _b++) {
9878
+ var port = _c[_b];
9879
+ var trigger = root.entity === 'port' && port.id === root.id ? rootTrigger : 'cascade';
9880
+ if (this.emitPortDeleting({
9881
+ portId: port.id,
9882
+ elementId: port.elementId,
9883
+ trigger: trigger,
9884
+ root: root,
9885
+ })) {
9886
+ return true;
9887
+ }
9888
+ }
9889
+ for (var _d = 0, _e = removed.links; _d < _e.length; _d++) {
9890
+ var link = _e[_d];
9891
+ var trigger = root.entity === 'link' && link.id === root.id ? rootTrigger : 'cascade';
9892
+ if (this.emitLinkDeleting({
9893
+ linkId: link.id,
9894
+ sourcePortId: link.sourcePortId,
9895
+ targetPortId: link.targetPortId,
9896
+ trigger: trigger,
9897
+ root: root,
9898
+ })) {
9899
+ return true;
9900
+ }
9901
+ }
9902
+ for (var _f = 0, _g = removed.texts; _f < _g.length; _f++) {
9903
+ var text = _g[_f];
9904
+ var trigger = root.entity === 'text' && text.id === root.id ? rootTrigger : 'cascade';
9905
+ if (this.emitTextDeleting({
9906
+ textId: text.id,
9907
+ ownerId: text.ownerId,
9908
+ trigger: trigger,
9909
+ root: root,
9910
+ })) {
9911
+ return true;
9912
+ }
9913
+ }
9914
+ return false;
9915
+ };
9916
+ DiagramEngine.prototype.emitElementDeleting = function (event) {
9917
+ var cancelled = false;
9918
+ var payload = __assign(__assign({}, event), { cancelled: false, cancel: function () {
9919
+ cancelled = true;
9920
+ payload.cancelled = true;
9921
+ } });
9922
+ this.events.emit('elementDeleting', payload);
9923
+ return cancelled || payload.cancelled;
9924
+ };
9925
+ DiagramEngine.prototype.emitPortDeleting = function (event) {
9926
+ var cancelled = false;
9927
+ var payload = __assign(__assign({}, event), { cancelled: false, cancel: function () {
9928
+ cancelled = true;
9929
+ payload.cancelled = true;
9930
+ } });
9931
+ this.events.emit('portDeleting', payload);
9932
+ return cancelled || payload.cancelled;
9933
+ };
9934
+ DiagramEngine.prototype.emitLinkDeleting = function (event) {
9935
+ var cancelled = false;
9936
+ var payload = __assign(__assign({}, event), { cancelled: false, cancel: function () {
9937
+ cancelled = true;
9938
+ payload.cancelled = true;
9939
+ } });
9940
+ this.events.emit('linkDeleting', payload);
9941
+ return cancelled || payload.cancelled;
9942
+ };
9943
+ DiagramEngine.prototype.emitTextDeleting = function (event) {
9944
+ var cancelled = false;
9945
+ var payload = __assign(__assign({}, event), { cancelled: false, cancel: function () {
9946
+ cancelled = true;
9947
+ payload.cancelled = true;
9948
+ } });
9949
+ this.events.emit('textDeleting', payload);
9950
+ return cancelled || payload.cancelled;
9951
+ };
9626
9952
  DiagramEngine.prototype.emitEntityDeletionEvents = function (removed) {
9627
9953
  var _this = this;
9954
+ removed.elements.forEach(function (element) {
9955
+ _this.events.emit('elementDeleted', { elementId: element.id });
9956
+ });
9628
9957
  removed.ports.forEach(function (port) {
9629
9958
  _this.events.emit('portDeleted', { portId: port.id, elementId: port.elementId });
9630
9959
  });
@@ -10774,6 +11103,7 @@ var KonvaInteraction = /** @class */ (function () {
10774
11103
  this.shapeHoverControls = this.normalizeShapeHoverControls(config.shapeHoverControls);
10775
11104
  this.onShapeHoverControlInteracted = config.onShapeHoverControlInteracted;
10776
11105
  this.onShapeHoverControlActivated = config.onShapeHoverControlActivated;
11106
+ this.onCreateLinkTargetPort = config.onCreateLinkTargetPort;
10777
11107
  }
10778
11108
  KonvaInteraction.prototype.setShapeHoverControls = function (controls) {
10779
11109
  this.shapeHoverControls = this.normalizeShapeHoverControls(controls);
@@ -10790,6 +11120,9 @@ var KonvaInteraction = /** @class */ (function () {
10790
11120
  var sourceElementId = this.engine.getPortElementId(sourcePortId);
10791
11121
  if (!sourceElementId)
10792
11122
  return;
11123
+ var sourcePort = this.getPortById(sourcePortId);
11124
+ if (!sourcePort)
11125
+ return;
10793
11126
  var sourcePoint = (_a = this.engine.getPortLinkWorldPosition(sourcePortId)) !== null && _a !== void 0 ? _a : this.engine.getPortWorldPosition(sourcePortId);
10794
11127
  if (!sourcePoint)
10795
11128
  return;
@@ -10806,6 +11139,7 @@ var KonvaInteraction = /** @class */ (function () {
10806
11139
  this.programmaticLinkSession = {
10807
11140
  sourcePortId: sourcePortId,
10808
11141
  sourceElementId: sourceElementId,
11142
+ sourcePort: this.clonePortData(sourcePort),
10809
11143
  start: start,
10810
11144
  current: start,
10811
11145
  };
@@ -10815,6 +11149,7 @@ var KonvaInteraction = /** @class */ (function () {
10815
11149
  mode: 'link-drag',
10816
11150
  sourcePortId: sourcePortId,
10817
11151
  sourceElementId: sourceElementId,
11152
+ sourcePort: this.clonePortData(sourcePort),
10818
11153
  start: start,
10819
11154
  current: start,
10820
11155
  isMulti: false,
@@ -10830,7 +11165,7 @@ var KonvaInteraction = /** @class */ (function () {
10830
11165
  }
10831
11166
  };
10832
11167
  KonvaInteraction.prototype.updateLinkPreview = function (pointer) {
10833
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
11168
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
10834
11169
  if (this.programmaticLinkSession) {
10835
11170
  this.programmaticLinkSession.current = __assign({}, pointer);
10836
11171
  }
@@ -10842,28 +11177,29 @@ var KonvaInteraction = /** @class */ (function () {
10842
11177
  return;
10843
11178
  }
10844
11179
  var sourcePortId = (_c = (_b = this.programmaticLinkSession) === null || _b === void 0 ? void 0 : _b.sourcePortId) !== null && _c !== void 0 ? _c : (((_d = this.dragState) === null || _d === void 0 ? void 0 : _d.mode) === 'link-drag' ? this.dragState.sourcePortId : null);
11180
+ var sourceElementId = (_f = (_e = this.programmaticLinkSession) === null || _e === void 0 ? void 0 : _e.sourceElementId) !== null && _f !== void 0 ? _f : (((_g = this.dragState) === null || _g === void 0 ? void 0 : _g.mode) === 'link-drag' ? this.dragState.sourceElementId : null);
10845
11181
  if (!sourcePortId)
10846
11182
  return;
10847
11183
  var source = this.resolveLinkPreviewSource(sourcePortId, pointer);
10848
11184
  if (source) {
10849
- (_e = this.renderer) === null || _e === void 0 ? void 0 : _e.renderTempLink([source, pointer]);
11185
+ (_h = this.renderer) === null || _h === void 0 ? void 0 : _h.renderTempLink([source, pointer]);
10850
11186
  }
10851
11187
  var hit = this.resolveHit(pointer);
10852
- if ((hit === null || hit === void 0 ? void 0 : hit.type) === 'element') {
10853
- var placeholder = this.createPlaceholderPort(hit.id, pointer, sourcePortId);
11188
+ if ((hit === null || hit === void 0 ? void 0 : hit.type) === 'element' && sourceElementId) {
11189
+ var placeholder = this.createPlaceholderPort(hit.id, pointer, sourcePortId, sourceElementId);
10854
11190
  if (placeholder) {
10855
11191
  var hostElement = this.getElementById(hit.id);
10856
11192
  if (hostElement) {
10857
- var hostWorld = (_f = this.engine.getElementWorldPosition(hit.id)) !== null && _f !== void 0 ? _f : hostElement.position;
10858
- (_h = (_g = this.renderer) === null || _g === void 0 ? void 0 : _g.renderPortPlaceholder) === null || _h === void 0 ? void 0 : _h.call(_g, placeholder, { id: hostElement.id, position: hostWorld, size: hostElement.size, shapeId: hostElement.shapeId });
11193
+ var hostWorld = (_j = this.engine.getElementWorldPosition(hit.id)) !== null && _j !== void 0 ? _j : hostElement.position;
11194
+ (_l = (_k = this.renderer) === null || _k === void 0 ? void 0 : _k.renderPortPlaceholder) === null || _l === void 0 ? void 0 : _l.call(_k, placeholder, { id: hostElement.id, position: hostWorld, size: hostElement.size, shapeId: hostElement.shapeId });
10859
11195
  }
10860
11196
  else {
10861
- (_k = (_j = this.renderer) === null || _j === void 0 ? void 0 : _j.renderPortPlaceholder) === null || _k === void 0 ? void 0 : _k.call(_j, placeholder);
11197
+ (_o = (_m = this.renderer) === null || _m === void 0 ? void 0 : _m.renderPortPlaceholder) === null || _o === void 0 ? void 0 : _o.call(_m, placeholder);
10862
11198
  }
10863
11199
  }
10864
11200
  return;
10865
11201
  }
10866
- (_m = (_l = this.renderer) === null || _l === void 0 ? void 0 : _l.clearPortPlaceholder) === null || _m === void 0 ? void 0 : _m.call(_l);
11202
+ (_q = (_p = this.renderer) === null || _p === void 0 ? void 0 : _p.clearPortPlaceholder) === null || _q === void 0 ? void 0 : _q.call(_p);
10867
11203
  };
10868
11204
  KonvaInteraction.prototype.completeLinkToPort = function (targetPortId) {
10869
11205
  var _a, _b;
@@ -11025,10 +11361,14 @@ var KonvaInteraction = /** @class */ (function () {
11025
11361
  }
11026
11362
  }
11027
11363
  else {
11364
+ var sourcePort = _this.getPortById(hit.id);
11365
+ if (!sourcePort)
11366
+ return;
11028
11367
  _this.dragState = {
11029
11368
  mode: 'link-drag',
11030
11369
  sourcePortId: hit.id,
11031
11370
  sourceElementId: elementId,
11371
+ sourcePort: _this.clonePortData(sourcePort),
11032
11372
  start: point,
11033
11373
  current: point,
11034
11374
  isMulti: isMulti,
@@ -11210,7 +11550,7 @@ var KonvaInteraction = /** @class */ (function () {
11210
11550
  }
11211
11551
  }
11212
11552
  else if ((hit === null || hit === void 0 ? void 0 : hit.type) === 'element') {
11213
- var placeholder = _this.createPlaceholderPort(hit.id, point, _this.dragState.sourcePortId);
11553
+ var placeholder = _this.createPlaceholderPort(hit.id, point, _this.dragState.sourcePortId, _this.dragState.sourceElementId);
11214
11554
  if (placeholder) {
11215
11555
  var hostElement = _this.getElementById(hit.id);
11216
11556
  if (hostElement) {
@@ -11452,15 +11792,29 @@ var KonvaInteraction = /** @class */ (function () {
11452
11792
  this.stage.on(upEvents, pointerUp);
11453
11793
  this.handlers.push([upEvents, pointerUp]);
11454
11794
  var doubleClick = function () {
11795
+ var args = [];
11796
+ for (var _i = 0; _i < arguments.length; _i++) {
11797
+ args[_i] = arguments[_i];
11798
+ }
11799
+ var event = args[0];
11800
+ var nativeEvent = event === null || event === void 0 ? void 0 : event.evt;
11455
11801
  var point = _this.getPointerPosition();
11456
11802
  if (!point)
11457
11803
  return;
11458
11804
  var hit = _this.resolveHit(point);
11459
- if (!hit || hit.type !== 'text')
11805
+ if (!hit)
11460
11806
  return;
11461
- if (!_this.isTextEditable(hit.id))
11807
+ if (hit.type === 'text') {
11808
+ if (!_this.isTextEditable(hit.id))
11809
+ return;
11810
+ _this.startTextEdit(hit.id);
11462
11811
  return;
11463
- _this.startTextEdit(hit.id);
11812
+ }
11813
+ if (hit.type !== 'element')
11814
+ return;
11815
+ var isMulti = Boolean(nativeEvent && (nativeEvent.ctrlKey || nativeEvent.metaKey || nativeEvent.shiftKey));
11816
+ var pointerInfo = _this.buildPointerInfo(point, nativeEvent);
11817
+ _this.engine.emitElementDoubleClick(hit.id, pointerInfo, isMulti);
11464
11818
  };
11465
11819
  this.stage.on('dblclick dbltap', doubleClick);
11466
11820
  this.handlers.push(['dblclick dbltap', doubleClick]);
@@ -12885,7 +13239,8 @@ var KonvaInteraction = /** @class */ (function () {
12885
13239
  return { createdLinkId: createdLinkId, targetPortId: targetPortId, targetElementId: targetElementId };
12886
13240
  };
12887
13241
  KonvaInteraction.prototype.tryCreateLinkToElement = function (sourcePortId, sourceElementId, targetElementId, worldPoint) {
12888
- var targetPort = this.createPortForLink(targetElementId, worldPoint, sourcePortId);
13242
+ var _a, _b;
13243
+ var targetPort = this.createPortForLink(targetElementId, worldPoint, sourcePortId, sourceElementId);
12889
13244
  if (!targetPort) {
12890
13245
  return { createdLinkId: null, targetPortId: null, targetElementId: null };
12891
13246
  }
@@ -12901,7 +13256,10 @@ var KonvaInteraction = /** @class */ (function () {
12901
13256
  return { createdLinkId: null, targetPortId: targetPort.id, targetElementId: targetElementId };
12902
13257
  }
12903
13258
  this.engine.addPortToElement(targetElementId, targetPort);
12904
- this.engine.movePortTo(targetPort.id, worldPoint.x, worldPoint.y);
13259
+ var targetElementWorld = (_a = this.engine.getElementWorldPosition(targetElementId)) !== null && _a !== void 0 ? _a : (_b = this.getElementById(targetElementId)) === null || _b === void 0 ? void 0 : _b.position;
13260
+ if (targetElementWorld) {
13261
+ this.engine.movePortTo(targetPort.id, targetElementWorld.x + targetPort.position.x, targetElementWorld.y + targetPort.position.y);
13262
+ }
12905
13263
  var createdLinkId = createId();
12906
13264
  this.engine.addLink({
12907
13265
  id: createdLinkId,
@@ -12911,61 +13269,139 @@ var KonvaInteraction = /** @class */ (function () {
12911
13269
  });
12912
13270
  return { createdLinkId: createdLinkId, targetPortId: targetPort.id, targetElementId: targetElementId };
12913
13271
  };
12914
- KonvaInteraction.prototype.createPortForLink = function (elementId, worldPoint, sourcePortId) {
12915
- var _a, _b, _c, _d;
12916
- var element = this.getElementById(elementId);
12917
- if (!element)
13272
+ KonvaInteraction.prototype.createPortForLink = function (elementId, worldPoint, sourcePortId, sourceElementId) {
13273
+ var resolved = this.resolveLinkTargetPortDraft(elementId, worldPoint, sourcePortId, sourceElementId, 'commit');
13274
+ if (!resolved)
12918
13275
  return null;
12919
- var elementPosition = (_a = this.engine.getElementWorldPosition(elementId)) !== null && _a !== void 0 ? _a : element.position;
12920
- var relative = {
12921
- x: worldPoint.x - elementPosition.x,
12922
- y: worldPoint.y - elementPosition.y,
12923
- };
12924
- var sourcePort = this.getPortById(sourcePortId);
12925
- var destinationMoveMode = ((_b = element.portMovement) === null || _b === void 0 ? void 0 : _b.moveMode) && element.portMovement.moveMode !== 'anchors'
12926
- ? element.portMovement.moveMode
12927
- : undefined;
12928
13276
  return {
12929
13277
  id: createId(),
12930
13278
  elementId: elementId,
12931
- position: relative,
12932
- shapeId: sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.shapeId,
12933
- size: (sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.size) ? __assign({}, sourcePort.size) : undefined,
12934
- style: (sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.style) ? __assign({}, sourcePort.style) : undefined,
12935
- moveMode: destinationMoveMode !== null && destinationMoveMode !== void 0 ? destinationMoveMode : sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.moveMode,
12936
- anchorCenter: (_c = sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.anchorCenter) !== null && _c !== void 0 ? _c : true,
12937
- orientToHostBorder: (_d = sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.orientToHostBorder) !== null && _d !== void 0 ? _d : true,
12938
- placementPoint: (sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.placementPoint) ? __assign({}, sourcePort.placementPoint) : undefined,
12939
- linkAttachPoint: (sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.linkAttachPoint) ? __assign({}, sourcePort.linkAttachPoint) : undefined,
12940
- externalLinkAttachPoint: (sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.externalLinkAttachPoint) ? __assign({}, sourcePort.externalLinkAttachPoint) : undefined,
12941
- internalLinkAttachPoint: (sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.internalLinkAttachPoint) ? __assign({}, sourcePort.internalLinkAttachPoint) : undefined,
12942
- rotationPivot: (sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.rotationPivot) ? __assign({}, sourcePort.rotationPivot) : undefined,
13279
+ position: __assign({}, resolved.draft.position),
13280
+ shapeId: resolved.draft.shapeId,
13281
+ size: resolved.draft.size ? __assign({}, resolved.draft.size) : undefined,
13282
+ style: resolved.draft.style ? __assign({}, resolved.draft.style) : undefined,
13283
+ textIds: resolved.draft.textIds ? __spreadArray([], resolved.draft.textIds, true) : undefined,
13284
+ moveMode: resolved.draft.moveMode,
13285
+ anchorCenter: resolved.draft.anchorCenter,
13286
+ orientToHostBorder: resolved.draft.orientToHostBorder,
13287
+ placementPoint: resolved.draft.placementPoint ? __assign({}, resolved.draft.placementPoint) : undefined,
13288
+ linkAttachPoint: resolved.draft.linkAttachPoint ? __assign({}, resolved.draft.linkAttachPoint) : undefined,
13289
+ externalLinkAttachPoint: resolved.draft.externalLinkAttachPoint ? __assign({}, resolved.draft.externalLinkAttachPoint) : undefined,
13290
+ internalLinkAttachPoint: resolved.draft.internalLinkAttachPoint ? __assign({}, resolved.draft.internalLinkAttachPoint) : undefined,
13291
+ rotationPivot: resolved.draft.rotationPivot ? __assign({}, resolved.draft.rotationPivot) : undefined,
13292
+ currentAnchorId: resolved.draft.currentAnchorId,
12943
13293
  };
12944
13294
  };
12945
- KonvaInteraction.prototype.createPlaceholderPort = function (elementId, worldPoint, sourcePortId) {
12946
- var _a, _b, _c;
12947
- var element = this.getElementById(elementId);
12948
- var sourcePort = this.getPortById(sourcePortId);
12949
- var destinationMoveMode = ((_a = element === null || element === void 0 ? void 0 : element.portMovement) === null || _a === void 0 ? void 0 : _a.moveMode) && element.portMovement.moveMode !== 'anchors'
12950
- ? element.portMovement.moveMode
12951
- : undefined;
13295
+ KonvaInteraction.prototype.createPlaceholderPort = function (elementId, worldPoint, sourcePortId, sourceElementId) {
13296
+ var _a;
13297
+ var resolved = this.resolveLinkTargetPortDraft(elementId, worldPoint, sourcePortId, sourceElementId, 'preview');
13298
+ if (!resolved)
13299
+ return null;
13300
+ var hostWorld = (_a = this.engine.getElementWorldPosition(elementId)) !== null && _a !== void 0 ? _a : resolved.targetElement.position;
12952
13301
  return {
12953
13302
  id: "port-placeholder:".concat(sourcePortId),
12954
13303
  elementId: elementId,
12955
- position: { x: worldPoint.x, y: worldPoint.y },
12956
- shapeId: sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.shapeId,
12957
- size: (sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.size) ? __assign({}, sourcePort.size) : undefined,
12958
- style: (sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.style) ? __assign({}, sourcePort.style) : undefined,
12959
- moveMode: destinationMoveMode !== null && destinationMoveMode !== void 0 ? destinationMoveMode : sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.moveMode,
12960
- anchorCenter: (_b = sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.anchorCenter) !== null && _b !== void 0 ? _b : true,
12961
- orientToHostBorder: (_c = sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.orientToHostBorder) !== null && _c !== void 0 ? _c : true,
12962
- placementPoint: (sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.placementPoint) ? __assign({}, sourcePort.placementPoint) : undefined,
12963
- linkAttachPoint: (sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.linkAttachPoint) ? __assign({}, sourcePort.linkAttachPoint) : undefined,
12964
- externalLinkAttachPoint: (sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.externalLinkAttachPoint) ? __assign({}, sourcePort.externalLinkAttachPoint) : undefined,
12965
- internalLinkAttachPoint: (sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.internalLinkAttachPoint) ? __assign({}, sourcePort.internalLinkAttachPoint) : undefined,
12966
- rotationPivot: (sourcePort === null || sourcePort === void 0 ? void 0 : sourcePort.rotationPivot) ? __assign({}, sourcePort.rotationPivot) : undefined,
13304
+ position: {
13305
+ x: hostWorld.x + resolved.draft.position.x,
13306
+ y: hostWorld.y + resolved.draft.position.y,
13307
+ },
13308
+ shapeId: resolved.draft.shapeId,
13309
+ size: resolved.draft.size ? __assign({}, resolved.draft.size) : undefined,
13310
+ style: resolved.draft.style ? __assign({}, resolved.draft.style) : undefined,
13311
+ textIds: resolved.draft.textIds ? __spreadArray([], resolved.draft.textIds, true) : undefined,
13312
+ moveMode: resolved.draft.moveMode,
13313
+ anchorCenter: resolved.draft.anchorCenter,
13314
+ orientToHostBorder: resolved.draft.orientToHostBorder,
13315
+ placementPoint: resolved.draft.placementPoint ? __assign({}, resolved.draft.placementPoint) : undefined,
13316
+ linkAttachPoint: resolved.draft.linkAttachPoint ? __assign({}, resolved.draft.linkAttachPoint) : undefined,
13317
+ externalLinkAttachPoint: resolved.draft.externalLinkAttachPoint ? __assign({}, resolved.draft.externalLinkAttachPoint) : undefined,
13318
+ internalLinkAttachPoint: resolved.draft.internalLinkAttachPoint ? __assign({}, resolved.draft.internalLinkAttachPoint) : undefined,
13319
+ rotationPivot: resolved.draft.rotationPivot ? __assign({}, resolved.draft.rotationPivot) : undefined,
13320
+ currentAnchorId: resolved.draft.currentAnchorId,
13321
+ };
13322
+ };
13323
+ KonvaInteraction.prototype.resolveLinkTargetPortDraft = function (elementId, worldPoint, sourcePortId, sourceElementId, phase) {
13324
+ var _a;
13325
+ var targetElement = this.getElementById(elementId);
13326
+ var sourcePort = this.resolveLinkSourcePort(sourcePortId);
13327
+ if (!targetElement || !sourcePort)
13328
+ return null;
13329
+ var defaultDraft = this.buildDefaultLinkTargetPortDraft(targetElement, worldPoint, sourcePort);
13330
+ var override = (_a = this.onCreateLinkTargetPort) === null || _a === void 0 ? void 0 : _a.call(this, {
13331
+ phase: phase,
13332
+ pointer: __assign({}, worldPoint),
13333
+ sourcePortId: sourcePortId,
13334
+ sourceElementId: sourceElementId,
13335
+ targetElementId: elementId,
13336
+ sourcePort: this.clonePortData(sourcePort),
13337
+ targetElement: this.cloneElementData(targetElement),
13338
+ defaultPort: this.cloneLinkTargetPortDraft(defaultDraft),
13339
+ });
13340
+ var mergedDraft = this.mergeLinkTargetPortDraft(defaultDraft, override);
13341
+ var normalizedDraft = this.engine.normalizePortDraftForElement(elementId, mergedDraft);
13342
+ if (!normalizedDraft)
13343
+ return null;
13344
+ return {
13345
+ draft: normalizedDraft,
13346
+ targetElement: this.cloneElementData(targetElement),
13347
+ };
13348
+ };
13349
+ KonvaInteraction.prototype.buildDefaultLinkTargetPortDraft = function (element, worldPoint, sourcePort) {
13350
+ var _a, _b, _c, _d;
13351
+ var elementPosition = (_a = this.engine.getElementWorldPosition(element.id)) !== null && _a !== void 0 ? _a : element.position;
13352
+ var destinationMoveMode = ((_b = element.portMovement) === null || _b === void 0 ? void 0 : _b.moveMode) && element.portMovement.moveMode !== 'anchors'
13353
+ ? element.portMovement.moveMode
13354
+ : undefined;
13355
+ return {
13356
+ position: {
13357
+ x: worldPoint.x - elementPosition.x,
13358
+ y: worldPoint.y - elementPosition.y,
13359
+ },
13360
+ shapeId: sourcePort.shapeId,
13361
+ size: sourcePort.size ? __assign({}, sourcePort.size) : undefined,
13362
+ style: sourcePort.style ? __assign({}, sourcePort.style) : undefined,
13363
+ moveMode: destinationMoveMode !== null && destinationMoveMode !== void 0 ? destinationMoveMode : sourcePort.moveMode,
13364
+ anchorCenter: (_c = sourcePort.anchorCenter) !== null && _c !== void 0 ? _c : true,
13365
+ orientToHostBorder: (_d = sourcePort.orientToHostBorder) !== null && _d !== void 0 ? _d : true,
13366
+ placementPoint: sourcePort.placementPoint ? __assign({}, sourcePort.placementPoint) : undefined,
13367
+ linkAttachPoint: sourcePort.linkAttachPoint ? __assign({}, sourcePort.linkAttachPoint) : undefined,
13368
+ externalLinkAttachPoint: sourcePort.externalLinkAttachPoint ? __assign({}, sourcePort.externalLinkAttachPoint) : undefined,
13369
+ internalLinkAttachPoint: sourcePort.internalLinkAttachPoint ? __assign({}, sourcePort.internalLinkAttachPoint) : undefined,
13370
+ rotationPivot: sourcePort.rotationPivot ? __assign({}, sourcePort.rotationPivot) : undefined,
12967
13371
  };
12968
13372
  };
13373
+ KonvaInteraction.prototype.mergeLinkTargetPortDraft = function (defaultDraft, override) {
13374
+ return this.cloneLinkTargetPortDraft(__assign(__assign({}, defaultDraft), (override !== null && override !== void 0 ? override : {})));
13375
+ };
13376
+ KonvaInteraction.prototype.resolveLinkSourcePort = function (sourcePortId) {
13377
+ var _a, _b;
13378
+ if (((_a = this.programmaticLinkSession) === null || _a === void 0 ? void 0 : _a.sourcePortId) === sourcePortId) {
13379
+ return this.clonePortData(this.programmaticLinkSession.sourcePort);
13380
+ }
13381
+ if (((_b = this.dragState) === null || _b === void 0 ? void 0 : _b.mode) === 'link-drag' && this.dragState.sourcePortId === sourcePortId) {
13382
+ return this.clonePortData(this.dragState.sourcePort);
13383
+ }
13384
+ var sourcePort = this.getPortById(sourcePortId);
13385
+ return sourcePort ? this.clonePortData(sourcePort) : null;
13386
+ };
13387
+ KonvaInteraction.prototype.clonePortData = function (port) {
13388
+ return __assign(__assign({}, port), { position: __assign({}, port.position), size: port.size ? __assign({}, port.size) : undefined, style: port.style ? __assign({}, port.style) : undefined, textIds: port.textIds ? __spreadArray([], port.textIds, true) : undefined, placementPoint: port.placementPoint ? __assign({}, port.placementPoint) : undefined, linkAttachPoint: port.linkAttachPoint ? __assign({}, port.linkAttachPoint) : undefined, externalLinkAttachPoint: port.externalLinkAttachPoint ? __assign({}, port.externalLinkAttachPoint) : undefined, internalLinkAttachPoint: port.internalLinkAttachPoint ? __assign({}, port.internalLinkAttachPoint) : undefined, rotationPivot: port.rotationPivot ? __assign({}, port.rotationPivot) : undefined });
13389
+ };
13390
+ KonvaInteraction.prototype.cloneLinkTargetPortDraft = function (draft) {
13391
+ return __assign(__assign({}, draft), { position: __assign({}, draft.position), size: draft.size ? __assign({}, draft.size) : undefined, style: draft.style ? __assign({}, draft.style) : undefined, textIds: draft.textIds ? __spreadArray([], draft.textIds, true) : undefined, placementPoint: draft.placementPoint ? __assign({}, draft.placementPoint) : undefined, linkAttachPoint: draft.linkAttachPoint ? __assign({}, draft.linkAttachPoint) : undefined, externalLinkAttachPoint: draft.externalLinkAttachPoint ? __assign({}, draft.externalLinkAttachPoint) : undefined, internalLinkAttachPoint: draft.internalLinkAttachPoint ? __assign({}, draft.internalLinkAttachPoint) : undefined, rotationPivot: draft.rotationPivot ? __assign({}, draft.rotationPivot) : undefined });
13392
+ };
13393
+ KonvaInteraction.prototype.cloneElementData = function (element) {
13394
+ return __assign(__assign({}, element), { position: __assign({}, element.position), size: __assign({}, element.size), style: element.style ? __assign({}, element.style) : undefined, portIds: element.portIds ? __spreadArray([], element.portIds, true) : undefined, textIds: element.textIds ? __spreadArray([], element.textIds, true) : undefined, layout: element.layout ? __assign({}, element.layout) : undefined, childElementInteraction: element.childElementInteraction ? __assign({}, element.childElementInteraction) : undefined, portMovement: element.portMovement
13395
+ ? __assign(__assign({}, element.portMovement), { anchorConstraint: element.portMovement.anchorConstraint
13396
+ ? __assign({}, element.portMovement.anchorConstraint) : undefined, positionLimits: element.portMovement.positionLimits
13397
+ ? {
13398
+ x: element.portMovement.positionLimits.x
13399
+ ? __assign({}, element.portMovement.positionLimits.x) : undefined,
13400
+ y: element.portMovement.positionLimits.y
13401
+ ? __assign({}, element.portMovement.positionLimits.y) : undefined,
13402
+ }
13403
+ : undefined }) : undefined });
13404
+ };
12969
13405
  KonvaInteraction.prototype.getElementById = function (id) {
12970
13406
  return this.engine.getState().elements.find(function (element) { return element.id === id; });
12971
13407
  };
@@ -13896,6 +14332,29 @@ var resolveViewportFitTransform = function (state, viewportSize, options) {
13896
14332
  };
13897
14333
  return { pan: pan, zoom: zoom };
13898
14334
  };
14335
+ var resolveFocusElementTransform = function (state, elementId, viewportSize, currentZoom, options) {
14336
+ var elementsById = new Map(state.elements.map(function (element) { return [element.id, element]; }));
14337
+ var element = elementsById.get(elementId);
14338
+ if (!element)
14339
+ return null;
14340
+ var position = resolveElementWorldPositionInState(elementId, elementsById);
14341
+ if (!position)
14342
+ return null;
14343
+ var safeWidth = Math.max(1, viewportSize.width);
14344
+ var safeHeight = Math.max(1, viewportSize.height);
14345
+ var requestedZoom = options === null || options === void 0 ? void 0 : options.zoom;
14346
+ var zoom = typeof requestedZoom === 'number' && Number.isFinite(requestedZoom)
14347
+ ? clamp(requestedZoom, DEFAULT_VIEWPORT_FIT_MIN_ZOOM, DEFAULT_VIEWPORT_FIT_MAX_ZOOM)
14348
+ : currentZoom;
14349
+ var safeZoom = zoom === 0 ? 1 : zoom;
14350
+ var centerX = position.x + element.size.width / 2;
14351
+ var centerY = position.y + element.size.height / 2;
14352
+ var pan = {
14353
+ x: safeWidth / 2 - centerX * safeZoom,
14354
+ y: safeHeight / 2 - centerY * safeZoom,
14355
+ };
14356
+ return { pan: pan, zoom: zoom };
14357
+ };
13899
14358
  var resolveFitToContentPadding = function (fitToContent) {
13900
14359
  if (typeof fitToContent === 'object' && typeof fitToContent.padding === 'number') {
13901
14360
  return Math.max(0, fitToContent.padding);
@@ -14082,6 +14541,7 @@ var createDiagramEditor = function (config) {
14082
14541
  shapeHoverControls: config.elementShapeHoverControls,
14083
14542
  onShapeHoverControlInteracted: config.onElementShapeHoverControlInteraction,
14084
14543
  onShapeHoverControlActivated: config.onElementShapeHoverControlActivated,
14544
+ onCreateLinkTargetPort: config.onCreateLinkTargetPort,
14085
14545
  });
14086
14546
  interaction.bind();
14087
14547
  if (config.initialState) {
@@ -14129,6 +14589,12 @@ var createDiagramEditor = function (config) {
14129
14589
  return;
14130
14590
  engine.setViewport(transform.pan, transform.zoom);
14131
14591
  },
14592
+ focusElement: function (elementId, options) {
14593
+ var transform = resolveFocusElementTransform(engine.getState(), elementId, { width: stageWidth, height: stageHeight }, engine.getViewport().zoom, options);
14594
+ if (!transform)
14595
+ return;
14596
+ engine.setViewport(transform.pan, transform.zoom);
14597
+ },
14132
14598
  exportImage: function (options) {
14133
14599
  engine.render();
14134
14600
  if (typeof stage.toDataURL !== 'function') {
@@ -14181,7 +14647,7 @@ var useDisplayBoxMetricsUpdater = function () {
14181
14647
  };
14182
14648
 
14183
14649
  var useDemoEditor = function (_a) {
14184
- var createState = _a.createState, elementShapes = _a.elementShapes, portShapes = _a.portShapes, router = _a.router, snapDefault = _a.snapDefault, linkRouteRefreshPolicy = _a.linkRouteRefreshPolicy, linkColorPoolPolicy = _a.linkColorPoolPolicy, elementShapeHoverControls = _a.elementShapeHoverControls, onElementShapeHoverControlInteraction = _a.onElementShapeHoverControlInteraction, onElementShapeHoverControlActivated = _a.onElementShapeHoverControlActivated;
14650
+ var createState = _a.createState, elementShapes = _a.elementShapes, portShapes = _a.portShapes, router = _a.router, snapDefault = _a.snapDefault, linkRouteRefreshPolicy = _a.linkRouteRefreshPolicy, linkColorPoolPolicy = _a.linkColorPoolPolicy, elementShapeHoverControls = _a.elementShapeHoverControls, onElementShapeHoverControlInteraction = _a.onElementShapeHoverControlInteraction, onElementShapeHoverControlActivated = _a.onElementShapeHoverControlActivated, onCreateLinkTargetPort = _a.onCreateLinkTargetPort;
14185
14651
  var containerRef = React.useRef(null);
14186
14652
  var editorRef = React.useRef(null);
14187
14653
  var _b = React.useState(null), diagramState = _b[0], setDiagramState = _b[1];
@@ -14228,6 +14694,7 @@ var useDemoEditor = function (_a) {
14228
14694
  elementShapeHoverControls: elementShapeHoverControls,
14229
14695
  onElementShapeHoverControlInteraction: onElementShapeHoverControlInteraction,
14230
14696
  onElementShapeHoverControlActivated: onElementShapeHoverControlActivated,
14697
+ onCreateLinkTargetPort: onCreateLinkTargetPort,
14231
14698
  onChange: function (event) {
14232
14699
  setDiagramState(event.state);
14233
14700
  var viewportPatch = event.patches.find(function (patch) { return patch.entity === 'viewport'; });
@@ -14275,6 +14742,7 @@ var useDemoEditor = function (_a) {
14275
14742
  elementShapeHoverControls,
14276
14743
  onElementShapeHoverControlInteraction,
14277
14744
  onElementShapeHoverControlActivated,
14745
+ onCreateLinkTargetPort,
14278
14746
  ]);
14279
14747
  return {
14280
14748
  containerRef: containerRef,
@@ -14622,6 +15090,66 @@ var LinkCancelDemo = function () {
14622
15090
  React.createElement(DisplayBoxStage, { containerRef: containerRef })));
14623
15091
  };
14624
15092
 
15093
+ var LinkPortCreationDemo = function () {
15094
+ var _a = React.useState(false), useHostTargetPort = _a[0], setUseHostTargetPort = _a[1];
15095
+ var onCreateLinkTargetPort = React.useMemo(function () {
15096
+ if (!useHostTargetPort)
15097
+ return undefined;
15098
+ return function (_a) {
15099
+ var defaultPort = _a.defaultPort;
15100
+ return ({
15101
+ shapeId: 'port-dark',
15102
+ size: { width: 16, height: 16 },
15103
+ style: {
15104
+ fill: '#f97316',
15105
+ stroke: '#9a3412',
15106
+ strokeWidth: 2,
15107
+ name: 'port',
15108
+ },
15109
+ position: {
15110
+ x: defaultPort.position.x,
15111
+ y: 24,
15112
+ },
15113
+ orientToHostBorder: false,
15114
+ });
15115
+ };
15116
+ }, [useHostTargetPort]);
15117
+ var _b = useDemoEditor({
15118
+ createState: linkPortCreationDemoConfig.createState,
15119
+ elementShapes: linkPortCreationDemoConfig.elementShapes,
15120
+ portShapes: linkPortCreationDemoConfig.portShapes,
15121
+ router: linkPortCreationDemoConfig.router,
15122
+ snapDefault: linkPortCreationDemoConfig.snapDefault,
15123
+ linkRouteRefreshPolicy: linkPortCreationDemoConfig.linkRouteRefreshPolicy,
15124
+ linkColorPoolPolicy: linkPortCreationDemoConfig.linkColorPoolPolicy,
15125
+ onCreateLinkTargetPort: onCreateLinkTargetPort,
15126
+ }), containerRef = _b.containerRef, editorRef = _b.editorRef, diagramState = _b.diagramState, selection = _b.selection, snapEnabled = _b.snapEnabled, setSnapEnabled = _b.setSnapEnabled;
15127
+ var nextOffset = useOffsetSequence();
15128
+ var actionHelpers = React.useMemo(function () { return ({ nextOffset: nextOffset }); }, [nextOffset]);
15129
+ var controls = useDemoControls({
15130
+ demo: linkPortCreationDemoConfig,
15131
+ editorRef: editorRef,
15132
+ diagramState: diagramState,
15133
+ selection: selection,
15134
+ snapEnabled: snapEnabled,
15135
+ setSnapEnabled: setSnapEnabled,
15136
+ actionHelpers: actionHelpers,
15137
+ });
15138
+ return (React.createElement("section", null,
15139
+ React.createElement("div", { style: { marginBottom: 12 } },
15140
+ React.createElement("h2", { style: { marginTop: 0, marginBottom: 4 } }, linkPortCreationDemoConfig.title),
15141
+ React.createElement("p", { style: { marginTop: 0, marginBottom: 8 } }, linkPortCreationDemoConfig.description),
15142
+ React.createElement("label", { style: { display: 'inline-flex', alignItems: 'center', gap: 8, fontWeight: 600 } },
15143
+ React.createElement("input", { type: "checkbox", checked: useHostTargetPort, onChange: function (event) { return setUseHostTargetPort(event.target.checked); } }),
15144
+ "Customize target port via onCreateLinkTargetPort"),
15145
+ React.createElement("p", { style: { marginTop: 8, marginBottom: 0, color: '#5c4a2c' } },
15146
+ "Default mode clones the source port. Custom mode reshapes the target-port preview and commit together; host cancellation still belongs to ",
15147
+ React.createElement("code", null, "elementLinkConnecting"),
15148
+ ".")),
15149
+ React.createElement(DisplayBoxControls, { actions: linkPortCreationDemoConfig.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 }),
15150
+ React.createElement(DisplayBoxStage, { containerRef: containerRef, stageStyle: linkPortCreationDemoConfig.stageStyle })));
15151
+ };
15152
+
14625
15153
  var parentOptions = [
14626
15154
  { id: 'layout-row', label: 'Horizontal layout' },
14627
15155
  { id: 'layout-column', label: 'Vertical layout' },
@@ -16096,10 +16624,21 @@ var ZoomToFitElementsDemo = function () { return (React.createElement(SimpleDemo
16096
16624
  React.createElement("li", null, "Use `Run Zoom-To-Fit (Padding 48)` to confirm optional padding keeps extra breathing room around content.")))) })); };
16097
16625
 
16098
16626
  var initialPayloads = {
16627
+ elementDeleting: null,
16099
16628
  elementDeleted: null,
16629
+ portDeleting: null,
16100
16630
  portDeleted: null,
16631
+ linkDeleting: null,
16101
16632
  linkDeleted: null,
16633
+ textDeleting: null,
16102
16634
  textDeleted: null,
16635
+ elementDoubleClick: null,
16636
+ };
16637
+ var initialCancelFlags = {
16638
+ element: false,
16639
+ port: false,
16640
+ link: false,
16641
+ text: false,
16103
16642
  };
16104
16643
  var eventBoxStyle = {
16105
16644
  width: '100%',
@@ -16132,21 +16671,77 @@ var DeletionEventsDemo = function () {
16132
16671
  actionHelpers: actionHelpers,
16133
16672
  });
16134
16673
  var _f = React.useState(initialPayloads), payloads = _f[0], setPayloads = _f[1];
16674
+ var _g = React.useState(initialCancelFlags), cancelFlags = _g[0], setCancelFlags = _g[1];
16675
+ var _h = React.useState([]), eventLog = _h[0], setEventLog = _h[1];
16676
+ var appendLog = React.useCallback(function (eventName, payload) {
16677
+ setEventLog(function (prev) { return __spreadArray([
16678
+ "".concat(eventName, ": ").concat(JSON.stringify(payload))
16679
+ ], prev, true).slice(0, 18); });
16680
+ }, []);
16135
16681
  React.useEffect(function () {
16136
16682
  var editor = editorRef.current;
16137
16683
  if (!editor)
16138
16684
  return undefined;
16139
16685
  setPayloads(initialPayloads);
16686
+ setEventLog([]);
16140
16687
  var unsubs = [
16141
- editor.on('elementDeleted', function (payload) { return setPayloads(function (prev) { return (__assign(__assign({}, prev), { elementDeleted: payload })); }); }),
16142
- editor.on('portDeleted', function (payload) { return setPayloads(function (prev) { return (__assign(__assign({}, prev), { portDeleted: payload })); }); }),
16143
- editor.on('linkDeleted', function (payload) { return setPayloads(function (prev) { return (__assign(__assign({}, prev), { linkDeleted: payload })); }); }),
16144
- editor.on('textDeleted', function (payload) { return setPayloads(function (prev) { return (__assign(__assign({}, prev), { textDeleted: payload })); }); }),
16688
+ editor.on('elementDeleting', function (payload) {
16689
+ if (cancelFlags.element) {
16690
+ payload.cancel();
16691
+ }
16692
+ setPayloads(function (prev) { return (__assign(__assign({}, prev), { elementDeleting: payload })); });
16693
+ appendLog('elementDeleting', payload);
16694
+ }),
16695
+ editor.on('elementDeleted', function (payload) {
16696
+ setPayloads(function (prev) { return (__assign(__assign({}, prev), { elementDeleted: payload })); });
16697
+ appendLog('elementDeleted', payload);
16698
+ }),
16699
+ editor.on('portDeleting', function (payload) {
16700
+ if (cancelFlags.port) {
16701
+ payload.cancel();
16702
+ }
16703
+ setPayloads(function (prev) { return (__assign(__assign({}, prev), { portDeleting: payload })); });
16704
+ appendLog('portDeleting', payload);
16705
+ }),
16706
+ editor.on('portDeleted', function (payload) {
16707
+ setPayloads(function (prev) { return (__assign(__assign({}, prev), { portDeleted: payload })); });
16708
+ appendLog('portDeleted', payload);
16709
+ }),
16710
+ editor.on('linkDeleting', function (payload) {
16711
+ if (cancelFlags.link) {
16712
+ payload.cancel();
16713
+ }
16714
+ setPayloads(function (prev) { return (__assign(__assign({}, prev), { linkDeleting: payload })); });
16715
+ appendLog('linkDeleting', payload);
16716
+ }),
16717
+ editor.on('linkDeleted', function (payload) {
16718
+ setPayloads(function (prev) { return (__assign(__assign({}, prev), { linkDeleted: payload })); });
16719
+ appendLog('linkDeleted', payload);
16720
+ }),
16721
+ editor.on('textDeleting', function (payload) {
16722
+ if (cancelFlags.text) {
16723
+ payload.cancel();
16724
+ }
16725
+ setPayloads(function (prev) { return (__assign(__assign({}, prev), { textDeleting: payload })); });
16726
+ appendLog('textDeleting', payload);
16727
+ }),
16728
+ editor.on('textDeleted', function (payload) {
16729
+ setPayloads(function (prev) { return (__assign(__assign({}, prev), { textDeleted: payload })); });
16730
+ appendLog('textDeleted', payload);
16731
+ }),
16732
+ editor.on('elementDoubleClick', function (payload) {
16733
+ setPayloads(function (prev) { return (__assign(__assign({}, prev), { elementDoubleClick: payload })); });
16734
+ appendLog('elementDoubleClick', payload);
16735
+ }),
16145
16736
  ];
16146
16737
  return function () {
16147
- unsubs.forEach(function (unsub) { return unsub(); });
16738
+ unsubs.forEach(function (unsub) {
16739
+ if (typeof unsub === 'function') {
16740
+ unsub();
16741
+ }
16742
+ });
16148
16743
  };
16149
- }, [editorRef]);
16744
+ }, [appendLog, cancelFlags, editorRef]);
16150
16745
  var hasPort = ((_a = diagramState === null || diagramState === void 0 ? void 0 : diagramState.ports) !== null && _a !== void 0 ? _a : []).some(function (port) { return port.id === 'delete-source-free-port'; });
16151
16746
  var hasLink = ((_b = diagramState === null || diagramState === void 0 ? void 0 : diagramState.links) !== null && _b !== void 0 ? _b : []).some(function (link) { return link.id === 'delete-link'; });
16152
16747
  var hasText = ((_c = diagramState === null || diagramState === void 0 ? void 0 : diagramState.texts) !== null && _c !== void 0 ? _c : []).some(function (text) { return text.id === 'delete-free-text'; });
@@ -16155,29 +16750,67 @@ var DeletionEventsDemo = function () {
16155
16750
  React.createElement("div", { style: { marginBottom: 12 } },
16156
16751
  React.createElement("h2", { style: { marginTop: 0, marginBottom: 4 } }, demo.title),
16157
16752
  React.createElement("p", { style: { marginTop: 0 } },
16158
- "Use direct delete buttons for port/link/text, then delete ",
16753
+ "Use the direct delete buttons for port/link/text, then delete ",
16159
16754
  React.createElement("code", null, "delete-source"),
16160
- " to trigger cascade removals. Latest payloads are shown below for integration debugging.")),
16755
+ " to trigger cascades. Turn cancellation toggles on to veto deletes before commit, double click an element body to log",
16756
+ React.createElement("code", null, " elementDoubleClick"),
16757
+ ", and use the batch-selection helper before pressing Delete to verify partial success.")),
16161
16758
  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 }),
16162
16759
  React.createElement("div", { style: { display: 'grid', gap: 12, marginBottom: 12 } },
16163
16760
  React.createElement("div", { style: { display: 'flex', flexWrap: 'wrap', gap: 8 } },
16164
16761
  React.createElement("button", { type: "button", onClick: function () { var _a; return (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.removePort('delete-source-free-port'); }, disabled: !hasPort }, "Delete Port"),
16165
16762
  React.createElement("button", { type: "button", onClick: function () { var _a; return (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.removeLink('delete-link'); }, disabled: !hasLink }, "Delete Link"),
16166
16763
  React.createElement("button", { type: "button", onClick: function () { var _a; return (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.removeText('delete-free-text'); }, disabled: !hasText }, "Delete Text"),
16167
- React.createElement("button", { type: "button", onClick: function () { var _a; return (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.removeElement('delete-source'); }, disabled: !hasCascadeElement }, "Delete Element (Cascade)")),
16168
- React.createElement("div", { style: { display: 'grid', gridTemplateColumns: 'repeat(2, minmax(0, 1fr))', gap: 12 } },
16764
+ React.createElement("button", { type: "button", onClick: function () { var _a; return (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.removeElement('delete-source'); }, disabled: !hasCascadeElement }, "Delete Element (Cascade)"),
16765
+ React.createElement("button", { type: "button", onClick: function () { var _a; return (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.setSelection(['delete-free-text', 'delete-target']); }, disabled: !hasText }, "Prepare Batch Delete Selection")),
16766
+ React.createElement("div", { style: { display: 'flex', flexWrap: 'wrap', gap: 12 } },
16767
+ React.createElement("label", null,
16768
+ React.createElement("input", { type: "checkbox", checked: cancelFlags.element, onChange: function (event) { return setCancelFlags(function (prev) { return (__assign(__assign({}, prev), { element: event.target.checked })); }); } }),
16769
+ ' ',
16770
+ "Cancel elementDeleting"),
16771
+ React.createElement("label", null,
16772
+ React.createElement("input", { type: "checkbox", checked: cancelFlags.port, onChange: function (event) { return setCancelFlags(function (prev) { return (__assign(__assign({}, prev), { port: event.target.checked })); }); } }),
16773
+ ' ',
16774
+ "Cancel portDeleting"),
16775
+ React.createElement("label", null,
16776
+ React.createElement("input", { type: "checkbox", checked: cancelFlags.link, onChange: function (event) { return setCancelFlags(function (prev) { return (__assign(__assign({}, prev), { link: event.target.checked })); }); } }),
16777
+ ' ',
16778
+ "Cancel linkDeleting"),
16779
+ React.createElement("label", null,
16780
+ React.createElement("input", { type: "checkbox", checked: cancelFlags.text, onChange: function (event) { return setCancelFlags(function (prev) { return (__assign(__assign({}, prev), { text: event.target.checked })); }); } }),
16781
+ ' ',
16782
+ "Cancel textDeleting")),
16783
+ React.createElement("div", { style: { display: 'grid', gridTemplateColumns: 'repeat(3, minmax(0, 1fr))', gap: 12 } },
16784
+ React.createElement("div", null,
16785
+ React.createElement("label", { style: { display: 'block', fontWeight: 600, marginBottom: 6 } }, "elementDeleting"),
16786
+ React.createElement("textarea", { readOnly: true, value: payloads.elementDeleting ? JSON.stringify(payloads.elementDeleting, null, 2) : '', style: eventBoxStyle })),
16169
16787
  React.createElement("div", null,
16170
16788
  React.createElement("label", { style: { display: 'block', fontWeight: 600, marginBottom: 6 } }, "elementDeleted"),
16171
16789
  React.createElement("textarea", { readOnly: true, value: payloads.elementDeleted ? JSON.stringify(payloads.elementDeleted, null, 2) : '', style: eventBoxStyle })),
16790
+ React.createElement("div", null,
16791
+ React.createElement("label", { style: { display: 'block', fontWeight: 600, marginBottom: 6 } }, "portDeleting"),
16792
+ React.createElement("textarea", { readOnly: true, value: payloads.portDeleting ? JSON.stringify(payloads.portDeleting, null, 2) : '', style: eventBoxStyle })),
16172
16793
  React.createElement("div", null,
16173
16794
  React.createElement("label", { style: { display: 'block', fontWeight: 600, marginBottom: 6 } }, "portDeleted"),
16174
16795
  React.createElement("textarea", { readOnly: true, value: payloads.portDeleted ? JSON.stringify(payloads.portDeleted, null, 2) : '', style: eventBoxStyle })),
16796
+ React.createElement("div", null,
16797
+ React.createElement("label", { style: { display: 'block', fontWeight: 600, marginBottom: 6 } }, "linkDeleting"),
16798
+ React.createElement("textarea", { readOnly: true, value: payloads.linkDeleting ? JSON.stringify(payloads.linkDeleting, null, 2) : '', style: eventBoxStyle })),
16175
16799
  React.createElement("div", null,
16176
16800
  React.createElement("label", { style: { display: 'block', fontWeight: 600, marginBottom: 6 } }, "linkDeleted"),
16177
16801
  React.createElement("textarea", { readOnly: true, value: payloads.linkDeleted ? JSON.stringify(payloads.linkDeleted, null, 2) : '', style: eventBoxStyle })),
16802
+ React.createElement("div", null,
16803
+ React.createElement("label", { style: { display: 'block', fontWeight: 600, marginBottom: 6 } }, "textDeleting"),
16804
+ React.createElement("textarea", { readOnly: true, value: payloads.textDeleting ? JSON.stringify(payloads.textDeleting, null, 2) : '', style: eventBoxStyle })),
16178
16805
  React.createElement("div", null,
16179
16806
  React.createElement("label", { style: { display: 'block', fontWeight: 600, marginBottom: 6 } }, "textDeleted"),
16180
- React.createElement("textarea", { readOnly: true, value: payloads.textDeleted ? JSON.stringify(payloads.textDeleted, null, 2) : '', style: eventBoxStyle })))),
16807
+ React.createElement("textarea", { readOnly: true, value: payloads.textDeleted ? JSON.stringify(payloads.textDeleted, null, 2) : '', style: eventBoxStyle })),
16808
+ React.createElement("div", null,
16809
+ React.createElement("label", { style: { display: 'block', fontWeight: 600, marginBottom: 6 } }, "elementDoubleClick"),
16810
+ React.createElement("textarea", { readOnly: true, value: payloads.elementDoubleClick ? JSON.stringify(payloads.elementDoubleClick, null, 2) : '', style: eventBoxStyle }))),
16811
+ React.createElement("div", null,
16812
+ React.createElement("label", { style: { display: 'block', fontWeight: 600, marginBottom: 6 } }, "Event Log"),
16813
+ React.createElement("textarea", { readOnly: true, value: eventLog.join('\n'), style: __assign(__assign({}, eventBoxStyle), { minHeight: 180 }) }))),
16181
16814
  React.createElement(DisplayBoxStage, { containerRef: containerRef })));
16182
16815
  };
16183
16816
 
@@ -16986,219 +17619,171 @@ var VertexControlLinkSessionDemo = function () {
16986
17619
  React.createElement(DisplayBoxStage, { containerRef: containerRef, stageStyle: gridStageStyle })));
16987
17620
  };
16988
17621
 
16989
- var wrapSimpleDemo = function (demo) { return function () { return React.createElement(SimpleDemo, { demo: demo }); }; };
16990
- var demoTabs = [
16991
- {
16992
- id: basicDemoConfig.id,
16993
- title: basicDemoConfig.title,
16994
- description: basicDemoConfig.description,
16995
- Component: wrapSimpleDemo(basicDemoConfig),
16996
- },
16997
- {
16998
- id: linkPortCreationDemoConfig.id,
16999
- title: linkPortCreationDemoConfig.title,
17000
- description: linkPortCreationDemoConfig.description,
17001
- Component: wrapSimpleDemo(linkPortCreationDemoConfig),
17002
- },
17003
- {
17004
- id: nestedDemoConfig.id,
17005
- title: nestedDemoConfig.title,
17006
- description: nestedDemoConfig.description,
17007
- Component: wrapSimpleDemo(nestedDemoConfig),
17008
- },
17009
- {
17010
- id: customDemoConfig.id,
17011
- title: customDemoConfig.title,
17012
- description: customDemoConfig.description,
17013
- Component: wrapSimpleDemo(customDemoConfig),
17014
- },
17015
- {
17016
- id: textDemoConfig.id,
17017
- title: textDemoConfig.title,
17018
- description: textDemoConfig.description,
17019
- Component: TextLayoutDemo,
17020
- },
17021
- {
17022
- id: selectionDemoConfig.id,
17023
- title: selectionDemoConfig.title,
17024
- description: selectionDemoConfig.description,
17025
- Component: wrapSimpleDemo(selectionDemoConfig),
17026
- },
17027
- {
17028
- id: elementVisibilitySelectionDemoConfig.id,
17029
- title: elementVisibilitySelectionDemoConfig.title,
17030
- description: elementVisibilitySelectionDemoConfig.description,
17031
- Component: wrapSimpleDemo(elementVisibilitySelectionDemoConfig),
17032
- },
17033
- {
17034
- id: eventHandlersDemoConfig.id,
17035
- title: eventHandlersDemoConfig.title,
17036
- description: eventHandlersDemoConfig.description,
17037
- Component: EventHandlersDemo,
17038
- },
17039
- {
17040
- id: engineEventsDemoConfig.id,
17041
- title: engineEventsDemoConfig.title,
17042
- description: engineEventsDemoConfig.description,
17043
- Component: EngineEventsDemo,
17044
- },
17045
- {
17046
- id: deletionEventsDemoConfig.id,
17047
- title: deletionEventsDemoConfig.title,
17048
- description: deletionEventsDemoConfig.description,
17049
- Component: DeletionEventsDemo,
17050
- },
17051
- {
17052
- id: autoLayoutDemoConfig.id,
17053
- title: autoLayoutDemoConfig.title,
17054
- description: autoLayoutDemoConfig.description,
17055
- Component: AutoLayoutDemo,
17056
- },
17057
- {
17058
- id: linkCancelDemoConfig.id,
17059
- title: linkCancelDemoConfig.title,
17060
- description: linkCancelDemoConfig.description,
17061
- Component: LinkCancelDemo,
17062
- },
17063
- {
17064
- id: externalDragDropDemoConfig.id,
17065
- title: externalDragDropDemoConfig.title,
17066
- description: externalDragDropDemoConfig.description,
17067
- Component: ExternalDragDropDemo,
17068
- },
17069
- {
17070
- id: shapeGalleryDemoConfig.id,
17071
- title: shapeGalleryDemoConfig.title,
17072
- description: shapeGalleryDemoConfig.description,
17073
- Component: wrapSimpleDemo(shapeGalleryDemoConfig),
17074
- },
17075
- {
17076
- id: roundedRectRadiusDemoConfig.id,
17077
- title: roundedRectRadiusDemoConfig.title,
17078
- description: roundedRectRadiusDemoConfig.description,
17079
- Component: wrapSimpleDemo(roundedRectRadiusDemoConfig),
17080
- },
17081
- {
17082
- id: rotatedCreationDemoConfig.id,
17083
- title: rotatedCreationDemoConfig.title,
17084
- description: rotatedCreationDemoConfig.description,
17085
- Component: wrapSimpleDemo(rotatedCreationDemoConfig),
17086
- },
17087
- {
17088
- id: svgPathDemoConfig.id,
17089
- title: svgPathDemoConfig.title,
17090
- description: svgPathDemoConfig.description,
17091
- Component: SvgPathDemo,
17092
- },
17093
- {
17094
- id: asymmetricPortMultiAnchorDemoConfig.id,
17095
- title: asymmetricPortMultiAnchorDemoConfig.title,
17096
- description: asymmetricPortMultiAnchorDemoConfig.description,
17097
- Component: AsymmetricPortMultiAnchorDemo,
17098
- },
17099
- {
17100
- id: multiLevelTreeDemoConfig.id,
17101
- title: multiLevelTreeDemoConfig.title,
17102
- description: multiLevelTreeDemoConfig.description,
17103
- Component: wrapSimpleDemo(multiLevelTreeDemoConfig),
17104
- },
17105
- {
17106
- id: multipleElementsDemoConfig.id,
17107
- title: multipleElementsDemoConfig.title,
17108
- description: multipleElementsDemoConfig.description,
17109
- Component: wrapSimpleDemo(multipleElementsDemoConfig),
17110
- },
17111
- {
17112
- id: portConstraintsDemoConfig.id,
17113
- title: portConstraintsDemoConfig.title,
17114
- description: portConstraintsDemoConfig.description,
17115
- Component: wrapSimpleDemo(portConstraintsDemoConfig),
17116
- },
17117
- {
17118
- id: portPositionLimitsDemoConfig.id,
17119
- title: portPositionLimitsDemoConfig.title,
17120
- description: portPositionLimitsDemoConfig.description,
17121
- Component: wrapSimpleDemo(portPositionLimitsDemoConfig),
17122
- },
17123
- {
17124
- id: labelStyleDemoConfig.id,
17125
- title: labelStyleDemoConfig.title,
17126
- description: labelStyleDemoConfig.description,
17127
- Component: wrapSimpleDemo(labelStyleDemoConfig),
17128
- },
17129
- {
17130
- id: linkColorPoolDemoConfig.id,
17131
- title: linkColorPoolDemoConfig.title,
17132
- description: linkColorPoolDemoConfig.description,
17133
- Component: LinkColorPoolDemo,
17134
- },
17135
- {
17136
- id: portBorderDemoConfig.id,
17137
- title: portBorderDemoConfig.title,
17138
- description: portBorderDemoConfig.description,
17139
- Component: wrapSimpleDemo(portBorderDemoConfig),
17140
- },
17141
- {
17142
- id: shapeBorderMovementDemoConfig.id,
17143
- title: shapeBorderMovementDemoConfig.title,
17144
- description: shapeBorderMovementDemoConfig.description,
17145
- Component: wrapSimpleDemo(shapeBorderMovementDemoConfig),
17146
- },
17147
- {
17148
- id: shapeHoverControlsDemoConfig.id,
17149
- title: shapeHoverControlsDemoConfig.title,
17150
- description: shapeHoverControlsDemoConfig.description,
17151
- Component: ShapeHoverControlsDemo,
17152
- },
17153
- {
17154
- id: vertexControlLinkSessionDemoConfig.id,
17155
- title: vertexControlLinkSessionDemoConfig.title,
17156
- description: vertexControlLinkSessionDemoConfig.description,
17157
- Component: VertexControlLinkSessionDemo,
17158
- },
17159
- {
17160
- id: childConstraintsDemoConfig.id,
17161
- title: childConstraintsDemoConfig.title,
17162
- description: childConstraintsDemoConfig.description,
17163
- Component: wrapSimpleDemo(childConstraintsDemoConfig),
17164
- },
17165
- {
17166
- id: gridOverlayDemoConfig.id,
17167
- title: gridOverlayDemoConfig.title,
17168
- description: gridOverlayDemoConfig.description,
17169
- Component: wrapSimpleDemo(gridOverlayDemoConfig),
17170
- },
17171
- {
17172
- id: routingDemoConfig.id,
17173
- title: routingDemoConfig.title,
17174
- description: routingDemoConfig.description,
17175
- Component: wrapSimpleDemo(routingDemoConfig),
17176
- },
17177
- {
17178
- id: obstacleRoutingDemoConfig.id,
17179
- title: obstacleRoutingDemoConfig.title,
17180
- description: obstacleRoutingDemoConfig.description,
17181
- Component: ObstacleRoutingDemo,
17622
+ var createFocusElementState = function () { return ({
17623
+ elements: [
17624
+ {
17625
+ id: 'focus-left',
17626
+ position: { x: 40, y: 80 },
17627
+ size: { width: 140, height: 90 },
17628
+ shapeId: 'default',
17629
+ style: { fill: '#e0f2fe', stroke: '#0369a1', strokeWidth: 2 },
17630
+ },
17631
+ {
17632
+ id: 'focus-right',
17633
+ position: { x: 820, y: 120 },
17634
+ size: { width: 180, height: 110 },
17635
+ shapeId: 'panel',
17636
+ style: { fill: '#fef3c7', stroke: '#b45309', strokeWidth: 2 },
17637
+ },
17638
+ {
17639
+ id: 'focus-parent',
17640
+ position: { x: 520, y: 420 },
17641
+ size: { width: 220, height: 160 },
17642
+ shapeId: 'default',
17643
+ style: { fill: '#ecfccb', stroke: '#4d7c0f', strokeWidth: 2 },
17644
+ },
17645
+ {
17646
+ id: 'focus-child',
17647
+ parentId: 'focus-parent',
17648
+ position: { x: 110, y: 60 },
17649
+ size: { width: 70, height: 50 },
17650
+ shapeId: 'default',
17651
+ anchorCenter: true,
17652
+ style: { fill: '#dcfce7', stroke: '#15803d', strokeWidth: 2 },
17653
+ },
17654
+ ],
17655
+ ports: [],
17656
+ links: [],
17657
+ texts: [
17658
+ {
17659
+ id: 'focus-copy',
17660
+ content: 'Compare explicit element focus against zoom-to-fit.',
17661
+ position: { x: 40, y: 26 },
17662
+ },
17663
+ ],
17664
+ }); };
17665
+ var focusLeftAction = {
17666
+ id: 'focus-left-default',
17667
+ label: 'Focus Left (Keep Zoom)',
17668
+ run: function (editor) {
17669
+ editor.focusElement('focus-left');
17182
17670
  },
17183
- {
17184
- id: offsetAnchorAvoidanceDemoConfig.id,
17185
- title: offsetAnchorAvoidanceDemoConfig.title,
17186
- description: offsetAnchorAvoidanceDemoConfig.description,
17187
- Component: OffsetAnchorAvoidanceDemo,
17671
+ };
17672
+ var focusRightZoomAction = {
17673
+ id: 'focus-right-zoom',
17674
+ label: 'Focus Right (Zoom 2.2)',
17675
+ run: function (editor) {
17676
+ editor.focusElement('focus-right', { zoom: 2.2 });
17188
17677
  },
17189
- {
17190
- id: zoomToFitElementsDemoConfig.id,
17191
- title: zoomToFitElementsDemoConfig.title,
17192
- description: zoomToFitElementsDemoConfig.description,
17193
- Component: ZoomToFitElementsDemo,
17678
+ };
17679
+ var focusChildZoomAction = {
17680
+ id: 'focus-child-zoom',
17681
+ label: 'Focus Nested Child (Zoom 1.8)',
17682
+ run: function (editor) {
17683
+ editor.focusElement('focus-child', { zoom: 1.8 });
17194
17684
  },
17195
- {
17196
- id: linkBendHandlesDemoConfig.id,
17197
- title: linkBendHandlesDemoConfig.title,
17198
- description: linkBendHandlesDemoConfig.description,
17199
- Component: wrapSimpleDemo(linkBendHandlesDemoConfig),
17685
+ };
17686
+ var fitAllAction = {
17687
+ id: 'focus-fit-all',
17688
+ label: 'Zoom-To-Fit For Comparison',
17689
+ run: function (editor) {
17690
+ editor.zoomToFitElements({ padding: 40 });
17200
17691
  },
17201
- ];
17692
+ };
17693
+ var focusElementDemoConfig = {
17694
+ id: 'focus-element',
17695
+ title: 'Focus Element',
17696
+ description: 'Centers one explicit element, optionally with a chosen zoom, unlike zoom-to-fit which frames the whole scene.',
17697
+ createState: createFocusElementState,
17698
+ elementShapes: baseElementShapes,
17699
+ portShapes: basePortShapes,
17700
+ defaultElementShapeId: 'default',
17701
+ defaultPortShapeId: 'port-circle',
17702
+ actions: [focusLeftAction, focusRightZoomAction, focusChildZoomAction, fitAllAction],
17703
+ };
17704
+
17705
+ var wrapSimpleDemo = function (demo) { return function () { return React.createElement(SimpleDemo, { demo: demo }); }; };
17706
+ var menuGroupOrder = {
17707
+ basics: 1,
17708
+ layoutText: 2,
17709
+ shapes: 3,
17710
+ portsAnchors: 4,
17711
+ linksRouting: 5,
17712
+ eventsIntegration: 6,
17713
+ };
17714
+ var registerDemo = function (demo, Component, menuGroup, menuOrder) { return ({
17715
+ demo: demo,
17716
+ Component: Component,
17717
+ menuGroup: menuGroup,
17718
+ menuOrder: menuOrder,
17719
+ }); };
17720
+ var toDemoDefinition = function (_a) {
17721
+ var demo = _a.demo, Component = _a.Component, menuGroup = _a.menuGroup, menuOrder = _a.menuOrder;
17722
+ return ({
17723
+ id: demo.id,
17724
+ title: demo.title,
17725
+ description: demo.description,
17726
+ Component: Component,
17727
+ menuGroup: menuGroup,
17728
+ menuOrder: menuOrder,
17729
+ });
17730
+ };
17731
+ var compareDemoDefinitions = function (left, right) {
17732
+ return menuGroupOrder[left.menuGroup] - menuGroupOrder[right.menuGroup]
17733
+ || left.menuOrder - right.menuOrder
17734
+ || left.title.localeCompare(right.title);
17735
+ };
17736
+ var basics = [
17737
+ registerDemo(basicDemoConfig, wrapSimpleDemo(basicDemoConfig), 'basics', 1),
17738
+ registerDemo(multipleElementsDemoConfig, wrapSimpleDemo(multipleElementsDemoConfig), 'basics', 2),
17739
+ registerDemo(nestedDemoConfig, wrapSimpleDemo(nestedDemoConfig), 'basics', 3),
17740
+ registerDemo(selectionDemoConfig, wrapSimpleDemo(selectionDemoConfig), 'basics', 4),
17741
+ registerDemo(elementVisibilitySelectionDemoConfig, wrapSimpleDemo(elementVisibilitySelectionDemoConfig), 'basics', 5),
17742
+ registerDemo(zoomToFitElementsDemoConfig, ZoomToFitElementsDemo, 'basics', 6),
17743
+ registerDemo(focusElementDemoConfig, wrapSimpleDemo(focusElementDemoConfig), 'basics', 7),
17744
+ ];
17745
+ var layoutAndText = [
17746
+ registerDemo(textDemoConfig, TextLayoutDemo, 'layoutText', 1),
17747
+ registerDemo(labelStyleDemoConfig, wrapSimpleDemo(labelStyleDemoConfig), 'layoutText', 2),
17748
+ registerDemo(autoLayoutDemoConfig, AutoLayoutDemo, 'layoutText', 3),
17749
+ registerDemo(multiLevelTreeDemoConfig, wrapSimpleDemo(multiLevelTreeDemoConfig), 'layoutText', 4),
17750
+ registerDemo(childConstraintsDemoConfig, wrapSimpleDemo(childConstraintsDemoConfig), 'layoutText', 5),
17751
+ registerDemo(gridOverlayDemoConfig, wrapSimpleDemo(gridOverlayDemoConfig), 'layoutText', 6),
17752
+ ];
17753
+ var shapes = [
17754
+ registerDemo(customDemoConfig, wrapSimpleDemo(customDemoConfig), 'shapes', 1),
17755
+ registerDemo(shapeGalleryDemoConfig, wrapSimpleDemo(shapeGalleryDemoConfig), 'shapes', 2),
17756
+ registerDemo(roundedRectRadiusDemoConfig, wrapSimpleDemo(roundedRectRadiusDemoConfig), 'shapes', 3),
17757
+ registerDemo(rotatedCreationDemoConfig, wrapSimpleDemo(rotatedCreationDemoConfig), 'shapes', 4),
17758
+ registerDemo(svgPathDemoConfig, SvgPathDemo, 'shapes', 5),
17759
+ registerDemo(shapeBorderMovementDemoConfig, wrapSimpleDemo(shapeBorderMovementDemoConfig), 'shapes', 6),
17760
+ registerDemo(shapeHoverControlsDemoConfig, ShapeHoverControlsDemo, 'shapes', 7),
17761
+ ];
17762
+ var portsAndAnchors = [
17763
+ registerDemo(linkPortCreationDemoConfig, LinkPortCreationDemo, 'portsAnchors', 1),
17764
+ registerDemo(portConstraintsDemoConfig, wrapSimpleDemo(portConstraintsDemoConfig), 'portsAnchors', 2),
17765
+ registerDemo(portPositionLimitsDemoConfig, wrapSimpleDemo(portPositionLimitsDemoConfig), 'portsAnchors', 3),
17766
+ registerDemo(portBorderDemoConfig, wrapSimpleDemo(portBorderDemoConfig), 'portsAnchors', 4),
17767
+ registerDemo(asymmetricPortMultiAnchorDemoConfig, AsymmetricPortMultiAnchorDemo, 'portsAnchors', 5),
17768
+ ];
17769
+ var linksAndRouting = [
17770
+ registerDemo(linkCancelDemoConfig, LinkCancelDemo, 'linksRouting', 1),
17771
+ registerDemo(linkBendHandlesDemoConfig, wrapSimpleDemo(linkBendHandlesDemoConfig), 'linksRouting', 2),
17772
+ registerDemo(linkLabelsDemoConfig, wrapSimpleDemo(linkLabelsDemoConfig), 'linksRouting', 3),
17773
+ registerDemo(linkColorPoolDemoConfig, LinkColorPoolDemo, 'linksRouting', 4),
17774
+ registerDemo(routingDemoConfig, wrapSimpleDemo(routingDemoConfig), 'linksRouting', 5),
17775
+ registerDemo(obstacleRoutingDemoConfig, ObstacleRoutingDemo, 'linksRouting', 6),
17776
+ registerDemo(offsetAnchorAvoidanceDemoConfig, OffsetAnchorAvoidanceDemo, 'linksRouting', 7),
17777
+ registerDemo(vertexControlLinkSessionDemoConfig, VertexControlLinkSessionDemo, 'linksRouting', 8),
17778
+ ];
17779
+ var eventsAndIntegration = [
17780
+ registerDemo(eventHandlersDemoConfig, EventHandlersDemo, 'eventsIntegration', 1),
17781
+ registerDemo(engineEventsDemoConfig, EngineEventsDemo, 'eventsIntegration', 2),
17782
+ registerDemo(deletionEventsDemoConfig, DeletionEventsDemo, 'eventsIntegration', 3),
17783
+ registerDemo(externalDragDropDemoConfig, ExternalDragDropDemo, 'eventsIntegration', 4),
17784
+ ];
17785
+ var demoTabs = __spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray(__spreadArray([], basics, true), layoutAndText, true), shapes, true), portsAndAnchors, true), linksAndRouting, true), eventsAndIntegration, true).map(toDemoDefinition)
17786
+ .sort(compareDemoDefinitions);
17202
17787
 
17203
17788
  exports.baseElementShapes = baseElementShapes;
17204
17789
  exports.basePortShapes = basePortShapes;