tldraw 3.15.0 → 3.16.0-canary.01f62b6d4455

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 (430) hide show
  1. package/dist-cjs/index.d.ts +271 -9
  2. package/dist-cjs/index.js +28 -2
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/canvas/TldrawCropHandles.js.map +2 -2
  5. package/dist-cjs/lib/canvas/TldrawScribble.js +1 -1
  6. package/dist-cjs/lib/canvas/TldrawScribble.js.map +2 -2
  7. package/dist-cjs/lib/defaultExternalContentHandlers.js +1 -0
  8. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  9. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +25 -39
  10. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  11. package/dist-cjs/lib/shapes/arrow/arrowLabel.js +16 -4
  12. package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +2 -2
  13. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js +1 -1
  14. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
  15. package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js +3 -3
  16. package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js.map +1 -1
  17. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +3 -0
  18. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  19. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +3 -3
  20. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
  21. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +1 -1
  22. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +1 -1
  23. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +12 -12
  24. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  25. package/dist-cjs/lib/shapes/frame/components/FrameHeading.js +1 -1
  26. package/dist-cjs/lib/shapes/frame/components/FrameHeading.js.map +2 -2
  27. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +2 -2
  28. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  29. package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js +2 -1
  30. package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js.map +2 -2
  31. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +5 -1
  32. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
  33. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -3
  34. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +1 -1
  35. package/dist-cjs/lib/shapes/line/LineShapeUtil.js +20 -2
  36. package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
  37. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +4 -4
  38. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  39. package/dist-cjs/lib/shapes/shared/ShapeFill.js +4 -4
  40. package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
  41. package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
  42. package/dist-cjs/lib/shapes/shared/usePrefersReducedMotion.js +10 -1
  43. package/dist-cjs/lib/shapes/shared/usePrefersReducedMotion.js.map +2 -2
  44. package/dist-cjs/lib/shapes/text/TextShapeUtil.js +2 -2
  45. package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
  46. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +3 -3
  47. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +1 -1
  48. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +25 -1
  49. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  50. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +12 -0
  51. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  52. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +43 -22
  53. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  54. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js +2 -15
  55. package/dist-cjs/lib/tools/SelectTool/childStates/Idle.js.map +2 -2
  56. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js +5 -0
  57. package/dist-cjs/lib/tools/SelectTool/childStates/PointingShape.js.map +2 -2
  58. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js +8 -0
  59. package/dist-cjs/lib/tools/SelectTool/childStates/Resizing.js.map +2 -2
  60. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js +8 -0
  61. package/dist-cjs/lib/tools/SelectTool/childStates/Rotating.js.map +2 -2
  62. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js +8 -0
  63. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  64. package/dist-cjs/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.js.map +2 -2
  65. package/dist-cjs/lib/ui/TldrawUi.js +14 -0
  66. package/dist-cjs/lib/ui/TldrawUi.js.map +3 -3
  67. package/dist-cjs/lib/ui/components/AccessibilityMenu.js +35 -0
  68. package/dist-cjs/lib/ui/components/AccessibilityMenu.js.map +7 -0
  69. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +12 -3
  70. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
  71. package/dist-cjs/lib/ui/components/DefaultMenuPanel.js +3 -2
  72. package/dist-cjs/lib/ui/components/DefaultMenuPanel.js.map +2 -2
  73. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +40 -0
  74. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +2 -2
  75. package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js +3 -3
  76. package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js.map +2 -2
  77. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +4 -4
  78. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
  79. package/dist-cjs/lib/ui/components/MobileStylePanel.js +5 -3
  80. package/dist-cjs/lib/ui/components/MobileStylePanel.js.map +2 -2
  81. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js +1 -1
  82. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js.map +2 -2
  83. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +2 -1
  84. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
  85. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js +3 -2
  86. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js.map +2 -2
  87. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js +2 -2
  88. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js.map +2 -2
  89. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +2 -0
  90. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
  91. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +171 -140
  92. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  93. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js +3 -3
  94. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +2 -2
  95. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js +26 -25
  96. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +3 -3
  97. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +1 -1
  98. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  99. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +66 -21
  100. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js.map +3 -3
  101. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +189 -80
  102. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +3 -3
  103. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +5 -4
  104. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
  105. package/dist-cjs/lib/ui/components/menu-items.js +6 -0
  106. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  107. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js +5 -16
  108. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +3 -3
  109. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -1
  110. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  111. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +3 -2
  112. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js.map +3 -3
  113. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +1 -0
  114. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  115. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +30 -7
  116. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  117. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +268 -0
  118. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +7 -0
  119. package/dist-cjs/lib/ui/components/primitives/layout.js +76 -0
  120. package/dist-cjs/lib/ui/components/primitives/layout.js.map +7 -0
  121. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuContext.js.map +2 -2
  122. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +25 -12
  123. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
  124. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +154 -20
  125. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  126. package/dist-cjs/lib/ui/context/TldrawUiContextProvider.js +3 -2
  127. package/dist-cjs/lib/ui/context/TldrawUiContextProvider.js.map +2 -2
  128. package/dist-cjs/lib/ui/context/actions.js +29 -7
  129. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  130. package/dist-cjs/lib/ui/context/events.js.map +2 -2
  131. package/dist-cjs/lib/ui/hooks/menu-hooks.js.map +2 -2
  132. package/dist-cjs/lib/ui/hooks/useTools.js +94 -9
  133. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  134. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  135. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +7 -0
  136. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  137. package/dist-cjs/lib/ui/kbd-utils.js +2 -1
  138. package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
  139. package/dist-cjs/lib/ui/version.js +3 -3
  140. package/dist-cjs/lib/ui/version.js.map +1 -1
  141. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js +1 -1
  142. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.js.map +2 -2
  143. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js +3 -2
  144. package/dist-cjs/lib/utils/tldr/buildFromV1Document.js.map +2 -2
  145. package/dist-esm/index.d.mts +271 -9
  146. package/dist-esm/index.mjs +44 -3
  147. package/dist-esm/index.mjs.map +2 -2
  148. package/dist-esm/lib/canvas/TldrawCropHandles.mjs.map +2 -2
  149. package/dist-esm/lib/canvas/TldrawScribble.mjs +1 -1
  150. package/dist-esm/lib/canvas/TldrawScribble.mjs.map +2 -2
  151. package/dist-esm/lib/defaultExternalContentHandlers.mjs +1 -0
  152. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  153. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +28 -39
  154. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  155. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +19 -5
  156. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +2 -2
  157. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs +1 -1
  158. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
  159. package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs +3 -3
  160. package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs.map +1 -1
  161. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +3 -0
  162. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  163. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +4 -3
  164. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
  165. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +1 -1
  166. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +1 -1
  167. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +13 -12
  168. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  169. package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs +1 -1
  170. package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs.map +2 -2
  171. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +3 -2
  172. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  173. package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs +2 -1
  174. package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs.map +2 -2
  175. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +6 -1
  176. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
  177. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -3
  178. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +1 -1
  179. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +21 -2
  180. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
  181. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +5 -4
  182. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  183. package/dist-esm/lib/shapes/shared/ShapeFill.mjs +5 -4
  184. package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
  185. package/dist-esm/lib/shapes/shared/freehand/svg.mjs.map +2 -2
  186. package/dist-esm/lib/shapes/shared/usePrefersReducedMotion.mjs +10 -1
  187. package/dist-esm/lib/shapes/shared/usePrefersReducedMotion.mjs.map +2 -2
  188. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +3 -2
  189. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
  190. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +3 -3
  191. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +1 -1
  192. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +26 -1
  193. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  194. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +13 -0
  195. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  196. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +43 -22
  197. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  198. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs +2 -15
  199. package/dist-esm/lib/tools/SelectTool/childStates/Idle.mjs.map +2 -2
  200. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs +5 -0
  201. package/dist-esm/lib/tools/SelectTool/childStates/PointingShape.mjs.map +2 -2
  202. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs +8 -0
  203. package/dist-esm/lib/tools/SelectTool/childStates/Resizing.mjs.map +2 -2
  204. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs +8 -0
  205. package/dist-esm/lib/tools/SelectTool/childStates/Rotating.mjs.map +2 -2
  206. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs +8 -0
  207. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  208. package/dist-esm/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.mjs.map +2 -2
  209. package/dist-esm/lib/ui/TldrawUi.mjs +16 -2
  210. package/dist-esm/lib/ui/TldrawUi.mjs.map +3 -3
  211. package/dist-esm/lib/ui/components/AccessibilityMenu.mjs +19 -0
  212. package/dist-esm/lib/ui/components/AccessibilityMenu.mjs.map +7 -0
  213. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +12 -3
  214. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
  215. package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs +3 -2
  216. package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs.map +2 -2
  217. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +40 -0
  218. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +2 -2
  219. package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs +3 -5
  220. package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs.map +2 -2
  221. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +4 -4
  222. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
  223. package/dist-esm/lib/ui/components/MobileStylePanel.mjs +6 -3
  224. package/dist-esm/lib/ui/components/MobileStylePanel.mjs.map +2 -2
  225. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs +1 -1
  226. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs.map +2 -2
  227. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +2 -1
  228. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
  229. package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs +3 -2
  230. package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs.map +2 -2
  231. package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs +2 -2
  232. package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs.map +2 -2
  233. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +3 -1
  234. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
  235. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +171 -140
  236. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  237. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs +3 -3
  238. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +2 -2
  239. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs +26 -25
  240. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +2 -2
  241. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +1 -1
  242. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  243. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs +56 -21
  244. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs.map +2 -2
  245. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +192 -81
  246. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +3 -3
  247. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +5 -4
  248. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
  249. package/dist-esm/lib/ui/components/menu-items.mjs +6 -0
  250. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  251. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +6 -6
  252. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +2 -2
  253. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +1 -1
  254. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  255. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs +3 -2
  256. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs.map +2 -2
  257. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +1 -0
  258. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  259. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +30 -7
  260. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  261. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +245 -0
  262. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +7 -0
  263. package/dist-esm/lib/ui/components/primitives/layout.mjs +46 -0
  264. package/dist-esm/lib/ui/components/primitives/layout.mjs.map +7 -0
  265. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuContext.mjs.map +2 -2
  266. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs +25 -12
  267. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
  268. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +162 -22
  269. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  270. package/dist-esm/lib/ui/context/TldrawUiContextProvider.mjs +3 -2
  271. package/dist-esm/lib/ui/context/TldrawUiContextProvider.mjs.map +2 -2
  272. package/dist-esm/lib/ui/context/actions.mjs +29 -7
  273. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  274. package/dist-esm/lib/ui/context/events.mjs.map +2 -2
  275. package/dist-esm/lib/ui/hooks/menu-hooks.mjs.map +2 -2
  276. package/dist-esm/lib/ui/hooks/useTools.mjs +102 -10
  277. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  278. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +7 -0
  279. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  280. package/dist-esm/lib/ui/kbd-utils.mjs +2 -1
  281. package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
  282. package/dist-esm/lib/ui/version.mjs +3 -3
  283. package/dist-esm/lib/ui/version.mjs.map +1 -1
  284. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs +1 -1
  285. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.mjs.map +2 -2
  286. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs +3 -2
  287. package/dist-esm/lib/utils/tldr/buildFromV1Document.mjs.map +2 -2
  288. package/package.json +9 -33
  289. package/src/index.ts +32 -1
  290. package/src/lib/canvas/TldrawCropHandles.tsx +2 -0
  291. package/src/lib/canvas/TldrawScribble.tsx +1 -1
  292. package/src/lib/defaultExternalContentHandlers.ts +2 -1
  293. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +2 -1
  294. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +4 -3
  295. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +12 -11
  296. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +29 -42
  297. package/src/lib/shapes/arrow/arrowLabel.ts +23 -3
  298. package/src/lib/shapes/arrow/arrowTargetState.ts +2 -1
  299. package/src/lib/shapes/arrow/elbow/ElbowArrowDebug.tsx +3 -3
  300. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +3 -0
  301. package/src/lib/shapes/draw/DrawShapeTool.test.ts +0 -5
  302. package/src/lib/shapes/draw/DrawShapeUtil.tsx +4 -3
  303. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
  304. package/src/lib/shapes/frame/FrameShapeUtil.tsx +21 -14
  305. package/src/lib/shapes/frame/components/FrameHeading.tsx +1 -1
  306. package/src/lib/shapes/geo/GeoShapeUtil.tsx +3 -2
  307. package/src/lib/shapes/geo/components/GeoShapeBody.tsx +2 -2
  308. package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +7 -1
  309. package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -3
  310. package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -3
  311. package/src/lib/shapes/line/LineShapeUtil.tsx +25 -3
  312. package/src/lib/shapes/line/__snapshots__/LineShapeUtil.test.tsx.snap +2 -2
  313. package/src/lib/shapes/note/NoteShapeUtil.tsx +9 -4
  314. package/src/lib/shapes/shared/ShapeFill.tsx +5 -4
  315. package/src/lib/shapes/shared/freehand/svg.ts +2 -0
  316. package/src/lib/shapes/shared/usePrefersReducedMotion.tsx +11 -1
  317. package/src/lib/shapes/text/TextShapeTool.test.ts +6 -5
  318. package/src/lib/shapes/text/TextShapeUtil.tsx +3 -2
  319. package/src/lib/shapes/video/VideoShapeUtil.tsx +3 -3
  320. package/src/lib/tools/EraserTool/childStates/Erasing.ts +34 -1
  321. package/src/lib/tools/EraserTool/childStates/Pointing.ts +20 -0
  322. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +54 -30
  323. package/src/lib/tools/SelectTool/childStates/Idle.ts +2 -24
  324. package/src/lib/tools/SelectTool/childStates/PointingShape.ts +7 -0
  325. package/src/lib/tools/SelectTool/childStates/Resizing.ts +12 -1
  326. package/src/lib/tools/SelectTool/childStates/Rotating.ts +11 -0
  327. package/src/lib/tools/SelectTool/childStates/Translating.ts +11 -1
  328. package/src/lib/tools/selection-logic/getHitShapeOnCanvasPointerDown.ts +1 -0
  329. package/src/lib/ui/TldrawUi.tsx +17 -2
  330. package/src/lib/ui/components/AccessibilityMenu.tsx +20 -0
  331. package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +15 -3
  332. package/src/lib/ui/components/DefaultMenuPanel.tsx +4 -3
  333. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +32 -0
  334. package/src/lib/ui/components/MainMenu/DefaultMainMenuContent.tsx +4 -4
  335. package/src/lib/ui/components/Minimap/MinimapManager.ts +4 -4
  336. package/src/lib/ui/components/MobileStylePanel.tsx +9 -6
  337. package/src/lib/ui/components/NavigationPanel/DefaultNavigationPanel.tsx +1 -1
  338. package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +3 -2
  339. package/src/lib/ui/components/SharePanel/PeopleMenuItem.tsx +4 -3
  340. package/src/lib/ui/components/SharePanel/UserPresenceColorPicker.tsx +3 -3
  341. package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +3 -1
  342. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +146 -107
  343. package/src/lib/ui/components/StylePanel/DoubleDropdownPicker.tsx +3 -3
  344. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +7 -6
  345. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +1 -1
  346. package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +55 -23
  347. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +212 -61
  348. package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +17 -12
  349. package/src/lib/ui/components/menu-items.tsx +8 -0
  350. package/src/lib/ui/components/primitives/TldrawUiButtonPicker.tsx +40 -37
  351. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +1 -1
  352. package/src/lib/ui/components/primitives/TldrawUiPopover.tsx +4 -2
  353. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +1 -0
  354. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +51 -12
  355. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +327 -0
  356. package/src/lib/ui/components/primitives/layout.tsx +107 -0
  357. package/src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx +0 -1
  358. package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +29 -16
  359. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +221 -19
  360. package/src/lib/ui/context/TldrawUiContextProvider.tsx +23 -20
  361. package/src/lib/ui/context/actions.tsx +29 -7
  362. package/src/lib/ui/context/events.tsx +4 -2
  363. package/src/lib/ui/hooks/menu-hooks.ts +1 -0
  364. package/src/lib/ui/hooks/useTools.tsx +140 -10
  365. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +7 -0
  366. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +7 -0
  367. package/src/lib/ui/kbd-utils.ts +2 -1
  368. package/src/lib/ui/version.ts +3 -3
  369. package/src/lib/ui.css +406 -292
  370. package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +21 -7
  371. package/src/lib/utils/excalidraw/putExcalidrawContent.ts +1 -1
  372. package/src/lib/utils/tldr/__snapshots__/buildFromV1Document.test.ts.snap +28 -7
  373. package/src/lib/utils/tldr/buildFromV1Document.ts +2 -1
  374. package/src/test/A11y.test.tsx +3 -2
  375. package/src/test/ClickManager.test.ts +7 -6
  376. package/src/test/Editor.test.tsx +20 -19
  377. package/src/test/EraserTool.test.ts +184 -13
  378. package/src/test/HandTool.test.ts +10 -9
  379. package/src/test/HighlightShape.test.ts +2 -1
  380. package/src/test/SelectTool.test.ts +40 -13
  381. package/src/test/TLUserPreferences.test.ts +4 -3
  382. package/src/test/TestEditor.ts +13 -15
  383. package/src/test/TldrawEditor.test.tsx +11 -10
  384. package/src/test/ZoomTool.test.ts +7 -6
  385. package/src/test/__snapshots__/drawing.test.ts.snap +2 -2
  386. package/src/test/__snapshots__/groups.test.tsx.snap +6 -6
  387. package/src/test/__snapshots__/resizing.test.ts.snap +2 -2
  388. package/src/test/arrows-megabus.test.tsx +17 -10
  389. package/src/test/bindings.test.tsx +24 -37
  390. package/src/test/bookmark-shapes.test.ts +1 -8
  391. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +23 -7
  392. package/src/test/commands/__snapshots__/packShapes.test.ts.snap +8 -8
  393. package/src/test/commands/__snapshots__/zoomToFit.test.ts.snap +2 -2
  394. package/src/test/commands/alignShapes.test.tsx +25 -24
  395. package/src/test/commands/animationSpeed.test.ts +2 -1
  396. package/src/test/commands/centerOnPoint.test.ts +3 -2
  397. package/src/test/commands/clipboard.test.ts +3 -2
  398. package/src/test/commands/createShapes.test.ts +2 -1
  399. package/src/test/commands/deletePage.test.ts +84 -1
  400. package/src/test/commands/deleteShapes.test.ts +2 -1
  401. package/src/test/commands/distributeShapes.test.tsx +11 -10
  402. package/src/test/commands/getSvgString.test.ts +2 -1
  403. package/src/test/commands/packShapes.test.ts +5 -4
  404. package/src/test/commands/resizeShape.test.ts +2 -1
  405. package/src/test/commands/rotateShapes.test.ts +7 -6
  406. package/src/test/commands/setCamera.test.ts +4 -3
  407. package/src/test/commands/setCurrentPage.test.ts +3 -2
  408. package/src/test/commands/stackShapes.test.ts +11 -10
  409. package/src/test/commands/stretch.test.tsx +13 -12
  410. package/src/test/createDeepLink.test.tsx +2 -1
  411. package/src/test/cropping.test.ts +3 -2
  412. package/src/test/drawing.test.ts +2 -1
  413. package/src/test/flipShapes.test.ts +4 -3
  414. package/src/test/frames.test.ts +25 -24
  415. package/src/test/getCulledShapes.test.tsx +3 -2
  416. package/src/test/groups.test.tsx +1 -1
  417. package/src/test/handleDeepLink.test.tsx +2 -1
  418. package/src/test/inner-outer-margin.test.ts +315 -0
  419. package/src/test/maxShapes.test.ts +3 -2
  420. package/src/test/modifiers.test.ts +5 -4
  421. package/src/test/navigation.test.ts +12 -11
  422. package/src/test/panning.test.ts +2 -1
  423. package/src/test/perf/perf.test.ts +2 -1
  424. package/src/test/registerDeepLinkListener.test.tsx +10 -9
  425. package/src/test/resizing.test.ts +39 -38
  426. package/src/test/select.test.tsx +4 -3
  427. package/src/test/selection-omnibus.test.ts +11 -10
  428. package/src/test/shapeutils.test.ts +398 -48
  429. package/src/test/translating.test.ts +9 -8
  430. package/tldraw.css +703 -603
@@ -1,9 +1,18 @@
1
- import { exhaustiveSwitchError, preventDefault } from '@tldraw/editor'
1
+ import {
2
+ exhaustiveSwitchError,
3
+ getPointerInfo,
4
+ preventDefault,
5
+ TLPointerEventInfo,
6
+ useEditor,
7
+ Vec,
8
+ VecModel,
9
+ } from '@tldraw/editor'
2
10
  import { ContextMenu as _ContextMenu } from 'radix-ui'
3
- import { useState } from 'react'
11
+ import { useMemo, useState } from 'react'
4
12
  import { unwrapLabel } from '../../../context/actions'
5
13
  import { TLUiEventSource } from '../../../context/events'
6
14
  import { useReadonly } from '../../../hooks/useReadonly'
15
+ import { TLUiToolItem } from '../../../hooks/useTools'
7
16
  import { TLUiTranslationKey } from '../../../hooks/useTranslation/TLUiTranslationKey'
8
17
  import { useTranslation } from '../../../hooks/useTranslation/useTranslation'
9
18
  import { kbdStr } from '../../../kbd-utils'
@@ -15,6 +24,7 @@ import { TldrawUiDropdownMenuItem } from '../TldrawUiDropdownMenu'
15
24
  import { TLUiIconJsx } from '../TldrawUiIcon'
16
25
  import { TldrawUiKbd } from '../TldrawUiKbd'
17
26
  import { TldrawUiToolbarButton } from '../TldrawUiToolbar'
27
+ import { tooltipManager } from '../TldrawUiTooltip'
18
28
  import { useTldrawUiMenuContext } from './TldrawUiMenuContext'
19
29
 
20
30
  /** @public */
@@ -63,6 +73,10 @@ export interface TLUiMenuItemProps<
63
73
  * Whether the item is selected.
64
74
  */
65
75
  isSelected?: boolean
76
+ /**
77
+ * The function to call when the item is dragged. If this is provided, the item will be draggable.
78
+ */
79
+ onDragStart?(source: TLUiEventSource, info: TLPointerEventInfo): void
66
80
  }
67
81
 
68
82
  /** @public @react */
@@ -81,6 +95,7 @@ export function TldrawUiMenuItem<
81
95
  onSelect,
82
96
  noClose,
83
97
  isSelected,
98
+ onDragStart,
84
99
  }: TLUiMenuItemProps<TranslationKey, IconType>) {
85
100
  const { type: menuType, sourceId } = useTldrawUiMenuContext()
86
101
 
@@ -105,7 +120,6 @@ export function TldrawUiMenuItem<
105
120
  type="menu"
106
121
  data-testid={`${sourceId}.${id}`}
107
122
  disabled={disabled}
108
- title={titleStr}
109
123
  onClick={(e) => {
110
124
  if (noClose) {
111
125
  preventDefault(e)
@@ -131,7 +145,6 @@ export function TldrawUiMenuItem<
131
145
  return (
132
146
  <_ContextMenu.Item
133
147
  dir="ltr"
134
- title={titleStr}
135
148
  draggable={false}
136
149
  className="tlui-button tlui-button__menu"
137
150
  data-testid={`${sourceId}.${id}`}
@@ -153,20 +166,6 @@ export function TldrawUiMenuItem<
153
166
  </_ContextMenu.Item>
154
167
  )
155
168
  }
156
- case 'panel': {
157
- return (
158
- <TldrawUiButton
159
- data-testid={`${sourceId}.${id}`}
160
- type="menu"
161
- title={titleStr}
162
- disabled={disabled}
163
- onClick={() => onSelect(sourceId)}
164
- >
165
- <TldrawUiButtonLabel>{labelStr}</TldrawUiButtonLabel>
166
- {spinner ? <Spinner /> : icon && <TldrawUiButtonIcon icon={icon} />}
167
- </TldrawUiButton>
168
- )
169
- }
170
169
  case 'small-icons':
171
170
  case 'icons': {
172
171
  return (
@@ -207,6 +206,20 @@ export function TldrawUiMenuItem<
207
206
  )
208
207
  }
209
208
  case 'toolbar': {
209
+ if (onDragStart) {
210
+ return (
211
+ <DraggableToolbarButton
212
+ id={id}
213
+ icon={icon}
214
+ onSelect={onSelect}
215
+ onDragStart={onDragStart}
216
+ labelToUse={labelToUse}
217
+ titleStr={titleStr}
218
+ disabled={disabled}
219
+ isSelected={isSelected}
220
+ />
221
+ )
222
+ }
210
223
  return (
211
224
  <TldrawUiToolbarButton
212
225
  aria-label={labelStr}
@@ -227,12 +240,26 @@ export function TldrawUiMenuItem<
227
240
  )
228
241
  }
229
242
  case 'toolbar-overflow': {
243
+ if (onDragStart) {
244
+ return (
245
+ <DraggableToolbarButton
246
+ id={id}
247
+ icon={icon}
248
+ onSelect={onSelect}
249
+ onDragStart={onDragStart}
250
+ labelToUse={labelToUse}
251
+ titleStr={titleStr}
252
+ disabled={disabled}
253
+ isSelected={isSelected}
254
+ overflow
255
+ />
256
+ )
257
+ }
230
258
  return (
231
259
  <TldrawUiToolbarButton
232
260
  aria-label={labelStr}
233
261
  aria-pressed={isSelected ? 'true' : 'false'}
234
262
  isActive={isSelected}
235
- className="tlui-button-grid__button"
236
263
  data-testid={`tools.more.${id}`}
237
264
  data-value={id}
238
265
  disabled={disabled}
@@ -249,3 +276,178 @@ export function TldrawUiMenuItem<
249
276
  }
250
277
  }
251
278
  }
279
+
280
+ function useDraggableEvents(
281
+ onDragStart: TLUiToolItem['onDragStart'],
282
+ onSelect: TLUiToolItem['onSelect']
283
+ ) {
284
+ const editor = useEditor()
285
+ const events = useMemo(() => {
286
+ let state = { name: 'idle' } as
287
+ | {
288
+ name: 'idle'
289
+ }
290
+ | {
291
+ name: 'pointing'
292
+ screenSpaceStart: VecModel
293
+ }
294
+ | {
295
+ name: 'dragging'
296
+ screenSpaceStart: VecModel
297
+ }
298
+ | {
299
+ name: 'dragged'
300
+ }
301
+
302
+ function handlePointerDown(e: React.PointerEvent<HTMLButtonElement>) {
303
+ state = {
304
+ name: 'pointing',
305
+ screenSpaceStart: { x: e.clientX, y: e.clientY },
306
+ }
307
+
308
+ e.currentTarget.setPointerCapture(e.pointerId)
309
+ }
310
+
311
+ function handlePointerMove(e: React.PointerEvent<HTMLButtonElement>) {
312
+ if ((e as any).isSpecialRedispatchedEvent) return
313
+
314
+ if (state.name === 'pointing') {
315
+ const distanceSq = Vec.Dist2(state.screenSpaceStart, { x: e.clientX, y: e.clientY })
316
+ if (
317
+ distanceSq >
318
+ (editor.getInstanceState().isCoarsePointer
319
+ ? editor.options.uiCoarseDragDistanceSquared
320
+ : editor.options.uiDragDistanceSquared)
321
+ ) {
322
+ const screenSpaceStart = state.screenSpaceStart
323
+ state = {
324
+ name: 'dragging',
325
+ screenSpaceStart,
326
+ }
327
+
328
+ editor.run(() => {
329
+ editor.setCurrentTool('select')
330
+
331
+ // Set origin point
332
+ editor.dispatch({
333
+ type: 'pointer',
334
+ target: 'canvas',
335
+ name: 'pointer_down',
336
+ ...getPointerInfo(e),
337
+ point: screenSpaceStart,
338
+ })
339
+
340
+ // Pointer down potentially selects shapes, so we need to deselect them.
341
+ editor.selectNone()
342
+
343
+ // start drag
344
+ onDragStart?.('toolbar', {
345
+ type: 'pointer',
346
+ target: 'canvas',
347
+ name: 'pointer_move',
348
+ ...getPointerInfo(e),
349
+ point: screenSpaceStart,
350
+ })
351
+
352
+ tooltipManager.hideAllTooltips()
353
+ editor.getContainer().focus()
354
+ })
355
+ }
356
+ }
357
+ }
358
+
359
+ function handlePointerUp(e: React.PointerEvent<HTMLButtonElement>) {
360
+ if ((e as any).isSpecialRedispatchedEvent) return
361
+
362
+ e.currentTarget.releasePointerCapture(e.pointerId)
363
+
364
+ editor.dispatch({
365
+ type: 'pointer',
366
+ target: 'canvas',
367
+ name: 'pointer_up',
368
+ ...getPointerInfo(e),
369
+ })
370
+ }
371
+
372
+ function handleClick() {
373
+ if (state.name === 'dragging' || state.name === 'dragged') {
374
+ state = { name: 'idle' }
375
+ return true
376
+ }
377
+
378
+ state = { name: 'idle' }
379
+ onSelect?.('toolbar')
380
+ }
381
+
382
+ return {
383
+ onPointerDown: handlePointerDown,
384
+ onPointerMove: handlePointerMove,
385
+ onPointerUp: handlePointerUp,
386
+ onClick: handleClick,
387
+ }
388
+ }, [onDragStart, editor, onSelect])
389
+
390
+ return events
391
+ }
392
+
393
+ function DraggableToolbarButton({
394
+ id,
395
+ labelToUse,
396
+ titleStr,
397
+ disabled,
398
+ isSelected,
399
+ icon,
400
+ onSelect,
401
+ onDragStart,
402
+ overflow,
403
+ }: {
404
+ id: string
405
+ disabled: boolean
406
+ labelToUse?: string
407
+ titleStr?: string
408
+ isSelected?: boolean
409
+ icon: TLUiMenuItemProps['icon']
410
+ onSelect: TLUiMenuItemProps['onSelect']
411
+ onDragStart: TLUiMenuItemProps['onDragStart']
412
+ overflow?: boolean
413
+ }) {
414
+ const events = useDraggableEvents(onDragStart, onSelect)
415
+
416
+ if (overflow) {
417
+ return (
418
+ <TldrawUiToolbarButton
419
+ aria-label={labelToUse}
420
+ aria-pressed={isSelected ? 'true' : 'false'}
421
+ isActive={isSelected}
422
+ className="tlui-button-grid__button"
423
+ data-testid={`tools.more.${id}`}
424
+ data-value={id}
425
+ disabled={disabled}
426
+ title={titleStr}
427
+ type="icon"
428
+ {...events}
429
+ >
430
+ <TldrawUiButtonIcon icon={icon!} />
431
+ </TldrawUiToolbarButton>
432
+ )
433
+ }
434
+
435
+ return (
436
+ <TldrawUiToolbarButton
437
+ aria-label={labelToUse}
438
+ aria-pressed={isSelected ? 'true' : 'false'}
439
+ data-testid={`tools.${id}`}
440
+ data-value={id}
441
+ disabled={disabled}
442
+ onTouchStart={(e) => {
443
+ preventDefault(e)
444
+ onSelect('toolbar')
445
+ }}
446
+ title={titleStr}
447
+ type="tool"
448
+ {...events}
449
+ >
450
+ <TldrawUiButtonIcon icon={icon!} />
451
+ </TldrawUiToolbarButton>
452
+ )
453
+ }
@@ -1,6 +1,7 @@
1
1
  import { RecursivePartial, defaultUserPreferences, track, useMaybeEditor } from '@tldraw/editor'
2
2
  import { ReactNode } from 'react'
3
3
  import { TLUiAssetUrls, useDefaultUiAssetUrlsWithOverrides } from '../assetUrls'
4
+ import { TldrawUiTooltipProvider } from '../components/primitives/TldrawUiTooltip'
4
5
  import { ToolsProvider } from '../hooks/useTools'
5
6
  import { TldrawUiTranslationProvider } from '../hooks/useTranslation/useTranslation'
6
7
  import {
@@ -72,26 +73,28 @@ export const TldrawUiContextProvider = track(function TldrawUiContextProvider({
72
73
  const editor = useMaybeEditor()
73
74
  return (
74
75
  <MimeTypeContext.Provider value={mediaMimeTypes}>
75
- <AssetUrlsProvider assetUrls={useDefaultUiAssetUrlsWithOverrides(assetUrls)}>
76
- <TldrawUiTranslationProvider
77
- overrides={useMergedTranslationOverrides(overrides)}
78
- locale={editor?.user.getLocale() ?? defaultUserPreferences.locale}
79
- >
80
- <TldrawUiEventsProvider onEvent={onUiEvent}>
81
- <TldrawUiToastsProvider>
82
- <TldrawUiDialogsProvider context={'tla'}>
83
- <TldrawUiA11yProvider>
84
- <BreakPointProvider forceMobile={forceMobile}>
85
- <TldrawUiComponentsProvider overrides={components}>
86
- <InternalProviders overrides={overrides}>{children}</InternalProviders>
87
- </TldrawUiComponentsProvider>
88
- </BreakPointProvider>
89
- </TldrawUiA11yProvider>
90
- </TldrawUiDialogsProvider>
91
- </TldrawUiToastsProvider>
92
- </TldrawUiEventsProvider>
93
- </TldrawUiTranslationProvider>
94
- </AssetUrlsProvider>
76
+ <TldrawUiTooltipProvider>
77
+ <AssetUrlsProvider assetUrls={useDefaultUiAssetUrlsWithOverrides(assetUrls)}>
78
+ <TldrawUiTranslationProvider
79
+ overrides={useMergedTranslationOverrides(overrides)}
80
+ locale={editor?.user.getLocale() ?? defaultUserPreferences.locale}
81
+ >
82
+ <TldrawUiEventsProvider onEvent={onUiEvent}>
83
+ <TldrawUiToastsProvider>
84
+ <TldrawUiDialogsProvider context={'tla'}>
85
+ <TldrawUiA11yProvider>
86
+ <BreakPointProvider forceMobile={forceMobile}>
87
+ <TldrawUiComponentsProvider overrides={components}>
88
+ <InternalProviders overrides={overrides}>{children}</InternalProviders>
89
+ </TldrawUiComponentsProvider>
90
+ </BreakPointProvider>
91
+ </TldrawUiA11yProvider>
92
+ </TldrawUiDialogsProvider>
93
+ </TldrawUiToastsProvider>
94
+ </TldrawUiEventsProvider>
95
+ </TldrawUiTranslationProvider>
96
+ </AssetUrlsProvider>
97
+ </TldrawUiTooltipProvider>
95
98
  </MimeTypeContext.Provider>
96
99
  )
97
100
  })
@@ -1037,17 +1037,20 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
1037
1037
  id: 'rotate-cw',
1038
1038
  label: 'action.rotate-cw',
1039
1039
  icon: 'rotate-cw',
1040
+ kbd: 'shift+.,shift+alt+.',
1040
1041
  onSelect(source) {
1041
1042
  if (!canApplySelectionAction()) return
1042
1043
  if (mustGoBackToSelectToolFirst()) return
1043
1044
 
1044
- trackEvent('rotate-cw', { source })
1045
+ const isFine = editor.inputs.altKey
1046
+ trackEvent('rotate-cw', { source, fine: isFine })
1045
1047
  editor.markHistoryStoppingPoint('rotate-cw')
1046
1048
  editor.run(() => {
1047
- const offset = editor.getSelectionRotation() % (HALF_PI / 2)
1048
- const dontUseOffset = approximately(offset, 0) || approximately(offset, HALF_PI / 2)
1049
+ const rotation = HALF_PI / (isFine ? 96 : 6)
1050
+ const offset = editor.getSelectionRotation() % rotation
1051
+ const dontUseOffset = approximately(offset, 0) || approximately(offset, rotation)
1049
1052
  const selectedShapeIds = editor.getSelectedShapeIds()
1050
- editor.rotateShapesBy(selectedShapeIds, HALF_PI / 2 - (dontUseOffset ? 0 : offset))
1053
+ editor.rotateShapesBy(selectedShapeIds, rotation - (dontUseOffset ? 0 : offset))
1051
1054
  kickoutOccludedShapes(editor, selectedShapeIds)
1052
1055
  })
1053
1056
  },
@@ -1056,17 +1059,21 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
1056
1059
  id: 'rotate-ccw',
1057
1060
  label: 'action.rotate-ccw',
1058
1061
  icon: 'rotate-ccw',
1062
+ // omg double comma
1063
+ kbd: 'shift+,,shift+alt+,',
1059
1064
  onSelect(source) {
1060
1065
  if (!canApplySelectionAction()) return
1061
1066
  if (mustGoBackToSelectToolFirst()) return
1062
1067
 
1063
- trackEvent('rotate-ccw', { source })
1068
+ const isFine = editor.inputs.altKey
1069
+ trackEvent('rotate-ccw', { source, fine: isFine })
1064
1070
  editor.markHistoryStoppingPoint('rotate-ccw')
1065
1071
  editor.run(() => {
1066
- const offset = editor.getSelectionRotation() % (HALF_PI / 2)
1072
+ const rotation = HALF_PI / (isFine ? 96 : 6)
1073
+ const offset = editor.getSelectionRotation() % rotation
1067
1074
  const offsetCloseToZero = approximately(offset, 0)
1068
1075
  const selectedShapeIds = editor.getSelectedShapeIds()
1069
- editor.rotateShapesBy(selectedShapeIds, offsetCloseToZero ? -(HALF_PI / 2) : -offset)
1076
+ editor.rotateShapesBy(selectedShapeIds, offsetCloseToZero ? -rotation : -offset)
1070
1077
  kickoutOccludedShapes(editor, selectedShapeIds)
1071
1078
  })
1072
1079
  },
@@ -1259,6 +1266,21 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
1259
1266
  },
1260
1267
  checkbox: true,
1261
1268
  },
1269
+ {
1270
+ id: 'toggle-ui-labels',
1271
+ label: {
1272
+ default: 'action.toggle-ui-labels',
1273
+ menu: 'action.toggle-ui-labels.menu',
1274
+ },
1275
+ readonlyOk: true,
1276
+ onSelect(source) {
1277
+ trackEvent('toggle-ui-labels', { source })
1278
+ editor.user.updateUserPreferences({
1279
+ showUiLabels: !editor.user.getShowUiLabels(),
1280
+ })
1281
+ },
1282
+ checkbox: true,
1283
+ },
1262
1284
  {
1263
1285
  id: 'toggle-edge-scrolling',
1264
1286
  label: {
@@ -76,8 +76,8 @@ export interface TLUiEventMap {
76
76
  'delete-shapes': null
77
77
  'select-all-shapes': null
78
78
  'select-none-shapes': null
79
- 'rotate-ccw': null
80
- 'rotate-cw': null
79
+ 'rotate-ccw': { fine: boolean }
80
+ 'rotate-cw': { fine: boolean }
81
81
  'zoom-in': { towardsCursor: boolean }
82
82
  'zoom-out': { towardsCursor: boolean }
83
83
  'zoom-to-fit': null
@@ -108,6 +108,7 @@ export interface TLUiEventMap {
108
108
  'toggle-lock': null
109
109
  'toggle-reduce-motion': null
110
110
  'toggle-keyboard-shortcuts': null
111
+ 'toggle-ui-labels': null
111
112
  'toggle-edge-scrolling': null
112
113
  'color-scheme': { value: string }
113
114
  'exit-pen-mode': null
@@ -126,6 +127,7 @@ export interface TLUiEventMap {
126
127
  'open-context-menu': null
127
128
  'adjust-shape-styles': null
128
129
  'copy-link': null
130
+ 'drag-tool': { id: string }
129
131
  'image-replace': null
130
132
  'video-replace': null
131
133
  'open-kbd-shortcuts': null
@@ -123,6 +123,7 @@ export function useAnySelectedShapesCount(min?: number, max?: number) {
123
123
 
124
124
  /**
125
125
  * Returns true if the number of UNLOCKED selected shapes is at least min or at most max.
126
+ * @public
126
127
  */
127
128
  export function useUnlockedSelectedShapesCount(min?: number, max?: number) {
128
129
  const editor = useEditor()
@@ -1,4 +1,15 @@
1
- import { Editor, GeoShapeGeoStyle, useMaybeEditor } from '@tldraw/editor'
1
+ import {
2
+ assertExists,
3
+ createShapeId,
4
+ Editor,
5
+ GeoShapeGeoStyle,
6
+ getIndicesBetween,
7
+ TLLineShape,
8
+ TLPointerEventInfo,
9
+ TLShapeId,
10
+ toRichText,
11
+ useMaybeEditor,
12
+ } from '@tldraw/editor'
2
13
  import * as React from 'react'
3
14
  import { EmbedDialog } from '../components/EmbedDialog'
4
15
  import { TLUiIconJsx } from '../components/primitives/TldrawUiIcon'
@@ -19,6 +30,7 @@ export interface TLUiToolItem<
19
30
  shortcutsLabel?: TranslationKey
20
31
  icon: IconType | TLUiIconJsx
21
32
  onSelect(source: TLUiEventSource): void
33
+ onDragStart?(source: TLUiEventSource, info: TLPointerEventInfo): void
22
34
  /**
23
35
  * The keyboard shortcut for this tool. This is a string that can be a single key,
24
36
  * or a combination of keys.
@@ -126,21 +138,28 @@ export function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {
126
138
  onToolSelect(source, this)
127
139
  },
128
140
  },
129
- ...[...GeoShapeGeoStyle.values].map((id) => ({
130
- id,
131
- label: `tool.${id}` as TLUiTranslationKey,
141
+ ...[...GeoShapeGeoStyle.values].map((geo) => ({
142
+ id: geo,
143
+ label: `tool.${geo}` as TLUiTranslationKey,
132
144
  meta: {
133
- geo: id,
145
+ geo,
134
146
  },
135
- kbd: id === 'rectangle' ? 'r' : id === 'ellipse' ? 'o' : undefined,
136
- icon: ('geo-' + id) as TLUiIconType,
147
+ kbd: geo === 'rectangle' ? 'r' : geo === 'ellipse' ? 'o' : undefined,
148
+ icon: ('geo-' + geo) as TLUiIconType,
137
149
  onSelect(source: TLUiEventSource) {
138
150
  editor.run(() => {
139
- editor.setStyleForNextShapes(GeoShapeGeoStyle, id)
151
+ editor.setStyleForNextShapes(GeoShapeGeoStyle, geo)
140
152
  editor.setCurrentTool('geo')
141
- onToolSelect(source, this, `geo-${id}`)
153
+ onToolSelect(source, this, `geo-${geo}`)
142
154
  })
143
155
  },
156
+ onDragStart(source: TLUiEventSource, info: TLPointerEventInfo) {
157
+ onDragFromToolbarToCreateShape(editor, info, {
158
+ createShape: (id) =>
159
+ editor.createShape({ id, type: 'geo', props: { w: 200, h: 200, geo } }),
160
+ })
161
+ trackEvent('drag-tool', { source, id: 'geo' })
162
+ },
144
163
  })),
145
164
  {
146
165
  id: 'arrow',
@@ -151,6 +170,17 @@ export function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {
151
170
  editor.setCurrentTool('arrow')
152
171
  onToolSelect(source, this)
153
172
  },
173
+ onDragStart(source: TLUiEventSource, info: TLPointerEventInfo) {
174
+ onDragFromToolbarToCreateShape(editor, info, {
175
+ createShape: (id) =>
176
+ editor.createShape({
177
+ id,
178
+ type: 'arrow',
179
+ props: { start: { x: 0, y: 0 }, end: { x: 200, y: 0 } },
180
+ }),
181
+ })
182
+ trackEvent('drag-tool', { source, id: 'arrow' })
183
+ },
154
184
  },
155
185
  {
156
186
  id: 'line',
@@ -161,6 +191,24 @@ export function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {
161
191
  editor.setCurrentTool('line')
162
192
  onToolSelect(source, this)
163
193
  },
194
+ onDragStart(source, info) {
195
+ onDragFromToolbarToCreateShape(editor, info, {
196
+ createShape: (id) => {
197
+ const [start, end] = getIndicesBetween(null, null, 2)
198
+ editor.createShape<TLLineShape>({
199
+ id,
200
+ type: 'line',
201
+ props: {
202
+ points: {
203
+ [start]: { id: start, index: start, x: 0, y: 200 },
204
+ [end]: { id: end, index: end, x: 200, y: 0 },
205
+ },
206
+ },
207
+ })
208
+ },
209
+ })
210
+ trackEvent('drag-tool', { source, id: 'line' })
211
+ },
164
212
  },
165
213
  {
166
214
  id: 'frame',
@@ -171,6 +219,12 @@ export function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {
171
219
  editor.setCurrentTool('frame')
172
220
  onToolSelect(source, this)
173
221
  },
222
+ onDragStart(source, info) {
223
+ onDragFromToolbarToCreateShape(editor, info, {
224
+ createShape: (id) => editor.createShape({ id, type: 'frame' }),
225
+ })
226
+ trackEvent('drag-tool', { source, id: 'frame' })
227
+ },
174
228
  },
175
229
  {
176
230
  id: 'text',
@@ -181,6 +235,17 @@ export function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {
181
235
  editor.setCurrentTool('text')
182
236
  onToolSelect(source, this)
183
237
  },
238
+ onDragStart(source, info) {
239
+ onDragFromToolbarToCreateShape(editor, info, {
240
+ createShape: (id) =>
241
+ editor.createShape({ id, type: 'text', props: { richText: toRichText('Text') } }),
242
+ onDragEnd: (id) => {
243
+ editor.setEditingShape(id)
244
+ editor.emit('select-all-text', { shapeId: id })
245
+ },
246
+ })
247
+ trackEvent('drag-tool', { source, id: 'text' })
248
+ },
184
249
  },
185
250
  {
186
251
  id: 'asset',
@@ -201,6 +266,16 @@ export function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {
201
266
  editor.setCurrentTool('note')
202
267
  onToolSelect(source, this)
203
268
  },
269
+ onDragStart(source, info) {
270
+ onDragFromToolbarToCreateShape(editor, info, {
271
+ createShape: (id) => editor.createShape({ id, type: 'note' }),
272
+ onDragEnd: (id) => {
273
+ editor.setEditingShape(id)
274
+ editor.emit('select-all-text', { shapeId: id })
275
+ },
276
+ })
277
+ trackEvent('drag-tool', { source, id: 'note' })
278
+ },
204
279
  },
205
280
  {
206
281
  id: 'laser',
@@ -244,7 +319,7 @@ export function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {
244
319
  }
245
320
 
246
321
  return tools
247
- }, [overrides, editor, helpers, onToolSelect])
322
+ }, [overrides, editor, helpers, onToolSelect, trackEvent])
248
323
 
249
324
  return <ToolsContext.Provider value={tools}>{children}</ToolsContext.Provider>
250
325
  }
@@ -259,3 +334,58 @@ export function useTools() {
259
334
 
260
335
  return ctx
261
336
  }
337
+
338
+ /**
339
+ * Options for {@link onDragFromToolbarToCreateShape}.
340
+ * @public
341
+ */
342
+ export interface OnDragFromToolbarToCreateShapesOpts {
343
+ /**
344
+ * Create the shape being dragged. You don't need to worry about positioning it, as it'll be
345
+ * immediately updated with the correct position.
346
+ */
347
+ createShape(id: TLShapeId): void
348
+ /**
349
+ * Called once the drag interaction has finished.
350
+ */
351
+ onDragEnd?(id: TLShapeId): void
352
+ }
353
+
354
+ /**
355
+ * A helper method to use in {@link TLUiToolItem#onDragStart} to create a shape by dragging it from
356
+ * the toolbar.
357
+ * @public
358
+ */
359
+ export function onDragFromToolbarToCreateShape(
360
+ editor: Editor,
361
+ info: TLPointerEventInfo,
362
+ opts: OnDragFromToolbarToCreateShapesOpts
363
+ ) {
364
+ const { x, y } = editor.inputs.currentPagePoint
365
+
366
+ const stoppingPoint = editor.markHistoryStoppingPoint('drag shape tool')
367
+ editor.setCurrentTool('select.translating')
368
+
369
+ const id = createShapeId()
370
+ opts.createShape(id)
371
+ const shape = assertExists(editor.getShape(id), 'Shape not found')
372
+
373
+ const { w, h } = editor.getShapePageBounds(id)!
374
+ editor.updateShape({ id, type: shape.type, x: x - w / 2, y: y - h / 2 })
375
+ editor.select(id)
376
+
377
+ editor.setCurrentTool('select.translating', {
378
+ ...info,
379
+ target: 'shape',
380
+ shape: editor.getShape(id),
381
+ isCreating: true,
382
+ creatingMarkId: stoppingPoint,
383
+ onCreate() {
384
+ editor.setCurrentTool('select.idle')
385
+ editor.select(id)
386
+ opts.onDragEnd?.(id)
387
+ },
388
+ })
389
+
390
+ editor.getCurrentTool().setCurrentToolIdMask(shape.type)
391
+ }