paperlab 0.2.0 → 0.3.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.
@@ -0,0 +1,1156 @@
1
+ import * as react from 'react';
2
+ import { F as FieldPaperSlot, a as PaperConfigInput } from './slots-D0Nc_5dq.cjs';
3
+ import { z } from 'zod';
4
+
5
+ /**
6
+ * The room the walk is in.
7
+ *
8
+ * Stage mode was a void with a horizon: a graded dome, a flat plane, and a
9
+ * bright rectangle at the end, none of it a knowable size. That is why the
10
+ * walking figure was carrying the whole scale burden by itself — and why
11
+ * simply removing the figure would have left an abstraction rather than a
12
+ * hall. Architecture is the better answer: objects whose size the viewer
13
+ * already knows, made of flat surfaces under good light, which is the one
14
+ * thing a renderer never gets wrong.
15
+ */
16
+ /**
17
+ * What holds the paper up.
18
+ *
19
+ * Every paper installation shows its hardware — monofilament from a ceiling
20
+ * grid, steel wire, bulldog clips, a rod — and in the scattered-sheet pieces
21
+ * the threads are half the composition. Stage mode's banners hung from
22
+ * nothing at all, which is a bigger realism gap than any shader in the
23
+ * backlog and closes for a few thin lines of geometry.
24
+ */
25
+ declare const stageSuspensionSchema: z.ZodObject<{
26
+ /**
27
+ * What carries the load.
28
+ *
29
+ * `thread` is monofilament to the ceiling — one straight line per sheet.
30
+ * `rod` is a dowel across each sheet's top edge, hung from the ceiling at
31
+ * both ends, which is a different image entirely: a rank on threads reads
32
+ * as sheets floating in a row, and a rank on rods reads as sheets that
33
+ * were HUNG, by someone, on something. `none` is for a stage where the
34
+ * paper is meant to be impossible.
35
+ */
36
+ type: z.ZodDefault<z.ZodEnum<["none", "thread", "rod"]>>;
37
+ color: z.ZodDefault<z.ZodString>;
38
+ /**
39
+ * What grips the sheet.
40
+ *
41
+ * A clip is wide and shallow — the bulldog clip of a gallery. A peg is
42
+ * narrow and deep, and grips DOWN the face of the sheet rather than
43
+ * across its edge: the domestic one, a line of paper on a washing line.
44
+ * They are told apart by silhouette at any distance, which is the only
45
+ * thing that survives being one instanced box at the top of an
46
+ * eight-metre banner.
47
+ *
48
+ * This replaced a `clips: boolean`. Two of the four pieces of hardware the
49
+ * plan named — pegs, and a rod — had no way to be asked for, and a boolean
50
+ * cannot grow a third answer.
51
+ */
52
+ hardware: z.ZodDefault<z.ZodEnum<["none", "clip", "peg"]>>;
53
+ }, "strip", z.ZodTypeAny, {
54
+ type: "none" | "thread" | "rod";
55
+ color: string;
56
+ hardware: "none" | "clip" | "peg";
57
+ }, {
58
+ type?: "none" | "thread" | "rod" | undefined;
59
+ color?: string | undefined;
60
+ hardware?: "none" | "clip" | "peg" | undefined;
61
+ }>;
62
+ declare const stageRoomSchema: z.ZodObject<{
63
+ enabled: z.ZodDefault<z.ZodBoolean>;
64
+ /**
65
+ * Ceiling height, as a multiple of the paper's own height.
66
+ *
67
+ * Relative rather than absolute because the banners ARE the architecture
68
+ * here: a hall whose ceiling sits just above its hangings reads as built
69
+ * for them, and one at a fixed world height reads as whatever the paper
70
+ * happened to be scaled to that day.
71
+ */
72
+ height: z.ZodDefault<z.ZodNumber>;
73
+ color: z.ZodDefault<z.ZodString>;
74
+ /** Columns flanking the walk — see `stageColumnsSchema`. */
75
+ columns: z.ZodDefault<z.ZodObject<{
76
+ enabled: z.ZodDefault<z.ZodBoolean>;
77
+ /** Centres this far apart along the walk. Roughly a bay. */
78
+ spacing: z.ZodDefault<z.ZodNumber>;
79
+ /** Shaft width. The number doing the work — a column is a known size. */
80
+ width: z.ZodDefault<z.ZodNumber>;
81
+ /**
82
+ * How far off the walk's centreline each rank stands.
83
+ *
84
+ * Outside the banners, always. Columns are the room; the paper is the
85
+ * subject, and a column standing between the viewer and a banner has
86
+ * swapped the two over. Default clears a `colonnade`'s widest sensible
87
+ * aisle with room to spare.
88
+ */
89
+ offset: z.ZodDefault<z.ZodNumber>;
90
+ /**
91
+ * Stone, and darker than paper on purpose.
92
+ *
93
+ * The brightest thing in any of these frames has to be the light, and the
94
+ * second brightest has to be the paper. A column the same value as a
95
+ * banner does not read as architecture behind the subject; it reads as
96
+ * more banners, and the eye stops being able to tell what the room is made
97
+ * of from what is hanging in it.
98
+ */
99
+ color: z.ZodDefault<z.ZodString>;
100
+ }, "strip", z.ZodTypeAny, {
101
+ width: number;
102
+ offset: number;
103
+ color: string;
104
+ spacing: number;
105
+ enabled: boolean;
106
+ }, {
107
+ width?: number | undefined;
108
+ offset?: number | undefined;
109
+ color?: string | undefined;
110
+ spacing?: number | undefined;
111
+ enabled?: boolean | undefined;
112
+ }>>;
113
+ /** A wall at the end of the walk with the source in it. */
114
+ doorway: z.ZodDefault<z.ZodObject<{
115
+ enabled: z.ZodDefault<z.ZodBoolean>;
116
+ /** Opening size, as a multiple of the source's own. 1 frames it exactly. */
117
+ opening: z.ZodDefault<z.ZodNumber>;
118
+ color: z.ZodDefault<z.ZodString>;
119
+ }, "strip", z.ZodTypeAny, {
120
+ color: string;
121
+ enabled: boolean;
122
+ opening: number;
123
+ }, {
124
+ color?: string | undefined;
125
+ enabled?: boolean | undefined;
126
+ opening?: number | undefined;
127
+ }>>;
128
+ }, "strip", z.ZodTypeAny, {
129
+ height: number;
130
+ color: string;
131
+ enabled: boolean;
132
+ columns: {
133
+ width: number;
134
+ offset: number;
135
+ color: string;
136
+ spacing: number;
137
+ enabled: boolean;
138
+ };
139
+ doorway: {
140
+ color: string;
141
+ enabled: boolean;
142
+ opening: number;
143
+ };
144
+ }, {
145
+ height?: number | undefined;
146
+ color?: string | undefined;
147
+ enabled?: boolean | undefined;
148
+ columns?: {
149
+ width?: number | undefined;
150
+ offset?: number | undefined;
151
+ color?: string | undefined;
152
+ spacing?: number | undefined;
153
+ enabled?: boolean | undefined;
154
+ } | undefined;
155
+ doorway?: {
156
+ color?: string | undefined;
157
+ enabled?: boolean | undefined;
158
+ opening?: number | undefined;
159
+ } | undefined;
160
+ }>;
161
+ /**
162
+ * The print: what happens to the frame after the scene is drawn.
163
+ *
164
+ * This lives on the stage rather than on the lighting rig, even though it
165
+ * belongs to the same family as `exposure` and `film`, because the rig is
166
+ * read by `<Paper>` too and `<Paper>` has no composer. A grade in the rig
167
+ * would be a promise one of the two modes could not keep.
168
+ *
169
+ * Every value defaults to a real look rather than to zero — a stage that
170
+ * asks for nothing should still be graded, and `grade: { bloom: 0 }` is how
171
+ * you say you want it raw.
172
+ */
173
+ declare const stageGradeSchema: z.ZodObject<{
174
+ /**
175
+ * How far light bleeds past what is emitting it.
176
+ *
177
+ * This is the one that matters most in a backlit hall, because the source
178
+ * plane is drawn with `toneMapped: false` — it is light, not an object, so
179
+ * no tone curve ever rolls it off. Bloom is the only thing that gives it
180
+ * an edge that behaves like light instead of like a lit rectangle.
181
+ */
182
+ bloom: z.ZodDefault<z.ZodNumber>;
183
+ /**
184
+ * How bright a pixel has to be before it blooms at all, in LINEAR light.
185
+ *
186
+ * Above 1.0 is not only legal, it is the useful range — and that is the
187
+ * whole reason the bound is 4 rather than 1. Bloom reads the scene before
188
+ * the tone curve, while values are still unbounded, so "1.0" means "as
189
+ * bright as white" rather than "as bright as the brightest pixel on
190
+ * screen". Lit near-white paper sits close to 1.0 all by itself; the
191
+ * source burns at `SOURCE_INTENSITY`, several times that. A threshold
192
+ * under 1 therefore blooms the PAPER, which fogs the hall and costs the
193
+ * sheets their edges — the exact failure this default is set to avoid.
194
+ */
195
+ threshold: z.ZodDefault<z.ZodNumber>;
196
+ /**
197
+ * Depth falloff — how much the near and far ends of the walk go soft.
198
+ *
199
+ * **Defaults to 0, and that is a considered default rather than a stub.**
200
+ * Depth in this scene is already staged by haze, which is how a real hall
201
+ * does it and which costs one fragment instruction; optical blur is a
202
+ * second full-screen pass with a circle-of-confusion buffer behind it, and
203
+ * it is the effect most likely to read as a video game rather than as a
204
+ * photograph. Every paper installation worth copying is shot deep — an
205
+ * f/11 room where the sheets at the far end are as sharp as the ones you
206
+ * can touch.
207
+ *
208
+ * It is here because a shallow frame is a legitimate look and the schema
209
+ * is the only place a look is allowed to live. Turn it up for a close shot
210
+ * on one banner; leave it alone for a hall.
211
+ */
212
+ depth: z.ZodDefault<z.ZodNumber>;
213
+ /** How far the corners fall off. A frame with no edge reads as a viewport rather than a photograph. */
214
+ vignette: z.ZodDefault<z.ZodNumber>;
215
+ /**
216
+ * Film grain.
217
+ *
218
+ * Worth more here than in most scenes: grain is the one texture shared
219
+ * between the render and the thing being rendered. Keep it under ~0.05 —
220
+ * past that it stops reading as stock and starts reading as noise.
221
+ */
222
+ grain: z.ZodDefault<z.ZodNumber>;
223
+ }, "strip", z.ZodTypeAny, {
224
+ grain: number;
225
+ depth: number;
226
+ bloom: number;
227
+ threshold: number;
228
+ vignette: number;
229
+ }, {
230
+ grain?: number | undefined;
231
+ depth?: number | undefined;
232
+ bloom?: number | undefined;
233
+ threshold?: number | undefined;
234
+ vignette?: number | undefined;
235
+ }>;
236
+ declare const stageSchema: z.ZodObject<{
237
+ path: z.ZodDefault<z.ZodObject<{
238
+ points: z.ZodDefault<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">>;
239
+ closed: z.ZodDefault<z.ZodBoolean>;
240
+ }, "strip", z.ZodTypeAny, {
241
+ points: [number, number][];
242
+ closed: boolean;
243
+ }, {
244
+ points?: [number, number][] | undefined;
245
+ closed?: boolean | undefined;
246
+ }>>;
247
+ shot: z.ZodDefault<z.ZodObject<{
248
+ shot: z.ZodDefault<z.ZodEnum<["follow", "lead", "low", "wide"]>>;
249
+ distance: z.ZodDefault<z.ZodNumber>;
250
+ height: z.ZodDefault<z.ZodNumber>;
251
+ lookAhead: z.ZodDefault<z.ZodNumber>;
252
+ offset: z.ZodDefault<z.ZodNumber>;
253
+ }, "strip", z.ZodTypeAny, {
254
+ height: number;
255
+ offset: number;
256
+ distance: number;
257
+ shot: "low" | "follow" | "lead" | "wide";
258
+ lookAhead: number;
259
+ }, {
260
+ height?: number | undefined;
261
+ offset?: number | undefined;
262
+ distance?: number | undefined;
263
+ shot?: "low" | "follow" | "lead" | "wide" | undefined;
264
+ lookAhead?: number | undefined;
265
+ }>>;
266
+ figure: z.ZodDefault<z.ZodObject<{
267
+ height: z.ZodDefault<z.ZodNumber>;
268
+ speed: z.ZodDefault<z.ZodNumber>;
269
+ stride: z.ZodDefault<z.ZodNumber>;
270
+ swing: z.ZodDefault<z.ZodNumber>;
271
+ color: z.ZodDefault<z.ZodString>;
272
+ finish: z.ZodDefault<z.ZodEnum<["silhouette", "shaded"]>>;
273
+ gait: z.ZodDefault<z.ZodEnum<["auto", "walk", "run"]>>;
274
+ model: z.ZodOptional<z.ZodString>;
275
+ }, "strip", z.ZodTypeAny, {
276
+ height: number;
277
+ speed: number;
278
+ color: string;
279
+ stride: number;
280
+ swing: number;
281
+ finish: "silhouette" | "shaded";
282
+ gait: "auto" | "walk" | "run";
283
+ model?: string | undefined;
284
+ }, {
285
+ height?: number | undefined;
286
+ speed?: number | undefined;
287
+ color?: string | undefined;
288
+ stride?: number | undefined;
289
+ swing?: number | undefined;
290
+ finish?: "silhouette" | "shaded" | undefined;
291
+ gait?: "auto" | "walk" | "run" | undefined;
292
+ model?: string | undefined;
293
+ }>>;
294
+ /** Stage mode is built for `nave`; the others are all front-lit. */
295
+ lighting: z.ZodDefault<z.ZodEnum<["studio", "window", "leaves", "goldenhour", "noir", "nave", "raking", "lightbox"]>>;
296
+ /**
297
+ * The light, by hand: exposure, key, direction, height, ambient, studio,
298
+ * haze. Overrides on `lighting` rather than a replacement for it, so a
299
+ * shared stage carries the sliders that were moved and nothing else.
300
+ */
301
+ light: z.ZodDefault<z.ZodObject<{
302
+ exposure: z.ZodOptional<z.ZodNumber>;
303
+ film: z.ZodOptional<z.ZodEnum<["agx", "neutral", "filmic"]>>;
304
+ key: z.ZodOptional<z.ZodNumber>;
305
+ color: z.ZodOptional<z.ZodString>;
306
+ direction: z.ZodOptional<z.ZodNumber>;
307
+ height: z.ZodOptional<z.ZodNumber>;
308
+ ambient: z.ZodOptional<z.ZodNumber>;
309
+ studio: z.ZodOptional<z.ZodNumber>;
310
+ haze: z.ZodOptional<z.ZodNumber>;
311
+ }, "strip", z.ZodTypeAny, {
312
+ key?: number | undefined;
313
+ height?: number | undefined;
314
+ color?: string | undefined;
315
+ studio?: number | undefined;
316
+ exposure?: number | undefined;
317
+ film?: "agx" | "neutral" | "filmic" | undefined;
318
+ direction?: number | undefined;
319
+ ambient?: number | undefined;
320
+ haze?: number | undefined;
321
+ }, {
322
+ key?: number | undefined;
323
+ height?: number | undefined;
324
+ color?: string | undefined;
325
+ studio?: number | undefined;
326
+ exposure?: number | undefined;
327
+ film?: "agx" | "neutral" | "filmic" | undefined;
328
+ direction?: number | undefined;
329
+ ambient?: number | undefined;
330
+ haze?: number | undefined;
331
+ }>>;
332
+ /**
333
+ * OFF by default now.
334
+ *
335
+ * The figure existed to say "this is a room at gallery scale", which is a
336
+ * real job and the right instinct. A rendered human is simply the most
337
+ * expensive and least reliable way to do it: it is the one thing in frame
338
+ * every viewer appraises, and a low-polygon one reads as an asset-store
339
+ * placeholder no matter how good the hall around it is.
340
+ *
341
+ * `stageRoomSchema` does the job instead, with objects whose size the
342
+ * viewer already knows. And the deciding argument is that the stage is
343
+ * NAVIGABLE — drag, wheel, arrow-step, click-to-approach — so there is
344
+ * already a person in the hall and it is the viewer. A second one walking
345
+ * the same aisle on its own clock competes for that role.
346
+ *
347
+ * Still one flag away for anyone who wants it.
348
+ */
349
+ showFigure: z.ZodDefault<z.ZodBoolean>;
350
+ source: z.ZodDefault<z.ZodObject<{
351
+ /** The bright void the walk resolves toward. Without it the vanishing point is a hole. */
352
+ enabled: z.ZodDefault<z.ZodBoolean>;
353
+ color: z.ZodDefault<z.ZodString>;
354
+ /** How far past the end of the walk it stands, world units. */
355
+ beyond: z.ZodDefault<z.ZodNumber>;
356
+ /**
357
+ * A cyclorama around the whole stage, graded from the source colour at the
358
+ * horizon to near-dark overhead. The source plane only faces down the walk,
359
+ * so without this every shot that isn't axial — `wide` especially — looks
360
+ * out at a black void where the room should be.
361
+ */
362
+ surround: z.ZodDefault<z.ZodBoolean>;
363
+ /** Colour overhead. The horizon takes the source's own colour. */
364
+ zenith: z.ZodDefault<z.ZodString>;
365
+ /**
366
+ * Size, as a multiple of the PAPER height.
367
+ *
368
+ * It is an OPENING, not a wall. At 5 the plane was 100 units across and
369
+ * filled the entire frame behind the colonnade, so the hall had no dark
370
+ * end to resolve toward and the whole picture sat at one value. Sized to
371
+ * roughly the height of the paper it stands behind, it reads as the way
372
+ * out — which is what the figure is walking toward.
373
+ */
374
+ spread: z.ZodDefault<z.ZodNumber>;
375
+ }, "strip", z.ZodTypeAny, {
376
+ color: string;
377
+ enabled: boolean;
378
+ spread: number;
379
+ zenith: string;
380
+ beyond: number;
381
+ surround: boolean;
382
+ }, {
383
+ color?: string | undefined;
384
+ enabled?: boolean | undefined;
385
+ spread?: number | undefined;
386
+ zenith?: string | undefined;
387
+ beyond?: number | undefined;
388
+ surround?: boolean | undefined;
389
+ }>>;
390
+ ground: z.ZodDefault<z.ZodObject<{
391
+ /** The floor. Without something to catch the shadows there is no ground and no scale. */
392
+ enabled: z.ZodDefault<z.ZodBoolean>;
393
+ /**
394
+ * Lifted off near-black (`#0e0b09`). A floor dark enough to disappear
395
+ * cannot show its own seams, and the seams are the scale cue — the hall
396
+ * kept its contrast against the source and gained a surface you can read
397
+ * the size of the room from.
398
+ */
399
+ color: z.ZodDefault<z.ZodString>;
400
+ /**
401
+ * Width of one poured slab, in world units. 0 leaves the floor unseamed.
402
+ *
403
+ * The cheapest scale cue there is, and the one this scene most lacked. A
404
+ * concrete floor is poured in bays of roughly two and a half metres, and a
405
+ * viewer knows that without being told — so a floor with seams in it
406
+ * states the size of the room, while a floor without them is a gradient
407
+ * that happens to be horizontal.
408
+ */
409
+ slab: z.ZodDefault<z.ZodNumber>;
410
+ }, "strip", z.ZodTypeAny, {
411
+ color: string;
412
+ enabled: boolean;
413
+ slab: number;
414
+ }, {
415
+ color?: string | undefined;
416
+ enabled?: boolean | undefined;
417
+ slab?: number | undefined;
418
+ }>>;
419
+ /** Ceiling and the architecture around the walk — see `stageRoomSchema`. */
420
+ room: z.ZodDefault<z.ZodObject<{
421
+ enabled: z.ZodDefault<z.ZodBoolean>;
422
+ /**
423
+ * Ceiling height, as a multiple of the paper's own height.
424
+ *
425
+ * Relative rather than absolute because the banners ARE the architecture
426
+ * here: a hall whose ceiling sits just above its hangings reads as built
427
+ * for them, and one at a fixed world height reads as whatever the paper
428
+ * happened to be scaled to that day.
429
+ */
430
+ height: z.ZodDefault<z.ZodNumber>;
431
+ color: z.ZodDefault<z.ZodString>;
432
+ /** Columns flanking the walk — see `stageColumnsSchema`. */
433
+ columns: z.ZodDefault<z.ZodObject<{
434
+ enabled: z.ZodDefault<z.ZodBoolean>;
435
+ /** Centres this far apart along the walk. Roughly a bay. */
436
+ spacing: z.ZodDefault<z.ZodNumber>;
437
+ /** Shaft width. The number doing the work — a column is a known size. */
438
+ width: z.ZodDefault<z.ZodNumber>;
439
+ /**
440
+ * How far off the walk's centreline each rank stands.
441
+ *
442
+ * Outside the banners, always. Columns are the room; the paper is the
443
+ * subject, and a column standing between the viewer and a banner has
444
+ * swapped the two over. Default clears a `colonnade`'s widest sensible
445
+ * aisle with room to spare.
446
+ */
447
+ offset: z.ZodDefault<z.ZodNumber>;
448
+ /**
449
+ * Stone, and darker than paper on purpose.
450
+ *
451
+ * The brightest thing in any of these frames has to be the light, and the
452
+ * second brightest has to be the paper. A column the same value as a
453
+ * banner does not read as architecture behind the subject; it reads as
454
+ * more banners, and the eye stops being able to tell what the room is made
455
+ * of from what is hanging in it.
456
+ */
457
+ color: z.ZodDefault<z.ZodString>;
458
+ }, "strip", z.ZodTypeAny, {
459
+ width: number;
460
+ offset: number;
461
+ color: string;
462
+ spacing: number;
463
+ enabled: boolean;
464
+ }, {
465
+ width?: number | undefined;
466
+ offset?: number | undefined;
467
+ color?: string | undefined;
468
+ spacing?: number | undefined;
469
+ enabled?: boolean | undefined;
470
+ }>>;
471
+ /** A wall at the end of the walk with the source in it. */
472
+ doorway: z.ZodDefault<z.ZodObject<{
473
+ enabled: z.ZodDefault<z.ZodBoolean>;
474
+ /** Opening size, as a multiple of the source's own. 1 frames it exactly. */
475
+ opening: z.ZodDefault<z.ZodNumber>;
476
+ color: z.ZodDefault<z.ZodString>;
477
+ }, "strip", z.ZodTypeAny, {
478
+ color: string;
479
+ enabled: boolean;
480
+ opening: number;
481
+ }, {
482
+ color?: string | undefined;
483
+ enabled?: boolean | undefined;
484
+ opening?: number | undefined;
485
+ }>>;
486
+ }, "strip", z.ZodTypeAny, {
487
+ height: number;
488
+ color: string;
489
+ enabled: boolean;
490
+ columns: {
491
+ width: number;
492
+ offset: number;
493
+ color: string;
494
+ spacing: number;
495
+ enabled: boolean;
496
+ };
497
+ doorway: {
498
+ color: string;
499
+ enabled: boolean;
500
+ opening: number;
501
+ };
502
+ }, {
503
+ height?: number | undefined;
504
+ color?: string | undefined;
505
+ enabled?: boolean | undefined;
506
+ columns?: {
507
+ width?: number | undefined;
508
+ offset?: number | undefined;
509
+ color?: string | undefined;
510
+ spacing?: number | undefined;
511
+ enabled?: boolean | undefined;
512
+ } | undefined;
513
+ doorway?: {
514
+ color?: string | undefined;
515
+ enabled?: boolean | undefined;
516
+ opening?: number | undefined;
517
+ } | undefined;
518
+ }>>;
519
+ /** Thread and clips — see `stageSuspensionSchema`. */
520
+ suspension: z.ZodDefault<z.ZodObject<{
521
+ /**
522
+ * What carries the load.
523
+ *
524
+ * `thread` is monofilament to the ceiling — one straight line per sheet.
525
+ * `rod` is a dowel across each sheet's top edge, hung from the ceiling at
526
+ * both ends, which is a different image entirely: a rank on threads reads
527
+ * as sheets floating in a row, and a rank on rods reads as sheets that
528
+ * were HUNG, by someone, on something. `none` is for a stage where the
529
+ * paper is meant to be impossible.
530
+ */
531
+ type: z.ZodDefault<z.ZodEnum<["none", "thread", "rod"]>>;
532
+ color: z.ZodDefault<z.ZodString>;
533
+ /**
534
+ * What grips the sheet.
535
+ *
536
+ * A clip is wide and shallow — the bulldog clip of a gallery. A peg is
537
+ * narrow and deep, and grips DOWN the face of the sheet rather than
538
+ * across its edge: the domestic one, a line of paper on a washing line.
539
+ * They are told apart by silhouette at any distance, which is the only
540
+ * thing that survives being one instanced box at the top of an
541
+ * eight-metre banner.
542
+ *
543
+ * This replaced a `clips: boolean`. Two of the four pieces of hardware the
544
+ * plan named — pegs, and a rod — had no way to be asked for, and a boolean
545
+ * cannot grow a third answer.
546
+ */
547
+ hardware: z.ZodDefault<z.ZodEnum<["none", "clip", "peg"]>>;
548
+ }, "strip", z.ZodTypeAny, {
549
+ type: "none" | "thread" | "rod";
550
+ color: string;
551
+ hardware: "none" | "clip" | "peg";
552
+ }, {
553
+ type?: "none" | "thread" | "rod" | undefined;
554
+ color?: string | undefined;
555
+ hardware?: "none" | "clip" | "peg" | undefined;
556
+ }>>;
557
+ /**
558
+ * The print — bloom, vignette, grain.
559
+ *
560
+ * Needs `@react-three/postprocessing` and `postprocessing`. They are
561
+ * declared OPTIONAL peers, which means `<Paper>` never pulls them in and a
562
+ * bundle that only imports `<Paper>` never contains them — not that a
563
+ * stage renders without them. A bundler asked to resolve `<PaperStage>`
564
+ * without them installed fails at build time, and that is the intended
565
+ * behaviour: a stage silently losing its grade would be worse than a
566
+ * missing-module error that names the package.
567
+ */
568
+ grade: z.ZodDefault<z.ZodObject<{
569
+ /**
570
+ * How far light bleeds past what is emitting it.
571
+ *
572
+ * This is the one that matters most in a backlit hall, because the source
573
+ * plane is drawn with `toneMapped: false` — it is light, not an object, so
574
+ * no tone curve ever rolls it off. Bloom is the only thing that gives it
575
+ * an edge that behaves like light instead of like a lit rectangle.
576
+ */
577
+ bloom: z.ZodDefault<z.ZodNumber>;
578
+ /**
579
+ * How bright a pixel has to be before it blooms at all, in LINEAR light.
580
+ *
581
+ * Above 1.0 is not only legal, it is the useful range — and that is the
582
+ * whole reason the bound is 4 rather than 1. Bloom reads the scene before
583
+ * the tone curve, while values are still unbounded, so "1.0" means "as
584
+ * bright as white" rather than "as bright as the brightest pixel on
585
+ * screen". Lit near-white paper sits close to 1.0 all by itself; the
586
+ * source burns at `SOURCE_INTENSITY`, several times that. A threshold
587
+ * under 1 therefore blooms the PAPER, which fogs the hall and costs the
588
+ * sheets their edges — the exact failure this default is set to avoid.
589
+ */
590
+ threshold: z.ZodDefault<z.ZodNumber>;
591
+ /**
592
+ * Depth falloff — how much the near and far ends of the walk go soft.
593
+ *
594
+ * **Defaults to 0, and that is a considered default rather than a stub.**
595
+ * Depth in this scene is already staged by haze, which is how a real hall
596
+ * does it and which costs one fragment instruction; optical blur is a
597
+ * second full-screen pass with a circle-of-confusion buffer behind it, and
598
+ * it is the effect most likely to read as a video game rather than as a
599
+ * photograph. Every paper installation worth copying is shot deep — an
600
+ * f/11 room where the sheets at the far end are as sharp as the ones you
601
+ * can touch.
602
+ *
603
+ * It is here because a shallow frame is a legitimate look and the schema
604
+ * is the only place a look is allowed to live. Turn it up for a close shot
605
+ * on one banner; leave it alone for a hall.
606
+ */
607
+ depth: z.ZodDefault<z.ZodNumber>;
608
+ /** How far the corners fall off. A frame with no edge reads as a viewport rather than a photograph. */
609
+ vignette: z.ZodDefault<z.ZodNumber>;
610
+ /**
611
+ * Film grain.
612
+ *
613
+ * Worth more here than in most scenes: grain is the one texture shared
614
+ * between the render and the thing being rendered. Keep it under ~0.05 —
615
+ * past that it stops reading as stock and starts reading as noise.
616
+ */
617
+ grain: z.ZodDefault<z.ZodNumber>;
618
+ }, "strip", z.ZodTypeAny, {
619
+ grain: number;
620
+ depth: number;
621
+ bloom: number;
622
+ threshold: number;
623
+ vignette: number;
624
+ }, {
625
+ grain?: number | undefined;
626
+ depth?: number | undefined;
627
+ bloom?: number | undefined;
628
+ threshold?: number | undefined;
629
+ vignette?: number | undefined;
630
+ }>>;
631
+ }, "strip", z.ZodTypeAny, {
632
+ path: {
633
+ points: [number, number][];
634
+ closed: boolean;
635
+ };
636
+ lighting: "studio" | "window" | "leaves" | "goldenhour" | "noir" | "nave" | "raking" | "lightbox";
637
+ figure: {
638
+ height: number;
639
+ speed: number;
640
+ color: string;
641
+ stride: number;
642
+ swing: number;
643
+ finish: "silhouette" | "shaded";
644
+ gait: "auto" | "walk" | "run";
645
+ model?: string | undefined;
646
+ };
647
+ source: {
648
+ color: string;
649
+ enabled: boolean;
650
+ spread: number;
651
+ zenith: string;
652
+ beyond: number;
653
+ surround: boolean;
654
+ };
655
+ light: {
656
+ key?: number | undefined;
657
+ height?: number | undefined;
658
+ color?: string | undefined;
659
+ studio?: number | undefined;
660
+ exposure?: number | undefined;
661
+ film?: "agx" | "neutral" | "filmic" | undefined;
662
+ direction?: number | undefined;
663
+ ambient?: number | undefined;
664
+ haze?: number | undefined;
665
+ };
666
+ shot: {
667
+ height: number;
668
+ offset: number;
669
+ distance: number;
670
+ shot: "low" | "follow" | "lead" | "wide";
671
+ lookAhead: number;
672
+ };
673
+ ground: {
674
+ color: string;
675
+ enabled: boolean;
676
+ slab: number;
677
+ };
678
+ showFigure: boolean;
679
+ room: {
680
+ height: number;
681
+ color: string;
682
+ enabled: boolean;
683
+ columns: {
684
+ width: number;
685
+ offset: number;
686
+ color: string;
687
+ spacing: number;
688
+ enabled: boolean;
689
+ };
690
+ doorway: {
691
+ color: string;
692
+ enabled: boolean;
693
+ opening: number;
694
+ };
695
+ };
696
+ suspension: {
697
+ type: "none" | "thread" | "rod";
698
+ color: string;
699
+ hardware: "none" | "clip" | "peg";
700
+ };
701
+ grade: {
702
+ grain: number;
703
+ depth: number;
704
+ bloom: number;
705
+ threshold: number;
706
+ vignette: number;
707
+ };
708
+ }, {
709
+ path?: {
710
+ points?: [number, number][] | undefined;
711
+ closed?: boolean | undefined;
712
+ } | undefined;
713
+ lighting?: "studio" | "window" | "leaves" | "goldenhour" | "noir" | "nave" | "raking" | "lightbox" | undefined;
714
+ figure?: {
715
+ height?: number | undefined;
716
+ speed?: number | undefined;
717
+ color?: string | undefined;
718
+ stride?: number | undefined;
719
+ swing?: number | undefined;
720
+ finish?: "silhouette" | "shaded" | undefined;
721
+ gait?: "auto" | "walk" | "run" | undefined;
722
+ model?: string | undefined;
723
+ } | undefined;
724
+ source?: {
725
+ color?: string | undefined;
726
+ enabled?: boolean | undefined;
727
+ spread?: number | undefined;
728
+ zenith?: string | undefined;
729
+ beyond?: number | undefined;
730
+ surround?: boolean | undefined;
731
+ } | undefined;
732
+ light?: {
733
+ key?: number | undefined;
734
+ height?: number | undefined;
735
+ color?: string | undefined;
736
+ studio?: number | undefined;
737
+ exposure?: number | undefined;
738
+ film?: "agx" | "neutral" | "filmic" | undefined;
739
+ direction?: number | undefined;
740
+ ambient?: number | undefined;
741
+ haze?: number | undefined;
742
+ } | undefined;
743
+ shot?: {
744
+ height?: number | undefined;
745
+ offset?: number | undefined;
746
+ distance?: number | undefined;
747
+ shot?: "low" | "follow" | "lead" | "wide" | undefined;
748
+ lookAhead?: number | undefined;
749
+ } | undefined;
750
+ ground?: {
751
+ color?: string | undefined;
752
+ enabled?: boolean | undefined;
753
+ slab?: number | undefined;
754
+ } | undefined;
755
+ showFigure?: boolean | undefined;
756
+ room?: {
757
+ height?: number | undefined;
758
+ color?: string | undefined;
759
+ enabled?: boolean | undefined;
760
+ columns?: {
761
+ width?: number | undefined;
762
+ offset?: number | undefined;
763
+ color?: string | undefined;
764
+ spacing?: number | undefined;
765
+ enabled?: boolean | undefined;
766
+ } | undefined;
767
+ doorway?: {
768
+ color?: string | undefined;
769
+ enabled?: boolean | undefined;
770
+ opening?: number | undefined;
771
+ } | undefined;
772
+ } | undefined;
773
+ suspension?: {
774
+ type?: "none" | "thread" | "rod" | undefined;
775
+ color?: string | undefined;
776
+ hardware?: "none" | "clip" | "peg" | undefined;
777
+ } | undefined;
778
+ grade?: {
779
+ grain?: number | undefined;
780
+ depth?: number | undefined;
781
+ bloom?: number | undefined;
782
+ threshold?: number | undefined;
783
+ vignette?: number | undefined;
784
+ } | undefined;
785
+ }>;
786
+ type StageConfig = z.infer<typeof stageSchema>;
787
+ type StageConfigInput = z.input<typeof stageSchema>;
788
+ type StageGradeConfig = z.infer<typeof stageGradeSchema>;
789
+
790
+ /**
791
+ * Moving through a stage.
792
+ *
793
+ * The scene was a picture you watched: the camera is stationed on the walk,
794
+ * the walk is driven by `progress`, and if nobody supplied one it ran on a
795
+ * clock. There was nothing to touch. This is the other half — the viewer
796
+ * drives the walk themselves, by dragging, by wheel, by arrow key, or by
797
+ * clicking the paper they want to stand in front of.
798
+ *
799
+ * It drives ONE number: distance walked. Everything else in the scene is
800
+ * already derived from that — the figure, the camera, the light at the end —
801
+ * so navigation cannot pull the parts of the scene away from each other,
802
+ * which is the failure this whole component is arranged to prevent. In
803
+ * particular the camera is still not something anything else may move: there
804
+ * is no orbit here, and dragging does not look around. It walks.
805
+ *
806
+ * Pure math lives here so it tests in node; the listeners are in `useWalk`.
807
+ */
808
+ declare const stageMotionSchema: z.ZodObject<{
809
+ /**
810
+ * Who drives the walk. Same three names as a field's, and they mean the
811
+ * same things — a stage and a field are the same contract seen from two
812
+ * distances.
813
+ *
814
+ * - `drag` — the viewer. Pointer, wheel, arrow keys, or a click on a paper.
815
+ * It DRIFTS on the clock until the first time they touch it, and then it
816
+ * is theirs for good. That is one behaviour rather than two drivers, and
817
+ * it is the default because the alternatives are each half wrong: a stage
818
+ * that only autoplays cannot be touched, and one that only waits opens as
819
+ * a still photograph of itself.
820
+ * - `autoplay` — the clock, and only the clock. It never hands over.
821
+ * - `none` — nothing. The walk stands wherever it was left.
822
+ *
823
+ * An explicit `progress` prop outranks all three: a stage bound to page
824
+ * scroll is a controlled component, and a driver fighting the page for the
825
+ * same number is the bug you would spend an afternoon on.
826
+ */
827
+ driver: z.ZodDefault<z.ZodEnum<["autoplay", "drag", "none"]>>;
828
+ /** Multiplier on the pace: the figure's walking speed for `autoplay`, the hand for `drag`. */
829
+ speed: z.ZodDefault<z.ZodNumber>;
830
+ /**
831
+ * Whether the walk takes the WHEEL and the TOUCH away from the page.
832
+ *
833
+ * True for a stage that fills the screen — it is the page, so there is
834
+ * nothing to take it from. False for one sitting in a column of prose,
835
+ * where capturing them means a reader who scrolls past it has their scroll
836
+ * eaten and a reader on a phone has their finger trapped. Dragging with a
837
+ * mouse and stepping with the arrow keys work either way, because neither
838
+ * is a gesture the page also wants.
839
+ *
840
+ * Even when captured, the wheel is handed BACK at the ends of an open
841
+ * walk: scrolling past the last banner should carry on down the page
842
+ * rather than press silently into a wall.
843
+ */
844
+ capture: z.ZodDefault<z.ZodBoolean>;
845
+ }, "strip", z.ZodTypeAny, {
846
+ speed: number;
847
+ driver: "none" | "autoplay" | "drag";
848
+ capture: boolean;
849
+ }, {
850
+ speed?: number | undefined;
851
+ driver?: "none" | "autoplay" | "drag" | undefined;
852
+ capture?: boolean | undefined;
853
+ }>;
854
+ type StageMotion = z.infer<typeof stageMotionSchema>;
855
+ type StageMotionInput = z.input<typeof stageMotionSchema>;
856
+
857
+ /**
858
+ * Render quality tiers.
859
+ *
860
+ * A stage is the heaviest thing this library draws — tens of thousands of
861
+ * subdivided vertices, a shadow pass, a translucent fragment shader and a
862
+ * full-screen backdrop — and it has to run on machines nobody developing it
863
+ * owns. Quality is deliberately NOT part of `stageSchema`: it describes the
864
+ * device, not the artwork, so it must never travel in a preset or a shared
865
+ * link. Two people opening the same link should see the same scene at
866
+ * whatever fidelity their hardware can hold.
867
+ *
868
+ * The five knobs, in the order they actually cost:
869
+ *
870
+ * - `segments` — a CEILING on what `segments: 'auto'` may ask for along the
871
+ * direction a banner's folds run. Quadratic in principle, though a
872
+ * deformer's own floor holds the bottom: `drape` states it needs 48 across
873
+ * its folds, so `low` cannot take the banners below that and should not.
874
+ *
875
+ * It used to be written straight over the sheet's `segments` as a number,
876
+ * and that made it **do nothing at all**. A number applies to BOTH axes,
877
+ * the field caps it at 48 on the way down, and the deformer floor raised
878
+ * it back to 48 on the way up — so every tier drew the identical 48 × 48
879
+ * banner. Measured before the fix: 143,644 triangles at `medium` whatever
880
+ * the tier said. Worth remembering as a shape of bug — a knob nobody had
881
+ * measured, in the file that exists to describe what things cost.
882
+ * - `shadowMapSize` — the shadow pass re-renders the scene's geometry. 0
883
+ * turns shadows off, which on a weak machine is the difference between
884
+ * moving and not.
885
+ * - `dpr` — fragment cost scales with the square of it, and this scene is
886
+ * fragment-heavy (translucency, fog, a full-screen backdrop).
887
+ * - `environment` — the studio light. One prefiltered cube built once, then
888
+ * a texture read per fragment for every lit surface in the scene. Measured
889
+ * at a third of the frame at `medium` (51 ms → 33 ms with it off), which
890
+ * makes it the most expensive single thing here after the geometry, so the
891
+ * bottom tier falls back to the flat ambient it replaced.
892
+ * - `surround` — one more full-screen draw; cheap, but free to drop.
893
+ */
894
+ declare const qualityNames: readonly ["auto", "low", "medium", "high"];
895
+ type QualityName = (typeof qualityNames)[number];
896
+ type QualityTier = Exclude<QualityName, 'auto'>;
897
+
898
+ interface PaperStageSceneProps {
899
+ /** Walk, shot, figure, lighting — see `stageSchema`. */
900
+ stage?: StageConfigInput;
901
+ /** Any layout, but `colonnade` is the one built to arrange along a walk. */
902
+ layout?: string;
903
+ layoutOptions?: Record<string, unknown>;
904
+ /** Per-banner slots, exactly as in field mode. */
905
+ papers?: FieldPaperSlot[];
906
+ images?: string[];
907
+ /**
908
+ * Words on the banners. A string is split across them a line at a time; an
909
+ * array is used as given. This is the whole point of the mode — a space
910
+ * built out of something the viewer wrote.
911
+ */
912
+ text?: string | string[];
913
+ /** Shared preset behind every banner. */
914
+ preset?: string | PaperConfigInput;
915
+ /** How many banners, when none of `papers` / `images` / `text` says. */
916
+ count?: number;
917
+ /**
918
+ * How far along the walk the figure is, 0..1. Bind it to scroll and the
919
+ * page scrolls the walk. Omit and `motion` decides who drives.
920
+ *
921
+ * Supplying it makes the stage a CONTROLLED component and outranks
922
+ * `motion` entirely — a driver and a page both writing the same number is
923
+ * a fight, not a feature.
924
+ */
925
+ progress?: number;
926
+ /**
927
+ * Who drives the walk when `progress` does not: `drag` hands it to the
928
+ * viewer (pointer, wheel, arrow keys, clicking a paper), `autoplay` to the
929
+ * clock, `none` to nobody. Same contract as a field's `motion`.
930
+ */
931
+ motion?: StageMotionInput;
932
+ /** Fires when the viewer moves to a paper — by clicking it, or by stepping onto it. */
933
+ onVisit?(paper: number): void;
934
+ /**
935
+ * The live position on the walk, 0..1, every frame it changes — whoever is
936
+ * driving. Mirror it into an uncontrolled input to show a scrubber that
937
+ * follows the walk without re-rendering the scene sixty times a second;
938
+ * `<PaperMesh>`'s `onProgress` is the same affordance for a behavior.
939
+ */
940
+ onProgress?(walk: number): void;
941
+ reducedMotion?: boolean;
942
+ /**
943
+ * How much the render is allowed to cost. `auto` (the default) starts in
944
+ * the middle and adapts to whatever the machine turns out to manage — this
945
+ * scene runs on hardware nobody developing it owns. Not part of the stage
946
+ * config: quality describes the DEVICE, not the artwork, so it must never
947
+ * travel in a preset or a shared link.
948
+ */
949
+ quality?: QualityName;
950
+ /**
951
+ * Fires when `auto` moves the tier. Useful for showing the viewer what
952
+ * they are getting, and for measuring what real machines settle on.
953
+ */
954
+ onQualityChange?(tier: QualityTier): void;
955
+ }
956
+ interface PaperStageProps extends PaperStageSceneProps {
957
+ children?: React.ReactNode;
958
+ className?: string;
959
+ style?: React.CSSProperties;
960
+ }
961
+ declare function PaperStageScene({ stage: stageInput, quality, onQualityChange, layout, layoutOptions, papers, images, text, preset, count, progress, motion, onVisit, onProgress, reducedMotion, }: PaperStageSceneProps): react.JSX.Element;
962
+ /** `<PaperStage />` owns its Canvas; `<PaperStageScene />` drops into an existing one. */
963
+ declare function PaperStage({ children, className, style, ...sceneProps }: PaperStageProps): react.JSX.Element;
964
+
965
+ /**
966
+ * The source's default burn, in linear light.
967
+ *
968
+ * Chosen by matching: at 3.4 the tone-mapped source lands on the same read
969
+ * as the un-mapped plane it replaces, so a stage that never mounts a
970
+ * composer looks the way it always did, and one that does gets a source
971
+ * that blooms instead of a rectangle that clips.
972
+ */
973
+ declare const SOURCE_INTENSITY = 3.4;
974
+
975
+ /**
976
+ * Named stages. A mode with no presets asks its visitor to invent a space
977
+ * out of eleven sliders before it will show them anything — and stage mode
978
+ * takes about fifteen seconds to understand once you have seen one, which
979
+ * means the presets ARE the explanation.
980
+ *
981
+ * Each names somewhere paper is actually hung at architectural scale, the
982
+ * same rule the layouts follow.
983
+ */
984
+ interface StagePreset {
985
+ id: string;
986
+ label: string;
987
+ /** One line, shown under the name. What you are about to look at. */
988
+ description: string;
989
+ stage: StageConfigInput;
990
+ layout: string;
991
+ layoutOptions?: Record<string, unknown>;
992
+ /** The paper itself — banners differ per stage more than anything else. */
993
+ paper?: PaperConfigInput;
994
+ count: number;
995
+ text?: string;
996
+ }
997
+ declare const stagePresets: Record<string, StagePreset>;
998
+ declare function getStagePreset(id: string): StagePreset;
999
+ declare function listStagePresets(): string[];
1000
+
1001
+ /**
1002
+ * The walk — a path across the ground plane that a figure follows and that
1003
+ * layouts arrange paper along. Pure 2D math (x, z on the floor, y is always
1004
+ * up), no three.js, so it tests in node and is cheap enough to call from
1005
+ * inside a layout's pure `pose`.
1006
+ *
1007
+ * Centripetal Catmull-Rom through the control points — it will not cusp or
1008
+ * overshoot when two points bunch together, which a uniform spline does —
1009
+ * resampled to a uniform arc-length polyline. That resampling is the point:
1010
+ * `pointAt(s)` advances at constant SPEED, so a figure stepping `s` forward
1011
+ * at a steady rate covers ground at a steady rate. A raw spline parameter
1012
+ * would have it sprint through the straights and crawl around the corners.
1013
+ */
1014
+ /** A point on the floor. */
1015
+ type Ground = [x: number, z: number];
1016
+ declare const walkPathSchema: z.ZodObject<{
1017
+ /**
1018
+ * Control points on the ground plane, [x, z]. The default walks away from
1019
+ * the camera down -Z — the shot every reference image is composed on.
1020
+ */
1021
+ points: z.ZodDefault<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">>;
1022
+ /** Join the last point back to the first: an endless walk, and the only form `phase` can slide. */
1023
+ closed: z.ZodDefault<z.ZodBoolean>;
1024
+ }, "strip", z.ZodTypeAny, {
1025
+ points: [number, number][];
1026
+ closed: boolean;
1027
+ }, {
1028
+ points?: [number, number][] | undefined;
1029
+ closed?: boolean | undefined;
1030
+ }>;
1031
+ type WalkPathOptions = z.infer<typeof walkPathSchema>;
1032
+ interface WalkPath {
1033
+ /** Total arc length in world units. */
1034
+ readonly length: number;
1035
+ readonly closed: boolean;
1036
+ /** `s` is normalized arc length: 0 = the start, 1 = the end. Closed paths wrap, open paths clamp. */
1037
+ pointAt(s: number): Ground;
1038
+ /** Unit forward direction at `s`. */
1039
+ tangentAt(s: number): Ground;
1040
+ /** Unit LEFT-hand normal at `s` — the side of the aisle a walker's left hand points to. */
1041
+ normalAt(s: number): Ground;
1042
+ }
1043
+ declare function createWalkPath(options: WalkPathOptions): WalkPath;
1044
+
1045
+ /**
1046
+ * Named walks. A path is a list of control points, which is the right thing
1047
+ * to serialize and the wrong thing to put in front of someone — nobody wants
1048
+ * to type coordinates to find out what a curved colonnade looks like. These
1049
+ * are the shapes worth starting from; every one resolves to ordinary points,
1050
+ * so editing on from here stays possible.
1051
+ */
1052
+ declare const walkNames: readonly ["straight", "bend", "ess", "ring", "spiral"];
1053
+ type WalkName = (typeof walkNames)[number];
1054
+ declare const walks: Record<WalkName, WalkPathOptions>;
1055
+ declare function getWalk(name: WalkName): WalkPathOptions;
1056
+
1057
+ /**
1058
+ * Where to put the camera on a walk.
1059
+ *
1060
+ * `fitCamera` in field/framing.ts solves a different problem — get every
1061
+ * sheet inside the frustum — and solving it here would produce the neutral
1062
+ * three-quarter product shot that stage mode exists to avoid. These are
1063
+ * SHOTS: a camera stationed relative to the walking figure, framing the
1064
+ * space rather than the objects, with the vanishing point doing the work.
1065
+ */
1066
+ declare const shotNames: readonly ["follow", "lead", "low", "wide"];
1067
+ type ShotName = (typeof shotNames)[number];
1068
+ declare const shotSchema: z.ZodObject<{
1069
+ shot: z.ZodDefault<z.ZodEnum<["follow", "lead", "low", "wide"]>>;
1070
+ /**
1071
+ * How far the camera stands off the figure ALONG the walk, world units.
1072
+ * `wide` reads it as how far back it stands; how far it steps aside is
1073
+ * derived from the paper, since that is what it has to clear.
1074
+ */
1075
+ distance: z.ZodDefault<z.ZodNumber>;
1076
+ /** Multiplier on the shot's natural camera height. 1 is as designed. */
1077
+ height: z.ZodDefault<z.ZodNumber>;
1078
+ /** How far up the walk the camera looks past the figure, world units. */
1079
+ lookAhead: z.ZodDefault<z.ZodNumber>;
1080
+ /** Sideways step off the walk line, world units. Positive is the walker's left. */
1081
+ offset: z.ZodDefault<z.ZodNumber>;
1082
+ }, "strip", z.ZodTypeAny, {
1083
+ height: number;
1084
+ offset: number;
1085
+ distance: number;
1086
+ shot: "low" | "follow" | "lead" | "wide";
1087
+ lookAhead: number;
1088
+ }, {
1089
+ height?: number | undefined;
1090
+ offset?: number | undefined;
1091
+ distance?: number | undefined;
1092
+ shot?: "low" | "follow" | "lead" | "wide" | undefined;
1093
+ lookAhead?: number | undefined;
1094
+ }>;
1095
+ type ShotOptions = z.infer<typeof shotSchema>;
1096
+ interface StageShot {
1097
+ position: [x: number, y: number, z: number];
1098
+ target: [x: number, y: number, z: number];
1099
+ }
1100
+ /**
1101
+ * What each shot is FOR. A stage has two subjects at very different scales —
1102
+ * a body about 1.75 units tall and paper five times that — and a camera that
1103
+ * only knows about the body frames the body, which is how a colonnade of
1104
+ * printed banners ends up showing its bottom third and the tops of some
1105
+ * letterforms. Camera height stays a body measurement (eye level is eye
1106
+ * level); where it AIMS is a blend, and the paper carries most of it.
1107
+ */
1108
+ interface StageScale {
1109
+ /** Standing height of the figure. */
1110
+ figure: number;
1111
+ /** Height of the tallest paper on the stage. */
1112
+ paper: number;
1113
+ }
1114
+
1115
+ /**
1116
+ * Stage-mode export. Same anatomy and version as the paper and field
1117
+ * exports, with one addition that matters more than the rest: the scroll
1118
+ * variant. `progress` is the whole interaction model of a stage, and a
1119
+ * scroll-driven hero is what most people opening this menu actually want —
1120
+ * so the export writes the pinning and the scroll math, which is the part
1121
+ * that is fiddly to get right and boring to write.
1122
+ */
1123
+ interface StageExportInput {
1124
+ stage: StageConfigInput;
1125
+ layout: string;
1126
+ layoutOptions?: Record<string, unknown>;
1127
+ /** The banner itself — dims, stock, drape. Omitted uses the built-in banner. */
1128
+ paper?: PaperConfigInput;
1129
+ /** The words the space is built from. Omitted renders blank banners. */
1130
+ text?: string;
1131
+ count?: number;
1132
+ /** Bind the walk to page scroll, pinned, rather than to the clock. */
1133
+ scroll?: boolean;
1134
+ /** Exported component name. */
1135
+ componentName?: string;
1136
+ }
1137
+ /** Which named walk these points are, if any — the export reads better for it. */
1138
+ declare function walkNameFor(path: StageConfig['path']): WalkName | undefined;
1139
+ /** The stage config with defaults removed — what actually needs writing down. */
1140
+ declare function diffStage(stage: StageConfigInput): Record<string, unknown>;
1141
+ /**
1142
+ * JSON.stringify, except an array of plain numbers stays on one line. A walk
1143
+ * is a list of coordinate pairs, and the default pretty-printer spreads each
1144
+ * `[6, 17]` over four lines — twenty lines of punctuation for one gentle
1145
+ * curve. Exported code is a product surface; it should read like something a
1146
+ * person wrote.
1147
+ */
1148
+ declare function stringifyStage(value: unknown, indent?: number): string;
1149
+ /** The one-line visual an agent verifies after `npm run dev`. */
1150
+ declare function describeStage(input: StageExportInput): string;
1151
+ /** Component source shared by the JSX snippet and the agent payload. */
1152
+ declare function buildStageComponentSource(input: StageExportInput): string;
1153
+ /** The self-contained stage integration brief — one paste into a coding agent. */
1154
+ declare function buildStageAgentPayload(input: StageExportInput): string;
1155
+
1156
+ export { type Ground, PaperStage, type PaperStageProps, PaperStageScene, type PaperStageSceneProps, type QualityName, type QualityTier, SOURCE_INTENSITY, type ShotName, type ShotOptions, type StageConfig, type StageConfigInput, type StageExportInput, type StageGradeConfig, type StageMotion, type StageMotionInput, type StagePreset, type StageScale, type StageShot, type WalkName, type WalkPath, type WalkPathOptions, buildStageAgentPayload, buildStageComponentSource, createWalkPath, describeStage, diffStage, getStagePreset, getWalk, listStagePresets, qualityNames, shotNames, stageGradeSchema, stageMotionSchema, stagePresets, stageRoomSchema, stageSchema, stageSuspensionSchema, stringifyStage, walkNameFor, walkNames, walks };