Next release

This release adds a center operation to Editor.alignShapes, a tleditors registry of mounted editors, iterateGraphemes to @tldraw/utils, and two new reactive methods on AtomMap. It also deprecates useViewportHeight, speeds up the signals and store layers, and fixes a batch of crashes and interaction bugs across dialogs, sync reconnection, undo, the frame loop, and keyboard shortcut tooltips.

API changes

  • 🔜 useViewportHeight() is deprecated. Read window.visualViewport directly instead. The hook returns only the visible viewport's bottom edge, and keeping a panel clear of the software keyboard generally needs the whole visible rectangle. (#9826)

  • Add 'center' as an Editor.alignShapes operation. It applies the existing 'center-horizontal' and 'center-vertical' operations together, so shapes center on both axes in one command. (#9074)

  • Add tleditors, a reactive global registry of currently mounted editors. Use it to reach live editors from outside the React tree, for example from sidebar chrome or a keyboard shortcut handler. (#9904)

    import { tleditors, useValue } from 'tldraw'
    
    const mounted = useValue('mounted editors', () => tleditors.getMounted(), [])
  • Add getOrInsert(key, defaultValue) and getOrInsertComputed(key, callback) to AtomMap, matching the Map methods added in newer JavaScript runtimes. Both are reactive, and the callback only runs when the key is absent. (#9752)

  • Add isPage(record) to @tldraw/tlschema, a type guard that narrows an unknown record to TLPage, matching the guards already exported for the other record types. (#9774)

  • Add iterateGraphemes(str) to @tldraw/utils. It iterates a string's grapheme clusters, using Intl.Segmenter when it's available and falling back to code-point iteration when it isn't. (#9896)

  • EmojiPickerProps.onSelect now receives the originating event as an optional second argument. Custom reaction palettes can forward it to opt into shift multi-select. (#9999)

Improvements

  • Shift-click an emoji in a comment's reaction palette to add several reactions without the palette closing. A plain click still applies the reaction and closes the palette. (#9999)
  • Reduce per-pointer-event allocations in Group2d and Editor hit-testing. (#8600)
  • Speed up signal reads in @tldraw/state. Capturing a parent used to scan the capturing signal's parent set twice, once to check for the parent and again to add it. (#9690)
  • Reduce the work and allocations in @tldraw/store history bookkeeping, so squashing record diffs and filtering query history no longer build intermediate copies on every tick. (#9689, #9869)

Bug fixes

  • Fix the editor failing to load on older browsers that lack Intl.Segmenter, such as Firefox before 125. (#9896)
  • Fix the frame loop stopping permanently when a tick or frame listener threw, which silently disabled camera animations, edge scrolling, and other frame-driven behavior for the rest of the session. (#9946)
  • Fix a crash when computing a frame's geometry if its heading text couldn't be measured yet. (#9496)
  • Fix undo after a cut also reverting the change made before it. (#9920)
  • Fix small, slowly drawn loops sometimes failing to close, because dense input sampling made the stroke measure shorter than it was. (#9930)
  • Fix modifier keys (Shift, Alt, Ctrl, Cmd) briefly being treated as held at the start of a new click or drag right after being released, which could momentarily affect snapping and other modifier-dependent behavior. (#9523)
  • Fix Flatten to image producing different groupings depending on selection order, and not merging clusters that were only connected through a bridging shape. (#8661)
  • Fix pasted links showing a broken preview image when the linked page has no Open Graph image. (#9909)
  • Fix video shapes showing a floating spinner with no bounding box while their asset uploads or loads. They now show the same loading plate as image shapes. (#9994)
  • Fix closing a stacked dialog by touch also closing the dialog beneath it. (#10002)
  • Fix wheel event normalization passing through non-finite delta values. (#9586)
  • Fix license validation treating native apps served from Tauri's origins, tauri://localhost and http://tauri.localhost, as development environments. A Tauri app is now a production deployment, so it needs a license whose hosts match its origin. (#10060)
  • Fix the counterclockwise rotation tooltip not showing its comma key. (#9772)
  • Fix the spacing around the cursor chat item in the context menu. (#9921)
  • Fix the people menu's collaborator rows not lining up with your own row above them: the follow icon sat too close to the right edge, and collaborator names sat slightly left of your own. (#9900)
  • Fix the comment thread popover briefly rendering with a doubled shadow the first time a thread is opened. (#9886)
  • Fix background tabs repeatedly dropping and re-establishing their sync connection when the browser throttles timers. (#9964)
Prev
Releases
Next
v5.3.0