mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
Expose scene.mutateElement and use original mutateElement
This commit is contained in:
parent
11600ee6a6
commit
2e4ca2d11a
44 changed files with 249 additions and 260 deletions
|
@ -20,7 +20,7 @@ import {
|
|||
import { getSelectedElements } from "@excalidraw/element/selection";
|
||||
|
||||
import {
|
||||
mutateElementWith,
|
||||
mutateElement,
|
||||
type ElementUpdate,
|
||||
} from "@excalidraw/element/mutateElement";
|
||||
|
||||
|
@ -424,23 +424,22 @@ class Scene {
|
|||
return getElementsInGroup(elementsMap, id);
|
||||
};
|
||||
|
||||
// TODO_SCENE: should be accessed as app.scene through the API
|
||||
// TODO_SCENE: inform mutation false is the new default, meaning all mutateElement with nothing should likely use scene instead
|
||||
// Mutate an element with passed updates and trigger the component to update. Make sure you
|
||||
// are calling it either from a React event handler or within unstable_batchedUpdates().
|
||||
mutate<TElement extends Mutable<ExcalidrawElement>>(
|
||||
mutateElement<TElement extends Mutable<ExcalidrawElement>>(
|
||||
element: TElement,
|
||||
updates: ElementUpdate<TElement>,
|
||||
options: {
|
||||
informMutation?: boolean;
|
||||
isDragging?: boolean;
|
||||
informMutation: boolean;
|
||||
isDragging: boolean;
|
||||
} = {
|
||||
informMutation: true,
|
||||
isDragging: false,
|
||||
},
|
||||
) {
|
||||
const elementsMap = this.getNonDeletedElementsMap();
|
||||
|
||||
mutateElementWith(element, elementsMap, updates, options);
|
||||
mutateElement(element, elementsMap, updates, options);
|
||||
|
||||
if (options.informMutation) {
|
||||
this.triggerUpdate();
|
||||
|
|
|
@ -32,7 +32,7 @@ export const alignElements = (
|
|||
);
|
||||
return group.map((element) => {
|
||||
// update element
|
||||
const updatedEle = scene.mutate(element, {
|
||||
const updatedEle = scene.mutateElement(element, {
|
||||
x: element.x + translation.x,
|
||||
y: element.y + translation.y,
|
||||
});
|
||||
|
|
|
@ -48,7 +48,7 @@ import {
|
|||
type Heading,
|
||||
} from "./heading";
|
||||
import { LinearElementEditor } from "./linearElementEditor";
|
||||
import { mutateElementWith } from "./mutateElement";
|
||||
import { mutateElement } from "./mutateElement";
|
||||
import { getBoundTextElement, handleBindTextResize } from "./textElement";
|
||||
import {
|
||||
isArrowElement,
|
||||
|
@ -157,7 +157,7 @@ export const bindOrUnbindLinearElement = (
|
|||
);
|
||||
|
||||
getNonDeletedElements(scene, onlyUnbound).forEach((element) => {
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
boundElements: element.boundElements?.filter(
|
||||
(element) =>
|
||||
element.type !== "arrow" || element.id !== linearElement.id,
|
||||
|
@ -509,13 +509,13 @@ export const bindLinearElement = (
|
|||
};
|
||||
}
|
||||
|
||||
scene.mutate(linearElement, {
|
||||
scene.mutateElement(linearElement, {
|
||||
[startOrEnd === "start" ? "startBinding" : "endBinding"]: binding,
|
||||
});
|
||||
|
||||
const boundElementsMap = arrayToMap(hoveredElement.boundElements || []);
|
||||
if (!boundElementsMap.has(linearElement.id)) {
|
||||
scene.mutate(hoveredElement, {
|
||||
scene.mutateElement(hoveredElement, {
|
||||
boundElements: (hoveredElement.boundElements || []).concat({
|
||||
id: linearElement.id,
|
||||
type: "arrow",
|
||||
|
@ -564,7 +564,7 @@ const unbindLinearElement = (
|
|||
if (binding == null) {
|
||||
return null;
|
||||
}
|
||||
scene.mutate(linearElement, { [field]: null });
|
||||
scene.mutateElement(linearElement, { [field]: null });
|
||||
return binding.elementId;
|
||||
};
|
||||
|
||||
|
@ -790,7 +790,7 @@ export const updateBoundElements = (
|
|||
|
||||
// `linearElement` is being moved/scaled already, just update the binding
|
||||
if (simultaneouslyUpdatedElementIds.has(element.id)) {
|
||||
mutateElementWith(element, elementsMap, bindings);
|
||||
scene.mutateElement(element, bindings);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1499,7 +1499,7 @@ const fixReversedBindingsForBindables = (
|
|||
(el) => el.id === newArrowId,
|
||||
)! as ExcalidrawArrowElement;
|
||||
|
||||
mutateElementWith(newArrow, originalElements, {
|
||||
mutateElement(newArrow, originalElements, {
|
||||
startBinding:
|
||||
oldArrow.startBinding?.elementId === binding.id
|
||||
? {
|
||||
|
@ -1515,7 +1515,7 @@ const fixReversedBindingsForBindables = (
|
|||
}
|
||||
: newArrow.endBinding,
|
||||
});
|
||||
mutateElementWith(duplicate, originalElements, {
|
||||
mutateElement(duplicate, originalElements, {
|
||||
boundElements: [
|
||||
...(duplicate.boundElements ?? []).filter(
|
||||
(el) => el.id !== binding.id && el.id !== newArrowId,
|
||||
|
@ -1529,7 +1529,7 @@ const fixReversedBindingsForBindables = (
|
|||
} else {
|
||||
// Linked arrow is outside the selection,
|
||||
// so we move the binding to the duplicate
|
||||
mutateElementWith(oldArrow, originalElements, {
|
||||
mutateElement(oldArrow, originalElements, {
|
||||
startBinding:
|
||||
oldArrow.startBinding?.elementId === original.id
|
||||
? {
|
||||
|
@ -1545,7 +1545,7 @@ const fixReversedBindingsForBindables = (
|
|||
}
|
||||
: oldArrow.endBinding,
|
||||
});
|
||||
mutateElementWith(duplicate, originalElements, {
|
||||
mutateElement(duplicate, originalElements, {
|
||||
boundElements: [
|
||||
...(duplicate.boundElements ?? []),
|
||||
{
|
||||
|
@ -1554,7 +1554,7 @@ const fixReversedBindingsForBindables = (
|
|||
},
|
||||
],
|
||||
});
|
||||
mutateElementWith(original, originalElements, {
|
||||
mutateElement(original, originalElements, {
|
||||
boundElements:
|
||||
original.boundElements?.filter((_, i) => i !== idx) ?? null,
|
||||
});
|
||||
|
@ -1580,13 +1580,13 @@ const fixReversedBindingsForArrows = (
|
|||
const newBindable = elementsWithClones.find(
|
||||
(el) => el.id === newBindableId,
|
||||
) as ExcalidrawBindableElement;
|
||||
mutateElementWith(duplicate, originalElements, {
|
||||
mutateElement(duplicate, originalElements, {
|
||||
[bindingProp]: {
|
||||
...original[bindingProp],
|
||||
elementId: newBindableId,
|
||||
},
|
||||
});
|
||||
mutateElementWith(newBindable, originalElements, {
|
||||
mutateElement(newBindable, originalElements, {
|
||||
boundElements: [
|
||||
...(newBindable.boundElements ?? []).filter(
|
||||
(el) => el.id !== original.id && el.id !== duplicate.id,
|
||||
|
@ -1603,13 +1603,13 @@ const fixReversedBindingsForArrows = (
|
|||
(el) => el.id === oldBindableId,
|
||||
);
|
||||
if (originalBindable) {
|
||||
mutateElementWith(duplicate, originalElements, {
|
||||
mutateElement(duplicate, originalElements, {
|
||||
[bindingProp]: original[bindingProp],
|
||||
});
|
||||
mutateElementWith(original, originalElements, {
|
||||
mutateElement(original, originalElements, {
|
||||
[bindingProp]: null,
|
||||
});
|
||||
mutateElementWith(originalBindable, originalElements, {
|
||||
mutateElement(originalBindable, originalElements, {
|
||||
boundElements: [
|
||||
...(originalBindable.boundElements?.filter(
|
||||
(el) => el.id !== original.id,
|
||||
|
@ -1672,10 +1672,10 @@ export const fixBindingsAfterDeletion = (
|
|||
|
||||
for (const element of deletedElements) {
|
||||
BoundElement.unbindAffected(elements, element, (element, updates) =>
|
||||
mutateElementWith(element, elements, updates),
|
||||
mutateElement(element, elements, updates),
|
||||
);
|
||||
BindableElement.unbindAffected(elements, element, (element, updates) =>
|
||||
mutateElementWith(element, elements, updates),
|
||||
mutateElement(element, elements, updates),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -168,7 +168,7 @@ const updateElementCoords = (
|
|||
const nextX = originalElement.x + dragOffset.x;
|
||||
const nextY = originalElement.y + dragOffset.y;
|
||||
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
x: nextX,
|
||||
y: nextY,
|
||||
});
|
||||
|
@ -292,7 +292,7 @@ export const dragNewElement = ({
|
|||
};
|
||||
}
|
||||
|
||||
scene.mutate(
|
||||
scene.mutateElement(
|
||||
newElement,
|
||||
{
|
||||
x: newX + (originOffset?.x ?? 0),
|
||||
|
@ -302,7 +302,7 @@ export const dragNewElement = ({
|
|||
...textAutoResize,
|
||||
...imageInitialDimension,
|
||||
},
|
||||
{ informMutation },
|
||||
{ informMutation, isDragging: false },
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -46,7 +46,7 @@ import {
|
|||
headingForPoint,
|
||||
} from "./heading";
|
||||
import { type ElementUpdate } from "./mutateElement";
|
||||
import { isBindableElement, isElbowArrow } from "./typeChecks";
|
||||
import { isBindableElement } from "./typeChecks";
|
||||
import {
|
||||
type ExcalidrawElbowArrowElement,
|
||||
type NonDeletedSceneElementsMap,
|
||||
|
@ -60,7 +60,6 @@ import type {
|
|||
Arrowhead,
|
||||
ElementsMap,
|
||||
ExcalidrawBindableElement,
|
||||
ExcalidrawElement,
|
||||
FixedPointBinding,
|
||||
FixedSegment,
|
||||
NonDeletedExcalidrawElement,
|
||||
|
@ -879,27 +878,6 @@ const handleEndpointDrag = (
|
|||
|
||||
const MAX_POS = 1e6;
|
||||
|
||||
export const elbowArrowNeedsToGetNormalized = (
|
||||
element: Readonly<ExcalidrawElement>,
|
||||
updates: {
|
||||
points?: readonly LocalPoint[];
|
||||
fixedSegments?: readonly FixedSegment[] | null;
|
||||
startBinding?: FixedPointBinding | null;
|
||||
endBinding?: FixedPointBinding | null;
|
||||
},
|
||||
) => {
|
||||
const { points, fixedSegments, startBinding, endBinding } = updates;
|
||||
|
||||
return (
|
||||
isElbowArrow(element) &&
|
||||
(Object.keys(updates).length === 0 || // normalization case
|
||||
typeof points !== "undefined" || // repositioning
|
||||
typeof fixedSegments !== "undefined" || // segment fixing
|
||||
typeof startBinding !== "undefined" ||
|
||||
typeof endBinding !== "undefined") // manual binding to element
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -19,7 +19,7 @@ import {
|
|||
type Heading,
|
||||
} from "./heading";
|
||||
import { LinearElementEditor } from "./linearElementEditor";
|
||||
import { mutateElementWith } from "./mutateElement";
|
||||
import { mutateElement } from "./mutateElement";
|
||||
import { newArrowElement, newElement } from "./newElement";
|
||||
import { aabbForElement } from "./shapes";
|
||||
import { elementsAreInFrameBounds, elementOverlapsWithFrame } from "./frame";
|
||||
|
@ -678,7 +678,7 @@ export class FlowChartCreator {
|
|||
)
|
||||
) {
|
||||
this.pendingNodes = this.pendingNodes.map((node) =>
|
||||
mutateElementWith(node, elementsMap, {
|
||||
mutateElement(node, elementsMap, {
|
||||
frameId: startNode.frameId,
|
||||
}),
|
||||
);
|
||||
|
|
|
@ -2,7 +2,7 @@ import { generateNKeysBetween } from "fractional-indexing";
|
|||
|
||||
import { arrayToMap } from "@excalidraw/common";
|
||||
|
||||
import { mutateElementWith } from "./mutateElement";
|
||||
import { mutateElement } from "./mutateElement";
|
||||
import { getBoundTextElement } from "./textElement";
|
||||
import { hasBoundTextElement } from "./typeChecks";
|
||||
|
||||
|
@ -177,7 +177,7 @@ export const syncMovedIndices = (
|
|||
|
||||
// split mutation so we don't end up in an incosistent state
|
||||
for (const [element, update] of elementsUpdates) {
|
||||
mutateElementWith(element, arrayToMap(elements), update);
|
||||
mutateElement(element, arrayToMap(elements), update);
|
||||
}
|
||||
} catch (e) {
|
||||
// fallback to default sync
|
||||
|
@ -198,7 +198,7 @@ export const syncInvalidIndices = (
|
|||
const indicesGroups = getInvalidIndicesGroups(elements);
|
||||
const elementsUpdates = generateIndices(elements, indicesGroups);
|
||||
for (const [element, update] of elementsUpdates) {
|
||||
mutateElementWith(element, arrayToMap(elements), update);
|
||||
mutateElement(element, arrayToMap(elements), update);
|
||||
}
|
||||
|
||||
return elements as OrderedExcalidrawElement[];
|
||||
|
|
|
@ -19,7 +19,7 @@ import {
|
|||
getCommonBounds,
|
||||
getElementAbsoluteCoords,
|
||||
} from "./bounds";
|
||||
import { mutateElementWith } from "./mutateElement";
|
||||
import { mutateElement } from "./mutateElement";
|
||||
import { getBoundTextElement, getContainerElement } from "./textElement";
|
||||
import {
|
||||
isFrameElement,
|
||||
|
@ -57,7 +57,7 @@ export const bindElementsToFramesAfterDuplication = (
|
|||
if (nextElementId) {
|
||||
const nextElement = nextElementMap.get(nextElementId);
|
||||
if (nextElement) {
|
||||
mutateElementWith(nextElement, nextElementMap, {
|
||||
mutateElement(nextElement, nextElementMap, {
|
||||
frameId: nextFrameId ?? element.frameId,
|
||||
});
|
||||
}
|
||||
|
@ -563,7 +563,7 @@ export const addElementsToFrame = <T extends ElementsMapOrArray>(
|
|||
}
|
||||
|
||||
for (const element of finalElementsToAdd) {
|
||||
mutateElementWith(element, elementsMap, {
|
||||
mutateElement(element, elementsMap, {
|
||||
frameId: frame.id,
|
||||
});
|
||||
}
|
||||
|
@ -603,7 +603,7 @@ export const removeElementsFromFrame = (
|
|||
}
|
||||
|
||||
for (const [, element] of _elementsToRemove) {
|
||||
mutateElementWith(element, elementsMap, {
|
||||
mutateElement(element, elementsMap, {
|
||||
frameId: null,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ import {
|
|||
} from "./bounds";
|
||||
|
||||
import { headingIsHorizontal, vectorToHeading } from "./heading";
|
||||
import { mutateElementWith } from "./mutateElement";
|
||||
import { mutateElement } from "./mutateElement";
|
||||
import { getBoundTextElement, handleBindTextResize } from "./textElement";
|
||||
import {
|
||||
isBindingElement,
|
||||
|
@ -793,7 +793,7 @@ export class LinearElementEditor {
|
|||
);
|
||||
} else if (event.altKey && appState.editingLinearElement) {
|
||||
if (linearElementEditor.lastUncommittedPoint == null) {
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
points: [
|
||||
...element.points,
|
||||
LinearElementEditor.createPointAt(
|
||||
|
@ -1165,7 +1165,7 @@ export class LinearElementEditor {
|
|||
element: NonDeleted<ExcalidrawLinearElement>,
|
||||
elementsMap: ElementsMap,
|
||||
) {
|
||||
mutateElementWith(
|
||||
mutateElement(
|
||||
element,
|
||||
elementsMap,
|
||||
LinearElementEditor.getNormalizedPoints(element),
|
||||
|
@ -1221,7 +1221,7 @@ export class LinearElementEditor {
|
|||
return acc;
|
||||
}, []);
|
||||
|
||||
scene.mutate(element, { points: nextPoints });
|
||||
scene.mutateElement(element, { points: nextPoints });
|
||||
|
||||
// temp hack to ensure the line doesn't move when adding point to the end,
|
||||
// potentially expanding the bounding box
|
||||
|
@ -1442,7 +1442,7 @@ export class LinearElementEditor {
|
|||
...element.points.slice(segmentMidpoint.index!),
|
||||
];
|
||||
|
||||
scene.mutate(element, { points });
|
||||
scene.mutateElement(element, { points });
|
||||
|
||||
ret.pointerDownState = {
|
||||
...linearElementEditor.pointerDownState,
|
||||
|
@ -1495,8 +1495,9 @@ export class LinearElementEditor {
|
|||
|
||||
updates.points = Array.from(nextPoints);
|
||||
|
||||
scene.mutate(element, updates, {
|
||||
isDragging: options?.isDragging,
|
||||
scene.mutateElement(element, updates, {
|
||||
informMutation: true,
|
||||
isDragging: options?.isDragging ?? false,
|
||||
});
|
||||
} else {
|
||||
const nextCoords = getElementPointsCoords(element, nextPoints);
|
||||
|
@ -1512,7 +1513,7 @@ export class LinearElementEditor {
|
|||
pointFrom(dX, dY),
|
||||
element.angle,
|
||||
);
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
...otherUpdates,
|
||||
points: nextPoints,
|
||||
x: element.x + rotated[0],
|
||||
|
@ -1571,7 +1572,7 @@ export class LinearElementEditor {
|
|||
elementsMap,
|
||||
);
|
||||
if (points.length < 2) {
|
||||
mutateElementWith(boundTextElement, elementsMap, { isDeleted: true });
|
||||
mutateElement(boundTextElement, elementsMap, { isDeleted: true });
|
||||
}
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
|
@ -1823,7 +1824,7 @@ export class LinearElementEditor {
|
|||
.map((segment) => segment.index)
|
||||
.reduce((count, idx) => (idx < index ? count + 1 : count), 0);
|
||||
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
fixedSegments: nextFixedSegments,
|
||||
});
|
||||
|
||||
|
@ -1860,7 +1861,7 @@ export class LinearElementEditor {
|
|||
scene: Scene,
|
||||
index: number,
|
||||
): void {
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
fixedSegments: element.fixedSegments?.filter(
|
||||
(segment) => segment.index !== index,
|
||||
),
|
||||
|
|
|
@ -10,12 +10,12 @@ import type { Mutable } from "@excalidraw/common/utility-types";
|
|||
|
||||
import { ShapeCache } from "./ShapeCache";
|
||||
|
||||
import {
|
||||
elbowArrowNeedsToGetNormalized,
|
||||
updateElbowArrowPoints,
|
||||
} from "./elbowArrow";
|
||||
import { updateElbowArrowPoints } from "./elbowArrow";
|
||||
|
||||
import { isElbowArrow } from "./typeChecks";
|
||||
|
||||
import type {
|
||||
ElementsMap,
|
||||
ExcalidrawElbowArrowElement,
|
||||
ExcalidrawElement,
|
||||
NonDeletedSceneElementsMap,
|
||||
|
@ -26,24 +26,38 @@ export type ElementUpdate<TElement extends ExcalidrawElement> = Omit<
|
|||
"id" | "version" | "versionNonce" | "updated"
|
||||
>;
|
||||
|
||||
// This function tracks updates of text elements for the purposes for collaboration.
|
||||
// The version is used to compare updates when more than one user is working in
|
||||
// the same drawing. Note: this won't trigger the component to update, unlike `scene.mutate`.
|
||||
export const mutateElementWith = <TElement extends Mutable<ExcalidrawElement>>(
|
||||
/**
|
||||
* This function tracks updates of text elements for the purposes for collaboration.
|
||||
* The version is used to compare updates when more than one user is working in
|
||||
* the same drawing.
|
||||
*
|
||||
* WARNING: this won't trigger the component to update, so if you need to trigger component update,
|
||||
* use `scene.mutateElement` or `ExcalidrawImperativeAPI.mutateElement` instead.
|
||||
*/
|
||||
export const mutateElement = <TElement extends Mutable<ExcalidrawElement>>(
|
||||
element: TElement,
|
||||
elementsMap: Map<string, ExcalidrawElement>,
|
||||
elementsMap: ElementsMap,
|
||||
updates: ElementUpdate<TElement>,
|
||||
options?: {
|
||||
isDragging?: boolean;
|
||||
},
|
||||
) => {
|
||||
let didChange = false;
|
||||
|
||||
// casting to any because can't use `in` operator
|
||||
// (see https://github.com/microsoft/TypeScript/issues/21732)
|
||||
const { points, fixedSegments, startBinding, endBinding, fileId } =
|
||||
updates as any;
|
||||
|
||||
if (
|
||||
elbowArrowNeedsToGetNormalized(
|
||||
element,
|
||||
updates as ElementUpdate<ExcalidrawElbowArrowElement>,
|
||||
)
|
||||
isElbowArrow(element) &&
|
||||
(Object.keys(updates).length === 0 || // normalization case
|
||||
typeof points !== "undefined" || // repositioning
|
||||
typeof fixedSegments !== "undefined" || // segment fixing
|
||||
typeof startBinding !== "undefined" ||
|
||||
typeof endBinding !== "undefined") // manual binding to element
|
||||
) {
|
||||
const normalizedUpdates = {
|
||||
updates = {
|
||||
...updates,
|
||||
angle: 0 as Radians,
|
||||
...updateElbowArrowPoints(
|
||||
|
@ -52,35 +66,8 @@ export const mutateElementWith = <TElement extends Mutable<ExcalidrawElement>>(
|
|||
updates as ElementUpdate<ExcalidrawElbowArrowElement>,
|
||||
options,
|
||||
),
|
||||
} as ElementUpdate<ExcalidrawElbowArrowElement>;
|
||||
|
||||
return mutateElement(
|
||||
element as ExcalidrawElbowArrowElement,
|
||||
normalizedUpdates,
|
||||
);
|
||||
}
|
||||
|
||||
return mutateElement(element, updates);
|
||||
};
|
||||
|
||||
/**
|
||||
* This function tracks updates of text elements for the purposes for collaboration.
|
||||
* The version is used to compare updates when more than one user is working in
|
||||
* the same drawing.
|
||||
*
|
||||
* @deprecated Use `scene.mutate` as direct equivalent, or `mutateElementWith` in case you don't need to trigger component update.
|
||||
*/
|
||||
export const mutateElement = <TElement extends Mutable<ExcalidrawElement>>(
|
||||
element: TElement,
|
||||
updates: ElementUpdate<TElement>,
|
||||
): TElement => {
|
||||
let didChange = false;
|
||||
|
||||
// casting to any because can't use `in` operator
|
||||
// (see https://github.com/microsoft/TypeScript/issues/21732)
|
||||
const { points, fileId } = updates as any;
|
||||
|
||||
if (typeof points !== "undefined") {
|
||||
};
|
||||
} else if (typeof points !== "undefined") {
|
||||
updates = { ...getSizeFromPoints(points), ...updates };
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ import {
|
|||
getElementBounds,
|
||||
} from "./bounds";
|
||||
import { LinearElementEditor } from "./linearElementEditor";
|
||||
import { mutateElementWith } from "./mutateElement";
|
||||
import {
|
||||
getBoundTextElement,
|
||||
getBoundTextElementId,
|
||||
|
@ -230,13 +229,13 @@ const rotateSingleElement = (
|
|||
}
|
||||
const boundTextElementId = getBoundTextElementId(element);
|
||||
|
||||
scene.mutate(element, { angle });
|
||||
scene.mutateElement(element, { angle });
|
||||
if (boundTextElementId) {
|
||||
const textElement =
|
||||
scene.getElement<ExcalidrawTextElementWithContainer>(boundTextElementId);
|
||||
|
||||
if (textElement && !isArrowElement(element)) {
|
||||
scene.mutate(textElement, { angle });
|
||||
scene.mutateElement(textElement, { angle });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -391,7 +390,7 @@ const resizeSingleTextElement = (
|
|||
);
|
||||
const [nextX, nextY] = newTopLeft;
|
||||
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
fontSize: metrics.size,
|
||||
width: nextWidth,
|
||||
height: nextHeight,
|
||||
|
@ -506,7 +505,7 @@ const resizeSingleTextElement = (
|
|||
autoResize: false,
|
||||
};
|
||||
|
||||
scene.mutate(element, resizedElement);
|
||||
scene.mutateElement(element, resizedElement);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -552,7 +551,7 @@ const rotateMultipleElements = (
|
|||
angle: normalizeRadians((centerAngle + origAngle) as Radians),
|
||||
};
|
||||
|
||||
scene.mutate(element, updates);
|
||||
scene.mutateElement(element, updates);
|
||||
|
||||
updateBoundElements(element, scene, {
|
||||
simultaneouslyUpdated: elements,
|
||||
|
@ -560,7 +559,7 @@ const rotateMultipleElements = (
|
|||
|
||||
const boundText = getBoundTextElement(element, elementsMap);
|
||||
if (boundText && !isArrowElement(element)) {
|
||||
mutateElementWith(boundText, elementsMap, {
|
||||
scene.mutateElement(boundText, {
|
||||
x: boundText.x + (rotatedCX - cx),
|
||||
y: boundText.y + (rotatedCY - cy),
|
||||
angle: normalizeRadians((centerAngle + origAngle) as Radians),
|
||||
|
@ -923,7 +922,7 @@ export const resizeSingleElement = (
|
|||
}
|
||||
|
||||
if ("scale" in latestElement && "scale" in origElement) {
|
||||
scene.mutate(latestElement, {
|
||||
scene.mutateElement(latestElement, {
|
||||
scale: [
|
||||
// defaulting because scaleX/Y can be 0/-0
|
||||
(Math.sign(nextWidth) || origElement.scale[0]) * origElement.scale[0],
|
||||
|
@ -958,8 +957,9 @@ export const resizeSingleElement = (
|
|||
...rescaledPoints,
|
||||
};
|
||||
|
||||
scene.mutate(latestElement, updates, {
|
||||
scene.mutateElement(latestElement, updates, {
|
||||
informMutation: shouldInformMutation,
|
||||
isDragging: false,
|
||||
});
|
||||
|
||||
updateBoundElements(latestElement, scene, {
|
||||
|
@ -968,7 +968,7 @@ export const resizeSingleElement = (
|
|||
});
|
||||
|
||||
if (boundTextElement && boundTextFont != null) {
|
||||
scene.mutate(boundTextElement, {
|
||||
scene.mutateElement(boundTextElement, {
|
||||
fontSize: boundTextFont.fontSize,
|
||||
});
|
||||
}
|
||||
|
@ -1518,7 +1518,8 @@ export const resizeMultipleElements = (
|
|||
} of elementsAndUpdates) {
|
||||
const { width, height, angle } = update;
|
||||
|
||||
scene.mutate(element, update, {
|
||||
scene.mutateElement(element, update, {
|
||||
informMutation: true,
|
||||
// needed for the fixed binding point udpate to take effect
|
||||
isDragging: true,
|
||||
});
|
||||
|
@ -1530,7 +1531,7 @@ export const resizeMultipleElements = (
|
|||
|
||||
const boundTextElement = getBoundTextElement(element, elementsMap);
|
||||
if (boundTextElement && boundTextFontSize) {
|
||||
scene.mutate(boundTextElement, {
|
||||
scene.mutateElement(boundTextElement, {
|
||||
fontSize: boundTextFontSize,
|
||||
angle: isLinearElement(element) ? undefined : angle,
|
||||
});
|
||||
|
|
|
@ -93,7 +93,7 @@ export const redrawTextBoundingBox = (
|
|||
metrics.height,
|
||||
container.type,
|
||||
);
|
||||
scene.mutate(container, { height: nextHeight });
|
||||
scene.mutateElement(container, { height: nextHeight });
|
||||
updateOriginalContainerCache(container.id, nextHeight);
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ export const redrawTextBoundingBox = (
|
|||
metrics.width,
|
||||
container.type,
|
||||
);
|
||||
scene.mutate(container, { width: nextWidth });
|
||||
scene.mutateElement(container, { width: nextWidth });
|
||||
}
|
||||
|
||||
const updatedTextElement = {
|
||||
|
@ -120,7 +120,7 @@ export const redrawTextBoundingBox = (
|
|||
boundTextUpdates.y = y;
|
||||
}
|
||||
|
||||
scene.mutate(textElement, boundTextUpdates);
|
||||
scene.mutateElement(textElement, boundTextUpdates);
|
||||
};
|
||||
|
||||
export const handleBindTextResize = (
|
||||
|
@ -182,20 +182,20 @@ export const handleBindTextResize = (
|
|||
transformHandleType === "n")
|
||||
? container.y - diff
|
||||
: container.y;
|
||||
scene.mutate(container, {
|
||||
scene.mutateElement(container, {
|
||||
height: containerHeight,
|
||||
y: updatedY,
|
||||
});
|
||||
}
|
||||
|
||||
scene.mutate(textElement, {
|
||||
scene.mutateElement(textElement, {
|
||||
text,
|
||||
width: nextWidth,
|
||||
height: nextHeight,
|
||||
});
|
||||
|
||||
if (!isArrowElement(container)) {
|
||||
scene.mutate(
|
||||
scene.mutateElement(
|
||||
textElement,
|
||||
computeBoundTextPosition(container, textElement, elementsMap),
|
||||
);
|
||||
|
|
|
@ -62,7 +62,7 @@ describe("duplicating single elements", () => {
|
|||
// @ts-ignore
|
||||
element.__proto__ = { hello: "world" };
|
||||
|
||||
h.app.scene.mutate(element, {
|
||||
h.app.scene.mutateElement(element, {
|
||||
points: [pointFrom<LocalPoint>(1, 2), pointFrom<LocalPoint>(3, 4)],
|
||||
});
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ describe("elbow arrow routing", () => {
|
|||
elbowed: true,
|
||||
}) as ExcalidrawElbowArrowElement;
|
||||
scene.insertElement(arrow);
|
||||
h.app.scene.mutate(arrow, {
|
||||
h.app.scene.mutateElement(arrow, {
|
||||
points: [
|
||||
pointFrom<LocalPoint>(-45 - arrow.x, -100.1 - arrow.y),
|
||||
pointFrom<LocalPoint>(45 - arrow.x, 99.9 - arrow.y),
|
||||
|
@ -195,7 +195,7 @@ describe("elbow arrow routing", () => {
|
|||
expect(arrow.startBinding).not.toBe(null);
|
||||
expect(arrow.endBinding).not.toBe(null);
|
||||
|
||||
h.app.scene.mutate(arrow, {
|
||||
h.app.scene.mutateElement(arrow, {
|
||||
points: [pointFrom<LocalPoint>(0, 0), pointFrom<LocalPoint>(90, 200)],
|
||||
});
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ describe("normalizeElementsOrder", () => {
|
|||
boundElements: [],
|
||||
});
|
||||
|
||||
h.app.scene.mutate(container, {
|
||||
h.app.scene.mutateElement(container, {
|
||||
boundElements: [{ type: "text", id: boundText.id }],
|
||||
});
|
||||
|
||||
|
@ -352,7 +352,7 @@ describe("normalizeElementsOrder", () => {
|
|||
containerId: container.id,
|
||||
});
|
||||
|
||||
h.app.scene.mutate(container, {
|
||||
h.app.scene.mutateElement(container, {
|
||||
boundElements: [
|
||||
{ type: "text", id: boundText.id },
|
||||
{ type: "text", id: "xxx" },
|
||||
|
@ -387,7 +387,7 @@ describe("normalizeElementsOrder", () => {
|
|||
boundElements: [],
|
||||
groupIds: ["C", "A"],
|
||||
});
|
||||
h.app.scene.mutate(container, {
|
||||
h.app.scene.mutateElement(container, {
|
||||
boundElements: [{ type: "text", id: boundText.id }],
|
||||
});
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ export const actionUnbindText = register({
|
|||
boundTextElement,
|
||||
elementsMap,
|
||||
);
|
||||
app.scene.mutate(boundTextElement as ExcalidrawTextElement, {
|
||||
app.scene.mutateElement(boundTextElement as ExcalidrawTextElement, {
|
||||
containerId: null,
|
||||
width,
|
||||
height,
|
||||
|
@ -84,7 +84,7 @@ export const actionUnbindText = register({
|
|||
x,
|
||||
y,
|
||||
});
|
||||
app.scene.mutate(element, {
|
||||
app.scene.mutateElement(element, {
|
||||
boundElements: element.boundElements?.filter(
|
||||
(ele) => ele.id !== boundTextElement.id,
|
||||
),
|
||||
|
@ -149,13 +149,13 @@ export const actionBindText = register({
|
|||
textElement = selectedElements[1] as ExcalidrawTextElement;
|
||||
container = selectedElements[0] as ExcalidrawTextContainer;
|
||||
}
|
||||
app.scene.mutate(textElement, {
|
||||
app.scene.mutateElement(textElement, {
|
||||
containerId: container.id,
|
||||
verticalAlign: VERTICAL_ALIGN.MIDDLE,
|
||||
textAlign: TEXT_ALIGN.CENTER,
|
||||
autoResize: true,
|
||||
});
|
||||
app.scene.mutate(container, {
|
||||
app.scene.mutateElement(container, {
|
||||
boundElements: (container.boundElements || []).concat({
|
||||
type: "text",
|
||||
id: textElement.id,
|
||||
|
@ -292,7 +292,7 @@ export const actionWrapTextInContainer = register({
|
|||
}
|
||||
|
||||
if (startBinding || endBinding) {
|
||||
app.scene.mutate(ele, {
|
||||
app.scene.mutateElement(ele, {
|
||||
startBinding,
|
||||
endBinding,
|
||||
});
|
||||
|
@ -300,7 +300,7 @@ export const actionWrapTextInContainer = register({
|
|||
});
|
||||
}
|
||||
|
||||
app.scene.mutate(textElement, {
|
||||
app.scene.mutateElement(textElement, {
|
||||
containerId: container.id,
|
||||
verticalAlign: VERTICAL_ALIGN.MIDDLE,
|
||||
boundElements: null,
|
||||
|
|
|
@ -56,7 +56,7 @@ describe("deleting selected elements when frame selected should keep children +
|
|||
frameId: f1.id,
|
||||
});
|
||||
|
||||
h.app.scene.mutate(r1, {
|
||||
h.app.scene.mutateElement(r1, {
|
||||
boundElements: [{ type: "text", id: t1.id }],
|
||||
});
|
||||
|
||||
|
@ -94,7 +94,7 @@ describe("deleting selected elements when frame selected should keep children +
|
|||
frameId: null,
|
||||
});
|
||||
|
||||
h.app.scene.mutate(r1, {
|
||||
h.app.scene.mutateElement(r1, {
|
||||
boundElements: [{ type: "text", id: t1.id }],
|
||||
});
|
||||
|
||||
|
@ -132,7 +132,7 @@ describe("deleting selected elements when frame selected should keep children +
|
|||
frameId: null,
|
||||
});
|
||||
|
||||
h.app.scene.mutate(r1, {
|
||||
h.app.scene.mutateElement(r1, {
|
||||
boundElements: [{ type: "text", id: t1.id }],
|
||||
});
|
||||
|
||||
|
@ -170,7 +170,7 @@ describe("deleting selected elements when frame selected should keep children +
|
|||
frameId: null,
|
||||
});
|
||||
|
||||
h.app.scene.mutate(a1, {
|
||||
h.app.scene.mutateElement(a1, {
|
||||
boundElements: [{ type: "text", id: t1.id }],
|
||||
});
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ const deleteSelectedElements = (
|
|||
el.boundElements.forEach((candidate) => {
|
||||
const bound = app.scene.getNonDeletedElementsMap().get(candidate.id);
|
||||
if (bound && isElbowArrow(bound)) {
|
||||
app.scene.mutate(bound, {
|
||||
app.scene.mutateElement(bound, {
|
||||
startBinding:
|
||||
el.id === bound.startBinding?.elementId
|
||||
? null
|
||||
|
|
|
@ -71,10 +71,10 @@ export const actionFinalize = register({
|
|||
scene.getElement(appState.pendingImageElementId);
|
||||
|
||||
if (pendingImageElement) {
|
||||
scene.mutate(
|
||||
scene.mutateElement(
|
||||
pendingImageElement,
|
||||
{ isDeleted: true },
|
||||
{ informMutation: false },
|
||||
{ informMutation: false, isDragging: false },
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ export const actionFinalize = register({
|
|||
!lastCommittedPoint ||
|
||||
points[points.length - 1] !== lastCommittedPoint
|
||||
) {
|
||||
scene.mutate(multiPointElement, {
|
||||
scene.mutateElement(multiPointElement, {
|
||||
points: multiPointElement.points.slice(0, -1),
|
||||
});
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ export const actionFinalize = register({
|
|||
if (isLoop) {
|
||||
const linePoints = multiPointElement.points;
|
||||
const firstPoint = linePoints[0];
|
||||
scene.mutate(multiPointElement, {
|
||||
scene.mutateElement(multiPointElement, {
|
||||
points: linePoints.map((p, index) =>
|
||||
index === linePoints.length - 1
|
||||
? pointFrom(firstPoint[0], firstPoint[1])
|
||||
|
|
|
@ -189,13 +189,13 @@ const flipElements = (
|
|||
getCommonBoundingBox(selectedElements);
|
||||
const [diffX, diffY] = [midX - newMidX, midY - newMidY];
|
||||
otherElements.forEach((element) =>
|
||||
app.scene.mutate(element, {
|
||||
app.scene.mutateElement(element, {
|
||||
x: element.x + diffX,
|
||||
y: element.y + diffY,
|
||||
}),
|
||||
);
|
||||
elbowArrows.forEach((element) =>
|
||||
app.scene.mutate(element, {
|
||||
app.scene.mutateElement(element, {
|
||||
x: element.x + diffX,
|
||||
y: element.y + diffY,
|
||||
}),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { getNonDeletedElements } from "@excalidraw/element";
|
||||
import { mutateElementWith } from "@excalidraw/element/mutateElement";
|
||||
import { mutateElement } from "@excalidraw/element/mutateElement";
|
||||
import { newFrameElement } from "@excalidraw/element/newElement";
|
||||
import { isFrameLikeElement } from "@excalidraw/element/typeChecks";
|
||||
import {
|
||||
|
@ -194,7 +194,7 @@ export const actionWrapSelectionInFrame = register({
|
|||
for (const elementInGroup of elementsInGroup) {
|
||||
const index = elementInGroup.groupIds.indexOf(appState.editingGroupId);
|
||||
|
||||
mutateElementWith(elementInGroup, elementsMap, {
|
||||
mutateElement(elementInGroup, elementsMap, {
|
||||
groupIds: elementInGroup.groupIds.slice(0, index),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -211,7 +211,7 @@ const offsetElementAfterFontResize = (
|
|||
if (isBoundToContainer(nextElement) || !nextElement.autoResize) {
|
||||
return nextElement;
|
||||
}
|
||||
return scene.mutate(nextElement, {
|
||||
return scene.mutateElement(nextElement, {
|
||||
x:
|
||||
prevElement.textAlign === "left"
|
||||
? prevElement.x
|
||||
|
@ -915,7 +915,7 @@ export const actionChangeFontFamily = register({
|
|||
|
||||
if (resetContainers && container && cachedContainer) {
|
||||
// reset the container back to it's cached version
|
||||
app.scene.mutate(container, { ...cachedContainer });
|
||||
app.scene.mutateElement(container, { ...cachedContainer });
|
||||
}
|
||||
|
||||
if (!skipFontFaceCheck) {
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
} from "@excalidraw/element/binding";
|
||||
import { LinearElementEditor } from "@excalidraw/element/linearElementEditor";
|
||||
import {
|
||||
mutateElementWith,
|
||||
mutateElement,
|
||||
newElementWith,
|
||||
} from "@excalidraw/element/mutateElement";
|
||||
import {
|
||||
|
@ -1344,7 +1344,7 @@ export class ElementsChange implements Change<SceneElementsMap> {
|
|||
updates as ElementUpdate<OrderedExcalidrawElement>,
|
||||
);
|
||||
} else {
|
||||
affectedElement = mutateElementWith(
|
||||
affectedElement = mutateElement(
|
||||
nextElement,
|
||||
nextElements,
|
||||
updates as ElementUpdate<OrderedExcalidrawElement>,
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
isPromiseLike,
|
||||
} from "@excalidraw/common";
|
||||
|
||||
import { mutateElementWith } from "@excalidraw/element/mutateElement";
|
||||
import { mutateElement } from "@excalidraw/element/mutateElement";
|
||||
import { deepCopyElement } from "@excalidraw/element/duplicate";
|
||||
import {
|
||||
isFrameLikeElement,
|
||||
|
@ -172,7 +172,7 @@ export const serializeAsClipboardJSON = ({
|
|||
!framesToCopy.has(getContainingFrame(element, elementsMap)!)
|
||||
) {
|
||||
const copiedElement = deepCopyElement(element);
|
||||
mutateElementWith(copiedElement, elementsMap, {
|
||||
mutateElement(copiedElement, elementsMap, {
|
||||
frameId: null,
|
||||
});
|
||||
return copiedElement;
|
||||
|
|
|
@ -301,6 +301,8 @@ import { isNonDeletedElement } from "@excalidraw/element";
|
|||
|
||||
import Scene from "@excalidraw/element/Scene";
|
||||
|
||||
import type { ElementUpdate } from "@excalidraw/element/mutateElement";
|
||||
|
||||
import type { LocalPoint, Radians } from "@excalidraw/math";
|
||||
|
||||
import type {
|
||||
|
@ -329,7 +331,7 @@ import type {
|
|||
ExcalidrawElbowArrowElement,
|
||||
} from "@excalidraw/element/types";
|
||||
|
||||
import type { ValueOf } from "@excalidraw/common/utility-types";
|
||||
import type { Mutable, ValueOf } from "@excalidraw/common/utility-types";
|
||||
|
||||
import {
|
||||
actionAddToLibrary,
|
||||
|
@ -776,6 +778,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
if (excalidrawAPI) {
|
||||
const api: ExcalidrawImperativeAPI = {
|
||||
updateScene: this.updateScene,
|
||||
mutateElement: this.mutateElement,
|
||||
updateLibrary: this.library.updateLibrary,
|
||||
addFiles: this.addFiles,
|
||||
resetScene: this.resetScene,
|
||||
|
@ -1403,7 +1406,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
|
||||
private resetEditingFrame = (frame: ExcalidrawFrameLikeElement | null) => {
|
||||
if (frame) {
|
||||
this.scene.mutate(frame, { name: frame.name?.trim() || null });
|
||||
this.scene.mutateElement(frame, { name: frame.name?.trim() || null });
|
||||
}
|
||||
this.setState({ editingFrame: null });
|
||||
};
|
||||
|
@ -1460,7 +1463,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
autoFocus
|
||||
value={frameNameInEdit}
|
||||
onChange={(e) => {
|
||||
this.scene.mutate(f, {
|
||||
this.scene.mutateElement(f, {
|
||||
name: e.target.value,
|
||||
});
|
||||
}}
|
||||
|
@ -1951,20 +1954,20 @@ class App extends React.Component<AppProps, AppState> {
|
|||
// state only.
|
||||
// Thus reset so that we prefer local cache (if there was some
|
||||
// generationData set previously)
|
||||
this.scene.mutate(
|
||||
this.scene.mutateElement(
|
||||
frameElement,
|
||||
{
|
||||
customData: { generationData: undefined },
|
||||
},
|
||||
{ informMutation: false },
|
||||
{ informMutation: false, isDragging: false },
|
||||
);
|
||||
} else {
|
||||
this.scene.mutate(
|
||||
this.scene.mutateElement(
|
||||
frameElement,
|
||||
{
|
||||
customData: { generationData: data },
|
||||
},
|
||||
{ informMutation: false },
|
||||
{ informMutation: false, isDragging: false },
|
||||
);
|
||||
}
|
||||
this.magicGenerations.set(frameElement.id, data);
|
||||
|
@ -2136,7 +2139,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
this.scene.insertElement(frame);
|
||||
|
||||
for (const child of selectedElements) {
|
||||
this.scene.mutate(child, { frameId: frame.id });
|
||||
this.scene.mutateElement(child, { frameId: frame.id });
|
||||
}
|
||||
|
||||
this.setState({
|
||||
|
@ -3456,10 +3459,10 @@ class App extends React.Component<AppProps, AppState> {
|
|||
}
|
||||
// hack to reset the `y` coord because we vertically center during
|
||||
// insertImageElement
|
||||
this.scene.mutate(
|
||||
this.scene.mutateElement(
|
||||
initializedImageElement,
|
||||
{ y },
|
||||
{ informMutation: false },
|
||||
{ informMutation: false, isDragging: false },
|
||||
);
|
||||
|
||||
y = imageElement.y + imageElement.height + 25;
|
||||
|
@ -4014,6 +4017,17 @@ class App extends React.Component<AppProps, AppState> {
|
|||
},
|
||||
);
|
||||
|
||||
public mutateElement = <TElement extends Mutable<ExcalidrawElement>>(
|
||||
element: TElement,
|
||||
updates: ElementUpdate<TElement>,
|
||||
informMutation = true,
|
||||
) => {
|
||||
return this.scene.mutateElement(element, updates, {
|
||||
informMutation,
|
||||
isDragging: false,
|
||||
});
|
||||
};
|
||||
|
||||
private triggerRender = (
|
||||
/** force always re-renders canvas even if no change */
|
||||
force?: boolean,
|
||||
|
@ -4426,13 +4440,13 @@ class App extends React.Component<AppProps, AppState> {
|
|||
}
|
||||
|
||||
selectedElements.forEach((element) => {
|
||||
this.scene.mutate(
|
||||
this.scene.mutateElement(
|
||||
element,
|
||||
{
|
||||
x: element.x + offsetX,
|
||||
y: element.y + offsetY,
|
||||
},
|
||||
{ informMutation: false },
|
||||
{ informMutation: false, isDragging: false },
|
||||
);
|
||||
|
||||
updateBoundElements(element, this.scene, {
|
||||
|
@ -5335,7 +5349,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
const minHeight = getApproxMinLineHeight(fontSize, lineHeight);
|
||||
const newHeight = Math.max(container.height, minHeight);
|
||||
const newWidth = Math.max(container.width, minWidth);
|
||||
this.scene.mutate(container, {
|
||||
this.scene.mutateElement(container, {
|
||||
height: newHeight,
|
||||
width: newWidth,
|
||||
});
|
||||
|
@ -5389,7 +5403,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
});
|
||||
|
||||
if (!existingTextElement && shouldBindToContainer && container) {
|
||||
this.scene.mutate(container, {
|
||||
this.scene.mutateElement(container, {
|
||||
boundElements: (container.boundElements || []).concat({
|
||||
type: "text",
|
||||
id: element.id,
|
||||
|
@ -5940,7 +5954,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
lastPoint,
|
||||
) >= LINE_CONFIRM_THRESHOLD
|
||||
) {
|
||||
this.scene.mutate(
|
||||
this.scene.mutateElement(
|
||||
multiElement,
|
||||
{
|
||||
points: [
|
||||
|
@ -5948,7 +5962,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
pointFrom<LocalPoint>(scenePointerX - rx, scenePointerY - ry),
|
||||
],
|
||||
},
|
||||
{ informMutation: false },
|
||||
{ informMutation: false, isDragging: false },
|
||||
);
|
||||
} else {
|
||||
setCursor(this.interactiveCanvas, CURSOR_TYPE.POINTER);
|
||||
|
@ -5964,12 +5978,12 @@ class App extends React.Component<AppProps, AppState> {
|
|||
) < LINE_CONFIRM_THRESHOLD
|
||||
) {
|
||||
setCursor(this.interactiveCanvas, CURSOR_TYPE.POINTER);
|
||||
this.scene.mutate(
|
||||
this.scene.mutateElement(
|
||||
multiElement,
|
||||
{
|
||||
points: points.slice(0, -1),
|
||||
},
|
||||
{ informMutation: false },
|
||||
{ informMutation: false, isDragging: false },
|
||||
);
|
||||
} else {
|
||||
const [gridX, gridY] = getGridPoint(
|
||||
|
@ -6003,7 +6017,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
}
|
||||
|
||||
// update last uncommitted point
|
||||
this.scene.mutate(
|
||||
this.scene.mutateElement(
|
||||
multiElement,
|
||||
{
|
||||
points: [
|
||||
|
@ -6688,7 +6702,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
|
||||
const frame = this.getTopLayerFrameAtSceneCoords({ x, y });
|
||||
|
||||
this.scene.mutate(pendingImageElement, {
|
||||
this.scene.mutateElement(pendingImageElement, {
|
||||
x,
|
||||
y,
|
||||
frameId: frame ? frame.id : null,
|
||||
|
@ -7742,7 +7756,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
multiElement.type === "line" &&
|
||||
isPathALoop(multiElement.points, this.state.zoom.value)
|
||||
) {
|
||||
this.scene.mutate(multiElement, {
|
||||
this.scene.mutateElement(multiElement, {
|
||||
lastCommittedPoint:
|
||||
multiElement.points[multiElement.points.length - 1],
|
||||
});
|
||||
|
@ -7753,7 +7767,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
// Elbow arrows cannot be created by putting down points
|
||||
// only the start and end points can be defined
|
||||
if (isElbowArrow(multiElement) && multiElement.points.length > 1) {
|
||||
this.scene.mutate(multiElement, {
|
||||
this.scene.mutateElement(multiElement, {
|
||||
lastCommittedPoint:
|
||||
multiElement.points[multiElement.points.length - 1],
|
||||
});
|
||||
|
@ -7790,7 +7804,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
}));
|
||||
// clicking outside commit zone → update reference for last committed
|
||||
// point
|
||||
this.scene.mutate(multiElement, {
|
||||
this.scene.mutateElement(multiElement, {
|
||||
lastCommittedPoint: multiElement.points[multiElement.points.length - 1],
|
||||
});
|
||||
setCursor(this.interactiveCanvas, CURSOR_TYPE.POINTER);
|
||||
|
@ -7876,7 +7890,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
),
|
||||
};
|
||||
});
|
||||
this.scene.mutate(element, {
|
||||
this.scene.mutateElement(element, {
|
||||
points: [...element.points, pointFrom<LocalPoint>(0, 0)],
|
||||
});
|
||||
const boundElement = getHoveredElementForBinding(
|
||||
|
@ -8458,7 +8472,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
),
|
||||
};
|
||||
|
||||
this.scene.mutate(croppingElement, {
|
||||
this.scene.mutateElement(croppingElement, {
|
||||
crop: nextCrop,
|
||||
});
|
||||
|
||||
|
@ -8655,7 +8669,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
? newElement.pressures
|
||||
: [...newElement.pressures, event.pressure];
|
||||
|
||||
this.scene.mutate(
|
||||
this.scene.mutateElement(
|
||||
newElement,
|
||||
{
|
||||
points: [...points, pointFrom<LocalPoint>(dx, dy)],
|
||||
|
@ -8663,6 +8677,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
},
|
||||
{
|
||||
informMutation: false,
|
||||
isDragging: false,
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -8686,23 +8701,23 @@ class App extends React.Component<AppProps, AppState> {
|
|||
}
|
||||
|
||||
if (points.length === 1) {
|
||||
this.scene.mutate(
|
||||
this.scene.mutateElement(
|
||||
newElement,
|
||||
{
|
||||
points: [...points, pointFrom<LocalPoint>(dx, dy)],
|
||||
},
|
||||
{ informMutation: false },
|
||||
{ informMutation: false, isDragging: false },
|
||||
);
|
||||
} else if (
|
||||
points.length === 2 ||
|
||||
(points.length > 1 && isElbowArrow(newElement))
|
||||
) {
|
||||
this.scene.mutate(
|
||||
this.scene.mutateElement(
|
||||
newElement,
|
||||
{
|
||||
points: [...points.slice(0, -1), pointFrom<LocalPoint>(dx, dy)],
|
||||
},
|
||||
{ isDragging: true },
|
||||
{ isDragging: true, informMutation: false },
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -8916,7 +8931,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
.map((e) => elementsMap.get(e.id))
|
||||
.filter((e) => isElbowArrow(e))
|
||||
.forEach((e) => {
|
||||
!!e && this.scene.mutate(e, {});
|
||||
!!e && this.scene.mutateElement(e, {});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -8952,7 +8967,10 @@ class App extends React.Component<AppProps, AppState> {
|
|||
this.scene.getNonDeletedElementsMap(),
|
||||
);
|
||||
if (element) {
|
||||
this.scene.mutate(element as ExcalidrawElbowArrowElement, {});
|
||||
this.scene.mutateElement(
|
||||
element as ExcalidrawElbowArrowElement,
|
||||
{},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9047,7 +9065,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
? []
|
||||
: [...newElement.pressures, childEvent.pressure];
|
||||
|
||||
this.scene.mutate(newElement, {
|
||||
this.scene.mutateElement(newElement, {
|
||||
points: [...points, pointFrom<LocalPoint>(dx, dy)],
|
||||
pressures,
|
||||
lastCommittedPoint: pointFrom<LocalPoint>(dx, dy),
|
||||
|
@ -9094,7 +9112,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
);
|
||||
|
||||
if (!pointerDownState.drag.hasOccurred && newElement && !multiElement) {
|
||||
this.scene.mutate(
|
||||
this.scene.mutateElement(
|
||||
newElement,
|
||||
{
|
||||
points: [
|
||||
|
@ -9105,7 +9123,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
),
|
||||
],
|
||||
},
|
||||
{ informMutation: false },
|
||||
{ informMutation: false, isDragging: false },
|
||||
);
|
||||
|
||||
this.setState({
|
||||
|
@ -9165,7 +9183,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
);
|
||||
|
||||
if (newElement.width < minWidth) {
|
||||
this.scene.mutate(newElement, {
|
||||
this.scene.mutateElement(newElement, {
|
||||
autoResize: true,
|
||||
});
|
||||
}
|
||||
|
@ -9215,9 +9233,14 @@ class App extends React.Component<AppProps, AppState> {
|
|||
}
|
||||
|
||||
if (newElement) {
|
||||
this.scene.mutate(newElement, getNormalizedDimensions(newElement), {
|
||||
this.scene.mutateElement(
|
||||
newElement,
|
||||
getNormalizedDimensions(newElement),
|
||||
{
|
||||
informMutation: false,
|
||||
});
|
||||
isDragging: false,
|
||||
},
|
||||
);
|
||||
// the above does not guarantee the scene to be rendered again, hence the trigger below
|
||||
this.scene.triggerUpdate();
|
||||
}
|
||||
|
@ -9249,7 +9272,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
) {
|
||||
// remove the linear element from all groups
|
||||
// before removing it from the frame as well
|
||||
this.scene.mutate(linearElement, {
|
||||
this.scene.mutateElement(linearElement, {
|
||||
groupIds: [],
|
||||
});
|
||||
|
||||
|
@ -9278,12 +9301,12 @@ class App extends React.Component<AppProps, AppState> {
|
|||
this.state.editingGroupId!,
|
||||
);
|
||||
|
||||
this.scene.mutate(
|
||||
this.scene.mutateElement(
|
||||
element,
|
||||
{
|
||||
groupIds: element.groupIds.slice(0, index),
|
||||
},
|
||||
{ informMutation: false },
|
||||
{ informMutation: false, isDragging: false },
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -9295,12 +9318,12 @@ class App extends React.Component<AppProps, AppState> {
|
|||
element.groupIds[element.groupIds.length - 1],
|
||||
).length < 2
|
||||
) {
|
||||
this.scene.mutate(
|
||||
this.scene.mutateElement(
|
||||
element,
|
||||
{
|
||||
groupIds: [],
|
||||
},
|
||||
{ informMutation: false },
|
||||
{ informMutation: false, isDragging: false },
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -9870,12 +9893,12 @@ class App extends React.Component<AppProps, AppState> {
|
|||
const dataURL =
|
||||
this.files[fileId]?.dataURL || (await getDataURL(imageFile));
|
||||
|
||||
const imageElement = this.scene.mutate(
|
||||
const imageElement = this.scene.mutateElement(
|
||||
_imageElement,
|
||||
{
|
||||
fileId,
|
||||
},
|
||||
{ informMutation: false },
|
||||
{ informMutation: false, isDragging: false },
|
||||
) as NonDeleted<InitializedExcalidrawImageElement>;
|
||||
|
||||
return new Promise<NonDeleted<InitializedExcalidrawImageElement>>(
|
||||
|
@ -9941,7 +9964,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
showCursorImagePreview,
|
||||
});
|
||||
} catch (error: any) {
|
||||
this.scene.mutate(imageElement, {
|
||||
this.scene.mutateElement(imageElement, {
|
||||
isDeleted: true,
|
||||
});
|
||||
this.actionManager.executeAction(actionFinalize);
|
||||
|
@ -10087,7 +10110,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
imageElement.height < DRAGGING_THRESHOLD / this.state.zoom.value
|
||||
) {
|
||||
const placeholderSize = 100 / this.state.zoom.value;
|
||||
this.scene.mutate(imageElement, {
|
||||
this.scene.mutateElement(imageElement, {
|
||||
x: imageElement.x - placeholderSize / 2,
|
||||
y: imageElement.y - placeholderSize / 2,
|
||||
width: placeholderSize,
|
||||
|
@ -10121,7 +10144,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
const x = imageElement.x + imageElement.width / 2 - width / 2;
|
||||
const y = imageElement.y + imageElement.height / 2 - height / 2;
|
||||
|
||||
this.scene.mutate(imageElement, {
|
||||
this.scene.mutateElement(imageElement, {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
|
@ -10742,7 +10765,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
transformHandleType,
|
||||
);
|
||||
|
||||
this.scene.mutate(
|
||||
this.scene.mutateElement(
|
||||
croppingElement,
|
||||
cropElement(
|
||||
croppingElement,
|
||||
|
|
|
@ -71,7 +71,7 @@ const ElementLinkDialog = ({
|
|||
if (nextLink && nextLink !== elementsMap.get(sourceElementId)?.link) {
|
||||
const elementToLink = elementsMap.get(sourceElementId);
|
||||
elementToLink &&
|
||||
scene.mutate(elementToLink, {
|
||||
scene.mutateElement(elementToLink, {
|
||||
link: nextLink,
|
||||
});
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ const ElementLinkDialog = ({
|
|||
if (!nextLink && linkEdited && sourceElementId) {
|
||||
const elementToLink = elementsMap.get(sourceElementId);
|
||||
elementToLink &&
|
||||
scene.mutate(elementToLink, {
|
||||
scene.mutateElement(elementToLink, {
|
||||
link: null,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
isShallowEqual,
|
||||
} from "@excalidraw/common";
|
||||
|
||||
import { mutateElementWith } from "@excalidraw/element/mutateElement";
|
||||
import { mutateElement } from "@excalidraw/element/mutateElement";
|
||||
|
||||
import { showSelectedShapeActions } from "@excalidraw/element/showSelectedShapeActions";
|
||||
|
||||
|
@ -446,7 +446,7 @@ const LayerUI = ({
|
|||
|
||||
if (selectedElements.length) {
|
||||
for (const element of selectedElements) {
|
||||
mutateElementWith(element, arrayToMap(elements), {
|
||||
mutateElement(element, arrayToMap(elements), {
|
||||
[altKey && eyeDropperState.swapPreviewOnAlt
|
||||
? colorPickerType === "elementBackground"
|
||||
? "strokeColor"
|
||||
|
|
|
@ -43,14 +43,14 @@ const handleDegreeChange: DragInputCallbackType<AngleProps["property"]> = ({
|
|||
|
||||
if (nextValue !== undefined) {
|
||||
const nextAngle = degreesToRadians(nextValue as Degrees);
|
||||
scene.mutate(latestElement, {
|
||||
scene.mutateElement(latestElement, {
|
||||
angle: nextAngle,
|
||||
});
|
||||
updateBindings(latestElement, scene);
|
||||
|
||||
const boundTextElement = getBoundTextElement(latestElement, elementsMap);
|
||||
if (boundTextElement && !isArrowElement(latestElement)) {
|
||||
scene.mutate(boundTextElement, { angle: nextAngle });
|
||||
scene.mutateElement(boundTextElement, { angle: nextAngle });
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -69,14 +69,14 @@ const handleDegreeChange: DragInputCallbackType<AngleProps["property"]> = ({
|
|||
|
||||
const nextAngle = degreesToRadians(nextAngleInDegrees as Degrees);
|
||||
|
||||
scene.mutate(latestElement, {
|
||||
scene.mutateElement(latestElement, {
|
||||
angle: nextAngle,
|
||||
});
|
||||
updateBindings(latestElement, scene);
|
||||
|
||||
const boundTextElement = getBoundTextElement(latestElement, elementsMap);
|
||||
if (boundTextElement && !isArrowElement(latestElement)) {
|
||||
scene.mutate(boundTextElement, { angle: nextAngle });
|
||||
scene.mutateElement(boundTextElement, { angle: nextAngle });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -113,7 +113,7 @@ const handleDimensionChange: DragInputCallbackType<
|
|||
};
|
||||
}
|
||||
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
crop: nextCrop,
|
||||
width: nextCrop.width / (crop.naturalWidth / uncroppedWidth),
|
||||
height: nextCrop.height / (crop.naturalHeight / uncroppedHeight),
|
||||
|
@ -144,7 +144,7 @@ const handleDimensionChange: DragInputCallbackType<
|
|||
height: nextCropHeight,
|
||||
};
|
||||
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
crop: nextCrop,
|
||||
width: nextCrop.width / (crop.naturalWidth / uncroppedWidth),
|
||||
height: nextCrop.height / (crop.naturalHeight / uncroppedHeight),
|
||||
|
|
|
@ -68,7 +68,7 @@ const handleFontSizeChange: DragInputCallbackType<
|
|||
}
|
||||
|
||||
if (nextFontSize) {
|
||||
scene.mutate(latestElement, {
|
||||
scene.mutateElement(latestElement, {
|
||||
fontSize: nextFontSize,
|
||||
});
|
||||
redrawTextBoundingBox(
|
||||
|
|
|
@ -53,13 +53,13 @@ const handleDegreeChange: DragInputCallbackType<
|
|||
if (!element) {
|
||||
continue;
|
||||
}
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
angle: nextAngle,
|
||||
});
|
||||
|
||||
const boundTextElement = getBoundTextElement(element, elementsMap);
|
||||
if (boundTextElement && !isArrowElement(element)) {
|
||||
scene.mutate(boundTextElement, { angle: nextAngle });
|
||||
scene.mutateElement(boundTextElement, { angle: nextAngle });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,13 +87,13 @@ const handleDegreeChange: DragInputCallbackType<
|
|||
|
||||
const nextAngle = degreesToRadians(nextAngleInDegrees as Degrees);
|
||||
|
||||
scene.mutate(latestElement, {
|
||||
scene.mutateElement(latestElement, {
|
||||
angle: nextAngle,
|
||||
});
|
||||
|
||||
const boundTextElement = getBoundTextElement(latestElement, elementsMap);
|
||||
if (boundTextElement && !isArrowElement(latestElement)) {
|
||||
scene.mutate(boundTextElement, { angle: nextAngle });
|
||||
scene.mutateElement(boundTextElement, { angle: nextAngle });
|
||||
}
|
||||
}
|
||||
scene.triggerUpdate();
|
||||
|
|
|
@ -81,7 +81,7 @@ const resizeElementInGroup = (
|
|||
const elementsMap = scene.getNonDeletedElementsMap();
|
||||
const updates = getResizedUpdates(anchorX, anchorY, scale, origElement);
|
||||
|
||||
scene.mutate(latestElement, updates);
|
||||
scene.mutateElement(latestElement, updates);
|
||||
|
||||
const boundTextElement = getBoundTextElement(
|
||||
origElement,
|
||||
|
@ -94,7 +94,7 @@ const resizeElementInGroup = (
|
|||
});
|
||||
const latestBoundTextElement = elementsMap.get(boundTextElement.id);
|
||||
if (latestBoundTextElement && isTextElement(latestBoundTextElement)) {
|
||||
scene.mutate(latestBoundTextElement, {
|
||||
scene.mutateElement(latestBoundTextElement, {
|
||||
fontSize: newFontSize,
|
||||
});
|
||||
handleBindTextResize(
|
||||
|
|
|
@ -84,7 +84,7 @@ const handleFontSizeChange: DragInputCallbackType<
|
|||
nextFontSize = Math.max(Math.round(nextValue), MIN_FONT_SIZE);
|
||||
|
||||
for (const textElement of latestTextElements) {
|
||||
scene.mutate(textElement, {
|
||||
scene.mutateElement(textElement, {
|
||||
fontSize: nextFontSize,
|
||||
});
|
||||
|
||||
|
@ -112,7 +112,7 @@ const handleFontSizeChange: DragInputCallbackType<
|
|||
if (shouldChangeByStepSize) {
|
||||
nextFontSize = getStepSizedValue(nextFontSize, STEP_SIZE);
|
||||
}
|
||||
scene.mutate(latestElement, {
|
||||
scene.mutateElement(latestElement, {
|
||||
fontSize: nextFontSize,
|
||||
});
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ const handlePositionChange: DragInputCallbackType<"x" | "y"> = ({
|
|||
};
|
||||
}
|
||||
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
crop: nextCrop,
|
||||
});
|
||||
|
||||
|
@ -118,7 +118,7 @@ const handlePositionChange: DragInputCallbackType<"x" | "y"> = ({
|
|||
y: clamp(crop.y + changeInY, 0, crop.naturalHeight - crop.height),
|
||||
};
|
||||
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
crop: nextCrop,
|
||||
});
|
||||
|
||||
|
|
|
@ -478,7 +478,7 @@ describe("stats for a non-generic element", () => {
|
|||
containerId: container.id,
|
||||
fontSize: 20,
|
||||
});
|
||||
h.app.scene.mutate(container, {
|
||||
h.app.scene.mutateElement(container, {
|
||||
boundElements: [{ type: "text", id: text.id }],
|
||||
});
|
||||
API.setElements([container, text]);
|
||||
|
|
|
@ -146,13 +146,13 @@ export const moveElement = (
|
|||
-originalElement.angle as Radians,
|
||||
);
|
||||
|
||||
scene.mutate(
|
||||
scene.mutateElement(
|
||||
latestElement,
|
||||
{
|
||||
x,
|
||||
y,
|
||||
},
|
||||
{ informMutation: shouldInformMutation },
|
||||
{ informMutation: shouldInformMutation, isDragging: false },
|
||||
);
|
||||
updateBindings(latestElement, scene);
|
||||
|
||||
|
@ -163,13 +163,13 @@ export const moveElement = (
|
|||
if (boundTextElement) {
|
||||
const latestBoundTextElement = elementsMap.get(boundTextElement.id);
|
||||
latestBoundTextElement &&
|
||||
scene.mutate(
|
||||
scene.mutateElement(
|
||||
latestBoundTextElement,
|
||||
{
|
||||
x: boundTextElement.x + changeInX,
|
||||
y: boundTextElement.y + changeInY,
|
||||
},
|
||||
{ informMutation: shouldInformMutation },
|
||||
{ informMutation: shouldInformMutation, isDragging: false },
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -115,7 +115,7 @@ export const Hyperlink = ({
|
|||
setAppState({ activeEmbeddable: null });
|
||||
}
|
||||
if (!link) {
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
link: null,
|
||||
});
|
||||
updateEmbedValidationStatus(element, false);
|
||||
|
@ -127,7 +127,7 @@ export const Hyperlink = ({
|
|||
setToast({ message: t("toast.unableToEmbed"), closable: true });
|
||||
}
|
||||
element.link && embeddableLinkCache.set(element.id, element.link);
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
link,
|
||||
});
|
||||
updateEmbedValidationStatus(element, false);
|
||||
|
@ -145,7 +145,7 @@ export const Hyperlink = ({
|
|||
: 1;
|
||||
const hasLinkChanged =
|
||||
embeddableLinkCache.get(element.id) !== element.link;
|
||||
scene.mutate(element, {
|
||||
scene.mutateElement(element, {
|
||||
...(hasLinkChanged
|
||||
? {
|
||||
width:
|
||||
|
@ -170,7 +170,7 @@ export const Hyperlink = ({
|
|||
}
|
||||
}
|
||||
} else {
|
||||
scene.mutate(element, { link });
|
||||
scene.mutateElement(element, { link });
|
||||
}
|
||||
}, [
|
||||
element,
|
||||
|
@ -231,7 +231,7 @@ export const Hyperlink = ({
|
|||
|
||||
const handleRemove = useCallback(() => {
|
||||
trackEvent("hyperlink", "delete");
|
||||
scene.mutate(element, { link: null });
|
||||
scene.mutateElement(element, { link: null });
|
||||
setAppState({ showHyperlinkPopup: false });
|
||||
}, [setAppState, element, scene]);
|
||||
|
||||
|
|
|
@ -259,7 +259,6 @@ export {
|
|||
} from "@excalidraw/common";
|
||||
|
||||
export {
|
||||
mutateElementWith,
|
||||
mutateElement,
|
||||
newElementWith,
|
||||
bumpVersion,
|
||||
|
|
|
@ -296,7 +296,7 @@ describe("element locking", () => {
|
|||
height: textSize,
|
||||
containerId: container.id,
|
||||
});
|
||||
h.app.scene.mutate(container, {
|
||||
h.app.scene.mutateElement(container, {
|
||||
boundElements: [{ id: text.id, type: "text" }],
|
||||
});
|
||||
|
||||
|
@ -337,7 +337,7 @@ describe("element locking", () => {
|
|||
containerId: container.id,
|
||||
locked: true,
|
||||
});
|
||||
h.app.scene.mutate(container, {
|
||||
h.app.scene.mutateElement(container, {
|
||||
boundElements: [{ id: text.id, type: "text" }],
|
||||
});
|
||||
API.setElements([container, text]);
|
||||
|
@ -371,7 +371,7 @@ describe("element locking", () => {
|
|||
containerId: container.id,
|
||||
locked: true,
|
||||
});
|
||||
h.app.scene.mutate(container, {
|
||||
h.app.scene.mutateElement(container, {
|
||||
boundElements: [{ id: text.id, type: "text" }],
|
||||
});
|
||||
API.setElements([container, text]);
|
||||
|
|
|
@ -99,10 +99,10 @@ export class API {
|
|||
|
||||
// eslint-disable-next-line prettier/prettier
|
||||
static updateElement = <T extends ExcalidrawElement>(
|
||||
...args: Parameters<typeof h.app.scene.mutate<T>>
|
||||
...args: Parameters<typeof h.app.scene.mutateElement<T>>
|
||||
) => {
|
||||
act(() => {
|
||||
h.app.scene.mutate(...args);
|
||||
h.app.scene.mutateElement(...args);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -418,7 +418,7 @@ export class API {
|
|||
|
||||
});
|
||||
|
||||
h.app.scene.mutate(
|
||||
h.app.scene.mutateElement(
|
||||
rectangle,
|
||||
{
|
||||
boundElements: [{ type: "text", id: text.id }],
|
||||
|
@ -452,7 +452,7 @@ export class API {
|
|||
: opts?.label?.frameId ?? null,
|
||||
});
|
||||
|
||||
h.app.scene.mutate(
|
||||
h.app.scene.mutateElement(
|
||||
arrow,
|
||||
{
|
||||
boundElements: [{ type: "text", id: text.id }],
|
||||
|
|
|
@ -518,7 +518,7 @@ export class UI {
|
|||
|
||||
if (angle !== 0) {
|
||||
act(() => {
|
||||
h.app.scene.mutate(origElement, { angle });
|
||||
h.app.scene.mutateElement(origElement, { angle });
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ describe("Test Linear Elements", () => {
|
|||
],
|
||||
roundness,
|
||||
});
|
||||
h.app.scene.mutate(line, { points: line.points });
|
||||
h.app.scene.mutateElement(line, { points: line.points });
|
||||
API.setElements([line]);
|
||||
mouse.clickAt(p1[0], p1[1]);
|
||||
return line;
|
||||
|
|
|
@ -779,6 +779,7 @@ export type UnsubscribeCallback = () => void;
|
|||
|
||||
export interface ExcalidrawImperativeAPI {
|
||||
updateScene: InstanceType<typeof App>["updateScene"];
|
||||
mutateElement: InstanceType<typeof App>["mutateElement"];
|
||||
updateLibrary: InstanceType<typeof Library>["updateLibrary"];
|
||||
resetScene: InstanceType<typeof App>["resetScene"];
|
||||
getSceneElementsIncludingDeleted: InstanceType<
|
||||
|
|
|
@ -199,7 +199,7 @@ export const textWysiwyg = ({
|
|||
container.type,
|
||||
);
|
||||
|
||||
app.scene.mutate(container, { height: targetContainerHeight });
|
||||
app.scene.mutateElement(container, { height: targetContainerHeight });
|
||||
return;
|
||||
} else if (
|
||||
// autoshrink container height until original container height
|
||||
|
@ -212,7 +212,7 @@ export const textWysiwyg = ({
|
|||
height,
|
||||
container.type,
|
||||
);
|
||||
app.scene.mutate(container, { height: targetContainerHeight });
|
||||
app.scene.mutateElement(container, { height: targetContainerHeight });
|
||||
} else {
|
||||
const { y } = computeBoundTextPosition(
|
||||
container,
|
||||
|
@ -285,7 +285,7 @@ export const textWysiwyg = ({
|
|||
editable.style.fontFamily = getFontFamilyString(updatedTextElement);
|
||||
}
|
||||
|
||||
app.scene.mutate(updatedTextElement, { x: coordX, y: coordY });
|
||||
app.scene.mutateElement(updatedTextElement, { x: coordX, y: coordY });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -557,7 +557,7 @@ export const textWysiwyg = ({
|
|||
if (editable.value.trim()) {
|
||||
const boundTextElementId = getBoundTextElementId(container);
|
||||
if (!boundTextElementId || boundTextElementId !== element.id) {
|
||||
app.scene.mutate(container, {
|
||||
app.scene.mutateElement(container, {
|
||||
boundElements: (container.boundElements || []).concat({
|
||||
type: "text",
|
||||
id: element.id,
|
||||
|
@ -568,7 +568,7 @@ export const textWysiwyg = ({
|
|||
bumpVersion(container);
|
||||
}
|
||||
} else {
|
||||
app.scene.mutate(container, {
|
||||
app.scene.mutateElement(container, {
|
||||
boundElements: container.boundElements?.filter(
|
||||
(ele) =>
|
||||
!isTextElement(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue