mirror of
https://github.com/excalidraw/excalidraw.git
synced 2026-10-20 00:16:54 +00:00
* feat(editor): wrap typed & pasted text at 800, clear of the side panels A free text growing as it's typed stopped only at the view's width (#12175), so on a large screen it ran to 2000+ px before wrapping, and a pasted text wrapped at half the view. Both now follow one rule, in `getMaxTextWidth`: - no wider than TEXT_MAX_WRAP_WIDTH (800, in @excalidraw/common) in scene units, at any zoom: the paste's former cap, now shared. A paste no longer wraps at half the view. - nor wider than the canvas between the side panels, less TEXT_VIEWPORT_PADDING at each side: the docked sidebar, as before; the full styles panel (desktop), which shows next to a text while it's edited, and once it's pasted and selected (pasting with nothing selected, its room is reserved: as last measured, else approximately); and the stats panel, only for a text beside it, i.e. with rows within that padding of it, as it covers only the top of the canvas' side. A text that starts wrapping is brought in between the same panels, as before. A paste is laid out as if the stats panel weren't there, and again, clear of it, only if it lands beside it. As the stats panel grows to show a selection's properties, with it open the paste is rendered selected first (not captured yet, via `flushSync`), so the panels are measured as they'll be; laid out again, it stays the same elements, and one undo step. A wrapped paste is then moved into view (as far as the view would have scrolled), instead of scrolling the view. The stats panel is marked as side viewport UI (`data-viewport-ui="side"`, named "stats"), so the viewport offsets' other users (zoom to fit, scroll to content, search, a host's `setViewport` with UI offsets) keep clear of it too while it's open. `AppViewport` gains `getSideInsets(names, { reserve })`, generalizing `getSidebarInsets`, and `getSideUIRect(name)`; `getOffsets` shares the reserve fallback through `getReservedSide`. Tests: the cap at 50% and 200%; a typed text clear of the styles and the stats panel, and of the stats panel only beside it; a paste wrapping as a typed one, with the styles panel's room reserved; a paste clear of the stats panel only where it lands beside it, and of the stats panel grown to show it, as one undo step; a wrapped paste moved into view, the view not scrolled. Claude Opus 5.5 (1M), xhigh effort * feat(editor): pan the canvas when the caret goes under the stats or styles panel The canvas follows the caret past the view's edge, and behind the docked sidebar, through the editor's box, which the browser scrolls to reveal a caret (#12175). The stats and the full styles panel don't span the box's height, so a caret typed in under them stayed out of sight. After each input, once the update (and any scroll it made) is in the app's state, the editor works out where the caret is: its line from `getWrappedTextLines`, its x from the width of the line before it, rotated with the text. In a line with RTL characters (`hasRTLChars`, new in @excalidraw/common) the x comes from the browser's bidirectional layout of the line instead, in its paragraph's direction (the editor's `dir="auto"` makes it `unicode-bidi: plaintext`: each paragraph goes its first strong character's way): with Hebrew then English, the caret after the English is mid-line, not at the line's edge. That's measured through a range in an off-screen mirror of the line, shared with the click-to-caret lookup. If the caret's under one of those panels, the canvas pans to bring it out on the canvas' side, with CARET_FOLLOW_PADDING to spare. Only then: a text beside or below a panel stays where it is. Tests: typing past the stats panel's left edge pans the canvas under it, but not below it; the caret in a bidirectional line, a paragraph after one going the other way, is found where the browser lays it out. Claude Opus 5.5 (1M), xhigh effort
@excalidraw/common
Install
npm install @excalidraw/common
If you prefer Yarn over npm, use this command to install the Excalidraw utils package:
yarn add @excalidraw/common
With PNPM, similarly install the package with this command:
pnpm add @excalidraw/common