apps/docs/content/releases/v4.5.0.mdx
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.
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.
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],
}),
]
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.
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)
🔜 EmbedShapeUtil.setEmbedDefinitions() deprecated. Use EmbedShapeUtil.configure({ embedDefinitions: [...] }) instead. (#8034)
🔜 Tldraw embeds prop is deprecated. Configure embed definitions via EmbedShapeUtil.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__onDropOnCanvas option to intercept canvas drop events. Return true from 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 pixelRatio property to TLImageAsset for correct high-DPI image sizing. Detected automatically from PNG metadata. (#8163)
Replace TypeScript enums (MigrationFailureReason, PORTRAIT_BREAKPOINT) with const object + type alias pattern for compatibility with Node's built-in TypeScript support (strip-types). Values are unchanged. (#8084)
canReceiveNewChildrenOfType instead of frame-specific checks. Prevent edge-only overlap from auto-reparenting pasted shapes into adjacent frames. (#8057)@tldraw/state, @tldraw/editor, and @tldraw/tldraw packages to improve compatibility with Jest mocking and tree-shaking. (#7935)isCircle in their crop schema. (#7931)currentPageId (e.g. when using deep links). (#7994)<image> elements. Nested SVGs are now recursively sanitized instead of blocked. (#8087)TldrawSelectionForeground crashing when used without TldrawUiContextProvider. (#8011)localOffset mutation bug in stretchShapes when shapes have parent transforms. (#8120)<foreignObject> dimensions when arrows have no text label. (#8137)onClick handler. (#7936)create-tldraw CLI to always create a subdirectory from the project name. (#8161)