tldraw 5.2.0-next.e2b8d10bf10e → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (420) hide show
  1. package/DOCS.md +20294 -0
  2. package/README.md +13 -1
  3. package/RELEASE_NOTES.md +2908 -0
  4. package/dist-cjs/index.d.ts +110 -23
  5. package/dist-cjs/index.js +3 -3
  6. package/dist-cjs/index.js.map +2 -2
  7. package/dist-cjs/lib/TldrawImage.js +0 -1
  8. package/dist-cjs/lib/TldrawImage.js.map +2 -2
  9. package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js +2 -1
  10. package/dist-cjs/lib/bindings/arrow/ArrowBindingUtil.js.map +2 -2
  11. package/dist-cjs/lib/defaultEmbedDefinitions.js +3 -2
  12. package/dist-cjs/lib/defaultEmbedDefinitions.js.map +2 -2
  13. package/dist-cjs/lib/defaultOverlayUtils.js +11 -11
  14. package/dist-cjs/lib/defaultOverlayUtils.js.map +2 -2
  15. package/dist-cjs/lib/overlays/SelectionForegroundOverlayUtil.js +76 -64
  16. package/dist-cjs/lib/overlays/SelectionForegroundOverlayUtil.js.map +2 -2
  17. package/dist-cjs/lib/overlays/ShapeHandleOverlayUtil.js +1 -1
  18. package/dist-cjs/lib/overlays/ShapeHandleOverlayUtil.js.map +2 -2
  19. package/dist-cjs/lib/overlays/ShapeIndicatorOverlayUtil.js +107 -0
  20. package/dist-cjs/lib/overlays/ShapeIndicatorOverlayUtil.js.map +7 -0
  21. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +3 -0
  22. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  23. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +12 -3
  24. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  25. package/dist-cjs/lib/shapes/bookmark/bookmarks.js +54 -6
  26. package/dist-cjs/lib/shapes/bookmark/bookmarks.js.map +2 -2
  27. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +2 -1
  28. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
  29. package/dist-cjs/lib/shapes/draw/getPath.js +1 -1
  30. package/dist-cjs/lib/shapes/draw/getPath.js.map +2 -2
  31. package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js +45 -47
  32. package/dist-cjs/lib/shapes/draw/toolStates/Drawing.js.map +2 -2
  33. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +2 -1
  34. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +2 -2
  35. package/dist-cjs/lib/shapes/frame/FrameShapeTool.js +23 -18
  36. package/dist-cjs/lib/shapes/frame/FrameShapeTool.js.map +2 -2
  37. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +1 -1
  38. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  39. package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js +3 -0
  40. package/dist-cjs/lib/shapes/geo/toolStates/Pointing.js.map +2 -2
  41. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +11 -7
  42. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
  43. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -11
  44. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
  45. package/dist-cjs/lib/shapes/line/toolStates/Pointing.js +5 -1
  46. package/dist-cjs/lib/shapes/line/toolStates/Pointing.js.map +2 -2
  47. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +31 -41
  48. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  49. package/dist-cjs/lib/shapes/note/noteHelpers.js +1 -1
  50. package/dist-cjs/lib/shapes/note/noteHelpers.js.map +2 -2
  51. package/dist-cjs/lib/shapes/note/toolStates/Pointing.js +28 -6
  52. package/dist-cjs/lib/shapes/note/toolStates/Pointing.js.map +2 -2
  53. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +3 -2
  54. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  55. package/dist-cjs/lib/shapes/shared/RichTextLabel.js +3 -3
  56. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
  57. package/dist-cjs/lib/shapes/shared/defaultStyleDefs.js +17 -3
  58. package/dist-cjs/lib/shapes/shared/defaultStyleDefs.js.map +2 -2
  59. package/dist-cjs/lib/shapes/shared/freehand/core.js +424 -0
  60. package/dist-cjs/lib/shapes/shared/freehand/core.js.map +7 -0
  61. package/dist-cjs/lib/shapes/shared/freehand/fmt.js +106 -0
  62. package/dist-cjs/lib/shapes/shared/freehand/fmt.js.map +7 -0
  63. package/dist-cjs/lib/shapes/shared/freehand/getStroke.js +6 -6
  64. package/dist-cjs/lib/shapes/shared/freehand/getStroke.js.map +2 -2
  65. package/dist-cjs/lib/shapes/shared/freehand/getStrokeOutlinePoints.js +320 -86
  66. package/dist-cjs/lib/shapes/shared/freehand/getStrokeOutlinePoints.js.map +3 -3
  67. package/dist-cjs/lib/shapes/shared/freehand/getStrokePoints.js +20 -96
  68. package/dist-cjs/lib/shapes/shared/freehand/getStrokePoints.js.map +3 -3
  69. package/dist-cjs/lib/shapes/shared/freehand/svg.js +55 -19
  70. package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
  71. package/dist-cjs/lib/shapes/shared/freehand/svgInk.js +189 -97
  72. package/dist-cjs/lib/shapes/shared/freehand/svgInk.js.map +3 -3
  73. package/dist-cjs/lib/shapes/shared/freehand/types.js.map +1 -1
  74. package/dist-cjs/lib/shapes/shared/interpolate-props.js +6 -2
  75. package/dist-cjs/lib/shapes/shared/interpolate-props.js.map +2 -2
  76. package/dist-cjs/lib/shapes/text/toolStates/Pointing.js +3 -0
  77. package/dist-cjs/lib/shapes/text/toolStates/Pointing.js.map +2 -2
  78. package/dist-cjs/lib/tools/HandTool/HandTool.js +16 -6
  79. package/dist-cjs/lib/tools/HandTool/HandTool.js.map +2 -2
  80. package/dist-cjs/lib/tools/HandTool/childStates/Dragging.js +10 -1
  81. package/dist-cjs/lib/tools/HandTool/childStates/Dragging.js.map +2 -2
  82. package/dist-cjs/lib/tools/HandTool/childStates/OneFingerZooming.js +84 -0
  83. package/dist-cjs/lib/tools/HandTool/childStates/OneFingerZooming.js.map +7 -0
  84. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +12 -0
  85. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
  86. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js +4 -0
  87. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js.map +2 -2
  88. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +107 -46
  89. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  90. package/dist-cjs/lib/ui/TldrawUi.js +4 -3
  91. package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
  92. package/dist-cjs/lib/ui/components/A11y.js +2 -0
  93. package/dist-cjs/lib/ui/components/A11y.js.map +2 -2
  94. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js +14 -1
  95. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenu.js.map +2 -2
  96. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenuContent.js +0 -6
  97. package/dist-cjs/lib/ui/components/ContextMenu/DefaultContextMenuContent.js.map +2 -2
  98. package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +2 -2
  99. package/dist-cjs/lib/ui/components/Dialogs.js +17 -37
  100. package/dist-cjs/lib/ui/components/Dialogs.js.map +2 -2
  101. package/dist-cjs/lib/ui/components/HelperButtons/BackToContent.js +19 -4
  102. package/dist-cjs/lib/ui/components/HelperButtons/BackToContent.js.map +2 -2
  103. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +12 -2
  104. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +2 -2
  105. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +47 -70
  106. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
  107. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +25 -46
  108. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
  109. package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuAvatar.js.map +2 -2
  110. package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuContent.js.map +2 -2
  111. package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuFacePile.js.map +2 -2
  112. package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuItem.js +1 -1
  113. package/dist-cjs/lib/ui/components/SharePanel/DefaultPeopleMenuItem.js.map +2 -2
  114. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js +1 -0
  115. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +2 -2
  116. package/dist-cjs/lib/ui/components/menu-items.js +7 -0
  117. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  118. package/dist-cjs/lib/ui/components/primitives/TldrawUiDropdownMenu.js +2 -1
  119. package/dist-cjs/lib/ui/components/primitives/TldrawUiDropdownMenu.js.map +2 -2
  120. package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js +14 -3
  121. package/dist-cjs/lib/ui/components/primitives/TldrawUiIcon.js.map +2 -2
  122. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +2 -0
  123. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js.map +2 -2
  124. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +2 -0
  125. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js.map +2 -2
  126. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js +0 -2
  127. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js.map +2 -2
  128. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.js +1 -2
  129. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.js.map +2 -2
  130. package/dist-cjs/lib/ui/context/actions.js +70 -1
  131. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  132. package/dist-cjs/lib/ui/context/asset-urls.js +5 -8
  133. package/dist-cjs/lib/ui/context/asset-urls.js.map +2 -2
  134. package/dist-cjs/lib/ui/context/events.js.map +2 -2
  135. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js +13 -0
  136. package/dist-cjs/lib/ui/hooks/useKeyboardShortcuts.js.map +2 -2
  137. package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
  138. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  139. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  140. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +2 -0
  141. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  142. package/dist-cjs/lib/ui/version.js +3 -3
  143. package/dist-cjs/lib/ui/version.js.map +1 -1
  144. package/dist-cjs/lib/utils/embeds/embeds.js +4 -4
  145. package/dist-cjs/lib/utils/embeds/embeds.js.map +2 -2
  146. package/dist-cjs/lib/utils/test-helpers.js +2 -2
  147. package/dist-cjs/lib/utils/test-helpers.js.map +2 -2
  148. package/dist-cjs/lib/utils/text/richText.js +3 -1
  149. package/dist-cjs/lib/utils/text/richText.js.map +2 -2
  150. package/dist-esm/index.d.mts +110 -23
  151. package/dist-esm/index.mjs +5 -3
  152. package/dist-esm/index.mjs.map +2 -2
  153. package/dist-esm/lib/TldrawImage.mjs +0 -1
  154. package/dist-esm/lib/TldrawImage.mjs.map +2 -2
  155. package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs +2 -1
  156. package/dist-esm/lib/bindings/arrow/ArrowBindingUtil.mjs.map +2 -2
  157. package/dist-esm/lib/defaultEmbedDefinitions.mjs +3 -2
  158. package/dist-esm/lib/defaultEmbedDefinitions.mjs.map +2 -2
  159. package/dist-esm/lib/defaultOverlayUtils.mjs +11 -11
  160. package/dist-esm/lib/defaultOverlayUtils.mjs.map +2 -2
  161. package/dist-esm/lib/overlays/SelectionForegroundOverlayUtil.mjs +77 -65
  162. package/dist-esm/lib/overlays/SelectionForegroundOverlayUtil.mjs.map +2 -2
  163. package/dist-esm/lib/overlays/ShapeHandleOverlayUtil.mjs +1 -1
  164. package/dist-esm/lib/overlays/ShapeHandleOverlayUtil.mjs.map +2 -2
  165. package/dist-esm/lib/overlays/ShapeIndicatorOverlayUtil.mjs +87 -0
  166. package/dist-esm/lib/overlays/ShapeIndicatorOverlayUtil.mjs.map +7 -0
  167. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +9 -1
  168. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  169. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +15 -3
  170. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  171. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs +54 -6
  172. package/dist-esm/lib/shapes/bookmark/bookmarks.mjs.map +2 -2
  173. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +3 -1
  174. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
  175. package/dist-esm/lib/shapes/draw/getPath.mjs +1 -1
  176. package/dist-esm/lib/shapes/draw/getPath.mjs.map +2 -2
  177. package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs +46 -47
  178. package/dist-esm/lib/shapes/draw/toolStates/Drawing.mjs.map +2 -2
  179. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +2 -1
  180. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +2 -2
  181. package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs +23 -18
  182. package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs.map +2 -2
  183. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +2 -1
  184. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  185. package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs +4 -0
  186. package/dist-esm/lib/shapes/geo/toolStates/Pointing.mjs.map +2 -2
  187. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +12 -7
  188. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
  189. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -11
  190. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
  191. package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs +6 -1
  192. package/dist-esm/lib/shapes/line/toolStates/Pointing.mjs.map +2 -2
  193. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +32 -42
  194. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  195. package/dist-esm/lib/shapes/note/noteHelpers.mjs +1 -1
  196. package/dist-esm/lib/shapes/note/noteHelpers.mjs.map +2 -2
  197. package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs +29 -6
  198. package/dist-esm/lib/shapes/note/toolStates/Pointing.mjs.map +2 -2
  199. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +3 -2
  200. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  201. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs +4 -3
  202. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  203. package/dist-esm/lib/shapes/shared/defaultStyleDefs.mjs +17 -3
  204. package/dist-esm/lib/shapes/shared/defaultStyleDefs.mjs.map +2 -2
  205. package/dist-esm/lib/shapes/shared/freehand/core.mjs +404 -0
  206. package/dist-esm/lib/shapes/shared/freehand/core.mjs.map +7 -0
  207. package/dist-esm/lib/shapes/shared/freehand/fmt.mjs +86 -0
  208. package/dist-esm/lib/shapes/shared/freehand/fmt.mjs.map +7 -0
  209. package/dist-esm/lib/shapes/shared/freehand/getStroke.mjs +7 -7
  210. package/dist-esm/lib/shapes/shared/freehand/getStroke.mjs.map +2 -2
  211. package/dist-esm/lib/shapes/shared/freehand/getStrokeOutlinePoints.mjs +332 -86
  212. package/dist-esm/lib/shapes/shared/freehand/getStrokeOutlinePoints.mjs.map +3 -3
  213. package/dist-esm/lib/shapes/shared/freehand/getStrokePoints.mjs +31 -96
  214. package/dist-esm/lib/shapes/shared/freehand/getStrokePoints.mjs.map +3 -3
  215. package/dist-esm/lib/shapes/shared/freehand/svg.mjs +55 -19
  216. package/dist-esm/lib/shapes/shared/freehand/svg.mjs.map +2 -2
  217. package/dist-esm/lib/shapes/shared/freehand/svgInk.mjs +214 -99
  218. package/dist-esm/lib/shapes/shared/freehand/svgInk.mjs.map +3 -3
  219. package/dist-esm/lib/shapes/shared/interpolate-props.mjs +6 -2
  220. package/dist-esm/lib/shapes/shared/interpolate-props.mjs.map +2 -2
  221. package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs +4 -0
  222. package/dist-esm/lib/shapes/text/toolStates/Pointing.mjs.map +2 -2
  223. package/dist-esm/lib/tools/HandTool/HandTool.mjs +16 -6
  224. package/dist-esm/lib/tools/HandTool/HandTool.mjs.map +2 -2
  225. package/dist-esm/lib/tools/HandTool/childStates/Dragging.mjs +10 -1
  226. package/dist-esm/lib/tools/HandTool/childStates/Dragging.mjs.map +2 -2
  227. package/dist-esm/lib/tools/HandTool/childStates/OneFingerZooming.mjs +64 -0
  228. package/dist-esm/lib/tools/HandTool/childStates/OneFingerZooming.mjs.map +7 -0
  229. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +12 -0
  230. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
  231. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs +4 -0
  232. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs.map +2 -2
  233. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +108 -46
  234. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  235. package/dist-esm/lib/ui/TldrawUi.mjs +4 -3
  236. package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
  237. package/dist-esm/lib/ui/components/A11y.mjs +2 -0
  238. package/dist-esm/lib/ui/components/A11y.mjs.map +2 -2
  239. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs +21 -2
  240. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenu.mjs.map +2 -2
  241. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenuContent.mjs +0 -6
  242. package/dist-esm/lib/ui/components/ContextMenu/DefaultContextMenuContent.mjs.map +2 -2
  243. package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +2 -2
  244. package/dist-esm/lib/ui/components/Dialogs.mjs +19 -39
  245. package/dist-esm/lib/ui/components/Dialogs.mjs.map +2 -2
  246. package/dist-esm/lib/ui/components/HelperButtons/BackToContent.mjs +20 -5
  247. package/dist-esm/lib/ui/components/HelperButtons/BackToContent.mjs.map +2 -2
  248. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +12 -2
  249. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +2 -2
  250. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +47 -70
  251. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
  252. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +25 -46
  253. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
  254. package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuAvatar.mjs.map +2 -2
  255. package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuContent.mjs.map +2 -2
  256. package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuFacePile.mjs.map +2 -2
  257. package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuItem.mjs +1 -1
  258. package/dist-esm/lib/ui/components/SharePanel/DefaultPeopleMenuItem.mjs.map +2 -2
  259. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +1 -0
  260. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +2 -2
  261. package/dist-esm/lib/ui/components/menu-items.mjs +7 -0
  262. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  263. package/dist-esm/lib/ui/components/primitives/TldrawUiDropdownMenu.mjs +2 -1
  264. package/dist-esm/lib/ui/components/primitives/TldrawUiDropdownMenu.mjs.map +2 -2
  265. package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs +14 -3
  266. package/dist-esm/lib/ui/components/primitives/TldrawUiIcon.mjs.map +2 -2
  267. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs +2 -0
  268. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs.map +2 -2
  269. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs +2 -0
  270. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs.map +2 -2
  271. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs +0 -2
  272. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs.map +2 -2
  273. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.mjs +1 -2
  274. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.mjs.map +2 -2
  275. package/dist-esm/lib/ui/context/actions.mjs +71 -1
  276. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  277. package/dist-esm/lib/ui/context/asset-urls.mjs +5 -8
  278. package/dist-esm/lib/ui/context/asset-urls.mjs.map +2 -2
  279. package/dist-esm/lib/ui/context/events.mjs.map +2 -2
  280. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs +13 -0
  281. package/dist-esm/lib/ui/hooks/useKeyboardShortcuts.mjs.map +2 -2
  282. package/dist-esm/lib/ui/hooks/useTools.mjs +1 -1
  283. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  284. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +2 -0
  285. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  286. package/dist-esm/lib/ui/version.mjs +3 -3
  287. package/dist-esm/lib/ui/version.mjs.map +1 -1
  288. package/dist-esm/lib/utils/embeds/embeds.mjs +4 -4
  289. package/dist-esm/lib/utils/embeds/embeds.mjs.map +2 -2
  290. package/dist-esm/lib/utils/test-helpers.mjs +2 -2
  291. package/dist-esm/lib/utils/test-helpers.mjs.map +2 -2
  292. package/dist-esm/lib/utils/text/richText.mjs +3 -1
  293. package/dist-esm/lib/utils/text/richText.mjs.map +2 -2
  294. package/package.json +11 -6
  295. package/src/index.ts +6 -1
  296. package/src/lib/TldrawImage.tsx +2 -2
  297. package/src/lib/bindings/arrow/ArrowBindingUtil.ts +5 -1
  298. package/src/lib/defaultEmbedDefinitions.ts +28 -6
  299. package/src/lib/defaultOverlayUtils.ts +11 -11
  300. package/src/lib/overlays/SelectionForegroundOverlayUtil.ts +91 -72
  301. package/src/lib/overlays/ShapeHandleOverlayUtil.ts +3 -1
  302. package/src/lib/overlays/ShapeIndicatorOverlayUtil.ts +133 -0
  303. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +11 -1
  304. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +16 -3
  305. package/src/lib/shapes/bookmark/bookmarks.ts +105 -15
  306. package/src/lib/shapes/draw/DrawShapeUtil.tsx +7 -5
  307. package/src/lib/shapes/draw/getPath.ts +1 -1
  308. package/src/lib/shapes/draw/toolStates/Drawing.ts +55 -48
  309. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +14 -4
  310. package/src/lib/shapes/frame/FrameShapeTool.ts +35 -24
  311. package/src/lib/shapes/geo/GeoShapeUtil.test.tsx +46 -0
  312. package/src/lib/shapes/geo/GeoShapeUtil.tsx +2 -1
  313. package/src/lib/shapes/geo/toolStates/Pointing.ts +5 -0
  314. package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +14 -11
  315. package/src/lib/shapes/image/ImageShapeUtil.tsx +7 -11
  316. package/src/lib/shapes/line/LineShapeTool.test.ts +41 -0
  317. package/src/lib/shapes/line/toolStates/Pointing.ts +12 -2
  318. package/src/lib/shapes/note/NoteShapeUtil.tsx +36 -51
  319. package/src/lib/shapes/note/noteCloning.test.ts +5 -5
  320. package/src/lib/shapes/note/noteHelpers.ts +1 -1
  321. package/src/lib/shapes/note/toolStates/Pointing.ts +40 -7
  322. package/src/lib/shapes/shared/PlainTextLabel.tsx +3 -3
  323. package/src/lib/shapes/shared/RichTextLabel.tsx +4 -3
  324. package/src/lib/shapes/shared/defaultStyleDefs.tsx +25 -3
  325. package/src/lib/shapes/shared/freehand/core.ts +547 -0
  326. package/src/lib/shapes/shared/freehand/fmt.ts +106 -0
  327. package/src/lib/shapes/shared/freehand/getStroke.ts +7 -7
  328. package/src/lib/shapes/shared/freehand/getStrokeOutlinePoints.ts +451 -139
  329. package/src/lib/shapes/shared/freehand/getStrokePoints.ts +33 -153
  330. package/src/lib/shapes/shared/freehand/svg.ts +72 -23
  331. package/src/lib/shapes/shared/freehand/svgInk.ts +281 -136
  332. package/src/lib/shapes/shared/freehand/types.ts +0 -1
  333. package/src/lib/shapes/shared/interpolate-props.ts +6 -2
  334. package/src/lib/shapes/text/toolStates/Pointing.ts +5 -0
  335. package/src/lib/tools/HandTool/HandTool.ts +19 -6
  336. package/src/lib/tools/HandTool/childStates/Dragging.ts +17 -1
  337. package/src/lib/tools/HandTool/childStates/OneFingerZooming.ts +79 -0
  338. package/src/lib/tools/SelectTool/childStates/Idle.ts +16 -2
  339. package/src/lib/tools/SelectTool/childStates/PointingShape.ts +8 -0
  340. package/src/lib/tools/SelectTool/childStates/Resizing.ts +137 -49
  341. package/src/lib/ui/TldrawUi.tsx +3 -3
  342. package/src/lib/ui/components/A11y.tsx +2 -0
  343. package/src/lib/ui/components/ContextMenu/DefaultContextMenu.tsx +32 -2
  344. package/src/lib/ui/components/ContextMenu/DefaultContextMenuContent.tsx +5 -6
  345. package/src/lib/ui/components/DefaultFollowingIndicator.tsx +2 -2
  346. package/src/lib/ui/components/Dialogs.tsx +20 -23
  347. package/src/lib/ui/components/HelperButtons/BackToContent.tsx +32 -4
  348. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +10 -0
  349. package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +60 -74
  350. package/src/lib/ui/components/Minimap/MinimapManager.ts +35 -57
  351. package/src/lib/ui/components/SharePanel/DefaultPeopleMenuAvatar.tsx +2 -2
  352. package/src/lib/ui/components/SharePanel/DefaultPeopleMenuContent.tsx +2 -1
  353. package/src/lib/ui/components/SharePanel/DefaultPeopleMenuFacePile.tsx +2 -1
  354. package/src/lib/ui/components/SharePanel/DefaultPeopleMenuItem.tsx +3 -3
  355. package/src/lib/ui/components/StylePanel/StylePanelButtonPicker.tsx +5 -0
  356. package/src/lib/ui/components/menu-items.tsx +9 -0
  357. package/src/lib/ui/components/primitives/TldrawUiDropdownMenu.tsx +3 -1
  358. package/src/lib/ui/components/primitives/TldrawUiIcon.tsx +15 -3
  359. package/src/lib/ui/components/primitives/TldrawUiInput.tsx +4 -0
  360. package/src/lib/ui/components/primitives/TldrawUiPopover.tsx +7 -0
  361. package/src/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.tsx +0 -2
  362. package/src/lib/ui/components/primitives/menus/TldrawUiMenuSubmenu.tsx +0 -1
  363. package/src/lib/ui/context/actions.tsx +88 -1
  364. package/src/lib/ui/context/asset-urls.tsx +9 -8
  365. package/src/lib/ui/context/events.tsx +2 -0
  366. package/src/lib/ui/hooks/useKeyboardShortcuts.ts +45 -7
  367. package/src/lib/ui/hooks/useTools.tsx +7 -1
  368. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +2 -0
  369. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +2 -0
  370. package/src/lib/ui/version.ts +3 -3
  371. package/src/lib/ui.css +20 -9
  372. package/src/lib/utils/embeds/embeds.test.ts +14 -12
  373. package/src/lib/utils/embeds/embeds.ts +10 -4
  374. package/src/lib/utils/test-helpers.ts +3 -3
  375. package/src/lib/utils/text/richText.test.ts +36 -0
  376. package/src/lib/utils/text/richText.ts +9 -1
  377. package/src/test/HandTool.test.ts +93 -0
  378. package/src/test/ImageShapeUtil.test.ts +88 -0
  379. package/src/test/SelectTool.test.ts +102 -1
  380. package/src/test/__snapshots__/drawing.test.ts.snap +2 -1
  381. package/src/test/attribution.test.ts +40 -29
  382. package/src/test/bookmark-shapes.test.ts +256 -28
  383. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +2 -2
  384. package/src/test/commands/clipboardCallbacks.test.ts +3 -1
  385. package/src/test/commands/getSvgString.test.ts +30 -0
  386. package/src/test/commands/penmode.test.ts +97 -1
  387. package/src/test/commands/setCamera.test.ts +12 -0
  388. package/src/test/dragFromToolbar.test.ts +67 -0
  389. package/src/test/drawing.test.ts +48 -7
  390. package/src/test/frames.test.ts +72 -0
  391. package/src/test/freehand/corpus/presets.ts +71 -0
  392. package/src/test/freehand/corpus/real.ts +370 -0
  393. package/src/test/freehand/corpus/strokes.ts +50 -0
  394. package/src/test/freehand/svg.test.ts +20 -0
  395. package/src/test/freehand/wellformed.test.ts +30 -0
  396. package/src/test/long-press-create.test.ts +102 -0
  397. package/src/test/overlays/CollaboratorBrushOverlayUtil.test.ts +4 -4
  398. package/src/test/overlays/CollaboratorCursorOverlayUtil.test.ts +18 -18
  399. package/src/test/overlays/CollaboratorHintOverlayUtil.test.ts +7 -7
  400. package/src/test/overlays/CollaboratorScribbleOverlayUtil.test.ts +3 -3
  401. package/src/test/overlays/OverlayManager.test.ts +1 -1
  402. package/src/test/overlays/SelectionForegroundOverlayUtil.test.ts +58 -0
  403. package/src/test/overlays/ShapeHandleOverlayUtil.test.ts +2 -2
  404. package/src/test/overlays/ShapeIndicatorOverlayUtil.test.ts +36 -0
  405. package/src/test/resizing.test.ts +250 -0
  406. package/src/test/right-click-context-menu.test.ts +90 -0
  407. package/src/test/rightClickPanning.test.ts +11 -0
  408. package/src/test/selection-omnibus.test.ts +15 -2
  409. package/src/test/spatialIndex.test.ts +132 -0
  410. package/src/test/translating.test.ts +0 -6
  411. package/src/test/ui/ContextMenu.test.tsx +146 -3
  412. package/src/test/ui/Dialogs.test.tsx +256 -0
  413. package/src/test/ui/copyHoveredStyles.test.tsx +154 -0
  414. package/src/test/ui/keyboardShortcuts.test.tsx +266 -0
  415. package/tldraw.css +35 -12
  416. package/dist-cjs/lib/shapes/shared/freehand/setStrokePointRadii.js +0 -100
  417. package/dist-cjs/lib/shapes/shared/freehand/setStrokePointRadii.js.map +0 -7
  418. package/dist-esm/lib/shapes/shared/freehand/setStrokePointRadii.mjs +0 -80
  419. package/dist-esm/lib/shapes/shared/freehand/setStrokePointRadii.mjs.map +0 -7
  420. package/src/lib/shapes/shared/freehand/setStrokePointRadii.ts +0 -127
@@ -0,0 +1,2908 @@
1
+ # Releases
2
+
3
+ Version: `5.2.0`
4
+
5
+ This file is generated during package publishing from the tldraw release notes content for this exact package version.
6
+
7
+ ## v5.2.0
8
+
9
+ This release simplifies multi-click handling down to a single double-click event — a breaking change for anyone relying on triple- or quadruple-click handlers — and adds per-embed configuration for API keys, a `shift+q` shortcut for copying styles between shapes, and full-speed sync across your own tabs and devices. It also fixes a number of canvas interaction bugs around pinch-zoom selection, pasting mid-gesture, note list editing, and zoom clamping.
10
+
11
+ ### API changes
12
+
13
+ - 💥 Simplify multi-click handling to double-click only. `ClickManager` no longer tracks triple or quadruple clicks: the `triple_click` and `quadruple_click` events and the `onTripleClick` / `onQuadrupleClick` handlers have been removed, and `TLClickEventName` is now just `'double_click'`. ([#8897](https://github.com/tldraw/tldraw/pull/8897))
14
+ - 💥 Move `ShapeIndicatorOverlayUtil` and `TLShapeIndicatorOverlay` from `@tldraw/editor` to `tldraw`. Both are still exported from `tldraw`; update any imports of these symbols that came directly from `@tldraw/editor`. ([#9018](https://github.com/tldraw/tldraw/pull/9018))
15
+ - Add an `embedConfig` option to `EmbedShapeUtil` for passing per-embed configuration such as API keys. The default Google Maps embed no longer reads `process.env.NEXT_PUBLIC_GC_API_KEY` — pass the key explicitly instead. ([#9068](https://github.com/tldraw/tldraw/pull/9068))
16
+
17
+ ```ts
18
+ EmbedShapeUtil.configure({
19
+ embedConfig: { google_maps: { apiKey: '...' } },
20
+ })
21
+ ```
22
+
23
+ ### Improvements
24
+
25
+ - Add a `shift+q` shortcut that copies the styles of the hovered shape and applies them to the next shapes you create. ([#9028](https://github.com/tldraw/tldraw/pull/9028))
26
+ - Keep sync at full speed when the same multiplayer room is open in multiple tabs, windows, or devices — previously a room with no other users throttled network sync to once per second. ([#8988](https://github.com/tldraw/tldraw/pull/8988))
27
+ - Include `DOCS.md` documentation in published npm packages, and a generated docs and release notes rollup in the `tldraw` package, so documentation is available when browsing package artifacts. ([#8503](https://github.com/tldraw/tldraw/pull/8503))
28
+
29
+ ### Bug fixes
30
+
31
+ - Fix the fill style dropdown trigger showing a misleading tooltip for the currently selected fill. ([#9023](https://github.com/tldraw/tldraw/pull/9023))
32
+ - Fix a two-finger pinch unintentionally changing the selection on touch devices. ([#9006](https://github.com/tldraw/tldraw/pull/9006))
33
+ - Pasting content while dragging, translating, resizing, or rotating no longer steals selection from the shape being manipulated. ([#8976](https://github.com/tldraw/tldraw/pull/8976))
34
+ - Fix a bug where pressing `Tab` while editing a list inside a note shape created a new note instead of indenting the list item. ([#8958](https://github.com/tldraw/tldraw/pull/8958))
35
+ - Fix the viewport shifting slightly when zooming past the minimum or maximum zoom level. ([#8957](https://github.com/tldraw/tldraw/pull/8957))
36
+ - Improve the contrast of disabled buttons and menu items in dark mode. ([#8931](https://github.com/tldraw/tldraw/pull/8931))
37
+ - Fix `debounce(...).cancel()` leaving an awaited call hanging forever; it now rejects the pending promise. ([#8683](https://github.com/tldraw/tldraw/pull/8683))
38
+
39
+ ## v5.1.0
40
+
41
+ [View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v5.1.0)
42
+
43
+ This release redesigns the page menu around inline interaction, adds a keyboard shortcut to copy styles from a hovered shape, and adds a `selectLockedShapes` option for inspecting locked shapes, along with new public translation APIs, canvas performance improvements, and various rendering and UI bug fixes.
44
+
45
+ ### What's new
46
+
47
+ #### Page menu redesign ([#8836](https://github.com/tldraw/tldraw/pull/8836))
48
+
49
+ The page menu no longer has an explicit edit mode. Reorder pages by dragging a row directly, rename inline by double-clicking the label or pressing Enter, and drag the new resize handle at the bottom of the popover to adjust the list height — the height is persisted across sessions and a double-click on the handle resets it to the default. The current page is now indicated by a subtle background pill, the row submenu trigger reveals on hover, and the "Create new page" button is pinned to the footer of the popover.
50
+
51
+ ### API changes
52
+
53
+ - Add a `selectLockedShapes` option to `TldrawOptions`. When enabled, locked shapes can be selected by left click or by brush/scribble selection while remaining protected from edits, moves, and deletes. ([#8860](https://github.com/tldraw/tldraw/pull/8860))
54
+ - Export `TldrawUiTranslationProvider`, `AssetUrlsProvider`, and `useAssetUrls` as public API so components like `TldrawSelectionForeground` can be rendered without the full `TldrawUiContextProvider`. ([#8909](https://github.com/tldraw/tldraw/pull/8909))
55
+ - Add `FontManager.dispose()`, `OverlayManager.dispose()`, and `OverlayUtil.dispose()` for cleaning up manager state across editor lifecycles. ([#8896](https://github.com/tldraw/tldraw/pull/8896))
56
+
57
+ ### Improvements
58
+
59
+ - Improve performance on busy canvases — `getRenderingShapes()` now skips its sort step when only shape props, not the set of shape ids, have changed. ([#8784](https://github.com/tldraw/tldraw/pull/8784))
60
+ - Improve drawing performance on pages with many shapes by skipping spatial index and culling recomputation when only shape props change. ([#8799](https://github.com/tldraw/tldraw/pull/8799), [#8804](https://github.com/tldraw/tldraw/pull/8804))
61
+
62
+ ### Bug fixes
63
+
64
+ - Fix a misleading "license expired" console warning for perpetual licenses on covered versions. ([#8791](https://github.com/tldraw/tldraw/pull/8791))
65
+ - Fix inconsistent tooltip behavior on the video toolbar by using `TldrawUiToolbarButton` for the replace and download buttons. ([#8794](https://github.com/tldraw/tldraw/pull/8794))
66
+ - Fix the missing open-state hint on the page menu and zoom menu triggers when rendered outside the main toolbar. ([#8813](https://github.com/tldraw/tldraw/pull/8813))
67
+ - Mark the tldraw UI layer with `role="document"` so toolbars, menus, and dialogs stay reachable to mobile screen readers like VoiceOver and TalkBack, which do not announce the outer canvas `role="application"`. ([#8901](https://github.com/tldraw/tldraw/pull/8901))
68
+ - Fix selection edge resize handles overlapping corner handles, which made corners hard to grab on small shapes. ([#8926](https://github.com/tldraw/tldraw/pull/8926))
69
+ - Fix a bug where deleting a shape inside a group could move the group to a different z-index. ([#8925](https://github.com/tldraw/tldraw/pull/8925))
70
+ - Avoid console errors from calling `preventDefault` on non-cancelable events. ([#8910](https://github.com/tldraw/tldraw/pull/8910))
71
+ - Only log the missing-translation warning once per session instead of once per `useTranslation` consumer. ([#8909](https://github.com/tldraw/tldraw/pull/8909))
72
+ - Catch `image.decode()` rejections from the icon preload effect so they no longer surface as uncaught promise errors in the console. ([#8824](https://github.com/tldraw/tldraw/pull/8824))
73
+
74
+ ## v5.0.0
75
+
76
+ This major release introduces a first-class theme system with display values, a new `OverlayUtil` system for canvas overlays, and 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.
77
+
78
+ ### What's new
79
+
80
+ #### 💥 Custom themes with display values ([#8410](https://github.com/tldraw/tldraw/pull/8410))
81
+
82
+ 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.
83
+
84
+ 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:
85
+
86
+ ```tsx
87
+ <Tldraw themes={{ corporate: myCorporateTheme }} initialTheme="corporate" />
88
+ ```
89
+
90
+ 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`:
91
+
92
+ ```tsx
93
+ const MyDrawShapeUtil = DrawShapeUtil.configure({
94
+ getCustomDisplayValues(_editor, _shape, _theme, _colorMode) {
95
+ return { strokeWidth: 10 }
96
+ },
97
+ })
98
+ ```
99
+
100
+ <details>
101
+ <summary>Migration guide</summary>
102
+
103
+ The `inferDarkMode` prop has been renamed to `colorScheme` and changed from `boolean` to `'light' | 'dark' | 'system'`:
104
+
105
+ ```tsx
106
+ // Before
107
+ <Tldraw inferDarkMode />
108
+
109
+ // After
110
+ <Tldraw colorScheme="system" />
111
+ ```
112
+
113
+ `useIsDarkMode()` has been renamed to `useColorMode()` and returns `'dark' | 'light'` instead of `boolean`.
114
+
115
+ `getDefaultColorTheme()` and `DefaultColorThemePalette` have been removed. Use `editor.getCurrentTheme().colors[colorMode]` instead:
116
+
117
+ ```tsx
118
+ // Before
119
+ const theme = getDefaultColorTheme({ isDarkMode })
120
+
121
+ // After
122
+ const theme = editor.getCurrentTheme()
123
+ const colors = theme.colors[editor.getColorMode()]
124
+ ```
125
+
126
+ `useDefaultColorTheme()` has been removed. Use `editor.getCurrentTheme()` and `useColorMode()` instead.
127
+
128
+ `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.
129
+
130
+ `SvgExportContext.themeId` has been renamed to `SvgExportContext.colorMode` and changed from `string` to `'light' | 'dark'`.
131
+
132
+ `getColorValue()` now takes `TLThemeColors` as its first argument instead of `TLDefaultColorTheme`.
133
+
134
+ </details>
135
+
136
+ #### 💥 Custom overlays ([#8469](https://github.com/tldraw/tldraw/pull/8469))
137
+
138
+ 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.
139
+
140
+ Overlays now render in front of indicators in a unified `CanvasOverlays` layer, and the legacy default component implementations and their CSS have been removed.
141
+
142
+ <details>
143
+ <summary>Migration guide</summary>
144
+
145
+ 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.
146
+
147
+ **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`:
148
+
149
+ ```tsx
150
+ // Before
151
+ const components: TLEditorComponents = {
152
+ Brush: MyBrushComponent,
153
+ }
154
+
155
+ <Tldraw components={components} />
156
+
157
+ // After
158
+ import { Tldraw, BrushOverlayUtil, type TLBrushOverlay } from 'tldraw'
159
+
160
+ class MyBrushOverlayUtil extends BrushOverlayUtil {
161
+ override render(ctx: CanvasRenderingContext2D, overlays: TLBrushOverlay[]) {
162
+ const overlay = overlays[0]
163
+ if (!overlay) return
164
+ const { x, y, w, h } = overlay.props
165
+ const zoom = this.editor.getEfficientZoomLevel()
166
+ ctx.fillStyle = 'rgba(0, 0, 255, 0.1)'
167
+ ctx.strokeStyle = 'blue'
168
+ ctx.lineWidth = 1 / zoom
169
+ ctx.beginPath()
170
+ ctx.rect(x, y, w, h)
171
+ ctx.fill()
172
+ ctx.stroke()
173
+ }
174
+ }
175
+
176
+ <Tldraw overlayUtils={[MyBrushOverlayUtil]} />
177
+ ```
178
+
179
+ The following slots have been removed from `TLEditorComponents`. Subclass the matching default overlay util instead:
180
+
181
+ - `Brush`, `ZoomBrush` → `BrushOverlayUtil`, `ZoomBrushOverlayUtil`
182
+ - `Scribble` → `ScribbleOverlayUtil`
183
+ - `SnapIndicator` → `SnapIndicatorOverlayUtil`
184
+ - `Handle`, `Handles` → `ShapeHandleOverlayUtil`
185
+ - `SelectionForeground`, `SelectionBackground` → `SelectionForegroundOverlayUtil`
186
+ - `CollaboratorHint` → `CollaboratorHintOverlayUtil` (collaborator cursors/brushes/scribbles have their own utils too)
187
+
188
+ The corresponding `Default*` exports and `LiveCollaborators` have also been removed.
189
+
190
+ **`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:
191
+
192
+ ```tsx
193
+ // Before
194
+ override indicator(shape: MyShape) {
195
+ return <rect width={shape.props.w} height={shape.props.h} />
196
+ }
197
+
198
+ // After
199
+ override getIndicatorPath(shape: MyShape): Path2D {
200
+ const path = new Path2D()
201
+ path.rect(0, 0, shape.props.w, shape.props.h)
202
+ return path
203
+ }
204
+ ```
205
+
206
+ 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`.
207
+
208
+ 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()`.
209
+
210
+ 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`.
211
+
212
+ 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.
213
+
214
+ These CSS variables have been removed: `--tl-color-snap`, `--tl-color-brush-fill`, `--tl-color-brush-stroke`, `--tl-color-laser`, `--tl-layer-overlays-custom`.
215
+
216
+ 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()`.
217
+
218
+ </details>
219
+
220
+ #### 💥 Tldraw component options
221
+
222
+ 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.
223
+
224
+ <details>
225
+ <summary>Migration guide</summary>
226
+
227
+ **`cameraOptions`, `textOptions`, and `deepLinks` props moved into `options`:**
228
+
229
+ ```tsx
230
+ // Before
231
+ <Tldraw cameraOptions={camOpts} textOptions={txtOpts} deepLinks />
232
+
233
+ // After
234
+ <Tldraw options={{ camera: camOpts, text: txtOpts, deepLinks: true }} />
235
+ ```
236
+
237
+ **`embeds` prop removed; configure embed definitions on `EmbedShapeUtil`:**
238
+
239
+ ```tsx
240
+ // Before
241
+ <Tldraw embeds={[...DEFAULT_EMBED_DEFINITIONS, customEmbed]} />
242
+
243
+ // After
244
+ import { EmbedShapeUtil } from 'tldraw'
245
+ const ConfiguredEmbedShapeUtil = EmbedShapeUtil.configure({
246
+ embedDefinitions: [...DEFAULT_EMBED_DEFINITIONS, customEmbed],
247
+ })
248
+ <Tldraw shapeUtils={[ConfiguredEmbedShapeUtil]} />
249
+ ```
250
+
251
+ 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.
252
+
253
+ **`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:
254
+
255
+ ```tsx
256
+ // Before
257
+ import { setDefaultEditorAssetUrls, setDefaultUiAssetUrls } from 'tldraw'
258
+ setDefaultEditorAssetUrls(assetUrls)
259
+ setDefaultUiAssetUrls(assetUrls)
260
+
261
+ <Tldraw />
262
+
263
+ // After
264
+ <Tldraw assetUrls={assetUrls} />
265
+ ```
266
+
267
+ Do not reach for module augmentation to re-expose the old globals — find each `<Tldraw>` mount point and pass `assetUrls` directly.
268
+
269
+ </details>
270
+
271
+ #### Custom record types ([#8213](https://github.com/tldraw/tldraw/pull/8213))
272
+
273
+ 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.
274
+
275
+ ```tsx
276
+ import { createTLSchema, createCustomRecordId } from 'tldraw'
277
+
278
+ const schema = createTLSchema({
279
+ records: [
280
+ {
281
+ typeName: 'marker',
282
+ scope: 'document',
283
+ validator: markerValidator,
284
+ },
285
+ ],
286
+ })
287
+ ```
288
+
289
+ TypeScript module augmentation via `TLGlobalRecordPropsMap` lets custom record types participate in the `TLRecord` union.
290
+
291
+ #### Extensible geo shapes ([#8543](https://github.com/tldraw/tldraw/pull/8543))
292
+
293
+ `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.
294
+
295
+ ```tsx
296
+ import { GeoShapeUtil, PathBuilder } from 'tldraw'
297
+
298
+ const MyGeoShapeUtil = GeoShapeUtil.configure({
299
+ customGeoTypes: {
300
+ 'rounded-rect': {
301
+ getPath: (w, h, shape) => {
302
+ const r = Math.min(w, h) * 0.2
303
+ return new PathBuilder()
304
+ .moveTo(r, 0, { geometry: { isFilled: shape.props.fill !== 'none' } })
305
+ .lineTo(w - r, 0)
306
+ .circularArcTo(r, false, true, w, r)
307
+ .lineTo(w, h - r)
308
+ .circularArcTo(r, false, true, w - r, h)
309
+ .lineTo(r, h)
310
+ .circularArcTo(r, false, true, 0, h - r)
311
+ .lineTo(0, r)
312
+ .circularArcTo(r, false, true, r, 0)
313
+ .close()
314
+ },
315
+ snapType: 'polygon',
316
+ icon: 'geo-rectangle',
317
+ defaultSize: { w: 200, h: 150 },
318
+ },
319
+ },
320
+ })
321
+
322
+ <Tldraw shapeUtils={[MyGeoShapeUtil]} />
323
+ ```
324
+
325
+ 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.
326
+
327
+ #### 💥 Extensible asset types ([#8031](https://github.com/tldraw/tldraw/pull/8031))
328
+
329
+ 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.
330
+
331
+ ```tsx
332
+ import { AssetUtil } from '@tldraw/editor'
333
+
334
+ class AudioAssetUtil extends AssetUtil<TLAudioAsset> {
335
+ static override type = 'audio' as const
336
+ override getSupportedMimeTypes() {
337
+ return ['audio/mpeg', 'audio/wav']
338
+ }
339
+ override async getAssetFromFile(editor, file) {
340
+ /* ... */
341
+ }
342
+ }
343
+
344
+ ;<Tldraw assetUtils={[AudioAssetUtil]} />
345
+ ```
346
+
347
+ `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.
348
+
349
+ <details>
350
+ <summary>Migration guide</summary>
351
+
352
+ `assetValidator` has been removed. Use `imageAssetValidator`, `videoAssetValidator`, or `bookmarkAssetValidator` instead.
353
+
354
+ `getMediaAssetInfoPartial` has been removed. Use `AssetUtil.getAssetFromFile` instead.
355
+
356
+ `notifyIfFileNotAllowed` signature changed from `(file, options)` to `(editor, file, options)`.
357
+
358
+ `getAssetInfo` signature changed from `(file, options, assetId?)` to `(editor, file, assetId?)` and now returns `TLAsset | null` instead of throwing.
359
+
360
+ </details>
361
+
362
+ #### Frame-like custom shapes ([#8331](https://github.com/tldraw/tldraw/pull/8331))
363
+
364
+ 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)`.
365
+
366
+ 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`:
367
+
368
+ ```tsx
369
+ import { BaseFrameLikeShapeUtil, SVGContainer } from '@tldraw/editor'
370
+
371
+ class MyContainerUtil extends BaseFrameLikeShapeUtil<MyContainerShape> {
372
+ static override type = 'my-container' as const
373
+ static override props = myContainerShapeProps
374
+
375
+ override getDefaultProps() {
376
+ return { w: 300, h: 200 }
377
+ }
378
+
379
+ override component(shape: MyContainerShape) {
380
+ return <SVGContainer>...</SVGContainer>
381
+ }
382
+
383
+ override indicator(shape: MyContainerShape) {
384
+ return <rect width={shape.props.w} height={shape.props.h} />
385
+ }
386
+ }
387
+ ```
388
+
389
+ 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.
390
+
391
+ #### Shape attribution and TLUserStore ([#8147](https://github.com/tldraw/tldraw/pull/8147))
392
+
393
+ 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.
394
+
395
+ ```tsx
396
+ <Tldraw
397
+ users={{
398
+ getCurrentUser: () => currentUserSignal,
399
+ resolve: (userId) => resolvedUserSignal(userId),
400
+ }}
401
+ />
402
+ ```
403
+
404
+ User records are now document-scoped via the unified `TLUser` record type. SDK users can extend user records with custom validated metadata through `createTLSchema`:
405
+
406
+ ```tsx
407
+ const schema = createTLSchema({
408
+ user: {
409
+ meta: {
410
+ isAdmin: T.boolean,
411
+ department: T.string,
412
+ },
413
+ },
414
+ })
415
+ ```
416
+
417
+ 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.
418
+
419
+ <details>
420
+ <summary>Migration guide</summary>
421
+
422
+ **`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:
423
+
424
+ - **Preferences** (color, color scheme, snap mode, etc.) are managed via `TLUserPreferences`. Set them with the editor's user-preferences API directly.
425
+ - **Identity** for attribution comes from a `TLUserStore` provider passed to the new `users` prop on `<Tldraw>`.
426
+
427
+ ```tsx
428
+ // Before
429
+ const user = useTldrawUser({ userPreferences, setUserPreferences })
430
+ <Tldraw user={user} />
431
+
432
+ // After
433
+ <Tldraw
434
+ users={{
435
+ getCurrentUser: () => currentUserSignal,
436
+ resolve: (userId) => resolvedUserSignal(userId),
437
+ }}
438
+ colorScheme={userPreferences.colorScheme}
439
+ />
440
+ ```
441
+
442
+ 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.
443
+
444
+ </details>
445
+
446
+ #### @tldraw/driver ([#7952](https://github.com/tldraw/tldraw/pull/7952))
447
+
448
+ 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.
449
+
450
+ ```tsx
451
+ import { Driver } from '@tldraw/driver'
452
+
453
+ const driver = new Driver(editor)
454
+ driver.pointerMove(100, 100).pointerDown().pointerMove(200, 200).pointerUp()
455
+ ```
456
+
457
+ This is useful for scripting, automation, agent workflows, and REPL-style interaction. The release includes a Scripter example that demonstrates the package.
458
+
459
+ #### @tldraw/mermaid ([#8194](https://github.com/tldraw/tldraw/pull/8194), [#8285](https://github.com/tldraw/tldraw/pull/8285), [#8322](https://github.com/tldraw/tldraw/pull/8322))
460
+
461
+ 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.
462
+
463
+ ```tsx
464
+ import { createMermaidDiagram } from '@tldraw/mermaid'
465
+
466
+ await createMermaidDiagram(
467
+ editor,
468
+ `
469
+ graph TD
470
+ A[Start] --> B{Decision}
471
+ B -->|Yes| C[Action]
472
+ B -->|No| D[End]
473
+ `
474
+ )
475
+ ```
476
+
477
+ 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.
478
+
479
+ 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.
480
+
481
+ #### Arbitrary iframe embeds ([#8306](https://github.com/tldraw/tldraw/pull/8306))
482
+
483
+ 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.
484
+
485
+ #### Clipboard hooks ([#8290](https://github.com/tldraw/tldraw/pull/8290))
486
+
487
+ 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.
488
+
489
+ ```tsx
490
+ const options: Partial<TldrawOptions> = {
491
+ onBeforeCopyToClipboard(info, content) {
492
+ // filter shapes or transform content before copy/cut
493
+ return content
494
+ },
495
+ onBeforePasteFromClipboard(info, content) {
496
+ // filter or transform parsed paste content
497
+ return content
498
+ },
499
+ onClipboardPasteRaw(info) {
500
+ // handle raw clipboard data yourself; return false to cancel tldraw handling
501
+ return false
502
+ },
503
+ }
504
+ ```
505
+
506
+ #### Cross-window embedding support ([#8196](https://github.com/tldraw/tldraw/pull/8196))
507
+
508
+ 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.
509
+
510
+ New helpers `getOwnerDocument()` and `getOwnerWindow()` are exported from `@tldraw/editor`, along with `Editor.getContainerDocument()` and `Editor.getContainerWindow()` convenience methods.
511
+
512
+ #### Performance measurement hooks ([#8421](https://github.com/tldraw/tldraw/pull/8421))
513
+
514
+ 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.
515
+
516
+ ```tsx
517
+ const unsubscribe = editor.performance.on('interaction-end', (event) => {
518
+ // forward to analytics
519
+ const { frameTimes, longAnimationFrames, ...metrics } = event
520
+ track('editor.interaction', metrics)
521
+ })
522
+ ```
523
+
524
+ 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.
525
+
526
+ #### RTL support ([#8033](https://github.com/tldraw/tldraw/pull/8033))
527
+
528
+ 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.
529
+
530
+ #### WebSocket hibernation in tlsync ([#8070](https://github.com/tldraw/tldraw/pull/8070))
531
+
532
+ `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.
533
+
534
+ New APIs include `handleSocketResume()` for restoring sessions from snapshots, `getSessionSnapshot()` for capturing session state, and an `onSessionSnapshot` callback for persisting snapshots to WebSocket attachments.
535
+
536
+ ### API changes
537
+
538
+ - 💥 Remove `defaultColorNames`, `DefaultColorThemePalette`, `DefaultLabelColorStyle`, `TLDefaultColorTheme` type, and `getDefaultColorTheme()` from `@tldraw/tlschema`. Use `editor.getCurrentTheme().colors` instead. ([#8410](https://github.com/tldraw/tldraw/pull/8410))
539
+ - 💥 Remove `ARROW_LABEL_FONT_SIZES`, `FONT_FAMILIES`, `FONT_SIZES`, `LABEL_FONT_SIZES`, `STROKE_SIZES`, `TEXT_PROPS`, and `useDefaultColorTheme()` from `@tldraw/tldraw`. These are now resolved via display values. ([#8410](https://github.com/tldraw/tldraw/pull/8410))
540
+ - 💥 Rename `inferDarkMode` prop to `colorScheme` (`boolean` → `'light' | 'dark' | 'system'`). Rename `useIsDarkMode()` to `useColorMode()` (returns `'dark' | 'light'` instead of `boolean`). ([#8410](https://github.com/tldraw/tldraw/pull/8410))
541
+ - 💥 Rename `SvgExportContext.themeId` to `SvgExportContext.colorMode` (`string` → `'light' | 'dark'`). ([#8410](https://github.com/tldraw/tldraw/pull/8410))
542
+ - 💥 Change `getColorValue()` first argument from `TLDefaultColorTheme` to `TLThemeColors`. ([#8410](https://github.com/tldraw/tldraw/pull/8410))
543
+ - 💥 Change `PlainTextLabelProps` and `RichTextLabelProps`: `font` → `fontFamily`, `align` → `textAlign`, `fill` removed. ([#8410](https://github.com/tldraw/tldraw/pull/8410))
544
+ - 💥 Remove `Brush`, `ZoomBrush`, `Scribble`, `SnapIndicator`, `Handle`, `Handles`, `SelectionForeground`, `SelectionBackground`, `CollaboratorHint`, `ShapeIndicator`, `ShapeIndicators`, and `ShapeIndicatorErrorFallback` from `TLEditorComponents`, along with the corresponding `Default*` component exports and `LiveCollaborators`. Migrate custom overlay components to `OverlayUtil`; indicator customization moves to `ShapeUtil.getIndicatorPath()`. ([#8469](https://github.com/tldraw/tldraw/pull/8469))
545
+ - 💥 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 from `TLTheme`. ([#8469](https://github.com/tldraw/tldraw/pull/8469))
546
+ - 💥 Remove `assetValidator`. Use `imageAssetValidator`, `videoAssetValidator`, or `bookmarkAssetValidator` instead. ([#8031](https://github.com/tldraw/tldraw/pull/8031))
547
+ - 💥 Remove `getMediaAssetInfoPartial`. Use `AssetUtil.getAssetFromFile` instead. ([#8031](https://github.com/tldraw/tldraw/pull/8031))
548
+ - 💥 Change `notifyIfFileNotAllowed` signature from `(file, options)` to `(editor, file, options)`. ([#8031](https://github.com/tldraw/tldraw/pull/8031))
549
+ - 💥 Change `getAssetInfo` signature from `(file, options, assetId?)` to `(editor, file, assetId?)` and return `TLAsset | null` instead of throwing. ([#8031](https://github.com/tldraw/tldraw/pull/8031))
550
+ - 💥 Move the `Cmd+Shift+C` / `Ctrl+Shift+C` shortcut from "Copy as SVG" to "Copy as PNG". ([#8532](https://github.com/tldraw/tldraw/pull/8532))
551
+ - 💥 Replace `ShapeUtil.indicator()` (returned JSX) with `ShapeUtil.getIndicatorPath()` (returns `Path2D | TLIndicatorPath | undefined`). Indicators now render to the canvas overlay layer instead of as React elements. ([#8469](https://github.com/tldraw/tldraw/pull/8469))
552
+ - 💥 Move `cameraOptions`, `textOptions`, and `deepLinks` from top-level `<Tldraw>` props into the `options` prop (e.g. `options={{ camera, text, deepLinks }}`).
553
+ - 💥 Remove the `embeds` prop from `<Tldraw>`. Configure embed definitions via `EmbedShapeUtil.configure({ embedDefinitions })` and pass the configured util through `shapeUtils`.
554
+ - 💥 Demote `setDefaultEditorAssetUrls()` and `setDefaultUiAssetUrls()` to `@internal`. Pass `assetUrls` to each `<Tldraw>` instead.
555
+ - 💥 Remove `useTldrawUser`. Use the new `users` prop (`TLUserStore`) for identity and `TLUserPreferences` for preferences.
556
+ - 💥 Replace `TLDrawShapeSegment.points` with the helper `getPointsFromDrawSegment(segment, scaleX, scaleY)` so segment points respect the shape's current scale.
557
+ - 💥 Change `BindingUtil` hook params: `fromShapeType`/`toShapeType` are removed in favor of full `fromShape`/`toShape` records (read `fromShape.type` / `toShape.type` directly).
558
+ - 💥 Add `'middle-legacy'` (and other legacy values) to the `align` union resolved by `PlainTextLabel`/`RichTextLabel`. If your code maps `align` into `PlainTextLabel.textAlign`, narrow legacy values to one of `'start' | 'center' | 'end'` before passing them through.
559
+ - Add `TLTheme`, `TLThemeId`, `TLThemes`, `TLThemeDefaultColors`, `TLThemeColors`, `TLRemovedDefaultThemeColors`, `ThemeManager`, `getDisplayValues()`, `getColorValue()`, and `DEFAULT_THEME` for the new theme system. ([#8410](https://github.com/tldraw/tldraw/pull/8410))
560
+ - Add `themes` and `initialTheme` props to `<Tldraw>` and `<TldrawEditor>`. ([#8410](https://github.com/tldraw/tldraw/pull/8410))
561
+ - Add `getCurrentTheme()`, `setCurrentTheme()`, `getThemes()`, `getTheme()`, `updateTheme()`, `updateThemes()`, and `getColorMode()` to the editor. ([#8410](https://github.com/tldraw/tldraw/pull/8410))
562
+ - Add `getDefaultDisplayValues` and `getCustomDisplayValues` to shape util options for theme-aware visual properties. ([#8410](https://github.com/tldraw/tldraw/pull/8410))
563
+ - Add `OverlayUtil`, `TLOverlay`, `OverlayManager`, `Editor.overlays`, `defaultOverlayUtils`, and the `overlayUtils` prop on `<Tldraw>` / `<TldrawEditor>` for registering and managing canvas overlays. ([#8469](https://github.com/tldraw/tldraw/pull/8469))
564
+ - Add per-overlay utils: `BrushOverlayUtil`, `ZoomBrushOverlayUtil`, `ScribbleOverlayUtil`, `SnapIndicatorOverlayUtil`, `ShapeHandleOverlayUtil`, `SelectionForegroundOverlayUtil`, `ArrowHintOverlayUtil`, `CollaboratorBrushOverlayUtil`, `CollaboratorScribbleOverlayUtil`, `CollaboratorHintOverlayUtil`, and `CollaboratorCursorOverlayUtil`. ([#8469](https://github.com/tldraw/tldraw/pull/8469))
565
+ - Add overlay-related colors to `TLTheme`. ([#8469](https://github.com/tldraw/tldraw/pull/8469))
566
+ - Add `BaseFrameLikeShapeUtil` abstract class and `ShapeUtil.isFrameLike()` so custom shapes can opt into frame-like behaviors (paste parenting, full-brush selection, blocking erasure from inside, clipping children). `FrameShapeUtil` now extends `BaseFrameLikeShapeUtil`. ([#8331](https://github.com/tldraw/tldraw/pull/8331))
567
+ - Add extensibility API for custom geo shape types via `GeoShapeUtil.configure({ customGeoTypes })`. Add `GeoTypeDefinition` interface for defining path geometry, snap behavior, creation size, style panel icon, and double-click handler while inheriting standard geo shape behavior. ([#8543](https://github.com/tldraw/tldraw/pull/8543))
568
+ - Add `AssetUtil` base class with `configure()`, `getDefaultProps()`, `getSupportedMimeTypes()`, `getAssetFromFile()`, and `createShape()`. Add `assetUtils` prop to `<Tldraw>`. Add `Editor.getAssetUtil()`, `Editor.hasAssetUtil()`, and `Editor.getAssetUtilForMimeType()`. Add `TLGlobalAssetPropsMap` for type-safe custom asset registration. Add `createAssetRecordType()`, `defaultAssetSchemas`, and `assets` parameter to `createTLSchema()`. ([#8031](https://github.com/tldraw/tldraw/pull/8031))
569
+ - Add `CustomRecordInfo` interface, `createCustomRecordId()`, `createCustomRecordMigrationIds()`, `createCustomRecordMigrationSequence()`, `isCustomRecord()`, `isCustomRecordId()` for custom record types. `createTLSchema()` and `createTLStore()` now accept a `records` option. ([#8213](https://github.com/tldraw/tldraw/pull/8213))
570
+ - Add `TLUserStore` interface with `getCurrentUser()` and `resolve()` for connecting tldraw to auth systems. Add unified `TLUser` record type, `UserRecordType`, `createUserId`, `isUserId`, `userIdValidator`, and `createUserRecordType()` for extensible user schemas. Add `user` parameter to `createTLSchema()`. Add `Editor.getAttributionUser()`, `Editor.getAttributionUserId()`, and `Editor.getAttributionDisplayName()`. Add `textFirstEditedBy` prop to `TLNoteShapeProps`. ([#8147](https://github.com/tldraw/tldraw/pull/8147))
571
+ - Add `@tldraw/driver` package with `Driver` class for imperative editor control. ([#7952](https://github.com/tldraw/tldraw/pull/7952))
572
+ - Add `@tldraw/mermaid` package with `createMermaidDiagram()`, `renderBlueprint()`, and `MermaidDiagramError` for converting Mermaid syntax to tldraw shapes. ([#8194](https://github.com/tldraw/tldraw/pull/8194))
573
+ - Add `mapNodeToRenderSpec` per-diagram-type option and `createShape` override to `@tldraw/mermaid` for customizing how diagram nodes are rendered as shapes. ([#8322](https://github.com/tldraw/tldraw/pull/8322))
574
+ - Add `onBeforeCopyToClipboard`, `onBeforePasteFromClipboard`, and `onClipboardPasteRaw` hooks to `TldrawOptions` for intercepting clipboard operations. Add `TLClipboardWriteInfo` and `TLClipboardPasteRawInfo` types. Export `handleNativeOrMenuCopy` from `@tldraw/tldraw`. ([#8290](https://github.com/tldraw/tldraw/pull/8290))
575
+ - Add `Cmd+Shift+V` / `Ctrl+Shift+V` shortcut to paste clipboard content as plain text. `Cmd+Shift+V` no longer toggles paste-at-cursor positioning. ([#8347](https://github.com/tldraw/tldraw/pull/8347))
576
+ - Add support for pasting arbitrary `<iframe>` embed codes to create embed shapes from any service. ([#8306](https://github.com/tldraw/tldraw/pull/8306))
577
+ - Add Canva to `DEFAULT_EMBED_DEFINITIONS` so Canva design URLs paste as iframe embeds. ([#8459](https://github.com/tldraw/tldraw/pull/8459))
578
+ - Add `TldrawOptions.rightClickPanning` (default `true`) to gate the new right-click drag-to-pan behavior. Add `InputsManager.getIsRightPointing()` / `setIsRightPointing()`. ([#8501](https://github.com/tldraw/tldraw/pull/8501))
579
+ - Add `Editor.performance` (`PerformanceManager`) with `on()`, `once()`, and `dispose()` for subscribing to interaction, camera, shape-operation, frame, and undo/redo performance events. Add `PerformanceApiAdapter` for piping events into the browser Performance API. Add `StateNode.trackPerformance` static field so custom tools can opt into interaction tracking. Add `TLPerfFrameTimeStats`, `TLPerfEventMap`, `TLInteractionStartPerfEvent`, `TLInteractionEndPerfEvent`, `TLCameraStartPerfEvent`, `TLCameraEndPerfEvent`, `TLShapeOperationPerfEvent`, `TLFramePerfEvent`, `TLUndoRedoPerfEvent`, `TLPerfLongAnimationFrame`, and `TLPerfLongAnimationFrameScript`. ([#8421](https://github.com/tldraw/tldraw/pull/8421))
580
+ - Add `Editor.getContainerDocument()` and `Editor.getContainerWindow()` methods, and `getOwnerDocument()` / `getOwnerWindow()` helpers for cross-window embedding. ([#8196](https://github.com/tldraw/tldraw/pull/8196))
581
+ - Add `handleSocketResume()`, `getSessionSnapshot()`, and `onSessionSnapshot` to `TLSocketRoom` for WebSocket hibernation support. Add `clientTimeout` option to `TLSyncRoom`. ([#8070](https://github.com/tldraw/tldraw/pull/8070))
582
+ - Add `useDirection()` hook for RTL support. ([#8033](https://github.com/tldraw/tldraw/pull/8033))
583
+ - Expose `PeopleMenu`, `PeopleMenuItem`, `PeopleMenuFacePile`, and `UserPresenceEditor` through `TldrawUiComponents` so the share panel sub-components can be overridden via the `<Tldraw />` `components` prop. ([#8346](https://github.com/tldraw/tldraw/pull/8346))
584
+ - Add `'none'` to `TLDefaultDashStyle` for hiding shape borders while preserving fills. The option is not exposed in the style panel — it can only be set programmatically. Add `NonePathBuilderOpts`; `PathBuilder.toSvg()` now returns `null` for the `'none'` style. ([#8453](https://github.com/tldraw/tldraw/pull/8453))
585
+ - Export `defaultHandleExternalFileReplaceContent`, which was previously referenced in docs but missing from the package's public exports. ([#8579](https://github.com/tldraw/tldraw/pull/8579))
586
+ - Change `TLSvgExportOptions.padding` to accept `number | 'auto'`. The `'auto'` mode (now default) renders with padding then trims to visual content bounds. ([#8202](https://github.com/tldraw/tldraw/pull/8202))
587
+ - Add `TextManager.measureHtmlBatch()` for batched DOM text measurement. ([#7949](https://github.com/tldraw/tldraw/pull/7949))
588
+ - Add `'json'` to `TLCopyType` for copying shapes as JSON in debug mode. ([#8206](https://github.com/tldraw/tldraw/pull/8206))
589
+ - Add `Vec.IsFinite()` for checking whether a vector has finite coordinates. ([#8176](https://github.com/tldraw/tldraw/pull/8176))
590
+ - Change `Vec.PointsBetween()` to accept an optional `ease` parameter. ([#7977](https://github.com/tldraw/tldraw/pull/7977))
591
+
592
+ ### Improvements
593
+
594
+ - 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](https://github.com/tldraw/tldraw/pull/8210))
595
+ - Improve resize performance for multiple geo shapes with text labels by batching DOM measurements into a single pass per frame. ([#7949](https://github.com/tldraw/tldraw/pull/7949))
596
+ - Exports now automatically trim to visual content bounds, capturing overflow like thick strokes and arrowheads without extra whitespace. ([#8202](https://github.com/tldraw/tldraw/pull/8202))
597
+ - Add `Cmd+Shift+V` / `Ctrl+Shift+V` shortcut to paste clipboard content as plain text, stripping HTML and rich formatting. `Cmd+Shift+V` no longer toggles paste-at-cursor positioning — the "Paste at cursor" preference covers that use case. ([#8347](https://github.com/tldraw/tldraw/pull/8347))
598
+ - Change `Cmd+Shift+C` / `Ctrl+Shift+C` to 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](https://github.com/tldraw/tldraw/pull/8532))
599
+ - 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 to `true`). ([#8501](https://github.com/tldraw/tldraw/pull/8501))
600
+ - Allow Cmd+click / Ctrl+click on style panel items to apply style changes only to selected shapes without updating defaults for future shapes. ([#8452](https://github.com/tldraw/tldraw/pull/8452))
601
+ - Hide selection overlay when nudging shapes with arrow keys. ([#8447](https://github.com/tldraw/tldraw/pull/8447))
602
+ - Move the debug mode toggle into the preferences submenu. ([#8259](https://github.com/tldraw/tldraw/pull/8259))
603
+ - Tighten iframe referrer policy for embeds to send only the origin instead of the full URL to third-party embed providers. ([#8412](https://github.com/tldraw/tldraw/pull/8412))
604
+ - Replace the `@use-gesture/react` dependency with custom gesture handling. Bundle size is smaller and a stale dependency is gone. ([#8392](https://github.com/tldraw/tldraw/pull/8392))
605
+
606
+ ### Bug fixes
607
+
608
+ - Fix `bailToMark` silently discarding pending history changes when the target mark doesn't exist. ([#8260](https://github.com/tldraw/tldraw/pull/8260))
609
+ - Fix `FocusManager.dispose()` not actually removing document event listeners due to `.bind()` creating new function references. ([#8232](https://github.com/tldraw/tldraw/pull/8232))
610
+ - 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](https://github.com/tldraw/tldraw/pull/8396))
611
+ - Fix leaked camera animations, following subscriptions, and stale menu state when the editor is disposed during active operations. ([#8422](https://github.com/tldraw/tldraw/pull/8422))
612
+ - Fix a memory leak where disposed `Editor` instances were retained through a shared throttled `updateHoveredShapeId` closure. ([#8439](https://github.com/tldraw/tldraw/pull/8439))
613
+ - Fix a memory leak where disposed `Editor` instances were retained through the `window.__tldraw__hardReset` global. ([#8476](https://github.com/tldraw/tldraw/pull/8476))
614
+ - Fix crash when isolating curved arrows with degenerate binding geometry. ([#8176](https://github.com/tldraw/tldraw/pull/8176))
615
+ - Fix all shapes disappearing when a labeled arrow has zero length (both endpoints overlapping), which previously propagated NaN values through the spatial index. ([#8329](https://github.com/tldraw/tldraw/pull/8329))
616
+ - Fix crash from duplicate fractional index keys in `kickoutOccludedShapes` during multiplayer sync. ([#8448](https://github.com/tldraw/tldraw/pull/8448))
617
+ - Fix crash in browsers without `OffscreenCanvas` support (e.g. older Safari) when preloading image alpha data. ([#8582](https://github.com/tldraw/tldraw/pull/8582))
618
+ - Fix over-softened corners and end artifacts when shift-clicking to draw straight line segments. ([#7977](https://github.com/tldraw/tldraw/pull/7977))
619
+ - Fix eraser not erasing shapes when starting a drag from inside a group's bounds. ([#8054](https://github.com/tldraw/tldraw/pull/8054))
620
+ - Fix draw-shape loop-closing sensitivity so closing works more consistently across zoom levels. ([#8293](https://github.com/tldraw/tldraw/pull/8293))
621
+ - Fix shadow artifact and oversized caret on notes and geo shapes at high zoom in dynamic size mode. ([#8378](https://github.com/tldraw/tldraw/pull/8378))
622
+ - Fix pattern fill not scaling correctly with dynamic size mode. ([#8441](https://github.com/tldraw/tldraw/pull/8441))
623
+ - Fix arrow labels rendered at incorrect size when editing at high zoom in dynamic size mode. ([#8451](https://github.com/tldraw/tldraw/pull/8451))
624
+ - 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](https://github.com/tldraw/tldraw/pull/8570))
625
+ - Fix spiky artifacts on draw-style geometric shapes by using a circular random offset distribution instead of a square one. ([#8466](https://github.com/tldraw/tldraw/pull/8466))
626
+ - Fix pasting into editable text shapes when the clipboard contains tldraw data. ([#8192](https://github.com/tldraw/tldraw/pull/8192))
627
+ - Fix slight positioning drift when pasting text onto the canvas. ([#8345](https://github.com/tldraw/tldraw/pull/8345))
628
+ - Fix right-clicking inside a multi-selection over a filled background shape changing the selection. ([#8434](https://github.com/tldraw/tldraw/pull/8434))
629
+ - Fix context menu briefly flashing when right-clicking to dismiss an already-open context menu. ([#8498](https://github.com/tldraw/tldraw/pull/8498))
630
+ - Fix context menu items accidentally being selected when right-clicking and quickly moving the mouse. ([#8499](https://github.com/tldraw/tldraw/pull/8499))
631
+ - Fix opacity slider drag not working on Safari due to `stopPropagation` blocking pointer events. ([#8519](https://github.com/tldraw/tldraw/pull/8519))
632
+ - 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](https://github.com/tldraw/tldraw/pull/8520))
633
+ - Fix `Cmd+Shift+V` doing 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](https://github.com/tldraw/tldraw/pull/8490))
634
+ - Fix keyboard shortcuts that change styles not marking the change as a style update, causing subsequent shapes to use the wrong defaults. ([#8599](https://github.com/tldraw/tldraw/pull/8599)) (contributed by [@danieljamesross](https://github.com/danieljamesross))
635
+ - Fix "back to content" button flickering when both it and the "move focus to canvas" button are visible. ([#8334](https://github.com/tldraw/tldraw/pull/8334))
636
+ - Fix intermittent `ResizeObserver loop` browser warnings when hovering over toolbar buttons. ([#8574](https://github.com/tldraw/tldraw/pull/8574))
637
+ - Fix missing sandbox attribute on GitHub Gist embeds. ([#8403](https://github.com/tldraw/tldraw/pull/8403))
638
+ - Restrict sandbox permissions for unknown/arbitrary embeds to mitigate security risks from untrusted content. ([#8404](https://github.com/tldraw/tldraw/pull/8404))
639
+ - 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](https://github.com/tldraw/tldraw/pull/8542))
640
+ - Fix sticky notes preserving stale attribution when cloned via a nib. ([#8614](https://github.com/tldraw/tldraw/pull/8614))
641
+ - Fix `Cmd+V` paste of tldraw-copied PNGs on Chrome 147 stable, where the custom-format clipboard entry returned a 0-byte blob. ([#8615](https://github.com/tldraw/tldraw/pull/8615))
642
+ - Fix note author attribution overflowing the sticky note width in SVG and PNG exports. ([#8664](https://github.com/tldraw/tldraw/pull/8664))
643
+ - Fix keyboard shortcuts not matching on alternative Latin keyboard layouts (Dvorak, Colemak, AZERTY) by replacing the `hotkeys-js` library with a small layout-aware native event matcher. ([#8669](https://github.com/tldraw/tldraw/pull/8669))
644
+ - Fix TypeScript signature mismatch on `ShapeUtil` base-class methods so overrides that need a `shape` parameter can declare it without errors. ([#8521](https://github.com/tldraw/tldraw/pull/8521))
645
+
646
+ ## v4.5.0
647
+
648
+ [View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.5.0)
649
+
650
+ 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.
651
+
652
+ ### What's new
653
+
654
+ #### Click-through on transparent image pixels ([#7942](https://github.com/tldraw/tldraw/pull/7942))
655
+
656
+ 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.
657
+
658
+ This is powered by a new `Geometry2d.ignoreHit(point)` method that allows geometries to reject successful hit tests.
659
+
660
+ #### 🔜 Configurable embed definitions ([#8034](https://github.com/tldraw/tldraw/pull/8034))
661
+
662
+ 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.
663
+
664
+ ```tsx
665
+ import { EmbedShapeUtil, DEFAULT_EMBED_DEFINITIONS } from 'tldraw'
666
+
667
+ const shapeUtils = [
668
+ EmbedShapeUtil.configure({
669
+ embedDefinitions: [...DEFAULT_EMBED_DEFINITIONS, myCustomEmbed],
670
+ }),
671
+ ]
672
+ ```
673
+
674
+ <details>
675
+ <summary>Migration guide</summary>
676
+
677
+ Before:
678
+
679
+ ```ts
680
+ EmbedShapeUtil.setEmbedDefinitions([...DEFAULT_EMBED_DEFINITIONS, myEmbed])
681
+ ```
682
+
683
+ After:
684
+
685
+ ```ts
686
+ const shapeUtils = [
687
+ EmbedShapeUtil.configure({
688
+ embedDefinitions: [...DEFAULT_EMBED_DEFINITIONS, myEmbed],
689
+ }),
690
+ ]
691
+ ```
692
+
693
+ The `embeds` prop on `Tldraw` still works but is deprecated. Use `EmbedShapeUtil.configure()` instead.
694
+
695
+ </details>
696
+
697
+ #### SVG sanitization ([#7896](https://github.com/tldraw/tldraw/pull/7896), [#8087](https://github.com/tldraw/tldraw/pull/8087))
698
+
699
+ 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).
700
+
701
+ The sanitizer is also available as a public export for custom content handling:
702
+
703
+ ```ts
704
+ import { sanitizeSvg } from 'tldraw'
705
+
706
+ const cleanSvg = sanitizeSvg(untrustedSvgText)
707
+ ```
708
+
709
+ ### API changes
710
+
711
+ - 🔜 **`EmbedShapeUtil.setEmbedDefinitions()`** deprecated. Use `EmbedShapeUtil.configure({ embedDefinitions: [...] })` instead. ([#8034](https://github.com/tldraw/tldraw/pull/8034))
712
+ - 🔜 **`Tldraw` `embeds` prop** is deprecated. Configure embed definitions via `EmbedShapeUtil.configure()`. ([#8034](https://github.com/tldraw/tldraw/pull/8034))
713
+ - Add `Geometry2d.ignoreHit(point)` for rejecting hit tests on transparent pixels. ([#7942](https://github.com/tldraw/tldraw/pull/7942))
714
+ - Add `Editor.resizeToBounds(shapes, bounds)` for resizing shapes to fit target bounds. ([#8120](https://github.com/tldraw/tldraw/pull/8120))
715
+ - Add `Editor.getResizeScaleFactor()` for computing the dynamic size scale factor at the current zoom level. ([#8042](https://github.com/tldraw/tldraw/pull/8042))
716
+ - Add `sanitizeSvg(svgText: string)` export for sanitizing SVG content against XSS and data exfiltration. ([#7896](https://github.com/tldraw/tldraw/pull/7896))
717
+ - Add experimental `experimental__onDropOnCanvas` option to intercept canvas drop events. Return `true` from the callback to prevent the editor's default drop behavior. ([#7911](https://github.com/tldraw/tldraw/pull/7911))
718
+
719
+ ```tsx
720
+ <Tldraw
721
+ options={{
722
+ experimental__onDropOnCanvas: (point, event) => {
723
+ // Handle drop at page-space point
724
+ return true // prevent default
725
+ },
726
+ }}
727
+ />
728
+ ```
729
+
730
+ - Add optional `pixelRatio` property to `TLImageAsset` for correct high-DPI image sizing. Detected automatically from PNG metadata. ([#8163](https://github.com/tldraw/tldraw/pull/8163))
731
+ - 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](https://github.com/tldraw/tldraw/pull/8084))
732
+
733
+ ### Improvements
734
+
735
+ - Improve arrow component rendering performance with finer-grained reactivity. ([#8167](https://github.com/tldraw/tldraw/pull/8167))
736
+ - Simplify paste-parent selection to use `canReceiveNewChildrenOfType` instead of frame-specific checks. Prevent edge-only overlap from auto-reparenting pasted shapes into adjacent frames. ([#8057](https://github.com/tldraw/tldraw/pull/8057))
737
+ - Save link and alt-text values when clicking outside the editor instead of discarding changes. ([#8037](https://github.com/tldraw/tldraw/pull/8037))
738
+ - Add SVG sanitization on paste and file drop to prevent XSS and data exfiltration. ([#7896](https://github.com/tldraw/tldraw/pull/7896))
739
+ - Fix circular dependencies across `@tldraw/state`, `@tldraw/editor`, and `@tldraw/tldraw` packages to improve compatibility with Jest mocking and tree-shaking. ([#7935](https://github.com/tldraw/tldraw/pull/7935))
740
+ - Fix high-DPI image sizing to work correctly across macOS and Windows by detecting the source DPI baseline from PNG metadata. ([#8163](https://github.com/tldraw/tldraw/pull/8163))
741
+
742
+ ### Bug fixes
743
+
744
+ - Fix shapes pasted with Ctrl+V not being parented to a frame when they land inside one. ([#7938](https://github.com/tldraw/tldraw/pull/7938))
745
+ - Fix a crash when cropping custom shapes that don't include `isCircle` in their crop schema. ([#7931](https://github.com/tldraw/tldraw/pull/7931))
746
+ - Fix a crash when loading session state without a `currentPageId` (e.g. when using deep links). ([#7994](https://github.com/tldraw/tldraw/pull/7994))
747
+ - Fix U+2028/U+2029 line separators breaking chunked sync messages. ([#7918](https://github.com/tldraw/tldraw/pull/7918))
748
+ - Fix "Download original" not triggering a download for cross-origin assets. ([#8090](https://github.com/tldraw/tldraw/pull/8090))
749
+ - Fix arrow endpoints terminating at invisible clipped shape boundaries instead of at the frame edge. ([#7932](https://github.com/tldraw/tldraw/pull/7932))
750
+ - Fix sticky notes having a hard shadow instead of a soft drop shadow when exported as SVG. ([#7934](https://github.com/tldraw/tldraw/pull/7934))
751
+ - Fix rich text toolbar staying open when the editing shape is deleted by another user. ([#8050](https://github.com/tldraw/tldraw/pull/8050))
752
+ - Fix SVG sanitizer stripping embedded SVG data URIs on `<image>` elements. Nested SVGs are now recursively sanitized instead of blocked. ([#8087](https://github.com/tldraw/tldraw/pull/8087))
753
+ - Fix `TldrawSelectionForeground` crashing when used without `TldrawUiContextProvider`. ([#8011](https://github.com/tldraw/tldraw/pull/8011))
754
+ - Fix dynamic-size shapes losing shadows and dashes too early when zoomed out. ([#8040](https://github.com/tldraw/tldraw/pull/8040))
755
+ - Fix a crash when resizing draw or highlight shapes to zero width or height. ([#8067](https://github.com/tldraw/tldraw/pull/8067))
756
+ - Fix crash when enabling Debug SVG with shapes on the canvas. ([#8101](https://github.com/tldraw/tldraw/pull/8101))
757
+ - Fix `localOffset` mutation bug in `stretchShapes` when shapes have parent transforms. ([#8120](https://github.com/tldraw/tldraw/pull/8120))
758
+ - Fix arrow SVG export producing invalid negative `<foreignObject>` dimensions when arrows have no text label. ([#8137](https://github.com/tldraw/tldraw/pull/8137))
759
+ - Fix arrow endpoint flickering when anchors are at exact shape boundaries. ([#8130](https://github.com/tldraw/tldraw/pull/8130))
760
+ - Fix shapes dragged from the toolbar not respecting dynamic size mode. ([#8042](https://github.com/tldraw/tldraw/pull/8042))
761
+ - Fix dragging unselected shapes that have an `onClick` handler. ([#7936](https://github.com/tldraw/tldraw/pull/7936))
762
+ - Fix false positive "multiple instances" warning in Next.js dev mode. ([#7933](https://github.com/tldraw/tldraw/pull/7933))
763
+ - Fix missing alt text on rendered image shapes in some cases. ([#8158](https://github.com/tldraw/tldraw/pull/8158))
764
+ - Fix drawing on tablets that report zero pen pressure. ([#5693](https://github.com/tldraw/tldraw/pull/5693))
765
+ - Fix `create-tldraw` CLI to always create a subdirectory from the project name. ([#8161](https://github.com/tldraw/tldraw/pull/8161))
766
+
767
+ ---
768
+
769
+ ### Patch releases
770
+
771
+ #### v4.5.3
772
+
773
+ - Fix dynamic import file extension handling. ([#8278](https://github.com/tldraw/tldraw/pull/8278))
774
+
775
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.5.3)
776
+
777
+ #### v4.5.4
778
+
779
+ - Fix all shapes disappearing when a labeled arrow has zero length due to NaN propagation through the spatial index. ([#8351](https://github.com/tldraw/tldraw/pull/8351))
780
+
781
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.5.4)
782
+
783
+ #### v4.5.5
784
+
785
+ - Fix camera state getting permanently stuck at 'moving' when the editor is disposed mid-camera-transition. ([#8396](https://github.com/tldraw/tldraw/pull/8396))
786
+
787
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.5.5)
788
+
789
+ #### v4.5.6
790
+
791
+ - Fix crash when isolating curved arrows with degenerate binding geometry. ([#8390](https://github.com/tldraw/tldraw/pull/8390))
792
+
793
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.5.6)
794
+
795
+ ## v4.4.0
796
+
797
+ [View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.4.0)
798
+
799
+ This release adds a consolidated `options` prop, quick zoom navigation, a fill styles dropdown, a new `TldrawUiSelect` component, and shape-aware binding checks. It also includes 2D canvas rendering for shape indicators, R-tree spatial indexing, telestrator-style laser behavior, significant performance improvements for large canvases, and various bug fixes.
800
+
801
+ ### What's new
802
+
803
+ #### 2D canvas rendering for shape indicators ([#7708](https://github.com/tldraw/tldraw/pull/7708))
804
+
805
+ Shape indicators (selection outlines, hover states) now render using a 2D canvas instead of SVG elements. This significantly improves performance when selecting or hovering over many shapes, with up to 25x faster rendering in some scenarios.
806
+
807
+ Custom shapes can opt into canvas indicators by implementing the new `getIndicatorPath()` method on their ShapeUtil, and marking `useLegactIndicator` to return false:
808
+
809
+ ```tsx
810
+ class MyShapeUtil extends ShapeUtil<MyShape> {
811
+ getIndicatorPath(shape: MyShape): TLIndicatorPath | undefined {
812
+ return {
813
+ path: new Path2D(),
814
+ // optional clip path for complex shapes like arrows with labels
815
+ }
816
+ }
817
+
818
+ // Return false to use the new canvas indicators (default is true for backwards compatibility)
819
+ useLegacyIndicator(): boolean {
820
+ return false
821
+ }
822
+ }
823
+ ```
824
+
825
+ #### Quick zoom navigation ([#7801](https://github.com/tldraw/tldraw/pull/7801), [#7836](https://github.com/tldraw/tldraw/pull/7836))
826
+
827
+ Press `z` then hold Shift to zoom out and see the whole canvas ("eagle eye" view). A viewport brush appears showing where you'll zoom to. Move the cursor to pick a location and release Shift to zoom there. Press Escape to cancel and return to the original view.
828
+
829
+ #### Fill styles dropdown ([#7885](https://github.com/tldraw/tldraw/pull/7885))
830
+
831
+ The style panel now exposes additional fill styles (pattern, fill, lined-fill) through a dropdown picker after the solid button. The first three fill options (none, semi, solid) remain as inline buttons.
832
+
833
+ #### User preference: Invert mouse wheel zoom direction ([#7732](https://github.com/tldraw/tldraw/pull/7732))
834
+
835
+ Added a new user preference to invert mouse wheel zoom direction. Some users prefer "natural" scrolling behavior where scrolling down zooms out, which this option now enables.
836
+
837
+ Access it via Menu → Preferences → Input device → Invert mouse zoom.
838
+
839
+ #### Performance improvements ([#7676](https://github.com/tldraw/tldraw/pull/7676), [#7826](https://github.com/tldraw/tldraw/pull/7826), [#7840](https://github.com/tldraw/tldraw/pull/7840), [#7657](https://github.com/tldraw/tldraw/pull/7657))
840
+
841
+ This release includes several performance improvements for large canvases:
842
+
843
+ - **R-tree spatial indexing**: Shape queries now use an R-tree (RBush) for O(log n) lookups instead of O(n) iteration, significantly improving brushing, scribble selection, and erasing with many shapes on the canvas. The spatial index is maintained internally and accessed through existing methods like `editor.getShapesAtPoint()` and `editor.getShapeAtPoint()`.
844
+ - **Faster panning**: Hover hit-testing is now skipped during camera movement, reducing work while panning through large documents.
845
+ - **Reduced allocations**: Optimized Set comparisons, reduced memory allocations, and added string hash caching for better performance in large canvases and multiplayer rooms.
846
+ - **Smarter network scheduling**: Solo-mode network traffic is reduced by throttling to 1 FPS when no collaborators are present.
847
+
848
+ #### Re-designed laser pointer ([#7681](https://github.com/tldraw/tldraw/pull/7681))
849
+
850
+ The laser pointer now behaves like a telestrator: all strokes remain visible while you're drawing and fade together when you stop. Previously, each stroke segment would fade independently, creating a trailing effect.
851
+
852
+ This is powered by a new generic session system on `ScribbleManager`. Sessions group multiple scribbles together and control how they fade:
853
+
854
+ ```tsx
855
+ // Start a grouped session (used internally by the laser tool)
856
+ const sessionId = editor.scribbles.startSession({
857
+ fadeMode: 'grouped',
858
+ idleTimeoutMs: 1200,
859
+ fadeDurationMs: 500,
860
+ })
861
+
862
+ // Add scribbles and points to a session
863
+ editor.scribbles.addScribbleToSession(sessionId, { color: 'laser' })
864
+ editor.scribbles.addPointToSession(sessionId, scribbleId, x, y)
865
+
866
+ // Stop or clear a session
867
+ editor.scribbles.stopSession(sessionId)
868
+ editor.scribbles.clearSession(sessionId)
869
+ ```
870
+
871
+ New option in `TldrawOptions`:
872
+
873
+ - `laserFadeoutMs` (default: 500ms) - How long to fade all laser scribbles after the session ends
874
+
875
+ #### Image pipeline starter template ([#7863](https://github.com/tldraw/tldraw/pull/7863))
876
+
877
+ A new "Image pipeline" starter template is available via `npx create-tldraw`. It provides a visual node-based canvas for building AI image generation workflows, with custom node shapes, typed port connections, pipeline regions with play/stop controls, and a DAG-based execution engine backed by a Cloudflare Worker API.
878
+
879
+ #### Agent starter template improvements ([#7640](https://github.com/tldraw/tldraw/pull/7640))
880
+
881
+ The agent starter template has been restructured around a manager-based architecture for better modularity and extensibility. It now includes a mode system for controlling agent capabilities per mode, action schema registries, prompt part definitions, canvas linting, and user action tracking. The template also renames "SimpleShape" to "FocusedShape" for clarity.
882
+
883
+ #### TldrawUiSelect component ([#7566](https://github.com/tldraw/tldraw/pull/7566))
884
+
885
+ New select dropdown primitive wrapping Radix UI's Select, following existing tldraw UI patterns.
886
+
887
+ #### 🔜 Consolidated options prop ([#7888](https://github.com/tldraw/tldraw/pull/7888))
888
+
889
+ The `cameraOptions`, `textOptions`, and `deepLinks` props on `Tldraw`, `TldrawEditor`, and `TldrawImage` are now consolidated into the `options` prop. The standalone props are deprecated but still work for backward compatibility.
890
+
891
+ ```tsx
892
+ // Before
893
+ <Tldraw cameraOptions={{ isLocked: true }} deepLinks textOptions={{ ... }} />
894
+
895
+ // After
896
+ <Tldraw options={{ camera: { isLocked: true }, deepLinks: true, text: { ... } }} />
897
+ ```
898
+
899
+ <details>
900
+ <summary>Migration guide</summary>
901
+
902
+ Replace standalone props with equivalent `options` fields:
903
+
904
+ - `cameraOptions={...}` → `options={{ camera: { ... } }}`
905
+ - `textOptions={...}` → `options={{ text: { ... } }}`
906
+ - `deepLinks` or `deepLinks={...}` → `options={{ deepLinks: true }}` or `options={{ deepLinks: { ... } }}`
907
+
908
+ The deprecated props still work. When both the deprecated prop and the `options` field are provided, the `options` value takes precedence.
909
+
910
+ </details>
911
+
912
+ ### API changes
913
+
914
+ - 🔜 **`TldrawEditorBaseProps.cameraOptions`**, **`TldrawEditorBaseProps.textOptions`**, **`TldrawEditorBaseProps.deepLinks`** deprecated in favor of `options.camera`, `options.text`, `options.deepLinks`. ([#7888](https://github.com/tldraw/tldraw/pull/7888))
915
+ - 🔜 **`TLShapeUtilCanBindOpts.fromShapeType`** and **`toShapeType`** replaced with `fromShape` and `toShape` accepting `TLShape | { type }`. ([#7821](https://github.com/tldraw/tldraw/pull/7821))
916
+ - Remove `editor.spatialIndex` from public API. The spatial index is now internal; use `editor.getShapesAtPoint()` and `editor.getShapeAtPoint()` for shape queries. ([#7699](https://github.com/tldraw/tldraw/pull/7699))
917
+ - Add `TldrawOptions.camera`, `TldrawOptions.text`, and `TldrawOptions.deepLinks` fields to the `options` prop. ([#7888](https://github.com/tldraw/tldraw/pull/7888))
918
+ - Add `TldrawUiSelect`, `TldrawUiSelectTrigger`, `TldrawUiSelectValue`, `TldrawUiSelectContent`, `TldrawUiSelectItem` components and associated prop types. Add `iconTypes` export for enumerating available icons. ([#7566](https://github.com/tldraw/tldraw/pull/7566))
919
+ - Add `useCanApplySelectionAction()` hook for checking if selection actions should be enabled. ([#7811](https://github.com/tldraw/tldraw/pull/7811))
920
+ - Add `TLInstance.cameraState: 'idle' | 'moving'` for tracking camera movement state. ([#7826](https://github.com/tldraw/tldraw/pull/7826))
921
+ - Add `quickZoomPreservesScreenBounds` to `TldrawOptions`. ([#7836](https://github.com/tldraw/tldraw/pull/7836))
922
+ - Add `fillExtra` to `STYLES` object for additional fill style options. ([#7885](https://github.com/tldraw/tldraw/pull/7885))
923
+ - Make `Editor.getShapeIdsInsideBounds()` public. ([#7863](https://github.com/tldraw/tldraw/pull/7863))
924
+ - Add `ShapeUtil.getIndicatorPath()` method and `TLIndicatorPath` type for canvas-based indicator rendering. Add `ShapeUtil.useLegacyIndicator()` to control whether shapes use SVG or canvas indicators. ([#7708](https://github.com/tldraw/tldraw/pull/7708))
925
+ - Add `isZoomDirectionInverted` to `TLUserPreferences` interface and `UserPreferencesManager.getIsZoomDirectionInverted()` method. Add `ToggleInvertZoomItem` component export and `toggle-invert-zoom` action. ([#7732](https://github.com/tldraw/tldraw/pull/7732))
926
+ - Add `complete` to `TL_SCRIBBLE_STATES` enum and `ScribbleManager.complete(id)` method for marking scribbles as complete before fading. ([#7760](https://github.com/tldraw/tldraw/pull/7760))
927
+ - Add scribble session system: `ScribbleManager.startSession()`, `stopSession()`, `clearSession()`, `extendSession()`, `isSessionActive()`, `addScribbleToSession()`, `addPointToSession()`, and `ScribbleSessionOptions` type. Add `LaserTool.getSessionId()`. Add `laserFadeoutMs` to `TldrawOptions`. ([#7681](https://github.com/tldraw/tldraw/pull/7681))
928
+ - Add `FpsScheduler` class to create FPS-throttled function queues with configurable target rates. ([#7418](https://github.com/tldraw/tldraw/pull/7418))
929
+
930
+ ### Improvements
931
+
932
+ - Improve performance in large canvases and multiplayer rooms by optimizing Set comparisons, reducing memory allocations, and caching string hashes. ([#7840](https://github.com/tldraw/tldraw/pull/7840))
933
+ - Improve panning performance in large documents by skipping hover hit-testing during camera movement. ([#7826](https://github.com/tldraw/tldraw/pull/7826))
934
+ - Improve performance when translating arrows together with bound shapes by skipping unnecessary reparenting. ([#7733](https://github.com/tldraw/tldraw/pull/7733))
935
+ - Add R-tree spatial indexing for O(log n) shape queries, improving performance of brushing, selection, and erasing with many shapes. ([#7676](https://github.com/tldraw/tldraw/pull/7676))
936
+ - Improve laser pointer to keep all strokes visible during a session (telestrator pattern), with strokes fading together when drawing stops. ([#7681](https://github.com/tldraw/tldraw/pull/7681))
937
+ - Improve laser pointer strokes with proper taper when lifting the pointer by adding a 'complete' state to the scribble lifecycle. ([#7760](https://github.com/tldraw/tldraw/pull/7760))
938
+ - Improve quick zoom to use zoom-to-fit instead of fixed 5%, add "quick peek" behavior, and add edge scrolling. ([#7836](https://github.com/tldraw/tldraw/pull/7836))
939
+ - Remove `core-js` polyfill dependency from `@tldraw/editor`. ([#7769](https://github.com/tldraw/tldraw/pull/7769))
940
+ - Reduce network traffic by squashing pending push requests before sending, so rapid edits result in fewer network calls. ([#7724](https://github.com/tldraw/tldraw/pull/7724))
941
+ - Reduce solo-mode network traffic by using a dedicated FPS-based scheduler that throttles to 1 FPS when no collaborators are present. ([#7657](https://github.com/tldraw/tldraw/pull/7657))
942
+ - Improve performance by separating UI and network scheduling into independent queues with configurable target FPS. ([#7418](https://github.com/tldraw/tldraw/pull/7418))
943
+ - Improve frame label sizing on smaller viewports and when zoomed out. ([#7746](https://github.com/tldraw/tldraw/pull/7746))
944
+ - Add image pipeline starter template with visual node-based AI image generation workflows. ([#7863](https://github.com/tldraw/tldraw/pull/7863))
945
+ - Restructure agent starter template with manager-based architecture and mode system. ([#7640](https://github.com/tldraw/tldraw/pull/7640))
946
+
947
+ ### Bug fixes
948
+
949
+ - Fix geo shapes with text not being resizable to a smaller size. ([#7878](https://github.com/tldraw/tldraw/pull/7878))
950
+ - Fix shapes exploding when resizing unaligned arrows. ([#7855](https://github.com/tldraw/tldraw/pull/7855))
951
+ - Fix Safari pinch zoom resetting selection to previous shapes. ([#7777](https://github.com/tldraw/tldraw/pull/7777))
952
+ - Fix toggle-lock action firing when no shapes are selected. ([#7815](https://github.com/tldraw/tldraw/pull/7815))
953
+ - Fix menu items (zoom to selection, cut, copy, delete) being enabled when not in select tool. ([#7811](https://github.com/tldraw/tldraw/pull/7811))
954
+ - Fix excessive tab indentation in text shapes (now 2 spaces instead of 8). ([#7796](https://github.com/tldraw/tldraw/pull/7796))
955
+ - Fix canvas-in-front elements (cursors, following indicators) appearing in front of UI panels instead of behind them. ([#7865](https://github.com/tldraw/tldraw/pull/7865))
956
+ - Fix license console message colors for warnings and errors. ([#7850](https://github.com/tldraw/tldraw/pull/7850))
957
+ - Fix asset resolution being delayed by 500ms when updating an image shape's asset. ([#7612](https://github.com/tldraw/tldraw/pull/7612))
958
+ - Fix Durable Object SQLite migration in the multiplayer Cloudflare template. ([#7829](https://github.com/tldraw/tldraw/pull/7829), [#7832](https://github.com/tldraw/tldraw/pull/7832), [#7834](https://github.com/tldraw/tldraw/pull/7834), [#7835](https://github.com/tldraw/tldraw/pull/7835))
959
+ - Fix `zoomToFit` and `getCurrentPageBounds` to ignore hidden shapes when computing bounds. ([#7770](https://github.com/tldraw/tldraw/pull/7770))
960
+ - Fix collaborator shape indicators not rendering after the canvas indicator change. ([#7759](https://github.com/tldraw/tldraw/pull/7759))
961
+ - Fix rich text content not updating correctly with message squashing due to reference comparison. ([#7758](https://github.com/tldraw/tldraw/pull/7758))
962
+ - Fix keyboard shortcut menu item labels to use consistent ellipsis formatting. ([#7757](https://github.com/tldraw/tldraw/pull/7757))
963
+ - Fix spatial index not removing shapes when moved to a different page. ([#7700](https://github.com/tldraw/tldraw/pull/7700))
964
+ - Fix tldraw failing to load in CJS environments (tsx, ts-node, Jest) due to ESM-only rbush dependency. ([#7905](https://github.com/tldraw/tldraw/pull/7905))
965
+
966
+ ---
967
+
968
+ ### Patch releases
969
+
970
+ #### v4.4.1
971
+
972
+ - Fix tooltip positioning when tldraw is rendered inside a container with CSS transforms. ([#8171](https://github.com/tldraw/tldraw/pull/8171))
973
+
974
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.4.1)
975
+
976
+ ## v4.3.0
977
+
978
+ [View on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.3.0)
979
+
980
+ This release introduces several significant changes: a new pattern for defining custom shape/binding typings, pluggable storage for `TLSocketRoom` with a new SQLite option, reactive `editor.inputs`, and optimized draw shape encoding. It also adds various other API improvements, performance optimizations, and bug fixes, including better support for React 19.
981
+
982
+ ---
983
+
984
+ #### 💥 New pattern for defining custom shape/binding types ([#7091](https://github.com/tldraw/tldraw/pull/7091))
985
+
986
+ We've improved the developer experience of working with custom shape and binding types. There's now less boilerplate and fewer gotchas when using tldraw APIs in a type-safe manner.
987
+
988
+ This is a minor breaking change at the type level—your code will still run, but you'll get TypeScript errors until you migrate.
989
+
990
+ <details>
991
+ <summary>Migration guide</summary>
992
+
993
+ When _declaring_ types for custom shapes, you can now use TypeScript's module augmentation feature to provide more specific types for the custom shape.
994
+
995
+ Before:
996
+
997
+ ```ts
998
+ import { TLBaseShape } from 'tldraw'
999
+
1000
+ // Shapes were defined by using the helper TLBaseShape type
1001
+ type MyShape = TLBaseShape`<'my-shape', { w: number; h: number; text: string }>`
1002
+ ```
1003
+
1004
+ After:
1005
+
1006
+ ```ts
1007
+ import { TLShape } from 'tldraw'
1008
+
1009
+ const MY_SHAPE = 'my-shape'
1010
+
1011
+ // We now use TypeScript's module augmentation feature to allow
1012
+ // extending the builtin TLShape type.
1013
+ declare module 'tldraw' {
1014
+ export interface TLGlobalShapePropsMap {
1015
+ [MY_SHAPE]: { w: number; h: number; text: string }
1016
+ }
1017
+ }
1018
+
1019
+ type MyShape = TLShape`<typeof MY_SHAPE>`
1020
+ ```
1021
+
1022
+ The benefit of this new system is that Editor APIs such as `createShape` now know about your custom shapes automatically:
1023
+
1024
+ ```ts
1025
+ // Just works - TypeScript validates props and provides autocomplete
1026
+ editor.createShape({ type: 'my-shape', props: { w: 100, h: 100, text: 'Hello' } })
1027
+
1028
+ // Will cause a TypeScript error for `text`
1029
+ editor.createShape({ type: 'my-shape', props: { w: 100, h: 100, text: 123 } })
1030
+ ```
1031
+
1032
+ The same pattern applies to custom bindings — augment `TLGlobalBindingPropsMap` and use `TLBinding<'binding-name'>`:
1033
+
1034
+ ```ts
1035
+ declare module 'tldraw' {
1036
+ export interface TLGlobalBindingPropsMap {
1037
+ 'my-binding': { offset: number }
1038
+ }
1039
+ }
1040
+
1041
+ type MyBinding = TLBinding`<'my-binding'>`
1042
+ ```
1043
+
1044
+ See the [Custom Shapes Guide](https://tldraw.dev/docs/shapes#custom-shapes) and the [Pin Bindings example](https://github.com/tldraw/tldraw/tree/main/apps/examples/src/examples/shapes/tools/pin-bindings) for details.
1045
+
1046
+ **After registering, remove the `TLBaseShape` import** — it's no longer used and will trip lint rules that flag unused imports.
1047
+
1048
+ **Shape type names are global.** `TLGlobalShapePropsMap` is a single shared registry, so two custom shapes that previously used the same type name in different files now collide. Pick a unique name for each, and remember the rename ripples beyond the type alias:
1049
+
1050
+ - `static override type = '...'` on the `ShapeUtil` subclass
1051
+ - Every `editor.createShape({ type: '...' })` and `editor.updateShape({ type: '...' })` call site
1052
+ - The `TLGlobalShapePropsMap` entry itself
1053
+ - Any persisted snapshot or migration JSON that references the old name
1054
+
1055
+ **Use `as const` on the static `type` field.** TypeScript may widen `static override type = 'my-shape'` to `string`, which fails the new constraint. Add `as const` to keep it a string literal:
1056
+
1057
+ ```ts
1058
+ class MyShapeUtil extends ShapeUtil`<MyShape>` {
1059
+ static override type = 'my-shape' as const
1060
+ // ...
1061
+ }
1062
+ ```
1063
+
1064
+ The same fix applies to `BaseBoxShapeTool` (and other tool) subclasses, which expose `static override shapeType = '...'`. If you see TS2416 on a tool's `shapeType`, add `as const` there too. The two fields are easy to confuse — check both.
1065
+
1066
+ **Heterogeneous `createShapes`/`updateShapes` arrays may need a cast.** Because `TLShape` is now a discriminated union over the global props map, a mapped array of mixed shape types no longer narrows automatically. For homogeneous arrays where every item shares one shape type, `as const` on the `type` field in the mapped object literal is enough. For genuinely heterogeneous arrays, go straight to `as TLShapePartial[]` (or `as TLCreateShapePartial[]` for `createShapes`):
1067
+
1068
+ ```ts
1069
+ // Heterogeneous update — the union doesn't narrow
1070
+ editor.updateShapes(
1071
+ shapes.map((s) => ({ id: s.id, type: s.type, x: s.x + 10 })) as TLShapePartial[]
1072
+ )
1073
+ ```
1074
+
1075
+ Don't reach for `satisfies TLShapePartial` here — `TLShapePartial` is distributive over the `TLShape` union, so `satisfies` enforces a literal-per-variant constraint that mapped-over heterogeneous shapes can't meet. The cast is the right tool for this specific shape of code.
1076
+
1077
+ </details>
1078
+
1079
+ (contributed by [@Andarist](https://github.com/Andarist))
1080
+
1081
+ ---
1082
+
1083
+ #### Pluggable storage for TLSocketRoom + SQLite support ([#7320](https://github.com/tldraw/tldraw/pull/7320), [#7123](https://github.com/tldraw/tldraw/pull/7123))
1084
+
1085
+ We've refactored the `TLSocketRoom` API to support a pluggable storage layer. We're providing two implementations:
1086
+
1087
+ - **`SQLiteSyncStorage`** – Automatically persists room state to SQLite. Recommended for production.
1088
+ - **`InMemorySyncStorage`** – Keeps state in memory with manual persistence via callbacks (previous built-in behavior).
1089
+
1090
+ **We recommend switching to `SQLiteSyncStorage` if your environment supports SQLite** (Cloudflare Durable Objects, Node.js, Bun, Deno). It provides automatic persistence, lower memory usage, and faster startup times.
1091
+
1092
+ <details>
1093
+ <summary>Why SQLite?</summary>
1094
+
1095
+ - **Automatic persistence**: Data survives process restarts without manual snapshot handling
1096
+ - **Lower memory usage**: No need to keep entire documents in memory
1097
+ - **Faster startup**: No need to load the document into memory before accepting socket connections
1098
+ - **Simpler code**: No more `onChange` callbacks and manual persistence logic
1099
+
1100
+ </details>
1101
+
1102
+ <details>
1103
+ <summary>Platform support</summary>
1104
+
1105
+ | Platform | Wrapper | SQLite Library |
1106
+ | -------------------------- | -------------------------------- | --------------------------------- |
1107
+ | Cloudflare Durable Objects | `DurableObjectSqliteSyncWrapper` | Built-in `ctx.storage` |
1108
+ | Node.js/Deno | `NodeSqliteWrapper` | `better-sqlite3` or `node:sqlite` |
1109
+
1110
+ See the [Cloudflare template](https://github.com/tldraw/tldraw-sync-cloudflare) and the [Node server example](https://github.com/tldraw/tldraw/tree/main/templates/simple-server-example) respectively. Bun support should be straightforward to add.
1111
+
1112
+ </details>
1113
+
1114
+ <details>
1115
+ <summary>Migration guide</summary>
1116
+
1117
+ Existing code continues to work, however we have deprecated the following `TLSocketRoom` options:
1118
+
1119
+ - `initialSnapshot`
1120
+ - `onDataChange`
1121
+
1122
+ These are replaced by the new `storage` option. We've also deprecated the `TLSocketRoom.updateStore` method, which has been supplanted by `storage.transaction`.
1123
+
1124
+ Before:
1125
+
1126
+ ```ts
1127
+ const existingSnapshot = loadExistingSnapshot()
1128
+
1129
+ const room = new TLSocketRoom({
1130
+ initialSnapshot: existingSnapshot,
1131
+ onDataChange: () => {
1132
+ persistSnapshot(room.getCurrentSnapshot())
1133
+ },
1134
+ })
1135
+ ```
1136
+
1137
+ If you want to keep the same behavior with in-memory document storage and manual persistence:
1138
+
1139
+ ```ts
1140
+ import { InMemorySyncStorage, TLSocketRoom } from '@tldraw/sync-core'
1141
+
1142
+ const room = new TLSocketRoom({
1143
+ storage: new InMemorySyncStorage({
1144
+ snapshot: existingSnapshot,
1145
+ onChange() {
1146
+ saveToDatabase(storage.getSnapshot())
1147
+ },
1148
+ }),
1149
+ })
1150
+ ```
1151
+
1152
+ However, we recommend switching to SQLite. Users of our Cloudflare template should follow the migration guide on the [sync docs page](https://tldraw.dev/docs/sync).
1153
+
1154
+ If you're using `TLSocketRoom` on Node, creating the room should end up looking something like this:
1155
+
1156
+ ```ts
1157
+ import Database from 'better-sqlite3'
1158
+ import { SQLiteSyncStorage, NodeSqliteWrapper, TLSocketRoom, RoomSnapshot } from '@tldraw/sync-core'
1159
+
1160
+ async function createRoom(roomId: string) {
1161
+ const db = new Database(`path/to/${roomId}.db`)
1162
+ const sql = new NodeSqliteWrapper(db)
1163
+ let snapshot: RoomSnapshot | undefined = undefined
1164
+ if (!SQLiteSyncStorage.hasBeenInitialized(sql)) {
1165
+ // This db hasn't been used before, so if it's a pre-existing
1166
+ // document, load the legacy room snapshot
1167
+ snapshot = await loadExistingSnapshot()
1168
+ }
1169
+
1170
+ const storage = new SQLiteSyncStorage({ sql, snapshot })
1171
+ return new TLSocketRoom({
1172
+ storage,
1173
+ onSessionRemoved(room, args) {
1174
+ if (args.numSessionsRemaining === 0) {
1175
+ room.close()
1176
+ db.close()
1177
+ }
1178
+ },
1179
+ })
1180
+ }
1181
+ ```
1182
+
1183
+ </details>
1184
+
1185
+ ---
1186
+
1187
+ #### Optimized draw shape encoding ([#7364](https://github.com/tldraw/tldraw/pull/7364), [#7710](https://github.com/tldraw/tldraw/pull/7710))
1188
+
1189
+ Draw and highlight shape point data is now stored using a compact delta-encoded binary format instead of JSON arrays. This reduces storage size by approximately 80% while preserving stroke fidelity.
1190
+
1191
+ <details>
1192
+ <summary>Breaking change details</summary>
1193
+
1194
+ If you were reading or writing draw shape data programatically you might need to update your code to use the new format.
1195
+
1196
+ - `TLDrawShapeSegment.points` renamed to `.path` and changed from `VecModel[]` to `string` (base64-encoded)
1197
+ - Added `scaleX` and `scaleY` properties to draw and highlight shapes
1198
+ - New exports: `b64Vecs` encoding utilities, e.g. `getPointsFromDrawSegment` helper. Use this if you need to manually read/write point data.
1199
+
1200
+ Existing documents are automatically migrated.
1201
+
1202
+ </details>
1203
+
1204
+ ---
1205
+
1206
+ #### Reactive inputs ([#7312](https://github.com/tldraw/tldraw/pull/7312))
1207
+
1208
+ Refactored `editor.inputs` to use reactive atoms via the new `InputsManager` class. All input state is now accessed via getter methods (e.g., `editor.inputs.getCurrentPagePoint()`, `editor.inputs.getShiftKey()`). Direct property access is deprecated but still supported for backwards compatibility.
1209
+
1210
+ ### API changes
1211
+
1212
+ - 💥 **`DefaultTopPanel`** export removed from `tldraw`. The top panel component for displaying the offline indicator is now handled internally by `PeopleMenu`. ([#7568](https://github.com/tldraw/tldraw/pull/7568))
1213
+ - 💥 **`TextDirection`** export removed from `tldraw`. Use TipTap's native `TextDirection` extension instead. The `richTextValidator` now includes an optional `attrs` property - a migration may be necessary for older clients/custom shapes. ([#7304](https://github.com/tldraw/tldraw/pull/7304))
1214
+ - Add `tlenvReactive` atom to `@tldraw/editor` for reactive environment state tracking, including coarse pointer detection that updates when users switch between mouse and touch input. ([#7296](https://github.com/tldraw/tldraw/pull/7296))
1215
+ - Add `hideAllTooltips()` helper function for programmatically dismissing tooltips. ([#7288](https://github.com/tldraw/tldraw/pull/7288))
1216
+ - Add `zoomToFitPadding` option to `TldrawOptions` to customize the default padding used by zoom-to-fit operations. ([#7602](https://github.com/tldraw/tldraw/pull/7602))
1217
+ - Add `snapThreshold` option to `TldrawOptions` for configuring the snap distance, defaulting to 8 screen pixels. ([#7543](https://github.com/tldraw/tldraw/pull/7543))
1218
+ - Add `resizeChildren` configuration option to `FrameShapeUtil` to allow frame children to be resized proportionally when the frame is resized. ([#7526](https://github.com/tldraw/tldraw/pull/7526))
1219
+ - Add `Editor.canEditShape()` and `Editor.canCropShape()` methods to centralize shape permission checks. Add `ShapeUtil.canEditWhileLocked()` for shapes that remain editable when locked. ([#7361](https://github.com/tldraw/tldraw/pull/7361))
1220
+ - Add `editor.getDebouncedZoomLevel()` and `editor.getEfficientZoomLevel()` methods for improved zoom performance on dense canvases. Add `debouncedZoom` and `debouncedZoomThreshold` options. ([#7235](https://github.com/tldraw/tldraw/pull/7235))
1221
+ - Add configurable `showTextOutline` option to `TextShapeUtil`, `ArrowShapeUtil`, and `GeoShapeUtil` via `.configure()` pattern. ([#7314](https://github.com/tldraw/tldraw/pull/7314))
1222
+ - Export freehand stroke utilities: `getStroke`, `getStrokeOutlinePoints`, and `setStrokePointRadii`. ([#7400](https://github.com/tldraw/tldraw/pull/7400)) (contributed by [@VimHax](https://github.com/VimHax))
1223
+ - Add `Box.isValid()` method to check for finite coordinates. ([#7532](https://github.com/tldraw/tldraw/pull/7532))
1224
+ - Add `spacebarPanning` option to control whether spacebar activates pan mode. ([#7312](https://github.com/tldraw/tldraw/pull/7312))
1225
+ - Introduce pluggable `TLSyncStorage` API for `TLSocketRoom`. The `initialSnapshot` and `onDataChange` options are now deprecated in favor of the new `storage` option. ([#7123](https://github.com/tldraw/tldraw/pull/7123))
1226
+ - Export `DefaultLabelColorStyle` which is necessary for rich text in custom shapes. ([#7114](https://github.com/tldraw/tldraw/pull/7114))
1227
+
1228
+ #### Improvements
1229
+
1230
+ - Improve coarse pointer detection by replacing CSS media queries with a reactive `data-coarse` attribute that updates when users switch between mouse and touch input. ([#7404](https://github.com/tldraw/tldraw/pull/7404))
1231
+ - Add CSS containment to main toolbar and text measurement element for improved rendering performance. ([#7406](https://github.com/tldraw/tldraw/pull/7406)) ([#7407](https://github.com/tldraw/tldraw/pull/7407))
1232
+ - Improve cross-realm support by scoping canvas event listeners to the editor container's ownerDocument. ([#7113](https://github.com/tldraw/tldraw/pull/7113))
1233
+ - Simplify ImmutableMap implementation for better code clarity. ([#7431](https://github.com/tldraw/tldraw/pull/7431))
1234
+ - Improve code readability in number validator by using `Number.isFinite()` instead of arithmetic trick. ([#7374](https://github.com/tldraw/tldraw/pull/7374))
1235
+ - Upgrade to React 19 with all necessary type and configuration changes for compatibility. ([#7317](https://github.com/tldraw/tldraw/pull/7317))
1236
+ - Improve signal graph traversal performance by eliminating per-recursion closure allocations. ([#7430](https://github.com/tldraw/tldraw/pull/7430))
1237
+ - Optimize object utility functions. ([#7432](https://github.com/tldraw/tldraw/pull/7432))
1238
+ - Use in-place sorting in parentsToChildren derivation. ([#7433](https://github.com/tldraw/tldraw/pull/7433))
1239
+ - Optimize notVisibleShapes derivation with inlined bounds checks. ([#7429](https://github.com/tldraw/tldraw/pull/7429))
1240
+ - Cache label size measurements with WeakCache for improved geo shape performance. ([#7412](https://github.com/tldraw/tldraw/pull/7412))
1241
+ - Optimize validators with fast paths and production inlining. ([#7373](https://github.com/tldraw/tldraw/pull/7373))
1242
+
1243
+ #### Bug fixes
1244
+
1245
+ - Fix migrations for draw and highlight shapes to be idempotent, preventing errors when migrations run multiple times. ([#7389](https://github.com/tldraw/tldraw/pull/7389))
1246
+ - Fix dot detection in draw and highlight shapes after the point compression change. ([#7365](https://github.com/tldraw/tldraw/pull/7365))
1247
+ - Fix clicking a shape's text label while editing to re-focus the input and select all text. ([#7342](https://github.com/tldraw/tldraw/pull/7342))
1248
+ - Fix pasting at cursor to correctly account for frames and parent containers. ([#7277](https://github.com/tldraw/tldraw/pull/7277))
1249
+ - Fix editing mode to exit when dragging causes the text input to blur. ([#7291](https://github.com/tldraw/tldraw/pull/7291))
1250
+ - Fix CommonJS build issues with TipTap imports in rich text module. ([#7282](https://github.com/tldraw/tldraw/pull/7282))
1251
+ - Fix iOS automatically zooming in on input fields by ensuring 16px minimum font size. ([#7118](https://github.com/tldraw/tldraw/pull/7118))
1252
+ - Fix `distanceToLineSegment` returning squared distance instead of actual distance, causing hit testing (eraser, scribble select) to be too strict. ([#7610](https://github.com/tldraw/tldraw/pull/7610)) (contributed by [@arpit-goblins](https://github.com/arpit-goblins))
1253
+ - Fix `zoomToSelection` to toggle between 100% zoom and zoom-to-fit behavior. ([#7536](https://github.com/tldraw/tldraw/pull/7536))
1254
+ - Fix export of SVG markers by handling fragment-only URLs correctly. ([#7506](https://github.com/tldraw/tldraw/pull/7506)) (contributed by [@PidgeyBE](https://github.com/PidgeyBE))
1255
+ - Restore wheel and pinch canvas event emission. ([#6834](https://github.com/tldraw/tldraw/pull/6834)) (contributed by [@swdev33](https://github.com/swdev33))
1256
+ - Fix context menu submenu flickering when hovered. ([#6837](https://github.com/tldraw/tldraw/pull/6837)) (contributed by [@swdev33](https://github.com/swdev33))
1257
+ - Fix rotated shape positions not being restored after flipping twice. ([#7359](https://github.com/tldraw/tldraw/pull/7359))
1258
+ - Fix keyboard shortcuts and clipboard events not working when `hideUi` is true. ([#7367](https://github.com/tldraw/tldraw/pull/7367))
1259
+ - Fix elbow arrows routing incorrectly when using dynamic sizing at high zoom levels. ([#7424](https://github.com/tldraw/tldraw/pull/7424))
1260
+ - Allow fullscreen for embed shapes. ([#7417](https://github.com/tldraw/tldraw/pull/7417))
1261
+ - Move mobile rotate handle to bottom for image and video shapes to accommodate the contextual toolbar. ([#6727](https://github.com/tldraw/tldraw/pull/6727))
1262
+ - Fix dropdown menu items incorrectly displaying an icon on the right side. ([#7533](https://github.com/tldraw/tldraw/pull/7533))
1263
+ - Fix zoom menu showing debounced zoom level for canvases with many shapes. ([#7626](https://github.com/tldraw/tldraw/pull/7626))
1264
+ - Fix extra line appearing after bullet and ordered lists in text shapes. ([#7643](https://github.com/tldraw/tldraw/pull/7643)) (contributed by [@sahiee-dev](https://github.com/sahiee-dev))
1265
+ - Fix "Back to content" button not appearing when selected shapes are off-screen. ([#7649](https://github.com/tldraw/tldraw/pull/7649))
1266
+ - Fix dotted freehand lines becoming invisible at minimum zoom on Chrome. ([#7650](https://github.com/tldraw/tldraw/pull/7650))
1267
+ - Fix menu bar stretching to full width on mobile viewports instead of fitting content. ([#7568](https://github.com/tldraw/tldraw/pull/7568))
1268
+
1269
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.3.0)
1270
+
1271
+ ---
1272
+
1273
+ ### Patch releases
1274
+
1275
+ #### v4.3.1
1276
+
1277
+ - Fix draw shape precision issues at high canvas coordinates by switching to delta encoding with a Float32 anchor point. ([#7710](https://github.com/tldraw/tldraw/pull/7710))
1278
+
1279
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.3.1)
1280
+
1281
+ #### v4.3.2
1282
+
1283
+ - Fix crash when cropping custom shapes that don't include `isCircle` in their crop schema. ([#7931](https://github.com/tldraw/tldraw/pull/7931))
1284
+
1285
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.3.2)
1286
+
1287
+ ## v4.2.0
1288
+
1289
+ This month's release includes many bug fixes and small API additions, along with a major version bump of our TipTap rich text editor.
1290
+
1291
+ ### What's new
1292
+
1293
+ #### 💥 TipTap v3 ([#5717](https://github.com/tldraw/tldraw/pull/5717))
1294
+
1295
+ We've upgraded TipTap from v2 to v3. If you've done any customization to our standard TipTap kit, please refer to TipTap's guide [How to upgrade Tiptap v2 to v3](https://tiptap.dev/docs/guides/upgrade-tiptap-v2) for breaking changes you might experience.
1296
+
1297
+ <details>
1298
+ <summary>Migration guide</summary>
1299
+
1300
+ Starting in v4.2, tldraw bundles TipTap v3 as a transitive dependency. If your project pins `@tiptap/*` v2 packages directly, upgrade them to v3 *before* trying to fix any code-level errors — leaving v2 in place produces a dual install that surfaces as confusing type errors.
1301
+
1302
+ **Dual-install symptom.** Deeply-nested errors like *"Property 'getCharacterCount' is missing in type 'Editor' but required in type 'Editor'"*, with the two `Editor` types resolving to different paths (one under `node_modules/@tiptap/core`, the other under `node_modules/@tldraw/editor/node_modules/@tiptap/core`), are not API changes — they are the v2/v3 dual install. The `Editor` classes are structurally similar but nominally different. Finishing the v3 upgrade collapses the duplicate and these errors disappear without code changes.
1303
+
1304
+ **Code-level changes that affect tldraw users:**
1305
+
1306
+ - **Default → named exports.** Several extensions changed from default to named exports:
1307
+
1308
+ ```ts
1309
+ // Before
1310
+ import StarterKit from '@tiptap/starter-kit'
1311
+
1312
+ // After
1313
+ import { StarterKit } from '@tiptap/starter-kit'
1314
+ ```
1315
+
1316
+ - **`TextStyle` → `TextStyleKit`, and `FontFamily` moved.** The `FontFamily` extension is no longer in `@tiptap/extension-font-family`; it's part of `TextStyleKit` in `@tiptap/extension-text-style`. The `setFontFamily` and `setFontSize` chain commands only exist on `TextStyleKit`, not on bare `TextStyle`.
1317
+
1318
+ - **Transaction handler types.** Inline parameter type annotations on TipTap event handlers no longer work. Import the proper event-map type:
1319
+
1320
+ ```ts
1321
+ import { EditorEvents } from '@tiptap/core'
1322
+ // ...
1323
+ onTransaction: (props: EditorEvents['transaction']) => { /* ... */ }
1324
+ ```
1325
+
1326
+ - **Custom chained commands** still register via `declare module '@tiptap/core'` augmentation in v3 — the augmentation target is the same.
1327
+
1328
+ </details>
1329
+
1330
+ ### API changes
1331
+
1332
+ - Add `Editor.setTool`/`Editor.removeTool` for dynamically altering the editor's tool state chart. ([#6909](https://github.com/tldraw/tldraw/pull/6909)) ([#7134](https://github.com/tldraw/tldraw/pull/7134))
1333
+ - Allow using custom socket implementations with `useSync` via a new `connect` option. ([#6859](https://github.com/tldraw/tldraw/pull/6859)) (contributed by [@Digital39999](https://github.com/Digital39999))
1334
+ - Add support for nested property queries in the store. ([#6981](https://github.com/tldraw/tldraw/pull/6981))
1335
+ - Add `createBookmarkFromUrl` helper for easier bookmark shape creation. ([#6894](https://github.com/tldraw/tldraw/pull/6894))
1336
+ - Add custom reference points for handle angle snapping. ([#6987](https://github.com/tldraw/tldraw/pull/6987)) (contributed by [@naaa760](https://github.com/naaa760))
1337
+ - Add new "lined-fill" style, accessible via Option+Shift+F. ([#7034](https://github.com/tldraw/tldraw/pull/7034))
1338
+ - Add `onInteractionEnd` callback option. ([#6919](https://github.com/tldraw/tldraw/pull/6919))
1339
+ - Add `allowReferrer` option for window opening functions. ([#7004](https://github.com/tldraw/tldraw/pull/7004))
1340
+ - Remove defunct Excalidraw embed definition. ([#6897](https://github.com/tldraw/tldraw/pull/6897))
1341
+
1342
+ ### Improvements
1343
+
1344
+ - Use window.prompt for renaming frames on mobile. ([#6838](https://github.com/tldraw/tldraw/pull/6838))
1345
+ - Optimize string append operations in sync protocol. ([#7007](https://github.com/tldraw/tldraw/pull/7007)) (contributed by [@quasor](https://github.com/quasor))
1346
+
1347
+ ### Bug fixes
1348
+
1349
+ - Fix Replit embed URL handling. ([#6892](https://github.com/tldraw/tldraw/pull/6892))
1350
+ - Fix accessibility issue that caused a misleading warning in the console. ([#6904](https://github.com/tldraw/tldraw/pull/6904))
1351
+ - Fix convert-to-bookmark action. ([#6894](https://github.com/tldraw/tldraw/pull/6894))
1352
+ - Fix dropdown menu pointer handling. ([#7021](https://github.com/tldraw/tldraw/pull/7021))
1353
+ - Fix iOS Safari image uploads. ([#7037](https://github.com/tldraw/tldraw/pull/7037))
1354
+ - Fix Alt+Tab conflict on Windows. ([#7005](https://github.com/tldraw/tldraw/pull/7005))
1355
+ - Fix text focus issues. ([#7043](https://github.com/tldraw/tldraw/pull/7043))
1356
+ - Fix `TldrawEditor` usability without `TldrawUiContextProvider`. ([#7053](https://github.com/tldraw/tldraw/pull/7053))
1357
+ - Fix cross-realm clipboard functionality. ([#7026](https://github.com/tldraw/tldraw/pull/7026))
1358
+ - Fix iOS ink rendering via coalesced events. ([#6917](https://github.com/tldraw/tldraw/pull/6917))
1359
+ - Fix menu-open dragging behavior. ([#6918](https://github.com/tldraw/tldraw/pull/6918))
1360
+
1361
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.2.0)
1362
+
1363
+ ---
1364
+
1365
+ ### Patch releases
1366
+
1367
+ #### v4.2.1
1368
+
1369
+ - Fix CommonJS/cjs builds that were broken in v4.2.0. ([#7282](https://github.com/tldraw/tldraw/pull/7282))
1370
+
1371
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.2.1)
1372
+
1373
+ ## v4.1.0
1374
+
1375
+ This month's release introduces a new shader starter kit for WebGL integration, along with API additions for embed control, minimap filtering, and localStorage-backed atoms.
1376
+
1377
+ ### What's new
1378
+
1379
+ #### Shader starter kit ([#6847](https://github.com/tldraw/tldraw/pull/6847))
1380
+
1381
+ A new template demonstrating WebGL shader integration with tldraw for dynamic, interactive backgrounds that respond to canvas interactions. Includes four complete examples:
1382
+
1383
+ - **Fluid simulation** - Navier-Stokes dynamics
1384
+ - **Rainbow** - Animated gradients
1385
+ - **Shadows** - Raymarching and signed distance fields
1386
+ - **Minimal** - Bare-bones template for custom shaders
1387
+
1388
+ Features configurable parameters, localStorage persistence, and full TypeScript support.
1389
+
1390
+ ### API changes
1391
+
1392
+ - Add `embedOnPaste` option to `EmbedDefinition` for opting out of automatic embed-on-paste behavior. ([#6874](https://github.com/tldraw/tldraw/pull/6874))
1393
+ - Add `hideInMinimap` option to `ShapeUtil` for excluding shapes from the minimap. ([#6327](https://github.com/tldraw/tldraw/pull/6327))
1394
+ - Add `snapType?: 'point' | 'align'` to `TLHandle` for finer control over handle snapping. The `canSnap` property is now deprecated. ([#6883](https://github.com/tldraw/tldraw/pull/6883))
1395
+ - Expose `Editor#getShapePageBounds` and `isRecordsDiffEmpty` as public methods. ([#6871](https://github.com/tldraw/tldraw/pull/6871))
1396
+ - Add `localStorageAtom` to `@tldraw/state` for atoms backed by localStorage with cross-tab syncing. ([#6876](https://github.com/tldraw/tldraw/pull/6876))
1397
+ - Add inline style picker component variants. ([#6920](https://github.com/tldraw/tldraw/pull/6920))
1398
+
1399
+ ### Improvements
1400
+
1401
+ - Make bookmark titles clickable. ([#6326](https://github.com/tldraw/tldraw/pull/6326))
1402
+ - Optimize mobile top bar rendering. ([#6895](https://github.com/tldraw/tldraw/pull/6895))
1403
+ - Add numpad Enter support for entering edit mode. ([#6830](https://github.com/tldraw/tldraw/pull/6830))
1404
+ - Consolidate preferences menu items. ([#6802](https://github.com/tldraw/tldraw/pull/6802))
1405
+
1406
+ ### Bug fixes
1407
+
1408
+ - Fix accessibility shortcut typo. ([#6811](https://github.com/tldraw/tldraw/pull/6811))
1409
+ - Fix focus mode action missing. ([#6812](https://github.com/tldraw/tldraw/pull/6812))
1410
+ - Fix arrow rendering edge case. ([#6799](https://github.com/tldraw/tldraw/pull/6799))
1411
+ - Fix empty window opening on anchor click. ([#6817](https://github.com/tldraw/tldraw/pull/6817))
1412
+ - Fix missing translation key. ([#6826](https://github.com/tldraw/tldraw/pull/6826))
1413
+ - Fix shape index race condition. ([#6884](https://github.com/tldraw/tldraw/pull/6884))
1414
+ - Fix zero geometry vertices edge case. ([#6885](https://github.com/tldraw/tldraw/pull/6885))
1415
+ - Fix style panel button overflow. ([#6920](https://github.com/tldraw/tldraw/pull/6920))
1416
+
1417
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.1.0)
1418
+
1419
+ ---
1420
+
1421
+ ### Patch releases
1422
+
1423
+ #### v4.1.1
1424
+
1425
+ - Update the formatting of the `npm create tldraw` command in the CLI output.
1426
+
1427
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.1.1)
1428
+
1429
+ #### v4.1.2
1430
+
1431
+ - Move `InFrontOfTheCanvas` component back out of the `.tl-canvas` element. ([#7021](https://github.com/tldraw/tldraw/pull/7021))
1432
+
1433
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.1.2)
1434
+
1435
+ ## v4.0.0
1436
+
1437
+ This major release introduces new starter kits, a CLI tool, WCAG 2.2 Level AA accessibility compliance, and significant API enhancements for building custom canvas applications.
1438
+
1439
+ ### What's new
1440
+
1441
+ #### npm create tldraw ([#6753](https://github.com/tldraw/tldraw/pull/6753))
1442
+
1443
+ A new CLI tool for quickly scaffolding tldraw projects. Run `npm create tldraw` to initialize projects using templates and starter kits.
1444
+
1445
+ #### Starter kits
1446
+
1447
+ Five new MIT-licensed starter kits demonstrate different applications of tldraw's canvas:
1448
+
1449
+ - **[agent](https://tldraw.dev/starter-kits/agent)** - Cursor-style chatbot interface where conversations occur on the canvas with AI assistance
1450
+ - **[workflow](https://tldraw.dev/starter-kits/workflow)** - Node-and-wire visual programming interface for automation workflows and state machines
1451
+ - **[branching-chat](https://tldraw.dev/starter-kits/branching-chat)** - Multi-path conversation explorer for managing conversation branches
1452
+ - **[chat](https://tldraw.dev/starter-kits/chat)** - Canvas-based image annotation with integrated chatbot
1453
+ - **[multiplayer](https://tldraw.dev/starter-kits/multiplayer)** - Collaborative whiteboard foundation built on tldraw sync
1454
+
1455
+ #### Licensing ([#6707](https://github.com/tldraw/tldraw/pull/6707))
1456
+
1457
+ Production deployments now require a license key. Development and localhost environments remain exempt. Available licenses include:
1458
+
1459
+ - Free 100-day trial license
1460
+ - Commercial license for commercial projects
1461
+ - Hobby license for non-commercial use
1462
+
1463
+ #### Accessibility ([#6695](https://github.com/tldraw/tldraw/pull/6695))
1464
+
1465
+ Achieves WCAG 2.2 Level AA compliance with an accessibility mode, improved keyboard shortcuts, comprehensive aria-labels, and scrollable menus.
1466
+
1467
+ #### Drag from toolbar ([#6681](https://github.com/tldraw/tldraw/pull/6681))
1468
+
1469
+ Create shapes by dragging directly from the toolbar, eliminating the click-then-draw workflow.
1470
+
1471
+ #### Custom shape clipping ([#6649](https://github.com/tldraw/tldraw/pull/6649))
1472
+
1473
+ Shapes can now clip their children, enabling complex visual hierarchies and container-style shapes.
1474
+
1475
+ #### Vertical toolbar support ([#6623](https://github.com/tldraw/tldraw/pull/6623))
1476
+
1477
+ The toolbar supports vertical orientation for alternative layout configurations.
1478
+
1479
+ #### Rich text arrows ([#6594](https://github.com/tldraw/tldraw/pull/6594))
1480
+
1481
+ Arrow labels support rich text formatting including bold, italic, and text styling.
1482
+
1483
+ ### API changes
1484
+
1485
+ - 💥 **CSS variables** now start with `--tl-` prefix. Update custom CSS: `--color-background` → `--tl-color-background`, `--space-4` → `--tl-space-4`. ([#6712](https://github.com/tldraw/tldraw/pull/6712))
1486
+ - 💥 **`Geometry2D.isLabel`** replaced with `excludeFromShapeBounds` flag. ([#6668](https://github.com/tldraw/tldraw/pull/6668))
1487
+ - 💥 **`open-url` event** now uses `destinationUrl` instead of `url`. ([#6641](https://github.com/tldraw/tldraw/pull/6641))
1488
+ - 💥 **Arrow shapes** now use `richText` instead of `text` property. Data migrates automatically, but direct access to `arrow.props.text` must update to `arrow.props.richText`. ([#6594](https://github.com/tldraw/tldraw/pull/6594))
1489
+ - 💥 **`@tldraw/ai` module** removed. Use the [agent starter kit](https://tldraw.dev/starter-kits/agent) instead.
1490
+ - 💥 **Event propagation behavior** changed. Use `editor.markEventAsHandled()` for custom event handling. ([#6592](https://github.com/tldraw/tldraw/pull/6592))
1491
+ - 💥 **Style panel** redesigned with legacy picker components removed. ([#6573](https://github.com/tldraw/tldraw/pull/6573))
1492
+ - 💥 **Toolbar CSS class names** updated for consistency. ([#6551](https://github.com/tldraw/tldraw/pull/6551))
1493
+ - Add custom messages in `TLSocketRoom` via `sendCustomMessage()` and `onCustomMessageReceived`. ([#6614](https://github.com/tldraw/tldraw/pull/6614)) (contributed by [@mootari](https://github.com/mootari))
1494
+ - Add `Editor.getShapesAtPoint()` with flexible margin options for precise hit testing. ([#6724](https://github.com/tldraw/tldraw/pull/6724))
1495
+ - Add `editor.toImageDataUrl()` for generating image data URLs directly from shapes. ([#6658](https://github.com/tldraw/tldraw/pull/6658))
1496
+ - Add `ShapeUtil.isExportBoundsContainer` and `canCull` methods for controlling export behavior and rendering optimization. ([#6649](https://github.com/tldraw/tldraw/pull/6649))
1497
+ - Add `EditorAtom` for managing UI state outside React components. ([#6687](https://github.com/tldraw/tldraw/pull/6687))
1498
+ - Add enhanced handle drag callbacks with timing events for custom drag interactions. ([#6702](https://github.com/tldraw/tldraw/pull/6702))
1499
+
1500
+ ### Bug fixes
1501
+
1502
+ - Fix arrow labels being cut off in exports. ([#6783](https://github.com/tldraw/tldraw/pull/6783))
1503
+ - Fix PNG physical pixel dimensions parsing. ([#6771](https://github.com/tldraw/tldraw/pull/6771))
1504
+ - Fix pointer events on mobile firing inconsistently. ([#6738](https://github.com/tldraw/tldraw/pull/6738))
1505
+ - Fix Chrome embed positioning at non-100% zoom levels. ([#6724](https://github.com/tldraw/tldraw/pull/6724))
1506
+ - Fix hollow shapes not being properly bound-to by arrows. ([#6705](https://github.com/tldraw/tldraw/pull/6705))
1507
+
1508
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.0.0)
1509
+
1510
+ ---
1511
+
1512
+ ### Patch releases
1513
+
1514
+ #### v4.0.1
1515
+
1516
+ - Fix template exports. ([#6804](https://github.com/tldraw/tldraw/pull/6804))
1517
+ - Fix documentation. ([#6805](https://github.com/tldraw/tldraw/pull/6805))
1518
+
1519
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.0.1)
1520
+
1521
+ #### v4.0.2
1522
+
1523
+ - Fix focus mode SDK issue that caused problems when using focus mode in the SDK. ([#6815](https://github.com/tldraw/tldraw/pull/6815))
1524
+
1525
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.0.2)
1526
+
1527
+ #### v4.0.3
1528
+
1529
+ - Add Claude 4.5 Sonnet to agent starter kit. ([#6852](https://github.com/tldraw/tldraw/pull/6852))
1530
+ - Ensure templates don't use internal functions. ([#6871](https://github.com/tldraw/tldraw/pull/6871))
1531
+
1532
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.0.3)
1533
+
1534
+ #### v4.0.4
1535
+
1536
+ - Fix shape index jitter for the first shape created, preventing potential index collisions. ([#6884](https://github.com/tldraw/tldraw/pull/6884))
1537
+
1538
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v4.0.4)
1539
+
1540
+ ## v3.15.0
1541
+
1542
+ This release introduces `npm create tldraw` for bootstrapping new projects, along with API additions, accessibility improvements, and performance optimizations.
1543
+
1544
+ ### What's new
1545
+
1546
+ #### npm create tldraw
1547
+
1548
+ Developers can now initialize new tldraw projects by running `npm create tldraw` in their terminal, selecting from available starter templates.
1549
+
1550
+ ### API changes
1551
+
1552
+ - Add handle interaction callbacks: `onHandleDragStart`, `onHandleDragEnd`, and cancellation callbacks (`onTranslateCancel`, `onResizeCancel`, `onRotateCancel`, `onHandleDragCancel`).
1553
+ - Add JSX icon support for custom icons in tool overrides, action overrides, buttons, and menu items.
1554
+ - Add `StateNode.addChild` method enabling dynamic tool functionality additions.
1555
+ - Convert `DefaultSpinner` component to SVG format, now accepts standard SVG properties.
1556
+ - Export `HeartToolbarItem` component.
1557
+
1558
+ ### Improvements
1559
+
1560
+ - Enhance "Select All" functionality to intelligently select within a shape's common parent context (e.g., selecting shapes within a frame without selecting the frame itself).
1561
+ - Add user preference option to disable keyboard shortcuts.
1562
+ - Prevent frame drops.
1563
+ - Optimize the `useValue` and `useReactor` hooks.
1564
+ - Enhance frame rendering efficiency.
1565
+ - Expand `aria-hidden` application.
1566
+ - Improve keyboard navigation.
1567
+ - Add proper `role="radiogroup"` assignment for toggle groups.
1568
+ - Correct aria slider values.
1569
+
1570
+ ### Bug fixes
1571
+
1572
+ - Fix HTML entity escaping in pasted content.
1573
+ - Fix text measurement accuracy.
1574
+ - Fix arrow rendering between circles.
1575
+ - Fix SVG text outline rendering.
1576
+ - Fix image toolbar camera movement interactions.
1577
+
1578
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.15.0)
1579
+
1580
+ ---
1581
+
1582
+ ### Patch releases
1583
+
1584
+ #### v3.15.1
1585
+
1586
+ - Fix room change event handling in the sync core library. ([#6543](https://github.com/tldraw/tldraw/pull/6543))
1587
+
1588
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.15.1)
1589
+
1590
+ #### v3.15.2
1591
+
1592
+ - Fix editor remounting in a loop when given custom assetUrls. ([#6605](https://github.com/tldraw/tldraw/pull/6605))
1593
+
1594
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.15.2)
1595
+
1596
+ #### v3.15.3
1597
+
1598
+ - Enhance callback functionality for shape utilities. ([#6634](https://github.com/tldraw/tldraw/pull/6634))
1599
+
1600
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.15.3)
1601
+
1602
+ #### v3.15.4
1603
+
1604
+ - Fix potential bug in TLSyncClient. ([#6660](https://github.com/tldraw/tldraw/pull/6660))
1605
+
1606
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.15.4)
1607
+
1608
+ #### v3.15.5
1609
+
1610
+ - Show license flags message as a warning. ([#6843](https://github.com/tldraw/tldraw/pull/6843))
1611
+ - Fix expired internal license verification. ([#6843](https://github.com/tldraw/tldraw/pull/6843))
1612
+
1613
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.15.5)
1614
+
1615
+ ## v3.14.0
1616
+
1617
+ This release introduces contextual toolbars for image and video shapes, enhanced cropping options, and a new PathBuilder API.
1618
+
1619
+ ### API changes
1620
+
1621
+ - 💥 **`Editor#getShapePageGeometry`** removed.
1622
+ - 💥 **`Editor#getShapesAtPoint`** now returns shapes in descending index order.
1623
+ - 💥 **Locked shapes** cannot be duplicated; pasting locked shapes unlocks them.
1624
+ - 💥 **`ShapeUtil.canDropShapes`** removed—drag-and-drop participation now requires implementing handlers.
1625
+ - Add `TldrawUiContextualToolbar` component enabling developers to create floating toolbars.
1626
+ - Add `PathBuilder` API for constructing tldraw-style inky and dashed SVGs.
1627
+ - Add arrow binding configuration for controlling when arrows should be exact and/or bind.
1628
+ - Add `measureScrollWidth` option for text measurement.
1629
+ - Add `defaultAutoplay` boolean property for `VideoShapeUtil`.
1630
+
1631
+ ### Improvements
1632
+
1633
+ - Add image and video contextual toolbar with floating controls for enhanced interaction.
1634
+ - Add download functionality for image and video shapes to download original files.
1635
+ - Add advanced image cropping options.
1636
+ - Improve context menu keyboard support.
1637
+ - Improve style panel keyboard navigation.
1638
+ - Improve focus management.
1639
+ - Optimize copy operations.
1640
+ - Optimize arrow rendering with labels.
1641
+ - Optimize shape resizing.
1642
+ - Optimize keyboard interactions.
1643
+ - Optimize arrow dragging.
1644
+ - Improve text measurement caching.
1645
+
1646
+ ### Bug fixes
1647
+
1648
+ - Fix page menu scrolling behavior.
1649
+ - Fix undo functionality for sticky creation.
1650
+ - Fix bookmark hyperlink handling.
1651
+ - Fix SVG output and vector calculations.
1652
+ - Fix frame resizing with multiple selections.
1653
+ - Fix HTML copy-paste positioning.
1654
+ - Fix keyboard shortcuts and text overflow issues.
1655
+
1656
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.14.0)
1657
+
1658
+ ---
1659
+
1660
+ ### Patch releases
1661
+
1662
+ #### v3.14.1
1663
+
1664
+ - Fix text measurement bug where styles could leak from one measurement to the next. ([#6388](https://github.com/tldraw/tldraw/pull/6388))
1665
+
1666
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.14.1)
1667
+
1668
+ #### v3.14.2
1669
+
1670
+ - Fix HTML entities being escaped in clipboard operations. ([#6396](https://github.com/tldraw/tldraw/pull/6396))
1671
+
1672
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.14.2)
1673
+
1674
+ ## v3.13.0
1675
+
1676
+ This release introduces elbow arrows for technical diagramming and continues accessibility improvements toward WCAG compliance.
1677
+
1678
+ ### What's new
1679
+
1680
+ #### Elbow arrows
1681
+
1682
+ The arrow shape now supports a new elbow connector style. These arrows travel between points using straight lines joined at right angles rather than curved paths, making them ideal for technical diagrams. Access this option through the arrow tool's line style settings.
1683
+
1684
+ ### API changes
1685
+
1686
+ - 💥 **`ShapeUtil.canEditInReadOnly`** renamed to `ShapeUtil.canEditInReadonly` (note capitalization change).
1687
+ - 💥 **Arrow target highlights** migrated from `setHintingShapes` to a custom `TldrawOverlays` component; users of `<TldrawEditor />` must pass this component to the `Overlays` slot.
1688
+ - Add text measurement API that accepts arbitrary style parameters.
1689
+ - Add new `Overlays` component for camera-following canvas overlays.
1690
+ - Add `hasCustomTabBehavior` prop to `RichTextLabel` for custom tab logic.
1691
+
1692
+ ### Improvements
1693
+
1694
+ - Auto-select link text when editing shape links.
1695
+ - Snap pasted text and embeds to grid when enabled.
1696
+ - Allow Figma embeds to work with selection links.
1697
+ - Show visual block indicating label placement when editing arrow labels.
1698
+ - Include background color in single frame exports.
1699
+ - Allow frames to be double-click resized to fit contents.
1700
+ - Allow style panel to focus with keyboard shortcut.
1701
+ - Add proper labels to more UI icons and handles.
1702
+ - Add container navigation shortcuts for moving selections in/out of frames and groups.
1703
+ - Make embed shapes keyboard-tabbable.
1704
+ - Add keyboard navigation to toolbars throughout the application.
1705
+ - Show rich text editing shortcuts in the help menu.
1706
+ - Improve performance of programmatic rotation of selected shapes.
1707
+ - Improve performance of multi-shape dragging operations.
1708
+ - Optimize selection evaluation to prevent unnecessary re-evaluations.
1709
+
1710
+ ### Bug fixes
1711
+
1712
+ - Fix flattened shape backgrounds.
1713
+ - Fix screenreader behavior.
1714
+ - Fix tool consistency.
1715
+ - Fix text rendering.
1716
+ - Fix selection accuracy.
1717
+ - Fix arrow flickering during rotation.
1718
+
1719
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.13.0)
1720
+
1721
+ ---
1722
+
1723
+ ### Patch releases
1724
+
1725
+ #### v3.13.1
1726
+
1727
+ - Show elbow arrow outline indicator on hover when creating elbow arrows. ([#6099](https://github.com/tldraw/tldraw/pull/6099))
1728
+
1729
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.13.1)
1730
+
1731
+ #### v3.13.2
1732
+
1733
+ - Fix LoadingScreen context bug where custom asset URL configuration was ignored. ([#6283](https://github.com/tldraw/tldraw/pull/6283))
1734
+
1735
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.13.2)
1736
+
1737
+ #### v3.13.3
1738
+
1739
+ - Fix overriding builtin tools not working. ([#6330](https://github.com/tldraw/tldraw/pull/6330))
1740
+
1741
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.13.3)
1742
+
1743
+ #### v3.13.4
1744
+
1745
+ - Fix cross-realm functionality issues. ([#6338](https://github.com/tldraw/tldraw/pull/6338))
1746
+
1747
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.13.4)
1748
+
1749
+ ## v3.12.0
1750
+
1751
+ This release focuses on accessibility improvements and API enhancements, with no breaking changes.
1752
+
1753
+ ### API changes
1754
+
1755
+ - Add new `getShapeVisibility` prop replacing the deprecated `isShapeHidden`, allowing hidden children to override parent visibility states.
1756
+ - Allow frames to display colorful borders and labels by configuring `FrameShapeUtil` with `showColors: true`.
1757
+ - Add `Geometry2d` helper methods including `intersectLineSegment`, `intersectCircle`, `transform`, and filtering options.
1758
+ - Export two Tiptap extensions individually for rich text customization.
1759
+
1760
+ ### Improvements
1761
+
1762
+ - Add keyboard-based selection movement between shapes using Tab and Cmd/Ctrl+Arrow keys.
1763
+ - Add screen reader announcements for tool and shape selection changes.
1764
+ - Add keyboard resizing capability via Cmd/Ctrl+Alt+Shift with +/- keys.
1765
+ - Improve semantic HTML5 tags and proper ARIA roles throughout the UI.
1766
+ - Simplify keyboard shortcut syntax (e.g., `'?!l'` becomes `'alt+shift+l'`).
1767
+ - Add atomic `Store.mergeRemoteChanges` with correct scope-triggered side effects.
1768
+ - Add smoother drawing on slower CPUs via `getCoalescedEvents`.
1769
+ - Add YouTube embed support for time/loop parameters.
1770
+ - Add optional asset URL overrides for unused Embed shape icons.
1771
+
1772
+ ### Bug fixes
1773
+
1774
+ - Fix Firefox SVG pasting.
1775
+ - Fix TailwindCSS text export styling.
1776
+ - Fix image pasting efficiency.
1777
+ - Fix Miro shape compatibility.
1778
+ - Fix Safari trackpad zoom.
1779
+ - Fix performance regressions in rich text and iPad drawing.
1780
+
1781
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.12.0)
1782
+
1783
+ ---
1784
+
1785
+ ### Patch releases
1786
+
1787
+ #### v3.12.1
1788
+
1789
+ - Fix group bounds containing text shapes. ([#5911](https://github.com/tldraw/tldraw/pull/5911))
1790
+
1791
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.12.1)
1792
+
1793
+ #### v3.12.2
1794
+
1795
+ - Restore DPR constrained shape dimensions. ([#6034](https://github.com/tldraw/tldraw/pull/6034))
1796
+
1797
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.12.2)
1798
+
1799
+ ## v3.11.0
1800
+
1801
+ This release addresses rich text issues following v3.10, adds zoom improvements, and introduces accessibility enhancements.
1802
+
1803
+ ### API changes
1804
+
1805
+ - 💥 **`editor.user.getName()`** no longer returns "New user" when unnamed; returns empty string instead.
1806
+ - 💥 **`defaultUserPreferences.name`** changed from "New user" to empty string.
1807
+ - Export `RichTextSVG` from the package.
1808
+
1809
+ ### Improvements
1810
+
1811
+ - Add a new minimum zoom step at 5%.
1812
+ - Add keyboard shortcuts (Shift +/Shift -) for zooming toward your cursor.
1813
+ - Add option to hit Enter to continue editing after selection in the style panel.
1814
+ - Improve rich text rendering performance with many shapes.
1815
+ - Improve hiding/showing shape indicators on large projects.
1816
+ - Add page navigation shortcuts (option + arrows).
1817
+ - Add support for satellite mode in Google Map embeds.
1818
+ - Add focus rings for accessibility.
1819
+ - Add nonce support for the editor security.
1820
+
1821
+ ### Bug fixes
1822
+
1823
+ - Fix rich text numbered list geometry bounds.
1824
+ - Fix React 19 StrictMode compatibility.
1825
+ - Fix export styling issues.
1826
+ - Fix missing internationalization strings for rich text elements.
1827
+
1828
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.11.0)
1829
+
1830
+ ---
1831
+
1832
+ ### Patch releases
1833
+
1834
+ #### v3.11.1
1835
+
1836
+ - Fix application of zoomSpeed setting to pinch gestures. ([#5696](https://github.com/tldraw/tldraw/pull/5696))
1837
+ - Fix unexpected borders in exports from Tailwind CSS pages. ([#5696](https://github.com/tldraw/tldraw/pull/5696))
1838
+
1839
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.11.1)
1840
+
1841
+ #### v3.11.2
1842
+
1843
+ - Fix sync core bug. ([#6667](https://github.com/tldraw/tldraw/pull/6667))
1844
+
1845
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.11.2)
1846
+
1847
+ ## v3.10.0
1848
+
1849
+ This release introduces rich text as a first-class primitive within the Editor, alongside various performance improvements and bug fixes.
1850
+
1851
+ ### What's new
1852
+
1853
+ #### Rich text support
1854
+
1855
+ The SDK now offers rich text as a first-class primitive. The implementation utilizes TipTap with its StarterKit extension plus additional customizations. Developers can configure this functionality through a `textOptions` property to customize TipTap and modify extensions.
1856
+
1857
+ ### API changes
1858
+
1859
+ - 💥 **`text` property** on most shapes replaced with `richText`. When setting values, use `richText: toRichText('some string')` instead of `text: 'some string'`. When retrieving values, use `renderPlaintextFromRichText(props.text)` rather than `props.text`.
1860
+ - Add asset rehydration for .tldr files containing embedded base64 data.
1861
+ - Add `BrokenAssetIcon` display on file upload failures.
1862
+ - Add public collaboration hooks (`usePeerIds`, `usePresence`).
1863
+ - Add `userId` parameter to collaboration components.
1864
+
1865
+ ### Bug fixes
1866
+
1867
+ - Fix performance regression affecting document loading.
1868
+ - Fix Firefox export/style embedding for foreignObjects.
1869
+ - Fix shape reparenting order preservation.
1870
+ - Fix resize functionality.
1871
+ - Fix Safari file pasting issues.
1872
+ - Fix SSR environment compatibility (core-js import removal).
1873
+ - Fix IME text duplication in Chrome.
1874
+
1875
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.10.0)
1876
+
1877
+ ---
1878
+
1879
+ ### Patch releases
1880
+
1881
+ #### v3.10.1
1882
+
1883
+ - Fix API reference links in state packages. ([#5610](https://github.com/tldraw/tldraw/pull/5610))
1884
+
1885
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.10.1)
1886
+
1887
+ #### v3.10.2
1888
+
1889
+ - Add `textOptions` to `<TldrawImage />` component. ([#5650](https://github.com/tldraw/tldraw/pull/5650))
1890
+
1891
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.10.2)
1892
+
1893
+ #### v3.10.3
1894
+
1895
+ - Fix Inter font being embedded in exports. ([#5676](https://github.com/tldraw/tldraw/pull/5676))
1896
+ - Reduce excessive styling in exported content. ([#5676](https://github.com/tldraw/tldraw/pull/5676))
1897
+
1898
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.10.3)
1899
+
1900
+ ## v3.9.0
1901
+
1902
+ This release focuses on bug fixes and performance enhancements, laying groundwork for v3.10 features.
1903
+
1904
+ ### API changes
1905
+
1906
+ - 💥 **`store.createSelectedComputedCache`** removed; use `store.createCache` with custom selector `computed` instead.
1907
+ - 💥 **`createComputerCache` API** modified: third argument now accepts options object with `areRecordsEqual` and `areResultsEqual` properties instead of single equality function.
1908
+
1909
+ ### Improvements
1910
+
1911
+ - Improve layout operations including align, distribute, flip, and stack with better compatibility for arrows and overlapping shapes.
1912
+ - Add new `AtomMap` class to accelerate shape, binding, and record creation/deletion, available as a utility for building custom reactive maps.
1913
+ - Add horizontal padding to text-bound arrows for improved visual appearance.
1914
+
1915
+ ### Bug fixes
1916
+
1917
+ - Fix pasted image size calculations.
1918
+ - Remove `canvas-size` dependency resolving bundler compatibility issues.
1919
+ - Fix SVG copy mimetype.
1920
+ - Fix text shape cloning crash.
1921
+ - Fix temporary image preview display during uploads.
1922
+ - Recognize `https://localhost` as development environment for licensing.
1923
+
1924
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.9.0)
1925
+
1926
+ ## v3.8.0
1927
+
1928
+ This release delivers performance enhancements, UI improvements, and developer experience upgrades alongside bug fixes.
1929
+
1930
+ ### API changes
1931
+
1932
+ - 💥 **`maxDrawShapePoints`** moved to `DrawShapeUtil.configure({ maxPoints })`.
1933
+ - 💥 **Asset upload** now returns `{ src, meta? }` object instead of string.
1934
+ - 💥 **JSON export option** removed; `useImageOrVideoAssetUrl` requires width parameter.
1935
+ - 💥 **`TldrawUiToasts` and `TldrawUiDialogs`** renamed to `DefaultToasts` and `DefaultDialogs`.
1936
+ - Add new `Editor.toImage` method for refined export functionality.
1937
+ - Add custom content handlers for pasted tldraw and excalidraw content.
1938
+ - Add "before-event" listener for custom input event handling.
1939
+ - Add `onCrop` method for shape-specific cropping customization.
1940
+
1941
+ ### Improvements
1942
+
1943
+ - Add `ShapeUtil.configure` utility for passing options to shape utilities.
1944
+ - Allow note shapes to resize by scale.
1945
+ - Add geometric tool shortcut (`g` key) for quick selection.
1946
+ - Add URL drag-and-drop to create bookmark shapes on canvas.
1947
+ - Expand support to 40+ languages via i18n enhancements.
1948
+ - Add React 19 compatibility.
1949
+ - Improve frame performance through computation relocation.
1950
+
1951
+ ### Bug fixes
1952
+
1953
+ - Fix dialog and edit menu glitches.
1954
+ - Fix mousewheel scrolling on elements.
1955
+ - Fix image export width.
1956
+ - Fix text paste behavior via keyboard shortcuts.
1957
+
1958
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.8.0)
1959
+
1960
+ ---
1961
+
1962
+ ### Patch releases
1963
+
1964
+ #### v3.8.1
1965
+
1966
+ - Fix `TldrawImage` not functioning properly with `format=png`. ([#5429](https://github.com/tldraw/tldraw/pull/5429))
1967
+
1968
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.8.1)
1969
+
1970
+ ## v3.7.0
1971
+
1972
+ This release delivers bug fixes and performance enhancements, including customization options for presence data synchronization.
1973
+
1974
+ ### What's new
1975
+
1976
+ #### Presence sync customization ([#5149](https://github.com/tldraw/tldraw/pull/5149))
1977
+
1978
+ Developers can now customize what presence data is synced between clients, or disable presence syncing entirely. This enables optimization for high-latency connections and privacy-focused applications.
1979
+
1980
+ ### API changes
1981
+
1982
+ - Allow `expandSelectionOutlinePx` to return a `Box` object to enable asymmetric expansion across different sides.
1983
+ - Modify behavior when using `editor.updateShape` to properly handle undefined values.
1984
+
1985
+ ### Bug fixes
1986
+
1987
+ - Fix React Strict Mode listener bug affecting `store.listen`.
1988
+ - Fix image rotation and cropping functionality issues.
1989
+ - Fix CSS import failures during export/print operations.
1990
+ - Fix text measurement div leakage during development hot reloads.
1991
+ - Fix popover menu viewport overflow problems.
1992
+ - Fix GitHub Gist URL validation.
1993
+ - Fix image dimension limits for pasted content.
1994
+ - Fix pages menu and quick actions rendering.
1995
+
1996
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.7.0)
1997
+
1998
+ ---
1999
+
2000
+ ### Patch releases
2001
+
2002
+ #### v3.7.1
2003
+
2004
+ - Pass custom migrations to `useLocalStore`. ([#5204](https://github.com/tldraw/tldraw/pull/5204))
2005
+
2006
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.7.1)
2007
+
2008
+ #### v3.7.2
2009
+
2010
+ - Fix pasting files copied from the local filesystem with cmd-v. ([#5225](https://github.com/tldraw/tldraw/pull/5225))
2011
+
2012
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.7.2)
2013
+
2014
+ ## v3.6.0
2015
+
2016
+ This release focuses on developer experience improvements with expanded helper functions and various bug fixes across the editor, embed system, and export functionality.
2017
+
2018
+ ### What's new
2019
+
2020
+ #### Expanded helper functions ([#5041](https://github.com/tldraw/tldraw/pull/5041))
2021
+
2022
+ Actions and toasts overrides now have access to a wider range of helper functions, including clipboard interactions, toast notifications, export utilities, printing, and more. This makes it easier to create custom actions and tools that integrate deeply with tldraw's functionality.
2023
+
2024
+ ### API changes
2025
+
2026
+ - 💥 **`setEmbedDefinitions`** changed from an instance method to a static method on the `EmbedShapeUtil` class. Update your embed definitions to use `EmbedShapeUtil.setEmbedDefinitions()` instead of calling it on an instance. ([#5027](https://github.com/tldraw/tldraw/pull/5027))
2027
+ - 💥 **`ExtractOptionalKeys` and `ExtractRequiredKeys`** utility types removed. Use the new utility type for creating optional properties instead. ([#5055](https://github.com/tldraw/tldraw/pull/5055))
2028
+
2029
+ ### Improvements
2030
+
2031
+ - Add utility type for making undefined properties optional, simplifying type definitions for shape props and other optional configurations. ([#5055](https://github.com/tldraw/tldraw/pull/5055))
2032
+ - Make notes properly snap to the grid after their position is updated, improving alignment consistency. ([#5010](https://github.com/tldraw/tldraw/pull/5010))
2033
+ - Add incremental derivation example demonstrating advanced computed value patterns. ([#5038](https://github.com/tldraw/tldraw/pull/5038))
2034
+
2035
+ ### Bug fixes
2036
+
2037
+ - Fix asset resolution when copying and pasting multiple items, including proper handling of video assets. ([#5061](https://github.com/tldraw/tldraw/pull/5061))
2038
+ - Fix text clipping in scaled frames during export, ensuring all text content is visible in exported images. ([#5022](https://github.com/tldraw/tldraw/pull/5022))
2039
+ - Fix concurrent export operations interfering with each other's font loading. ([#5022](https://github.com/tldraw/tldraw/pull/5022))
2040
+ - Fix long-press point accuracy to ensure touch interactions register at the correct coordinates. ([#5032](https://github.com/tldraw/tldraw/pull/5032))
2041
+ - Fix export naming for single unnamed frames, which now receive appropriate default names. ([#4918](https://github.com/tldraw/tldraw/pull/4918))
2042
+ - Fix custom embeds not rendering correctly on initial mount. ([#5027](https://github.com/tldraw/tldraw/pull/5027))
2043
+
2044
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.6.0)
2045
+
2046
+ ---
2047
+
2048
+ ### Patch releases
2049
+
2050
+ #### v3.6.1
2051
+
2052
+ - Fix bugs in the editor, state-react, and tldraw packages. ([#5132](https://github.com/tldraw/tldraw/pull/5132))
2053
+
2054
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.6.1)
2055
+
2056
+ ## v3.5.0
2057
+
2058
+ This release introduces enhancements to grid snapping during shape creation, improves layering mechanics, and provides better control over export functionality.
2059
+
2060
+ ### What's new
2061
+
2062
+ #### Grid snapping for shape creation ([#4894](https://github.com/tldraw/tldraw/pull/4894))
2063
+
2064
+ Shapes now automatically align to the grid when drawn in grid mode. The new `maybeSnapToGrid` function enables snapping for both click-created and drag-created shapes.
2065
+
2066
+ #### Improved layering actions ([#4898](https://github.com/tldraw/tldraw/pull/4898))
2067
+
2068
+ The "bring forward" and "send backward" actions now only consider nearby overlapping shapes, making layer management more intuitive when working with complex canvases.
2069
+
2070
+ ### API changes
2071
+
2072
+ - Add `scale` and `pixelRatio` parameters to export utilities for more precise control over export dimensions and quality.
2073
+ - Expose font size and stroke size APIs.
2074
+ - Add socket close reason for rate limiting.
2075
+ - Add option to toggle double-click text creation.
2076
+
2077
+ ### Improvements
2078
+
2079
+ - Improve panning performance for note-heavy canvases and zoomed-out views.
2080
+ - Improve page menu hover interaction.
2081
+ - Add custom React provider support in SVG exports.
2082
+ - Switch default theme to light mode.
2083
+ - Improve frame heading right-click behavior.
2084
+
2085
+ ### Bug fixes
2086
+
2087
+ - Fix off-screen shape zoom-to-edit.
2088
+ - Fix erasing state stickiness.
2089
+ - Fix frame heading drag interactions.
2090
+ - Fix Safari sleep-related crashes.
2091
+
2092
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.5.0)
2093
+
2094
+ ---
2095
+
2096
+ ### Patch releases
2097
+
2098
+ #### v3.5.1
2099
+
2100
+ - Fix long press on inset canvases. ([#5037](https://github.com/tldraw/tldraw/pull/5037))
2101
+
2102
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.5.1)
2103
+
2104
+ ## v3.4.0
2105
+
2106
+ This release addresses UI bugs, enhances image/video performance, and improves Excalidraw content compatibility.
2107
+
2108
+ ### API changes
2109
+
2110
+ - 💥 **`id` DOM attribute** on shapes removed in favor of a `data-shape-id` attribute on shape wrappers.
2111
+ - Add `labelColor` property to note shapes.
2112
+ - Add `useUniqueSafeId` and `useSharedSafeId` utilities for managing DOM IDs in tldraw components.
2113
+
2114
+ ### Improvements
2115
+
2116
+ - Improve tooltip wording in the style panel.
2117
+ - Prevent arrow label indicators from displaying behind labels.
2118
+ - Limit page name length in the move-to-page menu.
2119
+ - Improve image and video rendering performance.
2120
+
2121
+ ### Bug fixes
2122
+
2123
+ - Fix re-render loops caused by inline `options` in the Tldraw component.
2124
+ - Fix toolbar button outline border-radius alignment.
2125
+ - Fix color preservation when pasting Excalidraw content.
2126
+ - Fix unhighlighted menu triggers.
2127
+ - Fix drag event type handling.
2128
+ - Fix duplicate image creation on canvas drops.
2129
+ - Fix link indicator visibility on sticky notes.
2130
+ - Fix URL parsing in embed dialogs.
2131
+ - Fix cross-instance rendering conflicts.
2132
+ - Fix menu options in read-only mode.
2133
+
2134
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.4.0)
2135
+
2136
+ ---
2137
+
2138
+ ### Patch releases
2139
+
2140
+ #### v3.4.1
2141
+
2142
+ - Fix arrows being clipped incorrectly when multiple tldraw instances or exports are present in the DOM. ([#4819](https://github.com/tldraw/tldraw/pull/4819))
2143
+
2144
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.4.1)
2145
+
2146
+ ## v3.3.0
2147
+
2148
+ This release introduces sync improvements, readonly mode support, and various performance enhancements.
2149
+
2150
+ ### What's new
2151
+
2152
+ #### Readonly mode
2153
+
2154
+ Servers can now restrict client editing while preserving presence updates using the new "readonly" mode. This enables use cases like view-only sharing and presentation modes where users can see each other's cursors but cannot modify the document.
2155
+
2156
+ #### Sync server enhancements
2157
+
2158
+ New `TLSocketRoom` methods (`closeSession`, `getRecord`, and `getSessions`) provide finer control over sync connections and room state management.
2159
+
2160
+ ### API changes
2161
+
2162
+ - Add editor option for quick action shortcut placement.
2163
+ - Add `editor.getIsReadonly()` helper method.
2164
+
2165
+ ### Improvements
2166
+
2167
+ - Pass wheel events through toolbar elements for improved scrolling/zooming.
2168
+ - Allow Command/Control modifier keys to enable multi-select (previously shift-only).
2169
+ - Allow text tool to be locked.
2170
+ - Improve draw shape rendering performance during zoom interactions.
2171
+
2172
+ ### Bug fixes
2173
+
2174
+ - Fix Safari arrow rendering.
2175
+ - Fix image drop navigation errors.
2176
+ - Fix watermark layering.
2177
+ - Fix geometry calculations.
2178
+ - Fix readonly mode label editing prevention.
2179
+
2180
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.3.0)
2181
+
2182
+ ---
2183
+
2184
+ ### Patch releases
2185
+
2186
+ #### v3.3.1
2187
+
2188
+ - Fix meta key incorrectly triggering the shift key. ([#4703](https://github.com/tldraw/tldraw/pull/4703))
2189
+
2190
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.3.1)
2191
+
2192
+ #### v3.3.2
2193
+
2194
+ - Fix dropped images being created twice. ([#4727](https://github.com/tldraw/tldraw/pull/4727))
2195
+
2196
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.3.2)
2197
+
2198
+ #### v3.3.3
2199
+
2200
+ - Fix image duplication when dropping onto the canvas. ([#4789](https://github.com/tldraw/tldraw/pull/4789))
2201
+ - Fix additional keyboard modifier issues. ([#4789](https://github.com/tldraw/tldraw/pull/4789))
2202
+
2203
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.3.3)
2204
+
2205
+ ## v3.2.0
2206
+
2207
+ This release contains no code changes. It was published to align version numbers across packages. See the [v3.1.0 release notes](https://tldraw.dev/releases/v3.1.0) for information about changes since v3.0.x.
2208
+
2209
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.2.0)
2210
+
2211
+ ## v3.1.0
2212
+
2213
+ This release introduces shape visibility control and server-side data manipulation capabilities, alongside API enhancements and bug fixes.
2214
+
2215
+ ### What's new
2216
+
2217
+ #### Shape visibility control ([#4570](https://github.com/tldraw/tldraw/pull/4570))
2218
+
2219
+ The new `isShapeHidden` predicate option prevents shapes from being rendered or reacting to pointer events. This is useful for implementing permission systems in collaborative applications where certain shapes should be invisible to specific users.
2220
+
2221
+ #### Server-side document manipulation ([#4581](https://github.com/tldraw/tldraw/pull/4581))
2222
+
2223
+ The tldraw sync server now supports server-side document manipulation through the `updateShapes` method, enabling integration with third-party services and automated document updates.
2224
+
2225
+ ### API changes
2226
+
2227
+ - Add option to `Editor.rotateShapesBy` specifying rotation center point.
2228
+ - Add `useAsset` hook for resolving responsive asset versions.
2229
+
2230
+ ### Bug fixes
2231
+
2232
+ - Fix arrow label text measurement calculations.
2233
+ - Fix arrow collaborator indicators overlapping labels.
2234
+ - Fix binding processing error handling.
2235
+ - Fix watermark opacity and animation behavior.
2236
+
2237
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.1.0)
2238
+
2239
+ ## v3.0.0
2240
+
2241
+ This release introduces a revised licensing model alongside deep links, enhanced image export, custom embeds, and a new text search API.
2242
+
2243
+ ### What's new
2244
+
2245
+ #### Licensing
2246
+
2247
+ The most significant change involves updated licenses permitting use in both commercial and non-commercial projects when displaying a "Made with tldraw" watermark. Users can now purchase Business Licenses to remove the watermark, with details available at [tldraw.dev](https://tldraw.dev). ([#4449](https://github.com/tldraw/tldraw/pull/4449), [#4517](https://github.com/tldraw/tldraw/pull/4517), [#4561](https://github.com/tldraw/tldraw/pull/4561))
2248
+
2249
+ #### Deep links
2250
+
2251
+ New APIs enable creation of shareable URLs pointing to specific canvas locations, such as particular shapes or pages, with automatic URL updates as users navigate.
2252
+
2253
+ ```typescript
2254
+ // Create a deep link to a specific shape
2255
+ const url = editor.createDeepLink({
2256
+ shapeId: 'shape-id',
2257
+ viewport: 'fit',
2258
+ })
2259
+
2260
+ // The URL updates automatically as you navigate
2261
+ editor.on('change', () => {
2262
+ const currentUrl = editor.getCurrentDeepLink()
2263
+ })
2264
+ ```
2265
+
2266
+ See the [deep links guide](https://tldraw.dev/docs/editor#Deep-links) for more information. ([#4498](https://github.com/tldraw/tldraw/pull/4498))
2267
+
2268
+ #### Enhanced image export
2269
+
2270
+ Custom shapes now export as images by default through HTML/CSS embedding within SVG files, eliminating the need for developers to implement custom SVG rendering methods.
2271
+
2272
+ ```typescript
2273
+ // Custom shapes automatically export as images
2274
+ class MyShapeUtil extends ShapeUtil<MyShape> {
2275
+ // No need to implement toSvg() anymore
2276
+ component(shape: MyShape) {
2277
+ return <div className="my-shape">{/* ... */}</div>
2278
+ }
2279
+ }
2280
+ ```
2281
+
2282
+ #### Custom embeds API
2283
+
2284
+ Developers can now customize which external websites (YouTube, Google Maps, CodeSandbox, etc.) appear as embeddable content, or add entirely new embed types.
2285
+
2286
+ ```typescript
2287
+ // Add a custom embed type
2288
+ const customEmbedDef = {
2289
+ type: 'custom',
2290
+ title: 'My Custom Embed',
2291
+ hostnames: ['mysite.com'],
2292
+ toEmbedUrl: (url: string) => `https://mysite.com/embed/${url}`,
2293
+ fromEmbedUrl: (url: string) => url.replace('/embed/', '/')
2294
+ }
2295
+
2296
+ <Tldraw embedDefs={[customEmbedDef, ...defaultEmbedDefs]} />
2297
+ ```
2298
+
2299
+ #### Text search via getText API
2300
+
2301
+ A new `getText` API provides reliable access to human-readable shape content, facilitating text search implementation within applications.
2302
+
2303
+ ```typescript
2304
+ // Search through all shapes for text content
2305
+ const searchResults = editor.getCurrentPageShapes().filter((shape) => {
2306
+ const text = editor.getText(shape.id)
2307
+ return text?.toLowerCase().includes(searchTerm.toLowerCase())
2308
+ })
2309
+ ```
2310
+
2311
+ ### API changes
2312
+
2313
+ - 💥 **`TLRotationSnapshot`** type removed from the public API. Use `editor.getShapePageTransform(shape).rotation()` instead.
2314
+ - 💥 **`onEditorMount`** callback in `createTLStore` renamed to `onMount` for consistency.
2315
+ - 💥 **`Editor.mark()`** deprecated in favor of `Editor.markHistoryStoppingPoint()` for clearer intent.
2316
+ - 💥 **`TLSvgOptions`** type renamed to `TLImageExportOptions` to better reflect its broader use in image export.
2317
+ - 💥 **Focus event behavior**: Calling `updateInstanceState({isFocused: true})` now triggers standard focus events consistently. Use `editor.focus()` for reliable focus behavior.
2318
+ - Add `editor.getText(shapeId)` method for accessing shape text content.
2319
+ - Add `editor.createDeepLink(options)` for generating shareable URLs.
2320
+ - Add `embedDefs` prop to Tldraw component for customizing embed types.
2321
+ - Expose additional shape export utilities for custom image generation.
2322
+
2323
+ ### Improvements
2324
+
2325
+ - Improve bookmark rendering for URLs without preview images. ([#4460](https://github.com/tldraw/tldraw/pull/4460))
2326
+ - Improve handling of asset storage and persistence. ([#4542](https://github.com/tldraw/tldraw/pull/4542))
2327
+ - Improve documentation search functionality. ([#4485](https://github.com/tldraw/tldraw/pull/4485))
2328
+ - Refine watermark appearance and behavior. ([#4589](https://github.com/tldraw/tldraw/pull/4589), [#4622](https://github.com/tldraw/tldraw/pull/4622))
2329
+
2330
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.0.0)
2331
+
2332
+ ---
2333
+
2334
+ ### Patch releases
2335
+
2336
+ #### v3.0.1
2337
+
2338
+ - Fix documentation search functionality and article issues. ([#4515](https://github.com/tldraw/tldraw/pull/4515))
2339
+
2340
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.0.1)
2341
+
2342
+ #### v3.0.2
2343
+
2344
+ - Fix build caching issue causing "You have multiple versions of tldraw libraries installed" errors. ([#4525](https://github.com/tldraw/tldraw/pull/4525))
2345
+ - Fix container null error. ([#4524](https://github.com/tldraw/tldraw/pull/4524))
2346
+
2347
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.0.2)
2348
+
2349
+ #### v3.0.3
2350
+
2351
+ - Fix bugs in the editor and tldraw packages. ([#4541](https://github.com/tldraw/tldraw/pull/4541))
2352
+
2353
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v3.0.3)
2354
+
2355
+ ## v2.4.0
2356
+
2357
+ This release introduces our sync engine as a general-use library, new animation options for shapes, support for image flipping, and many bug fixes and developer experience enhancements.
2358
+
2359
+ ### What's new
2360
+
2361
+ #### Sync ([#4031](https://github.com/tldraw/tldraw/pull/4031))
2362
+
2363
+ For the first time, we're releasing our real-time collaboration engine—the one we developed for tldraw.com—as a general library. The SDK still supports any backend for collaboration, but we hope this will be the easiest option for developers. See the new `sync` package in the repository and the multiplayer-demo example.
2364
+
2365
+ #### Interpolation ([#4162](https://github.com/tldraw/tldraw/pull/4162))
2366
+
2367
+ You can use `Editor.animateShapes` to animate shapes on the canvas. Previously only position and rotation would animate. Now you can implement `ShapeUtil.getInterpolatedProps` to describe how your custom shape's other properties should animate.
2368
+
2369
+ ```ts
2370
+ override getInterpolatedProps(
2371
+ startShape: Shape,
2372
+ endShape: Shape,
2373
+ t: number
2374
+ ): Shape['props'] {
2375
+ return {
2376
+ ...endShape.props,
2377
+ w: lerp(startShape.props.w, endShape.props.w, t),
2378
+ h: lerp(startShape.props.h, endShape.props.h, t),
2379
+ }
2380
+ }
2381
+ ```
2382
+
2383
+ #### Editor.run ([#4042](https://github.com/tldraw/tldraw/pull/4042))
2384
+
2385
+ The new `Editor.run` method runs a function within additional context. By default, the function runs inside a transaction, meaning all changes settle at once—improving performance and avoiding unnecessary renders. You can also use options to ignore history or ignore locked shapes.
2386
+
2387
+ ```ts
2388
+ editor.run(
2389
+ () => {
2390
+ editor.createShapes(myShapes)
2391
+ editor.sendToBack(myShapes)
2392
+ editor.selectNone()
2393
+ },
2394
+ { history: 'ignore' }
2395
+ )
2396
+ ```
2397
+
2398
+ #### Assets
2399
+
2400
+ As part of our work on sync, we have a new system for handling large assets like images and videos. Provide a [`TLAssetStore`](https://tldraw.dev/reference/tlschema/TLAssetStore) to control how assets are uploaded and retrieved. Use [`Editor.uploadAsset`](https://tldraw.dev/reference/editor/Editor#uploadAsset) and [`Editor.resolveAssetURL`](https://tldraw.dev/reference/editor/Editor#resolveAssetUrl) in your shapes and tools.
2401
+
2402
+ ### API changes
2403
+
2404
+ - 💥 **`editor.history.ignore(cb)`** replaced with `editor.run(cb, {history: 'ignore'})`.
2405
+ - 💥 **`editor.batch`** deprecated, replaced with `editor.run`.
2406
+ - 💥 **`@tldraw/state` imports**: If you're importing from `@tldraw/state` directly, the `track` function and all hooks (e.g. `useValue`) have moved to `@tldraw/state-react`. ([#4170](https://github.com/tldraw/tldraw/pull/4170))
2407
+ - Add `DefaultMenuPanel` export. ([#4193](https://github.com/tldraw/tldraw/pull/4193))
2408
+ - Make `fileSize` property of `TLImageAsset` and `TLVideoAsset` optional. ([#4206](https://github.com/tldraw/tldraw/pull/4206))
2409
+ - Allow passing partial `TLEditorSnapshot` to `TldrawImage` and `useTLStore`. ([#4190](https://github.com/tldraw/tldraw/pull/4190))
2410
+ - Make `EffectScheduler` and `useStateTracking` public. ([#4155](https://github.com/tldraw/tldraw/pull/4155))
2411
+ - Add `setDefaultValue` to `StyleProp`. ([#4044](https://github.com/tldraw/tldraw/pull/4044))
2412
+ - Add `ShapeUtil.getInterpolatedProps`. ([#4162](https://github.com/tldraw/tldraw/pull/4162))
2413
+ - Add `Editor.run`, replacing `Editor.batch`. ([#4042](https://github.com/tldraw/tldraw/pull/4042))
2414
+
2415
+ ### Improvements
2416
+
2417
+ - Add horizontal and vertical flipping for images. ([#4113](https://github.com/tldraw/tldraw/pull/4113))
2418
+ - Allow custom tools to decide whether they are affected by shape lock. ([#4208](https://github.com/tldraw/tldraw/pull/4208))
2419
+ - Serve icons as a single SVG instead of many individual requests. ([#4150](https://github.com/tldraw/tldraw/pull/4150))
2420
+ - Make paste-at-point behavior based on a user preference. ([#4104](https://github.com/tldraw/tldraw/pull/4104))
2421
+ - Show toast when uploading an unsupported file type or file that's too large. ([#4114](https://github.com/tldraw/tldraw/pull/4114))
2422
+ - Show toast when pasting fails due to missing clipboard permissions. ([#4117](https://github.com/tldraw/tldraw/pull/4117))
2423
+ - Add `ShapeIndicators` component for custom logic about when to display indicators. ([#4083](https://github.com/tldraw/tldraw/pull/4083))
2424
+ - Animate shape opacity changes. ([#4242](https://github.com/tldraw/tldraw/pull/4242))
2425
+
2426
+ ### Bug fixes
2427
+
2428
+ - Fix font style export to SVG. ([#4195](https://github.com/tldraw/tldraw/pull/4195))
2429
+ - Fix `force` flag for camera methods. ([#4214](https://github.com/tldraw/tldraw/pull/4214))
2430
+ - Show user's color scheme in menu by default. ([#4184](https://github.com/tldraw/tldraw/pull/4184))
2431
+ - Fix padding for dynamically scaled text shapes. ([#4140](https://github.com/tldraw/tldraw/pull/4140))
2432
+ - Fix `cameraOptions` via React causing editor to re-mount. ([#4089](https://github.com/tldraw/tldraw/pull/4089))
2433
+ - Allow high-res images to be uploaded. ([#4198](https://github.com/tldraw/tldraw/pull/4198))
2434
+ - Prevent locked shapes from being updated, grouped, or ungrouped programmatically. ([#4042](https://github.com/tldraw/tldraw/pull/4042))
2435
+ - Fix `snapshots` prop in `createTLStore`. ([#4233](https://github.com/tldraw/tldraw/pull/4233))
2436
+ - Fix grid backgrounds with multiple tldraw instances. ([#4132](https://github.com/tldraw/tldraw/pull/4132))
2437
+ - Fix inputs staying in place while viewport-following. ([#4108](https://github.com/tldraw/tldraw/pull/4108))
2438
+ - Fix bookmarks rendering across devices. ([#4118](https://github.com/tldraw/tldraw/pull/4118))
2439
+ - Fix `InFrontOfTheCanvas` component stack order. ([#4024](https://github.com/tldraw/tldraw/pull/4024))
2440
+ - Fix frame headers not stopping edit on focus loss. ([#4092](https://github.com/tldraw/tldraw/pull/4092))
2441
+
2442
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.4.0)
2443
+
2444
+ ---
2445
+
2446
+ ### Patch releases
2447
+
2448
+ #### v2.4.1
2449
+
2450
+ - Fix `assets` prop on `<Tldraw />` and `<TldrawEditor />` components not being respected. ([#4285](https://github.com/tldraw/tldraw/pull/4285))
2451
+
2452
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.4.1)
2453
+
2454
+ #### v2.4.2
2455
+
2456
+ - Fix bugs and improve the sync engine and related packages. ([#4309](https://github.com/tldraw/tldraw/pull/4309))
2457
+
2458
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.4.2)
2459
+
2460
+ #### v2.4.3
2461
+
2462
+ - Fix bugs in the tldraw package. ([#4328](https://github.com/tldraw/tldraw/pull/4328))
2463
+
2464
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.4.3)
2465
+
2466
+ #### v2.4.4
2467
+
2468
+ - Fix bugs in the editor, sync, tldraw, and tlschema packages. ([#4352](https://github.com/tldraw/tldraw/pull/4352))
2469
+
2470
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.4.4)
2471
+
2472
+ #### v2.4.5
2473
+
2474
+ - Fix unhandled promise rejection during strict mode in the editor. ([#4407](https://github.com/tldraw/tldraw/pull/4407))
2475
+
2476
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.4.5)
2477
+
2478
+ #### v2.4.6
2479
+
2480
+ - Improve rendering performance in the store and tldraw packages. ([#4434](https://github.com/tldraw/tldraw/pull/4434))
2481
+
2482
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.4.6)
2483
+
2484
+ ## v2.3.0
2485
+
2486
+ This release focuses on image and video storage improvements, a new fonts/icons CDN, image performance optimizations, and a new flatten feature.
2487
+
2488
+ ### What's new
2489
+
2490
+ #### Image and video storage improvements ([#3836](https://github.com/tldraw/tldraw/pull/3836))
2491
+
2492
+ When using local-only storage, images and videos are now stored in a separate IndexedDB table instead of as base64-encoded blobs in the room's JSON. This significantly improves performance and reduces the size of room data.
2493
+
2494
+ #### Fonts and icons CDN ([#3923](https://github.com/tldraw/tldraw/pull/3923))
2495
+
2496
+ Improved our CDN for assets (fonts and icons). We were using unpkg before, but now we're using Cloudflare directly for more fine-grained control and better performance. ([#3927](https://github.com/tldraw/tldraw/pull/3927))
2497
+
2498
+ #### Image level-of-detail ([#3827](https://github.com/tldraw/tldraw/pull/3827))
2499
+
2500
+ For higher-resolution images (over a couple megabytes), the image gets transformed to an appropriate size depending on your viewport, zoom level, and network speed. This helps with bandwidth and browser memory usage when you have multiple high-res images on the board.
2501
+
2502
+ #### Flatten ([#3933](https://github.com/tldraw/tldraw/pull/3933))
2503
+
2504
+ You can now select multiple shapes and flatten them into a single image. For those moments when you need to press things together.
2505
+
2506
+ #### Security improvements ([#3884](https://github.com/tldraw/tldraw/pull/3884))
2507
+
2508
+ Locked down referrer network requests to make sure we weren't leaking tldraw rooms to external media/iframe requests. ([#3881](https://github.com/tldraw/tldraw/pull/3881))
2509
+
2510
+ ### API changes
2511
+
2512
+ - Add fill-fill style, accessible via `Alt`+`F`. ([#3966](https://github.com/tldraw/tldraw/pull/3966))
2513
+ - Make `ArrowBindingUtil` public. ([#3913](https://github.com/tldraw/tldraw/pull/3913))
2514
+ - Add `getSnapshot` and `loadSnapshot` methods to `Editor` class. ([#3912](https://github.com/tldraw/tldraw/pull/3912))
2515
+
2516
+ ### Improvements
2517
+
2518
+ - Allow users to use system appearance (dark/light) mode. ([#3703](https://github.com/tldraw/tldraw/pull/3703))
2519
+ - Remove ability to rename document while in readonly mode. ([#3911](https://github.com/tldraw/tldraw/pull/3911))
2520
+ - Add delay and easing to edge scrolling. ([#3950](https://github.com/tldraw/tldraw/pull/3950))
2521
+
2522
+ ### Bug fixes
2523
+
2524
+ - Fix copy/paste for older versions of Firefox. ([#4008](https://github.com/tldraw/tldraw/pull/4008))
2525
+ - Fix copy/paste in Firefox 127+. ([#4003](https://github.com/tldraw/tldraw/pull/4003))
2526
+ - Fix not allowing editing locked shapes when switching edit modes. ([#4007](https://github.com/tldraw/tldraw/pull/4007))
2527
+ - Fix text shape measurement in React strict mode. ([#4001](https://github.com/tldraw/tldraw/pull/4001))
2528
+ - Fix border color for following user. ([#3975](https://github.com/tldraw/tldraw/pull/3975))
2529
+ - Fix scale issue with new draw lines. ([#3971](https://github.com/tldraw/tldraw/pull/3971))
2530
+ - Fix edge scrolling at odd browser zoom levels. ([#3973](https://github.com/tldraw/tldraw/pull/3973))
2531
+ - Fix appearance of solid-style heart shapes. ([#3963](https://github.com/tldraw/tldraw/pull/3963))
2532
+ - Fix position of multiple assets when pasted/dropped onto canvas. ([#3965](https://github.com/tldraw/tldraw/pull/3965))
2533
+ - Fix indicator for stylus-drawn draw shapes. ([#3962](https://github.com/tldraw/tldraw/pull/3962))
2534
+
2535
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.3.0)
2536
+
2537
+ ## v2.2.0
2538
+
2539
+ This release introduces the bindings system, camera constraints, and configurable options—major features that unlock new types of applications you can build with tldraw.
2540
+
2541
+ ### What's new
2542
+
2543
+ #### Bindings ([#3326](https://github.com/tldraw/tldraw/pull/3326))
2544
+
2545
+ Bindings allow you to create relationships between shapes. Our default arrow shapes are a great example: each end of the arrow can bind to another shape. When that shape moves, so does the arrow.
2546
+
2547
+ Before this change, arrows were hard-coded into the library. Now, with the bindings system, you can create arrows, constraint systems, visual programming environments, and much more.
2548
+
2549
+ Check out the [bindings guide](https://tldraw.dev/docs/editor#Bindings) for more information. ([#3780](https://github.com/tldraw/tldraw/pull/3780)) ([#3797](https://github.com/tldraw/tldraw/pull/3797)) ([#3800](https://github.com/tldraw/tldraw/pull/3800)) ([#3871](https://github.com/tldraw/tldraw/pull/3871))
2550
+
2551
+ #### Camera constraints ([#3282](https://github.com/tldraw/tldraw/pull/3282))
2552
+
2553
+ You can now limit the camera to a fixed area of the canvas. This is useful for creating experiences that don't quite fit the "infinite canvas" paradigm: document annotators, image editors, slideshow creators, and more.
2554
+
2555
+ See the [camera constraints guide](https://tldraw.dev/docs/editor#Camera-options) for more information. ([#3747](https://github.com/tldraw/tldraw/pull/3747)) ([#3814](https://github.com/tldraw/tldraw/pull/3814))
2556
+
2557
+ #### Configurable options ([#3799](https://github.com/tldraw/tldraw/pull/3799))
2558
+
2559
+ You can now override many options which were previously hard-coded constants. Pass an `options` prop into the tldraw component to change the maximum number of pages, grid steps, or other previously hard-coded values.
2560
+
2561
+ See [`TldrawOptions`](https://tldraw.dev/reference/editor/TldrawOptions) for details. ([#3900](https://github.com/tldraw/tldraw/pull/3900))
2562
+
2563
+ #### 💥 Undo/redo changes
2564
+
2565
+ The history system has been significantly reworked:
2566
+
2567
+ 1. **History options simplified**: `squashing`, `ephemeral`, and `preserveRedoStack` flags have been consolidated. Use `editor.history.ignore(fn)` or `editor.history.batch(fn, {history: 'record-preserveRedoStack'})` instead.
2568
+
2569
+ 2. **Automatic recording**: Everything that touches the store is now recorded in undo/redo (unless part of `mergeRemoteChanges`). Use `editor.history.ignore(fn)` for changes you don't want recorded.
2570
+
2571
+ 3. **Side effects captured**: Changes in side-effects are now captured by undo/redo. Wrap in `editor.history.ignore` for the old behavior.
2572
+
2573
+ ### API changes
2574
+
2575
+ - 💥 **`canBind`** now accepts an options object instead of just the shape. See [`TLShapeUtilCanBindOpts`](https://tldraw.dev/reference/editor/TLShapeUtilCanBindOpts).
2576
+ - 💥 **`editor.sideEffects.registerBatchCompleteHandler`** replaced with `editor.sideEffects.registerOperationCompleteHandler`. ([#3748](https://github.com/tldraw/tldraw/pull/3748))
2577
+ - 💥 **`editor.getArrowInfo(shape)`** replaced with `getArrowInfo(editor, shape)`.
2578
+ - 💥 **`editor.getArrowsBoundTo(shape)`** removed—use `editor.getBindingsToShape(shape, 'arrow')` instead.
2579
+ - 💥 **Arrow shape `start` and `end` properties** are now always points. Use `getArrowBindings(editor, shape)` to check for bindings.
2580
+ - 💥 **Types renamed**: `ShapeProps` → `RecordProps`, `ShapePropsType` → `RecordPropsType`, `TLShapePropsMigrations` → `TLPropsMigrations`, `SchemaShapeInfo` → `SchemaPropsInfo`.
2581
+ - Add `editor.blur` method. ([#3875](https://github.com/tldraw/tldraw/pull/3875))
2582
+ - Add better defaults for `createTLStore`. ([#3886](https://github.com/tldraw/tldraw/pull/3886))
2583
+ - Add `getSnapshot` and `loadSnapshot` for easier document persistence. See [State Snapshots](https://tldraw.dev/docs/persistence#State-Snapshots). ([#3811](https://github.com/tldraw/tldraw/pull/3811))
2584
+ - Add `select` option to `Editor.groupShapes` and `Editor.ungroupShapes`. ([#3690](https://github.com/tldraw/tldraw/pull/3690))
2585
+ - `InFrontOfTheCanvas` now has access to the editor's UI context. ([#3782](https://github.com/tldraw/tldraw/pull/3782))
2586
+ - `useEditor` and other context-based hooks now throw an error when used out-of-context. ([#3750](https://github.com/tldraw/tldraw/pull/3750))
2587
+ - Add `defaultShapeSchemas` for custom multiplayer implementations. ([#3613](https://github.com/tldraw/tldraw/pull/3613))
2588
+
2589
+ ### Improvements
2590
+
2591
+ - Add a heart shape to the geo shape set. ([#3787](https://github.com/tldraw/tldraw/pull/3787))
2592
+ - Improve rendering for bookmarks without preview images. ([#3856](https://github.com/tldraw/tldraw/pull/3856))
2593
+ - Improve undo/redo UX around image cropping. ([#3891](https://github.com/tldraw/tldraw/pull/3891))
2594
+ - Increase default limit of shapes per page from 2000 to 4000. ([#3716](https://github.com/tldraw/tldraw/pull/3716))
2595
+ - Expand accepted image types to include webp, webm, apng, and avif. ([#3730](https://github.com/tldraw/tldraw/pull/3730))
2596
+ - Prune unused assets when loading `.tldr` files. ([#3689](https://github.com/tldraw/tldraw/pull/3689))
2597
+ - Improve handling of mouse-type devices that support pressure (e.g., Wacom tablets). ([#3639](https://github.com/tldraw/tldraw/pull/3639))
2598
+ - Change text shapes to be left-aligned by default. ([#3627](https://github.com/tldraw/tldraw/pull/3627))
2599
+ - Add Desmos graph embed type. ([#3608](https://github.com/tldraw/tldraw/pull/3608))
2600
+
2601
+ ### Bug fixes
2602
+
2603
+ - Fix 'insert media' undo removing other changes. ([#3910](https://github.com/tldraw/tldraw/pull/3910))
2604
+ - Fix referrer being sent for bookmarks and images. ([#3881](https://github.com/tldraw/tldraw/pull/3881))
2605
+ - Fix minimum drag distance being wrong when zoomed. ([#3873](https://github.com/tldraw/tldraw/pull/3873))
2606
+ - Fix cropped images not exporting properly. ([#3837](https://github.com/tldraw/tldraw/pull/3837))
2607
+ - Fix spacebar and middle mouse button panning. ([#3791](https://github.com/tldraw/tldraw/pull/3791)) ([#3792](https://github.com/tldraw/tldraw/pull/3792))
2608
+ - Fix cursor and shapes wiggling when following someone's viewport. ([#3695](https://github.com/tldraw/tldraw/pull/3695))
2609
+ - Fix cross-browser focus management issues. ([#3718](https://github.com/tldraw/tldraw/pull/3718))
2610
+ - Fix imports in Astro. ([#3742](https://github.com/tldraw/tldraw/pull/3742))
2611
+ - Fix copy/paste for patterned shapes as SVG/PNG. ([#3708](https://github.com/tldraw/tldraw/pull/3708))
2612
+ - Fix RTL text layout for SVG exports. ([#3680](https://github.com/tldraw/tldraw/pull/3680))
2613
+ - Fix clicking on minimap sometimes not changing viewport. ([#3617](https://github.com/tldraw/tldraw/pull/3617))
2614
+
2615
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.2.0)
2616
+
2617
+ ---
2618
+
2619
+ ### Patch releases
2620
+
2621
+ #### v2.2.1
2622
+
2623
+ - Improve documentation and make `ArrowBindingUtil` public. ([#3958](https://github.com/tldraw/tldraw/pull/3958))
2624
+ - Add `editor.getSnapshot()` and `editor.loadSnapshot()` methods. ([#3958](https://github.com/tldraw/tldraw/pull/3958))
2625
+ - Fix CSS styling for bookmark elements. ([#3958](https://github.com/tldraw/tldraw/pull/3958))
2626
+
2627
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.2.1)
2628
+
2629
+ #### v2.2.2
2630
+
2631
+ - Fix text measurement breaking when `Tldraw` was used with React strict mode. ([#4004](https://github.com/tldraw/tldraw/pull/4004))
2632
+
2633
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.2.2)
2634
+
2635
+ #### v2.2.3
2636
+
2637
+ - Fix copy/paste functionality in Firefox 127+. ([#4006](https://github.com/tldraw/tldraw/pull/4006))
2638
+
2639
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.2.3)
2640
+
2641
+ #### v2.2.4
2642
+
2643
+ - Fix copy/paste functionality for older versions of Firefox. ([#4011](https://github.com/tldraw/tldraw/pull/4011))
2644
+
2645
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.2.4)
2646
+
2647
+ ## v2.1.0
2648
+
2649
+ This release includes completely redesigned sticky notes, an overhaul to our migration system, and significant performance improvements.
2650
+
2651
+ ### What's new
2652
+
2653
+ #### New stickies ([#3249](https://github.com/tldraw/tldraw/pull/3249))
2654
+
2655
+ Sticky notes have been completely redesigned with a fresh look and improved functionality.
2656
+
2657
+ #### 💥 New migrations ([#3220](https://github.com/tldraw/tldraw/pull/3220))
2658
+
2659
+ The migrations system has been overhauled for better reliability and developer experience.
2660
+
2661
+ - The `Migrations` type is now called `LegacyMigrations`
2662
+ - The serialized schema format (returned by `StoreSchema.serialize()` and `Store.getSnapshot()`) has changed
2663
+ - `compareRecordVersions` and `RecordVersion` have been removed
2664
+ - `compareSchemas` is gone—use `schema.getMigrationsSince(prevSchema)` instead
2665
+ - `defineMigrations` has been deprecated. See [updating legacy shape migrations](https://tldraw.dev/docs/persistence#Updating-legacy-shape-migrations-defineMigrations) for upgrade instructions
2666
+ - `migrate` has been removed
2667
+
2668
+ #### 💥 Input buffering ([#3223](https://github.com/tldraw/tldraw/pull/3223))
2669
+
2670
+ Events are now buffered and sent to state nodes every tick, instead of immediately. This unlocks big performance improvements but could introduce subtle issues with custom tools—make sure to test any custom tools thoroughly.
2671
+
2672
+ #### 💥 React-powered SVG exports ([#3117](https://github.com/tldraw/tldraw/pull/3117))
2673
+
2674
+ If any of your shapes implement `toSvg` for exports, you'll need to replace your implementation with a new version that returns JSX instead of manually constructing SVG DOM nodes.
2675
+
2676
+ `editor.getSvg` is deprecated. Use `editor.getSvgElement` or `editor.getSvgString` instead.
2677
+
2678
+ #### 💥 Component-based toolbar customization ([#3067](https://github.com/tldraw/tldraw/pull/3067))
2679
+
2680
+ If you're using the `toolbar` callback to override toolbar items, switch to using the new `Toolbar` component override. See the [toolbar groups example](https://tldraw.dev/examples/ui/toolbar-groups) for details.
2681
+
2682
+ ### API changes
2683
+
2684
+ - 💥 **`getRenderingShapes`** no longer returns `isCulled`—use `getCulledShapes` instead.
2685
+ - Add `Editor.getStyleForNextShape`. ([#3039](https://github.com/tldraw/tldraw/pull/3039))
2686
+ - Add `usePreloadAssets` export. ([#3545](https://github.com/tldraw/tldraw/pull/3545))
2687
+
2688
+ ### Improvements
2689
+
2690
+ - Improve color contrast. ([#3486](https://github.com/tldraw/tldraw/pull/3486))
2691
+ - Add long press event. ([#3275](https://github.com/tldraw/tldraw/pull/3275))
2692
+ - Add severity colors and icons to toasts. ([#2988](https://github.com/tldraw/tldraw/pull/2988))
2693
+ - Improve handling of broken images/videos. ([#2990](https://github.com/tldraw/tldraw/pull/2990))
2694
+ - Improve performance of draw shapes. ([#3464](https://github.com/tldraw/tldraw/pull/3464))
2695
+ - Use WebGL to draw the minimap. ([#3510](https://github.com/tldraw/tldraw/pull/3510))
2696
+ - Improve reactivity bookkeeping performance. ([#3471](https://github.com/tldraw/tldraw/pull/3471)) ([#3487](https://github.com/tldraw/tldraw/pull/3487))
2697
+ - Improve selection/erasing performance. ([#3454](https://github.com/tldraw/tldraw/pull/3454))
2698
+ - Improve performance of text shapes on iOS/Safari. ([#3429](https://github.com/tldraw/tldraw/pull/3429))
2699
+ - Reduce rendered DOM nodes for geo shapes and arrows. ([#3283](https://github.com/tldraw/tldraw/pull/3283))
2700
+ - Improve shape rendering performance. ([#3176](https://github.com/tldraw/tldraw/pull/3176))
2701
+
2702
+ ### Bug fixes
2703
+
2704
+ - Fix copy error sound in Safari. ([#3536](https://github.com/tldraw/tldraw/pull/3536))
2705
+ - Fix arrow label positioning overlapping bound shapes. ([#3512](https://github.com/tldraw/tldraw/pull/3512))
2706
+ - Fix cursor chat button appearing when not in select tool. ([#3485](https://github.com/tldraw/tldraw/pull/3485))
2707
+ - Fix alt-duplicating shapes sometimes not working. ([#3488](https://github.com/tldraw/tldraw/pull/3488))
2708
+ - Fix camera sliding after pinch. ([#3462](https://github.com/tldraw/tldraw/pull/3462))
2709
+ - Fix text shapes overflowing their bounds when resized. ([#3327](https://github.com/tldraw/tldraw/pull/3327))
2710
+ - Fix incorrectly rotated handles on rotated cropping images. ([#3093](https://github.com/tldraw/tldraw/pull/3093))
2711
+ - Fix videos not being sized correctly. ([#3047](https://github.com/tldraw/tldraw/pull/3047))
2712
+ - Fix `localStorage` crash in React Native webviews. ([#3043](https://github.com/tldraw/tldraw/pull/3043))
2713
+
2714
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.1.0)
2715
+
2716
+ ---
2717
+
2718
+ ### Patch releases
2719
+
2720
+ #### v2.1.1
2721
+
2722
+ - Fix missing export for `createShapePropsMigrationIds`, part of the new migrations API. ([#3594](https://github.com/tldraw/tldraw/pull/3594))
2723
+ - Add exports for `defaultEditorAssetUrls`, `PORTRAIT_BREAKPOINT`, `useDefaultColorTheme`, and `getPerfectDashProps`. ([#3594](https://github.com/tldraw/tldraw/pull/3594))
2724
+
2725
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.1.1)
2726
+
2727
+ #### v2.1.2
2728
+
2729
+ - Revert a performance optimization that caused computed caches to sometimes not invalidate correctly, leading to stale data and crashes. ([#3611](https://github.com/tldraw/tldraw/pull/3611))
2730
+
2731
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.1.2)
2732
+
2733
+ #### v2.1.3
2734
+
2735
+ - Expose migrations, validators, and versions from tlschema. ([#3613](https://github.com/tldraw/tldraw/pull/3613))
2736
+ - Add `defaultShapeSchemas` which can be passed directly to `createTLSchema`. ([#3613](https://github.com/tldraw/tldraw/pull/3613))
2737
+
2738
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.1.3)
2739
+
2740
+ #### v2.1.4
2741
+
2742
+ - Fix text selection flakiness when clicking into text shapes. ([#3643](https://github.com/tldraw/tldraw/pull/3643))
2743
+ - Fix edit→edit not working correctly when unfilled geo shapes are on top of other shapes. ([#3643](https://github.com/tldraw/tldraw/pull/3643))
2744
+
2745
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.1.4)
2746
+
2747
+ ## v2.0.0
2748
+
2749
+ This is the initial public release of the tldraw SDK—a TypeScript library for creating infinite canvas experiences in React. After an extensive alpha and beta period, the SDK is ready for production use.
2750
+
2751
+ ### What's new
2752
+
2753
+ #### The editor
2754
+
2755
+ At the heart of tldraw is the `Editor` class, a single object that manages all editor state and provides the API for programmatic control. The editor maintains document state through a reactive store system containing JSON-serializable records.
2756
+
2757
+ ```tsx
2758
+ import { Tldraw } from 'tldraw'
2759
+
2760
+ function App() {
2761
+ return (
2762
+ <Tldraw
2763
+ onMount={(editor) => {
2764
+ // Full programmatic control
2765
+ editor.createShapes([{ type: 'geo', x: 100, y: 100 }])
2766
+ editor.selectAll()
2767
+ editor.zoomToFit()
2768
+ }}
2769
+ />
2770
+ )
2771
+ }
2772
+ ```
2773
+
2774
+ #### Default shapes
2775
+
2776
+ The SDK ships with a complete set of default shapes:
2777
+
2778
+ - **Geo shapes**: Rectangle, ellipse, triangle, diamond, pentagon, hexagon, octagon, star, rhombus, oval, trapezoid, arrow-shapes, cloud, and x-box
2779
+ - **Draw**: Freehand drawing with pressure sensitivity support
2780
+ - **Arrow**: Connectable arrows with labels, multiple arrowhead styles, and curved/straight/elbow routing
2781
+ - **Text**: Rich text with font, size, and alignment options
2782
+ - **Note**: Sticky notes with customizable colors
2783
+ - **Image & Video**: Media embedding with cropping support
2784
+ - **Frame**: Grouping containers that clip their contents
2785
+ - **Line**: Multi-point lines with various spline options
2786
+ - **Highlight**: Transparent highlight strokes
2787
+ - **Embed**: Web content embedding (YouTube, Figma, Google Maps, and more)
2788
+ - **Bookmark**: URL previews with metadata
2789
+
2790
+ #### Default tools
2791
+
2792
+ A full set of tools for interacting with the canvas:
2793
+
2794
+ - **Select**: Selection, multi-select, resize, rotate, and transform shapes
2795
+ - **Hand**: Pan the canvas
2796
+ - **Draw**: Freehand drawing
2797
+ - **Eraser**: Remove shapes by drawing over them
2798
+ - **Arrow, Line, Geo, Text, Note, Frame, Highlight**: Shape creation tools
2799
+ - **Laser**: Temporary pointer for presentations
2800
+ - **Zoom**: Zoom in/out with click or marquee
2801
+
2802
+ #### State management
2803
+
2804
+ The SDK uses a reactive signals system for state management. All editor state is observable, with automatic dependency tracking to prevent unnecessary re-renders.
2805
+
2806
+ ```tsx
2807
+ import { track, useEditor } from 'tldraw'
2808
+
2809
+ const SelectedShapeCount = track(() => {
2810
+ const editor = useEditor()
2811
+ return <div>{editor.getSelectedShapeIds().length} selected</div>
2812
+ })
2813
+ ```
2814
+
2815
+ #### The store
2816
+
2817
+ Document data lives in a `TLStore`—a reactive client-side database that supports:
2818
+
2819
+ - JSON-serializable records for shapes, pages, assets, and instance state
2820
+ - Reactive updates via signals
2821
+ - Snapshot export/import for persistence
2822
+ - Schema migrations for backwards compatibility
2823
+
2824
+ #### Tool system
2825
+
2826
+ Tools are implemented as hierarchical state machines using `StateNode`. Events flow through a state chart, enabling complex multi-step interactions:
2827
+
2828
+ ```tsx
2829
+ class MyTool extends StateNode {
2830
+ static id = 'my-tool'
2831
+
2832
+ onPointerDown(info) {
2833
+ const point = this.editor.inputs.currentPagePoint
2834
+ this.editor.createShape({ type: 'geo', x: point.x, y: point.y })
2835
+ }
2836
+ }
2837
+ ```
2838
+
2839
+ #### Shape system
2840
+
2841
+ Every shape type has a `ShapeUtil` class defining its behavior—geometry, rendering, interactions, and more. Create custom shapes by extending `ShapeUtil`:
2842
+
2843
+ ```tsx
2844
+ class CardShapeUtil extends ShapeUtil<CardShape> {
2845
+ static type = 'card'
2846
+
2847
+ getGeometry(shape) {
2848
+ return new Rectangle2d({ width: shape.props.w, height: shape.props.h })
2849
+ }
2850
+
2851
+ component(shape) {
2852
+ return <div className="card">{shape.props.title}</div>
2853
+ }
2854
+ }
2855
+ ```
2856
+
2857
+ #### User interface
2858
+
2859
+ A complete, responsive UI system with:
2860
+
2861
+ - Toolbar with tool selection and shape-specific options
2862
+ - Style panel for colors, fills, fonts, and more
2863
+ - Context menus with shape actions
2864
+ - Keyboard shortcuts dialog
2865
+ - Page management
2866
+ - Zoom controls and minimap
2867
+ - Actions menu and quick actions bar
2868
+ - Help menu and debug panel
2869
+
2870
+ All UI components can be overridden or extended via the `components` prop.
2871
+
2872
+ #### Features
2873
+
2874
+ - **Multi-page documents**: Create and manage multiple pages per document
2875
+ - **Undo/redo**: Full history management with marks and batching
2876
+ - **Copy/paste**: Between pages, documents, and external applications
2877
+ - **Export**: SVG, PNG, and JSON export
2878
+ - **Zoom & pan**: Pinch, scroll, keyboard shortcuts, and programmatic control
2879
+ - **Grid & snapping**: Align shapes to grid and each other
2880
+ - **Grouping**: Group shapes together
2881
+ - **Locking**: Prevent shape modification
2882
+ - **Duplication**: Alt-drag to duplicate
2883
+ - **Alignment & distribution**: Align and distribute selected shapes
2884
+ - **Flip**: Horizontal and vertical flipping
2885
+ - **Styles**: Color, fill, dash, size, font, and more
2886
+ - **Dark mode**: Full dark mode support
2887
+ - **Localization**: 30+ languages supported
2888
+ - **Accessibility**: Keyboard navigation and screen reader support
2889
+ - **Touch support**: Full touch and pen input support
2890
+ - **Pressure sensitivity**: For supported devices
2891
+
2892
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.0)
2893
+
2894
+ ---
2895
+
2896
+ ### Patch releases
2897
+
2898
+ #### v2.0.1
2899
+
2900
+ - Avoid randomness at init time, improving consistency for SSR and testing scenarios. ([#3076](https://github.com/tldraw/tldraw/pull/3076))
2901
+
2902
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.1)
2903
+
2904
+ #### v2.0.2
2905
+
2906
+ - Fix JPG export functionality. ([#3199](https://github.com/tldraw/tldraw/pull/3199))
2907
+
2908
+ [View release on GitHub](https://github.com/tldraw/tldraw/releases/tag/v2.0.2)