@tldraw/editor 3.13.0-canary.fd867adaa211 → 3.14.0-canary.95353287a2be

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 (147) hide show
  1. package/CHANGELOG.md +180 -0
  2. package/dist-cjs/index.d.ts +99 -99
  3. package/dist-cjs/index.js +7 -22
  4. package/dist-cjs/index.js.map +2 -2
  5. package/dist-cjs/lib/components/Shape.js +12 -8
  6. package/dist-cjs/lib/components/Shape.js.map +2 -2
  7. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +31 -8
  8. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  9. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +17 -11
  10. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
  11. package/dist-cjs/lib/editor/Editor.js +85 -24
  12. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  13. package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js.map +2 -2
  14. package/dist-cjs/lib/editor/managers/TextManager.js +10 -0
  15. package/dist-cjs/lib/editor/managers/TextManager.js.map +2 -2
  16. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +1 -1
  17. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  18. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +0 -3
  19. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
  20. package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js.map +2 -2
  21. package/dist-cjs/lib/exports/getSvgJsx.js +12 -3
  22. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  23. package/dist-cjs/lib/hooks/useEditorComponents.js +1 -2
  24. package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
  25. package/dist-cjs/lib/primitives/Box.js +16 -0
  26. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  27. package/dist-cjs/lib/primitives/Mat.js +1 -1
  28. package/dist-cjs/lib/primitives/Mat.js.map +2 -2
  29. package/dist-cjs/lib/primitives/Vec.js +20 -0
  30. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  31. package/dist-cjs/lib/primitives/geometry/Arc2d.js +2 -2
  32. package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
  33. package/dist-cjs/lib/primitives/geometry/Circle2d.js +1 -1
  34. package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
  35. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +1 -1
  36. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
  37. package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js.map +2 -2
  38. package/dist-cjs/lib/primitives/geometry/Edge2d.js +1 -1
  39. package/dist-cjs/lib/primitives/geometry/Edge2d.js.map +2 -2
  40. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
  41. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +91 -20
  42. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  43. package/dist-cjs/lib/primitives/geometry/Group2d.js +55 -2
  44. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  45. package/dist-cjs/lib/primitives/geometry/Point2d.js.map +2 -2
  46. package/dist-cjs/lib/primitives/geometry/Polyline2d.js.map +2 -2
  47. package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +2 -2
  48. package/dist-cjs/lib/utils/areShapesContentEqual.js +25 -0
  49. package/dist-cjs/lib/utils/areShapesContentEqual.js.map +7 -0
  50. package/dist-cjs/lib/utils/debug-flags.js +5 -2
  51. package/dist-cjs/lib/utils/debug-flags.js.map +2 -2
  52. package/dist-cjs/lib/utils/nearestMultiple.js +34 -0
  53. package/dist-cjs/lib/utils/nearestMultiple.js.map +7 -0
  54. package/dist-cjs/version.js +3 -3
  55. package/dist-cjs/version.js.map +1 -1
  56. package/dist-esm/index.d.mts +99 -99
  57. package/dist-esm/index.mjs +9 -41
  58. package/dist-esm/index.mjs.map +2 -2
  59. package/dist-esm/lib/components/Shape.mjs +12 -8
  60. package/dist-esm/lib/components/Shape.mjs.map +2 -2
  61. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +31 -8
  62. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  63. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +17 -11
  64. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  65. package/dist-esm/lib/editor/Editor.mjs +85 -24
  66. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  67. package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs.map +2 -2
  68. package/dist-esm/lib/editor/managers/TextManager.mjs +10 -0
  69. package/dist-esm/lib/editor/managers/TextManager.mjs.map +2 -2
  70. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +1 -1
  71. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  72. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +0 -3
  73. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
  74. package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs.map +2 -2
  75. package/dist-esm/lib/exports/getSvgJsx.mjs +12 -3
  76. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  77. package/dist-esm/lib/hooks/useEditorComponents.mjs +1 -4
  78. package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
  79. package/dist-esm/lib/primitives/Box.mjs +16 -0
  80. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  81. package/dist-esm/lib/primitives/Mat.mjs +1 -1
  82. package/dist-esm/lib/primitives/Mat.mjs.map +2 -2
  83. package/dist-esm/lib/primitives/Vec.mjs +20 -0
  84. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  85. package/dist-esm/lib/primitives/geometry/Arc2d.mjs +2 -2
  86. package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
  87. package/dist-esm/lib/primitives/geometry/Circle2d.mjs +1 -1
  88. package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
  89. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +1 -1
  90. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
  91. package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs.map +2 -2
  92. package/dist-esm/lib/primitives/geometry/Edge2d.mjs +1 -1
  93. package/dist-esm/lib/primitives/geometry/Edge2d.mjs.map +2 -2
  94. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
  95. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +92 -21
  96. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  97. package/dist-esm/lib/primitives/geometry/Group2d.mjs +55 -2
  98. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  99. package/dist-esm/lib/primitives/geometry/Point2d.mjs.map +2 -2
  100. package/dist-esm/lib/primitives/geometry/Polyline2d.mjs.map +2 -2
  101. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +2 -2
  102. package/dist-esm/lib/utils/areShapesContentEqual.mjs +5 -0
  103. package/dist-esm/lib/utils/areShapesContentEqual.mjs.map +7 -0
  104. package/dist-esm/lib/utils/debug-flags.mjs +5 -2
  105. package/dist-esm/lib/utils/debug-flags.mjs.map +2 -2
  106. package/dist-esm/lib/utils/nearestMultiple.mjs +14 -0
  107. package/dist-esm/lib/utils/nearestMultiple.mjs.map +7 -0
  108. package/dist-esm/version.mjs +3 -3
  109. package/dist-esm/version.mjs.map +1 -1
  110. package/editor.css +36 -4
  111. package/package.json +7 -7
  112. package/src/index.ts +16 -31
  113. package/src/lib/components/Shape.tsx +14 -10
  114. package/src/lib/components/default-components/DefaultCanvas.tsx +32 -8
  115. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +17 -8
  116. package/src/lib/editor/Editor.test.ts +1 -1
  117. package/src/lib/editor/Editor.ts +96 -24
  118. package/src/lib/editor/managers/SnapManager/HandleSnaps.ts +0 -1
  119. package/src/lib/editor/managers/TextManager.ts +12 -0
  120. package/src/lib/editor/shapes/ShapeUtil.ts +10 -2
  121. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +0 -4
  122. package/src/lib/editor/shapes/shared/getPerfectDashProps.ts +9 -9
  123. package/src/lib/exports/getSvgJsx.tsx +16 -7
  124. package/src/lib/hooks/useEditorComponents.tsx +2 -5
  125. package/src/lib/primitives/Box.ts +20 -0
  126. package/src/lib/primitives/Mat.ts +5 -4
  127. package/src/lib/primitives/Vec.ts +23 -0
  128. package/src/lib/primitives/geometry/Arc2d.ts +5 -5
  129. package/src/lib/primitives/geometry/Circle2d.ts +4 -4
  130. package/src/lib/primitives/geometry/CubicBezier2d.ts +4 -4
  131. package/src/lib/primitives/geometry/CubicSpline2d.ts +3 -3
  132. package/src/lib/primitives/geometry/Edge2d.ts +3 -3
  133. package/src/lib/primitives/geometry/Ellipse2d.ts +3 -3
  134. package/src/lib/primitives/geometry/Geometry2d.test.ts +42 -0
  135. package/src/lib/primitives/geometry/Geometry2d.ts +123 -35
  136. package/src/lib/primitives/geometry/Group2d.ts +70 -7
  137. package/src/lib/primitives/geometry/Point2d.ts +2 -2
  138. package/src/lib/primitives/geometry/Polyline2d.ts +3 -3
  139. package/src/lib/primitives/geometry/Stadium2d.ts +3 -3
  140. package/src/lib/test/currentToolIdMask.test.ts +1 -1
  141. package/src/lib/test/user.test.ts +1 -1
  142. package/src/lib/utils/areShapesContentEqual.ts +4 -0
  143. package/src/lib/utils/debug-flags.ts +7 -2
  144. package/src/lib/utils/nearestMultiple.ts +13 -0
  145. package/src/lib/utils/sync/LocalIndexedDb.test.ts +1 -1
  146. package/src/lib/utils/sync/TLLocalSyncClient.test.ts +1 -1
  147. package/src/version.ts +3 -3
@@ -100,6 +100,7 @@ var import_Group2d = require("../primitives/geometry/Group2d");
100
100
  var import_intersect = require("../primitives/intersect");
101
101
  var import_utils2 = require("../primitives/utils");
102
102
  var import_SharedStylesMap = require("../utils/SharedStylesMap");
103
+ var import_areShapesContentEqual = require("../utils/areShapesContentEqual");
103
104
  var import_assets = require("../utils/assets");
104
105
  var import_debug_flags = require("../utils/debug-flags");
105
106
  var import_deepLinks = require("../utils/deepLinks");
@@ -423,7 +424,6 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
423
424
  ) : getShapeVisibility;
424
425
  this.options = { ...import_options.defaultTldrawOptions, ...options };
425
426
  this.store = store;
426
- this.disposables.add(this.store.dispose.bind(this.store));
427
427
  this.history = new import_HistoryManager.HistoryManager({
428
428
  store,
429
429
  annotateError: (error) => {
@@ -835,6 +835,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
835
835
  dispose() {
836
836
  this.disposables.forEach((dispose) => dispose());
837
837
  this.disposables.clear();
838
+ this.store.dispose();
838
839
  this.isDisposed = true;
839
840
  }
840
841
  getShapeUtil(arg) {
@@ -1440,9 +1441,23 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1440
1441
  this.setSelectedShapes(this._getUnlockedShapeIds(ids));
1441
1442
  return this;
1442
1443
  }
1444
+ /**
1445
+ * Select the next shape in the reading order or in cardinal order.
1446
+ *
1447
+ * @example
1448
+ * ```ts
1449
+ * editor.selectAdjacentShape('next')
1450
+ * ```
1451
+ *
1452
+ * @public
1453
+ */
1443
1454
  selectAdjacentShape(direction) {
1444
- const readingOrderShapes = this.getCurrentPageShapesInReadingOrder();
1445
1455
  const selectedShapeIds = this.getSelectedShapeIds();
1456
+ const firstParentId = selectedShapeIds[0] ? this.getShape(selectedShapeIds[0])?.parentId : null;
1457
+ const isSelectedWithinContainer = firstParentId && selectedShapeIds.every((shapeId) => this.getShape(shapeId)?.parentId === firstParentId) && !(0, import_tlschema.isPageId)(firstParentId);
1458
+ const readingOrderShapes = isSelectedWithinContainer ? this._getShapesInReadingOrder(
1459
+ this.getCurrentPageShapes().filter((shape2) => shape2.parentId === firstParentId)
1460
+ ) : this.getCurrentPageShapesInReadingOrder();
1446
1461
  const currentShapeId = selectedShapeIds.length === 1 ? selectedShapeIds[0] : readingOrderShapes.find((shape2) => selectedShapeIds.includes(shape2.id))?.id;
1447
1462
  let adjacentShapeId;
1448
1463
  if (direction === "next" || direction === "prev") {
@@ -1456,18 +1471,15 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1456
1471
  }
1457
1472
  const shape = this.getShape(adjacentShapeId);
1458
1473
  if (!shape) return;
1459
- this.setSelectedShapes([shape.id]);
1460
- this.zoomToSelectionIfOffscreen(256, {
1461
- animation: {
1462
- duration: this.options.animationMediumMs
1463
- },
1464
- inset: 0
1465
- });
1474
+ this._selectShapesAndZoom([shape.id]);
1466
1475
  }
1467
1476
  getCurrentPageShapesInReadingOrder() {
1477
+ const shapes = this.getCurrentPageShapes().filter((shape) => (0, import_tlschema.isPageId)(shape.parentId));
1478
+ return this._getShapesInReadingOrder(shapes);
1479
+ }
1480
+ _getShapesInReadingOrder(shapes) {
1468
1481
  const SHALLOW_ANGLE = 20;
1469
1482
  const ROW_THRESHOLD = 100;
1470
- const shapes = this.getCurrentPageShapes();
1471
1483
  const tabbableShapes = shapes.filter((shape) => this.getShapeUtil(shape).canTabTo(shape));
1472
1484
  if (tabbableShapes.length <= 1) return tabbableShapes;
1473
1485
  const shapesWithCenters = tabbableShapes.map((shape) => ({
@@ -1565,6 +1577,31 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1565
1577
  });
1566
1578
  return lowestScoringShape.shape.id;
1567
1579
  }
1580
+ selectParentShape() {
1581
+ const selectedShape = this.getOnlySelectedShape();
1582
+ if (!selectedShape) return;
1583
+ const parentShape = this.getShape(selectedShape.parentId);
1584
+ if (!parentShape) return;
1585
+ this._selectShapesAndZoom([parentShape.id]);
1586
+ }
1587
+ selectFirstChildShape() {
1588
+ const selectedShapes = this.getSelectedShapes();
1589
+ if (!selectedShapes.length) return;
1590
+ const selectedShape = selectedShapes[0];
1591
+ const children = this.getSortedChildIdsForParent(selectedShape.id).map((id) => this.getShape(id)).filter((i) => i);
1592
+ const sortedChildren = this._getShapesInReadingOrder(children);
1593
+ if (sortedChildren.length === 0) return;
1594
+ this._selectShapesAndZoom([sortedChildren[0].id]);
1595
+ }
1596
+ _selectShapesAndZoom(ids) {
1597
+ this.setSelectedShapes(ids);
1598
+ this.zoomToSelectionIfOffscreen(256, {
1599
+ animation: {
1600
+ duration: this.options.animationMediumMs
1601
+ },
1602
+ inset: 0
1603
+ });
1604
+ }
1568
1605
  /**
1569
1606
  * Clear the selection.
1570
1607
  *
@@ -1737,13 +1774,21 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1737
1774
  setEditingShape(shape) {
1738
1775
  const id = typeof shape === "string" ? shape : shape?.id ?? null;
1739
1776
  this.setRichTextEditor(null);
1740
- if (id !== this.getEditingShapeId()) {
1777
+ const prevEditingShapeId = this.getEditingShapeId();
1778
+ if (id !== prevEditingShapeId) {
1741
1779
  if (id) {
1742
1780
  const shape2 = this.getShape(id);
1743
1781
  if (shape2 && this.getShapeUtil(shape2).canEdit(shape2)) {
1744
1782
  this.run(
1745
1783
  () => {
1746
1784
  this._updateCurrentPageState({ editingShapeId: id });
1785
+ if (prevEditingShapeId) {
1786
+ const prevEditingShape = this.getShape(prevEditingShapeId);
1787
+ if (prevEditingShape) {
1788
+ this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
1789
+ }
1790
+ }
1791
+ this.getShapeUtil(shape2).onEditStart?.(shape2);
1747
1792
  },
1748
1793
  { history: "ignore" }
1749
1794
  );
@@ -1754,6 +1799,12 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1754
1799
  () => {
1755
1800
  this._updateCurrentPageState({ editingShapeId: null });
1756
1801
  this._currentRichTextEditor.set(null);
1802
+ if (prevEditingShapeId) {
1803
+ const prevEditingShape = this.getShape(prevEditingShapeId);
1804
+ if (prevEditingShape) {
1805
+ this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape);
1806
+ }
1807
+ }
1757
1808
  },
1758
1809
  { history: "ignore" }
1759
1810
  );
@@ -3439,7 +3490,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3439
3490
  this.fonts.trackFontsForShape(shape2);
3440
3491
  return this.getShapeUtil(shape2).getGeometry(shape2, opts);
3441
3492
  },
3442
- { areRecordsEqual: (a, b) => a.props === b.props }
3493
+ { areRecordsEqual: import_areShapesContentEqual.areShapesContentEqual }
3443
3494
  );
3444
3495
  }
3445
3496
  return this._shapeGeometryCaches[context].get(
@@ -3482,9 +3533,15 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3482
3533
  );
3483
3534
  }
3484
3535
  _getShapeHandlesCache() {
3485
- return this.store.createComputedCache("handles", (shape) => {
3486
- return this.getShapeUtil(shape).getHandles?.(shape);
3487
- });
3536
+ return this.store.createComputedCache(
3537
+ "handles",
3538
+ (shape) => {
3539
+ return this.getShapeUtil(shape).getHandles?.(shape);
3540
+ },
3541
+ {
3542
+ areRecordsEqual: import_areShapesContentEqual.areShapesContentEqual
3543
+ }
3544
+ );
3488
3545
  }
3489
3546
  /**
3490
3547
  * Get the handles (if any) for a shape.
@@ -4368,9 +4425,15 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
4368
4425
  }
4369
4426
  _getBindingsIndexCache() {
4370
4427
  const index = (0, import_bindingsIndex.bindingsIndex)(this);
4371
- return this.store.createComputedCache("bindingsIndex", (shape) => {
4372
- return index.get().get(shape.id);
4373
- });
4428
+ return this.store.createComputedCache(
4429
+ "bindingsIndex",
4430
+ (shape) => {
4431
+ return index.get().get(shape.id);
4432
+ },
4433
+ // we can ignore the shape equality check here because the index is
4434
+ // computed incrementally based on what bindings are in the store
4435
+ { areRecordsEqual: () => true }
4436
+ );
4374
4437
  }
4375
4438
  /**
4376
4439
  * Get a binding from the store by its ID if it exists.
@@ -7445,7 +7508,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7445
7508
  const { x: cx, y: cy, z: cz } = (0, import_state.unsafe__withoutCapture)(() => this.getCamera());
7446
7509
  const { x: dx, y: dy, z: dz = 0 } = info.delta;
7447
7510
  let behavior = wheelBehavior;
7448
- if (inputs.ctrlKey) behavior = wheelBehavior === "pan" ? "zoom" : "pan";
7511
+ if (info.ctrlKey) behavior = wheelBehavior === "pan" ? "zoom" : "pan";
7449
7512
  switch (behavior) {
7450
7513
  case "zoom": {
7451
7514
  const { x, y } = this.inputs.currentScreenPoint;
@@ -7526,12 +7589,10 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7526
7589
  const { x: cx, y: cy, z: cz } = (0, import_state.unsafe__withoutCapture)(() => this.getCamera());
7527
7590
  if (this.inputs.isPanning && this.inputs.isPointing) {
7528
7591
  const { currentScreenPoint, previousScreenPoint } = this.inputs;
7529
- const { panSpeed } = cameraOptions;
7530
7592
  const offset = import_Vec.Vec.Sub(currentScreenPoint, previousScreenPoint);
7531
- this.setCamera(
7532
- new import_Vec.Vec(cx + offset.x * panSpeed / cz, cy + offset.y * panSpeed / cz, cz),
7533
- { immediate: true }
7534
- );
7593
+ this.setCamera(new import_Vec.Vec(cx + offset.x / cz, cy + offset.y / cz, cz), {
7594
+ immediate: true
7595
+ });
7535
7596
  this.maybeTrackPerformance("Panning");
7536
7597
  return;
7537
7598
  }