mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feat: text wrapping (#7999)
* resize single elements from the side * fix lint * do not resize texts from the sides (for we want to wrap/unwrap) * omit side handles for frames too * upgrade types * enable resizing from the sides for multiple elements as well * fix lint * maintain aspect ratio when elements are not of the same angle * lint * always resize proportionally for multiple elements * increase side resizing padding * code cleanup * adaptive handles * do not resize for linear elements with only two points * prioritize point dragging over edge resizing * lint * allow free resizing for multiple elements at degree 0 * always resize from the sides * reduce hit threshold * make small multiple elements movable * lint * show side handles on touch screen and mobile devices * differentiate touchscreens * keep proportional with text in multi-element resizing * update snapshot * update multi elements resizing logic * lint * reduce side resizing padding * bound texts do not scale in normal cases * lint * test sides for texts * wrap text * do not update text size when changing its alignment * keep text wrapped/unwrapped when editing * change wrapped size to auto size from context menu * fix test * lint * increase min width for wrapped texts * wrap wrapped text in container * unwrap when binding text to container * rename `wrapped` to `autoResize` * fix lint * revert: use `center` align when wrapping text in container * update snaps * fix lint * simplify logic on autoResize * lint and test * snapshots * remove unnecessary code * snapshots * fix: defaults not set correctly * tests for wrapping texts when resized * tests for text wrapping when edited * fix autoResize refactor * include autoResize flag check * refactor * feat: rename action label & change contextmenu position * fix: update version on `autoResize` action * fix infinite loop when editing text in a container * simplify * always maintain `width` if `!autoResize` * maintain `x` if `!autoResize` * maintain `y` pos after fontSize change if `!autoResize` * refactor * when editing, do not wrap text in textWysiwyg * simplify text editor * make test more readable * comment * rename action to match file name * revert function signature change * only update in app --------- Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>
This commit is contained in:
parent
cc4c51996c
commit
971b4d4ae6
22 changed files with 596 additions and 143 deletions
|
@ -114,7 +114,7 @@ import {
|
|||
newTextElement,
|
||||
newImageElement,
|
||||
transformElements,
|
||||
updateTextElement,
|
||||
refreshTextDimensions,
|
||||
redrawTextBoundingBox,
|
||||
getElementAbsoluteCoords,
|
||||
} from "../element";
|
||||
|
@ -429,6 +429,7 @@ import {
|
|||
isPointHittingLinkIcon,
|
||||
} from "./hyperlink/helpers";
|
||||
import { getShortcutFromShortcutName } from "../actions/shortcuts";
|
||||
import { actionTextAutoResize } from "../actions/actionTextAutoResize";
|
||||
|
||||
const AppContext = React.createContext<AppClassProperties>(null!);
|
||||
const AppPropsContext = React.createContext<AppProps>(null!);
|
||||
|
@ -4298,25 +4299,22 @@ class App extends React.Component<AppProps, AppState> {
|
|||
) {
|
||||
const elementsMap = this.scene.getElementsMapIncludingDeleted();
|
||||
|
||||
const updateElement = (
|
||||
text: string,
|
||||
originalText: string,
|
||||
isDeleted: boolean,
|
||||
) => {
|
||||
const updateElement = (nextOriginalText: string, isDeleted: boolean) => {
|
||||
this.scene.replaceAllElements([
|
||||
// Not sure why we include deleted elements as well hence using deleted elements map
|
||||
...this.scene.getElementsIncludingDeleted().map((_element) => {
|
||||
if (_element.id === element.id && isTextElement(_element)) {
|
||||
return updateTextElement(
|
||||
_element,
|
||||
getContainerElement(_element, elementsMap),
|
||||
elementsMap,
|
||||
{
|
||||
text,
|
||||
isDeleted,
|
||||
originalText,
|
||||
},
|
||||
);
|
||||
return newElementWith(_element, {
|
||||
originalText: nextOriginalText,
|
||||
isDeleted: isDeleted ?? _element.isDeleted,
|
||||
// returns (wrapped) text and new dimensions
|
||||
...refreshTextDimensions(
|
||||
_element,
|
||||
getContainerElement(_element, elementsMap),
|
||||
elementsMap,
|
||||
nextOriginalText,
|
||||
),
|
||||
});
|
||||
}
|
||||
return _element;
|
||||
}),
|
||||
|
@ -4339,15 +4337,15 @@ class App extends React.Component<AppProps, AppState> {
|
|||
viewportY - this.state.offsetTop,
|
||||
];
|
||||
},
|
||||
onChange: withBatchedUpdates((text) => {
|
||||
updateElement(text, text, false);
|
||||
onChange: withBatchedUpdates((nextOriginalText) => {
|
||||
updateElement(nextOriginalText, false);
|
||||
if (isNonDeletedElement(element)) {
|
||||
updateBoundElements(element, elementsMap);
|
||||
}
|
||||
}),
|
||||
onSubmit: withBatchedUpdates(({ text, viaKeyboard, originalText }) => {
|
||||
const isDeleted = !text.trim();
|
||||
updateElement(text, originalText, isDeleted);
|
||||
onSubmit: withBatchedUpdates(({ viaKeyboard, nextOriginalText }) => {
|
||||
const isDeleted = !nextOriginalText.trim();
|
||||
updateElement(nextOriginalText, isDeleted);
|
||||
// select the created text element only if submitting via keyboard
|
||||
// (when submitting via click it should act as signal to deselect)
|
||||
if (!isDeleted && viaKeyboard) {
|
||||
|
@ -4392,7 +4390,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
|
||||
// do an initial update to re-initialize element position since we were
|
||||
// modifying element's x/y for sake of editor (case: syncing to remote)
|
||||
updateElement(element.text, element.originalText, false);
|
||||
updateElement(element.originalText, false);
|
||||
}
|
||||
|
||||
private deselectElements() {
|
||||
|
@ -9631,6 +9629,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
}
|
||||
|
||||
return [
|
||||
CONTEXT_MENU_SEPARATOR,
|
||||
actionCut,
|
||||
actionCopy,
|
||||
actionPaste,
|
||||
|
@ -9643,6 +9642,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||
actionPasteStyles,
|
||||
CONTEXT_MENU_SEPARATOR,
|
||||
actionGroup,
|
||||
actionTextAutoResize,
|
||||
actionUnbindText,
|
||||
actionBindText,
|
||||
actionWrapTextInContainer,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue