@tldraw/editor 4.3.0 → 4.4.0-canary.15cff7ea86f8

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 (51) hide show
  1. package/README.md +1 -1
  2. package/dist-cjs/index.d.ts +9 -0
  3. package/dist-cjs/index.js +3 -1
  4. package/dist-cjs/index.js.map +2 -2
  5. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +1 -2
  6. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  7. package/dist-cjs/lib/config/TLUserPreferences.js +9 -3
  8. package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
  9. package/dist-cjs/lib/editor/Editor.js +58 -6
  10. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  11. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +13 -21
  12. package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +2 -2
  13. package/dist-cjs/lib/editor/managers/SpatialIndexManager/RBushIndex.js +144 -0
  14. package/dist-cjs/lib/editor/managers/SpatialIndexManager/RBushIndex.js.map +7 -0
  15. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +180 -0
  16. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +7 -0
  17. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +8 -3
  18. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  19. package/dist-cjs/version.js +3 -3
  20. package/dist-cjs/version.js.map +1 -1
  21. package/dist-esm/index.d.mts +9 -0
  22. package/dist-esm/index.mjs +3 -1
  23. package/dist-esm/index.mjs.map +2 -2
  24. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +1 -2
  25. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  26. package/dist-esm/lib/config/TLUserPreferences.mjs +9 -3
  27. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  28. package/dist-esm/lib/editor/Editor.mjs +58 -6
  29. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  30. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +13 -21
  31. package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +2 -2
  32. package/dist-esm/lib/editor/managers/SpatialIndexManager/RBushIndex.mjs +114 -0
  33. package/dist-esm/lib/editor/managers/SpatialIndexManager/RBushIndex.mjs.map +7 -0
  34. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +160 -0
  35. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +7 -0
  36. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +8 -3
  37. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  38. package/dist-esm/version.mjs +3 -3
  39. package/dist-esm/version.mjs.map +1 -1
  40. package/package.json +10 -8
  41. package/src/index.ts +1 -0
  42. package/src/lib/components/default-components/DefaultCanvas.tsx +1 -5
  43. package/src/lib/config/TLUserPreferences.test.ts +1 -0
  44. package/src/lib/config/TLUserPreferences.ts +8 -0
  45. package/src/lib/editor/Editor.ts +84 -6
  46. package/src/lib/editor/derivations/notVisibleShapes.ts +15 -41
  47. package/src/lib/editor/managers/SpatialIndexManager/RBushIndex.ts +144 -0
  48. package/src/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.ts +214 -0
  49. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +24 -0
  50. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +8 -0
  51. package/src/version.ts +3 -3
@@ -118,6 +118,7 @@ var import_HistoryManager = require("./managers/HistoryManager/HistoryManager");
118
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");
@@ -187,6 +188,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
187
188
  * @public
188
189
  */
189
190
  __publicField(this, "snaps");
191
+ __publicField(this, "_spatialIndex");
190
192
  /**
191
193
  * A manager for the any asynchronous events and making sure they're
192
194
  * cleaned up upon disposal.
@@ -303,6 +305,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
303
305
  /* --------------------- Shapes --------------------- */
304
306
  __publicField(this, "_shapeGeometryCaches", {});
305
307
  __publicField(this, "_notVisibleShapes", (0, import_notVisibleShapes.notVisibleShapes)(this));
308
+ __publicField(this, "_culledShapesCache", null);
306
309
  // Parents and children
307
310
  /**
308
311
  * A cache of parents to children.
@@ -378,6 +381,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
378
381
  }
379
382
  });
380
383
  this.snaps = new import_SnapManager.SnapManager(this);
384
+ this._spatialIndex = new import_SpatialIndexManager.SpatialIndexManager(this);
385
+ this.disposables.add(() => this._spatialIndex.dispose());
381
386
  this.disposables.add(this.timers.dispose);
382
387
  this._cameraOptions.set({ ...import_constants.DEFAULT_CAMERA_OPTIONS, ...cameraOptions });
383
388
  this._textOptions = (0, import_state.atom)("text options", textOptions ?? null);
@@ -3842,14 +3847,29 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3842
3847
  const notVisibleShapes2 = this.getNotVisibleShapes();
3843
3848
  const selectedShapeIds = this.getSelectedShapeIds();
3844
3849
  const editingId = this.getEditingShapeId();
3845
- const culledShapes = new Set(notVisibleShapes2);
3850
+ const nextValue = new Set(notVisibleShapes2);
3846
3851
  if (editingId) {
3847
- culledShapes.delete(editingId);
3852
+ nextValue.delete(editingId);
3848
3853
  }
3849
3854
  selectedShapeIds.forEach((id) => {
3850
- culledShapes.delete(id);
3855
+ nextValue.delete(id);
3851
3856
  });
3852
- return culledShapes;
3857
+ const prevValue = this._culledShapesCache;
3858
+ if (prevValue) {
3859
+ if (prevValue.size !== nextValue.size) {
3860
+ this._culledShapesCache = nextValue;
3861
+ return nextValue;
3862
+ }
3863
+ for (const id of prevValue) {
3864
+ if (!nextValue.has(id)) {
3865
+ this._culledShapesCache = nextValue;
3866
+ return nextValue;
3867
+ }
3868
+ }
3869
+ return prevValue;
3870
+ }
3871
+ this._culledShapesCache = nextValue;
3872
+ return nextValue;
3853
3873
  }
3854
3874
  getCurrentPageBounds() {
3855
3875
  let commonBounds;
@@ -3899,7 +3919,10 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3899
3919
  let inHollowSmallestAreaHit = null;
3900
3920
  let inMarginClosestToEdgeDistance = Infinity;
3901
3921
  let inMarginClosestToEdgeHit = null;
3922
+ const searchMargin = Math.max(innerMargin, outerMargin, this.options.hitTestMargin / zoomLevel);
3923
+ const candidateIds = this._spatialIndex.getShapeIdsAtPoint(point, searchMargin);
3902
3924
  const shapesToCheck = (opts.renderingOnly ? this.getCurrentPageRenderingShapesSorted() : this.getCurrentPageShapesSorted()).filter((shape) => {
3925
+ if (!candidateIds.has(shape.id) && !this.isShapeOfType(shape, "frame")) return false;
3903
3926
  if (shape.isLocked && !hitLocked || this.isShapeHidden(shape) || this.isShapeOfType(shape, "group"))
3904
3927
  return false;
3905
3928
  const pageMask = this.getShapeMask(shape);
@@ -4006,7 +4029,33 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
4006
4029
  * @public
4007
4030
  */
4008
4031
  getShapesAtPoint(point, opts = {}) {
4009
- return this.getCurrentPageShapesSorted().filter((shape) => !this.isShapeHidden(shape) && this.isPointInShape(shape, point, opts)).reverse();
4032
+ const margin = opts.margin ?? 0;
4033
+ const candidateIds = this._spatialIndex.getShapeIdsAtPoint(point, margin);
4034
+ return this.getCurrentPageShapesSorted().filter((shape) => {
4035
+ if (this.isShapeHidden(shape)) return false;
4036
+ if (!candidateIds.has(shape.id) && !this.isShapeOfType(shape, "frame")) return false;
4037
+ return this.isPointInShape(shape, point, opts);
4038
+ }).reverse();
4039
+ }
4040
+ /**
4041
+ * Get shape IDs within the given bounds.
4042
+ *
4043
+ * Note: Uses shape page bounds only. Frames with labels outside their bounds
4044
+ * may not be included even if the label is within the search bounds.
4045
+ *
4046
+ * Note: Results are unordered. If you need z-order, combine with sorted shapes:
4047
+ * ```ts
4048
+ * const candidates = editor.getShapeIdsInsideBounds(bounds)
4049
+ * const sorted = editor.getCurrentPageShapesSorted().filter(s => candidates.has(s.id))
4050
+ * ```
4051
+ *
4052
+ * @param bounds - The bounds to search within.
4053
+ * @returns Unordered set of shape IDs within the given bounds.
4054
+ *
4055
+ * @internal
4056
+ */
4057
+ getShapeIdsInsideBounds(bounds) {
4058
+ return this._spatialIndex.getShapeIdsInsideBounds(bounds);
4010
4059
  }
4011
4060
  /**
4012
4061
  * Test whether a point (in the current page space) will will a shape. This method takes into account masks,
@@ -7605,7 +7654,10 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7605
7654
  delta = dy / 100;
7606
7655
  }
7607
7656
  }
7608
- const zoom = cz + (delta ?? 0) * zoomSpeed * cz;
7657
+ const isZoomDirectionInverted = (this.user.getUserPreferences().isZoomDirectionInverted && inputMode === "mouse") ?? false;
7658
+ const deltaValue = delta ?? 0;
7659
+ const finalDelta = isZoomDirectionInverted ? -deltaValue : deltaValue;
7660
+ const zoom = cz + finalDelta * zoomSpeed * cz;
7609
7661
  this._setCamera(new import_Vec.Vec(cx + x / zoom - x / cz, cy + y / zoom - y / cz, zoom), {
7610
7662
  immediate: true
7611
7663
  });