tldraw 3.16.0-next.34fddf633325 → 3.16.0-next.b88d494af370

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 (229) hide show
  1. package/dist-cjs/index.d.ts +102 -5
  2. package/dist-cjs/index.js +8 -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/text/TextShapeUtil.js +2 -2
  33. package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
  34. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +3 -3
  35. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +1 -1
  36. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  37. package/dist-cjs/lib/ui/TldrawUi.js +14 -0
  38. package/dist-cjs/lib/ui/TldrawUi.js.map +3 -3
  39. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +12 -3
  40. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
  41. package/dist-cjs/lib/ui/components/DefaultMenuPanel.js +3 -2
  42. package/dist-cjs/lib/ui/components/DefaultMenuPanel.js.map +2 -2
  43. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +4 -4
  44. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
  45. package/dist-cjs/lib/ui/components/MobileStylePanel.js +5 -3
  46. package/dist-cjs/lib/ui/components/MobileStylePanel.js.map +2 -2
  47. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js +1 -1
  48. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js.map +2 -2
  49. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +2 -1
  50. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
  51. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js +3 -2
  52. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js.map +2 -2
  53. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js +2 -2
  54. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js.map +2 -2
  55. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +14 -14
  56. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  57. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js +3 -3
  58. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +2 -2
  59. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js +26 -25
  60. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +3 -3
  61. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +1 -1
  62. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  63. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +66 -21
  64. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js.map +3 -3
  65. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +189 -80
  66. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +3 -3
  67. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +2 -2
  68. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
  69. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js +5 -16
  70. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +3 -3
  71. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -1
  72. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  73. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +3 -2
  74. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js.map +3 -3
  75. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +19 -4
  76. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  77. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +153 -152
  78. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  79. package/dist-cjs/lib/ui/components/primitives/layout.js +76 -0
  80. package/dist-cjs/lib/ui/components/primitives/layout.js.map +7 -0
  81. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuContext.js.map +2 -2
  82. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +25 -12
  83. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
  84. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +153 -20
  85. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  86. package/dist-cjs/lib/ui/context/events.js.map +2 -2
  87. package/dist-cjs/lib/ui/hooks/useTools.js +94 -9
  88. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  89. package/dist-cjs/lib/ui/version.js +3 -3
  90. package/dist-cjs/lib/ui/version.js.map +1 -1
  91. package/dist-esm/index.d.mts +102 -5
  92. package/dist-esm/index.mjs +15 -1
  93. package/dist-esm/index.mjs.map +2 -2
  94. package/dist-esm/lib/canvas/TldrawScribble.mjs +1 -1
  95. package/dist-esm/lib/canvas/TldrawScribble.mjs.map +2 -2
  96. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +4 -3
  97. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  98. package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs +3 -3
  99. package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs.map +1 -1
  100. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +4 -3
  101. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
  102. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +1 -1
  103. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +1 -1
  104. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +13 -12
  105. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  106. package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs +1 -1
  107. package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs.map +2 -2
  108. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +3 -2
  109. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  110. package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs +2 -1
  111. package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs.map +2 -2
  112. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +6 -1
  113. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
  114. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -3
  115. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +1 -1
  116. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +6 -1
  117. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
  118. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +5 -4
  119. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  120. package/dist-esm/lib/shapes/shared/ShapeFill.mjs +5 -4
  121. package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
  122. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +3 -2
  123. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
  124. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +3 -3
  125. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +1 -1
  126. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  127. package/dist-esm/lib/ui/TldrawUi.mjs +16 -2
  128. package/dist-esm/lib/ui/TldrawUi.mjs.map +3 -3
  129. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +12 -3
  130. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
  131. package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs +3 -2
  132. package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs.map +2 -2
  133. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +4 -4
  134. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
  135. package/dist-esm/lib/ui/components/MobileStylePanel.mjs +6 -3
  136. package/dist-esm/lib/ui/components/MobileStylePanel.mjs.map +2 -2
  137. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs +1 -1
  138. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs.map +2 -2
  139. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +2 -1
  140. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
  141. package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs +3 -2
  142. package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs.map +2 -2
  143. package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs +2 -2
  144. package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs.map +2 -2
  145. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +14 -14
  146. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  147. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs +3 -3
  148. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +2 -2
  149. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs +26 -25
  150. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +2 -2
  151. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +1 -1
  152. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  153. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs +56 -21
  154. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs.map +2 -2
  155. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +192 -81
  156. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +3 -3
  157. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +2 -2
  158. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
  159. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +6 -6
  160. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +2 -2
  161. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +1 -1
  162. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  163. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs +3 -2
  164. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs.map +2 -2
  165. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +19 -4
  166. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  167. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +162 -154
  168. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  169. package/dist-esm/lib/ui/components/primitives/layout.mjs +46 -0
  170. package/dist-esm/lib/ui/components/primitives/layout.mjs.map +7 -0
  171. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuContext.mjs.map +2 -2
  172. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs +25 -12
  173. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
  174. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +161 -22
  175. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  176. package/dist-esm/lib/ui/context/events.mjs.map +2 -2
  177. package/dist-esm/lib/ui/hooks/useTools.mjs +102 -10
  178. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  179. package/dist-esm/lib/ui/version.mjs +3 -3
  180. package/dist-esm/lib/ui/version.mjs.map +1 -1
  181. package/package.json +3 -3
  182. package/src/index.ts +12 -0
  183. package/src/lib/canvas/TldrawScribble.tsx +1 -1
  184. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +4 -3
  185. package/src/lib/shapes/arrow/elbow/ElbowArrowDebug.tsx +3 -3
  186. package/src/lib/shapes/draw/DrawShapeUtil.tsx +4 -3
  187. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
  188. package/src/lib/shapes/frame/FrameShapeUtil.tsx +21 -14
  189. package/src/lib/shapes/frame/components/FrameHeading.tsx +1 -1
  190. package/src/lib/shapes/geo/GeoShapeUtil.tsx +3 -2
  191. package/src/lib/shapes/geo/components/GeoShapeBody.tsx +2 -2
  192. package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +7 -1
  193. package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -3
  194. package/src/lib/shapes/line/LineShapeUtil.tsx +6 -1
  195. package/src/lib/shapes/note/NoteShapeUtil.tsx +9 -4
  196. package/src/lib/shapes/shared/ShapeFill.tsx +5 -4
  197. package/src/lib/shapes/text/TextShapeUtil.tsx +3 -2
  198. package/src/lib/shapes/video/VideoShapeUtil.tsx +3 -3
  199. package/src/lib/tools/SelectTool/childStates/Translating.ts +0 -1
  200. package/src/lib/ui/TldrawUi.tsx +17 -2
  201. package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +15 -3
  202. package/src/lib/ui/components/DefaultMenuPanel.tsx +4 -3
  203. package/src/lib/ui/components/Minimap/MinimapManager.ts +4 -4
  204. package/src/lib/ui/components/MobileStylePanel.tsx +9 -6
  205. package/src/lib/ui/components/NavigationPanel/DefaultNavigationPanel.tsx +1 -1
  206. package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +3 -2
  207. package/src/lib/ui/components/SharePanel/PeopleMenuItem.tsx +4 -3
  208. package/src/lib/ui/components/SharePanel/UserPresenceColorPicker.tsx +3 -3
  209. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +39 -43
  210. package/src/lib/ui/components/StylePanel/DoubleDropdownPicker.tsx +3 -3
  211. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +7 -6
  212. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +1 -1
  213. package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +55 -23
  214. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +212 -61
  215. package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +2 -2
  216. package/src/lib/ui/components/primitives/TldrawUiButtonPicker.tsx +40 -37
  217. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +1 -1
  218. package/src/lib/ui/components/primitives/TldrawUiPopover.tsx +4 -2
  219. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +32 -9
  220. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +186 -172
  221. package/src/lib/ui/components/primitives/layout.tsx +107 -0
  222. package/src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx +0 -1
  223. package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +29 -16
  224. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +220 -19
  225. package/src/lib/ui/context/events.tsx +1 -0
  226. package/src/lib/ui/hooks/useTools.tsx +140 -10
  227. package/src/lib/ui/version.ts +3 -3
  228. package/src/lib/ui.css +363 -305
  229. package/tldraw.css +656 -595
@@ -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,177 @@ 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
+ })
354
+ }
355
+ }
356
+ }
357
+
358
+ function handlePointerUp(e: React.PointerEvent<HTMLButtonElement>) {
359
+ if ((e as any).isSpecialRedispatchedEvent) return
360
+
361
+ e.currentTarget.releasePointerCapture(e.pointerId)
362
+
363
+ editor.dispatch({
364
+ type: 'pointer',
365
+ target: 'canvas',
366
+ name: 'pointer_up',
367
+ ...getPointerInfo(e),
368
+ })
369
+ }
370
+
371
+ function handleClick() {
372
+ if (state.name === 'dragging' || state.name === 'dragged') {
373
+ state = { name: 'idle' }
374
+ return true
375
+ }
376
+
377
+ state = { name: 'idle' }
378
+ onSelect?.('toolbar')
379
+ }
380
+
381
+ return {
382
+ onPointerDown: handlePointerDown,
383
+ onPointerMove: handlePointerMove,
384
+ onPointerUp: handlePointerUp,
385
+ onClick: handleClick,
386
+ }
387
+ }, [onDragStart, editor, onSelect])
388
+
389
+ return events
390
+ }
391
+
392
+ function DraggableToolbarButton({
393
+ id,
394
+ labelToUse,
395
+ titleStr,
396
+ disabled,
397
+ isSelected,
398
+ icon,
399
+ onSelect,
400
+ onDragStart,
401
+ overflow,
402
+ }: {
403
+ id: string
404
+ disabled: boolean
405
+ labelToUse?: string
406
+ titleStr?: string
407
+ isSelected?: boolean
408
+ icon: TLUiMenuItemProps['icon']
409
+ onSelect: TLUiMenuItemProps['onSelect']
410
+ onDragStart: TLUiMenuItemProps['onDragStart']
411
+ overflow?: boolean
412
+ }) {
413
+ const events = useDraggableEvents(onDragStart, onSelect)
414
+
415
+ if (overflow) {
416
+ return (
417
+ <TldrawUiToolbarButton
418
+ aria-label={labelToUse}
419
+ aria-pressed={isSelected ? 'true' : 'false'}
420
+ isActive={isSelected}
421
+ className="tlui-button-grid__button"
422
+ data-testid={`tools.more.${id}`}
423
+ data-value={id}
424
+ disabled={disabled}
425
+ title={titleStr}
426
+ type="icon"
427
+ {...events}
428
+ >
429
+ <TldrawUiButtonIcon icon={icon!} />
430
+ </TldrawUiToolbarButton>
431
+ )
432
+ }
433
+
434
+ return (
435
+ <TldrawUiToolbarButton
436
+ aria-label={labelToUse}
437
+ aria-pressed={isSelected ? 'true' : 'false'}
438
+ data-testid={`tools.${id}`}
439
+ data-value={id}
440
+ disabled={disabled}
441
+ onTouchStart={(e) => {
442
+ preventDefault(e)
443
+ onSelect('toolbar')
444
+ }}
445
+ title={titleStr}
446
+ type="tool"
447
+ {...events}
448
+ >
449
+ <TldrawUiButtonIcon icon={icon!} />
450
+ </TldrawUiToolbarButton>
451
+ )
452
+ }
@@ -127,6 +127,7 @@ export interface TLUiEventMap {
127
127
  'open-context-menu': null
128
128
  'adjust-shape-styles': null
129
129
  'copy-link': null
130
+ 'drag-tool': { id: string }
130
131
  'image-replace': null
131
132
  'video-replace': null
132
133
  'open-kbd-shortcuts': null
@@ -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
+ }
@@ -1,9 +1,9 @@
1
1
  // This file is automatically generated by internal/scripts/refresh-assets.ts.
2
2
  // Do not edit manually. Or do, I'm a comment, not a cop.
3
3
 
4
- export const version = '3.16.0-next.34fddf633325'
4
+ export const version = '3.16.0-next.b88d494af370'
5
5
  export const publishDates = {
6
6
  major: '2024-09-13T14:36:29.063Z',
7
- minor: '2025-08-06T14:20:08.115Z',
8
- patch: '2025-08-06T14:20:08.115Z',
7
+ minor: '2025-08-15T10:33:20.761Z',
8
+ patch: '2025-08-15T10:33:20.761Z',
9
9
  }