feat: support decreasing/increasing fontSize
via keyboard (#4553)
Co-authored-by: david <dw@dw.local>
This commit is contained in:
parent
4501d6d630
commit
a51ed9ced6
@ -41,9 +41,16 @@ import {
|
|||||||
isTextElement,
|
isTextElement,
|
||||||
redrawTextBoundingBox,
|
redrawTextBoundingBox,
|
||||||
} from "../element";
|
} from "../element";
|
||||||
import { newElementWith } from "../element/mutateElement";
|
import { mutateElement, newElementWith } from "../element/mutateElement";
|
||||||
import { getBoundTextElement } from "../element/textElement";
|
import {
|
||||||
import { isLinearElement, isLinearElementType } from "../element/typeChecks";
|
getBoundTextElement,
|
||||||
|
getContainerElement,
|
||||||
|
} from "../element/textElement";
|
||||||
|
import {
|
||||||
|
isBoundToContainer,
|
||||||
|
isLinearElement,
|
||||||
|
isLinearElementType,
|
||||||
|
} from "../element/typeChecks";
|
||||||
import {
|
import {
|
||||||
Arrowhead,
|
Arrowhead,
|
||||||
ExcalidrawElement,
|
ExcalidrawElement,
|
||||||
@ -53,6 +60,7 @@ import {
|
|||||||
TextAlign,
|
TextAlign,
|
||||||
} from "../element/types";
|
} from "../element/types";
|
||||||
import { getLanguage, t } from "../i18n";
|
import { getLanguage, t } from "../i18n";
|
||||||
|
import { KEYS } from "../keys";
|
||||||
import { randomInteger } from "../random";
|
import { randomInteger } from "../random";
|
||||||
import {
|
import {
|
||||||
canChangeSharpness,
|
canChangeSharpness,
|
||||||
@ -63,10 +71,11 @@ import {
|
|||||||
isSomeElementSelected,
|
isSomeElementSelected,
|
||||||
} from "../scene";
|
} from "../scene";
|
||||||
import { hasStrokeColor } from "../scene/comparisons";
|
import { hasStrokeColor } from "../scene/comparisons";
|
||||||
import Scene from "../scene/Scene";
|
|
||||||
import { arrayToMap } from "../utils";
|
import { arrayToMap } from "../utils";
|
||||||
import { register } from "./register";
|
import { register } from "./register";
|
||||||
|
|
||||||
|
const FONT_SIZE_RELATIVE_INCREASE_STEP = 0.1;
|
||||||
|
|
||||||
const changeProperty = (
|
const changeProperty = (
|
||||||
elements: readonly ExcalidrawElement[],
|
elements: readonly ExcalidrawElement[],
|
||||||
appState: AppState,
|
appState: AppState,
|
||||||
@ -108,6 +117,79 @@ const getFormValue = function <T>(
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const offsetElementAfterFontResize = (
|
||||||
|
prevElement: ExcalidrawTextElement,
|
||||||
|
nextElement: ExcalidrawTextElement,
|
||||||
|
) => {
|
||||||
|
if (isBoundToContainer(nextElement)) {
|
||||||
|
return nextElement;
|
||||||
|
}
|
||||||
|
return mutateElement(
|
||||||
|
nextElement,
|
||||||
|
{
|
||||||
|
x:
|
||||||
|
prevElement.textAlign === "left"
|
||||||
|
? prevElement.x
|
||||||
|
: prevElement.x +
|
||||||
|
(prevElement.width - nextElement.width) /
|
||||||
|
(prevElement.textAlign === "center" ? 2 : 1),
|
||||||
|
// centering vertically is non-standard, but for Excalidraw I think
|
||||||
|
// it makes sense
|
||||||
|
y: prevElement.y + (prevElement.height - nextElement.height) / 2,
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeFontSize = (
|
||||||
|
elements: readonly ExcalidrawElement[],
|
||||||
|
appState: AppState,
|
||||||
|
getNewFontSize: (element: ExcalidrawTextElement) => number,
|
||||||
|
) => {
|
||||||
|
const newFontSizes = new Set<number>();
|
||||||
|
|
||||||
|
return {
|
||||||
|
elements: changeProperty(
|
||||||
|
elements,
|
||||||
|
appState,
|
||||||
|
(oldElement) => {
|
||||||
|
if (isTextElement(oldElement)) {
|
||||||
|
const newFontSize = getNewFontSize(oldElement);
|
||||||
|
newFontSizes.add(newFontSize);
|
||||||
|
|
||||||
|
let newElement: ExcalidrawTextElement = newElementWith(oldElement, {
|
||||||
|
fontSize: newFontSize,
|
||||||
|
});
|
||||||
|
redrawTextBoundingBox(
|
||||||
|
newElement,
|
||||||
|
getContainerElement(oldElement),
|
||||||
|
appState,
|
||||||
|
);
|
||||||
|
|
||||||
|
newElement = offsetElementAfterFontResize(oldElement, newElement);
|
||||||
|
|
||||||
|
return newElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return oldElement;
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
appState: {
|
||||||
|
...appState,
|
||||||
|
// update state only if we've set all select text elements to
|
||||||
|
// the same font size
|
||||||
|
currentItemFontSize:
|
||||||
|
newFontSizes.size === 1
|
||||||
|
? [...newFontSizes][0]
|
||||||
|
: appState.currentItemFontSize,
|
||||||
|
},
|
||||||
|
commitToHistory: true,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
export const actionChangeStrokeColor = register({
|
export const actionChangeStrokeColor = register({
|
||||||
name: "changeStrokeColor",
|
name: "changeStrokeColor",
|
||||||
perform: (elements, appState, value) => {
|
perform: (elements, appState, value) => {
|
||||||
@ -438,33 +520,7 @@ export const actionChangeOpacity = register({
|
|||||||
export const actionChangeFontSize = register({
|
export const actionChangeFontSize = register({
|
||||||
name: "changeFontSize",
|
name: "changeFontSize",
|
||||||
perform: (elements, appState, value) => {
|
perform: (elements, appState, value) => {
|
||||||
return {
|
return changeFontSize(elements, appState, () => value);
|
||||||
elements: changeProperty(
|
|
||||||
elements,
|
|
||||||
appState,
|
|
||||||
(el) => {
|
|
||||||
if (isTextElement(el)) {
|
|
||||||
const element: ExcalidrawTextElement = newElementWith(el, {
|
|
||||||
fontSize: value,
|
|
||||||
});
|
|
||||||
let container = null;
|
|
||||||
if (el.containerId) {
|
|
||||||
container = Scene.getScene(el)!.getElement(el.containerId);
|
|
||||||
}
|
|
||||||
redrawTextBoundingBox(element, container, appState);
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
return el;
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
appState: {
|
|
||||||
...appState,
|
|
||||||
currentItemFontSize: value,
|
|
||||||
},
|
|
||||||
commitToHistory: true,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
PanelComponent: ({ elements, appState, updateData }) => (
|
PanelComponent: ({ elements, appState, updateData }) => (
|
||||||
<fieldset>
|
<fieldset>
|
||||||
@ -514,6 +570,44 @@ export const actionChangeFontSize = register({
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const actionDecreaseFontSize = register({
|
||||||
|
name: "decreaseFontSize",
|
||||||
|
perform: (elements, appState, value) => {
|
||||||
|
return changeFontSize(elements, appState, (element) =>
|
||||||
|
Math.round(
|
||||||
|
// get previous value before relative increase (doesn't work fully
|
||||||
|
// due to rounding and float precision issues)
|
||||||
|
(1 / (1 + FONT_SIZE_RELATIVE_INCREASE_STEP)) * element.fontSize,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
keyTest: (event) => {
|
||||||
|
return (
|
||||||
|
event[KEYS.CTRL_OR_CMD] &&
|
||||||
|
event.shiftKey &&
|
||||||
|
// KEYS.COMMA needed for MacOS
|
||||||
|
(event.key === KEYS.CHEVRON_LEFT || event.key === KEYS.COMMA)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const actionIncreaseFontSize = register({
|
||||||
|
name: "increaseFontSize",
|
||||||
|
perform: (elements, appState, value) => {
|
||||||
|
return changeFontSize(elements, appState, (element) =>
|
||||||
|
Math.round(element.fontSize * (1 + FONT_SIZE_RELATIVE_INCREASE_STEP)),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
keyTest: (event) => {
|
||||||
|
return (
|
||||||
|
event[KEYS.CTRL_OR_CMD] &&
|
||||||
|
event.shiftKey &&
|
||||||
|
// KEYS.PERIOD needed for MacOS
|
||||||
|
(event.key === KEYS.CHEVRON_RIGHT || event.key === KEYS.PERIOD)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const actionChangeFontFamily = register({
|
export const actionChangeFontFamily = register({
|
||||||
name: "changeFontFamily",
|
name: "changeFontFamily",
|
||||||
perform: (elements, appState, value) => {
|
perform: (elements, appState, value) => {
|
||||||
@ -521,20 +615,23 @@ export const actionChangeFontFamily = register({
|
|||||||
elements: changeProperty(
|
elements: changeProperty(
|
||||||
elements,
|
elements,
|
||||||
appState,
|
appState,
|
||||||
(el) => {
|
(oldElement) => {
|
||||||
if (isTextElement(el)) {
|
if (isTextElement(oldElement)) {
|
||||||
const element: ExcalidrawTextElement = newElementWith(el, {
|
const newElement: ExcalidrawTextElement = newElementWith(
|
||||||
|
oldElement,
|
||||||
|
{
|
||||||
fontFamily: value,
|
fontFamily: value,
|
||||||
});
|
},
|
||||||
let container = null;
|
);
|
||||||
if (el.containerId) {
|
redrawTextBoundingBox(
|
||||||
container = Scene.getScene(el)!.getElement(el.containerId);
|
newElement,
|
||||||
}
|
getContainerElement(oldElement),
|
||||||
redrawTextBoundingBox(element, container, appState);
|
appState,
|
||||||
return element;
|
);
|
||||||
|
return newElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
return el;
|
return oldElement;
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
@ -603,20 +700,23 @@ export const actionChangeTextAlign = register({
|
|||||||
elements: changeProperty(
|
elements: changeProperty(
|
||||||
elements,
|
elements,
|
||||||
appState,
|
appState,
|
||||||
(el) => {
|
(oldElement) => {
|
||||||
if (isTextElement(el)) {
|
if (isTextElement(oldElement)) {
|
||||||
const element: ExcalidrawTextElement = newElementWith(el, {
|
const newElement: ExcalidrawTextElement = newElementWith(
|
||||||
|
oldElement,
|
||||||
|
{
|
||||||
textAlign: value,
|
textAlign: value,
|
||||||
});
|
},
|
||||||
let container = null;
|
);
|
||||||
if (el.containerId) {
|
redrawTextBoundingBox(
|
||||||
container = Scene.getScene(el)!.getElement(el.containerId);
|
newElement,
|
||||||
}
|
getContainerElement(oldElement),
|
||||||
redrawTextBoundingBox(element, container, appState);
|
appState,
|
||||||
return element;
|
);
|
||||||
|
return newElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
return el;
|
return oldElement;
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
|
@ -12,9 +12,7 @@ import {
|
|||||||
DEFAULT_FONT_FAMILY,
|
DEFAULT_FONT_FAMILY,
|
||||||
DEFAULT_TEXT_ALIGN,
|
DEFAULT_TEXT_ALIGN,
|
||||||
} from "../constants";
|
} from "../constants";
|
||||||
import Scene from "../scene/Scene";
|
import { getContainerElement } from "../element/textElement";
|
||||||
import { isBoundToContainer } from "../element/typeChecks";
|
|
||||||
import { ExcalidrawTextElement } from "../element/types";
|
|
||||||
|
|
||||||
// `copiedStyles` is exported only for tests.
|
// `copiedStyles` is exported only for tests.
|
||||||
export let copiedStyles: string = "{}";
|
export let copiedStyles: string = "{}";
|
||||||
@ -58,22 +56,16 @@ export const actionPasteStyles = register({
|
|||||||
opacity: pastedElement?.opacity,
|
opacity: pastedElement?.opacity,
|
||||||
roughness: pastedElement?.roughness,
|
roughness: pastedElement?.roughness,
|
||||||
});
|
});
|
||||||
if (isTextElement(newElement)) {
|
if (isTextElement(newElement) && isTextElement(element)) {
|
||||||
mutateElement(newElement, {
|
mutateElement(newElement, {
|
||||||
fontSize: pastedElement?.fontSize || DEFAULT_FONT_SIZE,
|
fontSize: pastedElement?.fontSize || DEFAULT_FONT_SIZE,
|
||||||
fontFamily: pastedElement?.fontFamily || DEFAULT_FONT_FAMILY,
|
fontFamily: pastedElement?.fontFamily || DEFAULT_FONT_FAMILY,
|
||||||
textAlign: pastedElement?.textAlign || DEFAULT_TEXT_ALIGN,
|
textAlign: pastedElement?.textAlign || DEFAULT_TEXT_ALIGN,
|
||||||
});
|
});
|
||||||
let container = null;
|
|
||||||
|
|
||||||
if (isBoundToContainer(element)) {
|
|
||||||
container = Scene.getScene(element)!.getElement(
|
|
||||||
element.containerId,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
redrawTextBoundingBox(
|
redrawTextBoundingBox(
|
||||||
element as ExcalidrawTextElement,
|
element,
|
||||||
container,
|
getContainerElement(element),
|
||||||
appState,
|
appState,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,9 @@ export type ActionName =
|
|||||||
| "flipVertical"
|
| "flipVertical"
|
||||||
| "viewMode"
|
| "viewMode"
|
||||||
| "exportWithDarkMode"
|
| "exportWithDarkMode"
|
||||||
| "toggleTheme";
|
| "toggleTheme"
|
||||||
|
| "increaseFontSize"
|
||||||
|
| "decreaseFontSize";
|
||||||
|
|
||||||
export type PanelComponentProps = {
|
export type PanelComponentProps = {
|
||||||
elements: readonly ExcalidrawElement[];
|
elements: readonly ExcalidrawElement[];
|
||||||
|
@ -1649,7 +1649,10 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(isWritableElement(event.target) && event.key !== KEYS.ESCAPE) ||
|
(isWritableElement(event.target) &&
|
||||||
|
event.key !== KEYS.ESCAPE &&
|
||||||
|
// handle cmd/ctrl-modifier shortcuts even inside inputs
|
||||||
|
!event[KEYS.CTRL_OR_CMD]) ||
|
||||||
// case: using arrows to move between buttons
|
// case: using arrows to move between buttons
|
||||||
(isArrowKey(event.key) && isInputLike(event.target))
|
(isArrowKey(event.key) && isInputLike(event.target))
|
||||||
) {
|
) {
|
||||||
|
@ -394,6 +394,14 @@ export const HelpDialog = ({ onClose }: { onClose?: () => void }) => {
|
|||||||
label={t("labels.showBackground")}
|
label={t("labels.showBackground")}
|
||||||
shortcuts={[getShortcutKey("G")]}
|
shortcuts={[getShortcutKey("G")]}
|
||||||
/>
|
/>
|
||||||
|
<Shortcut
|
||||||
|
label={t("labels.decreaseFontSize")}
|
||||||
|
shortcuts={[getShortcutKey("CtrlOrCmd+Shift+<")]}
|
||||||
|
/>
|
||||||
|
<Shortcut
|
||||||
|
label={t("labels.increaseFontSize")}
|
||||||
|
shortcuts={[getShortcutKey("CtrlOrCmd+Shift+>")]}
|
||||||
|
/>
|
||||||
</ShortcutIsland>
|
</ShortcutIsland>
|
||||||
</Column>
|
</Column>
|
||||||
</Columns>
|
</Columns>
|
||||||
|
@ -21,9 +21,8 @@ import { AppState } from "../types";
|
|||||||
import { getElementAbsoluteCoords } from ".";
|
import { getElementAbsoluteCoords } from ".";
|
||||||
import { adjustXYWithRotation } from "../math";
|
import { adjustXYWithRotation } from "../math";
|
||||||
import { getResizedElementAbsoluteCoords } from "./bounds";
|
import { getResizedElementAbsoluteCoords } from "./bounds";
|
||||||
import { measureText } from "./textElement";
|
import { getContainerElement, measureText } from "./textElement";
|
||||||
import { isBoundToContainer } from "./typeChecks";
|
import { isBoundToContainer } from "./typeChecks";
|
||||||
import Scene from "../scene/Scene";
|
|
||||||
import { BOUND_TEXT_PADDING } from "../constants";
|
import { BOUND_TEXT_PADDING } from "../constants";
|
||||||
|
|
||||||
type ElementConstructorOpts = MarkOptional<
|
type ElementConstructorOpts = MarkOptional<
|
||||||
@ -159,8 +158,8 @@ const getAdjustedDimensions = (
|
|||||||
baseline: number;
|
baseline: number;
|
||||||
} => {
|
} => {
|
||||||
let maxWidth = null;
|
let maxWidth = null;
|
||||||
if (element.containerId) {
|
const container = getContainerElement(element);
|
||||||
const container = Scene.getScene(element)!.getElement(element.containerId)!;
|
if (container) {
|
||||||
maxWidth = container.width - BOUND_TEXT_PADDING * 2;
|
maxWidth = container.width - BOUND_TEXT_PADDING * 2;
|
||||||
}
|
}
|
||||||
const {
|
const {
|
||||||
@ -220,7 +219,7 @@ const getAdjustedDimensions = (
|
|||||||
// make sure container dimensions are set properly when
|
// make sure container dimensions are set properly when
|
||||||
// text editor overflows beyond viewport dimensions
|
// text editor overflows beyond viewport dimensions
|
||||||
if (isBoundToContainer(element)) {
|
if (isBoundToContainer(element)) {
|
||||||
const container = Scene.getScene(element)!.getElement(element.containerId)!;
|
const container = getContainerElement(element)!;
|
||||||
let height = container.height;
|
let height = container.height;
|
||||||
let width = container.width;
|
let width = container.width;
|
||||||
if (nextHeight > height - BOUND_TEXT_PADDING * 2) {
|
if (nextHeight > height - BOUND_TEXT_PADDING * 2) {
|
||||||
|
@ -416,9 +416,25 @@ export const getBoundTextElement = (element: ExcalidrawElement | null) => {
|
|||||||
}
|
}
|
||||||
const boundTextElementId = getBoundTextElementId(element);
|
const boundTextElementId = getBoundTextElementId(element);
|
||||||
if (boundTextElementId) {
|
if (boundTextElementId) {
|
||||||
return Scene.getScene(element)!.getElement(
|
return (
|
||||||
|
(Scene.getScene(element)?.getElement(
|
||||||
boundTextElementId,
|
boundTextElementId,
|
||||||
) as ExcalidrawTextElementWithContainer;
|
) as ExcalidrawTextElementWithContainer) || null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getContainerElement = (
|
||||||
|
element:
|
||||||
|
| (ExcalidrawElement & { containerId: ExcalidrawElement["id"] | null })
|
||||||
|
| null,
|
||||||
|
) => {
|
||||||
|
if (!element) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (element.containerId) {
|
||||||
|
return Scene.getScene(element)?.getElement(element.containerId) || null;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
@ -8,16 +8,13 @@ import {
|
|||||||
import Scene from "../scene/Scene";
|
import Scene from "../scene/Scene";
|
||||||
import { isBoundToContainer, isTextElement } from "./typeChecks";
|
import { isBoundToContainer, isTextElement } from "./typeChecks";
|
||||||
import { CLASSES, BOUND_TEXT_PADDING } from "../constants";
|
import { CLASSES, BOUND_TEXT_PADDING } from "../constants";
|
||||||
import {
|
import { ExcalidrawElement, ExcalidrawTextElement } from "./types";
|
||||||
ExcalidrawBindableElement,
|
|
||||||
ExcalidrawElement,
|
|
||||||
ExcalidrawTextElement,
|
|
||||||
} from "./types";
|
|
||||||
import { AppState } from "../types";
|
import { AppState } from "../types";
|
||||||
import { mutateElement } from "./mutateElement";
|
import { mutateElement } from "./mutateElement";
|
||||||
import {
|
import {
|
||||||
getApproxLineHeight,
|
getApproxLineHeight,
|
||||||
getBoundTextElementId,
|
getBoundTextElementId,
|
||||||
|
getContainerElement,
|
||||||
wrapText,
|
wrapText,
|
||||||
} from "./textElement";
|
} from "./textElement";
|
||||||
|
|
||||||
@ -102,9 +99,7 @@ export const textWysiwyg = ({
|
|||||||
if (updatedElement && isTextElement(updatedElement)) {
|
if (updatedElement && isTextElement(updatedElement)) {
|
||||||
let coordX = updatedElement.x;
|
let coordX = updatedElement.x;
|
||||||
let coordY = updatedElement.y;
|
let coordY = updatedElement.y;
|
||||||
const container = updatedElement?.containerId
|
const container = getContainerElement(updatedElement);
|
||||||
? Scene.getScene(updatedElement)!.getElement(updatedElement.containerId)
|
|
||||||
: null;
|
|
||||||
let maxWidth = updatedElement.width;
|
let maxWidth = updatedElement.width;
|
||||||
|
|
||||||
let maxHeight = updatedElement.height;
|
let maxHeight = updatedElement.height;
|
||||||
@ -274,9 +269,7 @@ export const textWysiwyg = ({
|
|||||||
let height = "auto";
|
let height = "auto";
|
||||||
|
|
||||||
if (lines === 2) {
|
if (lines === 2) {
|
||||||
const container = Scene.getScene(element)!.getElement(
|
const container = getContainerElement(element);
|
||||||
element.containerId,
|
|
||||||
);
|
|
||||||
const actualLineCount = wrapText(
|
const actualLineCount = wrapText(
|
||||||
editable.value,
|
editable.value,
|
||||||
getFontString(element),
|
getFontString(element),
|
||||||
@ -300,13 +293,16 @@ export const textWysiwyg = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
editable.onkeydown = (event) => {
|
editable.onkeydown = (event) => {
|
||||||
|
if (!event[KEYS.CTRL_OR_CMD]) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
}
|
||||||
if (event.key === KEYS.ESCAPE) {
|
if (event.key === KEYS.ESCAPE) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
submittedViaKeyboard = true;
|
submittedViaKeyboard = true;
|
||||||
handleSubmit();
|
handleSubmit();
|
||||||
} else if (event.key === KEYS.ENTER && event[KEYS.CTRL_OR_CMD]) {
|
} else if (event.key === KEYS.ENTER && event[KEYS.CTRL_OR_CMD]) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
if (event.isComposing || event.keyCode === 229) {
|
if (event.isComposing || event.keyCode === 229) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -319,6 +315,7 @@ export const textWysiwyg = ({
|
|||||||
event.code === CODES.BRACKET_RIGHT))
|
event.code === CODES.BRACKET_RIGHT))
|
||||||
) {
|
) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
if (event.shiftKey || event.code === CODES.BRACKET_LEFT) {
|
if (event.shiftKey || event.code === CODES.BRACKET_LEFT) {
|
||||||
outdent();
|
outdent();
|
||||||
} else {
|
} else {
|
||||||
@ -443,9 +440,7 @@ export const textWysiwyg = ({
|
|||||||
}
|
}
|
||||||
let wrappedText = "";
|
let wrappedText = "";
|
||||||
if (isTextElement(updateElement) && updateElement?.containerId) {
|
if (isTextElement(updateElement) && updateElement?.containerId) {
|
||||||
const container = Scene.getScene(updateElement)!.getElement(
|
const container = getContainerElement(updateElement);
|
||||||
updateElement.containerId,
|
|
||||||
) as ExcalidrawBindableElement;
|
|
||||||
|
|
||||||
if (container) {
|
if (container) {
|
||||||
wrappedText = wrapText(
|
wrappedText = wrapText(
|
||||||
|
@ -40,6 +40,10 @@ export const KEYS = {
|
|||||||
QUESTION_MARK: "?",
|
QUESTION_MARK: "?",
|
||||||
SPACE: " ",
|
SPACE: " ",
|
||||||
TAB: "Tab",
|
TAB: "Tab",
|
||||||
|
CHEVRON_LEFT: "<",
|
||||||
|
CHEVRON_RIGHT: ">",
|
||||||
|
PERIOD: ".",
|
||||||
|
COMMA: ",",
|
||||||
|
|
||||||
A: "a",
|
A: "a",
|
||||||
D: "d",
|
D: "d",
|
||||||
|
@ -102,7 +102,9 @@
|
|||||||
"showBackground": "Show background color picker",
|
"showBackground": "Show background color picker",
|
||||||
"toggleTheme": "Toggle theme",
|
"toggleTheme": "Toggle theme",
|
||||||
"personalLib": "Personal Library",
|
"personalLib": "Personal Library",
|
||||||
"excalidrawLib": "Excalidraw Library"
|
"excalidrawLib": "Excalidraw Library",
|
||||||
|
"decreaseFontSize": "Decrease font size",
|
||||||
|
"increaseFontSize": "Increase font size"
|
||||||
},
|
},
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"clearReset": "Reset the canvas",
|
"clearReset": "Reset the canvas",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user