tldraw 3.16.0-canary.614a556981b7 → 3.16.0-canary.62bc202550a3

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 (299) hide show
  1. package/dist-cjs/index.d.ts +227 -103
  2. package/dist-cjs/index.js +33 -14
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/Tldraw.js +12 -2
  5. package/dist-cjs/lib/Tldraw.js.map +2 -2
  6. package/dist-cjs/lib/defaultExternalContentHandlers.js +5 -4
  7. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  8. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +10 -4
  9. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  10. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -0
  11. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -3
  13. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  14. package/dist-cjs/lib/shapes/shared/ShapeFill.js +1 -1
  15. package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
  16. package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
  17. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +0 -2
  18. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  19. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +0 -2
  20. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
  21. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +25 -1
  22. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  23. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +12 -0
  24. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  25. package/dist-cjs/lib/ui/TldrawUi.js +13 -12
  26. package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
  27. package/dist-cjs/lib/ui/assetUrls.js +13 -10
  28. package/dist-cjs/lib/ui/assetUrls.js.map +2 -2
  29. package/dist-cjs/lib/ui/components/{FollowingIndicator.js → DefaultFollowingIndicator.js} +6 -6
  30. package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +7 -0
  31. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +6 -6
  32. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
  33. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +9 -4
  34. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
  35. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +255 -316
  36. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  37. package/dist-cjs/lib/ui/components/{primitives/TldrawUiButtonPicker.js → StylePanel/StylePanelButtonPicker.js} +52 -45
  38. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +7 -0
  39. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js +68 -0
  40. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js.map +7 -0
  41. package/dist-cjs/lib/ui/components/StylePanel/{DoubleDropdownPicker.js → StylePanelDoubleDropdownPicker.js} +23 -22
  42. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +7 -0
  43. package/dist-cjs/lib/ui/components/StylePanel/{DropdownPicker.js → StylePanelDropdownPicker.js} +24 -21
  44. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +7 -0
  45. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js +28 -0
  46. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js.map +7 -0
  47. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +3 -2
  48. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  49. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +38 -9
  50. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  51. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js +15 -3
  52. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js.map +2 -2
  53. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +3 -3
  54. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
  55. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +10 -1
  56. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  57. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +17 -4
  58. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  59. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +2 -0
  60. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  61. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +100 -122
  62. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  63. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuContext.js.map +2 -2
  64. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +0 -10
  65. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
  66. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +3 -19
  67. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  68. package/dist-cjs/lib/ui/context/actions.js +23 -10
  69. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  70. package/dist-cjs/lib/ui/context/components.js +2 -0
  71. package/dist-cjs/lib/ui/context/components.js.map +2 -2
  72. package/dist-cjs/lib/ui/context/events.js.map +1 -1
  73. package/dist-cjs/lib/ui/hooks/useExportAs.js +3 -2
  74. package/dist-cjs/lib/ui/hooks/useExportAs.js.map +2 -2
  75. package/dist-cjs/lib/ui/hooks/useTools.js +21 -3
  76. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  77. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  78. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +2 -0
  79. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  80. package/dist-cjs/lib/ui/kbd-utils.js +9 -3
  81. package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
  82. package/dist-cjs/lib/ui/version.js +3 -3
  83. package/dist-cjs/lib/ui/version.js.map +1 -1
  84. package/dist-cjs/lib/utils/export/copyAs.js +1 -2
  85. package/dist-cjs/lib/utils/export/copyAs.js.map +2 -2
  86. package/dist-cjs/lib/utils/export/export.js +0 -20
  87. package/dist-cjs/lib/utils/export/export.js.map +2 -2
  88. package/dist-cjs/lib/utils/export/exportAs.js +1 -2
  89. package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
  90. package/dist-esm/index.d.mts +227 -103
  91. package/dist-esm/index.mjs +61 -29
  92. package/dist-esm/index.mjs.map +2 -2
  93. package/dist-esm/lib/Tldraw.mjs +14 -4
  94. package/dist-esm/lib/Tldraw.mjs.map +2 -2
  95. package/dist-esm/lib/defaultExternalContentHandlers.mjs +5 -4
  96. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  97. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +10 -4
  98. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  99. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -0
  100. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
  101. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -3
  102. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  103. package/dist-esm/lib/shapes/shared/ShapeFill.mjs +1 -1
  104. package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
  105. package/dist-esm/lib/shapes/shared/freehand/svg.mjs.map +2 -2
  106. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +0 -2
  107. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  108. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +0 -2
  109. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  110. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +26 -1
  111. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  112. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +13 -0
  113. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  114. package/dist-esm/lib/ui/TldrawUi.mjs +13 -12
  115. package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
  116. package/dist-esm/lib/ui/assetUrls.mjs +13 -10
  117. package/dist-esm/lib/ui/assetUrls.mjs.map +2 -2
  118. package/dist-esm/lib/ui/components/{FollowingIndicator.mjs → DefaultFollowingIndicator.mjs} +3 -3
  119. package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +7 -0
  120. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +6 -6
  121. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
  122. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +14 -5
  123. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
  124. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +257 -320
  125. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  126. package/dist-esm/lib/ui/components/{primitives/TldrawUiButtonPicker.mjs → StylePanel/StylePanelButtonPicker.mjs} +54 -43
  127. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +7 -0
  128. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +48 -0
  129. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +7 -0
  130. package/dist-esm/lib/ui/components/StylePanel/{DoubleDropdownPicker.mjs → StylePanelDoubleDropdownPicker.mjs} +20 -19
  131. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +7 -0
  132. package/dist-esm/lib/ui/components/StylePanel/{DropdownPicker.mjs → StylePanelDropdownPicker.mjs} +21 -18
  133. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +7 -0
  134. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs +8 -0
  135. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs.map +7 -0
  136. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +3 -2
  137. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  138. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +38 -9
  139. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  140. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs +15 -3
  141. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs.map +2 -2
  142. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +3 -3
  143. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
  144. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +10 -1
  145. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  146. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +17 -4
  147. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  148. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +2 -0
  149. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  150. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +109 -124
  151. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  152. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuContext.mjs.map +2 -2
  153. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs +0 -10
  154. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
  155. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +3 -19
  156. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  157. package/dist-esm/lib/ui/context/actions.mjs +23 -10
  158. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  159. package/dist-esm/lib/ui/context/components.mjs +2 -0
  160. package/dist-esm/lib/ui/context/components.mjs.map +2 -2
  161. package/dist-esm/lib/ui/context/events.mjs.map +1 -1
  162. package/dist-esm/lib/ui/hooks/useExportAs.mjs +3 -2
  163. package/dist-esm/lib/ui/hooks/useExportAs.mjs.map +2 -2
  164. package/dist-esm/lib/ui/hooks/useTools.mjs +22 -3
  165. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  166. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +2 -0
  167. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  168. package/dist-esm/lib/ui/kbd-utils.mjs +9 -3
  169. package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
  170. package/dist-esm/lib/ui/version.mjs +3 -3
  171. package/dist-esm/lib/ui/version.mjs.map +1 -1
  172. package/dist-esm/lib/utils/export/copyAs.mjs +1 -2
  173. package/dist-esm/lib/utils/export/copyAs.mjs.map +2 -2
  174. package/dist-esm/lib/utils/export/export.mjs +0 -20
  175. package/dist-esm/lib/utils/export/export.mjs.map +2 -2
  176. package/dist-esm/lib/utils/export/exportAs.mjs +1 -2
  177. package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
  178. package/package.json +11 -34
  179. package/src/index.ts +44 -22
  180. package/src/lib/Tldraw.tsx +15 -2
  181. package/src/lib/defaultExternalContentHandlers.ts +12 -4
  182. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +2 -1
  183. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +4 -3
  184. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +7 -6
  185. package/src/lib/shapes/draw/DrawShapeTool.test.ts +0 -5
  186. package/src/lib/shapes/frame/FrameShapeUtil.tsx +20 -4
  187. package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -0
  188. package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -3
  189. package/src/lib/shapes/line/__snapshots__/LineShapeUtil.test.tsx.snap +2 -2
  190. package/src/lib/shapes/shared/PlainTextLabel.tsx +0 -6
  191. package/src/lib/shapes/shared/ShapeFill.tsx +1 -1
  192. package/src/lib/shapes/shared/freehand/svg.ts +2 -0
  193. package/src/lib/shapes/shared/useEditablePlainText.ts +0 -6
  194. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +0 -7
  195. package/src/lib/shapes/text/TextShapeTool.test.ts +6 -5
  196. package/src/lib/tools/EraserTool/childStates/Erasing.ts +34 -1
  197. package/src/lib/tools/EraserTool/childStates/Pointing.ts +20 -0
  198. package/src/lib/ui/TldrawUi.tsx +16 -10
  199. package/src/lib/ui/assetUrls.ts +13 -10
  200. package/src/lib/ui/components/{FollowingIndicator.tsx → DefaultFollowingIndicator.tsx} +2 -1
  201. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +6 -6
  202. package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +27 -13
  203. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +260 -381
  204. package/src/lib/ui/components/{primitives/TldrawUiButtonPicker.tsx → StylePanel/StylePanelButtonPicker.tsx} +63 -50
  205. package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +63 -0
  206. package/src/lib/ui/components/StylePanel/{DoubleDropdownPicker.tsx → StylePanelDoubleDropdownPicker.tsx} +28 -19
  207. package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +119 -0
  208. package/src/lib/ui/components/StylePanel/StylePanelSubheading.tsx +9 -0
  209. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +4 -3
  210. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +32 -15
  211. package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
  212. package/src/lib/ui/components/Toolbar/LinkEditor.tsx +5 -5
  213. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +6 -1
  214. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +50 -30
  215. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +3 -0
  216. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +117 -125
  217. package/src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx +0 -1
  218. package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +0 -10
  219. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +5 -18
  220. package/src/lib/ui/context/actions.tsx +23 -10
  221. package/src/lib/ui/context/components.tsx +3 -0
  222. package/src/lib/ui/context/events.tsx +1 -1
  223. package/src/lib/ui/hooks/useExportAs.ts +3 -2
  224. package/src/lib/ui/hooks/useTools.tsx +25 -3
  225. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +2 -0
  226. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +2 -0
  227. package/src/lib/ui/kbd-utils.ts +10 -3
  228. package/src/lib/ui/version.ts +3 -3
  229. package/src/lib/ui.css +24 -8
  230. package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +5 -5
  231. package/src/lib/utils/export/copyAs.ts +1 -24
  232. package/src/lib/utils/export/export.ts +0 -36
  233. package/src/lib/utils/export/exportAs.ts +1 -32
  234. package/src/lib/utils/tldr/__snapshots__/buildFromV1Document.test.ts.snap +4 -4
  235. package/src/test/A11y.test.tsx +3 -2
  236. package/src/test/ClickManager.test.ts +7 -6
  237. package/src/test/Editor.test.tsx +20 -19
  238. package/src/test/EraserTool.test.ts +184 -13
  239. package/src/test/HandTool.test.ts +10 -9
  240. package/src/test/HighlightShape.test.ts +2 -1
  241. package/src/test/SelectTool.test.ts +3 -2
  242. package/src/test/TLUserPreferences.test.ts +4 -3
  243. package/src/test/TestEditor.ts +13 -15
  244. package/src/test/TldrawEditor.test.tsx +11 -10
  245. package/src/test/ZoomTool.test.ts +7 -6
  246. package/src/test/__snapshots__/drawing.test.ts.snap +2 -2
  247. package/src/test/__snapshots__/groups.test.tsx.snap +6 -6
  248. package/src/test/__snapshots__/resizing.test.ts.snap +2 -2
  249. package/src/test/arrows-megabus.test.tsx +5 -4
  250. package/src/test/bindings.test.tsx +24 -37
  251. package/src/test/bookmark-shapes.test.ts +1 -8
  252. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +23 -7
  253. package/src/test/commands/__snapshots__/packShapes.test.ts.snap +8 -8
  254. package/src/test/commands/__snapshots__/zoomToFit.test.ts.snap +2 -2
  255. package/src/test/commands/alignShapes.test.tsx +25 -24
  256. package/src/test/commands/animationSpeed.test.ts +2 -1
  257. package/src/test/commands/centerOnPoint.test.ts +3 -2
  258. package/src/test/commands/clipboard.test.ts +3 -2
  259. package/src/test/commands/createShapes.test.ts +2 -1
  260. package/src/test/commands/deleteShapes.test.ts +2 -1
  261. package/src/test/commands/distributeShapes.test.tsx +11 -10
  262. package/src/test/commands/getSvgString.test.ts +2 -1
  263. package/src/test/commands/packShapes.test.ts +5 -4
  264. package/src/test/commands/resizeShape.test.ts +2 -1
  265. package/src/test/commands/rotateShapes.test.ts +7 -6
  266. package/src/test/commands/setCamera.test.ts +4 -3
  267. package/src/test/commands/setCurrentPage.test.ts +3 -2
  268. package/src/test/commands/stackShapes.test.ts +11 -10
  269. package/src/test/commands/stretch.test.tsx +13 -12
  270. package/src/test/createDeepLink.test.tsx +2 -1
  271. package/src/test/cropping.test.ts +3 -2
  272. package/src/test/custom-clipping.test.ts +436 -0
  273. package/src/test/drawing.test.ts +2 -1
  274. package/src/test/flipShapes.test.ts +4 -3
  275. package/src/test/frames.test.ts +25 -24
  276. package/src/test/getCulledShapes.test.tsx +3 -2
  277. package/src/test/groups.test.tsx +1 -1
  278. package/src/test/handleDeepLink.test.tsx +2 -1
  279. package/src/test/maxShapes.test.ts +3 -2
  280. package/src/test/modifiers.test.ts +5 -4
  281. package/src/test/navigation.test.ts +12 -11
  282. package/src/test/panning.test.ts +2 -1
  283. package/src/test/perf/perf.test.ts +2 -1
  284. package/src/test/registerDeepLinkListener.test.tsx +10 -9
  285. package/src/test/resizing.test.ts +39 -38
  286. package/src/test/select.test.tsx +4 -3
  287. package/src/test/selection-omnibus.test.ts +11 -10
  288. package/src/test/shapeutils.test.ts +4 -3
  289. package/src/test/translating.test.ts +9 -8
  290. package/tldraw.css +32 -8
  291. package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
  292. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +0 -7
  293. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +0 -7
  294. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +0 -7
  295. package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
  296. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +0 -7
  297. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +0 -7
  298. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +0 -7
  299. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +0 -110
@@ -1,79 +1,75 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { assert, uniqueId, useMaybeEditor, Vec } from "@tldraw/editor";
2
+ import { assert, atom, uniqueId, useMaybeEditor, useValue } from "@tldraw/editor";
3
3
  import { Tooltip as _Tooltip } from "radix-ui";
4
- import React, { createContext, forwardRef, useContext, useEffect, useRef, useState } from "react";
5
- import { usePrefersReducedMotion } from "../../../shapes/shared/usePrefersReducedMotion.mjs";
4
+ import React, {
5
+ createContext,
6
+ forwardRef,
7
+ useContext,
8
+ useEffect,
9
+ useRef,
10
+ useState
11
+ } from "react";
6
12
  import { useTldrawUiOrientation } from "./layout.mjs";
7
13
  const DEFAULT_TOOLTIP_DELAY_MS = 700;
8
14
  class TooltipManager {
9
15
  static instance = null;
10
- currentTooltipId = null;
11
- currentContent = "";
12
- currentSide = "bottom";
13
- currentSideOffset = 5;
16
+ currentTooltip = atom("current tooltip", null);
14
17
  destroyTimeoutId = null;
15
- subscribers = /* @__PURE__ */ new Set();
16
- activeElement = null;
17
- editor = null;
18
18
  static getInstance() {
19
19
  if (!TooltipManager.instance) {
20
20
  TooltipManager.instance = new TooltipManager();
21
21
  }
22
22
  return TooltipManager.instance;
23
23
  }
24
- setEditor(editor) {
25
- this.editor = editor;
26
- }
27
- subscribe(callback) {
28
- this.subscribers.add(callback);
29
- return () => this.subscribers.delete(callback);
30
- }
31
- notify() {
32
- this.subscribers.forEach((callback) => callback());
33
- }
34
- showTooltip(tooltipId, content, element, side = "bottom", sideOffset = 5) {
24
+ showTooltip(tooltipId, content, targetElement, side, sideOffset, showOnMobile, delayDuration) {
35
25
  if (this.destroyTimeoutId) {
36
26
  clearTimeout(this.destroyTimeoutId);
37
27
  this.destroyTimeoutId = null;
38
28
  }
39
- this.currentTooltipId = tooltipId;
40
- this.currentContent = content;
41
- this.currentSide = side;
42
- this.currentSideOffset = sideOffset;
43
- this.activeElement = element;
44
- this.notify();
29
+ this.currentTooltip.set({
30
+ id: tooltipId,
31
+ content,
32
+ side,
33
+ sideOffset,
34
+ showOnMobile,
35
+ targetElement,
36
+ delayDuration
37
+ });
45
38
  }
46
- hideTooltip(tooltipId, instant = false) {
39
+ hideTooltip(editor, tooltipId, instant = false) {
47
40
  const hide = () => {
48
- if (this.currentTooltipId === tooltipId) {
49
- this.currentTooltipId = null;
50
- this.currentContent = "";
51
- this.activeElement = null;
41
+ if (this.currentTooltip.get()?.id === tooltipId) {
42
+ this.currentTooltip.set(null);
52
43
  this.destroyTimeoutId = null;
53
- this.notify();
54
44
  }
55
45
  };
56
- if (instant) {
46
+ if (editor && !instant) {
47
+ this.destroyTimeoutId = editor.timers.setTimeout(hide, 300);
48
+ } else {
57
49
  hide();
58
- } else if (this.editor) {
59
- this.destroyTimeoutId = this.editor.timers.setTimeout(hide, 300);
60
50
  }
61
51
  }
62
52
  hideAllTooltips() {
63
- this.currentTooltipId = null;
64
- this.currentContent = "";
65
- this.activeElement = null;
53
+ this.currentTooltip.set(null);
66
54
  this.destroyTimeoutId = null;
67
- this.notify();
68
55
  }
69
56
  getCurrentTooltipData() {
70
- return {
71
- id: this.currentTooltipId,
72
- content: this.currentContent,
73
- side: this.currentSide,
74
- sideOffset: this.currentSideOffset,
75
- element: this.activeElement
76
- };
57
+ const currentTooltip = this.currentTooltip.get();
58
+ if (!currentTooltip) return null;
59
+ if (!this.supportsHover() && !currentTooltip.showOnMobile) return null;
60
+ return currentTooltip;
61
+ }
62
+ supportsHoverAtom = null;
63
+ supportsHover() {
64
+ if (!this.supportsHoverAtom) {
65
+ const mediaQuery = window.matchMedia("(hover: hover)");
66
+ const supportsHover = atom("has hover", mediaQuery.matches);
67
+ this.supportsHoverAtom = supportsHover;
68
+ mediaQuery.addEventListener("change", (e) => {
69
+ supportsHover.set(e.matches);
70
+ });
71
+ }
72
+ return this.supportsHoverAtom.get();
77
73
  }
78
74
  }
79
75
  const tooltipManager = TooltipManager.getInstance();
@@ -85,45 +81,26 @@ function TldrawUiTooltipProvider({ children }) {
85
81
  ] }) });
86
82
  }
87
83
  function TooltipSingleton() {
88
- const editor = useMaybeEditor();
89
- const [, forceUpdate] = useState({});
90
84
  const [isOpen, setIsOpen] = useState(false);
91
85
  const triggerRef = useRef(null);
92
- const previousPositionRef = useRef(null);
93
- const prefersReducedMotion = usePrefersReducedMotion();
94
- const [shouldAnimate, setShouldAnimate] = useState(false);
95
86
  const isFirstShowRef = useRef(true);
96
- const showTimeoutRef = useRef(null);
97
- useEffect(() => {
98
- tooltipManager.setEditor(editor);
99
- }, [editor]);
100
- useEffect(() => {
101
- const unsubscribe = tooltipManager.subscribe(() => {
102
- forceUpdate({});
103
- });
104
- return unsubscribe;
105
- }, []);
106
- const tooltipData = tooltipManager.getCurrentTooltipData();
87
+ const editor = useMaybeEditor();
88
+ const currentTooltip = useValue(
89
+ "current tooltip",
90
+ () => tooltipManager.getCurrentTooltipData(),
91
+ []
92
+ );
93
+ const cameraState = useValue("camera state", () => editor?.getCameraState(), [editor]);
107
94
  useEffect(() => {
108
- const shouldBeOpen = Boolean(tooltipData.id && tooltipData.element);
109
- if (showTimeoutRef.current) {
110
- clearTimeout(showTimeoutRef.current);
111
- showTimeoutRef.current = null;
95
+ if (cameraState === "moving" && isOpen && currentTooltip) {
96
+ tooltipManager.hideTooltip(editor, currentTooltip.id, true);
112
97
  }
113
- if (shouldBeOpen && tooltipData.element && triggerRef.current) {
114
- const activeRect = tooltipData.element.getBoundingClientRect();
98
+ }, [cameraState, isOpen, currentTooltip, editor]);
99
+ useEffect(() => {
100
+ let timer = null;
101
+ if (currentTooltip && triggerRef.current) {
102
+ const activeRect = currentTooltip.targetElement.getBoundingClientRect();
115
103
  const trigger = triggerRef.current;
116
- const newPosition = {
117
- x: activeRect.left + activeRect.width / 2,
118
- y: activeRect.top + activeRect.height / 2
119
- };
120
- let shouldAnimateCheck = false;
121
- if (previousPositionRef.current) {
122
- const isNearPrevious = Vec.DistMin(previousPositionRef.current, newPosition, 200);
123
- shouldAnimateCheck = !prefersReducedMotion && isNearPrevious && Math.abs(newPosition.y - previousPositionRef.current.y) < 50;
124
- }
125
- setShouldAnimate(isFirstShowRef.current ? false : shouldAnimateCheck);
126
- previousPositionRef.current = newPosition;
127
104
  trigger.style.position = "fixed";
128
105
  trigger.style.left = `${activeRect.left}px`;
129
106
  trigger.style.top = `${activeRect.top}px`;
@@ -131,22 +108,25 @@ function TooltipSingleton() {
131
108
  trigger.style.height = `${activeRect.height}px`;
132
109
  trigger.style.pointerEvents = "none";
133
110
  trigger.style.zIndex = "9999";
134
- if (isFirstShowRef.current && editor) {
135
- showTimeoutRef.current = editor.timers.setTimeout(() => {
111
+ if (isFirstShowRef.current) {
112
+ timer = setTimeout(() => {
136
113
  setIsOpen(true);
137
114
  isFirstShowRef.current = false;
138
- }, editor.options.tooltipDelayMs);
115
+ }, currentTooltip.delayDuration);
139
116
  } else {
140
117
  setIsOpen(true);
141
118
  }
142
- } else if (!shouldBeOpen) {
119
+ } else {
143
120
  setIsOpen(false);
144
- previousPositionRef.current = null;
145
- setShouldAnimate(false);
146
121
  isFirstShowRef.current = true;
147
122
  }
148
- }, [tooltipData.id, tooltipData.element, editor, prefersReducedMotion]);
149
- if (!tooltipData.id) {
123
+ return () => {
124
+ if (timer !== null) {
125
+ clearTimeout(timer);
126
+ }
127
+ };
128
+ }, [currentTooltip]);
129
+ if (!currentTooltip) {
150
130
  return null;
151
131
  }
152
132
  return /* @__PURE__ */ jsxs(_Tooltip.Root, { open: isOpen, delayDuration: 0, children: [
@@ -155,14 +135,13 @@ function TooltipSingleton() {
155
135
  _Tooltip.Content,
156
136
  {
157
137
  className: "tlui-tooltip",
158
- "data-should-animate": shouldAnimate,
159
- side: tooltipData.side,
160
- sideOffset: tooltipData.sideOffset,
138
+ side: currentTooltip.side,
139
+ sideOffset: currentTooltip.sideOffset,
161
140
  avoidCollisions: true,
162
141
  collisionPadding: 8,
163
142
  dir: "ltr",
164
143
  children: [
165
- tooltipData.content,
144
+ currentTooltip.content,
166
145
  /* @__PURE__ */ jsx(_Tooltip.Arrow, { className: "tlui-tooltip__arrow" })
167
146
  ]
168
147
  }
@@ -170,7 +149,15 @@ function TooltipSingleton() {
170
149
  ] });
171
150
  }
172
151
  const TldrawUiTooltip = forwardRef(
173
- ({ children, content, side, sideOffset = 5, disabled = false }, ref) => {
152
+ ({
153
+ children,
154
+ content,
155
+ side,
156
+ sideOffset = 5,
157
+ disabled = false,
158
+ showOnMobile = false,
159
+ delayDuration
160
+ }, ref) => {
174
161
  const editor = useMaybeEditor();
175
162
  const tooltipId = useRef(uniqueId());
176
163
  const hasProvider = useContext(TooltipSingletonContext);
@@ -180,39 +167,33 @@ const TldrawUiTooltip = forwardRef(
180
167
  const currentTooltipId = tooltipId.current;
181
168
  return () => {
182
169
  if (hasProvider) {
183
- tooltipManager.hideTooltip(currentTooltipId, true);
170
+ tooltipManager.hideTooltip(editor, currentTooltipId, true);
184
171
  }
185
172
  };
186
- }, [hasProvider]);
173
+ }, [editor, hasProvider]);
187
174
  if (disabled || !content) {
188
175
  return /* @__PURE__ */ jsx(Fragment, { children });
189
176
  }
177
+ const delayDurationToUse = delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS);
190
178
  if (!hasProvider) {
191
- return /* @__PURE__ */ jsxs(
192
- _Tooltip.Root,
193
- {
194
- delayDuration: editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS,
195
- disableHoverableContent: true,
196
- children: [
197
- /* @__PURE__ */ jsx(_Tooltip.Trigger, { asChild: true, ref, children }),
198
- /* @__PURE__ */ jsxs(
199
- _Tooltip.Content,
200
- {
201
- className: "tlui-tooltip",
202
- side: sideToUse,
203
- sideOffset,
204
- avoidCollisions: true,
205
- collisionPadding: 8,
206
- dir: "ltr",
207
- children: [
208
- content,
209
- /* @__PURE__ */ jsx(_Tooltip.Arrow, { className: "tlui-tooltip__arrow" })
210
- ]
211
- }
212
- )
213
- ]
214
- }
215
- );
179
+ return /* @__PURE__ */ jsxs(_Tooltip.Root, { delayDuration: delayDurationToUse, disableHoverableContent: true, children: [
180
+ /* @__PURE__ */ jsx(_Tooltip.Trigger, { asChild: true, ref, children }),
181
+ /* @__PURE__ */ jsxs(
182
+ _Tooltip.Content,
183
+ {
184
+ className: "tlui-tooltip",
185
+ side: sideToUse,
186
+ sideOffset,
187
+ avoidCollisions: true,
188
+ collisionPadding: 8,
189
+ dir: "ltr",
190
+ children: [
191
+ content,
192
+ /* @__PURE__ */ jsx(_Tooltip.Arrow, { className: "tlui-tooltip__arrow" })
193
+ ]
194
+ }
195
+ )
196
+ ] });
216
197
  }
217
198
  const child = React.Children.only(children);
218
199
  assert(React.isValidElement(child), "TldrawUiTooltip children must be a single element");
@@ -223,12 +204,14 @@ const TldrawUiTooltip = forwardRef(
223
204
  content,
224
205
  event.currentTarget,
225
206
  sideToUse,
226
- sideOffset
207
+ sideOffset,
208
+ showOnMobile,
209
+ delayDurationToUse
227
210
  );
228
211
  };
229
212
  const handleMouseLeave = (event) => {
230
213
  child.props.onMouseLeave?.(event);
231
- tooltipManager.hideTooltip(tooltipId.current);
214
+ tooltipManager.hideTooltip(editor, tooltipId.current);
232
215
  };
233
216
  const handleFocus = (event) => {
234
217
  child.props.onFocus?.(event);
@@ -237,12 +220,14 @@ const TldrawUiTooltip = forwardRef(
237
220
  content,
238
221
  event.currentTarget,
239
222
  sideToUse,
240
- sideOffset
223
+ sideOffset,
224
+ showOnMobile,
225
+ delayDurationToUse
241
226
  );
242
227
  };
243
228
  const handleBlur = (event) => {
244
229
  child.props.onBlur?.(event);
245
- tooltipManager.hideTooltip(tooltipId.current);
230
+ tooltipManager.hideTooltip(editor, tooltipId.current);
246
231
  };
247
232
  const childrenWithHandlers = React.cloneElement(children, {
248
233
  onMouseEnter: handleMouseEnter,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/ui/components/primitives/TldrawUiTooltip.tsx"],
4
- "sourcesContent": ["import { assert, Editor, uniqueId, useMaybeEditor, Vec } from '@tldraw/editor'\nimport { Tooltip as _Tooltip } from 'radix-ui'\nimport React, { createContext, forwardRef, useContext, useEffect, useRef, useState } from 'react'\nimport { usePrefersReducedMotion } from '../../../shapes/shared/usePrefersReducedMotion'\nimport { useTldrawUiOrientation } from './layout'\n\nconst DEFAULT_TOOLTIP_DELAY_MS = 700\n\n/** @public */\nexport interface TldrawUiTooltipProps {\n\tchildren: React.ReactNode\n\tcontent?: string | React.ReactNode\n\tside?: 'top' | 'right' | 'bottom' | 'left'\n\tsideOffset?: number\n\tdisabled?: boolean\n}\n\n// Singleton tooltip manager\nclass TooltipManager {\n\tprivate static instance: TooltipManager | null = null\n\tprivate currentTooltipId: string | null = null\n\tprivate currentContent: string | React.ReactNode = ''\n\tprivate currentSide: 'top' | 'right' | 'bottom' | 'left' = 'bottom'\n\tprivate currentSideOffset: number = 5\n\tprivate destroyTimeoutId: number | null = null\n\tprivate subscribers: Set<() => void> = new Set()\n\tprivate activeElement: HTMLElement | null = null\n\tprivate editor: Editor | null = null\n\n\tstatic getInstance(): TooltipManager {\n\t\tif (!TooltipManager.instance) {\n\t\t\tTooltipManager.instance = new TooltipManager()\n\t\t}\n\t\treturn TooltipManager.instance\n\t}\n\n\tsetEditor(editor: Editor | null) {\n\t\tthis.editor = editor\n\t}\n\n\tsubscribe(callback: () => void): () => void {\n\t\tthis.subscribers.add(callback)\n\t\treturn () => this.subscribers.delete(callback)\n\t}\n\n\tprivate notify() {\n\t\tthis.subscribers.forEach((callback) => callback())\n\t}\n\n\tshowTooltip(\n\t\ttooltipId: string,\n\t\tcontent: string | React.ReactNode,\n\t\telement: HTMLElement,\n\t\tside: 'top' | 'right' | 'bottom' | 'left' = 'bottom',\n\t\tsideOffset: number = 5\n\t) {\n\t\t// Clear any existing destroy timeout\n\t\tif (this.destroyTimeoutId) {\n\t\t\tclearTimeout(this.destroyTimeoutId)\n\t\t\tthis.destroyTimeoutId = null\n\t\t}\n\n\t\t// Update current tooltip\n\t\tthis.currentTooltipId = tooltipId\n\t\tthis.currentContent = content\n\t\tthis.currentSide = side\n\t\tthis.currentSideOffset = sideOffset\n\t\tthis.activeElement = element\n\n\t\tthis.notify()\n\t}\n\n\thideTooltip(tooltipId: string, instant: boolean = false) {\n\t\tconst hide = () => {\n\t\t\t// Only hide if this is the current tooltip\n\t\t\tif (this.currentTooltipId === tooltipId) {\n\t\t\t\tthis.currentTooltipId = null\n\t\t\t\tthis.currentContent = ''\n\t\t\t\tthis.activeElement = null\n\t\t\t\tthis.destroyTimeoutId = null\n\t\t\t\tthis.notify()\n\t\t\t}\n\t\t}\n\n\t\tif (instant) {\n\t\t\thide()\n\t\t} else if (this.editor) {\n\t\t\t// Start destroy timeout (1 second)\n\t\t\tthis.destroyTimeoutId = this.editor.timers.setTimeout(hide, 300)\n\t\t}\n\t}\n\n\thideAllTooltips() {\n\t\tthis.currentTooltipId = null\n\t\tthis.currentContent = ''\n\t\tthis.activeElement = null\n\t\tthis.destroyTimeoutId = null\n\t\tthis.notify()\n\t}\n\n\tgetCurrentTooltipData() {\n\t\treturn {\n\t\t\tid: this.currentTooltipId,\n\t\t\tcontent: this.currentContent,\n\t\t\tside: this.currentSide,\n\t\t\tsideOffset: this.currentSideOffset,\n\t\t\telement: this.activeElement,\n\t\t}\n\t}\n}\n\nexport const tooltipManager = TooltipManager.getInstance()\n\n// Context for the tooltip singleton\nconst TooltipSingletonContext = createContext<boolean>(false)\n\n/** @public */\nexport interface TldrawUiTooltipProviderProps {\n\tchildren: React.ReactNode\n}\n\n/** @public @react */\nexport function TldrawUiTooltipProvider({ children }: TldrawUiTooltipProviderProps) {\n\treturn (\n\t\t<_Tooltip.Provider skipDelayDuration={700}>\n\t\t\t<TooltipSingletonContext.Provider value={true}>\n\t\t\t\t{children}\n\t\t\t\t<TooltipSingleton />\n\t\t\t</TooltipSingletonContext.Provider>\n\t\t</_Tooltip.Provider>\n\t)\n}\n\n// The singleton tooltip component that renders once\nfunction TooltipSingleton() {\n\tconst editor = useMaybeEditor()\n\tconst [, forceUpdate] = useState({})\n\tconst [isOpen, setIsOpen] = useState(false)\n\tconst triggerRef = useRef<HTMLDivElement>(null)\n\tconst previousPositionRef = useRef<{ x: number; y: number } | null>(null)\n\tconst prefersReducedMotion = usePrefersReducedMotion()\n\tconst [shouldAnimate, setShouldAnimate] = useState(false)\n\tconst isFirstShowRef = useRef(true)\n\tconst showTimeoutRef = useRef<number | null>(null)\n\n\t// Set editor in tooltip manager\n\tuseEffect(() => {\n\t\ttooltipManager.setEditor(editor)\n\t}, [editor])\n\n\t// Subscribe to tooltip manager updates\n\tuseEffect(() => {\n\t\tconst unsubscribe = tooltipManager.subscribe(() => {\n\t\t\tforceUpdate({})\n\t\t})\n\t\treturn unsubscribe\n\t}, [])\n\n\tconst tooltipData = tooltipManager.getCurrentTooltipData()\n\n\t// Update open state and trigger position\n\tuseEffect(() => {\n\t\tconst shouldBeOpen = Boolean(tooltipData.id && tooltipData.element)\n\n\t\t// Clear any existing show timeout\n\t\tif (showTimeoutRef.current) {\n\t\t\tclearTimeout(showTimeoutRef.current)\n\t\t\tshowTimeoutRef.current = null\n\t\t}\n\n\t\tif (shouldBeOpen && tooltipData.element && triggerRef.current) {\n\t\t\t// Position the invisible trigger element over the active element\n\t\t\tconst activeRect = tooltipData.element.getBoundingClientRect()\n\t\t\tconst trigger = triggerRef.current\n\n\t\t\tconst newPosition = {\n\t\t\t\tx: activeRect.left + activeRect.width / 2,\n\t\t\t\ty: activeRect.top + activeRect.height / 2,\n\t\t\t}\n\n\t\t\t// Determine if we should animate\n\t\t\tlet shouldAnimateCheck = false\n\t\t\tif (previousPositionRef.current) {\n\t\t\t\tconst isNearPrevious = Vec.DistMin(previousPositionRef.current, newPosition, 200)\n\t\t\t\t// Only animate if the distance is less than 200px (nearby tooltips)\n\t\t\t\tshouldAnimateCheck =\n\t\t\t\t\t!prefersReducedMotion &&\n\t\t\t\t\tisNearPrevious &&\n\t\t\t\t\tMath.abs(newPosition.y - previousPositionRef.current.y) < 50\n\t\t\t}\n\t\t\t// Don't animate on initial show (previousPositionRef.current is null)\n\n\t\t\tsetShouldAnimate(isFirstShowRef.current ? false : shouldAnimateCheck)\n\t\t\tpreviousPositionRef.current = newPosition\n\n\t\t\ttrigger.style.position = 'fixed'\n\t\t\ttrigger.style.left = `${activeRect.left}px`\n\t\t\ttrigger.style.top = `${activeRect.top}px`\n\t\t\ttrigger.style.width = `${activeRect.width}px`\n\t\t\ttrigger.style.height = `${activeRect.height}px`\n\t\t\ttrigger.style.pointerEvents = 'none'\n\t\t\ttrigger.style.zIndex = '9999'\n\n\t\t\t// Handle delay for first show\n\t\t\tif (isFirstShowRef.current && editor) {\n\t\t\t\tshowTimeoutRef.current = editor.timers.setTimeout(() => {\n\t\t\t\t\tsetIsOpen(true)\n\t\t\t\t\tisFirstShowRef.current = false\n\t\t\t\t}, editor.options.tooltipDelayMs)\n\t\t\t} else {\n\t\t\t\t// Subsequent tooltips show immediately\n\t\t\t\tsetIsOpen(true)\n\t\t\t}\n\t\t} else if (!shouldBeOpen) {\n\t\t\t// Hide tooltip immediately\n\t\t\tsetIsOpen(false)\n\t\t\t// Reset position tracking when tooltip closes\n\t\t\tpreviousPositionRef.current = null\n\t\t\tsetShouldAnimate(false)\n\t\t\t// Reset first show state after tooltip is hidden\n\t\t\tisFirstShowRef.current = true\n\t\t}\n\t}, [tooltipData.id, tooltipData.element, editor, prefersReducedMotion])\n\n\tif (!tooltipData.id) {\n\t\treturn null\n\t}\n\n\treturn (\n\t\t<_Tooltip.Root open={isOpen} delayDuration={0}>\n\t\t\t<_Tooltip.Trigger asChild>\n\t\t\t\t<div ref={triggerRef} />\n\t\t\t</_Tooltip.Trigger>\n\t\t\t<_Tooltip.Content\n\t\t\t\tclassName=\"tlui-tooltip\"\n\t\t\t\tdata-should-animate={shouldAnimate}\n\t\t\t\tside={tooltipData.side}\n\t\t\t\tsideOffset={tooltipData.sideOffset}\n\t\t\t\tavoidCollisions\n\t\t\t\tcollisionPadding={8}\n\t\t\t\tdir=\"ltr\"\n\t\t\t>\n\t\t\t\t{tooltipData.content}\n\t\t\t\t<_Tooltip.Arrow className=\"tlui-tooltip__arrow\" />\n\t\t\t</_Tooltip.Content>\n\t\t</_Tooltip.Root>\n\t)\n}\n\n/** @public @react */\nexport const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProps>(\n\t({ children, content, side, sideOffset = 5, disabled = false }, ref) => {\n\t\tconst editor = useMaybeEditor()\n\t\tconst tooltipId = useRef<string>(uniqueId())\n\t\tconst hasProvider = useContext(TooltipSingletonContext)\n\n\t\tconst orientationCtx = useTldrawUiOrientation()\n\t\tconst sideToUse = side ?? orientationCtx.tooltipSide\n\n\t\tuseEffect(() => {\n\t\t\tconst currentTooltipId = tooltipId.current\n\t\t\treturn () => {\n\t\t\t\tif (hasProvider) {\n\t\t\t\t\ttooltipManager.hideTooltip(currentTooltipId, true)\n\t\t\t\t}\n\t\t\t}\n\t\t}, [hasProvider])\n\n\t\t// Don't show tooltip if disabled, no content, or UI labels are disabled\n\t\tif (disabled || !content) {\n\t\t\treturn <>{children}</>\n\t\t}\n\n\t\t// Fallback to old behavior if no provider\n\t\tif (!hasProvider) {\n\t\t\treturn (\n\t\t\t\t<_Tooltip.Root\n\t\t\t\t\tdelayDuration={editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS}\n\t\t\t\t\tdisableHoverableContent\n\t\t\t\t>\n\t\t\t\t\t<_Tooltip.Trigger asChild ref={ref}>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</_Tooltip.Trigger>\n\t\t\t\t\t<_Tooltip.Content\n\t\t\t\t\t\tclassName=\"tlui-tooltip\"\n\t\t\t\t\t\tside={sideToUse}\n\t\t\t\t\t\tsideOffset={sideOffset}\n\t\t\t\t\t\tavoidCollisions\n\t\t\t\t\t\tcollisionPadding={8}\n\t\t\t\t\t\tdir=\"ltr\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{content}\n\t\t\t\t\t\t<_Tooltip.Arrow className=\"tlui-tooltip__arrow\" />\n\t\t\t\t\t</_Tooltip.Content>\n\t\t\t\t</_Tooltip.Root>\n\t\t\t)\n\t\t}\n\n\t\tconst child = React.Children.only(children)\n\t\tassert(React.isValidElement(child), 'TldrawUiTooltip children must be a single element')\n\n\t\tconst handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {\n\t\t\tchild.props.onMouseEnter?.(event)\n\t\t\ttooltipManager.showTooltip(\n\t\t\t\ttooltipId.current,\n\t\t\t\tcontent,\n\t\t\t\tevent.currentTarget as HTMLElement,\n\t\t\t\tsideToUse,\n\t\t\t\tsideOffset\n\t\t\t)\n\t\t}\n\n\t\tconst handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {\n\t\t\tchild.props.onMouseLeave?.(event)\n\t\t\ttooltipManager.hideTooltip(tooltipId.current)\n\t\t}\n\n\t\tconst handleFocus = (event: React.FocusEvent<HTMLElement>) => {\n\t\t\tchild.props.onFocus?.(event)\n\t\t\ttooltipManager.showTooltip(\n\t\t\t\ttooltipId.current,\n\t\t\t\tcontent,\n\t\t\t\tevent.currentTarget as HTMLElement,\n\t\t\t\tsideToUse,\n\t\t\t\tsideOffset\n\t\t\t)\n\t\t}\n\n\t\tconst handleBlur = (event: React.FocusEvent<HTMLElement>) => {\n\t\t\tchild.props.onBlur?.(event)\n\t\t\ttooltipManager.hideTooltip(tooltipId.current)\n\t\t}\n\n\t\tconst childrenWithHandlers = React.cloneElement(children as React.ReactElement, {\n\t\t\tonMouseEnter: handleMouseEnter,\n\t\t\tonMouseLeave: handleMouseLeave,\n\t\t\tonFocus: handleFocus,\n\t\t\tonBlur: handleBlur,\n\t\t})\n\n\t\treturn childrenWithHandlers\n\t}\n)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { assert, Atom, atom, Editor, uniqueId, useMaybeEditor, useValue } from '@tldraw/editor'\nimport { Tooltip as _Tooltip } from 'radix-ui'\nimport React, {\n\tcreateContext,\n\tforwardRef,\n\tReactNode,\n\tuseContext,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n} from 'react'\nimport { useTldrawUiOrientation } from './layout'\n\nconst DEFAULT_TOOLTIP_DELAY_MS = 700\n\n/** @public */\nexport interface TldrawUiTooltipProps {\n\tchildren: React.ReactNode\n\tcontent?: string | React.ReactNode\n\tside?: 'top' | 'right' | 'bottom' | 'left'\n\tsideOffset?: number\n\tdisabled?: boolean\n\tshowOnMobile?: boolean\n\tdelayDuration?: number\n}\n\n// Singleton tooltip manager\nclass TooltipManager {\n\tprivate static instance: TooltipManager | null = null\n\tprivate currentTooltip = atom<{\n\t\tid: string\n\t\tcontent: ReactNode\n\t\tside: 'top' | 'right' | 'bottom' | 'left'\n\t\tsideOffset: number\n\t\tshowOnMobile: boolean\n\t\ttargetElement: HTMLElement\n\t\tdelayDuration: number\n\t} | null>('current tooltip', null)\n\tprivate destroyTimeoutId: number | null = null\n\n\tstatic getInstance(): TooltipManager {\n\t\tif (!TooltipManager.instance) {\n\t\t\tTooltipManager.instance = new TooltipManager()\n\t\t}\n\t\treturn TooltipManager.instance\n\t}\n\n\tshowTooltip(\n\t\ttooltipId: string,\n\t\tcontent: string | React.ReactNode,\n\t\ttargetElement: HTMLElement,\n\t\tside: 'top' | 'right' | 'bottom' | 'left',\n\t\tsideOffset: number,\n\t\tshowOnMobile: boolean,\n\t\tdelayDuration: number\n\t) {\n\t\t// Clear any existing destroy timeout\n\t\tif (this.destroyTimeoutId) {\n\t\t\tclearTimeout(this.destroyTimeoutId)\n\t\t\tthis.destroyTimeoutId = null\n\t\t}\n\n\t\t// Update current tooltip\n\t\tthis.currentTooltip.set({\n\t\t\tid: tooltipId,\n\t\t\tcontent,\n\t\t\tside,\n\t\t\tsideOffset,\n\t\t\tshowOnMobile,\n\t\t\ttargetElement,\n\t\t\tdelayDuration,\n\t\t})\n\t}\n\n\thideTooltip(editor: Editor | null, tooltipId: string, instant: boolean = false) {\n\t\tconst hide = () => {\n\t\t\t// Only hide if this is the current tooltip\n\t\t\tif (this.currentTooltip.get()?.id === tooltipId) {\n\t\t\t\tthis.currentTooltip.set(null)\n\t\t\t\tthis.destroyTimeoutId = null\n\t\t\t}\n\t\t}\n\n\t\tif (editor && !instant) {\n\t\t\t// Start destroy timeout (1 second)\n\t\t\tthis.destroyTimeoutId = editor.timers.setTimeout(hide, 300)\n\t\t} else {\n\t\t\thide()\n\t\t}\n\t}\n\n\thideAllTooltips() {\n\t\tthis.currentTooltip.set(null)\n\t\tthis.destroyTimeoutId = null\n\t}\n\n\tgetCurrentTooltipData() {\n\t\tconst currentTooltip = this.currentTooltip.get()\n\t\tif (!currentTooltip) return null\n\t\tif (!this.supportsHover() && !currentTooltip.showOnMobile) return null\n\t\treturn currentTooltip\n\t}\n\n\tprivate supportsHoverAtom: Atom<boolean> | null = null\n\tsupportsHover() {\n\t\tif (!this.supportsHoverAtom) {\n\t\t\tconst mediaQuery = window.matchMedia('(hover: hover)')\n\t\t\tconst supportsHover = atom('has hover', mediaQuery.matches)\n\t\t\tthis.supportsHoverAtom = supportsHover\n\t\t\tmediaQuery.addEventListener('change', (e) => {\n\t\t\t\tsupportsHover.set(e.matches)\n\t\t\t})\n\t\t}\n\t\treturn this.supportsHoverAtom.get()\n\t}\n}\n\nexport const tooltipManager = TooltipManager.getInstance()\n\n// Context for the tooltip singleton\nconst TooltipSingletonContext = createContext<boolean>(false)\n\n/** @public */\nexport interface TldrawUiTooltipProviderProps {\n\tchildren: React.ReactNode\n}\n\n/** @public @react */\nexport function TldrawUiTooltipProvider({ children }: TldrawUiTooltipProviderProps) {\n\treturn (\n\t\t<_Tooltip.Provider skipDelayDuration={700}>\n\t\t\t<TooltipSingletonContext.Provider value={true}>\n\t\t\t\t{children}\n\t\t\t\t<TooltipSingleton />\n\t\t\t</TooltipSingletonContext.Provider>\n\t\t</_Tooltip.Provider>\n\t)\n}\n\n// The singleton tooltip component that renders once\nfunction TooltipSingleton() {\n\tconst [isOpen, setIsOpen] = useState(false)\n\tconst triggerRef = useRef<HTMLDivElement>(null)\n\tconst isFirstShowRef = useRef(true)\n\tconst editor = useMaybeEditor()\n\n\tconst currentTooltip = useValue(\n\t\t'current tooltip',\n\t\t() => tooltipManager.getCurrentTooltipData(),\n\t\t[]\n\t)\n\n\tconst cameraState = useValue('camera state', () => editor?.getCameraState(), [editor])\n\n\t// Hide tooltip when camera is moving (panning/zooming)\n\tuseEffect(() => {\n\t\tif (cameraState === 'moving' && isOpen && currentTooltip) {\n\t\t\ttooltipManager.hideTooltip(editor, currentTooltip.id, true)\n\t\t}\n\t}, [cameraState, isOpen, currentTooltip, editor])\n\n\t// Update open state and trigger position\n\tuseEffect(() => {\n\t\tlet timer: ReturnType<typeof setTimeout> | null = null\n\t\tif (currentTooltip && triggerRef.current) {\n\t\t\t// Position the invisible trigger element over the active element\n\t\t\tconst activeRect = currentTooltip.targetElement.getBoundingClientRect()\n\t\t\tconst trigger = triggerRef.current\n\n\t\t\ttrigger.style.position = 'fixed'\n\t\t\ttrigger.style.left = `${activeRect.left}px`\n\t\t\ttrigger.style.top = `${activeRect.top}px`\n\t\t\ttrigger.style.width = `${activeRect.width}px`\n\t\t\ttrigger.style.height = `${activeRect.height}px`\n\t\t\ttrigger.style.pointerEvents = 'none'\n\t\t\ttrigger.style.zIndex = '9999'\n\n\t\t\t// Handle delay for first show\n\t\t\tif (isFirstShowRef.current) {\n\t\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\t\ttimer = setTimeout(() => {\n\t\t\t\t\tsetIsOpen(true)\n\t\t\t\t\tisFirstShowRef.current = false\n\t\t\t\t}, currentTooltip.delayDuration)\n\t\t\t} else {\n\t\t\t\t// Subsequent tooltips show immediately\n\t\t\t\tsetIsOpen(true)\n\t\t\t}\n\t\t} else {\n\t\t\t// Hide tooltip immediately\n\t\t\tsetIsOpen(false)\n\t\t\t// Reset first show state after tooltip is hidden\n\t\t\tisFirstShowRef.current = true\n\t\t}\n\n\t\treturn () => {\n\t\t\tif (timer !== null) {\n\t\t\t\tclearTimeout(timer)\n\t\t\t}\n\t\t}\n\t}, [currentTooltip])\n\n\tif (!currentTooltip) {\n\t\treturn null\n\t}\n\n\treturn (\n\t\t<_Tooltip.Root open={isOpen} delayDuration={0}>\n\t\t\t<_Tooltip.Trigger asChild>\n\t\t\t\t<div ref={triggerRef} />\n\t\t\t</_Tooltip.Trigger>\n\t\t\t<_Tooltip.Content\n\t\t\t\tclassName=\"tlui-tooltip\"\n\t\t\t\tside={currentTooltip.side}\n\t\t\t\tsideOffset={currentTooltip.sideOffset}\n\t\t\t\tavoidCollisions\n\t\t\t\tcollisionPadding={8}\n\t\t\t\tdir=\"ltr\"\n\t\t\t>\n\t\t\t\t{currentTooltip.content}\n\t\t\t\t<_Tooltip.Arrow className=\"tlui-tooltip__arrow\" />\n\t\t\t</_Tooltip.Content>\n\t\t</_Tooltip.Root>\n\t)\n}\n\n/** @public @react */\nexport const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProps>(\n\t(\n\t\t{\n\t\t\tchildren,\n\t\t\tcontent,\n\t\t\tside,\n\t\t\tsideOffset = 5,\n\t\t\tdisabled = false,\n\t\t\tshowOnMobile = false,\n\t\t\tdelayDuration,\n\t\t},\n\t\tref\n\t) => {\n\t\tconst editor = useMaybeEditor()\n\t\tconst tooltipId = useRef<string>(uniqueId())\n\t\tconst hasProvider = useContext(TooltipSingletonContext)\n\n\t\tconst orientationCtx = useTldrawUiOrientation()\n\t\tconst sideToUse = side ?? orientationCtx.tooltipSide\n\n\t\tuseEffect(() => {\n\t\t\tconst currentTooltipId = tooltipId.current\n\t\t\treturn () => {\n\t\t\t\tif (hasProvider) {\n\t\t\t\t\ttooltipManager.hideTooltip(editor, currentTooltipId, true)\n\t\t\t\t}\n\t\t\t}\n\t\t}, [editor, hasProvider])\n\n\t\t// Don't show tooltip if disabled, no content, or UI labels are disabled\n\t\tif (disabled || !content) {\n\t\t\treturn <>{children}</>\n\t\t}\n\n\t\tconst delayDurationToUse =\n\t\t\tdelayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)\n\n\t\t// Fallback to old behavior if no provider\n\t\tif (!hasProvider) {\n\t\t\treturn (\n\t\t\t\t<_Tooltip.Root delayDuration={delayDurationToUse} disableHoverableContent>\n\t\t\t\t\t<_Tooltip.Trigger asChild ref={ref}>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</_Tooltip.Trigger>\n\t\t\t\t\t<_Tooltip.Content\n\t\t\t\t\t\tclassName=\"tlui-tooltip\"\n\t\t\t\t\t\tside={sideToUse}\n\t\t\t\t\t\tsideOffset={sideOffset}\n\t\t\t\t\t\tavoidCollisions\n\t\t\t\t\t\tcollisionPadding={8}\n\t\t\t\t\t\tdir=\"ltr\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{content}\n\t\t\t\t\t\t<_Tooltip.Arrow className=\"tlui-tooltip__arrow\" />\n\t\t\t\t\t</_Tooltip.Content>\n\t\t\t\t</_Tooltip.Root>\n\t\t\t)\n\t\t}\n\n\t\tconst child = React.Children.only(children)\n\t\tassert(React.isValidElement(child), 'TldrawUiTooltip children must be a single element')\n\n\t\tconst handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {\n\t\t\tchild.props.onMouseEnter?.(event)\n\t\t\ttooltipManager.showTooltip(\n\t\t\t\ttooltipId.current,\n\t\t\t\tcontent,\n\t\t\t\tevent.currentTarget as HTMLElement,\n\t\t\t\tsideToUse,\n\t\t\t\tsideOffset,\n\t\t\t\tshowOnMobile,\n\t\t\t\tdelayDurationToUse\n\t\t\t)\n\t\t}\n\n\t\tconst handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {\n\t\t\tchild.props.onMouseLeave?.(event)\n\t\t\ttooltipManager.hideTooltip(editor, tooltipId.current)\n\t\t}\n\n\t\tconst handleFocus = (event: React.FocusEvent<HTMLElement>) => {\n\t\t\tchild.props.onFocus?.(event)\n\t\t\ttooltipManager.showTooltip(\n\t\t\t\ttooltipId.current,\n\t\t\t\tcontent,\n\t\t\t\tevent.currentTarget as HTMLElement,\n\t\t\t\tsideToUse,\n\t\t\t\tsideOffset,\n\t\t\t\tshowOnMobile,\n\t\t\t\tdelayDurationToUse\n\t\t\t)\n\t\t}\n\n\t\tconst handleBlur = (event: React.FocusEvent<HTMLElement>) => {\n\t\t\tchild.props.onBlur?.(event)\n\t\t\ttooltipManager.hideTooltip(editor, tooltipId.current)\n\t\t}\n\n\t\tconst childrenWithHandlers = React.cloneElement(children as React.ReactElement, {\n\t\t\tonMouseEnter: handleMouseEnter,\n\t\t\tonMouseLeave: handleMouseLeave,\n\t\t\tonFocus: handleFocus,\n\t\t\tonBlur: handleBlur,\n\t\t})\n\n\t\treturn childrenWithHandlers\n\t}\n)\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx"],
4
- "sourcesContent": ["import { createContext, useContext } from 'react'\nimport { TLUiEventSource } from '../../../context/events'\n\n/** @public */\nexport type TLUiMenuContextType =\n\t| 'panel'\n\t| 'menu'\n\t| 'small-icons'\n\t| 'context-menu'\n\t| 'icons'\n\t| 'keyboard-shortcuts'\n\t| 'helper-buttons'\n\t| 'toolbar'\n\t| 'toolbar-overflow'\n\nconst menuContext = createContext<{\n\ttype: TLUiMenuContextType\n\tsourceId: TLUiEventSource\n} | null>(null)\n\n/** @public */\nexport function useTldrawUiMenuContext() {\n\tconst context = useContext(menuContext)\n\tif (!context) {\n\t\tthrow new Error('useTldrawUiMenuContext must be used within a TldrawUiMenuContextProvider')\n\t}\n\treturn context\n}\n\n/** @public */\nexport interface TLUiMenuContextProviderProps {\n\ttype: TLUiMenuContextType\n\tsourceId: TLUiEventSource\n\tchildren: React.ReactNode\n}\n\n/** @public @react */\nexport function TldrawUiMenuContextProvider({\n\ttype,\n\tsourceId,\n\tchildren,\n}: TLUiMenuContextProviderProps) {\n\treturn <menuContext.Provider value={{ type, sourceId }}>{children}</menuContext.Provider>\n}\n"],
5
- "mappings": "AA0CQ;AA1CR,SAAS,eAAe,kBAAkB;AAe1C,MAAM,cAAc,cAGV,IAAI;AAGP,SAAS,yBAAyB;AACxC,QAAM,UAAU,WAAW,WAAW;AACtC,MAAI,CAAC,SAAS;AACb,UAAM,IAAI,MAAM,0EAA0E;AAAA,EAC3F;AACA,SAAO;AACR;AAUO,SAAS,4BAA4B;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AACD,GAAiC;AAChC,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAO,EAAE,MAAM,SAAS,GAAI,UAAS;AACnE;",
4
+ "sourcesContent": ["import { createContext, useContext } from 'react'\nimport { TLUiEventSource } from '../../../context/events'\n\n/** @public */\nexport type TLUiMenuContextType =\n\t| 'menu'\n\t| 'small-icons'\n\t| 'context-menu'\n\t| 'icons'\n\t| 'keyboard-shortcuts'\n\t| 'helper-buttons'\n\t| 'toolbar'\n\t| 'toolbar-overflow'\n\nconst menuContext = createContext<{\n\ttype: TLUiMenuContextType\n\tsourceId: TLUiEventSource\n} | null>(null)\n\n/** @public */\nexport function useTldrawUiMenuContext() {\n\tconst context = useContext(menuContext)\n\tif (!context) {\n\t\tthrow new Error('useTldrawUiMenuContext must be used within a TldrawUiMenuContextProvider')\n\t}\n\treturn context\n}\n\n/** @public */\nexport interface TLUiMenuContextProviderProps {\n\ttype: TLUiMenuContextType\n\tsourceId: TLUiEventSource\n\tchildren: React.ReactNode\n}\n\n/** @public @react */\nexport function TldrawUiMenuContextProvider({\n\ttype,\n\tsourceId,\n\tchildren,\n}: TLUiMenuContextProviderProps) {\n\treturn <menuContext.Provider value={{ type, sourceId }}>{children}</menuContext.Provider>\n}\n"],
5
+ "mappings": "AAyCQ;AAzCR,SAAS,eAAe,kBAAkB;AAc1C,MAAM,cAAc,cAGV,IAAI;AAGP,SAAS,yBAAyB;AACxC,QAAM,UAAU,WAAW,WAAW;AACtC,MAAI,CAAC,SAAS;AACb,UAAM,IAAI,MAAM,0EAA0E;AAAA,EAC3F;AACA,SAAO;AACR;AAUO,SAAS,4BAA4B;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AACD,GAAiC;AAChC,SAAO,oBAAC,YAAY,UAAZ,EAAqB,OAAO,EAAE,MAAM,SAAS,GAAI,UAAS;AACnE;",
6
6
  "names": []
7
7
  }
@@ -12,16 +12,6 @@ function TldrawUiMenuGroup({ id, label, className, children }) {
12
12
  const labelToUse = unwrapLabel(label, menu.type);
13
13
  const labelStr = labelToUse ? msg(labelToUse) : void 0;
14
14
  switch (menu.type) {
15
- case "panel": {
16
- return /* @__PURE__ */ jsx(
17
- "div",
18
- {
19
- className: classNames("tlui-menu__group", className),
20
- "data-testid": `${menu.sourceId}-group.${id}`,
21
- children
22
- }
23
- );
24
- }
25
15
  case "menu": {
26
16
  return /* @__PURE__ */ jsx(
27
17
  TldrawUiDropdownMenuGroup,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx"],
4
- "sourcesContent": ["import classNames from 'classnames'\nimport { ReactNode } from 'react'\nimport { unwrapLabel } from '../../../context/actions'\nimport { TLUiTranslationKey } from '../../../hooks/useTranslation/TLUiTranslationKey'\nimport { useTranslation } from '../../../hooks/useTranslation/useTranslation'\nimport { TldrawUiColumn, TldrawUiGrid, TldrawUiRow, useTldrawUiOrientation } from '../layout'\nimport { TldrawUiDropdownMenuGroup } from '../TldrawUiDropdownMenu'\nimport { useTldrawUiMenuContext } from './TldrawUiMenuContext'\n\n/** @public */\nexport interface TLUiMenuGroupProps<TranslationKey extends string = string> {\n\tid: string\n\t/**\n\t * The label to display on the item. If it's a string, it will be translated. If it's an object, the keys will be used as the language keys and the values will be translated.\n\t */\n\tlabel?: TranslationKey | { [key: string]: TranslationKey }\n\tclassName?: string\n\tchildren?: ReactNode\n}\n\n/** @public @react */\nexport function TldrawUiMenuGroup({ id, label, className, children }: TLUiMenuGroupProps) {\n\tconst menu = useTldrawUiMenuContext()\n\tconst { orientation } = useTldrawUiOrientation()\n\tconst msg = useTranslation()\n\tconst labelToUse = unwrapLabel(label, menu.type)\n\tconst labelStr = labelToUse ? msg(labelToUse as TLUiTranslationKey) : undefined\n\n\tswitch (menu.type) {\n\t\tcase 'panel': {\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tclassName={classNames('tlui-menu__group', className)}\n\t\t\t\t\tdata-testid={`${menu.sourceId}-group.${id}`}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\t\tcase 'menu': {\n\t\t\treturn (\n\t\t\t\t<TldrawUiDropdownMenuGroup\n\t\t\t\t\tclassName={className}\n\t\t\t\t\tdata-testid={`${menu.sourceId}-group.${id}`}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</TldrawUiDropdownMenuGroup>\n\t\t\t)\n\t\t}\n\t\tcase 'context-menu': {\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tdir=\"ltr\"\n\t\t\t\t\tclassName={classNames('tlui-menu__group', className)}\n\t\t\t\t\tdata-testid={`${menu.sourceId}-group.${id}`}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\t\tcase 'keyboard-shortcuts': {\n\t\t\t// todo: if groups need a label, let's give em a label\n\t\t\treturn (\n\t\t\t\t<div className=\"tlui-shortcuts-dialog__group\" data-testid={`${menu.sourceId}-group.${id}`}>\n\t\t\t\t\t<h2 className=\"tlui-shortcuts-dialog__group__title\">{labelStr}</h2>\n\t\t\t\t\t<div className=\"tlui-shortcuts-dialog__group__content\">{children}</div>\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\t\tcase 'toolbar': {\n\t\t\tconst Layout = orientation === 'horizontal' ? TldrawUiRow : TldrawUiColumn\n\t\t\treturn (\n\t\t\t\t<Layout className=\"tlui-main-toolbar__group\" data-testid={`${menu.sourceId}-group.${id}`}>\n\t\t\t\t\t{children}\n\t\t\t\t</Layout>\n\t\t\t)\n\t\t}\n\t\tcase 'toolbar-overflow': {\n\t\t\treturn (\n\t\t\t\t<TldrawUiGrid\n\t\t\t\t\tclassName=\"tlui-main-toolbar__group\"\n\t\t\t\t\tdata-testid={`${menu.sourceId}-group.${id}`}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</TldrawUiGrid>\n\t\t\t)\n\t\t}\n\t\tdefault: {\n\t\t\treturn children\n\t\t}\n\t}\n}\n"],
5
- "mappings": "AA+BI,cAgCA,YAhCA;AA/BJ,OAAO,gBAAgB;AAEvB,SAAS,mBAAmB;AAE5B,SAAS,sBAAsB;AAC/B,SAAS,gBAAgB,cAAc,aAAa,8BAA8B;AAClF,SAAS,iCAAiC;AAC1C,SAAS,8BAA8B;AAchC,SAAS,kBAAkB,EAAE,IAAI,OAAO,WAAW,SAAS,GAAuB;AACzF,QAAM,OAAO,uBAAuB;AACpC,QAAM,EAAE,YAAY,IAAI,uBAAuB;AAC/C,QAAM,MAAM,eAAe;AAC3B,QAAM,aAAa,YAAY,OAAO,KAAK,IAAI;AAC/C,QAAM,WAAW,aAAa,IAAI,UAAgC,IAAI;AAEtE,UAAQ,KAAK,MAAM;AAAA,IAClB,KAAK,SAAS;AACb,aACC;AAAA,QAAC;AAAA;AAAA,UACA,WAAW,WAAW,oBAAoB,SAAS;AAAA,UACnD,eAAa,GAAG,KAAK,QAAQ,UAAU,EAAE;AAAA,UAExC;AAAA;AAAA,MACF;AAAA,IAEF;AAAA,IACA,KAAK,QAAQ;AACZ,aACC;AAAA,QAAC;AAAA;AAAA,UACA;AAAA,UACA,eAAa,GAAG,KAAK,QAAQ,UAAU,EAAE;AAAA,UAExC;AAAA;AAAA,MACF;AAAA,IAEF;AAAA,IACA,KAAK,gBAAgB;AACpB,aACC;AAAA,QAAC;AAAA;AAAA,UACA,KAAI;AAAA,UACJ,WAAW,WAAW,oBAAoB,SAAS;AAAA,UACnD,eAAa,GAAG,KAAK,QAAQ,UAAU,EAAE;AAAA,UAExC;AAAA;AAAA,MACF;AAAA,IAEF;AAAA,IACA,KAAK,sBAAsB;AAE1B,aACC,qBAAC,SAAI,WAAU,gCAA+B,eAAa,GAAG,KAAK,QAAQ,UAAU,EAAE,IACtF;AAAA,4BAAC,QAAG,WAAU,uCAAuC,oBAAS;AAAA,QAC9D,oBAAC,SAAI,WAAU,yCAAyC,UAAS;AAAA,SAClE;AAAA,IAEF;AAAA,IACA,KAAK,WAAW;AACf,YAAM,SAAS,gBAAgB,eAAe,cAAc;AAC5D,aACC,oBAAC,UAAO,WAAU,4BAA2B,eAAa,GAAG,KAAK,QAAQ,UAAU,EAAE,IACpF,UACF;AAAA,IAEF;AAAA,IACA,KAAK,oBAAoB;AACxB,aACC;AAAA,QAAC;AAAA;AAAA,UACA,WAAU;AAAA,UACV,eAAa,GAAG,KAAK,QAAQ,UAAU,EAAE;AAAA,UAExC;AAAA;AAAA,MACF;AAAA,IAEF;AAAA,IACA,SAAS;AACR,aAAO;AAAA,IACR;AAAA,EACD;AACD;",
4
+ "sourcesContent": ["import classNames from 'classnames'\nimport { ReactNode } from 'react'\nimport { unwrapLabel } from '../../../context/actions'\nimport { TLUiTranslationKey } from '../../../hooks/useTranslation/TLUiTranslationKey'\nimport { useTranslation } from '../../../hooks/useTranslation/useTranslation'\nimport { TldrawUiColumn, TldrawUiGrid, TldrawUiRow, useTldrawUiOrientation } from '../layout'\nimport { TldrawUiDropdownMenuGroup } from '../TldrawUiDropdownMenu'\nimport { useTldrawUiMenuContext } from './TldrawUiMenuContext'\n\n/** @public */\nexport interface TLUiMenuGroupProps<TranslationKey extends string = string> {\n\tid: string\n\t/**\n\t * The label to display on the item. If it's a string, it will be translated. If it's an object, the keys will be used as the language keys and the values will be translated.\n\t */\n\tlabel?: TranslationKey | { [key: string]: TranslationKey }\n\tclassName?: string\n\tchildren?: ReactNode\n}\n\n/** @public @react */\nexport function TldrawUiMenuGroup({ id, label, className, children }: TLUiMenuGroupProps) {\n\tconst menu = useTldrawUiMenuContext()\n\tconst { orientation } = useTldrawUiOrientation()\n\tconst msg = useTranslation()\n\tconst labelToUse = unwrapLabel(label, menu.type)\n\tconst labelStr = labelToUse ? msg(labelToUse as TLUiTranslationKey) : undefined\n\n\tswitch (menu.type) {\n\t\tcase 'menu': {\n\t\t\treturn (\n\t\t\t\t<TldrawUiDropdownMenuGroup\n\t\t\t\t\tclassName={className}\n\t\t\t\t\tdata-testid={`${menu.sourceId}-group.${id}`}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</TldrawUiDropdownMenuGroup>\n\t\t\t)\n\t\t}\n\t\tcase 'context-menu': {\n\t\t\treturn (\n\t\t\t\t<div\n\t\t\t\t\tdir=\"ltr\"\n\t\t\t\t\tclassName={classNames('tlui-menu__group', className)}\n\t\t\t\t\tdata-testid={`${menu.sourceId}-group.${id}`}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\t\tcase 'keyboard-shortcuts': {\n\t\t\t// todo: if groups need a label, let's give em a label\n\t\t\treturn (\n\t\t\t\t<div className=\"tlui-shortcuts-dialog__group\" data-testid={`${menu.sourceId}-group.${id}`}>\n\t\t\t\t\t<h2 className=\"tlui-shortcuts-dialog__group__title\">{labelStr}</h2>\n\t\t\t\t\t<div className=\"tlui-shortcuts-dialog__group__content\">{children}</div>\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\t\tcase 'toolbar': {\n\t\t\tconst Layout = orientation === 'horizontal' ? TldrawUiRow : TldrawUiColumn\n\t\t\treturn (\n\t\t\t\t<Layout className=\"tlui-main-toolbar__group\" data-testid={`${menu.sourceId}-group.${id}`}>\n\t\t\t\t\t{children}\n\t\t\t\t</Layout>\n\t\t\t)\n\t\t}\n\t\tcase 'toolbar-overflow': {\n\t\t\treturn (\n\t\t\t\t<TldrawUiGrid\n\t\t\t\t\tclassName=\"tlui-main-toolbar__group\"\n\t\t\t\t\tdata-testid={`${menu.sourceId}-group.${id}`}\n\t\t\t\t>\n\t\t\t\t\t{children}\n\t\t\t\t</TldrawUiGrid>\n\t\t\t)\n\t\t}\n\t\tdefault: {\n\t\t\treturn children\n\t\t}\n\t}\n}\n"],
5
+ "mappings": "AA+BI,cAsBA,YAtBA;AA/BJ,OAAO,gBAAgB;AAEvB,SAAS,mBAAmB;AAE5B,SAAS,sBAAsB;AAC/B,SAAS,gBAAgB,cAAc,aAAa,8BAA8B;AAClF,SAAS,iCAAiC;AAC1C,SAAS,8BAA8B;AAchC,SAAS,kBAAkB,EAAE,IAAI,OAAO,WAAW,SAAS,GAAuB;AACzF,QAAM,OAAO,uBAAuB;AACpC,QAAM,EAAE,YAAY,IAAI,uBAAuB;AAC/C,QAAM,MAAM,eAAe;AAC3B,QAAM,aAAa,YAAY,OAAO,KAAK,IAAI;AAC/C,QAAM,WAAW,aAAa,IAAI,UAAgC,IAAI;AAEtE,UAAQ,KAAK,MAAM;AAAA,IAClB,KAAK,QAAQ;AACZ,aACC;AAAA,QAAC;AAAA;AAAA,UACA;AAAA,UACA,eAAa,GAAG,KAAK,QAAQ,UAAU,EAAE;AAAA,UAExC;AAAA;AAAA,MACF;AAAA,IAEF;AAAA,IACA,KAAK,gBAAgB;AACpB,aACC;AAAA,QAAC;AAAA;AAAA,UACA,KAAI;AAAA,UACJ,WAAW,WAAW,oBAAoB,SAAS;AAAA,UACnD,eAAa,GAAG,KAAK,QAAQ,UAAU,EAAE;AAAA,UAExC;AAAA;AAAA,MACF;AAAA,IAEF;AAAA,IACA,KAAK,sBAAsB;AAE1B,aACC,qBAAC,SAAI,WAAU,gCAA+B,eAAa,GAAG,KAAK,QAAQ,UAAU,EAAE,IACtF;AAAA,4BAAC,QAAG,WAAU,uCAAuC,oBAAS;AAAA,QAC9D,oBAAC,SAAI,WAAU,yCAAyC,UAAS;AAAA,SAClE;AAAA,IAEF;AAAA,IACA,KAAK,WAAW;AACf,YAAM,SAAS,gBAAgB,eAAe,cAAc;AAC5D,aACC,oBAAC,UAAO,WAAU,4BAA2B,eAAa,GAAG,KAAK,QAAQ,UAAU,EAAE,IACpF,UACF;AAAA,IAEF;AAAA,IACA,KAAK,oBAAoB;AACxB,aACC;AAAA,QAAC;AAAA;AAAA,UACA,WAAU;AAAA,UACV,eAAa,GAAG,KAAK,QAAQ,UAAU,EAAE;AAAA,UAExC;AAAA;AAAA,MACF;AAAA,IAEF;AAAA,IACA,SAAS;AACR,aAAO;AAAA,IACR;AAAA,EACD;AACD;",
6
6
  "names": []
7
7
  }
@@ -52,7 +52,6 @@ function TldrawUiMenuItem({
52
52
  type: "menu",
53
53
  "data-testid": `${sourceId}.${id}`,
54
54
  disabled,
55
- title: titleStr,
56
55
  onClick: (e) => {
57
56
  if (noClose) {
58
57
  preventDefault(e);
@@ -77,7 +76,6 @@ function TldrawUiMenuItem({
77
76
  _ContextMenu.Item,
78
77
  {
79
78
  dir: "ltr",
80
- title: titleStr,
81
79
  draggable: false,
82
80
  className: "tlui-button tlui-button__menu",
83
81
  "data-testid": `${sourceId}.${id}`,
@@ -98,22 +96,6 @@ function TldrawUiMenuItem({
98
96
  }
99
97
  );
100
98
  }
101
- case "panel": {
102
- return /* @__PURE__ */ jsxs(
103
- TldrawUiButton,
104
- {
105
- "data-testid": `${sourceId}.${id}`,
106
- type: "menu",
107
- title: titleStr,
108
- disabled,
109
- onClick: () => onSelect(sourceId),
110
- children: [
111
- /* @__PURE__ */ jsx(TldrawUiButtonLabel, { children: labelStr }),
112
- spinner ? /* @__PURE__ */ jsx(Spinner, {}) : icon && /* @__PURE__ */ jsx(TldrawUiButtonIcon, { icon })
113
- ]
114
- }
115
- );
116
- }
117
99
  case "small-icons":
118
100
  case "icons": {
119
101
  return /* @__PURE__ */ jsx(
@@ -234,13 +216,14 @@ function useDraggableEvents(onDragStart, onSelect) {
234
216
  if (e.isSpecialRedispatchedEvent) return;
235
217
  if (state.name === "pointing") {
236
218
  const distanceSq = Vec.Dist2(state.screenSpaceStart, { x: e.clientX, y: e.clientY });
237
- if (distanceSq > (editor.getInstanceState().isCoarsePointer ? editor.options.coarseDragDistanceSquared : editor.options.dragDistanceSquared)) {
219
+ if (distanceSq > (editor.getInstanceState().isCoarsePointer ? editor.options.uiCoarseDragDistanceSquared : editor.options.uiDragDistanceSquared)) {
238
220
  const screenSpaceStart = state.screenSpaceStart;
239
221
  state = {
240
222
  name: "dragging",
241
223
  screenSpaceStart
242
224
  };
243
225
  editor.run(() => {
226
+ editor.setCurrentTool("select");
244
227
  editor.dispatch({
245
228
  type: "pointer",
246
229
  target: "canvas",
@@ -257,6 +240,7 @@ function useDraggableEvents(onDragStart, onSelect) {
257
240
  point: screenSpaceStart
258
241
  });
259
242
  tooltipManager.hideAllTooltips();
243
+ editor.getContainer().focus();
260
244
  });
261
245
  }
262
246
  }