@idle-screens/schema 3.13.0 → 3.14.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 CHANGED
@@ -490,7 +490,9 @@ for `"nearest"` and `"random"`; a `"chain"` may omit both, except that
490
490
  across the room, and opts that layer into two advisories:
491
491
  `text-legibility` fires when the text colour's WCAG ratio falls below
492
492
  **4.5:1** against the background sampled at the box centre (gradient stops
493
- interpolated at rest, `band` honoured) **or** against the brightest
493
+ interpolated at rest, `band` honoured) — or, where an earlier static,
494
+ hard-edged, unblended layer covers the whole box (a backing chip), against
495
+ that layer composited over the page — **or** against the brightest
494
496
  additive layer (`blend: lighter` / `screen`) whose entities can reach the
495
497
  box and are at least a glyph tall, taken at its peak alpha (base + pulse)
496
498
  composited over that background — a glow parked under a caption is
@@ -809,7 +811,16 @@ its drift, orbit and pulse run on (from mount; a sequence segment's `localT`):
809
811
  Keys are also checked **together**: two keys that are each valid can
810
812
  combine past a floor (a `clock.rate` and a `pulse.period` share one), so
811
813
  the validator resolves the scene at every key's start, end and glide
812
- quarter-points and rejects it there.
814
+ quarter-points and rejects it there. Paint keys on different paths can
815
+ also combine into a faster flicker than any one path allows: a top
816
+ layer's `opacity` switching between its own colour and the colour
817
+ beneath, each keyed at the floor and out of step, flickers the whole
818
+ frame 5 times a second. So where any one second holds 7 or more key
819
+ boundaries on paint paths (opacity, alpha, colours, stops, gradients,
820
+ strokes), publishing resolves the frame there and refuses more than 3
821
+ flashes a second over a quarter of the screen (WCAG 2.3.1,
822
+ `timelineFlashReport`). Keep big brightness changes at least ~170 ms
823
+ apart across the whole frame, not just per path.
813
824
  - A key on a **structural** path rebuilds the scene at that key — a pop, and
814
825
  the validator warns `timeline-structural-key`. Animate paint: colours,
815
826
  `opacity`, `transform`, polygon `points` (a whole equal-length array
@@ -962,14 +973,25 @@ moves and scales its positions and sizes (sprite rotation is not modelled).
962
973
  will look wrong on the wall; one that passes may still sit a few px off.
963
974
  Two more are **opt-in** through the text sprite's `role: "read"` (see the
964
975
  `textBlock` sprite): `text-legibility` (WCAG ratio below 4.5:1 against the
965
- background at the box centre or under the brightest additive layer that can
966
- sit beneath the line) and `text-safe-area` (the box within 5 % of an edge,
976
+ background at the box centre, or the solid chip painted under the whole box,
977
+ or under the brightest additive layer that can sit beneath the line) and `text-safe-area` (the box within 5 % of an edge,
967
978
  with its box in `boxes`). Undeclared text is never measured for either.
968
979
  `overlap-seams` catches the trap the other channels are blind to: a layer
969
980
  whose entities bury each other (so it was drawn as one shape) but whose paint
970
981
  settings make every overlap visible. It is gated to stay off deliberate
971
982
  washes — it needs at least 6 entities and a mean base alpha of 0.45, and
972
- never fires under `blend: lighter` / `screen`. No shipped example trips it.
983
+ never fires under `blend: lighter` / `screen`. Nor does it fire when the
984
+ only seam is a multi-colour palette and the shapes bury their neighbours'
985
+ outlines but under 15 % of their area — rows or tiles butted edge to edge
986
+ (overlapping by a hairline to hide the gap) are banding, not a pile. No
987
+ shipped example trips it.
988
+ `motion-intensity-mismatch` fires when a scene declares
989
+ `motionIntensity: "calm"` but a layer of shapes, glyphs or text spins
990
+ faster than 90°/s on average (shipped calm spins stay at or under 32°/s).
991
+ `flash-near-limit` fires when a timeline's luminance keys, resolved over
992
+ their densest one-second window, flicker at least 2 times a second over a
993
+ quarter of the frame — a full-frame step at the 200 ms key floor is 2.5, which
994
+ the publish-time WCAG gate (more than 3) lets through.
973
995
  The two density advisories read the spec's declared `density` first:
974
996
  `sparse-scene` is withheld under `density: "sparse"` and `dense-scene`
975
997
  under `"dense"`, and `density-mismatch` fires instead when the measured
package/dist/index.d.ts CHANGED
@@ -1444,6 +1444,16 @@ interface SteerDelta {
1444
1444
  }
1445
1445
  /** Apply deltas to a deep copy of the spec (last-wins, target values). */
1446
1446
  declare function applyDeltasToSpec(spec: SaverSpec, deltas: SteerDelta[]): SaverSpec;
1447
+ /**
1448
+ * `applyDeltasToSpec` for read-only callers: the same result, but every
1449
+ * subtree a delta does not touch is shared with `spec` — only the containers
1450
+ * on each delta's path are copied. The validator checks a timeline by applying
1451
+ * each key, and the composed keys at every sample time, to the whole spec; a
1452
+ * full deep copy per check was most of the cost of validating a long timeline
1453
+ * (a 132 KB scene spent ~60% of its CPU in JSON round-trips). The result
1454
+ * aliases `spec`, so it must never be mutated.
1455
+ */
1456
+ declare function applyDeltasShared(spec: SaverSpec, deltas: SteerDelta[]): SaverSpec;
1447
1457
  /**
1448
1458
  * Interpolate between two structurally-similar specs at progress k (0..1).
1449
1459
  * Numbers lerp, hex colours lerp per channel, everything else steps to the
@@ -1616,12 +1626,25 @@ declare function cohesionOf(layers: Array<{
1616
1626
  layer: LayerSpec;
1617
1627
  entities: Entity[];
1618
1628
  }>, t: number, w: number, h: number): LayerCohesion[];
1629
+ /**
1630
+ * Mean fraction of an entity's filled AREA covered by a same-layer sibling,
1631
+ * 0..1 — the counterpart of `overlap`, which measures outline. Edge contact
1632
+ * buries outline and no area; a real pile buries both. `null` where
1633
+ * `cohesionOf` reports no overlap.
1634
+ */
1635
+ declare function buriedAreaOf(layer: LayerSpec, entities: Entity[], t: number, w: number, h: number): number | null;
1619
1636
  /**
1620
1637
  * True when a `seamed` layer is worth warning about: dense enough to be
1621
1638
  * deliberate, and opaque enough that it cannot be an atmospheric wash. Keeps
1622
1639
  * the advisory off the soft low-alpha glow fields the playbook recommends.
1640
+ *
1641
+ * `buriedArea` (lazy, from {@link buriedAreaOf}) lets it also stay off a
1642
+ * TILING whose only seam is its palette: opaque hard tiles of unlike colour
1643
+ * that butt edge to edge show one clean colour boundary per join, which is
1644
+ * the banding the author drew (X574). A translucent tiling is still warned
1645
+ * about — each hairline overlap paints a darker line.
1623
1646
  */
1624
- declare function seamsWorthWarning(layer: LayerSpec, c: LayerCohesion, entityCount: number): boolean;
1647
+ declare function seamsWorthWarning(layer: LayerSpec, c: LayerCohesion, entityCount: number, buriedArea?: () => number | null): boolean;
1625
1648
 
1626
1649
  interface LayerSnapshot {
1627
1650
  key: string | undefined;
@@ -2027,6 +2050,20 @@ interface PerceiveSequenceOptions extends Omit<LuminanceGridOptions, 't'> {
2027
2050
  */
2028
2051
  declare function perceiveSequenceFrame(seq: IdleSequence, T: number, opts?: PerceiveSequenceOptions): SequenceFramePerception;
2029
2052
 
2053
+ interface TimelineFlashReport {
2054
+ /** More than 3 flashes in some one-second window over at least a quarter of the frame (WCAG 2.3.1). */
2055
+ fails: boolean;
2056
+ /** Worst flashes per second any part of the frame reaches (0 when nothing was dense enough to check). */
2057
+ flashesPerSecond: number;
2058
+ /** Fraction of the frame flashing more than 3 times a second. */
2059
+ flashingArea: number;
2060
+ /** Start (scene ms, within the lap) of the worst window checked, or null when none was checked. */
2061
+ at: number | null;
2062
+ /** Set (with `fails`) when dense sections remained beyond the {@link MAX_TOTAL_SAMPLES} budget: unchecked is never reported as safe. */
2063
+ incomplete?: true;
2064
+ }
2065
+ declare function timelineFlashReport(spec: SaverSpec): TimelineFlashReport;
2066
+
2030
2067
  /**
2031
2068
  * The `field` background sampler — seeded, dependency-free value noise that
2032
2069
  * is a PURE function of `(u, v, t, config, seed)`.
@@ -2352,8 +2389,9 @@ declare function timelineLocalTime(tl: Timeline, t: number): number;
2352
2389
  * The scene at time `t` with every key applied — and without its `timeline`,
2353
2390
  * so the result can be rendered, perceived, lerped or steered like any plain
2354
2391
  * spec. A spec without a timeline comes back as the same object.
2392
+ * `shared` (read-only callers): untouched subtrees alias `spec` — never mutate the result.
2355
2393
  */
2356
- declare function resolveTimelineAt(spec: SaverSpec, t: number): SaverSpec;
2394
+ declare function resolveTimelineAt(spec: SaverSpec, t: number, shared?: boolean): SaverSpec;
2357
2395
  /**
2358
2396
  * When the timeline next takes a path back: the scene time of that path's
2359
2397
  * next key after `t`, and that key's glide length — or null when no key will
@@ -2838,4 +2876,5 @@ declare function pathFrame(s: PolygonSprite, r: number, w: number, h: number): {
2838
2876
  uniform: boolean;
2839
2877
  };
2840
2878
 
2841
- export { AQUARIUM_SPEC, AURORA_SPEC, type BackgroundDrift, type BackgroundSpec, type BandSpec, COHESION_T, COMETS_SPEC, CONSTELLATION_SPEC, type CapabilityTier, type CohesionRead, type CycleSpec, DASHBOARD_SPEC, DEFAULT_KEY_DUR, DITHER_ALPHA, DITHER_TILE, type DominanceEntry, EXAMPLE_BY_ID, EXAMPLE_SEQUENCES, EXAMPLE_SPECS, type Entity, FACETS_SPEC, FIELD_BUCKET_MS, FIELD_DRIFT_DEFAULT_AMOUNT, FIELD_RASTER_SHORT_SIDE, FIELD_RASTER_SHORT_SIDE_LOW, FINISH_ANIMATE_HZ, type FieldBackground, type FieldDrift, type FinishPass, type FinishSpec, type FlattenedPath, GRAIN_ALPHA, GRAIN_TILE, type GradientStop, HAIKU_SPEC, type IdleSequence, LANTERNS_SPEC, LIMITS, LOBBY_TALK_SPEC, type LayerCohesion, type LayerGroup, type LayerMotionStats, type LayerSnapshot, type LayerSpec, type LayerTransform, type LinkEdge, type LuminanceGrid, type LuminanceGridOptions, MATRIX_RAIN_SPEC, MAX_PATH_POINTS, MURMUR_SPEC, type MotionEase, type MotionSpec, NOSTALGHIA_CANDLE_SPEC, ORRERY_SPEC, PHASE_DUET_SPEC, PINGS_SPEC, POLYGONS_SPEC, PROCESSION_SPEC, type PathGradient, type PathGradientStop, type PathPart, type PathStroke, type PerceiveOptions, type PerceiveSequenceOptions, type Placed, RAIN_SPEC, RELAY_BOARD_SPEC, type ResolveOptions, type ResolvedPart, type ResolvedSegment, type RevealState, SAKURA_SPEC, SCHEMA_EXAMPLES, SCHEMA_VERSION, SHARD_FALL_SPEC, SIGNAL_BOARD_SPEC, SNOWFALL_SPEC, SPARSE_NIGHT_SPEC, type SaverSpec, type SceneColour, type SceneDescription, type SceneDiff, type ScenePerception, type SceneSnapshot, type SchemaExample, type ScreenOp, type SequenceExample, type SequenceFramePerception, type SequenceMountContext, type SequenceSaverInstance, type SequenceSaverPlugin, type SequenceSegment, type SequenceTransition, type SpecError, type SpecMountContext, type SpecWarning, type SpriteSpec, type SteerDelta, THERMAL_FIELD_SPEC, THREE_MOVEMENTS_SEQUENCE, TYPED_CUE_SPEC, type TextBlockAnchor, type TextBlockLine, type TextMetricsClass, type TextRevealInput, type TextRevealSpec, type TextRole, type TextSpriteInfo, type Timeline, type TimelineKey, type ValidationResult, WARP_MAX_SCALE, WARP_NEAR, WARP_TUNNEL_SPEC, WEB_WORK_SPEC, type WanderOsc, type WarningBox, adviseSequence, adviseSpec, alphaAt, applyDeltasToSpec, assertValidSequence, assertValidSpec, bayerMatrix, bayerTilePixels, bedRenderSeed, breakTextBlock, buildEntities, canMorph, canWrapMorph, canonicalSpecPath, cohesionOf, compileSaver, compileSequence, createFinishPass, createSceneCanvas, describeScene, diffScenes, dominanceRanking, easeSmooth, emitEnvelope, emitWindow, entityScales, fieldAt, fieldOctaves, fieldRgb, fieldRgbAt, fieldSampleTime, finishStrength, flattenPath, grainOffset, grainTilePixels, graphemeClusters, hasHotSwapSequence, headingAt, hexToRgb255, ignoredPropertyPaths, isPathPolygon, latticeHash, layerCohesion, lerpPathD, lerpSpec, lerpValue, lifeAlphaAt, linkEdges, linkMaxDistPx, linkPairs, luminanceGrid, manifestFor, morphChainRoot, morphNothingMorphable, motionStats, nextKeyAfter, normalizeSeed, pathFrame, pathParts, perceiveScene, perceiveSequenceFrame, pickScreenOp, positionAt, presentWithFinish, readSpecPath, renderBrailleMap, renderDensityMap, resolveSegment, resolveSpecPath, resolveTimelineAt, revealState, rgb255Luma, rotationAt, sceneColour, seamCauseOf, seamsWorthWarning, segmentRenderSeed, segmentStart, sequenceSteerablePaths, sequenceSwapCompatible, sequenceWantsFinish, sizeAt, spriteIndexAt, spriteVariants, steerablePaths, structuralSignature, textBlockAnchorOffset, textMetricsClassFor, textSprites, textStringsDiffer, textStringsOf, textWidthEm, timelineLocalTime, timelineSampleTimes, timelineSampleTimesAfter, timelineTracks, validateSequence, validateSpec, validateSpecPaths, withoutTimeline };
2879
+ export { AQUARIUM_SPEC, AURORA_SPEC, COHESION_T, COMETS_SPEC, CONSTELLATION_SPEC, DASHBOARD_SPEC, DEFAULT_KEY_DUR, DITHER_ALPHA, DITHER_TILE, EXAMPLE_BY_ID, EXAMPLE_SEQUENCES, EXAMPLE_SPECS, FACETS_SPEC, FIELD_BUCKET_MS, FIELD_DRIFT_DEFAULT_AMOUNT, FIELD_RASTER_SHORT_SIDE, FIELD_RASTER_SHORT_SIDE_LOW, FINISH_ANIMATE_HZ, GRAIN_ALPHA, GRAIN_TILE, HAIKU_SPEC, LANTERNS_SPEC, LIMITS, LOBBY_TALK_SPEC, MATRIX_RAIN_SPEC, MAX_PATH_POINTS, MURMUR_SPEC, NOSTALGHIA_CANDLE_SPEC, ORRERY_SPEC, PHASE_DUET_SPEC, PINGS_SPEC, POLYGONS_SPEC, PROCESSION_SPEC, RAIN_SPEC, RELAY_BOARD_SPEC, SAKURA_SPEC, SCHEMA_EXAMPLES, SCHEMA_VERSION, SHARD_FALL_SPEC, SIGNAL_BOARD_SPEC, SNOWFALL_SPEC, SPARSE_NIGHT_SPEC, THERMAL_FIELD_SPEC, THREE_MOVEMENTS_SEQUENCE, TYPED_CUE_SPEC, WARP_MAX_SCALE, WARP_NEAR, WARP_TUNNEL_SPEC, WEB_WORK_SPEC, adviseSequence, adviseSpec, alphaAt, applyDeltasShared, applyDeltasToSpec, assertValidSequence, assertValidSpec, bayerMatrix, bayerTilePixels, bedRenderSeed, breakTextBlock, buildEntities, buriedAreaOf, canMorph, canWrapMorph, canonicalSpecPath, cohesionOf, compileSaver, compileSequence, createFinishPass, createSceneCanvas, describeScene, diffScenes, dominanceRanking, easeSmooth, emitEnvelope, emitWindow, entityScales, fieldAt, fieldOctaves, fieldRgb, fieldRgbAt, fieldSampleTime, finishStrength, flattenPath, grainOffset, grainTilePixels, graphemeClusters, hasHotSwapSequence, headingAt, hexToRgb255, ignoredPropertyPaths, isPathPolygon, latticeHash, layerCohesion, lerpPathD, lerpSpec, lerpValue, lifeAlphaAt, linkEdges, linkMaxDistPx, linkPairs, luminanceGrid, manifestFor, morphChainRoot, morphNothingMorphable, motionStats, nextKeyAfter, normalizeSeed, pathFrame, pathParts, perceiveScene, perceiveSequenceFrame, pickScreenOp, positionAt, presentWithFinish, readSpecPath, renderBrailleMap, renderDensityMap, resolveSegment, resolveSpecPath, resolveTimelineAt, revealState, rgb255Luma, rotationAt, sceneColour, seamCauseOf, seamsWorthWarning, segmentRenderSeed, segmentStart, sequenceSteerablePaths, sequenceSwapCompatible, sequenceWantsFinish, sizeAt, spriteIndexAt, spriteVariants, steerablePaths, structuralSignature, textBlockAnchorOffset, textMetricsClassFor, textSprites, textStringsDiffer, textStringsOf, textWidthEm, timelineFlashReport, timelineLocalTime, timelineSampleTimes, timelineSampleTimesAfter, timelineTracks, validateSequence, validateSpec, validateSpecPaths, withoutTimeline };
2880
+ export type { BackgroundDrift, BackgroundSpec, BandSpec, CapabilityTier, CohesionRead, CycleSpec, DominanceEntry, Entity, FieldBackground, FieldDrift, FinishPass, FinishSpec, FlattenedPath, GradientStop, IdleSequence, LayerCohesion, LayerGroup, LayerMotionStats, LayerSnapshot, LayerSpec, LayerTransform, LinkEdge, LuminanceGrid, LuminanceGridOptions, MotionEase, MotionSpec, PathGradient, PathGradientStop, PathPart, PathStroke, PerceiveOptions, PerceiveSequenceOptions, Placed, ResolveOptions, ResolvedPart, ResolvedSegment, RevealState, SaverSpec, SceneColour, SceneDescription, SceneDiff, ScenePerception, SceneSnapshot, SchemaExample, ScreenOp, SequenceExample, SequenceFramePerception, SequenceMountContext, SequenceSaverInstance, SequenceSaverPlugin, SequenceSegment, SequenceTransition, SpecError, SpecMountContext, SpecWarning, SpriteSpec, SteerDelta, TextBlockAnchor, TextBlockLine, TextMetricsClass, TextRevealInput, TextRevealSpec, TextRole, TextSpriteInfo, Timeline, TimelineFlashReport, TimelineKey, ValidationResult, WanderOsc, WarningBox };