tldraw 3.16.0-next.fe14f1b4181f → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) hide show
  1. package/dist-cjs/index.d.ts +232 -114
  2. package/dist-cjs/index.js +30 -15
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/defaultExternalContentHandlers.js +10 -0
  5. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  6. package/dist-cjs/lib/shapes/arrow/arrow-types.js.map +1 -1
  7. package/dist-cjs/lib/shapes/arrow/arrowLabel.js +6 -0
  8. package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +3 -3
  9. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js +3 -2
  10. package/dist-cjs/lib/shapes/arrow/arrowTargetState.js.map +2 -2
  11. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js +1 -1
  12. package/dist-cjs/lib/shapes/arrow/toolStates/Pointing.js.map +2 -2
  13. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +4 -4
  14. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  15. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +5 -1
  16. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  17. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js +8 -2
  18. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js.map +2 -2
  19. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +1 -0
  20. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  21. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +2 -1
  22. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  23. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +4 -4
  24. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js.map +2 -2
  25. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -3
  26. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  27. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +3 -5
  28. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  29. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +0 -2
  30. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
  31. package/dist-cjs/lib/shapes/text/PlainTextArea.js +3 -2
  32. package/dist-cjs/lib/shapes/text/PlainTextArea.js.map +2 -2
  33. package/dist-cjs/lib/shapes/text/RichTextArea.js +3 -3
  34. package/dist-cjs/lib/shapes/text/RichTextArea.js.map +2 -2
  35. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +3 -1
  36. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  37. package/dist-cjs/lib/ui/components/A11y.js +1 -1
  38. package/dist-cjs/lib/ui/components/A11y.js.map +2 -2
  39. package/dist-cjs/lib/ui/components/AccessibilityMenu.js +1 -1
  40. package/dist-cjs/lib/ui/components/AccessibilityMenu.js.map +2 -2
  41. package/dist-cjs/lib/ui/components/InputModeMenu.js +77 -0
  42. package/dist-cjs/lib/ui/components/InputModeMenu.js.map +7 -0
  43. package/dist-cjs/lib/ui/components/LanguageMenu.js +1 -0
  44. package/dist-cjs/lib/ui/components/LanguageMenu.js.map +2 -2
  45. package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js +2 -0
  46. package/dist-cjs/lib/ui/components/MainMenu/DefaultMainMenuContent.js.map +2 -2
  47. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +2 -1
  48. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
  49. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +1 -1
  50. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
  51. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +13 -6
  52. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
  53. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +255 -316
  54. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  55. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js +147 -0
  56. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +7 -0
  57. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js +70 -0
  58. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js.map +7 -0
  59. package/dist-cjs/lib/ui/components/StylePanel/{DoubleDropdownPicker.js → StylePanelDoubleDropdownPicker.js} +23 -22
  60. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +7 -0
  61. package/dist-cjs/lib/ui/components/StylePanel/{DropdownPicker.js → StylePanelDropdownPicker.js} +23 -20
  62. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +7 -0
  63. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js +28 -0
  64. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js.map +7 -0
  65. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +2 -0
  66. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  67. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +38 -9
  68. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  69. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js +15 -3
  70. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js.map +2 -2
  71. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +2 -1
  72. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
  73. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +1 -1
  74. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js.map +2 -2
  75. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js +6 -2
  76. package/dist-cjs/lib/ui/components/Toolbar/ToggleToolLockedButton.js.map +2 -2
  77. package/dist-cjs/lib/ui/components/menu-items.js +6 -4
  78. package/dist-cjs/lib/ui/components/menu-items.js.map +2 -2
  79. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +11 -2
  80. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  81. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +5 -3
  82. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js.map +2 -2
  83. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +13 -2
  84. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  85. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +3 -0
  86. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  87. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +75 -20
  88. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  89. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js +3 -0
  90. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.js.map +2 -2
  91. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +8 -8
  92. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  93. package/dist-cjs/lib/ui/context/actions.js +18 -33
  94. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  95. package/dist-cjs/lib/ui/context/events.js.map +2 -2
  96. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +1 -1
  97. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
  98. package/dist-cjs/lib/ui/hooks/useExportAs.js +3 -2
  99. package/dist-cjs/lib/ui/hooks/useExportAs.js.map +2 -2
  100. package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
  101. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  102. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  103. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +12 -3
  104. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  105. package/dist-cjs/lib/ui/version.js +4 -4
  106. package/dist-cjs/lib/ui/version.js.map +1 -1
  107. package/dist-cjs/lib/utils/export/copyAs.js +1 -2
  108. package/dist-cjs/lib/utils/export/copyAs.js.map +2 -2
  109. package/dist-cjs/lib/utils/export/export.js +0 -20
  110. package/dist-cjs/lib/utils/export/export.js.map +2 -2
  111. package/dist-cjs/lib/utils/export/exportAs.js +1 -2
  112. package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
  113. package/dist-esm/index.d.mts +232 -114
  114. package/dist-esm/index.mjs +61 -30
  115. package/dist-esm/index.mjs.map +2 -2
  116. package/dist-esm/lib/defaultExternalContentHandlers.mjs +10 -0
  117. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  118. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +6 -0
  119. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +3 -3
  120. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs +3 -2
  121. package/dist-esm/lib/shapes/arrow/arrowTargetState.mjs.map +2 -2
  122. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs +1 -1
  123. package/dist-esm/lib/shapes/arrow/toolStates/Pointing.mjs.map +2 -2
  124. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +4 -5
  125. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  126. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +5 -1
  127. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  128. package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs +9 -3
  129. package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs.map +2 -2
  130. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +1 -0
  131. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  132. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +2 -1
  133. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  134. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs +5 -5
  135. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs.map +2 -2
  136. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -3
  137. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  138. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +3 -6
  139. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  140. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +0 -2
  141. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  142. package/dist-esm/lib/shapes/text/PlainTextArea.mjs +4 -3
  143. package/dist-esm/lib/shapes/text/PlainTextArea.mjs.map +2 -2
  144. package/dist-esm/lib/shapes/text/RichTextArea.mjs +3 -4
  145. package/dist-esm/lib/shapes/text/RichTextArea.mjs.map +2 -2
  146. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +3 -1
  147. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  148. package/dist-esm/lib/ui/components/A11y.mjs +1 -2
  149. package/dist-esm/lib/ui/components/A11y.mjs.map +2 -2
  150. package/dist-esm/lib/ui/components/AccessibilityMenu.mjs +3 -3
  151. package/dist-esm/lib/ui/components/AccessibilityMenu.mjs.map +2 -2
  152. package/dist-esm/lib/ui/components/InputModeMenu.mjs +57 -0
  153. package/dist-esm/lib/ui/components/InputModeMenu.mjs.map +7 -0
  154. package/dist-esm/lib/ui/components/LanguageMenu.mjs +1 -0
  155. package/dist-esm/lib/ui/components/LanguageMenu.mjs.map +2 -2
  156. package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs +2 -0
  157. package/dist-esm/lib/ui/components/MainMenu/DefaultMainMenuContent.mjs.map +2 -2
  158. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +2 -1
  159. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
  160. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +1 -2
  161. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
  162. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +18 -7
  163. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
  164. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +257 -320
  165. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  166. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +135 -0
  167. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +7 -0
  168. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +50 -0
  169. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +7 -0
  170. package/dist-esm/lib/ui/components/StylePanel/{DoubleDropdownPicker.mjs → StylePanelDoubleDropdownPicker.mjs} +20 -19
  171. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +7 -0
  172. package/dist-esm/lib/ui/components/StylePanel/{DropdownPicker.mjs → StylePanelDropdownPicker.mjs} +20 -17
  173. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +7 -0
  174. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs +8 -0
  175. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs.map +7 -0
  176. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +2 -0
  177. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  178. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +38 -9
  179. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  180. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs +15 -3
  181. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs.map +2 -2
  182. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +2 -1
  183. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
  184. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +1 -1
  185. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +2 -2
  186. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs +6 -2
  187. package/dist-esm/lib/ui/components/Toolbar/ToggleToolLockedButton.mjs.map +2 -2
  188. package/dist-esm/lib/ui/components/menu-items.mjs +6 -4
  189. package/dist-esm/lib/ui/components/menu-items.mjs.map +2 -2
  190. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +11 -3
  191. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  192. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs +6 -4
  193. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs.map +2 -2
  194. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +13 -2
  195. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  196. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +3 -0
  197. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  198. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +76 -20
  199. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  200. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs +3 -0
  201. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs.map +2 -2
  202. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +8 -8
  203. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  204. package/dist-esm/lib/ui/context/actions.mjs +18 -33
  205. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  206. package/dist-esm/lib/ui/context/events.mjs.map +2 -2
  207. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +1 -2
  208. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
  209. package/dist-esm/lib/ui/hooks/useExportAs.mjs +3 -2
  210. package/dist-esm/lib/ui/hooks/useExportAs.mjs.map +2 -2
  211. package/dist-esm/lib/ui/hooks/useTools.mjs +1 -1
  212. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  213. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +12 -3
  214. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  215. package/dist-esm/lib/ui/version.mjs +4 -4
  216. package/dist-esm/lib/ui/version.mjs.map +1 -1
  217. package/dist-esm/lib/utils/export/copyAs.mjs +1 -2
  218. package/dist-esm/lib/utils/export/copyAs.mjs.map +2 -2
  219. package/dist-esm/lib/utils/export/export.mjs +0 -20
  220. package/dist-esm/lib/utils/export/export.mjs.map +2 -2
  221. package/dist-esm/lib/utils/export/exportAs.mjs +1 -2
  222. package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
  223. package/package.json +3 -3
  224. package/src/index.ts +46 -22
  225. package/src/lib/defaultExternalContentHandlers.ts +14 -0
  226. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +83 -13
  227. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +99 -5
  228. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +41 -0
  229. package/src/lib/shapes/arrow/arrow-types.ts +3 -5
  230. package/src/lib/shapes/arrow/arrowLabel.ts +8 -0
  231. package/src/lib/shapes/arrow/arrowTargetState.ts +34 -3
  232. package/src/lib/shapes/arrow/toolStates/Pointing.tsx +1 -1
  233. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +4 -5
  234. package/src/lib/shapes/frame/FrameShapeUtil.tsx +5 -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/note/NoteShapeUtil.tsx +1 -0
  238. package/src/lib/shapes/shared/HyperlinkButton.tsx +5 -5
  239. package/src/lib/shapes/shared/PlainTextLabel.tsx +0 -6
  240. package/src/lib/shapes/shared/useEditablePlainText.ts +3 -10
  241. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +0 -7
  242. package/src/lib/shapes/text/PlainTextArea.tsx +4 -3
  243. package/src/lib/shapes/text/RichTextArea.tsx +3 -4
  244. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +6 -2
  245. package/src/lib/ui/components/A11y.tsx +1 -2
  246. package/src/lib/ui/components/AccessibilityMenu.tsx +2 -2
  247. package/src/lib/ui/components/InputModeMenu.tsx +65 -0
  248. package/src/lib/ui/components/LanguageMenu.tsx +1 -0
  249. package/src/lib/ui/components/MainMenu/DefaultMainMenuContent.tsx +4 -0
  250. package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +2 -1
  251. package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +1 -2
  252. package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +30 -14
  253. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +262 -381
  254. package/src/lib/ui/components/{primitives/TldrawUiButtonPicker.tsx → StylePanel/StylePanelButtonPicker.tsx} +70 -50
  255. package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +65 -0
  256. package/src/lib/ui/components/StylePanel/{DoubleDropdownPicker.tsx → StylePanelDoubleDropdownPicker.tsx} +28 -19
  257. package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +119 -0
  258. package/src/lib/ui/components/StylePanel/StylePanelSubheading.tsx +9 -0
  259. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +2 -0
  260. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +32 -15
  261. package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
  262. package/src/lib/ui/components/Toolbar/LinkEditor.tsx +1 -0
  263. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +1 -1
  264. package/src/lib/ui/components/Toolbar/ToggleToolLockedButton.tsx +9 -2
  265. package/src/lib/ui/components/menu-items.tsx +5 -3
  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 +19 -4
  269. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +5 -1
  270. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +75 -14
  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 +25 -35
  274. package/src/lib/ui/context/events.tsx +3 -2
  275. package/src/lib/ui/hooks/useClipboardEvents.ts +1 -2
  276. package/src/lib/ui/hooks/useExportAs.ts +3 -2
  277. package/src/lib/ui/hooks/useTools.tsx +1 -1
  278. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +11 -2
  279. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +12 -3
  280. package/src/lib/ui/version.ts +4 -4
  281. package/src/lib/ui.css +41 -4
  282. package/src/lib/utils/export/copyAs.ts +1 -24
  283. package/src/lib/utils/export/export.ts +0 -36
  284. package/src/lib/utils/export/exportAs.ts +1 -32
  285. package/src/test/TestEditor.ts +8 -2
  286. package/src/test/commands/setCamera.test.ts +13 -0
  287. package/src/test/custom-clipping.test.ts +436 -0
  288. package/src/test/frames.test.ts +15 -0
  289. package/src/test/getCulledShapes.test.tsx +71 -2
  290. package/tldraw.css +49 -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/StylePanel/DoubleDropdownPicker.mjs.map +0 -7
  296. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +0 -7
  297. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +0 -115
  298. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +0 -7
  299. 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,3 +1,4 @@
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'
@@ -12,7 +13,7 @@ export interface TLUiSliderProps {
12
13
  label: string
13
14
  title: string
14
15
  onValueChange(value: number): void
15
- onHistoryMark(id: string): void
16
+ onHistoryMark?(id: string): void
16
17
  'data-testid'?: string
17
18
  ariaValueModifier?: number
18
19
  }
@@ -33,6 +34,7 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
33
34
  ref
34
35
  ) {
35
36
  const msg = useTranslation()
37
+ const [titleAndLabel, setTitleAndLabel] = useState('')
36
38
 
37
39
  // XXX: Radix starts out our slider with a tabIndex of 0
38
40
  // This causes some tab focusing issues, most prevelant in MobileStylePanel,
@@ -51,9 +53,24 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
51
53
 
52
54
  const handlePointerDown = useCallback(() => {
53
55
  tooltipManager.hideAllTooltips()
54
- onHistoryMark('click slider')
56
+ onHistoryMark?.('click slider')
55
57
  }, [onHistoryMark])
56
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
+
57
74
  // N.B. Annoying. For a11y purposes, we need Tab to work.
58
75
  // For some reason, Radix has some custom behavior here
59
76
  // that interferes with tabbing past the slider and then
@@ -64,8 +81,6 @@ export const TldrawUiSlider = React.forwardRef<HTMLDivElement, TLUiSliderProps>(
64
81
  }
65
82
  }, [])
66
83
 
67
- const titleAndLabel = title + ' — ' + msg(label as TLUiTranslationKey)
68
-
69
84
  return (
70
85
  <div className="tlui-slider__container">
71
86
  <TldrawUiTooltip content={titleAndLabel}>
@@ -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
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 {
@@ -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
@@ -142,6 +154,7 @@ function TooltipSingleton() {
142
154
  const [isOpen, setIsOpen] = useState(false)
143
155
  const triggerRef = useRef<HTMLDivElement>(null)
144
156
  const isFirstShowRef = useRef(true)
157
+ const editor = useMaybeEditor()
145
158
 
146
159
  const currentTooltip = useValue(
147
160
  'current tooltip',
@@ -149,6 +162,29 @@ function TooltipSingleton() {
149
162
  []
150
163
  )
151
164
 
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
+
174
+ useEffect(() => {
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 })
185
+ }
186
+ }, [editor, currentTooltip, isOpen])
187
+
152
188
  // Update open state and trigger position
153
189
  useEffect(() => {
154
190
  let timer: ReturnType<typeof setTimeout> | null = null
@@ -231,6 +267,11 @@ 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 enhancedA11yMode = useValue(
271
+ 'enhancedA11yMode',
272
+ () => editor?.user.getEnhancedA11yMode(),
273
+ [editor]
274
+ )
234
275
 
235
276
  const orientationCtx = useTldrawUiOrientation()
236
277
  const sideToUse = side ?? orientationCtx.tooltipSide
@@ -244,18 +285,38 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
244
285
  }
245
286
  }, [editor, hasProvider])
246
287
 
247
- // Don't show tooltip if disabled, no content, or UI labels are disabled
288
+ useLayoutEffect(() => {
289
+ if (hasProvider && tooltipManager.getCurrentTooltipData()?.id === tooltipId.current) {
290
+ tooltipManager.updateCurrentTooltip(tooltipId.current, (tooltip) => ({
291
+ ...tooltip,
292
+ content,
293
+ side: sideToUse,
294
+ sideOffset,
295
+ showOnMobile,
296
+ }))
297
+ }
298
+ }, [content, sideToUse, sideOffset, showOnMobile, hasProvider])
299
+
300
+ // Don't show tooltip if disabled, no content, or enhanced accessibility mode is disabled
248
301
  if (disabled || !content) {
249
302
  return <>{children}</>
250
303
  }
251
304
 
252
- const delayDurationToUse =
253
- delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)
305
+ let delayDurationToUse
306
+ if (enhancedA11yMode) {
307
+ delayDurationToUse = 0
308
+ } else {
309
+ delayDurationToUse =
310
+ delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)
311
+ }
254
312
 
255
313
  // Fallback to old behavior if no provider
256
- if (!hasProvider) {
314
+ if (!hasProvider || enhancedA11yMode) {
257
315
  return (
258
- <_Tooltip.Root delayDuration={delayDurationToUse} disableHoverableContent>
316
+ <_Tooltip.Root
317
+ delayDuration={delayDurationToUse}
318
+ disableHoverableContent={!enhancedA11yMode}
319
+ >
259
320
  <_Tooltip.Trigger asChild ref={ref}>
260
321
  {children}
261
322
  </_Tooltip.Trigger>
@@ -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}
@@ -225,7 +225,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
225
225
  if (ids.length === 0) ids = Array.from(editor.getCurrentPageShapeIds().values())
226
226
  if (ids.length === 0) return
227
227
  trackEvent('export-as', { format: 'svg', source })
228
- helpers.exportAs(ids, 'svg', getExportName(editor, defaultDocumentName))
228
+ helpers.exportAs(ids, { format: 'svg', name: getExportName(editor, defaultDocumentName) })
229
229
  },
230
230
  },
231
231
  {
@@ -241,7 +241,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
241
241
  if (ids.length === 0) ids = Array.from(editor.getCurrentPageShapeIds().values())
242
242
  if (ids.length === 0) return
243
243
  trackEvent('export-as', { format: 'png', source })
244
- helpers.exportAs(ids, 'png', getExportName(editor, defaultDocumentName))
244
+ helpers.exportAs(ids, { format: 'png', name: getExportName(editor, defaultDocumentName) })
245
245
  },
246
246
  },
247
247
  {
@@ -257,11 +257,10 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
257
257
  if (ids.length === 0) ids = Array.from(editor.getCurrentPageShapeIds().values())
258
258
  if (ids.length === 0) return
259
259
  trackEvent('export-all-as', { format: 'svg', source })
260
- helpers.exportAs(
261
- Array.from(editor.getCurrentPageShapeIds()),
262
- 'svg',
263
- getExportName(editor, defaultDocumentName)
264
- )
260
+ helpers.exportAs(Array.from(editor.getCurrentPageShapeIds()), {
261
+ format: 'svg',
262
+ name: getExportName(editor, defaultDocumentName),
263
+ })
265
264
  },
266
265
  },
267
266
  {
@@ -276,7 +275,7 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
276
275
  const ids = Array.from(editor.getCurrentPageShapeIds().values())
277
276
  if (ids.length === 0) return
278
277
  trackEvent('export-all-as', { format: 'png', source })
279
- helpers.exportAs(ids, 'png', getExportName(editor, defaultDocumentName))
278
+ helpers.exportAs(ids, { format: 'png', name: getExportName(editor, defaultDocumentName) })
280
279
  },
281
280
  },
282
281
  {
@@ -1271,16 +1270,16 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
1271
1270
  checkbox: true,
1272
1271
  },
1273
1272
  {
1274
- id: 'toggle-ui-labels',
1273
+ id: 'enhanced-a11y-mode',
1275
1274
  label: {
1276
- default: 'action.toggle-ui-labels',
1277
- menu: 'action.toggle-ui-labels.menu',
1275
+ default: 'action.enhanced-a11y-mode',
1276
+ menu: 'action.enhanced-a11y-mode.menu',
1278
1277
  },
1279
1278
  readonlyOk: true,
1280
1279
  onSelect(source) {
1281
- trackEvent('toggle-ui-labels', { source })
1280
+ trackEvent('enhanced-a11y-mode', { source })
1282
1281
  editor.user.updateUserPreferences({
1283
- showUiLabels: !editor.user.getShowUiLabels(),
1282
+ enhancedA11yMode: !editor.user.getEnhancedA11yMode(),
1284
1283
  })
1285
1284
  },
1286
1285
  checkbox: true,
@@ -1345,28 +1344,6 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
1345
1344
  }
1346
1345
  },
1347
1346
  },
1348
- {
1349
- id: 'toggle-focus-mode',
1350
- label: {
1351
- default: 'action.toggle-focus-mode',
1352
- menu: 'action.toggle-focus-mode.menu',
1353
- },
1354
- readonlyOk: true,
1355
- kbd: 'cmd+.,ctrl+.',
1356
- checkbox: true,
1357
- onSelect(source) {
1358
- // this needs to be deferred because it causes the menu
1359
- // UI to unmount which puts us in a dodgy state
1360
- editor.timers.requestAnimationFrame(() => {
1361
- editor.run(() => {
1362
- trackEvent('toggle-focus-mode', { source })
1363
- helpers.clearDialogs()
1364
- helpers.clearToasts()
1365
- editor.updateInstanceState({ isFocusMode: !editor.getInstanceState().isFocusMode })
1366
- })
1367
- })
1368
- },
1369
- },
1370
1347
  {
1371
1348
  id: 'toggle-grid',
1372
1349
  label: {
@@ -1585,6 +1562,19 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
1585
1562
  onSelect: async (source) => {
1586
1563
  if (!canApplySelectionAction()) return
1587
1564
 
1565
+ const onlySelectedShape = editor.getOnlySelectedShape()
1566
+ if (
1567
+ onlySelectedShape &&
1568
+ (editor.isShapeOfType<TLImageShape>(onlySelectedShape, 'image') ||
1569
+ editor.isShapeOfType<TLVideoShape>(onlySelectedShape, 'video'))
1570
+ ) {
1571
+ const firstToolbarButton = editor
1572
+ .getContainer()
1573
+ .querySelector('.tlui-contextual-toolbar button:first-child') as HTMLElement | null
1574
+ firstToolbarButton?.focus()
1575
+ return
1576
+ }
1577
+
1588
1578
  const firstButton = editor
1589
1579
  .getContainer()
1590
1580
  .querySelector('.tlui-style-panel button') as HTMLElement | null
@@ -102,13 +102,14 @@ export interface TLUiEventMap {
102
102
  'toggle-grid-mode': null
103
103
  'toggle-wrap-mode': null
104
104
  'toggle-focus-mode': null
105
+ 'input-mode': { value: string }
105
106
  'toggle-debug-mode': null
106
107
  'toggle-dynamic-size-mode': null
107
108
  'toggle-paste-at-cursor': null
108
109
  'toggle-lock': null
109
110
  'toggle-reduce-motion': null
110
111
  'toggle-keyboard-shortcuts': null
111
- 'toggle-ui-labels': null
112
+ 'enhanced-a11y-mode': null
112
113
  'toggle-edge-scrolling': null
113
114
  'color-scheme': { value: string }
114
115
  'exit-pen-mode': null
@@ -123,7 +124,7 @@ export interface TLUiEventMap {
123
124
  'shrink-shapes': null
124
125
  'flatten-to-image': null
125
126
  'a11y-repeat-shape-announce': null
126
- 'open-url': { url: string }
127
+ 'open-url': { destinationUrl: string }
127
128
  'open-context-menu': null
128
129
  'adjust-shape-styles': null
129
130
  'copy-link': null
@@ -8,7 +8,6 @@ import {
8
8
  compact,
9
9
  isDefined,
10
10
  preventDefault,
11
- stopEventPropagation,
12
11
  uniq,
13
12
  useEditor,
14
13
  useMaybeEditor,
@@ -763,7 +762,7 @@ export function useNativeClipboardEvents() {
763
762
 
764
763
  const paste = (e: ClipboardEvent) => {
765
764
  if (disablingMiddleClickPaste) {
766
- stopEventPropagation(e)
765
+ editor.markEventAsHandled(e)
767
766
  return
768
767
  }
769
768
 
@@ -11,12 +11,13 @@ export function useExportAs() {
11
11
  const msg = useTranslation()
12
12
 
13
13
  return useCallback(
14
- (ids: TLShapeId[], format: TLExportType = 'png', name: string | undefined) => {
14
+ (ids: TLShapeId[], opts: { format?: TLExportType; name?: string; scale?: number } = {}) => {
15
15
  assert(editor, 'useExportAs: editor is required')
16
+ const { format = 'png', name, scale = 1 } = opts
16
17
  exportAs(editor, ids, {
17
18
  format,
18
19
  name,
19
- scale: 1,
20
+ scale,
20
21
  }).catch((e) => {
21
22
  console.error(e.message)
22
23
  addToast({
@@ -176,7 +176,7 @@ export function ToolsProvider({ overrides, children }: TLUiToolsProviderProps) {
176
176
  editor.createShape({
177
177
  id,
178
178
  type: 'arrow',
179
- props: { start: { x: 0, y: 0 }, end: { x: 200, y: 0 } },
179
+ props: { start: { x: 0, y: 200 }, end: { x: 200, y: 0 } },
180
180
  }),
181
181
  })
182
182
  trackEvent('drag-tool', { source, id: 'arrow' })
@@ -3,6 +3,11 @@
3
3
 
4
4
  /** @public */
5
5
  export type TLUiTranslationKey =
6
+ | 'action.toggle-auto-pan'
7
+ | 'action.toggle-auto-zoom'
8
+ | 'action.toggle-auto-none'
9
+ | 'action.toggle-mouse'
10
+ | 'action.toggle-trackpad'
6
11
  | 'action.convert-to-bookmark'
7
12
  | 'action.convert-to-embed'
8
13
  | 'action.open-embed-link'
@@ -93,8 +98,8 @@ export type TLUiTranslationKey =
93
98
  | 'action.toggle-reduce-motion'
94
99
  | 'action.toggle-keyboard-shortcuts.menu'
95
100
  | 'action.toggle-keyboard-shortcuts'
96
- | 'action.toggle-ui-labels.menu'
97
- | 'action.toggle-ui-labels'
101
+ | 'action.enhanced-a11y-mode.menu'
102
+ | 'action.enhanced-a11y-mode'
98
103
  | 'action.toggle-edge-scrolling.menu'
99
104
  | 'action.toggle-edge-scrolling'
100
105
  | 'action.toggle-debug-mode.menu'
@@ -122,6 +127,7 @@ export type TLUiTranslationKey =
122
127
  | 'action.zoom-to-fit'
123
128
  | 'action.zoom-to-selection'
124
129
  | 'assets.files.size-too-big'
130
+ | 'assets.files.maximum-size'
125
131
  | 'assets.files.type-not-allowed'
126
132
  | 'assets.files.upload-failed'
127
133
  | 'assets.files.amount-too-many'
@@ -261,6 +267,7 @@ export type TLUiTranslationKey =
261
267
  | 'tool.aspect-ratio.wide'
262
268
  | 'tool.image-toolbar-title'
263
269
  | 'tool.image-crop'
270
+ | 'tool.image-crop-confirm'
264
271
  | 'tool.media-alt-text'
265
272
  | 'tool.media-alt-text-desc'
266
273
  | 'tool.media-alt-text-confirm'
@@ -309,6 +316,7 @@ export type TLUiTranslationKey =
309
316
  | 'menu.language'
310
317
  | 'menu.preferences'
311
318
  | 'menu.view'
319
+ | 'menu.input-mode'
312
320
  | 'context-menu.title'
313
321
  | 'context-menu.edit'
314
322
  | 'context-menu.arrange'
@@ -410,6 +418,7 @@ export type TLUiTranslationKey =
410
418
  | 'style-panel.opacity'
411
419
  | 'style-panel.size'
412
420
  | 'style-panel.spline'
421
+ | 'style-panel.selected'
413
422
  | 'tool-panel.title'
414
423
  | 'tool-panel.more'
415
424
  | 'navigation-zone.title'