feat: image support (#4011)

Co-authored-by: Emil Atanasov <heitara@gmail.com>
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
This commit is contained in:
David Luzar 2021-10-21 22:05:48 +02:00 committed by GitHub
parent 0f0244224d
commit 163ad1f4c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
85 changed files with 3536 additions and 618 deletions

View file

@ -10,6 +10,8 @@ import {
Arrowhead,
ChartType,
FontFamilyValues,
FileId,
ExcalidrawImageElement,
Theme,
} from "./element/types";
import { SHAPES } from "./shapes";
@ -24,7 +26,9 @@ import { Language } from "./i18n";
import { ClipboardData } from "./clipboard";
import { isOverScrollBars } from "./scene";
import { MaybeTransformHandleType } from "./element/transformHandles";
import { FileSystemHandle } from "./data/filesystem";
import Library from "./data/library";
import type { FileSystemHandle } from "./data/filesystem";
import type { ALLOWED_IMAGE_MIME_TYPES, MIME_TYPES } from "./constants";
export type Point = Readonly<RoughPoint>;
@ -43,6 +47,22 @@ export type Collaborator = {
};
};
export type DataURL = string & { _brand: "DataURL" };
export type BinaryFileData = {
mimeType:
| typeof ALLOWED_IMAGE_MIME_TYPES[number]
// future user or unknown file type
| typeof MIME_TYPES.binary;
id: FileId;
dataURL: DataURL;
created: number;
};
export type BinaryFileMetadata = Omit<BinaryFileData, "dataURL">;
export type BinaryFiles = Record<ExcalidrawElement["id"], BinaryFileData>;
export type AppState = {
isLoading: boolean;
errorMessage: string | null;
@ -127,6 +147,8 @@ export type AppState = {
shown: true;
data: Spreadsheet;
};
/** imageElement waiting to be placed on canvas */
pendingImageElement: NonDeleted<ExcalidrawImageElement> | null;
};
export type NormalizedZoomValue = number & { _brand: "normalizedZoom" };
@ -172,6 +194,7 @@ export interface ExcalidrawProps {
onChange?: (
elements: readonly ExcalidrawElement[],
appState: AppState,
files: BinaryFiles,
) => void;
initialData?: ImportedDataState | null | Promise<ImportedDataState | null>;
excalidrawRef?: ForwardRef<ExcalidrawAPIRefValue>;
@ -207,6 +230,7 @@ export interface ExcalidrawProps {
handleKeyboardGlobally?: boolean;
onLibraryChange?: (libraryItems: LibraryItems) => void | Promise<any>;
autoFocus?: boolean;
generateIdForFile?: (file: File) => string | Promise<string>;
}
export type SceneData = {
@ -227,11 +251,13 @@ export type ExportOpts = {
onExportToBackend?: (
exportedElements: readonly NonDeletedExcalidrawElement[],
appState: AppState,
files: BinaryFiles,
canvas: HTMLCanvasElement | null,
) => void;
renderCustomUI?: (
exportedElements: readonly NonDeletedExcalidrawElement[],
appState: AppState,
files: BinaryFiles,
canvas: HTMLCanvasElement | null,
) => JSX.Element;
};
@ -258,6 +284,23 @@ export type AppProps = ExcalidrawProps & {
handleKeyboardGlobally: boolean;
};
/** A subset of App class properties that we need to use elsewhere
* in the app, eg Manager. Factored out into a separate type to keep DRY. */
export type AppClassProperties = {
props: AppProps;
canvas: HTMLCanvasElement | null;
focusContainer(): void;
library: Library;
imageCache: Map<
FileId,
{
image: HTMLImageElement | Promise<HTMLImageElement>;
mimeType: typeof ALLOWED_IMAGE_MIME_TYPES[number];
}
>;
files: BinaryFiles;
};
export type PointerDownState = Readonly<{
// The first position at which pointerDown happened
origin: Readonly<{ x: number; y: number }>;
@ -327,9 +370,11 @@ export type ExcalidrawImperativeAPI = {
scrollToContent: InstanceType<typeof App>["scrollToContent"];
getSceneElements: InstanceType<typeof App>["getSceneElements"];
getAppState: () => InstanceType<typeof App>["state"];
getFiles: () => InstanceType<typeof App>["files"];
refresh: InstanceType<typeof App>["refresh"];
importLibrary: InstanceType<typeof App>["importLibraryFromUrl"];
setToastMessage: InstanceType<typeof App>["setToastMessage"];
addFiles: (data: BinaryFileData[]) => void;
readyPromise: ResolvablePromise<ExcalidrawImperativeAPI>;
ready: true;
id: string;