@idle-screens/schema 0.1.0 → 1.0.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/dist/index.d.ts CHANGED
@@ -52,6 +52,41 @@ interface LayerSpec {
52
52
  wrap?: boolean;
53
53
  /** Flip the sprite horizontally to face its heading. Default false. */
54
54
  flip?: boolean;
55
+ /** Per-entity opacity range, both 0..1. Default [1,1]. */
56
+ alpha?: [number, number];
57
+ /** Compositing for this layer. 'lighter' = additive (glow stacking). Default source-over. */
58
+ blend?: 'lighter';
59
+ /**
60
+ * Fractional spawn window (0 = left/top, 1 = right/bottom). Constrains where
61
+ * entities are PLACED, not where they may travel. Default full viewport.
62
+ */
63
+ region?: {
64
+ x?: [number, number];
65
+ y?: [number, number];
66
+ };
67
+ /**
68
+ * Sinusoidal opacity breathing. SAFETY: amp is capped (LIMITS.maxPulseAmp),
69
+ * period has a floor (LIMITS.minPulsePeriod — max 2 Hz), and every entity gets
70
+ * its own seeded phase, so a layer can never strobe in unison. Effective alpha
71
+ * is clamped to 0..1.
72
+ */
73
+ pulse?: {
74
+ amp: number;
75
+ period: number;
76
+ };
77
+ /**
78
+ * Addressable name for this layer. Enables `setParam` to use `key.field` paths
79
+ * instead of `layers.N.field` indices. Also makes specs self-documenting.
80
+ */
81
+ key?: string;
82
+ /**
83
+ * Exact fractional position {x, y} for a single entity (0 = left/top, 1 = right/bottom).
84
+ * Only valid when `count` is 1. Overrides `region` scatter placement.
85
+ */
86
+ position?: {
87
+ x: number;
88
+ y: number;
89
+ };
55
90
  }
56
91
  type SpriteSpec = {
57
92
  kind: 'emoji';
@@ -61,10 +96,16 @@ type SpriteSpec = {
61
96
  strings: string[];
62
97
  color?: string;
63
98
  font?: string;
64
- } | {
99
+ align?: 'left' | 'center' | 'right';
100
+ baseline?: 'top' | 'middle' | 'bottom';
101
+ maxWidth?: number;
102
+ }
103
+ /** `soft` renders a radial falloff (glow orb) instead of a hard disc. */
104
+ | {
65
105
  kind: 'circle';
66
106
  radius: [number, number];
67
107
  color: string;
108
+ soft?: boolean;
68
109
  };
69
110
  type MotionSpec =
70
111
  /**
@@ -91,6 +132,10 @@ type MotionSpec =
91
132
  | {
92
133
  type: 'bounce';
93
134
  speed: [number, number];
135
+ }
136
+ /** Entity stays exactly where placed. No movement. Use with `position` for pinned elements. */
137
+ | {
138
+ type: 'static';
94
139
  };
95
140
  /** A validation problem, pointing at a JSON path within the spec. */
96
141
  interface SpecError {
@@ -105,8 +150,10 @@ interface ValidationResult {
105
150
  declare const LIMITS: {
106
151
  readonly maxPerLayer: 400;
107
152
  readonly maxTotal: 800;
108
- readonly maxLayers: 8;
153
+ readonly maxLayers: 36;
109
154
  readonly maxSpeed: 4000;
155
+ readonly maxPulseAmp: 0.5;
156
+ readonly minPulsePeriod: 500;
110
157
  };
111
158
 
112
159
  /**
@@ -128,8 +175,12 @@ interface Entity {
128
175
  vx: number;
129
176
  vy: number;
130
177
  bob: number;
131
- motion: 'drift' | 'rise' | 'bounce';
178
+ motion: 'drift' | 'rise' | 'bounce' | 'static';
132
179
  headingLeft: boolean;
180
+ alpha: number;
181
+ pulseAmp: number;
182
+ pulsePeriod: number;
183
+ pulsePhase: number;
133
184
  }
134
185
  interface Placed {
135
186
  x: number;
@@ -139,6 +190,8 @@ interface Placed {
139
190
  declare function spriteVariants(sprite: SpriteSpec): number;
140
191
  /** Deterministically place a layer's entities using the seeded RNG (never Math.random). */
141
192
  declare function buildEntities(layer: LayerSpec, rng: Rng, w: number, h: number): Entity[];
193
+ /** Analytic opacity of an entity at logical time `t` (ms). Pure, clamped to 0..1. */
194
+ declare function alphaAt(e: Entity, t: number): number;
142
195
  /** Analytic position of an entity at logical time `t` (ms). Pure & deterministic. */
143
196
  declare function positionAt(e: Entity, t: number, w: number, h: number): Placed;
144
197
 
@@ -159,6 +212,37 @@ declare function compileSaver(spec: unknown): SaverPlugin;
159
212
  declare const AQUARIUM_SPEC: SaverSpec;
160
213
  /** Rain: dense text streaks falling straight down over a near-black sky. */
161
214
  declare const RAIN_SPEC: SaverSpec;
215
+ /** Snowfall: three depth layers of white circles drifting down with horizontal bob. */
216
+ declare const SNOWFALL_SPEC: SaverSpec;
217
+ /**
218
+ * Night Lanterns (Yi Peng festival sky): depth from four correlated parallax cues —
219
+ * closer layers are LARGER, FASTER, SWAY WIDER, and glow WARMER/BRIGHTER. v2 of this
220
+ * composition exercises the expressive additions the first draft exposed as missing:
221
+ * soft glow orbs + additive blend (lantern light that sums where it overlaps), bounded
222
+ * alpha pulse with per-entity phases (breathing flames, strobe-proof by construction),
223
+ * and spawn regions (stars only above the horizon; dim ember shimmer kept low near
224
+ * the water line).
225
+ */
226
+ declare const LANTERNS_SPEC: SaverSpec;
227
+ /**
228
+ * Sakura Drift: cherry-blossom petals carried on a spring twilight breeze. Five
229
+ * correlated-parallax layers build the depth — the far backdrop is a barely-moving
230
+ * field of soft blossom-glow orbs (additive, breathing out of phase), then three
231
+ * petal layers grow LARGER, FASTER, BRIGHTER and FLUTTER WIDER as they approach
232
+ * (the near gust), over a blue-hour gradient with a warm rose horizon and a dark
233
+ * grass band. A final low layer of dim pink glow settles at the grass line — fallen
234
+ * petals catching the last light. Wind direction is consistent (down-left) across
235
+ * every moving layer; petals differ from snowfall by glyph, colour, palette and the
236
+ * diagonal breeze, and from lanterns by falling rather than rising.
237
+ */
238
+ declare const SAKURA_SPEC: SaverSpec;
239
+ /**
240
+ * Dev Dashboard: a dense ops-style HUD exercising static positioning, keyed layers,
241
+ * and text alignment at scale. Two ambient particle layers provide depth behind 28
242
+ * pinned text elements arranged in a three-column layout with header, metrics,
243
+ * file list, and scrolling event log.
244
+ */
245
+ declare const DASHBOARD_SPEC: SaverSpec;
162
246
  declare const EXAMPLE_SPECS: SaverSpec[];
163
247
 
164
- export { AQUARIUM_SPEC, type BackgroundSpec, type BandSpec, EXAMPLE_SPECS, type Entity, type GradientStop, LIMITS, type LayerSpec, type MotionSpec, type Placed, RAIN_SPEC, SCHEMA_VERSION, type SaverSpec, type SpecError, type SpriteSpec, type ValidationResult, assertValidSpec, buildEntities, compileSaver, manifestFor, positionAt, spriteVariants, validateSpec };
248
+ export { AQUARIUM_SPEC, type BackgroundSpec, type BandSpec, DASHBOARD_SPEC, EXAMPLE_SPECS, type Entity, type GradientStop, LANTERNS_SPEC, LIMITS, type LayerSpec, type MotionSpec, type Placed, RAIN_SPEC, SAKURA_SPEC, SCHEMA_VERSION, SNOWFALL_SPEC, type SaverSpec, type SpecError, type SpriteSpec, type ValidationResult, alphaAt, assertValidSpec, buildEntities, compileSaver, manifestFor, positionAt, spriteVariants, validateSpec };