mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
chore: release @excalidraw/excalidraw@18.0.0 🎉 (#9127)
This commit is contained in:
parent
392118bf26
commit
ecef5d12f4
232 changed files with 3412 additions and 2851 deletions
|
@ -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
|
||||
|
|
|
@ -23,7 +23,7 @@ import { nativeFileSystemSupported } from "../data/filesystem";
|
|||
import type { NonDeletedExcalidrawElement } from "../element/types";
|
||||
import { t } from "../i18n";
|
||||
import { isSomeElementSelected } from "../scene";
|
||||
import { exportToCanvas } from "../../utils/export";
|
||||
import { exportToCanvas } from "@excalidraw/utils/export";
|
||||
|
||||
import { copyIcon, downloadIcon, helpIcon } from "./icons";
|
||||
import { Dialog } from "./Dialog";
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
import clsx from "clsx";
|
||||
import React from "react";
|
||||
import type { ActionManager } from "../actions/manager";
|
||||
import {
|
||||
CLASSES,
|
||||
DEFAULT_SIDEBAR,
|
||||
LIBRARY_SIDEBAR_WIDTH,
|
||||
TOOL_TYPE,
|
||||
} from "../constants";
|
||||
import { CLASSES, DEFAULT_SIDEBAR, TOOL_TYPE } from "../constants";
|
||||
import { showSelectedShapeActions } from "../element";
|
||||
import type { NonDeletedExcalidrawElement } from "../element/types";
|
||||
import type { Language } from "../i18n";
|
||||
|
@ -531,7 +526,7 @@ const LayerUI = ({
|
|||
appState.openSidebar &&
|
||||
isSidebarDocked &&
|
||||
device.editor.canFitSidebar
|
||||
? { width: `calc(100% - ${LIBRARY_SIDEBAR_WIDTH}px)` }
|
||||
? { width: `calc(100% - var(--right-sidebar-width)px)` }
|
||||
: {}
|
||||
}
|
||||
>
|
||||
|
|
|
@ -7,7 +7,7 @@ import { t } from "../i18n";
|
|||
import Trans from "./Trans";
|
||||
|
||||
import type { LibraryItems, LibraryItem, UIAppState } from "../types";
|
||||
import { exportToCanvas, exportToSvg } from "../../utils/export";
|
||||
import { exportToCanvas, exportToSvg } from "@excalidraw/utils/export";
|
||||
import {
|
||||
EDITOR_LS_KEYS,
|
||||
EXPORT_DATA_TYPES,
|
||||
|
|
|
@ -3,7 +3,7 @@ import { collapseDownIcon, upIcon, searchIcon } from "./icons";
|
|||
import { TextField } from "./TextField";
|
||||
import { Button } from "./Button";
|
||||
import { useApp, useExcalidrawSetAppState } from "./App";
|
||||
import { debounce } from "lodash";
|
||||
import debounce from "lodash.debounce";
|
||||
import type { AppClassProperties } from "../types";
|
||||
import { isTextElement, newTextElement } from "../element";
|
||||
import type { ExcalidrawTextElement } from "../element/types";
|
||||
|
@ -18,7 +18,7 @@ import { CLASSES, EVENT } from "../constants";
|
|||
import { useStable } from "../hooks/useStable";
|
||||
|
||||
import "./SearchMenu.scss";
|
||||
import { round } from "../../math";
|
||||
import { round } from "@excalidraw/math";
|
||||
import { measureText } from "../element/textMeasurements";
|
||||
|
||||
const searchQueryAtom = atom<string>("");
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
overflow: hidden;
|
||||
border-radius: 0;
|
||||
width: calc(#{$right-sidebar-width} - var(--space-factor) * 2);
|
||||
width: calc(var(--right-sidebar-width) - var(--space-factor) * 2);
|
||||
|
||||
border-left: 1px solid var(--sidebar-border-color);
|
||||
|
||||
|
|
|
@ -136,6 +136,9 @@ export const SidebarInner = forwardRef(
|
|||
<Island
|
||||
{...rest}
|
||||
className={clsx("sidebar", { "sidebar--docked": docked }, className)}
|
||||
style={{
|
||||
"--right-sidebar-width": "302px",
|
||||
}}
|
||||
ref={islandRef}
|
||||
>
|
||||
<SidebarPropsContext.Provider value={headerPropsRef.current}>
|
||||
|
|
|
@ -8,8 +8,8 @@ import type { DragInputCallbackType } from "./DragInput";
|
|||
import { getStepSizedValue, isPropertyEditable, updateBindings } from "./utils";
|
||||
import type Scene from "../../scene/Scene";
|
||||
import type { AppState } from "../../types";
|
||||
import type { Degrees } from "../../../math";
|
||||
import { degreesToRadians, radiansToDegrees } from "../../../math";
|
||||
import type { Degrees } from "@excalidraw/math";
|
||||
import { degreesToRadians, radiansToDegrees } from "@excalidraw/math";
|
||||
|
||||
interface AngleProps {
|
||||
element: ExcalidrawElement;
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
getUncroppedWidthAndHeight,
|
||||
} from "../../element/cropElement";
|
||||
import { mutateElement } from "../../element/mutateElement";
|
||||
import { clamp, round } from "../../../math";
|
||||
import { clamp, round } from "@excalidraw/math";
|
||||
|
||||
interface DimensionDragInputProps {
|
||||
property: "width" | "height";
|
||||
|
|
|
@ -8,7 +8,7 @@ import { useApp } from "../App";
|
|||
import { InlineIcon } from "../InlineIcon";
|
||||
import type { StatsInputProperty } from "./utils";
|
||||
import { SMALLEST_DELTA } from "./utils";
|
||||
import { StoreAction } from "../../store";
|
||||
import { CaptureUpdateAction } from "../../store";
|
||||
import type Scene from "../../scene/Scene";
|
||||
|
||||
import "./DragInput.scss";
|
||||
|
@ -132,7 +132,9 @@ const StatsDragInput = <
|
|||
originalAppState: appState,
|
||||
setInputValue: (value) => setInputValue(String(value)),
|
||||
});
|
||||
app.syncActionResult({ storeAction: StoreAction.CAPTURE });
|
||||
app.syncActionResult({
|
||||
captureUpdate: CaptureUpdateAction.IMMEDIATELY,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -276,7 +278,9 @@ const StatsDragInput = <
|
|||
false,
|
||||
);
|
||||
|
||||
app.syncActionResult({ storeAction: StoreAction.CAPTURE });
|
||||
app.syncActionResult({
|
||||
captureUpdate: CaptureUpdateAction.IMMEDIATELY,
|
||||
});
|
||||
|
||||
lastPointer = null;
|
||||
accumulatedChange = 0;
|
||||
|
|
|
@ -9,8 +9,8 @@ import DragInput from "./DragInput";
|
|||
import type { DragInputCallbackType } from "./DragInput";
|
||||
import { getStepSizedValue, isPropertyEditable } from "./utils";
|
||||
import type { AppState } from "../../types";
|
||||
import type { Degrees } from "../../../math";
|
||||
import { degreesToRadians, radiansToDegrees } from "../../../math";
|
||||
import type { Degrees } from "@excalidraw/math";
|
||||
import { degreesToRadians, radiansToDegrees } from "@excalidraw/math";
|
||||
|
||||
interface MultiAngleProps {
|
||||
elements: readonly ExcalidrawElement[];
|
||||
|
|
|
@ -23,7 +23,7 @@ import { getAtomicUnits, getStepSizedValue, isPropertyEditable } from "./utils";
|
|||
import { getElementsInAtomicUnit } from "./utils";
|
||||
import type { AtomicUnit } from "./utils";
|
||||
import { MIN_WIDTH_OR_HEIGHT } from "../../constants";
|
||||
import { pointFrom, type GlobalPoint } from "../../../math";
|
||||
import { pointFrom, type GlobalPoint } from "@excalidraw/math";
|
||||
|
||||
interface MultiDimensionProps {
|
||||
property: "width" | "height";
|
||||
|
|
|
@ -13,7 +13,7 @@ import { useMemo } from "react";
|
|||
import { getElementsInAtomicUnit, moveElement } from "./utils";
|
||||
import type { AtomicUnit } from "./utils";
|
||||
import type { AppState } from "../../types";
|
||||
import { pointFrom, pointRotateRads } from "../../../math";
|
||||
import { pointFrom, pointRotateRads } from "@excalidraw/math";
|
||||
|
||||
interface MultiPositionProps {
|
||||
property: "x" | "y";
|
||||
|
|
|
@ -4,7 +4,7 @@ import type { DragInputCallbackType } from "./DragInput";
|
|||
import { getStepSizedValue, moveElement } from "./utils";
|
||||
import type Scene from "../../scene/Scene";
|
||||
import type { AppState } from "../../types";
|
||||
import { clamp, pointFrom, pointRotateRads, round } from "../../../math";
|
||||
import { clamp, pointFrom, pointRotateRads, round } from "@excalidraw/math";
|
||||
import { isImageElement } from "../../element/typeChecks";
|
||||
import {
|
||||
getFlipAdjustedCropPosition,
|
||||
|
|
|
@ -9,7 +9,7 @@ import type {
|
|||
} from "../../types";
|
||||
import { CloseIcon } from "../icons";
|
||||
import { Island } from "../Island";
|
||||
import { throttle } from "lodash";
|
||||
import throttle from "lodash.throttle";
|
||||
import Dimension from "./Dimension";
|
||||
import Angle from "./Angle";
|
||||
import FontSize from "./FontSize";
|
||||
|
@ -30,7 +30,7 @@ import clsx from "clsx";
|
|||
import "./Stats.scss";
|
||||
import { isGridModeEnabled } from "../../snapping";
|
||||
import { getUncroppedWidthAndHeight } from "../../element/cropElement";
|
||||
import { round } from "../../../math";
|
||||
import { round } from "@excalidraw/math";
|
||||
import { frameAndChildrenSelectedTogether } from "../../frame";
|
||||
|
||||
interface StatsProps {
|
||||
|
|
|
@ -24,8 +24,8 @@ import { getCommonBounds, isTextElement } from "../../element";
|
|||
import { API } from "../../tests/helpers/api";
|
||||
import { actionGroup } from "../../actions";
|
||||
import { isInGroup } from "../../groups";
|
||||
import type { Degrees } from "../../../math";
|
||||
import { degreesToRadians, pointFrom, pointRotateRads } from "../../../math";
|
||||
import type { Degrees } from "@excalidraw/math";
|
||||
import { degreesToRadians, pointFrom, pointRotateRads } from "@excalidraw/math";
|
||||
|
||||
const { h } = window;
|
||||
const mouse = new Pointer("mouse");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { Radians } from "../../../math";
|
||||
import { pointFrom, pointRotateRads } from "../../../math";
|
||||
import type { Radians } from "@excalidraw/math";
|
||||
import { pointFrom, pointRotateRads } from "@excalidraw/math";
|
||||
import {
|
||||
bindOrUnbindLinearElements,
|
||||
updateBoundElements,
|
||||
|
|
|
@ -29,7 +29,7 @@ import { atom, useAtom } from "../../editor-jotai";
|
|||
import { trackEvent } from "../../analytics";
|
||||
import { InlineIcon } from "../InlineIcon";
|
||||
import { TTDDialogSubmitShortcut } from "./TTDDialogSubmitShortcut";
|
||||
import { isFiniteNumber } from "../../../math";
|
||||
import { isFiniteNumber } from "@excalidraw/math";
|
||||
|
||||
const MIN_PROMPT_LENGTH = 3;
|
||||
const MAX_PROMPT_LENGTH = 1000;
|
||||
|
|
|
@ -34,7 +34,7 @@ import { trackEvent } from "../../analytics";
|
|||
import { useAppProps, useDevice, useExcalidrawAppState } from "../App";
|
||||
import { isEmbeddableElement } from "../../element/typeChecks";
|
||||
import { getLinkHandleFromCoords } from "./helpers";
|
||||
import { pointFrom, type GlobalPoint } from "../../../math";
|
||||
import { pointFrom, type GlobalPoint } from "@excalidraw/math";
|
||||
import { isElementLink } from "../../element/elementLink";
|
||||
|
||||
import "./Hyperlink.scss";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { GlobalPoint, Radians } from "../../../math";
|
||||
import { pointFrom, pointRotateRads } from "../../../math";
|
||||
import type { GlobalPoint, Radians } from "@excalidraw/math";
|
||||
import { pointFrom, pointRotateRads } from "@excalidraw/math";
|
||||
import { MIME_TYPES } from "../../constants";
|
||||
import type { Bounds } from "../../element/bounds";
|
||||
import { getElementAbsoluteCoords } from "../../element/bounds";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue