@idle-screens/schema 3.6.1 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/FORMAT.md +261 -37
- package/dist/index.d.ts +274 -8
- package/dist/index.js +852 -86
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/saver-spec.schema.json +71 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Rng, SaverPlugin, SaverManifest } from '@idle-screens/core';
|
|
1
|
+
import { Rng, SaverContext, SaverPlugin, SaverManifest } from '@idle-screens/core';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Declarative, agent-authorable saver format. A `SaverSpec` describes a saver as DATA
|
|
@@ -291,6 +291,8 @@ type SpriteSpec = {
|
|
|
291
291
|
baseline?: 'top' | 'middle' | 'bottom';
|
|
292
292
|
maxWidth?: number;
|
|
293
293
|
cycle?: CycleSpec;
|
|
294
|
+
/** See `TextRole`. Absent ⇒ no legibility advisories, no pixel change. */
|
|
295
|
+
role?: TextRole;
|
|
294
296
|
}
|
|
295
297
|
/** `soft` renders a radial falloff (glow orb) instead of a hard disc.
|
|
296
298
|
* `colorWeights` (same length as `colors`) biases the seeded per-entity pick —
|
|
@@ -409,13 +411,49 @@ type SpriteSpec = {
|
|
|
409
411
|
| {
|
|
410
412
|
kind: 'textBlock';
|
|
411
413
|
text: string;
|
|
414
|
+
/** Wrap width as a fraction of `min(w,h)` (up to 2.0 — `text-off-screen` catches overflow). */
|
|
412
415
|
maxWidth: number;
|
|
413
416
|
fontSize: number;
|
|
414
417
|
lineHeight?: number;
|
|
418
|
+
/** Moves the painted lines inside the wrap width (ragged edge); never the block. */
|
|
415
419
|
align?: 'left' | 'center' | 'right';
|
|
416
420
|
color?: string;
|
|
417
421
|
reveal?: TextRevealSpec;
|
|
422
|
+
/**
|
|
423
|
+
* Which point of the rendered text (widest line × lines·lineHeight, as
|
|
424
|
+
* `align` lays it out) `position` names. Absent: today's behaviour —
|
|
425
|
+
* `position` is the top-left of the `maxWidth` layout box. With
|
|
426
|
+
* `'center'` the block is centred at `position` on every aspect ratio.
|
|
427
|
+
* Placement, so it is in the structural signature.
|
|
428
|
+
*/
|
|
429
|
+
anchor?: TextBlockAnchor;
|
|
430
|
+
/**
|
|
431
|
+
* CSS font family and/or weight/style only (`"bold monospace"`,
|
|
432
|
+
* `"300 'Inter', sans-serif"`). A size inside it is rejected —
|
|
433
|
+
* `fontSize` owns size. Absent: `system-ui, sans-serif`.
|
|
434
|
+
*/
|
|
435
|
+
font?: string;
|
|
436
|
+
/**
|
|
437
|
+
* 0..1 multiplier on the block's paint alpha (default 1). Paint, not
|
|
438
|
+
* carpentry: excluded from the structural signature, so steering it
|
|
439
|
+
* with `dur` glides the block in or out without a rebuild. Declare it
|
|
440
|
+
* (`"opacity": 1`) to make the path steerable.
|
|
441
|
+
*/
|
|
442
|
+
opacity?: number;
|
|
443
|
+
/** See `TextRole`. Absent ⇒ no legibility advisories, no pixel change. */
|
|
444
|
+
role?: TextRole;
|
|
418
445
|
};
|
|
446
|
+
/**
|
|
447
|
+
* What a text layer is *for* — a declaration, not a pixel. `read` says the
|
|
448
|
+
* words must be readable from across the room and opts the layer into
|
|
449
|
+
* `adviseSpec`'s legibility advisories (`text-legibility`, `text-safe-area`).
|
|
450
|
+
* `atmosphere` says the text is texture (a haiku fading in a corner, dim
|
|
451
|
+
* labels on a wall board) and is the same as absent: silent. Changes no
|
|
452
|
+
* pixel anywhere, on any client; never part of the structural signature.
|
|
453
|
+
*/
|
|
454
|
+
type TextRole = 'read' | 'atmosphere';
|
|
455
|
+
/** Compass points of a `textBlock`'s rendered box that `position` may name. */
|
|
456
|
+
type TextBlockAnchor = 'top-left' | 'top' | 'top-right' | 'left' | 'center' | 'right' | 'bottom-left' | 'bottom' | 'bottom-right';
|
|
419
457
|
/**
|
|
420
458
|
* Animated typing/deleting for `textBlock`. Layout always runs on the FULL
|
|
421
459
|
* text — reveal only masks which glyphs are painted, so lines never reflow
|
|
@@ -582,6 +620,20 @@ interface SpecWarning {
|
|
|
582
620
|
path: string;
|
|
583
621
|
code: string;
|
|
584
622
|
message: string;
|
|
623
|
+
/**
|
|
624
|
+
* Viewport-fraction boxes (`x`, `y`, `w`, `h` of `width`/`height`) the
|
|
625
|
+
* warning is about — `text-overlap` carries the two text boxes so an agent
|
|
626
|
+
* can move one without re-deriving the layout. Present only where a
|
|
627
|
+
* warning has geometry to report.
|
|
628
|
+
*/
|
|
629
|
+
boxes?: WarningBox[];
|
|
630
|
+
}
|
|
631
|
+
/** A rectangle in viewport fractions (x/w of width, y/h of height). */
|
|
632
|
+
interface WarningBox {
|
|
633
|
+
x: number;
|
|
634
|
+
y: number;
|
|
635
|
+
w: number;
|
|
636
|
+
h: number;
|
|
585
637
|
}
|
|
586
638
|
/** Perf/safety caps enforced by `validateSpec`. */
|
|
587
639
|
declare const LIMITS: {
|
|
@@ -613,7 +665,7 @@ declare const LIMITS: {
|
|
|
613
665
|
readonly maxTextBlockLength: 2000;
|
|
614
666
|
readonly minTextBlockFontSize: 0.01;
|
|
615
667
|
readonly maxTextBlockFontSize: 0.2;
|
|
616
|
-
readonly maxTextBlockMaxWidth:
|
|
668
|
+
readonly maxTextBlockMaxWidth: 2;
|
|
617
669
|
readonly maxRevealSpeed: 120;
|
|
618
670
|
readonly maxCaretBlinkHz: 3;
|
|
619
671
|
readonly maxSegments: 24;
|
|
@@ -637,9 +689,30 @@ declare const LIMITS: {
|
|
|
637
689
|
};
|
|
638
690
|
type SequenceTransition = {
|
|
639
691
|
type: 'cut';
|
|
640
|
-
}
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Interpolate numbers and hex colours into the next (structurally
|
|
695
|
+
* identical) segment over `dur` ms. Strings step on the first frame —
|
|
696
|
+
* unless `text: 'crossfade'`, which draws each `text` / `textBlock` layer
|
|
697
|
+
* whose string(s) differ twice for the window: the outgoing string at
|
|
698
|
+
* `1 − k`, the incoming at `k` (k = the morph's eased progress). Default
|
|
699
|
+
* `'step'`, today's behaviour, byte for byte.
|
|
700
|
+
*/
|
|
701
|
+
| {
|
|
641
702
|
type: 'morph';
|
|
642
703
|
dur: number;
|
|
704
|
+
text?: 'step' | 'crossfade';
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Cross-fade into the next segment over `dur` ms: the outgoing segment
|
|
708
|
+
* stays alive on its own canvas and is composited over the incoming one
|
|
709
|
+
* at `1 − easeSmooth(localT / dur)`. Works between unlike segments (no
|
|
710
|
+
* structural requirement). Hosts on the `basic`/`minimal` capability tier
|
|
711
|
+
* render it as `cut` (see `SequenceMountContext.capabilityTier`).
|
|
712
|
+
*/
|
|
713
|
+
| {
|
|
714
|
+
type: 'fade';
|
|
715
|
+
dur: number;
|
|
643
716
|
};
|
|
644
717
|
interface SequenceSegment {
|
|
645
718
|
key: string;
|
|
@@ -657,6 +730,25 @@ interface IdleSequence {
|
|
|
657
730
|
label: string;
|
|
658
731
|
seed?: number;
|
|
659
732
|
loop: boolean;
|
|
733
|
+
/**
|
|
734
|
+
* What the sequence clock is anchored to. `mount` (default — today's
|
|
735
|
+
* behaviour): every viewer starts at T = 0 when it mounts, so a joiner sees
|
|
736
|
+
* segment 0 (pre-roll semantics). `epoch`: a viewer handed `sequenceBaseT`
|
|
737
|
+
* on its mount context (the host's `Date.now() − epoch`) starts its clock
|
|
738
|
+
* there, so every screen in a room shows the same segment — a late joiner
|
|
739
|
+
* lands mid-loop. `advance: 'input'` holds stay armed under either mode.
|
|
740
|
+
*/
|
|
741
|
+
sync?: 'mount' | 'epoch';
|
|
742
|
+
/**
|
|
743
|
+
* A scene drawn under every segment on the sequence's **global** clock —
|
|
744
|
+
* the ground that does not reset at a boundary or under a `sequence.segment`
|
|
745
|
+
* steer. Segments render over it transparently (their `background` and
|
|
746
|
+
* `ghosting` are ignored; the bed may declare its own). Its entities count
|
|
747
|
+
* toward the perf cap together with the largest segment's, since the two
|
|
748
|
+
* are live at once. Steer it with `bed.<path>`. Absent ⇒ every segment
|
|
749
|
+
* paints its own ground, exactly as before the field existed.
|
|
750
|
+
*/
|
|
751
|
+
bed?: SaverSpec;
|
|
660
752
|
segments: SequenceSegment[];
|
|
661
753
|
}
|
|
662
754
|
|
|
@@ -673,6 +765,8 @@ declare function assertValidSequence(seq: unknown): IdleSequence;
|
|
|
673
765
|
|
|
674
766
|
/** Near plane for warp motion. z lives in [WARP_NEAR, 1]; screen scale is 1/z. */
|
|
675
767
|
declare const WARP_NEAR = 0.08;
|
|
768
|
+
/** Cap on the 1/z size multiplier so near stars don't blow out. */
|
|
769
|
+
declare const WARP_MAX_SCALE = 8;
|
|
676
770
|
/** One axis-pair of seeded harmonic octaves for wander motion (amps px, freqs rad/ms). */
|
|
677
771
|
interface WanderOsc {
|
|
678
772
|
ax: number[];
|
|
@@ -835,8 +929,26 @@ declare function linkPairs(positions: Array<{
|
|
|
835
929
|
x: number;
|
|
836
930
|
y: number;
|
|
837
931
|
}>, k: number, maxDist: number, doWrap: boolean, w: number, h: number): Array<[number, number]>;
|
|
838
|
-
/**
|
|
839
|
-
|
|
932
|
+
/**
|
|
933
|
+
* Which advance table the line-breaker uses. `proportional` is the
|
|
934
|
+
* character-class table below (the default, and the only table until
|
|
935
|
+
* `textBlock.font` existed); `mono` is a uniform 0.6 em advance — the classic
|
|
936
|
+
* monospace cell (Courier, Menlo, SF Mono all sit within a percent of it).
|
|
937
|
+
*/
|
|
938
|
+
type TextMetricsClass = 'proportional' | 'mono';
|
|
939
|
+
/**
|
|
940
|
+
* Metrics class for a `textBlock.font` string: `mono` when the family names
|
|
941
|
+
* a monospace face (the generic `monospace`, or a well-known fixed-pitch
|
|
942
|
+
* family), else `proportional`. Absent font ⇒ proportional, as before.
|
|
943
|
+
*/
|
|
944
|
+
declare function textMetricsClassFor(font?: string): TextMetricsClass;
|
|
945
|
+
/**
|
|
946
|
+
* Em-width of a string under the same character-class table `breakTextBlock`
|
|
947
|
+
* uses. `mono` counts grapheme clusters, not UTF-16 code units — an emoji or
|
|
948
|
+
* combining/ZWJ sequence is one advance-width cell, matching what's painted,
|
|
949
|
+
* not one cell per surrogate half or combining mark.
|
|
950
|
+
*/
|
|
951
|
+
declare function textWidthEm(str: string, metrics?: TextMetricsClass): number;
|
|
840
952
|
interface TextBlockLine {
|
|
841
953
|
text: string;
|
|
842
954
|
widthEm: number;
|
|
@@ -846,7 +958,24 @@ interface TextBlockLine {
|
|
|
846
958
|
* whitespace; a single word wider than the limit gets its own line unbroken.
|
|
847
959
|
* Explicit `\n` always forces a break. Pure, deterministic, no canvas needed.
|
|
848
960
|
*/
|
|
849
|
-
declare function breakTextBlock(text: string, maxWidthEm: number): TextBlockLine[];
|
|
961
|
+
declare function breakTextBlock(text: string, maxWidthEm: number, metrics?: TextMetricsClass): TextBlockLine[];
|
|
962
|
+
/**
|
|
963
|
+
* Where an anchored textBlock's layout origin sits relative to `position`:
|
|
964
|
+
* the (dx, dy) to ADD to `position` so that the named point of the rendered
|
|
965
|
+
* text lands on it. The rendered box is the widest line wide (placed inside
|
|
966
|
+
* the `maxWidth` box by `align`) and `lines × lineHeight` tall — so `anchor`
|
|
967
|
+
* says where the block sits and `align` only shapes its ragged edge. Absent
|
|
968
|
+
* anchor ⇒ (0, 0): `position` stays the layout box's top-left, exactly as
|
|
969
|
+
* before the field existed. Renderer, perception and advisories all call
|
|
970
|
+
* this, so their boxes agree by construction.
|
|
971
|
+
*/
|
|
972
|
+
declare function textBlockAnchorOffset(s: {
|
|
973
|
+
anchor?: TextBlockAnchor;
|
|
974
|
+
align?: 'left' | 'center' | 'right';
|
|
975
|
+
}, maxWPx: number, maxLineW: number, totalH: number): {
|
|
976
|
+
dx: number;
|
|
977
|
+
dy: number;
|
|
978
|
+
};
|
|
850
979
|
/**
|
|
851
980
|
* Split a string into paint-safe grapheme clusters: surrogate pairs stay
|
|
852
981
|
* whole, combining marks / variation selectors / skin tones attach to their
|
|
@@ -893,6 +1022,25 @@ declare function manifestFor(spec: SaverSpec): SaverManifest;
|
|
|
893
1022
|
* deterministic, `renderFrame(t,seed)`-addressable, and flash-safe by construction.
|
|
894
1023
|
*/
|
|
895
1024
|
declare function compileSaver(spec: unknown): SaverPlugin;
|
|
1025
|
+
/**
|
|
1026
|
+
* Mount context for a compiled sequence. A plain `SaverContext` works — the
|
|
1027
|
+
* clock starts at 0, as every SaverPlugin's does. `sequenceBaseT` is read
|
|
1028
|
+
* only when the sequence declares `sync: 'epoch'`; hosts pass the shared
|
|
1029
|
+
* clock's elapsed ms (idlescreens.com: `Date.now() − scene.epoch`) so every
|
|
1030
|
+
* viewer of that sequence resolves the same segment.
|
|
1031
|
+
*/
|
|
1032
|
+
interface SequenceMountContext extends SaverContext {
|
|
1033
|
+
/** ms already elapsed on the shared sequence clock. Ignored unless `sync: 'epoch'`. */
|
|
1034
|
+
sequenceBaseT?: number;
|
|
1035
|
+
/**
|
|
1036
|
+
* The device's compute tier (`computeTier` from `@idle-screens/capabilities`;
|
|
1037
|
+
* the string union is repeated here so schema does not depend on that
|
|
1038
|
+
* package). A `fade` transition keeps two segments live for `dur`, which
|
|
1039
|
+
* `basic` (canvas2d only) and `minimal` cannot afford: on those tiers fade
|
|
1040
|
+
* renders as `cut`. Absent ⇒ fade enabled.
|
|
1041
|
+
*/
|
|
1042
|
+
capabilityTier?: 'minimal' | 'basic' | 'standard' | 'high';
|
|
1043
|
+
}
|
|
896
1044
|
declare function compileSequence(spec: unknown): SaverPlugin;
|
|
897
1045
|
|
|
898
1046
|
/**
|
|
@@ -925,6 +1073,20 @@ declare function applyDeltasToSpec(spec: SaverSpec, deltas: SteerDelta[]): Saver
|
|
|
925
1073
|
* target immediately (k > 0). Layer counts round to integers.
|
|
926
1074
|
*/
|
|
927
1075
|
declare function lerpSpec(from: SaverSpec, to: SaverSpec, k: number): SaverSpec;
|
|
1076
|
+
/**
|
|
1077
|
+
* The string(s) a text layer paints — `strings` of a `text` sprite, `text`
|
|
1078
|
+
* of a `textBlock` — or null for every other sprite.
|
|
1079
|
+
*/
|
|
1080
|
+
declare function textStringsOf(sprite: SpriteSpec): string[] | null;
|
|
1081
|
+
/**
|
|
1082
|
+
* Whether the text layer at index `i` paints different words in `a` and
|
|
1083
|
+
* `b` — the layers a morph `text: 'crossfade'` draws twice. False for
|
|
1084
|
+
* non-text layers and when the strings match.
|
|
1085
|
+
*/
|
|
1086
|
+
declare function textStringsDiffer(a: SaverSpec, b: SaverSpec, i: number): boolean;
|
|
1087
|
+
declare function morphNothingMorphable(a: SaverSpec, b: SaverSpec, opts?: {
|
|
1088
|
+
textCrossfade?: boolean;
|
|
1089
|
+
}): boolean;
|
|
928
1090
|
/**
|
|
929
1091
|
* Enumerate all steerable leaf paths in a (resolved) spec. Returns dot-paths
|
|
930
1092
|
* like "layers.0.count", "background.stops.1.color", etc. Metadata fields
|
|
@@ -935,6 +1097,14 @@ declare function lerpSpec(from: SaverSpec, to: SaverSpec, k: number): SaverSpec;
|
|
|
935
1097
|
* Consumers can map to key-based paths via resolveSpecPath if needed.
|
|
936
1098
|
*/
|
|
937
1099
|
declare function steerablePaths(spec: unknown): string[];
|
|
1100
|
+
/**
|
|
1101
|
+
* Every path a sequence accepts on its track: `sequence.segment` (the
|
|
1102
|
+
* clicker), the bed's paths under the `bed.` prefix, and the union of every
|
|
1103
|
+
* segment's paths (a segment path lands on whichever segment owns it — see
|
|
1104
|
+
* `SequenceInstance.applyTrack`). Deduplicated, numeric layer indices as in
|
|
1105
|
+
* `steerablePaths`.
|
|
1106
|
+
*/
|
|
1107
|
+
declare function sequenceSteerablePaths(seq: IdleSequence): string[];
|
|
938
1108
|
/** Smooth (ease-in-out) progress curve used for glides. */
|
|
939
1109
|
declare function easeSmooth(k: number): number;
|
|
940
1110
|
/**
|
|
@@ -1289,6 +1459,58 @@ interface ScenePerception {
|
|
|
1289
1459
|
* Intended as the payload behind an MCP previewScene.
|
|
1290
1460
|
*/
|
|
1291
1461
|
declare function perceiveScene(spec: SaverSpec, opts?: LuminanceGridOptions): ScenePerception;
|
|
1462
|
+
interface SequenceFramePerception extends ScenePerception {
|
|
1463
|
+
/** Which segment the global time `T` resolved to, and where in it. */
|
|
1464
|
+
segment: {
|
|
1465
|
+
index: number;
|
|
1466
|
+
key: string;
|
|
1467
|
+
localT: number;
|
|
1468
|
+
held?: true;
|
|
1469
|
+
};
|
|
1470
|
+
/** True when a bed was composed under the segment. */
|
|
1471
|
+
bed: boolean;
|
|
1472
|
+
}
|
|
1473
|
+
interface PerceiveSequenceOptions extends Omit<LuminanceGridOptions, 't'> {
|
|
1474
|
+
/** Holds released by the clicker so far — see `ResolveOptions.releasedBelow`. */
|
|
1475
|
+
releasedBelow?: number;
|
|
1476
|
+
}
|
|
1477
|
+
/**
|
|
1478
|
+
* Perceive one frame of a sequence at global time `T`: resolve the segment,
|
|
1479
|
+
* then — when the sequence has a `bed` — compose the bed at `T` (its clock
|
|
1480
|
+
* never resets) under the segment's ink at `localT`, the segment's own
|
|
1481
|
+
* background dropped, exactly as the renderer stacks them. The luminance maps
|
|
1482
|
+
* add the two grids (clamped), so coverage, centroid and the profiles are of
|
|
1483
|
+
* the composite; dominance ranks bed and segment layers together by their raw
|
|
1484
|
+
* weights, bed layers keyed `bed:<key|index>`; text, motion and form list bed
|
|
1485
|
+
* layers first with the same prefix. Bed and segment are assumed to share
|
|
1486
|
+
* `units`/`referenceViewport`, as the renderer's shared canvas assumes. The
|
|
1487
|
+
* bed and segment seeds come from `segmentRenderSeed`/`bedRenderSeed`
|
|
1488
|
+
* (`./sequence`) — the same derivation `SequenceInstance` uses, chain roots
|
|
1489
|
+
* and zero-seed normalization included — so the composed frame matches what
|
|
1490
|
+
* the renderer actually draws at `T`, not just what the raw specs would show.
|
|
1491
|
+
* Without a bed this is `perceiveScene(segment, localT)` plus the `segment`
|
|
1492
|
+
* field. Intended as the payload behind a sequence-aware previewScene.
|
|
1493
|
+
*
|
|
1494
|
+
* Two known approximations, both accepted for a coarse, cheap, renderer-free
|
|
1495
|
+
* tool rather than fixed here:
|
|
1496
|
+
* - **The transition WINDOW isn't composed.** During a live `fade` or `morph`
|
|
1497
|
+
* (i.e. `localT < transition.dur`) the renderer also paints the outgoing
|
|
1498
|
+
* (or interpolating) segment, but this only ever perceives the segment
|
|
1499
|
+
* `resolveSegment` resolves to — call it at a `T` outside the transition's
|
|
1500
|
+
* `dur` for an accurate read. (Outside that window, a morph-chained
|
|
1501
|
+
* segment's entities and seed ARE correct — `segmentRenderSeed` already
|
|
1502
|
+
* resolves the chain root.) Composing the live window properly needs the
|
|
1503
|
+
* same capability-tier gate `SequenceInstance` uses to decide whether
|
|
1504
|
+
* `fade` even plays; this analytical path has no such context.
|
|
1505
|
+
* - **Ink composites onto the bed by addition, not by blend mode.** This
|
|
1506
|
+
* matches a plain `source-over`, opaque-ink segment (the common case), but
|
|
1507
|
+
* a segment layer with `blend: 'multiply'`/`'screen'`/etc. or partial alpha
|
|
1508
|
+
* composites directionally differently on the real canvas than adding
|
|
1509
|
+
* luminance values ever can (`multiply` darkens; addition only brightens).
|
|
1510
|
+
* The per-cell grids don't retain per-layer blend/alpha to composite
|
|
1511
|
+
* correctly at this resolution.
|
|
1512
|
+
*/
|
|
1513
|
+
declare function perceiveSequenceFrame(seq: IdleSequence, T: number, opts?: PerceiveSequenceOptions): SequenceFramePerception;
|
|
1292
1514
|
|
|
1293
1515
|
interface ResolvedSegment {
|
|
1294
1516
|
index: number;
|
|
@@ -1333,6 +1555,33 @@ declare function segmentStart(seq: IdleSequence, index: number): number;
|
|
|
1333
1555
|
* mode (validated elsewhere).
|
|
1334
1556
|
*/
|
|
1335
1557
|
declare function resolveSegment(seq: IdleSequence, T: number, opts?: ResolveOptions): ResolvedSegment;
|
|
1558
|
+
/** Whether the boundary from `from` to `from + 1` morphs: same scene structure, `morph` transition. */
|
|
1559
|
+
declare function canMorph(seq: IdleSequence, from: number): boolean;
|
|
1560
|
+
/**
|
|
1561
|
+
* Walk back through consecutive `morph` boundaries to the chain's origin. A
|
|
1562
|
+
* morph-chained segment's entities are never re-seeded at the boundary —
|
|
1563
|
+
* they're the same stream continued from wherever the chain started — so its
|
|
1564
|
+
* actual render seed (see `segmentRenderSeed`) is always the chain root's,
|
|
1565
|
+
* never its own index's.
|
|
1566
|
+
*/
|
|
1567
|
+
declare function morphChainRoot(seq: IdleSequence, index: number): number;
|
|
1568
|
+
/** `SpecInstance`'s seed normalization: 0 is falsy, so a valid `seed: 0` lands on 1. */
|
|
1569
|
+
declare function normalizeSeed(seed: number): number;
|
|
1570
|
+
/**
|
|
1571
|
+
* The seed segment `index`'s entities actually render with — its chain
|
|
1572
|
+
* root's own seed, else `seq.seed + ` the chain root's index, normalized
|
|
1573
|
+
* exactly like `SpecInstance`. `undefined` when neither is set: the same
|
|
1574
|
+
* "unknowable ahead of time" case a bare `SaverSpec` has via `ctx.seed`,
|
|
1575
|
+
* which callers fall back to their own default for (as `perceiveScene` does).
|
|
1576
|
+
*/
|
|
1577
|
+
declare function segmentRenderSeed(seq: IdleSequence, index: number): number | undefined;
|
|
1578
|
+
/**
|
|
1579
|
+
* The seed the bed's entities actually render with — its own seed, else
|
|
1580
|
+
* `seq.seed + LIMITS.maxSegments` (past every segment's `seq.seed + index`,
|
|
1581
|
+
* so a bed and segment 0 never share a stream), normalized like
|
|
1582
|
+
* `SpecInstance`. `undefined` when there's no bed or no derivable seed.
|
|
1583
|
+
*/
|
|
1584
|
+
declare function bedRenderSeed(seq: IdleSequence): number | undefined;
|
|
1336
1585
|
|
|
1337
1586
|
/**
|
|
1338
1587
|
* Reproduces the hand-coded Fish Aquarium saver as pure DATA — the discriminating test
|
|
@@ -1372,6 +1621,23 @@ declare const SNOWFALL_SPEC: SaverSpec;
|
|
|
1372
1621
|
*/
|
|
1373
1622
|
declare const LANTERNS_SPEC: SaverSpec;
|
|
1374
1623
|
|
|
1624
|
+
/**
|
|
1625
|
+
* Lobby Talk — one screen of a "quarter in review" that runs on a lobby wall
|
|
1626
|
+
* between meetings: a five-row adoption chart over the same slow haze and
|
|
1627
|
+
* dust the whole talk shares. The words are the point, so every text layer
|
|
1628
|
+
* declares `role: 'read'` — the opt-in that turns on `adviseSpec`'s
|
|
1629
|
+
* legibility advisories (`text-legibility` against the ground *and* the
|
|
1630
|
+
* brightest additive layer that can sit under a line, `text-safe-area` for
|
|
1631
|
+
* the bezel zone). Tuned to zero advisories: the haze is bright enough to
|
|
1632
|
+
* matter and dim enough to leave every label above 4.5:1 at its peak.
|
|
1633
|
+
*
|
|
1634
|
+
* Schema exercises: `role: 'read'` on both `textBlock` and `text`, a
|
|
1635
|
+
* `list`-laid chart in three layers (labels, `bar`s, readouts), additive
|
|
1636
|
+
* atmosphere (`lighter` soft circles with `pulse`) under readable copy.
|
|
1637
|
+
* Steer `bars.sprite.values` to change the numbers live.
|
|
1638
|
+
*/
|
|
1639
|
+
declare const LOBBY_TALK_SPEC: SaverSpec;
|
|
1640
|
+
|
|
1375
1641
|
/**
|
|
1376
1642
|
* Sakura Drift: cherry-blossom petals carried on a spring twilight breeze.
|
|
1377
1643
|
* Glow-up pass (v1-ceiling features): petals ride `wander` harmonics with shared
|
|
@@ -1467,7 +1733,7 @@ declare const FACETS_SPEC: SaverSpec;
|
|
|
1467
1733
|
* Relay Board — a six-row status chart in five layers instead of twenty-five.
|
|
1468
1734
|
* One `list` of labels, one `list` of `bar`s whose lengths are the numbers,
|
|
1469
1735
|
* one `list` of readouts, a title block, and a slow dust field behind so the
|
|
1470
|
-
* board reads as a live wall, not a document. Steer `bars.values` and the
|
|
1736
|
+
* board reads as a live wall, not a document. Steer `bars.sprite.values` and the
|
|
1471
1737
|
* bars glide to the new figures; the labels never move.
|
|
1472
1738
|
*/
|
|
1473
1739
|
declare const RELAY_BOARD_SPEC: SaverSpec;
|
|
@@ -1508,4 +1774,4 @@ declare const EXAMPLE_SPECS: SaverSpec[];
|
|
|
1508
1774
|
/** Lookup by saver id. */
|
|
1509
1775
|
declare const EXAMPLE_BY_ID: Readonly<Record<string, SaverSpec>>;
|
|
1510
1776
|
|
|
1511
|
-
export { AQUARIUM_SPEC, AURORA_SPEC, type BackgroundDrift, type BackgroundSpec, type BandSpec, COHESION_T, COMETS_SPEC, CONSTELLATION_SPEC, type CohesionRead, type CycleSpec, DASHBOARD_SPEC, type DominanceEntry, EXAMPLE_BY_ID, EXAMPLE_SPECS, type Entity, FACETS_SPEC, type GradientStop, HAIKU_SPEC, type IdleSequence, LANTERNS_SPEC, LIMITS, type LayerCohesion, type LayerMotionStats, type LayerSnapshot, type LayerSpec, type LinkEdge, type LuminanceGrid, type LuminanceGridOptions, MATRIX_RAIN_SPEC, type MotionEase, type MotionSpec, NOSTALGHIA_CANDLE_SPEC, ORRERY_SPEC, PINGS_SPEC, POLYGONS_SPEC, PROCESSION_SPEC, type PerceiveOptions, type Placed, RAIN_SPEC, RELAY_BOARD_SPEC, type ResolveOptions, type ResolvedSegment, type RevealState, SAKURA_SPEC, SCHEMA_EXAMPLES, SCHEMA_VERSION, SNOWFALL_SPEC, type SaverSpec, type SceneDescription, type SceneDiff, type ScenePerception, type SceneSnapshot, type SchemaExample, type SequenceSegment, type SequenceTransition, type SpecError, type SpecWarning, type SpriteSpec, type SteerDelta, type TextBlockLine, type TextRevealInput, type TextRevealSpec, type TextSpriteInfo, type ValidationResult, WARP_NEAR, WARP_TUNNEL_SPEC, type WanderOsc, adviseSequence, adviseSpec, alphaAt, applyDeltasToSpec, assertValidSequence, assertValidSpec, breakTextBlock, buildEntities, cohesionOf, compileSaver, compileSequence, describeScene, diffScenes, dominanceRanking, easeSmooth, emitEnvelope, emitWindow, graphemeClusters, headingAt, layerCohesion, lerpSpec, lifeAlphaAt, linkEdges, linkPairs, luminanceGrid, manifestFor, motionStats, perceiveScene, positionAt, renderBrailleMap, renderDensityMap, resolveSegment, resolveSpecPath, revealState, rotationAt, seamCauseOf, seamsWorthWarning, segmentStart, sizeAt, spriteIndexAt, spriteVariants, steerablePaths, structuralSignature, textSprites, textWidthEm, validateSequence, validateSpec };
|
|
1777
|
+
export { AQUARIUM_SPEC, AURORA_SPEC, type BackgroundDrift, type BackgroundSpec, type BandSpec, COHESION_T, COMETS_SPEC, CONSTELLATION_SPEC, type CohesionRead, type CycleSpec, DASHBOARD_SPEC, type DominanceEntry, EXAMPLE_BY_ID, EXAMPLE_SPECS, type Entity, FACETS_SPEC, type GradientStop, HAIKU_SPEC, type IdleSequence, LANTERNS_SPEC, LIMITS, LOBBY_TALK_SPEC, type LayerCohesion, type LayerMotionStats, type LayerSnapshot, type LayerSpec, type LinkEdge, type LuminanceGrid, type LuminanceGridOptions, MATRIX_RAIN_SPEC, type MotionEase, type MotionSpec, NOSTALGHIA_CANDLE_SPEC, ORRERY_SPEC, PINGS_SPEC, POLYGONS_SPEC, PROCESSION_SPEC, type PerceiveOptions, type PerceiveSequenceOptions, type Placed, RAIN_SPEC, RELAY_BOARD_SPEC, type ResolveOptions, type ResolvedSegment, type RevealState, SAKURA_SPEC, SCHEMA_EXAMPLES, SCHEMA_VERSION, SNOWFALL_SPEC, type SaverSpec, type SceneDescription, type SceneDiff, type ScenePerception, type SceneSnapshot, type SchemaExample, type SequenceFramePerception, type SequenceMountContext, type SequenceSegment, type SequenceTransition, type SpecError, type SpecWarning, type SpriteSpec, type SteerDelta, type TextBlockAnchor, type TextBlockLine, type TextMetricsClass, type TextRevealInput, type TextRevealSpec, type TextRole, type TextSpriteInfo, type ValidationResult, WARP_MAX_SCALE, WARP_NEAR, WARP_TUNNEL_SPEC, type WanderOsc, type WarningBox, adviseSequence, adviseSpec, alphaAt, applyDeltasToSpec, assertValidSequence, assertValidSpec, bedRenderSeed, breakTextBlock, buildEntities, canMorph, cohesionOf, compileSaver, compileSequence, describeScene, diffScenes, dominanceRanking, easeSmooth, emitEnvelope, emitWindow, graphemeClusters, headingAt, layerCohesion, lerpSpec, lifeAlphaAt, linkEdges, linkPairs, luminanceGrid, manifestFor, morphChainRoot, morphNothingMorphable, motionStats, normalizeSeed, perceiveScene, perceiveSequenceFrame, positionAt, renderBrailleMap, renderDensityMap, resolveSegment, resolveSpecPath, revealState, rotationAt, seamCauseOf, seamsWorthWarning, segmentRenderSeed, segmentStart, sequenceSteerablePaths, sizeAt, spriteIndexAt, spriteVariants, steerablePaths, structuralSignature, textBlockAnchorOffset, textMetricsClassFor, textSprites, textStringsDiffer, textStringsOf, textWidthEm, validateSequence, validateSpec };
|