@tldraw/editor 5.4.0-canary.b41840d4f0e4 → 5.4.0-canary.b8ec00e16e3a

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 (29) hide show
  1. package/dist-cjs/index.js +1 -1
  2. package/dist-cjs/lib/editor/Editor.js +17 -14
  3. package/dist-cjs/lib/editor/Editor.js.map +2 -2
  4. package/dist-cjs/lib/editor/derivations/shapeIdsInCurrentPage.js +7 -3
  5. package/dist-cjs/lib/editor/derivations/shapeIdsInCurrentPage.js.map +2 -2
  6. package/dist-cjs/lib/primitives/geometry/Group2d.js +63 -21
  7. package/dist-cjs/lib/primitives/geometry/Group2d.js.map +2 -2
  8. package/dist-cjs/lib/utils/normalizeWheel.js +2 -0
  9. package/dist-cjs/lib/utils/normalizeWheel.js.map +2 -2
  10. package/dist-cjs/version.js +3 -3
  11. package/dist-cjs/version.js.map +1 -1
  12. package/dist-esm/index.mjs +1 -1
  13. package/dist-esm/lib/editor/Editor.mjs +17 -14
  14. package/dist-esm/lib/editor/Editor.mjs.map +2 -2
  15. package/dist-esm/lib/editor/derivations/shapeIdsInCurrentPage.mjs +7 -3
  16. package/dist-esm/lib/editor/derivations/shapeIdsInCurrentPage.mjs.map +2 -2
  17. package/dist-esm/lib/primitives/geometry/Group2d.mjs +63 -21
  18. package/dist-esm/lib/primitives/geometry/Group2d.mjs.map +2 -2
  19. package/dist-esm/lib/utils/normalizeWheel.mjs +2 -0
  20. package/dist-esm/lib/utils/normalizeWheel.mjs.map +2 -2
  21. package/dist-esm/version.mjs +3 -3
  22. package/dist-esm/version.mjs.map +1 -1
  23. package/package.json +7 -7
  24. package/src/lib/editor/Editor.ts +25 -24
  25. package/src/lib/editor/derivations/shapeIdsInCurrentPage.ts +7 -3
  26. package/src/lib/primitives/geometry/Group2d.ts +63 -27
  27. package/src/lib/utils/normalizeWheel.test.ts +39 -0
  28. package/src/lib/utils/normalizeWheel.ts +6 -0
  29. package/src/version.ts +3 -3
@@ -38,9 +38,13 @@ function deriveShapeIdsInCurrentPage(store, getCurrentPageId) {
38
38
  function fromScratch() {
39
39
  const currentPageId = getCurrentPageId();
40
40
  lastPageId = currentPageId;
41
- return new Set(
42
- [...shapesIndex.get()].filter((id) => isShapeInPage(store, currentPageId, store.get(id)))
43
- );
41
+ const result = /* @__PURE__ */ new Set();
42
+ for (const id of shapesIndex.get()) {
43
+ if (isShapeInPage(store, currentPageId, store.get(id))) {
44
+ result.add(id);
45
+ }
46
+ }
47
+ return result;
44
48
  }
45
49
  return (0, import_state.computed)("_shapeIdsInCurrentPage", (prevValue, lastComputedEpoch) => {
46
50
  if ((0, import_state.isUninitialized)(prevValue)) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/editor/derivations/shapeIdsInCurrentPage.ts"],
4
- "sourcesContent": ["import { computed, isUninitialized, RESET_VALUE, withDiff } from '@tldraw/state'\nimport { IncrementalSetConstructor } from '@tldraw/store'\nimport {\n\tisPageId,\n\tisShape,\n\tisShapeId,\n\tTLPageId,\n\tTLShape,\n\tTLShapeId,\n\tTLStore,\n} from '@tldraw/tlschema'\n\n/**\n * Get whether a shape is in the current page.\n *\n * @param store - The tldraw store.\n * @param pageId - The id of the page to check.\n * @param shape - The the shape to check.\n */\nconst isShapeInPage = (store: TLStore, pageId: TLPageId, shape: TLShape): boolean => {\n\twhile (!isPageId(shape.parentId)) {\n\t\tconst parent = store.get(shape.parentId)\n\t\tif (!parent) return false\n\t\tshape = parent\n\t}\n\n\treturn shape.parentId === pageId\n}\n\n/**\n * A derivation that returns a list of shape ids in the current page.\n *\n * @param store - The tldraw store.\n * @param getCurrentPageId - A function that returns the current page id.\n */\nexport function deriveShapeIdsInCurrentPage(store: TLStore, getCurrentPageId: () => TLPageId) {\n\tconst shapesIndex = store.query.ids('shape')\n\tlet lastPageId: null | TLPageId = null\n\tfunction fromScratch() {\n\t\tconst currentPageId = getCurrentPageId()\n\t\tlastPageId = currentPageId\n\t\treturn new Set(\n\t\t\t[...shapesIndex.get()].filter((id) => isShapeInPage(store, currentPageId, store.get(id)!))\n\t\t)\n\t}\n\treturn computed<Set<TLShapeId>>('_shapeIdsInCurrentPage', (prevValue, lastComputedEpoch) => {\n\t\tif (isUninitialized(prevValue)) {\n\t\t\treturn fromScratch()\n\t\t}\n\n\t\tconst currentPageId = getCurrentPageId()\n\n\t\tif (currentPageId !== lastPageId) {\n\t\t\treturn fromScratch()\n\t\t}\n\n\t\tconst diff = store.history.getDiffSince(lastComputedEpoch)\n\n\t\tif (diff === RESET_VALUE) {\n\t\t\treturn fromScratch()\n\t\t}\n\n\t\tconst builder = new IncrementalSetConstructor<TLShapeId>(\n\t\t\tprevValue\n\t\t) as IncrementalSetConstructor<TLShapeId>\n\n\t\tfor (const changes of diff) {\n\t\t\tfor (const record of Object.values(changes.added)) {\n\t\t\t\tif (isShape(record) && isShapeInPage(store, currentPageId, record)) {\n\t\t\t\t\tbuilder.add(record.id)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const [_from, to] of Object.values(changes.updated)) {\n\t\t\t\tif (isShape(to)) {\n\t\t\t\t\tif (isShapeInPage(store, currentPageId, to)) {\n\t\t\t\t\t\tbuilder.add(to.id)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbuilder.remove(to.id)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const id of Object.keys(changes.removed)) {\n\t\t\t\tif (isShapeId(id)) {\n\t\t\t\t\tbuilder.remove(id)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst result = builder.get()\n\t\tif (!result) {\n\t\t\treturn prevValue\n\t\t}\n\n\t\treturn withDiff(result.value, result.diff)\n\t})\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiE;AACjE,mBAA0C;AAC1C,sBAQO;AASP,MAAM,gBAAgB,CAAC,OAAgB,QAAkB,UAA4B;AACpF,SAAO,KAAC,0BAAS,MAAM,QAAQ,GAAG;AACjC,UAAM,SAAS,MAAM,IAAI,MAAM,QAAQ;AACvC,QAAI,CAAC,OAAQ,QAAO;AACpB,YAAQ;AAAA,EACT;AAEA,SAAO,MAAM,aAAa;AAC3B;AAQO,SAAS,4BAA4B,OAAgB,kBAAkC;AAC7F,QAAM,cAAc,MAAM,MAAM,IAAI,OAAO;AAC3C,MAAI,aAA8B;AAClC,WAAS,cAAc;AACtB,UAAM,gBAAgB,iBAAiB;AACvC,iBAAa;AACb,WAAO,IAAI;AAAA,MACV,CAAC,GAAG,YAAY,IAAI,CAAC,EAAE,OAAO,CAAC,OAAO,cAAc,OAAO,eAAe,MAAM,IAAI,EAAE,CAAE,CAAC;AAAA,IAC1F;AAAA,EACD;AACA,aAAO,uBAAyB,0BAA0B,CAAC,WAAW,sBAAsB;AAC3F,YAAI,8BAAgB,SAAS,GAAG;AAC/B,aAAO,YAAY;AAAA,IACpB;AAEA,UAAM,gBAAgB,iBAAiB;AAEvC,QAAI,kBAAkB,YAAY;AACjC,aAAO,YAAY;AAAA,IACpB;AAEA,UAAM,OAAO,MAAM,QAAQ,aAAa,iBAAiB;AAEzD,QAAI,SAAS,0BAAa;AACzB,aAAO,YAAY;AAAA,IACpB;AAEA,UAAM,UAAU,IAAI;AAAA,MACnB;AAAA,IACD;AAEA,eAAW,WAAW,MAAM;AAC3B,iBAAW,UAAU,OAAO,OAAO,QAAQ,KAAK,GAAG;AAClD,gBAAI,yBAAQ,MAAM,KAAK,cAAc,OAAO,eAAe,MAAM,GAAG;AACnE,kBAAQ,IAAI,OAAO,EAAE;AAAA,QACtB;AAAA,MACD;AAEA,iBAAW,CAAC,OAAO,EAAE,KAAK,OAAO,OAAO,QAAQ,OAAO,GAAG;AACzD,gBAAI,yBAAQ,EAAE,GAAG;AAChB,cAAI,cAAc,OAAO,eAAe,EAAE,GAAG;AAC5C,oBAAQ,IAAI,GAAG,EAAE;AAAA,UAClB,OAAO;AACN,oBAAQ,OAAO,GAAG,EAAE;AAAA,UACrB;AAAA,QACD;AAAA,MACD;AAEA,iBAAW,MAAM,OAAO,KAAK,QAAQ,OAAO,GAAG;AAC9C,gBAAI,2BAAU,EAAE,GAAG;AAClB,kBAAQ,OAAO,EAAE;AAAA,QAClB;AAAA,MACD;AAAA,IACD;AAEA,UAAM,SAAS,QAAQ,IAAI;AAC3B,QAAI,CAAC,QAAQ;AACZ,aAAO;AAAA,IACR;AAEA,eAAO,uBAAS,OAAO,OAAO,OAAO,IAAI;AAAA,EAC1C,CAAC;AACF;",
4
+ "sourcesContent": ["import { computed, isUninitialized, RESET_VALUE, withDiff } from '@tldraw/state'\nimport { IncrementalSetConstructor } from '@tldraw/store'\nimport {\n\tisPageId,\n\tisShape,\n\tisShapeId,\n\tTLPageId,\n\tTLShape,\n\tTLShapeId,\n\tTLStore,\n} from '@tldraw/tlschema'\n\n/**\n * Get whether a shape is in the current page.\n *\n * @param store - The tldraw store.\n * @param pageId - The id of the page to check.\n * @param shape - The the shape to check.\n */\nconst isShapeInPage = (store: TLStore, pageId: TLPageId, shape: TLShape): boolean => {\n\twhile (!isPageId(shape.parentId)) {\n\t\tconst parent = store.get(shape.parentId)\n\t\tif (!parent) return false\n\t\tshape = parent\n\t}\n\n\treturn shape.parentId === pageId\n}\n\n/**\n * A derivation that returns a list of shape ids in the current page.\n *\n * @param store - The tldraw store.\n * @param getCurrentPageId - A function that returns the current page id.\n */\nexport function deriveShapeIdsInCurrentPage(store: TLStore, getCurrentPageId: () => TLPageId) {\n\tconst shapesIndex = store.query.ids('shape')\n\tlet lastPageId: null | TLPageId = null\n\tfunction fromScratch() {\n\t\tconst currentPageId = getCurrentPageId()\n\t\tlastPageId = currentPageId\n\t\tconst result = new Set<TLShapeId>()\n\t\tfor (const id of shapesIndex.get()) {\n\t\t\tif (isShapeInPage(store, currentPageId, store.get(id)!)) {\n\t\t\t\tresult.add(id)\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\treturn computed<Set<TLShapeId>>('_shapeIdsInCurrentPage', (prevValue, lastComputedEpoch) => {\n\t\tif (isUninitialized(prevValue)) {\n\t\t\treturn fromScratch()\n\t\t}\n\n\t\tconst currentPageId = getCurrentPageId()\n\n\t\tif (currentPageId !== lastPageId) {\n\t\t\treturn fromScratch()\n\t\t}\n\n\t\tconst diff = store.history.getDiffSince(lastComputedEpoch)\n\n\t\tif (diff === RESET_VALUE) {\n\t\t\treturn fromScratch()\n\t\t}\n\n\t\tconst builder = new IncrementalSetConstructor<TLShapeId>(\n\t\t\tprevValue\n\t\t) as IncrementalSetConstructor<TLShapeId>\n\n\t\tfor (const changes of diff) {\n\t\t\tfor (const record of Object.values(changes.added)) {\n\t\t\t\tif (isShape(record) && isShapeInPage(store, currentPageId, record)) {\n\t\t\t\t\tbuilder.add(record.id)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const [_from, to] of Object.values(changes.updated)) {\n\t\t\t\tif (isShape(to)) {\n\t\t\t\t\tif (isShapeInPage(store, currentPageId, to)) {\n\t\t\t\t\t\tbuilder.add(to.id)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbuilder.remove(to.id)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const id of Object.keys(changes.removed)) {\n\t\t\t\tif (isShapeId(id)) {\n\t\t\t\t\tbuilder.remove(id)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst result = builder.get()\n\t\tif (!result) {\n\t\t\treturn prevValue\n\t\t}\n\n\t\treturn withDiff(result.value, result.diff)\n\t})\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiE;AACjE,mBAA0C;AAC1C,sBAQO;AASP,MAAM,gBAAgB,CAAC,OAAgB,QAAkB,UAA4B;AACpF,SAAO,KAAC,0BAAS,MAAM,QAAQ,GAAG;AACjC,UAAM,SAAS,MAAM,IAAI,MAAM,QAAQ;AACvC,QAAI,CAAC,OAAQ,QAAO;AACpB,YAAQ;AAAA,EACT;AAEA,SAAO,MAAM,aAAa;AAC3B;AAQO,SAAS,4BAA4B,OAAgB,kBAAkC;AAC7F,QAAM,cAAc,MAAM,MAAM,IAAI,OAAO;AAC3C,MAAI,aAA8B;AAClC,WAAS,cAAc;AACtB,UAAM,gBAAgB,iBAAiB;AACvC,iBAAa;AACb,UAAM,SAAS,oBAAI,IAAe;AAClC,eAAW,MAAM,YAAY,IAAI,GAAG;AACnC,UAAI,cAAc,OAAO,eAAe,MAAM,IAAI,EAAE,CAAE,GAAG;AACxD,eAAO,IAAI,EAAE;AAAA,MACd;AAAA,IACD;AACA,WAAO;AAAA,EACR;AACA,aAAO,uBAAyB,0BAA0B,CAAC,WAAW,sBAAsB;AAC3F,YAAI,8BAAgB,SAAS,GAAG;AAC/B,aAAO,YAAY;AAAA,IACpB;AAEA,UAAM,gBAAgB,iBAAiB;AAEvC,QAAI,kBAAkB,YAAY;AACjC,aAAO,YAAY;AAAA,IACpB;AAEA,UAAM,OAAO,MAAM,QAAQ,aAAa,iBAAiB;AAEzD,QAAI,SAAS,0BAAa;AACzB,aAAO,YAAY;AAAA,IACpB;AAEA,UAAM,UAAU,IAAI;AAAA,MACnB;AAAA,IACD;AAEA,eAAW,WAAW,MAAM;AAC3B,iBAAW,UAAU,OAAO,OAAO,QAAQ,KAAK,GAAG;AAClD,gBAAI,yBAAQ,MAAM,KAAK,cAAc,OAAO,eAAe,MAAM,GAAG;AACnE,kBAAQ,IAAI,OAAO,EAAE;AAAA,QACtB;AAAA,MACD;AAEA,iBAAW,CAAC,OAAO,EAAE,KAAK,OAAO,OAAO,QAAQ,OAAO,GAAG;AACzD,gBAAI,yBAAQ,EAAE,GAAG;AAChB,cAAI,cAAc,OAAO,eAAe,EAAE,GAAG;AAC5C,oBAAQ,IAAI,GAAG,EAAE;AAAA,UAClB,OAAO;AACN,oBAAQ,OAAO,GAAG,EAAE;AAAA,UACrB;AAAA,QACD;AAAA,MACD;AAEA,iBAAW,MAAM,OAAO,KAAK,QAAQ,OAAO,GAAG;AAC9C,gBAAI,2BAAU,EAAE,GAAG;AAClB,kBAAQ,OAAO,EAAE;AAAA,QAClB;AAAA,MACD;AAAA,IACD;AAEA,UAAM,SAAS,QAAQ,IAAI;AAC3B,QAAI,CAAC,QAAQ;AACZ,aAAO;AAAA,IACR;AAEA,eAAO,uBAAS,OAAO,OAAO,OAAO,IAAI;AAAA,EAC1C,CAAC;AACF;",
6
6
  "names": []
7
7
  }
@@ -21,7 +21,6 @@ __export(Group2d_exports, {
21
21
  Group2d: () => Group2d
22
22
  });
23
23
  module.exports = __toCommonJS(Group2d_exports);
24
- var import_state = require("@tldraw/state");
25
24
  var import_utils = require("@tldraw/utils");
26
25
  var import_Box = require("../Box");
27
26
  var import_Vec = require("../Vec");
@@ -47,7 +46,15 @@ class Group2d extends import_Geometry2d.Geometry2d {
47
46
  }
48
47
  getVertices(filters) {
49
48
  if (this.isExcludedByFilter(filters)) return [];
50
- return this.children.filter((c) => !c.isExcludedByFilter(filters)).flatMap((c) => c.getVertices(filters));
49
+ const vertices = [];
50
+ for (const child of this.children) {
51
+ if (child.isExcludedByFilter(filters)) continue;
52
+ const childVertices = child.getVertices(filters);
53
+ for (let i = 0, n = childVertices.length; i < n; i++) {
54
+ vertices.push(childVertices[i]);
55
+ }
56
+ }
57
+ return vertices;
51
58
  }
52
59
  nearestPoint(point, filters) {
53
60
  let dist = Infinity;
@@ -82,38 +89,73 @@ class Group2d extends import_Geometry2d.Geometry2d {
82
89
  return smallestDistance;
83
90
  }
84
91
  hitTestPoint(point, margin, hitInside, filters = import_Geometry2d.Geometry2dFilters.EXCLUDE_LABELS) {
85
- return !!this.children.filter((c) => !c.isExcludedByFilter(filters)).find((c) => c.hitTestPoint(point, margin, hitInside));
92
+ for (const child of this.children) {
93
+ if (child.isExcludedByFilter(filters)) continue;
94
+ if (child.hitTestPoint(point, margin, hitInside)) return true;
95
+ }
96
+ return false;
86
97
  }
87
98
  hitTestLineSegment(A, B, zoom, filters = import_Geometry2d.Geometry2dFilters.EXCLUDE_LABELS) {
88
- return !!this.children.filter((c) => !c.isExcludedByFilter(filters)).find((c) => c.hitTestLineSegment(A, B, zoom));
99
+ for (const child of this.children) {
100
+ if (child.isExcludedByFilter(filters)) continue;
101
+ if (child.hitTestLineSegment(A, B, zoom)) return true;
102
+ }
103
+ return false;
89
104
  }
90
105
  intersectLineSegment(A, B, filters) {
91
- return this.children.flatMap((child) => {
92
- if (child.isExcludedByFilter(filters)) return import_state.EMPTY_ARRAY;
93
- return child.intersectLineSegment(A, B, filters);
94
- });
106
+ const result = [];
107
+ for (const child of this.children) {
108
+ if (child.isExcludedByFilter(filters)) continue;
109
+ const hits = child.intersectLineSegment(A, B, filters);
110
+ for (let i = 0, n = hits.length; i < n; i++) {
111
+ result.push(hits[i]);
112
+ }
113
+ }
114
+ return result;
95
115
  }
96
116
  intersectCircle(center, radius, filters) {
97
- return this.children.flatMap((child) => {
98
- if (child.isExcludedByFilter(filters)) return import_state.EMPTY_ARRAY;
99
- return child.intersectCircle(center, radius, filters);
100
- });
117
+ const result = [];
118
+ for (const child of this.children) {
119
+ if (child.isExcludedByFilter(filters)) continue;
120
+ const hits = child.intersectCircle(center, radius, filters);
121
+ for (let i = 0, n = hits.length; i < n; i++) {
122
+ result.push(hits[i]);
123
+ }
124
+ }
125
+ return result;
101
126
  }
102
127
  getBoundsVertices() {
103
128
  if (this.excludeFromShapeBounds) return [];
104
- return this.children.flatMap((child) => child.getBoundsVertices());
129
+ const vertices = [];
130
+ for (const child of this.children) {
131
+ const childVertices = child.getBoundsVertices();
132
+ for (let i = 0, n = childVertices.length; i < n; i++) {
133
+ vertices.push(childVertices[i]);
134
+ }
135
+ }
136
+ return vertices;
105
137
  }
106
138
  intersectPolygon(polygon, filters) {
107
- return this.children.flatMap((child) => {
108
- if (child.isExcludedByFilter(filters)) return import_state.EMPTY_ARRAY;
109
- return child.intersectPolygon(polygon, filters);
110
- });
139
+ const result = [];
140
+ for (const child of this.children) {
141
+ if (child.isExcludedByFilter(filters)) continue;
142
+ const hits = child.intersectPolygon(polygon, filters);
143
+ for (let i = 0, n = hits.length; i < n; i++) {
144
+ result.push(hits[i]);
145
+ }
146
+ }
147
+ return result;
111
148
  }
112
149
  intersectPolyline(polyline, filters) {
113
- return this.children.flatMap((child) => {
114
- if (child.isExcludedByFilter(filters)) return import_state.EMPTY_ARRAY;
115
- return child.intersectPolyline(polyline, filters);
116
- });
150
+ const result = [];
151
+ for (const child of this.children) {
152
+ if (child.isExcludedByFilter(filters)) continue;
153
+ const hits = child.intersectPolyline(polyline, filters);
154
+ for (let i = 0, n = hits.length; i < n; i++) {
155
+ result.push(hits[i]);
156
+ }
157
+ }
158
+ return result;
117
159
  }
118
160
  interpolateAlongEdge(t, filters) {
119
161
  const totalLength = this.getLength(filters);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/primitives/geometry/Group2d.ts"],
4
- "sourcesContent": ["import { EMPTY_ARRAY } from '@tldraw/state'\nimport { assert, invLerp, lerp } from '@tldraw/utils'\nimport { Box } from '../Box'\nimport { Mat } from '../Mat'\nimport { Vec, VecLike } from '../Vec'\nimport { Geometry2d, Geometry2dFilters, Geometry2dOptions } from './Geometry2d'\n\n/** @public */\nexport class Group2d extends Geometry2d {\n\tchildren: Geometry2d[] = []\n\tignoredChildren: Geometry2d[] = []\n\n\tconstructor(\n\t\tconfig: Omit<Geometry2dOptions, 'isClosed' | 'isFilled'> & {\n\t\t\tchildren: Geometry2d[]\n\t\t}\n\t) {\n\t\tsuper({ ...config, isClosed: true, isFilled: false })\n\n\t\tconst addChildren = (children: Geometry2d[]) => {\n\t\t\tfor (const child of children) {\n\t\t\t\tif (child instanceof Group2d) {\n\t\t\t\t\taddChildren(child.children)\n\t\t\t\t} else if (child.ignore) {\n\t\t\t\t\tthis.ignoredChildren.push(child)\n\t\t\t\t} else {\n\t\t\t\t\tthis.children.push(child)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\taddChildren(config.children)\n\n\t\tif (this.children.length === 0) throw Error('Group2d must have at least one child')\n\t}\n\n\toverride getVertices(filters: Geometry2dFilters): Vec[] {\n\t\tif (this.isExcludedByFilter(filters)) return []\n\t\treturn this.children\n\t\t\t.filter((c) => !c.isExcludedByFilter(filters))\n\t\t\t.flatMap((c) => c.getVertices(filters))\n\t}\n\n\toverride nearestPoint(point: VecLike, filters?: Geometry2dFilters): Vec {\n\t\tlet dist = Infinity\n\t\tlet nearest: Vec | undefined\n\n\t\tconst { children } = this\n\n\t\tif (children.length === 0) {\n\t\t\tthrow Error('no children')\n\t\t}\n\n\t\tlet p: Vec\n\t\tlet d: number\n\t\tfor (const child of children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tp = child.nearestPoint(point, filters)\n\t\t\td = Vec.Dist2(p, point)\n\t\t\tif (d < dist) {\n\t\t\t\tdist = d\n\t\t\t\tnearest = p\n\t\t\t}\n\t\t}\n\t\tif (!nearest) throw Error('nearest point not found')\n\t\treturn nearest\n\t}\n\n\toverride distanceToPoint(point: VecLike, hitInside = false, filters?: Geometry2dFilters) {\n\t\tlet smallestDistance = Infinity\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tconst distance = child.distanceToPoint(point, hitInside, filters)\n\t\t\tif (distance < smallestDistance) {\n\t\t\t\tsmallestDistance = distance\n\t\t\t}\n\t\t}\n\t\treturn smallestDistance\n\t}\n\n\toverride hitTestPoint(\n\t\tpoint: VecLike,\n\t\tmargin: number,\n\t\thitInside: boolean,\n\t\tfilters = Geometry2dFilters.EXCLUDE_LABELS\n\t): boolean {\n\t\treturn !!this.children\n\t\t\t.filter((c) => !c.isExcludedByFilter(filters))\n\t\t\t.find((c) => c.hitTestPoint(point, margin, hitInside))\n\t}\n\n\toverride hitTestLineSegment(\n\t\tA: VecLike,\n\t\tB: VecLike,\n\t\tzoom: number,\n\t\tfilters = Geometry2dFilters.EXCLUDE_LABELS\n\t): boolean {\n\t\treturn !!this.children\n\t\t\t.filter((c) => !c.isExcludedByFilter(filters))\n\t\t\t.find((c) => c.hitTestLineSegment(A, B, zoom))\n\t}\n\n\toverride intersectLineSegment(A: VecLike, B: VecLike, filters?: Geometry2dFilters) {\n\t\treturn this.children.flatMap((child) => {\n\t\t\tif (child.isExcludedByFilter(filters)) return EMPTY_ARRAY\n\t\t\treturn child.intersectLineSegment(A, B, filters)\n\t\t})\n\t}\n\n\toverride intersectCircle(center: VecLike, radius: number, filters?: Geometry2dFilters) {\n\t\treturn this.children.flatMap((child) => {\n\t\t\tif (child.isExcludedByFilter(filters)) return EMPTY_ARRAY\n\t\t\treturn child.intersectCircle(center, radius, filters)\n\t\t})\n\t}\n\n\toverride getBoundsVertices(): Vec[] {\n\t\tif (this.excludeFromShapeBounds) return []\n\t\treturn this.children.flatMap((child) => child.getBoundsVertices())\n\t}\n\n\toverride intersectPolygon(polygon: VecLike[], filters?: Geometry2dFilters) {\n\t\treturn this.children.flatMap((child) => {\n\t\t\tif (child.isExcludedByFilter(filters)) return EMPTY_ARRAY\n\t\t\treturn child.intersectPolygon(polygon, filters)\n\t\t})\n\t}\n\n\toverride intersectPolyline(polyline: VecLike[], filters?: Geometry2dFilters) {\n\t\treturn this.children.flatMap((child) => {\n\t\t\tif (child.isExcludedByFilter(filters)) return EMPTY_ARRAY\n\t\t\treturn child.intersectPolyline(polyline, filters)\n\t\t})\n\t}\n\n\toverride interpolateAlongEdge(t: number, filters?: Geometry2dFilters): Vec {\n\t\tconst totalLength = this.getLength(filters)\n\n\t\tconst distanceToTravel = t * totalLength\n\t\tlet distanceTraveled = 0\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tconst childLength = child.length\n\t\t\tconst newDistanceTraveled = distanceTraveled + childLength\n\t\t\tif (newDistanceTraveled >= distanceToTravel) {\n\t\t\t\treturn child.interpolateAlongEdge(\n\t\t\t\t\tinvLerp(distanceTraveled, newDistanceTraveled, distanceToTravel),\n\t\t\t\t\tfilters\n\t\t\t\t)\n\t\t\t}\n\t\t\tdistanceTraveled = newDistanceTraveled\n\t\t}\n\n\t\treturn this.children[this.children.length - 1].interpolateAlongEdge(1, filters)\n\t}\n\n\toverride uninterpolateAlongEdge(point: VecLike, filters?: Geometry2dFilters): number {\n\t\tconst totalLength = this.getLength(filters)\n\n\t\tlet closestChild = null\n\t\tlet closestDistance = Infinity\n\t\tlet distanceTraveled = 0\n\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tconst childLength = child.getLength(filters)\n\t\t\tconst newDistanceTraveled = distanceTraveled + childLength\n\n\t\t\tconst distance = child.distanceToPoint(point, false, filters)\n\t\t\tif (distance < closestDistance) {\n\t\t\t\tclosestDistance = distance\n\t\t\t\tclosestChild = {\n\t\t\t\t\tstartLength: distanceTraveled,\n\t\t\t\t\tendLength: newDistanceTraveled,\n\t\t\t\t\tchild,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdistanceTraveled = newDistanceTraveled\n\t\t}\n\n\t\tassert(closestChild)\n\n\t\tconst normalizedDistanceInChild = closestChild.child.uninterpolateAlongEdge(point, filters)\n\t\tconst childTLength = lerp(\n\t\t\tclosestChild.startLength,\n\t\t\tclosestChild.endLength,\n\t\t\tnormalizedDistanceInChild\n\t\t)\n\t\treturn childTLength / totalLength\n\t}\n\n\toverride transform(transform: Mat): Geometry2d {\n\t\treturn new Group2d({\n\t\t\tchildren: this.children.map((c) => c.transform(transform)),\n\t\t\tisLabel: this.isLabel,\n\t\t\tdebugColor: this.debugColor,\n\t\t\tignore: this.ignore,\n\t\t})\n\t}\n\n\tgetArea() {\n\t\t// todo: this is a temporary solution, assuming that the first child defines the group size; we would want to flatten the group and then find the area of the hull polygon\n\t\treturn this.children[0].area\n\t}\n\n\ttoSimpleSvgPath() {\n\t\tlet path = ''\n\t\tfor (const child of this.children) {\n\t\t\tpath += child.toSimpleSvgPath()\n\t\t}\n\n\t\tconst corners = Box.FromPoints(this.boundsVertices).corners\n\t\t// draw just a few pixels around each corner, e.g. an L shape for the bottom left\n\n\t\tfor (let i = 0, n = corners.length; i < n; i++) {\n\t\t\tconst corner = corners[i]\n\t\t\tconst prevCorner = corners[(i - 1 + n) % n]\n\t\t\tconst prevDist = corner.dist(prevCorner)\n\t\t\tconst nextCorner = corners[(i + 1) % n]\n\t\t\tconst nextDist = corner.dist(nextCorner)\n\n\t\t\tconst A = corner.clone().lrp(prevCorner, 4 / prevDist)\n\t\t\tconst B = corner\n\t\t\tconst C = corner.clone().lrp(nextCorner, 4 / nextDist)\n\n\t\t\tpath += `M${A.x},${A.y} L${B.x},${B.y} L${C.x},${C.y} `\n\t\t}\n\t\treturn path\n\t}\n\n\tgetLength(filters?: Geometry2dFilters): number {\n\t\tlet length = 0\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tlength += child.length\n\t\t}\n\t\treturn length\n\t}\n\n\tgetSvgPathData(): string {\n\t\treturn this.children.map((c, i) => (c.isLabel ? '' : c.getSvgPathData(i === 0))).join(' ')\n\t}\n\n\toverlapsPolygon(polygon: VecLike[]): boolean {\n\t\treturn this.children.some((child) => child.overlapsPolygon(polygon))\n\t}\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { assert, invLerp, lerp } from '@tldraw/utils'\nimport { Box } from '../Box'\nimport { Mat } from '../Mat'\nimport { Vec, VecLike } from '../Vec'\nimport { Geometry2d, Geometry2dFilters, Geometry2dOptions } from './Geometry2d'\n\n/** @public */\nexport class Group2d extends Geometry2d {\n\tchildren: Geometry2d[] = []\n\tignoredChildren: Geometry2d[] = []\n\n\tconstructor(\n\t\tconfig: Omit<Geometry2dOptions, 'isClosed' | 'isFilled'> & {\n\t\t\tchildren: Geometry2d[]\n\t\t}\n\t) {\n\t\tsuper({ ...config, isClosed: true, isFilled: false })\n\n\t\tconst addChildren = (children: Geometry2d[]) => {\n\t\t\tfor (const child of children) {\n\t\t\t\tif (child instanceof Group2d) {\n\t\t\t\t\taddChildren(child.children)\n\t\t\t\t} else if (child.ignore) {\n\t\t\t\t\tthis.ignoredChildren.push(child)\n\t\t\t\t} else {\n\t\t\t\t\tthis.children.push(child)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\taddChildren(config.children)\n\n\t\tif (this.children.length === 0) throw Error('Group2d must have at least one child')\n\t}\n\n\toverride getVertices(filters: Geometry2dFilters): Vec[] {\n\t\tif (this.isExcludedByFilter(filters)) return []\n\t\tconst vertices: Vec[] = []\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tconst childVertices = child.getVertices(filters)\n\t\t\tfor (let i = 0, n = childVertices.length; i < n; i++) {\n\t\t\t\tvertices.push(childVertices[i])\n\t\t\t}\n\t\t}\n\t\treturn vertices\n\t}\n\n\toverride nearestPoint(point: VecLike, filters?: Geometry2dFilters): Vec {\n\t\tlet dist = Infinity\n\t\tlet nearest: Vec | undefined\n\n\t\tconst { children } = this\n\n\t\tif (children.length === 0) {\n\t\t\tthrow Error('no children')\n\t\t}\n\n\t\tlet p: Vec\n\t\tlet d: number\n\t\tfor (const child of children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tp = child.nearestPoint(point, filters)\n\t\t\td = Vec.Dist2(p, point)\n\t\t\tif (d < dist) {\n\t\t\t\tdist = d\n\t\t\t\tnearest = p\n\t\t\t}\n\t\t}\n\t\tif (!nearest) throw Error('nearest point not found')\n\t\treturn nearest\n\t}\n\n\toverride distanceToPoint(point: VecLike, hitInside = false, filters?: Geometry2dFilters) {\n\t\tlet smallestDistance = Infinity\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tconst distance = child.distanceToPoint(point, hitInside, filters)\n\t\t\tif (distance < smallestDistance) {\n\t\t\t\tsmallestDistance = distance\n\t\t\t}\n\t\t}\n\t\treturn smallestDistance\n\t}\n\n\toverride hitTestPoint(\n\t\tpoint: VecLike,\n\t\tmargin: number,\n\t\thitInside: boolean,\n\t\tfilters = Geometry2dFilters.EXCLUDE_LABELS\n\t): boolean {\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tif (child.hitTestPoint(point, margin, hitInside)) return true\n\t\t}\n\t\treturn false\n\t}\n\n\toverride hitTestLineSegment(\n\t\tA: VecLike,\n\t\tB: VecLike,\n\t\tzoom: number,\n\t\tfilters = Geometry2dFilters.EXCLUDE_LABELS\n\t): boolean {\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tif (child.hitTestLineSegment(A, B, zoom)) return true\n\t\t}\n\t\treturn false\n\t}\n\n\toverride intersectLineSegment(A: VecLike, B: VecLike, filters?: Geometry2dFilters) {\n\t\tconst result: VecLike[] = []\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tconst hits = child.intersectLineSegment(A, B, filters)\n\t\t\tfor (let i = 0, n = hits.length; i < n; i++) {\n\t\t\t\tresult.push(hits[i])\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\toverride intersectCircle(center: VecLike, radius: number, filters?: Geometry2dFilters) {\n\t\tconst result: VecLike[] = []\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tconst hits = child.intersectCircle(center, radius, filters)\n\t\t\tfor (let i = 0, n = hits.length; i < n; i++) {\n\t\t\t\tresult.push(hits[i])\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\toverride getBoundsVertices(): Vec[] {\n\t\tif (this.excludeFromShapeBounds) return []\n\t\tconst vertices: Vec[] = []\n\t\tfor (const child of this.children) {\n\t\t\tconst childVertices = child.getBoundsVertices()\n\t\t\tfor (let i = 0, n = childVertices.length; i < n; i++) {\n\t\t\t\tvertices.push(childVertices[i])\n\t\t\t}\n\t\t}\n\t\treturn vertices\n\t}\n\n\toverride intersectPolygon(polygon: VecLike[], filters?: Geometry2dFilters) {\n\t\tconst result: VecLike[] = []\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tconst hits = child.intersectPolygon(polygon, filters)\n\t\t\tfor (let i = 0, n = hits.length; i < n; i++) {\n\t\t\t\tresult.push(hits[i])\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\toverride intersectPolyline(polyline: VecLike[], filters?: Geometry2dFilters) {\n\t\tconst result: VecLike[] = []\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tconst hits = child.intersectPolyline(polyline, filters)\n\t\t\tfor (let i = 0, n = hits.length; i < n; i++) {\n\t\t\t\tresult.push(hits[i])\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\n\toverride interpolateAlongEdge(t: number, filters?: Geometry2dFilters): Vec {\n\t\tconst totalLength = this.getLength(filters)\n\n\t\tconst distanceToTravel = t * totalLength\n\t\tlet distanceTraveled = 0\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tconst childLength = child.length\n\t\t\tconst newDistanceTraveled = distanceTraveled + childLength\n\t\t\tif (newDistanceTraveled >= distanceToTravel) {\n\t\t\t\treturn child.interpolateAlongEdge(\n\t\t\t\t\tinvLerp(distanceTraveled, newDistanceTraveled, distanceToTravel),\n\t\t\t\t\tfilters\n\t\t\t\t)\n\t\t\t}\n\t\t\tdistanceTraveled = newDistanceTraveled\n\t\t}\n\n\t\treturn this.children[this.children.length - 1].interpolateAlongEdge(1, filters)\n\t}\n\n\toverride uninterpolateAlongEdge(point: VecLike, filters?: Geometry2dFilters): number {\n\t\tconst totalLength = this.getLength(filters)\n\n\t\tlet closestChild = null\n\t\tlet closestDistance = Infinity\n\t\tlet distanceTraveled = 0\n\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tconst childLength = child.getLength(filters)\n\t\t\tconst newDistanceTraveled = distanceTraveled + childLength\n\n\t\t\tconst distance = child.distanceToPoint(point, false, filters)\n\t\t\tif (distance < closestDistance) {\n\t\t\t\tclosestDistance = distance\n\t\t\t\tclosestChild = {\n\t\t\t\t\tstartLength: distanceTraveled,\n\t\t\t\t\tendLength: newDistanceTraveled,\n\t\t\t\t\tchild,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdistanceTraveled = newDistanceTraveled\n\t\t}\n\n\t\tassert(closestChild)\n\n\t\tconst normalizedDistanceInChild = closestChild.child.uninterpolateAlongEdge(point, filters)\n\t\tconst childTLength = lerp(\n\t\t\tclosestChild.startLength,\n\t\t\tclosestChild.endLength,\n\t\t\tnormalizedDistanceInChild\n\t\t)\n\t\treturn childTLength / totalLength\n\t}\n\n\toverride transform(transform: Mat): Geometry2d {\n\t\treturn new Group2d({\n\t\t\tchildren: this.children.map((c) => c.transform(transform)),\n\t\t\tisLabel: this.isLabel,\n\t\t\tdebugColor: this.debugColor,\n\t\t\tignore: this.ignore,\n\t\t})\n\t}\n\n\tgetArea() {\n\t\t// todo: this is a temporary solution, assuming that the first child defines the group size; we would want to flatten the group and then find the area of the hull polygon\n\t\treturn this.children[0].area\n\t}\n\n\ttoSimpleSvgPath() {\n\t\tlet path = ''\n\t\tfor (const child of this.children) {\n\t\t\tpath += child.toSimpleSvgPath()\n\t\t}\n\n\t\tconst corners = Box.FromPoints(this.boundsVertices).corners\n\t\t// draw just a few pixels around each corner, e.g. an L shape for the bottom left\n\n\t\tfor (let i = 0, n = corners.length; i < n; i++) {\n\t\t\tconst corner = corners[i]\n\t\t\tconst prevCorner = corners[(i - 1 + n) % n]\n\t\t\tconst prevDist = corner.dist(prevCorner)\n\t\t\tconst nextCorner = corners[(i + 1) % n]\n\t\t\tconst nextDist = corner.dist(nextCorner)\n\n\t\t\tconst A = corner.clone().lrp(prevCorner, 4 / prevDist)\n\t\t\tconst B = corner\n\t\t\tconst C = corner.clone().lrp(nextCorner, 4 / nextDist)\n\n\t\t\tpath += `M${A.x},${A.y} L${B.x},${B.y} L${C.x},${C.y} `\n\t\t}\n\t\treturn path\n\t}\n\n\tgetLength(filters?: Geometry2dFilters): number {\n\t\tlet length = 0\n\t\tfor (const child of this.children) {\n\t\t\tif (child.isExcludedByFilter(filters)) continue\n\t\t\tlength += child.length\n\t\t}\n\t\treturn length\n\t}\n\n\tgetSvgPathData(): string {\n\t\treturn this.children.map((c, i) => (c.isLabel ? '' : c.getSvgPathData(i === 0))).join(' ')\n\t}\n\n\toverlapsPolygon(polygon: VecLike[]): boolean {\n\t\treturn this.children.some((child) => child.overlapsPolygon(polygon))\n\t}\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -25,6 +25,8 @@ var import_environment = require("../globals/environment");
25
25
  const MAX_ZOOM_STEP = 10;
26
26
  function normalizeWheel(event) {
27
27
  let { deltaY, deltaX } = event;
28
+ if (!Number.isFinite(deltaX)) deltaX = 0;
29
+ if (!Number.isFinite(deltaY)) deltaY = 0;
28
30
  let deltaZ = 0;
29
31
  if (event.ctrlKey || event.altKey || event.metaKey) {
30
32
  deltaZ = (Math.abs(deltaY) > MAX_ZOOM_STEP ? MAX_ZOOM_STEP * Math.sign(deltaY) : deltaY) / 100;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/utils/normalizeWheel.ts"],
4
- "sourcesContent": ["import { tlenv } from '../globals/environment'\n\nconst MAX_ZOOM_STEP = 10\n\n/**\n * Normalizes a wheel event, so that the delta values are consistent across different browsers or devices. Adapted from https://stackoverflow.com/a/13650579.\n * @param event - The wheel event to normalize.\n * @returns The normalized wheel event.\n * @internal */\nexport function normalizeWheel(event: WheelEvent | React.WheelEvent<HTMLElement>) {\n\tlet { deltaY, deltaX } = event\n\tlet deltaZ = 0\n\n\t// wheeling\n\tif (event.ctrlKey || event.altKey || event.metaKey) {\n\t\tdeltaZ = (Math.abs(deltaY) > MAX_ZOOM_STEP ? MAX_ZOOM_STEP * Math.sign(deltaY) : deltaY) / 100\n\t} else {\n\t\tif (event.shiftKey && !tlenv.isDarwin && !tlenv.isIos) {\n\t\t\tdeltaX = deltaY\n\t\t\tdeltaY = 0\n\t\t}\n\t}\n\n\treturn { x: -deltaX, y: -deltaY, z: -deltaZ }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAsB;AAEtB,MAAM,gBAAgB;AAOf,SAAS,eAAe,OAAmD;AACjF,MAAI,EAAE,QAAQ,OAAO,IAAI;AACzB,MAAI,SAAS;AAGb,MAAI,MAAM,WAAW,MAAM,UAAU,MAAM,SAAS;AACnD,cAAU,KAAK,IAAI,MAAM,IAAI,gBAAgB,gBAAgB,KAAK,KAAK,MAAM,IAAI,UAAU;AAAA,EAC5F,OAAO;AACN,QAAI,MAAM,YAAY,CAAC,yBAAM,YAAY,CAAC,yBAAM,OAAO;AACtD,eAAS;AACT,eAAS;AAAA,IACV;AAAA,EACD;AAEA,SAAO,EAAE,GAAG,CAAC,QAAQ,GAAG,CAAC,QAAQ,GAAG,CAAC,OAAO;AAC7C;",
4
+ "sourcesContent": ["import { tlenv } from '../globals/environment'\n\nconst MAX_ZOOM_STEP = 10\n\n/**\n * Normalizes a wheel event, so that the delta values are consistent across different browsers or devices. Adapted from https://stackoverflow.com/a/13650579.\n * @param event - The wheel event to normalize.\n * @returns The normalized wheel event.\n * @internal */\nexport function normalizeWheel(event: WheelEvent | React.WheelEvent<HTMLElement>) {\n\tlet { deltaY, deltaX } = event\n\n\t// Coerce non-finite deltas to no movement so they can't propagate into the camera and\n\t// crash validation. Also covers deltaZ below, which is derived from deltaY.\n\tif (!Number.isFinite(deltaX)) deltaX = 0\n\tif (!Number.isFinite(deltaY)) deltaY = 0\n\n\tlet deltaZ = 0\n\n\t// wheeling\n\tif (event.ctrlKey || event.altKey || event.metaKey) {\n\t\tdeltaZ = (Math.abs(deltaY) > MAX_ZOOM_STEP ? MAX_ZOOM_STEP * Math.sign(deltaY) : deltaY) / 100\n\t} else {\n\t\tif (event.shiftKey && !tlenv.isDarwin && !tlenv.isIos) {\n\t\t\tdeltaX = deltaY\n\t\t\tdeltaY = 0\n\t\t}\n\t}\n\n\treturn { x: -deltaX, y: -deltaY, z: -deltaZ }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAAsB;AAEtB,MAAM,gBAAgB;AAOf,SAAS,eAAe,OAAmD;AACjF,MAAI,EAAE,QAAQ,OAAO,IAAI;AAIzB,MAAI,CAAC,OAAO,SAAS,MAAM,EAAG,UAAS;AACvC,MAAI,CAAC,OAAO,SAAS,MAAM,EAAG,UAAS;AAEvC,MAAI,SAAS;AAGb,MAAI,MAAM,WAAW,MAAM,UAAU,MAAM,SAAS;AACnD,cAAU,KAAK,IAAI,MAAM,IAAI,gBAAgB,gBAAgB,KAAK,KAAK,MAAM,IAAI,UAAU;AAAA,EAC5F,OAAO;AACN,QAAI,MAAM,YAAY,CAAC,yBAAM,YAAY,CAAC,yBAAM,OAAO;AACtD,eAAS;AACT,eAAS;AAAA,IACV;AAAA,EACD;AAEA,SAAO,EAAE,GAAG,CAAC,QAAQ,GAAG,CAAC,QAAQ,GAAG,CAAC,OAAO;AAC7C;",
6
6
  "names": []
7
7
  }
@@ -22,10 +22,10 @@ __export(version_exports, {
22
22
  version: () => version
23
23
  });
24
24
  module.exports = __toCommonJS(version_exports);
25
- const version = "5.4.0-canary.b41840d4f0e4";
25
+ const version = "5.4.0-canary.b8ec00e16e3a";
26
26
  const publishDates = {
27
27
  major: "2026-05-06T16:28:18.473Z",
28
- minor: "2026-08-05T11:54:17.263Z",
29
- patch: "2026-08-05T11:54:17.263Z"
28
+ minor: "2026-08-10T11:16:23.204Z",
29
+ patch: "2026-08-10T11:16:23.204Z"
30
30
  };
31
31
  //# sourceMappingURL=version.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/version.ts"],
4
- "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '5.4.0-canary.b41840d4f0e4'\nexport const publishDates = {\n\tmajor: '2026-05-06T16:28:18.473Z',\n\tminor: '2026-08-05T11:54:17.263Z',\n\tpatch: '2026-08-05T11:54:17.263Z',\n}\n"],
4
+ "sourcesContent": ["// This file is automatically generated by internal/scripts/refresh-assets.ts.\n// Do not edit manually. Or do, I'm a comment, not a cop.\n\nexport const version = '5.4.0-canary.b8ec00e16e3a'\nexport const publishDates = {\n\tmajor: '2026-05-06T16:28:18.473Z',\n\tminor: '2026-08-10T11:16:23.204Z',\n\tpatch: '2026-08-10T11:16:23.204Z',\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,MAAM,UAAU;AAChB,MAAM,eAAe;AAAA,EAC3B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACR;",
6
6
  "names": []
7
7
  }
@@ -305,7 +305,7 @@ import { LocalIndexedDb, Table } from "./lib/utils/sync/LocalIndexedDb.mjs";
305
305
  import { uniq } from "./lib/utils/uniq.mjs";
306
306
  registerTldrawLibraryVersion(
307
307
  "@tldraw/editor",
308
- "5.4.0-canary.b41840d4f0e4",
308
+ "5.4.0-canary.b8ec00e16e3a",
309
309
  "esm"
310
310
  );
311
311
  import { getColorValue } from "./lib/editor/managers/ThemeManager/defaultThemes.mjs";
@@ -4331,17 +4331,16 @@ class Editor extends EventEmitter {
4331
4331
  let inMarginClosestToEdgeHit = null;
4332
4332
  const searchMargin = Math.max(innerMargin, outerMargin, this.getHitTestMargin());
4333
4333
  const candidateIds = this._spatialIndex.getShapeIdsAtPoint(point, searchMargin);
4334
- const shapesToCheck = (opts.renderingOnly ? this.getCurrentPageRenderingShapesSorted() : this.getCurrentPageShapesSorted()).filter((shape) => {
4335
- if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) return false;
4336
- if (shape.isLocked && !hitLocked || this.isShapeHidden(shape) || this.isShapeOfType(shape, "group"))
4337
- return false;
4338
- const pageMask = this.getShapeMask(shape);
4339
- if (pageMask && !pointInPolygon(point, pageMask)) return false;
4340
- if (filter && !filter(shape)) return false;
4341
- return true;
4342
- });
4334
+ const shapesToCheck = opts.renderingOnly ? this.getCurrentPageRenderingShapesSorted() : this.getCurrentPageShapesSorted();
4343
4335
  for (let i = shapesToCheck.length - 1; i >= 0; i--) {
4344
4336
  const shape = shapesToCheck[i];
4337
+ if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) continue;
4338
+ if (shape.isLocked && !hitLocked || this.isShapeHidden(shape) || this.isShapeOfType(shape, "group")) {
4339
+ continue;
4340
+ }
4341
+ const pageMask = this.getShapeMask(shape);
4342
+ if (pageMask && !pointInPolygon(point, pageMask)) continue;
4343
+ if (filter && !filter(shape)) continue;
4345
4344
  const geometry = this.getShapeGeometry(shape);
4346
4345
  const isGroup = geometry instanceof Group2d;
4347
4346
  const pointInShapeSpace = this.getPointInShapeSpace(shape, point);
@@ -4446,11 +4445,15 @@ class Editor extends EventEmitter {
4446
4445
  getShapesAtPoint(point, opts = {}) {
4447
4446
  const margin = opts.margin ?? 0;
4448
4447
  const candidateIds = this._spatialIndex.getShapeIdsAtPoint(point, margin);
4449
- return this.getCurrentPageShapesSorted().filter((shape) => {
4450
- if (this.isShapeHidden(shape)) return false;
4451
- if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) return false;
4452
- return this.isPointInShape(shape, point, opts);
4453
- }).reverse();
4448
+ const sorted = this.getCurrentPageShapesSorted();
4449
+ const result = [];
4450
+ for (let i = sorted.length - 1; i >= 0; i--) {
4451
+ const shape = sorted[i];
4452
+ if (this.isShapeHidden(shape)) continue;
4453
+ if (!candidateIds.has(shape.id) && !this.isShapeFrameLike(shape)) continue;
4454
+ if (this.isPointInShape(shape, point, opts)) result.push(shape);
4455
+ }
4456
+ return result;
4454
4457
  }
4455
4458
  /**
4456
4459
  * Get shape IDs within the given bounds.