diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index dc9d26efe..241d07feb 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -88,6 +88,7 @@ import { isIOS, supportsResizeObserver, DEFAULT_COLLISION_THRESHOLD, + DEFAULT_TEXT_ALIGN, } from "../constants"; import type { ExportedElements } from "../data"; import { exportCanvas, loadFromBlob } from "../data"; @@ -331,6 +332,8 @@ import { getLineHeightInPx, isMeasureTextSupported, isValidTextContainer, + measureText, + wrapText, } from "../element/textElement"; import { showHyperlinkTooltip, @@ -430,6 +433,7 @@ import { } from "./hyperlink/helpers"; import { getShortcutFromShortcutName } from "../actions/shortcuts"; import { actionTextAutoResize } from "../actions/actionTextAutoResize"; +import { getVisibleSceneBounds } from "../element/bounds"; const AppContext = React.createContext(null!); const AppPropsContext = React.createContext(null!); @@ -2565,7 +2569,7 @@ class App extends React.Component { addEventListener(document, EVENT.KEYUP, this.onKeyUp, { passive: true }), addEventListener( document, - EVENT.MOUSE_MOVE, + EVENT.POINTER_MOVE, this.updateCurrentCursorPosition, ), // rerender text elements on font load to fix #637 && #1553 @@ -3341,32 +3345,53 @@ class App extends React.Component { text, fontSize: this.state.currentItemFontSize, fontFamily: this.state.currentItemFontFamily, - textAlign: this.state.currentItemTextAlign, + textAlign: DEFAULT_TEXT_ALIGN, verticalAlign: DEFAULT_VERTICAL_ALIGN, locked: false, }; - + const fontString = getFontString({ + fontSize: textElementProps.fontSize, + fontFamily: textElementProps.fontFamily, + }); + const lineHeight = getDefaultLineHeight(textElementProps.fontFamily); + const [x1, , x2] = getVisibleSceneBounds(this.state); + // long texts should not go beyond 800 pixels in width nor should it go below 200 px + const maxTextWidth = Math.max(Math.min((x2 - x1) * 0.5, 800), 200); const LINE_GAP = 10; let currentY = y; const lines = isPlainPaste ? [text] : text.split("\n"); const textElements = lines.reduce( (acc: ExcalidrawTextElement[], line, idx) => { - const text = line.trim(); - - const lineHeight = getDefaultLineHeight(textElementProps.fontFamily); - if (text.length) { + const originalText = line.trim(); + if (originalText.length) { const topLayerFrame = this.getTopLayerFrameAtSceneCoords({ x, y: currentY, }); + let metrics = measureText(originalText, fontString, lineHeight); + const isTextWrapped = metrics.width > maxTextWidth; + + const text = isTextWrapped + ? wrapText(originalText, fontString, maxTextWidth) + : originalText; + + metrics = isTextWrapped + ? measureText(text, fontString, lineHeight) + : metrics; + + const startX = x - metrics.width / 2; + const startY = currentY - metrics.height / 2; + const element = newTextElement({ ...textElementProps, - x, - y: currentY, + x: startX, + y: startY, text, + originalText, lineHeight, + autoResize: !isTextWrapped, frameId: topLayerFrame ? topLayerFrame.id : null, }); acc.push(element); diff --git a/packages/excalidraw/element/newElement.ts b/packages/excalidraw/element/newElement.ts index 3fa203f49..0fd0d65ce 100644 --- a/packages/excalidraw/element/newElement.ts +++ b/packages/excalidraw/element/newElement.ts @@ -215,6 +215,7 @@ const getTextElementPositionOffsets = ( export const newTextElement = ( opts: { text: string; + originalText?: string; fontSize?: number; fontFamily?: FontFamilyValues; textAlign?: TextAlign; @@ -222,6 +223,7 @@ export const newTextElement = ( containerId?: ExcalidrawTextContainer["id"] | null; lineHeight?: ExcalidrawTextElement["lineHeight"]; strokeWidth?: ExcalidrawTextElement["strokeWidth"]; + autoResize?: ExcalidrawTextElement["autoResize"]; } & ElementConstructorOpts, ): NonDeleted => { const fontFamily = opts.fontFamily || DEFAULT_FONT_FAMILY; @@ -252,8 +254,8 @@ export const newTextElement = ( width: metrics.width, height: metrics.height, containerId: opts.containerId || null, - originalText: text, - autoResize: true, + originalText: opts.originalText ?? text, + autoResize: opts.autoResize ?? true, lineHeight, };