@excalidraw/element 0.18.0-dda3affcb → 0.18.0-de715913e

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
@@ -13533,10 +13533,20 @@ var StoreDelta = class {
13533
13533
  */
13534
13534
  static load({
13535
13535
  id,
13536
- elements: { added, removed, updated }
13536
+ elements: { added, removed, updated },
13537
+ appState: { delta: appStateDelta }
13537
13538
  }) {
13538
13539
  const elements = ElementsDelta.create(added, removed, updated);
13539
- 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 delta into the current instance.
13545
+ */
13546
+ squash(delta) {
13547
+ this.elements.squash(delta.elements);
13548
+ this.appState.squash(delta.appState);
13549
+ return this;
13540
13550
  }
13541
13551
  /**
13542
13552
  * Inverse store delta, creates new instance of `StoreDelta`.
@@ -13547,9 +13557,7 @@ var StoreDelta = class {
13547
13557
  /**
13548
13558
  * Apply the delta to the passed elements and appState, does not modify the snapshot.
13549
13559
  */
13550
- static applyTo(delta, elements, appState, options = {
13551
- excludedProperties: /* @__PURE__ */ new Set()
13552
- }) {
13560
+ static applyTo(delta, elements, appState, options) {
13553
13561
  const [nextElements, elementsContainVisibleChange] = delta.elements.applyTo(
13554
13562
  elements,
13555
13563
  StoreSnapshot.empty().elements,
@@ -14398,9 +14406,9 @@ var Scene = class {
14398
14406
  getFramesIncludingDeleted() {
14399
14407
  return this.frames;
14400
14408
  }
14401
- constructor(elements = null) {
14409
+ constructor(elements = null, options) {
14402
14410
  if (elements) {
14403
- this.replaceAllElements(elements);
14411
+ this.replaceAllElements(elements, options);
14404
14412
  }
14405
14413
  }
14406
14414
  getSelectedElements(opts) {
@@ -14465,10 +14473,12 @@ var Scene = class {
14465
14473
  }
14466
14474
  return didChange;
14467
14475
  }
14468
- replaceAllElements(nextElements) {
14476
+ replaceAllElements(nextElements, options) {
14469
14477
  const _nextElements = toArray(nextElements);
14470
14478
  const nextFrameLikes = [];
14471
- validateIndicesThrottled(_nextElements);
14479
+ if (!options?.skipValidation) {
14480
+ validateIndicesThrottled(_nextElements);
14481
+ }
14472
14482
  this.elements = syncInvalidIndices2(_nextElements);
14473
14483
  this.elementsMap.clear();
14474
14484
  this.elements.forEach((element) => {
@@ -14641,10 +14651,10 @@ var Delta = class _Delta {
14641
14651
  /**
14642
14652
  * Merges two deltas into a new one.
14643
14653
  */
14644
- static merge(delta1, delta2) {
14654
+ static merge(delta1, delta2, delta3) {
14645
14655
  return _Delta.create(
14646
- { ...delta1.deleted, ...delta2.deleted },
14647
- { ...delta1.inserted, ...delta2.inserted }
14656
+ { ...delta1.deleted, ...delta2.deleted, ...delta3?.deleted ?? {} },
14657
+ { ...delta1.inserted, ...delta2.inserted, ...delta3?.inserted ?? {} }
14648
14658
  );
14649
14659
  }
14650
14660
  /**
@@ -14652,7 +14662,7 @@ var Delta = class _Delta {
14652
14662
  */
14653
14663
  static mergeObjects(prev, added, removed) {
14654
14664
  const cloned = { ...prev };
14655
- for (const key of Object.keys(removed)) {
14665
+ for (const key of Object.keys(removed ?? {})) {
14656
14666
  delete cloned[key];
14657
14667
  }
14658
14668
  return { ...cloned, ...added };
@@ -14871,6 +14881,9 @@ var AppStateDelta = class _AppStateDelta {
14871
14881
  constructor(delta) {
14872
14882
  this.delta = delta;
14873
14883
  }
14884
+ static create(delta) {
14885
+ return new _AppStateDelta(delta);
14886
+ }
14874
14887
  static calculate(prevAppState, nextAppState) {
14875
14888
  const delta = Delta.calculate(
14876
14889
  prevAppState,
@@ -14893,7 +14906,33 @@ var AppStateDelta = class _AppStateDelta {
14893
14906
  return new _AppStateDelta(inversedDelta);
14894
14907
  }
14895
14908
  squash(delta) {
14896
- this.delta = Delta.merge(this.delta, delta.delta);
14909
+ const mergedDeletedSelectedElementIds = Delta.mergeObjects(
14910
+ this.delta.deleted.selectedElementIds ?? {},
14911
+ delta.delta.deleted.selectedElementIds ?? {}
14912
+ );
14913
+ const mergedInsertedSelectedElementIds = Delta.mergeObjects(
14914
+ this.delta.inserted.selectedElementIds ?? {},
14915
+ delta.delta.inserted.selectedElementIds ?? {}
14916
+ );
14917
+ const mergedInsertedSelectedGroupIds = Delta.mergeObjects(
14918
+ this.delta.inserted.selectedGroupIds ?? {},
14919
+ delta.delta.inserted.selectedGroupIds ?? {}
14920
+ );
14921
+ const mergedDeletedSelectedGroupIds = Delta.mergeObjects(
14922
+ this.delta.deleted.selectedGroupIds ?? {},
14923
+ delta.delta.deleted.selectedGroupIds ?? {}
14924
+ );
14925
+ const mergedDelta = Delta.create(
14926
+ {
14927
+ selectedElementIds: mergedDeletedSelectedElementIds,
14928
+ selectedGroupIds: mergedDeletedSelectedGroupIds
14929
+ },
14930
+ {
14931
+ selectedElementIds: mergedInsertedSelectedElementIds,
14932
+ selectedGroupIds: mergedInsertedSelectedGroupIds
14933
+ }
14934
+ );
14935
+ this.delta = Delta.merge(this.delta, delta.delta, mergedDelta);
14897
14936
  return this;
14898
14937
  }
14899
14938
  applyTo(appState, nextElements) {
@@ -15407,26 +15446,30 @@ var ElementsDelta = class _ElementsDelta {
15407
15446
  // redistribute the deltas as `isDeleted` could have been updated
15408
15447
  });
15409
15448
  }
15410
- applyTo(elements, snapshot = StoreSnapshot.empty().elements, options = {
15411
- excludedProperties: /* @__PURE__ */ new Set()
15412
- }) {
15449
+ applyTo(elements, snapshot = StoreSnapshot.empty().elements, options) {
15413
15450
  let nextElements = new Map(elements);
15414
15451
  let changedElements;
15415
15452
  const flags = {
15416
15453
  containsVisibleDifference: false,
15417
- containsZindexDifference: false
15454
+ containsZindexDifference: false,
15455
+ applyDirection: void 0
15418
15456
  };
15419
15457
  try {
15420
15458
  const applyDeltas = _ElementsDelta.createApplier(
15459
+ elements,
15421
15460
  nextElements,
15422
15461
  snapshot,
15423
- options,
15424
- flags
15462
+ flags,
15463
+ options
15425
15464
  );
15426
15465
  const addedElements = applyDeltas(this.added);
15427
15466
  const removedElements = applyDeltas(this.removed);
15428
15467
  const updatedElements = applyDeltas(this.updated);
15429
- const affectedElements = this.resolveConflicts(elements, nextElements);
15468
+ const affectedElements = this.resolveConflicts(
15469
+ elements,
15470
+ nextElements,
15471
+ flags.applyDirection
15472
+ );
15430
15473
  changedElements = new Map([
15431
15474
  ...addedElements,
15432
15475
  ...removedElements,
@@ -15446,9 +15489,7 @@ var ElementsDelta = class _ElementsDelta {
15446
15489
  changedElements,
15447
15490
  flags
15448
15491
  );
15449
- const tempScene = new Scene(nextElements);
15450
- _ElementsDelta.redrawTextBoundingBoxes(tempScene, changedElements);
15451
- _ElementsDelta.redrawBoundArrows(tempScene, changedElements);
15492
+ _ElementsDelta.redrawElements(nextElements, changedElements);
15452
15493
  } catch (e) {
15453
15494
  console.error(
15454
15495
  `Couldn't mutate elements after applying elements change`,
@@ -15463,12 +15504,35 @@ var ElementsDelta = class _ElementsDelta {
15463
15504
  }
15464
15505
  squash(delta) {
15465
15506
  const { added, removed, updated } = delta;
15507
+ function mergeBoundElements(prevDelta, nextDelta) {
15508
+ const mergedDeletedBoundElements = Delta.mergeArrays(
15509
+ prevDelta.deleted.boundElements ?? [],
15510
+ nextDelta.deleted.boundElements ?? [],
15511
+ void 0,
15512
+ (x) => x.id
15513
+ ) ?? [];
15514
+ const mergedInsertedBoundElements = Delta.mergeArrays(
15515
+ prevDelta.inserted.boundElements ?? [],
15516
+ nextDelta.inserted.boundElements ?? [],
15517
+ void 0,
15518
+ (x) => x.id
15519
+ ) ?? [];
15520
+ return Delta.create(
15521
+ {
15522
+ boundElements: mergedDeletedBoundElements
15523
+ },
15524
+ {
15525
+ boundElements: mergedInsertedBoundElements
15526
+ }
15527
+ );
15528
+ }
15466
15529
  for (const [id, nextDelta] of Object.entries(added)) {
15467
15530
  const prevDelta = this.added[id];
15468
15531
  if (!prevDelta) {
15469
15532
  this.added[id] = nextDelta;
15470
15533
  } else {
15471
- this.added[id] = Delta.merge(prevDelta, nextDelta);
15534
+ const mergedDelta = mergeBoundElements(prevDelta, nextDelta);
15535
+ this.added[id] = Delta.merge(prevDelta, nextDelta, mergedDelta);
15472
15536
  }
15473
15537
  }
15474
15538
  for (const [id, nextDelta] of Object.entries(removed)) {
@@ -15476,7 +15540,8 @@ var ElementsDelta = class _ElementsDelta {
15476
15540
  if (!prevDelta) {
15477
15541
  this.removed[id] = nextDelta;
15478
15542
  } else {
15479
- this.removed[id] = Delta.merge(prevDelta, nextDelta);
15543
+ const mergedDelta = mergeBoundElements(prevDelta, nextDelta);
15544
+ this.removed[id] = Delta.merge(prevDelta, nextDelta, mergedDelta);
15480
15545
  }
15481
15546
  }
15482
15547
  for (const [id, nextDelta] of Object.entries(updated)) {
@@ -15484,12 +15549,13 @@ var ElementsDelta = class _ElementsDelta {
15484
15549
  if (!prevDelta) {
15485
15550
  this.updated[id] = nextDelta;
15486
15551
  } else {
15487
- this.updated[id] = Delta.merge(prevDelta, nextDelta);
15552
+ const mergedDelta = mergeBoundElements(prevDelta, nextDelta);
15553
+ this.updated[id] = Delta.merge(prevDelta, nextDelta, mergedDelta);
15488
15554
  }
15489
15555
  }
15490
15556
  return this;
15491
15557
  }
15492
- static createApplier = (nextElements, snapshot, options, flags) => (deltas) => {
15558
+ static createApplier = (prevElements, nextElements, snapshot, flags, options) => (deltas) => {
15493
15559
  const getElement = _ElementsDelta.createGetter(
15494
15560
  nextElements,
15495
15561
  snapshot,
@@ -15498,14 +15564,20 @@ var ElementsDelta = class _ElementsDelta {
15498
15564
  return Object.entries(deltas).reduce((acc, [id, delta]) => {
15499
15565
  const element = getElement(id, delta.inserted);
15500
15566
  if (element) {
15501
- const newElement2 = _ElementsDelta.applyDelta(
15567
+ const nextElement = _ElementsDelta.applyDelta(
15502
15568
  element,
15503
15569
  delta,
15504
- options,
15505
- flags
15570
+ flags,
15571
+ options
15506
15572
  );
15507
- nextElements.set(newElement2.id, newElement2);
15508
- acc.set(newElement2.id, newElement2);
15573
+ nextElements.set(nextElement.id, nextElement);
15574
+ acc.set(nextElement.id, nextElement);
15575
+ if (!flags.applyDirection) {
15576
+ const prevElement = prevElements.get(id);
15577
+ if (prevElement) {
15578
+ flags.applyDirection = prevElement.version > nextElement.version ? "backward" : "forward";
15579
+ }
15580
+ }
15509
15581
  }
15510
15582
  return acc;
15511
15583
  }, /* @__PURE__ */ new Map());
@@ -15530,13 +15602,13 @@ var ElementsDelta = class _ElementsDelta {
15530
15602
  }
15531
15603
  return element;
15532
15604
  };
15533
- static applyDelta(element, delta, options, flags) {
15605
+ static applyDelta(element, delta, flags, options) {
15534
15606
  const directlyApplicablePartial = {};
15535
15607
  for (const key of Object.keys(delta.inserted)) {
15536
15608
  if (key === "boundElements") {
15537
15609
  continue;
15538
15610
  }
15539
- if (options.excludedProperties.has(key)) {
15611
+ if (options?.excludedProperties?.has(key)) {
15540
15612
  continue;
15541
15613
  }
15542
15614
  const value = delta.inserted[key];
@@ -15564,7 +15636,7 @@ var ElementsDelta = class _ElementsDelta {
15564
15636
  if (!flags.containsZindexDifference) {
15565
15637
  flags.containsZindexDifference = delta.deleted.index !== delta.inserted.index;
15566
15638
  }
15567
- return newElementWith(element, directlyApplicablePartial);
15639
+ return newElementWith(element, directlyApplicablePartial, true);
15568
15640
  }
15569
15641
  /**
15570
15642
  * Check for visible changes regardless of whether they were removed, added or updated.
@@ -15589,25 +15661,32 @@ var ElementsDelta = class _ElementsDelta {
15589
15661
  *
15590
15662
  * @returns all elements affected by the conflict resolution
15591
15663
  */
15592
- resolveConflicts(prevElements, nextElements) {
15664
+ resolveConflicts(prevElements, nextElements, applyDirection = "forward") {
15593
15665
  const nextAffectedElements = /* @__PURE__ */ new Map();
15594
15666
  const updater = (element, updates) => {
15595
15667
  const nextElement = nextElements.get(element.id);
15596
15668
  if (!nextElement) {
15597
15669
  return;
15598
15670
  }
15671
+ const prevElement = prevElements.get(element.id);
15672
+ const nextVersion = applyDirection === "forward" ? nextElement.version + 1 : nextElement.version - 1;
15673
+ const elementUpdates = updates;
15599
15674
  let affectedElement;
15600
- if (prevElements.get(element.id) === nextElement) {
15675
+ if (prevElement === nextElement) {
15601
15676
  affectedElement = newElementWith(
15602
15677
  nextElement,
15603
- updates
15678
+ {
15679
+ ...elementUpdates,
15680
+ version: nextVersion
15681
+ },
15682
+ true
15604
15683
  );
15605
15684
  } else {
15606
- affectedElement = mutateElement(
15607
- nextElement,
15608
- nextElements,
15609
- updates
15610
- );
15685
+ affectedElement = mutateElement(nextElement, nextElements, {
15686
+ ...elementUpdates,
15687
+ // don't modify the version further, if it's already different
15688
+ version: prevElement?.version !== nextElement.version ? nextElement.version : nextVersion
15689
+ });
15611
15690
  }
15612
15691
  nextAffectedElements.set(affectedElement.id, affectedElement);
15613
15692
  nextElements.set(affectedElement.id, affectedElement);
@@ -15670,6 +15749,20 @@ var ElementsDelta = class _ElementsDelta {
15670
15749
  );
15671
15750
  BindableElement.rebindAffected(nextElements, nextElement(), updater);
15672
15751
  }
15752
+ static redrawElements(nextElements, changedElements) {
15753
+ try {
15754
+ const tempScene = new Scene(nextElements, { skipValidation: true });
15755
+ _ElementsDelta.redrawTextBoundingBoxes(tempScene, changedElements);
15756
+ _ElementsDelta.redrawBoundArrows(tempScene, changedElements);
15757
+ } catch (e) {
15758
+ console.error(`Couldn't redraw elements`, e);
15759
+ if (isTestEnv8() || isDevEnv7()) {
15760
+ throw e;
15761
+ }
15762
+ } finally {
15763
+ return nextElements;
15764
+ }
15765
+ }
15673
15766
  static redrawTextBoundingBoxes(scene, changed) {
15674
15767
  const elements = scene.getNonDeletedElementsMap();
15675
15768
  const boxesToRedraw = /* @__PURE__ */ new Map();