From aa9139ad78a2e022f2edfb57e8d88eb975ff8391 Mon Sep 17 00:00:00 2001 From: Ryan Di Date: Mon, 24 Mar 2025 12:07:57 +1100 Subject: [PATCH] switch different types altogether --- packages/excalidraw/components/App.tsx | 49 ++++++++++++------- .../excalidraw/components/ShapeSwitch.tsx | 27 +++++----- packages/excalidraw/element/typeChecks.ts | 15 +++--- 3 files changed, 53 insertions(+), 38 deletions(-) diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 4c2aa7827..c5ce5eeef 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -193,9 +193,9 @@ import { isElbowArrow, isFlowchartNodeElement, isBindableElement, - isGenericSwitchableElement, + areGenericSwitchableElements, isGenericSwitchableToolType, - isLinearSwitchableElement, + areLinearSwitchableElements, isLinearSwitchableToolType, } from "../element/typeChecks"; import { getCenter, getDistance } from "../gesture"; @@ -4110,8 +4110,9 @@ class App extends React.Component { return; } - const genericSwitchable = isGenericSwitchableElement(selectedElements); - const linearSwitchable = isLinearSwitchableElement(selectedElements); + const genericSwitchable = + areGenericSwitchableElements(selectedElements); + const linearSwitchable = areLinearSwitchableElements(selectedElements); if (genericSwitchable || linearSwitchable) { const firstElement = selectedElements[0]; @@ -4122,21 +4123,31 @@ class App extends React.Component { event.preventDefault(); if (editorJotaiStore.get(shapeSwitchAtom)?.type === "panel") { - const index = genericSwitchable - ? GENERIC_SWITCHABLE_SHAPES.indexOf(selectedElements[0].type) - : LINEAR_SWITCHABLE_SHAPES.indexOf(selectedElements[0].type); + const sameType = selectedElements.every( + (element) => element.type === selectedElements[0].type, + ); - const nextType = ( - genericSwitchable - ? GENERIC_SWITCHABLE_SHAPES[ - (index + 1) % GENERIC_SWITCHABLE_SHAPES.length - ] - : LINEAR_SWITCHABLE_SHAPES[ - (index + 1) % LINEAR_SWITCHABLE_SHAPES.length - ] - ) as ToolType; + let nextType; - this.setActiveTool({ type: 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 }); + } } editorJotaiStore.set(shapeSwitchAtom, { @@ -4827,7 +4838,7 @@ class App extends React.Component { ); if ( - isGenericSwitchableElement(selectedElements) && + areGenericSwitchableElements(selectedElements) && isGenericSwitchableToolType(tool.type) ) { selectedElements.forEach((element) => { @@ -4889,7 +4900,7 @@ class App extends React.Component { } if ( - isLinearSwitchableElement(selectedElements) && + areLinearSwitchableElements(selectedElements) && isLinearSwitchableToolType(tool.type) ) { selectedElements.forEach((element) => { diff --git a/packages/excalidraw/components/ShapeSwitch.tsx b/packages/excalidraw/components/ShapeSwitch.tsx index a1dfbcf64..13387b506 100644 --- a/packages/excalidraw/components/ShapeSwitch.tsx +++ b/packages/excalidraw/components/ShapeSwitch.tsx @@ -192,6 +192,10 @@ const Panel = ({ let [x1, y2, cx, cy] = [0, 0, 0, 0]; let rotatedBottomLeft = [0, 0]; + const sameType = elements.every( + (element) => element.type === elements[0].type, + ); + if (elements.length === 1) { [x1, , , y2, cx, cy] = getElementAbsoluteCoords( elements[0], @@ -245,17 +249,18 @@ const Panel = ({ > {SHAPES.map(([type, shortcut, icon]) => { const isSelected = - type === elements[0].type || - (isArrowElement(elements[0]) && - elements[0].elbowed && - type === "elbow") || - (isArrowElement(elements[0]) && - elements[0].roundness && - type === "curve") || - (isArrowElement(elements[0]) && - !elements[0].elbowed && - !elements[0].roundness && - type === "straight"); + sameType && + (type === elements[0].type || + (isArrowElement(elements[0]) && + elements[0].elbowed && + type === "elbow") || + (isArrowElement(elements[0]) && + elements[0].roundness && + type === "curve") || + (isArrowElement(elements[0]) && + !elements[0].elbowed && + !elements[0].roundness && + type === "straight")); return ( => { if (elements.length === 0) { return false; } - const firstType = elements[0].type; - return ( - (firstType === "rectangle" || - firstType === "ellipse" || - firstType === "diamond") && - elements.every((element) => element.type === firstType) + return elements.every( + (element) => + element.type === "rectangle" || + element.type === "ellipse" || + element.type === "diamond", ); }; @@ -371,7 +370,7 @@ export const isGenericSwitchableToolType = ( return type === "rectangle" || type === "ellipse" || type === "diamond"; }; -export const isLinearSwitchableElement = ( +export const areLinearSwitchableElements = ( elements: ExcalidrawElement[], ): elements is NonEmptyArray => { if (elements.length === 0) {