tldraw 3.16.0-next.eafb52d15064 → 3.16.0-next.fe14f1b4181f

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 (359) hide show
  1. package/dist-cjs/index.d.ts +193 -6
  2. package/dist-cjs/index.js +16 -1
  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/canvas/TldrawScribble.js +1 -1
  7. package/dist-cjs/lib/canvas/TldrawScribble.js.map +2 -2
  8. package/dist-cjs/lib/defaultExternalContentHandlers.js +5 -4
  9. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  10. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js +3 -3
  11. package/dist-cjs/lib/shapes/arrow/ArrowShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js +3 -3
  13. package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js.map +1 -1
  14. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +3 -3
  15. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
  16. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +1 -1
  17. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +1 -1
  18. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +15 -12
  19. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  20. package/dist-cjs/lib/shapes/frame/components/FrameHeading.js +1 -1
  21. package/dist-cjs/lib/shapes/frame/components/FrameHeading.js.map +2 -2
  22. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +2 -2
  23. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  24. package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js +2 -1
  25. package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js.map +2 -2
  26. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +5 -1
  27. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
  28. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +6 -3
  29. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
  30. package/dist-cjs/lib/shapes/line/LineShapeUtil.js +5 -1
  31. package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
  32. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +4 -4
  33. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  34. package/dist-cjs/lib/shapes/shared/ShapeFill.js +4 -4
  35. package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
  36. package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
  37. package/dist-cjs/lib/shapes/text/TextShapeUtil.js +2 -2
  38. package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
  39. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +3 -3
  40. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +1 -1
  41. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +25 -1
  42. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  43. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +12 -0
  44. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  45. package/dist-cjs/lib/tools/SelectTool/childStates/Translating.js.map +2 -2
  46. package/dist-cjs/lib/ui/TldrawUi.js +27 -12
  47. package/dist-cjs/lib/ui/TldrawUi.js.map +3 -3
  48. package/dist-cjs/lib/ui/assetUrls.js +13 -10
  49. package/dist-cjs/lib/ui/assetUrls.js.map +2 -2
  50. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +12 -3
  51. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
  52. package/dist-cjs/lib/ui/components/{FollowingIndicator.js → DefaultFollowingIndicator.js} +6 -6
  53. package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +7 -0
  54. package/dist-cjs/lib/ui/components/DefaultMenuPanel.js +3 -2
  55. package/dist-cjs/lib/ui/components/DefaultMenuPanel.js.map +2 -2
  56. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +6 -6
  57. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
  58. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +4 -4
  59. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
  60. package/dist-cjs/lib/ui/components/MobileStylePanel.js +5 -3
  61. package/dist-cjs/lib/ui/components/MobileStylePanel.js.map +2 -2
  62. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js +1 -1
  63. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js.map +2 -2
  64. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +2 -1
  65. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
  66. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js +3 -2
  67. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js.map +2 -2
  68. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js +2 -2
  69. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js.map +2 -2
  70. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +14 -14
  71. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  72. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js +3 -3
  73. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +2 -2
  74. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js +26 -25
  75. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +3 -3
  76. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +1 -1
  77. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  78. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +66 -21
  79. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js.map +3 -3
  80. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +189 -80
  81. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +3 -3
  82. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +2 -2
  83. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
  84. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js +5 -16
  85. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +3 -3
  86. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +1 -1
  87. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  88. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +3 -2
  89. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js.map +3 -3
  90. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +6 -4
  91. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  92. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +19 -4
  93. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  94. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +155 -160
  95. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  96. package/dist-cjs/lib/ui/components/primitives/layout.js +76 -0
  97. package/dist-cjs/lib/ui/components/primitives/layout.js.map +7 -0
  98. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuContext.js.map +2 -2
  99. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +25 -12
  100. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
  101. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +154 -20
  102. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  103. package/dist-cjs/lib/ui/context/actions.js +16 -2
  104. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  105. package/dist-cjs/lib/ui/context/components.js +2 -0
  106. package/dist-cjs/lib/ui/context/components.js.map +2 -2
  107. package/dist-cjs/lib/ui/context/events.js.map +2 -2
  108. package/dist-cjs/lib/ui/hooks/useTools.js +94 -9
  109. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  110. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  111. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +1 -0
  112. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  113. package/dist-cjs/lib/ui/kbd-utils.js +9 -3
  114. package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
  115. package/dist-cjs/lib/ui/version.js +3 -3
  116. package/dist-cjs/lib/ui/version.js.map +1 -1
  117. package/dist-esm/index.d.mts +193 -6
  118. package/dist-esm/index.mjs +25 -2
  119. package/dist-esm/index.mjs.map +2 -2
  120. package/dist-esm/lib/Tldraw.mjs +14 -4
  121. package/dist-esm/lib/Tldraw.mjs.map +2 -2
  122. package/dist-esm/lib/canvas/TldrawScribble.mjs +1 -1
  123. package/dist-esm/lib/canvas/TldrawScribble.mjs.map +2 -2
  124. package/dist-esm/lib/defaultExternalContentHandlers.mjs +5 -4
  125. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  126. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +4 -3
  127. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  128. package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs +3 -3
  129. package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs.map +1 -1
  130. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +4 -3
  131. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
  132. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +1 -1
  133. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +1 -1
  134. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +16 -12
  135. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  136. package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs +1 -1
  137. package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs.map +2 -2
  138. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +3 -2
  139. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  140. package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs +2 -1
  141. package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs.map +2 -2
  142. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +6 -1
  143. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
  144. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +6 -3
  145. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
  146. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +6 -1
  147. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
  148. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +5 -4
  149. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  150. package/dist-esm/lib/shapes/shared/ShapeFill.mjs +5 -4
  151. package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
  152. package/dist-esm/lib/shapes/shared/freehand/svg.mjs.map +2 -2
  153. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +3 -2
  154. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
  155. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +3 -3
  156. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +1 -1
  157. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +26 -1
  158. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  159. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +13 -0
  160. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  161. package/dist-esm/lib/tools/SelectTool/childStates/Translating.mjs.map +2 -2
  162. package/dist-esm/lib/ui/TldrawUi.mjs +29 -14
  163. package/dist-esm/lib/ui/TldrawUi.mjs.map +3 -3
  164. package/dist-esm/lib/ui/assetUrls.mjs +13 -10
  165. package/dist-esm/lib/ui/assetUrls.mjs.map +2 -2
  166. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +12 -3
  167. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
  168. package/dist-esm/lib/ui/components/{FollowingIndicator.mjs → DefaultFollowingIndicator.mjs} +3 -3
  169. package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +7 -0
  170. package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs +3 -2
  171. package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs.map +2 -2
  172. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +6 -6
  173. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
  174. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +4 -4
  175. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
  176. package/dist-esm/lib/ui/components/MobileStylePanel.mjs +6 -3
  177. package/dist-esm/lib/ui/components/MobileStylePanel.mjs.map +2 -2
  178. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs +1 -1
  179. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs.map +2 -2
  180. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +2 -1
  181. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
  182. package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs +3 -2
  183. package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs.map +2 -2
  184. package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs +2 -2
  185. package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs.map +2 -2
  186. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +14 -14
  187. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  188. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs +3 -3
  189. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +2 -2
  190. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs +26 -25
  191. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +2 -2
  192. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +1 -1
  193. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  194. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs +56 -21
  195. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs.map +2 -2
  196. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +192 -81
  197. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +3 -3
  198. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +2 -2
  199. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
  200. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +6 -6
  201. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +2 -2
  202. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +1 -1
  203. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  204. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs +3 -2
  205. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs.map +2 -2
  206. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +6 -4
  207. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  208. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +19 -4
  209. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  210. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +164 -162
  211. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  212. package/dist-esm/lib/ui/components/primitives/layout.mjs +46 -0
  213. package/dist-esm/lib/ui/components/primitives/layout.mjs.map +7 -0
  214. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuContext.mjs.map +2 -2
  215. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs +25 -12
  216. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
  217. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +162 -22
  218. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  219. package/dist-esm/lib/ui/context/actions.mjs +16 -2
  220. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  221. package/dist-esm/lib/ui/context/components.mjs +2 -0
  222. package/dist-esm/lib/ui/context/components.mjs.map +2 -2
  223. package/dist-esm/lib/ui/context/events.mjs.map +2 -2
  224. package/dist-esm/lib/ui/hooks/useTools.mjs +102 -10
  225. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  226. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +1 -0
  227. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  228. package/dist-esm/lib/ui/kbd-utils.mjs +9 -3
  229. package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
  230. package/dist-esm/lib/ui/version.mjs +3 -3
  231. package/dist-esm/lib/ui/version.mjs.map +1 -1
  232. package/package.json +11 -34
  233. package/src/index.ts +18 -1
  234. package/src/lib/Tldraw.tsx +15 -2
  235. package/src/lib/canvas/TldrawScribble.tsx +1 -1
  236. package/src/lib/defaultExternalContentHandlers.ts +12 -4
  237. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +2 -1
  238. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +4 -3
  239. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +7 -6
  240. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +4 -3
  241. package/src/lib/shapes/arrow/elbow/ElbowArrowDebug.tsx +3 -3
  242. package/src/lib/shapes/draw/DrawShapeTool.test.ts +0 -5
  243. package/src/lib/shapes/draw/DrawShapeUtil.tsx +4 -3
  244. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
  245. package/src/lib/shapes/frame/FrameShapeUtil.tsx +25 -14
  246. package/src/lib/shapes/frame/components/FrameHeading.tsx +1 -1
  247. package/src/lib/shapes/geo/GeoShapeUtil.tsx +3 -2
  248. package/src/lib/shapes/geo/components/GeoShapeBody.tsx +2 -2
  249. package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +7 -1
  250. package/src/lib/shapes/image/ImageShapeUtil.tsx +6 -3
  251. package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -3
  252. package/src/lib/shapes/line/LineShapeUtil.tsx +6 -1
  253. package/src/lib/shapes/line/__snapshots__/LineShapeUtil.test.tsx.snap +2 -2
  254. package/src/lib/shapes/note/NoteShapeUtil.tsx +9 -4
  255. package/src/lib/shapes/shared/ShapeFill.tsx +5 -4
  256. package/src/lib/shapes/shared/freehand/svg.ts +2 -0
  257. package/src/lib/shapes/text/TextShapeTool.test.ts +6 -5
  258. package/src/lib/shapes/text/TextShapeUtil.tsx +3 -2
  259. package/src/lib/shapes/video/VideoShapeUtil.tsx +3 -3
  260. package/src/lib/tools/EraserTool/childStates/Erasing.ts +34 -1
  261. package/src/lib/tools/EraserTool/childStates/Pointing.ts +20 -0
  262. package/src/lib/tools/SelectTool/childStates/Translating.ts +0 -1
  263. package/src/lib/ui/TldrawUi.tsx +33 -12
  264. package/src/lib/ui/assetUrls.ts +13 -10
  265. package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +15 -3
  266. package/src/lib/ui/components/{FollowingIndicator.tsx → DefaultFollowingIndicator.tsx} +2 -1
  267. package/src/lib/ui/components/DefaultMenuPanel.tsx +4 -3
  268. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +6 -6
  269. package/src/lib/ui/components/Minimap/MinimapManager.ts +4 -4
  270. package/src/lib/ui/components/MobileStylePanel.tsx +9 -6
  271. package/src/lib/ui/components/NavigationPanel/DefaultNavigationPanel.tsx +1 -1
  272. package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +3 -2
  273. package/src/lib/ui/components/SharePanel/PeopleMenuItem.tsx +4 -3
  274. package/src/lib/ui/components/SharePanel/UserPresenceColorPicker.tsx +3 -3
  275. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +39 -43
  276. package/src/lib/ui/components/StylePanel/DoubleDropdownPicker.tsx +3 -3
  277. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +7 -6
  278. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +1 -1
  279. package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +55 -23
  280. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +212 -61
  281. package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +2 -2
  282. package/src/lib/ui/components/primitives/TldrawUiButtonPicker.tsx +40 -37
  283. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +1 -1
  284. package/src/lib/ui/components/primitives/TldrawUiPopover.tsx +4 -2
  285. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +35 -30
  286. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +32 -9
  287. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +196 -184
  288. package/src/lib/ui/components/primitives/layout.tsx +107 -0
  289. package/src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx +0 -1
  290. package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +29 -16
  291. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +221 -19
  292. package/src/lib/ui/context/actions.tsx +16 -2
  293. package/src/lib/ui/context/components.tsx +3 -0
  294. package/src/lib/ui/context/events.tsx +1 -0
  295. package/src/lib/ui/hooks/useTools.tsx +140 -10
  296. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +1 -0
  297. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +1 -0
  298. package/src/lib/ui/kbd-utils.ts +10 -3
  299. package/src/lib/ui/version.ts +3 -3
  300. package/src/lib/ui.css +366 -305
  301. package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +5 -5
  302. package/src/lib/utils/tldr/__snapshots__/buildFromV1Document.test.ts.snap +4 -4
  303. package/src/test/A11y.test.tsx +3 -2
  304. package/src/test/ClickManager.test.ts +7 -6
  305. package/src/test/Editor.test.tsx +20 -19
  306. package/src/test/EraserTool.test.ts +184 -13
  307. package/src/test/HandTool.test.ts +10 -9
  308. package/src/test/HighlightShape.test.ts +2 -1
  309. package/src/test/SelectTool.test.ts +3 -2
  310. package/src/test/TLUserPreferences.test.ts +4 -3
  311. package/src/test/TestEditor.ts +13 -15
  312. package/src/test/TldrawEditor.test.tsx +11 -10
  313. package/src/test/ZoomTool.test.ts +7 -6
  314. package/src/test/__snapshots__/drawing.test.ts.snap +2 -2
  315. package/src/test/__snapshots__/groups.test.tsx.snap +6 -6
  316. package/src/test/__snapshots__/resizing.test.ts.snap +2 -2
  317. package/src/test/arrows-megabus.test.tsx +5 -4
  318. package/src/test/bindings.test.tsx +24 -37
  319. package/src/test/bookmark-shapes.test.ts +1 -8
  320. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +23 -7
  321. package/src/test/commands/__snapshots__/packShapes.test.ts.snap +8 -8
  322. package/src/test/commands/__snapshots__/zoomToFit.test.ts.snap +2 -2
  323. package/src/test/commands/alignShapes.test.tsx +25 -24
  324. package/src/test/commands/animationSpeed.test.ts +2 -1
  325. package/src/test/commands/centerOnPoint.test.ts +3 -2
  326. package/src/test/commands/clipboard.test.ts +3 -2
  327. package/src/test/commands/createShapes.test.ts +2 -1
  328. package/src/test/commands/deleteShapes.test.ts +2 -1
  329. package/src/test/commands/distributeShapes.test.tsx +11 -10
  330. package/src/test/commands/getSvgString.test.ts +2 -1
  331. package/src/test/commands/packShapes.test.ts +5 -4
  332. package/src/test/commands/resizeShape.test.ts +2 -1
  333. package/src/test/commands/rotateShapes.test.ts +7 -6
  334. package/src/test/commands/setCamera.test.ts +4 -3
  335. package/src/test/commands/setCurrentPage.test.ts +3 -2
  336. package/src/test/commands/stackShapes.test.ts +11 -10
  337. package/src/test/commands/stretch.test.tsx +13 -12
  338. package/src/test/createDeepLink.test.tsx +2 -1
  339. package/src/test/cropping.test.ts +3 -2
  340. package/src/test/drawing.test.ts +2 -1
  341. package/src/test/flipShapes.test.ts +4 -3
  342. package/src/test/frames.test.ts +25 -24
  343. package/src/test/getCulledShapes.test.tsx +3 -2
  344. package/src/test/groups.test.tsx +1 -1
  345. package/src/test/handleDeepLink.test.tsx +2 -1
  346. package/src/test/maxShapes.test.ts +3 -2
  347. package/src/test/modifiers.test.ts +5 -4
  348. package/src/test/navigation.test.ts +12 -11
  349. package/src/test/panning.test.ts +2 -1
  350. package/src/test/perf/perf.test.ts +2 -1
  351. package/src/test/registerDeepLinkListener.test.tsx +10 -9
  352. package/src/test/resizing.test.ts +39 -38
  353. package/src/test/select.test.tsx +4 -3
  354. package/src/test/selection-omnibus.test.ts +11 -10
  355. package/src/test/shapeutils.test.ts +4 -3
  356. package/src/test/translating.test.ts +9 -8
  357. package/tldraw.css +667 -595
  358. package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
  359. package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
@@ -1,68 +1,75 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { 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, 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";
12
+ import { useTldrawUiOrientation } from "./layout.mjs";
6
13
  const DEFAULT_TOOLTIP_DELAY_MS = 700;
7
14
  class TooltipManager {
8
15
  static instance = null;
9
- currentTooltipId = null;
10
- currentContent = "";
11
- currentSide = "bottom";
12
- currentSideOffset = 5;
16
+ currentTooltip = atom("current tooltip", null);
13
17
  destroyTimeoutId = null;
14
- subscribers = /* @__PURE__ */ new Set();
15
- activeElement = null;
16
- editor = null;
17
18
  static getInstance() {
18
19
  if (!TooltipManager.instance) {
19
20
  TooltipManager.instance = new TooltipManager();
20
21
  }
21
22
  return TooltipManager.instance;
22
23
  }
23
- setEditor(editor) {
24
- this.editor = editor;
25
- }
26
- subscribe(callback) {
27
- this.subscribers.add(callback);
28
- return () => this.subscribers.delete(callback);
29
- }
30
- notify() {
31
- this.subscribers.forEach((callback) => callback());
32
- }
33
- showTooltip(tooltipId, content, element, side = "bottom", sideOffset = 5) {
24
+ showTooltip(tooltipId, content, targetElement, side, sideOffset, showOnMobile, delayDuration) {
34
25
  if (this.destroyTimeoutId) {
35
26
  clearTimeout(this.destroyTimeoutId);
36
27
  this.destroyTimeoutId = null;
37
28
  }
38
- this.currentTooltipId = tooltipId;
39
- this.currentContent = content;
40
- this.currentSide = side;
41
- this.currentSideOffset = sideOffset;
42
- this.activeElement = element;
43
- this.notify();
29
+ this.currentTooltip.set({
30
+ id: tooltipId,
31
+ content,
32
+ side,
33
+ sideOffset,
34
+ showOnMobile,
35
+ targetElement,
36
+ delayDuration
37
+ });
44
38
  }
45
- hideTooltip(tooltipId) {
46
- if (this.currentTooltipId === tooltipId) {
47
- if (this.editor) {
48
- this.destroyTimeoutId = this.editor.timers.setTimeout(() => {
49
- this.currentTooltipId = null;
50
- this.currentContent = "";
51
- this.activeElement = null;
52
- this.destroyTimeoutId = null;
53
- this.notify();
54
- }, 300);
39
+ hideTooltip(editor, tooltipId, instant = false) {
40
+ const hide = () => {
41
+ if (this.currentTooltip.get()?.id === tooltipId) {
42
+ this.currentTooltip.set(null);
43
+ this.destroyTimeoutId = null;
55
44
  }
45
+ };
46
+ if (editor && !instant) {
47
+ this.destroyTimeoutId = editor.timers.setTimeout(hide, 300);
48
+ } else {
49
+ hide();
56
50
  }
57
51
  }
52
+ hideAllTooltips() {
53
+ this.currentTooltip.set(null);
54
+ this.destroyTimeoutId = null;
55
+ }
58
56
  getCurrentTooltipData() {
59
- return {
60
- id: this.currentTooltipId,
61
- content: this.currentContent,
62
- side: this.currentSide,
63
- sideOffset: this.currentSideOffset,
64
- element: this.activeElement
65
- };
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();
66
73
  }
67
74
  }
68
75
  const tooltipManager = TooltipManager.getInstance();
@@ -74,45 +81,19 @@ function TldrawUiTooltipProvider({ children }) {
74
81
  ] }) });
75
82
  }
76
83
  function TooltipSingleton() {
77
- const editor = useMaybeEditor();
78
- const [, forceUpdate] = useState({});
79
84
  const [isOpen, setIsOpen] = useState(false);
80
85
  const triggerRef = useRef(null);
81
- const previousPositionRef = useRef(null);
82
- const prefersReducedMotion = usePrefersReducedMotion();
83
- const [shouldAnimate, setShouldAnimate] = useState(false);
84
86
  const isFirstShowRef = useRef(true);
85
- const showTimeoutRef = useRef(null);
86
- useEffect(() => {
87
- tooltipManager.setEditor(editor);
88
- }, [editor]);
87
+ const currentTooltip = useValue(
88
+ "current tooltip",
89
+ () => tooltipManager.getCurrentTooltipData(),
90
+ []
91
+ );
89
92
  useEffect(() => {
90
- const unsubscribe = tooltipManager.subscribe(() => {
91
- forceUpdate({});
92
- });
93
- return unsubscribe;
94
- }, []);
95
- const tooltipData = tooltipManager.getCurrentTooltipData();
96
- useEffect(() => {
97
- const shouldBeOpen = Boolean(tooltipData.id && tooltipData.element);
98
- if (showTimeoutRef.current) {
99
- clearTimeout(showTimeoutRef.current);
100
- showTimeoutRef.current = null;
101
- }
102
- if (shouldBeOpen && tooltipData.element && triggerRef.current) {
103
- const activeRect = tooltipData.element.getBoundingClientRect();
93
+ let timer = null;
94
+ if (currentTooltip && triggerRef.current) {
95
+ const activeRect = currentTooltip.targetElement.getBoundingClientRect();
104
96
  const trigger = triggerRef.current;
105
- const newPosition = {
106
- x: activeRect.left + activeRect.width / 2,
107
- y: activeRect.top + activeRect.height / 2
108
- };
109
- let shouldAnimateCheck = false;
110
- if (previousPositionRef.current) {
111
- const isNearPrevious = Vec.DistMin(previousPositionRef.current, newPosition, 200);
112
- shouldAnimateCheck = !prefersReducedMotion && isNearPrevious && Math.abs(newPosition.y - previousPositionRef.current.y) < 50;
113
- }
114
- setShouldAnimate(isFirstShowRef.current ? false : shouldAnimateCheck);
115
- previousPositionRef.current = newPosition;
116
97
  trigger.style.position = "fixed";
117
98
  trigger.style.left = `${activeRect.left}px`;
118
99
  trigger.style.top = `${activeRect.top}px`;
@@ -120,22 +101,25 @@ function TooltipSingleton() {
120
101
  trigger.style.height = `${activeRect.height}px`;
121
102
  trigger.style.pointerEvents = "none";
122
103
  trigger.style.zIndex = "9999";
123
- if (isFirstShowRef.current && editor) {
124
- showTimeoutRef.current = editor.timers.setTimeout(() => {
104
+ if (isFirstShowRef.current) {
105
+ timer = setTimeout(() => {
125
106
  setIsOpen(true);
126
107
  isFirstShowRef.current = false;
127
- }, editor.options.tooltipDelayMs);
108
+ }, currentTooltip.delayDuration);
128
109
  } else {
129
110
  setIsOpen(true);
130
111
  }
131
- } else if (!shouldBeOpen) {
112
+ } else {
132
113
  setIsOpen(false);
133
- previousPositionRef.current = null;
134
- setShouldAnimate(false);
135
114
  isFirstShowRef.current = true;
136
115
  }
137
- }, [tooltipData.id, tooltipData.element, editor, prefersReducedMotion]);
138
- if (!tooltipData.id) {
116
+ return () => {
117
+ if (timer !== null) {
118
+ clearTimeout(timer);
119
+ }
120
+ };
121
+ }, [currentTooltip]);
122
+ if (!currentTooltip) {
139
123
  return null;
140
124
  }
141
125
  return /* @__PURE__ */ jsxs(_Tooltip.Root, { open: isOpen, delayDuration: 0, children: [
@@ -144,94 +128,112 @@ function TooltipSingleton() {
144
128
  _Tooltip.Content,
145
129
  {
146
130
  className: "tlui-tooltip",
147
- "data-should-animate": shouldAnimate,
148
- side: tooltipData.side,
149
- sideOffset: tooltipData.sideOffset,
131
+ side: currentTooltip.side,
132
+ sideOffset: currentTooltip.sideOffset,
150
133
  avoidCollisions: true,
151
134
  collisionPadding: 8,
152
135
  dir: "ltr",
153
136
  children: [
154
- tooltipData.content,
137
+ currentTooltip.content,
155
138
  /* @__PURE__ */ jsx(_Tooltip.Arrow, { className: "tlui-tooltip__arrow" })
156
139
  ]
157
140
  }
158
141
  )
159
142
  ] });
160
143
  }
161
- function TldrawUiTooltip({
162
- children,
163
- content,
164
- side = "bottom",
165
- sideOffset = 5,
166
- disabled = false
167
- }) {
168
- const editor = useMaybeEditor();
169
- const tooltipId = useRef(uniqueId());
170
- const hasProvider = useContext(TooltipSingletonContext);
171
- if (disabled || !content) {
172
- return /* @__PURE__ */ jsx(Fragment, { children });
173
- }
174
- if (!hasProvider) {
175
- return /* @__PURE__ */ jsxs(
176
- _Tooltip.Root,
177
- {
178
- delayDuration: editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS,
179
- disableHoverableContent: true,
180
- children: [
181
- /* @__PURE__ */ jsx(_Tooltip.Trigger, { asChild: true, children }),
182
- /* @__PURE__ */ jsxs(
183
- _Tooltip.Content,
184
- {
185
- className: "tlui-tooltip",
186
- side,
187
- sideOffset,
188
- avoidCollisions: true,
189
- collisionPadding: 8,
190
- dir: "ltr",
191
- children: [
192
- content,
193
- /* @__PURE__ */ jsx(_Tooltip.Arrow, { className: "tlui-tooltip__arrow" })
194
- ]
195
- }
196
- )
197
- ]
198
- }
199
- );
144
+ const TldrawUiTooltip = forwardRef(
145
+ ({
146
+ children,
147
+ content,
148
+ side,
149
+ sideOffset = 5,
150
+ disabled = false,
151
+ showOnMobile = false,
152
+ delayDuration
153
+ }, ref) => {
154
+ const editor = useMaybeEditor();
155
+ const tooltipId = useRef(uniqueId());
156
+ const hasProvider = useContext(TooltipSingletonContext);
157
+ const orientationCtx = useTldrawUiOrientation();
158
+ const sideToUse = side ?? orientationCtx.tooltipSide;
159
+ useEffect(() => {
160
+ const currentTooltipId = tooltipId.current;
161
+ return () => {
162
+ if (hasProvider) {
163
+ tooltipManager.hideTooltip(editor, currentTooltipId, true);
164
+ }
165
+ };
166
+ }, [editor, hasProvider]);
167
+ if (disabled || !content) {
168
+ return /* @__PURE__ */ jsx(Fragment, { children });
169
+ }
170
+ const delayDurationToUse = delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS);
171
+ if (!hasProvider) {
172
+ return /* @__PURE__ */ jsxs(_Tooltip.Root, { delayDuration: delayDurationToUse, disableHoverableContent: true, children: [
173
+ /* @__PURE__ */ jsx(_Tooltip.Trigger, { asChild: true, ref, children }),
174
+ /* @__PURE__ */ jsxs(
175
+ _Tooltip.Content,
176
+ {
177
+ className: "tlui-tooltip",
178
+ side: sideToUse,
179
+ sideOffset,
180
+ avoidCollisions: true,
181
+ collisionPadding: 8,
182
+ dir: "ltr",
183
+ children: [
184
+ content,
185
+ /* @__PURE__ */ jsx(_Tooltip.Arrow, { className: "tlui-tooltip__arrow" })
186
+ ]
187
+ }
188
+ )
189
+ ] });
190
+ }
191
+ const child = React.Children.only(children);
192
+ assert(React.isValidElement(child), "TldrawUiTooltip children must be a single element");
193
+ const handleMouseEnter = (event) => {
194
+ child.props.onMouseEnter?.(event);
195
+ tooltipManager.showTooltip(
196
+ tooltipId.current,
197
+ content,
198
+ event.currentTarget,
199
+ sideToUse,
200
+ sideOffset,
201
+ showOnMobile,
202
+ delayDurationToUse
203
+ );
204
+ };
205
+ const handleMouseLeave = (event) => {
206
+ child.props.onMouseLeave?.(event);
207
+ tooltipManager.hideTooltip(editor, tooltipId.current);
208
+ };
209
+ const handleFocus = (event) => {
210
+ child.props.onFocus?.(event);
211
+ tooltipManager.showTooltip(
212
+ tooltipId.current,
213
+ content,
214
+ event.currentTarget,
215
+ sideToUse,
216
+ sideOffset,
217
+ showOnMobile,
218
+ delayDurationToUse
219
+ );
220
+ };
221
+ const handleBlur = (event) => {
222
+ child.props.onBlur?.(event);
223
+ tooltipManager.hideTooltip(editor, tooltipId.current);
224
+ };
225
+ const childrenWithHandlers = React.cloneElement(children, {
226
+ onMouseEnter: handleMouseEnter,
227
+ onMouseLeave: handleMouseLeave,
228
+ onFocus: handleFocus,
229
+ onBlur: handleBlur
230
+ });
231
+ return childrenWithHandlers;
200
232
  }
201
- const handleMouseEnter = (event) => {
202
- tooltipManager.showTooltip(
203
- tooltipId.current,
204
- content,
205
- event.currentTarget,
206
- side,
207
- sideOffset
208
- );
209
- };
210
- const handleMouseLeave = () => {
211
- tooltipManager.hideTooltip(tooltipId.current);
212
- };
213
- const handleFocus = (event) => {
214
- tooltipManager.showTooltip(
215
- tooltipId.current,
216
- content,
217
- event.currentTarget,
218
- side,
219
- sideOffset
220
- );
221
- };
222
- const handleBlur = () => {
223
- tooltipManager.hideTooltip(tooltipId.current);
224
- };
225
- const childrenWithHandlers = React.cloneElement(children, {
226
- onMouseEnter: handleMouseEnter,
227
- onMouseLeave: handleMouseLeave,
228
- onFocus: handleFocus,
229
- onBlur: handleBlur
230
- });
231
- return childrenWithHandlers;
232
- }
233
+ );
233
234
  export {
234
235
  TldrawUiTooltip,
235
- TldrawUiTooltipProvider
236
+ TldrawUiTooltipProvider,
237
+ tooltipManager
236
238
  };
237
239
  //# sourceMappingURL=TldrawUiTooltip.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/ui/components/primitives/TldrawUiTooltip.tsx"],
4
- "sourcesContent": ["import { Editor, uniqueId, useMaybeEditor, Vec } from '@tldraw/editor'\nimport { Tooltip as _Tooltip } from 'radix-ui'\nimport React, { createContext, useContext, useEffect, useRef, useState } from 'react'\nimport { usePrefersReducedMotion } from '../../../shapes/shared/usePrefersReducedMotion'\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) {\n\t\t// Only hide if this is the current tooltip\n\t\tif (this.currentTooltipId === tooltipId) {\n\t\t\t// Start destroy timeout (1 second)\n\t\t\tif (this.editor) {\n\t\t\t\tthis.destroyTimeoutId = this.editor.timers.setTimeout(() => {\n\t\t\t\t\tthis.currentTooltipId = null\n\t\t\t\t\tthis.currentContent = ''\n\t\t\t\t\tthis.activeElement = null\n\t\t\t\t\tthis.destroyTimeoutId = null\n\t\t\t\t\tthis.notify()\n\t\t\t\t}, 300)\n\t\t\t}\n\t\t}\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\nconst 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 function TldrawUiTooltip({\n\tchildren,\n\tcontent,\n\tside = 'bottom',\n\tsideOffset = 5,\n\tdisabled = false,\n}: TldrawUiTooltipProps) {\n\tconst editor = useMaybeEditor()\n\tconst tooltipId = useRef<string>(uniqueId())\n\tconst hasProvider = useContext(TooltipSingletonContext)\n\n\t// Don't show tooltip if disabled, no content, or UI labels are disabled\n\tif (disabled || !content) {\n\t\treturn <>{children}</>\n\t}\n\n\t// Fallback to old behavior if no provider\n\tif (!hasProvider) {\n\t\treturn (\n\t\t\t<_Tooltip.Root\n\t\t\t\tdelayDuration={editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS}\n\t\t\t\tdisableHoverableContent\n\t\t\t>\n\t\t\t\t<_Tooltip.Trigger asChild>{children}</_Tooltip.Trigger>\n\t\t\t\t<_Tooltip.Content\n\t\t\t\t\tclassName=\"tlui-tooltip\"\n\t\t\t\t\tside={side}\n\t\t\t\t\tsideOffset={sideOffset}\n\t\t\t\t\tavoidCollisions\n\t\t\t\t\tcollisionPadding={8}\n\t\t\t\t\tdir=\"ltr\"\n\t\t\t\t>\n\t\t\t\t\t{content}\n\t\t\t\t\t<_Tooltip.Arrow className=\"tlui-tooltip__arrow\" />\n\t\t\t\t</_Tooltip.Content>\n\t\t\t</_Tooltip.Root>\n\t\t)\n\t}\n\n\tconst handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {\n\t\ttooltipManager.showTooltip(\n\t\t\ttooltipId.current,\n\t\t\tcontent,\n\t\t\tevent.currentTarget as HTMLElement,\n\t\t\tside,\n\t\t\tsideOffset\n\t\t)\n\t}\n\n\tconst handleMouseLeave = () => {\n\t\ttooltipManager.hideTooltip(tooltipId.current)\n\t}\n\n\tconst handleFocus = (event: React.FocusEvent<HTMLElement>) => {\n\t\ttooltipManager.showTooltip(\n\t\t\ttooltipId.current,\n\t\t\tcontent,\n\t\t\tevent.currentTarget as HTMLElement,\n\t\t\tside,\n\t\t\tsideOffset\n\t\t)\n\t}\n\n\tconst handleBlur = () => {\n\t\ttooltipManager.hideTooltip(tooltipId.current)\n\t}\n\n\tconst childrenWithHandlers = React.cloneElement(children as React.ReactElement, {\n\t\tonMouseEnter: handleMouseEnter,\n\t\tonMouseLeave: handleMouseLeave,\n\t\tonFocus: handleFocus,\n\t\tonBlur: handleBlur,\n\t})\n\n\treturn childrenWithHandlers\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\n\tconst currentTooltip = useValue(\n\t\t'current tooltip',\n\t\t() => tooltipManager.getCurrentTooltipData(),\n\t\t[]\n\t)\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
  }
@@ -0,0 +1,46 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import classNames from "classnames";
3
+ import { Slot } from "radix-ui";
4
+ import { createContext, forwardRef, useContext } from "react";
5
+ const TldrawUiOrientationContext = createContext({
6
+ orientation: "horizontal",
7
+ tooltipSide: "bottom"
8
+ });
9
+ function TldrawUiOrientationProvider({
10
+ children,
11
+ orientation,
12
+ tooltipSide
13
+ }) {
14
+ const prevContext = useTldrawUiOrientation();
15
+ const tooltipSideToUse = tooltipSide ?? (orientation === prevContext.orientation ? prevContext.tooltipSide : orientation === "horizontal" ? "bottom" : "right");
16
+ return /* @__PURE__ */ jsx(TldrawUiOrientationContext.Provider, { value: { orientation, tooltipSide: tooltipSideToUse }, children });
17
+ }
18
+ function useTldrawUiOrientation() {
19
+ return useContext(TldrawUiOrientationContext);
20
+ }
21
+ const TldrawUiRow = forwardRef(
22
+ ({ asChild, className, tooltipSide, ...props }, ref) => {
23
+ const Component = asChild ? Slot.Root : "div";
24
+ return /* @__PURE__ */ jsx(TldrawUiOrientationProvider, { orientation: "horizontal", tooltipSide, children: /* @__PURE__ */ jsx(Component, { ref, className: classNames("tlui-row", className), ...props }) });
25
+ }
26
+ );
27
+ const TldrawUiColumn = forwardRef(
28
+ ({ asChild, className, tooltipSide, ...props }, ref) => {
29
+ const Component = asChild ? Slot.Root : "div";
30
+ return /* @__PURE__ */ jsx(TldrawUiOrientationProvider, { orientation: "vertical", tooltipSide, children: /* @__PURE__ */ jsx(Component, { ref, className: classNames("tlui-column", className), ...props }) });
31
+ }
32
+ );
33
+ const TldrawUiGrid = forwardRef(
34
+ ({ asChild, className, tooltipSide, ...props }, ref) => {
35
+ const Component = asChild ? Slot.Root : "div";
36
+ return /* @__PURE__ */ jsx(TldrawUiOrientationProvider, { orientation: "horizontal", tooltipSide, children: /* @__PURE__ */ jsx(Component, { ref, className: classNames("tlui-grid", className), ...props }) });
37
+ }
38
+ );
39
+ export {
40
+ TldrawUiColumn,
41
+ TldrawUiGrid,
42
+ TldrawUiOrientationProvider,
43
+ TldrawUiRow,
44
+ useTldrawUiOrientation
45
+ };
46
+ //# sourceMappingURL=layout.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/lib/ui/components/primitives/layout.tsx"],
4
+ "sourcesContent": ["import classNames from 'classnames'\nimport { Slot } from 'radix-ui'\nimport { HTMLAttributes, ReactNode, createContext, forwardRef, useContext } from 'react'\n\n/** @public */\nexport interface TldrawUiOrientationContext {\n\torientation: 'horizontal' | 'vertical'\n\ttooltipSide: 'top' | 'right' | 'bottom' | 'left'\n}\n\nconst TldrawUiOrientationContext = createContext<TldrawUiOrientationContext>({\n\torientation: 'horizontal',\n\ttooltipSide: 'bottom',\n})\n\n/** @public */\nexport interface TldrawUiOrientationProviderProps {\n\tchildren: ReactNode\n\torientation: 'horizontal' | 'vertical'\n\ttooltipSide?: 'top' | 'right' | 'bottom' | 'left'\n}\n/** @public @react */\nexport function TldrawUiOrientationProvider({\n\tchildren,\n\torientation,\n\ttooltipSide,\n}: TldrawUiOrientationProviderProps) {\n\tconst prevContext = useTldrawUiOrientation()\n\t// generally, we want tooltip side to cascade down through the layout - apart from when the\n\t// orientation changes. If the tooltip side is \"bottom\", and then I include some vertical layout\n\t// elements, keeping the tooltip side as bottom will cause the tooltip to overlap elements\n\t// stacked on top of each other. In the absence of a tooltip side, we pick a default side based\n\t// on the orientation whenever the orientation changes.\n\tconst tooltipSideToUse =\n\t\ttooltipSide ??\n\t\t(orientation === prevContext.orientation\n\t\t\t? prevContext.tooltipSide\n\t\t\t: orientation === 'horizontal'\n\t\t\t\t? 'bottom'\n\t\t\t\t: 'right')\n\n\treturn (\n\t\t<TldrawUiOrientationContext.Provider value={{ orientation, tooltipSide: tooltipSideToUse }}>\n\t\t\t{children}\n\t\t</TldrawUiOrientationContext.Provider>\n\t)\n}\n\n/** @public */\nexport function useTldrawUiOrientation() {\n\treturn useContext(TldrawUiOrientationContext)\n}\n\n/** @public */\nexport interface TLUiLayoutProps extends HTMLAttributes<HTMLDivElement> {\n\tchildren: ReactNode\n\ttooltipSide?: 'top' | 'right' | 'bottom' | 'left'\n\tasChild?: boolean\n}\n\n/**\n * A row, usually of UI controls like buttons, select dropdown, checkboxes, etc.\n *\n * @public @react\n */\nexport const TldrawUiRow = forwardRef<HTMLDivElement, TLUiLayoutProps>(\n\t({ asChild, className, tooltipSide, ...props }, ref) => {\n\t\tconst Component = asChild ? Slot.Root : 'div'\n\t\treturn (\n\t\t\t<TldrawUiOrientationProvider orientation=\"horizontal\" tooltipSide={tooltipSide}>\n\t\t\t\t<Component ref={ref} className={classNames('tlui-row', className)} {...props} />\n\t\t\t</TldrawUiOrientationProvider>\n\t\t)\n\t}\n)\n\n/**\n * A column, usually of UI controls like buttons, select dropdown, checkboxes, etc.\n *\n * @public @react\n */\nexport const TldrawUiColumn = forwardRef<HTMLDivElement, TLUiLayoutProps>(\n\t({ asChild, className, tooltipSide, ...props }, ref) => {\n\t\tconst Component = asChild ? Slot.Root : 'div'\n\t\treturn (\n\t\t\t<TldrawUiOrientationProvider orientation=\"vertical\" tooltipSide={tooltipSide}>\n\t\t\t\t<Component ref={ref} className={classNames('tlui-column', className)} {...props} />\n\t\t\t</TldrawUiOrientationProvider>\n\t\t)\n\t}\n)\n\n/**\n * A tight grid 4 elements wide, usually of UI controls like buttons, select dropdown, checkboxes,\n * etc.\n *\n * @public @react */\nexport const TldrawUiGrid = forwardRef<HTMLDivElement, TLUiLayoutProps>(\n\t({ asChild, className, tooltipSide, ...props }, ref) => {\n\t\tconst Component = asChild ? Slot.Root : 'div'\n\t\treturn (\n\t\t\t<TldrawUiOrientationProvider orientation=\"horizontal\" tooltipSide={tooltipSide}>\n\t\t\t\t<Component ref={ref} className={classNames('tlui-grid', className)} {...props} />\n\t\t\t</TldrawUiOrientationProvider>\n\t\t)\n\t}\n)\n"],
5
+ "mappings": "AA0CE;AA1CF,OAAO,gBAAgB;AACvB,SAAS,YAAY;AACrB,SAAoC,eAAe,YAAY,kBAAkB;AAQjF,MAAM,6BAA6B,cAA0C;AAAA,EAC5E,aAAa;AAAA,EACb,aAAa;AACd,CAAC;AASM,SAAS,4BAA4B;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AACD,GAAqC;AACpC,QAAM,cAAc,uBAAuB;AAM3C,QAAM,mBACL,gBACC,gBAAgB,YAAY,cAC1B,YAAY,cACZ,gBAAgB,eACf,WACA;AAEL,SACC,oBAAC,2BAA2B,UAA3B,EAAoC,OAAO,EAAE,aAAa,aAAa,iBAAiB,GACvF,UACF;AAEF;AAGO,SAAS,yBAAyB;AACxC,SAAO,WAAW,0BAA0B;AAC7C;AAcO,MAAM,cAAc;AAAA,EAC1B,CAAC,EAAE,SAAS,WAAW,aAAa,GAAG,MAAM,GAAG,QAAQ;AACvD,UAAM,YAAY,UAAU,KAAK,OAAO;AACxC,WACC,oBAAC,+BAA4B,aAAY,cAAa,aACrD,8BAAC,aAAU,KAAU,WAAW,WAAW,YAAY,SAAS,GAAI,GAAG,OAAO,GAC/E;AAAA,EAEF;AACD;AAOO,MAAM,iBAAiB;AAAA,EAC7B,CAAC,EAAE,SAAS,WAAW,aAAa,GAAG,MAAM,GAAG,QAAQ;AACvD,UAAM,YAAY,UAAU,KAAK,OAAO;AACxC,WACC,oBAAC,+BAA4B,aAAY,YAAW,aACnD,8BAAC,aAAU,KAAU,WAAW,WAAW,eAAe,SAAS,GAAI,GAAG,OAAO,GAClF;AAAA,EAEF;AACD;AAOO,MAAM,eAAe;AAAA,EAC3B,CAAC,EAAE,SAAS,WAAW,aAAa,GAAG,MAAM,GAAG,QAAQ;AACvD,UAAM,YAAY,UAAU,KAAK,OAAO;AACxC,WACC,oBAAC,+BAA4B,aAAY,cAAa,aACrD,8BAAC,aAAU,KAAU,WAAW,WAAW,aAAa,SAAS,GAAI,GAAG,OAAO,GAChF;AAAA,EAEF;AACD;",
6
+ "names": []
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
  }
@@ -2,44 +2,57 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import classNames from "classnames";
3
3
  import { unwrapLabel } from "../../../context/actions.mjs";
4
4
  import { useTranslation } from "../../../hooks/useTranslation/useTranslation.mjs";
5
+ import { TldrawUiColumn, TldrawUiGrid, TldrawUiRow, useTldrawUiOrientation } from "../layout.mjs";
5
6
  import { TldrawUiDropdownMenuGroup } from "../TldrawUiDropdownMenu.mjs";
6
7
  import { useTldrawUiMenuContext } from "./TldrawUiMenuContext.mjs";
7
8
  function TldrawUiMenuGroup({ id, label, className, children }) {
8
- const { type: menuType, sourceId } = useTldrawUiMenuContext();
9
+ const menu = useTldrawUiMenuContext();
10
+ const { orientation } = useTldrawUiOrientation();
9
11
  const msg = useTranslation();
10
- const labelToUse = unwrapLabel(label, menuType);
12
+ const labelToUse = unwrapLabel(label, menu.type);
11
13
  const labelStr = labelToUse ? msg(labelToUse) : void 0;
12
- switch (menuType) {
13
- case "panel": {
14
+ switch (menu.type) {
15
+ case "menu": {
14
16
  return /* @__PURE__ */ jsx(
15
- "div",
17
+ TldrawUiDropdownMenuGroup,
16
18
  {
17
- className: classNames("tlui-menu__group", className),
18
- "data-testid": `${sourceId}-group.${id}`,
19
+ className,
20
+ "data-testid": `${menu.sourceId}-group.${id}`,
19
21
  children
20
22
  }
21
23
  );
22
24
  }
23
- case "menu": {
24
- return /* @__PURE__ */ jsx(TldrawUiDropdownMenuGroup, { className, "data-testid": `${sourceId}-group.${id}`, children });
25
- }
26
25
  case "context-menu": {
27
26
  return /* @__PURE__ */ jsx(
28
27
  "div",
29
28
  {
30
29
  dir: "ltr",
31
30
  className: classNames("tlui-menu__group", className),
32
- "data-testid": `${sourceId}-group.${id}`,
31
+ "data-testid": `${menu.sourceId}-group.${id}`,
33
32
  children
34
33
  }
35
34
  );
36
35
  }
37
36
  case "keyboard-shortcuts": {
38
- return /* @__PURE__ */ jsxs("div", { className: "tlui-shortcuts-dialog__group", "data-testid": `${sourceId}-group.${id}`, children: [
37
+ return /* @__PURE__ */ jsxs("div", { className: "tlui-shortcuts-dialog__group", "data-testid": `${menu.sourceId}-group.${id}`, children: [
39
38
  /* @__PURE__ */ jsx("h2", { className: "tlui-shortcuts-dialog__group__title", children: labelStr }),
40
39
  /* @__PURE__ */ jsx("div", { className: "tlui-shortcuts-dialog__group__content", children })
41
40
  ] });
42
41
  }
42
+ case "toolbar": {
43
+ const Layout = orientation === "horizontal" ? TldrawUiRow : TldrawUiColumn;
44
+ return /* @__PURE__ */ jsx(Layout, { className: "tlui-main-toolbar__group", "data-testid": `${menu.sourceId}-group.${id}`, children });
45
+ }
46
+ case "toolbar-overflow": {
47
+ return /* @__PURE__ */ jsx(
48
+ TldrawUiGrid,
49
+ {
50
+ className: "tlui-main-toolbar__group",
51
+ "data-testid": `${menu.sourceId}-group.${id}`,
52
+ children
53
+ }
54
+ );
55
+ }
43
56
  default: {
44
57
  return children;
45
58
  }