@tldraw/editor 5.4.0-next.ef99ab47e5ce → 5.4.1

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 (249) hide show
  1. package/dist-cjs/index.d.ts +114 -47
  2. package/dist-cjs/index.js +4 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +7 -2
  5. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  6. package/dist-cjs/lib/components/MenuClickCapture.js +6 -8
  7. package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
  8. package/dist-cjs/lib/components/default-components/CanvasOverlays.js +1 -3
  9. package/dist-cjs/lib/components/default-components/CanvasOverlays.js.map +2 -2
  10. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
  11. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +1 -1
  12. package/dist-cjs/lib/config/TLUserPreferences.js +6 -2
  13. package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
  14. package/dist-cjs/lib/config/createTLStore.js +1 -1
  15. package/dist-cjs/lib/config/createTLStore.js.map +2 -2
  16. package/dist-cjs/lib/editor/Editor.js +181 -294
  17. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  18. package/dist-cjs/lib/editor/derivations/shapeIdsInCurrentPage.js +7 -3
  19. package/dist-cjs/lib/editor/derivations/shapeIdsInCurrentPage.js.map +2 -2
  20. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +3 -3
  21. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
  22. package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js +8 -8
  23. package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js.map +2 -2
  24. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +2 -1
  25. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
  26. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +79 -6
  27. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
  28. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +7 -0
  29. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +2 -2
  30. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +0 -2
  31. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +2 -2
  32. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +1 -2
  33. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  34. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +6 -3
  35. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +2 -2
  36. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +12 -1
  37. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  38. package/dist-cjs/lib/editor/overlays/OverlayManager.js +3 -7
  39. package/dist-cjs/lib/editor/overlays/OverlayManager.js.map +2 -2
  40. package/dist-cjs/lib/editor/overlays/strokeShapeIndicators.js +0 -1
  41. package/dist-cjs/lib/editor/overlays/strokeShapeIndicators.js.map +2 -2
  42. package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js +3 -1
  43. package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js.map +2 -2
  44. package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js +1 -0
  45. package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js.map +2 -2
  46. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +1 -1
  47. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
  48. package/dist-cjs/lib/editor/tools/StateNode.js +3 -2
  49. package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
  50. package/dist-cjs/lib/globals/editors.js +57 -0
  51. package/dist-cjs/lib/globals/editors.js.map +7 -0
  52. package/dist-cjs/lib/globals/menus.js +9 -4
  53. package/dist-cjs/lib/globals/menus.js.map +2 -2
  54. package/dist-cjs/lib/hooks/useCanvasEvents.js +2 -0
  55. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  56. package/dist-cjs/lib/hooks/useDocumentEvents.js +39 -9
  57. package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
  58. package/dist-cjs/lib/hooks/useLocalStore.js +10 -6
  59. package/dist-cjs/lib/hooks/useLocalStore.js.map +2 -2
  60. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js +1 -0
  61. package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
  62. package/dist-cjs/lib/hooks/usePeerIds.js +2 -1
  63. package/dist-cjs/lib/hooks/usePeerIds.js.map +2 -2
  64. package/dist-cjs/lib/license/LicenseManager.js +9 -2
  65. package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
  66. package/dist-cjs/lib/license/LicenseProvider.js +16 -3
  67. package/dist-cjs/lib/license/LicenseProvider.js.map +2 -2
  68. package/dist-cjs/lib/license/useLicenseManagerState.js +5 -4
  69. package/dist-cjs/lib/license/useLicenseManagerState.js.map +2 -2
  70. package/dist-cjs/lib/primitives/Box.js +2 -1
  71. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  72. package/dist-cjs/lib/primitives/Vec.js +4 -3
  73. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  74. package/dist-cjs/lib/primitives/geometry/Group2d.js +63 -21
  75. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  76. package/dist-cjs/lib/primitives/utils.js +2 -1
  77. package/dist-cjs/lib/primitives/utils.js.map +2 -2
  78. package/dist-cjs/lib/utils/deepLinks.js +5 -1
  79. package/dist-cjs/lib/utils/deepLinks.js.map +2 -2
  80. package/dist-cjs/lib/utils/normalizeWheel.js +2 -0
  81. package/dist-cjs/lib/utils/normalizeWheel.js.map +2 -2
  82. package/dist-cjs/lib/utils/rotation.js +1 -9
  83. package/dist-cjs/lib/utils/rotation.js.map +2 -2
  84. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +17 -0
  85. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
  86. package/dist-cjs/lib/utils/sync/alerts.js +1 -1
  87. package/dist-cjs/lib/utils/sync/alerts.js.map +1 -1
  88. package/dist-cjs/version.js +3 -3
  89. package/dist-cjs/version.js.map +1 -1
  90. package/dist-esm/index.d.mts +114 -47
  91. package/dist-esm/index.mjs +9 -2
  92. package/dist-esm/index.mjs.map +2 -2
  93. package/dist-esm/lib/TldrawEditor.mjs +9 -4
  94. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  95. package/dist-esm/lib/components/MenuClickCapture.mjs +6 -8
  96. package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
  97. package/dist-esm/lib/components/default-components/CanvasOverlays.mjs +1 -3
  98. package/dist-esm/lib/components/default-components/CanvasOverlays.mjs.map +2 -2
  99. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
  100. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +1 -1
  101. package/dist-esm/lib/config/TLUserPreferences.mjs +6 -2
  102. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  103. package/dist-esm/lib/config/createTLStore.mjs +1 -1
  104. package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
  105. package/dist-esm/lib/editor/Editor.mjs +189 -295
  106. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  107. package/dist-esm/lib/editor/derivations/shapeIdsInCurrentPage.mjs +7 -3
  108. package/dist-esm/lib/editor/derivations/shapeIdsInCurrentPage.mjs.map +2 -2
  109. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +3 -3
  110. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
  111. package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs +9 -9
  112. package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs.map +2 -2
  113. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +2 -1
  114. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
  115. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +81 -8
  116. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
  117. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +7 -0
  118. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +2 -2
  119. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +0 -2
  120. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +2 -2
  121. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +2 -3
  122. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  123. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +6 -3
  124. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +2 -2
  125. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +12 -1
  126. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  127. package/dist-esm/lib/editor/overlays/OverlayManager.mjs +3 -7
  128. package/dist-esm/lib/editor/overlays/OverlayManager.mjs.map +2 -2
  129. package/dist-esm/lib/editor/overlays/strokeShapeIndicators.mjs +0 -1
  130. package/dist-esm/lib/editor/overlays/strokeShapeIndicators.mjs.map +2 -2
  131. package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs +3 -1
  132. package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs.map +2 -2
  133. package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs +1 -0
  134. package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs.map +2 -2
  135. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +1 -1
  136. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
  137. package/dist-esm/lib/editor/tools/StateNode.mjs +3 -2
  138. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  139. package/dist-esm/lib/globals/editors.mjs +37 -0
  140. package/dist-esm/lib/globals/editors.mjs.map +7 -0
  141. package/dist-esm/lib/globals/menus.mjs +9 -4
  142. package/dist-esm/lib/globals/menus.mjs.map +2 -2
  143. package/dist-esm/lib/hooks/useCanvasEvents.mjs +2 -0
  144. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  145. package/dist-esm/lib/hooks/useDocumentEvents.mjs +40 -10
  146. package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
  147. package/dist-esm/lib/hooks/useLocalStore.mjs +11 -7
  148. package/dist-esm/lib/hooks/useLocalStore.mjs.map +2 -2
  149. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs +1 -0
  150. package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
  151. package/dist-esm/lib/hooks/usePeerIds.mjs +2 -1
  152. package/dist-esm/lib/hooks/usePeerIds.mjs.map +2 -2
  153. package/dist-esm/lib/license/LicenseManager.mjs +9 -2
  154. package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
  155. package/dist-esm/lib/license/LicenseProvider.mjs +16 -3
  156. package/dist-esm/lib/license/LicenseProvider.mjs.map +2 -2
  157. package/dist-esm/lib/license/useLicenseManagerState.mjs +5 -4
  158. package/dist-esm/lib/license/useLicenseManagerState.mjs.map +2 -2
  159. package/dist-esm/lib/primitives/Box.mjs +2 -1
  160. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  161. package/dist-esm/lib/primitives/Vec.mjs +4 -3
  162. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  163. package/dist-esm/lib/primitives/geometry/Group2d.mjs +63 -21
  164. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  165. package/dist-esm/lib/primitives/utils.mjs +2 -1
  166. package/dist-esm/lib/primitives/utils.mjs.map +2 -2
  167. package/dist-esm/lib/utils/deepLinks.mjs +5 -1
  168. package/dist-esm/lib/utils/deepLinks.mjs.map +2 -2
  169. package/dist-esm/lib/utils/normalizeWheel.mjs +2 -0
  170. package/dist-esm/lib/utils/normalizeWheel.mjs.map +2 -2
  171. package/dist-esm/lib/utils/rotation.mjs +1 -9
  172. package/dist-esm/lib/utils/rotation.mjs.map +2 -2
  173. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +17 -0
  174. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
  175. package/dist-esm/lib/utils/sync/alerts.mjs +1 -1
  176. package/dist-esm/lib/utils/sync/alerts.mjs.map +1 -1
  177. package/dist-esm/version.mjs +3 -3
  178. package/dist-esm/version.mjs.map +1 -1
  179. package/package.json +13 -7
  180. package/src/index.ts +6 -1
  181. package/src/lib/TldrawEditor.tsx +16 -4
  182. package/src/lib/components/MenuClickCapture.tsx +19 -18
  183. package/src/lib/components/default-components/CanvasOverlays.tsx +1 -3
  184. package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -1
  185. package/src/lib/config/TLUserPreferences.test.ts +18 -1
  186. package/src/lib/config/TLUserPreferences.ts +8 -4
  187. package/src/lib/config/createTLStore.ts +1 -1
  188. package/src/lib/editor/Editor.ts +266 -383
  189. package/src/lib/editor/derivations/shapeIdsInCurrentPage.ts +7 -3
  190. package/src/lib/editor/managers/ClickManager/ClickManager.ts +5 -3
  191. package/src/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.ts +9 -9
  192. package/src/lib/editor/managers/FontManager/FontManager.ts +2 -1
  193. package/src/lib/editor/managers/InputsManager/InputsManager.test.ts +199 -3
  194. package/src/lib/editor/managers/InputsManager/InputsManager.ts +128 -9
  195. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.ts +12 -1
  196. package/src/lib/editor/managers/SnapManager/BoundsSnaps.ts +0 -2
  197. package/src/lib/editor/managers/TextManager/TextManager.ts +2 -6
  198. package/src/lib/editor/managers/TickManager/TickManager.test.ts +13 -0
  199. package/src/lib/editor/managers/TickManager/TickManager.ts +9 -3
  200. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +64 -3
  201. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +18 -1
  202. package/src/lib/editor/overlays/OverlayManager.ts +3 -7
  203. package/src/lib/editor/overlays/strokeShapeIndicators.ts +0 -1
  204. package/src/lib/editor/shapes/BaseFrameLikeShapeUtil.tsx +5 -1
  205. package/src/lib/editor/shapes/shared/getPerfectDashProps.ts +3 -0
  206. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +4 -1
  207. package/src/lib/editor/tools/StateNode.test.ts +64 -0
  208. package/src/lib/editor/tools/StateNode.ts +12 -2
  209. package/src/lib/globals/editors.test.ts +76 -0
  210. package/src/lib/globals/editors.ts +53 -0
  211. package/src/lib/globals/menus.test.ts +33 -0
  212. package/src/lib/globals/menus.ts +11 -4
  213. package/src/lib/hooks/useCanvasEvents.ts +2 -0
  214. package/src/lib/hooks/useDocumentEvents.ts +60 -16
  215. package/src/lib/hooks/useLocalStore.ts +16 -8
  216. package/src/lib/hooks/usePassThroughWheelEvents.ts +3 -0
  217. package/src/lib/hooks/usePeerIds.ts +2 -1
  218. package/src/lib/license/LicenseManager.test.ts +160 -0
  219. package/src/lib/license/LicenseManager.ts +13 -4
  220. package/src/lib/license/LicenseProvider.tsx +24 -3
  221. package/src/lib/license/useLicenseManagerState.ts +8 -6
  222. package/src/lib/primitives/Box.test.ts +9 -1
  223. package/src/lib/primitives/Box.ts +3 -1
  224. package/src/lib/primitives/Vec.test.ts +10 -0
  225. package/src/lib/primitives/Vec.ts +4 -4
  226. package/src/lib/primitives/geometry/Arc2d.test.ts +226 -3
  227. package/src/lib/primitives/geometry/CubicBezier2d.test.ts +173 -3
  228. package/src/lib/primitives/geometry/CubicSpline2d.test.ts +160 -3
  229. package/src/lib/primitives/geometry/Ellipse2d.test.ts +243 -3
  230. package/src/lib/primitives/geometry/Geometry2d.test.ts +553 -1
  231. package/src/lib/primitives/geometry/Group2d.test.ts +398 -3
  232. package/src/lib/primitives/geometry/Group2d.ts +63 -27
  233. package/src/lib/primitives/geometry/Polyline2d.test.ts +207 -0
  234. package/src/lib/primitives/geometry/Stadium2d.test.ts +191 -3
  235. package/src/lib/primitives/utils.test.ts +10 -1
  236. package/src/lib/primitives/utils.ts +4 -1
  237. package/src/lib/test/useCanvasEvents.test.tsx +74 -0
  238. package/src/lib/test/useDocumentEvents.test.tsx +107 -0
  239. package/src/lib/test/usePassThroughWheelEvents.test.tsx +25 -2
  240. package/src/lib/utils/deepLinks.test.ts +15 -0
  241. package/src/lib/utils/deepLinks.ts +7 -1
  242. package/src/lib/utils/normalizeWheel.test.ts +39 -0
  243. package/src/lib/utils/normalizeWheel.ts +6 -0
  244. package/src/lib/utils/rotation.ts +4 -12
  245. package/src/lib/utils/sync/TLLocalSyncClient.test.ts +56 -0
  246. package/src/lib/utils/sync/TLLocalSyncClient.ts +24 -0
  247. package/src/lib/utils/sync/alerts.ts +1 -1
  248. package/src/version.ts +3 -3
  249. package/src/lib/primitives/geometry/Polyline.test.ts +0 -5
@@ -53,6 +53,7 @@ var import_constants = require("../constants");
53
53
  var import_domUtils = require("../exports/domUtils");
54
54
  var import_exportToSvg = require("../exports/exportToSvg");
55
55
  var import_getSvgAsImage = require("../exports/getSvgAsImage");
56
+ var import_editors = require("../globals/editors");
56
57
  var import_menus = require("../globals/menus");
57
58
  var import_time = require("../globals/time");
58
59
  var import_options = require("../options");
@@ -256,6 +257,10 @@ class Editor extends import_eventemitter3.default {
256
257
  if (!nextPageState) nextPageState = { ...prevPageState };
257
258
  nextPageState.editingShapeId = null;
258
259
  }
260
+ if (prevPageState.croppingShapeId && shapesNoLongerInPage.has(prevPageState.croppingShapeId)) {
261
+ if (!nextPageState) nextPageState = { ...prevPageState };
262
+ nextPageState.croppingShapeId = null;
263
+ }
259
264
  const hintingShapeIds = prevPageState.hintingShapeIds.filter(
260
265
  (id) => !shapesNoLongerInPage.has(id)
261
266
  );
@@ -498,10 +503,11 @@ class Editor extends import_eventemitter3.default {
498
503
  this.cancelDoubleClick();
499
504
  }
500
505
  if (prev?.selectedShapeIds !== next?.selectedShapeIds) {
506
+ const selectedShapeIds = new Set(next.selectedShapeIds);
501
507
  const filtered = next.selectedShapeIds.filter((id) => {
502
508
  let parentId = this.getShape(id)?.parentId;
503
509
  while ((0, import_tlschema.isShapeId)(parentId)) {
504
- if (next.selectedShapeIds.includes(parentId)) {
510
+ if (selectedShapeIds.has(parentId)) {
505
511
  return false;
506
512
  }
507
513
  parentId = this.getShape(parentId)?.parentId;
@@ -571,9 +577,11 @@ class Editor extends import_eventemitter3.default {
571
577
  this.on("tick", this._flushEventsForTick);
572
578
  this.on("mount", () => {
573
579
  this._isMounted.set(true);
580
+ (0, import_editors.registerMountedEditor)(this);
574
581
  });
575
582
  this.on("unmount", () => {
576
583
  this._isMounted.set(false);
584
+ (0, import_editors.unregisterMountedEditor)(this);
577
585
  });
578
586
  this.timers.requestAnimationFrame(() => {
579
587
  this._tickManager.start();
@@ -583,7 +591,10 @@ class Editor extends import_eventemitter3.default {
583
591
  const mode = this.store.props.collaboration.mode;
584
592
  this.disposables.add(
585
593
  (0, import_state.react)("update collaboration mode", () => {
586
- this.store.put([{ ...this.getInstanceState(), isReadonly: mode.get() === "readonly" }]);
594
+ const isReadonly = mode.get() === "readonly";
595
+ (0, import_state.unsafe__withoutCapture)(
596
+ () => this._updateInstanceState({ isReadonly }, { history: "ignore" })
597
+ );
587
598
  })
588
599
  );
589
600
  }
@@ -613,6 +624,14 @@ class Editor extends import_eventemitter3.default {
613
624
  );
614
625
  }
615
626
  options;
627
+ /**
628
+ * The license manager whose feature flags apply to this editor. Assigned by `<TldrawEditor />`
629
+ * when it creates the editor, so that UI rendered outside the editor tree can resolve the
630
+ * editor's license through the editor instance. Undefined for editors created directly.
631
+ *
632
+ * @internal
633
+ */
634
+ licenseManager;
616
635
  contextId = (0, import_utils.uniqueId)();
617
636
  /**
618
637
  * The editor's store
@@ -807,6 +826,7 @@ class Editor extends import_eventemitter3.default {
807
826
  if (this._isMounted.get()) {
808
827
  this.emit("unmount");
809
828
  }
829
+ (0, import_editors.unregisterMountedEditor)(this);
810
830
  this.stopCameraAnimation();
811
831
  if (this.getInstanceState().followingUserId) {
812
832
  this.stopFollowingUser();
@@ -932,7 +952,7 @@ class Editor extends import_eventemitter3.default {
932
952
  getShapeUtil(arg) {
933
953
  const type = typeof arg === "string" ? arg : arg.type;
934
954
  const shapeUtil = (0, import_utils.getOwnProperty)(this.shapeUtils, type);
935
- (0, import_utils.assert)(shapeUtil, `No shape util found for type "${type}"`);
955
+ if (!shapeUtil) throw new Error(`No shape util found for type "${type}"`);
936
956
  return shapeUtil;
937
957
  }
938
958
  hasShapeUtil(arg) {
@@ -1721,7 +1741,9 @@ class Editor extends import_eventemitter3.default {
1721
1741
  const selectedShapes = this.getSelectedShapes();
1722
1742
  if (!selectedShapes.length) return;
1723
1743
  const selectedShape = selectedShapes[0];
1724
- const children = this.getSortedChildIdsForParent(selectedShape.id).map((id) => this.getShape(id)).filter((i) => i);
1744
+ const children = (0, import_utils.compact)(
1745
+ this.getSortedChildIdsForParent(selectedShape.id).map((id) => this.getShape(id))
1746
+ );
1725
1747
  const sortedChildren = this._getShapesInReadingOrder(children);
1726
1748
  if (sortedChildren.length === 0) return;
1727
1749
  this._selectShapesAndZoom([sortedChildren[0].id]);
@@ -1788,18 +1810,13 @@ class Editor extends import_eventemitter3.default {
1788
1810
  * @internal
1789
1811
  */
1790
1812
  getShapesSharedRotation(shapeIds) {
1791
- let foundFirst = false;
1792
1813
  let rotation = 0;
1793
1814
  for (let i = 0, n = shapeIds.length; i < n; i++) {
1794
- const pageTransform = this.getShapePageTransform(shapeIds[i]);
1795
- if (!pageTransform) continue;
1796
- if (foundFirst) {
1797
- if (pageTransform.rotation() !== rotation) {
1798
- return 0;
1799
- }
1800
- } else {
1801
- foundFirst = true;
1802
- rotation = pageTransform.rotation();
1815
+ const pageRotation = this.getShapePageTransform(shapeIds[i]).rotation();
1816
+ if (i === 0) {
1817
+ rotation = pageRotation;
1818
+ } else if (pageRotation !== rotation) {
1819
+ return 0;
1803
1820
  }
1804
1821
  }
1805
1822
  return rotation;
@@ -1825,11 +1842,9 @@ class Editor extends import_eventemitter3.default {
1825
1842
  return bounds;
1826
1843
  }
1827
1844
  const boxFromRotatedVertices = import_Box.Box.FromPoints(
1828
- shapeIds.flatMap((id) => {
1829
- const pageTransform = this.getShapePageTransform(id);
1830
- if (!pageTransform) return [];
1831
- return pageTransform.applyToPoints(this.getShapeGeometry(id).bounds.corners);
1832
- }).map((p) => p.rot(-selectionRotation))
1845
+ shapeIds.flatMap(
1846
+ (id) => this.getShapePageTransform(id).applyToPoints(this.getShapeGeometry(id).bounds.corners)
1847
+ ).map((p) => p.rot(-selectionRotation))
1833
1848
  );
1834
1849
  boxFromRotatedVertices.point = boxFromRotatedVertices.point.rot(selectionRotation);
1835
1850
  return boxFromRotatedVertices;
@@ -1840,9 +1855,14 @@ class Editor extends import_eventemitter3.default {
1840
1855
  getSelectionRotatedScreenBounds() {
1841
1856
  const bounds = this.getSelectionRotatedPageBounds();
1842
1857
  if (!bounds) return void 0;
1843
- const { x, y } = this.pageToScreen(bounds.point);
1844
- const zoom = this.getZoomLevel();
1845
- return new import_Box.Box(x, y, bounds.width * zoom, bounds.height * zoom);
1858
+ const screenBounds = this.getViewportScreenBounds();
1859
+ const { x: cx, y: cy, z: zoom } = this.getCamera();
1860
+ return new import_Box.Box(
1861
+ (bounds.x + cx) * zoom + screenBounds.x,
1862
+ (bounds.y + cy) * zoom + screenBounds.y,
1863
+ bounds.width * zoom,
1864
+ bounds.height * zoom
1865
+ );
1846
1866
  }
1847
1867
  getFocusedGroupId() {
1848
1868
  return this.getCurrentPageState().focusedGroupId ?? this.getCurrentPageId();
@@ -1943,42 +1963,28 @@ class Editor extends import_eventemitter3.default {
1943
1963
  */
1944
1964
  setEditingShape(shape) {
1945
1965
  const id = typeof shape === "string" ? shape : shape?.id ?? null;
1946
- if (!id) {
1966
+ if (id && !this.canEditShape(id)) return this;
1967
+ this.run(() => {
1968
+ const prevEditingShapeId = this.getEditingShapeId();
1969
+ if (prevEditingShapeId) {
1970
+ const prevEditingShape = this.getShape(prevEditingShapeId);
1971
+ if (prevEditingShape) {
1972
+ this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
1973
+ }
1974
+ }
1947
1975
  this.run(
1948
1976
  () => {
1949
- const prevEditingShapeId = this.getEditingShapeId();
1950
- if (prevEditingShapeId) {
1951
- const prevEditingShape = this.getShape(prevEditingShapeId);
1952
- if (prevEditingShape) {
1953
- this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
1954
- }
1955
- }
1956
1977
  this._updateCurrentPageState({ editingShapeId: null });
1957
1978
  this._currentRichTextEditor.set(null);
1979
+ if (!id) return;
1980
+ this.select(id);
1981
+ this._updateCurrentPageState({ editingShapeId: id });
1982
+ const nextEditingShape = this.getShape(id);
1983
+ this.getShapeUtil(nextEditingShape).onEditStart?.(nextEditingShape);
1958
1984
  },
1959
1985
  { history: "ignore" }
1960
1986
  );
1961
- return this;
1962
- }
1963
- if (!this.canEditShape(id)) return this;
1964
- this.run(
1965
- () => {
1966
- const prevEditingShapeId = this.getEditingShapeId();
1967
- if (prevEditingShapeId) {
1968
- const prevEditingShape = this.getShape(prevEditingShapeId);
1969
- if (prevEditingShape) {
1970
- this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
1971
- }
1972
- }
1973
- this._updateCurrentPageState({ editingShapeId: null });
1974
- this._currentRichTextEditor.set(null);
1975
- this.select(id);
1976
- this._updateCurrentPageState({ editingShapeId: id });
1977
- const nextEditingShape = this.getShape(id);
1978
- this.getShapeUtil(nextEditingShape).onEditStart?.(nextEditingShape);
1979
- },
1980
- { history: "ignore" }
1981
- );
1987
+ });
1982
1988
  return this;
1983
1989
  }
1984
1990
  // Rich text editor
@@ -2084,19 +2090,12 @@ class Editor extends import_eventemitter3.default {
2084
2090
  * @public
2085
2091
  */
2086
2092
  setErasingShapes(shapes) {
2087
- const ids = typeof shapes[0] === "string" ? shapes : shapes.map((shape) => shape.id);
2093
+ const ids = typeof shapes[0] === "string" ? shapes.slice() : shapes.map((shape) => shape.id);
2088
2094
  ids.sort();
2089
2095
  const erasingShapeIds = this.getErasingShapeIds();
2090
2096
  this.run(
2091
2097
  () => {
2092
- if (ids.length === erasingShapeIds.length) {
2093
- for (let i = 0; i < ids.length; i++) {
2094
- if (ids[i] !== erasingShapeIds[i]) {
2095
- this._updateCurrentPageState({ erasingShapeIds: ids });
2096
- break;
2097
- }
2098
- }
2099
- } else {
2098
+ if (!(0, import_utils.areArraysShallowEqual)(ids, erasingShapeIds)) {
2100
2099
  this._updateCurrentPageState({ erasingShapeIds: ids });
2101
2100
  }
2102
2101
  },
@@ -2129,6 +2128,7 @@ class Editor extends import_eventemitter3.default {
2129
2128
  if (!_shape) return false;
2130
2129
  const util = this.getShapeUtil(_shape);
2131
2130
  if (!util.canCrop(_shape)) return false;
2131
+ if (this.getIsReadonly()) return false;
2132
2132
  if (this.isShapeOrAncestorLocked(_shape)) return false;
2133
2133
  return true;
2134
2134
  }
@@ -2193,11 +2193,11 @@ class Editor extends import_eventemitter3.default {
2193
2193
  const collaborators = this.getCollaborators();
2194
2194
  let leaderPresence = null;
2195
2195
  while (targetUserId && !visited.includes(targetUserId)) {
2196
- leaderPresence = collaborators.find((c) => c.userId === targetUserId) ?? null;
2197
- targetUserId = leaderPresence?.followingUserId ?? null;
2198
- if (leaderPresence) {
2199
- visited.push(leaderPresence.userId);
2200
- }
2196
+ const nextPresence = collaborators.find((c) => c.userId === targetUserId);
2197
+ if (!nextPresence) break;
2198
+ leaderPresence = nextPresence;
2199
+ targetUserId = nextPresence.followingUserId ?? null;
2200
+ visited.push(nextPresence.userId);
2201
2201
  }
2202
2202
  return leaderPresence;
2203
2203
  }
@@ -2260,39 +2260,7 @@ class Editor extends import_eventemitter3.default {
2260
2260
  *
2261
2261
  * @public */
2262
2262
  getInitialZoom() {
2263
- const cameraOptions = this.getCameraOptions();
2264
- if (!cameraOptions.constraints) return 1;
2265
- if (cameraOptions.constraints.initialZoom === "default") return 1;
2266
- const { zx, zy } = getCameraFitXFitY(this, cameraOptions);
2267
- switch (cameraOptions.constraints.initialZoom) {
2268
- case "fit-min": {
2269
- return Math.max(zx, zy);
2270
- }
2271
- case "fit-max": {
2272
- return Math.min(zx, zy);
2273
- }
2274
- case "fit-x": {
2275
- return zx;
2276
- }
2277
- case "fit-y": {
2278
- return zy;
2279
- }
2280
- case "fit-min-100": {
2281
- return Math.min(1, Math.max(zx, zy));
2282
- }
2283
- case "fit-max-100": {
2284
- return Math.min(1, Math.min(zx, zy));
2285
- }
2286
- case "fit-x-100": {
2287
- return Math.min(1, zx);
2288
- }
2289
- case "fit-y-100": {
2290
- return Math.min(1, zy);
2291
- }
2292
- default: {
2293
- throw (0, import_utils.exhaustiveSwitchError)(cameraOptions.constraints.initialZoom);
2294
- }
2295
- }
2263
+ return this._getFitZoom(this.getCameraOptions().constraints?.initialZoom ?? "default");
2296
2264
  }
2297
2265
  /**
2298
2266
  * Get the camera's base level for calculating actual zoom levels based on the zoom steps.
@@ -2304,11 +2272,13 @@ class Editor extends import_eventemitter3.default {
2304
2272
  *
2305
2273
  * @public */
2306
2274
  getBaseZoom() {
2275
+ return this._getFitZoom(this.getCameraOptions().constraints?.baseZoom ?? "default");
2276
+ }
2277
+ _getFitZoom(fit) {
2307
2278
  const cameraOptions = this.getCameraOptions();
2308
- if (!cameraOptions.constraints) return 1;
2309
- if (cameraOptions.constraints.baseZoom === "default") return 1;
2279
+ if (!cameraOptions.constraints || fit === "default") return 1;
2310
2280
  const { zx, zy } = getCameraFitXFitY(this, cameraOptions);
2311
- switch (cameraOptions.constraints.baseZoom) {
2281
+ switch (fit) {
2312
2282
  case "fit-min": {
2313
2283
  return Math.max(zx, zy);
2314
2284
  }
@@ -2334,7 +2304,7 @@ class Editor extends import_eventemitter3.default {
2334
2304
  return Math.min(1, zy);
2335
2305
  }
2336
2306
  default: {
2337
- throw (0, import_utils.exhaustiveSwitchError)(cameraOptions.constraints.baseZoom);
2307
+ throw (0, import_utils.exhaustiveSwitchError)(fit);
2338
2308
  }
2339
2309
  }
2340
2310
  }
@@ -2368,7 +2338,7 @@ class Editor extends import_eventemitter3.default {
2368
2338
  ...this._cameraOptions.__unsafe__getWithoutCapture(),
2369
2339
  ...opts
2370
2340
  });
2371
- if (next.zoomSteps?.length < 1) next.zoomSteps = [1];
2341
+ if (!next.zoomSteps || next.zoomSteps.length < 1) next.zoomSteps = [1];
2372
2342
  this._cameraOptions.set(next);
2373
2343
  this.setCamera(this.getCamera());
2374
2344
  return this;
@@ -2389,8 +2359,8 @@ class Editor extends import_eventemitter3.default {
2389
2359
  const vsb = this.getViewportScreenBounds();
2390
2360
  if (cameraOptions.constraints) {
2391
2361
  const { constraints } = cameraOptions;
2392
- const py = Math.min(constraints.padding.y, vsb.w / 2);
2393
- const px = Math.min(constraints.padding.x, vsb.h / 2);
2362
+ const px = Math.min(constraints.padding.x, vsb.w / 2);
2363
+ const py = Math.min(constraints.padding.y, vsb.h / 2);
2394
2364
  const bounds = import_Box.Box.From(cameraOptions.constraints.bounds);
2395
2365
  const zx = (vsb.w - px * 2) / bounds.w;
2396
2366
  const zy = (vsb.h - py * 2) / bounds.h;
@@ -2429,12 +2399,12 @@ class Editor extends import_eventemitter3.default {
2429
2399
  break;
2430
2400
  }
2431
2401
  case "inside": {
2432
- if (z < zx) x = (0, import_utils2.clamp)(x, minX, (vsb.w - px) / z - bounds.w);
2402
+ if (z < zx) x = (0, import_utils2.clamp)(x, minX, (vsb.w - px) / z - bounds.w - bounds.x);
2433
2403
  else x = (0, import_utils2.clamp)(x, minX + freeW, minX);
2434
2404
  break;
2435
2405
  }
2436
2406
  case "outside": {
2437
- x = (0, import_utils2.clamp)(x, px / z - bounds.w, (vsb.w - px) / z);
2407
+ x = (0, import_utils2.clamp)(x, px / z - bounds.w - bounds.x, (vsb.w - px) / z - bounds.x);
2438
2408
  break;
2439
2409
  }
2440
2410
  case "free": {
@@ -2455,12 +2425,12 @@ class Editor extends import_eventemitter3.default {
2455
2425
  break;
2456
2426
  }
2457
2427
  case "inside": {
2458
- if (z < zy) y = (0, import_utils2.clamp)(y, minY, (vsb.h - py) / z - bounds.h);
2428
+ if (z < zy) y = (0, import_utils2.clamp)(y, minY, (vsb.h - py) / z - bounds.h - bounds.y);
2459
2429
  else y = (0, import_utils2.clamp)(y, minY + freeH, minY);
2460
2430
  break;
2461
2431
  }
2462
2432
  case "outside": {
2463
- y = (0, import_utils2.clamp)(y, py / z - bounds.h, (vsb.h - py) / z);
2433
+ y = (0, import_utils2.clamp)(y, py / z - bounds.h - bounds.y, (vsb.h - py) / z - bounds.y);
2464
2434
  break;
2465
2435
  }
2466
2436
  case "free": {
@@ -2828,9 +2798,9 @@ class Editor extends import_eventemitter3.default {
2828
2798
  }
2829
2799
  const remaining = duration - elapsed;
2830
2800
  const t = easing(1 - remaining / duration);
2831
- const left = start.minX + (end.minX - start.minX) * t;
2832
- const top = start.minY + (end.minY - start.minY) * t;
2833
- const right = start.maxX + (end.maxX - start.maxX) * t;
2801
+ const left = (0, import_utils.lerp)(start.minX, end.minX, t);
2802
+ const top = (0, import_utils.lerp)(start.minY, end.minY, t);
2803
+ const right = (0, import_utils.lerp)(start.maxX, end.maxX, t);
2834
2804
  this._setCamera(new import_Vec.Vec(-left, -top, this.getViewportScreenBounds().width / (right - left)), {
2835
2805
  force: true
2836
2806
  });
@@ -2908,7 +2878,7 @@ class Editor extends import_eventemitter3.default {
2908
2878
  let newCy = cy + dy;
2909
2879
  let newCz = cz;
2910
2880
  if (dirZ !== 0) {
2911
- newCz = cz * (1 + dirZ * currentSpeed * elapsed);
2881
+ newCz = cz * Math.exp(dirZ * currentSpeed * elapsed);
2912
2882
  const center = this.getViewportScreenCenter();
2913
2883
  newCx += center.x / newCz - center.x / cz;
2914
2884
  newCy += center.y / newCz - center.y / cz;
@@ -3346,12 +3316,12 @@ class Editor extends import_eventemitter3.default {
3346
3316
  const renderingShapes = [];
3347
3317
  let nextIndex = this.options.maxShapesPerPage * 2;
3348
3318
  let nextBackgroundIndex = this.options.maxShapesPerPage;
3349
- const erasingShapeIds = this.getErasingShapeIds();
3319
+ const erasingShapeIds = new Set(this.getErasingShapeIds());
3350
3320
  const addShapeById = (id, opacity, isAncestorErasing) => {
3351
3321
  const shape = this.getShape(id);
3352
3322
  if (!shape) return;
3353
3323
  if (this.isShapeHidden(shape)) {
3354
- const isErasing = isAncestorErasing || erasingShapeIds.includes(id);
3324
+ const isErasing = isAncestorErasing || erasingShapeIds.has(id);
3355
3325
  for (const childId of this.getSortedChildIdsForParent(id)) {
3356
3326
  addShapeById(childId, opacity, isErasing);
3357
3327
  }
@@ -3361,7 +3331,7 @@ class Editor extends import_eventemitter3.default {
3361
3331
  let isShapeErasing = false;
3362
3332
  const util = this.getShapeUtil(shape);
3363
3333
  if (useEditorState) {
3364
- isShapeErasing = !isAncestorErasing && erasingShapeIds.includes(id);
3334
+ isShapeErasing = !isAncestorErasing && erasingShapeIds.has(id);
3365
3335
  if (isShapeErasing) {
3366
3336
  opacity *= 0.32;
3367
3337
  }
@@ -3953,10 +3923,8 @@ class Editor extends import_eventemitter3.default {
3953
3923
  }
3954
3924
  _getShapePageBoundsCache() {
3955
3925
  return this.store.createComputedCache("pageBoundsCache", (shape) => {
3956
- const pageTransform = this.getShapePageTransform(shape);
3957
- if (!pageTransform) return void 0;
3958
3926
  return import_Box.Box.FromPoints(
3959
- pageTransform.applyToPoints(this.getShapeGeometry(shape).boundsVertices)
3927
+ this.getShapePageTransform(shape).applyToPoints(this.getShapeGeometry(shape).boundsVertices)
3960
3928
  );
3961
3929
  });
3962
3930
  }
@@ -4074,7 +4042,9 @@ class Editor extends import_eventemitter3.default {
4074
4042
  if (pageMask) {
4075
4043
  if (pageMask.length === 0) return void 0;
4076
4044
  const { corners } = pageBounds;
4077
- if (corners.every((p, i) => p && import_Vec.Vec.Equals(p, pageMask[i]))) return pageBounds.clone();
4045
+ if (pageMask.length === corners.length && corners.every((p, i) => import_Vec.Vec.Equals(p, pageMask[i]))) {
4046
+ return pageBounds.clone();
4047
+ }
4078
4048
  const intersection = (0, import_intersect.intersectPolygonPolygon)(pageMask, corners);
4079
4049
  if (!intersection) return;
4080
4050
  return import_Box.Box.FromPoints(intersection);
@@ -4298,23 +4268,22 @@ class Editor extends import_eventemitter3.default {
4298
4268
  let inMarginClosestToEdgeHit = null;
4299
4269
  const searchMargin = Math.max(innerMargin, outerMargin, this.getHitTestMargin());
4300
4270
  const candidateIds = this._spatialIndex.getShapeIdsAtPoint(point, searchMargin);
4301
- const shapesToCheck = (opts.renderingOnly ? this.getCurrentPageRenderingShapesSorted() : this.getCurrentPageShapesSorted()).filter((shape) => {
4302
- if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) return false;
4303
- if (shape.isLocked && !hitLocked || this.isShapeHidden(shape) || this.isShapeOfType(shape, "group"))
4304
- return false;
4305
- const pageMask = this.getShapeMask(shape);
4306
- if (pageMask && !(0, import_utils2.pointInPolygon)(point, pageMask)) return false;
4307
- if (filter && !filter(shape)) return false;
4308
- return true;
4309
- });
4271
+ const shapesToCheck = opts.renderingOnly ? this.getCurrentPageRenderingShapesSorted() : this.getCurrentPageShapesSorted();
4310
4272
  for (let i = shapesToCheck.length - 1; i >= 0; i--) {
4311
4273
  const shape = shapesToCheck[i];
4274
+ if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) continue;
4275
+ if (shape.isLocked && !hitLocked || this.isShapeHidden(shape) || this.isShapeOfType(shape, "group")) {
4276
+ continue;
4277
+ }
4278
+ const pageMask = this.getShapeMask(shape);
4279
+ if (pageMask && !(0, import_utils2.pointInPolygon)(point, pageMask)) continue;
4280
+ if (filter && !filter(shape)) continue;
4312
4281
  const geometry = this.getShapeGeometry(shape);
4313
4282
  const isGroup = geometry instanceof import_Group2d.Group2d;
4314
4283
  const pointInShapeSpace = this.getPointInShapeSpace(shape, point);
4315
4284
  const shapeUtil = this.getShapeUtil(shape);
4316
4285
  const isShapeFrameLike = this.isShapeFrameLike(shape);
4317
- if (isShapeFrameLike || (this.isShapeOfType(shape, "note") || this.isShapeOfType(shape, "arrow") || this.isShapeOfType(shape, "geo") && shape.props.fill === "none") && shapeUtil.getText(shape)?.trim()) {
4286
+ if (isGroup && (isShapeFrameLike || (this.isShapeOfType(shape, "note") || this.isShapeOfType(shape, "arrow") || this.isShapeOfType(shape, "geo") && shape.props.fill === "none") && shapeUtil.getText(shape)?.trim())) {
4318
4287
  for (const childGeometry of geometry.children) {
4319
4288
  if (childGeometry.isLabel && childGeometry.isPointInBounds(pointInShapeSpace)) {
4320
4289
  return shape;
@@ -4413,11 +4382,15 @@ class Editor extends import_eventemitter3.default {
4413
4382
  getShapesAtPoint(point, opts = {}) {
4414
4383
  const margin = opts.margin ?? 0;
4415
4384
  const candidateIds = this._spatialIndex.getShapeIdsAtPoint(point, margin);
4416
- return this.getCurrentPageShapesSorted().filter((shape) => {
4417
- if (this.isShapeHidden(shape)) return false;
4418
- if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) return false;
4419
- return this.isPointInShape(shape, point, opts);
4420
- }).reverse();
4385
+ const sorted = this.getCurrentPageShapesSorted();
4386
+ const result = [];
4387
+ for (let i = sorted.length - 1; i >= 0; i--) {
4388
+ const shape = sorted[i];
4389
+ if (this.isShapeHidden(shape)) continue;
4390
+ if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) continue;
4391
+ if (this.isPointInShape(shape, point, opts)) result.push(shape);
4392
+ }
4393
+ return result;
4421
4394
  }
4422
4395
  /**
4423
4396
  * Get shape IDs within the given bounds.
@@ -4502,9 +4475,7 @@ class Editor extends import_eventemitter3.default {
4502
4475
  const freshShape = this.getShape(id);
4503
4476
  if (!freshShape) return new import_Vec.Vec(0, 0);
4504
4477
  if ((0, import_tlschema.isPageId)(freshShape.parentId)) return import_Vec.Vec.From(point);
4505
- const parentTransform = this.getShapePageTransform(freshShape.parentId);
4506
- if (!parentTransform) return import_Vec.Vec.From(point);
4507
- return parentTransform.clone().invert().applyToPoint(point);
4478
+ return this.getShapePageTransform(freshShape.parentId).clone().invert().applyToPoint(point);
4508
4479
  }
4509
4480
  getCurrentPageShapes() {
4510
4481
  return Array.from(this.getCurrentPageShapeIds(), (id) => this.store.get(id));
@@ -4616,23 +4587,7 @@ class Editor extends import_eventemitter3.default {
4616
4587
  * @public
4617
4588
  */
4618
4589
  isShapeInPage(shape, pageId = this.getCurrentPageId()) {
4619
- const id = typeof shape === "string" ? shape : shape.id;
4620
- const shapeToCheck = this.getShape(id);
4621
- if (!shapeToCheck) return false;
4622
- let shapeIsInPage = false;
4623
- if (shapeToCheck.parentId === pageId) {
4624
- shapeIsInPage = true;
4625
- } else {
4626
- let parent = this.getShape(shapeToCheck.parentId);
4627
- isInPageSearch: while (parent) {
4628
- if (parent.parentId === pageId) {
4629
- shapeIsInPage = true;
4630
- break isInPageSearch;
4631
- }
4632
- parent = this.getShape(parent.parentId);
4633
- }
4634
- }
4635
- return shapeIsInPage;
4590
+ return this.getAncestorPageId(shape) === pageId;
4636
4591
  }
4637
4592
  /**
4638
4593
  * Get the id of the containing page for a given shape.
@@ -4713,10 +4668,7 @@ class Editor extends import_eventemitter3.default {
4713
4668
  for (let i = 0; i < shapesToReparent.length; i++) {
4714
4669
  const shape = shapesToReparent[i];
4715
4670
  const pageTransform = this.getShapePageTransform(shape);
4716
- if (!pageTransform) continue;
4717
- const pagePoint = pageTransform.point();
4718
- if (!pagePoint) continue;
4719
- const newPoint = invertedParentTransform.applyToPoint(pagePoint);
4671
+ const newPoint = invertedParentTransform.applyToPoint(pageTransform.point());
4720
4672
  const newRotation = pageTransform.rotation() - parentPageRotation;
4721
4673
  if (shape.id === parentId) {
4722
4674
  throw Error("Attempted to reparent a shape to itself!");
@@ -4805,7 +4757,7 @@ class Editor extends import_eventemitter3.default {
4805
4757
  */
4806
4758
  getShapeAndDescendantIds(ids) {
4807
4759
  const shapeIds = /* @__PURE__ */ new Set();
4808
- for (const shape of ids.map((id) => this.getShape(id)).sort(import_utils.sortByIndex)) {
4760
+ for (const shape of (0, import_utils.compact)(ids.map((id) => this.getShape(id))).sort(import_utils.sortByIndex)) {
4809
4761
  shapeIds.add(shape.id);
4810
4762
  this.visitDescendants(shape, (descendantId) => {
4811
4763
  shapeIds.add(descendantId);
@@ -4827,11 +4779,12 @@ class Editor extends import_eventemitter3.default {
4827
4779
  const draggingShapes = (0, import_utils.compact)(droppingShapes.map((s) => this.getShape(s))).filter(
4828
4780
  (s) => !s.isLocked && !this.isShapeHidden(s)
4829
4781
  );
4782
+ const excludedIds = this.getShapeAndDescendantIds(draggingShapes.map((s) => s.id));
4830
4783
  const maybeDraggingOverShapes = this.getShapesAtPoint(point, {
4831
4784
  hitInside: true,
4832
4785
  margin: 0
4833
4786
  }).filter(
4834
- (s) => !droppingShapes.includes(s) && !s.isLocked && !this.isShapeHidden(s) && !draggingShapes.includes(s)
4787
+ (s) => !droppingShapes.includes(s) && !s.isLocked && !this.isShapeHidden(s) && !excludedIds.has(s.id)
4835
4788
  );
4836
4789
  for (const maybeDraggingOverShape of maybeDraggingOverShapes) {
4837
4790
  const shapeUtil = this.getShapeUtil(maybeDraggingOverShape);
@@ -5084,8 +5037,7 @@ class Editor extends import_eventemitter3.default {
5084
5037
  for (const id of ids) {
5085
5038
  const shape = this.getShape(id);
5086
5039
  const localDelta = import_Vec.Vec.From(offset);
5087
- const parentTransform = this.getShapeParentTransform(shape);
5088
- if (parentTransform) localDelta.rot(-parentTransform.rotation());
5040
+ localDelta.rot(-this.getShapeParentTransform(shape).rotation());
5089
5041
  changes.push(this.getChangesToTranslateShape(shape, localDelta.add(shape)));
5090
5042
  }
5091
5043
  this.updateShapes(changes);
@@ -5140,7 +5092,7 @@ class Editor extends import_eventemitter3.default {
5140
5092
  if (!originalShape) continue;
5141
5093
  let ox = 0;
5142
5094
  let oy = 0;
5143
- if (offset && initialIds.has(originalId)) {
5095
+ if (offset && initialIds.has(originalId) && !shapeIdSet.has(originalShape.parentId)) {
5144
5096
  const parentTransform = this.getShapeParentTransform(originalShape);
5145
5097
  const vec = new import_Vec.Vec(offset.x, offset.y).rot(-parentTransform.rotation());
5146
5098
  ox = vec.x;
@@ -5254,26 +5206,17 @@ class Editor extends import_eventemitter3.default {
5254
5206
  toggleLock(shapes) {
5255
5207
  const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
5256
5208
  if (this.getIsReadonly() || ids.length === 0) return this;
5257
- let allLocked = true, allUnlocked = true;
5209
+ let allLocked = true;
5258
5210
  const shapesToToggle = [];
5259
5211
  for (const id of ids) {
5260
5212
  const shape = this.getShape(id);
5261
5213
  if (shape) {
5262
5214
  shapesToToggle.push(shape);
5263
- if (shape.isLocked) {
5264
- allUnlocked = false;
5265
- } else {
5266
- allLocked = false;
5267
- }
5215
+ if (!shape.isLocked) allLocked = false;
5268
5216
  }
5269
5217
  }
5270
5218
  this.run(() => {
5271
- if (allUnlocked) {
5272
- this.updateShapes(
5273
- shapesToToggle.map((shape) => ({ id: shape.id, type: shape.type, isLocked: true }))
5274
- );
5275
- this.setSelectedShapes([]);
5276
- } else if (allLocked) {
5219
+ if (allLocked) {
5277
5220
  this.updateShapes(
5278
5221
  shapesToToggle.map((shape) => ({ id: shape.id, type: shape.type, isLocked: false }))
5279
5222
  );
@@ -5281,6 +5224,7 @@ class Editor extends import_eventemitter3.default {
5281
5224
  this.updateShapes(
5282
5225
  shapesToToggle.map((shape) => ({ id: shape.id, type: shape.type, isLocked: true }))
5283
5226
  );
5227
+ this.setSelectedShapes([]);
5284
5228
  }
5285
5229
  });
5286
5230
  return this;
@@ -5391,9 +5335,10 @@ class Editor extends import_eventemitter3.default {
5391
5335
  const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
5392
5336
  let freshShapes = (0, import_utils.compact)(ids.map((id) => this.getShape(id)));
5393
5337
  if (opts?.filterAxisAligned) {
5394
- freshShapes = freshShapes.filter(
5395
- (s) => this.getShapePageTransform(s)?.rotation() % (import_utils2.PI / 2) === 0
5396
- );
5338
+ freshShapes = freshShapes.filter((s) => {
5339
+ const remainder = Math.abs(this.getShapePageTransform(s).rotation() % import_utils2.HALF_PI);
5340
+ return Math.min(remainder, import_utils2.HALF_PI - remainder) < 1e-9;
5341
+ });
5397
5342
  }
5398
5343
  const clusters = [];
5399
5344
  const allBounds = [];
@@ -5558,9 +5503,9 @@ class Editor extends import_eventemitter3.default {
5558
5503
  dim = "height";
5559
5504
  }
5560
5505
  let shapeGap = 0;
5506
+ shapeClustersToStack.sort((a, b) => a.pageBounds[min] - b.pageBounds[min]);
5561
5507
  if (_gap === 0) {
5562
5508
  const gaps = {};
5563
- shapeClustersToStack.sort((a, b) => a.pageBounds[min] - b.pageBounds[min]);
5564
5509
  for (let i = 0; i < len - 1; i++) {
5565
5510
  const currCluster = shapeClustersToStack[i];
5566
5511
  const nextCluster = shapeClustersToStack[i + 1];
@@ -5598,8 +5543,7 @@ class Editor extends import_eventemitter3.default {
5598
5543
  const shapeDelta = delta.clone();
5599
5544
  const parent = this.getShapeParent(shape);
5600
5545
  if (parent) {
5601
- const parentTransform = this.getShapePageTransform(parent);
5602
- if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
5546
+ shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
5603
5547
  }
5604
5548
  shapeDelta.add(shape);
5605
5549
  changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
@@ -5637,7 +5581,7 @@ class Editor extends import_eventemitter3.default {
5637
5581
  }
5638
5582
  const commonBounds = import_Box.Box.Common(allBounds);
5639
5583
  const maxWidth = commonBounds.width;
5640
- shapeClustersToPack.sort((a, b) => a.pageBounds.width - b.pageBounds.width).sort((a, b) => a.pageBounds.height - b.pageBounds.height);
5584
+ shapeClustersToPack.sort((a, b) => b.pageBounds.width - a.pageBounds.width).sort((a, b) => b.pageBounds.height - a.pageBounds.height);
5641
5585
  const startWidth = Math.max(Math.ceil(Math.sqrt(area / 0.95)), maxWidth);
5642
5586
  const spaces = [new import_Box.Box(commonBounds.x, commonBounds.y, startWidth, Infinity)];
5643
5587
  let width = 0;
@@ -5685,8 +5629,7 @@ class Editor extends import_eventemitter3.default {
5685
5629
  const shapeDelta = delta.clone();
5686
5630
  const parent = this.getShapeParent(shape);
5687
5631
  if (parent) {
5688
- const parentTransform = this.getShapeParentTransform(shape);
5689
- if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
5632
+ shapeDelta.rot(-this.getShapeParentTransform(shape).rotation());
5690
5633
  }
5691
5634
  shapeDelta.add(shape);
5692
5635
  changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
@@ -5752,8 +5695,7 @@ class Editor extends import_eventemitter3.default {
5752
5695
  const shapeDelta = delta.clone();
5753
5696
  const parent = this.getShapeParent(shape);
5754
5697
  if (parent) {
5755
- const parentTransform = this.getShapePageTransform(parent);
5756
- if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
5698
+ shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
5757
5699
  }
5758
5700
  shapeDelta.add(shape);
5759
5701
  changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
@@ -5827,8 +5769,7 @@ class Editor extends import_eventemitter3.default {
5827
5769
  const shapeDelta = delta.clone();
5828
5770
  const parent = this.getShapeParent(shape);
5829
5771
  if (parent) {
5830
- const parentTransform = this.getShapePageTransform(parent);
5831
- if (parentTransform) shapeDelta.rot(-parentTransform.rotation());
5772
+ shapeDelta.rot(-this.getShapePageTransform(parent).rotation());
5832
5773
  }
5833
5774
  shapeDelta.add(shape);
5834
5775
  changes.push(this.getChangesToTranslateShape(shape, shapeDelta));
@@ -5883,8 +5824,7 @@ class Editor extends import_eventemitter3.default {
5883
5824
  scale[val] = commonBounds[dim] / pageBounds[dim];
5884
5825
  for (const shape of shapes2) {
5885
5826
  const shapeLocalOffset = localOffset.clone();
5886
- const parentTransform = this.getShapeParentTransform(shape);
5887
- if (parentTransform) shapeLocalOffset.rot(-parentTransform.rotation());
5827
+ shapeLocalOffset.rot(-this.getShapeParentTransform(shape).rotation());
5888
5828
  shapeLocalOffset.add(shape);
5889
5829
  const changes = this.getChangesToTranslateShape(shape, shapeLocalOffset);
5890
5830
  this.updateShape(changes);
@@ -5940,8 +5880,7 @@ class Editor extends import_eventemitter3.default {
5940
5880
  );
5941
5881
  for (const shape of shapes2) {
5942
5882
  const shapeLocalOffset = localOffset.clone();
5943
- const parentTransform = this.getShapeParentTransform(shape);
5944
- if (parentTransform) shapeLocalOffset.rot(-parentTransform.rotation());
5883
+ shapeLocalOffset.rot(-this.getShapeParentTransform(shape).rotation());
5945
5884
  shapeLocalOffset.add(shape);
5946
5885
  const changes = this.getChangesToTranslateShape(shape, shapeLocalOffset);
5947
5886
  this.updateShape(changes);
@@ -5990,9 +5929,7 @@ class Editor extends import_eventemitter3.default {
5990
5929
  const scaleOrigin = opts.scaleOrigin ?? this.getShapePageBounds(id)?.center;
5991
5930
  if (!scaleOrigin) return null;
5992
5931
  const pageTransform = opts.initialPageTransform ? import_Mat.Mat.Cast(opts.initialPageTransform) : this.getShapePageTransform(id);
5993
- if (!pageTransform) return null;
5994
5932
  const pageRotation = pageTransform.rotation();
5995
- if (pageRotation == null) return null;
5996
5933
  const scaleAxisRotation = opts.scaleAxisRotation ?? pageRotation;
5997
5934
  const initialBounds = opts.initialBounds ?? this.getShapeGeometry(id).bounds;
5998
5935
  if (!initialBounds) return null;
@@ -6143,7 +6080,6 @@ class Editor extends import_eventemitter3.default {
6143
6080
  const currentLocalBounds = this.getShapeGeometry(id).bounds;
6144
6081
  const currentPageCenter = import_Mat.Mat.applyToPoint(pageTransform, currentLocalBounds.center);
6145
6082
  const shapePageTransformOrigin = pageTransform.point();
6146
- if (!currentPageCenter || !shapePageTransformOrigin) return this;
6147
6083
  const pageDelta = import_Vec.Vec.Sub(postScaleShapePageCenter, currentPageCenter);
6148
6084
  const postScaleShapePagePoint = import_Vec.Vec.Add(shapePageTransformOrigin, pageDelta);
6149
6085
  const { x, y } = this.getPointInParentSpace(id, postScaleShapePagePoint);
@@ -6402,10 +6338,10 @@ class Editor extends import_eventemitter3.default {
6402
6338
  if (animationIdForShape !== animationId) continue;
6403
6339
  updates.push({
6404
6340
  ...end,
6405
- x: start.x + (end.x - start.x) * t,
6406
- y: start.y + (end.y - start.y) * t,
6407
- opacity: start.opacity + (end.opacity - start.opacity) * t,
6408
- rotation: start.rotation + (end.rotation - start.rotation) * t,
6341
+ x: (0, import_utils.lerp)(start.x, end.x, t),
6342
+ y: (0, import_utils.lerp)(start.y, end.y, t),
6343
+ opacity: (0, import_utils.lerp)(start.opacity, end.opacity, t),
6344
+ rotation: (0, import_utils.lerp)(start.rotation, end.rotation, t),
6409
6345
  props: this.getShapeUtil(end).getInterpolatedProps?.(start, end, t) ?? end.props
6410
6346
  });
6411
6347
  }
@@ -6531,7 +6467,7 @@ class Editor extends import_eventemitter3.default {
6531
6467
  * @public
6532
6468
  */
6533
6469
  updateShapes(partials) {
6534
- const compactedPartials = Array(partials.length);
6470
+ const compactedPartials = [];
6535
6471
  for (let i = 0, n = partials.length; i < n; i++) {
6536
6472
  const partial = partials[i];
6537
6473
  if (!partial) continue;
@@ -6602,28 +6538,32 @@ class Editor extends import_eventemitter3.default {
6602
6538
  }
6603
6539
  /* --------------------- Styles --------------------- */
6604
6540
  /**
6605
- * Get all the current styles among the users selected shapes
6541
+ * Groups have no styles of their own: a style read or write on a selection applies to the
6542
+ * non-group shapes beneath each group, however deeply nested. Returns those shapes.
6606
6543
  *
6607
6544
  * @internal
6608
6545
  */
6609
- _extractSharedStyles(shape, sharedStyleMap) {
6610
- if (this.isShapeOfType(shape, "group")) {
6611
- const childIds = this._parentIdsToChildIds.get()[shape.id];
6612
- if (!childIds) return;
6613
- for (let i = 0, n = childIds.length; i < n; i++) {
6614
- this._extractSharedStyles(this.getShape(childIds[i]), sharedStyleMap);
6615
- }
6616
- } else {
6617
- for (const [style, propKey] of this.styleProps[shape.type]) {
6618
- sharedStyleMap.applyValue(style, (0, import_utils.getOwnProperty)(shape.props, propKey));
6546
+ _getStyleableShapes(shapes) {
6547
+ const result = [];
6548
+ const visit = (shape) => {
6549
+ if (this.isShapeOfType(shape, "group")) {
6550
+ for (const childId of this.getSortedChildIdsForParent(shape.id)) {
6551
+ const child = this.getShape(childId);
6552
+ if (child) visit(child);
6553
+ }
6554
+ } else {
6555
+ result.push(shape);
6619
6556
  }
6620
- }
6557
+ };
6558
+ for (const shape of shapes) visit(shape);
6559
+ return result;
6621
6560
  }
6622
6561
  _getSelectionSharedStyles() {
6623
- const selectedShapes = this.getSelectedShapes();
6624
6562
  const sharedStyles = new import_SharedStylesMap.SharedStyleMap();
6625
- for (const selectedShape of selectedShapes) {
6626
- this._extractSharedStyles(selectedShape, sharedStyles);
6563
+ for (const shape of this._getStyleableShapes(this.getSelectedShapes())) {
6564
+ for (const [style, propKey] of this.styleProps[shape.type]) {
6565
+ sharedStyles.applyValue(style, (0, import_utils.getOwnProperty)(shape.props, propKey));
6566
+ }
6627
6567
  }
6628
6568
  return sharedStyles;
6629
6569
  }
@@ -6655,38 +6595,16 @@ class Editor extends import_eventemitter3.default {
6655
6595
  const styles = new import_SharedStylesMap.SharedStyleMap();
6656
6596
  if (!currentTool) return styles;
6657
6597
  if (currentTool.shapeType) {
6658
- if (currentTool.shapeType === "frame" && !this.getShapeUtil("frame").options.showColors) {
6659
- for (const style of this.styleProps[currentTool.shapeType].keys()) {
6660
- if (style.id === "tldraw:color") continue;
6661
- styles.applyValue(style, this.getStyleForNextShape(style));
6662
- }
6663
- } else {
6664
- for (const style of this.styleProps[currentTool.shapeType].keys()) {
6665
- styles.applyValue(style, this.getStyleForNextShape(style));
6666
- }
6598
+ for (const style of this.styleProps[currentTool.shapeType].keys()) {
6599
+ styles.applyValue(style, this.getStyleForNextShape(style));
6667
6600
  }
6668
6601
  }
6669
6602
  return styles;
6670
6603
  }
6671
6604
  getSharedOpacity() {
6672
6605
  if (this.isIn("select") && this.getSelectedShapeIds().length > 0) {
6673
- const shapesToCheck = [];
6674
- const addShape = (shapeId) => {
6675
- const shape = this.getShape(shapeId);
6676
- if (!shape) return;
6677
- if (this.isShapeOfType(shape, "group")) {
6678
- for (const childId of this.getSortedChildIdsForParent(shape.id)) {
6679
- addShape(childId);
6680
- }
6681
- } else {
6682
- shapesToCheck.push(shape);
6683
- }
6684
- };
6685
- for (const shapeId of this.getSelectedShapeIds()) {
6686
- addShape(shapeId);
6687
- }
6688
6606
  let opacity = null;
6689
- for (const shape of shapesToCheck) {
6607
+ for (const shape of this._getStyleableShapes(this.getSelectedShapes())) {
6690
6608
  if (opacity === null) {
6691
6609
  opacity = shape.opacity;
6692
6610
  } else if (opacity !== shape.opacity) {
@@ -6725,28 +6643,12 @@ class Editor extends import_eventemitter3.default {
6725
6643
  setOpacityForSelectedShapes(opacity) {
6726
6644
  const selectedShapes = this.getSelectedShapes();
6727
6645
  if (selectedShapes.length > 0) {
6728
- const shapesToUpdate = [];
6729
- const addShapeById = (shape) => {
6730
- if (this.isShapeOfType(shape, "group")) {
6731
- const childIds = this.getSortedChildIdsForParent(shape);
6732
- for (const childId of childIds) {
6733
- addShapeById(this.getShape(childId));
6734
- }
6735
- } else {
6736
- shapesToUpdate.push(shape);
6737
- }
6738
- };
6739
- for (const id of selectedShapes) {
6740
- addShapeById(id);
6741
- }
6742
6646
  this.updateShapes(
6743
- shapesToUpdate.map((shape) => {
6744
- return {
6745
- id: shape.id,
6746
- type: shape.type,
6747
- opacity
6748
- };
6749
- })
6647
+ this._getStyleableShapes(selectedShapes).map((shape) => ({
6648
+ id: shape.id,
6649
+ type: shape.type,
6650
+ opacity
6651
+ }))
6750
6652
  );
6751
6653
  }
6752
6654
  return this;
@@ -6791,33 +6693,17 @@ class Editor extends import_eventemitter3.default {
6791
6693
  const selectedShapes = this.getSelectedShapes();
6792
6694
  if (selectedShapes.length > 0) {
6793
6695
  const updates = [];
6794
- const addShapeById = (shape) => {
6795
- if (this.isShapeOfType(shape, "group")) {
6796
- const childIds = this.getSortedChildIdsForParent(shape.id);
6797
- for (const childId of childIds) {
6798
- addShapeById(this.getShape(childId));
6799
- }
6800
- } else {
6801
- const util = this.getShapeUtil(shape);
6802
- const stylePropKey = this.styleProps[shape.type].get(style);
6803
- if (stylePropKey) {
6804
- const shapePartial = {
6805
- id: shape.id,
6806
- type: shape.type,
6807
- props: { [stylePropKey]: value }
6808
- };
6809
- updates.push({
6810
- util,
6811
- originalShape: shape,
6812
- updatePartial: shapePartial
6813
- });
6814
- }
6696
+ for (const shape of this._getStyleableShapes(selectedShapes)) {
6697
+ const stylePropKey = this.styleProps[shape.type].get(style);
6698
+ if (stylePropKey) {
6699
+ updates.push({
6700
+ id: shape.id,
6701
+ type: shape.type,
6702
+ props: { [stylePropKey]: value }
6703
+ });
6815
6704
  }
6816
- };
6817
- for (const shape of selectedShapes) {
6818
- addShapeById(shape);
6819
6705
  }
6820
- this.updateShapes(updates.map(({ updatePartial }) => updatePartial));
6706
+ this.updateShapes(updates);
6821
6707
  }
6822
6708
  return this;
6823
6709
  }
@@ -7213,7 +7099,6 @@ class Editor extends import_eventemitter3.default {
7213
7099
  if (shapeIdMap.has(newShape.parentId)) {
7214
7100
  newShape.parentId = shapeIdMap.get(oldShape.parentId);
7215
7101
  } else {
7216
- rootShapeIds.push(newShape.id);
7217
7102
  newShape.index = index;
7218
7103
  index = (0, import_utils.getIndexAbove)(index);
7219
7104
  }
@@ -7238,8 +7123,11 @@ class Editor extends import_eventemitter3.default {
7238
7123
  continue;
7239
7124
  }
7240
7125
  if (asset.type === "image" && asset.props.src?.startsWith("data:image") || asset.type === "video" && asset.props.src?.startsWith("data:video")) {
7241
- assetsToUpdate.push((0, import_utils.structuredClone)(asset));
7242
- asset.props.src = null;
7126
+ assetsToUpdate.push(asset);
7127
+ const assetWithoutSrc = (0, import_utils.structuredClone)(asset);
7128
+ assetWithoutSrc.props.src = null;
7129
+ assetsToCreate.push(assetWithoutSrc);
7130
+ continue;
7243
7131
  }
7244
7132
  assetsToCreate.push(asset);
7245
7133
  }
@@ -8066,7 +7954,7 @@ class Editor extends import_eventemitter3.default {
8066
7954
  if (info.type === "misc") {
8067
7955
  if (info.name === "cancel" || info.name === "complete") {
8068
7956
  this.inputs.setIsDragging(false);
8069
- if (this.inputs.getIsPanning()) {
7957
+ if (this.inputs.getIsPanning() && !this.inputs.keys.has("Space")) {
8070
7958
  this.inputs.setIsPanning(false);
8071
7959
  this.inputs.setIsSpacebarPanning(false);
8072
7960
  this.setCursor({ type: this._prevCursor, rotation: 0 });
@@ -8818,10 +8706,9 @@ function withIsolatedShapes(editor, shapeIds, callback) {
8818
8706
  }
8819
8707
  function getCameraFitXFitY(editor, cameraOptions) {
8820
8708
  if (!cameraOptions.constraints) throw Error("Should have constraints here");
8821
- const {
8822
- padding: { x: px, y: py }
8823
- } = cameraOptions.constraints;
8824
8709
  const vsb = editor.getViewportScreenBounds();
8710
+ const px = Math.min(cameraOptions.constraints.padding.x, vsb.w / 2);
8711
+ const py = Math.min(cameraOptions.constraints.padding.y, vsb.h / 2);
8825
8712
  const bounds = import_Box.Box.From(cameraOptions.constraints.bounds);
8826
8713
  const zx = (vsb.w - px * 2) / bounds.w;
8827
8714
  const zy = (vsb.h - py * 2) / bounds.h;