v4.5.0
This release adds click-through on transparent image pixels, SVG sanitization for pasted and dropped content, configurable embed definitions via EmbedShapeUtil.configure(), and correct high-DPI image sizing across platforms. It also includes a new Editor.resizeToBounds() method, TypeScript enum-to-const refactoring for Node strip-types compatibility, and various other improvements and bug fixes.
What's new
Click-through on transparent image pixels (#7942)
Clicking on transparent areas of PNG, WebP, GIF, and AVIF images now selects shapes behind the image instead of the image itself. This works with cropped, flipped, and circle-cropped images.
This is powered by a new Geometry2d.ignoreHit(point) method that allows geometries to reject successful hit tests.
🔜 Configurable embed definitions (#8034)
Embed definitions are now configured through EmbedShapeUtil.configure() instead of the static setEmbedDefinitions() method, which has been deprecated. The embeds prop on Tldraw is deprecated in favor of this approach.
import { EmbedShapeUtil, DEFAULT_EMBED_DEFINITIONS } from 'tldraw'
const shapeUtils = [
EmbedShapeUtil.configure({
embedDefinitions: [...DEFAULT_EMBED_DEFINITIONS, myCustomEmbed],
}),
]Migration guide
Before:
EmbedShapeUtil.setEmbedDefinitions([...DEFAULT_EMBED_DEFINITIONS, myEmbed])After:
const shapeUtils = [
EmbedShapeUtil.configure({
embedDefinitions: [...DEFAULT_EMBED_DEFINITIONS, myEmbed],
}),
]The embeds prop on Tldraw still works but is deprecated. Use EmbedShapeUtil.configure() instead.
SVG sanitization (#7896, #8087)
Pasted and dropped SVG content is now sanitized against XSS and data exfiltration. The sanitizer uses an allowlist-based approach that blocks script injection, event handlers, dangerous URI schemes, and external resource loading while preserving tldraw's own SVG output (including <foreignObject> text rendering and CSS font references).
The sanitizer is also available as a public export for custom content handling:
import { sanitizeSvg } from 'tldraw'
const cleanSvg = sanitizeSvg(untrustedSvgText)API changes
-
🔜
EmbedShapeUtil.setEmbedDefinitions()deprecated. UseEmbedShapeUtil.configure({ embedDefinitions: [...] })instead. (#8034) -
🔜
Tldrawembedsprop is deprecated. Configure embed definitions viaEmbedShapeUtil.configure(). (#8034) -
Add
Geometry2d.ignoreHit(point)for rejecting hit tests on transparent pixels. (#7942) -
Add
Editor.resizeToBounds(shapes, bounds)for resizing shapes to fit target bounds. (#8120) -
Add
Editor.getResizeScaleFactor()for computing the dynamic size scale factor at the current zoom level. (#8042) -
Add
sanitizeSvg(svgText: string)export for sanitizing SVG content against XSS and data exfiltration. (#7896) -
Add experimental
experimental__onDropOnCanvasoption to intercept canvas drop events. Returntruefrom the callback to prevent the editor's default drop behavior. (#7911)<Tldraw options={{ experimental__onDropOnCanvas: (point, event) => { // Handle drop at page-space point return true // prevent default }, }} /> -
Add optional
pixelRatioproperty toTLImageAssetfor correct high-DPI image sizing. Detected automatically from PNG metadata. (#8163) -
Replace TypeScript enums (
MigrationFailureReason,PORTRAIT_BREAKPOINT) withconstobject + type alias pattern for compatibility with Node's built-in TypeScript support (strip-types). Values are unchanged. (#8084)
Improvements
- Improve arrow component rendering performance with finer-grained reactivity. (#8167)
- Simplify paste-parent selection to use
canReceiveNewChildrenOfTypeinstead of frame-specific checks. Prevent edge-only overlap from auto-reparenting pasted shapes into adjacent frames. (#8057) - Save link and alt-text values when clicking outside the editor instead of discarding changes. (#8037)
- Add SVG sanitization on paste and file drop to prevent XSS and data exfiltration. (#7896)
- Fix circular dependencies across
@tldraw/state,@tldraw/editor, and@tldraw/tldrawpackages to improve compatibility with Jest mocking and tree-shaking. (#7935) - Fix high-DPI image sizing to work correctly across macOS and Windows by detecting the source DPI baseline from PNG metadata. (#8163)
Bug fixes
- Fix shapes pasted with Ctrl+V not being parented to a frame when they land inside one. (#7938)
- Fix a crash when cropping custom shapes that don't include
isCirclein their crop schema. (#7931) - Fix a crash when loading session state without a
currentPageId(e.g. when using deep links). (#7994) - Fix U+2028/U+2029 line separators breaking chunked sync messages. (#7918)
- Fix "Download original" not triggering a download for cross-origin assets. (#8090)
- Fix arrow endpoints terminating at invisible clipped shape boundaries instead of at the frame edge. (#7932)
- Fix sticky notes having a hard shadow instead of a soft drop shadow when exported as SVG. (#7934)
- Fix rich text toolbar staying open when the editing shape is deleted by another user. (#8050)
- Fix SVG sanitizer stripping embedded SVG data URIs on
<image>elements. Nested SVGs are now recursively sanitized instead of blocked. (#8087) - Fix
TldrawSelectionForegroundcrashing when used withoutTldrawUiContextProvider. (#8011) - Fix dynamic-size shapes losing shadows and dashes too early when zoomed out. (#8040)
- Fix a crash when resizing draw or highlight shapes to zero width or height. (#8067)
- Fix crash when enabling Debug SVG with shapes on the canvas. (#8101)
- Fix
localOffsetmutation bug instretchShapeswhen shapes have parent transforms. (#8120) - Fix arrow SVG export producing invalid negative
<foreignObject>dimensions when arrows have no text label. (#8137) - Fix arrow endpoint flickering when anchors are at exact shape boundaries. (#8130)
- Fix shapes dragged from the toolbar not respecting dynamic size mode. (#8042)
- Fix dragging unselected shapes that have an
onClickhandler. (#7936) - Fix false positive "multiple instances" warning in Next.js dev mode. (#7933)
- Fix missing alt text on rendered image shapes in some cases. (#8158)
- Fix drawing on tablets that report zero pen pressure. (#5693)
- Fix
create-tldrawCLI to always create a subdirectory from the project name. (#8161)