mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
Add NonDeleted<ExcalidrawElement> (#1068)
* add NonDeleted * make test:all script run tests without prompt * rename helper * replace with helper * make element contructors return nonDeleted elements * cache filtered elements where appliacable for better perf * rename manager element getter * remove unnecessary assertion * fix test * make element types in resizeElement into nonDeleted Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
parent
c714c778ab
commit
df0613d8ac
29 changed files with 260 additions and 189 deletions
|
@ -1,6 +1,6 @@
|
|||
import { distanceBetweenPointAndSegment } from "../math";
|
||||
|
||||
import { ExcalidrawElement } from "./types";
|
||||
import { NonDeletedExcalidrawElement } from "./types";
|
||||
|
||||
import { getDiamondPoints, getElementAbsoluteCoords } from "./bounds";
|
||||
import { Point } from "../types";
|
||||
|
@ -11,7 +11,7 @@ import { isLinearElement } from "./typeChecks";
|
|||
import { rotate } from "../math";
|
||||
|
||||
function isElementDraggableFromInside(
|
||||
element: ExcalidrawElement,
|
||||
element: NonDeletedExcalidrawElement,
|
||||
appState: AppState,
|
||||
): boolean {
|
||||
return (
|
||||
|
@ -21,7 +21,7 @@ function isElementDraggableFromInside(
|
|||
}
|
||||
|
||||
export function hitTest(
|
||||
element: ExcalidrawElement,
|
||||
element: NonDeletedExcalidrawElement,
|
||||
appState: AppState,
|
||||
x: number,
|
||||
y: number,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ExcalidrawElement } from "./types";
|
||||
import { ExcalidrawElement, NonDeletedExcalidrawElement } from "./types";
|
||||
import { isInvisiblySmallElement } from "./sizeHelpers";
|
||||
|
||||
export {
|
||||
|
@ -63,6 +63,9 @@ export function getDrawingVersion(elements: readonly ExcalidrawElement[]) {
|
|||
return elements.reduce((acc, el) => acc + el.version, 0);
|
||||
}
|
||||
|
||||
export function hasNonDeletedElements(elements: readonly ExcalidrawElement[]) {
|
||||
return elements.some((element) => !element.isDeleted);
|
||||
export function getNonDeletedElements(elements: readonly ExcalidrawElement[]) {
|
||||
return (
|
||||
elements.filter((element) => !element.isDeleted) as
|
||||
readonly NonDeletedExcalidrawElement[]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import {
|
|||
ExcalidrawTextElement,
|
||||
ExcalidrawLinearElement,
|
||||
ExcalidrawGenericElement,
|
||||
NonDeleted,
|
||||
} from "../element/types";
|
||||
import { measureText } from "../utils";
|
||||
import { randomInteger, randomId } from "../random";
|
||||
|
@ -56,7 +57,7 @@ function _newElementBase<T extends ExcalidrawElement>(
|
|||
seed: rest.seed ?? randomInteger(),
|
||||
version: rest.version || 1,
|
||||
versionNonce: rest.versionNonce ?? 0,
|
||||
isDeleted: rest.isDeleted ?? false,
|
||||
isDeleted: false as false,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -64,7 +65,7 @@ export function newElement(
|
|||
opts: {
|
||||
type: ExcalidrawGenericElement["type"];
|
||||
} & ElementConstructorOpts,
|
||||
): ExcalidrawGenericElement {
|
||||
): NonDeleted<ExcalidrawGenericElement> {
|
||||
return _newElementBase<ExcalidrawGenericElement>(opts.type, opts);
|
||||
}
|
||||
|
||||
|
@ -73,13 +74,12 @@ export function newTextElement(
|
|||
text: string;
|
||||
font: string;
|
||||
} & ElementConstructorOpts,
|
||||
): ExcalidrawTextElement {
|
||||
): NonDeleted<ExcalidrawTextElement> {
|
||||
const { text, font } = opts;
|
||||
const metrics = measureText(text, font);
|
||||
const textElement = newElementWith(
|
||||
{
|
||||
..._newElementBase<ExcalidrawTextElement>("text", opts),
|
||||
isDeleted: false,
|
||||
text: text,
|
||||
font: font,
|
||||
// Center the text
|
||||
|
@ -100,7 +100,7 @@ export function newLinearElement(
|
|||
type: ExcalidrawLinearElement["type"];
|
||||
lastCommittedPoint?: ExcalidrawLinearElement["lastCommittedPoint"];
|
||||
} & ElementConstructorOpts,
|
||||
): ExcalidrawLinearElement {
|
||||
): NonDeleted<ExcalidrawLinearElement> {
|
||||
return {
|
||||
..._newElementBase<ExcalidrawLinearElement>(opts.type, opts),
|
||||
points: [],
|
||||
|
|
|
@ -3,7 +3,11 @@ import { SHIFT_LOCKING_ANGLE } from "../constants";
|
|||
import { getSelectedElements, globalSceneState } from "../scene";
|
||||
import { rescalePoints } from "../points";
|
||||
import { rotate, adjustXYWithRotation } from "../math";
|
||||
import { ExcalidrawElement, ExcalidrawLinearElement } from "./types";
|
||||
import {
|
||||
ExcalidrawLinearElement,
|
||||
NonDeletedExcalidrawElement,
|
||||
NonDeleted,
|
||||
} from "./types";
|
||||
import { getElementAbsoluteCoords, getCommonBounds } from "./bounds";
|
||||
import { isLinearElement } from "./typeChecks";
|
||||
import { mutateElement } from "./mutateElement";
|
||||
|
@ -17,7 +21,7 @@ import {
|
|||
type ResizeTestType = ReturnType<typeof resizeTest>;
|
||||
|
||||
export type ResizeArrowFnType = (
|
||||
element: ExcalidrawLinearElement,
|
||||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
pointIndex: number,
|
||||
deltaX: number,
|
||||
deltaY: number,
|
||||
|
@ -27,13 +31,13 @@ export type ResizeArrowFnType = (
|
|||
) => void;
|
||||
|
||||
const arrowResizeOrigin: ResizeArrowFnType = (
|
||||
element: ExcalidrawLinearElement,
|
||||
pointIndex: number,
|
||||
deltaX: number,
|
||||
deltaY: number,
|
||||
pointerX: number,
|
||||
pointerY: number,
|
||||
perfect: boolean,
|
||||
element,
|
||||
pointIndex,
|
||||
deltaX,
|
||||
deltaY,
|
||||
pointerX,
|
||||
pointerY,
|
||||
perfect,
|
||||
) => {
|
||||
const [px, py] = element.points[pointIndex];
|
||||
let x = element.x + deltaX;
|
||||
|
@ -63,13 +67,13 @@ const arrowResizeOrigin: ResizeArrowFnType = (
|
|||
};
|
||||
|
||||
const arrowResizeEnd: ResizeArrowFnType = (
|
||||
element: ExcalidrawLinearElement,
|
||||
pointIndex: number,
|
||||
deltaX: number,
|
||||
deltaY: number,
|
||||
pointerX: number,
|
||||
pointerY: number,
|
||||
perfect: boolean,
|
||||
element,
|
||||
pointIndex,
|
||||
deltaX,
|
||||
deltaY,
|
||||
pointerX,
|
||||
pointerY,
|
||||
perfect,
|
||||
) => {
|
||||
const [px, py] = element.points[pointIndex];
|
||||
if (perfect) {
|
||||
|
@ -110,7 +114,7 @@ export function resizeElements(
|
|||
isRotating: resizeHandle === "rotation",
|
||||
});
|
||||
const selectedElements = getSelectedElements(
|
||||
globalSceneState.getAllElements(),
|
||||
globalSceneState.getElements(),
|
||||
appState,
|
||||
);
|
||||
if (selectedElements.length === 1) {
|
||||
|
@ -451,7 +455,7 @@ export function resizeElements(
|
|||
}
|
||||
|
||||
export function canResizeMutlipleElements(
|
||||
elements: readonly ExcalidrawElement[],
|
||||
elements: readonly NonDeletedExcalidrawElement[],
|
||||
) {
|
||||
return elements.every((element) =>
|
||||
["rectangle", "diamond", "ellipse"].includes(element.type),
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
import { ExcalidrawElement, PointerType } from "./types";
|
||||
import {
|
||||
ExcalidrawElement,
|
||||
PointerType,
|
||||
NonDeletedExcalidrawElement,
|
||||
} from "./types";
|
||||
|
||||
import {
|
||||
OMIT_SIDES_FOR_MULTIPLE_ELEMENTS,
|
||||
|
@ -24,7 +28,7 @@ function isInHandlerRect(
|
|||
}
|
||||
|
||||
export function resizeTest(
|
||||
element: ExcalidrawElement,
|
||||
element: NonDeletedExcalidrawElement,
|
||||
appState: AppState,
|
||||
x: number,
|
||||
y: number,
|
||||
|
@ -66,7 +70,7 @@ export function resizeTest(
|
|||
}
|
||||
|
||||
export function getElementWithResizeHandler(
|
||||
elements: readonly ExcalidrawElement[],
|
||||
elements: readonly NonDeletedExcalidrawElement[],
|
||||
appState: AppState,
|
||||
{ x, y }: { x: number; y: number },
|
||||
zoom: number,
|
||||
|
@ -78,7 +82,7 @@ export function getElementWithResizeHandler(
|
|||
}
|
||||
const resizeHandle = resizeTest(element, appState, x, y, zoom, pointerType);
|
||||
return resizeHandle ? { element, resizeHandle } : null;
|
||||
}, null as { element: ExcalidrawElement; resizeHandle: ReturnType<typeof resizeTest> } | null);
|
||||
}, null as { element: NonDeletedExcalidrawElement; resizeHandle: ReturnType<typeof resizeTest> } | null);
|
||||
}
|
||||
|
||||
export function getResizeHandlerFromCoords(
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { AppState } from "../types";
|
||||
import { ExcalidrawElement } from "./types";
|
||||
import { NonDeletedExcalidrawElement } from "./types";
|
||||
import { getSelectedElements } from "../scene";
|
||||
|
||||
export const showSelectedShapeActions = (
|
||||
appState: AppState,
|
||||
elements: readonly ExcalidrawElement[],
|
||||
elements: readonly NonDeletedExcalidrawElement[],
|
||||
) =>
|
||||
Boolean(
|
||||
appState.editingElement ||
|
||||
|
|
|
@ -33,6 +33,12 @@ export type ExcalidrawElement =
|
|||
| ExcalidrawTextElement
|
||||
| ExcalidrawLinearElement;
|
||||
|
||||
export type NonDeleted<TElement extends ExcalidrawElement> = TElement & {
|
||||
isDeleted: false;
|
||||
};
|
||||
|
||||
export type NonDeletedExcalidrawElement = NonDeleted<ExcalidrawElement>;
|
||||
|
||||
export type ExcalidrawTextElement = _ExcalidrawElementBase &
|
||||
Readonly<{
|
||||
type: "text";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue