tldraw 3.16.0-canary.ffdf566dd0a8 → 3.16.0-internal.51e99e128bd4

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 (310) hide show
  1. package/dist-cjs/index.d.ts +173 -5
  2. package/dist-cjs/index.js +12 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/canvas/TldrawScribble.js +1 -1
  5. package/dist-cjs/lib/canvas/TldrawScribble.js.map +2 -2
  6. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +3 -3
  7. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  8. package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js +3 -3
  9. package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js.map +1 -1
  10. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +3 -3
  11. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +1 -1
  13. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +1 -1
  14. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +12 -12
  15. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  16. package/dist-cjs/lib/shapes/frame/components/FrameHeading.js +1 -1
  17. package/dist-cjs/lib/shapes/frame/components/FrameHeading.js.map +2 -2
  18. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +2 -2
  19. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  20. package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js +2 -1
  21. package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js.map +2 -2
  22. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +5 -1
  23. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
  24. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -3
  25. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +1 -1
  26. package/dist-cjs/lib/shapes/line/LineShapeUtil.js +5 -1
  27. package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
  28. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +4 -4
  29. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  30. package/dist-cjs/lib/shapes/shared/ShapeFill.js +4 -4
  31. package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
  32. package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
  33. package/dist-cjs/lib/shapes/text/TextShapeUtil.js +2 -2
  34. package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
  35. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +3 -3
  36. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +1 -1
  37. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +25 -1
  38. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  39. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +12 -0
  40. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  41. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  42. package/dist-cjs/lib/ui/TldrawUi.js +14 -0
  43. package/dist-cjs/lib/ui/TldrawUi.js.map +3 -3
  44. package/dist-cjs/lib/ui/assetUrls.js +13 -10
  45. package/dist-cjs/lib/ui/assetUrls.js.map +2 -2
  46. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +12 -3
  47. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
  48. package/dist-cjs/lib/ui/components/DefaultMenuPanel.js +3 -2
  49. package/dist-cjs/lib/ui/components/DefaultMenuPanel.js.map +2 -2
  50. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +4 -4
  51. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
  52. package/dist-cjs/lib/ui/components/MobileStylePanel.js +5 -3
  53. package/dist-cjs/lib/ui/components/MobileStylePanel.js.map +2 -2
  54. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js +1 -1
  55. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js.map +2 -2
  56. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +2 -1
  57. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
  58. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js +3 -2
  59. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js.map +2 -2
  60. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js +2 -2
  61. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js.map +2 -2
  62. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +14 -14
  63. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  64. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js +3 -3
  65. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +2 -2
  66. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js +26 -25
  67. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +3 -3
  68. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +1 -1
  69. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  70. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +66 -21
  71. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js.map +3 -3
  72. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +189 -80
  73. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +3 -3
  74. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +2 -2
  75. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
  76. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js +5 -16
  77. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +3 -3
  78. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -1
  79. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  80. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +3 -2
  81. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js.map +3 -3
  82. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +19 -4
  83. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  84. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +153 -152
  85. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  86. package/dist-cjs/lib/ui/components/primitives/layout.js +76 -0
  87. package/dist-cjs/lib/ui/components/primitives/layout.js.map +7 -0
  88. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuContext.js.map +2 -2
  89. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +25 -12
  90. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
  91. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +154 -20
  92. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  93. package/dist-cjs/lib/ui/context/events.js.map +2 -2
  94. package/dist-cjs/lib/ui/hooks/useTools.js +94 -9
  95. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  96. package/dist-cjs/lib/ui/version.js +3 -3
  97. package/dist-cjs/lib/ui/version.js.map +1 -1
  98. package/dist-esm/index.d.mts +173 -5
  99. package/dist-esm/index.mjs +19 -1
  100. package/dist-esm/index.mjs.map +2 -2
  101. package/dist-esm/lib/canvas/TldrawScribble.mjs +1 -1
  102. package/dist-esm/lib/canvas/TldrawScribble.mjs.map +2 -2
  103. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +4 -3
  104. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  105. package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs +3 -3
  106. package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs.map +1 -1
  107. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +4 -3
  108. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
  109. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +1 -1
  110. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +1 -1
  111. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +13 -12
  112. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  113. package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs +1 -1
  114. package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs.map +2 -2
  115. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +3 -2
  116. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  117. package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs +2 -1
  118. package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs.map +2 -2
  119. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +6 -1
  120. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
  121. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -3
  122. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +1 -1
  123. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +6 -1
  124. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
  125. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +5 -4
  126. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  127. package/dist-esm/lib/shapes/shared/ShapeFill.mjs +5 -4
  128. package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
  129. package/dist-esm/lib/shapes/shared/freehand/svg.mjs.map +2 -2
  130. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +3 -2
  131. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
  132. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +3 -3
  133. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +1 -1
  134. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +26 -1
  135. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  136. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +13 -0
  137. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  138. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  139. package/dist-esm/lib/ui/TldrawUi.mjs +16 -2
  140. package/dist-esm/lib/ui/TldrawUi.mjs.map +3 -3
  141. package/dist-esm/lib/ui/assetUrls.mjs +13 -10
  142. package/dist-esm/lib/ui/assetUrls.mjs.map +2 -2
  143. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +12 -3
  144. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
  145. package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs +3 -2
  146. package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs.map +2 -2
  147. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +4 -4
  148. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
  149. package/dist-esm/lib/ui/components/MobileStylePanel.mjs +6 -3
  150. package/dist-esm/lib/ui/components/MobileStylePanel.mjs.map +2 -2
  151. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs +1 -1
  152. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs.map +2 -2
  153. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +2 -1
  154. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
  155. package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs +3 -2
  156. package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs.map +2 -2
  157. package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs +2 -2
  158. package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs.map +2 -2
  159. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +14 -14
  160. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  161. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs +3 -3
  162. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +2 -2
  163. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs +26 -25
  164. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +2 -2
  165. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +1 -1
  166. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  167. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs +56 -21
  168. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs.map +2 -2
  169. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +192 -81
  170. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +3 -3
  171. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +2 -2
  172. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
  173. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +6 -6
  174. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +2 -2
  175. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +1 -1
  176. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  177. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs +3 -2
  178. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs.map +2 -2
  179. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +19 -4
  180. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  181. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +162 -154
  182. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  183. package/dist-esm/lib/ui/components/primitives/layout.mjs +46 -0
  184. package/dist-esm/lib/ui/components/primitives/layout.mjs.map +7 -0
  185. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuContext.mjs.map +2 -2
  186. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs +25 -12
  187. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
  188. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +162 -22
  189. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  190. package/dist-esm/lib/ui/context/events.mjs.map +2 -2
  191. package/dist-esm/lib/ui/hooks/useTools.mjs +102 -10
  192. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  193. package/dist-esm/lib/ui/version.mjs +3 -3
  194. package/dist-esm/lib/ui/version.mjs.map +1 -1
  195. package/package.json +11 -34
  196. package/src/index.ts +15 -0
  197. package/src/lib/canvas/TldrawScribble.tsx +1 -1
  198. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +2 -1
  199. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +4 -3
  200. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +7 -6
  201. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +4 -3
  202. package/src/lib/shapes/arrow/elbow/ElbowArrowDebug.tsx +3 -3
  203. package/src/lib/shapes/draw/DrawShapeTool.test.ts +0 -5
  204. package/src/lib/shapes/draw/DrawShapeUtil.tsx +4 -3
  205. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
  206. package/src/lib/shapes/frame/FrameShapeUtil.tsx +21 -14
  207. package/src/lib/shapes/frame/components/FrameHeading.tsx +1 -1
  208. package/src/lib/shapes/geo/GeoShapeUtil.tsx +3 -2
  209. package/src/lib/shapes/geo/components/GeoShapeBody.tsx +2 -2
  210. package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +7 -1
  211. package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -3
  212. package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -3
  213. package/src/lib/shapes/line/LineShapeUtil.tsx +6 -1
  214. package/src/lib/shapes/line/__snapshots__/LineShapeUtil.test.tsx.snap +2 -2
  215. package/src/lib/shapes/note/NoteShapeUtil.tsx +9 -4
  216. package/src/lib/shapes/shared/ShapeFill.tsx +5 -4
  217. package/src/lib/shapes/shared/freehand/svg.ts +2 -0
  218. package/src/lib/shapes/text/TextShapeTool.test.ts +6 -5
  219. package/src/lib/shapes/text/TextShapeUtil.tsx +3 -2
  220. package/src/lib/shapes/video/VideoShapeUtil.tsx +3 -3
  221. package/src/lib/tools/EraserTool/childStates/Erasing.ts +34 -1
  222. package/src/lib/tools/EraserTool/childStates/Pointing.ts +20 -0
  223. package/src/lib/tools/SelectTool/childStates/Translating.ts +0 -1
  224. package/src/lib/ui/TldrawUi.tsx +17 -2
  225. package/src/lib/ui/assetUrls.ts +13 -10
  226. package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +15 -3
  227. package/src/lib/ui/components/DefaultMenuPanel.tsx +4 -3
  228. package/src/lib/ui/components/Minimap/MinimapManager.ts +4 -4
  229. package/src/lib/ui/components/MobileStylePanel.tsx +9 -6
  230. package/src/lib/ui/components/NavigationPanel/DefaultNavigationPanel.tsx +1 -1
  231. package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +3 -2
  232. package/src/lib/ui/components/SharePanel/PeopleMenuItem.tsx +4 -3
  233. package/src/lib/ui/components/SharePanel/UserPresenceColorPicker.tsx +3 -3
  234. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +39 -43
  235. package/src/lib/ui/components/StylePanel/DoubleDropdownPicker.tsx +3 -3
  236. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +7 -6
  237. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +1 -1
  238. package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +55 -23
  239. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +212 -61
  240. package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +2 -2
  241. package/src/lib/ui/components/primitives/TldrawUiButtonPicker.tsx +40 -37
  242. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +1 -1
  243. package/src/lib/ui/components/primitives/TldrawUiPopover.tsx +4 -2
  244. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +32 -9
  245. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +186 -172
  246. package/src/lib/ui/components/primitives/layout.tsx +107 -0
  247. package/src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx +0 -1
  248. package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +29 -16
  249. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +221 -19
  250. package/src/lib/ui/context/events.tsx +1 -0
  251. package/src/lib/ui/hooks/useTools.tsx +140 -10
  252. package/src/lib/ui/version.ts +3 -3
  253. package/src/lib/ui.css +363 -305
  254. package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +5 -5
  255. package/src/lib/utils/tldr/__snapshots__/buildFromV1Document.test.ts.snap +4 -4
  256. package/src/test/A11y.test.tsx +3 -2
  257. package/src/test/ClickManager.test.ts +7 -6
  258. package/src/test/Editor.test.tsx +20 -19
  259. package/src/test/EraserTool.test.ts +184 -13
  260. package/src/test/HandTool.test.ts +10 -9
  261. package/src/test/HighlightShape.test.ts +2 -1
  262. package/src/test/SelectTool.test.ts +3 -2
  263. package/src/test/TLUserPreferences.test.ts +4 -3
  264. package/src/test/TestEditor.ts +13 -15
  265. package/src/test/TldrawEditor.test.tsx +11 -10
  266. package/src/test/ZoomTool.test.ts +7 -6
  267. package/src/test/__snapshots__/drawing.test.ts.snap +2 -2
  268. package/src/test/__snapshots__/groups.test.tsx.snap +6 -6
  269. package/src/test/__snapshots__/resizing.test.ts.snap +2 -2
  270. package/src/test/arrows-megabus.test.tsx +5 -4
  271. package/src/test/bindings.test.tsx +24 -37
  272. package/src/test/bookmark-shapes.test.ts +1 -8
  273. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +23 -7
  274. package/src/test/commands/__snapshots__/packShapes.test.ts.snap +8 -8
  275. package/src/test/commands/__snapshots__/zoomToFit.test.ts.snap +2 -2
  276. package/src/test/commands/alignShapes.test.tsx +25 -24
  277. package/src/test/commands/animationSpeed.test.ts +2 -1
  278. package/src/test/commands/centerOnPoint.test.ts +3 -2
  279. package/src/test/commands/clipboard.test.ts +3 -2
  280. package/src/test/commands/createShapes.test.ts +2 -1
  281. package/src/test/commands/deleteShapes.test.ts +2 -1
  282. package/src/test/commands/distributeShapes.test.tsx +11 -10
  283. package/src/test/commands/getSvgString.test.ts +2 -1
  284. package/src/test/commands/packShapes.test.ts +5 -4
  285. package/src/test/commands/resizeShape.test.ts +2 -1
  286. package/src/test/commands/rotateShapes.test.ts +7 -6
  287. package/src/test/commands/setCamera.test.ts +4 -3
  288. package/src/test/commands/setCurrentPage.test.ts +3 -2
  289. package/src/test/commands/stackShapes.test.ts +11 -10
  290. package/src/test/commands/stretch.test.tsx +13 -12
  291. package/src/test/createDeepLink.test.tsx +2 -1
  292. package/src/test/cropping.test.ts +3 -2
  293. package/src/test/drawing.test.ts +2 -1
  294. package/src/test/flipShapes.test.ts +4 -3
  295. package/src/test/frames.test.ts +25 -24
  296. package/src/test/getCulledShapes.test.tsx +3 -2
  297. package/src/test/groups.test.tsx +1 -1
  298. package/src/test/handleDeepLink.test.tsx +2 -1
  299. package/src/test/maxShapes.test.ts +3 -2
  300. package/src/test/modifiers.test.ts +5 -4
  301. package/src/test/navigation.test.ts +12 -11
  302. package/src/test/panning.test.ts +2 -1
  303. package/src/test/perf/perf.test.ts +2 -1
  304. package/src/test/registerDeepLinkListener.test.tsx +10 -9
  305. package/src/test/resizing.test.ts +39 -38
  306. package/src/test/select.test.tsx +4 -3
  307. package/src/test/selection-omnibus.test.ts +11 -10
  308. package/src/test/shapeutils.test.ts +4 -3
  309. package/src/test/translating.test.ts +9 -8
  310. package/tldraw.css +656 -595
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/ui/context/events.tsx"],
4
- "sourcesContent": ["import * as React from 'react'\n\n/** @public */\nexport type TLUiEventSource =\n\t| 'menu'\n\t| 'main-menu'\n\t| 'context-menu'\n\t| 'zoom-menu'\n\t| 'document-name'\n\t| 'navigation-zone'\n\t| 'quick-actions'\n\t| 'actions-menu'\n\t| 'kbd'\n\t| 'debug-panel'\n\t| 'page-menu'\n\t| 'share-menu'\n\t| 'export-menu'\n\t| 'toolbar'\n\t| 'people-menu'\n\t| 'dialog'\n\t| 'help-menu'\n\t| 'helper-buttons'\n\t| 'style-panel'\n\t| 'rich-text-menu'\n\t| 'image-toolbar'\n\t| 'video-toolbar'\n\t| 'unknown'\n\n/** @public */\nexport interface TLUiEventMap {\n\t// Actions\n\tundo: null\n\tredo: null\n\t'change-language': { locale: string }\n\t'change-page': { direction?: 'prev' | 'next' }\n\t'select-adjacent-shape': { direction: 'prev' | 'next' | 'left' | 'right' | 'up' | 'down' }\n\t'delete-page': null\n\t'duplicate-page': null\n\t'move-page': null\n\t'new-page': null\n\t'rename-page': null\n\t'move-to-page': null\n\t'move-to-new-page': null\n\t'rename-document': null\n\t'group-shapes': null\n\t'ungroup-shapes': null\n\t'remove-frame': null\n\t'fit-frame-to-content': null\n\t'convert-to-embed': null\n\t'convert-to-bookmark': null\n\t'open-embed-link': null\n\t'toggle-auto-size': null\n\t'copy-as': { format: 'svg' | 'png' | 'json' }\n\t'export-as': { format: 'svg' | 'png' | 'json' }\n\t'export-all-as': { format: 'svg' | 'png' | 'json' }\n\t'download-original': null\n\t'edit-link': null\n\t'insert-embed': null\n\t'insert-media': null\n\t'replace-media': null\n\t'image-manipulate': null\n\t'alt-text-start': null\n\t'set-alt-text': null\n\t'align-shapes': {\n\t\toperation: 'left' | 'center-horizontal' | 'right' | 'top' | 'center-vertical' | 'bottom'\n\t}\n\t'duplicate-shapes': null\n\t'pack-shapes': null\n\t'stack-shapes': { operation: 'horizontal' | 'vertical' }\n\t'flip-shapes': { operation: 'horizontal' | 'vertical' }\n\t'distribute-shapes': { operation: 'horizontal' | 'vertical' }\n\t'stretch-shapes': { operation: 'horizontal' | 'vertical' }\n\t'reorder-shapes': {\n\t\toperation: 'toBack' | 'toFront' | 'forward' | 'backward'\n\t}\n\t'delete-shapes': null\n\t'select-all-shapes': null\n\t'select-none-shapes': null\n\t'rotate-ccw': { fine: boolean }\n\t'rotate-cw': { fine: boolean }\n\t'zoom-in': { towardsCursor: boolean }\n\t'zoom-out': { towardsCursor: boolean }\n\t'zoom-to-fit': null\n\t'zoom-to-selection': null\n\t'reset-zoom': null\n\t'zoom-into-view': null\n\t'zoom-to-content': null\n\t'open-menu': { id: string }\n\t'close-menu': { id: string }\n\t'create-new-project': null\n\t'save-project-to-file': null\n\t'open-file': null\n\t'select-tool': { id: string }\n\tprint: null\n\tcopy: null\n\tpaste: null\n\tcut: null\n\t'set-style': { id: string; value: string | number }\n\t'toggle-transparent': null\n\t'toggle-snap-mode': null\n\t'toggle-tool-lock': null\n\t'toggle-grid-mode': null\n\t'toggle-wrap-mode': null\n\t'toggle-focus-mode': null\n\t'toggle-debug-mode': null\n\t'toggle-dynamic-size-mode': null\n\t'toggle-paste-at-cursor': null\n\t'toggle-lock': null\n\t'toggle-reduce-motion': null\n\t'toggle-keyboard-shortcuts': null\n\t'toggle-ui-labels': null\n\t'toggle-edge-scrolling': null\n\t'color-scheme': { value: string }\n\t'exit-pen-mode': null\n\t'start-following': null\n\t'stop-following': null\n\t'set-color': null\n\t'change-user-name': null\n\t'open-cursor-chat': null\n\t'zoom-tool': null\n\t'unlock-all': null\n\t'enlarge-shapes': null\n\t'shrink-shapes': null\n\t'flatten-to-image': null\n\t'a11y-repeat-shape-announce': null\n\t'open-url': { url: string }\n\t'open-context-menu': null\n\t'adjust-shape-styles': null\n\t'copy-link': null\n\t'image-replace': null\n\t'video-replace': null\n\t'open-kbd-shortcuts': null\n\t'rich-text': {\n\t\toperation:\n\t\t\t| 'bold'\n\t\t\t| 'strike'\n\t\t\t| 'link'\n\t\t\t| 'link-edit'\n\t\t\t| 'link-visit'\n\t\t\t| 'link-remove'\n\t\t\t| 'heading'\n\t\t\t| 'bulletList'\n\t}\n\tedit: null\n}\n\n/** @public */\nexport type TLUiEventData<K> = K extends null\n\t? { source: TLUiEventSource }\n\t: { source: TLUiEventSource } & K\n\n/** @public */\nexport type TLUiEventHandler = <T extends keyof TLUiEventMap>(\n\tname: T,\n\tdata: TLUiEventData<TLUiEventMap[T]>\n) => void\n\n/** @public */\nexport type TLUiEventContextType = TLUiEventHandler\n\n/** @internal */\nconst defaultEventHandler: TLUiEventContextType = () => void null\n\n/** @internal */\nexport const EventsContext = React.createContext<TLUiEventContextType | null>(null)\n\n/** @public */\nexport interface EventsProviderProps {\n\tonEvent?: TLUiEventHandler\n\tchildren: React.ReactNode\n}\n\n/** @public @react */\nexport function TldrawUiEventsProvider({ onEvent, children }: EventsProviderProps) {\n\treturn (\n\t\t<EventsContext.Provider value={onEvent ?? defaultEventHandler}>\n\t\t\t{children}\n\t\t</EventsContext.Provider>\n\t)\n}\n\n/** @public */\nexport function useUiEvents(): TLUiEventContextType {\n\tconst eventHandler = React.useContext(EventsContext)\n\treturn eventHandler ?? defaultEventHandler\n}\n"],
5
- "mappings": "AA+KE;AA/KF,YAAY,WAAW;AAiKvB,MAAM,sBAA4C,MAAM;AAGjD,MAAM,gBAAgB,MAAM,cAA2C,IAAI;AAS3E,SAAS,uBAAuB,EAAE,SAAS,SAAS,GAAwB;AAClF,SACC,oBAAC,cAAc,UAAd,EAAuB,OAAO,WAAW,qBACxC,UACF;AAEF;AAGO,SAAS,cAAoC;AACnD,QAAM,eAAe,MAAM,WAAW,aAAa;AACnD,SAAO,gBAAgB;AACxB;",
4
+ "sourcesContent": ["import * as React from 'react'\n\n/** @public */\nexport type TLUiEventSource =\n\t| 'menu'\n\t| 'main-menu'\n\t| 'context-menu'\n\t| 'zoom-menu'\n\t| 'document-name'\n\t| 'navigation-zone'\n\t| 'quick-actions'\n\t| 'actions-menu'\n\t| 'kbd'\n\t| 'debug-panel'\n\t| 'page-menu'\n\t| 'share-menu'\n\t| 'export-menu'\n\t| 'toolbar'\n\t| 'people-menu'\n\t| 'dialog'\n\t| 'help-menu'\n\t| 'helper-buttons'\n\t| 'style-panel'\n\t| 'rich-text-menu'\n\t| 'image-toolbar'\n\t| 'video-toolbar'\n\t| 'unknown'\n\n/** @public */\nexport interface TLUiEventMap {\n\t// Actions\n\tundo: null\n\tredo: null\n\t'change-language': { locale: string }\n\t'change-page': { direction?: 'prev' | 'next' }\n\t'select-adjacent-shape': { direction: 'prev' | 'next' | 'left' | 'right' | 'up' | 'down' }\n\t'delete-page': null\n\t'duplicate-page': null\n\t'move-page': null\n\t'new-page': null\n\t'rename-page': null\n\t'move-to-page': null\n\t'move-to-new-page': null\n\t'rename-document': null\n\t'group-shapes': null\n\t'ungroup-shapes': null\n\t'remove-frame': null\n\t'fit-frame-to-content': null\n\t'convert-to-embed': null\n\t'convert-to-bookmark': null\n\t'open-embed-link': null\n\t'toggle-auto-size': null\n\t'copy-as': { format: 'svg' | 'png' | 'json' }\n\t'export-as': { format: 'svg' | 'png' | 'json' }\n\t'export-all-as': { format: 'svg' | 'png' | 'json' }\n\t'download-original': null\n\t'edit-link': null\n\t'insert-embed': null\n\t'insert-media': null\n\t'replace-media': null\n\t'image-manipulate': null\n\t'alt-text-start': null\n\t'set-alt-text': null\n\t'align-shapes': {\n\t\toperation: 'left' | 'center-horizontal' | 'right' | 'top' | 'center-vertical' | 'bottom'\n\t}\n\t'duplicate-shapes': null\n\t'pack-shapes': null\n\t'stack-shapes': { operation: 'horizontal' | 'vertical' }\n\t'flip-shapes': { operation: 'horizontal' | 'vertical' }\n\t'distribute-shapes': { operation: 'horizontal' | 'vertical' }\n\t'stretch-shapes': { operation: 'horizontal' | 'vertical' }\n\t'reorder-shapes': {\n\t\toperation: 'toBack' | 'toFront' | 'forward' | 'backward'\n\t}\n\t'delete-shapes': null\n\t'select-all-shapes': null\n\t'select-none-shapes': null\n\t'rotate-ccw': { fine: boolean }\n\t'rotate-cw': { fine: boolean }\n\t'zoom-in': { towardsCursor: boolean }\n\t'zoom-out': { towardsCursor: boolean }\n\t'zoom-to-fit': null\n\t'zoom-to-selection': null\n\t'reset-zoom': null\n\t'zoom-into-view': null\n\t'zoom-to-content': null\n\t'open-menu': { id: string }\n\t'close-menu': { id: string }\n\t'create-new-project': null\n\t'save-project-to-file': null\n\t'open-file': null\n\t'select-tool': { id: string }\n\tprint: null\n\tcopy: null\n\tpaste: null\n\tcut: null\n\t'set-style': { id: string; value: string | number }\n\t'toggle-transparent': null\n\t'toggle-snap-mode': null\n\t'toggle-tool-lock': null\n\t'toggle-grid-mode': null\n\t'toggle-wrap-mode': null\n\t'toggle-focus-mode': null\n\t'toggle-debug-mode': null\n\t'toggle-dynamic-size-mode': null\n\t'toggle-paste-at-cursor': null\n\t'toggle-lock': null\n\t'toggle-reduce-motion': null\n\t'toggle-keyboard-shortcuts': null\n\t'toggle-ui-labels': null\n\t'toggle-edge-scrolling': null\n\t'color-scheme': { value: string }\n\t'exit-pen-mode': null\n\t'start-following': null\n\t'stop-following': null\n\t'set-color': null\n\t'change-user-name': null\n\t'open-cursor-chat': null\n\t'zoom-tool': null\n\t'unlock-all': null\n\t'enlarge-shapes': null\n\t'shrink-shapes': null\n\t'flatten-to-image': null\n\t'a11y-repeat-shape-announce': null\n\t'open-url': { url: string }\n\t'open-context-menu': null\n\t'adjust-shape-styles': null\n\t'copy-link': null\n\t'drag-tool': { id: string }\n\t'image-replace': null\n\t'video-replace': null\n\t'open-kbd-shortcuts': null\n\t'rich-text': {\n\t\toperation:\n\t\t\t| 'bold'\n\t\t\t| 'strike'\n\t\t\t| 'link'\n\t\t\t| 'link-edit'\n\t\t\t| 'link-visit'\n\t\t\t| 'link-remove'\n\t\t\t| 'heading'\n\t\t\t| 'bulletList'\n\t}\n\tedit: null\n}\n\n/** @public */\nexport type TLUiEventData<K> = K extends null\n\t? { source: TLUiEventSource }\n\t: { source: TLUiEventSource } & K\n\n/** @public */\nexport type TLUiEventHandler = <T extends keyof TLUiEventMap>(\n\tname: T,\n\tdata: TLUiEventData<TLUiEventMap[T]>\n) => void\n\n/** @public */\nexport type TLUiEventContextType = TLUiEventHandler\n\n/** @internal */\nconst defaultEventHandler: TLUiEventContextType = () => void null\n\n/** @internal */\nexport const EventsContext = React.createContext<TLUiEventContextType | null>(null)\n\n/** @public */\nexport interface EventsProviderProps {\n\tonEvent?: TLUiEventHandler\n\tchildren: React.ReactNode\n}\n\n/** @public @react */\nexport function TldrawUiEventsProvider({ onEvent, children }: EventsProviderProps) {\n\treturn (\n\t\t<EventsContext.Provider value={onEvent ?? defaultEventHandler}>\n\t\t\t{children}\n\t\t</EventsContext.Provider>\n\t)\n}\n\n/** @public */\nexport function useUiEvents(): TLUiEventContextType {\n\tconst eventHandler = React.useContext(EventsContext)\n\treturn eventHandler ?? defaultEventHandler\n}\n"],
5
+ "mappings": "AAgLE;AAhLF,YAAY,WAAW;AAkKvB,MAAM,sBAA4C,MAAM;AAGjD,MAAM,gBAAgB,MAAM,cAA2C,IAAI;AAS3E,SAAS,uBAAuB,EAAE,SAAS,SAAS,GAAwB;AAClF,SACC,oBAAC,cAAc,UAAd,EAAuB,OAAO,WAAW,qBACxC,UACF;AAEF;AAGO,SAAS,cAAoC;AACnD,QAAM,eAAe,MAAM,WAAW,aAAa;AACnD,SAAO,gBAAgB;AACxB;",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,12 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { GeoShapeGeoStyle, useMaybeEditor } from "@tldraw/editor";
2
+ import {
3
+ assertExists,
4
+ createShapeId,
5
+ GeoShapeGeoStyle,
6
+ getIndicesBetween,
7
+ toRichText,
8
+ useMaybeEditor
9
+ } from "@tldraw/editor";
3
10
  import * as React from "react";
4
11
  import { EmbedDialog } from "../components/EmbedDialog.mjs";
5
12
  import { useA11y } from "../context/a11y.mjs";
@@ -70,20 +77,26 @@ function ToolsProvider({ overrides, children }) {
70
77
  onToolSelect(source, this);
71
78
  }
72
79
  },
73
- ...[...GeoShapeGeoStyle.values].map((id) => ({
74
- id,
75
- label: `tool.${id}`,
80
+ ...[...GeoShapeGeoStyle.values].map((geo) => ({
81
+ id: geo,
82
+ label: `tool.${geo}`,
76
83
  meta: {
77
- geo: id
84
+ geo
78
85
  },
79
- kbd: id === "rectangle" ? "r" : id === "ellipse" ? "o" : void 0,
80
- icon: "geo-" + id,
86
+ kbd: geo === "rectangle" ? "r" : geo === "ellipse" ? "o" : void 0,
87
+ icon: "geo-" + geo,
81
88
  onSelect(source) {
82
89
  editor.run(() => {
83
- editor.setStyleForNextShapes(GeoShapeGeoStyle, id);
90
+ editor.setStyleForNextShapes(GeoShapeGeoStyle, geo);
84
91
  editor.setCurrentTool("geo");
85
- onToolSelect(source, this, `geo-${id}`);
92
+ onToolSelect(source, this, `geo-${geo}`);
86
93
  });
94
+ },
95
+ onDragStart(source, info) {
96
+ onDragFromToolbarToCreateShape(editor, info, {
97
+ createShape: (id) => editor.createShape({ id, type: "geo", props: { w: 200, h: 200, geo } })
98
+ });
99
+ trackEvent("drag-tool", { source, id: "geo" });
87
100
  }
88
101
  })),
89
102
  {
@@ -94,6 +107,16 @@ function ToolsProvider({ overrides, children }) {
94
107
  onSelect(source) {
95
108
  editor.setCurrentTool("arrow");
96
109
  onToolSelect(source, this);
110
+ },
111
+ onDragStart(source, info) {
112
+ onDragFromToolbarToCreateShape(editor, info, {
113
+ createShape: (id) => editor.createShape({
114
+ id,
115
+ type: "arrow",
116
+ props: { start: { x: 0, y: 0 }, end: { x: 200, y: 0 } }
117
+ })
118
+ });
119
+ trackEvent("drag-tool", { source, id: "arrow" });
97
120
  }
98
121
  },
99
122
  {
@@ -104,6 +127,24 @@ function ToolsProvider({ overrides, children }) {
104
127
  onSelect(source) {
105
128
  editor.setCurrentTool("line");
106
129
  onToolSelect(source, this);
130
+ },
131
+ onDragStart(source, info) {
132
+ onDragFromToolbarToCreateShape(editor, info, {
133
+ createShape: (id) => {
134
+ const [start, end] = getIndicesBetween(null, null, 2);
135
+ editor.createShape({
136
+ id,
137
+ type: "line",
138
+ props: {
139
+ points: {
140
+ [start]: { id: start, index: start, x: 0, y: 200 },
141
+ [end]: { id: end, index: end, x: 200, y: 0 }
142
+ }
143
+ }
144
+ });
145
+ }
146
+ });
147
+ trackEvent("drag-tool", { source, id: "line" });
107
148
  }
108
149
  },
109
150
  {
@@ -114,6 +155,12 @@ function ToolsProvider({ overrides, children }) {
114
155
  onSelect(source) {
115
156
  editor.setCurrentTool("frame");
116
157
  onToolSelect(source, this);
158
+ },
159
+ onDragStart(source, info) {
160
+ onDragFromToolbarToCreateShape(editor, info, {
161
+ createShape: (id) => editor.createShape({ id, type: "frame" })
162
+ });
163
+ trackEvent("drag-tool", { source, id: "frame" });
117
164
  }
118
165
  },
119
166
  {
@@ -124,6 +171,16 @@ function ToolsProvider({ overrides, children }) {
124
171
  onSelect(source) {
125
172
  editor.setCurrentTool("text");
126
173
  onToolSelect(source, this);
174
+ },
175
+ onDragStart(source, info) {
176
+ onDragFromToolbarToCreateShape(editor, info, {
177
+ createShape: (id) => editor.createShape({ id, type: "text", props: { richText: toRichText("Text") } }),
178
+ onDragEnd: (id) => {
179
+ editor.setEditingShape(id);
180
+ editor.emit("select-all-text", { shapeId: id });
181
+ }
182
+ });
183
+ trackEvent("drag-tool", { source, id: "text" });
127
184
  }
128
185
  },
129
186
  {
@@ -144,6 +201,16 @@ function ToolsProvider({ overrides, children }) {
144
201
  onSelect(source) {
145
202
  editor.setCurrentTool("note");
146
203
  onToolSelect(source, this);
204
+ },
205
+ onDragStart(source, info) {
206
+ onDragFromToolbarToCreateShape(editor, info, {
207
+ createShape: (id) => editor.createShape({ id, type: "note" }),
208
+ onDragEnd: (id) => {
209
+ editor.setEditingShape(id);
210
+ editor.emit("select-all-text", { shapeId: id });
211
+ }
212
+ });
213
+ trackEvent("drag-tool", { source, id: "note" });
147
214
  }
148
215
  },
149
216
  {
@@ -184,7 +251,7 @@ function ToolsProvider({ overrides, children }) {
184
251
  return overrides(editor, tools2, helpers);
185
252
  }
186
253
  return tools2;
187
- }, [overrides, editor, helpers, onToolSelect]);
254
+ }, [overrides, editor, helpers, onToolSelect, trackEvent]);
188
255
  return /* @__PURE__ */ jsx(ToolsContext.Provider, { value: tools, children });
189
256
  }
190
257
  function useTools() {
@@ -194,9 +261,34 @@ function useTools() {
194
261
  }
195
262
  return ctx;
196
263
  }
264
+ function onDragFromToolbarToCreateShape(editor, info, opts) {
265
+ const { x, y } = editor.inputs.currentPagePoint;
266
+ const stoppingPoint = editor.markHistoryStoppingPoint("drag shape tool");
267
+ editor.setCurrentTool("select.translating");
268
+ const id = createShapeId();
269
+ opts.createShape(id);
270
+ const shape = assertExists(editor.getShape(id), "Shape not found");
271
+ const { w, h } = editor.getShapePageBounds(id);
272
+ editor.updateShape({ id, type: shape.type, x: x - w / 2, y: y - h / 2 });
273
+ editor.select(id);
274
+ editor.setCurrentTool("select.translating", {
275
+ ...info,
276
+ target: "shape",
277
+ shape: editor.getShape(id),
278
+ isCreating: true,
279
+ creatingMarkId: stoppingPoint,
280
+ onCreate() {
281
+ editor.setCurrentTool("select.idle");
282
+ editor.select(id);
283
+ opts.onDragEnd?.(id);
284
+ }
285
+ });
286
+ editor.getCurrentTool().setCurrentToolIdMask(shape.type);
287
+ }
197
288
  export {
198
289
  ToolsContext,
199
290
  ToolsProvider,
291
+ onDragFromToolbarToCreateShape,
200
292
  useTools
201
293
  };
202
294
  //# sourceMappingURL=useTools.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/ui/hooks/useTools.tsx"],
4
- "sourcesContent": ["import { Editor, GeoShapeGeoStyle, useMaybeEditor } from '@tldraw/editor'\nimport * as React from 'react'\nimport { EmbedDialog } from '../components/EmbedDialog'\nimport { TLUiIconJsx } from '../components/primitives/TldrawUiIcon'\nimport { useA11y } from '../context/a11y'\nimport { TLUiEventSource, useUiEvents } from '../context/events'\nimport { TLUiIconType } from '../icon-types'\nimport { TLUiOverrideHelpers, useDefaultHelpers } from '../overrides'\nimport { TLUiTranslationKey } from './useTranslation/TLUiTranslationKey'\nimport { useTranslation } from './useTranslation/useTranslation'\n\n/** @public */\nexport interface TLUiToolItem<\n\tTranslationKey extends string = string,\n\tIconType extends string = string,\n> {\n\tid: string\n\tlabel: TranslationKey\n\tshortcutsLabel?: TranslationKey\n\ticon: IconType | TLUiIconJsx\n\tonSelect(source: TLUiEventSource): void\n\t/**\n\t * The keyboard shortcut for this tool. This is a string that can be a single key,\n\t * or a combination of keys.\n\t * For example, `cmd+z` or `cmd+shift+z` or `cmd+u,ctrl+u`, or just `v` or `a`.\n\t * We have backwards compatibility with the old system, where we used to use\n\t * symbols to denote cmd/alt/shift, using `!` for shift, `$` for cmd, and `?` for alt.\n\t */\n\tkbd?: string\n\treadonlyOk?: boolean\n\tmeta?: {\n\t\t[key: string]: any\n\t}\n}\n\n/** @public */\nexport type TLUiToolsContextType = Record<string, TLUiToolItem>\n\n/** @internal */\nexport const ToolsContext = React.createContext<null | TLUiToolsContextType>(null)\n\n/** @public */\nexport interface TLUiToolsProviderProps {\n\toverrides?(\n\t\teditor: Editor,\n\t\ttools: TLUiToolsContextType,\n\t\thelpers: Partial<TLUiOverrideHelpers>\n\t): TLUiToolsContextType\n\tchildren: React.ReactNode\n}\n\n/** @internal */\nexport function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {\n\tconst editor = useMaybeEditor()\n\tconst trackEvent = useUiEvents()\n\n\tconst a11y = useA11y()\n\tconst msg = useTranslation()\n\tconst helpers = useDefaultHelpers()\n\n\tconst onToolSelect = React.useCallback(\n\t\t(\n\t\t\tsource: TLUiEventSource,\n\t\t\ttool: TLUiToolItem<TLUiTranslationKey, TLUiIconType>,\n\t\t\tid?: string\n\t\t) => {\n\t\t\ta11y.announce({ msg: msg(tool.label) })\n\t\t\ttrackEvent('select-tool', { source, id: id ?? tool.id })\n\t\t},\n\t\t[a11y, msg, trackEvent]\n\t)\n\n\tconst tools = React.useMemo<TLUiToolsContextType>(() => {\n\t\tif (!editor) return {}\n\t\tconst toolsArray: TLUiToolItem<TLUiTranslationKey, TLUiIconType>[] = [\n\t\t\t{\n\t\t\t\tid: 'select',\n\t\t\t\tlabel: 'tool.select',\n\t\t\t\ticon: 'tool-pointer',\n\t\t\t\tkbd: 'v',\n\t\t\t\treadonlyOk: true,\n\t\t\t\tonSelect(source) {\n\t\t\t\t\tif (editor.isIn('select')) {\n\t\t\t\t\t\t// There's a quirk of select mode, where editing a shape is a sub-state of select.\n\t\t\t\t\t\t// Because the text tool can be locked/sticky, we need to make sure we exit the\n\t\t\t\t\t\t// text tool.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// psst, if you're changing this code, also change the code\n\t\t\t\t\t\t// in strange-tools.test.ts! Sadly it's duplicated there.\n\t\t\t\t\t\tconst currentNode = editor.root.getCurrent()!\n\t\t\t\t\t\tcurrentNode.exit({}, currentNode.id)\n\t\t\t\t\t\tcurrentNode.enter({}, currentNode.id)\n\t\t\t\t\t}\n\t\t\t\t\teditor.setCurrentTool('select')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'hand',\n\t\t\t\tlabel: 'tool.hand',\n\t\t\t\ticon: 'tool-hand',\n\t\t\t\tkbd: 'h',\n\t\t\t\treadonlyOk: true,\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('hand')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'eraser',\n\t\t\t\tlabel: 'tool.eraser',\n\t\t\t\ticon: 'tool-eraser',\n\t\t\t\tkbd: 'e',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('eraser')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'draw',\n\t\t\t\tlabel: 'tool.draw',\n\t\t\t\ticon: 'tool-pencil',\n\t\t\t\tkbd: 'd,b,x',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('draw')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t...[...GeoShapeGeoStyle.values].map((id) => ({\n\t\t\t\tid,\n\t\t\t\tlabel: `tool.${id}` as TLUiTranslationKey,\n\t\t\t\tmeta: {\n\t\t\t\t\tgeo: id,\n\t\t\t\t},\n\t\t\t\tkbd: id === 'rectangle' ? 'r' : id === 'ellipse' ? 'o' : undefined,\n\t\t\t\ticon: ('geo-' + id) as TLUiIconType,\n\t\t\t\tonSelect(source: TLUiEventSource) {\n\t\t\t\t\teditor.run(() => {\n\t\t\t\t\t\teditor.setStyleForNextShapes(GeoShapeGeoStyle, id)\n\t\t\t\t\t\teditor.setCurrentTool('geo')\n\t\t\t\t\t\tonToolSelect(source, this, `geo-${id}`)\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t})),\n\t\t\t{\n\t\t\t\tid: 'arrow',\n\t\t\t\tlabel: 'tool.arrow',\n\t\t\t\ticon: 'tool-arrow',\n\t\t\t\tkbd: 'a',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('arrow')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'line',\n\t\t\t\tlabel: 'tool.line',\n\t\t\t\ticon: 'tool-line',\n\t\t\t\tkbd: 'l',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('line')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'frame',\n\t\t\t\tlabel: 'tool.frame',\n\t\t\t\ticon: 'tool-frame',\n\t\t\t\tkbd: 'f',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('frame')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'text',\n\t\t\t\tlabel: 'tool.text',\n\t\t\t\ticon: 'tool-text',\n\t\t\t\tkbd: 't',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('text')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'asset',\n\t\t\t\tlabel: 'tool.media',\n\t\t\t\ticon: 'tool-media',\n\t\t\t\tkbd: 'cmd+u,ctrl+u',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\thelpers.insertMedia()\n\t\t\t\t\tonToolSelect(source, this, 'media')\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'note',\n\t\t\t\tlabel: 'tool.note',\n\t\t\t\ticon: 'tool-note',\n\t\t\t\tkbd: 'n',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('note')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'laser',\n\t\t\t\tlabel: 'tool.laser',\n\t\t\t\treadonlyOk: true,\n\t\t\t\ticon: 'tool-laser',\n\t\t\t\tkbd: 'k',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('laser')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'embed',\n\t\t\t\tlabel: 'tool.embed',\n\t\t\t\ticon: 'dot',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\thelpers.addDialog({ component: EmbedDialog })\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'highlight',\n\t\t\t\tlabel: 'tool.highlight',\n\t\t\t\ticon: 'tool-highlight',\n\t\t\t\t// TODO: pick a better shortcut\n\t\t\t\tkbd: 'shift+d',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('highlight')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t]\n\n\t\ttoolsArray.forEach((t) => (t.onSelect = t.onSelect.bind(t)))\n\n\t\tconst tools = Object.fromEntries(toolsArray.map((t) => [t.id, t]))\n\n\t\tif (overrides) {\n\t\t\treturn overrides(editor, tools, helpers)\n\t\t}\n\n\t\treturn tools\n\t}, [overrides, editor, helpers, onToolSelect])\n\n\treturn <ToolsContext.Provider value={tools}>{children}</ToolsContext.Provider>\n}\n\n/** @public */\nexport function useTools() {\n\tconst ctx = React.useContext(ToolsContext)\n\n\tif (!ctx) {\n\t\tthrow new Error('useTools must be used within a ToolProvider')\n\t}\n\n\treturn ctx\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tassertExists,\n\tcreateShapeId,\n\tEditor,\n\tGeoShapeGeoStyle,\n\tgetIndicesBetween,\n\tTLLineShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\ttoRichText,\n\tuseMaybeEditor,\n} from '@tldraw/editor'\nimport * as React from 'react'\nimport { EmbedDialog } from '../components/EmbedDialog'\nimport { TLUiIconJsx } from '../components/primitives/TldrawUiIcon'\nimport { useA11y } from '../context/a11y'\nimport { TLUiEventSource, useUiEvents } from '../context/events'\nimport { TLUiIconType } from '../icon-types'\nimport { TLUiOverrideHelpers, useDefaultHelpers } from '../overrides'\nimport { TLUiTranslationKey } from './useTranslation/TLUiTranslationKey'\nimport { useTranslation } from './useTranslation/useTranslation'\n\n/** @public */\nexport interface TLUiToolItem<\n\tTranslationKey extends string = string,\n\tIconType extends string = string,\n> {\n\tid: string\n\tlabel: TranslationKey\n\tshortcutsLabel?: TranslationKey\n\ticon: IconType | TLUiIconJsx\n\tonSelect(source: TLUiEventSource): void\n\tonDragStart?(source: TLUiEventSource, info: TLPointerEventInfo): void\n\t/**\n\t * The keyboard shortcut for this tool. This is a string that can be a single key,\n\t * or a combination of keys.\n\t * For example, `cmd+z` or `cmd+shift+z` or `cmd+u,ctrl+u`, or just `v` or `a`.\n\t * We have backwards compatibility with the old system, where we used to use\n\t * symbols to denote cmd/alt/shift, using `!` for shift, `$` for cmd, and `?` for alt.\n\t */\n\tkbd?: string\n\treadonlyOk?: boolean\n\tmeta?: {\n\t\t[key: string]: any\n\t}\n}\n\n/** @public */\nexport type TLUiToolsContextType = Record<string, TLUiToolItem>\n\n/** @internal */\nexport const ToolsContext = React.createContext<null | TLUiToolsContextType>(null)\n\n/** @public */\nexport interface TLUiToolsProviderProps {\n\toverrides?(\n\t\teditor: Editor,\n\t\ttools: TLUiToolsContextType,\n\t\thelpers: Partial<TLUiOverrideHelpers>\n\t): TLUiToolsContextType\n\tchildren: React.ReactNode\n}\n\n/** @internal */\nexport function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {\n\tconst editor = useMaybeEditor()\n\tconst trackEvent = useUiEvents()\n\n\tconst a11y = useA11y()\n\tconst msg = useTranslation()\n\tconst helpers = useDefaultHelpers()\n\n\tconst onToolSelect = React.useCallback(\n\t\t(\n\t\t\tsource: TLUiEventSource,\n\t\t\ttool: TLUiToolItem<TLUiTranslationKey, TLUiIconType>,\n\t\t\tid?: string\n\t\t) => {\n\t\t\ta11y.announce({ msg: msg(tool.label) })\n\t\t\ttrackEvent('select-tool', { source, id: id ?? tool.id })\n\t\t},\n\t\t[a11y, msg, trackEvent]\n\t)\n\n\tconst tools = React.useMemo<TLUiToolsContextType>(() => {\n\t\tif (!editor) return {}\n\t\tconst toolsArray: TLUiToolItem<TLUiTranslationKey, TLUiIconType>[] = [\n\t\t\t{\n\t\t\t\tid: 'select',\n\t\t\t\tlabel: 'tool.select',\n\t\t\t\ticon: 'tool-pointer',\n\t\t\t\tkbd: 'v',\n\t\t\t\treadonlyOk: true,\n\t\t\t\tonSelect(source) {\n\t\t\t\t\tif (editor.isIn('select')) {\n\t\t\t\t\t\t// There's a quirk of select mode, where editing a shape is a sub-state of select.\n\t\t\t\t\t\t// Because the text tool can be locked/sticky, we need to make sure we exit the\n\t\t\t\t\t\t// text tool.\n\t\t\t\t\t\t//\n\t\t\t\t\t\t// psst, if you're changing this code, also change the code\n\t\t\t\t\t\t// in strange-tools.test.ts! Sadly it's duplicated there.\n\t\t\t\t\t\tconst currentNode = editor.root.getCurrent()!\n\t\t\t\t\t\tcurrentNode.exit({}, currentNode.id)\n\t\t\t\t\t\tcurrentNode.enter({}, currentNode.id)\n\t\t\t\t\t}\n\t\t\t\t\teditor.setCurrentTool('select')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'hand',\n\t\t\t\tlabel: 'tool.hand',\n\t\t\t\ticon: 'tool-hand',\n\t\t\t\tkbd: 'h',\n\t\t\t\treadonlyOk: true,\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('hand')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'eraser',\n\t\t\t\tlabel: 'tool.eraser',\n\t\t\t\ticon: 'tool-eraser',\n\t\t\t\tkbd: 'e',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('eraser')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'draw',\n\t\t\t\tlabel: 'tool.draw',\n\t\t\t\ticon: 'tool-pencil',\n\t\t\t\tkbd: 'd,b,x',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('draw')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t...[...GeoShapeGeoStyle.values].map((geo) => ({\n\t\t\t\tid: geo,\n\t\t\t\tlabel: `tool.${geo}` as TLUiTranslationKey,\n\t\t\t\tmeta: {\n\t\t\t\t\tgeo,\n\t\t\t\t},\n\t\t\t\tkbd: geo === 'rectangle' ? 'r' : geo === 'ellipse' ? 'o' : undefined,\n\t\t\t\ticon: ('geo-' + geo) as TLUiIconType,\n\t\t\t\tonSelect(source: TLUiEventSource) {\n\t\t\t\t\teditor.run(() => {\n\t\t\t\t\t\teditor.setStyleForNextShapes(GeoShapeGeoStyle, geo)\n\t\t\t\t\t\teditor.setCurrentTool('geo')\n\t\t\t\t\t\tonToolSelect(source, this, `geo-${geo}`)\n\t\t\t\t\t})\n\t\t\t\t},\n\t\t\t\tonDragStart(source: TLUiEventSource, info: TLPointerEventInfo) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) =>\n\t\t\t\t\t\t\teditor.createShape({ id, type: 'geo', props: { w: 200, h: 200, geo } }),\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'geo' })\n\t\t\t\t},\n\t\t\t})),\n\t\t\t{\n\t\t\t\tid: 'arrow',\n\t\t\t\tlabel: 'tool.arrow',\n\t\t\t\ticon: 'tool-arrow',\n\t\t\t\tkbd: 'a',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('arrow')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t\tonDragStart(source: TLUiEventSource, info: TLPointerEventInfo) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) =>\n\t\t\t\t\t\t\teditor.createShape({\n\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\ttype: 'arrow',\n\t\t\t\t\t\t\t\tprops: { start: { x: 0, y: 0 }, end: { x: 200, y: 0 } },\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'arrow' })\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'line',\n\t\t\t\tlabel: 'tool.line',\n\t\t\t\ticon: 'tool-line',\n\t\t\t\tkbd: 'l',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('line')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t\tonDragStart(source, info) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) => {\n\t\t\t\t\t\t\tconst [start, end] = getIndicesBetween(null, null, 2)\n\t\t\t\t\t\t\teditor.createShape<TLLineShape>({\n\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\ttype: 'line',\n\t\t\t\t\t\t\t\tprops: {\n\t\t\t\t\t\t\t\t\tpoints: {\n\t\t\t\t\t\t\t\t\t\t[start]: { id: start, index: start, x: 0, y: 200 },\n\t\t\t\t\t\t\t\t\t\t[end]: { id: end, index: end, x: 200, y: 0 },\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'line' })\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'frame',\n\t\t\t\tlabel: 'tool.frame',\n\t\t\t\ticon: 'tool-frame',\n\t\t\t\tkbd: 'f',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('frame')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t\tonDragStart(source, info) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) => editor.createShape({ id, type: 'frame' }),\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'frame' })\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'text',\n\t\t\t\tlabel: 'tool.text',\n\t\t\t\ticon: 'tool-text',\n\t\t\t\tkbd: 't',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('text')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t\tonDragStart(source, info) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) =>\n\t\t\t\t\t\t\teditor.createShape({ id, type: 'text', props: { richText: toRichText('Text') } }),\n\t\t\t\t\t\tonDragEnd: (id) => {\n\t\t\t\t\t\t\teditor.setEditingShape(id)\n\t\t\t\t\t\t\teditor.emit('select-all-text', { shapeId: id })\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'text' })\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'asset',\n\t\t\t\tlabel: 'tool.media',\n\t\t\t\ticon: 'tool-media',\n\t\t\t\tkbd: 'cmd+u,ctrl+u',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\thelpers.insertMedia()\n\t\t\t\t\tonToolSelect(source, this, 'media')\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'note',\n\t\t\t\tlabel: 'tool.note',\n\t\t\t\ticon: 'tool-note',\n\t\t\t\tkbd: 'n',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('note')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t\tonDragStart(source, info) {\n\t\t\t\t\tonDragFromToolbarToCreateShape(editor, info, {\n\t\t\t\t\t\tcreateShape: (id) => editor.createShape({ id, type: 'note' }),\n\t\t\t\t\t\tonDragEnd: (id) => {\n\t\t\t\t\t\t\teditor.setEditingShape(id)\n\t\t\t\t\t\t\teditor.emit('select-all-text', { shapeId: id })\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\ttrackEvent('drag-tool', { source, id: 'note' })\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'laser',\n\t\t\t\tlabel: 'tool.laser',\n\t\t\t\treadonlyOk: true,\n\t\t\t\ticon: 'tool-laser',\n\t\t\t\tkbd: 'k',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('laser')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'embed',\n\t\t\t\tlabel: 'tool.embed',\n\t\t\t\ticon: 'dot',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\thelpers.addDialog({ component: EmbedDialog })\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tid: 'highlight',\n\t\t\t\tlabel: 'tool.highlight',\n\t\t\t\ticon: 'tool-highlight',\n\t\t\t\t// TODO: pick a better shortcut\n\t\t\t\tkbd: 'shift+d',\n\t\t\t\tonSelect(source) {\n\t\t\t\t\teditor.setCurrentTool('highlight')\n\t\t\t\t\tonToolSelect(source, this)\n\t\t\t\t},\n\t\t\t},\n\t\t]\n\n\t\ttoolsArray.forEach((t) => (t.onSelect = t.onSelect.bind(t)))\n\n\t\tconst tools = Object.fromEntries(toolsArray.map((t) => [t.id, t]))\n\n\t\tif (overrides) {\n\t\t\treturn overrides(editor, tools, helpers)\n\t\t}\n\n\t\treturn tools\n\t}, [overrides, editor, helpers, onToolSelect, trackEvent])\n\n\treturn <ToolsContext.Provider value={tools}>{children}</ToolsContext.Provider>\n}\n\n/** @public */\nexport function useTools() {\n\tconst ctx = React.useContext(ToolsContext)\n\n\tif (!ctx) {\n\t\tthrow new Error('useTools must be used within a ToolProvider')\n\t}\n\n\treturn ctx\n}\n\n/**\n * Options for {@link onDragFromToolbarToCreateShape}.\n * @public\n */\nexport interface OnDragFromToolbarToCreateShapesOpts {\n\t/**\n\t * Create the shape being dragged. You don't need to worry about positioning it, as it'll be\n\t * immediately updated with the correct position.\n\t */\n\tcreateShape(id: TLShapeId): void\n\t/**\n\t * Called once the drag interaction has finished.\n\t */\n\tonDragEnd?(id: TLShapeId): void\n}\n\n/**\n * A helper method to use in {@link TLUiToolItem#onDragStart} to create a shape by dragging it from\n * the toolbar.\n * @public\n */\nexport function onDragFromToolbarToCreateShape(\n\teditor: Editor,\n\tinfo: TLPointerEventInfo,\n\topts: OnDragFromToolbarToCreateShapesOpts\n) {\n\tconst { x, y } = editor.inputs.currentPagePoint\n\n\tconst stoppingPoint = editor.markHistoryStoppingPoint('drag shape tool')\n\teditor.setCurrentTool('select.translating')\n\n\tconst id = createShapeId()\n\topts.createShape(id)\n\tconst shape = assertExists(editor.getShape(id), 'Shape not found')\n\n\tconst { w, h } = editor.getShapePageBounds(id)!\n\teditor.updateShape({ id, type: shape.type, x: x - w / 2, y: y - h / 2 })\n\teditor.select(id)\n\n\teditor.setCurrentTool('select.translating', {\n\t\t...info,\n\t\ttarget: 'shape',\n\t\tshape: editor.getShape(id),\n\t\tisCreating: true,\n\t\tcreatingMarkId: stoppingPoint,\n\t\tonCreate() {\n\t\t\teditor.setCurrentTool('select.idle')\n\t\t\teditor.select(id)\n\t\t\topts.onDragEnd?.(id)\n\t\t},\n\t})\n\n\teditor.getCurrentTool().setCurrentToolIdMask(shape.type)\n}\n"],
5
+ "mappings": "AAmUQ;AAnUR;AAAA,EACC;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EAIA;AAAA,EACA;AAAA,OACM;AACP,YAAY,WAAW;AACvB,SAAS,mBAAmB;AAE5B,SAAS,eAAe;AACxB,SAA0B,mBAAmB;AAE7C,SAA8B,yBAAyB;AAEvD,SAAS,sBAAsB;AA+BxB,MAAM,eAAe,MAAM,cAA2C,IAAI;AAa1E,SAAS,cAAc,EAAE,WAAW,SAAS,GAA2B;AAC9E,QAAM,SAAS,eAAe;AAC9B,QAAM,aAAa,YAAY;AAE/B,QAAM,OAAO,QAAQ;AACrB,QAAM,MAAM,eAAe;AAC3B,QAAM,UAAU,kBAAkB;AAElC,QAAM,eAAe,MAAM;AAAA,IAC1B,CACC,QACA,MACA,OACI;AACJ,WAAK,SAAS,EAAE,KAAK,IAAI,KAAK,KAAK,EAAE,CAAC;AACtC,iBAAW,eAAe,EAAE,QAAQ,IAAI,MAAM,KAAK,GAAG,CAAC;AAAA,IACxD;AAAA,IACA,CAAC,MAAM,KAAK,UAAU;AAAA,EACvB;AAEA,QAAM,QAAQ,MAAM,QAA8B,MAAM;AACvD,QAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,UAAM,aAA+D;AAAA,MACpE;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,KAAK;AAAA,QACL,YAAY;AAAA,QACZ,SAAS,QAAQ;AAChB,cAAI,OAAO,KAAK,QAAQ,GAAG;AAO1B,kBAAM,cAAc,OAAO,KAAK,WAAW;AAC3C,wBAAY,KAAK,CAAC,GAAG,YAAY,EAAE;AACnC,wBAAY,MAAM,CAAC,GAAG,YAAY,EAAE;AAAA,UACrC;AACA,iBAAO,eAAe,QAAQ;AAC9B,uBAAa,QAAQ,IAAI;AAAA,QAC1B;AAAA,MACD;AAAA,MACA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,KAAK;AAAA,QACL,YAAY;AAAA,QACZ,SAAS,QAAQ;AAChB,iBAAO,eAAe,MAAM;AAC5B,uBAAa,QAAQ,IAAI;AAAA,QAC1B;AAAA,MACD;AAAA,MACA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,KAAK;AAAA,QACL,SAAS,QAAQ;AAChB,iBAAO,eAAe,QAAQ;AAC9B,uBAAa,QAAQ,IAAI;AAAA,QAC1B;AAAA,MACD;AAAA,MACA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,KAAK;AAAA,QACL,SAAS,QAAQ;AAChB,iBAAO,eAAe,MAAM;AAC5B,uBAAa,QAAQ,IAAI;AAAA,QAC1B;AAAA,MACD;AAAA,MACA,GAAG,CAAC,GAAG,iBAAiB,MAAM,EAAE,IAAI,CAAC,SAAS;AAAA,QAC7C,IAAI;AAAA,QACJ,OAAO,QAAQ,GAAG;AAAA,QAClB,MAAM;AAAA,UACL;AAAA,QACD;AAAA,QACA,KAAK,QAAQ,cAAc,MAAM,QAAQ,YAAY,MAAM;AAAA,QAC3D,MAAO,SAAS;AAAA,QAChB,SAAS,QAAyB;AACjC,iBAAO,IAAI,MAAM;AAChB,mBAAO,sBAAsB,kBAAkB,GAAG;AAClD,mBAAO,eAAe,KAAK;AAC3B,yBAAa,QAAQ,MAAM,OAAO,GAAG,EAAE;AAAA,UACxC,CAAC;AAAA,QACF;AAAA,QACA,YAAY,QAAyB,MAA0B;AAC9D,yCAA+B,QAAQ,MAAM;AAAA,YAC5C,aAAa,CAAC,OACb,OAAO,YAAY,EAAE,IAAI,MAAM,OAAO,OAAO,EAAE,GAAG,KAAK,GAAG,KAAK,IAAI,EAAE,CAAC;AAAA,UACxE,CAAC;AACD,qBAAW,aAAa,EAAE,QAAQ,IAAI,MAAM,CAAC;AAAA,QAC9C;AAAA,MACD,EAAE;AAAA,MACF;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,KAAK;AAAA,QACL,SAAS,QAAQ;AAChB,iBAAO,eAAe,OAAO;AAC7B,uBAAa,QAAQ,IAAI;AAAA,QAC1B;AAAA,QACA,YAAY,QAAyB,MAA0B;AAC9D,yCAA+B,QAAQ,MAAM;AAAA,YAC5C,aAAa,CAAC,OACb,OAAO,YAAY;AAAA,cAClB;AAAA,cACA,MAAM;AAAA,cACN,OAAO,EAAE,OAAO,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,KAAK,EAAE,GAAG,KAAK,GAAG,EAAE,EAAE;AAAA,YACvD,CAAC;AAAA,UACH,CAAC;AACD,qBAAW,aAAa,EAAE,QAAQ,IAAI,QAAQ,CAAC;AAAA,QAChD;AAAA,MACD;AAAA,MACA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,KAAK;AAAA,QACL,SAAS,QAAQ;AAChB,iBAAO,eAAe,MAAM;AAC5B,uBAAa,QAAQ,IAAI;AAAA,QAC1B;AAAA,QACA,YAAY,QAAQ,MAAM;AACzB,yCAA+B,QAAQ,MAAM;AAAA,YAC5C,aAAa,CAAC,OAAO;AACpB,oBAAM,CAAC,OAAO,GAAG,IAAI,kBAAkB,MAAM,MAAM,CAAC;AACpD,qBAAO,YAAyB;AAAA,gBAC/B;AAAA,gBACA,MAAM;AAAA,gBACN,OAAO;AAAA,kBACN,QAAQ;AAAA,oBACP,CAAC,KAAK,GAAG,EAAE,IAAI,OAAO,OAAO,OAAO,GAAG,GAAG,GAAG,IAAI;AAAA,oBACjD,CAAC,GAAG,GAAG,EAAE,IAAI,KAAK,OAAO,KAAK,GAAG,KAAK,GAAG,EAAE;AAAA,kBAC5C;AAAA,gBACD;AAAA,cACD,CAAC;AAAA,YACF;AAAA,UACD,CAAC;AACD,qBAAW,aAAa,EAAE,QAAQ,IAAI,OAAO,CAAC;AAAA,QAC/C;AAAA,MACD;AAAA,MACA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,KAAK;AAAA,QACL,SAAS,QAAQ;AAChB,iBAAO,eAAe,OAAO;AAC7B,uBAAa,QAAQ,IAAI;AAAA,QAC1B;AAAA,QACA,YAAY,QAAQ,MAAM;AACzB,yCAA+B,QAAQ,MAAM;AAAA,YAC5C,aAAa,CAAC,OAAO,OAAO,YAAY,EAAE,IAAI,MAAM,QAAQ,CAAC;AAAA,UAC9D,CAAC;AACD,qBAAW,aAAa,EAAE,QAAQ,IAAI,QAAQ,CAAC;AAAA,QAChD;AAAA,MACD;AAAA,MACA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,KAAK;AAAA,QACL,SAAS,QAAQ;AAChB,iBAAO,eAAe,MAAM;AAC5B,uBAAa,QAAQ,IAAI;AAAA,QAC1B;AAAA,QACA,YAAY,QAAQ,MAAM;AACzB,yCAA+B,QAAQ,MAAM;AAAA,YAC5C,aAAa,CAAC,OACb,OAAO,YAAY,EAAE,IAAI,MAAM,QAAQ,OAAO,EAAE,UAAU,WAAW,MAAM,EAAE,EAAE,CAAC;AAAA,YACjF,WAAW,CAAC,OAAO;AAClB,qBAAO,gBAAgB,EAAE;AACzB,qBAAO,KAAK,mBAAmB,EAAE,SAAS,GAAG,CAAC;AAAA,YAC/C;AAAA,UACD,CAAC;AACD,qBAAW,aAAa,EAAE,QAAQ,IAAI,OAAO,CAAC;AAAA,QAC/C;AAAA,MACD;AAAA,MACA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,KAAK;AAAA,QACL,SAAS,QAAQ;AAChB,kBAAQ,YAAY;AACpB,uBAAa,QAAQ,MAAM,OAAO;AAAA,QACnC;AAAA,MACD;AAAA,MACA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,KAAK;AAAA,QACL,SAAS,QAAQ;AAChB,iBAAO,eAAe,MAAM;AAC5B,uBAAa,QAAQ,IAAI;AAAA,QAC1B;AAAA,QACA,YAAY,QAAQ,MAAM;AACzB,yCAA+B,QAAQ,MAAM;AAAA,YAC5C,aAAa,CAAC,OAAO,OAAO,YAAY,EAAE,IAAI,MAAM,OAAO,CAAC;AAAA,YAC5D,WAAW,CAAC,OAAO;AAClB,qBAAO,gBAAgB,EAAE;AACzB,qBAAO,KAAK,mBAAmB,EAAE,SAAS,GAAG,CAAC;AAAA,YAC/C;AAAA,UACD,CAAC;AACD,qBAAW,aAAa,EAAE,QAAQ,IAAI,OAAO,CAAC;AAAA,QAC/C;AAAA,MACD;AAAA,MACA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,MAAM;AAAA,QACN,KAAK;AAAA,QACL,SAAS,QAAQ;AAChB,iBAAO,eAAe,OAAO;AAC7B,uBAAa,QAAQ,IAAI;AAAA,QAC1B;AAAA,MACD;AAAA,MACA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS,QAAQ;AAChB,kBAAQ,UAAU,EAAE,WAAW,YAAY,CAAC;AAC5C,uBAAa,QAAQ,IAAI;AAAA,QAC1B;AAAA,MACD;AAAA,MACA;AAAA,QACC,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,MAAM;AAAA;AAAA,QAEN,KAAK;AAAA,QACL,SAAS,QAAQ;AAChB,iBAAO,eAAe,WAAW;AACjC,uBAAa,QAAQ,IAAI;AAAA,QAC1B;AAAA,MACD;AAAA,IACD;AAEA,eAAW,QAAQ,CAAC,MAAO,EAAE,WAAW,EAAE,SAAS,KAAK,CAAC,CAAE;AAE3D,UAAMA,SAAQ,OAAO,YAAY,WAAW,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAEjE,QAAI,WAAW;AACd,aAAO,UAAU,QAAQA,QAAO,OAAO;AAAA,IACxC;AAEA,WAAOA;AAAA,EACR,GAAG,CAAC,WAAW,QAAQ,SAAS,cAAc,UAAU,CAAC;AAEzD,SAAO,oBAAC,aAAa,UAAb,EAAsB,OAAO,OAAQ,UAAS;AACvD;AAGO,SAAS,WAAW;AAC1B,QAAM,MAAM,MAAM,WAAW,YAAY;AAEzC,MAAI,CAAC,KAAK;AACT,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC9D;AAEA,SAAO;AACR;AAuBO,SAAS,+BACf,QACA,MACA,MACC;AACD,QAAM,EAAE,GAAG,EAAE,IAAI,OAAO,OAAO;AAE/B,QAAM,gBAAgB,OAAO,yBAAyB,iBAAiB;AACvE,SAAO,eAAe,oBAAoB;AAE1C,QAAM,KAAK,cAAc;AACzB,OAAK,YAAY,EAAE;AACnB,QAAM,QAAQ,aAAa,OAAO,SAAS,EAAE,GAAG,iBAAiB;AAEjE,QAAM,EAAE,GAAG,EAAE,IAAI,OAAO,mBAAmB,EAAE;AAC7C,SAAO,YAAY,EAAE,IAAI,MAAM,MAAM,MAAM,GAAG,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;AACvE,SAAO,OAAO,EAAE;AAEhB,SAAO,eAAe,sBAAsB;AAAA,IAC3C,GAAG;AAAA,IACH,QAAQ;AAAA,IACR,OAAO,OAAO,SAAS,EAAE;AAAA,IACzB,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,WAAW;AACV,aAAO,eAAe,aAAa;AACnC,aAAO,OAAO,EAAE;AAChB,WAAK,YAAY,EAAE;AAAA,IACpB;AAAA,EACD,CAAC;AAED,SAAO,eAAe,EAAE,qBAAqB,MAAM,IAAI;AACxD;",
6
6
  "names": ["tools"]
7
7
  }
@@ -1,8 +1,8 @@
1
- const version = "3.16.0-canary.ffdf566dd0a8";
1
+ const version = "3.16.0-internal.51e99e128bd4";
2
2
  const publishDates = {
3
3
  major: "2024-09-13T14:36:29.063Z",
4
- minor: "2025-08-06T13:55:07.190Z",
5
- patch: "2025-08-06T13:55:07.190Z"
4
+ minor: "2025-08-19T10:06:54.740Z",
5
+ patch: "2025-08-19T10:06:54.740Z"
6
6
  };
7
7
  export {
8
8
  publishDates,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/ui/version.ts"],
4
- "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.16.0-canary.ffdf566dd0a8'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-08-06T13:55:07.190Z',\n\tpatch: '2025-08-06T13:55:07.190Z',\n}\n"],
4
+ "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '3.16.0-internal.51e99e128bd4'\nexport const publishDates = {\n\tmajor: '2024-09-13T14:36:29.063Z',\n\tminor: '2025-08-19T10:06:54.740Z',\n\tpatch: '2025-08-19T10:06:54.740Z',\n}\n"],
5
5
  "mappings": "AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tldraw",
3
3
  "description": "A tiny little drawing editor.",
4
- "version": "3.16.0-canary.ffdf566dd0a8",
4
+ "version": "3.16.0-internal.51e99e128bd4",
5
5
  "author": {
6
6
  "name": "tldraw Inc.",
7
7
  "email": "hello@tldraw.com"
@@ -27,9 +27,9 @@
27
27
  ],
28
28
  "main": "dist-cjs/index.js",
29
29
  "scripts": {
30
- "test-ci": "lazy inherit",
31
- "test": "yarn run -T jest",
32
- "test-coverage": "lazy inherit",
30
+ "test-ci": "yarn run -T vitest run --passWithNoTests",
31
+ "test": "yarn run -T vitest --passWithNoTests",
32
+ "test-coverage": "yarn run -T vitest run --coverage --passWithNoTests",
33
33
  "predev": "node ./scripts/copy-css-files.mjs",
34
34
  "dev": "chokidar '../{editor/editor,tldraw/src/lib/ui}.css' -c 'node ./scripts/copy-css-files.mjs'",
35
35
  "prebuild": "node ./scripts/copy-css-files.mjs",
@@ -38,7 +38,8 @@
38
38
  "prepack": "yarn run -T tsx ../../internal/scripts/prepack.ts",
39
39
  "postpack": "../../internal/scripts/postpack.sh",
40
40
  "pack-tarball": "yarn pack",
41
- "lint": "yarn run -T tsx ../../internal/scripts/lint.ts"
41
+ "lint": "yarn run -T tsx ../../internal/scripts/lint.ts",
42
+ "context": "yarn run -T tsx ../../internal/scripts/context.ts"
42
43
  },
43
44
  "files": [
44
45
  "tldraw.css",
@@ -54,13 +55,13 @@
54
55
  "@tiptap/pm": "^2.9.1",
55
56
  "@tiptap/react": "^2.9.1",
56
57
  "@tiptap/starter-kit": "^2.9.1",
57
- "@tldraw/editor": "3.16.0-canary.ffdf566dd0a8",
58
- "@tldraw/store": "3.16.0-canary.ffdf566dd0a8",
58
+ "@tldraw/editor": "3.16.0-internal.51e99e128bd4",
59
+ "@tldraw/store": "3.16.0-internal.51e99e128bd4",
59
60
  "classnames": "^2.5.1",
60
61
  "hotkeys-js": "^3.13.9",
61
62
  "idb": "^7.1.1",
62
63
  "lz-string": "^1.5.0",
63
- "radix-ui": "^1.3.4"
64
+ "radix-ui": "^1.4.2"
64
65
  },
65
66
  "peerDependencies": {
66
67
  "react": "^18.2.0 || ^19.0.0",
@@ -68,40 +69,16 @@
68
69
  },
69
70
  "devDependencies": {
70
71
  "@peculiar/webcrypto": "^1.5.0",
71
- "@testing-library/jest-dom": "^5.17.0",
72
72
  "@testing-library/react": "^15.0.7",
73
73
  "@types/classnames": "^2.3.4",
74
74
  "@types/lz-string": "^1.5.0",
75
75
  "@types/react": "^18.3.18",
76
76
  "chokidar-cli": "^3.0.0",
77
- "jest-canvas-mock": "^2.5.2",
78
- "jest-environment-jsdom": "^29.7.0",
79
77
  "lazyrepo": "0.0.0-alpha.27",
80
78
  "react": "^18.3.1",
81
79
  "react-dom": "^18.3.1",
82
- "resize-observer-polyfill": "^1.5.1"
83
- },
84
- "jest": {
85
- "preset": "../../internal/config/jest/node/jest-preset.js",
86
- "testEnvironment": "../../../packages/utils/patchedJestJsDom.js",
87
- "fakeTimers": {
88
- "enableGlobally": true
89
- },
90
- "testPathIgnorePatterns": [
91
- "^.+\\.*.css$"
92
- ],
93
- "moduleNameMapper": {
94
- "^~(.*)": "<rootDir>/src/$1",
95
- "\\.(css|less|scss|sass)$": "identity-obj-proxy"
96
- },
97
- "setupFiles": [
98
- "raf/polyfill",
99
- "jest-canvas-mock",
100
- "<rootDir>/setupTests.js"
101
- ],
102
- "setupFilesAfterEnv": [
103
- "../../internal/config/setupJest.ts"
104
- ]
80
+ "resize-observer-polyfill": "^1.5.1",
81
+ "vitest": "^3.2.4"
105
82
  },
106
83
  "module": "dist-esm/index.mjs",
107
84
  "source": "src/index.ts",
package/src/index.ts CHANGED
@@ -25,6 +25,16 @@ export { DefaultA11yAnnouncer, useSelectedShapesAnnouncer } from './lib/ui/compo
25
25
  export { AccessibilityMenu } from './lib/ui/components/AccessibilityMenu'
26
26
  export { ColorSchemeMenu } from './lib/ui/components/ColorSchemeMenu'
27
27
  export { DefaultDialogs } from './lib/ui/components/Dialogs'
28
+ export {
29
+ TldrawUiColumn,
30
+ TldrawUiGrid,
31
+ TldrawUiOrientationProvider,
32
+ TldrawUiRow,
33
+ useTldrawUiOrientation,
34
+ type TldrawUiOrientationContext,
35
+ type TldrawUiOrientationProviderProps,
36
+ type TLUiLayoutProps,
37
+ } from './lib/ui/components/primitives/layout'
28
38
  export {
29
39
  TldrawUiMenuActionCheckboxItem,
30
40
  type TLUiMenuActionCheckboxItemProps,
@@ -156,6 +166,9 @@ export {
156
166
  type TLDefaultFont,
157
167
  type TLDefaultFonts,
158
168
  } from './lib/shapes/shared/defaultFonts'
169
+ export { getStrokePoints } from './lib/shapes/shared/freehand/getStrokePoints'
170
+ export { getSvgPathFromStrokePoints } from './lib/shapes/shared/freehand/svg'
171
+ export { type StrokeOptions, type StrokePoint } from './lib/shapes/shared/freehand/types'
159
172
  export {
160
173
  PlainTextLabel,
161
174
  TextLabel,
@@ -598,7 +611,9 @@ export { useMenuIsOpen } from './lib/ui/hooks/useMenuIsOpen'
598
611
  export { useReadonly } from './lib/ui/hooks/useReadonly'
599
612
  export { useRelevantStyles } from './lib/ui/hooks/useRelevantStyles'
600
613
  export {
614
+ onDragFromToolbarToCreateShape,
601
615
  useTools,
616
+ type OnDragFromToolbarToCreateShapesOpts,
602
617
  type TLUiToolItem,
603
618
  type TLUiToolsContextType,
604
619
  type TLUiToolsProviderProps,
@@ -31,7 +31,7 @@ export function TldrawScribble({ scribble, zoom, color, opacity, className }: TL
31
31
  <path
32
32
  className="tl-scribble"
33
33
  d={d}
34
- fill={color ?? `var(--color-${scribble.color})`}
34
+ fill={color ?? `var(--tl-color-${scribble.color})`}
35
35
  opacity={opacity ?? scribble.opacity}
36
36
  />
37
37
  </svg>
@@ -1,4 +1,5 @@
1
1
  import { TLArrowShape, createShapeId } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from '../../../test/TestEditor'
3
4
  import { ArrowShapeUtil } from './ArrowShapeUtil'
4
5
  import { updateArrowTargetState } from './arrowTargetState'
@@ -12,7 +13,7 @@ const ids = {
12
13
  arrow1: createShapeId('arrow1'),
13
14
  }
14
15
 
15
- jest.useFakeTimers()
16
+ vi.useFakeTimers()
16
17
 
17
18
  window.requestAnimationFrame = function requestAnimationFrame(cb) {
18
19
  return setTimeout(cb, 1000 / 60)
@@ -1,4 +1,5 @@
1
1
  import { IndexKey, TLArrowShape, TLShapeId, Vec, createShapeId } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from '../../../test/TestEditor'
3
4
  import { getArrowTargetState } from './arrowTargetState'
4
5
  import { getArrowBindings } from './shared'
@@ -13,7 +14,7 @@ global.cancelAnimationFrame = function cancelAnimationFrame(id) {
13
14
  clearTimeout(id)
14
15
  }
15
16
 
16
- jest.useFakeTimers()
17
+ vi.useFakeTimers()
17
18
 
18
19
  const ids = {
19
20
  box1: createShapeId('box1'),
@@ -242,7 +243,7 @@ describe('When pointing an end shape', () => {
242
243
  },
243
244
  })
244
245
 
245
- jest.advanceTimersByTime(1000)
246
+ vi.advanceTimersByTime(1000)
246
247
 
247
248
  arrow = editor.getCurrentPageShapes()[editor.getCurrentPageShapes().length - 1]
248
249
 
@@ -306,7 +307,7 @@ describe('When pointing an end shape', () => {
306
307
  })
307
308
 
308
309
  // Give time for the velocity to die down
309
- jest.advanceTimersByTime(1000)
310
+ vi.advanceTimersByTime(1000)
310
311
 
311
312
  arrow = editor.getCurrentPageShapes()[editor.getCurrentPageShapes().length - 1]
312
313
 
@@ -1,4 +1,5 @@
1
1
  import { HALF_PI, TLArrowShape, TLShapeId, createShapeId, toRichText } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from '../../../test/TestEditor'
3
4
  import { createOrUpdateArrowBinding, getArrowBindings } from './shared'
4
5
 
@@ -12,7 +13,7 @@ const ids = {
12
13
  arrow1: createShapeId('arrow1'),
13
14
  }
14
15
 
15
- jest.useFakeTimers()
16
+ vi.useFakeTimers()
16
17
 
17
18
  window.requestAnimationFrame = function requestAnimationFrame(cb) {
18
19
  return setTimeout(cb, 1000 / 60)
@@ -217,7 +218,7 @@ describe('Other cases when arrow are moved', () => {
217
218
  // When box one is not selected, unbinds box1 and keeps binding to box2
218
219
  editor.select(ids.arrow1, ids.box2, ids.box3)
219
220
  editor.alignShapes(editor.getSelectedShapeIds(), 'right')
220
- jest.advanceTimersByTime(1000)
221
+ vi.advanceTimersByTime(1000)
221
222
 
222
223
  expect(bindings()).toMatchObject({
223
224
  start: { toId: ids.box1, props: { isPrecise: false } },
@@ -227,7 +228,7 @@ describe('Other cases when arrow are moved', () => {
227
228
  // maintains bindings if they would still be over the same shape (but makes them precise), but unbinds others
228
229
  editor.select(ids.arrow1, ids.box3)
229
230
  editor.alignShapes(editor.getSelectedShapeIds(), 'top')
230
- jest.advanceTimersByTime(1000)
231
+ vi.advanceTimersByTime(1000)
231
232
 
232
233
  expect(bindings()).toMatchObject({
233
234
  start: { toId: ids.box1, props: { isPrecise: true } },
@@ -244,7 +245,7 @@ describe('Other cases when arrow are moved', () => {
244
245
  // When box one is not selected, unbinds box1 and keeps binding to box2
245
246
  editor.select(ids.arrow1, ids.box2, ids.box3)
246
247
  editor.distributeShapes(editor.getSelectedShapeIds(), 'horizontal')
247
- jest.advanceTimersByTime(1000)
248
+ vi.advanceTimersByTime(1000)
248
249
 
249
250
  expect(bindings()).toMatchObject({
250
251
  start: { toId: ids.box1, props: { isPrecise: false } },
@@ -254,7 +255,7 @@ describe('Other cases when arrow are moved', () => {
254
255
  // unbinds when only the arrow is selected (not its bound shapes) if the arrow itself has moved
255
256
  editor.select(ids.arrow1, ids.box3, ids.box4)
256
257
  editor.distributeShapes(editor.getSelectedShapeIds(), 'vertical')
257
- jest.advanceTimersByTime(1000)
258
+ vi.advanceTimersByTime(1000)
258
259
 
259
260
  // The arrow didn't actually move
260
261
  expect(bindings()).toMatchObject({
@@ -265,7 +266,7 @@ describe('Other cases when arrow are moved', () => {
265
266
  // The arrow will not move because it is still bound to another shape
266
267
  editor.updateShapes([{ id: ids.box4, type: 'geo', y: -600 }])
267
268
  editor.distributeShapes(editor.getSelectedShapeIds(), 'vertical')
268
- jest.advanceTimersByTime(1000)
269
+ vi.advanceTimersByTime(1000)
269
270
 
270
271
  expect(bindings()).toMatchObject({
271
272
  start: undefined,
@@ -31,6 +31,7 @@ import {
31
31
  clamp,
32
32
  debugFlags,
33
33
  exhaustiveSwitchError,
34
+ getColorValue,
34
35
  getDefaultColorTheme,
35
36
  getFontsFromRichText,
36
37
  invLerp,
@@ -785,8 +786,8 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
785
786
  lineHeight={TEXT_PROPS.lineHeight}
786
787
  align="middle"
787
788
  verticalAlign="middle"
789
+ labelColor={getColorValue(theme, shape.props.labelColor, 'solid')}
788
790
  richText={shape.props.richText}
789
- labelColor={theme[shape.props.labelColor].solid}
790
791
  textWidth={labelPosition.box.w - ARROW_LABEL_PADDING * 2 * shape.props.scale}
791
792
  isSelected={isSelected}
792
793
  padding={0}
@@ -934,8 +935,8 @@ export class ArrowShapeUtil extends ShapeUtil<TLArrowShape> {
934
935
  font={shape.props.font}
935
936
  align="middle"
936
937
  verticalAlign="middle"
938
+ labelColor={getColorValue(theme, shape.props.labelColor, 'solid')}
937
939
  richText={shape.props.richText}
938
- labelColor={theme[shape.props.labelColor].solid}
939
940
  bounds={getArrowLabelPosition(this.editor, shape)
940
941
  .box.clone()
941
942
  .expandBy(-ARROW_LABEL_PADDING * shape.props.scale)}
@@ -1077,7 +1078,7 @@ const ArrowSvg = track(function ArrowSvg({
1077
1078
  </defs>
1078
1079
  <g
1079
1080
  fill="none"
1080
- stroke={theme[shape.props.color].solid}
1081
+ stroke={getColorValue(theme, shape.props.color, 'solid')}
1081
1082
  strokeWidth={strokeWidth}
1082
1083
  strokeLinejoin="round"
1083
1084
  strokeLinecap="round"
@@ -98,7 +98,7 @@ export function ElbowArrowDebug({ arrow }: { arrow: TLArrowShape }) {
98
98
  y={fullBox.minY - 3}
99
99
  fontSize={10}
100
100
  fill="black"
101
- stroke="var(--color-background)"
101
+ stroke="var(--tl-color-background)"
102
102
  strokeWidth={2}
103
103
  paintOrder="stroke"
104
104
  >
@@ -109,7 +109,7 @@ export function ElbowArrowDebug({ arrow }: { arrow: TLArrowShape }) {
109
109
  y={info.A.expanded.y}
110
110
  fontSize={10}
111
111
  fill="black"
112
- stroke="var(--color-background)"
112
+ stroke="var(--tl-color-background)"
113
113
  strokeWidth={2}
114
114
  paintOrder="stroke"
115
115
  >
@@ -121,7 +121,7 @@ export function ElbowArrowDebug({ arrow }: { arrow: TLArrowShape }) {
121
121
  y={info.B.expanded.y}
122
122
  fontSize={10}
123
123
  fill="black"
124
- stroke="var(--color-background)"
124
+ stroke="var(--tl-color-background)"
125
125
  strokeWidth={2}
126
126
  paintOrder="stroke"
127
127
  >
@@ -1,5 +1,4 @@
1
1
  import { TestEditor } from '../../../test/TestEditor'
2
- import { DrawShapeTool } from './DrawShapeTool'
3
2
 
4
3
  let editor: TestEditor
5
4
 
@@ -10,10 +9,6 @@ afterEach(() => {
10
9
  editor?.dispose()
11
10
  })
12
11
 
13
- describe(DrawShapeTool, () => {
14
- return
15
- })
16
-
17
12
  describe('When in the idle state', () => {
18
13
  it('Returns to select on cancel', () => {
19
14
  editor.setCurrentTool('draw')