@tldraw/editor 3.13.0-canary.3095a57e7c2c → 3.13.0-canary.31a6adda2e18

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 (185) hide show
  1. package/dist-cjs/index.d.ts +129 -113
  2. package/dist-cjs/index.js +7 -22
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js +2 -1
  5. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  6. package/dist-cjs/lib/components/Shape.js +12 -8
  7. package/dist-cjs/lib/components/Shape.js.map +2 -2
  8. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +37 -8
  9. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  10. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +14 -12
  11. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
  12. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +17 -11
  13. package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
  14. package/dist-cjs/lib/components/default-components/DefaultSpinner.js +1 -1
  15. package/dist-cjs/lib/components/default-components/DefaultSpinner.js.map +2 -2
  16. package/dist-cjs/lib/editor/Editor.js +110 -44
  17. package/dist-cjs/lib/editor/Editor.js.map +3 -3
  18. package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js.map +2 -2
  19. package/dist-cjs/lib/editor/managers/TextManager.js +10 -0
  20. package/dist-cjs/lib/editor/managers/TextManager.js.map +2 -2
  21. package/dist-cjs/lib/editor/shapes/ShapeUtil.js +1 -1
  22. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
  23. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +0 -3
  24. package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
  25. package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js.map +2 -2
  26. package/dist-cjs/lib/exports/getSvgJsx.js +12 -3
  27. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  28. package/dist-cjs/lib/hooks/useDocumentEvents.js +3 -2
  29. package/dist-cjs/lib/hooks/useDocumentEvents.js.map +2 -2
  30. package/dist-cjs/lib/hooks/useEditorComponents.js +16 -16
  31. package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
  32. package/dist-cjs/lib/license/LicenseManager.js +8 -1
  33. package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
  34. package/dist-cjs/lib/options.js.map +2 -2
  35. package/dist-cjs/lib/primitives/Box.js +16 -0
  36. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  37. package/dist-cjs/lib/primitives/Mat.js +1 -1
  38. package/dist-cjs/lib/primitives/Mat.js.map +2 -2
  39. package/dist-cjs/lib/primitives/Vec.js +20 -0
  40. package/dist-cjs/lib/primitives/Vec.js.map +2 -2
  41. package/dist-cjs/lib/primitives/geometry/Arc2d.js +2 -2
  42. package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
  43. package/dist-cjs/lib/primitives/geometry/Circle2d.js +1 -1
  44. package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
  45. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js +1 -1
  46. package/dist-cjs/lib/primitives/geometry/CubicBezier2d.js.map +2 -2
  47. package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js.map +2 -2
  48. package/dist-cjs/lib/primitives/geometry/Edge2d.js +1 -1
  49. package/dist-cjs/lib/primitives/geometry/Edge2d.js.map +2 -2
  50. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
  51. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +91 -20
  52. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  53. package/dist-cjs/lib/primitives/geometry/Group2d.js +55 -2
  54. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  55. package/dist-cjs/lib/primitives/geometry/Point2d.js.map +2 -2
  56. package/dist-cjs/lib/primitives/geometry/Polyline2d.js.map +2 -2
  57. package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +2 -2
  58. package/dist-cjs/lib/utils/areShapesContentEqual.js +25 -0
  59. package/dist-cjs/lib/utils/areShapesContentEqual.js.map +7 -0
  60. package/dist-cjs/lib/utils/debug-flags.js +5 -2
  61. package/dist-cjs/lib/utils/debug-flags.js.map +2 -2
  62. package/dist-cjs/lib/utils/dom.js +3 -3
  63. package/dist-cjs/lib/utils/dom.js.map +2 -2
  64. package/dist-cjs/lib/utils/nearestMultiple.js +34 -0
  65. package/dist-cjs/lib/utils/nearestMultiple.js.map +7 -0
  66. package/dist-cjs/lib/utils/rotation.js +5 -5
  67. package/dist-cjs/lib/utils/rotation.js.map +2 -2
  68. package/dist-cjs/version.js +3 -3
  69. package/dist-cjs/version.js.map +1 -1
  70. package/dist-esm/index.d.mts +129 -113
  71. package/dist-esm/index.mjs +9 -41
  72. package/dist-esm/index.mjs.map +2 -2
  73. package/dist-esm/lib/TldrawEditor.mjs +2 -1
  74. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  75. package/dist-esm/lib/components/Shape.mjs +12 -8
  76. package/dist-esm/lib/components/Shape.mjs.map +2 -2
  77. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +37 -8
  78. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  79. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +14 -12
  80. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
  81. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +17 -11
  82. package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
  83. package/dist-esm/lib/components/default-components/DefaultSpinner.mjs +1 -1
  84. package/dist-esm/lib/components/default-components/DefaultSpinner.mjs.map +2 -2
  85. package/dist-esm/lib/editor/Editor.mjs +110 -44
  86. package/dist-esm/lib/editor/Editor.mjs.map +3 -3
  87. package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs.map +2 -2
  88. package/dist-esm/lib/editor/managers/TextManager.mjs +10 -0
  89. package/dist-esm/lib/editor/managers/TextManager.mjs.map +2 -2
  90. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +1 -1
  91. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
  92. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +0 -3
  93. package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
  94. package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs.map +2 -2
  95. package/dist-esm/lib/exports/getSvgJsx.mjs +12 -3
  96. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  97. package/dist-esm/lib/hooks/useDocumentEvents.mjs +3 -2
  98. package/dist-esm/lib/hooks/useDocumentEvents.mjs.map +2 -2
  99. package/dist-esm/lib/hooks/useEditorComponents.mjs +16 -18
  100. package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
  101. package/dist-esm/lib/license/LicenseManager.mjs +8 -1
  102. package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
  103. package/dist-esm/lib/options.mjs.map +2 -2
  104. package/dist-esm/lib/primitives/Box.mjs +16 -0
  105. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  106. package/dist-esm/lib/primitives/Mat.mjs +1 -1
  107. package/dist-esm/lib/primitives/Mat.mjs.map +2 -2
  108. package/dist-esm/lib/primitives/Vec.mjs +20 -0
  109. package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
  110. package/dist-esm/lib/primitives/geometry/Arc2d.mjs +2 -2
  111. package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
  112. package/dist-esm/lib/primitives/geometry/Circle2d.mjs +1 -1
  113. package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
  114. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs +1 -1
  115. package/dist-esm/lib/primitives/geometry/CubicBezier2d.mjs.map +2 -2
  116. package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs.map +2 -2
  117. package/dist-esm/lib/primitives/geometry/Edge2d.mjs +1 -1
  118. package/dist-esm/lib/primitives/geometry/Edge2d.mjs.map +2 -2
  119. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
  120. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +92 -21
  121. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  122. package/dist-esm/lib/primitives/geometry/Group2d.mjs +55 -2
  123. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  124. package/dist-esm/lib/primitives/geometry/Point2d.mjs.map +2 -2
  125. package/dist-esm/lib/primitives/geometry/Polyline2d.mjs.map +2 -2
  126. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +2 -2
  127. package/dist-esm/lib/utils/areShapesContentEqual.mjs +5 -0
  128. package/dist-esm/lib/utils/areShapesContentEqual.mjs.map +7 -0
  129. package/dist-esm/lib/utils/debug-flags.mjs +5 -2
  130. package/dist-esm/lib/utils/debug-flags.mjs.map +2 -2
  131. package/dist-esm/lib/utils/dom.mjs +3 -3
  132. package/dist-esm/lib/utils/dom.mjs.map +2 -2
  133. package/dist-esm/lib/utils/nearestMultiple.mjs +14 -0
  134. package/dist-esm/lib/utils/nearestMultiple.mjs.map +7 -0
  135. package/dist-esm/lib/utils/rotation.mjs +5 -5
  136. package/dist-esm/lib/utils/rotation.mjs.map +2 -2
  137. package/dist-esm/version.mjs +3 -3
  138. package/dist-esm/version.mjs.map +1 -1
  139. package/editor.css +47 -4
  140. package/package.json +7 -7
  141. package/src/index.ts +16 -31
  142. package/src/lib/TldrawEditor.tsx +6 -1
  143. package/src/lib/components/Shape.tsx +14 -10
  144. package/src/lib/components/default-components/DefaultCanvas.tsx +43 -8
  145. package/src/lib/components/default-components/DefaultErrorFallback.tsx +25 -14
  146. package/src/lib/components/default-components/DefaultShapeIndicator.tsx +17 -8
  147. package/src/lib/components/default-components/DefaultSpinner.tsx +1 -1
  148. package/src/lib/editor/Editor.test.ts +1 -1
  149. package/src/lib/editor/Editor.ts +118 -43
  150. package/src/lib/editor/managers/SnapManager/HandleSnaps.ts +0 -1
  151. package/src/lib/editor/managers/TextManager.ts +12 -0
  152. package/src/lib/editor/shapes/ShapeUtil.ts +23 -3
  153. package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +0 -4
  154. package/src/lib/editor/shapes/shared/getPerfectDashProps.ts +9 -9
  155. package/src/lib/exports/getSvgJsx.tsx +16 -7
  156. package/src/lib/hooks/useDocumentEvents.ts +7 -2
  157. package/src/lib/hooks/useEditorComponents.tsx +33 -32
  158. package/src/lib/license/LicenseManager.test.ts +40 -0
  159. package/src/lib/license/LicenseManager.ts +13 -1
  160. package/src/lib/options.ts +4 -0
  161. package/src/lib/primitives/Box.ts +20 -0
  162. package/src/lib/primitives/Mat.ts +5 -4
  163. package/src/lib/primitives/Vec.ts +23 -0
  164. package/src/lib/primitives/geometry/Arc2d.ts +5 -5
  165. package/src/lib/primitives/geometry/Circle2d.ts +4 -4
  166. package/src/lib/primitives/geometry/CubicBezier2d.ts +4 -4
  167. package/src/lib/primitives/geometry/CubicSpline2d.ts +3 -3
  168. package/src/lib/primitives/geometry/Edge2d.ts +3 -3
  169. package/src/lib/primitives/geometry/Ellipse2d.ts +3 -3
  170. package/src/lib/primitives/geometry/Geometry2d.test.ts +42 -0
  171. package/src/lib/primitives/geometry/Geometry2d.ts +123 -35
  172. package/src/lib/primitives/geometry/Group2d.ts +70 -7
  173. package/src/lib/primitives/geometry/Point2d.ts +2 -2
  174. package/src/lib/primitives/geometry/Polyline2d.ts +3 -3
  175. package/src/lib/primitives/geometry/Stadium2d.ts +3 -3
  176. package/src/lib/test/currentToolIdMask.test.ts +1 -1
  177. package/src/lib/test/user.test.ts +1 -1
  178. package/src/lib/utils/areShapesContentEqual.ts +4 -0
  179. package/src/lib/utils/debug-flags.ts +7 -2
  180. package/src/lib/utils/dom.ts +4 -4
  181. package/src/lib/utils/nearestMultiple.ts +13 -0
  182. package/src/lib/utils/rotation.ts +8 -6
  183. package/src/lib/utils/sync/LocalIndexedDb.test.ts +1 -1
  184. package/src/lib/utils/sync/TLLocalSyncClient.test.ts +1 -1
  185. 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) {
@@ -1347,8 +1348,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1347
1348
  return this.getCurrentPageState().selectedShapeIds;
1348
1349
  }
1349
1350
  getSelectedShapes() {
1350
- const { selectedShapeIds } = this.getCurrentPageState();
1351
- return (0, import_utils.compact)(selectedShapeIds.map((id) => this.store.get(id)));
1351
+ return (0, import_utils.compact)(this.getSelectedShapeIds().map((id) => this.store.get(id)));
1352
1352
  }
1353
1353
  /**
1354
1354
  * Select one or more shapes.
@@ -1441,9 +1441,23 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1441
1441
  this.setSelectedShapes(this._getUnlockedShapeIds(ids));
1442
1442
  return this;
1443
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
+ */
1444
1454
  selectAdjacentShape(direction) {
1445
- const readingOrderShapes = this.getCurrentPageShapesInReadingOrder();
1446
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();
1447
1461
  const currentShapeId = selectedShapeIds.length === 1 ? selectedShapeIds[0] : readingOrderShapes.find((shape2) => selectedShapeIds.includes(shape2.id))?.id;
1448
1462
  let adjacentShapeId;
1449
1463
  if (direction === "next" || direction === "prev") {
@@ -1457,18 +1471,15 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1457
1471
  }
1458
1472
  const shape = this.getShape(adjacentShapeId);
1459
1473
  if (!shape) return;
1460
- this.setSelectedShapes([shape.id]);
1461
- this.zoomToSelectionIfOffscreen(256, {
1462
- animation: {
1463
- duration: this.options.animationMediumMs
1464
- },
1465
- inset: 0
1466
- });
1474
+ this._selectShapesAndZoom([shape.id]);
1467
1475
  }
1468
1476
  getCurrentPageShapesInReadingOrder() {
1477
+ const shapes = this.getCurrentPageShapes().filter((shape) => (0, import_tlschema.isPageId)(shape.parentId));
1478
+ return this._getShapesInReadingOrder(shapes);
1479
+ }
1480
+ _getShapesInReadingOrder(shapes) {
1469
1481
  const SHALLOW_ANGLE = 20;
1470
1482
  const ROW_THRESHOLD = 100;
1471
- const shapes = this.getCurrentPageShapes();
1472
1483
  const tabbableShapes = shapes.filter((shape) => this.getShapeUtil(shape).canTabTo(shape));
1473
1484
  if (tabbableShapes.length <= 1) return tabbableShapes;
1474
1485
  const shapesWithCenters = tabbableShapes.map((shape) => ({
@@ -1566,6 +1577,31 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1566
1577
  });
1567
1578
  return lowestScoringShape.shape.id;
1568
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
+ }
1569
1605
  /**
1570
1606
  * Clear the selection.
1571
1607
  *
@@ -1738,13 +1774,21 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1738
1774
  setEditingShape(shape) {
1739
1775
  const id = typeof shape === "string" ? shape : shape?.id ?? null;
1740
1776
  this.setRichTextEditor(null);
1741
- if (id !== this.getEditingShapeId()) {
1777
+ const prevEditingShapeId = this.getEditingShapeId();
1778
+ if (id !== prevEditingShapeId) {
1742
1779
  if (id) {
1743
1780
  const shape2 = this.getShape(id);
1744
1781
  if (shape2 && this.getShapeUtil(shape2).canEdit(shape2)) {
1745
1782
  this.run(
1746
1783
  () => {
1747
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);
1748
1792
  },
1749
1793
  { history: "ignore" }
1750
1794
  );
@@ -1755,6 +1799,12 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1755
1799
  () => {
1756
1800
  this._updateCurrentPageState({ editingShapeId: null });
1757
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
+ }
1758
1808
  },
1759
1809
  { history: "ignore" }
1760
1810
  );
@@ -1950,12 +2000,22 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
1950
2000
  }
1951
2001
  return baseCamera;
1952
2002
  }
2003
+ _getFollowingPresence(targetUserId) {
2004
+ const visited = [this.user.getId()];
2005
+ const collaborators = this.getCollaborators();
2006
+ let leaderPresence = null;
2007
+ while (targetUserId && !visited.includes(targetUserId)) {
2008
+ leaderPresence = collaborators.find((c) => c.userId === targetUserId) ?? null;
2009
+ targetUserId = leaderPresence?.followingUserId ?? null;
2010
+ if (leaderPresence) {
2011
+ visited.push(leaderPresence.userId);
2012
+ }
2013
+ }
2014
+ return leaderPresence;
2015
+ }
1953
2016
  getViewportPageBoundsForFollowing() {
1954
- const followingUserId = this.getInstanceState().followingUserId;
1955
- if (!followingUserId) return null;
1956
- const leaderPresence = this.getCollaborators().find((c) => c.userId === followingUserId);
1957
- if (!leaderPresence) return null;
1958
- if (!leaderPresence.camera || !leaderPresence.screenBounds) return null;
2017
+ const leaderPresence = this._getFollowingPresence(this.getInstanceState().followingUserId);
2018
+ if (!leaderPresence?.camera || !leaderPresence?.screenBounds) return null;
1959
2019
  const { w: lw, h: lh } = leaderPresence.screenBounds;
1960
2020
  const { x: lx, y: ly, z: lz } = leaderPresence.camera;
1961
2021
  const theirViewport = new import_Box.Box(-lx, -ly, lw / lz, lh / lz);
@@ -2862,34 +2922,30 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
2862
2922
  */
2863
2923
  startFollowingUser(userId) {
2864
2924
  this.stopFollowingUser();
2865
- const leaderPresences = this._getCollaboratorsQuery().get().filter((p) => p.userId === userId);
2866
- if (!leaderPresences.length) {
2867
- console.warn("User not found");
2868
- return this;
2869
- }
2870
2925
  const thisUserId = this.user.getId();
2871
2926
  if (!thisUserId) {
2872
2927
  console.warn("You should set the userId for the current instance before following a user");
2873
2928
  }
2874
- if (leaderPresences.some((p) => p.followingUserId === thisUserId)) {
2929
+ const leaderPresence = this._getFollowingPresence(userId);
2930
+ if (!leaderPresence) {
2875
2931
  return this;
2876
2932
  }
2877
2933
  const latestLeaderPresence = (0, import_state.computed)("latestLeaderPresence", () => {
2878
- return this.getCollaborators().find((p) => p.userId === userId);
2934
+ return this._getFollowingPresence(userId);
2879
2935
  });
2880
2936
  (0, import_state.transact)(() => {
2881
2937
  this.updateInstanceState({ followingUserId: userId }, { history: "ignore" });
2882
2938
  const dispose = (0, import_state.react)("update current page", () => {
2883
- const leaderPresence = latestLeaderPresence.get();
2884
- if (!leaderPresence) {
2939
+ const leaderPresence2 = latestLeaderPresence.get();
2940
+ if (!leaderPresence2) {
2885
2941
  this.stopFollowingUser();
2886
2942
  return;
2887
2943
  }
2888
- if (leaderPresence.currentPageId !== this.getCurrentPageId() && this.getPage(leaderPresence.currentPageId)) {
2944
+ if (leaderPresence2.currentPageId !== this.getCurrentPageId() && this.getPage(leaderPresence2.currentPageId)) {
2889
2945
  this.run(
2890
2946
  () => {
2891
2947
  this.store.put([
2892
- { ...this.getInstanceState(), currentPageId: leaderPresence.currentPageId }
2948
+ { ...this.getInstanceState(), currentPageId: leaderPresence2.currentPageId }
2893
2949
  ]);
2894
2950
  this._isLockedOnFollowingUser.set(true);
2895
2951
  },
@@ -2904,8 +2960,8 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
2904
2960
  this.off("stop-following", cancel);
2905
2961
  };
2906
2962
  const moveTowardsUser = () => {
2907
- const leaderPresence = latestLeaderPresence.get();
2908
- if (!leaderPresence) {
2963
+ const leaderPresence2 = latestLeaderPresence.get();
2964
+ if (!leaderPresence2) {
2909
2965
  this.stopFollowingUser();
2910
2966
  return;
2911
2967
  }
@@ -3434,7 +3490,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3434
3490
  this.fonts.trackFontsForShape(shape2);
3435
3491
  return this.getShapeUtil(shape2).getGeometry(shape2, opts);
3436
3492
  },
3437
- { areRecordsEqual: (a, b) => a.props === b.props }
3493
+ { areRecordsEqual: import_areShapesContentEqual.areShapesContentEqual }
3438
3494
  );
3439
3495
  }
3440
3496
  return this._shapeGeometryCaches[context].get(
@@ -3477,9 +3533,15 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
3477
3533
  );
3478
3534
  }
3479
3535
  _getShapeHandlesCache() {
3480
- return this.store.createComputedCache("handles", (shape) => {
3481
- return this.getShapeUtil(shape).getHandles?.(shape);
3482
- });
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
+ );
3483
3545
  }
3484
3546
  /**
3485
3547
  * Get the handles (if any) for a shape.
@@ -4363,9 +4425,15 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
4363
4425
  }
4364
4426
  _getBindingsIndexCache() {
4365
4427
  const index = (0, import_bindingsIndex.bindingsIndex)(this);
4366
- return this.store.createComputedCache("bindingsIndex", (shape) => {
4367
- return index.get().get(shape.id);
4368
- });
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
+ );
4369
4437
  }
4370
4438
  /**
4371
4439
  * Get a binding from the store by its ID if it exists.
@@ -7440,7 +7508,7 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7440
7508
  const { x: cx, y: cy, z: cz } = (0, import_state.unsafe__withoutCapture)(() => this.getCamera());
7441
7509
  const { x: dx, y: dy, z: dz = 0 } = info.delta;
7442
7510
  let behavior = wheelBehavior;
7443
- if (inputs.ctrlKey) behavior = wheelBehavior === "pan" ? "zoom" : "pan";
7511
+ if (info.ctrlKey) behavior = wheelBehavior === "pan" ? "zoom" : "pan";
7444
7512
  switch (behavior) {
7445
7513
  case "zoom": {
7446
7514
  const { x, y } = this.inputs.currentScreenPoint;
@@ -7521,12 +7589,10 @@ class Editor extends (_a = import_eventemitter3.default, _getIsShapeHiddenCache_
7521
7589
  const { x: cx, y: cy, z: cz } = (0, import_state.unsafe__withoutCapture)(() => this.getCamera());
7522
7590
  if (this.inputs.isPanning && this.inputs.isPointing) {
7523
7591
  const { currentScreenPoint, previousScreenPoint } = this.inputs;
7524
- const { panSpeed } = cameraOptions;
7525
7592
  const offset = import_Vec.Vec.Sub(currentScreenPoint, previousScreenPoint);
7526
- this.setCamera(
7527
- new import_Vec.Vec(cx + offset.x * panSpeed / cz, cy + offset.y * panSpeed / cz, cz),
7528
- { immediate: true }
7529
- );
7593
+ this.setCamera(new import_Vec.Vec(cx + offset.x / cz, cy + offset.y / cz, cz), {
7594
+ immediate: true
7595
+ });
7530
7596
  this.maybeTrackPerformance("Panning");
7531
7597
  return;
7532
7598
  }