@tldraw/editor 4.3.0-next.f4772c19540d → 4.4.0-canary.1e3b436e33e4

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 (206) hide show
  1. package/README.md +1 -1
  2. package/dist-cjs/index.d.ts +503 -155
  3. package/dist-cjs/index.js +8 -1
  4. package/dist-cjs/index.js.map +2 -2
  5. package/dist-cjs/lib/components/ErrorBoundary.js.map +1 -1
  6. package/dist-cjs/lib/components/GeometryDebuggingView.js +1 -17
  7. package/dist-cjs/lib/components/GeometryDebuggingView.js.map +2 -2
  8. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +4 -5
  9. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  10. package/dist-cjs/lib/constants.js +1 -3
  11. package/dist-cjs/lib/constants.js.map +2 -2
  12. package/dist-cjs/lib/editor/Editor.js +346 -291
  13. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  14. package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +2 -2
  15. package/dist-cjs/lib/editor/derivations/bindingsIndex.js.map +2 -2
  16. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +16 -23
  17. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +3 -3
  18. package/dist-cjs/lib/editor/derivations/parentsToChildren.js +12 -3
  19. package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
  20. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +1 -1
  21. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
  22. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +5 -6
  23. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
  24. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +591 -0
  25. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +7 -0
  26. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +1 -1
  27. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
  28. package/dist-cjs/lib/editor/managers/SpatialIndexManager/RBushIndex.js +144 -0
  29. package/dist-cjs/lib/editor/managers/SpatialIndexManager/RBushIndex.js.map +7 -0
  30. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +181 -0
  31. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +7 -0
  32. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +1 -22
  33. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +2 -2
  34. package/dist-cjs/lib/editor/shapes/BaseBoxShapeUtil.js.map +1 -1
  35. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +31 -23
  36. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  37. package/dist-cjs/lib/editor/shapes/group/DashedOutlineBox.js +1 -1
  38. package/dist-cjs/lib/editor/shapes/group/DashedOutlineBox.js.map +2 -2
  39. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
  40. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.js.map +2 -2
  41. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +3 -3
  42. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
  43. package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
  44. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  45. package/dist-cjs/lib/exports/parseCss.js +1 -1
  46. package/dist-cjs/lib/exports/parseCss.js.map +2 -2
  47. package/dist-cjs/lib/globals/environment.js +45 -9
  48. package/dist-cjs/lib/globals/environment.js.map +2 -2
  49. package/dist-cjs/lib/globals/menus.js +1 -1
  50. package/dist-cjs/lib/globals/menus.js.map +2 -2
  51. package/dist-cjs/lib/hooks/useCoarsePointer.js +14 -29
  52. package/dist-cjs/lib/hooks/useCoarsePointer.js.map +2 -2
  53. package/dist-cjs/lib/hooks/useEvent.js +1 -1
  54. package/dist-cjs/lib/hooks/useEvent.js.map +2 -2
  55. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
  56. package/dist-cjs/lib/hooks/useGestureEvents.js +1 -1
  57. package/dist-cjs/lib/hooks/useGestureEvents.js.map +2 -2
  58. package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +2 -2
  59. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
  60. package/dist-cjs/lib/hooks/useScreenBounds.js.map +2 -2
  61. package/dist-cjs/lib/hooks/useStateAttribute.js +4 -1
  62. package/dist-cjs/lib/hooks/useStateAttribute.js.map +2 -2
  63. package/dist-cjs/lib/hooks/useTransform.js.map +1 -1
  64. package/dist-cjs/lib/hooks/useZoomCss.js +4 -8
  65. package/dist-cjs/lib/hooks/useZoomCss.js.map +2 -2
  66. package/dist-cjs/lib/options.js +6 -1
  67. package/dist-cjs/lib/options.js.map +2 -2
  68. package/dist-cjs/lib/primitives/Box.js +3 -0
  69. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  70. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +1 -0
  71. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  72. package/dist-cjs/lib/utils/reparenting.js.map +2 -2
  73. package/dist-cjs/lib/utils/rotation.js +1 -1
  74. package/dist-cjs/lib/utils/rotation.js.map +2 -2
  75. package/dist-cjs/version.js +3 -3
  76. package/dist-cjs/version.js.map +1 -1
  77. package/dist-esm/index.d.mts +503 -155
  78. package/dist-esm/index.mjs +9 -2
  79. package/dist-esm/index.mjs.map +2 -2
  80. package/dist-esm/lib/components/ErrorBoundary.mjs.map +1 -1
  81. package/dist-esm/lib/components/GeometryDebuggingView.mjs +1 -17
  82. package/dist-esm/lib/components/GeometryDebuggingView.mjs.map +2 -2
  83. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +4 -5
  84. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  85. package/dist-esm/lib/constants.mjs +1 -3
  86. package/dist-esm/lib/constants.mjs.map +2 -2
  87. package/dist-esm/lib/editor/Editor.mjs +347 -294
  88. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  89. package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +2 -2
  90. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs.map +2 -2
  91. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +16 -23
  92. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +3 -3
  93. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +13 -4
  94. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
  95. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +1 -1
  96. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
  97. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +5 -6
  98. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
  99. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +573 -0
  100. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +7 -0
  101. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +1 -1
  102. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
  103. package/dist-esm/lib/editor/managers/SpatialIndexManager/RBushIndex.mjs +114 -0
  104. package/dist-esm/lib/editor/managers/SpatialIndexManager/RBushIndex.mjs.map +7 -0
  105. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +161 -0
  106. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +7 -0
  107. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +1 -22
  108. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +2 -2
  109. package/dist-esm/lib/editor/shapes/BaseBoxShapeUtil.mjs.map +1 -1
  110. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +31 -23
  111. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  112. package/dist-esm/lib/editor/shapes/group/DashedOutlineBox.mjs +1 -1
  113. package/dist-esm/lib/editor/shapes/group/DashedOutlineBox.mjs.map +2 -2
  114. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
  115. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.mjs.map +2 -2
  116. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +3 -3
  117. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
  118. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  119. package/dist-esm/lib/exports/parseCss.mjs +1 -1
  120. package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
  121. package/dist-esm/lib/globals/environment.mjs +45 -9
  122. package/dist-esm/lib/globals/environment.mjs.map +2 -2
  123. package/dist-esm/lib/globals/menus.mjs +1 -1
  124. package/dist-esm/lib/globals/menus.mjs.map +2 -2
  125. package/dist-esm/lib/hooks/useCoarsePointer.mjs +15 -30
  126. package/dist-esm/lib/hooks/useCoarsePointer.mjs.map +2 -2
  127. package/dist-esm/lib/hooks/useEvent.mjs +1 -1
  128. package/dist-esm/lib/hooks/useEvent.mjs.map +2 -2
  129. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
  130. package/dist-esm/lib/hooks/useGestureEvents.mjs +1 -1
  131. package/dist-esm/lib/hooks/useGestureEvents.mjs.map +2 -2
  132. package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +2 -2
  133. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
  134. package/dist-esm/lib/hooks/useScreenBounds.mjs.map +2 -2
  135. package/dist-esm/lib/hooks/useStateAttribute.mjs +4 -1
  136. package/dist-esm/lib/hooks/useStateAttribute.mjs.map +2 -2
  137. package/dist-esm/lib/hooks/useTransform.mjs.map +1 -1
  138. package/dist-esm/lib/hooks/useZoomCss.mjs +4 -8
  139. package/dist-esm/lib/hooks/useZoomCss.mjs.map +2 -2
  140. package/dist-esm/lib/options.mjs +6 -1
  141. package/dist-esm/lib/options.mjs.map +2 -2
  142. package/dist-esm/lib/primitives/Box.mjs +3 -0
  143. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  144. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +1 -0
  145. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  146. package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
  147. package/dist-esm/lib/utils/rotation.mjs +1 -1
  148. package/dist-esm/lib/utils/rotation.mjs.map +2 -2
  149. package/dist-esm/version.mjs +3 -3
  150. package/dist-esm/version.mjs.map +1 -1
  151. package/editor.css +14 -12
  152. package/package.json +21 -17
  153. package/src/index.ts +5 -1
  154. package/src/lib/components/ErrorBoundary.tsx +1 -1
  155. package/src/lib/components/GeometryDebuggingView.tsx +1 -19
  156. package/src/lib/components/default-components/DefaultCanvas.tsx +5 -8
  157. package/src/lib/config/TLUserPreferences.test.ts +40 -0
  158. package/src/lib/constants.ts +0 -2
  159. package/src/lib/editor/Editor.test.ts +150 -10
  160. package/src/lib/editor/Editor.ts +533 -384
  161. package/src/lib/editor/bindings/BindingUtil.ts +15 -9
  162. package/src/lib/editor/derivations/bindingsIndex.ts +2 -2
  163. package/src/lib/editor/derivations/notVisibleShapes.ts +21 -33
  164. package/src/lib/editor/derivations/parentsToChildren.ts +18 -7
  165. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +17 -31
  166. package/src/lib/editor/managers/ClickManager/ClickManager.ts +1 -1
  167. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +129 -79
  168. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +10 -6
  169. package/src/lib/editor/managers/FontManager/FontManager.test.ts +14 -4
  170. package/src/lib/editor/managers/InputsManager/InputsManager.ts +566 -0
  171. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +0 -4
  172. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +12 -0
  173. package/src/lib/editor/managers/SnapManager/SnapManager.ts +4 -4
  174. package/src/lib/editor/managers/SpatialIndexManager/RBushIndex.ts +144 -0
  175. package/src/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.ts +215 -0
  176. package/src/lib/editor/managers/TickManager/TickManager.test.ts +40 -107
  177. package/src/lib/editor/managers/TickManager/TickManager.ts +2 -32
  178. package/src/lib/editor/shapes/BaseBoxShapeUtil.tsx +2 -2
  179. package/src/lib/editor/shapes/ShapeUtil.ts +72 -32
  180. package/src/lib/editor/shapes/group/DashedOutlineBox.tsx +1 -1
  181. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +1 -3
  182. package/src/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.ts +2 -1
  183. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +6 -6
  184. package/src/lib/editor/types/emit-types.ts +3 -1
  185. package/src/lib/exports/getSvgJsx.test.ts +10 -19
  186. package/src/lib/exports/getSvgJsx.tsx +2 -5
  187. package/src/lib/exports/parseCss.test.ts +1 -0
  188. package/src/lib/exports/parseCss.ts +1 -1
  189. package/src/lib/globals/environment.ts +65 -10
  190. package/src/lib/globals/menus.ts +1 -1
  191. package/src/lib/hooks/useCoarsePointer.ts +16 -59
  192. package/src/lib/hooks/useEvent.tsx +1 -1
  193. package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +1 -1
  194. package/src/lib/hooks/useGestureEvents.ts +2 -2
  195. package/src/lib/hooks/usePassThroughMouseOverEvents.ts +1 -1
  196. package/src/lib/hooks/usePassThroughWheelEvents.ts +1 -1
  197. package/src/lib/hooks/useScreenBounds.ts +1 -1
  198. package/src/lib/hooks/useStateAttribute.ts +4 -1
  199. package/src/lib/hooks/useTransform.ts +1 -1
  200. package/src/lib/hooks/useZoomCss.ts +3 -8
  201. package/src/lib/options.ts +32 -0
  202. package/src/lib/primitives/Box.ts +9 -0
  203. package/src/lib/primitives/geometry/Geometry2d.ts +1 -0
  204. package/src/lib/utils/reparenting.ts +5 -5
  205. package/src/lib/utils/rotation.ts +1 -1
  206. package/src/version.ts +3 -3
@@ -0,0 +1,114 @@
1
+ import RBush from "rbush";
2
+ import { Box } from "../../../primitives/Box.mjs";
3
+ class TldrawRBush extends RBush {
4
+ }
5
+ class RBushIndex {
6
+ rBush;
7
+ elementsInTree;
8
+ constructor() {
9
+ this.rBush = new TldrawRBush();
10
+ this.elementsInTree = /* @__PURE__ */ new Map();
11
+ }
12
+ /**
13
+ * Search for shapes within the given bounds.
14
+ * Returns set of shape IDs that intersect with the bounds.
15
+ */
16
+ search(bounds) {
17
+ const results = this.rBush.search({
18
+ minX: bounds.minX,
19
+ minY: bounds.minY,
20
+ maxX: bounds.maxX,
21
+ maxY: bounds.maxY
22
+ });
23
+ return new Set(results.map((e) => e.id));
24
+ }
25
+ /**
26
+ * Insert or update a shape in the spatial index.
27
+ * If the shape already exists, it will be removed first to prevent duplicates.
28
+ */
29
+ upsert(id, bounds) {
30
+ const existing = this.elementsInTree.get(id);
31
+ if (existing) {
32
+ this.rBush.remove(existing);
33
+ }
34
+ const element = {
35
+ minX: bounds.minX,
36
+ minY: bounds.minY,
37
+ maxX: bounds.maxX,
38
+ maxY: bounds.maxY,
39
+ id
40
+ };
41
+ this.rBush.insert(element);
42
+ this.elementsInTree.set(id, element);
43
+ }
44
+ /**
45
+ * Remove a shape from the spatial index.
46
+ */
47
+ remove(id) {
48
+ const element = this.elementsInTree.get(id);
49
+ if (element) {
50
+ this.rBush.remove(element);
51
+ this.elementsInTree.delete(id);
52
+ }
53
+ }
54
+ /**
55
+ * Bulk load elements into the spatial index.
56
+ * More efficient than individual inserts for initial loading.
57
+ */
58
+ bulkLoad(elements) {
59
+ this.rBush.load(elements);
60
+ for (const element of elements) {
61
+ this.elementsInTree.set(element.id, element);
62
+ }
63
+ }
64
+ /**
65
+ * Clear all elements from the spatial index.
66
+ */
67
+ clear() {
68
+ this.rBush.clear();
69
+ this.elementsInTree.clear();
70
+ }
71
+ /**
72
+ * Check if a shape is in the spatial index.
73
+ */
74
+ has(id) {
75
+ return this.elementsInTree.has(id);
76
+ }
77
+ /**
78
+ * Get the number of elements in the spatial index.
79
+ */
80
+ getSize() {
81
+ return this.elementsInTree.size;
82
+ }
83
+ /**
84
+ * Get all shape IDs currently in the spatial index.
85
+ */
86
+ getAllShapeIds() {
87
+ return Array.from(this.elementsInTree.keys());
88
+ }
89
+ /**
90
+ * Get the bounds currently stored in the spatial index for a shape.
91
+ * Returns undefined if the shape is not in the index.
92
+ */
93
+ getBounds(id) {
94
+ const element = this.elementsInTree.get(id);
95
+ if (!element) return void 0;
96
+ return new Box(
97
+ element.minX,
98
+ element.minY,
99
+ element.maxX - element.minX,
100
+ element.maxY - element.minY
101
+ );
102
+ }
103
+ /**
104
+ * Dispose of the spatial index.
105
+ * Clears all data structures to prevent memory leaks.
106
+ */
107
+ dispose() {
108
+ this.clear();
109
+ }
110
+ }
111
+ export {
112
+ RBushIndex
113
+ };
114
+ //# sourceMappingURL=RBushIndex.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/lib/editor/managers/SpatialIndexManager/RBushIndex.ts"],
4
+ "sourcesContent": ["import type { TLShapeId } from '@tldraw/tlschema'\nimport RBush from 'rbush'\nimport { Box } from '../../../primitives/Box'\n\n/**\n * Element stored in the R-tree spatial index.\n * Contains bounds (minX, minY, maxX, maxY) and shape ID.\n */\nexport interface SpatialElement {\n\tminX: number\n\tminY: number\n\tmaxX: number\n\tmaxY: number\n\tid: TLShapeId\n}\n\n/**\n * Custom RBush class for tldraw shapes.\n */\nclass TldrawRBush extends RBush<SpatialElement> {}\n\n/**\n * Wrapper around RBush R-tree for efficient spatial queries.\n * Maintains a map of elements currently in the tree for efficient updates.\n */\nexport class RBushIndex {\n\tprivate rBush: TldrawRBush\n\tprivate elementsInTree: Map<TLShapeId, SpatialElement>\n\n\tconstructor() {\n\t\tthis.rBush = new TldrawRBush()\n\t\tthis.elementsInTree = new Map()\n\t}\n\n\t/**\n\t * Search for shapes within the given bounds.\n\t * Returns set of shape IDs that intersect with the bounds.\n\t */\n\tsearch(bounds: Box): Set<TLShapeId> {\n\t\tconst results = this.rBush.search({\n\t\t\tminX: bounds.minX,\n\t\t\tminY: bounds.minY,\n\t\t\tmaxX: bounds.maxX,\n\t\t\tmaxY: bounds.maxY,\n\t\t})\n\t\treturn new Set(results.map((e: SpatialElement) => e.id))\n\t}\n\n\t/**\n\t * Insert or update a shape in the spatial index.\n\t * If the shape already exists, it will be removed first to prevent duplicates.\n\t */\n\tupsert(id: TLShapeId, bounds: Box): void {\n\t\t// Remove existing entry to prevent map-tree desync\n\t\tconst existing = this.elementsInTree.get(id)\n\t\tif (existing) {\n\t\t\tthis.rBush.remove(existing)\n\t\t}\n\n\t\tconst element: SpatialElement = {\n\t\t\tminX: bounds.minX,\n\t\t\tminY: bounds.minY,\n\t\t\tmaxX: bounds.maxX,\n\t\t\tmaxY: bounds.maxY,\n\t\t\tid,\n\t\t}\n\t\tthis.rBush.insert(element)\n\t\tthis.elementsInTree.set(id, element)\n\t}\n\n\t/**\n\t * Remove a shape from the spatial index.\n\t */\n\tremove(id: TLShapeId): void {\n\t\tconst element = this.elementsInTree.get(id)\n\t\tif (element) {\n\t\t\tthis.rBush.remove(element)\n\t\t\tthis.elementsInTree.delete(id)\n\t\t}\n\t}\n\n\t/**\n\t * Bulk load elements into the spatial index.\n\t * More efficient than individual inserts for initial loading.\n\t */\n\tbulkLoad(elements: SpatialElement[]): void {\n\t\tthis.rBush.load(elements)\n\t\tfor (const element of elements) {\n\t\t\tthis.elementsInTree.set(element.id, element)\n\t\t}\n\t}\n\n\t/**\n\t * Clear all elements from the spatial index.\n\t */\n\tclear(): void {\n\t\tthis.rBush.clear()\n\t\tthis.elementsInTree.clear()\n\t}\n\n\t/**\n\t * Check if a shape is in the spatial index.\n\t */\n\thas(id: TLShapeId): boolean {\n\t\treturn this.elementsInTree.has(id)\n\t}\n\n\t/**\n\t * Get the number of elements in the spatial index.\n\t */\n\tgetSize(): number {\n\t\treturn this.elementsInTree.size\n\t}\n\n\t/**\n\t * Get all shape IDs currently in the spatial index.\n\t */\n\tgetAllShapeIds(): TLShapeId[] {\n\t\treturn Array.from(this.elementsInTree.keys())\n\t}\n\n\t/**\n\t * Get the bounds currently stored in the spatial index for a shape.\n\t * Returns undefined if the shape is not in the index.\n\t */\n\tgetBounds(id: TLShapeId): Box | undefined {\n\t\tconst element = this.elementsInTree.get(id)\n\t\tif (!element) return undefined\n\t\treturn new Box(\n\t\t\telement.minX,\n\t\t\telement.minY,\n\t\t\telement.maxX - element.minX,\n\t\t\telement.maxY - element.minY\n\t\t)\n\t}\n\n\t/**\n\t * Dispose of the spatial index.\n\t * Clears all data structures to prevent memory leaks.\n\t */\n\tdispose(): void {\n\t\tthis.clear()\n\t}\n}\n"],
5
+ "mappings": "AACA,OAAO,WAAW;AAClB,SAAS,WAAW;AAiBpB,MAAM,oBAAoB,MAAsB;AAAC;AAM1C,MAAM,WAAW;AAAA,EACf;AAAA,EACA;AAAA,EAER,cAAc;AACb,SAAK,QAAQ,IAAI,YAAY;AAC7B,SAAK,iBAAiB,oBAAI,IAAI;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,QAA6B;AACnC,UAAM,UAAU,KAAK,MAAM,OAAO;AAAA,MACjC,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,IACd,CAAC;AACD,WAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAsB,EAAE,EAAE,CAAC;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,IAAe,QAAmB;AAExC,UAAM,WAAW,KAAK,eAAe,IAAI,EAAE;AAC3C,QAAI,UAAU;AACb,WAAK,MAAM,OAAO,QAAQ;AAAA,IAC3B;AAEA,UAAM,UAA0B;AAAA,MAC/B,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,MACb;AAAA,IACD;AACA,SAAK,MAAM,OAAO,OAAO;AACzB,SAAK,eAAe,IAAI,IAAI,OAAO;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,IAAqB;AAC3B,UAAM,UAAU,KAAK,eAAe,IAAI,EAAE;AAC1C,QAAI,SAAS;AACZ,WAAK,MAAM,OAAO,OAAO;AACzB,WAAK,eAAe,OAAO,EAAE;AAAA,IAC9B;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS,UAAkC;AAC1C,SAAK,MAAM,KAAK,QAAQ;AACxB,eAAW,WAAW,UAAU;AAC/B,WAAK,eAAe,IAAI,QAAQ,IAAI,OAAO;AAAA,IAC5C;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACb,SAAK,MAAM,MAAM;AACjB,SAAK,eAAe,MAAM;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,IAAwB;AAC3B,WAAO,KAAK,eAAe,IAAI,EAAE;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,UAAkB;AACjB,WAAO,KAAK,eAAe;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,iBAA8B;AAC7B,WAAO,MAAM,KAAK,KAAK,eAAe,KAAK,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,IAAgC;AACzC,UAAM,UAAU,KAAK,eAAe,IAAI,EAAE;AAC1C,QAAI,CAAC,QAAS,QAAO;AACrB,WAAO,IAAI;AAAA,MACV,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ,OAAO,QAAQ;AAAA,MACvB,QAAQ,OAAO,QAAQ;AAAA,IACxB;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAgB;AACf,SAAK,MAAM;AAAA,EACZ;AACD;",
6
+ "names": []
7
+ }
@@ -0,0 +1,161 @@
1
+ import { RESET_VALUE, computed, isUninitialized } from "@tldraw/state";
2
+ import { isShape } from "@tldraw/tlschema";
3
+ import { objectMapValues } from "@tldraw/utils";
4
+ import { Box } from "../../../primitives/Box.mjs";
5
+ import { RBushIndex } from "./RBushIndex.mjs";
6
+ class SpatialIndexManager {
7
+ constructor(editor) {
8
+ this.editor = editor;
9
+ this.rbush = new RBushIndex();
10
+ this.spatialIndexComputed = this.createSpatialIndexComputed();
11
+ }
12
+ rbush;
13
+ spatialIndexComputed;
14
+ lastPageId = null;
15
+ createSpatialIndexComputed() {
16
+ const shapeHistory = this.editor.store.query.filterHistory("shape");
17
+ return computed("spatialIndex", (_prevValue, lastComputedEpoch) => {
18
+ if (isUninitialized(_prevValue)) {
19
+ return this.buildFromScratch(lastComputedEpoch);
20
+ }
21
+ const shapeDiff = shapeHistory.getDiffSince(lastComputedEpoch);
22
+ if (shapeDiff === RESET_VALUE) {
23
+ return this.buildFromScratch(lastComputedEpoch);
24
+ }
25
+ const currentPageId = this.editor.getCurrentPageId();
26
+ if (this.lastPageId !== currentPageId) {
27
+ return this.buildFromScratch(lastComputedEpoch);
28
+ }
29
+ if (shapeDiff.length === 0) {
30
+ return lastComputedEpoch;
31
+ }
32
+ this.processIncrementalUpdate(shapeDiff);
33
+ return lastComputedEpoch;
34
+ });
35
+ }
36
+ buildFromScratch(epoch) {
37
+ this.rbush.clear();
38
+ this.lastPageId = this.editor.getCurrentPageId();
39
+ const shapes = this.editor.getCurrentPageShapes();
40
+ const elements = [];
41
+ for (const shape of shapes) {
42
+ const bounds = this.editor.getShapePageBounds(shape.id);
43
+ if (bounds) {
44
+ elements.push({
45
+ minX: bounds.minX,
46
+ minY: bounds.minY,
47
+ maxX: bounds.maxX,
48
+ maxY: bounds.maxY,
49
+ id: shape.id
50
+ });
51
+ }
52
+ }
53
+ this.rbush.bulkLoad(elements);
54
+ return epoch;
55
+ }
56
+ processIncrementalUpdate(shapeDiff) {
57
+ const processedShapeIds = /* @__PURE__ */ new Set();
58
+ for (const changes of shapeDiff) {
59
+ for (const shape of objectMapValues(changes.added)) {
60
+ if (isShape(shape) && this.editor.getAncestorPageId(shape) === this.lastPageId) {
61
+ const bounds = this.editor.getShapePageBounds(shape.id);
62
+ if (bounds) {
63
+ this.rbush.upsert(shape.id, bounds);
64
+ }
65
+ processedShapeIds.add(shape.id);
66
+ }
67
+ }
68
+ for (const shape of objectMapValues(changes.removed)) {
69
+ if (isShape(shape)) {
70
+ this.rbush.remove(shape.id);
71
+ processedShapeIds.add(shape.id);
72
+ }
73
+ }
74
+ for (const [from, to] of objectMapValues(changes.updated)) {
75
+ if (!isShape(to)) continue;
76
+ processedShapeIds.add(to.id);
77
+ const wasOnPage = this.editor.getAncestorPageId(from) === this.lastPageId;
78
+ const isOnPage = this.editor.getAncestorPageId(to) === this.lastPageId;
79
+ if (isOnPage) {
80
+ const bounds = this.editor.getShapePageBounds(to.id);
81
+ if (bounds) {
82
+ this.rbush.upsert(to.id, bounds);
83
+ }
84
+ } else if (wasOnPage) {
85
+ this.rbush.remove(to.id);
86
+ }
87
+ }
88
+ }
89
+ const allShapeIds = this.rbush.getAllShapeIds();
90
+ for (const shapeId of allShapeIds) {
91
+ if (processedShapeIds.has(shapeId)) continue;
92
+ const currentBounds = this.editor.getShapePageBounds(shapeId);
93
+ const indexedBounds = this.rbush.getBounds(shapeId);
94
+ if (!this.areBoundsEqual(currentBounds, indexedBounds)) {
95
+ if (currentBounds) {
96
+ this.rbush.upsert(shapeId, currentBounds);
97
+ } else {
98
+ this.rbush.remove(shapeId);
99
+ }
100
+ }
101
+ }
102
+ }
103
+ areBoundsEqual(a, b) {
104
+ if (!a && !b) return true;
105
+ if (!a || !b) return false;
106
+ return a.minX === b.minX && a.minY === b.minY && a.maxX === b.maxX && a.maxY === b.maxY;
107
+ }
108
+ /**
109
+ * Get shape IDs within the given bounds.
110
+ * Optimized for viewport culling queries.
111
+ *
112
+ * Note: Results are unordered. If you need z-order, combine with sorted shapes:
113
+ * ```ts
114
+ * const candidates = editor.spatialIndex.getShapeIdsInsideBounds(bounds)
115
+ * const sorted = editor.getCurrentPageShapesSorted().filter(s => candidates.has(s.id))
116
+ * ```
117
+ *
118
+ * @param bounds - The bounds to search within
119
+ * @returns Unordered set of shape IDs within the bounds
120
+ *
121
+ * @public
122
+ */
123
+ getShapeIdsInsideBounds(bounds) {
124
+ this.spatialIndexComputed.get();
125
+ return this.rbush.search(bounds);
126
+ }
127
+ /**
128
+ * Get shape IDs at a point (with optional margin).
129
+ * Creates a small bounding box around the point and searches the spatial index.
130
+ *
131
+ * Note: Results are unordered. If you need z-order, combine with sorted shapes:
132
+ * ```ts
133
+ * const candidates = editor.spatialIndex.getShapeIdsAtPoint(point, margin)
134
+ * const sorted = editor.getCurrentPageShapesSorted().filter(s => candidates.has(s.id))
135
+ * ```
136
+ *
137
+ * @param point - The point to search at
138
+ * @param margin - The margin around the point to search (default: 0)
139
+ * @returns Unordered set of shape IDs that could potentially contain the point
140
+ *
141
+ * @public
142
+ */
143
+ getShapeIdsAtPoint(point, margin = 0) {
144
+ this.spatialIndexComputed.get();
145
+ return this.rbush.search(new Box(point.x - margin, point.y - margin, margin * 2, margin * 2));
146
+ }
147
+ /**
148
+ * Dispose of the spatial index manager.
149
+ * Clears the R-tree to prevent memory leaks.
150
+ *
151
+ * @public
152
+ */
153
+ dispose() {
154
+ this.rbush.dispose();
155
+ this.lastPageId = null;
156
+ }
157
+ }
158
+ export {
159
+ SpatialIndexManager
160
+ };
161
+ //# sourceMappingURL=SpatialIndexManager.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.ts"],
4
+ "sourcesContent": ["import { Computed, RESET_VALUE, computed, isUninitialized } from '@tldraw/state'\nimport type { RecordsDiff } from '@tldraw/store'\nimport type { TLRecord } from '@tldraw/tlschema'\nimport { TLPageId, TLShape, TLShapeId, isShape } from '@tldraw/tlschema'\nimport { objectMapValues } from '@tldraw/utils'\nimport { Box } from '../../../primitives/Box'\nimport type { Editor } from '../../Editor'\nimport { RBushIndex, type SpatialElement } from './RBushIndex'\n\n/**\n * Manages spatial indexing for efficient shape location queries.\n *\n * Uses an R-tree (via RBush) to enable O(log n) spatial queries instead of O(n) iteration.\n * Handles shapes with computed bounds (arrows, groups, custom shapes) by checking all shapes'\n * bounds on each update using the reactive bounds cache.\n *\n * Key features:\n * - Incremental updates using filterHistory pattern\n * - Leverages existing bounds cache reactivity for dependency tracking\n * - Works with any custom shape type with computed bounds\n * - Per-page index (rebuilds on page change)\n * - Optimized for viewport culling queries\n *\n * @internal\n */\nexport class SpatialIndexManager {\n\tprivate rbush: RBushIndex\n\tprivate spatialIndexComputed: Computed<number>\n\tprivate lastPageId: TLPageId | null = null\n\n\tconstructor(public readonly editor: Editor) {\n\t\tthis.rbush = new RBushIndex()\n\t\tthis.spatialIndexComputed = this.createSpatialIndexComputed()\n\t}\n\n\tprivate createSpatialIndexComputed() {\n\t\tconst shapeHistory = this.editor.store.query.filterHistory('shape')\n\n\t\treturn computed<number>('spatialIndex', (_prevValue, lastComputedEpoch) => {\n\t\t\tif (isUninitialized(_prevValue)) {\n\t\t\t\treturn this.buildFromScratch(lastComputedEpoch)\n\t\t\t}\n\n\t\t\tconst shapeDiff = shapeHistory.getDiffSince(lastComputedEpoch)\n\n\t\t\tif (shapeDiff === RESET_VALUE) {\n\t\t\t\treturn this.buildFromScratch(lastComputedEpoch)\n\t\t\t}\n\n\t\t\tconst currentPageId = this.editor.getCurrentPageId()\n\t\t\tif (this.lastPageId !== currentPageId) {\n\t\t\t\treturn this.buildFromScratch(lastComputedEpoch)\n\t\t\t}\n\n\t\t\t// No shape changes - index is already up to date\n\t\t\tif (shapeDiff.length === 0) {\n\t\t\t\treturn lastComputedEpoch\n\t\t\t}\n\n\t\t\t// Process incremental updates\n\t\t\tthis.processIncrementalUpdate(shapeDiff)\n\n\t\t\treturn lastComputedEpoch\n\t\t})\n\t}\n\n\tprivate buildFromScratch(epoch: number): number {\n\t\tthis.rbush.clear()\n\t\tthis.lastPageId = this.editor.getCurrentPageId()\n\n\t\tconst shapes = this.editor.getCurrentPageShapes()\n\t\tconst elements: SpatialElement[] = []\n\n\t\t// Collect all shape elements for bulk loading\n\t\tfor (const shape of shapes) {\n\t\t\tconst bounds = this.editor.getShapePageBounds(shape.id)\n\t\t\tif (bounds) {\n\t\t\t\telements.push({\n\t\t\t\t\tminX: bounds.minX,\n\t\t\t\t\tminY: bounds.minY,\n\t\t\t\t\tmaxX: bounds.maxX,\n\t\t\t\t\tmaxY: bounds.maxY,\n\t\t\t\t\tid: shape.id,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\t// Bulk load for efficiency\n\t\tthis.rbush.bulkLoad(elements)\n\n\t\treturn epoch\n\t}\n\n\tprivate processIncrementalUpdate(shapeDiff: RecordsDiff<TLRecord>[]): void {\n\t\t// Track shapes we've already processed from the diff\n\t\tconst processedShapeIds = new Set<TLShapeId>()\n\n\t\t// 1. Process shape additions, removals, and updates from diff\n\t\tfor (const changes of shapeDiff) {\n\t\t\t// Handle additions (only for shapes on current page)\n\t\t\tfor (const shape of objectMapValues(changes.added) as TLShape[]) {\n\t\t\t\tif (isShape(shape) && this.editor.getAncestorPageId(shape) === this.lastPageId) {\n\t\t\t\t\tconst bounds = this.editor.getShapePageBounds(shape.id)\n\t\t\t\t\tif (bounds) {\n\t\t\t\t\t\tthis.rbush.upsert(shape.id, bounds)\n\t\t\t\t\t}\n\t\t\t\t\tprocessedShapeIds.add(shape.id)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle removals\n\t\t\tfor (const shape of objectMapValues(changes.removed) as TLShape[]) {\n\t\t\t\tif (isShape(shape)) {\n\t\t\t\t\tthis.rbush.remove(shape.id)\n\t\t\t\t\tprocessedShapeIds.add(shape.id)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle updated shapes: page changes and bounds updates\n\t\t\tfor (const [from, to] of objectMapValues(changes.updated) as [TLShape, TLShape][]) {\n\t\t\t\tif (!isShape(to)) continue\n\t\t\t\tprocessedShapeIds.add(to.id)\n\n\t\t\t\tconst wasOnPage = this.editor.getAncestorPageId(from) === this.lastPageId\n\t\t\t\tconst isOnPage = this.editor.getAncestorPageId(to) === this.lastPageId\n\n\t\t\t\tif (isOnPage) {\n\t\t\t\t\tconst bounds = this.editor.getShapePageBounds(to.id)\n\t\t\t\t\tif (bounds) {\n\t\t\t\t\t\tthis.rbush.upsert(to.id, bounds)\n\t\t\t\t\t}\n\t\t\t\t} else if (wasOnPage) {\n\t\t\t\t\tthis.rbush.remove(to.id)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 2. Check remaining shapes in index for bounds changes\n\t\t// This handles shapes with computed bounds (arrows bound to moved shapes, groups with moved children, etc.)\n\t\tconst allShapeIds = this.rbush.getAllShapeIds()\n\n\t\tfor (const shapeId of allShapeIds) {\n\t\t\tif (processedShapeIds.has(shapeId)) continue\n\n\t\t\tconst currentBounds = this.editor.getShapePageBounds(shapeId)\n\t\t\tconst indexedBounds = this.rbush.getBounds(shapeId)\n\n\t\t\tif (!this.areBoundsEqual(currentBounds, indexedBounds)) {\n\t\t\t\tif (currentBounds) {\n\t\t\t\t\tthis.rbush.upsert(shapeId, currentBounds)\n\t\t\t\t} else {\n\t\t\t\t\tthis.rbush.remove(shapeId)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate areBoundsEqual(a: Box | undefined, b: Box | undefined): boolean {\n\t\tif (!a && !b) return true\n\t\tif (!a || !b) return false\n\t\treturn a.minX === b.minX && a.minY === b.minY && a.maxX === b.maxX && a.maxY === b.maxY\n\t}\n\n\t/**\n\t * Get shape IDs within the given bounds.\n\t * Optimized for viewport culling queries.\n\t *\n\t * Note: Results are unordered. If you need z-order, combine with sorted shapes:\n\t * ```ts\n\t * const candidates = editor.spatialIndex.getShapeIdsInsideBounds(bounds)\n\t * const sorted = editor.getCurrentPageShapesSorted().filter(s => candidates.has(s.id))\n\t * ```\n\t *\n\t * @param bounds - The bounds to search within\n\t * @returns Unordered set of shape IDs within the bounds\n\t *\n\t * @public\n\t */\n\tgetShapeIdsInsideBounds(bounds: Box): Set<TLShapeId> {\n\t\tthis.spatialIndexComputed.get()\n\t\treturn this.rbush.search(bounds)\n\t}\n\n\t/**\n\t * Get shape IDs at a point (with optional margin).\n\t * Creates a small bounding box around the point and searches the spatial index.\n\t *\n\t * Note: Results are unordered. If you need z-order, combine with sorted shapes:\n\t * ```ts\n\t * const candidates = editor.spatialIndex.getShapeIdsAtPoint(point, margin)\n\t * const sorted = editor.getCurrentPageShapesSorted().filter(s => candidates.has(s.id))\n\t * ```\n\t *\n\t * @param point - The point to search at\n\t * @param margin - The margin around the point to search (default: 0)\n\t * @returns Unordered set of shape IDs that could potentially contain the point\n\t *\n\t * @public\n\t */\n\tgetShapeIdsAtPoint(point: { x: number; y: number }, margin = 0): Set<TLShapeId> {\n\t\tthis.spatialIndexComputed.get()\n\t\treturn this.rbush.search(new Box(point.x - margin, point.y - margin, margin * 2, margin * 2))\n\t}\n\n\t/**\n\t * Dispose of the spatial index manager.\n\t * Clears the R-tree to prevent memory leaks.\n\t *\n\t * @public\n\t */\n\tdispose(): void {\n\t\tthis.rbush.dispose()\n\t\tthis.lastPageId = null\n\t}\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -48,7 +48,6 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
48
48
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
49
49
  var _dispose_dec, _tick_dec, _init;
50
50
  import { throttleToNextFrame as _throttleToNextFrame, bind } from "@tldraw/utils";
51
- import { Vec } from "../../../primitives/Vec.mjs";
52
51
  const throttleToNextFrame = typeof process !== "undefined" && process.env.NODE_ENV === "test" ? (
53
52
  // At test time we should use actual raf and not throttle, because throttle was set up to evaluate immediately during tests, which causes stack overflow
54
53
  // for the tick manager since it sets up a raf loop.
@@ -65,7 +64,6 @@ class TickManager {
65
64
  __publicField(this, "cancelRaf");
66
65
  __publicField(this, "isPaused", true);
67
66
  __publicField(this, "now", 0);
68
- __publicField(this, "prevPoint", new Vec());
69
67
  this.editor.disposables.add(this.dispose);
70
68
  this.start();
71
69
  }
@@ -82,7 +80,7 @@ class TickManager {
82
80
  const now = Date.now();
83
81
  const elapsed = now - this.now;
84
82
  this.now = now;
85
- this.updatePointerVelocity(elapsed);
83
+ this.editor.inputs.updatePointerVelocity(elapsed);
86
84
  this.editor.emit("frame", elapsed);
87
85
  this.editor.emit("tick", elapsed);
88
86
  this.cancelRaf = throttleToNextFrame(this.tick);
@@ -91,25 +89,6 @@ class TickManager {
91
89
  this.isPaused = true;
92
90
  this.cancelRaf?.();
93
91
  }
94
- updatePointerVelocity(elapsed) {
95
- const {
96
- prevPoint,
97
- editor: {
98
- inputs: { currentScreenPoint, pointerVelocity }
99
- }
100
- } = this;
101
- if (elapsed === 0) return;
102
- const delta = Vec.Sub(currentScreenPoint, prevPoint);
103
- this.prevPoint = currentScreenPoint.clone();
104
- const length = delta.len();
105
- const direction = length ? delta.div(length) : new Vec(0, 0);
106
- const next = pointerVelocity.clone().lrp(direction.mul(length / elapsed), 0.5);
107
- if (Math.abs(next.x) < 0.01) next.x = 0;
108
- if (Math.abs(next.y) < 0.01) next.y = 0;
109
- if (!pointerVelocity.equals(next)) {
110
- this.editor.inputs.pointerVelocity = next;
111
- }
112
- }
113
92
  }
114
93
  _init = __decoratorStart(null);
115
94
  __decorateElement(_init, 1, "tick", _tick_dec, TickManager);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/editor/managers/TickManager/TickManager.ts"],
4
- "sourcesContent": ["import { throttleToNextFrame as _throttleToNextFrame, bind } from '@tldraw/utils'\nimport { Vec } from '../../../primitives/Vec'\nimport { Editor } from '../../Editor'\n\nconst throttleToNextFrame =\n\ttypeof process !== 'undefined' && process.env.NODE_ENV === 'test'\n\t\t? // At test time we should use actual raf and not throttle, because throttle was set up to evaluate immediately during tests, which causes stack overflow\n\t\t\t// for the tick manager since it sets up a raf loop.\n\t\t\tfunction mockThrottle(cb: any) {\n\t\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\t\tconst frame = requestAnimationFrame(cb)\n\t\t\t\treturn () => cancelAnimationFrame(frame)\n\t\t\t}\n\t\t: _throttleToNextFrame\n\nexport class TickManager {\n\tconstructor(public editor: Editor) {\n\t\tthis.editor.disposables.add(this.dispose)\n\t\tthis.start()\n\t}\n\n\tcancelRaf?: null | (() => void)\n\tisPaused = true\n\tnow = 0\n\n\tstart() {\n\t\tthis.isPaused = false\n\t\tthis.cancelRaf?.()\n\t\tthis.cancelRaf = throttleToNextFrame(this.tick)\n\t\tthis.now = Date.now()\n\t}\n\n\t@bind\n\ttick() {\n\t\tif (this.isPaused) {\n\t\t\treturn\n\t\t}\n\n\t\tconst now = Date.now()\n\t\tconst elapsed = now - this.now\n\t\tthis.now = now\n\n\t\tthis.updatePointerVelocity(elapsed)\n\t\tthis.editor.emit('frame', elapsed)\n\t\tthis.editor.emit('tick', elapsed)\n\t\tthis.cancelRaf = throttleToNextFrame(this.tick)\n\t}\n\n\t// Clear the listener\n\t@bind\n\tdispose() {\n\t\tthis.isPaused = true\n\n\t\tthis.cancelRaf?.()\n\t}\n\n\tprivate prevPoint = new Vec()\n\n\tupdatePointerVelocity(elapsed: number) {\n\t\tconst {\n\t\t\tprevPoint,\n\t\t\teditor: {\n\t\t\t\tinputs: { currentScreenPoint, pointerVelocity },\n\t\t\t},\n\t\t} = this\n\n\t\tif (elapsed === 0) return\n\n\t\tconst delta = Vec.Sub(currentScreenPoint, prevPoint)\n\t\tthis.prevPoint = currentScreenPoint.clone()\n\n\t\tconst length = delta.len()\n\t\tconst direction = length ? delta.div(length) : new Vec(0, 0)\n\n\t\t// consider adjusting this with an easing rather than a linear interpolation\n\t\tconst next = pointerVelocity.clone().lrp(direction.mul(length / elapsed), 0.5)\n\n\t\t// if the velocity is very small, just set it to 0\n\t\tif (Math.abs(next.x) < 0.01) next.x = 0\n\t\tif (Math.abs(next.y) < 0.01) next.y = 0\n\n\t\tif (!pointerVelocity.equals(next)) {\n\t\t\tthis.editor.inputs.pointerVelocity = next\n\t\t}\n\t}\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAS,uBAAuB,sBAAsB,YAAY;AAClE,SAAS,WAAW;AAGpB,MAAM,sBACL,OAAO,YAAY,eAAe,QAAQ,IAAI,aAAa;AAAA;AAAA;AAAA,EAGzD,SAAS,aAAa,IAAS;AAE9B,UAAM,QAAQ,sBAAsB,EAAE;AACtC,WAAO,MAAM,qBAAqB,KAAK;AAAA,EACxC;AAAA,IACC;AAmBH,aAAC,OAiBD,gBAAC;AAlCK,MAAM,YAAY;AAAA,EACxB,YAAmB,QAAgB;AAAhB;AADb;AAMN;AACA,oCAAW;AACX,+BAAM;AAiCN,wBAAQ,aAAY,IAAI,IAAI;AAvC3B,SAAK,OAAO,YAAY,IAAI,KAAK,OAAO;AACxC,SAAK,MAAM;AAAA,EACZ;AAAA,EAMA,QAAQ;AACP,SAAK,WAAW;AAChB,SAAK,YAAY;AACjB,SAAK,YAAY,oBAAoB,KAAK,IAAI;AAC9C,SAAK,MAAM,KAAK,IAAI;AAAA,EACrB;AAAA,EAGA,OAAO;AACN,QAAI,KAAK,UAAU;AAClB;AAAA,IACD;AAEA,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,UAAU,MAAM,KAAK;AAC3B,SAAK,MAAM;AAEX,SAAK,sBAAsB,OAAO;AAClC,SAAK,OAAO,KAAK,SAAS,OAAO;AACjC,SAAK,OAAO,KAAK,QAAQ,OAAO;AAChC,SAAK,YAAY,oBAAoB,KAAK,IAAI;AAAA,EAC/C;AAAA,EAIA,UAAU;AACT,SAAK,WAAW;AAEhB,SAAK,YAAY;AAAA,EAClB;AAAA,EAIA,sBAAsB,SAAiB;AACtC,UAAM;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,QACP,QAAQ,EAAE,oBAAoB,gBAAgB;AAAA,MAC/C;AAAA,IACD,IAAI;AAEJ,QAAI,YAAY,EAAG;AAEnB,UAAM,QAAQ,IAAI,IAAI,oBAAoB,SAAS;AACnD,SAAK,YAAY,mBAAmB,MAAM;AAE1C,UAAM,SAAS,MAAM,IAAI;AACzB,UAAM,YAAY,SAAS,MAAM,IAAI,MAAM,IAAI,IAAI,IAAI,GAAG,CAAC;AAG3D,UAAM,OAAO,gBAAgB,MAAM,EAAE,IAAI,UAAU,IAAI,SAAS,OAAO,GAAG,GAAG;AAG7E,QAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAM,MAAK,IAAI;AACtC,QAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAM,MAAK,IAAI;AAEtC,QAAI,CAAC,gBAAgB,OAAO,IAAI,GAAG;AAClC,WAAK,OAAO,OAAO,kBAAkB;AAAA,IACtC;AAAA,EACD;AACD;AAtEO;AAkBN,oCADA,WAjBY;AAmCZ,uCADA,cAlCY;AAAN,2BAAM;",
4
+ "sourcesContent": ["import { throttleToNextFrame as _throttleToNextFrame, bind } from '@tldraw/utils'\nimport { Editor } from '../../Editor'\n\nconst throttleToNextFrame =\n\ttypeof process !== 'undefined' && process.env.NODE_ENV === 'test'\n\t\t? // At test time we should use actual raf and not throttle, because throttle was set up to evaluate immediately during tests, which causes stack overflow\n\t\t\t// for the tick manager since it sets up a raf loop.\n\t\t\tfunction mockThrottle(cb: any) {\n\t\t\t\t// eslint-disable-next-line no-restricted-globals\n\t\t\t\tconst frame = requestAnimationFrame(cb)\n\t\t\t\treturn () => cancelAnimationFrame(frame)\n\t\t\t}\n\t\t: _throttleToNextFrame\n\n/** @internal */\nexport class TickManager {\n\tconstructor(public editor: Editor) {\n\t\tthis.editor.disposables.add(this.dispose)\n\t\tthis.start()\n\t}\n\n\tcancelRaf?: null | (() => void)\n\tisPaused = true\n\tnow = 0\n\n\tstart() {\n\t\tthis.isPaused = false\n\t\tthis.cancelRaf?.()\n\t\tthis.cancelRaf = throttleToNextFrame(this.tick)\n\t\tthis.now = Date.now()\n\t}\n\n\t@bind\n\ttick() {\n\t\tif (this.isPaused) {\n\t\t\treturn\n\t\t}\n\n\t\tconst now = Date.now()\n\t\tconst elapsed = now - this.now\n\t\tthis.now = now\n\n\t\tthis.editor.inputs.updatePointerVelocity(elapsed)\n\t\tthis.editor.emit('frame', elapsed)\n\t\tthis.editor.emit('tick', elapsed)\n\t\tthis.cancelRaf = throttleToNextFrame(this.tick)\n\t}\n\n\t// Clear the listener\n\t@bind\n\tdispose() {\n\t\tthis.isPaused = true\n\n\t\tthis.cancelRaf?.()\n\t}\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAS,uBAAuB,sBAAsB,YAAY;AAGlE,MAAM,sBACL,OAAO,YAAY,eAAe,QAAQ,IAAI,aAAa;AAAA;AAAA;AAAA,EAGzD,SAAS,aAAa,IAAS;AAE9B,UAAM,QAAQ,sBAAsB,EAAE;AACtC,WAAO,MAAM,qBAAqB,KAAK;AAAA,EACxC;AAAA,IACC;AAoBH,aAAC,OAiBD,gBAAC;AAlCK,MAAM,YAAY;AAAA,EACxB,YAAmB,QAAgB;AAAhB;AADb;AAMN;AACA,oCAAW;AACX,+BAAM;AANL,SAAK,OAAO,YAAY,IAAI,KAAK,OAAO;AACxC,SAAK,MAAM;AAAA,EACZ;AAAA,EAMA,QAAQ;AACP,SAAK,WAAW;AAChB,SAAK,YAAY;AACjB,SAAK,YAAY,oBAAoB,KAAK,IAAI;AAC9C,SAAK,MAAM,KAAK,IAAI;AAAA,EACrB;AAAA,EAGA,OAAO;AACN,QAAI,KAAK,UAAU;AAClB;AAAA,IACD;AAEA,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,UAAU,MAAM,KAAK;AAC3B,SAAK,MAAM;AAEX,SAAK,OAAO,OAAO,sBAAsB,OAAO;AAChD,SAAK,OAAO,KAAK,SAAS,OAAO;AACjC,SAAK,OAAO,KAAK,QAAQ,OAAO;AAChC,SAAK,YAAY,oBAAoB,KAAK,IAAI;AAAA,EAC/C;AAAA,EAIA,UAAU;AACT,SAAK,WAAW;AAEhB,SAAK,YAAY;AAAA,EAClB;AACD;AAxCO;AAkBN,oCADA,WAjBY;AAmCZ,uCADA,cAlCY;AAAN,2BAAM;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/editor/shapes/BaseBoxShapeUtil.tsx"],
4
- "sourcesContent": ["import { TLBaseShape } from '@tldraw/tlschema'\nimport { lerp } from '@tldraw/utils'\nimport { Geometry2d } from '../../primitives/geometry/Geometry2d'\nimport { Rectangle2d } from '../../primitives/geometry/Rectangle2d'\nimport { HandleSnapGeometry } from '../managers/SnapManager/HandleSnaps'\nimport { ShapeUtil, TLResizeInfo } from './ShapeUtil'\nimport { resizeBox } from './shared/resizeBox'\n\n/** @public */\nexport type TLBaseBoxShape = TLBaseShape<string, { w: number; h: number }>\n\n/** @public */\nexport abstract class BaseBoxShapeUtil<Shape extends TLBaseBoxShape> extends ShapeUtil<Shape> {\n\tgetGeometry(shape: Shape): Geometry2d {\n\t\treturn new Rectangle2d({\n\t\t\twidth: shape.props.w,\n\t\t\theight: shape.props.h,\n\t\t\tisFilled: true,\n\t\t})\n\t}\n\n\toverride onResize(shape: any, info: TLResizeInfo<any>) {\n\t\treturn resizeBox(shape, info)\n\t}\n\n\toverride getHandleSnapGeometry(shape: Shape): HandleSnapGeometry {\n\t\treturn {\n\t\t\tpoints: this.getGeometry(shape).bounds.cornersAndCenter,\n\t\t}\n\t}\n\n\toverride getInterpolatedProps(startShape: Shape, endShape: Shape, t: number): Shape['props'] {\n\t\treturn {\n\t\t\t...endShape.props,\n\t\t\tw: lerp(startShape.props.w, endShape.props.w, t),\n\t\t\th: lerp(startShape.props.h, endShape.props.h, t),\n\t\t}\n\t}\n}\n"],
4
+ "sourcesContent": ["import { ExtractShapeByProps } from '@tldraw/tlschema'\nimport { lerp } from '@tldraw/utils'\nimport { Geometry2d } from '../../primitives/geometry/Geometry2d'\nimport { Rectangle2d } from '../../primitives/geometry/Rectangle2d'\nimport { HandleSnapGeometry } from '../managers/SnapManager/HandleSnaps'\nimport { ShapeUtil, TLResizeInfo } from './ShapeUtil'\nimport { resizeBox } from './shared/resizeBox'\n\n/** @public */\nexport type TLBaseBoxShape = ExtractShapeByProps<{ w: number; h: number }>\n\n/** @public */\nexport abstract class BaseBoxShapeUtil<Shape extends TLBaseBoxShape> extends ShapeUtil<Shape> {\n\tgetGeometry(shape: Shape): Geometry2d {\n\t\treturn new Rectangle2d({\n\t\t\twidth: shape.props.w,\n\t\t\theight: shape.props.h,\n\t\t\tisFilled: true,\n\t\t})\n\t}\n\n\toverride onResize(shape: any, info: TLResizeInfo<any>) {\n\t\treturn resizeBox(shape, info)\n\t}\n\n\toverride getHandleSnapGeometry(shape: Shape): HandleSnapGeometry {\n\t\treturn {\n\t\t\tpoints: this.getGeometry(shape).bounds.cornersAndCenter,\n\t\t}\n\t}\n\n\toverride getInterpolatedProps(startShape: Shape, endShape: Shape, t: number): Shape['props'] {\n\t\treturn {\n\t\t\t...endShape.props,\n\t\t\tw: lerp(startShape.props.w, endShape.props.w, t),\n\t\t\th: lerp(startShape.props.h, endShape.props.h, t),\n\t\t}\n\t}\n}\n"],
5
5
  "mappings": "AACA,SAAS,YAAY;AAErB,SAAS,mBAAmB;AAE5B,SAAS,iBAA+B;AACxC,SAAS,iBAAiB;AAMnB,MAAe,yBAAuD,UAAiB;AAAA,EAC7F,YAAY,OAA0B;AACrC,WAAO,IAAI,YAAY;AAAA,MACtB,OAAO,MAAM,MAAM;AAAA,MACnB,QAAQ,MAAM,MAAM;AAAA,MACpB,UAAU;AAAA,IACX,CAAC;AAAA,EACF;AAAA,EAES,SAAS,OAAY,MAAyB;AACtD,WAAO,UAAU,OAAO,IAAI;AAAA,EAC7B;AAAA,EAES,sBAAsB,OAAkC;AAChE,WAAO;AAAA,MACN,QAAQ,KAAK,YAAY,KAAK,EAAE,OAAO;AAAA,IACxC;AAAA,EACD;AAAA,EAES,qBAAqB,YAAmB,UAAiB,GAA2B;AAC5F,WAAO;AAAA,MACN,GAAG,SAAS;AAAA,MACZ,GAAG,KAAK,WAAW,MAAM,GAAG,SAAS,MAAM,GAAG,CAAC;AAAA,MAC/C,GAAG,KAAK,WAAW,MAAM,GAAG,SAAS,MAAM,GAAG,CAAC;AAAA,IAChD;AAAA,EACD;AACD;",
6
6
  "names": []
7
7
  }
@@ -72,7 +72,7 @@ class ShapeUtil {
72
72
  * @param shape - The shape.
73
73
  * @public
74
74
  */
75
- canSnap(_shape) {
75
+ canSnap(shape) {
76
76
  return true;
77
77
  }
78
78
  /**
@@ -81,7 +81,7 @@ class ShapeUtil {
81
81
  * @param shape - The shape.
82
82
  * @public
83
83
  */
84
- canTabTo(_shape) {
84
+ canTabTo(shape) {
85
85
  return true;
86
86
  }
87
87
  /**
@@ -89,7 +89,7 @@ class ShapeUtil {
89
89
  *
90
90
  * @public
91
91
  */
92
- canScroll(_shape) {
92
+ canScroll(shape) {
93
93
  return false;
94
94
  }
95
95
  /**
@@ -105,7 +105,7 @@ class ShapeUtil {
105
105
  *
106
106
  * @public
107
107
  */
108
- canEdit(_shape) {
108
+ canEdit(shape, info) {
109
109
  return false;
110
110
  }
111
111
  /**
@@ -113,7 +113,7 @@ class ShapeUtil {
113
113
  *
114
114
  * @public
115
115
  */
116
- canResize(_shape) {
116
+ canResize(shape) {
117
117
  return true;
118
118
  }
119
119
  /**
@@ -121,7 +121,7 @@ class ShapeUtil {
121
121
  *
122
122
  * @public
123
123
  */
124
- canResizeChildren(_shape) {
124
+ canResizeChildren(shape) {
125
125
  return true;
126
126
  }
127
127
  /**
@@ -129,7 +129,15 @@ class ShapeUtil {
129
129
  *
130
130
  * @public
131
131
  */
132
- canEditInReadonly(_shape) {
132
+ canEditInReadonly(shape) {
133
+ return false;
134
+ }
135
+ /**
136
+ * Whether the shape can be edited while locked or while an ancestor is locked.
137
+ *
138
+ * @public
139
+ */
140
+ canEditWhileLocked(shape) {
133
141
  return false;
134
142
  }
135
143
  /**
@@ -137,7 +145,7 @@ class ShapeUtil {
137
145
  *
138
146
  * @public
139
147
  */
140
- canCrop(_shape) {
148
+ canCrop(shape) {
141
149
  return false;
142
150
  }
143
151
  /**
@@ -149,7 +157,7 @@ class ShapeUtil {
149
157
  *
150
158
  * @public
151
159
  */
152
- canBeLaidOut(_shape, _info) {
160
+ canBeLaidOut(shape, info) {
153
161
  return true;
154
162
  }
155
163
  /**
@@ -159,7 +167,7 @@ class ShapeUtil {
159
167
  *
160
168
  * @param shape - The shape.
161
169
  */
162
- canCull(_shape) {
170
+ canCull(shape) {
163
171
  return true;
164
172
  }
165
173
  /**
@@ -171,7 +179,7 @@ class ShapeUtil {
171
179
  *
172
180
  * @internal
173
181
  */
174
- providesBackgroundForChildren(_shape) {
182
+ providesBackgroundForChildren(shape) {
175
183
  return false;
176
184
  }
177
185
  /**
@@ -179,7 +187,7 @@ class ShapeUtil {
179
187
  *
180
188
  * @public
181
189
  */
182
- hideResizeHandles(_shape) {
190
+ hideResizeHandles(shape) {
183
191
  return false;
184
192
  }
185
193
  /**
@@ -187,7 +195,7 @@ class ShapeUtil {
187
195
  *
188
196
  * @public
189
197
  */
190
- hideRotateHandle(_shape) {
198
+ hideRotateHandle(shape) {
191
199
  return false;
192
200
  }
193
201
  /**
@@ -195,7 +203,7 @@ class ShapeUtil {
195
203
  *
196
204
  * @public
197
205
  */
198
- hideSelectionBoundsBg(_shape) {
206
+ hideSelectionBoundsBg(shape) {
199
207
  return false;
200
208
  }
201
209
  /**
@@ -203,7 +211,7 @@ class ShapeUtil {
203
211
  *
204
212
  * @public
205
213
  */
206
- hideSelectionBoundsFg(_shape) {
214
+ hideSelectionBoundsFg(shape) {
207
215
  return false;
208
216
  }
209
217
  /**
@@ -211,7 +219,7 @@ class ShapeUtil {
211
219
  *
212
220
  * @public
213
221
  */
214
- isAspectRatioLocked(_shape) {
222
+ isAspectRatioLocked(shape) {
215
223
  return false;
216
224
  }
217
225
  /**
@@ -221,10 +229,10 @@ class ShapeUtil {
221
229
  * useful in cases like annotating on top of an image, where you usually want to avoid extra
222
230
  * padding around the image if you don't need it.
223
231
  *
224
- * @param _shape - The shape to check
232
+ * @param shape - The shape to check
225
233
  * @returns True if this shape should be treated as an export bounds container
226
234
  */
227
- isExportBoundsContainer(_shape) {
235
+ isExportBoundsContainer(shape) {
228
236
  return false;
229
237
  }
230
238
  /**
@@ -234,7 +242,7 @@ class ShapeUtil {
234
242
  * @param type - The shape type.
235
243
  * @public
236
244
  */
237
- canReceiveNewChildrenOfType(_shape, _type) {
245
+ canReceiveNewChildrenOfType(shape, _type) {
238
246
  return false;
239
247
  }
240
248
  /** @internal */
@@ -256,20 +264,20 @@ class ShapeUtil {
256
264
  * Get the geometry to use when snapping to this this shape in translate/resize operations. See
257
265
  * {@link BoundsSnapGeometry} for details.
258
266
  */
259
- getBoundsSnapGeometry(_shape) {
267
+ getBoundsSnapGeometry(shape) {
260
268
  return {};
261
269
  }
262
270
  /**
263
271
  * Get the geometry to use when snapping handles to this shape. See {@link HandleSnapGeometry}
264
272
  * for details.
265
273
  */
266
- getHandleSnapGeometry(_shape) {
274
+ getHandleSnapGeometry(shape) {
267
275
  return {};
268
276
  }
269
- getText(_shape) {
277
+ getText(shape) {
270
278
  return void 0;
271
279
  }
272
- getAriaDescriptor(_shape) {
280
+ getAriaDescriptor(shape) {
273
281
  return void 0;
274
282
  }
275
283
  }