@tldraw/editor 3.14.0-canary.e099968e8b09 → 3.14.0-canary.e2a8e4a03aff

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 (162) hide show
  1. package/dist-cjs/index.d.ts +74 -63
  2. package/dist-cjs/index.js +8 -10
  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 +80 -73
  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} +1 -2
  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} +64 -6
  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.map +1 -1
  31. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +1 -1
  32. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +1 -1
  33. package/dist-cjs/lib/editor/tools/StateNode.js +3 -3
  34. package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
  35. package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
  36. package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
  37. package/dist-cjs/lib/exports/getSvgJsx.js.map +1 -1
  38. package/dist-cjs/lib/hooks/useCanvasEvents.js +1 -2
  39. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  40. package/dist-cjs/lib/primitives/Box.js +0 -6
  41. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  42. package/dist-cjs/lib/utils/areShapesContentEqual.js +1 -1
  43. package/dist-cjs/lib/utils/areShapesContentEqual.js.map +2 -2
  44. package/dist-cjs/lib/utils/reorderShapes.js +11 -10
  45. package/dist-cjs/lib/utils/reorderShapes.js.map +2 -2
  46. package/dist-cjs/lib/utils/richText.js +7 -2
  47. package/dist-cjs/lib/utils/richText.js.map +2 -2
  48. package/dist-cjs/version.js +3 -3
  49. package/dist-cjs/version.js.map +1 -1
  50. package/dist-esm/index.d.mts +74 -63
  51. package/dist-esm/index.mjs +12 -10
  52. package/dist-esm/index.mjs.map +2 -2
  53. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs +1 -1
  54. package/dist-esm/lib/config/TLSessionStateSnapshot.mjs.map +2 -2
  55. package/dist-esm/lib/editor/Editor.mjs +80 -73
  56. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  57. package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +2 -2
  58. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs +22 -22
  59. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs.map +2 -2
  60. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +16 -16
  61. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
  62. package/dist-esm/lib/editor/managers/{ClickManager.mjs → ClickManager/ClickManager.mjs} +1 -1
  63. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +7 -0
  64. package/dist-esm/lib/editor/managers/{EdgeScrollManager.mjs → EdgeScrollManager/EdgeScrollManager.mjs} +2 -2
  65. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +7 -0
  66. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +7 -0
  67. package/dist-esm/lib/editor/managers/{FontManager.mjs → FontManager/FontManager.mjs} +1 -2
  68. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +7 -0
  69. package/dist-esm/lib/editor/managers/{HistoryManager.mjs → HistoryManager/HistoryManager.mjs} +60 -2
  70. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +7 -0
  71. package/dist-esm/lib/editor/managers/{ScribbleManager.mjs → ScribbleManager/ScribbleManager.mjs} +1 -1
  72. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +7 -0
  73. package/dist-esm/lib/editor/managers/{TextManager.mjs → TextManager/TextManager.mjs} +73 -42
  74. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +7 -0
  75. package/dist-esm/lib/editor/managers/{TickManager.mjs → TickManager/TickManager.mjs} +1 -1
  76. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +7 -0
  77. package/dist-esm/lib/editor/managers/{UserPreferencesManager.mjs → UserPreferencesManager/UserPreferencesManager.mjs} +1 -1
  78. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +7 -0
  79. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +1 -1
  80. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +1 -1
  81. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +1 -1
  82. package/dist-esm/lib/editor/tools/StateNode.mjs +3 -3
  83. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  84. package/dist-esm/lib/exports/getSvgJsx.mjs.map +1 -1
  85. package/dist-esm/lib/hooks/useCanvasEvents.mjs +1 -2
  86. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  87. package/dist-esm/lib/primitives/Box.mjs +0 -6
  88. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  89. package/dist-esm/lib/utils/areShapesContentEqual.mjs +1 -1
  90. package/dist-esm/lib/utils/areShapesContentEqual.mjs.map +2 -2
  91. package/dist-esm/lib/utils/reorderShapes.mjs +11 -10
  92. package/dist-esm/lib/utils/reorderShapes.mjs.map +2 -2
  93. package/dist-esm/lib/utils/richText.mjs +8 -3
  94. package/dist-esm/lib/utils/richText.mjs.map +2 -2
  95. package/dist-esm/version.mjs +3 -3
  96. package/dist-esm/version.mjs.map +1 -1
  97. package/editor.css +433 -482
  98. package/package.json +8 -9
  99. package/src/index.ts +15 -8
  100. package/src/lib/config/TLSessionStateSnapshot.ts +1 -1
  101. package/src/lib/editor/Editor.test.ts +252 -3
  102. package/src/lib/editor/Editor.ts +81 -72
  103. package/src/lib/editor/bindings/BindingUtil.ts +6 -0
  104. package/src/lib/editor/derivations/bindingsIndex.ts +27 -26
  105. package/src/lib/editor/derivations/parentsToChildren.ts +28 -25
  106. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +442 -0
  107. package/src/lib/editor/managers/{ClickManager.ts → ClickManager/ClickManager.ts} +3 -3
  108. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +374 -0
  109. package/src/lib/editor/managers/{EdgeScrollManager.ts → EdgeScrollManager/EdgeScrollManager.ts} +3 -3
  110. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +455 -0
  111. package/src/lib/editor/managers/{FocusManager.ts → FocusManager/FocusManager.ts} +1 -1
  112. package/src/lib/editor/managers/FontManager/FontManager.test.ts +263 -0
  113. package/src/lib/editor/managers/{FontManager.ts → FontManager/FontManager.ts} +2 -3
  114. package/src/lib/editor/managers/{HistoryManager.test.ts → HistoryManager/HistoryManager.test.ts} +388 -1
  115. package/src/lib/editor/managers/{HistoryManager.ts → HistoryManager/HistoryManager.ts} +73 -2
  116. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +624 -0
  117. package/src/lib/editor/managers/{ScribbleManager.ts → ScribbleManager/ScribbleManager.ts} +2 -2
  118. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +485 -0
  119. package/src/lib/editor/managers/TextManager/TextManager.test.ts +407 -0
  120. package/src/lib/editor/managers/{TextManager.ts → TextManager/TextManager.ts} +119 -87
  121. package/src/lib/editor/managers/TickManager/TickManager.test.ts +314 -0
  122. package/src/lib/editor/managers/{TickManager.ts → TickManager/TickManager.ts} +2 -2
  123. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +591 -0
  124. package/src/lib/editor/managers/{UserPreferencesManager.ts → UserPreferencesManager/UserPreferencesManager.ts} +2 -2
  125. package/src/lib/editor/shapes/ShapeUtil.ts +2 -1
  126. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +1 -1
  127. package/src/lib/editor/tools/StateNode.ts +3 -3
  128. package/src/lib/editor/types/emit-types.ts +4 -0
  129. package/src/lib/editor/types/external-content.ts +11 -2
  130. package/src/lib/exports/getSvgJsx.tsx +1 -1
  131. package/src/lib/hooks/useCanvasEvents.ts +0 -1
  132. package/src/lib/primitives/Box.ts +0 -8
  133. package/src/lib/utils/areShapesContentEqual.ts +1 -2
  134. package/src/lib/utils/reorderShapes.ts +10 -13
  135. package/src/lib/utils/richText.ts +10 -4
  136. package/src/version.ts +3 -3
  137. package/dist-cjs/lib/editor/managers/ClickManager.js.map +0 -7
  138. package/dist-cjs/lib/editor/managers/EdgeScrollManager.js.map +0 -7
  139. package/dist-cjs/lib/editor/managers/FocusManager.js.map +0 -7
  140. package/dist-cjs/lib/editor/managers/FontManager.js.map +0 -7
  141. package/dist-cjs/lib/editor/managers/HistoryManager.js.map +0 -7
  142. package/dist-cjs/lib/editor/managers/ScribbleManager.js.map +0 -7
  143. package/dist-cjs/lib/editor/managers/Stack.js +0 -82
  144. package/dist-cjs/lib/editor/managers/Stack.js.map +0 -7
  145. package/dist-cjs/lib/editor/managers/TextManager.js.map +0 -7
  146. package/dist-cjs/lib/editor/managers/TickManager.js.map +0 -7
  147. package/dist-cjs/lib/editor/managers/UserPreferencesManager.js.map +0 -7
  148. package/dist-esm/lib/editor/managers/ClickManager.mjs.map +0 -7
  149. package/dist-esm/lib/editor/managers/EdgeScrollManager.mjs.map +0 -7
  150. package/dist-esm/lib/editor/managers/FocusManager.mjs.map +0 -7
  151. package/dist-esm/lib/editor/managers/FontManager.mjs.map +0 -7
  152. package/dist-esm/lib/editor/managers/HistoryManager.mjs.map +0 -7
  153. package/dist-esm/lib/editor/managers/ScribbleManager.mjs.map +0 -7
  154. package/dist-esm/lib/editor/managers/Stack.mjs +0 -62
  155. package/dist-esm/lib/editor/managers/Stack.mjs.map +0 -7
  156. package/dist-esm/lib/editor/managers/TextManager.mjs.map +0 -7
  157. package/dist-esm/lib/editor/managers/TickManager.mjs.map +0 -7
  158. package/dist-esm/lib/editor/managers/UserPreferencesManager.mjs.map +0 -7
  159. package/src/lib/editor/managers/ScribbleManager.test.ts +0 -32
  160. package/src/lib/editor/managers/Stack.ts +0 -71
  161. /package/dist-cjs/lib/editor/managers/{FocusManager.js → FocusManager/FocusManager.js} +0 -0
  162. /package/dist-esm/lib/editor/managers/{FocusManager.mjs → FocusManager/FocusManager.mjs} +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/editor/bindings/BindingUtil.ts"],
4
- "sourcesContent": ["import { RecordProps, TLPropsMigrations, TLShape, TLUnknownBinding } from '@tldraw/tlschema'\nimport { Editor } from '../Editor'\n\n/** @public */\nexport interface TLBindingUtilConstructor<\n\tT extends TLUnknownBinding,\n\tU extends BindingUtil<T> = BindingUtil<T>,\n> {\n\tnew (editor: Editor): U\n\ttype: T['type']\n\t/** Validations for this binding's props. */\n\tprops?: RecordProps<T>\n\t/** Migrations for this binding's props. */\n\tmigrations?: TLPropsMigrations\n}\n\n/**\n * Options passed to {@link BindingUtil.onBeforeCreate} and {@link BindingUtil.onAfterCreate},\n * describing a the creating a binding.\n *\n * @public\n */\nexport interface BindingOnCreateOptions<Binding extends TLUnknownBinding> {\n\t/** The binding being created. */\n\tbinding: Binding\n}\n\n/**\n * Options passed to {@link BindingUtil.onBeforeChange} and {@link BindingUtil.onAfterChange},\n * describing the data associated with a binding being changed.\n *\n * @public\n */\nexport interface BindingOnChangeOptions<Binding extends TLUnknownBinding> {\n\t/** The binding record before the change is made. */\n\tbindingBefore: Binding\n\t/** The binding record after the change is made. */\n\tbindingAfter: Binding\n}\n\n/**\n * Options passed to {@link BindingUtil.onBeforeDelete} and {@link BindingUtil.onAfterDelete},\n * describing a binding being deleted.\n *\n * @public\n */\nexport interface BindingOnDeleteOptions<Binding extends TLUnknownBinding> {\n\t/** The binding being deleted. */\n\tbinding: Binding\n}\n\n/**\n * Options passed to {@link BindingUtil.onAfterChangeFromShape} and\n * {@link BindingUtil.onAfterChangeToShape}, describing a bound shape being changed.\n *\n * @public\n */\nexport interface BindingOnShapeChangeOptions<Binding extends TLUnknownBinding> {\n\t/** The binding record linking these two shapes. */\n\tbinding: Binding\n\t/** The shape record before the change is made. */\n\tshapeBefore: TLShape\n\t/** The shape record after the change is made. */\n\tshapeAfter: TLShape\n}\n\n/**\n * Options passed to {@link BindingUtil.onBeforeIsolateFromShape} and\n * {@link BindingUtil.onBeforeIsolateToShape}, describing a shape that is about to be isolated from\n * the one that it's bound to.\n *\n * Isolation happens whenever two bound shapes are separated. For example\n * 1. One is deleted, but the other is not.\n * 1. One is copied, but the other is not.\n * 1. One is duplicated, but the other is not.\n *\n * In each of these cases, if the remaining shape depends on the binding for its rendering, it may\n * now be in an inconsistent state. For example, tldraw's arrow shape depends on the binding to know\n * where the end of the arrow is. If we removed the binding without doing anything else, the arrow\n * would suddenly be pointing to the wrong location. Instead, when the shape the arrow is pointing\n * to is deleted, or the arrow is copied/duplicated, we use an isolation callback. The callback\n * updates the arrow based on the binding that's about to be removed, so it doesn't end up pointing\n * to the wrong place.\n *\n * For this style of consistency update, use isolation callbacks. For actions specific to deletion\n * (like deleting a sticker when the shape it's bound to is removed), use the delete callbacks\n * ({@link BindingUtil.onBeforeDeleteFromShape} and {@link BindingUtil.onBeforeDeleteToShape})\n * instead.\n *\n * @public\n */\nexport interface BindingOnShapeIsolateOptions<Binding extends TLUnknownBinding> {\n\t/** The binding record that refers to the shape in question. */\n\tbinding: Binding\n\t/**\n\t * The shape being removed. For deletion, this is the deleted shape. For copy/duplicate, this is\n\t * the shape that _isn't_ being copied/duplicated and is getting left behind.\n\t */\n\tremovedShape: TLShape\n}\n\n/**\n * Options passed to {@link BindingUtil.onBeforeDeleteFromShape} and\n * {@link BindingUtil.onBeforeDeleteToShape}, describing a bound shape that is about to be deleted.\n *\n * See {@link BindingOnShapeIsolateOptions} for discussion on when to use the delete vs. the isolate\n * callbacks.\n *\n * @public\n */\nexport interface BindingOnShapeDeleteOptions<Binding extends TLUnknownBinding> {\n\t/** The binding record that refers to the shape in question. */\n\tbinding: Binding\n\t/** The shape that is about to be deleted. */\n\tshape: TLShape\n}\n\n/** @public */\nexport abstract class BindingUtil<Binding extends TLUnknownBinding = TLUnknownBinding> {\n\tconstructor(public editor: Editor) {}\n\tstatic props?: RecordProps<TLUnknownBinding>\n\tstatic migrations?: TLPropsMigrations\n\n\t/**\n\t * The type of the binding util, which should match the binding's type.\n\t *\n\t * @public\n\t */\n\tstatic type: string\n\n\t/**\n\t * Get the default props for a binding.\n\t *\n\t * @public\n\t */\n\tabstract getDefaultProps(): Partial<Binding['props']>\n\n\t/**\n\t * Called whenever a store operation involving this binding type has completed. This is useful\n\t * for working with networks of related bindings that may need to update together.\n\t *\n\t * @example\n\t * ```ts\n\t * class MyBindingUtil extends BindingUtil<MyBinding> {\n\t * changedBindingIds = new Set<TLBindingId>()\n\t *\n\t * onOperationComplete() {\n\t * doSomethingWithChangedBindings(this.changedBindingIds)\n\t * this.changedBindingIds.clear()\n\t * }\n\t *\n\t * onAfterChange({ bindingAfter }: BindingOnChangeOptions<MyBinding>) {\n\t * this.changedBindingIds.add(bindingAfter.id)\n\t * }\n\t * }\n\t * ```\n\t *\n\t * @public\n\t */\n\tonOperationComplete?(): void\n\n\t/**\n\t * Called when a binding is about to be created. See {@link BindingOnCreateOptions} for details.\n\t *\n\t * You can optionally return a new binding to replace the one being created - for example, to\n\t * set different initial props.\n\t *\n\t * @public\n\t */\n\tonBeforeCreate?(options: BindingOnCreateOptions<Binding>): Binding | void\n\n\t/**\n\t * Called after a binding has been created. See {@link BindingOnCreateOptions} for details.\n\t *\n\t * @public\n\t */\n\tonAfterCreate?(options: BindingOnCreateOptions<Binding>): void\n\n\t/**\n\t * Called when a binding is about to be changed. See {@link BindingOnChangeOptions} for details.\n\t *\n\t * Note that this only fires when the binding record is changing, not when the shapes\n\t * associated change. Use {@link BindingUtil.onAfterChangeFromShape} and\n\t * {@link BindingUtil.onAfterChangeToShape} for that.\n\t *\n\t * You can optionally return a new binding to replace the one being changed - for example, to\n\t * enforce constraints on the binding's props.\n\t *\n\t * @public\n\t */\n\tonBeforeChange?(options: BindingOnChangeOptions<Binding>): Binding | void\n\n\t/**\n\t * Called after a binding has been changed. See {@link BindingOnChangeOptions} for details.\n\t *\n\t * Note that this only fires when the binding record is changing, not when the shapes\n\t * associated change. Use {@link BindingUtil.onAfterChangeFromShape} and\n\t * {@link BindingUtil.onAfterChangeToShape} for that.\n\t *\n\t * @public\n\t */\n\tonAfterChange?(options: BindingOnChangeOptions<Binding>): void\n\n\t/**\n\t * Called when a binding is about to be deleted. See {@link BindingOnDeleteOptions} for details.\n\t *\n\t * @public\n\t */\n\tonBeforeDelete?(options: BindingOnDeleteOptions<Binding>): void\n\n\t/**\n\t * Called after a binding has been deleted. See {@link BindingOnDeleteOptions} for details.\n\t *\n\t * @public\n\t */\n\tonAfterDelete?(options: BindingOnDeleteOptions<Binding>): void\n\n\t/**\n\t * Called after the shape referenced in a binding's `fromId` is changed. Use this to propagate\n\t * any changes to the binding itself or the other shape as needed. See\n\t * {@link BindingOnShapeChangeOptions} for details.\n\t *\n\t * @public\n\t */\n\tonAfterChangeFromShape?(options: BindingOnShapeChangeOptions<Binding>): void\n\n\t/**\n\t * Called after the shape referenced in a binding's `toId` is changed. Use this to propagate any\n\t * changes to the binding itself or the other shape as needed. See\n\t * {@link BindingOnShapeChangeOptions} for details.\n\t *\n\t * @public\n\t */\n\tonAfterChangeToShape?(options: BindingOnShapeChangeOptions<Binding>): void\n\n\t/**\n\t * Called before the shape referenced in a binding's `fromId` is about to be deleted. Use this\n\t * with care - you may want to use {@link BindingUtil.onBeforeIsolateToShape} instead. See\n\t * {@link BindingOnShapeDeleteOptions} for details.\n\t *\n\t * @public\n\t */\n\tonBeforeDeleteFromShape?(options: BindingOnShapeDeleteOptions<Binding>): void\n\t/**\n\t * Called before the shape referenced in a binding's `toId` is about to be deleted. Use this\n\t * with care - you may want to use {@link BindingUtil.onBeforeIsolateFromShape} instead. See\n\t * {@link BindingOnShapeDeleteOptions} for details.\n\t *\n\t * @public\n\t */\n\tonBeforeDeleteToShape?(options: BindingOnShapeDeleteOptions<Binding>): void\n\n\t/**\n\t * Called before the shape referenced in a binding's `fromId` is about to be isolated from the\n\t * shape referenced in `toId`. See {@link BindingOnShapeIsolateOptions} for discussion on what\n\t * isolation means, and when/how to use this callback.\n\t */\n\tonBeforeIsolateFromShape?(options: BindingOnShapeIsolateOptions<Binding>): void\n\n\t/**\n\t * Called before the shape referenced in a binding's `toId` is about to be isolated from the\n\t * shape referenced in `fromId`. See {@link BindingOnShapeIsolateOptions} for discussion on what\n\t * isolation means, and when/how to use this callback.\n\t */\n\tonBeforeIsolateToShape?(options: BindingOnShapeIsolateOptions<Binding>): void\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAsHO,MAAe,YAAiE;AAAA,EACtF,YAAmB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EACpC,OAAO;AAAA,EACP,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOP,OAAO;AAyIR;",
4
+ "sourcesContent": ["import { RecordProps, TLPropsMigrations, TLShape, TLUnknownBinding } from '@tldraw/tlschema'\nimport { Editor } from '../Editor'\n\n/** @public */\nexport interface TLBindingUtilConstructor<\n\tT extends TLUnknownBinding,\n\tU extends BindingUtil<T> = BindingUtil<T>,\n> {\n\tnew (editor: Editor): U\n\ttype: T['type']\n\t/** Validations for this binding's props. */\n\tprops?: RecordProps<T>\n\t/** Migrations for this binding's props. */\n\tmigrations?: TLPropsMigrations\n}\n\n/**\n * Options passed to {@link BindingUtil.onBeforeCreate} and {@link BindingUtil.onAfterCreate},\n * describing a the creating a binding.\n *\n * @public\n */\nexport interface BindingOnCreateOptions<Binding extends TLUnknownBinding> {\n\t/** The binding being created. */\n\tbinding: Binding\n}\n\n/**\n * Options passed to {@link BindingUtil.onBeforeChange} and {@link BindingUtil.onAfterChange},\n * describing the data associated with a binding being changed.\n *\n * @public\n */\nexport interface BindingOnChangeOptions<Binding extends TLUnknownBinding> {\n\t/** The binding record before the change is made. */\n\tbindingBefore: Binding\n\t/** The binding record after the change is made. */\n\tbindingAfter: Binding\n}\n\n/**\n * Options passed to {@link BindingUtil.onBeforeDelete} and {@link BindingUtil.onAfterDelete},\n * describing a binding being deleted.\n *\n * @public\n */\nexport interface BindingOnDeleteOptions<Binding extends TLUnknownBinding> {\n\t/** The binding being deleted. */\n\tbinding: Binding\n}\n\n/**\n * Options passed to {@link BindingUtil.onAfterChangeFromShape} and\n * {@link BindingUtil.onAfterChangeToShape}, describing a bound shape being changed.\n *\n * @public\n */\nexport interface BindingOnShapeChangeOptions<Binding extends TLUnknownBinding> {\n\t/** The binding record linking these two shapes. */\n\tbinding: Binding\n\t/** The shape record before the change is made. */\n\tshapeBefore: TLShape\n\t/** The shape record after the change is made. */\n\tshapeAfter: TLShape\n\t/**\n\t * Why did this shape change?\n\t * - 'self': the shape itself changed\n\t * - 'ancestry': the ancestry of the shape changed, but the shape itself may not have done\n\t */\n\treason: 'self' | 'ancestry'\n}\n\n/**\n * Options passed to {@link BindingUtil.onBeforeIsolateFromShape} and\n * {@link BindingUtil.onBeforeIsolateToShape}, describing a shape that is about to be isolated from\n * the one that it's bound to.\n *\n * Isolation happens whenever two bound shapes are separated. For example\n * 1. One is deleted, but the other is not.\n * 1. One is copied, but the other is not.\n * 1. One is duplicated, but the other is not.\n *\n * In each of these cases, if the remaining shape depends on the binding for its rendering, it may\n * now be in an inconsistent state. For example, tldraw's arrow shape depends on the binding to know\n * where the end of the arrow is. If we removed the binding without doing anything else, the arrow\n * would suddenly be pointing to the wrong location. Instead, when the shape the arrow is pointing\n * to is deleted, or the arrow is copied/duplicated, we use an isolation callback. The callback\n * updates the arrow based on the binding that's about to be removed, so it doesn't end up pointing\n * to the wrong place.\n *\n * For this style of consistency update, use isolation callbacks. For actions specific to deletion\n * (like deleting a sticker when the shape it's bound to is removed), use the delete callbacks\n * ({@link BindingUtil.onBeforeDeleteFromShape} and {@link BindingUtil.onBeforeDeleteToShape})\n * instead.\n *\n * @public\n */\nexport interface BindingOnShapeIsolateOptions<Binding extends TLUnknownBinding> {\n\t/** The binding record that refers to the shape in question. */\n\tbinding: Binding\n\t/**\n\t * The shape being removed. For deletion, this is the deleted shape. For copy/duplicate, this is\n\t * the shape that _isn't_ being copied/duplicated and is getting left behind.\n\t */\n\tremovedShape: TLShape\n}\n\n/**\n * Options passed to {@link BindingUtil.onBeforeDeleteFromShape} and\n * {@link BindingUtil.onBeforeDeleteToShape}, describing a bound shape that is about to be deleted.\n *\n * See {@link BindingOnShapeIsolateOptions} for discussion on when to use the delete vs. the isolate\n * callbacks.\n *\n * @public\n */\nexport interface BindingOnShapeDeleteOptions<Binding extends TLUnknownBinding> {\n\t/** The binding record that refers to the shape in question. */\n\tbinding: Binding\n\t/** The shape that is about to be deleted. */\n\tshape: TLShape\n}\n\n/** @public */\nexport abstract class BindingUtil<Binding extends TLUnknownBinding = TLUnknownBinding> {\n\tconstructor(public editor: Editor) {}\n\tstatic props?: RecordProps<TLUnknownBinding>\n\tstatic migrations?: TLPropsMigrations\n\n\t/**\n\t * The type of the binding util, which should match the binding's type.\n\t *\n\t * @public\n\t */\n\tstatic type: string\n\n\t/**\n\t * Get the default props for a binding.\n\t *\n\t * @public\n\t */\n\tabstract getDefaultProps(): Partial<Binding['props']>\n\n\t/**\n\t * Called whenever a store operation involving this binding type has completed. This is useful\n\t * for working with networks of related bindings that may need to update together.\n\t *\n\t * @example\n\t * ```ts\n\t * class MyBindingUtil extends BindingUtil<MyBinding> {\n\t * changedBindingIds = new Set<TLBindingId>()\n\t *\n\t * onOperationComplete() {\n\t * doSomethingWithChangedBindings(this.changedBindingIds)\n\t * this.changedBindingIds.clear()\n\t * }\n\t *\n\t * onAfterChange({ bindingAfter }: BindingOnChangeOptions<MyBinding>) {\n\t * this.changedBindingIds.add(bindingAfter.id)\n\t * }\n\t * }\n\t * ```\n\t *\n\t * @public\n\t */\n\tonOperationComplete?(): void\n\n\t/**\n\t * Called when a binding is about to be created. See {@link BindingOnCreateOptions} for details.\n\t *\n\t * You can optionally return a new binding to replace the one being created - for example, to\n\t * set different initial props.\n\t *\n\t * @public\n\t */\n\tonBeforeCreate?(options: BindingOnCreateOptions<Binding>): Binding | void\n\n\t/**\n\t * Called after a binding has been created. See {@link BindingOnCreateOptions} for details.\n\t *\n\t * @public\n\t */\n\tonAfterCreate?(options: BindingOnCreateOptions<Binding>): void\n\n\t/**\n\t * Called when a binding is about to be changed. See {@link BindingOnChangeOptions} for details.\n\t *\n\t * Note that this only fires when the binding record is changing, not when the shapes\n\t * associated change. Use {@link BindingUtil.onAfterChangeFromShape} and\n\t * {@link BindingUtil.onAfterChangeToShape} for that.\n\t *\n\t * You can optionally return a new binding to replace the one being changed - for example, to\n\t * enforce constraints on the binding's props.\n\t *\n\t * @public\n\t */\n\tonBeforeChange?(options: BindingOnChangeOptions<Binding>): Binding | void\n\n\t/**\n\t * Called after a binding has been changed. See {@link BindingOnChangeOptions} for details.\n\t *\n\t * Note that this only fires when the binding record is changing, not when the shapes\n\t * associated change. Use {@link BindingUtil.onAfterChangeFromShape} and\n\t * {@link BindingUtil.onAfterChangeToShape} for that.\n\t *\n\t * @public\n\t */\n\tonAfterChange?(options: BindingOnChangeOptions<Binding>): void\n\n\t/**\n\t * Called when a binding is about to be deleted. See {@link BindingOnDeleteOptions} for details.\n\t *\n\t * @public\n\t */\n\tonBeforeDelete?(options: BindingOnDeleteOptions<Binding>): void\n\n\t/**\n\t * Called after a binding has been deleted. See {@link BindingOnDeleteOptions} for details.\n\t *\n\t * @public\n\t */\n\tonAfterDelete?(options: BindingOnDeleteOptions<Binding>): void\n\n\t/**\n\t * Called after the shape referenced in a binding's `fromId` is changed. Use this to propagate\n\t * any changes to the binding itself or the other shape as needed. See\n\t * {@link BindingOnShapeChangeOptions} for details.\n\t *\n\t * @public\n\t */\n\tonAfterChangeFromShape?(options: BindingOnShapeChangeOptions<Binding>): void\n\n\t/**\n\t * Called after the shape referenced in a binding's `toId` is changed. Use this to propagate any\n\t * changes to the binding itself or the other shape as needed. See\n\t * {@link BindingOnShapeChangeOptions} for details.\n\t *\n\t * @public\n\t */\n\tonAfterChangeToShape?(options: BindingOnShapeChangeOptions<Binding>): void\n\n\t/**\n\t * Called before the shape referenced in a binding's `fromId` is about to be deleted. Use this\n\t * with care - you may want to use {@link BindingUtil.onBeforeIsolateToShape} instead. See\n\t * {@link BindingOnShapeDeleteOptions} for details.\n\t *\n\t * @public\n\t */\n\tonBeforeDeleteFromShape?(options: BindingOnShapeDeleteOptions<Binding>): void\n\t/**\n\t * Called before the shape referenced in a binding's `toId` is about to be deleted. Use this\n\t * with care - you may want to use {@link BindingUtil.onBeforeIsolateFromShape} instead. See\n\t * {@link BindingOnShapeDeleteOptions} for details.\n\t *\n\t * @public\n\t */\n\tonBeforeDeleteToShape?(options: BindingOnShapeDeleteOptions<Binding>): void\n\n\t/**\n\t * Called before the shape referenced in a binding's `fromId` is about to be isolated from the\n\t * shape referenced in `toId`. See {@link BindingOnShapeIsolateOptions} for discussion on what\n\t * isolation means, and when/how to use this callback.\n\t */\n\tonBeforeIsolateFromShape?(options: BindingOnShapeIsolateOptions<Binding>): void\n\n\t/**\n\t * Called before the shape referenced in a binding's `toId` is about to be isolated from the\n\t * shape referenced in `fromId`. See {@link BindingOnShapeIsolateOptions} for discussion on what\n\t * isolation means, and when/how to use this callback.\n\t */\n\tonBeforeIsolateToShape?(options: BindingOnShapeIsolateOptions<Binding>): void\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA4HO,MAAe,YAAiE;AAAA,EACtF,YAAmB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,EACpC,OAAO;AAAA,EACP,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOP,OAAO;AAyIR;",
6
6
  "names": []
7
7
  }
@@ -23,38 +23,38 @@ __export(bindingsIndex_exports, {
23
23
  module.exports = __toCommonJS(bindingsIndex_exports);
24
24
  var import_state = require("@tldraw/state");
25
25
  var import_utils = require("@tldraw/utils");
26
+ function fromScratch(bindingsQuery) {
27
+ const allBindings = bindingsQuery.get();
28
+ const shapesToBindings = /* @__PURE__ */ new Map();
29
+ for (const binding of allBindings) {
30
+ const { fromId, toId } = binding;
31
+ const bindingsForFromShape = shapesToBindings.get(fromId);
32
+ if (!bindingsForFromShape) {
33
+ shapesToBindings.set(fromId, [binding]);
34
+ } else {
35
+ bindingsForFromShape.push(binding);
36
+ }
37
+ const bindingsForToShape = shapesToBindings.get(toId);
38
+ if (!bindingsForToShape) {
39
+ shapesToBindings.set(toId, [binding]);
40
+ } else {
41
+ bindingsForToShape.push(binding);
42
+ }
43
+ }
44
+ return shapesToBindings;
45
+ }
26
46
  const bindingsIndex = (editor) => {
27
47
  const { store } = editor;
28
48
  const bindingsHistory = store.query.filterHistory("binding");
29
49
  const bindingsQuery = store.query.records("binding");
30
- function fromScratch() {
31
- const allBindings = bindingsQuery.get();
32
- const shape2Binding = /* @__PURE__ */ new Map();
33
- for (const binding of allBindings) {
34
- const { fromId, toId } = binding;
35
- const bindingsForFromShape = shape2Binding.get(fromId);
36
- if (!bindingsForFromShape) {
37
- shape2Binding.set(fromId, [binding]);
38
- } else {
39
- bindingsForFromShape.push(binding);
40
- }
41
- const bindingsForToShape = shape2Binding.get(toId);
42
- if (!bindingsForToShape) {
43
- shape2Binding.set(toId, [binding]);
44
- } else {
45
- bindingsForToShape.push(binding);
46
- }
47
- }
48
- return shape2Binding;
49
- }
50
50
  return (0, import_state.computed)("arrowBindingsIndex", (_lastValue, lastComputedEpoch) => {
51
51
  if ((0, import_state.isUninitialized)(_lastValue)) {
52
- return fromScratch();
52
+ return fromScratch(bindingsQuery);
53
53
  }
54
54
  const lastValue = _lastValue;
55
55
  const diff = bindingsHistory.getDiffSince(lastComputedEpoch);
56
56
  if (diff === import_state.RESET_VALUE) {
57
- return fromScratch();
57
+ return fromScratch(bindingsQuery);
58
58
  }
59
59
  let nextValue = void 0;
60
60
  function removingBinding(binding) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/editor/derivations/bindingsIndex.ts"],
4
- "sourcesContent": ["import { Computed, RESET_VALUE, computed, isUninitialized } from '@tldraw/state'\nimport { TLBinding, TLShapeId } from '@tldraw/tlschema'\nimport { objectMapValues } from '@tldraw/utils'\nimport { Editor } from '../Editor'\n\ntype TLBindingsIndex = Map<TLShapeId, TLBinding[]>\n\nexport const bindingsIndex = (editor: Editor): Computed<TLBindingsIndex> => {\n\tconst { store } = editor\n\tconst bindingsHistory = store.query.filterHistory('binding')\n\tconst bindingsQuery = store.query.records('binding')\n\tfunction fromScratch() {\n\t\tconst allBindings = bindingsQuery.get() as TLBinding[]\n\n\t\tconst shape2Binding: TLBindingsIndex = new Map()\n\n\t\tfor (const binding of allBindings) {\n\t\t\tconst { fromId, toId } = binding\n\t\t\tconst bindingsForFromShape = shape2Binding.get(fromId)\n\t\t\tif (!bindingsForFromShape) {\n\t\t\t\tshape2Binding.set(fromId, [binding])\n\t\t\t} else {\n\t\t\t\tbindingsForFromShape.push(binding)\n\t\t\t}\n\t\t\tconst bindingsForToShape = shape2Binding.get(toId)\n\t\t\tif (!bindingsForToShape) {\n\t\t\t\tshape2Binding.set(toId, [binding])\n\t\t\t} else {\n\t\t\t\tbindingsForToShape.push(binding)\n\t\t\t}\n\t\t}\n\n\t\treturn shape2Binding\n\t}\n\n\treturn computed<TLBindingsIndex>('arrowBindingsIndex', (_lastValue, lastComputedEpoch) => {\n\t\tif (isUninitialized(_lastValue)) {\n\t\t\treturn fromScratch()\n\t\t}\n\n\t\tconst lastValue = _lastValue\n\n\t\tconst diff = bindingsHistory.getDiffSince(lastComputedEpoch)\n\n\t\tif (diff === RESET_VALUE) {\n\t\t\treturn fromScratch()\n\t\t}\n\n\t\tlet nextValue: TLBindingsIndex | undefined = undefined\n\n\t\tfunction removingBinding(binding: TLBinding) {\n\t\t\tnextValue ??= new Map(lastValue)\n\t\t\tconst prevFrom = nextValue.get(binding.fromId)\n\t\t\tconst nextFrom = prevFrom?.filter((b) => b.id !== binding.id)\n\t\t\tif (!nextFrom?.length) {\n\t\t\t\tnextValue.delete(binding.fromId)\n\t\t\t} else {\n\t\t\t\tnextValue.set(binding.fromId, nextFrom)\n\t\t\t}\n\t\t\tconst prevTo = nextValue.get(binding.toId)\n\t\t\tconst nextTo = prevTo?.filter((b) => b.id !== binding.id)\n\t\t\tif (!nextTo?.length) {\n\t\t\t\tnextValue.delete(binding.toId)\n\t\t\t} else {\n\t\t\t\tnextValue.set(binding.toId, nextTo)\n\t\t\t}\n\t\t}\n\n\t\tfunction ensureNewArray(shapeId: TLShapeId) {\n\t\t\tnextValue ??= new Map(lastValue)\n\n\t\t\tlet result = nextValue.get(shapeId)\n\t\t\tif (!result) {\n\t\t\t\tresult = []\n\t\t\t\tnextValue.set(shapeId, result)\n\t\t\t} else if (result === lastValue.get(shapeId)) {\n\t\t\t\tresult = result.slice(0)\n\t\t\t\tnextValue.set(shapeId, result)\n\t\t\t}\n\t\t\treturn result\n\t\t}\n\n\t\tfunction addBinding(binding: TLBinding) {\n\t\t\tensureNewArray(binding.fromId).push(binding)\n\t\t\tensureNewArray(binding.toId).push(binding)\n\t\t}\n\n\t\tfor (const changes of diff) {\n\t\t\tfor (const newBinding of objectMapValues(changes.added)) {\n\t\t\t\taddBinding(newBinding)\n\t\t\t}\n\n\t\t\tfor (const [prev, next] of objectMapValues(changes.updated)) {\n\t\t\t\tremovingBinding(prev)\n\t\t\t\taddBinding(next)\n\t\t\t}\n\n\t\t\tfor (const prev of objectMapValues(changes.removed)) {\n\t\t\t\tremovingBinding(prev)\n\t\t\t}\n\t\t}\n\n\t\t// TODO: add diff entries if we need them\n\t\treturn nextValue ?? lastValue\n\t})\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiE;AAEjE,mBAAgC;AAKzB,MAAM,gBAAgB,CAAC,WAA8C;AAC3E,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,kBAAkB,MAAM,MAAM,cAAc,SAAS;AAC3D,QAAM,gBAAgB,MAAM,MAAM,QAAQ,SAAS;AACnD,WAAS,cAAc;AACtB,UAAM,cAAc,cAAc,IAAI;AAEtC,UAAM,gBAAiC,oBAAI,IAAI;AAE/C,eAAW,WAAW,aAAa;AAClC,YAAM,EAAE,QAAQ,KAAK,IAAI;AACzB,YAAM,uBAAuB,cAAc,IAAI,MAAM;AACrD,UAAI,CAAC,sBAAsB;AAC1B,sBAAc,IAAI,QAAQ,CAAC,OAAO,CAAC;AAAA,MACpC,OAAO;AACN,6BAAqB,KAAK,OAAO;AAAA,MAClC;AACA,YAAM,qBAAqB,cAAc,IAAI,IAAI;AACjD,UAAI,CAAC,oBAAoB;AACxB,sBAAc,IAAI,MAAM,CAAC,OAAO,CAAC;AAAA,MAClC,OAAO;AACN,2BAAmB,KAAK,OAAO;AAAA,MAChC;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAEA,aAAO,uBAA0B,sBAAsB,CAAC,YAAY,sBAAsB;AACzF,YAAI,8BAAgB,UAAU,GAAG;AAChC,aAAO,YAAY;AAAA,IACpB;AAEA,UAAM,YAAY;AAElB,UAAM,OAAO,gBAAgB,aAAa,iBAAiB;AAE3D,QAAI,SAAS,0BAAa;AACzB,aAAO,YAAY;AAAA,IACpB;AAEA,QAAI,YAAyC;AAE7C,aAAS,gBAAgB,SAAoB;AAC5C,oBAAc,IAAI,IAAI,SAAS;AAC/B,YAAM,WAAW,UAAU,IAAI,QAAQ,MAAM;AAC7C,YAAM,WAAW,UAAU,OAAO,CAAC,MAAM,EAAE,OAAO,QAAQ,EAAE;AAC5D,UAAI,CAAC,UAAU,QAAQ;AACtB,kBAAU,OAAO,QAAQ,MAAM;AAAA,MAChC,OAAO;AACN,kBAAU,IAAI,QAAQ,QAAQ,QAAQ;AAAA,MACvC;AACA,YAAM,SAAS,UAAU,IAAI,QAAQ,IAAI;AACzC,YAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,EAAE,OAAO,QAAQ,EAAE;AACxD,UAAI,CAAC,QAAQ,QAAQ;AACpB,kBAAU,OAAO,QAAQ,IAAI;AAAA,MAC9B,OAAO;AACN,kBAAU,IAAI,QAAQ,MAAM,MAAM;AAAA,MACnC;AAAA,IACD;AAEA,aAAS,eAAe,SAAoB;AAC3C,oBAAc,IAAI,IAAI,SAAS;AAE/B,UAAI,SAAS,UAAU,IAAI,OAAO;AAClC,UAAI,CAAC,QAAQ;AACZ,iBAAS,CAAC;AACV,kBAAU,IAAI,SAAS,MAAM;AAAA,MAC9B,WAAW,WAAW,UAAU,IAAI,OAAO,GAAG;AAC7C,iBAAS,OAAO,MAAM,CAAC;AACvB,kBAAU,IAAI,SAAS,MAAM;AAAA,MAC9B;AACA,aAAO;AAAA,IACR;AAEA,aAAS,WAAW,SAAoB;AACvC,qBAAe,QAAQ,MAAM,EAAE,KAAK,OAAO;AAC3C,qBAAe,QAAQ,IAAI,EAAE,KAAK,OAAO;AAAA,IAC1C;AAEA,eAAW,WAAW,MAAM;AAC3B,iBAAW,kBAAc,8BAAgB,QAAQ,KAAK,GAAG;AACxD,mBAAW,UAAU;AAAA,MACtB;AAEA,iBAAW,CAAC,MAAM,IAAI,SAAK,8BAAgB,QAAQ,OAAO,GAAG;AAC5D,wBAAgB,IAAI;AACpB,mBAAW,IAAI;AAAA,MAChB;AAEA,iBAAW,YAAQ,8BAAgB,QAAQ,OAAO,GAAG;AACpD,wBAAgB,IAAI;AAAA,MACrB;AAAA,IACD;AAGA,WAAO,aAAa;AAAA,EACrB,CAAC;AACF;",
4
+ "sourcesContent": ["import { Computed, RESET_VALUE, computed, isUninitialized } from '@tldraw/state'\nimport { TLArrowBinding, TLBinding, TLShapeId, TLUnknownBinding } from '@tldraw/tlschema'\nimport { objectMapValues } from '@tldraw/utils'\nimport { Editor } from '../Editor'\n\ntype TLBindingsIndex = Map<TLShapeId, TLBinding[]>\n\nfunction fromScratch(bindingsQuery: Computed<(TLArrowBinding | TLUnknownBinding)[], unknown>) {\n\tconst allBindings = bindingsQuery.get() as TLBinding[]\n\n\tconst shapesToBindings: TLBindingsIndex = new Map()\n\n\tfor (const binding of allBindings) {\n\t\tconst { fromId, toId } = binding\n\t\tconst bindingsForFromShape = shapesToBindings.get(fromId)\n\t\tif (!bindingsForFromShape) {\n\t\t\tshapesToBindings.set(fromId, [binding])\n\t\t} else {\n\t\t\tbindingsForFromShape.push(binding)\n\t\t}\n\t\tconst bindingsForToShape = shapesToBindings.get(toId)\n\t\tif (!bindingsForToShape) {\n\t\t\tshapesToBindings.set(toId, [binding])\n\t\t} else {\n\t\t\tbindingsForToShape.push(binding)\n\t\t}\n\t}\n\n\treturn shapesToBindings\n}\n\nexport const bindingsIndex = (editor: Editor): Computed<TLBindingsIndex> => {\n\tconst { store } = editor\n\tconst bindingsHistory = store.query.filterHistory('binding')\n\tconst bindingsQuery = store.query.records('binding')\n\n\treturn computed<TLBindingsIndex>('arrowBindingsIndex', (_lastValue, lastComputedEpoch) => {\n\t\tif (isUninitialized(_lastValue)) {\n\t\t\treturn fromScratch(bindingsQuery)\n\t\t}\n\n\t\tconst lastValue = _lastValue\n\n\t\tconst diff = bindingsHistory.getDiffSince(lastComputedEpoch)\n\n\t\tif (diff === RESET_VALUE) {\n\t\t\treturn fromScratch(bindingsQuery)\n\t\t}\n\n\t\tlet nextValue: TLBindingsIndex | undefined = undefined\n\n\t\tfunction removingBinding(binding: TLBinding) {\n\t\t\tnextValue ??= new Map(lastValue)\n\t\t\tconst prevFrom = nextValue.get(binding.fromId)\n\t\t\tconst nextFrom = prevFrom?.filter((b) => b.id !== binding.id)\n\t\t\tif (!nextFrom?.length) {\n\t\t\t\tnextValue.delete(binding.fromId)\n\t\t\t} else {\n\t\t\t\tnextValue.set(binding.fromId, nextFrom)\n\t\t\t}\n\t\t\tconst prevTo = nextValue.get(binding.toId)\n\t\t\tconst nextTo = prevTo?.filter((b) => b.id !== binding.id)\n\t\t\tif (!nextTo?.length) {\n\t\t\t\tnextValue.delete(binding.toId)\n\t\t\t} else {\n\t\t\t\tnextValue.set(binding.toId, nextTo)\n\t\t\t}\n\t\t}\n\n\t\tfunction ensureNewArray(shapeId: TLShapeId) {\n\t\t\tnextValue ??= new Map(lastValue)\n\n\t\t\tlet result = nextValue.get(shapeId)\n\t\t\tif (!result) {\n\t\t\t\tresult = []\n\t\t\t\tnextValue.set(shapeId, result)\n\t\t\t} else if (result === lastValue.get(shapeId)) {\n\t\t\t\tresult = result.slice(0)\n\t\t\t\tnextValue.set(shapeId, result)\n\t\t\t}\n\t\t\treturn result\n\t\t}\n\n\t\tfunction addBinding(binding: TLBinding) {\n\t\t\tensureNewArray(binding.fromId).push(binding)\n\t\t\tensureNewArray(binding.toId).push(binding)\n\t\t}\n\n\t\tfor (const changes of diff) {\n\t\t\tfor (const newBinding of objectMapValues(changes.added)) {\n\t\t\t\taddBinding(newBinding)\n\t\t\t}\n\n\t\t\tfor (const [prev, next] of objectMapValues(changes.updated)) {\n\t\t\t\tremovingBinding(prev)\n\t\t\t\taddBinding(next)\n\t\t\t}\n\n\t\t\tfor (const prev of objectMapValues(changes.removed)) {\n\t\t\t\tremovingBinding(prev)\n\t\t\t}\n\t\t}\n\n\t\t// TODO: add diff entries if we need them\n\t\treturn nextValue ?? lastValue\n\t})\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -24,32 +24,32 @@ module.exports = __toCommonJS(parentsToChildren_exports);
24
24
  var import_state = require("@tldraw/state");
25
25
  var import_tlschema = require("@tldraw/tlschema");
26
26
  var import_utils = require("@tldraw/utils");
27
+ function fromScratch(shapeIdsQuery, store) {
28
+ const result = {};
29
+ const shapeIds = shapeIdsQuery.get();
30
+ const shapes = Array(shapeIds.size);
31
+ shapeIds.forEach((id) => shapes.push(store.get(id)));
32
+ shapes.sort(import_utils.sortByIndex);
33
+ shapes.forEach((shape) => {
34
+ if (!result[shape.parentId]) {
35
+ result[shape.parentId] = [];
36
+ }
37
+ result[shape.parentId].push(shape.id);
38
+ });
39
+ return result;
40
+ }
27
41
  const parentsToChildren = (store) => {
28
42
  const shapeIdsQuery = store.query.ids("shape");
29
43
  const shapeHistory = store.query.filterHistory("shape");
30
- function fromScratch() {
31
- const result = {};
32
- const shapeIds = shapeIdsQuery.get();
33
- const shapes = Array(shapeIds.size);
34
- shapeIds.forEach((id) => shapes.push(store.get(id)));
35
- shapes.sort(import_utils.sortByIndex);
36
- shapes.forEach((shape) => {
37
- if (!result[shape.parentId]) {
38
- result[shape.parentId] = [];
39
- }
40
- result[shape.parentId].push(shape.id);
41
- });
42
- return result;
43
- }
44
44
  return (0, import_state.computed)(
45
45
  "parentsToChildrenWithIndexes",
46
46
  (lastValue, lastComputedEpoch) => {
47
47
  if ((0, import_state.isUninitialized)(lastValue)) {
48
- return fromScratch();
48
+ return fromScratch(shapeIdsQuery, store);
49
49
  }
50
50
  const diff = shapeHistory.getDiffSince(lastComputedEpoch);
51
51
  if (diff === import_state.RESET_VALUE) {
52
- return fromScratch();
52
+ return fromScratch(shapeIdsQuery, store);
53
53
  }
54
54
  if (diff.length === 0) return lastValue;
55
55
  let newValue = null;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/editor/derivations/parentsToChildren.ts"],
4
- "sourcesContent": ["import { computed, isUninitialized, RESET_VALUE } from '@tldraw/state'\nimport { RecordsDiff } from '@tldraw/store'\nimport { isShape, TLParentId, TLRecord, TLShape, TLShapeId, TLStore } from '@tldraw/tlschema'\nimport { compact, sortByIndex } from '@tldraw/utils'\n\ntype Parents2Children = Record<TLParentId, TLShapeId[]>\n\nexport const parentsToChildren = (store: TLStore) => {\n\tconst shapeIdsQuery = store.query.ids<'shape'>('shape')\n\tconst shapeHistory = store.query.filterHistory('shape')\n\n\tfunction fromScratch() {\n\t\tconst result: Parents2Children = {}\n\t\tconst shapeIds = shapeIdsQuery.get()\n\t\tconst shapes = Array(shapeIds.size) as TLShape[]\n\t\tshapeIds.forEach((id) => shapes.push(store.get(id)!))\n\n\t\t// Sort the shapes by index\n\t\tshapes.sort(sortByIndex)\n\n\t\t// Populate the result object with an array for each parent.\n\t\tshapes.forEach((shape) => {\n\t\t\tif (!result[shape.parentId]) {\n\t\t\t\tresult[shape.parentId] = []\n\t\t\t}\n\t\t\tresult[shape.parentId].push(shape.id)\n\t\t})\n\n\t\treturn result\n\t}\n\n\treturn computed<Parents2Children>(\n\t\t'parentsToChildrenWithIndexes',\n\t\t(lastValue, lastComputedEpoch) => {\n\t\t\tif (isUninitialized(lastValue)) {\n\t\t\t\treturn fromScratch()\n\t\t\t}\n\n\t\t\tconst diff = shapeHistory.getDiffSince(lastComputedEpoch)\n\n\t\t\tif (diff === RESET_VALUE) {\n\t\t\t\treturn fromScratch()\n\t\t\t}\n\n\t\t\tif (diff.length === 0) return lastValue\n\n\t\t\tlet newValue: Record<TLParentId, TLShapeId[]> | null = null\n\n\t\t\tconst ensureNewArray = (parentId: TLParentId) => {\n\t\t\t\tif (!newValue) {\n\t\t\t\t\tnewValue = { ...lastValue }\n\t\t\t\t}\n\t\t\t\tif (!newValue[parentId]) {\n\t\t\t\t\tnewValue[parentId] = []\n\t\t\t\t} else if (newValue[parentId] === lastValue[parentId]) {\n\t\t\t\t\tnewValue[parentId] = [...newValue[parentId]!]\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst toSort = new Set<TLShapeId[]>()\n\n\t\t\tlet changes: RecordsDiff<TLRecord>\n\n\t\t\tfor (let i = 0, n = diff.length; i < n; i++) {\n\t\t\t\tchanges = diff[i]\n\n\t\t\t\t// Iterate through the added shapes, add them to the new value and mark them for sorting\n\t\t\t\tfor (const record of Object.values(changes.added)) {\n\t\t\t\t\tif (!isShape(record)) continue\n\t\t\t\t\tensureNewArray(record.parentId)\n\t\t\t\t\tnewValue![record.parentId].push(record.id)\n\t\t\t\t\ttoSort.add(newValue![record.parentId])\n\t\t\t\t}\n\n\t\t\t\t// Iterate through the updated shapes, add them to their parents in the new value and mark them for sorting\n\t\t\t\tfor (const [from, to] of Object.values(changes.updated)) {\n\t\t\t\t\tif (!isShape(to)) continue\n\t\t\t\t\tif (!isShape(from)) continue\n\n\t\t\t\t\tif (from.parentId !== to.parentId) {\n\t\t\t\t\t\t// If the parents have changed, remove the new value from the old parent and add it to the new parent\n\t\t\t\t\t\tensureNewArray(from.parentId)\n\t\t\t\t\t\tensureNewArray(to.parentId)\n\t\t\t\t\t\tnewValue![from.parentId].splice(newValue![from.parentId].indexOf(to.id), 1)\n\t\t\t\t\t\tnewValue![to.parentId].push(to.id)\n\t\t\t\t\t\ttoSort.add(newValue![to.parentId])\n\t\t\t\t\t} else if (from.index !== to.index) {\n\t\t\t\t\t\t// If the parent is the same but the index has changed (e.g. if they've been reordered), update the parent's array at the new index\n\t\t\t\t\t\tensureNewArray(to.parentId)\n\t\t\t\t\t\tconst idx = newValue![to.parentId].indexOf(to.id)\n\t\t\t\t\t\tnewValue![to.parentId][idx] = to.id\n\t\t\t\t\t\ttoSort.add(newValue![to.parentId])\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Iterate through the removed shapes, remove them from their parents in new value\n\t\t\t\tfor (const record of Object.values(changes.removed)) {\n\t\t\t\t\tif (!isShape(record)) continue\n\t\t\t\t\tensureNewArray(record.parentId)\n\t\t\t\t\tnewValue![record.parentId].splice(newValue![record.parentId].indexOf(record.id), 1)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Sort the arrays that have been marked for sorting\n\t\t\tfor (const arr of toSort) {\n\t\t\t\t// It's possible that some of the shapes may be deleted. But in which case would this be so?\n\t\t\t\tconst shapesInArr = compact(arr.map((id) => store.get(id)))\n\t\t\t\tshapesInArr.sort(sortByIndex)\n\t\t\t\tarr.splice(0, arr.length, ...shapesInArr.map((shape) => shape.id))\n\t\t\t}\n\n\t\t\treturn newValue ?? lastValue\n\t\t}\n\t)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Computed, computed, isUninitialized, RESET_VALUE } from '@tldraw/state'\nimport { CollectionDiff, RecordsDiff } from '@tldraw/store'\nimport { isShape, TLParentId, TLRecord, TLShape, TLShapeId, TLStore } from '@tldraw/tlschema'\nimport { compact, sortByIndex } from '@tldraw/utils'\n\ntype ParentShapeIdsToChildShapeIds = Record<TLParentId, TLShapeId[]>\n\nfunction fromScratch(\n\tshapeIdsQuery: Computed<Set<TLShapeId>, CollectionDiff<TLShapeId>>,\n\tstore: TLStore\n) {\n\tconst result: ParentShapeIdsToChildShapeIds = {}\n\tconst shapeIds = shapeIdsQuery.get()\n\tconst shapes = Array(shapeIds.size) as TLShape[]\n\tshapeIds.forEach((id) => shapes.push(store.get(id)!))\n\n\t// Sort the shapes by index\n\tshapes.sort(sortByIndex)\n\n\t// Populate the result object with an array for each parent.\n\tshapes.forEach((shape) => {\n\t\tif (!result[shape.parentId]) {\n\t\t\tresult[shape.parentId] = []\n\t\t}\n\t\tresult[shape.parentId].push(shape.id)\n\t})\n\n\treturn result\n}\n\nexport const parentsToChildren = (store: TLStore) => {\n\tconst shapeIdsQuery = store.query.ids<'shape'>('shape')\n\tconst shapeHistory = store.query.filterHistory('shape')\n\n\treturn computed<ParentShapeIdsToChildShapeIds>(\n\t\t'parentsToChildrenWithIndexes',\n\t\t(lastValue, lastComputedEpoch) => {\n\t\t\tif (isUninitialized(lastValue)) {\n\t\t\t\treturn fromScratch(shapeIdsQuery, store)\n\t\t\t}\n\n\t\t\tconst diff = shapeHistory.getDiffSince(lastComputedEpoch)\n\n\t\t\tif (diff === RESET_VALUE) {\n\t\t\t\treturn fromScratch(shapeIdsQuery, store)\n\t\t\t}\n\n\t\t\tif (diff.length === 0) return lastValue\n\n\t\t\tlet newValue: Record<TLParentId, TLShapeId[]> | null = null\n\n\t\t\tconst ensureNewArray = (parentId: TLParentId) => {\n\t\t\t\tif (!newValue) {\n\t\t\t\t\tnewValue = { ...lastValue }\n\t\t\t\t}\n\t\t\t\tif (!newValue[parentId]) {\n\t\t\t\t\tnewValue[parentId] = []\n\t\t\t\t} else if (newValue[parentId] === lastValue[parentId]) {\n\t\t\t\t\tnewValue[parentId] = [...newValue[parentId]!]\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst toSort = new Set<TLShapeId[]>()\n\n\t\t\tlet changes: RecordsDiff<TLRecord>\n\n\t\t\tfor (let i = 0, n = diff.length; i < n; i++) {\n\t\t\t\tchanges = diff[i]\n\n\t\t\t\t// Iterate through the added shapes, add them to the new value and mark them for sorting\n\t\t\t\tfor (const record of Object.values(changes.added)) {\n\t\t\t\t\tif (!isShape(record)) continue\n\t\t\t\t\tensureNewArray(record.parentId)\n\t\t\t\t\tnewValue![record.parentId].push(record.id)\n\t\t\t\t\ttoSort.add(newValue![record.parentId])\n\t\t\t\t}\n\n\t\t\t\t// Iterate through the updated shapes, add them to their parents in the new value and mark them for sorting\n\t\t\t\tfor (const [from, to] of Object.values(changes.updated)) {\n\t\t\t\t\tif (!isShape(to)) continue\n\t\t\t\t\tif (!isShape(from)) continue\n\n\t\t\t\t\tif (from.parentId !== to.parentId) {\n\t\t\t\t\t\t// If the parents have changed, remove the new value from the old parent and add it to the new parent\n\t\t\t\t\t\tensureNewArray(from.parentId)\n\t\t\t\t\t\tensureNewArray(to.parentId)\n\t\t\t\t\t\tnewValue![from.parentId].splice(newValue![from.parentId].indexOf(to.id), 1)\n\t\t\t\t\t\tnewValue![to.parentId].push(to.id)\n\t\t\t\t\t\ttoSort.add(newValue![to.parentId])\n\t\t\t\t\t} else if (from.index !== to.index) {\n\t\t\t\t\t\t// If the parent is the same but the index has changed (e.g. if they've been reordered), update the parent's array at the new index\n\t\t\t\t\t\tensureNewArray(to.parentId)\n\t\t\t\t\t\tconst idx = newValue![to.parentId].indexOf(to.id)\n\t\t\t\t\t\tnewValue![to.parentId][idx] = to.id\n\t\t\t\t\t\ttoSort.add(newValue![to.parentId])\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Iterate through the removed shapes, remove them from their parents in new value\n\t\t\t\tfor (const record of Object.values(changes.removed)) {\n\t\t\t\t\tif (!isShape(record)) continue\n\t\t\t\t\tensureNewArray(record.parentId)\n\t\t\t\t\tnewValue![record.parentId].splice(newValue![record.parentId].indexOf(record.id), 1)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Sort the arrays that have been marked for sorting\n\t\t\tfor (const arr of toSort) {\n\t\t\t\t// It's possible that some of the shapes may be deleted. But in which case would this be so?\n\t\t\t\tconst shapesInArr = compact(arr.map((id) => store.get(id)))\n\t\t\t\tshapesInArr.sort(sortByIndex)\n\t\t\t\tarr.splice(0, arr.length, ...shapesInArr.map((shape) => shape.id))\n\t\t\t}\n\n\t\t\treturn newValue ?? lastValue\n\t\t}\n\t)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -68,7 +68,7 @@ __export(ClickManager_exports, {
68
68
  });
69
69
  module.exports = __toCommonJS(ClickManager_exports);
70
70
  var import_utils = require("@tldraw/utils");
71
- var import_Vec = require("../../primitives/Vec");
71
+ var import_Vec = require("../../../primitives/Vec");
72
72
  var _cancelDoubleClickTimeout_dec, __getClickTimeout_dec, _init;
73
73
  const MAX_CLICK_DISTANCE = 40;
74
74
  __getClickTimeout_dec = [import_utils.bind], _cancelDoubleClickTimeout_dec = [import_utils.bind];
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/lib/editor/managers/ClickManager/ClickManager.ts"],
4
+ "sourcesContent": ["import { bind, uniqueId } from '@tldraw/utils'\nimport { Vec } from '../../../primitives/Vec'\nimport type { Editor } from '../../Editor'\nimport { TLClickEventInfo, TLPointerEventInfo } from '../../types/event-types'\n\n/** @public */\nexport type TLClickState =\n\t| 'idle'\n\t| 'pendingDouble'\n\t| 'pendingTriple'\n\t| 'pendingQuadruple'\n\t| 'pendingOverflow'\n\t| 'overflow'\n\nconst MAX_CLICK_DISTANCE = 40\n\n/** @public */\nexport class ClickManager {\n\tconstructor(public editor: Editor) {}\n\n\tprivate _clickId = ''\n\n\tprivate _clickTimeout?: any\n\n\tprivate _clickScreenPoint?: Vec\n\n\tprivate _previousScreenPoint?: Vec\n\n\t@bind\n\t_getClickTimeout(state: TLClickState, id = uniqueId()) {\n\t\tthis._clickId = id\n\t\tclearTimeout(this._clickTimeout)\n\t\tthis._clickTimeout = this.editor.timers.setTimeout(\n\t\t\t() => {\n\t\t\t\tif (this._clickState === state && this._clickId === id) {\n\t\t\t\t\tswitch (this._clickState) {\n\t\t\t\t\t\tcase 'pendingTriple': {\n\t\t\t\t\t\t\tthis.editor.dispatch({\n\t\t\t\t\t\t\t\t...this.lastPointerInfo,\n\t\t\t\t\t\t\t\ttype: 'click',\n\t\t\t\t\t\t\t\tname: 'double_click',\n\t\t\t\t\t\t\t\tphase: 'settle',\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'pendingQuadruple': {\n\t\t\t\t\t\t\tthis.editor.dispatch({\n\t\t\t\t\t\t\t\t...this.lastPointerInfo,\n\t\t\t\t\t\t\t\ttype: 'click',\n\t\t\t\t\t\t\t\tname: 'triple_click',\n\t\t\t\t\t\t\t\tphase: 'settle',\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'pendingOverflow': {\n\t\t\t\t\t\t\tthis.editor.dispatch({\n\t\t\t\t\t\t\t\t...this.lastPointerInfo,\n\t\t\t\t\t\t\t\ttype: 'click',\n\t\t\t\t\t\t\t\tname: 'quadruple_click',\n\t\t\t\t\t\t\t\tphase: 'settle',\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\t// noop\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._clickState = 'idle'\n\t\t\t\t}\n\t\t\t},\n\t\t\tstate === 'idle' || state === 'pendingDouble'\n\t\t\t\t? this.editor.options.doubleClickDurationMs\n\t\t\t\t: this.editor.options.multiClickDurationMs\n\t\t)\n\t}\n\n\t/**\n\t * The current click state.\n\t *\n\t * @internal\n\t */\n\tprivate _clickState?: TLClickState = 'idle'\n\n\t/**\n\t * The current click state.\n\t *\n\t * @public\n\t */\n\t// eslint-disable-next-line no-restricted-syntax\n\tget clickState() {\n\t\treturn this._clickState\n\t}\n\n\tlastPointerInfo = {} as TLPointerEventInfo\n\n\thandlePointerEvent(info: TLPointerEventInfo): TLPointerEventInfo | TLClickEventInfo {\n\t\tswitch (info.name) {\n\t\t\tcase 'pointer_down': {\n\t\t\t\tif (!this._clickState) return info\n\t\t\t\tthis._clickScreenPoint = Vec.From(info.point)\n\n\t\t\t\tif (\n\t\t\t\t\tthis._previousScreenPoint &&\n\t\t\t\t\tVec.Dist2(this._previousScreenPoint, this._clickScreenPoint) > MAX_CLICK_DISTANCE ** 2\n\t\t\t\t) {\n\t\t\t\t\tthis._clickState = 'idle'\n\t\t\t\t}\n\n\t\t\t\tthis._previousScreenPoint = this._clickScreenPoint\n\n\t\t\t\tthis.lastPointerInfo = info\n\n\t\t\t\tswitch (this._clickState) {\n\t\t\t\t\tcase 'pendingDouble': {\n\t\t\t\t\t\tthis._clickState = 'pendingTriple'\n\t\t\t\t\t\tthis._clickTimeout = this._getClickTimeout(this._clickState)\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...info,\n\t\t\t\t\t\t\ttype: 'click',\n\t\t\t\t\t\t\tname: 'double_click',\n\t\t\t\t\t\t\tphase: 'down',\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcase 'pendingTriple': {\n\t\t\t\t\t\tthis._clickState = 'pendingQuadruple'\n\t\t\t\t\t\tthis._clickTimeout = this._getClickTimeout(this._clickState)\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...info,\n\t\t\t\t\t\t\ttype: 'click',\n\t\t\t\t\t\t\tname: 'triple_click',\n\t\t\t\t\t\t\tphase: 'down',\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcase 'pendingQuadruple': {\n\t\t\t\t\t\tthis._clickState = 'pendingOverflow'\n\t\t\t\t\t\tthis._clickTimeout = this._getClickTimeout(this._clickState)\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...info,\n\t\t\t\t\t\t\ttype: 'click',\n\t\t\t\t\t\t\tname: 'quadruple_click',\n\t\t\t\t\t\t\tphase: 'down',\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcase 'idle': {\n\t\t\t\t\t\tthis._clickState = 'pendingDouble'\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'pendingOverflow': {\n\t\t\t\t\t\tthis._clickState = 'overflow'\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\t// overflow\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tthis._clickTimeout = this._getClickTimeout(this._clickState)\n\t\t\t\treturn info\n\t\t\t}\n\t\t\tcase 'pointer_up': {\n\t\t\t\tif (!this._clickState) return info\n\t\t\t\tthis._clickScreenPoint = Vec.From(info.point)\n\n\t\t\t\tswitch (this._clickState) {\n\t\t\t\t\tcase 'pendingTriple': {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...this.lastPointerInfo,\n\t\t\t\t\t\t\ttype: 'click',\n\t\t\t\t\t\t\tname: 'double_click',\n\t\t\t\t\t\t\tphase: 'up',\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcase 'pendingQuadruple': {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...this.lastPointerInfo,\n\t\t\t\t\t\t\ttype: 'click',\n\t\t\t\t\t\t\tname: 'triple_click',\n\t\t\t\t\t\t\tphase: 'up',\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcase 'pendingOverflow': {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...this.lastPointerInfo,\n\t\t\t\t\t\t\ttype: 'click',\n\t\t\t\t\t\t\tname: 'quadruple_click',\n\t\t\t\t\t\t\tphase: 'up',\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\t// idle, pendingDouble, overflow\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn info\n\t\t\t}\n\t\t\tcase 'pointer_move': {\n\t\t\t\tif (\n\t\t\t\t\tthis._clickState !== 'idle' &&\n\t\t\t\t\tthis._clickScreenPoint &&\n\t\t\t\t\tVec.Dist2(this._clickScreenPoint, this.editor.inputs.currentScreenPoint) >\n\t\t\t\t\t\t(this.editor.getInstanceState().isCoarsePointer\n\t\t\t\t\t\t\t? this.editor.options.coarseDragDistanceSquared\n\t\t\t\t\t\t\t: this.editor.options.dragDistanceSquared)\n\t\t\t\t) {\n\t\t\t\t\tthis.cancelDoubleClickTimeout()\n\t\t\t\t}\n\t\t\t\treturn info\n\t\t\t}\n\t\t}\n\t\treturn info\n\t}\n\n\t/**\n\t * Cancel the double click timeout.\n\t *\n\t * @internal\n\t */\n\t@bind\n\tcancelDoubleClickTimeout() {\n\t\tthis._clickTimeout = clearTimeout(this._clickTimeout)\n\t\tthis._clickState = 'idle'\n\t}\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -21,8 +21,8 @@ __export(EdgeScrollManager_exports, {
21
21
  EdgeScrollManager: () => EdgeScrollManager
22
22
  });
23
23
  module.exports = __toCommonJS(EdgeScrollManager_exports);
24
- var import_Vec = require("../../primitives/Vec");
25
- var import_easings = require("../../primitives/easings");
24
+ var import_Vec = require("../../../primitives/Vec");
25
+ var import_easings = require("../../../primitives/easings");
26
26
  class EdgeScrollManager {
27
27
  constructor(editor) {
28
28
  this.editor = editor;
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts"],
4
+ "sourcesContent": ["import { Vec } from '../../../primitives/Vec'\nimport { EASINGS } from '../../../primitives/easings'\nimport { Editor } from '../../Editor'\n\n/** @public */\nexport class EdgeScrollManager {\n\tconstructor(public editor: Editor) {}\n\n\tprivate _isEdgeScrolling = false\n\tprivate _edgeScrollDuration = -1\n\n\t/**\n\t * Update the camera position when the mouse is close to the edge of the screen.\n\t * Run this on every tick when in a state where edge scrolling is enabled.\n\t *\n\t * @public\n\t */\n\tupdateEdgeScrolling(elapsed: number) {\n\t\tconst { editor } = this\n\t\tconst edgeScrollProximityFactor = this.getEdgeScroll()\n\t\tif (edgeScrollProximityFactor.x === 0 && edgeScrollProximityFactor.y === 0) {\n\t\t\tif (this._isEdgeScrolling) {\n\t\t\t\tthis._isEdgeScrolling = false\n\t\t\t\tthis._edgeScrollDuration = 0\n\t\t\t}\n\t\t} else {\n\t\t\tif (!this._isEdgeScrolling) {\n\t\t\t\tthis._isEdgeScrolling = true\n\t\t\t\tthis._edgeScrollDuration = 0\n\t\t\t}\n\t\t\tthis._edgeScrollDuration += elapsed\n\t\t\tif (this._edgeScrollDuration > editor.options.edgeScrollDelay) {\n\t\t\t\tconst eased =\n\t\t\t\t\teditor.options.edgeScrollEaseDuration > 0\n\t\t\t\t\t\t? EASINGS.easeInCubic(\n\t\t\t\t\t\t\t\tMath.min(\n\t\t\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t\t\tthis._edgeScrollDuration /\n\t\t\t\t\t\t\t\t\t\t(editor.options.edgeScrollDelay + editor.options.edgeScrollEaseDuration)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: 1\n\t\t\t\tthis.moveCameraWhenCloseToEdge({\n\t\t\t\t\tx: edgeScrollProximityFactor.x * eased,\n\t\t\t\t\ty: edgeScrollProximityFactor.y * eased,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Helper function to get the scroll proximity factor for a given position.\n\t * @param position - The mouse position on the axis.\n\t * @param dimension - The component dimension on the axis.\n\t * @param isCoarse - Whether the pointer is coarse.\n\t * @param insetStart - Whether the pointer is inset at the start of the axis.\n\t * @param insetEnd - Whether the pointer is inset at the end of the axis.\n\t * @internal\n\t */\n\tprivate getEdgeProximityFactors(\n\t\tposition: number,\n\t\tdimension: number,\n\t\tisCoarse: boolean,\n\t\tinsetStart: boolean,\n\t\tinsetEnd: boolean\n\t) {\n\t\tconst { editor } = this\n\t\tconst dist = editor.options.edgeScrollDistance\n\t\tconst pw = isCoarse ? editor.options.coarsePointerWidth : 0 // pointer width\n\t\tconst pMin = position - pw\n\t\tconst pMax = position + pw\n\t\tconst min = insetStart ? 0 : dist\n\t\tconst max = insetEnd ? dimension : dimension - dist\n\t\tif (pMin < min) {\n\t\t\treturn Math.min(1, (min - pMin) / dist)\n\t\t} else if (pMax > max) {\n\t\t\treturn -Math.min(1, (pMax - max) / dist)\n\t\t}\n\t\treturn 0\n\t}\n\n\tprivate getEdgeScroll() {\n\t\tconst { editor } = this\n\t\tconst {\n\t\t\tinputs: {\n\t\t\t\tcurrentScreenPoint: { x, y },\n\t\t\t},\n\t\t} = editor\n\t\tconst screenBounds = editor.getViewportScreenBounds()\n\n\t\tconst {\n\t\t\tisCoarsePointer,\n\t\t\tinsets: [t, r, b, l],\n\t\t} = editor.getInstanceState()\n\t\tconst proximityFactorX = this.getEdgeProximityFactors(x, screenBounds.w, isCoarsePointer, l, r)\n\t\tconst proximityFactorY = this.getEdgeProximityFactors(y, screenBounds.h, isCoarsePointer, t, b)\n\n\t\treturn {\n\t\t\tx: proximityFactorX,\n\t\t\ty: proximityFactorY,\n\t\t}\n\t}\n\n\t/**\n\t * Moves the camera when the mouse is close to the edge of the screen.\n\t * @public\n\t */\n\tprivate moveCameraWhenCloseToEdge(proximityFactor: { x: number; y: number }) {\n\t\tconst { editor } = this\n\t\tif (!editor.inputs.isDragging || editor.inputs.isPanning || editor.getCameraOptions().isLocked)\n\t\t\treturn\n\n\t\tif (proximityFactor.x === 0 && proximityFactor.y === 0) return\n\n\t\tconst screenBounds = editor.getViewportScreenBounds()\n\n\t\t// Determines how much the speed is affected by the screen size\n\t\tconst screenSizeFactorX = screenBounds.w < 1000 ? 0.612 : 1\n\t\tconst screenSizeFactorY = screenBounds.h < 1000 ? 0.612 : 1\n\n\t\t// Determines the base speed of the scroll\n\t\tconst zoomLevel = editor.getZoomLevel()\n\t\tconst pxSpeed = editor.user.getEdgeScrollSpeed() * editor.options.edgeScrollSpeed\n\t\tconst scrollDeltaX = (pxSpeed * proximityFactor.x * screenSizeFactorX) / zoomLevel\n\t\tconst scrollDeltaY = (pxSpeed * proximityFactor.y * screenSizeFactorY) / zoomLevel\n\n\t\t// update the camera\n\t\tconst { x, y, z } = editor.getCamera()\n\t\teditor.setCamera(new Vec(x + scrollDeltaX, y + scrollDeltaY, z))\n\t}\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/lib/editor/managers/FocusManager/FocusManager.ts"],
4
+ "sourcesContent": ["import type { Editor } from '../../Editor'\n\n/**\n * A manager for ensuring correct focus across the editor.\n * It will listen for changes in the instance state to make sure the\n * container is focused when the editor is focused.\n * Also, it will make sure that the focus is on things like text\n * labels when the editor is in editing mode.\n *\n * @internal\n */\nexport class FocusManager {\n\tprivate disposeSideEffectListener?: () => void\n\n\tconstructor(\n\t\tpublic editor: Editor,\n\t\tautoFocus?: boolean\n\t) {\n\t\tthis.disposeSideEffectListener = editor.sideEffects.registerAfterChangeHandler(\n\t\t\t'instance',\n\t\t\t(prev, next) => {\n\t\t\t\tif (prev.isFocused !== next.isFocused) {\n\t\t\t\t\tthis.updateContainerClass()\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\n\t\tconst currentFocusState = editor.getInstanceState().isFocused\n\t\tif (autoFocus !== currentFocusState) {\n\t\t\teditor.updateInstanceState({ isFocused: !!autoFocus })\n\t\t}\n\t\tthis.updateContainerClass()\n\n\t\tdocument.body.addEventListener('keydown', this.handleKeyDown.bind(this))\n\t\tdocument.body.addEventListener('mousedown', this.handleMouseDown.bind(this))\n\t}\n\n\t/**\n\t * The editor's focus state and the container's focus state\n\t * are not necessarily always in sync. For that reason we\n\t * can't rely on the css `:focus` or `:focus-within` selectors to style the\n\t * editor when it is in focus.\n\t *\n\t * For that reason we synchronize the editor's focus state with a\n\t * special class on the container: tl-container__focused\n\t */\n\tprivate updateContainerClass() {\n\t\tconst container = this.editor.getContainer()\n\t\tconst instanceState = this.editor.getInstanceState()\n\n\t\tif (instanceState.isFocused) {\n\t\t\tcontainer.classList.add('tl-container__focused')\n\t\t} else {\n\t\t\tcontainer.classList.remove('tl-container__focused')\n\t\t}\n\t\tcontainer.classList.add('tl-container__no-focus-ring')\n\t}\n\n\tprivate handleKeyDown(keyEvent: KeyboardEvent) {\n\t\tconst container = this.editor.getContainer()\n\t\tif (this.editor.isIn('select.editing_shape')) return\n\t\tif (document.activeElement === container && this.editor.getSelectedShapeIds().length > 0) return\n\t\tif (['Tab', 'ArrowUp', 'ArrowDown'].includes(keyEvent.key)) {\n\t\t\tcontainer.classList.remove('tl-container__no-focus-ring')\n\t\t}\n\t}\n\n\tprivate handleMouseDown() {\n\t\tconst container = this.editor.getContainer()\n\t\tcontainer.classList.add('tl-container__no-focus-ring')\n\t}\n\n\tfocus() {\n\t\tthis.editor.getContainer().focus()\n\t}\n\n\tblur() {\n\t\tthis.editor.complete() // stop any interaction\n\t\tthis.editor.getContainer().blur() // blur the container\n\t}\n\n\tdispose() {\n\t\tdocument.body.removeEventListener('keydown', this.handleKeyDown.bind(this))\n\t\tdocument.body.removeEventListener('mousedown', this.handleMouseDown.bind(this))\n\t\tthis.disposeSideEffectListener?.()\n\t}\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAWO,MAAM,aAAa;AAAA,EAGzB,YACQ,QACP,WACC;AAFM;AAGP,SAAK,4BAA4B,OAAO,YAAY;AAAA,MACnD;AAAA,MACA,CAAC,MAAM,SAAS;AACf,YAAI,KAAK,cAAc,KAAK,WAAW;AACtC,eAAK,qBAAqB;AAAA,QAC3B;AAAA,MACD;AAAA,IACD;AAEA,UAAM,oBAAoB,OAAO,iBAAiB,EAAE;AACpD,QAAI,cAAc,mBAAmB;AACpC,aAAO,oBAAoB,EAAE,WAAW,CAAC,CAAC,UAAU,CAAC;AAAA,IACtD;AACA,SAAK,qBAAqB;AAE1B,aAAS,KAAK,iBAAiB,WAAW,KAAK,cAAc,KAAK,IAAI,CAAC;AACvE,aAAS,KAAK,iBAAiB,aAAa,KAAK,gBAAgB,KAAK,IAAI,CAAC;AAAA,EAC5E;AAAA,EAvBQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkCA,uBAAuB;AAC9B,UAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,UAAM,gBAAgB,KAAK,OAAO,iBAAiB;AAEnD,QAAI,cAAc,WAAW;AAC5B,gBAAU,UAAU,IAAI,uBAAuB;AAAA,IAChD,OAAO;AACN,gBAAU,UAAU,OAAO,uBAAuB;AAAA,IACnD;AACA,cAAU,UAAU,IAAI,6BAA6B;AAAA,EACtD;AAAA,EAEQ,cAAc,UAAyB;AAC9C,UAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,QAAI,KAAK,OAAO,KAAK,sBAAsB,EAAG;AAC9C,QAAI,SAAS,kBAAkB,aAAa,KAAK,OAAO,oBAAoB,EAAE,SAAS,EAAG;AAC1F,QAAI,CAAC,OAAO,WAAW,WAAW,EAAE,SAAS,SAAS,GAAG,GAAG;AAC3D,gBAAU,UAAU,OAAO,6BAA6B;AAAA,IACzD;AAAA,EACD;AAAA,EAEQ,kBAAkB;AACzB,UAAM,YAAY,KAAK,OAAO,aAAa;AAC3C,cAAU,UAAU,IAAI,6BAA6B;AAAA,EACtD;AAAA,EAEA,QAAQ;AACP,SAAK,OAAO,aAAa,EAAE,MAAM;AAAA,EAClC;AAAA,EAEA,OAAO;AACN,SAAK,OAAO,SAAS;AACrB,SAAK,OAAO,aAAa,EAAE,KAAK;AAAA,EACjC;AAAA,EAEA,UAAU;AACT,aAAS,KAAK,oBAAoB,WAAW,KAAK,cAAc,KAAK,IAAI,CAAC;AAC1E,aAAS,KAAK,oBAAoB,aAAa,KAAK,gBAAgB,KAAK,IAAI,CAAC;AAC9E,SAAK,4BAA4B;AAAA,EAClC;AACD;",
6
+ "names": []
7
+ }
@@ -36,8 +36,7 @@ class FontManager {
36
36
  },
37
37
  {
38
38
  areResultsEqual: import_utils.areArraysShallowEqual,
39
- // @ts-expect-error
40
- areRecordsEqual: (a, b) => a.props.richText === b.props.richText
39
+ areRecordsEqual: (a, b) => a.props === b.props && a.meta === b.meta
41
40
  }
42
41
  );
43
42
  this.shapeFontLoadStateCache = editor.store.createCache(
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/lib/editor/managers/FontManager/FontManager.ts"],
4
+ "sourcesContent": ["import { computed, EMPTY_ARRAY, transact } from '@tldraw/state'\nimport { AtomMap } from '@tldraw/store'\nimport { TLShape, TLShapeId } from '@tldraw/tlschema'\nimport {\n\tareArraysShallowEqual,\n\tcompact,\n\tFileHelpers,\n\tmapObjectMapValues,\n\tobjectMapEntries,\n} from '@tldraw/utils'\nimport { Editor } from '../../Editor'\n\n/**\n * Represents the `src` property of a {@link TLFontFace}.\n * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src | `src`} for details of the properties here.\n * @public\n */\nexport interface TLFontFaceSource {\n\t/**\n\t * A URL from which to load the font. If the value here is a key in\n\t * {@link tldraw#TLEditorAssetUrls.fonts}, the value from there will be used instead.\n\t */\n\turl: string\n\tformat?: string\n\ttech?: string\n}\n\n/**\n * A font face that can be used in the editor. The properties of this are largely the same as the\n * ones in the\n * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face | css `@font-face` rule}.\n * @public\n */\nexport interface TLFontFace {\n\t/**\n\t * How this font can be referred to in CSS.\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-family | `font-family`}.\n\t */\n\treadonly family: string\n\t/**\n\t * The source of the font. This\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src | `src`}.\n\t */\n\treadonly src: TLFontFaceSource\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/ascent-override | `ascent-override`}.\n\t */\n\treadonly ascentOverride?: string\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/descent-override | `descent-override`}.\n\t */\n\treadonly descentOverride?: string\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-stretch | `font-stretch`}.\n\t */\n\treadonly stretch?: string\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-style | `font-style`}.\n\t */\n\treadonly style?: string\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-weight | `font-weight`}.\n\t */\n\treadonly weight?: string\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-feature-settings | `font-feature-settings`}.\n\t */\n\treadonly featureSettings?: string\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/line-gap-override | `line-gap-override`}.\n\t */\n\treadonly lineGapOverride?: string\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range | `unicode-range`}.\n\t */\n\treadonly unicodeRange?: string\n}\n\ninterface FontState {\n\treadonly state: 'loading' | 'ready' | 'error'\n\treadonly instance: FontFace\n\treadonly loadingPromise: Promise<void>\n}\n\n/** @public */\nexport class FontManager {\n\tconstructor(\n\t\tprivate readonly editor: Editor,\n\t\tprivate readonly assetUrls?: { [key: string]: string | undefined }\n\t) {\n\t\tthis.shapeFontFacesCache = editor.store.createComputedCache(\n\t\t\t'shape font faces',\n\t\t\t(shape: TLShape) => {\n\t\t\t\tconst shapeUtil = this.editor.getShapeUtil(shape)\n\t\t\t\treturn shapeUtil.getFontFaces(shape)\n\t\t\t},\n\t\t\t{\n\t\t\t\tareResultsEqual: areArraysShallowEqual,\n\t\t\t\tareRecordsEqual: (a, b) => a.props === b.props && a.meta === b.meta,\n\t\t\t}\n\t\t)\n\n\t\tthis.shapeFontLoadStateCache = editor.store.createCache<(FontState | null)[], TLShape>(\n\t\t\t(id: TLShapeId) => {\n\t\t\t\tconst fontFacesComputed = computed('font faces', () => this.getShapeFontFaces(id))\n\t\t\t\treturn computed(\n\t\t\t\t\t'font load state',\n\t\t\t\t\t() => {\n\t\t\t\t\t\tconst states = fontFacesComputed.get().map((face) => this.getFontState(face))\n\t\t\t\t\t\treturn states\n\t\t\t\t\t},\n\t\t\t\t\t{ isEqual: areArraysShallowEqual }\n\t\t\t\t)\n\t\t\t}\n\t\t)\n\t}\n\n\tprivate readonly shapeFontFacesCache\n\tprivate readonly shapeFontLoadStateCache\n\n\tgetShapeFontFaces(shape: TLShape | TLShapeId): TLFontFace[] {\n\t\tconst shapeId = typeof shape === 'string' ? shape : shape.id\n\t\treturn this.shapeFontFacesCache.get(shapeId) ?? EMPTY_ARRAY\n\t}\n\n\ttrackFontsForShape(shape: TLShape | TLShapeId) {\n\t\tconst shapeId = typeof shape === 'string' ? shape : shape.id\n\t\tthis.shapeFontLoadStateCache.get(shapeId)\n\t}\n\n\tasync loadRequiredFontsForCurrentPage(limit = Infinity) {\n\t\tconst neededFonts = new Set<TLFontFace>()\n\t\tfor (const shapeId of this.editor.getCurrentPageShapeIds()) {\n\t\t\tfor (const font of this.getShapeFontFaces(this.editor.getShape(shapeId)!)) {\n\t\t\t\tneededFonts.add(font)\n\t\t\t}\n\t\t}\n\n\t\tif (neededFonts.size > limit) {\n\t\t\treturn\n\t\t}\n\n\t\tconst promises = Array.from(neededFonts, (font) => this.ensureFontIsLoaded(font))\n\t\tawait Promise.all(promises)\n\t}\n\n\tprivate readonly fontStates = new AtomMap<TLFontFace, FontState>('font states')\n\tprivate getFontState(font: TLFontFace): FontState | null {\n\t\treturn this.fontStates.get(font) ?? null\n\t}\n\n\tensureFontIsLoaded(font: TLFontFace): Promise<void> {\n\t\tconst existingState = this.getFontState(font)\n\t\tif (existingState) return existingState.loadingPromise\n\n\t\tconst instance = this.findOrCreateFontFace(font)\n\t\tconst state: FontState = {\n\t\t\tstate: 'loading',\n\t\t\tinstance,\n\t\t\tloadingPromise: instance\n\t\t\t\t.load()\n\t\t\t\t.then(() => {\n\t\t\t\t\tdocument.fonts.add(instance)\n\t\t\t\t\tthis.fontStates.update(font, (s) => ({ ...s, state: 'ready' }))\n\t\t\t\t})\n\t\t\t\t.catch((err) => {\n\t\t\t\t\tconsole.error(err)\n\t\t\t\t\tthis.fontStates.update(font, (s) => ({ ...s, state: 'error' }))\n\t\t\t\t}),\n\t\t}\n\n\t\tthis.fontStates.set(font, state)\n\t\treturn state.loadingPromise\n\t}\n\n\tprivate fontsToLoad = new Set<TLFontFace>()\n\trequestFonts(fonts: TLFontFace[]) {\n\t\tif (!this.fontsToLoad.size) {\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tif (this.editor.isDisposed) return\n\t\t\t\tconst toLoad = this.fontsToLoad\n\t\t\t\tthis.fontsToLoad = new Set()\n\t\t\t\ttransact(() => {\n\t\t\t\t\tfor (const font of toLoad) {\n\t\t\t\t\t\tthis.ensureFontIsLoaded(font)\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t}\n\t\tfor (const font of fonts) {\n\t\t\tthis.fontsToLoad.add(font)\n\t\t}\n\t}\n\n\tprivate findOrCreateFontFace(font: TLFontFace) {\n\t\tfor (const existing of document.fonts) {\n\t\t\tif (\n\t\t\t\texisting.family === font.family &&\n\t\t\t\tobjectMapEntries(defaultFontFaceDescriptors).every(\n\t\t\t\t\t([key, defaultValue]) => existing[key] === (font[key] ?? defaultValue)\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn existing\n\t\t\t}\n\t\t}\n\n\t\tconst url = this.assetUrls?.[font.src.url] ?? font.src.url\n\t\tconst instance = new FontFace(font.family, `url(${JSON.stringify(url)})`, {\n\t\t\t...mapObjectMapValues(defaultFontFaceDescriptors, (key) => font[key]),\n\t\t\tdisplay: 'swap',\n\t\t})\n\n\t\tdocument.fonts.add(instance)\n\n\t\treturn instance\n\t}\n\n\tasync toEmbeddedCssDeclaration(font: TLFontFace) {\n\t\tconst url = this.assetUrls?.[font.src.url] ?? font.src.url\n\t\tconst dataUrl = await FileHelpers.urlToDataUrl(url)\n\n\t\tconst src = compact([\n\t\t\t`url(\"${dataUrl}\")`,\n\t\t\tfont.src.format ? `format(${font.src.format})` : null,\n\t\t\tfont.src.tech ? `tech(${font.src.tech})` : null,\n\t\t]).join(' ')\n\t\treturn compact([\n\t\t\t`@font-face {`,\n\t\t\t` font-family: \"${font.family}\";`,\n\t\t\tfont.ascentOverride ? ` ascent-override: ${font.ascentOverride};` : null,\n\t\t\tfont.descentOverride ? ` descent-override: ${font.descentOverride};` : null,\n\t\t\tfont.stretch ? ` font-stretch: ${font.stretch};` : null,\n\t\t\tfont.style ? ` font-style: ${font.style};` : null,\n\t\t\tfont.weight ? ` font-weight: ${font.weight};` : null,\n\t\t\tfont.featureSettings ? ` font-feature-settings: ${font.featureSettings};` : null,\n\t\t\tfont.lineGapOverride ? ` line-gap-override: ${font.lineGapOverride};` : null,\n\t\t\tfont.unicodeRange ? ` unicode-range: ${font.unicodeRange};` : null,\n\t\t\t` src: ${src};`,\n\t\t\t`}`,\n\t\t]).join('\\n')\n\t}\n}\n\n// From https://drafts.csswg.org/css-font-loading/#fontface-interface\nconst defaultFontFaceDescriptors = {\n\tstyle: 'normal',\n\tweight: 'normal',\n\tstretch: 'normal',\n\tunicodeRange: 'U+0-10FFFF',\n\tfeatureSettings: 'normal',\n\tascentOverride: 'normal',\n\tdescentOverride: 'normal',\n\tlineGapOverride: 'normal',\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -18,13 +18,14 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var HistoryManager_exports = {};
20
20
  __export(HistoryManager_exports, {
21
- HistoryManager: () => HistoryManager
21
+ HistoryManager: () => HistoryManager,
22
+ stack: () => stack
22
23
  });
23
24
  module.exports = __toCommonJS(HistoryManager_exports);
24
25
  var import_state = require("@tldraw/state");
25
26
  var import_store = require("@tldraw/store");
26
27
  var import_utils = require("@tldraw/utils");
27
- var import_Stack = require("./Stack");
28
+ var import_state2 = require("@tldraw/state");
28
29
  var HistoryRecorderState = /* @__PURE__ */ ((HistoryRecorderState2) => {
29
30
  HistoryRecorderState2["Recording"] = "recording";
30
31
  HistoryRecorderState2["RecordingPreserveRedoStack"] = "recordingPreserveRedoStack";
@@ -39,8 +40,8 @@ class HistoryManager {
39
40
  stacks = (0, import_state.atom)(
40
41
  "HistoryManager.stacks",
41
42
  {
42
- undos: (0, import_Stack.stack)(),
43
- redos: (0, import_Stack.stack)()
43
+ undos: stack(),
44
+ redos: stack()
44
45
  },
45
46
  {
46
47
  isEqual: (a, b) => a.undos === b.undos && a.redos === b.redos
@@ -55,7 +56,7 @@ class HistoryManager {
55
56
  switch (this.state) {
56
57
  case "recording" /* Recording */:
57
58
  this.pendingDiff.apply(entry.changes);
58
- this.stacks.update(({ undos }) => ({ undos, redos: (0, import_Stack.stack)() }));
59
+ this.stacks.update(({ undos }) => ({ undos, redos: stack() }));
59
60
  break;
60
61
  case "recordingPreserveRedoStack" /* RecordingPreserveRedoStack */:
61
62
  this.pendingDiff.apply(entry.changes);
@@ -246,7 +247,7 @@ class HistoryManager {
246
247
  });
247
248
  }
248
249
  clear() {
249
- this.stacks.set({ undos: (0, import_Stack.stack)(), redos: (0, import_Stack.stack)() });
250
+ this.stacks.set({ undos: stack(), redos: stack() });
250
251
  this.pendingDiff.clear();
251
252
  }
252
253
  /** @internal */
@@ -296,4 +297,61 @@ class PendingDiff {
296
297
  return { diff: this.diff, isEmpty: this.isEmpty() };
297
298
  }
298
299
  }
300
+ function stack(items) {
301
+ if (items) {
302
+ let result = EMPTY_STACK_ITEM;
303
+ while (items.length) {
304
+ result = result.push(items.pop());
305
+ }
306
+ return result;
307
+ }
308
+ return EMPTY_STACK_ITEM;
309
+ }
310
+ class EmptyStackItem {
311
+ length = 0;
312
+ head = null;
313
+ tail = this;
314
+ push(head) {
315
+ return new StackItem(head, this);
316
+ }
317
+ toArray() {
318
+ return import_state2.EMPTY_ARRAY;
319
+ }
320
+ [Symbol.iterator]() {
321
+ return {
322
+ next() {
323
+ return { value: void 0, done: true };
324
+ }
325
+ };
326
+ }
327
+ }
328
+ const EMPTY_STACK_ITEM = new EmptyStackItem();
329
+ class StackItem {
330
+ constructor(head, tail) {
331
+ this.head = head;
332
+ this.tail = tail;
333
+ this.length = tail.length + 1;
334
+ }
335
+ length;
336
+ push(head) {
337
+ return new StackItem(head, this);
338
+ }
339
+ toArray() {
340
+ return Array.from(this);
341
+ }
342
+ [Symbol.iterator]() {
343
+ let stack2 = this;
344
+ return {
345
+ next() {
346
+ if (stack2.length) {
347
+ const value = stack2.head;
348
+ stack2 = stack2.tail;
349
+ return { value, done: false };
350
+ } else {
351
+ return { value: void 0, done: true };
352
+ }
353
+ }
354
+ };
355
+ }
356
+ }
299
357
  //# sourceMappingURL=HistoryManager.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/lib/editor/managers/HistoryManager/HistoryManager.ts"],
4
+ "sourcesContent": ["import { atom, transact } from '@tldraw/state'\nimport {\n\tRecordsDiff,\n\tStore,\n\tUnknownRecord,\n\tcreateEmptyRecordsDiff,\n\tisRecordsDiffEmpty,\n\treverseRecordsDiff,\n\tsquashRecordDiffsMutable,\n} from '@tldraw/store'\nimport { exhaustiveSwitchError, noop } from '@tldraw/utils'\nimport { TLHistoryBatchOptions, TLHistoryEntry } from '../../types/history-types'\n\nenum HistoryRecorderState {\n\tRecording = 'recording',\n\tRecordingPreserveRedoStack = 'recordingPreserveRedoStack',\n\tPaused = 'paused',\n}\n\n/** @public */\nexport class HistoryManager<R extends UnknownRecord> {\n\tprivate readonly store: Store<R>\n\n\treadonly dispose: () => void\n\n\tprivate state: HistoryRecorderState = HistoryRecorderState.Recording\n\tprivate readonly pendingDiff = new PendingDiff<R>()\n\tprivate stacks = atom(\n\t\t'HistoryManager.stacks',\n\t\t{\n\t\t\tundos: stack<TLHistoryEntry<R>>(),\n\t\t\tredos: stack<TLHistoryEntry<R>>(),\n\t\t},\n\t\t{\n\t\t\tisEqual: (a, b) => a.undos === b.undos && a.redos === b.redos,\n\t\t}\n\t)\n\n\tprivate readonly annotateError: (error: unknown) => void\n\n\tconstructor(opts: { store: Store<R>; annotateError?(error: unknown): void }) {\n\t\tthis.store = opts.store\n\t\tthis.annotateError = opts.annotateError ?? noop\n\t\tthis.dispose = this.store.addHistoryInterceptor((entry, source) => {\n\t\t\tif (source !== 'user') return\n\n\t\t\tswitch (this.state) {\n\t\t\t\tcase HistoryRecorderState.Recording:\n\t\t\t\t\tthis.pendingDiff.apply(entry.changes)\n\t\t\t\t\tthis.stacks.update(({ undos }) => ({ undos, redos: stack() }))\n\t\t\t\t\tbreak\n\t\t\t\tcase HistoryRecorderState.RecordingPreserveRedoStack:\n\t\t\t\t\tthis.pendingDiff.apply(entry.changes)\n\t\t\t\t\tbreak\n\t\t\t\tcase HistoryRecorderState.Paused:\n\t\t\t\t\tbreak\n\t\t\t\tdefault:\n\t\t\t\t\texhaustiveSwitchError(this.state)\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate flushPendingDiff() {\n\t\tif (this.pendingDiff.isEmpty()) return\n\n\t\tconst diff = this.pendingDiff.clear()\n\t\tthis.stacks.update(({ undos, redos }) => ({\n\t\t\tundos: undos.push({ type: 'diff', diff }),\n\t\t\tredos,\n\t\t}))\n\t}\n\n\tgetNumUndos() {\n\t\treturn this.stacks.get().undos.length + (this.pendingDiff.isEmpty() ? 0 : 1)\n\t}\n\n\tgetNumRedos() {\n\t\treturn this.stacks.get().redos.length\n\t}\n\n\t/** @internal */\n\t_isInBatch = false\n\n\tbatch(fn: () => void, opts?: TLHistoryBatchOptions) {\n\t\tconst previousState = this.state\n\n\t\t// we move to the new state only if we haven't explicitly paused\n\t\tif (previousState !== HistoryRecorderState.Paused && opts?.history) {\n\t\t\tthis.state = modeToState[opts.history]\n\t\t}\n\n\t\ttry {\n\t\t\tif (this._isInBatch) {\n\t\t\t\ttransact(fn)\n\t\t\t\treturn this\n\t\t\t}\n\n\t\t\tthis._isInBatch = true\n\t\t\ttry {\n\t\t\t\ttransact(fn)\n\t\t\t} catch (error) {\n\t\t\t\tthis.annotateError(error)\n\t\t\t\tthrow error\n\t\t\t} finally {\n\t\t\t\tthis._isInBatch = false\n\t\t\t}\n\n\t\t\treturn this\n\t\t} finally {\n\t\t\tthis.state = previousState\n\t\t}\n\t}\n\n\t// History\n\t_undo({ pushToRedoStack, toMark = undefined }: { pushToRedoStack: boolean; toMark?: string }) {\n\t\tconst previousState = this.state\n\t\tthis.state = HistoryRecorderState.Paused\n\t\ttry {\n\t\t\tlet { undos, redos } = this.stacks.get()\n\n\t\t\t// start by collecting the pending diff (everything since the last mark).\n\t\t\t// we'll accumulate the diff to undo in this variable so we can apply it atomically.\n\t\t\tconst pendingDiff = this.pendingDiff.clear()\n\t\t\tconst isPendingDiffEmpty = isRecordsDiffEmpty(pendingDiff)\n\t\t\tconst diffToUndo = reverseRecordsDiff(pendingDiff)\n\n\t\t\tif (pushToRedoStack && !isPendingDiffEmpty) {\n\t\t\t\tredos = redos.push({ type: 'diff', diff: pendingDiff })\n\t\t\t}\n\n\t\t\tlet didFindMark = false\n\t\t\tif (isPendingDiffEmpty) {\n\t\t\t\t// if nothing has happened since the last mark, pop any intermediate marks off the stack\n\t\t\t\twhile (undos.head?.type === 'stop') {\n\t\t\t\t\tconst mark = undos.head\n\t\t\t\t\tundos = undos.tail\n\t\t\t\t\tif (pushToRedoStack) {\n\t\t\t\t\t\tredos = redos.push(mark)\n\t\t\t\t\t}\n\t\t\t\t\tif (mark.id === toMark) {\n\t\t\t\t\t\tdidFindMark = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!didFindMark) {\n\t\t\t\tloop: while (undos.head) {\n\t\t\t\t\tconst undo = undos.head\n\t\t\t\t\tundos = undos.tail\n\n\t\t\t\t\tif (pushToRedoStack) {\n\t\t\t\t\t\tredos = redos.push(undo)\n\t\t\t\t\t}\n\n\t\t\t\t\tswitch (undo.type) {\n\t\t\t\t\t\tcase 'diff':\n\t\t\t\t\t\t\tsquashRecordDiffsMutable(diffToUndo, [reverseRecordsDiff(undo.diff)])\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tcase 'stop':\n\t\t\t\t\t\t\tif (!toMark) break loop\n\t\t\t\t\t\t\tif (undo.id === toMark) {\n\t\t\t\t\t\t\t\tdidFindMark = true\n\t\t\t\t\t\t\t\tbreak loop\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\texhaustiveSwitchError(undo)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!didFindMark && toMark) {\n\t\t\t\t// whoops, we didn't find the mark we were looking for\n\t\t\t\t// don't do anything\n\t\t\t\treturn this\n\t\t\t}\n\n\t\t\tthis.store.applyDiff(diffToUndo, { ignoreEphemeralKeys: true })\n\t\t\tthis.store.ensureStoreIsUsable()\n\t\t\tthis.stacks.set({ undos, redos })\n\t\t} finally {\n\t\t\tthis.state = previousState\n\t\t}\n\n\t\treturn this\n\t}\n\n\tundo() {\n\t\tthis._undo({ pushToRedoStack: true })\n\n\t\treturn this\n\t}\n\n\tredo() {\n\t\tconst previousState = this.state\n\t\tthis.state = HistoryRecorderState.Paused\n\t\ttry {\n\t\t\tthis.flushPendingDiff()\n\n\t\t\tlet { undos, redos } = this.stacks.get()\n\t\t\tif (redos.length === 0) {\n\t\t\t\treturn this\n\t\t\t}\n\n\t\t\t// ignore any intermediate marks - this should take us to the first `diff` entry\n\t\t\twhile (redos.head?.type === 'stop') {\n\t\t\t\tundos = undos.push(redos.head)\n\t\t\t\tredos = redos.tail\n\t\t\t}\n\n\t\t\t// accumulate diffs to be redone so they can be applied atomically\n\t\t\tconst diffToRedo = createEmptyRecordsDiff<R>()\n\n\t\t\twhile (redos.head) {\n\t\t\t\tconst redo = redos.head\n\t\t\t\tundos = undos.push(redo)\n\t\t\t\tredos = redos.tail\n\n\t\t\t\tif (redo.type === 'diff') {\n\t\t\t\t\tsquashRecordDiffsMutable(diffToRedo, [redo.diff])\n\t\t\t\t} else {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.store.applyDiff(diffToRedo, { ignoreEphemeralKeys: true })\n\t\t\tthis.store.ensureStoreIsUsable()\n\t\t\tthis.stacks.set({ undos, redos })\n\t\t} finally {\n\t\t\tthis.state = previousState\n\t\t}\n\n\t\treturn this\n\t}\n\n\tbail() {\n\t\tthis._undo({ pushToRedoStack: false })\n\n\t\treturn this\n\t}\n\n\tbailToMark(id: string) {\n\t\tthis._undo({ pushToRedoStack: false, toMark: id })\n\n\t\treturn this\n\t}\n\n\tsquashToMark(id: string) {\n\t\t// remove marks between head and the mark\n\n\t\tlet top = this.stacks.get().undos\n\t\tconst popped: Array<RecordsDiff<R>> = []\n\n\t\twhile (top.head && !(top.head.type === 'stop' && top.head.id === id)) {\n\t\t\tif (top.head.type === 'diff') {\n\t\t\t\tpopped.push(top.head.diff)\n\t\t\t}\n\t\t\ttop = top.tail\n\t\t}\n\n\t\tif (!top.head || top.head?.id !== id) {\n\t\t\tconsole.error('Could not find mark to squash to: ', id)\n\t\t\treturn this\n\t\t}\n\t\tif (popped.length === 0) {\n\t\t\treturn this\n\t\t}\n\n\t\tconst diff = createEmptyRecordsDiff<R>()\n\t\tsquashRecordDiffsMutable(diff, popped.reverse())\n\n\t\tthis.stacks.update(({ redos }) => ({\n\t\t\tundos: top.push({\n\t\t\t\ttype: 'diff',\n\t\t\t\tdiff,\n\t\t\t}),\n\t\t\tredos,\n\t\t}))\n\n\t\treturn this\n\t}\n\n\t/** @internal */\n\t_mark(id: string) {\n\t\ttransact(() => {\n\t\t\tthis.flushPendingDiff()\n\t\t\tthis.stacks.update(({ undos, redos }) => ({ undos: undos.push({ type: 'stop', id }), redos }))\n\t\t})\n\t}\n\n\tclear() {\n\t\tthis.stacks.set({ undos: stack(), redos: stack() })\n\t\tthis.pendingDiff.clear()\n\t}\n\n\t/** @internal */\n\tgetMarkIdMatching(idSubstring: string) {\n\t\tlet top = this.stacks.get().undos\n\t\twhile (top.head) {\n\t\t\tif (top.head.type === 'stop' && top.head.id.includes(idSubstring)) {\n\t\t\t\treturn top.head.id\n\t\t\t}\n\t\t\ttop = top.tail\n\t\t}\n\t\treturn null\n\t}\n\n\t/** @internal */\n\tdebug() {\n\t\tconst { undos, redos } = this.stacks.get()\n\t\treturn {\n\t\t\tundos: undos.toArray(),\n\t\t\tredos: redos.toArray(),\n\t\t\tpendingDiff: this.pendingDiff.debug(),\n\t\t\tstate: this.state as string,\n\t\t}\n\t}\n}\n\nconst modeToState = {\n\trecord: HistoryRecorderState.Recording,\n\t'record-preserveRedoStack': HistoryRecorderState.RecordingPreserveRedoStack,\n\tignore: HistoryRecorderState.Paused,\n} as const\n\nclass PendingDiff<R extends UnknownRecord> {\n\tprivate diff = createEmptyRecordsDiff<R>()\n\tprivate isEmptyAtom = atom('PendingDiff.isEmpty', true)\n\n\tclear() {\n\t\tconst diff = this.diff\n\t\tthis.diff = createEmptyRecordsDiff<R>()\n\t\tthis.isEmptyAtom.set(true)\n\t\treturn diff\n\t}\n\n\tisEmpty() {\n\t\treturn this.isEmptyAtom.get()\n\t}\n\n\tapply(diff: RecordsDiff<R>) {\n\t\tsquashRecordDiffsMutable(this.diff, [diff])\n\t\tthis.isEmptyAtom.set(isRecordsDiffEmpty(this.diff))\n\t}\n\n\tdebug() {\n\t\treturn { diff: this.diff, isEmpty: this.isEmpty() }\n\t}\n}\n\nimport { EMPTY_ARRAY } from '@tldraw/state'\n\nexport type Stack<T> = StackItem<T> | EmptyStackItem<T>\n\nexport function stack<T>(items?: Array<T>): Stack<T> {\n\tif (items) {\n\t\tlet result = EMPTY_STACK_ITEM as Stack<T>\n\t\twhile (items.length) {\n\t\t\tresult = result.push(items.pop()!)\n\t\t}\n\t\treturn result\n\t}\n\treturn EMPTY_STACK_ITEM as any\n}\n\nclass EmptyStackItem<T> implements Iterable<T> {\n\treadonly length = 0\n\treadonly head = null\n\treadonly tail: Stack<T> = this\n\n\tpush(head: T): Stack<T> {\n\t\treturn new StackItem<T>(head, this)\n\t}\n\n\ttoArray() {\n\t\treturn EMPTY_ARRAY\n\t}\n\n\t[Symbol.iterator]() {\n\t\treturn {\n\t\t\tnext() {\n\t\t\t\treturn { value: undefined, done: true as const }\n\t\t\t},\n\t\t}\n\t}\n}\n\nconst EMPTY_STACK_ITEM = new EmptyStackItem()\n\nclass StackItem<T> implements Iterable<T> {\n\tlength: number\n\tconstructor(\n\t\tpublic readonly head: T,\n\t\tpublic readonly tail: Stack<T>\n\t) {\n\t\tthis.length = tail.length + 1\n\t}\n\n\tpush(head: T): Stack<T> {\n\t\treturn new StackItem(head, this)\n\t}\n\n\ttoArray() {\n\t\treturn Array.from(this)\n\t}\n\n\t[Symbol.iterator]() {\n\t\tlet stack = this as Stack<T>\n\t\treturn {\n\t\t\tnext() {\n\t\t\t\tif (stack.length) {\n\t\t\t\t\tconst value = stack.head!\n\t\t\t\t\tstack = stack.tail\n\t\t\t\t\treturn { value, done: false as const }\n\t\t\t\t} else {\n\t\t\t\t\treturn { value: undefined, done: true as const }\n\t\t\t\t}\n\t\t\t},\n\t\t}\n\t}\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA+B;AAC/B,mBAQO;AACP,mBAA4C;AAqV5C,IAAAA,gBAA4B;AAlV5B,IAAK,uBAAL,kBAAKC,0BAAL;AACC,EAAAA,sBAAA,eAAY;AACZ,EAAAA,sBAAA,gCAA6B;AAC7B,EAAAA,sBAAA,YAAS;AAHL,SAAAA;AAAA,GAAA;AAOE,MAAM,eAAwC;AAAA,EACnC;AAAA,EAER;AAAA,EAED,QAA8B;AAAA,EACrB,cAAc,IAAI,YAAe;AAAA,EAC1C,aAAS;AAAA,IAChB;AAAA,IACA;AAAA,MACC,OAAO,MAAyB;AAAA,MAChC,OAAO,MAAyB;AAAA,IACjC;AAAA,IACA;AAAA,MACC,SAAS,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE;AAAA,IACzD;AAAA,EACD;AAAA,EAEiB;AAAA,EAEjB,YAAY,MAAiE;AAC5E,SAAK,QAAQ,KAAK;AAClB,SAAK,gBAAgB,KAAK,iBAAiB;AAC3C,SAAK,UAAU,KAAK,MAAM,sBAAsB,CAAC,OAAO,WAAW;AAClE,UAAI,WAAW,OAAQ;AAEvB,cAAQ,KAAK,OAAO;AAAA,QACnB,KAAK;AACJ,eAAK,YAAY,MAAM,MAAM,OAAO;AACpC,eAAK,OAAO,OAAO,CAAC,EAAE,MAAM,OAAO,EAAE,OAAO,OAAO,MAAM,EAAE,EAAE;AAC7D;AAAA,QACD,KAAK;AACJ,eAAK,YAAY,MAAM,MAAM,OAAO;AACpC;AAAA,QACD,KAAK;AACJ;AAAA,QACD;AACC,kDAAsB,KAAK,KAAK;AAAA,MAClC;AAAA,IACD,CAAC;AAAA,EACF;AAAA,EAEQ,mBAAmB;AAC1B,QAAI,KAAK,YAAY,QAAQ,EAAG;AAEhC,UAAM,OAAO,KAAK,YAAY,MAAM;AACpC,SAAK,OAAO,OAAO,CAAC,EAAE,OAAO,MAAM,OAAO;AAAA,MACzC,OAAO,MAAM,KAAK,EAAE,MAAM,QAAQ,KAAK,CAAC;AAAA,MACxC;AAAA,IACD,EAAE;AAAA,EACH;AAAA,EAEA,cAAc;AACb,WAAO,KAAK,OAAO,IAAI,EAAE,MAAM,UAAU,KAAK,YAAY,QAAQ,IAAI,IAAI;AAAA,EAC3E;AAAA,EAEA,cAAc;AACb,WAAO,KAAK,OAAO,IAAI,EAAE,MAAM;AAAA,EAChC;AAAA;AAAA,EAGA,aAAa;AAAA,EAEb,MAAM,IAAgB,MAA8B;AACnD,UAAM,gBAAgB,KAAK;AAG3B,QAAI,kBAAkB,yBAA+B,MAAM,SAAS;AACnE,WAAK,QAAQ,YAAY,KAAK,OAAO;AAAA,IACtC;AAEA,QAAI;AACH,UAAI,KAAK,YAAY;AACpB,mCAAS,EAAE;AACX,eAAO;AAAA,MACR;AAEA,WAAK,aAAa;AAClB,UAAI;AACH,mCAAS,EAAE;AAAA,MACZ,SAAS,OAAO;AACf,aAAK,cAAc,KAAK;AACxB,cAAM;AAAA,MACP,UAAE;AACD,aAAK,aAAa;AAAA,MACnB;AAEA,aAAO;AAAA,IACR,UAAE;AACD,WAAK,QAAQ;AAAA,IACd;AAAA,EACD;AAAA;AAAA,EAGA,MAAM,EAAE,iBAAiB,SAAS,OAAU,GAAkD;AAC7F,UAAM,gBAAgB,KAAK;AAC3B,SAAK,QAAQ;AACb,QAAI;AACH,UAAI,EAAE,OAAO,MAAM,IAAI,KAAK,OAAO,IAAI;AAIvC,YAAM,cAAc,KAAK,YAAY,MAAM;AAC3C,YAAM,yBAAqB,iCAAmB,WAAW;AACzD,YAAM,iBAAa,iCAAmB,WAAW;AAEjD,UAAI,mBAAmB,CAAC,oBAAoB;AAC3C,gBAAQ,MAAM,KAAK,EAAE,MAAM,QAAQ,MAAM,YAAY,CAAC;AAAA,MACvD;AAEA,UAAI,cAAc;AAClB,UAAI,oBAAoB;AAEvB,eAAO,MAAM,MAAM,SAAS,QAAQ;AACnC,gBAAM,OAAO,MAAM;AACnB,kBAAQ,MAAM;AACd,cAAI,iBAAiB;AACpB,oBAAQ,MAAM,KAAK,IAAI;AAAA,UACxB;AACA,cAAI,KAAK,OAAO,QAAQ;AACvB,0BAAc;AACd;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAEA,UAAI,CAAC,aAAa;AACjB,aAAM,QAAO,MAAM,MAAM;AACxB,gBAAM,OAAO,MAAM;AACnB,kBAAQ,MAAM;AAEd,cAAI,iBAAiB;AACpB,oBAAQ,MAAM,KAAK,IAAI;AAAA,UACxB;AAEA,kBAAQ,KAAK,MAAM;AAAA,YAClB,KAAK;AACJ,yDAAyB,YAAY,KAAC,iCAAmB,KAAK,IAAI,CAAC,CAAC;AACpE;AAAA,YACD,KAAK;AACJ,kBAAI,CAAC,OAAQ,OAAM;AACnB,kBAAI,KAAK,OAAO,QAAQ;AACvB,8BAAc;AACd,sBAAM;AAAA,cACP;AACA;AAAA,YACD;AACC,sDAAsB,IAAI;AAAA,UAC5B;AAAA,QACD;AAAA,MACD;AAEA,UAAI,CAAC,eAAe,QAAQ;AAG3B,eAAO;AAAA,MACR;AAEA,WAAK,MAAM,UAAU,YAAY,EAAE,qBAAqB,KAAK,CAAC;AAC9D,WAAK,MAAM,oBAAoB;AAC/B,WAAK,OAAO,IAAI,EAAE,OAAO,MAAM,CAAC;AAAA,IACjC,UAAE;AACD,WAAK,QAAQ;AAAA,IACd;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,OAAO;AACN,SAAK,MAAM,EAAE,iBAAiB,KAAK,CAAC;AAEpC,WAAO;AAAA,EACR;AAAA,EAEA,OAAO;AACN,UAAM,gBAAgB,KAAK;AAC3B,SAAK,QAAQ;AACb,QAAI;AACH,WAAK,iBAAiB;AAEtB,UAAI,EAAE,OAAO,MAAM,IAAI,KAAK,OAAO,IAAI;AACvC,UAAI,MAAM,WAAW,GAAG;AACvB,eAAO;AAAA,MACR;AAGA,aAAO,MAAM,MAAM,SAAS,QAAQ;AACnC,gBAAQ,MAAM,KAAK,MAAM,IAAI;AAC7B,gBAAQ,MAAM;AAAA,MACf;AAGA,YAAM,iBAAa,qCAA0B;AAE7C,aAAO,MAAM,MAAM;AAClB,cAAM,OAAO,MAAM;AACnB,gBAAQ,MAAM,KAAK,IAAI;AACvB,gBAAQ,MAAM;AAEd,YAAI,KAAK,SAAS,QAAQ;AACzB,qDAAyB,YAAY,CAAC,KAAK,IAAI,CAAC;AAAA,QACjD,OAAO;AACN;AAAA,QACD;AAAA,MACD;AAEA,WAAK,MAAM,UAAU,YAAY,EAAE,qBAAqB,KAAK,CAAC;AAC9D,WAAK,MAAM,oBAAoB;AAC/B,WAAK,OAAO,IAAI,EAAE,OAAO,MAAM,CAAC;AAAA,IACjC,UAAE;AACD,WAAK,QAAQ;AAAA,IACd;AAEA,WAAO;AAAA,EACR;AAAA,EAEA,OAAO;AACN,SAAK,MAAM,EAAE,iBAAiB,MAAM,CAAC;AAErC,WAAO;AAAA,EACR;AAAA,EAEA,WAAW,IAAY;AACtB,SAAK,MAAM,EAAE,iBAAiB,OAAO,QAAQ,GAAG,CAAC;AAEjD,WAAO;AAAA,EACR;AAAA,EAEA,aAAa,IAAY;AAGxB,QAAI,MAAM,KAAK,OAAO,IAAI,EAAE;AAC5B,UAAM,SAAgC,CAAC;AAEvC,WAAO,IAAI,QAAQ,EAAE,IAAI,KAAK,SAAS,UAAU,IAAI,KAAK,OAAO,KAAK;AACrE,UAAI,IAAI,KAAK,SAAS,QAAQ;AAC7B,eAAO,KAAK,IAAI,KAAK,IAAI;AAAA,MAC1B;AACA,YAAM,IAAI;AAAA,IACX;AAEA,QAAI,CAAC,IAAI,QAAQ,IAAI,MAAM,OAAO,IAAI;AACrC,cAAQ,MAAM,sCAAsC,EAAE;AACtD,aAAO;AAAA,IACR;AACA,QAAI,OAAO,WAAW,GAAG;AACxB,aAAO;AAAA,IACR;AAEA,UAAM,WAAO,qCAA0B;AACvC,+CAAyB,MAAM,OAAO,QAAQ,CAAC;AAE/C,SAAK,OAAO,OAAO,CAAC,EAAE,MAAM,OAAO;AAAA,MAClC,OAAO,IAAI,KAAK;AAAA,QACf,MAAM;AAAA,QACN;AAAA,MACD,CAAC;AAAA,MACD;AAAA,IACD,EAAE;AAEF,WAAO;AAAA,EACR;AAAA;AAAA,EAGA,MAAM,IAAY;AACjB,+BAAS,MAAM;AACd,WAAK,iBAAiB;AACtB,WAAK,OAAO,OAAO,CAAC,EAAE,OAAO,MAAM,OAAO,EAAE,OAAO,MAAM,KAAK,EAAE,MAAM,QAAQ,GAAG,CAAC,GAAG,MAAM,EAAE;AAAA,IAC9F,CAAC;AAAA,EACF;AAAA,EAEA,QAAQ;AACP,SAAK,OAAO,IAAI,EAAE,OAAO,MAAM,GAAG,OAAO,MAAM,EAAE,CAAC;AAClD,SAAK,YAAY,MAAM;AAAA,EACxB;AAAA;AAAA,EAGA,kBAAkB,aAAqB;AACtC,QAAI,MAAM,KAAK,OAAO,IAAI,EAAE;AAC5B,WAAO,IAAI,MAAM;AAChB,UAAI,IAAI,KAAK,SAAS,UAAU,IAAI,KAAK,GAAG,SAAS,WAAW,GAAG;AAClE,eAAO,IAAI,KAAK;AAAA,MACjB;AACA,YAAM,IAAI;AAAA,IACX;AACA,WAAO;AAAA,EACR;AAAA;AAAA,EAGA,QAAQ;AACP,UAAM,EAAE,OAAO,MAAM,IAAI,KAAK,OAAO,IAAI;AACzC,WAAO;AAAA,MACN,OAAO,MAAM,QAAQ;AAAA,MACrB,OAAO,MAAM,QAAQ;AAAA,MACrB,aAAa,KAAK,YAAY,MAAM;AAAA,MACpC,OAAO,KAAK;AAAA,IACb;AAAA,EACD;AACD;AAEA,MAAM,cAAc;AAAA,EACnB,QAAQ;AAAA,EACR,4BAA4B;AAAA,EAC5B,QAAQ;AACT;AAEA,MAAM,YAAqC;AAAA,EAClC,WAAO,qCAA0B;AAAA,EACjC,kBAAc,mBAAK,uBAAuB,IAAI;AAAA,EAEtD,QAAQ;AACP,UAAM,OAAO,KAAK;AAClB,SAAK,WAAO,qCAA0B;AACtC,SAAK,YAAY,IAAI,IAAI;AACzB,WAAO;AAAA,EACR;AAAA,EAEA,UAAU;AACT,WAAO,KAAK,YAAY,IAAI;AAAA,EAC7B;AAAA,EAEA,MAAM,MAAsB;AAC3B,+CAAyB,KAAK,MAAM,CAAC,IAAI,CAAC;AAC1C,SAAK,YAAY,QAAI,iCAAmB,KAAK,IAAI,CAAC;AAAA,EACnD;AAAA,EAEA,QAAQ;AACP,WAAO,EAAE,MAAM,KAAK,MAAM,SAAS,KAAK,QAAQ,EAAE;AAAA,EACnD;AACD;AAMO,SAAS,MAAS,OAA4B;AACpD,MAAI,OAAO;AACV,QAAI,SAAS;AACb,WAAO,MAAM,QAAQ;AACpB,eAAS,OAAO,KAAK,MAAM,IAAI,CAAE;AAAA,IAClC;AACA,WAAO;AAAA,EACR;AACA,SAAO;AACR;AAEA,MAAM,eAAyC;AAAA,EACrC,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAiB;AAAA,EAE1B,KAAK,MAAmB;AACvB,WAAO,IAAI,UAAa,MAAM,IAAI;AAAA,EACnC;AAAA,EAEA,UAAU;AACT,WAAO;AAAA,EACR;AAAA,EAEA,CAAC,OAAO,QAAQ,IAAI;AACnB,WAAO;AAAA,MACN,OAAO;AACN,eAAO,EAAE,OAAO,QAAW,MAAM,KAAc;AAAA,MAChD;AAAA,IACD;AAAA,EACD;AACD;AAEA,MAAM,mBAAmB,IAAI,eAAe;AAE5C,MAAM,UAAoC;AAAA,EAEzC,YACiB,MACA,MACf;AAFe;AACA;AAEhB,SAAK,SAAS,KAAK,SAAS;AAAA,EAC7B;AAAA,EANA;AAAA,EAQA,KAAK,MAAmB;AACvB,WAAO,IAAI,UAAU,MAAM,IAAI;AAAA,EAChC;AAAA,EAEA,UAAU;AACT,WAAO,MAAM,KAAK,IAAI;AAAA,EACvB;AAAA,EAEA,CAAC,OAAO,QAAQ,IAAI;AACnB,QAAIC,SAAQ;AACZ,WAAO;AAAA,MACN,OAAO;AACN,YAAIA,OAAM,QAAQ;AACjB,gBAAM,QAAQA,OAAM;AACpB,UAAAA,SAAQA,OAAM;AACd,iBAAO,EAAE,OAAO,MAAM,MAAe;AAAA,QACtC,OAAO;AACN,iBAAO,EAAE,OAAO,QAAW,MAAM,KAAc;AAAA,QAChD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;",
6
+ "names": ["import_state", "HistoryRecorderState", "stack"]
7
+ }
@@ -22,7 +22,7 @@ __export(ScribbleManager_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(ScribbleManager_exports);
24
24
  var import_utils = require("@tldraw/utils");
25
- var import_Vec = require("../../primitives/Vec");
25
+ var import_Vec = require("../../../primitives/Vec");
26
26
  class ScribbleManager {
27
27
  constructor(editor) {
28
28
  this.editor = editor;
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/lib/editor/managers/ScribbleManager/ScribbleManager.ts"],
4
+ "sourcesContent": ["import { TLScribble, VecModel } from '@tldraw/tlschema'\nimport { uniqueId } from '@tldraw/utils'\nimport { Vec } from '../../../primitives/Vec'\nimport { Editor } from '../../Editor'\n\n/** @public */\nexport interface ScribbleItem {\n\tid: string\n\tscribble: TLScribble\n\ttimeoutMs: number\n\tdelayRemaining: number\n\tprev: null | VecModel\n\tnext: null | VecModel\n}\n\n/** @public */\nexport class ScribbleManager {\n\tscribbleItems = new Map<string, ScribbleItem>()\n\tstate = 'paused' as 'paused' | 'running'\n\n\tconstructor(private editor: Editor) {}\n\n\taddScribble(scribble: Partial<TLScribble>, id = uniqueId()) {\n\t\tconst item: ScribbleItem = {\n\t\t\tid,\n\t\t\tscribble: {\n\t\t\t\tid,\n\t\t\t\tsize: 20,\n\t\t\t\tcolor: 'accent',\n\t\t\t\topacity: 0.8,\n\t\t\t\tdelay: 0,\n\t\t\t\tpoints: [],\n\t\t\t\tshrink: 0.1,\n\t\t\t\ttaper: true,\n\t\t\t\t...scribble,\n\t\t\t\tstate: 'starting',\n\t\t\t},\n\t\t\ttimeoutMs: 0,\n\t\t\tdelayRemaining: scribble.delay ?? 0,\n\t\t\tprev: null,\n\t\t\tnext: null,\n\t\t}\n\t\tthis.scribbleItems.set(id, item)\n\t\treturn item\n\t}\n\n\treset() {\n\t\tthis.editor.updateInstanceState({ scribbles: [] })\n\t\tthis.scribbleItems.clear()\n\t}\n\n\t/**\n\t * Start stopping the scribble. The scribble won't be removed until its last point is cleared.\n\t *\n\t * @public\n\t */\n\tstop(id: ScribbleItem['id']) {\n\t\tconst item = this.scribbleItems.get(id)\n\t\tif (!item) throw Error(`Scribble with id ${id} not found`)\n\t\titem.delayRemaining = Math.min(item.delayRemaining, 200)\n\t\titem.scribble.state = 'stopping'\n\t\treturn item\n\t}\n\n\t/**\n\t * Set the scribble's next point.\n\t *\n\t * @param id - The id of the scribble to add a point to.\n\t * @param x - The x coordinate of the point.\n\t * @param y - The y coordinate of the point.\n\t * @param z - The z coordinate of the point.\n\t * @public\n\t */\n\taddPoint(id: ScribbleItem['id'], x: number, y: number, z = 0.5) {\n\t\tconst item = this.scribbleItems.get(id)\n\t\tif (!item) throw Error(`Scribble with id ${id} not found`)\n\t\tconst { prev } = item\n\t\tconst point = { x, y, z }\n\t\tif (!prev || Vec.Dist(prev, point) >= 1) {\n\t\t\titem.next = point\n\t\t}\n\t\treturn item\n\t}\n\n\t/**\n\t * Update on each animation frame.\n\t *\n\t * @param elapsed - The number of milliseconds since the last tick.\n\t * @public\n\t */\n\ttick(elapsed: number) {\n\t\tif (this.scribbleItems.size === 0) return\n\t\tthis.editor.run(() => {\n\t\t\tthis.scribbleItems.forEach((item) => {\n\t\t\t\t// let the item get at least eight points before\n\t\t\t\t// switching from starting to active\n\t\t\t\tif (item.scribble.state === 'starting') {\n\t\t\t\t\tconst { next, prev } = item\n\t\t\t\t\tif (next && next !== prev) {\n\t\t\t\t\t\titem.prev = next\n\t\t\t\t\t\titem.scribble.points.push(next)\n\t\t\t\t\t}\n\n\t\t\t\t\tif (item.scribble.points.length > 8) {\n\t\t\t\t\t\titem.scribble.state = 'active'\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (item.delayRemaining > 0) {\n\t\t\t\t\titem.delayRemaining = Math.max(0, item.delayRemaining - elapsed)\n\t\t\t\t}\n\n\t\t\t\titem.timeoutMs += elapsed\n\t\t\t\tif (item.timeoutMs >= 16) {\n\t\t\t\t\titem.timeoutMs = 0\n\t\t\t\t}\n\n\t\t\t\tconst { delayRemaining, timeoutMs, prev, next, scribble } = item\n\n\t\t\t\tswitch (scribble.state) {\n\t\t\t\t\tcase 'active': {\n\t\t\t\t\t\tif (next && next !== prev) {\n\t\t\t\t\t\t\titem.prev = next\n\t\t\t\t\t\t\tscribble.points.push(next)\n\n\t\t\t\t\t\t\t// If we've run out of delay, then shrink the scribble from the start\n\t\t\t\t\t\t\tif (delayRemaining === 0) {\n\t\t\t\t\t\t\t\tif (scribble.points.length > 8) {\n\t\t\t\t\t\t\t\t\tscribble.points.shift()\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// While not moving, shrink the scribble from the start\n\t\t\t\t\t\t\tif (timeoutMs === 0) {\n\t\t\t\t\t\t\t\tif (scribble.points.length > 1) {\n\t\t\t\t\t\t\t\t\tscribble.points.shift()\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// Reset the item's delay\n\t\t\t\t\t\t\t\t\titem.delayRemaining = scribble.delay\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'stopping': {\n\t\t\t\t\t\tif (item.delayRemaining === 0) {\n\t\t\t\t\t\t\tif (timeoutMs === 0) {\n\t\t\t\t\t\t\t\t// If the scribble is down to one point, we're done!\n\t\t\t\t\t\t\t\tif (scribble.points.length === 1) {\n\t\t\t\t\t\t\t\t\tthis.scribbleItems.delete(item.id) // Remove the scribble\n\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (scribble.shrink) {\n\t\t\t\t\t\t\t\t\t// Drop the scribble's size as it shrinks\n\t\t\t\t\t\t\t\t\tscribble.size = Math.max(1, scribble.size * (1 - scribble.shrink))\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Drop the scribble's first point (its tail)\n\t\t\t\t\t\t\t\tscribble.points.shift()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'paused': {\n\t\t\t\t\t\t// Nothing to do while paused.\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\n\t\t\t// The object here will get frozen into the record, so we need to\n\t\t\t// create a copies of the parts that what we'll be mutating later.\n\t\t\tthis.editor.updateInstanceState({\n\t\t\t\tscribbles: Array.from(this.scribbleItems.values())\n\t\t\t\t\t.map(({ scribble }) => ({\n\t\t\t\t\t\t...scribble,\n\t\t\t\t\t\tpoints: [...scribble.points],\n\t\t\t\t\t}))\n\t\t\t\t\t.slice(-5), // limit to three as a minor sanity check\n\t\t\t})\n\t\t})\n\t}\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["next", "prev"]
7
+ }