@tldraw/editor 4.3.0-next.f4772c19540d → 4.4.0-canary.29afdff6bb04

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/README.md +1 -1
  2. package/dist-cjs/index.d.ts +503 -155
  3. package/dist-cjs/index.js +8 -1
  4. package/dist-cjs/index.js.map +2 -2
  5. package/dist-cjs/lib/components/ErrorBoundary.js.map +1 -1
  6. package/dist-cjs/lib/components/GeometryDebuggingView.js +1 -17
  7. package/dist-cjs/lib/components/GeometryDebuggingView.js.map +2 -2
  8. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +4 -5
  9. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  10. package/dist-cjs/lib/constants.js +1 -3
  11. package/dist-cjs/lib/constants.js.map +2 -2
  12. package/dist-cjs/lib/editor/Editor.js +346 -291
  13. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  14. package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +2 -2
  15. package/dist-cjs/lib/editor/derivations/bindingsIndex.js.map +2 -2
  16. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +16 -23
  17. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +3 -3
  18. package/dist-cjs/lib/editor/derivations/parentsToChildren.js +12 -3
  19. package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
  20. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +1 -1
  21. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
  22. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +5 -6
  23. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
  24. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +591 -0
  25. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +7 -0
  26. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +1 -1
  27. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
  28. package/dist-cjs/lib/editor/managers/SpatialIndexManager/RBushIndex.js +144 -0
  29. package/dist-cjs/lib/editor/managers/SpatialIndexManager/RBushIndex.js.map +7 -0
  30. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +181 -0
  31. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +7 -0
  32. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +1 -22
  33. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +2 -2
  34. package/dist-cjs/lib/editor/shapes/BaseBoxShapeUtil.js.map +1 -1
  35. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +31 -23
  36. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  37. package/dist-cjs/lib/editor/shapes/group/DashedOutlineBox.js +1 -1
  38. package/dist-cjs/lib/editor/shapes/group/DashedOutlineBox.js.map +2 -2
  39. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
  40. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.js.map +2 -2
  41. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +3 -3
  42. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
  43. package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
  44. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  45. package/dist-cjs/lib/exports/parseCss.js +1 -1
  46. package/dist-cjs/lib/exports/parseCss.js.map +2 -2
  47. package/dist-cjs/lib/globals/environment.js +45 -9
  48. package/dist-cjs/lib/globals/environment.js.map +2 -2
  49. package/dist-cjs/lib/globals/menus.js +1 -1
  50. package/dist-cjs/lib/globals/menus.js.map +2 -2
  51. package/dist-cjs/lib/hooks/useCoarsePointer.js +14 -29
  52. package/dist-cjs/lib/hooks/useCoarsePointer.js.map +2 -2
  53. package/dist-cjs/lib/hooks/useEvent.js +1 -1
  54. package/dist-cjs/lib/hooks/useEvent.js.map +2 -2
  55. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
  56. package/dist-cjs/lib/hooks/useGestureEvents.js +1 -1
  57. package/dist-cjs/lib/hooks/useGestureEvents.js.map +2 -2
  58. package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +2 -2
  59. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
  60. package/dist-cjs/lib/hooks/useScreenBounds.js.map +2 -2
  61. package/dist-cjs/lib/hooks/useStateAttribute.js +4 -1
  62. package/dist-cjs/lib/hooks/useStateAttribute.js.map +2 -2
  63. package/dist-cjs/lib/hooks/useTransform.js.map +1 -1
  64. package/dist-cjs/lib/hooks/useZoomCss.js +4 -8
  65. package/dist-cjs/lib/hooks/useZoomCss.js.map +2 -2
  66. package/dist-cjs/lib/options.js +6 -1
  67. package/dist-cjs/lib/options.js.map +2 -2
  68. package/dist-cjs/lib/primitives/Box.js +3 -0
  69. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  70. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +1 -0
  71. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  72. package/dist-cjs/lib/utils/reparenting.js.map +2 -2
  73. package/dist-cjs/lib/utils/rotation.js +1 -1
  74. package/dist-cjs/lib/utils/rotation.js.map +2 -2
  75. package/dist-cjs/version.js +3 -3
  76. package/dist-cjs/version.js.map +1 -1
  77. package/dist-esm/index.d.mts +503 -155
  78. package/dist-esm/index.mjs +9 -2
  79. package/dist-esm/index.mjs.map +2 -2
  80. package/dist-esm/lib/components/ErrorBoundary.mjs.map +1 -1
  81. package/dist-esm/lib/components/GeometryDebuggingView.mjs +1 -17
  82. package/dist-esm/lib/components/GeometryDebuggingView.mjs.map +2 -2
  83. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +4 -5
  84. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  85. package/dist-esm/lib/constants.mjs +1 -3
  86. package/dist-esm/lib/constants.mjs.map +2 -2
  87. package/dist-esm/lib/editor/Editor.mjs +347 -294
  88. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  89. package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +2 -2
  90. package/dist-esm/lib/editor/derivations/bindingsIndex.mjs.map +2 -2
  91. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +16 -23
  92. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +3 -3
  93. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +13 -4
  94. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
  95. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +1 -1
  96. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
  97. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +5 -6
  98. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
  99. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +573 -0
  100. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +7 -0
  101. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +1 -1
  102. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
  103. package/dist-esm/lib/editor/managers/SpatialIndexManager/RBushIndex.mjs +114 -0
  104. package/dist-esm/lib/editor/managers/SpatialIndexManager/RBushIndex.mjs.map +7 -0
  105. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +161 -0
  106. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +7 -0
  107. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +1 -22
  108. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +2 -2
  109. package/dist-esm/lib/editor/shapes/BaseBoxShapeUtil.mjs.map +1 -1
  110. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +31 -23
  111. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  112. package/dist-esm/lib/editor/shapes/group/DashedOutlineBox.mjs +1 -1
  113. package/dist-esm/lib/editor/shapes/group/DashedOutlineBox.mjs.map +2 -2
  114. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
  115. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.mjs.map +2 -2
  116. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +3 -3
  117. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
  118. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  119. package/dist-esm/lib/exports/parseCss.mjs +1 -1
  120. package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
  121. package/dist-esm/lib/globals/environment.mjs +45 -9
  122. package/dist-esm/lib/globals/environment.mjs.map +2 -2
  123. package/dist-esm/lib/globals/menus.mjs +1 -1
  124. package/dist-esm/lib/globals/menus.mjs.map +2 -2
  125. package/dist-esm/lib/hooks/useCoarsePointer.mjs +15 -30
  126. package/dist-esm/lib/hooks/useCoarsePointer.mjs.map +2 -2
  127. package/dist-esm/lib/hooks/useEvent.mjs +1 -1
  128. package/dist-esm/lib/hooks/useEvent.mjs.map +2 -2
  129. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
  130. package/dist-esm/lib/hooks/useGestureEvents.mjs +1 -1
  131. package/dist-esm/lib/hooks/useGestureEvents.mjs.map +2 -2
  132. package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +2 -2
  133. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
  134. package/dist-esm/lib/hooks/useScreenBounds.mjs.map +2 -2
  135. package/dist-esm/lib/hooks/useStateAttribute.mjs +4 -1
  136. package/dist-esm/lib/hooks/useStateAttribute.mjs.map +2 -2
  137. package/dist-esm/lib/hooks/useTransform.mjs.map +1 -1
  138. package/dist-esm/lib/hooks/useZoomCss.mjs +4 -8
  139. package/dist-esm/lib/hooks/useZoomCss.mjs.map +2 -2
  140. package/dist-esm/lib/options.mjs +6 -1
  141. package/dist-esm/lib/options.mjs.map +2 -2
  142. package/dist-esm/lib/primitives/Box.mjs +3 -0
  143. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  144. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +1 -0
  145. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  146. package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
  147. package/dist-esm/lib/utils/rotation.mjs +1 -1
  148. package/dist-esm/lib/utils/rotation.mjs.map +2 -2
  149. package/dist-esm/version.mjs +3 -3
  150. package/dist-esm/version.mjs.map +1 -1
  151. package/editor.css +14 -12
  152. package/package.json +21 -17
  153. package/src/index.ts +5 -1
  154. package/src/lib/components/ErrorBoundary.tsx +1 -1
  155. package/src/lib/components/GeometryDebuggingView.tsx +1 -19
  156. package/src/lib/components/default-components/DefaultCanvas.tsx +5 -8
  157. package/src/lib/config/TLUserPreferences.test.ts +40 -0
  158. package/src/lib/constants.ts +0 -2
  159. package/src/lib/editor/Editor.test.ts +150 -10
  160. package/src/lib/editor/Editor.ts +533 -384
  161. package/src/lib/editor/bindings/BindingUtil.ts +15 -9
  162. package/src/lib/editor/derivations/bindingsIndex.ts +2 -2
  163. package/src/lib/editor/derivations/notVisibleShapes.ts +21 -33
  164. package/src/lib/editor/derivations/parentsToChildren.ts +18 -7
  165. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +17 -31
  166. package/src/lib/editor/managers/ClickManager/ClickManager.ts +1 -1
  167. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +129 -79
  168. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +10 -6
  169. package/src/lib/editor/managers/FontManager/FontManager.test.ts +14 -4
  170. package/src/lib/editor/managers/InputsManager/InputsManager.ts +566 -0
  171. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +0 -4
  172. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +12 -0
  173. package/src/lib/editor/managers/SnapManager/SnapManager.ts +4 -4
  174. package/src/lib/editor/managers/SpatialIndexManager/RBushIndex.ts +144 -0
  175. package/src/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.ts +215 -0
  176. package/src/lib/editor/managers/TickManager/TickManager.test.ts +40 -107
  177. package/src/lib/editor/managers/TickManager/TickManager.ts +2 -32
  178. package/src/lib/editor/shapes/BaseBoxShapeUtil.tsx +2 -2
  179. package/src/lib/editor/shapes/ShapeUtil.ts +72 -32
  180. package/src/lib/editor/shapes/group/DashedOutlineBox.tsx +1 -1
  181. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +1 -3
  182. package/src/lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool.ts +2 -1
  183. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +6 -6
  184. package/src/lib/editor/types/emit-types.ts +3 -1
  185. package/src/lib/exports/getSvgJsx.test.ts +10 -19
  186. package/src/lib/exports/getSvgJsx.tsx +2 -5
  187. package/src/lib/exports/parseCss.test.ts +1 -0
  188. package/src/lib/exports/parseCss.ts +1 -1
  189. package/src/lib/globals/environment.ts +65 -10
  190. package/src/lib/globals/menus.ts +1 -1
  191. package/src/lib/hooks/useCoarsePointer.ts +16 -59
  192. package/src/lib/hooks/useEvent.tsx +1 -1
  193. package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +1 -1
  194. package/src/lib/hooks/useGestureEvents.ts +2 -2
  195. package/src/lib/hooks/usePassThroughMouseOverEvents.ts +1 -1
  196. package/src/lib/hooks/usePassThroughWheelEvents.ts +1 -1
  197. package/src/lib/hooks/useScreenBounds.ts +1 -1
  198. package/src/lib/hooks/useStateAttribute.ts +4 -1
  199. package/src/lib/hooks/useTransform.ts +1 -1
  200. package/src/lib/hooks/useZoomCss.ts +3 -8
  201. package/src/lib/options.ts +32 -0
  202. package/src/lib/primitives/Box.ts +9 -0
  203. package/src/lib/primitives/geometry/Geometry2d.ts +1 -0
  204. package/src/lib/utils/reparenting.ts +5 -5
  205. package/src/lib/utils/rotation.ts +1 -1
  206. package/src/version.ts +3 -3
@@ -46,7 +46,7 @@ var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use
46
46
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
47
47
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
48
48
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
49
- var __setMetaKeyTimeout_dec, __setCtrlKeyTimeout_dec, __setAltKeyTimeout_dec, __setShiftKeyTimeout_dec, _getIsReadonly_dec, _getIsFocused_dec, _getSharedOpacity_dec, _getSharedStyles_dec, __getSelectionSharedStyles_dec, __getBindingsIndexCache_dec, _getCurrentPageRenderingShapesSorted_dec, _getCurrentPageShapesSorted_dec, _getCurrentPageShapes_dec, _getCurrentPageBounds_dec, _getCulledShapes_dec, _getNotVisibleShapes_dec, __getShapeMaskedPageBoundsCache_dec, __getShapeMaskCache_dec, __getShapeClipPathCache_dec, __getShapePageBoundsCache_dec, __getShapePageTransformCache_dec, __getShapeHandlesCache_dec, __getAllAssetsQuery_dec, _getCurrentPageShapeIdsSorted_dec, _getCurrentPageId_dec, _getPages_dec, __getAllPagesQuery_dec, _getRenderingShapes_dec, _getCollaboratorsOnCurrentPage_dec, _getCollaborators_dec, __getCollaboratorsQuery_dec, _getViewportPageBounds_dec, _getViewportScreenCenter_dec, _getViewportScreenBounds_dec, _getZoomLevel_dec, _getCameraForFollowing_dec, _getViewportPageBoundsForFollowing_dec, _getCamera_dec, __unsafe_getCameraId_dec, _getErasingShapes_dec, _getErasingShapeIds_dec, _getHintingShape_dec, _getHintingShapeIds_dec, _getHoveredShape_dec, _getHoveredShapeId_dec, _getRichTextEditor_dec, _getEditingShape_dec, _getEditingShapeId_dec, _getFocusedGroup_dec, _getFocusedGroupId_dec, _getSelectionRotatedScreenBounds_dec, _getSelectionRotatedPageBounds_dec, _getSelectionRotation_dec, _getSelectionPageBounds_dec, _getOnlySelectedShape_dec, _getOnlySelectedShapeId_dec, _getCurrentPageShapesInReadingOrder_dec, _getSelectedShapes_dec, _getSelectedShapeIds_dec, __getCurrentPageStateId_dec, _getCurrentPageState_dec, __getPageStatesQuery_dec, _getPageStates_dec, _getInstanceState_dec, _getDocumentSettings_dec, _getCurrentToolId_dec, _getCurrentTool_dec, _getPath_dec, _getCanRedo_dec, _getCanUndo_dec, _getIsShapeHiddenCache_dec, _a, _init;
49
+ var __setMetaKeyTimeout_dec, __setCtrlKeyTimeout_dec, __setAltKeyTimeout_dec, __setShiftKeyTimeout_dec, _getIsReadonly_dec, _getIsFocused_dec, _getSharedOpacity_dec, _getSharedStyles_dec, __getSelectionSharedStyles_dec, __getBindingsIndexCache_dec, _getCurrentPageRenderingShapesSorted_dec, _getCurrentPageShapesSorted_dec, _getCurrentPageShapes_dec, _getCurrentPageBounds_dec, _getCulledShapes_dec, _getNotVisibleShapes_dec, __getShapeMaskedPageBoundsCache_dec, __getShapeMaskCache_dec, __getShapeClipPathCache_dec, __getShapePageBoundsCache_dec, __getShapePageTransformCache_dec, __getShapeHandlesCache_dec, __getAllAssetsQuery_dec, _getCurrentPageShapeIdsSorted_dec, _getCurrentPageId_dec, _getPages_dec, __getAllPagesQuery_dec, _getRenderingShapes_dec, _getCollaboratorsOnCurrentPage_dec, _getCollaborators_dec, __getCollaboratorsQuery_dec, _getViewportPageBounds_dec, _getViewportScreenCenter_dec, _getViewportScreenBounds_dec, _getEfficientZoomLevel_dec, __getAboveDebouncedZoomThreshold_dec, _getDebouncedZoomLevel_dec, _getZoomLevel_dec, _getCameraForFollowing_dec, _getViewportPageBoundsForFollowing_dec, _getCamera_dec, __unsafe_getCameraId_dec, _getErasingShapes_dec, _getErasingShapeIds_dec, _getHintingShape_dec, _getHintingShapeIds_dec, _getHoveredShape_dec, _getHoveredShapeId_dec, _getRichTextEditor_dec, _getEditingShape_dec, _getEditingShapeId_dec, _getFocusedGroup_dec, _getFocusedGroupId_dec, _getSelectionRotatedScreenBounds_dec, _getSelectionRotatedPageBounds_dec, _getSelectionRotation_dec, _getSelectionPageBounds_dec, _getOnlySelectedShape_dec, _getOnlySelectedShapeId_dec, _getCurrentPageShapesInReadingOrder_dec, _getSelectedShapes_dec, _getSelectedShapeIds_dec, __getCurrentPageStateId_dec, _getCurrentPageState_dec, __getPageStatesQuery_dec, _getPageStates_dec, _getInstanceState_dec, _getDocumentSettings_dec, _getCurrentToolId_dec, _getCurrentTool_dec, _getPath_dec, _canRedo_dec, _canUndo_dec, _getIsShapeHiddenCache_dec, _a, _init;
50
50
  import {
51
51
  EMPTY_ARRAY,
52
52
  atom,
@@ -64,7 +64,6 @@ import {
64
64
  PageRecordType,
65
65
  TLDOCUMENT_ID,
66
66
  TLINSTANCE_ID,
67
- TLPOINTER_ID,
68
67
  createBindingId,
69
68
  createShapeId,
70
69
  getShapePropKeysByStyle,
@@ -116,8 +115,7 @@ import {
116
115
  LEFT_MOUSE_BUTTON,
117
116
  MIDDLE_MOUSE_BUTTON,
118
117
  RIGHT_MOUSE_BUTTON,
119
- STYLUS_ERASER_BUTTON,
120
- ZOOM_TO_FIT_PADDING
118
+ STYLUS_ERASER_BUTTON
121
119
  } from "../constants.mjs";
122
120
  import { exportToSvg } from "../exports/exportToSvg.mjs";
123
121
  import { getSvgAsImage } from "../exports/getSvgAsImage.mjs";
@@ -140,7 +138,6 @@ import {
140
138
  parseDeepLinkString
141
139
  } from "../utils/deepLinks.mjs";
142
140
  import { getIncrementedName } from "../utils/getIncrementedName.mjs";
143
- import { isAccelKey } from "../utils/keyboard.mjs";
144
141
  import { getReorderingShapesChanges } from "../utils/reorderShapes.mjs";
145
142
  import { applyRotationToSnapshotShapes, getRotationSnapshot } from "../utils/rotation.mjs";
146
143
  import { bindingsIndex } from "./derivations/bindingsIndex.mjs";
@@ -152,13 +149,15 @@ import { EdgeScrollManager } from "./managers/EdgeScrollManager/EdgeScrollManage
152
149
  import { FocusManager } from "./managers/FocusManager/FocusManager.mjs";
153
150
  import { FontManager } from "./managers/FontManager/FontManager.mjs";
154
151
  import { HistoryManager } from "./managers/HistoryManager/HistoryManager.mjs";
152
+ import { InputsManager } from "./managers/InputsManager/InputsManager.mjs";
155
153
  import { ScribbleManager } from "./managers/ScribbleManager/ScribbleManager.mjs";
156
154
  import { SnapManager } from "./managers/SnapManager/SnapManager.mjs";
155
+ import { SpatialIndexManager } from "./managers/SpatialIndexManager/SpatialIndexManager.mjs";
157
156
  import { TextManager } from "./managers/TextManager/TextManager.mjs";
158
157
  import { TickManager } from "./managers/TickManager/TickManager.mjs";
159
158
  import { UserPreferencesManager } from "./managers/UserPreferencesManager/UserPreferencesManager.mjs";
160
159
  import { RootState } from "./tools/RootState.mjs";
161
- class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed], _getCanUndo_dec = [computed], _getCanRedo_dec = [computed], _getPath_dec = [computed], _getCurrentTool_dec = [computed], _getCurrentToolId_dec = [computed], _getDocumentSettings_dec = [computed], _getInstanceState_dec = [computed], _getPageStates_dec = [computed], __getPageStatesQuery_dec = [computed], _getCurrentPageState_dec = [computed], __getCurrentPageStateId_dec = [computed], _getSelectedShapeIds_dec = [computed], _getSelectedShapes_dec = [computed], _getCurrentPageShapesInReadingOrder_dec = [computed], _getOnlySelectedShapeId_dec = [computed], _getOnlySelectedShape_dec = [computed], _getSelectionPageBounds_dec = [computed], _getSelectionRotation_dec = [computed], _getSelectionRotatedPageBounds_dec = [computed], _getSelectionRotatedScreenBounds_dec = [computed], _getFocusedGroupId_dec = [computed], _getFocusedGroup_dec = [computed], _getEditingShapeId_dec = [computed], _getEditingShape_dec = [computed], _getRichTextEditor_dec = [computed], _getHoveredShapeId_dec = [computed], _getHoveredShape_dec = [computed], _getHintingShapeIds_dec = [computed], _getHintingShape_dec = [computed], _getErasingShapeIds_dec = [computed], _getErasingShapes_dec = [computed], __unsafe_getCameraId_dec = [computed], _getCamera_dec = [computed], _getViewportPageBoundsForFollowing_dec = [computed], _getCameraForFollowing_dec = [computed], _getZoomLevel_dec = [computed], _getViewportScreenBounds_dec = [computed], _getViewportScreenCenter_dec = [computed], _getViewportPageBounds_dec = [computed], __getCollaboratorsQuery_dec = [computed], _getCollaborators_dec = [computed], _getCollaboratorsOnCurrentPage_dec = [computed], _getRenderingShapes_dec = [computed], __getAllPagesQuery_dec = [computed], _getPages_dec = [computed], _getCurrentPageId_dec = [computed], _getCurrentPageShapeIdsSorted_dec = [computed], __getAllAssetsQuery_dec = [computed], __getShapeHandlesCache_dec = [computed], __getShapePageTransformCache_dec = [computed], __getShapePageBoundsCache_dec = [computed], __getShapeClipPathCache_dec = [computed], __getShapeMaskCache_dec = [computed], __getShapeMaskedPageBoundsCache_dec = [computed], _getNotVisibleShapes_dec = [computed], _getCulledShapes_dec = [computed], _getCurrentPageBounds_dec = [computed], _getCurrentPageShapes_dec = [computed], _getCurrentPageShapesSorted_dec = [computed], _getCurrentPageRenderingShapesSorted_dec = [computed], __getBindingsIndexCache_dec = [computed], __getSelectionSharedStyles_dec = [computed], _getSharedStyles_dec = [computed({ isEqual: (a, b) => a.equals(b) })], _getSharedOpacity_dec = [computed], _getIsFocused_dec = [computed], _getIsReadonly_dec = [computed], __setShiftKeyTimeout_dec = [bind], __setAltKeyTimeout_dec = [bind], __setCtrlKeyTimeout_dec = [bind], __setMetaKeyTimeout_dec = [bind], _a) {
160
+ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed], _canUndo_dec = [computed], _canRedo_dec = [computed], _getPath_dec = [computed], _getCurrentTool_dec = [computed], _getCurrentToolId_dec = [computed], _getDocumentSettings_dec = [computed], _getInstanceState_dec = [computed], _getPageStates_dec = [computed], __getPageStatesQuery_dec = [computed], _getCurrentPageState_dec = [computed], __getCurrentPageStateId_dec = [computed], _getSelectedShapeIds_dec = [computed], _getSelectedShapes_dec = [computed], _getCurrentPageShapesInReadingOrder_dec = [computed], _getOnlySelectedShapeId_dec = [computed], _getOnlySelectedShape_dec = [computed], _getSelectionPageBounds_dec = [computed], _getSelectionRotation_dec = [computed], _getSelectionRotatedPageBounds_dec = [computed], _getSelectionRotatedScreenBounds_dec = [computed], _getFocusedGroupId_dec = [computed], _getFocusedGroup_dec = [computed], _getEditingShapeId_dec = [computed], _getEditingShape_dec = [computed], _getRichTextEditor_dec = [computed], _getHoveredShapeId_dec = [computed], _getHoveredShape_dec = [computed], _getHintingShapeIds_dec = [computed], _getHintingShape_dec = [computed], _getErasingShapeIds_dec = [computed], _getErasingShapes_dec = [computed], __unsafe_getCameraId_dec = [computed], _getCamera_dec = [computed], _getViewportPageBoundsForFollowing_dec = [computed], _getCameraForFollowing_dec = [computed], _getZoomLevel_dec = [computed], _getDebouncedZoomLevel_dec = [computed], __getAboveDebouncedZoomThreshold_dec = [computed], _getEfficientZoomLevel_dec = [computed], _getViewportScreenBounds_dec = [computed], _getViewportScreenCenter_dec = [computed], _getViewportPageBounds_dec = [computed], __getCollaboratorsQuery_dec = [computed], _getCollaborators_dec = [computed], _getCollaboratorsOnCurrentPage_dec = [computed], _getRenderingShapes_dec = [computed], __getAllPagesQuery_dec = [computed], _getPages_dec = [computed], _getCurrentPageId_dec = [computed], _getCurrentPageShapeIdsSorted_dec = [computed], __getAllAssetsQuery_dec = [computed], __getShapeHandlesCache_dec = [computed], __getShapePageTransformCache_dec = [computed], __getShapePageBoundsCache_dec = [computed], __getShapeClipPathCache_dec = [computed], __getShapeMaskCache_dec = [computed], __getShapeMaskedPageBoundsCache_dec = [computed], _getNotVisibleShapes_dec = [computed], _getCulledShapes_dec = [computed], _getCurrentPageBounds_dec = [computed], _getCurrentPageShapes_dec = [computed], _getCurrentPageShapesSorted_dec = [computed], _getCurrentPageRenderingShapesSorted_dec = [computed], __getBindingsIndexCache_dec = [computed], __getSelectionSharedStyles_dec = [computed], _getSharedStyles_dec = [computed({ isEqual: (a, b) => a.equals(b) })], _getSharedOpacity_dec = [computed], _getIsFocused_dec = [computed], _getIsReadonly_dec = [computed], __setShiftKeyTimeout_dec = [bind], __setAltKeyTimeout_dec = [bind], __setCtrlKeyTimeout_dec = [bind], __setMetaKeyTimeout_dec = [bind], _a) {
162
161
  constructor({
163
162
  store,
164
163
  user,
@@ -194,7 +193,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
194
193
  */
195
194
  __publicField(this, "root");
196
195
  /**
197
- * A set of functions to call when the app is disposed.
196
+ * A set of functions to call when the editor is disposed.
198
197
  *
199
198
  * @public
200
199
  */
@@ -205,14 +204,24 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
205
204
  * @public
206
205
  */
207
206
  __publicField(this, "isDisposed", false);
208
- /** @internal */
207
+ /**
208
+ * A manager for the editor's tick events.
209
+ *
210
+ * @internal */
209
211
  __publicField(this, "_tickManager");
210
212
  /**
211
- * A manager for the app's snapping feature.
213
+ * A manager for the editor's input state.
214
+ *
215
+ * @public
216
+ */
217
+ __publicField(this, "inputs");
218
+ /**
219
+ * A manager for the editor's snapping feature.
212
220
  *
213
221
  * @public
214
222
  */
215
223
  __publicField(this, "snaps");
224
+ __publicField(this, "_spatialIndex");
216
225
  /**
217
226
  * A manager for the any asynchronous events and making sure they're
218
227
  * cleaned up upon disposal.
@@ -290,7 +299,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
290
299
  __publicField(this, "bindingUtils");
291
300
  /* --------------------- History -------------------- */
292
301
  /**
293
- * A manager for the app's history.
302
+ * A manager for the editor's history.
294
303
  *
295
304
  * @readonly
296
305
  */
@@ -305,6 +314,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
305
314
  // Rich text editor
306
315
  __publicField(this, "_currentRichTextEditor", atom("rich text editor", null));
307
316
  __publicField(this, "_textOptions");
317
+ __publicField(this, "_debouncedZoomLevel", atom("debounced zoom level", 1));
308
318
  __publicField(this, "_cameraOptions", atom("camera options", DEFAULT_CAMERA_OPTIONS));
309
319
  /** @internal */
310
320
  __publicField(this, "_viewportAnimation", null);
@@ -328,6 +338,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
328
338
  /* --------------------- Shapes --------------------- */
329
339
  __publicField(this, "_shapeGeometryCaches", {});
330
340
  __publicField(this, "_notVisibleShapes", notVisibleShapes(this));
341
+ __publicField(this, "_culledShapesCache", null);
331
342
  // Parents and children
332
343
  /**
333
344
  * A cache of parents to children.
@@ -355,54 +366,6 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
355
366
  tldraw: null,
356
367
  excalidraw: null
357
368
  });
358
- /* --------------------- Events --------------------- */
359
- /**
360
- * The app's current input state.
361
- *
362
- * @public
363
- */
364
- __publicField(this, "inputs", {
365
- /** The most recent pointer down's position in the current page space. */
366
- originPagePoint: new Vec(),
367
- /** The most recent pointer down's position in screen space. */
368
- originScreenPoint: new Vec(),
369
- /** The previous pointer position in the current page space. */
370
- previousPagePoint: new Vec(),
371
- /** The previous pointer position in screen space. */
372
- previousScreenPoint: new Vec(),
373
- /** The most recent pointer position in the current page space. */
374
- currentPagePoint: new Vec(),
375
- /** The most recent pointer position in screen space. */
376
- currentScreenPoint: new Vec(),
377
- /** A set containing the currently pressed keys. */
378
- keys: /* @__PURE__ */ new Set(),
379
- /** A set containing the currently pressed buttons. */
380
- buttons: /* @__PURE__ */ new Set(),
381
- /** Whether the input is from a pe. */
382
- isPen: false,
383
- /** Whether the shift key is currently pressed. */
384
- shiftKey: false,
385
- /** Whether the meta key is currently pressed. */
386
- metaKey: false,
387
- /** Whether the control or command key is currently pressed. */
388
- ctrlKey: false,
389
- /** Whether the alt or option key is currently pressed. */
390
- altKey: false,
391
- /** Whether the user is dragging. */
392
- isDragging: false,
393
- /** Whether the user is pointing. */
394
- isPointing: false,
395
- /** Whether the user is pinching. */
396
- isPinching: false,
397
- /** Whether the user is editing. */
398
- isEditing: false,
399
- /** Whether the user is panning. */
400
- isPanning: false,
401
- /** Whether the user is spacebar panning. */
402
- isSpacebarPanning: false,
403
- /** Velocity of mouse pointer, in pixels per millisecond */
404
- pointerVelocity: new Vec()
405
- });
406
369
  /**
407
370
  * A manager for recording multiple click events.
408
371
  *
@@ -426,8 +389,6 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
426
389
  /** @internal */
427
390
  __publicField(this, "_restoreToolId", "select");
428
391
  /** @internal */
429
- __publicField(this, "_pinchStart", 1);
430
- /** @internal */
431
392
  __publicField(this, "_didPinch", false);
432
393
  /** @internal */
433
394
  __publicField(this, "_selectedShapeIdsAtPointerDown", []);
@@ -453,6 +414,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
453
414
  }
454
415
  });
455
416
  this.snaps = new SnapManager(this);
417
+ this._spatialIndex = new SpatialIndexManager(this);
418
+ this.disposables.add(() => this._spatialIndex.dispose());
456
419
  this.disposables.add(this.timers.dispose);
457
420
  this._cameraOptions.set({ ...DEFAULT_CAMERA_OPTIONS, ...cameraOptions });
458
421
  this._textOptions = atom("text options", textOptions ?? null);
@@ -463,6 +426,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
463
426
  this.disposables.add(() => this.textMeasure.dispose());
464
427
  this.fonts = new FontManager(this, fontAssetUrls);
465
428
  this._tickManager = new TickManager(this);
429
+ this.inputs = new InputsManager(this);
466
430
  class NewRoot extends RootState {
467
431
  static initial = initialState ?? "";
468
432
  }
@@ -895,6 +859,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
895
859
  this.disposables.clear();
896
860
  this.store.dispose();
897
861
  this.isDisposed = true;
862
+ this.emit("dispose");
898
863
  }
899
864
  getShapeUtil(arg) {
900
865
  const type = typeof arg === "string" ? arg : arg.type;
@@ -928,9 +893,12 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
928
893
  this.history.undo();
929
894
  return this;
930
895
  }
931
- getCanUndo() {
896
+ canUndo() {
932
897
  return this.history.getNumUndos() > 0;
933
898
  }
899
+ getCanUndo() {
900
+ return this.canUndo();
901
+ }
934
902
  /**
935
903
  * Redo to the next mark.
936
904
  *
@@ -947,13 +915,16 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
947
915
  this.history.redo();
948
916
  return this;
949
917
  }
918
+ canRedo() {
919
+ return this.history.getNumRedos() > 0;
920
+ }
921
+ getCanRedo() {
922
+ return this.canRedo();
923
+ }
950
924
  clearHistory() {
951
925
  this.history.clear();
952
926
  return this;
953
927
  }
954
- getCanRedo() {
955
- return this.history.getNumRedos() > 0;
956
- }
957
928
  /**
958
929
  * Create a new "mark", or stopping point, in the undo redo history. Creating a mark will clear
959
930
  * any redos. You typically want to do this just before a user interaction begins or is handled.
@@ -1108,7 +1079,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
1108
1079
  }),
1109
1080
  selectionCount: this.getSelectedShapes().length,
1110
1081
  editingShape: editingShapeId ? this.getShape(editingShapeId) : void 0,
1111
- inputs: this.inputs,
1082
+ inputs: this.inputs.toJson(),
1112
1083
  pageState: this.getCurrentPageState(),
1113
1084
  instanceState: this.getInstanceState(),
1114
1085
  collaboratorCount: this.getCollaboratorsOnCurrentPage().length
@@ -1129,7 +1100,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
1129
1100
  * we're in a transaction that's about to be rolled back due to the same error we're currently
1130
1101
  * reporting.
1131
1102
  *
1132
- * Instead, to listen to changes to this value, you need to listen to app's `crash` event.
1103
+ * Instead, to listen to changes to this value, you need to listen to editor's `crash` event.
1133
1104
  *
1134
1105
  * @internal
1135
1106
  */
@@ -1780,6 +1751,28 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
1780
1751
  const editingShapeId = this.getEditingShapeId();
1781
1752
  return editingShapeId ? this.getShape(editingShapeId) : void 0;
1782
1753
  }
1754
+ /**
1755
+ * Whether the shape can be edited.
1756
+ *
1757
+ * @param shape - The shape (or shape id) to check if it can be edited.
1758
+ * @param info - The info about the edit start.
1759
+ *
1760
+ * @public
1761
+ * @returns true if the shape can be edited, false otherwise.
1762
+ */
1763
+ canEditShape(shape, info) {
1764
+ const id = typeof shape === "string" ? shape : shape?.id ?? null;
1765
+ if (!id) return false;
1766
+ if (id === this.getEditingShapeId()) return false;
1767
+ const _shape = this.getShape(id);
1768
+ if (!_shape) return false;
1769
+ const util = this.getShapeUtil(_shape);
1770
+ const _info = info ?? { type: "unknown" };
1771
+ if (!util.canEdit(_shape, _info)) return false;
1772
+ if (this.getIsReadonly() && !util.canEditInReadonly(_shape)) return false;
1773
+ if (this.isShapeOrAncestorLocked(_shape) && !util.canEditWhileLocked(_shape)) return false;
1774
+ return true;
1775
+ }
1783
1776
  /**
1784
1777
  * Set the current editing shape.
1785
1778
  *
@@ -1795,42 +1788,42 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
1795
1788
  */
1796
1789
  setEditingShape(shape) {
1797
1790
  const id = typeof shape === "string" ? shape : shape?.id ?? null;
1798
- this.setRichTextEditor(null);
1799
- const prevEditingShapeId = this.getEditingShapeId();
1800
- if (id !== prevEditingShapeId) {
1801
- if (id) {
1802
- const shape2 = this.getShape(id);
1803
- if (shape2 && this.getShapeUtil(shape2).canEdit(shape2)) {
1804
- this.run(
1805
- () => {
1806
- this._updateCurrentPageState({ editingShapeId: id });
1807
- if (prevEditingShapeId) {
1808
- const prevEditingShape = this.getShape(prevEditingShapeId);
1809
- if (prevEditingShape) {
1810
- this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
1811
- }
1812
- }
1813
- this.getShapeUtil(shape2).onEditStart?.(shape2);
1814
- },
1815
- { history: "ignore" }
1816
- );
1817
- return this;
1818
- }
1819
- }
1791
+ if (!id) {
1820
1792
  this.run(
1821
1793
  () => {
1822
- this._updateCurrentPageState({ editingShapeId: null });
1823
- this._currentRichTextEditor.set(null);
1794
+ const prevEditingShapeId = this.getEditingShapeId();
1824
1795
  if (prevEditingShapeId) {
1825
1796
  const prevEditingShape = this.getShape(prevEditingShapeId);
1826
1797
  if (prevEditingShape) {
1827
1798
  this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
1828
1799
  }
1829
1800
  }
1801
+ this._updateCurrentPageState({ editingShapeId: null });
1802
+ this._currentRichTextEditor.set(null);
1830
1803
  },
1831
1804
  { history: "ignore" }
1832
1805
  );
1806
+ return this;
1833
1807
  }
1808
+ if (!this.canEditShape(id)) return this;
1809
+ this.run(
1810
+ () => {
1811
+ const prevEditingShapeId = this.getEditingShapeId();
1812
+ if (prevEditingShapeId) {
1813
+ const prevEditingShape = this.getShape(prevEditingShapeId);
1814
+ if (prevEditingShape) {
1815
+ this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
1816
+ }
1817
+ }
1818
+ this._updateCurrentPageState({ editingShapeId: null });
1819
+ this._currentRichTextEditor.set(null);
1820
+ this.select(id);
1821
+ this._updateCurrentPageState({ editingShapeId: id });
1822
+ const nextEditingShape = this.getShape(id);
1823
+ this.getShapeUtil(nextEditingShape).onEditStart?.(nextEditingShape);
1824
+ },
1825
+ { history: "ignore" }
1826
+ );
1834
1827
  return this;
1835
1828
  }
1836
1829
  getRichTextEditor() {
@@ -1963,6 +1956,25 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
1963
1956
  getCroppingShapeId() {
1964
1957
  return this.getCurrentPageState().croppingShapeId;
1965
1958
  }
1959
+ /**
1960
+ * Whether the shape can be cropped.
1961
+ *
1962
+ * @param shape - The shape (or shape id) to check if it can be cropped.
1963
+ *
1964
+ * @public
1965
+ * @returns true if the shape can be cropped, false otherwise.
1966
+ */
1967
+ canCropShape(shape) {
1968
+ if (!shape) return false;
1969
+ const id = typeof shape === "string" ? shape : shape?.id ?? null;
1970
+ if (!id) return false;
1971
+ const _shape = this.getShape(id);
1972
+ if (!_shape) return false;
1973
+ const util = this.getShapeUtil(_shape);
1974
+ if (!util.canCrop(_shape)) return false;
1975
+ if (this.isShapeOrAncestorLocked(_shape)) return false;
1976
+ return true;
1977
+ }
1966
1978
  /**
1967
1979
  * Set the current cropping shape.
1968
1980
  *
@@ -1984,12 +1996,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
1984
1996
  () => {
1985
1997
  if (!id) {
1986
1998
  this.updateCurrentPageState({ croppingShapeId: null });
1987
- } else {
1988
- const shape2 = this.getShape(id);
1989
- const util = this.getShapeUtil(shape2);
1990
- if (shape2 && util.canCrop(shape2)) {
1991
- this.updateCurrentPageState({ croppingShapeId: id });
1992
- }
1999
+ } else if (this.canCropShape(id)) {
2000
+ this.updateCurrentPageState({ croppingShapeId: id });
1993
2001
  }
1994
2002
  },
1995
2003
  { history: "ignore" }
@@ -2064,6 +2072,22 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
2064
2072
  getZoomLevel() {
2065
2073
  return this.getCamera().z;
2066
2074
  }
2075
+ getDebouncedZoomLevel() {
2076
+ if (this.options.debouncedZoom) {
2077
+ if (this.getCameraState() === "idle") {
2078
+ return this.getZoomLevel();
2079
+ } else {
2080
+ return this._debouncedZoomLevel.get();
2081
+ }
2082
+ }
2083
+ return this.getZoomLevel();
2084
+ }
2085
+ _getAboveDebouncedZoomThreshold() {
2086
+ return this.getCurrentPageShapeIds().size > this.options.debouncedZoomThreshold;
2087
+ }
2088
+ getEfficientZoomLevel() {
2089
+ return this._getAboveDebouncedZoomThreshold() ? this.getDebouncedZoomLevel() : this.getZoomLevel();
2090
+ }
2067
2091
  /**
2068
2092
  * Get the camera's initial or reset zoom level.
2069
2093
  *
@@ -2309,7 +2333,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
2309
2333
  },
2310
2334
  { history: "ignore" }
2311
2335
  );
2312
- const { currentScreenPoint, currentPagePoint } = this.inputs;
2336
+ const currentScreenPoint = this.inputs.getCurrentScreenPoint();
2337
+ const currentPagePoint = this.inputs.getCurrentPagePoint();
2313
2338
  if (currentScreenPoint.x / z - x !== currentPagePoint.x || currentScreenPoint.y / z - y !== currentPagePoint.y) {
2314
2339
  this.updatePointer({
2315
2340
  immediate: opts?.immediate,
@@ -2444,7 +2469,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
2444
2469
  * ```ts
2445
2470
  * editor.zoomIn()
2446
2471
  * editor.zoomIn(editor.getViewportScreenCenter(), { animation: { duration: 200 } })
2447
- * editor.zoomIn(editor.inputs.currentScreenPoint, { animation: { duration: 200 } })
2472
+ * editor.zoomIn(editor.inputs.getCurrentScreenPoint(), { animation: { duration: 200 } })
2448
2473
  * ```
2449
2474
  *
2450
2475
  * @param point - The screen point to zoom in on. Defaults to the screen center
@@ -2485,7 +2510,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
2485
2510
  * ```ts
2486
2511
  * editor.zoomOut()
2487
2512
  * editor.zoomOut(editor.getViewportScreenCenter(), { animation: { duration: 120 } })
2488
- * editor.zoomOut(editor.inputs.currentScreenPoint, { animation: { duration: 120 } })
2513
+ * editor.zoomOut(editor.inputs.getCurrentScreenPoint(), { animation: { duration: 120 } })
2489
2514
  * ```
2490
2515
  *
2491
2516
  * @param point - The point to zoom out on. Defaults to the viewport screen center.
@@ -2537,10 +2562,15 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
2537
2562
  if (isLocked && !opts?.force) return this;
2538
2563
  const selectionPageBounds = this.getSelectionPageBounds();
2539
2564
  if (selectionPageBounds) {
2540
- this.zoomToBounds(selectionPageBounds, {
2541
- targetZoom: Math.max(1, this.getZoomLevel()),
2542
- ...opts
2543
- });
2565
+ const currentZoom = this.getZoomLevel();
2566
+ if (Math.abs(currentZoom - 1) < 0.01) {
2567
+ this.zoomToBounds(selectionPageBounds, opts);
2568
+ } else {
2569
+ this.zoomToBounds(selectionPageBounds, {
2570
+ targetZoom: 1,
2571
+ ...opts
2572
+ });
2573
+ }
2544
2574
  }
2545
2575
  return this;
2546
2576
  }
@@ -2580,7 +2610,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
2580
2610
  const cameraOptions = this._cameraOptions.__unsafe__getWithoutCapture();
2581
2611
  if (cameraOptions.isLocked && !opts?.force) return this;
2582
2612
  const viewportScreenBounds = this.getViewportScreenBounds();
2583
- const inset = opts?.inset ?? Math.min(ZOOM_TO_FIT_PADDING, viewportScreenBounds.width * 0.28);
2613
+ const inset = opts?.inset ?? Math.min(this.options.zoomToFitPadding, viewportScreenBounds.width * 0.28);
2584
2614
  const baseZoom = this.getBaseZoom();
2585
2615
  const zoomMin = cameraOptions.zoomSteps[0];
2586
2616
  const zoomMax = last(cameraOptions.zoomSteps);
@@ -2804,18 +2834,20 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
2804
2834
  }
2805
2835
  if (_willSetInitialBounds) {
2806
2836
  this.updateInstanceState({ screenBounds: screenBounds.toJson(), insets });
2837
+ this.emit("resize", screenBounds.toJson());
2807
2838
  this.setCamera(this.getCamera());
2808
2839
  } else {
2809
2840
  if (center && !this.getInstanceState().followingUserId) {
2810
2841
  const before = this.getViewportPageBounds().center;
2811
2842
  this.updateInstanceState({ screenBounds: screenBounds.toJson(), insets });
2843
+ this.emit("resize", screenBounds.toJson());
2812
2844
  this.centerOnPoint(before);
2813
2845
  } else {
2814
2846
  this.updateInstanceState({ screenBounds: screenBounds.toJson(), insets });
2847
+ this.emit("resize", screenBounds.toJson());
2815
2848
  this._setCamera(Vec.From({ ...this.getCamera() }));
2816
2849
  }
2817
2850
  }
2818
- this._tickCameraState();
2819
2851
  return this;
2820
2852
  }
2821
2853
  getViewportScreenBounds() {
@@ -3095,6 +3127,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
3095
3127
  this._cameraStateTimeoutRemaining = this.options.cameraMovingTimeoutMs;
3096
3128
  if (this._cameraState.__unsafe__getWithoutCapture() !== "idle") return;
3097
3129
  this._cameraState.set("moving");
3130
+ this._debouncedZoomLevel.set(unsafe__withoutCapture(() => this.getCamera().z));
3098
3131
  this.on("tick", this._decayCameraStateTimeout);
3099
3132
  }
3100
3133
  /**
@@ -3847,14 +3880,29 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
3847
3880
  const notVisibleShapes2 = this.getNotVisibleShapes();
3848
3881
  const selectedShapeIds = this.getSelectedShapeIds();
3849
3882
  const editingId = this.getEditingShapeId();
3850
- const culledShapes = new Set(notVisibleShapes2);
3883
+ const nextValue = new Set(notVisibleShapes2);
3851
3884
  if (editingId) {
3852
- culledShapes.delete(editingId);
3885
+ nextValue.delete(editingId);
3853
3886
  }
3854
3887
  selectedShapeIds.forEach((id) => {
3855
- culledShapes.delete(id);
3888
+ nextValue.delete(id);
3856
3889
  });
3857
- return culledShapes;
3890
+ const prevValue = this._culledShapesCache;
3891
+ if (prevValue) {
3892
+ if (prevValue.size !== nextValue.size) {
3893
+ this._culledShapesCache = nextValue;
3894
+ return nextValue;
3895
+ }
3896
+ for (const id of prevValue) {
3897
+ if (!nextValue.has(id)) {
3898
+ this._culledShapesCache = nextValue;
3899
+ return nextValue;
3900
+ }
3901
+ }
3902
+ return prevValue;
3903
+ }
3904
+ this._culledShapesCache = nextValue;
3905
+ return nextValue;
3858
3906
  }
3859
3907
  getCurrentPageBounds() {
3860
3908
  let commonBounds;
@@ -3904,7 +3952,10 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
3904
3952
  let inHollowSmallestAreaHit = null;
3905
3953
  let inMarginClosestToEdgeDistance = Infinity;
3906
3954
  let inMarginClosestToEdgeHit = null;
3955
+ const searchMargin = Math.max(innerMargin, outerMargin, this.options.hitTestMargin / zoomLevel);
3956
+ const candidateIds = this._spatialIndex.getShapeIdsAtPoint(point, searchMargin);
3907
3957
  const shapesToCheck = (opts.renderingOnly ? this.getCurrentPageRenderingShapesSorted() : this.getCurrentPageShapesSorted()).filter((shape) => {
3958
+ if (!candidateIds.has(shape.id) && !this.isShapeOfType(shape, "frame")) return false;
3908
3959
  if (shape.isLocked && !hitLocked || this.isShapeHidden(shape) || this.isShapeOfType(shape, "group"))
3909
3960
  return false;
3910
3961
  const pageMask = this.getShapeMask(shape);
@@ -4011,7 +4062,33 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4011
4062
  * @public
4012
4063
  */
4013
4064
  getShapesAtPoint(point, opts = {}) {
4014
- return this.getCurrentPageShapesSorted().filter((shape) => !this.isShapeHidden(shape) && this.isPointInShape(shape, point, opts)).reverse();
4065
+ const margin = opts.margin ?? 0;
4066
+ const candidateIds = this._spatialIndex.getShapeIdsAtPoint(point, margin);
4067
+ return this.getCurrentPageShapesSorted().filter((shape) => {
4068
+ if (this.isShapeHidden(shape)) return false;
4069
+ if (!candidateIds.has(shape.id) && !this.isShapeOfType(shape, "frame")) return false;
4070
+ return this.isPointInShape(shape, point, opts);
4071
+ }).reverse();
4072
+ }
4073
+ /**
4074
+ * Get shape IDs within the given bounds.
4075
+ *
4076
+ * Note: Uses shape page bounds only. Frames with labels outside their bounds
4077
+ * may not be included even if the label is within the search bounds.
4078
+ *
4079
+ * Note: Results are unordered. If you need z-order, combine with sorted shapes:
4080
+ * ```ts
4081
+ * const candidates = editor.getShapeIdsInsideBounds(bounds)
4082
+ * const sorted = editor.getCurrentPageShapesSorted().filter(s => candidates.has(s.id))
4083
+ * ```
4084
+ *
4085
+ * @param bounds - The bounds to search within.
4086
+ * @returns Unordered set of shape IDs within the given bounds.
4087
+ *
4088
+ * @internal
4089
+ */
4090
+ getShapeIdsInsideBounds(bounds) {
4091
+ return this._spatialIndex.getShapeIdsInsideBounds(bounds);
4015
4092
  }
4016
4093
  /**
4017
4094
  * Test whether a point (in the current page space) will will a shape. This method takes into account masks,
@@ -4435,30 +4512,18 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4435
4512
  getBinding(id) {
4436
4513
  return this.store.get(id);
4437
4514
  }
4438
- /**
4439
- * Get all bindings of a certain type _from_ a particular shape. These are the bindings whose
4440
- * `fromId` matched the shape's ID.
4441
- */
4442
4515
  getBindingsFromShape(shape, type) {
4443
4516
  const id = typeof shape === "string" ? shape : shape.id;
4444
4517
  return this.getBindingsInvolvingShape(id).filter(
4445
4518
  (b) => b.fromId === id && b.type === type
4446
4519
  );
4447
4520
  }
4448
- /**
4449
- * Get all bindings of a certain type _to_ a particular shape. These are the bindings whose
4450
- * `toId` matches the shape's ID.
4451
- */
4452
4521
  getBindingsToShape(shape, type) {
4453
4522
  const id = typeof shape === "string" ? shape : shape.id;
4454
4523
  return this.getBindingsInvolvingShape(id).filter(
4455
4524
  (b) => b.toId === id && b.type === type
4456
4525
  );
4457
4526
  }
4458
- /**
4459
- * Get all bindings involving a particular shape. This includes bindings where the shape is the
4460
- * `fromId` or `toId`. If a type is provided, only bindings of that type are returned.
4461
- */
4462
4527
  getBindingsInvolvingShape(shape, type) {
4463
4528
  const id = typeof shape === "string" ? shape : shape.id;
4464
4529
  const result = this._getBindingsIndexCache().get(id) ?? EMPTY_ARRAY;
@@ -5706,8 +5771,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
5706
5771
  isAspectRatioLocked: options.isAspectRatioLocked
5707
5772
  });
5708
5773
  if (Math.sign(scale.x) * Math.sign(scale.y) < 0) {
5709
- let { rotation } = Mat.Decompose(options.initialPageTransform);
5710
- rotation -= 2 * rotation;
5774
+ const parentRotation = this.getShapeParentTransform(id).rotation();
5775
+ const rotation = -options.initialShape.rotation - 2 * parentRotation;
5711
5776
  this.updateShapes([{ id, type, rotation }]);
5712
5777
  }
5713
5778
  const preScaleShapePageCenter = Mat.applyToPoint(
@@ -5720,9 +5785,9 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
5720
5785
  scale,
5721
5786
  options.scaleAxisRotation
5722
5787
  );
5723
- const pageBounds = this.getShapePageBounds(id);
5724
5788
  const pageTransform = this.getShapePageTransform(id);
5725
- const currentPageCenter = pageBounds.center;
5789
+ const currentLocalBounds = this.getShapeGeometry(id).bounds;
5790
+ const currentPageCenter = Mat.applyToPoint(pageTransform, currentLocalBounds.center);
5726
5791
  const shapePageTransformOrigin = pageTransform.point();
5727
5792
  if (!currentPageCenter || !shapePageTransformOrigin) return this;
5728
5793
  const pageDelta = Vec.Sub(postScaleShapePageCenter, currentPageCenter);
@@ -6008,7 +6073,11 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6008
6073
  )
6009
6074
  );
6010
6075
  const sortedShapeIds = shapesToGroup.sort(sortByIndex).map((s) => s.id);
6011
- const pageBounds = Box.Common(compact(shapesToGroup.map((id) => this.getShapePageBounds(id))));
6076
+ const childBounds = compact(shapesToGroup.map((shape) => this.getShapePageBounds(shape)));
6077
+ const pageBounds = Box.Common(childBounds);
6078
+ if (!pageBounds.isValid()) {
6079
+ throw Error(`Editor.groupShapes: group bounds are invalid (NaN).`);
6080
+ }
6012
6081
  const { x, y } = pageBounds.point;
6013
6082
  const parentId = this.findCommonAncestor(shapesToGroup) ?? this.getCurrentPageId();
6014
6083
  if (this.getCurrentToolId() !== "select") return this;
@@ -6698,6 +6767,25 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6698
6767
  }
6699
6768
  }
6700
6769
  }
6770
+ if (point) {
6771
+ const shapesById = new Map(shapes.map((shape) => [shape.id, shape]));
6772
+ const rootShapesFromContent = compact(rootShapeIds.map((id) => shapesById.get(id)));
6773
+ if (rootShapesFromContent.length > 0) {
6774
+ const targetParent = this.getShapeAtPoint(point, {
6775
+ hitInside: true,
6776
+ hitFrameInside: true,
6777
+ hitLocked: true,
6778
+ filter: (shape) => {
6779
+ const util = this.getShapeUtil(shape);
6780
+ if (!util.canReceiveNewChildrenOfType) return false;
6781
+ return rootShapesFromContent.every(
6782
+ (rootShape) => util.canReceiveNewChildrenOfType(shape, rootShape.type)
6783
+ );
6784
+ }
6785
+ });
6786
+ pasteParentId = targetParent ? targetParent.id : currentPageId;
6787
+ }
6788
+ }
6701
6789
  let isDuplicating = false;
6702
6790
  if (!isPageId(pasteParentId)) {
6703
6791
  const parent = this.getShape(pasteParentId);
@@ -6942,60 +7030,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6942
7030
  height
6943
7031
  };
6944
7032
  }
6945
- /**
6946
- * Update the input points from a pointer, pinch, or wheel event.
6947
- *
6948
- * @param info - The event info.
6949
- */
6950
- _updateInputsFromEvent(info) {
6951
- const {
6952
- pointerVelocity,
6953
- previousScreenPoint,
6954
- previousPagePoint,
6955
- currentScreenPoint,
6956
- currentPagePoint,
6957
- originScreenPoint,
6958
- originPagePoint
6959
- } = this.inputs;
6960
- const { screenBounds } = this.store.unsafeGetWithoutCapture(TLINSTANCE_ID);
6961
- const { x: cx, y: cy, z: cz } = unsafe__withoutCapture(() => this.getCamera());
6962
- const sx = info.point.x - screenBounds.x;
6963
- const sy = info.point.y - screenBounds.y;
6964
- const sz = info.point.z ?? 0.5;
6965
- previousScreenPoint.setTo(currentScreenPoint);
6966
- previousPagePoint.setTo(currentPagePoint);
6967
- currentScreenPoint.set(sx, sy);
6968
- const nx = sx / cz - cx;
6969
- const ny = sy / cz - cy;
6970
- if (isFinite(nx) && isFinite(ny)) {
6971
- currentPagePoint.set(nx, ny, sz);
6972
- }
6973
- this.inputs.isPen = info.type === "pointer" && info.isPen;
6974
- if (info.name === "pointer_down" || this.inputs.isPinching) {
6975
- pointerVelocity.set(0, 0);
6976
- originScreenPoint.setTo(currentScreenPoint);
6977
- originPagePoint.setTo(currentPagePoint);
6978
- }
6979
- this.run(
6980
- () => {
6981
- this.store.put([
6982
- {
6983
- id: TLPOINTER_ID,
6984
- typeName: "pointer",
6985
- x: currentPagePoint.x,
6986
- y: currentPagePoint.y,
6987
- lastActivityTimestamp: (
6988
- // If our pointer moved only because we're following some other user, then don't
6989
- // update our last activity timestamp; otherwise, update it to the current timestamp.
6990
- (info.type === "pointer" && info.pointerId === INTERNAL_POINTER_IDS.CAMERA_MOVE ? this.store.unsafeGetWithoutCapture(TLPOINTER_ID)?.lastActivityTimestamp ?? this._tickManager.now : this._tickManager.now)
6991
- ),
6992
- meta: {}
6993
- }
6994
- ]);
6995
- },
6996
- { history: "ignore" }
6997
- );
6998
- }
7033
+ /* --------------------- Events --------------------- */
6999
7034
  /**
7000
7035
  * Dispatch a cancel event.
7001
7036
  *
@@ -7060,18 +7095,19 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7060
7095
  point: options?.point ?? // weird but true: what `inputs` calls screen-space is actually viewport space. so
7061
7096
  // we need to convert back into true screen space first. we should fix this...
7062
7097
  Vec.Add(
7063
- this.inputs.currentScreenPoint,
7098
+ this.inputs.getCurrentScreenPoint(),
7064
7099
  this.store.unsafeGetWithoutCapture(TLINSTANCE_ID).screenBounds
7065
7100
  ),
7066
7101
  pointerId: options?.pointerId ?? 0,
7067
7102
  button: options?.button ?? 0,
7068
- isPen: options?.isPen ?? this.inputs.isPen,
7069
- shiftKey: options?.shiftKey ?? this.inputs.shiftKey,
7070
- altKey: options?.altKey ?? this.inputs.altKey,
7071
- ctrlKey: options?.ctrlKey ?? this.inputs.ctrlKey,
7072
- metaKey: options?.metaKey ?? this.inputs.metaKey,
7073
- accelKey: options?.accelKey ?? isAccelKey(this.inputs)
7103
+ isPen: options?.isPen ?? this.inputs.getIsPen(),
7104
+ shiftKey: options?.shiftKey ?? this.inputs.getShiftKey(),
7105
+ altKey: options?.altKey ?? this.inputs.getAltKey(),
7106
+ ctrlKey: options?.ctrlKey ?? this.inputs.getCtrlKey(),
7107
+ metaKey: options?.metaKey ?? this.inputs.getMetaKey(),
7108
+ accelKey: false
7074
7109
  };
7110
+ event.accelKey = options?.accelKey ?? this.inputs.getAccelKey();
7075
7111
  if (options?.immediate) {
7076
7112
  this._flushEventForTick(event);
7077
7113
  } else {
@@ -7387,58 +7423,58 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7387
7423
  this._clickManager.cancelDoubleClickTimeout();
7388
7424
  }
7389
7425
  _setShiftKeyTimeout() {
7390
- this.inputs.shiftKey = false;
7426
+ this.inputs.setShiftKey(false);
7391
7427
  this.dispatch({
7392
7428
  type: "keyboard",
7393
7429
  name: "key_up",
7394
7430
  key: "Shift",
7395
- shiftKey: this.inputs.shiftKey,
7396
- ctrlKey: this.inputs.ctrlKey,
7397
- altKey: this.inputs.altKey,
7398
- metaKey: this.inputs.metaKey,
7399
- accelKey: isAccelKey(this.inputs),
7431
+ shiftKey: this.inputs.getShiftKey(),
7432
+ ctrlKey: this.inputs.getCtrlKey(),
7433
+ altKey: this.inputs.getAltKey(),
7434
+ metaKey: this.inputs.getMetaKey(),
7435
+ accelKey: this.inputs.getAccelKey(),
7400
7436
  code: "ShiftLeft"
7401
7437
  });
7402
7438
  }
7403
7439
  _setAltKeyTimeout() {
7404
- this.inputs.altKey = false;
7440
+ this.inputs.setAltKey(false);
7405
7441
  this.dispatch({
7406
7442
  type: "keyboard",
7407
7443
  name: "key_up",
7408
7444
  key: "Alt",
7409
- shiftKey: this.inputs.shiftKey,
7410
- ctrlKey: this.inputs.ctrlKey,
7411
- altKey: this.inputs.altKey,
7412
- metaKey: this.inputs.metaKey,
7413
- accelKey: isAccelKey(this.inputs),
7445
+ shiftKey: this.inputs.getShiftKey(),
7446
+ ctrlKey: this.inputs.getCtrlKey(),
7447
+ altKey: this.inputs.getAltKey(),
7448
+ metaKey: this.inputs.getMetaKey(),
7449
+ accelKey: this.inputs.getAccelKey(),
7414
7450
  code: "AltLeft"
7415
7451
  });
7416
7452
  }
7417
7453
  _setCtrlKeyTimeout() {
7418
- this.inputs.ctrlKey = false;
7454
+ this.inputs.setCtrlKey(false);
7419
7455
  this.dispatch({
7420
7456
  type: "keyboard",
7421
7457
  name: "key_up",
7422
7458
  key: "Ctrl",
7423
- shiftKey: this.inputs.shiftKey,
7424
- ctrlKey: this.inputs.ctrlKey,
7425
- altKey: this.inputs.altKey,
7426
- metaKey: this.inputs.metaKey,
7427
- accelKey: isAccelKey(this.inputs),
7459
+ shiftKey: this.inputs.getShiftKey(),
7460
+ ctrlKey: this.inputs.getCtrlKey(),
7461
+ altKey: this.inputs.getAltKey(),
7462
+ metaKey: this.inputs.getMetaKey(),
7463
+ accelKey: this.inputs.getAccelKey(),
7428
7464
  code: "ControlLeft"
7429
7465
  });
7430
7466
  }
7431
7467
  _setMetaKeyTimeout() {
7432
- this.inputs.metaKey = false;
7468
+ this.inputs.setMetaKey(false);
7433
7469
  this.dispatch({
7434
7470
  type: "keyboard",
7435
7471
  name: "key_up",
7436
7472
  key: "Meta",
7437
- shiftKey: this.inputs.shiftKey,
7438
- ctrlKey: this.inputs.ctrlKey,
7439
- altKey: this.inputs.altKey,
7440
- metaKey: this.inputs.metaKey,
7441
- accelKey: isAccelKey(this.inputs),
7473
+ shiftKey: this.inputs.getShiftKey(),
7474
+ ctrlKey: this.inputs.getCtrlKey(),
7475
+ altKey: this.inputs.getAltKey(),
7476
+ metaKey: this.inputs.getMetaKey(),
7477
+ accelKey: this.inputs.getAccelKey(),
7442
7478
  code: "MetaLeft"
7443
7479
  });
7444
7480
  }
@@ -7509,47 +7545,47 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7509
7545
  const { type } = info;
7510
7546
  if (info.type === "misc") {
7511
7547
  if (info.name === "cancel" || info.name === "complete") {
7512
- this.inputs.isDragging = false;
7513
- if (this.inputs.isPanning) {
7514
- this.inputs.isPanning = false;
7515
- this.inputs.isSpacebarPanning = false;
7548
+ this.inputs.setIsDragging(false);
7549
+ if (this.inputs.getIsPanning()) {
7550
+ this.inputs.setIsPanning(false);
7551
+ this.inputs.setIsSpacebarPanning(false);
7516
7552
  this.setCursor({ type: this._prevCursor, rotation: 0 });
7517
7553
  }
7518
7554
  }
7519
7555
  this.root.handleEvent(info);
7556
+ this.emit("event", info);
7520
7557
  return;
7521
7558
  }
7522
7559
  if (info.shiftKey) {
7523
7560
  clearTimeout(this._shiftKeyTimeout);
7524
7561
  this._shiftKeyTimeout = -1;
7525
- inputs.shiftKey = true;
7526
- } else if (!info.shiftKey && inputs.shiftKey && this._shiftKeyTimeout === -1) {
7562
+ inputs.setShiftKey(true);
7563
+ } else if (!info.shiftKey && inputs.getShiftKey() && this._shiftKeyTimeout === -1) {
7527
7564
  this._shiftKeyTimeout = this.timers.setTimeout(this._setShiftKeyTimeout, 150);
7528
7565
  }
7529
7566
  if (info.altKey) {
7530
7567
  clearTimeout(this._altKeyTimeout);
7531
7568
  this._altKeyTimeout = -1;
7532
- inputs.altKey = true;
7533
- } else if (!info.altKey && inputs.altKey && this._altKeyTimeout === -1) {
7569
+ inputs.setAltKey(true);
7570
+ } else if (!info.altKey && inputs.getAltKey() && this._altKeyTimeout === -1) {
7534
7571
  this._altKeyTimeout = this.timers.setTimeout(this._setAltKeyTimeout, 150);
7535
7572
  }
7536
7573
  if (info.ctrlKey) {
7537
7574
  clearTimeout(this._ctrlKeyTimeout);
7538
7575
  this._ctrlKeyTimeout = -1;
7539
- inputs.ctrlKey = true;
7540
- } else if (!info.ctrlKey && inputs.ctrlKey && this._ctrlKeyTimeout === -1) {
7576
+ inputs.setCtrlKey(true);
7577
+ } else if (!info.ctrlKey && inputs.getCtrlKey() && this._ctrlKeyTimeout === -1) {
7541
7578
  this._ctrlKeyTimeout = this.timers.setTimeout(this._setCtrlKeyTimeout, 150);
7542
7579
  }
7543
7580
  if (info.metaKey) {
7544
7581
  clearTimeout(this._metaKeyTimeout);
7545
7582
  this._metaKeyTimeout = -1;
7546
- inputs.metaKey = true;
7547
- } else if (!info.metaKey && inputs.metaKey && this._metaKeyTimeout === -1) {
7583
+ inputs.setMetaKey(true);
7584
+ } else if (!info.metaKey && inputs.getMetaKey() && this._metaKeyTimeout === -1) {
7548
7585
  this._metaKeyTimeout = this.timers.setTimeout(this._setMetaKeyTimeout, 150);
7549
7586
  }
7550
- const { originPagePoint, currentPagePoint } = inputs;
7551
- if (!inputs.isPointing) {
7552
- inputs.isDragging = false;
7587
+ if (!inputs.getIsPointing()) {
7588
+ inputs.setIsDragging(false);
7553
7589
  }
7554
7590
  const instanceState = this.store.unsafeGetWithoutCapture(TLINSTANCE_ID);
7555
7591
  const pageState = this.store.get(this._getCurrentPageStateId());
@@ -7558,23 +7594,23 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7558
7594
  case "pinch": {
7559
7595
  if (cameraOptions.isLocked) return;
7560
7596
  clearTimeout(this._longPressTimeout);
7561
- this._updateInputsFromEvent(info);
7597
+ this.inputs.updateFromEvent(info);
7562
7598
  switch (info.name) {
7563
7599
  case "pinch_start": {
7564
- if (inputs.isPinching) return;
7565
- if (!inputs.isEditing) {
7566
- this._pinchStart = this.getCamera().z;
7600
+ if (inputs.getIsPinching()) return;
7601
+ if (!inputs.getIsEditing()) {
7567
7602
  if (!this._selectedShapeIdsAtPointerDown.length) {
7568
7603
  this._selectedShapeIdsAtPointerDown = [...pageState.selectedShapeIds];
7569
7604
  }
7570
7605
  this._didPinch = true;
7571
- inputs.isPinching = true;
7606
+ inputs.setIsPinching(true);
7572
7607
  this.interrupt();
7573
7608
  }
7609
+ this.emit("event", info);
7574
7610
  return;
7575
7611
  }
7576
7612
  case "pinch": {
7577
- if (!inputs.isPinching) return;
7613
+ if (!inputs.getIsPinching()) return;
7578
7614
  const {
7579
7615
  point: { z = 1 },
7580
7616
  delta: { x: dx, y: dy }
@@ -7598,11 +7634,12 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7598
7634
  ),
7599
7635
  { immediate: true }
7600
7636
  );
7637
+ this.emit("event", info);
7601
7638
  return;
7602
7639
  }
7603
7640
  case "pinch_end": {
7604
- if (!inputs.isPinching) return this;
7605
- inputs.isPinching = false;
7641
+ if (!inputs.getIsPinching()) return this;
7642
+ inputs.setIsPinching(false);
7606
7643
  const { _selectedShapeIdsAtPointerDown: shapesToReselect } = this;
7607
7644
  this.setSelectedShapes(this._selectedShapeIdsAtPointerDown);
7608
7645
  this._selectedShapeIdsAtPointerDown = [];
@@ -7616,13 +7653,14 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7616
7653
  });
7617
7654
  }
7618
7655
  }
7656
+ this.emit("event", info);
7619
7657
  return;
7620
7658
  }
7621
7659
  }
7622
7660
  }
7623
7661
  case "wheel": {
7624
7662
  if (cameraOptions.isLocked) return;
7625
- this._updateInputsFromEvent(info);
7663
+ this.inputs.updateFromEvent(info);
7626
7664
  const { panSpeed, zoomSpeed } = cameraOptions;
7627
7665
  let wheelBehavior = cameraOptions.wheelBehavior;
7628
7666
  const inputMode = this.user.getUserPreferences().inputMode;
@@ -7640,7 +7678,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7640
7678
  if (info.ctrlKey) behavior = wheelBehavior === "pan" ? "zoom" : "pan";
7641
7679
  switch (behavior) {
7642
7680
  case "zoom": {
7643
- const { x, y } = this.inputs.currentScreenPoint;
7681
+ const { x, y } = this.inputs.getCurrentScreenPoint();
7644
7682
  let delta = dz;
7645
7683
  if (wheelBehavior === "zoom") {
7646
7684
  if (Math.abs(dy) > 10) {
@@ -7654,6 +7692,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7654
7692
  immediate: true
7655
7693
  });
7656
7694
  this.maybeTrackPerformance("Zooming");
7695
+ this.root.handleEvent(info);
7696
+ this.emit("event", info);
7657
7697
  return;
7658
7698
  }
7659
7699
  case "pan": {
@@ -7661,6 +7701,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7661
7701
  immediate: true
7662
7702
  });
7663
7703
  this.maybeTrackPerformance("Panning");
7704
+ this.root.handleEvent(info);
7705
+ this.emit("event", info);
7664
7706
  return;
7665
7707
  }
7666
7708
  }
@@ -7668,14 +7710,14 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7668
7710
  break;
7669
7711
  }
7670
7712
  case "pointer": {
7671
- if (inputs.isPinching) return;
7672
- this._updateInputsFromEvent(info);
7713
+ if (inputs.getIsPinching()) return;
7714
+ this.inputs.updateFromEvent(info);
7673
7715
  const { isPen } = info;
7674
7716
  const { isPenMode } = instanceState;
7675
7717
  switch (info.name) {
7676
7718
  case "pointer_down": {
7677
7719
  if (isPenMode && !isPen) return;
7678
- if (!this.inputs.isPanning) {
7720
+ if (!this.inputs.getIsPanning()) {
7679
7721
  this._longPressTimeout = this.timers.setTimeout(() => {
7680
7722
  const vsb = this.getViewportScreenBounds();
7681
7723
  this.dispatch({
@@ -7684,7 +7726,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7684
7726
  // viewport bounds, and will be again when this event is handled...
7685
7727
  // so we need to counter-adjust from the stored value so that the
7686
7728
  // new value is set correctly.
7687
- point: this.inputs.originScreenPoint.clone().addXY(vsb.x, vsb.y),
7729
+ point: this.inputs.getOriginScreenPoint().clone().addXY(vsb.x, vsb.y),
7688
7730
  name: "long_press"
7689
7731
  });
7690
7732
  }, this.options.longPressDurationMs);
@@ -7692,21 +7734,21 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7692
7734
  this._selectedShapeIdsAtPointerDown = this.getSelectedShapeIds();
7693
7735
  if (info.button === LEFT_MOUSE_BUTTON) this.capturedPointerId = info.pointerId;
7694
7736
  inputs.buttons.add(info.button);
7695
- inputs.isPointing = true;
7696
- inputs.isDragging = false;
7737
+ inputs.setIsPointing(true);
7738
+ inputs.setIsDragging(false);
7697
7739
  if (!isPenMode && isPen) this.updateInstanceState({ isPenMode: true });
7698
7740
  if (info.button === STYLUS_ERASER_BUTTON) {
7699
7741
  this._restoreToolId = this.getCurrentToolId();
7700
7742
  this.complete();
7701
7743
  this.setCurrentTool("eraser");
7702
7744
  } else if (info.button === MIDDLE_MOUSE_BUTTON) {
7703
- if (!this.inputs.isPanning) {
7745
+ if (!this.inputs.getIsPanning()) {
7704
7746
  this._prevCursor = this.getInstanceState().cursor.type;
7705
7747
  }
7706
- this.inputs.isPanning = true;
7748
+ this.inputs.setIsPanning(true);
7707
7749
  clearTimeout(this._longPressTimeout);
7708
7750
  }
7709
- if (this.inputs.isPanning) {
7751
+ if (this.inputs.getIsPanning()) {
7710
7752
  this.stopCameraAnimation();
7711
7753
  this.setCursor({ type: "grabbing", rotation: 0 });
7712
7754
  return this;
@@ -7716,8 +7758,9 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7716
7758
  case "pointer_move": {
7717
7759
  if (!isPen && isPenMode) return;
7718
7760
  const { x: cx, y: cy, z: cz } = unsafe__withoutCapture(() => this.getCamera());
7719
- if (this.inputs.isPanning && this.inputs.isPointing) {
7720
- const { currentScreenPoint, previousScreenPoint } = this.inputs;
7761
+ if (this.inputs.getIsPanning() && this.inputs.getIsPointing()) {
7762
+ const currentScreenPoint = this.inputs.getCurrentScreenPoint();
7763
+ const previousScreenPoint = this.inputs.getPreviousScreenPoint();
7721
7764
  const offset = Vec.Sub(currentScreenPoint, previousScreenPoint);
7722
7765
  this.setCamera(new Vec(cx + offset.x / cz, cy + offset.y / cz, cz), {
7723
7766
  immediate: true
@@ -7725,15 +7768,15 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7725
7768
  this.maybeTrackPerformance("Panning");
7726
7769
  return;
7727
7770
  }
7728
- if (inputs.isPointing && !inputs.isDragging && Vec.Dist2(originPagePoint, currentPagePoint) * this.getZoomLevel() > (instanceState.isCoarsePointer ? this.options.coarseDragDistanceSquared : this.options.dragDistanceSquared) / cz) {
7729
- inputs.isDragging = true;
7771
+ if (inputs.getIsPointing() && !inputs.getIsDragging() && Vec.Dist2(inputs.getOriginPagePoint(), inputs.getCurrentPagePoint()) * this.getZoomLevel() > (instanceState.isCoarsePointer ? this.options.coarseDragDistanceSquared : this.options.dragDistanceSquared) / cz) {
7772
+ inputs.setIsDragging(true);
7730
7773
  clearTimeout(this._longPressTimeout);
7731
7774
  }
7732
7775
  break;
7733
7776
  }
7734
7777
  case "pointer_up": {
7735
- inputs.isDragging = false;
7736
- inputs.isPointing = false;
7778
+ inputs.setIsDragging(false);
7779
+ inputs.setIsPointing(false);
7737
7780
  clearTimeout(this._longPressTimeout);
7738
7781
  inputs.buttons.delete(info.button);
7739
7782
  if (instanceState.isPenMode && !isPen) return;
@@ -7741,12 +7784,12 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7741
7784
  this.capturedPointerId = null;
7742
7785
  info.button = 0;
7743
7786
  }
7744
- if (inputs.isPanning) {
7787
+ if (inputs.getIsPanning()) {
7745
7788
  if (!inputs.keys.has("Space")) {
7746
- inputs.isPanning = false;
7747
- inputs.isSpacebarPanning = false;
7789
+ inputs.setIsPanning(false);
7790
+ inputs.setIsSpacebarPanning(false);
7748
7791
  }
7749
- const slideDirection = this.inputs.pointerVelocity;
7792
+ const slideDirection = this.inputs.getPointerVelocity();
7750
7793
  const slideSpeed = Math.min(2, slideDirection.len());
7751
7794
  switch (info.button) {
7752
7795
  case LEFT_MOUSE_BUTTON: {
@@ -7783,51 +7826,58 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7783
7826
  switch (info.name) {
7784
7827
  case "key_down": {
7785
7828
  inputs.keys.add(info.code);
7786
- if (info.code === "Space" && !info.ctrlKey) {
7787
- if (!this.inputs.isPanning) {
7788
- this._prevCursor = instanceState.cursor.type;
7789
- }
7790
- this.inputs.isPanning = true;
7791
- this.inputs.isSpacebarPanning = true;
7792
- clearTimeout(this._longPressTimeout);
7793
- this.setCursor({ type: this.inputs.isPointing ? "grabbing" : "grab", rotation: 0 });
7794
- }
7795
- if (this.inputs.isSpacebarPanning) {
7796
- let offset;
7797
- switch (info.code) {
7798
- case "ArrowUp": {
7799
- offset = new Vec(0, -1);
7800
- break;
7801
- }
7802
- case "ArrowRight": {
7803
- offset = new Vec(1, 0);
7804
- break;
7829
+ if (this.options.spacebarPanning) {
7830
+ if (info.code === "Space" && !info.ctrlKey) {
7831
+ if (!this.inputs.getIsPanning()) {
7832
+ this._prevCursor = instanceState.cursor.type;
7805
7833
  }
7806
- case "ArrowDown": {
7807
- offset = new Vec(0, 1);
7808
- break;
7834
+ this.inputs.setIsPanning(true);
7835
+ this.inputs.setIsSpacebarPanning(true);
7836
+ clearTimeout(this._longPressTimeout);
7837
+ this.setCursor({
7838
+ type: this.inputs.getIsPointing() ? "grabbing" : "grab",
7839
+ rotation: 0
7840
+ });
7841
+ }
7842
+ if (this.inputs.getIsSpacebarPanning()) {
7843
+ let offset;
7844
+ switch (info.code) {
7845
+ case "ArrowUp": {
7846
+ offset = new Vec(0, -1);
7847
+ break;
7848
+ }
7849
+ case "ArrowRight": {
7850
+ offset = new Vec(1, 0);
7851
+ break;
7852
+ }
7853
+ case "ArrowDown": {
7854
+ offset = new Vec(0, 1);
7855
+ break;
7856
+ }
7857
+ case "ArrowLeft": {
7858
+ offset = new Vec(-1, 0);
7859
+ break;
7860
+ }
7809
7861
  }
7810
- case "ArrowLeft": {
7811
- offset = new Vec(-1, 0);
7812
- break;
7862
+ if (offset) {
7863
+ const bounds = this.getViewportPageBounds();
7864
+ const next = bounds.clone().translate(offset.mulV({ x: bounds.w, y: bounds.h }));
7865
+ this._animateToViewport(next, { animation: { duration: 320 } });
7813
7866
  }
7814
7867
  }
7815
- if (offset) {
7816
- const bounds = this.getViewportPageBounds();
7817
- const next = bounds.clone().translate(offset.mulV({ x: bounds.w, y: bounds.h }));
7818
- this._animateToViewport(next, { animation: { duration: 320 } });
7819
- }
7820
7868
  }
7821
7869
  break;
7822
7870
  }
7823
7871
  case "key_up": {
7824
7872
  inputs.keys.delete(info.code);
7825
- if (info.code === "Space") {
7826
- if (this.inputs.buttons.has(MIDDLE_MOUSE_BUTTON)) {
7827
- } else {
7828
- this.inputs.isPanning = false;
7829
- this.inputs.isSpacebarPanning = false;
7830
- this.setCursor({ type: this._prevCursor, rotation: 0 });
7873
+ if (this.options.spacebarPanning) {
7874
+ if (info.code === "Space") {
7875
+ if (this.inputs.buttons.has(MIDDLE_MOUSE_BUTTON)) {
7876
+ } else {
7877
+ this.inputs.setIsPanning(false);
7878
+ this.inputs.setIsSpacebarPanning(false);
7879
+ this.setCursor({ type: this._prevCursor, rotation: 0 });
7880
+ }
7831
7881
  }
7832
7882
  }
7833
7883
  break;
@@ -7880,8 +7930,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
7880
7930
  }
7881
7931
  _init = __decoratorStart(_a);
7882
7932
  __decorateElement(_init, 1, "getIsShapeHiddenCache", _getIsShapeHiddenCache_dec, Editor);
7883
- __decorateElement(_init, 1, "getCanUndo", _getCanUndo_dec, Editor);
7884
- __decorateElement(_init, 1, "getCanRedo", _getCanRedo_dec, Editor);
7933
+ __decorateElement(_init, 1, "canUndo", _canUndo_dec, Editor);
7934
+ __decorateElement(_init, 1, "canRedo", _canRedo_dec, Editor);
7885
7935
  __decorateElement(_init, 1, "getPath", _getPath_dec, Editor);
7886
7936
  __decorateElement(_init, 1, "getCurrentTool", _getCurrentTool_dec, Editor);
7887
7937
  __decorateElement(_init, 1, "getCurrentToolId", _getCurrentToolId_dec, Editor);
@@ -7916,6 +7966,9 @@ __decorateElement(_init, 1, "getCamera", _getCamera_dec, Editor);
7916
7966
  __decorateElement(_init, 1, "getViewportPageBoundsForFollowing", _getViewportPageBoundsForFollowing_dec, Editor);
7917
7967
  __decorateElement(_init, 1, "getCameraForFollowing", _getCameraForFollowing_dec, Editor);
7918
7968
  __decorateElement(_init, 1, "getZoomLevel", _getZoomLevel_dec, Editor);
7969
+ __decorateElement(_init, 1, "getDebouncedZoomLevel", _getDebouncedZoomLevel_dec, Editor);
7970
+ __decorateElement(_init, 1, "_getAboveDebouncedZoomThreshold", __getAboveDebouncedZoomThreshold_dec, Editor);
7971
+ __decorateElement(_init, 1, "getEfficientZoomLevel", _getEfficientZoomLevel_dec, Editor);
7919
7972
  __decorateElement(_init, 1, "getViewportScreenBounds", _getViewportScreenBounds_dec, Editor);
7920
7973
  __decorateElement(_init, 1, "getViewportScreenCenter", _getViewportScreenCenter_dec, Editor);
7921
7974
  __decorateElement(_init, 1, "getViewportPageBounds", _getViewportPageBounds_dec, Editor);