@tldraw/editor 5.2.5 → 5.3.0-canary.00f14de1f81d

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 (100) hide show
  1. package/dist-cjs/index.d.ts +76 -10
  2. package/dist-cjs/index.js +3 -3
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +6 -1
  5. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  6. package/dist-cjs/lib/editor/Editor.js +67 -15
  7. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  8. package/dist-cjs/lib/editor/managers/EditorManager.js +52 -0
  9. package/dist-cjs/lib/editor/managers/EditorManager.js.map +7 -0
  10. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +9 -11
  11. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +2 -2
  12. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +9 -0
  13. package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
  14. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +5 -9
  15. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
  16. package/dist-cjs/lib/editor/managers/SpatialIndexManager/RBushIndex.js +18 -29
  17. package/dist-cjs/lib/editor/managers/SpatialIndexManager/RBushIndex.js.map +2 -2
  18. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +96 -54
  19. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +2 -2
  20. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +27 -19
  21. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  22. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +4 -7
  23. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +2 -2
  24. package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js +3 -0
  25. package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js.map +2 -2
  26. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +1 -1
  27. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +1 -2
  28. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
  29. package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
  30. package/dist-cjs/lib/license/LicenseManager.js +14 -5
  31. package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
  32. package/dist-cjs/lib/options.js +2 -1
  33. package/dist-cjs/lib/options.js.map +2 -2
  34. package/dist-cjs/version.js +3 -3
  35. package/dist-cjs/version.js.map +1 -1
  36. package/dist-esm/index.d.mts +76 -10
  37. package/dist-esm/index.mjs +3 -3
  38. package/dist-esm/index.mjs.map +2 -2
  39. package/dist-esm/lib/TldrawEditor.mjs +6 -1
  40. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  41. package/dist-esm/lib/editor/Editor.mjs +67 -15
  42. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  43. package/dist-esm/lib/editor/managers/EditorManager.mjs +32 -0
  44. package/dist-esm/lib/editor/managers/EditorManager.mjs.map +7 -0
  45. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +9 -11
  46. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +2 -2
  47. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +9 -0
  48. package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
  49. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +5 -9
  50. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
  51. package/dist-esm/lib/editor/managers/SpatialIndexManager/RBushIndex.mjs +18 -29
  52. package/dist-esm/lib/editor/managers/SpatialIndexManager/RBushIndex.mjs.map +2 -2
  53. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +103 -56
  54. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +2 -2
  55. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +27 -19
  56. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  57. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +4 -7
  58. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +2 -2
  59. package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs +3 -0
  60. package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs.map +2 -2
  61. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +1 -1
  62. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +1 -2
  63. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
  64. package/dist-esm/lib/license/LicenseManager.mjs +14 -5
  65. package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
  66. package/dist-esm/lib/options.mjs +2 -1
  67. package/dist-esm/lib/options.mjs.map +2 -2
  68. package/dist-esm/version.mjs +3 -3
  69. package/dist-esm/version.mjs.map +1 -1
  70. package/editor.css +10 -0
  71. package/package.json +7 -7
  72. package/src/index.ts +1 -1
  73. package/src/lib/TldrawEditor.tsx +10 -1
  74. package/src/lib/editor/Editor.ts +101 -20
  75. package/src/lib/editor/managers/EditorManager.test.ts +51 -0
  76. package/src/lib/editor/managers/EditorManager.ts +60 -0
  77. package/src/lib/editor/managers/FocusManager/FocusManager.test.ts +2 -1
  78. package/src/lib/editor/managers/FocusManager/FocusManager.ts +10 -14
  79. package/src/lib/editor/managers/FontManager/FontManager.test.ts +66 -0
  80. package/src/lib/editor/managers/FontManager/FontManager.ts +14 -0
  81. package/src/lib/editor/managers/InputsManager/InputsManager.ts +6 -9
  82. package/src/lib/editor/managers/SpatialIndexManager/RBushIndex.ts +19 -33
  83. package/src/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.ts +173 -86
  84. package/src/lib/editor/managers/TextManager/TextManager.test.ts +61 -1
  85. package/src/lib/editor/managers/TextManager/TextManager.ts +36 -19
  86. package/src/lib/editor/managers/TickManager/TickManager.test.ts +0 -10
  87. package/src/lib/editor/managers/TickManager/TickManager.ts +5 -6
  88. package/src/lib/editor/shapes/BaseFrameLikeShapeUtil.tsx +6 -1
  89. package/src/lib/editor/shapes/ShapeUtil.ts +1 -0
  90. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +2 -2
  91. package/src/lib/editor/types/emit-types.ts +1 -0
  92. package/src/lib/license/LicenseManager.test.ts +99 -29
  93. package/src/lib/license/LicenseManager.ts +16 -4
  94. package/src/lib/options.ts +3 -1
  95. package/src/version.ts +3 -3
  96. package/dist-cjs/lib/editor/tools/cancelShapeCreationOnLongPress.js +0 -28
  97. package/dist-cjs/lib/editor/tools/cancelShapeCreationOnLongPress.js.map +0 -7
  98. package/dist-esm/lib/editor/tools/cancelShapeCreationOnLongPress.mjs +0 -8
  99. package/dist-esm/lib/editor/tools/cancelShapeCreationOnLongPress.mjs.map +0 -7
  100. package/src/lib/editor/tools/cancelShapeCreationOnLongPress.ts +0 -31
@@ -273,12 +273,27 @@ class Editor extends import_eventemitter3.default {
273
273
  let deletedBindings = /* @__PURE__ */ new Map();
274
274
  const deletedShapeIds = /* @__PURE__ */ new Set();
275
275
  const invalidParents = /* @__PURE__ */ new Set();
276
+ const createdShapes = /* @__PURE__ */ new Set();
276
277
  let invalidBindingTypes = /* @__PURE__ */ new Set();
277
278
  this.disposables.add(
278
279
  this.sideEffects.registerOperationCompleteHandler(() => {
280
+ const deletedIds = deletedShapeIds.size ? new Set(deletedShapeIds) : null;
279
281
  deletedShapeIds.clear();
282
+ if (deletedIds) {
283
+ const updates = (0, import_utils.compact)(
284
+ this.getPageStates().map((pageState) => {
285
+ return cleanupInstancePageState(pageState, deletedIds);
286
+ })
287
+ );
288
+ if (updates.length) {
289
+ this.store.put(updates);
290
+ }
291
+ }
292
+ const justCreatedShapeIds = new Set(createdShapes);
293
+ createdShapes.clear();
280
294
  for (const parentId of invalidParents) {
281
295
  invalidParents.delete(parentId);
296
+ if (justCreatedShapeIds.has(parentId)) continue;
282
297
  const parent = this.getShape(parentId);
283
298
  if (!parent) continue;
284
299
  const util = this.getShapeUtil(parent);
@@ -308,6 +323,12 @@ class Editor extends import_eventemitter3.default {
308
323
  this.disposables.add(
309
324
  this.sideEffects.register({
310
325
  shape: {
326
+ afterCreate: (shape) => {
327
+ createdShapes.add(shape.id);
328
+ if (shape.parentId && (0, import_tlschema.isShapeId)(shape.parentId)) {
329
+ invalidParents.add(shape.parentId);
330
+ }
331
+ },
311
332
  afterChange: (shapeBefore, shapeAfter) => {
312
333
  for (const binding of this.getBindingsInvolvingShape(shapeAfter)) {
313
334
  invalidBindingTypes.add(binding.type);
@@ -397,15 +418,6 @@ class Editor extends import_eventemitter3.default {
397
418
  if (deleteBindingIds.length) {
398
419
  this.deleteBindings(deleteBindingIds);
399
420
  }
400
- const deletedIds = /* @__PURE__ */ new Set([shape.id]);
401
- const updates = (0, import_utils.compact)(
402
- this.getPageStates().map((pageState) => {
403
- return cleanupInstancePageState(pageState, deletedIds);
404
- })
405
- );
406
- if (updates.length) {
407
- this.store.put(updates);
408
- }
409
421
  }
410
422
  },
411
423
  binding: {
@@ -482,6 +494,9 @@ class Editor extends import_eventemitter3.default {
482
494
  },
483
495
  instance_page_state: {
484
496
  afterChange: (prev, next) => {
497
+ if (prev?.focusedGroupId !== next?.focusedGroupId) {
498
+ this.cancelDoubleClick();
499
+ }
485
500
  if (prev?.selectedShapeIds !== next?.selectedShapeIds) {
486
501
  const filtered = next.selectedShapeIds.filter((id) => {
487
502
  let parentId = this.getShape(id)?.parentId;
@@ -549,11 +564,17 @@ class Editor extends import_eventemitter3.default {
549
564
  this.root.enter(void 0, "initial");
550
565
  this.edgeScrollManager = new import_EdgeScrollManager.EdgeScrollManager(this);
551
566
  this.focusManager = new import_FocusManager.FocusManager(this, autoFocus);
552
- this.disposables.add(this.focusManager.dispose.bind(this.focusManager));
567
+ this.disposables.add(() => this.focusManager.dispose());
553
568
  if (this.getInstanceState().followingUserId) {
554
569
  this.stopFollowingUser();
555
570
  }
556
571
  this.on("tick", this._flushEventsForTick);
572
+ this.on("mount", () => {
573
+ this._isMounted.set(true);
574
+ });
575
+ this.on("unmount", () => {
576
+ this._isMounted.set(false);
577
+ });
557
578
  this.timers.requestAnimationFrame(() => {
558
579
  this._tickManager.start();
559
580
  });
@@ -648,6 +669,10 @@ class Editor extends import_eventemitter3.default {
648
669
  * @public
649
670
  */
650
671
  isDisposed = false;
672
+ _isMounted = (0, import_state.atom)("isMounted", false);
673
+ getIsMounted() {
674
+ return this._isMounted.get();
675
+ }
651
676
  /**
652
677
  * A manager for the editor's tick events.
653
678
  *
@@ -779,6 +804,9 @@ class Editor extends import_eventemitter3.default {
779
804
  * @public
780
805
  */
781
806
  dispose() {
807
+ if (this._isMounted.get()) {
808
+ this.emit("unmount");
809
+ }
782
810
  this.stopCameraAnimation();
783
811
  if (this.getInstanceState().followingUserId) {
784
812
  this.stopFollowingUser();
@@ -4215,6 +4243,11 @@ class Editor extends import_eventemitter3.default {
4215
4243
  });
4216
4244
  return commonBounds;
4217
4245
  }
4246
+ getHitTestMargin() {
4247
+ const { hitTestMargin, coarseHitTestMargin } = this.options;
4248
+ const margin = this.getInstanceState().isCoarsePointer ? coarseHitTestMargin : hitTestMargin;
4249
+ return margin / this.getZoomLevel();
4250
+ }
4218
4251
  /**
4219
4252
  * Get the top-most selected shape at the given point, ignoring groups.
4220
4253
  *
@@ -4224,7 +4257,21 @@ class Editor extends import_eventemitter3.default {
4224
4257
  */
4225
4258
  getSelectedShapeAtPoint(point) {
4226
4259
  const selectedShapeIds = this.getSelectedShapeIds();
4227
- return this.getCurrentPageShapesSorted().filter((shape) => shape.type !== "group" && selectedShapeIds.includes(shape.id)).reverse().find((shape) => this.isPointInShape(shape, point, { hitInside: true, margin: 0 }));
4260
+ const margin = this.options.hitTestMargin / this.getZoomLevel();
4261
+ const sortedShapes = this.getCurrentPageShapesSorted();
4262
+ for (let i = sortedShapes.length - 1; i >= 0; i--) {
4263
+ const shape = sortedShapes[i];
4264
+ if (shape.type === "group") continue;
4265
+ if (!selectedShapeIds.includes(shape.id)) continue;
4266
+ if (this.getShapeGeometry(shape).hitTestPoint(
4267
+ this.getPointInShapeSpace(shape, point),
4268
+ margin,
4269
+ true
4270
+ )) {
4271
+ return shape;
4272
+ }
4273
+ }
4274
+ return void 0;
4228
4275
  }
4229
4276
  /**
4230
4277
  * Get the shape at the current point.
@@ -4235,7 +4282,6 @@ class Editor extends import_eventemitter3.default {
4235
4282
  * @returns The shape at the given point, or undefined if there is no shape at the point.
4236
4283
  */
4237
4284
  getShapeAtPoint(point, opts = {}) {
4238
- const zoomLevel = this.getZoomLevel();
4239
4285
  const viewportPageBounds = this.getViewportPageBounds();
4240
4286
  const {
4241
4287
  filter,
@@ -4250,7 +4296,7 @@ class Editor extends import_eventemitter3.default {
4250
4296
  let inHollowSmallestAreaHit = null;
4251
4297
  let inMarginClosestToEdgeDistance = Infinity;
4252
4298
  let inMarginClosestToEdgeHit = null;
4253
- const searchMargin = Math.max(innerMargin, outerMargin, this.options.hitTestMargin / zoomLevel);
4299
+ const searchMargin = Math.max(innerMargin, outerMargin, this.getHitTestMargin());
4254
4300
  const candidateIds = this._spatialIndex.getShapeIdsAtPoint(point, searchMargin);
4255
4301
  const shapesToCheck = (opts.renderingOnly ? this.getCurrentPageRenderingShapesSorted() : this.getCurrentPageShapesSorted()).filter((shape) => {
4256
4302
  if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) return false;
@@ -4341,7 +4387,7 @@ class Editor extends import_eventemitter3.default {
4341
4387
  }
4342
4388
  }
4343
4389
  } else {
4344
- if (distance < this.options.hitTestMargin / zoomLevel) {
4390
+ if (distance < this.getHitTestMargin()) {
4345
4391
  return shape;
4346
4392
  }
4347
4393
  }
@@ -7994,7 +8040,7 @@ class Editor extends import_eventemitter3.default {
7994
8040
  } else if (!info.ctrlKey && inputs.getCtrlKey() && this._ctrlKeyTimeout === -1) {
7995
8041
  this._ctrlKeyTimeout = this.timers.setTimeout(this._setCtrlKeyTimeout, 150);
7996
8042
  }
7997
- if (info.metaKey) {
8043
+ if (info.metaKey && info.name !== "key_up") {
7998
8044
  clearTimeout(this._metaKeyTimeout);
7999
8045
  this._metaKeyTimeout = -1;
8000
8046
  inputs.setMetaKey(true);
@@ -8417,6 +8463,9 @@ class Editor extends import_eventemitter3.default {
8417
8463
  __decorateClass([
8418
8464
  import_state.computed
8419
8465
  ], Editor.prototype, "getIsShapeHiddenCache", 1);
8466
+ __decorateClass([
8467
+ import_state.computed
8468
+ ], Editor.prototype, "getIsMounted", 1);
8420
8469
  __decorateClass([
8421
8470
  import_state.computed
8422
8471
  ], Editor.prototype, "canUndo", 1);
@@ -8591,6 +8640,9 @@ __decorateClass([
8591
8640
  __decorateClass([
8592
8641
  import_state.computed
8593
8642
  ], Editor.prototype, "getCurrentPageBounds", 1);
8643
+ __decorateClass([
8644
+ import_state.computed
8645
+ ], Editor.prototype, "getHitTestMargin", 1);
8594
8646
  __decorateClass([
8595
8647
  import_state.computed
8596
8648
  ], Editor.prototype, "getCurrentPageShapes", 1);