@idle-screens/schema 2.0.0 → 2.1.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
@@ -22,6 +22,8 @@ interface SaverSpec {
22
22
  background?: BackgroundSpec;
23
23
  layers: LayerSpec[];
24
24
  motionIntensity?: 'calm' | 'moderate' | 'energetic';
25
+ /** Dimensional unit system. 'viewport' = all sizes/speeds/distances are fractions of min(w,h). */
26
+ units?: 'px' | 'viewport';
25
27
  }
26
28
  type BackgroundSpec = {
27
29
  type: 'solid';
@@ -74,6 +76,20 @@ interface LayerSpec {
74
76
  amp: number;
75
77
  period: number;
76
78
  };
79
+ /**
80
+ * Per-entity rotation speed in degrees/sec (positive = clockwise).
81
+ * Each entity gets a seeded starting angle. Composes with any motion type.
82
+ */
83
+ spin?: number;
84
+ /**
85
+ * Sinusoidal size breathing, parallel to `pulse` for opacity. `amp` is a
86
+ * fraction of base size (0.3 = ±30 %). `period` in ms with the same
87
+ * flash-safety floor as pulse. Per-entity seeded phase.
88
+ */
89
+ grow?: {
90
+ amp: number;
91
+ period: number;
92
+ };
77
93
  /**
78
94
  * Addressable name for this layer. Enables `setParam` to use `key.field` paths
79
95
  * instead of `layers.N.field` indices. Also makes specs self-documenting.
@@ -87,10 +103,22 @@ interface LayerSpec {
87
103
  x: number;
88
104
  y: number;
89
105
  };
106
+ /**
107
+ * Inter-entity links: draw lines to each entity's k nearest neighbors within maxDist.
108
+ * Capped at LIMITS.maxLinksK. Layer count must be <= LIMITS.maxLinkLayerCount when set.
109
+ */
110
+ links?: {
111
+ k: number;
112
+ maxDist: number;
113
+ color?: string;
114
+ alpha?: number;
115
+ width?: number;
116
+ };
90
117
  }
91
118
  type SpriteSpec = {
92
119
  kind: 'emoji';
93
120
  glyphs: string[];
121
+ cycle?: CycleSpec;
94
122
  } | {
95
123
  kind: 'text';
96
124
  strings: string[];
@@ -99,6 +127,7 @@ type SpriteSpec = {
99
127
  align?: 'left' | 'center' | 'right';
100
128
  baseline?: 'top' | 'middle' | 'bottom';
101
129
  maxWidth?: number;
130
+ cycle?: CycleSpec;
102
131
  }
103
132
  /** `soft` renders a radial falloff (glow orb) instead of a hard disc. */
104
133
  | {
@@ -106,7 +135,12 @@ type SpriteSpec = {
106
135
  radius: [number, number];
107
136
  color: string;
108
137
  soft?: boolean;
138
+ colors?: string[];
109
139
  };
140
+ /** Rotate through sprite variants over time. Each entity offsets by its seeded phase. */
141
+ interface CycleSpec {
142
+ period: number;
143
+ }
110
144
  type MotionSpec =
111
145
  /**
112
146
  * Drift at a per-entity speed picked from `speed` (px/sec) along `angle` degrees
@@ -136,6 +170,20 @@ type MotionSpec =
136
170
  /** Entity stays exactly where placed. No movement. Use with `position` for pinned elements. */
137
171
  | {
138
172
  type: 'static';
173
+ }
174
+ /**
175
+ * Orbit around a center point. Each entity gets a seeded radius from `radius`
176
+ * and a seeded phase. `speed` is angular velocity in degrees/sec. `center` is
177
+ * fractional {x, y} (default {0.5, 0.5} = viewport center).
178
+ */
179
+ | {
180
+ type: 'orbit';
181
+ speed: [number, number];
182
+ radius: [number, number];
183
+ center?: {
184
+ x: number;
185
+ y: number;
186
+ };
139
187
  };
140
188
  /** A validation problem, pointing at a JSON path within the spec. */
141
189
  interface SpecError {
@@ -146,6 +194,12 @@ interface ValidationResult {
146
194
  valid: boolean;
147
195
  errors: SpecError[];
148
196
  }
197
+ /** An advisory warning (non-blocking). Returned by `adviseSpec`. */
198
+ interface SpecWarning {
199
+ path: string;
200
+ code: string;
201
+ message: string;
202
+ }
149
203
  /** Perf/safety caps enforced by `validateSpec`. */
150
204
  declare const LIMITS: {
151
205
  readonly maxPerLayer: 400;
@@ -154,6 +208,13 @@ declare const LIMITS: {
154
208
  readonly maxSpeed: 4000;
155
209
  readonly maxPulseAmp: 0.5;
156
210
  readonly minPulsePeriod: 500;
211
+ readonly maxSpin: 360;
212
+ readonly maxGrowAmp: 0.8;
213
+ readonly maxOrbitSpeed: 180;
214
+ readonly maxLinksK: 8;
215
+ readonly maxLinkLayerCount: 200;
216
+ readonly minCyclePeriod: 500;
217
+ readonly referenceViewport: 1080;
157
218
  };
158
219
 
159
220
  /**
@@ -175,12 +236,22 @@ interface Entity {
175
236
  vx: number;
176
237
  vy: number;
177
238
  bob: number;
178
- motion: 'drift' | 'rise' | 'bounce' | 'static';
239
+ motion: 'drift' | 'rise' | 'bounce' | 'static' | 'orbit';
179
240
  headingLeft: boolean;
180
241
  alpha: number;
181
242
  pulseAmp: number;
182
243
  pulsePeriod: number;
183
244
  pulsePhase: number;
245
+ spinSpeed: number;
246
+ spinPhase: number;
247
+ growAmp: number;
248
+ growPeriod: number;
249
+ growPhase: number;
250
+ orbitR: number;
251
+ orbitCx: number;
252
+ orbitCy: number;
253
+ colorIndex: number;
254
+ cyclePeriod: number;
184
255
  }
185
256
  interface Placed {
186
257
  x: number;
@@ -188,12 +259,25 @@ interface Placed {
188
259
  flip: boolean;
189
260
  }
190
261
  declare function spriteVariants(sprite: SpriteSpec): number;
191
- /** Deterministically place a layer's entities using the seeded RNG (never Math.random). */
192
- declare function buildEntities(layer: LayerSpec, rng: Rng, w: number, h: number): Entity[];
262
+ /** Deterministically place a layer's entities using the seeded RNG (never Math.random).
263
+ * `scale` multiplies every dimensional draw (default 1). Used for viewport units. */
264
+ declare function buildEntities(layer: LayerSpec, rng: Rng, w: number, h: number, scale?: number): Entity[];
193
265
  /** Analytic opacity of an entity at logical time `t` (ms). Pure, clamped to 0..1. */
194
266
  declare function alphaAt(e: Entity, t: number): number;
267
+ /** Analytic size multiplier at time `t` (ms). Pure, clamped to > 0. */
268
+ declare function sizeAt(e: Entity, t: number): number;
269
+ /** Analytic rotation angle at time `t` (ms) in radians. Pure. */
270
+ declare function rotationAt(e: Entity, t: number): number;
195
271
  /** Analytic position of an entity at logical time `t` (ms). Pure & deterministic. */
196
272
  declare function positionAt(e: Entity, t: number, w: number, h: number): Placed;
273
+ /** Time-varying sprite index for text/emoji cycling. Returns static index when cyclePeriod is 0. */
274
+ declare function spriteIndexAt(e: Entity, t: number, variants: number): number;
275
+ /** K-nearest-neighbor edge list. Deterministic tie-break: (dist, index).
276
+ * When `doWrap` is true, uses toroidal distance so links don't streak across wrap seams. */
277
+ declare function linkPairs(positions: Array<{
278
+ x: number;
279
+ y: number;
280
+ }>, k: number, maxDist: number, doWrap: boolean, w: number, h: number): Array<[number, number]>;
197
281
 
198
282
  /** Derive a manifest so a compiled spec composes with @idle-screens/capabilities. */
199
283
  declare function manifestFor(spec: SaverSpec): SaverManifest;
@@ -242,6 +326,15 @@ declare function easeSmooth(k: number): number;
242
326
  */
243
327
  declare function structuralSignature(spec: SaverSpec): string;
244
328
 
329
+ /**
330
+ * Non-blocking advisory warnings for a valid spec. Does NOT replace validateSpec —
331
+ * call advise only on specs that have already passed validation.
332
+ */
333
+ declare function adviseSpec(spec: SaverSpec, viewport?: {
334
+ width: number;
335
+ height: number;
336
+ }): SpecWarning[];
337
+
245
338
  /**
246
339
  * Reproduces the hand-coded Fish Aquarium saver as pure DATA — the discriminating test
247
340
  * that the schema is actually expressive: two layers (fish drifting both ways at varied
@@ -249,6 +342,13 @@ declare function structuralSignature(spec: SaverSpec): string;
249
342
  */
250
343
  declare const AQUARIUM_SPEC: SaverSpec;
251
344
 
345
+ /**
346
+ * Constellation: drifting stars connected by faint k-nearest links. Exercises
347
+ * colors[] (multi-hued stars), links (k-nearest neighbor lines), and cycle
348
+ * (emoji asterisms rotate glyphs). Stars are soft circles in pixel units.
349
+ */
350
+ declare const CONSTELLATION_SPEC: SaverSpec;
351
+
252
352
  /** Rain: dense text streaks falling straight down over a near-black sky. */
253
353
  declare const RAIN_SPEC: SaverSpec;
254
354
 
@@ -287,6 +387,14 @@ declare const SAKURA_SPEC: SaverSpec;
287
387
  */
288
388
  declare const DASHBOARD_SPEC: SaverSpec;
289
389
 
390
+ /**
391
+ * Orrery: a mechanical solar system. Exercises orbit motion (concentric rings
392
+ * at different speeds), spin (planets rotate on their axes), and grow (the sun
393
+ * pulses). Soft glow circles with additive blending create the corona and
394
+ * planetary halos.
395
+ */
396
+ declare const ORRERY_SPEC: SaverSpec;
397
+
290
398
  /** Catalog entry for a bundled schema example. */
291
399
  interface SchemaExample {
292
400
  id: string;
@@ -300,4 +408,4 @@ declare const EXAMPLE_SPECS: SaverSpec[];
300
408
  /** Lookup by saver id. */
301
409
  declare const EXAMPLE_BY_ID: Readonly<Record<string, SaverSpec>>;
302
410
 
303
- export { AQUARIUM_SPEC, type BackgroundSpec, type BandSpec, DASHBOARD_SPEC, EXAMPLE_BY_ID, EXAMPLE_SPECS, type Entity, type GradientStop, LANTERNS_SPEC, LIMITS, type LayerSpec, type MotionSpec, type Placed, RAIN_SPEC, SAKURA_SPEC, SCHEMA_EXAMPLES, SCHEMA_VERSION, SNOWFALL_SPEC, type SaverSpec, type SchemaExample, type SpecError, type SpriteSpec, type SteerDelta, type ValidationResult, alphaAt, applyDeltasToSpec, assertValidSpec, buildEntities, compileSaver, easeSmooth, lerpSpec, manifestFor, positionAt, resolveSpecPath, spriteVariants, structuralSignature, validateSpec };
411
+ export { AQUARIUM_SPEC, type BackgroundSpec, type BandSpec, CONSTELLATION_SPEC, type CycleSpec, DASHBOARD_SPEC, EXAMPLE_BY_ID, EXAMPLE_SPECS, type Entity, type GradientStop, LANTERNS_SPEC, LIMITS, type LayerSpec, type MotionSpec, ORRERY_SPEC, type Placed, RAIN_SPEC, SAKURA_SPEC, SCHEMA_EXAMPLES, SCHEMA_VERSION, SNOWFALL_SPEC, type SaverSpec, type SchemaExample, type SpecError, type SpecWarning, type SpriteSpec, type SteerDelta, type ValidationResult, adviseSpec, alphaAt, applyDeltasToSpec, assertValidSpec, buildEntities, compileSaver, easeSmooth, lerpSpec, linkPairs, manifestFor, positionAt, resolveSpecPath, rotationAt, sizeAt, spriteIndexAt, spriteVariants, structuralSignature, validateSpec };