@tldraw/editor 3.14.0-canary.f907ed7d9ee5 → 3.14.0-canary.faba3f64c07f

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 (54) hide show
  1. package/dist-cjs/index.d.ts +133 -50
  2. package/dist-cjs/index.js +4 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/editor/Editor.js +60 -22
  5. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  6. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +73 -42
  7. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  8. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +0 -10
  9. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  10. package/dist-cjs/lib/editor/tools/StateNode.js +3 -3
  11. package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
  12. package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
  13. package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
  14. package/dist-cjs/lib/hooks/useCanvasEvents.js +1 -2
  15. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  16. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +6 -2
  17. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  18. package/dist-cjs/lib/utils/reparenting.js +232 -0
  19. package/dist-cjs/lib/utils/reparenting.js.map +7 -0
  20. package/dist-cjs/version.js +3 -3
  21. package/dist-cjs/version.js.map +1 -1
  22. package/dist-esm/index.d.mts +133 -50
  23. package/dist-esm/index.mjs +4 -1
  24. package/dist-esm/index.mjs.map +2 -2
  25. package/dist-esm/lib/editor/Editor.mjs +60 -22
  26. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  27. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +73 -42
  28. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  29. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +0 -10
  30. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  31. package/dist-esm/lib/editor/tools/StateNode.mjs +3 -3
  32. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  33. package/dist-esm/lib/hooks/useCanvasEvents.mjs +1 -2
  34. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  35. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +6 -2
  36. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  37. package/dist-esm/lib/utils/reparenting.mjs +216 -0
  38. package/dist-esm/lib/utils/reparenting.mjs.map +7 -0
  39. package/dist-esm/version.mjs +3 -3
  40. package/dist-esm/version.mjs.map +1 -1
  41. package/editor.css +442 -492
  42. package/package.json +7 -7
  43. package/src/index.ts +7 -0
  44. package/src/lib/editor/Editor.ts +73 -30
  45. package/src/lib/editor/managers/TextManager/TextManager.test.ts +1 -5
  46. package/src/lib/editor/managers/TextManager/TextManager.ts +118 -86
  47. package/src/lib/editor/shapes/ShapeUtil.ts +47 -15
  48. package/src/lib/editor/tools/StateNode.ts +3 -3
  49. package/src/lib/editor/types/emit-types.ts +4 -0
  50. package/src/lib/editor/types/external-content.ts +11 -2
  51. package/src/lib/hooks/useCanvasEvents.ts +0 -1
  52. package/src/lib/primitives/geometry/Geometry2d.ts +7 -2
  53. package/src/lib/utils/reparenting.ts +383 -0
  54. package/src/version.ts +3 -3
@@ -357,6 +357,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
357
357
  __publicField(this, "externalContentHandlers", {
358
358
  text: null,
359
359
  files: null,
360
+ "file-replace": null,
360
361
  embed: null,
361
362
  "svg-text": null,
362
363
  url: null,
@@ -473,6 +474,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
473
474
  this.disposables.add(() => this.user.dispose());
474
475
  this.getContainer = getContainer;
475
476
  this.textMeasure = new TextManager(this);
477
+ this.disposables.add(() => this.textMeasure.dispose());
476
478
  this.fonts = new FontManager(this, fontAssetUrls);
477
479
  this._tickManager = new TickManager(this);
478
480
  class NewRoot extends RootState {
@@ -1674,6 +1676,19 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
1674
1676
  getSelectionPageBounds() {
1675
1677
  return this.getShapesPageBounds(this.getSelectedShapeIds());
1676
1678
  }
1679
+ /**
1680
+ * The bounds of the selection bounding box in the current page space.
1681
+ *
1682
+ * @readonly
1683
+ * @public
1684
+ */
1685
+ getSelectionScreenBounds() {
1686
+ const bounds = this.getSelectionPageBounds();
1687
+ if (!bounds) return void 0;
1688
+ const { x, y } = this.pageToScreen(bounds.point);
1689
+ const zoom = this.getZoomLevel();
1690
+ return new Box(x, y, bounds.width * zoom, bounds.height * zoom);
1691
+ }
1677
1692
  /**
1678
1693
  * @internal
1679
1694
  */
@@ -4150,7 +4165,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4150
4165
  if (!id) return void 0;
4151
4166
  const freshShape = this.getShape(id);
4152
4167
  if (freshShape === void 0 || !isShapeId(freshShape.parentId)) return void 0;
4153
- return this.store.get(freshShape.parentId);
4168
+ return this.getShape(freshShape.parentId);
4154
4169
  }
4155
4170
  /**
4156
4171
  * If siblingShape and targetShape are siblings, this returns targetShape. If targetShape has an
@@ -4282,6 +4297,9 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4282
4297
  if (!pagePoint) continue;
4283
4298
  const newPoint = invertedParentTransform.applyToPoint(pagePoint);
4284
4299
  const newRotation = pageTransform.rotation() - parentPageRotation;
4300
+ if (shape.id === parentId) {
4301
+ throw Error("Attempted to reparent a shape to itself!");
4302
+ }
4285
4303
  changes.push({
4286
4304
  id: shape.id,
4287
4305
  type: shape.type,
@@ -4374,6 +4392,10 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4374
4392
  }
4375
4393
  return shapeIds;
4376
4394
  }
4395
+ /** @deprecated Use {@link Editor.getDraggingOverShape} instead */
4396
+ getDroppingOverShape(point, droppingShapes) {
4397
+ return this.getDraggingOverShape(point, droppingShapes);
4398
+ }
4377
4399
  /**
4378
4400
  * Get the shape that some shapes should be dropped on at a given point.
4379
4401
  *
@@ -4384,22 +4406,20 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4384
4406
  *
4385
4407
  * @public
4386
4408
  */
4387
- getDroppingOverShape(point, droppingShapes = []) {
4388
- const currentPageShapesSorted = this.getCurrentPageShapesSorted();
4389
- for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
4390
- const shape = currentPageShapesSorted[i];
4391
- if (
4392
- // ignore hidden shapes
4393
- this.isShapeHidden(shape) || // don't allow dropping on selected shapes
4394
- this.getSelectedShapeIds().includes(shape.id) || // only allow shapes that can receive children
4395
- !this.getShapeUtil(shape).canDropShapes(shape, droppingShapes) || // don't allow dropping a shape on itself or one of it's children
4396
- droppingShapes.find((s) => s.id === shape.id || this.hasAncestor(shape, s.id))
4397
- ) {
4398
- continue;
4399
- }
4400
- const maskedPageBounds = this.getShapeMaskedPageBounds(shape.id);
4401
- if (maskedPageBounds && maskedPageBounds.containsPoint(point) && this.getShapeGeometry(shape).hitTestPoint(this.getPointInShapeSpace(shape, point), 0, true)) {
4402
- return shape;
4409
+ getDraggingOverShape(point, droppingShapes) {
4410
+ const draggingShapes = compact(droppingShapes.map((s) => this.getShape(s))).filter(
4411
+ (s) => !s.isLocked && !this.isShapeHidden(s)
4412
+ );
4413
+ const maybeDraggingOverShapes = this.getShapesAtPoint(point, {
4414
+ hitInside: true,
4415
+ margin: 0
4416
+ }).filter(
4417
+ (s) => !droppingShapes.includes(s) && !s.isLocked && !this.isShapeHidden(s) && !draggingShapes.includes(s)
4418
+ );
4419
+ for (const maybeDraggingOverShape of maybeDraggingOverShapes) {
4420
+ const shapeUtil = this.getShapeUtil(maybeDraggingOverShape);
4421
+ if (shapeUtil.onDragShapesOver || shapeUtil.onDragShapesIn || shapeUtil.onDragShapesOut || shapeUtil.onDropShapesOver) {
4422
+ return maybeDraggingOverShape;
4403
4423
  }
4404
4424
  }
4405
4425
  }
@@ -4676,7 +4696,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4676
4696
  */
4677
4697
  duplicateShapes(shapes, offset) {
4678
4698
  this.run(() => {
4679
- const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
4699
+ const _ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
4700
+ const ids = this._shouldIgnoreShapeLock ? _ids : this._getUnlockedShapeIds(_ids);
4680
4701
  if (ids.length <= 0) return this;
4681
4702
  const initialIds = new Set(ids);
4682
4703
  const shapeIdSet = this.getShapeAndDescendantIds(ids);
@@ -5809,7 +5830,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
5809
5830
  let parentId = this.getFocusedGroupId();
5810
5831
  for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
5811
5832
  const parent = currentPageShapesSorted[i];
5812
- if (!this.isShapeHidden(parent) && this.getShapeUtil(parent).canReceiveNewChildrenOfType(parent, partial.type) && this.isPointInShape(
5833
+ const util = this.getShapeUtil(parent);
5834
+ if (util.canReceiveNewChildrenOfType(parent, partial.type) && !this.isShapeHidden(parent) && this.isPointInShape(
5813
5835
  parent,
5814
5836
  // If no parent is provided, then we can treat the
5815
5837
  // shape's provided x/y as being in the page's space.
@@ -5884,6 +5906,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
5884
5906
  ...shape.meta
5885
5907
  };
5886
5908
  });
5909
+ this.emit("created-shapes", shapeRecordsToCreate);
5910
+ this.emit("edit");
5887
5911
  this.store.put(shapeRecordsToCreate);
5888
5912
  });
5889
5913
  return this;
@@ -6125,6 +6149,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6125
6149
  updated = this.getShapeUtil(shape).onBeforeUpdate?.(shape, updated) ?? updated;
6126
6150
  updates.push(updated);
6127
6151
  }
6152
+ this.emit("edited-shapes", updates);
6153
+ this.emit("edit");
6128
6154
  this.store.put(updates);
6129
6155
  });
6130
6156
  }
@@ -6146,6 +6172,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6146
6172
  allShapeIdsToDelete.add(childId);
6147
6173
  });
6148
6174
  }
6175
+ this.emit("deleted-shapes", [...allShapeIdsToDelete]);
6176
+ this.emit("edit");
6149
6177
  return this.run(() => this.store.remove([...allShapeIdsToDelete]));
6150
6178
  }
6151
6179
  deleteShape(_id) {
@@ -6489,6 +6517,14 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6489
6517
  async putExternalContent(info) {
6490
6518
  return this.externalContentHandlers[info.type]?.(info);
6491
6519
  }
6520
+ /**
6521
+ * Handle replacing external content.
6522
+ *
6523
+ * @param info - Info about the external content.
6524
+ */
6525
+ async replaceExternalContent(info) {
6526
+ return this.externalContentHandlers[info.type]?.(info);
6527
+ }
6492
6528
  /**
6493
6529
  * Get content that can be exported for the given shape ids.
6494
6530
  *
@@ -6906,7 +6942,9 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6906
6942
  previousScreenPoint,
6907
6943
  previousPagePoint,
6908
6944
  currentScreenPoint,
6909
- currentPagePoint
6945
+ currentPagePoint,
6946
+ originScreenPoint,
6947
+ originPagePoint
6910
6948
  } = this.inputs;
6911
6949
  const { screenBounds } = this.store.unsafeGetWithoutCapture(TLINSTANCE_ID);
6912
6950
  const { x: cx, y: cy, z: cz } = unsafe__withoutCapture(() => this.getCamera());
@@ -6924,8 +6962,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6924
6962
  this.inputs.isPen = info.type === "pointer" && info.isPen;
6925
6963
  if (info.name === "pointer_down" || this.inputs.isPinching) {
6926
6964
  pointerVelocity.set(0, 0);
6927
- this.inputs.originScreenPoint.setTo(currentScreenPoint);
6928
- this.inputs.originPagePoint.setTo(currentPagePoint);
6965
+ originScreenPoint.setTo(currentScreenPoint);
6966
+ originPagePoint.setTo(currentPagePoint);
6929
6967
  }
6930
6968
  this.run(
6931
6969
  () => {