@weasel-js/guides 1.14.2 → 1.15.0

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.
package/README.md CHANGED
@@ -42,9 +42,25 @@ source it is built from, `createGridLayer` and `gridSnapSource`, go to
42
42
  `<SceneCanvas layers>` and `snap.sources` on their own where a canvas wants
43
43
  only one of them.
44
44
 
45
+ `spacing` is a pitch for both axes, or a rule per axis. An axis left out has
46
+ no lines, so it neither draws nor snaps:
47
+
48
+ ```ts
49
+ createGridPreset({ spacing: { y: 25 } }); // slatwall: rows only
50
+ createGridPreset({ spacing: { x: { at: [0, 40, 55, 100] }, y: 10 } }); // uneven bays
51
+ createGridPreset({ spacing: { x: { pitch: 25.4, offset: 12.7, from: 12.7, to: 600 }, y: 25.4 } });
52
+ ```
53
+
54
+ A container can run a grid of its own, which its children snap to in its frame
55
+ (from its corner, turned and scaled as it is): pass `gridOf` to the snap source
56
+ (or the preset's `snap`), and the same `gridOf` to `sceneGridRegions` for the
57
+ layer's `regions`. A node declaring snap anchors (`<SceneCanvas snap={{ anchors }}>`)
58
+ lands those on the grid instead of its box, and `gridFit` checks whether a set of
59
+ points sits on its crossings.
60
+
45
61
  | Area | Exports |
46
62
  |---|---|
47
- | Grid | `createGridPreset`, `createGridLayer`, `createCellHighlightLayer`, `useGridCellHover`, `pointToGridCell`, `roundToCell` |
63
+ | Grid | `createGridPreset`, `createGridLayer`, `createCellHighlightLayer`, `useGridCellHover`, `pointToGridCell`, `roundToCell`, `sceneGridRegions`, `gridLines`, `gridFit` |
48
64
  | Guides | `useGuides`, `createGuidesLayer`, `deriveAlignmentGuides`, `matchSpacing`, `measureGaps`, `siblingBounds`, `worldBoundsOf`, `worldUnionOf` |
49
65
  | Snap sources | `gridSnapSource`, `guideSnapSource`, `alignmentSnapSource`, `spacingSnapSource`, for `<SceneCanvas snap={{ sources }}>` or a preset's `snapSources` |
50
66
  | Spacing hints | `createSpacingHintsPreset` (below), `distanceReadout`, `measureDistances` |
package/dist/index.d.ts CHANGED
@@ -1,23 +1,123 @@
1
1
  import { RefObject } from 'react';
2
- import { UnitScope, Scene, NodeId, PlaneValue, PlaneUnits, PerAxis, ViewTransform, View, Dims, CommandStroke, RenderLayer, CommandFill, SnapSource, FeaturePreset, Bounds, PlaneMap, PoseDescriptor, SceneNode, SurfaceContribution, LayoutSnap, LayoutStrategy, LayoutContainer, Vec2, ContainerBounds, LayoutChild } from '@weasel-js/core';
2
+ import { PlaneValue, PerAxis, UnitScope, PlaneUnits, NodeId, ScopedScene, Scene, ViewTransform, View, Dims, CommandStroke, RenderLayer, CommandFill, SnapSource, FeaturePreset, Bounds, PlaneMap, PoseDescriptor, SceneNode, SurfaceContribution, LayoutSnap, LayoutStrategy, LayoutContainer, Vec2, ContainerBounds, LayoutChild } from '@weasel-js/core';
3
3
  import { Affine, Rect as Rect$1 } from '@weasel-js/geom';
4
4
 
5
5
  /** Round `value` to the nearest multiple of `cellSize`. Returns 0 when the result would be -0. */
6
6
  declare function roundToCell(value: number, cellSize: number): number;
7
7
 
8
- type Point$1 = {
8
+ /** A length on a grid: a bare number, or a value tagged with a unit. */
9
+ type GridLength = Exclude<PlaneValue, PerAxis<unknown>>;
10
+ /**
11
+ * One axis of a grid: a pitch from zero; a pitch with an `offset` its lines
12
+ * pass through, limited to `from`..`to` (inclusive); or lines at explicit
13
+ * positions, for uneven bays. Positions are measured from the grid's origin:
14
+ * a container's corner, or the root's origin. A pitch that is not a positive
15
+ * finite number gives the axis no lines.
16
+ */
17
+ type GridAxis = GridLength | {
18
+ pitch: GridLength;
19
+ offset?: GridLength;
20
+ from?: GridLength;
21
+ to?: GridLength;
22
+ } | {
23
+ at: readonly GridLength[];
24
+ };
25
+ /** A grid's lines: one rule for both axes, or one per axis. An axis left out
26
+ * has no lines: it draws none and nothing snaps on it. */
27
+ type GridSpacing = GridLength | {
28
+ x?: GridAxis;
29
+ y?: GridAxis;
30
+ };
31
+ /** An axis's lines, resolved to numbers in the space the grid runs in. */
32
+ type AxisLines = {
33
+ pitch: number;
34
+ offset: number;
35
+ from: number;
36
+ to: number;
37
+ } | {
38
+ at: readonly number[];
39
+ };
40
+ /** A grid's lines on each axis, `null` where it has none. */
41
+ type GridLines = PerAxis<AxisLines | null>;
42
+ type Axis = 'x' | 'y';
43
+ /** `spacing`'s lines, each length read by `read` for its axis. */
44
+ declare function resolveGridLines(spacing: GridSpacing, read: (v: GridLength, axis: Axis) => number): GridLines;
45
+ /** The line at or before `v` and the one after it, nearer first, the upper
46
+ * on a tie; at an end of the lines, the two nearest. Empty where the axis
47
+ * has no line. */
48
+ declare function linesNear(a: AxisLines, v: number): number[];
49
+ /** The line nearest `v`, or `null` where the axis has none. */
50
+ declare function nearestLine(a: AxisLines, v: number): number | null;
51
+ /** Every line from `lo` to `hi`, in order. The caller bounds how many a
52
+ * pitch gives over the span. */
53
+ declare function linesIn(a: AxisLines, lo: number, hi: number): number[];
54
+ /** The cell holding `v`: the gap between two adjacent lines, numbered from
55
+ * the line through the offset (or the first explicit line). An axis with
56
+ * no lines is one cell, `0`, without end. `null` outside the lines. */
57
+ declare function cellOf(a: AxisLines | null, v: number): {
58
+ index: number;
59
+ lo: number;
60
+ hi: number;
61
+ } | null;
62
+ /** `a` with every position `p` moved to `p * scale + shift`. */
63
+ declare function mapLines(a: AxisLines, scale: number, shift: number): AxisLines;
64
+
65
+ /** An axis-aligned rectangle, in whatever coordinates a lattice is drawn in. */
66
+ type Rect = {
9
67
  x: number;
10
68
  y: number;
69
+ width: number;
70
+ height: number;
11
71
  };
12
- /** A container that declares its own unit scope, where a grid draws and
13
- * hit-tests that scope's lattice instead of its parent's. */
72
+
73
+ /** How a grid reads the unit scopes a scene's containers declare
74
+ * (`GroupNode.units`). */
75
+ interface GridScopes {
76
+ /** The scene's outermost scope, as `sceneUnitScopes` is handed it. The grid's
77
+ * `spacing` is read in its system, in place of `unitSystem`. */
78
+ root: UnitScope;
79
+ /** The grid inside a container's scope, written in that scope's units.
80
+ * Default: the grid's `spacing`, read there, so a bare 10 is ten of its
81
+ * base units. */
82
+ spacing?: (scope: UnitScope) => GridSpacing;
83
+ }
84
+ /**
85
+ * A grid's lines in world units: read in `chain` (the root alone by default)
86
+ * when `scopes` is given, else against `unitSystem`. What every grid reader
87
+ * that takes both asks.
88
+ */
89
+ declare function gridLines(spacing: GridSpacing, unitSystem: PlaneUnits | undefined, scopes: GridScopes | undefined, chain?: readonly UnitScope[]): GridLines;
90
+ /** A container's lattice in its own coordinates: its `own` grid (`gridOf`;
91
+ * `null` for none), else the one its scope gives, read in `chain`. */
92
+ declare function containerLines(own: GridSpacing | null | undefined, spacing: GridSpacing, unitSystem: PlaneUnits | undefined, scopes: GridScopes | undefined, chain: readonly UnitScope[] | undefined): GridLines | null;
93
+
94
+ type Point$2 = {
95
+ x: number;
96
+ y: number;
97
+ };
98
+ /** Which of a scene's containers run a grid of their own. */
99
+ interface GridOwners {
100
+ /** The scene's outermost unit scope: given, every container declaring a
101
+ * scope (`GroupNode.units`) runs that scope's lattice, and lengths inside
102
+ * a container are read in its scope. */
103
+ root?: UnitScope;
104
+ /** A container's own grid: `undefined` to leave it to the container's
105
+ * parent, `null` for no grid inside it at all. Its children snap on it,
106
+ * in the container's frame. */
107
+ gridOf?: (id: NodeId) => GridSpacing | null | undefined;
108
+ }
109
+ /** A container running its own lattice, where a grid draws and hit-tests it
110
+ * instead of its parent's. */
14
111
  interface GridRegion {
15
112
  /** The container's outline in world units, as a closed polygon. */
16
- outline: readonly Point$1[];
17
- /** The scopes its lattice is read in, outermost first, rooted at the
18
- * grid's `scopes.root`, the container's own scope last. */
19
- chain: readonly UnitScope[];
20
- /** Scoped containers inside this one. */
113
+ outline: readonly Point$2[];
114
+ /** The scopes its lattice is read in, outermost first, rooted at
115
+ * `GridOwners.root`, the container's own scope last. Absent without one. */
116
+ chain?: readonly UnitScope[];
117
+ /** Its own grid, from `gridOf`: `null` for none. Absent, it runs the grid's
118
+ * `spacing`, or its scope's (`GridScopes.spacing`). */
119
+ spacing?: GridSpacing | null;
120
+ /** Containers inside this one running their own. */
21
121
  regions?: readonly GridRegion[];
22
122
  /** The container's frame, its own coordinates to world (`sceneBoxFrames`):
23
123
  * its lattice runs from the frame's origin along its axes, in its units,
@@ -26,68 +126,51 @@ interface GridRegion {
26
126
  frame?: Affine;
27
127
  }
28
128
  /**
29
- * Every container in `scene` declaring a unit scope, as `GridRegion`s nested
129
+ * Every container in `scene` running its own grid, as `GridRegion`s nested
30
130
  * the way the containers are, each in its box frame. `outlineOf` gives a
31
- * node's world outline, or `null` to leave it, and every scope inside it,
131
+ * node's world outline, or `null` to leave it, and every region inside it,
32
132
  * out; by default, a box pose's outline as it is drawn, and none for any
33
133
  * other pose.
34
134
  */
35
- declare function sceneGridRegions(scene: Scene<unknown, string, unknown>, root: UnitScope, outlineOf?: (id: NodeId) => readonly Point$1[] | null): GridRegion[];
135
+ declare function sceneGridRegions(scene: Scene<unknown, string, unknown>, owners: GridOwners, outlineOf?: (id: NodeId) => readonly Point$2[] | null): GridRegion[];
136
+ /** The nearest container above `id` running its own grid, or `null` for the
137
+ * root's: whose lattice `id` sits on. `inclusive` counts `id` itself. */
138
+ declare function gridOwner(scene: ScopedScene, id: NodeId, owners: GridOwners, inclusive?: boolean): NodeId | null;
36
139
  /** The innermost region holding `point`, or `null` outside them all. */
37
- declare function regionAt(regions: readonly GridRegion[] | undefined, point: Point$1): GridRegion | null;
140
+ declare function regionAt(regions: readonly GridRegion[] | undefined, point: Point$2): GridRegion | null;
38
141
 
39
- /** How a grid reads the unit scopes a scene's containers declare
40
- * (`GroupNode.units`). */
41
- interface GridScopes {
42
- /** The scene's outermost scope, as `sceneUnitScopes` is handed it. The grid's
43
- * `spacing` is read in its system, in place of `unitSystem`. */
44
- root: UnitScope;
45
- /** The pitch inside a container's scope, written in that scope's units.
46
- * Default: the grid's `spacing`, read there, so a bare 10 is ten of its
47
- * base units. */
48
- spacing?: (scope: UnitScope) => PlaneValue;
49
- }
50
- /**
51
- * A grid's pitch on each axis, in world units, where `chain` (outermost
52
- * first, rooted at `scopes.root`) encloses it: `spacing` in the root, and
53
- * `scopes.spacing` of the innermost scope inside a container's.
54
- */
55
- declare function scopedGridPitch(spacing: PlaneValue, scopes: GridScopes, chain: readonly UnitScope[]): PerAxis<number>;
56
- /**
57
- * A grid's pitch in world units: read in `chain` (the root alone by default)
58
- * when `scopes` is given, else against `unitSystem`. What every grid reader
59
- * that takes both asks.
60
- */
61
- declare function gridPitch(spacing: PlaneValue, unitSystem: PlaneUnits | undefined, scopes: GridScopes | undefined, chain?: readonly UnitScope[]): PerAxis<number>;
62
-
63
- /** A cell of a grid. `pitch` names the lattice it belongs to, in world units,
64
- * where a grid reads unit scopes; without it, the cell is the grid's own.
65
- * `frame` is that lattice's region's frame, the cell counted from its origin. */
142
+ /** A cell of a grid: the gap between two adjacent lines on each axis,
143
+ * numbered from the line through each axis's offset (or its first explicit
144
+ * line). `box` is the cell in the grid's space: world, or `frame`'s, the
145
+ * frame of the region whose lattice it is on. An axis with no lines is one
146
+ * cell, `0`, spanning the region, or without end at the root. */
66
147
  interface GridCell {
67
148
  col: number;
68
149
  row: number;
69
- pitch?: PerAxis<number>;
150
+ box: Rect;
70
151
  frame?: Affine;
71
152
  }
72
- /** Where a grid reads unit scopes: `scopes`, and the containers declaring them. */
153
+ /** Where a grid's containers run lattices of their own: the unit `scopes`
154
+ * it reads, and the `regions` (`sceneGridRegions`) running them. */
73
155
  interface GridScoping {
74
- scopes: GridScopes;
156
+ scopes?: GridScopes;
75
157
  regions?: readonly GridRegion[];
76
158
  }
77
159
  /**
78
- * The integer cell `{col, row}` that contains `point`. Pair with
160
+ * The cell holding `point`, on the lattice of the innermost region holding
161
+ * it, else the root's, which runs through `origin`. Pair with
79
162
  * `createCellHighlightLayer` (its `getCell` callback) to draw a snap-target
80
- * preview that uses the same spacing as `gridSnapSource`. Given `scoped`,
81
- * the cell is on the lattice of the innermost region holding `point`, and
82
- * carries that lattice's `pitch`, and its `frame` where the region has one.
163
+ * preview on the lattice `gridSnapSource` snaps to. `null` where `point` is
164
+ * outside the lines: past a range a pitch is limited to, or the explicit
165
+ * lines, or in a region with no grid.
83
166
  */
84
167
  declare function pointToGridCell(point: {
85
168
  x: number;
86
169
  y: number;
87
- }, spacing: PlaneValue, unitSystem?: PlaneUnits, origin?: {
170
+ }, spacing: GridSpacing, unitSystem?: PlaneUnits, origin?: {
88
171
  x: number;
89
172
  y: number;
90
- }, scoped?: GridScoping): GridCell;
173
+ }, scoped?: GridScoping): GridCell | null;
91
174
 
92
175
  /**
93
176
  * Pointer-tracking glue that turns hover position into a grid cell, suitable
@@ -104,9 +187,8 @@ interface UseGridCellHoverOptions {
104
187
  /** Read the current view transform. Called on every pointermove so it can
105
188
  * reflect live pan/zoom without a re-binding step. */
106
189
  view: () => ViewTransform;
107
- /** Cell spacing in world units. Same value you pass to `createGridLayer`
108
- * and `createCellHighlightLayer`. */
109
- spacing: PlaneValue;
190
+ /** The grid's lines. Same value you pass to `createGridLayer`. */
191
+ spacing: GridSpacing;
110
192
  /** Required if `spacing` is tagged (e.g. `{ value: 1, unit: 'ft' }`). */
111
193
  unitSystem?: PlaneUnits;
112
194
  /** Origin the cell grid is anchored to, in world units. Default `(0, 0)`. */
@@ -114,10 +196,10 @@ interface UseGridCellHoverOptions {
114
196
  x: number;
115
197
  y: number;
116
198
  };
117
- /** Read `spacing` in these scopes, as `createGridLayer` does: a cell inside
118
- * one of `regions` is on its scope's lattice and carries that `pitch`. */
199
+ /** Read `spacing` in these scopes, as `createGridLayer` does. */
119
200
  scopes?: GridScopes;
120
- /** The containers declaring scopes, read on every pointermove. */
201
+ /** The containers running lattices of their own, read on every
202
+ * pointermove: a cell inside one is on its lattice, in its frame. */
121
203
  regions?: () => readonly GridRegion[];
122
204
  /** Fires when the hovered cell changes (including to/from `null`). Use it
123
205
  * to invalidate your layer renderer. */
@@ -136,14 +218,6 @@ interface UseGridCellHoverReturn {
136
218
  /** Track which grid cell the pointer is over; pairs with `createCellHighlightLayer`. */
137
219
  declare function useGridCellHover(opts: UseGridCellHoverOptions): UseGridCellHoverReturn;
138
220
 
139
- /** An axis-aligned rectangle, in whatever coordinates a lattice is drawn in. */
140
- type Rect = {
141
- x: number;
142
- y: number;
143
- width: number;
144
- height: number;
145
- };
146
-
147
221
  /**
148
222
  * Grid overlay — a reusable render layer that draws a world-space grid with
149
223
  * optional finer subdivisions and accent lines every N cells.
@@ -157,26 +231,26 @@ type Rect = {
157
231
  /** Options for `createGridLayer`. */
158
232
  interface GridLayerOpts {
159
233
  /**
160
- * Distance between adjacent grid lines (also known as grid pitch),
161
- * in world (base) units. Accepts a bare number or a tagged
162
- * `{ value, unit }`. Tagged values require `unitSystem` to be supplied.
163
- * Either may be per axis — `{ x, y }`.
234
+ * The grid's lines: a pitch for both axes, or a rule per axis (`{ x, y }`,
235
+ * see `GridAxis`), an axis left out drawing none. Lengths are a bare
236
+ * number in world (base) units or a tagged `{ value, unit }`, which needs
237
+ * `unitSystem`.
164
238
  */
165
- spacing: PlaneValue;
239
+ spacing: GridSpacing;
166
240
  /** Optional unit system for resolving tagged `spacing` values. */
167
241
  unitSystem?: PlaneUnits;
168
242
  /** Read `spacing` in these scopes, in place of `unitSystem`: the root's
169
243
  * system outside every region, and each region's own scope inside it. */
170
244
  scopes?: GridScopes;
171
- /** The containers drawing their own scope's lattice, read every paint,
172
- * each cut out of the lattice around it and drawn in its own `frame`.
173
- * Read only with `scopes`; `sceneGridRegions` builds them from a scene. */
245
+ /** The containers drawing a lattice of their own, read every paint, each
246
+ * cut out of the lattice around it and drawn in its own `frame`:
247
+ * `sceneGridRegions` builds them from a scene. */
174
248
  regions?: () => readonly GridRegion[];
175
249
  /**
176
250
  * The area to cover, in world units, read every paint with that paint's
177
251
  * view and canvas size. Lines start at its own `x`/`y`. Omitted, the grid
178
- * covers whatever the canvas shows, with its lines on world multiples of
179
- * `spacing` so they stay put as the view pans.
252
+ * covers whatever the canvas shows, with its lines measured from world
253
+ * zero so they stay put as the view pans.
180
254
  */
181
255
  bounds?: (view: View, dims: Dims) => Rect;
182
256
  /** Lines every N cells get the accent style. 0/undef = no accent. */
@@ -201,18 +275,8 @@ declare function createGridLayer(opts: GridLayerOpts): RenderLayer<unknown>;
201
275
 
202
276
  /** Options for `createCellHighlightLayer`. */
203
277
  interface CellHighlightLayerOpts {
204
- /** Cell size in world units (matches the grid's `spacing`). */
205
- spacing: PlaneValue;
206
- /** Optional unit system for resolving tagged `spacing` values. */
207
- unitSystem?: PlaneUnits;
208
- /** Origin the cell grid is anchored to, in world units. Defaults to (0,0). */
209
- origin?: () => {
210
- x: number;
211
- y: number;
212
- };
213
- /** Cell to highlight, or `null` to skip drawing. A cell carrying its
214
- * lattice's `pitch` (`useGridCellHover` with `scopes`) is drawn at it,
215
- * and one carrying a `frame` is drawn in it, from its origin. */
278
+ /** Cell to highlight, or `null` to skip drawing: its `box`, in its
279
+ * `frame` where it has one (`pointToGridCell`, `useGridCellHover`). */
216
280
  getCell: () => GridCell | null;
217
281
  /** Fill for the highlighted cell. Defaults to a soft green. */
218
282
  fill?: CommandFill;
@@ -220,32 +284,60 @@ interface CellHighlightLayerOpts {
220
284
  /** Build a `RenderLayer` that fills a single grid cell — typically a snap-target preview. */
221
285
  declare function createCellHighlightLayer(opts: CellHighlightLayerOpts): RenderLayer<unknown>;
222
286
 
287
+ type Point$1 = {
288
+ x: number;
289
+ y: number;
290
+ };
291
+ /** A point of `gridFit` off its line on one axis, by `distance`. */
292
+ interface GridMiss {
293
+ index: number;
294
+ axis: 'x' | 'y';
295
+ distance: number;
296
+ }
297
+ /**
298
+ * Whether every one of `points` sits within `tolerance` of a line on each
299
+ * axis `lines` has lines on, so on a crossing where it has both: a hanger's
300
+ * holes on a pegboard's. Points and tolerance are in the grid's own space,
301
+ * measured from its origin; `gridLines` resolves a `GridSpacing` into it.
302
+ */
303
+ declare function gridFit(points: readonly Point$1[], lines: GridLines, tolerance?: number): {
304
+ fits: boolean;
305
+ misses: GridMiss[];
306
+ };
307
+
223
308
  type Point = {
224
309
  x: number;
225
310
  y: number;
226
311
  };
227
312
  /** Options for `gridSnapSource`. */
228
313
  interface GridSnapSourceOptions {
229
- /** The grid's pitch, or one per axis, in `unitSystem`'s units. */
230
- spacing: PlaneValue;
231
- /** A point the lattice passes through. Default `(0, 0)`. */
314
+ /** The grid's lines, one rule for both axes or one per axis, in
315
+ * `unitSystem`'s units. */
316
+ spacing: GridSpacing;
317
+ /** A point the root's lattice passes through. Default `(0, 0)`. */
232
318
  origin?: Point;
233
319
  unitSystem?: PlaneUnits;
234
320
  /** Read the unit scope the subject sits in: a node inside a millimeter
235
- * sub-assembly snaps on that scope's pitch. The subject's scope is the one
236
- * all its nodes share; for a gesture with none, the scope of the
237
- * container it draws into (`SnapCollect.parent`), else the root. When that
238
- * scope is one container's, the lattice runs in its frame
239
- * (`SnapCollect.frameOf`): from its corner, turned as it is. */
321
+ * sub-assembly snaps on that scope's lattice, in that container's frame. */
240
322
  scopes?: GridScopes;
323
+ /** A container's own grid, which its children snap on in its frame (from
324
+ * its corner, turned and scaled as it is): the nearest container above
325
+ * the subject with one, or with a unit scope under `scopes`. `null` for a
326
+ * container with no grid inside it. */
327
+ gridOf?: GridOwners['gridOf'];
328
+ /** The source's id, so two grids can snap on one canvas. Default `'grid'`. */
329
+ id?: string;
241
330
  }
242
331
  /**
243
- * A grid as snap targets: for each box or pointer probe, the grid line on
244
- * either side of it on each axis, so a move lands the drawn box, stroke
332
+ * A grid as snap targets: for each probe, the grid line on either side of it
333
+ * on each axis the grid has lines on, so a move lands the drawn box, stroke
245
334
  * included, with an edge or its center on a line; on a turned container's
246
- * lattice, which no world-axis box lines up with, its pose origin. Its reach is unlimited and it is a
247
- * fallback, so it holds every axis no target claims and never displaces one.
248
- * Its lines are the camera's, carried into the plane a gesture runs in.
335
+ * lattice, which no world-axis box lines up with, its pose origin. A subject
336
+ * declaring snap anchors (`SceneCanvasSnap.anchors`) lands those instead of
337
+ * its box. Nodes spread over containers snap on the lattice they all run,
338
+ * along the world's axes, and on none where those differ. Its reach is unlimited and it is a fallback,
339
+ * so it holds every axis no target claims and never displaces one. Its lines
340
+ * are the camera's, carried into the plane a gesture runs in.
249
341
  */
250
342
  declare function gridSnapSource(opts: GridSnapSourceOptions): SnapSource;
251
343
 
@@ -254,9 +346,11 @@ interface GridPresetOptions extends GridLayerOpts {
254
346
  /** Preset id. Default `'grid'`. */
255
347
  id?: string;
256
348
  /** Snap gestures to the grid's lines, on its `spacing`, `unitSystem` and
257
- * `scopes`; `origin` is where the snap lattice starts. `false` draws the
258
- * grid without snapping to it. Default on, from `(0, 0)`. */
259
- snap?: false | Pick<GridSnapSourceOptions, 'origin'>;
349
+ * `scopes`; `origin` is where the snap lattice starts, and `gridOf` gives
350
+ * containers their own (pair it with `regions` from `sceneGridRegions`
351
+ * with the same `gridOf`, so what is drawn is what snaps). `false` draws
352
+ * the grid without snapping to it. Default on, from `(0, 0)`. */
353
+ snap?: false | Pick<GridSnapSourceOptions, 'origin' | 'gridOf'>;
260
354
  }
261
355
  /**
262
356
  * A grid as one `<SceneCanvas features>` preset: the lattice drawn in the
@@ -917,4 +1011,4 @@ interface Sequencer<TPose> {
917
1011
  */
918
1012
  declare function sequenceLayout<TPose>(seq: Sequencer<TPose>): LayoutStrategy<TPose>;
919
1013
 
920
- export { type AlignmentSnapSourceOptions, type Arrangement, type CellHighlightLayerOpts, type DeriveAlignmentGuidesOptions, type DistanceReadout, type DistanceReadoutContribution, type DistanceReadoutOptions, type FreeformOptions, type GridCell, type GridLayerOpts, type GridPresetOptions, type GridRegion, type GridScopes, type GridScoping, type GridSlotsOptions, type GridSnapSourceOptions, type Guide, type GuidesLayerOpts, type PackOptions, type PackOverflow, type PerContainerOptions, type PerContainerStrategy, type QuadtreeCell, type QuadtreeOptions, type QuadtreeStrategy, type RingSlotsOptions, type RowSlotsOptions, type SceneBoundsOptions, type Sequencer, type Slot, type SlotsOptions, type SnapPattern, type SnapPointOptions, type SpacingEdge, type SpacingGap, type SpacingHintsOptions, type SpacingMatchResult, type SpacingSnapSourceOptions, type TargetFilter, type TileGridOptions, type TileGridOverflow, type UseGridCellHoverOptions, type UseGridCellHoverReturn, type UseGuidesReturn, alignmentSnapSource, cellAt, containedThenNearest, createCellHighlightLayer, createGridLayer, createGridPreset, createGuidesLayer, createSpacingHintsPreset, deriveAlignmentGuides, distanceReadout, freeform, gridPitch, gridSlots, gridSnapSource, guideSnapSource, matchSpacing, measureDistances, measureGaps, nearest, nearestWithin, none, pack, perContainer, pointToGridCell, quadtree, regionAt, ringSlots, roundToCell, rowSlots, sceneGridRegions, scopedGridPitch, sequenceLayout, siblingBounds, slots, snapPoint, spacingSnapSource, tileGrid, useGridCellHover, useGuides, worldBoundsOf, worldUnionOf };
1014
+ export { type AlignmentSnapSourceOptions, type Arrangement, type AxisLines, type CellHighlightLayerOpts, type DeriveAlignmentGuidesOptions, type DistanceReadout, type DistanceReadoutContribution, type DistanceReadoutOptions, type FreeformOptions, type GridAxis, type GridCell, type GridLayerOpts, type GridLength, type GridLines, type GridMiss, type GridOwners, type GridPresetOptions, type GridRegion, type GridScopes, type GridScoping, type GridSlotsOptions, type GridSnapSourceOptions, type GridSpacing, type Guide, type GuidesLayerOpts, type PackOptions, type PackOverflow, type PerContainerOptions, type PerContainerStrategy, type QuadtreeCell, type QuadtreeOptions, type QuadtreeStrategy, type RingSlotsOptions, type RowSlotsOptions, type SceneBoundsOptions, type Sequencer, type Slot, type SlotsOptions, type SnapPattern, type SnapPointOptions, type SpacingEdge, type SpacingGap, type SpacingHintsOptions, type SpacingMatchResult, type SpacingSnapSourceOptions, type TargetFilter, type TileGridOptions, type TileGridOverflow, type UseGridCellHoverOptions, type UseGridCellHoverReturn, type UseGuidesReturn, alignmentSnapSource, cellAt, cellOf, containedThenNearest, containerLines, createCellHighlightLayer, createGridLayer, createGridPreset, createGuidesLayer, createSpacingHintsPreset, deriveAlignmentGuides, distanceReadout, freeform, gridFit, gridLines, gridOwner, gridSlots, gridSnapSource, guideSnapSource, linesIn, linesNear, mapLines, matchSpacing, measureDistances, measureGaps, nearest, nearestLine, nearestWithin, none, pack, perContainer, pointToGridCell, quadtree, regionAt, resolveGridLines, ringSlots, roundToCell, rowSlots, sceneGridRegions, sequenceLayout, siblingBounds, slots, snapPoint, spacingSnapSource, tileGrid, useGridCellHover, useGuides, worldBoundsOf, worldUnionOf };