|
@@ -9,10 +9,10 @@ import {
|
|
|
} from "../../element/textElement";
|
|
|
import type { ElementsMap, ExcalidrawElement } from "../../element/types";
|
|
|
import type Scene from "../../scene/Scene";
|
|
|
-import type { Point } from "../../types";
|
|
|
+import type { AppState, Point } from "../../types";
|
|
|
import DragInput from "./DragInput";
|
|
|
import type { DragInputCallbackType } from "./DragInput";
|
|
|
-import { getStepSizedValue, isPropertyEditable } from "./utils";
|
|
|
+import { getAtomicUnits, getStepSizedValue, isPropertyEditable } from "./utils";
|
|
|
import { getElementsInAtomicUnit, resizeElement } from "./utils";
|
|
|
import type { AtomicUnit } from "./utils";
|
|
|
import { MIN_WIDTH_OR_HEIGHT } from "../../constants";
|
|
@@ -23,6 +23,7 @@ interface MultiDimensionProps {
|
|
|
elementsMap: ElementsMap;
|
|
|
atomicUnits: AtomicUnit[];
|
|
|
scene: Scene;
|
|
|
+ appState: AppState;
|
|
|
}
|
|
|
|
|
|
const STEP_SIZE = 10;
|
|
@@ -131,143 +132,21 @@ const resizeGroup = (
|
|
|
}
|
|
|
};
|
|
|
|
|
|
-const MultiDimension = ({
|
|
|
- property,
|
|
|
- elements,
|
|
|
- elementsMap,
|
|
|
- atomicUnits,
|
|
|
+const handleDimensionChange: DragInputCallbackType<
|
|
|
+ MultiDimensionProps["property"]
|
|
|
+> = ({
|
|
|
+ accumulatedChange,
|
|
|
+ originalElements,
|
|
|
+ originalElementsMap,
|
|
|
+ originalAppState,
|
|
|
+ shouldChangeByStepSize,
|
|
|
+ nextValue,
|
|
|
scene,
|
|
|
-}: MultiDimensionProps) => {
|
|
|
- const sizes = useMemo(
|
|
|
- () =>
|
|
|
- atomicUnits.map((atomicUnit) => {
|
|
|
- const elementsInUnit = getElementsInAtomicUnit(atomicUnit, elementsMap);
|
|
|
-
|
|
|
- if (elementsInUnit.length > 1) {
|
|
|
- const [x1, y1, x2, y2] = getCommonBounds(
|
|
|
- elementsInUnit.map((el) => el.latest),
|
|
|
- );
|
|
|
- return (
|
|
|
- Math.round((property === "width" ? x2 - x1 : y2 - y1) * 100) / 100
|
|
|
- );
|
|
|
- }
|
|
|
- const [el] = elementsInUnit;
|
|
|
-
|
|
|
- return (
|
|
|
- Math.round(
|
|
|
- (property === "width" ? el.latest.width : el.latest.height) * 100,
|
|
|
- ) / 100
|
|
|
- );
|
|
|
- }),
|
|
|
- [elementsMap, atomicUnits, property],
|
|
|
- );
|
|
|
-
|
|
|
- const value =
|
|
|
- new Set(sizes).size === 1 ? Math.round(sizes[0] * 100) / 100 : "Mixed";
|
|
|
-
|
|
|
- const editable = sizes.length > 0;
|
|
|
-
|
|
|
- const handleDimensionChange: DragInputCallbackType = ({
|
|
|
- accumulatedChange,
|
|
|
- originalElementsMap,
|
|
|
- shouldChangeByStepSize,
|
|
|
- nextValue,
|
|
|
- }) => {
|
|
|
- if (nextValue !== undefined) {
|
|
|
- for (const atomicUnit of atomicUnits) {
|
|
|
- const elementsInUnit = getElementsInAtomicUnit(
|
|
|
- atomicUnit,
|
|
|
- elementsMap,
|
|
|
- originalElementsMap,
|
|
|
- );
|
|
|
-
|
|
|
- if (elementsInUnit.length > 1) {
|
|
|
- const latestElements = elementsInUnit.map((el) => el.latest!);
|
|
|
- const originalElements = elementsInUnit.map((el) => el.original!);
|
|
|
- const [x1, y1, x2, y2] = getCommonBounds(originalElements);
|
|
|
- const initialWidth = x2 - x1;
|
|
|
- const initialHeight = y2 - y1;
|
|
|
- const aspectRatio = initialWidth / initialHeight;
|
|
|
- const nextWidth = Math.max(
|
|
|
- MIN_WIDTH_OR_HEIGHT,
|
|
|
- property === "width" ? Math.max(0, nextValue) : initialWidth,
|
|
|
- );
|
|
|
- const nextHeight = Math.max(
|
|
|
- MIN_WIDTH_OR_HEIGHT,
|
|
|
- property === "height" ? Math.max(0, nextValue) : initialHeight,
|
|
|
- );
|
|
|
-
|
|
|
- resizeGroup(
|
|
|
- nextWidth,
|
|
|
- nextHeight,
|
|
|
- initialHeight,
|
|
|
- aspectRatio,
|
|
|
- [x1, y1],
|
|
|
- property,
|
|
|
- latestElements,
|
|
|
- originalElements,
|
|
|
- elementsMap,
|
|
|
- originalElementsMap,
|
|
|
- );
|
|
|
- } else {
|
|
|
- const [el] = elementsInUnit;
|
|
|
- const latestElement = el?.latest;
|
|
|
- const origElement = el?.original;
|
|
|
-
|
|
|
- if (
|
|
|
- latestElement &&
|
|
|
- origElement &&
|
|
|
- isPropertyEditable(latestElement, property)
|
|
|
- ) {
|
|
|
- let nextWidth =
|
|
|
- property === "width"
|
|
|
- ? Math.max(0, nextValue)
|
|
|
- : latestElement.width;
|
|
|
- if (property === "width") {
|
|
|
- if (shouldChangeByStepSize) {
|
|
|
- nextWidth = getStepSizedValue(nextWidth, STEP_SIZE);
|
|
|
- } else {
|
|
|
- nextWidth = Math.round(nextWidth);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- let nextHeight =
|
|
|
- property === "height"
|
|
|
- ? Math.max(0, nextValue)
|
|
|
- : latestElement.height;
|
|
|
- if (property === "height") {
|
|
|
- if (shouldChangeByStepSize) {
|
|
|
- nextHeight = getStepSizedValue(nextHeight, STEP_SIZE);
|
|
|
- } else {
|
|
|
- nextHeight = Math.round(nextHeight);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- nextWidth = Math.max(MIN_WIDTH_OR_HEIGHT, nextWidth);
|
|
|
- nextHeight = Math.max(MIN_WIDTH_OR_HEIGHT, nextHeight);
|
|
|
-
|
|
|
- resizeElement(
|
|
|
- nextWidth,
|
|
|
- nextHeight,
|
|
|
- false,
|
|
|
- latestElement,
|
|
|
- origElement,
|
|
|
- elementsMap,
|
|
|
- originalElementsMap,
|
|
|
- false,
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- scene.triggerUpdate();
|
|
|
-
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- const changeInWidth = property === "width" ? accumulatedChange : 0;
|
|
|
- const changeInHeight = property === "height" ? accumulatedChange : 0;
|
|
|
-
|
|
|
+ property,
|
|
|
+}) => {
|
|
|
+ const elementsMap = scene.getNonDeletedElementsMap();
|
|
|
+ const atomicUnits = getAtomicUnits(originalElements, originalAppState);
|
|
|
+ if (nextValue !== undefined) {
|
|
|
for (const atomicUnit of atomicUnits) {
|
|
|
const elementsInUnit = getElementsInAtomicUnit(
|
|
|
atomicUnit,
|
|
@@ -278,31 +157,18 @@ const MultiDimension = ({
|
|
|
if (elementsInUnit.length > 1) {
|
|
|
const latestElements = elementsInUnit.map((el) => el.latest!);
|
|
|
const originalElements = elementsInUnit.map((el) => el.original!);
|
|
|
-
|
|
|
const [x1, y1, x2, y2] = getCommonBounds(originalElements);
|
|
|
const initialWidth = x2 - x1;
|
|
|
const initialHeight = y2 - y1;
|
|
|
const aspectRatio = initialWidth / initialHeight;
|
|
|
- let nextWidth = Math.max(0, initialWidth + changeInWidth);
|
|
|
- if (property === "width") {
|
|
|
- if (shouldChangeByStepSize) {
|
|
|
- nextWidth = getStepSizedValue(nextWidth, STEP_SIZE);
|
|
|
- } else {
|
|
|
- nextWidth = Math.round(nextWidth);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- let nextHeight = Math.max(0, initialHeight + changeInHeight);
|
|
|
- if (property === "height") {
|
|
|
- if (shouldChangeByStepSize) {
|
|
|
- nextHeight = getStepSizedValue(nextHeight, STEP_SIZE);
|
|
|
- } else {
|
|
|
- nextHeight = Math.round(nextHeight);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- nextWidth = Math.max(MIN_WIDTH_OR_HEIGHT, nextWidth);
|
|
|
- nextHeight = Math.max(MIN_WIDTH_OR_HEIGHT, nextHeight);
|
|
|
+ const nextWidth = Math.max(
|
|
|
+ MIN_WIDTH_OR_HEIGHT,
|
|
|
+ property === "width" ? Math.max(0, nextValue) : initialWidth,
|
|
|
+ );
|
|
|
+ const nextHeight = Math.max(
|
|
|
+ MIN_WIDTH_OR_HEIGHT,
|
|
|
+ property === "height" ? Math.max(0, nextValue) : initialHeight,
|
|
|
+ );
|
|
|
|
|
|
resizeGroup(
|
|
|
nextWidth,
|
|
@@ -326,7 +192,8 @@ const MultiDimension = ({
|
|
|
origElement &&
|
|
|
isPropertyEditable(latestElement, property)
|
|
|
) {
|
|
|
- let nextWidth = Math.max(0, origElement.width + changeInWidth);
|
|
|
+ let nextWidth =
|
|
|
+ property === "width" ? Math.max(0, nextValue) : latestElement.width;
|
|
|
if (property === "width") {
|
|
|
if (shouldChangeByStepSize) {
|
|
|
nextWidth = getStepSizedValue(nextWidth, STEP_SIZE);
|
|
@@ -335,7 +202,10 @@ const MultiDimension = ({
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- let nextHeight = Math.max(0, origElement.height + changeInHeight);
|
|
|
+ let nextHeight =
|
|
|
+ property === "height"
|
|
|
+ ? Math.max(0, nextValue)
|
|
|
+ : latestElement.height;
|
|
|
if (property === "height") {
|
|
|
if (shouldChangeByStepSize) {
|
|
|
nextHeight = getStepSizedValue(nextHeight, STEP_SIZE);
|
|
@@ -351,17 +221,145 @@ const MultiDimension = ({
|
|
|
nextWidth,
|
|
|
nextHeight,
|
|
|
false,
|
|
|
- latestElement,
|
|
|
origElement,
|
|
|
elementsMap,
|
|
|
- originalElementsMap,
|
|
|
+ false,
|
|
|
);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
scene.triggerUpdate();
|
|
|
- };
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const changeInWidth = property === "width" ? accumulatedChange : 0;
|
|
|
+ const changeInHeight = property === "height" ? accumulatedChange : 0;
|
|
|
+
|
|
|
+ for (const atomicUnit of atomicUnits) {
|
|
|
+ const elementsInUnit = getElementsInAtomicUnit(
|
|
|
+ atomicUnit,
|
|
|
+ elementsMap,
|
|
|
+ originalElementsMap,
|
|
|
+ );
|
|
|
+
|
|
|
+ if (elementsInUnit.length > 1) {
|
|
|
+ const latestElements = elementsInUnit.map((el) => el.latest!);
|
|
|
+ const originalElements = elementsInUnit.map((el) => el.original!);
|
|
|
+
|
|
|
+ const [x1, y1, x2, y2] = getCommonBounds(originalElements);
|
|
|
+ const initialWidth = x2 - x1;
|
|
|
+ const initialHeight = y2 - y1;
|
|
|
+ const aspectRatio = initialWidth / initialHeight;
|
|
|
+ let nextWidth = Math.max(0, initialWidth + changeInWidth);
|
|
|
+ if (property === "width") {
|
|
|
+ if (shouldChangeByStepSize) {
|
|
|
+ nextWidth = getStepSizedValue(nextWidth, STEP_SIZE);
|
|
|
+ } else {
|
|
|
+ nextWidth = Math.round(nextWidth);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ let nextHeight = Math.max(0, initialHeight + changeInHeight);
|
|
|
+ if (property === "height") {
|
|
|
+ if (shouldChangeByStepSize) {
|
|
|
+ nextHeight = getStepSizedValue(nextHeight, STEP_SIZE);
|
|
|
+ } else {
|
|
|
+ nextHeight = Math.round(nextHeight);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ nextWidth = Math.max(MIN_WIDTH_OR_HEIGHT, nextWidth);
|
|
|
+ nextHeight = Math.max(MIN_WIDTH_OR_HEIGHT, nextHeight);
|
|
|
+
|
|
|
+ resizeGroup(
|
|
|
+ nextWidth,
|
|
|
+ nextHeight,
|
|
|
+ initialHeight,
|
|
|
+ aspectRatio,
|
|
|
+ [x1, y1],
|
|
|
+ property,
|
|
|
+ latestElements,
|
|
|
+ originalElements,
|
|
|
+ elementsMap,
|
|
|
+ originalElementsMap,
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ const [el] = elementsInUnit;
|
|
|
+ const latestElement = el?.latest;
|
|
|
+ const origElement = el?.original;
|
|
|
+
|
|
|
+ if (
|
|
|
+ latestElement &&
|
|
|
+ origElement &&
|
|
|
+ isPropertyEditable(latestElement, property)
|
|
|
+ ) {
|
|
|
+ let nextWidth = Math.max(0, origElement.width + changeInWidth);
|
|
|
+ if (property === "width") {
|
|
|
+ if (shouldChangeByStepSize) {
|
|
|
+ nextWidth = getStepSizedValue(nextWidth, STEP_SIZE);
|
|
|
+ } else {
|
|
|
+ nextWidth = Math.round(nextWidth);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ let nextHeight = Math.max(0, origElement.height + changeInHeight);
|
|
|
+ if (property === "height") {
|
|
|
+ if (shouldChangeByStepSize) {
|
|
|
+ nextHeight = getStepSizedValue(nextHeight, STEP_SIZE);
|
|
|
+ } else {
|
|
|
+ nextHeight = Math.round(nextHeight);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ nextWidth = Math.max(MIN_WIDTH_OR_HEIGHT, nextWidth);
|
|
|
+ nextHeight = Math.max(MIN_WIDTH_OR_HEIGHT, nextHeight);
|
|
|
+
|
|
|
+ resizeElement(nextWidth, nextHeight, false, origElement, elementsMap);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ scene.triggerUpdate();
|
|
|
+};
|
|
|
+
|
|
|
+const MultiDimension = ({
|
|
|
+ property,
|
|
|
+ elements,
|
|
|
+ elementsMap,
|
|
|
+ atomicUnits,
|
|
|
+ scene,
|
|
|
+ appState,
|
|
|
+}: MultiDimensionProps) => {
|
|
|
+ const sizes = useMemo(
|
|
|
+ () =>
|
|
|
+ atomicUnits.map((atomicUnit) => {
|
|
|
+ const elementsInUnit = getElementsInAtomicUnit(atomicUnit, elementsMap);
|
|
|
+
|
|
|
+ if (elementsInUnit.length > 1) {
|
|
|
+ const [x1, y1, x2, y2] = getCommonBounds(
|
|
|
+ elementsInUnit.map((el) => el.latest),
|
|
|
+ );
|
|
|
+ return (
|
|
|
+ Math.round((property === "width" ? x2 - x1 : y2 - y1) * 100) / 100
|
|
|
+ );
|
|
|
+ }
|
|
|
+ const [el] = elementsInUnit;
|
|
|
+
|
|
|
+ return (
|
|
|
+ Math.round(
|
|
|
+ (property === "width" ? el.latest.width : el.latest.height) * 100,
|
|
|
+ ) / 100
|
|
|
+ );
|
|
|
+ }),
|
|
|
+ [elementsMap, atomicUnits, property],
|
|
|
+ );
|
|
|
+
|
|
|
+ const value =
|
|
|
+ new Set(sizes).size === 1 ? Math.round(sizes[0] * 100) / 100 : "Mixed";
|
|
|
+
|
|
|
+ const editable = sizes.length > 0;
|
|
|
|
|
|
return (
|
|
|
<DragInput
|
|
@@ -370,6 +368,9 @@ const MultiDimension = ({
|
|
|
dragInputCallback={handleDimensionChange}
|
|
|
value={value}
|
|
|
editable={editable}
|
|
|
+ appState={appState}
|
|
|
+ property={property}
|
|
|
+ scene={scene}
|
|
|
/>
|
|
|
);
|
|
|
};
|