@excalidraw/element 0.18.0-200a6bd94 → 0.18.0-3085f4a

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.
package/dist/dev/index.js CHANGED
@@ -5338,6 +5338,11 @@ var handleSegmentRelease = (arrow, fixedSegments, elementsMap) => {
5338
5338
  null,
5339
5339
  null
5340
5340
  );
5341
+ if (!restoredPoints || restoredPoints.length < 2) {
5342
+ throw new Error(
5343
+ "Property 'points' is required in the update returned by normalizeArrowElementUpdate()"
5344
+ );
5345
+ }
5341
5346
  const nextPoints = [];
5342
5347
  if (prevSegment) {
5343
5348
  for (let i = 0; i < prevSegment.index; i++) {
@@ -5583,8 +5588,13 @@ var handleEndpointDrag = (arrow, updatedPoints, fixedSegments, startHeading, end
5583
5588
  newPoints.push(globalUpdatedPoints[newPoints.length + offset]);
5584
5589
  }
5585
5590
  {
5586
- const secondPoint = globalUpdatedPoints[startIsSpecial ? 2 : 1];
5587
- const thirdPoint = globalUpdatedPoints[startIsSpecial ? 3 : 2];
5591
+ const secondPoint = globalUpdatedPoints.at(startIsSpecial ? 2 : 1);
5592
+ const thirdPoint = globalUpdatedPoints.at(startIsSpecial ? 3 : 2);
5593
+ if (!secondPoint || !thirdPoint) {
5594
+ throw new Error(
5595
+ `Second and third points must exist when handling endpoint drag (${startIsSpecial})`
5596
+ );
5597
+ }
5588
5598
  const startIsHorizontal = headingIsHorizontal(startHeading);
5589
5599
  const secondIsHorizontal = headingIsHorizontal(
5590
5600
  vectorToHeading(vectorFromPoint5(secondPoint, thirdPoint))
@@ -5630,8 +5640,17 @@ var handleEndpointDrag = (arrow, updatedPoints, fixedSegments, startHeading, end
5630
5640
  newPoints.unshift(startGlobalPoint);
5631
5641
  }
5632
5642
  {
5633
- const secondToLastPoint = globalUpdatedPoints[globalUpdatedPoints.length - (endIsSpecial ? 3 : 2)];
5634
- const thirdToLastPoint = globalUpdatedPoints[globalUpdatedPoints.length - (endIsSpecial ? 4 : 3)];
5643
+ const secondToLastPoint = globalUpdatedPoints.at(
5644
+ globalUpdatedPoints.length - (endIsSpecial ? 3 : 2)
5645
+ );
5646
+ const thirdToLastPoint = globalUpdatedPoints.at(
5647
+ globalUpdatedPoints.length - (endIsSpecial ? 4 : 3)
5648
+ );
5649
+ if (!secondToLastPoint || !thirdToLastPoint) {
5650
+ throw new Error(
5651
+ `Second and third to last points must exist when handling endpoint drag (${endIsSpecial})`
5652
+ );
5653
+ }
5635
5654
  const endIsHorizontal = headingIsHorizontal(endHeading);
5636
5655
  const secondIsHorizontal = headingForPointIsHorizontal(
5637
5656
  thirdToLastPoint,
@@ -13495,7 +13514,7 @@ var EphemeralIncrement = class extends StoreIncrement {
13495
13514
  this.change = change;
13496
13515
  }
13497
13516
  };
13498
- var StoreDelta = class {
13517
+ var StoreDelta = class _StoreDelta {
13499
13518
  constructor(id, elements, appState) {
13500
13519
  this.id = id;
13501
13520
  this.elements = elements;
@@ -13533,10 +13552,23 @@ var StoreDelta = class {
13533
13552
  */
13534
13553
  static load({
13535
13554
  id,
13536
- elements: { added, removed, updated }
13555
+ elements: { added, removed, updated },
13556
+ appState: { delta: appStateDelta }
13537
13557
  }) {
13538
13558
  const elements = ElementsDelta.create(added, removed, updated);
13539
- return new this(id, elements, AppStateDelta.empty());
13559
+ const appState = AppStateDelta.create(appStateDelta);
13560
+ return new this(id, elements, appState);
13561
+ }
13562
+ /**
13563
+ * Squash the passed deltas into the aggregated delta instance.
13564
+ */
13565
+ static squash(...deltas) {
13566
+ const aggregatedDelta = _StoreDelta.empty();
13567
+ for (const delta of deltas) {
13568
+ aggregatedDelta.elements.squash(delta.elements);
13569
+ aggregatedDelta.appState.squash(delta.appState);
13570
+ }
13571
+ return aggregatedDelta;
13540
13572
  }
13541
13573
  /**
13542
13574
  * Inverse store delta, creates new instance of `StoreDelta`.
@@ -13547,9 +13579,7 @@ var StoreDelta = class {
13547
13579
  /**
13548
13580
  * Apply the delta to the passed elements and appState, does not modify the snapshot.
13549
13581
  */
13550
- static applyTo(delta, elements, appState, options = {
13551
- excludedProperties: /* @__PURE__ */ new Set()
13552
- }) {
13582
+ static applyTo(delta, elements, appState, options) {
13553
13583
  const [nextElements, elementsContainVisibleChange] = delta.elements.applyTo(
13554
13584
  elements,
13555
13585
  StoreSnapshot.empty().elements,
@@ -13575,6 +13605,9 @@ var StoreDelta = class {
13575
13605
  }
13576
13606
  );
13577
13607
  }
13608
+ static empty() {
13609
+ return _StoreDelta.create(ElementsDelta.empty(), AppStateDelta.empty());
13610
+ }
13578
13611
  isEmpty() {
13579
13612
  return this.elements.isEmpty() && this.appState.isEmpty();
13580
13613
  }
@@ -13815,14 +13848,13 @@ var getDefaultObservedAppState = () => {
13815
13848
  viewBackgroundColor: COLOR_PALETTE2.white,
13816
13849
  selectedElementIds: {},
13817
13850
  selectedGroupIds: {},
13818
- activeLinearElement: null,
13851
+ selectedLinearElement: null,
13819
13852
  croppingElementId: null,
13820
13853
  activeLockedId: null,
13821
13854
  lockedMultiSelections: {}
13822
13855
  };
13823
13856
  };
13824
13857
  var getObservedAppState = (appState) => {
13825
- const selectedLinearElement = appState.selectedLinearElement;
13826
13858
  const observedAppState = {
13827
13859
  name: appState.name,
13828
13860
  editingGroupId: appState.editingGroupId,
@@ -13832,10 +13864,10 @@ var getObservedAppState = (appState) => {
13832
13864
  croppingElementId: appState.croppingElementId,
13833
13865
  activeLockedId: appState.activeLockedId,
13834
13866
  lockedMultiSelections: appState.lockedMultiSelections,
13835
- activeLinearElement: selectedLinearElement ? {
13836
- id: selectedLinearElement.elementId,
13837
- isEditing: !!selectedLinearElement.isEditing
13838
- } : appState.activeLinearElement ?? null
13867
+ selectedLinearElement: appState.selectedLinearElement ? {
13868
+ elementId: appState.selectedLinearElement.elementId,
13869
+ isEditing: !!appState.selectedLinearElement.isEditing
13870
+ } : null
13839
13871
  };
13840
13872
  Reflect.defineProperty(observedAppState, hiddenObservedAppStateProp, {
13841
13873
  value: true,
@@ -14399,9 +14431,9 @@ var Scene = class {
14399
14431
  getFramesIncludingDeleted() {
14400
14432
  return this.frames;
14401
14433
  }
14402
- constructor(elements = null) {
14434
+ constructor(elements = null, options) {
14403
14435
  if (elements) {
14404
- this.replaceAllElements(elements);
14436
+ this.replaceAllElements(elements, options);
14405
14437
  }
14406
14438
  }
14407
14439
  getSelectedElements(opts) {
@@ -14466,10 +14498,12 @@ var Scene = class {
14466
14498
  }
14467
14499
  return didChange;
14468
14500
  }
14469
- replaceAllElements(nextElements) {
14501
+ replaceAllElements(nextElements, options) {
14470
14502
  const _nextElements = toArray(nextElements);
14471
14503
  const nextFrameLikes = [];
14472
- validateIndicesThrottled(_nextElements);
14504
+ if (!options?.skipValidation) {
14505
+ validateIndicesThrottled(_nextElements);
14506
+ }
14473
14507
  this.elements = syncInvalidIndices2(_nextElements);
14474
14508
  this.elementsMap.clear();
14475
14509
  this.elements.forEach((element) => {
@@ -14642,16 +14676,16 @@ var Delta = class _Delta {
14642
14676
  /**
14643
14677
  * Merges two deltas into a new one.
14644
14678
  */
14645
- static merge(delta1, delta2) {
14679
+ static merge(delta1, delta2, delta3 = _Delta.empty()) {
14646
14680
  return _Delta.create(
14647
- { ...delta1.deleted, ...delta2.deleted },
14648
- { ...delta1.inserted, ...delta2.inserted }
14681
+ { ...delta1.deleted, ...delta2.deleted, ...delta3.deleted },
14682
+ { ...delta1.inserted, ...delta2.inserted, ...delta3.inserted }
14649
14683
  );
14650
14684
  }
14651
14685
  /**
14652
14686
  * Merges deleted and inserted object partials.
14653
14687
  */
14654
- static mergeObjects(prev, added, removed) {
14688
+ static mergeObjects(prev, added, removed = {}) {
14655
14689
  const cloned = { ...prev };
14656
14690
  for (const key of Object.keys(removed)) {
14657
14691
  delete cloned[key];
@@ -14872,6 +14906,9 @@ var AppStateDelta = class _AppStateDelta {
14872
14906
  constructor(delta) {
14873
14907
  this.delta = delta;
14874
14908
  }
14909
+ static create(delta) {
14910
+ return new _AppStateDelta(delta);
14911
+ }
14875
14912
  static calculate(prevAppState, nextAppState) {
14876
14913
  const delta = Delta.calculate(
14877
14914
  prevAppState,
@@ -14894,44 +14931,97 @@ var AppStateDelta = class _AppStateDelta {
14894
14931
  return new _AppStateDelta(inversedDelta);
14895
14932
  }
14896
14933
  squash(delta) {
14897
- this.delta = Delta.merge(this.delta, delta.delta);
14934
+ if (delta.isEmpty()) {
14935
+ return this;
14936
+ }
14937
+ const mergedDeletedSelectedElementIds = Delta.mergeObjects(
14938
+ this.delta.deleted.selectedElementIds ?? {},
14939
+ delta.delta.deleted.selectedElementIds ?? {}
14940
+ );
14941
+ const mergedInsertedSelectedElementIds = Delta.mergeObjects(
14942
+ this.delta.inserted.selectedElementIds ?? {},
14943
+ delta.delta.inserted.selectedElementIds ?? {}
14944
+ );
14945
+ const mergedDeletedSelectedGroupIds = Delta.mergeObjects(
14946
+ this.delta.deleted.selectedGroupIds ?? {},
14947
+ delta.delta.deleted.selectedGroupIds ?? {}
14948
+ );
14949
+ const mergedInsertedSelectedGroupIds = Delta.mergeObjects(
14950
+ this.delta.inserted.selectedGroupIds ?? {},
14951
+ delta.delta.inserted.selectedGroupIds ?? {}
14952
+ );
14953
+ const mergedDeletedLockedMultiSelections = Delta.mergeObjects(
14954
+ this.delta.deleted.lockedMultiSelections ?? {},
14955
+ delta.delta.deleted.lockedMultiSelections ?? {}
14956
+ );
14957
+ const mergedInsertedLockedMultiSelections = Delta.mergeObjects(
14958
+ this.delta.inserted.lockedMultiSelections ?? {},
14959
+ delta.delta.inserted.lockedMultiSelections ?? {}
14960
+ );
14961
+ const mergedInserted = {};
14962
+ const mergedDeleted = {};
14963
+ if (Object.keys(mergedDeletedSelectedElementIds).length || Object.keys(mergedInsertedSelectedElementIds).length) {
14964
+ mergedDeleted.selectedElementIds = mergedDeletedSelectedElementIds;
14965
+ mergedInserted.selectedElementIds = mergedInsertedSelectedElementIds;
14966
+ }
14967
+ if (Object.keys(mergedDeletedSelectedGroupIds).length || Object.keys(mergedInsertedSelectedGroupIds).length) {
14968
+ mergedDeleted.selectedGroupIds = mergedDeletedSelectedGroupIds;
14969
+ mergedInserted.selectedGroupIds = mergedInsertedSelectedGroupIds;
14970
+ }
14971
+ if (Object.keys(mergedDeletedLockedMultiSelections).length || Object.keys(mergedInsertedLockedMultiSelections).length) {
14972
+ mergedDeleted.lockedMultiSelections = mergedDeletedLockedMultiSelections;
14973
+ mergedInserted.lockedMultiSelections = mergedInsertedLockedMultiSelections;
14974
+ }
14975
+ this.delta = Delta.merge(
14976
+ this.delta,
14977
+ delta.delta,
14978
+ Delta.create(mergedDeleted, mergedInserted)
14979
+ );
14898
14980
  return this;
14899
14981
  }
14900
14982
  applyTo(appState, nextElements) {
14901
14983
  try {
14902
14984
  const {
14903
- selectedElementIds: removedSelectedElementIds = {},
14904
- selectedGroupIds: removedSelectedGroupIds = {}
14985
+ selectedElementIds: deletedSelectedElementIds = {},
14986
+ selectedGroupIds: deletedSelectedGroupIds = {},
14987
+ lockedMultiSelections: deletedLockedMultiSelections = {}
14905
14988
  } = this.delta.deleted;
14906
14989
  const {
14907
- selectedElementIds: addedSelectedElementIds = {},
14908
- selectedGroupIds: addedSelectedGroupIds = {},
14909
- activeLinearElement,
14990
+ selectedElementIds: insertedSelectedElementIds = {},
14991
+ selectedGroupIds: insertedSelectedGroupIds = {},
14992
+ lockedMultiSelections: insertedLockedMultiSelections = {},
14993
+ selectedLinearElement: insertedSelectedLinearElement,
14910
14994
  ...directlyApplicablePartial
14911
14995
  } = this.delta.inserted;
14912
14996
  const mergedSelectedElementIds = Delta.mergeObjects(
14913
14997
  appState.selectedElementIds,
14914
- addedSelectedElementIds,
14915
- removedSelectedElementIds
14998
+ insertedSelectedElementIds,
14999
+ deletedSelectedElementIds
14916
15000
  );
14917
15001
  const mergedSelectedGroupIds = Delta.mergeObjects(
14918
15002
  appState.selectedGroupIds,
14919
- addedSelectedGroupIds,
14920
- removedSelectedGroupIds
15003
+ insertedSelectedGroupIds,
15004
+ deletedSelectedGroupIds
14921
15005
  );
14922
- const selectedLinearElement = activeLinearElement && nextElements.has(activeLinearElement.id) ? new LinearElementEditor(
15006
+ const mergedLockedMultiSelections = Delta.mergeObjects(
15007
+ appState.lockedMultiSelections,
15008
+ insertedLockedMultiSelections,
15009
+ deletedLockedMultiSelections
15010
+ );
15011
+ const selectedLinearElement = insertedSelectedLinearElement && nextElements.has(insertedSelectedLinearElement.elementId) ? new LinearElementEditor(
14923
15012
  nextElements.get(
14924
- activeLinearElement.id
15013
+ insertedSelectedLinearElement.elementId
14925
15014
  ),
14926
15015
  nextElements,
14927
- activeLinearElement.isEditing
15016
+ insertedSelectedLinearElement.isEditing
14928
15017
  ) : null;
14929
15018
  const nextAppState = {
14930
15019
  ...appState,
14931
15020
  ...directlyApplicablePartial,
14932
15021
  selectedElementIds: mergedSelectedElementIds,
14933
15022
  selectedGroupIds: mergedSelectedGroupIds,
14934
- selectedLinearElement: typeof activeLinearElement !== "undefined" ? selectedLinearElement : appState.selectedLinearElement
15023
+ lockedMultiSelections: mergedLockedMultiSelections,
15024
+ selectedLinearElement: typeof insertedSelectedLinearElement !== "undefined" ? selectedLinearElement : appState.selectedLinearElement
14935
15025
  };
14936
15026
  const constainsVisibleChanges = this.filterInvisibleChanges(
14937
15027
  appState,
@@ -15021,9 +15111,8 @@ var AppStateDelta = class _AppStateDelta {
15021
15111
  nextAppState[key] = null;
15022
15112
  }
15023
15113
  break;
15024
- case "activeLinearElement":
15025
- const appStateKey = _AppStateDelta.convertToAppStateKey(key);
15026
- const nextLinearElement = nextAppState[appStateKey];
15114
+ case "selectedLinearElement":
15115
+ const nextLinearElement = nextAppState[key];
15027
15116
  if (!nextLinearElement) {
15028
15117
  visibleDifferenceFlag.value = true;
15029
15118
  } else {
@@ -15031,7 +15120,7 @@ var AppStateDelta = class _AppStateDelta {
15031
15120
  if (element && !element.isDeleted) {
15032
15121
  visibleDifferenceFlag.value = true;
15033
15122
  } else {
15034
- nextAppState[appStateKey] = null;
15123
+ nextAppState[key] = null;
15035
15124
  }
15036
15125
  }
15037
15126
  break;
@@ -15060,12 +15149,6 @@ var AppStateDelta = class _AppStateDelta {
15060
15149
  }
15061
15150
  return visibleDifferenceFlag.value;
15062
15151
  }
15063
- static convertToAppStateKey(key) {
15064
- switch (key) {
15065
- case "activeLinearElement":
15066
- return "selectedLinearElement";
15067
- }
15068
- }
15069
15152
  static filterSelectedElements(selectedElementIds, elements, visibleDifferenceFlag) {
15070
15153
  const ids = Object.keys(selectedElementIds);
15071
15154
  if (!ids.length) {
@@ -15104,7 +15187,7 @@ var AppStateDelta = class _AppStateDelta {
15104
15187
  editingGroupId,
15105
15188
  selectedGroupIds,
15106
15189
  selectedElementIds,
15107
- activeLinearElement,
15190
+ selectedLinearElement,
15108
15191
  croppingElementId,
15109
15192
  lockedMultiSelections,
15110
15193
  activeLockedId,
@@ -15141,12 +15224,6 @@ var AppStateDelta = class _AppStateDelta {
15141
15224
  "lockedMultiSelections",
15142
15225
  (prevValue) => prevValue ?? {}
15143
15226
  );
15144
- Delta.diffObjects(
15145
- deleted,
15146
- inserted,
15147
- "activeLockedId",
15148
- (prevValue) => prevValue ?? null
15149
- );
15150
15227
  } catch (e) {
15151
15228
  console.error(`Couldn't postprocess appstate change deltas.`);
15152
15229
  if (isTestEnv8() || isDevEnv7()) {
@@ -15225,13 +15302,17 @@ var ElementsDelta = class _ElementsDelta {
15225
15302
  static satisfiesCommmonInvariants = ({
15226
15303
  deleted,
15227
15304
  inserted
15228
- }) => !!(deleted.version && inserted.version && // versions are required integers
15229
- Number.isInteger(deleted.version) && Number.isInteger(inserted.version) && // versions should be positive, zero included
15305
+ }) => !!// versions are required integers
15306
+ (Number.isInteger(deleted.version) && Number.isInteger(inserted.version) && // versions should be positive, zero included
15230
15307
  deleted.version >= 0 && inserted.version >= 0 && // versions should never be the same
15231
15308
  deleted.version !== inserted.version);
15309
+ static satisfiesUniqueInvariants = (elementsDelta, id) => {
15310
+ const { added, removed, updated } = elementsDelta;
15311
+ return [added[id], removed[id], updated[id]].filter(Boolean).length === 1;
15312
+ };
15232
15313
  static validate(elementsDelta, type, satifiesSpecialInvariants) {
15233
15314
  for (const [id, delta] of Object.entries(elementsDelta[type])) {
15234
- if (!this.satisfiesCommmonInvariants(delta) || !satifiesSpecialInvariants(delta)) {
15315
+ if (!this.satisfiesCommmonInvariants(delta) || !this.satisfiesUniqueInvariants(elementsDelta, id) || !satifiesSpecialInvariants(delta)) {
15235
15316
  console.error(
15236
15317
  `Broken invariant for "${type}" delta, element "${id}", delta:`,
15237
15318
  delta
@@ -15258,7 +15339,7 @@ var ElementsDelta = class _ElementsDelta {
15258
15339
  for (const prevElement of prevElements.values()) {
15259
15340
  const nextElement = nextElements.get(prevElement.id);
15260
15341
  if (!nextElement) {
15261
- const deleted = { ...prevElement, isDeleted: false };
15342
+ const deleted = { ...prevElement };
15262
15343
  const inserted = {
15263
15344
  isDeleted: true,
15264
15345
  version: prevElement.version + 1,
@@ -15269,7 +15350,11 @@ var ElementsDelta = class _ElementsDelta {
15269
15350
  inserted,
15270
15351
  _ElementsDelta.stripIrrelevantProps
15271
15352
  );
15272
- removed[prevElement.id] = delta;
15353
+ if (!prevElement.isDeleted) {
15354
+ removed[prevElement.id] = delta;
15355
+ } else {
15356
+ updated[prevElement.id] = delta;
15357
+ }
15273
15358
  }
15274
15359
  }
15275
15360
  for (const nextElement of nextElements.values()) {
@@ -15281,15 +15366,18 @@ var ElementsDelta = class _ElementsDelta {
15281
15366
  versionNonce: randomInteger4()
15282
15367
  };
15283
15368
  const inserted = {
15284
- ...nextElement,
15285
- isDeleted: false
15369
+ ...nextElement
15286
15370
  };
15287
15371
  const delta = Delta.create(
15288
15372
  deleted,
15289
15373
  inserted,
15290
15374
  _ElementsDelta.stripIrrelevantProps
15291
15375
  );
15292
- added[nextElement.id] = delta;
15376
+ if (!nextElement.isDeleted) {
15377
+ added[nextElement.id] = delta;
15378
+ } else {
15379
+ updated[nextElement.id] = delta;
15380
+ }
15293
15381
  continue;
15294
15382
  }
15295
15383
  if (prevElement.versionNonce !== nextElement.versionNonce) {
@@ -15310,9 +15398,7 @@ var ElementsDelta = class _ElementsDelta {
15310
15398
  }
15311
15399
  continue;
15312
15400
  }
15313
- if (!Delta.isEmpty(delta)) {
15314
- updated[nextElement.id] = delta;
15315
- }
15401
+ updated[nextElement.id] = delta;
15316
15402
  }
15317
15403
  }
15318
15404
  return _ElementsDelta.create(added, removed, updated);
@@ -15402,26 +15488,30 @@ var ElementsDelta = class _ElementsDelta {
15402
15488
  // redistribute the deltas as `isDeleted` could have been updated
15403
15489
  });
15404
15490
  }
15405
- applyTo(elements, snapshot = StoreSnapshot.empty().elements, options = {
15406
- excludedProperties: /* @__PURE__ */ new Set()
15407
- }) {
15491
+ applyTo(elements, snapshot = StoreSnapshot.empty().elements, options) {
15408
15492
  let nextElements = new Map(elements);
15409
15493
  let changedElements;
15410
15494
  const flags = {
15411
15495
  containsVisibleDifference: false,
15412
- containsZindexDifference: false
15496
+ containsZindexDifference: false,
15497
+ applyDirection: void 0
15413
15498
  };
15414
15499
  try {
15415
15500
  const applyDeltas = _ElementsDelta.createApplier(
15501
+ elements,
15416
15502
  nextElements,
15417
15503
  snapshot,
15418
- options,
15419
- flags
15504
+ flags,
15505
+ options
15420
15506
  );
15421
15507
  const addedElements = applyDeltas(this.added);
15422
15508
  const removedElements = applyDeltas(this.removed);
15423
15509
  const updatedElements = applyDeltas(this.updated);
15424
- const affectedElements = this.resolveConflicts(elements, nextElements);
15510
+ const affectedElements = this.resolveConflicts(
15511
+ elements,
15512
+ nextElements,
15513
+ flags.applyDirection
15514
+ );
15425
15515
  changedElements = new Map([
15426
15516
  ...addedElements,
15427
15517
  ...removedElements,
@@ -15441,9 +15531,7 @@ var ElementsDelta = class _ElementsDelta {
15441
15531
  changedElements,
15442
15532
  flags
15443
15533
  );
15444
- const tempScene = new Scene(nextElements);
15445
- _ElementsDelta.redrawTextBoundingBoxes(tempScene, changedElements);
15446
- _ElementsDelta.redrawBoundArrows(tempScene, changedElements);
15534
+ _ElementsDelta.redrawElements(nextElements, changedElements);
15447
15535
  } catch (e) {
15448
15536
  console.error(
15449
15537
  `Couldn't mutate elements after applying elements change`,
@@ -15457,34 +15545,81 @@ var ElementsDelta = class _ElementsDelta {
15457
15545
  }
15458
15546
  }
15459
15547
  squash(delta) {
15548
+ if (delta.isEmpty()) {
15549
+ return this;
15550
+ }
15460
15551
  const { added, removed, updated } = delta;
15552
+ const mergeBoundElements = (prevDelta, nextDelta) => {
15553
+ const mergedDeletedBoundElements = Delta.mergeArrays(
15554
+ prevDelta.deleted.boundElements ?? [],
15555
+ nextDelta.deleted.boundElements ?? [],
15556
+ void 0,
15557
+ (x) => x.id
15558
+ ) ?? [];
15559
+ const mergedInsertedBoundElements = Delta.mergeArrays(
15560
+ prevDelta.inserted.boundElements ?? [],
15561
+ nextDelta.inserted.boundElements ?? [],
15562
+ void 0,
15563
+ (x) => x.id
15564
+ ) ?? [];
15565
+ if (!mergedDeletedBoundElements.length && !mergedInsertedBoundElements.length) {
15566
+ return;
15567
+ }
15568
+ return Delta.create(
15569
+ {
15570
+ boundElements: mergedDeletedBoundElements
15571
+ },
15572
+ {
15573
+ boundElements: mergedInsertedBoundElements
15574
+ }
15575
+ );
15576
+ };
15461
15577
  for (const [id, nextDelta] of Object.entries(added)) {
15462
- const prevDelta = this.added[id];
15578
+ const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];
15463
15579
  if (!prevDelta) {
15464
15580
  this.added[id] = nextDelta;
15465
15581
  } else {
15466
- this.added[id] = Delta.merge(prevDelta, nextDelta);
15582
+ const mergedDelta = mergeBoundElements(prevDelta, nextDelta);
15583
+ delete this.removed[id];
15584
+ delete this.updated[id];
15585
+ this.added[id] = Delta.merge(prevDelta, nextDelta, mergedDelta);
15467
15586
  }
15468
15587
  }
15469
15588
  for (const [id, nextDelta] of Object.entries(removed)) {
15470
- const prevDelta = this.removed[id];
15589
+ const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];
15471
15590
  if (!prevDelta) {
15472
15591
  this.removed[id] = nextDelta;
15473
15592
  } else {
15474
- this.removed[id] = Delta.merge(prevDelta, nextDelta);
15593
+ const mergedDelta = mergeBoundElements(prevDelta, nextDelta);
15594
+ delete this.added[id];
15595
+ delete this.updated[id];
15596
+ this.removed[id] = Delta.merge(prevDelta, nextDelta, mergedDelta);
15475
15597
  }
15476
15598
  }
15477
15599
  for (const [id, nextDelta] of Object.entries(updated)) {
15478
- const prevDelta = this.updated[id];
15600
+ const prevDelta = this.added[id] ?? this.removed[id] ?? this.updated[id];
15479
15601
  if (!prevDelta) {
15480
15602
  this.updated[id] = nextDelta;
15481
15603
  } else {
15482
- this.updated[id] = Delta.merge(prevDelta, nextDelta);
15604
+ const mergedDelta = mergeBoundElements(prevDelta, nextDelta);
15605
+ const updatedDelta = Delta.merge(prevDelta, nextDelta, mergedDelta);
15606
+ if (prevDelta === this.added[id]) {
15607
+ this.added[id] = updatedDelta;
15608
+ } else if (prevDelta === this.removed[id]) {
15609
+ this.removed[id] = updatedDelta;
15610
+ } else {
15611
+ this.updated[id] = updatedDelta;
15612
+ }
15483
15613
  }
15484
15614
  }
15615
+ if (isTestEnv8() || isDevEnv7()) {
15616
+ _ElementsDelta.validate(this, "added", _ElementsDelta.satisfiesAddition);
15617
+ _ElementsDelta.validate(this, "removed", _ElementsDelta.satisfiesRemoval);
15618
+ _ElementsDelta.validate(this, "updated", _ElementsDelta.satisfiesUpdate);
15619
+ }
15485
15620
  return this;
15486
15621
  }
15487
- static createApplier = (nextElements, snapshot, options, flags) => (deltas) => {
15622
+ static createApplier = (prevElements, nextElements, snapshot, flags, options) => (deltas) => {
15488
15623
  const getElement = _ElementsDelta.createGetter(
15489
15624
  nextElements,
15490
15625
  snapshot,
@@ -15493,14 +15628,20 @@ var ElementsDelta = class _ElementsDelta {
15493
15628
  return Object.entries(deltas).reduce((acc, [id, delta]) => {
15494
15629
  const element = getElement(id, delta.inserted);
15495
15630
  if (element) {
15496
- const newElement2 = _ElementsDelta.applyDelta(
15631
+ const nextElement = _ElementsDelta.applyDelta(
15497
15632
  element,
15498
15633
  delta,
15499
- options,
15500
- flags
15634
+ flags,
15635
+ options
15501
15636
  );
15502
- nextElements.set(newElement2.id, newElement2);
15503
- acc.set(newElement2.id, newElement2);
15637
+ nextElements.set(nextElement.id, nextElement);
15638
+ acc.set(nextElement.id, nextElement);
15639
+ if (!flags.applyDirection) {
15640
+ const prevElement = prevElements.get(id);
15641
+ if (prevElement) {
15642
+ flags.applyDirection = prevElement.version > nextElement.version ? "backward" : "forward";
15643
+ }
15644
+ }
15504
15645
  }
15505
15646
  return acc;
15506
15647
  }, /* @__PURE__ */ new Map());
@@ -15525,13 +15666,13 @@ var ElementsDelta = class _ElementsDelta {
15525
15666
  }
15526
15667
  return element;
15527
15668
  };
15528
- static applyDelta(element, delta, options, flags) {
15669
+ static applyDelta(element, delta, flags, options) {
15529
15670
  const directlyApplicablePartial = {};
15530
15671
  for (const key of Object.keys(delta.inserted)) {
15531
15672
  if (key === "boundElements") {
15532
15673
  continue;
15533
15674
  }
15534
- if (options.excludedProperties.has(key)) {
15675
+ if (options?.excludedProperties?.has(key)) {
15535
15676
  continue;
15536
15677
  }
15537
15678
  const value = delta.inserted[key];
@@ -15559,7 +15700,7 @@ var ElementsDelta = class _ElementsDelta {
15559
15700
  if (!flags.containsZindexDifference) {
15560
15701
  flags.containsZindexDifference = delta.deleted.index !== delta.inserted.index;
15561
15702
  }
15562
- return newElementWith(element, directlyApplicablePartial);
15703
+ return newElementWith(element, directlyApplicablePartial, true);
15563
15704
  }
15564
15705
  /**
15565
15706
  * Check for visible changes regardless of whether they were removed, added or updated.
@@ -15584,25 +15725,32 @@ var ElementsDelta = class _ElementsDelta {
15584
15725
  *
15585
15726
  * @returns all elements affected by the conflict resolution
15586
15727
  */
15587
- resolveConflicts(prevElements, nextElements) {
15728
+ resolveConflicts(prevElements, nextElements, applyDirection = "forward") {
15588
15729
  const nextAffectedElements = /* @__PURE__ */ new Map();
15589
15730
  const updater = (element, updates) => {
15590
15731
  const nextElement = nextElements.get(element.id);
15591
15732
  if (!nextElement) {
15592
15733
  return;
15593
15734
  }
15735
+ const prevElement = prevElements.get(element.id);
15736
+ const nextVersion = applyDirection === "forward" ? nextElement.version + 1 : nextElement.version - 1;
15737
+ const elementUpdates = updates;
15594
15738
  let affectedElement;
15595
- if (prevElements.get(element.id) === nextElement) {
15739
+ if (prevElement === nextElement) {
15596
15740
  affectedElement = newElementWith(
15597
15741
  nextElement,
15598
- updates
15742
+ {
15743
+ ...elementUpdates,
15744
+ version: nextVersion
15745
+ },
15746
+ true
15599
15747
  );
15600
15748
  } else {
15601
- affectedElement = mutateElement(
15602
- nextElement,
15603
- nextElements,
15604
- updates
15605
- );
15749
+ affectedElement = mutateElement(nextElement, nextElements, {
15750
+ ...elementUpdates,
15751
+ // don't modify the version further, if it's already different
15752
+ version: prevElement?.version !== nextElement.version ? nextElement.version : nextVersion
15753
+ });
15606
15754
  }
15607
15755
  nextAffectedElements.set(affectedElement.id, affectedElement);
15608
15756
  nextElements.set(affectedElement.id, affectedElement);
@@ -15665,6 +15813,20 @@ var ElementsDelta = class _ElementsDelta {
15665
15813
  );
15666
15814
  BindableElement.rebindAffected(nextElements, nextElement(), updater);
15667
15815
  }
15816
+ static redrawElements(nextElements, changedElements) {
15817
+ try {
15818
+ const tempScene = new Scene(nextElements, { skipValidation: true });
15819
+ _ElementsDelta.redrawTextBoundingBoxes(tempScene, changedElements);
15820
+ _ElementsDelta.redrawBoundArrows(tempScene, changedElements);
15821
+ } catch (e) {
15822
+ console.error(`Couldn't redraw elements`, e);
15823
+ if (isTestEnv8() || isDevEnv7()) {
15824
+ throw e;
15825
+ }
15826
+ } finally {
15827
+ return nextElements;
15828
+ }
15829
+ }
15668
15830
  static redrawTextBoundingBoxes(scene, changed) {
15669
15831
  const elements = scene.getNonDeletedElementsMap();
15670
15832
  const boxesToRedraw = /* @__PURE__ */ new Map();