feat: introduce frames (#6123)

Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
Ryan Di 2023-06-15 00:42:01 +08:00 committed by GitHub
parent 4d7d96eb7b
commit 81ebf82979
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
78 changed files with 4563 additions and 480 deletions

View file

@ -15,6 +15,7 @@ import {
ExcalidrawImageElement,
Theme,
StrokeRoundness,
ExcalidrawFrameElement,
} from "./element/types";
import { SHAPES } from "./shapes";
import { Point as RoughPoint } from "roughjs/bin/geometry";
@ -85,7 +86,7 @@ export type BinaryFiles = Record<ExcalidrawElement["id"], BinaryFileData>;
export type LastActiveTool =
| {
type: typeof SHAPES[number]["value"] | "eraser" | "hand";
type: typeof SHAPES[number]["value"] | "eraser" | "hand" | "frame";
customType: null;
}
| {
@ -113,6 +114,10 @@ export type AppState = {
isBindingEnabled: boolean;
startBoundElement: NonDeleted<ExcalidrawBindableElement> | null;
suggestedBindings: SuggestedBinding[];
frameToHighlight: NonDeleted<ExcalidrawFrameElement> | null;
shouldRenderFrames: boolean;
editingFrame: string | null;
elementsToHighlight: NonDeleted<ExcalidrawElement>[] | null;
// element being edited, but not necessarily added to elements array yet
// (e.g. text element when typing into the input)
editingElement: NonDeletedExcalidrawElement | null;
@ -126,7 +131,7 @@ export type AppState = {
locked: boolean;
} & (
| {
type: typeof SHAPES[number]["value"] | "eraser" | "hand";
type: typeof SHAPES[number]["value"] | "eraser" | "hand" | "frame";
customType: null;
}
| {
@ -178,6 +183,7 @@ export type AppState = {
lastPointerDownWith: PointerType;
selectedElementIds: { [id: string]: boolean };
previousSelectedElementIds: { [id: string]: boolean };
selectedElementsAreBeingDragged: boolean;
shouldCacheIgnoreZoom: boolean;
toast: { message: string; closable?: boolean; duration?: number } | null;
zenModeEnabled: boolean;
@ -532,6 +538,12 @@ export type ExcalidrawImperativeAPI = {
setCursor: InstanceType<typeof App>["setCursor"];
resetCursor: InstanceType<typeof App>["resetCursor"];
toggleSidebar: InstanceType<typeof App>["toggleSidebar"];
/**
* Disables rendering of frames (including element clipping), but currently
* the frames are still interactive in edit mode. As such, this API should be
* used in conjunction with view mode (props.viewModeEnabled).
*/
toggleFrameRendering: InstanceType<typeof App>["toggleFrameRendering"];
};
export type Device = Readonly<{
@ -541,3 +553,22 @@ export type Device = Readonly<{
canDeviceFitSidebar: boolean;
isLandscape: boolean;
}>;
type FrameNameBounds = {
x: number;
y: number;
width: number;
height: number;
angle: number;
};
export type FrameNameBoundsCache = {
get: (frameElement: ExcalidrawFrameElement) => FrameNameBounds | null;
_cache: Map<
string,
FrameNameBounds & {
zoom: AppState["zoom"]["value"];
versionNonce: ExcalidrawFrameElement["versionNonce"];
}
>;
};