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
@@ -1,11 +1,12 @@
1
1
  import { PI, TLShapeId } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from '../TestEditor'
3
4
  import { TL } from '../test-jsx'
4
5
 
5
6
  let editor: TestEditor
6
7
  let ids: Record<string, TLShapeId>
7
8
 
8
- jest.useFakeTimers()
9
+ vi.useFakeTimers()
9
10
 
10
11
  function createVideoShape() {
11
12
  return editor.createShapesFromJsx(<TL.video ref="video1" x={0} y={0} w={160} h={90} />).video1
@@ -26,10 +27,10 @@ beforeEach(() => {
26
27
  describe('when less than two shapes are selected', () => {
27
28
  it('does nothing', () => {
28
29
  editor.setSelectedShapes([ids.boxB])
29
- const fn = jest.fn()
30
+ const fn = vi.fn()
30
31
  editor.store.listen(fn)
31
32
  editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
32
- jest.advanceTimersByTime(1000)
33
+ vi.advanceTimersByTime(1000)
33
34
 
34
35
  expect(fn).not.toHaveBeenCalled()
35
36
  })
@@ -39,7 +40,7 @@ describe('when multiple shapes are selected', () => {
39
40
  it('stretches horizontally', () => {
40
41
  editor.selectAll()
41
42
  editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
42
- jest.advanceTimersByTime(1000)
43
+ vi.advanceTimersByTime(1000)
43
44
  editor.expectShapeToMatch(
44
45
  { id: ids.boxA, x: 0, y: 0, props: { w: 500 } },
45
46
  { id: ids.boxB, x: 0, y: 100, props: { w: 500 } },
@@ -52,7 +53,7 @@ describe('when multiple shapes are selected', () => {
52
53
  editor.selectAll()
53
54
  expect(editor.getSelectedShapes().length).toBe(4)
54
55
  editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
55
- jest.advanceTimersByTime(1000)
56
+ vi.advanceTimersByTime(1000)
56
57
  const newHeight = (500 * 9) / 16
57
58
  editor.expectShapeToMatch(
58
59
  { id: ids.boxA, x: 0, y: 0, props: { w: 500 } },
@@ -65,7 +66,7 @@ describe('when multiple shapes are selected', () => {
65
66
  it('stretches vertically', () => {
66
67
  editor.selectAll()
67
68
  editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
68
- jest.advanceTimersByTime(1000)
69
+ vi.advanceTimersByTime(1000)
69
70
  editor.expectShapeToMatch(
70
71
  { id: ids.boxA, x: 0, y: 0, props: { h: 500 } },
71
72
  { id: ids.boxB, x: 100, y: 0, props: { h: 500 } },
@@ -78,7 +79,7 @@ describe('when multiple shapes are selected', () => {
78
79
  editor.selectAll()
79
80
  expect(editor.getSelectedShapes().length).toBe(4)
80
81
  editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
81
- jest.advanceTimersByTime(1000)
82
+ vi.advanceTimersByTime(1000)
82
83
  const newWidth = (500 * 16) / 9
83
84
  editor.expectShapeToMatch(
84
85
  { id: ids.boxA, x: 0, y: 0, props: { h: 500 } },
@@ -91,7 +92,7 @@ describe('when multiple shapes are selected', () => {
91
92
  it('does, undoes and redoes command', () => {
92
93
  editor.markHistoryStoppingPoint('stretch')
93
94
  editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
94
- jest.advanceTimersByTime(1000)
95
+ vi.advanceTimersByTime(1000)
95
96
 
96
97
  editor.expectShapeToMatch({ id: ids.boxB, x: 0, props: { w: 500 } })
97
98
  editor.undo()
@@ -106,7 +107,7 @@ describe('When shapes are the child of another shape.', () => {
106
107
  editor.reparentShapes([ids.boxB], ids.boxA)
107
108
  editor.select(ids.boxB, ids.boxC)
108
109
  editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
109
- jest.advanceTimersByTime(1000)
110
+ vi.advanceTimersByTime(1000)
110
111
  editor.expectShapeToMatch(
111
112
  { id: ids.boxB, x: 100, y: 100, props: { w: 400 } },
112
113
  { id: ids.boxC, x: 100, y: 400, props: { w: 400 } }
@@ -117,7 +118,7 @@ describe('When shapes are the child of another shape.', () => {
117
118
  editor.reparentShapes([ids.boxB], ids.boxA)
118
119
  editor.select(ids.boxB, ids.boxC)
119
120
  editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
120
- jest.advanceTimersByTime(1000)
121
+ vi.advanceTimersByTime(1000)
121
122
  editor.expectShapeToMatch(
122
123
  { id: ids.boxB, x: 100, y: 100, props: { h: 400 } },
123
124
  { id: ids.boxC, x: 400, y: 100, props: { h: 400 } }
@@ -140,7 +141,7 @@ describe('When shapes are the child of a rotated shape.', () => {
140
141
 
141
142
  editor.select(ids.boxA, ids.boxC)
142
143
  editor.stretchShapes(editor.getSelectedShapeIds(), 'horizontal')
143
- jest.advanceTimersByTime(1000)
144
+ vi.advanceTimersByTime(1000)
144
145
  editor.expectShapeToMatch(
145
146
  {
146
147
  id: ids.boxA,
@@ -184,7 +185,7 @@ describe('When shapes are the child of a rotated shape.', () => {
184
185
  editor.selectAll()
185
186
 
186
187
  editor.stretchShapes(editor.getSelectedShapeIds(), 'vertical')
187
- jest.advanceTimersByTime(1000)
188
+ vi.advanceTimersByTime(1000)
188
189
  editor.expectShapeToMatch(
189
190
  {
190
191
  id: ids.boxA,
@@ -1,7 +1,8 @@
1
1
  import { PageRecordType, createShapeId } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from './TestEditor'
3
4
 
4
- jest.useFakeTimers()
5
+ vi.useFakeTimers()
5
6
 
6
7
  let editor: TestEditor
7
8
 
@@ -1,8 +1,9 @@
1
1
  import { createShapeId, TLImageShape } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { MIN_CROP_SIZE } from '../lib/shapes/shared/crop'
3
4
  import { TestEditor } from './TestEditor'
4
5
 
5
- jest.useFakeTimers()
6
+ vi.useFakeTimers()
6
7
 
7
8
  let editor: TestEditor
8
9
 
@@ -495,7 +496,7 @@ describe('When in the select.crop.translating_crop state', () => {
495
496
  })
496
497
 
497
498
  editor.keyUp('Shift')
498
- jest.advanceTimersByTime(500)
499
+ vi.advanceTimersByTime(500)
499
500
 
500
501
  const afterShiftUp = editor.getShape<TLImageShape>(ids.imageB)!.props.crop!
501
502
 
@@ -0,0 +1,436 @@
1
+ import {
2
+ atom,
3
+ BaseBoxShapeUtil,
4
+ Circle2d,
5
+ createShapeId,
6
+ Geometry2d,
7
+ RecordProps,
8
+ resizeBox,
9
+ StateNode,
10
+ T,
11
+ TLBaseShape,
12
+ TLEventHandlers,
13
+ TLGeoShape,
14
+ TLResizeInfo,
15
+ TLShape,
16
+ TLTextShape,
17
+ toRichText,
18
+ Vec,
19
+ } from '@tldraw/editor'
20
+ import { TestEditor } from './TestEditor'
21
+
22
+ // Custom Circle Clip Shape Definition
23
+ export type CircleClipShape = TLBaseShape<
24
+ 'circle-clip',
25
+ {
26
+ w: number
27
+ h: number
28
+ }
29
+ >
30
+
31
+ export const isClippingEnabled$ = atom('isClippingEnabled', true)
32
+
33
+ export class CircleClipShapeUtil extends BaseBoxShapeUtil<CircleClipShape> {
34
+ static override type = 'circle-clip' as const
35
+ static override props: RecordProps<CircleClipShape> = {
36
+ w: T.number,
37
+ h: T.number,
38
+ }
39
+
40
+ override canBind() {
41
+ return false
42
+ }
43
+
44
+ override canReceiveNewChildrenOfType(shape: TLShape) {
45
+ return !shape.isLocked
46
+ }
47
+
48
+ override getDefaultProps(): CircleClipShape['props'] {
49
+ return {
50
+ w: 200,
51
+ h: 200,
52
+ }
53
+ }
54
+
55
+ override getGeometry(shape: CircleClipShape): Geometry2d {
56
+ const radius = Math.min(shape.props.w, shape.props.h) / 2
57
+ return new Circle2d({
58
+ radius,
59
+ x: shape.props.w / 2 - radius,
60
+ y: shape.props.h / 2 - radius,
61
+ isFilled: true,
62
+ })
63
+ }
64
+
65
+ override getClipPath(shape: CircleClipShape): Vec[] | undefined {
66
+ // Generate a polygon approximation of the circle
67
+ const centerX = shape.props.w / 2
68
+ const centerY = shape.props.h / 2
69
+ const radius = Math.min(shape.props.w, shape.props.h) / 2
70
+ const segments = 48 // More segments = smoother circle
71
+
72
+ const points: Vec[] = []
73
+ for (let i = 0; i < segments; i++) {
74
+ const angle = (i / segments) * Math.PI * 2
75
+ const x = centerX + Math.cos(angle) * radius
76
+ const y = centerY + Math.sin(angle) * radius
77
+ points.push(new Vec(x, y))
78
+ }
79
+
80
+ return points
81
+ }
82
+
83
+ override shouldClipChild(_child: TLShape): boolean {
84
+ // For now, clip all children - we removed the onlyClipText feature for simplicity
85
+ return isClippingEnabled$.get()
86
+ }
87
+
88
+ override component(_shape: CircleClipShape) {
89
+ // For testing purposes, we'll just return null
90
+ // In a real implementation, this would return JSX
91
+ return null as any
92
+ }
93
+
94
+ override indicator(_shape: CircleClipShape) {
95
+ // For testing purposes, we'll just return null
96
+ // In a real implementation, this would return JSX
97
+ return null as any
98
+ }
99
+
100
+ override onResize(shape: CircleClipShape, info: TLResizeInfo<CircleClipShape>) {
101
+ return resizeBox(shape, info)
102
+ }
103
+ }
104
+
105
+ export class CircleClipShapeTool extends StateNode {
106
+ static override id = 'circle-clip'
107
+
108
+ override onEnter(): void {
109
+ this.editor.setCursor({ type: 'cross', rotation: 0 })
110
+ }
111
+
112
+ override onPointerDown(info: Parameters<TLEventHandlers['onPointerDown']>[0]) {
113
+ if (info.target === 'canvas') {
114
+ const { originPagePoint } = this.editor.inputs
115
+
116
+ this.editor.createShape<CircleClipShape>({
117
+ type: 'circle-clip',
118
+ x: originPagePoint.x - 100,
119
+ y: originPagePoint.y - 100,
120
+ props: {
121
+ w: 200,
122
+ h: 200,
123
+ },
124
+ })
125
+ }
126
+ }
127
+ }
128
+
129
+ let editor: TestEditor
130
+
131
+ afterEach(() => {
132
+ editor?.dispose()
133
+ })
134
+
135
+ const ids = {
136
+ circleClip1: createShapeId('circleClip1'),
137
+ circleClip2: createShapeId('circleClip2'),
138
+ text1: createShapeId('text1'),
139
+ geo1: createShapeId('geo1'),
140
+ geo2: createShapeId('geo2'),
141
+ }
142
+
143
+ beforeEach(() => {
144
+ editor = new TestEditor({
145
+ shapeUtils: [CircleClipShapeUtil],
146
+ tools: [CircleClipShapeTool],
147
+ })
148
+
149
+ // Reset clipping state
150
+ isClippingEnabled$.set(true)
151
+ })
152
+
153
+ describe('CircleClipShapeUtil', () => {
154
+ describe('shape creation and properties', () => {
155
+ it('should create a circle clip shape with default properties', () => {
156
+ editor.createShape<CircleClipShape>({
157
+ id: ids.circleClip1,
158
+ type: 'circle-clip',
159
+ x: 100,
160
+ y: 100,
161
+ props: {
162
+ w: 200,
163
+ h: 200,
164
+ },
165
+ })
166
+
167
+ const shape = editor.getShape<CircleClipShape>(ids.circleClip1)
168
+ expect(shape).toBeDefined()
169
+ expect(shape!.type).toBe('circle-clip')
170
+ expect(shape!.props.w).toBe(200)
171
+ expect(shape!.props.h).toBe(200)
172
+ })
173
+
174
+ it('should use default props when not specified', () => {
175
+ editor.createShape<CircleClipShape>({
176
+ id: ids.circleClip1,
177
+ type: 'circle-clip',
178
+ x: 100,
179
+ y: 100,
180
+ props: {},
181
+ })
182
+
183
+ const shape = editor.getShape<CircleClipShape>(ids.circleClip1)
184
+ expect(shape!.props.w).toBe(200) // default from getDefaultProps
185
+ expect(shape!.props.h).toBe(200) // default from getDefaultProps
186
+ })
187
+ })
188
+
189
+ describe('geometry and clipping', () => {
190
+ it('should generate correct circle geometry', () => {
191
+ editor.createShape<CircleClipShape>({
192
+ id: ids.circleClip1,
193
+ type: 'circle-clip',
194
+ x: 100,
195
+ y: 100,
196
+ props: {
197
+ w: 200,
198
+ h: 200,
199
+ },
200
+ })
201
+
202
+ const shape = editor.getShape<CircleClipShape>(ids.circleClip1)
203
+ const util = editor.getShapeUtil<CircleClipShape>('circle-clip')
204
+ const geometry = util.getGeometry(shape!)
205
+
206
+ expect(geometry).toBeDefined()
207
+ expect(geometry.bounds).toBeDefined()
208
+ expect(geometry.bounds.width).toBe(200)
209
+ expect(geometry.bounds.height).toBe(200)
210
+ })
211
+
212
+ it('should generate clip path for circle', () => {
213
+ editor.createShape<CircleClipShape>({
214
+ id: ids.circleClip1,
215
+ type: 'circle-clip',
216
+ x: 100,
217
+ y: 100,
218
+ props: {
219
+ w: 200,
220
+ h: 200,
221
+ },
222
+ })
223
+
224
+ const shape = editor.getShape<CircleClipShape>(ids.circleClip1)
225
+ const util = editor.getShapeUtil<CircleClipShape>('circle-clip')
226
+ const clipPath = util.getClipPath?.(shape!)
227
+ if (!clipPath) throw new Error('Clip path is undefined')
228
+
229
+ expect(clipPath).toBeDefined()
230
+ expect(Array.isArray(clipPath)).toBe(true)
231
+ expect(clipPath.length).toBeGreaterThan(0)
232
+
233
+ // Should be a polygon approximation of a circle
234
+ // Check that points are roughly in a circle pattern
235
+ const centerX = 100 // shape.x
236
+ const centerY = 100 // shape.y
237
+ const radius = 100 // min(w, h) / 2
238
+
239
+ clipPath.forEach((point) => {
240
+ const distance = Math.sqrt(Math.pow(point.x - centerX, 2) + Math.pow(point.y - centerY, 2))
241
+ expect(distance).toBeCloseTo(radius, 0)
242
+ })
243
+ })
244
+ })
245
+
246
+ describe('child clipping behavior', () => {
247
+ it('should clip children when clipping is enabled', () => {
248
+ editor.createShape<CircleClipShape>({
249
+ id: ids.circleClip1,
250
+ type: 'circle-clip',
251
+ x: 100,
252
+ y: 100,
253
+ props: {
254
+ w: 200,
255
+ h: 200,
256
+ },
257
+ })
258
+
259
+ editor.createShape<TLTextShape>({
260
+ id: ids.text1,
261
+ type: 'text',
262
+ x: 0,
263
+ y: 0,
264
+ parentId: ids.circleClip1,
265
+ props: {
266
+ richText: toRichText('Test text'),
267
+ },
268
+ })
269
+
270
+ const util = editor.getShapeUtil<CircleClipShape>('circle-clip')
271
+ const textShape = editor.getShape<TLTextShape>(ids.text1)
272
+
273
+ // Clipping should be enabled by default
274
+ expect(isClippingEnabled$.get()).toBe(true)
275
+ expect(util.shouldClipChild?.(textShape!)).toBe(true)
276
+ expect(editor.getShapeClipPath(ids.text1)).toBeDefined()
277
+ })
278
+
279
+ it('should not clip children when clipping is disabled', () => {
280
+ isClippingEnabled$.set(false)
281
+
282
+ editor.createShape<CircleClipShape>({
283
+ id: ids.circleClip1,
284
+ type: 'circle-clip',
285
+ x: 100,
286
+ y: 100,
287
+ props: {
288
+ w: 200,
289
+ h: 200,
290
+ },
291
+ })
292
+
293
+ editor.createShape<TLTextShape>({
294
+ id: ids.text1,
295
+ type: 'text',
296
+ x: 0,
297
+ y: 0,
298
+ parentId: ids.circleClip1,
299
+ props: {
300
+ richText: toRichText('Test text'),
301
+ },
302
+ })
303
+
304
+ const util = editor.getShapeUtil<CircleClipShape>('circle-clip')
305
+ const textShape = editor.getShape<TLTextShape>(ids.text1)
306
+
307
+ expect(isClippingEnabled$.get()).toBe(false)
308
+ expect(util.shouldClipChild?.(textShape!)).toBe(false)
309
+ expect(editor.getShapeClipPath(ids.text1)).toBeUndefined()
310
+ })
311
+ })
312
+ })
313
+
314
+ describe('Integration tests', () => {
315
+ it('should create and manage circle clip shapes with children', () => {
316
+ // Create circle clip shape
317
+ editor.createShape<CircleClipShape>({
318
+ id: ids.circleClip1,
319
+ type: 'circle-clip',
320
+ x: 100,
321
+ y: 100,
322
+ props: {
323
+ w: 200,
324
+ h: 200,
325
+ },
326
+ })
327
+
328
+ // Add text child
329
+ editor.createShape<TLTextShape>({
330
+ id: ids.text1,
331
+ type: 'text',
332
+ x: 50,
333
+ y: 50,
334
+ parentId: ids.circleClip1,
335
+ props: {
336
+ richText: toRichText('Clipped text'),
337
+ },
338
+ })
339
+
340
+ // Add geo child
341
+ editor.createShape<TLGeoShape>({
342
+ id: ids.geo1,
343
+ type: 'geo',
344
+ x: 150,
345
+ y: 150,
346
+ parentId: ids.circleClip1,
347
+ props: {
348
+ w: 50,
349
+ h: 50,
350
+ },
351
+ })
352
+
353
+ const circleClipShape = editor.getShape<CircleClipShape>(ids.circleClip1)
354
+ const textShape = editor.getShape<TLTextShape>(ids.text1)
355
+ const geoShape = editor.getShape<TLGeoShape>(ids.geo1)
356
+
357
+ expect(circleClipShape).toBeDefined()
358
+ expect(textShape!.parentId).toBe(ids.circleClip1)
359
+ expect(geoShape!.parentId).toBe(ids.circleClip1)
360
+
361
+ // Verify clipping behavior
362
+ const util = editor.getShapeUtil<CircleClipShape>('circle-clip')
363
+ expect(util.shouldClipChild?.(textShape!)).toBe(true)
364
+ expect(util.shouldClipChild?.(geoShape!)).toBe(true)
365
+ expect(editor.getShapeClipPath(ids.text1)).toBeDefined()
366
+ expect(editor.getShapeClipPath(ids.geo1)).toBeDefined()
367
+
368
+ // Test clipping toggle
369
+ isClippingEnabled$.set(false)
370
+ expect(util.shouldClipChild?.(textShape!)).toBe(false)
371
+ expect(util.shouldClipChild?.(geoShape!)).toBe(false)
372
+ expect(editor.getShapeClipPath(ids.text1)).toBeUndefined()
373
+ expect(editor.getShapeClipPath(ids.geo1)).toBeUndefined()
374
+ })
375
+
376
+ it('should handle multiple circle clip shapes independently', () => {
377
+ // Create two circle clip shapes
378
+ editor.createShape<CircleClipShape>({
379
+ id: ids.circleClip1,
380
+ type: 'circle-clip',
381
+ x: 100,
382
+ y: 100,
383
+ props: {
384
+ w: 200,
385
+ h: 200,
386
+ },
387
+ })
388
+
389
+ editor.createShape<CircleClipShape>({
390
+ id: ids.circleClip2,
391
+ type: 'circle-clip',
392
+ x: 400,
393
+ y: 100,
394
+ props: {
395
+ w: 150,
396
+ h: 150,
397
+ },
398
+ })
399
+
400
+ // Add children to both
401
+ editor.createShape<TLTextShape>({
402
+ id: ids.text1,
403
+ type: 'text',
404
+ x: 0,
405
+ y: 0,
406
+ parentId: ids.circleClip1,
407
+ props: {
408
+ richText: toRichText('First clip'),
409
+ },
410
+ })
411
+
412
+ editor.createShape<TLTextShape>({
413
+ id: ids.geo1,
414
+ type: 'text',
415
+ x: 0,
416
+ y: 0,
417
+ parentId: ids.circleClip2,
418
+ props: {
419
+ richText: toRichText('Second clip'),
420
+ },
421
+ })
422
+
423
+ const util = editor.getShapeUtil<CircleClipShape>('circle-clip')
424
+ const text1 = editor.getShape<TLTextShape>(ids.text1)
425
+ const text2 = editor.getShape<TLTextShape>(ids.geo1)
426
+
427
+ // Both should be clipped when enabled
428
+ expect(util.shouldClipChild?.(text1!)).toBe(true)
429
+ expect(util.shouldClipChild?.(text2!)).toBe(true)
430
+
431
+ // Both should not be clipped when disabled
432
+ isClippingEnabled$.set(false)
433
+ expect(util.shouldClipChild?.(text1!)).toBe(false)
434
+ expect(util.shouldClipChild?.(text2!)).toBe(false)
435
+ })
436
+ })
@@ -1,8 +1,9 @@
1
1
  import { TLDrawShape, TLHighlightShape, last } from '@tldraw/editor'
2
+ import { vi } from 'vitest'
2
3
  import { TestEditor } from './TestEditor'
3
4
  import { TEST_DRAW_SHAPE_SCREEN_POINTS } from './drawing.data'
4
5
 
5
- jest.useFakeTimers()
6
+ vi.useFakeTimers()
6
7
 
7
8
  let editor: TestEditor
8
9
 
@@ -10,12 +10,13 @@ import {
10
10
  createBindingId,
11
11
  createShapeId,
12
12
  } from '@tldraw/editor'
13
+ import { vi } from 'vitest'
13
14
  import { getArrowBindings } from '../lib/shapes/arrow/shared'
14
15
  import { TestEditor } from './TestEditor'
15
16
 
16
17
  let editor: TestEditor
17
18
 
18
- jest.useFakeTimers()
19
+ vi.useFakeTimers()
19
20
 
20
21
  const ids = {
21
22
  boxA: createShapeId('boxA'),
@@ -297,7 +298,7 @@ describe('When one shape is selected', () => {
297
298
  })
298
299
 
299
300
  it('Flips the direct child shape positions if the shape is a group', async () => {
300
- const fn = jest.fn()
301
+ const fn = vi.fn()
301
302
 
302
303
  editor.selectAll()
303
304
  editor.groupShapes(editor.getSelectedShapeIds()) // this will also select the new group
@@ -306,7 +307,7 @@ describe('When one shape is selected', () => {
306
307
  editor.flipShapes(editor.getSelectedShapeIds(), 'horizontal')
307
308
 
308
309
  // The change event should have been called
309
- jest.runOnlyPendingTimers()
310
+ vi.runOnlyPendingTimers()
310
311
  expect(fn).toHaveBeenCalled()
311
312
 
312
313
  editor.expectShapeToMatch(