@tldraw/editor 3.14.0-canary.e0ab6f4c80f9 → 3.14.0-canary.e2a8e4a03aff
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.
- package/dist-cjs/index.d.ts +133 -107
- package/dist-cjs/index.js +8 -8
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/config/TLSessionStateSnapshot.js +1 -12
- package/dist-cjs/lib/config/TLSessionStateSnapshot.js.map +3 -3
- package/dist-cjs/lib/editor/Editor.js +82 -78
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/bindingsIndex.js +22 -22
- package/dist-cjs/lib/editor/derivations/bindingsIndex.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +16 -20
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +3 -3
- package/dist-cjs/lib/editor/derivations/parentsToChildren.js +16 -16
- package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
- package/dist-cjs/lib/editor/managers/{ClickManager.js → ClickManager/ClickManager.js} +1 -1
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{EdgeScrollManager.js → EdgeScrollManager/EdgeScrollManager.js} +2 -2
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{FocusManager.js → FocusManager/FocusManager.js} +2 -0
- package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{FontManager.js → FontManager/FontManager.js} +4 -1
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{HistoryManager.js → HistoryManager/HistoryManager.js} +64 -6
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{ScribbleManager.js → ScribbleManager/ScribbleManager.js} +1 -1
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{TextManager.js → TextManager/TextManager.js} +73 -42
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{TickManager.js → TickManager/TickManager.js} +1 -1
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/{UserPreferencesManager.js → UserPreferencesManager/UserPreferencesManager.js} +1 -1
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +7 -0
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +8 -0
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +6 -0
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js.map +2 -2
- package/dist-cjs/lib/editor/tools/StateNode.js +3 -3
- package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
- package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
- package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
- package/dist-cjs/lib/exports/getSvgJsx.js.map +1 -1
- package/dist-cjs/lib/hooks/useCanvasEvents.js +1 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +33 -33
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/lib/primitives/Vec.js +18 -13
- package/dist-cjs/lib/primitives/Vec.js.map +3 -3
- package/dist-cjs/lib/primitives/geometry/Arc2d.js +41 -21
- package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Circle2d.js +11 -11
- package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +13 -16
- package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js +4 -4
- package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Edge2d.js +14 -21
- package/dist-cjs/lib/primitives/geometry/Edge2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +10 -10
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +5 -0
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Point2d.js +6 -6
- package/dist-cjs/lib/primitives/geometry/Point2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Polygon2d.js +3 -0
- package/dist-cjs/lib/primitives/geometry/Polygon2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Polyline2d.js +8 -5
- package/dist-cjs/lib/primitives/geometry/Polyline2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Rectangle2d.js +22 -11
- package/dist-cjs/lib/primitives/geometry/Rectangle2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Stadium2d.js +22 -22
- package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +2 -2
- package/dist-cjs/lib/utils/reorderShapes.js +11 -10
- package/dist-cjs/lib/utils/reorderShapes.js.map +2 -2
- package/dist-cjs/lib/utils/richText.js +7 -2
- package/dist-cjs/lib/utils/richText.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +133 -107
- package/dist-esm/index.mjs +15 -9
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/config/TLSessionStateSnapshot.mjs +1 -1
- package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +82 -78
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/bindingsIndex.mjs +22 -22
- package/dist-esm/lib/editor/derivations/bindingsIndex.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +16 -20
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +3 -3
- package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +16 -16
- package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/{ClickManager.mjs → ClickManager/ClickManager.mjs} +1 -1
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{EdgeScrollManager.mjs → EdgeScrollManager/EdgeScrollManager.mjs} +2 -2
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{FocusManager.mjs → FocusManager/FocusManager.mjs} +2 -0
- package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{FontManager.mjs → FontManager/FontManager.mjs} +4 -1
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{HistoryManager.mjs → HistoryManager/HistoryManager.mjs} +60 -2
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{ScribbleManager.mjs → ScribbleManager/ScribbleManager.mjs} +1 -1
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{TextManager.mjs → TextManager/TextManager.mjs} +73 -42
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{TickManager.mjs → TickManager/TickManager.mjs} +1 -1
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/{UserPreferencesManager.mjs → UserPreferencesManager/UserPreferencesManager.mjs} +1 -1
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +7 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +8 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +6 -0
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs +3 -3
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +1 -1
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +1 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +33 -33
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/lib/primitives/Vec.mjs +19 -14
- package/dist-esm/lib/primitives/Vec.mjs.map +3 -3
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs +41 -21
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs +11 -11
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +13 -16
- package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs +4 -4
- package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Edge2d.mjs +14 -21
- package/dist-esm/lib/primitives/geometry/Edge2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +11 -11
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +7 -1
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Point2d.mjs +6 -6
- package/dist-esm/lib/primitives/geometry/Point2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Polygon2d.mjs +3 -0
- package/dist-esm/lib/primitives/geometry/Polygon2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Polyline2d.mjs +8 -5
- package/dist-esm/lib/primitives/geometry/Polyline2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Rectangle2d.mjs +22 -11
- package/dist-esm/lib/primitives/geometry/Rectangle2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +22 -22
- package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +2 -2
- package/dist-esm/lib/utils/reorderShapes.mjs +11 -10
- package/dist-esm/lib/utils/reorderShapes.mjs.map +2 -2
- package/dist-esm/lib/utils/richText.mjs +8 -3
- package/dist-esm/lib/utils/richText.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +433 -482
- package/package.json +8 -9
- package/src/index.ts +19 -8
- package/src/lib/config/TLSessionStateSnapshot.ts +1 -1
- package/src/lib/editor/Editor.test.ts +252 -3
- package/src/lib/editor/Editor.ts +83 -76
- package/src/lib/editor/bindings/BindingUtil.ts +6 -0
- package/src/lib/editor/derivations/bindingsIndex.ts +27 -26
- package/src/lib/editor/derivations/notVisibleShapes.ts +24 -25
- package/src/lib/editor/derivations/parentsToChildren.ts +28 -25
- package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +442 -0
- package/src/lib/editor/managers/{ClickManager.ts → ClickManager/ClickManager.ts} +3 -3
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +374 -0
- package/src/lib/editor/managers/{EdgeScrollManager.ts → EdgeScrollManager/EdgeScrollManager.ts} +3 -3
- package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +455 -0
- package/src/lib/editor/managers/{FocusManager.ts → FocusManager/FocusManager.ts} +3 -1
- package/src/lib/editor/managers/FontManager/FontManager.test.ts +263 -0
- package/src/lib/editor/managers/{FontManager.ts → FontManager/FontManager.ts} +5 -2
- package/src/lib/editor/managers/{HistoryManager.test.ts → HistoryManager/HistoryManager.test.ts} +388 -1
- package/src/lib/editor/managers/{HistoryManager.ts → HistoryManager/HistoryManager.ts} +73 -2
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +624 -0
- package/src/lib/editor/managers/{ScribbleManager.ts → ScribbleManager/ScribbleManager.ts} +2 -2
- package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +485 -0
- package/src/lib/editor/managers/TextManager/TextManager.test.ts +407 -0
- package/src/lib/editor/managers/{TextManager.ts → TextManager/TextManager.ts} +119 -87
- package/src/lib/editor/managers/TickManager/TickManager.test.ts +314 -0
- package/src/lib/editor/managers/{TickManager.ts → TickManager/TickManager.ts} +2 -2
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +591 -0
- package/src/lib/editor/managers/{UserPreferencesManager.ts → UserPreferencesManager/UserPreferencesManager.ts} +2 -2
- package/src/lib/editor/shapes/ShapeUtil.ts +11 -1
- package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +8 -0
- package/src/lib/editor/shapes/shared/getPerfectDashProps.ts +5 -2
- package/src/lib/editor/tools/StateNode.ts +3 -3
- package/src/lib/editor/types/emit-types.ts +4 -0
- package/src/lib/editor/types/external-content.ts +11 -2
- package/src/lib/exports/getSvgJsx.tsx +1 -1
- package/src/lib/hooks/useCanvasEvents.ts +0 -1
- package/src/lib/primitives/Box.test.ts +588 -7
- package/src/lib/primitives/Box.ts +33 -33
- package/src/lib/primitives/Vec.test.ts +2 -2
- package/src/lib/primitives/Vec.ts +15 -10
- package/src/lib/primitives/geometry/Arc2d.ts +42 -23
- package/src/lib/primitives/geometry/Circle2d.ts +12 -12
- package/src/lib/primitives/geometry/CubicBezier2d.test.ts +5 -0
- package/src/lib/primitives/geometry/CubicBezier2d.ts +13 -17
- package/src/lib/primitives/geometry/CubicSpline2d.ts +5 -5
- package/src/lib/primitives/geometry/Edge2d.ts +14 -25
- package/src/lib/primitives/geometry/Ellipse2d.ts +12 -13
- package/src/lib/primitives/geometry/Geometry2d.ts +6 -0
- package/src/lib/primitives/geometry/Point2d.ts +6 -6
- package/src/lib/primitives/geometry/Polygon2d.ts +4 -0
- package/src/lib/primitives/geometry/Polyline2d.ts +10 -7
- package/src/lib/primitives/geometry/Rectangle2d.ts +24 -11
- package/src/lib/primitives/geometry/Stadium2d.ts +22 -23
- package/src/lib/utils/reorderShapes.ts +10 -13
- package/src/lib/utils/richText.ts +10 -4
- package/src/version.ts +3 -3
- package/dist-cjs/lib/editor/managers/ClickManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/EdgeScrollManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/FocusManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/FontManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/HistoryManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/ScribbleManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/Stack.js +0 -82
- package/dist-cjs/lib/editor/managers/Stack.js.map +0 -7
- package/dist-cjs/lib/editor/managers/TextManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/TickManager.js.map +0 -7
- package/dist-cjs/lib/editor/managers/UserPreferencesManager.js.map +0 -7
- package/dist-esm/lib/editor/managers/ClickManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/EdgeScrollManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/FocusManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/FontManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/HistoryManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/ScribbleManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/Stack.mjs +0 -62
- package/dist-esm/lib/editor/managers/Stack.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/TextManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/TickManager.mjs.map +0 -7
- package/dist-esm/lib/editor/managers/UserPreferencesManager.mjs.map +0 -7
- package/src/lib/editor/managers/ScribbleManager.test.ts +0 -32
- package/src/lib/editor/managers/Stack.ts +0 -71
|
@@ -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 '
|
|
3
|
-
import { Editor } from '
|
|
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'
|