@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 +112 -4
- package/dist/index.js +447 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/saver-spec.schema.json +66 -3
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
|
-
|
|
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 };
|