@excalidraw/element 0.18.0-b7aac689a → 0.18.0-c65b684e9

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 (41) hide show
  1. package/dist/dev/index.js +189 -82
  2. package/dist/dev/index.js.map +3 -3
  3. package/dist/prod/index.js +9 -9
  4. package/dist/types/common/src/constants.d.ts +1 -0
  5. package/dist/types/element/src/align.d.ts +2 -1
  6. package/dist/types/element/src/delta.d.ts +11 -1
  7. package/dist/types/element/src/distribute.d.ts +2 -1
  8. package/dist/types/element/src/groups.d.ts +1 -0
  9. package/dist/types/element/src/linearElementEditor.d.ts +2 -1
  10. package/dist/types/excalidraw/actions/actionAddToLibrary.d.ts +0 -3
  11. package/dist/types/excalidraw/actions/actionBoundText.d.ts +0 -2
  12. package/dist/types/excalidraw/actions/actionCanvas.d.ts +13 -13
  13. package/dist/types/excalidraw/actions/actionClipboard.d.ts +3 -8
  14. package/dist/types/excalidraw/actions/actionCropEditor.d.ts +0 -1
  15. package/dist/types/excalidraw/actions/actionDeleteSelected.d.ts +3 -6
  16. package/dist/types/excalidraw/actions/actionElementLink.d.ts +0 -1
  17. package/dist/types/excalidraw/actions/actionElementLock.d.ts +0 -2
  18. package/dist/types/excalidraw/actions/actionEmbeddable.d.ts +0 -1
  19. package/dist/types/excalidraw/actions/actionExport.d.ts +0 -9
  20. package/dist/types/excalidraw/actions/actionFinalize.d.ts +2 -3
  21. package/dist/types/excalidraw/actions/actionFrame.d.ts +0 -4
  22. package/dist/types/excalidraw/actions/actionGroup.d.ts +0 -2
  23. package/dist/types/excalidraw/actions/actionLinearEditor.d.ts +33 -3
  24. package/dist/types/excalidraw/actions/actionLink.d.ts +0 -1
  25. package/dist/types/excalidraw/actions/actionMenu.d.ts +0 -3
  26. package/dist/types/excalidraw/actions/actionNavigate.d.ts +0 -2
  27. package/dist/types/excalidraw/actions/actionProperties.d.ts +0 -15
  28. package/dist/types/excalidraw/actions/actionSelectAll.d.ts +0 -1
  29. package/dist/types/excalidraw/actions/actionStyles.d.ts +0 -1
  30. package/dist/types/excalidraw/actions/actionToggleGridMode.d.ts +0 -1
  31. package/dist/types/excalidraw/actions/actionToggleObjectsSnapMode.d.ts +0 -1
  32. package/dist/types/excalidraw/actions/actionToggleSearchMenu.d.ts +0 -1
  33. package/dist/types/excalidraw/actions/actionToggleStats.d.ts +0 -1
  34. package/dist/types/excalidraw/actions/actionToggleViewMode.d.ts +0 -1
  35. package/dist/types/excalidraw/actions/actionToggleZenMode.d.ts +0 -1
  36. package/dist/types/excalidraw/components/Actions.d.ts +0 -4
  37. package/dist/types/excalidraw/components/Ellipsify.d.ts +4 -0
  38. package/dist/types/excalidraw/index.d.ts +1 -0
  39. package/dist/types/excalidraw/renderer/staticScene.d.ts +4 -1
  40. package/dist/types/excalidraw/types.d.ts +1 -3
  41. 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) => {
@@ -12794,6 +12849,7 @@ import {
12794
12849
  arrayToMap as arrayToMap10,
12795
12850
  arrayToObject,
12796
12851
  assertNever as assertNever4,
12852
+ invariant as invariant8,
12797
12853
  isDevEnv as isDevEnv7,
12798
12854
  isShallowEqual as isShallowEqual2,
12799
12855
  isTestEnv as isTestEnv8,
@@ -13182,8 +13238,9 @@ var Store = class {
13182
13238
  constructor(app) {
13183
13239
  this.app = app;
13184
13240
  }
13185
- // internally used by history
13241
+ // for internal use by history
13186
13242
  onDurableIncrementEmitter = new Emitter();
13243
+ // for public use as part of onIncrement API
13187
13244
  onStoreIncrementEmitter = new Emitter();
13188
13245
  scheduledMacroActions = /* @__PURE__ */ new Set();
13189
13246
  scheduledMicroActions = [];
@@ -13759,8 +13816,8 @@ var getDefaultObservedAppState = () => {
13759
13816
  viewBackgroundColor: COLOR_PALETTE2.white,
13760
13817
  selectedElementIds: {},
13761
13818
  selectedGroupIds: {},
13762
- editingLinearElementId: null,
13763
13819
  selectedLinearElementId: null,
13820
+ selectedLinearElementIsEditing: null,
13764
13821
  croppingElementId: null,
13765
13822
  activeLockedId: null,
13766
13823
  lockedMultiSelections: {}
@@ -13776,10 +13833,8 @@ var getObservedAppState = (appState) => {
13776
13833
  croppingElementId: appState.croppingElementId,
13777
13834
  activeLockedId: appState.activeLockedId,
13778
13835
  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
13836
+ selectedLinearElementId: appState.selectedLinearElement?.elementId ?? appState.selectedLinearElementId ?? null,
13837
+ selectedLinearElementIsEditing: appState.selectedLinearElement?.isEditing ?? appState.selectedLinearElementIsEditing ?? null
13783
13838
  };
13784
13839
  Reflect.defineProperty(observedAppState, hiddenObservedAppStateProp, {
13785
13840
  value: true,
@@ -14583,6 +14638,15 @@ var Delta = class _Delta {
14583
14638
  static isEmpty(delta) {
14584
14639
  return !Object.keys(delta.deleted).length && !Object.keys(delta.inserted).length;
14585
14640
  }
14641
+ /**
14642
+ * Merges two deltas into a new one.
14643
+ */
14644
+ static merge(delta1, delta2) {
14645
+ return _Delta.create(
14646
+ { ...delta1.deleted, ...delta2.deleted },
14647
+ { ...delta1.inserted, ...delta2.inserted }
14648
+ );
14649
+ }
14586
14650
  /**
14587
14651
  * Merges deleted and inserted object partials.
14588
14652
  */
@@ -14828,6 +14892,10 @@ var AppStateDelta = class _AppStateDelta {
14828
14892
  const inversedDelta = Delta.create(this.delta.inserted, this.delta.deleted);
14829
14893
  return new _AppStateDelta(inversedDelta);
14830
14894
  }
14895
+ squash(delta) {
14896
+ this.delta = Delta.merge(this.delta, delta.delta);
14897
+ return this;
14898
+ }
14831
14899
  applyTo(appState, nextElements) {
14832
14900
  try {
14833
14901
  const {
@@ -14838,7 +14906,7 @@ var AppStateDelta = class _AppStateDelta {
14838
14906
  selectedElementIds: addedSelectedElementIds = {},
14839
14907
  selectedGroupIds: addedSelectedGroupIds = {},
14840
14908
  selectedLinearElementId,
14841
- editingLinearElementId,
14909
+ selectedLinearElementIsEditing,
14842
14910
  ...directlyApplicablePartial
14843
14911
  } = this.delta.inserted;
14844
14912
  const mergedSelectedElementIds = Delta.mergeObjects(
@@ -14851,27 +14919,39 @@ var AppStateDelta = class _AppStateDelta {
14851
14919
  addedSelectedGroupIds,
14852
14920
  removedSelectedGroupIds
14853
14921
  );
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(
14861
- nextElements.get(
14862
- editingLinearElementId
14863
- ),
14864
- nextElements
14865
- ) : null;
14922
+ let selectedLinearElement = appState.selectedLinearElement;
14923
+ if (selectedLinearElementId === null) {
14924
+ selectedLinearElement = null;
14925
+ } else if (selectedLinearElementId && nextElements.has(selectedLinearElementId)) {
14926
+ selectedLinearElement = new LinearElementEditor(
14927
+ nextElements.get(
14928
+ selectedLinearElementId
14929
+ ),
14930
+ nextElements,
14931
+ selectedLinearElementIsEditing === true
14932
+ // Can be unknown which is defaulted to false
14933
+ );
14934
+ }
14935
+ if (
14936
+ // Value being 'null' is equivaluent to unknown in this case because it only gets set
14937
+ // to null when 'selectedLinearElementId' is set to null
14938
+ selectedLinearElementIsEditing != null
14939
+ ) {
14940
+ invariant8(
14941
+ selectedLinearElement,
14942
+ `selectedLinearElement is null when selectedLinearElementIsEditing is set to ${selectedLinearElementIsEditing}`
14943
+ );
14944
+ selectedLinearElement = {
14945
+ ...selectedLinearElement,
14946
+ isEditing: selectedLinearElementIsEditing
14947
+ };
14948
+ }
14866
14949
  const nextAppState = {
14867
14950
  ...appState,
14868
14951
  ...directlyApplicablePartial,
14869
14952
  selectedElementIds: mergedSelectedElementIds,
14870
14953
  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
14954
+ selectedLinearElement
14875
14955
  };
14876
14956
  const constainsVisibleChanges = this.filterInvisibleChanges(
14877
14957
  appState,
@@ -14961,8 +15041,7 @@ var AppStateDelta = class _AppStateDelta {
14961
15041
  nextAppState[key] = null;
14962
15042
  }
14963
15043
  break;
14964
- case "selectedLinearElementId":
14965
- case "editingLinearElementId":
15044
+ case "selectedLinearElementId": {
14966
15045
  const appStateKey = _AppStateDelta.convertToAppStateKey(key);
14967
15046
  const linearElement = nextAppState[appStateKey];
14968
15047
  if (!linearElement) {
@@ -14976,6 +15055,15 @@ var AppStateDelta = class _AppStateDelta {
14976
15055
  }
14977
15056
  }
14978
15057
  break;
15058
+ }
15059
+ case "selectedLinearElementIsEditing": {
15060
+ const prevIsEditing = prevAppState.selectedLinearElement?.isEditing ?? false;
15061
+ const nextIsEditing = nextAppState.selectedLinearElement?.isEditing ?? false;
15062
+ if (prevIsEditing !== nextIsEditing) {
15063
+ visibleDifferenceFlag.value = true;
15064
+ }
15065
+ break;
15066
+ }
14979
15067
  case "lockedMultiSelections": {
14980
15068
  const prevLockedUnits = prevAppState[key] || {};
14981
15069
  const nextLockedUnits = nextAppState[key] || {};
@@ -15008,8 +15096,6 @@ var AppStateDelta = class _AppStateDelta {
15008
15096
  switch (key) {
15009
15097
  case "selectedLinearElementId":
15010
15098
  return "selectedLinearElement";
15011
- case "editingLinearElementId":
15012
- return "editingLinearElement";
15013
15099
  }
15014
15100
  }
15015
15101
  static filterSelectedElements(selectedElementIds, elements, visibleDifferenceFlag) {
@@ -15050,8 +15136,8 @@ var AppStateDelta = class _AppStateDelta {
15050
15136
  editingGroupId,
15051
15137
  selectedGroupIds,
15052
15138
  selectedElementIds,
15053
- editingLinearElementId,
15054
15139
  selectedLinearElementId,
15140
+ selectedLinearElementIsEditing,
15055
15141
  croppingElementId,
15056
15142
  lockedMultiSelections,
15057
15143
  activeLockedId,
@@ -15270,8 +15356,8 @@ var ElementsDelta = class _ElementsDelta {
15270
15356
  inverse() {
15271
15357
  const inverseInternal = (deltas) => {
15272
15358
  const inversedDeltas = {};
15273
- for (const [id, delta] of Object.entries(deltas)) {
15274
- inversedDeltas[id] = Delta.create(delta.inserted, delta.deleted);
15359
+ for (const [id, { inserted, deleted }] of Object.entries(deltas)) {
15360
+ inversedDeltas[id] = Delta.create({ ...inserted }, { ...deleted });
15275
15361
  }
15276
15362
  return inversedDeltas;
15277
15363
  };
@@ -15403,6 +15489,34 @@ var ElementsDelta = class _ElementsDelta {
15403
15489
  return [nextElements, flags.containsVisibleDifference];
15404
15490
  }
15405
15491
  }
15492
+ squash(delta) {
15493
+ const { added, removed, updated } = delta;
15494
+ for (const [id, nextDelta] of Object.entries(added)) {
15495
+ const prevDelta = this.added[id];
15496
+ if (!prevDelta) {
15497
+ this.added[id] = nextDelta;
15498
+ } else {
15499
+ this.added[id] = Delta.merge(prevDelta, nextDelta);
15500
+ }
15501
+ }
15502
+ for (const [id, nextDelta] of Object.entries(removed)) {
15503
+ const prevDelta = this.removed[id];
15504
+ if (!prevDelta) {
15505
+ this.removed[id] = nextDelta;
15506
+ } else {
15507
+ this.removed[id] = Delta.merge(prevDelta, nextDelta);
15508
+ }
15509
+ }
15510
+ for (const [id, nextDelta] of Object.entries(updated)) {
15511
+ const prevDelta = this.updated[id];
15512
+ if (!prevDelta) {
15513
+ this.updated[id] = nextDelta;
15514
+ } else {
15515
+ this.updated[id] = Delta.merge(prevDelta, nextDelta);
15516
+ }
15517
+ }
15518
+ return this;
15519
+ }
15406
15520
  static createApplier = (nextElements, snapshot, options, flags) => (deltas) => {
15407
15521
  const getElement = _ElementsDelta.createGetter(
15408
15522
  nextElements,
@@ -15546,19 +15660,10 @@ var ElementsDelta = class _ElementsDelta {
15546
15660
  const prevAffectedElements = new Map(
15547
15661
  Array.from(prevElements).filter(([id]) => nextAffectedElements.has(id))
15548
15662
  );
15549
- const { added, removed, updated } = _ElementsDelta.calculate(
15550
- prevAffectedElements,
15551
- nextAffectedElements
15663
+ this.squash(
15664
+ // technically we could do better here if perf. would become an issue
15665
+ _ElementsDelta.calculate(prevAffectedElements, nextAffectedElements)
15552
15666
  );
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
15667
  return nextAffectedElements;
15563
15668
  }
15564
15669
  /**
@@ -15622,9 +15727,6 @@ var ElementsDelta = class _ElementsDelta {
15622
15727
  if (container.isDeleted || boundText.isDeleted) {
15623
15728
  continue;
15624
15729
  }
15625
- if (!boundText.text) {
15626
- continue;
15627
- }
15628
15730
  redrawTextBoundingBox(boundText, container, scene);
15629
15731
  }
15630
15732
  }
@@ -15688,10 +15790,14 @@ var ElementsDelta = class _ElementsDelta {
15688
15790
 
15689
15791
  // src/distribute.ts
15690
15792
  init_define_import_meta_env();
15691
- var distributeElements = (selectedElements, elementsMap, distribution) => {
15793
+ var distributeElements = (selectedElements, elementsMap, distribution, appState) => {
15692
15794
  const [start, mid, end, extent] = distribution.axis === "x" ? ["minX", "midX", "maxX", "width"] : ["minY", "midY", "maxY", "height"];
15693
15795
  const bounds = getCommonBoundingBox(selectedElements);
15694
- const groups = getMaximumGroups(selectedElements, elementsMap).map((group) => [group, getCommonBoundingBox(group)]).sort((a2, b2) => a2[1][mid] - b2[1][mid]);
15796
+ const groups = getSelectedElementsByGroup(
15797
+ selectedElements,
15798
+ elementsMap,
15799
+ appState
15800
+ ).map((group) => [group, getCommonBoundingBox(group)]).sort((a2, b2) => a2[1][mid] - b2[1][mid]);
15695
15801
  let span = 0;
15696
15802
  for (const group of groups) {
15697
15803
  span += group[1][extent];
@@ -16683,7 +16789,7 @@ var embeddableURLValidator = (url, validateEmbeddable) => {
16683
16789
 
16684
16790
  // src/flowchart.ts
16685
16791
  init_define_import_meta_env();
16686
- import { KEYS as KEYS3, invariant as invariant8, toBrandedType as toBrandedType2 } from "@excalidraw/common";
16792
+ import { KEYS as KEYS3, invariant as invariant9, toBrandedType as toBrandedType2 } from "@excalidraw/common";
16687
16793
  import { pointFrom as pointFrom13 } from "@excalidraw/math";
16688
16794
  var VERTICAL_OFFSET = 100;
16689
16795
  var HORIZONTAL_OFFSET = 100;
@@ -16713,7 +16819,7 @@ var getNodeRelatives = (type, node, elementsMap, direction) => {
16713
16819
  if (!relative) {
16714
16820
  return acc;
16715
16821
  }
16716
- invariant8(
16822
+ invariant9(
16717
16823
  isBindableElement(relative),
16718
16824
  "not an ExcalidrawBindableElement"
16719
16825
  );
@@ -16829,7 +16935,7 @@ var addNewNode = (element, appState, direction, scene) => {
16829
16935
  fillStyle: element.fillStyle,
16830
16936
  strokeStyle: element.strokeStyle
16831
16937
  });
16832
- invariant8(
16938
+ invariant9(
16833
16939
  isFlowchartNodeElement(nextNode),
16834
16940
  "not an ExcalidrawFlowchartNodeElement"
16835
16941
  );
@@ -16887,7 +16993,7 @@ var addNewNodes = (startNode, appState, direction, scene, numberOfNodes) => {
16887
16993
  fillStyle: startNode.fillStyle,
16888
16994
  strokeStyle: startNode.strokeStyle
16889
16995
  });
16890
- invariant8(
16996
+ invariant9(
16891
16997
  isFlowchartNodeElement(nextNode),
16892
16998
  "not an ExcalidrawFlowchartNodeElement"
16893
16999
  );
@@ -17113,7 +17219,7 @@ var FlowChartCreator = class {
17113
17219
  }
17114
17220
  if (startNode.frameId) {
17115
17221
  const frame = elementsMap.get(startNode.frameId);
17116
- invariant8(
17222
+ invariant9(
17117
17223
  frame && isFrameElement(frame),
17118
17224
  "not an ExcalidrawFrameElement"
17119
17225
  );
@@ -18403,7 +18509,7 @@ var getTransformHandles = (element, zoom, elementsMap, pointerType = "mouse", om
18403
18509
  );
18404
18510
  };
18405
18511
  var shouldShowBoundingBox = (elements, appState) => {
18406
- if (appState.editingLinearElement) {
18512
+ if (appState.selectedLinearElement?.isEditing) {
18407
18513
  return false;
18408
18514
  }
18409
18515
  if (elements.length > 1) {
@@ -19151,6 +19257,7 @@ export {
19151
19257
  getRootElements,
19152
19258
  getSceneVersion,
19153
19259
  getSelectedElements,
19260
+ getSelectedElementsByGroup,
19154
19261
  getSelectedGroupForElement,
19155
19262
  getSelectedGroupIdForElement,
19156
19263
  getSelectedGroupIds,