|
@@ -30,11 +30,15 @@ import {
|
|
|
TextAlignCenterIcon,
|
|
|
TextAlignLeftIcon,
|
|
|
TextAlignRightIcon,
|
|
|
+ TextAlignTopIcon,
|
|
|
+ TextAlignBottomIcon,
|
|
|
+ TextAlignMiddleIcon,
|
|
|
} from "../components/icons";
|
|
|
import {
|
|
|
DEFAULT_FONT_FAMILY,
|
|
|
DEFAULT_FONT_SIZE,
|
|
|
FONT_FAMILY,
|
|
|
+ VERTICAL_ALIGN,
|
|
|
} from "../constants";
|
|
|
import {
|
|
|
getNonDeletedElements,
|
|
@@ -58,6 +62,7 @@ import {
|
|
|
ExcalidrawTextElement,
|
|
|
FontFamilyValues,
|
|
|
TextAlign,
|
|
|
+ VerticalAlign,
|
|
|
} from "../element/types";
|
|
|
import { getLanguage, t } from "../i18n";
|
|
|
import { KEYS } from "../keys";
|
|
@@ -713,9 +718,7 @@ export const actionChangeTextAlign = register({
|
|
|
if (isTextElement(oldElement)) {
|
|
|
const newElement: ExcalidrawTextElement = newElementWith(
|
|
|
oldElement,
|
|
|
- {
|
|
|
- textAlign: value,
|
|
|
- },
|
|
|
+ { textAlign: value },
|
|
|
);
|
|
|
redrawTextBoundingBox(
|
|
|
newElement,
|
|
@@ -736,47 +739,119 @@ export const actionChangeTextAlign = register({
|
|
|
commitToHistory: true,
|
|
|
};
|
|
|
},
|
|
|
- PanelComponent: ({ elements, appState, updateData }) => (
|
|
|
- <fieldset>
|
|
|
- <legend>{t("labels.textAlign")}</legend>
|
|
|
- <ButtonIconSelect<TextAlign | false>
|
|
|
- group="text-align"
|
|
|
- options={[
|
|
|
- {
|
|
|
- value: "left",
|
|
|
- text: t("labels.left"),
|
|
|
- icon: <TextAlignLeftIcon theme={appState.theme} />,
|
|
|
- },
|
|
|
- {
|
|
|
- value: "center",
|
|
|
- text: t("labels.center"),
|
|
|
- icon: <TextAlignCenterIcon theme={appState.theme} />,
|
|
|
- },
|
|
|
- {
|
|
|
- value: "right",
|
|
|
- text: t("labels.right"),
|
|
|
- icon: <TextAlignRightIcon theme={appState.theme} />,
|
|
|
- },
|
|
|
- ]}
|
|
|
- value={getFormValue(
|
|
|
- elements,
|
|
|
- appState,
|
|
|
- (element) => {
|
|
|
- if (isTextElement(element)) {
|
|
|
- return element.textAlign;
|
|
|
+ PanelComponent: ({ elements, appState, updateData }) => {
|
|
|
+ return (
|
|
|
+ <fieldset>
|
|
|
+ <legend>{t("labels.textAlign")}</legend>
|
|
|
+ <ButtonIconSelect<TextAlign | false>
|
|
|
+ group="text-align"
|
|
|
+ options={[
|
|
|
+ {
|
|
|
+ value: "left",
|
|
|
+ text: t("labels.left"),
|
|
|
+ icon: <TextAlignLeftIcon theme={appState.theme} />,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: "center",
|
|
|
+ text: t("labels.center"),
|
|
|
+ icon: <TextAlignCenterIcon theme={appState.theme} />,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: "right",
|
|
|
+ text: t("labels.right"),
|
|
|
+ icon: <TextAlignRightIcon theme={appState.theme} />,
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ value={getFormValue(
|
|
|
+ elements,
|
|
|
+ appState,
|
|
|
+ (element) => {
|
|
|
+ if (isTextElement(element)) {
|
|
|
+ return element.textAlign;
|
|
|
+ }
|
|
|
+ const boundTextElement = getBoundTextElement(element);
|
|
|
+ if (boundTextElement) {
|
|
|
+ return boundTextElement.textAlign;
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ },
|
|
|
+ appState.currentItemTextAlign,
|
|
|
+ )}
|
|
|
+ onChange={(value) => updateData(value)}
|
|
|
+ />
|
|
|
+ </fieldset>
|
|
|
+ );
|
|
|
+ },
|
|
|
+});
|
|
|
+export const actionChangeVerticalAlign = register({
|
|
|
+ name: "changeVerticalAlign",
|
|
|
+ perform: (elements, appState, value) => {
|
|
|
+ return {
|
|
|
+ elements: changeProperty(
|
|
|
+ elements,
|
|
|
+ appState,
|
|
|
+ (oldElement) => {
|
|
|
+ if (isTextElement(oldElement)) {
|
|
|
+ const newElement: ExcalidrawTextElement = newElementWith(
|
|
|
+ oldElement,
|
|
|
+ { verticalAlign: value },
|
|
|
+ );
|
|
|
+
|
|
|
+ redrawTextBoundingBox(
|
|
|
+ newElement,
|
|
|
+ getContainerElement(oldElement),
|
|
|
+ appState,
|
|
|
+ );
|
|
|
+ return newElement;
|
|
|
+ }
|
|
|
+
|
|
|
+ return oldElement;
|
|
|
+ },
|
|
|
+ true,
|
|
|
+ ),
|
|
|
+ appState: {
|
|
|
+ ...appState,
|
|
|
+ },
|
|
|
+ commitToHistory: true,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ PanelComponent: ({ elements, appState, updateData }) => {
|
|
|
+ return (
|
|
|
+ <fieldset>
|
|
|
+ <ButtonIconSelect<VerticalAlign | false>
|
|
|
+ group="text-align"
|
|
|
+ options={[
|
|
|
+ {
|
|
|
+ value: VERTICAL_ALIGN.TOP,
|
|
|
+ text: t("labels.alignTop"),
|
|
|
+ icon: <TextAlignTopIcon theme={appState.theme} />,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: VERTICAL_ALIGN.MIDDLE,
|
|
|
+ text: t("labels.centerVertically"),
|
|
|
+ icon: <TextAlignMiddleIcon theme={appState.theme} />,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ value: VERTICAL_ALIGN.BOTTOM,
|
|
|
+ text: t("labels.alignBottom"),
|
|
|
+ icon: <TextAlignBottomIcon theme={appState.theme} />,
|
|
|
+ },
|
|
|
+ ]}
|
|
|
+ value={getFormValue(elements, appState, (element) => {
|
|
|
+ if (isTextElement(element) && element.containerId) {
|
|
|
+ return element.verticalAlign;
|
|
|
}
|
|
|
const boundTextElement = getBoundTextElement(element);
|
|
|
if (boundTextElement) {
|
|
|
- return boundTextElement.textAlign;
|
|
|
+ return boundTextElement.verticalAlign;
|
|
|
}
|
|
|
return null;
|
|
|
- },
|
|
|
- appState.currentItemTextAlign,
|
|
|
- )}
|
|
|
- onChange={(value) => updateData(value)}
|
|
|
- />
|
|
|
- </fieldset>
|
|
|
- ),
|
|
|
+ })}
|
|
|
+ onChange={(value) => updateData(value)}
|
|
|
+ />
|
|
|
+ </fieldset>
|
|
|
+ );
|
|
|
+ },
|
|
|
});
|
|
|
|
|
|
export const actionChangeSharpness = register({
|