@tldraw/editor 3.14.0-canary.67f5b0896cc3 → 3.14.0-canary.6c9c0f761ef8

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 (133) hide show
  1. package/dist-cjs/index.d.ts +16 -21
  2. package/dist-cjs/index.js +10 -8
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/editor/Editor.js +43 -71
  5. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  6. package/dist-cjs/lib/editor/derivations/bindingsIndex.js +22 -22
  7. package/dist-cjs/lib/editor/derivations/bindingsIndex.js.map +2 -2
  8. package/dist-cjs/lib/editor/derivations/parentsToChildren.js +16 -16
  9. package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
  10. package/dist-cjs/lib/editor/managers/{ClickManager.js → ClickManager/ClickManager.js} +1 -1
  11. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +7 -0
  12. package/dist-cjs/lib/editor/managers/{EdgeScrollManager.js → EdgeScrollManager/EdgeScrollManager.js} +2 -2
  13. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +7 -0
  14. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +7 -0
  15. package/dist-cjs/lib/editor/managers/{FontManager.js → FontManager/FontManager.js} +5 -1
  16. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +7 -0
  17. package/dist-cjs/lib/editor/managers/{HistoryManager.js → HistoryManager/HistoryManager.js} +64 -6
  18. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +7 -0
  19. package/dist-cjs/lib/editor/managers/{ScribbleManager.js → ScribbleManager/ScribbleManager.js} +1 -1
  20. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +7 -0
  21. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +7 -0
  22. package/dist-cjs/lib/editor/managers/{TickManager.js → TickManager/TickManager.js} +1 -1
  23. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +7 -0
  24. package/dist-cjs/lib/editor/managers/{UserPreferencesManager.js → UserPreferencesManager/UserPreferencesManager.js} +1 -1
  25. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +7 -0
  26. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +1 -1
  27. package/dist-cjs/lib/exports/getSvgJsx.js.map +1 -1
  28. package/dist-cjs/lib/primitives/Box.js +39 -33
  29. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  30. package/dist-cjs/lib/utils/areShapesContentEqual.js +1 -1
  31. package/dist-cjs/lib/utils/areShapesContentEqual.js.map +2 -2
  32. package/dist-cjs/lib/utils/reorderShapes.js +11 -10
  33. package/dist-cjs/lib/utils/reorderShapes.js.map +2 -2
  34. package/dist-cjs/lib/utils/richText.js.map +1 -1
  35. package/dist-cjs/version.js +3 -3
  36. package/dist-cjs/version.js.map +1 -1
  37. package/dist-esm/index.d.mts +16 -21
  38. package/dist-esm/index.mjs +14 -8
  39. package/dist-esm/index.mjs.map +2 -2
  40. package/dist-esm/lib/editor/Editor.mjs +43 -71
  41. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  42. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs +22 -22
  43. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs.map +2 -2
  44. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +16 -16
  45. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
  46. package/dist-esm/lib/editor/managers/{ClickManager.mjs → ClickManager/ClickManager.mjs} +1 -1
  47. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +7 -0
  48. package/dist-esm/lib/editor/managers/{EdgeScrollManager.mjs → EdgeScrollManager/EdgeScrollManager.mjs} +2 -2
  49. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +7 -0
  50. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +7 -0
  51. package/dist-esm/lib/editor/managers/{FontManager.mjs → FontManager/FontManager.mjs} +5 -1
  52. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +7 -0
  53. package/dist-esm/lib/editor/managers/{HistoryManager.mjs → HistoryManager/HistoryManager.mjs} +60 -2
  54. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +7 -0
  55. package/dist-esm/lib/editor/managers/{ScribbleManager.mjs → ScribbleManager/ScribbleManager.mjs} +1 -1
  56. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +7 -0
  57. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +7 -0
  58. package/dist-esm/lib/editor/managers/{TickManager.mjs → TickManager/TickManager.mjs} +1 -1
  59. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +7 -0
  60. package/dist-esm/lib/editor/managers/{UserPreferencesManager.mjs → UserPreferencesManager/UserPreferencesManager.mjs} +1 -1
  61. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +7 -0
  62. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +1 -1
  63. package/dist-esm/lib/exports/getSvgJsx.mjs.map +1 -1
  64. package/dist-esm/lib/primitives/Box.mjs +39 -33
  65. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  66. package/dist-esm/lib/utils/areShapesContentEqual.mjs +1 -1
  67. package/dist-esm/lib/utils/areShapesContentEqual.mjs.map +2 -2
  68. package/dist-esm/lib/utils/reorderShapes.mjs +11 -10
  69. package/dist-esm/lib/utils/reorderShapes.mjs.map +2 -2
  70. package/dist-esm/lib/utils/richText.mjs.map +1 -1
  71. package/dist-esm/version.mjs +3 -3
  72. package/dist-esm/version.mjs.map +1 -1
  73. package/package.json +7 -7
  74. package/src/index.ts +14 -7
  75. package/src/lib/editor/Editor.test.ts +252 -3
  76. package/src/lib/editor/Editor.ts +46 -73
  77. package/src/lib/editor/derivations/bindingsIndex.ts +27 -26
  78. package/src/lib/editor/derivations/parentsToChildren.ts +28 -25
  79. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +442 -0
  80. package/src/lib/editor/managers/{ClickManager.ts → ClickManager/ClickManager.ts} +3 -3
  81. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +374 -0
  82. package/src/lib/editor/managers/{EdgeScrollManager.ts → EdgeScrollManager/EdgeScrollManager.ts} +3 -3
  83. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +455 -0
  84. package/src/lib/editor/managers/{FocusManager.ts → FocusManager/FocusManager.ts} +1 -1
  85. package/src/lib/editor/managers/FontManager/FontManager.test.ts +263 -0
  86. package/src/lib/editor/managers/{FontManager.ts → FontManager/FontManager.ts} +6 -2
  87. package/src/lib/editor/managers/{HistoryManager.test.ts → HistoryManager/HistoryManager.test.ts} +388 -1
  88. package/src/lib/editor/managers/{HistoryManager.ts → HistoryManager/HistoryManager.ts} +73 -2
  89. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +624 -0
  90. package/src/lib/editor/managers/{ScribbleManager.ts → ScribbleManager/ScribbleManager.ts} +2 -2
  91. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +485 -0
  92. package/src/lib/editor/managers/TextManager/TextManager.test.ts +411 -0
  93. package/src/lib/editor/managers/{TextManager.ts → TextManager/TextManager.ts} +1 -1
  94. package/src/lib/editor/managers/TickManager/TickManager.test.ts +314 -0
  95. package/src/lib/editor/managers/{TickManager.ts → TickManager/TickManager.ts} +2 -2
  96. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +591 -0
  97. package/src/lib/editor/managers/{UserPreferencesManager.ts → UserPreferencesManager/UserPreferencesManager.ts} +2 -2
  98. package/src/lib/editor/shapes/ShapeUtil.ts +1 -1
  99. package/src/lib/exports/getSvgJsx.tsx +1 -1
  100. package/src/lib/primitives/Box.test.ts +588 -7
  101. package/src/lib/primitives/Box.ts +41 -33
  102. package/src/lib/utils/areShapesContentEqual.ts +2 -1
  103. package/src/lib/utils/reorderShapes.ts +10 -13
  104. package/src/lib/utils/richText.ts +1 -1
  105. package/src/version.ts +3 -3
  106. package/dist-cjs/lib/editor/managers/ClickManager.js.map +0 -7
  107. package/dist-cjs/lib/editor/managers/EdgeScrollManager.js.map +0 -7
  108. package/dist-cjs/lib/editor/managers/FocusManager.js.map +0 -7
  109. package/dist-cjs/lib/editor/managers/FontManager.js.map +0 -7
  110. package/dist-cjs/lib/editor/managers/HistoryManager.js.map +0 -7
  111. package/dist-cjs/lib/editor/managers/ScribbleManager.js.map +0 -7
  112. package/dist-cjs/lib/editor/managers/Stack.js +0 -82
  113. package/dist-cjs/lib/editor/managers/Stack.js.map +0 -7
  114. package/dist-cjs/lib/editor/managers/TextManager.js.map +0 -7
  115. package/dist-cjs/lib/editor/managers/TickManager.js.map +0 -7
  116. package/dist-cjs/lib/editor/managers/UserPreferencesManager.js.map +0 -7
  117. package/dist-esm/lib/editor/managers/ClickManager.mjs.map +0 -7
  118. package/dist-esm/lib/editor/managers/EdgeScrollManager.mjs.map +0 -7
  119. package/dist-esm/lib/editor/managers/FocusManager.mjs.map +0 -7
  120. package/dist-esm/lib/editor/managers/FontManager.mjs.map +0 -7
  121. package/dist-esm/lib/editor/managers/HistoryManager.mjs.map +0 -7
  122. package/dist-esm/lib/editor/managers/ScribbleManager.mjs.map +0 -7
  123. package/dist-esm/lib/editor/managers/Stack.mjs +0 -62
  124. package/dist-esm/lib/editor/managers/Stack.mjs.map +0 -7
  125. package/dist-esm/lib/editor/managers/TextManager.mjs.map +0 -7
  126. package/dist-esm/lib/editor/managers/TickManager.mjs.map +0 -7
  127. package/dist-esm/lib/editor/managers/UserPreferencesManager.mjs.map +0 -7
  128. package/src/lib/editor/managers/ScribbleManager.test.ts +0 -32
  129. package/src/lib/editor/managers/Stack.ts +0 -71
  130. /package/dist-cjs/lib/editor/managers/{FocusManager.js → FocusManager/FocusManager.js} +0 -0
  131. /package/dist-cjs/lib/editor/managers/{TextManager.js → TextManager/TextManager.js} +0 -0
  132. /package/dist-esm/lib/editor/managers/{FocusManager.mjs → FocusManager/FocusManager.mjs} +0 -0
  133. /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
  },
@@ -506,6 +506,8 @@ export class Editor extends EventEmitter<TLEventMap> {
506
506
  shape: {
507
507
  afterChange: (shapeBefore, shapeAfter) => {
508
508
  for (const binding of this.getBindingsInvolvingShape(shapeAfter)) {
509
+ if (areShapesContentEqual(shapeBefore, shapeAfter)) continue
510
+
509
511
  invalidBindingTypes.add(binding.type)
510
512
  if (binding.fromId === shapeAfter.id) {
511
513
  this.getBindingUtil(binding).onAfterChangeFromShape?.({
@@ -3715,10 +3717,7 @@ export class Editor extends EventEmitter<TLEventMap> {
3715
3717
  */
3716
3718
  @computed getViewportScreenCenter() {
3717
3719
  const viewportScreenBounds = this.getViewportScreenBounds()
3718
- return new Vec(
3719
- viewportScreenBounds.midX - viewportScreenBounds.minX,
3720
- viewportScreenBounds.midY - viewportScreenBounds.minY
3721
- )
3720
+ return new Vec(viewportScreenBounds.w / 2, viewportScreenBounds.h / 2)
3722
3721
  }
3723
3722
 
3724
3723
  /**
@@ -4644,44 +4643,6 @@ export class Editor extends EventEmitter<TLEventMap> {
4644
4643
  )! as T
4645
4644
  }
4646
4645
 
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
4646
  /** @internal */
4686
4647
  @computed private _getShapeHandlesCache(): ComputedCache<TLHandle[] | undefined, TLShape> {
4687
4648
  return this.store.createComputedCache(
@@ -4794,7 +4755,10 @@ export class Editor extends EventEmitter<TLEventMap> {
4794
4755
  /** @internal */
4795
4756
  @computed private _getShapePageBoundsCache(): ComputedCache<Box, TLShape> {
4796
4757
  return this.store.createComputedCache<Box, TLShape>('pageBoundsCache', (shape) => {
4797
- return this.getShapePageGeometry(shape).bounds
4758
+ const pageTransform = this.getShapePageTransform(shape)
4759
+ if (!pageTransform) return undefined
4760
+ const geometry = this.getShapeGeometry(shape)
4761
+ return Box.FromPoints(pageTransform.applyToPoints(geometry.vertices))
4798
4762
  })
4799
4763
  }
4800
4764
 
@@ -4868,11 +4832,12 @@ export class Editor extends EventEmitter<TLEventMap> {
4868
4832
  if (frameAncestors.length === 0) return undefined
4869
4833
 
4870
4834
  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
- )
4835
+ .map<Vec[] | undefined>((s) => {
4836
+ // Apply the frame transform to the frame outline to get the frame outline in the current page space
4837
+ const geometry = this.getShapeGeometry(s.id)
4838
+ const pageTransform = this.getShapePageTransform(s.id)
4839
+ return pageTransform.applyToPoints(geometry.vertices)
4840
+ })
4876
4841
  .reduce((acc, b) => {
4877
4842
  if (!(b && acc)) return undefined
4878
4843
  const intersection = intersectPolygonPolygon(acc, b)
@@ -5070,28 +5035,33 @@ export class Editor extends EventEmitter<TLEventMap> {
5070
5035
  *
5071
5036
  * @public
5072
5037
  */
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))
5038
+ isShapeOrAncestorLocked(shape?: TLShape | TLShapeId): boolean {
5039
+ const _shape = shape && this.getShape(shape)
5040
+ if (_shape === undefined) return false
5041
+ if (_shape.isLocked) return true
5042
+ return this.isShapeOrAncestorLocked(this.getShapeParent(_shape))
5080
5043
  }
5081
5044
 
5045
+ /**
5046
+ * Get shapes that are outside of the viewport.
5047
+ *
5048
+ * @public
5049
+ */
5082
5050
  @computed
5083
- private _notVisibleShapes() {
5084
- return notVisibleShapes(this)
5051
+ getNotVisibleShapes() {
5052
+ return this._notVisibleShapes.get()
5085
5053
  }
5086
5054
 
5055
+ private _notVisibleShapes = notVisibleShapes(this)
5056
+
5087
5057
  /**
5088
- * Get culled shapes.
5058
+ * Get culled shapes (those that should not render), taking into account which shapes are selected or editing.
5089
5059
  *
5090
5060
  * @public
5091
5061
  */
5092
5062
  @computed
5093
5063
  getCulledShapes() {
5094
- const notVisibleShapes = this._notVisibleShapes().get()
5064
+ const notVisibleShapes = this.getNotVisibleShapes()
5095
5065
  const selectedShapeIds = this.getSelectedShapeIds()
5096
5066
  const editingId = this.getEditingShapeId()
5097
5067
  const culledShapes = new Set<TLShapeId>(notVisibleShapes)
@@ -5340,21 +5310,23 @@ export class Editor extends EventEmitter<TLEventMap> {
5340
5310
  * @example
5341
5311
  * ```ts
5342
5312
  * editor.getShapesAtPoint({ x: 100, y: 100 })
5343
- * editor.getShapesAtPoint({ x: 100, y: 100 }, { hitInside: true, exact: true })
5313
+ * editor.getShapesAtPoint({ x: 100, y: 100 }, { hitInside: true, margin: 8 })
5344
5314
  * ```
5345
5315
  *
5346
5316
  * @param point - The page point to test.
5347
5317
  * @param opts - The options for the hit point testing.
5348
5318
  *
5319
+ * @returns An array of shapes at the given point, sorted in reverse order of their absolute z-index (top-most shape first).
5320
+ *
5349
5321
  * @public
5350
5322
  */
5351
5323
  getShapesAtPoint(
5352
5324
  point: VecLike,
5353
5325
  opts = {} as { margin?: number; hitInside?: boolean }
5354
5326
  ): TLShape[] {
5355
- return this.getCurrentPageShapes().filter(
5356
- (shape) => !this.isShapeHidden(shape) && this.isPointInShape(shape, point, opts)
5357
- )
5327
+ return this.getCurrentPageShapesSorted()
5328
+ .filter((shape) => !this.isShapeHidden(shape) && this.isPointInShape(shape, point, opts))
5329
+ .reverse()
5358
5330
  }
5359
5331
 
5360
5332
  /**
@@ -9303,6 +9275,7 @@ export class Editor extends EventEmitter<TLEventMap> {
9303
9275
  if (rootShapes.length === 1) {
9304
9276
  const onlyRoot = rootShapes[0] as TLFrameShape
9305
9277
  // If the old bounds are in the viewport...
9278
+ // todo: replace frame references with shapes that can accept children
9306
9279
  if (this.isShapeOfType<TLFrameShape>(onlyRoot, 'frame')) {
9307
9280
  while (
9308
9281
  this.getShapesAtPoint(point).some(
@@ -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