import { getShortcutKey, updateActiveTool } from "../utils"; import { t } from "../i18n"; import { Action } from "../actions/types"; import { ToolButton } from "./ToolButton"; import clsx from "clsx"; import { Subtype, isValidSubtype, subtypeCollides } from "../subtypes"; import { ExcalidrawElement, Theme } from "../element/types"; export const SubtypeButton = ( subtype: Subtype, parentType: ExcalidrawElement["type"], icon: ({ theme }: { theme: Theme }) => JSX.Element, key?: string, ) => { const title = key !== undefined ? ` - ${getShortcutKey(key)}` : ""; const keyTest: Action["keyTest"] = key !== undefined ? (event) => event.code === `Key${key}` : undefined; const subtypeAction: Action = { name: subtype, trackEvent: false, predicate: (...rest) => rest[4]?.source === subtype, perform: (elements, appState) => { const inactive = !appState.activeSubtypes?.includes(subtype) ?? true; const activeSubtypes: Subtype[] = []; if (appState.activeSubtypes) { activeSubtypes.push(...appState.activeSubtypes); } let activated = false; if (inactive) { // Ensure `element.subtype` is well-defined if (!subtypeCollides(subtype, activeSubtypes)) { activeSubtypes.push(subtype); activated = true; } } else { // Can only be active if appState.activeSubtypes is defined // and contains subtype. activeSubtypes.splice(activeSubtypes.indexOf(subtype), 1); } const type = appState.activeTool.type !== "custom" && isValidSubtype(subtype, appState.activeTool.type) ? appState.activeTool.type : parentType; const activeTool = !inactive ? appState.activeTool : updateActiveTool(appState, { type }); const selectedElementIds = activated ? {} : appState.selectedElementIds; const selectedGroupIds = activated ? {} : appState.selectedGroupIds; return { appState: { ...appState, activeSubtypes, selectedElementIds, selectedGroupIds, activeTool, }, commitToHistory: true, }; }, keyTest, PanelComponent: ({ elements, appState, updateData, data }) => ( { updateData(null); }} onContextMenu={ data && "onContextMenu" in data ? (event: React.MouseEvent) => { if ( appState.activeSubtypes === undefined || (appState.activeSubtypes !== undefined && !appState.activeSubtypes.includes(subtype)) ) { updateData(null); } data.onContextMenu(event, subtype); } : undefined } size={data?.size || "medium"} > ), }; if (key === "") { delete subtypeAction.keyTest; } return subtypeAction; };