@tldraw/editor 4.3.0-canary.2362fd2ebe56 → 4.3.0-canary.2643056dfc8d

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 (177) hide show
  1. package/dist-cjs/index.d.ts +537 -120
  2. package/dist-cjs/index.js +8 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/components/ErrorBoundary.js.map +1 -1
  5. package/dist-cjs/lib/components/GeometryDebuggingView.js +1 -17
  6. package/dist-cjs/lib/components/GeometryDebuggingView.js.map +2 -2
  7. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +4 -5
  8. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  9. package/dist-cjs/lib/constants.js +1 -3
  10. package/dist-cjs/lib/constants.js.map +2 -2
  11. package/dist-cjs/lib/editor/Editor.js +349 -280
  12. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  13. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +16 -23
  14. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +3 -3
  15. package/dist-cjs/lib/editor/derivations/parentsToChildren.js +12 -3
  16. package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
  17. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +1 -1
  18. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
  19. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +5 -6
  20. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
  21. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +591 -0
  22. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +7 -0
  23. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +1 -1
  24. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
  25. package/dist-cjs/lib/editor/managers/SpatialIndexManager/RBushIndex.js +144 -0
  26. package/dist-cjs/lib/editor/managers/SpatialIndexManager/RBushIndex.js.map +7 -0
  27. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +181 -0
  28. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +7 -0
  29. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +1 -22
  30. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +2 -2
  31. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +31 -23
  32. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  33. package/dist-cjs/lib/editor/shapes/group/DashedOutlineBox.js +1 -1
  34. package/dist-cjs/lib/editor/shapes/group/DashedOutlineBox.js.map +2 -2
  35. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +3 -3
  36. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
  37. package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
  38. package/dist-cjs/lib/exports/parseCss.js +1 -1
  39. package/dist-cjs/lib/exports/parseCss.js.map +2 -2
  40. package/dist-cjs/lib/globals/environment.js +45 -9
  41. package/dist-cjs/lib/globals/environment.js.map +2 -2
  42. package/dist-cjs/lib/hooks/useCoarsePointer.js +14 -29
  43. package/dist-cjs/lib/hooks/useCoarsePointer.js.map +2 -2
  44. package/dist-cjs/lib/hooks/useEvent.js +1 -1
  45. package/dist-cjs/lib/hooks/useEvent.js.map +2 -2
  46. package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
  47. package/dist-cjs/lib/hooks/useGestureEvents.js +1 -1
  48. package/dist-cjs/lib/hooks/useGestureEvents.js.map +2 -2
  49. package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +2 -2
  50. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
  51. package/dist-cjs/lib/hooks/useScreenBounds.js.map +2 -2
  52. package/dist-cjs/lib/hooks/useStateAttribute.js +4 -1
  53. package/dist-cjs/lib/hooks/useStateAttribute.js.map +2 -2
  54. package/dist-cjs/lib/hooks/useTransform.js.map +1 -1
  55. package/dist-cjs/lib/hooks/useZoomCss.js +4 -8
  56. package/dist-cjs/lib/hooks/useZoomCss.js.map +2 -2
  57. package/dist-cjs/lib/options.js +6 -1
  58. package/dist-cjs/lib/options.js.map +2 -2
  59. package/dist-cjs/lib/primitives/Box.js +3 -0
  60. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  61. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +1 -0
  62. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  63. package/dist-cjs/lib/utils/rotation.js +1 -1
  64. package/dist-cjs/lib/utils/rotation.js.map +2 -2
  65. package/dist-cjs/version.js +3 -3
  66. package/dist-cjs/version.js.map +1 -1
  67. package/dist-esm/index.d.mts +537 -120
  68. package/dist-esm/index.mjs +9 -2
  69. package/dist-esm/index.mjs.map +2 -2
  70. package/dist-esm/lib/components/ErrorBoundary.mjs.map +1 -1
  71. package/dist-esm/lib/components/GeometryDebuggingView.mjs +1 -17
  72. package/dist-esm/lib/components/GeometryDebuggingView.mjs.map +2 -2
  73. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +4 -5
  74. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  75. package/dist-esm/lib/constants.mjs +1 -3
  76. package/dist-esm/lib/constants.mjs.map +2 -2
  77. package/dist-esm/lib/editor/Editor.mjs +350 -283
  78. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  79. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +16 -23
  80. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +3 -3
  81. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +13 -4
  82. package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
  83. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +1 -1
  84. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
  85. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +5 -6
  86. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
  87. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +573 -0
  88. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +7 -0
  89. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +1 -1
  90. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
  91. package/dist-esm/lib/editor/managers/SpatialIndexManager/RBushIndex.mjs +114 -0
  92. package/dist-esm/lib/editor/managers/SpatialIndexManager/RBushIndex.mjs.map +7 -0
  93. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +161 -0
  94. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +7 -0
  95. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +1 -22
  96. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +2 -2
  97. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +31 -23
  98. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  99. package/dist-esm/lib/editor/shapes/group/DashedOutlineBox.mjs +1 -1
  100. package/dist-esm/lib/editor/shapes/group/DashedOutlineBox.mjs.map +2 -2
  101. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +3 -3
  102. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
  103. package/dist-esm/lib/exports/parseCss.mjs +1 -1
  104. package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
  105. package/dist-esm/lib/globals/environment.mjs +45 -9
  106. package/dist-esm/lib/globals/environment.mjs.map +2 -2
  107. package/dist-esm/lib/hooks/useCoarsePointer.mjs +15 -30
  108. package/dist-esm/lib/hooks/useCoarsePointer.mjs.map +2 -2
  109. package/dist-esm/lib/hooks/useEvent.mjs +1 -1
  110. package/dist-esm/lib/hooks/useEvent.mjs.map +2 -2
  111. package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
  112. package/dist-esm/lib/hooks/useGestureEvents.mjs +1 -1
  113. package/dist-esm/lib/hooks/useGestureEvents.mjs.map +2 -2
  114. package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +2 -2
  115. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
  116. package/dist-esm/lib/hooks/useScreenBounds.mjs.map +2 -2
  117. package/dist-esm/lib/hooks/useStateAttribute.mjs +4 -1
  118. package/dist-esm/lib/hooks/useStateAttribute.mjs.map +2 -2
  119. package/dist-esm/lib/hooks/useTransform.mjs.map +1 -1
  120. package/dist-esm/lib/hooks/useZoomCss.mjs +4 -8
  121. package/dist-esm/lib/hooks/useZoomCss.mjs.map +2 -2
  122. package/dist-esm/lib/options.mjs +6 -1
  123. package/dist-esm/lib/options.mjs.map +2 -2
  124. package/dist-esm/lib/primitives/Box.mjs +3 -0
  125. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  126. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +1 -0
  127. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  128. package/dist-esm/lib/utils/rotation.mjs +1 -1
  129. package/dist-esm/lib/utils/rotation.mjs.map +2 -2
  130. package/dist-esm/version.mjs +3 -3
  131. package/dist-esm/version.mjs.map +1 -1
  132. package/editor.css +14 -12
  133. package/package.json +21 -17
  134. package/src/index.ts +5 -1
  135. package/src/lib/components/ErrorBoundary.tsx +1 -1
  136. package/src/lib/components/GeometryDebuggingView.tsx +1 -19
  137. package/src/lib/components/default-components/DefaultCanvas.tsx +5 -8
  138. package/src/lib/config/TLUserPreferences.test.ts +40 -0
  139. package/src/lib/constants.ts +0 -2
  140. package/src/lib/editor/Editor.test.ts +140 -0
  141. package/src/lib/editor/Editor.ts +455 -326
  142. package/src/lib/editor/derivations/notVisibleShapes.ts +21 -33
  143. package/src/lib/editor/derivations/parentsToChildren.ts +18 -7
  144. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +17 -31
  145. package/src/lib/editor/managers/ClickManager/ClickManager.ts +1 -1
  146. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +129 -79
  147. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +10 -6
  148. package/src/lib/editor/managers/InputsManager/InputsManager.ts +566 -0
  149. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +0 -4
  150. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +12 -0
  151. package/src/lib/editor/managers/SnapManager/SnapManager.ts +1 -1
  152. package/src/lib/editor/managers/SpatialIndexManager/RBushIndex.ts +144 -0
  153. package/src/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.ts +215 -0
  154. package/src/lib/editor/managers/TickManager/TickManager.test.ts +40 -107
  155. package/src/lib/editor/managers/TickManager/TickManager.ts +2 -32
  156. package/src/lib/editor/shapes/ShapeUtil.ts +67 -24
  157. package/src/lib/editor/shapes/group/DashedOutlineBox.tsx +1 -1
  158. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +3 -3
  159. package/src/lib/editor/types/emit-types.ts +3 -1
  160. package/src/lib/exports/parseCss.test.ts +1 -0
  161. package/src/lib/exports/parseCss.ts +1 -1
  162. package/src/lib/globals/environment.ts +65 -10
  163. package/src/lib/hooks/useCoarsePointer.ts +16 -59
  164. package/src/lib/hooks/useEvent.tsx +1 -1
  165. package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +1 -1
  166. package/src/lib/hooks/useGestureEvents.ts +2 -2
  167. package/src/lib/hooks/usePassThroughMouseOverEvents.ts +1 -1
  168. package/src/lib/hooks/usePassThroughWheelEvents.ts +1 -1
  169. package/src/lib/hooks/useScreenBounds.ts +1 -1
  170. package/src/lib/hooks/useStateAttribute.ts +4 -1
  171. package/src/lib/hooks/useTransform.ts +1 -1
  172. package/src/lib/hooks/useZoomCss.ts +3 -8
  173. package/src/lib/options.ts +32 -0
  174. package/src/lib/primitives/Box.ts +9 -0
  175. package/src/lib/primitives/geometry/Geometry2d.ts +1 -0
  176. package/src/lib/utils/rotation.ts +1 -1
  177. package/src/version.ts +3 -3
@@ -104,7 +104,6 @@ var import_assets = require("../utils/assets");
104
104
  var import_debug_flags = require("../utils/debug-flags");
105
105
  var import_deepLinks = require("../utils/deepLinks");
106
106
  var import_getIncrementedName = require("../utils/getIncrementedName");
107
- var import_keyboard = require("../utils/keyboard");
108
107
  var import_reorderShapes = require("../utils/reorderShapes");
109
108
  var import_rotation = require("../utils/rotation");
110
109
  var import_bindingsIndex = require("./derivations/bindingsIndex");
@@ -116,14 +115,16 @@ var import_EdgeScrollManager = require("./managers/EdgeScrollManager/EdgeScrollM
116
115
  var import_FocusManager = require("./managers/FocusManager/FocusManager");
117
116
  var import_FontManager = require("./managers/FontManager/FontManager");
118
117
  var import_HistoryManager = require("./managers/HistoryManager/HistoryManager");
118
+ var import_InputsManager = require("./managers/InputsManager/InputsManager");
119
119
  var import_ScribbleManager = require("./managers/ScribbleManager/ScribbleManager");
120
120
  var import_SnapManager = require("./managers/SnapManager/SnapManager");
121
+ var import_SpatialIndexManager = require("./managers/SpatialIndexManager/SpatialIndexManager");
121
122
  var import_TextManager = require("./managers/TextManager/TextManager");
122
123
  var import_TickManager = require("./managers/TickManager/TickManager");
123
124
  var import_UserPreferencesManager = require("./managers/UserPreferencesManager/UserPreferencesManager");
124
125
  var import_RootState = require("./tools/RootState");
125
- 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;
126
- class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_dec = [import_state.computed], _getCanUndo_dec = [import_state.computed], _getCanRedo_dec = [import_state.computed], _getPath_dec = [import_state.computed], _getCurrentTool_dec = [import_state.computed], _getCurrentToolId_dec = [import_state.computed], _getDocumentSettings_dec = [import_state.computed], _getInstanceState_dec = [import_state.computed], _getPageStates_dec = [import_state.computed], __getPageStatesQuery_dec = [import_state.computed], _getCurrentPageState_dec = [import_state.computed], __getCurrentPageStateId_dec = [import_state.computed], _getSelectedShapeIds_dec = [import_state.computed], _getSelectedShapes_dec = [import_state.computed], _getCurrentPageShapesInReadingOrder_dec = [import_state.computed], _getOnlySelectedShapeId_dec = [import_state.computed], _getOnlySelectedShape_dec = [import_state.computed], _getSelectionPageBounds_dec = [import_state.computed], _getSelectionRotation_dec = [import_state.computed], _getSelectionRotatedPageBounds_dec = [import_state.computed], _getSelectionRotatedScreenBounds_dec = [import_state.computed], _getFocusedGroupId_dec = [import_state.computed], _getFocusedGroup_dec = [import_state.computed], _getEditingShapeId_dec = [import_state.computed], _getEditingShape_dec = [import_state.computed], _getRichTextEditor_dec = [import_state.computed], _getHoveredShapeId_dec = [import_state.computed], _getHoveredShape_dec = [import_state.computed], _getHintingShapeIds_dec = [import_state.computed], _getHintingShape_dec = [import_state.computed], _getErasingShapeIds_dec = [import_state.computed], _getErasingShapes_dec = [import_state.computed], __unsafe_getCameraId_dec = [import_state.computed], _getCamera_dec = [import_state.computed], _getViewportPageBoundsForFollowing_dec = [import_state.computed], _getCameraForFollowing_dec = [import_state.computed], _getZoomLevel_dec = [import_state.computed], _getViewportScreenBounds_dec = [import_state.computed], _getViewportScreenCenter_dec = [import_state.computed], _getViewportPageBounds_dec = [import_state.computed], __getCollaboratorsQuery_dec = [import_state.computed], _getCollaborators_dec = [import_state.computed], _getCollaboratorsOnCurrentPage_dec = [import_state.computed], _getRenderingShapes_dec = [import_state.computed], __getAllPagesQuery_dec = [import_state.computed], _getPages_dec = [import_state.computed], _getCurrentPageId_dec = [import_state.computed], _getCurrentPageShapeIdsSorted_dec = [import_state.computed], __getAllAssetsQuery_dec = [import_state.computed], __getShapeHandlesCache_dec = [import_state.computed], __getShapePageTransformCache_dec = [import_state.computed], __getShapePageBoundsCache_dec = [import_state.computed], __getShapeClipPathCache_dec = [import_state.computed], __getShapeMaskCache_dec = [import_state.computed], __getShapeMaskedPageBoundsCache_dec = [import_state.computed], _getNotVisibleShapes_dec = [import_state.computed], _getCulledShapes_dec = [import_state.computed], _getCurrentPageBounds_dec = [import_state.computed], _getCurrentPageShapes_dec = [import_state.computed], _getCurrentPageShapesSorted_dec = [import_state.computed], _getCurrentPageRenderingShapesSorted_dec = [import_state.computed], __getBindingsIndexCache_dec = [import_state.computed], __getSelectionSharedStyles_dec = [import_state.computed], _getSharedStyles_dec = [(0, import_state.computed)({ isEqual: (a, b) => a.equals(b) })], _getSharedOpacity_dec = [import_state.computed], _getIsFocused_dec = [import_state.computed], _getIsReadonly_dec = [import_state.computed], __setShiftKeyTimeout_dec = [import_utils.bind], __setAltKeyTimeout_dec = [import_utils.bind], __setCtrlKeyTimeout_dec = [import_utils.bind], __setMetaKeyTimeout_dec = [import_utils.bind], _a) {
126
+ 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;
127
+ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_dec = [import_state.computed], _canUndo_dec = [import_state.computed], _canRedo_dec = [import_state.computed], _getPath_dec = [import_state.computed], _getCurrentTool_dec = [import_state.computed], _getCurrentToolId_dec = [import_state.computed], _getDocumentSettings_dec = [import_state.computed], _getInstanceState_dec = [import_state.computed], _getPageStates_dec = [import_state.computed], __getPageStatesQuery_dec = [import_state.computed], _getCurrentPageState_dec = [import_state.computed], __getCurrentPageStateId_dec = [import_state.computed], _getSelectedShapeIds_dec = [import_state.computed], _getSelectedShapes_dec = [import_state.computed], _getCurrentPageShapesInReadingOrder_dec = [import_state.computed], _getOnlySelectedShapeId_dec = [import_state.computed], _getOnlySelectedShape_dec = [import_state.computed], _getSelectionPageBounds_dec = [import_state.computed], _getSelectionRotation_dec = [import_state.computed], _getSelectionRotatedPageBounds_dec = [import_state.computed], _getSelectionRotatedScreenBounds_dec = [import_state.computed], _getFocusedGroupId_dec = [import_state.computed], _getFocusedGroup_dec = [import_state.computed], _getEditingShapeId_dec = [import_state.computed], _getEditingShape_dec = [import_state.computed], _getRichTextEditor_dec = [import_state.computed], _getHoveredShapeId_dec = [import_state.computed], _getHoveredShape_dec = [import_state.computed], _getHintingShapeIds_dec = [import_state.computed], _getHintingShape_dec = [import_state.computed], _getErasingShapeIds_dec = [import_state.computed], _getErasingShapes_dec = [import_state.computed], __unsafe_getCameraId_dec = [import_state.computed], _getCamera_dec = [import_state.computed], _getViewportPageBoundsForFollowing_dec = [import_state.computed], _getCameraForFollowing_dec = [import_state.computed], _getZoomLevel_dec = [import_state.computed], _getDebouncedZoomLevel_dec = [import_state.computed], __getAboveDebouncedZoomThreshold_dec = [import_state.computed], _getEfficientZoomLevel_dec = [import_state.computed], _getViewportScreenBounds_dec = [import_state.computed], _getViewportScreenCenter_dec = [import_state.computed], _getViewportPageBounds_dec = [import_state.computed], __getCollaboratorsQuery_dec = [import_state.computed], _getCollaborators_dec = [import_state.computed], _getCollaboratorsOnCurrentPage_dec = [import_state.computed], _getRenderingShapes_dec = [import_state.computed], __getAllPagesQuery_dec = [import_state.computed], _getPages_dec = [import_state.computed], _getCurrentPageId_dec = [import_state.computed], _getCurrentPageShapeIdsSorted_dec = [import_state.computed], __getAllAssetsQuery_dec = [import_state.computed], __getShapeHandlesCache_dec = [import_state.computed], __getShapePageTransformCache_dec = [import_state.computed], __getShapePageBoundsCache_dec = [import_state.computed], __getShapeClipPathCache_dec = [import_state.computed], __getShapeMaskCache_dec = [import_state.computed], __getShapeMaskedPageBoundsCache_dec = [import_state.computed], _getNotVisibleShapes_dec = [import_state.computed], _getCulledShapes_dec = [import_state.computed], _getCurrentPageBounds_dec = [import_state.computed], _getCurrentPageShapes_dec = [import_state.computed], _getCurrentPageShapesSorted_dec = [import_state.computed], _getCurrentPageRenderingShapesSorted_dec = [import_state.computed], __getBindingsIndexCache_dec = [import_state.computed], __getSelectionSharedStyles_dec = [import_state.computed], _getSharedStyles_dec = [(0, import_state.computed)({ isEqual: (a, b) => a.equals(b) })], _getSharedOpacity_dec = [import_state.computed], _getIsFocused_dec = [import_state.computed], _getIsReadonly_dec = [import_state.computed], __setShiftKeyTimeout_dec = [import_utils.bind], __setAltKeyTimeout_dec = [import_utils.bind], __setCtrlKeyTimeout_dec = [import_utils.bind], __setMetaKeyTimeout_dec = [import_utils.bind], _a) {
127
128
  constructor({
128
129
  store,
129
130
  user,
@@ -159,7 +160,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
159
160
  */
160
161
  __publicField(this, "root");
161
162
  /**
162
- * A set of functions to call when the app is disposed.
163
+ * A set of functions to call when the editor is disposed.
163
164
  *
164
165
  * @public
165
166
  */
@@ -170,14 +171,29 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
170
171
  * @public
171
172
  */
172
173
  __publicField(this, "isDisposed", false);
173
- /** @internal */
174
+ /**
175
+ * A manager for the editor's tick events.
176
+ *
177
+ * @internal */
174
178
  __publicField(this, "_tickManager");
175
179
  /**
176
- * A manager for the app's snapping feature.
180
+ * A manager for the editor's input state.
181
+ *
182
+ * @public
183
+ */
184
+ __publicField(this, "inputs");
185
+ /**
186
+ * A manager for the editor's snapping feature.
177
187
  *
178
188
  * @public
179
189
  */
180
190
  __publicField(this, "snaps");
191
+ /**
192
+ * A manager for spatial indexing, enabling efficient shape location queries.
193
+ *
194
+ * @public
195
+ */
196
+ __publicField(this, "spatialIndex");
181
197
  /**
182
198
  * A manager for the any asynchronous events and making sure they're
183
199
  * cleaned up upon disposal.
@@ -255,7 +271,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
255
271
  __publicField(this, "bindingUtils");
256
272
  /* --------------------- History -------------------- */
257
273
  /**
258
- * A manager for the app's history.
274
+ * A manager for the editor's history.
259
275
  *
260
276
  * @readonly
261
277
  */
@@ -270,6 +286,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
270
286
  // Rich text editor
271
287
  __publicField(this, "_currentRichTextEditor", (0, import_state.atom)("rich text editor", null));
272
288
  __publicField(this, "_textOptions");
289
+ __publicField(this, "_debouncedZoomLevel", (0, import_state.atom)("debounced zoom level", 1));
273
290
  __publicField(this, "_cameraOptions", (0, import_state.atom)("camera options", import_constants.DEFAULT_CAMERA_OPTIONS));
274
291
  /** @internal */
275
292
  __publicField(this, "_viewportAnimation", null);
@@ -293,6 +310,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
293
310
  /* --------------------- Shapes --------------------- */
294
311
  __publicField(this, "_shapeGeometryCaches", {});
295
312
  __publicField(this, "_notVisibleShapes", (0, import_notVisibleShapes.notVisibleShapes)(this));
313
+ __publicField(this, "_culledShapesCache", null);
296
314
  // Parents and children
297
315
  /**
298
316
  * A cache of parents to children.
@@ -320,54 +338,6 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
320
338
  tldraw: null,
321
339
  excalidraw: null
322
340
  });
323
- /* --------------------- Events --------------------- */
324
- /**
325
- * The app's current input state.
326
- *
327
- * @public
328
- */
329
- __publicField(this, "inputs", {
330
- /** The most recent pointer down's position in the current page space. */
331
- originPagePoint: new import_Vec.Vec(),
332
- /** The most recent pointer down's position in screen space. */
333
- originScreenPoint: new import_Vec.Vec(),
334
- /** The previous pointer position in the current page space. */
335
- previousPagePoint: new import_Vec.Vec(),
336
- /** The previous pointer position in screen space. */
337
- previousScreenPoint: new import_Vec.Vec(),
338
- /** The most recent pointer position in the current page space. */
339
- currentPagePoint: new import_Vec.Vec(),
340
- /** The most recent pointer position in screen space. */
341
- currentScreenPoint: new import_Vec.Vec(),
342
- /** A set containing the currently pressed keys. */
343
- keys: /* @__PURE__ */ new Set(),
344
- /** A set containing the currently pressed buttons. */
345
- buttons: /* @__PURE__ */ new Set(),
346
- /** Whether the input is from a pe. */
347
- isPen: false,
348
- /** Whether the shift key is currently pressed. */
349
- shiftKey: false,
350
- /** Whether the meta key is currently pressed. */
351
- metaKey: false,
352
- /** Whether the control or command key is currently pressed. */
353
- ctrlKey: false,
354
- /** Whether the alt or option key is currently pressed. */
355
- altKey: false,
356
- /** Whether the user is dragging. */
357
- isDragging: false,
358
- /** Whether the user is pointing. */
359
- isPointing: false,
360
- /** Whether the user is pinching. */
361
- isPinching: false,
362
- /** Whether the user is editing. */
363
- isEditing: false,
364
- /** Whether the user is panning. */
365
- isPanning: false,
366
- /** Whether the user is spacebar panning. */
367
- isSpacebarPanning: false,
368
- /** Velocity of mouse pointer, in pixels per millisecond */
369
- pointerVelocity: new import_Vec.Vec()
370
- });
371
341
  /**
372
342
  * A manager for recording multiple click events.
373
343
  *
@@ -391,8 +361,6 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
391
361
  /** @internal */
392
362
  __publicField(this, "_restoreToolId", "select");
393
363
  /** @internal */
394
- __publicField(this, "_pinchStart", 1);
395
- /** @internal */
396
364
  __publicField(this, "_didPinch", false);
397
365
  /** @internal */
398
366
  __publicField(this, "_selectedShapeIdsAtPointerDown", []);
@@ -418,6 +386,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
418
386
  }
419
387
  });
420
388
  this.snaps = new import_SnapManager.SnapManager(this);
389
+ this.spatialIndex = new import_SpatialIndexManager.SpatialIndexManager(this);
390
+ this.disposables.add(() => this.spatialIndex.dispose());
421
391
  this.disposables.add(this.timers.dispose);
422
392
  this._cameraOptions.set({ ...import_constants.DEFAULT_CAMERA_OPTIONS, ...cameraOptions });
423
393
  this._textOptions = (0, import_state.atom)("text options", textOptions ?? null);
@@ -428,6 +398,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
428
398
  this.disposables.add(() => this.textMeasure.dispose());
429
399
  this.fonts = new import_FontManager.FontManager(this, fontAssetUrls);
430
400
  this._tickManager = new import_TickManager.TickManager(this);
401
+ this.inputs = new import_InputsManager.InputsManager(this);
431
402
  class NewRoot extends import_RootState.RootState {
432
403
  static initial = initialState ?? "";
433
404
  }
@@ -860,6 +831,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
860
831
  this.disposables.clear();
861
832
  this.store.dispose();
862
833
  this.isDisposed = true;
834
+ this.emit("dispose");
863
835
  }
864
836
  getShapeUtil(arg) {
865
837
  const type = typeof arg === "string" ? arg : arg.type;
@@ -893,9 +865,12 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
893
865
  this.history.undo();
894
866
  return this;
895
867
  }
896
- getCanUndo() {
868
+ canUndo() {
897
869
  return this.history.getNumUndos() > 0;
898
870
  }
871
+ getCanUndo() {
872
+ return this.canUndo();
873
+ }
899
874
  /**
900
875
  * Redo to the next mark.
901
876
  *
@@ -912,13 +887,16 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
912
887
  this.history.redo();
913
888
  return this;
914
889
  }
890
+ canRedo() {
891
+ return this.history.getNumRedos() > 0;
892
+ }
893
+ getCanRedo() {
894
+ return this.canRedo();
895
+ }
915
896
  clearHistory() {
916
897
  this.history.clear();
917
898
  return this;
918
899
  }
919
- getCanRedo() {
920
- return this.history.getNumRedos() > 0;
921
- }
922
900
  /**
923
901
  * Create a new "mark", or stopping point, in the undo redo history. Creating a mark will clear
924
902
  * any redos. You typically want to do this just before a user interaction begins or is handled.
@@ -1073,7 +1051,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1073
1051
  }),
1074
1052
  selectionCount: this.getSelectedShapes().length,
1075
1053
  editingShape: editingShapeId ? this.getShape(editingShapeId) : void 0,
1076
- inputs: this.inputs,
1054
+ inputs: this.inputs.toJson(),
1077
1055
  pageState: this.getCurrentPageState(),
1078
1056
  instanceState: this.getInstanceState(),
1079
1057
  collaboratorCount: this.getCollaboratorsOnCurrentPage().length
@@ -1094,7 +1072,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1094
1072
  * we're in a transaction that's about to be rolled back due to the same error we're currently
1095
1073
  * reporting.
1096
1074
  *
1097
- * Instead, to listen to changes to this value, you need to listen to app's `crash` event.
1075
+ * Instead, to listen to changes to this value, you need to listen to editor's `crash` event.
1098
1076
  *
1099
1077
  * @internal
1100
1078
  */
@@ -1745,6 +1723,28 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1745
1723
  const editingShapeId = this.getEditingShapeId();
1746
1724
  return editingShapeId ? this.getShape(editingShapeId) : void 0;
1747
1725
  }
1726
+ /**
1727
+ * Whether the shape can be edited.
1728
+ *
1729
+ * @param shape - The shape (or shape id) to check if it can be edited.
1730
+ * @param info - The info about the edit start.
1731
+ *
1732
+ * @public
1733
+ * @returns true if the shape can be edited, false otherwise.
1734
+ */
1735
+ canEditShape(shape, info) {
1736
+ const id = typeof shape === "string" ? shape : shape?.id ?? null;
1737
+ if (!id) return false;
1738
+ if (id === this.getEditingShapeId()) return false;
1739
+ const _shape = this.getShape(id);
1740
+ if (!_shape) return false;
1741
+ const util = this.getShapeUtil(_shape);
1742
+ const _info = info ?? { type: "unknown" };
1743
+ if (!util.canEdit(_shape, _info)) return false;
1744
+ if (this.getIsReadonly() && !util.canEditInReadonly(_shape)) return false;
1745
+ if (this.isShapeOrAncestorLocked(_shape) && !util.canEditWhileLocked(_shape)) return false;
1746
+ return true;
1747
+ }
1748
1748
  /**
1749
1749
  * Set the current editing shape.
1750
1750
  *
@@ -1760,42 +1760,42 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1760
1760
  */
1761
1761
  setEditingShape(shape) {
1762
1762
  const id = typeof shape === "string" ? shape : shape?.id ?? null;
1763
- this.setRichTextEditor(null);
1764
- const prevEditingShapeId = this.getEditingShapeId();
1765
- if (id !== prevEditingShapeId) {
1766
- if (id) {
1767
- const shape2 = this.getShape(id);
1768
- if (shape2 && this.getShapeUtil(shape2).canEdit(shape2)) {
1769
- this.run(
1770
- () => {
1771
- this._updateCurrentPageState({ editingShapeId: id });
1772
- if (prevEditingShapeId) {
1773
- const prevEditingShape = this.getShape(prevEditingShapeId);
1774
- if (prevEditingShape) {
1775
- this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
1776
- }
1777
- }
1778
- this.getShapeUtil(shape2).onEditStart?.(shape2);
1779
- },
1780
- { history: "ignore" }
1781
- );
1782
- return this;
1783
- }
1784
- }
1763
+ if (!id) {
1785
1764
  this.run(
1786
1765
  () => {
1787
- this._updateCurrentPageState({ editingShapeId: null });
1788
- this._currentRichTextEditor.set(null);
1766
+ const prevEditingShapeId = this.getEditingShapeId();
1789
1767
  if (prevEditingShapeId) {
1790
1768
  const prevEditingShape = this.getShape(prevEditingShapeId);
1791
1769
  if (prevEditingShape) {
1792
1770
  this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
1793
1771
  }
1794
1772
  }
1773
+ this._updateCurrentPageState({ editingShapeId: null });
1774
+ this._currentRichTextEditor.set(null);
1795
1775
  },
1796
1776
  { history: "ignore" }
1797
1777
  );
1778
+ return this;
1798
1779
  }
1780
+ if (!this.canEditShape(id)) return this;
1781
+ this.run(
1782
+ () => {
1783
+ const prevEditingShapeId = this.getEditingShapeId();
1784
+ if (prevEditingShapeId) {
1785
+ const prevEditingShape = this.getShape(prevEditingShapeId);
1786
+ if (prevEditingShape) {
1787
+ this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
1788
+ }
1789
+ }
1790
+ this._updateCurrentPageState({ editingShapeId: null });
1791
+ this._currentRichTextEditor.set(null);
1792
+ this.select(id);
1793
+ this._updateCurrentPageState({ editingShapeId: id });
1794
+ const nextEditingShape = this.getShape(id);
1795
+ this.getShapeUtil(nextEditingShape).onEditStart?.(nextEditingShape);
1796
+ },
1797
+ { history: "ignore" }
1798
+ );
1799
1799
  return this;
1800
1800
  }
1801
1801
  getRichTextEditor() {
@@ -1928,6 +1928,25 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1928
1928
  getCroppingShapeId() {
1929
1929
  return this.getCurrentPageState().croppingShapeId;
1930
1930
  }
1931
+ /**
1932
+ * Whether the shape can be cropped.
1933
+ *
1934
+ * @param shape - The shape (or shape id) to check if it can be cropped.
1935
+ *
1936
+ * @public
1937
+ * @returns true if the shape can be cropped, false otherwise.
1938
+ */
1939
+ canCropShape(shape) {
1940
+ if (!shape) return false;
1941
+ const id = typeof shape === "string" ? shape : shape?.id ?? null;
1942
+ if (!id) return false;
1943
+ const _shape = this.getShape(id);
1944
+ if (!_shape) return false;
1945
+ const util = this.getShapeUtil(_shape);
1946
+ if (!util.canCrop(_shape)) return false;
1947
+ if (this.isShapeOrAncestorLocked(_shape)) return false;
1948
+ return true;
1949
+ }
1931
1950
  /**
1932
1951
  * Set the current cropping shape.
1933
1952
  *
@@ -1949,12 +1968,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1949
1968
  () => {
1950
1969
  if (!id) {
1951
1970
  this.updateCurrentPageState({ croppingShapeId: null });
1952
- } else {
1953
- const shape2 = this.getShape(id);
1954
- const util = this.getShapeUtil(shape2);
1955
- if (shape2 && util.canCrop(shape2)) {
1956
- this.updateCurrentPageState({ croppingShapeId: id });
1957
- }
1971
+ } else if (this.canCropShape(id)) {
1972
+ this.updateCurrentPageState({ croppingShapeId: id });
1958
1973
  }
1959
1974
  },
1960
1975
  { history: "ignore" }
@@ -2029,6 +2044,22 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
2029
2044
  getZoomLevel() {
2030
2045
  return this.getCamera().z;
2031
2046
  }
2047
+ getDebouncedZoomLevel() {
2048
+ if (this.options.debouncedZoom) {
2049
+ if (this.getCameraState() === "idle") {
2050
+ return this.getZoomLevel();
2051
+ } else {
2052
+ return this._debouncedZoomLevel.get();
2053
+ }
2054
+ }
2055
+ return this.getZoomLevel();
2056
+ }
2057
+ _getAboveDebouncedZoomThreshold() {
2058
+ return this.getCurrentPageShapeIds().size > this.options.debouncedZoomThreshold;
2059
+ }
2060
+ getEfficientZoomLevel() {
2061
+ return this._getAboveDebouncedZoomThreshold() ? this.getDebouncedZoomLevel() : this.getZoomLevel();
2062
+ }
2032
2063
  /**
2033
2064
  * Get the camera's initial or reset zoom level.
2034
2065
  *
@@ -2274,7 +2305,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
2274
2305
  },
2275
2306
  { history: "ignore" }
2276
2307
  );
2277
- const { currentScreenPoint, currentPagePoint } = this.inputs;
2308
+ const currentScreenPoint = this.inputs.getCurrentScreenPoint();
2309
+ const currentPagePoint = this.inputs.getCurrentPagePoint();
2278
2310
  if (currentScreenPoint.x / z - x !== currentPagePoint.x || currentScreenPoint.y / z - y !== currentPagePoint.y) {
2279
2311
  this.updatePointer({
2280
2312
  immediate: opts?.immediate,
@@ -2409,7 +2441,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
2409
2441
  * ```ts
2410
2442
  * editor.zoomIn()
2411
2443
  * editor.zoomIn(editor.getViewportScreenCenter(), { animation: { duration: 200 } })
2412
- * editor.zoomIn(editor.inputs.currentScreenPoint, { animation: { duration: 200 } })
2444
+ * editor.zoomIn(editor.inputs.getCurrentScreenPoint(), { animation: { duration: 200 } })
2413
2445
  * ```
2414
2446
  *
2415
2447
  * @param point - The screen point to zoom in on. Defaults to the screen center
@@ -2450,7 +2482,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
2450
2482
  * ```ts
2451
2483
  * editor.zoomOut()
2452
2484
  * editor.zoomOut(editor.getViewportScreenCenter(), { animation: { duration: 120 } })
2453
- * editor.zoomOut(editor.inputs.currentScreenPoint, { animation: { duration: 120 } })
2485
+ * editor.zoomOut(editor.inputs.getCurrentScreenPoint(), { animation: { duration: 120 } })
2454
2486
  * ```
2455
2487
  *
2456
2488
  * @param point - The point to zoom out on. Defaults to the viewport screen center.
@@ -2502,10 +2534,15 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
2502
2534
  if (isLocked && !opts?.force) return this;
2503
2535
  const selectionPageBounds = this.getSelectionPageBounds();
2504
2536
  if (selectionPageBounds) {
2505
- this.zoomToBounds(selectionPageBounds, {
2506
- targetZoom: Math.max(1, this.getZoomLevel()),
2507
- ...opts
2508
- });
2537
+ const currentZoom = this.getZoomLevel();
2538
+ if (Math.abs(currentZoom - 1) < 0.01) {
2539
+ this.zoomToBounds(selectionPageBounds, opts);
2540
+ } else {
2541
+ this.zoomToBounds(selectionPageBounds, {
2542
+ targetZoom: 1,
2543
+ ...opts
2544
+ });
2545
+ }
2509
2546
  }
2510
2547
  return this;
2511
2548
  }
@@ -2545,7 +2582,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
2545
2582
  const cameraOptions = this._cameraOptions.__unsafe__getWithoutCapture();
2546
2583
  if (cameraOptions.isLocked && !opts?.force) return this;
2547
2584
  const viewportScreenBounds = this.getViewportScreenBounds();
2548
- const inset = opts?.inset ?? Math.min(import_constants.ZOOM_TO_FIT_PADDING, viewportScreenBounds.width * 0.28);
2585
+ const inset = opts?.inset ?? Math.min(this.options.zoomToFitPadding, viewportScreenBounds.width * 0.28);
2549
2586
  const baseZoom = this.getBaseZoom();
2550
2587
  const zoomMin = cameraOptions.zoomSteps[0];
2551
2588
  const zoomMax = (0, import_utils.last)(cameraOptions.zoomSteps);
@@ -2769,18 +2806,20 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
2769
2806
  }
2770
2807
  if (_willSetInitialBounds) {
2771
2808
  this.updateInstanceState({ screenBounds: screenBounds.toJson(), insets });
2809
+ this.emit("resize", screenBounds.toJson());
2772
2810
  this.setCamera(this.getCamera());
2773
2811
  } else {
2774
2812
  if (center && !this.getInstanceState().followingUserId) {
2775
2813
  const before = this.getViewportPageBounds().center;
2776
2814
  this.updateInstanceState({ screenBounds: screenBounds.toJson(), insets });
2815
+ this.emit("resize", screenBounds.toJson());
2777
2816
  this.centerOnPoint(before);
2778
2817
  } else {
2779
2818
  this.updateInstanceState({ screenBounds: screenBounds.toJson(), insets });
2819
+ this.emit("resize", screenBounds.toJson());
2780
2820
  this._setCamera(import_Vec.Vec.From({ ...this.getCamera() }));
2781
2821
  }
2782
2822
  }
2783
- this._tickCameraState();
2784
2823
  return this;
2785
2824
  }
2786
2825
  getViewportScreenBounds() {
@@ -3060,6 +3099,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3060
3099
  this._cameraStateTimeoutRemaining = this.options.cameraMovingTimeoutMs;
3061
3100
  if (this._cameraState.__unsafe__getWithoutCapture() !== "idle") return;
3062
3101
  this._cameraState.set("moving");
3102
+ this._debouncedZoomLevel.set((0, import_state.unsafe__withoutCapture)(() => this.getCamera().z));
3063
3103
  this.on("tick", this._decayCameraStateTimeout);
3064
3104
  }
3065
3105
  /**
@@ -3812,14 +3852,29 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3812
3852
  const notVisibleShapes2 = this.getNotVisibleShapes();
3813
3853
  const selectedShapeIds = this.getSelectedShapeIds();
3814
3854
  const editingId = this.getEditingShapeId();
3815
- const culledShapes = new Set(notVisibleShapes2);
3855
+ const nextValue = new Set(notVisibleShapes2);
3816
3856
  if (editingId) {
3817
- culledShapes.delete(editingId);
3857
+ nextValue.delete(editingId);
3818
3858
  }
3819
3859
  selectedShapeIds.forEach((id) => {
3820
- culledShapes.delete(id);
3860
+ nextValue.delete(id);
3821
3861
  });
3822
- return culledShapes;
3862
+ const prevValue = this._culledShapesCache;
3863
+ if (prevValue) {
3864
+ if (prevValue.size !== nextValue.size) {
3865
+ this._culledShapesCache = nextValue;
3866
+ return nextValue;
3867
+ }
3868
+ for (const id of prevValue) {
3869
+ if (!nextValue.has(id)) {
3870
+ this._culledShapesCache = nextValue;
3871
+ return nextValue;
3872
+ }
3873
+ }
3874
+ return prevValue;
3875
+ }
3876
+ this._culledShapesCache = nextValue;
3877
+ return nextValue;
3823
3878
  }
3824
3879
  getCurrentPageBounds() {
3825
3880
  let commonBounds;
@@ -3869,7 +3924,10 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3869
3924
  let inHollowSmallestAreaHit = null;
3870
3925
  let inMarginClosestToEdgeDistance = Infinity;
3871
3926
  let inMarginClosestToEdgeHit = null;
3927
+ const searchMargin = Math.max(innerMargin, outerMargin, this.options.hitTestMargin / zoomLevel);
3928
+ const candidateIds = this.spatialIndex.getShapeIdsAtPoint(point, searchMargin);
3872
3929
  const shapesToCheck = (opts.renderingOnly ? this.getCurrentPageRenderingShapesSorted() : this.getCurrentPageShapesSorted()).filter((shape) => {
3930
+ if (!candidateIds.has(shape.id) && !this.isShapeOfType(shape, "frame")) return false;
3873
3931
  if (shape.isLocked && !hitLocked || this.isShapeHidden(shape) || this.isShapeOfType(shape, "group"))
3874
3932
  return false;
3875
3933
  const pageMask = this.getShapeMask(shape);
@@ -3976,7 +4034,31 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3976
4034
  * @public
3977
4035
  */
3978
4036
  getShapesAtPoint(point, opts = {}) {
3979
- return this.getCurrentPageShapesSorted().filter((shape) => !this.isShapeHidden(shape) && this.isPointInShape(shape, point, opts)).reverse();
4037
+ const margin = opts.margin ?? 0;
4038
+ const candidateIds = this.spatialIndex.getShapeIdsAtPoint(point, margin);
4039
+ return this.getCurrentPageShapesSorted().filter((shape) => {
4040
+ if (this.isShapeHidden(shape)) return false;
4041
+ if (!candidateIds.has(shape.id) && !this.isShapeOfType(shape, "frame")) return false;
4042
+ return this.isPointInShape(shape, point, opts);
4043
+ }).reverse();
4044
+ }
4045
+ /**
4046
+ * Get shape IDs within the given bounds.
4047
+ *
4048
+ * Note: Results are unordered. If you need z-order, combine with sorted shapes:
4049
+ * ```ts
4050
+ * const candidates = editor.getShapeIdsInsideBounds(bounds)
4051
+ * const sorted = editor.getCurrentPageShapesSorted().filter(s => candidates.has(s.id))
4052
+ * ```
4053
+ *
4054
+ * @param bounds - The bounds to search within.
4055
+ *
4056
+ * @returns Unordered set of shape IDs within the given bounds.
4057
+ *
4058
+ * @public
4059
+ */
4060
+ getShapeIdsInsideBounds(bounds) {
4061
+ return this.spatialIndex.getShapeIdsInsideBounds(bounds);
3980
4062
  }
3981
4063
  /**
3982
4064
  * Test whether a point (in the current page space) will will a shape. This method takes into account masks,
@@ -5659,8 +5741,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
5659
5741
  isAspectRatioLocked: options.isAspectRatioLocked
5660
5742
  });
5661
5743
  if (Math.sign(scale.x) * Math.sign(scale.y) < 0) {
5662
- let { rotation } = import_Mat.Mat.Decompose(options.initialPageTransform);
5663
- rotation -= 2 * rotation;
5744
+ const parentRotation = this.getShapeParentTransform(id).rotation();
5745
+ const rotation = -options.initialShape.rotation - 2 * parentRotation;
5664
5746
  this.updateShapes([{ id, type, rotation }]);
5665
5747
  }
5666
5748
  const preScaleShapePageCenter = import_Mat.Mat.applyToPoint(
@@ -5673,9 +5755,9 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
5673
5755
  scale,
5674
5756
  options.scaleAxisRotation
5675
5757
  );
5676
- const pageBounds = this.getShapePageBounds(id);
5677
5758
  const pageTransform = this.getShapePageTransform(id);
5678
- const currentPageCenter = pageBounds.center;
5759
+ const currentLocalBounds = this.getShapeGeometry(id).bounds;
5760
+ const currentPageCenter = import_Mat.Mat.applyToPoint(pageTransform, currentLocalBounds.center);
5679
5761
  const shapePageTransformOrigin = pageTransform.point();
5680
5762
  if (!currentPageCenter || !shapePageTransformOrigin) return this;
5681
5763
  const pageDelta = import_Vec.Vec.Sub(postScaleShapePageCenter, currentPageCenter);
@@ -5961,7 +6043,11 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
5961
6043
  )
5962
6044
  );
5963
6045
  const sortedShapeIds = shapesToGroup.sort(import_utils.sortByIndex).map((s) => s.id);
5964
- const pageBounds = import_Box.Box.Common((0, import_utils.compact)(shapesToGroup.map((id) => this.getShapePageBounds(id))));
6046
+ const childBounds = (0, import_utils.compact)(shapesToGroup.map((shape) => this.getShapePageBounds(shape)));
6047
+ const pageBounds = import_Box.Box.Common(childBounds);
6048
+ if (!pageBounds.isValid()) {
6049
+ throw Error(`Editor.groupShapes: group bounds are invalid (NaN).`);
6050
+ }
5965
6051
  const { x, y } = pageBounds.point;
5966
6052
  const parentId = this.findCommonAncestor(shapesToGroup) ?? this.getCurrentPageId();
5967
6053
  if (this.getCurrentToolId() !== "select") return this;
@@ -6651,6 +6737,25 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
6651
6737
  }
6652
6738
  }
6653
6739
  }
6740
+ if (point) {
6741
+ const shapesById = new Map(shapes.map((shape) => [shape.id, shape]));
6742
+ const rootShapesFromContent = (0, import_utils.compact)(rootShapeIds.map((id) => shapesById.get(id)));
6743
+ if (rootShapesFromContent.length > 0) {
6744
+ const targetParent = this.getShapeAtPoint(point, {
6745
+ hitInside: true,
6746
+ hitFrameInside: true,
6747
+ hitLocked: true,
6748
+ filter: (shape) => {
6749
+ const util = this.getShapeUtil(shape);
6750
+ if (!util.canReceiveNewChildrenOfType) return false;
6751
+ return rootShapesFromContent.every(
6752
+ (rootShape) => util.canReceiveNewChildrenOfType(shape, rootShape.type)
6753
+ );
6754
+ }
6755
+ });
6756
+ pasteParentId = targetParent ? targetParent.id : currentPageId;
6757
+ }
6758
+ }
6654
6759
  let isDuplicating = false;
6655
6760
  if (!(0, import_tlschema.isPageId)(pasteParentId)) {
6656
6761
  const parent = this.getShape(pasteParentId);
@@ -6895,60 +7000,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
6895
7000
  height
6896
7001
  };
6897
7002
  }
6898
- /**
6899
- * Update the input points from a pointer, pinch, or wheel event.
6900
- *
6901
- * @param info - The event info.
6902
- */
6903
- _updateInputsFromEvent(info) {
6904
- const {
6905
- pointerVelocity,
6906
- previousScreenPoint,
6907
- previousPagePoint,
6908
- currentScreenPoint,
6909
- currentPagePoint,
6910
- originScreenPoint,
6911
- originPagePoint
6912
- } = this.inputs;
6913
- const { screenBounds } = this.store.unsafeGetWithoutCapture(import_tlschema.TLINSTANCE_ID);
6914
- const { x: cx, y: cy, z: cz } = (0, import_state.unsafe__withoutCapture)(() => this.getCamera());
6915
- const sx = info.point.x - screenBounds.x;
6916
- const sy = info.point.y - screenBounds.y;
6917
- const sz = info.point.z ?? 0.5;
6918
- previousScreenPoint.setTo(currentScreenPoint);
6919
- previousPagePoint.setTo(currentPagePoint);
6920
- currentScreenPoint.set(sx, sy);
6921
- const nx = sx / cz - cx;
6922
- const ny = sy / cz - cy;
6923
- if (isFinite(nx) && isFinite(ny)) {
6924
- currentPagePoint.set(nx, ny, sz);
6925
- }
6926
- this.inputs.isPen = info.type === "pointer" && info.isPen;
6927
- if (info.name === "pointer_down" || this.inputs.isPinching) {
6928
- pointerVelocity.set(0, 0);
6929
- originScreenPoint.setTo(currentScreenPoint);
6930
- originPagePoint.setTo(currentPagePoint);
6931
- }
6932
- this.run(
6933
- () => {
6934
- this.store.put([
6935
- {
6936
- id: import_tlschema.TLPOINTER_ID,
6937
- typeName: "pointer",
6938
- x: currentPagePoint.x,
6939
- y: currentPagePoint.y,
6940
- lastActivityTimestamp: (
6941
- // If our pointer moved only because we're following some other user, then don't
6942
- // update our last activity timestamp; otherwise, update it to the current timestamp.
6943
- info.type === "pointer" && info.pointerId === import_constants.INTERNAL_POINTER_IDS.CAMERA_MOVE ? this.store.unsafeGetWithoutCapture(import_tlschema.TLPOINTER_ID)?.lastActivityTimestamp ?? this._tickManager.now : this._tickManager.now
6944
- ),
6945
- meta: {}
6946
- }
6947
- ]);
6948
- },
6949
- { history: "ignore" }
6950
- );
6951
- }
7003
+ /* --------------------- Events --------------------- */
6952
7004
  /**
6953
7005
  * Dispatch a cancel event.
6954
7006
  *
@@ -7013,18 +7065,19 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7013
7065
  point: options?.point ?? // weird but true: what `inputs` calls screen-space is actually viewport space. so
7014
7066
  // we need to convert back into true screen space first. we should fix this...
7015
7067
  import_Vec.Vec.Add(
7016
- this.inputs.currentScreenPoint,
7068
+ this.inputs.getCurrentScreenPoint(),
7017
7069
  this.store.unsafeGetWithoutCapture(import_tlschema.TLINSTANCE_ID).screenBounds
7018
7070
  ),
7019
7071
  pointerId: options?.pointerId ?? 0,
7020
7072
  button: options?.button ?? 0,
7021
- isPen: options?.isPen ?? this.inputs.isPen,
7022
- shiftKey: options?.shiftKey ?? this.inputs.shiftKey,
7023
- altKey: options?.altKey ?? this.inputs.altKey,
7024
- ctrlKey: options?.ctrlKey ?? this.inputs.ctrlKey,
7025
- metaKey: options?.metaKey ?? this.inputs.metaKey,
7026
- accelKey: options?.accelKey ?? (0, import_keyboard.isAccelKey)(this.inputs)
7073
+ isPen: options?.isPen ?? this.inputs.getIsPen(),
7074
+ shiftKey: options?.shiftKey ?? this.inputs.getShiftKey(),
7075
+ altKey: options?.altKey ?? this.inputs.getAltKey(),
7076
+ ctrlKey: options?.ctrlKey ?? this.inputs.getCtrlKey(),
7077
+ metaKey: options?.metaKey ?? this.inputs.getMetaKey(),
7078
+ accelKey: false
7027
7079
  };
7080
+ event.accelKey = options?.accelKey ?? this.inputs.getAccelKey();
7028
7081
  if (options?.immediate) {
7029
7082
  this._flushEventForTick(event);
7030
7083
  } else {
@@ -7340,58 +7393,58 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7340
7393
  this._clickManager.cancelDoubleClickTimeout();
7341
7394
  }
7342
7395
  _setShiftKeyTimeout() {
7343
- this.inputs.shiftKey = false;
7396
+ this.inputs.setShiftKey(false);
7344
7397
  this.dispatch({
7345
7398
  type: "keyboard",
7346
7399
  name: "key_up",
7347
7400
  key: "Shift",
7348
- shiftKey: this.inputs.shiftKey,
7349
- ctrlKey: this.inputs.ctrlKey,
7350
- altKey: this.inputs.altKey,
7351
- metaKey: this.inputs.metaKey,
7352
- accelKey: (0, import_keyboard.isAccelKey)(this.inputs),
7401
+ shiftKey: this.inputs.getShiftKey(),
7402
+ ctrlKey: this.inputs.getCtrlKey(),
7403
+ altKey: this.inputs.getAltKey(),
7404
+ metaKey: this.inputs.getMetaKey(),
7405
+ accelKey: this.inputs.getAccelKey(),
7353
7406
  code: "ShiftLeft"
7354
7407
  });
7355
7408
  }
7356
7409
  _setAltKeyTimeout() {
7357
- this.inputs.altKey = false;
7410
+ this.inputs.setAltKey(false);
7358
7411
  this.dispatch({
7359
7412
  type: "keyboard",
7360
7413
  name: "key_up",
7361
7414
  key: "Alt",
7362
- shiftKey: this.inputs.shiftKey,
7363
- ctrlKey: this.inputs.ctrlKey,
7364
- altKey: this.inputs.altKey,
7365
- metaKey: this.inputs.metaKey,
7366
- accelKey: (0, import_keyboard.isAccelKey)(this.inputs),
7415
+ shiftKey: this.inputs.getShiftKey(),
7416
+ ctrlKey: this.inputs.getCtrlKey(),
7417
+ altKey: this.inputs.getAltKey(),
7418
+ metaKey: this.inputs.getMetaKey(),
7419
+ accelKey: this.inputs.getAccelKey(),
7367
7420
  code: "AltLeft"
7368
7421
  });
7369
7422
  }
7370
7423
  _setCtrlKeyTimeout() {
7371
- this.inputs.ctrlKey = false;
7424
+ this.inputs.setCtrlKey(false);
7372
7425
  this.dispatch({
7373
7426
  type: "keyboard",
7374
7427
  name: "key_up",
7375
7428
  key: "Ctrl",
7376
- shiftKey: this.inputs.shiftKey,
7377
- ctrlKey: this.inputs.ctrlKey,
7378
- altKey: this.inputs.altKey,
7379
- metaKey: this.inputs.metaKey,
7380
- accelKey: (0, import_keyboard.isAccelKey)(this.inputs),
7429
+ shiftKey: this.inputs.getShiftKey(),
7430
+ ctrlKey: this.inputs.getCtrlKey(),
7431
+ altKey: this.inputs.getAltKey(),
7432
+ metaKey: this.inputs.getMetaKey(),
7433
+ accelKey: this.inputs.getAccelKey(),
7381
7434
  code: "ControlLeft"
7382
7435
  });
7383
7436
  }
7384
7437
  _setMetaKeyTimeout() {
7385
- this.inputs.metaKey = false;
7438
+ this.inputs.setMetaKey(false);
7386
7439
  this.dispatch({
7387
7440
  type: "keyboard",
7388
7441
  name: "key_up",
7389
7442
  key: "Meta",
7390
- shiftKey: this.inputs.shiftKey,
7391
- ctrlKey: this.inputs.ctrlKey,
7392
- altKey: this.inputs.altKey,
7393
- metaKey: this.inputs.metaKey,
7394
- accelKey: (0, import_keyboard.isAccelKey)(this.inputs),
7443
+ shiftKey: this.inputs.getShiftKey(),
7444
+ ctrlKey: this.inputs.getCtrlKey(),
7445
+ altKey: this.inputs.getAltKey(),
7446
+ metaKey: this.inputs.getMetaKey(),
7447
+ accelKey: this.inputs.getAccelKey(),
7395
7448
  code: "MetaLeft"
7396
7449
  });
7397
7450
  }
@@ -7462,48 +7515,47 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7462
7515
  const { type } = info;
7463
7516
  if (info.type === "misc") {
7464
7517
  if (info.name === "cancel" || info.name === "complete") {
7465
- this.inputs.isDragging = false;
7466
- if (this.inputs.isPanning) {
7467
- this.inputs.isPanning = false;
7468
- this.inputs.isSpacebarPanning = false;
7518
+ this.inputs.setIsDragging(false);
7519
+ if (this.inputs.getIsPanning()) {
7520
+ this.inputs.setIsPanning(false);
7521
+ this.inputs.setIsSpacebarPanning(false);
7469
7522
  this.setCursor({ type: this._prevCursor, rotation: 0 });
7470
7523
  }
7471
7524
  }
7472
- this.emit("event", info);
7473
7525
  this.root.handleEvent(info);
7526
+ this.emit("event", info);
7474
7527
  return;
7475
7528
  }
7476
7529
  if (info.shiftKey) {
7477
7530
  clearTimeout(this._shiftKeyTimeout);
7478
7531
  this._shiftKeyTimeout = -1;
7479
- inputs.shiftKey = true;
7480
- } else if (!info.shiftKey && inputs.shiftKey && this._shiftKeyTimeout === -1) {
7532
+ inputs.setShiftKey(true);
7533
+ } else if (!info.shiftKey && inputs.getShiftKey() && this._shiftKeyTimeout === -1) {
7481
7534
  this._shiftKeyTimeout = this.timers.setTimeout(this._setShiftKeyTimeout, 150);
7482
7535
  }
7483
7536
  if (info.altKey) {
7484
7537
  clearTimeout(this._altKeyTimeout);
7485
7538
  this._altKeyTimeout = -1;
7486
- inputs.altKey = true;
7487
- } else if (!info.altKey && inputs.altKey && this._altKeyTimeout === -1) {
7539
+ inputs.setAltKey(true);
7540
+ } else if (!info.altKey && inputs.getAltKey() && this._altKeyTimeout === -1) {
7488
7541
  this._altKeyTimeout = this.timers.setTimeout(this._setAltKeyTimeout, 150);
7489
7542
  }
7490
7543
  if (info.ctrlKey) {
7491
7544
  clearTimeout(this._ctrlKeyTimeout);
7492
7545
  this._ctrlKeyTimeout = -1;
7493
- inputs.ctrlKey = true;
7494
- } else if (!info.ctrlKey && inputs.ctrlKey && this._ctrlKeyTimeout === -1) {
7546
+ inputs.setCtrlKey(true);
7547
+ } else if (!info.ctrlKey && inputs.getCtrlKey() && this._ctrlKeyTimeout === -1) {
7495
7548
  this._ctrlKeyTimeout = this.timers.setTimeout(this._setCtrlKeyTimeout, 150);
7496
7549
  }
7497
7550
  if (info.metaKey) {
7498
7551
  clearTimeout(this._metaKeyTimeout);
7499
7552
  this._metaKeyTimeout = -1;
7500
- inputs.metaKey = true;
7501
- } else if (!info.metaKey && inputs.metaKey && this._metaKeyTimeout === -1) {
7553
+ inputs.setMetaKey(true);
7554
+ } else if (!info.metaKey && inputs.getMetaKey() && this._metaKeyTimeout === -1) {
7502
7555
  this._metaKeyTimeout = this.timers.setTimeout(this._setMetaKeyTimeout, 150);
7503
7556
  }
7504
- const { originPagePoint, currentPagePoint } = inputs;
7505
- if (!inputs.isPointing) {
7506
- inputs.isDragging = false;
7557
+ if (!inputs.getIsPointing()) {
7558
+ inputs.setIsDragging(false);
7507
7559
  }
7508
7560
  const instanceState = this.store.unsafeGetWithoutCapture(import_tlschema.TLINSTANCE_ID);
7509
7561
  const pageState = this.store.get(this._getCurrentPageStateId());
@@ -7512,23 +7564,23 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7512
7564
  case "pinch": {
7513
7565
  if (cameraOptions.isLocked) return;
7514
7566
  clearTimeout(this._longPressTimeout);
7515
- this._updateInputsFromEvent(info);
7567
+ this.inputs.updateFromEvent(info);
7516
7568
  switch (info.name) {
7517
7569
  case "pinch_start": {
7518
- if (inputs.isPinching) return;
7519
- if (!inputs.isEditing) {
7520
- this._pinchStart = this.getCamera().z;
7570
+ if (inputs.getIsPinching()) return;
7571
+ if (!inputs.getIsEditing()) {
7521
7572
  if (!this._selectedShapeIdsAtPointerDown.length) {
7522
7573
  this._selectedShapeIdsAtPointerDown = [...pageState.selectedShapeIds];
7523
7574
  }
7524
7575
  this._didPinch = true;
7525
- inputs.isPinching = true;
7576
+ inputs.setIsPinching(true);
7526
7577
  this.interrupt();
7527
7578
  }
7579
+ this.emit("event", info);
7528
7580
  return;
7529
7581
  }
7530
7582
  case "pinch": {
7531
- if (!inputs.isPinching) return;
7583
+ if (!inputs.getIsPinching()) return;
7532
7584
  const {
7533
7585
  point: { z = 1 },
7534
7586
  delta: { x: dx, y: dy }
@@ -7552,11 +7604,12 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7552
7604
  ),
7553
7605
  { immediate: true }
7554
7606
  );
7607
+ this.emit("event", info);
7555
7608
  return;
7556
7609
  }
7557
7610
  case "pinch_end": {
7558
- if (!inputs.isPinching) return this;
7559
- inputs.isPinching = false;
7611
+ if (!inputs.getIsPinching()) return this;
7612
+ inputs.setIsPinching(false);
7560
7613
  const { _selectedShapeIdsAtPointerDown: shapesToReselect } = this;
7561
7614
  this.setSelectedShapes(this._selectedShapeIdsAtPointerDown);
7562
7615
  this._selectedShapeIdsAtPointerDown = [];
@@ -7570,13 +7623,14 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7570
7623
  });
7571
7624
  }
7572
7625
  }
7626
+ this.emit("event", info);
7573
7627
  return;
7574
7628
  }
7575
7629
  }
7576
7630
  }
7577
7631
  case "wheel": {
7578
7632
  if (cameraOptions.isLocked) return;
7579
- this._updateInputsFromEvent(info);
7633
+ this.inputs.updateFromEvent(info);
7580
7634
  const { panSpeed, zoomSpeed } = cameraOptions;
7581
7635
  let wheelBehavior = cameraOptions.wheelBehavior;
7582
7636
  const inputMode = this.user.getUserPreferences().inputMode;
@@ -7594,7 +7648,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7594
7648
  if (info.ctrlKey) behavior = wheelBehavior === "pan" ? "zoom" : "pan";
7595
7649
  switch (behavior) {
7596
7650
  case "zoom": {
7597
- const { x, y } = this.inputs.currentScreenPoint;
7651
+ const { x, y } = this.inputs.getCurrentScreenPoint();
7598
7652
  let delta = dz;
7599
7653
  if (wheelBehavior === "zoom") {
7600
7654
  if (Math.abs(dy) > 10) {
@@ -7608,6 +7662,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7608
7662
  immediate: true
7609
7663
  });
7610
7664
  this.maybeTrackPerformance("Zooming");
7665
+ this.root.handleEvent(info);
7666
+ this.emit("event", info);
7611
7667
  return;
7612
7668
  }
7613
7669
  case "pan": {
@@ -7615,6 +7671,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7615
7671
  immediate: true
7616
7672
  });
7617
7673
  this.maybeTrackPerformance("Panning");
7674
+ this.root.handleEvent(info);
7675
+ this.emit("event", info);
7618
7676
  return;
7619
7677
  }
7620
7678
  }
@@ -7622,14 +7680,14 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7622
7680
  break;
7623
7681
  }
7624
7682
  case "pointer": {
7625
- if (inputs.isPinching) return;
7626
- this._updateInputsFromEvent(info);
7683
+ if (inputs.getIsPinching()) return;
7684
+ this.inputs.updateFromEvent(info);
7627
7685
  const { isPen } = info;
7628
7686
  const { isPenMode } = instanceState;
7629
7687
  switch (info.name) {
7630
7688
  case "pointer_down": {
7631
7689
  if (isPenMode && !isPen) return;
7632
- if (!this.inputs.isPanning) {
7690
+ if (!this.inputs.getIsPanning()) {
7633
7691
  this._longPressTimeout = this.timers.setTimeout(() => {
7634
7692
  const vsb = this.getViewportScreenBounds();
7635
7693
  this.dispatch({
@@ -7638,7 +7696,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7638
7696
  // viewport bounds, and will be again when this event is handled...
7639
7697
  // so we need to counter-adjust from the stored value so that the
7640
7698
  // new value is set correctly.
7641
- point: this.inputs.originScreenPoint.clone().addXY(vsb.x, vsb.y),
7699
+ point: this.inputs.getOriginScreenPoint().clone().addXY(vsb.x, vsb.y),
7642
7700
  name: "long_press"
7643
7701
  });
7644
7702
  }, this.options.longPressDurationMs);
@@ -7646,21 +7704,21 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7646
7704
  this._selectedShapeIdsAtPointerDown = this.getSelectedShapeIds();
7647
7705
  if (info.button === import_constants.LEFT_MOUSE_BUTTON) this.capturedPointerId = info.pointerId;
7648
7706
  inputs.buttons.add(info.button);
7649
- inputs.isPointing = true;
7650
- inputs.isDragging = false;
7707
+ inputs.setIsPointing(true);
7708
+ inputs.setIsDragging(false);
7651
7709
  if (!isPenMode && isPen) this.updateInstanceState({ isPenMode: true });
7652
7710
  if (info.button === import_constants.STYLUS_ERASER_BUTTON) {
7653
7711
  this._restoreToolId = this.getCurrentToolId();
7654
7712
  this.complete();
7655
7713
  this.setCurrentTool("eraser");
7656
7714
  } else if (info.button === import_constants.MIDDLE_MOUSE_BUTTON) {
7657
- if (!this.inputs.isPanning) {
7715
+ if (!this.inputs.getIsPanning()) {
7658
7716
  this._prevCursor = this.getInstanceState().cursor.type;
7659
7717
  }
7660
- this.inputs.isPanning = true;
7718
+ this.inputs.setIsPanning(true);
7661
7719
  clearTimeout(this._longPressTimeout);
7662
7720
  }
7663
- if (this.inputs.isPanning) {
7721
+ if (this.inputs.getIsPanning()) {
7664
7722
  this.stopCameraAnimation();
7665
7723
  this.setCursor({ type: "grabbing", rotation: 0 });
7666
7724
  return this;
@@ -7670,8 +7728,9 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7670
7728
  case "pointer_move": {
7671
7729
  if (!isPen && isPenMode) return;
7672
7730
  const { x: cx, y: cy, z: cz } = (0, import_state.unsafe__withoutCapture)(() => this.getCamera());
7673
- if (this.inputs.isPanning && this.inputs.isPointing) {
7674
- const { currentScreenPoint, previousScreenPoint } = this.inputs;
7731
+ if (this.inputs.getIsPanning() && this.inputs.getIsPointing()) {
7732
+ const currentScreenPoint = this.inputs.getCurrentScreenPoint();
7733
+ const previousScreenPoint = this.inputs.getPreviousScreenPoint();
7675
7734
  const offset = import_Vec.Vec.Sub(currentScreenPoint, previousScreenPoint);
7676
7735
  this.setCamera(new import_Vec.Vec(cx + offset.x / cz, cy + offset.y / cz, cz), {
7677
7736
  immediate: true
@@ -7679,15 +7738,15 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7679
7738
  this.maybeTrackPerformance("Panning");
7680
7739
  return;
7681
7740
  }
7682
- if (inputs.isPointing && !inputs.isDragging && import_Vec.Vec.Dist2(originPagePoint, currentPagePoint) * this.getZoomLevel() > (instanceState.isCoarsePointer ? this.options.coarseDragDistanceSquared : this.options.dragDistanceSquared) / cz) {
7683
- inputs.isDragging = true;
7741
+ if (inputs.getIsPointing() && !inputs.getIsDragging() && import_Vec.Vec.Dist2(inputs.getOriginPagePoint(), inputs.getCurrentPagePoint()) * this.getZoomLevel() > (instanceState.isCoarsePointer ? this.options.coarseDragDistanceSquared : this.options.dragDistanceSquared) / cz) {
7742
+ inputs.setIsDragging(true);
7684
7743
  clearTimeout(this._longPressTimeout);
7685
7744
  }
7686
7745
  break;
7687
7746
  }
7688
7747
  case "pointer_up": {
7689
- inputs.isDragging = false;
7690
- inputs.isPointing = false;
7748
+ inputs.setIsDragging(false);
7749
+ inputs.setIsPointing(false);
7691
7750
  clearTimeout(this._longPressTimeout);
7692
7751
  inputs.buttons.delete(info.button);
7693
7752
  if (instanceState.isPenMode && !isPen) return;
@@ -7695,12 +7754,12 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7695
7754
  this.capturedPointerId = null;
7696
7755
  info.button = 0;
7697
7756
  }
7698
- if (inputs.isPanning) {
7757
+ if (inputs.getIsPanning()) {
7699
7758
  if (!inputs.keys.has("Space")) {
7700
- inputs.isPanning = false;
7701
- inputs.isSpacebarPanning = false;
7759
+ inputs.setIsPanning(false);
7760
+ inputs.setIsSpacebarPanning(false);
7702
7761
  }
7703
- const slideDirection = this.inputs.pointerVelocity;
7762
+ const slideDirection = this.inputs.getPointerVelocity();
7704
7763
  const slideSpeed = Math.min(2, slideDirection.len());
7705
7764
  switch (info.button) {
7706
7765
  case import_constants.LEFT_MOUSE_BUTTON: {
@@ -7737,51 +7796,58 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7737
7796
  switch (info.name) {
7738
7797
  case "key_down": {
7739
7798
  inputs.keys.add(info.code);
7740
- if (info.code === "Space" && !info.ctrlKey) {
7741
- if (!this.inputs.isPanning) {
7742
- this._prevCursor = instanceState.cursor.type;
7743
- }
7744
- this.inputs.isPanning = true;
7745
- this.inputs.isSpacebarPanning = true;
7746
- clearTimeout(this._longPressTimeout);
7747
- this.setCursor({ type: this.inputs.isPointing ? "grabbing" : "grab", rotation: 0 });
7748
- }
7749
- if (this.inputs.isSpacebarPanning) {
7750
- let offset;
7751
- switch (info.code) {
7752
- case "ArrowUp": {
7753
- offset = new import_Vec.Vec(0, -1);
7754
- break;
7755
- }
7756
- case "ArrowRight": {
7757
- offset = new import_Vec.Vec(1, 0);
7758
- break;
7799
+ if (this.options.spacebarPanning) {
7800
+ if (info.code === "Space" && !info.ctrlKey) {
7801
+ if (!this.inputs.getIsPanning()) {
7802
+ this._prevCursor = instanceState.cursor.type;
7759
7803
  }
7760
- case "ArrowDown": {
7761
- offset = new import_Vec.Vec(0, 1);
7762
- break;
7804
+ this.inputs.setIsPanning(true);
7805
+ this.inputs.setIsSpacebarPanning(true);
7806
+ clearTimeout(this._longPressTimeout);
7807
+ this.setCursor({
7808
+ type: this.inputs.getIsPointing() ? "grabbing" : "grab",
7809
+ rotation: 0
7810
+ });
7811
+ }
7812
+ if (this.inputs.getIsSpacebarPanning()) {
7813
+ let offset;
7814
+ switch (info.code) {
7815
+ case "ArrowUp": {
7816
+ offset = new import_Vec.Vec(0, -1);
7817
+ break;
7818
+ }
7819
+ case "ArrowRight": {
7820
+ offset = new import_Vec.Vec(1, 0);
7821
+ break;
7822
+ }
7823
+ case "ArrowDown": {
7824
+ offset = new import_Vec.Vec(0, 1);
7825
+ break;
7826
+ }
7827
+ case "ArrowLeft": {
7828
+ offset = new import_Vec.Vec(-1, 0);
7829
+ break;
7830
+ }
7763
7831
  }
7764
- case "ArrowLeft": {
7765
- offset = new import_Vec.Vec(-1, 0);
7766
- break;
7832
+ if (offset) {
7833
+ const bounds = this.getViewportPageBounds();
7834
+ const next = bounds.clone().translate(offset.mulV({ x: bounds.w, y: bounds.h }));
7835
+ this._animateToViewport(next, { animation: { duration: 320 } });
7767
7836
  }
7768
7837
  }
7769
- if (offset) {
7770
- const bounds = this.getViewportPageBounds();
7771
- const next = bounds.clone().translate(offset.mulV({ x: bounds.w, y: bounds.h }));
7772
- this._animateToViewport(next, { animation: { duration: 320 } });
7773
- }
7774
7838
  }
7775
7839
  break;
7776
7840
  }
7777
7841
  case "key_up": {
7778
7842
  inputs.keys.delete(info.code);
7779
- if (info.code === "Space") {
7780
- if (this.inputs.buttons.has(import_constants.MIDDLE_MOUSE_BUTTON)) {
7781
- } else {
7782
- this.inputs.isPanning = false;
7783
- this.inputs.isSpacebarPanning = false;
7784
- this.setCursor({ type: this._prevCursor, rotation: 0 });
7843
+ if (this.options.spacebarPanning) {
7844
+ if (info.code === "Space") {
7845
+ if (this.inputs.buttons.has(import_constants.MIDDLE_MOUSE_BUTTON)) {
7846
+ } else {
7847
+ this.inputs.setIsPanning(false);
7848
+ this.inputs.setIsSpacebarPanning(false);
7849
+ this.setCursor({ type: this._prevCursor, rotation: 0 });
7850
+ }
7785
7851
  }
7786
7852
  }
7787
7853
  break;
@@ -7834,8 +7900,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7834
7900
  }
7835
7901
  _init = __decoratorStart(_a);
7836
7902
  __decorateElement(_init, 1, "getIsShapeHiddenCache", _getIsShapeHiddenCache_dec, Editor);
7837
- __decorateElement(_init, 1, "getCanUndo", _getCanUndo_dec, Editor);
7838
- __decorateElement(_init, 1, "getCanRedo", _getCanRedo_dec, Editor);
7903
+ __decorateElement(_init, 1, "canUndo", _canUndo_dec, Editor);
7904
+ __decorateElement(_init, 1, "canRedo", _canRedo_dec, Editor);
7839
7905
  __decorateElement(_init, 1, "getPath", _getPath_dec, Editor);
7840
7906
  __decorateElement(_init, 1, "getCurrentTool", _getCurrentTool_dec, Editor);
7841
7907
  __decorateElement(_init, 1, "getCurrentToolId", _getCurrentToolId_dec, Editor);
@@ -7870,6 +7936,9 @@ __decorateElement(_init, 1, "getCamera", _getCamera_dec, Editor);
7870
7936
  __decorateElement(_init, 1, "getViewportPageBoundsForFollowing", _getViewportPageBoundsForFollowing_dec, Editor);
7871
7937
  __decorateElement(_init, 1, "getCameraForFollowing", _getCameraForFollowing_dec, Editor);
7872
7938
  __decorateElement(_init, 1, "getZoomLevel", _getZoomLevel_dec, Editor);
7939
+ __decorateElement(_init, 1, "getDebouncedZoomLevel", _getDebouncedZoomLevel_dec, Editor);
7940
+ __decorateElement(_init, 1, "_getAboveDebouncedZoomThreshold", __getAboveDebouncedZoomThreshold_dec, Editor);
7941
+ __decorateElement(_init, 1, "getEfficientZoomLevel", _getEfficientZoomLevel_dec, Editor);
7873
7942
  __decorateElement(_init, 1, "getViewportScreenBounds", _getViewportScreenBounds_dec, Editor);
7874
7943
  __decorateElement(_init, 1, "getViewportScreenCenter", _getViewportScreenCenter_dec, Editor);
7875
7944
  __decorateElement(_init, 1, "getViewportPageBounds", _getViewportPageBounds_dec, Editor);