@tldraw/editor 3.14.0-canary.8141719daaf3 → 3.14.0-canary.8704233e0ed5

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 (79) hide show
  1. package/dist-cjs/index.d.ts +133 -18
  2. package/dist-cjs/index.js +5 -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/hooks/useEditor.js +1 -4
  21. package/dist-cjs/lib/hooks/useEditor.js.map +2 -2
  22. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +6 -2
  23. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  24. package/dist-cjs/lib/primitives/geometry/Group2d.js +11 -6
  25. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  26. package/dist-cjs/lib/utils/dom.js +1 -1
  27. package/dist-cjs/lib/utils/dom.js.map +2 -2
  28. package/dist-cjs/lib/utils/reparenting.js +232 -0
  29. package/dist-cjs/lib/utils/reparenting.js.map +7 -0
  30. package/dist-cjs/version.js +3 -3
  31. package/dist-cjs/version.js.map +1 -1
  32. package/dist-esm/index.d.mts +133 -18
  33. package/dist-esm/index.mjs +11 -2
  34. package/dist-esm/index.mjs.map +2 -2
  35. package/dist-esm/lib/editor/Editor.mjs +81 -25
  36. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  37. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +3 -1
  38. package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +2 -2
  39. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +3 -2
  40. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  41. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +0 -10
  42. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  43. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +13 -6
  44. package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +3 -3
  45. package/dist-esm/lib/editor/tools/StateNode.mjs +3 -3
  46. package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
  47. package/dist-esm/lib/hooks/useCanvasEvents.mjs +1 -2
  48. package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
  49. package/dist-esm/lib/hooks/useEditor.mjs +1 -4
  50. package/dist-esm/lib/hooks/useEditor.mjs.map +2 -2
  51. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +6 -2
  52. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  53. package/dist-esm/lib/primitives/geometry/Group2d.mjs +11 -6
  54. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  55. package/dist-esm/lib/utils/dom.mjs +1 -1
  56. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  57. package/dist-esm/lib/utils/reparenting.mjs +216 -0
  58. package/dist-esm/lib/utils/reparenting.mjs.map +7 -0
  59. package/dist-esm/version.mjs +3 -3
  60. package/dist-esm/version.mjs.map +1 -1
  61. package/editor.css +34 -12
  62. package/package.json +7 -7
  63. package/src/index.ts +13 -1
  64. package/src/lib/editor/Editor.ts +101 -36
  65. package/src/lib/editor/managers/HistoryManager/HistoryManager.ts +3 -1
  66. package/src/lib/editor/managers/TextManager/TextManager.ts +4 -2
  67. package/src/lib/editor/shapes/ShapeUtil.ts +47 -15
  68. package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +25 -17
  69. package/src/lib/editor/tools/StateNode.ts +3 -3
  70. package/src/lib/editor/types/emit-types.ts +4 -0
  71. package/src/lib/editor/types/external-content.ts +11 -2
  72. package/src/lib/hooks/useCanvasEvents.ts +0 -1
  73. package/src/lib/hooks/useEditor.tsx +6 -5
  74. package/src/lib/primitives/geometry/Geometry2d.ts +7 -2
  75. package/src/lib/primitives/geometry/Group2d.ts +11 -5
  76. package/src/lib/utils/dom.ts +1 -1
  77. package/src/lib/utils/reparenting.ts +383 -0
  78. package/src/version.ts +3 -3
  79. package/CHANGELOG.md +0 -4327
@@ -323,6 +323,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
323
323
  __publicField(this, "externalContentHandlers", {
324
324
  text: null,
325
325
  files: null,
326
+ "file-replace": null,
326
327
  embed: null,
327
328
  "svg-text": null,
328
329
  url: null,
@@ -1641,6 +1642,19 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1641
1642
  getSelectionPageBounds() {
1642
1643
  return this.getShapesPageBounds(this.getSelectedShapeIds());
1643
1644
  }
1645
+ /**
1646
+ * The bounds of the selection bounding box in the current page space.
1647
+ *
1648
+ * @readonly
1649
+ * @public
1650
+ */
1651
+ getSelectionScreenBounds() {
1652
+ const bounds = this.getSelectionPageBounds();
1653
+ if (!bounds) return void 0;
1654
+ const { x, y } = this.pageToScreen(bounds.point);
1655
+ const zoom = this.getZoomLevel();
1656
+ return new import_Box.Box(x, y, bounds.width * zoom, bounds.height * zoom);
1657
+ }
1644
1658
  /**
1645
1659
  * @internal
1646
1660
  */
@@ -2774,7 +2788,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
2774
2788
  * @public
2775
2789
  */
2776
2790
  updateViewportScreenBounds(screenBounds, center = false) {
2777
- if (screenBounds instanceof HTMLElement) {
2791
+ if (!(screenBounds instanceof import_Box.Box)) {
2778
2792
  const rect = screenBounds.getBoundingClientRect();
2779
2793
  screenBounds = new import_Box.Box(
2780
2794
  rect.left || rect.x,
@@ -4117,7 +4131,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
4117
4131
  if (!id) return void 0;
4118
4132
  const freshShape = this.getShape(id);
4119
4133
  if (freshShape === void 0 || !(0, import_tlschema.isShapeId)(freshShape.parentId)) return void 0;
4120
- return this.store.get(freshShape.parentId);
4134
+ return this.getShape(freshShape.parentId);
4121
4135
  }
4122
4136
  /**
4123
4137
  * If siblingShape and targetShape are siblings, this returns targetShape. If targetShape has an
@@ -4249,6 +4263,9 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
4249
4263
  if (!pagePoint) continue;
4250
4264
  const newPoint = invertedParentTransform.applyToPoint(pagePoint);
4251
4265
  const newRotation = pageTransform.rotation() - parentPageRotation;
4266
+ if (shape.id === parentId) {
4267
+ throw Error("Attempted to reparent a shape to itself!");
4268
+ }
4252
4269
  changes.push({
4253
4270
  id: shape.id,
4254
4271
  type: shape.type,
@@ -4341,6 +4358,10 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
4341
4358
  }
4342
4359
  return shapeIds;
4343
4360
  }
4361
+ /** @deprecated Use {@link Editor.getDraggingOverShape} instead */
4362
+ getDroppingOverShape(point, droppingShapes) {
4363
+ return this.getDraggingOverShape(point, droppingShapes);
4364
+ }
4344
4365
  /**
4345
4366
  * Get the shape that some shapes should be dropped on at a given point.
4346
4367
  *
@@ -4351,22 +4372,20 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
4351
4372
  *
4352
4373
  * @public
4353
4374
  */
4354
- getDroppingOverShape(point, droppingShapes = []) {
4355
- const currentPageShapesSorted = this.getCurrentPageShapesSorted();
4356
- for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
4357
- const shape = currentPageShapesSorted[i];
4358
- if (
4359
- // ignore hidden shapes
4360
- this.isShapeHidden(shape) || // don't allow dropping on selected shapes
4361
- this.getSelectedShapeIds().includes(shape.id) || // only allow shapes that can receive children
4362
- !this.getShapeUtil(shape).canDropShapes(shape, droppingShapes) || // don't allow dropping a shape on itself or one of it's children
4363
- droppingShapes.find((s) => s.id === shape.id || this.hasAncestor(shape, s.id))
4364
- ) {
4365
- continue;
4366
- }
4367
- const maskedPageBounds = this.getShapeMaskedPageBounds(shape.id);
4368
- if (maskedPageBounds && maskedPageBounds.containsPoint(point) && this.getShapeGeometry(shape).hitTestPoint(this.getPointInShapeSpace(shape, point), 0, true)) {
4369
- return shape;
4375
+ getDraggingOverShape(point, droppingShapes) {
4376
+ const draggingShapes = (0, import_utils.compact)(droppingShapes.map((s) => this.getShape(s))).filter(
4377
+ (s) => !s.isLocked && !this.isShapeHidden(s)
4378
+ );
4379
+ const maybeDraggingOverShapes = this.getShapesAtPoint(point, {
4380
+ hitInside: true,
4381
+ margin: 0
4382
+ }).filter(
4383
+ (s) => !droppingShapes.includes(s) && !s.isLocked && !this.isShapeHidden(s) && !draggingShapes.includes(s)
4384
+ );
4385
+ for (const maybeDraggingOverShape of maybeDraggingOverShapes) {
4386
+ const shapeUtil = this.getShapeUtil(maybeDraggingOverShape);
4387
+ if (shapeUtil.onDragShapesOver || shapeUtil.onDragShapesIn || shapeUtil.onDragShapesOut || shapeUtil.onDropShapesOver) {
4388
+ return maybeDraggingOverShape;
4370
4389
  }
4371
4390
  }
4372
4391
  }
@@ -4643,7 +4662,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
4643
4662
  */
4644
4663
  duplicateShapes(shapes, offset) {
4645
4664
  this.run(() => {
4646
- const ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
4665
+ const _ids = typeof shapes[0] === "string" ? shapes : shapes.map((s) => s.id);
4666
+ const ids = this._shouldIgnoreShapeLock ? _ids : this._getUnlockedShapeIds(_ids);
4647
4667
  if (ids.length <= 0) return this;
4648
4668
  const initialIds = new Set(ids);
4649
4669
  const shapeIdSet = this.getShapeAndDescendantIds(ids);
@@ -4707,8 +4727,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
4707
4727
  shape.index = index;
4708
4728
  });
4709
4729
  const shapesToCreate = shapesToCreateWithOriginals.map(({ shape }) => shape);
4710
- const maxShapesReached = shapesToCreate.length + this.getCurrentPageShapeIds().size > this.options.maxShapesPerPage;
4711
- if (maxShapesReached) {
4730
+ if (!this.canCreateShapes(shapesToCreate)) {
4712
4731
  alertMaxShapes(this);
4713
4732
  return;
4714
4733
  }
@@ -5723,6 +5742,26 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
5723
5742
  getInitialMetaForShape(_shape) {
5724
5743
  return {};
5725
5744
  }
5745
+ /**
5746
+ * Get whether the provided shape can be created.
5747
+ *
5748
+ * @param shape - The shape or shape IDs to check.
5749
+ *
5750
+ * @public
5751
+ */
5752
+ canCreateShape(shape) {
5753
+ return this.canCreateShapes([shape]);
5754
+ }
5755
+ /**
5756
+ * Get whether the provided shapes can be created.
5757
+ *
5758
+ * @param shapes - The shapes or shape IDs to create.
5759
+ *
5760
+ * @public
5761
+ */
5762
+ canCreateShapes(shapes) {
5763
+ return shapes.length + this.getCurrentPageShapeIds().size <= this.options.maxShapesPerPage;
5764
+ }
5726
5765
  /**
5727
5766
  * Create a single shape.
5728
5767
  *
@@ -5776,7 +5815,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
5776
5815
  let parentId = this.getFocusedGroupId();
5777
5816
  for (let i = currentPageShapesSorted.length - 1; i >= 0; i--) {
5778
5817
  const parent = currentPageShapesSorted[i];
5779
- if (!this.isShapeHidden(parent) && this.getShapeUtil(parent).canReceiveNewChildrenOfType(parent, partial.type) && this.isPointInShape(
5818
+ const util = this.getShapeUtil(parent);
5819
+ if (util.canReceiveNewChildrenOfType(parent, partial.type) && !this.isShapeHidden(parent) && this.isPointInShape(
5780
5820
  parent,
5781
5821
  // If no parent is provided, then we can treat the
5782
5822
  // shape's provided x/y as being in the page's space.
@@ -5851,6 +5891,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
5851
5891
  ...shape.meta
5852
5892
  };
5853
5893
  });
5894
+ this.emit("created-shapes", shapeRecordsToCreate);
5895
+ this.emit("edit");
5854
5896
  this.store.put(shapeRecordsToCreate);
5855
5897
  });
5856
5898
  return this;
@@ -6092,6 +6134,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
6092
6134
  updated = this.getShapeUtil(shape).onBeforeUpdate?.(shape, updated) ?? updated;
6093
6135
  updates.push(updated);
6094
6136
  }
6137
+ this.emit("edited-shapes", updates);
6138
+ this.emit("edit");
6095
6139
  this.store.put(updates);
6096
6140
  });
6097
6141
  }
@@ -6113,6 +6157,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
6113
6157
  allShapeIdsToDelete.add(childId);
6114
6158
  });
6115
6159
  }
6160
+ this.emit("deleted-shapes", [...allShapeIdsToDelete]);
6161
+ this.emit("edit");
6116
6162
  return this.run(() => this.store.remove([...allShapeIdsToDelete]));
6117
6163
  }
6118
6164
  deleteShape(_id) {
@@ -6456,6 +6502,14 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
6456
6502
  async putExternalContent(info) {
6457
6503
  return this.externalContentHandlers[info.type]?.(info);
6458
6504
  }
6505
+ /**
6506
+ * Handle replacing external content.
6507
+ *
6508
+ * @param info - Info about the external content.
6509
+ */
6510
+ async replaceExternalContent(info) {
6511
+ return this.externalContentHandlers[info.type]?.(info);
6512
+ }
6459
6513
  /**
6460
6514
  * Get content that can be exported for the given shape ids.
6461
6515
  *
@@ -6873,7 +6927,9 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
6873
6927
  previousScreenPoint,
6874
6928
  previousPagePoint,
6875
6929
  currentScreenPoint,
6876
- currentPagePoint
6930
+ currentPagePoint,
6931
+ originScreenPoint,
6932
+ originPagePoint
6877
6933
  } = this.inputs;
6878
6934
  const { screenBounds } = this.store.unsafeGetWithoutCapture(import_tlschema.TLINSTANCE_ID);
6879
6935
  const { x: cx, y: cy, z: cz } = (0, import_state.unsafe__withoutCapture)(() => this.getCamera());
@@ -6891,8 +6947,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
6891
6947
  this.inputs.isPen = info.type === "pointer" && info.isPen;
6892
6948
  if (info.name === "pointer_down" || this.inputs.isPinching) {
6893
6949
  pointerVelocity.set(0, 0);
6894
- this.inputs.originScreenPoint.setTo(currentScreenPoint);
6895
- this.inputs.originPagePoint.setTo(currentPagePoint);
6950
+ originScreenPoint.setTo(currentScreenPoint);
6951
+ originPagePoint.setTo(currentPagePoint);
6896
6952
  }
6897
6953
  this.run(
6898
6954
  () => {