@tldraw/editor 3.16.0-next.eafb52d15064 → 3.16.0-next.fe14f1b4181f

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 (123) hide show
  1. package/dist-cjs/index.d.ts +30 -0
  2. package/dist-cjs/index.js +1 -1
  3. package/dist-cjs/lib/TldrawEditor.js +6 -2
  4. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  5. package/dist-cjs/lib/components/MenuClickCapture.js +0 -5
  6. package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
  7. package/dist-cjs/lib/components/Shape.js +7 -10
  8. package/dist-cjs/lib/components/Shape.js.map +2 -2
  9. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +4 -23
  10. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  11. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +1 -1
  12. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +1 -1
  13. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
  14. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
  15. package/dist-cjs/lib/components/default-components/DefaultScribble.js +1 -1
  16. package/dist-cjs/lib/components/default-components/DefaultScribble.js.map +2 -2
  17. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +9 -1
  18. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
  19. package/dist-cjs/lib/config/TLUserPreferences.js +1 -1
  20. package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
  21. package/dist-cjs/lib/editor/Editor.js +44 -15
  22. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  23. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +1 -1
  24. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  25. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +13 -0
  26. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  27. package/dist-cjs/lib/exports/getSvgJsx.js +35 -16
  28. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  29. package/dist-cjs/lib/hooks/useCanvasEvents.js +31 -25
  30. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  31. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +4 -1
  32. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
  33. package/dist-cjs/lib/license/Watermark.js +6 -6
  34. package/dist-cjs/lib/license/Watermark.js.map +1 -1
  35. package/dist-cjs/lib/options.js +6 -0
  36. package/dist-cjs/lib/options.js.map +2 -2
  37. package/dist-cjs/lib/primitives/Box.js +3 -0
  38. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  39. package/dist-cjs/version.js +3 -3
  40. package/dist-cjs/version.js.map +1 -1
  41. package/dist-esm/index.d.mts +30 -0
  42. package/dist-esm/index.mjs +1 -1
  43. package/dist-esm/lib/TldrawEditor.mjs +6 -2
  44. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  45. package/dist-esm/lib/components/MenuClickCapture.mjs +0 -5
  46. package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
  47. package/dist-esm/lib/components/Shape.mjs +7 -10
  48. package/dist-esm/lib/components/Shape.mjs.map +2 -2
  49. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +4 -23
  50. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  51. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +1 -1
  52. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +1 -1
  53. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
  54. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
  55. package/dist-esm/lib/components/default-components/DefaultScribble.mjs +1 -1
  56. package/dist-esm/lib/components/default-components/DefaultScribble.mjs.map +2 -2
  57. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +9 -1
  58. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  59. package/dist-esm/lib/config/TLUserPreferences.mjs +1 -1
  60. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  61. package/dist-esm/lib/editor/Editor.mjs +44 -15
  62. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  63. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +1 -1
  64. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  65. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +13 -0
  66. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  67. package/dist-esm/lib/exports/getSvgJsx.mjs +36 -16
  68. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  69. package/dist-esm/lib/hooks/useCanvasEvents.mjs +32 -26
  70. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  71. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +4 -1
  72. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
  73. package/dist-esm/lib/license/Watermark.mjs +6 -6
  74. package/dist-esm/lib/license/Watermark.mjs.map +1 -1
  75. package/dist-esm/lib/options.mjs +6 -0
  76. package/dist-esm/lib/options.mjs.map +2 -2
  77. package/dist-esm/lib/primitives/Box.mjs +4 -1
  78. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  79. package/dist-esm/version.mjs +3 -3
  80. package/dist-esm/version.mjs.map +1 -1
  81. package/editor.css +301 -290
  82. package/package.json +14 -37
  83. package/src/lib/TldrawEditor.tsx +11 -6
  84. package/src/lib/components/MenuClickCapture.tsx +0 -8
  85. package/src/lib/components/Shape.tsx +6 -12
  86. package/src/lib/components/default-components/DefaultCanvas.tsx +5 -22
  87. package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +1 -1
  88. package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
  89. package/src/lib/components/default-components/DefaultScribble.tsx +1 -1
  90. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +5 -1
  91. package/src/lib/config/TLUserPreferences.ts +1 -1
  92. package/src/lib/editor/Editor.test.ts +12 -11
  93. package/src/lib/editor/Editor.ts +55 -20
  94. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +15 -14
  95. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +16 -15
  96. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +49 -48
  97. package/src/lib/editor/managers/FontManager/FontManager.test.ts +24 -23
  98. package/src/lib/editor/managers/HistoryManager/HistoryManager.test.ts +7 -6
  99. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +12 -11
  100. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +57 -50
  101. package/src/lib/editor/managers/TextManager/TextManager.test.ts +51 -26
  102. package/src/lib/editor/managers/TickManager/TickManager.test.ts +14 -13
  103. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +21 -26
  104. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +1 -1
  105. package/src/lib/editor/shapes/ShapeUtil.ts +14 -0
  106. package/src/lib/exports/getSvgJsx.test.ts +868 -0
  107. package/src/lib/exports/getSvgJsx.tsx +78 -21
  108. package/src/lib/hooks/useCanvasEvents.ts +45 -38
  109. package/src/lib/hooks/usePassThroughWheelEvents.ts +6 -1
  110. package/src/lib/license/LicenseManager.test.ts +3 -1
  111. package/src/lib/license/Watermark.test.tsx +2 -1
  112. package/src/lib/license/Watermark.tsx +6 -6
  113. package/src/lib/options.ts +6 -0
  114. package/src/lib/primitives/Box.test.ts +126 -0
  115. package/src/lib/primitives/Box.ts +10 -1
  116. package/src/lib/utils/sync/LocalIndexedDb.test.ts +2 -1
  117. package/src/lib/utils/sync/TLLocalSyncClient.test.ts +15 -15
  118. package/src/version.ts +3 -3
  119. package/dist-cjs/lib/utils/nearestMultiple.js +0 -34
  120. package/dist-cjs/lib/utils/nearestMultiple.js.map +0 -7
  121. package/dist-esm/lib/utils/nearestMultiple.mjs +0 -14
  122. package/dist-esm/lib/utils/nearestMultiple.mjs.map +0 -7
  123. package/src/lib/utils/nearestMultiple.ts +0 -13
@@ -1,19 +1,20 @@
1
+ import { Mock, Mocked, vi } from 'vitest'
1
2
  import { Box } from '../../../primitives/Box'
2
3
  import { Vec } from '../../../primitives/Vec'
3
4
  import { Editor } from '../../Editor'
4
5
  import { EdgeScrollManager } from './EdgeScrollManager'
5
6
 
6
7
  // Mock the Editor class
7
- jest.mock('../../Editor')
8
+ vi.mock('../../Editor')
8
9
 
9
10
  describe('EdgeScrollManager', () => {
10
- let editor: jest.Mocked<
11
+ let editor: Mocked<
11
12
  Editor & {
12
- user: { getEdgeScrollSpeed: jest.Mock }
13
- getCamera: jest.Mock
14
- getCameraOptions: jest.Mock
15
- getZoomLevel: jest.Mock
16
- getViewportScreenBounds: jest.Mock
13
+ user: { getEdgeScrollSpeed: Mock }
14
+ getCamera: Mock
15
+ getCameraOptions: Mock
16
+ getZoomLevel: Mock
17
+ getViewportScreenBounds: Mock
17
18
  }
18
19
  >
19
20
  let edgeScrollManager: EdgeScrollManager
@@ -33,33 +34,33 @@ describe('EdgeScrollManager', () => {
33
34
  isPanning: false,
34
35
  },
35
36
  user: {
36
- getEdgeScrollSpeed: jest.fn(() => 1),
37
+ getEdgeScrollSpeed: vi.fn(() => 1),
37
38
  },
38
- getViewportScreenBounds: jest.fn(() => new Box(0, 0, 1000, 600)),
39
- getInstanceState: jest.fn(
39
+ getViewportScreenBounds: vi.fn(() => new Box(0, 0, 1000, 600)),
40
+ getInstanceState: vi.fn(
40
41
  () =>
41
42
  ({
42
43
  isCoarsePointer: false,
43
44
  insets: [false, false, false, false], // [top, right, bottom, left]
44
45
  }) as any
45
46
  ),
46
- getCameraOptions: jest.fn(() => ({
47
+ getCameraOptions: vi.fn(() => ({
47
48
  isLocked: false,
48
49
  panSpeed: 1,
49
50
  zoomSpeed: 1,
50
51
  zoomSteps: [1],
51
52
  wheelBehavior: 'pan' as const,
52
53
  })),
53
- getZoomLevel: jest.fn(() => 1),
54
- getCamera: jest.fn(() => new Vec(0, 0, 1)),
55
- setCamera: jest.fn(),
54
+ getZoomLevel: vi.fn(() => 1),
55
+ getCamera: vi.fn(() => new Vec(0, 0, 1)),
56
+ setCamera: vi.fn(),
56
57
  } as any
57
58
 
58
59
  edgeScrollManager = new EdgeScrollManager(editor as any)
59
60
  })
60
61
 
61
62
  afterEach(() => {
62
- jest.clearAllMocks()
63
+ vi.clearAllMocks()
63
64
  })
64
65
 
65
66
  describe('constructor and initialization', () => {
@@ -1,58 +1,59 @@
1
+ import { Mock, Mocked, vi } from 'vitest'
1
2
  import { Editor } from '../../Editor'
2
3
  import { FocusManager } from './FocusManager'
3
4
 
4
5
  // Mock the Editor class
5
- jest.mock('../../Editor')
6
+ vi.mock('../../Editor')
6
7
 
7
8
  describe('FocusManager', () => {
8
- let editor: jest.Mocked<
9
+ let editor: Mocked<
9
10
  Editor & {
10
11
  sideEffects: {
11
- registerAfterChangeHandler: jest.Mock
12
+ registerAfterChangeHandler: Mock
12
13
  }
13
- getInstanceState: jest.Mock
14
- updateInstanceState: jest.Mock
15
- getContainer: jest.Mock
16
- isIn: jest.Mock
17
- getSelectedShapeIds: jest.Mock
18
- complete: jest.Mock
14
+ getInstanceState: Mock
15
+ updateInstanceState: Mock
16
+ getContainer: Mock
17
+ isIn: Mock
18
+ getSelectedShapeIds: Mock
19
+ complete: Mock
19
20
  }
20
21
  >
21
22
  let focusManager: FocusManager
22
23
  let mockContainer: HTMLElement
23
- let mockDispose: jest.Mock
24
+ let mockDispose: Mock
24
25
  let originalAddEventListener: typeof document.body.addEventListener
25
26
  let originalRemoveEventListener: typeof document.body.removeEventListener
26
27
 
27
28
  beforeEach(() => {
28
29
  // Create mock container element
29
30
  mockContainer = document.createElement('div')
30
- mockContainer.focus = jest.fn()
31
- mockContainer.blur = jest.fn()
32
- jest.spyOn(mockContainer.classList, 'add')
33
- jest.spyOn(mockContainer.classList, 'remove')
31
+ mockContainer.focus = vi.fn()
32
+ mockContainer.blur = vi.fn()
33
+ vi.spyOn(mockContainer.classList, 'add')
34
+ vi.spyOn(mockContainer.classList, 'remove')
34
35
 
35
36
  // Create mock dispose function
36
- mockDispose = jest.fn()
37
+ mockDispose = vi.fn()
37
38
 
38
39
  // Mock editor
39
40
  editor = {
40
41
  sideEffects: {
41
- registerAfterChangeHandler: jest.fn(() => mockDispose),
42
+ registerAfterChangeHandler: vi.fn(() => mockDispose),
42
43
  },
43
- getInstanceState: jest.fn(() => ({ isFocused: false })),
44
- updateInstanceState: jest.fn(),
45
- getContainer: jest.fn(() => mockContainer),
46
- isIn: jest.fn(() => false),
47
- getSelectedShapeIds: jest.fn(() => []),
48
- complete: jest.fn(),
44
+ getInstanceState: vi.fn(() => ({ isFocused: false })),
45
+ updateInstanceState: vi.fn(),
46
+ getContainer: vi.fn(() => mockContainer),
47
+ isIn: vi.fn(() => false),
48
+ getSelectedShapeIds: vi.fn(() => []),
49
+ complete: vi.fn(),
49
50
  } as any
50
51
 
51
52
  // Mock document.body event listeners
52
53
  originalAddEventListener = document.body.addEventListener
53
54
  originalRemoveEventListener = document.body.removeEventListener
54
- document.body.addEventListener = jest.fn()
55
- document.body.removeEventListener = jest.fn()
55
+ document.body.addEventListener = vi.fn()
56
+ document.body.removeEventListener = vi.fn()
56
57
  })
57
58
 
58
59
  afterEach(() => {
@@ -65,7 +66,7 @@ describe('FocusManager', () => {
65
66
  focusManager.dispose()
66
67
  }
67
68
 
68
- jest.clearAllMocks()
69
+ vi.clearAllMocks()
69
70
  })
70
71
 
71
72
  describe('constructor', () => {
@@ -131,7 +132,7 @@ describe('FocusManager', () => {
131
132
  const handler = handlerCall[1]
132
133
 
133
134
  // Clear previous calls
134
- jest.clearAllMocks()
135
+ vi.clearAllMocks()
135
136
 
136
137
  // Simulate focus state change
137
138
  const prev = { isFocused: false }
@@ -149,7 +150,7 @@ describe('FocusManager', () => {
149
150
  const handlerCall = editor.sideEffects.registerAfterChangeHandler.mock.calls[0]
150
151
  const handler = handlerCall[1]
151
152
 
152
- jest.clearAllMocks()
153
+ vi.clearAllMocks()
153
154
 
154
155
  // Simulate no focus state change
155
156
  const prev = { isFocused: true }
@@ -170,7 +171,7 @@ describe('FocusManager', () => {
170
171
  // Get the handler before clearing mocks
171
172
  const handlerCall = editor.sideEffects.registerAfterChangeHandler.mock.calls[0]
172
173
  handler = handlerCall[1]
173
- jest.clearAllMocks()
174
+ vi.clearAllMocks()
174
175
  })
175
176
 
176
177
  it('should add focused class when editor is focused', () => {
@@ -205,11 +206,11 @@ describe('FocusManager', () => {
205
206
  focusManager = new FocusManager(editor)
206
207
 
207
208
  // Get the keydown handler that was registered
208
- const addEventListenerCalls = (document.body.addEventListener as jest.Mock).mock.calls
209
- const keydownCall = addEventListenerCalls.find((call) => call[0] === 'keydown')
210
- keydownHandler = keydownCall[1]
209
+ const addEventListenerCalls = (document.body.addEventListener as Mock).mock.calls
210
+ const keydownCall = addEventListenerCalls.find((call: any) => call[0] === 'keydown')
211
+ keydownHandler = keydownCall![1]
211
212
 
212
- jest.clearAllMocks()
213
+ vi.clearAllMocks()
213
214
  })
214
215
 
215
216
  it('should remove no-focus-ring class on Tab key', () => {
@@ -283,11 +284,11 @@ describe('FocusManager', () => {
283
284
  focusManager = new FocusManager(editor)
284
285
 
285
286
  // Get the mousedown handler that was registered
286
- const addEventListenerCalls = (document.body.addEventListener as jest.Mock).mock.calls
287
- const mousedownCall = addEventListenerCalls.find((call) => call[0] === 'mousedown')
288
- mousedownHandler = mousedownCall[1]
287
+ const addEventListenerCalls = (document.body.addEventListener as Mock).mock.calls
288
+ const mousedownCall = addEventListenerCalls.find((call: any) => call[0] === 'mousedown')
289
+ mousedownHandler = mousedownCall![1]
289
290
 
290
- jest.clearAllMocks()
291
+ vi.clearAllMocks()
291
292
  })
292
293
 
293
294
  it('should add no-focus-ring class on mouse down', () => {
@@ -326,7 +327,7 @@ describe('FocusManager', () => {
326
327
  it('should complete before bluring', () => {
327
328
  const callOrder: string[] = []
328
329
  editor.complete.mockImplementation(() => callOrder.push('complete'))
329
- mockContainer.blur = jest.fn(() => callOrder.push('blur'))
330
+ mockContainer.blur = vi.fn(() => callOrder.push('blur'))
330
331
 
331
332
  focusManager.blur()
332
333
 
@@ -337,7 +338,7 @@ describe('FocusManager', () => {
337
338
  describe('dispose', () => {
338
339
  beforeEach(() => {
339
340
  focusManager = new FocusManager(editor)
340
- jest.clearAllMocks()
341
+ vi.clearAllMocks()
341
342
  })
342
343
 
343
344
  it('should remove keyboard event listener', () => {
@@ -376,7 +377,7 @@ describe('FocusManager', () => {
376
377
  const handlerCall = editor.sideEffects.registerAfterChangeHandler.mock.calls[0]
377
378
  const handler = handlerCall[1]
378
379
 
379
- jest.clearAllMocks()
380
+ vi.clearAllMocks()
380
381
 
381
382
  // Rapid focus changes
382
383
  editor.getInstanceState.mockReturnValue({ isFocused: true })
@@ -394,9 +395,9 @@ describe('FocusManager', () => {
394
395
 
395
396
  it('should handle keyboard navigation while editing', () => {
396
397
  focusManager = new FocusManager(editor)
397
- const addEventListenerCalls = (document.body.addEventListener as jest.Mock).mock.calls
398
- const keydownCall = addEventListenerCalls.find((call) => call[0] === 'keydown')
399
- const keydownHandler = keydownCall[1]
398
+ const addEventListenerCalls = (document.body.addEventListener as Mock).mock.calls
399
+ const keydownCall = addEventListenerCalls.find((call: any) => call[0] === 'keydown')
400
+ const keydownHandler = keydownCall![1]
400
401
 
401
402
  editor.isIn.mockReturnValue(true) // Editing mode
402
403
 
@@ -409,15 +410,15 @@ describe('FocusManager', () => {
409
410
 
410
411
  it('should handle mouse and keyboard interaction sequence', () => {
411
412
  focusManager = new FocusManager(editor)
412
- const addEventListenerCalls = (document.body.addEventListener as jest.Mock).mock.calls
413
+ const addEventListenerCalls = (document.body.addEventListener as Mock).mock.calls
413
414
 
414
- const mousedownCall = addEventListenerCalls.find((call) => call[0] === 'mousedown')
415
- const keydownCall = addEventListenerCalls.find((call) => call[0] === 'keydown')
415
+ const mousedownCall = addEventListenerCalls.find((call: any) => call[0] === 'mousedown')
416
+ const keydownCall = addEventListenerCalls.find((call: any) => call[0] === 'keydown')
416
417
 
417
- const mousedownHandler = mousedownCall[1]
418
- const keydownHandler = keydownCall[1]
418
+ const mousedownHandler = mousedownCall![1]
419
+ const keydownHandler = keydownCall![1]
419
420
 
420
- jest.clearAllMocks()
421
+ vi.clearAllMocks()
421
422
 
422
423
  // Mouse down adds no-focus-ring
423
424
  mousedownHandler()
@@ -1,30 +1,31 @@
1
1
  import { TLShape, TLShapeId, createShapeId } from '@tldraw/tlschema'
2
+ import { Mock, Mocked, vi } from 'vitest'
2
3
  import { Editor } from '../../Editor'
3
4
  import { FontManager, TLFontFace } from './FontManager'
4
5
 
5
6
  // Mock the Editor class
6
- jest.mock('../../Editor')
7
+ vi.mock('../../Editor')
7
8
 
8
9
  // Mock globals
9
- global.FontFace = jest.fn().mockImplementation((family, src, descriptors) => ({
10
+ global.FontFace = vi.fn().mockImplementation((family, src, descriptors) => ({
10
11
  family,
11
12
  src,
12
13
  ...descriptors,
13
- load: jest.fn(() => Promise.resolve()),
14
+ load: vi.fn(() => Promise.resolve()),
14
15
  }))
15
16
 
16
17
  Object.defineProperty(global.document, 'fonts', {
17
18
  value: {
18
- add: jest.fn(),
19
- [Symbol.iterator]: jest.fn(() => [].values()),
19
+ add: vi.fn(),
20
+ [Symbol.iterator]: vi.fn(() => [].values()),
20
21
  },
21
22
  configurable: true,
22
23
  })
23
24
 
24
- global.queueMicrotask = jest.fn((fn) => Promise.resolve().then(fn))
25
+ global.queueMicrotask = vi.fn((fn) => Promise.resolve().then(fn))
25
26
 
26
27
  describe('FontManager', () => {
27
- let editor: jest.Mocked<Editor>
28
+ let editor: Mocked<Editor>
28
29
  let fontManager: FontManager
29
30
  let mockAssetUrls: { [key: string]: string }
30
31
 
@@ -50,30 +51,30 @@ describe('FontManager', () => {
50
51
  })
51
52
 
52
53
  beforeEach(() => {
53
- jest.clearAllMocks()
54
+ vi.clearAllMocks()
54
55
 
55
56
  mockAssetUrls = {
56
57
  'test-font.woff2': 'https://example.com/fonts/test-font.woff2',
57
58
  }
58
59
 
59
60
  const mockShapeUtil = {
60
- getFontFaces: jest.fn(() => []),
61
+ getFontFaces: vi.fn(() => []),
61
62
  }
62
63
 
63
64
  const mockStore = {
64
- createComputedCache: jest.fn(() => ({
65
- get: jest.fn(() => []),
65
+ createComputedCache: vi.fn(() => ({
66
+ get: vi.fn(() => []),
66
67
  })),
67
- createCache: jest.fn(() => ({
68
- get: jest.fn(() => ({ get: jest.fn(() => []) })),
68
+ createCache: vi.fn(() => ({
69
+ get: vi.fn(() => ({ get: vi.fn(() => []) })),
69
70
  })),
70
71
  }
71
72
 
72
73
  editor = {
73
74
  store: mockStore,
74
- getShapeUtil: jest.fn(() => mockShapeUtil),
75
- getCurrentPageShapeIds: jest.fn(() => new Set()),
76
- getShape: jest.fn(),
75
+ getShapeUtil: vi.fn(() => mockShapeUtil),
76
+ getCurrentPageShapeIds: vi.fn(() => new Set()),
77
+ getShape: vi.fn(),
77
78
  isDisposed: false,
78
79
  } as any
79
80
 
@@ -127,7 +128,7 @@ describe('FontManager', () => {
127
128
  const shapes = shapeIds.map(createMockShape)
128
129
 
129
130
  editor.getCurrentPageShapeIds.mockReturnValue(new Set(shapeIds))
130
- editor.getShape.mockImplementation((id) => shapes.find((s) => s.id === id))
131
+ editor.getShape.mockImplementation((id: any) => shapes.find((s) => s.id === id))
131
132
 
132
133
  await expect(fontManager.loadRequiredFontsForCurrentPage(3)).resolves.toBeUndefined()
133
134
  })
@@ -150,12 +151,12 @@ describe('FontManager', () => {
150
151
  const font = createMockFont()
151
152
  const error = new Error('Font load failed')
152
153
 
153
- ;(global.FontFace as jest.Mock).mockReturnValue({
154
+ ;(global.FontFace as Mock).mockReturnValue({
154
155
  family: font.family,
155
- load: jest.fn(() => Promise.reject(error)),
156
+ load: vi.fn(() => Promise.reject(error)),
156
157
  })
157
158
 
158
- const consoleSpy = jest.spyOn(console, 'error').mockImplementation()
159
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
159
160
 
160
161
  await fontManager.ensureFontIsLoaded(font)
161
162
 
@@ -198,7 +199,7 @@ describe('FontManager', () => {
198
199
 
199
200
  fontManager.requestFonts(fonts)
200
201
 
201
- const callback = (queueMicrotask as jest.Mock).mock.calls[0][0]
202
+ const callback = (queueMicrotask as Mock).mock.calls[0][0]
202
203
  expect(() => callback()).not.toThrow()
203
204
  })
204
205
  })
@@ -213,7 +214,7 @@ describe('FontManager', () => {
213
214
  src: url("mock-data-url");
214
215
  }`
215
216
 
216
- jest.spyOn(fontManager, 'toEmbeddedCssDeclaration').mockResolvedValue(mockCssDeclaration)
217
+ vi.spyOn(fontManager, 'toEmbeddedCssDeclaration').mockResolvedValue(mockCssDeclaration)
217
218
 
218
219
  const result = await fontManager.toEmbeddedCssDeclaration(font)
219
220
 
@@ -227,7 +228,7 @@ describe('FontManager', () => {
227
228
  const font = createMockFont()
228
229
 
229
230
  // Simple spy to verify the method is called
230
- const spy = jest.spyOn(fontManager, 'toEmbeddedCssDeclaration').mockResolvedValue('mock-css')
231
+ const spy = vi.spyOn(fontManager, 'toEmbeddedCssDeclaration').mockResolvedValue('mock-css')
231
232
 
232
233
  await fontManager.toEmbeddedCssDeclaration(font)
233
234
 
@@ -1,4 +1,5 @@
1
1
  import { BaseRecord, RecordId, Store, StoreSchema, createRecordType } from '@tldraw/store'
2
+ import { vi } from 'vitest'
2
3
  import { TLHistoryBatchOptions } from '../../types/history-types'
3
4
  import { HistoryManager } from './HistoryManager'
4
5
 
@@ -489,7 +490,7 @@ describe('HistoryManager constructor and lifecycle', () => {
489
490
  })
490
491
 
491
492
  it('should initialize with optional annotateError callback', () => {
492
- const mockAnnotateError = jest.fn()
493
+ const mockAnnotateError = vi.fn()
493
494
  const manager = new HistoryManager({ store, annotateError: mockAnnotateError })
494
495
  expect(manager).toBeDefined()
495
496
  })
@@ -503,7 +504,7 @@ describe('HistoryManager constructor and lifecycle', () => {
503
504
  })
504
505
 
505
506
  it('should handle errors in batch operations with annotateError', () => {
506
- const mockAnnotateError = jest.fn()
507
+ const mockAnnotateError = vi.fn()
507
508
  const manager = new HistoryManager({ store, annotateError: mockAnnotateError })
508
509
 
509
510
  const errorFn = () => {
@@ -515,7 +516,7 @@ describe('HistoryManager constructor and lifecycle', () => {
515
516
  })
516
517
 
517
518
  it('should handle nested batch error scenarios', () => {
518
- const mockAnnotateError = jest.fn()
519
+ const mockAnnotateError = vi.fn()
519
520
  const manager = new HistoryManager({ store, annotateError: mockAnnotateError })
520
521
 
521
522
  const nestedErrorFn = () => {
@@ -695,7 +696,7 @@ describe('HistoryManager error scenarios and edge cases', () => {
695
696
  describe('squashToMark error handling', () => {
696
697
  it('should handle non-existent mark gracefully', () => {
697
698
  store.update(ids.a, (s) => ({ ...s, value: 1 }))
698
- const consoleSpy = jest.spyOn(console, 'error').mockImplementation()
699
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
699
700
 
700
701
  manager.squashToMark('non-existent-mark')
701
702
 
@@ -707,7 +708,7 @@ describe('HistoryManager error scenarios and edge cases', () => {
707
708
  })
708
709
 
709
710
  it('should handle empty stack when squashing', () => {
710
- const consoleSpy = jest.spyOn(console, 'error').mockImplementation()
711
+ const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
711
712
 
712
713
  manager.squashToMark('non-existent')
713
714
 
@@ -780,7 +781,7 @@ describe('HistoryManager error scenarios and edge cases', () => {
780
781
  })
781
782
 
782
783
  it('should maintain batch state correctly during errors', () => {
783
- const mockAnnotateError = jest.fn()
784
+ const mockAnnotateError = vi.fn()
784
785
  const errorManager = new HistoryManager({ store, annotateError: mockAnnotateError })
785
786
 
786
787
  try {
@@ -1,33 +1,34 @@
1
1
  import { TLScribble } from '@tldraw/tlschema'
2
+ import { Mock, Mocked, vi } from 'vitest'
2
3
  import { Editor } from '../../Editor'
3
4
  import { ScribbleItem, ScribbleManager } from './ScribbleManager'
4
5
 
5
6
  // Mock the Editor class
6
- jest.mock('../../Editor')
7
- jest.mock('@tldraw/utils', () => ({
8
- uniqueId: jest.fn(() => 'test-id'),
7
+ vi.mock('../../Editor')
8
+ vi.mock('@tldraw/utils', () => ({
9
+ uniqueId: vi.fn(() => 'test-id'),
9
10
  }))
10
11
 
11
12
  describe('ScribbleManager', () => {
12
- let editor: jest.Mocked<Editor>
13
+ let editor: Mocked<Editor>
13
14
  let scribbleManager: ScribbleManager
14
- let mockUniqueId: jest.Mock
15
+ let mockUniqueId: Mock
15
16
 
16
- beforeEach(() => {
17
+ beforeEach(async () => {
17
18
  editor = {
18
- updateInstanceState: jest.fn(),
19
- run: jest.fn((fn) => fn()),
19
+ updateInstanceState: vi.fn(),
20
+ run: vi.fn((fn) => fn()),
20
21
  } as any
21
22
 
22
- const { uniqueId } = jest.requireMock('@tldraw/utils')
23
- mockUniqueId = uniqueId
23
+ const { uniqueId } = await vi.importMock('@tldraw/utils')
24
+ mockUniqueId = uniqueId as Mock
24
25
  mockUniqueId.mockReturnValue('test-id')
25
26
 
26
27
  scribbleManager = new ScribbleManager(editor)
27
28
  })
28
29
 
29
30
  afterEach(() => {
30
- jest.clearAllMocks()
31
+ vi.clearAllMocks()
31
32
  })
32
33
 
33
34
  describe('constructor and initialization', () => {