@tldraw/editor 5.5.0-canary.ccc28ba47d5e → 5.5.0-canary.ccee63fc4a00

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 (77) hide show
  1. package/dist-cjs/index.d.ts +17 -11
  2. package/dist-cjs/index.js +1 -1
  3. package/dist-cjs/lib/editor/Editor.js +31 -20
  4. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  5. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +3 -2
  6. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
  7. package/dist-cjs/lib/editor/managers/EditorManager.js +11 -2
  8. package/dist-cjs/lib/editor/managers/EditorManager.js.map +2 -2
  9. package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceManager.js +49 -63
  10. package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceManager.js.map +2 -2
  11. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +1 -1
  12. package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +2 -2
  13. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +24 -24
  14. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +2 -2
  15. package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js +7 -1
  16. package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js.map +2 -2
  17. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +4 -3
  18. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
  19. package/dist-cjs/lib/editor/shapes/shared/resizeBox.js +21 -16
  20. package/dist-cjs/lib/editor/shapes/shared/resizeBox.js.map +2 -2
  21. package/dist-cjs/lib/hooks/useCursor.js +12 -8
  22. package/dist-cjs/lib/hooks/useCursor.js.map +2 -2
  23. package/dist-cjs/lib/utils/sync/LocalIndexedDb.js +10 -1
  24. package/dist-cjs/lib/utils/sync/LocalIndexedDb.js.map +2 -2
  25. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +12 -5
  26. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
  27. package/dist-cjs/version.js +3 -3
  28. package/dist-cjs/version.js.map +1 -1
  29. package/dist-esm/index.d.mts +17 -11
  30. package/dist-esm/index.mjs +1 -1
  31. package/dist-esm/lib/editor/Editor.mjs +33 -21
  32. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  33. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +3 -2
  34. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
  35. package/dist-esm/lib/editor/managers/EditorManager.mjs +11 -2
  36. package/dist-esm/lib/editor/managers/EditorManager.mjs.map +2 -2
  37. package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceManager.mjs +49 -63
  38. package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceManager.mjs.map +2 -2
  39. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +1 -1
  40. package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +2 -2
  41. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +24 -24
  42. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +2 -2
  43. package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs +7 -1
  44. package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs.map +2 -2
  45. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +4 -3
  46. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
  47. package/dist-esm/lib/editor/shapes/shared/resizeBox.mjs +21 -16
  48. package/dist-esm/lib/editor/shapes/shared/resizeBox.mjs.map +2 -2
  49. package/dist-esm/lib/hooks/useCursor.mjs +12 -8
  50. package/dist-esm/lib/hooks/useCursor.mjs.map +2 -2
  51. package/dist-esm/lib/utils/sync/LocalIndexedDb.mjs +10 -1
  52. package/dist-esm/lib/utils/sync/LocalIndexedDb.mjs.map +2 -2
  53. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +13 -6
  54. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
  55. package/dist-esm/version.mjs +3 -3
  56. package/dist-esm/version.mjs.map +1 -1
  57. package/package.json +16 -18
  58. package/src/lib/editor/Editor.ts +54 -25
  59. package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +1 -0
  60. package/src/lib/editor/managers/ClickManager/ClickManager.ts +3 -2
  61. package/src/lib/editor/managers/EditorManager.test.ts +32 -1
  62. package/src/lib/editor/managers/EditorManager.ts +15 -3
  63. package/src/lib/editor/managers/PerformanceManager/PerformanceManager.test.ts +80 -0
  64. package/src/lib/editor/managers/PerformanceManager/PerformanceManager.ts +54 -81
  65. package/src/lib/editor/managers/ScribbleManager/ScribbleManager.ts +1 -1
  66. package/src/lib/editor/managers/SnapManager/BoundsSnaps.ts +32 -36
  67. package/src/lib/editor/managers/SnapManager/HandleSnaps.ts +13 -2
  68. package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +13 -0
  69. package/src/lib/editor/managers/SnapManager/SnapManager.ts +6 -4
  70. package/src/lib/editor/shapes/shared/resizeBox.ts +21 -16
  71. package/src/lib/hooks/useCursor.ts +14 -7
  72. package/src/lib/test/useCursor.test.tsx +36 -0
  73. package/src/lib/utils/sync/LocalIndexedDb.test.ts +26 -1
  74. package/src/lib/utils/sync/LocalIndexedDb.ts +10 -1
  75. package/src/lib/utils/sync/TLLocalSyncClient.test.ts +73 -0
  76. package/src/lib/utils/sync/TLLocalSyncClient.ts +24 -8
  77. package/src/version.ts +3 -3
@@ -1274,6 +1274,9 @@ export declare class Editor extends EventEmitter<TLEventMap> {
1274
1274
  * @public
1275
1275
  */
1276
1276
  readonly timers: {
1277
+ cancelAnimationFrame: (id: number | undefined) => void;
1278
+ clearInterval: (id: number | undefined) => void;
1279
+ clearTimeout: (id: number | undefined) => void;
1277
1280
  dispose: () => void;
1278
1281
  requestAnimationFrame: (callback: FrameRequestCallback) => number;
1279
1282
  setInterval: (handler: TimerHandler, timeout?: number, ...args: any[]) => number;
@@ -4576,6 +4579,8 @@ export declare const EditorContext: React_3.Context<Editor | null>;
4576
4579
  * - Reaction (`react(...)` from `@tldraw/state`): `this.register(react(...))`
4577
4580
  * - DOM listener: `this.register(() => el.removeEventListener(...))`
4578
4581
  * - Other resource (cache, index, child manager): `this.register(() => x.dispose())`
4582
+ * - Resource held only part of the time (a listener attached while subscribers exist):
4583
+ * `this.register(...)` on attach and `this.unregister(...)` on detach, see `PerformanceManager`
4579
4584
  *
4580
4585
  * For timeouts, intervals, and animation frames prefer `editor.timers` (context-grouped
4581
4586
  * and auto-disposed) over raw `setTimeout`. For cleanup on the editor itself rather than a
@@ -4595,11 +4600,18 @@ export declare abstract class EditorManager {
4595
4600
  * make a resource "see itself out". Returns the same function for convenience.
4596
4601
  */
4597
4602
  protected register(dispose: () => void): () => void;
4603
+ /**
4604
+ * Run a registered teardown now instead of at `dispose()`. A teardown that is no longer
4605
+ * registered (already run by `dispose()`, or never registered) is skipped, so nothing is
4606
+ * torn down twice.
4607
+ */
4608
+ protected unregister(dispose: () => void): void;
4598
4609
  /**
4599
4610
  * Subscribe to an editor bus event and register the matching unsubscribe, so the listener
4600
- * is removed automatically on `dispose()`.
4611
+ * is removed automatically on `dispose()`. Returns that unsubscribe, for passing to
4612
+ * {@link EditorManager.unregister} to detach it before `dispose()`.
4601
4613
  */
4602
- protected addEditorEvent<E extends keyof TLEventMap>(event: E, fn: (...args: TLEventMap[E]) => void): void;
4614
+ protected addEditorEvent<E extends keyof TLEventMap>(event: E, fn: (...args: TLEventMap[E]) => void): () => void;
4603
4615
  /* Excluded from this release type: dispose */
4604
4616
  }
4605
4617
 
@@ -5987,17 +5999,11 @@ export declare class PerformanceApiAdapter {
5987
5999
  *
5988
6000
  * @public
5989
6001
  */
5990
- export declare class PerformanceManager {
6002
+ export declare class PerformanceManager extends EditorManager {
5991
6003
  /* Excluded from this release type: emitter */
5992
- private editor;
5993
6004
  private activeInteraction;
5994
6005
  private activeCamera;
5995
- private frameCleanup;
5996
- private shapeCreatedCleanup;
5997
- private shapeEditedCleanup;
5998
- private shapeDeletedCleanup;
5999
- private loafObserver;
6000
- constructor(editor: Editor);
6006
+ private readonly lazyCleanups;
6001
6007
  /**
6002
6008
  * Subscribe to a performance event. Returns an unsubscribe function.
6003
6009
  *
@@ -6031,11 +6037,11 @@ export declare class PerformanceManager {
6031
6037
  private _onShapesEdited;
6032
6038
  private _onShapesDeleted;
6033
6039
  private _startLoafObserver;
6034
- private _stopLoafObserver;
6035
6040
  private _needsFrameListener;
6036
6041
  private _needsLoafObserver;
6037
6042
  private _maybeAttachLazyListeners;
6038
6043
  private _maybeDetachLazyListeners;
6044
+ private _detachLazy;
6039
6045
  }
6040
6046
 
6041
6047
  /**
package/dist-cjs/index.js CHANGED
@@ -392,7 +392,7 @@ var import_uniq = require("./lib/utils/uniq");
392
392
  var import_defaultThemes2 = require("./lib/editor/managers/ThemeManager/defaultThemes");
393
393
  (0, import_utils.registerTldrawLibraryVersion)(
394
394
  "@tldraw/editor",
395
- "5.5.0-canary.ccc28ba47d5e",
395
+ "5.5.0-canary.ccee63fc4a00",
396
396
  "cjs"
397
397
  );
398
398
  //# sourceMappingURL=index.js.map
@@ -1408,7 +1408,7 @@ class Editor extends import_eventemitter3.default {
1408
1408
  updateInstanceState(partial, historyOptions) {
1409
1409
  this._updateInstanceState(partial, { history: "ignore", ...historyOptions });
1410
1410
  if (partial.isChangingStyle !== void 0) {
1411
- clearTimeout(this._isChangingStyleTimeout);
1411
+ this.timers.clearTimeout(this._isChangingStyleTimeout);
1412
1412
  if (partial.isChangingStyle === true) {
1413
1413
  this._isChangingStyleTimeout = this.timers.setTimeout(() => {
1414
1414
  this._updateInstanceState({ isChangingStyle: false }, { history: "ignore" });
@@ -3657,7 +3657,9 @@ class Editor extends import_eventemitter3.default {
3657
3657
  const id = typeof page === "string" ? page : page.id;
3658
3658
  const freshPage = this.getPage(id);
3659
3659
  if (!freshPage) return this;
3660
- const prevCamera = { ...this.getCamera() };
3660
+ const prevCamera = {
3661
+ ...this.store.get(import_tlschema.CameraRecordType.createId(freshPage.id)) ?? this.getCamera()
3662
+ };
3661
3663
  const content = this.getContentFromCurrentPage(this.getSortedChildIdsForParent(freshPage.id));
3662
3664
  this.run(() => {
3663
3665
  const pages = this.getPages();
@@ -3666,7 +3668,7 @@ class Editor extends import_eventemitter3.default {
3666
3668
  this.setCurrentPage(createId);
3667
3669
  this.setCamera(prevCamera);
3668
3670
  if (content) {
3669
- return this.putContentOntoCurrentPage(content);
3671
+ return this.putContentOntoCurrentPage(content, { preservePosition: true });
3670
3672
  }
3671
3673
  });
3672
3674
  return this;
@@ -6030,11 +6032,20 @@ class Editor extends import_eventemitter3.default {
6030
6032
  initialShape: options.initialShape,
6031
6033
  initialBounds: options.initialBounds,
6032
6034
  isAspectRatioLocked: options.isAspectRatioLocked,
6033
- initialPageTransform: options.initialPageTransform
6035
+ initialPageTransform: options.initialPageTransform,
6036
+ dragHandle: options.dragHandle,
6037
+ mode: options.mode,
6038
+ // this is one frame of the same resize, not a new one, so don't fire start/end again
6039
+ skipStartAndEndCallbacks: options.skipStartAndEndCallbacks
6034
6040
  });
6035
6041
  if (Math.sign(scale.x) * Math.sign(scale.y) < 0) {
6036
6042
  const parentRotation = this.getShapeParentTransform(id).rotation();
6037
- const rotation = -options.initialShape.rotation - 2 * parentRotation;
6043
+ const parentDelta = (0, import_utils2.shortAngleDist)(
6044
+ import_Mat.Mat.Cast(options.initialPageTransform).rotation() - options.initialShape.rotation,
6045
+ parentRotation
6046
+ );
6047
+ const initialParentRotation = parentRotation - parentDelta;
6048
+ const rotation = 2 * options.scaleAxisRotation - options.initialShape.rotation - 2 * initialParentRotation - parentDelta;
6038
6049
  this.updateShapes([{ id, type, rotation }]);
6039
6050
  }
6040
6051
  const preScaleShapePageCenter = import_Mat.Mat.applyToPoint(
@@ -7822,22 +7833,22 @@ class Editor extends import_eventemitter3.default {
7822
7833
  const releaseCtrl = this._ctrlKeyTimeout !== -1;
7823
7834
  const releaseMeta = this._metaKeyTimeout !== -1;
7824
7835
  if (releaseShift) {
7825
- clearTimeout(this._shiftKeyTimeout);
7836
+ this.timers.clearTimeout(this._shiftKeyTimeout);
7826
7837
  this._shiftKeyTimeout = -1;
7827
7838
  this.inputs.setShiftKey(false);
7828
7839
  }
7829
7840
  if (releaseAlt) {
7830
- clearTimeout(this._altKeyTimeout);
7841
+ this.timers.clearTimeout(this._altKeyTimeout);
7831
7842
  this._altKeyTimeout = -1;
7832
7843
  this.inputs.setAltKey(false);
7833
7844
  }
7834
7845
  if (releaseCtrl) {
7835
- clearTimeout(this._ctrlKeyTimeout);
7846
+ this.timers.clearTimeout(this._ctrlKeyTimeout);
7836
7847
  this._ctrlKeyTimeout = -1;
7837
7848
  this.inputs.setCtrlKey(false);
7838
7849
  }
7839
7850
  if (releaseMeta) {
7840
- clearTimeout(this._metaKeyTimeout);
7851
+ this.timers.clearTimeout(this._metaKeyTimeout);
7841
7852
  this._metaKeyTimeout = -1;
7842
7853
  this.inputs.setMetaKey(false);
7843
7854
  }
@@ -7951,28 +7962,28 @@ class Editor extends import_eventemitter3.default {
7951
7962
  return;
7952
7963
  }
7953
7964
  if (info.shiftKey) {
7954
- clearTimeout(this._shiftKeyTimeout);
7965
+ this.timers.clearTimeout(this._shiftKeyTimeout);
7955
7966
  this._shiftKeyTimeout = -1;
7956
7967
  inputs.setShiftKey(true);
7957
7968
  } else if (!info.shiftKey && inputs.getShiftKey() && this._shiftKeyTimeout === -1) {
7958
7969
  this._shiftKeyTimeout = this.timers.setTimeout(this._releaseShiftKey, 150);
7959
7970
  }
7960
7971
  if (info.altKey) {
7961
- clearTimeout(this._altKeyTimeout);
7972
+ this.timers.clearTimeout(this._altKeyTimeout);
7962
7973
  this._altKeyTimeout = -1;
7963
7974
  inputs.setAltKey(true);
7964
7975
  } else if (!info.altKey && inputs.getAltKey() && this._altKeyTimeout === -1) {
7965
7976
  this._altKeyTimeout = this.timers.setTimeout(this._releaseAltKey, 150);
7966
7977
  }
7967
7978
  if (info.ctrlKey) {
7968
- clearTimeout(this._ctrlKeyTimeout);
7979
+ this.timers.clearTimeout(this._ctrlKeyTimeout);
7969
7980
  this._ctrlKeyTimeout = -1;
7970
7981
  inputs.setCtrlKey(true);
7971
7982
  } else if (!info.ctrlKey && inputs.getCtrlKey() && this._ctrlKeyTimeout === -1) {
7972
7983
  this._ctrlKeyTimeout = this.timers.setTimeout(this._releaseCtrlKey, 150);
7973
7984
  }
7974
7985
  if (info.metaKey && info.name !== "key_up") {
7975
- clearTimeout(this._metaKeyTimeout);
7986
+ this.timers.clearTimeout(this._metaKeyTimeout);
7976
7987
  this._metaKeyTimeout = -1;
7977
7988
  inputs.setMetaKey(true);
7978
7989
  } else if (!info.metaKey && inputs.getMetaKey() && this._metaKeyTimeout === -1) {
@@ -7986,7 +7997,7 @@ class Editor extends import_eventemitter3.default {
7986
7997
  const cameraOptions = this._cameraOptions.__unsafe__getWithoutCapture();
7987
7998
  switch (type) {
7988
7999
  case "pinch": {
7989
- clearTimeout(this._longPressTimeout);
8000
+ this.timers.clearTimeout(this._longPressTimeout);
7990
8001
  this.inputs.updateFromEvent(info);
7991
8002
  switch (info.name) {
7992
8003
  case "pinch_start": {
@@ -8158,10 +8169,10 @@ class Editor extends import_eventemitter3.default {
8158
8169
  this._prevCursor = this.getInstanceState().cursor.type;
8159
8170
  }
8160
8171
  this.inputs.setIsPanning(true);
8161
- clearTimeout(this._longPressTimeout);
8172
+ this.timers.clearTimeout(this._longPressTimeout);
8162
8173
  } else if (info.button === import_constants.RIGHT_MOUSE_BUTTON && this.options.rightClickPanning) {
8163
8174
  this.inputs.setIsRightPointing(true);
8164
- clearTimeout(this._longPressTimeout);
8175
+ this.timers.clearTimeout(this._longPressTimeout);
8165
8176
  return this;
8166
8177
  }
8167
8178
  if (this.inputs.getIsPanning()) {
@@ -8202,14 +8213,14 @@ class Editor extends import_eventemitter3.default {
8202
8213
  }
8203
8214
  if (inputs.getIsPointing() && !inputs.getIsDragging() && import_Vec.Vec.Dist2(inputs.getOriginPagePoint(), inputs.getCurrentPagePoint()) * this.getZoomLevel() > (instanceState.isCoarsePointer ? this.options.coarseDragDistanceSquared : this.options.dragDistanceSquared) / cz) {
8204
8215
  inputs.setIsDragging(true);
8205
- clearTimeout(this._longPressTimeout);
8216
+ this.timers.clearTimeout(this._longPressTimeout);
8206
8217
  }
8207
8218
  break;
8208
8219
  }
8209
8220
  case "pointer_up": {
8210
8221
  inputs.setIsDragging(false);
8211
8222
  inputs.setIsPointing(false);
8212
- clearTimeout(this._longPressTimeout);
8223
+ this.timers.clearTimeout(this._longPressTimeout);
8213
8224
  inputs.buttons.delete(info.button);
8214
8225
  if (this.inputs.getIsRightPointing() && !this.inputs.getIsPanning()) {
8215
8226
  this.inputs.setIsRightPointing(false);
@@ -8293,7 +8304,7 @@ class Editor extends import_eventemitter3.default {
8293
8304
  }
8294
8305
  this.inputs.setIsPanning(true);
8295
8306
  this.inputs.setIsSpacebarPanning(true);
8296
- clearTimeout(this._longPressTimeout);
8307
+ this.timers.clearTimeout(this._longPressTimeout);
8297
8308
  this.setCursor({
8298
8309
  type: this.inputs.getIsPointing() ? "grabbing" : "grab",
8299
8310
  rotation: 0
@@ -8381,7 +8392,7 @@ class Editor extends import_eventemitter3.default {
8381
8392
  maybeTrackPerformance(name) {
8382
8393
  if (import_debug_flags.debugFlags.measurePerformance.get()) {
8383
8394
  if (this.performanceTracker.isStarted()) {
8384
- clearTimeout(this.performanceTrackerTimeout);
8395
+ this.timers.clearTimeout(this.performanceTrackerTimeout);
8385
8396
  } else {
8386
8397
  this.performanceTracker.start(name);
8387
8398
  }