@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
@@ -1,15 +1,9 @@
1
- import {
2
- RecordProps,
3
- TLBinding,
4
- TLPropsMigrations,
5
- TLShape,
6
- TLUnknownBinding,
7
- } from '@tldraw/tlschema'
1
+ import { RecordProps, TLPropsMigrations, TLShape, TLUnknownBinding } from '@tldraw/tlschema'
8
2
  import { Editor } from '../Editor'
9
3
 
10
4
  /** @public */
11
5
  export interface TLBindingUtilConstructor<
12
- T extends TLBinding,
6
+ T extends TLUnknownBinding,
13
7
  U extends BindingUtil<T> = BindingUtil<T>,
14
8
  > {
15
9
  new (editor: Editor): U
@@ -26,7 +20,7 @@ export interface TLBindingUtilConstructor<
26
20
  *
27
21
  * @public
28
22
  */
29
- export interface BindingOnCreateOptions<Binding extends TLBinding = TLBinding> {
23
+ export interface BindingOnCreateOptions<Binding extends TLUnknownBinding> {
30
24
  /** The binding being created. */
31
25
  binding: Binding
32
26
  }
@@ -37,7 +31,7 @@ export interface BindingOnCreateOptions<Binding extends TLBinding = TLBinding> {
37
31
  *
38
32
  * @public
39
33
  */
40
- export interface BindingOnChangeOptions<Binding extends TLBinding = TLBinding> {
34
+ export interface BindingOnChangeOptions<Binding extends TLUnknownBinding> {
41
35
  /** The binding record before the change is made. */
42
36
  bindingBefore: Binding
43
37
  /** The binding record after the change is made. */
@@ -50,7 +44,7 @@ export interface BindingOnChangeOptions<Binding extends TLBinding = TLBinding> {
50
44
  *
51
45
  * @public
52
46
  */
53
- export interface BindingOnDeleteOptions<Binding extends TLBinding = TLBinding> {
47
+ export interface BindingOnDeleteOptions<Binding extends TLUnknownBinding> {
54
48
  /** The binding being deleted. */
55
49
  binding: Binding
56
50
  }
@@ -61,7 +55,7 @@ export interface BindingOnDeleteOptions<Binding extends TLBinding = TLBinding> {
61
55
  *
62
56
  * @public
63
57
  */
64
- export interface BindingOnShapeChangeOptions<Binding extends TLBinding = TLBinding> {
58
+ export interface BindingOnShapeChangeOptions<Binding extends TLUnknownBinding> {
65
59
  /** The binding record linking these two shapes. */
66
60
  binding: Binding
67
61
  /** The shape record before the change is made. */
@@ -101,7 +95,7 @@ export interface BindingOnShapeChangeOptions<Binding extends TLBinding = TLBindi
101
95
  *
102
96
  * @public
103
97
  */
104
- export interface BindingOnShapeIsolateOptions<Binding extends TLBinding = TLBinding> {
98
+ export interface BindingOnShapeIsolateOptions<Binding extends TLUnknownBinding> {
105
99
  /** The binding record that refers to the shape in question. */
106
100
  binding: Binding
107
101
  /**
@@ -120,7 +114,7 @@ export interface BindingOnShapeIsolateOptions<Binding extends TLBinding = TLBind
120
114
  *
121
115
  * @public
122
116
  */
123
- export interface BindingOnShapeDeleteOptions<Binding extends TLBinding = TLBinding> {
117
+ export interface BindingOnShapeDeleteOptions<Binding extends TLUnknownBinding> {
124
118
  /** The binding record that refers to the shape in question. */
125
119
  binding: Binding
126
120
  /** The shape that is about to be deleted. */
@@ -128,7 +122,7 @@ export interface BindingOnShapeDeleteOptions<Binding extends TLBinding = TLBindi
128
122
  }
129
123
 
130
124
  /** @public */
131
- export abstract class BindingUtil<Binding extends TLBinding = TLBinding> {
125
+ export abstract class BindingUtil<Binding extends TLUnknownBinding = TLUnknownBinding> {
132
126
  constructor(public editor: Editor) {}
133
127
  static props?: RecordProps<TLUnknownBinding>
134
128
  static migrations?: TLPropsMigrations
@@ -1,11 +1,11 @@
1
1
  import { Computed, RESET_VALUE, computed, isUninitialized } from '@tldraw/state'
2
- import { TLBinding, TLShapeId } from '@tldraw/tlschema'
2
+ import { TLArrowBinding, TLBinding, TLShapeId, TLUnknownBinding } from '@tldraw/tlschema'
3
3
  import { objectMapValues } from '@tldraw/utils'
4
4
  import { Editor } from '../Editor'
5
5
 
6
6
  type TLBindingsIndex = Map<TLShapeId, TLBinding[]>
7
7
 
8
- function fromScratch(bindingsQuery: Computed<TLBinding[], unknown>) {
8
+ function fromScratch(bindingsQuery: Computed<(TLArrowBinding | TLUnknownBinding)[], unknown>) {
9
9
  const allBindings = bindingsQuery.get() as TLBinding[]
10
10
 
11
11
  const shapesToBindings: TLBindingsIndex = new Map()
@@ -2,7 +2,29 @@ import { computed, isUninitialized } from '@tldraw/state'
2
2
  import { TLShapeId } from '@tldraw/tlschema'
3
3
  import { Editor } from '../Editor'
4
4
 
5
+ function fromScratch(editor: Editor): Set<TLShapeId> {
6
+ const shapesIds = editor.getCurrentPageShapeIds()
7
+ const viewportPageBounds = editor.getViewportPageBounds()
8
+ const notVisibleShapes = new Set<TLShapeId>()
9
+ shapesIds.forEach((id) => {
10
+ const shape = editor.getShape(id)
11
+ if (!shape) return
12
+
13
+ const canCull = editor.getShapeUtil(shape.type).canCull(shape)
14
+ if (!canCull) return
15
+
16
+ // If the shape is fully outside of the viewport page bounds, add it to the set.
17
+ // We'll ignore masks here, since they're more expensive to compute and the overhead is not worth it.
18
+ const pageBounds = editor.getShapePageBounds(id)
19
+ if (pageBounds === undefined || !viewportPageBounds.includes(pageBounds)) {
20
+ notVisibleShapes.add(id)
21
+ }
22
+ })
23
+ return notVisibleShapes
24
+ }
25
+
5
26
  /**
27
+ * Incremental derivation of not visible shapes.
6
28
  * Non visible shapes are shapes outside of the viewport page bounds.
7
29
  *
8
30
  * @param editor - Instance of the tldraw Editor.
@@ -10,43 +32,7 @@ import { Editor } from '../Editor'
10
32
  */
11
33
  export function notVisibleShapes(editor: Editor) {
12
34
  return computed<Set<TLShapeId>>('notVisibleShapes', function updateNotVisibleShapes(prevValue) {
13
- const shapeIds = editor.getCurrentPageShapeIds()
14
- const nextValue = new Set<TLShapeId>()
15
-
16
- // Extract viewport bounds once to avoid repeated property access
17
- const viewportPageBounds = editor.getViewportPageBounds()
18
- const viewMinX = viewportPageBounds.minX
19
- const viewMinY = viewportPageBounds.minY
20
- const viewMaxX = viewportPageBounds.maxX
21
- const viewMaxY = viewportPageBounds.maxY
22
-
23
- for (const id of shapeIds) {
24
- const pageBounds = editor.getShapePageBounds(id)
25
-
26
- // Hybrid check: if bounds exist and shape overlaps viewport, it's visible.
27
- // This inlines Box.Collides to avoid function call overhead and the
28
- // redundant Contains check that Box.Includes was doing.
29
- if (
30
- pageBounds !== undefined &&
31
- pageBounds.maxX >= viewMinX &&
32
- pageBounds.minX <= viewMaxX &&
33
- pageBounds.maxY >= viewMinY &&
34
- pageBounds.minY <= viewMaxY
35
- ) {
36
- continue
37
- }
38
-
39
- // Shape is outside viewport or has no bounds - check if it can be culled.
40
- // We defer getShape and canCull checks until here since most shapes are
41
- // typically visible and we can skip these calls for them.
42
- const shape = editor.getShape(id)
43
- if (!shape) continue
44
-
45
- const canCull = editor.getShapeUtil(shape.type).canCull(shape)
46
- if (!canCull) continue
47
-
48
- nextValue.add(id)
49
- }
35
+ const nextValue = fromScratch(editor)
50
36
 
51
37
  if (isUninitialized(prevValue)) {
52
38
  return nextValue
@@ -1,7 +1,7 @@
1
1
  import { Computed, computed, isUninitialized, RESET_VALUE } from '@tldraw/state'
2
2
  import { CollectionDiff, RecordsDiff } from '@tldraw/store'
3
- import { isShape, TLParentId, TLRecord, TLShape, TLShapeId, TLStore } from '@tldraw/tlschema'
4
- import { sortByIndex } from '@tldraw/utils'
3
+ import { isShape, TLParentId, TLRecord, TLShapeId, TLStore } from '@tldraw/tlschema'
4
+ import { compact, sortByIndex } from '@tldraw/utils'
5
5
 
6
6
  type ParentShapeIdsToChildShapeIds = Record<TLParentId, TLShapeId[]>
7
7
 
@@ -98,23 +98,12 @@ export const parentsToChildren = (store: TLStore) => {
98
98
  }
99
99
  }
100
100
 
101
- // Sort the arrays that have been marked for sorting (in-place to avoid intermediate arrays)
101
+ // Sort the arrays that have been marked for sorting
102
102
  for (const arr of toSort) {
103
- // Filter out any deleted shapes in-place
104
- let writeIdx = 0
105
- for (let readIdx = 0; readIdx < arr.length; readIdx++) {
106
- if (store.get(arr[readIdx])) {
107
- arr[writeIdx++] = arr[readIdx]
108
- }
109
- }
110
- arr.length = writeIdx
111
-
112
- // Sort in-place by index
113
- arr.sort((a, b) => {
114
- const shapeA = store.get(a) as TLShape
115
- const shapeB = store.get(b) as TLShape
116
- return sortByIndex(shapeA, shapeB)
117
- })
103
+ // It's possible that some of the shapes may be deleted. But in which case would this be so?
104
+ const shapesInArr = compact(arr.map((id) => store.get(id)))
105
+ shapesInArr.sort(sortByIndex)
106
+ arr.splice(0, arr.length, ...shapesInArr.map((shape) => shape.id))
118
107
  }
119
108
 
120
109
  return newValue ?? lastValue
@@ -1,5 +1,4 @@
1
1
  import { Mocked, vi } from 'vitest'
2
- import { Vec } from '../../../primitives/Vec'
3
2
  import { Editor } from '../../Editor'
4
3
  import { TLClickEventInfo, TLPointerEventInfo } from '../../types/event-types'
5
4
  import { ClickManager } from './ClickManager'
@@ -36,8 +35,6 @@ describe('ClickManager', () => {
36
35
  setTimeout: vi.fn((fn, delay) => setTimeout(fn, delay)),
37
36
  }
38
37
 
39
- const mockCurrentScreenPoint = new Vec(0, 0)
40
-
41
38
  editor = {
42
39
  timers: mockTimers,
43
40
  dispatch: vi.fn(),
@@ -48,8 +45,7 @@ describe('ClickManager', () => {
48
45
  coarseDragDistanceSquared: 36,
49
46
  },
50
47
  inputs: {
51
- getCurrentScreenPoint: vi.fn(() => mockCurrentScreenPoint),
52
- currentScreenPoint: mockCurrentScreenPoint, // deprecated getter for compatibility
48
+ currentScreenPoint: { x: 0, y: 0 },
53
49
  },
54
50
  getInstanceState: vi.fn(() => ({
55
51
  isCoarsePointer: false,
@@ -325,9 +321,8 @@ describe('ClickManager', () => {
325
321
  const downEvent = createPointerEvent('pointer_down', { x: 0, y: 0 })
326
322
  const moveEvent = createPointerEvent('pointer_move', { x: 10, y: 10 })
327
323
 
328
- const currentScreenPoint = editor.inputs.getCurrentScreenPoint()
329
- currentScreenPoint.x = 10
330
- currentScreenPoint.y = 10
324
+ editor.inputs.currentScreenPoint.x = 10
325
+ editor.inputs.currentScreenPoint.y = 10
331
326
 
332
327
  clickManager.handlePointerEvent(downEvent)
333
328
  expect(clickManager.clickState).toBe('pendingDouble')
@@ -352,15 +347,13 @@ describe('ClickManager', () => {
352
347
  expect(clickManager.clickState).toBe('pendingDouble')
353
348
 
354
349
  // Should not cancel for coarse pointer with small movement
355
- const currentScreenPoint1 = editor.inputs.getCurrentScreenPoint()
356
- currentScreenPoint1.x = 1
357
- currentScreenPoint1.y = 1
350
+ editor.inputs.currentScreenPoint.x = 1
351
+ editor.inputs.currentScreenPoint.y = 1
358
352
  clickManager.handlePointerEvent(moveEvent1)
359
353
  expect(clickManager.clickState).toBe('pendingDouble')
360
354
 
361
- const currentScreenPoint2 = editor.inputs.getCurrentScreenPoint()
362
- currentScreenPoint2.x = 5
363
- currentScreenPoint2.y = 5
355
+ editor.inputs.currentScreenPoint.x = 5
356
+ editor.inputs.currentScreenPoint.y = 5
364
357
  clickManager.handlePointerEvent(moveEvent2)
365
358
 
366
359
  expect(clickManager.clickState).toBe('idle')
@@ -369,9 +362,8 @@ describe('ClickManager', () => {
369
362
  it('should not cancel in idle state', () => {
370
363
  const moveEvent = createPointerEvent('pointer_move', { x: 100, y: 100 })
371
364
 
372
- const currentScreenPoint = editor.inputs.getCurrentScreenPoint()
373
- currentScreenPoint.x = 100
374
- currentScreenPoint.y = 100
365
+ editor.inputs.currentScreenPoint.x = 100
366
+ editor.inputs.currentScreenPoint.y = 100
375
367
 
376
368
  clickManager.handlePointerEvent(moveEvent)
377
369
 
@@ -409,6 +401,28 @@ describe('ClickManager', () => {
409
401
  })
410
402
 
411
403
  describe('edge cases', () => {
404
+ it('should handle null click state gracefully', () => {
405
+ // Force null state
406
+ ;(clickManager as any)._clickState = null
407
+
408
+ const pointerEvent = createPointerEvent('pointer_down', { x: 100, y: 100 })
409
+ const result = clickManager.handlePointerEvent(pointerEvent)
410
+
411
+ expect(result).toBe(pointerEvent)
412
+ })
413
+
414
+ it('should handle missing previous screen point', () => {
415
+ const firstDown = createPointerEvent('pointer_down', { x: 0, y: 0 })
416
+
417
+ // Clear previous point
418
+ ;(clickManager as any)._previousScreenPoint = undefined
419
+
420
+ const result = clickManager.handlePointerEvent(firstDown)
421
+
422
+ expect(result).toBe(firstDown)
423
+ expect(clickManager.clickState).toBe('pendingDouble')
424
+ })
425
+
412
426
  it('should handle overflow state correctly', () => {
413
427
  const pointerDown = createPointerEvent('pointer_down', { x: 100, y: 100 })
414
428
  const pointerUp = createPointerEvent('pointer_up', { x: 100, y: 100 })
@@ -197,7 +197,7 @@ export class ClickManager {
197
197
  if (
198
198
  this._clickState !== 'idle' &&
199
199
  this._clickScreenPoint &&
200
- Vec.Dist2(this._clickScreenPoint, this.editor.inputs.getCurrentScreenPoint()) >
200
+ Vec.Dist2(this._clickScreenPoint, this.editor.inputs.currentScreenPoint) >
201
201
  (this.editor.getInstanceState().isCoarsePointer
202
202
  ? this.editor.options.coarseDragDistanceSquared
203
203
  : this.editor.options.dragDistanceSquared)