tldraw 3.16.0-canary.e9c30b532b82 → 3.16.0-canary.eb473ba53051

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 (368) hide show
  1. package/dist-cjs/index.d.ts +233 -107
  2. package/dist-cjs/index.js +33 -14
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/Tldraw.js +12 -2
  5. package/dist-cjs/lib/Tldraw.js.map +2 -2
  6. package/dist-cjs/lib/defaultExternalContentHandlers.js +15 -4
  7. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  8. package/dist-cjs/lib/shapes/arrow/arrowLabel.js +6 -0
  9. package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +3 -3
  10. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js +4 -4
  11. package/dist-cjs/lib/shapes/bookmark/BookmarkShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +8 -1
  13. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  14. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js +2 -2
  15. package/dist-cjs/lib/shapes/frame/components/FrameLabelInput.js.map +2 -2
  16. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js +1 -0
  17. package/dist-cjs/lib/shapes/geo/GeoShapeUtil.js.map +2 -2
  18. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -0
  19. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
  20. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js +2 -1
  21. package/dist-cjs/lib/shapes/note/NoteShapeUtil.js.map +2 -2
  22. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js +4 -4
  23. package/dist-cjs/lib/shapes/shared/HyperlinkButton.js.map +2 -2
  24. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -3
  25. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  26. package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
  27. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +3 -4
  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 +2 -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/EraserTool/childStates/Erasing.js +25 -1
  36. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  37. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +12 -0
  38. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  39. package/dist-cjs/lib/ui/TldrawUi.js +13 -12
  40. package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
  41. package/dist-cjs/lib/ui/assetUrls.js +13 -10
  42. package/dist-cjs/lib/ui/assetUrls.js.map +2 -2
  43. package/dist-cjs/lib/ui/components/A11y.js +1 -1
  44. package/dist-cjs/lib/ui/components/A11y.js.map +2 -2
  45. package/dist-cjs/lib/ui/components/{FollowingIndicator.js → DefaultFollowingIndicator.js} +6 -6
  46. package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +7 -0
  47. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +6 -6
  48. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
  49. package/dist-cjs/lib/ui/components/LanguageMenu.js +1 -0
  50. package/dist-cjs/lib/ui/components/LanguageMenu.js.map +2 -2
  51. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js +1 -0
  52. package/dist-cjs/lib/ui/components/Minimap/DefaultMinimap.js.map +2 -2
  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/StylePanel/StylePanelButtonPicker.js +147 -0
  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 +2 -0
  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 +2 -1
  76. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
  77. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.js +1 -1
  78. package/dist-cjs/lib/ui/components/Toolbar/OverflowingToolbar.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 +18 -5
  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 +96 -43
  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 +7 -6
  92. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  93. package/dist-cjs/lib/ui/context/actions.js +29 -10
  94. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  95. package/dist-cjs/lib/ui/context/components.js +2 -0
  96. package/dist-cjs/lib/ui/context/components.js.map +2 -2
  97. package/dist-cjs/lib/ui/context/events.js.map +1 -1
  98. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js +1 -1
  99. package/dist-cjs/lib/ui/hooks/useClipboardEvents.js.map +2 -2
  100. package/dist-cjs/lib/ui/hooks/useExportAs.js +3 -2
  101. package/dist-cjs/lib/ui/hooks/useExportAs.js.map +2 -2
  102. package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
  103. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  104. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  105. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +6 -2
  106. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  107. package/dist-cjs/lib/ui/kbd-utils.js +9 -3
  108. package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
  109. package/dist-cjs/lib/ui/version.js +3 -3
  110. package/dist-cjs/lib/ui/version.js.map +1 -1
  111. package/dist-cjs/lib/utils/export/copyAs.js +1 -2
  112. package/dist-cjs/lib/utils/export/copyAs.js.map +2 -2
  113. package/dist-cjs/lib/utils/export/export.js +0 -20
  114. package/dist-cjs/lib/utils/export/export.js.map +2 -2
  115. package/dist-cjs/lib/utils/export/exportAs.js +1 -2
  116. package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
  117. package/dist-esm/index.d.mts +233 -107
  118. package/dist-esm/index.mjs +61 -29
  119. package/dist-esm/index.mjs.map +2 -2
  120. package/dist-esm/lib/Tldraw.mjs +14 -4
  121. package/dist-esm/lib/Tldraw.mjs.map +2 -2
  122. package/dist-esm/lib/defaultExternalContentHandlers.mjs +15 -4
  123. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  124. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +6 -0
  125. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +3 -3
  126. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs +5 -5
  127. package/dist-esm/lib/shapes/bookmark/BookmarkShapeUtil.mjs.map +2 -2
  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/freehand/svg.mjs.map +2 -2
  143. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +4 -5
  144. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  145. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +0 -2
  146. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  147. package/dist-esm/lib/shapes/text/PlainTextArea.mjs +3 -3
  148. package/dist-esm/lib/shapes/text/PlainTextArea.mjs.map +2 -2
  149. package/dist-esm/lib/shapes/text/RichTextArea.mjs +3 -4
  150. package/dist-esm/lib/shapes/text/RichTextArea.mjs.map +2 -2
  151. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +26 -1
  152. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  153. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +13 -0
  154. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  155. package/dist-esm/lib/ui/TldrawUi.mjs +13 -12
  156. package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
  157. package/dist-esm/lib/ui/assetUrls.mjs +13 -10
  158. package/dist-esm/lib/ui/assetUrls.mjs.map +2 -2
  159. package/dist-esm/lib/ui/components/A11y.mjs +2 -2
  160. package/dist-esm/lib/ui/components/A11y.mjs.map +2 -2
  161. package/dist-esm/lib/ui/components/{FollowingIndicator.mjs → DefaultFollowingIndicator.mjs} +3 -3
  162. package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +7 -0
  163. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +6 -6
  164. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
  165. package/dist-esm/lib/ui/components/LanguageMenu.mjs +1 -0
  166. package/dist-esm/lib/ui/components/LanguageMenu.mjs.map +2 -2
  167. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs +1 -0
  168. package/dist-esm/lib/ui/components/Minimap/DefaultMinimap.mjs.map +2 -2
  169. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs +2 -2
  170. package/dist-esm/lib/ui/components/PageMenu/DefaultPageMenu.mjs.map +2 -2
  171. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +14 -5
  172. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
  173. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +257 -320
  174. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  175. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs +135 -0
  176. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +7 -0
  177. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +48 -0
  178. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +7 -0
  179. package/dist-esm/lib/ui/components/StylePanel/{DoubleDropdownPicker.mjs → StylePanelDoubleDropdownPicker.mjs} +20 -19
  180. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +7 -0
  181. package/dist-esm/lib/ui/components/StylePanel/{DropdownPicker.mjs → StylePanelDropdownPicker.mjs} +21 -18
  182. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +7 -0
  183. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs +8 -0
  184. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs.map +7 -0
  185. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +2 -0
  186. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  187. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +38 -9
  188. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  189. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs +15 -3
  190. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs.map +2 -2
  191. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +2 -1
  192. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
  193. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs +1 -1
  194. package/dist-esm/lib/ui/components/Toolbar/OverflowingToolbar.mjs.map +2 -2
  195. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +12 -3
  196. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  197. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs +6 -4
  198. package/dist-esm/lib/ui/components/primitives/TldrawUiInput.mjs.map +2 -2
  199. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +18 -5
  200. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  201. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +3 -0
  202. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  203. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +97 -43
  204. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  205. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs +3 -0
  206. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.mjs.map +2 -2
  207. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +7 -6
  208. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  209. package/dist-esm/lib/ui/context/actions.mjs +29 -10
  210. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  211. package/dist-esm/lib/ui/context/components.mjs +2 -0
  212. package/dist-esm/lib/ui/context/components.mjs.map +2 -2
  213. package/dist-esm/lib/ui/context/events.mjs.map +1 -1
  214. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs +2 -2
  215. package/dist-esm/lib/ui/hooks/useClipboardEvents.mjs.map +2 -2
  216. package/dist-esm/lib/ui/hooks/useExportAs.mjs +3 -2
  217. package/dist-esm/lib/ui/hooks/useExportAs.mjs.map +2 -2
  218. package/dist-esm/lib/ui/hooks/useTools.mjs +1 -1
  219. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  220. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +6 -2
  221. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  222. package/dist-esm/lib/ui/kbd-utils.mjs +9 -3
  223. package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
  224. package/dist-esm/lib/ui/version.mjs +3 -3
  225. package/dist-esm/lib/ui/version.mjs.map +1 -1
  226. package/dist-esm/lib/utils/export/copyAs.mjs +1 -2
  227. package/dist-esm/lib/utils/export/copyAs.mjs.map +2 -2
  228. package/dist-esm/lib/utils/export/export.mjs +0 -20
  229. package/dist-esm/lib/utils/export/export.mjs.map +2 -2
  230. package/dist-esm/lib/utils/export/exportAs.mjs +1 -2
  231. package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
  232. package/package.json +11 -34
  233. package/src/index.ts +44 -22
  234. package/src/lib/Tldraw.tsx +15 -2
  235. package/src/lib/defaultExternalContentHandlers.ts +26 -4
  236. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +2 -1
  237. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +6 -5
  238. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +48 -6
  239. package/src/lib/shapes/arrow/arrowLabel.ts +8 -0
  240. package/src/lib/shapes/bookmark/BookmarkShapeUtil.tsx +5 -5
  241. package/src/lib/shapes/draw/DrawShapeTool.test.ts +0 -5
  242. package/src/lib/shapes/frame/FrameShapeUtil.tsx +9 -0
  243. package/src/lib/shapes/frame/components/FrameLabelInput.tsx +3 -3
  244. package/src/lib/shapes/geo/GeoShapeUtil.tsx +1 -0
  245. package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -0
  246. package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -3
  247. package/src/lib/shapes/line/__snapshots__/LineShapeUtil.test.tsx.snap +2 -2
  248. package/src/lib/shapes/note/NoteShapeUtil.tsx +1 -0
  249. package/src/lib/shapes/shared/HyperlinkButton.tsx +5 -5
  250. package/src/lib/shapes/shared/PlainTextLabel.tsx +0 -6
  251. package/src/lib/shapes/shared/freehand/svg.ts +2 -0
  252. package/src/lib/shapes/shared/useEditablePlainText.ts +5 -9
  253. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +0 -7
  254. package/src/lib/shapes/text/PlainTextArea.tsx +3 -3
  255. package/src/lib/shapes/text/RichTextArea.tsx +3 -4
  256. package/src/lib/shapes/text/TextShapeTool.test.ts +6 -5
  257. package/src/lib/tools/EraserTool/childStates/Erasing.ts +34 -1
  258. package/src/lib/tools/EraserTool/childStates/Pointing.ts +20 -0
  259. package/src/lib/ui/TldrawUi.tsx +16 -10
  260. package/src/lib/ui/assetUrls.ts +13 -10
  261. package/src/lib/ui/components/A11y.tsx +2 -2
  262. package/src/lib/ui/components/{FollowingIndicator.tsx → DefaultFollowingIndicator.tsx} +2 -1
  263. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +6 -6
  264. package/src/lib/ui/components/LanguageMenu.tsx +1 -0
  265. package/src/lib/ui/components/Minimap/DefaultMinimap.tsx +1 -0
  266. package/src/lib/ui/components/PageMenu/DefaultPageMenu.tsx +2 -2
  267. package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +27 -13
  268. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +260 -381
  269. package/src/lib/ui/components/{primitives/TldrawUiButtonPicker.tsx → StylePanel/StylePanelButtonPicker.tsx} +70 -50
  270. package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +63 -0
  271. package/src/lib/ui/components/StylePanel/{DoubleDropdownPicker.tsx → StylePanelDoubleDropdownPicker.tsx} +28 -19
  272. package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +119 -0
  273. package/src/lib/ui/components/StylePanel/StylePanelSubheading.tsx +9 -0
  274. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +2 -0
  275. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +32 -15
  276. package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
  277. package/src/lib/ui/components/Toolbar/LinkEditor.tsx +1 -0
  278. package/src/lib/ui/components/Toolbar/OverflowingToolbar.tsx +1 -1
  279. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +8 -3
  280. package/src/lib/ui/components/primitives/TldrawUiInput.tsx +6 -3
  281. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +52 -32
  282. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +5 -1
  283. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +109 -31
  284. package/src/lib/ui/components/primitives/menus/TldrawUiMenuCheckboxItem.tsx +4 -0
  285. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +9 -8
  286. package/src/lib/ui/context/actions.tsx +36 -10
  287. package/src/lib/ui/context/components.tsx +3 -0
  288. package/src/lib/ui/context/events.tsx +1 -1
  289. package/src/lib/ui/hooks/useClipboardEvents.ts +2 -2
  290. package/src/lib/ui/hooks/useExportAs.ts +3 -2
  291. package/src/lib/ui/hooks/useTools.tsx +1 -1
  292. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +4 -0
  293. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +6 -2
  294. package/src/lib/ui/kbd-utils.ts +10 -3
  295. package/src/lib/ui/version.ts +3 -3
  296. package/src/lib/ui.css +29 -2
  297. package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +5 -5
  298. package/src/lib/utils/export/copyAs.ts +1 -24
  299. package/src/lib/utils/export/export.ts +0 -36
  300. package/src/lib/utils/export/exportAs.ts +1 -32
  301. package/src/lib/utils/tldr/__snapshots__/buildFromV1Document.test.ts.snap +4 -4
  302. package/src/test/A11y.test.tsx +3 -2
  303. package/src/test/ClickManager.test.ts +7 -6
  304. package/src/test/Editor.test.tsx +20 -19
  305. package/src/test/EraserTool.test.ts +184 -13
  306. package/src/test/HandTool.test.ts +10 -9
  307. package/src/test/HighlightShape.test.ts +2 -1
  308. package/src/test/SelectTool.test.ts +3 -2
  309. package/src/test/TLUserPreferences.test.ts +4 -3
  310. package/src/test/TestEditor.ts +13 -15
  311. package/src/test/TldrawEditor.test.tsx +11 -10
  312. package/src/test/ZoomTool.test.ts +7 -6
  313. package/src/test/__snapshots__/drawing.test.ts.snap +2 -2
  314. package/src/test/__snapshots__/groups.test.tsx.snap +6 -6
  315. package/src/test/__snapshots__/resizing.test.ts.snap +2 -2
  316. package/src/test/arrows-megabus.test.tsx +5 -4
  317. package/src/test/bindings.test.tsx +24 -37
  318. package/src/test/bookmark-shapes.test.ts +1 -8
  319. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +23 -7
  320. package/src/test/commands/__snapshots__/packShapes.test.ts.snap +8 -8
  321. package/src/test/commands/__snapshots__/zoomToFit.test.ts.snap +2 -2
  322. package/src/test/commands/alignShapes.test.tsx +25 -24
  323. package/src/test/commands/animationSpeed.test.ts +2 -1
  324. package/src/test/commands/centerOnPoint.test.ts +3 -2
  325. package/src/test/commands/clipboard.test.ts +3 -2
  326. package/src/test/commands/createShapes.test.ts +2 -1
  327. package/src/test/commands/deleteShapes.test.ts +2 -1
  328. package/src/test/commands/distributeShapes.test.tsx +11 -10
  329. package/src/test/commands/getSvgString.test.ts +2 -1
  330. package/src/test/commands/packShapes.test.ts +5 -4
  331. package/src/test/commands/resizeShape.test.ts +2 -1
  332. package/src/test/commands/rotateShapes.test.ts +7 -6
  333. package/src/test/commands/setCamera.test.ts +4 -3
  334. package/src/test/commands/setCurrentPage.test.ts +3 -2
  335. package/src/test/commands/stackShapes.test.ts +11 -10
  336. package/src/test/commands/stretch.test.tsx +13 -12
  337. package/src/test/createDeepLink.test.tsx +2 -1
  338. package/src/test/cropping.test.ts +3 -2
  339. package/src/test/custom-clipping.test.ts +436 -0
  340. package/src/test/drawing.test.ts +2 -1
  341. package/src/test/flipShapes.test.ts +4 -3
  342. package/src/test/frames.test.ts +25 -24
  343. package/src/test/getCulledShapes.test.tsx +74 -4
  344. package/src/test/groups.test.tsx +1 -1
  345. package/src/test/handleDeepLink.test.tsx +2 -1
  346. package/src/test/maxShapes.test.ts +3 -2
  347. package/src/test/modifiers.test.ts +5 -4
  348. package/src/test/navigation.test.ts +12 -11
  349. package/src/test/panning.test.ts +2 -1
  350. package/src/test/perf/perf.test.ts +2 -1
  351. package/src/test/registerDeepLinkListener.test.tsx +10 -9
  352. package/src/test/resizing.test.ts +39 -38
  353. package/src/test/select.test.tsx +4 -3
  354. package/src/test/selection-omnibus.test.ts +11 -10
  355. package/src/test/shapeutils.test.ts +4 -3
  356. package/src/test/translating.test.ts +9 -8
  357. package/tldraw.css +45 -5
  358. package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
  359. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +0 -7
  360. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +0 -7
  361. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js +0 -131
  362. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +0 -7
  363. package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
  364. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +0 -7
  365. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +0 -7
  366. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs +0 -115
  367. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +0 -7
  368. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +0 -110
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/shapes/shared/freehand/svg.ts"],
4
- "sourcesContent": ["import { average, precise } from '@tldraw/editor'\nimport { StrokePoint } from './types'\n\n/**\n * Turn an array of stroke points into a path of quadradic curves.\n *\n * @param points - The stroke points returned from perfect-freehand\n * @param closed - Whether the shape is closed\n */\nexport function getSvgPathFromStrokePoints(points: StrokePoint[], closed = false): string {\n\tconst len = points.length\n\n\tif (len < 2) {\n\t\treturn ''\n\t}\n\n\tlet a = points[0].point\n\tlet b = points[1].point\n\n\tif (len === 2) {\n\t\treturn `M${precise(a)}L${precise(b)}`\n\t}\n\n\tlet result = ''\n\n\tfor (let i = 2, max = len - 1; i < max; i++) {\n\t\ta = points[i].point\n\t\tb = points[i + 1].point\n\t\tresult += average(a, b)\n\t}\n\n\tif (closed) {\n\t\t// If closed, draw a curve from the last point to the first\n\t\treturn `M${average(points[0].point, points[1].point)}Q${precise(points[1].point)}${average(\n\t\t\tpoints[1].point,\n\t\t\tpoints[2].point\n\t\t)}T${result}${average(points[len - 1].point, points[0].point)}${average(\n\t\t\tpoints[0].point,\n\t\t\tpoints[1].point\n\t\t)}Z`\n\t} else {\n\t\t// If not closed, draw a curve starting at the first point and\n\t\t// ending at the midpoint of the last and second-last point, then\n\t\t// complete the curve with a line segment to the last point.\n\t\treturn `M${precise(points[0].point)}Q${precise(points[1].point)}${average(\n\t\t\tpoints[1].point,\n\t\t\tpoints[2].point\n\t\t)}${points.length > 3 ? 'T' : ''}${result}L${precise(points[len - 1].point)}`\n\t}\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAiC;AAS1B,SAAS,2BAA2B,QAAuB,SAAS,OAAe;AACzF,QAAM,MAAM,OAAO;AAEnB,MAAI,MAAM,GAAG;AACZ,WAAO;AAAA,EACR;AAEA,MAAI,IAAI,OAAO,CAAC,EAAE;AAClB,MAAI,IAAI,OAAO,CAAC,EAAE;AAElB,MAAI,QAAQ,GAAG;AACd,WAAO,QAAI,uBAAQ,CAAC,CAAC,QAAI,uBAAQ,CAAC,CAAC;AAAA,EACpC;AAEA,MAAI,SAAS;AAEb,WAAS,IAAI,GAAG,MAAM,MAAM,GAAG,IAAI,KAAK,KAAK;AAC5C,QAAI,OAAO,CAAC,EAAE;AACd,QAAI,OAAO,IAAI,CAAC,EAAE;AAClB,kBAAU,uBAAQ,GAAG,CAAC;AAAA,EACvB;AAEA,MAAI,QAAQ;AAEX,WAAO,QAAI,uBAAQ,OAAO,CAAC,EAAE,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,QAAI,uBAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,OAAG;AAAA,MAClF,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC,IAAI,MAAM,OAAG,uBAAQ,OAAO,MAAM,CAAC,EAAE,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,OAAG;AAAA,MAC/D,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC;AAAA,EACF,OAAO;AAIN,WAAO,QAAI,uBAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,QAAI,uBAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,OAAG;AAAA,MACjE,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC,GAAG,OAAO,SAAS,IAAI,MAAM,EAAE,GAAG,MAAM,QAAI,uBAAQ,OAAO,MAAM,CAAC,EAAE,KAAK,CAAC;AAAA,EAC5E;AACD;",
4
+ "sourcesContent": ["import { average, precise } from '@tldraw/editor'\nimport { StrokePoint } from './types'\n\n/**\n * Turn an array of stroke points into a path of quadradic curves.\n *\n * @param points - The stroke points returned from perfect-freehand\n * @param closed - Whether the shape is closed\n *\n * @public\n */\nexport function getSvgPathFromStrokePoints(points: StrokePoint[], closed = false): string {\n\tconst len = points.length\n\n\tif (len < 2) {\n\t\treturn ''\n\t}\n\n\tlet a = points[0].point\n\tlet b = points[1].point\n\n\tif (len === 2) {\n\t\treturn `M${precise(a)}L${precise(b)}`\n\t}\n\n\tlet result = ''\n\n\tfor (let i = 2, max = len - 1; i < max; i++) {\n\t\ta = points[i].point\n\t\tb = points[i + 1].point\n\t\tresult += average(a, b)\n\t}\n\n\tif (closed) {\n\t\t// If closed, draw a curve from the last point to the first\n\t\treturn `M${average(points[0].point, points[1].point)}Q${precise(points[1].point)}${average(\n\t\t\tpoints[1].point,\n\t\t\tpoints[2].point\n\t\t)}T${result}${average(points[len - 1].point, points[0].point)}${average(\n\t\t\tpoints[0].point,\n\t\t\tpoints[1].point\n\t\t)}Z`\n\t} else {\n\t\t// If not closed, draw a curve starting at the first point and\n\t\t// ending at the midpoint of the last and second-last point, then\n\t\t// complete the curve with a line segment to the last point.\n\t\treturn `M${precise(points[0].point)}Q${precise(points[1].point)}${average(\n\t\t\tpoints[1].point,\n\t\t\tpoints[2].point\n\t\t)}${points.length > 3 ? 'T' : ''}${result}L${precise(points[len - 1].point)}`\n\t}\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAiC;AAW1B,SAAS,2BAA2B,QAAuB,SAAS,OAAe;AACzF,QAAM,MAAM,OAAO;AAEnB,MAAI,MAAM,GAAG;AACZ,WAAO;AAAA,EACR;AAEA,MAAI,IAAI,OAAO,CAAC,EAAE;AAClB,MAAI,IAAI,OAAO,CAAC,EAAE;AAElB,MAAI,QAAQ,GAAG;AACd,WAAO,QAAI,uBAAQ,CAAC,CAAC,QAAI,uBAAQ,CAAC,CAAC;AAAA,EACpC;AAEA,MAAI,SAAS;AAEb,WAAS,IAAI,GAAG,MAAM,MAAM,GAAG,IAAI,KAAK,KAAK;AAC5C,QAAI,OAAO,CAAC,EAAE;AACd,QAAI,OAAO,IAAI,CAAC,EAAE;AAClB,kBAAU,uBAAQ,GAAG,CAAC;AAAA,EACvB;AAEA,MAAI,QAAQ;AAEX,WAAO,QAAI,uBAAQ,OAAO,CAAC,EAAE,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,QAAI,uBAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,OAAG;AAAA,MAClF,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC,IAAI,MAAM,OAAG,uBAAQ,OAAO,MAAM,CAAC,EAAE,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,OAAG;AAAA,MAC/D,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC;AAAA,EACF,OAAO;AAIN,WAAO,QAAI,uBAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,QAAI,uBAAQ,OAAO,CAAC,EAAE,KAAK,CAAC,OAAG;AAAA,MACjE,OAAO,CAAC,EAAE;AAAA,MACV,OAAO,CAAC,EAAE;AAAA,IACX,CAAC,GAAG,OAAO,SAAS,IAAI,MAAM,EAAE,GAAG,MAAM,QAAI,uBAAQ,OAAO,MAAM,CAAC,EAAE,KAAK,CAAC;AAAA,EAC5E;AACD;",
6
6
  "names": []
7
7
  }
@@ -19,7 +19,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var useEditablePlainText_exports = {};
20
20
  __export(useEditablePlainText_exports, {
21
21
  useEditablePlainText: () => useEditablePlainText,
22
- useEditableText: () => useEditableText,
23
22
  useEditableTextCommon: () => useEditableTextCommon,
24
23
  useIsReadyForEditing: () => useIsReadyForEditing
25
24
  });
@@ -117,7 +116,7 @@ function useEditableTextCommon(shapeId) {
117
116
  target: "shape",
118
117
  shape: editor.getShape(shapeId)
119
118
  });
120
- (0, import_editor.stopEventPropagation)(e);
119
+ e.stopPropagation();
121
120
  },
122
121
  [editor, shapeId]
123
122
  );
@@ -135,15 +134,15 @@ function useEditableTextCommon(shapeId) {
135
134
  },
136
135
  [editor, shapeId]
137
136
  );
137
+ const handleDoubleClick = import_editor.markEventAsHandled;
138
138
  return {
139
139
  handleFocus: import_editor.noop,
140
140
  handleBlur: import_editor.noop,
141
141
  handleInputPointerDown,
142
- handleDoubleClick: import_editor.stopEventPropagation,
142
+ handleDoubleClick,
143
143
  handlePaste,
144
144
  isEditing,
145
145
  isReadyForEditing
146
146
  };
147
147
  }
148
- const useEditableText = useEditablePlainText;
149
148
  //# sourceMappingURL=useEditablePlainText.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/shared/useEditablePlainText.ts"],
4
- "sourcesContent": ["import {\n\tEditor,\n\tTLShapeId,\n\tTLUnknownShape,\n\tgetPointerInfo,\n\tnoop,\n\tpreventDefault,\n\tstopEventPropagation,\n\ttlenv,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\nimport React, { useCallback, useEffect, useRef } from 'react'\nimport { TextHelpers } from './TextHelpers'\n\n/** @public */\nexport function useEditablePlainText(shapeId: TLShapeId, type: string, text?: string) {\n\tconst commonUseEditableTextHandlers = useEditableTextCommon(shapeId)\n\tconst isEditing = commonUseEditableTextHandlers.isEditing\n\tconst editor = useEditor()\n\tconst rInput = useRef<HTMLTextAreaElement>(null)\n\tconst isEmpty = (text || '').trim().length === 0\n\n\tuseEffect(() => {\n\t\tfunction selectAllIfEditing(event: { shapeId: TLShapeId }) {\n\t\t\tif (event.shapeId === shapeId) {\n\t\t\t\trInput.current?.select?.()\n\t\t\t}\n\t\t}\n\n\t\teditor.on('select-all-text', selectAllIfEditing)\n\t\treturn () => {\n\t\t\teditor.off('select-all-text', selectAllIfEditing)\n\t\t}\n\t}, [editor, shapeId, isEditing])\n\n\tuseEffect(() => {\n\t\tif (!isEditing) return\n\n\t\tif (document.activeElement !== rInput.current) {\n\t\t\trInput.current?.focus()\n\t\t}\n\n\t\tif (editor.getInstanceState().isCoarsePointer) {\n\t\t\trInput.current?.select()\n\t\t}\n\n\t\t// XXX(mime): This fixes iOS not showing the caret sometimes.\n\t\t// This \"shakes\" the caret awake.\n\t\tif (tlenv.isSafari) {\n\t\t\trInput.current?.blur()\n\t\t\trInput.current?.focus()\n\t\t}\n\t}, [editor, isEditing])\n\n\t// When the user presses ctrl / meta enter, complete the editing state.\n\tconst handleKeyDown = useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\n\t\t\tswitch (e.key) {\n\t\t\t\tcase 'Enter': {\n\t\t\t\t\tif (e.ctrlKey || e.metaKey) {\n\t\t\t\t\t\teditor.complete()\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\t// When the text changes, update the text value.\n\tconst handleChange = useCallback(\n\t\t({ plaintext }: { plaintext: string }) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\n\t\t\tconst normalizedPlaintext = TextHelpers.normalizeText(plaintext || '')\n\t\t\teditor.updateShape<TLUnknownShape & { props: { text: string } }>({\n\t\t\t\tid: shapeId,\n\t\t\t\ttype,\n\t\t\t\tprops: { text: normalizedPlaintext },\n\t\t\t})\n\t\t},\n\t\t[editor, shapeId, type]\n\t)\n\n\treturn {\n\t\trInput,\n\t\thandleKeyDown,\n\t\thandleChange,\n\t\tisEmpty,\n\t\t...commonUseEditableTextHandlers,\n\t}\n}\n\n/** @internal */\nexport function useIsReadyForEditing(editor: Editor, shapeId: TLShapeId) {\n\treturn useValue(\n\t\t'isReadyForEditing',\n\t\t() => {\n\t\t\tconst editingShapeId = editor.getEditingShapeId()\n\t\t\treturn (\n\t\t\t\t// something's being editing... and either it's this shape OR this shape is hovered\n\t\t\t\teditingShapeId !== null &&\n\t\t\t\t(editingShapeId === shapeId || editor.getHoveredShapeId() === shapeId)\n\t\t\t)\n\t\t},\n\t\t[editor, shapeId]\n\t)\n}\n\n/** @internal */\nexport function useEditableTextCommon(shapeId: TLShapeId) {\n\tconst editor = useEditor()\n\tconst isEditing = useValue('isEditing', () => editor.getEditingShapeId() === shapeId, [editor])\n\tconst isReadyForEditing = useIsReadyForEditing(editor, shapeId)\n\n\tconst handleInputPointerDown = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\t// N.B. We used to only do this only when isEditing to help\n\t\t\t// prevent an issue where you could drag a selected shape\n\t\t\t// behind another shape. That is addressed now by the CSS logic\n\t\t\t// looking at data-isselectinganything.\n\t\t\t//\n\t\t\t// We still need to follow this logic even if not isEditing\n\t\t\t// because otherwise there is some flakiness in selection.\n\t\t\t// When selecting text, it would sometimes select some text\n\t\t\t// partially if we didn't dispatch/stop below.\n\n\t\t\teditor.dispatch({\n\t\t\t\t...getPointerInfo(e),\n\t\t\t\ttype: 'pointer',\n\t\t\t\tname: 'pointer_down',\n\t\t\t\ttarget: 'shape',\n\t\t\t\tshape: editor.getShape(shapeId)!,\n\t\t\t})\n\n\t\t\tstopEventPropagation(e) // we need to prevent blurring the input\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\tconst handlePaste = useCallback(\n\t\t(e: ClipboardEvent | React.ClipboardEvent<HTMLTextAreaElement>) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\t\t\tif (e.clipboardData) {\n\t\t\t\t// find html in the clipboard and look for the tldraw data\n\t\t\t\tconst html = e.clipboardData.getData('text/html')\n\t\t\t\tif (html) {\n\t\t\t\t\tif (html.includes('<div data-tldraw')) {\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\treturn {\n\t\thandleFocus: noop,\n\t\thandleBlur: noop,\n\t\thandleInputPointerDown,\n\t\thandleDoubleClick: stopEventPropagation,\n\t\thandlePaste,\n\t\tisEditing,\n\t\tisReadyForEditing,\n\t}\n}\n\n/**\n * @deprecated Use `useEditablePlainText` instead.\n * @public\n */\nexport const useEditableText = useEditablePlainText\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tEditor,\n\tTLShapeId,\n\tTLUnknownShape,\n\tgetPointerInfo,\n\tmarkEventAsHandled,\n\tnoop,\n\tpreventDefault,\n\ttlenv,\n\tuseEditor,\n\tuseValue,\n} from '@tldraw/editor'\nimport React, { useCallback, useEffect, useRef } from 'react'\nimport { TextHelpers } from './TextHelpers'\n\n/** @public */\nexport function useEditablePlainText(shapeId: TLShapeId, type: string, text?: string) {\n\tconst commonUseEditableTextHandlers = useEditableTextCommon(shapeId)\n\tconst isEditing = commonUseEditableTextHandlers.isEditing\n\tconst editor = useEditor()\n\tconst rInput = useRef<HTMLTextAreaElement>(null)\n\tconst isEmpty = (text || '').trim().length === 0\n\n\tuseEffect(() => {\n\t\tfunction selectAllIfEditing(event: { shapeId: TLShapeId }) {\n\t\t\tif (event.shapeId === shapeId) {\n\t\t\t\trInput.current?.select?.()\n\t\t\t}\n\t\t}\n\n\t\teditor.on('select-all-text', selectAllIfEditing)\n\t\treturn () => {\n\t\t\teditor.off('select-all-text', selectAllIfEditing)\n\t\t}\n\t}, [editor, shapeId, isEditing])\n\n\tuseEffect(() => {\n\t\tif (!isEditing) return\n\n\t\tif (document.activeElement !== rInput.current) {\n\t\t\trInput.current?.focus()\n\t\t}\n\n\t\tif (editor.getInstanceState().isCoarsePointer) {\n\t\t\trInput.current?.select()\n\t\t}\n\n\t\t// XXX(mime): This fixes iOS not showing the caret sometimes.\n\t\t// This \"shakes\" the caret awake.\n\t\tif (tlenv.isSafari) {\n\t\t\trInput.current?.blur()\n\t\t\trInput.current?.focus()\n\t\t}\n\t}, [editor, isEditing])\n\n\t// When the user presses ctrl / meta enter, complete the editing state.\n\tconst handleKeyDown = useCallback(\n\t\t(e: KeyboardEvent) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\n\t\t\tswitch (e.key) {\n\t\t\t\tcase 'Enter': {\n\t\t\t\t\tif (e.ctrlKey || e.metaKey) {\n\t\t\t\t\t\teditor.complete()\n\t\t\t\t\t}\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\t// When the text changes, update the text value.\n\tconst handleChange = useCallback(\n\t\t({ plaintext }: { plaintext: string }) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\n\t\t\tconst normalizedPlaintext = TextHelpers.normalizeText(plaintext || '')\n\t\t\teditor.updateShape<TLUnknownShape & { props: { text: string } }>({\n\t\t\t\tid: shapeId,\n\t\t\t\ttype,\n\t\t\t\tprops: { text: normalizedPlaintext },\n\t\t\t})\n\t\t},\n\t\t[editor, shapeId, type]\n\t)\n\n\treturn {\n\t\trInput,\n\t\thandleKeyDown,\n\t\thandleChange,\n\t\tisEmpty,\n\t\t...commonUseEditableTextHandlers,\n\t}\n}\n\n/** @internal */\nexport function useIsReadyForEditing(editor: Editor, shapeId: TLShapeId) {\n\treturn useValue(\n\t\t'isReadyForEditing',\n\t\t() => {\n\t\t\tconst editingShapeId = editor.getEditingShapeId()\n\t\t\treturn (\n\t\t\t\t// something's being editing... and either it's this shape OR this shape is hovered\n\t\t\t\teditingShapeId !== null &&\n\t\t\t\t(editingShapeId === shapeId || editor.getHoveredShapeId() === shapeId)\n\t\t\t)\n\t\t},\n\t\t[editor, shapeId]\n\t)\n}\n\n/** @internal */\nexport function useEditableTextCommon(shapeId: TLShapeId) {\n\tconst editor = useEditor()\n\tconst isEditing = useValue('isEditing', () => editor.getEditingShapeId() === shapeId, [editor])\n\tconst isReadyForEditing = useIsReadyForEditing(editor, shapeId)\n\n\tconst handleInputPointerDown = useCallback(\n\t\t(e: React.PointerEvent) => {\n\t\t\t// N.B. We used to only do this only when isEditing to help\n\t\t\t// prevent an issue where you could drag a selected shape\n\t\t\t// behind another shape. That is addressed now by the CSS logic\n\t\t\t// looking at data-isselectinganything.\n\t\t\t//\n\t\t\t// We still need to follow this logic even if not isEditing\n\t\t\t// because otherwise there is some flakiness in selection.\n\t\t\t// When selecting text, it would sometimes select some text\n\t\t\t// partially if we didn't dispatch/stop below.\n\n\t\t\teditor.dispatch({\n\t\t\t\t...getPointerInfo(e),\n\t\t\t\ttype: 'pointer',\n\t\t\t\tname: 'pointer_down',\n\t\t\t\ttarget: 'shape',\n\t\t\t\tshape: editor.getShape(shapeId)!,\n\t\t\t})\n\n\t\t\te.stopPropagation() // we need to prevent blurring the input\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\tconst handlePaste = useCallback(\n\t\t(e: ClipboardEvent | React.ClipboardEvent<HTMLTextAreaElement>) => {\n\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\t\t\tif (e.clipboardData) {\n\t\t\t\t// find html in the clipboard and look for the tldraw data\n\t\t\t\tconst html = e.clipboardData.getData('text/html')\n\t\t\t\tif (html) {\n\t\t\t\t\tif (html.includes('<div data-tldraw')) {\n\t\t\t\t\t\tpreventDefault(e)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[editor, shapeId]\n\t)\n\n\tconst handleDoubleClick: (e: React.MouseEvent) => void = markEventAsHandled\n\n\treturn {\n\t\thandleFocus: noop,\n\t\thandleBlur: noop,\n\t\thandleInputPointerDown,\n\t\thandleDoubleClick,\n\t\thandlePaste,\n\t\tisEditing,\n\t\tisReadyForEditing,\n\t}\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAWO;AACP,mBAAsD;AACtD,yBAA4B;AAGrB,SAAS,qBAAqB,SAAoB,MAAc,MAAe;AACrF,QAAM,gCAAgC,sBAAsB,OAAO;AACnE,QAAM,YAAY,8BAA8B;AAChD,QAAM,aAAS,yBAAU;AACzB,QAAM,aAAS,qBAA4B,IAAI;AAC/C,QAAM,WAAW,QAAQ,IAAI,KAAK,EAAE,WAAW;AAE/C,8BAAU,MAAM;AACf,aAAS,mBAAmB,OAA+B;AAC1D,UAAI,MAAM,YAAY,SAAS;AAC9B,eAAO,SAAS,SAAS;AAAA,MAC1B;AAAA,IACD;AAEA,WAAO,GAAG,mBAAmB,kBAAkB;AAC/C,WAAO,MAAM;AACZ,aAAO,IAAI,mBAAmB,kBAAkB;AAAA,IACjD;AAAA,EACD,GAAG,CAAC,QAAQ,SAAS,SAAS,CAAC;AAE/B,8BAAU,MAAM;AACf,QAAI,CAAC,UAAW;AAEhB,QAAI,SAAS,kBAAkB,OAAO,SAAS;AAC9C,aAAO,SAAS,MAAM;AAAA,IACvB;AAEA,QAAI,OAAO,iBAAiB,EAAE,iBAAiB;AAC9C,aAAO,SAAS,OAAO;AAAA,IACxB;AAIA,QAAI,oBAAM,UAAU;AACnB,aAAO,SAAS,KAAK;AACrB,aAAO,SAAS,MAAM;AAAA,IACvB;AAAA,EACD,GAAG,CAAC,QAAQ,SAAS,CAAC;AAGtB,QAAM,oBAAgB;AAAA,IACrB,CAAC,MAAqB;AACrB,UAAI,OAAO,kBAAkB,MAAM,QAAS;AAE5C,cAAQ,EAAE,KAAK;AAAA,QACd,KAAK,SAAS;AACb,cAAI,EAAE,WAAW,EAAE,SAAS;AAC3B,mBAAO,SAAS;AAAA,UACjB;AACA;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA,CAAC,QAAQ,OAAO;AAAA,EACjB;AAGA,QAAM,mBAAe;AAAA,IACpB,CAAC,EAAE,UAAU,MAA6B;AACzC,UAAI,OAAO,kBAAkB,MAAM,QAAS;AAE5C,YAAM,sBAAsB,+BAAY,cAAc,aAAa,EAAE;AACrE,aAAO,YAA0D;AAAA,QAChE,IAAI;AAAA,QACJ;AAAA,QACA,OAAO,EAAE,MAAM,oBAAoB;AAAA,MACpC,CAAC;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,SAAS,IAAI;AAAA,EACvB;AAEA,SAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACJ;AACD;AAGO,SAAS,qBAAqB,QAAgB,SAAoB;AACxE,aAAO;AAAA,IACN;AAAA,IACA,MAAM;AACL,YAAM,iBAAiB,OAAO,kBAAkB;AAChD;AAAA;AAAA,QAEC,mBAAmB,SAClB,mBAAmB,WAAW,OAAO,kBAAkB,MAAM;AAAA;AAAA,IAEhE;AAAA,IACA,CAAC,QAAQ,OAAO;AAAA,EACjB;AACD;AAGO,SAAS,sBAAsB,SAAoB;AACzD,QAAM,aAAS,yBAAU;AACzB,QAAM,gBAAY,wBAAS,aAAa,MAAM,OAAO,kBAAkB,MAAM,SAAS,CAAC,MAAM,CAAC;AAC9F,QAAM,oBAAoB,qBAAqB,QAAQ,OAAO;AAE9D,QAAM,6BAAyB;AAAA,IAC9B,CAAC,MAA0B;AAW1B,aAAO,SAAS;AAAA,QACf,OAAG,8BAAe,CAAC;AAAA,QACnB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,OAAO,OAAO,SAAS,OAAO;AAAA,MAC/B,CAAC;AAED,QAAE,gBAAgB;AAAA,IACnB;AAAA,IACA,CAAC,QAAQ,OAAO;AAAA,EACjB;AAEA,QAAM,kBAAc;AAAA,IACnB,CAAC,MAAkE;AAClE,UAAI,OAAO,kBAAkB,MAAM,QAAS;AAC5C,UAAI,EAAE,eAAe;AAEpB,cAAM,OAAO,EAAE,cAAc,QAAQ,WAAW;AAChD,YAAI,MAAM;AACT,cAAI,KAAK,SAAS,kBAAkB,GAAG;AACtC,8CAAe,CAAC;AAAA,UACjB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA,CAAC,QAAQ,OAAO;AAAA,EACjB;AAEA,QAAM,oBAAmD;AAEzD,SAAO;AAAA,IACN,aAAa;AAAA,IACb,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;",
6
6
  "names": []
7
7
  }
@@ -18,7 +18,6 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var useImageOrVideoAsset_exports = {};
20
20
  __export(useImageOrVideoAsset_exports, {
21
- useAsset: () => useAsset,
22
21
  useImageOrVideoAsset: () => useImageOrVideoAsset
23
22
  });
24
23
  module.exports = __toCommonJS(useImageOrVideoAsset_exports);
@@ -98,5 +97,4 @@ function resolveAssetUrl(editor, assetId, screenScale, exportInfo, callback) {
98
97
  callback(url);
99
98
  });
100
99
  }
101
- const useAsset = useImageOrVideoAsset;
102
100
  //# sourceMappingURL=useImageOrVideoAsset.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/shared/useImageOrVideoAsset.ts"],
4
- "sourcesContent": ["import {\n\tEditor,\n\tSvgExportContext,\n\tTLAssetId,\n\tTLImageAsset,\n\tTLShapeId,\n\tTLVideoAsset,\n\treact,\n\tuseDelaySvgExport,\n\tuseEditor,\n\tuseSvgExportContext,\n} from '@tldraw/editor'\nimport { useEffect, useRef, useState } from 'react'\n\n/**\n * Options for {@link useImageOrVideoAsset}.\n *\n * @public\n */\nexport interface UseImageOrVideoAssetOptions {\n\t/** The asset ID you want a URL for. */\n\tassetId: TLAssetId | null\n\t/**\n\t * The shape the asset is being used for. We won't update the resolved URL while the shape is\n\t * off-screen.\n\t */\n\tshapeId?: TLShapeId\n\t/**\n\t * The width at which the asset will be displayed, in shape-space pixels.\n\t */\n\twidth: number\n}\n\n/**\n * This is a handy helper hook that resolves an asset to an optimized URL for a given shape, or its\n * {@link @tldraw/editor#Editor.createTemporaryAssetPreview | placeholder} if the asset is still\n * uploading. This is used in particular for high-resolution images when you want lower and higher\n * resolution depending on the size of the image on the canvas and the zoom level.\n *\n * For image scaling to work, you need to implement scaled URLs in\n * {@link @tldraw/tlschema#TLAssetStore.resolve}.\n *\n * @public\n */\nexport function useImageOrVideoAsset({ shapeId, assetId, width }: UseImageOrVideoAssetOptions) {\n\tconst editor = useEditor()\n\tconst exportInfo = useSvgExportContext()\n\tconst exportIsReady = useDelaySvgExport()\n\n\t// We use a state to store the result of the asset resolution, and we're going to avoid updating this whenever we can\n\tconst [result, setResult] = useState<{\n\t\tasset: (TLImageAsset | TLVideoAsset) | null\n\t\turl: string | null\n\t}>(() => ({\n\t\tasset: assetId ? (editor.getAsset<TLImageAsset | TLVideoAsset>(assetId) ?? null) : null,\n\t\turl: null as string | null,\n\t}))\n\n\t// A flag for whether we've resolved the asset URL at least once, after which we can debounce\n\tconst didAlreadyResolve = useRef(false)\n\n\t// The last URL that we've seen for the shape\n\tconst previousUrl = useRef<string | null>(null)\n\n\tuseEffect(() => {\n\t\tif (!assetId) return\n\n\t\tlet isCancelled = false\n\t\tlet cancelDebounceFn: (() => void) | undefined\n\n\t\tconst cleanupEffectScheduler = react('update state', () => {\n\t\t\tif (!exportInfo && shapeId && editor.getCulledShapes().has(shapeId)) return\n\n\t\t\t// Get the fresh asset\n\t\t\tconst asset = editor.getAsset<TLImageAsset | TLVideoAsset>(assetId)\n\t\t\tif (!asset) {\n\t\t\t\t// If the asset is deleted, such as when an upload fails, set the URL to null\n\t\t\t\tsetResult((prev) => ({ ...prev, asset: null, url: null }))\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Set initial preview for the shape if it has no source (if it was pasted into a local project as base64)\n\t\t\tif (!asset.props.src) {\n\t\t\t\tconst preview = editor.getTemporaryAssetPreview(asset.id)\n\t\t\t\tif (preview) {\n\t\t\t\t\tif (previousUrl.current !== preview) {\n\t\t\t\t\t\tpreviousUrl.current = preview // just for kicks, let's save the url as the previous URL\n\t\t\t\t\t\tsetResult((prev) => ({ ...prev, isPlaceholder: true, url: preview })) // set the preview as the URL\n\t\t\t\t\t\texportIsReady() // let the SVG export know we're ready for export\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// aside ...we could bail here if the only thing that has changed is the shape has changed from culled to not culled\n\n\t\t\tconst screenScale = exportInfo\n\t\t\t\t? exportInfo.scale * (width / asset.props.w)\n\t\t\t\t: editor.getZoomLevel() * (width / asset.props.w)\n\n\t\t\tfunction resolve(asset: TLImageAsset | TLVideoAsset, url: string | null) {\n\t\t\t\tif (isCancelled) return // don't update if the hook has remounted\n\t\t\t\tif (previousUrl.current === url) return // don't update the state if the url is the same\n\t\t\t\tdidAlreadyResolve.current = true // mark that we've resolved our first image\n\t\t\t\tpreviousUrl.current = url // keep the url around to compare with the next one\n\t\t\t\tsetResult({ asset, url })\n\t\t\t\texportIsReady() // let the SVG export know we're ready for export\n\t\t\t}\n\n\t\t\t// If we already resolved the URL, debounce fetching potentially multiple image variations.\n\t\t\tif (didAlreadyResolve.current) {\n\t\t\t\tlet tick = 0\n\n\t\t\t\tconst resolveAssetAfterAWhile = () => {\n\t\t\t\t\ttick++\n\t\t\t\t\tif (tick > 500 / 16) {\n\t\t\t\t\t\t// debounce for 500ms\n\t\t\t\t\t\tresolveAssetUrl(editor, assetId, screenScale, exportInfo, (url) => resolve(asset, url))\n\t\t\t\t\t\tcancelDebounceFn?.()\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcancelDebounceFn?.()\n\t\t\t\teditor.on('tick', resolveAssetAfterAWhile)\n\t\t\t\tcancelDebounceFn = () => editor.off('tick', resolveAssetAfterAWhile)\n\t\t\t} else {\n\t\t\t\tresolveAssetUrl(editor, assetId, screenScale, exportInfo, (url) => resolve(asset, url))\n\t\t\t}\n\t\t})\n\n\t\treturn () => {\n\t\t\tcleanupEffectScheduler()\n\t\t\tcancelDebounceFn?.()\n\t\t\tisCancelled = true\n\t\t}\n\t}, [editor, assetId, exportInfo, exportIsReady, shapeId, width])\n\n\treturn result\n}\n\nfunction resolveAssetUrl(\n\teditor: Editor,\n\tassetId: TLAssetId,\n\tscreenScale: number,\n\texportInfo: SvgExportContext | null,\n\tcallback: (url: string | null) => void\n) {\n\teditor\n\t\t.resolveAssetUrl(assetId, {\n\t\t\tscreenScale,\n\t\t\tshouldResolveToOriginal: exportInfo ? exportInfo.pixelRatio === null : false,\n\t\t\tdpr: exportInfo?.pixelRatio ?? undefined,\n\t\t})\n\t\t// There's a weird bug with out debounce function that doesn't\n\t\t// make it work right with async functions, so we use a callback\n\t\t// here instead of returning a promise.\n\t\t.then((url) => {\n\t\t\tcallback(url)\n\t\t})\n}\n\n/**\n * @deprecated Use {@link useImageOrVideoAsset} instead.\n *\n * @public\n */\nexport const useAsset = useImageOrVideoAsset\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAWO;AACP,mBAA4C;AAgCrC,SAAS,qBAAqB,EAAE,SAAS,SAAS,MAAM,GAAgC;AAC9F,QAAM,aAAS,yBAAU;AACzB,QAAM,iBAAa,mCAAoB;AACvC,QAAM,oBAAgB,iCAAkB;AAGxC,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAGzB,OAAO;AAAA,IACT,OAAO,UAAW,OAAO,SAAsC,OAAO,KAAK,OAAQ;AAAA,IACnF,KAAK;AAAA,EACN,EAAE;AAGF,QAAM,wBAAoB,qBAAO,KAAK;AAGtC,QAAM,kBAAc,qBAAsB,IAAI;AAE9C,8BAAU,MAAM;AACf,QAAI,CAAC,QAAS;AAEd,QAAI,cAAc;AAClB,QAAI;AAEJ,UAAM,6BAAyB,qBAAM,gBAAgB,MAAM;AAC1D,UAAI,CAAC,cAAc,WAAW,OAAO,gBAAgB,EAAE,IAAI,OAAO,EAAG;AAGrE,YAAM,QAAQ,OAAO,SAAsC,OAAO;AAClE,UAAI,CAAC,OAAO;AAEX,kBAAU,CAAC,UAAU,EAAE,GAAG,MAAM,OAAO,MAAM,KAAK,KAAK,EAAE;AACzD;AAAA,MACD;AAGA,UAAI,CAAC,MAAM,MAAM,KAAK;AACrB,cAAM,UAAU,OAAO,yBAAyB,MAAM,EAAE;AACxD,YAAI,SAAS;AACZ,cAAI,YAAY,YAAY,SAAS;AACpC,wBAAY,UAAU;AACtB,sBAAU,CAAC,UAAU,EAAE,GAAG,MAAM,eAAe,MAAM,KAAK,QAAQ,EAAE;AACpE,0BAAc;AAAA,UACf;AACA;AAAA,QACD;AAAA,MACD;AAIA,YAAM,cAAc,aACjB,WAAW,SAAS,QAAQ,MAAM,MAAM,KACxC,OAAO,aAAa,KAAK,QAAQ,MAAM,MAAM;AAEhD,eAAS,QAAQA,QAAoC,KAAoB;AACxE,YAAI,YAAa;AACjB,YAAI,YAAY,YAAY,IAAK;AACjC,0BAAkB,UAAU;AAC5B,oBAAY,UAAU;AACtB,kBAAU,EAAE,OAAAA,QAAO,IAAI,CAAC;AACxB,sBAAc;AAAA,MACf;AAGA,UAAI,kBAAkB,SAAS;AAC9B,YAAI,OAAO;AAEX,cAAM,0BAA0B,MAAM;AACrC;AACA,cAAI,OAAO,MAAM,IAAI;AAEpB,4BAAgB,QAAQ,SAAS,aAAa,YAAY,CAAC,QAAQ,QAAQ,OAAO,GAAG,CAAC;AACtF,+BAAmB;AAAA,UACpB;AAAA,QACD;AAEA,2BAAmB;AACnB,eAAO,GAAG,QAAQ,uBAAuB;AACzC,2BAAmB,MAAM,OAAO,IAAI,QAAQ,uBAAuB;AAAA,MACpE,OAAO;AACN,wBAAgB,QAAQ,SAAS,aAAa,YAAY,CAAC,QAAQ,QAAQ,OAAO,GAAG,CAAC;AAAA,MACvF;AAAA,IACD,CAAC;AAED,WAAO,MAAM;AACZ,6BAAuB;AACvB,yBAAmB;AACnB,oBAAc;AAAA,IACf;AAAA,EACD,GAAG,CAAC,QAAQ,SAAS,YAAY,eAAe,SAAS,KAAK,CAAC;AAE/D,SAAO;AACR;AAEA,SAAS,gBACR,QACA,SACA,aACA,YACA,UACC;AACD,SACE,gBAAgB,SAAS;AAAA,IACzB;AAAA,IACA,yBAAyB,aAAa,WAAW,eAAe,OAAO;AAAA,IACvE,KAAK,YAAY,cAAc;AAAA,EAChC,CAAC,EAIA,KAAK,CAAC,QAAQ;AACd,aAAS,GAAG;AAAA,EACb,CAAC;AACH;AAOO,MAAM,WAAW;",
4
+ "sourcesContent": ["import {\n\tEditor,\n\tSvgExportContext,\n\tTLAssetId,\n\tTLImageAsset,\n\tTLShapeId,\n\tTLVideoAsset,\n\treact,\n\tuseDelaySvgExport,\n\tuseEditor,\n\tuseSvgExportContext,\n} from '@tldraw/editor'\nimport { useEffect, useRef, useState } from 'react'\n\n/**\n * Options for {@link useImageOrVideoAsset}.\n *\n * @public\n */\nexport interface UseImageOrVideoAssetOptions {\n\t/** The asset ID you want a URL for. */\n\tassetId: TLAssetId | null\n\t/**\n\t * The shape the asset is being used for. We won't update the resolved URL while the shape is\n\t * off-screen.\n\t */\n\tshapeId?: TLShapeId\n\t/**\n\t * The width at which the asset will be displayed, in shape-space pixels.\n\t */\n\twidth: number\n}\n\n/**\n * This is a handy helper hook that resolves an asset to an optimized URL for a given shape, or its\n * {@link @tldraw/editor#Editor.createTemporaryAssetPreview | placeholder} if the asset is still\n * uploading. This is used in particular for high-resolution images when you want lower and higher\n * resolution depending on the size of the image on the canvas and the zoom level.\n *\n * For image scaling to work, you need to implement scaled URLs in\n * {@link @tldraw/tlschema#TLAssetStore.resolve}.\n *\n * @public\n */\nexport function useImageOrVideoAsset({ shapeId, assetId, width }: UseImageOrVideoAssetOptions) {\n\tconst editor = useEditor()\n\tconst exportInfo = useSvgExportContext()\n\tconst exportIsReady = useDelaySvgExport()\n\n\t// We use a state to store the result of the asset resolution, and we're going to avoid updating this whenever we can\n\tconst [result, setResult] = useState<{\n\t\tasset: (TLImageAsset | TLVideoAsset) | null\n\t\turl: string | null\n\t}>(() => ({\n\t\tasset: assetId ? (editor.getAsset<TLImageAsset | TLVideoAsset>(assetId) ?? null) : null,\n\t\turl: null as string | null,\n\t}))\n\n\t// A flag for whether we've resolved the asset URL at least once, after which we can debounce\n\tconst didAlreadyResolve = useRef(false)\n\n\t// The last URL that we've seen for the shape\n\tconst previousUrl = useRef<string | null>(null)\n\n\tuseEffect(() => {\n\t\tif (!assetId) return\n\n\t\tlet isCancelled = false\n\t\tlet cancelDebounceFn: (() => void) | undefined\n\n\t\tconst cleanupEffectScheduler = react('update state', () => {\n\t\t\tif (!exportInfo && shapeId && editor.getCulledShapes().has(shapeId)) return\n\n\t\t\t// Get the fresh asset\n\t\t\tconst asset = editor.getAsset<TLImageAsset | TLVideoAsset>(assetId)\n\t\t\tif (!asset) {\n\t\t\t\t// If the asset is deleted, such as when an upload fails, set the URL to null\n\t\t\t\tsetResult((prev) => ({ ...prev, asset: null, url: null }))\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Set initial preview for the shape if it has no source (if it was pasted into a local project as base64)\n\t\t\tif (!asset.props.src) {\n\t\t\t\tconst preview = editor.getTemporaryAssetPreview(asset.id)\n\t\t\t\tif (preview) {\n\t\t\t\t\tif (previousUrl.current !== preview) {\n\t\t\t\t\t\tpreviousUrl.current = preview // just for kicks, let's save the url as the previous URL\n\t\t\t\t\t\tsetResult((prev) => ({ ...prev, isPlaceholder: true, url: preview })) // set the preview as the URL\n\t\t\t\t\t\texportIsReady() // let the SVG export know we're ready for export\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// aside ...we could bail here if the only thing that has changed is the shape has changed from culled to not culled\n\n\t\t\tconst screenScale = exportInfo\n\t\t\t\t? exportInfo.scale * (width / asset.props.w)\n\t\t\t\t: editor.getZoomLevel() * (width / asset.props.w)\n\n\t\t\tfunction resolve(asset: TLImageAsset | TLVideoAsset, url: string | null) {\n\t\t\t\tif (isCancelled) return // don't update if the hook has remounted\n\t\t\t\tif (previousUrl.current === url) return // don't update the state if the url is the same\n\t\t\t\tdidAlreadyResolve.current = true // mark that we've resolved our first image\n\t\t\t\tpreviousUrl.current = url // keep the url around to compare with the next one\n\t\t\t\tsetResult({ asset, url })\n\t\t\t\texportIsReady() // let the SVG export know we're ready for export\n\t\t\t}\n\n\t\t\t// If we already resolved the URL, debounce fetching potentially multiple image variations.\n\t\t\tif (didAlreadyResolve.current) {\n\t\t\t\tlet tick = 0\n\n\t\t\t\tconst resolveAssetAfterAWhile = () => {\n\t\t\t\t\ttick++\n\t\t\t\t\tif (tick > 500 / 16) {\n\t\t\t\t\t\t// debounce for 500ms\n\t\t\t\t\t\tresolveAssetUrl(editor, assetId, screenScale, exportInfo, (url) => resolve(asset, url))\n\t\t\t\t\t\tcancelDebounceFn?.()\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcancelDebounceFn?.()\n\t\t\t\teditor.on('tick', resolveAssetAfterAWhile)\n\t\t\t\tcancelDebounceFn = () => editor.off('tick', resolveAssetAfterAWhile)\n\t\t\t} else {\n\t\t\t\tresolveAssetUrl(editor, assetId, screenScale, exportInfo, (url) => resolve(asset, url))\n\t\t\t}\n\t\t})\n\n\t\treturn () => {\n\t\t\tcleanupEffectScheduler()\n\t\t\tcancelDebounceFn?.()\n\t\t\tisCancelled = true\n\t\t}\n\t}, [editor, assetId, exportInfo, exportIsReady, shapeId, width])\n\n\treturn result\n}\n\nfunction resolveAssetUrl(\n\teditor: Editor,\n\tassetId: TLAssetId,\n\tscreenScale: number,\n\texportInfo: SvgExportContext | null,\n\tcallback: (url: string | null) => void\n) {\n\teditor\n\t\t.resolveAssetUrl(assetId, {\n\t\t\tscreenScale,\n\t\t\tshouldResolveToOriginal: exportInfo ? exportInfo.pixelRatio === null : false,\n\t\t\tdpr: exportInfo?.pixelRatio ?? undefined,\n\t\t})\n\t\t// There's a weird bug with out debounce function that doesn't\n\t\t// make it work right with async functions, so we use a callback\n\t\t// here instead of returning a promise.\n\t\t.then((url) => {\n\t\t\tcallback(url)\n\t\t})\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAWO;AACP,mBAA4C;AAgCrC,SAAS,qBAAqB,EAAE,SAAS,SAAS,MAAM,GAAgC;AAC9F,QAAM,aAAS,yBAAU;AACzB,QAAM,iBAAa,mCAAoB;AACvC,QAAM,oBAAgB,iCAAkB;AAGxC,QAAM,CAAC,QAAQ,SAAS,QAAI,uBAGzB,OAAO;AAAA,IACT,OAAO,UAAW,OAAO,SAAsC,OAAO,KAAK,OAAQ;AAAA,IACnF,KAAK;AAAA,EACN,EAAE;AAGF,QAAM,wBAAoB,qBAAO,KAAK;AAGtC,QAAM,kBAAc,qBAAsB,IAAI;AAE9C,8BAAU,MAAM;AACf,QAAI,CAAC,QAAS;AAEd,QAAI,cAAc;AAClB,QAAI;AAEJ,UAAM,6BAAyB,qBAAM,gBAAgB,MAAM;AAC1D,UAAI,CAAC,cAAc,WAAW,OAAO,gBAAgB,EAAE,IAAI,OAAO,EAAG;AAGrE,YAAM,QAAQ,OAAO,SAAsC,OAAO;AAClE,UAAI,CAAC,OAAO;AAEX,kBAAU,CAAC,UAAU,EAAE,GAAG,MAAM,OAAO,MAAM,KAAK,KAAK,EAAE;AACzD;AAAA,MACD;AAGA,UAAI,CAAC,MAAM,MAAM,KAAK;AACrB,cAAM,UAAU,OAAO,yBAAyB,MAAM,EAAE;AACxD,YAAI,SAAS;AACZ,cAAI,YAAY,YAAY,SAAS;AACpC,wBAAY,UAAU;AACtB,sBAAU,CAAC,UAAU,EAAE,GAAG,MAAM,eAAe,MAAM,KAAK,QAAQ,EAAE;AACpE,0BAAc;AAAA,UACf;AACA;AAAA,QACD;AAAA,MACD;AAIA,YAAM,cAAc,aACjB,WAAW,SAAS,QAAQ,MAAM,MAAM,KACxC,OAAO,aAAa,KAAK,QAAQ,MAAM,MAAM;AAEhD,eAAS,QAAQA,QAAoC,KAAoB;AACxE,YAAI,YAAa;AACjB,YAAI,YAAY,YAAY,IAAK;AACjC,0BAAkB,UAAU;AAC5B,oBAAY,UAAU;AACtB,kBAAU,EAAE,OAAAA,QAAO,IAAI,CAAC;AACxB,sBAAc;AAAA,MACf;AAGA,UAAI,kBAAkB,SAAS;AAC9B,YAAI,OAAO;AAEX,cAAM,0BAA0B,MAAM;AACrC;AACA,cAAI,OAAO,MAAM,IAAI;AAEpB,4BAAgB,QAAQ,SAAS,aAAa,YAAY,CAAC,QAAQ,QAAQ,OAAO,GAAG,CAAC;AACtF,+BAAmB;AAAA,UACpB;AAAA,QACD;AAEA,2BAAmB;AACnB,eAAO,GAAG,QAAQ,uBAAuB;AACzC,2BAAmB,MAAM,OAAO,IAAI,QAAQ,uBAAuB;AAAA,MACpE,OAAO;AACN,wBAAgB,QAAQ,SAAS,aAAa,YAAY,CAAC,QAAQ,QAAQ,OAAO,GAAG,CAAC;AAAA,MACvF;AAAA,IACD,CAAC;AAED,WAAO,MAAM;AACZ,6BAAuB;AACvB,yBAAmB;AACnB,oBAAc;AAAA,IACf;AAAA,EACD,GAAG,CAAC,QAAQ,SAAS,YAAY,eAAe,SAAS,KAAK,CAAC;AAE/D,SAAO;AACR;AAEA,SAAS,gBACR,QACA,SACA,aACA,YACA,UACC;AACD,SACE,gBAAgB,SAAS;AAAA,IACzB;AAAA,IACA,yBAAyB,aAAa,WAAW,eAAe,OAAO;AAAA,IACvE,KAAK,YAAY,cAAc;AAAA,EAChC,CAAC,EAIA,KAAK,CAAC,QAAQ;AACd,aAAS,GAAG;AAAA,EACb,CAAC;AACH;",
6
6
  "names": ["asset"]
7
7
  }
@@ -70,8 +70,8 @@ const PlainTextArea = import_react.default.forwardRef(function TextArea({
70
70
  onChange,
71
71
  onKeyDown: (e) => handleKeyDown(e.nativeEvent),
72
72
  onBlur: handleBlur,
73
- onTouchEnd: import_editor.stopEventPropagation,
74
- onContextMenu: isEditing ? import_editor.stopEventPropagation : void 0,
73
+ onTouchEnd: import_editor.markEventAsHandled,
74
+ onContextMenu: isEditing ? (e) => e.stopPropagation() : void 0,
75
75
  onPointerDown: handleInputPointerDown,
76
76
  onPaste: handlePaste,
77
77
  onDoubleClick: handleDoubleClick,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/text/PlainTextArea.tsx"],
4
- "sourcesContent": ["import { preventDefault, stopEventPropagation } from '@tldraw/editor'\nimport React from 'react'\nimport { TextAreaProps } from './RichTextArea'\n\n/**\n * A plain text area that can be used for basic editing text.\n *\n * @public @react\n */\nexport const PlainTextArea = React.forwardRef<HTMLTextAreaElement, TextAreaProps>(function TextArea(\n\t{\n\t\tisEditing,\n\t\ttext,\n\t\thandleFocus,\n\t\thandleChange,\n\t\thandleKeyDown,\n\t\thandlePaste,\n\t\thandleBlur,\n\t\thandleInputPointerDown,\n\t\thandleDoubleClick,\n\t},\n\tref\n) {\n\tconst onChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n\t\thandleChange({ plaintext: e.target.value })\n\t}\n\n\treturn (\n\t\t<textarea\n\t\t\tref={ref}\n\t\t\tclassName=\"tl-text tl-text-input\"\n\t\t\tname=\"text\"\n\t\t\ttabIndex={-1}\n\t\t\tdisabled={!isEditing}\n\t\t\treadOnly={!isEditing}\n\t\t\tautoComplete=\"off\"\n\t\t\tautoCapitalize=\"off\"\n\t\t\tautoCorrect=\"off\"\n\t\t\tautoSave=\"off\"\n\t\t\tplaceholder=\"\"\n\t\t\tspellCheck=\"true\"\n\t\t\twrap=\"off\"\n\t\t\tdir=\"auto\"\n\t\t\tdefaultValue={text}\n\t\t\tonFocus={handleFocus}\n\t\t\tonChange={onChange}\n\t\t\tonKeyDown={(e) => handleKeyDown(e.nativeEvent)}\n\t\t\tonBlur={handleBlur}\n\t\t\tonTouchEnd={stopEventPropagation}\n\t\t\tonContextMenu={isEditing ? stopEventPropagation : undefined}\n\t\t\tonPointerDown={handleInputPointerDown}\n\t\t\tonPaste={handlePaste}\n\t\t\tonDoubleClick={handleDoubleClick}\n\t\t\t// On FF, there's a behavior where dragging a selection will grab that selection into\n\t\t\t// the drag event. However, once the drag is over, and you select away from the textarea,\n\t\t\t// starting a drag over the textarea will restart a selection drag instead of a shape drag.\n\t\t\t// This prevents that default behavior in FF.\n\t\t\tonDragStart={preventDefault}\n\t\t/>\n\t)\n})\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA4BE;AA5BF,oBAAqD;AACrD,mBAAkB;AAQX,MAAM,gBAAgB,aAAAA,QAAM,WAA+C,SAAS,SAC1F;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GACA,KACC;AACD,QAAM,WAAW,CAAC,MAA8C;AAC/D,iBAAa,EAAE,WAAW,EAAE,OAAO,MAAM,CAAC;AAAA,EAC3C;AAEA,SACC;AAAA,IAAC;AAAA;AAAA,MACA;AAAA,MACA,WAAU;AAAA,MACV,MAAK;AAAA,MACL,UAAU;AAAA,MACV,UAAU,CAAC;AAAA,MACX,UAAU,CAAC;AAAA,MACX,cAAa;AAAA,MACb,gBAAe;AAAA,MACf,aAAY;AAAA,MACZ,UAAS;AAAA,MACT,aAAY;AAAA,MACZ,YAAW;AAAA,MACX,MAAK;AAAA,MACL,KAAI;AAAA,MACJ,cAAc;AAAA,MACd,SAAS;AAAA,MACT;AAAA,MACA,WAAW,CAAC,MAAM,cAAc,EAAE,WAAW;AAAA,MAC7C,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,eAAe,YAAY,qCAAuB;AAAA,MAClD,eAAe;AAAA,MACf,SAAS;AAAA,MACT,eAAe;AAAA,MAKf,aAAa;AAAA;AAAA,EACd;AAEF,CAAC;",
4
+ "sourcesContent": ["import { markEventAsHandled, preventDefault } from '@tldraw/editor'\nimport React from 'react'\nimport { TextAreaProps } from './RichTextArea'\n\n/**\n * A plain text area that can be used for basic editing text.\n *\n * @public @react\n */\nexport const PlainTextArea = React.forwardRef<HTMLTextAreaElement, TextAreaProps>(function TextArea(\n\t{\n\t\tisEditing,\n\t\ttext,\n\t\thandleFocus,\n\t\thandleChange,\n\t\thandleKeyDown,\n\t\thandlePaste,\n\t\thandleBlur,\n\t\thandleInputPointerDown,\n\t\thandleDoubleClick,\n\t},\n\tref\n) {\n\tconst onChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n\t\thandleChange({ plaintext: e.target.value })\n\t}\n\n\treturn (\n\t\t<textarea\n\t\t\tref={ref}\n\t\t\tclassName=\"tl-text tl-text-input\"\n\t\t\tname=\"text\"\n\t\t\ttabIndex={-1}\n\t\t\tdisabled={!isEditing}\n\t\t\treadOnly={!isEditing}\n\t\t\tautoComplete=\"off\"\n\t\t\tautoCapitalize=\"off\"\n\t\t\tautoCorrect=\"off\"\n\t\t\tautoSave=\"off\"\n\t\t\tplaceholder=\"\"\n\t\t\tspellCheck=\"true\"\n\t\t\twrap=\"off\"\n\t\t\tdir=\"auto\"\n\t\t\tdefaultValue={text}\n\t\t\tonFocus={handleFocus}\n\t\t\tonChange={onChange}\n\t\t\tonKeyDown={(e) => handleKeyDown(e.nativeEvent)}\n\t\t\tonBlur={handleBlur}\n\t\t\tonTouchEnd={markEventAsHandled}\n\t\t\tonContextMenu={isEditing ? (e) => e.stopPropagation() : undefined}\n\t\t\tonPointerDown={handleInputPointerDown}\n\t\t\tonPaste={handlePaste}\n\t\t\tonDoubleClick={handleDoubleClick}\n\t\t\t// On FF, there's a behavior where dragging a selection will grab that selection into\n\t\t\t// the drag event. However, once the drag is over, and you select away from the textarea,\n\t\t\t// starting a drag over the textarea will restart a selection drag instead of a shape drag.\n\t\t\t// This prevents that default behavior in FF.\n\t\t\tonDragStart={preventDefault}\n\t\t/>\n\t)\n})\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA4BE;AA5BF,oBAAmD;AACnD,mBAAkB;AAQX,MAAM,gBAAgB,aAAAA,QAAM,WAA+C,SAAS,SAC1F;AAAA,EACC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GACA,KACC;AACD,QAAM,WAAW,CAAC,MAA8C;AAC/D,iBAAa,EAAE,WAAW,EAAE,OAAO,MAAM,CAAC;AAAA,EAC3C;AAEA,SACC;AAAA,IAAC;AAAA;AAAA,MACA;AAAA,MACA,WAAU;AAAA,MACV,MAAK;AAAA,MACL,UAAU;AAAA,MACV,UAAU,CAAC;AAAA,MACX,UAAU,CAAC;AAAA,MACX,cAAa;AAAA,MACb,gBAAe;AAAA,MACf,aAAY;AAAA,MACZ,UAAS;AAAA,MACT,aAAY;AAAA,MACZ,YAAW;AAAA,MACX,MAAK;AAAA,MACL,KAAI;AAAA,MACJ,cAAc;AAAA,MACd,SAAS;AAAA,MACT;AAAA,MACA,WAAW,CAAC,MAAM,cAAc,EAAE,WAAW;AAAA,MAC7C,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,eAAe,YAAY,CAAC,MAAM,EAAE,gBAAgB,IAAI;AAAA,MACxD,eAAe;AAAA,MACf,SAAS;AAAA,MACT,eAAe;AAAA,MAKf,aAAa;AAAA;AAAA,EACd;AAEF,CAAC;",
6
6
  "names": ["React"]
7
7
  }
@@ -183,9 +183,9 @@ const RichTextArea = import_react2.default.forwardRef(function RichTextArea2({
183
183
  tabIndex: -1,
184
184
  "data-testid": "rich-text-area",
185
185
  className: "tl-rich-text tl-text tl-text-input",
186
- onContextMenu: isEditing ? import_editor.stopEventPropagation : void 0,
187
- onPointerDownCapture: import_editor.stopEventPropagation,
188
- onTouchEnd: import_editor.stopEventPropagation,
186
+ onContextMenu: isEditing ? (e) => e.stopPropagation() : void 0,
187
+ onPointerDownCapture: (e) => e.stopPropagation(),
188
+ onTouchEnd: (e) => e.stopPropagation(),
189
189
  onDragStart: import_editor.preventDefault,
190
190
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tl-rich-text", ref: rTextEditorEl })
191
191
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/shapes/text/RichTextArea.tsx"],
4
- "sourcesContent": ["import { EditorView } from '@tiptap/pm/view'\nimport {\n\tEditorEvents,\n\tJSONContent,\n\tEditor as TextEditor,\n\ttype Editor as TTEditor,\n} from '@tiptap/react'\nimport {\n\tEditor,\n\tTLRichText,\n\tTLShapeId,\n\tpreventDefault,\n\tstopEventPropagation,\n\tuseEditor,\n\tuseEvent,\n\tuseUniqueSafeId,\n} from '@tldraw/editor'\nimport React, { useLayoutEffect, useRef } from 'react'\n\n/** @public */\nexport interface TextAreaProps {\n\tisEditing: boolean\n\ttext?: string\n\tshapeId: TLShapeId\n\trichText?: TLRichText\n\thandleFocus(): void\n\thandleBlur(): void\n\thandleKeyDown(e: KeyboardEvent): void\n\thandleChange(changeInfo: { plaintext?: string; richText?: TLRichText }): void\n\thandleInputPointerDown(e: React.PointerEvent<HTMLElement>): void\n\thandleDoubleClick(e: any): any\n\thandlePaste(e: ClipboardEvent | React.ClipboardEvent<HTMLTextAreaElement>): void\n\thasCustomTabBehavior?: boolean\n}\n\n/**\n * N.B. In Development mode you need to ensure you're testing this without StrictMode on.\n * Otherwise it's not gonna work as expected on iOS.\n * Specifically, it means that the virtual keyboard won't pop open sometimes\n * (iOS starts flipping out when you render multiple times when trying to focus something) .\n */\n\n/**\n * A rich text area that can be used for editing text with rich text formatting.\n * This component uses the TipTap editor under the hood.\n *\n * @public @react\n */\nexport const RichTextArea = React.forwardRef<HTMLDivElement, TextAreaProps>(function RichTextArea(\n\t{\n\t\tshapeId,\n\t\tisEditing,\n\t\trichText,\n\t\thandleFocus,\n\t\thandleChange,\n\t\thandleBlur,\n\t\thandleKeyDown,\n\t\thandleDoubleClick,\n\t\thasCustomTabBehavior,\n\t\thandlePaste,\n\t},\n\tref\n) {\n\tconst editor = useEditor()\n\tconst tipTapId = useUniqueSafeId('tip-tap-editor')\n\tconst tipTapConfig = editor.getTextOptions().tipTapConfig\n\n\tconst rInitialRichText = useRef(richText)\n\tconst rTextEditor = useRef<TTEditor | null>(null)\n\tconst rTextEditorEl = useRef<HTMLDivElement>(null)\n\n\tuseLayoutEffect(() => {\n\t\tif (!rTextEditor.current) {\n\t\t\trInitialRichText.current = richText\n\t\t} else if (rInitialRichText.current !== richText) {\n\t\t\trTextEditor.current.commands.setContent(richText as JSONContent)\n\t\t}\n\t}, [richText])\n\n\t// The order of events is:\n\t// - editor begins editing any shape\n\t// - we set listeners for select all / place caret events\n\t// - if the user is editing this shape, this component is rendered\n\t// - editor emits the select all event / place caret event\n\t// - the text editor is onCreate callback is called\n\tconst rCreateInfo = useRef({\n\t\tselectAll: false,\n\t\tcaretPosition: null as { x: number; y: number } | null,\n\t})\n\n\tuseLayoutEffect(() => {\n\t\tfunction selectAllIfEditing(event: { shapeId: TLShapeId }) {\n\t\t\tif (event.shapeId === editor.getEditingShapeId()) {\n\t\t\t\trCreateInfo.current.selectAll = true\n\t\t\t}\n\t\t}\n\n\t\tfunction placeCaret(event: { shapeId: TLShapeId; point: { x: number; y: number } }) {\n\t\t\tif (event.shapeId === editor.getEditingShapeId()) {\n\t\t\t\trCreateInfo.current.caretPosition = event.point\n\t\t\t}\n\t\t}\n\n\t\teditor.on('select-all-text', selectAllIfEditing)\n\t\teditor.on('place-caret', placeCaret)\n\t\treturn () => {\n\t\t\teditor.off('select-all-text', selectAllIfEditing)\n\t\t\teditor.off('place-caret', placeCaret)\n\t\t}\n\t}, [editor, isEditing])\n\n\tconst onChange = useEvent(handleChange)\n\tconst onKeyDown = useEvent(handleKeyDown)\n\tconst onFocus = useEvent(handleFocus)\n\tconst onBlur = useEvent(handleBlur)\n\tconst onDoubleClick = useEvent(handleDoubleClick)\n\tconst onPaste = useEvent(handlePaste)\n\tuseLayoutEffect(() => {\n\t\tif (!isEditing || !tipTapConfig || !rTextEditorEl.current) return\n\n\t\tconst { editorProps, ...restOfTipTapConfig } = tipTapConfig\n\n\t\t// Because React can double-render in Strict Mode, we need to make sure we're not setting\n\t\t// the text editor twice. This became more much more prevalent in React 19, but also it\n\t\t// started manifesting in some cases in Next 14.2 (which maybe patches React 18.3 in weird\n\t\t// ways). So we used to use EditorProvider but we into weird rendering issues.\n\t\tconst textEditorInstance = new TextEditor({\n\t\t\telement: rTextEditorEl.current,\n\t\t\tautofocus: true,\n\t\t\teditable: isEditing,\n\t\t\tonUpdate: (props: EditorEvents['update']) => {\n\t\t\t\tconst content: TLRichText = props.editor.state.doc.toJSON()\n\t\t\t\trInitialRichText.current = content\n\t\t\t\tonChange({ richText: content })\n\t\t\t},\n\t\t\tonFocus,\n\t\t\tonBlur,\n\t\t\t// onCreate is called after a `setTimeout(0)`\n\t\t\tonCreate: (props) => {\n\t\t\t\t// If we're not still editing the original shape, then don't do anything.\n\t\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\n\t\t\t\tconst textEditor = props.editor\n\t\t\t\teditor.setRichTextEditor(textEditor)\n\n\t\t\t\tconst { selectAll, caretPosition } = rCreateInfo.current\n\n\t\t\t\tif (selectAll) {\n\t\t\t\t\t// Select all of the text\n\t\t\t\t\ttextEditor.chain().focus().selectAll().run()\n\t\t\t\t} else if (caretPosition) {\n\t\t\t\t\t// Set the initial caret screen position\n\t\t\t\t\tconst pos = textEditor.view.posAtCoords({\n\t\t\t\t\t\tleft: caretPosition.x,\n\t\t\t\t\t\ttop: caretPosition.y,\n\t\t\t\t\t})?.pos\n\n\t\t\t\t\tif (pos) {\n\t\t\t\t\t\t// Focus to that position.\n\t\t\t\t\t\ttextEditor.chain().focus().setTextSelection(pos).run()\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If no position, default to select all.\n\t\t\t\t\t\ttextEditor.chain().focus().selectAll().run()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\teditorProps: {\n\t\t\t\thandleKeyDown: (view: EditorView, event: KeyboardEvent) => {\n\t\t\t\t\tif (!hasCustomTabBehavior && event.key === 'Tab') {\n\t\t\t\t\t\thandleTab(editor, view, event)\n\t\t\t\t\t}\n\n\t\t\t\t\tonKeyDown(event)\n\t\t\t\t},\n\t\t\t\thandlePaste: (view: EditorView, event: ClipboardEvent) => {\n\t\t\t\t\tonPaste(event)\n\t\t\t\t\tif (event.defaultPrevented) return true\n\t\t\t\t},\n\t\t\t\thandleDoubleClick: (_view, _pos, event) => onDoubleClick(event),\n\t\t\t\t...editorProps,\n\t\t\t},\n\t\t\tcoreExtensionOptions: {\n\t\t\t\tclipboardTextSerializer: {\n\t\t\t\t\tblockSeparator: '\\n',\n\t\t\t\t},\n\t\t\t},\n\t\t\t...restOfTipTapConfig,\n\t\t\tcontent: rInitialRichText.current as JSONContent,\n\t\t})\n\n\t\t// XXX: When creating a brand new shape and double-clicking into it quickly to edit it,\n\t\t// there's some kind of race condition happening where the editor doesn't focus properly.\n\t\tconst timeout = editor.timers.setTimeout(() => {\n\t\t\tif (rCreateInfo.current.caretPosition || rCreateInfo.current.selectAll) {\n\t\t\t\ttextEditorInstance.commands.focus()\n\t\t\t} else {\n\t\t\t\ttextEditorInstance.commands.focus('end')\n\t\t\t}\n\n\t\t\trCreateInfo.current.selectAll = false\n\t\t\trCreateInfo.current.caretPosition = null\n\t\t}, 100)\n\n\t\trTextEditor.current = textEditorInstance\n\n\t\treturn () => {\n\t\t\trTextEditor.current = null\n\t\t\tclearTimeout(timeout)\n\t\t\ttextEditorInstance.destroy()\n\t\t}\n\t}, [\n\t\tisEditing,\n\t\ttipTapConfig,\n\t\tonFocus,\n\t\tonBlur,\n\t\tonDoubleClick,\n\t\tonChange,\n\t\tonPaste,\n\t\tonKeyDown,\n\t\teditor,\n\t\tshapeId,\n\t\thasCustomTabBehavior,\n\t])\n\n\tif (!isEditing || !tipTapConfig) {\n\t\treturn null\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tid={tipTapId}\n\t\t\tref={ref}\n\t\t\ttabIndex={-1}\n\t\t\tdata-testid=\"rich-text-area\"\n\t\t\tclassName=\"tl-rich-text tl-text tl-text-input\"\n\t\t\tonContextMenu={isEditing ? stopEventPropagation : undefined}\n\t\t\t// N.B. When PointerStateExtension was introduced, this was moved there.\n\t\t\t// However, that caused selecting over list items to break.\n\t\t\t// The handleDOMEvents in TipTap don't seem to support the pointerDownCapture event.\n\t\t\tonPointerDownCapture={stopEventPropagation}\n\t\t\t// This onTouchEnd is important for Android to be able to change selection on text.\n\t\t\tonTouchEnd={stopEventPropagation}\n\t\t\t// On FF, there's a behavior where dragging a selection will grab that selection into\n\t\t\t// the drag event. However, once the drag is over, and you select away from the textarea,\n\t\t\t// starting a drag over the textarea will restart a selection drag instead of a shape drag.\n\t\t\t// This prevents that default behavior in FF.\n\t\t\tonDragStart={preventDefault}\n\t\t>\n\t\t\t<div className=\"tl-rich-text\" ref={rTextEditorEl} />\n\t\t</div>\n\t)\n})\n\n// Prevent exiting the editor when hitting Tab.\n// Also, insert a tab character at the front of the line if the shift key isn't pressed,\n// otherwise if shift is pressed, remove a tab character from the front of the line.\nfunction handleTab(editor: Editor, view: EditorView, event: KeyboardEvent) {\n\t// Don't exit the editor.\n\tevent.preventDefault()\n\n\tconst textEditor = editor.getRichTextEditor()\n\tif (textEditor?.isActive('bulletList') || textEditor?.isActive('orderedList')) return\n\n\tconst { state, dispatch } = view\n\tconst { $from, $to } = state.selection\n\tconst isShift = event.shiftKey\n\n\t// Create a new transaction\n\tlet tr = state.tr\n\n\t// Iterate over each line in the selection in reverse so that the positions\n\t// are stable as we modify the document.\n\tlet pos = $to.end()\n\twhile (pos >= $from.start()) {\n\t\tconst line = state.doc.resolve(pos).blockRange()\n\t\tif (!line) break\n\n\t\tconst lineStart = line.start\n\t\tconst lineEnd = line.end\n\t\tconst lineText = state.doc.textBetween(lineStart, lineEnd, '\\n')\n\n\t\t// Check if the current line or any of its parent nodes are part of a list\n\t\tlet isInList = false\n\t\tstate.doc.nodesBetween(lineStart, lineEnd, (node) => {\n\t\t\tif (node.type.name === 'bulletList' || node.type.name === 'orderedList') {\n\t\t\t\tisInList = true\n\t\t\t\treturn false // Stop iteration\n\t\t\t}\n\t\t})\n\n\t\t// TODO: for now skip over lists. Later, we might consider handling them using\n\t\t// sinkListItem and liftListItem from @tiptap/pm/schema-list\n\t\tif (!isInList) {\n\t\t\tif (!isShift) {\n\t\t\t\t// Insert a tab character at the start of the line\n\t\t\t\ttr = tr.insertText('\\t', lineStart + 1)\n\t\t\t} else {\n\t\t\t\t// Remove a tab character from the start of the line\n\t\t\t\tif (lineText.startsWith('\\t')) {\n\t\t\t\t\ttr = tr.delete(lineStart + 1, lineStart + 2)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpos = lineStart - 1\n\t}\n\n\tconst mappedSelection = state.selection.map(tr.doc, tr.mapping)\n\ttr.setSelection(mappedSelection)\n\n\tif (tr.docChanged) {\n\t\tdispatch(tr)\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { EditorView } from '@tiptap/pm/view'\nimport {\n\tEditorEvents,\n\tJSONContent,\n\tEditor as TextEditor,\n\ttype Editor as TTEditor,\n} from '@tiptap/react'\nimport {\n\tEditor,\n\tTLRichText,\n\tTLShapeId,\n\tpreventDefault,\n\tuseEditor,\n\tuseEvent,\n\tuseUniqueSafeId,\n} from '@tldraw/editor'\nimport React, { useLayoutEffect, useRef } from 'react'\n\n/** @public */\nexport interface TextAreaProps {\n\tisEditing: boolean\n\ttext?: string\n\tshapeId: TLShapeId\n\trichText?: TLRichText\n\thandleFocus(): void\n\thandleBlur(): void\n\thandleKeyDown(e: KeyboardEvent): void\n\thandleChange(changeInfo: { plaintext?: string; richText?: TLRichText }): void\n\thandleInputPointerDown(e: React.PointerEvent<HTMLElement>): void\n\thandleDoubleClick(e: any): any\n\thandlePaste(e: ClipboardEvent | React.ClipboardEvent<HTMLTextAreaElement>): void\n\thasCustomTabBehavior?: boolean\n}\n\n/**\n * N.B. In Development mode you need to ensure you're testing this without StrictMode on.\n * Otherwise it's not gonna work as expected on iOS.\n * Specifically, it means that the virtual keyboard won't pop open sometimes\n * (iOS starts flipping out when you render multiple times when trying to focus something) .\n */\n\n/**\n * A rich text area that can be used for editing text with rich text formatting.\n * This component uses the TipTap editor under the hood.\n *\n * @public @react\n */\nexport const RichTextArea = React.forwardRef<HTMLDivElement, TextAreaProps>(function RichTextArea(\n\t{\n\t\tshapeId,\n\t\tisEditing,\n\t\trichText,\n\t\thandleFocus,\n\t\thandleChange,\n\t\thandleBlur,\n\t\thandleKeyDown,\n\t\thandleDoubleClick,\n\t\thasCustomTabBehavior,\n\t\thandlePaste,\n\t},\n\tref\n) {\n\tconst editor = useEditor()\n\tconst tipTapId = useUniqueSafeId('tip-tap-editor')\n\tconst tipTapConfig = editor.getTextOptions().tipTapConfig\n\n\tconst rInitialRichText = useRef(richText)\n\tconst rTextEditor = useRef<TTEditor | null>(null)\n\tconst rTextEditorEl = useRef<HTMLDivElement>(null)\n\n\tuseLayoutEffect(() => {\n\t\tif (!rTextEditor.current) {\n\t\t\trInitialRichText.current = richText\n\t\t} else if (rInitialRichText.current !== richText) {\n\t\t\trTextEditor.current.commands.setContent(richText as JSONContent)\n\t\t}\n\t}, [richText])\n\n\t// The order of events is:\n\t// - editor begins editing any shape\n\t// - we set listeners for select all / place caret events\n\t// - if the user is editing this shape, this component is rendered\n\t// - editor emits the select all event / place caret event\n\t// - the text editor is onCreate callback is called\n\tconst rCreateInfo = useRef({\n\t\tselectAll: false,\n\t\tcaretPosition: null as { x: number; y: number } | null,\n\t})\n\n\tuseLayoutEffect(() => {\n\t\tfunction selectAllIfEditing(event: { shapeId: TLShapeId }) {\n\t\t\tif (event.shapeId === editor.getEditingShapeId()) {\n\t\t\t\trCreateInfo.current.selectAll = true\n\t\t\t}\n\t\t}\n\n\t\tfunction placeCaret(event: { shapeId: TLShapeId; point: { x: number; y: number } }) {\n\t\t\tif (event.shapeId === editor.getEditingShapeId()) {\n\t\t\t\trCreateInfo.current.caretPosition = event.point\n\t\t\t}\n\t\t}\n\n\t\teditor.on('select-all-text', selectAllIfEditing)\n\t\teditor.on('place-caret', placeCaret)\n\t\treturn () => {\n\t\t\teditor.off('select-all-text', selectAllIfEditing)\n\t\t\teditor.off('place-caret', placeCaret)\n\t\t}\n\t}, [editor, isEditing])\n\n\tconst onChange = useEvent(handleChange)\n\tconst onKeyDown = useEvent(handleKeyDown)\n\tconst onFocus = useEvent(handleFocus)\n\tconst onBlur = useEvent(handleBlur)\n\tconst onDoubleClick = useEvent(handleDoubleClick)\n\tconst onPaste = useEvent(handlePaste)\n\tuseLayoutEffect(() => {\n\t\tif (!isEditing || !tipTapConfig || !rTextEditorEl.current) return\n\n\t\tconst { editorProps, ...restOfTipTapConfig } = tipTapConfig\n\n\t\t// Because React can double-render in Strict Mode, we need to make sure we're not setting\n\t\t// the text editor twice. This became more much more prevalent in React 19, but also it\n\t\t// started manifesting in some cases in Next 14.2 (which maybe patches React 18.3 in weird\n\t\t// ways). So we used to use EditorProvider but we into weird rendering issues.\n\t\tconst textEditorInstance = new TextEditor({\n\t\t\telement: rTextEditorEl.current,\n\t\t\tautofocus: true,\n\t\t\teditable: isEditing,\n\t\t\tonUpdate: (props: EditorEvents['update']) => {\n\t\t\t\tconst content: TLRichText = props.editor.state.doc.toJSON()\n\t\t\t\trInitialRichText.current = content\n\t\t\t\tonChange({ richText: content })\n\t\t\t},\n\t\t\tonFocus,\n\t\t\tonBlur,\n\t\t\t// onCreate is called after a `setTimeout(0)`\n\t\t\tonCreate: (props) => {\n\t\t\t\t// If we're not still editing the original shape, then don't do anything.\n\t\t\t\tif (editor.getEditingShapeId() !== shapeId) return\n\n\t\t\t\tconst textEditor = props.editor\n\t\t\t\teditor.setRichTextEditor(textEditor)\n\n\t\t\t\tconst { selectAll, caretPosition } = rCreateInfo.current\n\n\t\t\t\tif (selectAll) {\n\t\t\t\t\t// Select all of the text\n\t\t\t\t\ttextEditor.chain().focus().selectAll().run()\n\t\t\t\t} else if (caretPosition) {\n\t\t\t\t\t// Set the initial caret screen position\n\t\t\t\t\tconst pos = textEditor.view.posAtCoords({\n\t\t\t\t\t\tleft: caretPosition.x,\n\t\t\t\t\t\ttop: caretPosition.y,\n\t\t\t\t\t})?.pos\n\n\t\t\t\t\tif (pos) {\n\t\t\t\t\t\t// Focus to that position.\n\t\t\t\t\t\ttextEditor.chain().focus().setTextSelection(pos).run()\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If no position, default to select all.\n\t\t\t\t\t\ttextEditor.chain().focus().selectAll().run()\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\teditorProps: {\n\t\t\t\thandleKeyDown: (view: EditorView, event: KeyboardEvent) => {\n\t\t\t\t\tif (!hasCustomTabBehavior && event.key === 'Tab') {\n\t\t\t\t\t\thandleTab(editor, view, event)\n\t\t\t\t\t}\n\n\t\t\t\t\tonKeyDown(event)\n\t\t\t\t},\n\t\t\t\thandlePaste: (view: EditorView, event: ClipboardEvent) => {\n\t\t\t\t\tonPaste(event)\n\t\t\t\t\tif (event.defaultPrevented) return true\n\t\t\t\t},\n\t\t\t\thandleDoubleClick: (_view, _pos, event) => onDoubleClick(event),\n\t\t\t\t...editorProps,\n\t\t\t},\n\t\t\tcoreExtensionOptions: {\n\t\t\t\tclipboardTextSerializer: {\n\t\t\t\t\tblockSeparator: '\\n',\n\t\t\t\t},\n\t\t\t},\n\t\t\t...restOfTipTapConfig,\n\t\t\tcontent: rInitialRichText.current as JSONContent,\n\t\t})\n\n\t\t// XXX: When creating a brand new shape and double-clicking into it quickly to edit it,\n\t\t// there's some kind of race condition happening where the editor doesn't focus properly.\n\t\tconst timeout = editor.timers.setTimeout(() => {\n\t\t\tif (rCreateInfo.current.caretPosition || rCreateInfo.current.selectAll) {\n\t\t\t\ttextEditorInstance.commands.focus()\n\t\t\t} else {\n\t\t\t\ttextEditorInstance.commands.focus('end')\n\t\t\t}\n\n\t\t\trCreateInfo.current.selectAll = false\n\t\t\trCreateInfo.current.caretPosition = null\n\t\t}, 100)\n\n\t\trTextEditor.current = textEditorInstance\n\n\t\treturn () => {\n\t\t\trTextEditor.current = null\n\t\t\tclearTimeout(timeout)\n\t\t\ttextEditorInstance.destroy()\n\t\t}\n\t}, [\n\t\tisEditing,\n\t\ttipTapConfig,\n\t\tonFocus,\n\t\tonBlur,\n\t\tonDoubleClick,\n\t\tonChange,\n\t\tonPaste,\n\t\tonKeyDown,\n\t\teditor,\n\t\tshapeId,\n\t\thasCustomTabBehavior,\n\t])\n\n\tif (!isEditing || !tipTapConfig) {\n\t\treturn null\n\t}\n\n\treturn (\n\t\t<div\n\t\t\tid={tipTapId}\n\t\t\tref={ref}\n\t\t\ttabIndex={-1}\n\t\t\tdata-testid=\"rich-text-area\"\n\t\t\tclassName=\"tl-rich-text tl-text tl-text-input\"\n\t\t\tonContextMenu={isEditing ? (e) => e.stopPropagation() : undefined}\n\t\t\t// N.B. When PointerStateExtension was introduced, this was moved there.\n\t\t\t// However, that caused selecting over list items to break.\n\t\t\t// The handleDOMEvents in TipTap don't seem to support the pointerDownCapture event.\n\t\t\tonPointerDownCapture={(e) => e.stopPropagation()}\n\t\t\t// This onTouchEnd is important for Android to be able to change selection on text.\n\t\t\tonTouchEnd={(e) => e.stopPropagation()}\n\t\t\t// On FF, there's a behavior where dragging a selection will grab that selection into\n\t\t\t// the drag event. However, once the drag is over, and you select away from the textarea,\n\t\t\t// starting a drag over the textarea will restart a selection drag instead of a shape drag.\n\t\t\t// This prevents that default behavior in FF.\n\t\t\tonDragStart={preventDefault}\n\t\t>\n\t\t\t<div className=\"tl-rich-text\" ref={rTextEditorEl} />\n\t\t</div>\n\t)\n})\n\n// Prevent exiting the editor when hitting Tab.\n// Also, insert a tab character at the front of the line if the shift key isn't pressed,\n// otherwise if shift is pressed, remove a tab character from the front of the line.\nfunction handleTab(editor: Editor, view: EditorView, event: KeyboardEvent) {\n\t// Don't exit the editor.\n\tevent.preventDefault()\n\n\tconst textEditor = editor.getRichTextEditor()\n\tif (textEditor?.isActive('bulletList') || textEditor?.isActive('orderedList')) return\n\n\tconst { state, dispatch } = view\n\tconst { $from, $to } = state.selection\n\tconst isShift = event.shiftKey\n\n\t// Create a new transaction\n\tlet tr = state.tr\n\n\t// Iterate over each line in the selection in reverse so that the positions\n\t// are stable as we modify the document.\n\tlet pos = $to.end()\n\twhile (pos >= $from.start()) {\n\t\tconst line = state.doc.resolve(pos).blockRange()\n\t\tif (!line) break\n\n\t\tconst lineStart = line.start\n\t\tconst lineEnd = line.end\n\t\tconst lineText = state.doc.textBetween(lineStart, lineEnd, '\\n')\n\n\t\t// Check if the current line or any of its parent nodes are part of a list\n\t\tlet isInList = false\n\t\tstate.doc.nodesBetween(lineStart, lineEnd, (node) => {\n\t\t\tif (node.type.name === 'bulletList' || node.type.name === 'orderedList') {\n\t\t\t\tisInList = true\n\t\t\t\treturn false // Stop iteration\n\t\t\t}\n\t\t})\n\n\t\t// TODO: for now skip over lists. Later, we might consider handling them using\n\t\t// sinkListItem and liftListItem from @tiptap/pm/schema-list\n\t\tif (!isInList) {\n\t\t\tif (!isShift) {\n\t\t\t\t// Insert a tab character at the start of the line\n\t\t\t\ttr = tr.insertText('\\t', lineStart + 1)\n\t\t\t} else {\n\t\t\t\t// Remove a tab character from the start of the line\n\t\t\t\tif (lineText.startsWith('\\t')) {\n\t\t\t\t\ttr = tr.delete(lineStart + 1, lineStart + 2)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tpos = lineStart - 1\n\t}\n\n\tconst mappedSelection = state.selection.map(tr.doc, tr.mapping)\n\ttr.setSelection(mappedSelection)\n\n\tif (tr.docChanged) {\n\t\tdispatch(tr)\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_react", "React", "RichTextArea", "TextEditor"]
7
7
  }
@@ -28,7 +28,13 @@ class Erasing extends import_editor.StateNode {
28
28
  scribbleId = "id";
29
29
  markId = "";
30
30
  excludedShapeIds = /* @__PURE__ */ new Set();
31
+ _isHoldingAccelKey = false;
32
+ _firstErasingShapeId = null;
33
+ _erasingShapeIds = [];
31
34
  onEnter(info) {
35
+ this._isHoldingAccelKey = (0, import_editor.isAccelKey)(this.editor.inputs);
36
+ this._firstErasingShapeId = this.editor.getErasingShapeIds()[0];
37
+ this._erasingShapeIds = this.editor.getErasingShapeIds();
32
38
  this.markId = this.editor.markHistoryStoppingPoint("erase scribble begin");
33
39
  this.info = info;
34
40
  const { originPagePoint } = this.editor.inputs;
@@ -70,6 +76,14 @@ class Erasing extends import_editor.StateNode {
70
76
  onComplete() {
71
77
  this.complete();
72
78
  }
79
+ onKeyUp() {
80
+ this._isHoldingAccelKey = (0, import_editor.isAccelKey)(this.editor.inputs);
81
+ this.update();
82
+ }
83
+ onKeyDown() {
84
+ this._isHoldingAccelKey = (0, import_editor.isAccelKey)(this.editor.inputs);
85
+ this.update();
86
+ }
73
87
  update() {
74
88
  const { editor, excludedShapeIds } = this;
75
89
  const erasingShapeIds = editor.getErasingShapeIds();
@@ -100,13 +114,23 @@ class Erasing extends import_editor.StateNode {
100
114
  if (geometry.hitTestLineSegment(A, B, minDist)) {
101
115
  erasing.add(editor.getOutermostSelectableShape(shape).id);
102
116
  }
117
+ this._erasingShapeIds = [...erasing];
118
+ }
119
+ if (this._isHoldingAccelKey && this._firstErasingShapeId) {
120
+ const erasingShapeId = this._firstErasingShapeId;
121
+ if (erasingShapeId && this.editor.getShape(erasingShapeId)) {
122
+ editor.setErasingShapes([erasingShapeId]);
123
+ }
124
+ return;
103
125
  }
104
- this.editor.setErasingShapes([...erasing].filter((id) => !excludedShapeIds.has(id)));
126
+ this.editor.setErasingShapes(this._erasingShapeIds.filter((id) => !excludedShapeIds.has(id)));
105
127
  }
106
128
  complete() {
107
129
  const { editor } = this;
108
130
  editor.deleteShapes(editor.getCurrentPageState().erasingShapeIds);
109
131
  this.parent.transition("idle");
132
+ this._erasingShapeIds = [];
133
+ this._firstErasingShapeId = null;
110
134
  }
111
135
  cancel() {
112
136
  const { editor } = this;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/tools/EraserTool/childStates/Erasing.ts"],
4
- "sourcesContent": ["import {\n\tStateNode,\n\tTLFrameShape,\n\tTLGroupShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\tpointInPolygon,\n} from '@tldraw/editor'\n\nexport class Erasing extends StateNode {\n\tstatic override id = 'erasing'\n\n\tprivate info = {} as TLPointerEventInfo\n\tprivate scribbleId = 'id'\n\tprivate markId = ''\n\tprivate excludedShapeIds = new Set<TLShapeId>()\n\n\toverride onEnter(info: TLPointerEventInfo) {\n\t\tthis.markId = this.editor.markHistoryStoppingPoint('erase scribble begin')\n\t\tthis.info = info\n\n\t\tconst { originPagePoint } = this.editor.inputs\n\t\tthis.excludedShapeIds = new Set(\n\t\t\tthis.editor\n\t\t\t\t.getCurrentPageShapes()\n\t\t\t\t.filter((shape) => {\n\t\t\t\t\t//If the shape is locked, we shouldn't erase it\n\t\t\t\t\tif (this.editor.isShapeOrAncestorLocked(shape)) return true\n\t\t\t\t\t//If the shape is a group or frame, check we're inside it when we start erasing\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis.editor.isShapeOfType<TLGroupShape>(shape, 'group') ||\n\t\t\t\t\t\tthis.editor.isShapeOfType<TLFrameShape>(shape, 'frame')\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst pointInShapeShape = this.editor.getPointInShapeSpace(shape, originPagePoint)\n\t\t\t\t\t\tconst geometry = this.editor.getShapeGeometry(shape)\n\t\t\t\t\t\treturn geometry.bounds.containsPoint(pointInShapeShape)\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false\n\t\t\t\t})\n\t\t\t\t.map((shape) => shape.id)\n\t\t)\n\n\t\tconst scribble = this.editor.scribbles.addScribble({\n\t\t\tcolor: 'muted-1',\n\t\t\tsize: 12,\n\t\t})\n\t\tthis.scribbleId = scribble.id\n\n\t\tthis.update()\n\t}\n\n\tprivate pushPointToScribble() {\n\t\tconst { x, y } = this.editor.inputs.currentPagePoint\n\t\tthis.editor.scribbles.addPoint(this.scribbleId, x, y)\n\t}\n\n\toverride onExit() {\n\t\tthis.editor.setErasingShapes([])\n\t\tthis.editor.scribbles.stop(this.scribbleId)\n\t}\n\n\toverride onPointerMove() {\n\t\tthis.update()\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\tupdate() {\n\t\tconst { editor, excludedShapeIds } = this\n\t\tconst erasingShapeIds = editor.getErasingShapeIds()\n\t\tconst zoomLevel = editor.getZoomLevel()\n\t\tconst currentPageShapes = editor.getCurrentPageRenderingShapesSorted()\n\t\tconst {\n\t\t\tinputs: { currentPagePoint, previousPagePoint },\n\t\t} = editor\n\n\t\tthis.pushPointToScribble()\n\n\t\tconst erasing = new Set<TLShapeId>(erasingShapeIds)\n\t\tconst minDist = this.editor.options.hitTestMargin / zoomLevel\n\n\t\tfor (const shape of currentPageShapes) {\n\t\t\tif (editor.isShapeOfType<TLGroupShape>(shape, 'group')) continue\n\n\t\t\t// Avoid testing masked shapes, unless the pointer is inside the mask\n\t\t\tconst pageMask = editor.getShapeMask(shape.id)\n\t\t\tif (pageMask && !pointInPolygon(currentPagePoint, pageMask)) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Hit test the shape using a line segment\n\t\t\tconst geometry = editor.getShapeGeometry(shape)\n\t\t\tconst pageTransform = editor.getShapePageTransform(shape)\n\t\t\tif (!geometry || !pageTransform) continue\n\t\t\tconst pt = pageTransform.clone().invert()\n\t\t\tconst A = pt.applyToPoint(previousPagePoint)\n\t\t\tconst B = pt.applyToPoint(currentPagePoint)\n\n\t\t\t// If the line segment is entirely above / below / left / right of the shape's bounding box, skip the hit test\n\t\t\tconst { bounds } = geometry\n\t\t\tif (\n\t\t\t\tbounds.minX - minDist > Math.max(A.x, B.x) ||\n\t\t\t\tbounds.minY - minDist > Math.max(A.y, B.y) ||\n\t\t\t\tbounds.maxX + minDist < Math.min(A.x, B.x) ||\n\t\t\t\tbounds.maxY + minDist < Math.min(A.y, B.y)\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (geometry.hitTestLineSegment(A, B, minDist)) {\n\t\t\t\terasing.add(editor.getOutermostSelectableShape(shape).id)\n\t\t\t}\n\t\t}\n\n\t\t// Remove the hit shapes, except if they're in the list of excluded shapes\n\t\t// (these excluded shapes will be any frames or groups the pointer was inside of\n\t\t// when the user started erasing)\n\t\tthis.editor.setErasingShapes([...erasing].filter((id) => !excludedShapeIds.has(id)))\n\t}\n\n\tcomplete() {\n\t\tconst { editor } = this\n\t\teditor.deleteShapes(editor.getCurrentPageState().erasingShapeIds)\n\t\tthis.parent.transition('idle')\n\t}\n\n\tcancel() {\n\t\tconst { editor } = this\n\t\teditor.bailToMark(this.markId)\n\t\tthis.parent.transition('idle', this.info)\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {\n\tStateNode,\n\tTLFrameShape,\n\tTLGroupShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n\tisAccelKey,\n\tpointInPolygon,\n} from '@tldraw/editor'\n\nexport class Erasing extends StateNode {\n\tstatic override id = 'erasing'\n\n\tprivate info = {} as TLPointerEventInfo\n\tprivate scribbleId = 'id'\n\tprivate markId = ''\n\tprivate excludedShapeIds = new Set<TLShapeId>()\n\n\t_isHoldingAccelKey = false\n\t_firstErasingShapeId: TLShapeId | null = null\n\t_erasingShapeIds: TLShapeId[] = []\n\n\toverride onEnter(info: TLPointerEventInfo) {\n\t\tthis._isHoldingAccelKey = isAccelKey(this.editor.inputs)\n\t\tthis._firstErasingShapeId = this.editor.getErasingShapeIds()[0] // the first one should be the first one we hit... is it?\n\t\tthis._erasingShapeIds = this.editor.getErasingShapeIds()\n\n\t\tthis.markId = this.editor.markHistoryStoppingPoint('erase scribble begin')\n\t\tthis.info = info\n\n\t\tconst { originPagePoint } = this.editor.inputs\n\t\tthis.excludedShapeIds = new Set(\n\t\t\tthis.editor\n\t\t\t\t.getCurrentPageShapes()\n\t\t\t\t.filter((shape) => {\n\t\t\t\t\t//If the shape is locked, we shouldn't erase it\n\t\t\t\t\tif (this.editor.isShapeOrAncestorLocked(shape)) return true\n\t\t\t\t\t//If the shape is a group or frame, check we're inside it when we start erasing\n\t\t\t\t\tif (\n\t\t\t\t\t\tthis.editor.isShapeOfType<TLGroupShape>(shape, 'group') ||\n\t\t\t\t\t\tthis.editor.isShapeOfType<TLFrameShape>(shape, 'frame')\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst pointInShapeShape = this.editor.getPointInShapeSpace(shape, originPagePoint)\n\t\t\t\t\t\tconst geometry = this.editor.getShapeGeometry(shape)\n\t\t\t\t\t\treturn geometry.bounds.containsPoint(pointInShapeShape)\n\t\t\t\t\t}\n\n\t\t\t\t\treturn false\n\t\t\t\t})\n\t\t\t\t.map((shape) => shape.id)\n\t\t)\n\n\t\tconst scribble = this.editor.scribbles.addScribble({\n\t\t\tcolor: 'muted-1',\n\t\t\tsize: 12,\n\t\t})\n\t\tthis.scribbleId = scribble.id\n\n\t\tthis.update()\n\t}\n\n\tprivate pushPointToScribble() {\n\t\tconst { x, y } = this.editor.inputs.currentPagePoint\n\t\tthis.editor.scribbles.addPoint(this.scribbleId, x, y)\n\t}\n\n\toverride onExit() {\n\t\tthis.editor.setErasingShapes([])\n\t\tthis.editor.scribbles.stop(this.scribbleId)\n\t}\n\n\toverride onPointerMove() {\n\t\tthis.update()\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onKeyUp() {\n\t\tthis._isHoldingAccelKey = isAccelKey(this.editor.inputs)\n\t\tthis.update()\n\t}\n\n\toverride onKeyDown() {\n\t\tthis._isHoldingAccelKey = isAccelKey(this.editor.inputs)\n\t\tthis.update()\n\t}\n\n\tupdate() {\n\t\tconst { editor, excludedShapeIds } = this\n\t\tconst erasingShapeIds = editor.getErasingShapeIds()\n\t\tconst zoomLevel = editor.getZoomLevel()\n\t\tconst currentPageShapes = editor.getCurrentPageRenderingShapesSorted()\n\t\tconst {\n\t\t\tinputs: { currentPagePoint, previousPagePoint },\n\t\t} = editor\n\n\t\tthis.pushPointToScribble()\n\n\t\t// Otherwise, erasing shapes are all the shapes that were hit before plus any new shapes that are hit\n\t\tconst erasing = new Set<TLShapeId>(erasingShapeIds)\n\t\tconst minDist = this.editor.options.hitTestMargin / zoomLevel\n\n\t\tfor (const shape of currentPageShapes) {\n\t\t\tif (editor.isShapeOfType<TLGroupShape>(shape, 'group')) continue\n\n\t\t\t// Avoid testing masked shapes, unless the pointer is inside the mask\n\t\t\tconst pageMask = editor.getShapeMask(shape.id)\n\t\t\tif (pageMask && !pointInPolygon(currentPagePoint, pageMask)) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Hit test the shape using a line segment\n\t\t\tconst geometry = editor.getShapeGeometry(shape)\n\t\t\tconst pageTransform = editor.getShapePageTransform(shape)\n\t\t\tif (!geometry || !pageTransform) continue\n\t\t\tconst pt = pageTransform.clone().invert()\n\t\t\tconst A = pt.applyToPoint(previousPagePoint)\n\t\t\tconst B = pt.applyToPoint(currentPagePoint)\n\n\t\t\t// If the line segment is entirely above / below / left / right of the shape's bounding box, skip the hit test\n\t\t\tconst { bounds } = geometry\n\t\t\tif (\n\t\t\t\tbounds.minX - minDist > Math.max(A.x, B.x) ||\n\t\t\t\tbounds.minY - minDist > Math.max(A.y, B.y) ||\n\t\t\t\tbounds.maxX + minDist < Math.min(A.x, B.x) ||\n\t\t\t\tbounds.maxY + minDist < Math.min(A.y, B.y)\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (geometry.hitTestLineSegment(A, B, minDist)) {\n\t\t\t\terasing.add(editor.getOutermostSelectableShape(shape).id)\n\t\t\t}\n\n\t\t\tthis._erasingShapeIds = [...erasing]\n\t\t}\n\n\t\t// If the user is holding the meta / ctrl key, we should only erase the first shape we hit\n\t\tif (this._isHoldingAccelKey && this._firstErasingShapeId) {\n\t\t\tconst erasingShapeId = this._firstErasingShapeId\n\t\t\tif (erasingShapeId && this.editor.getShape(erasingShapeId)) {\n\t\t\t\teditor.setErasingShapes([erasingShapeId])\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\t// Remove the hit shapes, except if they're in the list of excluded shapes\n\t\t// (these excluded shapes will be any frames or groups the pointer was inside of\n\t\t// when the user started erasing)\n\t\tthis.editor.setErasingShapes(this._erasingShapeIds.filter((id) => !excludedShapeIds.has(id)))\n\t}\n\n\tcomplete() {\n\t\tconst { editor } = this\n\t\teditor.deleteShapes(editor.getCurrentPageState().erasingShapeIds)\n\t\tthis.parent.transition('idle')\n\t\tthis._erasingShapeIds = []\n\t\tthis._firstErasingShapeId = null\n\t}\n\n\tcancel() {\n\t\tconst { editor } = this\n\t\teditor.bailToMark(this.markId)\n\t\tthis.parent.transition('idle', this.info)\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -24,7 +24,9 @@ module.exports = __toCommonJS(Pointing_exports);
24
24
  var import_editor = require("@tldraw/editor");
25
25
  class Pointing extends import_editor.StateNode {
26
26
  static id = "pointing";
27
+ _isHoldingAccelKey = false;
27
28
  onEnter() {
29
+ this._isHoldingAccelKey = (0, import_editor.isAccelKey)(this.editor.inputs);
28
30
  const zoomLevel = this.editor.getZoomLevel();
29
31
  const currentPageShapesSorted = this.editor.getCurrentPageRenderingShapesSorted();
30
32
  const {
@@ -46,10 +48,19 @@ class Pointing extends import_editor.StateNode {
46
48
  break;
47
49
  }
48
50
  erasing.add(hitShape.id);
51
+ if (this._isHoldingAccelKey) {
52
+ break;
53
+ }
49
54
  }
50
55
  }
51
56
  this.editor.setErasingShapes([...erasing]);
52
57
  }
58
+ onKeyUp() {
59
+ this._isHoldingAccelKey = (0, import_editor.isAccelKey)(this.editor.inputs);
60
+ }
61
+ onKeyDown() {
62
+ this._isHoldingAccelKey = (0, import_editor.isAccelKey)(this.editor.inputs);
63
+ }
53
64
  onLongPress(info) {
54
65
  this.startErasing(info);
55
66
  }
@@ -59,6 +70,7 @@ class Pointing extends import_editor.StateNode {
59
70
  }
60
71
  }
61
72
  onPointerMove(info) {
73
+ if (this._isHoldingAccelKey) return;
62
74
  if (this.editor.inputs.isDragging) {
63
75
  this.startErasing(info);
64
76
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/tools/EraserTool/childStates/Pointing.ts"],
4
- "sourcesContent": ["import {\n\tStateNode,\n\tTLFrameShape,\n\tTLGroupShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n} from '@tldraw/editor'\n\nexport class Pointing extends StateNode {\n\tstatic override id = 'pointing'\n\n\toverride onEnter() {\n\t\tconst zoomLevel = this.editor.getZoomLevel()\n\t\tconst currentPageShapesSorted = this.editor.getCurrentPageRenderingShapesSorted()\n\t\tconst {\n\t\t\tinputs: { currentPagePoint },\n\t\t} = this.editor\n\n\t\tconst erasing = new Set<TLShapeId>()\n\n\t\tconst initialSize = erasing.size\n\n\t\tfor (let n = currentPageShapesSorted.length, i = n - 1; i >= 0; i--) {\n\t\t\tconst shape = currentPageShapesSorted[i]\n\t\t\tif (\n\t\t\t\tthis.editor.isShapeOrAncestorLocked(shape) ||\n\t\t\t\tthis.editor.isShapeOfType<TLGroupShape>(shape, 'group')\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tthis.editor.isPointInShape(shape, currentPagePoint, {\n\t\t\t\t\thitInside: false,\n\t\t\t\t\tmargin: this.editor.options.hitTestMargin / zoomLevel,\n\t\t\t\t})\n\t\t\t) {\n\t\t\t\tconst hitShape = this.editor.getOutermostSelectableShape(shape)\n\t\t\t\t// If we've hit a frame after hitting any other shape, stop here\n\t\t\t\tif (\n\t\t\t\t\tthis.editor.isShapeOfType<TLFrameShape>(hitShape, 'frame') &&\n\t\t\t\t\terasing.size > initialSize\n\t\t\t\t) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\terasing.add(hitShape.id)\n\t\t\t}\n\t\t}\n\n\t\tthis.editor.setErasingShapes([...erasing])\n\t}\n\n\toverride onLongPress(info: TLPointerEventInfo) {\n\t\tthis.startErasing(info)\n\t}\n\n\toverride onExit(_info: any, to: string) {\n\t\tif (to !== 'erasing') {\n\t\t\tthis.editor.setErasingShapes([])\n\t\t}\n\t}\n\n\toverride onPointerMove(info: TLPointerEventInfo) {\n\t\tif (this.editor.inputs.isDragging) {\n\t\t\tthis.startErasing(info)\n\t\t}\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate startErasing(info: TLPointerEventInfo) {\n\t\tthis.parent.transition('erasing', info)\n\t}\n\n\tcomplete() {\n\t\tconst erasingShapeIds = this.editor.getErasingShapeIds()\n\n\t\tif (erasingShapeIds.length) {\n\t\t\tthis.editor.markHistoryStoppingPoint('erase end')\n\t\t\tthis.editor.deleteShapes(erasingShapeIds)\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tcancel() {\n\t\tthis.parent.transition('idle')\n\t}\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAMO;AAEA,MAAM,iBAAiB,wBAAU;AAAA,EACvC,OAAgB,KAAK;AAAA,EAEZ,UAAU;AAClB,UAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,UAAM,0BAA0B,KAAK,OAAO,oCAAoC;AAChF,UAAM;AAAA,MACL,QAAQ,EAAE,iBAAiB;AAAA,IAC5B,IAAI,KAAK;AAET,UAAM,UAAU,oBAAI,IAAe;AAEnC,UAAM,cAAc,QAAQ;AAE5B,aAAS,IAAI,wBAAwB,QAAQ,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;AACpE,YAAM,QAAQ,wBAAwB,CAAC;AACvC,UACC,KAAK,OAAO,wBAAwB,KAAK,KACzC,KAAK,OAAO,cAA4B,OAAO,OAAO,GACrD;AACD;AAAA,MACD;AAEA,UACC,KAAK,OAAO,eAAe,OAAO,kBAAkB;AAAA,QACnD,WAAW;AAAA,QACX,QAAQ,KAAK,OAAO,QAAQ,gBAAgB;AAAA,MAC7C,CAAC,GACA;AACD,cAAM,WAAW,KAAK,OAAO,4BAA4B,KAAK;AAE9D,YACC,KAAK,OAAO,cAA4B,UAAU,OAAO,KACzD,QAAQ,OAAO,aACd;AACD;AAAA,QACD;AAEA,gBAAQ,IAAI,SAAS,EAAE;AAAA,MACxB;AAAA,IACD;AAEA,SAAK,OAAO,iBAAiB,CAAC,GAAG,OAAO,CAAC;AAAA,EAC1C;AAAA,EAES,YAAY,MAA0B;AAC9C,SAAK,aAAa,IAAI;AAAA,EACvB;AAAA,EAES,OAAO,OAAY,IAAY;AACvC,QAAI,OAAO,WAAW;AACrB,WAAK,OAAO,iBAAiB,CAAC,CAAC;AAAA,IAChC;AAAA,EACD;AAAA,EAES,cAAc,MAA0B;AAChD,QAAI,KAAK,OAAO,OAAO,YAAY;AAClC,WAAK,aAAa,IAAI;AAAA,IACvB;AAAA,EACD;AAAA,EAES,cAAc;AACtB,SAAK,SAAS;AAAA,EACf;AAAA,EAES,WAAW;AACnB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,aAAa;AACrB,SAAK,SAAS;AAAA,EACf;AAAA,EAES,cAAc;AACtB,SAAK,OAAO;AAAA,EACb;AAAA,EAEQ,aAAa,MAA0B;AAC9C,SAAK,OAAO,WAAW,WAAW,IAAI;AAAA,EACvC;AAAA,EAEA,WAAW;AACV,UAAM,kBAAkB,KAAK,OAAO,mBAAmB;AAEvD,QAAI,gBAAgB,QAAQ;AAC3B,WAAK,OAAO,yBAAyB,WAAW;AAChD,WAAK,OAAO,aAAa,eAAe;AAAA,IACzC;AAEA,SAAK,OAAO,WAAW,MAAM;AAAA,EAC9B;AAAA,EAEA,SAAS;AACR,SAAK,OAAO,WAAW,MAAM;AAAA,EAC9B;AACD;",
4
+ "sourcesContent": ["import {\n\tisAccelKey,\n\tStateNode,\n\tTLFrameShape,\n\tTLGroupShape,\n\tTLPointerEventInfo,\n\tTLShapeId,\n} from '@tldraw/editor'\n\nexport class Pointing extends StateNode {\n\tstatic override id = 'pointing'\n\n\t_isHoldingAccelKey = false\n\n\toverride onEnter() {\n\t\tthis._isHoldingAccelKey = isAccelKey(this.editor.inputs)\n\n\t\tconst zoomLevel = this.editor.getZoomLevel()\n\t\tconst currentPageShapesSorted = this.editor.getCurrentPageRenderingShapesSorted()\n\t\tconst {\n\t\t\tinputs: { currentPagePoint },\n\t\t} = this.editor\n\n\t\tconst erasing = new Set<TLShapeId>()\n\n\t\tconst initialSize = erasing.size\n\n\t\tfor (let n = currentPageShapesSorted.length, i = n - 1; i >= 0; i--) {\n\t\t\tconst shape = currentPageShapesSorted[i]\n\t\t\tif (\n\t\t\t\tthis.editor.isShapeOrAncestorLocked(shape) ||\n\t\t\t\tthis.editor.isShapeOfType<TLGroupShape>(shape, 'group')\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tthis.editor.isPointInShape(shape, currentPagePoint, {\n\t\t\t\t\thitInside: false,\n\t\t\t\t\tmargin: this.editor.options.hitTestMargin / zoomLevel,\n\t\t\t\t})\n\t\t\t) {\n\t\t\t\tconst hitShape = this.editor.getOutermostSelectableShape(shape)\n\t\t\t\t// If we've hit a frame after hitting any other shape, stop here\n\t\t\t\tif (\n\t\t\t\t\tthis.editor.isShapeOfType<TLFrameShape>(hitShape, 'frame') &&\n\t\t\t\t\terasing.size > initialSize\n\t\t\t\t) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\terasing.add(hitShape.id)\n\n\t\t\t\t// If the user is holding the meta / ctrl key, stop after the first shape\n\t\t\t\tif (this._isHoldingAccelKey) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tthis.editor.setErasingShapes([...erasing])\n\t}\n\n\toverride onKeyUp() {\n\t\tthis._isHoldingAccelKey = isAccelKey(this.editor.inputs)\n\t}\n\n\toverride onKeyDown() {\n\t\tthis._isHoldingAccelKey = isAccelKey(this.editor.inputs)\n\t}\n\n\toverride onLongPress(info: TLPointerEventInfo) {\n\t\tthis.startErasing(info)\n\t}\n\n\toverride onExit(_info: any, to: string) {\n\t\tif (to !== 'erasing') {\n\t\t\tthis.editor.setErasingShapes([])\n\t\t}\n\t}\n\n\toverride onPointerMove(info: TLPointerEventInfo) {\n\t\tif (this._isHoldingAccelKey) return\n\n\t\tif (this.editor.inputs.isDragging) {\n\t\t\tthis.startErasing(info)\n\t\t}\n\t}\n\n\toverride onPointerUp() {\n\t\tthis.complete()\n\t}\n\n\toverride onCancel() {\n\t\tthis.cancel()\n\t}\n\n\toverride onComplete() {\n\t\tthis.complete()\n\t}\n\n\toverride onInterrupt() {\n\t\tthis.cancel()\n\t}\n\n\tprivate startErasing(info: TLPointerEventInfo) {\n\t\tthis.parent.transition('erasing', info)\n\t}\n\n\tcomplete() {\n\t\tconst erasingShapeIds = this.editor.getErasingShapeIds()\n\n\t\tif (erasingShapeIds.length) {\n\t\t\tthis.editor.markHistoryStoppingPoint('erase end')\n\t\t\tthis.editor.deleteShapes(erasingShapeIds)\n\t\t}\n\n\t\tthis.parent.transition('idle')\n\t}\n\n\tcancel() {\n\t\tthis.parent.transition('idle')\n\t}\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAOO;AAEA,MAAM,iBAAiB,wBAAU;AAAA,EACvC,OAAgB,KAAK;AAAA,EAErB,qBAAqB;AAAA,EAEZ,UAAU;AAClB,SAAK,yBAAqB,0BAAW,KAAK,OAAO,MAAM;AAEvD,UAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,UAAM,0BAA0B,KAAK,OAAO,oCAAoC;AAChF,UAAM;AAAA,MACL,QAAQ,EAAE,iBAAiB;AAAA,IAC5B,IAAI,KAAK;AAET,UAAM,UAAU,oBAAI,IAAe;AAEnC,UAAM,cAAc,QAAQ;AAE5B,aAAS,IAAI,wBAAwB,QAAQ,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK;AACpE,YAAM,QAAQ,wBAAwB,CAAC;AACvC,UACC,KAAK,OAAO,wBAAwB,KAAK,KACzC,KAAK,OAAO,cAA4B,OAAO,OAAO,GACrD;AACD;AAAA,MACD;AAEA,UACC,KAAK,OAAO,eAAe,OAAO,kBAAkB;AAAA,QACnD,WAAW;AAAA,QACX,QAAQ,KAAK,OAAO,QAAQ,gBAAgB;AAAA,MAC7C,CAAC,GACA;AACD,cAAM,WAAW,KAAK,OAAO,4BAA4B,KAAK;AAE9D,YACC,KAAK,OAAO,cAA4B,UAAU,OAAO,KACzD,QAAQ,OAAO,aACd;AACD;AAAA,QACD;AAEA,gBAAQ,IAAI,SAAS,EAAE;AAGvB,YAAI,KAAK,oBAAoB;AAC5B;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,SAAK,OAAO,iBAAiB,CAAC,GAAG,OAAO,CAAC;AAAA,EAC1C;AAAA,EAES,UAAU;AAClB,SAAK,yBAAqB,0BAAW,KAAK,OAAO,MAAM;AAAA,EACxD;AAAA,EAES,YAAY;AACpB,SAAK,yBAAqB,0BAAW,KAAK,OAAO,MAAM;AAAA,EACxD;AAAA,EAES,YAAY,MAA0B;AAC9C,SAAK,aAAa,IAAI;AAAA,EACvB;AAAA,EAES,OAAO,OAAY,IAAY;AACvC,QAAI,OAAO,WAAW;AACrB,WAAK,OAAO,iBAAiB,CAAC,CAAC;AAAA,IAChC;AAAA,EACD;AAAA,EAES,cAAc,MAA0B;AAChD,QAAI,KAAK,mBAAoB;AAE7B,QAAI,KAAK,OAAO,OAAO,YAAY;AAClC,WAAK,aAAa,IAAI;AAAA,IACvB;AAAA,EACD;AAAA,EAES,cAAc;AACtB,SAAK,SAAS;AAAA,EACf;AAAA,EAES,WAAW;AACnB,SAAK,OAAO;AAAA,EACb;AAAA,EAES,aAAa;AACrB,SAAK,SAAS;AAAA,EACf;AAAA,EAES,cAAc;AACtB,SAAK,OAAO;AAAA,EACb;AAAA,EAEQ,aAAa,MAA0B;AAC9C,SAAK,OAAO,WAAW,WAAW,IAAI;AAAA,EACvC;AAAA,EAEA,WAAW;AACV,UAAM,kBAAkB,KAAK,OAAO,mBAAmB;AAEvD,QAAI,gBAAgB,QAAQ;AAC3B,WAAK,OAAO,yBAAyB,WAAW;AAChD,WAAK,OAAO,aAAa,eAAe;AAAA,IACzC;AAEA,SAAK,OAAO,WAAW,MAAM;AAAA,EAC9B;AAAA,EAEA,SAAS;AACR,SAAK,OAAO,WAAW,MAAM;AAAA,EAC9B;AACD;",
6
6
  "names": []
7
7
  }
@@ -28,7 +28,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
  var TldrawUi_exports = {};
30
30
  __export(TldrawUi_exports, {
31
- TldrawUi: () => TldrawUi
31
+ TldrawUi: () => TldrawUi,
32
+ TldrawUiInFrontOfTheCanvas: () => TldrawUiInFrontOfTheCanvas
32
33
  });
33
34
  module.exports = __toCommonJS(TldrawUi_exports);
34
35
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -36,7 +37,6 @@ var import_editor = require("@tldraw/editor");
36
37
  var import_classnames = __toESM(require("classnames"));
37
38
  var import_react = __toESM(require("react"));
38
39
  var import_A11y = require("./components/A11y");
39
- var import_FollowingIndicator = require("./components/FollowingIndicator");
40
40
  var import_TldrawUiButton = require("./components/primitives/Button/TldrawUiButton");
41
41
  var import_TldrawUiButtonIcon = require("./components/primitives/Button/TldrawUiButtonIcon");
42
42
  var import_constants = require("./constants");
@@ -85,10 +85,6 @@ const TldrawUiContent = import_react.default.memo(function TldrawUI() {
85
85
  NavigationPanel,
86
86
  HelperButtons,
87
87
  DebugPanel,
88
- CursorChatBubble,
89
- RichTextToolbar,
90
- ImageToolbar,
91
- VideoToolbar,
92
88
  Toasts,
93
89
  Dialogs,
94
90
  A11y
@@ -183,15 +179,20 @@ const TldrawUiContent = import_react.default.memo(function TldrawUI() {
183
179
  A11y && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(A11y, {})
184
180
  ] })
185
181
  ] }),
186
- RichTextToolbar && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RichTextToolbar, {}),
187
- ImageToolbar && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImageToolbar, {}),
188
- VideoToolbar && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VideoToolbar, {}),
189
182
  Toasts && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Toasts, {}),
190
- Dialogs && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Dialogs, {}),
191
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_FollowingIndicator.FollowingIndicator, {}),
192
- CursorChatBubble && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CursorChatBubble, {})
183
+ Dialogs && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Dialogs, {})
193
184
  ]
194
185
  }
195
186
  );
196
187
  });
188
+ function TldrawUiInFrontOfTheCanvas() {
189
+ const { RichTextToolbar, ImageToolbar, VideoToolbar, CursorChatBubble, FollowingIndicator } = (0, import_components.useTldrawUiComponents)();
190
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
191
+ RichTextToolbar && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RichTextToolbar, {}),
192
+ ImageToolbar && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImageToolbar, {}),
193
+ VideoToolbar && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VideoToolbar, {}),
194
+ FollowingIndicator && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FollowingIndicator, {}),
195
+ CursorChatBubble && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CursorChatBubble, {})
196
+ ] });
197
+ }
197
198
  //# sourceMappingURL=TldrawUi.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/ui/TldrawUi.tsx"],
4
- "sourcesContent": ["import { tlenv, useEditor, useReactor, useValue } from '@tldraw/editor'\nimport classNames from 'classnames'\nimport React, { ReactNode, useMemo, useRef, useState } from 'react'\nimport { TLUiAssetUrlOverrides } from './assetUrls'\nimport { SkipToMainContent } from './components/A11y'\nimport { FollowingIndicator } from './components/FollowingIndicator'\nimport { TldrawUiButton } from './components/primitives/Button/TldrawUiButton'\nimport { TldrawUiButtonIcon } from './components/primitives/Button/TldrawUiButtonIcon'\nimport { PORTRAIT_BREAKPOINT, PORTRAIT_BREAKPOINTS } from './constants'\nimport {\n\tTLUiContextProviderProps,\n\tTldrawUiContextProvider,\n} from './context/TldrawUiContextProvider'\nimport { useActions } from './context/actions'\nimport { useBreakpoint } from './context/breakpoints'\nimport { TLUiComponents, useTldrawUiComponents } from './context/components'\nimport { useNativeClipboardEvents } from './hooks/useClipboardEvents'\nimport { useEditorEvents } from './hooks/useEditorEvents'\nimport { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts'\nimport { useReadonly } from './hooks/useReadonly'\nimport { useTranslation } from './hooks/useTranslation/useTranslation'\n\n/** @public */\nexport interface TldrawUiProps extends TLUiContextProviderProps {\n\t/**\n\t * The component's children.\n\t */\n\tchildren?: ReactNode\n\n\t/**\n\t * Whether to hide the user interface and only display the canvas.\n\t */\n\thideUi?: boolean\n\n\t/**\n\t * Overrides for the UI components.\n\t */\n\tcomponents?: TLUiComponents\n\n\t/**\n\t * Additional items to add to the debug menu (will be deprecated)\n\t */\n\trenderDebugMenuItems?(): React.ReactNode\n\n\t/** Asset URL override. */\n\tassetUrls?: TLUiAssetUrlOverrides\n}\n\n/**\n * @public\n * @react\n */\nexport const TldrawUi = React.memo(function TldrawUi({\n\trenderDebugMenuItems,\n\tchildren,\n\thideUi,\n\tcomponents,\n\t...rest\n}: TldrawUiProps) {\n\treturn (\n\t\t<TldrawUiContextProvider {...rest} components={components}>\n\t\t\t<TldrawUiInner hideUi={hideUi} renderDebugMenuItems={renderDebugMenuItems}>\n\t\t\t\t{children}\n\t\t\t</TldrawUiInner>\n\t\t</TldrawUiContextProvider>\n\t)\n})\n\ninterface TldrawUiContentProps {\n\thideUi?: boolean\n\tshareZone?: ReactNode\n\ttopZone?: ReactNode\n\trenderDebugMenuItems?(): React.ReactNode\n}\n\nconst TldrawUiInner = React.memo(function TldrawUiInner({\n\tchildren,\n\thideUi,\n\t...rest\n}: TldrawUiContentProps & { children: ReactNode }) {\n\t// The hideUi prop should prevent the UI from mounting.\n\t// If we ever need want the UI to mount and preserve state, then\n\t// we should change this behavior and hide the UI via CSS instead.\n\n\treturn (\n\t\t<>\n\t\t\t{children}\n\t\t\t{hideUi ? null : <TldrawUiContent {...rest} />}\n\t\t</>\n\t)\n})\n\nconst TldrawUiContent = React.memo(function TldrawUI() {\n\tconst editor = useEditor()\n\tconst msg = useTranslation()\n\tconst breakpoint = useBreakpoint()\n\tconst isReadonlyMode = useReadonly()\n\tconst isFocusMode = useValue('focus', () => editor.getInstanceState().isFocusMode, [editor])\n\tconst isDebugMode = useValue('debug', () => editor.getInstanceState().isDebugMode, [editor])\n\n\tconst {\n\t\tSharePanel,\n\t\tTopPanel,\n\t\tMenuPanel,\n\t\tStylePanel,\n\t\tToolbar,\n\t\tHelpMenu,\n\t\tNavigationPanel,\n\t\tHelperButtons,\n\t\tDebugPanel,\n\t\tCursorChatBubble,\n\t\tRichTextToolbar,\n\t\tImageToolbar,\n\t\tVideoToolbar,\n\t\tToasts,\n\t\tDialogs,\n\t\tA11y,\n\t} = useTldrawUiComponents()\n\n\tuseKeyboardShortcuts()\n\tuseNativeClipboardEvents()\n\tuseEditorEvents()\n\n\tconst rIsEditingAnything = useRef(false)\n\tconst rHidingTimeout = useRef(-1 as any)\n\tconst [hideToolbarWhileEditing, setHideToolbarWhileEditing] = useState(false)\n\n\tuseReactor(\n\t\t'update hide toolbar while delayed',\n\t\t() => {\n\t\t\tconst isMobileEnvironment = tlenv.isIos || tlenv.isAndroid\n\t\t\tif (!isMobileEnvironment) return\n\n\t\t\tconst editingShape = editor.getEditingShapeId()\n\t\t\tif (editingShape === null) {\n\t\t\t\tif (rIsEditingAnything.current) {\n\t\t\t\t\trIsEditingAnything.current = false\n\t\t\t\t\tclearTimeout(rHidingTimeout.current)\n\t\t\t\t\tif (tlenv.isAndroid) {\n\t\t\t\t\t\t// On Android, hide it after 150ms\n\t\t\t\t\t\trHidingTimeout.current = editor.timers.setTimeout(() => {\n\t\t\t\t\t\t\tsetHideToolbarWhileEditing(false)\n\t\t\t\t\t\t}, 150)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// On iOS, just hide it immediately\n\t\t\t\t\t\tsetHideToolbarWhileEditing(false)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!rIsEditingAnything.current) {\n\t\t\t\trIsEditingAnything.current = true\n\t\t\t\tclearTimeout(rHidingTimeout.current)\n\t\t\t\tsetHideToolbarWhileEditing(true)\n\t\t\t}\n\t\t},\n\t\t[]\n\t)\n\n\tconst { 'toggle-focus-mode': toggleFocus } = useActions()\n\n\tconst { breakpointsAbove, breakpointsBelow } = useMemo(() => {\n\t\tconst breakpointsAbove = []\n\t\tconst breakpointsBelow = []\n\t\tfor (let bp = 0; bp < PORTRAIT_BREAKPOINTS.length; bp++) {\n\t\t\tif (bp <= breakpoint) {\n\t\t\t\tbreakpointsAbove.push(bp)\n\t\t\t} else {\n\t\t\t\tbreakpointsBelow.push(bp)\n\t\t\t}\n\t\t}\n\t\treturn { breakpointsAbove, breakpointsBelow }\n\t}, [breakpoint])\n\n\treturn (\n\t\t<div\n\t\t\tclassName={classNames('tlui-layout', {\n\t\t\t\t'tlui-layout__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,\n\t\t\t})}\n\t\t\t// When the virtual keyboard is opening we want it to hide immediately.\n\t\t\t// But when the virtual keyboard is closing we want to wait a bit before showing it again.\n\t\t\tdata-iseditinganything={hideToolbarWhileEditing}\n\t\t\tdata-breakpoint={breakpoint}\n\t\t\tdata-breakpoints-above={breakpointsAbove.join(' ')}\n\t\t\tdata-breakpoints-below={breakpointsBelow.join(' ')}\n\t\t>\n\t\t\t<SkipToMainContent />\n\t\t\t{isFocusMode ? (\n\t\t\t\t<div className=\"tlui-layout__top\">\n\t\t\t\t\t<TldrawUiButton\n\t\t\t\t\t\ttype=\"icon\"\n\t\t\t\t\t\tclassName=\"tlui-focus-button\"\n\t\t\t\t\t\ttitle={msg('focus-mode.toggle-focus-mode')}\n\t\t\t\t\t\tonClick={() => toggleFocus.onSelect('menu')}\n\t\t\t\t\t>\n\t\t\t\t\t\t<TldrawUiButtonIcon icon=\"dot\" />\n\t\t\t\t\t</TldrawUiButton>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"tlui-layout__top\">\n\t\t\t\t\t\t<div className=\"tlui-layout__top__left\">\n\t\t\t\t\t\t\t{MenuPanel && <MenuPanel />}\n\t\t\t\t\t\t\t{HelperButtons && <HelperButtons />}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"tlui-layout__top__center\">{TopPanel && <TopPanel />}</div>\n\t\t\t\t\t\t<div className=\"tlui-layout__top__right\">\n\t\t\t\t\t\t\t{SharePanel && <SharePanel />}\n\t\t\t\t\t\t\t{StylePanel && breakpoint >= PORTRAIT_BREAKPOINT.TABLET_SM && !isReadonlyMode && (\n\t\t\t\t\t\t\t\t<StylePanel />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"tlui-layout__bottom\">\n\t\t\t\t\t\t<div className=\"tlui-layout__bottom__main\">\n\t\t\t\t\t\t\t{NavigationPanel && <NavigationPanel />}\n\t\t\t\t\t\t\t{Toolbar && <Toolbar />}\n\t\t\t\t\t\t\t{HelpMenu && <HelpMenu />}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{isDebugMode && DebugPanel && <DebugPanel />}\n\t\t\t\t\t\t{A11y && <A11y />}\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t)}\n\t\t\t{RichTextToolbar && <RichTextToolbar />}\n\t\t\t{ImageToolbar && <ImageToolbar />}\n\t\t\t{VideoToolbar && <VideoToolbar />}\n\t\t\t{Toasts && <Toasts />}\n\t\t\t{Dialogs && <Dialogs />}\n\t\t\t<FollowingIndicator />\n\t\t\t{CursorChatBubble && <CursorChatBubble />}\n\t\t</div>\n\t)\n})\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { tlenv, useEditor, useReactor, useValue } from '@tldraw/editor'\nimport classNames from 'classnames'\nimport React, { ReactNode, useMemo, useRef, useState } from 'react'\nimport { TLUiAssetUrlOverrides } from './assetUrls'\nimport { SkipToMainContent } from './components/A11y'\nimport { TldrawUiButton } from './components/primitives/Button/TldrawUiButton'\nimport { TldrawUiButtonIcon } from './components/primitives/Button/TldrawUiButtonIcon'\nimport { PORTRAIT_BREAKPOINT, PORTRAIT_BREAKPOINTS } from './constants'\nimport {\n\tTLUiContextProviderProps,\n\tTldrawUiContextProvider,\n} from './context/TldrawUiContextProvider'\nimport { useActions } from './context/actions'\nimport { useBreakpoint } from './context/breakpoints'\nimport { TLUiComponents, useTldrawUiComponents } from './context/components'\nimport { useNativeClipboardEvents } from './hooks/useClipboardEvents'\nimport { useEditorEvents } from './hooks/useEditorEvents'\nimport { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts'\nimport { useReadonly } from './hooks/useReadonly'\nimport { useTranslation } from './hooks/useTranslation/useTranslation'\n\n/** @public */\nexport interface TldrawUiProps extends TLUiContextProviderProps {\n\t/**\n\t * The component's children.\n\t */\n\tchildren?: ReactNode\n\n\t/**\n\t * Whether to hide the user interface and only display the canvas.\n\t */\n\thideUi?: boolean\n\n\t/**\n\t * Overrides for the UI components.\n\t */\n\tcomponents?: TLUiComponents\n\n\t/**\n\t * Additional items to add to the debug menu (will be deprecated)\n\t */\n\trenderDebugMenuItems?(): React.ReactNode\n\n\t/** Asset URL override. */\n\tassetUrls?: TLUiAssetUrlOverrides\n}\n\n/**\n * @public\n * @react\n */\nexport const TldrawUi = React.memo(function TldrawUi({\n\trenderDebugMenuItems,\n\tchildren,\n\thideUi,\n\tcomponents,\n\t...rest\n}: TldrawUiProps) {\n\treturn (\n\t\t<TldrawUiContextProvider {...rest} components={components}>\n\t\t\t<TldrawUiInner hideUi={hideUi} renderDebugMenuItems={renderDebugMenuItems}>\n\t\t\t\t{children}\n\t\t\t</TldrawUiInner>\n\t\t</TldrawUiContextProvider>\n\t)\n})\n\ninterface TldrawUiContentProps {\n\thideUi?: boolean\n\tshareZone?: ReactNode\n\ttopZone?: ReactNode\n\trenderDebugMenuItems?(): React.ReactNode\n}\n\nconst TldrawUiInner = React.memo(function TldrawUiInner({\n\tchildren,\n\thideUi,\n\t...rest\n}: TldrawUiContentProps & { children: ReactNode }) {\n\t// The hideUi prop should prevent the UI from mounting.\n\t// If we ever need want the UI to mount and preserve state, then\n\t// we should change this behavior and hide the UI via CSS instead.\n\n\treturn (\n\t\t<>\n\t\t\t{children}\n\t\t\t{hideUi ? null : <TldrawUiContent {...rest} />}\n\t\t</>\n\t)\n})\n\nconst TldrawUiContent = React.memo(function TldrawUI() {\n\tconst editor = useEditor()\n\tconst msg = useTranslation()\n\tconst breakpoint = useBreakpoint()\n\tconst isReadonlyMode = useReadonly()\n\tconst isFocusMode = useValue('focus', () => editor.getInstanceState().isFocusMode, [editor])\n\tconst isDebugMode = useValue('debug', () => editor.getInstanceState().isDebugMode, [editor])\n\n\tconst {\n\t\tSharePanel,\n\t\tTopPanel,\n\t\tMenuPanel,\n\t\tStylePanel,\n\t\tToolbar,\n\t\tHelpMenu,\n\t\tNavigationPanel,\n\t\tHelperButtons,\n\t\tDebugPanel,\n\t\tToasts,\n\t\tDialogs,\n\t\tA11y,\n\t} = useTldrawUiComponents()\n\n\tuseKeyboardShortcuts()\n\tuseNativeClipboardEvents()\n\tuseEditorEvents()\n\n\tconst rIsEditingAnything = useRef(false)\n\tconst rHidingTimeout = useRef(-1 as any)\n\tconst [hideToolbarWhileEditing, setHideToolbarWhileEditing] = useState(false)\n\n\tuseReactor(\n\t\t'update hide toolbar while delayed',\n\t\t() => {\n\t\t\tconst isMobileEnvironment = tlenv.isIos || tlenv.isAndroid\n\t\t\tif (!isMobileEnvironment) return\n\n\t\t\tconst editingShape = editor.getEditingShapeId()\n\t\t\tif (editingShape === null) {\n\t\t\t\tif (rIsEditingAnything.current) {\n\t\t\t\t\trIsEditingAnything.current = false\n\t\t\t\t\tclearTimeout(rHidingTimeout.current)\n\t\t\t\t\tif (tlenv.isAndroid) {\n\t\t\t\t\t\t// On Android, hide it after 150ms\n\t\t\t\t\t\trHidingTimeout.current = editor.timers.setTimeout(() => {\n\t\t\t\t\t\t\tsetHideToolbarWhileEditing(false)\n\t\t\t\t\t\t}, 150)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// On iOS, just hide it immediately\n\t\t\t\t\t\tsetHideToolbarWhileEditing(false)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (!rIsEditingAnything.current) {\n\t\t\t\trIsEditingAnything.current = true\n\t\t\t\tclearTimeout(rHidingTimeout.current)\n\t\t\t\tsetHideToolbarWhileEditing(true)\n\t\t\t}\n\t\t},\n\t\t[]\n\t)\n\n\tconst { 'toggle-focus-mode': toggleFocus } = useActions()\n\n\tconst { breakpointsAbove, breakpointsBelow } = useMemo(() => {\n\t\tconst breakpointsAbove = []\n\t\tconst breakpointsBelow = []\n\t\tfor (let bp = 0; bp < PORTRAIT_BREAKPOINTS.length; bp++) {\n\t\t\tif (bp <= breakpoint) {\n\t\t\t\tbreakpointsAbove.push(bp)\n\t\t\t} else {\n\t\t\t\tbreakpointsBelow.push(bp)\n\t\t\t}\n\t\t}\n\t\treturn { breakpointsAbove, breakpointsBelow }\n\t}, [breakpoint])\n\n\treturn (\n\t\t<div\n\t\t\tclassName={classNames('tlui-layout', {\n\t\t\t\t'tlui-layout__mobile': breakpoint < PORTRAIT_BREAKPOINT.TABLET_SM,\n\t\t\t})}\n\t\t\t// When the virtual keyboard is opening we want it to hide immediately.\n\t\t\t// But when the virtual keyboard is closing we want to wait a bit before showing it again.\n\t\t\tdata-iseditinganything={hideToolbarWhileEditing}\n\t\t\tdata-breakpoint={breakpoint}\n\t\t\tdata-breakpoints-above={breakpointsAbove.join(' ')}\n\t\t\tdata-breakpoints-below={breakpointsBelow.join(' ')}\n\t\t>\n\t\t\t<SkipToMainContent />\n\t\t\t{isFocusMode ? (\n\t\t\t\t<div className=\"tlui-layout__top\">\n\t\t\t\t\t<TldrawUiButton\n\t\t\t\t\t\ttype=\"icon\"\n\t\t\t\t\t\tclassName=\"tlui-focus-button\"\n\t\t\t\t\t\ttitle={msg('focus-mode.toggle-focus-mode')}\n\t\t\t\t\t\tonClick={() => toggleFocus.onSelect('menu')}\n\t\t\t\t\t>\n\t\t\t\t\t\t<TldrawUiButtonIcon icon=\"dot\" />\n\t\t\t\t\t</TldrawUiButton>\n\t\t\t\t</div>\n\t\t\t) : (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"tlui-layout__top\">\n\t\t\t\t\t\t<div className=\"tlui-layout__top__left\">\n\t\t\t\t\t\t\t{MenuPanel && <MenuPanel />}\n\t\t\t\t\t\t\t{HelperButtons && <HelperButtons />}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"tlui-layout__top__center\">{TopPanel && <TopPanel />}</div>\n\t\t\t\t\t\t<div className=\"tlui-layout__top__right\">\n\t\t\t\t\t\t\t{SharePanel && <SharePanel />}\n\t\t\t\t\t\t\t{StylePanel && breakpoint >= PORTRAIT_BREAKPOINT.TABLET_SM && !isReadonlyMode && (\n\t\t\t\t\t\t\t\t<StylePanel />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"tlui-layout__bottom\">\n\t\t\t\t\t\t<div className=\"tlui-layout__bottom__main\">\n\t\t\t\t\t\t\t{NavigationPanel && <NavigationPanel />}\n\t\t\t\t\t\t\t{Toolbar && <Toolbar />}\n\t\t\t\t\t\t\t{HelpMenu && <HelpMenu />}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t{isDebugMode && DebugPanel && <DebugPanel />}\n\t\t\t\t\t\t{A11y && <A11y />}\n\t\t\t\t\t</div>\n\t\t\t\t</>\n\t\t\t)}\n\t\t\t{Toasts && <Toasts />}\n\t\t\t{Dialogs && <Dialogs />}\n\t\t</div>\n\t)\n})\n\n/** @public @react */\nexport function TldrawUiInFrontOfTheCanvas() {\n\tconst { RichTextToolbar, ImageToolbar, VideoToolbar, CursorChatBubble, FollowingIndicator } =\n\t\tuseTldrawUiComponents()\n\n\treturn (\n\t\t<>\n\t\t\t{RichTextToolbar && <RichTextToolbar />}\n\t\t\t{ImageToolbar && <ImageToolbar />}\n\t\t\t{VideoToolbar && <VideoToolbar />}\n\t\t\t{FollowingIndicator && <FollowingIndicator />}\n\t\t\t{CursorChatBubble && <CursorChatBubble />}\n\t\t</>\n\t)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["React", "TldrawUi", "TldrawUiInner", "breakpointsAbove", "breakpointsBelow", "classNames"]
7
7
  }