@kanso-labs/kanso-ui 0.38.0 → 0.39.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/README.md +234 -35
  2. package/dist/button/hooks.js +1 -1
  3. package/dist/button/index.js +1 -1
  4. package/dist/button/index.js.map +1 -1
  5. package/dist/collection/index.js +4 -4
  6. package/dist/collection/index.js.map +1 -1
  7. package/dist/color-scheme.d.ts +19 -12
  8. package/dist/color-scheme.js +22 -15
  9. package/dist/color-scheme.js.map +1 -1
  10. package/dist/components/app-bar/index.d.ts +10 -14
  11. package/dist/components/app-bar/index.js +12 -12
  12. package/dist/components/app-bar/index.js.map +1 -1
  13. package/dist/components/avatar/index.d.ts +15 -1
  14. package/dist/components/avatar/index.js +43 -145
  15. package/dist/components/avatar/index.js.map +1 -1
  16. package/dist/components/breadcrumbs/index.d.ts +1 -1
  17. package/dist/components/breadcrumbs/index.js.map +1 -1
  18. package/dist/components/button/index.js +3 -3
  19. package/dist/components/button/index.js.map +1 -1
  20. package/dist/components/calendar/index.js.map +1 -1
  21. package/dist/components/card/index.js.map +1 -1
  22. package/dist/components/chip/index.js +27 -25
  23. package/dist/components/chip/index.js.map +1 -1
  24. package/dist/components/chip-group/index.d.ts +22 -1
  25. package/dist/components/chip-group/index.js +3 -3
  26. package/dist/components/chip-group/index.js.map +1 -1
  27. package/dist/components/code/index.js +1 -1
  28. package/dist/components/code/index.js.map +1 -1
  29. package/dist/components/color-picker/index.d.ts +5 -5
  30. package/dist/components/color-picker/index.js +46 -51
  31. package/dist/components/color-picker/index.js.map +1 -1
  32. package/dist/components/color-swatch-picker/index.d.ts +1 -1
  33. package/dist/components/color-swatch-picker/index.js.map +1 -1
  34. package/dist/components/combo-box/index.d.ts +5 -5
  35. package/dist/components/combo-box/index.js +33 -35
  36. package/dist/components/combo-box/index.js.map +1 -1
  37. package/dist/components/copy-field/index.js +1 -1
  38. package/dist/components/copy-field/index.js.map +1 -1
  39. package/dist/components/currency/index.d.ts +16 -0
  40. package/dist/components/currency/index.js +16 -0
  41. package/dist/components/currency/index.js.map +1 -1
  42. package/dist/components/date-field/index.js.map +1 -1
  43. package/dist/components/date-picker/index.d.ts +5 -5
  44. package/dist/components/date-picker/index.js +35 -40
  45. package/dist/components/date-picker/index.js.map +1 -1
  46. package/dist/components/date-range-picker/index.d.ts +5 -5
  47. package/dist/components/date-range-picker/index.js +35 -40
  48. package/dist/components/date-range-picker/index.js.map +1 -1
  49. package/dist/components/dialog/index.d.ts +15 -12
  50. package/dist/components/dialog/index.js +151 -97
  51. package/dist/components/dialog/index.js.map +1 -1
  52. package/dist/components/disclosure/index.d.ts +1 -1
  53. package/dist/components/disclosure/index.js.map +1 -1
  54. package/dist/components/fab-menu/index.d.ts +4 -2
  55. package/dist/components/fab-menu/index.js.map +1 -1
  56. package/dist/components/index.d.ts +4 -2
  57. package/dist/components/list/index.d.ts +3 -3
  58. package/dist/components/list/index.js +2 -2
  59. package/dist/components/list/index.js.map +1 -1
  60. package/dist/components/list-box/index.d.ts +3 -3
  61. package/dist/components/list-box/index.js +2 -2
  62. package/dist/components/list-box/index.js.map +1 -1
  63. package/dist/components/list-item/index.js +1 -1
  64. package/dist/components/loading-indicator/index.d.ts +30 -0
  65. package/dist/components/loading-indicator/index.js +71 -0
  66. package/dist/components/loading-indicator/index.js.map +1 -0
  67. package/dist/components/menu/index.d.ts +8 -8
  68. package/dist/components/menu/index.js +2 -2
  69. package/dist/components/menu/index.js.map +1 -1
  70. package/dist/components/navigation-tree/index.d.ts +2 -2
  71. package/dist/components/navigation-tree/index.js.map +1 -1
  72. package/dist/components/popover/index.d.ts +7 -7
  73. package/dist/components/popover/index.js.map +1 -1
  74. package/dist/components/product-icon/index.d.ts +1 -1
  75. package/dist/components/product-icon/index.js +28 -142
  76. package/dist/components/product-icon/index.js.map +1 -1
  77. package/dist/components/progress-indicator/index.d.ts +21 -15
  78. package/dist/components/progress-indicator/index.js +485 -185
  79. package/dist/components/progress-indicator/index.js.map +1 -1
  80. package/dist/components/range-calendar/index.js.map +1 -1
  81. package/dist/components/search-view/index.d.ts +5 -5
  82. package/dist/components/search-view/index.js.map +1 -1
  83. package/dist/components/segmented-button/index.d.ts +1 -1
  84. package/dist/components/segmented-button/index.js.map +1 -1
  85. package/dist/components/select/index.d.ts +5 -5
  86. package/dist/components/select/index.js +5 -2
  87. package/dist/components/select/index.js.map +1 -1
  88. package/dist/components/sheet/index.d.ts +10 -10
  89. package/dist/components/sheet/index.js +27 -20
  90. package/dist/components/sheet/index.js.map +1 -1
  91. package/dist/components/slider/index.js +1 -1
  92. package/dist/components/slider/index.js.map +1 -1
  93. package/dist/components/split-button/index.d.ts +4 -2
  94. package/dist/components/split-button/index.js.map +1 -1
  95. package/dist/components/stack/index.d.ts +4 -1
  96. package/dist/components/stack/index.js +7 -1
  97. package/dist/components/stack/index.js.map +1 -1
  98. package/dist/components/table/index.d.ts +7 -7
  99. package/dist/components/table/index.js +39 -26
  100. package/dist/components/table/index.js.map +1 -1
  101. package/dist/components/tabs/index.d.ts +4 -4
  102. package/dist/components/tabs/index.js +59 -27
  103. package/dist/components/tabs/index.js.map +1 -1
  104. package/dist/components/text/index.d.ts +22 -9
  105. package/dist/components/text/index.js +22 -5
  106. package/dist/components/text/index.js.map +1 -1
  107. package/dist/components/time-picker/index.d.ts +110 -0
  108. package/dist/components/time-picker/index.js +954 -0
  109. package/dist/components/time-picker/index.js.map +1 -0
  110. package/dist/components/tooltip/index.d.ts +5 -5
  111. package/dist/components/tooltip/index.js +1 -0
  112. package/dist/components/tooltip/index.js.map +1 -1
  113. package/dist/components/tree/index.d.ts +2 -2
  114. package/dist/components/tree/index.js +2 -2
  115. package/dist/components/tree/index.js.map +1 -1
  116. package/dist/glyphs/index.js +37 -1
  117. package/dist/glyphs/index.js.map +1 -1
  118. package/dist/i18n/index.js +4 -0
  119. package/dist/i18n/index.js.map +1 -1
  120. package/dist/i18n/messages.js +136 -0
  121. package/dist/i18n/messages.js.map +1 -1
  122. package/dist/index.d.ts +6 -3
  123. package/dist/index.js +5 -2
  124. package/dist/indicator/index.js +38 -35
  125. package/dist/indicator/index.js.map +1 -1
  126. package/dist/mark/index.js +137 -0
  127. package/dist/mark/index.js.map +1 -0
  128. package/dist/mark/initials.js +42 -0
  129. package/dist/mark/initials.js.map +1 -0
  130. package/dist/mark/styles.js +91 -0
  131. package/dist/mark/styles.js.map +1 -0
  132. package/dist/render/ref.js +35 -1
  133. package/dist/render/ref.js.map +1 -1
  134. package/dist/render/useRender.js +1 -30
  135. package/dist/render/useRender.js.map +1 -1
  136. package/dist/styles/picker.js +29 -1
  137. package/dist/styles/picker.js.map +1 -1
  138. package/dist/styles.css +685 -231
  139. package/dist/theme-scope.d.ts +40 -0
  140. package/dist/theme-scope.js +112 -0
  141. package/dist/theme-scope.js.map +1 -0
  142. package/dist/tokens/design.tokens.stylex.js +39 -5
  143. package/dist/tokens/design.tokens.stylex.js.map +1 -1
  144. package/package.json +2 -1
package/README.md CHANGED
@@ -20,6 +20,9 @@ Every component is documented in Storybook, published from the latest release at
20
20
  npm install @kanso-labs/kanso-ui
21
21
  ```
22
22
 
23
+ Coming from an earlier 0.x release? [`UPGRADING.md`](UPGRADING.md) lists every
24
+ breaking change on the way to 1.0, with the edit each one asks for.
25
+
23
26
  ## Usage
24
27
 
25
28
  ```tsx
@@ -36,13 +39,19 @@ default, in both light and dark (respecting the OS-level
36
39
  `prefers-color-scheme`), and every component sizes itself with
37
40
  `box-sizing: border-box` rather than leaving that to a reset you supply.
38
41
 
39
- A bundler is what resolves that stylesheet. In an environment that cannot import
40
- CSS from JavaScript — some server-side renderers, or a plain Node process —
41
- import it yourself instead and the components style themselves the same way:
42
+ A bundler is what resolves that stylesheet, so the package always loads through
43
+ one. The main entry imports `./styles.css` itself and Node has no loader for
44
+ CSS, so in plain Node an `import` or a `require()` of `@kanso-labs/kanso-ui`
45
+ throws `ERR_UNKNOWN_FILE_EXTENSION`; `@kanso-labs/kanso-ui/date` is the one
46
+ entry plain Node can load. A server renderer or a test runner that leaves
47
+ dependencies to Node takes one setting to hand this package to its bundler
48
+ instead, and [Server rendering and tests](#server-rendering-and-tests) gives it
49
+ for Vite, Vitest and Jest.
42
50
 
43
- ```ts
44
- import '@kanso-labs/kanso-ui/styles.css'
45
- ```
51
+ The same stylesheet is published on its own, as
52
+ `@kanso-labs/kanso-ui/styles.css`, for CSS that loads it apart from the
53
+ JavaScript: an `@import` in a stylesheet of your own, or a `<link>`. It adds the
54
+ rules and nothing else, so it is not a way round the main entry's own import.
46
55
 
47
56
  `className` and `style` reach the element a component renders, so a component is
48
57
  positioned from the call site like any other element:
@@ -203,7 +212,7 @@ the page scrolls, becoming the small bar:
203
212
  contentMaxInlineSize="960px"
204
213
  headline="Headline"
205
214
  scrolled={scrollTop > 0}
206
- size="large"
215
+ size="lg"
207
216
  />
208
217
  {page}
209
218
  </div>
@@ -299,14 +308,17 @@ function StarIcon() {
299
308
  `1em` works because the slots that own an icon's size set it as a font size, and
300
309
  the icon inherits it:
301
310
 
302
- | Slot | Size an `em` icon takes |
303
- | ------------------------------------------ | ---------------------------------------------------- |
304
- | `Button`'s `icon` | 20px, 20px, 24px, 32px and 40px across `xs` to `xxl` |
305
- | `Chip`'s and `ChipGroup.Chip`'s `icon` | 18px |
306
- | `IconButton` | 20px, 24px, 24px, 32px and 40px across `xs` to `xxl` |
307
- | A field's `leadingIcon` and `trailingIcon` | 24px |
308
- | `SegmentedButton.Segment`'s `icon` | 18px |
309
- | `Tabs.Tab`'s `icon` | 24px |
311
+ | Slot | Size an `em` icon takes |
312
+ | ------------------------------------------- | ---------------------------------------------------- |
313
+ | `Button`'s `icon` | 20px, 20px, 24px, 32px and 40px across `xs` to `xxl` |
314
+ | `Chip`'s and `ChipGroup.Chip`'s `icon` | 18px |
315
+ | `Fab`'s children, with or without a `label` | 24px, 28px and 36px across `md` to `xl` |
316
+ | `FabMenu`'s `icon` | 24px, 28px and 36px across `md` to `xl` |
317
+ | `FabMenu.Item`'s `icon` | 24px |
318
+ | `IconButton` | 20px, 24px, 24px, 32px and 40px across `xs` to `xxl` |
319
+ | A field's `leadingIcon` and `trailingIcon` | 24px |
320
+ | `SegmentedButton.Segment`'s `icon` | 18px |
321
+ | `Tabs.Tab`'s `icon` | 24px |
310
322
 
311
323
  **The `leading` and `trailing` slots on a row are different.** A list item, a
312
324
  menu item, a tree item and an app bar set no icon size, so an icon there takes
@@ -367,13 +379,70 @@ Four things follow from where that boundary falls.
367
379
  ```
368
380
 
369
381
  - **The React Aria utilities the package re-exports are client-only** —
370
- `I18nProvider`, `useListData`, `parseColor` and the rest. `collectionSizes` is
371
- a plain value and works on either side.
382
+ `I18nProvider`, `useListData`, `parseColor` and the rest. `collectionSizes`,
383
+ `colorScheme` and `themeScope` are plain values and work on either side.
372
384
  - **A server-rendered app wraps its tree in `I18nProvider`** with the request's
373
385
  locale. React Aria reads the browser's locale on the client and has none on
374
386
  the server, so without it a date or a number can render differently on the two
375
387
  and fail hydration.
376
388
 
389
+ ### Server rendering and tests
390
+
391
+ The main entry imports its own stylesheet, so the package has to reach a bundler
392
+ wherever it runs. Three tools hand dependencies to Node by default, and each has
393
+ a setting that sends this package through its bundler instead.
394
+
395
+ **Vite's server rendering** leaves dependencies to Node, in `vite dev` and in a
396
+ built server alike, so the server of a Vite-based framework — React Router's
397
+ framework mode, TanStack Start, Astro, Vike — throws
398
+ `ERR_UNKNOWN_FILE_EXTENSION` for `dist/styles.css` as it starts. Name the
399
+ package in `ssr.noExternal`, wherever the framework takes its Vite settings
400
+ (Astro's sit under `vite` in `astro.config.mjs`):
401
+
402
+ ```ts
403
+ // vite.config.ts
404
+ import { defineConfig } from 'vite'
405
+
406
+ export default defineConfig({
407
+ ssr: { noExternal: ['@kanso-labs/kanso-ui'] },
408
+ })
409
+ ```
410
+
411
+ **Vitest** leaves dependencies to Node too, so the first test that imports a
412
+ component fails with `Unknown file extension ".css"`. Inline the package:
413
+
414
+ ```ts
415
+ // vitest.config.ts
416
+ import { defineConfig } from 'vitest/config'
417
+
418
+ export default defineConfig({
419
+ test: { server: { deps: { inline: ['@kanso-labs/kanso-ui'] } } },
420
+ })
421
+ ```
422
+
423
+ **Jest** wants a stand-in for the stylesheet, since it has no loader for CSS,
424
+ and a transform for the package, since the package is ES modules:
425
+
426
+ ```js
427
+ // jest.config.cjs
428
+ module.exports = {
429
+ moduleNameMapper: { '\\.css$': '<rootDir>/style-stub.cjs' },
430
+ transformIgnorePatterns: [
431
+ '^(?!.*/node_modules/@kanso-labs/kanso-ui/).*/node_modules/',
432
+ ],
433
+ }
434
+ ```
435
+
436
+ `style-stub.cjs` is `module.exports = {}`, and the transform needs a Babel
437
+ config that compiles modules to CommonJS, such as `@babel/preset-env`. The
438
+ pattern is written to let in everything under the package, its own
439
+ `dist/node_modules` included, which carries StyleX's runtime: the shorter
440
+ `/node_modules/(?!@kanso-labs/kanso-ui/)` matches again at that second
441
+ `node_modules` and leaves the runtime untransformed. On Node 24.9 or newer, Jest
442
+ 30 can load the package as ES modules instead, under
443
+ `NODE_OPTIONS=--experimental-vm-modules`, and then needs the `moduleNameMapper`
444
+ alone.
445
+
377
446
  ## Theming
378
447
 
379
448
  Every design token — color, spacing, radii, sizing, shadows, typography,
@@ -395,10 +464,8 @@ component, independent of your app's build tooling:
395
464
  }
396
465
  ```
397
466
 
398
- Overrides must target `:root` (or another selector matching the `<html>`
399
- element) — components resolve their tokens once, at the root, so redeclaring a
400
- `--kui-*` property on a smaller scope (e.g. a wrapping `<div>`) doesn't reach
401
- them.
467
+ Overrides on `:root` reach the whole page. To theme part of one, declare them on
468
+ a `ThemeScope` instead — see [Theming part of a page](#theming-part-of-a-page).
402
469
 
403
470
  [`@kanso-labs/kanso-ui/tokens.css`](src/tokens/design.tokens.css) is the
404
471
  canonical, generated reference for every available variable and its current
@@ -409,41 +476,173 @@ default value — useful for discovering names, not required at runtime
409
476
  import '@kanso-labs/kanso-ui/tokens.css'
410
477
  ```
411
478
 
479
+ ### A scheme from Material Theme Builder
480
+
481
+ The colour roles are Material Design's, so a whole scheme can come from
482
+ [Material Theme Builder](https://material-foundation.github.io/material-theme-builder/)
483
+ rather than being written out one role at a time. Pick a source colour there, or
484
+ one each for primary, secondary and tertiary, and export the theme as JSON. The
485
+ file, `material-theme.json`, keeps its schemes under `schemes`, and the `light`
486
+ and `dark` ones each name 49 roles in camel case. Every one of them is a role
487
+ here under the same name, `onPrimaryContainer` being
488
+ `--kui-color-on-primary-container`, so this script turns the two into the
489
+ overrides above:
490
+
491
+ ```js
492
+ // node theme.mjs material-theme.json > theme.css
493
+ import { readFileSync } from 'node:fs'
494
+
495
+ const { schemes } = JSON.parse(readFileSync(process.argv[2], 'utf8'))
496
+
497
+ // onPrimaryContainer becomes --kui-color-on-primary-container.
498
+ const block = (scheme, indent) =>
499
+ Object.entries(scheme)
500
+ .map(([role, value]) => {
501
+ const name = role.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)
502
+ return `${indent}--kui-color-${name}: ${value};`
503
+ })
504
+ .join('\n')
505
+
506
+ console.log(`:root {
507
+ ${block(schemes.light, ' ')}
508
+ }
509
+
510
+ @media (prefers-color-scheme: dark) {
511
+ :root {
512
+ ${block(schemes.dark, ' ')}
513
+ }
514
+ }`)
515
+ ```
516
+
517
+ `schemes` holds a medium-contrast and a high-contrast version of each scheme as
518
+ well, `light-medium-contrast` and the rest; read those in place of `light` and
519
+ `dark` for an app that offers more contrast. An app that pins light or dark keys
520
+ the two blocks on its own switch rather than on the media query, as
521
+ [Pinning light or dark](#pinning-light-or-dark) describes.
522
+
523
+ That leaves `positive` and `negative`, the two roles here that Material Design
524
+ does not have. They are the `positive` and `negative` tones on `Avatar`,
525
+ `Currency`, `Meter`, `ProductIcon`, `Tag` and `Text`, the pair `Currency`'s
526
+ `auto` tone picks between by a value's sign, and they are kept apart from
527
+ `error` so that a negative amount does not read as a failed field. The export
528
+ has no role for them, so they keep the library's own green and rust unless you
529
+ set them as well. To match them to a brand, add each as a custom colour in Theme
530
+ Builder. It draws a custom colour at the tones Material Design draws `error` at,
531
+ 40, 100, 90 and 10 in light and 80, 20, 30 and 90 in dark, which is how the
532
+ library's own two are drawn, and its four roles in each scheme map onto four
533
+ here:
534
+
535
+ | Custom colour role | Here |
536
+ | ------------------- | ----------------------------------- |
537
+ | Colour | `--kui-color-positive` |
538
+ | On colour | `--kui-color-on-positive` |
539
+ | Colour container | `--kui-color-positive-container` |
540
+ | On colour container | `--kui-color-on-positive-container` |
541
+
542
+ `negative` takes its four the same way. With the 49 from the script, that is
543
+ every colour role `tokens.css` lists.
544
+
545
+ ### Theming part of a page
546
+
547
+ The tokens resolve once, on `:root`, and every component inherits them already
548
+ resolved, so a `--kui-*` property redeclared on a smaller element — a wrapping
549
+ `<div>` — reaches nothing on its own. `ThemeScope` resolves them again on an
550
+ element of its own. An override declared on the scope, through `className` or
551
+ `style`, or on any element around it, reaches every component inside, and the
552
+ rest of the page keeps its own tokens:
553
+
554
+ ```css
555
+ .accent {
556
+ --kui-color-primary: #7d5260;
557
+ --kui-color-on-primary: #ffffff;
558
+ }
559
+ ```
560
+
561
+ ```tsx
562
+ import { Select, ThemeScope } from '@kanso-labs/kanso-ui'
563
+
564
+ function Section() {
565
+ return (
566
+ <ThemeScope className="accent">
567
+ <Select label="Label">…</Select>
568
+ </ThemeScope>
569
+ )
570
+ }
571
+ ```
572
+
573
+ `scheme` pins the scope to `'light'` or `'dark'`, whatever the OS asks for. Left
574
+ unset, the scope keeps the scheme around it, so a scope inside a dark page stays
575
+ dark.
576
+
577
+ Overlays come along. React Aria portals a popover, a sheet, a tooltip or a
578
+ snackbar to the end of `<body>`, outside any wrapper; one opened inside a
579
+ `ThemeScope` portals into the scope instead, and takes its tokens with it. The
580
+ cost is that an ancestor confining its descendants confines those overlays too —
581
+ a `transform` or a `filter` makes a sheet's scrim cover that ancestor rather
582
+ than the viewport, and `overflow: hidden` clips a popover — so put the scope
583
+ around such an element rather than inside it.
584
+
585
+ `themeScope` is the same thing as a class name, for an element you render
586
+ yourself. Overlays opened under it still portal to the body and keep the page's
587
+ tokens, since nothing tells them otherwise.
588
+
412
589
  ### Pinning light or dark
413
590
 
414
591
  The colours follow the reader's OS through `prefers-color-scheme` unless the app
415
592
  says otherwise. An app with a theme switch of its own pins a scheme with
416
- `colorScheme`, two class names: put `colorScheme.light` or `colorScheme.dark` on
417
- the `<html>` element, and remove both to follow the OS again. The `<html>`
418
- element is the place for it, since overlays are portalled to the body and still
419
- sit inside it.
593
+ `colorScheme`: put `colorScheme.light` or `colorScheme.dark` on the `<html>`
594
+ element, and remove it to follow the OS again. The `<html>` element is the place
595
+ for it, since overlays are portalled to the body and still sit inside it. Either
596
+ also works on a smaller element, as a `themeScope` that pins.
420
597
 
421
- Its shape is the one next-themes takes for class names, so a provider is all it
422
- needs:
598
+ Each is several class names separated by spaces, so set it through `className`,
599
+ or spread `name.split(' ')` into `classList.add`. A provider that adds one class
600
+ per scheme throws on it — next-themes' `value` option is one. With a provider of
601
+ that kind, render a `ThemeScope` around the app instead and hand it the
602
+ provider's scheme:
423
603
 
424
604
  ```tsx
425
- import { ThemeProvider } from 'next-themes'
426
- import { colorScheme } from '@kanso-labs/kanso-ui'
605
+ 'use client'
606
+
607
+ import { ThemeProvider, useTheme } from 'next-themes'
608
+ import { useEffect, useState } from 'react'
609
+ import { ThemeScope } from '@kanso-labs/kanso-ui'
610
+
611
+ function Scheme({ children }: { children: React.ReactNode }) {
612
+ const { resolvedTheme } = useTheme()
613
+ const [mounted, setMounted] = useState(false)
614
+ useEffect(() => setMounted(true), [])
615
+ const scheme =
616
+ mounted && (resolvedTheme === 'dark' || resolvedTheme === 'light')
617
+ ? resolvedTheme
618
+ : undefined
619
+
620
+ return <ThemeScope scheme={scheme}>{children}</ThemeScope>
621
+ }
427
622
 
428
623
  function Providers({ children }: { children: React.ReactNode }) {
429
624
  return (
430
- <ThemeProvider attribute="class" value={colorScheme}>
431
- {children}
625
+ <ThemeProvider attribute="data-theme">
626
+ <Scheme>{children}</Scheme>
432
627
  </ThemeProvider>
433
628
  )
434
629
  }
435
630
  ```
436
631
 
632
+ The server cannot know the stored choice, so the scope takes it only once the
633
+ page has mounted, which keeps the first client render matching the server's. The
634
+ first paint follows the OS until then.
635
+
437
636
  A `--kui-color-*` override on `:root` still applies under a pinned scheme. To
438
637
  give one scheme a value of its own, key the override on an attribute your switch
439
638
  sets beside the class, since the class names are generated.
440
639
 
441
640
  ### For StyleX consumers
442
641
 
443
- If your app also uses StyleX, theme with
444
- [`stylex.createTheme()`](https://stylexjs.com/docs/learn/theming/) instead — it
445
- produces a scoped override class rather than a global one. The token objects
446
- themselves (`colors`, `typography`, `spacing`, `radii`, `sizing`, `shadows`,
642
+ An app that also uses StyleX themes the same way, through the `--kui-*`
643
+ properties and `ThemeScope`. The token objects
644
+ [`stylex.createTheme()`](https://stylexjs.com/docs/learn/theming/) would take
645
+ (`colors`, `typography`, `spacing`, `radii`, `sizing`, `shadows`,
447
646
  `stateLayerOpacity` and `motion`) aren't part of the public API yet; open an
448
647
  issue if you need them exported.
449
648
 
@@ -1,6 +1,6 @@
1
+ import { refCallback } from "../render/ref.js";
1
2
  import { ariaAttributesOf } from "../render/aria.js";
2
3
  import { useRipple } from "../hooks/useRipple.js";
3
- import { refCallback } from "../render/ref.js";
4
4
  import { c } from "react/compiler-runtime";
5
5
  import { ButtonContext, useSlottedContext } from "react-aria-components";
6
6
  //#region src/button/hooks.ts
@@ -146,8 +146,8 @@ function buttonContent(children, pendingLabel, surface) {
146
146
  ...props(buttonBaseStyles.pending),
147
147
  children: /* @__PURE__ */ jsx(ProgressIndicator, {
148
148
  "aria-label": pendingLabel,
149
+ diameter: "1em",
149
150
  isIndeterminate: true,
150
- size: "1em",
151
151
  tone: "inherit",
152
152
  variant: "circular"
153
153
  })
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["DOMAttributes","ReactNode","RefAttributes","ButtonRenderProps","ClassNameOrFunction","ButtonProps","RACButtonProps","ToggleButtonProps","RACToggleButtonProps","StyleOrFunction","stylex","Button","RACButton","Link","RACLink","ToggleButton","RACToggleButton","ProgressIndicator","useToggleGroupDisabled","useMessages","buttonRenderer","linkRenderer","toggleButtonRenderer","mergeStatefulStyles","useButtonBase","buttonBaseStyles","ButtonBaseProps","children","classes","state","ButtonState","ReturnType","props","className","disableRipple","href","pendingLabel","rel","style","target","ButtonDOMProps","HTMLAnchorElement","HTMLButtonElement","Omit","GlobalEventKey","Pick","HTMLElement","isSelected","Exclude","ToggleButtonBaseProps","defaultSelected","onChange","ButtonBase","t0","$","_c","input","render","t1","isPending","undefined","messages","disabled","element","ref","ripple","t2","styleProps","t3","t4","handlers","surface","t5","loading","t6","buttonContent","t7","label","labelPending","pending","ToggleButtonBase","disabledByGroup","id","isDisabled","toggleRender","toggleContent","_c","RACLink","RACButton","stylex.props","RACToggleButton"],"sources":["../../src/button/index.tsx"],"sourcesContent":["import type { DOMAttributes, ReactNode, RefAttributes } from 'react';\nimport type { ButtonRenderProps, ClassNameOrFunction, ButtonProps as RACButtonProps, ToggleButtonProps as RACToggleButtonProps, StyleOrFunction } from 'react-aria-components';\nimport * as stylex from '@stylexjs/stylex';\nimport { Button as RACButton, Link as RACLink, ToggleButton as RACToggleButton } from 'react-aria-components';\nimport ProgressIndicator from '../components/progress-indicator';\nimport { useToggleGroupDisabled } from '../hooks/useToggleGroupDisabled';\nimport { useMessages } from '../i18n';\nimport { buttonRenderer, linkRenderer, toggleButtonRenderer } from '../render/aria';\nimport { mergeStatefulStyles } from '../styles/merge';\nimport { useButtonBase } from './hooks';\nimport { buttonBaseStyles } from './styles';\n\n// The press-button core Button and IconButton both render through. A button\n// is React Aria's `Button`, its `Link` once given `href`, or its\n// `ToggleButton` once it reports a state, and around each this adds what\n// React Aria leaves out: the ripple, the disabled state a parent's context\n// sets, the `aria-*` props and keyboard handlers it would drop or wrap, and\n// the ring drawn over the label while the button is pending. Each component\n// brings its own classes, as a function of the render state, and the call\n// site's `className` and `style` are merged over them.\n//\n// One module rather than a copy in each, since the copies had already drifted\n// once: IconButton read `ButtonContext` for a parent's disabled state and\n// Button did not. Not a component of the library's own and not exported from\n// the package; see `src/row` for the same arrangement around a list's row.\n\ntype ButtonBaseProps = {\n children?: ReactNode;\n /**\n * The component's own classes, from the render state. The call site's\n * `className` and `style` are merged over them.\n */\n classes: (state: ButtonState) => ReturnType<typeof stylex.props>;\n className?: ClassNameOrFunction<ButtonState>;\n disableRipple?: boolean;\n href?: string;\n pendingLabel?: string;\n rel?: string;\n style?: StyleOrFunction<ButtonState>;\n target?: string;\n} & ButtonDOMProps & RefAttributes<HTMLAnchorElement | HTMLButtonElement>;\n\n// The props a button hands React Aria. React Aria types the global DOM events\n// — pointer, mouse, touch, wheel and the rest — against the element each\n// component renders, and a handler written for a <button> does not type-check\n// against an <a>. The keys are retyped against HTMLElement here so one set of\n// props serves both forms; the events React Aria defines itself (press,\n// focus, keyboard) keep its types, since it hands those its own event objects.\ntype ButtonDOMProps = Omit<RACButtonProps, 'children' | 'className' | 'style' | GlobalEventKey> & Pick<DOMAttributes<HTMLElement>, GlobalEventKey>;\n\n// The render state React Aria's three elements share. A className or style\n// function written against it serves the button, the link and the toggle\n// alike; `isPending` belongs to the button alone, and `isCurrent` to the\n// link, so neither is here. What the button draws while pending is decided\n// in `buttonContent`, which sees React Aria's own state rather than this one.\n//\n// `isSelected` is optional because only the toggle has one: React Aria hands\n// the button and the link a state without it and the toggle a state with\n// it, and a parameter type this wide accepts either.\ntype ButtonState = Pick<ButtonRenderProps, 'isDisabled' | 'isFocused' | 'isFocusVisible' | 'isHovered' | 'isPressed'> & {\n isSelected?: boolean;\n};\ntype GlobalEventKey = Exclude<keyof DOMAttributes<HTMLElement> & keyof RACButtonProps, 'onBlur' | 'onClick' | 'onFocus'>;\ntype ToggleButtonBaseProps = {\n children?: ReactNode;\n /** As for ButtonBase, handed `isSelected` as well. */\n classes: (state: ButtonState) => ReturnType<typeof stylex.props>;\n className?: ClassNameOrFunction<ButtonState>;\n defaultSelected?: boolean;\n disableRipple?: boolean;\n isSelected?: boolean;\n onChange?: (isSelected: boolean) => void;\n style?: StyleOrFunction<ButtonState>;\n} & ButtonDOMProps & RefAttributes<HTMLAnchorElement | HTMLButtonElement>;\n\n/**\n * A button drawn with the classes a component hands it: React Aria's\n * `Button`, or its `Link` given `href`. See the header.\n */\nfunction ButtonBase({\n children,\n classes,\n href,\n isPending = false,\n pendingLabel,\n rel,\n render,\n target,\n ...input\n}: ButtonBaseProps) {\n const messages = useMessages();\n const {\n disabled,\n element,\n props,\n ref,\n ripple\n } = useButtonBase(input, isPending);\n const styleProps = mergeStatefulStyles(classes, props);\n if (href !== undefined) {\n return <RACLink href={href} isDisabled={disabled} ref={ref} rel={rel} render={linkRenderer(element)} target={target} {...ripple.handlers} {...props} {...styleProps}>\n {children}\n {ripple.surface}\n </RACLink>;\n }\n return <RACButton isDisabled={disabled} isPending={isPending} ref={ref} render={buttonRenderer(element, render)} {...ripple.handlers} {...props} {...styleProps}>\n {buttonContent(children, pendingLabel ?? messages.loading, ripple.surface)}\n </RACButton>;\n}\n\n// What the button draws: its label, hidden while the button is pending, with\n// the ring over it. The ring takes the button's own content colour rather\n// than the progress page's primary, which on a filled button is the fill\n// itself and so invisible. The label stays in the flow so the button keeps its\n// width, which is what stops a form jumping the moment it is submitted.\n// React Aria wants the progress bar in the accessibility tree as soon as the\n// button goes pending, so it is rendered from the render state rather than\n// after a delay.\n//\n// Built by a call rather than written inline at the prop, which is what\n// react-perf's no-new-function-as-prop is after; the React Compiler\n// memoises the result on its inputs.\nfunction buttonContent(children: ReactNode, pendingLabel: string, surface: ReactNode) {\n return (state: ButtonRenderProps) => <>\n <span {...stylex.props(buttonBaseStyles.label, state.isPending && buttonBaseStyles.labelPending)}>\n {children}\n </span>\n {state.isPending ? <span {...stylex.props(buttonBaseStyles.pending)}>\n <ProgressIndicator aria-label={pendingLabel} isIndeterminate size=\"1em\" tone=\"inherit\" variant=\"circular\" />\n </span> : null}\n {surface}\n </>;\n}\n\n/**\n * A toggle drawn with the classes a component hands it: React Aria's\n * `ToggleButton`, which reports its state through `aria-pressed`. It is never\n * a link and never pending — React Aria's toggle takes neither, and neither\n * means anything for a control whose whole job is to report which of two\n * states it is in — so `isPending` reaches it only to keep the ripple off,\n * as it does for the plain button.\n */\nfunction ToggleButtonBase({\n children,\n classes,\n defaultSelected,\n isPending = false,\n isSelected,\n onChange,\n render,\n ...input\n}: ToggleButtonBaseProps) {\n // A selecting ButtonGroup disables its toggles through React Aria's group\n // state, which no prop here carries, so the ripple would stay on in a\n // disabled group and answer a press with an animation. Handed on as the\n // toggle's own `isDisabled`, which is what React Aria makes of it anyway.\n const disabledByGroup = useToggleGroupDisabled(input.id);\n const {\n disabled,\n element,\n props,\n ref,\n ripple\n } = useButtonBase(disabledByGroup ? {\n ...input,\n isDisabled: true\n } : input, isPending);\n return <RACToggleButton defaultSelected={defaultSelected} isDisabled={disabled} isSelected={isSelected} onChange={onChange} ref={ref} render={toggleButtonRenderer(element, toggleRender(render))} {...ripple.handlers} {...props} {...mergeStatefulStyles(classes, props)}>\n {toggleContent(children, ripple.surface)}\n </RACToggleButton>;\n}\n\n// What a toggle draws: its label and the ripple. No pending ring — see\n// ToggleButtonBase. Built by a call for the reason `buttonContent` is.\nfunction toggleContent(children: ReactNode, surface: ReactNode) {\n return () => <>\n {children}\n {surface}\n </>;\n}\n\n// A call site's `render` is written for React Aria's button, whose render\n// state says whether it is pending; a toggle's says nothing of it, and a\n// toggle never is. So the toggle hands that function its own state with\n// `isPending` filled in, which is what lets one `render` prop serve a button\n// whichever element it turns out to be.\nfunction toggleRender(render: RACButtonProps['render']): RACToggleButtonProps['render'] {\n if (render === undefined) {\n return undefined;\n }\n return (props, state) => render(props, {\n ...state,\n isPending: false\n });\n}\nexport type { ButtonDOMProps, ButtonState };\nexport { ButtonBase, ToggleButtonBase };"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["DOMAttributes","ReactNode","RefAttributes","ButtonRenderProps","ClassNameOrFunction","ButtonProps","RACButtonProps","ToggleButtonProps","RACToggleButtonProps","StyleOrFunction","stylex","Button","RACButton","Link","RACLink","ToggleButton","RACToggleButton","ProgressIndicator","useToggleGroupDisabled","useMessages","buttonRenderer","linkRenderer","toggleButtonRenderer","mergeStatefulStyles","useButtonBase","buttonBaseStyles","ButtonBaseProps","children","classes","state","ButtonState","ReturnType","props","className","disableRipple","href","pendingLabel","rel","style","target","ButtonDOMProps","HTMLAnchorElement","HTMLButtonElement","Omit","GlobalEventKey","Pick","HTMLElement","isSelected","Exclude","ToggleButtonBaseProps","defaultSelected","onChange","ButtonBase","t0","$","_c","input","render","t1","isPending","undefined","messages","disabled","element","ref","ripple","t2","styleProps","t3","t4","handlers","surface","t5","loading","t6","buttonContent","t7","label","labelPending","pending","ToggleButtonBase","disabledByGroup","id","isDisabled","toggleRender","toggleContent","_c","RACLink","RACButton","stylex.props","RACToggleButton"],"sources":["../../src/button/index.tsx"],"sourcesContent":["import type { DOMAttributes, ReactNode, RefAttributes } from 'react';\nimport type { ButtonRenderProps, ClassNameOrFunction, ButtonProps as RACButtonProps, ToggleButtonProps as RACToggleButtonProps, StyleOrFunction } from 'react-aria-components';\nimport * as stylex from '@stylexjs/stylex';\nimport { Button as RACButton, Link as RACLink, ToggleButton as RACToggleButton } from 'react-aria-components';\nimport ProgressIndicator from '../components/progress-indicator';\nimport { useToggleGroupDisabled } from '../hooks/useToggleGroupDisabled';\nimport { useMessages } from '../i18n';\nimport { buttonRenderer, linkRenderer, toggleButtonRenderer } from '../render/aria';\nimport { mergeStatefulStyles } from '../styles/merge';\nimport { useButtonBase } from './hooks';\nimport { buttonBaseStyles } from './styles';\n\n// The press-button core Button and IconButton both render through. A button\n// is React Aria's `Button`, its `Link` once given `href`, or its\n// `ToggleButton` once it reports a state, and around each this adds what\n// React Aria leaves out: the ripple, the disabled state a parent's context\n// sets, the `aria-*` props and keyboard handlers it would drop or wrap, and\n// the ring drawn over the label while the button is pending. Each component\n// brings its own classes, as a function of the render state, and the call\n// site's `className` and `style` are merged over them.\n//\n// One module rather than a copy in each, since the copies had already drifted\n// once: IconButton read `ButtonContext` for a parent's disabled state and\n// Button did not. Not a component of the library's own and not exported from\n// the package; see `src/row` for the same arrangement around a list's row.\n\ntype ButtonBaseProps = {\n children?: ReactNode;\n /**\n * The component's own classes, from the render state. The call site's\n * `className` and `style` are merged over them.\n */\n classes: (state: ButtonState) => ReturnType<typeof stylex.props>;\n className?: ClassNameOrFunction<ButtonState>;\n disableRipple?: boolean;\n href?: string;\n pendingLabel?: string;\n rel?: string;\n style?: StyleOrFunction<ButtonState>;\n target?: string;\n} & ButtonDOMProps & RefAttributes<HTMLAnchorElement | HTMLButtonElement>;\n\n// The props a button hands React Aria. React Aria types the global DOM events\n// — pointer, mouse, touch, wheel and the rest — against the element each\n// component renders, and a handler written for a <button> does not type-check\n// against an <a>. The keys are retyped against HTMLElement here so one set of\n// props serves both forms; the events React Aria defines itself (press,\n// focus, keyboard) keep its types, since it hands those its own event objects.\ntype ButtonDOMProps = Omit<RACButtonProps, 'children' | 'className' | 'style' | GlobalEventKey> & Pick<DOMAttributes<HTMLElement>, GlobalEventKey>;\n\n// The render state React Aria's three elements share. A className or style\n// function written against it serves the button, the link and the toggle\n// alike; `isPending` belongs to the button alone, and `isCurrent` to the\n// link, so neither is here. What the button draws while pending is decided\n// in `buttonContent`, which sees React Aria's own state rather than this one.\n//\n// `isSelected` is optional because only the toggle has one: React Aria hands\n// the button and the link a state without it and the toggle a state with\n// it, and a parameter type this wide accepts either.\ntype ButtonState = Pick<ButtonRenderProps, 'isDisabled' | 'isFocused' | 'isFocusVisible' | 'isHovered' | 'isPressed'> & {\n isSelected?: boolean;\n};\ntype GlobalEventKey = Exclude<keyof DOMAttributes<HTMLElement> & keyof RACButtonProps, 'onBlur' | 'onClick' | 'onFocus'>;\ntype ToggleButtonBaseProps = {\n children?: ReactNode;\n /** As for ButtonBase, handed `isSelected` as well. */\n classes: (state: ButtonState) => ReturnType<typeof stylex.props>;\n className?: ClassNameOrFunction<ButtonState>;\n defaultSelected?: boolean;\n disableRipple?: boolean;\n isSelected?: boolean;\n onChange?: (isSelected: boolean) => void;\n style?: StyleOrFunction<ButtonState>;\n} & ButtonDOMProps & RefAttributes<HTMLAnchorElement | HTMLButtonElement>;\n\n/**\n * A button drawn with the classes a component hands it: React Aria's\n * `Button`, or its `Link` given `href`. See the header.\n */\nfunction ButtonBase({\n children,\n classes,\n href,\n isPending = false,\n pendingLabel,\n rel,\n render,\n target,\n ...input\n}: ButtonBaseProps) {\n const messages = useMessages();\n const {\n disabled,\n element,\n props,\n ref,\n ripple\n } = useButtonBase(input, isPending);\n const styleProps = mergeStatefulStyles(classes, props);\n if (href !== undefined) {\n return <RACLink href={href} isDisabled={disabled} ref={ref} rel={rel} render={linkRenderer(element)} target={target} {...ripple.handlers} {...props} {...styleProps}>\n {children}\n {ripple.surface}\n </RACLink>;\n }\n return <RACButton isDisabled={disabled} isPending={isPending} ref={ref} render={buttonRenderer(element, render)} {...ripple.handlers} {...props} {...styleProps}>\n {buttonContent(children, pendingLabel ?? messages.loading, ripple.surface)}\n </RACButton>;\n}\n\n// What the button draws: its label, hidden while the button is pending, with\n// the ring over it. The ring takes the button's own content colour rather\n// than the progress page's primary, which on a filled button is the fill\n// itself and so invisible. The label stays in the flow so the button keeps its\n// width, which is what stops a form jumping the moment it is submitted.\n// React Aria wants the progress bar in the accessibility tree as soon as the\n// button goes pending, so it is rendered from the render state rather than\n// after a delay.\n//\n// Built by a call rather than written inline at the prop, which is what\n// react-perf's no-new-function-as-prop is after; the React Compiler\n// memoises the result on its inputs.\nfunction buttonContent(children: ReactNode, pendingLabel: string, surface: ReactNode) {\n return (state: ButtonRenderProps) => <>\n <span {...stylex.props(buttonBaseStyles.label, state.isPending && buttonBaseStyles.labelPending)}>\n {children}\n </span>\n {state.isPending ? <span {...stylex.props(buttonBaseStyles.pending)}>\n <ProgressIndicator aria-label={pendingLabel} diameter=\"1em\" isIndeterminate tone=\"inherit\" variant=\"circular\" />\n </span> : null}\n {surface}\n </>;\n}\n\n/**\n * A toggle drawn with the classes a component hands it: React Aria's\n * `ToggleButton`, which reports its state through `aria-pressed`. It is never\n * a link and never pending — React Aria's toggle takes neither, and neither\n * means anything for a control whose whole job is to report which of two\n * states it is in — so `isPending` reaches it only to keep the ripple off,\n * as it does for the plain button.\n */\nfunction ToggleButtonBase({\n children,\n classes,\n defaultSelected,\n isPending = false,\n isSelected,\n onChange,\n render,\n ...input\n}: ToggleButtonBaseProps) {\n // A selecting ButtonGroup disables its toggles through React Aria's group\n // state, which no prop here carries, so the ripple would stay on in a\n // disabled group and answer a press with an animation. Handed on as the\n // toggle's own `isDisabled`, which is what React Aria makes of it anyway.\n const disabledByGroup = useToggleGroupDisabled(input.id);\n const {\n disabled,\n element,\n props,\n ref,\n ripple\n } = useButtonBase(disabledByGroup ? {\n ...input,\n isDisabled: true\n } : input, isPending);\n return <RACToggleButton defaultSelected={defaultSelected} isDisabled={disabled} isSelected={isSelected} onChange={onChange} ref={ref} render={toggleButtonRenderer(element, toggleRender(render))} {...ripple.handlers} {...props} {...mergeStatefulStyles(classes, props)}>\n {toggleContent(children, ripple.surface)}\n </RACToggleButton>;\n}\n\n// What a toggle draws: its label and the ripple. No pending ring — see\n// ToggleButtonBase. Built by a call for the reason `buttonContent` is.\nfunction toggleContent(children: ReactNode, surface: ReactNode) {\n return () => <>\n {children}\n {surface}\n </>;\n}\n\n// A call site's `render` is written for React Aria's button, whose render\n// state says whether it is pending; a toggle's says nothing of it, and a\n// toggle never is. So the toggle hands that function its own state with\n// `isPending` filled in, which is what lets one `render` prop serve a button\n// whichever element it turns out to be.\nfunction toggleRender(render: RACButtonProps['render']): RACToggleButtonProps['render'] {\n if (render === undefined) {\n return undefined;\n }\n return (props, state) => render(props, {\n ...state,\n isPending: false\n });\n}\nexport type { ButtonDOMProps, ButtonState };\nexport { ButtonBase, ToggleButtonBase };"],"mappings":"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"}
@@ -11,18 +11,18 @@ import { jsx } from "react/jsx-runtime";
11
11
  */
12
12
  function CollectionLoadMore(t0) {
13
13
  const $ = c(3);
14
- const { label, size } = t0;
14
+ const { diameter, label } = t0;
15
15
  const messages = useMessages();
16
16
  const t1 = label ?? messages.loadingMore;
17
17
  let t2;
18
- if ($[0] !== size || $[1] !== t1) {
18
+ if ($[0] !== diameter || $[1] !== t1) {
19
19
  t2 = /* @__PURE__ */ jsx(ProgressIndicator, {
20
20
  "aria-label": t1,
21
+ diameter,
21
22
  isIndeterminate: true,
22
- size,
23
23
  variant: "circular"
24
24
  });
25
- $[0] = size;
25
+ $[0] = diameter;
26
26
  $[1] = t1;
27
27
  $[2] = t2;
28
28
  } else t2 = $[2];
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["ProgressIndicator","useMessages","CollectionLoadMoreProps","label","size","CollectionLoadMore","t0","$","_c","messages","t1","loadingMore","t2","_c"],"sources":["../../src/collection/index.tsx"],"sourcesContent":["import ProgressIndicator from '../components/progress-indicator'\nimport { useMessages } from '../i18n'\n\ntype CollectionLoadMoreProps = {\n /**\n * What a screen reader announces while the next page is on its way. Left\n * out, it is the I18nProvider's locale's word for it.\n */\n label: string | undefined\n /** The ring's diameter, which follows the row it sits in. */\n size: string\n}\n\n/**\n * The ring a collection shows while it loads more items.\n *\n * Indeterminate and circular in every collection that has one, since none of\n * them knows how many items are still to come.\n */\nfunction CollectionLoadMore({ label, size }: CollectionLoadMoreProps) {\n const messages = useMessages()\n\n return (\n <ProgressIndicator\n aria-label={label ?? messages.loadingMore}\n isIndeterminate\n size={size}\n variant=\"circular\"\n />\n )\n}\n\nexport type { CollectionLoadMoreProps }\nexport { CollectionLoadMore }\n"],"mappings":";;;;;;;;;;;AAmBA,SAAAK,mBAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAA4B,MAAA,EAAAL,OAAAC,SAAAE;CAC1B,MAAAG,WAAiBR,YAAY;CAIb,MAAAS,KAAAP,SAASM,SAAQE;CAAY,IAAAC;CAAA,IAAAL,EAAA,OAAAH,QAAAG,EAAA,OAAAG,IAAA;EAD3CE,KAAA,oBAAC,mBAAD;GACc,cAAAF;GACZ,iBAAA;GACMN;GACE,SAAA;EAAU,CAAA;EAClBG,EAAA,KAAAH;EAAAG,EAAA,KAAAG;EAAAH,EAAA,KAAAK;CAAA,OAAAA,KAAAL,EAAA;CAAA,OALFK;AAKE"}
1
+ {"version":3,"file":"index.js","names":["ProgressIndicator","useMessages","CollectionLoadMoreProps","diameter","label","CollectionLoadMore","t0","$","_c","messages","t1","loadingMore","t2","_c"],"sources":["../../src/collection/index.tsx"],"sourcesContent":["import ProgressIndicator from '../components/progress-indicator'\nimport { useMessages } from '../i18n'\n\ntype CollectionLoadMoreProps = {\n /** The ring's diameter, which follows the row it sits in. */\n diameter: string\n /**\n * What a screen reader announces while the next page is on its way. Left\n * out, it is the I18nProvider's locale's word for it.\n */\n label: string | undefined\n}\n\n/**\n * The ring a collection shows while it loads more items.\n *\n * Indeterminate and circular in every collection that has one, since none of\n * them knows how many items are still to come.\n */\nfunction CollectionLoadMore({ diameter, label }: CollectionLoadMoreProps) {\n const messages = useMessages()\n\n return (\n <ProgressIndicator\n aria-label={label ?? messages.loadingMore}\n diameter={diameter}\n isIndeterminate\n variant=\"circular\"\n />\n )\n}\n\nexport type { CollectionLoadMoreProps }\nexport { CollectionLoadMore }\n"],"mappings":";;;;;;;;;;;AAmBA,SAAAK,mBAAAC,IAAA;CAAA,MAAAC,IAAAC,EAAA,CAAA;CAA4B,MAAA,EAAAL,UAAAC,UAAAE;CAC1B,MAAAG,WAAiBR,YAAY;CAIb,MAAAS,KAAAN,SAASK,SAAQE;CAAY,IAAAC;CAAA,IAAAL,EAAA,OAAAJ,YAAAI,EAAA,OAAAG,IAAA;EAD3CE,KAAA,oBAAC,mBAAD;GACc,cAAAF;GACFP;GACV,iBAAA;GACQ,SAAA;EAAU,CAAA;EAClBI,EAAA,KAAAJ;EAAAI,EAAA,KAAAG;EAAAH,EAAA,KAAAK;CAAA,OAAAA,KAAAL,EAAA;CAAA,OALFK;AAKE"}
@@ -1,21 +1,28 @@
1
1
  //#region src/color-scheme.d.ts
2
+ /**
3
+ * The class that lets an element theme what is inside it. A `--kui-*`
4
+ * override declared on that element, or on one around it, reaches every
5
+ * component rendered inside, where on any element but `<html>` it would
6
+ * otherwise reach none — the tokens resolve on `:root` and are inherited from
7
+ * there already resolved. The scheme is inherited from around it, so a scope
8
+ * inside a dark page stays dark.
9
+ *
10
+ * Overlays are portalled to the body, outside the element, so they keep the
11
+ * page's tokens; `ThemeScope` is the same class with a portal container of
12
+ * its own, which takes them along.
13
+ */
14
+ declare const themeScope: string;
2
15
  /**
3
16
  * The classes that pin the library's colours to its light or its dark
4
17
  * scheme, whatever the reader's OS asks for — for an app with a theme switch
5
18
  * of its own. Put one on the `<html>` element, where overlays portalled to
6
19
  * the body still sit inside it; with neither there, the colours follow the
7
- * OS as they always have.
8
- *
9
- * Shaped as next-themes takes its class names:
10
- *
11
- * ```tsx
12
- * import { ThemeProvider } from 'next-themes'
13
- * import { colorScheme } from '@kanso-labs/kanso-ui'
20
+ * OS as they always have. Each is also a {@link themeScope}, so either on a
21
+ * smaller element pins and scopes the subtree under it.
14
22
  *
15
- * <ThemeProvider attribute="class" value={colorScheme}>
16
- * {children}
17
- * </ThemeProvider>
18
- * ```
23
+ * Shaped as an object of class names, one per scheme. Each name is several
24
+ * classes separated by spaces, so add them with `className` rather than
25
+ * `classList.add`, which takes one class per argument.
19
26
  *
20
27
  * A `--kui-color-*` override still applies under either, declared on the
21
28
  * same element or above it.
@@ -25,5 +32,5 @@ declare const colorScheme: {
25
32
  light: string;
26
33
  };
27
34
  //#endregion
28
- export { colorScheme };
35
+ export { colorScheme, themeScope };
29
36
  //# sourceMappingURL=color-scheme.d.ts.map
@@ -1,32 +1,39 @@
1
1
  import { props } from "./node_modules/@stylexjs/stylex/lib/es/stylex.js";
2
- import { colorsDarkTheme, colorsLightTheme } from "./tokens/design.tokens.stylex.js";
2
+ import { colorDefaultsDarkTheme, colorDefaultsLightTheme, tokenScope } from "./tokens/design.tokens.stylex.js";
3
3
  //#region src/color-scheme.ts
4
4
  /**
5
+ * The class that lets an element theme what is inside it. A `--kui-*`
6
+ * override declared on that element, or on one around it, reaches every
7
+ * component rendered inside, where on any element but `<html>` it would
8
+ * otherwise reach none — the tokens resolve on `:root` and are inherited from
9
+ * there already resolved. The scheme is inherited from around it, so a scope
10
+ * inside a dark page stays dark.
11
+ *
12
+ * Overlays are portalled to the body, outside the element, so they keep the
13
+ * page's tokens; `ThemeScope` is the same class with a portal container of
14
+ * its own, which takes them along.
15
+ */
16
+ const themeScope = props(tokenScope).className ?? "";
17
+ /**
5
18
  * The classes that pin the library's colours to its light or its dark
6
19
  * scheme, whatever the reader's OS asks for — for an app with a theme switch
7
20
  * of its own. Put one on the `<html>` element, where overlays portalled to
8
21
  * the body still sit inside it; with neither there, the colours follow the
9
- * OS as they always have.
10
- *
11
- * Shaped as next-themes takes its class names:
12
- *
13
- * ```tsx
14
- * import { ThemeProvider } from 'next-themes'
15
- * import { colorScheme } from '@kanso-labs/kanso-ui'
22
+ * OS as they always have. Each is also a {@link themeScope}, so either on a
23
+ * smaller element pins and scopes the subtree under it.
16
24
  *
17
- * <ThemeProvider attribute="class" value={colorScheme}>
18
- * {children}
19
- * </ThemeProvider>
20
- * ```
25
+ * Shaped as an object of class names, one per scheme. Each name is several
26
+ * classes separated by spaces, so add them with `className` rather than
27
+ * `classList.add`, which takes one class per argument.
21
28
  *
22
29
  * A `--kui-color-*` override still applies under either, declared on the
23
30
  * same element or above it.
24
31
  */
25
32
  const colorScheme = {
26
- dark: props(colorsDarkTheme).className ?? "",
27
- light: props(colorsLightTheme).className ?? ""
33
+ dark: props(tokenScope, colorDefaultsDarkTheme).className ?? "",
34
+ light: props(tokenScope, colorDefaultsLightTheme).className ?? ""
28
35
  };
29
36
  //#endregion
30
- export { colorScheme };
37
+ export { colorScheme, themeScope };
31
38
 
32
39
  //# sourceMappingURL=color-scheme.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"color-scheme.js","names":["stylex","colorsDarkTheme","colorsLightTheme","colorScheme","dark","props","className","light","stylex.props"],"sources":["../src/color-scheme.ts"],"sourcesContent":["import * as stylex from '@stylexjs/stylex';\nimport { colorsDarkTheme, colorsLightTheme } from './tokens/design.tokens.stylex';\n\n// The library's colours follow the reader's OS through `prefers-color-scheme`\n// unless something says otherwise, and these are what say otherwise. Both\n// classes have always been generated and shipped in the stylesheet, for\n// Storybook's Theme control; nothing in the package named them, so an app\n// with a switch of its own had to restate every colour token under its own\n// selector, twice — dark for a light OS, light for a dark one.\n//\n// A server module like the entry, since it is two strings.\n\n/**\n * The classes that pin the library's colours to its light or its dark\n * scheme, whatever the reader's OS asks for — for an app with a theme switch\n * of its own. Put one on the `<html>` element, where overlays portalled to\n * the body still sit inside it; with neither there, the colours follow the\n * OS as they always have.\n *\n * Shaped as next-themes takes its class names:\n *\n * ```tsx\n * import { ThemeProvider } from 'next-themes'\n * import { colorScheme } from '@kanso-labs/kanso-ui'\n *\n * <ThemeProvider attribute=\"class\" value={colorScheme}>\n * {children}\n * </ThemeProvider>\n * ```\n *\n * A `--kui-color-*` override still applies under either, declared on the\n * same element or above it.\n */\nconst colorScheme = {\n dark: stylex.props(colorsDarkTheme).className ?? '',\n light: stylex.props(colorsLightTheme).className ?? ''\n};\nexport { colorScheme };"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAiCA,MAAMG,cAAc;CAClBC,MAAMJ,MAAaC,eAAe,CAAC,CAACK,aAAa;CACjDC,OAAOP,MAAaE,gBAAgB,CAAC,CAACI,aAAa;AACrD"}
1
+ {"version":3,"file":"color-scheme.js","names":["stylex","colorDefaultsDarkTheme","colorDefaultsLightTheme","tokenScope","themeScope","props","className","colorScheme","dark","light","stylex.props"],"sources":["../src/color-scheme.ts"],"sourcesContent":["import * as stylex from '@stylexjs/stylex';\nimport { colorDefaultsDarkTheme, colorDefaultsLightTheme, tokenScope } from './tokens/design.tokens.stylex';\n\n// The library's tokens resolve once, on `:root`, and follow the reader's OS\n// through `prefers-color-scheme` unless something says otherwise. These are\n// the classes that say otherwise, for a page that cannot or would rather not\n// render `ThemeScope`: `themeScope` resolves every token again on the element\n// it lands on, and each `colorScheme` class does that and pins the scheme\n// too. All three were generated for Storybook first, where the Theme control\n// uses the scheme pair; nothing in the package named them, so an app with a\n// switch of its own had to restate every colour token under its own\n// selector, twice — dark for a light OS, light for a dark one.\n//\n// A server module like the entry, since it is three strings.\n\n/**\n * The class that lets an element theme what is inside it. A `--kui-*`\n * override declared on that element, or on one around it, reaches every\n * component rendered inside, where on any element but `<html>` it would\n * otherwise reach none — the tokens resolve on `:root` and are inherited from\n * there already resolved. The scheme is inherited from around it, so a scope\n * inside a dark page stays dark.\n *\n * Overlays are portalled to the body, outside the element, so they keep the\n * page's tokens; `ThemeScope` is the same class with a portal container of\n * its own, which takes them along.\n */\nconst themeScope = stylex.props(tokenScope).className ?? '';\n\n/**\n * The classes that pin the library's colours to its light or its dark\n * scheme, whatever the reader's OS asks for — for an app with a theme switch\n * of its own. Put one on the `<html>` element, where overlays portalled to\n * the body still sit inside it; with neither there, the colours follow the\n * OS as they always have. Each is also a {@link themeScope}, so either on a\n * smaller element pins and scopes the subtree under it.\n *\n * Shaped as an object of class names, one per scheme. Each name is several\n * classes separated by spaces, so add them with `className` rather than\n * `classList.add`, which takes one class per argument.\n *\n * A `--kui-color-*` override still applies under either, declared on the\n * same element or above it.\n */\nconst colorScheme = {\n dark: stylex.props(tokenScope, colorDefaultsDarkTheme).className ?? '',\n light: stylex.props(tokenScope, colorDefaultsLightTheme).className ?? ''\n};\nexport { colorScheme, themeScope };"],"mappings":";;;;;;;;;;;;;;;AA2BA,MAAMI,aAAaJ,MAAaG,UAAU,CAAC,CAACG,aAAa;;;;;;;;;;;;;;;;AAiBzD,MAAMC,cAAc;CAClBC,MAAMR,MAAaG,YAAYF,sBAAsB,CAAC,CAACK,aAAa;CACpEG,OAAOT,MAAaG,YAAYD,uBAAuB,CAAC,CAACI,aAAa;AACxE"}