@tldraw/editor 4.2.2 → 4.2.3

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 (200) hide show
  1. package/dist-cjs/index.d.ts +155 -498
  2. package/dist-cjs/index.js +1 -6
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/components/ErrorBoundary.js.map +1 -1
  5. package/dist-cjs/lib/components/GeometryDebuggingView.js +17 -1
  6. package/dist-cjs/lib/components/GeometryDebuggingView.js.map +2 -2
  7. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +3 -3
  8. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  9. package/dist-cjs/lib/constants.js +3 -1
  10. package/dist-cjs/lib/constants.js.map +2 -2
  11. package/dist-cjs/lib/editor/Editor.js +286 -292
  12. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  13. package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +2 -2
  14. package/dist-cjs/lib/editor/derivations/bindingsIndex.js.map +2 -2
  15. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +17 -18
  16. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +3 -3
  17. package/dist-cjs/lib/editor/derivations/parentsToChildren.js +3 -12
  18. package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
  19. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +1 -1
  20. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
  21. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +6 -5
  22. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
  23. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +1 -1
  24. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
  25. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +22 -1
  26. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +2 -2
  27. package/dist-cjs/lib/editor/shapes/BaseBoxShapeUtil.js.map +1 -1
  28. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +23 -31
  29. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  30. package/dist-cjs/lib/editor/shapes/group/DashedOutlineBox.js +1 -1
  31. package/dist-cjs/lib/editor/shapes/group/DashedOutlineBox.js.map +2 -2
  32. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
  33. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.js.map +2 -2
  34. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +3 -3
  35. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
  36. package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
  37. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  38. package/dist-cjs/lib/exports/parseCss.js +1 -1
  39. package/dist-cjs/lib/exports/parseCss.js.map +2 -2
  40. package/dist-cjs/lib/globals/environment.js +9 -45
  41. package/dist-cjs/lib/globals/environment.js.map +2 -2
  42. package/dist-cjs/lib/globals/menus.js +1 -1
  43. package/dist-cjs/lib/globals/menus.js.map +2 -2
  44. package/dist-cjs/lib/hooks/useCanvasEvents.js +3 -4
  45. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  46. package/dist-cjs/lib/hooks/useCoarsePointer.js +29 -14
  47. package/dist-cjs/lib/hooks/useCoarsePointer.js.map +2 -2
  48. package/dist-cjs/lib/hooks/useEvent.js +1 -1
  49. package/dist-cjs/lib/hooks/useEvent.js.map +2 -2
  50. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
  51. package/dist-cjs/lib/hooks/useGestureEvents.js +1 -1
  52. package/dist-cjs/lib/hooks/useGestureEvents.js.map +2 -2
  53. package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +2 -2
  54. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
  55. package/dist-cjs/lib/hooks/useScreenBounds.js.map +2 -2
  56. package/dist-cjs/lib/hooks/useStateAttribute.js +1 -4
  57. package/dist-cjs/lib/hooks/useStateAttribute.js.map +2 -2
  58. package/dist-cjs/lib/hooks/useTransform.js.map +1 -1
  59. package/dist-cjs/lib/hooks/useZoomCss.js +8 -4
  60. package/dist-cjs/lib/hooks/useZoomCss.js.map +2 -2
  61. package/dist-cjs/lib/options.js +1 -6
  62. package/dist-cjs/lib/options.js.map +2 -2
  63. package/dist-cjs/lib/primitives/Box.js +0 -3
  64. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  65. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +0 -1
  66. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  67. package/dist-cjs/lib/utils/reparenting.js.map +2 -2
  68. package/dist-cjs/lib/utils/rotation.js +1 -1
  69. package/dist-cjs/lib/utils/rotation.js.map +2 -2
  70. package/dist-cjs/version.js +3 -3
  71. package/dist-cjs/version.js.map +1 -1
  72. package/dist-esm/index.d.mts +155 -498
  73. package/dist-esm/index.mjs +2 -7
  74. package/dist-esm/index.mjs.map +2 -2
  75. package/dist-esm/lib/components/ErrorBoundary.mjs.map +1 -1
  76. package/dist-esm/lib/components/GeometryDebuggingView.mjs +17 -1
  77. package/dist-esm/lib/components/GeometryDebuggingView.mjs.map +2 -2
  78. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +3 -3
  79. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  80. package/dist-esm/lib/constants.mjs +3 -1
  81. package/dist-esm/lib/constants.mjs.map +2 -2
  82. package/dist-esm/lib/editor/Editor.mjs +289 -293
  83. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  84. package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +2 -2
  85. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs.map +2 -2
  86. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +17 -18
  87. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +3 -3
  88. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +4 -13
  89. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
  90. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +1 -1
  91. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
  92. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +6 -5
  93. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
  94. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +1 -1
  95. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
  96. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +22 -1
  97. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +2 -2
  98. package/dist-esm/lib/editor/shapes/BaseBoxShapeUtil.mjs.map +1 -1
  99. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +23 -31
  100. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  101. package/dist-esm/lib/editor/shapes/group/DashedOutlineBox.mjs +1 -1
  102. package/dist-esm/lib/editor/shapes/group/DashedOutlineBox.mjs.map +2 -2
  103. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
  104. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.mjs.map +2 -2
  105. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +3 -3
  106. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
  107. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  108. package/dist-esm/lib/exports/parseCss.mjs +1 -1
  109. package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
  110. package/dist-esm/lib/globals/environment.mjs +9 -45
  111. package/dist-esm/lib/globals/environment.mjs.map +2 -2
  112. package/dist-esm/lib/globals/menus.mjs +1 -1
  113. package/dist-esm/lib/globals/menus.mjs.map +2 -2
  114. package/dist-esm/lib/hooks/useCanvasEvents.mjs +3 -4
  115. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  116. package/dist-esm/lib/hooks/useCoarsePointer.mjs +30 -15
  117. package/dist-esm/lib/hooks/useCoarsePointer.mjs.map +2 -2
  118. package/dist-esm/lib/hooks/useEvent.mjs +1 -1
  119. package/dist-esm/lib/hooks/useEvent.mjs.map +2 -2
  120. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
  121. package/dist-esm/lib/hooks/useGestureEvents.mjs +1 -1
  122. package/dist-esm/lib/hooks/useGestureEvents.mjs.map +2 -2
  123. package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +2 -2
  124. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
  125. package/dist-esm/lib/hooks/useScreenBounds.mjs.map +2 -2
  126. package/dist-esm/lib/hooks/useStateAttribute.mjs +1 -4
  127. package/dist-esm/lib/hooks/useStateAttribute.mjs.map +2 -2
  128. package/dist-esm/lib/hooks/useTransform.mjs.map +1 -1
  129. package/dist-esm/lib/hooks/useZoomCss.mjs +8 -4
  130. package/dist-esm/lib/hooks/useZoomCss.mjs.map +2 -2
  131. package/dist-esm/lib/options.mjs +1 -6
  132. package/dist-esm/lib/options.mjs.map +2 -2
  133. package/dist-esm/lib/primitives/Box.mjs +0 -3
  134. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  135. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +0 -1
  136. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  137. package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
  138. package/dist-esm/lib/utils/rotation.mjs +1 -1
  139. package/dist-esm/lib/utils/rotation.mjs.map +2 -2
  140. package/dist-esm/version.mjs +3 -3
  141. package/dist-esm/version.mjs.map +1 -1
  142. package/editor.css +12 -14
  143. package/package.json +16 -18
  144. package/src/index.ts +1 -4
  145. package/src/lib/components/ErrorBoundary.tsx +1 -1
  146. package/src/lib/components/GeometryDebuggingView.tsx +19 -1
  147. package/src/lib/components/default-components/DefaultCanvas.tsx +3 -4
  148. package/src/lib/constants.ts +2 -0
  149. package/src/lib/editor/Editor.test.ts +10 -150
  150. package/src/lib/editor/Editor.ts +379 -459
  151. package/src/lib/editor/bindings/BindingUtil.ts +9 -15
  152. package/src/lib/editor/derivations/bindingsIndex.ts +2 -2
  153. package/src/lib/editor/derivations/notVisibleShapes.ts +23 -37
  154. package/src/lib/editor/derivations/parentsToChildren.ts +7 -18
  155. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +31 -17
  156. package/src/lib/editor/managers/ClickManager/ClickManager.ts +1 -1
  157. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +79 -129
  158. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +6 -10
  159. package/src/lib/editor/managers/FontManager/FontManager.test.ts +4 -14
  160. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +4 -0
  161. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +0 -12
  162. package/src/lib/editor/managers/SnapManager/SnapManager.ts +4 -4
  163. package/src/lib/editor/managers/TickManager/TickManager.test.ts +107 -40
  164. package/src/lib/editor/managers/TickManager/TickManager.ts +32 -2
  165. package/src/lib/editor/shapes/BaseBoxShapeUtil.tsx +2 -2
  166. package/src/lib/editor/shapes/ShapeUtil.ts +32 -72
  167. package/src/lib/editor/shapes/group/DashedOutlineBox.tsx +1 -1
  168. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +3 -1
  169. package/src/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.ts +1 -2
  170. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +6 -6
  171. package/src/lib/editor/types/emit-types.ts +1 -3
  172. package/src/lib/exports/getSvgJsx.test.ts +19 -10
  173. package/src/lib/exports/getSvgJsx.tsx +5 -2
  174. package/src/lib/exports/parseCss.test.ts +0 -1
  175. package/src/lib/exports/parseCss.ts +1 -1
  176. package/src/lib/globals/environment.ts +10 -65
  177. package/src/lib/globals/menus.ts +1 -1
  178. package/src/lib/hooks/useCanvasEvents.ts +3 -4
  179. package/src/lib/hooks/useCoarsePointer.ts +59 -16
  180. package/src/lib/hooks/useEvent.tsx +1 -1
  181. package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +1 -1
  182. package/src/lib/hooks/useGestureEvents.ts +2 -2
  183. package/src/lib/hooks/usePassThroughMouseOverEvents.ts +1 -1
  184. package/src/lib/hooks/usePassThroughWheelEvents.ts +1 -1
  185. package/src/lib/hooks/useScreenBounds.ts +1 -1
  186. package/src/lib/hooks/useStateAttribute.ts +1 -4
  187. package/src/lib/hooks/useTransform.ts +1 -1
  188. package/src/lib/hooks/useZoomCss.ts +8 -3
  189. package/src/lib/options.ts +0 -32
  190. package/src/lib/primitives/Box.ts +0 -9
  191. package/src/lib/primitives/geometry/Geometry2d.ts +0 -1
  192. package/src/lib/utils/reparenting.ts +5 -5
  193. package/src/lib/utils/rotation.ts +1 -1
  194. package/src/version.ts +3 -3
  195. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +0 -591
  196. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +0 -7
  197. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +0 -573
  198. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +0 -7
  199. package/src/lib/config/TLUserPreferences.test.ts +0 -40
  200. package/src/lib/editor/managers/InputsManager/InputsManager.ts +0 -566
@@ -18,56 +18,8 @@ describe('EdgeScrollManager', () => {
18
18
  }
19
19
  >
20
20
  let edgeScrollManager: EdgeScrollManager
21
- let mockInputs: {
22
- _currentScreenPoint: Vec
23
- currentScreenPoint: Vec
24
- getCurrentScreenPoint(): Vec
25
- setCurrentScreenPoint(value: Vec): void
26
- _isDragging: boolean
27
- isDragging: boolean
28
- getIsDragging(): boolean
29
- setIsDragging(value: boolean): void
30
- _isPanning: boolean
31
- isPanning: boolean
32
- getIsPanning(): boolean
33
- setIsPanning(value: boolean): void
34
- }
35
21
 
36
22
  beforeEach(() => {
37
- // Create a mock inputs object with writable properties and getters
38
- mockInputs = {
39
- _currentScreenPoint: new Vec(500, 300),
40
- get currentScreenPoint() {
41
- return this._currentScreenPoint
42
- },
43
- getCurrentScreenPoint() {
44
- return this._currentScreenPoint
45
- },
46
- setCurrentScreenPoint(value: Vec) {
47
- this._currentScreenPoint = value
48
- },
49
- _isDragging: true,
50
- get isDragging() {
51
- return this._isDragging
52
- },
53
- getIsDragging() {
54
- return this._isDragging
55
- },
56
- setIsDragging(value: boolean) {
57
- this._isDragging = value
58
- },
59
- _isPanning: false,
60
- get isPanning() {
61
- return this._isPanning
62
- },
63
- getIsPanning() {
64
- return this._isPanning
65
- },
66
- setIsPanning(value: boolean) {
67
- this._isPanning = value
68
- },
69
- }
70
-
71
23
  editor = {
72
24
  options: {
73
25
  edgeScrollDelay: 200,
@@ -76,15 +28,22 @@ describe('EdgeScrollManager', () => {
76
28
  edgeScrollDistance: 8,
77
29
  coarsePointerWidth: 12,
78
30
  },
79
- inputs: mockInputs as unknown as Editor['inputs'],
31
+ inputs: {
32
+ currentScreenPoint: new Vec(500, 300),
33
+ isDragging: true,
34
+ isPanning: false,
35
+ },
80
36
  user: {
81
37
  getEdgeScrollSpeed: vi.fn(() => 1),
82
38
  },
83
39
  getViewportScreenBounds: vi.fn(() => new Box(0, 0, 1000, 600)),
84
- getInstanceState: vi.fn(() => ({
85
- isCoarsePointer: false,
86
- insets: [false, false, false, false], // [top, right, bottom, left]
87
- })),
40
+ getInstanceState: vi.fn(
41
+ () =>
42
+ ({
43
+ isCoarsePointer: false,
44
+ insets: [false, false, false, false], // [top, right, bottom, left]
45
+ }) as any
46
+ ),
88
47
  getCameraOptions: vi.fn(() => ({
89
48
  isLocked: false,
90
49
  panSpeed: 1,
@@ -95,17 +54,9 @@ describe('EdgeScrollManager', () => {
95
54
  getZoomLevel: vi.fn(() => 1),
96
55
  getCamera: vi.fn(() => new Vec(0, 0, 1)),
97
56
  setCamera: vi.fn(),
98
- } as unknown as Mocked<
99
- Editor & {
100
- user: { getEdgeScrollSpeed: Mock }
101
- getCamera: Mock
102
- getCameraOptions: Mock
103
- getZoomLevel: Mock
104
- getViewportScreenBounds: Mock
105
- }
106
- >
57
+ } as any
107
58
 
108
- edgeScrollManager = new EdgeScrollManager(editor)
59
+ edgeScrollManager = new EdgeScrollManager(editor as any)
109
60
  })
110
61
 
111
62
  afterEach(() => {
@@ -116,45 +67,49 @@ describe('EdgeScrollManager', () => {
116
67
  it('should initialize with editor reference', () => {
117
68
  expect(edgeScrollManager.editor).toBe(editor)
118
69
  })
70
+
71
+ it('should initialize edge scrolling state as false', () => {
72
+ // Access private properties for testing
73
+ expect((edgeScrollManager as any)._isEdgeScrolling).toBe(false)
74
+ expect((edgeScrollManager as any)._edgeScrollDuration).toBe(-1)
75
+ })
119
76
  })
120
77
 
121
78
  describe('basic edge scrolling behavior', () => {
122
79
  it('should not trigger edge scrolling when pointer is in center', () => {
123
- mockInputs.setCurrentScreenPoint(new Vec(500, 300))
80
+ editor.inputs.currentScreenPoint = new Vec(500, 300)
124
81
 
125
82
  edgeScrollManager.updateEdgeScrolling(16)
126
83
 
84
+ expect((edgeScrollManager as any)._isEdgeScrolling).toBe(false)
127
85
  expect(editor.setCamera).not.toHaveBeenCalled()
128
86
  })
129
87
 
130
88
  it('should start edge scrolling when pointer is near edge', () => {
131
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
89
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
132
90
 
133
- // Should not scroll immediately due to delay
134
91
  edgeScrollManager.updateEdgeScrolling(16)
135
- expect(editor.setCamera).not.toHaveBeenCalled()
136
92
 
137
- // Should scroll after delay
138
- edgeScrollManager.updateEdgeScrolling(200)
139
- expect(editor.setCamera).toHaveBeenCalled()
93
+ expect((edgeScrollManager as any)._isEdgeScrolling).toBe(true)
94
+ expect((edgeScrollManager as any)._edgeScrollDuration).toBe(16)
140
95
  })
141
96
 
142
97
  it('should stop edge scrolling when pointer moves away from edge', () => {
143
- // Start edge scrolling near edge
144
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
145
- edgeScrollManager.updateEdgeScrolling(300)
146
- expect(editor.setCamera).toHaveBeenCalled()
98
+ // Start edge scrolling
99
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
100
+ edgeScrollManager.updateEdgeScrolling(16)
101
+ expect((edgeScrollManager as any)._isEdgeScrolling).toBe(true)
147
102
 
148
- // Move pointer to center - should stop scrolling
149
- editor.setCamera.mockClear()
150
- mockInputs.setCurrentScreenPoint(new Vec(500, 300))
103
+ // Move pointer to center
104
+ editor.inputs.currentScreenPoint = new Vec(500, 300)
151
105
  edgeScrollManager.updateEdgeScrolling(16)
152
106
 
153
- expect(editor.setCamera).not.toHaveBeenCalled()
107
+ expect((edgeScrollManager as any)._isEdgeScrolling).toBe(false)
108
+ expect((edgeScrollManager as any)._edgeScrollDuration).toBe(0)
154
109
  })
155
110
 
156
111
  it('should respect edge scroll delay', () => {
157
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
112
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
158
113
 
159
114
  // First update - should not scroll yet due to delay
160
115
  edgeScrollManager.updateEdgeScrolling(100)
@@ -168,7 +123,7 @@ describe('EdgeScrollManager', () => {
168
123
 
169
124
  describe('edge proximity detection', () => {
170
125
  it('should detect left edge proximity', () => {
171
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
126
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
172
127
  edgeScrollManager.updateEdgeScrolling(300) // Enough to trigger after delay
173
128
 
174
129
  expect(editor.setCamera).toHaveBeenCalled()
@@ -177,7 +132,7 @@ describe('EdgeScrollManager', () => {
177
132
  })
178
133
 
179
134
  it('should detect right edge proximity', () => {
180
- mockInputs.setCurrentScreenPoint(new Vec(995, 300))
135
+ editor.inputs.currentScreenPoint = new Vec(995, 300)
181
136
  edgeScrollManager.updateEdgeScrolling(300)
182
137
 
183
138
  expect(editor.setCamera).toHaveBeenCalled()
@@ -186,7 +141,7 @@ describe('EdgeScrollManager', () => {
186
141
  })
187
142
 
188
143
  it('should detect top edge proximity', () => {
189
- mockInputs.setCurrentScreenPoint(new Vec(500, 5))
144
+ editor.inputs.currentScreenPoint = new Vec(500, 5)
190
145
  edgeScrollManager.updateEdgeScrolling(300)
191
146
 
192
147
  expect(editor.setCamera).toHaveBeenCalled()
@@ -195,7 +150,7 @@ describe('EdgeScrollManager', () => {
195
150
  })
196
151
 
197
152
  it('should detect bottom edge proximity', () => {
198
- mockInputs.setCurrentScreenPoint(new Vec(500, 595))
153
+ editor.inputs.currentScreenPoint = new Vec(500, 595)
199
154
  edgeScrollManager.updateEdgeScrolling(300)
200
155
 
201
156
  expect(editor.setCamera).toHaveBeenCalled()
@@ -204,7 +159,7 @@ describe('EdgeScrollManager', () => {
204
159
  })
205
160
 
206
161
  it('should handle corner proximity (both x and y)', () => {
207
- mockInputs.setCurrentScreenPoint(new Vec(5, 5))
162
+ editor.inputs.currentScreenPoint = new Vec(5, 5)
208
163
  edgeScrollManager.updateEdgeScrolling(300)
209
164
 
210
165
  expect(editor.setCamera).toHaveBeenCalled()
@@ -217,11 +172,11 @@ describe('EdgeScrollManager', () => {
217
172
  describe('coarse pointer handling', () => {
218
173
  it('should account for coarse pointer width', () => {
219
174
  editor.getInstanceState.mockReturnValue({
220
- ...editor.getInstanceState(),
221
175
  isCoarsePointer: true,
222
176
  insets: [false, false, false, false],
223
- })
224
- mockInputs.setCurrentScreenPoint(new Vec(15, 300))
177
+ } as any)
178
+
179
+ editor.inputs.currentScreenPoint = new Vec(15, 300)
225
180
  edgeScrollManager.updateEdgeScrolling(300)
226
181
 
227
182
  expect(editor.setCamera).toHaveBeenCalled()
@@ -229,11 +184,11 @@ describe('EdgeScrollManager', () => {
229
184
 
230
185
  it('should not trigger edge scrolling for fine pointer at same position', () => {
231
186
  editor.getInstanceState.mockReturnValue({
232
- ...editor.getInstanceState(),
233
187
  isCoarsePointer: false,
234
188
  insets: [false, false, false, false],
235
- })
236
- mockInputs.setCurrentScreenPoint(new Vec(15, 300))
189
+ } as any)
190
+
191
+ editor.inputs.currentScreenPoint = new Vec(15, 300)
237
192
  edgeScrollManager.updateEdgeScrolling(300)
238
193
 
239
194
  expect(editor.setCamera).not.toHaveBeenCalled()
@@ -242,8 +197,8 @@ describe('EdgeScrollManager', () => {
242
197
 
243
198
  describe('camera movement conditions', () => {
244
199
  it('should not move camera when not dragging', () => {
245
- editor.inputs.setIsDragging(false)
246
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
200
+ editor.inputs.isDragging = false
201
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
247
202
 
248
203
  edgeScrollManager.updateEdgeScrolling(300)
249
204
 
@@ -251,8 +206,8 @@ describe('EdgeScrollManager', () => {
251
206
  })
252
207
 
253
208
  it('should not move camera when panning', () => {
254
- editor.inputs.setIsPanning(true)
255
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
209
+ editor.inputs.isPanning = true
210
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
256
211
 
257
212
  edgeScrollManager.updateEdgeScrolling(300)
258
213
 
@@ -267,7 +222,7 @@ describe('EdgeScrollManager', () => {
267
222
  zoomSteps: [1],
268
223
  wheelBehavior: 'pan' as const,
269
224
  })
270
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
225
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
271
226
 
272
227
  edgeScrollManager.updateEdgeScrolling(300)
273
228
 
@@ -278,7 +233,7 @@ describe('EdgeScrollManager', () => {
278
233
  describe('camera movement calculation', () => {
279
234
  it('should calculate scroll speed based on user preference', () => {
280
235
  editor.user.getEdgeScrollSpeed.mockReturnValue(2)
281
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
236
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
282
237
 
283
238
  edgeScrollManager.updateEdgeScrolling(300)
284
239
 
@@ -289,7 +244,7 @@ describe('EdgeScrollManager', () => {
289
244
 
290
245
  it('should apply screen size factor for small screens', () => {
291
246
  editor.getViewportScreenBounds.mockReturnValue(new Box(0, 0, 800, 600))
292
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
247
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
293
248
 
294
249
  edgeScrollManager.updateEdgeScrolling(300)
295
250
 
@@ -298,7 +253,7 @@ describe('EdgeScrollManager', () => {
298
253
 
299
254
  it('should adjust scroll speed based on zoom level', () => {
300
255
  editor.getZoomLevel.mockReturnValue(2)
301
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
256
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
302
257
 
303
258
  edgeScrollManager.updateEdgeScrolling(300)
304
259
 
@@ -311,7 +266,7 @@ describe('EdgeScrollManager', () => {
311
266
  it('should add scroll delta to current camera position', () => {
312
267
  const currentCamera = new Vec(100, 200, 1)
313
268
  editor.getCamera.mockReturnValue(currentCamera)
314
- mockInputs.setCurrentScreenPoint(new Vec(5, 5))
269
+ editor.inputs.currentScreenPoint = new Vec(5, 5)
315
270
 
316
271
  edgeScrollManager.updateEdgeScrolling(300)
317
272
 
@@ -325,14 +280,14 @@ describe('EdgeScrollManager', () => {
325
280
 
326
281
  describe('proximity factor calculation', () => {
327
282
  it('should return 0 when not near any edge', () => {
328
- mockInputs.setCurrentScreenPoint(new Vec(500, 300))
283
+ editor.inputs.currentScreenPoint = new Vec(500, 300)
329
284
  edgeScrollManager.updateEdgeScrolling(16)
330
285
 
331
286
  expect(editor.setCamera).not.toHaveBeenCalled()
332
287
  })
333
288
 
334
289
  it('should cap proximity factor at 1', () => {
335
- mockInputs.setCurrentScreenPoint(new Vec(0, 300))
290
+ editor.inputs.currentScreenPoint = new Vec(0, 300)
336
291
  edgeScrollManager.updateEdgeScrolling(300)
337
292
 
338
293
  expect(editor.setCamera).toHaveBeenCalled()
@@ -342,20 +297,20 @@ describe('EdgeScrollManager', () => {
342
297
 
343
298
  describe('edge cases and error handling', () => {
344
299
  it('should handle negative elapsed time', () => {
345
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
300
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
346
301
 
347
302
  expect(() => edgeScrollManager.updateEdgeScrolling(-16)).not.toThrow()
348
303
  })
349
304
 
350
305
  it('should handle very large elapsed time', () => {
351
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
306
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
352
307
 
353
308
  expect(() => edgeScrollManager.updateEdgeScrolling(100000)).not.toThrow()
354
309
  })
355
310
 
356
311
  it('should handle zero user edge scroll speed', () => {
357
312
  editor.user.getEdgeScrollSpeed.mockReturnValue(0)
358
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
313
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
359
314
 
360
315
  edgeScrollManager.updateEdgeScrolling(300)
361
316
 
@@ -367,7 +322,7 @@ describe('EdgeScrollManager', () => {
367
322
  })
368
323
 
369
324
  it('should handle extreme zoom levels', () => {
370
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
325
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
371
326
 
372
327
  editor.getZoomLevel.mockReturnValue(0.01) // Very zoomed out
373
328
  expect(() => edgeScrollManager.updateEdgeScrolling(300)).not.toThrow()
@@ -380,46 +335,41 @@ describe('EdgeScrollManager', () => {
380
335
  describe('state transitions', () => {
381
336
  it('should properly transition from not scrolling to scrolling', () => {
382
337
  // Start with no edge scrolling
383
- mockInputs.setCurrentScreenPoint(new Vec(500, 300))
338
+ editor.inputs.currentScreenPoint = new Vec(500, 300)
384
339
  edgeScrollManager.updateEdgeScrolling(16)
385
- expect(editor.setCamera).not.toHaveBeenCalled()
340
+ expect((edgeScrollManager as any)._isEdgeScrolling).toBe(false)
386
341
 
387
- // Move to edge - should start scrolling after delay
388
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
342
+ // Move to edge
343
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
389
344
  edgeScrollManager.updateEdgeScrolling(16)
390
- expect(editor.setCamera).not.toHaveBeenCalled() // Not yet, due to delay
391
-
392
- edgeScrollManager.updateEdgeScrolling(200)
393
- expect(editor.setCamera).toHaveBeenCalled()
345
+ expect((edgeScrollManager as any)._isEdgeScrolling).toBe(true)
346
+ expect((edgeScrollManager as any)._edgeScrollDuration).toBe(16)
394
347
  })
395
348
 
396
349
  it('should accumulate edge scroll duration over multiple updates', () => {
397
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
350
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
398
351
 
399
- // First update - not enough time
400
352
  edgeScrollManager.updateEdgeScrolling(50)
401
- expect(editor.setCamera).not.toHaveBeenCalled()
353
+ expect((edgeScrollManager as any)._edgeScrollDuration).toBe(50)
402
354
 
403
- // Second update - still not enough
404
- edgeScrollManager.updateEdgeScrolling(50)
405
- expect(editor.setCamera).not.toHaveBeenCalled()
355
+ edgeScrollManager.updateEdgeScrolling(30)
356
+ expect((edgeScrollManager as any)._edgeScrollDuration).toBe(80)
406
357
 
407
- // Third update - now should trigger (50 + 50 + 101 = 201ms > 200ms delay)
408
- edgeScrollManager.updateEdgeScrolling(101)
409
- expect(editor.setCamera).toHaveBeenCalled()
358
+ edgeScrollManager.updateEdgeScrolling(25)
359
+ expect((edgeScrollManager as any)._edgeScrollDuration).toBe(105)
410
360
  })
411
361
 
412
362
  it('should reset duration when stopping edge scroll', () => {
413
363
  // Start edge scrolling
414
- mockInputs.setCurrentScreenPoint(new Vec(5, 300))
415
- edgeScrollManager.updateEdgeScrolling(300)
416
- expect(editor.setCamera).toHaveBeenCalled()
364
+ editor.inputs.currentScreenPoint = new Vec(5, 300)
365
+ edgeScrollManager.updateEdgeScrolling(100)
366
+ expect((edgeScrollManager as any)._edgeScrollDuration).toBe(100)
417
367
 
418
- // Stop edge scrolling - move away
419
- editor.setCamera.mockClear()
420
- mockInputs.setCurrentScreenPoint(new Vec(500, 300))
368
+ // Stop edge scrolling
369
+ editor.inputs.currentScreenPoint = new Vec(500, 300)
421
370
  edgeScrollManager.updateEdgeScrolling(16)
422
- expect(editor.setCamera).not.toHaveBeenCalled()
371
+ expect((edgeScrollManager as any)._isEdgeScrolling).toBe(false)
372
+ expect((edgeScrollManager as any)._edgeScrollDuration).toBe(0)
423
373
  })
424
374
  })
425
375
  })
@@ -9,10 +9,6 @@ export class EdgeScrollManager {
9
9
  private _isEdgeScrolling = false
10
10
  private _edgeScrollDuration = -1
11
11
 
12
- getIsEdgeScrolling() {
13
- return this._isEdgeScrolling
14
- }
15
-
16
12
  /**
17
13
  * Update the camera position when the mouse is close to the edge of the screen.
18
14
  * Run this on every tick when in a state where edge scrolling is enabled.
@@ -85,7 +81,11 @@ export class EdgeScrollManager {
85
81
 
86
82
  private getEdgeScroll() {
87
83
  const { editor } = this
88
- const { x, y } = editor.inputs.getCurrentScreenPoint()
84
+ const {
85
+ inputs: {
86
+ currentScreenPoint: { x, y },
87
+ },
88
+ } = editor
89
89
  const screenBounds = editor.getViewportScreenBounds()
90
90
 
91
91
  const {
@@ -107,11 +107,7 @@ export class EdgeScrollManager {
107
107
  */
108
108
  private moveCameraWhenCloseToEdge(proximityFactor: { x: number; y: number }) {
109
109
  const { editor } = this
110
- if (
111
- !editor.inputs.getIsDragging() ||
112
- editor.inputs.getIsPanning() ||
113
- editor.getCameraOptions().isLocked
114
- )
110
+ if (!editor.inputs.isDragging || editor.inputs.isPanning || editor.getCameraOptions().isLocked)
115
111
  return
116
112
 
117
113
  if (proximityFactor.x === 0 && proximityFactor.y === 0) return
@@ -1,5 +1,4 @@
1
- import { TLParentId, TLShape, TLShapeId, createShapeId, toRichText } from '@tldraw/tlschema'
2
- import { IndexKey } from '@tldraw/utils'
1
+ import { TLShape, TLShapeId, createShapeId } from '@tldraw/tlschema'
3
2
  import { Mock, Mocked, vi } from 'vitest'
4
3
  import { Editor } from '../../Editor'
5
4
  import { FontManager, TLFontFace } from './FontManager'
@@ -42,21 +41,12 @@ describe('FontManager', () => {
42
41
  x: 0,
43
42
  y: 0,
44
43
  rotation: 0,
45
- index: 'a1' as IndexKey,
46
- parentId: 'page:page' as TLParentId,
44
+ index: 'a1' as any,
45
+ parentId: 'page:page' as any,
47
46
  opacity: 1,
48
47
  isLocked: false,
49
48
  meta: {},
50
- props: {
51
- color: 'black',
52
- size: 'xl',
53
- font: 'serif',
54
- textAlign: 'middle',
55
- w: 100,
56
- richText: toRichText('❤️'),
57
- scale: 2,
58
- autoSize: true,
59
- },
49
+ props: {},
60
50
  typeName: 'shape' as const,
61
51
  })
62
52
 
@@ -36,6 +36,10 @@ describe('ScribbleManager', () => {
36
36
  expect(scribbleManager.scribbleItems.size).toBe(0)
37
37
  expect(scribbleManager.state).toBe('paused')
38
38
  })
39
+
40
+ it('should store reference to editor', () => {
41
+ expect((scribbleManager as any).editor).toBe(editor)
42
+ })
39
43
  })
40
44
 
41
45
  describe('addScribble', () => {
@@ -64,7 +64,6 @@ describe('SnapManager', () => {
64
64
  beforeEach(() => {
65
65
  editor = {
66
66
  getZoomLevel: vi.fn(() => 1),
67
- options: { snapThreshold: 8 },
68
67
  getViewportPageBounds: vi.fn(() => new Box(0, 0, 1000, 1000)),
69
68
  getSelectedShapeIds: vi.fn(() => []),
70
69
  getSelectedShapes: vi.fn(() => []),
@@ -249,17 +248,6 @@ describe('SnapManager', () => {
249
248
  editor.getZoomLevel.mockReturnValue(10)
250
249
  expect(snapManager.getSnapThreshold()).toBe(0.8)
251
250
  })
252
-
253
- it('should use custom snap threshold when configured', () => {
254
- ;(editor as any).options = { snapThreshold: 16 }
255
- editor.getZoomLevel.mockReturnValue(1)
256
- const customSnapManager = new SnapManager(editor)
257
- expect(customSnapManager.getSnapThreshold()).toBe(16)
258
-
259
- editor.getZoomLevel.mockReturnValue(2)
260
- const customSnapManager2 = new SnapManager(editor)
261
- expect(customSnapManager2.getSnapThreshold()).toBe(8)
262
- })
263
251
  })
264
252
 
265
253
  describe('getCurrentCommonAncestor', () => {
@@ -1,5 +1,5 @@
1
1
  import { EMPTY_ARRAY, atom, computed } from '@tldraw/state'
2
- import { TLParentId, TLShapeId, isShapeId } from '@tldraw/tlschema'
2
+ import { TLFrameShape, TLGroupShape, TLParentId, TLShapeId, isShapeId } from '@tldraw/tlschema'
3
3
  import { Vec, VecLike } from '../../../primitives/Vec'
4
4
  import type { Editor } from '../../Editor'
5
5
  import { BoundsSnaps } from './BoundsSnaps'
@@ -58,7 +58,7 @@ export class SnapManager {
58
58
  }
59
59
 
60
60
  @computed getSnapThreshold() {
61
- return this.editor.options.snapThreshold / this.editor.getZoomLevel()
61
+ return 8 / this.editor.getZoomLevel()
62
62
  }
63
63
 
64
64
  // TODO: make this an incremental derivation
@@ -72,7 +72,7 @@ export class SnapManager {
72
72
  const collectSnappableShapesFromParent = (parentId: TLParentId) => {
73
73
  if (isShapeId(parentId)) {
74
74
  const parent = editor.getShape(parentId)
75
- if (parent && editor.isShapeOfType(parent, 'frame')) {
75
+ if (parent && editor.isShapeOfType<TLFrameShape>(parent, 'frame')) {
76
76
  snappableShapes.add(parentId)
77
77
  }
78
78
  }
@@ -89,7 +89,7 @@ export class SnapManager {
89
89
  const pageBounds = editor.getShapePageBounds(childId)
90
90
  if (!(pageBounds && renderingBounds.includes(pageBounds))) continue
91
91
  // Snap to children of groups but not group itself
92
- if (editor.isShapeOfType(childShape, 'group')) {
92
+ if (editor.isShapeOfType<TLGroupShape>(childShape, 'group')) {
93
93
  collectSnappableShapesFromParent(childId)
94
94
  continue
95
95
  }