tldraw 3.16.0-internal.51e99e128bd4 → 3.16.0-internal.71f83a8a571b

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 (310) hide show
  1. package/dist-cjs/index.d.ts +177 -110
  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 +5 -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/arrow/arrowTargetState.js.map +2 -2
  11. package/dist-cjs/lib/shapes/arrow/elbow/elbowArrowSnapLines.js.map +1 -1
  12. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +4 -4
  13. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  14. package/dist-cjs/lib/shapes/frame/FrameShapeTool.js.map +1 -1
  15. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +8 -1
  16. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  17. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js +2 -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/image/ImageShapeUtil.js +3 -0
  22. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
  23. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +2 -1
  24. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  25. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +4 -4
  26. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js.map +2 -2
  27. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -3
  28. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  29. package/dist-cjs/lib/shapes/shared/RichTextLabel.js.map +2 -2
  30. package/dist-cjs/lib/shapes/shared/crop.js +1 -0
  31. package/dist-cjs/lib/shapes/shared/crop.js.map +2 -2
  32. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +3 -4
  33. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  34. package/dist-cjs/lib/shapes/shared/useEditableRichText.js.map +2 -2
  35. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +0 -2
  36. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
  37. package/dist-cjs/lib/shapes/text/PlainTextArea.js +2 -2
  38. package/dist-cjs/lib/shapes/text/PlainTextArea.js.map +2 -2
  39. package/dist-cjs/lib/shapes/text/RichTextArea.js +3 -3
  40. package/dist-cjs/lib/shapes/text/RichTextArea.js.map +2 -2
  41. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js +1 -1
  42. package/dist-cjs/lib/tools/SelectTool/childStates/DraggingHandle.js.map +2 -2
  43. package/dist-cjs/lib/ui/TldrawUi.js +13 -12
  44. package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
  45. package/dist-cjs/lib/ui/components/A11y.js +1 -1
  46. package/dist-cjs/lib/ui/components/A11y.js.map +2 -2
  47. package/dist-cjs/lib/ui/components/{FollowingIndicator.js → DefaultFollowingIndicator.js} +6 -6
  48. package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +7 -0
  49. package/dist-cjs/lib/ui/components/EditLinkDialog.js +11 -1
  50. package/dist-cjs/lib/ui/components/EditLinkDialog.js.map +2 -2
  51. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +6 -6
  52. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
  53. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js +1 -1
  54. package/dist-cjs/lib/ui/components/PageMenu/DefaultPageMenu.js.map +2 -2
  55. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +9 -4
  56. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
  57. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +255 -316
  58. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  59. package/dist-cjs/lib/ui/components/{primitives/TldrawUiButtonPicker.js → StylePanel/StylePanelButtonPicker.js} +52 -45
  60. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +7 -0
  61. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js +68 -0
  62. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js.map +7 -0
  63. package/dist-cjs/lib/ui/components/StylePanel/{DoubleDropdownPicker.js → StylePanelDoubleDropdownPicker.js} +23 -22
  64. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +7 -0
  65. package/dist-cjs/lib/ui/components/StylePanel/{DropdownPicker.js → StylePanelDropdownPicker.js} +24 -21
  66. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +7 -0
  67. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js +28 -0
  68. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js.map +7 -0
  69. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +3 -2
  70. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  71. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +38 -9
  72. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  73. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js +15 -3
  74. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js.map +2 -2
  75. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +3 -3
  76. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
  77. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +11 -2
  78. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  79. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js +2 -2
  80. package/dist-cjs/lib/ui/components/primitives/TldrawUiInput.js.map +2 -2
  81. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +18 -5
  82. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  83. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +2 -0
  84. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  85. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +62 -36
  86. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  87. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +5 -5
  88. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +1 -1
  89. package/dist-cjs/lib/ui/context/actions.js +23 -10
  90. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  91. package/dist-cjs/lib/ui/context/components.js +2 -0
  92. package/dist-cjs/lib/ui/context/components.js.map +2 -2
  93. package/dist-cjs/lib/ui/context/events.js.map +1 -1
  94. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +1 -1
  95. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
  96. package/dist-cjs/lib/ui/hooks/useExportAs.js +3 -2
  97. package/dist-cjs/lib/ui/hooks/useExportAs.js.map +2 -2
  98. package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
  99. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  100. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  101. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +4 -2
  102. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  103. package/dist-cjs/lib/ui/kbd-utils.js +9 -3
  104. package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
  105. package/dist-cjs/lib/ui/version.js +3 -3
  106. package/dist-cjs/lib/ui/version.js.map +1 -1
  107. package/dist-cjs/lib/utils/excalidraw/putExcalidrawContent.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 +177 -110
  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 +5 -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/arrow/arrowTargetState.mjs.map +2 -2
  124. package/dist-esm/lib/shapes/arrow/elbow/elbowArrowSnapLines.mjs.map +1 -1
  125. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +5 -5
  126. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  127. package/dist-esm/lib/shapes/frame/FrameShapeTool.mjs.map +1 -1
  128. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +8 -1
  129. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  130. package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs +3 -3
  131. package/dist-esm/lib/shapes/frame/components/FrameLabelInput.mjs.map +2 -2
  132. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs +1 -0
  133. package/dist-esm/lib/shapes/geo/GeoShapeUtil.mjs.map +2 -2
  134. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -0
  135. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
  136. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs +2 -1
  137. package/dist-esm/lib/shapes/note/NoteShapeUtil.mjs.map +2 -2
  138. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs +5 -5
  139. package/dist-esm/lib/shapes/shared/HyperlinkButton.mjs.map +2 -2
  140. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -3
  141. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  142. package/dist-esm/lib/shapes/shared/RichTextLabel.mjs.map +2 -2
  143. package/dist-esm/lib/shapes/shared/crop.mjs +1 -0
  144. package/dist-esm/lib/shapes/shared/crop.mjs.map +2 -2
  145. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +4 -5
  146. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  147. package/dist-esm/lib/shapes/shared/useEditableRichText.mjs.map +2 -2
  148. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +0 -2
  149. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  150. package/dist-esm/lib/shapes/text/PlainTextArea.mjs +3 -3
  151. package/dist-esm/lib/shapes/text/PlainTextArea.mjs.map +2 -2
  152. package/dist-esm/lib/shapes/text/RichTextArea.mjs +3 -4
  153. package/dist-esm/lib/shapes/text/RichTextArea.mjs.map +2 -2
  154. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs +1 -1
  155. package/dist-esm/lib/tools/SelectTool/childStates/DraggingHandle.mjs.map +2 -2
  156. package/dist-esm/lib/ui/TldrawUi.mjs +13 -12
  157. package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
  158. package/dist-esm/lib/ui/components/A11y.mjs +2 -2
  159. package/dist-esm/lib/ui/components/A11y.mjs.map +2 -2
  160. package/dist-esm/lib/ui/components/{FollowingIndicator.mjs → DefaultFollowingIndicator.mjs} +3 -3
  161. package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +7 -0
  162. package/dist-esm/lib/ui/components/EditLinkDialog.mjs +11 -1
  163. package/dist-esm/lib/ui/components/EditLinkDialog.mjs.map +2 -2
  164. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +6 -6
  165. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
  166. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +2 -2
  167. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
  168. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +14 -5
  169. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
  170. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +257 -320
  171. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  172. package/dist-esm/lib/ui/components/{primitives/TldrawUiButtonPicker.mjs → StylePanel/StylePanelButtonPicker.mjs} +54 -43
  173. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +7 -0
  174. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +48 -0
  175. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +7 -0
  176. package/dist-esm/lib/ui/components/StylePanel/{DoubleDropdownPicker.mjs → StylePanelDoubleDropdownPicker.mjs} +20 -19
  177. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +7 -0
  178. package/dist-esm/lib/ui/components/StylePanel/{DropdownPicker.mjs → StylePanelDropdownPicker.mjs} +21 -18
  179. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +7 -0
  180. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs +8 -0
  181. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs.map +7 -0
  182. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +3 -2
  183. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  184. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +38 -9
  185. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  186. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs +15 -3
  187. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs.map +2 -2
  188. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +3 -3
  189. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
  190. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +12 -3
  191. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  192. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs +3 -3
  193. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs.map +2 -2
  194. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +18 -5
  195. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  196. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +2 -0
  197. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  198. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +63 -36
  199. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  200. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +5 -5
  201. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +1 -1
  202. package/dist-esm/lib/ui/context/actions.mjs +23 -10
  203. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  204. package/dist-esm/lib/ui/context/components.mjs +2 -0
  205. package/dist-esm/lib/ui/context/components.mjs.map +2 -2
  206. package/dist-esm/lib/ui/context/events.mjs.map +1 -1
  207. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +2 -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 +4 -2
  214. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  215. package/dist-esm/lib/ui/kbd-utils.mjs +9 -3
  216. package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
  217. package/dist-esm/lib/ui/version.mjs +3 -3
  218. package/dist-esm/lib/ui/version.mjs.map +1 -1
  219. package/dist-esm/lib/utils/excalidraw/putExcalidrawContent.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 +12 -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/arrow/arrowTargetState.ts +1 -1
  234. package/src/lib/shapes/arrow/elbow/elbowArrowSnapLines.tsx +2 -2
  235. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +5 -5
  236. package/src/lib/shapes/frame/FrameShapeTool.ts +1 -1
  237. package/src/lib/shapes/frame/FrameShapeUtil.tsx +9 -0
  238. package/src/lib/shapes/frame/components/FrameLabelInput.tsx +3 -3
  239. package/src/lib/shapes/geo/GeoShapeUtil.tsx +1 -0
  240. package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -0
  241. package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -4
  242. package/src/lib/shapes/note/NoteShapeTool.test.ts +2 -1
  243. package/src/lib/shapes/note/NoteShapeUtil.tsx +1 -0
  244. package/src/lib/shapes/shared/HyperlinkButton.tsx +5 -5
  245. package/src/lib/shapes/shared/PlainTextLabel.tsx +2 -7
  246. package/src/lib/shapes/shared/RichTextLabel.tsx +2 -1
  247. package/src/lib/shapes/shared/crop.ts +1 -0
  248. package/src/lib/shapes/shared/useEditablePlainText.ts +12 -12
  249. package/src/lib/shapes/shared/useEditableRichText.ts +7 -3
  250. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +0 -7
  251. package/src/lib/shapes/text/PlainTextArea.tsx +3 -3
  252. package/src/lib/shapes/text/RichTextArea.tsx +3 -4
  253. package/src/lib/tools/SelectTool/childStates/DraggingHandle.tsx +1 -1
  254. package/src/lib/ui/TldrawUi.tsx +16 -10
  255. package/src/lib/ui/components/A11y.tsx +2 -2
  256. package/src/lib/ui/components/{FollowingIndicator.tsx → DefaultFollowingIndicator.tsx} +2 -1
  257. package/src/lib/ui/components/EditLinkDialog.tsx +16 -6
  258. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +6 -6
  259. package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +2 -2
  260. package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +27 -13
  261. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +260 -381
  262. package/src/lib/ui/components/{primitives/TldrawUiButtonPicker.tsx → StylePanel/StylePanelButtonPicker.tsx} +63 -50
  263. package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +63 -0
  264. package/src/lib/ui/components/StylePanel/{DoubleDropdownPicker.tsx → StylePanelDoubleDropdownPicker.tsx} +28 -19
  265. package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +119 -0
  266. package/src/lib/ui/components/StylePanel/StylePanelSubheading.tsx +9 -0
  267. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +5 -4
  268. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +32 -15
  269. package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
  270. package/src/lib/ui/components/Toolbar/LinkEditor.tsx +5 -5
  271. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +8 -3
  272. package/src/lib/ui/components/primitives/TldrawUiInput.tsx +3 -3
  273. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +52 -32
  274. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +3 -0
  275. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +67 -29
  276. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +6 -6
  277. package/src/lib/ui/context/actions.tsx +23 -10
  278. package/src/lib/ui/context/components.tsx +3 -0
  279. package/src/lib/ui/context/events.tsx +1 -1
  280. package/src/lib/ui/hooks/useClipboardEvents.ts +2 -2
  281. package/src/lib/ui/hooks/useExportAs.ts +3 -2
  282. package/src/lib/ui/hooks/useTools.tsx +1 -1
  283. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +2 -0
  284. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +4 -2
  285. package/src/lib/ui/kbd-utils.ts +10 -3
  286. package/src/lib/ui/version.ts +3 -3
  287. package/src/lib/ui.css +19 -2
  288. package/src/lib/utils/excalidraw/putExcalidrawContent.ts +6 -6
  289. package/src/lib/utils/export/copyAs.ts +1 -24
  290. package/src/lib/utils/export/export.ts +0 -36
  291. package/src/lib/utils/export/exportAs.ts +1 -32
  292. package/src/test/Editor.test.tsx +37 -10
  293. package/src/test/TldrawEditor.test.tsx +15 -9
  294. package/src/test/commands/putContent.test.ts +1 -0
  295. package/src/test/commands/updateShapes.test.ts +9 -5
  296. package/src/test/custom-clipping.test.ts +442 -0
  297. package/src/test/customSnapping.test.tsx +55 -41
  298. package/src/test/getCulledShapes.test.tsx +77 -2
  299. package/src/test/groups.test.tsx +4 -2
  300. package/src/test/translating.test.ts +2 -2
  301. package/tldraw.css +35 -5
  302. package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
  303. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +0 -7
  304. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +0 -7
  305. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +0 -7
  306. package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
  307. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +0 -7
  308. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +0 -7
  309. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +0 -7
  310. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +0 -110
@@ -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'
@@ -118,7 +118,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
118
118
  // `onChange` with a duplicated text value.
119
119
  if (isComposing.current) return
120
120
  e.currentTarget.blur()
121
- stopEventPropagation(e)
121
+ e.stopPropagation()
122
122
  onComplete?.(e.currentTarget.value)
123
123
  break
124
124
  }
@@ -126,7 +126,7 @@ export const TldrawUiInput = React.forwardRef<HTMLInputElement, TLUiInputProps>(
126
126
  e.currentTarget.value = rInitialValue.current
127
127
  onCancel?.(e.currentTarget.value)
128
128
  e.currentTarget.blur()
129
- stopEventPropagation(e)
129
+ e.stopPropagation()
130
130
  break
131
131
  }
132
132
  }
@@ -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
  })
@@ -94,6 +94,7 @@ export interface TLUiToolbarToggleGroupProps extends React.HTMLAttributes<HTMLDi
94
94
  // TODO: fix up this type later
95
95
  defaultValue?: any
96
96
  type: 'single' | 'multiple'
97
+ asChild?: boolean
97
98
  }
98
99
 
99
100
  /** @public @react */
@@ -101,10 +102,12 @@ export const TldrawUiToolbarToggleGroup = ({
101
102
  children,
102
103
  className,
103
104
  type,
105
+ asChild,
104
106
  ...props
105
107
  }: TLUiToolbarToggleGroupProps) => {
106
108
  return (
107
109
  <_Toolbar.ToggleGroup
110
+ asChild={asChild}
108
111
  type={type}
109
112
  {...props}
110
113
  // TODO: this fixes a bug in Radix until they fix it.
@@ -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,18 @@ 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)
155
168
  useEffect(() => {
156
- // Clear any existing show timeout
157
- if (showTimeoutRef.current) {
158
- clearTimeout(showTimeoutRef.current)
159
- showTimeoutRef.current = null
169
+ if (cameraState === 'moving' && isOpen && currentTooltip) {
170
+ tooltipManager.hideTooltip(editor, currentTooltip.id, true)
160
171
  }
172
+ }, [cameraState, isOpen, currentTooltip, editor])
161
173
 
174
+ // Update open state and trigger position
175
+ useEffect(() => {
176
+ let timer: ReturnType<typeof setTimeout> | null = null
162
177
  if (currentTooltip && triggerRef.current) {
163
178
  // Position the invisible trigger element over the active element
164
179
  const activeRect = currentTooltip.targetElement.getBoundingClientRect()
@@ -173,11 +188,12 @@ function TooltipSingleton() {
173
188
  trigger.style.zIndex = '9999'
174
189
 
175
190
  // Handle delay for first show
176
- if (isFirstShowRef.current && editor) {
177
- showTimeoutRef.current = editor.timers.setTimeout(() => {
191
+ if (isFirstShowRef.current) {
192
+ // eslint-disable-next-line no-restricted-globals
193
+ timer = setTimeout(() => {
178
194
  setIsOpen(true)
179
195
  isFirstShowRef.current = false
180
- }, currentTooltip.delayDuration ?? editor.options.tooltipDelayMs)
196
+ }, currentTooltip.delayDuration)
181
197
  } else {
182
198
  // Subsequent tooltips show immediately
183
199
  setIsOpen(true)
@@ -188,7 +204,13 @@ function TooltipSingleton() {
188
204
  // Reset first show state after tooltip is hidden
189
205
  isFirstShowRef.current = true
190
206
  }
191
- }, [editor, currentTooltip])
207
+
208
+ return () => {
209
+ if (timer !== null) {
210
+ clearTimeout(timer)
211
+ }
212
+ }
213
+ }, [currentTooltip])
192
214
 
193
215
  if (!currentTooltip) {
194
216
  return null
@@ -231,6 +253,7 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
231
253
  const editor = useMaybeEditor()
232
254
  const tooltipId = useRef<string>(uniqueId())
233
255
  const hasProvider = useContext(TooltipSingletonContext)
256
+ const showUiLabels = useValue('showUiLabels', () => editor?.user.getShowUiLabels(), [editor])
234
257
 
235
258
  const orientationCtx = useTldrawUiOrientation()
236
259
  const sideToUse = side ?? orientationCtx.tooltipSide
@@ -244,20 +267,35 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
244
267
  }
245
268
  }, [editor, hasProvider])
246
269
 
270
+ useLayoutEffect(() => {
271
+ if (hasProvider && tooltipManager.getCurrentTooltipData()?.id === tooltipId.current) {
272
+ tooltipManager.updateCurrentTooltip(tooltipId.current, (tooltip) => ({
273
+ ...tooltip,
274
+ content,
275
+ side: sideToUse,
276
+ sideOffset,
277
+ showOnMobile,
278
+ }))
279
+ }
280
+ }, [content, sideToUse, sideOffset, showOnMobile, hasProvider])
281
+
247
282
  // Don't show tooltip if disabled, no content, or UI labels are disabled
248
283
  if (disabled || !content) {
249
284
  return <>{children}</>
250
285
  }
251
286
 
287
+ let delayDurationToUse
288
+ if (showUiLabels) {
289
+ delayDurationToUse = 0
290
+ } else {
291
+ delayDurationToUse =
292
+ delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)
293
+ }
294
+
252
295
  // Fallback to old behavior if no provider
253
296
  if (!hasProvider) {
254
297
  return (
255
- <_Tooltip.Root
256
- delayDuration={
257
- delayDuration ?? (editor?.options.tooltipDelayMs || DEFAULT_TOOLTIP_DELAY_MS)
258
- }
259
- disableHoverableContent
260
- >
298
+ <_Tooltip.Root delayDuration={delayDurationToUse} disableHoverableContent>
261
299
  <_Tooltip.Trigger asChild ref={ref}>
262
300
  {children}
263
301
  </_Tooltip.Trigger>
@@ -288,7 +326,7 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
288
326
  sideToUse,
289
327
  sideOffset,
290
328
  showOnMobile,
291
- delayDuration
329
+ delayDurationToUse
292
330
  )
293
331
  }
294
332
 
@@ -306,7 +344,7 @@ export const TldrawUiTooltip = forwardRef<HTMLButtonElement, TldrawUiTooltipProp
306
344
  sideToUse,
307
345
  sideOffset,
308
346
  showOnMobile,
309
- delayDuration
347
+ delayDurationToUse
310
348
  )
311
349
  }
312
350
 
@@ -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}
@@ -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
  {
@@ -1755,7 +1758,17 @@ export function ActionsProvider({ overrides, children }: ActionsProviderProps) {
1755
1758
  }
1756
1759
 
1757
1760
  return actions
1758
- }, [helpers, _editor, trackEvent, overrides, defaultDocumentName, showCollaborationUi, msg, a11y])
1761
+ }, [
1762
+ helpers,
1763
+ _editor,
1764
+ trackEvent,
1765
+ overrides,
1766
+ defaultDocumentName,
1767
+ showCollaborationUi,
1768
+ msg,
1769
+ a11y,
1770
+ components,
1771
+ ])
1759
1772
 
1760
1773
  return <ActionsContext.Provider value={asActions(actions)}>{children}</ActionsContext.Provider>
1761
1774
  }
@@ -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]
@@ -123,7 +123,7 @@ export interface TLUiEventMap {
123
123
  'shrink-shapes': null
124
124
  'flatten-to-image': null
125
125
  'a11y-repeat-shape-announce': null
126
- 'open-url': { url: string }
126
+ 'open-url': { destinationUrl: string }
127
127
  'open-context-menu': null
128
128
  'adjust-shape-styles': null
129
129
  'copy-link': null
@@ -7,8 +7,8 @@ import {
7
7
  assert,
8
8
  compact,
9
9
  isDefined,
10
+ markEventAsHandled,
10
11
  preventDefault,
11
- stopEventPropagation,
12
12
  uniq,
13
13
  useEditor,
14
14
  useMaybeEditor,
@@ -763,7 +763,7 @@ export function useNativeClipboardEvents() {
763
763
 
764
764
  const paste = (e: ClipboardEvent) => {
765
765
  if (disablingMiddleClickPaste) {
766
- stopEventPropagation(e)
766
+ markEventAsHandled(e)
767
767
  return
768
768
  }
769
769
 
@@ -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' })
@@ -186,6 +186,7 @@ export type TLUiTranslationKey =
186
186
  | 'geo-style.pentagon'
187
187
  | 'geo-style.rectangle'
188
188
  | 'geo-style.rhombus'
189
+ | 'geo-style.rhombus-2'
189
190
  | 'geo-style.star'
190
191
  | 'geo-style.trapezoid'
191
192
  | 'geo-style.triangle'
@@ -260,6 +261,7 @@ export type TLUiTranslationKey =
260
261
  | 'tool.aspect-ratio.wide'
261
262
  | 'tool.image-toolbar-title'
262
263
  | 'tool.image-crop'
264
+ | 'tool.image-crop-confirm'
263
265
  | 'tool.media-alt-text'
264
266
  | 'tool.media-alt-text-desc'
265
267
  | 'tool.media-alt-text-confirm'
@@ -92,9 +92,9 @@ export const DEFAULT_TRANSLATION = {
92
92
  'action.toggle-wrap-mode': 'Toggle Select on wrap',
93
93
  'action.toggle-reduce-motion.menu': 'Reduce motion',
94
94
  'action.toggle-reduce-motion': 'Toggle reduce motion',
95
- 'action.toggle-keyboard-shortcuts.menu': 'Keyboard shortcuts',
95
+ 'action.toggle-keyboard-shortcuts.menu': 'Enable keyboard shortcuts',
96
96
  'action.toggle-keyboard-shortcuts': 'Toggle keyboard shortcuts',
97
- 'action.toggle-ui-labels.menu': 'UI labels',
97
+ 'action.toggle-ui-labels.menu': 'Enable UI labels',
98
98
  'action.toggle-ui-labels': 'Toggle UI labels',
99
99
  'action.toggle-edge-scrolling.menu': 'Edge scrolling',
100
100
  'action.toggle-edge-scrolling': 'Toggle edge scrolling',
@@ -187,6 +187,7 @@ export const DEFAULT_TRANSLATION = {
187
187
  'geo-style.pentagon': 'Pentagon',
188
188
  'geo-style.rectangle': 'Rectangle',
189
189
  'geo-style.rhombus': 'Rhombus',
190
+ 'geo-style.rhombus-2': 'Rhombus left',
190
191
  'geo-style.star': 'Star',
191
192
  'geo-style.trapezoid': 'Trapezoid',
192
193
  'geo-style.triangle': 'Triangle',
@@ -261,6 +262,7 @@ export const DEFAULT_TRANSLATION = {
261
262
  'tool.aspect-ratio.wide': 'Wide (16:9)',
262
263
  'tool.image-toolbar-title': 'Image tools',
263
264
  'tool.image-crop': 'Crop image',
265
+ 'tool.image-crop-confirm': 'Confirm',
264
266
  'tool.media-alt-text': 'Alternative text',
265
267
  'tool.media-alt-text-desc': 'Give a description…',
266
268
  'tool.media-alt-text-confirm': 'Confirm',
@@ -31,9 +31,16 @@ export function kbd(str: string) {
31
31
  )
32
32
  .flat()
33
33
  .map((sub, index) => {
34
- if (sub === '__CTRL__') return 'Ctrl'
35
- if (sub === '__ALT__') return 'Alt'
36
- const modifiedKey = sub[0].toUpperCase() + sub.slice(1)
34
+ if (sub[0] === '+') return []
35
+
36
+ let modifiedKey
37
+ if (sub === '__CTRL__') {
38
+ modifiedKey = 'Ctrl'
39
+ } else if (sub === '__ALT__') {
40
+ modifiedKey = 'Alt'
41
+ } else {
42
+ modifiedKey = sub[0].toUpperCase() + sub.slice(1)
43
+ }
37
44
  return tlenv.isDarwin || !index ? modifiedKey : ['+', modifiedKey]
38
45
  })
39
46
  .flat()
@@ -1,9 +1,9 @@
1
1
  // This file is automatically generated by internal/scripts/refresh-assets.ts.
2
2
  // Do not edit manually. Or do, I'm a comment, not a cop.
3
3
 
4
- export const version = '3.16.0-internal.51e99e128bd4'
4
+ export const version = '3.16.0-internal.71f83a8a571b'
5
5
  export const publishDates = {
6
6
  major: '2024-09-13T14:36:29.063Z',
7
- minor: '2025-08-19T10:06:54.740Z',
8
- patch: '2025-08-19T10:06:54.740Z',
7
+ minor: '2025-09-15T18:29:53.804Z',
8
+ patch: '2025-09-15T18:29:53.804Z',
9
9
  }