@excalidraw/element 0.18.0-b7aac689a → 0.18.0-c6f8ef9

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 (46) hide show
  1. package/dist/dev/index.js +383 -154
  2. package/dist/dev/index.js.map +3 -3
  3. package/dist/prod/index.js +12 -12
  4. package/dist/types/common/src/constants.d.ts +1 -0
  5. package/dist/types/element/src/Scene.d.ts +6 -2
  6. package/dist/types/element/src/align.d.ts +2 -1
  7. package/dist/types/element/src/delta.d.ts +17 -4
  8. package/dist/types/element/src/distribute.d.ts +2 -1
  9. package/dist/types/element/src/groups.d.ts +1 -0
  10. package/dist/types/element/src/linearElementEditor.d.ts +2 -1
  11. package/dist/types/element/src/store.d.ts +6 -1
  12. package/dist/types/excalidraw/actions/actionAddToLibrary.d.ts +0 -3
  13. package/dist/types/excalidraw/actions/actionBoundText.d.ts +0 -2
  14. package/dist/types/excalidraw/actions/actionCanvas.d.ts +0 -13
  15. package/dist/types/excalidraw/actions/actionClipboard.d.ts +3 -8
  16. package/dist/types/excalidraw/actions/actionCropEditor.d.ts +0 -1
  17. package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +3 -6
  18. package/dist/types/excalidraw/actions/actionElementLink.d.ts +0 -1
  19. package/dist/types/excalidraw/actions/actionElementLock.d.ts +0 -2
  20. package/dist/types/excalidraw/actions/actionEmbeddable.d.ts +0 -1
  21. package/dist/types/excalidraw/actions/actionExport.d.ts +0 -9
  22. package/dist/types/excalidraw/actions/actionFinalize.d.ts +2 -3
  23. package/dist/types/excalidraw/actions/actionFrame.d.ts +0 -4
  24. package/dist/types/excalidraw/actions/actionGroup.d.ts +0 -2
  25. package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +33 -3
  26. package/dist/types/excalidraw/actions/actionLink.d.ts +0 -1
  27. package/dist/types/excalidraw/actions/actionMenu.d.ts +0 -3
  28. package/dist/types/excalidraw/actions/actionNavigate.d.ts +0 -2
  29. package/dist/types/excalidraw/actions/actionProperties.d.ts +0 -15
  30. package/dist/types/excalidraw/actions/actionSelectAll.d.ts +0 -1
  31. package/dist/types/excalidraw/actions/actionStyles.d.ts +0 -1
  32. package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +0 -1
  33. package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +0 -1
  34. package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +0 -1
  35. package/dist/types/excalidraw/actions/actionToggleStats.d.ts +0 -1
  36. package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +0 -1
  37. package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +0 -1
  38. package/dist/types/excalidraw/components/Actions.d.ts +0 -4
  39. package/dist/types/excalidraw/components/App.d.ts +3 -2
  40. package/dist/types/excalidraw/components/Ellipsify.d.ts +4 -0
  41. package/dist/types/excalidraw/data/reconcile.d.ts +1 -0
  42. package/dist/types/excalidraw/data/restore.d.ts +6 -1
  43. package/dist/types/excalidraw/index.d.ts +2 -1
  44. package/dist/types/excalidraw/renderer/staticScene.d.ts +4 -1
  45. package/dist/types/excalidraw/types.d.ts +5 -4
  46. package/package.json +3 -3
package/dist/dev/index.js CHANGED
@@ -8127,7 +8127,8 @@ var LinearElementEditor = class _LinearElementEditor {
8127
8127
  segmentMidPointHoveredCoords;
8128
8128
  elbowed;
8129
8129
  customLineAngle;
8130
- constructor(element, elementsMap) {
8130
+ isEditing;
8131
+ constructor(element, elementsMap, isEditing = false) {
8131
8132
  this.elementId = element.id;
8132
8133
  if (!pointsEqual6(element.points[0], pointFrom8(0, 0))) {
8133
8134
  console.error("Linear element is not normalized", Error().stack);
@@ -8158,6 +8159,7 @@ var LinearElementEditor = class _LinearElementEditor {
8158
8159
  this.segmentMidPointHoveredCoords = null;
8159
8160
  this.elbowed = isElbowArrow(element) && element.elbowed;
8160
8161
  this.customLineAngle = null;
8162
+ this.isEditing = isEditing;
8161
8163
  }
8162
8164
  // ---------------------------------------------------------------------------
8163
8165
  // static methods
@@ -8175,11 +8177,11 @@ var LinearElementEditor = class _LinearElementEditor {
8175
8177
  return null;
8176
8178
  }
8177
8179
  static handleBoxSelection(event, appState, setState, elementsMap) {
8178
- if (!appState.editingLinearElement || !appState.selectionElement) {
8180
+ if (!appState.selectedLinearElement?.isEditing || !appState.selectionElement) {
8179
8181
  return false;
8180
8182
  }
8181
- const { editingLinearElement } = appState;
8182
- const { selectedPointsIndices, elementId } = editingLinearElement;
8183
+ const { selectedLinearElement } = appState;
8184
+ const { selectedPointsIndices, elementId } = selectedLinearElement;
8183
8185
  const element = _LinearElementEditor.getElement(elementId, elementsMap);
8184
8186
  if (!element) {
8185
8187
  return false;
@@ -8201,8 +8203,8 @@ var LinearElementEditor = class _LinearElementEditor {
8201
8203
  return true;
8202
8204
  });
8203
8205
  setState({
8204
- editingLinearElement: {
8205
- ...editingLinearElement,
8206
+ selectedLinearElement: {
8207
+ ...selectedLinearElement,
8206
8208
  selectedPointsIndices: nextSelectedPoints.length ? nextSelectedPoints : null
8207
8209
  }
8208
8210
  });
@@ -8356,7 +8358,6 @@ var LinearElementEditor = class _LinearElementEditor {
8356
8358
  };
8357
8359
  return {
8358
8360
  ...app.state,
8359
- editingLinearElement: app.state.editingLinearElement ? newLinearElementEditor : null,
8360
8361
  selectedLinearElement: newLinearElementEditor,
8361
8362
  suggestedBindings
8362
8363
  };
@@ -8440,7 +8441,7 @@ var LinearElementEditor = class _LinearElementEditor {
8440
8441
  }
8441
8442
  static getEditorMidPoints = (element, elementsMap, appState) => {
8442
8443
  const boundText = getBoundTextElement(element, elementsMap);
8443
- if (!isElbowArrow(element) && !appState.editingLinearElement && element.points.length > 2 && !boundText) {
8444
+ if (!isElbowArrow(element) && !appState.selectedLinearElement?.isEditing && element.points.length > 2 && !boundText) {
8444
8445
  return [];
8445
8446
  }
8446
8447
  const points = _LinearElementEditor.getPointsGlobalCoordinates(
@@ -8490,7 +8491,7 @@ var LinearElementEditor = class _LinearElementEditor {
8490
8491
  element,
8491
8492
  elementsMap
8492
8493
  );
8493
- if (points.length >= 3 && !appState.editingLinearElement && !isElbowArrow(element)) {
8494
+ if (points.length >= 3 && !appState.selectedLinearElement?.isEditing && !isElbowArrow(element)) {
8494
8495
  return null;
8495
8496
  }
8496
8497
  const threshold = (_LinearElementEditor.POINT_HANDLE_SIZE + 1) / appState.zoom.value;
@@ -8630,7 +8631,7 @@ var LinearElementEditor = class _LinearElementEditor {
8630
8631
  segmentMidpoint,
8631
8632
  elementsMap
8632
8633
  );
8633
- } else if (event.altKey && appState.editingLinearElement) {
8634
+ } else if (event.altKey && appState.selectedLinearElement?.isEditing) {
8634
8635
  if (linearElementEditor.lastUncommittedPoint == null) {
8635
8636
  scene.mutateElement(element, {
8636
8637
  points: [
@@ -8740,14 +8741,14 @@ var LinearElementEditor = class _LinearElementEditor {
8740
8741
  }
8741
8742
  static handlePointerMove(event, scenePointerX, scenePointerY, app) {
8742
8743
  const appState = app.state;
8743
- if (!appState.editingLinearElement) {
8744
+ if (!appState.selectedLinearElement?.isEditing) {
8744
8745
  return null;
8745
8746
  }
8746
- const { elementId, lastUncommittedPoint } = appState.editingLinearElement;
8747
+ const { elementId, lastUncommittedPoint } = appState.selectedLinearElement;
8747
8748
  const elementsMap = app.scene.getNonDeletedElementsMap();
8748
8749
  const element = _LinearElementEditor.getElement(elementId, elementsMap);
8749
8750
  if (!element) {
8750
- return appState.editingLinearElement;
8751
+ return appState.selectedLinearElement;
8751
8752
  }
8752
8753
  const { points } = element;
8753
8754
  const lastPoint = points[points.length - 1];
@@ -8755,10 +8756,10 @@ var LinearElementEditor = class _LinearElementEditor {
8755
8756
  if (lastPoint === lastUncommittedPoint) {
8756
8757
  _LinearElementEditor.deletePoints(element, app, [points.length - 1]);
8757
8758
  }
8758
- return {
8759
- ...appState.editingLinearElement,
8759
+ return appState.selectedLinearElement?.lastUncommittedPoint ? {
8760
+ ...appState.selectedLinearElement,
8760
8761
  lastUncommittedPoint: null
8761
- };
8762
+ } : appState.selectedLinearElement;
8762
8763
  }
8763
8764
  let newPoint;
8764
8765
  if (shouldRotateWithDiscreteAngle(event) && points.length >= 2) {
@@ -8778,8 +8779,8 @@ var LinearElementEditor = class _LinearElementEditor {
8778
8779
  newPoint = _LinearElementEditor.createPointAt(
8779
8780
  element,
8780
8781
  elementsMap,
8781
- scenePointerX - appState.editingLinearElement.pointerOffset.x,
8782
- scenePointerY - appState.editingLinearElement.pointerOffset.y,
8782
+ scenePointerX - appState.selectedLinearElement.pointerOffset.x,
8783
+ scenePointerY - appState.selectedLinearElement.pointerOffset.y,
8783
8784
  event[KEYS2.CTRL_OR_CMD] || isElbowArrow(element) ? null : app.getEffectiveGridSize()
8784
8785
  );
8785
8786
  }
@@ -8800,7 +8801,7 @@ var LinearElementEditor = class _LinearElementEditor {
8800
8801
  _LinearElementEditor.addPoints(element, app.scene, [newPoint]);
8801
8802
  }
8802
8803
  return {
8803
- ...appState.editingLinearElement,
8804
+ ...appState.selectedLinearElement,
8804
8805
  lastUncommittedPoint: element.points[element.points.length - 1]
8805
8806
  };
8806
8807
  }
@@ -8906,11 +8907,11 @@ var LinearElementEditor = class _LinearElementEditor {
8906
8907
  // ---------------------------------------------------------------------------
8907
8908
  static duplicateSelectedPoints(appState, scene) {
8908
8909
  invariant6(
8909
- appState.editingLinearElement,
8910
+ appState.selectedLinearElement?.isEditing,
8910
8911
  "Not currently editing a linear element"
8911
8912
  );
8912
8913
  const elementsMap = scene.getNonDeletedElementsMap();
8913
- const { selectedPointsIndices, elementId } = appState.editingLinearElement;
8914
+ const { selectedPointsIndices, elementId } = appState.selectedLinearElement;
8914
8915
  const element = _LinearElementEditor.getElement(elementId, elementsMap);
8915
8916
  invariant6(
8916
8917
  element,
@@ -8957,14 +8958,14 @@ var LinearElementEditor = class _LinearElementEditor {
8957
8958
  }
8958
8959
  return {
8959
8960
  ...appState,
8960
- editingLinearElement: {
8961
- ...appState.editingLinearElement,
8961
+ selectedLinearElement: {
8962
+ ...appState.selectedLinearElement,
8962
8963
  selectedPointsIndices: nextSelectedIndices
8963
8964
  }
8964
8965
  };
8965
8966
  }
8966
8967
  static deletePoints(element, app, pointIndices) {
8967
- const isUncommittedPoint = app.state.editingLinearElement?.lastUncommittedPoint === element.points[element.points.length - 1];
8968
+ const isUncommittedPoint = app.state.selectedLinearElement?.isEditing && app.state.selectedLinearElement?.lastUncommittedPoint === element.points[element.points.length - 1];
8968
8969
  const nextPoints = element.points.filter((_, idx) => {
8969
8970
  return !pointIndices.includes(idx);
8970
8971
  });
@@ -9073,7 +9074,7 @@ var LinearElementEditor = class _LinearElementEditor {
9073
9074
  pointFrom8(origin.x, origin.y),
9074
9075
  pointFrom8(pointerCoords.x, pointerCoords.y)
9075
9076
  );
9076
- if (!appState.editingLinearElement && dist < DRAGGING_THRESHOLD / appState.zoom.value) {
9077
+ if (!appState.selectedLinearElement?.isEditing && dist < DRAGGING_THRESHOLD / appState.zoom.value) {
9077
9078
  return false;
9078
9079
  }
9079
9080
  return true;
@@ -9826,6 +9827,55 @@ var getNewGroupIdsForDuplication = (groupIds, editingGroupId, mapper) => {
9826
9827
  }
9827
9828
  return copy;
9828
9829
  };
9830
+ var getSelectedElementsByGroup = (selectedElements, elementsMap, appState) => {
9831
+ const selectedGroupIds = getSelectedGroupIds(appState);
9832
+ const unboundElements = selectedElements.filter(
9833
+ (element) => !isBoundToContainer(element)
9834
+ );
9835
+ const groups = /* @__PURE__ */ new Map();
9836
+ const elements = /* @__PURE__ */ new Map();
9837
+ const addToElementsMap = (element) => {
9838
+ const currentElementMembers = elements.get(element.id) || [];
9839
+ const boundTextElement = getBoundTextElement(element, elementsMap);
9840
+ if (boundTextElement) {
9841
+ currentElementMembers.push(boundTextElement);
9842
+ }
9843
+ elements.set(element.id, [...currentElementMembers, element]);
9844
+ };
9845
+ const addToGroupsMap = (element, groupId) => {
9846
+ const currentGroupMembers = groups.get(groupId) || [];
9847
+ const boundTextElement = getBoundTextElement(element, elementsMap);
9848
+ if (boundTextElement) {
9849
+ currentGroupMembers.push(boundTextElement);
9850
+ }
9851
+ groups.set(groupId, [...currentGroupMembers, element]);
9852
+ };
9853
+ const handleSingleSelectedGroupCase = (element, selectedGroupId) => {
9854
+ const indexOfSelectedGroupId = element.groupIds.indexOf(selectedGroupId, 0);
9855
+ const nestedGroupCount = element.groupIds.slice(
9856
+ 0,
9857
+ indexOfSelectedGroupId
9858
+ ).length;
9859
+ return nestedGroupCount > 0 ? addToGroupsMap(element, element.groupIds[indexOfSelectedGroupId - 1]) : addToElementsMap(element);
9860
+ };
9861
+ const isAllInSameGroup = selectedElements.every(
9862
+ (element) => isSelectedViaGroup(appState, element)
9863
+ );
9864
+ unboundElements.forEach((element) => {
9865
+ const selectedGroupId = getSelectedGroupIdForElement(
9866
+ element,
9867
+ appState.selectedGroupIds
9868
+ );
9869
+ if (!selectedGroupId) {
9870
+ addToElementsMap(element);
9871
+ } else if (selectedGroupIds.length === 1 && isAllInSameGroup) {
9872
+ handleSingleSelectedGroupCase(element, selectedGroupId);
9873
+ } else {
9874
+ addToGroupsMap(element, selectedGroupId);
9875
+ }
9876
+ });
9877
+ return Array.from(groups.values()).concat(Array.from(elements.values()));
9878
+ };
9829
9879
 
9830
9880
  // src/selection.ts
9831
9881
  var excludeElementsInFramesFromSelection = (selectedElements) => {
@@ -10513,6 +10563,11 @@ var getCanvasPadding = (element) => {
10513
10563
  return element.strokeWidth * 12;
10514
10564
  case "text":
10515
10565
  return element.fontSize / 2;
10566
+ case "arrow":
10567
+ if (element.endArrowhead || element.endArrowhead) {
10568
+ return 40;
10569
+ }
10570
+ return 20;
10516
10571
  default:
10517
10572
  return 20;
10518
10573
  }
@@ -12742,11 +12797,11 @@ var getNormalizedDimensions = (element) => {
12742
12797
 
12743
12798
  // src/align.ts
12744
12799
  init_define_import_meta_env();
12745
- var alignElements = (selectedElements, alignment, scene) => {
12746
- const elementsMap = scene.getNonDeletedElementsMap();
12747
- const groups = getMaximumGroups(
12800
+ var alignElements = (selectedElements, alignment, scene, appState) => {
12801
+ const groups = getSelectedElementsByGroup(
12748
12802
  selectedElements,
12749
- elementsMap
12803
+ scene.getNonDeletedElementsMap(),
12804
+ appState
12750
12805
  );
12751
12806
  const selectionBoundingBox = getCommonBoundingBox(selectedElements);
12752
12807
  return groups.flatMap((group) => {
@@ -13182,8 +13237,9 @@ var Store = class {
13182
13237
  constructor(app) {
13183
13238
  this.app = app;
13184
13239
  }
13185
- // internally used by history
13240
+ // for internal use by history
13186
13241
  onDurableIncrementEmitter = new Emitter();
13242
+ // for public use as part of onIncrement API
13187
13243
  onStoreIncrementEmitter = new Emitter();
13188
13244
  scheduledMacroActions = /* @__PURE__ */ new Set();
13189
13245
  scheduledMicroActions = [];
@@ -13439,7 +13495,7 @@ var EphemeralIncrement = class extends StoreIncrement {
13439
13495
  this.change = change;
13440
13496
  }
13441
13497
  };
13442
- var StoreDelta = class {
13498
+ var StoreDelta = class _StoreDelta {
13443
13499
  constructor(id, elements, appState) {
13444
13500
  this.id = id;
13445
13501
  this.elements = elements;
@@ -13477,10 +13533,23 @@ var StoreDelta = class {
13477
13533
  */
13478
13534
  static load({
13479
13535
  id,
13480
- elements: { added, removed, updated }
13536
+ elements: { added, removed, updated },
13537
+ appState: { delta: appStateDelta }
13481
13538
  }) {
13482
13539
  const elements = ElementsDelta.create(added, removed, updated);
13483
- return new this(id, elements, AppStateDelta.empty());
13540
+ const appState = AppStateDelta.create(appStateDelta);
13541
+ return new this(id, elements, appState);
13542
+ }
13543
+ /**
13544
+ * Squash the passed deltas into the aggregated delta instance.
13545
+ */
13546
+ static squash(...deltas) {
13547
+ const aggregatedDelta = _StoreDelta.empty();
13548
+ for (const delta of deltas) {
13549
+ aggregatedDelta.elements.squash(delta.elements);
13550
+ aggregatedDelta.appState.squash(delta.appState);
13551
+ }
13552
+ return aggregatedDelta;
13484
13553
  }
13485
13554
  /**
13486
13555
  * Inverse store delta, creates new instance of `StoreDelta`.
@@ -13491,9 +13560,7 @@ var StoreDelta = class {
13491
13560
  /**
13492
13561
  * Apply the delta to the passed elements and appState, does not modify the snapshot.
13493
13562
  */
13494
- static applyTo(delta, elements, appState, options = {
13495
- excludedProperties: /* @__PURE__ */ new Set()
13496
- }) {
13563
+ static applyTo(delta, elements, appState, options) {
13497
13564
  const [nextElements, elementsContainVisibleChange] = delta.elements.applyTo(
13498
13565
  elements,
13499
13566
  StoreSnapshot.empty().elements,
@@ -13519,6 +13586,9 @@ var StoreDelta = class {
13519
13586
  }
13520
13587
  );
13521
13588
  }
13589
+ static empty() {
13590
+ return _StoreDelta.create(ElementsDelta.empty(), AppStateDelta.empty());
13591
+ }
13522
13592
  isEmpty() {
13523
13593
  return this.elements.isEmpty() && this.appState.isEmpty();
13524
13594
  }
@@ -13759,8 +13829,7 @@ var getDefaultObservedAppState = () => {
13759
13829
  viewBackgroundColor: COLOR_PALETTE2.white,
13760
13830
  selectedElementIds: {},
13761
13831
  selectedGroupIds: {},
13762
- editingLinearElementId: null,
13763
- selectedLinearElementId: null,
13832
+ selectedLinearElement: null,
13764
13833
  croppingElementId: null,
13765
13834
  activeLockedId: null,
13766
13835
  lockedMultiSelections: {}
@@ -13776,10 +13845,10 @@ var getObservedAppState = (appState) => {
13776
13845
  croppingElementId: appState.croppingElementId,
13777
13846
  activeLockedId: appState.activeLockedId,
13778
13847
  lockedMultiSelections: appState.lockedMultiSelections,
13779
- editingLinearElementId: appState.editingLinearElement?.elementId ?? // prefer app state, as it's likely newer
13780
- appState.editingLinearElementId ?? // fallback to observed app state, as it's likely older coming from a previous snapshot
13781
- null,
13782
- selectedLinearElementId: appState.selectedLinearElement?.elementId ?? appState.selectedLinearElementId ?? null
13848
+ selectedLinearElement: appState.selectedLinearElement ? {
13849
+ elementId: appState.selectedLinearElement.elementId,
13850
+ isEditing: !!appState.selectedLinearElement.isEditing
13851
+ } : null
13783
13852
  };
13784
13853
  Reflect.defineProperty(observedAppState, hiddenObservedAppStateProp, {
13785
13854
  value: true,
@@ -14343,9 +14412,9 @@ var Scene = class {
14343
14412
  getFramesIncludingDeleted() {
14344
14413
  return this.frames;
14345
14414
  }
14346
- constructor(elements = null) {
14415
+ constructor(elements = null, options) {
14347
14416
  if (elements) {
14348
- this.replaceAllElements(elements);
14417
+ this.replaceAllElements(elements, options);
14349
14418
  }
14350
14419
  }
14351
14420
  getSelectedElements(opts) {
@@ -14410,10 +14479,12 @@ var Scene = class {
14410
14479
  }
14411
14480
  return didChange;
14412
14481
  }
14413
- replaceAllElements(nextElements) {
14482
+ replaceAllElements(nextElements, options) {
14414
14483
  const _nextElements = toArray(nextElements);
14415
14484
  const nextFrameLikes = [];
14416
- validateIndicesThrottled(_nextElements);
14485
+ if (!options?.skipValidation) {
14486
+ validateIndicesThrottled(_nextElements);
14487
+ }
14417
14488
  this.elements = syncInvalidIndices2(_nextElements);
14418
14489
  this.elementsMap.clear();
14419
14490
  this.elements.forEach((element) => {
@@ -14583,10 +14654,19 @@ var Delta = class _Delta {
14583
14654
  static isEmpty(delta) {
14584
14655
  return !Object.keys(delta.deleted).length && !Object.keys(delta.inserted).length;
14585
14656
  }
14657
+ /**
14658
+ * Merges two deltas into a new one.
14659
+ */
14660
+ static merge(delta1, delta2, delta3 = _Delta.empty()) {
14661
+ return _Delta.create(
14662
+ { ...delta1.deleted, ...delta2.deleted, ...delta3.deleted },
14663
+ { ...delta1.inserted, ...delta2.inserted, ...delta3.inserted }
14664
+ );
14665
+ }
14586
14666
  /**
14587
14667
  * Merges deleted and inserted object partials.
14588
14668
  */
14589
- static mergeObjects(prev, added, removed) {
14669
+ static mergeObjects(prev, added, removed = {}) {
14590
14670
  const cloned = { ...prev };
14591
14671
  for (const key of Object.keys(removed)) {
14592
14672
  delete cloned[key];
@@ -14807,6 +14887,9 @@ var AppStateDelta = class _AppStateDelta {
14807
14887
  constructor(delta) {
14808
14888
  this.delta = delta;
14809
14889
  }
14890
+ static create(delta) {
14891
+ return new _AppStateDelta(delta);
14892
+ }
14810
14893
  static calculate(prevAppState, nextAppState) {
14811
14894
  const delta = Delta.calculate(
14812
14895
  prevAppState,
@@ -14828,50 +14911,98 @@ var AppStateDelta = class _AppStateDelta {
14828
14911
  const inversedDelta = Delta.create(this.delta.inserted, this.delta.deleted);
14829
14912
  return new _AppStateDelta(inversedDelta);
14830
14913
  }
14914
+ squash(delta) {
14915
+ if (delta.isEmpty()) {
14916
+ return this;
14917
+ }
14918
+ const mergedDeletedSelectedElementIds = Delta.mergeObjects(
14919
+ this.delta.deleted.selectedElementIds ?? {},
14920
+ delta.delta.deleted.selectedElementIds ?? {}
14921
+ );
14922
+ const mergedInsertedSelectedElementIds = Delta.mergeObjects(
14923
+ this.delta.inserted.selectedElementIds ?? {},
14924
+ delta.delta.inserted.selectedElementIds ?? {}
14925
+ );
14926
+ const mergedDeletedSelectedGroupIds = Delta.mergeObjects(
14927
+ this.delta.deleted.selectedGroupIds ?? {},
14928
+ delta.delta.deleted.selectedGroupIds ?? {}
14929
+ );
14930
+ const mergedInsertedSelectedGroupIds = Delta.mergeObjects(
14931
+ this.delta.inserted.selectedGroupIds ?? {},
14932
+ delta.delta.inserted.selectedGroupIds ?? {}
14933
+ );
14934
+ const mergedDeletedLockedMultiSelections = Delta.mergeObjects(
14935
+ this.delta.deleted.lockedMultiSelections ?? {},
14936
+ delta.delta.deleted.lockedMultiSelections ?? {}
14937
+ );
14938
+ const mergedInsertedLockedMultiSelections = Delta.mergeObjects(
14939
+ this.delta.inserted.lockedMultiSelections ?? {},
14940
+ delta.delta.inserted.lockedMultiSelections ?? {}
14941
+ );
14942
+ const mergedInserted = {};
14943
+ const mergedDeleted = {};
14944
+ if (Object.keys(mergedDeletedSelectedElementIds).length || Object.keys(mergedInsertedSelectedElementIds).length) {
14945
+ mergedDeleted.selectedElementIds = mergedDeletedSelectedElementIds;
14946
+ mergedInserted.selectedElementIds = mergedInsertedSelectedElementIds;
14947
+ }
14948
+ if (Object.keys(mergedDeletedSelectedGroupIds).length || Object.keys(mergedInsertedSelectedGroupIds).length) {
14949
+ mergedDeleted.selectedGroupIds = mergedDeletedSelectedGroupIds;
14950
+ mergedInserted.selectedGroupIds = mergedInsertedSelectedGroupIds;
14951
+ }
14952
+ if (Object.keys(mergedDeletedLockedMultiSelections).length || Object.keys(mergedInsertedLockedMultiSelections).length) {
14953
+ mergedDeleted.lockedMultiSelections = mergedDeletedLockedMultiSelections;
14954
+ mergedInserted.lockedMultiSelections = mergedInsertedLockedMultiSelections;
14955
+ }
14956
+ this.delta = Delta.merge(
14957
+ this.delta,
14958
+ delta.delta,
14959
+ Delta.create(mergedDeleted, mergedInserted)
14960
+ );
14961
+ return this;
14962
+ }
14831
14963
  applyTo(appState, nextElements) {
14832
14964
  try {
14833
14965
  const {
14834
- selectedElementIds: removedSelectedElementIds = {},
14835
- selectedGroupIds: removedSelectedGroupIds = {}
14966
+ selectedElementIds: deletedSelectedElementIds = {},
14967
+ selectedGroupIds: deletedSelectedGroupIds = {},
14968
+ lockedMultiSelections: deletedLockedMultiSelections = {}
14836
14969
  } = this.delta.deleted;
14837
14970
  const {
14838
- selectedElementIds: addedSelectedElementIds = {},
14839
- selectedGroupIds: addedSelectedGroupIds = {},
14840
- selectedLinearElementId,
14841
- editingLinearElementId,
14971
+ selectedElementIds: insertedSelectedElementIds = {},
14972
+ selectedGroupIds: insertedSelectedGroupIds = {},
14973
+ lockedMultiSelections: insertedLockedMultiSelections = {},
14974
+ selectedLinearElement: insertedSelectedLinearElement,
14842
14975
  ...directlyApplicablePartial
14843
14976
  } = this.delta.inserted;
14844
14977
  const mergedSelectedElementIds = Delta.mergeObjects(
14845
14978
  appState.selectedElementIds,
14846
- addedSelectedElementIds,
14847
- removedSelectedElementIds
14979
+ insertedSelectedElementIds,
14980
+ deletedSelectedElementIds
14848
14981
  );
14849
14982
  const mergedSelectedGroupIds = Delta.mergeObjects(
14850
14983
  appState.selectedGroupIds,
14851
- addedSelectedGroupIds,
14852
- removedSelectedGroupIds
14984
+ insertedSelectedGroupIds,
14985
+ deletedSelectedGroupIds
14853
14986
  );
14854
- const selectedLinearElement = selectedLinearElementId && nextElements.has(selectedLinearElementId) ? new LinearElementEditor(
14855
- nextElements.get(
14856
- selectedLinearElementId
14857
- ),
14858
- nextElements
14859
- ) : null;
14860
- const editingLinearElement = editingLinearElementId && nextElements.has(editingLinearElementId) ? new LinearElementEditor(
14987
+ const mergedLockedMultiSelections = Delta.mergeObjects(
14988
+ appState.lockedMultiSelections,
14989
+ insertedLockedMultiSelections,
14990
+ deletedLockedMultiSelections
14991
+ );
14992
+ const selectedLinearElement = insertedSelectedLinearElement && nextElements.has(insertedSelectedLinearElement.elementId) ? new LinearElementEditor(
14861
14993
  nextElements.get(
14862
- editingLinearElementId
14994
+ insertedSelectedLinearElement.elementId
14863
14995
  ),
14864
- nextElements
14996
+ nextElements,
14997
+ insertedSelectedLinearElement.isEditing
14865
14998
  ) : null;
14866
14999
  const nextAppState = {
14867
15000
  ...appState,
14868
15001
  ...directlyApplicablePartial,
14869
15002
  selectedElementIds: mergedSelectedElementIds,
14870
15003
  selectedGroupIds: mergedSelectedGroupIds,
14871
- selectedLinearElement: typeof selectedLinearElementId !== "undefined" ? selectedLinearElement : appState.selectedLinearElement,
14872
- // otherwise assign what we had before
14873
- editingLinearElement: typeof editingLinearElementId !== "undefined" ? editingLinearElement : appState.editingLinearElement
14874
- // otherwise assign what we had before
15004
+ lockedMultiSelections: mergedLockedMultiSelections,
15005
+ selectedLinearElement: typeof insertedSelectedLinearElement !== "undefined" ? selectedLinearElement : appState.selectedLinearElement
14875
15006
  };
14876
15007
  const constainsVisibleChanges = this.filterInvisibleChanges(
14877
15008
  appState,
@@ -14961,57 +15092,44 @@ var AppStateDelta = class _AppStateDelta {
14961
15092
  nextAppState[key] = null;
14962
15093
  }
14963
15094
  break;
14964
- case "selectedLinearElementId":
14965
- case "editingLinearElementId":
14966
- const appStateKey = _AppStateDelta.convertToAppStateKey(key);
14967
- const linearElement = nextAppState[appStateKey];
14968
- if (!linearElement) {
15095
+ case "selectedLinearElement":
15096
+ const nextLinearElement = nextAppState[key];
15097
+ if (!nextLinearElement) {
14969
15098
  visibleDifferenceFlag.value = true;
14970
15099
  } else {
14971
- const element = nextElements.get(linearElement.elementId);
15100
+ const element = nextElements.get(nextLinearElement.elementId);
14972
15101
  if (element && !element.isDeleted) {
14973
15102
  visibleDifferenceFlag.value = true;
14974
15103
  } else {
14975
- nextAppState[appStateKey] = null;
15104
+ nextAppState[key] = null;
14976
15105
  }
14977
15106
  }
14978
15107
  break;
14979
- case "lockedMultiSelections": {
15108
+ case "lockedMultiSelections":
14980
15109
  const prevLockedUnits = prevAppState[key] || {};
14981
15110
  const nextLockedUnits = nextAppState[key] || {};
14982
15111
  if (!isShallowEqual2(prevLockedUnits, nextLockedUnits)) {
14983
15112
  visibleDifferenceFlag.value = true;
14984
15113
  }
14985
15114
  break;
14986
- }
14987
- case "activeLockedId": {
15115
+ case "activeLockedId":
14988
15116
  const prevHitLockedId = prevAppState[key] || null;
14989
15117
  const nextHitLockedId = nextAppState[key] || null;
14990
15118
  if (prevHitLockedId !== nextHitLockedId) {
14991
15119
  visibleDifferenceFlag.value = true;
14992
15120
  }
14993
15121
  break;
14994
- }
14995
- default: {
15122
+ default:
14996
15123
  assertNever4(
14997
15124
  key,
14998
15125
  `Unknown ObservedElementsAppState's key "${key}"`,
14999
15126
  true
15000
15127
  );
15001
- }
15002
15128
  }
15003
15129
  }
15004
15130
  }
15005
15131
  return visibleDifferenceFlag.value;
15006
15132
  }
15007
- static convertToAppStateKey(key) {
15008
- switch (key) {
15009
- case "selectedLinearElementId":
15010
- return "selectedLinearElement";
15011
- case "editingLinearElementId":
15012
- return "editingLinearElement";
15013
- }
15014
- }
15015
15133
  static filterSelectedElements(selectedElementIds, elements, visibleDifferenceFlag) {
15016
15134
  const ids = Object.keys(selectedElementIds);
15017
15135
  if (!ids.length) {
@@ -15050,8 +15168,7 @@ var AppStateDelta = class _AppStateDelta {
15050
15168
  editingGroupId,
15051
15169
  selectedGroupIds,
15052
15170
  selectedElementIds,
15053
- editingLinearElementId,
15054
- selectedLinearElementId,
15171
+ selectedLinearElement,
15055
15172
  croppingElementId,
15056
15173
  lockedMultiSelections,
15057
15174
  activeLockedId,
@@ -15088,12 +15205,6 @@ var AppStateDelta = class _AppStateDelta {
15088
15205
  "lockedMultiSelections",
15089
15206
  (prevValue) => prevValue ?? {}
15090
15207
  );
15091
- Delta.diffObjects(
15092
- deleted,
15093
- inserted,
15094
- "activeLockedId",
15095
- (prevValue) => prevValue ?? null
15096
- );
15097
15208
  } catch (e) {
15098
15209
  console.error(`Couldn't postprocess appstate change deltas.`);
15099
15210
  if (isTestEnv8() || isDevEnv7()) {
@@ -15176,9 +15287,13 @@ var ElementsDelta = class _ElementsDelta {
15176
15287
  Number.isInteger(deleted.version) && Number.isInteger(inserted.version) && // versions should be positive, zero included
15177
15288
  deleted.version >= 0 && inserted.version >= 0 && // versions should never be the same
15178
15289
  deleted.version !== inserted.version);
15290
+ static satisfiesUniqueInvariants = (elementsDelta, id) => {
15291
+ const { added, removed, updated } = elementsDelta;
15292
+ return [added[id], removed[id], updated[id]].filter(Boolean).length === 1;
15293
+ };
15179
15294
  static validate(elementsDelta, type, satifiesSpecialInvariants) {
15180
15295
  for (const [id, delta] of Object.entries(elementsDelta[type])) {
15181
- if (!this.satisfiesCommmonInvariants(delta) || !satifiesSpecialInvariants(delta)) {
15296
+ if (!this.satisfiesCommmonInvariants(delta) || !this.satisfiesUniqueInvariants(elementsDelta, id) || !satifiesSpecialInvariants(delta)) {
15182
15297
  console.error(
15183
15298
  `Broken invariant for "${type}" delta, element "${id}", delta:`,
15184
15299
  delta
@@ -15205,7 +15320,7 @@ var ElementsDelta = class _ElementsDelta {
15205
15320
  for (const prevElement of prevElements.values()) {
15206
15321
  const nextElement = nextElements.get(prevElement.id);
15207
15322
  if (!nextElement) {
15208
- const deleted = { ...prevElement, isDeleted: false };
15323
+ const deleted = { ...prevElement };
15209
15324
  const inserted = {
15210
15325
  isDeleted: true,
15211
15326
  version: prevElement.version + 1,
@@ -15216,7 +15331,9 @@ var ElementsDelta = class _ElementsDelta {
15216
15331
  inserted,
15217
15332
  _ElementsDelta.stripIrrelevantProps
15218
15333
  );
15219
- removed[prevElement.id] = delta;
15334
+ if (!prevElement.isDeleted) {
15335
+ removed[prevElement.id] = delta;
15336
+ }
15220
15337
  }
15221
15338
  }
15222
15339
  for (const nextElement of nextElements.values()) {
@@ -15228,15 +15345,16 @@ var ElementsDelta = class _ElementsDelta {
15228
15345
  versionNonce: randomInteger4()
15229
15346
  };
15230
15347
  const inserted = {
15231
- ...nextElement,
15232
- isDeleted: false
15348
+ ...nextElement
15233
15349
  };
15234
15350
  const delta = Delta.create(
15235
15351
  deleted,
15236
15352
  inserted,
15237
15353
  _ElementsDelta.stripIrrelevantProps
15238
15354
  );
15239
- added[nextElement.id] = delta;
15355
+ if (!nextElement.isDeleted) {
15356
+ added[nextElement.id] = delta;
15357
+ }
15240
15358
  continue;
15241
15359
  }
15242
15360
  if (prevElement.versionNonce !== nextElement.versionNonce) {
@@ -15257,7 +15375,11 @@ var ElementsDelta = class _ElementsDelta {
15257
15375
  }
15258
15376
  continue;
15259
15377
  }
15260
- if (!Delta.isEmpty(delta)) {
15378
+ const strippedDeleted = _ElementsDelta.stripVersionProps(delta.deleted);
15379
+ const strippedInserted = _ElementsDelta.stripVersionProps(
15380
+ delta.inserted
15381
+ );
15382
+ if (Delta.isInnerDifferent(strippedDeleted, strippedInserted, true)) {
15261
15383
  updated[nextElement.id] = delta;
15262
15384
  }
15263
15385
  }
@@ -15270,8 +15392,8 @@ var ElementsDelta = class _ElementsDelta {
15270
15392
  inverse() {
15271
15393
  const inverseInternal = (deltas) => {
15272
15394
  const inversedDeltas = {};
15273
- for (const [id, delta] of Object.entries(deltas)) {
15274
- inversedDeltas[id] = Delta.create(delta.inserted, delta.deleted);
15395
+ for (const [id, { inserted, deleted }] of Object.entries(deltas)) {
15396
+ inversedDeltas[id] = Delta.create({ ...inserted }, { ...deleted });
15275
15397
  }
15276
15398
  return inversedDeltas;
15277
15399
  };
@@ -15335,7 +15457,13 @@ var ElementsDelta = class _ElementsDelta {
15335
15457
  } else {
15336
15458
  latestDelta = delta;
15337
15459
  }
15338
- if (Delta.isInnerDifferent(latestDelta.deleted, latestDelta.inserted)) {
15460
+ const strippedDeleted = _ElementsDelta.stripVersionProps(
15461
+ latestDelta.deleted
15462
+ );
15463
+ const strippedInserted = _ElementsDelta.stripVersionProps(
15464
+ latestDelta.inserted
15465
+ );
15466
+ if (Delta.isInnerDifferent(strippedDeleted, strippedInserted)) {
15339
15467
  modifiedDeltas[id] = latestDelta;
15340
15468
  }
15341
15469
  }
@@ -15349,26 +15477,30 @@ var ElementsDelta = class _ElementsDelta {
15349
15477
  // redistribute the deltas as `isDeleted` could have been updated
15350
15478
  });
15351
15479
  }
15352
- applyTo(elements, snapshot = StoreSnapshot.empty().elements, options = {
15353
- excludedProperties: /* @__PURE__ */ new Set()
15354
- }) {
15480
+ applyTo(elements, snapshot = StoreSnapshot.empty().elements, options) {
15355
15481
  let nextElements = new Map(elements);
15356
15482
  let changedElements;
15357
15483
  const flags = {
15358
15484
  containsVisibleDifference: false,
15359
- containsZindexDifference: false
15485
+ containsZindexDifference: false,
15486
+ applyDirection: void 0
15360
15487
  };
15361
15488
  try {
15362
15489
  const applyDeltas = _ElementsDelta.createApplier(
15490
+ elements,
15363
15491
  nextElements,
15364
15492
  snapshot,
15365
- options,
15366
- flags
15493
+ flags,
15494
+ options
15367
15495
  );
15368
15496
  const addedElements = applyDeltas(this.added);
15369
15497
  const removedElements = applyDeltas(this.removed);
15370
15498
  const updatedElements = applyDeltas(this.updated);
15371
- const affectedElements = this.resolveConflicts(elements, nextElements);
15499
+ const affectedElements = this.resolveConflicts(
15500
+ elements,
15501
+ nextElements,
15502
+ flags.applyDirection
15503
+ );
15372
15504
  changedElements = new Map([
15373
15505
  ...addedElements,
15374
15506
  ...removedElements,
@@ -15388,9 +15520,7 @@ var ElementsDelta = class _ElementsDelta {
15388
15520
  changedElements,
15389
15521
  flags
15390
15522
  );
15391
- const tempScene = new Scene(nextElements);
15392
- _ElementsDelta.redrawTextBoundingBoxes(tempScene, changedElements);
15393
- _ElementsDelta.redrawBoundArrows(tempScene, changedElements);
15523
+ _ElementsDelta.redrawElements(nextElements, changedElements);
15394
15524
  } catch (e) {
15395
15525
  console.error(
15396
15526
  `Couldn't mutate elements after applying elements change`,
@@ -15403,7 +15533,82 @@ var ElementsDelta = class _ElementsDelta {
15403
15533
  return [nextElements, flags.containsVisibleDifference];
15404
15534
  }
15405
15535
  }
15406
- static createApplier = (nextElements, snapshot, options, flags) => (deltas) => {
15536
+ squash(delta) {
15537
+ if (delta.isEmpty()) {
15538
+ return this;
15539
+ }
15540
+ const { added, removed, updated } = delta;
15541
+ const mergeBoundElements = (prevDelta, nextDelta) => {
15542
+ const mergedDeletedBoundElements = Delta.mergeArrays(
15543
+ prevDelta.deleted.boundElements ?? [],
15544
+ nextDelta.deleted.boundElements ?? [],
15545
+ void 0,
15546
+ (x) => x.id
15547
+ ) ?? [];
15548
+ const mergedInsertedBoundElements = Delta.mergeArrays(
15549
+ prevDelta.inserted.boundElements ?? [],
15550
+ nextDelta.inserted.boundElements ?? [],
15551
+ void 0,
15552
+ (x) => x.id
15553
+ ) ?? [];
15554
+ if (!mergedDeletedBoundElements.length && !mergedInsertedBoundElements.length) {
15555
+ return;
15556
+ }
15557
+ return Delta.create(
15558
+ {
15559
+ boundElements: mergedDeletedBoundElements
15560
+ },
15561
+ {
15562
+ boundElements: mergedInsertedBoundElements
15563
+ }
15564
+ );
15565
+ };
15566
+ for (const [id, nextDelta] of Object.entries(added)) {
15567
+ const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];
15568
+ if (!prevDelta) {
15569
+ this.added[id] = nextDelta;
15570
+ } else {
15571
+ const mergedDelta = mergeBoundElements(prevDelta, nextDelta);
15572
+ delete this.removed[id];
15573
+ delete this.updated[id];
15574
+ this.added[id] = Delta.merge(prevDelta, nextDelta, mergedDelta);
15575
+ }
15576
+ }
15577
+ for (const [id, nextDelta] of Object.entries(removed)) {
15578
+ const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];
15579
+ if (!prevDelta) {
15580
+ this.removed[id] = nextDelta;
15581
+ } else {
15582
+ const mergedDelta = mergeBoundElements(prevDelta, nextDelta);
15583
+ delete this.added[id];
15584
+ delete this.updated[id];
15585
+ this.removed[id] = Delta.merge(prevDelta, nextDelta, mergedDelta);
15586
+ }
15587
+ }
15588
+ for (const [id, nextDelta] of Object.entries(updated)) {
15589
+ const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];
15590
+ if (!prevDelta) {
15591
+ this.updated[id] = nextDelta;
15592
+ } else {
15593
+ const mergedDelta = mergeBoundElements(prevDelta, nextDelta);
15594
+ const updatedDelta = Delta.merge(prevDelta, nextDelta, mergedDelta);
15595
+ if (prevDelta === this.added[id]) {
15596
+ this.added[id] = updatedDelta;
15597
+ } else if (prevDelta === this.removed[id]) {
15598
+ this.removed[id] = updatedDelta;
15599
+ } else {
15600
+ this.updated[id] = updatedDelta;
15601
+ }
15602
+ }
15603
+ }
15604
+ if (isTestEnv8() || isDevEnv7()) {
15605
+ _ElementsDelta.validate(this, "added", _ElementsDelta.satisfiesAddition);
15606
+ _ElementsDelta.validate(this, "removed", _ElementsDelta.satisfiesRemoval);
15607
+ _ElementsDelta.validate(this, "updated", _ElementsDelta.satisfiesUpdate);
15608
+ }
15609
+ return this;
15610
+ }
15611
+ static createApplier = (prevElements, nextElements, snapshot, flags, options) => (deltas) => {
15407
15612
  const getElement = _ElementsDelta.createGetter(
15408
15613
  nextElements,
15409
15614
  snapshot,
@@ -15412,14 +15617,20 @@ var ElementsDelta = class _ElementsDelta {
15412
15617
  return Object.entries(deltas).reduce((acc, [id, delta]) => {
15413
15618
  const element = getElement(id, delta.inserted);
15414
15619
  if (element) {
15415
- const newElement2 = _ElementsDelta.applyDelta(
15620
+ const nextElement = _ElementsDelta.applyDelta(
15416
15621
  element,
15417
15622
  delta,
15418
- options,
15419
- flags
15623
+ flags,
15624
+ options
15420
15625
  );
15421
- nextElements.set(newElement2.id, newElement2);
15422
- acc.set(newElement2.id, newElement2);
15626
+ nextElements.set(nextElement.id, nextElement);
15627
+ acc.set(nextElement.id, nextElement);
15628
+ if (!flags.applyDirection) {
15629
+ const prevElement = prevElements.get(id);
15630
+ if (prevElement) {
15631
+ flags.applyDirection = prevElement.version > nextElement.version ? "backward" : "forward";
15632
+ }
15633
+ }
15423
15634
  }
15424
15635
  return acc;
15425
15636
  }, /* @__PURE__ */ new Map());
@@ -15444,13 +15655,13 @@ var ElementsDelta = class _ElementsDelta {
15444
15655
  }
15445
15656
  return element;
15446
15657
  };
15447
- static applyDelta(element, delta, options, flags) {
15658
+ static applyDelta(element, delta, flags, options) {
15448
15659
  const directlyApplicablePartial = {};
15449
15660
  for (const key of Object.keys(delta.inserted)) {
15450
15661
  if (key === "boundElements") {
15451
15662
  continue;
15452
15663
  }
15453
- if (options.excludedProperties.has(key)) {
15664
+ if (options?.excludedProperties?.has(key)) {
15454
15665
  continue;
15455
15666
  }
15456
15667
  const value = delta.inserted[key];
@@ -15478,7 +15689,7 @@ var ElementsDelta = class _ElementsDelta {
15478
15689
  if (!flags.containsZindexDifference) {
15479
15690
  flags.containsZindexDifference = delta.deleted.index !== delta.inserted.index;
15480
15691
  }
15481
- return newElementWith(element, directlyApplicablePartial);
15692
+ return newElementWith(element, directlyApplicablePartial, true);
15482
15693
  }
15483
15694
  /**
15484
15695
  * Check for visible changes regardless of whether they were removed, added or updated.
@@ -15503,25 +15714,32 @@ var ElementsDelta = class _ElementsDelta {
15503
15714
  *
15504
15715
  * @returns all elements affected by the conflict resolution
15505
15716
  */
15506
- resolveConflicts(prevElements, nextElements) {
15717
+ resolveConflicts(prevElements, nextElements, applyDirection = "forward") {
15507
15718
  const nextAffectedElements = /* @__PURE__ */ new Map();
15508
15719
  const updater = (element, updates) => {
15509
15720
  const nextElement = nextElements.get(element.id);
15510
15721
  if (!nextElement) {
15511
15722
  return;
15512
15723
  }
15724
+ const prevElement = prevElements.get(element.id);
15725
+ const nextVersion = applyDirection === "forward" ? nextElement.version + 1 : nextElement.version - 1;
15726
+ const elementUpdates = updates;
15513
15727
  let affectedElement;
15514
- if (prevElements.get(element.id) === nextElement) {
15728
+ if (prevElement === nextElement) {
15515
15729
  affectedElement = newElementWith(
15516
15730
  nextElement,
15517
- updates
15731
+ {
15732
+ ...elementUpdates,
15733
+ version: nextVersion
15734
+ },
15735
+ true
15518
15736
  );
15519
15737
  } else {
15520
- affectedElement = mutateElement(
15521
- nextElement,
15522
- nextElements,
15523
- updates
15524
- );
15738
+ affectedElement = mutateElement(nextElement, nextElements, {
15739
+ ...elementUpdates,
15740
+ // don't modify the version further, if it's already different
15741
+ version: prevElement?.version !== nextElement.version ? nextElement.version : nextVersion
15742
+ });
15525
15743
  }
15526
15744
  nextAffectedElements.set(affectedElement.id, affectedElement);
15527
15745
  nextElements.set(affectedElement.id, affectedElement);
@@ -15546,19 +15764,10 @@ var ElementsDelta = class _ElementsDelta {
15546
15764
  const prevAffectedElements = new Map(
15547
15765
  Array.from(prevElements).filter(([id]) => nextAffectedElements.has(id))
15548
15766
  );
15549
- const { added, removed, updated } = _ElementsDelta.calculate(
15550
- prevAffectedElements,
15551
- nextAffectedElements
15767
+ this.squash(
15768
+ // technically we could do better here if perf. would become an issue
15769
+ _ElementsDelta.calculate(prevAffectedElements, nextAffectedElements)
15552
15770
  );
15553
- for (const [id, delta] of Object.entries(added)) {
15554
- this.added[id] = delta;
15555
- }
15556
- for (const [id, delta] of Object.entries(removed)) {
15557
- this.removed[id] = delta;
15558
- }
15559
- for (const [id, delta] of Object.entries(updated)) {
15560
- this.updated[id] = delta;
15561
- }
15562
15771
  return nextAffectedElements;
15563
15772
  }
15564
15773
  /**
@@ -15593,6 +15802,20 @@ var ElementsDelta = class _ElementsDelta {
15593
15802
  );
15594
15803
  BindableElement.rebindAffected(nextElements, nextElement(), updater);
15595
15804
  }
15805
+ static redrawElements(nextElements, changedElements) {
15806
+ try {
15807
+ const tempScene = new Scene(nextElements, { skipValidation: true });
15808
+ _ElementsDelta.redrawTextBoundingBoxes(tempScene, changedElements);
15809
+ _ElementsDelta.redrawBoundArrows(tempScene, changedElements);
15810
+ } catch (e) {
15811
+ console.error(`Couldn't redraw elements`, e);
15812
+ if (isTestEnv8() || isDevEnv7()) {
15813
+ throw e;
15814
+ }
15815
+ } finally {
15816
+ return nextElements;
15817
+ }
15818
+ }
15596
15819
  static redrawTextBoundingBoxes(scene, changed) {
15597
15820
  const elements = scene.getNonDeletedElementsMap();
15598
15821
  const boxesToRedraw = /* @__PURE__ */ new Map();
@@ -15622,9 +15845,6 @@ var ElementsDelta = class _ElementsDelta {
15622
15845
  if (container.isDeleted || boundText.isDeleted) {
15623
15846
  continue;
15624
15847
  }
15625
- if (!boundText.text) {
15626
- continue;
15627
- }
15628
15848
  redrawTextBoundingBox(boundText, container, scene);
15629
15849
  }
15630
15850
  }
@@ -15684,14 +15904,22 @@ var ElementsDelta = class _ElementsDelta {
15684
15904
  const { id, updated, ...strippedPartial } = partial;
15685
15905
  return strippedPartial;
15686
15906
  }
15907
+ static stripVersionProps(partial) {
15908
+ const { version, versionNonce, ...strippedPartial } = partial;
15909
+ return strippedPartial;
15910
+ }
15687
15911
  };
15688
15912
 
15689
15913
  // src/distribute.ts
15690
15914
  init_define_import_meta_env();
15691
- var distributeElements = (selectedElements, elementsMap, distribution) => {
15915
+ var distributeElements = (selectedElements, elementsMap, distribution, appState) => {
15692
15916
  const [start, mid, end, extent] = distribution.axis === "x" ? ["minX", "midX", "maxX", "width"] : ["minY", "midY", "maxY", "height"];
15693
15917
  const bounds = getCommonBoundingBox(selectedElements);
15694
- const groups = getMaximumGroups(selectedElements, elementsMap).map((group) => [group, getCommonBoundingBox(group)]).sort((a2, b2) => a2[1][mid] - b2[1][mid]);
15918
+ const groups = getSelectedElementsByGroup(
15919
+ selectedElements,
15920
+ elementsMap,
15921
+ appState
15922
+ ).map((group) => [group, getCommonBoundingBox(group)]).sort((a2, b2) => a2[1][mid] - b2[1][mid]);
15695
15923
  let span = 0;
15696
15924
  for (const group of groups) {
15697
15925
  span += group[1][extent];
@@ -18403,7 +18631,7 @@ var getTransformHandles = (element, zoom, elementsMap, pointerType = "mouse", om
18403
18631
  );
18404
18632
  };
18405
18633
  var shouldShowBoundingBox = (elements, appState) => {
18406
- if (appState.editingLinearElement) {
18634
+ if (appState.selectedLinearElement?.isEditing) {
18407
18635
  return false;
18408
18636
  }
18409
18637
  if (elements.length > 1) {
@@ -19151,6 +19379,7 @@ export {
19151
19379
  getRootElements,
19152
19380
  getSceneVersion,
19153
19381
  getSelectedElements,
19382
+ getSelectedElementsByGroup,
19154
19383
  getSelectedGroupForElement,
19155
19384
  getSelectedGroupIdForElement,
19156
19385
  getSelectedGroupIds,