tldraw 3.16.0-canary.f60032f16651 → 3.16.0-canary.ffc5da6dc09f

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 (460) hide show
  1. package/dist-cjs/index.d.ts +322 -105
  2. package/dist-cjs/index.js +45 -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/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/arrowLabel.js +6 -0
  13. package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +3 -3
  14. package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js +3 -3
  15. package/dist-cjs/lib/shapes/arrow/elbow/ElbowArrowDebug.js.map +1 -1
  16. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js +3 -3
  17. package/dist-cjs/lib/shapes/draw/DrawShapeUtil.js.map +2 -2
  18. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js +1 -1
  19. package/dist-cjs/lib/shapes/embed/EmbedShapeUtil.js.map +1 -1
  20. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +18 -12
  21. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  22. package/dist-cjs/lib/shapes/frame/components/FrameHeading.js +1 -1
  23. package/dist-cjs/lib/shapes/frame/components/FrameHeading.js.map +2 -2
  24. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +2 -2
  25. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  26. package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js +2 -1
  27. package/dist-cjs/lib/shapes/geo/components/GeoShapeBody.js.map +2 -2
  28. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js +5 -1
  29. package/dist-cjs/lib/shapes/highlight/HighlightShapeUtil.js.map +2 -2
  30. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +6 -3
  31. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
  32. package/dist-cjs/lib/shapes/line/LineShapeUtil.js +5 -1
  33. package/dist-cjs/lib/shapes/line/LineShapeUtil.js.map +2 -2
  34. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +4 -4
  35. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  36. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -3
  37. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  38. package/dist-cjs/lib/shapes/shared/ShapeFill.js +4 -4
  39. package/dist-cjs/lib/shapes/shared/ShapeFill.js.map +2 -2
  40. package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
  41. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +0 -2
  42. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  43. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +0 -2
  44. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
  45. package/dist-cjs/lib/shapes/shared/usePrefersReducedMotion.js +10 -1
  46. package/dist-cjs/lib/shapes/shared/usePrefersReducedMotion.js.map +2 -2
  47. package/dist-cjs/lib/shapes/text/TextShapeUtil.js +2 -2
  48. package/dist-cjs/lib/shapes/text/TextShapeUtil.js.map +2 -2
  49. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js +3 -3
  50. package/dist-cjs/lib/shapes/video/VideoShapeUtil.js.map +1 -1
  51. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +25 -1
  52. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  53. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +12 -0
  54. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  55. package/dist-cjs/lib/ui/TldrawUi.js +27 -12
  56. package/dist-cjs/lib/ui/TldrawUi.js.map +3 -3
  57. package/dist-cjs/lib/ui/assetUrls.js +13 -10
  58. package/dist-cjs/lib/ui/assetUrls.js.map +2 -2
  59. package/dist-cjs/lib/ui/components/AccessibilityMenu.js +35 -0
  60. package/dist-cjs/lib/ui/components/AccessibilityMenu.js.map +7 -0
  61. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js +12 -3
  62. package/dist-cjs/lib/ui/components/ActionsMenu/DefaultActionsMenu.js.map +2 -2
  63. package/dist-cjs/lib/ui/components/{FollowingIndicator.js → DefaultFollowingIndicator.js} +6 -6
  64. package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +7 -0
  65. package/dist-cjs/lib/ui/components/DefaultMenuPanel.js +3 -2
  66. package/dist-cjs/lib/ui/components/DefaultMenuPanel.js.map +2 -2
  67. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +6 -6
  68. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
  69. package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js +3 -3
  70. package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js.map +2 -2
  71. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js +4 -4
  72. package/dist-cjs/lib/ui/components/Minimap/MinimapManager.js.map +2 -2
  73. package/dist-cjs/lib/ui/components/MobileStylePanel.js +5 -3
  74. package/dist-cjs/lib/ui/components/MobileStylePanel.js.map +2 -2
  75. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js +1 -1
  76. package/dist-cjs/lib/ui/components/NavigationPanel/DefaultNavigationPanel.js.map +2 -2
  77. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +2 -1
  78. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
  79. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js +3 -2
  80. package/dist-cjs/lib/ui/components/SharePanel/PeopleMenuItem.js.map +2 -2
  81. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js +2 -2
  82. package/dist-cjs/lib/ui/components/SharePanel/UserPresenceColorPicker.js.map +2 -2
  83. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +11 -4
  84. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
  85. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +249 -279
  86. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  87. package/dist-cjs/lib/ui/components/{primitives/TldrawUiButtonPicker.js → StylePanel/StylePanelButtonPicker.js} +52 -56
  88. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +7 -0
  89. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js +68 -0
  90. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js.map +7 -0
  91. package/dist-cjs/lib/ui/components/StylePanel/{DoubleDropdownPicker.js → StylePanelDoubleDropdownPicker.js} +26 -25
  92. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +7 -0
  93. package/dist-cjs/lib/ui/components/StylePanel/{DropdownPicker.js → StylePanelDropdownPicker.js} +47 -43
  94. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +7 -0
  95. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js +28 -0
  96. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js.map +7 -0
  97. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +3 -2
  98. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  99. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +39 -10
  100. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  101. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js +66 -21
  102. package/dist-cjs/lib/ui/components/Toolbar/DefaultToolbar.js.map +3 -3
  103. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js +15 -3
  104. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js.map +2 -2
  105. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +3 -3
  106. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
  107. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +189 -80
  108. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +3 -3
  109. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +5 -4
  110. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
  111. package/dist-cjs/lib/ui/components/menu-items.js +6 -0
  112. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  113. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +10 -1
  114. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  115. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js +3 -2
  116. package/dist-cjs/lib/ui/components/primitives/TldrawUiPopover.js.map +3 -3
  117. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +17 -4
  118. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  119. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +32 -7
  120. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  121. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +269 -0
  122. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +7 -0
  123. package/dist-cjs/lib/ui/components/primitives/layout.js +76 -0
  124. package/dist-cjs/lib/ui/components/primitives/layout.js.map +7 -0
  125. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuContext.js.map +2 -2
  126. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js +25 -12
  127. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuGroup.js.map +2 -2
  128. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +12 -26
  129. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  130. package/dist-cjs/lib/ui/context/TldrawUiContextProvider.js +3 -2
  131. package/dist-cjs/lib/ui/context/TldrawUiContextProvider.js.map +2 -2
  132. package/dist-cjs/lib/ui/context/actions.js +38 -10
  133. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  134. package/dist-cjs/lib/ui/context/components.js +2 -0
  135. package/dist-cjs/lib/ui/context/components.js.map +2 -2
  136. package/dist-cjs/lib/ui/context/events.js.map +2 -2
  137. package/dist-cjs/lib/ui/hooks/useExportAs.js +3 -2
  138. package/dist-cjs/lib/ui/hooks/useExportAs.js.map +2 -2
  139. package/dist-cjs/lib/ui/hooks/useTools.js +22 -4
  140. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  141. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  142. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +5 -0
  143. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  144. package/dist-cjs/lib/ui/kbd-utils.js +9 -3
  145. package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
  146. package/dist-cjs/lib/ui/version.js +3 -3
  147. package/dist-cjs/lib/ui/version.js.map +1 -1
  148. package/dist-cjs/lib/utils/export/copyAs.js +1 -2
  149. package/dist-cjs/lib/utils/export/copyAs.js.map +2 -2
  150. package/dist-cjs/lib/utils/export/export.js +0 -20
  151. package/dist-cjs/lib/utils/export/export.js.map +2 -2
  152. package/dist-cjs/lib/utils/export/exportAs.js +1 -2
  153. package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
  154. package/dist-esm/index.d.mts +322 -105
  155. package/dist-esm/index.mjs +83 -29
  156. package/dist-esm/index.mjs.map +2 -2
  157. package/dist-esm/lib/Tldraw.mjs +14 -4
  158. package/dist-esm/lib/Tldraw.mjs.map +2 -2
  159. package/dist-esm/lib/canvas/TldrawScribble.mjs +1 -1
  160. package/dist-esm/lib/canvas/TldrawScribble.mjs.map +2 -2
  161. package/dist-esm/lib/defaultExternalContentHandlers.mjs +5 -4
  162. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  163. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs +4 -3
  164. package/dist-esm/lib/shapes/arrow/ArrowShapeUtil.mjs.map +2 -2
  165. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +6 -0
  166. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +3 -3
  167. package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs +3 -3
  168. package/dist-esm/lib/shapes/arrow/elbow/ElbowArrowDebug.mjs.map +1 -1
  169. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs +4 -3
  170. package/dist-esm/lib/shapes/draw/DrawShapeUtil.mjs.map +2 -2
  171. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs +1 -1
  172. package/dist-esm/lib/shapes/embed/EmbedShapeUtil.mjs.map +1 -1
  173. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +19 -12
  174. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  175. package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs +1 -1
  176. package/dist-esm/lib/shapes/frame/components/FrameHeading.mjs.map +2 -2
  177. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +3 -2
  178. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  179. package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs +2 -1
  180. package/dist-esm/lib/shapes/geo/components/GeoShapeBody.mjs.map +2 -2
  181. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs +6 -1
  182. package/dist-esm/lib/shapes/highlight/HighlightShapeUtil.mjs.map +2 -2
  183. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +6 -3
  184. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
  185. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs +6 -1
  186. package/dist-esm/lib/shapes/line/LineShapeUtil.mjs.map +2 -2
  187. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +5 -4
  188. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  189. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -3
  190. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  191. package/dist-esm/lib/shapes/shared/ShapeFill.mjs +5 -4
  192. package/dist-esm/lib/shapes/shared/ShapeFill.mjs.map +2 -2
  193. package/dist-esm/lib/shapes/shared/freehand/svg.mjs.map +2 -2
  194. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +0 -2
  195. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  196. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +0 -2
  197. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  198. package/dist-esm/lib/shapes/shared/usePrefersReducedMotion.mjs +10 -1
  199. package/dist-esm/lib/shapes/shared/usePrefersReducedMotion.mjs.map +2 -2
  200. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs +3 -2
  201. package/dist-esm/lib/shapes/text/TextShapeUtil.mjs.map +2 -2
  202. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs +3 -3
  203. package/dist-esm/lib/shapes/video/VideoShapeUtil.mjs.map +1 -1
  204. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +26 -1
  205. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  206. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +13 -0
  207. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  208. package/dist-esm/lib/ui/TldrawUi.mjs +29 -14
  209. package/dist-esm/lib/ui/TldrawUi.mjs.map +3 -3
  210. package/dist-esm/lib/ui/assetUrls.mjs +13 -10
  211. package/dist-esm/lib/ui/assetUrls.mjs.map +2 -2
  212. package/dist-esm/lib/ui/components/AccessibilityMenu.mjs +19 -0
  213. package/dist-esm/lib/ui/components/AccessibilityMenu.mjs.map +7 -0
  214. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs +12 -3
  215. package/dist-esm/lib/ui/components/ActionsMenu/DefaultActionsMenu.mjs.map +2 -2
  216. package/dist-esm/lib/ui/components/{FollowingIndicator.mjs → DefaultFollowingIndicator.mjs} +3 -3
  217. package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +7 -0
  218. package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs +3 -2
  219. package/dist-esm/lib/ui/components/DefaultMenuPanel.mjs.map +2 -2
  220. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +6 -6
  221. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
  222. package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs +3 -5
  223. package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs.map +2 -2
  224. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs +4 -4
  225. package/dist-esm/lib/ui/components/Minimap/MinimapManager.mjs.map +2 -2
  226. package/dist-esm/lib/ui/components/MobileStylePanel.mjs +6 -3
  227. package/dist-esm/lib/ui/components/MobileStylePanel.mjs.map +2 -2
  228. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs +1 -1
  229. package/dist-esm/lib/ui/components/NavigationPanel/DefaultNavigationPanel.mjs.map +2 -2
  230. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +2 -1
  231. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
  232. package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs +3 -2
  233. package/dist-esm/lib/ui/components/SharePanel/PeopleMenuItem.mjs.map +2 -2
  234. package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs +2 -2
  235. package/dist-esm/lib/ui/components/SharePanel/UserPresenceColorPicker.mjs.map +2 -2
  236. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +16 -5
  237. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
  238. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +251 -283
  239. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  240. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +126 -0
  241. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +7 -0
  242. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +48 -0
  243. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +7 -0
  244. package/dist-esm/lib/ui/components/StylePanel/{DoubleDropdownPicker.mjs → StylePanelDoubleDropdownPicker.mjs} +23 -22
  245. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +7 -0
  246. package/dist-esm/lib/ui/components/StylePanel/{DropdownPicker.mjs → StylePanelDropdownPicker.mjs} +44 -40
  247. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +7 -0
  248. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs +8 -0
  249. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs.map +7 -0
  250. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +3 -2
  251. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  252. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +39 -10
  253. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  254. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs +56 -21
  255. package/dist-esm/lib/ui/components/Toolbar/DefaultToolbar.mjs.map +2 -2
  256. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs +15 -3
  257. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs.map +2 -2
  258. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +3 -3
  259. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
  260. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +192 -81
  261. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +3 -3
  262. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +5 -4
  263. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
  264. package/dist-esm/lib/ui/components/menu-items.mjs +6 -0
  265. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  266. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +10 -1
  267. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  268. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs +3 -2
  269. package/dist-esm/lib/ui/components/primitives/TldrawUiPopover.mjs.map +2 -2
  270. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +17 -4
  271. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  272. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +32 -7
  273. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  274. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +246 -0
  275. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +7 -0
  276. package/dist-esm/lib/ui/components/primitives/layout.mjs +46 -0
  277. package/dist-esm/lib/ui/components/primitives/layout.mjs.map +7 -0
  278. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuContext.mjs.map +2 -2
  279. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs +25 -12
  280. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuGroup.mjs.map +2 -2
  281. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +12 -26
  282. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  283. package/dist-esm/lib/ui/context/TldrawUiContextProvider.mjs +3 -2
  284. package/dist-esm/lib/ui/context/TldrawUiContextProvider.mjs.map +2 -2
  285. package/dist-esm/lib/ui/context/actions.mjs +38 -10
  286. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  287. package/dist-esm/lib/ui/context/components.mjs +2 -0
  288. package/dist-esm/lib/ui/context/components.mjs.map +2 -2
  289. package/dist-esm/lib/ui/context/events.mjs.map +2 -2
  290. package/dist-esm/lib/ui/hooks/useExportAs.mjs +3 -2
  291. package/dist-esm/lib/ui/hooks/useExportAs.mjs.map +2 -2
  292. package/dist-esm/lib/ui/hooks/useTools.mjs +23 -4
  293. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  294. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +5 -0
  295. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  296. package/dist-esm/lib/ui/kbd-utils.mjs +9 -3
  297. package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
  298. package/dist-esm/lib/ui/version.mjs +3 -3
  299. package/dist-esm/lib/ui/version.mjs.map +1 -1
  300. package/dist-esm/lib/utils/export/copyAs.mjs +1 -2
  301. package/dist-esm/lib/utils/export/copyAs.mjs.map +2 -2
  302. package/dist-esm/lib/utils/export/export.mjs +0 -20
  303. package/dist-esm/lib/utils/export/export.mjs.map +2 -2
  304. package/dist-esm/lib/utils/export/exportAs.mjs +1 -2
  305. package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
  306. package/package.json +11 -34
  307. package/src/index.ts +62 -22
  308. package/src/lib/Tldraw.tsx +15 -2
  309. package/src/lib/canvas/TldrawScribble.tsx +1 -1
  310. package/src/lib/defaultExternalContentHandlers.ts +12 -4
  311. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +2 -1
  312. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +4 -3
  313. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +7 -6
  314. package/src/lib/shapes/arrow/ArrowShapeUtil.tsx +4 -3
  315. package/src/lib/shapes/arrow/arrowLabel.ts +8 -0
  316. package/src/lib/shapes/arrow/elbow/ElbowArrowDebug.tsx +3 -3
  317. package/src/lib/shapes/draw/DrawShapeTool.test.ts +0 -5
  318. package/src/lib/shapes/draw/DrawShapeUtil.tsx +4 -3
  319. package/src/lib/shapes/embed/EmbedShapeUtil.tsx +1 -1
  320. package/src/lib/shapes/frame/FrameShapeUtil.tsx +29 -14
  321. package/src/lib/shapes/frame/components/FrameHeading.tsx +1 -1
  322. package/src/lib/shapes/geo/GeoShapeUtil.tsx +3 -2
  323. package/src/lib/shapes/geo/components/GeoShapeBody.tsx +2 -2
  324. package/src/lib/shapes/highlight/HighlightShapeUtil.tsx +7 -1
  325. package/src/lib/shapes/image/ImageShapeUtil.tsx +6 -3
  326. package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -3
  327. package/src/lib/shapes/line/LineShapeUtil.tsx +6 -1
  328. package/src/lib/shapes/line/__snapshots__/LineShapeUtil.test.tsx.snap +2 -2
  329. package/src/lib/shapes/note/NoteShapeUtil.tsx +9 -4
  330. package/src/lib/shapes/shared/PlainTextLabel.tsx +0 -6
  331. package/src/lib/shapes/shared/ShapeFill.tsx +5 -4
  332. package/src/lib/shapes/shared/freehand/svg.ts +2 -0
  333. package/src/lib/shapes/shared/useEditablePlainText.ts +0 -6
  334. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +0 -7
  335. package/src/lib/shapes/shared/usePrefersReducedMotion.tsx +11 -1
  336. package/src/lib/shapes/text/TextShapeTool.test.ts +6 -5
  337. package/src/lib/shapes/text/TextShapeUtil.tsx +3 -2
  338. package/src/lib/shapes/video/VideoShapeUtil.tsx +3 -3
  339. package/src/lib/tools/EraserTool/childStates/Erasing.ts +34 -1
  340. package/src/lib/tools/EraserTool/childStates/Pointing.ts +20 -0
  341. package/src/lib/ui/TldrawUi.tsx +33 -12
  342. package/src/lib/ui/assetUrls.ts +13 -10
  343. package/src/lib/ui/components/AccessibilityMenu.tsx +20 -0
  344. package/src/lib/ui/components/ActionsMenu/DefaultActionsMenu.tsx +15 -3
  345. package/src/lib/ui/components/{FollowingIndicator.tsx → DefaultFollowingIndicator.tsx} +2 -1
  346. package/src/lib/ui/components/DefaultMenuPanel.tsx +4 -3
  347. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +6 -6
  348. package/src/lib/ui/components/MainMenu/DefaultMainMenuContent.tsx +4 -4
  349. package/src/lib/ui/components/Minimap/MinimapManager.ts +4 -4
  350. package/src/lib/ui/components/MobileStylePanel.tsx +9 -6
  351. package/src/lib/ui/components/NavigationPanel/DefaultNavigationPanel.tsx +1 -1
  352. package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +3 -2
  353. package/src/lib/ui/components/SharePanel/PeopleMenuItem.tsx +4 -3
  354. package/src/lib/ui/components/SharePanel/UserPresenceColorPicker.tsx +3 -3
  355. package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +28 -12
  356. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +261 -343
  357. package/src/lib/ui/components/{primitives/TldrawUiButtonPicker.tsx → StylePanel/StylePanelButtonPicker.tsx} +66 -50
  358. package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +63 -0
  359. package/src/lib/ui/components/StylePanel/{DoubleDropdownPicker.tsx → StylePanelDoubleDropdownPicker.tsx} +31 -22
  360. package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +119 -0
  361. package/src/lib/ui/components/StylePanel/StylePanelSubheading.tsx +9 -0
  362. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +4 -3
  363. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +33 -16
  364. package/src/lib/ui/components/Toolbar/DefaultToolbar.tsx +55 -23
  365. package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
  366. package/src/lib/ui/components/Toolbar/LinkEditor.tsx +5 -5
  367. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +212 -61
  368. package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +14 -11
  369. package/src/lib/ui/components/menu-items.tsx +8 -0
  370. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +6 -1
  371. package/src/lib/ui/components/primitives/TldrawUiPopover.tsx +4 -2
  372. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +50 -30
  373. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +54 -12
  374. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +335 -0
  375. package/src/lib/ui/components/primitives/layout.tsx +107 -0
  376. package/src/lib/ui/components/primitives/menus/TldrawUiMenuContext.tsx +0 -1
  377. package/src/lib/ui/components/primitives/menus/TldrawUiMenuGroup.tsx +29 -16
  378. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +18 -27
  379. package/src/lib/ui/context/TldrawUiContextProvider.tsx +23 -20
  380. package/src/lib/ui/context/actions.tsx +38 -10
  381. package/src/lib/ui/context/components.tsx +3 -0
  382. package/src/lib/ui/context/events.tsx +2 -1
  383. package/src/lib/ui/hooks/useExportAs.ts +3 -2
  384. package/src/lib/ui/hooks/useTools.tsx +26 -4
  385. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +5 -0
  386. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +5 -0
  387. package/src/lib/ui/kbd-utils.ts +10 -3
  388. package/src/lib/ui/version.ts +3 -3
  389. package/src/lib/ui.css +424 -293
  390. package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +5 -5
  391. package/src/lib/utils/export/copyAs.ts +1 -24
  392. package/src/lib/utils/export/export.ts +0 -36
  393. package/src/lib/utils/export/exportAs.ts +1 -32
  394. package/src/lib/utils/tldr/__snapshots__/buildFromV1Document.test.ts.snap +4 -4
  395. package/src/test/A11y.test.tsx +3 -2
  396. package/src/test/ClickManager.test.ts +7 -6
  397. package/src/test/Editor.test.tsx +20 -19
  398. package/src/test/EraserTool.test.ts +184 -13
  399. package/src/test/HandTool.test.ts +10 -9
  400. package/src/test/HighlightShape.test.ts +2 -1
  401. package/src/test/SelectTool.test.ts +3 -2
  402. package/src/test/TLUserPreferences.test.ts +4 -3
  403. package/src/test/TestEditor.ts +13 -15
  404. package/src/test/TldrawEditor.test.tsx +11 -10
  405. package/src/test/ZoomTool.test.ts +7 -6
  406. package/src/test/__snapshots__/drawing.test.ts.snap +2 -2
  407. package/src/test/__snapshots__/groups.test.tsx.snap +6 -6
  408. package/src/test/__snapshots__/resizing.test.ts.snap +2 -2
  409. package/src/test/arrows-megabus.test.tsx +5 -4
  410. package/src/test/bindings.test.tsx +24 -37
  411. package/src/test/bookmark-shapes.test.ts +1 -8
  412. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +23 -7
  413. package/src/test/commands/__snapshots__/packShapes.test.ts.snap +8 -8
  414. package/src/test/commands/__snapshots__/zoomToFit.test.ts.snap +2 -2
  415. package/src/test/commands/alignShapes.test.tsx +25 -24
  416. package/src/test/commands/animationSpeed.test.ts +2 -1
  417. package/src/test/commands/centerOnPoint.test.ts +3 -2
  418. package/src/test/commands/clipboard.test.ts +3 -2
  419. package/src/test/commands/createShapes.test.ts +2 -1
  420. package/src/test/commands/deleteShapes.test.ts +2 -1
  421. package/src/test/commands/distributeShapes.test.tsx +11 -10
  422. package/src/test/commands/getSvgString.test.ts +2 -1
  423. package/src/test/commands/packShapes.test.ts +5 -4
  424. package/src/test/commands/resizeShape.test.ts +2 -1
  425. package/src/test/commands/rotateShapes.test.ts +7 -6
  426. package/src/test/commands/setCamera.test.ts +4 -3
  427. package/src/test/commands/setCurrentPage.test.ts +3 -2
  428. package/src/test/commands/stackShapes.test.ts +11 -10
  429. package/src/test/commands/stretch.test.tsx +13 -12
  430. package/src/test/createDeepLink.test.tsx +2 -1
  431. package/src/test/cropping.test.ts +3 -2
  432. package/src/test/custom-clipping.test.ts +436 -0
  433. package/src/test/drawing.test.ts +2 -1
  434. package/src/test/flipShapes.test.ts +4 -3
  435. package/src/test/frames.test.ts +25 -24
  436. package/src/test/getCulledShapes.test.tsx +3 -2
  437. package/src/test/groups.test.tsx +1 -1
  438. package/src/test/handleDeepLink.test.tsx +2 -1
  439. package/src/test/maxShapes.test.ts +3 -2
  440. package/src/test/modifiers.test.ts +5 -4
  441. package/src/test/navigation.test.ts +12 -11
  442. package/src/test/panning.test.ts +2 -1
  443. package/src/test/perf/perf.test.ts +2 -1
  444. package/src/test/registerDeepLinkListener.test.tsx +10 -9
  445. package/src/test/resizing.test.ts +39 -38
  446. package/src/test/select.test.tsx +4 -3
  447. package/src/test/selection-omnibus.test.ts +11 -10
  448. package/src/test/shapeutils.test.ts +4 -3
  449. package/src/test/translating.test.ts +9 -8
  450. package/tldraw.css +732 -583
  451. package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
  452. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +0 -7
  453. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +0 -7
  454. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +0 -7
  455. package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
  456. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +0 -7
  457. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +0 -7
  458. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +0 -115
  459. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +0 -7
  460. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +0 -109
@@ -1,4 +1,5 @@
1
1
  import { useEditor, usePassThroughWheelEvents, useValue } from '@tldraw/editor'
2
+ import classNames from 'classnames'
2
3
  import { ReactNode, memo, useRef } from 'react'
3
4
  import { PORTRAIT_BREAKPOINT } from '../../constants'
4
5
  import { useBreakpoint } from '../../context/breakpoints'
@@ -6,6 +7,7 @@ import { useTldrawUiComponents } from '../../context/components'
6
7
  import { useReadonly } from '../../hooks/useReadonly'
7
8
  import { useTranslation } from '../../hooks/useTranslation/useTranslation'
8
9
  import { MobileStylePanel } from '../MobileStylePanel'
10
+ import { TldrawUiOrientationProvider } from '../primitives/layout'
9
11
  import { TldrawUiToolbar } from '../primitives/TldrawUiToolbar'
10
12
  import { DefaultToolbarContent } from './DefaultToolbarContent'
11
13
  import { OverflowingToolbar } from './OverflowingToolbar'
@@ -14,6 +16,11 @@ import { ToggleToolLockedButton } from './ToggleToolLockedButton'
14
16
  /** @public */
15
17
  export interface DefaultToolbarProps {
16
18
  children?: ReactNode
19
+ orientation?: 'horizontal' | 'vertical'
20
+ minItems?: number
21
+ minSizePx?: number
22
+ maxItems?: number
23
+ maxSizePx?: number
17
24
  }
18
25
 
19
26
  /**
@@ -24,7 +31,14 @@ export interface DefaultToolbarProps {
24
31
  * @public
25
32
  * @react
26
33
  */
27
- export const DefaultToolbar = memo(function DefaultToolbar({ children }: DefaultToolbarProps) {
34
+ export const DefaultToolbar = memo(function DefaultToolbar({
35
+ children,
36
+ orientation = 'horizontal',
37
+ minItems = 4,
38
+ minSizePx = 310,
39
+ maxItems = 8,
40
+ maxSizePx = 470,
41
+ }: DefaultToolbarProps) {
28
42
  const editor = useEditor()
29
43
  const msg = useTranslation()
30
44
  const breakpoint = useBreakpoint()
@@ -44,31 +58,49 @@ export const DefaultToolbar = memo(function DefaultToolbar({ children }: Default
44
58
  : breakpoint < PORTRAIT_BREAKPOINT.TABLET
45
59
 
46
60
  return (
47
- <div ref={ref} className="tlui-toolbar">
48
- <div className="tlui-toolbar__inner">
49
- <div className="tlui-toolbar__left">
50
- {!isReadonlyMode && (
51
- <div className="tlui-toolbar__extras">
52
- {showQuickActions && (
53
- <TldrawUiToolbar
54
- className="tlui-toolbar__extras__controls tlui-buttons__horizontal"
55
- label={msg('actions-menu.title')}
56
- >
57
- {QuickActions && <QuickActions />}
58
- {ActionsMenu && <ActionsMenu />}
59
- </TldrawUiToolbar>
60
- )}
61
- <ToggleToolLockedButton activeToolId={activeToolId} />
61
+ <TldrawUiOrientationProvider
62
+ orientation={orientation}
63
+ tooltipSide={orientation === 'horizontal' ? 'top' : 'right'}
64
+ >
65
+ <div
66
+ ref={ref}
67
+ className={classNames('tlui-main-toolbar', `tlui-main-toolbar--${orientation}`)}
68
+ >
69
+ <div className="tlui-main-toolbar__inner">
70
+ <div className="tlui-main-toolbar__left">
71
+ {!isReadonlyMode && (
72
+ <div className="tlui-main-toolbar__extras">
73
+ {showQuickActions && (
74
+ <TldrawUiToolbar
75
+ orientation={orientation}
76
+ className="tlui-main-toolbar__extras__controls"
77
+ label={msg('actions-menu.title')}
78
+ >
79
+ {QuickActions && <QuickActions />}
80
+ {ActionsMenu && <ActionsMenu />}
81
+ </TldrawUiToolbar>
82
+ )}
83
+ <ToggleToolLockedButton activeToolId={activeToolId} />
84
+ </div>
85
+ )}
86
+ <OverflowingToolbar
87
+ orientation={orientation}
88
+ sizingParentClassName="tlui-main-toolbar"
89
+ minItems={minItems}
90
+ maxItems={maxItems}
91
+ minSizePx={minSizePx}
92
+ maxSizePx={maxSizePx}
93
+ >
94
+ {children ?? <DefaultToolbarContent />}
95
+ </OverflowingToolbar>
96
+ </div>
97
+ {breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM && !isReadonlyMode && (
98
+ <div className="tlui-main-toolbar__tools tlui-main-toolbar__mobile-style-panel">
99
+ <MobileStylePanel />
62
100
  </div>
63
101
  )}
64
- <OverflowingToolbar>{children ?? <DefaultToolbarContent />}</OverflowingToolbar>
65
102
  </div>
66
- {breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM && !isReadonlyMode && (
67
- <div className="tlui-toolbar__tools">
68
- <MobileStylePanel />
69
- </div>
70
- )}
71
103
  </div>
72
- </div>
104
+ </TldrawUiOrientationProvider>
73
105
  )
74
106
  })
@@ -5,6 +5,7 @@ import { useUiEvents } from '../../context/events'
5
5
  import { useTranslation } from '../../hooks/useTranslation/useTranslation'
6
6
  import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
7
7
  import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
8
+ import { TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
8
9
 
9
10
  /** @public */
10
11
  export interface DefaultVideoToolbarContentProps {
@@ -44,7 +45,12 @@ export const DefaultVideoToolbarContent = track(function DefaultVideoToolbarCont
44
45
  return (
45
46
  <>
46
47
  {!isReadonly && (
47
- <TldrawUiButton type="icon" title={msg('tool.replace-media')} onClick={handleVideoReplace}>
48
+ <TldrawUiButton
49
+ type="icon"
50
+ title={msg('tool.replace-media')}
51
+ onClick={handleVideoReplace}
52
+ data-testid="tool.video-replace"
53
+ >
48
54
  <TldrawUiButtonIcon small icon="tool-media" />
49
55
  </TldrawUiButton>
50
56
  )}
@@ -52,21 +58,23 @@ export const DefaultVideoToolbarContent = track(function DefaultVideoToolbarCont
52
58
  type="icon"
53
59
  title={msg('action.download-original')}
54
60
  onClick={handleVideoDownload}
61
+ data-testid="tool.video-download"
55
62
  >
56
63
  <TldrawUiButtonIcon small icon="download" />
57
64
  </TldrawUiButton>
58
65
  {(altText || !isReadonly) && (
59
- <TldrawUiButton
60
- type="normal"
66
+ <TldrawUiToolbarButton
67
+ type="icon"
61
68
  isActive={!!altText}
62
69
  title={msg('tool.media-alt-text')}
70
+ data-testid="tool.video-alt-text"
63
71
  onClick={() => {
64
72
  trackEvent('alt-text-start', { source })
65
73
  onEditAltTextStart()
66
74
  }}
67
75
  >
68
76
  <TldrawUiButtonIcon small icon="alt" />
69
- </TldrawUiButton>
77
+ </TldrawUiToolbarButton>
70
78
  )}
71
79
  </>
72
80
  )
@@ -2,9 +2,9 @@ import { preventDefault, TiptapEditor, useEditor } from '@tldraw/editor'
2
2
  import { useEffect, useRef, useState } from 'react'
3
3
  import { useUiEvents } from '../../context/events'
4
4
  import { useTranslation } from '../../hooks/useTranslation/useTranslation'
5
- import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
6
5
  import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
7
6
  import { TldrawUiInput } from '../primitives/TldrawUiInput'
7
+ import { TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
8
8
 
9
9
  /** @public */
10
10
  export interface LinkEditorProps {
@@ -76,7 +76,7 @@ export function LinkEditor({ textEditor, value: initialValue, onClose }: LinkEdi
76
76
  onCancel={handleLinkCancel}
77
77
  placeholder="example.com"
78
78
  />
79
- <TldrawUiButton
79
+ <TldrawUiToolbarButton
80
80
  className="tlui-rich-text__toolbar-link-visit"
81
81
  title={msg('tool.rich-text-link-visit')}
82
82
  type="icon"
@@ -85,8 +85,8 @@ export function LinkEditor({ textEditor, value: initialValue, onClose }: LinkEdi
85
85
  disabled={!value}
86
86
  >
87
87
  <TldrawUiButtonIcon small icon="external-link" />
88
- </TldrawUiButton>
89
- <TldrawUiButton
88
+ </TldrawUiToolbarButton>
89
+ <TldrawUiToolbarButton
90
90
  className="tlui-rich-text__toolbar-link-remove"
91
91
  title={msg('tool.rich-text-link-remove')}
92
92
  data-testid="rich-text.link-remove"
@@ -95,7 +95,7 @@ export function LinkEditor({ textEditor, value: initialValue, onClose }: LinkEdi
95
95
  onClick={handleRemoveLink}
96
96
  >
97
97
  <TldrawUiButtonIcon small icon="trash" />
98
- </TldrawUiButton>
98
+ </TldrawUiToolbarButton>
99
99
  </>
100
100
  )
101
101
  }
@@ -1,5 +1,7 @@
1
1
  import {
2
2
  activeElementShouldCaptureKeys,
3
+ assert,
4
+ modulate,
3
5
  preventDefault,
4
6
  tlmenus,
5
7
  useEditor,
@@ -7,7 +9,7 @@ import {
7
9
  useUniqueSafeId,
8
10
  } from '@tldraw/editor'
9
11
  import classNames from 'classnames'
10
- import { createContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
12
+ import { createContext, useEffect, useLayoutEffect, useRef, useState } from 'react'
11
13
  import { PORTRAIT_BREAKPOINT } from '../../constants'
12
14
  import { useBreakpoint } from '../../context/breakpoints'
13
15
  import { areShortcutsDisabled } from '../../hooks/useKeyboardShortcuts'
@@ -20,6 +22,7 @@ import {
20
22
  TldrawUiPopoverTrigger,
21
23
  } from '../primitives/TldrawUiPopover'
22
24
  import { TldrawUiToolbar, TldrawUiToolbarButton } from '../primitives/TldrawUiToolbar'
25
+ import { TldrawUiColumn, TldrawUiRow } from '../primitives/layout'
23
26
  import { TldrawUiMenuContextProvider } from '../primitives/menus/TldrawUiMenuContext'
24
27
 
25
28
  export const IsInOverflowContext = createContext(false)
@@ -40,10 +43,24 @@ const NUMBERED_SHORTCUT_KEYS: Record<string, number> = {
40
43
  /** @public */
41
44
  export interface OverflowingToolbarProps {
42
45
  children: React.ReactNode
46
+ orientation: 'horizontal' | 'vertical'
47
+ sizingParentClassName: string
48
+ minItems: number
49
+ minSizePx: number
50
+ maxItems: number
51
+ maxSizePx: number
43
52
  }
44
53
 
45
54
  /** @public @react */
46
- export function OverflowingToolbar({ children }: OverflowingToolbarProps) {
55
+ export function OverflowingToolbar({
56
+ children,
57
+ orientation,
58
+ sizingParentClassName,
59
+ minItems,
60
+ minSizePx,
61
+ maxItems,
62
+ maxSizePx,
63
+ }: OverflowingToolbarProps) {
47
64
  const editor = useEditor()
48
65
  const id = useUniqueSafeId()
49
66
  const breakpoint = useBreakpoint()
@@ -51,66 +68,165 @@ export function OverflowingToolbar({ children }: OverflowingToolbarProps) {
51
68
  const rButtons = useRef<HTMLElement[]>([])
52
69
  const [isOpen, setIsOpen] = useState(false)
53
70
 
54
- const overflowIndex = Math.min(8, 5 + breakpoint)
55
-
56
- const [totalItems, setTotalItems] = useState(0)
57
71
  const mainToolsRef = useRef<HTMLDivElement>(null)
58
- const [lastActiveOverflowItem, setLastActiveOverflowItem] = useState<string | null>(null)
59
-
60
- const css = useMemo(() => {
61
- const activeCss = lastActiveOverflowItem ? `:not([data-value="${lastActiveOverflowItem}"])` : ''
62
72
 
63
- return `
64
- #${id}_main > *:nth-child(n + ${overflowIndex + (lastActiveOverflowItem ? 1 : 2)})${activeCss} {
65
- display: none;
66
- }
67
- #${id}_more > *:nth-child(-n + ${overflowIndex}) {
68
- display: none;
69
- }
70
- #${id}_more > *:nth-child(-n + ${overflowIndex + 4}) {
71
- margin-top: 0;
72
- }
73
- `
74
- }, [lastActiveOverflowItem, id, overflowIndex])
73
+ // we have to use state instead of a ref here so that we get
74
+ // an update when the overflow popover mounts / unmounts
75
+ const [overflowTools, setOverflowTools] = useState<HTMLDivElement | null>(null)
76
+ const [lastActiveOverflowItem, setLastActiveOverflowItem] = useState<string | null>(null)
77
+ const [shouldShowOverflow, setShouldShowOverflow] = useState(false)
75
78
 
76
79
  const onDomUpdate = useEvent(() => {
77
80
  if (!mainToolsRef.current) return
78
81
 
79
- const children = Array.from(mainToolsRef.current.children)
80
- setTotalItems(children.length)
82
+ // whenever we get an update, we need to re-calculate the number of items to show and update
83
+ // the component accordingly.
84
+ const sizeProp = orientation === 'horizontal' ? 'offsetWidth' : 'offsetHeight'
81
85
 
82
- // If the last active overflow item is no longer in the overflow, clear it
83
- const lastActiveElementIdx = children.findIndex(
84
- (el) => el.getAttribute('data-value') === lastActiveOverflowItem
85
- )
86
- if (lastActiveElementIdx <= overflowIndex) {
87
- setLastActiveOverflowItem(null)
86
+ // toolbars can contain both single items and groups. we need to keep track of both.
87
+ type Items = (
88
+ | { type: 'item'; element: HTMLElement }
89
+ | { type: 'group'; items: Items; element: HTMLElement }
90
+ )[]
91
+
92
+ // walk through the dom and collect items so we can calculate what to show/hide
93
+ const mainItems = collectItems(mainToolsRef.current.children)
94
+ const overflowItems = overflowTools ? collectItems(overflowTools.children) : null
95
+ function collectItems(collection: HTMLCollection) {
96
+ const items: Items = []
97
+ for (const child of collection) {
98
+ if (child.classList.contains('tlui-main-toolbar__group')) {
99
+ items.push({
100
+ type: 'group',
101
+ items: collectItems(child.children),
102
+ element: child as HTMLElement,
103
+ })
104
+ } else {
105
+ items.push({ type: 'item', element: child as HTMLElement })
106
+ }
107
+ }
108
+
109
+ return items
88
110
  }
89
111
 
90
- // But if there's a new active item...
91
- const activeElementIdx = Array.from(mainToolsRef.current.children).findIndex(
92
- (el) => el.getAttribute('aria-pressed') === 'true'
112
+ // the number of items to show is based on the space available to the toolbar.
113
+ const sizingParent = findParentWithClassName(mainToolsRef.current, sizingParentClassName)
114
+ const size = sizingParent[sizeProp]
115
+ const itemsToShow = Math.floor(
116
+ modulate(size, [minSizePx, maxSizePx], [minItems, maxItems], true)
93
117
  )
94
- if (activeElementIdx === -1) return
95
118
 
96
- // ...and it's in the overflow, set it as the last active overflow item
97
- if (activeElementIdx >= overflowIndex) {
98
- setLastActiveOverflowItem(children[activeElementIdx].getAttribute('data-value'))
99
- }
119
+ // now we know how many items to show, we need to walk through the items we found and show /
120
+ // hide them accordingly. We need to keep track of:
121
+ // the number of item's we've shown in the main content so far
122
+ let mainItemCount = 0
123
+ // the item that is currently active in the overflow content (if any)
124
+ let newActiveOverflowItem: string | null = null
125
+ // whether the last active overflow item is actually still in the overflow content
126
+ let shouldInvalidateLastActiveOverflowItem = false
127
+ // the buttons visible in the main content
128
+ const numberedButtons: HTMLButtonElement[] = []
129
+ function visitItems(
130
+ mainItems: Items,
131
+ overflowItems: Items | null
132
+ ): {
133
+ // for each group of items we visit, we need to know whether we showed anything in
134
+ // either section
135
+ didShowAnyInMain: boolean
136
+ didShowAnyInOverflow: boolean
137
+ } {
138
+ if (overflowItems) assert(mainItems.length === overflowItems.length)
139
+
140
+ let didShowAnyInMain = false
141
+ let didShowAnyInOverflow = false
142
+
143
+ for (let i = 0; i < mainItems.length; i++) {
144
+ const mainItem = mainItems[i]
145
+ const overflowItem = overflowItems?.[i]
146
+
147
+ if (mainItem.type === 'item') {
148
+ const isLastActiveOverflowItem =
149
+ mainItem.element.getAttribute('data-value') === lastActiveOverflowItem
150
+
151
+ // for single items, we show them in main if we have space, or if they're the
152
+ // last-used item from the overflow.
153
+ let shouldShowInMain
154
+ if (lastActiveOverflowItem) {
155
+ shouldShowInMain = mainItemCount < itemsToShow || isLastActiveOverflowItem
156
+ } else {
157
+ // we use <= here because if there is no last active overflow item, we want
158
+ // to show at least one item in the main toolbar.
159
+ shouldShowInMain = mainItemCount <= itemsToShow
160
+ }
161
+ const shouldShowInOverflow = mainItemCount >= itemsToShow
100
162
 
101
- // Save the buttons that are actually visible
102
- rButtons.current = Array.from(mainToolsRef.current?.children ?? []).filter(
103
- (el): el is HTMLElement => {
104
- // only count html elements...
105
- if (!(el instanceof HTMLElement)) return false
163
+ didShowAnyInMain ||= shouldShowInMain
164
+ didShowAnyInOverflow ||= shouldShowInOverflow
106
165
 
107
- // ...that are buttons...
108
- if (el.tagName.toLowerCase() !== 'button') return false
166
+ setAttribute(
167
+ mainItem.element,
168
+ 'data-toolbar-visible',
169
+ shouldShowInMain ? 'true' : 'false'
170
+ )
171
+ if (overflowItem) {
172
+ assert(overflowItem.type === 'item')
173
+ setAttribute(
174
+ overflowItem.element,
175
+ 'data-toolbar-visible',
176
+ shouldShowInOverflow ? 'true' : 'false'
177
+ )
178
+ }
179
+ if (shouldShowInOverflow && mainItem.element.getAttribute('aria-pressed') === 'true') {
180
+ newActiveOverflowItem = mainItem.element.getAttribute('data-value')
181
+ }
182
+ if (shouldShowInMain && mainItem.element.tagName === 'BUTTON') {
183
+ numberedButtons.push(mainItem.element as HTMLButtonElement)
184
+ }
185
+ if (!shouldShowInOverflow && isLastActiveOverflowItem) {
186
+ shouldInvalidateLastActiveOverflowItem = true
187
+ }
188
+ mainItemCount++
189
+ } else {
190
+ // for groups, we show them in main if we have space, or if they're the
191
+ // last-used item from the overflow.
192
+ let result, overflowGroup
193
+ if (overflowItem) {
194
+ assert(overflowItem.type === 'group')
195
+ overflowGroup = overflowItem
196
+ result = visitItems(mainItem.items, overflowGroup.items)
197
+ } else {
198
+ result = visitItems(mainItem.items, null)
199
+ }
109
200
 
110
- // ...that are actually visible
111
- return !!(el.offsetWidth || el.offsetHeight)
201
+ didShowAnyInMain ||= result.didShowAnyInMain
202
+ didShowAnyInOverflow ||= result.didShowAnyInOverflow
203
+
204
+ setAttribute(
205
+ mainItem.element,
206
+ 'data-toolbar-visible',
207
+ result.didShowAnyInMain ? 'true' : 'false'
208
+ )
209
+ if (overflowGroup) {
210
+ setAttribute(
211
+ overflowGroup.element,
212
+ 'data-toolbar-visible',
213
+ result.didShowAnyInOverflow ? 'true' : 'false'
214
+ )
215
+ }
216
+ }
112
217
  }
113
- )
218
+ return { didShowAnyInMain, didShowAnyInOverflow }
219
+ }
220
+
221
+ const { didShowAnyInOverflow } = visitItems(mainItems, overflowItems)
222
+ setShouldShowOverflow(didShowAnyInOverflow)
223
+ if (newActiveOverflowItem) {
224
+ setLastActiveOverflowItem(newActiveOverflowItem)
225
+ } else if (shouldInvalidateLastActiveOverflowItem) {
226
+ setLastActiveOverflowItem(null)
227
+ }
228
+
229
+ rButtons.current = numberedButtons
114
230
  })
115
231
 
116
232
  useLayoutEffect(() => {
@@ -124,20 +240,31 @@ export function OverflowingToolbar({ children }: OverflowingToolbarProps) {
124
240
  mutationObserver.observe(mainToolsRef.current, {
125
241
  childList: true,
126
242
  subtree: true,
127
- attributeFilter: ['data-value', 'aria-pressed'],
243
+ attributes: true,
244
+ characterData: true,
128
245
  })
129
246
 
247
+ const sizingParent = findParentWithClassName(mainToolsRef.current, sizingParentClassName)
248
+ const resizeObserver = new ResizeObserver(onDomUpdate)
249
+ resizeObserver.observe(sizingParent)
250
+
130
251
  return () => {
131
252
  mutationObserver.disconnect()
253
+ resizeObserver.disconnect()
132
254
  }
133
- }, [onDomUpdate])
255
+ }, [onDomUpdate, sizingParentClassName])
134
256
 
135
257
  useEffect(() => {
136
258
  if (!editor.options.enableToolbarKeyboardShortcuts) return
137
259
 
138
260
  function handleKeyDown(event: KeyboardEvent) {
139
- if (areShortcutsDisabled(editor) || activeElementShouldCaptureKeys(true /* allow buttons */))
261
+ if (
262
+ areShortcutsDisabled(editor) ||
263
+ activeElementShouldCaptureKeys(true /* allow buttons */)
264
+ ) {
140
265
  return
266
+ }
267
+
141
268
  // no accelerator keys
142
269
  if (event.ctrlKey || event.metaKey || event.altKey || event.shiftKey) return
143
270
  const index = NUMBERED_SHORTCUT_KEYS[event.key]
@@ -154,37 +281,45 @@ export function OverflowingToolbar({ children }: OverflowingToolbarProps) {
154
281
  }, [editor])
155
282
 
156
283
  const popoverId = 'toolbar overflow'
284
+
285
+ const Layout = orientation === 'horizontal' ? TldrawUiRow : TldrawUiColumn
157
286
  return (
158
287
  <>
159
- <style nonce={editor.options.nonce}>{css}</style>
160
288
  <TldrawUiToolbar
161
- className={classNames('tlui-toolbar__tools', {
162
- 'tlui-toolbar__tools__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,
289
+ orientation={orientation}
290
+ className={classNames('tlui-main-toolbar__tools', {
291
+ 'tlui-main-toolbar__tools__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,
163
292
  })}
164
293
  label={msg('tool-panel.title')}
165
294
  >
166
- <div id={`${id}_main`} ref={mainToolsRef} className="tlui-toolbar__tools__list">
295
+ <Layout id={`${id}_main`} ref={mainToolsRef}>
167
296
  <TldrawUiMenuContextProvider type="toolbar" sourceId="toolbar">
168
297
  {children}
169
298
  </TldrawUiMenuContextProvider>
170
- </div>
171
- {/* There is a +1 because if the menu is just one item, it's not necessary. */}
172
- {totalItems > overflowIndex + 1 && (
299
+ </Layout>
300
+ {shouldShowOverflow && (
173
301
  <IsInOverflowContext.Provider value={true}>
174
302
  <TldrawUiPopover id={popoverId} open={isOpen} onOpenChange={setIsOpen}>
175
303
  <TldrawUiPopoverTrigger>
176
304
  <TldrawUiToolbarButton
177
305
  title={msg('tool-panel.more')}
178
306
  type="tool"
179
- className="tlui-toolbar__overflow"
307
+ className="tlui-main-toolbar__overflow"
180
308
  data-testid="tools.more-button"
181
309
  >
182
- <TldrawUiButtonIcon icon="chevron-up" />
310
+ <TldrawUiButtonIcon
311
+ icon={orientation === 'horizontal' ? 'chevron-up' : 'chevron-right'}
312
+ />
183
313
  </TldrawUiToolbarButton>
184
314
  </TldrawUiPopoverTrigger>
185
- <TldrawUiPopoverContent side="top" align="center">
315
+ <TldrawUiPopoverContent
316
+ side={orientation === 'horizontal' ? 'top' : 'right'}
317
+ align={orientation === 'horizontal' ? 'center' : 'end'}
318
+ >
186
319
  <TldrawUiToolbar
187
- className="tlui-buttons__grid"
320
+ orientation="grid"
321
+ className="tlui-main-toolbar__overflow-content"
322
+ ref={setOverflowTools}
188
323
  data-testid="tools.more-content"
189
324
  label={msg('tool-panel.more')}
190
325
  id={`${id}_more`}
@@ -215,3 +350,19 @@ export const isActiveTLUiToolItem = (
215
350
  ? activeToolId === 'geo' && geoState === item.meta?.geo
216
351
  : activeToolId === item.id
217
352
  }
353
+
354
+ function findParentWithClassName(startingElement: HTMLElement, className: string): HTMLElement {
355
+ let element: HTMLElement | null = startingElement
356
+ while (element) {
357
+ if (element.classList.contains(className)) {
358
+ return element
359
+ }
360
+ element = element.parentElement
361
+ }
362
+ throw new Error('Could not find parent with class name ' + className)
363
+ }
364
+
365
+ function setAttribute(element: HTMLElement, name: string, value: string) {
366
+ if (element.getAttribute(name) === value) return
367
+ element.setAttribute(name, value)
368
+ }
@@ -5,6 +5,7 @@ import { useBreakpoint } from '../../context/breakpoints'
5
5
  import { useTranslation } from '../../hooks/useTranslation/useTranslation'
6
6
  import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
7
7
  import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
8
+ import { TldrawUiTooltip } from '../primitives/TldrawUiTooltip'
8
9
 
9
10
  /** @public */
10
11
  export interface ToggleToolLockedButtonProps {
@@ -25,16 +26,18 @@ export function ToggleToolLockedButton({ activeToolId }: ToggleToolLockedButtonP
25
26
  if (!activeToolId || !tool.isLockable) return null
26
27
 
27
28
  return (
28
- <TldrawUiButton
29
- type="normal"
30
- title={msg('action.toggle-tool-lock')}
31
- data-testid="tool-lock"
32
- className={classNames('tlui-toolbar__lock-button', {
33
- 'tlui-toolbar__lock-button__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,
34
- })}
35
- onClick={() => editor.updateInstanceState({ isToolLocked: !isToolLocked })}
36
- >
37
- <TldrawUiButtonIcon icon={isToolLocked ? 'lock' : 'unlock'} small />
38
- </TldrawUiButton>
29
+ <TldrawUiTooltip content={msg('action.toggle-tool-lock')}>
30
+ <TldrawUiButton
31
+ type="normal"
32
+ title={msg('action.toggle-tool-lock')}
33
+ data-testid="tool-lock"
34
+ className={classNames('tlui-main-toolbar__lock-button', {
35
+ 'tlui-main-toolbar__lock-button__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,
36
+ })}
37
+ onClick={() => editor.updateInstanceState({ isToolLocked: !isToolLocked })}
38
+ >
39
+ <TldrawUiButtonIcon icon={isToolLocked ? 'lock' : 'unlock'} small />
40
+ </TldrawUiButton>
41
+ </TldrawUiTooltip>
39
42
  )
40
43
  }
@@ -651,6 +651,14 @@ export function ToggleKeyboardShortcutsItem() {
651
651
  )
652
652
  }
653
653
 
654
+ /** @public @react */
655
+ export function ToggleUiLabelsItem() {
656
+ const editor = useEditor()
657
+ const showUiLabels = useValue('showUiLabels', () => editor.user.getShowUiLabels(), [editor])
658
+
659
+ return <TldrawUiMenuActionCheckboxItem actionId="toggle-ui-labels" checked={showUiLabels} />
660
+ }
661
+
654
662
  /** @public @react */
655
663
  export function ToggleDebugModeItem() {
656
664
  const editor = useEditor()
@@ -172,7 +172,12 @@ export const TldrawUiContextualToolbar = ({
172
172
  className={classNames('tlui-contextual-toolbar', className)}
173
173
  onPointerDown={stopEventPropagation}
174
174
  >
175
- <TldrawUiToolbar className="tlui-menu tlui-buttons__horizontal" label={label}>
175
+ <TldrawUiToolbar
176
+ orientation="horizontal"
177
+ className="tlui-menu"
178
+ label={label}
179
+ tooltipSide="top"
180
+ >
176
181
  {children}
177
182
  </TldrawUiToolbar>
178
183
  </div>
@@ -1,4 +1,5 @@
1
1
  import { useContainer } from '@tldraw/editor'
2
+ import classNames from 'classnames'
2
3
  import { Popover as _Popover } from 'radix-ui'
3
4
  import React from 'react'
4
5
  import { useMenuIsOpen } from '../../hooks/useMenuIsOpen'
@@ -9,15 +10,16 @@ export interface TLUiPopoverProps {
9
10
  open?: boolean
10
11
  children: React.ReactNode
11
12
  onOpenChange?(isOpen: boolean): void
13
+ className?: string
12
14
  }
13
15
 
14
16
  /** @public @react */
15
- export function TldrawUiPopover({ id, children, onOpenChange, open }: TLUiPopoverProps) {
17
+ export function TldrawUiPopover({ id, children, onOpenChange, open, className }: TLUiPopoverProps) {
16
18
  const [isOpen, handleOpenChange] = useMenuIsOpen(id, onOpenChange)
17
19
 
18
20
  return (
19
21
  <_Popover.Root onOpenChange={handleOpenChange} open={open || isOpen /* allow debugging */}>
20
- <div className="tlui-popover">{children}</div>
22
+ <div className={classNames('tlui-popover', className)}>{children}</div>
21
23
  </_Popover.Root>
22
24
  )
23
25
  }