mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
do not switch from active tool change
This commit is contained in:
parent
64bd73762e
commit
31d2c0b7e9
4 changed files with 225 additions and 165 deletions
|
@ -191,9 +191,7 @@ import {
|
||||||
isFlowchartNodeElement,
|
isFlowchartNodeElement,
|
||||||
isBindableElement,
|
isBindableElement,
|
||||||
areGenericSwitchableElements,
|
areGenericSwitchableElements,
|
||||||
isGenericSwitchableToolType,
|
|
||||||
areLinearSwitchableElements,
|
areLinearSwitchableElements,
|
||||||
isLinearSwitchableToolType,
|
|
||||||
} from "../element/typeChecks";
|
} from "../element/typeChecks";
|
||||||
import { getCenter, getDistance } from "../gesture";
|
import { getCenter, getDistance } from "../gesture";
|
||||||
import {
|
import {
|
||||||
|
@ -387,11 +385,9 @@ import {
|
||||||
} from "../element/textMeasurements";
|
} from "../element/textMeasurements";
|
||||||
|
|
||||||
import ShapeSwitch, {
|
import ShapeSwitch, {
|
||||||
adjustBoundTextSize,
|
|
||||||
GENERIC_SWITCHABLE_SHAPES,
|
|
||||||
LINEAR_SWITCHABLE_SHAPES,
|
|
||||||
shapeSwitchAtom,
|
shapeSwitchAtom,
|
||||||
shapeSwitchFontSizeAtom,
|
shapeSwitchFontSizeAtom,
|
||||||
|
switchShapes,
|
||||||
} from "./ShapeSwitch";
|
} from "./ShapeSwitch";
|
||||||
|
|
||||||
import { activeConfirmDialogAtom } from "./ActiveConfirmDialog";
|
import { activeConfirmDialogAtom } from "./ActiveConfirmDialog";
|
||||||
|
@ -443,7 +439,6 @@ import type {
|
||||||
ExcalidrawNonSelectionElement,
|
ExcalidrawNonSelectionElement,
|
||||||
ExcalidrawArrowElement,
|
ExcalidrawArrowElement,
|
||||||
GenericSwitchableToolType,
|
GenericSwitchableToolType,
|
||||||
LinearSwitchableToolType,
|
|
||||||
} from "../element/types";
|
} from "../element/types";
|
||||||
import type {
|
import type {
|
||||||
RenderInteractiveSceneCallback,
|
RenderInteractiveSceneCallback,
|
||||||
|
@ -4104,46 +4099,28 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const genericSwitchable =
|
// Shape switching
|
||||||
areGenericSwitchableElements(selectedElements);
|
if (event.key === KEYS.ESCAPE) {
|
||||||
const linearSwitchable = areLinearSwitchableElements(selectedElements);
|
editorJotaiStore.set(shapeSwitchAtom, null);
|
||||||
|
} else if (event.key === KEYS.TAB) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
if (genericSwitchable || linearSwitchable) {
|
const genericSwitchable =
|
||||||
const firstElement = selectedElements[0];
|
areGenericSwitchableElements(selectedElements);
|
||||||
|
const linearSwitchable =
|
||||||
|
areLinearSwitchableElements(selectedElements);
|
||||||
|
|
||||||
if (event.key === KEYS.ESCAPE) {
|
if (editorJotaiStore.get(shapeSwitchAtom)?.type === "panel") {
|
||||||
editorJotaiStore.set(shapeSwitchAtom, null);
|
if (
|
||||||
} else if (event.key === KEYS.TAB) {
|
switchShapes(this, {
|
||||||
event.preventDefault();
|
genericSwitchable,
|
||||||
|
linearSwitchable,
|
||||||
if (editorJotaiStore.get(shapeSwitchAtom)?.type === "panel") {
|
})
|
||||||
const sameType = selectedElements.every(
|
) {
|
||||||
(element) => element.type === selectedElements[0].type,
|
this.store.shouldCaptureIncrement();
|
||||||
);
|
|
||||||
|
|
||||||
let nextType;
|
|
||||||
|
|
||||||
if (genericSwitchable) {
|
|
||||||
const index = sameType
|
|
||||||
? GENERIC_SWITCHABLE_SHAPES.indexOf(selectedElements[0].type)
|
|
||||||
: -1;
|
|
||||||
|
|
||||||
nextType = GENERIC_SWITCHABLE_SHAPES[
|
|
||||||
(index + 1) % GENERIC_SWITCHABLE_SHAPES.length
|
|
||||||
] as ToolType;
|
|
||||||
this.setActiveTool({ type: nextType });
|
|
||||||
} else if (linearSwitchable) {
|
|
||||||
const index = sameType
|
|
||||||
? LINEAR_SWITCHABLE_SHAPES.indexOf(selectedElements[0].type)
|
|
||||||
: -1;
|
|
||||||
|
|
||||||
nextType = LINEAR_SWITCHABLE_SHAPES[
|
|
||||||
(index + 1) % LINEAR_SWITCHABLE_SHAPES.length
|
|
||||||
] as ToolType;
|
|
||||||
this.setActiveTool({ type: nextType });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (genericSwitchable || linearSwitchable) {
|
||||||
editorJotaiStore.set(shapeSwitchAtom, {
|
editorJotaiStore.set(shapeSwitchAtom, {
|
||||||
type: "panel",
|
type: "panel",
|
||||||
});
|
});
|
||||||
|
@ -4153,7 +4130,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
element,
|
element,
|
||||||
this.scene.getNonDeletedElementsMap(),
|
this.scene.getNonDeletedElementsMap(),
|
||||||
);
|
);
|
||||||
if (boundText && genericSwitchable && firstElement) {
|
if (boundText && genericSwitchable && element) {
|
||||||
editorJotaiStore.set(shapeSwitchFontSizeAtom, {
|
editorJotaiStore.set(shapeSwitchFontSizeAtom, {
|
||||||
...editorJotaiStore.get(shapeSwitchFontSizeAtom),
|
...editorJotaiStore.get(shapeSwitchFontSizeAtom),
|
||||||
[element.id]: {
|
[element.id]: {
|
||||||
|
@ -4822,106 +4799,6 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
...commonResets,
|
...commonResets,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectedElements = getSelectedElements(
|
|
||||||
this.scene.getNonDeletedElementsMap(),
|
|
||||||
this.state,
|
|
||||||
);
|
|
||||||
const selectedElementIds = selectedElements.reduce(
|
|
||||||
(acc, element) => ({ ...acc, [element.id]: true }),
|
|
||||||
{},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
|
||||||
areGenericSwitchableElements(selectedElements) &&
|
|
||||||
isGenericSwitchableToolType(tool.type)
|
|
||||||
) {
|
|
||||||
selectedElements.forEach((element) => {
|
|
||||||
ShapeCache.delete(element);
|
|
||||||
|
|
||||||
mutateElement(
|
|
||||||
element,
|
|
||||||
{
|
|
||||||
type: tool.type as GenericSwitchableToolType,
|
|
||||||
roundness:
|
|
||||||
tool.type === "diamond" && element.roundness
|
|
||||||
? {
|
|
||||||
type: isUsingAdaptiveRadius(tool.type)
|
|
||||||
? ROUNDNESS.ADAPTIVE_RADIUS
|
|
||||||
: ROUNDNESS.PROPORTIONAL_RADIUS,
|
|
||||||
value: ROUNDNESS.PROPORTIONAL_RADIUS,
|
|
||||||
}
|
|
||||||
: element.roundness,
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
const boundText = getBoundTextElement(
|
|
||||||
element,
|
|
||||||
this.scene.getNonDeletedElementsMap(),
|
|
||||||
);
|
|
||||||
if (boundText) {
|
|
||||||
if (
|
|
||||||
editorJotaiStore.get(shapeSwitchFontSizeAtom)?.[element.id]
|
|
||||||
?.elementType === tool.type
|
|
||||||
) {
|
|
||||||
mutateElement(
|
|
||||||
boundText,
|
|
||||||
{
|
|
||||||
fontSize:
|
|
||||||
editorJotaiStore.get(shapeSwitchFontSizeAtom)?.[element.id]
|
|
||||||
?.fontSize ?? boundText.fontSize,
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
adjustBoundTextSize(
|
|
||||||
element,
|
|
||||||
boundText,
|
|
||||||
this.scene.getNonDeletedElementsMap(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.setState((prevState) => {
|
|
||||||
return {
|
|
||||||
selectedElementIds,
|
|
||||||
activeTool: updateActiveTool(prevState, { type: "selection" }),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
this.store.shouldCaptureIncrement();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
areLinearSwitchableElements(selectedElements) &&
|
|
||||||
isLinearSwitchableToolType(tool.type)
|
|
||||||
) {
|
|
||||||
selectedElements.forEach((element) => {
|
|
||||||
ShapeCache.delete(element);
|
|
||||||
|
|
||||||
mutateElement(
|
|
||||||
element as ExcalidrawLinearElement,
|
|
||||||
{
|
|
||||||
type: tool.type as LinearSwitchableToolType,
|
|
||||||
startArrowhead: null,
|
|
||||||
endArrowhead: tool.type === "arrow" ? "arrow" : null,
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
const firstElement = selectedElements[0];
|
|
||||||
|
|
||||||
this.setState((prevState) => ({
|
|
||||||
selectedElementIds,
|
|
||||||
selectedLinearElement:
|
|
||||||
selectedElements.length === 1
|
|
||||||
? new LinearElementEditor(firstElement as ExcalidrawLinearElement)
|
|
||||||
: null,
|
|
||||||
activeTool: updateActiveTool(prevState, { type: "selection" }),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
setOpenDialog = (dialogType: AppState["openDialog"]) => {
|
setOpenDialog = (dialogType: AppState["openDialog"]) => {
|
||||||
|
|
|
@ -1,20 +1,31 @@
|
||||||
import { type ReactNode, useEffect, useRef } from "react";
|
import { type ReactNode, useEffect, useMemo, useRef } from "react";
|
||||||
|
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
import { pointFrom, pointRotateRads } from "@excalidraw/math";
|
import { pointFrom, pointRotateRads } from "@excalidraw/math";
|
||||||
|
|
||||||
import { atom, useAtom } from "../editor-jotai";
|
import { atom, editorJotaiStore, useAtom } from "../editor-jotai";
|
||||||
|
|
||||||
import { getElementAbsoluteCoords, refreshTextDimensions } from "../element";
|
import { getElementAbsoluteCoords, refreshTextDimensions } from "../element";
|
||||||
import { getFontString, sceneCoordsToViewportCoords } from "../utils";
|
import {
|
||||||
|
getFontString,
|
||||||
|
sceneCoordsToViewportCoords,
|
||||||
|
updateActiveTool,
|
||||||
|
} from "../utils";
|
||||||
import { getSelectedElements } from "../scene";
|
import { getSelectedElements } from "../scene";
|
||||||
import { trackEvent } from "../analytics";
|
import { trackEvent } from "../analytics";
|
||||||
import { isArrowElement, isLinearElement } from "../element/typeChecks";
|
import {
|
||||||
|
areGenericSwitchableElements,
|
||||||
|
areLinearSwitchableElements,
|
||||||
|
isArrowElement,
|
||||||
|
isLinearElement,
|
||||||
|
isUsingAdaptiveRadius,
|
||||||
|
} from "../element/typeChecks";
|
||||||
import { t } from "../i18n";
|
import { t } from "../i18n";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
computeBoundTextPosition,
|
computeBoundTextPosition,
|
||||||
|
getBoundTextElement,
|
||||||
getBoundTextMaxHeight,
|
getBoundTextMaxHeight,
|
||||||
getBoundTextMaxWidth,
|
getBoundTextMaxWidth,
|
||||||
} from "../element/textElement";
|
} from "../element/textElement";
|
||||||
|
@ -22,6 +33,9 @@ import { wrapText } from "../element/textWrapping";
|
||||||
import { measureText } from "../element/textMeasurements";
|
import { measureText } from "../element/textMeasurements";
|
||||||
import { mutateElement } from "../element/mutateElement";
|
import { mutateElement } from "../element/mutateElement";
|
||||||
import { getCommonBoundingBox } from "../element/bounds";
|
import { getCommonBoundingBox } from "../element/bounds";
|
||||||
|
import { ShapeCache } from "../scene/ShapeCache";
|
||||||
|
import { ROUNDNESS } from "../constants";
|
||||||
|
import { LinearElementEditor } from "../element/linearElementEditor";
|
||||||
|
|
||||||
import { ToolButton } from "./ToolButton";
|
import { ToolButton } from "./ToolButton";
|
||||||
import {
|
import {
|
||||||
|
@ -38,11 +52,12 @@ import type App from "./App";
|
||||||
import type {
|
import type {
|
||||||
ElementsMap,
|
ElementsMap,
|
||||||
ExcalidrawElement,
|
ExcalidrawElement,
|
||||||
|
ExcalidrawLinearElement,
|
||||||
ExcalidrawTextContainer,
|
ExcalidrawTextContainer,
|
||||||
ExcalidrawTextElementWithContainer,
|
ExcalidrawTextElementWithContainer,
|
||||||
GenericSwitchableToolType,
|
GenericSwitchableToolType,
|
||||||
|
LinearSwitchableToolType,
|
||||||
} from "../element/types";
|
} from "../element/types";
|
||||||
import type { ToolType } from "../types";
|
|
||||||
|
|
||||||
const GAP_HORIZONTAL = 8;
|
const GAP_HORIZONTAL = 8;
|
||||||
const GAP_VERTICAL = 10;
|
const GAP_VERTICAL = 10;
|
||||||
|
@ -72,21 +87,42 @@ const ShapeSwitch = ({ app }: { app: App }) => {
|
||||||
const [shapeSwitch, setShapeSwitch] = useAtom(shapeSwitchAtom);
|
const [shapeSwitch, setShapeSwitch] = useAtom(shapeSwitchAtom);
|
||||||
const [, setShapeSwitchFontSize] = useAtom(shapeSwitchFontSizeAtom);
|
const [, setShapeSwitchFontSize] = useAtom(shapeSwitchFontSizeAtom);
|
||||||
|
|
||||||
|
const selectedElements = useMemo(
|
||||||
|
() => getSelectedElements(app.scene.getNonDeletedElementsMap(), app.state),
|
||||||
|
[app.scene, app.state],
|
||||||
|
);
|
||||||
|
const selectedElementsTypeRef = useRef<"generic" | "linear">(null);
|
||||||
|
|
||||||
|
// close shape switch panel if selecting different "types" of elements
|
||||||
|
useEffect(() => {
|
||||||
|
const selectedElementsType = areGenericSwitchableElements(selectedElements)
|
||||||
|
? "generic"
|
||||||
|
: areLinearSwitchableElements(selectedElements)
|
||||||
|
? "linear"
|
||||||
|
: null;
|
||||||
|
|
||||||
|
if (selectedElementsType && !selectedElementsTypeRef.current) {
|
||||||
|
selectedElementsTypeRef.current = selectedElementsType;
|
||||||
|
} else if (
|
||||||
|
(selectedElementsTypeRef.current && !selectedElementsType) ||
|
||||||
|
(selectedElementsTypeRef.current &&
|
||||||
|
selectedElementsType !== selectedElementsTypeRef.current)
|
||||||
|
) {
|
||||||
|
setShapeSwitch(null);
|
||||||
|
selectedElementsTypeRef.current = null;
|
||||||
|
}
|
||||||
|
}, [selectedElements, app.state.selectedElementIds, setShapeSwitch]);
|
||||||
|
|
||||||
// clear if not active
|
// clear if not active
|
||||||
if (!shapeSwitch) {
|
if (!shapeSwitch) {
|
||||||
setShapeSwitchFontSize(null);
|
setShapeSwitchFontSize(null);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedElements = getSelectedElements(
|
|
||||||
app.scene.getNonDeletedElementsMap(),
|
|
||||||
app.state,
|
|
||||||
);
|
|
||||||
|
|
||||||
// clear if hint target no longer matches
|
// clear if hint target no longer matches
|
||||||
if (
|
if (
|
||||||
shapeSwitch.type === "hint" &&
|
shapeSwitch.type === "hint" &&
|
||||||
selectedElements?.[0]?.id !== shapeSwitch.id
|
selectedElements[0]?.id !== shapeSwitch.id
|
||||||
) {
|
) {
|
||||||
setShapeSwitch(null);
|
setShapeSwitch(null);
|
||||||
return null;
|
return null;
|
||||||
|
@ -283,7 +319,13 @@ const Panel = ({
|
||||||
if (app.state.activeTool.type !== type) {
|
if (app.state.activeTool.type !== type) {
|
||||||
trackEvent("shape-switch", type, "ui");
|
trackEvent("shape-switch", type, "ui");
|
||||||
}
|
}
|
||||||
app.setActiveTool({ type: type as ToolType });
|
switchShapes(app, {
|
||||||
|
genericSwitchable: GENERIC_SWITCHABLE_SHAPES.includes(type),
|
||||||
|
linearSwitchable: LINEAR_SWITCHABLE_SHAPES.includes(type),
|
||||||
|
nextType: type as
|
||||||
|
| GenericSwitchableToolType
|
||||||
|
| LinearSwitchableToolType,
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -365,4 +407,146 @@ export const adjustBoundTextSize = (
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const switchShapes = (
|
||||||
|
app: App,
|
||||||
|
{
|
||||||
|
genericSwitchable,
|
||||||
|
linearSwitchable,
|
||||||
|
nextType,
|
||||||
|
}: {
|
||||||
|
genericSwitchable?: boolean;
|
||||||
|
linearSwitchable?: boolean;
|
||||||
|
nextType?: GenericSwitchableToolType | LinearSwitchableToolType;
|
||||||
|
} = {},
|
||||||
|
): boolean => {
|
||||||
|
if (!genericSwitchable && !linearSwitchable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectedElements = getSelectedElements(
|
||||||
|
app.scene.getNonDeletedElementsMap(),
|
||||||
|
app.state,
|
||||||
|
);
|
||||||
|
|
||||||
|
const selectedElementIds = selectedElements.reduce(
|
||||||
|
(acc, element) => ({ ...acc, [element.id]: true }),
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
|
||||||
|
const sameType = selectedElements.every(
|
||||||
|
(element) => element.type === selectedElements[0].type,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (genericSwitchable) {
|
||||||
|
// TODO: filter generic elements
|
||||||
|
const index = sameType
|
||||||
|
? GENERIC_SWITCHABLE_SHAPES.indexOf(selectedElements[0].type)
|
||||||
|
: -1;
|
||||||
|
|
||||||
|
nextType =
|
||||||
|
nextType ??
|
||||||
|
(GENERIC_SWITCHABLE_SHAPES[
|
||||||
|
(index + 1) % GENERIC_SWITCHABLE_SHAPES.length
|
||||||
|
] as GenericSwitchableToolType);
|
||||||
|
|
||||||
|
selectedElements.forEach((element) => {
|
||||||
|
ShapeCache.delete(element);
|
||||||
|
|
||||||
|
mutateElement(
|
||||||
|
element,
|
||||||
|
{
|
||||||
|
type: nextType as GenericSwitchableToolType,
|
||||||
|
roundness:
|
||||||
|
nextType === "diamond" && element.roundness
|
||||||
|
? {
|
||||||
|
type: isUsingAdaptiveRadius(nextType)
|
||||||
|
? ROUNDNESS.ADAPTIVE_RADIUS
|
||||||
|
: ROUNDNESS.PROPORTIONAL_RADIUS,
|
||||||
|
value: ROUNDNESS.PROPORTIONAL_RADIUS,
|
||||||
|
}
|
||||||
|
: element.roundness,
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
const boundText = getBoundTextElement(
|
||||||
|
element,
|
||||||
|
app.scene.getNonDeletedElementsMap(),
|
||||||
|
);
|
||||||
|
if (boundText) {
|
||||||
|
if (
|
||||||
|
editorJotaiStore.get(shapeSwitchFontSizeAtom)?.[element.id]
|
||||||
|
?.elementType === nextType
|
||||||
|
) {
|
||||||
|
mutateElement(
|
||||||
|
boundText,
|
||||||
|
{
|
||||||
|
fontSize:
|
||||||
|
editorJotaiStore.get(shapeSwitchFontSizeAtom)?.[element.id]
|
||||||
|
?.fontSize ?? boundText.fontSize,
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
adjustBoundTextSize(
|
||||||
|
element as ExcalidrawTextContainer,
|
||||||
|
boundText,
|
||||||
|
app.scene.getNonDeletedElementsMap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.setState((prevState) => {
|
||||||
|
return {
|
||||||
|
selectedElementIds,
|
||||||
|
activeTool: updateActiveTool(prevState, {
|
||||||
|
type: "selection",
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linearSwitchable) {
|
||||||
|
const index = sameType
|
||||||
|
? LINEAR_SWITCHABLE_SHAPES.indexOf(selectedElements[0].type)
|
||||||
|
: -1;
|
||||||
|
nextType =
|
||||||
|
nextType ??
|
||||||
|
(LINEAR_SWITCHABLE_SHAPES[
|
||||||
|
(index + 1) % LINEAR_SWITCHABLE_SHAPES.length
|
||||||
|
] as LinearSwitchableToolType);
|
||||||
|
|
||||||
|
selectedElements.forEach((element) => {
|
||||||
|
ShapeCache.delete(element);
|
||||||
|
|
||||||
|
mutateElement(
|
||||||
|
element as ExcalidrawLinearElement,
|
||||||
|
{
|
||||||
|
type: nextType as LinearSwitchableToolType,
|
||||||
|
startArrowhead: null,
|
||||||
|
endArrowhead: nextType === "arrow" ? "arrow" : null,
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
const firstElement = selectedElements[0];
|
||||||
|
|
||||||
|
app.setState((prevState) => ({
|
||||||
|
selectedElementIds,
|
||||||
|
selectedLinearElement:
|
||||||
|
selectedElements.length === 1
|
||||||
|
? new LinearElementEditor(firstElement as ExcalidrawLinearElement)
|
||||||
|
: null,
|
||||||
|
activeTool: updateActiveTool(prevState, {
|
||||||
|
type: "selection",
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const switchLinearShapes = (app: App) => {};
|
||||||
|
|
||||||
export default ShapeSwitch;
|
export default ShapeSwitch;
|
||||||
|
|
|
@ -27,11 +27,9 @@ import type {
|
||||||
PointBinding,
|
PointBinding,
|
||||||
FixedPointBinding,
|
FixedPointBinding,
|
||||||
ExcalidrawFlowchartNodeElement,
|
ExcalidrawFlowchartNodeElement,
|
||||||
ExcalidrawRectangleElement,
|
|
||||||
ExcalidrawEllipseElement,
|
|
||||||
ExcalidrawDiamondElement,
|
|
||||||
GenericSwitchableToolType,
|
GenericSwitchableToolType,
|
||||||
LinearSwitchableToolType,
|
LinearSwitchableToolType,
|
||||||
|
ExcalidrawGenericSwitchableElement,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
export const isInitializedImageElement = (
|
export const isInitializedImageElement = (
|
||||||
|
@ -345,11 +343,6 @@ export const isBounds = (box: unknown): box is Bounds =>
|
||||||
|
|
||||||
type NonEmptyArray<T> = [T, ...T[]];
|
type NonEmptyArray<T> = [T, ...T[]];
|
||||||
|
|
||||||
type ExcalidrawGenericSwitchableElement =
|
|
||||||
| ExcalidrawRectangleElement
|
|
||||||
| ExcalidrawEllipseElement
|
|
||||||
| ExcalidrawDiamondElement;
|
|
||||||
|
|
||||||
export const areGenericSwitchableElements = (
|
export const areGenericSwitchableElements = (
|
||||||
elements: ExcalidrawElement[],
|
elements: ExcalidrawElement[],
|
||||||
): elements is NonEmptyArray<ExcalidrawGenericSwitchableElement> => {
|
): elements is NonEmptyArray<ExcalidrawGenericSwitchableElement> => {
|
||||||
|
@ -379,7 +372,9 @@ export const areLinearSwitchableElements = (
|
||||||
const firstType = elements[0].type;
|
const firstType = elements[0].type;
|
||||||
return (
|
return (
|
||||||
(firstType === "arrow" || firstType === "line") &&
|
(firstType === "arrow" || firstType === "line") &&
|
||||||
elements.every((element) => element.type === firstType)
|
elements.every(
|
||||||
|
(element) => element.type === "arrow" || element.type === "line",
|
||||||
|
)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -414,3 +414,7 @@ export type ElementsMapOrArray =
|
||||||
|
|
||||||
export type GenericSwitchableToolType = "rectangle" | "ellipse" | "diamond";
|
export type GenericSwitchableToolType = "rectangle" | "ellipse" | "diamond";
|
||||||
export type LinearSwitchableToolType = "line" | "arrow";
|
export type LinearSwitchableToolType = "line" | "arrow";
|
||||||
|
export type ExcalidrawGenericSwitchableElement =
|
||||||
|
| ExcalidrawRectangleElement
|
||||||
|
| ExcalidrawEllipseElement
|
||||||
|
| ExcalidrawDiamondElement;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue