diff --git a/src/actions/actionAlign.tsx b/src/actions/actionAlign.tsx new file mode 100644 index 00000000..2b130df4 --- /dev/null +++ b/src/actions/actionAlign.tsx @@ -0,0 +1,221 @@ +import React from "react"; +import { KEYS } from "../keys"; +import { t } from "../i18n"; +import { register } from "./register"; +import { + AlignBottomIcon, + AlignLeftIcon, + AlignRightIcon, + AlignTopIcon, + CenterHorizontallyIcon, + CenterVerticallyIcon, +} from "../components/icons"; +import { getSelectedElements, isSomeElementSelected } from "../scene"; +import { getElementMap, getNonDeletedElements } from "../element"; +import { ToolButton } from "../components/ToolButton"; +import { ExcalidrawElement } from "../element/types"; +import { AppState } from "../types"; +import { alignElements, Alignment } from "../align"; +import { getShortcutKey } from "../utils"; + +const enableActionGroup = ( + elements: readonly ExcalidrawElement[], + appState: AppState, +) => getSelectedElements(getNonDeletedElements(elements), appState).length > 1; + +function alignSelectedElements( + elements: readonly ExcalidrawElement[], + appState: Readonly, + alignment: Alignment, +) { + const selectedElements = getSelectedElements( + getNonDeletedElements(elements), + appState, + ); + + const updatedElements = alignElements(selectedElements, alignment); + + const updatedElementsMap = getElementMap(updatedElements); + + return elements.map((element) => updatedElementsMap[element.id] || element); +} + +export const actionAlignTop = register({ + name: "alignTop", + perform: (elements, appState) => { + return { + appState, + elements: alignSelectedElements(elements, appState, { + position: "start", + axis: "y", + }), + commitToHistory: true, + }; + }, + keyTest: (event) => { + return ( + event[KEYS.CTRL_OR_CMD] && event.shiftKey && event.key === KEYS.ARROW_UP + ); + }, + PanelComponent: ({ elements, appState, updateData }) => ( +