@silverpoint/mcp 0.7.0 → 0.8.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.
@@ -10,11 +10,11 @@ import { LATEST_PROTOCOL_VERSION } from '@modelcontextprotocol/sdk/types.js';
10
10
  // agent-catalog.json
11
11
  var agent_catalog_default = {
12
12
  schema: 1,
13
- version: "0.7.0",
13
+ version: "0.8.0",
14
14
  reflex: {
15
15
  version: "0.7.1",
16
16
  wraps: "0.7.0",
17
- stale: false
17
+ stale: true
18
18
  },
19
19
  frameworks: [
20
20
  "react",
@@ -408,7 +408,8 @@ var agent_catalog_default = {
408
408
  hits: 11,
409
409
  baseline: 15
410
410
  }
411
- ]
411
+ ],
412
+ stale: "0.7.0"
412
413
  },
413
414
  {
414
415
  slug: "bullet-chart",
@@ -497,7 +498,8 @@ var agent_catalog_default = {
497
498
  actual: 86,
498
499
  target: 75
499
500
  }
500
- ]
501
+ ],
502
+ stale: "0.7.0"
501
503
  },
502
504
  {
503
505
  slug: "pyramid-chart",
@@ -581,7 +583,8 @@ var agent_catalog_default = {
581
583
  label: "Specialists",
582
584
  width: 70
583
585
  }
584
- ]
586
+ ],
587
+ stale: "0.7.0"
585
588
  },
586
589
  {
587
590
  slug: "heatmap-chart",
@@ -688,7 +691,8 @@ var agent_catalog_default = {
688
691
  47
689
692
  ]
690
693
  }
691
- ]
694
+ ],
695
+ stale: "0.7.0"
692
696
  },
693
697
  {
694
698
  slug: "treemap-chart",
@@ -778,7 +782,8 @@ var agent_catalog_default = {
778
782
  cols: 2,
779
783
  rows: 2
780
784
  }
781
- ]
785
+ ],
786
+ stale: "0.7.0"
782
787
  },
783
788
  {
784
789
  slug: "sankey-chart",
@@ -866,7 +871,8 @@ var agent_catalog_default = {
866
871
  target: "Visit",
867
872
  value: 15
868
873
  }
869
- ]
874
+ ],
875
+ stale: "0.7.0"
870
876
  },
871
877
  {
872
878
  slug: "activity-grid",
@@ -962,7 +968,8 @@ var agent_catalog_default = {
962
968
  count: 4,
963
969
  level: 2
964
970
  }
965
- ]
971
+ ],
972
+ stale: "0.7.0"
966
973
  },
967
974
  {
968
975
  slug: "step-chart",
@@ -1041,7 +1048,8 @@ var agent_catalog_default = {
1041
1048
  x: "Mar",
1042
1049
  value: 18
1043
1050
  }
1044
- ]
1051
+ ],
1052
+ stale: "0.7.0"
1045
1053
  },
1046
1054
  {
1047
1055
  slug: "sparkline-rows",
@@ -1176,7 +1184,8 @@ var agent_catalog_default = {
1176
1184
  84
1177
1185
  ]
1178
1186
  }
1179
- ]
1187
+ ],
1188
+ stale: "0.7.0"
1180
1189
  },
1181
1190
  {
1182
1191
  slug: "kpi-card",
@@ -1252,7 +1261,8 @@ var agent_catalog_default = {
1252
1261
  {
1253
1262
  value: 121
1254
1263
  }
1255
- ]
1264
+ ],
1265
+ stale: "0.7.0"
1256
1266
  },
1257
1267
  {
1258
1268
  slug: "bar-chart",
@@ -1351,7 +1361,8 @@ var agent_catalog_default = {
1351
1361
  value: 51,
1352
1362
  previous: 49
1353
1363
  }
1354
- ]
1364
+ ],
1365
+ stale: "0.7.0"
1355
1366
  },
1356
1367
  {
1357
1368
  slug: "stacked-bar-chart",
@@ -1439,7 +1450,8 @@ var agent_catalog_default = {
1439
1450
  pro: 26,
1440
1451
  team: 11
1441
1452
  }
1442
- ]
1453
+ ],
1454
+ stale: "0.7.0"
1443
1455
  },
1444
1456
  {
1445
1457
  slug: "composed-chart",
@@ -1540,7 +1552,8 @@ var agent_catalog_default = {
1540
1552
  revenue: 39,
1541
1553
  margin: 17
1542
1554
  }
1543
- ]
1555
+ ],
1556
+ stale: "0.7.0"
1544
1557
  },
1545
1558
  {
1546
1559
  slug: "waterfall-chart",
@@ -1625,7 +1638,8 @@ var agent_catalog_default = {
1625
1638
  step: "Services",
1626
1639
  delta: 22
1627
1640
  }
1628
- ]
1641
+ ],
1642
+ stale: "0.7.0"
1629
1643
  },
1630
1644
  {
1631
1645
  slug: "funnel-chart",
@@ -1696,7 +1710,8 @@ var agent_catalog_default = {
1696
1710
  stage: "Cart",
1697
1711
  value: 2900
1698
1712
  }
1699
- ]
1713
+ ],
1714
+ stale: "0.7.0"
1700
1715
  },
1701
1716
  {
1702
1717
  slug: "candlestick-chart",
@@ -1825,7 +1840,8 @@ var agent_catalog_default = {
1825
1840
  low: 97,
1826
1841
  close: 99
1827
1842
  }
1828
- ]
1843
+ ],
1844
+ stale: "0.7.0"
1829
1845
  },
1830
1846
  {
1831
1847
  slug: "area-chart",
@@ -1904,7 +1920,8 @@ var agent_catalog_default = {
1904
1920
  x: "Wed",
1905
1921
  value: 41
1906
1922
  }
1907
- ]
1923
+ ],
1924
+ stale: "0.7.0"
1908
1925
  },
1909
1926
  {
1910
1927
  slug: "range-band-chart",
@@ -1992,7 +2009,8 @@ var agent_catalog_default = {
1992
2009
  low: 14,
1993
2010
  high: 24
1994
2011
  }
1995
- ]
2012
+ ],
2013
+ stale: "0.7.0"
1996
2014
  },
1997
2015
  {
1998
2016
  slug: "stream-chart",
@@ -2078,7 +2096,8 @@ var agent_catalog_default = {
2078
2096
  organic: 35,
2079
2097
  paid: 16
2080
2098
  }
2081
- ]
2099
+ ],
2100
+ stale: "0.7.0"
2082
2101
  },
2083
2102
  {
2084
2103
  slug: "scatter-chart",
@@ -2171,7 +2190,8 @@ var agent_catalog_default = {
2171
2190
  y: 54,
2172
2191
  size: 3
2173
2192
  }
2174
- ]
2193
+ ],
2194
+ stale: "0.7.0"
2175
2195
  },
2176
2196
  {
2177
2197
  slug: "bubble-chart",
@@ -2264,7 +2284,8 @@ var agent_catalog_default = {
2264
2284
  y: 12,
2265
2285
  size: 65
2266
2286
  }
2267
- ]
2287
+ ],
2288
+ stale: "0.7.0"
2268
2289
  },
2269
2290
  {
2270
2291
  slug: "donut-chart",
@@ -2356,7 +2377,8 @@ var agent_catalog_default = {
2356
2377
  name: "Savings",
2357
2378
  value: 15
2358
2379
  }
2359
- ]
2380
+ ],
2381
+ stale: "0.7.0"
2360
2382
  },
2361
2383
  {
2362
2384
  slug: "radar-chart",
@@ -2433,7 +2455,8 @@ var agent_catalog_default = {
2433
2455
  subject: "Comfort",
2434
2456
  value: 7
2435
2457
  }
2436
- ]
2458
+ ],
2459
+ stale: "0.7.0"
2437
2460
  },
2438
2461
  {
2439
2462
  slug: "polar-bar-chart",
@@ -2504,7 +2527,8 @@ var agent_catalog_default = {
2504
2527
  name: "Mar",
2505
2528
  value: 41
2506
2529
  }
2507
- ]
2530
+ ],
2531
+ stale: "0.7.0"
2508
2532
  },
2509
2533
  {
2510
2534
  slug: "radial-arc-group",
@@ -2573,7 +2597,8 @@ var agent_catalog_default = {
2573
2597
  name: "Online",
2574
2598
  value: 47
2575
2599
  }
2576
- ]
2600
+ ],
2601
+ stale: "0.7.0"
2577
2602
  },
2578
2603
  {
2579
2604
  slug: "radial-rings",
@@ -2641,7 +2666,8 @@ var agent_catalog_default = {
2641
2666
  name: "Stand",
2642
2667
  value: 100
2643
2668
  }
2644
- ]
2669
+ ],
2670
+ stale: "0.7.0"
2645
2671
  },
2646
2672
  {
2647
2673
  slug: "gauge-arc",
@@ -2689,7 +2715,8 @@ var agent_catalog_default = {
2689
2715
  optional: true,
2690
2716
  doc: "Printed in place of the percent."
2691
2717
  }
2692
- ]
2718
+ ],
2719
+ stale: "0.7.0"
2693
2720
  },
2694
2721
  {
2695
2722
  slug: "meter-chart",
@@ -2737,7 +2764,8 @@ var agent_catalog_default = {
2737
2764
  optional: true,
2738
2765
  doc: "Printed in place of the percent."
2739
2766
  }
2740
- ]
2767
+ ],
2768
+ stale: "0.7.0"
2741
2769
  },
2742
2770
  {
2743
2771
  slug: "coxcomb-chart",
@@ -2816,7 +2844,8 @@ var agent_catalog_default = {
2816
2844
  name: "Wed",
2817
2845
  value: 31
2818
2846
  }
2819
- ]
2847
+ ],
2848
+ stale: "0.7.0"
2820
2849
  },
2821
2850
  {
2822
2851
  slug: "wind-rose",
@@ -2902,7 +2931,8 @@ var agent_catalog_default = {
2902
2931
  bearing: 180,
2903
2932
  speed: 9
2904
2933
  }
2905
- ]
2934
+ ],
2935
+ stale: "0.7.0"
2906
2936
  },
2907
2937
  {
2908
2938
  slug: "volvelle-chart",
@@ -2984,7 +3014,8 @@ var agent_catalog_default = {
2984
3014
  "Eridanus"
2985
3015
  ]
2986
3016
  }
2987
- ]
3017
+ ],
3018
+ stale: "0.7.0"
2988
3019
  },
2989
3020
  {
2990
3021
  slug: "chord-ring",
@@ -3080,7 +3111,8 @@ var agent_catalog_default = {
3080
3111
  target: "Shop",
3081
3112
  value: 16
3082
3113
  }
3083
- ]
3114
+ ],
3115
+ stale: "0.7.0"
3084
3116
  },
3085
3117
  {
3086
3118
  slug: "orbit-chart",
@@ -3208,7 +3240,8 @@ var agent_catalog_default = {
3208
3240
  }
3209
3241
  ]
3210
3242
  }
3211
- ]
3243
+ ],
3244
+ stale: "0.7.0"
3212
3245
  },
3213
3246
  {
3214
3247
  slug: "histogram-chart",
@@ -3291,7 +3324,8 @@ var agent_catalog_default = {
3291
3324
  device: "phone",
3292
3325
  minutes: 3
3293
3326
  }
3294
- ]
3327
+ ],
3328
+ stale: "0.7.0"
3295
3329
  },
3296
3330
  {
3297
3331
  slug: "ecdf-chart",
@@ -3375,7 +3409,8 @@ var agent_catalog_default = {
3375
3409
  device: "phone",
3376
3410
  minutes: 3
3377
3411
  }
3378
- ]
3412
+ ],
3413
+ stale: "0.7.0"
3379
3414
  },
3380
3415
  {
3381
3416
  slug: "box-plot-chart",
@@ -3471,7 +3506,8 @@ var agent_catalog_default = {
3471
3506
  service: "Search",
3472
3507
  ms: 158
3473
3508
  }
3474
- ]
3509
+ ],
3510
+ stale: "0.7.0"
3475
3511
  },
3476
3512
  {
3477
3513
  slug: "violin-chart",
@@ -3566,7 +3602,8 @@ var agent_catalog_default = {
3566
3602
  service: "Search",
3567
3603
  ms: 158
3568
3604
  }
3569
- ]
3605
+ ],
3606
+ stale: "0.7.0"
3570
3607
  },
3571
3608
  {
3572
3609
  slug: "ridgeline-chart",
@@ -3655,7 +3692,8 @@ var agent_catalog_default = {
3655
3692
  service: "Search",
3656
3693
  ms: 158
3657
3694
  }
3658
- ]
3695
+ ],
3696
+ stale: "0.7.0"
3659
3697
  },
3660
3698
  {
3661
3699
  slug: "beeswarm-chart",
@@ -3752,7 +3790,8 @@ var agent_catalog_default = {
3752
3790
  device: "phone",
3753
3791
  minutes: 3
3754
3792
  }
3755
- ]
3793
+ ],
3794
+ stale: "0.7.0"
3756
3795
  },
3757
3796
  {
3758
3797
  slug: "lollipop-chart",
@@ -3841,7 +3880,8 @@ var agent_catalog_default = {
3841
3880
  branch: "Old Mill",
3842
3881
  loans: 6096
3843
3882
  }
3844
- ]
3883
+ ],
3884
+ stale: "0.7.0"
3845
3885
  },
3846
3886
  {
3847
3887
  slug: "dumbbell-chart",
@@ -3961,7 +4001,8 @@ var agent_catalog_default = {
3961
4001
  y2024: 33,
3962
4002
  y2025: 47
3963
4003
  }
3964
- ]
4004
+ ],
4005
+ stale: "0.7.0"
3965
4006
  },
3966
4007
  {
3967
4008
  slug: "slope-chart",
@@ -4066,7 +4107,8 @@ var agent_catalog_default = {
4066
4107
  y2024: 33,
4067
4108
  y2025: 47
4068
4109
  }
4069
- ]
4110
+ ],
4111
+ stale: "0.7.0"
4070
4112
  },
4071
4113
  {
4072
4114
  slug: "bump-chart",
@@ -4174,7 +4216,8 @@ var agent_catalog_default = {
4174
4216
  team: "Lynx",
4175
4217
  points: 52
4176
4218
  }
4177
- ]
4219
+ ],
4220
+ stale: "0.7.0"
4178
4221
  },
4179
4222
  {
4180
4223
  slug: "error-bar-chart",
@@ -4300,7 +4343,8 @@ var agent_catalog_default = {
4300
4343
  low: 0.35,
4301
4344
  high: 2.79
4302
4345
  }
4303
- ]
4346
+ ],
4347
+ stale: "0.7.0"
4304
4348
  },
4305
4349
  {
4306
4350
  slug: "interval-chart",
@@ -4418,7 +4462,8 @@ var agent_catalog_default = {
4418
4462
  from: "2026-03-09",
4419
4463
  to: "2026-03-31"
4420
4464
  }
4421
- ]
4465
+ ],
4466
+ stale: "0.7.0"
4422
4467
  },
4423
4468
  {
4424
4469
  slug: "diverging-bar-chart",
@@ -4525,7 +4570,8 @@ var agent_catalog_default = {
4525
4570
  Agree: 31,
4526
4571
  "Strongly agree": 41
4527
4572
  }
4528
- ]
4573
+ ],
4574
+ stale: "0.7.0"
4529
4575
  },
4530
4576
  {
4531
4577
  slug: "connected-scatter-chart",
@@ -4625,7 +4671,8 @@ var agent_catalog_default = {
4625
4671
  fare: 1.72,
4626
4672
  riders: 42.7
4627
4673
  }
4628
- ]
4674
+ ],
4675
+ stale: "0.7.0"
4629
4676
  },
4630
4677
  {
4631
4678
  slug: "waffle-chart",
@@ -4716,7 +4763,8 @@ var agent_catalog_default = {
4716
4763
  use: "Appliances",
4717
4764
  kwh: 158
4718
4765
  }
4719
- ]
4766
+ ],
4767
+ stale: "0.7.0"
4720
4768
  },
4721
4769
  {
4722
4770
  slug: "marimekko-chart",
@@ -4809,7 +4857,8 @@ var agent_catalog_default = {
4809
4857
  channel: "Wholesale",
4810
4858
  sales: 37
4811
4859
  }
4812
- ]
4860
+ ],
4861
+ stale: "0.7.0"
4813
4862
  },
4814
4863
  {
4815
4864
  slug: "squarified-treemap",
@@ -4931,7 +4980,8 @@ var agent_catalog_default = {
4931
4980
  name: "Roads"
4932
4981
  }
4933
4982
  ],
4934
- drillable: true
4983
+ drillable: true,
4984
+ stale: "0.7.0"
4935
4985
  },
4936
4986
  {
4937
4987
  slug: "sunburst-chart",
@@ -5053,7 +5103,8 @@ var agent_catalog_default = {
5053
5103
  name: "Roads"
5054
5104
  }
5055
5105
  ],
5056
- drillable: true
5106
+ drillable: true,
5107
+ stale: "0.7.0"
5057
5108
  },
5058
5109
  {
5059
5110
  slug: "tree-chart",
@@ -5165,7 +5216,8 @@ var agent_catalog_default = {
5165
5216
  parent: "works",
5166
5217
  name: "Roads"
5167
5218
  }
5168
- ]
5219
+ ],
5220
+ stale: "0.7.0"
5169
5221
  },
5170
5222
  {
5171
5223
  slug: "parallel-coordinates-chart",
@@ -5263,7 +5315,8 @@ var agent_catalog_default = {
5263
5315
  range: 62,
5264
5316
  rating: 2.9
5265
5317
  }
5266
- ]
5318
+ ],
5319
+ stale: "0.7.0"
5267
5320
  },
5268
5321
  {
5269
5322
  slug: "polar-line-chart",
@@ -5354,7 +5407,8 @@ var agent_catalog_default = {
5354
5407
  month: 2,
5355
5408
  rain: 54
5356
5409
  }
5357
- ]
5410
+ ],
5411
+ stale: "0.7.0"
5358
5412
  },
5359
5413
  {
5360
5414
  slug: "polar-scatter-chart",
@@ -5450,7 +5504,8 @@ var agent_catalog_default = {
5450
5504
  bearing: 229.3,
5451
5505
  distance: 19.6
5452
5506
  }
5453
- ]
5507
+ ],
5508
+ stale: "0.7.0"
5454
5509
  },
5455
5510
  {
5456
5511
  slug: "density-bin-chart",
@@ -5540,7 +5595,8 @@ var agent_catalog_default = {
5540
5595
  x: 39.92,
5541
5596
  y: 61.68
5542
5597
  }
5543
- ]
5598
+ ],
5599
+ stale: "0.7.0"
5544
5600
  },
5545
5601
  {
5546
5602
  slug: "contour-chart",
@@ -5651,7 +5707,8 @@ var agent_catalog_default = {
5651
5707
  x: 39.92,
5652
5708
  y: 61.68
5653
5709
  }
5654
- ]
5710
+ ],
5711
+ stale: "0.7.0"
5655
5712
  },
5656
5713
  {
5657
5714
  slug: "delaunay-chart",
@@ -5750,7 +5807,8 @@ var agent_catalog_default = {
5750
5807
  x: 90.6,
5751
5808
  y: 39.1
5752
5809
  }
5753
- ]
5810
+ ],
5811
+ stale: "0.7.0"
5754
5812
  },
5755
5813
  {
5756
5814
  slug: "vector-field-chart",
@@ -5867,7 +5925,8 @@ var agent_catalog_default = {
5867
5925
  u: 1.097,
5868
5926
  v: -1.266
5869
5927
  }
5870
- ]
5928
+ ],
5929
+ stale: "0.7.0"
5871
5930
  },
5872
5931
  {
5873
5932
  slug: "network-chart",
@@ -5975,7 +6034,8 @@ var agent_catalog_default = {
5975
6034
  target: "p07",
5976
6035
  weight: 5
5977
6036
  }
5978
- ]
6037
+ ],
6038
+ stale: "0.7.0"
5979
6039
  }
5980
6040
  ],
5981
6041
  components: [
@@ -6070,7 +6130,8 @@ var agent_catalog_default = {
6070
6130
  ],
6071
6131
  demo: {
6072
6132
  content: "Default"
6073
- }
6133
+ },
6134
+ stale: "0.7.0"
6074
6135
  },
6075
6136
  {
6076
6137
  slug: "input",
@@ -6190,7 +6251,8 @@ var agent_catalog_default = {
6190
6251
  type: "search",
6191
6252
  name: "q",
6192
6253
  value: ""
6193
- }
6254
+ },
6255
+ stale: "0.7.0"
6194
6256
  },
6195
6257
  {
6196
6258
  slug: "checkbox",
@@ -6270,7 +6332,8 @@ var agent_catalog_default = {
6270
6332
  label: "Legend",
6271
6333
  name: "legend",
6272
6334
  value: false
6273
- }
6335
+ },
6336
+ stale: "0.7.0"
6274
6337
  },
6275
6338
  {
6276
6339
  slug: "radio-group",
@@ -6360,7 +6423,8 @@ var agent_catalog_default = {
6360
6423
  ],
6361
6424
  value: "silverpoint",
6362
6425
  orientation: "horizontal"
6363
- }
6426
+ },
6427
+ stale: "0.7.0"
6364
6428
  },
6365
6429
  {
6366
6430
  slug: "switch",
@@ -6432,7 +6496,8 @@ var agent_catalog_default = {
6432
6496
  label: "Linked hover",
6433
6497
  name: "linked",
6434
6498
  value: false
6435
- }
6499
+ },
6500
+ stale: "0.7.0"
6436
6501
  },
6437
6502
  {
6438
6503
  slug: "slider",
@@ -6541,7 +6606,8 @@ var agent_catalog_default = {
6541
6606
  75,
6542
6607
  100
6543
6608
  ]
6544
- }
6609
+ },
6610
+ stale: "0.7.0"
6545
6611
  },
6546
6612
  {
6547
6613
  slug: "rate",
@@ -6628,7 +6694,8 @@ var agent_catalog_default = {
6628
6694
  name: "quality",
6629
6695
  value: 3,
6630
6696
  count: 5
6631
- }
6697
+ },
6698
+ stale: "0.7.0"
6632
6699
  },
6633
6700
  {
6634
6701
  slug: "segmented",
@@ -6724,7 +6791,8 @@ var agent_catalog_default = {
6724
6791
  }
6725
6792
  ],
6726
6793
  value: "day"
6727
- }
6794
+ },
6795
+ stale: "0.7.0"
6728
6796
  },
6729
6797
  {
6730
6798
  slug: "tabs",
@@ -6827,7 +6895,8 @@ var agent_catalog_default = {
6827
6895
  }
6828
6896
  ],
6829
6897
  value: "overview"
6830
- }
6898
+ },
6899
+ stale: "0.7.0"
6831
6900
  },
6832
6901
  {
6833
6902
  slug: "steps",
@@ -6912,7 +6981,8 @@ var agent_catalog_default = {
6912
6981
  }
6913
6982
  ],
6914
6983
  current: 2
6915
- }
6984
+ },
6985
+ stale: "0.7.0"
6916
6986
  },
6917
6987
  {
6918
6988
  slug: "card",
@@ -6976,7 +7046,8 @@ var agent_catalog_default = {
6976
7046
  ],
6977
7047
  demo: {
6978
7048
  content: "Hits per hour rose through the afternoon and eased at night."
6979
- }
7049
+ },
7050
+ stale: "0.7.0"
6980
7051
  },
6981
7052
  {
6982
7053
  slug: "tag",
@@ -7048,7 +7119,8 @@ var agent_catalog_default = {
7048
7119
  demo: {
7049
7120
  content: "draft",
7050
7121
  tone: 1
7051
- }
7122
+ },
7123
+ stale: "0.7.0"
7052
7124
  },
7053
7125
  {
7054
7126
  slug: "badge",
@@ -7122,7 +7194,8 @@ var agent_catalog_default = {
7122
7194
  demo: {
7123
7195
  content: "Inbox",
7124
7196
  count: 12
7125
- }
7197
+ },
7198
+ stale: "0.7.0"
7126
7199
  },
7127
7200
  {
7128
7201
  slug: "divider",
@@ -7180,7 +7253,8 @@ var agent_catalog_default = {
7180
7253
  "plain",
7181
7254
  "text"
7182
7255
  ],
7183
- demo: {}
7256
+ demo: {},
7257
+ stale: "0.7.0"
7184
7258
  },
7185
7259
  {
7186
7260
  slug: "progress",
@@ -7249,7 +7323,8 @@ var agent_catalog_default = {
7249
7323
  demo: {
7250
7324
  label: "Upload",
7251
7325
  value: 40
7252
- }
7326
+ },
7327
+ stale: "0.7.0"
7253
7328
  },
7254
7329
  {
7255
7330
  slug: "alert",
@@ -7332,7 +7407,8 @@ var agent_catalog_default = {
7332
7407
  kind: "info",
7333
7408
  title: "New ground available",
7334
7409
  content: "cyanotype ships in 0.2.0."
7335
- }
7410
+ },
7411
+ stale: "0.7.0"
7336
7412
  },
7337
7413
  {
7338
7414
  slug: "skeleton",
@@ -7392,7 +7468,8 @@ var agent_catalog_default = {
7392
7468
  ],
7393
7469
  demo: {
7394
7470
  lines: 3
7395
- }
7471
+ },
7472
+ stale: "0.7.0"
7396
7473
  },
7397
7474
  {
7398
7475
  slug: "surface",
@@ -7464,7 +7541,8 @@ var agent_catalog_default = {
7464
7541
  demo: {
7465
7542
  frame: "card",
7466
7543
  content: "A surface takes the ground: its substrate, its ink and a hand-drawn frame."
7467
- }
7544
+ },
7545
+ stale: "0.7.0"
7468
7546
  },
7469
7547
  {
7470
7548
  slug: "glyph",
@@ -7507,7 +7585,8 @@ var agent_catalog_default = {
7507
7585
  ],
7508
7586
  demo: {
7509
7587
  glyph: "tick"
7510
- }
7588
+ },
7589
+ stale: "0.7.0"
7511
7590
  },
7512
7591
  {
7513
7592
  slug: "table",
@@ -7680,7 +7759,8 @@ var agent_catalog_default = {
7680
7759
  }
7681
7760
  ],
7682
7761
  rowKey: "order"
7683
- }
7762
+ },
7763
+ stale: "0.7.0"
7684
7764
  },
7685
7765
  {
7686
7766
  slug: "pagination",
@@ -7806,7 +7886,8 @@ var agent_catalog_default = {
7806
7886
  total: 200,
7807
7887
  pageSize: 10,
7808
7888
  current: 10
7809
- }
7889
+ },
7890
+ stale: "0.7.0"
7810
7891
  },
7811
7892
  {
7812
7893
  slug: "breadcrumb",
@@ -7872,7 +7953,8 @@ var agent_catalog_default = {
7872
7953
  label: "Order 1042"
7873
7954
  }
7874
7955
  ]
7875
- }
7956
+ },
7957
+ stale: "0.7.0"
7876
7958
  },
7877
7959
  {
7878
7960
  slug: "avatar",
@@ -7953,7 +8035,8 @@ var agent_catalog_default = {
7953
8035
  ],
7954
8036
  demo: {
7955
8037
  name: "Ada Lovelace"
7956
- }
8038
+ },
8039
+ stale: "0.7.0"
7957
8040
  },
7958
8041
  {
7959
8042
  slug: "statistic",
@@ -8033,7 +8116,8 @@ var agent_catalog_default = {
8033
8116
  demo: {
8034
8117
  title: "Orders",
8035
8118
  value: 1284
8036
- }
8119
+ },
8120
+ stale: "0.7.0"
8037
8121
  },
8038
8122
  {
8039
8123
  slug: "descriptions",
@@ -8131,7 +8215,8 @@ var agent_catalog_default = {
8131
8215
  }
8132
8216
  ],
8133
8217
  columns: 2
8134
- }
8218
+ },
8219
+ stale: "0.7.0"
8135
8220
  },
8136
8221
  {
8137
8222
  slug: "timeline-list",
@@ -8207,7 +8292,8 @@ var agent_catalog_default = {
8207
8292
  status: "pending"
8208
8293
  }
8209
8294
  ]
8210
- }
8295
+ },
8296
+ stale: "0.7.0"
8211
8297
  },
8212
8298
  {
8213
8299
  slug: "collapse",
@@ -8283,7 +8369,8 @@ var agent_catalog_default = {
8283
8369
  content: "From hatching, level by level, never from transparency."
8284
8370
  }
8285
8371
  ]
8286
- }
8372
+ },
8373
+ stale: "0.7.0"
8287
8374
  },
8288
8375
  {
8289
8376
  slug: "empty",
@@ -8333,7 +8420,8 @@ var agent_catalog_default = {
8333
8420
  ],
8334
8421
  demo: {
8335
8422
  description: "No orders yet"
8336
- }
8423
+ },
8424
+ stale: "0.7.0"
8337
8425
  },
8338
8426
  {
8339
8427
  slug: "result",
@@ -8408,7 +8496,8 @@ var agent_catalog_default = {
8408
8496
  status: "success",
8409
8497
  title: "Order placed",
8410
8498
  subtitle: "Order 1042 is on its way to the workshop."
8411
- }
8499
+ },
8500
+ stale: "0.7.0"
8412
8501
  },
8413
8502
  {
8414
8503
  slug: "textarea",
@@ -8532,7 +8621,8 @@ var agent_catalog_default = {
8532
8621
  value: "Leave it at the door.",
8533
8622
  maxLength: 120,
8534
8623
  showCount: true
8535
- }
8624
+ },
8625
+ stale: "0.7.0"
8536
8626
  },
8537
8627
  {
8538
8628
  slug: "input-number",
@@ -8676,7 +8766,8 @@ var agent_catalog_default = {
8676
8766
  value: 3,
8677
8767
  min: 1,
8678
8768
  max: 10
8679
- }
8769
+ },
8770
+ stale: "0.7.0"
8680
8771
  },
8681
8772
  {
8682
8773
  slug: "modal",
@@ -8790,7 +8881,8 @@ var agent_catalog_default = {
8790
8881
  title: "Edit order",
8791
8882
  description: "Order 1042, placed on 14 October.",
8792
8883
  content: "Changes reach the workshop before the order is packed."
8793
- }
8884
+ },
8885
+ stale: "0.7.0"
8794
8886
  },
8795
8887
  {
8796
8888
  slug: "drawer",
@@ -8875,7 +8967,8 @@ var agent_catalog_default = {
8875
8967
  trigger: "Filters",
8876
8968
  title: "Filters",
8877
8969
  content: "Narrow the orders by status, customer or amount."
8878
- }
8970
+ },
8971
+ stale: "0.7.0"
8879
8972
  },
8880
8973
  {
8881
8974
  slug: "popover",
@@ -8994,7 +9087,8 @@ var agent_catalog_default = {
8994
9087
  trigger: "Details",
8995
9088
  title: "Order 1042",
8996
9089
  content: "Two prints, one framed; shipped on 16 October."
8997
- }
9090
+ },
9091
+ stale: "0.7.0"
8998
9092
  },
8999
9093
  {
9000
9094
  slug: "tooltip",
@@ -9086,7 +9180,8 @@ var agent_catalog_default = {
9086
9180
  open: true,
9087
9181
  trigger: "Copy id",
9088
9182
  text: "Copy the order id"
9089
- }
9183
+ },
9184
+ stale: "0.7.0"
9090
9185
  },
9091
9186
  {
9092
9187
  slug: "select",
@@ -9214,7 +9309,8 @@ var agent_catalog_default = {
9214
9309
  }
9215
9310
  ],
9216
9311
  value: null
9217
- }
9312
+ },
9313
+ stale: "0.7.0"
9218
9314
  },
9219
9315
  {
9220
9316
  slug: "dropdown-menu",
@@ -9334,7 +9430,8 @@ var agent_catalog_default = {
9334
9430
  ],
9335
9431
  open: true,
9336
9432
  active: "edit"
9337
- }
9433
+ },
9434
+ stale: "0.7.0"
9338
9435
  },
9339
9436
  {
9340
9437
  slug: "toast",
@@ -9426,7 +9523,8 @@ var agent_catalog_default = {
9426
9523
  title: "Order saved",
9427
9524
  description: "Order 1042 was updated.",
9428
9525
  open: true
9429
- }
9526
+ },
9527
+ stale: "0.7.0"
9430
9528
  }
9431
9529
  ],
9432
9530
  dashboard: {
@@ -11412,16 +11510,16 @@ function generateCode(catalog2, input) {
11412
11510
 
11413
11511
  // src/guides.generated.ts
11414
11512
  var GUIDES = {
11415
- "choosing-charts": "<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Choosing a chart\n\n*Describes silverpoint 0.7.0.*\n\nChoose a chart in two steps. First name the shape of the rows, then name what the reader is asked to\nsee. The recommender (`recommend_chart` on the MCP server) reads the table below. It is a reviewed\ntable, not a model, and a pair that is missing from it falls back on the charts that declare both.\n\n## Data shapes\n\n| Shape | The rows hold | For example |\n|---|---|---|\n| `series` | one row per point along an ordered x (time, sequence) | hits per hour |\n| `categories` | one row per category with one or more values | revenue by region |\n| `parts` | shares of one whole | traffic by channel |\n| `matrix` | a value per pair of categories | errors by day and hour |\n| `hierarchy` | one row per node, with an `id` and its `parent` (`null` for the root) | a budget by department |\n| `links` | rows with a source, a target and a value | signup funnel steps |\n| `points` | two or more numeric measures per row | price against rating |\n| `distribution` | many raw observations of one measure | response times |\n| `intervals` | a start and an end per row | task schedule |\n| `events` | dated occurrences, or marks along a cycle | commits per day |\n| `single` | one figure, perhaps with a target | revenue this month |\n| `field` | a measure or a vector (`x`, `y`, `u`, `v`) over a plane | a wind field |\n\n## The charts by shape and intent\n\n| Chart | Family | Shape | Intents | Summary |\n|---|---|---|---|---|\n| `line-chart` | lines | `series` | trend, change, compare | Spline with an optional dotted baseline series. |\n| `bullet-chart` | bars | `categories` | progress, kpi, compare | One bar per target, with a marker at the target. Values in 0-100. |\n| `pyramid-chart` | bars | `categories` | rank, compare | Stacked tiers whose width encodes the value (0-100). |\n| `heatmap-chart` | points-grids | `matrix` | compare, distribution | Labelled rows of values, normalised against `scaleMax`. |\n| `treemap-chart` | points-grids | `parts` | part-to-whole | Tiles of `cols \xD7 rows` cells placed in a `columns \xD7 rows` grid. |\n| `sankey-chart` | flows | `links` | flow, part-to-whole | Flow bands between layered nodes. |\n| `activity-grid` | points-grids | `events` | schedule, trend | One cell per day, a column per week. |\n| `step-chart` | lines | `series` | trend, change | A series drawn as steps. |\n| `sparkline-rows` | lines | `series` | trend, compare, kpi | One row per series \u2014 name, sparkline, readout. |\n| `kpi-card` | lines | `single` | kpi, change | A metric, its delta, and an area sparkline of the series. |\n| `bar-chart` | bars | `categories` | compare, rank | Pill bars, as columns or rows, with an optional second series. |\n| `stacked-bar-chart` | bars | `categories` | compare, part-to-whole | One stacked segment per key. |\n| `composed-chart` | bars | `series` | compare, trend | Columns and a spline on one value scale. |\n| `waterfall-chart` | bars | `categories` | change, part-to-whole | Totals from zero and floating deltas from the running total. |\n| `funnel-chart` | bars | `categories` | progress, compare | Horizontal, centred stages. |\n| `candlestick-chart` | bars | `intervals` | change, trend | OHLC bodies and wicks. |\n| `area-chart` | areas | `series` | trend, change | A curved, toned area under its line. |\n| `range-band-chart` | areas | `intervals` | uncertainty, trend | The band between a low and a high series. |\n| `stream-chart` | areas | `series` | trend, part-to-whole, compare | Two waves, overlaid or stacked. |\n| `scatter-chart` | points-grids | `points` | correlation, distribution | Points on two linear scales, optionally sized. |\n| `bubble-chart` | points-grids | `points` | correlation, compare | Circles whose area encodes `sizeKey`. |\n| `donut-chart` | radial | `parts` | part-to-whole | Sectors \u221D value around a central readout. |\n| `radar-chart` | radial | `categories` | compare | One spoke per subject, a closed polygon of values. |\n| `polar-bar-chart` | radial | `categories` | compare, rank | 360\xB0 bars out from a hole, length \u221D value. |\n| `radial-arc-group` | radial | `categories` | compare, progress | Concentric 180\xB0 tracks, sweep \u221D value / the largest. |\n| `radial-rings` | radial | `categories` | progress | Concentric progress rings, sweep \u221D value in 0-100. |\n| `gauge-arc` | radial | `single` | kpi, progress | A 240\xB0 arc swept to a percent. |\n| `meter-chart` | radial | `single` | kpi, progress | A semicircular meter with a needle at a percent. |\n| `coxcomb-chart` | radial | `categories` | compare, part-to-whole | Equal angles, sector area \u221D value. |\n| `wind-rose` | radial | `distribution` | distribution | Observations of (bearing, speed) binned by compass sector and speed. |\n| `volvelle-chart` | radial | `categories` | schedule, compare | Concentric categorical rings read against one index. |\n| `chord-ring` | flows | `links` | flow, network | Directed flows between categories around a circle. |\n| `orbit-chart` | radial | `events` | schedule | Nested elliptical orbits with markers along them. |\n| `histogram-chart` | distributions-comparisons | `distribution` | distribution | Raw observations binned in the core. |\n| `ecdf-chart` | distributions-comparisons | `distribution` | distribution, compare | The empirical cumulative distribution as a step function. |\n| `box-plot-chart` | distributions-comparisons | `distribution` | distribution, compare | Quartiles, median, Tukey whiskers and outliers per group. |\n| `violin-chart` | distributions-comparisons | `distribution` | distribution, compare | A mirrored kernel density per group. |\n| `ridgeline-chart` | distributions-comparisons | `distribution` | distribution, compare, change | A kernel density per group on overlapping baselines. |\n| `beeswarm-chart` | distributions-comparisons | `distribution` | distribution | One point per observation, packed without overlap. |\n| `lollipop-chart` | distributions-comparisons | `categories` | compare, rank | A stem from the baseline and a head at the value. |\n| `dumbbell-chart` | distributions-comparisons | `categories` | change, compare | Two values per category joined by a segment. |\n| `slope-chart` | distributions-comparisons | `categories` | change, rank | Two period axes, one segment per category. |\n| `bump-chart` | distributions-comparisons | `series` | rank, change | The rank of each series at each x. |\n| `error-bar-chart` | distributions-comparisons | `intervals` | uncertainty, compare | A point estimate with its interval per category. |\n| `interval-chart` | distributions-comparisons | `intervals` | schedule | Floating bars from start to end on lanes. |\n| `diverging-bar-chart` | distributions-comparisons | `parts` | part-to-whole, compare | Ordered levels stacked on both sides of a neutral centre. |\n| `connected-scatter-chart` | distributions-comparisons | `points` | correlation, change | An ordered path through x-y points. |\n| `waffle-chart` | hierarchies-dimensions | `parts` | part-to-whole, progress | A unit grid filled in reading order by category. |\n| `marimekko-chart` | hierarchies-dimensions | `matrix` | part-to-whole, compare | Column width by total, segment height by share. |\n| `squarified-treemap` | hierarchies-dimensions | `hierarchy` | hierarchy, part-to-whole | Nested rectangles, area by value, drillable through `rootId` and `onRootChange`. |\n| `sunburst-chart` | hierarchies-dimensions | `hierarchy` | hierarchy, part-to-whole | A hierarchy as rings of arcs, drillable through `rootId` and `onRootChange`. |\n| `tree-chart` | hierarchies-dimensions | `hierarchy` | hierarchy | A tidy node-link tree. |\n| `parallel-coordinates-chart` | hierarchies-dimensions | `matrix` | correlation, compare | One polyline per row across parallel axes. |\n| `polar-line-chart` | hierarchies-dimensions | `series` | trend, compare | A line over angle and radius. |\n| `polar-scatter-chart` | hierarchies-dimensions | `points` | distribution, correlation | Points over angle and radius. |\n| `density-bin-chart` | fields-networks | `points` | distribution, correlation | X-y points counted in two-dimensional bins. |\n| `contour-chart` | fields-networks | `points` | distribution, correlation | Iso-lines and filled bands of a density or a grid. |\n| `delaunay-chart` | fields-networks | `points` | network, distribution | The triangulation of x-y points, or its Voronoi cells. |\n| `vector-field-chart` | fields-networks | `field` | flow | An arrow per grid point. |\n| `network-chart` | fields-networks | `links` | network, flow | A node-link graph. |\n\n## The recommender's table\n\nThe scores run from 0 to 1. An adjustment applies when the row count (`rows`) or the number of\nvalue columns (`values`) passes its bound.\n\n| Shape | Intent | Charts, best first | Adjustments |\n|---|---|---|---|\n| `series` | `trend` | `line-chart` 0.9 \u2014 A line is the plainest reading of a value over an ordered axis.<br>`area-chart` 0.8 \u2014 An area gives one series the weight of its magnitude.<br>`step-chart` 0.6 \u2014 Steps show a value that holds until it changes.<br>`stream-chart` 0.5 \u2014 Several value columns overlay or stack as waves.<br>`polar-line-chart` 0.3 \u2014 A cyclic axis (hours, months, degrees) closes the line around a circle. | values>1: `stream-chart` +0.3 \u2014 Several value fields read together as streams.<br>values>1: `area-chart` -0.2 \u2014 An area draws one series only. |\n| `series` | `change` | `line-chart` 0.8 \u2014 The slope between points is the change.<br>`step-chart` 0.75 \u2014 Steps mark when the value changed and by how much.<br>`area-chart` 0.6 \u2014 An area shows the change in magnitude.<br>`bump-chart` 0.5 \u2014 When the change that matters is in rank. | |\n| `series` | `compare` | `line-chart` 0.8 \u2014 A second series draws as a dotted baseline against the first.<br>`composed-chart` 0.75 \u2014 Columns and a line share one value scale.<br>`stream-chart` 0.6 \u2014 Several series overlaid on one axis.<br>`sparkline-rows` 0.55 \u2014 One small line per series, side by side with its readout.<br>`polar-line-chart` 0.3 \u2014 Values around a cycle compared by angle. | |\n| `series` | `rank` | `bump-chart` 0.9 \u2014 The rank of each series at each x, ranks joined across x. | |\n| `series` | `kpi` | `sparkline-rows` 0.85 \u2014 One row per series: its name, its trend and its latest readout.<br>`kpi-card` 0.75 \u2014 One metric, its delta and its trend. | |\n| `series` | `part-to-whole` | `stream-chart` 0.8 \u2014 Stacked waves show each part of a total over x. | |\n| `categories` | `compare` | `bar-chart` 0.9 \u2014 Bars compare values against one common baseline.<br>`lollipop-chart` 0.75 \u2014 A lighter mark per category, readable with many of them.<br>`radar-chart` 0.5 \u2014 Spokes compare a few subjects at once.<br>`polar-bar-chart` 0.4 \u2014 Bars around a circle, for a cyclic set of categories.<br>`coxcomb-chart` 0.35 \u2014 Equal angles, area by value: cyclic categories such as months.<br>`radial-arc-group` 0.3 \u2014 Concentric tracks, each swept by its value. | rows>12: `lollipop-chart` +0.2 \u2014 Many categories read better as lollipops.<br>rows>12: `radar-chart` -0.3 \u2014 Radial layouts crowd past a dozen categories.<br>rows>12: `polar-bar-chart` -0.3 \u2014 Radial layouts crowd past a dozen categories.<br>rows>12: `coxcomb-chart` -0.3 \u2014 Radial layouts crowd past a dozen categories.<br>values>1: `bar-chart` +0.05 \u2014 A second value field draws as a second series of bars. |\n| `categories` | `rank` | `bar-chart` 0.85 \u2014 Sorted bars read as a ranking.<br>`lollipop-chart` 0.85 \u2014 Lollipops sort themselves with `sort`.<br>`pyramid-chart` 0.5 \u2014 Stacked tiers, widest at the base.<br>`polar-bar-chart` 0.4 \u2014 A ranking around a circle. | |\n| `categories` | `part-to-whole` | `stacked-bar-chart` 0.85 \u2014 Each bar stacks its parts, one segment per value column.<br>`waterfall-chart` 0.6 \u2014 Parts that add up to a running total.<br>`coxcomb-chart` 0.4 \u2014 Sectors whose area is each part. | |\n| `categories` | `change` | `dumbbell-chart` 0.9 \u2014 Two values per category joined by a segment: before and after.<br>`slope-chart` 0.85 \u2014 Two period axes, one segment per category: the slope is the change.<br>`waterfall-chart` 0.75 \u2014 Each step a delta from the running total. | |\n| `categories` | `progress` | `bullet-chart` 0.9 \u2014 Each bar against its own target.<br>`radial-rings` 0.75 \u2014 Concentric rings, each swept to its percent.<br>`funnel-chart` 0.7 \u2014 Stages that narrow, such as a conversion.<br>`radial-arc-group` 0.5 \u2014 Tracks swept relative to the largest. | |\n| `categories` | `kpi` | `bullet-chart` 0.8 \u2014 Each measure against its target, compact.<br>`radial-rings` 0.6 \u2014 A few percents at a glance. | |\n| `parts` | `part-to-whole` | `donut-chart` 0.9 \u2014 A ring reads a few shares of one whole around a central figure.<br>`waffle-chart` 0.85 \u2014 Unit cells make the shares countable.<br>`treemap-chart` 0.7 \u2014 Tiles sized by share.<br>`diverging-bar-chart` 0.4 \u2014 For ordered levels (agree\u2026 disagree) around a neutral centre.<br>`stacked-bar-chart` 0.35 \u2014 One bar stacked with the shares, to set beside other wholes. | rows>6: `donut-chart` -0.3 \u2014 A ring loses its shares past six slices.<br>rows>6: `treemap-chart` +0.1 \u2014 Tiles hold many shares better than a ring. |\n| `parts` | `compare` | `diverging-bar-chart` 0.8 \u2014 Likert-style levels on both sides of a neutral centre, row by row.<br>`waffle-chart` 0.6 \u2014 Countable cells per part. | |\n| `parts` | `progress` | `waffle-chart` 0.8 \u2014 A hundred cells filled to the share done. | |\n| `matrix` | `compare` | `heatmap-chart` 0.9 \u2014 One toned cell per row and column.<br>`marimekko-chart` 0.7 \u2014 Columns by total, segments by share.<br>`parallel-coordinates-chart` 0.6 \u2014 One polyline per row across many dimensions. | |\n| `matrix` | `part-to-whole` | `marimekko-chart` 0.9 \u2014 Each column a whole, each segment its share, column width by total. | |\n| `matrix` | `correlation` | `parallel-coordinates-chart` 0.9 \u2014 Crossing lines between axes show how dimensions move together.<br>`heatmap-chart` 0.6 \u2014 A grid of values, read for patterns. | |\n| `matrix` | `distribution` | `heatmap-chart` 0.8 \u2014 Where the high values gather in the grid. | |\n| `hierarchy` | `hierarchy` | `tree-chart` 0.85 \u2014 The structure itself, node by node.<br>`squarified-treemap` 0.8 \u2014 Nested rectangles, drillable.<br>`sunburst-chart` 0.75 \u2014 Rings of arcs, one ring per level, drillable. | |\n| `hierarchy` | `part-to-whole` | `squarified-treemap` 0.9 \u2014 Area by value, nested by level.<br>`sunburst-chart` 0.85 \u2014 Each arc its share of its parent. | |\n| `links` | `flow` | `sankey-chart` 0.9 \u2014 Bands between layered stages, width by value.<br>`chord-ring` 0.75 \u2014 Flows between categories around a circle, both ways.<br>`network-chart` 0.5 \u2014 When the links matter more than their volume. | |\n| `links` | `network` | `network-chart` 0.9 \u2014 Nodes and links laid out by a seeded force.<br>`chord-ring` 0.7 \u2014 Who connects to whom, around a circle. | |\n| `links` | `part-to-whole` | `sankey-chart` 0.8 \u2014 How a total splits and merges across stages. | |\n| `points` | `correlation` | `scatter-chart` 0.9 \u2014 Points on two linear scales.<br>`bubble-chart` 0.75 \u2014 A third variable as each point\u2019s area.<br>`density-bin-chart` 0.6 \u2014 Counts per bin when points overlap.<br>`connected-scatter-chart` 0.5 \u2014 When the points have an order.<br>`polar-scatter-chart` 0.3 \u2014 When one variable is an angle. | rows>500: `density-bin-chart` +0.35 \u2014 Hundreds of points read better as counts per bin.<br>rows>500: `scatter-chart` -0.2 \u2014 Points overplot and hide their density.<br>values>2: `bubble-chart` +0.2 \u2014 A third numeric field can size the points. |\n| `points` | `distribution` | `density-bin-chart` 0.85 \u2014 Points counted in hexagonal or square bins.<br>`contour-chart` 0.8 \u2014 Iso-lines of the density.<br>`scatter-chart` 0.6 \u2014 Every point, when there are few.<br>`polar-scatter-chart` 0.4 \u2014 Points by angle and radius. | |\n| `points` | `change` | `connected-scatter-chart` 0.9 \u2014 An ordered path through x-y points: how two values moved together. | |\n| `points` | `network` | `delaunay-chart` 0.85 \u2014 Neighbours by triangulation, or each point\u2019s Voronoi cell. | |\n| `points` | `compare` | `bubble-chart` 0.7 \u2014 Positions and sizes compared at once. | |\n| `distribution` | `distribution` | `histogram-chart` 0.9 \u2014 Observations binned in the core.<br>`box-plot-chart` 0.8 \u2014 Quartiles, median, whiskers and outliers.<br>`violin-chart` 0.75 \u2014 The density\u2019s shape, mirrored.<br>`beeswarm-chart` 0.7 \u2014 Every observation, packed without overlap.<br>`ecdf-chart` 0.65 \u2014 The cumulative share below each value.<br>`wind-rose` 0.3 \u2014 When the observations carry a bearing. | rows<30: `beeswarm-chart` +0.25 \u2014 Few observations: show each one.<br>rows<30: `histogram-chart` -0.2 \u2014 Few observations make coarse bins.<br>rows>1000: `beeswarm-chart` -0.4 \u2014 Too many observations to draw one by one. |\n| `distribution` | `compare` | `box-plot-chart` 0.9 \u2014 Quartiles side by side, one box per group.<br>`violin-chart` 0.85 \u2014 Density shapes side by side.<br>`ridgeline-chart` 0.8 \u2014 Densities on overlapping baselines, one per group.<br>`ecdf-chart` 0.75 \u2014 Cumulative curves of each group on one axis. | |\n| `distribution` | `change` | `ridgeline-chart` 0.85 \u2014 A density per period, stacked in order. | |\n| `intervals` | `uncertainty` | `error-bar-chart` 0.9 \u2014 A point estimate with its interval per category.<br>`range-band-chart` 0.85 \u2014 A band between low and high over x. | |\n| `intervals` | `trend` | `range-band-chart` 0.85 \u2014 The band between low and high over time.<br>`candlestick-chart` 0.8 \u2014 Open, high, low and close per period. | |\n| `intervals` | `change` | `candlestick-chart` 0.9 \u2014 Each period\u2019s open-to-close change and its range. | |\n| `intervals` | `schedule` | `interval-chart` 0.95 \u2014 Floating bars from start to end on lanes. | |\n| `events` | `schedule` | `activity-grid` 0.85 \u2014 One cell per day, a column per week. | |\n| `events` | `trend` | `activity-grid` 0.8 \u2014 Activity per day over weeks. | |\n| `single` | `kpi` | `kpi-card` 0.9 \u2014 The figure, its delta and its trend.<br>`gauge-arc` 0.75 \u2014 A percent on a 240\xB0 arc.<br>`meter-chart` 0.7 \u2014 A percent with a needle. | |\n| `single` | `progress` | `gauge-arc` 0.85 \u2014 An arc swept to the percent done.<br>`meter-chart` 0.8 \u2014 A needle at the percent done. | |\n| `field` | `flow` | `vector-field-chart` 0.95 \u2014 An arrow per grid point, its direction and magnitude. | |\n| `field` | `distribution` | `contour-chart` 0.85 \u2014 Iso-lines and bands of a scalar grid (`source: 'grid'`). | |\n\n## Common chart props\n\nEvery chart takes these, under the same names in React, Vue and Angular.\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `data` | `readonly Datum[]` | | Rows to draw. If omitted, the demo dataset is rendered (REQ-093): accessor props (`\u2026Key`, `keys`, `names`, `levels`, `axis`, `dimensions`, `period`, `nodes`) are ignored, every other prop applies. |\n| `ground` | `GroundRef` | `'silverpoint'` | Style ground. Defaults to the app provider's, or `silverpoint`. |\n| `substrate` | `SubstrateName` | `'cream'` | Prepared substrate within the ground (REQ-046). |\n| `mode` | `InkMode` | `'ink'` | `ink` by default; `precision` disables inking (REQ-021). |\n| `palette` | `Palette` | | Colours over the ground's, field by field, written on the root's `style` (REQ-461). Merged over the dashboard's and the provider's (REQ-462); presets are on `@silverpoint/core/palettes`. |\n| `seed` | `Seed` | | Seed. If omitted, it is derived from `id` stably (REQ-003). |\n| `id` | `string` | | Stable identifier. If omitted, it is generated deterministically. |\n| `height` | `number` | `160` | Height of the drawing area in px. Width is the container's unless pinned. |\n| `width` | `number` | | |\n| `chrome` | `'card' \\| 'bare'` | `'card'` | `card` draws the full frame; `bare` only the drawing area (REQ-095). |\n| `hatchFill` | `'tile' \\| 'per-shape'` | `'tile'` | How areas are filled (REQ-029). |\n| `title` | `string` | | |\n| `badge` | `string` | | |\n| `value` | `string \\| number` | | |\n| `unit` | `string` | | |\n| `footerLeft` | `string` | | |\n| `footerRight` | `string` | | |\n| `label` | `string` | | Accessible name. If omitted, it is derived from `title` (REQ-120). |\n| `description` | `string` | | Long description for screen readers (REQ-120). |\n| `dataTable` | `'visible' \\| 'hidden' \\| 'none'` | `'hidden'` | Tabular alternative; `hidden` leaves it for assistive technology only (REQ-121). |\n| `locale` | `string` | | |\n| `numberFormat` | `Intl.NumberFormatOptions` | | |\n| `className` | `string` | | |\n\nDefaults to know:\n\n- `height` is 160, the drawing area without the card frame.\n- `chrome` is `card`. `bare` drops the frame.\n- `dataTable` is `hidden`: the table stays in the page for screen readers only.\n- `hatchFill` is `tile`. `per-shape` traces the hatching shape by shape, which costs 10 to 40 times\n the path weight, so keep it for a hero chart or an export.\n\n## Events\n\n| React | Vue | Angular | Payload |\n|---|---|---|---|\n| `onActiveChange` | `@active-change` | `(activeChange)` | the item under the pointer or keyboard focus, or `null` |\n| `onSelect` | `@select` | `(select)` | the item clicked or chosen with Enter or Space |\n| `onRootChange` | `@root-change` | `(rootChange)` | the sunburst's or treemap's new root id, `null` for the data root |\n",
11416
- "grounds-and-palettes": '<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Grounds and palettes\n\n*Describes silverpoint 0.7.0.*\n\n## Grounds\n\nA *ground* is the drawing technique. Every chart and component draws in the ground the application\nprovider sets, and a `ground` prop overrides it.\n\n| Ground | Substrates | What it draws |\n|---|---|---|\n| `silverpoint` | `cream`, `green`, `blue`, `ochre` | Metal point on prepared paper: hatched tone, a hand-inked line, cream and other prepared substrates. |\n| `cyanotype` | `prussian` | A contact print: a white, exact line on Prussian blue; tone is line weight, nothing is hatched. |\n\n- **silverpoint** (the default): tone is *hatch density*, not colour. A darker category gets\n denser hatching, so a chart reads in grey scale and in print. Highlights are white heightening\n with an ink outline.\n- **cyanotype**: tone is *line weight*, and nothing is hatched. Its only substrate, `prussian`, is\n painted whatever `substrate` says, so leave `substrate` out.\n- `mode="precision"` turns the hand-inked jitter off: the lines become exact. It is forced\n when the page declares `prefers-contrast: more` or `forced-colors: active`, and no prop can undo\n that.\n\n## Palettes\n\nA palette recolours a ground field by field. The fields you leave unset keep the ground\'s colours.\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `substrate` | `string` | | The prepared ground the drawing sits on. |\n| `ink` | `string` | | The main series and the frames of UI components. |\n| `inkSecondary` | `string` | | The second series and the hatch of tones. |\n| `heighten` | `string` | | White heightening on the live value (always outlined with `ink`). |\n| `rule` | `string` | | Rules and baselines. |\n| `grid` | `string` | | Grid lines. |\n| `text` | `string` | | Large figures and primary labels. |\n| `textMuted` | `string` | | Axis labels and secondary text. |\n| `focus` | `string` | `ink` | Focus ring of UI components; `ink` by default. |\n\nThe six presets, all checked for contrast on their substrate:\n\n| Preset | `substrate` | `ink` | `inkSecondary` | `heighten` | `rule` | `grid` | `text` | `textMuted` | `focus` |\n|---|---|---|---|---|---|---|---|---|---|\n| `silverpoint` | #EDE7DA | #5A5E65 | #685C4D | #FFFFFF | #737A82 | #737A82 | #3F4348 | #5A5E65 | |\n| `sanguine` | #F2E8DC | #8A3A24 | #6A4A3A | #FFFFFF | #9A6450 | #9A6450 | #4A2216 | #7A3E2C | |\n| `sepia` | #F0E6D2 | #6B4C2C | #5A5148 | #FFFFFF | #8A6E52 | #8A6E52 | #3B2A18 | #6B4C2C | |\n| `ironGall` | #EEEAE0 | #3C4858 | #6A4E36 | #FFFFFF | #6C7584 | #6C7584 | #232B36 | #4A5566 | |\n| `verdigris` | #E7EDE6 | #2C6355 | #65563F | #FFFFFF | #5C7B71 | #5C7B71 | #1F3D36 | #3E6A5E | |\n| `indigo` | #E9EAF1 | #3A4884 | #675641 | #FFFFFF | #68709A | #68709A | #232C52 | #4A5590 | |\n\nPass the object, never its name. That way a page that names no preset ships none:\n\n```tsx\nimport { sanguine } from \'@silverpoint/core/palettes\';\nimport { BarChart } from \'@silverpoint/react/bar-chart\';\n\nexport function Revenue() {\n return <BarChart title="Revenue by quarter" palette={sanguine} />;\n}\n```\n\nA palette of your own is a plain object, so check its contrast before you ship it, with\n`check_palette` on the MCP server or `checkPalette` from `@silverpoint/core/palettes`. A colour\nthat is not a CSS colour is dropped with `SP024`, and a pair under its contrast threshold warns\n`SP023`.\n\n## Precedence\n\n`ground`, `substrate`, `mode`, `locale` and `palette` resolve from the chart\'s prop first, then the\ndashboard, then the provider, then the library default. A palette merges field by field at each\nlevel, and a nested provider inherits what it does not set.\n\n```tsx\nimport { sepia } from \'@silverpoint/core/palettes\';\nimport { SilverpointProvider } from \'@silverpoint/react\';\nimport { LineChart } from \'@silverpoint/react/line-chart\';\n\nexport function Report() {\n return (\n <SilverpointProvider ground="silverpoint" substrate="ochre" palette={sepia}>\n <LineChart title="Visits" />\n <LineChart title="Visits, exact" mode="precision" />\n </SilverpointProvider>\n );\n}\n```\n',
11417
- "dashboard": '<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Dashboard\n\n*Describes silverpoint 0.7.0.*\n\nA dashboard is a responsive grid of cards. The charts are its children, and the layout is a plain,\nserialisable object matched to them by cell id. There are no placement coordinates and no drag or\nresize.\n\n- **`id` is required.** The seed of every chart without an id of its own derives from it\n (`<dashboard id>--<cell id>`), so choose a stable one.\n- **`title` or `label` is required.** It is the region\'s name. React and Vue refuse a dashboard\n without one by type, and Angular warns `SP002`.\n- **The cells are in reading order.** `columns` defaults to `{ sm: 1, md: 2, lg: 4 }` and collapses\n 4 \u2192 2 \u2192 1 by container width. A `colSpan` wider than the breakpoint\'s columns is clamped, with\n `SP014`.\n- **A chart inside a cell takes the cell\'s box** unless it sets its own `width` and `height`, and it\n inherits the dashboard\'s `ground`, `substrate`, `mode`, `locale` and `palette`.\n- **`link={{ key: \'hour\' }}` highlights the same value** of that field in every chart when one is\n hovered or focused. It is client-only: React\'s server `Dashboard` refuses it.\n- **On the server,** cells are sized at `ssrWidth` (1200 by default) until they are measured.\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `Dashboard` | `SpDashboard` | `sp-dashboard` | `dashboard` |\n| Import | `@silverpoint/react/dashboard` | `@silverpoint/vue/dashboard` | `@silverpoint/angular/dashboard` | `reflex_silverpoint_react` |\n\n### Dashboard props\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `title` | `string` | | |\n| `label` | `string` | | |\n| `id` | `string` | | **Required.** Stable identifier; seeds of unnamed charts derive from it (REQ-209). Required. |\n| `layout` | `DashboardLayout` | | |\n| `description` | `string` | | Long description, exposed as the region\'s description (REQ-214). |\n| `headingLevel` | `2 \\| 3 \\| 4 \\| 5 \\| 6` | `2` | Heading level of `title`. Default `2`. |\n| `ssrWidth` | `number` | `1200` | Width in px used for nominal cell boxes on the server and at hydration (REQ-207). Default `1200`. |\n| `link` | `DashboardLink` | | Linked interaction (REQ-216); client entry points only. |\n| `ground` | `GroundRef` | | Inherited by every chart inside, below the chart\'s own prop (REQ-212). |\n| `substrate` | `SubstrateName` | | |\n| `mode` | `InkMode` | | |\n| `locale` | `string` | | |\n| `palette` | `Palette` | | The section\'s colours, written on its root and merged under every chart\'s and component\'s own (REQ-462). |\n| `className` | `string` | | |\n\n## Layout\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `columns` | `PerBreakpoint<number>` | `{ sm: 1, md: 2, lg: 4 }` | Columns per breakpoint. Default `{ sm: 1, md: 2, lg: 4 }` (REQ-208). |\n| `rowHeight` | `number` | `240` | Height of one row unit, in px, card chrome included. Default `240`. |\n| `gap` | `number` | `16` | Gap between cells, in px. Default `16`. |\n| `cells` | `readonly DashboardCellLayout[]` | | Cells in reading order (REQ-203). Omitted: every child, span 1. |\n\n### Cell layout (`layout.cells[]`)\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `id` | `string` | | **Required.** Matches `DashboardCell`\'s `cell` prop; unique within the dashboard (REQ-205). |\n| `colSpan` | `PerBreakpoint<number>` | `1` | Default `1`. Clamped to the breakpoint\'s columns with `SP014` (REQ-204). |\n| `rowSpan` | `PerBreakpoint<number>` | `1` | Default `1`. |\n\n## React\n\n```tsx\nimport { Dashboard, DashboardCell, type DashboardLayout } from \'@silverpoint/react/dashboard\';\nimport { BarChart } from \'@silverpoint/react/bar-chart\';\nimport { KpiCard } from \'@silverpoint/react/kpi-card\';\nimport { LineChart } from \'@silverpoint/react/line-chart\';\n\nconst layout: DashboardLayout = {\n columns: { sm: 1, md: 2, lg: 4 },\n cells: [{ id: \'revenue\' }, { id: \'traffic\', colSpan: { md: 2, lg: 3 }, rowSpan: 2 }, { id: \'errors\' }],\n};\n\n// A type, not an interface: an interface has no index signature, so it is not a `Datum`.\ntype Row = { readonly hour: string; readonly hits: number; readonly errors: number };\n\nexport function Operations({ rows, revenue }: { rows: readonly Row[]; revenue: number }) {\n return (\n <Dashboard id="ops" title="Operations" layout={layout} link={{ key: \'hour\' }}>\n <DashboardCell cell="revenue">\n <KpiCard title="Revenue" data={[{ value: revenue }]} unit="EUR" />\n </DashboardCell>\n <DashboardCell cell="traffic">\n <LineChart title="Traffic" data={rows} xKey="hour" valueKey="hits" />\n </DashboardCell>\n <DashboardCell cell="errors">\n <BarChart title="Errors" data={rows} xKey="hour" valueKey="errors" />\n </DashboardCell>\n </Dashboard>\n );\n}\n```\n\nReact hands each cell\'s box and configuration to its chart as props, so a chart must be the cell\'s\ndirect child.\n\n## Vue\n\n```vue\n<script setup lang="ts">\nimport { SpDashboard, SpDashboardCell, type DashboardLayout } from \'@silverpoint/vue/dashboard\';\nimport { SpBarChart } from \'@silverpoint/vue/bar-chart\';\nimport { SpLineChart } from \'@silverpoint/vue/line-chart\';\n\ndefineProps<{ rows: readonly { hour: string; hits: number; errors: number }[] }>();\n\nconst layout: DashboardLayout = { cells: [{ id: \'traffic\', colSpan: { md: 2, lg: 3 } }, { id: \'errors\' }] };\n</script>\n\n<template>\n <SpDashboard id="ops" title="Operations" :layout="layout" :link="{ key: \'hour\' }">\n <SpDashboardCell cell="traffic"><SpLineChart title="Traffic" :data="rows" x-key="hour" value-key="hits" /></SpDashboardCell>\n <SpDashboardCell cell="errors"><SpBarChart title="Errors" :data="rows" x-key="hour" value-key="errors" /></SpDashboardCell>\n </SpDashboard>\n</template>\n```\n\n## Angular\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, input } from \'@angular/core\';\nimport { SpBarChart } from \'@silverpoint/angular/bar-chart\';\nimport { SpDashboard, SpDashboardCell, type DashboardLayout } from \'@silverpoint/angular/dashboard\';\nimport { SpLineChart } from \'@silverpoint/angular/line-chart\';\n\n@Component({\n selector: \'app-operations\',\n imports: [SpDashboard, SpDashboardCell, SpLineChart, SpBarChart],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-dashboard [id]="\'ops\'" [title]="\'Operations\'" [layout]="layout" [link]="{ key: \'hour\' }">\n <sp-dashboard-cell [cell]="\'traffic\'">\n <sp-line-chart [title]="\'Traffic\'" [data]="rows()" [xKey]="\'hour\'" [valueKey]="\'hits\'" />\n </sp-dashboard-cell>\n <sp-dashboard-cell [cell]="\'errors\'">\n <sp-bar-chart [title]="\'Errors\'" [data]="rows()" [xKey]="\'hour\'" [valueKey]="\'errors\'" />\n </sp-dashboard-cell>\n </sp-dashboard>\n `,\n})\nexport class Operations {\n readonly rows = input.required<readonly { hour: string; hits: number; errors: number }[]>();\n protected readonly layout: DashboardLayout = { cells: [{ id: \'traffic\', colSpan: { md: 2, lg: 3 } }, { id: \'errors\' }] };\n}\n```\n',
11418
- "ui-components": "<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# UI and composed components\n\n*Describes silverpoint 0.7.0.*\n\nEvery component is named `Sp<Name>` in the three frameworks (`SpButton`, `<sp-input>`), imported\nfrom its own subpath (`@silverpoint/react/ui/button`), and drawn in the same ground as the\ncharts. Import `@silverpoint/grounds/ui.css` once, after `styles.css`.\n\n## Binding a value\n\n| | Controlled | Uncontrolled | Change |\n|---|---|---|---|\n| React | `value` (`checked` for Checkbox and Switch) | `defaultValue` (`defaultChecked`) | `onChange(value)`: the value, not the DOM event |\n| Vue | `v-model` | omit `v-model`, pass `default-value` | `update:modelValue`, then `change` on commit |\n| Angular | `[(value)]`, or `formControl` / `ngModel` | `[defaultValue]` | `(valueChange)` |\n\nValue events fire on user input only, never on a prop change, and never for a disabled component\nor item. Angular value components are `ControlValueAccessor`s, so they work in reactive and\ntemplate-driven forms.\n\n## Server rendering\n\nIn React, display components also have server entries (`@silverpoint/react/server/ui/<name>`):\n`card`, `tag`, `badge`, `divider`, `progress`, `alert`, `skeleton`, `steps`, `surface`, `glyph`,\n`table` (unsortable), `breadcrumb`, `avatar`, `statistic`, `descriptions`, `timeline-list`, `empty`\nand `result`. Every other component is a client component.\n\n## Notes\n\n- `SpButton` is an attribute component in Angular (`<button spButton>`, `<a spButton>`), so your own\n element is the control. `SpSurface` is `[spSurface]` in the same way.\n- `SpTabs` renders `SpTabPanel` children matched by `value`.\n- `SpTable` draws its rows as given: sort them yourself on `onSort` (`@sort`, `(sort)`), which also\n keeps paging with `SpPagination` correct.\n- A link's `href` (`SpButton`, `SpBreadcrumb`) keeps relative URLs and the `http`, `https`,\n `mailto` and `tel` schemes. Any other is dropped with `SP017`.\n- Named content: React takes node props, Vue slots (`prefix`, `suffix`, `extra`, `footer`), and\n Angular templates (`<ng-template spExtra>`, `spFooter`, `spPrefix`, `spSuffix`).\n\n**Contents:** [SpButton](#spbutton) \xB7 [SpInput](#spinput) \xB7 [SpCheckbox](#spcheckbox) \xB7 [SpRadioGroup](#spradiogroup) \xB7 [SpSwitch](#spswitch) \xB7 [SpSlider](#spslider) \xB7 [SpRate](#sprate) \xB7 [SpSegmented](#spsegmented) \xB7 [SpTabs](#sptabs) \xB7 [SpSteps](#spsteps) \xB7 [SpCard](#spcard) \xB7 [SpTag](#sptag) \xB7 [SpBadge](#spbadge) \xB7 [SpDivider](#spdivider) \xB7 [SpProgress](#spprogress) \xB7 [SpAlert](#spalert) \xB7 [SpSkeleton](#spskeleton) \xB7 [SpSurface](#spsurface) \xB7 [SpGlyph](#spglyph) \xB7 [SpTable](#sptable) \xB7 [SpPagination](#sppagination) \xB7 [SpBreadcrumb](#spbreadcrumb) \xB7 [SpAvatar](#spavatar) \xB7 [SpStatistic](#spstatistic) \xB7 [SpDescriptions](#spdescriptions) \xB7 [SpTimelineList](#sptimelinelist) \xB7 [SpCollapse](#spcollapse) \xB7 [SpEmpty](#spempty) \xB7 [SpResult](#spresult) \xB7 [SpTextarea](#sptextarea) \xB7 [SpInputNumber](#spinputnumber)\n\n## SpButton\n\n`button` \xB7 A button or a link styled as one; `primary` and `danger` variants. (actions)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpButton` | `SpButton` | `button[spButton]` | `sp_button` |\n| Import | `@silverpoint/react/ui/button` | `@silverpoint/vue/ui/button` | `@silverpoint/angular/ui/button` | `reflex_silverpoint_react` |\n\n**Events:** React `onClick`; Vue `click`; Angular .\n\n**Content:** React `children`; Vue `default`; Angular `content`.\n\n**States:** `default`, `primary`, `danger`, `disabled`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `variant` | `UiVariant` | `'default'` | Default `'default'`; `danger` also draws the exact \u2715 glyph (REQ-310). |\n| `type` | `'button' \\| 'submit' \\| 'reset'` | `'button'` | Default `'button'`. |\n| `disabled` | `boolean` | | Not focusable, not submitted; drawn with the disabled tone. |\n| `label` | `string` | | Accessible name of an icon-only button (REQ-319). |\n| `block` | `boolean` | | Fills the width of its container. |\n| `href` | `string` | | Renders an `<a>`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpButton } from '@silverpoint/react/ui/button';\n\nexport function ButtonView() {\n return (\n <SpButton>\n Default\n </SpButton>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpButton } from '@silverpoint/vue/ui/button';\n</script>\n\n<template>\n <SpButton>\n Default\n </SpButton>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpButton } from '@silverpoint/angular/ui/button';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-button-view',\n imports: [SpButton],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <button\n spButton\n >\n Default\n </button>\n `,\n})\nexport class ButtonView {}\n```\n\n## SpInput\n\n`input` \xB7 A labelled text field with an optional message and an invalid state. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpInput` | `SpInput` | `sp-input` | `sp_input` |\n| Import | `@silverpoint/react/ui/input` | `@silverpoint/vue/ui/input` | `@silverpoint/angular/ui/input` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**Content:** React `prefix`, `suffix`; Vue `prefix`, `suffix`; Angular `spPrefix`, `spSuffix`.\n\n**States:** `empty`, `filled`, `invalid`, `disabled`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `type` | `'text' \\| 'search' \\| 'email' \\| 'url' \\| 'tel' \\| 'password' \\| 'number'` | `'text'` | Native input type. Default `'text'`. |\n| `placeholder` | `string` | | Hint shown while empty; not a substitute for the accessible name. |\n| `name` | `string` | | Form field name; the native input submits under it (REQ-323). |\n| `disabled` | `boolean` | | Not focusable and not submitted. |\n| `readOnly` | `boolean` | | Focusable and submitted, but not editable. |\n| `invalid` | `boolean` | | Sets `aria-invalid` and draws the exact \u26A0 glyph (REQ-334). |\n| `message` | `string` | | Help or error text under the control, referenced by `aria-describedby` (REQ-334). |\n| `label` | `string` | | Accessible name, when no `<label for>` names the control. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpInput } from '@silverpoint/react/ui/input';\n\nexport function InputView() {\n const [value, setValue] = useState<string>('');\n return (\n <SpInput\n label=\"Search charts\"\n placeholder=\"Search charts\u2026\"\n type=\"search\"\n name=\"q\"\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpInput } from '@silverpoint/vue/ui/input';\n\nconst value = ref<string>('');\n</script>\n\n<template>\n <SpInput\n label=\"Search charts\"\n placeholder=\"Search charts\u2026\"\n type=\"search\"\n name=\"q\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpInput } from '@silverpoint/angular/ui/input';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-input-view',\n imports: [SpInput],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-input\n [label]=\"'Search charts'\"\n [placeholder]=\"'Search charts\u2026'\"\n [type]=\"'search'\"\n [name]=\"'q'\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class InputView {\n protected readonly value = signal<string>('');\n}\n```\n\n## SpCheckbox\n\n`checkbox` \xB7 A labelled checkbox, with an indeterminate state. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpCheckbox` | `SpCheckbox` | `sp-checkbox` | `sp_checkbox` |\n| Import | `@silverpoint/react/ui/checkbox` | `@silverpoint/vue/ui/checkbox` | `@silverpoint/angular/ui/checkbox` | `reflex_silverpoint_react` |\n\n**Value:** React `checked + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**States:** `unchecked`, `checked`, `indeterminate`, `disabled`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `label` | `string` | | **Required.** The visible text and accessible name. |\n| `name` | `string` | | Form field name; submitted as `on` when checked. |\n| `disabled` | `boolean` | | Not focusable and not submitted. |\n| `indeterminate` | `boolean` | | Draws the exact dash and sets the native `indeterminate` state. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpCheckbox } from '@silverpoint/react/ui/checkbox';\n\nexport function CheckboxView() {\n const [value, setValue] = useState<boolean>(false);\n return (\n <SpCheckbox\n label=\"Legend\"\n name=\"legend\"\n checked={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpCheckbox } from '@silverpoint/vue/ui/checkbox';\n\nconst value = ref<boolean>(false);\n</script>\n\n<template>\n <SpCheckbox\n label=\"Legend\"\n name=\"legend\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpCheckbox } from '@silverpoint/angular/ui/checkbox';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-checkbox-view',\n imports: [SpCheckbox],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-checkbox\n [label]=\"'Legend'\"\n [name]=\"'legend'\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class CheckboxView {\n protected readonly value = signal<boolean>(false);\n}\n```\n\n## SpRadioGroup\n\n`radio-group` \xB7 One choice among a few, as a fieldset of radios. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpRadioGroup` | `SpRadioGroup` | `sp-radio-group` | `sp_radio_group` |\n| Import | `@silverpoint/react/ui/radio-group` | `@silverpoint/vue/ui/radio-group` | `@silverpoint/angular/ui/radio-group` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**States:** `selected`, `disabled-item`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly UiItem[]` | | **Required.** The choices; each a native radio. Keys are unique (REQ-325). |\n| `name` | `string` | | **Required.** Required: the native radios submit under it (REQ-323). |\n| `label` | `string` | | **Required.** The group's name, its `<legend>`. |\n| `orientation` | `UiOrientation` | `'vertical'` | Default `'vertical'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpRadioGroup } from '@silverpoint/react/ui/radio-group';\n\nexport function RadioGroupView() {\n const [value, setValue] = useState<string>('silverpoint');\n return (\n <SpRadioGroup\n label=\"Ground\"\n name=\"ground\"\n items={[{ key: 'silverpoint', label: 'silverpoint' }, { key: 'cyanotype', label: 'cyanotype' }]}\n orientation=\"horizontal\"\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpRadioGroup } from '@silverpoint/vue/ui/radio-group';\n\nconst value = ref<string>('silverpoint');\n</script>\n\n<template>\n <SpRadioGroup\n label=\"Ground\"\n name=\"ground\"\n :items=\"[{ key: 'silverpoint', label: 'silverpoint' }, { key: 'cyanotype', label: 'cyanotype' }]\"\n orientation=\"horizontal\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpRadioGroup } from '@silverpoint/angular/ui/radio-group';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-radio-group-view',\n imports: [SpRadioGroup],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-radio-group\n [label]=\"'Ground'\"\n [name]=\"'ground'\"\n [items]=\"[{ key: 'silverpoint', label: 'silverpoint' }, { key: 'cyanotype', label: 'cyanotype' }]\"\n [orientation]=\"'horizontal'\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class RadioGroupView {\n protected readonly value = signal<string>('silverpoint');\n}\n```\n\n## SpSwitch\n\n`switch` \xB7 An on/off toggle with the switch role. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpSwitch` | `SpSwitch` | `sp-switch` | `sp_switch` |\n| Import | `@silverpoint/react/ui/switch` | `@silverpoint/vue/ui/switch` | `@silverpoint/angular/ui/switch` | `reflex_silverpoint_react` |\n\n**Value:** React `checked + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**States:** `off`, `on`, `disabled`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `label` | `string` | | **Required.** The visible text and accessible name. |\n| `name` | `string` | | Form field name; submitted as `on` when on. |\n| `disabled` | `boolean` | | Not focusable and not submitted. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpSwitch } from '@silverpoint/react/ui/switch';\n\nexport function SwitchView() {\n const [value, setValue] = useState<boolean>(false);\n return (\n <SpSwitch\n label=\"Linked hover\"\n name=\"linked\"\n checked={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpSwitch } from '@silverpoint/vue/ui/switch';\n\nconst value = ref<boolean>(false);\n</script>\n\n<template>\n <SpSwitch\n label=\"Linked hover\"\n name=\"linked\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpSwitch } from '@silverpoint/angular/ui/switch';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-switch-view',\n imports: [SpSwitch],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-switch\n [label]=\"'Linked hover'\"\n [name]=\"'linked'\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class SwitchView {\n protected readonly value = signal<boolean>(false);\n}\n```\n\n## SpSlider\n\n`slider` \xB7 A value on a range, with optional marks. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpSlider` | `SpSlider` | `sp-slider` | `sp_slider` |\n| Import | `@silverpoint/react/ui/slider` | `@silverpoint/vue/ui/slider` | `@silverpoint/angular/ui/slider` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**States:** `marks`, `disabled`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `label` | `string` | | **Required.** Accessible name of the native range input. |\n| `min` | `number` | `0` | Default `0`. |\n| `max` | `number` | `100` | Default `100`. |\n| `step` | `number` | `1` | Default `1`. |\n| `name` | `string` | | Form field name; the native input submits under it. |\n| `disabled` | `boolean` | | Not focusable and not submitted. |\n| `marks` | `readonly number[]` | | Values on the rail that get a labelled mark. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpSlider } from '@silverpoint/react/ui/slider';\n\nexport function SliderView() {\n const [value, setValue] = useState<number>(30);\n return (\n <SpSlider\n label=\"Volume\"\n name=\"volume\"\n marks={[0, 25, 50, 75, 100]}\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpSlider } from '@silverpoint/vue/ui/slider';\n\nconst value = ref<number>(30);\n</script>\n\n<template>\n <SpSlider\n label=\"Volume\"\n name=\"volume\"\n :marks=\"[0, 25, 50, 75, 100]\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpSlider } from '@silverpoint/angular/ui/slider';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-slider-view',\n imports: [SpSlider],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-slider\n [label]=\"'Volume'\"\n [name]=\"'volume'\"\n [marks]=\"[0, 25, 50, 75, 100]\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class SliderView {\n protected readonly value = signal<number>(30);\n}\n```\n\n## SpRate\n\n`rate` \xB7 A rating from 1 to `count`, optionally read-only. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpRate` | `SpRate` | `sp-rate` | `sp_rate` |\n| Import | `@silverpoint/react/ui/rate` | `@silverpoint/vue/ui/rate` | `@silverpoint/angular/ui/rate` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**States:** `three`, `read-only`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `label` | `string` | | **Required.** The group's name, its `<legend>`. |\n| `count` | `number` | `5` | Default `5`, in 1..10; each mark an exact lozenge. |\n| `name` | `string` | | Form field name; the native radios submit under it. |\n| `disabled` | `boolean` | | Not focusable and not submitted. |\n| `readOnly` | `boolean` | | Shows the value; the keyboard and the pointer do not change it. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpRate } from '@silverpoint/react/ui/rate';\n\nexport function RateView() {\n const [value, setValue] = useState<number>(3);\n return (\n <SpRate\n label=\"Quality\"\n name=\"quality\"\n count={5}\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpRate } from '@silverpoint/vue/ui/rate';\n\nconst value = ref<number>(3);\n</script>\n\n<template>\n <SpRate\n label=\"Quality\"\n name=\"quality\"\n :count=\"5\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpRate } from '@silverpoint/angular/ui/rate';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-rate-view',\n imports: [SpRate],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-rate\n [label]=\"'Quality'\"\n [name]=\"'quality'\"\n [count]=\"5\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class RateView {\n protected readonly value = signal<number>(3);\n}\n```\n\n## SpSegmented\n\n`segmented` \xB7 One choice among a few, as joined segments. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpSegmented` | `SpSegmented` | `sp-segmented` | `sp_segmented` |\n| Import | `@silverpoint/react/ui/segmented` | `@silverpoint/vue/ui/segmented` | `@silverpoint/angular/ui/segmented` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**States:** `first`, `middle`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly UiItem[]` | | **Required.** The options; each a native radio. Keys are unique (REQ-325). |\n| `label` | `string` | | **Required.** The control's name, its `<legend>`. |\n| `name` | `string` | | Form field name; the native radios submit under it. |\n| `block` | `boolean` | | Fills the width of its container. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpSegmented } from '@silverpoint/react/ui/segmented';\n\nexport function SegmentedView() {\n const [value, setValue] = useState<string>('day');\n return (\n <SpSegmented\n label=\"Period\"\n name=\"period\"\n items={[{ key: 'day', label: 'Day' }, { key: 'week', label: 'Week' }, { key: 'month', label: 'Month' }, { key: 'year', label: 'Year' }]}\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpSegmented } from '@silverpoint/vue/ui/segmented';\n\nconst value = ref<string>('day');\n</script>\n\n<template>\n <SpSegmented\n label=\"Period\"\n name=\"period\"\n :items=\"[{ key: 'day', label: 'Day' }, { key: 'week', label: 'Week' }, { key: 'month', label: 'Month' }, { key: 'year', label: 'Year' }]\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpSegmented } from '@silverpoint/angular/ui/segmented';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-segmented-view',\n imports: [SpSegmented],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-segmented\n [label]=\"'Period'\"\n [name]=\"'period'\"\n [items]=\"[{ key: 'day', label: 'Day' }, { key: 'week', label: 'Week' }, { key: 'month', label: 'Month' }, { key: 'year', label: 'Year' }]\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class SegmentedView {\n protected readonly value = signal<string>('day');\n}\n```\n\n## SpTabs\n\n`tabs` \xB7 Tabs and their panels (`SpTabPanel`), with automatic or manual activation. (navigation)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpTabs` | `SpTabs` | `sp-tabs` | `sp_tabs` |\n| Import | `@silverpoint/react/ui/tabs` | `@silverpoint/vue/ui/tabs` | `@silverpoint/angular/ui/tabs` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**Content:** React `children`; Vue `default`; Angular `content`.\n\n**States:** `first`, `disabled-tab`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly UiItem[]` | | **Required.** The tabs; a disabled one is skipped by the arrows. Keys are unique (REQ-325). |\n| `label` | `string` | | Accessible name of the tab list. |\n| `orientation` | `UiOrientation` | `'horizontal'` | Default `'horizontal'`. |\n| `activation` | `'automatic' \\| 'manual'` | `'automatic'` | Default `'automatic'`: a tab is selected as focus reaches it. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpTabs } from '@silverpoint/react/ui/tabs';\n\nexport function TabsView() {\n const [value, setValue] = useState<string>('overview');\n return (\n <SpTabs\n label=\"Views\"\n items={[{ key: 'overview', label: 'Overview' }, { key: 'traffic', label: 'Traffic' }, { key: 'errors', label: 'Errors' }, { key: 'settings', label: 'Settings' }]}\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpTabs } from '@silverpoint/vue/ui/tabs';\n\nconst value = ref<string>('overview');\n</script>\n\n<template>\n <SpTabs\n label=\"Views\"\n :items=\"[{ key: 'overview', label: 'Overview' }, { key: 'traffic', label: 'Traffic' }, { key: 'errors', label: 'Errors' }, { key: 'settings', label: 'Settings' }]\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpTabs } from '@silverpoint/angular/ui/tabs';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-tabs-view',\n imports: [SpTabs],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-tabs\n [label]=\"'Views'\"\n [items]=\"[{ key: 'overview', label: 'Overview' }, { key: 'traffic', label: 'Traffic' }, { key: 'errors', label: 'Errors' }, { key: 'settings', label: 'Settings' }]\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class TabsView {\n protected readonly value = signal<string>('overview');\n}\n```\n\n## SpSteps\n\n`steps` \xB7 The steps of a process, with the current one and an error state. (navigation)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpSteps` | `SpSteps` | `sp-steps` | `sp_steps` |\n| Import | `@silverpoint/react/ui/steps` | `@silverpoint/vue/ui/steps` | `@silverpoint/angular/ui/steps` | `reflex_silverpoint_react` |\n\n**States:** `current`, `error`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly StepItem[]` | | **Required.** The steps, in order; a status is derived from `current` unless set. |\n| `current` | `number` | | **Required.** 0-based. |\n| `orientation` | `UiOrientation` | `'horizontal'` | Default `'horizontal'`. |\n| `label` | `string` | | Accessible name of the list. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpSteps } from '@silverpoint/react/ui/steps';\n\nexport function StepsView() {\n return (\n <SpSteps\n label=\"Release\"\n items={[{ key: 'install', title: 'Install' }, { key: 'import', title: 'Import' }, { key: 'configure', title: 'Configure' }, { key: 'publish', title: 'Publish' }]}\n current={2}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpSteps } from '@silverpoint/vue/ui/steps';\n</script>\n\n<template>\n <SpSteps\n label=\"Release\"\n :items=\"[{ key: 'install', title: 'Install' }, { key: 'import', title: 'Import' }, { key: 'configure', title: 'Configure' }, { key: 'publish', title: 'Publish' }]\"\n :current=\"2\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpSteps } from '@silverpoint/angular/ui/steps';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-steps-view',\n imports: [SpSteps],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-steps\n [label]=\"'Release'\"\n [items]=\"[{ key: 'install', title: 'Install' }, { key: 'import', title: 'Import' }, { key: 'configure', title: 'Configure' }, { key: 'publish', title: 'Publish' }]\"\n [current]=\"2\"\n />\n `,\n})\nexport class StepsView {}\n```\n\n## SpCard\n\n`card` \xB7 A framed card with a title, an extra slot and a footer. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpCard` | `SpCard` | `sp-card` | `sp_card` |\n| Import | `@silverpoint/react/ui/card` | `@silverpoint/vue/ui/card` | `@silverpoint/angular/ui/card` | `reflex_silverpoint_react` |\n\n**Content:** React `children`, `extra`, `footer`; Vue `default`, `extra`, `footer`; Angular `content`, `spExtra`, `spFooter`.\n\n**States:** `plain`, `titled`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `title` | `string` | | Heading of the card; without it the card is a plain container. |\n| `headingLevel` | `2 \\| 3 \\| 4 \\| 5 \\| 6` | `3` | Default `3`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpCard } from '@silverpoint/react/ui/card';\n\nexport function CardView() {\n return (\n <SpCard>\n Hits per hour rose through the afternoon and eased at night.\n </SpCard>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpCard } from '@silverpoint/vue/ui/card';\n</script>\n\n<template>\n <SpCard>\n Hits per hour rose through the afternoon and eased at night.\n </SpCard>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpCard } from '@silverpoint/angular/ui/card';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-card-view',\n imports: [SpCard],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-card>\n Hits per hour rose through the afternoon and eased at night.\n </sp-card>\n `,\n})\nexport class CardView {}\n```\n\n## SpTag\n\n`tag` \xB7 A short toned label, optionally closable. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpTag` | `SpTag` | `sp-tag` | `sp_tag` |\n| Import | `@silverpoint/react/ui/tag` | `@silverpoint/vue/ui/tag` | `@silverpoint/angular/ui/tag` | `reflex_silverpoint_react` |\n\n**Events:** React `onClose`; Vue `close`; Angular `close`.\n\n**Content:** React `children`; Vue `default`; Angular `content`.\n\n**States:** `tone-1`, `closable`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `tone` | `UiToneLevel` | | Tonal level, default `1`. |\n| `closable` | `boolean` | | Adds a native close button; each adapter raises its close event. |\n| `closeLabel` | `string` | `Remove <text>` | Accessible name of the close button. Default `Remove <text>`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTag } from '@silverpoint/react/ui/tag';\n\nexport function TagView() {\n return (\n <SpTag\n tone={1}\n >\n draft\n </SpTag>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTag } from '@silverpoint/vue/ui/tag';\n</script>\n\n<template>\n <SpTag\n :tone=\"1\"\n >\n draft\n </SpTag>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpTag } from '@silverpoint/angular/ui/tag';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-tag-view',\n imports: [SpTag],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-tag\n [tone]=\"1\"\n >\n draft\n </sp-tag>\n `,\n})\nexport class TagView {}\n```\n\n## SpBadge\n\n`badge` \xB7 A count or a dot over its content. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpBadge` | `SpBadge` | `sp-badge` | `sp_badge` |\n| Import | `@silverpoint/react/ui/badge` | `@silverpoint/vue/ui/badge` | `@silverpoint/angular/ui/badge` | `reflex_silverpoint_react` |\n\n**Content:** React `children`; Vue `default`; Angular `content`.\n\n**States:** `count`, `dot`, `overflow`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `count` | `number` | | The number shown, up to `max`. |\n| `max` | `number` | `99` | Default `99`; above it the badge reads `99+`. |\n| `dot` | `boolean` | | A dot with no number. |\n| `label` | `string` | | Accessible text of the badge, e.g. `unread messages`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpBadge } from '@silverpoint/react/ui/badge';\n\nexport function BadgeView() {\n return (\n <SpBadge\n count={12}\n >\n Inbox\n </SpBadge>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpBadge } from '@silverpoint/vue/ui/badge';\n</script>\n\n<template>\n <SpBadge\n :count=\"12\"\n >\n Inbox\n </SpBadge>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpBadge } from '@silverpoint/angular/ui/badge';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-badge-view',\n imports: [SpBadge],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-badge\n [count]=\"12\"\n >\n Inbox\n </sp-badge>\n `,\n})\nexport class BadgeView {}\n```\n\n## SpDivider\n\n`divider` \xB7 A rule between sections, optionally with text. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpDivider` | `SpDivider` | `sp-divider` | `sp_divider` |\n| Import | `@silverpoint/react/ui/divider` | `@silverpoint/vue/ui/divider` | `@silverpoint/angular/ui/divider` | `reflex_silverpoint_react` |\n\n**States:** `plain`, `text`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `orientation` | `UiOrientation` | `'horizontal'` | Default `'horizontal'`. |\n| `text` | `string` | | A caption set in the rule. |\n| `align` | `'start' \\| 'center' \\| 'end'` | `'center'` | Default `'center'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDivider } from '@silverpoint/react/ui/divider';\n\nexport function DividerView() {\n return (\n <SpDivider />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDivider } from '@silverpoint/vue/ui/divider';\n</script>\n\n<template>\n <SpDivider />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpDivider } from '@silverpoint/angular/ui/divider';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-divider-view',\n imports: [SpDivider],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-divider />\n `,\n})\nexport class DividerView {}\n```\n\n## SpProgress\n\n`progress` \xB7 Progress as a line or a circle, or indeterminate. (feedback)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpProgress` | `SpProgress` | `sp-progress` | `sp_progress` |\n| Import | `@silverpoint/react/ui/progress` | `@silverpoint/vue/ui/progress` | `@silverpoint/angular/ui/progress` | `reflex_silverpoint_react` |\n\n**States:** `line`, `circle`, `indeterminate`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `value` | `number` | | 0..100; omitted, the progress is indeterminate. |\n| `shape` | `'line' \\| 'circle'` | `'line'` | Default `'line'`. |\n| `label` | `string` | | **Required.** Accessible name (REQ-318). |\n| `showValue` | `boolean` | `true` | Default `true`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpProgress } from '@silverpoint/react/ui/progress';\n\nexport function ProgressView() {\n return (\n <SpProgress\n label=\"Upload\"\n value={40}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpProgress } from '@silverpoint/vue/ui/progress';\n</script>\n\n<template>\n <SpProgress\n label=\"Upload\"\n :value=\"40\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpProgress } from '@silverpoint/angular/ui/progress';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-progress-view',\n imports: [SpProgress],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-progress\n [label]=\"'Upload'\"\n [value]=\"40\"\n />\n `,\n})\nexport class ProgressView {}\n```\n\n## SpAlert\n\n`alert` \xB7 An info, success, warning or error message, optionally closable. (feedback)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpAlert` | `SpAlert` | `sp-alert` | `sp_alert` |\n| Import | `@silverpoint/react/ui/alert` | `@silverpoint/vue/ui/alert` | `@silverpoint/angular/ui/alert` | `reflex_silverpoint_react` |\n\n**Events:** React `onClose`; Vue `close`; Angular `close`.\n\n**Content:** React `children`; Vue `default`; Angular `content`.\n\n**States:** `info`, `success`, `warning`, `error`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `kind` | `AlertKind` | `'info'` | Default `'info'`. |\n| `title` | `string` | | Bold first line of the alert. |\n| `closable` | `boolean` | | Adds a native close button; each adapter raises its close event. |\n| `closeLabel` | `string` | `'Close'` | Accessible name of the close button. Default `'Close'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpAlert } from '@silverpoint/react/ui/alert';\n\nexport function AlertView() {\n return (\n <SpAlert\n kind=\"info\"\n title=\"New ground available\"\n >\n cyanotype ships in 0.2.0.\n </SpAlert>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpAlert } from '@silverpoint/vue/ui/alert';\n</script>\n\n<template>\n <SpAlert\n kind=\"info\"\n title=\"New ground available\"\n >\n cyanotype ships in 0.2.0.\n </SpAlert>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpAlert } from '@silverpoint/angular/ui/alert';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-alert-view',\n imports: [SpAlert],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-alert\n [kind]=\"'info'\"\n [title]=\"'New ground available'\"\n >\n cyanotype ships in 0.2.0.\n </sp-alert>\n `,\n})\nexport class AlertView {}\n```\n\n## SpSkeleton\n\n`skeleton` \xB7 A placeholder for content that is loading. (feedback)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpSkeleton` | `SpSkeleton` | `sp-skeleton` | `sp_skeleton` |\n| Import | `@silverpoint/react/ui/skeleton` | `@silverpoint/vue/ui/skeleton` | `@silverpoint/angular/ui/skeleton` | `reflex_silverpoint_react` |\n\n**States:** `paragraph`, `avatar`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `lines` | `number` | `3` | Default `3`, in 1..8. |\n| `avatar` | `boolean` | | Draws an avatar placeholder before the lines. |\n| `label` | `string` | `'Loading'` | Default `'Loading'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpSkeleton } from '@silverpoint/react/ui/skeleton';\n\nexport function SkeletonView() {\n return (\n <SpSkeleton\n lines={3}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpSkeleton } from '@silverpoint/vue/ui/skeleton';\n</script>\n\n<template>\n <SpSkeleton\n :lines=\"3\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpSkeleton } from '@silverpoint/angular/ui/skeleton';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-skeleton-view',\n imports: [SpSkeleton],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-skeleton\n [lines]=\"3\"\n />\n `,\n})\nexport class SkeletonView {}\n```\n\n## SpSurface\n\n`surface` \xB7 A framed, toned surface to build your own components on. (building-blocks)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpSurface` | `SpSurface` | `[spSurface]` | `sp_surface` |\n| Import | `@silverpoint/react/ui/surface` | `@silverpoint/vue/ui/surface` | `@silverpoint/angular/ui/surface` | `reflex_silverpoint_react` |\n\n**Content:** React `children`; Vue `default`; Angular `content`.\n\n**States:** `frame-card`, `tone-2`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `as` | `string` | `'div'` | The element, a lowercase HTML tag name. Default `'div'`. |\n| `name` | `string` | | Adds the class `sp-<name>`, a lowercase ident. |\n| `frame` | `UiFrameKind` | | Draws a frame of that kind. |\n| `tone` | `UiToneLevel \\| string` | | Lays a tone: a level 1-4 of the ramp, or a state (`selected`, `primary`\u2026). |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpSurface } from '@silverpoint/react/ui/surface';\n\nexport function SurfaceView() {\n return (\n <SpSurface\n frame=\"card\"\n >\n A surface takes the ground: its substrate, its ink and a hand-drawn frame.\n </SpSurface>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpSurface } from '@silverpoint/vue/ui/surface';\n</script>\n\n<template>\n <SpSurface\n frame=\"card\"\n >\n A surface takes the ground: its substrate, its ink and a hand-drawn frame.\n </SpSurface>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpSurface } from '@silverpoint/angular/ui/surface';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-surface-view',\n imports: [SpSurface],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div\n spSurface\n [frame]=\"'card'\"\n >\n A surface takes the ground: its substrate, its ink and a hand-drawn frame.\n </div>\n `,\n})\nexport class SurfaceView {}\n```\n\n## SpGlyph\n\n`glyph` \xB7 One of the exact glyphs the components draw (tick, cross, arrows, chevrons\u2026). (building-blocks)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpGlyph` | `SpGlyph` | `sp-glyph` | `sp_glyph` |\n| Import | `@silverpoint/react/ui/glyph` | `@silverpoint/vue/ui/glyph` | `@silverpoint/angular/ui/glyph` | `reflex_silverpoint_react` |\n\n**States:** `all`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `glyph` | `string` | | **Required.** A key of `UI_GLYPHS`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpGlyph } from '@silverpoint/react/ui/glyph';\n\nexport function GlyphView() {\n return (\n <SpGlyph\n glyph=\"tick\"\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpGlyph } from '@silverpoint/vue/ui/glyph';\n</script>\n\n<template>\n <SpGlyph\n glyph=\"tick\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpGlyph } from '@silverpoint/angular/ui/glyph';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-glyph-view',\n imports: [SpGlyph],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-glyph\n [glyph]=\"'tick'\"\n />\n `,\n})\nexport class GlyphView {}\n```\n\n## SpTable\n\n`table` \xB7 A data table with sortable columns, stripes and an empty state. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpTable` | `SpTable` | `sp-table` | `sp_table` |\n| Import | `@silverpoint/react/ui/table` | `@silverpoint/vue/ui/table` | `@silverpoint/angular/ui/table` | `reflex_silverpoint_react` |\n\n**Events:** React `onSort`; Vue `sort`; Angular `sort`.\n\n**States:** `plain`, `sorted-striped`, `empty`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `columns` | `readonly TableColumn[]` | | **Required.** The columns, in order; each names the key it reads from a row. |\n| `data` | `readonly Readonly<Record<string, unknown>>[]` | | **Required.** The rows, drawn as given: the consumer sorts them (DD-040). |\n| `caption` | `string` | | The table's `<caption>`, its accessible name. |\n| `sortKey` | `string` | | A sortable column's key; another key sorts nothing, silently. |\n| `sortOrder` | `'asc' \\| 'desc'` | `'asc'` | Default `'asc'`. |\n| `striped` | `boolean` | `false` | Default `false`. |\n| `hoverable` | `boolean` | `true` | Default `true`. |\n| `bordered` | `boolean` | `true` | Default `true`. |\n| `emptyText` | `string` | `'No data'` | Default `'No data'`. |\n| `rowKey` | `string` | | The column whose value keys each row. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTable } from '@silverpoint/react/ui/table';\n\nexport function TableView() {\n return (\n <SpTable\n caption=\"Orders\"\n columns={[{ key: 'order', title: 'Order' }, { key: 'customer', title: 'Customer', sortable: true }, { key: 'status', title: 'Status' }, { key: 'amount', title: 'Amount', align: 'end', sortable: true }]}\n data={[{ order: '1042', customer: 'Ada Lovelace', status: 'Shipped', amount: 128 }, { order: '1043', customer: 'Grace Hopper', status: 'Packed', amount: 64.5 }, { order: '1044', customer: 'Alan Turing', status: 'Paid', amount: 312 }, { order: '1045', customer: 'Emmy Noether', status: 'Placed', amount: 18.25 }, { order: '1046', customer: 'Kurt G\xF6del', status: 'Shipped', amount: 96 }]}\n rowKey=\"order\"\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTable } from '@silverpoint/vue/ui/table';\n</script>\n\n<template>\n <SpTable\n caption=\"Orders\"\n :columns=\"[{ key: 'order', title: 'Order' }, { key: 'customer', title: 'Customer', sortable: true }, { key: 'status', title: 'Status' }, { key: 'amount', title: 'Amount', align: 'end', sortable: true }]\"\n :data=\"[{ order: '1042', customer: 'Ada Lovelace', status: 'Shipped', amount: 128 }, { order: '1043', customer: 'Grace Hopper', status: 'Packed', amount: 64.5 }, { order: '1044', customer: 'Alan Turing', status: 'Paid', amount: 312 }, { order: '1045', customer: 'Emmy Noether', status: 'Placed', amount: 18.25 }, { order: '1046', customer: 'Kurt G\xF6del', status: 'Shipped', amount: 96 }]\"\n rowKey=\"order\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpTable } from '@silverpoint/angular/ui/table';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-table-view',\n imports: [SpTable],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-table\n [caption]=\"'Orders'\"\n [columns]=\"[{ key: 'order', title: 'Order' }, { key: 'customer', title: 'Customer', sortable: true }, { key: 'status', title: 'Status' }, { key: 'amount', title: 'Amount', align: 'end', sortable: true }]\"\n [data]=\"[{ order: '1042', customer: 'Ada Lovelace', status: 'Shipped', amount: 128 }, { order: '1043', customer: 'Grace Hopper', status: 'Packed', amount: 64.5 }, { order: '1044', customer: 'Alan Turing', status: 'Paid', amount: 312 }, { order: '1045', customer: 'Emmy Noether', status: 'Placed', amount: 18.25 }, { order: '1046', customer: 'Kurt G\xF6del', status: 'Shipped', amount: 96 }]\"\n [rowKey]=\"'order'\"\n />\n `,\n})\nexport class TableView {}\n```\n\n## SpPagination\n\n`pagination` \xB7 Page navigation with a current page, siblings and an optional total. (navigation)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpPagination` | `SpPagination` | `sp-pagination` | `sp_pagination` |\n| Import | `@silverpoint/react/ui/pagination` | `@silverpoint/vue/ui/pagination` | `@silverpoint/angular/ui/pagination` | `reflex_silverpoint_react` |\n\n**Value:** React `current + onChange`, Vue `v-model:current`, Angular `[(current)]`.\n\n**Events:** React `onChange`; Vue ; Angular .\n\n**States:** `middle`, `total`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `total` | `number` | | **Required.** The number of items paged over. |\n| `pageSize` | `number` | `10` | Default `10`. |\n| `siblings` | `number` | `1` | Pages shown on each side of the current one. Default `1`. |\n| `showTotal` | `boolean` | `false` | Default `false`. |\n| `totalTemplate` | `string` | `'{start}\u2013{end} of {total}'` | Default `'{start}\u2013{end} of {total}'`. |\n| `label` | `string` | `'Pagination'` | Default `'Pagination'`. |\n| `previousLabel` | `string` | `'Previous page'` | Default `'Previous page'`. |\n| `nextLabel` | `string` | `'Next page'` | Default `'Next page'`. |\n| `pageLabel` | `string` | `'Page'` | Default `'Page'`. |\n| `disabled` | `boolean` | | Every page button disabled. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpPagination } from '@silverpoint/react/ui/pagination';\n\nexport function PaginationView() {\n const [value, setValue] = useState<number>(10);\n return (\n <SpPagination\n total={200}\n pageSize={10}\n current={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpPagination } from '@silverpoint/vue/ui/pagination';\n\nconst value = ref<number>(10);\n</script>\n\n<template>\n <SpPagination\n :total=\"200\"\n :pageSize=\"10\"\n v-model:current=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpPagination } from '@silverpoint/angular/ui/pagination';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-pagination-view',\n imports: [SpPagination],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-pagination\n [total]=\"200\"\n [pageSize]=\"10\"\n [(current)]=\"value\"\n />\n `,\n})\nexport class PaginationView {\n protected readonly value = signal<number>(10);\n}\n```\n\n## SpBreadcrumb\n\n`breadcrumb` \xB7 The trail of pages to the current one. (navigation)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpBreadcrumb` | `SpBreadcrumb` | `sp-breadcrumb` | `sp_breadcrumb` |\n| Import | `@silverpoint/react/ui/breadcrumb` | `@silverpoint/vue/ui/breadcrumb` | `@silverpoint/angular/ui/breadcrumb` | `reflex_silverpoint_react` |\n\n**States:** `three`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly BreadcrumbItem[]` | | **Required.** The last item is the current page. |\n| `label` | `string` | `'Breadcrumb'` | Default `'Breadcrumb'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpBreadcrumb } from '@silverpoint/react/ui/breadcrumb';\n\nexport function BreadcrumbView() {\n return (\n <SpBreadcrumb\n items={[{ key: 'home', label: 'Home', href: '/' }, { key: 'orders', label: 'Orders', href: '/orders' }, { key: '1042', label: 'Order 1042' }]}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpBreadcrumb } from '@silverpoint/vue/ui/breadcrumb';\n</script>\n\n<template>\n <SpBreadcrumb\n :items=\"[{ key: 'home', label: 'Home', href: '/' }, { key: 'orders', label: 'Orders', href: '/orders' }, { key: '1042', label: 'Order 1042' }]\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpBreadcrumb } from '@silverpoint/angular/ui/breadcrumb';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-breadcrumb-view',\n imports: [SpBreadcrumb],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-breadcrumb\n [items]=\"[{ key: 'home', label: 'Home', href: '/' }, { key: 'orders', label: 'Orders', href: '/orders' }, { key: '1042', label: 'Order 1042' }]\"\n />\n `,\n})\nexport class BreadcrumbView {}\n```\n\n## SpAvatar\n\n`avatar` \xB7 A picture or initials in a round or square frame; `SpAvatarGroup` stacks several. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpAvatar` | `SpAvatar` | `sp-avatar` | `sp_avatar` |\n| Import | `@silverpoint/react/ui/avatar` | `@silverpoint/vue/ui/avatar` | `@silverpoint/angular/ui/avatar` | `reflex_silverpoint_react` |\n\n**States:** `initials`, `square`, `group`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `src` | `string` | | An image; the initials are drawn without one. |\n| `name` | `string` | | The person's name: the accessible name and the source of the initials. |\n| `initials` | `string` | | Overrides the initials derived from `name`. |\n| `alt` | `string` | | Overrides `name` as the accessible name. |\n| `shape` | `'circle' \\| 'square'` | `'circle'` | Default `'circle'`. |\n| `pixelSize` | `number` | | Side length in px; the ground's control height when omitted. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpAvatar } from '@silverpoint/react/ui/avatar';\n\nexport function AvatarView() {\n return (\n <SpAvatar\n name=\"Ada Lovelace\"\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpAvatar } from '@silverpoint/vue/ui/avatar';\n</script>\n\n<template>\n <SpAvatar\n name=\"Ada Lovelace\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpAvatar } from '@silverpoint/angular/ui/avatar';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-avatar-view',\n imports: [SpAvatar],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-avatar\n [name]=\"'Ada Lovelace'\"\n />\n `,\n})\nexport class AvatarView {}\n```\n\n## SpStatistic\n\n`statistic` \xB7 A titled figure with a prefix, a suffix and an optional trend. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpStatistic` | `SpStatistic` | `sp-statistic` | `sp_statistic` |\n| Import | `@silverpoint/react/ui/statistic` | `@silverpoint/vue/ui/statistic` | `@silverpoint/angular/ui/statistic` | `reflex_silverpoint_react` |\n\n**States:** `plain`, `trend-down`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `title` | `string` | | **Required.** The label above the value. |\n| `value` | `string \\| number` | | **Required.** Printed as given. |\n| `prefix` | `string` | | Printed before the value (`$`). |\n| `suffix` | `string` | | Printed after the value (`%`). |\n| `trend` | `'up' \\| 'down'` | | Draws the exact \u2191 or \u2193 glyph beside the delta. |\n| `delta` | `string` | | The change, as text (`+4.2%`). |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpStatistic } from '@silverpoint/react/ui/statistic';\n\nexport function StatisticView() {\n return (\n <SpStatistic\n title=\"Orders\"\n value={1284}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpStatistic } from '@silverpoint/vue/ui/statistic';\n</script>\n\n<template>\n <SpStatistic\n title=\"Orders\"\n :value=\"1284\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpStatistic } from '@silverpoint/angular/ui/statistic';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-statistic-view',\n imports: [SpStatistic],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-statistic\n [title]=\"'Orders'\"\n [value]=\"1284\"\n />\n `,\n})\nexport class StatisticView {}\n```\n\n## SpDescriptions\n\n`descriptions` \xB7 Label and value pairs as a description list. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpDescriptions` | `SpDescriptions` | `sp-descriptions` | `sp_descriptions` |\n| Import | `@silverpoint/react/ui/descriptions` | `@silverpoint/vue/ui/descriptions` | `@silverpoint/angular/ui/descriptions` | `reflex_silverpoint_react` |\n\n**States:** `bordered`, `plain`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly DescriptionItem[]` | | **Required.** The label\u2013value pairs, a `<dl>`. Keys, when given, are unique (REQ-325). |\n| `title` | `string` | | A heading above the list, at `headingLevel`. |\n| `columns` | `number` | `3` | Default `3`, in 1..6. |\n| `bordered` | `boolean` | `true` | Default `true`. |\n| `headingLevel` | `2 \\| 3 \\| 4 \\| 5 \\| 6` | `3` | Default `3`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDescriptions } from '@silverpoint/react/ui/descriptions';\n\nexport function DescriptionsView() {\n return (\n <SpDescriptions\n title=\"Order 1042\"\n items={[{ key: 'customer', label: 'Customer', value: 'Ada Lovelace' }, { key: 'status', label: 'Status', value: 'Shipped' }, { key: 'amount', label: 'Amount', value: '128.00' }, { key: 'placed', label: 'Placed', value: '14 October 2026' }]}\n columns={2}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDescriptions } from '@silverpoint/vue/ui/descriptions';\n</script>\n\n<template>\n <SpDescriptions\n title=\"Order 1042\"\n :items=\"[{ key: 'customer', label: 'Customer', value: 'Ada Lovelace' }, { key: 'status', label: 'Status', value: 'Shipped' }, { key: 'amount', label: 'Amount', value: '128.00' }, { key: 'placed', label: 'Placed', value: '14 October 2026' }]\"\n :columns=\"2\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpDescriptions } from '@silverpoint/angular/ui/descriptions';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-descriptions-view',\n imports: [SpDescriptions],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-descriptions\n [title]=\"'Order 1042'\"\n [items]=\"[{ key: 'customer', label: 'Customer', value: 'Ada Lovelace' }, { key: 'status', label: 'Status', value: 'Shipped' }, { key: 'amount', label: 'Amount', value: '128.00' }, { key: 'placed', label: 'Placed', value: '14 October 2026' }]\"\n [columns]=\"2\"\n />\n `,\n})\nexport class DescriptionsView {}\n```\n\n## SpTimelineList\n\n`timeline-list` \xB7 Events in order, each done, current, pending or in error. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpTimelineList` | `SpTimelineList` | `sp-timeline-list` | `sp_timeline_list` |\n| Import | `@silverpoint/react/ui/timeline-list` | `@silverpoint/vue/ui/timeline-list` | `@silverpoint/angular/ui/timeline-list` | `reflex_silverpoint_react` |\n\n**States:** `mixed`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly TimelineListItem[]` | | **Required.** The events, in reading order. |\n| `label` | `string` | | Accessible name of the list. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTimelineList } from '@silverpoint/react/ui/timeline-list';\n\nexport function TimelineListView() {\n return (\n <SpTimelineList\n label=\"Order history\"\n items={[{ key: 'placed', title: 'Placed', time: '14 Oct, 09:12', description: 'Two prints, one framed.' }, { key: 'paid', title: 'Payment', time: '14 Oct, 09:14', description: 'Card declined; paid on the second try.', status: 'error' }, { key: 'packed', title: 'Packed', time: '15 Oct, 16:40', status: 'current' }, { key: 'shipped', title: 'Shipped', status: 'pending' }]}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTimelineList } from '@silverpoint/vue/ui/timeline-list';\n</script>\n\n<template>\n <SpTimelineList\n label=\"Order history\"\n :items=\"[{ key: 'placed', title: 'Placed', time: '14 Oct, 09:12', description: 'Two prints, one framed.' }, { key: 'paid', title: 'Payment', time: '14 Oct, 09:14', description: 'Card declined; paid on the second try.', status: 'error' }, { key: 'packed', title: 'Packed', time: '15 Oct, 16:40', status: 'current' }, { key: 'shipped', title: 'Shipped', status: 'pending' }]\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpTimelineList } from '@silverpoint/angular/ui/timeline-list';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-timeline-list-view',\n imports: [SpTimelineList],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-timeline-list\n [label]=\"'Order history'\"\n [items]=\"[{ key: 'placed', title: 'Placed', time: '14 Oct, 09:12', description: 'Two prints, one framed.' }, { key: 'paid', title: 'Payment', time: '14 Oct, 09:14', description: 'Card declined; paid on the second try.', status: 'error' }, { key: 'packed', title: 'Packed', time: '15 Oct, 16:40', status: 'current' }, { key: 'shipped', title: 'Shipped', status: 'pending' }]\"\n />\n `,\n})\nexport class TimelineListView {}\n```\n\n## SpCollapse\n\n`collapse` \xB7 Disclosure panels (`SpCollapseItem`), optionally as an accordion. (disclosure)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpCollapse` | `SpCollapse` | `sp-collapse` | `sp_collapse` |\n| Import | `@silverpoint/react/ui/collapse` | `@silverpoint/vue/ui/collapse` | `@silverpoint/angular/ui/collapse` | `reflex_silverpoint_react` |\n\n**Content:** React `children`; Vue `default`; Angular `content`.\n\n**States:** `one-open`, `accordion-disabled`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `accordion` | `boolean` | `false` | One item open at a time, natively (`<details name>`). Default `false`. |\n| `bordered` | `boolean` | `true` | Default `true`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpCollapse } from '@silverpoint/react/ui/collapse';\n\nexport function CollapseView() {\n return (\n <SpCollapse />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpCollapse } from '@silverpoint/vue/ui/collapse';\n</script>\n\n<template>\n <SpCollapse />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpCollapse } from '@silverpoint/angular/ui/collapse';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-collapse-view',\n imports: [SpCollapse],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-collapse />\n `,\n})\nexport class CollapseView {}\n```\n\n## SpEmpty\n\n`empty` \xB7 The empty state of a list or a table. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpEmpty` | `SpEmpty` | `sp-empty` | `sp_empty` |\n| Import | `@silverpoint/react/ui/empty` | `@silverpoint/vue/ui/empty` | `@silverpoint/angular/ui/empty` | `reflex_silverpoint_react` |\n\n**Content:** React `extra`; Vue `extra`; Angular `spExtra`.\n\n**States:** `plain`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `description` | `string` | `'No data'` | Default `'No data'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpEmpty } from '@silverpoint/react/ui/empty';\n\nexport function EmptyView() {\n return (\n <SpEmpty\n description=\"No orders yet\"\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpEmpty } from '@silverpoint/vue/ui/empty';\n</script>\n\n<template>\n <SpEmpty\n description=\"No orders yet\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpEmpty } from '@silverpoint/angular/ui/empty';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-empty-view',\n imports: [SpEmpty],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-empty\n [description]=\"'No orders yet'\"\n />\n `,\n})\nexport class EmptyView {}\n```\n\n## SpResult\n\n`result` \xB7 The outcome of an action: success, error, information or warning. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpResult` | `SpResult` | `sp-result` | `sp_result` |\n| Import | `@silverpoint/react/ui/result` | `@silverpoint/vue/ui/result` | `@silverpoint/angular/ui/result` | `reflex_silverpoint_react` |\n\n**Content:** React `extra`; Vue `extra`; Angular `spExtra`.\n\n**States:** `success`, `error`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `status` | `AlertKind` | `'info'` | Default `'info'`. |\n| `title` | `string` | | **Required.** The heading, at `headingLevel`. |\n| `subtitle` | `string` | | A paragraph under the title. |\n| `headingLevel` | `2 \\| 3 \\| 4 \\| 5 \\| 6` | `3` | Default `3`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpResult } from '@silverpoint/react/ui/result';\n\nexport function ResultView() {\n return (\n <SpResult\n status=\"success\"\n title=\"Order placed\"\n subtitle=\"Order 1042 is on its way to the workshop.\"\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpResult } from '@silverpoint/vue/ui/result';\n</script>\n\n<template>\n <SpResult\n status=\"success\"\n title=\"Order placed\"\n subtitle=\"Order 1042 is on its way to the workshop.\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpResult } from '@silverpoint/angular/ui/result';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-result-view',\n imports: [SpResult],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-result\n [status]=\"'success'\"\n [title]=\"'Order placed'\"\n [subtitle]=\"'Order 1042 is on its way to the workshop.'\"\n />\n `,\n})\nexport class ResultView {}\n```\n\n## SpTextarea\n\n`textarea` \xB7 A multi-line text field with a counter and an invalid state. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpTextarea` | `SpTextarea` | `sp-textarea` | `sp_textarea` |\n| Import | `@silverpoint/react/ui/textarea` | `@silverpoint/vue/ui/textarea` | `@silverpoint/angular/ui/textarea` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**States:** `count`, `invalid`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `rows` | `number` | `3` | Default `3`. |\n| `placeholder` | `string` | | Hint shown while empty; not a substitute for the accessible name. |\n| `label` | `string` | | Accessible name, when no `<label for>` names the control. |\n| `message` | `string` | | Help or error text under the control, referenced by `aria-describedby` (REQ-334). |\n| `invalid` | `boolean` | | Sets `aria-invalid` and draws the exact \u26A0 glyph (REQ-334). |\n| `disabled` | `boolean` | | Not focusable and not submitted. |\n| `readOnly` | `boolean` | | Focusable and submitted, but not editable. |\n| `maxLength` | `number` | | The native limit; the counter shows it with `showCount`. |\n| `showCount` | `boolean` | `false` | Default `false`. |\n| `name` | `string` | | Form field name; the native textarea submits under it (REQ-323). |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpTextarea } from '@silverpoint/react/ui/textarea';\n\nexport function TextareaView() {\n const [value, setValue] = useState<string>('Leave it at the door.');\n return (\n <SpTextarea\n label=\"Notes\"\n name=\"notes\"\n maxLength={120}\n showCount={true}\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpTextarea } from '@silverpoint/vue/ui/textarea';\n\nconst value = ref<string>('Leave it at the door.');\n</script>\n\n<template>\n <SpTextarea\n label=\"Notes\"\n name=\"notes\"\n :maxLength=\"120\"\n :showCount=\"true\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpTextarea } from '@silverpoint/angular/ui/textarea';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-textarea-view',\n imports: [SpTextarea],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-textarea\n [label]=\"'Notes'\"\n [name]=\"'notes'\"\n [maxLength]=\"120\"\n [showCount]=\"true\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class TextareaView {\n protected readonly value = signal<string>('Leave it at the door.');\n}\n```\n\n## SpInputNumber\n\n`input-number` \xB7 A number field with steppers, bounds and precision. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpInputNumber` | `SpInputNumber` | `sp-input-number` | `sp_input_number` |\n| Import | `@silverpoint/react/ui/input-number` | `@silverpoint/vue/ui/input-number` | `@silverpoint/angular/ui/input-number` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue ; Angular .\n\n**States:** `value`, `at-min`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `min` | `number` | | The lowest value; the value is clamped to it (REQ-485). |\n| `max` | `number` | | The highest value; the value is clamped to it (REQ-485). |\n| `step` | `number` | `1` | Default `1`. |\n| `precision` | `number` | | Decimals. |\n| `placeholder` | `string` | | Hint shown while empty; not a substitute for the accessible name. |\n| `label` | `string` | | Accessible name, when no `<label for>` names the control. |\n| `message` | `string` | | Help or error text under the control, referenced by `aria-describedby` (REQ-334). |\n| `invalid` | `boolean` | | Sets `aria-invalid` and draws the exact \u26A0 glyph (REQ-334). |\n| `disabled` | `boolean` | | Not focusable and not submitted; the steppers are disabled too. |\n| `readOnly` | `boolean` | | Focusable and submitted, but not editable. |\n| `name` | `string` | | Form field name; the native input submits under it (REQ-323). |\n| `decrementLabel` | `string` | `'Decrease'` | Default `'Decrease'`. |\n| `incrementLabel` | `string` | `'Increase'` | Default `'Increase'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpInputNumber } from '@silverpoint/react/ui/input-number';\n\nexport function InputNumberView() {\n const [value, setValue] = useState<number | null>(3);\n return (\n <SpInputNumber\n label=\"Quantity\"\n name=\"quantity\"\n min={1}\n max={10}\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpInputNumber } from '@silverpoint/vue/ui/input-number';\n\nconst value = ref<number | null>(3);\n</script>\n\n<template>\n <SpInputNumber\n label=\"Quantity\"\n name=\"quantity\"\n :min=\"1\"\n :max=\"10\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpInputNumber } from '@silverpoint/angular/ui/input-number';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-input-number-view',\n imports: [SpInputNumber],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-input-number\n [label]=\"'Quantity'\"\n [name]=\"'quantity'\"\n [min]=\"1\"\n [max]=\"10\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class InputNumberView {\n protected readonly value = signal<number | null>(3);\n}\n```\n",
11419
- "overlays": "<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Overlays\n\n*Describes silverpoint 0.7.0.*\n\nModal, Drawer, Popover, Tooltip, Select, DropdownMenu and Toast are built on the platform's\n`<dialog>` and Popover API. They are client components only.\n\n## The trigger is a native button\n\nGive every overlay a native `<button type=\"button\">` as its trigger:\n\n- **React:** the `trigger` prop, `trigger={<button type=\"button\">Edit</button>}`. The overlay\n clones it with its ARIA and its toggle. Do not pass `SpButton`: it drops the ARIA it is given.\n- **Vue:** the `trigger` slot, `<template #trigger><button type=\"button\">Edit</button></template>`.\n Its first element is cloned.\n- **Angular:** project the button with the `spTrigger` directive,\n `<button type=\"button\" spTrigger>Edit</button>`, and import `SpTrigger` from the overlay's own\n subpath.\n\n## Open state\n\n| | Controlled | Uncontrolled | Change |\n|---|---|---|---|\n| React | `open` | `defaultOpen` | `onOpenChange(open)` |\n| Vue | `v-model:open` | `default-open` | `update:open` |\n| Angular | `[(open)]` | `[defaultOpen]` | `(openChange)` |\n\n`onOpenChange` also fires when the platform closes it: Escape, or a click outside. A Modal with\n`dismissible={false}` ignores both.\n\n## Toasts\n\nPut one `SpToaster` near the root and render `SpToast` children inside it. A toast closes after the\ntoaster's `duration` (5000 ms) unless its own `duration` says otherwise. It pauses while hovered or\nfocused, and F8 moves focus to the toaster.\n\n## Sides\n\nSides are logical, `start` and `end`, so they mirror in right-to-left pages. Reflex's `left` and\n`right` become `start` and `end`.\n\n**Contents:** [SpModal](#spmodal) \xB7 [SpDrawer](#spdrawer) \xB7 [SpPopover](#sppopover) \xB7 [SpTooltip](#sptooltip) \xB7 [SpSelect](#spselect) \xB7 [SpDropdownMenu](#spdropdownmenu) \xB7 [SpToast](#sptoast)\n\n## SpModal\n\n`modal` \xB7 A modal dialog on the native `<dialog>`, opened by its trigger. (overlays)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpModal` | `SpModal` | `sp-modal` | `sp_modal` |\n| Import | `@silverpoint/react/ui/modal` | `@silverpoint/vue/ui/modal` | `@silverpoint/angular/ui/modal` | `reflex_silverpoint_react` |\n\n**Open state:** React `open + onOpenChange`, Vue `v-model:open`, Angular `[(open)]`.\n\n**Events:** React `onOpenChange`; Vue ; Angular .\n\n**Content:** React `children`, `footer`, `trigger`; Vue `default`, `footer`, `trigger`; Angular `content`, `spFooter`, `spTrigger`.\n\n**States:** `open`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `title` | `string` | | The heading, `${id}--title`, that names the dialog. |\n| `description` | `string` | | A paragraph, `${id}--description`, that describes the dialog. |\n| `label` | `string` | | Accessible name without a title (REQ-501). |\n| `closable` | `boolean` | `true` | Default `true`. |\n| `closeLabel` | `string` | `'Close'` | Default `'Close'`. |\n| `width` | `string` | `'520px'` | CSS length. Default `'520px'` (from `ui.css`). |\n| `dismissible` | `boolean` | `true` | Escape and a backdrop click close it. Default `true`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpModal } from '@silverpoint/react/ui/modal';\n\nexport function ModalView() {\n return (\n <SpModal\n title=\"Edit order\"\n description=\"Order 1042, placed on 14 October.\"\n trigger={<button type=\"button\">Edit order</button>}\n >\n Changes reach the workshop before the order is packed.\n </SpModal>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpModal } from '@silverpoint/vue/ui/modal';\n</script>\n\n<template>\n <SpModal\n title=\"Edit order\"\n description=\"Order 1042, placed on 14 October.\"\n >\n <template #trigger><button type=\"button\">Edit order</button></template>\n Changes reach the workshop before the order is packed.\n </SpModal>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpModal, SpTrigger } from '@silverpoint/angular/ui/modal';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-modal-view',\n imports: [SpModal, SpTrigger],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-modal\n [title]=\"'Edit order'\"\n [description]=\"'Order 1042, placed on 14 October.'\"\n >\n <button type=\"button\" spTrigger>Edit order</button>\n Changes reach the workshop before the order is packed.\n </sp-modal>\n `,\n})\nexport class ModalView {}\n```\n\n## SpDrawer\n\n`drawer` \xB7 A dialog sliding in from one side of the viewport. (overlays)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpDrawer` | `SpDrawer` | `sp-drawer` | `sp_drawer` |\n| Import | `@silverpoint/react/ui/drawer` | `@silverpoint/vue/ui/drawer` | `@silverpoint/angular/ui/drawer` | `reflex_silverpoint_react` |\n\n**Open state:** React `open + onOpenChange`, Vue `v-model:open`, Angular `[(open)]`.\n\n**Events:** React `onOpenChange`; Vue ; Angular .\n\n**Content:** React `children`, `footer`, `trigger`; Vue `default`, `footer`, `trigger`; Angular `content`, `spFooter`, `spTrigger`.\n\n**States:** `end-open`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `side` | `'start' \\| 'end' \\| 'top' \\| 'bottom'` | `'end'` | Default `'end'`. |\n| `extent` | `string` | `'380px'` | CSS length across the side. Default `'380px'` (start/end) or `'320px'` (top/bottom). |\n| `modal` | `boolean` | `true` | `false` opens with `show()`. Default `true`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDrawer } from '@silverpoint/react/ui/drawer';\n\nexport function DrawerView() {\n return (\n <SpDrawer\n side=\"end\"\n trigger={<button type=\"button\">Filters</button>}\n >\n Narrow the orders by status, customer or amount.\n </SpDrawer>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDrawer } from '@silverpoint/vue/ui/drawer';\n</script>\n\n<template>\n <SpDrawer\n side=\"end\"\n >\n <template #trigger><button type=\"button\">Filters</button></template>\n Narrow the orders by status, customer or amount.\n </SpDrawer>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpDrawer, SpTrigger } from '@silverpoint/angular/ui/drawer';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-drawer-view',\n imports: [SpDrawer, SpTrigger],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-drawer\n [side]=\"'end'\"\n >\n <button type=\"button\" spTrigger>Filters</button>\n Narrow the orders by status, customer or amount.\n </sp-drawer>\n `,\n})\nexport class DrawerView {}\n```\n\n## SpPopover\n\n`popover` \xB7 Non-modal content anchored to its trigger, on the Popover API. (overlays)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpPopover` | `SpPopover` | `sp-popover` | `sp_popover` |\n| Import | `@silverpoint/react/ui/popover` | `@silverpoint/vue/ui/popover` | `@silverpoint/angular/ui/popover` | `reflex_silverpoint_react` |\n\n**Open state:** React `open + onOpenChange`, Vue `v-model:open`, Angular `[(open)]`.\n\n**Events:** React `onOpenChange`; Vue ; Angular .\n\n**Content:** React `children`, `trigger`; Vue `default`, `trigger`; Angular `content`, `spTrigger`.\n\n**States:** `open`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `title` | `string` | | A heading that names the popover. |\n| `label` | `string` | | Accessible name without a title. |\n| `side` | `'top' \\| 'end' \\| 'bottom' \\| 'start'` | `'bottom'` | Default `'bottom'`. |\n| `align` | `'start' \\| 'center' \\| 'end'` | `'center'` | Default `'center'`. |\n| `offset` | `number` | `6` | Default `6`. |\n| `closable` | `boolean` | `false` | Default `false`. |\n| `closeLabel` | `string` | `'Close'` | Default `'Close'`. |\n| `width` | `string` | `'320px'` | CSS length. Default `'320px'` (from `ui.css`). |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpPopover } from '@silverpoint/react/ui/popover';\n\nexport function PopoverView() {\n return (\n <SpPopover\n title=\"Order 1042\"\n trigger={<button type=\"button\">Details</button>}\n >\n Two prints, one framed; shipped on 16 October.\n </SpPopover>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpPopover } from '@silverpoint/vue/ui/popover';\n</script>\n\n<template>\n <SpPopover\n title=\"Order 1042\"\n >\n <template #trigger><button type=\"button\">Details</button></template>\n Two prints, one framed; shipped on 16 October.\n </SpPopover>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpPopover, SpTrigger } from '@silverpoint/angular/ui/popover';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-popover-view',\n imports: [SpPopover, SpTrigger],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-popover\n [title]=\"'Order 1042'\"\n >\n <button type=\"button\" spTrigger>Details</button>\n Two prints, one framed; shipped on 16 October.\n </sp-popover>\n `,\n})\nexport class PopoverView {}\n```\n\n## SpTooltip\n\n`tooltip` \xB7 A short text shown on hover or focus of its trigger. (overlays)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpTooltip` | `SpTooltip` | `sp-tooltip` | `sp_tooltip` |\n| Import | `@silverpoint/react/ui/tooltip` | `@silverpoint/vue/ui/tooltip` | `@silverpoint/angular/ui/tooltip` | `reflex_silverpoint_react` |\n\n**Open state:** React `open + onOpenChange`, Vue `v-model:open`, Angular `[(open)]`.\n\n**Events:** React `onOpenChange`; Vue ; Angular .\n\n**Content:** React `trigger`; Vue `trigger`; Angular `spTrigger`.\n\n**States:** `open`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `text` | `string` | | **Required.** The tooltip, the trigger's accessible description. |\n| `side` | `'top' \\| 'end' \\| 'bottom' \\| 'start'` | `'top'` | Default `'top'`. |\n| `align` | `'start' \\| 'center' \\| 'end'` | `'center'` | Default `'center'`. |\n| `offset` | `number` | `6` | Default `6`. |\n| `delay` | `number` | `300` | Default `300` ms. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTooltip } from '@silverpoint/react/ui/tooltip';\n\nexport function TooltipView() {\n return (\n <SpTooltip\n text=\"Copy the order id\"\n trigger={<button type=\"button\">Copy id</button>}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTooltip } from '@silverpoint/vue/ui/tooltip';\n</script>\n\n<template>\n <SpTooltip\n text=\"Copy the order id\"\n >\n <template #trigger><button type=\"button\">Copy id</button></template>\n </SpTooltip>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpTooltip, SpTrigger } from '@silverpoint/angular/ui/tooltip';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-tooltip-view',\n imports: [SpTooltip, SpTrigger],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-tooltip\n [text]=\"'Copy the order id'\"\n >\n <button type=\"button\" spTrigger>Copy id</button>\n </sp-tooltip>\n `,\n})\nexport class TooltipView {}\n```\n\n## SpSelect\n\n`select` \xB7 A select-only combobox: one option from a list. (overlays)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpSelect` | `SpSelect` | `sp-select` | `sp_select` |\n| Import | `@silverpoint/react/ui/select` | `@silverpoint/vue/ui/select` | `@silverpoint/angular/ui/select` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Open state:** React `open + onOpenChange`, Vue `v-model:open`, Angular `[(open)]`.\n\n**Events:** React `onChange`, `onOpenChange`; Vue ; Angular .\n\n**States:** `placeholder`, `open-selected`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly (string \\| UiItem)[]` | | **Required.** A string is its own key and label. |\n| `placeholder` | `string` | `'Select\u2026'` | Default `'Select\u2026'`. |\n| `label` | `string` | | **Required.** Accessible name of the combobox. |\n| `disabled` | `boolean` | | Not focusable and not submitted. |\n| `required` | `boolean` | | Sets `aria-required` on the combobox. |\n| `name` | `string` | | Submits the key under this name, from a hidden input (REQ-323). |\n| `width` | `string` | `'180px'` | CSS length. Default `'180px'` (from `ui.css`). |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpSelect } from '@silverpoint/react/ui/select';\n\nexport function SelectView() {\n const [value, setValue] = useState<string | undefined>(undefined);\n return (\n <SpSelect\n label=\"Status\"\n name=\"status\"\n items={[{ key: 'placed', label: 'Placed' }, { key: 'paid', label: 'Paid' }, { key: 'packed', label: 'Packed' }, { key: 'shipped', label: 'Shipped' }, { key: 'returned', label: 'Returned', disabled: true }]}\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpSelect } from '@silverpoint/vue/ui/select';\n\nconst value = ref<string>();\n</script>\n\n<template>\n <SpSelect\n label=\"Status\"\n name=\"status\"\n :items=\"[{ key: 'placed', label: 'Placed' }, { key: 'paid', label: 'Paid' }, { key: 'packed', label: 'Packed' }, { key: 'shipped', label: 'Shipped' }, { key: 'returned', label: 'Returned', disabled: true }]\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpSelect } from '@silverpoint/angular/ui/select';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-select-view',\n imports: [SpSelect],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-select\n [label]=\"'Status'\"\n [name]=\"'status'\"\n [items]=\"[{ key: 'placed', label: 'Placed' }, { key: 'paid', label: 'Paid' }, { key: 'packed', label: 'Packed' }, { key: 'shipped', label: 'Shipped' }, { key: 'returned', label: 'Returned', disabled: true }]\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class SelectView {\n protected readonly value = signal<string | undefined>(undefined);\n}\n```\n\n## SpDropdownMenu\n\n`dropdown-menu` \xB7 A menu of actions opened from its trigger. (overlays)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpDropdownMenu` | `SpDropdownMenu` | `sp-dropdown-menu` | `sp_dropdown_menu` |\n| Import | `@silverpoint/react/ui/dropdown-menu` | `@silverpoint/vue/ui/dropdown-menu` | `@silverpoint/angular/ui/dropdown-menu` | `reflex_silverpoint_react` |\n\n**Open state:** React `open + onOpenChange`, Vue `v-model:open`, Angular `[(open)]`.\n\n**Events:** React `onOpenChange`, `onSelect`; Vue `select`; Angular `select`.\n\n**Content:** React `trigger`; Vue `trigger`; Angular `spTrigger`.\n\n**States:** `open`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly MenuEntry[]` | | **Required.** Items, separators and labels, in order. Keys are unique (REQ-325). |\n| `label` | `string` | | **Required.** The menu's accessible name and the trigger's text when no trigger slot. |\n| `side` | `'top' \\| 'end' \\| 'bottom' \\| 'start'` | `'bottom'` | Default `'bottom'`. |\n| `align` | `'start' \\| 'center' \\| 'end'` | `'start'` | Default `'start'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDropdownMenu } from '@silverpoint/react/ui/dropdown-menu';\n\nexport function DropdownMenuView() {\n return (\n <SpDropdownMenu\n label=\"Actions\"\n items={[{ type: 'label', key: 'order', label: 'Order 1042' }, { key: 'edit', label: 'Edit', shortcut: 'E' }, { key: 'duplicate', label: 'Duplicate', shortcut: 'D' }, { key: 'archive', label: 'Archive', disabled: true }, { type: 'separator', key: 'end' }, { key: 'delete', label: 'Delete', danger: true }]}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDropdownMenu } from '@silverpoint/vue/ui/dropdown-menu';\n</script>\n\n<template>\n <SpDropdownMenu\n label=\"Actions\"\n :items=\"[{ type: 'label', key: 'order', label: 'Order 1042' }, { key: 'edit', label: 'Edit', shortcut: 'E' }, { key: 'duplicate', label: 'Duplicate', shortcut: 'D' }, { key: 'archive', label: 'Archive', disabled: true }, { type: 'separator', key: 'end' }, { key: 'delete', label: 'Delete', danger: true }]\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpDropdownMenu } from '@silverpoint/angular/ui/dropdown-menu';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-dropdown-menu-view',\n imports: [SpDropdownMenu],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-dropdown-menu\n [label]=\"'Actions'\"\n [items]=\"[{ type: 'label', key: 'order', label: 'Order 1042' }, { key: 'edit', label: 'Edit', shortcut: 'E' }, { key: 'duplicate', label: 'Duplicate', shortcut: 'D' }, { key: 'archive', label: 'Archive', disabled: true }, { type: 'separator', key: 'end' }, { key: 'delete', label: 'Delete', danger: true }]\"\n />\n `,\n})\nexport class DropdownMenuView {}\n```\n\n## SpToast\n\n`toast` \xB7 A transient message in a `SpToaster`, with an optional action. (overlays)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpToast` | `SpToast` | `sp-toast` | `sp_toast` |\n| Import | `@silverpoint/react/ui/toast` | `@silverpoint/vue/ui/toast` | `@silverpoint/angular/ui/toast` | `reflex_silverpoint_react` |\n\n**Open state:** React `open + onOpenChange`, Vue `v-model:open`, Angular `[(open)]`.\n\n**Events:** React `onOpenChange`; Vue ; Angular .\n\n**Content:** React `action`; Vue `action`; Angular `spAction`.\n\n**States:** `info`, `error-action`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `title` | `string` | | **Required.** The toast's first line. |\n| `description` | `string` | | A line under the title. |\n| `kind` | `AlertKind` | `'info'` | Default `'info'`. |\n| `duration` | `number` | | ms, at least 1000, or `Infinity`; the toaster's when omitted. |\n| `closeLabel` | `string` | `'Dismiss'` | Default `'Dismiss'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpToast } from '@silverpoint/react/ui/toast';\n\nexport function ToastView() {\n const [open, setOpen] = useState<boolean>(true);\n return (\n <SpToast\n kind=\"info\"\n title=\"Order saved\"\n description=\"Order 1042 was updated.\"\n open={open}\n onOpenChange={setOpen}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpToast } from '@silverpoint/vue/ui/toast';\n\nconst open = ref<boolean>(true);\n</script>\n\n<template>\n <SpToast\n kind=\"info\"\n title=\"Order saved\"\n description=\"Order 1042 was updated.\"\n v-model:open=\"open\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpToast } from '@silverpoint/angular/ui/toast';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-toast-view',\n imports: [SpToast],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-toast\n [kind]=\"'info'\"\n [title]=\"'Order saved'\"\n [description]=\"'Order 1042 was updated.'\"\n [(open)]=\"open\"\n />\n `,\n})\nexport class ToastView {\n protected readonly open = signal<boolean>(true);\n}\n```\n",
11420
- "timeline": "<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Timeline\n\n*Describes silverpoint 0.7.0.*\n\n`SpTimeline` is a skin over TimelineJS: its slides, eras and navigation, drawn in the ground's\nframes and type. TimelineJS is an **optional peer**. Install it yourself before you import the\n`timeline` subpath, or the build cannot resolve it:\n\n```sh\nnpm install @knight-lab/timelinejs@^3.9.13\n```\n\nImport TimelineJS's stylesheet before silverpoint's:\n`@knight-lab/timelinejs/dist/css/timeline.css`, then `@silverpoint/grounds/timeline.css`.\n\n- `data` is TimelineJS's JSON: `title`, `events`, `eras`, `scale`. The component builds TimelineJS on\n a copy, so your object is never changed.\n- TimelineJS loads on the client only. If it fails to load, the `fallback` (React prop, Vue slot,\n Angular `<ng-template spFallback>`) is shown and `SP025` is warned.\n- `options` passes TimelineJS options through, except `font` and `theme`, which the ground sets.\n- `height` is a CSS length (`'600px'` by default). Anything else is dropped with `SP017`.\n- Its events are `change` (the slide's `unique_id`), `loaded`, `navNext`, `navPrevious`, `zoomIn`,\n `zoomOut` and `backToStart`: React `onChange`\u2026, Vue emits, Angular outputs.\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpTimeline` | `SpTimeline` | `sp-timeline` | `sp_timeline` |\n| Import | `@silverpoint/react/timeline` | `@silverpoint/vue/timeline` | `@silverpoint/angular/timeline` | `reflex_silverpoint_react` |\n\nOptional peer: `@knight-lab/timelinejs@^3.9.13`.\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `data` | `TimelineData` | | **Required.** TimelineJS's JSON: a `title` slide, the `events`, optional `eras` and `scale`. |\n| `options` | `Readonly<Record<string, unknown>>` | | TimelineJS options; `font` and `theme` are ignored, the skin sets both. |\n| `height` | `string` | `'600px'` | A plain CSS length. Default `'600px'`. |\n| `inkedFrames` | `boolean` | `true` | Lays the ground's frames and tones on TimelineJS's pieces (REQ-512). Default `true`. |\n| `card` | `boolean` | `true` | Frames the whole timeline as a card. Default `true`. |\n| `label` | `string` | | The region's accessible name; the title's headline when omitted. |\n\n```tsx\nimport '@knight-lab/timelinejs/dist/css/timeline.css';\nimport '@silverpoint/grounds/timeline.css';\nimport { SpTimeline } from '@silverpoint/react/timeline';\n\nconst data = {\n title: { text: { headline: 'Releases' } },\n events: [\n { start_date: { year: 2026, month: 9, day: 26 }, text: { headline: '0.2.0', text: 'The dashboard.' } },\n { start_date: { year: 2026, month: 10, day: 1 }, text: { headline: '0.3.0', text: 'UI components.' } },\n ],\n};\n\nexport function Releases() {\n return <SpTimeline data={data} height=\"480px\" label=\"Release history\" fallback={<p>The timeline could not load.</p>} />;\n}\n```\n",
11421
- "react": "<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# React\n\n*Describes silverpoint 0.7.0.*\n\n```sh\nnpm install @silverpoint/react @silverpoint/grounds @silverpoint/fonts\n```\n\nReact 18 and 19 are supported. Import the stylesheets once, in the entry file or the root layout:\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\n\nexport {};\n```\n\n## Names and imports\n\nCharts carry no prefix (`LineChart`) and components carry `Sp` (`SpModal`). Each one is imported\nfrom its own subpath: `@silverpoint/react/line-chart`, `@silverpoint/react/ui/modal`. The barrel\n`@silverpoint/react` holds the charts and `SilverpointProvider`, but a subpath keeps the bundle\nsmall.\n\n## Server Components and Next.js\n\n- `@silverpoint/react/<chart>` is a client entry (`\"use client\"`), with pointer and keyboard\n interaction. It renders on the server too and hydrates with no mismatch.\n- `@silverpoint/react/server/<chart>` renders pure SVG with no client JavaScript. On its own it needs\n `id`, `width` and `height` (`SP002`, `SP003` without them). Inside a `Dashboard`, the cell gives\n them. It takes no event handlers.\n- `@silverpoint/react/server/dashboard` is the server dashboard. It takes no `link`.\n- Display components have server entries as well (`@silverpoint/react/server/ui/card`\u2026). The\n overlays and every component with state are client-only.\n\n## Events and the handle\n\n`onActiveChange(item | null)`, `onSelect(item)` and, on the sunburst and the squarified treemap,\n`onRootChange(id | null)`. A `ref` gives `getGeometry()` and `toSVGString()`, which serialises the\nchart with its palette.\n\n## Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport { sanguine } from '@silverpoint/core/palettes';\nimport { LineChart } from '@silverpoint/react/line-chart';\n\nexport function LineChartView({ rows }: { rows: readonly Record<string, unknown>[] }) {\n return (\n <LineChart\n data={rows}\n xKey=\"hour\"\n valueKey=\"hits\"\n secondaryKey=\"baseline\"\n title=\"Line chart\"\n palette={sanguine}\n />\n );\n}\n```\n\nA custom readout replaces the built-in tooltip:\n\n```tsx\nimport { LineChart } from '@silverpoint/react/line-chart';\n\nexport function Hits({ rows }: { rows: readonly { hour: string; hits: number }[] }) {\n return (\n <LineChart\n title=\"Hits per hour\"\n data={rows}\n xKey=\"hour\"\n valueKey=\"hits\"\n tooltip={(active) => <span>{String(active.datum.hour)}: {active.value} hits</span>}\n />\n );\n}\n```\n",
11422
- "vue": "<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Vue\n\n*Describes silverpoint 0.7.0.*\n\n```sh\nnpm install @silverpoint/vue @silverpoint/grounds @silverpoint/fonts\n```\n\nVue 3. Import the stylesheets once, in `main.ts`, and set the application's defaults with the\nplugin:\n\n```ts vue\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { provideSilverpoint } from '@silverpoint/vue';\nimport { createApp, h } from 'vue';\n\ncreateApp({ render: () => h('main') })\n .use(provideSilverpoint({ ground: 'silverpoint', substrate: 'cream' }))\n .mount('#app');\n```\n\n## Names and props\n\nEvery component is `Sp<Name>`: `SpLineChart`, `SpModal`. Each one is imported from its own subpath,\n`@silverpoint/vue/line-chart` or `@silverpoint/vue/ui/modal`. Props are the same camelCase names as\nin React. In a template, write them in kebab-case (`x-key`, `value-key`) and bind non-strings with\n`:` (`:data=\"rows\"`, `:height=\"240\"`).\n\n- Values: `v-model`. Open state: `v-model:open`. Pagination: `v-model:current`.\n- Events: `@active-change`, `@select`, `@root-change`, `@sort`, `@toggle`.\n- Content: slots `trigger`, `footer`, `extra`, `prefix`, `suffix`, `action`, `fallback`, `tooltip`.\n- A section of the page: `<SilverpointProvider :palette=\"sepia\">`. It renders no element of its\n own.\n- Server rendering works with `@vue/server-renderer`. Nuxt is not a validated integration.\n\n## Example\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpSelect } from '@silverpoint/vue/ui/select';\n\nconst value = ref<string>();\n</script>\n\n<template>\n <SpSelect\n label=\"Status\"\n name=\"status\"\n :items=\"[{ key: 'placed', label: 'Placed' }, { key: 'paid', label: 'Paid' }, { key: 'packed', label: 'Packed' }, { key: 'shipped', label: 'Shipped' }, { key: 'returned', label: 'Returned', disabled: true }]\"\n v-model=\"value\"\n />\n</template>\n```\n",
11423
- "angular": "<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Angular\n\n*Describes silverpoint 0.7.0.*\n\n```sh\nnpm install @silverpoint/angular @silverpoint/grounds @silverpoint/fonts\n```\n\nAdd the stylesheets to the `styles` array of `angular.json`, in this order:\n`@silverpoint/fonts/fonts.css`, `@silverpoint/grounds/styles.css`, and\n`@silverpoint/grounds/ui.css` if you use components.\n\n```ts angular\nimport { bootstrapApplication } from '@angular/platform-browser';\nimport { Component } from '@angular/core';\nimport { provideSilverpoint } from '@silverpoint/angular';\n\n@Component({ selector: 'app-root', template: '' })\nclass App {}\n\nbootstrapApplication(App, { providers: [provideSilverpoint({ ground: 'silverpoint', substrate: 'cream' })] }).catch(console.error);\n```\n\n## Components\n\nEvery chart and component is a standalone component with signal inputs and `OnPush`, imported from\nits own secondary entry point: `@silverpoint/angular/line-chart`, `@silverpoint/angular/ui/modal`.\nSelectors are `sp-<name>`. The exceptions are `SpButton` (`<button spButton>`) and `SpSurface`\n(`[spSurface]`), which sit on your own element.\n\n- **Bind every input**, strings included: `[title]=\"'Traffic'\"`. `strictTemplates` checks\n bindings, while a static attribute with a misspelt name passes silently.\n- Values: `[(value)]`, or a forms directive (`formControlName`, `ngModel`): the value components\n are `ControlValueAccessor`s. Open state: `[(open)]`. Pagination: `[(current)]`.\n- Events are outputs: `(activeChange)`, `(select)`, `(rootChange)`, `(openChange)`, `(sort)`.\n- Content is projected through templates: `<ng-template spFooter>`, `spExtra`, `spAction`,\n `spFallback`, `spTooltip`. An overlay's trigger is `<button type=\"button\" spTrigger>`, with\n `SpTrigger` imported from the overlay's subpath.\n- `provideSilverpoint` returns a `Provider`, so a component's own `providers` can nest one for its\n subtree.\n- Server rendering with `@angular/ssr` is supported.\n\n## Example\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpModal, SpTrigger } from '@silverpoint/angular/ui/modal';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-modal-view',\n imports: [SpModal, SpTrigger],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-modal\n [title]=\"'Edit order'\"\n [description]=\"'Order 1042, placed on 14 October.'\"\n >\n <button type=\"button\" spTrigger>Edit order</button>\n Changes reach the workshop before the order is packed.\n </sp-modal>\n `,\n})\nexport class ModalView {}\n```\n",
11424
- "reflex": '<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Reflex\n\n*Describes silverpoint 0.7.0.*\n\n`reflex-silverpoint-react` 0.7.1 wraps the React components for Reflex, so the same\ncharts and components are Python builders. For anything beyond names and a first example, use the\n`reflex-silverpoint` skill, which covers state, events and the demo app\'s patterns.\n\n```sh\npip install reflex-silverpoint-react\n```\n\n- Builders are snake_case: `line_chart`, `sankey_chart`, `sp_modal`, `sp_select`. Props are\n snake_case too (`x_key`, `value_key`), with the same meaning as in React.\n- Data comes from a `rx.State` field, as a list of dicts.\n- `palette` takes a preset\'s name (`"sanguine"`).\n- An overlay\'s `trigger` is the trigger\'s text.\n\n```python\nimport reflex as rx\nfrom reflex_silverpoint_react import line_chart\n\n\nclass State(rx.State):\n rows: list[dict] = []\n\n\ndef line_chart_view() -> rx.Component:\n return line_chart(\n data=State.rows,\n x_key="hour",\n value_key="hits",\n secondary_key="baseline",\n title="Line chart",\n )\n```\n\n```python\nimport reflex as rx\nfrom reflex_silverpoint_react import sp_modal\n\n\ndef modal_view() -> rx.Component:\n return sp_modal(\n "Changes reach the workshop before the order is packed.",\n title="Edit order",\n description="Order 1042, placed on 14 October.",\n trigger="Edit order",\n )\n```\n\n## Builders\n\n| Slug | Builder | Kind |\n|---|---|---|\n| `line-chart` | `line_chart` | chart |\n| `bullet-chart` | `bullet_chart` | chart |\n| `pyramid-chart` | `pyramid_chart` | chart |\n| `heatmap-chart` | `heatmap_chart` | chart |\n| `treemap-chart` | `treemap_chart` | chart |\n| `sankey-chart` | `sankey_chart` | chart |\n| `activity-grid` | `activity_grid` | chart |\n| `step-chart` | `step_chart` | chart |\n| `sparkline-rows` | `sparkline_rows` | chart |\n| `kpi-card` | `kpi_card` | chart |\n| `bar-chart` | `bar_chart` | chart |\n| `stacked-bar-chart` | `stacked_bar_chart` | chart |\n| `composed-chart` | `composed_chart` | chart |\n| `waterfall-chart` | `waterfall_chart` | chart |\n| `funnel-chart` | `funnel_chart` | chart |\n| `candlestick-chart` | `candlestick_chart` | chart |\n| `area-chart` | `area_chart` | chart |\n| `range-band-chart` | `range_band_chart` | chart |\n| `stream-chart` | `stream_chart` | chart |\n| `scatter-chart` | `scatter_chart` | chart |\n| `bubble-chart` | `bubble_chart` | chart |\n| `donut-chart` | `donut_chart` | chart |\n| `radar-chart` | `radar_chart` | chart |\n| `polar-bar-chart` | `polar_bar_chart` | chart |\n| `radial-arc-group` | `radial_arc_group` | chart |\n| `radial-rings` | `radial_rings` | chart |\n| `gauge-arc` | `gauge_arc` | chart |\n| `meter-chart` | `meter_chart` | chart |\n| `coxcomb-chart` | `coxcomb_chart` | chart |\n| `wind-rose` | `wind_rose` | chart |\n| `volvelle-chart` | `volvelle_chart` | chart |\n| `chord-ring` | `chord_ring` | chart |\n| `orbit-chart` | `orbit_chart` | chart |\n| `histogram-chart` | `histogram_chart` | chart |\n| `ecdf-chart` | `ecdf_chart` | chart |\n| `box-plot-chart` | `box_plot_chart` | chart |\n| `violin-chart` | `violin_chart` | chart |\n| `ridgeline-chart` | `ridgeline_chart` | chart |\n| `beeswarm-chart` | `beeswarm_chart` | chart |\n| `lollipop-chart` | `lollipop_chart` | chart |\n| `dumbbell-chart` | `dumbbell_chart` | chart |\n| `slope-chart` | `slope_chart` | chart |\n| `bump-chart` | `bump_chart` | chart |\n| `error-bar-chart` | `error_bar_chart` | chart |\n| `interval-chart` | `interval_chart` | chart |\n| `diverging-bar-chart` | `diverging_bar_chart` | chart |\n| `connected-scatter-chart` | `connected_scatter_chart` | chart |\n| `waffle-chart` | `waffle_chart` | chart |\n| `marimekko-chart` | `marimekko_chart` | chart |\n| `squarified-treemap` | `squarified_treemap` | chart |\n| `sunburst-chart` | `sunburst_chart` | chart |\n| `tree-chart` | `tree_chart` | chart |\n| `parallel-coordinates-chart` | `parallel_coordinates_chart` | chart |\n| `polar-line-chart` | `polar_line_chart` | chart |\n| `polar-scatter-chart` | `polar_scatter_chart` | chart |\n| `density-bin-chart` | `density_bin_chart` | chart |\n| `contour-chart` | `contour_chart` | chart |\n| `delaunay-chart` | `delaunay_chart` | chart |\n| `vector-field-chart` | `vector_field_chart` | chart |\n| `network-chart` | `network_chart` | chart |\n| `button` | `sp_button` | ui |\n| `input` | `sp_input` | ui |\n| `checkbox` | `sp_checkbox` | ui |\n| `radio-group` | `sp_radio_group` | ui |\n| `switch` | `sp_switch` | ui |\n| `slider` | `sp_slider` | ui |\n| `rate` | `sp_rate` | ui |\n| `segmented` | `sp_segmented` | ui |\n| `tabs` | `sp_tabs` | ui |\n| `steps` | `sp_steps` | ui |\n| `card` | `sp_card` | ui |\n| `tag` | `sp_tag` | ui |\n| `badge` | `sp_badge` | ui |\n| `divider` | `sp_divider` | ui |\n| `progress` | `sp_progress` | ui |\n| `alert` | `sp_alert` | ui |\n| `skeleton` | `sp_skeleton` | ui |\n| `surface` | `sp_surface` | composed |\n| `glyph` | `sp_glyph` | composed |\n| `table` | `sp_table` | composed |\n| `pagination` | `sp_pagination` | composed |\n| `breadcrumb` | `sp_breadcrumb` | composed |\n| `avatar` | `sp_avatar` | composed |\n| `statistic` | `sp_statistic` | composed |\n| `descriptions` | `sp_descriptions` | composed |\n| `timeline-list` | `sp_timeline_list` | composed |\n| `collapse` | `sp_collapse` | composed |\n| `empty` | `sp_empty` | composed |\n| `result` | `sp_result` | composed |\n| `textarea` | `sp_textarea` | composed |\n| `input-number` | `sp_input_number` | composed |\n| `modal` | `sp_modal` | overlay |\n| `drawer` | `sp_drawer` | overlay |\n| `popover` | `sp_popover` | overlay |\n| `tooltip` | `sp_tooltip` | overlay |\n| `select` | `sp_select` | overlay |\n| `dropdown-menu` | `sp_dropdown_menu` | overlay |\n| `toast` | `sp_toast` | overlay |\n'
11513
+ "choosing-charts": "<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Choosing a chart\n\n*Describes silverpoint 0.8.0.*\n\nChoose a chart in two steps. First name the shape of the rows, then name what the reader is asked to\nsee. The recommender (`recommend_chart` on the MCP server) reads the table below. It is a reviewed\ntable, not a model, and a pair that is missing from it falls back on the charts that declare both.\n\n## Data shapes\n\n| Shape | The rows hold | For example |\n|---|---|---|\n| `series` | one row per point along an ordered x (time, sequence) | hits per hour |\n| `categories` | one row per category with one or more values | revenue by region |\n| `parts` | shares of one whole | traffic by channel |\n| `matrix` | a value per pair of categories | errors by day and hour |\n| `hierarchy` | one row per node, with an `id` and its `parent` (`null` for the root) | a budget by department |\n| `links` | rows with a source, a target and a value | signup funnel steps |\n| `points` | two or more numeric measures per row | price against rating |\n| `distribution` | many raw observations of one measure | response times |\n| `intervals` | a start and an end per row | task schedule |\n| `events` | dated occurrences, or marks along a cycle | commits per day |\n| `single` | one figure, perhaps with a target | revenue this month |\n| `field` | a measure or a vector (`x`, `y`, `u`, `v`) over a plane | a wind field |\n\n## The charts by shape and intent\n\n| Chart | Family | Shape | Intents | Summary |\n|---|---|---|---|---|\n| `line-chart` | lines | `series` | trend, change, compare | Spline with an optional dotted baseline series. |\n| `bullet-chart` | bars | `categories` | progress, kpi, compare | One bar per target, with a marker at the target. Values in 0-100. |\n| `pyramid-chart` | bars | `categories` | rank, compare | Stacked tiers whose width encodes the value (0-100). |\n| `heatmap-chart` | points-grids | `matrix` | compare, distribution | Labelled rows of values, normalised against `scaleMax`. |\n| `treemap-chart` | points-grids | `parts` | part-to-whole | Tiles of `cols \xD7 rows` cells placed in a `columns \xD7 rows` grid. |\n| `sankey-chart` | flows | `links` | flow, part-to-whole | Flow bands between layered nodes. |\n| `activity-grid` | points-grids | `events` | schedule, trend | One cell per day, a column per week. |\n| `step-chart` | lines | `series` | trend, change | A series drawn as steps. |\n| `sparkline-rows` | lines | `series` | trend, compare, kpi | One row per series \u2014 name, sparkline, readout. |\n| `kpi-card` | lines | `single` | kpi, change | A metric, its delta, and an area sparkline of the series. |\n| `bar-chart` | bars | `categories` | compare, rank | Pill bars, as columns or rows, with an optional second series. |\n| `stacked-bar-chart` | bars | `categories` | compare, part-to-whole | One stacked segment per key. |\n| `composed-chart` | bars | `series` | compare, trend | Columns and a spline on one value scale. |\n| `waterfall-chart` | bars | `categories` | change, part-to-whole | Totals from zero and floating deltas from the running total. |\n| `funnel-chart` | bars | `categories` | progress, compare | Horizontal, centred stages. |\n| `candlestick-chart` | bars | `intervals` | change, trend | OHLC bodies and wicks. |\n| `area-chart` | areas | `series` | trend, change | A curved, toned area under its line. |\n| `range-band-chart` | areas | `intervals` | uncertainty, trend | The band between a low and a high series. |\n| `stream-chart` | areas | `series` | trend, part-to-whole, compare | Two waves, overlaid or stacked. |\n| `scatter-chart` | points-grids | `points` | correlation, distribution | Points on two linear scales, optionally sized. |\n| `bubble-chart` | points-grids | `points` | correlation, compare | Circles whose area encodes `sizeKey`. |\n| `donut-chart` | radial | `parts` | part-to-whole | Sectors \u221D value around a central readout. |\n| `radar-chart` | radial | `categories` | compare | One spoke per subject, a closed polygon of values. |\n| `polar-bar-chart` | radial | `categories` | compare, rank | 360\xB0 bars out from a hole, length \u221D value. |\n| `radial-arc-group` | radial | `categories` | compare, progress | Concentric 180\xB0 tracks, sweep \u221D value / the largest. |\n| `radial-rings` | radial | `categories` | progress | Concentric progress rings, sweep \u221D value in 0-100. |\n| `gauge-arc` | radial | `single` | kpi, progress | A 240\xB0 arc swept to a percent. |\n| `meter-chart` | radial | `single` | kpi, progress | A semicircular meter with a needle at a percent. |\n| `coxcomb-chart` | radial | `categories` | compare, part-to-whole | Equal angles, sector area \u221D value. |\n| `wind-rose` | radial | `distribution` | distribution | Observations of (bearing, speed) binned by compass sector and speed. |\n| `volvelle-chart` | radial | `categories` | schedule, compare | Concentric categorical rings read against one index. |\n| `chord-ring` | flows | `links` | flow, network | Directed flows between categories around a circle. |\n| `orbit-chart` | radial | `events` | schedule | Nested elliptical orbits with markers along them. |\n| `histogram-chart` | distributions-comparisons | `distribution` | distribution | Raw observations binned in the core. |\n| `ecdf-chart` | distributions-comparisons | `distribution` | distribution, compare | The empirical cumulative distribution as a step function. |\n| `box-plot-chart` | distributions-comparisons | `distribution` | distribution, compare | Quartiles, median, Tukey whiskers and outliers per group. |\n| `violin-chart` | distributions-comparisons | `distribution` | distribution, compare | A mirrored kernel density per group. |\n| `ridgeline-chart` | distributions-comparisons | `distribution` | distribution, compare, change | A kernel density per group on overlapping baselines. |\n| `beeswarm-chart` | distributions-comparisons | `distribution` | distribution | One point per observation, packed without overlap. |\n| `lollipop-chart` | distributions-comparisons | `categories` | compare, rank | A stem from the baseline and a head at the value. |\n| `dumbbell-chart` | distributions-comparisons | `categories` | change, compare | Two values per category joined by a segment. |\n| `slope-chart` | distributions-comparisons | `categories` | change, rank | Two period axes, one segment per category. |\n| `bump-chart` | distributions-comparisons | `series` | rank, change | The rank of each series at each x. |\n| `error-bar-chart` | distributions-comparisons | `intervals` | uncertainty, compare | A point estimate with its interval per category. |\n| `interval-chart` | distributions-comparisons | `intervals` | schedule | Floating bars from start to end on lanes. |\n| `diverging-bar-chart` | distributions-comparisons | `parts` | part-to-whole, compare | Ordered levels stacked on both sides of a neutral centre. |\n| `connected-scatter-chart` | distributions-comparisons | `points` | correlation, change | An ordered path through x-y points. |\n| `waffle-chart` | hierarchies-dimensions | `parts` | part-to-whole, progress | A unit grid filled in reading order by category. |\n| `marimekko-chart` | hierarchies-dimensions | `matrix` | part-to-whole, compare | Column width by total, segment height by share. |\n| `squarified-treemap` | hierarchies-dimensions | `hierarchy` | hierarchy, part-to-whole | Nested rectangles, area by value, drillable through `rootId` and `onRootChange`. |\n| `sunburst-chart` | hierarchies-dimensions | `hierarchy` | hierarchy, part-to-whole | A hierarchy as rings of arcs, drillable through `rootId` and `onRootChange`. |\n| `tree-chart` | hierarchies-dimensions | `hierarchy` | hierarchy | A tidy node-link tree. |\n| `parallel-coordinates-chart` | hierarchies-dimensions | `matrix` | correlation, compare | One polyline per row across parallel axes. |\n| `polar-line-chart` | hierarchies-dimensions | `series` | trend, compare | A line over angle and radius. |\n| `polar-scatter-chart` | hierarchies-dimensions | `points` | distribution, correlation | Points over angle and radius. |\n| `density-bin-chart` | fields-networks | `points` | distribution, correlation | X-y points counted in two-dimensional bins. |\n| `contour-chart` | fields-networks | `points` | distribution, correlation | Iso-lines and filled bands of a density or a grid. |\n| `delaunay-chart` | fields-networks | `points` | network, distribution | The triangulation of x-y points, or its Voronoi cells. |\n| `vector-field-chart` | fields-networks | `field` | flow | An arrow per grid point. |\n| `network-chart` | fields-networks | `links` | network, flow | A node-link graph. |\n\n## The recommender's table\n\nThe scores run from 0 to 1. An adjustment applies when the row count (`rows`) or the number of\nvalue columns (`values`) passes its bound.\n\n| Shape | Intent | Charts, best first | Adjustments |\n|---|---|---|---|\n| `series` | `trend` | `line-chart` 0.9 \u2014 A line is the plainest reading of a value over an ordered axis.<br>`area-chart` 0.8 \u2014 An area gives one series the weight of its magnitude.<br>`step-chart` 0.6 \u2014 Steps show a value that holds until it changes.<br>`stream-chart` 0.5 \u2014 Several value columns overlay or stack as waves.<br>`polar-line-chart` 0.3 \u2014 A cyclic axis (hours, months, degrees) closes the line around a circle. | values>1: `stream-chart` +0.3 \u2014 Several value fields read together as streams.<br>values>1: `area-chart` -0.2 \u2014 An area draws one series only. |\n| `series` | `change` | `line-chart` 0.8 \u2014 The slope between points is the change.<br>`step-chart` 0.75 \u2014 Steps mark when the value changed and by how much.<br>`area-chart` 0.6 \u2014 An area shows the change in magnitude.<br>`bump-chart` 0.5 \u2014 When the change that matters is in rank. | |\n| `series` | `compare` | `line-chart` 0.8 \u2014 A second series draws as a dotted baseline against the first.<br>`composed-chart` 0.75 \u2014 Columns and a line share one value scale.<br>`stream-chart` 0.6 \u2014 Several series overlaid on one axis.<br>`sparkline-rows` 0.55 \u2014 One small line per series, side by side with its readout.<br>`polar-line-chart` 0.3 \u2014 Values around a cycle compared by angle. | |\n| `series` | `rank` | `bump-chart` 0.9 \u2014 The rank of each series at each x, ranks joined across x. | |\n| `series` | `kpi` | `sparkline-rows` 0.85 \u2014 One row per series: its name, its trend and its latest readout.<br>`kpi-card` 0.75 \u2014 One metric, its delta and its trend. | |\n| `series` | `part-to-whole` | `stream-chart` 0.8 \u2014 Stacked waves show each part of a total over x. | |\n| `categories` | `compare` | `bar-chart` 0.9 \u2014 Bars compare values against one common baseline.<br>`lollipop-chart` 0.75 \u2014 A lighter mark per category, readable with many of them.<br>`radar-chart` 0.5 \u2014 Spokes compare a few subjects at once.<br>`polar-bar-chart` 0.4 \u2014 Bars around a circle, for a cyclic set of categories.<br>`coxcomb-chart` 0.35 \u2014 Equal angles, area by value: cyclic categories such as months.<br>`radial-arc-group` 0.3 \u2014 Concentric tracks, each swept by its value. | rows>12: `lollipop-chart` +0.2 \u2014 Many categories read better as lollipops.<br>rows>12: `radar-chart` -0.3 \u2014 Radial layouts crowd past a dozen categories.<br>rows>12: `polar-bar-chart` -0.3 \u2014 Radial layouts crowd past a dozen categories.<br>rows>12: `coxcomb-chart` -0.3 \u2014 Radial layouts crowd past a dozen categories.<br>values>1: `bar-chart` +0.05 \u2014 A second value field draws as a second series of bars. |\n| `categories` | `rank` | `bar-chart` 0.85 \u2014 Sorted bars read as a ranking.<br>`lollipop-chart` 0.85 \u2014 Lollipops sort themselves with `sort`.<br>`pyramid-chart` 0.5 \u2014 Stacked tiers, widest at the base.<br>`polar-bar-chart` 0.4 \u2014 A ranking around a circle. | |\n| `categories` | `part-to-whole` | `stacked-bar-chart` 0.85 \u2014 Each bar stacks its parts, one segment per value column.<br>`waterfall-chart` 0.6 \u2014 Parts that add up to a running total.<br>`coxcomb-chart` 0.4 \u2014 Sectors whose area is each part. | |\n| `categories` | `change` | `dumbbell-chart` 0.9 \u2014 Two values per category joined by a segment: before and after.<br>`slope-chart` 0.85 \u2014 Two period axes, one segment per category: the slope is the change.<br>`waterfall-chart` 0.75 \u2014 Each step a delta from the running total. | |\n| `categories` | `progress` | `bullet-chart` 0.9 \u2014 Each bar against its own target.<br>`radial-rings` 0.75 \u2014 Concentric rings, each swept to its percent.<br>`funnel-chart` 0.7 \u2014 Stages that narrow, such as a conversion.<br>`radial-arc-group` 0.5 \u2014 Tracks swept relative to the largest. | |\n| `categories` | `kpi` | `bullet-chart` 0.8 \u2014 Each measure against its target, compact.<br>`radial-rings` 0.6 \u2014 A few percents at a glance. | |\n| `parts` | `part-to-whole` | `donut-chart` 0.9 \u2014 A ring reads a few shares of one whole around a central figure.<br>`waffle-chart` 0.85 \u2014 Unit cells make the shares countable.<br>`treemap-chart` 0.7 \u2014 Tiles sized by share.<br>`diverging-bar-chart` 0.4 \u2014 For ordered levels (agree\u2026 disagree) around a neutral centre.<br>`stacked-bar-chart` 0.35 \u2014 One bar stacked with the shares, to set beside other wholes. | rows>6: `donut-chart` -0.3 \u2014 A ring loses its shares past six slices.<br>rows>6: `treemap-chart` +0.1 \u2014 Tiles hold many shares better than a ring. |\n| `parts` | `compare` | `diverging-bar-chart` 0.8 \u2014 Likert-style levels on both sides of a neutral centre, row by row.<br>`waffle-chart` 0.6 \u2014 Countable cells per part. | |\n| `parts` | `progress` | `waffle-chart` 0.8 \u2014 A hundred cells filled to the share done. | |\n| `matrix` | `compare` | `heatmap-chart` 0.9 \u2014 One toned cell per row and column.<br>`marimekko-chart` 0.7 \u2014 Columns by total, segments by share.<br>`parallel-coordinates-chart` 0.6 \u2014 One polyline per row across many dimensions. | |\n| `matrix` | `part-to-whole` | `marimekko-chart` 0.9 \u2014 Each column a whole, each segment its share, column width by total. | |\n| `matrix` | `correlation` | `parallel-coordinates-chart` 0.9 \u2014 Crossing lines between axes show how dimensions move together.<br>`heatmap-chart` 0.6 \u2014 A grid of values, read for patterns. | |\n| `matrix` | `distribution` | `heatmap-chart` 0.8 \u2014 Where the high values gather in the grid. | |\n| `hierarchy` | `hierarchy` | `tree-chart` 0.85 \u2014 The structure itself, node by node.<br>`squarified-treemap` 0.8 \u2014 Nested rectangles, drillable.<br>`sunburst-chart` 0.75 \u2014 Rings of arcs, one ring per level, drillable. | |\n| `hierarchy` | `part-to-whole` | `squarified-treemap` 0.9 \u2014 Area by value, nested by level.<br>`sunburst-chart` 0.85 \u2014 Each arc its share of its parent. | |\n| `links` | `flow` | `sankey-chart` 0.9 \u2014 Bands between layered stages, width by value.<br>`chord-ring` 0.75 \u2014 Flows between categories around a circle, both ways.<br>`network-chart` 0.5 \u2014 When the links matter more than their volume. | |\n| `links` | `network` | `network-chart` 0.9 \u2014 Nodes and links laid out by a seeded force.<br>`chord-ring` 0.7 \u2014 Who connects to whom, around a circle. | |\n| `links` | `part-to-whole` | `sankey-chart` 0.8 \u2014 How a total splits and merges across stages. | |\n| `points` | `correlation` | `scatter-chart` 0.9 \u2014 Points on two linear scales.<br>`bubble-chart` 0.75 \u2014 A third variable as each point\u2019s area.<br>`density-bin-chart` 0.6 \u2014 Counts per bin when points overlap.<br>`connected-scatter-chart` 0.5 \u2014 When the points have an order.<br>`polar-scatter-chart` 0.3 \u2014 When one variable is an angle. | rows>500: `density-bin-chart` +0.35 \u2014 Hundreds of points read better as counts per bin.<br>rows>500: `scatter-chart` -0.2 \u2014 Points overplot and hide their density.<br>values>2: `bubble-chart` +0.2 \u2014 A third numeric field can size the points. |\n| `points` | `distribution` | `density-bin-chart` 0.85 \u2014 Points counted in hexagonal or square bins.<br>`contour-chart` 0.8 \u2014 Iso-lines of the density.<br>`scatter-chart` 0.6 \u2014 Every point, when there are few.<br>`polar-scatter-chart` 0.4 \u2014 Points by angle and radius. | |\n| `points` | `change` | `connected-scatter-chart` 0.9 \u2014 An ordered path through x-y points: how two values moved together. | |\n| `points` | `network` | `delaunay-chart` 0.85 \u2014 Neighbours by triangulation, or each point\u2019s Voronoi cell. | |\n| `points` | `compare` | `bubble-chart` 0.7 \u2014 Positions and sizes compared at once. | |\n| `distribution` | `distribution` | `histogram-chart` 0.9 \u2014 Observations binned in the core.<br>`box-plot-chart` 0.8 \u2014 Quartiles, median, whiskers and outliers.<br>`violin-chart` 0.75 \u2014 The density\u2019s shape, mirrored.<br>`beeswarm-chart` 0.7 \u2014 Every observation, packed without overlap.<br>`ecdf-chart` 0.65 \u2014 The cumulative share below each value.<br>`wind-rose` 0.3 \u2014 When the observations carry a bearing. | rows<30: `beeswarm-chart` +0.25 \u2014 Few observations: show each one.<br>rows<30: `histogram-chart` -0.2 \u2014 Few observations make coarse bins.<br>rows>1000: `beeswarm-chart` -0.4 \u2014 Too many observations to draw one by one. |\n| `distribution` | `compare` | `box-plot-chart` 0.9 \u2014 Quartiles side by side, one box per group.<br>`violin-chart` 0.85 \u2014 Density shapes side by side.<br>`ridgeline-chart` 0.8 \u2014 Densities on overlapping baselines, one per group.<br>`ecdf-chart` 0.75 \u2014 Cumulative curves of each group on one axis. | |\n| `distribution` | `change` | `ridgeline-chart` 0.85 \u2014 A density per period, stacked in order. | |\n| `intervals` | `uncertainty` | `error-bar-chart` 0.9 \u2014 A point estimate with its interval per category.<br>`range-band-chart` 0.85 \u2014 A band between low and high over x. | |\n| `intervals` | `trend` | `range-band-chart` 0.85 \u2014 The band between low and high over time.<br>`candlestick-chart` 0.8 \u2014 Open, high, low and close per period. | |\n| `intervals` | `change` | `candlestick-chart` 0.9 \u2014 Each period\u2019s open-to-close change and its range. | |\n| `intervals` | `schedule` | `interval-chart` 0.95 \u2014 Floating bars from start to end on lanes. | |\n| `events` | `schedule` | `activity-grid` 0.85 \u2014 One cell per day, a column per week. | |\n| `events` | `trend` | `activity-grid` 0.8 \u2014 Activity per day over weeks. | |\n| `single` | `kpi` | `kpi-card` 0.9 \u2014 The figure, its delta and its trend.<br>`gauge-arc` 0.75 \u2014 A percent on a 240\xB0 arc.<br>`meter-chart` 0.7 \u2014 A percent with a needle. | |\n| `single` | `progress` | `gauge-arc` 0.85 \u2014 An arc swept to the percent done.<br>`meter-chart` 0.8 \u2014 A needle at the percent done. | |\n| `field` | `flow` | `vector-field-chart` 0.95 \u2014 An arrow per grid point, its direction and magnitude. | |\n| `field` | `distribution` | `contour-chart` 0.85 \u2014 Iso-lines and bands of a scalar grid (`source: 'grid'`). | |\n\n## Common chart props\n\nEvery chart takes these, under the same names in React, Vue and Angular.\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `data` | `readonly Datum[]` | | Rows to draw. If omitted, the demo dataset is rendered (REQ-093): accessor props (`\u2026Key`, `keys`, `names`, `levels`, `axis`, `dimensions`, `period`, `nodes`) are ignored, every other prop applies. |\n| `ground` | `GroundRef` | `'silverpoint'` | Style ground. Defaults to the app provider's, or `silverpoint`. |\n| `substrate` | `SubstrateName` | `'cream'` | Prepared substrate within the ground (REQ-046). |\n| `mode` | `InkMode` | `'ink'` | `ink` by default; `precision` disables inking (REQ-021). |\n| `palette` | `Palette` | | Colours over the ground's, field by field, written on the root's `style` (REQ-461). Merged over the dashboard's and the provider's (REQ-462); presets are on `@silverpoint/core/palettes`. |\n| `seed` | `Seed` | | Seed. If omitted, it is derived from `id` stably (REQ-003). |\n| `id` | `string` | | Stable identifier. If omitted, it is generated deterministically. |\n| `height` | `number` | `160` | Height of the drawing area in px. Width is the container's unless pinned. |\n| `width` | `number` | | |\n| `chrome` | `'card' \\| 'bare'` | `'card'` | `card` draws the full frame; `bare` only the drawing area (REQ-095). |\n| `hatchFill` | `'tile' \\| 'per-shape'` | `'tile'` | How areas are filled (REQ-029). |\n| `title` | `string` | | |\n| `badge` | `string` | | |\n| `value` | `string \\| number` | | |\n| `unit` | `string` | | |\n| `footerLeft` | `string` | | |\n| `footerRight` | `string` | | |\n| `label` | `string` | | Accessible name. If omitted, it is derived from `title` (REQ-120). |\n| `description` | `string` | | Long description for screen readers (REQ-120). |\n| `dataTable` | `'visible' \\| 'hidden' \\| 'none'` | `'hidden'` | Tabular alternative; `hidden` leaves it for assistive technology only (REQ-121). |\n| `locale` | `string` | | |\n| `numberFormat` | `Intl.NumberFormatOptions` | | |\n| `className` | `string` | | |\n\nDefaults to know:\n\n- `height` is 160, the drawing area without the card frame.\n- `chrome` is `card`. `bare` drops the frame.\n- `dataTable` is `hidden`: the table stays in the page for screen readers only.\n- `hatchFill` is `tile`. `per-shape` traces the hatching shape by shape, which costs 10 to 40 times\n the path weight, so keep it for a hero chart or an export.\n\n## Events\n\n| React | Vue | Angular | Payload |\n|---|---|---|---|\n| `onActiveChange` | `@active-change` | `(activeChange)` | the item under the pointer or keyboard focus, or `null` |\n| `onSelect` | `@select` | `(select)` | the item clicked or chosen with Enter or Space |\n| `onRootChange` | `@root-change` | `(rootChange)` | the sunburst's or treemap's new root id, `null` for the data root |\n",
11514
+ "grounds-and-palettes": '<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Grounds and palettes\n\n*Describes silverpoint 0.8.0.*\n\n## Grounds\n\nA *ground* is the drawing technique. Every chart and component draws in the ground the application\nprovider sets, and a `ground` prop overrides it.\n\n| Ground | Substrates | What it draws |\n|---|---|---|\n| `silverpoint` | `cream`, `green`, `blue`, `ochre` | Metal point on prepared paper: hatched tone, a hand-inked line, cream and other prepared substrates. |\n| `cyanotype` | `prussian` | A contact print: a white, exact line on Prussian blue; tone is line weight, nothing is hatched. |\n\n- **silverpoint** (the default): tone is *hatch density*, not colour. A darker category gets\n denser hatching, so a chart reads in grey scale and in print. Highlights are white heightening\n with an ink outline.\n- **cyanotype**: tone is *line weight*, and nothing is hatched. Its only substrate, `prussian`, is\n painted whatever `substrate` says, so leave `substrate` out.\n- `mode="precision"` turns the hand-inked jitter off: the lines become exact. It is forced\n when the page declares `prefers-contrast: more` or `forced-colors: active`, and no prop can undo\n that.\n\n## Palettes\n\nA palette recolours a ground field by field. The fields you leave unset keep the ground\'s colours.\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `substrate` | `string` | | The prepared ground the drawing sits on. |\n| `ink` | `string` | | The main series and the frames of UI components. |\n| `inkSecondary` | `string` | | The second series and the hatch of tones. |\n| `heighten` | `string` | | White heightening on the live value (always outlined with `ink`). |\n| `rule` | `string` | | Rules and baselines. |\n| `grid` | `string` | | Grid lines. |\n| `text` | `string` | | Large figures and primary labels. |\n| `textMuted` | `string` | | Axis labels and secondary text. |\n| `focus` | `string` | `ink` | Focus ring of UI components; `ink` by default. |\n\nThe six presets, all checked for contrast on their substrate:\n\n| Preset | `substrate` | `ink` | `inkSecondary` | `heighten` | `rule` | `grid` | `text` | `textMuted` | `focus` |\n|---|---|---|---|---|---|---|---|---|---|\n| `silverpoint` | #EDE7DA | #5A5E65 | #685C4D | #FFFFFF | #737A82 | #737A82 | #3F4348 | #5A5E65 | |\n| `sanguine` | #F2E8DC | #8A3A24 | #6A4A3A | #FFFFFF | #9A6450 | #9A6450 | #4A2216 | #7A3E2C | |\n| `sepia` | #F0E6D2 | #6B4C2C | #5A5148 | #FFFFFF | #8A6E52 | #8A6E52 | #3B2A18 | #6B4C2C | |\n| `ironGall` | #EEEAE0 | #3C4858 | #6A4E36 | #FFFFFF | #6C7584 | #6C7584 | #232B36 | #4A5566 | |\n| `verdigris` | #E7EDE6 | #2C6355 | #65563F | #FFFFFF | #5C7B71 | #5C7B71 | #1F3D36 | #3E6A5E | |\n| `indigo` | #E9EAF1 | #3A4884 | #675641 | #FFFFFF | #68709A | #68709A | #232C52 | #4A5590 | |\n\nPass the object, never its name. That way a page that names no preset ships none:\n\n```tsx\nimport { sanguine } from \'@silverpoint/core/palettes\';\nimport { BarChart } from \'@silverpoint/react/bar-chart\';\n\nexport function Revenue() {\n return <BarChart title="Revenue by quarter" palette={sanguine} />;\n}\n```\n\nA palette of your own is a plain object, so check its contrast before you ship it, with\n`check_palette` on the MCP server or `checkPalette` from `@silverpoint/core/palettes`. A colour\nthat is not a CSS colour is dropped with `SP024`, and a pair under its contrast threshold warns\n`SP023`.\n\n## Precedence\n\n`ground`, `substrate`, `mode`, `locale` and `palette` resolve from the chart\'s prop first, then the\ndashboard, then the provider, then the library default. A palette merges field by field at each\nlevel, and a nested provider inherits what it does not set.\n\n```tsx\nimport { sepia } from \'@silverpoint/core/palettes\';\nimport { SilverpointProvider } from \'@silverpoint/react\';\nimport { LineChart } from \'@silverpoint/react/line-chart\';\n\nexport function Report() {\n return (\n <SilverpointProvider ground="silverpoint" substrate="ochre" palette={sepia}>\n <LineChart title="Visits" />\n <LineChart title="Visits, exact" mode="precision" />\n </SilverpointProvider>\n );\n}\n```\n',
11515
+ "dashboard": '<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Dashboard\n\n*Describes silverpoint 0.8.0.*\n\nA dashboard is a responsive grid of cards. The charts are its children, and the layout is a plain,\nserialisable object matched to them by cell id. There are no placement coordinates and no drag or\nresize.\n\n- **`id` is required.** The seed of every chart without an id of its own derives from it\n (`<dashboard id>--<cell id>`), so choose a stable one.\n- **`title` or `label` is required.** It is the region\'s name. React and Vue refuse a dashboard\n without one by type, and Angular warns `SP002`.\n- **The cells are in reading order.** `columns` defaults to `{ sm: 1, md: 2, lg: 4 }` and collapses\n 4 \u2192 2 \u2192 1 by container width. A `colSpan` wider than the breakpoint\'s columns is clamped, with\n `SP014`.\n- **A chart inside a cell takes the cell\'s box** unless it sets its own `width` and `height`, and it\n inherits the dashboard\'s `ground`, `substrate`, `mode`, `locale` and `palette`.\n- **`link={{ key: \'hour\' }}` highlights the same value** of that field in every chart when one is\n hovered or focused. It is client-only: React\'s server `Dashboard` refuses it.\n- **On the server,** cells are sized at `ssrWidth` (1200 by default) until they are measured.\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `Dashboard` | `SpDashboard` | `sp-dashboard` | `dashboard` |\n| Import | `@silverpoint/react/dashboard` | `@silverpoint/vue/dashboard` | `@silverpoint/angular/dashboard` | `reflex_silverpoint_react` |\n\n### Dashboard props\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `title` | `string` | | |\n| `label` | `string` | | |\n| `id` | `string` | | **Required.** Stable identifier; seeds of unnamed charts derive from it (REQ-209). Required. |\n| `layout` | `DashboardLayout` | | |\n| `description` | `string` | | Long description, exposed as the region\'s description (REQ-214). |\n| `headingLevel` | `2 \\| 3 \\| 4 \\| 5 \\| 6` | `2` | Heading level of `title`. Default `2`. |\n| `ssrWidth` | `number` | `1200` | Width in px used for nominal cell boxes on the server and at hydration (REQ-207). Default `1200`. |\n| `link` | `DashboardLink` | | Linked interaction (REQ-216); client entry points only. |\n| `ground` | `GroundRef` | | Inherited by every chart inside, below the chart\'s own prop (REQ-212). |\n| `substrate` | `SubstrateName` | | |\n| `mode` | `InkMode` | | |\n| `locale` | `string` | | |\n| `palette` | `Palette` | | The section\'s colours, written on its root and merged under every chart\'s and component\'s own (REQ-462). |\n| `className` | `string` | | |\n\n## Layout\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `columns` | `PerBreakpoint<number>` | `{ sm: 1, md: 2, lg: 4 }` | Columns per breakpoint. Default `{ sm: 1, md: 2, lg: 4 }` (REQ-208). |\n| `rowHeight` | `number` | `240` | Height of one row unit, in px, card chrome included. Default `240`. |\n| `gap` | `number` | `16` | Gap between cells, in px. Default `16`. |\n| `cells` | `readonly DashboardCellLayout[]` | | Cells in reading order (REQ-203). Omitted: every child, span 1. |\n\n### Cell layout (`layout.cells[]`)\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `id` | `string` | | **Required.** Matches `DashboardCell`\'s `cell` prop; unique within the dashboard (REQ-205). |\n| `colSpan` | `PerBreakpoint<number>` | `1` | Default `1`. Clamped to the breakpoint\'s columns with `SP014` (REQ-204). |\n| `rowSpan` | `PerBreakpoint<number>` | `1` | Default `1`. |\n\n## React\n\n```tsx\nimport { Dashboard, DashboardCell, type DashboardLayout } from \'@silverpoint/react/dashboard\';\nimport { BarChart } from \'@silverpoint/react/bar-chart\';\nimport { KpiCard } from \'@silverpoint/react/kpi-card\';\nimport { LineChart } from \'@silverpoint/react/line-chart\';\n\nconst layout: DashboardLayout = {\n columns: { sm: 1, md: 2, lg: 4 },\n cells: [{ id: \'revenue\' }, { id: \'traffic\', colSpan: { md: 2, lg: 3 }, rowSpan: 2 }, { id: \'errors\' }],\n};\n\n// A type, not an interface: an interface has no index signature, so it is not a `Datum`.\ntype Row = { readonly hour: string; readonly hits: number; readonly errors: number };\n\nexport function Operations({ rows, revenue }: { rows: readonly Row[]; revenue: number }) {\n return (\n <Dashboard id="ops" title="Operations" layout={layout} link={{ key: \'hour\' }}>\n <DashboardCell cell="revenue">\n <KpiCard title="Revenue" data={[{ value: revenue }]} unit="EUR" />\n </DashboardCell>\n <DashboardCell cell="traffic">\n <LineChart title="Traffic" data={rows} xKey="hour" valueKey="hits" />\n </DashboardCell>\n <DashboardCell cell="errors">\n <BarChart title="Errors" data={rows} xKey="hour" valueKey="errors" />\n </DashboardCell>\n </Dashboard>\n );\n}\n```\n\nReact hands each cell\'s box and configuration to its chart as props, so a chart must be the cell\'s\ndirect child.\n\n## Vue\n\n```vue\n<script setup lang="ts">\nimport { SpDashboard, SpDashboardCell, type DashboardLayout } from \'@silverpoint/vue/dashboard\';\nimport { SpBarChart } from \'@silverpoint/vue/bar-chart\';\nimport { SpLineChart } from \'@silverpoint/vue/line-chart\';\n\ndefineProps<{ rows: readonly { hour: string; hits: number; errors: number }[] }>();\n\nconst layout: DashboardLayout = { cells: [{ id: \'traffic\', colSpan: { md: 2, lg: 3 } }, { id: \'errors\' }] };\n</script>\n\n<template>\n <SpDashboard id="ops" title="Operations" :layout="layout" :link="{ key: \'hour\' }">\n <SpDashboardCell cell="traffic"><SpLineChart title="Traffic" :data="rows" x-key="hour" value-key="hits" /></SpDashboardCell>\n <SpDashboardCell cell="errors"><SpBarChart title="Errors" :data="rows" x-key="hour" value-key="errors" /></SpDashboardCell>\n </SpDashboard>\n</template>\n```\n\n## Angular\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, input } from \'@angular/core\';\nimport { SpBarChart } from \'@silverpoint/angular/bar-chart\';\nimport { SpDashboard, SpDashboardCell, type DashboardLayout } from \'@silverpoint/angular/dashboard\';\nimport { SpLineChart } from \'@silverpoint/angular/line-chart\';\n\n@Component({\n selector: \'app-operations\',\n imports: [SpDashboard, SpDashboardCell, SpLineChart, SpBarChart],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-dashboard [id]="\'ops\'" [title]="\'Operations\'" [layout]="layout" [link]="{ key: \'hour\' }">\n <sp-dashboard-cell [cell]="\'traffic\'">\n <sp-line-chart [title]="\'Traffic\'" [data]="rows()" [xKey]="\'hour\'" [valueKey]="\'hits\'" />\n </sp-dashboard-cell>\n <sp-dashboard-cell [cell]="\'errors\'">\n <sp-bar-chart [title]="\'Errors\'" [data]="rows()" [xKey]="\'hour\'" [valueKey]="\'errors\'" />\n </sp-dashboard-cell>\n </sp-dashboard>\n `,\n})\nexport class Operations {\n readonly rows = input.required<readonly { hour: string; hits: number; errors: number }[]>();\n protected readonly layout: DashboardLayout = { cells: [{ id: \'traffic\', colSpan: { md: 2, lg: 3 } }, { id: \'errors\' }] };\n}\n```\n',
11516
+ "ui-components": "<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# UI and composed components\n\n*Describes silverpoint 0.8.0.*\n\nEvery component is named `Sp<Name>` in the three frameworks (`SpButton`, `<sp-input>`), imported\nfrom its own subpath (`@silverpoint/react/ui/button`), and drawn in the same ground as the\ncharts. Import `@silverpoint/grounds/ui.css` once, after `styles.css`.\n\n## Binding a value\n\n| | Controlled | Uncontrolled | Change |\n|---|---|---|---|\n| React | `value` (`checked` for Checkbox and Switch) | `defaultValue` (`defaultChecked`) | `onChange(value)`: the value, not the DOM event |\n| Vue | `v-model` | omit `v-model`, pass `default-value` | `update:modelValue`, then `change` on commit |\n| Angular | `[(value)]`, or `formControl` / `ngModel` | `[defaultValue]` | `(valueChange)` |\n\nValue events fire on user input only, never on a prop change, and never for a disabled component\nor item. Angular value components are `ControlValueAccessor`s, so they work in reactive and\ntemplate-driven forms.\n\n## Server rendering\n\nIn React, display components also have server entries (`@silverpoint/react/server/ui/<name>`):\n`card`, `tag`, `badge`, `divider`, `progress`, `alert`, `skeleton`, `steps`, `surface`, `glyph`,\n`table` (unsortable), `breadcrumb`, `avatar`, `statistic`, `descriptions`, `timeline-list`, `empty`\nand `result`. Every other component is a client component.\n\n## Notes\n\n- `SpButton` is an attribute component in Angular (`<button spButton>`, `<a spButton>`), so your own\n element is the control. `SpSurface` is `[spSurface]` in the same way.\n- `SpTabs` renders `SpTabPanel` children matched by `value`.\n- `SpTable` draws its rows as given: sort them yourself on `onSort` (`@sort`, `(sort)`), which also\n keeps paging with `SpPagination` correct.\n- A link's `href` (`SpButton`, `SpBreadcrumb`) keeps relative URLs and the `http`, `https`,\n `mailto` and `tel` schemes. Any other is dropped with `SP017`.\n- Named content: React takes node props, Vue slots (`prefix`, `suffix`, `extra`, `footer`), and\n Angular templates (`<ng-template spExtra>`, `spFooter`, `spPrefix`, `spSuffix`).\n\n**Contents:** [SpButton](#spbutton) \xB7 [SpInput](#spinput) \xB7 [SpCheckbox](#spcheckbox) \xB7 [SpRadioGroup](#spradiogroup) \xB7 [SpSwitch](#spswitch) \xB7 [SpSlider](#spslider) \xB7 [SpRate](#sprate) \xB7 [SpSegmented](#spsegmented) \xB7 [SpTabs](#sptabs) \xB7 [SpSteps](#spsteps) \xB7 [SpCard](#spcard) \xB7 [SpTag](#sptag) \xB7 [SpBadge](#spbadge) \xB7 [SpDivider](#spdivider) \xB7 [SpProgress](#spprogress) \xB7 [SpAlert](#spalert) \xB7 [SpSkeleton](#spskeleton) \xB7 [SpSurface](#spsurface) \xB7 [SpGlyph](#spglyph) \xB7 [SpTable](#sptable) \xB7 [SpPagination](#sppagination) \xB7 [SpBreadcrumb](#spbreadcrumb) \xB7 [SpAvatar](#spavatar) \xB7 [SpStatistic](#spstatistic) \xB7 [SpDescriptions](#spdescriptions) \xB7 [SpTimelineList](#sptimelinelist) \xB7 [SpCollapse](#spcollapse) \xB7 [SpEmpty](#spempty) \xB7 [SpResult](#spresult) \xB7 [SpTextarea](#sptextarea) \xB7 [SpInputNumber](#spinputnumber)\n\n## SpButton\n\n`button` \xB7 A button or a link styled as one; `primary` and `danger` variants. (actions)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpButton` | `SpButton` | `button[spButton]` | `sp_button` |\n| Import | `@silverpoint/react/ui/button` | `@silverpoint/vue/ui/button` | `@silverpoint/angular/ui/button` | `reflex_silverpoint_react` |\n\n**Events:** React `onClick`; Vue `click`; Angular .\n\n**Content:** React `children`; Vue `default`; Angular `content`.\n\n**States:** `default`, `primary`, `danger`, `disabled`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `variant` | `UiVariant` | `'default'` | Default `'default'`; `danger` also draws the exact \u2715 glyph (REQ-310). |\n| `type` | `'button' \\| 'submit' \\| 'reset'` | `'button'` | Default `'button'`. |\n| `disabled` | `boolean` | | Not focusable, not submitted; drawn with the disabled tone. |\n| `label` | `string` | | Accessible name of an icon-only button (REQ-319). |\n| `block` | `boolean` | | Fills the width of its container. |\n| `href` | `string` | | Renders an `<a>`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpButton } from '@silverpoint/react/ui/button';\n\nexport function ButtonView() {\n return (\n <SpButton>\n Default\n </SpButton>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpButton } from '@silverpoint/vue/ui/button';\n</script>\n\n<template>\n <SpButton>\n Default\n </SpButton>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpButton } from '@silverpoint/angular/ui/button';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-button-view',\n imports: [SpButton],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <button\n spButton\n >\n Default\n </button>\n `,\n})\nexport class ButtonView {}\n```\n\n## SpInput\n\n`input` \xB7 A labelled text field with an optional message and an invalid state. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpInput` | `SpInput` | `sp-input` | `sp_input` |\n| Import | `@silverpoint/react/ui/input` | `@silverpoint/vue/ui/input` | `@silverpoint/angular/ui/input` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**Content:** React `prefix`, `suffix`; Vue `prefix`, `suffix`; Angular `spPrefix`, `spSuffix`.\n\n**States:** `empty`, `filled`, `invalid`, `disabled`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `type` | `'text' \\| 'search' \\| 'email' \\| 'url' \\| 'tel' \\| 'password' \\| 'number'` | `'text'` | Native input type. Default `'text'`. |\n| `placeholder` | `string` | | Hint shown while empty; not a substitute for the accessible name. |\n| `name` | `string` | | Form field name; the native input submits under it (REQ-323). |\n| `disabled` | `boolean` | | Not focusable and not submitted. |\n| `readOnly` | `boolean` | | Focusable and submitted, but not editable. |\n| `invalid` | `boolean` | | Sets `aria-invalid` and draws the exact \u26A0 glyph (REQ-334). |\n| `message` | `string` | | Help or error text under the control, referenced by `aria-describedby` (REQ-334). |\n| `label` | `string` | | Accessible name, when no `<label for>` names the control. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpInput } from '@silverpoint/react/ui/input';\n\nexport function InputView() {\n const [value, setValue] = useState<string>('');\n return (\n <SpInput\n label=\"Search charts\"\n placeholder=\"Search charts\u2026\"\n type=\"search\"\n name=\"q\"\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpInput } from '@silverpoint/vue/ui/input';\n\nconst value = ref<string>('');\n</script>\n\n<template>\n <SpInput\n label=\"Search charts\"\n placeholder=\"Search charts\u2026\"\n type=\"search\"\n name=\"q\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpInput } from '@silverpoint/angular/ui/input';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-input-view',\n imports: [SpInput],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-input\n [label]=\"'Search charts'\"\n [placeholder]=\"'Search charts\u2026'\"\n [type]=\"'search'\"\n [name]=\"'q'\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class InputView {\n protected readonly value = signal<string>('');\n}\n```\n\n## SpCheckbox\n\n`checkbox` \xB7 A labelled checkbox, with an indeterminate state. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpCheckbox` | `SpCheckbox` | `sp-checkbox` | `sp_checkbox` |\n| Import | `@silverpoint/react/ui/checkbox` | `@silverpoint/vue/ui/checkbox` | `@silverpoint/angular/ui/checkbox` | `reflex_silverpoint_react` |\n\n**Value:** React `checked + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**States:** `unchecked`, `checked`, `indeterminate`, `disabled`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `label` | `string` | | **Required.** The visible text and accessible name. |\n| `name` | `string` | | Form field name; submitted as `on` when checked. |\n| `disabled` | `boolean` | | Not focusable and not submitted. |\n| `indeterminate` | `boolean` | | Draws the exact dash and sets the native `indeterminate` state. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpCheckbox } from '@silverpoint/react/ui/checkbox';\n\nexport function CheckboxView() {\n const [value, setValue] = useState<boolean>(false);\n return (\n <SpCheckbox\n label=\"Legend\"\n name=\"legend\"\n checked={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpCheckbox } from '@silverpoint/vue/ui/checkbox';\n\nconst value = ref<boolean>(false);\n</script>\n\n<template>\n <SpCheckbox\n label=\"Legend\"\n name=\"legend\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpCheckbox } from '@silverpoint/angular/ui/checkbox';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-checkbox-view',\n imports: [SpCheckbox],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-checkbox\n [label]=\"'Legend'\"\n [name]=\"'legend'\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class CheckboxView {\n protected readonly value = signal<boolean>(false);\n}\n```\n\n## SpRadioGroup\n\n`radio-group` \xB7 One choice among a few, as a fieldset of radios. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpRadioGroup` | `SpRadioGroup` | `sp-radio-group` | `sp_radio_group` |\n| Import | `@silverpoint/react/ui/radio-group` | `@silverpoint/vue/ui/radio-group` | `@silverpoint/angular/ui/radio-group` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**States:** `selected`, `disabled-item`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly UiItem[]` | | **Required.** The choices; each a native radio. Keys are unique (REQ-325). |\n| `name` | `string` | | **Required.** Required: the native radios submit under it (REQ-323). |\n| `label` | `string` | | **Required.** The group's name, its `<legend>`. |\n| `orientation` | `UiOrientation` | `'vertical'` | Default `'vertical'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpRadioGroup } from '@silverpoint/react/ui/radio-group';\n\nexport function RadioGroupView() {\n const [value, setValue] = useState<string>('silverpoint');\n return (\n <SpRadioGroup\n label=\"Ground\"\n name=\"ground\"\n items={[{ key: 'silverpoint', label: 'silverpoint' }, { key: 'cyanotype', label: 'cyanotype' }]}\n orientation=\"horizontal\"\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpRadioGroup } from '@silverpoint/vue/ui/radio-group';\n\nconst value = ref<string>('silverpoint');\n</script>\n\n<template>\n <SpRadioGroup\n label=\"Ground\"\n name=\"ground\"\n :items=\"[{ key: 'silverpoint', label: 'silverpoint' }, { key: 'cyanotype', label: 'cyanotype' }]\"\n orientation=\"horizontal\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpRadioGroup } from '@silverpoint/angular/ui/radio-group';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-radio-group-view',\n imports: [SpRadioGroup],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-radio-group\n [label]=\"'Ground'\"\n [name]=\"'ground'\"\n [items]=\"[{ key: 'silverpoint', label: 'silverpoint' }, { key: 'cyanotype', label: 'cyanotype' }]\"\n [orientation]=\"'horizontal'\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class RadioGroupView {\n protected readonly value = signal<string>('silverpoint');\n}\n```\n\n## SpSwitch\n\n`switch` \xB7 An on/off toggle with the switch role. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpSwitch` | `SpSwitch` | `sp-switch` | `sp_switch` |\n| Import | `@silverpoint/react/ui/switch` | `@silverpoint/vue/ui/switch` | `@silverpoint/angular/ui/switch` | `reflex_silverpoint_react` |\n\n**Value:** React `checked + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**States:** `off`, `on`, `disabled`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `label` | `string` | | **Required.** The visible text and accessible name. |\n| `name` | `string` | | Form field name; submitted as `on` when on. |\n| `disabled` | `boolean` | | Not focusable and not submitted. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpSwitch } from '@silverpoint/react/ui/switch';\n\nexport function SwitchView() {\n const [value, setValue] = useState<boolean>(false);\n return (\n <SpSwitch\n label=\"Linked hover\"\n name=\"linked\"\n checked={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpSwitch } from '@silverpoint/vue/ui/switch';\n\nconst value = ref<boolean>(false);\n</script>\n\n<template>\n <SpSwitch\n label=\"Linked hover\"\n name=\"linked\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpSwitch } from '@silverpoint/angular/ui/switch';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-switch-view',\n imports: [SpSwitch],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-switch\n [label]=\"'Linked hover'\"\n [name]=\"'linked'\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class SwitchView {\n protected readonly value = signal<boolean>(false);\n}\n```\n\n## SpSlider\n\n`slider` \xB7 A value on a range, with optional marks. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpSlider` | `SpSlider` | `sp-slider` | `sp_slider` |\n| Import | `@silverpoint/react/ui/slider` | `@silverpoint/vue/ui/slider` | `@silverpoint/angular/ui/slider` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**States:** `marks`, `disabled`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `label` | `string` | | **Required.** Accessible name of the native range input. |\n| `min` | `number` | `0` | Default `0`. |\n| `max` | `number` | `100` | Default `100`. |\n| `step` | `number` | `1` | Default `1`. |\n| `name` | `string` | | Form field name; the native input submits under it. |\n| `disabled` | `boolean` | | Not focusable and not submitted. |\n| `marks` | `readonly number[]` | | Values on the rail that get a labelled mark. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpSlider } from '@silverpoint/react/ui/slider';\n\nexport function SliderView() {\n const [value, setValue] = useState<number>(30);\n return (\n <SpSlider\n label=\"Volume\"\n name=\"volume\"\n marks={[0, 25, 50, 75, 100]}\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpSlider } from '@silverpoint/vue/ui/slider';\n\nconst value = ref<number>(30);\n</script>\n\n<template>\n <SpSlider\n label=\"Volume\"\n name=\"volume\"\n :marks=\"[0, 25, 50, 75, 100]\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpSlider } from '@silverpoint/angular/ui/slider';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-slider-view',\n imports: [SpSlider],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-slider\n [label]=\"'Volume'\"\n [name]=\"'volume'\"\n [marks]=\"[0, 25, 50, 75, 100]\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class SliderView {\n protected readonly value = signal<number>(30);\n}\n```\n\n## SpRate\n\n`rate` \xB7 A rating from 1 to `count`, optionally read-only. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpRate` | `SpRate` | `sp-rate` | `sp_rate` |\n| Import | `@silverpoint/react/ui/rate` | `@silverpoint/vue/ui/rate` | `@silverpoint/angular/ui/rate` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**States:** `three`, `read-only`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `label` | `string` | | **Required.** The group's name, its `<legend>`. |\n| `count` | `number` | `5` | Default `5`, in 1..10; each mark an exact lozenge. |\n| `name` | `string` | | Form field name; the native radios submit under it. |\n| `disabled` | `boolean` | | Not focusable and not submitted. |\n| `readOnly` | `boolean` | | Shows the value; the keyboard and the pointer do not change it. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpRate } from '@silverpoint/react/ui/rate';\n\nexport function RateView() {\n const [value, setValue] = useState<number>(3);\n return (\n <SpRate\n label=\"Quality\"\n name=\"quality\"\n count={5}\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpRate } from '@silverpoint/vue/ui/rate';\n\nconst value = ref<number>(3);\n</script>\n\n<template>\n <SpRate\n label=\"Quality\"\n name=\"quality\"\n :count=\"5\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpRate } from '@silverpoint/angular/ui/rate';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-rate-view',\n imports: [SpRate],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-rate\n [label]=\"'Quality'\"\n [name]=\"'quality'\"\n [count]=\"5\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class RateView {\n protected readonly value = signal<number>(3);\n}\n```\n\n## SpSegmented\n\n`segmented` \xB7 One choice among a few, as joined segments. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpSegmented` | `SpSegmented` | `sp-segmented` | `sp_segmented` |\n| Import | `@silverpoint/react/ui/segmented` | `@silverpoint/vue/ui/segmented` | `@silverpoint/angular/ui/segmented` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**States:** `first`, `middle`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly UiItem[]` | | **Required.** The options; each a native radio. Keys are unique (REQ-325). |\n| `label` | `string` | | **Required.** The control's name, its `<legend>`. |\n| `name` | `string` | | Form field name; the native radios submit under it. |\n| `block` | `boolean` | | Fills the width of its container. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpSegmented } from '@silverpoint/react/ui/segmented';\n\nexport function SegmentedView() {\n const [value, setValue] = useState<string>('day');\n return (\n <SpSegmented\n label=\"Period\"\n name=\"period\"\n items={[{ key: 'day', label: 'Day' }, { key: 'week', label: 'Week' }, { key: 'month', label: 'Month' }, { key: 'year', label: 'Year' }]}\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpSegmented } from '@silverpoint/vue/ui/segmented';\n\nconst value = ref<string>('day');\n</script>\n\n<template>\n <SpSegmented\n label=\"Period\"\n name=\"period\"\n :items=\"[{ key: 'day', label: 'Day' }, { key: 'week', label: 'Week' }, { key: 'month', label: 'Month' }, { key: 'year', label: 'Year' }]\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpSegmented } from '@silverpoint/angular/ui/segmented';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-segmented-view',\n imports: [SpSegmented],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-segmented\n [label]=\"'Period'\"\n [name]=\"'period'\"\n [items]=\"[{ key: 'day', label: 'Day' }, { key: 'week', label: 'Week' }, { key: 'month', label: 'Month' }, { key: 'year', label: 'Year' }]\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class SegmentedView {\n protected readonly value = signal<string>('day');\n}\n```\n\n## SpTabs\n\n`tabs` \xB7 Tabs and their panels (`SpTabPanel`), with automatic or manual activation. (navigation)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpTabs` | `SpTabs` | `sp-tabs` | `sp_tabs` |\n| Import | `@silverpoint/react/ui/tabs` | `@silverpoint/vue/ui/tabs` | `@silverpoint/angular/ui/tabs` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**Content:** React `children`; Vue `default`; Angular `content`.\n\n**States:** `first`, `disabled-tab`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly UiItem[]` | | **Required.** The tabs; a disabled one is skipped by the arrows. Keys are unique (REQ-325). |\n| `label` | `string` | | Accessible name of the tab list. |\n| `orientation` | `UiOrientation` | `'horizontal'` | Default `'horizontal'`. |\n| `activation` | `'automatic' \\| 'manual'` | `'automatic'` | Default `'automatic'`: a tab is selected as focus reaches it. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpTabs } from '@silverpoint/react/ui/tabs';\n\nexport function TabsView() {\n const [value, setValue] = useState<string>('overview');\n return (\n <SpTabs\n label=\"Views\"\n items={[{ key: 'overview', label: 'Overview' }, { key: 'traffic', label: 'Traffic' }, { key: 'errors', label: 'Errors' }, { key: 'settings', label: 'Settings' }]}\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpTabs } from '@silverpoint/vue/ui/tabs';\n\nconst value = ref<string>('overview');\n</script>\n\n<template>\n <SpTabs\n label=\"Views\"\n :items=\"[{ key: 'overview', label: 'Overview' }, { key: 'traffic', label: 'Traffic' }, { key: 'errors', label: 'Errors' }, { key: 'settings', label: 'Settings' }]\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpTabs } from '@silverpoint/angular/ui/tabs';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-tabs-view',\n imports: [SpTabs],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-tabs\n [label]=\"'Views'\"\n [items]=\"[{ key: 'overview', label: 'Overview' }, { key: 'traffic', label: 'Traffic' }, { key: 'errors', label: 'Errors' }, { key: 'settings', label: 'Settings' }]\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class TabsView {\n protected readonly value = signal<string>('overview');\n}\n```\n\n## SpSteps\n\n`steps` \xB7 The steps of a process, with the current one and an error state. (navigation)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpSteps` | `SpSteps` | `sp-steps` | `sp_steps` |\n| Import | `@silverpoint/react/ui/steps` | `@silverpoint/vue/ui/steps` | `@silverpoint/angular/ui/steps` | `reflex_silverpoint_react` |\n\n**States:** `current`, `error`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly StepItem[]` | | **Required.** The steps, in order; a status is derived from `current` unless set. |\n| `current` | `number` | | **Required.** 0-based. |\n| `orientation` | `UiOrientation` | `'horizontal'` | Default `'horizontal'`. |\n| `label` | `string` | | Accessible name of the list. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpSteps } from '@silverpoint/react/ui/steps';\n\nexport function StepsView() {\n return (\n <SpSteps\n label=\"Release\"\n items={[{ key: 'install', title: 'Install' }, { key: 'import', title: 'Import' }, { key: 'configure', title: 'Configure' }, { key: 'publish', title: 'Publish' }]}\n current={2}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpSteps } from '@silverpoint/vue/ui/steps';\n</script>\n\n<template>\n <SpSteps\n label=\"Release\"\n :items=\"[{ key: 'install', title: 'Install' }, { key: 'import', title: 'Import' }, { key: 'configure', title: 'Configure' }, { key: 'publish', title: 'Publish' }]\"\n :current=\"2\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpSteps } from '@silverpoint/angular/ui/steps';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-steps-view',\n imports: [SpSteps],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-steps\n [label]=\"'Release'\"\n [items]=\"[{ key: 'install', title: 'Install' }, { key: 'import', title: 'Import' }, { key: 'configure', title: 'Configure' }, { key: 'publish', title: 'Publish' }]\"\n [current]=\"2\"\n />\n `,\n})\nexport class StepsView {}\n```\n\n## SpCard\n\n`card` \xB7 A framed card with a title, an extra slot and a footer. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpCard` | `SpCard` | `sp-card` | `sp_card` |\n| Import | `@silverpoint/react/ui/card` | `@silverpoint/vue/ui/card` | `@silverpoint/angular/ui/card` | `reflex_silverpoint_react` |\n\n**Content:** React `children`, `extra`, `footer`; Vue `default`, `extra`, `footer`; Angular `content`, `spExtra`, `spFooter`.\n\n**States:** `plain`, `titled`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `title` | `string` | | Heading of the card; without it the card is a plain container. |\n| `headingLevel` | `2 \\| 3 \\| 4 \\| 5 \\| 6` | `3` | Default `3`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpCard } from '@silverpoint/react/ui/card';\n\nexport function CardView() {\n return (\n <SpCard>\n Hits per hour rose through the afternoon and eased at night.\n </SpCard>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpCard } from '@silverpoint/vue/ui/card';\n</script>\n\n<template>\n <SpCard>\n Hits per hour rose through the afternoon and eased at night.\n </SpCard>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpCard } from '@silverpoint/angular/ui/card';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-card-view',\n imports: [SpCard],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-card>\n Hits per hour rose through the afternoon and eased at night.\n </sp-card>\n `,\n})\nexport class CardView {}\n```\n\n## SpTag\n\n`tag` \xB7 A short toned label, optionally closable. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpTag` | `SpTag` | `sp-tag` | `sp_tag` |\n| Import | `@silverpoint/react/ui/tag` | `@silverpoint/vue/ui/tag` | `@silverpoint/angular/ui/tag` | `reflex_silverpoint_react` |\n\n**Events:** React `onClose`; Vue `close`; Angular `close`.\n\n**Content:** React `children`; Vue `default`; Angular `content`.\n\n**States:** `tone-1`, `closable`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `tone` | `UiToneLevel` | | Tonal level, default `1`. |\n| `closable` | `boolean` | | Adds a native close button; each adapter raises its close event. |\n| `closeLabel` | `string` | `Remove <text>` | Accessible name of the close button. Default `Remove <text>`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTag } from '@silverpoint/react/ui/tag';\n\nexport function TagView() {\n return (\n <SpTag\n tone={1}\n >\n draft\n </SpTag>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTag } from '@silverpoint/vue/ui/tag';\n</script>\n\n<template>\n <SpTag\n :tone=\"1\"\n >\n draft\n </SpTag>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpTag } from '@silverpoint/angular/ui/tag';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-tag-view',\n imports: [SpTag],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-tag\n [tone]=\"1\"\n >\n draft\n </sp-tag>\n `,\n})\nexport class TagView {}\n```\n\n## SpBadge\n\n`badge` \xB7 A count or a dot over its content. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpBadge` | `SpBadge` | `sp-badge` | `sp_badge` |\n| Import | `@silverpoint/react/ui/badge` | `@silverpoint/vue/ui/badge` | `@silverpoint/angular/ui/badge` | `reflex_silverpoint_react` |\n\n**Content:** React `children`; Vue `default`; Angular `content`.\n\n**States:** `count`, `dot`, `overflow`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `count` | `number` | | The number shown, up to `max`. |\n| `max` | `number` | `99` | Default `99`; above it the badge reads `99+`. |\n| `dot` | `boolean` | | A dot with no number. |\n| `label` | `string` | | Accessible text of the badge, e.g. `unread messages`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpBadge } from '@silverpoint/react/ui/badge';\n\nexport function BadgeView() {\n return (\n <SpBadge\n count={12}\n >\n Inbox\n </SpBadge>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpBadge } from '@silverpoint/vue/ui/badge';\n</script>\n\n<template>\n <SpBadge\n :count=\"12\"\n >\n Inbox\n </SpBadge>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpBadge } from '@silverpoint/angular/ui/badge';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-badge-view',\n imports: [SpBadge],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-badge\n [count]=\"12\"\n >\n Inbox\n </sp-badge>\n `,\n})\nexport class BadgeView {}\n```\n\n## SpDivider\n\n`divider` \xB7 A rule between sections, optionally with text. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpDivider` | `SpDivider` | `sp-divider` | `sp_divider` |\n| Import | `@silverpoint/react/ui/divider` | `@silverpoint/vue/ui/divider` | `@silverpoint/angular/ui/divider` | `reflex_silverpoint_react` |\n\n**States:** `plain`, `text`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `orientation` | `UiOrientation` | `'horizontal'` | Default `'horizontal'`. |\n| `text` | `string` | | A caption set in the rule. |\n| `align` | `'start' \\| 'center' \\| 'end'` | `'center'` | Default `'center'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDivider } from '@silverpoint/react/ui/divider';\n\nexport function DividerView() {\n return (\n <SpDivider />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDivider } from '@silverpoint/vue/ui/divider';\n</script>\n\n<template>\n <SpDivider />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpDivider } from '@silverpoint/angular/ui/divider';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-divider-view',\n imports: [SpDivider],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-divider />\n `,\n})\nexport class DividerView {}\n```\n\n## SpProgress\n\n`progress` \xB7 Progress as a line or a circle, or indeterminate. (feedback)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpProgress` | `SpProgress` | `sp-progress` | `sp_progress` |\n| Import | `@silverpoint/react/ui/progress` | `@silverpoint/vue/ui/progress` | `@silverpoint/angular/ui/progress` | `reflex_silverpoint_react` |\n\n**States:** `line`, `circle`, `indeterminate`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `value` | `number` | | 0..100; omitted, the progress is indeterminate. |\n| `shape` | `'line' \\| 'circle'` | `'line'` | Default `'line'`. |\n| `label` | `string` | | **Required.** Accessible name (REQ-318). |\n| `showValue` | `boolean` | `true` | Default `true`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpProgress } from '@silverpoint/react/ui/progress';\n\nexport function ProgressView() {\n return (\n <SpProgress\n label=\"Upload\"\n value={40}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpProgress } from '@silverpoint/vue/ui/progress';\n</script>\n\n<template>\n <SpProgress\n label=\"Upload\"\n :value=\"40\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpProgress } from '@silverpoint/angular/ui/progress';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-progress-view',\n imports: [SpProgress],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-progress\n [label]=\"'Upload'\"\n [value]=\"40\"\n />\n `,\n})\nexport class ProgressView {}\n```\n\n## SpAlert\n\n`alert` \xB7 An info, success, warning or error message, optionally closable. (feedback)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpAlert` | `SpAlert` | `sp-alert` | `sp_alert` |\n| Import | `@silverpoint/react/ui/alert` | `@silverpoint/vue/ui/alert` | `@silverpoint/angular/ui/alert` | `reflex_silverpoint_react` |\n\n**Events:** React `onClose`; Vue `close`; Angular `close`.\n\n**Content:** React `children`; Vue `default`; Angular `content`.\n\n**States:** `info`, `success`, `warning`, `error`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `kind` | `AlertKind` | `'info'` | Default `'info'`. |\n| `title` | `string` | | Bold first line of the alert. |\n| `closable` | `boolean` | | Adds a native close button; each adapter raises its close event. |\n| `closeLabel` | `string` | `'Close'` | Accessible name of the close button. Default `'Close'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpAlert } from '@silverpoint/react/ui/alert';\n\nexport function AlertView() {\n return (\n <SpAlert\n kind=\"info\"\n title=\"New ground available\"\n >\n cyanotype ships in 0.2.0.\n </SpAlert>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpAlert } from '@silverpoint/vue/ui/alert';\n</script>\n\n<template>\n <SpAlert\n kind=\"info\"\n title=\"New ground available\"\n >\n cyanotype ships in 0.2.0.\n </SpAlert>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpAlert } from '@silverpoint/angular/ui/alert';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-alert-view',\n imports: [SpAlert],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-alert\n [kind]=\"'info'\"\n [title]=\"'New ground available'\"\n >\n cyanotype ships in 0.2.0.\n </sp-alert>\n `,\n})\nexport class AlertView {}\n```\n\n## SpSkeleton\n\n`skeleton` \xB7 A placeholder for content that is loading. (feedback)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpSkeleton` | `SpSkeleton` | `sp-skeleton` | `sp_skeleton` |\n| Import | `@silverpoint/react/ui/skeleton` | `@silverpoint/vue/ui/skeleton` | `@silverpoint/angular/ui/skeleton` | `reflex_silverpoint_react` |\n\n**States:** `paragraph`, `avatar`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `lines` | `number` | `3` | Default `3`, in 1..8. |\n| `avatar` | `boolean` | | Draws an avatar placeholder before the lines. |\n| `label` | `string` | `'Loading'` | Default `'Loading'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpSkeleton } from '@silverpoint/react/ui/skeleton';\n\nexport function SkeletonView() {\n return (\n <SpSkeleton\n lines={3}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpSkeleton } from '@silverpoint/vue/ui/skeleton';\n</script>\n\n<template>\n <SpSkeleton\n :lines=\"3\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpSkeleton } from '@silverpoint/angular/ui/skeleton';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-skeleton-view',\n imports: [SpSkeleton],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-skeleton\n [lines]=\"3\"\n />\n `,\n})\nexport class SkeletonView {}\n```\n\n## SpSurface\n\n`surface` \xB7 A framed, toned surface to build your own components on. (building-blocks)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpSurface` | `SpSurface` | `[spSurface]` | `sp_surface` |\n| Import | `@silverpoint/react/ui/surface` | `@silverpoint/vue/ui/surface` | `@silverpoint/angular/ui/surface` | `reflex_silverpoint_react` |\n\n**Content:** React `children`; Vue `default`; Angular `content`.\n\n**States:** `frame-card`, `tone-2`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `as` | `string` | `'div'` | The element, a lowercase HTML tag name. Default `'div'`. |\n| `name` | `string` | | Adds the class `sp-<name>`, a lowercase ident. |\n| `frame` | `UiFrameKind` | | Draws a frame of that kind. |\n| `tone` | `UiToneLevel \\| string` | | Lays a tone: a level 1-4 of the ramp, or a state (`selected`, `primary`\u2026). |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpSurface } from '@silverpoint/react/ui/surface';\n\nexport function SurfaceView() {\n return (\n <SpSurface\n frame=\"card\"\n >\n A surface takes the ground: its substrate, its ink and a hand-drawn frame.\n </SpSurface>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpSurface } from '@silverpoint/vue/ui/surface';\n</script>\n\n<template>\n <SpSurface\n frame=\"card\"\n >\n A surface takes the ground: its substrate, its ink and a hand-drawn frame.\n </SpSurface>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpSurface } from '@silverpoint/angular/ui/surface';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-surface-view',\n imports: [SpSurface],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <div\n spSurface\n [frame]=\"'card'\"\n >\n A surface takes the ground: its substrate, its ink and a hand-drawn frame.\n </div>\n `,\n})\nexport class SurfaceView {}\n```\n\n## SpGlyph\n\n`glyph` \xB7 One of the exact glyphs the components draw (tick, cross, arrows, chevrons\u2026). (building-blocks)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpGlyph` | `SpGlyph` | `sp-glyph` | `sp_glyph` |\n| Import | `@silverpoint/react/ui/glyph` | `@silverpoint/vue/ui/glyph` | `@silverpoint/angular/ui/glyph` | `reflex_silverpoint_react` |\n\n**States:** `all`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `glyph` | `string` | | **Required.** A key of `UI_GLYPHS`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpGlyph } from '@silverpoint/react/ui/glyph';\n\nexport function GlyphView() {\n return (\n <SpGlyph\n glyph=\"tick\"\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpGlyph } from '@silverpoint/vue/ui/glyph';\n</script>\n\n<template>\n <SpGlyph\n glyph=\"tick\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpGlyph } from '@silverpoint/angular/ui/glyph';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-glyph-view',\n imports: [SpGlyph],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-glyph\n [glyph]=\"'tick'\"\n />\n `,\n})\nexport class GlyphView {}\n```\n\n## SpTable\n\n`table` \xB7 A data table with sortable columns, stripes and an empty state. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpTable` | `SpTable` | `sp-table` | `sp_table` |\n| Import | `@silverpoint/react/ui/table` | `@silverpoint/vue/ui/table` | `@silverpoint/angular/ui/table` | `reflex_silverpoint_react` |\n\n**Events:** React `onSort`; Vue `sort`; Angular `sort`.\n\n**States:** `plain`, `sorted-striped`, `empty`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `columns` | `readonly TableColumn[]` | | **Required.** The columns, in order; each names the key it reads from a row. |\n| `data` | `readonly Readonly<Record<string, unknown>>[]` | | **Required.** The rows, drawn as given: the consumer sorts them (DD-040). |\n| `caption` | `string` | | The table's `<caption>`, its accessible name. |\n| `sortKey` | `string` | | A sortable column's key; another key sorts nothing, silently. |\n| `sortOrder` | `'asc' \\| 'desc'` | `'asc'` | Default `'asc'`. |\n| `striped` | `boolean` | `false` | Default `false`. |\n| `hoverable` | `boolean` | `true` | Default `true`. |\n| `bordered` | `boolean` | `true` | Default `true`. |\n| `emptyText` | `string` | `'No data'` | Default `'No data'`. |\n| `rowKey` | `string` | | The column whose value keys each row. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTable } from '@silverpoint/react/ui/table';\n\nexport function TableView() {\n return (\n <SpTable\n caption=\"Orders\"\n columns={[{ key: 'order', title: 'Order' }, { key: 'customer', title: 'Customer', sortable: true }, { key: 'status', title: 'Status' }, { key: 'amount', title: 'Amount', align: 'end', sortable: true }]}\n data={[{ order: '1042', customer: 'Ada Lovelace', status: 'Shipped', amount: 128 }, { order: '1043', customer: 'Grace Hopper', status: 'Packed', amount: 64.5 }, { order: '1044', customer: 'Alan Turing', status: 'Paid', amount: 312 }, { order: '1045', customer: 'Emmy Noether', status: 'Placed', amount: 18.25 }, { order: '1046', customer: 'Kurt G\xF6del', status: 'Shipped', amount: 96 }]}\n rowKey=\"order\"\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTable } from '@silverpoint/vue/ui/table';\n</script>\n\n<template>\n <SpTable\n caption=\"Orders\"\n :columns=\"[{ key: 'order', title: 'Order' }, { key: 'customer', title: 'Customer', sortable: true }, { key: 'status', title: 'Status' }, { key: 'amount', title: 'Amount', align: 'end', sortable: true }]\"\n :data=\"[{ order: '1042', customer: 'Ada Lovelace', status: 'Shipped', amount: 128 }, { order: '1043', customer: 'Grace Hopper', status: 'Packed', amount: 64.5 }, { order: '1044', customer: 'Alan Turing', status: 'Paid', amount: 312 }, { order: '1045', customer: 'Emmy Noether', status: 'Placed', amount: 18.25 }, { order: '1046', customer: 'Kurt G\xF6del', status: 'Shipped', amount: 96 }]\"\n rowKey=\"order\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpTable } from '@silverpoint/angular/ui/table';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-table-view',\n imports: [SpTable],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-table\n [caption]=\"'Orders'\"\n [columns]=\"[{ key: 'order', title: 'Order' }, { key: 'customer', title: 'Customer', sortable: true }, { key: 'status', title: 'Status' }, { key: 'amount', title: 'Amount', align: 'end', sortable: true }]\"\n [data]=\"[{ order: '1042', customer: 'Ada Lovelace', status: 'Shipped', amount: 128 }, { order: '1043', customer: 'Grace Hopper', status: 'Packed', amount: 64.5 }, { order: '1044', customer: 'Alan Turing', status: 'Paid', amount: 312 }, { order: '1045', customer: 'Emmy Noether', status: 'Placed', amount: 18.25 }, { order: '1046', customer: 'Kurt G\xF6del', status: 'Shipped', amount: 96 }]\"\n [rowKey]=\"'order'\"\n />\n `,\n})\nexport class TableView {}\n```\n\n## SpPagination\n\n`pagination` \xB7 Page navigation with a current page, siblings and an optional total. (navigation)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpPagination` | `SpPagination` | `sp-pagination` | `sp_pagination` |\n| Import | `@silverpoint/react/ui/pagination` | `@silverpoint/vue/ui/pagination` | `@silverpoint/angular/ui/pagination` | `reflex_silverpoint_react` |\n\n**Value:** React `current + onChange`, Vue `v-model:current`, Angular `[(current)]`.\n\n**Events:** React `onChange`; Vue ; Angular .\n\n**States:** `middle`, `total`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `total` | `number` | | **Required.** The number of items paged over. |\n| `pageSize` | `number` | `10` | Default `10`. |\n| `siblings` | `number` | `1` | Pages shown on each side of the current one. Default `1`. |\n| `showTotal` | `boolean` | `false` | Default `false`. |\n| `totalTemplate` | `string` | `'{start}\u2013{end} of {total}'` | Default `'{start}\u2013{end} of {total}'`. |\n| `label` | `string` | `'Pagination'` | Default `'Pagination'`. |\n| `previousLabel` | `string` | `'Previous page'` | Default `'Previous page'`. |\n| `nextLabel` | `string` | `'Next page'` | Default `'Next page'`. |\n| `pageLabel` | `string` | `'Page'` | Default `'Page'`. |\n| `disabled` | `boolean` | | Every page button disabled. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpPagination } from '@silverpoint/react/ui/pagination';\n\nexport function PaginationView() {\n const [value, setValue] = useState<number>(10);\n return (\n <SpPagination\n total={200}\n pageSize={10}\n current={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpPagination } from '@silverpoint/vue/ui/pagination';\n\nconst value = ref<number>(10);\n</script>\n\n<template>\n <SpPagination\n :total=\"200\"\n :pageSize=\"10\"\n v-model:current=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpPagination } from '@silverpoint/angular/ui/pagination';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-pagination-view',\n imports: [SpPagination],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-pagination\n [total]=\"200\"\n [pageSize]=\"10\"\n [(current)]=\"value\"\n />\n `,\n})\nexport class PaginationView {\n protected readonly value = signal<number>(10);\n}\n```\n\n## SpBreadcrumb\n\n`breadcrumb` \xB7 The trail of pages to the current one. (navigation)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpBreadcrumb` | `SpBreadcrumb` | `sp-breadcrumb` | `sp_breadcrumb` |\n| Import | `@silverpoint/react/ui/breadcrumb` | `@silverpoint/vue/ui/breadcrumb` | `@silverpoint/angular/ui/breadcrumb` | `reflex_silverpoint_react` |\n\n**States:** `three`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly BreadcrumbItem[]` | | **Required.** The last item is the current page. |\n| `label` | `string` | `'Breadcrumb'` | Default `'Breadcrumb'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpBreadcrumb } from '@silverpoint/react/ui/breadcrumb';\n\nexport function BreadcrumbView() {\n return (\n <SpBreadcrumb\n items={[{ key: 'home', label: 'Home', href: '/' }, { key: 'orders', label: 'Orders', href: '/orders' }, { key: '1042', label: 'Order 1042' }]}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpBreadcrumb } from '@silverpoint/vue/ui/breadcrumb';\n</script>\n\n<template>\n <SpBreadcrumb\n :items=\"[{ key: 'home', label: 'Home', href: '/' }, { key: 'orders', label: 'Orders', href: '/orders' }, { key: '1042', label: 'Order 1042' }]\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpBreadcrumb } from '@silverpoint/angular/ui/breadcrumb';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-breadcrumb-view',\n imports: [SpBreadcrumb],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-breadcrumb\n [items]=\"[{ key: 'home', label: 'Home', href: '/' }, { key: 'orders', label: 'Orders', href: '/orders' }, { key: '1042', label: 'Order 1042' }]\"\n />\n `,\n})\nexport class BreadcrumbView {}\n```\n\n## SpAvatar\n\n`avatar` \xB7 A picture or initials in a round or square frame; `SpAvatarGroup` stacks several. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpAvatar` | `SpAvatar` | `sp-avatar` | `sp_avatar` |\n| Import | `@silverpoint/react/ui/avatar` | `@silverpoint/vue/ui/avatar` | `@silverpoint/angular/ui/avatar` | `reflex_silverpoint_react` |\n\n**States:** `initials`, `square`, `group`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `src` | `string` | | An image; the initials are drawn without one. |\n| `name` | `string` | | The person's name: the accessible name and the source of the initials. |\n| `initials` | `string` | | Overrides the initials derived from `name`. |\n| `alt` | `string` | | Overrides `name` as the accessible name. |\n| `shape` | `'circle' \\| 'square'` | `'circle'` | Default `'circle'`. |\n| `pixelSize` | `number` | | Side length in px; the ground's control height when omitted. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpAvatar } from '@silverpoint/react/ui/avatar';\n\nexport function AvatarView() {\n return (\n <SpAvatar\n name=\"Ada Lovelace\"\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpAvatar } from '@silverpoint/vue/ui/avatar';\n</script>\n\n<template>\n <SpAvatar\n name=\"Ada Lovelace\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpAvatar } from '@silverpoint/angular/ui/avatar';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-avatar-view',\n imports: [SpAvatar],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-avatar\n [name]=\"'Ada Lovelace'\"\n />\n `,\n})\nexport class AvatarView {}\n```\n\n## SpStatistic\n\n`statistic` \xB7 A titled figure with a prefix, a suffix and an optional trend. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpStatistic` | `SpStatistic` | `sp-statistic` | `sp_statistic` |\n| Import | `@silverpoint/react/ui/statistic` | `@silverpoint/vue/ui/statistic` | `@silverpoint/angular/ui/statistic` | `reflex_silverpoint_react` |\n\n**States:** `plain`, `trend-down`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `title` | `string` | | **Required.** The label above the value. |\n| `value` | `string \\| number` | | **Required.** Printed as given. |\n| `prefix` | `string` | | Printed before the value (`$`). |\n| `suffix` | `string` | | Printed after the value (`%`). |\n| `trend` | `'up' \\| 'down'` | | Draws the exact \u2191 or \u2193 glyph beside the delta. |\n| `delta` | `string` | | The change, as text (`+4.2%`). |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpStatistic } from '@silverpoint/react/ui/statistic';\n\nexport function StatisticView() {\n return (\n <SpStatistic\n title=\"Orders\"\n value={1284}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpStatistic } from '@silverpoint/vue/ui/statistic';\n</script>\n\n<template>\n <SpStatistic\n title=\"Orders\"\n :value=\"1284\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpStatistic } from '@silverpoint/angular/ui/statistic';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-statistic-view',\n imports: [SpStatistic],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-statistic\n [title]=\"'Orders'\"\n [value]=\"1284\"\n />\n `,\n})\nexport class StatisticView {}\n```\n\n## SpDescriptions\n\n`descriptions` \xB7 Label and value pairs as a description list. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpDescriptions` | `SpDescriptions` | `sp-descriptions` | `sp_descriptions` |\n| Import | `@silverpoint/react/ui/descriptions` | `@silverpoint/vue/ui/descriptions` | `@silverpoint/angular/ui/descriptions` | `reflex_silverpoint_react` |\n\n**States:** `bordered`, `plain`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly DescriptionItem[]` | | **Required.** The label\u2013value pairs, a `<dl>`. Keys, when given, are unique (REQ-325). |\n| `title` | `string` | | A heading above the list, at `headingLevel`. |\n| `columns` | `number` | `3` | Default `3`, in 1..6. |\n| `bordered` | `boolean` | `true` | Default `true`. |\n| `headingLevel` | `2 \\| 3 \\| 4 \\| 5 \\| 6` | `3` | Default `3`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDescriptions } from '@silverpoint/react/ui/descriptions';\n\nexport function DescriptionsView() {\n return (\n <SpDescriptions\n title=\"Order 1042\"\n items={[{ key: 'customer', label: 'Customer', value: 'Ada Lovelace' }, { key: 'status', label: 'Status', value: 'Shipped' }, { key: 'amount', label: 'Amount', value: '128.00' }, { key: 'placed', label: 'Placed', value: '14 October 2026' }]}\n columns={2}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDescriptions } from '@silverpoint/vue/ui/descriptions';\n</script>\n\n<template>\n <SpDescriptions\n title=\"Order 1042\"\n :items=\"[{ key: 'customer', label: 'Customer', value: 'Ada Lovelace' }, { key: 'status', label: 'Status', value: 'Shipped' }, { key: 'amount', label: 'Amount', value: '128.00' }, { key: 'placed', label: 'Placed', value: '14 October 2026' }]\"\n :columns=\"2\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpDescriptions } from '@silverpoint/angular/ui/descriptions';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-descriptions-view',\n imports: [SpDescriptions],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-descriptions\n [title]=\"'Order 1042'\"\n [items]=\"[{ key: 'customer', label: 'Customer', value: 'Ada Lovelace' }, { key: 'status', label: 'Status', value: 'Shipped' }, { key: 'amount', label: 'Amount', value: '128.00' }, { key: 'placed', label: 'Placed', value: '14 October 2026' }]\"\n [columns]=\"2\"\n />\n `,\n})\nexport class DescriptionsView {}\n```\n\n## SpTimelineList\n\n`timeline-list` \xB7 Events in order, each done, current, pending or in error. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpTimelineList` | `SpTimelineList` | `sp-timeline-list` | `sp_timeline_list` |\n| Import | `@silverpoint/react/ui/timeline-list` | `@silverpoint/vue/ui/timeline-list` | `@silverpoint/angular/ui/timeline-list` | `reflex_silverpoint_react` |\n\n**States:** `mixed`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly TimelineListItem[]` | | **Required.** The events, in reading order. |\n| `label` | `string` | | Accessible name of the list. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTimelineList } from '@silverpoint/react/ui/timeline-list';\n\nexport function TimelineListView() {\n return (\n <SpTimelineList\n label=\"Order history\"\n items={[{ key: 'placed', title: 'Placed', time: '14 Oct, 09:12', description: 'Two prints, one framed.' }, { key: 'paid', title: 'Payment', time: '14 Oct, 09:14', description: 'Card declined; paid on the second try.', status: 'error' }, { key: 'packed', title: 'Packed', time: '15 Oct, 16:40', status: 'current' }, { key: 'shipped', title: 'Shipped', status: 'pending' }]}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTimelineList } from '@silverpoint/vue/ui/timeline-list';\n</script>\n\n<template>\n <SpTimelineList\n label=\"Order history\"\n :items=\"[{ key: 'placed', title: 'Placed', time: '14 Oct, 09:12', description: 'Two prints, one framed.' }, { key: 'paid', title: 'Payment', time: '14 Oct, 09:14', description: 'Card declined; paid on the second try.', status: 'error' }, { key: 'packed', title: 'Packed', time: '15 Oct, 16:40', status: 'current' }, { key: 'shipped', title: 'Shipped', status: 'pending' }]\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpTimelineList } from '@silverpoint/angular/ui/timeline-list';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-timeline-list-view',\n imports: [SpTimelineList],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-timeline-list\n [label]=\"'Order history'\"\n [items]=\"[{ key: 'placed', title: 'Placed', time: '14 Oct, 09:12', description: 'Two prints, one framed.' }, { key: 'paid', title: 'Payment', time: '14 Oct, 09:14', description: 'Card declined; paid on the second try.', status: 'error' }, { key: 'packed', title: 'Packed', time: '15 Oct, 16:40', status: 'current' }, { key: 'shipped', title: 'Shipped', status: 'pending' }]\"\n />\n `,\n})\nexport class TimelineListView {}\n```\n\n## SpCollapse\n\n`collapse` \xB7 Disclosure panels (`SpCollapseItem`), optionally as an accordion. (disclosure)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpCollapse` | `SpCollapse` | `sp-collapse` | `sp_collapse` |\n| Import | `@silverpoint/react/ui/collapse` | `@silverpoint/vue/ui/collapse` | `@silverpoint/angular/ui/collapse` | `reflex_silverpoint_react` |\n\n**Content:** React `children`; Vue `default`; Angular `content`.\n\n**States:** `one-open`, `accordion-disabled`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `accordion` | `boolean` | `false` | One item open at a time, natively (`<details name>`). Default `false`. |\n| `bordered` | `boolean` | `true` | Default `true`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpCollapse } from '@silverpoint/react/ui/collapse';\n\nexport function CollapseView() {\n return (\n <SpCollapse />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpCollapse } from '@silverpoint/vue/ui/collapse';\n</script>\n\n<template>\n <SpCollapse />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpCollapse } from '@silverpoint/angular/ui/collapse';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-collapse-view',\n imports: [SpCollapse],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-collapse />\n `,\n})\nexport class CollapseView {}\n```\n\n## SpEmpty\n\n`empty` \xB7 The empty state of a list or a table. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpEmpty` | `SpEmpty` | `sp-empty` | `sp_empty` |\n| Import | `@silverpoint/react/ui/empty` | `@silverpoint/vue/ui/empty` | `@silverpoint/angular/ui/empty` | `reflex_silverpoint_react` |\n\n**Content:** React `extra`; Vue `extra`; Angular `spExtra`.\n\n**States:** `plain`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `description` | `string` | `'No data'` | Default `'No data'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpEmpty } from '@silverpoint/react/ui/empty';\n\nexport function EmptyView() {\n return (\n <SpEmpty\n description=\"No orders yet\"\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpEmpty } from '@silverpoint/vue/ui/empty';\n</script>\n\n<template>\n <SpEmpty\n description=\"No orders yet\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpEmpty } from '@silverpoint/angular/ui/empty';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-empty-view',\n imports: [SpEmpty],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-empty\n [description]=\"'No orders yet'\"\n />\n `,\n})\nexport class EmptyView {}\n```\n\n## SpResult\n\n`result` \xB7 The outcome of an action: success, error, information or warning. (data-display)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpResult` | `SpResult` | `sp-result` | `sp_result` |\n| Import | `@silverpoint/react/ui/result` | `@silverpoint/vue/ui/result` | `@silverpoint/angular/ui/result` | `reflex_silverpoint_react` |\n\n**Content:** React `extra`; Vue `extra`; Angular `spExtra`.\n\n**States:** `success`, `error`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `status` | `AlertKind` | `'info'` | Default `'info'`. |\n| `title` | `string` | | **Required.** The heading, at `headingLevel`. |\n| `subtitle` | `string` | | A paragraph under the title. |\n| `headingLevel` | `2 \\| 3 \\| 4 \\| 5 \\| 6` | `3` | Default `3`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpResult } from '@silverpoint/react/ui/result';\n\nexport function ResultView() {\n return (\n <SpResult\n status=\"success\"\n title=\"Order placed\"\n subtitle=\"Order 1042 is on its way to the workshop.\"\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpResult } from '@silverpoint/vue/ui/result';\n</script>\n\n<template>\n <SpResult\n status=\"success\"\n title=\"Order placed\"\n subtitle=\"Order 1042 is on its way to the workshop.\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpResult } from '@silverpoint/angular/ui/result';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-result-view',\n imports: [SpResult],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-result\n [status]=\"'success'\"\n [title]=\"'Order placed'\"\n [subtitle]=\"'Order 1042 is on its way to the workshop.'\"\n />\n `,\n})\nexport class ResultView {}\n```\n\n## SpTextarea\n\n`textarea` \xB7 A multi-line text field with a counter and an invalid state. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpTextarea` | `SpTextarea` | `sp-textarea` | `sp_textarea` |\n| Import | `@silverpoint/react/ui/textarea` | `@silverpoint/vue/ui/textarea` | `@silverpoint/angular/ui/textarea` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue `change`; Angular .\n\n**States:** `count`, `invalid`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `rows` | `number` | `3` | Default `3`. |\n| `placeholder` | `string` | | Hint shown while empty; not a substitute for the accessible name. |\n| `label` | `string` | | Accessible name, when no `<label for>` names the control. |\n| `message` | `string` | | Help or error text under the control, referenced by `aria-describedby` (REQ-334). |\n| `invalid` | `boolean` | | Sets `aria-invalid` and draws the exact \u26A0 glyph (REQ-334). |\n| `disabled` | `boolean` | | Not focusable and not submitted. |\n| `readOnly` | `boolean` | | Focusable and submitted, but not editable. |\n| `maxLength` | `number` | | The native limit; the counter shows it with `showCount`. |\n| `showCount` | `boolean` | `false` | Default `false`. |\n| `name` | `string` | | Form field name; the native textarea submits under it (REQ-323). |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpTextarea } from '@silverpoint/react/ui/textarea';\n\nexport function TextareaView() {\n const [value, setValue] = useState<string>('Leave it at the door.');\n return (\n <SpTextarea\n label=\"Notes\"\n name=\"notes\"\n maxLength={120}\n showCount={true}\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpTextarea } from '@silverpoint/vue/ui/textarea';\n\nconst value = ref<string>('Leave it at the door.');\n</script>\n\n<template>\n <SpTextarea\n label=\"Notes\"\n name=\"notes\"\n :maxLength=\"120\"\n :showCount=\"true\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpTextarea } from '@silverpoint/angular/ui/textarea';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-textarea-view',\n imports: [SpTextarea],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-textarea\n [label]=\"'Notes'\"\n [name]=\"'notes'\"\n [maxLength]=\"120\"\n [showCount]=\"true\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class TextareaView {\n protected readonly value = signal<string>('Leave it at the door.');\n}\n```\n\n## SpInputNumber\n\n`input-number` \xB7 A number field with steppers, bounds and precision. (data-entry)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpInputNumber` | `SpInputNumber` | `sp-input-number` | `sp_input_number` |\n| Import | `@silverpoint/react/ui/input-number` | `@silverpoint/vue/ui/input-number` | `@silverpoint/angular/ui/input-number` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Events:** React `onChange`; Vue ; Angular .\n\n**States:** `value`, `at-min`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `min` | `number` | | The lowest value; the value is clamped to it (REQ-485). |\n| `max` | `number` | | The highest value; the value is clamped to it (REQ-485). |\n| `step` | `number` | `1` | Default `1`. |\n| `precision` | `number` | | Decimals. |\n| `placeholder` | `string` | | Hint shown while empty; not a substitute for the accessible name. |\n| `label` | `string` | | Accessible name, when no `<label for>` names the control. |\n| `message` | `string` | | Help or error text under the control, referenced by `aria-describedby` (REQ-334). |\n| `invalid` | `boolean` | | Sets `aria-invalid` and draws the exact \u26A0 glyph (REQ-334). |\n| `disabled` | `boolean` | | Not focusable and not submitted; the steppers are disabled too. |\n| `readOnly` | `boolean` | | Focusable and submitted, but not editable. |\n| `name` | `string` | | Form field name; the native input submits under it (REQ-323). |\n| `decrementLabel` | `string` | `'Decrease'` | Default `'Decrease'`. |\n| `incrementLabel` | `string` | `'Increase'` | Default `'Increase'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpInputNumber } from '@silverpoint/react/ui/input-number';\n\nexport function InputNumberView() {\n const [value, setValue] = useState<number | null>(3);\n return (\n <SpInputNumber\n label=\"Quantity\"\n name=\"quantity\"\n min={1}\n max={10}\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpInputNumber } from '@silverpoint/vue/ui/input-number';\n\nconst value = ref<number | null>(3);\n</script>\n\n<template>\n <SpInputNumber\n label=\"Quantity\"\n name=\"quantity\"\n :min=\"1\"\n :max=\"10\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpInputNumber } from '@silverpoint/angular/ui/input-number';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-input-number-view',\n imports: [SpInputNumber],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-input-number\n [label]=\"'Quantity'\"\n [name]=\"'quantity'\"\n [min]=\"1\"\n [max]=\"10\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class InputNumberView {\n protected readonly value = signal<number | null>(3);\n}\n```\n",
11517
+ "overlays": "<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Overlays\n\n*Describes silverpoint 0.8.0.*\n\nModal, Drawer, Popover, Tooltip, Select, DropdownMenu and Toast are built on the platform's\n`<dialog>` and Popover API. They are client components only.\n\n## The trigger is a native button\n\nGive every overlay a native `<button type=\"button\">` as its trigger:\n\n- **React:** the `trigger` prop, `trigger={<button type=\"button\">Edit</button>}`. The overlay\n clones it with its ARIA and its toggle. Do not pass `SpButton`: it drops the ARIA it is given.\n- **Vue:** the `trigger` slot, `<template #trigger><button type=\"button\">Edit</button></template>`.\n Its first element is cloned.\n- **Angular:** project the button with the `spTrigger` directive,\n `<button type=\"button\" spTrigger>Edit</button>`, and import `SpTrigger` from the overlay's own\n subpath.\n\n## Open state\n\n| | Controlled | Uncontrolled | Change |\n|---|---|---|---|\n| React | `open` | `defaultOpen` | `onOpenChange(open)` |\n| Vue | `v-model:open` | `default-open` | `update:open` |\n| Angular | `[(open)]` | `[defaultOpen]` | `(openChange)` |\n\n`onOpenChange` also fires when the platform closes it: Escape, or a click outside. A Modal with\n`dismissible={false}` ignores both.\n\n## Toasts\n\nPut one `SpToaster` near the root and render `SpToast` children inside it. A toast closes after the\ntoaster's `duration` (5000 ms) unless its own `duration` says otherwise. It pauses while hovered or\nfocused, and F8 moves focus to the toaster.\n\n## Sides\n\nSides are logical, `start` and `end`, so they mirror in right-to-left pages. Reflex's `left` and\n`right` become `start` and `end`.\n\n**Contents:** [SpModal](#spmodal) \xB7 [SpDrawer](#spdrawer) \xB7 [SpPopover](#sppopover) \xB7 [SpTooltip](#sptooltip) \xB7 [SpSelect](#spselect) \xB7 [SpDropdownMenu](#spdropdownmenu) \xB7 [SpToast](#sptoast)\n\n## SpModal\n\n`modal` \xB7 A modal dialog on the native `<dialog>`, opened by its trigger. (overlays)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpModal` | `SpModal` | `sp-modal` | `sp_modal` |\n| Import | `@silverpoint/react/ui/modal` | `@silverpoint/vue/ui/modal` | `@silverpoint/angular/ui/modal` | `reflex_silverpoint_react` |\n\n**Open state:** React `open + onOpenChange`, Vue `v-model:open`, Angular `[(open)]`.\n\n**Events:** React `onOpenChange`; Vue ; Angular .\n\n**Content:** React `children`, `footer`, `trigger`; Vue `default`, `footer`, `trigger`; Angular `content`, `spFooter`, `spTrigger`.\n\n**States:** `open`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `title` | `string` | | The heading, `${id}--title`, that names the dialog. |\n| `description` | `string` | | A paragraph, `${id}--description`, that describes the dialog. |\n| `label` | `string` | | Accessible name without a title (REQ-501). |\n| `closable` | `boolean` | `true` | Default `true`. |\n| `closeLabel` | `string` | `'Close'` | Default `'Close'`. |\n| `width` | `string` | `'520px'` | CSS length. Default `'520px'` (from `ui.css`). |\n| `dismissible` | `boolean` | `true` | Escape and a backdrop click close it. Default `true`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpModal } from '@silverpoint/react/ui/modal';\n\nexport function ModalView() {\n return (\n <SpModal\n title=\"Edit order\"\n description=\"Order 1042, placed on 14 October.\"\n trigger={<button type=\"button\">Edit order</button>}\n >\n Changes reach the workshop before the order is packed.\n </SpModal>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpModal } from '@silverpoint/vue/ui/modal';\n</script>\n\n<template>\n <SpModal\n title=\"Edit order\"\n description=\"Order 1042, placed on 14 October.\"\n >\n <template #trigger><button type=\"button\">Edit order</button></template>\n Changes reach the workshop before the order is packed.\n </SpModal>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpModal, SpTrigger } from '@silverpoint/angular/ui/modal';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-modal-view',\n imports: [SpModal, SpTrigger],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-modal\n [title]=\"'Edit order'\"\n [description]=\"'Order 1042, placed on 14 October.'\"\n >\n <button type=\"button\" spTrigger>Edit order</button>\n Changes reach the workshop before the order is packed.\n </sp-modal>\n `,\n})\nexport class ModalView {}\n```\n\n## SpDrawer\n\n`drawer` \xB7 A dialog sliding in from one side of the viewport. (overlays)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpDrawer` | `SpDrawer` | `sp-drawer` | `sp_drawer` |\n| Import | `@silverpoint/react/ui/drawer` | `@silverpoint/vue/ui/drawer` | `@silverpoint/angular/ui/drawer` | `reflex_silverpoint_react` |\n\n**Open state:** React `open + onOpenChange`, Vue `v-model:open`, Angular `[(open)]`.\n\n**Events:** React `onOpenChange`; Vue ; Angular .\n\n**Content:** React `children`, `footer`, `trigger`; Vue `default`, `footer`, `trigger`; Angular `content`, `spFooter`, `spTrigger`.\n\n**States:** `end-open`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `side` | `'start' \\| 'end' \\| 'top' \\| 'bottom'` | `'end'` | Default `'end'`. |\n| `extent` | `string` | `'380px'` | CSS length across the side. Default `'380px'` (start/end) or `'320px'` (top/bottom). |\n| `modal` | `boolean` | `true` | `false` opens with `show()`. Default `true`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDrawer } from '@silverpoint/react/ui/drawer';\n\nexport function DrawerView() {\n return (\n <SpDrawer\n side=\"end\"\n trigger={<button type=\"button\">Filters</button>}\n >\n Narrow the orders by status, customer or amount.\n </SpDrawer>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDrawer } from '@silverpoint/vue/ui/drawer';\n</script>\n\n<template>\n <SpDrawer\n side=\"end\"\n >\n <template #trigger><button type=\"button\">Filters</button></template>\n Narrow the orders by status, customer or amount.\n </SpDrawer>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpDrawer, SpTrigger } from '@silverpoint/angular/ui/drawer';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-drawer-view',\n imports: [SpDrawer, SpTrigger],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-drawer\n [side]=\"'end'\"\n >\n <button type=\"button\" spTrigger>Filters</button>\n Narrow the orders by status, customer or amount.\n </sp-drawer>\n `,\n})\nexport class DrawerView {}\n```\n\n## SpPopover\n\n`popover` \xB7 Non-modal content anchored to its trigger, on the Popover API. (overlays)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpPopover` | `SpPopover` | `sp-popover` | `sp_popover` |\n| Import | `@silverpoint/react/ui/popover` | `@silverpoint/vue/ui/popover` | `@silverpoint/angular/ui/popover` | `reflex_silverpoint_react` |\n\n**Open state:** React `open + onOpenChange`, Vue `v-model:open`, Angular `[(open)]`.\n\n**Events:** React `onOpenChange`; Vue ; Angular .\n\n**Content:** React `children`, `trigger`; Vue `default`, `trigger`; Angular `content`, `spTrigger`.\n\n**States:** `open`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `title` | `string` | | A heading that names the popover. |\n| `label` | `string` | | Accessible name without a title. |\n| `side` | `'top' \\| 'end' \\| 'bottom' \\| 'start'` | `'bottom'` | Default `'bottom'`. |\n| `align` | `'start' \\| 'center' \\| 'end'` | `'center'` | Default `'center'`. |\n| `offset` | `number` | `6` | Default `6`. |\n| `closable` | `boolean` | `false` | Default `false`. |\n| `closeLabel` | `string` | `'Close'` | Default `'Close'`. |\n| `width` | `string` | `'320px'` | CSS length. Default `'320px'` (from `ui.css`). |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpPopover } from '@silverpoint/react/ui/popover';\n\nexport function PopoverView() {\n return (\n <SpPopover\n title=\"Order 1042\"\n trigger={<button type=\"button\">Details</button>}\n >\n Two prints, one framed; shipped on 16 October.\n </SpPopover>\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpPopover } from '@silverpoint/vue/ui/popover';\n</script>\n\n<template>\n <SpPopover\n title=\"Order 1042\"\n >\n <template #trigger><button type=\"button\">Details</button></template>\n Two prints, one framed; shipped on 16 October.\n </SpPopover>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpPopover, SpTrigger } from '@silverpoint/angular/ui/popover';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-popover-view',\n imports: [SpPopover, SpTrigger],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-popover\n [title]=\"'Order 1042'\"\n >\n <button type=\"button\" spTrigger>Details</button>\n Two prints, one framed; shipped on 16 October.\n </sp-popover>\n `,\n})\nexport class PopoverView {}\n```\n\n## SpTooltip\n\n`tooltip` \xB7 A short text shown on hover or focus of its trigger. (overlays)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpTooltip` | `SpTooltip` | `sp-tooltip` | `sp_tooltip` |\n| Import | `@silverpoint/react/ui/tooltip` | `@silverpoint/vue/ui/tooltip` | `@silverpoint/angular/ui/tooltip` | `reflex_silverpoint_react` |\n\n**Open state:** React `open + onOpenChange`, Vue `v-model:open`, Angular `[(open)]`.\n\n**Events:** React `onOpenChange`; Vue ; Angular .\n\n**Content:** React `trigger`; Vue `trigger`; Angular `spTrigger`.\n\n**States:** `open`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `text` | `string` | | **Required.** The tooltip, the trigger's accessible description. |\n| `side` | `'top' \\| 'end' \\| 'bottom' \\| 'start'` | `'top'` | Default `'top'`. |\n| `align` | `'start' \\| 'center' \\| 'end'` | `'center'` | Default `'center'`. |\n| `offset` | `number` | `6` | Default `6`. |\n| `delay` | `number` | `300` | Default `300` ms. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTooltip } from '@silverpoint/react/ui/tooltip';\n\nexport function TooltipView() {\n return (\n <SpTooltip\n text=\"Copy the order id\"\n trigger={<button type=\"button\">Copy id</button>}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpTooltip } from '@silverpoint/vue/ui/tooltip';\n</script>\n\n<template>\n <SpTooltip\n text=\"Copy the order id\"\n >\n <template #trigger><button type=\"button\">Copy id</button></template>\n </SpTooltip>\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpTooltip, SpTrigger } from '@silverpoint/angular/ui/tooltip';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-tooltip-view',\n imports: [SpTooltip, SpTrigger],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-tooltip\n [text]=\"'Copy the order id'\"\n >\n <button type=\"button\" spTrigger>Copy id</button>\n </sp-tooltip>\n `,\n})\nexport class TooltipView {}\n```\n\n## SpSelect\n\n`select` \xB7 A select-only combobox: one option from a list. (overlays)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpSelect` | `SpSelect` | `sp-select` | `sp_select` |\n| Import | `@silverpoint/react/ui/select` | `@silverpoint/vue/ui/select` | `@silverpoint/angular/ui/select` | `reflex_silverpoint_react` |\n\n**Value:** React `value + onChange`, Vue `v-model`, Angular `[(value)]`.\n\n**Open state:** React `open + onOpenChange`, Vue `v-model:open`, Angular `[(open)]`.\n\n**Events:** React `onChange`, `onOpenChange`; Vue ; Angular .\n\n**States:** `placeholder`, `open-selected`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly (string \\| UiItem)[]` | | **Required.** A string is its own key and label. |\n| `placeholder` | `string` | `'Select\u2026'` | Default `'Select\u2026'`. |\n| `label` | `string` | | **Required.** Accessible name of the combobox. |\n| `disabled` | `boolean` | | Not focusable and not submitted. |\n| `required` | `boolean` | | Sets `aria-required` on the combobox. |\n| `name` | `string` | | Submits the key under this name, from a hidden input (REQ-323). |\n| `width` | `string` | `'180px'` | CSS length. Default `'180px'` (from `ui.css`). |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpSelect } from '@silverpoint/react/ui/select';\n\nexport function SelectView() {\n const [value, setValue] = useState<string | undefined>(undefined);\n return (\n <SpSelect\n label=\"Status\"\n name=\"status\"\n items={[{ key: 'placed', label: 'Placed' }, { key: 'paid', label: 'Paid' }, { key: 'packed', label: 'Packed' }, { key: 'shipped', label: 'Shipped' }, { key: 'returned', label: 'Returned', disabled: true }]}\n value={value}\n onChange={setValue}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpSelect } from '@silverpoint/vue/ui/select';\n\nconst value = ref<string>();\n</script>\n\n<template>\n <SpSelect\n label=\"Status\"\n name=\"status\"\n :items=\"[{ key: 'placed', label: 'Placed' }, { key: 'paid', label: 'Paid' }, { key: 'packed', label: 'Packed' }, { key: 'shipped', label: 'Shipped' }, { key: 'returned', label: 'Returned', disabled: true }]\"\n v-model=\"value\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpSelect } from '@silverpoint/angular/ui/select';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-select-view',\n imports: [SpSelect],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-select\n [label]=\"'Status'\"\n [name]=\"'status'\"\n [items]=\"[{ key: 'placed', label: 'Placed' }, { key: 'paid', label: 'Paid' }, { key: 'packed', label: 'Packed' }, { key: 'shipped', label: 'Shipped' }, { key: 'returned', label: 'Returned', disabled: true }]\"\n [(value)]=\"value\"\n />\n `,\n})\nexport class SelectView {\n protected readonly value = signal<string | undefined>(undefined);\n}\n```\n\n## SpDropdownMenu\n\n`dropdown-menu` \xB7 A menu of actions opened from its trigger. (overlays)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpDropdownMenu` | `SpDropdownMenu` | `sp-dropdown-menu` | `sp_dropdown_menu` |\n| Import | `@silverpoint/react/ui/dropdown-menu` | `@silverpoint/vue/ui/dropdown-menu` | `@silverpoint/angular/ui/dropdown-menu` | `reflex_silverpoint_react` |\n\n**Open state:** React `open + onOpenChange`, Vue `v-model:open`, Angular `[(open)]`.\n\n**Events:** React `onOpenChange`, `onSelect`; Vue `select`; Angular `select`.\n\n**Content:** React `trigger`; Vue `trigger`; Angular `spTrigger`.\n\n**States:** `open`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `items` | `readonly MenuEntry[]` | | **Required.** Items, separators and labels, in order. Keys are unique (REQ-325). |\n| `label` | `string` | | **Required.** The menu's accessible name and the trigger's text when no trigger slot. |\n| `side` | `'top' \\| 'end' \\| 'bottom' \\| 'start'` | `'bottom'` | Default `'bottom'`. |\n| `align` | `'start' \\| 'center' \\| 'end'` | `'start'` | Default `'start'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDropdownMenu } from '@silverpoint/react/ui/dropdown-menu';\n\nexport function DropdownMenuView() {\n return (\n <SpDropdownMenu\n label=\"Actions\"\n items={[{ type: 'label', key: 'order', label: 'Order 1042' }, { key: 'edit', label: 'Edit', shortcut: 'E' }, { key: 'duplicate', label: 'Duplicate', shortcut: 'D' }, { key: 'archive', label: 'Archive', disabled: true }, { type: 'separator', key: 'end' }, { key: 'delete', label: 'Delete', danger: true }]}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { SpDropdownMenu } from '@silverpoint/vue/ui/dropdown-menu';\n</script>\n\n<template>\n <SpDropdownMenu\n label=\"Actions\"\n :items=\"[{ type: 'label', key: 'order', label: 'Order 1042' }, { key: 'edit', label: 'Edit', shortcut: 'E' }, { key: 'duplicate', label: 'Duplicate', shortcut: 'D' }, { key: 'archive', label: 'Archive', disabled: true }, { type: 'separator', key: 'end' }, { key: 'delete', label: 'Delete', danger: true }]\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpDropdownMenu } from '@silverpoint/angular/ui/dropdown-menu';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-dropdown-menu-view',\n imports: [SpDropdownMenu],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-dropdown-menu\n [label]=\"'Actions'\"\n [items]=\"[{ type: 'label', key: 'order', label: 'Order 1042' }, { key: 'edit', label: 'Edit', shortcut: 'E' }, { key: 'duplicate', label: 'Duplicate', shortcut: 'D' }, { key: 'archive', label: 'Archive', disabled: true }, { type: 'separator', key: 'end' }, { key: 'delete', label: 'Delete', danger: true }]\"\n />\n `,\n})\nexport class DropdownMenuView {}\n```\n\n## SpToast\n\n`toast` \xB7 A transient message in a `SpToaster`, with an optional action. (overlays)\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpToast` | `SpToast` | `sp-toast` | `sp_toast` |\n| Import | `@silverpoint/react/ui/toast` | `@silverpoint/vue/ui/toast` | `@silverpoint/angular/ui/toast` | `reflex_silverpoint_react` |\n\n**Open state:** React `open + onOpenChange`, Vue `v-model:open`, Angular `[(open)]`.\n\n**Events:** React `onOpenChange`; Vue ; Angular .\n\n**Content:** React `action`; Vue `action`; Angular `spAction`.\n\n**States:** `info`, `error-action`.\n\n### Props\n\nIts own props, beside the common ones (`id`, `seed`, `ground`, `substrate`, `mode`, `palette`, `size`, `className`).\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `title` | `string` | | **Required.** The toast's first line. |\n| `description` | `string` | | A line under the title. |\n| `kind` | `AlertKind` | `'info'` | Default `'info'`. |\n| `duration` | `number` | | ms, at least 1000, or `Infinity`; the toaster's when omitted. |\n| `closeLabel` | `string` | `'Dismiss'` | Default `'Dismiss'`. |\n\n### Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { useState } from 'react';\nimport { SpToast } from '@silverpoint/react/ui/toast';\n\nexport function ToastView() {\n const [open, setOpen] = useState<boolean>(true);\n return (\n <SpToast\n kind=\"info\"\n title=\"Order saved\"\n description=\"Order 1042 was updated.\"\n open={open}\n onOpenChange={setOpen}\n />\n );\n}\n```\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpToast } from '@silverpoint/vue/ui/toast';\n\nconst open = ref<boolean>(true);\n</script>\n\n<template>\n <SpToast\n kind=\"info\"\n title=\"Order saved\"\n description=\"Order 1042 was updated.\"\n v-model:open=\"open\"\n />\n</template>\n```\n\n```ts angular\nimport { ChangeDetectionStrategy, Component, signal } from '@angular/core';\nimport { SpToast } from '@silverpoint/angular/ui/toast';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-toast-view',\n imports: [SpToast],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-toast\n [kind]=\"'info'\"\n [title]=\"'Order saved'\"\n [description]=\"'Order 1042 was updated.'\"\n [(open)]=\"open\"\n />\n `,\n})\nexport class ToastView {\n protected readonly open = signal<boolean>(true);\n}\n```\n",
11518
+ "timeline": "<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Timeline\n\n*Describes silverpoint 0.8.0.*\n\n`SpTimeline` is a skin over TimelineJS: its slides, eras and navigation, drawn in the ground's\nframes and type. TimelineJS is an **optional peer**. Install it yourself before you import the\n`timeline` subpath, or the build cannot resolve it:\n\n```sh\nnpm install @knight-lab/timelinejs@^3.9.13\n```\n\nImport TimelineJS's stylesheet before silverpoint's:\n`@knight-lab/timelinejs/dist/css/timeline.css`, then `@silverpoint/grounds/timeline.css`.\n\n- `data` is TimelineJS's JSON: `title`, `events`, `eras`, `scale`. The component builds TimelineJS on\n a copy, so your object is never changed.\n- TimelineJS loads on the client only. If it fails to load, the `fallback` (React prop, Vue slot,\n Angular `<ng-template spFallback>`) is shown and `SP025` is warned.\n- `options` passes TimelineJS options through, except `font` and `theme`, which the ground sets.\n- `height` is a CSS length (`'600px'` by default). Anything else is dropped with `SP017`.\n- Its events are `change` (the slide's `unique_id`), `loaded`, `navNext`, `navPrevious`, `zoomIn`,\n `zoomOut` and `backToStart`: React `onChange`\u2026, Vue emits, Angular outputs.\n\n| | React | Vue | Angular | Reflex |\n|---|---|---|---|---|\n| Name | `SpTimeline` | `SpTimeline` | `sp-timeline` | `sp_timeline` |\n| Import | `@silverpoint/react/timeline` | `@silverpoint/vue/timeline` | `@silverpoint/angular/timeline` | `reflex_silverpoint_react` |\n\nOptional peer: `@knight-lab/timelinejs@^3.9.13`.\n\n| Prop | Type | Default | Notes |\n|---|---|---|---|\n| `data` | `TimelineData` | | **Required.** TimelineJS's JSON: a `title` slide, the `events`, optional `eras` and `scale`. |\n| `options` | `Readonly<Record<string, unknown>>` | | TimelineJS options; `font` and `theme` are ignored, the skin sets both. |\n| `height` | `string` | `'600px'` | A plain CSS length. Default `'600px'`. |\n| `inkedFrames` | `boolean` | `true` | Lays the ground's frames and tones on TimelineJS's pieces (REQ-512). Default `true`. |\n| `card` | `boolean` | `true` | Frames the whole timeline as a card. Default `true`. |\n| `label` | `string` | | The region's accessible name; the title's headline when omitted. |\n\n```tsx\nimport '@knight-lab/timelinejs/dist/css/timeline.css';\nimport '@silverpoint/grounds/timeline.css';\nimport { SpTimeline } from '@silverpoint/react/timeline';\n\nconst data = {\n title: { text: { headline: 'Releases' } },\n events: [\n { start_date: { year: 2026, month: 9, day: 26 }, text: { headline: '0.2.0', text: 'The dashboard.' } },\n { start_date: { year: 2026, month: 10, day: 1 }, text: { headline: '0.3.0', text: 'UI components.' } },\n ],\n};\n\nexport function Releases() {\n return <SpTimeline data={data} height=\"480px\" label=\"Release history\" fallback={<p>The timeline could not load.</p>} />;\n}\n```\n",
11519
+ "react": "<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# React\n\n*Describes silverpoint 0.8.0.*\n\n```sh\nnpm install @silverpoint/react @silverpoint/grounds @silverpoint/fonts\n```\n\nReact 18 and 19 are supported. Import the stylesheets once, in the entry file or the root layout:\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\n\nexport {};\n```\n\n## Names and imports\n\nCharts carry no prefix (`LineChart`) and components carry `Sp` (`SpModal`). Each one is imported\nfrom its own subpath: `@silverpoint/react/line-chart`, `@silverpoint/react/ui/modal`. The barrel\n`@silverpoint/react` holds the charts and `SilverpointProvider`, but a subpath keeps the bundle\nsmall.\n\n## Server Components and Next.js\n\n- `@silverpoint/react/<chart>` is a client entry (`\"use client\"`), with pointer and keyboard\n interaction. It renders on the server too and hydrates with no mismatch.\n- `@silverpoint/react/server/<chart>` renders pure SVG with no client JavaScript. On its own it needs\n `id`, `width` and `height` (`SP002`, `SP003` without them). Inside a `Dashboard`, the cell gives\n them. It takes no event handlers.\n- `@silverpoint/react/server/dashboard` is the server dashboard. It takes no `link`.\n- Display components have server entries as well (`@silverpoint/react/server/ui/card`\u2026). The\n overlays and every component with state are client-only.\n\n## Events and the handle\n\n`onActiveChange(item | null)`, `onSelect(item)` and, on the sunburst and the squarified treemap,\n`onRootChange(id | null)`. A `ref` gives `getGeometry()` and `toSVGString()`, which serialises the\nchart with its palette.\n\n## Example\n\n```tsx\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport { sanguine } from '@silverpoint/core/palettes';\nimport { LineChart } from '@silverpoint/react/line-chart';\n\nexport function LineChartView({ rows }: { rows: readonly Record<string, unknown>[] }) {\n return (\n <LineChart\n data={rows}\n xKey=\"hour\"\n valueKey=\"hits\"\n secondaryKey=\"baseline\"\n title=\"Line chart\"\n palette={sanguine}\n />\n );\n}\n```\n\nA custom readout replaces the built-in tooltip:\n\n```tsx\nimport { LineChart } from '@silverpoint/react/line-chart';\n\nexport function Hits({ rows }: { rows: readonly { hour: string; hits: number }[] }) {\n return (\n <LineChart\n title=\"Hits per hour\"\n data={rows}\n xKey=\"hour\"\n valueKey=\"hits\"\n tooltip={(active) => <span>{String(active.datum.hour)}: {active.value} hits</span>}\n />\n );\n}\n```\n",
11520
+ "vue": "<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Vue\n\n*Describes silverpoint 0.8.0.*\n\n```sh\nnpm install @silverpoint/vue @silverpoint/grounds @silverpoint/fonts\n```\n\nVue 3. Import the stylesheets once, in `main.ts`, and set the application's defaults with the\nplugin:\n\n```ts vue\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { provideSilverpoint } from '@silverpoint/vue';\nimport { createApp, h } from 'vue';\n\ncreateApp({ render: () => h('main') })\n .use(provideSilverpoint({ ground: 'silverpoint', substrate: 'cream' }))\n .mount('#app');\n```\n\n## Names and props\n\nEvery component is `Sp<Name>`: `SpLineChart`, `SpModal`. Each one is imported from its own subpath,\n`@silverpoint/vue/line-chart` or `@silverpoint/vue/ui/modal`. Props are the same camelCase names as\nin React. In a template, write them in kebab-case (`x-key`, `value-key`) and bind non-strings with\n`:` (`:data=\"rows\"`, `:height=\"240\"`).\n\n- Values: `v-model`. Open state: `v-model:open`. Pagination: `v-model:current`.\n- Events: `@active-change`, `@select`, `@root-change`, `@sort`, `@toggle`.\n- Content: slots `trigger`, `footer`, `extra`, `prefix`, `suffix`, `action`, `fallback`, `tooltip`.\n- A section of the page: `<SilverpointProvider :palette=\"sepia\">`. It renders no element of its\n own.\n- Server rendering works with `@vue/server-renderer`. Nuxt is not a validated integration.\n\n## Example\n\n```vue\n<script setup lang=\"ts\">\nimport '@silverpoint/fonts/fonts.css';\nimport '@silverpoint/grounds/styles.css';\nimport '@silverpoint/grounds/ui.css';\nimport { ref } from 'vue';\nimport { SpSelect } from '@silverpoint/vue/ui/select';\n\nconst value = ref<string>();\n</script>\n\n<template>\n <SpSelect\n label=\"Status\"\n name=\"status\"\n :items=\"[{ key: 'placed', label: 'Placed' }, { key: 'paid', label: 'Paid' }, { key: 'packed', label: 'Packed' }, { key: 'shipped', label: 'Shipped' }, { key: 'returned', label: 'Returned', disabled: true }]\"\n v-model=\"value\"\n />\n</template>\n```\n",
11521
+ "angular": "<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Angular\n\n*Describes silverpoint 0.8.0.*\n\n```sh\nnpm install @silverpoint/angular @silverpoint/grounds @silverpoint/fonts\n```\n\nAdd the stylesheets to the `styles` array of `angular.json`, in this order:\n`@silverpoint/fonts/fonts.css`, `@silverpoint/grounds/styles.css`, and\n`@silverpoint/grounds/ui.css` if you use components.\n\n```ts angular\nimport { bootstrapApplication } from '@angular/platform-browser';\nimport { Component } from '@angular/core';\nimport { provideSilverpoint } from '@silverpoint/angular';\n\n@Component({ selector: 'app-root', template: '' })\nclass App {}\n\nbootstrapApplication(App, { providers: [provideSilverpoint({ ground: 'silverpoint', substrate: 'cream' })] }).catch(console.error);\n```\n\n## Components\n\nEvery chart and component is a standalone component with signal inputs and `OnPush`, imported from\nits own secondary entry point: `@silverpoint/angular/line-chart`, `@silverpoint/angular/ui/modal`.\nSelectors are `sp-<name>`. The exceptions are `SpButton` (`<button spButton>`) and `SpSurface`\n(`[spSurface]`), which sit on your own element.\n\n- **Bind every input**, strings included: `[title]=\"'Traffic'\"`. `strictTemplates` checks\n bindings, while a static attribute with a misspelt name passes silently.\n- Values: `[(value)]`, or a forms directive (`formControlName`, `ngModel`): the value components\n are `ControlValueAccessor`s. Open state: `[(open)]`. Pagination: `[(current)]`.\n- Events are outputs: `(activeChange)`, `(select)`, `(rootChange)`, `(openChange)`, `(sort)`.\n- Content is projected through templates: `<ng-template spFooter>`, `spExtra`, `spAction`,\n `spFallback`, `spTooltip`. An overlay's trigger is `<button type=\"button\" spTrigger>`, with\n `SpTrigger` imported from the overlay's subpath.\n- `provideSilverpoint` returns a `Provider`, so a component's own `providers` can nest one for its\n subtree.\n- Server rendering with `@angular/ssr` is supported.\n\n## Example\n\n```ts angular\nimport { ChangeDetectionStrategy, Component } from '@angular/core';\nimport { SpModal, SpTrigger } from '@silverpoint/angular/ui/modal';\n\n/** Add '@silverpoint/fonts/fonts.css', '@silverpoint/grounds/styles.css', '@silverpoint/grounds/ui.css' to the `styles` of angular.json. */\n@Component({\n selector: 'app-modal-view',\n imports: [SpModal, SpTrigger],\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: `\n <sp-modal\n [title]=\"'Edit order'\"\n [description]=\"'Order 1042, placed on 14 October.'\"\n >\n <button type=\"button\" spTrigger>Edit order</button>\n Changes reach the workshop before the order is packed.\n </sp-modal>\n `,\n})\nexport class ModalView {}\n```\n",
11522
+ "reflex": '<!-- Generated by tools/agent-catalog from skills/silverpoint/templates and the agent catalog. Do not edit: run `pnpm --filter @silverpoint/agent-catalog generate`. -->\n# Reflex\n\n*Describes silverpoint 0.8.0.*\n\n`reflex-silverpoint-react` 0.7.1 wraps the React components for Reflex, so the same\ncharts and components are Python builders. For anything beyond names and a first example, use the\n`reflex-silverpoint` skill, which covers state, events and the demo app\'s patterns.\n\n```sh\npip install reflex-silverpoint-react\n```\n\n- Builders are snake_case: `line_chart`, `sankey_chart`, `sp_modal`, `sp_select`. Props are\n snake_case too (`x_key`, `value_key`), with the same meaning as in React.\n- Data comes from a `rx.State` field, as a list of dicts.\n- `palette` takes a preset\'s name (`"sanguine"`).\n- An overlay\'s `trigger` is the trigger\'s text.\n\n```python\nimport reflex as rx\nfrom reflex_silverpoint_react import line_chart\n\n\nclass State(rx.State):\n rows: list[dict] = []\n\n\ndef line_chart_view() -> rx.Component:\n return line_chart(\n data=State.rows,\n x_key="hour",\n value_key="hits",\n secondary_key="baseline",\n title="Line chart",\n )\n```\n\n```python\nimport reflex as rx\nfrom reflex_silverpoint_react import sp_modal\n\n\ndef modal_view() -> rx.Component:\n return sp_modal(\n "Changes reach the workshop before the order is packed.",\n title="Edit order",\n description="Order 1042, placed on 14 October.",\n trigger="Edit order",\n )\n```\n\n## Builders\n\n| Slug | Builder | Kind |\n|---|---|---|\n| `line-chart` | `line_chart` | chart |\n| `bullet-chart` | `bullet_chart` | chart |\n| `pyramid-chart` | `pyramid_chart` | chart |\n| `heatmap-chart` | `heatmap_chart` | chart |\n| `treemap-chart` | `treemap_chart` | chart |\n| `sankey-chart` | `sankey_chart` | chart |\n| `activity-grid` | `activity_grid` | chart |\n| `step-chart` | `step_chart` | chart |\n| `sparkline-rows` | `sparkline_rows` | chart |\n| `kpi-card` | `kpi_card` | chart |\n| `bar-chart` | `bar_chart` | chart |\n| `stacked-bar-chart` | `stacked_bar_chart` | chart |\n| `composed-chart` | `composed_chart` | chart |\n| `waterfall-chart` | `waterfall_chart` | chart |\n| `funnel-chart` | `funnel_chart` | chart |\n| `candlestick-chart` | `candlestick_chart` | chart |\n| `area-chart` | `area_chart` | chart |\n| `range-band-chart` | `range_band_chart` | chart |\n| `stream-chart` | `stream_chart` | chart |\n| `scatter-chart` | `scatter_chart` | chart |\n| `bubble-chart` | `bubble_chart` | chart |\n| `donut-chart` | `donut_chart` | chart |\n| `radar-chart` | `radar_chart` | chart |\n| `polar-bar-chart` | `polar_bar_chart` | chart |\n| `radial-arc-group` | `radial_arc_group` | chart |\n| `radial-rings` | `radial_rings` | chart |\n| `gauge-arc` | `gauge_arc` | chart |\n| `meter-chart` | `meter_chart` | chart |\n| `coxcomb-chart` | `coxcomb_chart` | chart |\n| `wind-rose` | `wind_rose` | chart |\n| `volvelle-chart` | `volvelle_chart` | chart |\n| `chord-ring` | `chord_ring` | chart |\n| `orbit-chart` | `orbit_chart` | chart |\n| `histogram-chart` | `histogram_chart` | chart |\n| `ecdf-chart` | `ecdf_chart` | chart |\n| `box-plot-chart` | `box_plot_chart` | chart |\n| `violin-chart` | `violin_chart` | chart |\n| `ridgeline-chart` | `ridgeline_chart` | chart |\n| `beeswarm-chart` | `beeswarm_chart` | chart |\n| `lollipop-chart` | `lollipop_chart` | chart |\n| `dumbbell-chart` | `dumbbell_chart` | chart |\n| `slope-chart` | `slope_chart` | chart |\n| `bump-chart` | `bump_chart` | chart |\n| `error-bar-chart` | `error_bar_chart` | chart |\n| `interval-chart` | `interval_chart` | chart |\n| `diverging-bar-chart` | `diverging_bar_chart` | chart |\n| `connected-scatter-chart` | `connected_scatter_chart` | chart |\n| `waffle-chart` | `waffle_chart` | chart |\n| `marimekko-chart` | `marimekko_chart` | chart |\n| `squarified-treemap` | `squarified_treemap` | chart |\n| `sunburst-chart` | `sunburst_chart` | chart |\n| `tree-chart` | `tree_chart` | chart |\n| `parallel-coordinates-chart` | `parallel_coordinates_chart` | chart |\n| `polar-line-chart` | `polar_line_chart` | chart |\n| `polar-scatter-chart` | `polar_scatter_chart` | chart |\n| `density-bin-chart` | `density_bin_chart` | chart |\n| `contour-chart` | `contour_chart` | chart |\n| `delaunay-chart` | `delaunay_chart` | chart |\n| `vector-field-chart` | `vector_field_chart` | chart |\n| `network-chart` | `network_chart` | chart |\n| `button` | `sp_button` | ui |\n| `input` | `sp_input` | ui |\n| `checkbox` | `sp_checkbox` | ui |\n| `radio-group` | `sp_radio_group` | ui |\n| `switch` | `sp_switch` | ui |\n| `slider` | `sp_slider` | ui |\n| `rate` | `sp_rate` | ui |\n| `segmented` | `sp_segmented` | ui |\n| `tabs` | `sp_tabs` | ui |\n| `steps` | `sp_steps` | ui |\n| `card` | `sp_card` | ui |\n| `tag` | `sp_tag` | ui |\n| `badge` | `sp_badge` | ui |\n| `divider` | `sp_divider` | ui |\n| `progress` | `sp_progress` | ui |\n| `alert` | `sp_alert` | ui |\n| `skeleton` | `sp_skeleton` | ui |\n| `surface` | `sp_surface` | composed |\n| `glyph` | `sp_glyph` | composed |\n| `table` | `sp_table` | composed |\n| `pagination` | `sp_pagination` | composed |\n| `breadcrumb` | `sp_breadcrumb` | composed |\n| `avatar` | `sp_avatar` | composed |\n| `statistic` | `sp_statistic` | composed |\n| `descriptions` | `sp_descriptions` | composed |\n| `timeline-list` | `sp_timeline_list` | composed |\n| `collapse` | `sp_collapse` | composed |\n| `empty` | `sp_empty` | composed |\n| `result` | `sp_result` | composed |\n| `textarea` | `sp_textarea` | composed |\n| `input-number` | `sp_input_number` | composed |\n| `modal` | `sp_modal` | overlay |\n| `drawer` | `sp_drawer` | overlay |\n| `popover` | `sp_popover` | overlay |\n| `tooltip` | `sp_tooltip` | overlay |\n| `select` | `sp_select` | overlay |\n| `dropdown-menu` | `sp_dropdown_menu` | overlay |\n| `toast` | `sp_toast` | overlay |\n'
11425
11523
  };
11426
11524
 
11427
11525
  // src/tools/entries.ts