@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.
- package/README.md +234 -35
- package/dist/button/hooks.js +1 -1
- package/dist/button/index.js +1 -1
- package/dist/button/index.js.map +1 -1
- package/dist/collection/index.js +4 -4
- package/dist/collection/index.js.map +1 -1
- package/dist/color-scheme.d.ts +19 -12
- package/dist/color-scheme.js +22 -15
- package/dist/color-scheme.js.map +1 -1
- package/dist/components/app-bar/index.d.ts +10 -14
- package/dist/components/app-bar/index.js +12 -12
- package/dist/components/app-bar/index.js.map +1 -1
- package/dist/components/avatar/index.d.ts +15 -1
- package/dist/components/avatar/index.js +43 -145
- package/dist/components/avatar/index.js.map +1 -1
- package/dist/components/breadcrumbs/index.d.ts +1 -1
- package/dist/components/breadcrumbs/index.js.map +1 -1
- package/dist/components/button/index.js +3 -3
- package/dist/components/button/index.js.map +1 -1
- package/dist/components/calendar/index.js.map +1 -1
- package/dist/components/card/index.js.map +1 -1
- package/dist/components/chip/index.js +27 -25
- package/dist/components/chip/index.js.map +1 -1
- package/dist/components/chip-group/index.d.ts +22 -1
- package/dist/components/chip-group/index.js +3 -3
- package/dist/components/chip-group/index.js.map +1 -1
- package/dist/components/code/index.js +1 -1
- package/dist/components/code/index.js.map +1 -1
- package/dist/components/color-picker/index.d.ts +5 -5
- package/dist/components/color-picker/index.js +46 -51
- package/dist/components/color-picker/index.js.map +1 -1
- package/dist/components/color-swatch-picker/index.d.ts +1 -1
- package/dist/components/color-swatch-picker/index.js.map +1 -1
- package/dist/components/combo-box/index.d.ts +5 -5
- package/dist/components/combo-box/index.js +33 -35
- package/dist/components/combo-box/index.js.map +1 -1
- package/dist/components/copy-field/index.js +1 -1
- package/dist/components/copy-field/index.js.map +1 -1
- package/dist/components/currency/index.d.ts +16 -0
- package/dist/components/currency/index.js +16 -0
- package/dist/components/currency/index.js.map +1 -1
- package/dist/components/date-field/index.js.map +1 -1
- package/dist/components/date-picker/index.d.ts +5 -5
- package/dist/components/date-picker/index.js +35 -40
- package/dist/components/date-picker/index.js.map +1 -1
- package/dist/components/date-range-picker/index.d.ts +5 -5
- package/dist/components/date-range-picker/index.js +35 -40
- package/dist/components/date-range-picker/index.js.map +1 -1
- package/dist/components/dialog/index.d.ts +15 -12
- package/dist/components/dialog/index.js +151 -97
- package/dist/components/dialog/index.js.map +1 -1
- package/dist/components/disclosure/index.d.ts +1 -1
- package/dist/components/disclosure/index.js.map +1 -1
- package/dist/components/fab-menu/index.d.ts +4 -2
- package/dist/components/fab-menu/index.js.map +1 -1
- package/dist/components/index.d.ts +4 -2
- package/dist/components/list/index.d.ts +3 -3
- package/dist/components/list/index.js +2 -2
- package/dist/components/list/index.js.map +1 -1
- package/dist/components/list-box/index.d.ts +3 -3
- package/dist/components/list-box/index.js +2 -2
- package/dist/components/list-box/index.js.map +1 -1
- package/dist/components/list-item/index.js +1 -1
- package/dist/components/loading-indicator/index.d.ts +30 -0
- package/dist/components/loading-indicator/index.js +71 -0
- package/dist/components/loading-indicator/index.js.map +1 -0
- package/dist/components/menu/index.d.ts +8 -8
- package/dist/components/menu/index.js +2 -2
- package/dist/components/menu/index.js.map +1 -1
- package/dist/components/navigation-tree/index.d.ts +2 -2
- package/dist/components/navigation-tree/index.js.map +1 -1
- package/dist/components/popover/index.d.ts +7 -7
- package/dist/components/popover/index.js.map +1 -1
- package/dist/components/product-icon/index.d.ts +1 -1
- package/dist/components/product-icon/index.js +28 -142
- package/dist/components/product-icon/index.js.map +1 -1
- package/dist/components/progress-indicator/index.d.ts +21 -15
- package/dist/components/progress-indicator/index.js +485 -185
- package/dist/components/progress-indicator/index.js.map +1 -1
- package/dist/components/range-calendar/index.js.map +1 -1
- package/dist/components/search-view/index.d.ts +5 -5
- package/dist/components/search-view/index.js.map +1 -1
- package/dist/components/segmented-button/index.d.ts +1 -1
- package/dist/components/segmented-button/index.js.map +1 -1
- package/dist/components/select/index.d.ts +5 -5
- package/dist/components/select/index.js +5 -2
- package/dist/components/select/index.js.map +1 -1
- package/dist/components/sheet/index.d.ts +10 -10
- package/dist/components/sheet/index.js +27 -20
- package/dist/components/sheet/index.js.map +1 -1
- package/dist/components/slider/index.js +1 -1
- package/dist/components/slider/index.js.map +1 -1
- package/dist/components/split-button/index.d.ts +4 -2
- package/dist/components/split-button/index.js.map +1 -1
- package/dist/components/stack/index.d.ts +4 -1
- package/dist/components/stack/index.js +7 -1
- package/dist/components/stack/index.js.map +1 -1
- package/dist/components/table/index.d.ts +7 -7
- package/dist/components/table/index.js +39 -26
- package/dist/components/table/index.js.map +1 -1
- package/dist/components/tabs/index.d.ts +4 -4
- package/dist/components/tabs/index.js +59 -27
- package/dist/components/tabs/index.js.map +1 -1
- package/dist/components/text/index.d.ts +22 -9
- package/dist/components/text/index.js +22 -5
- package/dist/components/text/index.js.map +1 -1
- package/dist/components/time-picker/index.d.ts +110 -0
- package/dist/components/time-picker/index.js +954 -0
- package/dist/components/time-picker/index.js.map +1 -0
- package/dist/components/tooltip/index.d.ts +5 -5
- package/dist/components/tooltip/index.js +1 -0
- package/dist/components/tooltip/index.js.map +1 -1
- package/dist/components/tree/index.d.ts +2 -2
- package/dist/components/tree/index.js +2 -2
- package/dist/components/tree/index.js.map +1 -1
- package/dist/glyphs/index.js +37 -1
- package/dist/glyphs/index.js.map +1 -1
- package/dist/i18n/index.js +4 -0
- package/dist/i18n/index.js.map +1 -1
- package/dist/i18n/messages.js +136 -0
- package/dist/i18n/messages.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.js +5 -2
- package/dist/indicator/index.js +38 -35
- package/dist/indicator/index.js.map +1 -1
- package/dist/mark/index.js +137 -0
- package/dist/mark/index.js.map +1 -0
- package/dist/mark/initials.js +42 -0
- package/dist/mark/initials.js.map +1 -0
- package/dist/mark/styles.js +91 -0
- package/dist/mark/styles.js.map +1 -0
- package/dist/render/ref.js +35 -1
- package/dist/render/ref.js.map +1 -1
- package/dist/render/useRender.js +1 -30
- package/dist/render/useRender.js.map +1 -1
- package/dist/styles/picker.js +29 -1
- package/dist/styles/picker.js.map +1 -1
- package/dist/styles.css +685 -231
- package/dist/theme-scope.d.ts +40 -0
- package/dist/theme-scope.js +112 -0
- package/dist/theme-scope.js.map +1 -0
- package/dist/tokens/design.tokens.stylex.js +39 -5
- package/dist/tokens/design.tokens.stylex.js.map +1 -1
- 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
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
44
|
-
|
|
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="
|
|
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
|
|
303
|
-
|
|
|
304
|
-
| `Button`'s `icon`
|
|
305
|
-
| `Chip`'s and `ChipGroup.Chip`'s `icon`
|
|
306
|
-
| `
|
|
307
|
-
|
|
|
308
|
-
| `
|
|
309
|
-
| `
|
|
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
|
|
371
|
-
|
|
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
|
|
399
|
-
|
|
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
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
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
|
-
|
|
422
|
-
|
|
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
|
-
|
|
426
|
-
|
|
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="
|
|
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
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
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
|
|
package/dist/button/hooks.js
CHANGED
|
@@ -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
|
package/dist/button/index.js
CHANGED
|
@@ -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
|
})
|
package/dist/button/index.js.map
CHANGED
|
@@ -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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"}
|
package/dist/collection/index.js
CHANGED
|
@@ -11,18 +11,18 @@ import { jsx } from "react/jsx-runtime";
|
|
|
11
11
|
*/
|
|
12
12
|
function CollectionLoadMore(t0) {
|
|
13
13
|
const $ = c(3);
|
|
14
|
-
const {
|
|
14
|
+
const { diameter, label } = t0;
|
|
15
15
|
const messages = useMessages();
|
|
16
16
|
const t1 = label ?? messages.loadingMore;
|
|
17
17
|
let t2;
|
|
18
|
-
if ($[0] !==
|
|
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] =
|
|
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","
|
|
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"}
|
package/dist/color-scheme.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
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
|
package/dist/color-scheme.js
CHANGED
|
@@ -1,32 +1,39 @@
|
|
|
1
1
|
import { props } from "./node_modules/@stylexjs/stylex/lib/es/stylex.js";
|
|
2
|
-
import {
|
|
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
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
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(
|
|
27
|
-
light: props(
|
|
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
|
package/dist/color-scheme.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color-scheme.js","names":["stylex","
|
|
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"}
|