@tldraw/editor 3.14.0-canary.bf9ab5f94a7d → 3.14.0-canary.c0df84d88f32

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 (210) hide show
  1. package/dist-cjs/index.d.ts +71 -67
  2. package/dist-cjs/index.js +8 -8
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/config/TLSessionStateSnapshot.js +1 -12
  5. package/dist-cjs/lib/config/TLSessionStateSnapshot.js.map +3 -3
  6. package/dist-cjs/lib/editor/Editor.js +51 -77
  7. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  8. package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +2 -2
  9. package/dist-cjs/lib/editor/derivations/bindingsIndex.js +22 -22
  10. package/dist-cjs/lib/editor/derivations/bindingsIndex.js.map +2 -2
  11. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +16 -20
  12. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +3 -3
  13. package/dist-cjs/lib/editor/derivations/parentsToChildren.js +16 -16
  14. package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
  15. package/dist-cjs/lib/editor/managers/{ClickManager.js → ClickManager/ClickManager.js} +1 -1
  16. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +7 -0
  17. package/dist-cjs/lib/editor/managers/{EdgeScrollManager.js → EdgeScrollManager/EdgeScrollManager.js} +2 -2
  18. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +7 -0
  19. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +7 -0
  20. package/dist-cjs/lib/editor/managers/{FontManager.js → FontManager/FontManager.js} +5 -1
  21. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +7 -0
  22. package/dist-cjs/lib/editor/managers/{HistoryManager.js → HistoryManager/HistoryManager.js} +64 -6
  23. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +7 -0
  24. package/dist-cjs/lib/editor/managers/{ScribbleManager.js → ScribbleManager/ScribbleManager.js} +1 -1
  25. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +7 -0
  26. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +7 -0
  27. package/dist-cjs/lib/editor/managers/{TickManager.js → TickManager/TickManager.js} +1 -1
  28. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +7 -0
  29. package/dist-cjs/lib/editor/managers/{UserPreferencesManager.js → UserPreferencesManager/UserPreferencesManager.js} +1 -1
  30. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +7 -0
  31. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +8 -0
  32. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  33. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +6 -0
  34. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
  35. package/dist-cjs/lib/exports/getSvgJsx.js.map +1 -1
  36. package/dist-cjs/lib/primitives/Box.js +33 -33
  37. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  38. package/dist-cjs/lib/primitives/Vec.js +13 -8
  39. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  40. package/dist-cjs/lib/primitives/geometry/Arc2d.js +41 -21
  41. package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
  42. package/dist-cjs/lib/primitives/geometry/Circle2d.js +11 -11
  43. package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
  44. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +13 -16
  45. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
  46. package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js +4 -4
  47. package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js.map +2 -2
  48. package/dist-cjs/lib/primitives/geometry/Edge2d.js +14 -17
  49. package/dist-cjs/lib/primitives/geometry/Edge2d.js.map +2 -2
  50. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +10 -10
  51. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
  52. package/dist-cjs/lib/primitives/geometry/Point2d.js +6 -6
  53. package/dist-cjs/lib/primitives/geometry/Point2d.js.map +2 -2
  54. package/dist-cjs/lib/primitives/geometry/Polygon2d.js +3 -0
  55. package/dist-cjs/lib/primitives/geometry/Polygon2d.js.map +2 -2
  56. package/dist-cjs/lib/primitives/geometry/Polyline2d.js +8 -5
  57. package/dist-cjs/lib/primitives/geometry/Polyline2d.js.map +2 -2
  58. package/dist-cjs/lib/primitives/geometry/Rectangle2d.js +22 -11
  59. package/dist-cjs/lib/primitives/geometry/Rectangle2d.js.map +2 -2
  60. package/dist-cjs/lib/primitives/geometry/Stadium2d.js +22 -22
  61. package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +2 -2
  62. package/dist-cjs/lib/utils/reorderShapes.js +11 -10
  63. package/dist-cjs/lib/utils/reorderShapes.js.map +2 -2
  64. package/dist-cjs/lib/utils/richText.js.map +1 -1
  65. package/dist-cjs/version.js +3 -3
  66. package/dist-cjs/version.js.map +1 -1
  67. package/dist-esm/index.d.mts +71 -67
  68. package/dist-esm/index.mjs +12 -8
  69. package/dist-esm/index.mjs.map +2 -2
  70. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs +1 -1
  71. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
  72. package/dist-esm/lib/editor/Editor.mjs +51 -77
  73. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  74. package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +2 -2
  75. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs +22 -22
  76. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs.map +2 -2
  77. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +16 -20
  78. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +3 -3
  79. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +16 -16
  80. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
  81. package/dist-esm/lib/editor/managers/{ClickManager.mjs → ClickManager/ClickManager.mjs} +1 -1
  82. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +7 -0
  83. package/dist-esm/lib/editor/managers/{EdgeScrollManager.mjs → EdgeScrollManager/EdgeScrollManager.mjs} +2 -2
  84. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +7 -0
  85. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +7 -0
  86. package/dist-esm/lib/editor/managers/{FontManager.mjs → FontManager/FontManager.mjs} +5 -1
  87. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +7 -0
  88. package/dist-esm/lib/editor/managers/{HistoryManager.mjs → HistoryManager/HistoryManager.mjs} +60 -2
  89. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +7 -0
  90. package/dist-esm/lib/editor/managers/{ScribbleManager.mjs → ScribbleManager/ScribbleManager.mjs} +1 -1
  91. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +7 -0
  92. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +7 -0
  93. package/dist-esm/lib/editor/managers/{TickManager.mjs → TickManager/TickManager.mjs} +1 -1
  94. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +7 -0
  95. package/dist-esm/lib/editor/managers/{UserPreferencesManager.mjs → UserPreferencesManager/UserPreferencesManager.mjs} +1 -1
  96. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +7 -0
  97. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +8 -0
  98. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  99. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +6 -0
  100. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
  101. package/dist-esm/lib/exports/getSvgJsx.mjs.map +1 -1
  102. package/dist-esm/lib/primitives/Box.mjs +33 -33
  103. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  104. package/dist-esm/lib/primitives/Vec.mjs +13 -8
  105. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  106. package/dist-esm/lib/primitives/geometry/Arc2d.mjs +41 -21
  107. package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
  108. package/dist-esm/lib/primitives/geometry/Circle2d.mjs +11 -11
  109. package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
  110. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +13 -16
  111. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
  112. package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs +4 -4
  113. package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs.map +2 -2
  114. package/dist-esm/lib/primitives/geometry/Edge2d.mjs +14 -17
  115. package/dist-esm/lib/primitives/geometry/Edge2d.mjs.map +2 -2
  116. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +11 -11
  117. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
  118. package/dist-esm/lib/primitives/geometry/Point2d.mjs +6 -6
  119. package/dist-esm/lib/primitives/geometry/Point2d.mjs.map +2 -2
  120. package/dist-esm/lib/primitives/geometry/Polygon2d.mjs +3 -0
  121. package/dist-esm/lib/primitives/geometry/Polygon2d.mjs.map +2 -2
  122. package/dist-esm/lib/primitives/geometry/Polyline2d.mjs +8 -5
  123. package/dist-esm/lib/primitives/geometry/Polyline2d.mjs.map +2 -2
  124. package/dist-esm/lib/primitives/geometry/Rectangle2d.mjs +22 -11
  125. package/dist-esm/lib/primitives/geometry/Rectangle2d.mjs.map +2 -2
  126. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +22 -22
  127. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +2 -2
  128. package/dist-esm/lib/utils/reorderShapes.mjs +11 -10
  129. package/dist-esm/lib/utils/reorderShapes.mjs.map +2 -2
  130. package/dist-esm/lib/utils/richText.mjs.map +1 -1
  131. package/dist-esm/version.mjs +3 -3
  132. package/dist-esm/version.mjs.map +1 -1
  133. package/package.json +8 -9
  134. package/src/index.ts +13 -7
  135. package/src/lib/config/TLSessionStateSnapshot.ts +1 -1
  136. package/src/lib/editor/Editor.test.ts +252 -3
  137. package/src/lib/editor/Editor.ts +49 -75
  138. package/src/lib/editor/bindings/BindingUtil.ts +6 -0
  139. package/src/lib/editor/derivations/bindingsIndex.ts +27 -26
  140. package/src/lib/editor/derivations/notVisibleShapes.ts +24 -25
  141. package/src/lib/editor/derivations/parentsToChildren.ts +28 -25
  142. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +442 -0
  143. package/src/lib/editor/managers/{ClickManager.ts → ClickManager/ClickManager.ts} +3 -3
  144. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +374 -0
  145. package/src/lib/editor/managers/{EdgeScrollManager.ts → EdgeScrollManager/EdgeScrollManager.ts} +3 -3
  146. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +455 -0
  147. package/src/lib/editor/managers/{FocusManager.ts → FocusManager/FocusManager.ts} +1 -1
  148. package/src/lib/editor/managers/FontManager/FontManager.test.ts +263 -0
  149. package/src/lib/editor/managers/{FontManager.ts → FontManager/FontManager.ts} +6 -2
  150. package/src/lib/editor/managers/{HistoryManager.test.ts → HistoryManager/HistoryManager.test.ts} +388 -1
  151. package/src/lib/editor/managers/{HistoryManager.ts → HistoryManager/HistoryManager.ts} +73 -2
  152. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +624 -0
  153. package/src/lib/editor/managers/{ScribbleManager.ts → ScribbleManager/ScribbleManager.ts} +2 -2
  154. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +485 -0
  155. package/src/lib/editor/managers/TextManager/TextManager.test.ts +411 -0
  156. package/src/lib/editor/managers/{TextManager.ts → TextManager/TextManager.ts} +1 -1
  157. package/src/lib/editor/managers/TickManager/TickManager.test.ts +314 -0
  158. package/src/lib/editor/managers/{TickManager.ts → TickManager/TickManager.ts} +2 -2
  159. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +591 -0
  160. package/src/lib/editor/managers/{UserPreferencesManager.ts → UserPreferencesManager/UserPreferencesManager.ts} +2 -2
  161. package/src/lib/editor/shapes/ShapeUtil.ts +10 -1
  162. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +8 -0
  163. package/src/lib/exports/getSvgJsx.tsx +1 -1
  164. package/src/lib/primitives/Box.test.ts +588 -7
  165. package/src/lib/primitives/Box.ts +33 -33
  166. package/src/lib/primitives/Vec.test.ts +2 -2
  167. package/src/lib/primitives/Vec.ts +13 -8
  168. package/src/lib/primitives/geometry/Arc2d.ts +42 -23
  169. package/src/lib/primitives/geometry/Circle2d.ts +12 -12
  170. package/src/lib/primitives/geometry/CubicBezier2d.test.ts +5 -0
  171. package/src/lib/primitives/geometry/CubicBezier2d.ts +13 -17
  172. package/src/lib/primitives/geometry/CubicSpline2d.ts +5 -5
  173. package/src/lib/primitives/geometry/Edge2d.ts +14 -18
  174. package/src/lib/primitives/geometry/Ellipse2d.ts +12 -13
  175. package/src/lib/primitives/geometry/Point2d.ts +6 -6
  176. package/src/lib/primitives/geometry/Polygon2d.ts +4 -0
  177. package/src/lib/primitives/geometry/Polyline2d.ts +10 -7
  178. package/src/lib/primitives/geometry/Rectangle2d.ts +24 -11
  179. package/src/lib/primitives/geometry/Stadium2d.ts +22 -23
  180. package/src/lib/utils/reorderShapes.ts +10 -13
  181. package/src/lib/utils/richText.ts +1 -1
  182. package/src/version.ts +3 -3
  183. package/dist-cjs/lib/editor/managers/ClickManager.js.map +0 -7
  184. package/dist-cjs/lib/editor/managers/EdgeScrollManager.js.map +0 -7
  185. package/dist-cjs/lib/editor/managers/FocusManager.js.map +0 -7
  186. package/dist-cjs/lib/editor/managers/FontManager.js.map +0 -7
  187. package/dist-cjs/lib/editor/managers/HistoryManager.js.map +0 -7
  188. package/dist-cjs/lib/editor/managers/ScribbleManager.js.map +0 -7
  189. package/dist-cjs/lib/editor/managers/Stack.js +0 -82
  190. package/dist-cjs/lib/editor/managers/Stack.js.map +0 -7
  191. package/dist-cjs/lib/editor/managers/TextManager.js.map +0 -7
  192. package/dist-cjs/lib/editor/managers/TickManager.js.map +0 -7
  193. package/dist-cjs/lib/editor/managers/UserPreferencesManager.js.map +0 -7
  194. package/dist-esm/lib/editor/managers/ClickManager.mjs.map +0 -7
  195. package/dist-esm/lib/editor/managers/EdgeScrollManager.mjs.map +0 -7
  196. package/dist-esm/lib/editor/managers/FocusManager.mjs.map +0 -7
  197. package/dist-esm/lib/editor/managers/FontManager.mjs.map +0 -7
  198. package/dist-esm/lib/editor/managers/HistoryManager.mjs.map +0 -7
  199. package/dist-esm/lib/editor/managers/ScribbleManager.mjs.map +0 -7
  200. package/dist-esm/lib/editor/managers/Stack.mjs +0 -62
  201. package/dist-esm/lib/editor/managers/Stack.mjs.map +0 -7
  202. package/dist-esm/lib/editor/managers/TextManager.mjs.map +0 -7
  203. package/dist-esm/lib/editor/managers/TickManager.mjs.map +0 -7
  204. package/dist-esm/lib/editor/managers/UserPreferencesManager.mjs.map +0 -7
  205. package/src/lib/editor/managers/ScribbleManager.test.ts +0 -32
  206. package/src/lib/editor/managers/Stack.ts +0 -71
  207. /package/dist-cjs/lib/editor/managers/{FocusManager.js → FocusManager/FocusManager.js} +0 -0
  208. /package/dist-cjs/lib/editor/managers/{TextManager.js → TextManager/TextManager.js} +0 -0
  209. /package/dist-esm/lib/editor/managers/{FocusManager.mjs → FocusManager/FocusManager.mjs} +0 -0
  210. /package/dist-esm/lib/editor/managers/{TextManager.mjs → TextManager/TextManager.mjs} +0 -0
@@ -148,16 +148,16 @@ import { bindingsIndex } from './derivations/bindingsIndex'
148
148
  import { notVisibleShapes } from './derivations/notVisibleShapes'
149
149
  import { parentsToChildren } from './derivations/parentsToChildren'
150
150
  import { deriveShapeIdsInCurrentPage } from './derivations/shapeIdsInCurrentPage'
151
- import { ClickManager } from './managers/ClickManager'
152
- import { EdgeScrollManager } from './managers/EdgeScrollManager'
153
- import { FocusManager } from './managers/FocusManager'
154
- import { FontManager } from './managers/FontManager'
155
- import { HistoryManager } from './managers/HistoryManager'
156
- import { ScribbleManager } from './managers/ScribbleManager'
151
+ import { ClickManager } from './managers/ClickManager/ClickManager'
152
+ import { EdgeScrollManager } from './managers/EdgeScrollManager/EdgeScrollManager'
153
+ import { FocusManager } from './managers/FocusManager/FocusManager'
154
+ import { FontManager } from './managers/FontManager/FontManager'
155
+ import { HistoryManager } from './managers/HistoryManager/HistoryManager'
156
+ import { ScribbleManager } from './managers/ScribbleManager/ScribbleManager'
157
157
  import { SnapManager } from './managers/SnapManager/SnapManager'
158
- import { TextManager } from './managers/TextManager'
159
- import { TickManager } from './managers/TickManager'
160
- import { UserPreferencesManager } from './managers/UserPreferencesManager'
158
+ import { TextManager } from './managers/TextManager/TextManager'
159
+ import { TickManager } from './managers/TickManager/TickManager'
160
+ import { UserPreferencesManager } from './managers/UserPreferencesManager/UserPreferencesManager'
161
161
  import { ShapeUtil, TLGeometryOpts, TLResizeMode } from './shapes/ShapeUtil'
162
162
  import { RootState } from './tools/RootState'
163
163
  import { StateNode, TLStateNodeConstructor } from './tools/StateNode'
@@ -328,7 +328,7 @@ export class Editor extends EventEmitter<TLEventMap> {
328
328
  this.store = store
329
329
  this.history = new HistoryManager<TLRecord>({
330
330
  store,
331
- annotateError: (error) => {
331
+ annotateError: (error: any) => {
332
332
  this.annotateError(error, { origin: 'history.batch', willCrashApp: true })
333
333
  this.crash(error)
334
334
  },
@@ -512,6 +512,7 @@ export class Editor extends EventEmitter<TLEventMap> {
512
512
  binding,
513
513
  shapeBefore,
514
514
  shapeAfter,
515
+ reason: 'self',
515
516
  })
516
517
  }
517
518
  if (binding.toId === shapeAfter.id) {
@@ -519,6 +520,7 @@ export class Editor extends EventEmitter<TLEventMap> {
519
520
  binding,
520
521
  shapeBefore,
521
522
  shapeAfter,
523
+ reason: 'self',
522
524
  })
523
525
  }
524
526
  }
@@ -537,6 +539,7 @@ export class Editor extends EventEmitter<TLEventMap> {
537
539
  binding,
538
540
  shapeBefore: descendantShape,
539
541
  shapeAfter: descendantShape,
542
+ reason: 'ancestry',
540
543
  })
541
544
  }
542
545
  if (binding.toId === descendantShape.id) {
@@ -544,6 +547,7 @@ export class Editor extends EventEmitter<TLEventMap> {
544
547
  binding,
545
548
  shapeBefore: descendantShape,
546
549
  shapeAfter: descendantShape,
550
+ reason: 'ancestry',
547
551
  })
548
552
  }
549
553
  }
@@ -3715,10 +3719,7 @@ export class Editor extends EventEmitter<TLEventMap> {
3715
3719
  */
3716
3720
  @computed getViewportScreenCenter() {
3717
3721
  const viewportScreenBounds = this.getViewportScreenBounds()
3718
- return new Vec(
3719
- viewportScreenBounds.midX - viewportScreenBounds.minX,
3720
- viewportScreenBounds.midY - viewportScreenBounds.minY
3721
- )
3722
+ return new Vec(viewportScreenBounds.w / 2, viewportScreenBounds.h / 2)
3722
3723
  }
3723
3724
 
3724
3725
  /**
@@ -4644,44 +4645,6 @@ export class Editor extends EventEmitter<TLEventMap> {
4644
4645
  )! as T
4645
4646
  }
4646
4647
 
4647
- private _shapePageGeometryCaches: Record<string, ComputedCache<Geometry2d, TLShape>> = {}
4648
-
4649
- /**
4650
- * Get the geometry of a shape in page-space.
4651
- *
4652
- * @example
4653
- * ```ts
4654
- * editor.getShapePageGeometry(myShape)
4655
- * editor.getShapePageGeometry(myShapeId)
4656
- * editor.getShapePageGeometry(myShapeId, { context: "arrow" })
4657
- * ```
4658
- *
4659
- * @param shape - The shape (or shape id) to get the geometry for.
4660
- * @param opts - Additional options about the request for geometry. Passed to {@link ShapeUtil.getGeometry}.
4661
- *
4662
- * @public
4663
- */
4664
- getShapePageGeometry<T extends Geometry2d>(shape: TLShape | TLShapeId, opts?: TLGeometryOpts): T {
4665
- const context = opts?.context ?? 'none'
4666
- if (!this._shapePageGeometryCaches[context]) {
4667
- this._shapePageGeometryCaches[context] = this.store.createComputedCache(
4668
- 'bounds',
4669
- (shape) => {
4670
- const geometry = this.getShapeGeometry(shape.id, opts)
4671
- const pageTransform = this.getShapePageTransform(shape.id)
4672
- return geometry.transform(pageTransform)
4673
- },
4674
- {
4675
- // we only depend directly on the shape id, and changing geometry/transform will update us anyway
4676
- areRecordsEqual: () => true,
4677
- }
4678
- )
4679
- }
4680
- return this._shapePageGeometryCaches[context].get(
4681
- typeof shape === 'string' ? shape : shape.id
4682
- )! as T
4683
- }
4684
-
4685
4648
  /** @internal */
4686
4649
  @computed private _getShapeHandlesCache(): ComputedCache<TLHandle[] | undefined, TLShape> {
4687
4650
  return this.store.createComputedCache(
@@ -4794,7 +4757,10 @@ export class Editor extends EventEmitter<TLEventMap> {
4794
4757
  /** @internal */
4795
4758
  @computed private _getShapePageBoundsCache(): ComputedCache<Box, TLShape> {
4796
4759
  return this.store.createComputedCache<Box, TLShape>('pageBoundsCache', (shape) => {
4797
- return this.getShapePageGeometry(shape).bounds
4760
+ const pageTransform = this.getShapePageTransform(shape)
4761
+ if (!pageTransform) return undefined
4762
+ const geometry = this.getShapeGeometry(shape)
4763
+ return Box.FromPoints(pageTransform.applyToPoints(geometry.vertices))
4798
4764
  })
4799
4765
  }
4800
4766
 
@@ -4868,11 +4834,12 @@ export class Editor extends EventEmitter<TLEventMap> {
4868
4834
  if (frameAncestors.length === 0) return undefined
4869
4835
 
4870
4836
  const pageMask = frameAncestors
4871
- .map<Vec[] | undefined>(
4872
- (s) =>
4873
- // Apply the frame transform to the frame outline to get the frame outline in the current page space
4874
- this.getShapePageGeometry(s.id).vertices
4875
- )
4837
+ .map<Vec[] | undefined>((s) => {
4838
+ // Apply the frame transform to the frame outline to get the frame outline in the current page space
4839
+ const geometry = this.getShapeGeometry(s.id)
4840
+ const pageTransform = this.getShapePageTransform(s.id)
4841
+ return pageTransform.applyToPoints(geometry.vertices)
4842
+ })
4876
4843
  .reduce((acc, b) => {
4877
4844
  if (!(b && acc)) return undefined
4878
4845
  const intersection = intersectPolygonPolygon(acc, b)
@@ -5070,28 +5037,33 @@ export class Editor extends EventEmitter<TLEventMap> {
5070
5037
  *
5071
5038
  * @public
5072
5039
  */
5073
- isShapeOrAncestorLocked(shape?: TLShape): boolean
5074
- isShapeOrAncestorLocked(id?: TLShapeId): boolean
5075
- isShapeOrAncestorLocked(arg?: TLShape | TLShapeId): boolean {
5076
- const shape = typeof arg === 'string' ? this.getShape(arg) : arg
5077
- if (shape === undefined) return false
5078
- if (shape.isLocked) return true
5079
- return this.isShapeOrAncestorLocked(this.getShapeParent(shape))
5040
+ isShapeOrAncestorLocked(shape?: TLShape | TLShapeId): boolean {
5041
+ const _shape = shape && this.getShape(shape)
5042
+ if (_shape === undefined) return false
5043
+ if (_shape.isLocked) return true
5044
+ return this.isShapeOrAncestorLocked(this.getShapeParent(_shape))
5080
5045
  }
5081
5046
 
5047
+ /**
5048
+ * Get shapes that are outside of the viewport.
5049
+ *
5050
+ * @public
5051
+ */
5082
5052
  @computed
5083
- private _notVisibleShapes() {
5084
- return notVisibleShapes(this)
5053
+ getNotVisibleShapes() {
5054
+ return this._notVisibleShapes.get()
5085
5055
  }
5086
5056
 
5057
+ private _notVisibleShapes = notVisibleShapes(this)
5058
+
5087
5059
  /**
5088
- * Get culled shapes.
5060
+ * Get culled shapes (those that should not render), taking into account which shapes are selected or editing.
5089
5061
  *
5090
5062
  * @public
5091
5063
  */
5092
5064
  @computed
5093
5065
  getCulledShapes() {
5094
- const notVisibleShapes = this._notVisibleShapes().get()
5066
+ const notVisibleShapes = this.getNotVisibleShapes()
5095
5067
  const selectedShapeIds = this.getSelectedShapeIds()
5096
5068
  const editingId = this.getEditingShapeId()
5097
5069
  const culledShapes = new Set<TLShapeId>(notVisibleShapes)
@@ -5340,21 +5312,23 @@ export class Editor extends EventEmitter<TLEventMap> {
5340
5312
  * @example
5341
5313
  * ```ts
5342
5314
  * editor.getShapesAtPoint({ x: 100, y: 100 })
5343
- * editor.getShapesAtPoint({ x: 100, y: 100 }, { hitInside: true, exact: true })
5315
+ * editor.getShapesAtPoint({ x: 100, y: 100 }, { hitInside: true, margin: 8 })
5344
5316
  * ```
5345
5317
  *
5346
5318
  * @param point - The page point to test.
5347
5319
  * @param opts - The options for the hit point testing.
5348
5320
  *
5321
+ * @returns An array of shapes at the given point, sorted in reverse order of their absolute z-index (top-most shape first).
5322
+ *
5349
5323
  * @public
5350
5324
  */
5351
5325
  getShapesAtPoint(
5352
5326
  point: VecLike,
5353
5327
  opts = {} as { margin?: number; hitInside?: boolean }
5354
5328
  ): TLShape[] {
5355
- return this.getCurrentPageShapes().filter(
5356
- (shape) => !this.isShapeHidden(shape) && this.isPointInShape(shape, point, opts)
5357
- )
5329
+ return this.getCurrentPageShapesSorted()
5330
+ .filter((shape) => !this.isShapeHidden(shape) && this.isPointInShape(shape, point, opts))
5331
+ .reverse()
5358
5332
  }
5359
5333
 
5360
5334
  /**
@@ -5796,8 +5770,7 @@ export class Editor extends EventEmitter<TLEventMap> {
5796
5770
  parent: TLParentId | TLPage | TLShape,
5797
5771
  visitor: (id: TLShapeId) => void | false
5798
5772
  ): this {
5799
- const parentId = typeof parent === 'string' ? parent : parent.id
5800
- const children = this.getSortedChildIdsForParent(parentId)
5773
+ const children = this.getSortedChildIdsForParent(parent)
5801
5774
  for (const id of children) {
5802
5775
  if (visitor(id) === false) continue
5803
5776
  this.visitDescendants(id, visitor)
@@ -9304,6 +9277,7 @@ export class Editor extends EventEmitter<TLEventMap> {
9304
9277
  if (rootShapes.length === 1) {
9305
9278
  const onlyRoot = rootShapes[0] as TLFrameShape
9306
9279
  // If the old bounds are in the viewport...
9280
+ // todo: replace frame references with shapes that can accept children
9307
9281
  if (this.isShapeOfType<TLFrameShape>(onlyRoot, 'frame')) {
9308
9282
  while (
9309
9283
  this.getShapesAtPoint(point).some(
@@ -62,6 +62,12 @@ export interface BindingOnShapeChangeOptions<Binding extends TLUnknownBinding> {
62
62
  shapeBefore: TLShape
63
63
  /** The shape record after the change is made. */
64
64
  shapeAfter: TLShape
65
+ /**
66
+ * Why did this shape change?
67
+ * - 'self': the shape itself changed
68
+ * - 'ancestry': the ancestry of the shape changed, but the shape itself may not have done
69
+ */
70
+ reason: 'self' | 'ancestry'
65
71
  }
66
72
 
67
73
  /**
@@ -1,41 +1,42 @@
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
- export const bindingsIndex = (editor: Editor): Computed<TLBindingsIndex> => {
9
- const { store } = editor
10
- const bindingsHistory = store.query.filterHistory('binding')
11
- const bindingsQuery = store.query.records('binding')
12
- function fromScratch() {
13
- const allBindings = bindingsQuery.get() as TLBinding[]
8
+ function fromScratch(bindingsQuery: Computed<(TLArrowBinding | TLUnknownBinding)[], unknown>) {
9
+ const allBindings = bindingsQuery.get() as TLBinding[]
14
10
 
15
- const shape2Binding: TLBindingsIndex = new Map()
11
+ const shapesToBindings: TLBindingsIndex = new Map()
16
12
 
17
- for (const binding of allBindings) {
18
- const { fromId, toId } = binding
19
- const bindingsForFromShape = shape2Binding.get(fromId)
20
- if (!bindingsForFromShape) {
21
- shape2Binding.set(fromId, [binding])
22
- } else {
23
- bindingsForFromShape.push(binding)
24
- }
25
- const bindingsForToShape = shape2Binding.get(toId)
26
- if (!bindingsForToShape) {
27
- shape2Binding.set(toId, [binding])
28
- } else {
29
- bindingsForToShape.push(binding)
30
- }
13
+ for (const binding of allBindings) {
14
+ const { fromId, toId } = binding
15
+ const bindingsForFromShape = shapesToBindings.get(fromId)
16
+ if (!bindingsForFromShape) {
17
+ shapesToBindings.set(fromId, [binding])
18
+ } else {
19
+ bindingsForFromShape.push(binding)
20
+ }
21
+ const bindingsForToShape = shapesToBindings.get(toId)
22
+ if (!bindingsForToShape) {
23
+ shapesToBindings.set(toId, [binding])
24
+ } else {
25
+ bindingsForToShape.push(binding)
31
26
  }
32
-
33
- return shape2Binding
34
27
  }
35
28
 
29
+ return shapesToBindings
30
+ }
31
+
32
+ export const bindingsIndex = (editor: Editor): Computed<TLBindingsIndex> => {
33
+ const { store } = editor
34
+ const bindingsHistory = store.query.filterHistory('binding')
35
+ const bindingsQuery = store.query.records('binding')
36
+
36
37
  return computed<TLBindingsIndex>('arrowBindingsIndex', (_lastValue, lastComputedEpoch) => {
37
38
  if (isUninitialized(_lastValue)) {
38
- return fromScratch()
39
+ return fromScratch(bindingsQuery)
39
40
  }
40
41
 
41
42
  const lastValue = _lastValue
@@ -43,7 +44,7 @@ export const bindingsIndex = (editor: Editor): Computed<TLBindingsIndex> => {
43
44
  const diff = bindingsHistory.getDiffSince(lastComputedEpoch)
44
45
 
45
46
  if (diff === RESET_VALUE) {
46
- return fromScratch()
47
+ return fromScratch(bindingsQuery)
47
48
  }
48
49
 
49
50
  let nextValue: TLBindingsIndex | undefined = undefined
@@ -1,49 +1,48 @@
1
1
  import { computed, isUninitialized } from '@tldraw/state'
2
2
  import { TLShapeId } from '@tldraw/tlschema'
3
- import { Box } from '../../primitives/Box'
4
3
  import { Editor } from '../Editor'
5
4
 
6
- function isShapeNotVisible(editor: Editor, id: TLShapeId, viewportPageBounds: Box): boolean {
7
- const maskedPageBounds = editor.getShapeMaskedPageBounds(id)
8
- // if the shape is fully outside of its parent's clipping bounds...
9
- if (maskedPageBounds === undefined) return true
10
-
11
- // if the shape is fully outside of the viewport page bounds...
12
- return !viewportPageBounds.includes(maskedPageBounds)
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
+ // If the shape is fully outside of the viewport page bounds, add it to the set.
11
+ // We'll ignore masks here, since they're more expensive to compute and the overhead is not worth it.
12
+ const pageBounds = editor.getShapePageBounds(id)
13
+ if (pageBounds === undefined || !viewportPageBounds.includes(pageBounds)) {
14
+ notVisibleShapes.add(id)
15
+ }
16
+ })
17
+ return notVisibleShapes
13
18
  }
14
19
 
15
20
  /**
16
21
  * Incremental derivation of not visible shapes.
17
- * Non visible shapes are shapes outside of the viewport page bounds and shapes outside of parent's clipping bounds.
22
+ * Non visible shapes are shapes outside of the viewport page bounds.
18
23
  *
19
24
  * @param editor - Instance of the tldraw Editor.
20
25
  * @returns Incremental derivation of non visible shapes.
21
26
  */
22
- export const notVisibleShapes = (editor: Editor) => {
23
- function fromScratch(editor: Editor): Set<TLShapeId> {
24
- const shapes = editor.getCurrentPageShapeIds()
25
- const viewportPageBounds = editor.getViewportPageBounds()
26
- const notVisibleShapes = new Set<TLShapeId>()
27
- shapes.forEach((id) => {
28
- if (isShapeNotVisible(editor, id, viewportPageBounds)) {
29
- notVisibleShapes.add(id)
30
- }
31
- })
32
- return notVisibleShapes
33
- }
34
- return computed<Set<TLShapeId>>('notVisibleShapes', (prevValue) => {
27
+ export function notVisibleShapes(editor: Editor) {
28
+ return computed<Set<TLShapeId>>('notVisibleShapes', function updateNotVisibleShapes(prevValue) {
29
+ const nextValue = fromScratch(editor)
30
+
35
31
  if (isUninitialized(prevValue)) {
36
- return fromScratch(editor)
32
+ return nextValue
37
33
  }
38
34
 
39
- const nextValue = fromScratch(editor)
40
-
35
+ // If there are more or less shapes, we know there's a change
41
36
  if (prevValue.size !== nextValue.size) return nextValue
37
+
38
+ // If any of the old shapes are not in the new set, we know there's a change
42
39
  for (const prev of prevValue) {
43
40
  if (!nextValue.has(prev)) {
44
41
  return nextValue
45
42
  }
46
43
  }
44
+
45
+ // If we've made it here, we know that the set is the same
47
46
  return prevValue
48
47
  })
49
48
  }
@@ -1,45 +1,48 @@
1
- import { computed, isUninitialized, RESET_VALUE } from '@tldraw/state'
2
- import { RecordsDiff } from '@tldraw/store'
1
+ import { Computed, computed, isUninitialized, RESET_VALUE } from '@tldraw/state'
2
+ import { CollectionDiff, RecordsDiff } from '@tldraw/store'
3
3
  import { isShape, TLParentId, TLRecord, TLShape, TLShapeId, TLStore } from '@tldraw/tlschema'
4
4
  import { compact, sortByIndex } from '@tldraw/utils'
5
5
 
6
- type Parents2Children = Record<TLParentId, TLShapeId[]>
6
+ type ParentShapeIdsToChildShapeIds = Record<TLParentId, TLShapeId[]>
7
7
 
8
- export const parentsToChildren = (store: TLStore) => {
9
- const shapeIdsQuery = store.query.ids<'shape'>('shape')
10
- const shapeHistory = store.query.filterHistory('shape')
8
+ function fromScratch(
9
+ shapeIdsQuery: Computed<Set<TLShapeId>, CollectionDiff<TLShapeId>>,
10
+ store: TLStore
11
+ ) {
12
+ const result: ParentShapeIdsToChildShapeIds = {}
13
+ const shapeIds = shapeIdsQuery.get()
14
+ const shapes = Array(shapeIds.size) as TLShape[]
15
+ shapeIds.forEach((id) => shapes.push(store.get(id)!))
11
16
 
12
- function fromScratch() {
13
- const result: Parents2Children = {}
14
- const shapeIds = shapeIdsQuery.get()
15
- const shapes = Array(shapeIds.size) as TLShape[]
16
- shapeIds.forEach((id) => shapes.push(store.get(id)!))
17
+ // Sort the shapes by index
18
+ shapes.sort(sortByIndex)
17
19
 
18
- // Sort the shapes by index
19
- shapes.sort(sortByIndex)
20
+ // Populate the result object with an array for each parent.
21
+ shapes.forEach((shape) => {
22
+ if (!result[shape.parentId]) {
23
+ result[shape.parentId] = []
24
+ }
25
+ result[shape.parentId].push(shape.id)
26
+ })
20
27
 
21
- // Populate the result object with an array for each parent.
22
- shapes.forEach((shape) => {
23
- if (!result[shape.parentId]) {
24
- result[shape.parentId] = []
25
- }
26
- result[shape.parentId].push(shape.id)
27
- })
28
+ return result
29
+ }
28
30
 
29
- return result
30
- }
31
+ export const parentsToChildren = (store: TLStore) => {
32
+ const shapeIdsQuery = store.query.ids<'shape'>('shape')
33
+ const shapeHistory = store.query.filterHistory('shape')
31
34
 
32
- return computed<Parents2Children>(
35
+ return computed<ParentShapeIdsToChildShapeIds>(
33
36
  'parentsToChildrenWithIndexes',
34
37
  (lastValue, lastComputedEpoch) => {
35
38
  if (isUninitialized(lastValue)) {
36
- return fromScratch()
39
+ return fromScratch(shapeIdsQuery, store)
37
40
  }
38
41
 
39
42
  const diff = shapeHistory.getDiffSince(lastComputedEpoch)
40
43
 
41
44
  if (diff === RESET_VALUE) {
42
- return fromScratch()
45
+ return fromScratch(shapeIdsQuery, store)
43
46
  }
44
47
 
45
48
  if (diff.length === 0) return lastValue