chore: release @excalidraw/excalidraw@18.0.0 🎉 (#9127)

This commit is contained in:
Marcel Mraz 2025-02-28 16:49:09 +01:00 committed by GitHub
parent 392118bf26
commit ecef5d12f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
232 changed files with 3412 additions and 2851 deletions

View file

@ -236,8 +236,8 @@ import {
getElementShape,
isPathALoop,
} from "../shapes";
import { getSelectionBoxShape } from "../../utils/geometry/shape";
import { isPointInShape } from "../../utils/collision";
import { getSelectionBoxShape } from "@excalidraw/utils/geometry/shape";
import { isPointInShape } from "@excalidraw/utils/collision";
import type {
AppClassProperties,
AppProps,
@ -412,7 +412,7 @@ import { COLOR_PALETTE } from "../colors";
import { ElementCanvasButton } from "./MagicButton";
import { MagicIcon, copyIcon, fullscreenIcon } from "./icons";
import FollowMode from "./FollowMode/FollowMode";
import { Store, StoreAction } from "../store";
import { Store, CaptureUpdateAction } from "../store";
import { AnimationFrameHandler } from "../animation-frame-handler";
import { AnimatedTrail } from "../animated-trail";
import { LaserTrails } from "../laser-trails";
@ -441,7 +441,7 @@ import {
getLinkDirectionFromKey,
} from "../element/flowchart";
import { searchItemInFocusAtom } from "./SearchMenu";
import type { LocalPoint, Radians } from "../../math";
import type { LocalPoint, Radians } from "@excalidraw/math";
import {
clamp,
pointFrom,
@ -453,7 +453,7 @@ import {
vectorSubtract,
vectorDot,
vectorNormalize,
} from "../../math";
} from "@excalidraw/math";
import { cropElement } from "../element/cropElement";
import { wrapText } from "../element/textWrapping";
import { actionCopyElementLink } from "../actions/actionElementLink";
@ -2097,12 +2097,12 @@ class App extends React.Component<AppProps, AppState> {
if (shouldUpdateStrokeColor) {
this.syncActionResult({
appState: { ...this.state, currentItemStrokeColor: color },
storeAction: StoreAction.CAPTURE,
captureUpdate: CaptureUpdateAction.IMMEDIATELY,
});
} else {
this.syncActionResult({
appState: { ...this.state, currentItemBackgroundColor: color },
storeAction: StoreAction.CAPTURE,
captureUpdate: CaptureUpdateAction.IMMEDIATELY,
});
}
} else {
@ -2116,7 +2116,7 @@ class App extends React.Component<AppProps, AppState> {
}
return el;
}),
storeAction: StoreAction.CAPTURE,
captureUpdate: CaptureUpdateAction.IMMEDIATELY,
});
}
},
@ -2137,9 +2137,9 @@ class App extends React.Component<AppProps, AppState> {
return;
}
if (actionResult.storeAction === StoreAction.UPDATE) {
if (actionResult.captureUpdate === CaptureUpdateAction.NEVER) {
this.store.shouldUpdateSnapshot();
} else if (actionResult.storeAction === StoreAction.CAPTURE) {
} else if (actionResult.captureUpdate === CaptureUpdateAction.IMMEDIATELY) {
this.store.shouldCaptureIncrement();
}
@ -2214,7 +2214,10 @@ class App extends React.Component<AppProps, AppState> {
didUpdate = true;
}
if (!didUpdate && actionResult.storeAction !== StoreAction.NONE) {
if (
!didUpdate &&
actionResult.captureUpdate !== CaptureUpdateAction.EVENTUALLY
) {
this.scene.triggerUpdate();
}
});
@ -2342,7 +2345,7 @@ class App extends React.Component<AppProps, AppState> {
this.resetHistory();
this.syncActionResult({
...scene,
storeAction: StoreAction.UPDATE,
captureUpdate: CaptureUpdateAction.NEVER,
});
// clear the shape and image cache so that any images in initialData
@ -2822,7 +2825,7 @@ class App extends React.Component<AppProps, AppState> {
this.state.editingLinearElement &&
!this.state.selectedElementIds[this.state.editingLinearElement.elementId]
) {
// defer so that the storeAction flag isn't reset via current update
// defer so that the shouldCaptureIncrement flag isn't reset via current update
setTimeout(() => {
// execute only if the condition still holds when the deferred callback
// executes (it can be scheduled multiple times depending on how
@ -3883,12 +3886,25 @@ class App extends React.Component<AppProps, AppState> {
elements?: SceneData["elements"];
appState?: Pick<AppState, K> | null;
collaborators?: SceneData["collaborators"];
/** @default StoreAction.NONE */
storeAction?: SceneData["storeAction"];
/**
* Controls which updates should be captured by the `Store`. Captured updates are emmitted and listened to by other components, such as `History` for undo / redo purposes.
*
* - `CaptureUpdateAction.IMMEDIATELY`: Updates are immediately undoable. Use for most local updates.
* - `CaptureUpdateAction.NEVER`: Updates never make it to undo/redo stack. Use for remote updates or scene initialization.
* - `CaptureUpdateAction.EVENTUALLY`: Updates will be eventually be captured as part of a future increment.
*
* Check [API docs](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/excalidraw-api#captureUpdate) for more details.
*
* @default CaptureUpdateAction.EVENTUALLY
*/
captureUpdate?: SceneData["captureUpdate"];
}) => {
const nextElements = syncInvalidIndices(sceneData.elements ?? []);
if (sceneData.storeAction && sceneData.storeAction !== StoreAction.NONE) {
if (
sceneData.captureUpdate &&
sceneData.captureUpdate !== CaptureUpdateAction.EVENTUALLY
) {
const prevCommittedAppState = this.store.snapshot.appState;
const prevCommittedElements = this.store.snapshot.elements;
@ -3905,12 +3921,12 @@ class App extends React.Component<AppProps, AppState> {
// WARN: store action always performs deep clone of changed elements, for ephemeral remote updates (i.e. remote dragging, resizing, drawing) we might consider doing something smarter
// do NOT schedule store actions (execute after re-render), as it might cause unexpected concurrency issues if not handled well
if (sceneData.storeAction === StoreAction.CAPTURE) {
if (sceneData.captureUpdate === CaptureUpdateAction.IMMEDIATELY) {
this.store.captureIncrement(
nextCommittedElements,
nextCommittedAppState,
);
} else if (sceneData.storeAction === StoreAction.UPDATE) {
} else if (sceneData.captureUpdate === CaptureUpdateAction.NEVER) {
this.store.updateSnapshot(
nextCommittedElements,
nextCommittedAppState,
@ -4590,7 +4606,9 @@ class App extends React.Component<AppProps, AppState> {
if (!event.altKey) {
if (this.flowChartNavigator.isExploring) {
this.flowChartNavigator.clear();
this.syncActionResult({ storeAction: StoreAction.CAPTURE });
this.syncActionResult({
captureUpdate: CaptureUpdateAction.IMMEDIATELY,
});
}
}
@ -4637,7 +4655,9 @@ class App extends React.Component<AppProps, AppState> {
}
this.flowChartCreator.clear();
this.syncActionResult({ storeAction: StoreAction.CAPTURE });
this.syncActionResult({
captureUpdate: CaptureUpdateAction.IMMEDIATELY,
});
}
}
});
@ -6376,10 +6396,10 @@ class App extends React.Component<AppProps, AppState> {
this.state,
),
},
storeAction:
captureUpdate:
this.state.openDialog?.name === "elementLinkSelector"
? StoreAction.NONE
: StoreAction.UPDATE,
? CaptureUpdateAction.EVENTUALLY
: CaptureUpdateAction.NEVER,
});
return;
}
@ -9042,7 +9062,7 @@ class App extends React.Component<AppProps, AppState> {
appState: {
newElement: null,
},
storeAction: StoreAction.UPDATE,
captureUpdate: CaptureUpdateAction.NEVER,
});
return;
@ -9212,7 +9232,7 @@ class App extends React.Component<AppProps, AppState> {
elements: this.scene
.getElementsIncludingDeleted()
.filter((el) => el.id !== resizingElement.id),
storeAction: StoreAction.UPDATE,
captureUpdate: CaptureUpdateAction.NEVER,
});
}
@ -10183,7 +10203,7 @@ class App extends React.Component<AppProps, AppState> {
isLoading: false,
},
replaceFiles: true,
storeAction: StoreAction.CAPTURE,
captureUpdate: CaptureUpdateAction.IMMEDIATELY,
});
return;
} catch (error: any) {
@ -10312,7 +10332,7 @@ class App extends React.Component<AppProps, AppState> {
isLoading: false,
},
replaceFiles: true,
storeAction: StoreAction.CAPTURE,
captureUpdate: CaptureUpdateAction.IMMEDIATELY,
});
} else if (ret.type === MIME_TYPES.excalidrawlib) {
await this.library