v16.3.0-canary.12
- Refactor: Decouple request store creation from
req/res: #93499 - Detect
'use cache'module-scope deadlocks early in dev: #93500 - Bundle the
'use cache'deadlock probe worker: #93538 - Support configuring a default instant validation level : #93301
- Upgrade React from
f4e0d4ed-20260429todd453071-20260506: #93547
- [turbopack] shrink the size of futures: #93474
- [turbopack] Simplify local task tracking: #93478
- [turbopack] correct a fencepost error in our inline string descision: #93524
- Turbopack: make rcstr! macro expansion const: #93516
- Turbopack: lazy aggregation optimize via persistent pending flag: #93454
- docs: remove unreachable forms and mutations: #93509
- docs: broken link from usePathname compat call out: #93528
- Turbopack: really fix MAX_INLINE_LEN: #93531
- [ci] Clarify new preview build flow: #93540
- Turbopack: simplify asset ident constructors: #93213
Huge thanks to @lukesandberg, @unstubbable, @mischnic, @sokra, @icyJoseph, @eps1lon, @gnoff, and @vercel-release-bot for helping!
v15.5.16
This release contains security fixes for the following advisories:
High:
- GHSA-8h8q-6873-q5fj: Denial of Service with Server Components
- GHSA-267c-6grr-h53f: Middleware / Proxy bypass in App Router applications via segment-prefetch routes
- GHSA-mg66-mrh9-m8jx: Denial of Service via connection exhaustion in applications using Cache Components
- GHSA-492v-c6pp-mqqv: Middleware / Proxy bypass through dynamic route parameter injection
- GHSA-c4j6-fc7j-m34r: Server-side request forgery in applications using WebSocket upgrades
- GHSA-36qx-fr4f-26g5: Middleware / Proxy bypass in Pages Router applications using i18n
Moderate:
- GHSA-ffhc-5mcf-pf4q: Cross-site scripting in App Router applications using CSP nonces
- GHSA-gx5p-jg67-6x7h: Cross-site scripting in beforeInteractive scripts with untrusted input
- GHSA-h64f-5h5j-jqjh: Denial of Service in the Image Optimization API
- GHSA-wfc6-r584-vfw7: Cache poisoning in React Server Component responses
Low:
v16.2.5
This release contains security fixes for the following advisories:
High:
- GHSA-8h8q-6873-q5fj: Denial of Service with Server Components
- GHSA-267c-6grr-h53f: Middleware / Proxy bypass in App Router applications via segment-prefetch routes
- GHSA-mg66-mrh9-m8jx: Denial of Service via connection exhaustion in applications using Cache Components
- GHSA-492v-c6pp-mqqv: Middleware / Proxy bypass through dynamic route parameter injection
- GHSA-c4j6-fc7j-m34r: Server-side request forgery in applications using WebSocket upgrades
- GHSA-36qx-fr4f-26g5: Middleware / Proxy bypass in Pages Router applications using i18n
Moderate:
- GHSA-ffhc-5mcf-pf4q: Cross-site scripting in App Router applications using CSP nonces
- GHSA-gx5p-jg67-6x7h: Cross-site scripting in beforeInteractive scripts with untrusted input
- GHSA-h64f-5h5j-jqjh: Denial of Service in the Image Optimization API
- GHSA-wfc6-r584-vfw7: Cache poisoning in React Server Component responses
Low:
electron v43.0.0-alpha.1
Note: This is an alpha release. Please file new issues for any bugs you find in it.
This release is published to npm under the alpha tag and can be installed via npm install electron@alpha, or npm install electron@43.0.0-alpha.1.
- Added Clone method to WebContents. #49959
- Added JS stack trace to crash reports on renderer OOM. #50043 (Also in 42)
- Added Linux support for
app.getApplicationInfoForProtocol(). #51297 - Added
Notification.getHistory()for macOS, allowing developers to restore all delivered notifications still present in Notification Center. #50325 (Also in 42) - Added
accessibilityLabelproperty toMenuItemconstructor options and properties for defining screen-reader-friendly labels. #50240 - Added
allowExtensionsprivilege toprotocol.registerSchemesAsPrivileged()to enable Chrome extensions on custom protocols. #49951 (Also in 40, 41, 42) - Added
app.configureWebAuthn()to enable the Touch ID platform authenticator for WebAuthn on macOS, and aselect-webauthn-accountsession event for choosing between multiple discoverable credentials. #51255 (Also in 41, 42) - Added
globalShortcut.setSuspended()andglobalShortcut.isSuspended()methods to temporarily suspend and resume global shortcut handling. #50425 (Also in 42) - Added
idandgroupIdoptions to the Notification constructor on macOS.idallows custom identifiers for notifications, andgroupIdvisually groups notifications together in Notification Center. #50097 (Also in 42) - Added
nv12OSR pixel format support for professional use. #49799 - Added
view.setBackgroundBlur. #51076 - Added
webContents.copyVideoFrameAt(x, y)andwebContents.saveVideoFrameAs(x, y)methods. #48149 - Added id, groupId, and groupTitle support for Windows notifications. #50328 (Also in 42)
- Added nativeTheme.shouldDifferentiateWithoutColor on macOS. #49912 (Also in 41, 42)
- Added session support to net module requests from utility process. #51279
- Added support for heap profiling via
contentTracing.enableHeapProfiling(). #50826 (Also in 41, 42) - Added support for importing shared textures using the nv16 pixel format. #50728 (Also in 42)
- Allowed the
--experimental-inspector-network-resourceNode.js flag to be passed through Electron. #49689 - Feat: SF Symbol customisation. #48911
- File downloads will open by default in the user's Downloads folder (or Home directory if Downloads doesn't exist). #49868
- Fixed contentTracing module to capture Node.js trace categories. #50591
- Notes: Added support for the
urgencyoption in Notifications on Windows. #50225 (Also in 41, 42)
- Added additional ASAR support to additional
fscopy methods. #50226 (Also in 39, 40, 41, 42) - Added crash keys to diagnose power monitor shutdown crash on arm64 windows. #51198 (Also in 42)
- Added missing
metadatafields tocontentTracingtraces. #50892 (Also in 41, 42) - BrowserWindow now enforces min/max size constraints on window creation, even if they conflict with the requested width and height. #49906 (Also in 41, 42)
- Changed the
kResizeThresholdto trigger the resize on corners. #50637 (Also in 41, 42) - Ensured cross-origin
fetch()and XHR are blocked for custom protocols registered withsupportFetchAPI: trueunlesscorsEnabled: trueis also set; cross-originmode: 'no-cors'requests now receive an opaque response. #51152 (Also in 39, 40, 41, 42) - Fixed DesktopCapturer crash on macOS. #50960 (Also in 42)
- Fixed Electron child process titles on Linux so they show their types (render, gpu, etc.) and complete command-line arguments and flags in
ps aux. #50509 (Also in 42) - Fixed
ELECTRON_INSTALL_PLATFORMbeing ignored when resolving the Electron executable path during postinstall, which causedpath.txtto be written for the host platform instead of the requested target and madeisInstalled()always re-download on subsequent installs. #51029 (Also in 42) - Fixed
app.getLoginItemSettings()returningundefinedforexecutableWillLaunchAtLoginon macOS; the property is now always a boolean. #51416 (Also in 40, 41, 42) - Fixed
desktopCapturer.getSources()hanging on macOS. #51128 - Fixed
fs.staton files inside asar archives returningundefinedforblksizeandblocksinstead of numeric values. #50825 (Also in 40, 41, 42) - Fixed
webContents.printToPDFrejecting on all subsequent calls after a prior call was rejected with an invalidpageRangesvalue. #51174 (Also in 40, 41, 42) - Fixed a crash when providing invalid HTTP header names or values in the
webRequest.onBeforeSendHeaders()callback. #51340 (Also in 40, 41, 42) - Fixed a bug where Windows notification icons could fail to save because their temporary filenames contained invalid characters. #50454 (Also in 40, 41, 42)
- Fixed a bug where errors would occur when using the Chrome DevTools Fetch API. #50744 (Also in 41, 42)
- Fixed a crash in
clipboard.readImage()when the clipboard contains malformed image data. #50475 (Also in 39, 40, 41, 42) - Fixed a crash that could occur when an autofill suggestion popup was shown while a window was closing. #51302 (Also in 41, 42)
- Fixed a crash when calling
contentTracing.getTraceBufferUsage()while a trace session is active. #50556 (Also in 39, 40, 41, 42) - Fixed a crash when calling an offscreen shared texture's
release()after the texture object was garbage collected. #50473 (Also in 39, 40, 41, 42) - Fixed a crash when rendering PDFs when Site Isolation is disabled. #50689 (Also in 41, 42)
- Fixed a memory leak where Menu items were not cleaned up after Menu.setApplicationMenu was called repeatedly. #50806 (Also in 40, 41, 42)
- Fixed a potential crash when using
webContents.print(). #50843 (Also in 42) - Fixed a potential race condition crash when closing DevTools. #51420 (Also in 41, 42)
- Fixed a regression on Linux where transparent frameless windows would have visible borders. Also fixed a longstanding issue where transparent windows on Linux could show smeared and glitched content as windows moved around. #50541 (Also in 41, 42)
- Fixed a regression on Windows where frameless windows changed their size after calling
setResizable. #51252 (Also in 41, 42) - Fixed a regression where frameless fullscreen windows had white borders on Windows. #51287 (Also in 41, 42)
- Fixed a renderer crash when a page uses the
<geolocation>HTML element. #51346 (Also in 41, 42) - Fixed absent 'Electron Isolated Context' in the execution context dropdown in Dev Tools. #51062 (Also in 41, 42)
- Fixed an accessibility issue where the AXMenuOpened event was not fired on menu creation. #50377 (Also in 40, 41, 42)
- Fixed an intermittent
Invoke in DisallowJavascriptExecutionScopecrash on application quit when aWebContents(or other JS-emitting native object) is garbage-collected during shutdown. #50688 (Also in 40, 41, 42) - Fixed an issue on Windows where a transient
UnhookWindowsHookExfailure insetIgnoreMouseEvents(true, { forward: true })teardown could cause duplicate low-level mouse hooks to be installed on the next activation. #51098 (Also in 41, 42) - Fixed an issue on macOS where
show/hideevents andWebContentsvisibility state could be reported incorrectly when multipleWebContentsViews were attached to a window. #50579 (Also in 40, 41, 42) - Fixed an issue where DevTools would re-attach to the window when opened after previously being detached. #50807 (Also in 39, 40, 41, 42)
- Fixed an issue where
app-region: draginside a hiddenWebContentsViewwould still drag the parent window on Windows. #51200 (Also in 40, 41, 42) - Fixed an issue where
nodeIntegrationInWorkerdidn't always work in AudioWorklet. #47244 (Also in 40, 41, 42) - Fixed an issue where
setSimpleFullScreenon macOS would exit when web content calledrequestFullscreen(). #50874 (Also in 40, 41, 42) - Fixed an issue where an Electron auto-update job would occasionally fail if a macOS system update is pending. #51070 (Also in 42)
- Fixed an issue where an Electron macOS update would not be applied if another app was previously blocking the macOS system update loop. #51191 (Also in 40, 41, 42)
- Fixed an issue where an app shortcut may lose its icon after auto-updating on Windows. #50471 (Also in 40, 41, 42)
- Fixed an issue where calling
contentTracingAPIs beforeapp.whenReady()would crash the application. #50920 (Also in 41, 42) - Fixed an issue where closing devtools immediately after focus caused a crash. #47435 (Also in 41, 42)
- Fixed an issue where concurrent
getFileHandlerequests on the same path could stall indefinitely. #50597 (Also in 40, 41, 42) - Fixed an issue where custom options in
webContents.print()did not prefill the print dialog on macOS. #50600 (Also in 42) - Fixed an issue where importing
electronvia ESM would touch the OS keychain on app-ready even whensafeStoragewas never used.safeStorage.isAsyncEncryptionAvailable()now returns a Promise as documented. #50419 - Fixed an issue where margins did not look as expected when printing in silent mode. #50615 (Also in 41, 42)
- Fixed an issue where saving edited PDF files would fail with a cross-origin SecurityError. #51042 (Also in 41, 42)
- Fixed an issue where some DevTools functionality didn't work as expected. #50241 (Also in 40, 41, 42)
- Fixed an issue where some toast notification properties didn't work as expected in WinRT. #51286 (Also in 41, 42)
- Fixed an issue where the Squirrel.Mac installer could resolve the target bundle path to different locations at different stages of an install. #50745 (Also in 39, 42)
- Fixed an issue where the
webContents.print()callback may not fire correctly in some cases. #50431 (Also in 41, 42) - Fixed an issue where webContents.print() would ignore pageSize / mediaSize when silent was true. #50808 (Also in 41, 42)
- Fixed an issue with the main process where
process.exit()with no argument did not exit withprocess.exitCode- Fixed handling of string value arguments to
process.exit()in the main process. #51428
- Fixed handling of string value arguments to
- Fixed aspect ratio min/max size clamping to correctly account for extraSize on macOS. #50794 (Also in 40, 41, 42)
- Fixed bug that could occasionally cause browserWindow's
always-on-top-changedeven to fire with incorrect values. #51110 (Also in 40, 41, 42) - Fixed buggy behavior where Backspace would accept macOS text replacements inside
contenteditableelements. #51289 (Also in 40, 41, 42) - Fixed build failure when building with
enable_pdfdisabled. #51223 (Also in 41, 42) - Fixed certain DevTools extension panels not showing without a page reload. #50611 (Also in 42)
- Fixed crash when
app.setPath('sessionData')was called with a non-existent directory. #50891 (Also in 41, 42) - Fixed crash when handling JavaScript dialogs from windows opened with invalid or empty URLs. #50062 (Also in 39, 40, 41, 42)
- Fixed cross-origin isolation failing for non-file origins. #50789 (Also in 41, 42)
- Fixed frameless transparent windows on Windows losing their transparency after
setResizable(false)followed bysetResizable(true). #51175 (Also in 41, 42) - Fixed improper focus tracking in BaseWindow on MacOS. #49460 (Also in 39, 40, 41, 42)
- Fixed logic bug that rendered certain window types un-resizable on MAS builds. #50096 (Also in 40, 41, 42)
- Fixed native notification clicks not focusing the application window on Wayland. #50568 (Also in 42)
- Fixed printing on Linux failing with "Invalid printer settings". #50430 (Also in 41, 42)
- Fixed remote debugging via
--remote-debugging-portnot working when inspecting from Chrome'schrome://inspectpage. The DevTools page would appear empty due to the frontend URL pointing to a CDN that returned 404 for Electron's Chromium builds. #51236 (Also in 41) - Fixed resize hit targets for frameless windows on Windows. Resize targets now start at the side and bottom edges of the window and extend outward when
frame: false, matching the behavior for windows with frames. #50706 (Also in 41, 42) - Fixed shutdown crash on windows when power monitor notifications were subscribed. #50878 (Also in 42)
- Fixed test scaffolding bug when running tests locally on Linux. #51129 (Also in 40, 41, 42)
- Fixed the appearance of maximized windows on GNOME in Wayland, especially when non-default GTK themes like Breeze are set. #50550 (Also in 41, 42)
- Fixed the crash keys being lost and the crash reporter hanging on macOS when many dynamic crash keys were registered. #50795 (Also in 40, 41, 42)
- Fixed user resizing of transparent windows on win32 platform. #49428 (Also in 39, 40, 41, 42)
- Fixed utilityProcess exit event reporting incorrect exit codes on Windows when the exit code has the high bit. #50256 (Also in 40, 41, 42)
- Fixed window freeze when failing to enter/exit fullscreen on macOS. #49421 (Also in 39, 40, 41, 42)
- Improved the way Electron determines the default XDG App ID and WM_CLASS on Linux for better platform compatibility if
desktopNameis not provided inpackage.json. #51424 (Also in 41, 42) - Moved Electron-specific help menu links to the default app only; unpackaged apps will no longer see these items in their default menu. #50629 (Also in 40, 41, 42)
- On Linux, apps should now display their names and icons in audio managers instead of all being labeled as Chromium. #49270
- Removed "representedObject is not a WeakPtrToElectronMenuModelAsNSObject" logging when interacting with macOS menus. #50608 (Also in 41, 42)
- Removed support for the ELECTRON_SKIP_BINARY_DOWNLOAD environment variable. #50406 (Also in 42)
- This PR fixes a regression in silent printing where custom DPI values from webContents.print were not honored, causing incorrect output scaling in real-world print flows. #51046 (Also in 41, 42)
- Added support for using a proxy during yarn install. #50322 (Also in 39, 40, 41, 42)
- Enabled profile-guided optimization for V8 builtins in release builds, improving JavaScript builtin performance (Array, String, RegExp, etc.). #50416 (Also in 40, 41, 42)
- Fixed
gn genfailing to resolveelectron_versionwhen building from agit worktreecheckout. #51146 (Also in 39, 40, 41, 42) - Improved performance of
app.getApplicationNameForProtocol()on Linux. #51251 - Improved performance of
app.isDefaultProtocolClient()andapp.setAsDefaultProtocolClient()on Linux. #51316 - Updated Chromium to 149.0.7827.0. #51481
- Updated Node.js to v24.15.0. #51091
v5.0.0
Welcome to the release for the tldraw SDK's fifth major release.
This 5.0 release introduces several new systems and long-requested features, including:
- a first-class theme system with display values
- a new
OverlayUtilsystem for canvas overlays - an extensibility APIs for custom record types, asset types, geo shapes, and frame-like shapes
Two new packages ship alongside it: @tldraw/driver for imperative editor control and @tldraw/mermaid for converting Mermaid diagrams into native shapes. It also adds a shape attribution system with the TLUserStore provider, clipboard and performance-measurement hooks, WebSocket hibernation in tlsync, RTL support, cross-window embedding, and various other improvements and bug fixes.
We've created a new experimental agent skill that you can use to migrate tldraw automatically. To use the skill, run your agent harness of choice (e.g. Claude Code or Codex) at the directory containing your tldraw project, and ask it to:
Please visit
https://github.com/tldraw/tldraw/blob/main/skills/tldraw-migrate/README.mdand follow the instructions there to migrate tldraw to the latest version.
The skill will copy the necessary files into your directory, pull the relevant release notes and migration guides from tldraw, and then get to work on the migration. We've seen good results in the repos that we've tried it on, however agents are still is a bit of a dice roll so please check their work.
💥 Custom themes with display values (#8410)
A new first-class theme system replaces the previous approach where colors were hardcoded and resolved inline. Themes are named, registered objects that shape utils consume via a structured display values pipeline.
Register custom themes via TLThemes module augmentation for type-safe IDs, add or remove palette colors via TLThemeDefaultColors and TLRemovedDefaultThemeColors, and pass themes to the editor via the themes and initialTheme props:
<Tldraw themes={{ corporate: myCorporateTheme }} initialTheme="corporate" />
Each default shape util defines getDefaultDisplayValues to resolve visual properties (colors, stroke widths, font sizes) from the current theme and color mode. Override display values for a default shape with getCustomDisplayValues:
const MyDrawShapeUtil = DrawShapeUtil.configure({
getCustomDisplayValues(_editor, _shape, _theme, _colorMode) {
return { strokeWidth: 10 }
},
})
Migration guide
The inferDarkMode prop has been renamed to colorScheme and changed from boolean to 'light' | 'dark' | 'system':
// Before
<Tldraw inferDarkMode />
// After
<Tldraw colorScheme="system" />
useIsDarkMode() has been renamed to useColorMode() and returns 'dark' | 'light' instead of boolean.
getDefaultColorTheme() and DefaultColorThemePalette have been removed. Use editor.getCurrentTheme().colors[colorMode] instead:
// Before
const theme = getDefaultColorTheme({ isDarkMode })
// After
const theme = editor.getCurrentTheme()
const colors = theme.colors[editor.getColorMode()]
useDefaultColorTheme() has been removed. Use editor.getCurrentTheme() and useColorMode() instead.
FONT_FAMILIES, FONT_SIZES, LABEL_FONT_SIZES, STROKE_SIZES, TEXT_PROPS, and ARROW_LABEL_FONT_SIZES have been removed — these are now resolved via display values.
SvgExportContext.themeId has been renamed to SvgExportContext.colorMode and changed from string to 'light' | 'dark'.
getColorValue() now takes TLThemeColors as its first argument instead of TLDefaultColorTheme.
💥 Custom overlays (#8469)
A new OverlayUtil system unifies canvas overlays. Built-in brushes, handles, scribbles, snap indicators, selection foreground, collaborator cursors, and arrow hints are now implemented as overlay utils and can be customized or extended via the overlayUtils prop.
Overlays now render in front of indicators in a unified CanvasOverlays layer, and the legacy default component implementations and their CSS have been removed.
Migration guide
The legacy overlay components have been removed from TLEditorComponents. Canvas overlays are now rendered directly to a 2D canvas context by OverlayUtil classes, and customization happens by subclassing the default util rather than swapping a React component.
Customizing a built-in overlay: extend the default util and give it the same static type; it replaces the built-in when passed via overlayUtils:
// Before
const components: TLEditorComponents = {
Brush: MyBrushComponent,
}
<Tldraw components={components} />
// After
import { Tldraw, BrushOverlayUtil, type TLBrushOverlay } from 'tldraw'
class MyBrushOverlayUtil extends BrushOverlayUtil {
override render(ctx: CanvasRenderingContext2D, overlays: TLBrushOverlay[]) {
const overlay = overlays[0]
if (!overlay) return
const { x, y, w, h } = overlay.props
const zoom = this.editor.getEfficientZoomLevel()
ctx.fillStyle = 'rgba(0, 0, 255, 0.1)'
ctx.strokeStyle = 'blue'
ctx.lineWidth = 1 / zoom
ctx.beginPath()
ctx.rect(x, y, w, h)
ctx.fill()
ctx.stroke()
}
}
<Tldraw overlayUtils={[MyBrushOverlayUtil]} />
The following slots have been removed from TLEditorComponents. Subclass the matching default overlay util instead:
Brush,ZoomBrush→BrushOverlayUtil,ZoomBrushOverlayUtilScribble→ScribbleOverlayUtilSnapIndicator→SnapIndicatorOverlayUtilHandle,Handles→ShapeHandleOverlayUtilSelectionForeground,SelectionBackground→SelectionForegroundOverlayUtilCollaboratorHint→CollaboratorHintOverlayUtil(collaborator cursors/brushes/scribbles have their own utils too)
The corresponding Default* exports and LiveCollaborators have also been removed.
ShapeUtil.indicator() → ShapeUtil.getIndicatorPath(). The shape util method that draws a shape's selection indicator no longer returns JSX. It now returns a Path2D (or a TLIndicatorPath) and is composited onto the canvas overlay layer. Every custom ShapeUtil that overrides indicator needs to migrate:
// Before
override indicator(shape: MyShape) {
return <rect width={shape.props.w} height={shape.props.h} />
}
// After
override getIndicatorPath(shape: MyShape): Path2D {
const path = new Path2D()
path.rect(0, 0, shape.props.w, shape.props.h)
return path
}
For shapes whose indicator should match the shape's geometry, return path built from the same primitives. For placeholder shapes (e.g. an ErrorShape), return an empty new Path2D() and declare the return type explicitly so TypeScript doesn't infer never.
The React component slots ShapeIndicator, ShapeIndicators, and ShapeIndicatorErrorFallback are also removed from TLEditorComponents — there is no replacement React slot, since indicators now render through getIndicatorPath().
Overlays cannot render React; they draw into a 2D canvas context. For React-based overlays, render an HTML layer above the canvas via a regular TLEditorComponents slot like InFrontOfTheCanvas.
Overlay colors come from TLTheme, not CSS variables. Read them inside render() via this.editor.getCurrentTheme().colors[this.editor.getColorMode()] so overlays follow light/dark mode automatically.
These CSS variables have been removed: --tl-color-snap, --tl-color-brush-fill, --tl-color-brush-stroke, --tl-color-laser, --tl-layer-overlays-custom.
Overriding them (or the removed selectors .tl-brush, .tl-scribble, .tl-snap-indicator, .tl-handle*, .tl-selection__fg__outline, .tl-corner-handle, .tl-text-handle, .tl-corner-crop-handle, .tl-mobile-rotate__*) no longer has any effect. Port these to TLTheme entries or to the overlay util's render().
Several <Tldraw> props that previously lived at the top level have been consolidated under the options prop, and a few extension points moved off the component entirely.
Migration guide
cameraOptions, textOptions, and deepLinks props moved into options:
// Before
<Tldraw cameraOptions={camOpts} textOptions={txtOpts} deepLinks />
// After
<Tldraw options={{ camera: camOpts, text: txtOpts, deepLinks: true }} />
embeds prop removed; configure embed definitions on EmbedShapeUtil:
// Before
<Tldraw embeds={[...DEFAULT_EMBED_DEFINITIONS, customEmbed]} />
// After
import { EmbedShapeUtil } from 'tldraw'
const ConfiguredEmbedShapeUtil = EmbedShapeUtil.configure({
embedDefinitions: [...DEFAULT_EMBED_DEFINITIONS, customEmbed],
})
<Tldraw shapeUtils={[ConfiguredEmbedShapeUtil]} />
This silently compiles in some setups (the prop is unknown but JSX won't always reject it), so this is the kind of change that the typecheck won't always catch — search the source for embeds= and migrate any matches.
setDefaultEditorAssetUrls() and setDefaultUiAssetUrls() are no longer part of the public API. They still exist at runtime for now, but they're marked @internal and should not be relied on. Pass assetUrls to each <Tldraw> instead:
// Before
import { setDefaultEditorAssetUrls, setDefaultUiAssetUrls } from 'tldraw'
setDefaultEditorAssetUrls(assetUrls)
setDefaultUiAssetUrls(assetUrls)
<Tldraw />
// After
<Tldraw assetUrls={assetUrls} />
Do not reach for module augmentation to re-expose the old globals — find each <Tldraw> mount point and pass assetUrls directly.
Custom record types (#8213)
You can now register custom record types in the tldraw store for persisting and synchronizing domain-specific data that doesn't fit into shapes, bindings, or assets. Custom records support scoping (document/session/presence), validation, migrations, and default properties.
import { createTLSchema, createCustomRecordId } from 'tldraw'
const schema = createTLSchema({
records: [
{
typeName: 'marker',
scope: 'document',
validator: markerValidator,
},
],
})
TypeScript module augmentation via TLGlobalRecordPropsMap lets custom record types participate in the TLRecord union.
Extensible geo shapes (#8543)
GeoShapeUtil now supports custom geo types via a customGeoTypes option on configure(). Previously, adding a new geo type required forking or monkey-patching GeoShapeUtil; now custom types plug into the existing system and inherit labels, resizing, fill/dash/color styling, SVG export, and hyperlink support — while supplying their own path geometry, snap behavior, creation size, and style panel icon.
import { GeoShapeUtil, PathBuilder } from 'tldraw'
const MyGeoShapeUtil = GeoShapeUtil.configure({
customGeoTypes: {
'rounded-rect': {
getPath: (w, h, shape) => {
const r = Math.min(w, h) * 0.2
return new PathBuilder()
.moveTo(r, 0, { geometry: { isFilled: shape.props.fill !== 'none' } })
.lineTo(w - r, 0)
.circularArcTo(r, false, true, w, r)
.lineTo(w, h - r)
.circularArcTo(r, false, true, w - r, h)
.lineTo(r, h)
.circularArcTo(r, false, true, 0, h - r)
.lineTo(0, r)
.circularArcTo(r, false, true, r, 0)
.close()
},
snapType: 'polygon',
icon: 'geo-rectangle',
defaultSize: { w: 200, h: 150 },
},
},
})
<Tldraw shapeUtils={[MyGeoShapeUtil]} />
Each definition supplies getPath, snapType ('polygon' for vertex + center snaps, 'blobby' for center-only), and an icon for the style panel, plus optional defaultSize and onDoubleClick handler. Custom types appear alongside the built-ins in the geo picker.
💥 Extensible asset types (#8031)
A new AssetUtil base class follows the ShapeUtil / BindingUtil pattern, making the asset system extensible. Previously, assets were a hardcoded union of image, video, and bookmark types. Now you can register custom asset types with their own MIME type handling, file-to-asset conversion, and shape creation logic.
import { AssetUtil } from '@tldraw/editor'
class AudioAssetUtil extends AssetUtil<TLAudioAsset> {
static override type = 'audio' as const
override getSupportedMimeTypes() {
return ['audio/mpeg', 'audio/wav']
}
override async getAssetFromFile(editor, file) {
/* ... */
}
}
;<Tldraw assetUtils={[AudioAssetUtil]} />
TLAssetStore keeps upload/resolve/remove as cross-cutting concerns, while AssetUtil handles type-specific behavior: MIME types, file-to-asset metadata, and asset-to-shape creation.
Migration guide
assetValidator has been removed. Use imageAssetValidator, videoAssetValidator, or bookmarkAssetValidator instead.
getMediaAssetInfoPartial has been removed. Use AssetUtil.getAssetFromFile instead.
notifyIfFileNotAllowed signature changed from (file, options) to (editor, file, options).
getAssetInfo signature changed from (file, options, assetId?) to (editor, file, assetId?) and now returns TLAsset | null instead of throwing.
Frame-like custom shapes (#8331)
Custom shapes can now opt into frame-like behavior: clipping children, acting as a parent on paste and drag-in, blocking erasure from inside, and supporting full-brush selection. Previously, frame behavior was hardcoded to the built-in frame type; the editor and tools now route frame checks through editor.getShapeUtil(shape).isFrameLike(shape).
The easiest way to build one is to extend the new BaseFrameLikeShapeUtil abstract class, which provides sensible defaults for isFrameLike, providesBackgroundForChildren, canReceiveNewChildrenOfType, canRemoveChildrenOfType, getClipPath, onDragShapesIn, and onDragShapesOut:
import { BaseFrameLikeShapeUtil, SVGContainer } from '@tldraw/editor'
class MyContainerUtil extends BaseFrameLikeShapeUtil<MyContainerShape> {
static override type = 'my-container' as const
static override props = myContainerShapeProps
override getDefaultProps() {
return { w: 300, h: 200 }
}
override component(shape: MyContainerShape) {
return <SVGContainer>...</SVGContainer>
}
override indicator(shape: MyContainerShape) {
return <rect width={shape.props.w} height={shape.props.h} />
}
}
Shapes that need frame behavior without inheriting from BaseFrameLikeShapeUtil can override isFrameLike() directly on any ShapeUtil. FrameShapeUtil now extends BaseFrameLikeShapeUtil, so existing frames are unaffected.
Shape attribution and TLUserStore (#8147)
A new shape attribution system tracks who created and last edited shapes. The TLUserStore provider interface connects tldraw to your auth system with reactive Signal-based methods: getCurrentUser() returns the active user for presence and attribution, while resolve(userId) resolves any user ID to display info.
<Tldraw
users={{
getCurrentUser: () => currentUserSignal,
resolve: (userId) => resolvedUserSignal(userId),
}}
/>
User records are now document-scoped via the unified TLUser record type. SDK users can extend user records with custom validated metadata through createTLSchema:
const schema = createTLSchema({
user: {
meta: {
isAdmin: T.boolean,
department: T.string,
},
},
})
Note shapes now track and display a "first edited by" attribution label in the bottom-right corner, showing who first added text to the note.
Migration guide
useTldrawUser has been removed. Previously it bundled user preferences (color, color scheme) and user identity (id, name) into a single object. These are now separate concerns:
- Preferences (color, color scheme, snap mode, etc.) are managed via
TLUserPreferences. Set them with the editor's user-preferences API directly. - Identity for attribution comes from a
TLUserStoreprovider passed to the newusersprop on<Tldraw>.
// Before
const user = useTldrawUser({ userPreferences, setUserPreferences })
<Tldraw user={user} />
// After
<Tldraw
users={{
getCurrentUser: () => currentUserSignal,
resolve: (userId) => resolvedUserSignal(userId),
}}
colorScheme={userPreferences.colorScheme}
/>
If you only need preferences (no custom identity), pass colorScheme directly and seed preferences imperatively after mount; if you only need identity, pass users. Most apps want both.
@tldraw/driver (#7952)
A new @tldraw/driver package provides an imperative API for driving the tldraw editor programmatically. Driver wraps an Editor instance and exposes event dispatch, selection transforms, clipboard operations, and shape queries with fluent chaining.
import { Driver } from '@tldraw/driver'
const driver = new Driver(editor)
driver.pointerMove(100, 100).pointerDown().pointerMove(200, 200).pointerUp()
This is useful for scripting, automation, agent workflows, and REPL-style interaction. The release includes a Scripter example that demonstrates the package.
A new @tldraw/mermaid package converts Mermaid diagram syntax into native tldraw shapes. Paste Mermaid text to create flowcharts, sequence diagrams, state diagrams, and mind maps as editable shapes on the canvas.
import { createMermaidDiagram } from '@tldraw/mermaid'
await createMermaidDiagram(
editor,
`
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Action]
B -->|No| D[End]
`
)
The package parses Mermaid syntax, extracts layout from the rendered SVG, and produces a diagram-agnostic blueprint that gets rendered into geo shapes, arrows, and groups.
Node creation is extensible: pass mapNodeToRenderSpec per diagram type to map diagram nodes to different shapes, or use createShape in BlueprintRenderingOptions to take full control of how nodes are created on the canvas.
Arbitrary iframe embeds (#8306)
Paste any <iframe> embed code onto the canvas to create an embed shape. Previously only URLs matching known providers (YouTube, Google Maps, etc.) worked. Now any valid iframe with an HTTP(S) source creates an embed directly. It works with services like OpenStreetMap, SoundCloud, Loom, and more.
Clipboard hooks (#8290)
New TldrawOptions hooks let you intercept and customize clipboard copy, cut, and paste. onBeforeCopyToClipboard filters or transforms serialized content before it hits the clipboard, onBeforePasteFromClipboard filters parsed paste payloads before shapes are created, and onClipboardPasteRaw handles raw clipboard data before tldraw's default paste pipeline.
const options: Partial<TldrawOptions> = {
onBeforeCopyToClipboard(info, content) {
// filter shapes or transform content before copy/cut
return content
},
onBeforePasteFromClipboard(info, content) {
// filter or transform parsed paste content
return content
},
onClipboardPasteRaw(info) {
// handle raw clipboard data yourself; return false to cancel tldraw handling
return false
},
}
Cross-window embedding support (#8196)
Tldraw now works correctly when embedded in iframes, Electron pop-out windows, and Obsidian plugins where the global document and window differ from the ones tldraw is mounted in. All bare document and window references have been replaced with container-aware alternatives.
New helpers getOwnerDocument() and getOwnerWindow() are exported from @tldraw/editor, along with Editor.getContainerDocument() and Editor.getContainerWindow() convenience methods.
Performance measurement hooks (#8421)
A new editor.performance API lets SDK users subscribe to editor performance events: interaction frame times (translating, resizing, drawing), camera pan/zoom sessions, shape create/update/delete operations, and undo/redo timings. Events aggregate frame-time percentiles (avg / median / p95 / p99) and, on Chromium, attach Long Animation Frame data with per-script attribution for diagnosing jank.
const unsubscribe = editor.performance.on('interaction-end', (event) => {
// forward to analytics
const { frameTimes, longAnimationFrames, ...metrics } = event
track('editor.interaction', metrics)
})
The manager is zero-overhead when no listeners are attached. Custom tools opt in to interaction tracking via static trackPerformance = true on the StateNode. A PerformanceApiAdapter is also available for piping events into the browser Performance API for DevTools timelines.
RTL support (#8033)
The tldraw UI now supports right-to-left languages like Arabic. A new useDirection() hook returns 'ltr' or 'rtl' from the current translation context, and all Radix UI components and CSS have been updated to respect text direction. The dir attribute is set on .tl-container, and CSS uses logical properties (margin-inline-start, inset-inline-end, etc.) instead of physical ones.
WebSocket hibernation in tlsync (#8070)
TLSocketRoom now supports session resume and snapshot APIs for WebSocket hibernation environments like Cloudflare Durable Objects. Sessions can be suspended and restored without losing state, and the sync-cloudflare template has been updated to use the WebSocket Hibernation API.
New APIs include handleSocketResume() for restoring sessions from snapshots, getSessionSnapshot() for capturing session state, and an onSessionSnapshot callback for persisting snapshots to WebSocket attachments.
- 💥 Remove
defaultColorNames,DefaultColorThemePalette,DefaultLabelColorStyle,TLDefaultColorThemetype, andgetDefaultColorTheme()from@tldraw/tlschema. Useeditor.getCurrentTheme().colorsinstead. (#8410) - 💥 Remove
ARROW_LABEL_FONT_SIZES,FONT_FAMILIES,FONT_SIZES,LABEL_FONT_SIZES,STROKE_SIZES,TEXT_PROPS, anduseDefaultColorTheme()from@tldraw/tldraw. These are now resolved via display values. (#8410) - 💥 Rename
inferDarkModeprop tocolorScheme(boolean→'light' | 'dark' | 'system'). RenameuseIsDarkMode()touseColorMode()(returns'dark' | 'light'instead ofboolean). (#8410) - 💥 Rename
SvgExportContext.themeIdtoSvgExportContext.colorMode(string→'light' | 'dark'). (#8410) - 💥 Change
getColorValue()first argument fromTLDefaultColorThemetoTLThemeColors. (#8410) - 💥 Change
PlainTextLabelPropsandRichTextLabelProps:font→fontFamily,align→textAlign,fillremoved. (#8410) - 💥 Remove
Brush,ZoomBrush,Scribble,SnapIndicator,Handle,Handles,SelectionForeground,SelectionBackground,CollaboratorHint,ShapeIndicator,ShapeIndicators, andShapeIndicatorErrorFallbackfromTLEditorComponents, along with the correspondingDefault*component exports andLiveCollaborators. Migrate custom overlay components toOverlayUtil; indicator customization moves toShapeUtil.getIndicatorPath(). (#8469) - 💥 Remove the CSS variables
--tl-color-snap,--tl-color-brush-fill,--tl-color-brush-stroke,--tl-color-laser, and--tl-layer-overlays-custom, along with the overlay class selectors (.tl-brush,.tl-scribble,.tl-snap-indicator,.tl-handle*,.tl-selection__fg__outline,.tl-corner-handle,.tl-text-handle,.tl-corner-crop-handle,.tl-mobile-rotate__*). Overlay colors now come fromTLTheme. (#8469) - 💥 Remove
assetValidator. UseimageAssetValidator,videoAssetValidator, orbookmarkAssetValidatorinstead. (#8031) - 💥 Remove
getMediaAssetInfoPartial. UseAssetUtil.getAssetFromFileinstead. (#8031) - 💥 Change
notifyIfFileNotAllowedsignature from(file, options)to(editor, file, options). (#8031) - 💥 Change
getAssetInfosignature from(file, options, assetId?)to(editor, file, assetId?)and returnTLAsset | nullinstead of throwing. (#8031) - 💥 Move the
Cmd+Shift+C/Ctrl+Shift+Cshortcut from "Copy as SVG" to "Copy as PNG". (#8532) - 💥 Replace
ShapeUtil.indicator()(returned JSX) withShapeUtil.getIndicatorPath()(returnsPath2D | TLIndicatorPath | undefined). Indicators now render to the canvas overlay layer instead of as React elements. (#8469) - 💥 Move
cameraOptions,textOptions, anddeepLinksfrom top-level<Tldraw>props into theoptionsprop (e.g.options={{ camera, text, deepLinks }}). - 💥 Remove the
embedsprop from<Tldraw>. Configure embed definitions viaEmbedShapeUtil.configure({ embedDefinitions })and pass the configured util throughshapeUtils. - 💥 Demote
setDefaultEditorAssetUrls()andsetDefaultUiAssetUrls()to@internal. PassassetUrlsto each<Tldraw>instead. - 💥 Remove
useTldrawUser. Use the newusersprop (TLUserStore) for identity andTLUserPreferencesfor preferences. - 💥 Replace
TLDrawShapeSegment.pointswith the helpergetPointsFromDrawSegment(segment, scaleX, scaleY)so segment points respect the shape's current scale. - 💥 Change
BindingUtilhook params:fromShapeType/toShapeTypeare removed in favor of fullfromShape/toShaperecords (readfromShape.type/toShape.typedirectly). - 💥 Add
'middle-legacy'(and other legacy values) to thealignunion resolved byPlainTextLabel/RichTextLabel. If your code mapsalignintoPlainTextLabel.textAlign, narrow legacy values to one of'start' | 'center' | 'end'before passing them through. - Add
TLTheme,TLThemeId,TLThemes,TLThemeDefaultColors,TLThemeColors,TLRemovedDefaultThemeColors,ThemeManager,getDisplayValues(),getColorValue(), andDEFAULT_THEMEfor the new theme system. (#8410) - Add
themesandinitialThemeprops to<Tldraw>and<TldrawEditor>. (#8410) - Add
getCurrentTheme(),setCurrentTheme(),getThemes(),getTheme(),updateTheme(),updateThemes(), andgetColorMode()to the editor. (#8410) - Add
getDefaultDisplayValuesandgetCustomDisplayValuesto shape util options for theme-aware visual properties. (#8410) - Add
OverlayUtil,TLOverlay,OverlayManager,Editor.overlays,defaultOverlayUtils, and theoverlayUtilsprop on<Tldraw>/<TldrawEditor>for registering and managing canvas overlays. (#8469) - Add per-overlay utils:
BrushOverlayUtil,ZoomBrushOverlayUtil,ScribbleOverlayUtil,SnapIndicatorOverlayUtil,ShapeHandleOverlayUtil,SelectionForegroundOverlayUtil,ArrowHintOverlayUtil,CollaboratorBrushOverlayUtil,CollaboratorScribbleOverlayUtil,CollaboratorHintOverlayUtil, andCollaboratorCursorOverlayUtil. (#8469) - Add overlay-related colors to
TLTheme. (#8469) - Add
BaseFrameLikeShapeUtilabstract class andShapeUtil.isFrameLike()so custom shapes can opt into frame-like behaviors (paste parenting, full-brush selection, blocking erasure from inside, clipping children).FrameShapeUtilnow extendsBaseFrameLikeShapeUtil. (#8331) - Add extensibility API for custom geo shape types via
GeoShapeUtil.configure({ customGeoTypes }). AddGeoTypeDefinitioninterface for defining path geometry, snap behavior, creation size, style panel icon, and double-click handler while inheriting standard geo shape behavior. (#8543) - Add
AssetUtilbase class withconfigure(),getDefaultProps(),getSupportedMimeTypes(),getAssetFromFile(), andcreateShape(). AddassetUtilsprop to<Tldraw>. AddEditor.getAssetUtil(),Editor.hasAssetUtil(), andEditor.getAssetUtilForMimeType(). AddTLGlobalAssetPropsMapfor type-safe custom asset registration. AddcreateAssetRecordType(),defaultAssetSchemas, andassetsparameter tocreateTLSchema(). (#8031) - Add
CustomRecordInfointerface,createCustomRecordId(),createCustomRecordMigrationIds(),createCustomRecordMigrationSequence(),isCustomRecord(),isCustomRecordId()for custom record types.createTLSchema()andcreateTLStore()now accept arecordsoption. (#8213) - Add
TLUserStoreinterface withgetCurrentUser()andresolve()for connecting tldraw to auth systems. Add unifiedTLUserrecord type,UserRecordType,createUserId,isUserId,userIdValidator, andcreateUserRecordType()for extensible user schemas. Adduserparameter tocreateTLSchema(). AddEditor.getAttributionUser(),Editor.getAttributionUserId(), andEditor.getAttributionDisplayName(). AddtextFirstEditedByprop toTLNoteShapeProps. (#8147) - Add
@tldraw/driverpackage withDriverclass for imperative editor control. (#7952) - Add
@tldraw/mermaidpackage withcreateMermaidDiagram(),renderBlueprint(), andMermaidDiagramErrorfor converting Mermaid syntax to tldraw shapes. (#8194) - Add
mapNodeToRenderSpecper-diagram-type option andcreateShapeoverride to@tldraw/mermaidfor customizing how diagram nodes are rendered as shapes. (#8322) - Add
onBeforeCopyToClipboard,onBeforePasteFromClipboard, andonClipboardPasteRawhooks toTldrawOptionsfor intercepting clipboard operations. AddTLClipboardWriteInfoandTLClipboardPasteRawInfotypes. ExporthandleNativeOrMenuCopyfrom@tldraw/tldraw. (#8290) - Add
Cmd+Shift+V/Ctrl+Shift+Vshortcut to paste clipboard content as plain text.Cmd+Shift+Vno longer toggles paste-at-cursor positioning. (#8347) - Add support for pasting arbitrary
<iframe>embed codes to create embed shapes from any service. (#8306) - Add Canva to
DEFAULT_EMBED_DEFINITIONSso Canva design URLs paste as iframe embeds. (#8459) - Add
TldrawOptions.rightClickPanning(defaulttrue) to gate the new right-click drag-to-pan behavior. AddInputsManager.getIsRightPointing()/setIsRightPointing(). (#8501) - Add
Editor.performance(PerformanceManager) withon(),once(), anddispose()for subscribing to interaction, camera, shape-operation, frame, and undo/redo performance events. AddPerformanceApiAdapterfor piping events into the browser Performance API. AddStateNode.trackPerformancestatic field so custom tools can opt into interaction tracking. AddTLPerfFrameTimeStats,TLPerfEventMap,TLInteractionStartPerfEvent,TLInteractionEndPerfEvent,TLCameraStartPerfEvent,TLCameraEndPerfEvent,TLShapeOperationPerfEvent,TLFramePerfEvent,TLUndoRedoPerfEvent,TLPerfLongAnimationFrame, andTLPerfLongAnimationFrameScript. (#8421) - Add
Editor.getContainerDocument()andEditor.getContainerWindow()methods, andgetOwnerDocument()/getOwnerWindow()helpers for cross-window embedding. (#8196) - Add
handleSocketResume(),getSessionSnapshot(), andonSessionSnapshottoTLSocketRoomfor WebSocket hibernation support. AddclientTimeoutoption toTLSyncRoom. (#8070) - Add
useDirection()hook for RTL support. (#8033) - Expose
PeopleMenu,PeopleMenuItem,PeopleMenuFacePile, andUserPresenceEditorthroughTldrawUiComponentsso the share panel sub-components can be overridden via the<Tldraw />componentsprop. (#8346) - Add
'none'toTLDefaultDashStylefor hiding shape borders while preserving fills. The option is not exposed in the style panel — it can only be set programmatically. AddNonePathBuilderOpts;PathBuilder.toSvg()now returnsnullfor the'none'style. (#8453) - Export
defaultHandleExternalFileReplaceContent, which was previously referenced in docs but missing from the package's public exports. (#8579) - Change
TLSvgExportOptions.paddingto acceptnumber | 'auto'. The'auto'mode (now default) renders with padding then trims to visual content bounds. (#8202) - Add
TextManager.measureHtmlBatch()for batched DOM text measurement. (#7949) - Add
'json'toTLCopyTypefor copying shapes as JSON in debug mode. (#8206) - Add
Vec.IsFinite()for checking whether a vector has finite coordinates. (#8176) - Change
Vec.PointsBetween()to accept an optionaleaseparameter. (#7977)
- Optimize geometry hot paths for hit testing: reduce allocations and function call overhead in
Vec,Edge2d,Circle2d,Arc2d,Polyline2d, and intersection routines. Circle hit testing is up to 19x faster, polyline nearest-point is 6.8x faster. (#8210) - Improve resize performance for multiple geo shapes with text labels by batching DOM measurements into a single pass per frame. (#7949)
- Exports now automatically trim to visual content bounds, capturing overflow like thick strokes and arrowheads without extra whitespace. (#8202)
- Add
Cmd+Shift+V/Ctrl+Shift+Vshortcut to paste clipboard content as plain text, stripping HTML and rich formatting.Cmd+Shift+Vno longer toggles paste-at-cursor positioning — the "Paste at cursor" preference covers that use case. (#8347) - Change
Cmd+Shift+C/Ctrl+Shift+Cto copy selected shapes as PNG instead of SVG, matching the default in most apps. The SVG copy path is still available from the Copy-as menu. (#8532) - Right-click and drag now pans the camera, matching tools like Figma. A static right-click still opens the context menu on release. Gate via
TldrawOptions.rightClickPanning(defaults totrue). (#8501) - Allow Cmd+click / Ctrl+click on style panel items to apply style changes only to selected shapes without updating defaults for future shapes. (#8452)
- Hide selection overlay when nudging shapes with arrow keys. (#8447)
- Move the debug mode toggle into the preferences submenu. (#8259)
- Tighten iframe referrer policy for embeds to send only the origin instead of the full URL to third-party embed providers. (#8412)
- Replace the
@use-gesture/reactdependency with custom gesture handling. Bundle size is smaller and a stale dependency is gone. (#8392)
- Fix
bailToMarksilently discarding pending history changes when the target mark doesn't exist. (#8260) - Fix
FocusManager.dispose()not actually removing document event listeners due to.bind()creating new function references. (#8232) - Fix camera state getting stuck at
'moving'when the editor is disposed mid-transition (e.g. deep links under React strict mode), which blocked all pointer interactions on the canvas. (#8396) - Fix leaked camera animations, following subscriptions, and stale menu state when the editor is disposed during active operations. (#8422)
- Fix a memory leak where disposed
Editorinstances were retained through a shared throttledupdateHoveredShapeIdclosure. (#8439) - Fix a memory leak where disposed
Editorinstances were retained through thewindow.__tldraw__hardResetglobal. (#8476) - Fix crash when isolating curved arrows with degenerate binding geometry. (#8176)
- Fix all shapes disappearing when a labeled arrow has zero length (both endpoints overlapping), which previously propagated NaN values through the spatial index. (#8329)
- Fix crash from duplicate fractional index keys in
kickoutOccludedShapesduring multiplayer sync. (#8448) - Fix crash in browsers without
OffscreenCanvassupport (e.g. older Safari) when preloading image alpha data. (#8582) - Fix over-softened corners and end artifacts when shift-clicking to draw straight line segments. (#7977)
- Fix eraser not erasing shapes when starting a drag from inside a group's bounds. (#8054)
- Fix draw-shape loop-closing sensitivity so closing works more consistently across zoom levels. (#8293)
- Fix shadow artifact and oversized caret on notes and geo shapes at high zoom in dynamic size mode. (#8378)
- Fix pattern fill not scaling correctly with dynamic size mode. (#8441)
- Fix arrow labels rendered at incorrect size when editing at high zoom in dynamic size mode. (#8451)
- Fix rotation performance regression where CSS
transform: scale()was applied to shape labels even when dynamic size was inactive, forcing an unnecessary compositing layer on every shape. (#8570) - Fix spiky artifacts on draw-style geometric shapes by using a circular random offset distribution instead of a square one. (#8466)
- Fix pasting into editable text shapes when the clipboard contains tldraw data. (#8192)
- Fix slight positioning drift when pasting text onto the canvas. (#8345)
- Fix right-clicking inside a multi-selection over a filled background shape changing the selection. (#8434)
- Fix context menu briefly flashing when right-clicking to dismiss an already-open context menu. (#8498)
- Fix context menu items accidentally being selected when right-clicking and quickly moving the mouse. (#8499)
- Fix opacity slider drag not working on Safari due to
stopPropagationblocking pointer events. (#8519) - Fix quick zoom mode (Z + Shift) cursor anchor and brush misalignment when the tldraw container is offset from the top-left of the window. (#8520)
- Fix
Cmd+Shift+Vdoing nothing when the clipboard contains an image; the shortcut now falls back to the regular paste flow when there is no plain-text payload. (#8490) - Fix keyboard shortcuts that change styles not marking the change as a style update, causing subsequent shapes to use the wrong defaults. (#8599) (contributed by @danieljamesross)
- Fix "back to content" button flickering when both it and the "move focus to canvas" button are visible. (#8334)
- Fix intermittent
ResizeObserver loopbrowser warnings when hovering over toolbar buttons. (#8574) - Fix missing sandbox attribute on GitHub Gist embeds. (#8403)
- Restrict sandbox permissions for unknown/arbitrary embeds to mitigate security risks from untrusted content. (#8404)
- Fix duplicate presence cursors appearing after login or logout in multiplayer sessions by filtering a session's own stale record from the connect handshake response. (#8542)
- Fix sticky notes preserving stale attribution when cloned via a nib. (#8614)
- Fix
Cmd+Vpaste of tldraw-copied PNGs on Chrome 147 stable, where the custom-format clipboard entry returned a 0-byte blob. (#8615) - Fix note author attribution overflowing the sticky note width in SVG and PNG exports. (#8664)
- Fix keyboard shortcuts not matching on alternative Latin keyboard layouts (Dvorak, Colemak, AZERTY) by replacing the
hotkeys-jslibrary with a small layout-aware native event matcher. (#8669) - Fix TypeScript signature mismatch on
ShapeUtilbase-class methods so overrides that need ashapeparameter can declare it without errors. (#8521)
v2.0.2
- perf(split-chunks): lazily precompute sorted modules for compare by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/13854
- perf(split-chunks): batch split chunk runtime updates by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/13859
- perf(split-chunks): optimize module chunk lookup by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/13873
- perf(build): reduce binding size with size-optimized Wasmtime crates by @Timeless0911 in https://github.com/web-infra-dev/rspack/pull/13877
- feat: add logging for persistent cache validation info by @ahabhgk in https://github.com/web-infra-dev/rspack/pull/13855
- feat(rslib): support emit isolated declarations by @Timeless0911 in https://github.com/web-infra-dev/rspack/pull/13872
- feat(create-rspack): support rslint template mapping by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/13882
- feat(rstest): inject source-module origin into dynamic imports by @fi3ework in https://github.com/web-infra-dev/rspack/pull/13849
- fix: handle weak dynamic imports without async chunks by @hardfist in https://github.com/web-infra-dev/rspack/pull/13848
- fix(source-maps): avoid loader request in lightningcss source maps by @zalishchuk in https://github.com/web-infra-dev/rspack/pull/13830
- fix(rsc): handle server component css by server entry scope by @SyMind in https://github.com/web-infra-dev/rspack/pull/13844
- fix: sort ConcatenatedModule export keys for deterministic builds by @mango766 in https://github.com/web-infra-dev/rspack/pull/13425
- fix: use index maps for concatenated export rendering by @JSerFeng in https://github.com/web-infra-dev/rspack/pull/13875
- fix(core): ignore optional hono type imports by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/13883
- fix(rsc): scope server-entry CSS collection by entry by @SyMind in https://github.com/web-infra-dev/rspack/pull/13878
- fix(rslib): make isolated dts metadata relative by @Timeless0911 in https://github.com/web-infra-dev/rspack/pull/13884
- fix(deps): update http-proxy-middleware to 4.0.0-beta.6 by @Darshan808 in https://github.com/web-infra-dev/rspack/pull/13909
- fix(plugin-library): skip unused exports in ModuleLibraryPlugin by @SAY-5 in https://github.com/web-infra-dev/rspack/pull/13920
- fix: expose numeric chunk ids in JS APIs by @JSerFeng in https://github.com/web-infra-dev/rspack/pull/13839
- fix(rsc): support void onServerComponentChanges callbacks by @SyMind in https://github.com/web-infra-dev/rspack/pull/13885
- fix: align module external remapping with webpack by @JSerFeng in https://github.com/web-infra-dev/rspack/pull/13802
- docs: Add Shakapacker to Ecosystem (Ruby on Rails) by @cody-elhard in https://github.com/web-infra-dev/rspack/pull/13866
- docs: sync Shakapacker ecosystem docs to zh by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/13867
- docs: fix Modern.js links by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/13868
- docs: add TanStack Router to ecosystem by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/13870
- docs: sort config options sidebar by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/13874
- docs(faq): remove outdated React Server Components support section by @lajczi in https://github.com/web-infra-dev/rspack/pull/13898
- docs: sync zh FAQ with RSC update by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/13902
- docs: add webpack package replacements by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/13910
- docs: replace storybook roadmap link with migration guide by @fi3ework in https://github.com/web-infra-dev/rspack/pull/13923
- docs: clarify splitChunks name function by @JSerFeng in https://github.com/web-infra-dev/rspack/pull/13928
- chore: move check source changed jobs to self-hosted runner by @hardfist in https://github.com/web-infra-dev/rspack/pull/13862
- chore: release version 2.0.1 by @intellild in https://github.com/web-infra-dev/rspack/pull/13860
- chore(benchmark): disable minimize for bundle codspeed by @LingyuCoder in https://github.com/web-infra-dev/rspack/pull/13871
- chore(deps): update dependency happy-dom to ^20.9.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13833
- chore(deps): update dependency toml to v4 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13892
- chore(deps): update dependency image-minimizer-webpack-plugin to v5 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13891
- chore(deps): update dependency lint-staged to ^16.4.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13887
- chore(deps): update dependency @module-federation/runtime-tools to v2.4.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13886
- chore(deps): update dependency cspell to v10 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13897
- chore(deps): update dependency @shikijs/transformers to v4 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13896
- chore(deps): update dependency mermaid to ^11.14.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13894
- chore(deps): update dependency terser-webpack-plugin to ^5.5.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13889
- chore(deps): update dependency ws to ^8.20.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13895
- chore(deps): update patch npm dependencies by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13900
- build: replace webpack-merge with rspack-merge by @intellild in https://github.com/web-infra-dev/rspack/pull/13907
- chore(deps): update rust crate rayon to 1.12.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13904
- chore(deps): update rust crate oneshot to 0.2.1 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13903
- chore(deps): update dependency exit-hook to v5 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13906
- chore(deps): update yarn to v4.14.1 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13905
- chore(deps): update dependency memfs to v4.57.2 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13888
- chore(deps): update dependency watchpack to v2.5.1 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13890
- chore(deps): update dependency axios to ^1.16.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13911
- chore(deps): update rust crate hashlink to 0.11.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13912
- chore(deps): update rust crate indexmap to 2.14.0 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13913
- chore(deps): remove http-proxy-middleware dts patch by @chenjiahan in https://github.com/web-infra-dev/rspack/pull/13919
- chore(deps): update dependency @discoveryjs/json-ext to v1 by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13916
- chore(deps): update napi by @renovate[bot] in https://github.com/web-infra-dev/rspack/pull/13899
- @zalishchuk made their first contribution in https://github.com/web-infra-dev/rspack/pull/13830
- @cody-elhard made their first contribution in https://github.com/web-infra-dev/rspack/pull/13866
- @mango766 made their first contribution in https://github.com/web-infra-dev/rspack/pull/13425
- @lajczi made their first contribution in https://github.com/web-infra-dev/rspack/pull/13898
- @Darshan808 made their first contribution in https://github.com/web-infra-dev/rspack/pull/13909
- @SAY-5 made their first contribution in https://github.com/web-infra-dev/rspack/pull/13920
Full Changelog: https://github.com/web-infra-dev/rspack/compare/v2.0.1...v2.0.2
2.14.5
- Fix incorrect invitation token handling on register process Github #9380