@motionscript/layout-grid 0.0.0-stage → 0.1.0-alpha.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.
Files changed (132) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +201 -0
  3. package/dist/browser/chunks/chunk-PB3E5HQV.js +2 -0
  4. package/dist/browser/chunks/chunk-PB3E5HQV.js.map +7 -0
  5. package/dist/browser/index.js +2 -0
  6. package/dist/browser/index.js.map +7 -0
  7. package/dist/browser/kit.js +2 -0
  8. package/dist/browser/kit.js.map +7 -0
  9. package/dist/browser/manifest.json +12 -0
  10. package/dist/engine.d.ts +13 -0
  11. package/dist/engine.d.ts.map +1 -0
  12. package/dist/engine.js +13 -0
  13. package/dist/engine.js.map +1 -0
  14. package/dist/index.d.ts +7 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +7 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/kit/index.d.ts +7 -0
  19. package/dist/kit/index.d.ts.map +1 -0
  20. package/dist/kit/index.js +7 -0
  21. package/dist/kit/index.js.map +1 -0
  22. package/dist/kit/item-effects.d.ts +37 -0
  23. package/dist/kit/item-effects.d.ts.map +1 -0
  24. package/dist/kit/item-effects.js +76 -0
  25. package/dist/kit/item-effects.js.map +1 -0
  26. package/dist/kit/layout-grid.d.ts +243 -0
  27. package/dist/kit/layout-grid.d.ts.map +1 -0
  28. package/dist/kit/layout-grid.js +542 -0
  29. package/dist/kit/layout-grid.js.map +1 -0
  30. package/dist/kit/order.d.ts +13 -0
  31. package/dist/kit/order.d.ts.map +1 -0
  32. package/dist/kit/order.js +43 -0
  33. package/dist/kit/order.js.map +1 -0
  34. package/dist/kit/random.d.ts +7 -0
  35. package/dist/kit/random.d.ts.map +1 -0
  36. package/dist/kit/random.js +29 -0
  37. package/dist/kit/random.js.map +1 -0
  38. package/dist/kit/slots/index.d.ts +22 -0
  39. package/dist/kit/slots/index.d.ts.map +1 -0
  40. package/dist/kit/slots/index.js +28 -0
  41. package/dist/kit/slots/index.js.map +1 -0
  42. package/dist/kit/slots/path-templates.d.ts +15 -0
  43. package/dist/kit/slots/path-templates.d.ts.map +1 -0
  44. package/dist/kit/slots/path-templates.js +113 -0
  45. package/dist/kit/slots/path-templates.js.map +1 -0
  46. package/dist/kit/slots/path.d.ts +45 -0
  47. package/dist/kit/slots/path.d.ts.map +1 -0
  48. package/dist/kit/slots/path.js +87 -0
  49. package/dist/kit/slots/path.js.map +1 -0
  50. package/dist/kit/slots/radial.d.ts +30 -0
  51. package/dist/kit/slots/radial.d.ts.map +1 -0
  52. package/dist/kit/slots/radial.js +45 -0
  53. package/dist/kit/slots/radial.js.map +1 -0
  54. package/dist/kit/slots/rectangular.d.ts +42 -0
  55. package/dist/kit/slots/rectangular.d.ts.map +1 -0
  56. package/dist/kit/slots/rectangular.js +79 -0
  57. package/dist/kit/slots/rectangular.js.map +1 -0
  58. package/dist/kit/slots/slot.d.ts +62 -0
  59. package/dist/kit/slots/slot.d.ts.map +1 -0
  60. package/dist/kit/slots/slot.js +41 -0
  61. package/dist/kit/slots/slot.js.map +1 -0
  62. package/dist/kit/slots/sphere.d.ts +36 -0
  63. package/dist/kit/slots/sphere.d.ts.map +1 -0
  64. package/dist/kit/slots/sphere.js +68 -0
  65. package/dist/kit/slots/sphere.js.map +1 -0
  66. package/dist/kit/stagger.d.ts +24 -0
  67. package/dist/kit/stagger.d.ts.map +1 -0
  68. package/dist/kit/stagger.js +90 -0
  69. package/dist/kit/stagger.js.map +1 -0
  70. package/dist/nodes.d.ts +15 -0
  71. package/dist/nodes.d.ts.map +1 -0
  72. package/dist/nodes.js +15 -0
  73. package/dist/nodes.js.map +1 -0
  74. package/dist/path-grid/index.d.ts +2 -0
  75. package/dist/path-grid/index.d.ts.map +1 -0
  76. package/dist/path-grid/index.js +2 -0
  77. package/dist/path-grid/index.js.map +1 -0
  78. package/dist/path-grid/path-grid.d.ts +82 -0
  79. package/dist/path-grid/path-grid.d.ts.map +1 -0
  80. package/dist/path-grid/path-grid.js +192 -0
  81. package/dist/path-grid/path-grid.js.map +1 -0
  82. package/dist/radial-grid/index.d.ts +2 -0
  83. package/dist/radial-grid/index.d.ts.map +1 -0
  84. package/dist/radial-grid/index.js +2 -0
  85. package/dist/radial-grid/index.js.map +1 -0
  86. package/dist/radial-grid/radial-grid.d.ts +51 -0
  87. package/dist/radial-grid/radial-grid.d.ts.map +1 -0
  88. package/dist/radial-grid/radial-grid.js +95 -0
  89. package/dist/radial-grid/radial-grid.js.map +1 -0
  90. package/dist/rectangular-grid/index.d.ts +2 -0
  91. package/dist/rectangular-grid/index.d.ts.map +1 -0
  92. package/dist/rectangular-grid/index.js +2 -0
  93. package/dist/rectangular-grid/index.js.map +1 -0
  94. package/dist/rectangular-grid/rectangular-grid.d.ts +79 -0
  95. package/dist/rectangular-grid/rectangular-grid.d.ts.map +1 -0
  96. package/dist/rectangular-grid/rectangular-grid.js +156 -0
  97. package/dist/rectangular-grid/rectangular-grid.js.map +1 -0
  98. package/dist/sphere-grid/index.d.ts +2 -0
  99. package/dist/sphere-grid/index.d.ts.map +1 -0
  100. package/dist/sphere-grid/index.js +2 -0
  101. package/dist/sphere-grid/index.js.map +1 -0
  102. package/dist/sphere-grid/sphere-grid.d.ts +68 -0
  103. package/dist/sphere-grid/sphere-grid.d.ts.map +1 -0
  104. package/dist/sphere-grid/sphere-grid.js +149 -0
  105. package/dist/sphere-grid/sphere-grid.js.map +1 -0
  106. package/package.json +69 -3
  107. package/registry.json +32 -0
  108. package/src/engine.ts +12 -0
  109. package/src/index.ts +6 -0
  110. package/src/kit/index.ts +6 -0
  111. package/src/kit/item-effects.ts +114 -0
  112. package/src/kit/layout-grid.ts +605 -0
  113. package/src/kit/order.ts +41 -0
  114. package/src/kit/random.ts +29 -0
  115. package/src/kit/slots/index.ts +39 -0
  116. package/src/kit/slots/path-templates.ts +120 -0
  117. package/src/kit/slots/path.ts +120 -0
  118. package/src/kit/slots/radial.ts +62 -0
  119. package/src/kit/slots/rectangular.ts +108 -0
  120. package/src/kit/slots/slot.ts +82 -0
  121. package/src/kit/slots/sphere.ts +94 -0
  122. package/src/kit/stagger.ts +96 -0
  123. package/src/nodes.ts +15 -0
  124. package/src/path-grid/index.ts +1 -0
  125. package/src/path-grid/path-grid.ts +213 -0
  126. package/src/radial-grid/index.ts +1 -0
  127. package/src/radial-grid/radial-grid.ts +90 -0
  128. package/src/rectangular-grid/index.ts +1 -0
  129. package/src/rectangular-grid/rectangular-grid.ts +160 -0
  130. package/src/sphere-grid/index.ts +1 -0
  131. package/src/sphere-grid/sphere-grid.ts +143 -0
  132. package/README.md +0 -4
@@ -0,0 +1,542 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { command, easeIn, easeInOut, easeOut, flowOps, insetsOps, Node2D, property, sizeInputOps, } from "@motionscript/core";
8
+ import { applyItemEffects, REVEAL_STYLES, WAVE_STYLES, } from "./item-effects.js";
9
+ import { normalizeOrder, parseOrder, slotOfItem } from "./order.js";
10
+ import { hashSeed, shuffled } from "./random.js";
11
+ import { blendSlot, focalLengthOf, slotsOf, spreadSlot } from "./slots/index.js";
12
+ import { STAGGER_ORDERS, staggerProgress, staggerRanks } from "./stagger.js";
13
+ /** `@command` descriptors for {@link StaggerArgs}, `stagger` defaulting to `fallback`. */
14
+ export function staggerArgs(fallback) {
15
+ return [
16
+ { key: "staggerOrder", kind: "enum", options: STAGGER_ORDERS, default: "index" },
17
+ { key: "stagger", min: 0, max: 0.95, step: 0.05, default: fallback },
18
+ ];
19
+ }
20
+ /**
21
+ * Every grid's document key — what a reference to "another grid" may name. A
22
+ * `nodeRef` descriptor carries it as `nodeTypes`, for a host's picker to offer
23
+ * only those.
24
+ */
25
+ export const LAYOUT_GRID_TYPES = ["rectangularGrid", "radialGrid", "pathGrid", "sphereGrid"];
26
+ /** The stagger a move to new slots takes when its command states none. */
27
+ export const TRANSITION_STAGGER = 0.3;
28
+ const NO_CONTENT = { width: 0, height: 0 };
29
+ const CENTRE = { x: 0, y: 0 };
30
+ /**
31
+ * The base of every grid: a container that places each of its children in a
32
+ * slot of an arrangement — a rectangular grid, a ring, a path, a sphere.
33
+ *
34
+ * ## Children only
35
+ *
36
+ * The items are the children, in layer order. A child's slot is a parent
37
+ * transform on it, so its own `x`/`y`/`rotation`/`scale` — and any command on
38
+ * them — still work, relative to the slot. A group is one item; a grid of
39
+ * grids is a grid of items that happen to be grids.
40
+ *
41
+ * ## One pass
42
+ *
43
+ * Every frame: measure the children, ask the arrangement for its slots (a pure
44
+ * function of the props, the sizes and the clock), blend them from where a
45
+ * transition is leaving, and layer on the per-item effects — reveal, wave,
46
+ * focus. What is left is each child's box and {@link ChildPlacement}, which the
47
+ * renderer, picking and `global` all read, so a selection outline lands on
48
+ * the pixels even on a sphere.
49
+ *
50
+ * ## Commands
51
+ *
52
+ * Every command is a pure function of time, like the rest of the library. The
53
+ * per-item ones stagger *inside* their duration — a one-second reveal takes one
54
+ * second for four children or four hundred — and write their per-item state
55
+ * into props ({@link revealState} and its siblings), which is what keeps them
56
+ * seekable. The ones that change the arrangement itself (a reorder, a morph, a
57
+ * column count) keep the arrangement they are leaving as data and blend each
58
+ * item from its old slot to its new one.
59
+ */
60
+ export class LayoutGrid extends Node2D {
61
+ /**
62
+ * Bring the items in, one after another. Every item starts hidden, so place
63
+ * it where the grid enters — or after a {@link conceal}.
64
+ */
65
+ reveal(args) {
66
+ const style = args.data?.style ?? "scale";
67
+ const ease = args.easing ?? (style === "scale" || style === "flip" ? easeOut("back") : easeOut("cubic"));
68
+ const ranks = this._ranks(args.data?.staggerOrder);
69
+ const stagger = args.data?.stagger ?? 0.5;
70
+ return this.command((t) => {
71
+ if (t >= 1)
72
+ return { revealState: null };
73
+ return { revealState: { style, values: ranks.map((rank) => ease(staggerProgress(rank, t, stagger))) } };
74
+ }, args.duration);
75
+ }
76
+ /** Take the items out, one after another — {@link reveal} in reverse. They stay hidden after. */
77
+ conceal(args) {
78
+ const style = args.data?.style ?? "scale";
79
+ const ease = args.easing ?? (style === "scale" || style === "flip" ? easeIn("back") : easeInOut("cubic"));
80
+ const ranks = this._ranks(args.data?.staggerOrder);
81
+ const stagger = args.data?.stagger ?? 0.5;
82
+ const from = this.revealState?.values;
83
+ return this.command((t) => ({
84
+ revealState: {
85
+ style,
86
+ values: ranks.map((rank, i) => (from?.[i] ?? 1) * (1 - ease(staggerProgress(rank, t, stagger)))),
87
+ },
88
+ }), args.duration);
89
+ }
90
+ /** Send a ripple through the items that swells each in turn and settles back. */
91
+ wave(args) {
92
+ const style = args.data?.style ?? "scale";
93
+ const amount = args.data?.amount ?? 0.3;
94
+ const ease = args.easing ?? easeInOut("sine");
95
+ const ranks = this._ranks(args.data?.staggerOrder);
96
+ const stagger = args.data?.stagger ?? 0.7;
97
+ return this.command((t) => {
98
+ if (t >= 1)
99
+ return { waveState: null };
100
+ return {
101
+ waveState: {
102
+ style,
103
+ amount,
104
+ values: ranks.map((rank) => Math.sin(Math.PI * ease(staggerProgress(rank, t, stagger)))),
105
+ },
106
+ };
107
+ }, args.duration);
108
+ }
109
+ /** Bring one item (by its place in the layers, from 0) forward and push the rest back. */
110
+ focus(args) {
111
+ const n = this._itemCount();
112
+ const item = Math.round(args.data?.item ?? 0);
113
+ return this._focusOn((i) => i === item, n, args);
114
+ }
115
+ /** Bring every item back to even. */
116
+ unfocus(args) {
117
+ const from = this.focusState;
118
+ const ease = args.easing ?? easeInOut("cubic");
119
+ return this.command((t) => {
120
+ if (t >= 1 || !from)
121
+ return { focusState: null };
122
+ const k = 1 - ease(t);
123
+ return { focusState: { ...from, values: from.values.map((v) => v * k) } };
124
+ }, args.duration);
125
+ }
126
+ /** Gather the items toward the centre (`0`), back to the arrangement (`1`), or push them apart. */
127
+ spreadTo(args) {
128
+ return this.to({ data: { spread: args.data?.spread ?? 1 }, duration: args.duration, easing: args.easing });
129
+ }
130
+ /** Send every item to a random slot. The same `seed` always deals the same way. */
131
+ shuffle(args) {
132
+ const current = normalizeOrder(this.order, this._itemCount());
133
+ let next = shuffled(current, args.data?.seed ?? 1);
134
+ // A shuffle that deals everything back where it was would look like nothing happened.
135
+ if (next.length > 1 && next.every((item, k) => item === current[k]))
136
+ next = [...next.slice(1), next[0]];
137
+ return this._transitionTo({ order: next }, args);
138
+ }
139
+ /** Two items trade places, by their place in the layers. */
140
+ swap(args) {
141
+ const order = normalizeOrder(this.order, this._itemCount());
142
+ const a = order.indexOf(Math.round(args.data?.first ?? 0));
143
+ const b = order.indexOf(Math.round(args.data?.second ?? 1));
144
+ if (a >= 0 && b >= 0)
145
+ [order[a], order[b]] = [order[b], order[a]];
146
+ return this._transitionTo({ order }, args, 0);
147
+ }
148
+ /** Move the items into a new order — a list of layer indices, first slot first, like `"2, 0, 1"`. */
149
+ reorder(args) {
150
+ const order = normalizeOrder(parseOrder(args.data?.order), this._itemCount());
151
+ return this._transitionTo({ order }, args);
152
+ }
153
+ /**
154
+ * Move every item into another grid's arrangement — a grid into a ring, a ring
155
+ * onto a sphere — and keep following it. An empty `target` morphs back to
156
+ * this grid's own.
157
+ */
158
+ morphInto(args) {
159
+ return this._transitionTo({ arrangeLike: args.data?.target ?? "" }, args);
160
+ }
161
+ // A grid's size is what its items come to. The base's rule — hug only when
162
+ // built with children — would have a grid from a document, whose children
163
+ // arrive after it, fill its parent instead.
164
+ applyDefaultSize(props) {
165
+ if (!props || props.width === undefined)
166
+ this.applyProp("width", "hug", { tween: sizeInputOps.lerp });
167
+ if (!props || props.height === undefined)
168
+ this.applyProp("height", "hug", { tween: sizeInputOps.lerp });
169
+ }
170
+ /** The room each item is measured in — the whole content box, unless an arrangement has cells. */
171
+ itemSpace(_count, space, _sizes) {
172
+ return space;
173
+ }
174
+ measure(constraints, scope) {
175
+ this.lastMeasure = { constraints, measurer: scope };
176
+ const padding = this.effectivePadding();
177
+ const items = this.flowChildren();
178
+ if (items.length === 0) {
179
+ this._measured = null;
180
+ return flowOps.size(this, constraints, padding, NO_CONTENT);
181
+ }
182
+ const space = flowOps.contentBox(this, constraints, padding);
183
+ const sizes = this._measureItems(items, space, scope);
184
+ this._measured = { space, sizes };
185
+ return flowOps.size(this, constraints, padding, extentOf(this._targetSlots(items.length, sizes, space).slots, sizes, this._focal));
186
+ }
187
+ layoutChildren(rect, scope) {
188
+ this._placements.clear();
189
+ const items = this.flowChildren();
190
+ if (items.length === 0) {
191
+ this._slots = [];
192
+ this._sizes = [];
193
+ this._focal = 0;
194
+ return;
195
+ }
196
+ const inner = insetsOps.insetBounds(rect.width, rect.height, this.effectivePadding());
197
+ const measured = this._measured;
198
+ this._measured = null;
199
+ const sizes = measured && measured.sizes.length === items.length && sameSize(measured.space, inner)
200
+ ? measured.sizes
201
+ : this._measureItems(items, inner, scope);
202
+ const slots = this._resolve(sizes, inner);
203
+ this._slots = slots;
204
+ this._sizes = sizes;
205
+ for (let i = 0; i < items.length; i++) {
206
+ const s = slots[i];
207
+ items[i].layout({ x: inner.x + s.x, y: inner.y - s.y, width: sizes[i].width, height: sizes[i].height }, scope);
208
+ if (s.rotation !== 0 || s.scale !== 1 || s.rotationX !== 0 || s.rotationY !== 0 || s.depth !== 0 || s.opacity !== 1) {
209
+ this._placements.set(items[i], {
210
+ rotation: s.rotation,
211
+ scale: s.scale,
212
+ rotationX: s.rotationX,
213
+ rotationY: s.rotationY,
214
+ depth: s.depth,
215
+ opacity: s.opacity,
216
+ });
217
+ }
218
+ }
219
+ }
220
+ _placementOf(child) {
221
+ return this._placements.get(child) ?? null;
222
+ }
223
+ /**
224
+ * A grid whose arrangement has depth is seen through a camera of its own,
225
+ * which paints its items far to near — unless it already sits in a space (an
226
+ * orbit camera, a 3D stage), where its items join that one and its camera.
227
+ */
228
+ _spaceCamera() {
229
+ const focal = this._focal;
230
+ if (focal <= 0 || this._inSpace())
231
+ return null;
232
+ return {
233
+ perspective: focal,
234
+ orbit: 0,
235
+ elevation: 0,
236
+ dolly: 0,
237
+ lookAt: CENTRE,
238
+ zoom: 1,
239
+ heading: 0,
240
+ viewportX: 0,
241
+ viewportY: 0,
242
+ };
243
+ }
244
+ _placements = new Map();
245
+ /** What {@link measure} found, for {@link layoutChildren} to reuse in the same pass. */
246
+ _measured = null;
247
+ /** Each item's slot from the last layout — what a command ranks its stagger by. */
248
+ _slots = [];
249
+ /** Each item's size from the last layout. */
250
+ _sizes = [];
251
+ /** The last layout's camera distance, `0` while flat. */
252
+ _focal = 0;
253
+ _borrowCache = null;
254
+ /** How many items a command built now will act on. */
255
+ _itemCount() {
256
+ return this.flowChildren().length;
257
+ }
258
+ /** Each item's slot as it stands, for a command being built — the last layout's where it still fits. */
259
+ _itemSlots() {
260
+ const n = this._itemCount();
261
+ if (this._slots.length === n)
262
+ return this._slots;
263
+ const sizes = new Array(n).fill({ width: 100, height: 100 });
264
+ return this._targetSlots(n, sizes, contentBoxOf(this)).slots;
265
+ }
266
+ /** The item sizes the last layout found. */
267
+ _itemSizes() {
268
+ return this._sizes.length === this._itemCount() ? this._sizes : [];
269
+ }
270
+ /** Each item's start in a stagger. A random order is seeded by the node's id, so it never changes between builds. */
271
+ _ranks(order) {
272
+ return staggerRanks(order ?? "index", this._itemSlots(), hashSeed(this.id));
273
+ }
274
+ /**
275
+ * Write `changes` to the arrangement and move each item from its slot in the
276
+ * one being left to its slot in the new one, staggered.
277
+ */
278
+ _transitionTo(changes, args, stagger = TRANSITION_STAGGER) {
279
+ const from = this._snapshot();
280
+ const ease = args.easing ?? easeInOut("cubic");
281
+ const ranks = this._ranks(args.data?.staggerOrder);
282
+ const spread = args.data?.stagger ?? stagger;
283
+ return this.command((t) => {
284
+ if (t >= 1)
285
+ return { ...changes, transition: null };
286
+ const mix = ranks.map((rank) => ease(staggerProgress(rank, t, spread)));
287
+ return { ...changes, transition: { from, mix } };
288
+ }, args.duration);
289
+ }
290
+ /** Emphasise the items `isFocus` picks and push the rest back. */
291
+ _focusOn(isFocus, count, args) {
292
+ const from = this.focusState;
293
+ const dim = args.data?.dim ?? 0.7;
294
+ const grow = args.data?.grow ?? 0.15;
295
+ const target = Array.from({ length: count }, (_, i) => (isFocus(i) ? 1 : -1));
296
+ const ease = args.easing ?? easeInOut("cubic");
297
+ return this.command((t) => {
298
+ const e = ease(t);
299
+ return {
300
+ focusState: {
301
+ dim: lerp(from?.dim ?? dim, dim, e),
302
+ grow: lerp(from?.grow ?? grow, grow, e),
303
+ values: target.map((v, i) => lerp(from?.values[i] ?? 0, v, e)),
304
+ },
305
+ };
306
+ }, args.duration);
307
+ }
308
+ _snapshot() {
309
+ const source = this._borrowed();
310
+ return {
311
+ arrangement: source ? source.arrangementFor(contentBoxOf(source)) : this.arrangementFor(contentBoxOf(this)),
312
+ source: source?.id ?? "",
313
+ order: normalizeOrder(this.order, this._itemCount()),
314
+ spread: this.spread,
315
+ };
316
+ }
317
+ _measureItems(items, space, scope) {
318
+ const measured = flowOps.measure({}, items, space, scope).sizes;
319
+ const cell = this.itemSpace(items.length, space, measured);
320
+ if (cell === space)
321
+ return [...measured];
322
+ return [...flowOps.measure({}, items, cell, scope).sizes];
323
+ }
324
+ /** Where each item sits in the arrangement it is heading for, before any transition or effect. */
325
+ _targetSlots(count, sizes, box) {
326
+ const source = this._borrowed();
327
+ const arrangement = source ? source.arrangementFor(contentBoxOf(source)) : this.arrangementFor(box);
328
+ let slots = slotsOf(arrangement, { count, sizes, box: source ? contentBoxOf(source) : box, time: this.time.total });
329
+ if (source)
330
+ slots = this._fromGrid(source, slots);
331
+ const slotOf = slotOfItem(normalizeOrder(this.order, count));
332
+ return { slots: slotOf.map((k) => spreadSlot(slots[k], this.spread)), arrangement };
333
+ }
334
+ /** Each item's final slot this frame: the target, blended from any transition, with its effects on. */
335
+ _resolve(sizes, box) {
336
+ const count = sizes.length;
337
+ const target = this._targetSlots(count, sizes, box);
338
+ const slots = target.slots;
339
+ let focal = focalLengthOf(target.arrangement);
340
+ const transition = this.transition;
341
+ if (transition) {
342
+ const { from } = transition;
343
+ const source = from.source ? this._gridById(from.source) : null;
344
+ const fromBox = source ? contentBoxOf(source) : box;
345
+ let leaving = slotsOf(from.arrangement, { count, sizes, box: fromBox, time: this.time.total });
346
+ if (source && source !== this)
347
+ leaving = this._fromGrid(source, leaving);
348
+ const slotOf = slotOfItem(normalizeOrder(from.order, count));
349
+ for (let i = 0; i < count; i++) {
350
+ slots[i] = blendSlot(spreadSlot(leaving[slotOf[i]], from.spread), slots[i], transition.mix[i] ?? 1);
351
+ }
352
+ // A morph into or out of depth keeps the camera for its whole length.
353
+ focal = focal || focalLengthOf(from.arrangement);
354
+ }
355
+ this._focal = focal;
356
+ const reveal = this.revealState;
357
+ const wave = this.waveState;
358
+ const focus = this.focusState;
359
+ if (reveal || wave || focus) {
360
+ for (let i = 0; i < count; i++)
361
+ applyItemEffects(slots[i], i, sizes[i], reveal, wave, focus);
362
+ }
363
+ return slots;
364
+ }
365
+ /** Whether an ancestor places this grid in a space, as `spaceFrameOf` walks it. */
366
+ _inSpace() {
367
+ for (let n = this.parent; n; n = n.parent) {
368
+ if (n._spaceCamera())
369
+ return true;
370
+ if (!n._rendersChildrenInSpace())
371
+ return false;
372
+ }
373
+ return false;
374
+ }
375
+ /** The grid {@link arrangeLike} names, when it names another grid in this tree. */
376
+ _borrowed() {
377
+ const id = this.arrangeLike;
378
+ if (!id || id === this.id)
379
+ return null;
380
+ return this._gridById(id);
381
+ }
382
+ _gridById(id) {
383
+ if (id === this.id)
384
+ return this;
385
+ const cached = this._borrowCache;
386
+ if (cached && cached.id === id && cached.grid.mounted)
387
+ return cached.grid;
388
+ const found = findNode2D(this, id);
389
+ const grid = found instanceof LayoutGrid ? found : null;
390
+ this._borrowCache = grid ? { id, grid } : null;
391
+ return grid;
392
+ }
393
+ /** `slots`, laid out in `source`'s frame, moved into this grid's. */
394
+ _fromGrid(source, slots) {
395
+ const frame = frameIn(this, source);
396
+ return slots.map((s) => {
397
+ const p = rotateClockwise(s.x * frame.scale, s.y * frame.scale, frame.rotation);
398
+ return {
399
+ ...s,
400
+ x: frame.x + p.x,
401
+ y: frame.y + p.y,
402
+ depth: s.depth * frame.scale,
403
+ rotation: s.rotation + frame.rotation,
404
+ scale: s.scale * frame.scale,
405
+ };
406
+ });
407
+ }
408
+ }
409
+ __decorate([
410
+ property({ default: [], kind: "order", animatable: false })
411
+ ], LayoutGrid.prototype, "order", void 0);
412
+ __decorate([
413
+ property({ default: 1, min: 0, max: 3, step: 0.05 })
414
+ ], LayoutGrid.prototype, "spread", void 0);
415
+ __decorate([
416
+ property({ default: "", kind: "nodeRef", nodeTypes: LAYOUT_GRID_TYPES, animatable: false })
417
+ ], LayoutGrid.prototype, "arrangeLike", void 0);
418
+ __decorate([
419
+ property({ default: undefined, kind: "state", animatable: false })
420
+ ], LayoutGrid.prototype, "revealState", void 0);
421
+ __decorate([
422
+ property({ default: undefined, kind: "state", animatable: false })
423
+ ], LayoutGrid.prototype, "waveState", void 0);
424
+ __decorate([
425
+ property({ default: undefined, kind: "state", animatable: false })
426
+ ], LayoutGrid.prototype, "focusState", void 0);
427
+ __decorate([
428
+ property({ default: undefined, kind: "state", animatable: false })
429
+ ], LayoutGrid.prototype, "transition", void 0);
430
+ __decorate([
431
+ command({ args: [{ key: "style", kind: "enum", options: REVEAL_STYLES, default: "scale" }, ...staggerArgs(0.5)] })
432
+ ], LayoutGrid.prototype, "reveal", null);
433
+ __decorate([
434
+ command({ args: [{ key: "style", kind: "enum", options: REVEAL_STYLES, default: "scale" }, ...staggerArgs(0.5)] })
435
+ ], LayoutGrid.prototype, "conceal", null);
436
+ __decorate([
437
+ command({
438
+ args: [
439
+ { key: "style", kind: "enum", options: WAVE_STYLES, default: "scale" },
440
+ { key: "amount", min: 0, max: 2, step: 0.05, default: 0.3 },
441
+ ...staggerArgs(0.7),
442
+ ],
443
+ })
444
+ ], LayoutGrid.prototype, "wave", null);
445
+ __decorate([
446
+ command({
447
+ args: [
448
+ { key: "item", min: 0, step: 1, default: 0 },
449
+ { key: "dim", min: 0, max: 1, step: 0.05, default: 0.7 },
450
+ { key: "grow", min: 0, max: 1, step: 0.05, default: 0.15 },
451
+ ],
452
+ })
453
+ ], LayoutGrid.prototype, "focus", null);
454
+ __decorate([
455
+ command()
456
+ ], LayoutGrid.prototype, "unfocus", null);
457
+ __decorate([
458
+ command({ args: [{ key: "spread", min: 0, max: 3, step: 0.05, default: 1 }] })
459
+ ], LayoutGrid.prototype, "spreadTo", null);
460
+ __decorate([
461
+ command({ args: [{ key: "seed", min: 0, step: 1, default: 1 }, ...staggerArgs(TRANSITION_STAGGER)] })
462
+ ], LayoutGrid.prototype, "shuffle", null);
463
+ __decorate([
464
+ command({
465
+ args: [
466
+ { key: "first", min: 0, step: 1, default: 0 },
467
+ { key: "second", min: 0, step: 1, default: 1 },
468
+ ...staggerArgs(0),
469
+ ],
470
+ })
471
+ ], LayoutGrid.prototype, "swap", null);
472
+ __decorate([
473
+ command({ args: [{ key: "order", kind: "text", default: "" }, ...staggerArgs(TRANSITION_STAGGER)] })
474
+ ], LayoutGrid.prototype, "reorder", null);
475
+ __decorate([
476
+ command({ args: [{ key: "target", kind: "nodeRef", nodeTypes: LAYOUT_GRID_TYPES }, ...staggerArgs(TRANSITION_STAGGER)] })
477
+ ], LayoutGrid.prototype, "morphInto", null);
478
+ /** A node's content box: its laid-out size inside its padding. */
479
+ export function contentBoxOf(grid) {
480
+ const b = grid.layoutBounds;
481
+ const inner = insetsOps.insetBounds(b.width, b.height, grid.effectivePadding());
482
+ return { width: inner.width, height: inner.height };
483
+ }
484
+ /** The box, centred on the grid, that holds every item where its slot puts it. */
485
+ function extentOf(slots, sizes, focal) {
486
+ let halfWidth = 0;
487
+ let halfHeight = 0;
488
+ for (let i = 0; i < slots.length; i++) {
489
+ const s = slots[i];
490
+ const size = sizes[i];
491
+ const rad = (s.rotation * Math.PI) / 180;
492
+ const cos = Math.abs(Math.cos(rad));
493
+ const sin = Math.abs(Math.sin(rad));
494
+ // What the camera does to a slot at depth, so a sphere hugs its front.
495
+ const lens = focal > 0 && focal - s.depth > 1 ? focal / (focal - s.depth) : 1;
496
+ const w = ((size.width * cos + size.height * sin) / 2) * s.scale * lens;
497
+ const h = ((size.width * sin + size.height * cos) / 2) * s.scale * lens;
498
+ halfWidth = Math.max(halfWidth, Math.abs(s.x) * lens + w);
499
+ halfHeight = Math.max(halfHeight, Math.abs(s.y) * lens + h);
500
+ }
501
+ return { width: halfWidth * 2, height: halfHeight * 2 };
502
+ }
503
+ function rotateClockwise(x, y, degrees) {
504
+ if (degrees === 0)
505
+ return { x, y };
506
+ const rad = (degrees * Math.PI) / 180;
507
+ const cos = Math.cos(rad);
508
+ const sin = Math.sin(rad);
509
+ return { x: x * cos + y * sin, y: -x * sin + y * cos };
510
+ }
511
+ function sameSize(a, b) {
512
+ return Math.abs(a.width - b.width) < 1e-6 && Math.abs(a.height - b.height) < 1e-6;
513
+ }
514
+ function lerp(a, b, t) {
515
+ return a + (b - a) * t;
516
+ }
517
+ /** The 2D node `id` names in the tree `from` is in, or `null`. */
518
+ export function findNode2D(from, id) {
519
+ let root = from;
520
+ while (root.parent)
521
+ root = root.parent;
522
+ return findIn(root, id);
523
+ }
524
+ function findIn(at, id) {
525
+ if (at.id === id)
526
+ return at;
527
+ for (const child of at.children) {
528
+ const found = findIn(child, id);
529
+ if (found)
530
+ return found;
531
+ }
532
+ return null;
533
+ }
534
+ /** Where `node`'s frame sits in `grid`'s: offset, turn and scale, y-up. */
535
+ export function frameIn(grid, node) {
536
+ const there = node.global;
537
+ const here = grid.global;
538
+ const inverse = here.scale === 0 ? 0 : 1 / here.scale;
539
+ const offset = rotateClockwise((there.x - here.x) * inverse, (there.y - here.y) * inverse, -here.rotation);
540
+ return { x: offset.x, y: offset.y, rotation: there.rotation - here.rotation, scale: there.scale * inverse };
541
+ }
542
+ //# sourceMappingURL=layout-grid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout-grid.js","sourceRoot":"","sources":["../../src/kit/layout-grid.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n command,\n easeIn,\n easeInOut,\n easeOut,\n flowOps,\n insetsOps,\n Node2D,\n property,\n sizeInputOps,\n type BoxBounds,\n type ChildPlacement,\n type Command,\n type CommandArgs,\n type MeasureContext2D,\n type EasingFunction,\n type Node2DProps,\n type Size2D,\n type SizeConstraints,\n type SpaceCamera,\n} from \"@motionscript/core\"\n\nimport {\n applyItemEffects,\n REVEAL_STYLES,\n WAVE_STYLES,\n type FocusState,\n type RevealState,\n type RevealStyle,\n type WaveState,\n type WaveStyle,\n} from \"./item-effects\"\nimport { normalizeOrder, parseOrder, slotOfItem } from \"./order\"\nimport { hashSeed, shuffled } from \"./random\"\nimport { blendSlot, focalLengthOf, slotsOf, spreadSlot, type Arrangement, type Slot } from \"./slots\"\nimport { STAGGER_ORDERS, staggerProgress, staggerRanks, type StaggerOrder } from \"./stagger\"\n\n/** An arrangement a grid is leaving, kept as data so its slots can be worked out afresh every frame. */\nexport interface GridSnapshot {\n arrangement: Arrangement\n /** The grid the arrangement was borrowed from, or `\"\"` for the grid's own. */\n source: string\n order: readonly number[]\n spread: number\n}\n\n/** A change of arrangement under way: where the items are coming from, and how far each has come. */\nexport interface GridTransition {\n from: GridSnapshot\n /** Each item's eased, staggered progress, `0..1`. */\n mix: readonly number[]\n}\n\nexport interface LayoutGridProps extends Node2DProps {\n /** Items in slot order: slot `k` holds child `order[k]`. Empty is the children's own order. */\n order: number[]\n /** `0` gathers every item at the centre, `1` is the arrangement, past `1` pushes them apart. */\n spread: number\n /** Another grid whose arrangement this one takes on — what {@link LayoutGrid.morphInto} animates. */\n arrangeLike: string\n // What the per-item commands write. State rather than settings: a command\n // owns each while it runs, and a document has no reason to name them.\n revealState: RevealState | null\n waveState: WaveState | null\n focusState: FocusState | null\n transition: GridTransition | null\n}\n\n/** What a command that moves the items to new slots is built from. */\nexport interface TransitionArgs {\n data?: StaggerArgs\n duration: number\n easing?: EasingFunction\n}\n\n/** The stagger options every per-item command takes. */\nexport interface StaggerArgs {\n staggerOrder?: StaggerOrder\n /** `0..0.95`: how much of the command's length the items' offsets take up. */\n stagger?: number\n}\n\n/** `@command` descriptors for {@link StaggerArgs}, `stagger` defaulting to `fallback`. */\nexport function staggerArgs(fallback: number) {\n return [\n { key: \"staggerOrder\", kind: \"enum\", options: STAGGER_ORDERS, default: \"index\" },\n { key: \"stagger\", min: 0, max: 0.95, step: 0.05, default: fallback },\n ] as const\n}\n\n/**\n * Every grid's document key — what a reference to \"another grid\" may name. A\n * `nodeRef` descriptor carries it as `nodeTypes`, for a host's picker to offer\n * only those.\n */\nexport const LAYOUT_GRID_TYPES = [\"rectangularGrid\", \"radialGrid\", \"pathGrid\", \"sphereGrid\"] as const\n\n/** The stagger a move to new slots takes when its command states none. */\nexport const TRANSITION_STAGGER = 0.3\n\nconst NO_CONTENT: Size2D = { width: 0, height: 0 }\nconst CENTRE = { x: 0, y: 0 }\n\n/**\n * The base of every grid: a container that places each of its children in a\n * slot of an arrangement — a rectangular grid, a ring, a path, a sphere.\n *\n * ## Children only\n *\n * The items are the children, in layer order. A child's slot is a parent\n * transform on it, so its own `x`/`y`/`rotation`/`scale` — and any command on\n * them — still work, relative to the slot. A group is one item; a grid of\n * grids is a grid of items that happen to be grids.\n *\n * ## One pass\n *\n * Every frame: measure the children, ask the arrangement for its slots (a pure\n * function of the props, the sizes and the clock), blend them from where a\n * transition is leaving, and layer on the per-item effects — reveal, wave,\n * focus. What is left is each child's box and {@link ChildPlacement}, which the\n * renderer, picking and `global` all read, so a selection outline lands on\n * the pixels even on a sphere.\n *\n * ## Commands\n *\n * Every command is a pure function of time, like the rest of the library. The\n * per-item ones stagger *inside* their duration — a one-second reveal takes one\n * second for four children or four hundred — and write their per-item state\n * into props ({@link revealState} and its siblings), which is what keeps them\n * seekable. The ones that change the arrangement itself (a reorder, a morph, a\n * column count) keep the arrangement they are leaving as data and blend each\n * item from its old slot to its new one.\n */\nexport abstract class LayoutGrid<P extends LayoutGridProps = LayoutGridProps> extends Node2D<P> {\n @property({ default: [], kind: \"order\", animatable: false }) declare order: number[]\n @property({ default: 1, min: 0, max: 3, step: 0.05 }) declare spread: number\n @property({ default: \"\", kind: \"nodeRef\", nodeTypes: LAYOUT_GRID_TYPES, animatable: false }) declare arrangeLike: string\n // Unset until a command writes one, so a fresh node's row does not state them.\n @property({ default: undefined, kind: \"state\", animatable: false }) declare revealState: RevealState | null | undefined\n @property({ default: undefined, kind: \"state\", animatable: false }) declare waveState: WaveState | null | undefined\n @property({ default: undefined, kind: \"state\", animatable: false }) declare focusState: FocusState | null | undefined\n @property({ default: undefined, kind: \"state\", animatable: false }) declare transition: GridTransition | null | undefined\n\n /**\n * Bring the items in, one after another. Every item starts hidden, so place\n * it where the grid enters — or after a {@link conceal}.\n */\n @command({ args: [{ key: \"style\", kind: \"enum\", options: REVEAL_STYLES, default: \"scale\" }, ...staggerArgs(0.5)] })\n reveal(args: CommandArgs<{ style?: RevealStyle } & StaggerArgs> & { duration: number }): Command<LayoutGridProps> {\n const style = args.data?.style ?? \"scale\"\n const ease = args.easing ?? (style === \"scale\" || style === \"flip\" ? easeOut(\"back\") : easeOut(\"cubic\"))\n const ranks = this._ranks(args.data?.staggerOrder)\n const stagger = args.data?.stagger ?? 0.5\n return this.command<LayoutGridProps>((t) => {\n if (t >= 1) return { revealState: null }\n return { revealState: { style, values: ranks.map((rank) => ease(staggerProgress(rank, t, stagger))) } }\n }, args.duration)\n }\n\n /** Take the items out, one after another — {@link reveal} in reverse. They stay hidden after. */\n @command({ args: [{ key: \"style\", kind: \"enum\", options: REVEAL_STYLES, default: \"scale\" }, ...staggerArgs(0.5)] })\n conceal(args: CommandArgs<{ style?: RevealStyle } & StaggerArgs> & { duration: number }): Command<LayoutGridProps> {\n const style = args.data?.style ?? \"scale\"\n const ease = args.easing ?? (style === \"scale\" || style === \"flip\" ? easeIn(\"back\") : easeInOut(\"cubic\"))\n const ranks = this._ranks(args.data?.staggerOrder)\n const stagger = args.data?.stagger ?? 0.5\n const from = this.revealState?.values\n return this.command<LayoutGridProps>((t) => ({\n revealState: {\n style,\n values: ranks.map((rank, i) => (from?.[i] ?? 1) * (1 - ease(staggerProgress(rank, t, stagger)))),\n },\n }), args.duration)\n }\n\n /** Send a ripple through the items that swells each in turn and settles back. */\n @command({\n args: [\n { key: \"style\", kind: \"enum\", options: WAVE_STYLES, default: \"scale\" },\n { key: \"amount\", min: 0, max: 2, step: 0.05, default: 0.3 },\n ...staggerArgs(0.7),\n ],\n })\n wave(args: CommandArgs<{ style?: WaveStyle; amount?: number } & StaggerArgs> & { duration: number }): Command<LayoutGridProps> {\n const style = args.data?.style ?? \"scale\"\n const amount = args.data?.amount ?? 0.3\n const ease = args.easing ?? easeInOut(\"sine\")\n const ranks = this._ranks(args.data?.staggerOrder)\n const stagger = args.data?.stagger ?? 0.7\n return this.command<LayoutGridProps>((t) => {\n if (t >= 1) return { waveState: null }\n return {\n waveState: {\n style,\n amount,\n values: ranks.map((rank) => Math.sin(Math.PI * ease(staggerProgress(rank, t, stagger)))),\n },\n }\n }, args.duration)\n }\n\n /** Bring one item (by its place in the layers, from 0) forward and push the rest back. */\n @command({\n args: [\n { key: \"item\", min: 0, step: 1, default: 0 },\n { key: \"dim\", min: 0, max: 1, step: 0.05, default: 0.7 },\n { key: \"grow\", min: 0, max: 1, step: 0.05, default: 0.15 },\n ],\n })\n focus(args: CommandArgs<{ item?: number; dim?: number; grow?: number }> & { duration: number }): Command<LayoutGridProps> {\n const n = this._itemCount()\n const item = Math.round(args.data?.item ?? 0)\n return this._focusOn((i) => i === item, n, args)\n }\n\n /** Bring every item back to even. */\n @command()\n unfocus(args: CommandArgs<Record<string, never>> & { duration: number }): Command<LayoutGridProps> {\n const from = this.focusState\n const ease = args.easing ?? easeInOut(\"cubic\")\n return this.command<LayoutGridProps>((t) => {\n if (t >= 1 || !from) return { focusState: null }\n const k = 1 - ease(t)\n return { focusState: { ...from, values: from.values.map((v) => v * k) } }\n }, args.duration)\n }\n\n /** Gather the items toward the centre (`0`), back to the arrangement (`1`), or push them apart. */\n @command({ args: [{ key: \"spread\", min: 0, max: 3, step: 0.05, default: 1 }] })\n spreadTo(args: CommandArgs<{ spread: number }> & { duration: number }): Command<P> {\n return this.to({ data: { spread: args.data?.spread ?? 1 } as Partial<P>, duration: args.duration, easing: args.easing })\n }\n\n /** Send every item to a random slot. The same `seed` always deals the same way. */\n @command({ args: [{ key: \"seed\", min: 0, step: 1, default: 1 }, ...staggerArgs(TRANSITION_STAGGER)] })\n shuffle(args: CommandArgs<{ seed?: number } & StaggerArgs> & { duration: number }): Command<P> {\n const current = normalizeOrder(this.order, this._itemCount())\n let next = shuffled(current, args.data?.seed ?? 1)\n // A shuffle that deals everything back where it was would look like nothing happened.\n if (next.length > 1 && next.every((item, k) => item === current[k])) next = [...next.slice(1), next[0]]\n return this._transitionTo({ order: next } as Partial<P>, args)\n }\n\n /** Two items trade places, by their place in the layers. */\n @command({\n args: [\n { key: \"first\", min: 0, step: 1, default: 0 },\n { key: \"second\", min: 0, step: 1, default: 1 },\n ...staggerArgs(0),\n ],\n })\n swap(args: CommandArgs<{ first?: number; second?: number } & StaggerArgs> & { duration: number }): Command<P> {\n const order = normalizeOrder(this.order, this._itemCount())\n const a = order.indexOf(Math.round(args.data?.first ?? 0))\n const b = order.indexOf(Math.round(args.data?.second ?? 1))\n if (a >= 0 && b >= 0) [order[a], order[b]] = [order[b], order[a]]\n return this._transitionTo({ order } as Partial<P>, args, 0)\n }\n\n /** Move the items into a new order — a list of layer indices, first slot first, like `\"2, 0, 1\"`. */\n @command({ args: [{ key: \"order\", kind: \"text\", default: \"\" }, ...staggerArgs(TRANSITION_STAGGER)] })\n reorder(args: CommandArgs<{ order?: string | number[] } & StaggerArgs> & { duration: number }): Command<P> {\n const order = normalizeOrder(parseOrder(args.data?.order), this._itemCount())\n return this._transitionTo({ order } as Partial<P>, args)\n }\n\n /**\n * Move every item into another grid's arrangement — a grid into a ring, a ring\n * onto a sphere — and keep following it. An empty `target` morphs back to\n * this grid's own.\n */\n @command({ args: [{ key: \"target\", kind: \"nodeRef\", nodeTypes: LAYOUT_GRID_TYPES }, ...staggerArgs(TRANSITION_STAGGER)] })\n morphInto(args: CommandArgs<{ target?: string } & StaggerArgs> & { duration: number }): Command<P> {\n return this._transitionTo({ arrangeLike: args.data?.target ?? \"\" } as Partial<P>, args)\n }\n\n /** This grid's own arrangement, for a content box of `box`. */\n protected abstract arrangementFor(box: Size2D): Arrangement\n\n // A grid's size is what its items come to. The base's rule — hug only when\n // built with children — would have a grid from a document, whose children\n // arrive after it, fill its parent instead.\n protected override applyDefaultSize(props?: { readonly width?: unknown; readonly height?: unknown }): void {\n if (!props || props.width === undefined) this.applyProp(\"width\", \"hug\", { tween: sizeInputOps.lerp })\n if (!props || props.height === undefined) this.applyProp(\"height\", \"hug\", { tween: sizeInputOps.lerp })\n }\n\n /** The room each item is measured in — the whole content box, unless an arrangement has cells. */\n protected itemSpace(_count: number, space: Size2D, _sizes?: readonly Size2D[]): Size2D {\n return space\n }\n\n override measure(constraints: SizeConstraints, scope: MeasureContext2D): Partial<Size2D> {\n this.lastMeasure = { constraints, measurer: scope }\n const padding = this.effectivePadding()\n const items = this.flowChildren()\n if (items.length === 0) {\n this._measured = null\n return flowOps.size(this, constraints, padding, NO_CONTENT)\n }\n const space = flowOps.contentBox(this, constraints, padding)\n const sizes = this._measureItems(items, space, scope)\n this._measured = { space, sizes }\n return flowOps.size(this, constraints, padding, extentOf(this._targetSlots(items.length, sizes, space).slots, sizes, this._focal))\n }\n\n protected override layoutChildren(rect: BoxBounds, scope: MeasureContext2D): void {\n this._placements.clear()\n const items = this.flowChildren()\n if (items.length === 0) {\n this._slots = []\n this._sizes = []\n this._focal = 0\n return\n }\n const inner = insetsOps.insetBounds(rect.width, rect.height, this.effectivePadding())\n const measured = this._measured\n this._measured = null\n const sizes = measured && measured.sizes.length === items.length && sameSize(measured.space, inner)\n ? measured.sizes\n : this._measureItems(items, inner, scope)\n const slots = this._resolve(sizes, inner)\n this._slots = slots\n this._sizes = sizes\n for (let i = 0; i < items.length; i++) {\n const s = slots[i]\n items[i].layout({ x: inner.x + s.x, y: inner.y - s.y, width: sizes[i].width, height: sizes[i].height }, scope)\n if (s.rotation !== 0 || s.scale !== 1 || s.rotationX !== 0 || s.rotationY !== 0 || s.depth !== 0 || s.opacity !== 1) {\n this._placements.set(items[i], {\n rotation: s.rotation,\n scale: s.scale,\n rotationX: s.rotationX,\n rotationY: s.rotationY,\n depth: s.depth,\n opacity: s.opacity,\n })\n }\n }\n }\n\n override _placementOf(child: Node2D): ChildPlacement | null {\n return this._placements.get(child) ?? null\n }\n\n /**\n * A grid whose arrangement has depth is seen through a camera of its own,\n * which paints its items far to near — unless it already sits in a space (an\n * orbit camera, a 3D stage), where its items join that one and its camera.\n */\n override _spaceCamera(): SpaceCamera | null {\n const focal = this._focal\n if (focal <= 0 || this._inSpace()) return null\n return {\n perspective: focal,\n orbit: 0,\n elevation: 0,\n dolly: 0,\n lookAt: CENTRE,\n zoom: 1,\n heading: 0,\n viewportX: 0,\n viewportY: 0,\n }\n }\n\n private readonly _placements = new Map<Node2D, ChildPlacement>()\n /** What {@link measure} found, for {@link layoutChildren} to reuse in the same pass. */\n private _measured: { space: Size2D; sizes: Size2D[] } | null = null\n /** Each item's slot from the last layout — what a command ranks its stagger by. */\n private _slots: Slot[] = []\n /** Each item's size from the last layout. */\n private _sizes: readonly Size2D[] = []\n /** The last layout's camera distance, `0` while flat. */\n private _focal = 0\n private _borrowCache: { id: string; grid: LayoutGrid } | null = null\n\n /** How many items a command built now will act on. */\n protected _itemCount(): number {\n return this.flowChildren().length\n }\n\n /** Each item's slot as it stands, for a command being built — the last layout's where it still fits. */\n protected _itemSlots(): Slot[] {\n const n = this._itemCount()\n if (this._slots.length === n) return this._slots\n const sizes = new Array<Size2D>(n).fill({ width: 100, height: 100 })\n return this._targetSlots(n, sizes, contentBoxOf(this)).slots\n }\n\n /** The item sizes the last layout found. */\n protected _itemSizes(): readonly Size2D[] {\n return this._sizes.length === this._itemCount() ? this._sizes : []\n }\n\n /** Each item's start in a stagger. A random order is seeded by the node's id, so it never changes between builds. */\n protected _ranks(order: StaggerOrder | undefined): number[] {\n return staggerRanks(order ?? \"index\", this._itemSlots(), hashSeed(this.id))\n }\n\n /**\n * Write `changes` to the arrangement and move each item from its slot in the\n * one being left to its slot in the new one, staggered.\n */\n protected _transitionTo(changes: Partial<P>, args: TransitionArgs, stagger = TRANSITION_STAGGER): Command<P> {\n const from = this._snapshot()\n const ease = args.easing ?? easeInOut(\"cubic\")\n const ranks = this._ranks(args.data?.staggerOrder)\n const spread = args.data?.stagger ?? stagger\n return this.command<P>((t) => {\n if (t >= 1) return { ...changes, transition: null } as Partial<P>\n const mix = ranks.map((rank) => ease(staggerProgress(rank, t, spread)))\n return { ...changes, transition: { from, mix } } as Partial<P>\n }, args.duration)\n }\n\n /** Emphasise the items `isFocus` picks and push the rest back. */\n protected _focusOn(\n isFocus: (item: number) => boolean,\n count: number,\n args: CommandArgs<{ dim?: number; grow?: number }> & { duration: number },\n ): Command<LayoutGridProps> {\n const from = this.focusState\n const dim = args.data?.dim ?? 0.7\n const grow = args.data?.grow ?? 0.15\n const target = Array.from({ length: count }, (_, i) => (isFocus(i) ? 1 : -1))\n const ease = args.easing ?? easeInOut(\"cubic\")\n return this.command<LayoutGridProps>((t) => {\n const e = ease(t)\n return {\n focusState: {\n dim: lerp(from?.dim ?? dim, dim, e),\n grow: lerp(from?.grow ?? grow, grow, e),\n values: target.map((v, i) => lerp(from?.values[i] ?? 0, v, e)),\n },\n }\n }, args.duration)\n }\n\n private _snapshot(): GridSnapshot {\n const source = this._borrowed()\n return {\n arrangement: source ? source.arrangementFor(contentBoxOf(source)) : this.arrangementFor(contentBoxOf(this)),\n source: source?.id ?? \"\",\n order: normalizeOrder(this.order, this._itemCount()),\n spread: this.spread,\n }\n }\n\n private _measureItems(items: readonly Node2D[], space: Size2D, scope: MeasureContext2D): Size2D[] {\n const measured = flowOps.measure({}, items, space, scope).sizes\n const cell = this.itemSpace(items.length, space, measured)\n if (cell === space) return [...measured]\n return [...flowOps.measure({}, items, cell, scope).sizes]\n }\n\n /** Where each item sits in the arrangement it is heading for, before any transition or effect. */\n private _targetSlots(count: number, sizes: readonly Size2D[], box: Size2D): { slots: Slot[]; arrangement: Arrangement } {\n const source = this._borrowed()\n const arrangement = source ? source.arrangementFor(contentBoxOf(source)) : this.arrangementFor(box)\n let slots = slotsOf(arrangement, { count, sizes, box: source ? contentBoxOf(source) : box, time: this.time.total })\n if (source) slots = this._fromGrid(source, slots)\n const slotOf = slotOfItem(normalizeOrder(this.order, count))\n return { slots: slotOf.map((k) => spreadSlot(slots[k], this.spread)), arrangement }\n }\n\n /** Each item's final slot this frame: the target, blended from any transition, with its effects on. */\n private _resolve(sizes: readonly Size2D[], box: Size2D): Slot[] {\n const count = sizes.length\n const target = this._targetSlots(count, sizes, box)\n const slots = target.slots\n let focal = focalLengthOf(target.arrangement)\n const transition = this.transition\n if (transition) {\n const { from } = transition\n const source = from.source ? this._gridById(from.source) : null\n const fromBox = source ? contentBoxOf(source) : box\n let leaving = slotsOf(from.arrangement, { count, sizes, box: fromBox, time: this.time.total })\n if (source && source !== this) leaving = this._fromGrid(source, leaving)\n const slotOf = slotOfItem(normalizeOrder(from.order, count))\n for (let i = 0; i < count; i++) {\n slots[i] = blendSlot(spreadSlot(leaving[slotOf[i]], from.spread), slots[i], transition.mix[i] ?? 1)\n }\n // A morph into or out of depth keeps the camera for its whole length.\n focal = focal || focalLengthOf(from.arrangement)\n }\n this._focal = focal\n const reveal = this.revealState\n const wave = this.waveState\n const focus = this.focusState\n if (reveal || wave || focus) {\n for (let i = 0; i < count; i++) applyItemEffects(slots[i], i, sizes[i], reveal, wave, focus)\n }\n return slots\n }\n\n /** Whether an ancestor places this grid in a space, as `spaceFrameOf` walks it. */\n private _inSpace(): boolean {\n for (let n = this.parent; n; n = n.parent) {\n if (n._spaceCamera()) return true\n if (!n._rendersChildrenInSpace()) return false\n }\n return false\n }\n\n /** The grid {@link arrangeLike} names, when it names another grid in this tree. */\n private _borrowed(): LayoutGrid | null {\n const id = this.arrangeLike\n if (!id || id === this.id) return null\n return this._gridById(id)\n }\n\n private _gridById(id: string): LayoutGrid | null {\n if (id === this.id) return this\n const cached = this._borrowCache\n if (cached && cached.id === id && cached.grid.mounted) return cached.grid\n const found = findNode2D(this, id)\n const grid = found instanceof LayoutGrid ? found : null\n this._borrowCache = grid ? { id, grid } : null\n return grid\n }\n\n /** `slots`, laid out in `source`'s frame, moved into this grid's. */\n private _fromGrid(source: LayoutGrid, slots: Slot[]): Slot[] {\n const frame = frameIn(this, source)\n return slots.map((s) => {\n const p = rotateClockwise(s.x * frame.scale, s.y * frame.scale, frame.rotation)\n return {\n ...s,\n x: frame.x + p.x,\n y: frame.y + p.y,\n depth: s.depth * frame.scale,\n rotation: s.rotation + frame.rotation,\n scale: s.scale * frame.scale,\n }\n })\n }\n}\n\n/** A node's content box: its laid-out size inside its padding. */\nexport function contentBoxOf(grid: Node2D): Size2D {\n const b = grid.layoutBounds\n const inner = insetsOps.insetBounds(b.width, b.height, grid.effectivePadding())\n return { width: inner.width, height: inner.height }\n}\n\n/** The box, centred on the grid, that holds every item where its slot puts it. */\nfunction extentOf(slots: readonly Slot[], sizes: readonly Size2D[], focal: number): Size2D {\n let halfWidth = 0\n let halfHeight = 0\n for (let i = 0; i < slots.length; i++) {\n const s = slots[i]\n const size = sizes[i]\n const rad = (s.rotation * Math.PI) / 180\n const cos = Math.abs(Math.cos(rad))\n const sin = Math.abs(Math.sin(rad))\n // What the camera does to a slot at depth, so a sphere hugs its front.\n const lens = focal > 0 && focal - s.depth > 1 ? focal / (focal - s.depth) : 1\n const w = ((size.width * cos + size.height * sin) / 2) * s.scale * lens\n const h = ((size.width * sin + size.height * cos) / 2) * s.scale * lens\n halfWidth = Math.max(halfWidth, Math.abs(s.x) * lens + w)\n halfHeight = Math.max(halfHeight, Math.abs(s.y) * lens + h)\n }\n return { width: halfWidth * 2, height: halfHeight * 2 }\n}\n\nfunction rotateClockwise(x: number, y: number, degrees: number): { x: number; y: number } {\n if (degrees === 0) return { x, y }\n const rad = (degrees * Math.PI) / 180\n const cos = Math.cos(rad)\n const sin = Math.sin(rad)\n return { x: x * cos + y * sin, y: -x * sin + y * cos }\n}\n\nfunction sameSize(a: Size2D, b: Size2D): boolean {\n return Math.abs(a.width - b.width) < 1e-6 && Math.abs(a.height - b.height) < 1e-6\n}\n\nfunction lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t\n}\n\n/** The 2D node `id` names in the tree `from` is in, or `null`. */\nexport function findNode2D(from: Node2D, id: string): Node2D | null {\n let root: Node2D = from\n while (root.parent) root = root.parent\n return findIn(root, id)\n}\n\nfunction findIn(at: Node2D, id: string): Node2D | null {\n if (at.id === id) return at\n for (const child of at.children) {\n const found = findIn(child, id)\n if (found) return found\n }\n return null\n}\n\n/** Where `node`'s frame sits in `grid`'s: offset, turn and scale, y-up. */\nexport function frameIn(grid: Node2D, node: Node2D): { x: number; y: number; rotation: number; scale: number } {\n const there = node.global\n const here = grid.global\n const inverse = here.scale === 0 ? 0 : 1 / here.scale\n const offset = rotateClockwise((there.x - here.x) * inverse, (there.y - here.y) * inverse, -here.rotation)\n return { x: offset.x, y: offset.y, rotation: there.rotation - here.rotation, scale: there.scale * inverse }\n}\n"]}