tldraw 3.16.0-canary.c1bcdabc9513 → 3.16.0-canary.c349490eaef0

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 (300) hide show
  1. package/dist-cjs/index.d.ts +164 -107
  2. package/dist-cjs/index.js +29 -14
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/Tldraw.js +12 -2
  5. package/dist-cjs/lib/Tldraw.js.map +2 -2
  6. package/dist-cjs/lib/defaultExternalContentHandlers.js +15 -4
  7. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  8. package/dist-cjs/lib/shapes/arrow/arrowLabel.js +6 -0
  9. package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +3 -3
  10. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +4 -4
  11. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +8 -1
  13. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  14. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js +8 -2
  15. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js.map +2 -2
  16. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +1 -0
  17. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  18. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -0
  19. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
  20. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +2 -1
  21. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  22. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +4 -4
  23. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js.map +2 -2
  24. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -3
  25. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  26. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +3 -5
  27. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  28. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +0 -2
  29. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
  30. package/dist-cjs/lib/shapes/text/PlainTextArea.js +3 -2
  31. package/dist-cjs/lib/shapes/text/PlainTextArea.js.map +2 -2
  32. package/dist-cjs/lib/shapes/text/RichTextArea.js +3 -3
  33. package/dist-cjs/lib/shapes/text/RichTextArea.js.map +2 -2
  34. package/dist-cjs/lib/ui/TldrawUi.js +13 -12
  35. package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
  36. package/dist-cjs/lib/ui/assetUrls.js +13 -10
  37. package/dist-cjs/lib/ui/assetUrls.js.map +2 -2
  38. package/dist-cjs/lib/ui/components/A11y.js +1 -1
  39. package/dist-cjs/lib/ui/components/A11y.js.map +2 -2
  40. package/dist-cjs/lib/ui/components/{FollowingIndicator.js → DefaultFollowingIndicator.js} +6 -6
  41. package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +7 -0
  42. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +6 -6
  43. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
  44. package/dist-cjs/lib/ui/components/LanguageMenu.js +1 -0
  45. package/dist-cjs/lib/ui/components/LanguageMenu.js.map +2 -2
  46. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +2 -1
  47. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
  48. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +1 -1
  49. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
  50. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +9 -4
  51. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
  52. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +255 -316
  53. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  54. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js +147 -0
  55. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +7 -0
  56. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js +68 -0
  57. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js.map +7 -0
  58. package/dist-cjs/lib/ui/components/StylePanel/{DoubleDropdownPicker.js → StylePanelDoubleDropdownPicker.js} +23 -22
  59. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +7 -0
  60. package/dist-cjs/lib/ui/components/StylePanel/{DropdownPicker.js → StylePanelDropdownPicker.js} +24 -21
  61. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +7 -0
  62. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js +28 -0
  63. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js.map +7 -0
  64. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +2 -0
  65. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  66. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +38 -9
  67. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  68. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js +15 -3
  69. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js.map +2 -2
  70. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +2 -1
  71. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
  72. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +1 -1
  73. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +2 -2
  74. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +6 -2
  75. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
  76. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +11 -2
  77. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  78. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +5 -3
  79. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js.map +2 -2
  80. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +18 -5
  81. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  82. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +3 -0
  83. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  84. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +75 -37
  85. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  86. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js +3 -0
  87. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js.map +2 -2
  88. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +8 -8
  89. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  90. package/dist-cjs/lib/ui/context/actions.js +29 -10
  91. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  92. package/dist-cjs/lib/ui/context/components.js +2 -0
  93. package/dist-cjs/lib/ui/context/components.js.map +2 -2
  94. package/dist-cjs/lib/ui/context/events.js.map +1 -1
  95. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +1 -1
  96. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
  97. package/dist-cjs/lib/ui/hooks/useExportAs.js +3 -2
  98. package/dist-cjs/lib/ui/hooks/useExportAs.js.map +2 -2
  99. package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
  100. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  101. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  102. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +6 -2
  103. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  104. package/dist-cjs/lib/ui/kbd-utils.js +9 -3
  105. package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
  106. package/dist-cjs/lib/ui/version.js +3 -3
  107. package/dist-cjs/lib/ui/version.js.map +1 -1
  108. package/dist-cjs/lib/utils/export/copyAs.js +1 -2
  109. package/dist-cjs/lib/utils/export/copyAs.js.map +2 -2
  110. package/dist-cjs/lib/utils/export/export.js +0 -20
  111. package/dist-cjs/lib/utils/export/export.js.map +2 -2
  112. package/dist-cjs/lib/utils/export/exportAs.js +1 -2
  113. package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
  114. package/dist-esm/index.d.mts +164 -107
  115. package/dist-esm/index.mjs +57 -29
  116. package/dist-esm/index.mjs.map +2 -2
  117. package/dist-esm/lib/Tldraw.mjs +14 -4
  118. package/dist-esm/lib/Tldraw.mjs.map +2 -2
  119. package/dist-esm/lib/defaultExternalContentHandlers.mjs +15 -4
  120. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  121. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +6 -0
  122. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +3 -3
  123. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +4 -5
  124. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  125. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +8 -1
  126. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  127. package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs +9 -3
  128. package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs.map +2 -2
  129. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +1 -0
  130. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  131. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -0
  132. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
  133. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +2 -1
  134. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  135. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs +5 -5
  136. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs.map +2 -2
  137. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -3
  138. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  139. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +3 -6
  140. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  141. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +0 -2
  142. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  143. package/dist-esm/lib/shapes/text/PlainTextArea.mjs +4 -3
  144. package/dist-esm/lib/shapes/text/PlainTextArea.mjs.map +2 -2
  145. package/dist-esm/lib/shapes/text/RichTextArea.mjs +3 -4
  146. package/dist-esm/lib/shapes/text/RichTextArea.mjs.map +2 -2
  147. package/dist-esm/lib/ui/TldrawUi.mjs +13 -12
  148. package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
  149. package/dist-esm/lib/ui/assetUrls.mjs +13 -10
  150. package/dist-esm/lib/ui/assetUrls.mjs.map +2 -2
  151. package/dist-esm/lib/ui/components/A11y.mjs +1 -2
  152. package/dist-esm/lib/ui/components/A11y.mjs.map +2 -2
  153. package/dist-esm/lib/ui/components/{FollowingIndicator.mjs → DefaultFollowingIndicator.mjs} +3 -3
  154. package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +7 -0
  155. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +6 -6
  156. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
  157. package/dist-esm/lib/ui/components/LanguageMenu.mjs +1 -0
  158. package/dist-esm/lib/ui/components/LanguageMenu.mjs.map +2 -2
  159. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +2 -1
  160. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
  161. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +1 -2
  162. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
  163. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +14 -5
  164. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
  165. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +257 -320
  166. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  167. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +135 -0
  168. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +7 -0
  169. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +48 -0
  170. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +7 -0
  171. package/dist-esm/lib/ui/components/StylePanel/{DoubleDropdownPicker.mjs → StylePanelDoubleDropdownPicker.mjs} +20 -19
  172. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +7 -0
  173. package/dist-esm/lib/ui/components/StylePanel/{DropdownPicker.mjs → StylePanelDropdownPicker.mjs} +21 -18
  174. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +7 -0
  175. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs +8 -0
  176. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs.map +7 -0
  177. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +2 -0
  178. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  179. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +38 -9
  180. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  181. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs +15 -3
  182. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs.map +2 -2
  183. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +2 -1
  184. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
  185. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +1 -1
  186. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +2 -2
  187. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +6 -2
  188. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
  189. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +11 -3
  190. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  191. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs +6 -4
  192. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs.map +2 -2
  193. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +18 -5
  194. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  195. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +3 -0
  196. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  197. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +76 -37
  198. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  199. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs +3 -0
  200. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs.map +2 -2
  201. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +8 -8
  202. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  203. package/dist-esm/lib/ui/context/actions.mjs +29 -10
  204. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  205. package/dist-esm/lib/ui/context/components.mjs +2 -0
  206. package/dist-esm/lib/ui/context/components.mjs.map +2 -2
  207. package/dist-esm/lib/ui/context/events.mjs.map +1 -1
  208. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +1 -2
  209. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
  210. package/dist-esm/lib/ui/hooks/useExportAs.mjs +3 -2
  211. package/dist-esm/lib/ui/hooks/useExportAs.mjs.map +2 -2
  212. package/dist-esm/lib/ui/hooks/useTools.mjs +1 -1
  213. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  214. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +6 -2
  215. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  216. package/dist-esm/lib/ui/kbd-utils.mjs +9 -3
  217. package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
  218. package/dist-esm/lib/ui/version.mjs +3 -3
  219. package/dist-esm/lib/ui/version.mjs.map +1 -1
  220. package/dist-esm/lib/utils/export/copyAs.mjs +1 -2
  221. package/dist-esm/lib/utils/export/copyAs.mjs.map +2 -2
  222. package/dist-esm/lib/utils/export/export.mjs +0 -20
  223. package/dist-esm/lib/utils/export/export.mjs.map +2 -2
  224. package/dist-esm/lib/utils/export/exportAs.mjs +1 -2
  225. package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
  226. package/package.json +3 -3
  227. package/src/index.ts +41 -22
  228. package/src/lib/Tldraw.tsx +15 -2
  229. package/src/lib/defaultExternalContentHandlers.ts +26 -4
  230. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +2 -2
  231. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +41 -0
  232. package/src/lib/shapes/arrow/arrowLabel.ts +8 -0
  233. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +4 -5
  234. package/src/lib/shapes/frame/FrameShapeUtil.tsx +9 -0
  235. package/src/lib/shapes/frame/components/FrameLabelInput.tsx +10 -3
  236. package/src/lib/shapes/geo/GeoShapeUtil.tsx +1 -0
  237. package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -0
  238. package/src/lib/shapes/note/NoteShapeUtil.tsx +1 -0
  239. package/src/lib/shapes/shared/HyperlinkButton.tsx +5 -5
  240. package/src/lib/shapes/shared/PlainTextLabel.tsx +0 -6
  241. package/src/lib/shapes/shared/useEditablePlainText.ts +3 -10
  242. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +0 -7
  243. package/src/lib/shapes/text/PlainTextArea.tsx +4 -3
  244. package/src/lib/shapes/text/RichTextArea.tsx +3 -4
  245. package/src/lib/ui/TldrawUi.tsx +16 -10
  246. package/src/lib/ui/assetUrls.ts +13 -10
  247. package/src/lib/ui/components/A11y.tsx +1 -2
  248. package/src/lib/ui/components/{FollowingIndicator.tsx → DefaultFollowingIndicator.tsx} +2 -1
  249. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +6 -6
  250. package/src/lib/ui/components/LanguageMenu.tsx +1 -0
  251. package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +2 -1
  252. package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +1 -2
  253. package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +27 -13
  254. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +260 -381
  255. package/src/lib/ui/components/{primitives/TldrawUiButtonPicker.tsx → StylePanel/StylePanelButtonPicker.tsx} +70 -50
  256. package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +63 -0
  257. package/src/lib/ui/components/StylePanel/{DoubleDropdownPicker.tsx → StylePanelDoubleDropdownPicker.tsx} +28 -19
  258. package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +119 -0
  259. package/src/lib/ui/components/StylePanel/StylePanelSubheading.tsx +9 -0
  260. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +2 -0
  261. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +32 -15
  262. package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
  263. package/src/lib/ui/components/Toolbar/LinkEditor.tsx +1 -0
  264. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +1 -1
  265. package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +9 -2
  266. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +7 -3
  267. package/src/lib/ui/components/primitives/TldrawUiInput.tsx +6 -3
  268. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +52 -32
  269. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +5 -1
  270. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +82 -30
  271. package/src/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.tsx +4 -0
  272. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +9 -9
  273. package/src/lib/ui/context/actions.tsx +36 -10
  274. package/src/lib/ui/context/components.tsx +3 -0
  275. package/src/lib/ui/context/events.tsx +1 -1
  276. package/src/lib/ui/hooks/useClipboardEvents.ts +1 -2
  277. package/src/lib/ui/hooks/useExportAs.ts +3 -2
  278. package/src/lib/ui/hooks/useTools.tsx +1 -1
  279. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +4 -0
  280. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +6 -2
  281. package/src/lib/ui/kbd-utils.ts +10 -3
  282. package/src/lib/ui/version.ts +3 -3
  283. package/src/lib/ui.css +29 -2
  284. package/src/lib/utils/export/copyAs.ts +1 -24
  285. package/src/lib/utils/export/export.ts +0 -36
  286. package/src/lib/utils/export/exportAs.ts +1 -32
  287. package/src/test/custom-clipping.test.ts +436 -0
  288. package/src/test/getCulledShapes.test.tsx +71 -2
  289. package/tldraw.css +45 -5
  290. package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
  291. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +0 -7
  292. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +0 -7
  293. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js +0 -131
  294. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +0 -7
  295. package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
  296. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +0 -7
  297. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +0 -7
  298. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +0 -115
  299. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +0 -7
  300. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +0 -110
@@ -4,7 +4,6 @@ import {
4
4
  clamp,
5
5
  Editor,
6
6
  react,
7
- stopEventPropagation,
8
7
  useAtom,
9
8
  useEditor,
10
9
  usePassThroughMouseOverEvents,
@@ -170,9 +169,14 @@ export const TldrawUiContextualToolbar = ({
170
169
  data-visible={false}
171
170
  data-testid="contextual-toolbar"
172
171
  className={classNames('tlui-contextual-toolbar', className)}
173
- onPointerDown={stopEventPropagation}
172
+ onPointerDown={editor.markEventAsHandled}
174
173
  >
175
- <TldrawUiToolbar orientation="horizontal" className="tlui-menu" label={label}>
174
+ <TldrawUiToolbar
175
+ orientation="horizontal"
176
+ className="tlui-menu"
177
+ label={label}
178
+ tooltipSide="top"
179
+ >
176
180
  {children}
177
181
  </TldrawUiToolbar>
178
182
  </div>
@@ -1,4 +1,4 @@
1
- import { stopEventPropagation, tlenv, tltime, useMaybeEditor } from '@tldraw/editor'
1
+ import { tlenv, tltime, useMaybeEditor } from '@tldraw/editor'
2
2
  import classNames from 'classnames'
3
3
  import * as React from 'react'
4
4
  import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
@@ -35,6 +35,7 @@ export interface TLUiInputProps {
35
35
  shouldManuallyMaintainScrollPositionWhenFocused?: boolean
36
36
  value?: string
37
37
  'data-testid'?: string
38
+ 'aria-label'?: string
38
39
  }
39
40
 
40
41
  /** @public @react */
@@ -60,6 +61,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
60
61
  value,
61
62
  'data-testid': dataTestId,
62
63
  disabled,
64
+ 'aria-label': ariaLabel,
63
65
  },
64
66
  ref
65
67
  ) {
@@ -118,7 +120,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
118
120
  // `onChange` with a duplicated text value.
119
121
  if (isComposing.current) return
120
122
  e.currentTarget.blur()
121
- stopEventPropagation(e)
123
+ e.stopPropagation()
122
124
  onComplete?.(e.currentTarget.value)
123
125
  break
124
126
  }
@@ -126,7 +128,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
126
128
  e.currentTarget.value = rInitialValue.current
127
129
  onCancel?.(e.currentTarget.value)
128
130
  e.currentTarget.blur()
129
- stopEventPropagation(e)
131
+ e.stopPropagation()
130
132
  break
131
133
  }
132
134
  }
@@ -198,6 +200,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
198
200
  onCompositionStart={handleCompositionStart}
199
201
  onCompositionEnd={handleCompositionEnd}
200
202
  autoFocus={autoFocus}
203
+ aria-label={ariaLabel}
201
204
  placeholder={placeholder}
202
205
  value={value}
203
206
  data-testid={dataTestId}
@@ -1,7 +1,9 @@
1
+ import { tltime } from '@tldraw/editor'
1
2
  import { Slider as _Slider } from 'radix-ui'
2
3
  import React, { useCallback, useEffect, useState } from 'react'
3
4
  import { TLUiTranslationKey } from '../../hooks/useTranslation/TLUiTranslationKey'
4
5
  import { useTranslation } from '../../hooks/useTranslation/useTranslation'
6
+ import { TldrawUiTooltip, tooltipManager } from './TldrawUiTooltip'
5
7
 
6
8
  /** @public */
7
9
  export interface TLUiSliderProps {
@@ -11,7 +13,7 @@ export interface TLUiSliderProps {
11
13
  label: string
12
14
  title: string
13
15
  onValueChange(value: number): void
14
- onHistoryMark(id: string): void
16
+ onHistoryMark?(id: string): void
15
17
  'data-testid'?: string
16
18
  ariaValueModifier?: number
17
19
  }
@@ -32,6 +34,7 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
32
34
  ref
33
35
  ) {
34
36
  const msg = useTranslation()
37
+ const [titleAndLabel, setTitleAndLabel] = useState('')
35
38
 
36
39
  // XXX: Radix starts out our slider with a tabIndex of 0
37
40
  // This causes some tab focusing issues, most prevelant in MobileStylePanel,
@@ -49,9 +52,25 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
49
52
  )
50
53
 
51
54
  const handlePointerDown = useCallback(() => {
52
- onHistoryMark('click slider')
55
+ tooltipManager.hideAllTooltips()
56
+ onHistoryMark?.('click slider')
53
57
  }, [onHistoryMark])
54
58
 
59
+ // N.B. This is a bit silly. The Radix slider auto-focuses which
60
+ // triggers TldrawUiTooltip handleFocus when we dbl-click to edit an image,
61
+ // which in turn makes the tooltip display prematurely.
62
+ // This makes it wait until we've focused to show the tooltip.
63
+ useEffect(() => {
64
+ const timeout = tltime.setTimeout(
65
+ 'set title and label',
66
+ () => {
67
+ setTitleAndLabel(title + ' — ' + msg(label as TLUiTranslationKey))
68
+ },
69
+ 0
70
+ )
71
+ return () => clearTimeout(timeout)
72
+ }, [label, msg, title])
73
+
55
74
  // N.B. Annoying. For a11y purposes, we need Tab to work.
56
75
  // For some reason, Radix has some custom behavior here
57
76
  // that interferes with tabbing past the slider and then
@@ -64,36 +83,37 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
64
83
 
65
84
  return (
66
85
  <div className="tlui-slider__container">
67
- <_Slider.Root
68
- data-testid={testId}
69
- className="tlui-slider"
70
- dir="ltr"
71
- min={min ?? 0}
72
- max={steps}
73
- step={1}
74
- value={value !== null ? [value] : undefined}
75
- onPointerDown={handlePointerDown}
76
- onValueChange={handleValueChange}
77
- onKeyDownCapture={handleKeyEvent}
78
- onKeyUpCapture={handleKeyEvent}
79
- title={title + ' — ' + msg(label as TLUiTranslationKey)}
80
- >
81
- <_Slider.Track className="tlui-slider__track" dir="ltr">
82
- {value !== null && <_Slider.Range className="tlui-slider__range" dir="ltr" />}
83
- </_Slider.Track>
84
- {value !== null && (
85
- <_Slider.Thumb
86
- aria-valuemin={(min ?? 0) * ariaValueModifier}
87
- aria-valuenow={value * ariaValueModifier}
88
- aria-valuemax={steps * ariaValueModifier}
89
- aria-label={title + ' — ' + msg(label as TLUiTranslationKey)}
90
- className="tlui-slider__thumb"
91
- dir="ltr"
92
- ref={ref}
93
- tabIndex={tabIndex}
94
- />
95
- )}
96
- </_Slider.Root>
86
+ <TldrawUiTooltip content={titleAndLabel}>
87
+ <_Slider.Root
88
+ data-testid={testId}
89
+ className="tlui-slider"
90
+ dir="ltr"
91
+ min={min ?? 0}
92
+ max={steps}
93
+ step={1}
94
+ value={value !== null ? [value] : undefined}
95
+ onPointerDown={handlePointerDown}
96
+ onValueChange={handleValueChange}
97
+ onKeyDownCapture={handleKeyEvent}
98
+ onKeyUpCapture={handleKeyEvent}
99
+ >
100
+ <_Slider.Track className="tlui-slider__track" dir="ltr">
101
+ {value !== null && <_Slider.Range className="tlui-slider__range" dir="ltr" />}
102
+ </_Slider.Track>
103
+ {value !== null && (
104
+ <_Slider.Thumb
105
+ aria-valuemin={(min ?? 0) * ariaValueModifier}
106
+ aria-valuenow={value * ariaValueModifier}
107
+ aria-valuemax={steps * ariaValueModifier}
108
+ aria-label={titleAndLabel}
109
+ className="tlui-slider__thumb"
110
+ dir="ltr"
111
+ ref={ref}
112
+ tabIndex={tabIndex}
113
+ />
114
+ )}
115
+ </_Slider.Root>
116
+ </TldrawUiTooltip>
97
117
  </div>
98
118
  )
99
119
  })
@@ -71,6 +71,7 @@ export const TldrawUiToolbarButton = React.forwardRef<HTMLButtonElement, TLUiToo
71
71
  draggable={false}
72
72
  data-isactive={isActive}
73
73
  {...props}
74
+ aria-label={props.title}
74
75
  // The tooltip takes care of this.
75
76
  title={undefined}
76
77
  className={classnames('tlui-button', `tlui-button__${type}`, props.className)}
@@ -94,6 +95,7 @@ export interface TLUiToolbarToggleGroupProps extends React.HTMLAttributes<HTMLDi
94
95
  // TODO: fix up this type later
95
96
  defaultValue?: any
96
97
  type: 'single' | 'multiple'
98
+ asChild?: boolean
97
99
  }
98
100
 
99
101
  /** @public @react */
@@ -101,10 +103,12 @@ export const TldrawUiToolbarToggleGroup = ({
101
103
  children,
102
104
  className,
103
105
  type,
106
+ asChild,
104
107
  ...props
105
108
  }: TLUiToolbarToggleGroupProps) => {
106
109
  return (
107
110
  <_Toolbar.ToggleGroup
111
+ asChild={asChild}
108
112
  type={type}
109
113
  {...props}
110
114
  // TODO: this fixes a bug in Radix until they fix it.
@@ -124,7 +128,7 @@ export interface TLUiToolbarToggleItemProps extends React.HTMLAttributes<HTMLBut
124
128
  className?: string
125
129
  type: 'icon' | 'tool'
126
130
  value: string
127
- tooltip?: string
131
+ tooltip?: React.ReactNode
128
132
  }
129
133
 
130
134
  /** @public @react */
@@ -6,6 +6,7 @@ import React, {
6
6
  ReactNode,
7
7
  useContext,
8
8
  useEffect,
9
+ useLayoutEffect,
9
10
  useRef,
10
11
  useState,
11
12
  } from 'react'
@@ -24,18 +25,20 @@ export interface TldrawUiTooltipProps {
24
25
  delayDuration?: number
25
26
  }
26
27
 
28
+ interface CurrentTooltip {
29
+ id: string
30
+ content: ReactNode
31
+ side: 'top' | 'right' | 'bottom' | 'left'
32
+ sideOffset: number
33
+ showOnMobile: boolean
34
+ targetElement: HTMLElement
35
+ delayDuration: number
36
+ }
37
+
27
38
  // Singleton tooltip manager
28
39
  class TooltipManager {
29
40
  private static instance: TooltipManager | null = null
30
- private currentTooltip = atom<{
31
- id: string
32
- content: ReactNode
33
- side: 'top' | 'right' | 'bottom' | 'left'
34
- sideOffset: number
35
- showOnMobile: boolean
36
- targetElement: HTMLElement
37
- delayDuration: number | undefined
38
- } | null>('current tooltip', null)
41
+ private currentTooltip = atom<CurrentTooltip | null>('current tooltip', null)
39
42
  private destroyTimeoutId: number | null = null
40
43
 
41
44
  static getInstance(): TooltipManager {
@@ -52,7 +55,7 @@ class TooltipManager {
52
55
  side: 'top' | 'right' | 'bottom' | 'left',
53
56
  sideOffset: number,
54
57
  showOnMobile: boolean,
55
- delayDuration: number | undefined
58
+ delayDuration: number
56
59
  ) {
57
60
  // Clear any existing destroy timeout
58
61
  if (this.destroyTimeoutId) {
@@ -72,6 +75,15 @@ class TooltipManager {
72
75
  })
73
76
  }
74
77
 
78
+ updateCurrentTooltip(tooltipId: string, update: (tooltip: CurrentTooltip) => CurrentTooltip) {
79
+ this.currentTooltip.update((tooltip) => {
80
+ if (tooltip?.id === tooltipId) {
81
+ return update(tooltip)
82
+ }
83
+ return tooltip
84
+ })
85
+ }
86
+
75
87
  hideTooltip(editor: Editor | null, tooltipId: string, instant: boolean = false) {
76
88
  const hide = () => {
77
89
  // Only hide if this is the current tooltip
@@ -139,11 +151,10 @@ export function TldrawUiTooltipProvider({ children }: TldrawUiTooltipProviderPro
139
151
 
140
152
  // The singleton tooltip component that renders once
141
153
  function TooltipSingleton() {
142
- const editor = useMaybeEditor()
143
154
  const [isOpen, setIsOpen] = useState(false)
144
155
  const triggerRef = useRef<HTMLDivElement>(null)
145
156
  const isFirstShowRef = useRef(true)
146
- const showTimeoutRef = useRef<number | null>(null)
157
+ const editor = useMaybeEditor()
147
158
 
148
159
  const currentTooltip = useValue(
149
160
  'current tooltip',
@@ -151,14 +162,32 @@ function TooltipSingleton() {
151
162
  []
152
163
  )
153
164
 
154
- // Update open state and trigger position
165
+ const cameraState = useValue('camera state', () => editor?.getCameraState(), [editor])
166
+
167
+ // Hide tooltip when camera is moving (panning/zooming)
168
+ useEffect(() => {
169
+ if (cameraState === 'moving' && isOpen && currentTooltip) {
170
+ tooltipManager.hideTooltip(editor, currentTooltip.id, true)
171
+ }
172
+ }, [cameraState, isOpen, currentTooltip, editor])
173
+
155
174
  useEffect(() => {
156
- // Clear any existing show timeout
157
- if (showTimeoutRef.current) {
158
- clearTimeout(showTimeoutRef.current)
159
- showTimeoutRef.current = null
175
+ function handleKeyDown(event: KeyboardEvent) {
176
+ if (event.key === 'Escape' && currentTooltip && isOpen) {
177
+ tooltipManager.hideTooltip(editor, currentTooltip.id)
178
+ event.stopPropagation()
179
+ }
180
+ }
181
+
182
+ document.addEventListener('keydown', handleKeyDown, { capture: true })
183
+ return () => {
184
+ document.removeEventListener('keydown', handleKeyDown, { capture: true })
160
185
  }
186
+ }, [editor, currentTooltip, isOpen])
161
187
 
188
+ // Update open state and trigger position
189
+ useEffect(() => {
190
+ let timer: ReturnType<typeof setTimeout> | null = null
162
191
  if (currentTooltip && triggerRef.current) {
163
192
  // Position the invisible trigger element over the active element
164
193
  const activeRect = currentTooltip.targetElement.getBoundingClientRect()
@@ -173,11 +202,12 @@ function TooltipSingleton() {
173
202
  trigger.style.zIndex = '9999'
174
203
 
175
204
  // Handle delay for first show
176
- if (isFirstShowRef.current && editor) {
177
- showTimeoutRef.current = editor.timers.setTimeout(() => {
205
+ if (isFirstShowRef.current) {
206
+ // eslint-disable-next-line no-restricted-globals
207
+ timer = setTimeout(() => {
178
208
  setIsOpen(true)
179
209
  isFirstShowRef.current = false
180
- }, currentTooltip.delayDuration ?? editor.options.tooltipDelayMs)
210
+ }, currentTooltip.delayDuration)
181
211
  } else {
182
212
  // Subsequent tooltips show immediately
183
213
  setIsOpen(true)
@@ -188,7 +218,13 @@ function TooltipSingleton() {
188
218
  // Reset first show state after tooltip is hidden
189
219
  isFirstShowRef.current = true
190
220
  }
191
- }, [editor, currentTooltip])
221
+
222
+ return () => {
223
+ if (timer !== null) {
224
+ clearTimeout(timer)
225
+ }
226
+ }
227
+ }, [currentTooltip])
192
228
 
193
229
  if (!currentTooltip) {
194
230
  return null
@@ -231,6 +267,7 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
231
267
  const editor = useMaybeEditor()
232
268
  const tooltipId = useRef<string>(uniqueId())
233
269
  const hasProvider = useContext(TooltipSingletonContext)
270
+ const showUiLabels = useValue('showUiLabels', () => editor?.user.getShowUiLabels(), [editor])
234
271
 
235
272
  const orientationCtx = useTldrawUiOrientation()
236
273
  const sideToUse = side ?? orientationCtx.tooltipSide
@@ -244,20 +281,35 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
244
281
  }
245
282
  }, [editor, hasProvider])
246
283
 
284
+ useLayoutEffect(() => {
285
+ if (hasProvider && tooltipManager.getCurrentTooltipData()?.id === tooltipId.current) {
286
+ tooltipManager.updateCurrentTooltip(tooltipId.current, (tooltip) => ({
287
+ ...tooltip,
288
+ content,
289
+ side: sideToUse,
290
+ sideOffset,
291
+ showOnMobile,
292
+ }))
293
+ }
294
+ }, [content, sideToUse, sideOffset, showOnMobile, hasProvider])
295
+
247
296
  // Don't show tooltip if disabled, no content, or UI labels are disabled
248
297
  if (disabled || !content) {
249
298
  return <>{children}</>
250
299
  }
251
300
 
301
+ let delayDurationToUse
302
+ if (showUiLabels) {
303
+ delayDurationToUse = 0
304
+ } else {
305
+ delayDurationToUse =
306
+ delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)
307
+ }
308
+
252
309
  // Fallback to old behavior if no provider
253
- if (!hasProvider) {
310
+ if (!hasProvider || showUiLabels) {
254
311
  return (
255
- <_Tooltip.Root
256
- delayDuration={
257
- delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)
258
- }
259
- disableHoverableContent
260
- >
312
+ <_Tooltip.Root delayDuration={delayDurationToUse} disableHoverableContent={!showUiLabels}>
261
313
  <_Tooltip.Trigger asChild ref={ref}>
262
314
  {children}
263
315
  </_Tooltip.Trigger>
@@ -288,7 +340,7 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
288
340
  sideToUse,
289
341
  sideOffset,
290
342
  showOnMobile,
291
- delayDuration
343
+ delayDurationToUse
292
344
  )
293
345
  }
294
346
 
@@ -306,7 +358,7 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
306
358
  sideToUse,
307
359
  sideOffset,
308
360
  showOnMobile,
309
- delayDuration
361
+ delayDurationToUse
310
362
  )
311
363
  }
312
364
 
@@ -19,6 +19,7 @@ export interface TLUiMenuCheckboxItemProps<
19
19
  kbd?: string
20
20
  title?: string
21
21
  label?: TranslationKey | { [key: string]: TranslationKey }
22
+ lang?: string
22
23
  readonlyOk?: boolean
23
24
  onSelect(source: TLUiEventSource): Promise<void> | void
24
25
  toggle?: boolean
@@ -34,6 +35,7 @@ export function TldrawUiMenuCheckboxItem<
34
35
  id,
35
36
  kbd,
36
37
  label,
38
+ lang,
37
39
  readonlyOk,
38
40
  onSelect,
39
41
  toggle = false,
@@ -55,6 +57,7 @@ export function TldrawUiMenuCheckboxItem<
55
57
  return (
56
58
  <_DropdownMenu.CheckboxItem
57
59
  dir="ltr"
60
+ lang={lang}
58
61
  className="tlui-button tlui-button__menu tlui-button__checkbox"
59
62
  title={labelStr}
60
63
  onSelect={(e) => {
@@ -84,6 +87,7 @@ export function TldrawUiMenuCheckboxItem<
84
87
  key={id}
85
88
  className="tlui-button tlui-button__menu tlui-button__checkbox"
86
89
  dir="ltr"
90
+ lang={lang}
87
91
  title={labelStr}
88
92
  onSelect={(e) => {
89
93
  onSelect(sourceId)
@@ -213,7 +213,7 @@ export function TldrawUiMenuItem<
213
213
  icon={icon}
214
214
  onSelect={onSelect}
215
215
  onDragStart={onDragStart}
216
- labelToUse={labelToUse}
216
+ labelStr={labelStr}
217
217
  titleStr={titleStr}
218
218
  disabled={disabled}
219
219
  isSelected={isSelected}
@@ -247,7 +247,7 @@ export function TldrawUiMenuItem<
247
247
  icon={icon}
248
248
  onSelect={onSelect}
249
249
  onDragStart={onDragStart}
250
- labelToUse={labelToUse}
250
+ labelStr={labelStr}
251
251
  titleStr={titleStr}
252
252
  disabled={disabled}
253
253
  isSelected={isSelected}
@@ -333,7 +333,7 @@ function useDraggableEvents(
333
333
  type: 'pointer',
334
334
  target: 'canvas',
335
335
  name: 'pointer_down',
336
- ...getPointerInfo(e),
336
+ ...getPointerInfo(editor, e),
337
337
  point: screenSpaceStart,
338
338
  })
339
339
 
@@ -345,7 +345,7 @@ function useDraggableEvents(
345
345
  type: 'pointer',
346
346
  target: 'canvas',
347
347
  name: 'pointer_move',
348
- ...getPointerInfo(e),
348
+ ...getPointerInfo(editor, e),
349
349
  point: screenSpaceStart,
350
350
  })
351
351
 
@@ -365,7 +365,7 @@ function useDraggableEvents(
365
365
  type: 'pointer',
366
366
  target: 'canvas',
367
367
  name: 'pointer_up',
368
- ...getPointerInfo(e),
368
+ ...getPointerInfo(editor, e),
369
369
  })
370
370
  }
371
371
 
@@ -392,7 +392,7 @@ function useDraggableEvents(
392
392
 
393
393
  function DraggableToolbarButton({
394
394
  id,
395
- labelToUse,
395
+ labelStr,
396
396
  titleStr,
397
397
  disabled,
398
398
  isSelected,
@@ -403,7 +403,7 @@ function DraggableToolbarButton({
403
403
  }: {
404
404
  id: string
405
405
  disabled: boolean
406
- labelToUse?: string
406
+ labelStr?: string
407
407
  titleStr?: string
408
408
  isSelected?: boolean
409
409
  icon: TLUiMenuItemProps['icon']
@@ -416,7 +416,7 @@ function DraggableToolbarButton({
416
416
  if (overflow) {
417
417
  return (
418
418
  <TldrawUiToolbarButton
419
- aria-label={labelToUse}
419
+ aria-label={labelStr}
420
420
  aria-pressed={isSelected ? 'true' : 'false'}
421
421
  isActive={isSelected}
422
422
  className="tlui-button-grid__button"
@@ -434,7 +434,7 @@ function DraggableToolbarButton({
434
434
 
435
435
  return (
436
436
  <TldrawUiToolbarButton
437
- aria-label={labelToUse}
437
+ aria-label={labelStr}
438
438
  aria-pressed={isSelected ? 'true' : 'false'}
439
439
  data-testid={`tools.${id}`}
440
440
  data-value={id}
@@ -36,6 +36,7 @@ import { useTranslation } from '../hooks/useTranslation/useTranslation'
36
36
  import { TLUiIconType } from '../icon-types'
37
37
  import { TLUiOverrideHelpers, useDefaultHelpers } from '../overrides'
38
38
  import { useA11y } from './a11y'
39
+ import { useTldrawUiComponents } from './components'
39
40
  import { TLUiEventSource, useUiEvents } from './events'
40
41
 
41
42
  /** @public */
@@ -98,6 +99,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
98
99
  const _editor = useMaybeEditor()
99
100
  const showCollaborationUi = useShowCollaborationUi()
100
101
  const helpers = useDefaultHelpers()
102
+ const components = useTldrawUiComponents()
101
103
  const trackEvent = useUiEvents()
102
104
  const a11y = useA11y()
103
105
  const msg = useTranslation()
@@ -176,7 +178,9 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
176
178
  kbd: 'cmd+alt+/,ctrl+alt+/',
177
179
  onSelect(source) {
178
180
  trackEvent('open-kbd-shortcuts', { source })
179
- helpers.addDialog({ component: DefaultKeyboardShortcutsDialog })
181
+ helpers.addDialog({
182
+ component: components.KeyboardShortcutsDialog ?? DefaultKeyboardShortcutsDialog,
183
+ })
180
184
  },
181
185
  },
182
186
  {
@@ -221,7 +225,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
221
225
  if (ids.length === 0) ids = Array.from(editor.getCurrentPageShapeIds().values())
222
226
  if (ids.length === 0) return
223
227
  trackEvent('export-as', { format: 'svg', source })
224
- helpers.exportAs(ids, 'svg', getExportName(editor, defaultDocumentName))
228
+ helpers.exportAs(ids, { format: 'svg', name: getExportName(editor, defaultDocumentName) })
225
229
  },
226
230
  },
227
231
  {
@@ -237,7 +241,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
237
241
  if (ids.length === 0) ids = Array.from(editor.getCurrentPageShapeIds().values())
238
242
  if (ids.length === 0) return
239
243
  trackEvent('export-as', { format: 'png', source })
240
- helpers.exportAs(ids, 'png', getExportName(editor, defaultDocumentName))
244
+ helpers.exportAs(ids, { format: 'png', name: getExportName(editor, defaultDocumentName) })
241
245
  },
242
246
  },
243
247
  {
@@ -253,11 +257,10 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
253
257
  if (ids.length === 0) ids = Array.from(editor.getCurrentPageShapeIds().values())
254
258
  if (ids.length === 0) return
255
259
  trackEvent('export-all-as', { format: 'svg', source })
256
- helpers.exportAs(
257
- Array.from(editor.getCurrentPageShapeIds()),
258
- 'svg',
259
- getExportName(editor, defaultDocumentName)
260
- )
260
+ helpers.exportAs(Array.from(editor.getCurrentPageShapeIds()), {
261
+ format: 'svg',
262
+ name: getExportName(editor, defaultDocumentName),
263
+ })
261
264
  },
262
265
  },
263
266
  {
@@ -272,7 +275,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
272
275
  const ids = Array.from(editor.getCurrentPageShapeIds().values())
273
276
  if (ids.length === 0) return
274
277
  trackEvent('export-all-as', { format: 'png', source })
275
- helpers.exportAs(ids, 'png', getExportName(editor, defaultDocumentName))
278
+ helpers.exportAs(ids, { format: 'png', name: getExportName(editor, defaultDocumentName) })
276
279
  },
277
280
  },
278
281
  {
@@ -1581,6 +1584,19 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
1581
1584
  onSelect: async (source) => {
1582
1585
  if (!canApplySelectionAction()) return
1583
1586
 
1587
+ const onlySelectedShape = editor.getOnlySelectedShape()
1588
+ if (
1589
+ onlySelectedShape &&
1590
+ (editor.isShapeOfType<TLImageShape>(onlySelectedShape, 'image') ||
1591
+ editor.isShapeOfType<TLVideoShape>(onlySelectedShape, 'video'))
1592
+ ) {
1593
+ const firstToolbarButton = editor
1594
+ .getContainer()
1595
+ .querySelector('.tlui-contextual-toolbar button:first-child') as HTMLElement | null
1596
+ firstToolbarButton?.focus()
1597
+ return
1598
+ }
1599
+
1584
1600
  const firstButton = editor
1585
1601
  .getContainer()
1586
1602
  .querySelector('.tlui-style-panel button') as HTMLElement | null
@@ -1755,7 +1771,17 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
1755
1771
  }
1756
1772
 
1757
1773
  return actions
1758
- }, [helpers, _editor, trackEvent, overrides, defaultDocumentName, showCollaborationUi, msg, a11y])
1774
+ }, [
1775
+ helpers,
1776
+ _editor,
1777
+ trackEvent,
1778
+ overrides,
1779
+ defaultDocumentName,
1780
+ showCollaborationUi,
1781
+ msg,
1782
+ a11y,
1783
+ components,
1784
+ ])
1759
1785
 
1760
1786
  return <ActionsContext.Provider value={asActions(actions)}>{children}</ActionsContext.Provider>
1761
1787
  }
@@ -12,6 +12,7 @@ import {
12
12
  import { CursorChatBubble } from '../components/CursorChatBubble'
13
13
  import { DefaultDebugMenu } from '../components/DebugMenu/DefaultDebugMenu'
14
14
  import { DefaultDebugPanel } from '../components/DefaultDebugPanel'
15
+ import { DefaultFollowingIndicator } from '../components/DefaultFollowingIndicator'
15
16
  import { DefaultMenuPanel } from '../components/DefaultMenuPanel'
16
17
  import { DefaultDialogs } from '../components/Dialogs'
17
18
  import { TLUiHelpMenuProps } from '../components/HelpMenu/DefaultHelpMenu'
@@ -72,6 +73,7 @@ export interface TLUiComponents {
72
73
  Dialogs?: ComponentType | null
73
74
  Toasts?: ComponentType | null
74
75
  A11y?: ComponentType | null
76
+ FollowingIndicator?: ComponentType | null
75
77
  }
76
78
 
77
79
  const TldrawUiComponentsContext = createContext<TLUiComponents | null>(null)
@@ -119,6 +121,7 @@ export function TldrawUiComponentsProvider({
119
121
  Dialogs: DefaultDialogs,
120
122
  Toasts: DefaultToasts,
121
123
  A11y: DefaultA11yAnnouncer,
124
+ FollowingIndicator: DefaultFollowingIndicator,
122
125
  ..._overrides,
123
126
  }),
124
127
  [_overrides, showCollaborationUi]