@nxgt/material 3.76.0 → 3.78.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +3 -3
  3. package/dist/{calculator-BaSMe0SK.js → calculator-DSSaYRmM.js} +2 -2
  4. package/dist/calculator-field.js +2 -2
  5. package/dist/calculator.js +1 -1
  6. package/dist/components/ui/display/chip/chip-hairline.css +19 -0
  7. package/dist/components/ui/display/chip/chip-soft.css +18 -0
  8. package/dist/{components-Ci3Zo8kC.js → components-j6sIvxhs.js} +15819 -15727
  9. package/dist/components.js +34 -34
  10. package/dist/{currency-field-BJ9rSrif.js → currency-field-DWHB5oms.js} +3 -2
  11. package/dist/editor.js +1 -1
  12. package/dist/{financial-variant-BsZEa5sF.js → financial-variant-vZdgyMeN.js} +3 -3
  13. package/dist/lib/components/ui/actions/back-link/back-link.d.ts +12 -3
  14. package/dist/lib/components/ui/collections/row-menu/use-row-menu-focus.d.ts +11 -1
  15. package/dist/lib/components/ui/collections/server-table/partials/server-table-grid-sorting.d.ts +6 -0
  16. package/dist/lib/components/ui/collections/server-table/partials/server-table-passed-through.d.ts +1 -0
  17. package/dist/lib/components/ui/collections/server-table/partials/server-table-phone-row.d.ts +1 -1
  18. package/dist/lib/components/ui/collections/server-table/types.d.ts +1 -1
  19. package/dist/lib/components/ui/display/entity-header/partials/entity-header-actions.d.ts +3 -1
  20. package/dist/lib/components/ui/display/entity-header/partials/entity-header-layout.d.ts +10 -0
  21. package/dist/lib/components/ui/feedback/state-frame/scene-registry.d.ts +24 -4
  22. package/dist/lib/components/ui/fields/quantity-field/quantity-row.d.ts +4 -3
  23. package/dist/lib/components/ui/layout/app-shell/page-title.d.ts +4 -3
  24. package/dist/lib/components/ui/layout/hero/hero-backdrop.d.ts +7 -0
  25. package/dist/lib/components/ui/layout/hero/hero-parts.d.ts +27 -0
  26. package/dist/lib/components/ui/layout/hero/hero.d.ts +26 -1
  27. package/dist/lib/components/ui/primitives/tabs/tabs-manual-scroll.d.ts +16 -0
  28. package/dist/lib/components/ui/primitives/tabs/use-tabs-overflow.d.ts +1 -1
  29. package/dist/lib/illustrations/index.d.ts +1 -1
  30. package/dist/main.js +49 -49
  31. package/dist/material.css +1 -1
  32. package/dist/{percent-field-lahyDJDG.js → percent-field--WIXV5dX.js} +1 -1
  33. package/dist/{tabs-DzEqMb1W.js → tabs-BT9pSRwk.js} +128 -97
  34. package/dist/{use-chat-composer-DMXu9E1O.js → use-chat-composer-BOx4I6Ma.js} +1 -1
  35. package/docs/components/buttons-and-actions.md +9 -1
  36. package/docs/components/data-display.md +2 -1
  37. package/docs/components/data-table-filter-and-lists.md +16 -3
  38. package/docs/components/form-fields.md +6 -3
  39. package/docs/components/navigation-and-layout.md +29 -1
  40. package/docs/components/selection-and-choice.md +3 -1
  41. package/docs/guides/app-shell.md +6 -4
  42. package/docs/guides/illustrations.md +34 -1
  43. package/docs/guides/theming.md +5 -5
  44. package/docs/troubleshooting.md +3 -2
  45. package/lib/components/ui/display/chip/chip-hairline.css +19 -0
  46. package/lib/components/ui/display/chip/chip-soft.css +18 -0
  47. package/lib/themes/ambre.css +1 -1
  48. package/lib/themes/ardoise.css +1 -1
  49. package/lib/themes/bleumono.css +1 -1
  50. package/lib/themes/bluemoon.css +1 -1
  51. package/lib/themes/corail.css +2 -2
  52. package/lib/themes/foret.css +1 -1
  53. package/lib/themes/lavande.css +1 -1
  54. package/lib/themes/menthe.css +1 -1
  55. package/lib/themes/ocean.css +1 -1
  56. package/lib/themes/pink.css +2 -2
  57. package/lib/themes/prune.css +1 -1
  58. package/lib/themes/sable.css +1 -1
  59. package/lib/themes/slate.css +1 -1
  60. package/lib/themes/teal.css +3 -3
  61. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # @nxgt/material
2
2
 
3
+ ## 3.78.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#2381](https://github.com/softistx/nxgt-material/pull/2381) [`e1b6dbe`](https://github.com/softistx/nxgt-material/commit/e1b6dbe608e7fe41796c0bc26c08ec2ef0ce883e) Thanks [@SteveGT96](https://github.com/SteveGT96)! - `BackLink` takes `collapse="phone"`: below 768px it shows only its arrow, the label staying its accessible name and, when it is a string, its tooltip (as `ResponsiveLinkButton` does), with `variant` and `aria-label` kept. Unset, the label always shows, as before. Fixes [#2375](https://github.com/softistx/nxgt-material/issues/2375).
8
+
9
+ - [#2385](https://github.com/softistx/nxgt-material/pull/2385) [`2b2ad61`](https://github.com/softistx/nxgt-material/commit/2b2ad6145dcfe8074677f8c29d832f482fa1abab) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Scenes registered through `IllustrationDefaults` `sets` are now typed. `@nxgt/material/illustrations` exports an empty `RegisteredScenes` interface to augment (`declare module '@nxgt/material/illustrations' { interface RegisteredScenes extends SceneTableIds<typeof MY_SCENES> {} }`) and the helper type `SceneTableIds<T extends SceneTable>`; the keys widen `SceneId` (and `RegisteredScene`), so `<Illustration scene="my-scene" />`, a state's `illustration` and `emptyIllustration` accept them beside the built-in ids, without a cast. The `scenes={T}` overload is unchanged. Nothing to adapt: an app that does not augment keeps today's types, and a `scene={id as SceneId}` cast can go. Fixes [#2384](https://github.com/softistx/nxgt-material/issues/2384).
10
+
11
+ ### Patch Changes
12
+
13
+ - [#2387](https://github.com/softistx/nxgt-material/pull/2387) [`17e479e`](https://github.com/softistx/nxgt-material/commit/17e479e30265dc30eedd29a46f0866262164760a) Thanks [@SteveGT96](https://github.com/SteveGT96)! - `ServerTable` now takes `focusRef`, as `DataTable` does, and fills it with the table (or the list of cards or tiles) it renders, beside its own ref. `useRowMenuFocus()`'s `focusRef` given to a `ServerTable` scopes `focusRowMenu(id)` to that table, so two tables on a page may share a row id. Nothing to adapt: pass `focusRef={focusRef}` and drop the wrapper element used as a workaround. Fixes [#2086](https://github.com/softistx/nxgt-material/issues/2086).
14
+
15
+ ## 3.77.0
16
+
17
+ ### Minor Changes
18
+
19
+ - [#2336](https://github.com/softistx/nxgt-material/pull/2336) [`bdfa59d`](https://github.com/softistx/nxgt-material/commit/bdfa59d3566b2bc65c09214b735c2a1febb1c645) Thanks [@SteveGT96](https://github.com/SteveGT96)! - `Hero` gains `background` (the props of the `Background` of `@nxgt/material/backgrounds`: `preset`, `intensity`, `tone`, `fill`…, drawn `aria-hidden` behind the content, clipped by the band's radius, loaded on demand, replacing the built-in gradient and glows), `size="compact"` (a greeting band for a home page: `rounded-xl`, a Card's content padding, the title in `headline-lg` emphasized, a muted description, actions at the end from `lg` and wrapping below, buttons at least 44px tall) and `headingLevel` (1 to 6, default 1). `aria-label` now passes through to the section. The new type `HeroBackgroundProps` is exported from `@nxgt/material/components`. The default Hero renders as before. Fixes [#2335](https://github.com/softistx/nxgt-material/issues/2335).
20
+
21
+ - [#2378](https://github.com/softistx/nxgt-material/pull/2378) [`034fe52`](https://github.com/softistx/nxgt-material/commit/034fe5294cebca878c3bcb53fe19753f29214ec3) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Add `rowFocusProps(rowId)`, to spread on a plain row button (an edit pen opening a dialog) so `useRowMenuFocus().focusRowMenu(rowId)` hands the focus back to it like a `RowMenu` trigger, with no local map of button refs ([#2377](https://github.com/softistx/nxgt-material/issues/2377)).
22
+
23
+ ### Patch Changes
24
+
25
+ - [#2351](https://github.com/softistx/nxgt-material/pull/2351) [`4eebac0`](https://github.com/softistx/nxgt-material/commit/4eebac0fe3574ce52acf9bdef722137c3df3c47b) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Fix the app bar's page title on a phone: a long title (a record's number such as `Prescription P00000001`) now wraps to a second line before it is cut with an ellipsis, so the identifier stays readable by touch, where the `title` tooltip cannot be reached. From `md` up it is unchanged (one line, ellipsis); the full-text `title` is still set whenever the text is cut off. Fixes [#2324](https://github.com/softistx/nxgt-material/issues/2324).
26
+
27
+ - [#2374](https://github.com/softistx/nxgt-material/pull/2374) [`fef1413`](https://github.com/softistx/nxgt-material/commit/fef14130acaf94aa69a65ed4343504fd3b64870c) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Fix `ChangeHistory` on a phone: a long unbroken value (a URL, a reference) is no longer clipped inside the rail's value pill or the old value, and a long unbroken field name now wraps in both the rail and the cards instead of widening the page at 360px. Spaced text already wrapped. Fixes [#2358](https://github.com/softistx/nxgt-material/issues/2358).
28
+
29
+ - [#2370](https://github.com/softistx/nxgt-material/pull/2370) [`fcdeacc`](https://github.com/softistx/nxgt-material/commit/fcdeacc3332119aa0860d986e55edceb24095227) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Fix the unselected chips of a `ChipGroupField` (and any neutral toggle `Chip`, `aria-checked` or `aria-pressed`) having no visible container in dark mode: the tonal fill alone was about 1.2:1 over the card. An unselected toggle chip now draws a boundary of 50 % of `--foreground` over the page (64 % on hover), at least 3:1 against the page and the card in light and dark on the 14 presets, teal included (WCAG 1.4.11). Selected chips, plain and coloured chips are unchanged. Fixes [#2357](https://github.com/softistx/nxgt-material/issues/2357).
30
+
31
+ - [#2347](https://github.com/softistx/nxgt-material/pull/2347) [`875ce11`](https://github.com/softistx/nxgt-material/commit/875ce1161e95e41594cf27b50958cbed0d831494) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Fix `CurrencyField` and `CurrencyFormField` drawing the currency code in an opaque 32 px box off the field's fill, with the code at its top: the code now sits on the field's own surface and is centred on the amount's line, in light and dark and on touch screens ([#2343](https://github.com/softistx/nxgt-material/issues/2343)).
32
+
33
+ - [#2353](https://github.com/softistx/nxgt-material/pull/2353) [`5d876d4`](https://github.com/softistx/nxgt-material/commit/5d876d4e27218dd0281cee04f33572c3026bb6fe) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Paint the EntityHeader band with the Card surface (`bg-card`) instead of the page ground (`bg-background`). In dark an EntityHeader beside a Card was near-black while the Card was a lighter surface; both now sit on the same elevation, in every preset. Fixes [#2323](https://github.com/softistx/nxgt-material/issues/2323).
34
+
35
+ - [#2367](https://github.com/softistx/nxgt-material/pull/2367) [`7615ecc`](https://github.com/softistx/nxgt-material/commit/7615ecc5c8c54c3188742d1a4108ed39852dfbd5) Thanks [@SteveGT96](https://github.com/SteveGT96)! - `EntityHeader`: a lone icon-only action (`expanded: false`) stays beside the title at narrow widths instead of taking its own row ([#2360](https://github.com/softistx/nxgt-material/issues/2360)).
36
+
37
+ - [#2338](https://github.com/softistx/nxgt-material/pull/2338) [`ddcfa2c`](https://github.com/softistx/nxgt-material/commit/ddcfa2cf9e4166f9e86e9bb574ec02f5c5942bfb) Thanks [@SteveGT96](https://github.com/SteveGT96)! - fix(quantity-field): keep the number input a 44px tap target at 375px; the unit part shrinks before the number does ([#2327](https://github.com/softistx/nxgt-material/issues/2327)).
38
+
39
+ - [#2364](https://github.com/softistx/nxgt-material/pull/2364) [`45bb1dd`](https://github.com/softistx/nxgt-material/commit/45bb1dd8fc939f3d57971054020de4622baeee96) Thanks [@SteveGT96](https://github.com/SteveGT96)! - A `ServerTable` on a phone without `actions` now puts the labelled "Select all" in the second row (with the sort and "Filters"), as it does with `actions`, instead of a blank full-width band holding a bare checkbox. Fixes [#2363](https://github.com/softistx/nxgt-material/issues/2363).
40
+
41
+ - [#2373](https://github.com/softistx/nxgt-material/pull/2373) [`cc97b1a`](https://github.com/softistx/nxgt-material/commit/cc97b1a91e4137a109e641d73a93dd9012c09172) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Docs and a code comment only: the theming guides now describe `--primary-text` (light) and the dark `--error-text` as solved shares per theme (teal 94 %, corail 89 %, pink 94 %; dark error 71 % on teal), not the fixed 96 % and 76 %. No behaviour change.
42
+
43
+ - [#2334](https://github.com/softistx/nxgt-material/pull/2334) [`599fab6`](https://github.com/softistx/nxgt-material/commit/599fab6f0b743b7b06e09fc420c5c52911bec201) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Fix `TabsNav` (and `Tabs`) leaving the active tab half under a scroll chevron after the tabs or the list changed size (a web font, a count, a rotation): the active tab is now kept revealed, clear of the chevrons, until the person scrolls the list themselves ([#2328](https://github.com/softistx/nxgt-material/issues/2328)).
44
+
45
+ - [#2362](https://github.com/softistx/nxgt-material/pull/2362) [`3bc6091`](https://github.com/softistx/nxgt-material/commit/3bc6091b15e0fa644907720b4b220ba43a09eaae) Thanks [@SteveGT96](https://github.com/SteveGT96)! - The dark `--error-text` is solved against the dark `--background` and `--card`: its share of the error colour drops below 76 % when a lighter card (the teal preset's) would leave it under 5.3:1, so a field's error message and an inline alert keep 4.5:1 in axe on that card. Other presets are unchanged. Fixes [#2332](https://github.com/softistx/nxgt-material/issues/2332).
46
+
47
+ - [#2366](https://github.com/softistx/nxgt-material/pull/2366) [`2ae3bba`](https://github.com/softistx/nxgt-material/commit/2ae3bbacf31cce96639579468d4edd2d2f66c943) Thanks [@SteveGT96](https://github.com/SteveGT96)! - fix(theme): `primary-text` (light) darkens when a tinted page would leave a tonal Button label under 4.5:1 on a striped table row; Teal's label is now AA there. `CONTRAST_PAIRS` gains `primary-text` on `primary@row15` ([#2322](https://github.com/softistx/nxgt-material/issues/2322)).
48
+ - Updated dependencies [[`cc97b1a`](https://github.com/softistx/nxgt-material/commit/cc97b1a91e4137a109e641d73a93dd9012c09172), [`3bc6091`](https://github.com/softistx/nxgt-material/commit/3bc6091b15e0fa644907720b4b220ba43a09eaae), [`2ae3bba`](https://github.com/softistx/nxgt-material/commit/2ae3bbacf31cce96639579468d4edd2d2f66c943)]:
49
+ - @nxgt/material-core@0.49.1
50
+
3
51
  ## 3.76.0
4
52
 
5
53
  ### Minor Changes
package/README.md CHANGED
@@ -207,7 +207,7 @@ reads `duotone.svg`, the file that exists (it used to ask for the missing
207
207
  | `@nxgt/material/map` | Leaflet maps, markers, a location field — **its own entry, not in the barrel, and browser-only** ([maps guide](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/guides/maps.md)) |
208
208
  | `@nxgt/material/themes` | `NxgtThemeProvider` (the registry, the persisted theme name, `<html data-nxgt-theme>`, `defaultMode`; renders no element; `useTheme({ defaultMode })` takes the first-visit mode too), `NxgtTheme` (a zone in another theme, `mode`, `asChild`), `useThemeContext`, `defineTheme` (a bad background `motif` key or value is dropped and warned about in development, 4.0: an error; core's own `defineTheme` warns only through `{ warn }`), `ThemeDefinitionError`, `themeBootScript` and `THEME_BOOT_SCRIPT` (with `ThemeBootOptions`), the 14 presets and `THEME_PRESETS`, `ThemeName` and `NxgtThemes` (augmentable), with the `NxgtThemeProps`, `NxgtThemeProviderProps`, `ThemeContextValue`, `Theme`, `ThemeDefinition` and `ThemeBackground` types ([guide](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/guides/theming.md#the-provider-and-zones)). `Background` and `ActivityLayout` take their background from the nearest theme |
209
209
  | `@nxgt/material/theme-picker` | `ThemePicker`, the theme and mode chooser (swatches and a mini background per theme; `themes`, `value`, `onValueChange`, `showMode`, `showBackground`, `layout`) and `ThemePickerProps`; its own entry so `/themes` stays small ([guide](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/guides/theming.md#let-users-choose)) |
210
- | `@nxgt/material/illustrations` | State illustrations: `Illustration` (`scene`: `empty`, `no-results`, `not-found`, `error`, `offline`, `success`, `welcome`, `forbidden`, `maintenance`, `invitation`, `sign-in`, `empty-inbox`, or an id of the `scenes` table it is given; `size`, `title`, `animated`, `hero`, `satellites`, `iconStyle`, `tone`, `duotone`) draws a hero icon on a Material 3 Expressive plate with satellites, from the Font Awesome sprites your app serves (no icon artwork ships); `IllustrationDefaults` (`icons`: `'suggested'` or a table, `iconStyle`, `sets`) opts a subtree's `EmptyState` and `ErrorState` into them; `ILLUSTRATION_SCENES`, `SUGGESTED_ICONS` and the types re-exported from `@nxgt/material-core/illustrations` (`SceneRow`, `SceneTable`), plus `IconStyleInput` and `IconStyleRef` (the `iconStyle` types: `{ family?, type? }` or one of the 37 sprite file names), `SceneId`, `RegisteredScene` and `IllustrationSceneRegistry`, the scene id type that an imported set's ids widen. `unauthorized` and `maintenance` states draw the `forbidden` and `maintenance` scenes. `EmptyState`, `ErrorState` and the `DataTable` empty row (`emptyIllustration`) also take `illustration` as a scene id or `true`. Colours are theme tones in `styles.css`; its own entry ([illustrations guide](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/guides/illustrations.md)) |
210
+ | `@nxgt/material/illustrations` | State illustrations: `Illustration` (`scene`: `empty`, `no-results`, `not-found`, `error`, `offline`, `success`, `welcome`, `forbidden`, `maintenance`, `invitation`, `sign-in`, `empty-inbox`, or an id of the `scenes` table it is given; `size`, `title`, `animated`, `hero`, `satellites`, `iconStyle`, `tone`, `duotone`) draws a hero icon on a Material 3 Expressive plate with satellites, from the Font Awesome sprites your app serves (no icon artwork ships); `IllustrationDefaults` (`icons`: `'suggested'` or a table, `iconStyle`, `sets`) opts a subtree's `EmptyState` and `ErrorState` into them; `ILLUSTRATION_SCENES`, `SUGGESTED_ICONS` and the types re-exported from `@nxgt/material-core/illustrations` (`SceneRow`, `SceneTable`), plus `IconStyleInput` and `IconStyleRef` (the `iconStyle` types: `{ family?, type? }` or one of the 37 sprite file names), `SceneId` and `RegisteredScene` (the scene id types: the built-in ids plus those registered through `IllustrationSceneRegistry` by an imported set, or through `RegisteredScenes` by you), `RegisteredScenes` (an interface to augment with the ids of a table of your own registered through `sets`) and `SceneTableIds` (the helper type that gives a table's ids: `interface RegisteredScenes extends SceneTableIds<typeof MY_SCENES> {}`). `unauthorized` and `maintenance` states draw the `forbidden` and `maintenance` scenes. `EmptyState`, `ErrorState` and the `DataTable` empty row (`emptyIllustration`) also take `illustration` as a scene id or `true`. Colours are theme tones in `styles.css`; its own entry ([illustrations guide](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/guides/illustrations.md)) |
211
211
  | `@nxgt/material/illustrations/health` | The health scenes: `HEALTH_SCENES` (`patient-record`, `consultation`, `appointment`, `lab-sample`, `prescription`, `vaccination`, `hospitalisation`, `emergency`, `no-patients`, `lab-results`), `HEALTH_SCENE_IDS`, `HEALTH_SUGGESTED_ICONS`, `HealthScene`; register it with `<IllustrationDefaults sets={[HEALTH_SCENES]}>` so `<Illustration scene="patient-record" />` and `<EmptyState illustration="no-patients" />` work (or pass `scenes={HEALTH_SCENES}` to one `Illustration`); importing it adds the ids to `SceneId`. An app that does not import it does not carry it |
212
212
  | `@nxgt/material/illustrations/education` | The education scenes: `EDUCATION_SCENES` (`classroom`, `homework`, `exam-grades`, `timetable`, `attendance`, `enrolment`, `library`, `graduation`, `no-students`, `report-card`), `EDUCATION_SCENE_IDS`, `EDUCATION_SUGGESTED_ICONS`, `EducationScene`; register it with `<IllustrationDefaults sets={[EDUCATION_SCENES]}>` so `<Illustration scene="classroom" />` and `<EmptyState illustration="no-students" />` work (or pass `scenes={EDUCATION_SCENES}` to one `Illustration`); importing it adds the ids to `SceneId`. An app that does not import it does not carry it |
213
213
  | `@nxgt/material/illustrations/game` | The game scenes, for a game, quiz, community or event app: `GAME_SCENES` (`night-sky`, `dawn`, `village`, `day-village`, `graveyard`, `seer`, `healer`, `archer`, `cupid`, `wolf`, `villager`, `witch`, `victory`, `empty-table`, `waiting-players`, `connection-lost`), `GAME_SCENE_IDS`, `GAME_SUGGESTED_ICONS`, `GameScene`; register it with `<IllustrationDefaults sets={[GAME_SCENES]}>` so `<Illustration scene="village" />` and `<EmptyState illustration="empty-table" />` work (or pass `scenes={GAME_SCENES}` to one `Illustration`); importing it adds the ids to `SceneId`. Pass `title` for an accessible name, otherwise the picture is decorative (`aria-hidden`). An app that does not import it does not carry it |
@@ -715,7 +715,7 @@ Not components: what the stylesheet gives any element.
715
715
  | --- | --- | --- | --- |
716
716
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/previews/data-table-filter-lists-datatable.webp" width="120" alt="DataTable"> | [`DataTable`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/data-table-filter-and-lists.md#datatable), `DataTableColumnHeader`, `DataTablePagination`, `DataTableServerFooter`, `DataTableViewOptions` | TanStack Table v9 with sorting, filtering, selection, expandable rows, pagination or load-more, column visibility, skeleton rows while loading and your own empty state — or one server page at a time, with controlled sorting and selection, cursor Previous / Next links and row links. On a phone it keeps its header row and scrolls sideways in a keyboard-reachable region; the page does not. Or cards and tiles instead of the table (`layout`, `renderCard`, `renderTile`), and `layout={{ phone: 'tiles', wide: 'table' }}` for tiles on a phone ([cards and tiles guide](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/guides/cards-and-tiles.md)). Long lists render only the rows in view (`virtual`). | `DataTable`, `DataTableColumnHeader`, `DataTablePagination`, `DataTableServerFooter`, `DataTableViewOptions` |
717
717
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/previews/data-table-filter-lists-servertable.webp" width="120" alt="ServerTable"> | [`ServerTable`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/data-table-filter-and-lists.md#servertable), `createSorting`, `tableFilters`, `defineFilterModel`, `parseFilterQuery`, `serializeFilterQuery`, `paramsFromQuery`, `serverPagination`… | A server-mode `DataTable` driven by the URL's search params, for any router: the Filter in its top band with the page's title (optional), description and actions, the sort, forward cursor paging, a selection reset on a new query, the empty page (a scene and an action for "nothing yet", the filters as removable chips), a compact band (`bandDensity`), icon-only Previous / Next (`pageControls`, 44px targets on a touch screen, focus kept while a page loads), actions that stay on the search's row on a phone (`bandActions`), `surface="none"` to sit in a Card with no frame of its own, a bulk bar that reserves no row until a selection, bulk actions with `appliesTo` that count and run only the selected rows they apply to (hidden at zero), an accessible `name`, a `max` rows with a notice, and `focusTrigger()` to give the focus back after a dialog, a `filterRef` to focus the Filter, a page past the last (rows deleted) that says so and links back to the first, an error state with Retry for a failed fetch (`error`, `onRetry`), and one count announced. | `ServerTable`, `createSorting`, `tableFilters`, `serverPagination` |
718
- | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/previews/data-table-filter-lists-rowmenu.webp" width="120" alt="RowMenu"> | [`RowMenu`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/data-table-filter-and-lists.md#rowmenu), `RowMenuTrigger`, `rowMenuColumn` | A row's "..." button named after its row ("Actions for Ada"; 44px on touch, 36px with a mouse from `md`), its menu aligned to the end with the destructive item last and 44px items on touch, and a column helper for `DataTable` and `ServerTable` under a hidden but named "Actions" header; focus returns to the button, also from a dialog an item opened; `useRowMenuFocus()` / `focusRowMenu(rowId)` hands it back to one row's button after an async action, a toast or a later dialog. | — |
718
+ | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/previews/data-table-filter-lists-rowmenu.webp" width="120" alt="RowMenu"> | [`RowMenu`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/data-table-filter-and-lists.md#rowmenu), `RowMenuTrigger`, `rowMenuColumn` | A row's "..." button named after its row ("Actions for Ada"; 44px on touch, 36px with a mouse from `md`), its menu aligned to the end with the destructive item last and 44px items on touch, and a column helper for `DataTable` and `ServerTable` under a hidden but named "Actions" header; focus returns to the button, also from a dialog an item opened; `useRowMenuFocus()` / `focusRowMenu(rowId)` hands it back to one row's button after an async action, a toast or a later dialog, and `rowFocusProps(rowId)` marks a plain row button the same way. | — |
719
719
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/previews/data-table-filter-lists-recordactionsmenu.webp" width="120" alt="RecordActionsMenu"> | [`RecordActionsMenu`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/data-table-filter-and-lists.md#recordactionsmenu), `useRecordActions` | A record's archive, restore and delete menu over `RowMenu`: Archive runs at once with an Undo toast that stays until dismissed, Restore runs at once, Delete permanently (archived records only) always asks and keeps a refusal in its locked dialog; `can` hides what is not allowed (and the whole menu when nothing is), `send` does the action, `onDone` follows it, `items` / `children` add your own entries, `messages` renames the words; `archivePolicy="confirm"` asks before archiving (no Undo), `consequence` notes what an action entails, `successAction` adds a toast action, and `ActionRefusal` / `isActionRefusal` carry a refusal's details and action. | — |
720
720
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/previews/data-table-filter-lists-listempty.webp" width="120" alt="ListEmpty"> | [`ListEmpty`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/data-table-filter-and-lists.md#listempty) | A list's empty page: nothing yet (a title, or a scene, a line and an action), or nothing matches with what narrows it and a way out (a button or a link); its title is an `h2` (`headingLevel`). | `ListEmpty` |
721
721
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/previews/data-table-filter-lists-pagefooter.webp" width="120" alt="PageFooter"> | [`PageFooter`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/data-table-filter-and-lists.md#pagefooter) | The page footer of a feed that is not a table (a list of cards, a news feed) under a `FilterBar`: the range ("21–40 of 134") and Previous / Next as real links built from the URL's cursor trail (`pageInfo`, `totalCount`, `params`; `totalCount` is optional: a feed with no total shows no range, only Previous / Next; `hideOnSinglePage` renders nothing when there is no previous and no next page), the same footer `ServerTable` draws, icon-only with `pageControls="icon"` (44px targets on a touch screen); an end with no page is a disabled button, `aria-disabled`. | `PageFooter` |
@@ -751,7 +751,7 @@ Not components: what the stylesheet gives any element.
751
751
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/previews/navigation-layout-toc.webp" width="120" alt="Toc"> | [`Toc`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/navigation-and-layout.md#toc) | On-this-page outline with a per-item active bar. Rail from `xl`, collapsible panel below. `DocToc` composes it. | `Toc` |
752
752
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/previews/navigation-layout-stepper.webp" width="120" alt="Stepper"> | [`Stepper`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/navigation-and-layout.md#stepper), `StepperIndicator` | Clickable horizontal or vertical steps with status and progress (expressive shapes, optional steps, a phone header with Back and Next). | `Stepper` |
753
753
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/previews/navigation-layout-steps.webp" width="120" alt="Steps"> | [`Steps`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/navigation-and-layout.md#steps), `StepsItem` | Numbered editorial steps that stay visible on every breakpoint. | `Steps`, `StepsItem` |
754
- | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/previews/navigation-layout-hero.webp" width="120" alt="Hero"> | [`Hero`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/navigation-and-layout.md#hero) | Landing band with eyebrow, title, supporting copy and actions. | `Hero` |
754
+ | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/previews/navigation-layout-hero.webp" width="120" alt="Hero"> | [`Hero`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/navigation-and-layout.md#hero) | Landing band with eyebrow, title, supporting copy and actions; `size="compact"` is a home-page greeting band, and `background` draws a `Background` behind it. | `Hero`, `HeroBackgroundProps` |
755
755
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/previews/navigation-layout-doc.webp" width="120" alt="Doc"> | [`Doc`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/navigation-and-layout.md#doc), `DocPage`, `DocTopbar`, `DocSidebar`, `DocToc`, `DocPager`, `DocSearch`, `DocChildCards`, `DocSeeAlso`, `DocEmpty`, `DocProgress` | Documentation site shell: sidebar from `md`, TOC rail from `xl`. Reading bar, copy-page / markdown, child cards, see also, and a 404 slot. Storybook `UI/Doc/Api` composes an API page from `DocPage`, `AnchorHeading`, `ApiOperation`, `ParamTable` and `CodeGroup`. | `Doc` (same parts) |
756
756
  | <img src="https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/previews/navigation-layout-background.webp" width="120" alt="Background"> | [`Background`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/navigation-and-layout.md#background) | Full-viewport gradient with blurred colour blobs; centres its children; 52 presets on `/backgrounds`, and a `sky` overlay. | `Background` |
757
757
  | — | [`NavigationRail`](https://cdn.jsdelivr.net/npm/@nxgt/material@3/docs/components/navigation-and-layout.md#navigationrail) | Placeholder: renders an empty rail container and takes no props yet. | `NavigationRail` |
@@ -1,5 +1,5 @@
1
1
  import { t as e } from "./utils-BLfntITJ.js";
2
- import { n as t, r as n, t as r, u as i } from "./tabs-DzEqMb1W.js";
2
+ import { n as t, r as n, t as r, u as i } from "./tabs-BT9pSRwk.js";
3
3
  import { t as a } from "./button-3op3rtZh.js";
4
4
  import { t as o } from "./use-material-translation-CD6QoVal.js";
5
5
  import { t as s } from "./icon-button-Cogxy1cy.js";
@@ -282,7 +282,7 @@ var Re = {
282
282
  scientific: () => import("./scientific-variant-2y3UxAAU.js"),
283
283
  pos: () => import("./pos-variant-GrUfbTTP.js"),
284
284
  programmer: () => import("./programmer-variant-eKJNKENL.js"),
285
- financial: () => import("./financial-variant-BsZEa5sF.js"),
285
+ financial: () => import("./financial-variant-vZdgyMeN.js"),
286
286
  conversion: () => import("./conversion-variant-BDFAxqe9.js")
287
287
  }, B = "failed", V = /* @__PURE__ */ new Map(), H = /* @__PURE__ */ new Map(), U = /* @__PURE__ */ new Set(), W = () => {
288
288
  for (let e of U) e();
@@ -3,9 +3,9 @@ import { t } from "./button-3op3rtZh.js";
3
3
  import { t as n } from "./use-material-translation-CD6QoVal.js";
4
4
  import { t as r } from "./icon-button-Cogxy1cy.js";
5
5
  import { a as i, i as a, n as o, r as s, t as c } from "./picker-surface-CV09H7Nb.js";
6
- import { r as l, t as u } from "./currency-field-BJ9rSrif.js";
6
+ import { r as l, t as u } from "./currency-field-DWHB5oms.js";
7
7
  import { r as d, t as f } from "./field-blur-DkiZOVNV.js";
8
- import { t as p } from "./calculator-BaSMe0SK.js";
8
+ import { t as p } from "./calculator-DSSaYRmM.js";
9
9
  import { useId as m, useState as h } from "react";
10
10
  import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
11
11
  import { Calculator as y } from "lucide-react";
@@ -1,2 +1,2 @@
1
- import { n as e, t } from "./calculator-BaSMe0SK.js";
1
+ import { n as e, t } from "./calculator-DSSaYRmM.js";
2
2
  export { e as CALCULATOR_VARIANTS, t as Calculator };
@@ -72,6 +72,25 @@
72
72
  }
73
73
  }
74
74
 
75
+ /* A toggle chip (`aria-checked` or `aria-pressed`: a choice of a
76
+ * ChipGroupField, a filter) is a control, and its boundary is what shows
77
+ * where it is: 3:1 against the page and the card (WCAG 1.4.11), in light and
78
+ * dark, on every preset (#2357). The soft look draws it too (chip-soft.css
79
+ * reads --chip-line). The share is checked in chip-line-contrast.test.ts. A
80
+ * plain or a coloured chip keeps its quiet look. */
81
+ @layer components {
82
+ .nxgt-chip[data-tone="neutral"]:is([aria-checked], [aria-pressed]),
83
+ :is(.dark, [data-theme="dark"])
84
+ .nxgt-chip[data-tone="neutral"]:is([aria-checked], [aria-pressed]) {
85
+ --chip-line: color-mix(in oklab, var(--foreground) 50%, var(--background));
86
+ --chip-line-hover: color-mix(
87
+ in oklab,
88
+ var(--foreground) 64%,
89
+ var(--background)
90
+ );
91
+ }
92
+ }
93
+
75
94
  /* A coloured chip: the hairline takes the tone, the face a breath of it,
76
95
  * hover included (through the variables the hover rule reads). */
77
96
  @layer components {
@@ -65,6 +65,24 @@
65
65
  }
66
66
  }
67
67
 
68
+ /* A toggle chip left unselected keeps a boundary (--chip-line, set in
69
+ * chip-hairline.css): the fill alone is under 3:1 (#2357). Selected has its
70
+ * ring and its check. */
71
+ @layer components {
72
+ .nxgt-chip[data-look="soft"][data-tone="neutral"]:is(
73
+ [aria-checked="false"],
74
+ [aria-pressed="false"]
75
+ ) {
76
+ border-color: var(--chip-line);
77
+ }
78
+ .nxgt-chip[data-look="soft"][data-tone="neutral"]:is(
79
+ [aria-checked="false"],
80
+ [aria-pressed="false"]
81
+ ):is(button:hover):not(:disabled, [data-disabled]) {
82
+ border-color: var(--chip-line-hover);
83
+ }
84
+ }
85
+
68
86
  /* A coloured chip (`color` other than default) is a status: the tone
69
87
  * (in dark the base of the tone's container, --nxgt-tone-container-base: the
70
88
  * tone held at a container's lightness) at