From e636f84bb6f3526a5dfe0666757720479ff587d9 Mon Sep 17 00:00:00 2001 From: dwelle <5153846+dwelle@users.noreply.github.com> Date: Wed, 30 Apr 2025 15:42:27 +0200 Subject: [PATCH] file & variable renaming --- packages/common/src/constants.ts | 2 +- .../actions/actionToggleShapeSwitch.tsx | 10 +- packages/excalidraw/components/App.tsx | 40 +++--- .../components/ConvertElementTypePopup.scss | 18 +++ ...Switch.tsx => ConvertElementTypePopup.tsx} | 128 +++++++++--------- .../excalidraw/components/ShapeSwitch.scss | 51 ------- 6 files changed, 111 insertions(+), 138 deletions(-) create mode 100644 packages/excalidraw/components/ConvertElementTypePopup.scss rename packages/excalidraw/components/{ShapeSwitch.tsx => ConvertElementTypePopup.tsx} (87%) delete mode 100644 packages/excalidraw/components/ShapeSwitch.scss diff --git a/packages/common/src/constants.ts b/packages/common/src/constants.ts index 39cd3dcb9..f50d86e4f 100644 --- a/packages/common/src/constants.ts +++ b/packages/common/src/constants.ts @@ -119,7 +119,7 @@ export const CLASSES = { SHAPE_ACTIONS_MENU: "App-menu__left", ZOOM_ACTIONS: "zoom-actions", SEARCH_MENU_INPUT_WRAPPER: "layer-ui__search-inputWrapper", - SHAPE_SWITCH_PANEL_CLASSNAME: "ShapeSwitch__Panel", + CONVERT_ELEMENT_TYPE_POPUP: "ConvertElementTypePopup", }; export const CJK_HAND_DRAWN_FALLBACK_FONT = "Xiaolai"; diff --git a/packages/excalidraw/actions/actionToggleShapeSwitch.tsx b/packages/excalidraw/actions/actionToggleShapeSwitch.tsx index be27960d0..39e7566fb 100644 --- a/packages/excalidraw/actions/actionToggleShapeSwitch.tsx +++ b/packages/excalidraw/actions/actionToggleShapeSwitch.tsx @@ -1,9 +1,9 @@ import type { ExcalidrawElement } from "@excalidraw/element/types"; import { - getSwitchCategoryFromElements, - shapeSwitchAtom, -} from "../components/ShapeSwitch"; + getConversionTypeFromElements, + convertElementTypePopupAtom, +} from "../components/ConvertElementTypePopup"; import { editorJotaiStore } from "../editor-jotai"; import { CaptureUpdateAction } from "../store"; @@ -20,7 +20,7 @@ export const actionToggleShapeSwitch = register({ }, keywords: ["change", "switch", "swap"], perform(elements, appState, _, app) { - editorJotaiStore.set(shapeSwitchAtom, { + editorJotaiStore.set(convertElementTypePopupAtom, { type: "panel", }); @@ -30,5 +30,5 @@ export const actionToggleShapeSwitch = register({ }, checked: (appState) => appState.gridModeEnabled, predicate: (elements, appState, props) => - getSwitchCategoryFromElements(elements as ExcalidrawElement[]) !== null, + getConversionTypeFromElements(elements as ExcalidrawElement[]) !== null, }); diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index d85476cc4..ddb071981 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -468,11 +468,11 @@ import { LassoTrail } from "../lasso"; import { EraserTrail } from "../eraser"; -import ShapeSwitch, { - getSwitchCategoryFromElements, - shapeSwitchAtom, - switchShapes, -} from "./ShapeSwitch"; +import ConvertElementTypePopup, { + getConversionTypeFromElements, + convertElementTypePopupAtom, + convertElementTypes, +} from "./ConvertElementTypePopup"; import { activeConfirmDialogAtom } from "./ActiveConfirmDialog"; import BraveMeasureTextError from "./BraveMeasureTextError"; @@ -1599,7 +1599,7 @@ class App extends React.Component { const firstSelectedElement = selectedElements[0]; const showShapeSwitchPanel = - editorJotaiStore.get(shapeSwitchAtom)?.type === "panel"; + editorJotaiStore.get(convertElementTypePopupAtom)?.type === "panel"; return (
{ /> )} {this.renderFrameNames()} - {showShapeSwitchPanel && } + {showShapeSwitchPanel && ( + + )} {this.renderEmbeddables()} @@ -4178,31 +4180,33 @@ class App extends React.Component { // Shape switching if (event.key === KEYS.ESCAPE) { - this.updateEditorAtom(shapeSwitchAtom, null); + this.updateEditorAtom(convertElementTypePopupAtom, null); } else if ( event.key === KEYS.TAB && (document.activeElement === this.excalidrawContainerRef?.current || document.activeElement?.classList.contains( - CLASSES.SHAPE_SWITCH_PANEL_CLASSNAME, + CLASSES.CONVERT_ELEMENT_TYPE_POPUP, )) ) { event.preventDefault(); - const switchCategory = - getSwitchCategoryFromElements(selectedElements); + const conversionType = + getConversionTypeFromElements(selectedElements); - if (editorJotaiStore.get(shapeSwitchAtom)?.type === "panel") { + if ( + editorJotaiStore.get(convertElementTypePopupAtom)?.type === "panel" + ) { if ( - switchShapes(this, { - switchCategory, + convertElementTypes(this, { + conversionType, direction: event.shiftKey ? "left" : "right", }) ) { this.store.shouldCaptureIncrement(); } } - if (switchCategory) { - this.updateEditorAtom(shapeSwitchAtom, { + if (conversionType) { + this.updateEditorAtom(convertElementTypePopupAtom, { type: "panel", }); } @@ -6418,8 +6422,8 @@ class App extends React.Component { this.updateEditorAtom(searchItemInFocusAtom, null); } - if (editorJotaiStore.get(shapeSwitchAtom)) { - this.updateEditorAtom(shapeSwitchAtom, null); + if (editorJotaiStore.get(convertElementTypePopupAtom)) { + this.updateEditorAtom(convertElementTypePopupAtom, null); } // since contextMenu options are potentially evaluated on each render, diff --git a/packages/excalidraw/components/ConvertElementTypePopup.scss b/packages/excalidraw/components/ConvertElementTypePopup.scss new file mode 100644 index 000000000..414ca9533 --- /dev/null +++ b/packages/excalidraw/components/ConvertElementTypePopup.scss @@ -0,0 +1,18 @@ +@import "../css//variables.module.scss"; + +.excalidraw { + .ConvertElementTypePopup { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.2rem; + border-radius: 0.5rem; + background: var(--island-bg-color); + box-shadow: var(--shadow-island); + padding: 0.5rem; + + &:focus { + outline: none; + } + } +} diff --git a/packages/excalidraw/components/ShapeSwitch.tsx b/packages/excalidraw/components/ConvertElementTypePopup.tsx similarity index 87% rename from packages/excalidraw/components/ShapeSwitch.tsx rename to packages/excalidraw/components/ConvertElementTypePopup.tsx index 50013079a..973d9d523 100644 --- a/packages/excalidraw/components/ShapeSwitch.tsx +++ b/packages/excalidraw/components/ConvertElementTypePopup.tsx @@ -76,7 +76,7 @@ import { import { trackEvent } from "../analytics"; import { atom, editorJotaiStore, useSetAtom } from "../editor-jotai"; -import "./ShapeSwitch.scss"; +import "./ConvertElementTypePopup.scss"; import { ToolButton } from "./ToolButton"; import { DiamondIcon, @@ -124,12 +124,12 @@ const isConvertibleLinearType = ( elementType === "arrow" || CONVERTIBLE_LINEAR_TYPES.has(elementType as ConvertibleLinearTypes); -export const shapeSwitchAtom = atom<{ +export const convertElementTypePopupAtom = atom<{ type: "panel"; } | null>(null); // NOTE doesn't need to be an atom. Review once we integrate with properties panel. -export const shapeSwitchFontSizeAtom = atom<{ +export const fontSize_conversionCacheAtom = atom<{ [id: string]: { fontSize: number; elementType: ConvertibleGenericTypes; @@ -137,7 +137,7 @@ export const shapeSwitchFontSizeAtom = atom<{ } | null>(null); // NOTE doesn't need to be an atom. Review once we integrate with properties panel. -export const shapeSwitchLinearAtom = atom<{ +export const linearElement_conversionCacheAtom = atom<{ [id: string]: { properties: | Partial @@ -146,40 +146,40 @@ export const shapeSwitchLinearAtom = atom<{ }; } | null>(null); -const ShapeSwitch = ({ app }: { app: App }) => { - const setShapeSwitchFontSize = useSetAtom(shapeSwitchFontSizeAtom); - const setShapeSwitchLinear = useSetAtom(shapeSwitchLinearAtom); +const ConvertElementTypePopup = ({ app }: { app: App }) => { + const setFontSizeCache = useSetAtom(fontSize_conversionCacheAtom); + const setLinearElementCache = useSetAtom(linearElement_conversionCacheAtom); const selectedElements = app.scene.getSelectedElements(app.state); - const elementsCategoryRef = useRef(null); + const elementsCategoryRef = useRef(null); // close shape switch panel if selecting different "types" of elements useEffect(() => { if (selectedElements.length === 0) { - app.updateEditorAtom(shapeSwitchAtom, null); + app.updateEditorAtom(convertElementTypePopupAtom, null); return; } - const switchCategory = getSwitchCategoryFromElements(selectedElements); + const conversionType = getConversionTypeFromElements(selectedElements); - if (switchCategory && !elementsCategoryRef.current) { - elementsCategoryRef.current = switchCategory; + if (conversionType && !elementsCategoryRef.current) { + elementsCategoryRef.current = conversionType; } else if ( - (elementsCategoryRef.current && !switchCategory) || + (elementsCategoryRef.current && !conversionType) || (elementsCategoryRef.current && - switchCategory !== elementsCategoryRef.current) + conversionType !== elementsCategoryRef.current) ) { - app.updateEditorAtom(shapeSwitchAtom, null); + app.updateEditorAtom(convertElementTypePopupAtom, null); elementsCategoryRef.current = null; } }, [selectedElements, app]); useEffect(() => { return () => { - setShapeSwitchFontSize(null); - setShapeSwitchLinear(null); + setFontSizeCache(null); + setLinearElementCache(null); }; - }, [setShapeSwitchFontSize, setShapeSwitchLinear]); + }, [setFontSizeCache, setLinearElementCache]); return ; }; @@ -191,15 +191,15 @@ const Panel = ({ app: App; elements: ExcalidrawElement[]; }) => { - const switchCategory = getSwitchCategoryFromElements(elements); - const generic = switchCategory === "generic"; - const linear = switchCategory === "linear"; + const conversionType = getConversionTypeFromElements(elements); + const generic = conversionType === "generic"; + const linear = conversionType === "linear"; const genericElements = useMemo(() => { - return generic ? getGenericSwitchableElements(elements) : []; + return generic ? filterGenericConvetibleElements(elements) : []; }, [generic, elements]); const linearElements = useMemo(() => { - return linear ? getLinearSwitchableElements(elements) : []; + return linear ? filterLinearConvertibleElements(elements) : []; }, [linear, elements]); const sameType = generic @@ -257,7 +257,7 @@ const Panel = ({ }, [genericElements, linearElements, app.scene, app.state]); useEffect(() => { - if (editorJotaiStore.get(shapeSwitchLinearAtom)) { + if (editorJotaiStore.get(linearElement_conversionCacheAtom)) { return; } @@ -274,8 +274,8 @@ const Panel = ({ ? getElbowArrowProperties(linearElement) : {}; - editorJotaiStore.set(shapeSwitchLinearAtom, { - ...editorJotaiStore.get(shapeSwitchLinearAtom), + editorJotaiStore.set(linearElement_conversionCacheAtom, { + ...editorJotaiStore.get(linearElement_conversionCacheAtom), [linearElement.id]: { properties: cachedProperties, initialType, @@ -285,7 +285,7 @@ const Panel = ({ }, [linearElements]); useEffect(() => { - if (editorJotaiStore.get(shapeSwitchFontSizeAtom)) { + if (editorJotaiStore.get(fontSize_conversionCacheAtom)) { return; } @@ -295,8 +295,8 @@ const Panel = ({ app.scene.getNonDeletedElementsMap(), ); if (boundText) { - editorJotaiStore.set(shapeSwitchFontSizeAtom, { - ...editorJotaiStore.get(shapeSwitchFontSizeAtom), + editorJotaiStore.set(fontSize_conversionCacheAtom, { + ...editorJotaiStore.get(fontSize_conversionCacheAtom), [element.id]: { fontSize: boundText.fontSize, elementType: element.type as ConvertibleGenericTypes, @@ -335,7 +335,7 @@ const Panel = ({ left: `${panelPosition.x - app.state.offsetLeft - GAP_HORIZONTAL}px`, zIndex: 2, }} - className={CLASSES.SHAPE_SWITCH_PANEL_CLASSNAME} + className={CLASSES.CONVERT_ELEMENT_TYPE_POPUP} > {SHAPES.map(([type, icon]) => { const isSelected = @@ -350,17 +350,17 @@ const Panel = ({ type="radio" icon={icon} checked={isSelected} - name="shape-switch-option" + name="convertElementType-option" title={type} keyBindingLabel={""} aria-label={type} data-testid={`toolbar-${type}`} onChange={() => { if (app.state.activeTool.type !== type) { - trackEvent("shape-switch", type, "ui"); + trackEvent("convertElementType", type, "ui"); } - switchShapes(app, { - switchCategory, + convertElementTypes(app, { + conversionType, nextType: type as | ConvertibleGenericTypes | ConvertibleLinearTypes, @@ -420,21 +420,21 @@ export const adjustBoundTextSize = ( redrawTextBoundingBox(boundText, container, scene); }; -type SwitchShapeCategory = "generic" | "linear" | null; +type ConversionType = "generic" | "linear" | null; -export const switchShapes = ( +export const convertElementTypes = ( app: App, { - switchCategory, + conversionType, nextType, direction = "right", }: { - switchCategory: SwitchShapeCategory; + conversionType: ConversionType; nextType?: ConvertibleTypes; direction?: "left" | "right"; }, ): boolean => { - if (!switchCategory) { + if (!conversionType) { return false; } @@ -447,16 +447,16 @@ export const switchShapes = ( const advancement = direction === "right" ? 1 : -1; - if (switchCategory === "generic") { - const selectedGenericSwitchableElements = - getGenericSwitchableElements(selectedElements); + if (conversionType === "generic") { + const convertibleGenericElements = + filterGenericConvetibleElements(selectedElements); - const sameType = selectedGenericSwitchableElements.every( - (element) => element.type === selectedGenericSwitchableElements[0].type, + const sameType = convertibleGenericElements.every( + (element) => element.type === convertibleGenericElements[0].type, ); const index = sameType - ? GENERIC_TYPES.indexOf(selectedGenericSwitchableElements[0].type) + ? GENERIC_TYPES.indexOf(convertibleGenericElements[0].type) : -1; nextType = @@ -468,7 +468,7 @@ export const switchShapes = ( if (nextType && isConvertibleGenericType(nextType)) { const convertedElements: Record = {}; - for (const element of selectedGenericSwitchableElements) { + for (const element of convertibleGenericElements) { const convertedElement = convertElementType(element, nextType, app); convertedElements[convertedElement.id] = convertedElement; } @@ -492,12 +492,12 @@ export const switchShapes = ( ); if (boundText) { if ( - editorJotaiStore.get(shapeSwitchFontSizeAtom)?.[element.id] + editorJotaiStore.get(fontSize_conversionCacheAtom)?.[element.id] ?.elementType === nextType ) { mutateElement(boundText, app.scene.getNonDeletedElementsMap(), { fontSize: - editorJotaiStore.get(shapeSwitchFontSizeAtom)?.[element.id] + editorJotaiStore.get(fontSize_conversionCacheAtom)?.[element.id] ?.fontSize ?? boundText.fontSize, }); } @@ -521,13 +521,13 @@ export const switchShapes = ( } } - if (switchCategory === "linear") { - const selectedLinearSwitchableElements = getLinearSwitchableElements( + if (conversionType === "linear") { + const convertibleLinearElements = filterLinearConvertibleElements( selectedElements, ) as ExcalidrawLinearElement[]; - const arrowType = getArrowType(selectedLinearSwitchableElements[0]); - const sameType = selectedLinearSwitchableElements.every( + const arrowType = getArrowType(convertibleLinearElements[0]); + const sameType = convertibleLinearElements.every( (element) => getArrowType(element) === arrowType, ); @@ -540,9 +540,11 @@ export const switchShapes = ( if (nextType && isConvertibleLinearType(nextType)) { const convertedElements: Record = {}; - for (const element of selectedLinearSwitchableElements) { + for (const element of convertibleLinearElements) { const { properties, initialType } = - editorJotaiStore.get(shapeSwitchLinearAtom)?.[element.id] || {}; + editorJotaiStore.get(linearElement_conversionCacheAtom)?.[ + element.id + ] || {}; // If the initial type is not elbow, and when we switch to elbow, // the linear line might be "bent" and the points would likely be different. @@ -597,9 +599,9 @@ export const switchShapes = ( app.scene.replaceAllElements(nextElements); for (const element of Object.values(convertedElements)) { - const cachedLinear = editorJotaiStore.get(shapeSwitchLinearAtom)?.[ - element.id - ]; + const cachedLinear = editorJotaiStore.get( + linearElement_conversionCacheAtom, + )?.[element.id]; if (cachedLinear) { const { properties, initialType } = cachedLinear; @@ -642,7 +644,7 @@ export const switchShapes = ( } } } - const convertedSelectedLinearElements = getLinearSwitchableElements( + const convertedSelectedLinearElements = filterLinearConvertibleElements( app.scene.getSelectedElements(app.state), ); @@ -664,9 +666,9 @@ export const switchShapes = ( return true; }; -export const getSwitchCategoryFromElements = ( +export const getConversionTypeFromElements = ( elements: ExcalidrawElement[], -): SwitchShapeCategory => { +): ConversionType => { if (elements.length === 0) { return null; } @@ -776,14 +778,14 @@ const getElbowArrowProperties = ( return {}; }; -const getGenericSwitchableElements = (elements: ExcalidrawElement[]) => +const filterGenericConvetibleElements = (elements: ExcalidrawElement[]) => elements.filter((element) => isConvertibleGenericType(element.type)) as Array< | ExcalidrawRectangleElement | ExcalidrawDiamondElement | ExcalidrawEllipseElement >; -const getLinearSwitchableElements = (elements: ExcalidrawElement[]) => +const filterLinearConvertibleElements = (elements: ExcalidrawElement[]) => elements.filter((element) => isEligibleLinearElement(element), ) as ExcalidrawLinearElement[]; @@ -1049,4 +1051,4 @@ const isValidConversion = ( return false; }; -export default ShapeSwitch; +export default ConvertElementTypePopup; diff --git a/packages/excalidraw/components/ShapeSwitch.scss b/packages/excalidraw/components/ShapeSwitch.scss deleted file mode 100644 index 4406d32d0..000000000 --- a/packages/excalidraw/components/ShapeSwitch.scss +++ /dev/null @@ -1,51 +0,0 @@ -@import "../css//variables.module.scss"; - -@keyframes disappear { - from { - opacity: 1; - } - to { - opacity: 0; - } -} - -.excalidraw { - .ShapeSwitch__Hint { - display: flex; - align-items: center; - justify-content: center; - opacity: 0; - - .key { - background: var(--color-primary-light); - padding: 0.4rem 0.8rem; - font-weight: bold; - border-radius: 0.5rem; - box-shadow: 0 0 0.5rem rgba(0, 0, 0, 0.1); - } - - .text { - margin-left: 0.5rem; - } - } - - .animation { - opacity: 1; - animation: disappear 2s ease-out; - } - - .ShapeSwitch__Panel { - display: flex; - flex-wrap: wrap; - justify-content: center; - gap: 0.2rem; - border-radius: 0.5rem; - background: var(--island-bg-color); - box-shadow: var(--shadow-island); - padding: 0.5rem; - - &:focus { - outline: none; - } - } -}