@tldraw/editor 4.6.0-next.5a871ec02ff3 → 4.6.0-next.d15997ff5a4b

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 (189) hide show
  1. package/dist-cjs/index.d.ts +124 -6
  2. package/dist-cjs/index.js +1 -1
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/TldrawEditor.js.map +2 -2
  5. package/dist-cjs/lib/components/default-components/DefaultCanvas.js +1 -1
  6. package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
  7. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +1 -1
  8. package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +2 -2
  9. package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
  10. package/dist-cjs/lib/config/createTLStore.js +1 -1
  11. package/dist-cjs/lib/config/createTLStore.js.map +2 -2
  12. package/dist-cjs/lib/config/createTLUser.js.map +1 -1
  13. package/dist-cjs/lib/config/defaultShapes.js.map +2 -2
  14. package/dist-cjs/lib/editor/Editor.js +463 -354
  15. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  16. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +25 -64
  17. package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
  18. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +1 -1
  19. package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
  20. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +14 -53
  21. package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +1 -1
  22. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +71 -112
  23. package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
  24. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +21 -56
  25. package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +2 -2
  26. package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js +11 -52
  27. package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js.map +2 -2
  28. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +19 -56
  29. package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +1 -1
  30. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +4 -4
  31. package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +2 -2
  32. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +102 -30
  33. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  34. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +16 -55
  35. package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +1 -1
  36. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +57 -68
  37. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  38. package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +1 -1
  39. package/dist-cjs/lib/exports/ExportDelay.js +12 -53
  40. package/dist-cjs/lib/exports/ExportDelay.js.map +1 -1
  41. package/dist-cjs/lib/exports/FontEmbedder.js +14 -57
  42. package/dist-cjs/lib/exports/FontEmbedder.js.map +1 -1
  43. package/dist-cjs/lib/exports/StyleEmbedder.js +1 -1
  44. package/dist-cjs/lib/exports/StyleEmbedder.js.map +2 -2
  45. package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
  46. package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
  47. package/dist-cjs/lib/hooks/useLocalStore.js.map +2 -2
  48. package/dist-cjs/lib/options.js +3 -0
  49. package/dist-cjs/lib/options.js.map +2 -2
  50. package/dist-cjs/lib/primitives/Box.js +26 -26
  51. package/dist-cjs/lib/primitives/Box.js.map +2 -2
  52. package/dist-cjs/lib/primitives/Vec.js +1 -1
  53. package/dist-cjs/lib/primitives/Vec.js.map +1 -1
  54. package/dist-cjs/lib/primitives/geometry/Arc2d.js +2 -2
  55. package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
  56. package/dist-cjs/lib/primitives/geometry/Circle2d.js +2 -2
  57. package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
  58. package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js +1 -1
  59. package/dist-cjs/lib/primitives/geometry/CubicSpline2d.js.map +1 -1
  60. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +3 -3
  61. package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
  62. package/dist-cjs/lib/primitives/geometry/Geometry2d.js +10 -9
  63. package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
  64. package/dist-cjs/lib/primitives/geometry/Polyline2d.js +2 -2
  65. package/dist-cjs/lib/primitives/geometry/Polyline2d.js.map +2 -2
  66. package/dist-cjs/lib/primitives/geometry/Stadium2d.js +1 -1
  67. package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +2 -2
  68. package/dist-cjs/lib/utils/SharedStylesMap.js +1 -1
  69. package/dist-cjs/lib/utils/SharedStylesMap.js.map +1 -1
  70. package/dist-cjs/lib/utils/getSvgPathFromPoints.js.map +2 -2
  71. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +3 -2
  72. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
  73. package/dist-cjs/version.js +3 -3
  74. package/dist-cjs/version.js.map +1 -1
  75. package/dist-esm/index.d.mts +124 -6
  76. package/dist-esm/index.mjs +4 -2
  77. package/dist-esm/index.mjs.map +2 -2
  78. package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
  79. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +1 -1
  80. package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
  81. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +1 -1
  82. package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +2 -2
  83. package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
  84. package/dist-esm/lib/config/createTLStore.mjs +1 -1
  85. package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
  86. package/dist-esm/lib/config/createTLUser.mjs.map +1 -1
  87. package/dist-esm/lib/config/defaultShapes.mjs.map +2 -2
  88. package/dist-esm/lib/editor/Editor.mjs +465 -357
  89. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  90. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +25 -64
  91. package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
  92. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +1 -1
  93. package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
  94. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +14 -53
  95. package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +1 -1
  96. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +71 -112
  97. package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
  98. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +21 -56
  99. package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +2 -2
  100. package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs +11 -52
  101. package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs.map +2 -2
  102. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +19 -56
  103. package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +1 -1
  104. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +4 -4
  105. package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +2 -2
  106. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +102 -30
  107. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  108. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +16 -55
  109. package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +1 -1
  110. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +57 -68
  111. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  112. package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +1 -1
  113. package/dist-esm/lib/exports/ExportDelay.mjs +12 -53
  114. package/dist-esm/lib/exports/ExportDelay.mjs.map +1 -1
  115. package/dist-esm/lib/exports/FontEmbedder.mjs +14 -57
  116. package/dist-esm/lib/exports/FontEmbedder.mjs.map +1 -1
  117. package/dist-esm/lib/exports/StyleEmbedder.mjs +1 -1
  118. package/dist-esm/lib/exports/StyleEmbedder.mjs.map +2 -2
  119. package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
  120. package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
  121. package/dist-esm/lib/hooks/useLocalStore.mjs.map +2 -2
  122. package/dist-esm/lib/options.mjs +3 -0
  123. package/dist-esm/lib/options.mjs.map +2 -2
  124. package/dist-esm/lib/primitives/Box.mjs +26 -26
  125. package/dist-esm/lib/primitives/Box.mjs.map +2 -2
  126. package/dist-esm/lib/primitives/Vec.mjs +1 -1
  127. package/dist-esm/lib/primitives/Vec.mjs.map +1 -1
  128. package/dist-esm/lib/primitives/geometry/Arc2d.mjs +2 -2
  129. package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
  130. package/dist-esm/lib/primitives/geometry/Circle2d.mjs +2 -2
  131. package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
  132. package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs +1 -1
  133. package/dist-esm/lib/primitives/geometry/CubicSpline2d.mjs.map +1 -1
  134. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +3 -3
  135. package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
  136. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +10 -9
  137. package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
  138. package/dist-esm/lib/primitives/geometry/Polyline2d.mjs +2 -2
  139. package/dist-esm/lib/primitives/geometry/Polyline2d.mjs.map +2 -2
  140. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +1 -1
  141. package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +2 -2
  142. package/dist-esm/lib/utils/SharedStylesMap.mjs +1 -1
  143. package/dist-esm/lib/utils/SharedStylesMap.mjs.map +1 -1
  144. package/dist-esm/lib/utils/getSvgPathFromPoints.mjs.map +2 -2
  145. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +3 -2
  146. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
  147. package/dist-esm/version.mjs +3 -3
  148. package/dist-esm/version.mjs.map +1 -1
  149. package/package.json +8 -8
  150. package/src/index.ts +15 -7
  151. package/src/lib/TldrawEditor.tsx +1 -1
  152. package/src/lib/components/default-components/DefaultCanvas.tsx +1 -1
  153. package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +1 -1
  154. package/src/lib/components/default-components/DefaultErrorFallback.tsx +1 -0
  155. package/src/lib/config/TLEditorSnapshot.test.ts +1 -1
  156. package/src/lib/config/createTLStore.ts +1 -1
  157. package/src/lib/config/createTLUser.ts +3 -3
  158. package/src/lib/config/defaultShapes.ts +1 -1
  159. package/src/lib/editor/Editor.ts +9 -8
  160. package/src/lib/editor/managers/ClickManager/ClickManager.ts +1 -1
  161. package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +1 -1
  162. package/src/lib/editor/managers/InputsManager/InputsManager.ts +30 -30
  163. package/src/lib/editor/managers/SnapManager/BoundsSnaps.ts +1 -1
  164. package/src/lib/editor/managers/SnapManager/HandleSnaps.ts +1 -1
  165. package/src/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.ts +5 -5
  166. package/src/lib/editor/managers/TextManager/TextManager.test.ts +18 -4
  167. package/src/lib/editor/managers/TextManager/TextManager.ts +140 -34
  168. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +1 -1
  169. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +1 -1
  170. package/src/lib/editor/shapes/ShapeUtil.ts +2 -2
  171. package/src/lib/exports/StyleEmbedder.ts +1 -1
  172. package/src/lib/exports/getSvgJsx.tsx +1 -1
  173. package/src/lib/hooks/useEditorComponents.tsx +1 -1
  174. package/src/lib/hooks/useLocalStore.ts +1 -1
  175. package/src/lib/options.ts +108 -0
  176. package/src/lib/primitives/Box.ts +26 -26
  177. package/src/lib/primitives/Vec.ts +1 -1
  178. package/src/lib/primitives/geometry/Arc2d.ts +2 -2
  179. package/src/lib/primitives/geometry/Circle2d.ts +2 -2
  180. package/src/lib/primitives/geometry/CubicSpline2d.ts +1 -1
  181. package/src/lib/primitives/geometry/Ellipse2d.ts +3 -3
  182. package/src/lib/primitives/geometry/Geometry2d.ts +10 -9
  183. package/src/lib/primitives/geometry/Polyline2d.ts +2 -2
  184. package/src/lib/primitives/geometry/Stadium2d.ts +1 -1
  185. package/src/lib/utils/SharedStylesMap.ts +1 -1
  186. package/src/lib/utils/getSvgPathFromPoints.ts +1 -1
  187. package/src/lib/utils/sync/TLLocalSyncClient.test.ts +1 -1
  188. package/src/lib/utils/sync/TLLocalSyncClient.ts +2 -1
  189. package/src/version.ts +3 -3
@@ -1,52 +1,13 @@
1
- var __create = Object.create;
2
1
  var __defProp = Object.defineProperty;
3
2
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
5
- var __typeError = (msg) => {
6
- throw TypeError(msg);
7
- };
8
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
10
- var __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
11
- var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
12
- var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
13
- var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
14
- var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
15
- var __runInitializers = (array, flags, self, value) => {
16
- for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
17
- return value;
18
- };
19
- var __decorateElement = (array, flags, name, decorators, target, extra) => {
20
- var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
21
- var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
22
- var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
23
- var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : { get [name]() {
24
- return __privateGet(this, extra);
25
- }, set [name](x) {
26
- return __privateSet(this, extra, x);
27
- } }, name));
28
- k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
29
- for (var i = decorators.length - 1; i >= 0; i--) {
30
- ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
31
- if (k) {
32
- ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name in x };
33
- if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
34
- if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
35
- }
36
- it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
37
- if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
38
- else if (typeof it !== "object" || it === null) __typeError("Object expected");
39
- else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
40
- }
41
- return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result) __defProp(target, key, result);
9
+ return result;
42
10
  };
43
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
44
- var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
45
- var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
46
- var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
47
- var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
48
- var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
49
- var _getVisibleGaps_dec, _getSnappableGapNodes_dec, _getSnappablePoints_dec, _getSnapPointsCache_dec, _init;
50
11
  import { computed } from "@tldraw/state";
51
12
  import { assertExists, dedupe, uniqueId } from "@tldraw/utils";
52
13
  import {
@@ -56,8 +17,8 @@ import {
56
17
  isSelectionCorner
57
18
  } from "../../../primitives/Box.mjs";
58
19
  import { Mat } from "../../../primitives/Mat.mjs";
59
- import { Vec } from "../../../primitives/Vec.mjs";
60
20
  import { rangeIntersection, rangesOverlap } from "../../../primitives/utils.mjs";
21
+ import { Vec } from "../../../primitives/Vec.mjs";
61
22
  const round = (x) => {
62
23
  const decimalPlacesTolerance = 8;
63
24
  return Math.round(x * 10 ** decimalPlacesTolerance) / 10 ** decimalPlacesTolerance;
@@ -113,14 +74,12 @@ function dedupeGapSnaps(snaps) {
113
74
  }
114
75
  }
115
76
  }
116
- _getSnapPointsCache_dec = [computed], _getSnappablePoints_dec = [computed], _getSnappableGapNodes_dec = [computed], _getVisibleGaps_dec = [computed];
117
77
  class BoundsSnaps {
118
78
  constructor(manager) {
119
79
  this.manager = manager;
120
- __runInitializers(_init, 5, this);
121
- __publicField(this, "editor");
122
80
  this.editor = manager.editor;
123
81
  }
82
+ editor;
124
83
  getSnapPointsCache() {
125
84
  const { editor } = this;
126
85
  return editor.store.createComputedCache("snapPoints", (shape) => {
@@ -827,12 +786,18 @@ class BoundsSnaps {
827
786
  return result;
828
787
  }
829
788
  }
830
- _init = __decoratorStart(null);
831
- __decorateElement(_init, 1, "getSnapPointsCache", _getSnapPointsCache_dec, BoundsSnaps);
832
- __decorateElement(_init, 1, "getSnappablePoints", _getSnappablePoints_dec, BoundsSnaps);
833
- __decorateElement(_init, 1, "getSnappableGapNodes", _getSnappableGapNodes_dec, BoundsSnaps);
834
- __decorateElement(_init, 1, "getVisibleGaps", _getVisibleGaps_dec, BoundsSnaps);
835
- __decoratorMetadata(_init, BoundsSnaps);
789
+ __decorateClass([
790
+ computed
791
+ ], BoundsSnaps.prototype, "getSnapPointsCache", 1);
792
+ __decorateClass([
793
+ computed
794
+ ], BoundsSnaps.prototype, "getSnappablePoints", 1);
795
+ __decorateClass([
796
+ computed
797
+ ], BoundsSnaps.prototype, "getSnappableGapNodes", 1);
798
+ __decorateClass([
799
+ computed
800
+ ], BoundsSnaps.prototype, "getVisibleGaps", 1);
836
801
  function getResizeSnapPointsForHandle(handle, selectionPageBounds) {
837
802
  const { minX, maxX, minY, maxY } = selectionPageBounds;
838
803
  const result = [];
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/editor/managers/SnapManager/BoundsSnaps.ts"],
4
- "sourcesContent": ["import { computed } from '@tldraw/state'\nimport { TLShape, TLShapeId, VecModel } from '@tldraw/tlschema'\nimport { assertExists, dedupe, uniqueId } from '@tldraw/utils'\nimport {\n\tBox,\n\tSelectionCorner,\n\tSelectionEdge,\n\tflipSelectionHandleX,\n\tflipSelectionHandleY,\n\tisSelectionCorner,\n} from '../../../primitives/Box'\nimport { Mat } from '../../../primitives/Mat'\nimport { Vec } from '../../../primitives/Vec'\nimport { rangeIntersection, rangesOverlap } from '../../../primitives/utils'\nimport type { Editor } from '../../Editor'\nimport type {\n\tGapsSnapIndicator,\n\tPointsSnapIndicator,\n\tSnapData,\n\tSnapIndicator,\n\tSnapManager,\n} from './SnapManager'\n\n/**\n * When moving or resizing shapes, the bounds of the shape can snap to key geometry on other nearby\n * shapes. Customize how a shape snaps to others with {@link ShapeUtil.getBoundsSnapGeometry}.\n *\n * @public\n */\nexport interface BoundsSnapGeometry {\n\t/**\n\t * Points that this shape will snap to. By default, this will be the corners and center of the\n\t * shapes bounding box. To disable snapping to a specific point, use an empty array.\n\t */\n\tpoints?: VecModel[]\n}\n\n/** @public */\nexport interface BoundsSnapPoint {\n\tid: string\n\tx: number\n\ty: number\n\thandle?: SelectionCorner\n}\n\ninterface SnapPair {\n\tthisPoint: BoundsSnapPoint\n\totherPoint: BoundsSnapPoint\n}\n\ninterface NearestPointsSnap {\n\t// selection snaps to a nearby snap point\n\ttype: 'points'\n\tpoints: SnapPair\n\tnudge: number\n}\n\ntype NearestSnap =\n\t| NearestPointsSnap\n\t| {\n\t\t\t// selection snaps to the center of a gap\n\t\t\ttype: 'gap_center'\n\t\t\tgap: Gap\n\t\t\tnudge: number\n\t }\n\t| {\n\t\t\t// selection snaps to create a new gap of equal size to another gap\n\t\t\t// on the opposite side of some shape\n\t\t\ttype: 'gap_duplicate'\n\t\t\tgap: Gap\n\t\t\tprotrusionDirection: 'left' | 'right' | 'top' | 'bottom'\n\t\t\tnudge: number\n\t }\n\ninterface GapNode {\n\tid: TLShapeId\n\tpageBounds: Box\n}\n\ninterface Gap {\n\t// e.g.\n\t// start\n\t// edge \u2502 breadth\n\t// \u2502 intersection\n\t// \u25BC [40,100] end\n\t// \u2502 \u2502 edge\n\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502 100,0 \u2502 \u2502\n\t// \u2502 \u2502 \u2502 \u25BC \u25BC\n\t// \u2502 \u2502 \u2502\n\t// \u2502 start \u2502 \u2502 \u2502 200,40 \u2502 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t// \u2502 node \u2502 \u2502 \u2502 \u2502 \u2502 \u2502\n\t// \u2502 \u2502 \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524 \u2502 end \u2502\n\t// \u2502 \u2502 \u2502 \u2502 \u2502 \u2502 node \u2502\n\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502 100,100 \u2502 \u2502 \u2502 \u2502\n\t// \u2502 \u2502 \u2502\n\t// 200,120 \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\t//\n\t// length 100\n\t// \u25C4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25BA\n\tstartNode: GapNode\n\tendNode: GapNode\n\tstartEdge: [Vec, Vec]\n\tendEdge: [Vec, Vec]\n\tlength: number\n\tbreadthIntersection: [number, number]\n}\n\nconst round = (x: number) => {\n\t// round numbers to avoid glitches for floating point rounding errors\n\tconst decimalPlacesTolerance = 8\n\treturn Math.round(x * 10 ** decimalPlacesTolerance) / 10 ** decimalPlacesTolerance\n}\n\nfunction findAdjacentGaps(\n\tgaps: Gap[],\n\tshapeId: TLShapeId,\n\tgapLength: number,\n\tdirection: 'forward' | 'backward',\n\tintersection: [number, number]\n): Gap[] {\n\t// TODO: take advantage of the fact that gaps is sorted by starting position?\n\tconst matches = gaps.filter(\n\t\t(gap) =>\n\t\t\t(direction === 'forward' ? gap.startNode.id === shapeId : gap.endNode.id === shapeId) &&\n\t\t\tround(gap.length) === round(gapLength) &&\n\t\t\trangeIntersection(\n\t\t\t\tgap.breadthIntersection[0],\n\t\t\t\tgap.breadthIntersection[1],\n\t\t\t\tintersection[0],\n\t\t\t\tintersection[1]\n\t\t\t)\n\t)\n\n\tif (matches.length === 0) return []\n\n\tconst nextNodes = new Set<TLShapeId>()\n\n\tmatches.forEach((match) => {\n\t\tconst node = direction === 'forward' ? match.endNode.id : match.startNode.id\n\t\tif (!nextNodes.has(node)) {\n\t\t\tnextNodes.add(node)\n\t\t\tconst foundGaps = findAdjacentGaps(\n\t\t\t\tgaps,\n\t\t\t\tnode,\n\t\t\t\tgapLength,\n\t\t\t\tdirection,\n\t\t\t\trangeIntersection(\n\t\t\t\t\tmatch.breadthIntersection[0],\n\t\t\t\t\tmatch.breadthIntersection[1],\n\t\t\t\t\tintersection[0],\n\t\t\t\t\tintersection[1]\n\t\t\t\t)!\n\t\t\t)\n\n\t\t\tmatches.push(...foundGaps)\n\t\t}\n\t})\n\n\treturn matches\n}\n\nfunction dedupeGapSnaps(snaps: Array<Extract<SnapIndicator, { type: 'gaps' }>>) {\n\t// sort by descending order of number of gaps\n\tsnaps.sort((a, b) => b.gaps.length - a.gaps.length)\n\t// pop off any that are included already\n\tfor (let i = snaps.length - 1; i > 0; i--) {\n\t\tconst snap = snaps[i]\n\t\tfor (let j = i - 1; j >= 0; j--) {\n\t\t\tconst otherSnap = snaps[j]\n\t\t\t// if every edge in this snap is included in the other snap somewhere, then it's redundant\n\t\t\tif (\n\t\t\t\totherSnap.direction === snap.direction &&\n\t\t\t\tsnap.gaps.every(\n\t\t\t\t\t(gap) =>\n\t\t\t\t\t\totherSnap.gaps.some(\n\t\t\t\t\t\t\t(otherGap) =>\n\t\t\t\t\t\t\t\tround(gap.startEdge[0].x) === round(otherGap.startEdge[0].x) &&\n\t\t\t\t\t\t\t\tround(gap.startEdge[0].y) === round(otherGap.startEdge[0].y) &&\n\t\t\t\t\t\t\t\tround(gap.startEdge[1].x) === round(otherGap.startEdge[1].x) &&\n\t\t\t\t\t\t\t\tround(gap.startEdge[1].y) === round(otherGap.startEdge[1].y)\n\t\t\t\t\t\t) &&\n\t\t\t\t\t\totherSnap.gaps.some(\n\t\t\t\t\t\t\t(otherGap) =>\n\t\t\t\t\t\t\t\tround(gap.endEdge[0].x) === round(otherGap.endEdge[0].x) &&\n\t\t\t\t\t\t\t\tround(gap.endEdge[0].y) === round(otherGap.endEdge[0].y) &&\n\t\t\t\t\t\t\t\tround(gap.endEdge[1].x) === round(otherGap.endEdge[1].x) &&\n\t\t\t\t\t\t\t\tround(gap.endEdge[1].y) === round(otherGap.endEdge[1].y)\n\t\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tsnaps.splice(i, 1)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** @public */\nexport class BoundsSnaps {\n\treadonly editor: Editor\n\tconstructor(readonly manager: SnapManager) {\n\t\tthis.editor = manager.editor\n\t}\n\n\t@computed private getSnapPointsCache() {\n\t\tconst { editor } = this\n\t\treturn editor.store.createComputedCache<BoundsSnapPoint[], TLShape>('snapPoints', (shape) => {\n\t\t\tconst pageTransform = editor.getShapePageTransform(shape.id)\n\t\t\tif (!pageTransform) return undefined\n\t\t\tconst boundsSnapGeometry = editor.getShapeUtil(shape).getBoundsSnapGeometry(shape)\n\t\t\tconst snapPoints =\n\t\t\t\tboundsSnapGeometry.points ?? editor.getShapeGeometry(shape).bounds.cornersAndCenter\n\n\t\t\tif (!pageTransform || !snapPoints) return undefined\n\t\t\treturn snapPoints.map((point, i) => {\n\t\t\t\tconst { x, y } = Mat.applyToPoint(pageTransform, point)\n\t\t\t\treturn { x, y, id: `${shape.id}:${i}` }\n\t\t\t})\n\t\t})\n\t}\n\n\tgetSnapPoints(shapeId: TLShapeId) {\n\t\treturn this.getSnapPointsCache().get(shapeId) ?? []\n\t}\n\n\t// Points which belong to snappable shapes\n\t@computed private getSnappablePoints() {\n\t\tconst snapPointsCache = this.getSnapPointsCache()\n\t\tconst snappableShapes = this.manager.getSnappableShapes()\n\t\tconst result: BoundsSnapPoint[] = []\n\n\t\tfor (const shapeId of snappableShapes) {\n\t\t\tconst snapPoints = snapPointsCache.get(shapeId)\n\t\t\tif (snapPoints) {\n\t\t\t\tresult.push(...snapPoints)\n\t\t\t}\n\t\t}\n\n\t\treturn result\n\t}\n\n\t@computed private getSnappableGapNodes(): Array<GapNode> {\n\t\treturn Array.from(this.manager.getSnappableShapes(), (shapeId) => ({\n\t\t\tid: shapeId,\n\t\t\tpageBounds: assertExists(this.editor.getShapePageBounds(shapeId)),\n\t\t}))\n\t}\n\n\t@computed private getVisibleGaps(): { horizontal: Gap[]; vertical: Gap[] } {\n\t\tconst horizontal: Gap[] = []\n\t\tconst vertical: Gap[] = []\n\n\t\tlet startNode: GapNode, endNode: GapNode\n\n\t\tconst sortedShapesOnCurrentPageHorizontal = this.getSnappableGapNodes().sort((a, b) => {\n\t\t\treturn a.pageBounds.minX - b.pageBounds.minX\n\t\t})\n\n\t\t// Collect horizontal gaps\n\t\tfor (let i = 0; i < sortedShapesOnCurrentPageHorizontal.length; i++) {\n\t\t\tstartNode = sortedShapesOnCurrentPageHorizontal[i]\n\t\t\tfor (let j = i + 1; j < sortedShapesOnCurrentPageHorizontal.length; j++) {\n\t\t\t\tendNode = sortedShapesOnCurrentPageHorizontal[j]\n\n\t\t\t\tif (\n\t\t\t\t\t// is there space between the boxes\n\t\t\t\t\tstartNode.pageBounds.maxX < endNode.pageBounds.minX &&\n\t\t\t\t\t// and they overlap in the y axis\n\t\t\t\t\trangesOverlap(\n\t\t\t\t\t\tstartNode.pageBounds.minY,\n\t\t\t\t\t\tstartNode.pageBounds.maxY,\n\t\t\t\t\t\tendNode.pageBounds.minY,\n\t\t\t\t\t\tendNode.pageBounds.maxY\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\thorizontal.push({\n\t\t\t\t\t\tstartNode,\n\t\t\t\t\t\tendNode,\n\t\t\t\t\t\tstartEdge: [\n\t\t\t\t\t\t\tnew Vec(startNode.pageBounds.maxX, startNode.pageBounds.minY),\n\t\t\t\t\t\t\tnew Vec(startNode.pageBounds.maxX, startNode.pageBounds.maxY),\n\t\t\t\t\t\t],\n\t\t\t\t\t\tendEdge: [\n\t\t\t\t\t\t\tnew Vec(endNode.pageBounds.minX, endNode.pageBounds.minY),\n\t\t\t\t\t\t\tnew Vec(endNode.pageBounds.minX, endNode.pageBounds.maxY),\n\t\t\t\t\t\t],\n\t\t\t\t\t\tlength: endNode.pageBounds.minX - startNode.pageBounds.maxX,\n\t\t\t\t\t\tbreadthIntersection: rangeIntersection(\n\t\t\t\t\t\t\tstartNode.pageBounds.minY,\n\t\t\t\t\t\t\tstartNode.pageBounds.maxY,\n\t\t\t\t\t\t\tendNode.pageBounds.minY,\n\t\t\t\t\t\t\tendNode.pageBounds.maxY\n\t\t\t\t\t\t)!,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Collect vertical gaps\n\t\tconst sortedShapesOnCurrentPageVertical = sortedShapesOnCurrentPageHorizontal.sort((a, b) => {\n\t\t\treturn a.pageBounds.minY - b.pageBounds.minY\n\t\t})\n\n\t\tfor (let i = 0; i < sortedShapesOnCurrentPageVertical.length; i++) {\n\t\t\tstartNode = sortedShapesOnCurrentPageVertical[i]\n\t\t\tfor (let j = i + 1; j < sortedShapesOnCurrentPageVertical.length; j++) {\n\t\t\t\tendNode = sortedShapesOnCurrentPageVertical[j]\n\n\t\t\t\tif (\n\t\t\t\t\t// is there space between the boxes\n\t\t\t\t\tstartNode.pageBounds.maxY < endNode.pageBounds.minY &&\n\t\t\t\t\t// do they overlap in the x axis\n\t\t\t\t\trangesOverlap(\n\t\t\t\t\t\tstartNode.pageBounds.minX,\n\t\t\t\t\t\tstartNode.pageBounds.maxX,\n\t\t\t\t\t\tendNode.pageBounds.minX,\n\t\t\t\t\t\tendNode.pageBounds.maxX\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tvertical.push({\n\t\t\t\t\t\tstartNode,\n\t\t\t\t\t\tendNode,\n\t\t\t\t\t\tstartEdge: [\n\t\t\t\t\t\t\tnew Vec(startNode.pageBounds.minX, startNode.pageBounds.maxY),\n\t\t\t\t\t\t\tnew Vec(startNode.pageBounds.maxX, startNode.pageBounds.maxY),\n\t\t\t\t\t\t],\n\t\t\t\t\t\tendEdge: [\n\t\t\t\t\t\t\tnew Vec(endNode.pageBounds.minX, endNode.pageBounds.minY),\n\t\t\t\t\t\t\tnew Vec(endNode.pageBounds.maxX, endNode.pageBounds.minY),\n\t\t\t\t\t\t],\n\t\t\t\t\t\tlength: endNode.pageBounds.minY - startNode.pageBounds.maxY,\n\t\t\t\t\t\tbreadthIntersection: rangeIntersection(\n\t\t\t\t\t\t\tstartNode.pageBounds.minX,\n\t\t\t\t\t\t\tstartNode.pageBounds.maxX,\n\t\t\t\t\t\t\tendNode.pageBounds.minX,\n\t\t\t\t\t\t\tendNode.pageBounds.maxX\n\t\t\t\t\t\t)!,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { horizontal, vertical }\n\t}\n\n\tsnapTranslateShapes({\n\t\tlockedAxis,\n\t\tinitialSelectionPageBounds,\n\t\tinitialSelectionSnapPoints,\n\t\tdragDelta,\n\t}: {\n\t\tlockedAxis: 'x' | 'y' | null\n\t\tinitialSelectionSnapPoints: BoundsSnapPoint[]\n\t\tinitialSelectionPageBounds: Box\n\t\tdragDelta: Vec\n\t}): SnapData {\n\t\tconst snapThreshold = this.manager.getSnapThreshold()\n\t\tconst visibleSnapPointsNotInSelection = this.getSnappablePoints()\n\n\t\tconst selectionPageBounds = initialSelectionPageBounds.clone().translate(dragDelta)\n\n\t\tconst selectionSnapPoints: BoundsSnapPoint[] = initialSelectionSnapPoints.map(\n\t\t\t({ x, y }, i) => ({\n\t\t\t\tid: 'selection:' + i,\n\t\t\t\tx: x + dragDelta.x,\n\t\t\t\ty: y + dragDelta.y,\n\t\t\t})\n\t\t)\n\n\t\tconst otherNodeSnapPoints = visibleSnapPointsNotInSelection\n\n\t\tconst nearestSnapsX: NearestSnap[] = []\n\t\tconst nearestSnapsY: NearestSnap[] = []\n\t\tconst minOffset = new Vec(snapThreshold, snapThreshold)\n\n\t\tthis.collectPointSnaps({\n\t\t\tminOffset,\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t\totherNodeSnapPoints,\n\t\t\tselectionSnapPoints,\n\t\t})\n\n\t\tthis.collectGapSnaps({\n\t\t\tselectionPageBounds,\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t\tminOffset,\n\t\t})\n\n\t\t// at the same time, calculate how far we need to nudge the shape to 'snap' to the target point(s)\n\t\tconst nudge = new Vec(\n\t\t\tlockedAxis === 'x' ? 0 : (nearestSnapsX[0]?.nudge ?? 0),\n\t\t\tlockedAxis === 'y' ? 0 : (nearestSnapsY[0]?.nudge ?? 0)\n\t\t)\n\n\t\t// ok we've figured out how much the box should be nudged, now let's find all the snap points\n\t\t// that are exact after making that translation, so we can render all of them.\n\t\t// first reset everything and adjust the original shapes to conform to the nudge\n\t\tminOffset.x = 0\n\t\tminOffset.y = 0\n\t\tnearestSnapsX.length = 0\n\t\tnearestSnapsY.length = 0\n\t\tselectionSnapPoints.forEach((s) => {\n\t\t\ts.x += nudge.x\n\t\t\ts.y += nudge.y\n\t\t})\n\t\tselectionPageBounds.translate(nudge)\n\n\t\tthis.collectPointSnaps({\n\t\t\tminOffset,\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t\totherNodeSnapPoints,\n\t\t\tselectionSnapPoints,\n\t\t})\n\n\t\tthis.collectGapSnaps({\n\t\t\tselectionPageBounds,\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t\tminOffset,\n\t\t})\n\n\t\tconst pointSnapsLines = this.getPointSnapLines({\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t})\n\n\t\tconst gapSnapLines = this.getGapSnapLines({\n\t\t\tselectionPageBounds,\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t})\n\n\t\tthis.manager.setIndicators([...gapSnapLines, ...pointSnapsLines])\n\n\t\treturn { nudge }\n\t}\n\n\tsnapResizeShapes({\n\t\tinitialSelectionPageBounds,\n\t\tdragDelta,\n\t\thandle: originalHandle,\n\t\tisAspectRatioLocked,\n\t\tisResizingFromCenter,\n\t}: {\n\t\t// the page bounds when the pointer went down, before any dragging\n\t\tinitialSelectionPageBounds: Box\n\t\t// how far the pointer has been dragged\n\t\tdragDelta: Vec\n\n\t\thandle: SelectionCorner | SelectionEdge\n\t\tisAspectRatioLocked: boolean\n\t\tisResizingFromCenter: boolean\n\t}): SnapData {\n\t\tconst snapThreshold = this.manager.getSnapThreshold()\n\n\t\t// first figure out the new bounds of the selection\n\t\tconst {\n\t\t\tbox: unsnappedResizedPageBounds,\n\t\t\tscaleX,\n\t\t\tscaleY,\n\t\t} = Box.Resize(\n\t\t\tinitialSelectionPageBounds,\n\t\t\toriginalHandle,\n\t\t\tisResizingFromCenter ? dragDelta.x * 2 : dragDelta.x,\n\t\t\tisResizingFromCenter ? dragDelta.y * 2 : dragDelta.y,\n\t\t\tisAspectRatioLocked\n\t\t)\n\n\t\tlet handle = originalHandle\n\n\t\tif (scaleX < 0) {\n\t\t\thandle = flipSelectionHandleX(handle)\n\t\t}\n\t\tif (scaleY < 0) {\n\t\t\thandle = flipSelectionHandleY(handle)\n\t\t}\n\n\t\tif (isResizingFromCenter) {\n\t\t\t// reposition if resizing from center\n\t\t\tunsnappedResizedPageBounds.center = initialSelectionPageBounds.center\n\t\t}\n\n\t\tconst isXLocked = handle === 'top' || handle === 'bottom'\n\t\tconst isYLocked = handle === 'left' || handle === 'right'\n\n\t\tconst selectionSnapPoints = getResizeSnapPointsForHandle(handle, unsnappedResizedPageBounds)\n\n\t\tconst otherNodeSnapPoints = this.getSnappablePoints()\n\n\t\tconst nearestSnapsX: NearestPointsSnap[] = []\n\t\tconst nearestSnapsY: NearestPointsSnap[] = []\n\t\tconst minOffset = new Vec(snapThreshold, snapThreshold)\n\n\t\tthis.collectPointSnaps({\n\t\t\tminOffset,\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t\totherNodeSnapPoints,\n\t\t\tselectionSnapPoints,\n\t\t})\n\n\t\t// at the same time, calculate how far we need to nudge the shape to 'snap' to the target point(s)\n\t\tconst nudge = new Vec(\n\t\t\tisXLocked ? 0 : (nearestSnapsX[0]?.nudge ?? 0),\n\t\t\tisYLocked ? 0 : (nearestSnapsY[0]?.nudge ?? 0)\n\t\t)\n\n\t\tif (isAspectRatioLocked && isSelectionCorner(handle) && nudge.len() !== 0) {\n\t\t\t// if the aspect ratio is locked we need to make the nudge diagonal rather than independent in each axis\n\t\t\t// so we use the aspect ratio along with one axis value to set the other axis value, but which axis we use\n\t\t\t// as a source of truth depends what we have snapped to and how far.\n\n\t\t\t// if we found a snap in both axes, pick the closest one and discard the other\n\t\t\tconst primaryNudgeAxis: 'x' | 'y' =\n\t\t\t\tnearestSnapsX.length && nearestSnapsY.length\n\t\t\t\t\t? Math.abs(nudge.x) < Math.abs(nudge.y)\n\t\t\t\t\t\t? 'x'\n\t\t\t\t\t\t: 'y'\n\t\t\t\t\t: nearestSnapsX.length\n\t\t\t\t\t\t? 'x'\n\t\t\t\t\t\t: 'y'\n\n\t\t\tconst ratio = initialSelectionPageBounds.aspectRatio\n\n\t\t\tif (primaryNudgeAxis === 'x') {\n\t\t\t\tnearestSnapsY.length = 0\n\t\t\t\tnudge.y = nudge.x / ratio\n\t\t\t\tif (handle === 'bottom_left' || handle === 'top_right') {\n\t\t\t\t\tnudge.y = -nudge.y\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tnearestSnapsX.length = 0\n\t\t\t\tnudge.x = nudge.y * ratio\n\t\t\t\tif (handle === 'bottom_left' || handle === 'top_right') {\n\t\t\t\t\tnudge.x = -nudge.x\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// now resize the box after nudging, calculate the snaps again, and return the snap lines to match\n\t\t// the fully resized box\n\t\tconst snappedDelta = Vec.Add(dragDelta, nudge)\n\n\t\t// first figure out the new bounds of the selection\n\t\tconst { box: snappedResizedPageBounds } = Box.Resize(\n\t\t\tinitialSelectionPageBounds,\n\t\t\toriginalHandle,\n\t\t\tisResizingFromCenter ? snappedDelta.x * 2 : snappedDelta.x,\n\t\t\tisResizingFromCenter ? snappedDelta.y * 2 : snappedDelta.y,\n\t\t\tisAspectRatioLocked\n\t\t)\n\n\t\tif (isResizingFromCenter) {\n\t\t\t// reposition if resizing from center\n\t\t\tsnappedResizedPageBounds.center = initialSelectionPageBounds.center\n\t\t}\n\n\t\tconst snappedSelectionPoints = getResizeSnapPointsForHandle('any', snappedResizedPageBounds)\n\t\t// calculate snaps again using all points\n\t\tnearestSnapsX.length = 0\n\t\tnearestSnapsY.length = 0\n\t\tminOffset.x = 0\n\t\tminOffset.y = 0\n\n\t\tthis.collectPointSnaps({\n\t\t\tminOffset,\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t\totherNodeSnapPoints,\n\t\t\tselectionSnapPoints: snappedSelectionPoints,\n\t\t})\n\t\tconst pointSnaps = this.getPointSnapLines({\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t})\n\n\t\tthis.manager.setIndicators([...pointSnaps])\n\n\t\treturn { nudge }\n\t}\n\n\tprivate collectPointSnaps({\n\t\tselectionSnapPoints,\n\t\totherNodeSnapPoints,\n\t\tminOffset,\n\t\tnearestSnapsX,\n\t\tnearestSnapsY,\n\t}: {\n\t\tselectionSnapPoints: BoundsSnapPoint[]\n\t\totherNodeSnapPoints: BoundsSnapPoint[]\n\t\tminOffset: Vec\n\t\tnearestSnapsX: NearestSnap[]\n\t\tnearestSnapsY: NearestSnap[]\n\t}) {\n\t\t// for each snap point on the bounding box of the selection, find the set of points\n\t\t// which are closest to it in each axis\n\t\tfor (const thisSnapPoint of selectionSnapPoints) {\n\t\t\tfor (const otherSnapPoint of otherNodeSnapPoints) {\n\t\t\t\tconst offset = Vec.Sub(thisSnapPoint, otherSnapPoint)\n\t\t\t\tconst offsetX = Math.abs(offset.x)\n\t\t\t\tconst offsetY = Math.abs(offset.y)\n\n\t\t\t\tif (round(offsetX) <= round(minOffset.x)) {\n\t\t\t\t\tif (round(offsetX) < round(minOffset.x)) {\n\t\t\t\t\t\t// we found a point that is significantly closer than all previous points\n\t\t\t\t\t\t// so wipe the slate clean and start over\n\t\t\t\t\t\tnearestSnapsX.length = 0\n\t\t\t\t\t}\n\n\t\t\t\t\tnearestSnapsX.push({\n\t\t\t\t\t\ttype: 'points',\n\t\t\t\t\t\tpoints: { thisPoint: thisSnapPoint, otherPoint: otherSnapPoint },\n\t\t\t\t\t\tnudge: otherSnapPoint.x - thisSnapPoint.x,\n\t\t\t\t\t})\n\t\t\t\t\tminOffset.x = offsetX\n\t\t\t\t}\n\n\t\t\t\tif (round(offsetY) <= round(minOffset.y)) {\n\t\t\t\t\tif (round(offsetY) < round(minOffset.y)) {\n\t\t\t\t\t\t// we found a point that is significantly closer than all previous points\n\t\t\t\t\t\t// so wipe the slate clean and start over\n\t\t\t\t\t\tnearestSnapsY.length = 0\n\t\t\t\t\t}\n\t\t\t\t\tnearestSnapsY.push({\n\t\t\t\t\t\ttype: 'points',\n\t\t\t\t\t\tpoints: { thisPoint: thisSnapPoint, otherPoint: otherSnapPoint },\n\t\t\t\t\t\tnudge: otherSnapPoint.y - thisSnapPoint.y,\n\t\t\t\t\t})\n\t\t\t\t\tminOffset.y = offsetY\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate collectGapSnaps({\n\t\tselectionPageBounds,\n\t\tminOffset,\n\t\tnearestSnapsX,\n\t\tnearestSnapsY,\n\t}: {\n\t\tselectionPageBounds: Box\n\t\tminOffset: Vec\n\t\tnearestSnapsX: NearestSnap[]\n\t\tnearestSnapsY: NearestSnap[]\n\t}) {\n\t\tconst { horizontal, vertical } = this.getVisibleGaps()\n\n\t\tfor (const gap of horizontal) {\n\t\t\t// ignore this gap if the selection doesn't overlap with it in the y axis\n\t\t\tif (\n\t\t\t\t!rangesOverlap(\n\t\t\t\t\tgap.breadthIntersection[0],\n\t\t\t\t\tgap.breadthIntersection[1],\n\t\t\t\t\tselectionPageBounds.minY,\n\t\t\t\t\tselectionPageBounds.maxY\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// check for center match\n\t\t\tconst gapMidX = gap.startEdge[0].x + gap.length / 2\n\t\t\tconst centerNudge = gapMidX - selectionPageBounds.center.x\n\t\t\tconst gapIsLargerThanSelection = gap.length > selectionPageBounds.width\n\n\t\t\tif (gapIsLargerThanSelection && round(Math.abs(centerNudge)) <= round(minOffset.x)) {\n\t\t\t\tif (round(Math.abs(centerNudge)) < round(minOffset.x)) {\n\t\t\t\t\t// reset if we found a closer snap\n\t\t\t\t\tnearestSnapsX.length = 0\n\t\t\t\t}\n\t\t\t\tminOffset.x = Math.abs(centerNudge)\n\n\t\t\t\tconst snap: NearestSnap = {\n\t\t\t\t\ttype: 'gap_center',\n\t\t\t\t\tgap,\n\t\t\t\t\tnudge: centerNudge,\n\t\t\t\t}\n\n\t\t\t\t// we need to avoid creating visual noise with too many center snaps in situations\n\t\t\t\t// where there are lots of adjacent items with even spacing\n\t\t\t\t// so let's only show other center snaps where the gap's breadth does not overlap with this one\n\t\t\t\t// i.e.\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2518\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2534\u2510 \u2502\n\t\t\t\t// \u2502 \u2502 \u253C\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u252C\u2518 \u2502\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502 \u25C4\u2500\u2500\u2500\u2500 i'm dragging this one\n\t\t\t\t// \u2514\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\t\t\t\t// \u2500\u2500\u2500\u2500\u2500\u25BA \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2534\u2510 \u2502 don't show these\n\t\t\t\t// show these \u2502 \u2502 \u253C larger gaps since\n\t\t\t\t// smaller \u2514\u2500\u2500\u2500\u2500\u2500\u252C\u2518 \u2502 \u25C4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 the smaller ones\n\t\t\t\t// gaps \u253C \u2502 cover the same\n\t\t\t\t// \u2500\u2500\u2500\u2500\u2500\u25BA \u250C\u2534\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2510 information\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\t\t\t\t//\n\t\t\t\t// but we want to show all of these ones since the gap breadths don't overlap\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2510 \u2514\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\t\t\t\t// \u2502 \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u252C\u2500\u2518 \u253C\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2510\n\t\t\t\t// \u2502 \u2502 \u25C4\u2500\u2500\u2500\u2500\u2500 i'm dragging this one\n\t\t\t\t// \u2514\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2518\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2510 \u253C\n\t\t\t\t// \u2502 \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u250C\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n\t\t\t\tconst otherCenterSnap = nearestSnapsX.find(({ type }) => type === 'gap_center') as\n\t\t\t\t\t| Extract<NearestSnap, { type: 'gap_center' }>\n\t\t\t\t\t| undefined\n\n\t\t\t\tconst gapBreadthsOverlap =\n\t\t\t\t\totherCenterSnap &&\n\t\t\t\t\trangeIntersection(\n\t\t\t\t\t\tgap.breadthIntersection[0],\n\t\t\t\t\t\tgap.breadthIntersection[1],\n\t\t\t\t\t\totherCenterSnap.gap.breadthIntersection[0],\n\t\t\t\t\t\totherCenterSnap.gap.breadthIntersection[1]\n\t\t\t\t\t)\n\n\t\t\t\t// if there is another center snap and it's bigger than this one, and it overlaps with this one, replace it\n\t\t\t\tif (otherCenterSnap && otherCenterSnap.gap.length > gap.length && gapBreadthsOverlap) {\n\t\t\t\t\tnearestSnapsX[nearestSnapsX.indexOf(otherCenterSnap)] = snap\n\t\t\t\t} else if (!otherCenterSnap || !gapBreadthsOverlap) {\n\t\t\t\t\tnearestSnapsX.push(snap)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// check for duplication left match\n\t\t\tconst duplicationLeftX = gap.startNode.pageBounds.minX - gap.length\n\t\t\tconst selectionRightX = selectionPageBounds.maxX\n\n\t\t\tconst duplicationLeftNudge = duplicationLeftX - selectionRightX\n\t\t\tif (round(Math.abs(duplicationLeftNudge)) <= round(minOffset.x)) {\n\t\t\t\tif (round(Math.abs(duplicationLeftNudge)) < round(minOffset.x)) {\n\t\t\t\t\t// reset if we found a closer snap\n\t\t\t\t\tnearestSnapsX.length = 0\n\t\t\t\t}\n\t\t\t\tminOffset.x = Math.abs(duplicationLeftNudge)\n\n\t\t\t\tnearestSnapsX.push({\n\t\t\t\t\ttype: 'gap_duplicate',\n\t\t\t\t\tgap,\n\t\t\t\t\tprotrusionDirection: 'left',\n\t\t\t\t\tnudge: duplicationLeftNudge,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// check for duplication right match\n\t\t\tconst duplicationRightX = gap.endNode.pageBounds.maxX + gap.length\n\t\t\tconst selectionLeftX = selectionPageBounds.minX\n\n\t\t\tconst duplicationRightNudge = duplicationRightX - selectionLeftX\n\t\t\tif (round(Math.abs(duplicationRightNudge)) <= round(minOffset.x)) {\n\t\t\t\tif (round(Math.abs(duplicationRightNudge)) < round(minOffset.x)) {\n\t\t\t\t\t// reset if we found a closer snap\n\t\t\t\t\tnearestSnapsX.length = 0\n\t\t\t\t}\n\t\t\t\tminOffset.x = Math.abs(duplicationRightNudge)\n\n\t\t\t\tnearestSnapsX.push({\n\t\t\t\t\ttype: 'gap_duplicate',\n\t\t\t\t\tgap,\n\t\t\t\t\tprotrusionDirection: 'right',\n\t\t\t\t\tnudge: duplicationRightNudge,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tfor (const gap of vertical) {\n\t\t\t// ignore this gap if the selection doesn't overlap with it in the y axis\n\t\t\tif (\n\t\t\t\t!rangesOverlap(\n\t\t\t\t\tgap.breadthIntersection[0],\n\t\t\t\t\tgap.breadthIntersection[1],\n\t\t\t\t\tselectionPageBounds.minX,\n\t\t\t\t\tselectionPageBounds.maxX\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// check for center match\n\t\t\tconst gapMidY = gap.startEdge[0].y + gap.length / 2\n\t\t\tconst centerNudge = gapMidY - selectionPageBounds.center.y\n\n\t\t\tconst gapIsLargerThanSelection = gap.length > selectionPageBounds.height\n\n\t\t\tif (gapIsLargerThanSelection && round(Math.abs(centerNudge)) <= round(minOffset.y)) {\n\t\t\t\tif (round(Math.abs(centerNudge)) < round(minOffset.y)) {\n\t\t\t\t\t// reset if we found a closer snap\n\t\t\t\t\tnearestSnapsY.length = 0\n\t\t\t\t}\n\t\t\t\tminOffset.y = Math.abs(centerNudge)\n\n\t\t\t\tconst snap: NearestSnap = {\n\t\t\t\t\ttype: 'gap_center',\n\t\t\t\t\tgap,\n\t\t\t\t\tnudge: centerNudge,\n\t\t\t\t}\n\n\t\t\t\t// we need to avoid creating visual noise with too many center snaps in situations\n\t\t\t\t// where there are lots of adjacent items with even spacing\n\t\t\t\t// so let's only show other center snaps where the gap's breadth does not overlap with this one\n\t\t\t\t// i.e.\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2518\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2534\u2510 \u2502\n\t\t\t\t// \u2502 \u2502 \u253C\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u252C\u2518 \u2502\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502 \u25C4\u2500\u2500\u2500\u2500 i'm dragging this one\n\t\t\t\t// \u2514\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\t\t\t\t// \u2500\u2500\u2500\u2500\u2500\u25BA \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2534\u2510 \u2502 don't show these\n\t\t\t\t// show these \u2502 \u2502 \u253C larger gaps since\n\t\t\t\t// smaller \u2514\u2500\u2500\u2500\u2500\u2500\u252C\u2518 \u2502 \u25C4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 the smaller ones\n\t\t\t\t// gaps \u253C \u2502 cover the same\n\t\t\t\t// \u2500\u2500\u2500\u2500\u2500\u25BA \u250C\u2534\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2510 information\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\t\t\t\t//\n\t\t\t\t// but we want to show all of these ones since the gap breadths don't overlap\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2510 \u2514\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\t\t\t\t// \u2502 \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u252C\u2500\u2518 \u253C\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2510\n\t\t\t\t// \u2502 \u2502 \u25C4\u2500\u2500\u2500\u2500\u2500 i'm dragging this one\n\t\t\t\t// \u2514\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2518\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2510 \u253C\n\t\t\t\t// \u2502 \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u250C\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n\t\t\t\tconst otherCenterSnap = nearestSnapsY.find(({ type }) => type === 'gap_center') as\n\t\t\t\t\t| Extract<NearestSnap, { type: 'gap_center' }>\n\t\t\t\t\t| undefined\n\n\t\t\t\tconst gapBreadthsOverlap =\n\t\t\t\t\totherCenterSnap &&\n\t\t\t\t\trangesOverlap(\n\t\t\t\t\t\totherCenterSnap.gap.breadthIntersection[0],\n\t\t\t\t\t\totherCenterSnap.gap.breadthIntersection[1],\n\t\t\t\t\t\tgap.breadthIntersection[0],\n\t\t\t\t\t\tgap.breadthIntersection[1]\n\t\t\t\t\t)\n\n\t\t\t\t// if there is another center snap and it's bigger than this one, and it overlaps with this one, replace it\n\t\t\t\tif (otherCenterSnap && otherCenterSnap.gap.length > gap.length && gapBreadthsOverlap) {\n\t\t\t\t\tnearestSnapsY[nearestSnapsY.indexOf(otherCenterSnap)] = snap\n\t\t\t\t} else if (!otherCenterSnap || !gapBreadthsOverlap) {\n\t\t\t\t\tnearestSnapsY.push(snap)\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// check for duplication top match\n\t\t\tconst duplicationTopY = gap.startNode.pageBounds.minY - gap.length\n\t\t\tconst selectionBottomY = selectionPageBounds.maxY\n\n\t\t\tconst duplicationTopNudge = duplicationTopY - selectionBottomY\n\t\t\tif (round(Math.abs(duplicationTopNudge)) <= round(minOffset.y)) {\n\t\t\t\tif (round(Math.abs(duplicationTopNudge)) < round(minOffset.y)) {\n\t\t\t\t\t// reset if we found a closer snap\n\t\t\t\t\tnearestSnapsY.length = 0\n\t\t\t\t}\n\t\t\t\tminOffset.y = Math.abs(duplicationTopNudge)\n\n\t\t\t\tnearestSnapsY.push({\n\t\t\t\t\ttype: 'gap_duplicate',\n\t\t\t\t\tgap,\n\t\t\t\t\tprotrusionDirection: 'top',\n\t\t\t\t\tnudge: duplicationTopNudge,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// check for duplication bottom match\n\t\t\tconst duplicationBottomY = gap.endNode.pageBounds.maxY + gap.length\n\t\t\tconst selectionTopY = selectionPageBounds.minY\n\n\t\t\tconst duplicationBottomNudge = duplicationBottomY - selectionTopY\n\t\t\tif (round(Math.abs(duplicationBottomNudge)) <= round(minOffset.y)) {\n\t\t\t\tif (round(Math.abs(duplicationBottomNudge)) < round(minOffset.y)) {\n\t\t\t\t\t// reset if we found a closer snap\n\t\t\t\t\tnearestSnapsY.length = 0\n\t\t\t\t}\n\t\t\t\tminOffset.y = Math.abs(duplicationBottomNudge)\n\n\t\t\t\tnearestSnapsY.push({\n\t\t\t\t\ttype: 'gap_duplicate',\n\t\t\t\t\tgap,\n\t\t\t\t\tprotrusionDirection: 'bottom',\n\t\t\t\t\tnudge: duplicationBottomNudge,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getPointSnapLines({\n\t\tnearestSnapsX,\n\t\tnearestSnapsY,\n\t}: {\n\t\tnearestSnapsX: NearestSnap[]\n\t\tnearestSnapsY: NearestSnap[]\n\t}): PointsSnapIndicator[] {\n\t\t// point snaps may align on multiple parallel lines so we need to split the pairs\n\t\t// into groups based on where they are in their their snap axes\n\t\tconst snapGroupsX = {} as { [key: string]: SnapPair[] }\n\t\tconst snapGroupsY = {} as { [key: string]: SnapPair[] }\n\n\t\tif (nearestSnapsX.length > 0) {\n\t\t\tfor (const snap of nearestSnapsX) {\n\t\t\t\tif (snap.type === 'points') {\n\t\t\t\t\tconst key = round(snap.points.otherPoint.x)\n\t\t\t\t\tif (!snapGroupsX[key]) {\n\t\t\t\t\t\tsnapGroupsX[key] = []\n\t\t\t\t\t}\n\t\t\t\t\tsnapGroupsX[key].push(snap.points)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (nearestSnapsY.length > 0) {\n\t\t\tfor (const snap of nearestSnapsY) {\n\t\t\t\tif (snap.type === 'points') {\n\t\t\t\t\tconst key = round(snap.points.otherPoint.y)\n\t\t\t\t\tif (!snapGroupsY[key]) {\n\t\t\t\t\t\tsnapGroupsY[key] = []\n\t\t\t\t\t}\n\t\t\t\t\tsnapGroupsY[key].push(snap.points)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// and finally create all the snap lines for the UI to render\n\t\treturn Object.values(snapGroupsX)\n\t\t\t.concat(Object.values(snapGroupsY))\n\t\t\t.map((snapGroup) => ({\n\t\t\t\tid: uniqueId(),\n\t\t\t\ttype: 'points',\n\t\t\t\tpoints: dedupe(\n\t\t\t\t\tsnapGroup\n\t\t\t\t\t\t.map((snap) => Vec.From(snap.otherPoint))\n\t\t\t\t\t\t// be sure to nudge over the selection snap points\n\t\t\t\t\t\t.concat(snapGroup.map((snap) => Vec.From(snap.thisPoint))),\n\t\t\t\t\t(a: Vec, b: Vec) => a.equals(b)\n\t\t\t\t),\n\t\t\t}))\n\t}\n\n\tprivate getGapSnapLines({\n\t\tselectionPageBounds,\n\t\tnearestSnapsX,\n\t\tnearestSnapsY,\n\t}: {\n\t\tselectionPageBounds: Box\n\t\tnearestSnapsX: NearestSnap[]\n\t\tnearestSnapsY: NearestSnap[]\n\t}): GapsSnapIndicator[] {\n\t\tconst { vertical, horizontal } = this.getVisibleGaps()\n\n\t\tconst selectionSides: Record<SelectionEdge, [Vec, Vec]> = {\n\t\t\ttop: selectionPageBounds.sides[0],\n\t\t\tright: selectionPageBounds.sides[1],\n\t\t\t// need bottom and left to be sorted asc, which .sides is not.\n\t\t\tbottom: [selectionPageBounds.corners[3], selectionPageBounds.corners[2]],\n\t\t\tleft: [selectionPageBounds.corners[0], selectionPageBounds.corners[3]],\n\t\t}\n\n\t\tconst result: GapsSnapIndicator[] = []\n\n\t\tif (nearestSnapsX.length > 0) {\n\t\t\tfor (const snap of nearestSnapsX) {\n\t\t\t\tif (snap.type === 'points') continue\n\n\t\t\t\tconst {\n\t\t\t\t\tgap: { breadthIntersection, startEdge, startNode, endNode, length, endEdge },\n\t\t\t\t} = snap\n\n\t\t\t\tswitch (snap.type) {\n\t\t\t\t\tcase 'gap_center': {\n\t\t\t\t\t\t// create\n\t\t\t\t\t\tconst newGapsLength = (length - selectionPageBounds.width) / 2\n\t\t\t\t\t\tconst gapBreadthIntersection = rangeIntersection(\n\t\t\t\t\t\t\tbreadthIntersection[0],\n\t\t\t\t\t\t\tbreadthIntersection[1],\n\t\t\t\t\t\t\tselectionPageBounds.minY,\n\t\t\t\t\t\t\tselectionPageBounds.maxY\n\t\t\t\t\t\t)!\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\ttype: 'gaps',\n\t\t\t\t\t\t\tdirection: 'horizontal',\n\t\t\t\t\t\t\tid: uniqueId(),\n\t\t\t\t\t\t\tgaps: [\n\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\thorizontal,\n\t\t\t\t\t\t\t\t\tstartNode.id,\n\t\t\t\t\t\t\t\t\tnewGapsLength,\n\t\t\t\t\t\t\t\t\t'backward',\n\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstartEdge,\n\t\t\t\t\t\t\t\t\tendEdge: selectionSides.left,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstartEdge: selectionSides.right,\n\t\t\t\t\t\t\t\t\tendEdge,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\thorizontal,\n\t\t\t\t\t\t\t\t\tendNode.id,\n\t\t\t\t\t\t\t\t\tnewGapsLength,\n\t\t\t\t\t\t\t\t\t'forward',\n\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t})\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'gap_duplicate': {\n\t\t\t\t\t\t// create\n\t\t\t\t\t\tconst gapBreadthIntersection = rangeIntersection(\n\t\t\t\t\t\t\tbreadthIntersection[0],\n\t\t\t\t\t\t\tbreadthIntersection[1],\n\t\t\t\t\t\t\tselectionPageBounds.minY,\n\t\t\t\t\t\t\tselectionPageBounds.maxY\n\t\t\t\t\t\t)!\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\ttype: 'gaps',\n\t\t\t\t\t\t\tdirection: 'horizontal',\n\t\t\t\t\t\t\tid: uniqueId(),\n\t\t\t\t\t\t\tgaps:\n\t\t\t\t\t\t\t\tsnap.protrusionDirection === 'left'\n\t\t\t\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tstartEdge: selectionSides.right,\n\t\t\t\t\t\t\t\t\t\t\t\tendEdge: startEdge.map((v) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\tv.clone().addXY(-startNode.pageBounds.width, 0)\n\t\t\t\t\t\t\t\t\t\t\t\t) as [Vec, Vec],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{ startEdge, endEdge },\n\t\t\t\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\t\t\t\thorizontal,\n\t\t\t\t\t\t\t\t\t\t\t\tendNode.id,\n\t\t\t\t\t\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\t\t\t\t\t\t'forward',\n\t\t\t\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\t\t\t\thorizontal,\n\t\t\t\t\t\t\t\t\t\t\t\tstartNode.id,\n\t\t\t\t\t\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\t\t\t\t\t\t'backward',\n\t\t\t\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t{ startEdge, endEdge },\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tstartEdge: endEdge.map((v) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\tv.clone().addXY(snap.gap.endNode.pageBounds.width, 0)\n\t\t\t\t\t\t\t\t\t\t\t\t) as [Vec, Vec],\n\t\t\t\t\t\t\t\t\t\t\t\tendEdge: selectionSides.left,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (nearestSnapsY.length > 0) {\n\t\t\tfor (const snap of nearestSnapsY) {\n\t\t\t\tif (snap.type === 'points') continue\n\n\t\t\t\tconst {\n\t\t\t\t\tgap: { breadthIntersection, startEdge, startNode, endNode, length, endEdge },\n\t\t\t\t} = snap\n\n\t\t\t\tswitch (snap.type) {\n\t\t\t\t\tcase 'gap_center': {\n\t\t\t\t\t\tconst newGapsLength = (length - selectionPageBounds.height) / 2\n\t\t\t\t\t\tconst gapBreadthIntersection = rangeIntersection(\n\t\t\t\t\t\t\tbreadthIntersection[0],\n\t\t\t\t\t\t\tbreadthIntersection[1],\n\t\t\t\t\t\t\tselectionPageBounds.minX,\n\t\t\t\t\t\t\tselectionPageBounds.maxX\n\t\t\t\t\t\t)!\n\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\ttype: 'gaps',\n\t\t\t\t\t\t\tdirection: 'vertical',\n\t\t\t\t\t\t\tid: uniqueId(),\n\t\t\t\t\t\t\tgaps: [\n\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\tvertical,\n\t\t\t\t\t\t\t\t\tstartNode.id,\n\t\t\t\t\t\t\t\t\tnewGapsLength,\n\t\t\t\t\t\t\t\t\t'backward',\n\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstartEdge,\n\t\t\t\t\t\t\t\t\tendEdge: selectionSides.top,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstartEdge: selectionSides.bottom,\n\t\t\t\t\t\t\t\t\tendEdge,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\tvertical,\n\t\t\t\t\t\t\t\t\tsnap.gap.endNode.id,\n\t\t\t\t\t\t\t\t\tnewGapsLength,\n\t\t\t\t\t\t\t\t\t'forward',\n\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t})\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'gap_duplicate':\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst gapBreadthIntersection = rangeIntersection(\n\t\t\t\t\t\t\t\tbreadthIntersection[0],\n\t\t\t\t\t\t\t\tbreadthIntersection[1],\n\t\t\t\t\t\t\t\tselectionPageBounds.minX,\n\t\t\t\t\t\t\t\tselectionPageBounds.maxX\n\t\t\t\t\t\t\t)!\n\n\t\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\t\ttype: 'gaps',\n\t\t\t\t\t\t\t\tdirection: 'vertical',\n\t\t\t\t\t\t\t\tid: uniqueId(),\n\t\t\t\t\t\t\t\tgaps:\n\t\t\t\t\t\t\t\t\tsnap.protrusionDirection === 'top'\n\t\t\t\t\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tstartEdge: selectionSides.bottom,\n\t\t\t\t\t\t\t\t\t\t\t\t\tendEdge: startEdge.map((v) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tv.clone().addXY(0, -startNode.pageBounds.height)\n\t\t\t\t\t\t\t\t\t\t\t\t\t) as [Vec, Vec],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{ startEdge, endEdge },\n\t\t\t\t\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\t\t\t\t\tvertical,\n\t\t\t\t\t\t\t\t\t\t\t\t\tendNode.id,\n\t\t\t\t\t\t\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\t\t\t\t\t\t\t'forward',\n\t\t\t\t\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\t\t\t\t\tvertical,\n\t\t\t\t\t\t\t\t\t\t\t\t\tstartNode.id,\n\t\t\t\t\t\t\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\t\t\t\t\t\t\t'backward',\n\t\t\t\t\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t{ startEdge, endEdge },\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tstartEdge: endEdge.map((v) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tv.clone().addXY(0, endNode.pageBounds.height)\n\t\t\t\t\t\t\t\t\t\t\t\t\t) as [Vec, Vec],\n\t\t\t\t\t\t\t\t\t\t\t\t\tendEdge: selectionSides.top,\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdedupeGapSnaps(result)\n\t\treturn result\n\t}\n}\n\nfunction getResizeSnapPointsForHandle(\n\thandle: SelectionCorner | SelectionEdge | 'any',\n\tselectionPageBounds: Box\n): BoundsSnapPoint[] {\n\tconst { minX, maxX, minY, maxY } = selectionPageBounds\n\tconst result: BoundsSnapPoint[] = []\n\n\t// top left corner\n\tswitch (handle) {\n\t\tcase 'top':\n\t\tcase 'left':\n\t\tcase 'top_left':\n\t\tcase 'any':\n\t\t\tresult.push({\n\t\t\t\tid: 'top_left',\n\t\t\t\thandle: 'top_left',\n\t\t\t\tx: minX,\n\t\t\t\ty: minY,\n\t\t\t})\n\t}\n\n\t// top right corner\n\tswitch (handle) {\n\t\tcase 'top':\n\t\tcase 'right':\n\t\tcase 'top_right':\n\t\tcase 'any':\n\t\t\tresult.push({\n\t\t\t\tid: 'top_right',\n\t\t\t\thandle: 'top_right',\n\t\t\t\tx: maxX,\n\t\t\t\ty: minY,\n\t\t\t})\n\t}\n\n\t// bottom right corner\n\tswitch (handle) {\n\t\tcase 'bottom':\n\t\tcase 'right':\n\t\tcase 'bottom_right':\n\t\tcase 'any':\n\t\t\tresult.push({\n\t\t\t\tid: 'bottom_right',\n\t\t\t\thandle: 'bottom_right',\n\t\t\t\tx: maxX,\n\t\t\t\ty: maxY,\n\t\t\t})\n\t}\n\n\t// bottom left corner\n\tswitch (handle) {\n\t\tcase 'bottom':\n\t\tcase 'left':\n\t\tcase 'bottom_left':\n\t\tcase 'any':\n\t\t\tresult.push({\n\t\t\t\tid: 'bottom_left',\n\t\t\t\thandle: 'bottom_left',\n\t\t\t\tx: minX,\n\t\t\t\ty: maxY,\n\t\t\t})\n\t}\n\n\treturn result\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { computed } from '@tldraw/state'\nimport { TLShape, TLShapeId, VecModel } from '@tldraw/tlschema'\nimport { assertExists, dedupe, uniqueId } from '@tldraw/utils'\nimport {\n\tBox,\n\tSelectionCorner,\n\tSelectionEdge,\n\tflipSelectionHandleX,\n\tflipSelectionHandleY,\n\tisSelectionCorner,\n} from '../../../primitives/Box'\nimport { Mat } from '../../../primitives/Mat'\nimport { rangeIntersection, rangesOverlap } from '../../../primitives/utils'\nimport { Vec } from '../../../primitives/Vec'\nimport type { Editor } from '../../Editor'\nimport type {\n\tGapsSnapIndicator,\n\tPointsSnapIndicator,\n\tSnapData,\n\tSnapIndicator,\n\tSnapManager,\n} from './SnapManager'\n\n/**\n * When moving or resizing shapes, the bounds of the shape can snap to key geometry on other nearby\n * shapes. Customize how a shape snaps to others with {@link ShapeUtil.getBoundsSnapGeometry}.\n *\n * @public\n */\nexport interface BoundsSnapGeometry {\n\t/**\n\t * Points that this shape will snap to. By default, this will be the corners and center of the\n\t * shapes bounding box. To disable snapping to a specific point, use an empty array.\n\t */\n\tpoints?: VecModel[]\n}\n\n/** @public */\nexport interface BoundsSnapPoint {\n\tid: string\n\tx: number\n\ty: number\n\thandle?: SelectionCorner\n}\n\ninterface SnapPair {\n\tthisPoint: BoundsSnapPoint\n\totherPoint: BoundsSnapPoint\n}\n\ninterface NearestPointsSnap {\n\t// selection snaps to a nearby snap point\n\ttype: 'points'\n\tpoints: SnapPair\n\tnudge: number\n}\n\ntype NearestSnap =\n\t| NearestPointsSnap\n\t| {\n\t\t\t// selection snaps to the center of a gap\n\t\t\ttype: 'gap_center'\n\t\t\tgap: Gap\n\t\t\tnudge: number\n\t }\n\t| {\n\t\t\t// selection snaps to create a new gap of equal size to another gap\n\t\t\t// on the opposite side of some shape\n\t\t\ttype: 'gap_duplicate'\n\t\t\tgap: Gap\n\t\t\tprotrusionDirection: 'left' | 'right' | 'top' | 'bottom'\n\t\t\tnudge: number\n\t }\n\ninterface GapNode {\n\tid: TLShapeId\n\tpageBounds: Box\n}\n\ninterface Gap {\n\t// e.g.\n\t// start\n\t// edge \u2502 breadth\n\t// \u2502 intersection\n\t// \u25BC [40,100] end\n\t// \u2502 \u2502 edge\n\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502 100,0 \u2502 \u2502\n\t// \u2502 \u2502 \u2502 \u25BC \u25BC\n\t// \u2502 \u2502 \u2502\n\t// \u2502 start \u2502 \u2502 \u2502 200,40 \u2502 \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t// \u2502 node \u2502 \u2502 \u2502 \u2502 \u2502 \u2502\n\t// \u2502 \u2502 \u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524 \u2502 end \u2502\n\t// \u2502 \u2502 \u2502 \u2502 \u2502 \u2502 node \u2502\n\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502 100,100 \u2502 \u2502 \u2502 \u2502\n\t// \u2502 \u2502 \u2502\n\t// 200,120 \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\t//\n\t// length 100\n\t// \u25C4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25BA\n\tstartNode: GapNode\n\tendNode: GapNode\n\tstartEdge: [Vec, Vec]\n\tendEdge: [Vec, Vec]\n\tlength: number\n\tbreadthIntersection: [number, number]\n}\n\nconst round = (x: number) => {\n\t// round numbers to avoid glitches for floating point rounding errors\n\tconst decimalPlacesTolerance = 8\n\treturn Math.round(x * 10 ** decimalPlacesTolerance) / 10 ** decimalPlacesTolerance\n}\n\nfunction findAdjacentGaps(\n\tgaps: Gap[],\n\tshapeId: TLShapeId,\n\tgapLength: number,\n\tdirection: 'forward' | 'backward',\n\tintersection: [number, number]\n): Gap[] {\n\t// TODO: take advantage of the fact that gaps is sorted by starting position?\n\tconst matches = gaps.filter(\n\t\t(gap) =>\n\t\t\t(direction === 'forward' ? gap.startNode.id === shapeId : gap.endNode.id === shapeId) &&\n\t\t\tround(gap.length) === round(gapLength) &&\n\t\t\trangeIntersection(\n\t\t\t\tgap.breadthIntersection[0],\n\t\t\t\tgap.breadthIntersection[1],\n\t\t\t\tintersection[0],\n\t\t\t\tintersection[1]\n\t\t\t)\n\t)\n\n\tif (matches.length === 0) return []\n\n\tconst nextNodes = new Set<TLShapeId>()\n\n\tmatches.forEach((match) => {\n\t\tconst node = direction === 'forward' ? match.endNode.id : match.startNode.id\n\t\tif (!nextNodes.has(node)) {\n\t\t\tnextNodes.add(node)\n\t\t\tconst foundGaps = findAdjacentGaps(\n\t\t\t\tgaps,\n\t\t\t\tnode,\n\t\t\t\tgapLength,\n\t\t\t\tdirection,\n\t\t\t\trangeIntersection(\n\t\t\t\t\tmatch.breadthIntersection[0],\n\t\t\t\t\tmatch.breadthIntersection[1],\n\t\t\t\t\tintersection[0],\n\t\t\t\t\tintersection[1]\n\t\t\t\t)!\n\t\t\t)\n\n\t\t\tmatches.push(...foundGaps)\n\t\t}\n\t})\n\n\treturn matches\n}\n\nfunction dedupeGapSnaps(snaps: Array<Extract<SnapIndicator, { type: 'gaps' }>>) {\n\t// sort by descending order of number of gaps\n\tsnaps.sort((a, b) => b.gaps.length - a.gaps.length)\n\t// pop off any that are included already\n\tfor (let i = snaps.length - 1; i > 0; i--) {\n\t\tconst snap = snaps[i]\n\t\tfor (let j = i - 1; j >= 0; j--) {\n\t\t\tconst otherSnap = snaps[j]\n\t\t\t// if every edge in this snap is included in the other snap somewhere, then it's redundant\n\t\t\tif (\n\t\t\t\totherSnap.direction === snap.direction &&\n\t\t\t\tsnap.gaps.every(\n\t\t\t\t\t(gap) =>\n\t\t\t\t\t\totherSnap.gaps.some(\n\t\t\t\t\t\t\t(otherGap) =>\n\t\t\t\t\t\t\t\tround(gap.startEdge[0].x) === round(otherGap.startEdge[0].x) &&\n\t\t\t\t\t\t\t\tround(gap.startEdge[0].y) === round(otherGap.startEdge[0].y) &&\n\t\t\t\t\t\t\t\tround(gap.startEdge[1].x) === round(otherGap.startEdge[1].x) &&\n\t\t\t\t\t\t\t\tround(gap.startEdge[1].y) === round(otherGap.startEdge[1].y)\n\t\t\t\t\t\t) &&\n\t\t\t\t\t\totherSnap.gaps.some(\n\t\t\t\t\t\t\t(otherGap) =>\n\t\t\t\t\t\t\t\tround(gap.endEdge[0].x) === round(otherGap.endEdge[0].x) &&\n\t\t\t\t\t\t\t\tround(gap.endEdge[0].y) === round(otherGap.endEdge[0].y) &&\n\t\t\t\t\t\t\t\tround(gap.endEdge[1].x) === round(otherGap.endEdge[1].x) &&\n\t\t\t\t\t\t\t\tround(gap.endEdge[1].y) === round(otherGap.endEdge[1].y)\n\t\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tsnaps.splice(i, 1)\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n}\n\n/** @public */\nexport class BoundsSnaps {\n\treadonly editor: Editor\n\tconstructor(readonly manager: SnapManager) {\n\t\tthis.editor = manager.editor\n\t}\n\n\t@computed private getSnapPointsCache() {\n\t\tconst { editor } = this\n\t\treturn editor.store.createComputedCache<BoundsSnapPoint[], TLShape>('snapPoints', (shape) => {\n\t\t\tconst pageTransform = editor.getShapePageTransform(shape.id)\n\t\t\tif (!pageTransform) return undefined\n\t\t\tconst boundsSnapGeometry = editor.getShapeUtil(shape).getBoundsSnapGeometry(shape)\n\t\t\tconst snapPoints =\n\t\t\t\tboundsSnapGeometry.points ?? editor.getShapeGeometry(shape).bounds.cornersAndCenter\n\n\t\t\tif (!pageTransform || !snapPoints) return undefined\n\t\t\treturn snapPoints.map((point, i) => {\n\t\t\t\tconst { x, y } = Mat.applyToPoint(pageTransform, point)\n\t\t\t\treturn { x, y, id: `${shape.id}:${i}` }\n\t\t\t})\n\t\t})\n\t}\n\n\tgetSnapPoints(shapeId: TLShapeId) {\n\t\treturn this.getSnapPointsCache().get(shapeId) ?? []\n\t}\n\n\t// Points which belong to snappable shapes\n\t@computed private getSnappablePoints() {\n\t\tconst snapPointsCache = this.getSnapPointsCache()\n\t\tconst snappableShapes = this.manager.getSnappableShapes()\n\t\tconst result: BoundsSnapPoint[] = []\n\n\t\tfor (const shapeId of snappableShapes) {\n\t\t\tconst snapPoints = snapPointsCache.get(shapeId)\n\t\t\tif (snapPoints) {\n\t\t\t\tresult.push(...snapPoints)\n\t\t\t}\n\t\t}\n\n\t\treturn result\n\t}\n\n\t@computed private getSnappableGapNodes(): Array<GapNode> {\n\t\treturn Array.from(this.manager.getSnappableShapes(), (shapeId) => ({\n\t\t\tid: shapeId,\n\t\t\tpageBounds: assertExists(this.editor.getShapePageBounds(shapeId)),\n\t\t}))\n\t}\n\n\t@computed private getVisibleGaps(): { horizontal: Gap[]; vertical: Gap[] } {\n\t\tconst horizontal: Gap[] = []\n\t\tconst vertical: Gap[] = []\n\n\t\tlet startNode: GapNode, endNode: GapNode\n\n\t\tconst sortedShapesOnCurrentPageHorizontal = this.getSnappableGapNodes().sort((a, b) => {\n\t\t\treturn a.pageBounds.minX - b.pageBounds.minX\n\t\t})\n\n\t\t// Collect horizontal gaps\n\t\tfor (let i = 0; i < sortedShapesOnCurrentPageHorizontal.length; i++) {\n\t\t\tstartNode = sortedShapesOnCurrentPageHorizontal[i]\n\t\t\tfor (let j = i + 1; j < sortedShapesOnCurrentPageHorizontal.length; j++) {\n\t\t\t\tendNode = sortedShapesOnCurrentPageHorizontal[j]\n\n\t\t\t\tif (\n\t\t\t\t\t// is there space between the boxes\n\t\t\t\t\tstartNode.pageBounds.maxX < endNode.pageBounds.minX &&\n\t\t\t\t\t// and they overlap in the y axis\n\t\t\t\t\trangesOverlap(\n\t\t\t\t\t\tstartNode.pageBounds.minY,\n\t\t\t\t\t\tstartNode.pageBounds.maxY,\n\t\t\t\t\t\tendNode.pageBounds.minY,\n\t\t\t\t\t\tendNode.pageBounds.maxY\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\thorizontal.push({\n\t\t\t\t\t\tstartNode,\n\t\t\t\t\t\tendNode,\n\t\t\t\t\t\tstartEdge: [\n\t\t\t\t\t\t\tnew Vec(startNode.pageBounds.maxX, startNode.pageBounds.minY),\n\t\t\t\t\t\t\tnew Vec(startNode.pageBounds.maxX, startNode.pageBounds.maxY),\n\t\t\t\t\t\t],\n\t\t\t\t\t\tendEdge: [\n\t\t\t\t\t\t\tnew Vec(endNode.pageBounds.minX, endNode.pageBounds.minY),\n\t\t\t\t\t\t\tnew Vec(endNode.pageBounds.minX, endNode.pageBounds.maxY),\n\t\t\t\t\t\t],\n\t\t\t\t\t\tlength: endNode.pageBounds.minX - startNode.pageBounds.maxX,\n\t\t\t\t\t\tbreadthIntersection: rangeIntersection(\n\t\t\t\t\t\t\tstartNode.pageBounds.minY,\n\t\t\t\t\t\t\tstartNode.pageBounds.maxY,\n\t\t\t\t\t\t\tendNode.pageBounds.minY,\n\t\t\t\t\t\t\tendNode.pageBounds.maxY\n\t\t\t\t\t\t)!,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Collect vertical gaps\n\t\tconst sortedShapesOnCurrentPageVertical = sortedShapesOnCurrentPageHorizontal.sort((a, b) => {\n\t\t\treturn a.pageBounds.minY - b.pageBounds.minY\n\t\t})\n\n\t\tfor (let i = 0; i < sortedShapesOnCurrentPageVertical.length; i++) {\n\t\t\tstartNode = sortedShapesOnCurrentPageVertical[i]\n\t\t\tfor (let j = i + 1; j < sortedShapesOnCurrentPageVertical.length; j++) {\n\t\t\t\tendNode = sortedShapesOnCurrentPageVertical[j]\n\n\t\t\t\tif (\n\t\t\t\t\t// is there space between the boxes\n\t\t\t\t\tstartNode.pageBounds.maxY < endNode.pageBounds.minY &&\n\t\t\t\t\t// do they overlap in the x axis\n\t\t\t\t\trangesOverlap(\n\t\t\t\t\t\tstartNode.pageBounds.minX,\n\t\t\t\t\t\tstartNode.pageBounds.maxX,\n\t\t\t\t\t\tendNode.pageBounds.minX,\n\t\t\t\t\t\tendNode.pageBounds.maxX\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tvertical.push({\n\t\t\t\t\t\tstartNode,\n\t\t\t\t\t\tendNode,\n\t\t\t\t\t\tstartEdge: [\n\t\t\t\t\t\t\tnew Vec(startNode.pageBounds.minX, startNode.pageBounds.maxY),\n\t\t\t\t\t\t\tnew Vec(startNode.pageBounds.maxX, startNode.pageBounds.maxY),\n\t\t\t\t\t\t],\n\t\t\t\t\t\tendEdge: [\n\t\t\t\t\t\t\tnew Vec(endNode.pageBounds.minX, endNode.pageBounds.minY),\n\t\t\t\t\t\t\tnew Vec(endNode.pageBounds.maxX, endNode.pageBounds.minY),\n\t\t\t\t\t\t],\n\t\t\t\t\t\tlength: endNode.pageBounds.minY - startNode.pageBounds.maxY,\n\t\t\t\t\t\tbreadthIntersection: rangeIntersection(\n\t\t\t\t\t\t\tstartNode.pageBounds.minX,\n\t\t\t\t\t\t\tstartNode.pageBounds.maxX,\n\t\t\t\t\t\t\tendNode.pageBounds.minX,\n\t\t\t\t\t\t\tendNode.pageBounds.maxX\n\t\t\t\t\t\t)!,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { horizontal, vertical }\n\t}\n\n\tsnapTranslateShapes({\n\t\tlockedAxis,\n\t\tinitialSelectionPageBounds,\n\t\tinitialSelectionSnapPoints,\n\t\tdragDelta,\n\t}: {\n\t\tlockedAxis: 'x' | 'y' | null\n\t\tinitialSelectionSnapPoints: BoundsSnapPoint[]\n\t\tinitialSelectionPageBounds: Box\n\t\tdragDelta: Vec\n\t}): SnapData {\n\t\tconst snapThreshold = this.manager.getSnapThreshold()\n\t\tconst visibleSnapPointsNotInSelection = this.getSnappablePoints()\n\n\t\tconst selectionPageBounds = initialSelectionPageBounds.clone().translate(dragDelta)\n\n\t\tconst selectionSnapPoints: BoundsSnapPoint[] = initialSelectionSnapPoints.map(\n\t\t\t({ x, y }, i) => ({\n\t\t\t\tid: 'selection:' + i,\n\t\t\t\tx: x + dragDelta.x,\n\t\t\t\ty: y + dragDelta.y,\n\t\t\t})\n\t\t)\n\n\t\tconst otherNodeSnapPoints = visibleSnapPointsNotInSelection\n\n\t\tconst nearestSnapsX: NearestSnap[] = []\n\t\tconst nearestSnapsY: NearestSnap[] = []\n\t\tconst minOffset = new Vec(snapThreshold, snapThreshold)\n\n\t\tthis.collectPointSnaps({\n\t\t\tminOffset,\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t\totherNodeSnapPoints,\n\t\t\tselectionSnapPoints,\n\t\t})\n\n\t\tthis.collectGapSnaps({\n\t\t\tselectionPageBounds,\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t\tminOffset,\n\t\t})\n\n\t\t// at the same time, calculate how far we need to nudge the shape to 'snap' to the target point(s)\n\t\tconst nudge = new Vec(\n\t\t\tlockedAxis === 'x' ? 0 : (nearestSnapsX[0]?.nudge ?? 0),\n\t\t\tlockedAxis === 'y' ? 0 : (nearestSnapsY[0]?.nudge ?? 0)\n\t\t)\n\n\t\t// ok we've figured out how much the box should be nudged, now let's find all the snap points\n\t\t// that are exact after making that translation, so we can render all of them.\n\t\t// first reset everything and adjust the original shapes to conform to the nudge\n\t\tminOffset.x = 0\n\t\tminOffset.y = 0\n\t\tnearestSnapsX.length = 0\n\t\tnearestSnapsY.length = 0\n\t\tselectionSnapPoints.forEach((s) => {\n\t\t\ts.x += nudge.x\n\t\t\ts.y += nudge.y\n\t\t})\n\t\tselectionPageBounds.translate(nudge)\n\n\t\tthis.collectPointSnaps({\n\t\t\tminOffset,\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t\totherNodeSnapPoints,\n\t\t\tselectionSnapPoints,\n\t\t})\n\n\t\tthis.collectGapSnaps({\n\t\t\tselectionPageBounds,\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t\tminOffset,\n\t\t})\n\n\t\tconst pointSnapsLines = this.getPointSnapLines({\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t})\n\n\t\tconst gapSnapLines = this.getGapSnapLines({\n\t\t\tselectionPageBounds,\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t})\n\n\t\tthis.manager.setIndicators([...gapSnapLines, ...pointSnapsLines])\n\n\t\treturn { nudge }\n\t}\n\n\tsnapResizeShapes({\n\t\tinitialSelectionPageBounds,\n\t\tdragDelta,\n\t\thandle: originalHandle,\n\t\tisAspectRatioLocked,\n\t\tisResizingFromCenter,\n\t}: {\n\t\t// the page bounds when the pointer went down, before any dragging\n\t\tinitialSelectionPageBounds: Box\n\t\t// how far the pointer has been dragged\n\t\tdragDelta: Vec\n\n\t\thandle: SelectionCorner | SelectionEdge\n\t\tisAspectRatioLocked: boolean\n\t\tisResizingFromCenter: boolean\n\t}): SnapData {\n\t\tconst snapThreshold = this.manager.getSnapThreshold()\n\n\t\t// first figure out the new bounds of the selection\n\t\tconst {\n\t\t\tbox: unsnappedResizedPageBounds,\n\t\t\tscaleX,\n\t\t\tscaleY,\n\t\t} = Box.Resize(\n\t\t\tinitialSelectionPageBounds,\n\t\t\toriginalHandle,\n\t\t\tisResizingFromCenter ? dragDelta.x * 2 : dragDelta.x,\n\t\t\tisResizingFromCenter ? dragDelta.y * 2 : dragDelta.y,\n\t\t\tisAspectRatioLocked\n\t\t)\n\n\t\tlet handle = originalHandle\n\n\t\tif (scaleX < 0) {\n\t\t\thandle = flipSelectionHandleX(handle)\n\t\t}\n\t\tif (scaleY < 0) {\n\t\t\thandle = flipSelectionHandleY(handle)\n\t\t}\n\n\t\tif (isResizingFromCenter) {\n\t\t\t// reposition if resizing from center\n\t\t\tunsnappedResizedPageBounds.center = initialSelectionPageBounds.center\n\t\t}\n\n\t\tconst isXLocked = handle === 'top' || handle === 'bottom'\n\t\tconst isYLocked = handle === 'left' || handle === 'right'\n\n\t\tconst selectionSnapPoints = getResizeSnapPointsForHandle(handle, unsnappedResizedPageBounds)\n\n\t\tconst otherNodeSnapPoints = this.getSnappablePoints()\n\n\t\tconst nearestSnapsX: NearestPointsSnap[] = []\n\t\tconst nearestSnapsY: NearestPointsSnap[] = []\n\t\tconst minOffset = new Vec(snapThreshold, snapThreshold)\n\n\t\tthis.collectPointSnaps({\n\t\t\tminOffset,\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t\totherNodeSnapPoints,\n\t\t\tselectionSnapPoints,\n\t\t})\n\n\t\t// at the same time, calculate how far we need to nudge the shape to 'snap' to the target point(s)\n\t\tconst nudge = new Vec(\n\t\t\tisXLocked ? 0 : (nearestSnapsX[0]?.nudge ?? 0),\n\t\t\tisYLocked ? 0 : (nearestSnapsY[0]?.nudge ?? 0)\n\t\t)\n\n\t\tif (isAspectRatioLocked && isSelectionCorner(handle) && nudge.len() !== 0) {\n\t\t\t// if the aspect ratio is locked we need to make the nudge diagonal rather than independent in each axis\n\t\t\t// so we use the aspect ratio along with one axis value to set the other axis value, but which axis we use\n\t\t\t// as a source of truth depends what we have snapped to and how far.\n\n\t\t\t// if we found a snap in both axes, pick the closest one and discard the other\n\t\t\tconst primaryNudgeAxis: 'x' | 'y' =\n\t\t\t\tnearestSnapsX.length && nearestSnapsY.length\n\t\t\t\t\t? Math.abs(nudge.x) < Math.abs(nudge.y)\n\t\t\t\t\t\t? 'x'\n\t\t\t\t\t\t: 'y'\n\t\t\t\t\t: nearestSnapsX.length\n\t\t\t\t\t\t? 'x'\n\t\t\t\t\t\t: 'y'\n\n\t\t\tconst ratio = initialSelectionPageBounds.aspectRatio\n\n\t\t\tif (primaryNudgeAxis === 'x') {\n\t\t\t\tnearestSnapsY.length = 0\n\t\t\t\tnudge.y = nudge.x / ratio\n\t\t\t\tif (handle === 'bottom_left' || handle === 'top_right') {\n\t\t\t\t\tnudge.y = -nudge.y\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tnearestSnapsX.length = 0\n\t\t\t\tnudge.x = nudge.y * ratio\n\t\t\t\tif (handle === 'bottom_left' || handle === 'top_right') {\n\t\t\t\t\tnudge.x = -nudge.x\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// now resize the box after nudging, calculate the snaps again, and return the snap lines to match\n\t\t// the fully resized box\n\t\tconst snappedDelta = Vec.Add(dragDelta, nudge)\n\n\t\t// first figure out the new bounds of the selection\n\t\tconst { box: snappedResizedPageBounds } = Box.Resize(\n\t\t\tinitialSelectionPageBounds,\n\t\t\toriginalHandle,\n\t\t\tisResizingFromCenter ? snappedDelta.x * 2 : snappedDelta.x,\n\t\t\tisResizingFromCenter ? snappedDelta.y * 2 : snappedDelta.y,\n\t\t\tisAspectRatioLocked\n\t\t)\n\n\t\tif (isResizingFromCenter) {\n\t\t\t// reposition if resizing from center\n\t\t\tsnappedResizedPageBounds.center = initialSelectionPageBounds.center\n\t\t}\n\n\t\tconst snappedSelectionPoints = getResizeSnapPointsForHandle('any', snappedResizedPageBounds)\n\t\t// calculate snaps again using all points\n\t\tnearestSnapsX.length = 0\n\t\tnearestSnapsY.length = 0\n\t\tminOffset.x = 0\n\t\tminOffset.y = 0\n\n\t\tthis.collectPointSnaps({\n\t\t\tminOffset,\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t\totherNodeSnapPoints,\n\t\t\tselectionSnapPoints: snappedSelectionPoints,\n\t\t})\n\t\tconst pointSnaps = this.getPointSnapLines({\n\t\t\tnearestSnapsX,\n\t\t\tnearestSnapsY,\n\t\t})\n\n\t\tthis.manager.setIndicators([...pointSnaps])\n\n\t\treturn { nudge }\n\t}\n\n\tprivate collectPointSnaps({\n\t\tselectionSnapPoints,\n\t\totherNodeSnapPoints,\n\t\tminOffset,\n\t\tnearestSnapsX,\n\t\tnearestSnapsY,\n\t}: {\n\t\tselectionSnapPoints: BoundsSnapPoint[]\n\t\totherNodeSnapPoints: BoundsSnapPoint[]\n\t\tminOffset: Vec\n\t\tnearestSnapsX: NearestSnap[]\n\t\tnearestSnapsY: NearestSnap[]\n\t}) {\n\t\t// for each snap point on the bounding box of the selection, find the set of points\n\t\t// which are closest to it in each axis\n\t\tfor (const thisSnapPoint of selectionSnapPoints) {\n\t\t\tfor (const otherSnapPoint of otherNodeSnapPoints) {\n\t\t\t\tconst offset = Vec.Sub(thisSnapPoint, otherSnapPoint)\n\t\t\t\tconst offsetX = Math.abs(offset.x)\n\t\t\t\tconst offsetY = Math.abs(offset.y)\n\n\t\t\t\tif (round(offsetX) <= round(minOffset.x)) {\n\t\t\t\t\tif (round(offsetX) < round(minOffset.x)) {\n\t\t\t\t\t\t// we found a point that is significantly closer than all previous points\n\t\t\t\t\t\t// so wipe the slate clean and start over\n\t\t\t\t\t\tnearestSnapsX.length = 0\n\t\t\t\t\t}\n\n\t\t\t\t\tnearestSnapsX.push({\n\t\t\t\t\t\ttype: 'points',\n\t\t\t\t\t\tpoints: { thisPoint: thisSnapPoint, otherPoint: otherSnapPoint },\n\t\t\t\t\t\tnudge: otherSnapPoint.x - thisSnapPoint.x,\n\t\t\t\t\t})\n\t\t\t\t\tminOffset.x = offsetX\n\t\t\t\t}\n\n\t\t\t\tif (round(offsetY) <= round(minOffset.y)) {\n\t\t\t\t\tif (round(offsetY) < round(minOffset.y)) {\n\t\t\t\t\t\t// we found a point that is significantly closer than all previous points\n\t\t\t\t\t\t// so wipe the slate clean and start over\n\t\t\t\t\t\tnearestSnapsY.length = 0\n\t\t\t\t\t}\n\t\t\t\t\tnearestSnapsY.push({\n\t\t\t\t\t\ttype: 'points',\n\t\t\t\t\t\tpoints: { thisPoint: thisSnapPoint, otherPoint: otherSnapPoint },\n\t\t\t\t\t\tnudge: otherSnapPoint.y - thisSnapPoint.y,\n\t\t\t\t\t})\n\t\t\t\t\tminOffset.y = offsetY\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate collectGapSnaps({\n\t\tselectionPageBounds,\n\t\tminOffset,\n\t\tnearestSnapsX,\n\t\tnearestSnapsY,\n\t}: {\n\t\tselectionPageBounds: Box\n\t\tminOffset: Vec\n\t\tnearestSnapsX: NearestSnap[]\n\t\tnearestSnapsY: NearestSnap[]\n\t}) {\n\t\tconst { horizontal, vertical } = this.getVisibleGaps()\n\n\t\tfor (const gap of horizontal) {\n\t\t\t// ignore this gap if the selection doesn't overlap with it in the y axis\n\t\t\tif (\n\t\t\t\t!rangesOverlap(\n\t\t\t\t\tgap.breadthIntersection[0],\n\t\t\t\t\tgap.breadthIntersection[1],\n\t\t\t\t\tselectionPageBounds.minY,\n\t\t\t\t\tselectionPageBounds.maxY\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// check for center match\n\t\t\tconst gapMidX = gap.startEdge[0].x + gap.length / 2\n\t\t\tconst centerNudge = gapMidX - selectionPageBounds.center.x\n\t\t\tconst gapIsLargerThanSelection = gap.length > selectionPageBounds.width\n\n\t\t\tif (gapIsLargerThanSelection && round(Math.abs(centerNudge)) <= round(minOffset.x)) {\n\t\t\t\tif (round(Math.abs(centerNudge)) < round(minOffset.x)) {\n\t\t\t\t\t// reset if we found a closer snap\n\t\t\t\t\tnearestSnapsX.length = 0\n\t\t\t\t}\n\t\t\t\tminOffset.x = Math.abs(centerNudge)\n\n\t\t\t\tconst snap: NearestSnap = {\n\t\t\t\t\ttype: 'gap_center',\n\t\t\t\t\tgap,\n\t\t\t\t\tnudge: centerNudge,\n\t\t\t\t}\n\n\t\t\t\t// we need to avoid creating visual noise with too many center snaps in situations\n\t\t\t\t// where there are lots of adjacent items with even spacing\n\t\t\t\t// so let's only show other center snaps where the gap's breadth does not overlap with this one\n\t\t\t\t// i.e.\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2518\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2534\u2510 \u2502\n\t\t\t\t// \u2502 \u2502 \u253C\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u252C\u2518 \u2502\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502 \u25C4\u2500\u2500\u2500\u2500 i'm dragging this one\n\t\t\t\t// \u2514\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\t\t\t\t// \u2500\u2500\u2500\u2500\u2500\u25BA \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2534\u2510 \u2502 don't show these\n\t\t\t\t// show these \u2502 \u2502 \u253C larger gaps since\n\t\t\t\t// smaller \u2514\u2500\u2500\u2500\u2500\u2500\u252C\u2518 \u2502 \u25C4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 the smaller ones\n\t\t\t\t// gaps \u253C \u2502 cover the same\n\t\t\t\t// \u2500\u2500\u2500\u2500\u2500\u25BA \u250C\u2534\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2510 information\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\t\t\t\t//\n\t\t\t\t// but we want to show all of these ones since the gap breadths don't overlap\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2510 \u2514\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\t\t\t\t// \u2502 \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u252C\u2500\u2518 \u253C\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2510\n\t\t\t\t// \u2502 \u2502 \u25C4\u2500\u2500\u2500\u2500\u2500 i'm dragging this one\n\t\t\t\t// \u2514\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2518\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2510 \u253C\n\t\t\t\t// \u2502 \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u250C\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n\t\t\t\tconst otherCenterSnap = nearestSnapsX.find(({ type }) => type === 'gap_center') as\n\t\t\t\t\t| Extract<NearestSnap, { type: 'gap_center' }>\n\t\t\t\t\t| undefined\n\n\t\t\t\tconst gapBreadthsOverlap =\n\t\t\t\t\totherCenterSnap &&\n\t\t\t\t\trangeIntersection(\n\t\t\t\t\t\tgap.breadthIntersection[0],\n\t\t\t\t\t\tgap.breadthIntersection[1],\n\t\t\t\t\t\totherCenterSnap.gap.breadthIntersection[0],\n\t\t\t\t\t\totherCenterSnap.gap.breadthIntersection[1]\n\t\t\t\t\t)\n\n\t\t\t\t// if there is another center snap and it's bigger than this one, and it overlaps with this one, replace it\n\t\t\t\tif (otherCenterSnap && otherCenterSnap.gap.length > gap.length && gapBreadthsOverlap) {\n\t\t\t\t\tnearestSnapsX[nearestSnapsX.indexOf(otherCenterSnap)] = snap\n\t\t\t\t} else if (!otherCenterSnap || !gapBreadthsOverlap) {\n\t\t\t\t\tnearestSnapsX.push(snap)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// check for duplication left match\n\t\t\tconst duplicationLeftX = gap.startNode.pageBounds.minX - gap.length\n\t\t\tconst selectionRightX = selectionPageBounds.maxX\n\n\t\t\tconst duplicationLeftNudge = duplicationLeftX - selectionRightX\n\t\t\tif (round(Math.abs(duplicationLeftNudge)) <= round(minOffset.x)) {\n\t\t\t\tif (round(Math.abs(duplicationLeftNudge)) < round(minOffset.x)) {\n\t\t\t\t\t// reset if we found a closer snap\n\t\t\t\t\tnearestSnapsX.length = 0\n\t\t\t\t}\n\t\t\t\tminOffset.x = Math.abs(duplicationLeftNudge)\n\n\t\t\t\tnearestSnapsX.push({\n\t\t\t\t\ttype: 'gap_duplicate',\n\t\t\t\t\tgap,\n\t\t\t\t\tprotrusionDirection: 'left',\n\t\t\t\t\tnudge: duplicationLeftNudge,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// check for duplication right match\n\t\t\tconst duplicationRightX = gap.endNode.pageBounds.maxX + gap.length\n\t\t\tconst selectionLeftX = selectionPageBounds.minX\n\n\t\t\tconst duplicationRightNudge = duplicationRightX - selectionLeftX\n\t\t\tif (round(Math.abs(duplicationRightNudge)) <= round(minOffset.x)) {\n\t\t\t\tif (round(Math.abs(duplicationRightNudge)) < round(minOffset.x)) {\n\t\t\t\t\t// reset if we found a closer snap\n\t\t\t\t\tnearestSnapsX.length = 0\n\t\t\t\t}\n\t\t\t\tminOffset.x = Math.abs(duplicationRightNudge)\n\n\t\t\t\tnearestSnapsX.push({\n\t\t\t\t\ttype: 'gap_duplicate',\n\t\t\t\t\tgap,\n\t\t\t\t\tprotrusionDirection: 'right',\n\t\t\t\t\tnudge: duplicationRightNudge,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\tfor (const gap of vertical) {\n\t\t\t// ignore this gap if the selection doesn't overlap with it in the y axis\n\t\t\tif (\n\t\t\t\t!rangesOverlap(\n\t\t\t\t\tgap.breadthIntersection[0],\n\t\t\t\t\tgap.breadthIntersection[1],\n\t\t\t\t\tselectionPageBounds.minX,\n\t\t\t\t\tselectionPageBounds.maxX\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// check for center match\n\t\t\tconst gapMidY = gap.startEdge[0].y + gap.length / 2\n\t\t\tconst centerNudge = gapMidY - selectionPageBounds.center.y\n\n\t\t\tconst gapIsLargerThanSelection = gap.length > selectionPageBounds.height\n\n\t\t\tif (gapIsLargerThanSelection && round(Math.abs(centerNudge)) <= round(minOffset.y)) {\n\t\t\t\tif (round(Math.abs(centerNudge)) < round(minOffset.y)) {\n\t\t\t\t\t// reset if we found a closer snap\n\t\t\t\t\tnearestSnapsY.length = 0\n\t\t\t\t}\n\t\t\t\tminOffset.y = Math.abs(centerNudge)\n\n\t\t\t\tconst snap: NearestSnap = {\n\t\t\t\t\ttype: 'gap_center',\n\t\t\t\t\tgap,\n\t\t\t\t\tnudge: centerNudge,\n\t\t\t\t}\n\n\t\t\t\t// we need to avoid creating visual noise with too many center snaps in situations\n\t\t\t\t// where there are lots of adjacent items with even spacing\n\t\t\t\t// so let's only show other center snaps where the gap's breadth does not overlap with this one\n\t\t\t\t// i.e.\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2518\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2534\u2510 \u2502\n\t\t\t\t// \u2502 \u2502 \u253C\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u252C\u2518 \u2502\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502 \u25C4\u2500\u2500\u2500\u2500 i'm dragging this one\n\t\t\t\t// \u2514\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\t\t\t\t// \u2500\u2500\u2500\u2500\u2500\u25BA \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2534\u2510 \u2502 don't show these\n\t\t\t\t// show these \u2502 \u2502 \u253C larger gaps since\n\t\t\t\t// smaller \u2514\u2500\u2500\u2500\u2500\u2500\u252C\u2518 \u2502 \u25C4\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 the smaller ones\n\t\t\t\t// gaps \u253C \u2502 cover the same\n\t\t\t\t// \u2500\u2500\u2500\u2500\u2500\u25BA \u250C\u2534\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2510 information\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\t\t\t\t//\n\t\t\t\t// but we want to show all of these ones since the gap breadths don't overlap\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2500\u2500\u2510 \u2514\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\t\t\t\t// \u2502 \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u252C\u2500\u2518 \u253C\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2510\n\t\t\t\t// \u2502 \u2502 \u25C4\u2500\u2500\u2500\u2500\u2500 i'm dragging this one\n\t\t\t\t// \u2514\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2518\n\t\t\t\t// \u253C \u2502\n\t\t\t\t// \u250C\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2510 \u253C\n\t\t\t\t// \u2502 \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u250C\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\t\t\t\t// \u2502 \u2502\n\t\t\t\t// \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n\t\t\t\tconst otherCenterSnap = nearestSnapsY.find(({ type }) => type === 'gap_center') as\n\t\t\t\t\t| Extract<NearestSnap, { type: 'gap_center' }>\n\t\t\t\t\t| undefined\n\n\t\t\t\tconst gapBreadthsOverlap =\n\t\t\t\t\totherCenterSnap &&\n\t\t\t\t\trangesOverlap(\n\t\t\t\t\t\totherCenterSnap.gap.breadthIntersection[0],\n\t\t\t\t\t\totherCenterSnap.gap.breadthIntersection[1],\n\t\t\t\t\t\tgap.breadthIntersection[0],\n\t\t\t\t\t\tgap.breadthIntersection[1]\n\t\t\t\t\t)\n\n\t\t\t\t// if there is another center snap and it's bigger than this one, and it overlaps with this one, replace it\n\t\t\t\tif (otherCenterSnap && otherCenterSnap.gap.length > gap.length && gapBreadthsOverlap) {\n\t\t\t\t\tnearestSnapsY[nearestSnapsY.indexOf(otherCenterSnap)] = snap\n\t\t\t\t} else if (!otherCenterSnap || !gapBreadthsOverlap) {\n\t\t\t\t\tnearestSnapsY.push(snap)\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// check for duplication top match\n\t\t\tconst duplicationTopY = gap.startNode.pageBounds.minY - gap.length\n\t\t\tconst selectionBottomY = selectionPageBounds.maxY\n\n\t\t\tconst duplicationTopNudge = duplicationTopY - selectionBottomY\n\t\t\tif (round(Math.abs(duplicationTopNudge)) <= round(minOffset.y)) {\n\t\t\t\tif (round(Math.abs(duplicationTopNudge)) < round(minOffset.y)) {\n\t\t\t\t\t// reset if we found a closer snap\n\t\t\t\t\tnearestSnapsY.length = 0\n\t\t\t\t}\n\t\t\t\tminOffset.y = Math.abs(duplicationTopNudge)\n\n\t\t\t\tnearestSnapsY.push({\n\t\t\t\t\ttype: 'gap_duplicate',\n\t\t\t\t\tgap,\n\t\t\t\t\tprotrusionDirection: 'top',\n\t\t\t\t\tnudge: duplicationTopNudge,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// check for duplication bottom match\n\t\t\tconst duplicationBottomY = gap.endNode.pageBounds.maxY + gap.length\n\t\t\tconst selectionTopY = selectionPageBounds.minY\n\n\t\t\tconst duplicationBottomNudge = duplicationBottomY - selectionTopY\n\t\t\tif (round(Math.abs(duplicationBottomNudge)) <= round(minOffset.y)) {\n\t\t\t\tif (round(Math.abs(duplicationBottomNudge)) < round(minOffset.y)) {\n\t\t\t\t\t// reset if we found a closer snap\n\t\t\t\t\tnearestSnapsY.length = 0\n\t\t\t\t}\n\t\t\t\tminOffset.y = Math.abs(duplicationBottomNudge)\n\n\t\t\t\tnearestSnapsY.push({\n\t\t\t\t\ttype: 'gap_duplicate',\n\t\t\t\t\tgap,\n\t\t\t\t\tprotrusionDirection: 'bottom',\n\t\t\t\t\tnudge: duplicationBottomNudge,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate getPointSnapLines({\n\t\tnearestSnapsX,\n\t\tnearestSnapsY,\n\t}: {\n\t\tnearestSnapsX: NearestSnap[]\n\t\tnearestSnapsY: NearestSnap[]\n\t}): PointsSnapIndicator[] {\n\t\t// point snaps may align on multiple parallel lines so we need to split the pairs\n\t\t// into groups based on where they are in their their snap axes\n\t\tconst snapGroupsX = {} as { [key: string]: SnapPair[] }\n\t\tconst snapGroupsY = {} as { [key: string]: SnapPair[] }\n\n\t\tif (nearestSnapsX.length > 0) {\n\t\t\tfor (const snap of nearestSnapsX) {\n\t\t\t\tif (snap.type === 'points') {\n\t\t\t\t\tconst key = round(snap.points.otherPoint.x)\n\t\t\t\t\tif (!snapGroupsX[key]) {\n\t\t\t\t\t\tsnapGroupsX[key] = []\n\t\t\t\t\t}\n\t\t\t\t\tsnapGroupsX[key].push(snap.points)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (nearestSnapsY.length > 0) {\n\t\t\tfor (const snap of nearestSnapsY) {\n\t\t\t\tif (snap.type === 'points') {\n\t\t\t\t\tconst key = round(snap.points.otherPoint.y)\n\t\t\t\t\tif (!snapGroupsY[key]) {\n\t\t\t\t\t\tsnapGroupsY[key] = []\n\t\t\t\t\t}\n\t\t\t\t\tsnapGroupsY[key].push(snap.points)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// and finally create all the snap lines for the UI to render\n\t\treturn Object.values(snapGroupsX)\n\t\t\t.concat(Object.values(snapGroupsY))\n\t\t\t.map((snapGroup) => ({\n\t\t\t\tid: uniqueId(),\n\t\t\t\ttype: 'points',\n\t\t\t\tpoints: dedupe(\n\t\t\t\t\tsnapGroup\n\t\t\t\t\t\t.map((snap) => Vec.From(snap.otherPoint))\n\t\t\t\t\t\t// be sure to nudge over the selection snap points\n\t\t\t\t\t\t.concat(snapGroup.map((snap) => Vec.From(snap.thisPoint))),\n\t\t\t\t\t(a: Vec, b: Vec) => a.equals(b)\n\t\t\t\t),\n\t\t\t}))\n\t}\n\n\tprivate getGapSnapLines({\n\t\tselectionPageBounds,\n\t\tnearestSnapsX,\n\t\tnearestSnapsY,\n\t}: {\n\t\tselectionPageBounds: Box\n\t\tnearestSnapsX: NearestSnap[]\n\t\tnearestSnapsY: NearestSnap[]\n\t}): GapsSnapIndicator[] {\n\t\tconst { vertical, horizontal } = this.getVisibleGaps()\n\n\t\tconst selectionSides: Record<SelectionEdge, [Vec, Vec]> = {\n\t\t\ttop: selectionPageBounds.sides[0],\n\t\t\tright: selectionPageBounds.sides[1],\n\t\t\t// need bottom and left to be sorted asc, which .sides is not.\n\t\t\tbottom: [selectionPageBounds.corners[3], selectionPageBounds.corners[2]],\n\t\t\tleft: [selectionPageBounds.corners[0], selectionPageBounds.corners[3]],\n\t\t}\n\n\t\tconst result: GapsSnapIndicator[] = []\n\n\t\tif (nearestSnapsX.length > 0) {\n\t\t\tfor (const snap of nearestSnapsX) {\n\t\t\t\tif (snap.type === 'points') continue\n\n\t\t\t\tconst {\n\t\t\t\t\tgap: { breadthIntersection, startEdge, startNode, endNode, length, endEdge },\n\t\t\t\t} = snap\n\n\t\t\t\tswitch (snap.type) {\n\t\t\t\t\tcase 'gap_center': {\n\t\t\t\t\t\t// create\n\t\t\t\t\t\tconst newGapsLength = (length - selectionPageBounds.width) / 2\n\t\t\t\t\t\tconst gapBreadthIntersection = rangeIntersection(\n\t\t\t\t\t\t\tbreadthIntersection[0],\n\t\t\t\t\t\t\tbreadthIntersection[1],\n\t\t\t\t\t\t\tselectionPageBounds.minY,\n\t\t\t\t\t\t\tselectionPageBounds.maxY\n\t\t\t\t\t\t)!\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\ttype: 'gaps',\n\t\t\t\t\t\t\tdirection: 'horizontal',\n\t\t\t\t\t\t\tid: uniqueId(),\n\t\t\t\t\t\t\tgaps: [\n\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\thorizontal,\n\t\t\t\t\t\t\t\t\tstartNode.id,\n\t\t\t\t\t\t\t\t\tnewGapsLength,\n\t\t\t\t\t\t\t\t\t'backward',\n\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstartEdge,\n\t\t\t\t\t\t\t\t\tendEdge: selectionSides.left,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstartEdge: selectionSides.right,\n\t\t\t\t\t\t\t\t\tendEdge,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\thorizontal,\n\t\t\t\t\t\t\t\t\tendNode.id,\n\t\t\t\t\t\t\t\t\tnewGapsLength,\n\t\t\t\t\t\t\t\t\t'forward',\n\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t})\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'gap_duplicate': {\n\t\t\t\t\t\t// create\n\t\t\t\t\t\tconst gapBreadthIntersection = rangeIntersection(\n\t\t\t\t\t\t\tbreadthIntersection[0],\n\t\t\t\t\t\t\tbreadthIntersection[1],\n\t\t\t\t\t\t\tselectionPageBounds.minY,\n\t\t\t\t\t\t\tselectionPageBounds.maxY\n\t\t\t\t\t\t)!\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\ttype: 'gaps',\n\t\t\t\t\t\t\tdirection: 'horizontal',\n\t\t\t\t\t\t\tid: uniqueId(),\n\t\t\t\t\t\t\tgaps:\n\t\t\t\t\t\t\t\tsnap.protrusionDirection === 'left'\n\t\t\t\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tstartEdge: selectionSides.right,\n\t\t\t\t\t\t\t\t\t\t\t\tendEdge: startEdge.map((v) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\tv.clone().addXY(-startNode.pageBounds.width, 0)\n\t\t\t\t\t\t\t\t\t\t\t\t) as [Vec, Vec],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{ startEdge, endEdge },\n\t\t\t\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\t\t\t\thorizontal,\n\t\t\t\t\t\t\t\t\t\t\t\tendNode.id,\n\t\t\t\t\t\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\t\t\t\t\t\t'forward',\n\t\t\t\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\t\t\t\thorizontal,\n\t\t\t\t\t\t\t\t\t\t\t\tstartNode.id,\n\t\t\t\t\t\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\t\t\t\t\t\t'backward',\n\t\t\t\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t{ startEdge, endEdge },\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tstartEdge: endEdge.map((v) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\tv.clone().addXY(snap.gap.endNode.pageBounds.width, 0)\n\t\t\t\t\t\t\t\t\t\t\t\t) as [Vec, Vec],\n\t\t\t\t\t\t\t\t\t\t\t\tendEdge: selectionSides.left,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t})\n\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (nearestSnapsY.length > 0) {\n\t\t\tfor (const snap of nearestSnapsY) {\n\t\t\t\tif (snap.type === 'points') continue\n\n\t\t\t\tconst {\n\t\t\t\t\tgap: { breadthIntersection, startEdge, startNode, endNode, length, endEdge },\n\t\t\t\t} = snap\n\n\t\t\t\tswitch (snap.type) {\n\t\t\t\t\tcase 'gap_center': {\n\t\t\t\t\t\tconst newGapsLength = (length - selectionPageBounds.height) / 2\n\t\t\t\t\t\tconst gapBreadthIntersection = rangeIntersection(\n\t\t\t\t\t\t\tbreadthIntersection[0],\n\t\t\t\t\t\t\tbreadthIntersection[1],\n\t\t\t\t\t\t\tselectionPageBounds.minX,\n\t\t\t\t\t\t\tselectionPageBounds.maxX\n\t\t\t\t\t\t)!\n\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\ttype: 'gaps',\n\t\t\t\t\t\t\tdirection: 'vertical',\n\t\t\t\t\t\t\tid: uniqueId(),\n\t\t\t\t\t\t\tgaps: [\n\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\tvertical,\n\t\t\t\t\t\t\t\t\tstartNode.id,\n\t\t\t\t\t\t\t\t\tnewGapsLength,\n\t\t\t\t\t\t\t\t\t'backward',\n\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstartEdge,\n\t\t\t\t\t\t\t\t\tendEdge: selectionSides.top,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tstartEdge: selectionSides.bottom,\n\t\t\t\t\t\t\t\t\tendEdge,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\tvertical,\n\t\t\t\t\t\t\t\t\tsnap.gap.endNode.id,\n\t\t\t\t\t\t\t\t\tnewGapsLength,\n\t\t\t\t\t\t\t\t\t'forward',\n\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t})\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'gap_duplicate':\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tconst gapBreadthIntersection = rangeIntersection(\n\t\t\t\t\t\t\t\tbreadthIntersection[0],\n\t\t\t\t\t\t\t\tbreadthIntersection[1],\n\t\t\t\t\t\t\t\tselectionPageBounds.minX,\n\t\t\t\t\t\t\t\tselectionPageBounds.maxX\n\t\t\t\t\t\t\t)!\n\n\t\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\t\ttype: 'gaps',\n\t\t\t\t\t\t\t\tdirection: 'vertical',\n\t\t\t\t\t\t\t\tid: uniqueId(),\n\t\t\t\t\t\t\t\tgaps:\n\t\t\t\t\t\t\t\t\tsnap.protrusionDirection === 'top'\n\t\t\t\t\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tstartEdge: selectionSides.bottom,\n\t\t\t\t\t\t\t\t\t\t\t\t\tendEdge: startEdge.map((v) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tv.clone().addXY(0, -startNode.pageBounds.height)\n\t\t\t\t\t\t\t\t\t\t\t\t\t) as [Vec, Vec],\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t{ startEdge, endEdge },\n\t\t\t\t\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\t\t\t\t\tvertical,\n\t\t\t\t\t\t\t\t\t\t\t\t\tendNode.id,\n\t\t\t\t\t\t\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\t\t\t\t\t\t\t'forward',\n\t\t\t\t\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\t\t\t\t\t...findAdjacentGaps(\n\t\t\t\t\t\t\t\t\t\t\t\t\tvertical,\n\t\t\t\t\t\t\t\t\t\t\t\t\tstartNode.id,\n\t\t\t\t\t\t\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\t\t\t\t\t\t\t'backward',\n\t\t\t\t\t\t\t\t\t\t\t\t\tgapBreadthIntersection\n\t\t\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t\t\t\t{ startEdge, endEdge },\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\tstartEdge: endEdge.map((v) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tv.clone().addXY(0, endNode.pageBounds.height)\n\t\t\t\t\t\t\t\t\t\t\t\t\t) as [Vec, Vec],\n\t\t\t\t\t\t\t\t\t\t\t\t\tendEdge: selectionSides.top,\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdedupeGapSnaps(result)\n\t\treturn result\n\t}\n}\n\nfunction getResizeSnapPointsForHandle(\n\thandle: SelectionCorner | SelectionEdge | 'any',\n\tselectionPageBounds: Box\n): BoundsSnapPoint[] {\n\tconst { minX, maxX, minY, maxY } = selectionPageBounds\n\tconst result: BoundsSnapPoint[] = []\n\n\t// top left corner\n\tswitch (handle) {\n\t\tcase 'top':\n\t\tcase 'left':\n\t\tcase 'top_left':\n\t\tcase 'any':\n\t\t\tresult.push({\n\t\t\t\tid: 'top_left',\n\t\t\t\thandle: 'top_left',\n\t\t\t\tx: minX,\n\t\t\t\ty: minY,\n\t\t\t})\n\t}\n\n\t// top right corner\n\tswitch (handle) {\n\t\tcase 'top':\n\t\tcase 'right':\n\t\tcase 'top_right':\n\t\tcase 'any':\n\t\t\tresult.push({\n\t\t\t\tid: 'top_right',\n\t\t\t\thandle: 'top_right',\n\t\t\t\tx: maxX,\n\t\t\t\ty: minY,\n\t\t\t})\n\t}\n\n\t// bottom right corner\n\tswitch (handle) {\n\t\tcase 'bottom':\n\t\tcase 'right':\n\t\tcase 'bottom_right':\n\t\tcase 'any':\n\t\t\tresult.push({\n\t\t\t\tid: 'bottom_right',\n\t\t\t\thandle: 'bottom_right',\n\t\t\t\tx: maxX,\n\t\t\t\ty: maxY,\n\t\t\t})\n\t}\n\n\t// bottom left corner\n\tswitch (handle) {\n\t\tcase 'bottom':\n\t\tcase 'left':\n\t\tcase 'bottom_left':\n\t\tcase 'any':\n\t\t\tresult.push({\n\t\t\t\tid: 'bottom_left',\n\t\t\t\thandle: 'bottom_left',\n\t\t\t\tx: minX,\n\t\t\t\ty: maxY,\n\t\t\t})\n\t}\n\n\treturn result\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,65 +1,24 @@
1
- var __create = Object.create;
2
1
  var __defProp = Object.defineProperty;
3
2
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
5
- var __typeError = (msg) => {
6
- throw TypeError(msg);
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result) __defProp(target, key, result);
9
+ return result;
7
10
  };
8
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
10
- var __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
11
- var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
12
- var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
13
- var __decoratorContext = (kind, name, done, metadata, fns) => ({ kind: __decoratorStrings[kind], name, metadata, addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null)) });
14
- var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
15
- var __runInitializers = (array, flags, self, value) => {
16
- for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) flags & 1 ? fns[i].call(self) : value = fns[i].call(self, value);
17
- return value;
18
- };
19
- var __decorateElement = (array, flags, name, decorators, target, extra) => {
20
- var fn, it, done, ctx, access, k = flags & 7, s = !!(flags & 8), p = !!(flags & 16);
21
- var j = k > 3 ? array.length + 1 : k ? s ? 1 : 2 : 0, key = __decoratorStrings[k + 5];
22
- var initializers = k > 3 && (array[j - 1] = []), extraInitializers = array[j] || (array[j] = []);
23
- var desc = k && (!p && !s && (target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(k < 4 ? target : { get [name]() {
24
- return __privateGet(this, extra);
25
- }, set [name](x) {
26
- return __privateSet(this, extra, x);
27
- } }, name));
28
- k ? p && k < 4 && __name(extra, (k > 2 ? "set " : k > 1 ? "get " : "") + name) : __name(target, name);
29
- for (var i = decorators.length - 1; i >= 0; i--) {
30
- ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
31
- if (k) {
32
- ctx.static = s, ctx.private = p, access = ctx.access = { has: p ? (x) => __privateIn(target, x) : (x) => name in x };
33
- if (k ^ 3) access.get = p ? (x) => (k ^ 1 ? __privateGet : __privateMethod)(x, target, k ^ 4 ? extra : desc.get) : (x) => x[name];
34
- if (k > 2) access.set = p ? (x, y) => __privateSet(x, target, y, k ^ 4 ? extra : desc.set) : (x, y) => x[name] = y;
35
- }
36
- it = (0, decorators[i])(k ? k < 4 ? p ? extra : desc[key] : k > 4 ? void 0 : { get: desc.get, set: desc.set } : target, ctx), done._ = 1;
37
- if (k ^ 4 || it === void 0) __expectFn(it) && (k > 4 ? initializers.unshift(it) : k ? p ? extra = it : desc[key] = it : target = it);
38
- else if (typeof it !== "object" || it === null) __typeError("Object expected");
39
- else __expectFn(fn = it.get) && (desc.get = fn), __expectFn(fn = it.set) && (desc.set = fn), __expectFn(fn = it.init) && initializers.unshift(fn);
40
- }
41
- return k || __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
42
- };
43
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
44
- var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
45
- var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use the "in" operator on this value') : member.has(obj);
46
- var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
47
- var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
48
- var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
49
- var _getSnapGeometryCache_dec, _init;
50
11
  import { computed } from "@tldraw/state";
51
12
  import { assertExists, uniqueId } from "@tldraw/utils";
52
13
  import { Vec } from "../../../primitives/Vec.mjs";
53
14
  const defaultGetSelfSnapOutline = () => null;
54
15
  const defaultGetSelfSnapPoints = () => [];
55
- _getSnapGeometryCache_dec = [computed];
56
16
  class HandleSnaps {
57
17
  constructor(manager) {
58
18
  this.manager = manager;
59
- __runInitializers(_init, 5, this);
60
- __publicField(this, "editor");
61
19
  this.editor = manager.editor;
62
20
  }
21
+ editor;
63
22
  getSnapGeometryCache() {
64
23
  const { editor } = this;
65
24
  return editor.store.createComputedCache("handle snap geometry", (shape) => {
@@ -219,9 +178,9 @@ class HandleSnaps {
219
178
  return null;
220
179
  }
221
180
  }
222
- _init = __decoratorStart(null);
223
- __decorateElement(_init, 1, "getSnapGeometryCache", _getSnapGeometryCache_dec, HandleSnaps);
224
- __decoratorMetadata(_init, HandleSnaps);
181
+ __decorateClass([
182
+ computed
183
+ ], HandleSnaps.prototype, "getSnapGeometryCache", 1);
225
184
  export {
226
185
  HandleSnaps
227
186
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/lib/editor/managers/SnapManager/HandleSnaps.ts"],
4
- "sourcesContent": ["import { computed } from '@tldraw/state'\nimport { TLHandle, TLShape, TLShapeId, VecModel } from '@tldraw/tlschema'\nimport { assertExists, uniqueId } from '@tldraw/utils'\nimport { Vec } from '../../../primitives/Vec'\nimport { Geometry2d } from '../../../primitives/geometry/Geometry2d'\nimport type { Editor } from '../../Editor'\nimport type { PointsSnapIndicator, SnapData, SnapManager } from './SnapManager'\n\n/**\n * When dragging a handle, users can snap the handle to key geometry on other nearby shapes.\n * Customize how handles snap to a shape by returning this from\n * {@link ShapeUtil.getHandleSnapGeometry}.\n *\n * Any co-ordinates here should be in the shape's local space.\n *\n * @public\n */\nexport interface HandleSnapGeometry {\n\t/**\n\t * A `Geometry2d` that describe the outline of the shape that the handle will snap to - fills\n\t * are ignored. By default, this is the same geometry returned by {@link ShapeUtil.getGeometry}.\n\t * Set this to `null` to disable handle snapping to this shape's outline.\n\t */\n\toutline?: Geometry2d | null\n\t/**\n\t * Key points on the shape that the handle will snap to. For example, the corners of a\n\t * rectangle, or the centroid of a triangle. By default, no points are used.\n\t */\n\tpoints?: VecModel[]\n\t/**\n\t * By default, handles can't snap to their own shape because moving the handle might change the\n\t * snapping location which can cause feedback loops. You can override this by returning a\n\t * version of `outline` that won't be affected by the current handle's position to use for\n\t * self-snapping.\n\t */\n\tgetSelfSnapOutline?(handle: TLHandle): Geometry2d | null\n\t/**\n\t * By default, handles can't snap to their own shape because moving the handle might change the\n\t * snapping location which can cause feedback loops. You can override this by returning a\n\t * version of `points` that won't be affected by the current handle's position to use for\n\t * self-snapping.\n\t */\n\tgetSelfSnapPoints?(handle: TLHandle): VecModel[]\n}\n\ninterface AlignPointsSnap {\n\tsnaps: PointsSnapIndicator[]\n\tnudge: Vec\n}\n\nconst defaultGetSelfSnapOutline = () => null\nconst defaultGetSelfSnapPoints = () => []\n/** @public */\nexport class HandleSnaps {\n\treadonly editor: Editor\n\tconstructor(readonly manager: SnapManager) {\n\t\tthis.editor = manager.editor\n\t}\n\n\t@computed private getSnapGeometryCache() {\n\t\tconst { editor } = this\n\t\treturn editor.store.createComputedCache('handle snap geometry', (shape: TLShape) => {\n\t\t\tconst snapGeometry = editor.getShapeUtil(shape).getHandleSnapGeometry(shape)\n\t\t\tconst getSelfSnapOutline = snapGeometry.getSelfSnapOutline\n\t\t\t\t? snapGeometry.getSelfSnapOutline.bind(snapGeometry)\n\t\t\t\t: defaultGetSelfSnapOutline\n\t\t\tconst getSelfSnapPoints = snapGeometry.getSelfSnapPoints\n\t\t\t\t? snapGeometry.getSelfSnapPoints.bind(snapGeometry)\n\t\t\t\t: defaultGetSelfSnapPoints\n\n\t\t\treturn {\n\t\t\t\toutline:\n\t\t\t\t\tsnapGeometry.outline === undefined\n\t\t\t\t\t\t? editor.getShapeGeometry(shape)\n\t\t\t\t\t\t: snapGeometry.outline,\n\n\t\t\t\tpoints: snapGeometry.points ?? [],\n\t\t\t\tgetSelfSnapOutline,\n\t\t\t\tgetSelfSnapPoints,\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate *iterateSnapPointsInPageSpace(currentShapeId: TLShapeId, currentHandle: TLHandle) {\n\t\tconst selfSnapPoints = this.getSnapGeometryCache()\n\t\t\t.get(currentShapeId)\n\t\t\t?.getSelfSnapPoints(currentHandle)\n\t\tif (selfSnapPoints && selfSnapPoints.length) {\n\t\t\tconst shapePageTransform = assertExists(this.editor.getShapePageTransform(currentShapeId))\n\t\t\tfor (const point of selfSnapPoints) {\n\t\t\t\tyield shapePageTransform.applyToPoint(point)\n\t\t\t}\n\t\t}\n\n\t\tfor (const shapeId of this.manager.getSnappableShapes()) {\n\t\t\tif (shapeId === currentShapeId) continue\n\t\t\tconst snapPoints = this.getSnapGeometryCache().get(shapeId)?.points\n\t\t\tif (!snapPoints || !snapPoints.length) continue\n\n\t\t\tconst shapePageTransform = assertExists(this.editor.getShapePageTransform(shapeId))\n\t\t\tfor (const point of snapPoints) {\n\t\t\t\tyield shapePageTransform.applyToPoint(point)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate *iterateSnapOutlines(currentShapeId: TLShapeId, currentHandle: TLHandle) {\n\t\tconst selfSnapOutline = this.getSnapGeometryCache()\n\t\t\t.get(currentShapeId)\n\t\t\t?.getSelfSnapOutline(currentHandle)\n\t\tif (selfSnapOutline) {\n\t\t\tyield { shapeId: currentShapeId, outline: selfSnapOutline }\n\t\t}\n\n\t\tfor (const shapeId of this.manager.getSnappableShapes()) {\n\t\t\tif (shapeId === currentShapeId) continue\n\n\t\t\tconst snapOutline = this.getSnapGeometryCache().get(shapeId)?.outline\n\t\t\tif (!snapOutline) continue\n\n\t\t\tyield { shapeId, outline: snapOutline }\n\t\t}\n\t}\n\n\tprivate getHandleSnapPosition({\n\t\tcurrentShapeId,\n\t\thandle,\n\t\thandleInPageSpace,\n\t}: {\n\t\tcurrentShapeId: TLShapeId\n\t\thandle: TLHandle\n\t\thandleInPageSpace: Vec\n\t}): Vec | null {\n\t\tconst snapThreshold = this.manager.getSnapThreshold()\n\n\t\t// We snap to two different parts of the shape's handle snap geometry:\n\t\t// 1. The `points`. These are handles or other key points that we want to snap to with a\n\t\t// higher priority than the normal outline snapping.\n\t\t// 2. The `outline`. This describes the outline of the shape, and we just snap to the\n\t\t// nearest point on that outline.\n\n\t\t// Start with the points:\n\t\tlet minDistanceForSnapPoint = snapThreshold\n\t\tlet nearestSnapPoint: Vec | null = null\n\t\tfor (const snapPoint of this.iterateSnapPointsInPageSpace(currentShapeId, handle)) {\n\t\t\tif (Vec.DistMin(handleInPageSpace, snapPoint, minDistanceForSnapPoint)) {\n\t\t\t\tminDistanceForSnapPoint = Vec.Dist(handleInPageSpace, snapPoint)\n\t\t\t\tnearestSnapPoint = snapPoint\n\t\t\t}\n\t\t}\n\n\t\t// if we found a snap point, return it - we don't need to check the outlines because points\n\t\t// have a higher priority\n\t\tif (nearestSnapPoint) return nearestSnapPoint\n\n\t\tlet minDistanceForOutline = snapThreshold\n\t\tlet nearestPointOnOutline: Vec | null = null\n\n\t\tfor (const { shapeId, outline } of this.iterateSnapOutlines(currentShapeId, handle)) {\n\t\t\tconst shapePageTransform = assertExists(this.editor.getShapePageTransform(shapeId))\n\t\t\tconst pointInShapeSpace = this.editor.getPointInShapeSpace(shapeId, handleInPageSpace)\n\n\t\t\tconst nearestShapePointInShapeSpace = outline.nearestPoint(pointInShapeSpace)\n\t\t\tconst nearestInPageSpace = shapePageTransform.applyToPoint(nearestShapePointInShapeSpace)\n\n\t\t\tif (Vec.DistMin(handleInPageSpace, nearestInPageSpace, minDistanceForOutline)) {\n\t\t\t\tminDistanceForOutline = Vec.Dist(handleInPageSpace, nearestInPageSpace)\n\t\t\t\tnearestPointOnOutline = nearestInPageSpace\n\t\t\t}\n\t\t}\n\n\t\t// if we found a point on the outline, return it\n\t\tif (nearestPointOnOutline) return nearestPointOnOutline\n\n\t\t// if not, there's no nearby snap point\n\t\treturn null\n\t}\n\n\tprivate getHandleSnapData({\n\t\thandle,\n\t\tcurrentShapeId,\n\t}: {\n\t\thandle: TLHandle\n\t\tcurrentShapeId: TLShapeId\n\t}): AlignPointsSnap | null {\n\t\tconst snapThreshold = this.manager.getSnapThreshold()\n\t\tconst currentShapeTransform = assertExists(this.editor.getShapePageTransform(currentShapeId))\n\t\tconst handleInPageSpace = currentShapeTransform.applyToPoint(handle)\n\n\t\tlet nearestXSnap: Vec | null = null\n\t\tlet nearestYSnap: Vec | null = null\n\t\tlet minOffsetX = snapThreshold\n\t\tlet minOffsetY = snapThreshold\n\n\t\tfor (const snapPoint of this.iterateSnapPointsInPageSpace(currentShapeId, handle)) {\n\t\t\tconst offsetX = Math.abs(handleInPageSpace.x - snapPoint.x)\n\t\t\tconst offsetY = Math.abs(handleInPageSpace.y - snapPoint.y)\n\t\t\tif (offsetX < minOffsetX) {\n\t\t\t\tminOffsetX = offsetX\n\t\t\t\tnearestXSnap = snapPoint\n\t\t\t}\n\t\t\tif (offsetY < minOffsetY) {\n\t\t\t\tminOffsetY = offsetY\n\t\t\t\tnearestYSnap = snapPoint\n\t\t\t}\n\t\t}\n\n\t\tif (!nearestXSnap && !nearestYSnap) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst nudge = new Vec(\n\t\t\tnearestXSnap ? nearestXSnap.x - handleInPageSpace.x : 0,\n\t\t\tnearestYSnap ? nearestYSnap.y - handleInPageSpace.y : 0\n\t\t)\n\n\t\tconst snappedHandle = Vec.Add(handleInPageSpace, nudge)\n\t\tconst snaps: PointsSnapIndicator[] = []\n\n\t\tif (nearestXSnap) {\n\t\t\tconst snappedHandleOnX = new Vec(nearestXSnap.x, snappedHandle.y)\n\t\t\tsnaps.push({\n\t\t\t\tid: uniqueId(),\n\t\t\t\ttype: 'points',\n\t\t\t\tpoints: [nearestXSnap, snappedHandleOnX],\n\t\t\t})\n\t\t}\n\t\tif (nearestYSnap) {\n\t\t\tconst snappedHandleOnY = new Vec(snappedHandle.x, nearestYSnap.y)\n\t\t\tsnaps.push({\n\t\t\t\tid: uniqueId(),\n\t\t\t\ttype: 'points',\n\t\t\t\tpoints: [nearestYSnap, snappedHandleOnY],\n\t\t\t})\n\t\t}\n\n\t\treturn { snaps, nudge }\n\t}\n\n\tsnapHandle({\n\t\tcurrentShapeId,\n\t\thandle,\n\t}: {\n\t\tcurrentShapeId: TLShapeId\n\t\thandle: TLHandle\n\t}): SnapData | null {\n\t\tconst currentShapeTransform = assertExists(this.editor.getShapePageTransform(currentShapeId))\n\t\tconst handleInPageSpace = currentShapeTransform.applyToPoint(handle)\n\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\tconst snapType = handle.canSnap ? 'point' : handle.snapType\n\n\t\tif (snapType === 'point') {\n\t\t\tconst snapPosition = this.getHandleSnapPosition({ currentShapeId, handle, handleInPageSpace })\n\n\t\t\tif (!snapPosition) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tthis.manager.setIndicators([\n\t\t\t\t{\n\t\t\t\t\tid: uniqueId(),\n\t\t\t\t\ttype: 'points',\n\t\t\t\t\tpoints: [snapPosition],\n\t\t\t\t},\n\t\t\t])\n\n\t\t\treturn { nudge: Vec.Sub(snapPosition, handleInPageSpace) }\n\t\t}\n\n\t\tif (snapType === 'align') {\n\t\t\tconst snapData = this.getHandleSnapData({\n\t\t\t\thandle,\n\t\t\t\tcurrentShapeId,\n\t\t\t})\n\n\t\t\tif (!snapData) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tthis.manager.setIndicators(snapData.snaps)\n\n\t\t\treturn { nudge: snapData.nudge }\n\t\t}\n\n\t\treturn null\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { computed } from '@tldraw/state'\nimport { TLHandle, TLShape, TLShapeId, VecModel } from '@tldraw/tlschema'\nimport { assertExists, uniqueId } from '@tldraw/utils'\nimport { Geometry2d } from '../../../primitives/geometry/Geometry2d'\nimport { Vec } from '../../../primitives/Vec'\nimport type { Editor } from '../../Editor'\nimport type { PointsSnapIndicator, SnapData, SnapManager } from './SnapManager'\n\n/**\n * When dragging a handle, users can snap the handle to key geometry on other nearby shapes.\n * Customize how handles snap to a shape by returning this from\n * {@link ShapeUtil.getHandleSnapGeometry}.\n *\n * Any co-ordinates here should be in the shape's local space.\n *\n * @public\n */\nexport interface HandleSnapGeometry {\n\t/**\n\t * A `Geometry2d` that describe the outline of the shape that the handle will snap to - fills\n\t * are ignored. By default, this is the same geometry returned by {@link ShapeUtil.getGeometry}.\n\t * Set this to `null` to disable handle snapping to this shape's outline.\n\t */\n\toutline?: Geometry2d | null\n\t/**\n\t * Key points on the shape that the handle will snap to. For example, the corners of a\n\t * rectangle, or the centroid of a triangle. By default, no points are used.\n\t */\n\tpoints?: VecModel[]\n\t/**\n\t * By default, handles can't snap to their own shape because moving the handle might change the\n\t * snapping location which can cause feedback loops. You can override this by returning a\n\t * version of `outline` that won't be affected by the current handle's position to use for\n\t * self-snapping.\n\t */\n\tgetSelfSnapOutline?(handle: TLHandle): Geometry2d | null\n\t/**\n\t * By default, handles can't snap to their own shape because moving the handle might change the\n\t * snapping location which can cause feedback loops. You can override this by returning a\n\t * version of `points` that won't be affected by the current handle's position to use for\n\t * self-snapping.\n\t */\n\tgetSelfSnapPoints?(handle: TLHandle): VecModel[]\n}\n\ninterface AlignPointsSnap {\n\tsnaps: PointsSnapIndicator[]\n\tnudge: Vec\n}\n\nconst defaultGetSelfSnapOutline = () => null\nconst defaultGetSelfSnapPoints = () => []\n/** @public */\nexport class HandleSnaps {\n\treadonly editor: Editor\n\tconstructor(readonly manager: SnapManager) {\n\t\tthis.editor = manager.editor\n\t}\n\n\t@computed private getSnapGeometryCache() {\n\t\tconst { editor } = this\n\t\treturn editor.store.createComputedCache('handle snap geometry', (shape: TLShape) => {\n\t\t\tconst snapGeometry = editor.getShapeUtil(shape).getHandleSnapGeometry(shape)\n\t\t\tconst getSelfSnapOutline = snapGeometry.getSelfSnapOutline\n\t\t\t\t? snapGeometry.getSelfSnapOutline.bind(snapGeometry)\n\t\t\t\t: defaultGetSelfSnapOutline\n\t\t\tconst getSelfSnapPoints = snapGeometry.getSelfSnapPoints\n\t\t\t\t? snapGeometry.getSelfSnapPoints.bind(snapGeometry)\n\t\t\t\t: defaultGetSelfSnapPoints\n\n\t\t\treturn {\n\t\t\t\toutline:\n\t\t\t\t\tsnapGeometry.outline === undefined\n\t\t\t\t\t\t? editor.getShapeGeometry(shape)\n\t\t\t\t\t\t: snapGeometry.outline,\n\n\t\t\t\tpoints: snapGeometry.points ?? [],\n\t\t\t\tgetSelfSnapOutline,\n\t\t\t\tgetSelfSnapPoints,\n\t\t\t}\n\t\t})\n\t}\n\n\tprivate *iterateSnapPointsInPageSpace(currentShapeId: TLShapeId, currentHandle: TLHandle) {\n\t\tconst selfSnapPoints = this.getSnapGeometryCache()\n\t\t\t.get(currentShapeId)\n\t\t\t?.getSelfSnapPoints(currentHandle)\n\t\tif (selfSnapPoints && selfSnapPoints.length) {\n\t\t\tconst shapePageTransform = assertExists(this.editor.getShapePageTransform(currentShapeId))\n\t\t\tfor (const point of selfSnapPoints) {\n\t\t\t\tyield shapePageTransform.applyToPoint(point)\n\t\t\t}\n\t\t}\n\n\t\tfor (const shapeId of this.manager.getSnappableShapes()) {\n\t\t\tif (shapeId === currentShapeId) continue\n\t\t\tconst snapPoints = this.getSnapGeometryCache().get(shapeId)?.points\n\t\t\tif (!snapPoints || !snapPoints.length) continue\n\n\t\t\tconst shapePageTransform = assertExists(this.editor.getShapePageTransform(shapeId))\n\t\t\tfor (const point of snapPoints) {\n\t\t\t\tyield shapePageTransform.applyToPoint(point)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate *iterateSnapOutlines(currentShapeId: TLShapeId, currentHandle: TLHandle) {\n\t\tconst selfSnapOutline = this.getSnapGeometryCache()\n\t\t\t.get(currentShapeId)\n\t\t\t?.getSelfSnapOutline(currentHandle)\n\t\tif (selfSnapOutline) {\n\t\t\tyield { shapeId: currentShapeId, outline: selfSnapOutline }\n\t\t}\n\n\t\tfor (const shapeId of this.manager.getSnappableShapes()) {\n\t\t\tif (shapeId === currentShapeId) continue\n\n\t\t\tconst snapOutline = this.getSnapGeometryCache().get(shapeId)?.outline\n\t\t\tif (!snapOutline) continue\n\n\t\t\tyield { shapeId, outline: snapOutline }\n\t\t}\n\t}\n\n\tprivate getHandleSnapPosition({\n\t\tcurrentShapeId,\n\t\thandle,\n\t\thandleInPageSpace,\n\t}: {\n\t\tcurrentShapeId: TLShapeId\n\t\thandle: TLHandle\n\t\thandleInPageSpace: Vec\n\t}): Vec | null {\n\t\tconst snapThreshold = this.manager.getSnapThreshold()\n\n\t\t// We snap to two different parts of the shape's handle snap geometry:\n\t\t// 1. The `points`. These are handles or other key points that we want to snap to with a\n\t\t// higher priority than the normal outline snapping.\n\t\t// 2. The `outline`. This describes the outline of the shape, and we just snap to the\n\t\t// nearest point on that outline.\n\n\t\t// Start with the points:\n\t\tlet minDistanceForSnapPoint = snapThreshold\n\t\tlet nearestSnapPoint: Vec | null = null\n\t\tfor (const snapPoint of this.iterateSnapPointsInPageSpace(currentShapeId, handle)) {\n\t\t\tif (Vec.DistMin(handleInPageSpace, snapPoint, minDistanceForSnapPoint)) {\n\t\t\t\tminDistanceForSnapPoint = Vec.Dist(handleInPageSpace, snapPoint)\n\t\t\t\tnearestSnapPoint = snapPoint\n\t\t\t}\n\t\t}\n\n\t\t// if we found a snap point, return it - we don't need to check the outlines because points\n\t\t// have a higher priority\n\t\tif (nearestSnapPoint) return nearestSnapPoint\n\n\t\tlet minDistanceForOutline = snapThreshold\n\t\tlet nearestPointOnOutline: Vec | null = null\n\n\t\tfor (const { shapeId, outline } of this.iterateSnapOutlines(currentShapeId, handle)) {\n\t\t\tconst shapePageTransform = assertExists(this.editor.getShapePageTransform(shapeId))\n\t\t\tconst pointInShapeSpace = this.editor.getPointInShapeSpace(shapeId, handleInPageSpace)\n\n\t\t\tconst nearestShapePointInShapeSpace = outline.nearestPoint(pointInShapeSpace)\n\t\t\tconst nearestInPageSpace = shapePageTransform.applyToPoint(nearestShapePointInShapeSpace)\n\n\t\t\tif (Vec.DistMin(handleInPageSpace, nearestInPageSpace, minDistanceForOutline)) {\n\t\t\t\tminDistanceForOutline = Vec.Dist(handleInPageSpace, nearestInPageSpace)\n\t\t\t\tnearestPointOnOutline = nearestInPageSpace\n\t\t\t}\n\t\t}\n\n\t\t// if we found a point on the outline, return it\n\t\tif (nearestPointOnOutline) return nearestPointOnOutline\n\n\t\t// if not, there's no nearby snap point\n\t\treturn null\n\t}\n\n\tprivate getHandleSnapData({\n\t\thandle,\n\t\tcurrentShapeId,\n\t}: {\n\t\thandle: TLHandle\n\t\tcurrentShapeId: TLShapeId\n\t}): AlignPointsSnap | null {\n\t\tconst snapThreshold = this.manager.getSnapThreshold()\n\t\tconst currentShapeTransform = assertExists(this.editor.getShapePageTransform(currentShapeId))\n\t\tconst handleInPageSpace = currentShapeTransform.applyToPoint(handle)\n\n\t\tlet nearestXSnap: Vec | null = null\n\t\tlet nearestYSnap: Vec | null = null\n\t\tlet minOffsetX = snapThreshold\n\t\tlet minOffsetY = snapThreshold\n\n\t\tfor (const snapPoint of this.iterateSnapPointsInPageSpace(currentShapeId, handle)) {\n\t\t\tconst offsetX = Math.abs(handleInPageSpace.x - snapPoint.x)\n\t\t\tconst offsetY = Math.abs(handleInPageSpace.y - snapPoint.y)\n\t\t\tif (offsetX < minOffsetX) {\n\t\t\t\tminOffsetX = offsetX\n\t\t\t\tnearestXSnap = snapPoint\n\t\t\t}\n\t\t\tif (offsetY < minOffsetY) {\n\t\t\t\tminOffsetY = offsetY\n\t\t\t\tnearestYSnap = snapPoint\n\t\t\t}\n\t\t}\n\n\t\tif (!nearestXSnap && !nearestYSnap) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst nudge = new Vec(\n\t\t\tnearestXSnap ? nearestXSnap.x - handleInPageSpace.x : 0,\n\t\t\tnearestYSnap ? nearestYSnap.y - handleInPageSpace.y : 0\n\t\t)\n\n\t\tconst snappedHandle = Vec.Add(handleInPageSpace, nudge)\n\t\tconst snaps: PointsSnapIndicator[] = []\n\n\t\tif (nearestXSnap) {\n\t\t\tconst snappedHandleOnX = new Vec(nearestXSnap.x, snappedHandle.y)\n\t\t\tsnaps.push({\n\t\t\t\tid: uniqueId(),\n\t\t\t\ttype: 'points',\n\t\t\t\tpoints: [nearestXSnap, snappedHandleOnX],\n\t\t\t})\n\t\t}\n\t\tif (nearestYSnap) {\n\t\t\tconst snappedHandleOnY = new Vec(snappedHandle.x, nearestYSnap.y)\n\t\t\tsnaps.push({\n\t\t\t\tid: uniqueId(),\n\t\t\t\ttype: 'points',\n\t\t\t\tpoints: [nearestYSnap, snappedHandleOnY],\n\t\t\t})\n\t\t}\n\n\t\treturn { snaps, nudge }\n\t}\n\n\tsnapHandle({\n\t\tcurrentShapeId,\n\t\thandle,\n\t}: {\n\t\tcurrentShapeId: TLShapeId\n\t\thandle: TLHandle\n\t}): SnapData | null {\n\t\tconst currentShapeTransform = assertExists(this.editor.getShapePageTransform(currentShapeId))\n\t\tconst handleInPageSpace = currentShapeTransform.applyToPoint(handle)\n\t\t// eslint-disable-next-line @typescript-eslint/no-deprecated\n\t\tconst snapType = handle.canSnap ? 'point' : handle.snapType\n\n\t\tif (snapType === 'point') {\n\t\t\tconst snapPosition = this.getHandleSnapPosition({ currentShapeId, handle, handleInPageSpace })\n\n\t\t\tif (!snapPosition) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tthis.manager.setIndicators([\n\t\t\t\t{\n\t\t\t\t\tid: uniqueId(),\n\t\t\t\t\ttype: 'points',\n\t\t\t\t\tpoints: [snapPosition],\n\t\t\t\t},\n\t\t\t])\n\n\t\t\treturn { nudge: Vec.Sub(snapPosition, handleInPageSpace) }\n\t\t}\n\n\t\tif (snapType === 'align') {\n\t\t\tconst snapData = this.getHandleSnapData({\n\t\t\t\thandle,\n\t\t\t\tcurrentShapeId,\n\t\t\t})\n\n\t\t\tif (!snapData) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tthis.manager.setIndicators(snapData.snaps)\n\n\t\t\treturn { nudge: snapData.nudge }\n\t\t}\n\n\t\treturn null\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }