mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
improve & granularize ExcalidrawElement types (#991)
* improve & granularize ExcalidrawElement types * fix incorrectly passing type * fix tests * fix more tests * fix unnecessary spreads & refactor * add comments
This commit is contained in:
parent
1c545c1d47
commit
373d16abe6
22 changed files with 430 additions and 272 deletions
|
@ -1,25 +1,45 @@
|
|||
import { randomSeed } from "roughjs/bin/math";
|
||||
import nanoid from "nanoid";
|
||||
import { Point } from "../types";
|
||||
|
||||
import { ExcalidrawElement, ExcalidrawTextElement } from "../element/types";
|
||||
import {
|
||||
ExcalidrawElement,
|
||||
ExcalidrawTextElement,
|
||||
ExcalidrawLinearElement,
|
||||
ExcalidrawGenericElement,
|
||||
} from "../element/types";
|
||||
import { measureText } from "../utils";
|
||||
|
||||
export function newElement(
|
||||
type: string,
|
||||
x: number,
|
||||
y: number,
|
||||
strokeColor: string,
|
||||
backgroundColor: string,
|
||||
fillStyle: string,
|
||||
strokeWidth: number,
|
||||
roughness: number,
|
||||
opacity: number,
|
||||
width = 0,
|
||||
height = 0,
|
||||
type ElementConstructorOpts = {
|
||||
x: ExcalidrawGenericElement["x"];
|
||||
y: ExcalidrawGenericElement["y"];
|
||||
strokeColor: ExcalidrawGenericElement["strokeColor"];
|
||||
backgroundColor: ExcalidrawGenericElement["backgroundColor"];
|
||||
fillStyle: ExcalidrawGenericElement["fillStyle"];
|
||||
strokeWidth: ExcalidrawGenericElement["strokeWidth"];
|
||||
roughness: ExcalidrawGenericElement["roughness"];
|
||||
opacity: ExcalidrawGenericElement["opacity"];
|
||||
width?: ExcalidrawGenericElement["width"];
|
||||
height?: ExcalidrawGenericElement["height"];
|
||||
};
|
||||
|
||||
function _newElementBase<T extends ExcalidrawElement>(
|
||||
type: T["type"],
|
||||
{
|
||||
x,
|
||||
y,
|
||||
strokeColor,
|
||||
backgroundColor,
|
||||
fillStyle,
|
||||
strokeWidth,
|
||||
roughness,
|
||||
opacity,
|
||||
width = 0,
|
||||
height = 0,
|
||||
...rest
|
||||
}: ElementConstructorOpts & Partial<ExcalidrawGenericElement>,
|
||||
) {
|
||||
const element = {
|
||||
id: nanoid(),
|
||||
return {
|
||||
id: rest.id || nanoid(),
|
||||
type,
|
||||
x,
|
||||
y,
|
||||
|
@ -31,29 +51,36 @@ export function newElement(
|
|||
strokeWidth,
|
||||
roughness,
|
||||
opacity,
|
||||
seed: randomSeed(),
|
||||
points: [] as readonly Point[],
|
||||
version: 1,
|
||||
versionNonce: 0,
|
||||
isDeleted: false,
|
||||
seed: rest.seed ?? randomSeed(),
|
||||
version: rest.version || 1,
|
||||
versionNonce: rest.versionNonce ?? 0,
|
||||
isDeleted: rest.isDeleted ?? false,
|
||||
};
|
||||
return element;
|
||||
}
|
||||
|
||||
export function newElement(
|
||||
opts: {
|
||||
type: ExcalidrawGenericElement["type"];
|
||||
} & ElementConstructorOpts,
|
||||
): ExcalidrawGenericElement {
|
||||
return _newElementBase<ExcalidrawGenericElement>(opts.type, opts);
|
||||
}
|
||||
|
||||
export function newTextElement(
|
||||
element: ExcalidrawElement,
|
||||
text: string,
|
||||
font: string,
|
||||
) {
|
||||
opts: {
|
||||
text: string;
|
||||
font: string;
|
||||
} & ElementConstructorOpts,
|
||||
): ExcalidrawTextElement {
|
||||
const { text, font } = opts;
|
||||
const metrics = measureText(text, font);
|
||||
const textElement: ExcalidrawTextElement = {
|
||||
...element,
|
||||
type: "text",
|
||||
const textElement = {
|
||||
..._newElementBase<ExcalidrawTextElement>("text", opts),
|
||||
text: text,
|
||||
font: font,
|
||||
// Center the text
|
||||
x: element.x - metrics.width / 2,
|
||||
y: element.y - metrics.height / 2,
|
||||
x: opts.x - metrics.width / 2,
|
||||
y: opts.y - metrics.height / 2,
|
||||
width: metrics.width,
|
||||
height: metrics.height,
|
||||
baseline: metrics.baseline,
|
||||
|
@ -62,6 +89,17 @@ export function newTextElement(
|
|||
return textElement;
|
||||
}
|
||||
|
||||
export function newLinearElement(
|
||||
opts: {
|
||||
type: "arrow" | "line";
|
||||
} & ElementConstructorOpts,
|
||||
): ExcalidrawLinearElement {
|
||||
return {
|
||||
..._newElementBase<ExcalidrawLinearElement>(opts.type, opts),
|
||||
points: [],
|
||||
};
|
||||
}
|
||||
|
||||
// Simplified deep clone for the purpose of cloning ExcalidrawElement only
|
||||
// (doesn't clone Date, RegExp, Map, Set, Typed arrays etc.)
|
||||
//
|
||||
|
@ -100,11 +138,15 @@ function _duplicateElement(val: any, depth: number = 0) {
|
|||
return val;
|
||||
}
|
||||
|
||||
export function duplicateElement(
|
||||
element: ReturnType<typeof newElement>,
|
||||
): ReturnType<typeof newElement> {
|
||||
const copy = _duplicateElement(element);
|
||||
export function duplicateElement<TElement extends Mutable<ExcalidrawElement>>(
|
||||
element: TElement,
|
||||
overrides?: Partial<TElement>,
|
||||
): TElement {
|
||||
let copy: TElement = _duplicateElement(element);
|
||||
copy.id = nanoid();
|
||||
copy.seed = randomSeed();
|
||||
if (overrides) {
|
||||
copy = Object.assign(copy, overrides);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue