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