@idle-screens/schema 3.5.0 → 3.6.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idle-screens/schema",
3
- "version": "3.5.0",
3
+ "version": "3.6.1",
4
4
  "description": "Declarative, agent-authorable saver format for idle-screens: validate a data spec, then compile it into a runnable, seeded, flash-safe SaverPlugin.",
5
5
  "license": "MIT",
6
6
  "author": "Shawn Partridge",
@@ -49,6 +49,57 @@
49
49
  "maxItems": 2,
50
50
  "description": "[min, max] px/sec, capped at 4000 so nothing teleports."
51
51
  },
52
+ "textReveal": {
53
+ "type": "object",
54
+ "additionalProperties": false,
55
+ "properties": {
56
+ "progress": {
57
+ "type": "number",
58
+ "minimum": 0,
59
+ "maximum": 1
60
+ },
61
+ "mode": {
62
+ "enum": [
63
+ "typewriter",
64
+ "word",
65
+ "line",
66
+ "glyphFade"
67
+ ]
68
+ },
69
+ "speed": {
70
+ "type": "number",
71
+ "minimum": 0,
72
+ "maximum": 120
73
+ },
74
+ "caret": {
75
+ "oneOf": [
76
+ {
77
+ "type": "boolean"
78
+ },
79
+ {
80
+ "type": "object",
81
+ "additionalProperties": false,
82
+ "properties": {
83
+ "blink": {
84
+ "type": "number",
85
+ "exclusiveMinimum": 0,
86
+ "maximum": 3
87
+ },
88
+ "color": {
89
+ "$ref": "#/definitions/hexColor"
90
+ }
91
+ }
92
+ }
93
+ ]
94
+ },
95
+ "fade": {
96
+ "type": "number",
97
+ "exclusiveMinimum": 0,
98
+ "maximum": 1
99
+ }
100
+ },
101
+ "description": "Animated reveal controls for a text block."
102
+ },
52
103
  "background": {
53
104
  "oneOf": [
54
105
  {
@@ -389,49 +440,131 @@
389
440
  "description": "Draw lines between entities. The layer's entity count (count field) must be <= 200 for performance."
390
441
  },
391
442
  "layout": {
392
- "type": "object",
393
- "required": [
394
- "type"
395
- ],
396
- "additionalProperties": false,
397
- "properties": {
398
- "type": {
399
- "const": "grid"
400
- },
401
- "columns": {
402
- "type": "integer",
403
- "minimum": 1,
404
- "maximum": 100,
405
- "description": "Grid columns. Default: aspect-fit square-ish grid."
406
- },
407
- "jitter": {
408
- "oneOf": [
409
- {
410
- "type": "number",
411
- "minimum": 0,
412
- "maximum": 1
443
+ "oneOf": [
444
+ {
445
+ "type": "object",
446
+ "required": [
447
+ "type"
448
+ ],
449
+ "additionalProperties": false,
450
+ "properties": {
451
+ "type": {
452
+ "const": "grid"
413
453
  },
414
- {
415
- "type": "object",
416
- "additionalProperties": false,
417
- "properties": {
418
- "x": {
454
+ "columns": {
455
+ "type": "integer",
456
+ "minimum": 1,
457
+ "maximum": 100,
458
+ "description": "Grid columns. Default: aspect-fit square-ish grid."
459
+ },
460
+ "jitter": {
461
+ "oneOf": [
462
+ {
419
463
  "type": "number",
420
464
  "minimum": 0,
421
465
  "maximum": 1
422
466
  },
423
- "y": {
424
- "type": "number",
425
- "minimum": 0,
426
- "maximum": 1
467
+ {
468
+ "type": "object",
469
+ "additionalProperties": false,
470
+ "properties": {
471
+ "x": {
472
+ "type": "number",
473
+ "minimum": 0,
474
+ "maximum": 1
475
+ },
476
+ "y": {
477
+ "type": "number",
478
+ "minimum": 0,
479
+ "maximum": 1
480
+ }
481
+ }
427
482
  }
428
- }
483
+ ],
484
+ "description": "Seeded per-entity offset as a fraction of cell size (scalar or per-axis). { y: 1 } keeps columns crisp while scattering vertically (Matrix rain). Default 0."
429
485
  }
430
- ],
431
- "description": "Seeded per-entity offset as a fraction of cell size (scalar or per-axis). { y: 1 } keeps columns crisp while scattering vertically (Matrix rain). Default 0."
486
+ },
487
+ "description": "Place entities on a grid (row-major, within region) instead of random scatter \u2014 Matrix columns, LED walls, uniform dot fields."
488
+ },
489
+ {
490
+ "type": "object",
491
+ "required": ["type"],
492
+ "additionalProperties": false,
493
+ "properties": {
494
+ "type": { "const": "list" },
495
+ "gap": { "type": "number", "exclusiveMinimum": 0, "description": "Row pitch in viewport units of min(w,h) (px in px specs). Default 0.06 / 40 px." }
496
+ },
497
+ "description": "Data layout: entities stacked in one column in reading order; strings[i], glyphs[i] and colors[i] are taken in order. position (any count) anchors the block's top-left; otherwise centred in region."
498
+ },
499
+ {
500
+ "type": "object",
501
+ "required": ["type", "columns"],
502
+ "additionalProperties": false,
503
+ "properties": {
504
+ "type": { "const": "table" },
505
+ "columns": { "type": "integer", "minimum": 1, "maximum": 100 },
506
+ "gap": {
507
+ "oneOf": [
508
+ { "type": "number", "exclusiveMinimum": 0 },
509
+ { "type": "object", "additionalProperties": false, "properties": { "x": { "type": "number", "exclusiveMinimum": 0 }, "y": { "type": "number", "exclusiveMinimum": 0 } } }
510
+ ],
511
+ "description": "Cell pitch, one number or {x, y}, in viewport units of min(w,h). Default 0.06."
512
+ }
513
+ },
514
+ "description": "Data layout: entities fill columns row-major in reading order (see list)."
515
+ }
516
+ ]
517
+ },
518
+ "emit": {
519
+ "type": "object",
520
+ "required": ["every", "life"],
521
+ "additionalProperties": false,
522
+ "properties": {
523
+ "every": {
524
+ "type": "number",
525
+ "minimum": 1000,
526
+ "maximum": 600000,
527
+ "description": "Event period in ms per entity (floor 1000: at most one event per second per entity)."
528
+ },
529
+ "life": {
530
+ "type": "number",
531
+ "minimum": 500,
532
+ "description": "Visible window per event in ms (floor 500; must be <= every). Fades in over the first quarter, out over the rest."
533
+ },
534
+ "jitter": {
535
+ "type": "number",
536
+ "minimum": 0,
537
+ "maximum": 1,
538
+ "description": "0 = entities evenly staggered across the period (one event at a time while life <= every / count); 1 (default) = scattered offsets from a fixed low-discrepancy sequence (not seeded)."
539
+ },
540
+ "grow": {
541
+ "type": "array",
542
+ "items": { "type": "number", "minimum": 0, "maximum": 8 },
543
+ "minItems": 2,
544
+ "maxItems": 2,
545
+ "description": "[from, to] size multipliers across the window \u2014 expansion rather than travel."
546
+ }
547
+ },
548
+ "description": "Sparse events: each entity appears, expands and fades in place for `life` ms every `every` ms, dark in between. The one-ping primitive; a pure function of t."
549
+ },
550
+ "clock": {
551
+ "type": "object",
552
+ "additionalProperties": false,
553
+ "properties": {
554
+ "phase": {
555
+ "type": "number",
556
+ "minimum": 0,
557
+ "maximum": 1,
558
+ "description": "Shared phase in turns (0..1). Default 0."
559
+ },
560
+ "rate": {
561
+ "type": "number",
562
+ "minimum": 0.1,
563
+ "maximum": 4,
564
+ "description": "Time multiplier for pulse/grow/cycle. Default 1. Their periods must satisfy period / rate >= 1000 ms."
432
565
  }
433
566
  },
434
- "description": "Place entities on a grid (row-major, within region) instead of random scatter \u2014 Matrix columns, LED walls, uniform dot fields."
567
+ "description": "Phase-lock: replaces the seeded per-entity phases of pulse, grow and cycle with one shared phase so layers can breathe in step."
435
568
  },
436
569
  "life": {
437
570
  "type": "object",
@@ -459,7 +592,16 @@
459
592
  "if": {
460
593
  "required": [
461
594
  "position"
462
- ]
595
+ ],
596
+ "not": {
597
+ "required": ["layout"],
598
+ "properties": {
599
+ "layout": {
600
+ "required": ["type"],
601
+ "properties": { "type": { "enum": ["list", "table"] } }
602
+ }
603
+ }
604
+ }
463
605
  },
464
606
  "then": {
465
607
  "properties": {
@@ -676,6 +818,12 @@
676
818
  "color": {
677
819
  "$ref": "#/definitions/hexColor"
678
820
  },
821
+ "feather": {
822
+ "type": "number",
823
+ "minimum": 0,
824
+ "maximum": 1,
825
+ "description": "Soft edge: the fraction of the half-size that fades out toward the border (Rothko's block at 0.5\u20130.8). Default 0 = hard."
826
+ },
679
827
  "colors": {
680
828
  "type": "array",
681
829
  "minItems": 1,
@@ -690,6 +838,70 @@
690
838
  },
691
839
  "description": "Axis-aligned rectangle (rotates with spin) \u2014 Mondrian blocks, confetti, city lights."
692
840
  },
841
+ {
842
+ "type": "object",
843
+ "required": ["kind", "values", "length", "thickness", "color"],
844
+ "additionalProperties": false,
845
+ "properties": {
846
+ "kind": { "const": "bar" },
847
+ "values": { "type": "array", "minItems": 1, "maxItems": 400, "items": { "type": "number", "minimum": 0 }, "description": "One value per entity in reading order; bar i is length x values[i] / max. Paint: steer layers.N.sprite.values and the bars glide." },
848
+ "length": { "type": "number", "exclusiveMinimum": 0, "description": "Full-scale bar length (px or viewport-units of min(w,h))." },
849
+ "thickness": { "type": "number", "exclusiveMinimum": 0, "description": "Bar thickness (px or viewport-units)." },
850
+ "color": { "$ref": "#/definitions/hexColor" },
851
+ "max": { "type": "number", "exclusiveMinimum": 0, "description": "Full-scale value. Default: the largest value." },
852
+ "direction": { "enum": ["right", "left", "up", "down"], "description": "Growth direction from the entity's position. Default right." },
853
+ "colors": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/hexColor" }, "description": "Per-entity color palette (in order under a list/table layout, seeded otherwise)." },
854
+ "colorWeights": { "$ref": "#/definitions/colorWeights" }
855
+ },
856
+ "description": "A data bar whose length is a number. Pair with a list layout for a chart that is one layer."
857
+ },
858
+ {
859
+ "type": "object",
860
+ "required": ["kind", "radius", "color"],
861
+ "additionalProperties": false,
862
+ "properties": {
863
+ "kind": { "const": "polygon" },
864
+ "radius": { "$ref": "#/definitions/positiveRange", "description": "Circumradius range (px or viewport-units)." },
865
+ "color": { "$ref": "#/definitions/hexColor" },
866
+ "sides": { "type": "integer", "minimum": 3, "maximum": 12, "description": "Regular n-gon, point up. Default 6. Not with points." },
867
+ "points": {
868
+ "type": "array",
869
+ "minItems": 3,
870
+ "maxItems": 24,
871
+ "items": { "type": "array", "minItems": 2, "maxItems": 2, "items": { "type": "number", "minimum": -1, "maximum": 1 } },
872
+ "description": "Custom vertices in unit coordinates (-1..1), scaled by the radius. Not with sides."
873
+ },
874
+ "soft": { "type": "boolean", "description": "Feather the fill from the centre, like a soft circle." },
875
+ "colors": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/hexColor" }, "description": "Per-entity color palette (seeded pick)." },
876
+ "colorWeights": { "$ref": "#/definitions/colorWeights" }
877
+ },
878
+ "not": { "required": ["sides", "points"] },
879
+ "description": "Regular or custom polygon (rotates with spin) \u2014 a facet, a triangle, a plane, a mosaic tile."
880
+ },
881
+ {
882
+ "type": "object",
883
+ "required": ["kind", "length", "points", "color"],
884
+ "additionalProperties": false,
885
+ "properties": {
886
+ "kind": { "const": "stroke" },
887
+ "length": { "$ref": "#/definitions/positiveRange", "description": "Bounding size range of the mark (px or viewport-units); the unit box is scaled to it." },
888
+ "points": {
889
+ "type": "array",
890
+ "minItems": 2,
891
+ "maxItems": 24,
892
+ "items": { "type": "array", "minItems": 2, "maxItems": 2, "items": { "type": "number", "minimum": -1, "maximum": 1 } },
893
+ "description": "Path control points in unit coordinates (-1..1)."
894
+ },
895
+ "color": { "$ref": "#/definitions/hexColor" },
896
+ "width": { "type": "number", "exclusiveMinimum": 0, "description": "Stroke width (px or viewport-units). Default 0.002 viewport-units / 2 px." },
897
+ "curve": { "enum": ["smooth", "linear"], "description": "Catmull-Rom spline through the points (default) or a polyline." },
898
+ "taper": { "type": "boolean", "description": "Thin the mark to almost nothing at both ends \u2014 a brush stroke rather than a line." },
899
+ "orient": { "type": "boolean", "description": "Turn the path's +x along the entity's heading (like streak)." },
900
+ "colors": { "type": "array", "minItems": 1, "items": { "$ref": "#/definitions/hexColor" }, "description": "Per-entity color palette (seeded pick)." },
901
+ "colorWeights": { "$ref": "#/definitions/colorWeights" }
902
+ },
903
+ "description": "A freehand mark: a path stroked with round joins, optionally tapered and heading-oriented. Rotates with spin."
904
+ },
693
905
  {
694
906
  "type": "object",
695
907
  "required": [
@@ -737,6 +949,9 @@
737
949
  },
738
950
  "color": {
739
951
  "$ref": "#/definitions/hexColor"
952
+ },
953
+ "reveal": {
954
+ "$ref": "#/definitions/textReveal"
740
955
  }
741
956
  },
742
957
  "description": "Multi-line text block with deterministic line-breaking. All dimensions are viewport fractions. Use with count: 1, static motion, and position."
@@ -795,6 +1010,16 @@
795
1010
  "type": "boolean",
796
1011
  "description": "Randomly flip horizontal direction per entity (fish)."
797
1012
  },
1013
+ "ease": {
1014
+ "type": "object",
1015
+ "required": ["type", "tau"],
1016
+ "additionalProperties": false,
1017
+ "properties": {
1018
+ "type": { "enum": ["settle", "buoyant"] },
1019
+ "tau": { "type": "number", "minimum": 100, "maximum": 120000, "description": "Time constant in ms." }
1020
+ },
1021
+ "description": "Closed-form velocity easing: settle decelerates from speed to rest (travels speed x tau); buoyant accelerates from rest to speed. With emit, restarts every event."
1022
+ },
798
1023
  "bob": {
799
1024
  "type": "number",
800
1025
  "description": "Vertical wobble amplitude in px."
@@ -815,6 +1040,16 @@
815
1040
  "speed": {
816
1041
  "$ref": "#/definitions/speedRange"
817
1042
  },
1043
+ "ease": {
1044
+ "type": "object",
1045
+ "required": ["type", "tau"],
1046
+ "additionalProperties": false,
1047
+ "properties": {
1048
+ "type": { "enum": ["settle", "buoyant"] },
1049
+ "tau": { "type": "number", "minimum": 100, "maximum": 120000, "description": "Time constant in ms." }
1050
+ },
1051
+ "description": "Closed-form velocity easing: settle decelerates from speed to rest (travels speed x tau); buoyant accelerates from rest to speed. With emit, restarts every event."
1052
+ },
818
1053
  "sway": {
819
1054
  "type": "number",
820
1055
  "description": "Horizontal sway amplitude in px (bubbles)."
@@ -866,7 +1101,7 @@
866
1101
  "type": "array",
867
1102
  "items": {
868
1103
  "type": "number",
869
- "minimum": 0,
1104
+ "minimum": -180,
870
1105
  "maximum": 180
871
1106
  },
872
1107
  "minItems": 2,
@@ -942,6 +1177,16 @@
942
1177
  "exclusiveMinimum": 0,
943
1178
  "description": "Harmonic amplitude (px or viewport-units). Default ~0.05 viewport-units. How far paths curve away from the base line."
944
1179
  },
1180
+ "ease": {
1181
+ "type": "object",
1182
+ "required": ["type", "tau"],
1183
+ "additionalProperties": false,
1184
+ "properties": {
1185
+ "type": { "enum": ["settle", "buoyant"] },
1186
+ "tau": { "type": "number", "minimum": 100, "maximum": 120000, "description": "Time constant in ms." }
1187
+ },
1188
+ "description": "Closed-form velocity easing: settle decelerates from speed to rest (travels speed x tau); buoyant accelerates from rest to speed. With emit, restarts every event."
1189
+ },
945
1190
  "coherence": {
946
1191
  "type": "number",
947
1192
  "minimum": 0,
@@ -1099,6 +1344,10 @@
1099
1344
  ],
1100
1345
  "description": "Advisory intensity for capability/reduced-motion gating."
1101
1346
  },
1347
+ "density": {
1348
+ "enum": ["sparse", "normal", "dense"],
1349
+ "description": "Declared density intent. sparse withholds the sparse-scene advisory (the emptiness is the point); dense withholds dense-scene. Checked against measured coverage (density-mismatch). A hint only — changes no pixel."
1350
+ },
1102
1351
  "units": {
1103
1352
  "enum": [
1104
1353
  "px",