@tldraw/editor 3.14.0-canary.d926f92ca8d6 → 3.14.0-canary.db789786fb06

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 (237) hide show
  1. package/dist-cjs/index.d.ts +212 -117
  2. package/dist-cjs/index.js +11 -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 +131 -99
  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/parentsToChildren.js +16 -16
  12. package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
  13. package/dist-cjs/lib/editor/managers/{ClickManager.js → ClickManager/ClickManager.js} +1 -1
  14. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +7 -0
  15. package/dist-cjs/lib/editor/managers/{EdgeScrollManager.js → EdgeScrollManager/EdgeScrollManager.js} +2 -2
  16. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +7 -0
  17. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +7 -0
  18. package/dist-cjs/lib/editor/managers/{FontManager.js → FontManager/FontManager.js} +4 -1
  19. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +7 -0
  20. package/dist-cjs/lib/editor/managers/{HistoryManager.js → HistoryManager/HistoryManager.js} +67 -7
  21. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +7 -0
  22. package/dist-cjs/lib/editor/managers/{ScribbleManager.js → ScribbleManager/ScribbleManager.js} +1 -1
  23. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +7 -0
  24. package/dist-cjs/lib/editor/managers/{TextManager.js → TextManager/TextManager.js} +73 -42
  25. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +7 -0
  26. package/dist-cjs/lib/editor/managers/{TickManager.js → TickManager/TickManager.js} +1 -1
  27. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +7 -0
  28. package/dist-cjs/lib/editor/managers/{UserPreferencesManager.js → UserPreferencesManager/UserPreferencesManager.js} +1 -1
  29. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +7 -0
  30. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +0 -10
  31. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  32. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +1 -1
  33. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +1 -1
  34. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +10 -6
  35. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +3 -3
  36. package/dist-cjs/lib/editor/tools/StateNode.js +3 -3
  37. package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
  38. package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
  39. package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
  40. package/dist-cjs/lib/exports/getSvgJsx.js.map +1 -1
  41. package/dist-cjs/lib/hooks/useCanvasEvents.js +1 -2
  42. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  43. package/dist-cjs/lib/primitives/Box.js +33 -33
  44. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  45. package/dist-cjs/lib/primitives/Vec.js +13 -8
  46. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  47. package/dist-cjs/lib/primitives/geometry/Arc2d.js +41 -21
  48. package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
  49. package/dist-cjs/lib/primitives/geometry/Circle2d.js +11 -11
  50. package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
  51. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +13 -16
  52. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
  53. package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js +4 -4
  54. package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js.map +2 -2
  55. package/dist-cjs/lib/primitives/geometry/Edge2d.js +14 -17
  56. package/dist-cjs/lib/primitives/geometry/Edge2d.js.map +2 -2
  57. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +10 -10
  58. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
  59. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +6 -2
  60. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  61. package/dist-cjs/lib/primitives/geometry/Point2d.js +6 -6
  62. package/dist-cjs/lib/primitives/geometry/Point2d.js.map +2 -2
  63. package/dist-cjs/lib/primitives/geometry/Polygon2d.js +3 -0
  64. package/dist-cjs/lib/primitives/geometry/Polygon2d.js.map +2 -2
  65. package/dist-cjs/lib/primitives/geometry/Polyline2d.js +8 -5
  66. package/dist-cjs/lib/primitives/geometry/Polyline2d.js.map +2 -2
  67. package/dist-cjs/lib/primitives/geometry/Rectangle2d.js +22 -11
  68. package/dist-cjs/lib/primitives/geometry/Rectangle2d.js.map +2 -2
  69. package/dist-cjs/lib/primitives/geometry/Stadium2d.js +22 -22
  70. package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +2 -2
  71. package/dist-cjs/lib/utils/reorderShapes.js +11 -10
  72. package/dist-cjs/lib/utils/reorderShapes.js.map +2 -2
  73. package/dist-cjs/lib/utils/reparenting.js +232 -0
  74. package/dist-cjs/lib/utils/reparenting.js.map +7 -0
  75. package/dist-cjs/lib/utils/richText.js +7 -2
  76. package/dist-cjs/lib/utils/richText.js.map +2 -2
  77. package/dist-cjs/version.js +3 -3
  78. package/dist-cjs/version.js.map +1 -1
  79. package/dist-esm/index.d.mts +212 -117
  80. package/dist-esm/index.mjs +15 -8
  81. package/dist-esm/index.mjs.map +2 -2
  82. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs +1 -1
  83. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
  84. package/dist-esm/lib/editor/Editor.mjs +131 -99
  85. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  86. package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +2 -2
  87. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs +22 -22
  88. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs.map +2 -2
  89. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +16 -16
  90. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
  91. package/dist-esm/lib/editor/managers/{ClickManager.mjs → ClickManager/ClickManager.mjs} +1 -1
  92. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +7 -0
  93. package/dist-esm/lib/editor/managers/{EdgeScrollManager.mjs → EdgeScrollManager/EdgeScrollManager.mjs} +2 -2
  94. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +7 -0
  95. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +7 -0
  96. package/dist-esm/lib/editor/managers/{FontManager.mjs → FontManager/FontManager.mjs} +4 -1
  97. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +7 -0
  98. package/dist-esm/lib/editor/managers/{HistoryManager.mjs → HistoryManager/HistoryManager.mjs} +63 -3
  99. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +7 -0
  100. package/dist-esm/lib/editor/managers/{ScribbleManager.mjs → ScribbleManager/ScribbleManager.mjs} +1 -1
  101. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +7 -0
  102. package/dist-esm/lib/editor/managers/{TextManager.mjs → TextManager/TextManager.mjs} +73 -42
  103. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +7 -0
  104. package/dist-esm/lib/editor/managers/{TickManager.mjs → TickManager/TickManager.mjs} +1 -1
  105. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +7 -0
  106. package/dist-esm/lib/editor/managers/{UserPreferencesManager.mjs → UserPreferencesManager/UserPreferencesManager.mjs} +1 -1
  107. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +7 -0
  108. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +0 -10
  109. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  110. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +1 -1
  111. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +1 -1
  112. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +10 -6
  113. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +3 -3
  114. package/dist-esm/lib/editor/tools/StateNode.mjs +3 -3
  115. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  116. package/dist-esm/lib/exports/getSvgJsx.mjs.map +1 -1
  117. package/dist-esm/lib/hooks/useCanvasEvents.mjs +1 -2
  118. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  119. package/dist-esm/lib/primitives/Box.mjs +33 -33
  120. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  121. package/dist-esm/lib/primitives/Vec.mjs +13 -8
  122. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  123. package/dist-esm/lib/primitives/geometry/Arc2d.mjs +41 -21
  124. package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
  125. package/dist-esm/lib/primitives/geometry/Circle2d.mjs +11 -11
  126. package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
  127. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +13 -16
  128. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
  129. package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs +4 -4
  130. package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs.map +2 -2
  131. package/dist-esm/lib/primitives/geometry/Edge2d.mjs +14 -17
  132. package/dist-esm/lib/primitives/geometry/Edge2d.mjs.map +2 -2
  133. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +11 -11
  134. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
  135. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +6 -2
  136. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  137. package/dist-esm/lib/primitives/geometry/Point2d.mjs +6 -6
  138. package/dist-esm/lib/primitives/geometry/Point2d.mjs.map +2 -2
  139. package/dist-esm/lib/primitives/geometry/Polygon2d.mjs +3 -0
  140. package/dist-esm/lib/primitives/geometry/Polygon2d.mjs.map +2 -2
  141. package/dist-esm/lib/primitives/geometry/Polyline2d.mjs +8 -5
  142. package/dist-esm/lib/primitives/geometry/Polyline2d.mjs.map +2 -2
  143. package/dist-esm/lib/primitives/geometry/Rectangle2d.mjs +22 -11
  144. package/dist-esm/lib/primitives/geometry/Rectangle2d.mjs.map +2 -2
  145. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +22 -22
  146. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +2 -2
  147. package/dist-esm/lib/utils/reorderShapes.mjs +11 -10
  148. package/dist-esm/lib/utils/reorderShapes.mjs.map +2 -2
  149. package/dist-esm/lib/utils/reparenting.mjs +216 -0
  150. package/dist-esm/lib/utils/reparenting.mjs.map +7 -0
  151. package/dist-esm/lib/utils/richText.mjs +8 -3
  152. package/dist-esm/lib/utils/richText.mjs.map +2 -2
  153. package/dist-esm/version.mjs +3 -3
  154. package/dist-esm/version.mjs.map +1 -1
  155. package/editor.css +442 -492
  156. package/package.json +8 -9
  157. package/src/index.ts +20 -7
  158. package/src/lib/config/TLSessionStateSnapshot.ts +1 -1
  159. package/src/lib/editor/Editor.test.ts +252 -3
  160. package/src/lib/editor/Editor.ts +149 -107
  161. package/src/lib/editor/bindings/BindingUtil.ts +6 -0
  162. package/src/lib/editor/derivations/bindingsIndex.ts +27 -26
  163. package/src/lib/editor/derivations/parentsToChildren.ts +28 -25
  164. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +442 -0
  165. package/src/lib/editor/managers/{ClickManager.ts → ClickManager/ClickManager.ts} +3 -3
  166. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +374 -0
  167. package/src/lib/editor/managers/{EdgeScrollManager.ts → EdgeScrollManager/EdgeScrollManager.ts} +3 -3
  168. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +455 -0
  169. package/src/lib/editor/managers/{FocusManager.ts → FocusManager/FocusManager.ts} +1 -1
  170. package/src/lib/editor/managers/FontManager/FontManager.test.ts +263 -0
  171. package/src/lib/editor/managers/{FontManager.ts → FontManager/FontManager.ts} +5 -2
  172. package/src/lib/editor/managers/{HistoryManager.test.ts → HistoryManager/HistoryManager.test.ts} +388 -1
  173. package/src/lib/editor/managers/{HistoryManager.ts → HistoryManager/HistoryManager.ts} +76 -3
  174. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +624 -0
  175. package/src/lib/editor/managers/{ScribbleManager.ts → ScribbleManager/ScribbleManager.ts} +2 -2
  176. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +485 -0
  177. package/src/lib/editor/managers/TextManager/TextManager.test.ts +407 -0
  178. package/src/lib/editor/managers/{TextManager.ts → TextManager/TextManager.ts} +119 -87
  179. package/src/lib/editor/managers/TickManager/TickManager.test.ts +314 -0
  180. package/src/lib/editor/managers/{TickManager.ts → TickManager/TickManager.ts} +2 -2
  181. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +591 -0
  182. package/src/lib/editor/managers/{UserPreferencesManager.ts → UserPreferencesManager/UserPreferencesManager.ts} +2 -2
  183. package/src/lib/editor/shapes/ShapeUtil.ts +48 -16
  184. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +1 -1
  185. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +22 -17
  186. package/src/lib/editor/tools/StateNode.ts +3 -3
  187. package/src/lib/editor/types/emit-types.ts +4 -0
  188. package/src/lib/editor/types/external-content.ts +11 -2
  189. package/src/lib/exports/getSvgJsx.tsx +1 -1
  190. package/src/lib/hooks/useCanvasEvents.ts +0 -1
  191. package/src/lib/primitives/Box.test.ts +588 -7
  192. package/src/lib/primitives/Box.ts +33 -33
  193. package/src/lib/primitives/Vec.test.ts +2 -2
  194. package/src/lib/primitives/Vec.ts +13 -8
  195. package/src/lib/primitives/geometry/Arc2d.ts +42 -23
  196. package/src/lib/primitives/geometry/Circle2d.ts +12 -12
  197. package/src/lib/primitives/geometry/CubicBezier2d.test.ts +5 -0
  198. package/src/lib/primitives/geometry/CubicBezier2d.ts +13 -17
  199. package/src/lib/primitives/geometry/CubicSpline2d.ts +5 -5
  200. package/src/lib/primitives/geometry/Edge2d.ts +14 -18
  201. package/src/lib/primitives/geometry/Ellipse2d.ts +12 -13
  202. package/src/lib/primitives/geometry/Geometry2d.ts +7 -2
  203. package/src/lib/primitives/geometry/Point2d.ts +6 -6
  204. package/src/lib/primitives/geometry/Polygon2d.ts +4 -0
  205. package/src/lib/primitives/geometry/Polyline2d.ts +10 -7
  206. package/src/lib/primitives/geometry/Rectangle2d.ts +24 -11
  207. package/src/lib/primitives/geometry/Stadium2d.ts +22 -23
  208. package/src/lib/utils/reorderShapes.ts +10 -13
  209. package/src/lib/utils/reparenting.ts +383 -0
  210. package/src/lib/utils/richText.ts +10 -4
  211. package/src/version.ts +3 -3
  212. package/dist-cjs/lib/editor/managers/ClickManager.js.map +0 -7
  213. package/dist-cjs/lib/editor/managers/EdgeScrollManager.js.map +0 -7
  214. package/dist-cjs/lib/editor/managers/FocusManager.js.map +0 -7
  215. package/dist-cjs/lib/editor/managers/FontManager.js.map +0 -7
  216. package/dist-cjs/lib/editor/managers/HistoryManager.js.map +0 -7
  217. package/dist-cjs/lib/editor/managers/ScribbleManager.js.map +0 -7
  218. package/dist-cjs/lib/editor/managers/Stack.js +0 -82
  219. package/dist-cjs/lib/editor/managers/Stack.js.map +0 -7
  220. package/dist-cjs/lib/editor/managers/TextManager.js.map +0 -7
  221. package/dist-cjs/lib/editor/managers/TickManager.js.map +0 -7
  222. package/dist-cjs/lib/editor/managers/UserPreferencesManager.js.map +0 -7
  223. package/dist-esm/lib/editor/managers/ClickManager.mjs.map +0 -7
  224. package/dist-esm/lib/editor/managers/EdgeScrollManager.mjs.map +0 -7
  225. package/dist-esm/lib/editor/managers/FocusManager.mjs.map +0 -7
  226. package/dist-esm/lib/editor/managers/FontManager.mjs.map +0 -7
  227. package/dist-esm/lib/editor/managers/HistoryManager.mjs.map +0 -7
  228. package/dist-esm/lib/editor/managers/ScribbleManager.mjs.map +0 -7
  229. package/dist-esm/lib/editor/managers/Stack.mjs +0 -62
  230. package/dist-esm/lib/editor/managers/Stack.mjs.map +0 -7
  231. package/dist-esm/lib/editor/managers/TextManager.mjs.map +0 -7
  232. package/dist-esm/lib/editor/managers/TickManager.mjs.map +0 -7
  233. package/dist-esm/lib/editor/managers/UserPreferencesManager.mjs.map +0 -7
  234. package/src/lib/editor/managers/ScribbleManager.test.ts +0 -32
  235. package/src/lib/editor/managers/Stack.ts +0 -71
  236. /package/dist-cjs/lib/editor/managers/{FocusManager.js → FocusManager/FocusManager.js} +0 -0
  237. /package/dist-esm/lib/editor/managers/{FocusManager.mjs → FocusManager/FocusManager.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
  },
@@ -348,6 +348,8 @@ export class Editor extends EventEmitter<TLEventMap> {
348
348
  this.getContainer = getContainer
349
349
 
350
350
  this.textMeasure = new TextManager(this)
351
+ this.disposables.add(() => this.textMeasure.dispose())
352
+
351
353
  this.fonts = new FontManager(this, fontAssetUrls)
352
354
 
353
355
  this._tickManager = new TickManager(this)
@@ -512,6 +514,7 @@ export class Editor extends EventEmitter<TLEventMap> {
512
514
  binding,
513
515
  shapeBefore,
514
516
  shapeAfter,
517
+ reason: 'self',
515
518
  })
516
519
  }
517
520
  if (binding.toId === shapeAfter.id) {
@@ -519,6 +522,7 @@ export class Editor extends EventEmitter<TLEventMap> {
519
522
  binding,
520
523
  shapeBefore,
521
524
  shapeAfter,
525
+ reason: 'self',
522
526
  })
523
527
  }
524
528
  }
@@ -537,6 +541,7 @@ export class Editor extends EventEmitter<TLEventMap> {
537
541
  binding,
538
542
  shapeBefore: descendantShape,
539
543
  shapeAfter: descendantShape,
544
+ reason: 'ancestry',
540
545
  })
541
546
  }
542
547
  if (binding.toId === descendantShape.id) {
@@ -544,6 +549,7 @@ export class Editor extends EventEmitter<TLEventMap> {
544
549
  binding,
545
550
  shapeBefore: descendantShape,
546
551
  shapeAfter: descendantShape,
552
+ reason: 'ancestry',
547
553
  })
548
554
  }
549
555
  }
@@ -2116,6 +2122,20 @@ export class Editor extends EventEmitter<TLEventMap> {
2116
2122
  return this.getShapesPageBounds(this.getSelectedShapeIds())
2117
2123
  }
2118
2124
 
2125
+ /**
2126
+ * The bounds of the selection bounding box in the current page space.
2127
+ *
2128
+ * @readonly
2129
+ * @public
2130
+ */
2131
+ getSelectionScreenBounds(): Box | undefined {
2132
+ const bounds = this.getSelectionPageBounds()
2133
+ if (!bounds) return undefined
2134
+ const { x, y } = this.pageToScreen(bounds.point)
2135
+ const zoom = this.getZoomLevel()
2136
+ return new Box(x, y, bounds.width * zoom, bounds.height * zoom)
2137
+ }
2138
+
2119
2139
  /**
2120
2140
  * @internal
2121
2141
  */
@@ -3715,10 +3735,7 @@ export class Editor extends EventEmitter<TLEventMap> {
3715
3735
  */
3716
3736
  @computed getViewportScreenCenter() {
3717
3737
  const viewportScreenBounds = this.getViewportScreenBounds()
3718
- return new Vec(
3719
- viewportScreenBounds.midX - viewportScreenBounds.minX,
3720
- viewportScreenBounds.midY - viewportScreenBounds.minY
3721
- )
3738
+ return new Vec(viewportScreenBounds.w / 2, viewportScreenBounds.h / 2)
3722
3739
  }
3723
3740
 
3724
3741
  /**
@@ -4644,44 +4661,6 @@ export class Editor extends EventEmitter<TLEventMap> {
4644
4661
  )! as T
4645
4662
  }
4646
4663
 
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
4664
  /** @internal */
4686
4665
  @computed private _getShapeHandlesCache(): ComputedCache<TLHandle[] | undefined, TLShape> {
4687
4666
  return this.store.createComputedCache(
@@ -4794,7 +4773,10 @@ export class Editor extends EventEmitter<TLEventMap> {
4794
4773
  /** @internal */
4795
4774
  @computed private _getShapePageBoundsCache(): ComputedCache<Box, TLShape> {
4796
4775
  return this.store.createComputedCache<Box, TLShape>('pageBoundsCache', (shape) => {
4797
- return this.getShapePageGeometry(shape).bounds
4776
+ const pageTransform = this.getShapePageTransform(shape)
4777
+ if (!pageTransform) return undefined
4778
+ const geometry = this.getShapeGeometry(shape)
4779
+ return Box.FromPoints(pageTransform.applyToPoints(geometry.vertices))
4798
4780
  })
4799
4781
  }
4800
4782
 
@@ -4868,11 +4850,12 @@ export class Editor extends EventEmitter<TLEventMap> {
4868
4850
  if (frameAncestors.length === 0) return undefined
4869
4851
 
4870
4852
  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
- )
4853
+ .map<Vec[] | undefined>((s) => {
4854
+ // Apply the frame transform to the frame outline to get the frame outline in the current page space
4855
+ const geometry = this.getShapeGeometry(s.id)
4856
+ const pageTransform = this.getShapePageTransform(s.id)
4857
+ return pageTransform.applyToPoints(geometry.vertices)
4858
+ })
4876
4859
  .reduce((acc, b) => {
4877
4860
  if (!(b && acc)) return undefined
4878
4861
  const intersection = intersectPolygonPolygon(acc, b)
@@ -5070,28 +5053,33 @@ export class Editor extends EventEmitter<TLEventMap> {
5070
5053
  *
5071
5054
  * @public
5072
5055
  */
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))
5056
+ isShapeOrAncestorLocked(shape?: TLShape | TLShapeId): boolean {
5057
+ const _shape = shape && this.getShape(shape)
5058
+ if (_shape === undefined) return false
5059
+ if (_shape.isLocked) return true
5060
+ return this.isShapeOrAncestorLocked(this.getShapeParent(_shape))
5080
5061
  }
5081
5062
 
5063
+ /**
5064
+ * Get shapes that are outside of the viewport.
5065
+ *
5066
+ * @public
5067
+ */
5082
5068
  @computed
5083
- private _notVisibleShapes() {
5084
- return notVisibleShapes(this)
5069
+ getNotVisibleShapes() {
5070
+ return this._notVisibleShapes.get()
5085
5071
  }
5086
5072
 
5073
+ private _notVisibleShapes = notVisibleShapes(this)
5074
+
5087
5075
  /**
5088
- * Get culled shapes.
5076
+ * Get culled shapes (those that should not render), taking into account which shapes are selected or editing.
5089
5077
  *
5090
5078
  * @public
5091
5079
  */
5092
5080
  @computed
5093
5081
  getCulledShapes() {
5094
- const notVisibleShapes = this._notVisibleShapes().get()
5082
+ const notVisibleShapes = this.getNotVisibleShapes()
5095
5083
  const selectedShapeIds = this.getSelectedShapeIds()
5096
5084
  const editingId = this.getEditingShapeId()
5097
5085
  const culledShapes = new Set<TLShapeId>(notVisibleShapes)
@@ -5340,21 +5328,23 @@ export class Editor extends EventEmitter<TLEventMap> {
5340
5328
  * @example
5341
5329
  * ```ts
5342
5330
  * editor.getShapesAtPoint({ x: 100, y: 100 })
5343
- * editor.getShapesAtPoint({ x: 100, y: 100 }, { hitInside: true, exact: true })
5331
+ * editor.getShapesAtPoint({ x: 100, y: 100 }, { hitInside: true, margin: 8 })
5344
5332
  * ```
5345
5333
  *
5346
5334
  * @param point - The page point to test.
5347
5335
  * @param opts - The options for the hit point testing.
5348
5336
  *
5337
+ * @returns An array of shapes at the given point, sorted in reverse order of their absolute z-index (top-most shape first).
5338
+ *
5349
5339
  * @public
5350
5340
  */
5351
5341
  getShapesAtPoint(
5352
5342
  point: VecLike,
5353
5343
  opts = {} as { margin?: number; hitInside?: boolean }
5354
5344
  ): TLShape[] {
5355
- return this.getCurrentPageShapes().filter(
5356
- (shape) => !this.isShapeHidden(shape) && this.isPointInShape(shape, point, opts)
5357
- )
5345
+ return this.getCurrentPageShapesSorted()
5346
+ .filter((shape) => !this.isShapeHidden(shape) && this.isPointInShape(shape, point, opts))
5347
+ .reverse()
5358
5348
  }
5359
5349
 
5360
5350
  /**
@@ -5538,7 +5528,7 @@ export class Editor extends EventEmitter<TLEventMap> {
5538
5528
  if (!id) return undefined
5539
5529
  const freshShape = this.getShape(id)
5540
5530
  if (freshShape === undefined || !isShapeId(freshShape.parentId)) return undefined
5541
- return this.store.get(freshShape.parentId)
5531
+ return this.getShape(freshShape.parentId)
5542
5532
  }
5543
5533
 
5544
5534
  /**
@@ -5721,6 +5711,10 @@ export class Editor extends EventEmitter<TLEventMap> {
5721
5711
  const newPoint = invertedParentTransform.applyToPoint(pagePoint)
5722
5712
  const newRotation = pageTransform.rotation() - parentPageRotation
5723
5713
 
5714
+ if (shape.id === parentId) {
5715
+ throw Error('Attempted to reparent a shape to itself!')
5716
+ }
5717
+
5724
5718
  changes.push({
5725
5719
  id: shape.id,
5726
5720
  type: shape.type,
@@ -5824,6 +5818,11 @@ export class Editor extends EventEmitter<TLEventMap> {
5824
5818
  return shapeIds
5825
5819
  }
5826
5820
 
5821
+ /** @deprecated Use {@link Editor.getDraggingOverShape} instead */
5822
+ getDroppingOverShape(point: Vec, droppingShapes: TLShape[]): TLShape | undefined {
5823
+ return this.getDraggingOverShape(point, droppingShapes)
5824
+ }
5825
+
5827
5826
  /**
5828
5827
  * Get the shape that some shapes should be dropped on at a given point.
5829
5828
  *
@@ -5834,35 +5833,33 @@ export class Editor extends EventEmitter<TLEventMap> {
5834
5833
  *
5835
5834
  * @public
5836
5835
  */
5837
- getDroppingOverShape(point: VecLike, droppingShapes: TLShape[] = []) {
5838
- // starting from the top...
5839
- const currentPageShapesSorted = this.getCurrentPageShapesSorted()
5840
- for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
5841
- const shape = currentPageShapesSorted[i]
5842
-
5843
- if (
5844
- // ignore hidden shapes
5845
- this.isShapeHidden(shape) ||
5846
- // don't allow dropping on selected shapes
5847
- this.getSelectedShapeIds().includes(shape.id) ||
5848
- // only allow shapes that can receive children
5849
- !this.getShapeUtil(shape).canDropShapes(shape, droppingShapes) ||
5850
- // don't allow dropping a shape on itself or one of it's children
5851
- droppingShapes.find((s) => s.id === shape.id || this.hasAncestor(shape, s.id))
5852
- ) {
5853
- continue
5854
- }
5836
+ getDraggingOverShape(point: Vec, droppingShapes: TLShape[]): TLShape | undefined {
5837
+ // get fresh moving shapes
5838
+ const draggingShapes = compact(droppingShapes.map((s) => this.getShape(s))).filter(
5839
+ (s) => !s.isLocked && !this.isShapeHidden(s)
5840
+ )
5855
5841
 
5856
- // Only allow dropping into the masked page bounds of the shape, e.g. when a frame is
5857
- // partially clipped by its own parent frame
5858
- const maskedPageBounds = this.getShapeMaskedPageBounds(shape.id)
5842
+ const maybeDraggingOverShapes = this.getShapesAtPoint(point, {
5843
+ hitInside: true,
5844
+ margin: 0,
5845
+ }).filter(
5846
+ (s) =>
5847
+ !droppingShapes.includes(s) &&
5848
+ !s.isLocked &&
5849
+ !this.isShapeHidden(s) &&
5850
+ !draggingShapes.includes(s)
5851
+ )
5859
5852
 
5853
+ for (const maybeDraggingOverShape of maybeDraggingOverShapes) {
5854
+ const shapeUtil = this.getShapeUtil(maybeDraggingOverShape)
5855
+ // Any shape that can handle any dragging interactions is a valid target
5860
5856
  if (
5861
- maskedPageBounds &&
5862
- maskedPageBounds.containsPoint(point) &&
5863
- this.getShapeGeometry(shape).hitTestPoint(this.getPointInShapeSpace(shape, point), 0, true)
5857
+ shapeUtil.onDragShapesOver ||
5858
+ shapeUtil.onDragShapesIn ||
5859
+ shapeUtil.onDragShapesOut ||
5860
+ shapeUtil.onDropShapesOver
5864
5861
  ) {
5865
- return shape
5862
+ return maybeDraggingOverShape
5866
5863
  }
5867
5864
  }
5868
5865
  }
@@ -6221,11 +6218,12 @@ export class Editor extends EventEmitter<TLEventMap> {
6221
6218
  */
6222
6219
  duplicateShapes(shapes: TLShapeId[] | TLShape[], offset?: VecLike): this {
6223
6220
  this.run(() => {
6224
- const ids =
6221
+ const _ids =
6225
6222
  typeof shapes[0] === 'string'
6226
6223
  ? (shapes as TLShapeId[])
6227
6224
  : (shapes as TLShape[]).map((s) => s.id)
6228
6225
 
6226
+ const ids = this._shouldIgnoreShapeLock ? _ids : this._getUnlockedShapeIds(_ids)
6229
6227
  if (ids.length <= 0) return this
6230
6228
 
6231
6229
  const initialIds = new Set(ids)
@@ -6305,10 +6303,7 @@ export class Editor extends EventEmitter<TLEventMap> {
6305
6303
  })
6306
6304
  const shapesToCreate = shapesToCreateWithOriginals.map(({ shape }) => shape)
6307
6305
 
6308
- const maxShapesReached =
6309
- shapesToCreate.length + this.getCurrentPageShapeIds().size > this.options.maxShapesPerPage
6310
-
6311
- if (maxShapesReached) {
6306
+ if (!this.canCreateShapes(shapesToCreate)) {
6312
6307
  alertMaxShapes(this)
6313
6308
  return
6314
6309
  }
@@ -7737,6 +7732,32 @@ export class Editor extends EventEmitter<TLEventMap> {
7737
7732
  return {}
7738
7733
  }
7739
7734
 
7735
+ /**
7736
+ * Get whether the provided shape can be created.
7737
+ *
7738
+ * @param shape - The shape or shape IDs to check.
7739
+ *
7740
+ * @public
7741
+ */
7742
+ canCreateShape<T extends TLUnknownShape>(
7743
+ shape: OptionalKeys<TLShapePartial<T>, 'id'> | T['id']
7744
+ ): boolean {
7745
+ return this.canCreateShapes([shape])
7746
+ }
7747
+
7748
+ /**
7749
+ * Get whether the provided shapes can be created.
7750
+ *
7751
+ * @param shapes - The shapes or shape IDs to create.
7752
+ *
7753
+ * @public
7754
+ */
7755
+ canCreateShapes<T extends TLUnknownShape>(
7756
+ shapes: (T['id'] | OptionalKeys<TLShapePartial<T>, 'id'>)[]
7757
+ ): boolean {
7758
+ return shapes.length + this.getCurrentPageShapeIds().size <= this.options.maxShapesPerPage
7759
+ }
7760
+
7740
7761
  /**
7741
7762
  * Create a single shape.
7742
7763
  *
@@ -7783,6 +7804,7 @@ export class Editor extends EventEmitter<TLEventMap> {
7783
7804
  if (maxShapesReached) {
7784
7805
  // can't create more shapes than fit on the page
7785
7806
  alertMaxShapes(this)
7807
+ // todo: throw an error here? Otherwise we'll need to check every time whether the shapes were actually created
7786
7808
  return this
7787
7809
  }
7788
7810
 
@@ -7815,9 +7837,10 @@ export class Editor extends EventEmitter<TLEventMap> {
7815
7837
 
7816
7838
  for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
7817
7839
  const parent = currentPageShapesSorted[i]
7840
+ const util = this.getShapeUtil(parent)
7818
7841
  if (
7842
+ util.canReceiveNewChildrenOfType(parent, partial.type) &&
7819
7843
  !this.isShapeHidden(parent) &&
7820
- this.getShapeUtil(parent).canReceiveNewChildrenOfType(parent, partial.type) &&
7821
7844
  this.isPointInShape(
7822
7845
  parent,
7823
7846
  // If no parent is provided, then we can treat the
@@ -7946,6 +7969,8 @@ export class Editor extends EventEmitter<TLEventMap> {
7946
7969
  }
7947
7970
  })
7948
7971
 
7972
+ this.emit('created-shapes', shapeRecordsToCreate)
7973
+ this.emit('edit')
7949
7974
  this.store.put(shapeRecordsToCreate)
7950
7975
  })
7951
7976
 
@@ -8340,6 +8365,8 @@ export class Editor extends EventEmitter<TLEventMap> {
8340
8365
  updates.push(updated)
8341
8366
  }
8342
8367
 
8368
+ this.emit('edited-shapes', updates)
8369
+ this.emit('edit')
8343
8370
  this.store.put(updates)
8344
8371
  })
8345
8372
  }
@@ -8389,6 +8416,8 @@ export class Editor extends EventEmitter<TLEventMap> {
8389
8416
  })
8390
8417
  }
8391
8418
 
8419
+ this.emit('deleted-shapes', [...allShapeIdsToDelete])
8420
+ this.emit('edit')
8392
8421
  return this.run(() => this.store.remove([...allShapeIdsToDelete]))
8393
8422
  }
8394
8423
 
@@ -8837,6 +8866,7 @@ export class Editor extends EventEmitter<TLEventMap> {
8837
8866
  } = {
8838
8867
  text: null,
8839
8868
  files: null,
8869
+ 'file-replace': null,
8840
8870
  embed: null,
8841
8871
  'svg-text': null,
8842
8872
  url: null,
@@ -8886,6 +8916,15 @@ export class Editor extends EventEmitter<TLEventMap> {
8886
8916
  return this.externalContentHandlers[info.type]?.(info as any)
8887
8917
  }
8888
8918
 
8919
+ /**
8920
+ * Handle replacing external content.
8921
+ *
8922
+ * @param info - Info about the external content.
8923
+ */
8924
+ async replaceExternalContent<E>(info: TLExternalContent<E>): Promise<void> {
8925
+ return this.externalContentHandlers[info.type]?.(info as any)
8926
+ }
8927
+
8889
8928
  /**
8890
8929
  * Get content that can be exported for the given shape ids.
8891
8930
  *
@@ -9303,6 +9342,7 @@ export class Editor extends EventEmitter<TLEventMap> {
9303
9342
  if (rootShapes.length === 1) {
9304
9343
  const onlyRoot = rootShapes[0] as TLFrameShape
9305
9344
  // If the old bounds are in the viewport...
9345
+ // todo: replace frame references with shapes that can accept children
9306
9346
  if (this.isShapeOfType<TLFrameShape>(onlyRoot, 'frame')) {
9307
9347
  while (
9308
9348
  this.getShapesAtPoint(point).some(
@@ -9504,6 +9544,8 @@ export class Editor extends EventEmitter<TLEventMap> {
9504
9544
  previousPagePoint,
9505
9545
  currentScreenPoint,
9506
9546
  currentPagePoint,
9547
+ originScreenPoint,
9548
+ originPagePoint,
9507
9549
  } = this.inputs
9508
9550
 
9509
9551
  const { screenBounds } = this.store.unsafeGetWithoutCapture(TLINSTANCE_ID)!
@@ -9532,8 +9574,8 @@ export class Editor extends EventEmitter<TLEventMap> {
9532
9574
  // Reset velocity on pointer down, or when a pinch starts or ends
9533
9575
  if (info.name === 'pointer_down' || this.inputs.isPinching) {
9534
9576
  pointerVelocity.set(0, 0)
9535
- this.inputs.originScreenPoint.setTo(currentScreenPoint)
9536
- this.inputs.originPagePoint.setTo(currentPagePoint)
9577
+ originScreenPoint.setTo(currentScreenPoint)
9578
+ originPagePoint.setTo(currentPagePoint)
9537
9579
  }
9538
9580
 
9539
9581
  // todo: We only have to do this if there are multiple users in the document
@@ -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,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