@box-kite/react 2.1.0 → 2.2.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.
Files changed (63) hide show
  1. package/.claude/rules/box-kite-rules.md +8 -2
  2. package/.claude/skills/box-kite/SKILL.md +11 -5
  3. package/.claude/skills/box-kite/references/patterns.md +1 -1
  4. package/.claude/skills/box-kite/references/styling.md +23 -0
  5. package/.cursor/rules/box-kite.mdc +9 -3
  6. package/AGENTS.md +9 -3
  7. package/BOX_AI_CONTEXT.md +171 -12
  8. package/BOX_KITE_AI_CONTEXT.md +171 -12
  9. package/README.md +2 -2
  10. package/box.cjs +1 -1
  11. package/box.d.ts +13 -2
  12. package/box.mjs +25 -18
  13. package/catalog.cjs +1 -1
  14. package/catalog.mjs +15 -1
  15. package/client.cjs +1 -1
  16. package/client.mjs +59 -51
  17. package/components/button.cjs +1 -1
  18. package/components/button.mjs +10 -14
  19. package/components/flex.cjs +1 -1
  20. package/components/flex.mjs +10 -13
  21. package/components/form.cjs +1 -1
  22. package/components/form.mjs +7 -7
  23. package/components/grid.cjs +1 -1
  24. package/components/grid.mjs +10 -13
  25. package/components/menu.cjs +1 -1
  26. package/components/menu.mjs +16 -16
  27. package/components/overlay.cjs +1 -1
  28. package/components/overlay.mjs +35 -34
  29. package/components/popover.cjs +1 -1
  30. package/components/popover.mjs +4 -4
  31. package/components/semantics.cjs +1 -1
  32. package/components/semantics.mjs +9 -13
  33. package/components/svg.cjs +1 -1
  34. package/components/svg.mjs +38 -44
  35. package/components/textarea.cjs +1 -1
  36. package/components/textarea.mjs +12 -16
  37. package/components/textbox.cjs +1 -1
  38. package/components/textbox.mjs +12 -16
  39. package/components/toaster.cjs +1 -1
  40. package/components/toaster.mjs +42 -43
  41. package/components/visuallyHidden.cjs +1 -1
  42. package/components/visuallyHidden.mjs +10 -13
  43. package/docs/mcp.md +6 -5
  44. package/docs/props.md +132 -20
  45. package/layer.cjs +1 -1
  46. package/layer.mjs +61 -59
  47. package/mcp/src/data.d.ts +1 -1
  48. package/mcp/src/styles.d.ts +2 -2
  49. package/mcp/src/vocabulary.d.ts +1 -1
  50. package/package.json +74 -48
  51. package/react/boxComponent.d.ts +10 -0
  52. package/react/popover/useTopLayer.d.ts +17 -0
  53. package/react/theme/theme.d.ts +10 -0
  54. package/react/useStyles.d.ts +2 -0
  55. package/react-shared.cjs +1 -1
  56. package/react-shared.mjs +44 -37
  57. package/rsc.cjs +1 -1
  58. package/rsc.d.ts +11 -1
  59. package/rsc.mjs +15 -12
  60. package/ssg.cjs +1 -1
  61. package/ssg.d.ts +8 -2
  62. package/ssg.mjs +13 -9
  63. package/utils/environment/environmentUtils.d.ts +5 -0
package/docs/props.md CHANGED
@@ -1,4 +1,4 @@
1
- # Every prop (221)
1
+ # Every prop (235)
2
2
 
3
3
  Generated from the prop registry of `@box-kite/react`. The description is the prop's own doc comment and the example is **measured** — the CSS beside a value is what the engine emits for it, not what a doc claims. Alphabetical; the registry's own order is what decides the cascade and is not this.
4
4
 
@@ -14,7 +14,7 @@ The accent-color CSS property tints the parts of a native control the page does
14
14
 
15
15
  - Writes: `accent-color`
16
16
  - Values: 304 named values, anything else the types allow
17
- - Example: `accentColor="sky-500"` → `accent-color: var(--sky-500)`
17
+ - Example: `accentColor="sky-500"` → `accent-color: var(--sky-500,oklch(68.5% .169 237.3))`
18
18
 
19
19
  ### `ai`
20
20
 
@@ -112,6 +112,38 @@ The animation-play-state CSS property sets whether an animation is running or pa
112
112
  - Values: `running` · `paused`
113
113
  - Example: `animationPlayState="running"` → `animation-play-state: running`
114
114
 
115
+ ### `animationRange`
116
+
117
+ The shorthand that sets both ends of the range at once: one value sets the start and leaves the end at `normal`, two set both. `entry` is the whole of the element coming into view, `cover 0% cover 50%` the first half of its pass across the scrollport. Only meaningful beside a view timeline.
118
+
119
+ - Writes: `animation-range`
120
+ - Values: whatever the types allow
121
+ - Example: `animationRange="entry"` → `animation-range: entry`
122
+
123
+ ### `animationRangeEnd`
124
+
125
+ Where along the timeline the animation finishes: a named part of the pass (`cover`, `contain`, `entry`, `exit`, `entry-crossing`, `exit-crossing`), an offset into one, or a plain length.
126
+
127
+ - Writes: `animation-range-end`
128
+ - Values: whatever the types allow
129
+ - Example: `animationRangeEnd="exit"` → `animation-range-end: exit`
130
+
131
+ ### `animationRangeStart`
132
+
133
+ Where along the timeline the animation starts. Same values as the end, and the pair is what turns "when this element is scrolled past" into "while it is entering, and no longer".
134
+
135
+ - Writes: `animation-range-start`
136
+ - Values: whatever the types allow
137
+ - Example: `animationRangeStart="entry 25%"` → `animation-range-start: entry 25%`
138
+
139
+ ### `animationTimeline`
140
+
141
+ What drives the animation — a scroll position rather than a clock, so there is no rAF loop, no scroll listener and no state. `scroll()` is the nearest scrollport's progress (`scroll(root)` the page's), `view()` this element's progress through it; both need nothing declared anywhere else. A name is a timeline `scrollTimeline`/`viewTimeline` declared elsewhere. Two things to know. **It is declared after `animation`**, because the CSS shorthand resets this property to `auto` — the registry's order is what stops `animation="spin"` quietly undoing it. And a scroll-driven animation has **no duration**, so `--transitionTime` cannot reach it and reduced motion needs saying out loud: `motionReduce={{ animation: 'none' }}`.
142
+
143
+ - Writes: `animation-timeline`
144
+ - Values: `none` · `auto`, anything else the types allow
145
+ - Example: `animationTimeline="scroll()"` → `animation-timeline: scroll()`
146
+
115
147
  ### `animationTimingFunction`
116
148
 
117
149
  How an animation progresses through each cycle: a keyword, one of the four sampled springs, or a curve of your own — `cubic-bezier()`, `steps()` and `linear()` are values. A spring names its duration too.
@@ -254,7 +286,7 @@ The background-color CSS property sets the background color of an element.
254
286
 
255
287
  - Writes: `background-color`
256
288
  - Values: 304 named values, anything else the types allow
257
- - Example: `bgColor="sky-500"` → `background-color: var(--sky-500)`
289
+ - Example: `bgColor="sky-500"` → `background-color: var(--sky-500,oklch(68.5% .169 237.3))`
258
290
 
259
291
  ### `bgGradient`
260
292
 
@@ -262,7 +294,7 @@ A gradient written as a value: the key names the kind and carries its geometry (
262
294
 
263
295
  - Writes: `background-image`
264
296
  - Values: whatever the types allow
265
- - Example: `bgGradient={{ linear: 'r', colors: ['blue-500', 'pink-500'] }}` → `background-image: linear-gradient(to right,var(--blue-500),var(--pink-500))`
297
+ - Example: `bgGradient={{ linear: 'r', colors: ['blue-500', 'pink-500'] }}` → `background-image: linear-gradient(to right,var(--blue-500,oklch(62.3% .214 259.8)),var(--pink-500,oklch(65.6% .241 354.3)))`
266
298
 
267
299
  ### `bgImage`
268
300
 
@@ -270,7 +302,7 @@ The background-image CSS property sets one or more background images on an eleme
270
302
 
271
303
  - Writes: `background-image`
272
304
  - Values: `gradient-primary` · `gradient-aurora-light` · `gradient-aurora-dark` · `gradient-accent` · `bg-img-checked` · `bg-img-indeterminate` · `bg-img-radio` · `none`
273
- - Example: `bgImage="gradient-primary"` → `background-image: var(--gradient-primary)`
305
+ - Example: `bgImage="gradient-primary"` → `background-image: var(--gradient-primary,linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #a855f7 100%))`
274
306
 
275
307
  ### `bl`
276
308
 
@@ -302,7 +334,7 @@ The border-color shorthand CSS property sets the color of an element's border.
302
334
 
303
335
  - Writes: `border-color`
304
336
  - Values: 304 named values, anything else the types allow
305
- - Example: `borderColor="sky-500"` → `border-color: var(--sky-500)`
337
+ - Example: `borderColor="sky-500"` → `border-color: var(--sky-500,oklch(68.5% .169 237.3))`
306
338
 
307
339
  ### `borderRadius`
308
340
 
@@ -510,7 +542,7 @@ The caret-color CSS property sets the colour of the insertion caret in a text fi
510
542
 
511
543
  - Writes: `caret-color`
512
544
  - Values: 304 named values, anything else the types allow
513
- - Example: `caretColor="sky-500"` → `caret-color: var(--sky-500)`
545
+ - Example: `caretColor="sky-500"` → `caret-color: var(--sky-500,oklch(68.5% .169 237.3))`
514
546
 
515
547
  ### `clipPath`
516
548
 
@@ -526,7 +558,7 @@ The color CSS property sets the foreground color value of an element's text and
526
558
 
527
559
  - Writes: `color`
528
560
  - Values: 304 named values, anything else the types allow
529
- - Example: `color="sky-500"` → `color: var(--sky-500)`
561
+ - Example: `color="sky-500"` → `color: var(--sky-500,oklch(68.5% .169 237.3))`
530
562
 
531
563
  ### `colorScheme`
532
564
 
@@ -662,7 +694,7 @@ What colour `dropShadow` draws in. Shows nothing on its own.
662
694
 
663
695
  - Writes: `--boxDropShadowColor`
664
696
  - Values: 304 named values, anything else the types allow
665
- - Example: `dropShadowColor="sky-500"` → `--boxDropShadowColor: var(--sky-500)`
697
+ - Example: `dropShadowColor="sky-500"` → `--boxDropShadowColor: var(--sky-500,oklch(68.5% .169 237.3))`
666
698
 
667
699
  ### `fieldSizing`
668
700
 
@@ -678,7 +710,7 @@ The fill CSS property defines how SVG text content and the interior canvas of SV
678
710
 
679
711
  - Writes: `fill`
680
712
  - Values: 304 named values, anything else the types allow
681
- - Example: `fill="sky-500"` → `fill: var(--sky-500)`
713
+ - Example: `fill="sky-500"` → `fill: var(--sky-500,oklch(68.5% .169 237.3))`
682
714
 
683
715
  ### `fillOpacity`
684
716
 
@@ -894,7 +926,7 @@ What colour `insetRing` draws in. `currentColor` otherwise.
894
926
 
895
927
  - Writes: `--boxInsetRingColor`
896
928
  - Values: 304 named values, anything else the types allow
897
- - Example: `insetRingColor="sky-500"` → `--boxInsetRingColor: var(--sky-500)`
929
+ - Example: `insetRingColor="sky-500"` → `--boxInsetRingColor: var(--sky-500,oklch(68.5% .169 237.3))`
898
930
 
899
931
  ### `insetShadow`
900
932
 
@@ -910,7 +942,7 @@ What colour `insetShadow` draws in. Shows nothing on its own.
910
942
 
911
943
  - Writes: `--boxInsetShadowColor`
912
944
  - Values: 304 named values, anything else the types allow
913
- - Example: `insetShadowColor="sky-500"` → `--boxInsetShadowColor: var(--sky-500)`
945
+ - Example: `insetShadowColor="sky-500"` → `--boxInsetShadowColor: var(--sky-500,oklch(68.5% .169 237.3))`
914
946
 
915
947
  ### `insetStart`
916
948
 
@@ -1022,7 +1054,7 @@ What the element is masked by: the alpha channel of an image decides which of it
1022
1054
 
1023
1055
  - Writes: `mask-image`
1024
1056
  - Values: `none`, anything else the types allow
1025
- - Example: `maskImage={{ linear: 'b', colors: ['black', 'transparent'] }}` → `mask-image: linear-gradient(to bottom,var(--black),var(--transparent))`
1057
+ - Example: `maskImage={{ linear: 'b', colors: ['black', 'transparent'] }}` → `mask-image: linear-gradient(to bottom,var(--black,#000),var(--transparent,transparent))`
1026
1058
 
1027
1059
  ### `maxHeight`
1028
1060
 
@@ -1158,7 +1190,7 @@ The outline-color CSS property sets the color of an element's outline.
1158
1190
 
1159
1191
  - Writes: `outline-color`
1160
1192
  - Values: 304 named values, anything else the types allow
1161
- - Example: `outlineColor="sky-500"` → `outline-color: var(--sky-500)`
1193
+ - Example: `outlineColor="sky-500"` → `outline-color: var(--sky-500,oklch(68.5% .169 237.3))`
1162
1194
 
1163
1195
  ### `outlineOffset`
1164
1196
 
@@ -1390,7 +1422,7 @@ What colour `ring` draws in. `currentColor` otherwise.
1390
1422
 
1391
1423
  - Writes: `--boxRingColor`
1392
1424
  - Values: 304 named values, anything else the types allow
1393
- - Example: `ringColor="sky-500"` → `--boxRingColor: var(--sky-500)`
1425
+ - Example: `ringColor="sky-500"` → `--boxRingColor: var(--sky-500,oklch(68.5% .169 237.3))`
1394
1426
 
1395
1427
  ### `rotate`
1396
1428
 
@@ -1446,7 +1478,7 @@ The scrollbar-color CSS property sets the color of the scrollbar thumb and track
1446
1478
 
1447
1479
  - Writes: `scrollbar-color`
1448
1480
  - Values: `currentColor,transparent,green,red,blue,gray,black,white,vi,slate-50,slate-100,slate-200,slate-300,slate-400,slate-500,slate-600,slate-700,slate-800,slate-900,slate-950,gray-50,gray-100,gray-200,gray-300,gray-400,gray-500,gray-600,gray-700,gray-800,gray-900,gray-950,zinc-50,zinc-100,zinc-200,zinc-300,zinc-400,zinc-500,zinc-600,zinc-700,zinc-800,zinc-900,zinc-950,neutral-50,neutral-100,neutral-200,neutral-300,neutral-400,neutral-500,neutral-600,neutral-700,neutral-800,neutral-900,neutral-950,stone-50,stone-100,stone-200,stone-300,stone-400,stone-500,stone-600,stone-700,stone-800,stone-900,stone-950,mauve-50,mauve-100,mauve-200,mauve-300,mauve-400,mauve-500,mauve-600,mauve-700,mauve-800,mauve-900,mauve-950,mist-50,mist-100,mist-200,mist-300,mist-400,mist-500,mist-600,mist-700,mist-800,mist-900,mist-950,olive-50,olive-100,olive-200,olive-300,olive-400,olive-500,olive-600,olive-700,olive-800,olive-900,olive-950,taupe-50,taupe-100,taupe-200,taupe-300,taupe-400,taupe-500,taupe-600,taupe-700,taupe-800,taupe-900,taupe-950,red-50,red-100,red-200,red-300,red-400,red-500,red-600,red-700,red-800,red-900,red-950,orange-50,orange-100,orange-200,orange-300,orange-400,orange-500,orange-600,orange-700,orange-800,orange-900,orange-950,amber-50,amber-100,amber-200,amber-300,amber-400,amber-500,amber-600,amber-700,amber-800,amber-900,amber-950,yellow-50,yellow-100,yellow-200,yellow-300,yellow-400,yellow-500,yellow-600,yellow-700,yellow-800,yellow-900,yellow-950,lime-50,lime-100,lime-200,lime-300,lime-400,lime-500,lime-600,lime-700,lime-800,lime-900,lime-950,green-50,green-100,green-200,green-300,green-400,green-500,green-600,green-700,green-800,green-900,green-950,emerald-50,emerald-100,emerald-200,emerald-300,emerald-400,emerald-500,emerald-600,emerald-700,emerald-800,emerald-900,emerald-950,teal-50,teal-100,teal-200,teal-300,teal-400,teal-500,teal-600,teal-700,teal-800,teal-900,teal-950,cyan-50,cyan-100,cyan-200,cyan-300,cyan-400,cyan-500,cyan-600,cyan-700,cyan-800,cyan-900,cyan-950,sky-50,sky-100,sky-200,sky-300,sky-400,sky-500,sky-600,sky-700,sky-800,sky-900,sky-950,blue-50,blue-100,blue-200,blue-300,blue-400,blue-500,blue-600,blue-700,blue-800,blue-900,blue-950,indigo-50,indigo-100,indigo-200,indigo-300,indigo-400,indigo-500,indigo-600,indigo-700,indigo-800,indigo-900,indigo-950,violet-50,violet-100,violet-200,violet-300,violet-400,violet-500,violet-600,violet-700,violet-800,violet-900,violet-950,purple-50,purple-100,purple-200,purple-300,purple-400,purple-500,purple-600,purple-700,purple-800,purple-900,purple-950,fuchsia-50,fuchsia-100,fuchsia-200,fuchsia-300,fuchsia-400,fuchsia-500,fuchsia-600,fuchsia-700,fuchsia-800,fuchsia-900,fuchsia-950,pink-50,pink-100,pink-200,pink-300,pink-400,pink-500,pink-600,pink-700,pink-800,pink-900,pink-950,rose-50,rose-100,rose-200,rose-300,rose-400,rose-500,rose-600,rose-700,rose-800,rose-900,rose-950,none`
1449
- - Example: `scrollbarColor={['gray-400', 'gray-100']}` → `scrollbar-color: var(--gray-400) var(--gray-100)`
1481
+ - Example: `scrollbarColor={['gray-400', 'gray-100']}` → `scrollbar-color: var(--gray-400,oklch(70.7% .022 261.3)) var(--gray-100,oklch(96.7% .003 264.5))`
1450
1482
 
1451
1483
  ### `scrollbarGutter`
1452
1484
 
@@ -1464,6 +1496,30 @@ How wide a scrollbar the browser draws. `none` hides it without taking the scrol
1464
1496
  - Values: `auto` · `thin` · `none`
1465
1497
  - Example: `scrollbarWidth="auto"` → `scrollbar-width: auto`
1466
1498
 
1499
+ ### `scrollTimeline`
1500
+
1501
+ Declares a named scroll timeline on this scroller — the shorthand, `<name>` or `<name> <axis>`, and the one to reach for: the longhands exist to override half of it. The name is written with or without the `--`, the way an anchor's is. Anything inside this element can then name it on `animationTimeline`; anything outside needs a `timelineScope` on a common ancestor.
1502
+
1503
+ - Writes: `scroll-timeline`
1504
+ - Values: `none`, anything else the types allow
1505
+ - Example: `scrollTimeline="page block"` → `scroll-timeline: --page block`
1506
+
1507
+ ### `scrollTimelineAxis`
1508
+
1509
+ Which axis of this scroller the named timeline follows. `block`/`inline` are the writing mode's, so a timeline declared on the block axis is the vertical one in English and still correct in Japanese.
1510
+
1511
+ - Writes: `scroll-timeline-axis`
1512
+ - Values: `block` · `inline` · `x` · `y`
1513
+ - Example: `scrollTimelineAxis="block"` → `scroll-timeline-axis: block`
1514
+
1515
+ ### `scrollTimelineName`
1516
+
1517
+ The name half of `scrollTimeline`, on its own.
1518
+
1519
+ - Writes: `scroll-timeline-name`
1520
+ - Values: `none`, anything else the types allow
1521
+ - Example: `scrollTimelineName="page"` → `scroll-timeline-name: --page`
1522
+
1467
1523
  ### `sepia`
1468
1524
 
1469
1525
  How far the element is pushed towards sepia, as a percentage.
@@ -1486,7 +1542,7 @@ What colour `shadow` draws in — the scale's own translucent black otherwise. S
1486
1542
 
1487
1543
  - Writes: `--boxShadowColor`
1488
1544
  - Values: 304 named values, anything else the types allow
1489
- - Example: `shadowColor="sky-500"` → `--boxShadowColor: var(--sky-500)`
1545
+ - Example: `shadowColor="sky-500"` → `--boxShadowColor: var(--sky-500,oklch(68.5% .169 237.3))`
1490
1546
 
1491
1547
  ### `shapeRendering`
1492
1548
 
@@ -1502,7 +1558,7 @@ The stroke CSS property defines the color or SVG paint server used to draw an el
1502
1558
 
1503
1559
  - Writes: `stroke`
1504
1560
  - Values: 304 named values, anything else the types allow
1505
- - Example: `stroke="sky-500"` → `stroke: var(--sky-500)`
1561
+ - Example: `stroke="sky-500"` → `stroke: var(--sky-500,oklch(68.5% .169 237.3))`
1506
1562
 
1507
1563
  ### `strokeDasharray`
1508
1564
 
@@ -1614,7 +1670,7 @@ What colour `textShadow` draws in. Shows nothing on its own.
1614
1670
 
1615
1671
  - Writes: `--boxTextShadowColor`
1616
1672
  - Values: 304 named values, anything else the types allow
1617
- - Example: `textShadowColor="sky-500"` → `--boxTextShadowColor: var(--sky-500)`
1673
+ - Example: `textShadowColor="sky-500"` → `--boxTextShadowColor: var(--sky-500,oklch(68.5% .169 237.3))`
1618
1674
 
1619
1675
  ### `textTransform`
1620
1676
 
@@ -1632,6 +1688,14 @@ The text-wrap CSS shorthand property controls how text inside an element is wrap
1632
1688
  - Values: `wrap` · `nowrap` · `balance` · `pretty`
1633
1689
  - Example: `textWrap="wrap"` → `text-wrap: wrap`
1634
1690
 
1691
+ ### `timelineScope`
1692
+
1693
+ Makes the named timelines below this element reachable from anywhere else below it. A timeline is otherwise visible only to the declaring element's own descendants, so a progress bar that is not inside the article it tracks needs their common ancestor to declare the scope. Comma-separated.
1694
+
1695
+ - Writes: `timeline-scope`
1696
+ - Values: `none`, anything else the types allow
1697
+ - Example: `timelineScope="page"` → `timeline-scope: --page`
1698
+
1635
1699
  ### `top`
1636
1700
 
1637
1701
  The top CSS property sets the vertical position of a positioned element. This inset property has no effect on non-positioned elements. It also takes `anchor()`, an inset measured to one of the anchor's own edges.
@@ -1710,7 +1774,7 @@ CSS custom properties on this element, inherited by everything inside it: `vars=
1710
1774
 
1711
1775
  - Writes: `--color-revenue`
1712
1776
  - Values: whatever the types allow
1713
- - Example: `vars={{ 'color-revenue': 'sky-500' }}` → `--color-revenue: var(--sky-500)`
1777
+ - Example: `vars={{ 'color-revenue': 'sky-500' }}` → `--color-revenue: var(--sky-500,oklch(68.5% .169 237.3))`
1714
1778
 
1715
1779
  ### `vectorEffect`
1716
1780
 
@@ -1720,6 +1784,54 @@ How an SVG element's stroke reacts to the transforms above it: `non-scaling-stro
1720
1784
  - Values: `none` · `non-scaling-stroke`
1721
1785
  - Example: `vectorEffect="none"` → `vector-effect: none`
1722
1786
 
1787
+ ### `viewTimeline`
1788
+
1789
+ Declares a named view timeline on this element — its own progress across the scrollport, rather than the scroller's progress through its content. Same shorthand shape as `scrollTimeline`, and the same rule about who can see the name.
1790
+
1791
+ - Writes: `view-timeline`
1792
+ - Values: `none`, anything else the types allow
1793
+ - Example: `viewTimeline="card block"` → `view-timeline: --card block`
1794
+
1795
+ ### `viewTimelineAxis`
1796
+
1797
+ Which axis this element's pass across the scrollport is measured on.
1798
+
1799
+ - Writes: `view-timeline-axis`
1800
+ - Values: `block` · `inline` · `x` · `y`
1801
+ - Example: `viewTimelineAxis="block"` → `view-timeline-axis: block`
1802
+
1803
+ ### `viewTimelineInset`
1804
+
1805
+ Shrinks the scrollport the timeline measures against, so the pass starts and ends somewhere other than the viewport edges: one value for both ends, two for the start and the end. A positive inset moves the edge inwards, which is what makes an element count as "in view" before it really is.
1806
+
1807
+ - Writes: `view-timeline-inset`
1808
+ - Values: whatever the types allow
1809
+ - Example: `viewTimelineInset="20%"` → `view-timeline-inset: 20%`
1810
+
1811
+ ### `viewTimelineName`
1812
+
1813
+ The name half of `viewTimeline`, on its own.
1814
+
1815
+ - Writes: `view-timeline-name`
1816
+ - Values: `none`, anything else the types allow
1817
+ - Example: `viewTimelineName="card"` → `view-timeline-name: --card`
1818
+
1819
+ ### `viewTransitionClass`
1820
+
1821
+ A class shared by several named elements, so one rule styles the lot of them: `::view-transition-group(.card)` reaches every element carrying `viewTransitionClass="card"`. Space separated for more than one.
1822
+
1823
+ - Writes: `view-transition-class`
1824
+ - Values: `none`, anything else the types allow
1825
+ - Example: `viewTransitionClass="card"` → `view-transition-class: card`
1826
+
1827
+ ### `viewTransitionName`
1828
+
1829
+ Names this element for a view transition, which is what makes the browser animate it from where it was to where it is rather than cross-fading the whole page over it. A name has to be **unique in the document while the transition runs** — two elements sharing one is how a transition silently does nothing — so a list wants a name per item, and that is a rule per item this library would never free: write those with `props={{ style: { viewTransitionName: id } }}`, the exception `useAnchorPosition` already takes. This prop is for the handful of names a layout has (`header`, `main`, `sidebar`).
1830
+
1831
+ - Writes: `view-transition-name`
1832
+ - Values: `none` · `auto` · `match-element`, anything else the types allow
1833
+ - Example: `viewTransitionName="header"` → `view-transition-name: header`
1834
+
1723
1835
  ### `visibility`
1724
1836
 
1725
1837
  The visibility CSS property shows or hides an element without changing the layout of a document. The property can also hide rows or columns in a <table>.
package/layer.cjs CHANGED
@@ -1 +1 @@
1
- const e=require("./platform.cjs"),t=require("./effects.cjs"),n=require("./behavior.cjs"),r=require("./identity.cjs");let i=require("react");function a(a){let{haspopup:o,id:s,idPrefix:c,open:l,defaultOpen:u=!1,onOpenChange:d,onOpened:f,onClosing:p,inside:m}=a,h=r.t(c),g=s??h,[_,v]=n.i({value:l,defaultValue:u,onChange:d}),[y,b]=(0,i.useState)(null),[x,S]=(0,i.useState)(null),[C,w]=(0,i.useState)(!0),[T,E]=(0,i.useState)(!1),[D,O]=(0,i.useState)(),k=(0,i.useRef)(`imperative`),A=(0,i.useRef)(!1);t.n(()=>{e.a()||w(!1)},[]);let j=n.a(f),M=n.a(p),N=n.a(e=>{let t=e.newState===`open`,n=e.currentTarget;if(t&&l===!1){e.preventDefault();return}t||(A.current=n.contains(document.activeElement),M(A.current,y)),E(t);let r=t?`trigger`:k.current;k.current=`imperative`,v(t,{reason:r,event:e})}),P=n.a(e=>{let t=e.currentTarget;e.newState===`open`&&j(t)});t.n(()=>{if(!C||!x)return;let e=new AbortController;return x.addEventListener(`beforetoggle`,N,{signal:e.signal}),x.addEventListener(`toggle`,P,{signal:e.signal}),()=>e.abort()},[C,x,N,P]),t.n(()=>{!C||!x||_===T||(_?x.showPopover():x.hidePopover())},[_,T,x,C]),t.n(()=>{if(!C||!_)return;let t=new AbortController,n=(e,n)=>document.addEventListener(e,n,{signal:t.signal,capture:!0});return n(`keydown`,e=>{e.key===`Escape`&&(k.current=`escape`)}),n(`pointerdown`,t=>{let n=!!y&&e.l(t,[y]);k.current=n?`trigger`:`outside-pointer`}),()=>t.abort()},[C,_,y]),t.n(()=>{y&&(y.id||y.setAttribute(`id`,`${g}-trigger`),O(y.id))},[y,g]),t.n(()=>{if(!(!C||!y))return y.setAttribute(`popovertarget`,g),()=>y.removeAttribute(`popovertarget`)},[C,y,g]),t.n(()=>{C||!_||!x||j(x)},[C,_,x,j]),n.r({enabled:!C&&_,inside:[x,y,...m??[]],onDismiss:(e,t)=>v(!1,{reason:e,event:t})}),n.n({enabled:!C&&_,returnTo:y});let F=n.a(e=>{v(e=>!e,{reason:`trigger`,event:e})});return{platform:C,isOpen:_,setOpen:v,id:g,trigger:(0,i.useMemo)(()=>({ref:b,props:{"aria-expanded":_,"aria-haspopup":o,"aria-controls":_?g:void 0,...C?{}:{onClick:F}}}),[F,o,_,g,C]),triggerElement:y,triggerId:D,setPanel:S,panelElement:x}}Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return a}});
1
+ const e=require("./platform.cjs"),t=require("./effects.cjs"),n=require("./behavior.cjs"),r=require("./identity.cjs");let i=require("react");var a=()=>()=>{},o=()=>!0;function s(){return(0,i.useSyncExternalStore)(a,e.a,o)}function c(a){let{haspopup:o,id:c,idPrefix:l,open:u,defaultOpen:d=!1,onOpenChange:f,onOpened:p,onClosing:m,inside:h}=a,g=r.t(l),_=c??g,[v,y]=n.i({value:u,defaultValue:d,onChange:f}),[b,x]=(0,i.useState)(null),[S,C]=(0,i.useState)(null),w=s(),[T,E]=(0,i.useState)(!1),[D,O]=(0,i.useState)(),k=(0,i.useRef)(`imperative`),A=(0,i.useRef)(!1),j=n.a(p),M=n.a(m),N=n.a(e=>{let t=e.newState===`open`,n=e.currentTarget;if(t&&u===!1){e.preventDefault();return}t||(A.current=n.contains(document.activeElement),M(A.current,b)),E(t);let r=t?`trigger`:k.current;k.current=`imperative`,y(t,{reason:r,event:e})}),P=n.a(e=>{let t=e.currentTarget;e.newState===`open`&&j(t)});t.n(()=>{if(!w||!S)return;let e=new AbortController;return S.addEventListener(`beforetoggle`,N,{signal:e.signal}),S.addEventListener(`toggle`,P,{signal:e.signal}),()=>e.abort()},[w,S,N,P]),t.n(()=>{!w||!e.a()||!S||v===T||(v?S.showPopover():S.hidePopover())},[v,T,S,w]),t.n(()=>{if(!w||!v)return;let t=new AbortController,n=(e,n)=>document.addEventListener(e,n,{signal:t.signal,capture:!0});return n(`keydown`,e=>{e.key===`Escape`&&(k.current=`escape`)}),n(`pointerdown`,t=>{let n=!!b&&e.l(t,[b]);k.current=n?`trigger`:`outside-pointer`}),()=>t.abort()},[w,v,b]),t.n(()=>{b&&(b.id||b.setAttribute(`id`,`${_}-trigger`),O(b.id))},[b,_]),t.n(()=>{if(!(!w||!b))return b.setAttribute(`popovertarget`,_),()=>b.removeAttribute(`popovertarget`)},[w,b,_]),t.n(()=>{w||!v||!S||j(S)},[w,v,S,j]),n.r({enabled:!w&&v,inside:[S,b,...h??[]],onDismiss:(e,t)=>y(!1,{reason:e,event:t})}),n.n({enabled:!w&&v,returnTo:b});let F=n.a(e=>{y(e=>!e,{reason:`trigger`,event:e})});return{platform:w,isOpen:v,setOpen:y,id:_,trigger:(0,i.useMemo)(()=>({ref:x,props:{"aria-expanded":v,"aria-haspopup":o,"aria-controls":v?_:void 0,...w?{}:{onClick:F}}}),[F,o,v,_,w]),triggerElement:b,triggerId:D,setPanel:C,panelElement:S}}Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return c}});
package/layer.mjs CHANGED
@@ -2,26 +2,28 @@ import { a as e, l as t } from "./platform.mjs";
2
2
  import { n } from "./effects.mjs";
3
3
  import { a as r, i, n as a, r as o } from "./behavior.mjs";
4
4
  import { t as s } from "./identity.mjs";
5
- import { useMemo as c, useRef as l, useState as u } from "react";
5
+ import { useMemo as c, useRef as l, useState as u, useSyncExternalStore as d } from "react";
6
+ //#region src/react/popover/useTopLayer.ts
7
+ var f = () => () => {}, p = () => !0;
8
+ function m() {
9
+ return d(f, e, p);
10
+ }
11
+ //#endregion
6
12
  //#region src/react/popover/usePopoverLayer.ts
7
- function d(d) {
8
- let { haspopup: f, id: p, idPrefix: m, open: h, defaultOpen: g = !1, onOpenChange: _, onOpened: v, onClosing: y, inside: b } = d, x = s(m), S = p ?? x, [C, w] = i({
9
- value: h,
10
- defaultValue: g,
11
- onChange: _
12
- }), [T, E] = u(null), [D, O] = u(null), [k, A] = u(!0), [j, M] = u(!1), [N, P] = u(), F = l("imperative"), I = l(!1);
13
- n(() => {
14
- e() || A(!1);
15
- }, []);
16
- let L = r(v), R = r(y), z = r((e) => {
13
+ function h(d) {
14
+ let { haspopup: f, id: p, idPrefix: h, open: g, defaultOpen: _ = !1, onOpenChange: v, onOpened: y, onClosing: b, inside: x } = d, S = s(h), C = p ?? S, [w, T] = i({
15
+ value: g,
16
+ defaultValue: _,
17
+ onChange: v
18
+ }), [E, D] = u(null), [O, k] = u(null), A = m(), [j, M] = u(!1), [N, P] = u(), F = l("imperative"), I = l(!1), L = r(y), R = r(b), z = r((e) => {
17
19
  let t = e.newState === "open", n = e.currentTarget;
18
- if (t && h === !1) {
20
+ if (t && g === !1) {
19
21
  e.preventDefault();
20
22
  return;
21
23
  }
22
- t || (I.current = n.contains(document.activeElement), R(I.current, T)), M(t);
24
+ t || (I.current = n.contains(document.activeElement), R(I.current, E)), M(t);
23
25
  let r = t ? "trigger" : F.current;
24
- F.current = "imperative", w(t, {
26
+ F.current = "imperative", T(t, {
25
27
  reason: r,
26
28
  event: e
27
29
  });
@@ -30,23 +32,23 @@ function d(d) {
30
32
  e.newState === "open" && L(t);
31
33
  });
32
34
  n(() => {
33
- if (!k || !D) return;
35
+ if (!A || !O) return;
34
36
  let e = new AbortController();
35
- return D.addEventListener("beforetoggle", z, { signal: e.signal }), D.addEventListener("toggle", B, { signal: e.signal }), () => e.abort();
37
+ return O.addEventListener("beforetoggle", z, { signal: e.signal }), O.addEventListener("toggle", B, { signal: e.signal }), () => e.abort();
36
38
  }, [
37
- k,
38
- D,
39
+ A,
40
+ O,
39
41
  z,
40
42
  B
41
43
  ]), n(() => {
42
- !k || !D || C === j || (C ? D.showPopover() : D.hidePopover());
44
+ !A || !e() || !O || w === j || (w ? O.showPopover() : O.hidePopover());
43
45
  }, [
44
- C,
46
+ w,
45
47
  j,
46
- D,
47
- k
48
+ O,
49
+ A
48
50
  ]), n(() => {
49
- if (!k || !C) return;
51
+ if (!A || !w) return;
50
52
  let e = new AbortController(), n = (t, n) => document.addEventListener(t, n, {
51
53
  signal: e.signal,
52
54
  capture: !0
@@ -54,74 +56,74 @@ function d(d) {
54
56
  return n("keydown", (e) => {
55
57
  e.key === "Escape" && (F.current = "escape");
56
58
  }), n("pointerdown", (e) => {
57
- let n = !!T && t(e, [T]);
59
+ let n = !!E && t(e, [E]);
58
60
  F.current = n ? "trigger" : "outside-pointer";
59
61
  }), () => e.abort();
60
62
  }, [
61
- k,
62
- C,
63
- T
63
+ A,
64
+ w,
65
+ E
64
66
  ]), n(() => {
65
- T && (T.id || T.setAttribute("id", `${S}-trigger`), P(T.id));
66
- }, [T, S]), n(() => {
67
- if (!(!k || !T)) return T.setAttribute("popovertarget", S), () => T.removeAttribute("popovertarget");
67
+ E && (E.id || E.setAttribute("id", `${C}-trigger`), P(E.id));
68
+ }, [E, C]), n(() => {
69
+ if (!(!A || !E)) return E.setAttribute("popovertarget", C), () => E.removeAttribute("popovertarget");
68
70
  }, [
69
- k,
70
- T,
71
- S
71
+ A,
72
+ E,
73
+ C
72
74
  ]), n(() => {
73
- k || !C || !D || L(D);
75
+ A || !w || !O || L(O);
74
76
  }, [
75
- k,
76
- C,
77
- D,
77
+ A,
78
+ w,
79
+ O,
78
80
  L
79
81
  ]), o({
80
- enabled: !k && C,
82
+ enabled: !A && w,
81
83
  inside: [
82
- D,
83
- T,
84
- ...b ?? []
84
+ O,
85
+ E,
86
+ ...x ?? []
85
87
  ],
86
- onDismiss: (e, t) => w(!1, {
88
+ onDismiss: (e, t) => T(!1, {
87
89
  reason: e,
88
90
  event: t
89
91
  })
90
92
  }), a({
91
- enabled: !k && C,
92
- returnTo: T
93
+ enabled: !A && w,
94
+ returnTo: E
93
95
  });
94
96
  let V = r((e) => {
95
- w((e) => !e, {
97
+ T((e) => !e, {
96
98
  reason: "trigger",
97
99
  event: e
98
100
  });
99
101
  });
100
102
  return {
101
- platform: k,
102
- isOpen: C,
103
- setOpen: w,
104
- id: S,
103
+ platform: A,
104
+ isOpen: w,
105
+ setOpen: T,
106
+ id: C,
105
107
  trigger: c(() => ({
106
- ref: E,
108
+ ref: D,
107
109
  props: {
108
- "aria-expanded": C,
110
+ "aria-expanded": w,
109
111
  "aria-haspopup": f,
110
- "aria-controls": C ? S : void 0,
111
- ...k ? {} : { onClick: V }
112
+ "aria-controls": w ? C : void 0,
113
+ ...A ? {} : { onClick: V }
112
114
  }
113
115
  }), [
114
116
  V,
115
117
  f,
118
+ w,
116
119
  C,
117
- S,
118
- k
120
+ A
119
121
  ]),
120
- triggerElement: T,
122
+ triggerElement: E,
121
123
  triggerId: N,
122
- setPanel: O,
123
- panelElement: D
124
+ setPanel: k,
125
+ panelElement: O
124
126
  };
125
127
  }
126
128
  //#endregion
127
- export { d as t };
129
+ export { m as n, h as t };
package/mcp/src/data.d.ts CHANGED
@@ -76,7 +76,7 @@ export declare const priorFacts: readonly string[];
76
76
  export declare const blocks: readonly RegistryItem[];
77
77
  export declare const blockInstall: (name: string) => string;
78
78
  /**
79
- * A fresh engine with readable class names and no DOM: what `check_styles` judges a value with. One
79
+ * A fresh engine with readable class names, no DOM and no console: what `check_styles` judges a value with. One
80
80
  * per call rather than one for the process, so a caller's `vars` or `css` cannot leak into the next
81
81
  * answer through the rule registry.
82
82
  */
@@ -6,11 +6,11 @@
6
6
  * Each prop is measured on its own, because one bag would let a rejected value hide behind an
7
7
  * accepted one in the same class list.
8
8
  */
9
- export type Verdict = 'ok' | 'rejected-value' | 'unknown-prop' | 'html-attribute' | 'reserved';
9
+ export type Verdict = 'ok' | 'misread' | 'rejected-value' | 'unknown-prop' | 'html-attribute' | 'reserved';
10
10
  export interface PropCheck {
11
11
  name: string;
12
12
  verdict: Verdict;
13
- /** The rules this prop wrote, at-rules included. Empty unless `ok`. */
13
+ /** The rules this prop wrote, at-rules included. Empty unless `ok` or `misread`. */
14
14
  css: string;
15
15
  /** What to do about it, when the verdict is not `ok`. */
16
16
  note?: string;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Every key a Box takes that is *not* one of the 221 style props: the nesting keys, and the four
2
+ * Every key a Box takes that is *not* one of the 235 style props: the nesting keys, and the four
3
3
  * reserved names. Imported from the engine's own records rather than listed here, so a key added to
4
4
  * the library is in the MCP server the same day — the whole reason this package lives in this repo.
5
5
  */