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,11 +1,50 @@
1
- import { Box, TLShapeId, createShapeId } from '@tldraw/editor'
1
+ import {
2
+ BaseBoxShapeUtil,
3
+ Box,
4
+ RecordProps,
5
+ T,
6
+ TLBaseShape,
7
+ TLShapeId,
8
+ createShapeId,
9
+ } from '@tldraw/editor'
10
+ import { vi } from 'vitest'
2
11
  import { TestEditor } from './TestEditor'
3
12
  import { TL } from './test-jsx'
4
13
 
14
+ // Custom uncullable shape type for testing canCull override
15
+ type UncullableShape = TLBaseShape<'uncullable', { w: number; h: number }>
16
+
17
+ class UncullableShapeUtil extends BaseBoxShapeUtil<UncullableShape> {
18
+ static override type = 'uncullable' as const
19
+ static override props: RecordProps<UncullableShape> = {
20
+ w: T.number,
21
+ h: T.number,
22
+ }
23
+
24
+ override canCull() {
25
+ return false
26
+ }
27
+
28
+ override getDefaultProps(): UncullableShape['props'] {
29
+ return {
30
+ w: 100,
31
+ h: 100,
32
+ }
33
+ }
34
+
35
+ override component() {
36
+ return <div>Uncullable shape</div>
37
+ }
38
+
39
+ override indicator() {
40
+ return <div>Uncullable shape</div>
41
+ }
42
+ }
43
+
5
44
  let editor: TestEditor
6
45
 
7
46
  beforeEach(() => {
8
- editor = new TestEditor()
47
+ editor = new TestEditor({ shapeUtils: [UncullableShapeUtil] })
9
48
  editor.setScreenBounds({ x: 0, y: 0, w: 1800, h: 900 })
10
49
  })
11
50
 
@@ -28,13 +67,13 @@ it('lists shapes in viewport', () => {
28
67
 
29
68
  // Move the camera 201 pixels to the right and 201 pixels down
30
69
  editor.pan({ x: -201, y: -201 })
31
- jest.advanceTimersByTime(500)
70
+ vi.advanceTimersByTime(500)
32
71
 
33
72
  // A is now outside of the viewport, like D
34
73
  expect(editor.getCulledShapes()).toStrictEqual(new Set([ids.A, ids.D]))
35
74
 
36
75
  editor.pan({ x: -900, y: -900 })
37
- jest.advanceTimersByTime(500)
76
+ vi.advanceTimersByTime(500)
38
77
  // Now all shapes are outside of the viewport, except for D (which is clipped)
39
78
  expect(editor.getCulledShapes()).toStrictEqual(new Set([ids.A, ids.B, ids.C]))
40
79
 
@@ -202,3 +241,34 @@ it('works for shapes that are outside of the viewport, but are then moved inside
202
241
  // Arrow should also not be culled
203
242
  expect(editor.getCulledShapes()).toEqual(new Set())
204
243
  })
244
+
245
+ it('respects canCull override - shapes that cannot be culled are never culled', () => {
246
+ const cullableShapeId = createShapeId()
247
+ const uncullableShapeId = createShapeId()
248
+
249
+ // Create both shapes outside the viewport
250
+ editor.createShapes([
251
+ {
252
+ id: cullableShapeId,
253
+ type: 'geo',
254
+ x: -2000, // Way outside viewport
255
+ y: -2000,
256
+ props: { w: 100, h: 100 },
257
+ },
258
+ {
259
+ id: uncullableShapeId,
260
+ type: 'uncullable',
261
+ x: -2000, // Way outside viewport
262
+ y: -2000,
263
+ props: { w: 100, h: 100 },
264
+ },
265
+ ])
266
+
267
+ const culledShapes = editor.getCulledShapes()
268
+
269
+ // The regular geo shape should be culled since it's outside the viewport
270
+ expect(culledShapes).toContain(cullableShapeId)
271
+
272
+ // The uncullable shape should NOT be culled even though it's outside the viewport
273
+ expect(culledShapes).not.toContain(uncullableShapeId)
274
+ })
@@ -1070,7 +1070,7 @@ describe('the select tool', () => {
1070
1070
  // that we're doing hit testing manually—we'll catch that it was inside a shape
1071
1071
 
1072
1072
  // editor.keyUp('Shift')
1073
- // jest.advanceTimersByTime(200)
1073
+ // vi.advanceTimersByTime(200)
1074
1074
 
1075
1075
  // expect(editor.selectedShapeIds.includes(ids.boxA)).toBe(false)
1076
1076
  // expect(editor.selectedShapeIds.includes(ids.boxB)).toBe(true)
@@ -1,8 +1,9 @@
1
1
  import { PageRecordType, TLDeepLink, createDeepLinkString, createShapeId } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from './TestEditor'
3
4
  import { TL } from './test-jsx'
4
5
 
5
- jest.useFakeTimers()
6
+ vi.useFakeTimers()
6
7
 
7
8
  let editor: TestEditor
8
9
 
@@ -1,4 +1,5 @@
1
1
  import { createShapeId } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from './TestEditor'
3
4
 
4
5
  let editor: TestEditor
@@ -82,7 +83,7 @@ describe('Maximum shapes behavior', () => {
82
83
  })
83
84
 
84
85
  it('should emit max-shapes event when limit is reached', () => {
85
- const maxShapesHandler = jest.fn()
86
+ const maxShapesHandler = vi.fn()
86
87
  editor.addListener('max-shapes', maxShapesHandler)
87
88
 
88
89
  // Set up the note tool
@@ -282,7 +283,7 @@ describe('Maximum shapes behavior', () => {
282
283
  expect(editor.getCurrentPageShapeIds().size).toBe(5)
283
284
 
284
285
  // Try to create one more shape
285
- const maxShapesHandler = jest.fn()
286
+ const maxShapesHandler = vi.fn()
286
287
  editor.addListener('max-shapes', maxShapesHandler)
287
288
 
288
289
  const extraShapeId = createShapeId('extra-shape')
@@ -1,3 +1,4 @@
1
+ import { vi } from 'vitest'
1
2
  import { TestEditor } from './TestEditor'
2
3
 
3
4
  let editor: TestEditor
@@ -6,14 +7,14 @@ beforeEach(() => {
6
7
  editor = new TestEditor()
7
8
  })
8
9
 
9
- jest.useFakeTimers()
10
+ vi.useFakeTimers()
10
11
 
11
12
  it('Shift Key', () => {
12
13
  editor.pointerDown(0, 0)
13
14
  editor.pointerMove(100, 100, { shiftKey: true })
14
15
  editor.pointerMove(100, 100, { shiftKey: false })
15
16
  expect(editor.inputs.shiftKey).toBe(true)
16
- jest.advanceTimersByTime(200)
17
+ vi.advanceTimersByTime(200)
17
18
  expect(editor.inputs.shiftKey).toBe(false)
18
19
  })
19
20
 
@@ -22,7 +23,7 @@ it('Alt Key', () => {
22
23
  editor.pointerMove(100, 100, { altKey: true })
23
24
  editor.pointerMove(100, 100, { altKey: false })
24
25
  expect(editor.inputs.altKey).toBe(true)
25
- jest.advanceTimersByTime(200)
26
+ vi.advanceTimersByTime(200)
26
27
  expect(editor.inputs.altKey).toBe(false)
27
28
  })
28
29
 
@@ -31,6 +32,6 @@ it('Ctrl Key', () => {
31
32
  editor.pointerMove(100, 100, { ctrlKey: true })
32
33
  editor.pointerMove(100, 100, { ctrlKey: false })
33
34
  expect(editor.inputs.ctrlKey).toBe(true)
34
- jest.advanceTimersByTime(200)
35
+ vi.advanceTimersByTime(200)
35
36
  expect(editor.inputs.ctrlKey).toBe(false)
36
37
  })
@@ -1,4 +1,5 @@
1
1
  import { createShapeId } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from './TestEditor'
3
4
 
4
5
  let editor: TestEditor
@@ -54,7 +55,7 @@ describe('Shape navigation', () => {
54
55
  ])
55
56
 
56
57
  // Mock canTabTo to return false for the second shape
57
- jest.spyOn(editor.getShapeUtil('geo'), 'canTabTo').mockImplementation((shape) => {
58
+ vi.spyOn(editor.getShapeUtil('geo'), 'canTabTo').mockImplementation((shape) => {
58
59
  return shape.id !== ids.box2
59
60
  })
60
61
 
@@ -100,7 +101,7 @@ describe('Shape navigation', () => {
100
101
  editor.select(ids.box1)
101
102
 
102
103
  // Spy on zoomToSelectionIfOffscreen method
103
- const zoomSpy = jest.spyOn(editor, 'zoomToSelectionIfOffscreen')
104
+ const zoomSpy = vi.spyOn(editor, 'zoomToSelectionIfOffscreen')
104
105
 
105
106
  // Navigate to next shape (offscreen)
106
107
  editor.selectAdjacentShape('next')
@@ -119,7 +120,7 @@ describe('Shape navigation', () => {
119
120
  ])
120
121
 
121
122
  // Mock a culled shape (not rendered)
122
- jest.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
123
+ vi.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
123
124
  // Return normal bounds for box1, null for box2 as if it's culled/not rendered
124
125
  if (shape?.id === ids.box2) {
125
126
  // Still return bounds, but pretend it was calculated even though shape is culled
@@ -150,7 +151,7 @@ describe('Shape navigation', () => {
150
151
  ])
151
152
 
152
153
  // Setup shape centers for the test
153
- jest.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
154
+ vi.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
154
155
  if (shape?.id === ids.boxA) {
155
156
  return { center: { x: 10, y: 110 } } as any
156
157
  }
@@ -182,7 +183,7 @@ describe('Shape navigation', () => {
182
183
  ])
183
184
 
184
185
  // Setup shape centers for the test
185
- jest.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
186
+ vi.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
186
187
  if (shape?.id === ids.center) {
187
188
  return { center: { x: 100, y: 100 } } as any
188
189
  }
@@ -219,7 +220,7 @@ describe('Shape navigation', () => {
219
220
  ])
220
221
 
221
222
  // Setup shape centers
222
- jest.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
223
+ vi.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
223
224
  if (shape?.id === ids.center) return { center: { x: 200, y: 200 } } as any
224
225
  if (shape?.id === ids.right) return { center: { x: 300, y: 200 } } as any
225
226
  if (shape?.id === ids.left) return { center: { x: 100, y: 200 } } as any
@@ -258,7 +259,7 @@ describe('Shape navigation', () => {
258
259
  ])
259
260
 
260
261
  // Setup shape centers
261
- jest.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
262
+ vi.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
262
263
  if (shape?.id === ids.center) return { center: { x: 200, y: 200 } } as any
263
264
  if (shape?.id === ids.nearRight) return { center: { x: 250, y: 200 } } as any
264
265
  if (shape?.id === ids.farRight) return { center: { x: 350, y: 200 } } as any
@@ -284,7 +285,7 @@ describe('Shape navigation', () => {
284
285
  ])
285
286
 
286
287
  // Setup shape centers
287
- jest.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
288
+ vi.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
288
289
  if (shape?.id === ids.box1) return { center: { x: 50, y: 50 } } as any
289
290
  if (shape?.id === ids.box2) return { center: { x: 150, y: 50 } } as any
290
291
  if (shape?.id === ids.box3) return { center: { x: 150, y: 150 } } as any
@@ -485,7 +486,7 @@ describe('Shape navigation', () => {
485
486
  ])
486
487
 
487
488
  // Setup shape centers for consistent testing
488
- jest.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
489
+ vi.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
489
490
  const positions = {
490
491
  [ids.box1]: { x: 25, y: 115 },
491
492
  [ids.box2]: { x: 65, y: 115 },
@@ -612,7 +613,7 @@ describe('Shape navigation', () => {
612
613
  ])
613
614
 
614
615
  // Setup shape centers for consistent testing
615
- jest.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
616
+ vi.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
616
617
  const positions = {
617
618
  [ids.box1]: { x: 115, y: 25 },
618
619
  [ids.box2]: { x: 115, y: 65 },
@@ -1006,7 +1007,7 @@ describe('Shape navigation', () => {
1006
1007
  ])
1007
1008
 
1008
1009
  // Setup shape centers
1009
- jest.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
1010
+ vi.spyOn(editor, 'getShapePageBounds').mockImplementation((shape: any) => {
1010
1011
  if (shape?.id === ids.row1Shape1) return { center: { x: 50, y: 50 } } as any
1011
1012
  if (shape?.id === ids.row1Shape2) return { center: { x: 150, y: 50 } } as any
1012
1013
  if (shape?.id === ids.row1Shape3) return { center: { x: 250, y: 50 } } as any
@@ -1,6 +1,7 @@
1
+ import { vi } from 'vitest'
1
2
  import { TestEditor } from './TestEditor'
2
3
 
3
- jest.useFakeTimers()
4
+ vi.useFakeTimers()
4
5
 
5
6
  let editor: TestEditor
6
7
 
@@ -1,10 +1,11 @@
1
1
  import { TLShapePartial, Vec, createShapeId } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from '../TestEditor'
3
4
  import { PerformanceMeasurer } from './PerformanceMeasurer'
4
5
 
5
6
  let editor = new TestEditor()
6
7
 
7
- jest.useRealTimers()
8
+ vi.useRealTimers()
8
9
 
9
10
  describe.skip('Example perf tests', () => {
10
11
  it('measures Editor.createShape vs Editor.createShapes', () => {
@@ -1,8 +1,9 @@
1
1
  import { PageRecordType, Vec, createShapeId } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from './TestEditor'
3
4
  import { TL } from './test-jsx'
4
5
 
5
- jest.useFakeTimers()
6
+ vi.useFakeTimers()
6
7
 
7
8
  let editor: TestEditor
8
9
 
@@ -20,20 +21,20 @@ beforeEach(() => {
20
21
  test('it creates a listener that updates the current url', async () => {
21
22
  const unlisten = editor.registerDeepLinkListener()
22
23
 
23
- jest.advanceTimersByTime(1000)
24
+ vi.advanceTimersByTime(1000)
24
25
  expect(window.location.href).toMatchInlineSnapshot(`"http://localhost/test?d=v0.0.1080.720.page"`)
25
26
 
26
27
  const pageId = PageRecordType.createId('foo')
27
28
  editor.createPage({ id: pageId })
28
29
  editor.setCurrentPage(pageId)
29
30
 
30
- jest.advanceTimersByTime(1000)
31
+ vi.advanceTimersByTime(1000)
31
32
 
32
33
  expect(window.location.href).toMatchInlineSnapshot(`"http://localhost/test?d=v0.0.1080.720.foo"`)
33
34
 
34
35
  editor.pan({ x: 100, y: 100 })
35
36
 
36
- jest.advanceTimersByTime(1000)
37
+ vi.advanceTimersByTime(1000)
37
38
 
38
39
  expect(window.location.href).toMatchInlineSnapshot(
39
40
  `"http://localhost/test?d=v-100.-100.1080.720.foo"`
@@ -43,7 +44,7 @@ test('it creates a listener that updates the current url', async () => {
43
44
 
44
45
  editor.pan({ x: 500, y: 500 })
45
46
 
46
- jest.advanceTimersByTime(1000)
47
+ vi.advanceTimersByTime(1000)
47
48
 
48
49
  expect(window.location.href).toMatchInlineSnapshot(
49
50
  `"http://localhost/test?d=v-100.-100.1080.720.foo"`
@@ -75,7 +76,7 @@ test('it allows specifying a page target', async () => {
75
76
  param: 'foo',
76
77
  })
77
78
 
78
- jest.advanceTimersByTime(1000)
79
+ vi.advanceTimersByTime(1000)
79
80
 
80
81
  // no shapes yet
81
82
  expect(window.location.href).toMatchInlineSnapshot(`"http://localhost/test?foo=ppage"`)
@@ -87,19 +88,19 @@ test('it allows specifying a page target', async () => {
87
88
  <TL.geo id={boxB} x={1000} y={1000} w={100} h={100} />,
88
89
  ])
89
90
 
90
- jest.advanceTimersByTime(1000)
91
+ vi.advanceTimersByTime(1000)
91
92
  expect(window.location.href).toMatchInlineSnapshot(`"http://localhost/test?foo=sa"`)
92
93
 
93
94
  editor.pan({ x: -1000, y: -1000 })
94
95
 
95
- jest.advanceTimersByTime(1000)
96
+ vi.advanceTimersByTime(1000)
96
97
  expect(window.location.href).toMatchInlineSnapshot(`"http://localhost/test?foo=sb"`)
97
98
 
98
99
  unlisten()
99
100
 
100
101
  editor.pan({ x: 1000, y: 1000 })
101
102
 
102
- jest.advanceTimersByTime(1000)
103
+ vi.advanceTimersByTime(1000)
103
104
  expect(window.location.href).toMatchInlineSnapshot(`"http://localhost/test?foo=sb"`)
104
105
  expect(getNearestShape().id).toBe(boxA)
105
106
  })
@@ -15,12 +15,13 @@ import {
15
15
  rotateSelectionHandle,
16
16
  toRichText,
17
17
  } from '@tldraw/editor'
18
+ import { vi } from 'vitest'
18
19
  import { NoteShapeUtil } from '../lib/shapes/note/NoteShapeUtil'
19
20
  import { TestEditor } from './TestEditor'
20
21
  import { getSnapLines } from './getSnapLines'
21
22
  import { roundedBox } from './roundedBox'
22
23
 
23
- jest.useFakeTimers()
24
+ vi.useFakeTimers()
24
25
 
25
26
  const ORDERED_ROTATE_CORNERS: TLSelectionHandle[] = [
26
27
  'top_left_rotate',
@@ -544,7 +545,7 @@ describe('Reisizing a selection of multiple shapes', () => {
544
545
  // └──────────────────O
545
546
 
546
547
  editor.pointerMove(15, 8, { altKey: false, shiftKey: true })
547
- jest.advanceTimersByTime(200)
548
+ vi.advanceTimersByTime(200)
548
549
 
549
550
  expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({ w: 15, h: 15 })
550
551
  expect(roundedPageBounds(ids.boxA)).toMatchObject({ x: 0, y: 0, w: 5, h: 5 })
@@ -593,7 +594,7 @@ describe('Reisizing a selection of multiple shapes', () => {
593
594
  editor.pointerDown(30, 20, { target: 'selection', handle: 'top_left_rotate' })
594
595
  editor.pointerMove(20, 20, { shiftKey: true })
595
596
  editor.pointerUp(20, 20, { shiftKey: false })
596
- jest.advanceTimersByTime(200)
597
+ vi.advanceTimersByTime(200)
597
598
 
598
599
  expect(editor.getShape(ids.boxB)!.rotation).toBeCloseTo(canonicalizeRotation(-PI / 2))
599
600
 
@@ -740,7 +741,7 @@ describe('Reisizing a selection of multiple shapes', () => {
740
741
  // └──────────────────O
741
742
 
742
743
  editor.pointerMove(15, 8, { altKey: false, shiftKey: true })
743
- jest.advanceTimersByTime(200)
744
+ vi.advanceTimersByTime(200)
744
745
 
745
746
  expect(roundedBox(editor.getSelectionPageBounds()!)).toMatchObject({ w: 15, h: 15 })
746
747
  expect(roundedPageBounds(ids.boxA)).toMatchObject({ x: 0, y: 0, w: 5, h: 5 })
@@ -2364,7 +2365,7 @@ describe('snapping while resizing a shape that has been rotated by multiples of
2364
2365
  .select(ids.boxX)
2365
2366
  .pointerDown(100, 70, { target: 'selection', handle: 'top' })
2366
2367
  .pointerMove(121, 70, { ctrlKey: true, shiftKey: false })
2367
- jest.advanceTimersByTime(200)
2368
+ vi.advanceTimersByTime(200)
2368
2369
 
2369
2370
  expect(editor.getShapePageBounds(ids.boxX)!).toMatchObject({
2370
2371
  x: 40,
@@ -2432,7 +2433,7 @@ describe('snapping while resizing a shape that has been rotated by multiples of
2432
2433
  .select(ids.boxX)
2433
2434
  .pointerDown(70, 40, { target: 'selection', handle: 'bottom' })
2434
2435
  .pointerMove(70, 18, { ctrlKey: true, shiftKey: false })
2435
- jest.advanceTimersByTime(200)
2436
+ vi.advanceTimersByTime(200)
2436
2437
 
2437
2438
  expect(editor.getShapePageBounds(ids.boxX)!.x).toBeCloseTo(40)
2438
2439
  expect(editor.getShapePageBounds(ids.boxX)!.y).toBeCloseTo(20)
@@ -2564,7 +2565,7 @@ describe('snapping while resizing a shape that has been rotated by multiples of
2564
2565
  .select(ids.boxX)
2565
2566
  .pointerDown(100, 70, { target: 'selection', handle: 'right' })
2566
2567
  .pointerMove(121, 70, { ctrlKey: true, shiftKey: false })
2567
- jest.advanceTimersByTime(200)
2568
+ vi.advanceTimersByTime(200)
2568
2569
 
2569
2570
  expect(editor.getShapePageBounds(ids.boxX)!.x).toBeCloseTo(40)
2570
2571
  expect(editor.getShapePageBounds(ids.boxX)!.y).toBeCloseTo(40)
@@ -3824,36 +3825,36 @@ describe('shapes that have do not resize', () => {
3824
3825
  // })
3825
3826
  // })
3826
3827
 
3827
- describe('bugs', () => {
3828
- // it('resizing a zero width shape', () => {
3829
- // // Draw shapes can no longer have zero width / height
3830
- // const shapeId = createShapeId()
3831
- // app
3832
- // .createShapes([
3833
- // {
3834
- // id: shapeId,
3835
- // type: 'draw',
3836
- // x: 0,
3837
- // y: 0,
3838
- // props: {
3839
- // segments: [
3840
- // {
3841
- // type: 'straight',
3842
- // points: [
3843
- // { x: 0, y: 0 },
3844
- // { x: 0, y: 100 },
3845
- // ],
3846
- // },
3847
- // ],
3848
- // },
3849
- // },
3850
- // ])
3851
- // .select(shapeId)
3852
- // expect(editor.selectionRotatedBounds!.width).toBe(0)
3853
- // editor.pointerDown(0, 100, { target: 'selection', handle: 'bottom_right' }).pointerMove(10, 110)
3854
- // expect(editor.selectionRotatedBounds!.width).toBe(0)
3855
- // })
3856
- })
3828
+ // describe('bugs', () => {
3829
+ // it('resizing a zero width shape', () => {
3830
+ // // Draw shapes can no longer have zero width / height
3831
+ // const shapeId = createShapeId()
3832
+ // app
3833
+ // .createShapes([
3834
+ // {
3835
+ // id: shapeId,
3836
+ // type: 'draw',
3837
+ // x: 0,
3838
+ // y: 0,
3839
+ // props: {
3840
+ // segments: [
3841
+ // {
3842
+ // type: 'straight',
3843
+ // points: [
3844
+ // { x: 0, y: 0 },
3845
+ // { x: 0, y: 100 },
3846
+ // ],
3847
+ // },
3848
+ // ],
3849
+ // },
3850
+ // },
3851
+ // ])
3852
+ // .select(shapeId)
3853
+ // expect(editor.selectionRotatedBounds!.width).toBe(0)
3854
+ // editor.pointerDown(0, 100, { target: 'selection', handle: 'bottom_right' }).pointerMove(10, 110)
3855
+ // expect(editor.selectionRotatedBounds!.width).toBe(0)
3856
+ // })
3857
+ // })
3857
3858
 
3858
3859
  it('uses the cross cursor when create resizing', () => {
3859
3860
  editor.setCurrentTool('geo')
@@ -3942,7 +3943,7 @@ describe('When resizing near the edges of the screen', () => {
3942
3943
  handle: 'top_left',
3943
3944
  })
3944
3945
  .pointerMove(-1, -1) // into the edge scrolling distance
3945
- jest.advanceTimersByTime(1000)
3946
+ vi.advanceTimersByTime(1000)
3946
3947
  const after = editor.getShape<TLGeoShape>(ids.boxA)!
3947
3948
  expect(after.x).toBeLessThan(before.x)
3948
3949
  expect(after.y).toBeLessThan(before.y)
@@ -1,3 +1,4 @@
1
+ import { vi } from 'vitest'
1
2
  import { SelectTool } from '../lib/tools/SelectTool/SelectTool'
2
3
  import { TestEditor } from './TestEditor'
3
4
  import { TL } from './test-jsx'
@@ -28,12 +29,12 @@ describe(SelectTool, () => {
28
29
  // clicking on the input will preserve selection, however you can
29
30
  // click on the shape itself to select it as usual.
30
31
  // clicking on the shape should not do anything
31
- // jest.advanceTimersByTime(1000)
32
+ // vi.advanceTimersByTime(1000)
32
33
  // editor.pointerDown(50, 50, shapeId)
33
34
  // expect(editor.currentPageState.editingShapeId).toBe(shapeId)
34
35
 
35
36
  // clicking outside the shape should end editing
36
- jest.advanceTimersByTime(1000)
37
+ vi.advanceTimersByTime(1000)
37
38
 
38
39
  editor.pointerDown(150, 150).pointerUp()
39
40
  expect(editor.getCurrentPageState().editingShapeId).toBe(null)
@@ -51,7 +52,7 @@ describe(SelectTool, () => {
51
52
  expect(editor.getCurrentPageState().editingShapeId).toBe(shapeId)
52
53
 
53
54
  // clicking outside the shape should end editing
54
- jest.advanceTimersByTime(1000)
55
+ vi.advanceTimersByTime(1000)
55
56
 
56
57
  editor.pointerDown(150, 150).pointerUp()
57
58
  expect(editor.getCurrentPageState().editingShapeId).toBe(null)
@@ -7,6 +7,7 @@ import {
7
7
  tlenv,
8
8
  toRichText,
9
9
  } from '@tldraw/editor'
10
+ import { vi } from 'vitest'
10
11
  import { TestEditor } from './TestEditor'
11
12
 
12
13
  let editor: TestEditor
@@ -1652,7 +1653,7 @@ describe('shift brushes to add to the selection', () => {
1652
1653
  editor.keyUp('Shift')
1653
1654
  // there's a timer here—we should keep the shift mode until the timer expires
1654
1655
  expect(editor.getSelectedShapeIds()).toEqual([ids.box2, ids.box1])
1655
- jest.advanceTimersByTime(500)
1656
+ vi.advanceTimersByTime(500)
1656
1657
  // once the timer expires, we should be back in regular mode
1657
1658
  expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
1658
1659
  editor.keyDown('Shift')
@@ -1722,7 +1723,7 @@ describe('scribble brushes to add to the selection', () => {
1722
1723
  editor.pointerMove(50, 50)
1723
1724
  expect(editor.getSelectedShapeIds()).toEqual([ids.box1, ids.box2])
1724
1725
  editor.keyUp('Shift')
1725
- jest.advanceTimersByTime(500)
1726
+ vi.advanceTimersByTime(500)
1726
1727
  expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
1727
1728
  editor.keyDown('Shift')
1728
1729
  expect(editor.getSelectedShapeIds()).toEqual([ids.box1, ids.box2])
@@ -1739,7 +1740,7 @@ describe('scribble brushes to add to the selection', () => {
1739
1740
  expect(editor.getSelectedShapeIds()).toEqual([ids.box4])
1740
1741
  editor.keyUp('Alt') // scribble
1741
1742
  expect(editor.getSelectedShapeIds()).toEqual([ids.box4]) // still in timer
1742
- jest.advanceTimersByTime(1000) // let timer expire
1743
+ vi.advanceTimersByTime(1000) // let timer expire
1743
1744
  expect(editor.getSelectedShapeIds()).toEqual([ids.box3, ids.box4]) // brushed!
1744
1745
  editor.keyDown('Alt') // scribble
1745
1746
  expect(editor.getSelectedShapeIds()).toEqual([ids.box4]) // back to brushed only
@@ -1824,7 +1825,7 @@ describe('When brushing close to the edges of the screen', () => {
1824
1825
  editor.pointerMove(300, 300)
1825
1826
  editor.pointerDown()
1826
1827
  editor.pointerMove(0, 0)
1827
- jest.advanceTimersByTime(100)
1828
+ vi.advanceTimersByTime(100)
1828
1829
  editor.pointerUp()
1829
1830
  const camera2 = editor.getCamera()
1830
1831
  expect(camera2.x).toBeGreaterThan(camera1.x) // for some reason > is left
@@ -1837,7 +1838,7 @@ describe('When brushing close to the edges of the screen', () => {
1837
1838
  editor.pointerMove(300, 300)
1838
1839
  editor.pointerDown()
1839
1840
  editor.pointerMove(100, 100)
1840
- jest.advanceTimersByTime(100)
1841
+ vi.advanceTimersByTime(100)
1841
1842
  editor.pointerUp()
1842
1843
  const camera2 = editor.getCamera()
1843
1844
  // should NOT have moved the camera by edge scrolling
@@ -1851,7 +1852,7 @@ describe('When brushing close to the edges of the screen', () => {
1851
1852
  editor.pointerMove(300, 300)
1852
1853
  editor.pointerDown()
1853
1854
  editor.pointerMove(100, 100)
1854
- jest.advanceTimersByTime(100)
1855
+ vi.advanceTimersByTime(100)
1855
1856
  editor.pointerUp()
1856
1857
  const camera4 = editor.getCamera()
1857
1858
  // should NOT have moved the camera by edge scrolling because the edge is now "inset"
@@ -1860,7 +1861,7 @@ describe('When brushing close to the edges of the screen', () => {
1860
1861
 
1861
1862
  editor.pointerDown()
1862
1863
  editor.pointerMove(90, 90) // off the edge of the component
1863
- jest.advanceTimersByTime(100)
1864
+ vi.advanceTimersByTime(100)
1864
1865
  const camera5 = editor.getCamera()
1865
1866
  // should have moved the camera by edge scrolling off the component edge
1866
1867
  expect(camera5.x).toBeGreaterThan(camera4.x)
@@ -1882,7 +1883,7 @@ describe('When brushing close to the edges of the screen', () => {
1882
1883
  editor.pointerMove(0, 0)
1883
1884
  // still only box 1...
1884
1885
  expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
1885
- jest.advanceTimersByTime(100)
1886
+ vi.advanceTimersByTime(100)
1886
1887
  // ...but now viewport will have moved to select box2 as well
1887
1888
  expect(editor.getSelectedShapeIds()).toEqual([ids.box1, ids.box2])
1888
1889
  editor.pointerUp()
@@ -1902,7 +1903,7 @@ describe('When brushing close to the edges of the screen', () => {
1902
1903
  expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
1903
1904
  editor.pointerMove(0, 0)
1904
1905
  expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
1905
- jest.advanceTimersByTime(100)
1906
+ vi.advanceTimersByTime(100)
1906
1907
  expect(editor.getSelectedShapeIds()).toEqual([ids.box1])
1907
1908
  editor.pointerUp()
1908
1909
  })
@@ -2199,7 +2200,7 @@ describe('long press', () => {
2199
2200
  it('works correctly with screenbounds offset', () => {
2200
2201
  editor.updateViewportScreenBounds(new Box(100, 100, 800, 600))
2201
2202
  editor.pointerDown(201, 202)
2202
- jest.advanceTimersByTime(1000)
2203
+ vi.advanceTimersByTime(1000)
2203
2204
  // without the fix added in this PR, it would have been 1, 2
2204
2205
  expect(editor.inputs.currentScreenPoint).toMatchObject({ x: 101, y: 102 })
2205
2206
  })