mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
413 lines
12 KiB
TypeScript
413 lines
12 KiB
TypeScript
import type { LocalPoint, Radians } from "@excalidraw/math";
|
|
|
|
import type {
|
|
FONT_FAMILY,
|
|
ROUNDNESS,
|
|
TEXT_ALIGN,
|
|
THEME,
|
|
VERTICAL_ALIGN,
|
|
} from "../constants";
|
|
import type {
|
|
MakeBrand,
|
|
MarkNonNullable,
|
|
Merge,
|
|
ValueOf,
|
|
} from "../utility-types";
|
|
|
|
export type ChartType = "bar" | "line";
|
|
export type FillStyle = "hachure" | "cross-hatch" | "solid" | "zigzag";
|
|
export type FontFamilyKeys = keyof typeof FONT_FAMILY;
|
|
export type FontFamilyValues = typeof FONT_FAMILY[FontFamilyKeys];
|
|
export type Theme = typeof THEME[keyof typeof THEME];
|
|
export type FontString = string & { _brand: "fontString" };
|
|
export type GroupId = string;
|
|
export type PointerType = "mouse" | "pen" | "touch";
|
|
export type StrokeRoundness = "round" | "sharp";
|
|
export type RoundnessType = ValueOf<typeof ROUNDNESS>;
|
|
export type StrokeStyle = "solid" | "dashed" | "dotted";
|
|
export type TextAlign = typeof TEXT_ALIGN[keyof typeof TEXT_ALIGN];
|
|
|
|
type VerticalAlignKeys = keyof typeof VERTICAL_ALIGN;
|
|
export type VerticalAlign = typeof VERTICAL_ALIGN[VerticalAlignKeys];
|
|
export type FractionalIndex = string & { _brand: "franctionalIndex" };
|
|
|
|
export type BoundElement = Readonly<{
|
|
id: ExcalidrawLinearElement["id"];
|
|
type: "arrow" | "text";
|
|
}>;
|
|
|
|
type _ExcalidrawElementBase = Readonly<{
|
|
id: string;
|
|
x: number;
|
|
y: number;
|
|
strokeColor: string;
|
|
backgroundColor: string;
|
|
fillStyle: FillStyle;
|
|
strokeWidth: number;
|
|
strokeStyle: StrokeStyle;
|
|
roundness: null | { type: RoundnessType; value?: number };
|
|
roughness: number;
|
|
opacity: number;
|
|
width: number;
|
|
height: number;
|
|
angle: Radians;
|
|
/** Random integer used to seed shape generation so that the roughjs shape
|
|
doesn't differ across renders. */
|
|
seed: number;
|
|
/** Integer that is sequentially incremented on each change. Used to reconcile
|
|
elements during collaboration or when saving to server. */
|
|
version: number;
|
|
/** Random integer that is regenerated on each change.
|
|
Used for deterministic reconciliation of updates during collaboration,
|
|
in case the versions (see above) are identical. */
|
|
versionNonce: number;
|
|
/** String in a fractional form defined by https://github.com/rocicorp/fractional-indexing.
|
|
Used for ordering in multiplayer scenarios, such as during reconciliation or undo / redo.
|
|
Always kept in sync with the array order by `syncMovedIndices` and `syncInvalidIndices`.
|
|
Could be null, i.e. for new elements which were not yet assigned to the scene. */
|
|
index: FractionalIndex | null;
|
|
isDeleted: boolean;
|
|
/** List of groups the element belongs to.
|
|
Ordered from deepest to shallowest. */
|
|
groupIds: readonly GroupId[];
|
|
frameId: string | null;
|
|
/** other elements that are bound to this element */
|
|
boundElements: readonly BoundElement[] | null;
|
|
/** epoch (ms) timestamp of last element update */
|
|
updated: number;
|
|
link: string | null;
|
|
locked: boolean;
|
|
customData?: Record<string, any>;
|
|
}>;
|
|
|
|
export type ExcalidrawSelectionElement = _ExcalidrawElementBase & {
|
|
type: "selection";
|
|
};
|
|
|
|
export type ExcalidrawRectangleElement = _ExcalidrawElementBase & {
|
|
type: "rectangle";
|
|
};
|
|
|
|
export type ExcalidrawDiamondElement = _ExcalidrawElementBase & {
|
|
type: "diamond";
|
|
};
|
|
|
|
export type ExcalidrawEllipseElement = _ExcalidrawElementBase & {
|
|
type: "ellipse";
|
|
};
|
|
|
|
export type ExcalidrawEmbeddableElement = _ExcalidrawElementBase &
|
|
Readonly<{
|
|
type: "embeddable";
|
|
}>;
|
|
|
|
export type MagicGenerationData =
|
|
| {
|
|
status: "pending";
|
|
}
|
|
| { status: "done"; html: string }
|
|
| {
|
|
status: "error";
|
|
message?: string;
|
|
code: "ERR_GENERATION_INTERRUPTED" | string;
|
|
};
|
|
|
|
export type ExcalidrawIframeElement = _ExcalidrawElementBase &
|
|
Readonly<{
|
|
type: "iframe";
|
|
// TODO move later to AI-specific frame
|
|
customData?: { generationData?: MagicGenerationData };
|
|
}>;
|
|
|
|
export type ExcalidrawIframeLikeElement =
|
|
| ExcalidrawIframeElement
|
|
| ExcalidrawEmbeddableElement;
|
|
|
|
export type IframeData =
|
|
| {
|
|
intrinsicSize: { w: number; h: number };
|
|
error?: Error;
|
|
sandbox?: { allowSameOrigin?: boolean };
|
|
} & (
|
|
| { type: "video" | "generic"; link: string }
|
|
| { type: "document"; srcdoc: (theme: Theme) => string }
|
|
);
|
|
|
|
export type ImageCrop = {
|
|
x: number;
|
|
y: number;
|
|
width: number;
|
|
height: number;
|
|
naturalWidth: number;
|
|
naturalHeight: number;
|
|
};
|
|
|
|
export type ExcalidrawImageElement = _ExcalidrawElementBase &
|
|
Readonly<{
|
|
type: "image";
|
|
fileId: FileId | null;
|
|
/** whether respective file is persisted */
|
|
status: "pending" | "saved" | "error";
|
|
/** X and Y scale factors <-1, 1>, used for image axis flipping */
|
|
scale: [number, number];
|
|
/** whether an element is cropped */
|
|
crop: ImageCrop | null;
|
|
}>;
|
|
|
|
export type InitializedExcalidrawImageElement = MarkNonNullable<
|
|
ExcalidrawImageElement,
|
|
"fileId"
|
|
>;
|
|
|
|
export type ExcalidrawFrameElement = _ExcalidrawElementBase & {
|
|
type: "frame";
|
|
name: string | null;
|
|
};
|
|
|
|
export type ExcalidrawMagicFrameElement = _ExcalidrawElementBase & {
|
|
type: "magicframe";
|
|
name: string | null;
|
|
};
|
|
|
|
export type ExcalidrawFrameLikeElement =
|
|
| ExcalidrawFrameElement
|
|
| ExcalidrawMagicFrameElement;
|
|
|
|
/**
|
|
* These are elements that don't have any additional properties.
|
|
*/
|
|
export type ExcalidrawGenericElement =
|
|
| ExcalidrawSelectionElement
|
|
| ExcalidrawRectangleElement
|
|
| ExcalidrawDiamondElement
|
|
| ExcalidrawEllipseElement;
|
|
|
|
export type ExcalidrawFlowchartNodeElement =
|
|
| ExcalidrawRectangleElement
|
|
| ExcalidrawDiamondElement
|
|
| ExcalidrawEllipseElement;
|
|
|
|
export type ExcalidrawRectanguloidElement =
|
|
| ExcalidrawRectangleElement
|
|
| ExcalidrawImageElement
|
|
| ExcalidrawTextElement
|
|
| ExcalidrawFreeDrawElement
|
|
| ExcalidrawIframeLikeElement
|
|
| ExcalidrawFrameLikeElement
|
|
| ExcalidrawEmbeddableElement;
|
|
|
|
/**
|
|
* ExcalidrawElement should be JSON serializable and (eventually) contain
|
|
* no computed data. The list of all ExcalidrawElements should be shareable
|
|
* between peers and contain no state local to the peer.
|
|
*/
|
|
export type ExcalidrawElement =
|
|
| ExcalidrawGenericElement
|
|
| ExcalidrawTextElement
|
|
| ExcalidrawLinearElement
|
|
| ExcalidrawArrowElement
|
|
| ExcalidrawFreeDrawElement
|
|
| ExcalidrawImageElement
|
|
| ExcalidrawFrameElement
|
|
| ExcalidrawMagicFrameElement
|
|
| ExcalidrawIframeElement
|
|
| ExcalidrawEmbeddableElement;
|
|
|
|
export type ExcalidrawNonSelectionElement = Exclude<
|
|
ExcalidrawElement,
|
|
ExcalidrawSelectionElement
|
|
>;
|
|
|
|
export type Ordered<TElement extends ExcalidrawElement> = TElement & {
|
|
index: FractionalIndex;
|
|
};
|
|
|
|
export type OrderedExcalidrawElement = Ordered<ExcalidrawElement>;
|
|
|
|
export type NonDeleted<TElement extends ExcalidrawElement> = TElement & {
|
|
isDeleted: boolean;
|
|
};
|
|
|
|
export type NonDeletedExcalidrawElement = NonDeleted<ExcalidrawElement>;
|
|
|
|
export type ExcalidrawTextElement = _ExcalidrawElementBase &
|
|
Readonly<{
|
|
type: "text";
|
|
fontSize: number;
|
|
fontFamily: FontFamilyValues;
|
|
text: string;
|
|
textAlign: TextAlign;
|
|
verticalAlign: VerticalAlign;
|
|
containerId: ExcalidrawGenericElement["id"] | null;
|
|
originalText: string;
|
|
/**
|
|
* If `true` the width will fit the text. If `false`, the text will
|
|
* wrap to fit the width.
|
|
*
|
|
* @default true
|
|
*/
|
|
autoResize: boolean;
|
|
/**
|
|
* Unitless line height (aligned to W3C). To get line height in px, multiply
|
|
* with font size (using `getLineHeightInPx` helper).
|
|
*/
|
|
lineHeight: number & { _brand: "unitlessLineHeight" };
|
|
}>;
|
|
|
|
export type ExcalidrawBindableElement =
|
|
| ExcalidrawRectangleElement
|
|
| ExcalidrawDiamondElement
|
|
| ExcalidrawEllipseElement
|
|
| ExcalidrawTextElement
|
|
| ExcalidrawImageElement
|
|
| ExcalidrawIframeElement
|
|
| ExcalidrawEmbeddableElement
|
|
| ExcalidrawFrameElement
|
|
| ExcalidrawMagicFrameElement;
|
|
|
|
export type ExcalidrawTextContainer =
|
|
| ExcalidrawRectangleElement
|
|
| ExcalidrawDiamondElement
|
|
| ExcalidrawEllipseElement
|
|
| ExcalidrawArrowElement;
|
|
|
|
export type ExcalidrawTextElementWithContainer = {
|
|
containerId: ExcalidrawTextContainer["id"];
|
|
} & ExcalidrawTextElement;
|
|
|
|
export type FixedPoint = [number, number];
|
|
|
|
export type PointBinding = {
|
|
elementId: ExcalidrawBindableElement["id"];
|
|
focus: number;
|
|
gap: number;
|
|
};
|
|
|
|
export type FixedPointBinding = Merge<
|
|
PointBinding,
|
|
{
|
|
// Represents the fixed point binding information in form of a vertical and
|
|
// horizontal ratio (i.e. a percentage value in the 0.0-1.0 range). This ratio
|
|
// gives the user selected fixed point by multiplying the bound element width
|
|
// with fixedPoint[0] and the bound element height with fixedPoint[1] to get the
|
|
// bound element-local point coordinate.
|
|
fixedPoint: FixedPoint;
|
|
}
|
|
>;
|
|
|
|
export type Arrowhead =
|
|
| "arrow"
|
|
| "bar"
|
|
| "dot" // legacy. Do not use for new elements.
|
|
| "circle"
|
|
| "circle_outline"
|
|
| "triangle"
|
|
| "triangle_outline"
|
|
| "diamond"
|
|
| "diamond_outline"
|
|
| "crowfoot_one"
|
|
| "crowfoot_many"
|
|
| "crowfoot_one_or_many";
|
|
|
|
export type ExcalidrawLinearElement = _ExcalidrawElementBase &
|
|
Readonly<{
|
|
type: "line" | "arrow";
|
|
points: readonly LocalPoint[];
|
|
lastCommittedPoint: LocalPoint | null;
|
|
startBinding: PointBinding | null;
|
|
endBinding: PointBinding | null;
|
|
startArrowhead: Arrowhead | null;
|
|
endArrowhead: Arrowhead | null;
|
|
}>;
|
|
|
|
export type FixedSegment = {
|
|
start: LocalPoint;
|
|
end: LocalPoint;
|
|
index: number;
|
|
};
|
|
|
|
export type ExcalidrawArrowElement = ExcalidrawLinearElement &
|
|
Readonly<{
|
|
type: "arrow";
|
|
elbowed: boolean;
|
|
}>;
|
|
|
|
export type ExcalidrawElbowArrowElement = Merge<
|
|
ExcalidrawArrowElement,
|
|
{
|
|
elbowed: true;
|
|
startBinding: FixedPointBinding | null;
|
|
endBinding: FixedPointBinding | null;
|
|
fixedSegments: readonly FixedSegment[] | null;
|
|
/**
|
|
* Marks that the 3rd point should be used as the 2nd point of the arrow in
|
|
* order to temporarily hide the first segment of the arrow without losing
|
|
* the data from the points array. It allows creating the expected arrow
|
|
* path when the arrow with fixed segments is bound on a horizontal side and
|
|
* moved to a vertical and vica versa.
|
|
*/
|
|
startIsSpecial: boolean | null;
|
|
/**
|
|
* Marks that the 3rd point backwards from the end should be used as the 2nd
|
|
* point of the arrow in order to temporarily hide the last segment of the
|
|
* arrow without losing the data from the points array. It allows creating
|
|
* the expected arrow path when the arrow with fixed segments is bound on a
|
|
* horizontal side and moved to a vertical and vica versa.
|
|
*/
|
|
endIsSpecial: boolean | null;
|
|
}
|
|
>;
|
|
|
|
export type ExcalidrawFreeDrawElement = _ExcalidrawElementBase &
|
|
Readonly<{
|
|
type: "freedraw";
|
|
points: readonly LocalPoint[];
|
|
pressures: readonly number[];
|
|
simulatePressure: boolean;
|
|
lastCommittedPoint: LocalPoint | null;
|
|
}>;
|
|
|
|
export type FileId = string & { _brand: "FileId" };
|
|
|
|
export type ExcalidrawElementType = ExcalidrawElement["type"];
|
|
|
|
/**
|
|
* Map of excalidraw elements.
|
|
* Unspecified whether deleted or non-deleted.
|
|
* Can be a subset of Scene elements.
|
|
*/
|
|
export type ElementsMap = Map<ExcalidrawElement["id"], ExcalidrawElement>;
|
|
|
|
/**
|
|
* Map of non-deleted elements.
|
|
* Can be a subset of Scene elements.
|
|
*/
|
|
export type NonDeletedElementsMap = Map<
|
|
ExcalidrawElement["id"],
|
|
NonDeletedExcalidrawElement
|
|
> &
|
|
MakeBrand<"NonDeletedElementsMap">;
|
|
|
|
/**
|
|
* Map of all excalidraw Scene elements, including deleted.
|
|
* Not a subset. Use this type when you need access to current Scene elements.
|
|
*/
|
|
export type SceneElementsMap = Map<
|
|
ExcalidrawElement["id"],
|
|
Ordered<ExcalidrawElement>
|
|
> &
|
|
MakeBrand<"SceneElementsMap">;
|
|
|
|
/**
|
|
* Map of all non-deleted Scene elements.
|
|
* Not a subset. Use this type when you need access to current Scene elements.
|
|
*/
|
|
export type NonDeletedSceneElementsMap = Map<
|
|
ExcalidrawElement["id"],
|
|
Ordered<NonDeletedExcalidrawElement>
|
|
> &
|
|
MakeBrand<"NonDeletedSceneElementsMap">;
|
|
|
|
export type ElementsMapOrArray =
|
|
| readonly ExcalidrawElement[]
|
|
| Readonly<ElementsMap>;
|