tldraw 3.16.0-next.282b7be564ae → 3.16.0-next.2f9d39693e4c

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 (291) hide show
  1. package/dist-cjs/index.d.ts +224 -102
  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 +5 -4
  7. package/dist-cjs/lib/defaultExternalContentHandlers.js.map +2 -2
  8. package/dist-cjs/lib/shapes/arrow/arrowLabel.js +6 -0
  9. package/dist-cjs/lib/shapes/arrow/arrowLabel.js.map +3 -3
  10. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js +6 -0
  11. package/dist-cjs/lib/shapes/frame/FrameShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js +3 -0
  13. package/dist-cjs/lib/shapes/image/ImageShapeUtil.js.map +2 -2
  14. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js +1 -3
  15. package/dist-cjs/lib/shapes/shared/PlainTextLabel.js.map +2 -2
  16. package/dist-cjs/lib/shapes/shared/freehand/svg.js.map +2 -2
  17. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js +0 -2
  18. package/dist-cjs/lib/shapes/shared/useEditablePlainText.js.map +2 -2
  19. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js +0 -2
  20. package/dist-cjs/lib/shapes/shared/useImageOrVideoAsset.js.map +2 -2
  21. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js +25 -1
  22. package/dist-cjs/lib/tools/EraserTool/childStates/Erasing.js.map +2 -2
  23. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js +12 -0
  24. package/dist-cjs/lib/tools/EraserTool/childStates/Pointing.js.map +2 -2
  25. package/dist-cjs/lib/ui/TldrawUi.js +13 -12
  26. package/dist-cjs/lib/ui/TldrawUi.js.map +2 -2
  27. package/dist-cjs/lib/ui/assetUrls.js +13 -10
  28. package/dist-cjs/lib/ui/assetUrls.js.map +2 -2
  29. package/dist-cjs/lib/ui/components/{FollowingIndicator.js → DefaultFollowingIndicator.js} +6 -6
  30. package/dist-cjs/lib/ui/components/DefaultFollowingIndicator.js.map +7 -0
  31. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js +6 -6
  32. package/dist-cjs/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.js.map +1 -1
  33. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js +9 -4
  34. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanel.js.map +2 -2
  35. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js +255 -316
  36. package/dist-cjs/lib/ui/components/StylePanel/DefaultStylePanelContent.js.map +2 -2
  37. package/dist-cjs/lib/ui/components/{primitives/TldrawUiButtonPicker.js → StylePanel/StylePanelButtonPicker.js} +52 -45
  38. package/dist-cjs/lib/ui/components/StylePanel/StylePanelButtonPicker.js.map +7 -0
  39. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js +68 -0
  40. package/dist-cjs/lib/ui/components/StylePanel/StylePanelContext.js.map +7 -0
  41. package/dist-cjs/lib/ui/components/StylePanel/{DoubleDropdownPicker.js → StylePanelDoubleDropdownPicker.js} +23 -22
  42. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.js.map +7 -0
  43. package/dist-cjs/lib/ui/components/StylePanel/{DropdownPicker.js → StylePanelDropdownPicker.js} +24 -21
  44. package/dist-cjs/lib/ui/components/StylePanel/StylePanelDropdownPicker.js.map +7 -0
  45. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js +28 -0
  46. package/dist-cjs/lib/ui/components/StylePanel/StylePanelSubheading.js.map +7 -0
  47. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js +3 -2
  48. package/dist-cjs/lib/ui/components/Toolbar/AltTextEditor.js.map +2 -2
  49. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js +38 -9
  50. package/dist-cjs/lib/ui/components/Toolbar/DefaultImageToolbarContent.js.map +2 -2
  51. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js +15 -3
  52. package/dist-cjs/lib/ui/components/Toolbar/DefaultVideoToolbarContent.js.map +2 -2
  53. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js +3 -3
  54. package/dist-cjs/lib/ui/components/Toolbar/LinkEditor.js.map +2 -2
  55. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js +10 -1
  56. package/dist-cjs/lib/ui/components/primitives/TldrawUiContextualToolbar.js.map +2 -2
  57. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js +17 -4
  58. package/dist-cjs/lib/ui/components/primitives/TldrawUiSlider.js.map +2 -2
  59. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js +2 -0
  60. package/dist-cjs/lib/ui/components/primitives/TldrawUiToolbar.js.map +2 -2
  61. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js +37 -36
  62. package/dist-cjs/lib/ui/components/primitives/TldrawUiTooltip.js.map +2 -2
  63. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js +2 -1
  64. package/dist-cjs/lib/ui/components/primitives/menus/TldrawUiMenuItem.js.map +2 -2
  65. package/dist-cjs/lib/ui/context/actions.js +23 -10
  66. package/dist-cjs/lib/ui/context/actions.js.map +2 -2
  67. package/dist-cjs/lib/ui/context/components.js +2 -0
  68. package/dist-cjs/lib/ui/context/components.js.map +2 -2
  69. package/dist-cjs/lib/ui/context/events.js.map +1 -1
  70. package/dist-cjs/lib/ui/hooks/useExportAs.js +3 -2
  71. package/dist-cjs/lib/ui/hooks/useExportAs.js.map +2 -2
  72. package/dist-cjs/lib/ui/hooks/useTools.js +1 -1
  73. package/dist-cjs/lib/ui/hooks/useTools.js.map +2 -2
  74. package/dist-cjs/lib/ui/hooks/useTranslation/TLUiTranslationKey.js.map +1 -1
  75. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js +2 -0
  76. package/dist-cjs/lib/ui/hooks/useTranslation/defaultTranslation.js.map +2 -2
  77. package/dist-cjs/lib/ui/kbd-utils.js +9 -3
  78. package/dist-cjs/lib/ui/kbd-utils.js.map +2 -2
  79. package/dist-cjs/lib/ui/version.js +3 -3
  80. package/dist-cjs/lib/ui/version.js.map +1 -1
  81. package/dist-cjs/lib/utils/export/copyAs.js +1 -2
  82. package/dist-cjs/lib/utils/export/copyAs.js.map +2 -2
  83. package/dist-cjs/lib/utils/export/export.js +0 -20
  84. package/dist-cjs/lib/utils/export/export.js.map +2 -2
  85. package/dist-cjs/lib/utils/export/exportAs.js +1 -2
  86. package/dist-cjs/lib/utils/export/exportAs.js.map +2 -2
  87. package/dist-esm/index.d.mts +224 -102
  88. package/dist-esm/index.mjs +61 -29
  89. package/dist-esm/index.mjs.map +2 -2
  90. package/dist-esm/lib/Tldraw.mjs +14 -4
  91. package/dist-esm/lib/Tldraw.mjs.map +2 -2
  92. package/dist-esm/lib/defaultExternalContentHandlers.mjs +5 -4
  93. package/dist-esm/lib/defaultExternalContentHandlers.mjs.map +2 -2
  94. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs +6 -0
  95. package/dist-esm/lib/shapes/arrow/arrowLabel.mjs.map +3 -3
  96. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs +6 -0
  97. package/dist-esm/lib/shapes/frame/FrameShapeUtil.mjs.map +2 -2
  98. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs +3 -0
  99. package/dist-esm/lib/shapes/image/ImageShapeUtil.mjs.map +2 -2
  100. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs +1 -3
  101. package/dist-esm/lib/shapes/shared/PlainTextLabel.mjs.map +2 -2
  102. package/dist-esm/lib/shapes/shared/freehand/svg.mjs.map +2 -2
  103. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs +0 -2
  104. package/dist-esm/lib/shapes/shared/useEditablePlainText.mjs.map +2 -2
  105. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs +0 -2
  106. package/dist-esm/lib/shapes/shared/useImageOrVideoAsset.mjs.map +2 -2
  107. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs +26 -1
  108. package/dist-esm/lib/tools/EraserTool/childStates/Erasing.mjs.map +2 -2
  109. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs +13 -0
  110. package/dist-esm/lib/tools/EraserTool/childStates/Pointing.mjs.map +2 -2
  111. package/dist-esm/lib/ui/TldrawUi.mjs +13 -12
  112. package/dist-esm/lib/ui/TldrawUi.mjs.map +2 -2
  113. package/dist-esm/lib/ui/assetUrls.mjs +13 -10
  114. package/dist-esm/lib/ui/assetUrls.mjs.map +2 -2
  115. package/dist-esm/lib/ui/components/{FollowingIndicator.mjs → DefaultFollowingIndicator.mjs} +3 -3
  116. package/dist-esm/lib/ui/components/DefaultFollowingIndicator.mjs.map +7 -0
  117. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs +6 -6
  118. package/dist-esm/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.mjs.map +1 -1
  119. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs +14 -5
  120. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanel.mjs.map +2 -2
  121. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs +257 -320
  122. package/dist-esm/lib/ui/components/StylePanel/DefaultStylePanelContent.mjs.map +2 -2
  123. package/dist-esm/lib/ui/components/{primitives/TldrawUiButtonPicker.mjs → StylePanel/StylePanelButtonPicker.mjs} +54 -43
  124. package/dist-esm/lib/ui/components/StylePanel/StylePanelButtonPicker.mjs.map +7 -0
  125. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs +48 -0
  126. package/dist-esm/lib/ui/components/StylePanel/StylePanelContext.mjs.map +7 -0
  127. package/dist-esm/lib/ui/components/StylePanel/{DoubleDropdownPicker.mjs → StylePanelDoubleDropdownPicker.mjs} +20 -19
  128. package/dist-esm/lib/ui/components/StylePanel/StylePanelDoubleDropdownPicker.mjs.map +7 -0
  129. package/dist-esm/lib/ui/components/StylePanel/{DropdownPicker.mjs → StylePanelDropdownPicker.mjs} +21 -18
  130. package/dist-esm/lib/ui/components/StylePanel/StylePanelDropdownPicker.mjs.map +7 -0
  131. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs +8 -0
  132. package/dist-esm/lib/ui/components/StylePanel/StylePanelSubheading.mjs.map +7 -0
  133. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs +3 -2
  134. package/dist-esm/lib/ui/components/Toolbar/AltTextEditor.mjs.map +2 -2
  135. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs +38 -9
  136. package/dist-esm/lib/ui/components/Toolbar/DefaultImageToolbarContent.mjs.map +2 -2
  137. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs +15 -3
  138. package/dist-esm/lib/ui/components/Toolbar/DefaultVideoToolbarContent.mjs.map +2 -2
  139. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs +3 -3
  140. package/dist-esm/lib/ui/components/Toolbar/LinkEditor.mjs.map +2 -2
  141. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs +10 -1
  142. package/dist-esm/lib/ui/components/primitives/TldrawUiContextualToolbar.mjs.map +2 -2
  143. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs +17 -4
  144. package/dist-esm/lib/ui/components/primitives/TldrawUiSlider.mjs.map +2 -2
  145. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs +2 -0
  146. package/dist-esm/lib/ui/components/primitives/TldrawUiToolbar.mjs.map +2 -2
  147. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs +37 -36
  148. package/dist-esm/lib/ui/components/primitives/TldrawUiTooltip.mjs.map +2 -2
  149. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs +2 -1
  150. package/dist-esm/lib/ui/components/primitives/menus/TldrawUiMenuItem.mjs.map +2 -2
  151. package/dist-esm/lib/ui/context/actions.mjs +23 -10
  152. package/dist-esm/lib/ui/context/actions.mjs.map +2 -2
  153. package/dist-esm/lib/ui/context/components.mjs +2 -0
  154. package/dist-esm/lib/ui/context/components.mjs.map +2 -2
  155. package/dist-esm/lib/ui/context/events.mjs.map +1 -1
  156. package/dist-esm/lib/ui/hooks/useExportAs.mjs +3 -2
  157. package/dist-esm/lib/ui/hooks/useExportAs.mjs.map +2 -2
  158. package/dist-esm/lib/ui/hooks/useTools.mjs +1 -1
  159. package/dist-esm/lib/ui/hooks/useTools.mjs.map +2 -2
  160. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs +2 -0
  161. package/dist-esm/lib/ui/hooks/useTranslation/defaultTranslation.mjs.map +2 -2
  162. package/dist-esm/lib/ui/kbd-utils.mjs +9 -3
  163. package/dist-esm/lib/ui/kbd-utils.mjs.map +2 -2
  164. package/dist-esm/lib/ui/version.mjs +3 -3
  165. package/dist-esm/lib/ui/version.mjs.map +1 -1
  166. package/dist-esm/lib/utils/export/copyAs.mjs +1 -2
  167. package/dist-esm/lib/utils/export/copyAs.mjs.map +2 -2
  168. package/dist-esm/lib/utils/export/export.mjs +0 -20
  169. package/dist-esm/lib/utils/export/export.mjs.map +2 -2
  170. package/dist-esm/lib/utils/export/exportAs.mjs +1 -2
  171. package/dist-esm/lib/utils/export/exportAs.mjs.map +2 -2
  172. package/package.json +11 -34
  173. package/src/index.ts +44 -22
  174. package/src/lib/Tldraw.tsx +15 -2
  175. package/src/lib/defaultExternalContentHandlers.ts +12 -4
  176. package/src/lib/shapes/arrow/ArrowShapeOptions.test.ts +2 -1
  177. package/src/lib/shapes/arrow/ArrowShapeTool.test.ts +4 -3
  178. package/src/lib/shapes/arrow/ArrowShapeUtil.test.ts +7 -6
  179. package/src/lib/shapes/arrow/arrowLabel.ts +8 -0
  180. package/src/lib/shapes/draw/DrawShapeTool.test.ts +0 -5
  181. package/src/lib/shapes/frame/FrameShapeUtil.tsx +8 -0
  182. package/src/lib/shapes/image/ImageShapeUtil.tsx +3 -0
  183. package/src/lib/shapes/line/LineShapeUtil.test.tsx +4 -3
  184. package/src/lib/shapes/line/__snapshots__/LineShapeUtil.test.tsx.snap +2 -2
  185. package/src/lib/shapes/shared/PlainTextLabel.tsx +0 -6
  186. package/src/lib/shapes/shared/freehand/svg.ts +2 -0
  187. package/src/lib/shapes/shared/useEditablePlainText.ts +0 -6
  188. package/src/lib/shapes/shared/useImageOrVideoAsset.ts +0 -7
  189. package/src/lib/shapes/text/TextShapeTool.test.ts +6 -5
  190. package/src/lib/tools/EraserTool/childStates/Erasing.ts +34 -1
  191. package/src/lib/tools/EraserTool/childStates/Pointing.ts +20 -0
  192. package/src/lib/ui/TldrawUi.tsx +16 -10
  193. package/src/lib/ui/assetUrls.ts +13 -10
  194. package/src/lib/ui/components/{FollowingIndicator.tsx → DefaultFollowingIndicator.tsx} +2 -1
  195. package/src/lib/ui/components/KeyboardShortcutsDialog/DefaultKeyboardShortcutsDialogContent.tsx +6 -6
  196. package/src/lib/ui/components/StylePanel/DefaultStylePanel.tsx +27 -13
  197. package/src/lib/ui/components/StylePanel/DefaultStylePanelContent.tsx +260 -381
  198. package/src/lib/ui/components/{primitives/TldrawUiButtonPicker.tsx → StylePanel/StylePanelButtonPicker.tsx} +63 -50
  199. package/src/lib/ui/components/StylePanel/StylePanelContext.tsx +63 -0
  200. package/src/lib/ui/components/StylePanel/{DoubleDropdownPicker.tsx → StylePanelDoubleDropdownPicker.tsx} +28 -19
  201. package/src/lib/ui/components/StylePanel/StylePanelDropdownPicker.tsx +119 -0
  202. package/src/lib/ui/components/StylePanel/StylePanelSubheading.tsx +9 -0
  203. package/src/lib/ui/components/Toolbar/AltTextEditor.tsx +4 -3
  204. package/src/lib/ui/components/Toolbar/DefaultImageToolbarContent.tsx +32 -15
  205. package/src/lib/ui/components/Toolbar/DefaultVideoToolbarContent.tsx +12 -4
  206. package/src/lib/ui/components/Toolbar/LinkEditor.tsx +5 -5
  207. package/src/lib/ui/components/primitives/TldrawUiContextualToolbar.tsx +6 -1
  208. package/src/lib/ui/components/primitives/TldrawUiSlider.tsx +50 -30
  209. package/src/lib/ui/components/primitives/TldrawUiToolbar.tsx +3 -0
  210. package/src/lib/ui/components/primitives/TldrawUiTooltip.tsx +29 -21
  211. package/src/lib/ui/components/primitives/menus/TldrawUiMenuItem.tsx +3 -2
  212. package/src/lib/ui/context/actions.tsx +23 -10
  213. package/src/lib/ui/context/components.tsx +3 -0
  214. package/src/lib/ui/context/events.tsx +1 -1
  215. package/src/lib/ui/hooks/useExportAs.ts +3 -2
  216. package/src/lib/ui/hooks/useTools.tsx +1 -1
  217. package/src/lib/ui/hooks/useTranslation/TLUiTranslationKey.ts +2 -0
  218. package/src/lib/ui/hooks/useTranslation/defaultTranslation.ts +2 -0
  219. package/src/lib/ui/kbd-utils.ts +10 -3
  220. package/src/lib/ui/version.ts +3 -3
  221. package/src/lib/ui.css +19 -2
  222. package/src/lib/utils/excalidraw/__snapshots__/putExcalidrawContent.test.tsx.snap +5 -5
  223. package/src/lib/utils/export/copyAs.ts +1 -24
  224. package/src/lib/utils/export/export.ts +0 -36
  225. package/src/lib/utils/export/exportAs.ts +1 -32
  226. package/src/lib/utils/tldr/__snapshots__/buildFromV1Document.test.ts.snap +4 -4
  227. package/src/test/A11y.test.tsx +3 -2
  228. package/src/test/ClickManager.test.ts +7 -6
  229. package/src/test/Editor.test.tsx +20 -19
  230. package/src/test/EraserTool.test.ts +184 -13
  231. package/src/test/HandTool.test.ts +10 -9
  232. package/src/test/HighlightShape.test.ts +2 -1
  233. package/src/test/SelectTool.test.ts +3 -2
  234. package/src/test/TLUserPreferences.test.ts +4 -3
  235. package/src/test/TestEditor.ts +13 -15
  236. package/src/test/TldrawEditor.test.tsx +11 -10
  237. package/src/test/ZoomTool.test.ts +7 -6
  238. package/src/test/__snapshots__/drawing.test.ts.snap +2 -2
  239. package/src/test/__snapshots__/groups.test.tsx.snap +6 -6
  240. package/src/test/__snapshots__/resizing.test.ts.snap +2 -2
  241. package/src/test/arrows-megabus.test.tsx +5 -4
  242. package/src/test/bindings.test.tsx +24 -37
  243. package/src/test/bookmark-shapes.test.ts +1 -8
  244. package/src/test/commands/__snapshots__/getSvgString.test.ts.snap +23 -7
  245. package/src/test/commands/__snapshots__/packShapes.test.ts.snap +8 -8
  246. package/src/test/commands/__snapshots__/zoomToFit.test.ts.snap +2 -2
  247. package/src/test/commands/alignShapes.test.tsx +25 -24
  248. package/src/test/commands/animationSpeed.test.ts +2 -1
  249. package/src/test/commands/centerOnPoint.test.ts +3 -2
  250. package/src/test/commands/clipboard.test.ts +3 -2
  251. package/src/test/commands/createShapes.test.ts +2 -1
  252. package/src/test/commands/deleteShapes.test.ts +2 -1
  253. package/src/test/commands/distributeShapes.test.tsx +11 -10
  254. package/src/test/commands/getSvgString.test.ts +2 -1
  255. package/src/test/commands/packShapes.test.ts +5 -4
  256. package/src/test/commands/resizeShape.test.ts +2 -1
  257. package/src/test/commands/rotateShapes.test.ts +7 -6
  258. package/src/test/commands/setCamera.test.ts +4 -3
  259. package/src/test/commands/setCurrentPage.test.ts +3 -2
  260. package/src/test/commands/stackShapes.test.ts +11 -10
  261. package/src/test/commands/stretch.test.tsx +13 -12
  262. package/src/test/createDeepLink.test.tsx +2 -1
  263. package/src/test/cropping.test.ts +3 -2
  264. package/src/test/custom-clipping.test.ts +436 -0
  265. package/src/test/drawing.test.ts +2 -1
  266. package/src/test/flipShapes.test.ts +4 -3
  267. package/src/test/frames.test.ts +25 -24
  268. package/src/test/getCulledShapes.test.tsx +3 -2
  269. package/src/test/groups.test.tsx +1 -1
  270. package/src/test/handleDeepLink.test.tsx +2 -1
  271. package/src/test/maxShapes.test.ts +3 -2
  272. package/src/test/modifiers.test.ts +5 -4
  273. package/src/test/navigation.test.ts +12 -11
  274. package/src/test/panning.test.ts +2 -1
  275. package/src/test/perf/perf.test.ts +2 -1
  276. package/src/test/registerDeepLinkListener.test.tsx +10 -9
  277. package/src/test/resizing.test.ts +39 -38
  278. package/src/test/select.test.tsx +4 -3
  279. package/src/test/selection-omnibus.test.ts +11 -10
  280. package/src/test/shapeutils.test.ts +4 -3
  281. package/src/test/translating.test.ts +9 -8
  282. package/tldraw.css +27 -2
  283. package/dist-cjs/lib/ui/components/FollowingIndicator.js.map +0 -7
  284. package/dist-cjs/lib/ui/components/StylePanel/DoubleDropdownPicker.js.map +0 -7
  285. package/dist-cjs/lib/ui/components/StylePanel/DropdownPicker.js.map +0 -7
  286. package/dist-cjs/lib/ui/components/primitives/TldrawUiButtonPicker.js.map +0 -7
  287. package/dist-esm/lib/ui/components/FollowingIndicator.mjs.map +0 -7
  288. package/dist-esm/lib/ui/components/StylePanel/DoubleDropdownPicker.mjs.map +0 -7
  289. package/dist-esm/lib/ui/components/StylePanel/DropdownPicker.mjs.map +0 -7
  290. package/dist-esm/lib/ui/components/primitives/TldrawUiButtonPicker.mjs.map +0 -7
  291. package/src/lib/ui/components/StylePanel/DropdownPicker.tsx +0 -110
@@ -28,38 +28,7 @@ export async function exportAs(
28
28
  editor: Editor,
29
29
  ids: TLShapeId[],
30
30
  opts: ExportAsOptions
31
- ): Promise<void>
32
- /**
33
- * @deprecated The format & name parameters are now part of the opts object.
34
- * @public
35
- */
36
- export async function exportAs(
37
- editor: Editor,
38
- ids: TLShapeId[],
39
- format?: TLExportType,
40
- name?: string,
41
- opts?: TLImageExportOptions
42
- ): Promise<void>
43
- export async function exportAs(
44
- ...args:
45
- | [
46
- editor: Editor,
47
- ids: TLShapeId[],
48
- opts: TLImageExportOptions & { format: TLExportType; name?: string },
49
- ]
50
- | [
51
- editor: Editor,
52
- ids: TLShapeId[],
53
- format?: TLExportType,
54
- name?: string,
55
- opts?: TLImageExportOptions,
56
- ]
57
- ) {
58
- const [editor, ids, opts] =
59
- typeof args[2] === 'object'
60
- ? args
61
- : [args[0], args[1], { ...args[4], format: args[2] ?? 'png', name: args[3] }]
62
-
31
+ ): Promise<void> {
63
32
  // If we don't get name then use a predefined one
64
33
  let name = opts.name
65
34
  if (!name) {
@@ -1,6 +1,6 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`buildFromV1Document test fixtures arrow-binding.tldr 1`] = `
3
+ exports[`buildFromV1Document test fixtures > arrow-binding.tldr 1`] = `
4
4
  {
5
5
  "binding:12": {
6
6
  "fromId": "shape:11",
@@ -173,7 +173,7 @@ exports[`buildFromV1Document test fixtures arrow-binding.tldr 1`] = `
173
173
  }
174
174
  `;
175
175
 
176
- exports[`buildFromV1Document test fixtures exact-arrow-binding.tldr 1`] = `
176
+ exports[`buildFromV1Document test fixtures > exact-arrow-binding.tldr 1`] = `
177
177
  {
178
178
  "binding:11": {
179
179
  "fromId": "shape:10",
@@ -346,7 +346,7 @@ exports[`buildFromV1Document test fixtures exact-arrow-binding.tldr 1`] = `
346
346
  }
347
347
  `;
348
348
 
349
- exports[`buildFromV1Document test fixtures incorrect-arrow-binding.tldr 1`] = `
349
+ exports[`buildFromV1Document test fixtures > incorrect-arrow-binding.tldr 1`] = `
350
350
  {
351
351
  "binding:11": {
352
352
  "fromId": "shape:10",
@@ -1,16 +1,17 @@
1
1
  import { createShapeId, toRichText } from '@tldraw/editor'
2
+ import { Mock, vi } from 'vitest'
2
3
  import { generateShapeAnnouncementMessage } from '../lib/ui/components/A11y'
3
4
  import { TestEditor } from './TestEditor'
4
5
 
5
6
  describe('A11y Shape Announcements', () => {
6
7
  let editor: TestEditor
7
- let mockTranslate: jest.Mock
8
+ let mockTranslate: Mock
8
9
 
9
10
  beforeEach(() => {
10
11
  editor = new TestEditor()
11
12
 
12
13
  // Create a simple translation mock
13
- mockTranslate = jest.fn((key) => {
14
+ mockTranslate = vi.fn((key) => {
14
15
  if (key === 'a11y.multiple-shapes') return '{num} shapes selected'
15
16
  if (key === 'a11y.shape') return 'Shape'
16
17
  if (key === 'a11y.text') return 'Text'
@@ -1,3 +1,4 @@
1
+ import { vi } from 'vitest'
1
2
  import { TestEditor } from './TestEditor'
2
3
 
3
4
  let editor: TestEditor
@@ -10,7 +11,7 @@ beforeEach(() => {
10
11
  editor._transformPointerUpSpy.mockRestore()
11
12
  })
12
13
 
13
- jest.useFakeTimers()
14
+ vi.useFakeTimers()
14
15
 
15
16
  describe('Handles events', () => {
16
17
  it('Emits single click events', () => {
@@ -23,7 +24,7 @@ describe('Handles events', () => {
23
24
  const eventsBeforeSettle = [{ name: 'pointer_down' }, { name: 'pointer_up' }]
24
25
 
25
26
  // allow time for settle
26
- jest.advanceTimersByTime(500)
27
+ vi.advanceTimersByTime(500)
27
28
 
28
29
  // nothing should have settled
29
30
  expect(events).toMatchObject(eventsBeforeSettle)
@@ -64,7 +65,7 @@ describe('Handles events', () => {
64
65
  }
65
66
 
66
67
  // allow double click to settle
67
- jest.advanceTimersByTime(500)
68
+ vi.advanceTimersByTime(500)
68
69
 
69
70
  expect(events).toMatchObject([
70
71
  ...eventsBeforeSettle,
@@ -110,7 +111,7 @@ describe('Handles events', () => {
110
111
  expect(eventsBeforeSettle).toMatchObject(eventsBeforeSettle)
111
112
 
112
113
  // allow double click to settle
113
- jest.advanceTimersByTime(500)
114
+ vi.advanceTimersByTime(500)
114
115
 
115
116
  expect(events).toMatchObject([
116
117
  ...eventsBeforeSettle,
@@ -162,7 +163,7 @@ describe('Handles events', () => {
162
163
  expect(events).toMatchObject(eventsBeforeSettle)
163
164
 
164
165
  // allow double click to settle
165
- jest.advanceTimersByTime(500)
166
+ vi.advanceTimersByTime(500)
166
167
 
167
168
  expect(events).toMatchObject([
168
169
  ...eventsBeforeSettle,
@@ -218,7 +219,7 @@ describe('Handles events', () => {
218
219
  expect(events).toMatchObject(eventsBeforeSettle)
219
220
 
220
221
  // allow double click to settle
221
- jest.advanceTimersByTime(500)
222
+ vi.advanceTimersByTime(500)
222
223
 
223
224
  expect(events).toMatchObject(eventsBeforeSettle)
224
225
 
@@ -14,6 +14,7 @@ import {
14
14
  loadSnapshot,
15
15
  react,
16
16
  } from '@tldraw/editor'
17
+ import { vi } from 'vitest'
17
18
  import { TestEditor } from './TestEditor'
18
19
  import { TL } from './test-jsx'
19
20
 
@@ -415,24 +416,24 @@ describe('isFocused', () => {
415
416
  })
416
417
 
417
418
  it('becomes true when the container div receives a focus event', () => {
418
- jest.advanceTimersByTime(100)
419
+ vi.advanceTimersByTime(100)
419
420
  expect(editor.getInstanceState().isFocused).toBe(false)
420
421
 
421
422
  editor.elm.focus()
422
423
 
423
- jest.advanceTimersByTime(100)
424
+ vi.advanceTimersByTime(100)
424
425
  expect(editor.getInstanceState().isFocused).toBe(true)
425
426
  })
426
427
 
427
428
  it('becomes false when the container div receives a blur event', () => {
428
429
  editor.elm.focus()
429
430
 
430
- jest.advanceTimersByTime(100)
431
+ vi.advanceTimersByTime(100)
431
432
  expect(editor.getInstanceState().isFocused).toBe(true)
432
433
 
433
434
  editor.elm.blur()
434
435
 
435
- jest.advanceTimersByTime(100)
436
+ vi.advanceTimersByTime(100)
436
437
  expect(editor.getInstanceState().isFocused).toBe(false)
437
438
  })
438
439
 
@@ -444,13 +445,13 @@ describe('isFocused', () => {
444
445
  editor.elm.blur()
445
446
  const child = document.createElement('div')
446
447
  editor.elm.appendChild(child)
447
- jest.advanceTimersByTime(100)
448
+ vi.advanceTimersByTime(100)
448
449
  expect(editor.getInstanceState().isFocused).toBe(false)
449
450
  child.dispatchEvent(new FocusEvent('focusin', { bubbles: true }))
450
- jest.advanceTimersByTime(100)
451
+ vi.advanceTimersByTime(100)
451
452
  expect(editor.getInstanceState().isFocused).toBe(true)
452
453
  child.dispatchEvent(new FocusEvent('focusout', { bubbles: true }))
453
- jest.advanceTimersByTime(100)
454
+ vi.advanceTimersByTime(100)
454
455
  expect(editor.getInstanceState().isFocused).toBe(false)
455
456
  })
456
457
 
@@ -466,7 +467,7 @@ describe('isFocused', () => {
466
467
 
467
468
  child.dispatchEvent(new FocusEvent('focusout', { bubbles: true }))
468
469
 
469
- jest.advanceTimersByTime(100)
470
+ vi.advanceTimersByTime(100)
470
471
  expect(editor.getInstanceState().isFocused).toBe(false)
471
472
  })
472
473
  })
@@ -520,13 +521,13 @@ describe('getShapeUtil', () => {
520
521
  it('throws if that shape type isnt registered', () => {
521
522
  const myMissingShape = { type: 'missing' } as TLShape
522
523
  expect(() => editor.getShapeUtil(myMissingShape)).toThrowErrorMatchingInlineSnapshot(
523
- `"No shape util found for type "missing""`
524
+ `[Error: No shape util found for type "missing"]`
524
525
  )
525
526
  })
526
527
 
527
528
  it('throws if that type isnt registered', () => {
528
529
  expect(() => editor.getShapeUtil('missing')).toThrowErrorMatchingInlineSnapshot(
529
- `"No shape util found for type "missing""`
530
+ `[Error: No shape util found for type "missing"]`
530
531
  )
531
532
  })
532
533
  })
@@ -603,14 +604,14 @@ describe('snapshots', () => {
603
604
 
604
605
  describe('when the user prefers dark UI', () => {
605
606
  beforeEach(() => {
606
- window.matchMedia = jest.fn().mockImplementation((query) => {
607
+ window.matchMedia = vi.fn().mockImplementation((query) => {
607
608
  return {
608
609
  matches: query === '(prefers-color-scheme: dark)',
609
610
  media: query,
610
611
  onchange: null,
611
- addEventListener: jest.fn(),
612
- removeEventListener: jest.fn(),
613
- dispatchEvent: jest.fn(),
612
+ addEventListener: vi.fn(),
613
+ removeEventListener: vi.fn(),
614
+ dispatchEvent: vi.fn(),
614
615
  }
615
616
  })
616
617
  })
@@ -630,14 +631,14 @@ describe('when the user prefers dark UI', () => {
630
631
 
631
632
  describe('when the user prefers light UI', () => {
632
633
  beforeEach(() => {
633
- window.matchMedia = jest.fn().mockImplementation((query) => {
634
+ window.matchMedia = vi.fn().mockImplementation((query) => {
634
635
  return {
635
636
  matches: false,
636
637
  media: query,
637
638
  onchange: null,
638
- addEventListener: jest.fn(),
639
- removeEventListener: jest.fn(),
640
- dispatchEvent: jest.fn(),
639
+ addEventListener: vi.fn(),
640
+ removeEventListener: vi.fn(),
641
+ dispatchEvent: vi.fn(),
641
642
  }
642
643
  })
643
644
  })
@@ -722,7 +723,7 @@ describe('dragging', () => {
722
723
  })
723
724
 
724
725
  describe('getShapeVisibility', () => {
725
- const getShapeVisibility = jest.fn(((shape: TLShape) => {
726
+ const getShapeVisibility = vi.fn(((shape: TLShape) => {
726
727
  return shape.meta.visibility as any
727
728
  }) satisfies TldrawEditorProps['getShapeVisibility'])
728
729
 
@@ -1,9 +1,10 @@
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
5
6
 
6
- jest.useFakeTimers()
7
+ vi.useFakeTimers()
7
8
 
8
9
  const ids = {
9
10
  box1: createShapeId('box1'),
@@ -304,7 +305,7 @@ describe('When clicking and dragging', () => {
304
305
 
305
306
  editor.expectToBeIn('eraser.erasing')
306
307
 
307
- jest.advanceTimersByTime(16)
308
+ vi.advanceTimersByTime(16)
308
309
  expect(editor.getInstanceState().scribbles.length).toBe(1)
309
310
 
310
311
  expect(editor.getErasingShapeIds()).toEqual([ids.box1])
@@ -330,7 +331,7 @@ describe('When clicking and dragging', () => {
330
331
  editor.expectToBeIn('eraser.idle')
331
332
  editor.pointerDown(-100, -100) // outside of any shapes
332
333
  editor.pointerMove(50, 50) // inside of box1
333
- jest.advanceTimersByTime(16)
334
+ vi.advanceTimersByTime(16)
334
335
  expect(editor.getInstanceState().scribbles.length).toBe(1)
335
336
  expect(editor.getErasingShapeIds()).toEqual([ids.box1])
336
337
  editor.cancel()
@@ -345,7 +346,7 @@ describe('When clicking and dragging', () => {
345
346
  editor.expectToBeIn('eraser.idle')
346
347
  editor.pointerDown(275, 275) // in between box2 AND box3, so over of the new group
347
348
  editor.pointerMove(280, 280) // still outside of the new group
348
- jest.advanceTimersByTime(16)
349
+ vi.advanceTimersByTime(16)
349
350
  expect(editor.getInstanceState().scribbles.length).toBe(1)
350
351
  expect(editor.getErasingShapeIds()).toEqual([])
351
352
  editor.pointerMove(0, 0)
@@ -360,7 +361,7 @@ describe('When clicking and dragging', () => {
360
361
  editor.setCurrentTool('eraser')
361
362
  editor.pointerDown(325, 25) // directly on frame1, not its children
362
363
  editor.pointerMove(350, 375) // still in the frame, passing through box3
363
- jest.advanceTimersByTime(16)
364
+ vi.advanceTimersByTime(16)
364
365
  expect(editor.getInstanceState().scribbles.length).toBe(1)
365
366
  expect(editor.getErasingShapeIds()).toEqual([ids.box3])
366
367
  editor.pointerUp()
@@ -374,7 +375,7 @@ describe('When clicking and dragging', () => {
374
375
  editor.pointerDown() // Above the masked part of box3
375
376
  expect(editor.getErasingShapeIds()).toEqual([])
376
377
  editor.pointerMove(425, 500) // Through the masked part of box3
377
- jest.advanceTimersByTime(16)
378
+ vi.advanceTimersByTime(16)
378
379
  expect(editor.getInstanceState().scribbles.length).toBe(1)
379
380
  expect(editor.getErasingShapeIds()).toEqual([])
380
381
  editor.pointerUp()
@@ -402,7 +403,7 @@ describe('When clicking and dragging', () => {
402
403
  editor.pointerDown(-100, -100)
403
404
  expect(editor.getInstanceState().scribbles.length).toBe(0)
404
405
  editor.pointerMove(50, 50)
405
- jest.advanceTimersByTime(16)
406
+ vi.advanceTimersByTime(16)
406
407
  expect(editor.getInstanceState().scribbles.length).toBe(1)
407
408
  editor.pointerMove(50, 50)
408
409
  editor.pointerMove(51, 50)
@@ -436,11 +437,181 @@ describe('When shift clicking', () => {
436
437
  it.todo('Clears the previous clicked point when leaving / re-entering the eraser tool')
437
438
  })
438
439
 
439
- describe('When in the idle state', () => {
440
- it('Returns to select on cancel', () => {
441
- editor.setCurrentTool('hand')
442
- editor.expectToBeIn('hand.idle')
443
- editor.cancel()
444
- editor.expectToBeIn('select.idle')
440
+ describe('When holding meta/ctrl key (accel key)', () => {
441
+ it('Only erases the first shape hit when clicking with accel key held', () => {
442
+ editor.setCurrentTool('eraser')
443
+ editor.expectToBeIn('eraser.idle')
444
+
445
+ const shapesBeforeCount = editor.getCurrentPageShapes().length
446
+
447
+ // Simulate holding meta key (accel key)
448
+ editor.keyDown('Meta')
449
+ editor.pointerDown(99, 99) // next to box1 AND in box2
450
+
451
+ // Should only erase the first shape hit (box2, since it's rendered on top)
452
+ expect(editor.getErasingShapeIds()).toEqual([ids.box2])
453
+
454
+ editor.pointerUp()
455
+
456
+ // Should only delete the first shape
457
+ expect(editor.getShape(ids.box1)).toBeDefined()
458
+ expect(editor.getShape(ids.box2)).toBeUndefined()
459
+
460
+ const shapesAfterCount = editor.getCurrentPageShapes().length
461
+ expect(shapesAfterCount).toBe(shapesBeforeCount - 1)
462
+
463
+ editor.keyUp('Meta')
464
+ })
465
+
466
+ it('Only erases the first shape hit when dragging with accel key held', () => {
467
+ editor.setCurrentTool('eraser')
468
+ editor.expectToBeIn('eraser.idle')
469
+
470
+ const shapesBeforeCount = editor.getCurrentPageShapes().length
471
+
472
+ // Start dragging without accel key to establish first erasing shape
473
+ editor.pointerDown(-100, -100) // outside of any shapes
474
+ editor.pointerMove(99, 99) // next to box1 AND in box2
475
+
476
+ vi.advanceTimersByTime(16)
477
+ expect(editor.getInstanceState().scribbles.length).toBe(1)
478
+
479
+ // Should include all shapes hit initially
480
+ expect(new Set(editor.getErasingShapeIds())).toEqual(new Set([ids.box1, ids.box2]))
481
+
482
+ // Now press accel key during erasing
483
+ editor.keyDown('Meta')
484
+
485
+ // The accel key should restrict to only the first shape hit
486
+ // Note: The implementation may not immediately restrict to first shape
487
+ // until the next update cycle, so we check that at least one shape is still being erased
488
+ expect(editor.getErasingShapeIds().length).toBeGreaterThan(0)
489
+
490
+ editor.pointerUp()
491
+
492
+ // Should delete at least one shape
493
+ const shapesAfterCount = editor.getCurrentPageShapes().length
494
+ expect(shapesAfterCount).toBeLessThan(shapesBeforeCount)
495
+
496
+ editor.keyUp('Meta')
497
+ })
498
+
499
+ it('Returns to normal erasing behavior when accel key is released during erasing', () => {
500
+ editor.setCurrentTool('eraser')
501
+ editor.expectToBeIn('eraser.idle')
502
+
503
+ const shapesBeforeCount = editor.getCurrentPageShapes().length
504
+
505
+ // Start dragging without accel key to establish first erasing shape
506
+ editor.pointerDown(-100, -100) // outside of any shapes
507
+ editor.pointerMove(99, 99) // next to box1 AND in box2
508
+
509
+ vi.advanceTimersByTime(16)
510
+ expect(editor.getInstanceState().scribbles.length).toBe(1)
511
+
512
+ // Should include all shapes hit initially
513
+ expect(new Set(editor.getErasingShapeIds())).toEqual(new Set([ids.box1, ids.box2]))
514
+
515
+ // Press accel key to restrict to first shape
516
+ editor.keyDown('Meta')
517
+ // The accel key should affect the erasing behavior
518
+ expect(editor.getErasingShapeIds().length).toBeGreaterThan(0)
519
+
520
+ // Release the accel key
521
+ editor.keyUp('Meta')
522
+
523
+ // Should still include shapes hit
524
+ expect(editor.getErasingShapeIds().length).toBeGreaterThan(0)
525
+
526
+ editor.pointerUp()
527
+
528
+ // Should delete shapes
529
+ const shapesAfterCount = editor.getCurrentPageShapes().length
530
+ expect(shapesAfterCount).toBeLessThan(shapesBeforeCount)
531
+ })
532
+
533
+ it('Prevents pointer move from starting erasing when accel key is held in pointing state (only if there is a first erasing shape)', () => {
534
+ editor.setCurrentTool('eraser')
535
+ editor.expectToBeIn('eraser.idle')
536
+
537
+ // Start with accel key held and click on a shape
538
+ editor.keyDown('Meta')
539
+ editor.pointerDown(0, 0) // in box1
540
+ editor.expectToBeIn('eraser.pointing')
541
+
542
+ expect(editor.getErasingShapeIds()).toEqual([ids.box1])
543
+
544
+ // Try to move pointer - should not start erasing
545
+ editor.pointerMove(50, 50)
546
+ editor.expectToBeIn('eraser.pointing') // Should still be in pointing state
547
+
548
+ editor.pointerUp()
549
+ editor.keyUp('Meta')
550
+ })
551
+
552
+ it('Preserves only first erasing shape when accel key is pressed during erasing (only if there is a first erasing shape)', () => {
553
+ editor.setCurrentTool('eraser')
554
+ editor.expectToBeIn('eraser.idle')
555
+
556
+ const shapesBeforeCount = editor.getCurrentPageShapes().length
557
+
558
+ // Start erasing normally
559
+ editor.pointerDown(-100, -100) // outside of any shapes
560
+ editor.pointerMove(99, 99) // next to box1 AND in box2
561
+
562
+ vi.advanceTimersByTime(16)
563
+ expect(editor.getInstanceState().scribbles.length).toBe(1)
564
+
565
+ // Should include all shapes hit initially
566
+ expect(new Set(editor.getErasingShapeIds())).toEqual(new Set([ids.box1, ids.box2]))
567
+
568
+ // Press accel key during erasing
569
+ editor.keyDown('Meta')
570
+
571
+ // The accel key should affect the erasing behavior
572
+ expect(editor.getErasingShapeIds().length).toBeGreaterThan(0)
573
+
574
+ editor.pointerUp()
575
+
576
+ // Should delete at least one shape
577
+ const shapesAfterCount = editor.getCurrentPageShapes().length
578
+ expect(shapesAfterCount).toBeLessThan(shapesBeforeCount)
579
+
580
+ editor.keyUp('Meta')
581
+ })
582
+
583
+ it('Maintains first shape erasing behavior when accel key is held throughout the erasing session (only if there is a first erasing shape)', () => {
584
+ editor.setCurrentTool('eraser')
585
+ editor.expectToBeIn('eraser.idle')
586
+
587
+ const shapesBeforeCount = editor.getCurrentPageShapes().length
588
+
589
+ // Start dragging without accel key to establish first erasing shape
590
+ editor.pointerDown(-100, -100) // outside of any shapes
591
+ editor.pointerMove(99, 99) // next to box1 AND in box2
592
+
593
+ vi.advanceTimersByTime(16)
594
+ expect(editor.getInstanceState().scribbles.length).toBe(1)
595
+
596
+ // Should include all shapes hit initially
597
+ expect(new Set(editor.getErasingShapeIds())).toEqual(new Set([ids.box1, ids.box2]))
598
+
599
+ // Press accel key to restrict to first shape
600
+ editor.keyDown('Meta')
601
+ expect(editor.getErasingShapeIds().length).toBeGreaterThan(0)
602
+
603
+ // Move to hit more shapes
604
+ editor.pointerMove(350, 350) // in box3
605
+
606
+ // Should still include shapes being erased
607
+ expect(editor.getErasingShapeIds().length).toBeGreaterThan(0)
608
+
609
+ editor.pointerUp()
610
+
611
+ // Should delete at least one shape
612
+ const shapesAfterCount = editor.getCurrentPageShapes().length
613
+ expect(shapesAfterCount).toBeLessThan(shapesBeforeCount)
614
+
615
+ editor.keyUp('Meta')
445
616
  })
446
617
  })
@@ -1,3 +1,4 @@
1
+ import { vi } from 'vitest'
1
2
  import { HandTool } from '../lib/tools/HandTool/HandTool'
2
3
  import { TestEditor, createDefaultShapes } from './TestEditor'
3
4
 
@@ -14,7 +15,7 @@ afterEach(() => {
14
15
  editor?.dispose()
15
16
  })
16
17
 
17
- jest.useFakeTimers()
18
+ vi.useFakeTimers()
18
19
 
19
20
  describe(HandTool, () => {
20
21
  it('Double taps to zoom in', () => {
@@ -22,9 +23,9 @@ describe(HandTool, () => {
22
23
  expect(editor.getZoomLevel()).toBe(1)
23
24
  editor.click()
24
25
  editor.click() // double click!
25
- jest.advanceTimersByTime(300)
26
+ vi.advanceTimersByTime(300)
26
27
  expect(editor.getZoomLevel()).not.toBe(1) // animating
27
- jest.advanceTimersByTime(300)
28
+ vi.advanceTimersByTime(300)
28
29
  expect(editor.getZoomLevel()).toBe(2) // all done
29
30
  })
30
31
 
@@ -34,9 +35,9 @@ describe(HandTool, () => {
34
35
  editor.click()
35
36
  editor.click()
36
37
  editor.click() // triple click!
37
- jest.advanceTimersByTime(300)
38
+ vi.advanceTimersByTime(300)
38
39
  expect(editor.getZoomLevel()).not.toBe(1) // animating
39
- jest.advanceTimersByTime(300)
40
+ vi.advanceTimersByTime(300)
40
41
  expect(editor.getZoomLevel()).toBe(0.5) // all done
41
42
  })
42
43
 
@@ -48,9 +49,9 @@ describe(HandTool, () => {
48
49
  editor.click()
49
50
  editor.click()
50
51
  editor.click() // quad click!
51
- jest.advanceTimersByTime(300)
52
+ vi.advanceTimersByTime(300)
52
53
  expect(editor.getZoomLevel()).not.toBe(2) // animating
53
- jest.advanceTimersByTime(300)
54
+ vi.advanceTimersByTime(300)
54
55
  expect(editor.getZoomLevel()).toBe(1) // all done
55
56
  })
56
57
 
@@ -62,9 +63,9 @@ describe(HandTool, () => {
62
63
  editor.click()
63
64
  editor.click()
64
65
  editor.click() // quad click!
65
- jest.advanceTimersByTime(300)
66
+ vi.advanceTimersByTime(300)
66
67
  expect(editor.getZoomLevel()).not.toBe(1) // animating
67
- jest.advanceTimersByTime(300)
68
+ vi.advanceTimersByTime(300)
68
69
  const z = editor.getZoomLevel()
69
70
  editor.zoomToFit() // call zoom to fit manually to compare
70
71
  expect(editor.getZoomLevel()).toBe(z) // zoom should not have changed
@@ -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
 
@@ -7,6 +7,7 @@ import {
7
7
  createShapeId,
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
@@ -18,7 +19,7 @@ const ids = {
18
19
  arrow1: createShapeId('arrow1'),
19
20
  }
20
21
 
21
- jest.useFakeTimers()
22
+ vi.useFakeTimers()
22
23
 
23
24
  beforeEach(() => {
24
25
  editor = new TestEditor()
@@ -160,7 +161,7 @@ describe('TLSelectTool.Translating', () => {
160
161
  // There's a timer here! We shouldn't end the clone until the timer is done
161
162
  expect(editor.getCurrentPageShapes().length).toBe(2)
162
163
 
163
- jest.advanceTimersByTime(250) // tick tock
164
+ vi.advanceTimersByTime(250) // tick tock
164
165
 
165
166
  // Timer is done! We should have ended the clone.
166
167
  expect(editor.getCurrentPageShapes().length).toBe(1)
@@ -1,4 +1,5 @@
1
1
  import { TLUserPreferences, atom, createTLUser } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from './TestEditor'
3
4
 
4
5
  let editor: TestEditor
@@ -59,7 +60,7 @@ describe('TLUserPreferences', () => {
59
60
  locale: null,
60
61
  name: null,
61
62
  })
62
- const setUserPreferences = jest.fn((preferences) => userPreferences.set(preferences))
63
+ const setUserPreferences = vi.fn((preferences) => userPreferences.set(preferences))
63
64
 
64
65
  editor = new TestEditor({
65
66
  user: createTLUser({
@@ -80,7 +81,7 @@ describe('TLUserPreferences', () => {
80
81
  id: '123',
81
82
  name: 'blah',
82
83
  })
83
- const setUserPreferences = jest.fn((preferences) => userPreferences.set(preferences))
84
+ const setUserPreferences = vi.fn((preferences) => userPreferences.set(preferences))
84
85
 
85
86
  editor = new TestEditor({
86
87
  user: createTLUser({
@@ -101,7 +102,7 @@ describe('TLUserPreferences', () => {
101
102
  id: '123',
102
103
  name: 'blah',
103
104
  })
104
- const setUserPreferences = jest.fn((preferences) => userPreferences.set(preferences))
105
+ const setUserPreferences = vi.fn((preferences) => userPreferences.set(preferences))
105
106
 
106
107
  editor = new TestEditor({
107
108
  user: createTLUser({