neba 1.11.0 → 1.13.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 (218) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +43 -41
  3. package/dist/components/accordion/Accordion.d.ts +18 -0
  4. package/dist/components/accordion/Accordion.js +1 -1
  5. package/dist/components/anchor/Anchor.js +1 -1
  6. package/dist/components/animate-appear/AnimateAppear.d.ts +2 -13
  7. package/dist/components/animate-appear/AnimateAppear.js +1 -1
  8. package/dist/components/animate-blink/AnimateBlink.d.ts +2 -2
  9. package/dist/components/animate-blink/AnimateBlink.js +1 -1
  10. package/dist/components/animate-counter/AnimateCounter.d.ts +45 -0
  11. package/dist/components/animate-counter/AnimateCounter.js +1 -0
  12. package/dist/components/animate-counter/index.d.ts +1 -0
  13. package/dist/components/animate-counter/index.js +1 -0
  14. package/dist/components/animate-fade/AnimateFade.d.ts +2 -2
  15. package/dist/components/animate-fade/AnimateFade.js +1 -1
  16. package/dist/components/animate-float/AnimateFloat.d.ts +35 -0
  17. package/dist/components/animate-float/AnimateFloat.js +1 -0
  18. package/dist/components/animate-float/index.d.ts +1 -0
  19. package/dist/components/animate-float/index.js +1 -0
  20. package/dist/components/animate-grow/AnimateGrow.d.ts +2 -2
  21. package/dist/components/animate-grow/AnimateGrow.js +1 -1
  22. package/dist/components/animate-marquee/AnimateMarquee.d.ts +5 -3
  23. package/dist/components/animate-marquee/AnimateMarquee.js +1 -1
  24. package/dist/components/animate-reveal/AnimateReveal.d.ts +41 -0
  25. package/dist/components/animate-reveal/AnimateReveal.js +1 -0
  26. package/dist/components/animate-reveal/index.d.ts +1 -0
  27. package/dist/components/animate-reveal/index.js +1 -0
  28. package/dist/components/animate-rotate/AnimateRotate.d.ts +2 -2
  29. package/dist/components/animate-rotate/AnimateRotate.js +1 -1
  30. package/dist/components/animate-scramble/AnimateScramble.d.ts +48 -0
  31. package/dist/components/animate-scramble/AnimateScramble.js +1 -0
  32. package/dist/components/animate-scramble/index.d.ts +1 -0
  33. package/dist/components/animate-scramble/index.js +1 -0
  34. package/dist/components/animate-shake/AnimateShake.d.ts +39 -0
  35. package/dist/components/animate-shake/AnimateShake.js +1 -0
  36. package/dist/components/animate-shake/index.d.ts +1 -0
  37. package/dist/components/animate-shake/index.js +1 -0
  38. package/dist/components/animate-slide/AnimateSlide.d.ts +2 -2
  39. package/dist/components/animate-slide/AnimateSlide.js +1 -1
  40. package/dist/components/animate-split/AnimateSplit.d.ts +61 -0
  41. package/dist/components/animate-split/AnimateSplit.js +1 -0
  42. package/dist/components/animate-split/index.d.ts +1 -0
  43. package/dist/components/animate-split/index.js +1 -0
  44. package/dist/components/animate-typing/AnimateTyping.js +1 -1
  45. package/dist/components/animate-zoom/AnimateZoom.d.ts +2 -2
  46. package/dist/components/animate-zoom/AnimateZoom.js +1 -1
  47. package/dist/components/app-logo/AppLogo.js +1 -1
  48. package/dist/components/avatar/Avatar.js +1 -1
  49. package/dist/components/bar-chart/BarChart.js +1 -1
  50. package/dist/components/bottom-navigation/BottomNavigation.d.ts +10 -0
  51. package/dist/components/bottom-navigation/BottomNavigation.js +1 -1
  52. package/dist/components/button/Button.js +1 -1
  53. package/dist/components/calendar/Calendar.js +1 -1
  54. package/dist/components/carousel/Carousel.d.ts +13 -0
  55. package/dist/components/carousel/Carousel.js +1 -1
  56. package/dist/components/checkbox/Checkbox.js +1 -1
  57. package/dist/components/code-block/CodeBlock.js +1 -1
  58. package/dist/components/color-picker/ColorPicker.js +1 -1
  59. package/dist/components/combobox/Combobox.d.ts +18 -0
  60. package/dist/components/combobox/Combobox.js +1 -1
  61. package/dist/components/command-palette/CommandPalette.js +1 -1
  62. package/dist/components/container/Container.d.ts +12 -4
  63. package/dist/components/container/Container.js +1 -1
  64. package/dist/components/data-table/DataTable.js +1 -1
  65. package/dist/components/date-picker/DatePicker.js +1 -1
  66. package/dist/components/date-range-picker/DateRangePicker.js +1 -1
  67. package/dist/components/date-time-picker/DateTimePicker.js +1 -1
  68. package/dist/components/dialog/Dialog.js +1 -1
  69. package/dist/components/drawer/Drawer.js +1 -1
  70. package/dist/components/flex/Flex.d.ts +93 -0
  71. package/dist/components/flex/Flex.js +1 -0
  72. package/dist/components/flex/index.d.ts +2 -0
  73. package/dist/components/flex/index.js +1 -0
  74. package/dist/components/floating-action-button/FloatingActionButton.js +1 -1
  75. package/dist/components/footer/Footer.d.ts +4 -3
  76. package/dist/components/footer/Footer.js +1 -1
  77. package/dist/components/gallery/Gallery.d.ts +150 -0
  78. package/dist/components/gallery/Gallery.js +1 -0
  79. package/dist/components/gallery/GalleryViewer.d.ts +30 -0
  80. package/dist/components/gallery/GalleryViewer.js +1 -0
  81. package/dist/components/gallery/index.d.ts +2 -0
  82. package/dist/components/gallery/index.js +1 -0
  83. package/dist/components/gauge-chart/GaugeChart.js +1 -1
  84. package/dist/components/grid/Grid.d.ts +11 -1
  85. package/dist/components/grid/Grid.js +1 -1
  86. package/dist/components/grid-container/GridContainer.js +1 -1
  87. package/dist/components/header/Header.d.ts +5 -4
  88. package/dist/components/header/Header.js +1 -1
  89. package/dist/components/heatmap-chart/HeatmapChart.js +1 -1
  90. package/dist/components/hover-card/HoverCard.js +1 -1
  91. package/dist/components/how-to-steps/HowToSteps.js +1 -1
  92. package/dist/components/image/Image.d.ts +155 -7
  93. package/dist/components/image/Image.js +1 -1
  94. package/dist/components/image/index.d.ts +1 -1
  95. package/dist/components/menu/Menu.js +1 -1
  96. package/dist/components/meter/Meter.d.ts +7 -0
  97. package/dist/components/meter/Meter.js +1 -1
  98. package/dist/components/navigation-menu/NavigationMenu.js +1 -1
  99. package/dist/components/number-field/NumberField.js +1 -1
  100. package/dist/components/otp-field/OtpField.js +1 -1
  101. package/dist/components/overlay/Overlay.js +1 -1
  102. package/dist/components/panes/Panes.js +1 -1
  103. package/dist/components/pie-chart/PieChart.js +1 -1
  104. package/dist/components/popover/Popover.js +1 -1
  105. package/dist/components/progress-circular/ProgressCircular.d.ts +10 -1
  106. package/dist/components/progress-circular/ProgressCircular.js +1 -1
  107. package/dist/components/progress-linear/ProgressLinear.d.ts +7 -1
  108. package/dist/components/progress-linear/ProgressLinear.js +1 -1
  109. package/dist/components/provider/NebaProvider.js +1 -1
  110. package/dist/components/radio-group/RadioGroup.js +1 -1
  111. package/dist/components/rating/Rating.js +1 -1
  112. package/dist/components/scatter-chart/ScatterChart.js +1 -1
  113. package/dist/components/scroll-area/ScrollArea.js +1 -1
  114. package/dist/components/scroll-zone/ScrollZone.d.ts +17 -11
  115. package/dist/components/scroll-zone/ScrollZone.js +1 -1
  116. package/dist/components/select/Select.d.ts +13 -0
  117. package/dist/components/select/Select.js +1 -1
  118. package/dist/components/show/Show.d.ts +60 -0
  119. package/dist/components/show/Show.js +1 -0
  120. package/dist/components/show/index.d.ts +2 -0
  121. package/dist/components/show/index.js +1 -0
  122. package/dist/components/sidebar/Sidebar.js +1 -1
  123. package/dist/components/slider/Slider.d.ts +37 -2
  124. package/dist/components/slider/Slider.js +1 -1
  125. package/dist/components/spoiler/Spoiler.js +1 -1
  126. package/dist/components/stack/Stack.d.ts +126 -0
  127. package/dist/components/stack/Stack.js +1 -0
  128. package/dist/components/stack/index.d.ts +1 -0
  129. package/dist/components/stack/index.js +1 -0
  130. package/dist/components/statistic/Statistic.d.ts +8 -3
  131. package/dist/components/tabs/Tabs.d.ts +46 -0
  132. package/dist/components/tabs/Tabs.js +1 -1
  133. package/dist/components/text-field/TextField.js +1 -1
  134. package/dist/components/time-picker/TimePicker.js +1 -1
  135. package/dist/components/timeline-chart/TimelineChart.js +1 -1
  136. package/dist/components/toast/Toast.js +1 -1
  137. package/dist/components/toggle/Toggle.js +1 -1
  138. package/dist/components/tooltip/Tooltip.js +1 -1
  139. package/dist/components/tour/Tour.js +1 -1
  140. package/dist/components/transfer/Transfer.js +1 -1
  141. package/dist/components/tree-select/TreeSelect.d.ts +2 -0
  142. package/dist/components/tree-select/TreeSelect.js +1 -1
  143. package/dist/components/tree-view/TreeView.js +1 -1
  144. package/dist/components/typography/Typography.js +1 -1
  145. package/dist/hooks/index.d.ts +1 -1
  146. package/dist/hooks/index.js +1 -1
  147. package/dist/hooks/useMediaQuery.d.ts +35 -1
  148. package/dist/hooks/useMediaQuery.js +1 -1
  149. package/dist/index.d.ts +10 -1
  150. package/dist/index.js +1 -1
  151. package/dist/internal/animate.d.ts +65 -2
  152. package/dist/internal/animate.js +1 -1
  153. package/dist/internal/cache.d.ts +24 -0
  154. package/dist/internal/cache.js +1 -0
  155. package/dist/internal/calendar.d.ts +15 -42
  156. package/dist/internal/calendar.js +1 -1
  157. package/dist/internal/chart-frame.d.ts +48 -3
  158. package/dist/internal/chart-frame.js +1 -1
  159. package/dist/internal/chart-line.js +1 -1
  160. package/dist/internal/chart.d.ts +16 -0
  161. package/dist/internal/chart.js +1 -1
  162. package/dist/internal/date.js +1 -1
  163. package/dist/internal/drag.d.ts +8 -6
  164. package/dist/internal/drag.js +1 -1
  165. package/dist/internal/format.d.ts +21 -7
  166. package/dist/internal/format.js +1 -1
  167. package/dist/internal/grid.d.ts +29 -27
  168. package/dist/internal/grid.js +1 -1
  169. package/dist/internal/i18n.d.ts +92 -0
  170. package/dist/internal/i18n.js +1 -1
  171. package/dist/internal/icons.d.ts +25 -0
  172. package/dist/internal/icons.js +1 -1
  173. package/dist/internal/link.d.ts +5 -4
  174. package/dist/internal/media.d.ts +9 -2
  175. package/dist/internal/media.js +1 -1
  176. package/dist/internal/observe.js +1 -1
  177. package/dist/internal/page-layout.d.ts +11 -9
  178. package/dist/internal/page-layout.js +1 -1
  179. package/dist/internal/picker.d.ts +8 -3
  180. package/dist/internal/picker.js +1 -1
  181. package/dist/internal/progress.d.ts +24 -1
  182. package/dist/internal/progress.js +1 -1
  183. package/dist/internal/responsive.d.ts +97 -0
  184. package/dist/internal/responsive.js +1 -0
  185. package/dist/internal/styles.d.ts +140 -2
  186. package/dist/internal/styles.js +1 -1
  187. package/dist/internal/text.d.ts +32 -0
  188. package/dist/internal/text.js +1 -0
  189. package/dist/internal/wheel.d.ts +38 -0
  190. package/dist/internal/wheel.js +1 -0
  191. package/dist/locales/ar.js +1 -1
  192. package/dist/locales/de.js +1 -1
  193. package/dist/locales/es.js +1 -1
  194. package/dist/locales/fr.js +1 -1
  195. package/dist/locales/hi.js +1 -1
  196. package/dist/locales/id.js +1 -1
  197. package/dist/locales/it.js +1 -1
  198. package/dist/locales/ja.js +1 -1
  199. package/dist/locales/ko.js +1 -1
  200. package/dist/locales/nl.js +1 -1
  201. package/dist/locales/pl.js +1 -1
  202. package/dist/locales/pt.js +1 -1
  203. package/dist/locales/ru.js +1 -1
  204. package/dist/locales/th.js +1 -1
  205. package/dist/locales/tr.js +1 -1
  206. package/dist/locales/vi.js +1 -1
  207. package/dist/locales/zh-hans.js +1 -1
  208. package/dist/locales/zh-hant.js +1 -1
  209. package/dist/styles.css +1 -1
  210. package/dist/tailwind.css +411 -30
  211. package/dist/types.d.ts +119 -6
  212. package/package.json +19 -18
  213. package/dist/components/avatar-group/AvatarGroup.d.ts +0 -47
  214. package/dist/components/avatar-group/AvatarGroup.js +0 -1
  215. package/dist/components/avatar-group/index.d.ts +0 -2
  216. package/dist/components/avatar-group/index.js +0 -1
  217. package/dist/internal/avatar-group.d.ts +0 -22
  218. package/dist/internal/avatar-group.js +0 -1
package/dist/tailwind.css CHANGED
@@ -172,6 +172,13 @@
172
172
  as a move. Nothing else may use it. */
173
173
  --neba-duration-window: 240ms;
174
174
 
175
+ /* How high every portalled surface sits: a menu, a dialog, a drawer, a
176
+ tooltip, a toast. One number, because they are all the same kind of thing
177
+ — something drawn over the page the reader was looking at — and because
178
+ the value a host needs is its own. A site whose fixed header is at 1200
179
+ sets this once rather than beating fourteen `z-50`s with a selector. */
180
+ --neba-z-portal: 50;
181
+
175
182
  /* Color families -------------------------------------------------------
176
183
  Chroma sits just under the sRGB gamut boundary for each family's lightness
177
184
  — around 90% of the maximum, close enough to be vivid and far enough that
@@ -1391,7 +1398,57 @@
1391
1398
  }
1392
1399
 
1393
1400
  /* ---------------------------------------------------------------------------
1394
- * Grid
1401
+ * Breakpoints
1402
+ *
1403
+ * The five widths the whole library branches on, taken from Tailwind's theme
1404
+ * rather than written out — `theme()` resolves at build time, in whichever
1405
+ * Tailwind build compiles this file, so a consumer who redeclares
1406
+ * `--breakpoint-md` in their own `@theme` moves the media queries below, the
1407
+ * `md:` variants the components spell out, and the JavaScript that reads the
1408
+ * tokens here, all at once. That is the whole mechanism: a breakpoint is a
1409
+ * build-time decision, because `@media` cannot read a custom property and no
1410
+ * amount of runtime configuration can change that.
1411
+ *
1412
+ * `xs` has no token because its floor is `0`: it is the value with no media
1413
+ * query around it, and there is nothing for JavaScript to look up.
1414
+ *
1415
+ * Tailwind does not emit `--breakpoint-*` into `:root` — they are compile-time
1416
+ * values to it — so the four are copied under a name of the library's own,
1417
+ * which is what `internal/media.ts` reads to build its `matchMedia` queries.
1418
+ * Declared once, on `:root` alone: a width is not a theme-dependent value, so
1419
+ * the rule about repeating derived tokens per theme root does not apply.
1420
+ * ------------------------------------------------------------------------- */
1421
+
1422
+ :root {
1423
+ --neba-breakpoint-sm: theme(--breakpoint-sm);
1424
+ --neba-breakpoint-md: theme(--breakpoint-md);
1425
+ --neba-breakpoint-lg: theme(--breakpoint-lg);
1426
+ --neba-breakpoint-xl: theme(--breakpoint-xl);
1427
+ }
1428
+
1429
+ /* ---------------------------------------------------------------------------
1430
+ * Responsive slots
1431
+ *
1432
+ * Every value in the library that changes at a breakpoint resolves here: one
1433
+ * cascade per slot name, each breakpoint falling back through the ones below
1434
+ * it, so `span={{ md: 6 }}` sets one custom property and not five. A media
1435
+ * query can change an inherited custom property without React hearing about
1436
+ * it, which is the whole reason this is CSS — the alternative is re-rendering
1437
+ * the tree at every breakpoint to say the same thing.
1438
+ *
1439
+ * Nothing here *applies* a value except the grid's own width arithmetic. The
1440
+ * components read the resolved slot through an ordinary Tailwind utility —
1441
+ * `gap-x-(--n-gap-x)`, `max-w-(--n-max-w)` — so a caller's own class fights
1442
+ * that utility on equal terms, exactly as it did before the value was
1443
+ * responsive. A real declaration in this file would win that fight, because
1444
+ * this sheet is loaded after the utilities.
1445
+ *
1446
+ * The chains get long at `xl`; that is the cost of keeping the DOM lean, and it
1447
+ * is paid once here rather than on every grid item in a consumer's app. It is
1448
+ * also why the list of responsive axes is deliberately short — four media
1449
+ * blocks per slot cannot be generated, so each new one is a decision.
1450
+ *
1451
+ * The grid ------------------------------------------------------------------
1395
1452
  *
1396
1453
  * A column is `(100% + gap) * span / columns - gap` wide, and an offset shifts
1397
1454
  * it by `(100% + gap) * offset / columns`. Both are exact rather than
@@ -1409,21 +1466,121 @@
1409
1466
  * `min(span, columns)` is the clamp: a `span={99}` fills its row instead of
1410
1467
  * overflowing the page, which is what the caller meant.
1411
1468
  *
1412
- * Every slot cascades upward — each breakpoint falls back through the ones
1413
- * below it — so `span={{ md: 6 }}` sets one custom property and not five. The
1414
- * chains get long at `xl`; that is the cost of keeping the DOM lean, and it is
1415
- * paid once here rather than on every grid item in a consumer's app.
1416
- *
1417
- * The widths are Tailwind's own breakpoints, so a Neba grid and a `md:` utility
1418
- * change at the same moment.
1469
+ * The widths are read from Tailwind's theme, so a Neba grid and a `md:` utility
1470
+ * change at the same moment — including when a consumer has moved them.
1419
1471
  * ------------------------------------------------------------------------- */
1420
1472
 
1421
- .neba-grid {
1422
- --n-cols: var(--n-cols-xs, 12);
1473
+ /* Every breakpoint slot is cleared on the element that reads it, and that is
1474
+ what keeps a nested component from reading its ancestor's layout.
1475
+
1476
+ A custom property inherits, and a slot the element did not write is
1477
+ therefore whatever the nearest ancestor wrote — so a grid inside a grid item
1478
+ resolved the *item's* `--n-span-md` and came out a third of the width it had
1479
+ asked for. Only the breakpoints a caller names are emitted, which is what
1480
+ keeps the inline style to one property, so there is nothing on the element
1481
+ to overwrite the inherited value with.
1482
+
1483
+ An inline style wins over this rule, so a component that really did name a
1484
+ breakpoint is untouched. What is deliberately *not* cleared is the resolved
1485
+ slot beside each of these: `--n-cols` and `--n-gap-x` are read by a grid's
1486
+ items rather than by the grid, and inheriting is how they get there. */
1487
+ .neba-grid,
1488
+ .neba-flex {
1489
+ --n-gap-x-xs: initial;
1490
+ --n-gap-x-sm: initial;
1491
+ --n-gap-x-md: initial;
1492
+ --n-gap-x-lg: initial;
1493
+ --n-gap-x-xl: initial;
1494
+ --n-gap-y-xs: initial;
1495
+ --n-gap-y-sm: initial;
1496
+ --n-gap-y-md: initial;
1497
+ --n-gap-y-lg: initial;
1498
+ --n-gap-y-xl: initial;
1499
+ }
1500
+
1501
+ .neba-grid,
1502
+ .neba-gallery {
1503
+ --n-cols-xs: initial;
1504
+ --n-cols-sm: initial;
1505
+ --n-cols-md: initial;
1506
+ --n-cols-lg: initial;
1507
+ --n-cols-xl: initial;
1508
+ }
1509
+
1510
+ .neba-flex {
1511
+ --n-flex-dir-xs: initial;
1512
+ --n-flex-dir-sm: initial;
1513
+ --n-flex-dir-md: initial;
1514
+ --n-flex-dir-lg: initial;
1515
+ --n-flex-dir-xl: initial;
1516
+ }
1517
+
1518
+ .neba-measure {
1519
+ --n-max-w-xs: initial;
1520
+ --n-max-w-sm: initial;
1521
+ --n-max-w-md: initial;
1522
+ --n-max-w-lg: initial;
1523
+ --n-max-w-xl: initial;
1524
+ }
1525
+
1526
+ .neba-grid-item {
1527
+ --n-span-xs: initial;
1528
+ --n-span-sm: initial;
1529
+ --n-span-md: initial;
1530
+ --n-span-lg: initial;
1531
+ --n-span-xl: initial;
1532
+ --n-span-w-xs: initial;
1533
+ --n-span-w-sm: initial;
1534
+ --n-span-w-md: initial;
1535
+ --n-span-w-lg: initial;
1536
+ --n-span-w-xl: initial;
1537
+ --n-grow-xs: initial;
1538
+ --n-grow-sm: initial;
1539
+ --n-grow-md: initial;
1540
+ --n-grow-lg: initial;
1541
+ --n-grow-xl: initial;
1542
+ --n-offset-xs: initial;
1543
+ --n-offset-sm: initial;
1544
+ --n-offset-md: initial;
1545
+ --n-offset-lg: initial;
1546
+ --n-offset-xl: initial;
1547
+ }
1548
+
1549
+ /* The two gutters, shared: a GridContainer and a Flex ask the same question
1550
+ and `spacing` has to mean the same number on both.
1551
+
1552
+ `--n-cols` is shared with a Gallery one rule down for that same reason: how
1553
+ many columns a row is cut into is one question, and a second cascade for it
1554
+ would be four more media blocks saying the thing this one already says. The
1555
+ `12` fallback is a grid's; a Gallery always emits its own `xs`, so it never
1556
+ reaches. */
1557
+ .neba-grid,
1558
+ .neba-flex {
1423
1559
  --n-gap-x: var(--n-gap-x-xs, 0px);
1424
1560
  --n-gap-y: var(--n-gap-y-xs, 0px);
1425
1561
  }
1426
1562
 
1563
+ .neba-grid,
1564
+ .neba-gallery {
1565
+ --n-cols: var(--n-cols-xs, 12);
1566
+ }
1567
+
1568
+ /* A Flex, whose other responsive value is which way the row runs. `row` is the
1569
+ fallback so a `<Flex>` with no direction at all is still a row. */
1570
+ .neba-flex {
1571
+ --n-flex-dir: var(--n-flex-dir-xs, row);
1572
+ }
1573
+
1574
+ /* A Container, a Header and a Footer, whose one responsive value is how wide
1575
+ the content on them is allowed to get. The slot is applied by a
1576
+ `max-w-(--n-max-w)` utility on the component rather than by a rule here, so
1577
+ the component's measure stays exactly as overridable by a caller's own
1578
+ `max-w-*` as it was when it was a `max-w-[48rem]` — a custom property is
1579
+ invisible to that fight, and a real class in this file would have won it. */
1580
+ .neba-measure {
1581
+ --n-max-w: var(--n-max-w-xs, none);
1582
+ }
1583
+
1427
1584
  .neba-grid-item {
1428
1585
  --n-span: var(--n-span-xs, var(--n-cols, 12));
1429
1586
  --n-offset: var(--n-offset-xs, 0);
@@ -1432,64 +1589,136 @@
1432
1589
  the container, so this re-resolves on its own at every breakpoint. */
1433
1590
  --n-track: calc((100% + var(--n-gap-x, 0px)) / var(--n-cols, 12));
1434
1591
 
1435
- /* Inseparable from the width above it: `flex` stops the row from resizing
1436
- the item, `min-width` stops a long unbroken word from doing the same, and
1437
- `box-sizing` is what makes the percentage mean the whole item. */
1592
+ /* What a span that is a share of the row works out to, named rather than
1593
+ written into `width` so that a breakpoint which goes back to a number can
1594
+ point at it. */
1595
+ --n-col-width: calc(var(--n-track) * min(var(--n-span), var(--n-cols, 12)) - var(--n-gap-x, 0px));
1596
+
1597
+ /* `auto` and `grow` are the two widths a column count cannot reach — the
1598
+ contents' own width, with and without the space left over in the row — so
1599
+ they are a cascade of their own rather than a value inside the one above.
1600
+ A caller who names a number at a wider breakpoint points this back at the
1601
+ arithmetic, which is what lets the two mix in one map. */
1602
+ --n-span-w: var(--n-span-w-xs, var(--n-col-width));
1603
+ --n-grow: var(--n-grow-xs, 0);
1604
+
1605
+ /* Inseparable from the width above it: the row must not resize the item,
1606
+ `min-width` stops a long unbroken word from doing the same, `max-width`
1607
+ holds an `auto` item inside the row it is in, and `box-sizing` is what
1608
+ makes the percentage mean the whole item. */
1438
1609
  box-sizing: border-box;
1439
- flex: 0 0 auto;
1610
+ flex-grow: var(--n-grow);
1611
+ flex-shrink: 0;
1612
+ flex-basis: auto;
1440
1613
  min-width: 0;
1441
- width: calc(var(--n-track) * min(var(--n-span), var(--n-cols, 12)) - var(--n-gap-x, 0px));
1614
+ max-width: 100%;
1615
+ width: var(--n-span-w);
1442
1616
  margin-inline-start: calc(var(--n-track) * min(var(--n-offset), var(--n-cols, 12)));
1443
1617
  }
1444
1618
 
1445
- @media (width >= 40rem) {
1446
- .neba-grid {
1447
- --n-cols: var(--n-cols-sm, var(--n-cols-xs, 12));
1619
+ @media (width >= theme(--breakpoint-sm)) {
1620
+ .neba-measure {
1621
+ --n-max-w: var(--n-max-w-sm, var(--n-max-w-xs, none));
1622
+ }
1623
+
1624
+ .neba-grid,
1625
+ .neba-flex {
1448
1626
  --n-gap-x: var(--n-gap-x-sm, var(--n-gap-x-xs, 0px));
1449
1627
  --n-gap-y: var(--n-gap-y-sm, var(--n-gap-y-xs, 0px));
1450
1628
  }
1451
1629
 
1630
+ .neba-grid,
1631
+ .neba-gallery {
1632
+ --n-cols: var(--n-cols-sm, var(--n-cols-xs, 12));
1633
+ }
1634
+
1635
+ .neba-flex {
1636
+ --n-flex-dir: var(--n-flex-dir-sm, var(--n-flex-dir-xs, row));
1637
+ }
1638
+
1452
1639
  .neba-grid-item {
1453
1640
  --n-span: var(--n-span-sm, var(--n-span-xs, var(--n-cols, 12)));
1641
+ --n-span-w: var(--n-span-w-sm, var(--n-span-w-xs, var(--n-col-width)));
1642
+ --n-grow: var(--n-grow-sm, var(--n-grow-xs, 0));
1454
1643
  --n-offset: var(--n-offset-sm, var(--n-offset-xs, 0));
1455
1644
  }
1456
1645
  }
1457
1646
 
1458
- @media (width >= 48rem) {
1459
- .neba-grid {
1460
- --n-cols: var(--n-cols-md, var(--n-cols-sm, var(--n-cols-xs, 12)));
1647
+ @media (width >= theme(--breakpoint-md)) {
1648
+ .neba-measure {
1649
+ --n-max-w: var(--n-max-w-md, var(--n-max-w-sm, var(--n-max-w-xs, none)));
1650
+ }
1651
+
1652
+ .neba-grid,
1653
+ .neba-flex {
1461
1654
  --n-gap-x: var(--n-gap-x-md, var(--n-gap-x-sm, var(--n-gap-x-xs, 0px)));
1462
1655
  --n-gap-y: var(--n-gap-y-md, var(--n-gap-y-sm, var(--n-gap-y-xs, 0px)));
1463
1656
  }
1464
1657
 
1658
+ .neba-grid,
1659
+ .neba-gallery {
1660
+ --n-cols: var(--n-cols-md, var(--n-cols-sm, var(--n-cols-xs, 12)));
1661
+ }
1662
+
1663
+ .neba-flex {
1664
+ --n-flex-dir: var(--n-flex-dir-md, var(--n-flex-dir-sm, var(--n-flex-dir-xs, row)));
1665
+ }
1666
+
1465
1667
  .neba-grid-item {
1466
1668
  --n-span: var(--n-span-md, var(--n-span-sm, var(--n-span-xs, var(--n-cols, 12))));
1669
+ --n-span-w: var(--n-span-w-md, var(--n-span-w-sm, var(--n-span-w-xs, var(--n-col-width))));
1670
+ --n-grow: var(--n-grow-md, var(--n-grow-sm, var(--n-grow-xs, 0)));
1467
1671
  --n-offset: var(--n-offset-md, var(--n-offset-sm, var(--n-offset-xs, 0)));
1468
1672
  }
1469
1673
  }
1470
1674
 
1471
- @media (width >= 64rem) {
1472
- .neba-grid {
1473
- --n-cols: var(--n-cols-lg, var(--n-cols-md, var(--n-cols-sm, var(--n-cols-xs, 12))));
1675
+ @media (width >= theme(--breakpoint-lg)) {
1676
+ .neba-measure {
1677
+ --n-max-w: var(--n-max-w-lg, var(--n-max-w-md, var(--n-max-w-sm, var(--n-max-w-xs, none))));
1678
+ }
1679
+
1680
+ .neba-grid,
1681
+ .neba-flex {
1474
1682
  --n-gap-x: var(--n-gap-x-lg, var(--n-gap-x-md, var(--n-gap-x-sm, var(--n-gap-x-xs, 0px))));
1475
1683
  --n-gap-y: var(--n-gap-y-lg, var(--n-gap-y-md, var(--n-gap-y-sm, var(--n-gap-y-xs, 0px))));
1476
1684
  }
1477
1685
 
1686
+ .neba-grid,
1687
+ .neba-gallery {
1688
+ --n-cols: var(--n-cols-lg, var(--n-cols-md, var(--n-cols-sm, var(--n-cols-xs, 12))));
1689
+ }
1690
+
1691
+ .neba-flex {
1692
+ --n-flex-dir: var(
1693
+ --n-flex-dir-lg,
1694
+ var(--n-flex-dir-md, var(--n-flex-dir-sm, var(--n-flex-dir-xs, row)))
1695
+ );
1696
+ }
1697
+
1478
1698
  .neba-grid-item {
1479
1699
  --n-span: var(
1480
1700
  --n-span-lg,
1481
1701
  var(--n-span-md, var(--n-span-sm, var(--n-span-xs, var(--n-cols, 12))))
1482
1702
  );
1703
+ --n-span-w: var(
1704
+ --n-span-w-lg,
1705
+ var(--n-span-w-md, var(--n-span-w-sm, var(--n-span-w-xs, var(--n-col-width))))
1706
+ );
1707
+ --n-grow: var(--n-grow-lg, var(--n-grow-md, var(--n-grow-sm, var(--n-grow-xs, 0))));
1483
1708
  --n-offset: var(--n-offset-lg, var(--n-offset-md, var(--n-offset-sm, var(--n-offset-xs, 0))));
1484
1709
  }
1485
1710
  }
1486
1711
 
1487
- @media (width >= 80rem) {
1488
- .neba-grid {
1489
- --n-cols: var(
1490
- --n-cols-xl,
1491
- var(--n-cols-lg, var(--n-cols-md, var(--n-cols-sm, var(--n-cols-xs, 12))))
1712
+ @media (width >= theme(--breakpoint-xl)) {
1713
+ .neba-measure {
1714
+ --n-max-w: var(
1715
+ --n-max-w-xl,
1716
+ var(--n-max-w-lg, var(--n-max-w-md, var(--n-max-w-sm, var(--n-max-w-xs, none))))
1492
1717
  );
1718
+ }
1719
+
1720
+ .neba-grid,
1721
+ .neba-flex {
1493
1722
  --n-gap-x: var(
1494
1723
  --n-gap-x-xl,
1495
1724
  var(--n-gap-x-lg, var(--n-gap-x-md, var(--n-gap-x-sm, var(--n-gap-x-xs, 0px))))
@@ -1500,11 +1729,37 @@
1500
1729
  );
1501
1730
  }
1502
1731
 
1732
+ .neba-grid,
1733
+ .neba-gallery {
1734
+ --n-cols: var(
1735
+ --n-cols-xl,
1736
+ var(--n-cols-lg, var(--n-cols-md, var(--n-cols-sm, var(--n-cols-xs, 12))))
1737
+ );
1738
+ }
1739
+
1740
+ .neba-flex {
1741
+ --n-flex-dir: var(
1742
+ --n-flex-dir-xl,
1743
+ var(--n-flex-dir-lg, var(--n-flex-dir-md, var(--n-flex-dir-sm, var(--n-flex-dir-xs, row))))
1744
+ );
1745
+ }
1746
+
1503
1747
  .neba-grid-item {
1504
1748
  --n-span: var(
1505
1749
  --n-span-xl,
1506
1750
  var(--n-span-lg, var(--n-span-md, var(--n-span-sm, var(--n-span-xs, var(--n-cols, 12)))))
1507
1751
  );
1752
+ --n-span-w: var(
1753
+ --n-span-w-xl,
1754
+ var(
1755
+ --n-span-w-lg,
1756
+ var(--n-span-w-md, var(--n-span-w-sm, var(--n-span-w-xs, var(--n-col-width))))
1757
+ )
1758
+ );
1759
+ --n-grow: var(
1760
+ --n-grow-xl,
1761
+ var(--n-grow-lg, var(--n-grow-md, var(--n-grow-sm, var(--n-grow-xs, 0))))
1762
+ );
1508
1763
  --n-offset: var(
1509
1764
  --n-offset-xl,
1510
1765
  var(--n-offset-lg, var(--n-offset-md, var(--n-offset-sm, var(--n-offset-xs, 0))))
@@ -1512,6 +1767,31 @@
1512
1767
  }
1513
1768
  }
1514
1769
 
1770
+ /* ---------------------------------------------------------------------------
1771
+ * A justified gallery's last row
1772
+ *
1773
+ * `layout="justified"` is a wrapping flex row where every tile grows in
1774
+ * proportion to its own aspect ratio, which is what makes each row fill the
1775
+ * width exactly and every tile in it come out the same height. The arithmetic
1776
+ * is the browser's; nothing is measured and nothing re-renders on a resize.
1777
+ *
1778
+ * The one thing it gets wrong on its own is the last row, which has fewer tiles
1779
+ * to share the same width and blows them up to fill it — five photographs
1780
+ * ending in one the size of a poster. A generated box with an absurd
1781
+ * `flex-grow` takes that leftover instead, so the last row keeps the height the
1782
+ * rows above it have.
1783
+ *
1784
+ * It is `::after` rather than an element because the gallery is a `<ul>`, and a
1785
+ * spacer `<span>` between the `<li>`s is markup that says a list item is
1786
+ * something it is not.
1787
+ * ------------------------------------------------------------------------- */
1788
+
1789
+ .neba-gallery-justified::after {
1790
+ content: '';
1791
+ flex-grow: 1000000000;
1792
+ min-inline-size: 0;
1793
+ }
1794
+
1515
1795
  /* ---------------------------------------------------------------------------
1516
1796
  * Tree guides
1517
1797
  *
@@ -1858,6 +2138,27 @@
1858
2138
  animation-play-state: var(--n-anim-state, running);
1859
2139
  }
1860
2140
 
2141
+ /*
2142
+ * The same eleven effects, driven by where the element is rather than by when.
2143
+ *
2144
+ * Two declarations and nothing else, which is the whole reason this is a prop
2145
+ * and not a component: every keyframe already runs from a start state to the
2146
+ * element's own, so pointing it at a scroll timeline instead of the clock needs
2147
+ * no new keyframe and no JavaScript. A `timeline` of `view` fills the slot; the
2148
+ * default `auto` is the clock, and the three declarations above go on meaning
2149
+ * what they meant.
2150
+ *
2151
+ * Guarded, because a browser without `animation-timeline` must not be handed an
2152
+ * animation with no clock to run on: unsupported, the whole block is skipped and
2153
+ * the effect plays once on the timeline it always had. Degraded, never blank.
2154
+ */
2155
+ @supports (animation-timeline: view()) {
2156
+ .neba-anim {
2157
+ animation-timeline: var(--n-anim-timeline, auto);
2158
+ animation-range: var(--n-anim-range, normal);
2159
+ }
2160
+ }
2161
+
1861
2162
  @keyframes neba-anim-fade {
1862
2163
  from {
1863
2164
  opacity: var(--n-anim-opacity, 0);
@@ -1936,6 +2237,81 @@
1936
2237
  animation-name: neba-anim-blink;
1937
2238
  }
1938
2239
 
2240
+ /*
2241
+ * Reveal: an edge travelling across something that is already there.
2242
+ *
2243
+ * `clip-path` rather than a mask, and rather than a wrapper with `overflow`.
2244
+ * A mask would need a gradient whose direction is a fourth thing to keep in
2245
+ * step with the side; a wrapper would be an element in the layout that the
2246
+ * effect had no other reason to add. An inset is one property, it is animatable,
2247
+ * and `inset(0)` — the resting state — is exactly "nothing clipped".
2248
+ *
2249
+ * The opacity slot defaults to `1` here rather than to `0`: a reveal is not a
2250
+ * fade, and something wiped in while also fading has had the wipe wasted on it.
2251
+ * Pass `fade` and it is both.
2252
+ */
2253
+ @keyframes neba-anim-reveal {
2254
+ from {
2255
+ opacity: var(--n-anim-opacity, 1);
2256
+ clip-path: var(--n-anim-clip, inset(0 100% 0 0));
2257
+ }
2258
+ to {
2259
+ opacity: 1;
2260
+ clip-path: inset(0);
2261
+ }
2262
+ }
2263
+
2264
+ .neba-anim-reveal {
2265
+ animation-name: neba-anim-reveal;
2266
+ }
2267
+
2268
+ /* Float: a slow drift with nowhere to get to. Asymmetric on purpose — it starts
2269
+ where the element sits, so an element whose animation is interrupted is left
2270
+ where the layout put it rather than half a centimetre above it. */
2271
+ @keyframes neba-anim-float {
2272
+ from {
2273
+ translate: 0 0;
2274
+ }
2275
+ to {
2276
+ translate: var(--n-anim-x, 0px) var(--n-anim-y, -0.5rem);
2277
+ }
2278
+ }
2279
+
2280
+ .neba-anim-float {
2281
+ animation-name: neba-anim-float;
2282
+ }
2283
+
2284
+ /*
2285
+ * Shake: the one effect in the set that says *no*.
2286
+ *
2287
+ * Five stops rather than two, and the last two are smaller than the first two,
2288
+ * because a shake that ends as hard as it began reads as a loop that was cut
2289
+ * off. It starts and ends at zero for the reason `blink` is symmetric: an
2290
+ * interrupted run must not leave the element off its own mark.
2291
+ */
2292
+ @keyframes neba-anim-shake {
2293
+ 0%,
2294
+ 100% {
2295
+ translate: 0 0;
2296
+ }
2297
+ 20% {
2298
+ translate: calc(var(--n-anim-x, 6px) * -1) 0;
2299
+ }
2300
+ 40% {
2301
+ translate: var(--n-anim-x, 6px) 0;
2302
+ }
2303
+ 60% {
2304
+ translate: calc(var(--n-anim-x, 6px) * -0.55) 0;
2305
+ }
2306
+ 80% {
2307
+ translate: calc(var(--n-anim-x, 6px) * 0.55) 0;
2308
+ }
2309
+ }
2310
+
2311
+ .neba-anim-shake {
2312
+ animation-name: neba-anim-shake;
2313
+ }
2314
+
1939
2315
  /*
1940
2316
  * Lighting: a light travelling around the outside of something.
1941
2317
  *
@@ -2048,7 +2424,12 @@
2048
2424
  animation-name: neba-anim-marquee-y;
2049
2425
  }
2050
2426
 
2051
- .neba-marquee[data-pause-on-hover]:hover .neba-marquee-track {
2427
+ /* `:focus-within` beside `:hover` for the same reason the prop exists at all. A
2428
+ pointer stops the strip so a link on it can be aimed at; a keyboard reaches
2429
+ that link by tabbing to it, and a strip that kept moving would be carrying the
2430
+ focused element off the screen. */
2431
+ .neba-marquee[data-pause-on-hover]:hover .neba-marquee-track,
2432
+ .neba-marquee[data-pause-on-hover]:focus-within .neba-marquee-track {
2052
2433
  animation-play-state: paused;
2053
2434
  }
2054
2435