@tldraw/editor 3.14.0-canary.c76a772c4700 → 3.14.0-canary.cad451c26011

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 (74) hide show
  1. package/dist-cjs/index.d.ts +122 -16
  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 +81 -25
  5. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  6. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +3 -1
  7. package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +2 -2
  8. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +3 -2
  9. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  10. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +0 -10
  11. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  12. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +13 -6
  13. package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +3 -3
  14. package/dist-cjs/lib/editor/tools/StateNode.js +3 -3
  15. package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
  16. package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
  17. package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
  18. package/dist-cjs/lib/hooks/useCanvasEvents.js +1 -2
  19. package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
  20. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +6 -2
  21. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  22. package/dist-cjs/lib/primitives/geometry/Group2d.js +11 -6
  23. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  24. package/dist-cjs/lib/utils/dom.js +1 -1
  25. package/dist-cjs/lib/utils/dom.js.map +2 -2
  26. package/dist-cjs/lib/utils/reparenting.js +232 -0
  27. package/dist-cjs/lib/utils/reparenting.js.map +7 -0
  28. package/dist-cjs/version.js +4 -4
  29. package/dist-cjs/version.js.map +1 -1
  30. package/dist-esm/index.d.mts +122 -16
  31. package/dist-esm/index.mjs +4 -1
  32. package/dist-esm/index.mjs.map +2 -2
  33. package/dist-esm/lib/editor/Editor.mjs +81 -25
  34. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  35. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +3 -1
  36. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +2 -2
  37. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +3 -2
  38. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  39. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +0 -10
  40. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  41. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +13 -6
  42. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +3 -3
  43. package/dist-esm/lib/editor/tools/StateNode.mjs +3 -3
  44. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  45. package/dist-esm/lib/hooks/useCanvasEvents.mjs +1 -2
  46. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  47. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +6 -2
  48. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  49. package/dist-esm/lib/primitives/geometry/Group2d.mjs +11 -6
  50. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  51. package/dist-esm/lib/utils/dom.mjs +1 -1
  52. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  53. package/dist-esm/lib/utils/reparenting.mjs +216 -0
  54. package/dist-esm/lib/utils/reparenting.mjs.map +7 -0
  55. package/dist-esm/version.mjs +4 -4
  56. package/dist-esm/version.mjs.map +1 -1
  57. package/editor.css +34 -12
  58. package/package.json +7 -7
  59. package/src/index.ts +6 -0
  60. package/src/lib/editor/Editor.ts +101 -36
  61. package/src/lib/editor/managers/HistoryManager/HistoryManager.ts +3 -1
  62. package/src/lib/editor/managers/TextManager/TextManager.ts +4 -2
  63. package/src/lib/editor/shapes/ShapeUtil.ts +47 -15
  64. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +25 -17
  65. package/src/lib/editor/tools/StateNode.ts +3 -3
  66. package/src/lib/editor/types/emit-types.ts +4 -0
  67. package/src/lib/editor/types/external-content.ts +11 -2
  68. package/src/lib/hooks/useCanvasEvents.ts +0 -1
  69. package/src/lib/primitives/geometry/Geometry2d.ts +7 -2
  70. package/src/lib/primitives/geometry/Group2d.ts +11 -5
  71. package/src/lib/utils/dom.ts +1 -1
  72. package/src/lib/utils/reparenting.ts +383 -0
  73. package/src/version.ts +4 -4
  74. package/CHANGELOG.md +0 -4327
@@ -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,
@@ -1675,6 +1676,19 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
1675
1676
  getSelectionPageBounds() {
1676
1677
  return this.getShapesPageBounds(this.getSelectedShapeIds());
1677
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
+ }
1678
1692
  /**
1679
1693
  * @internal
1680
1694
  */
@@ -2808,7 +2822,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
2808
2822
  * @public
2809
2823
  */
2810
2824
  updateViewportScreenBounds(screenBounds, center = false) {
2811
- if (screenBounds instanceof HTMLElement) {
2825
+ if (!(screenBounds instanceof Box)) {
2812
2826
  const rect = screenBounds.getBoundingClientRect();
2813
2827
  screenBounds = new Box(
2814
2828
  rect.left || rect.x,
@@ -4151,7 +4165,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4151
4165
  if (!id) return void 0;
4152
4166
  const freshShape = this.getShape(id);
4153
4167
  if (freshShape === void 0 || !isShapeId(freshShape.parentId)) return void 0;
4154
- return this.store.get(freshShape.parentId);
4168
+ return this.getShape(freshShape.parentId);
4155
4169
  }
4156
4170
  /**
4157
4171
  * If siblingShape and targetShape are siblings, this returns targetShape. If targetShape has an
@@ -4283,6 +4297,9 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4283
4297
  if (!pagePoint) continue;
4284
4298
  const newPoint = invertedParentTransform.applyToPoint(pagePoint);
4285
4299
  const newRotation = pageTransform.rotation() - parentPageRotation;
4300
+ if (shape.id === parentId) {
4301
+ throw Error("Attempted to reparent a shape to itself!");
4302
+ }
4286
4303
  changes.push({
4287
4304
  id: shape.id,
4288
4305
  type: shape.type,
@@ -4375,6 +4392,10 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4375
4392
  }
4376
4393
  return shapeIds;
4377
4394
  }
4395
+ /** @deprecated Use {@link Editor.getDraggingOverShape} instead */
4396
+ getDroppingOverShape(point, droppingShapes) {
4397
+ return this.getDraggingOverShape(point, droppingShapes);
4398
+ }
4378
4399
  /**
4379
4400
  * Get the shape that some shapes should be dropped on at a given point.
4380
4401
  *
@@ -4385,22 +4406,20 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4385
4406
  *
4386
4407
  * @public
4387
4408
  */
4388
- getDroppingOverShape(point, droppingShapes = []) {
4389
- const currentPageShapesSorted = this.getCurrentPageShapesSorted();
4390
- for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
4391
- const shape = currentPageShapesSorted[i];
4392
- if (
4393
- // ignore hidden shapes
4394
- this.isShapeHidden(shape) || // don't allow dropping on selected shapes
4395
- this.getSelectedShapeIds().includes(shape.id) || // only allow shapes that can receive children
4396
- !this.getShapeUtil(shape).canDropShapes(shape, droppingShapes) || // don't allow dropping a shape on itself or one of it's children
4397
- droppingShapes.find((s) => s.id === shape.id || this.hasAncestor(shape, s.id))
4398
- ) {
4399
- continue;
4400
- }
4401
- const maskedPageBounds = this.getShapeMaskedPageBounds(shape.id);
4402
- if (maskedPageBounds && maskedPageBounds.containsPoint(point) && this.getShapeGeometry(shape).hitTestPoint(this.getPointInShapeSpace(shape, point), 0, true)) {
4403
- 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;
4404
4423
  }
4405
4424
  }
4406
4425
  }
@@ -4677,7 +4696,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4677
4696
  */
4678
4697
  duplicateShapes(shapes, offset) {
4679
4698
  this.run(() => {
4680
- 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);
4681
4701
  if (ids.length <= 0) return this;
4682
4702
  const initialIds = new Set(ids);
4683
4703
  const shapeIdSet = this.getShapeAndDescendantIds(ids);
@@ -4741,8 +4761,7 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
4741
4761
  shape.index = index;
4742
4762
  });
4743
4763
  const shapesToCreate = shapesToCreateWithOriginals.map(({ shape }) => shape);
4744
- const maxShapesReached = shapesToCreate.length + this.getCurrentPageShapeIds().size > this.options.maxShapesPerPage;
4745
- if (maxShapesReached) {
4764
+ if (!this.canCreateShapes(shapesToCreate)) {
4746
4765
  alertMaxShapes(this);
4747
4766
  return;
4748
4767
  }
@@ -5757,6 +5776,26 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
5757
5776
  getInitialMetaForShape(_shape) {
5758
5777
  return {};
5759
5778
  }
5779
+ /**
5780
+ * Get whether the provided shape can be created.
5781
+ *
5782
+ * @param shape - The shape or shape IDs to check.
5783
+ *
5784
+ * @public
5785
+ */
5786
+ canCreateShape(shape) {
5787
+ return this.canCreateShapes([shape]);
5788
+ }
5789
+ /**
5790
+ * Get whether the provided shapes can be created.
5791
+ *
5792
+ * @param shapes - The shapes or shape IDs to create.
5793
+ *
5794
+ * @public
5795
+ */
5796
+ canCreateShapes(shapes) {
5797
+ return shapes.length + this.getCurrentPageShapeIds().size <= this.options.maxShapesPerPage;
5798
+ }
5760
5799
  /**
5761
5800
  * Create a single shape.
5762
5801
  *
@@ -5810,7 +5849,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
5810
5849
  let parentId = this.getFocusedGroupId();
5811
5850
  for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
5812
5851
  const parent = currentPageShapesSorted[i];
5813
- if (!this.isShapeHidden(parent) && this.getShapeUtil(parent).canReceiveNewChildrenOfType(parent, partial.type) && this.isPointInShape(
5852
+ const util = this.getShapeUtil(parent);
5853
+ if (util.canReceiveNewChildrenOfType(parent, partial.type) && !this.isShapeHidden(parent) && this.isPointInShape(
5814
5854
  parent,
5815
5855
  // If no parent is provided, then we can treat the
5816
5856
  // shape's provided x/y as being in the page's space.
@@ -5885,6 +5925,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
5885
5925
  ...shape.meta
5886
5926
  };
5887
5927
  });
5928
+ this.emit("created-shapes", shapeRecordsToCreate);
5929
+ this.emit("edit");
5888
5930
  this.store.put(shapeRecordsToCreate);
5889
5931
  });
5890
5932
  return this;
@@ -6126,6 +6168,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6126
6168
  updated = this.getShapeUtil(shape).onBeforeUpdate?.(shape, updated) ?? updated;
6127
6169
  updates.push(updated);
6128
6170
  }
6171
+ this.emit("edited-shapes", updates);
6172
+ this.emit("edit");
6129
6173
  this.store.put(updates);
6130
6174
  });
6131
6175
  }
@@ -6147,6 +6191,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6147
6191
  allShapeIdsToDelete.add(childId);
6148
6192
  });
6149
6193
  }
6194
+ this.emit("deleted-shapes", [...allShapeIdsToDelete]);
6195
+ this.emit("edit");
6150
6196
  return this.run(() => this.store.remove([...allShapeIdsToDelete]));
6151
6197
  }
6152
6198
  deleteShape(_id) {
@@ -6490,6 +6536,14 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6490
6536
  async putExternalContent(info) {
6491
6537
  return this.externalContentHandlers[info.type]?.(info);
6492
6538
  }
6539
+ /**
6540
+ * Handle replacing external content.
6541
+ *
6542
+ * @param info - Info about the external content.
6543
+ */
6544
+ async replaceExternalContent(info) {
6545
+ return this.externalContentHandlers[info.type]?.(info);
6546
+ }
6493
6547
  /**
6494
6548
  * Get content that can be exported for the given shape ids.
6495
6549
  *
@@ -6907,7 +6961,9 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6907
6961
  previousScreenPoint,
6908
6962
  previousPagePoint,
6909
6963
  currentScreenPoint,
6910
- currentPagePoint
6964
+ currentPagePoint,
6965
+ originScreenPoint,
6966
+ originPagePoint
6911
6967
  } = this.inputs;
6912
6968
  const { screenBounds } = this.store.unsafeGetWithoutCapture(TLINSTANCE_ID);
6913
6969
  const { x: cx, y: cy, z: cz } = unsafe__withoutCapture(() => this.getCamera());
@@ -6925,8 +6981,8 @@ class Editor extends (_a = EventEmitter, _getIsShapeHiddenCache_dec = [computed]
6925
6981
  this.inputs.isPen = info.type === "pointer" && info.isPen;
6926
6982
  if (info.name === "pointer_down" || this.inputs.isPinching) {
6927
6983
  pointerVelocity.set(0, 0);
6928
- this.inputs.originScreenPoint.setTo(currentScreenPoint);
6929
- this.inputs.originPagePoint.setTo(currentPagePoint);
6984
+ originScreenPoint.setTo(currentScreenPoint);
6985
+ originPagePoint.setTo(currentPagePoint);
6930
6986
  }
6931
6987
  this.run(
6932
6988
  () => {