@tldraw/editor 3.14.0-canary.f6a0206007b3 → 3.14.0-canary.f907ed7d9ee5

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 (148) hide show
  1. package/dist-cjs/index.d.ts +17 -26
  2. package/dist-cjs/index.js +8 -10
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/config/TLSessionStateSnapshot.js +1 -12
  5. package/dist-cjs/lib/config/TLSessionStateSnapshot.js.map +3 -3
  6. package/dist-cjs/lib/editor/Editor.js +50 -76
  7. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  8. package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +2 -2
  9. package/dist-cjs/lib/editor/derivations/bindingsIndex.js +22 -22
  10. package/dist-cjs/lib/editor/derivations/bindingsIndex.js.map +2 -2
  11. package/dist-cjs/lib/editor/derivations/parentsToChildren.js +16 -16
  12. package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
  13. package/dist-cjs/lib/editor/managers/{ClickManager.js → ClickManager/ClickManager.js} +1 -1
  14. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +7 -0
  15. package/dist-cjs/lib/editor/managers/{EdgeScrollManager.js → EdgeScrollManager/EdgeScrollManager.js} +2 -2
  16. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +7 -0
  17. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +7 -0
  18. package/dist-cjs/lib/editor/managers/{FontManager.js → FontManager/FontManager.js} +4 -1
  19. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +7 -0
  20. package/dist-cjs/lib/editor/managers/{HistoryManager.js → HistoryManager/HistoryManager.js} +64 -6
  21. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +7 -0
  22. package/dist-cjs/lib/editor/managers/{ScribbleManager.js → ScribbleManager/ScribbleManager.js} +1 -1
  23. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +7 -0
  24. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +7 -0
  25. package/dist-cjs/lib/editor/managers/{TickManager.js → TickManager/TickManager.js} +1 -1
  26. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +7 -0
  27. package/dist-cjs/lib/editor/managers/{UserPreferencesManager.js → UserPreferencesManager/UserPreferencesManager.js} +1 -1
  28. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +7 -0
  29. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +1 -1
  30. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +1 -1
  31. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +1 -1
  32. package/dist-cjs/lib/exports/getSvgJsx.js.map +1 -1
  33. package/dist-cjs/lib/primitives/Box.js +33 -39
  34. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  35. package/dist-cjs/lib/utils/areShapesContentEqual.js +1 -1
  36. package/dist-cjs/lib/utils/areShapesContentEqual.js.map +2 -2
  37. package/dist-cjs/lib/utils/reorderShapes.js +11 -10
  38. package/dist-cjs/lib/utils/reorderShapes.js.map +2 -2
  39. package/dist-cjs/lib/utils/richText.js +7 -2
  40. package/dist-cjs/lib/utils/richText.js.map +2 -2
  41. package/dist-cjs/version.js +3 -3
  42. package/dist-cjs/version.js.map +1 -1
  43. package/dist-esm/index.d.mts +17 -26
  44. package/dist-esm/index.mjs +12 -10
  45. package/dist-esm/index.mjs.map +2 -2
  46. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs +1 -1
  47. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
  48. package/dist-esm/lib/editor/Editor.mjs +50 -76
  49. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  50. package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +2 -2
  51. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs +22 -22
  52. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs.map +2 -2
  53. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +16 -16
  54. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
  55. package/dist-esm/lib/editor/managers/{ClickManager.mjs → ClickManager/ClickManager.mjs} +1 -1
  56. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +7 -0
  57. package/dist-esm/lib/editor/managers/{EdgeScrollManager.mjs → EdgeScrollManager/EdgeScrollManager.mjs} +2 -2
  58. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +7 -0
  59. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +7 -0
  60. package/dist-esm/lib/editor/managers/{FontManager.mjs → FontManager/FontManager.mjs} +4 -1
  61. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +7 -0
  62. package/dist-esm/lib/editor/managers/{HistoryManager.mjs → HistoryManager/HistoryManager.mjs} +60 -2
  63. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +7 -0
  64. package/dist-esm/lib/editor/managers/{ScribbleManager.mjs → ScribbleManager/ScribbleManager.mjs} +1 -1
  65. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +7 -0
  66. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +7 -0
  67. package/dist-esm/lib/editor/managers/{TickManager.mjs → TickManager/TickManager.mjs} +1 -1
  68. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +7 -0
  69. package/dist-esm/lib/editor/managers/{UserPreferencesManager.mjs → UserPreferencesManager/UserPreferencesManager.mjs} +1 -1
  70. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +7 -0
  71. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +1 -1
  72. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +1 -1
  73. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +1 -1
  74. package/dist-esm/lib/exports/getSvgJsx.mjs.map +1 -1
  75. package/dist-esm/lib/primitives/Box.mjs +33 -39
  76. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  77. package/dist-esm/lib/utils/areShapesContentEqual.mjs +1 -1
  78. package/dist-esm/lib/utils/areShapesContentEqual.mjs.map +2 -2
  79. package/dist-esm/lib/utils/reorderShapes.mjs +11 -10
  80. package/dist-esm/lib/utils/reorderShapes.mjs.map +2 -2
  81. package/dist-esm/lib/utils/richText.mjs +8 -3
  82. package/dist-esm/lib/utils/richText.mjs.map +2 -2
  83. package/dist-esm/version.mjs +3 -3
  84. package/dist-esm/version.mjs.map +1 -1
  85. package/package.json +8 -9
  86. package/src/index.ts +13 -8
  87. package/src/lib/config/TLSessionStateSnapshot.ts +1 -1
  88. package/src/lib/editor/Editor.test.ts +252 -3
  89. package/src/lib/editor/Editor.ts +48 -75
  90. package/src/lib/editor/bindings/BindingUtil.ts +6 -0
  91. package/src/lib/editor/derivations/bindingsIndex.ts +27 -26
  92. package/src/lib/editor/derivations/parentsToChildren.ts +28 -25
  93. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +442 -0
  94. package/src/lib/editor/managers/{ClickManager.ts → ClickManager/ClickManager.ts} +3 -3
  95. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +374 -0
  96. package/src/lib/editor/managers/{EdgeScrollManager.ts → EdgeScrollManager/EdgeScrollManager.ts} +3 -3
  97. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +455 -0
  98. package/src/lib/editor/managers/{FocusManager.ts → FocusManager/FocusManager.ts} +1 -1
  99. package/src/lib/editor/managers/FontManager/FontManager.test.ts +263 -0
  100. package/src/lib/editor/managers/{FontManager.ts → FontManager/FontManager.ts} +5 -2
  101. package/src/lib/editor/managers/{HistoryManager.test.ts → HistoryManager/HistoryManager.test.ts} +388 -1
  102. package/src/lib/editor/managers/{HistoryManager.ts → HistoryManager/HistoryManager.ts} +73 -2
  103. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +624 -0
  104. package/src/lib/editor/managers/{ScribbleManager.ts → ScribbleManager/ScribbleManager.ts} +2 -2
  105. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +485 -0
  106. package/src/lib/editor/managers/TextManager/TextManager.test.ts +411 -0
  107. package/src/lib/editor/managers/{TextManager.ts → TextManager/TextManager.ts} +1 -1
  108. package/src/lib/editor/managers/TickManager/TickManager.test.ts +314 -0
  109. package/src/lib/editor/managers/{TickManager.ts → TickManager/TickManager.ts} +2 -2
  110. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +591 -0
  111. package/src/lib/editor/managers/{UserPreferencesManager.ts → UserPreferencesManager/UserPreferencesManager.ts} +2 -2
  112. package/src/lib/editor/shapes/ShapeUtil.ts +1 -1
  113. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +1 -1
  114. package/src/lib/exports/getSvgJsx.tsx +1 -1
  115. package/src/lib/primitives/Box.test.ts +588 -7
  116. package/src/lib/primitives/Box.ts +33 -41
  117. package/src/lib/utils/areShapesContentEqual.ts +1 -2
  118. package/src/lib/utils/reorderShapes.ts +10 -13
  119. package/src/lib/utils/richText.ts +10 -4
  120. package/src/version.ts +3 -3
  121. package/dist-cjs/lib/editor/managers/ClickManager.js.map +0 -7
  122. package/dist-cjs/lib/editor/managers/EdgeScrollManager.js.map +0 -7
  123. package/dist-cjs/lib/editor/managers/FocusManager.js.map +0 -7
  124. package/dist-cjs/lib/editor/managers/FontManager.js.map +0 -7
  125. package/dist-cjs/lib/editor/managers/HistoryManager.js.map +0 -7
  126. package/dist-cjs/lib/editor/managers/ScribbleManager.js.map +0 -7
  127. package/dist-cjs/lib/editor/managers/Stack.js +0 -82
  128. package/dist-cjs/lib/editor/managers/Stack.js.map +0 -7
  129. package/dist-cjs/lib/editor/managers/TextManager.js.map +0 -7
  130. package/dist-cjs/lib/editor/managers/TickManager.js.map +0 -7
  131. package/dist-cjs/lib/editor/managers/UserPreferencesManager.js.map +0 -7
  132. package/dist-esm/lib/editor/managers/ClickManager.mjs.map +0 -7
  133. package/dist-esm/lib/editor/managers/EdgeScrollManager.mjs.map +0 -7
  134. package/dist-esm/lib/editor/managers/FocusManager.mjs.map +0 -7
  135. package/dist-esm/lib/editor/managers/FontManager.mjs.map +0 -7
  136. package/dist-esm/lib/editor/managers/HistoryManager.mjs.map +0 -7
  137. package/dist-esm/lib/editor/managers/ScribbleManager.mjs.map +0 -7
  138. package/dist-esm/lib/editor/managers/Stack.mjs +0 -62
  139. package/dist-esm/lib/editor/managers/Stack.mjs.map +0 -7
  140. package/dist-esm/lib/editor/managers/TextManager.mjs.map +0 -7
  141. package/dist-esm/lib/editor/managers/TickManager.mjs.map +0 -7
  142. package/dist-esm/lib/editor/managers/UserPreferencesManager.mjs.map +0 -7
  143. package/src/lib/editor/managers/ScribbleManager.test.ts +0 -32
  144. package/src/lib/editor/managers/Stack.ts +0 -71
  145. /package/dist-cjs/lib/editor/managers/{FocusManager.js → FocusManager/FocusManager.js} +0 -0
  146. /package/dist-cjs/lib/editor/managers/{TextManager.js → TextManager/TextManager.js} +0 -0
  147. /package/dist-esm/lib/editor/managers/{FocusManager.mjs → FocusManager/FocusManager.mjs} +0 -0
  148. /package/dist-esm/lib/editor/managers/{TextManager.mjs → TextManager/TextManager.mjs} +0 -0
@@ -0,0 +1,314 @@
1
+ import { Vec } from '../../../primitives/Vec'
2
+ import { Editor } from '../../Editor'
3
+ import { TickManager } from './TickManager'
4
+
5
+ // Mock the Editor class
6
+ jest.mock('../../Editor')
7
+
8
+ // Mock Date.now to control time
9
+ const mockDateNow = jest.fn()
10
+ Date.now = mockDateNow
11
+
12
+ // Mock requestAnimationFrame and cancelAnimationFrame
13
+ const mockRequestAnimationFrame = jest.fn()
14
+ const mockCancelAnimationFrame = jest.fn()
15
+ global.requestAnimationFrame = mockRequestAnimationFrame
16
+ global.cancelAnimationFrame = mockCancelAnimationFrame
17
+
18
+ describe('TickManager', () => {
19
+ let editor: jest.Mocked<Editor>
20
+ let tickManager: TickManager
21
+ let mockEmit: jest.Mock
22
+ let mockDisposablesAdd: jest.Mock
23
+
24
+ beforeEach(() => {
25
+ jest.clearAllMocks()
26
+
27
+ // Reset time
28
+ mockDateNow.mockReturnValue(1000)
29
+
30
+ // Mock RAF to execute callback immediately in tests
31
+ mockRequestAnimationFrame.mockImplementation((callback) => {
32
+ const id = Math.random()
33
+ // Execute immediately for tests
34
+ setTimeout(callback, 0)
35
+ return id
36
+ })
37
+
38
+ mockCancelAnimationFrame.mockImplementation(() => {})
39
+
40
+ mockEmit = jest.fn()
41
+ mockDisposablesAdd = jest.fn()
42
+
43
+ editor = {
44
+ emit: mockEmit,
45
+ disposables: {
46
+ add: mockDisposablesAdd,
47
+ },
48
+ inputs: {
49
+ currentScreenPoint: new Vec(100, 100),
50
+ pointerVelocity: new Vec(0, 0),
51
+ },
52
+ } as any
53
+
54
+ tickManager = new TickManager(editor)
55
+ })
56
+
57
+ afterEach(() => {
58
+ if (tickManager) {
59
+ tickManager.dispose()
60
+ }
61
+ })
62
+
63
+ describe('constructor and initialization', () => {
64
+ it('should initialize with correct default values', () => {
65
+ expect(tickManager.editor).toBe(editor)
66
+ expect(tickManager.isPaused).toBe(false)
67
+ expect(tickManager.now).toBe(1000)
68
+ })
69
+
70
+ it('should add dispose method to editor disposables', () => {
71
+ expect(mockDisposablesAdd).toHaveBeenCalledWith(tickManager.dispose)
72
+ })
73
+
74
+ it('should start the tick loop on construction', () => {
75
+ expect(mockRequestAnimationFrame).toHaveBeenCalled()
76
+ })
77
+ })
78
+
79
+ describe('start method', () => {
80
+ it('should set isPaused to false', () => {
81
+ tickManager.isPaused = true
82
+ tickManager.start()
83
+ expect(tickManager.isPaused).toBe(false)
84
+ })
85
+
86
+ it('should update the now timestamp', () => {
87
+ mockDateNow.mockReturnValue(2000)
88
+ tickManager.start()
89
+ expect(tickManager.now).toBe(2000)
90
+ })
91
+
92
+ it('should cancel existing RAF before starting new one', () => {
93
+ const mockCancel = jest.fn()
94
+ tickManager.cancelRaf = mockCancel
95
+
96
+ tickManager.start()
97
+
98
+ expect(mockCancel).toHaveBeenCalled()
99
+ })
100
+
101
+ it('should schedule new RAF', () => {
102
+ mockRequestAnimationFrame.mockClear()
103
+ tickManager.start()
104
+ expect(mockRequestAnimationFrame).toHaveBeenCalled()
105
+ })
106
+ })
107
+
108
+ describe('tick method', () => {
109
+ beforeEach(() => {
110
+ // Reset mocks
111
+ mockEmit.mockClear()
112
+ mockRequestAnimationFrame.mockClear()
113
+ })
114
+
115
+ it('should return early if paused', () => {
116
+ tickManager.isPaused = true
117
+ tickManager.tick()
118
+
119
+ expect(mockEmit).not.toHaveBeenCalled()
120
+ expect(mockRequestAnimationFrame).not.toHaveBeenCalled()
121
+ })
122
+
123
+ it('should calculate elapsed time correctly', () => {
124
+ tickManager.now = 1000
125
+ mockDateNow.mockReturnValue(1050)
126
+
127
+ tickManager.tick()
128
+
129
+ expect(tickManager.now).toBe(1050)
130
+ expect(mockEmit).toHaveBeenCalledWith('frame', 50)
131
+ expect(mockEmit).toHaveBeenCalledWith('tick', 50)
132
+ })
133
+
134
+ it('should emit frame and tick events with elapsed time', () => {
135
+ tickManager.now = 1000
136
+ mockDateNow.mockReturnValue(1100)
137
+
138
+ tickManager.tick()
139
+
140
+ expect(mockEmit).toHaveBeenCalledWith('frame', 100)
141
+ expect(mockEmit).toHaveBeenCalledWith('tick', 100)
142
+ expect(mockEmit).toHaveBeenCalledTimes(2)
143
+ })
144
+
145
+ it('should update pointer velocity', () => {
146
+ const updatePointerVelocitySpy = jest.spyOn(tickManager as any, 'updatePointerVelocity')
147
+ tickManager.now = 1000
148
+ mockDateNow.mockReturnValue(1016)
149
+
150
+ tickManager.tick()
151
+
152
+ expect(updatePointerVelocitySpy).toHaveBeenCalledWith(16)
153
+ })
154
+
155
+ it('should schedule next RAF', () => {
156
+ tickManager.tick()
157
+ expect(mockRequestAnimationFrame).toHaveBeenCalled()
158
+ })
159
+
160
+ it('should handle zero elapsed time', () => {
161
+ tickManager.now = 1000
162
+ mockDateNow.mockReturnValue(1000)
163
+
164
+ tickManager.tick()
165
+
166
+ expect(mockEmit).toHaveBeenCalledWith('frame', 0)
167
+ expect(mockEmit).toHaveBeenCalledWith('tick', 0)
168
+ })
169
+ })
170
+
171
+ describe('dispose method', () => {
172
+ it('should set isPaused to true', () => {
173
+ tickManager.isPaused = false
174
+ tickManager.dispose()
175
+ expect(tickManager.isPaused).toBe(true)
176
+ })
177
+
178
+ it('should cancel RAF if exists', () => {
179
+ const mockCancel = jest.fn()
180
+ tickManager.cancelRaf = mockCancel
181
+
182
+ tickManager.dispose()
183
+
184
+ expect(mockCancel).toHaveBeenCalled()
185
+ })
186
+
187
+ it('should handle dispose when cancelRaf is null', () => {
188
+ tickManager.cancelRaf = null
189
+
190
+ expect(() => tickManager.dispose()).not.toThrow()
191
+ })
192
+ })
193
+
194
+ describe('updatePointerVelocity method', () => {
195
+ let updatePointerVelocity: any
196
+
197
+ beforeEach(() => {
198
+ // Access private method for testing
199
+ updatePointerVelocity = (tickManager as any).updatePointerVelocity.bind(tickManager)
200
+ // Reset the prevPoint to a known state
201
+ ;(tickManager as any).prevPoint = new Vec(50, 50)
202
+ })
203
+
204
+ it('should return early if elapsed time is 0', () => {
205
+ const originalVelocity = editor.inputs.pointerVelocity.clone()
206
+
207
+ updatePointerVelocity(0)
208
+
209
+ expect(editor.inputs.pointerVelocity).toEqual(originalVelocity)
210
+ })
211
+
212
+ it('should calculate velocity based on pointer movement', () => {
213
+ editor.inputs.currentScreenPoint = new Vec(150, 150)
214
+ ;(tickManager as any).prevPoint = new Vec(50, 50)
215
+ editor.inputs.pointerVelocity = new Vec(0, 0)
216
+
217
+ updatePointerVelocity(100) // 100ms elapsed
218
+
219
+ // Delta should be (100, 100), length = ~141.42, direction = (~0.707, ~0.707)
220
+ // Velocity should be length/elapsed = ~1.414 per ms in each direction
221
+ // But with linear interpolation (lrp factor 0.5), it will be halved
222
+ const expectedVelocity = new Vec(0.5, 0.5) // With lrp factor 0.5
223
+ expect(editor.inputs.pointerVelocity.x).toBeCloseTo(expectedVelocity.x, 1)
224
+ expect(editor.inputs.pointerVelocity.y).toBeCloseTo(expectedVelocity.y, 1)
225
+ })
226
+
227
+ it('should update prevPoint to current screen point', () => {
228
+ const newPoint = new Vec(200, 200)
229
+ editor.inputs.currentScreenPoint = newPoint
230
+
231
+ updatePointerVelocity(16)
232
+
233
+ expect((tickManager as any).prevPoint).toEqual(newPoint)
234
+ })
235
+
236
+ it('should use linear interpolation to smooth velocity', () => {
237
+ editor.inputs.currentScreenPoint = new Vec(150, 50)
238
+ ;(tickManager as any).prevPoint = new Vec(50, 50)
239
+ editor.inputs.pointerVelocity = new Vec(2, 2)
240
+
241
+ updatePointerVelocity(100)
242
+
243
+ // Should interpolate between current velocity (2,2) and new velocity (1,0)
244
+ // lrp with factor 0.5 should give us something between them
245
+ expect(editor.inputs.pointerVelocity.x).toBeGreaterThan(0.5)
246
+ expect(editor.inputs.pointerVelocity.x).toBeLessThan(2)
247
+ })
248
+
249
+ it('should set very small velocity components to 0', () => {
250
+ editor.inputs.currentScreenPoint = new Vec(50.005, 50.005)
251
+ ;(tickManager as any).prevPoint = new Vec(50, 50)
252
+ editor.inputs.pointerVelocity = new Vec(0, 0)
253
+
254
+ updatePointerVelocity(1000) // Long elapsed time = very small velocity
255
+
256
+ expect(editor.inputs.pointerVelocity.x).toBe(0)
257
+ expect(editor.inputs.pointerVelocity.y).toBe(0)
258
+ })
259
+
260
+ it('should handle zero movement (stationary pointer)', () => {
261
+ editor.inputs.currentScreenPoint = new Vec(100, 100)
262
+ ;(tickManager as any).prevPoint = new Vec(100, 100)
263
+ editor.inputs.pointerVelocity = new Vec(1, 1)
264
+
265
+ updatePointerVelocity(16)
266
+
267
+ // Should interpolate towards zero velocity
268
+ expect(editor.inputs.pointerVelocity.x).toBeLessThan(1)
269
+ expect(editor.inputs.pointerVelocity.y).toBeLessThan(1)
270
+ })
271
+
272
+ it('should only update pointerVelocity if it actually changes', () => {
273
+ // Setup scenario where velocity won't change
274
+ editor.inputs.currentScreenPoint = new Vec(100, 100)
275
+ ;(tickManager as any).prevPoint = new Vec(100, 100)
276
+ editor.inputs.pointerVelocity = new Vec(0, 0)
277
+
278
+ const originalVelocity = editor.inputs.pointerVelocity
279
+ updatePointerVelocity(16)
280
+
281
+ // Should still be the same object reference since no change occurred
282
+ expect(editor.inputs.pointerVelocity).toBe(originalVelocity)
283
+ })
284
+ })
285
+
286
+ describe('RAF throttling behavior', () => {
287
+ it('should use test-specific RAF behavior in test environment', () => {
288
+ // The TickManager should detect test environment and use requestAnimationFrame directly
289
+ // This is already handled by the mock, but we can verify the behavior
290
+ expect(mockRequestAnimationFrame).toHaveBeenCalled()
291
+ })
292
+ })
293
+
294
+ describe('integration with tick loop', () => {
295
+ it('should schedule RAF on start', () => {
296
+ mockRequestAnimationFrame.mockClear()
297
+ tickManager.start()
298
+ expect(mockRequestAnimationFrame).toHaveBeenCalled()
299
+ })
300
+
301
+ it('should schedule RAF after each tick', () => {
302
+ mockRequestAnimationFrame.mockClear()
303
+ tickManager.tick()
304
+ expect(mockRequestAnimationFrame).toHaveBeenCalled()
305
+ })
306
+
307
+ it('should not schedule RAF when paused', () => {
308
+ tickManager.isPaused = true
309
+ mockRequestAnimationFrame.mockClear()
310
+ tickManager.tick()
311
+ expect(mockRequestAnimationFrame).not.toHaveBeenCalled()
312
+ })
313
+ })
314
+ })
@@ -1,6 +1,6 @@
1
1
  import { throttleToNextFrame as _throttleToNextFrame, bind } from '@tldraw/utils'
2
- import { Vec } from '../../primitives/Vec'
3
- import { Editor } from '../Editor'
2
+ import { Vec } from '../../../primitives/Vec'
3
+ import { Editor } from '../../Editor'
4
4
 
5
5
  const throttleToNextFrame =
6
6
  typeof process !== 'undefined' && process.env.NODE_ENV === 'test'