@nxgt/material 2.12.0 → 2.14.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.
- package/CHANGELOG.md +79 -0
- package/README.md +19 -6
- package/dist/{_Uint8Array-azThpjEP.js → _Uint8Array-QCcRMhXd.js} +1 -1
- package/dist/{_overRest-DMn4Dt71.js → _overRest-C21ZmKyH.js} +1 -1
- package/dist/{async-slice-DhZDjEtw.js → async-slice-TBZ6Taw2.js} +2 -2
- package/dist/{blockDiagram-BEXU5L5S-CnFXw-7E.js → blockDiagram-BEXU5L5S-Cn9cG3vt.js} +2 -2
- package/dist/{chunk-3FUC2YCW-3vMiTgTl.js → chunk-3FUC2YCW-XrT5pZo5.js} +2 -2
- package/dist/{chunk-7M6MHVWA-NPaJJ6Gy.js → chunk-7M6MHVWA-Uf-8NCRF.js} +1 -1
- package/dist/{chunk-GNY47TPC-DCFqYc_z.js → chunk-GNY47TPC-CGgBmY0O.js} +4 -4
- package/dist/{chunk-NETBCI7D-BB4rjLSQ.js → chunk-NETBCI7D-g-jPsM9q.js} +1 -1
- package/dist/{chunk-Z7XXMR3K-vmLFt9Cr.js → chunk-Z7XXMR3K-BzO1efzA.js} +1 -1
- package/dist/{classDiagram-v2-NBCMYWYE-eUVWeh_6.js → classDiagram-v2-NBCMYWYE-7WgpfVcn.js} +2 -2
- package/dist/components/components.css +13 -2
- package/dist/components/ui/feedback/spinner/spinner.css +28 -0
- package/dist/components/ui/fields/otp-field/input-otp.css +48 -0
- package/dist/components/ui/media/pdf-viewer/pdf-viewer.css +24 -0
- package/dist/components/ui/overlays/drawer/vaul-drawer.css +199 -0
- package/dist/components/ui/overlays/drawer/vaul-keyframes.css +95 -0
- package/dist/{components-BYxsGbyO.js → components-qTUjhFuo.js} +116423 -127245
- package/dist/components.js +6 -6
- package/dist/{dagre-6A5THRUB-LmEtEC93.js → dagre-6A5THRUB-BOuRxJdA.js} +11 -11
- package/dist/{diagram-22UHCM2B-BwARaM-x.js → diagram-22UHCM2B-CF0vLJbn.js} +2 -2
- package/dist/{diagram-3UASUU5V-BkeqK_e8.js → diagram-3UASUU5V-RLo-MTfV.js} +1 -1
- package/dist/dnd.js +1 -1
- package/dist/{elk-276RUBZZ-DL4pxCSP.js → elk-276RUBZZ-Dr2yBM7k.js} +3 -3
- package/dist/{erDiagram-OPXOYQCR-Ajlj2lcb.js → erDiagram-OPXOYQCR-l7kPZ4FO.js} +2 -2
- package/dist/{field-blur-DgfIJceK.js → field-blur-BKGVq9_k.js} +865 -870
- package/dist/{flowDiagram-KWPJA3E3-BOEc9KSn.js → flowDiagram-KWPJA3E3-BQEK3XTl.js} +3 -3
- package/dist/fonts/katex/KaTeX_AMS-Regular.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Caligraphic-Bold.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Caligraphic-Regular.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Fraktur-Bold.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Fraktur-Regular.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Main-Bold.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Main-BoldItalic.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Main-Italic.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Main-Regular.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Math-BoldItalic.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Math-Italic.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_SansSerif-Bold.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_SansSerif-Italic.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_SansSerif-Regular.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Script-Regular.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Size1-Regular.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Size2-Regular.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Size3-Regular.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Size4-Regular.woff2 +0 -0
- package/dist/fonts/katex/KaTeX_Typewriter-Regular.woff2 +0 -0
- package/dist/{ganttDiagram-FUAMR5RP-DdxLcLNx.js → ganttDiagram-FUAMR5RP-WYm8XV7U.js} +1 -1
- package/dist/{graphlib-DLjE3QPd.js → graphlib-CbcZi5bx.js} +6 -6
- package/dist/hooks.js +26 -26
- package/dist/{i18n-provider-CQL7fqLy.js → i18n-provider-D5hkauu6.js} +1 -1
- package/dist/i18n.js +6 -6
- package/dist/{isArrayLikeObject-CO-5KAzG.js → isArrayLikeObject-COiPdhFP.js} +3 -3
- package/dist/{isEmpty-Bl1drJE7.js → isEmpty-B7UlCLih.js} +3 -3
- package/dist/{journeyDiagram-ZHPQQLJL-BIzB9BVn.js → journeyDiagram-ZHPQQLJL-p90NnenY.js} +1 -1
- package/dist/lib/components/ui/fields/attributes/attribute-form/consts.d.ts +5 -1
- package/dist/lib/components/ui/fields/attributes/attribute-form/types.d.ts +2 -2
- package/dist/lib/components/ui/fields/opening-hours/consts.d.ts +12 -1
- package/dist/lib/components/ui/fields/search-field/index.d.ts +2 -2
- package/dist/lib/components/ui/media/image-cropper/image-crop-aspects.d.ts +6 -0
- package/dist/lib/components/ui/media/image-cropper/use-frame-size.d.ts +4 -0
- package/dist/lib/components/ui/primitives/index.d.ts +1 -0
- package/dist/lib/components/ui/primitives/nonce-provider/index.d.ts +1 -0
- package/dist/lib/components/ui/primitives/nonce-provider/nonce-provider.d.ts +20 -0
- package/dist/lib/components/ui/selection/autocomplete/autocomplete.d.ts +2 -34
- package/dist/lib/components/ui/selection/autocomplete/partials/autocomplete-announcer.d.ts +10 -0
- package/dist/lib/components/ui/selection/autocomplete/partials/autocomplete-chips.d.ts +8 -3
- package/dist/lib/components/ui/selection/autocomplete/partials/autocomplete-list-status.d.ts +13 -0
- package/dist/lib/components/ui/selection/autocomplete/partials/autocomplete-popup.d.ts +26 -0
- package/dist/lib/components/ui/selection/autocomplete/types.d.ts +72 -0
- package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-filter.d.ts +13 -0
- package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-handlers.d.ts +17 -0
- package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-search.d.ts +8 -0
- package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-status.d.ts +28 -0
- package/dist/lib/components/ui/selection/autocomplete/use-autocomplete-values.d.ts +27 -0
- package/dist/lib/components/ui/selection/autocomplete/use-autocomplete.d.ts +29 -0
- package/dist/lib/components/ui/selection/radio-group/radio-group.d.ts +7 -4
- package/dist/lib/components/ui/widgets/rich-text-editor/extensions/extensions.d.ts +2 -2
- package/dist/lib/components/ui/widgets/rich-text-editor/use-rich-text-editor.d.ts +17 -0
- package/dist/lib/hooks/index.d.ts +1 -0
- package/dist/lib/hooks/use-csp-nonce.d.ts +16 -0
- package/dist/lib/i18n/resources/en/en.d.ts +4 -0
- package/dist/lib/i18n/resources/en/material.json.d.ts +5 -1
- package/dist/lib/i18n/resources/fr/fr.d.ts +4 -0
- package/dist/lib/i18n/resources/fr/material.json.d.ts +5 -1
- package/dist/lib/i18n/resources/resources.d.ts +8 -0
- package/dist/lib/i18n/translator.d.ts +1 -1
- package/dist/lib/lib/index.d.ts +1 -0
- package/dist/lib/vite/index.d.ts +3 -2
- package/dist/lib.js +32 -31
- package/dist/main.js +16 -16
- package/dist/map.js +2 -2
- package/dist/material.css +25 -1
- package/dist/{merge-CwwtONfp.js → merge-KEf_u3Zy.js} +4 -4
- package/dist/{mermaid.core-6yWyNdZa.js → mermaid.core-CW8DO1T1.js} +21 -21
- package/dist/{mindmap-definition-NLK3R4M7-aHycauO9.js → mindmap-definition-NLK3R4M7-DJcCg9PL.js} +2 -2
- package/dist/{pieDiagram-5QR66LMP-DEiooyQu.js → pieDiagram-5QR66LMP-b_dHXzkV.js} +1 -1
- package/dist/print.js +2 -2
- package/dist/{quadrantDiagram-O4NWA36T-CLlaqEdw.js → quadrantDiagram-O4NWA36T-BSqAcBs7.js} +1 -1
- package/dist/{requirementDiagram-PLB6GJNP-DD74Pa6_.js → requirementDiagram-PLB6GJNP-BcxkmIFp.js} +2 -2
- package/dist/{sankeyDiagram-IPEJSGJF-DAR9G0yC.js → sankeyDiagram-IPEJSGJF-aD5r_n1q.js} +1 -1
- package/dist/{sortable-provider-D4S-mqLP.js → sortable-provider-C8mr3XP2.js} +1 -1
- package/dist/{stateDiagram-v2-GCMORJYK-pti7a_r-.js → stateDiagram-v2-GCMORJYK-Ct9ylaoP.js} +2 -2
- package/dist/{stored-language-BW32owje.js → stored-language-g121Yv0w.js} +10 -2
- package/dist/{swimlanes-2SLR337P-D10pSc8m.js → swimlanes-2SLR337P-BwCqwEoR.js} +3 -3
- package/dist/{swimlanesDiagram-TC7HE7FX-B8HgZod5.js → swimlanesDiagram-TC7HE7FX-WxBGUt0w.js} +3 -3
- package/dist/{timeline-definition-EJHVYXUP-D8CWcNj3.js → timeline-definition-EJHVYXUP-5Q8GU13Q.js} +1 -1
- package/dist/{translate-material-ZEzF-LKH.js → translate-material-D3Hp_AI5.js} +2 -2
- package/dist/{translator-BfqVlNGW.js → translator-BMFC0lBV.js} +1 -1
- package/dist/{use-heading-spy-DvZVu15k.js → use-heading-spy-wlOv87q3.js} +65 -59
- package/dist/{use-material-translation-B2GUtxUY.js → use-material-translation-BGFp1yXp.js} +2 -2
- package/dist/{usecaseDiagram-POWQR4AR-DIdH4Oia.js → usecaseDiagram-POWQR4AR-CzGOd4ic.js} +2 -2
- package/dist/vite.js +2 -2
- package/dist/{xychartDiagram-PMCCYNJV-aecZdRhd.js → xychartDiagram-PMCCYNJV-Bh_1zZoW.js} +1 -1
- package/docs/README.md +1 -0
- package/docs/components/data-display.md +5 -0
- package/docs/components/form-fields.md +14 -0
- package/docs/components/primitives.md +31 -0
- package/docs/components/selection-and-choice.md +74 -4
- package/docs/getting-started.md +5 -1
- package/docs/guides/csp.md +408 -0
- package/docs/guides/helpers.md +2 -0
- package/docs/guides/theming.md +27 -0
- package/docs/roadmap.md +21 -1
- package/docs/troubleshooting.md +220 -0
- package/lib/components/components.css +13 -2
- package/lib/components/ui/feedback/spinner/spinner.css +28 -0
- package/lib/components/ui/fields/otp-field/input-otp.css +48 -0
- package/lib/components/ui/media/pdf-viewer/pdf-viewer.css +24 -0
- package/lib/components/ui/overlays/drawer/vaul-drawer.css +199 -0
- package/lib/components/ui/overlays/drawer/vaul-keyframes.css +95 -0
- package/package.json +9 -4
- package/dist/lib/components/ui/fields/search-field/debounce.d.ts +0 -5
|
@@ -8,11 +8,11 @@ import "./chunk-7PRAP22T-0C6_H8Li.js";
|
|
|
8
8
|
import { a as g, i as _, o as v, r as y } from "./chunk-J5ZVWO5B-DmRRmhon.js";
|
|
9
9
|
import "./chunk-7INBJB4K-k-I67NSP.js";
|
|
10
10
|
import "./chunk-5DYCD2WN-Cd1zazNp.js";
|
|
11
|
-
import "./chunk-Z7XXMR3K-
|
|
11
|
+
import "./chunk-Z7XXMR3K-BzO1efzA.js";
|
|
12
12
|
import { t as ee } from "./chunk-XXDRQBXY-dKXxu_aj.js";
|
|
13
13
|
import { t as te } from "./chunk-WEXAMYUT-CbFOhEve.js";
|
|
14
14
|
import "./chunk-UA2S7LBM-ChuksCDg.js";
|
|
15
|
-
import { r as ne, t as re } from "./chunk-GNY47TPC-
|
|
15
|
+
import { r as ne, t as re } from "./chunk-GNY47TPC-CGgBmY0O.js";
|
|
16
16
|
//#region ../../node_modules/chevrotain/node_modules/lodash-es/_freeGlobal.js
|
|
17
17
|
var ie = typeof global == "object" && global && global.Object === Object && global, ae = typeof self == "object" && self && self.Object === Object && self, b = ie || ae || Function("return this")(), oe = b.Symbol, se = Object.prototype, ce = se.hasOwnProperty, le = se.toString, ue = oe ? oe.toStringTag : void 0;
|
|
18
18
|
function de(e) {
|
package/dist/vite.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { e as pdfkitStandardFonts };
|
|
1
|
+
import { cspAssetsInlineLimit as e, pdfkitStandardFonts as t } from "@nxgt/material-core/vite";
|
|
2
|
+
export { e as cspAssetsInlineLimit, t as pdfkitStandardFonts };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { at as e, rt as t, st as n } from "./components-
|
|
1
|
+
import { at as e, rt as t, st as n } from "./components-qTUjhFuo.js";
|
|
2
2
|
import { n as r } from "./src-CsLQInsN.js";
|
|
3
3
|
import { i } from "./chunk-ZIGJFQKS-9VXArDKF.js";
|
|
4
4
|
import { n as a } from "./chunk-Y2CYZVJY-BAad7w_K.js";
|
package/docs/README.md
CHANGED
|
@@ -14,6 +14,7 @@ detail: every option, the second example, and the traps.
|
|
|
14
14
|
| [Printing](guides/printing.md) | You render PDF documents with `@nxgt/material/print`, turn them into a download, a new tab or a server response, write them as plain data, or bundle them into an SSR server |
|
|
15
15
|
| [Maps](guides/maps.md) | You render Leaflet maps or a location field with `@nxgt/material/map` |
|
|
16
16
|
| [SSR](guides/ssr.md) | Your app renders on a server and bundles this package |
|
|
17
|
+
| [Content Security Policy](guides/csp.md) | Your app sends a strict CSP: the directives to use, the components that still inject a `<style>`, the zod and KaTeX settings, self-hosting a font, the per-request nonce |
|
|
17
18
|
| [Helpers](guides/helpers.md) | You need a utility, hook, slice factory or type from `/lib`, `/hooks`, `/i18n`, `/models`, `/types` or `/dnd` |
|
|
18
19
|
| [Troubleshooting](troubleshooting.md) | Something failed and you have an error message or a symptom |
|
|
19
20
|
| [Roadmap](roadmap.md) | You want to know what is planned, what shipped, and what will not be done |
|
|
@@ -532,6 +532,11 @@ import { Markdown } from '@nxgt/material/components';
|
|
|
532
532
|
Mermaid diagrams render in the browser only, after mount; on the server the
|
|
533
533
|
fence is left empty.
|
|
534
534
|
|
|
535
|
+
Math needs no import of its own: KaTeX's CSS is in the stylesheet, and its
|
|
536
|
+
fonts are files the stylesheet loads (`dist/fonts/katex/` on the compiled
|
|
537
|
+
route), allowed by `font-src 'self'`. Math in system fonts means the fonts
|
|
538
|
+
were not served ([troubleshooting](../troubleshooting.md#math-renders-in-the-system-fonts)).
|
|
539
|
+
|
|
535
540
|
**Storybook:** `Data display/Markdown` · **Vue:** `Markdown`, `MermaidDiagram`
|
|
536
541
|
|
|
537
542
|
---
|
|
@@ -744,6 +744,8 @@ Parts: `AttributesField` (the editable list), `AttributesList` (display with
|
|
|
744
744
|
attribute), `AttributeValuesForm` (fill values for a set of attributes).
|
|
745
745
|
Form wrappers: `AttributesFormField` (the definitions),
|
|
746
746
|
`AttributeValuesFormFieldSet` and `AttributeValueFormField` (the values).
|
|
747
|
+
`AttributeForm` builds its zod schema when it first renders, not when the
|
|
748
|
+
module loads ([CSP](../guides/csp.md#zod-and-unsafe-eval)).
|
|
747
749
|
|
|
748
750
|
| Prop | Type | Default | Effect |
|
|
749
751
|
| --- | --- | --- | --- |
|
|
@@ -856,6 +858,18 @@ const hours: OpeningHour[] = [
|
|
|
856
858
|
Parts: `OpeningHours` (the list) and `OpeningHoursDialog` (add / edit).
|
|
857
859
|
`OpeningHoursItem`, a day row bound to a react-hook-form array, is
|
|
858
860
|
**deprecated** and removed in 3.0: use `OpeningHoursFormField`.
|
|
861
|
+
`openingHoursSchema()` returns the zod schema of one `OpeningHour`
|
|
862
|
+
(`dayOfWeek` coerced from a string), built on the first call; the
|
|
863
|
+
`OpeningHoursSchema` constant is **deprecated** and removed in 3.0. Under a
|
|
864
|
+
strict CSP, call `z.config({ jitless: true })` first: see
|
|
865
|
+
[CSP](../guides/csp.md#zod-and-unsafe-eval).
|
|
866
|
+
|
|
867
|
+
```ts
|
|
868
|
+
import { openingHoursSchema } from '@nxgt/material/components';
|
|
869
|
+
import { z } from 'zod';
|
|
870
|
+
|
|
871
|
+
const schema = z.object({ hours: z.array(openingHoursSchema()) });
|
|
872
|
+
```
|
|
859
873
|
|
|
860
874
|
| Prop | Type | Default | Effect |
|
|
861
875
|
| --- | --- | --- | --- |
|
|
@@ -27,6 +27,7 @@ other pages are built from these.
|
|
|
27
27
|
| <img src="../previews/primitives-toggle.webp" width="96" alt=""> | [Toggle](#toggle) | Pressable on / off button |
|
|
28
28
|
| <img src="../previews/primitives-togglegroup.webp" width="96" alt=""> | [ToggleGroup](#togglegroup) | Single or multiple toggle group |
|
|
29
29
|
| | [Activity](#activity) | React `<Activity>` switched by a boolean |
|
|
30
|
+
| | [NonceProvider](#nonceprovider) | Gives the page's CSP nonce to every component below |
|
|
30
31
|
|
|
31
32
|
## Accordion
|
|
32
33
|
|
|
@@ -773,3 +774,33 @@ import { Activity } from '@nxgt/material/components';
|
|
|
773
774
|
| `visible` | `boolean` | `false` | `true` renders with `mode="visible"`; `false` hides the subtree and keeps its state |
|
|
774
775
|
|
|
775
776
|
**Storybook:** — · **Vue:** `Activity`
|
|
777
|
+
|
|
778
|
+
## NonceProvider
|
|
779
|
+
|
|
780
|
+
No preview: it draws nothing of its own, it hands the page's Content Security
|
|
781
|
+
Policy nonce down.
|
|
782
|
+
|
|
783
|
+
Gives this request's CSP nonce to every component below it: the `<style>`
|
|
784
|
+
elements of `ScrollArea` and `Select`, the stylesheet tiptap injects for
|
|
785
|
+
`RichTextEditor`, and, on the client, the scroll lock of every modal. Render it once, at the root, on the server and on
|
|
786
|
+
the client, with the same nonce.
|
|
787
|
+
|
|
788
|
+
```tsx
|
|
789
|
+
import { NonceProvider } from '@nxgt/material/components';
|
|
790
|
+
|
|
791
|
+
<NonceProvider nonce={nonce}>
|
|
792
|
+
<App />
|
|
793
|
+
</NonceProvider>;
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
| Prop | Type | Default | Effect |
|
|
797
|
+
| --- | --- | --- | --- |
|
|
798
|
+
| `nonce` | `string \| undefined` | — | the nonce of the page's `style-src-elem 'nonce-…'`; `undefined` or `''` inherits the nearest outer `NonceProvider`'s nonce (none at the root) |
|
|
799
|
+
|
|
800
|
+
`useCspNonce()` (`@nxgt/material/hooks`) reads it in a component of your own;
|
|
801
|
+
`getCspNonce()` and `setCspNonce()` (`@nxgt/material/lib`) read and keep the
|
|
802
|
+
page's nonce outside React. The server entry, the client entry and what each
|
|
803
|
+
component needs are in the [Content Security Policy
|
|
804
|
+
guide](../guides/csp.md#nonceprovider).
|
|
805
|
+
|
|
806
|
+
**Storybook:** `Primitives/NonceProvider` · **Vue:** `NonceProvider`
|
|
@@ -250,7 +250,7 @@ export function Framework() {
|
|
|
250
250
|
|
|
251
251
|

|
|
252
252
|
|
|
253
|
-
Single or multiple (chips) autocomplete with free-solo values and a
|
|
253
|
+
Single or multiple (chips) autocomplete with free-solo values, accent-insensitive matching and a debounced server search.
|
|
254
254
|
|
|
255
255
|
```tsx
|
|
256
256
|
import { Autocomplete } from '@nxgt/material/components';
|
|
@@ -286,15 +286,79 @@ Parts: `Autocomplete`, `AutocompleteChips` (the chips row it uses in
|
|
|
286
286
|
| `mode` | `'single' \| 'multiple'` | — | required; decides the `value` type |
|
|
287
287
|
| `value` | `string` / `string[]` | — | required, per `mode` |
|
|
288
288
|
| `onValueChange` | `(value?: string \| null) => void` / `(value?: string[] \| null) => void` | — | per `mode` |
|
|
289
|
-
| `options` | `T[]` (`{ value, label }` by default) |
|
|
289
|
+
| `options` | `T[]` (`{ value, label }` by default) | `[]` | the items; with `onSearch`, the list before a search and the selected options' labels |
|
|
290
290
|
| `getOptionValue`, `getOptionLabel` | `(option: T) => string` | `.value`, `.label` | for other option shapes |
|
|
291
|
+
| `filter` | `'accent-insensitive' \| 'none' \| (option: T, query: string) => boolean` | `'accent-insensitive'`, `'none'` with `onSearch` | how the list is filtered as the user types: label or value, ignoring case and accents (`e` finds "École") in the provider's language; `'none'` shows `options` as given; a function gets the trimmed query, never an empty one |
|
|
291
292
|
| `freeSolo` | `boolean` | — | accept a typed value that is not an option |
|
|
292
|
-
| `
|
|
293
|
+
| `onSearch` | `(query: string, { signal }: { signal: AbortSignal }) => Promise<T[]>` | — | server search: called once typing pauses; its results become the list. Each search aborts the previous one, and a response that lands after a newer one is dropped |
|
|
294
|
+
| `onSearchError` | `(error: unknown) => void` | — | `onSearch` rejected (an abort is not a rejection) |
|
|
295
|
+
| `minQueryLength` | `number` | `1` | `onSearch` waits for this many characters; below it the list says "Type at least N characters to search." |
|
|
296
|
+
| `debounceMs` | `number` | `250` | the pause before `onSearch` and `onQueryChange` run |
|
|
297
|
+
| `onQueryChange` | `(query: string) => void` | — | the query once typing pauses — fetch `options` yourself here |
|
|
298
|
+
| `loading` | `boolean` | — | with `onQueryChange`: "Loading…" in the list, `aria-busy` on the listbox, announced |
|
|
299
|
+
| `searchError` | `ReactNode` | — | with `onQueryChange`: shown and announced in place of the options |
|
|
300
|
+
| `empty` | `ReactNode` | "No option found." | text when nothing matches |
|
|
293
301
|
| `actions` | `ReactNode \| ((query: string) => ReactNode)` | — | buttons at the end of the list ("Create …") |
|
|
294
302
|
| `required` | `boolean` | — | the asterisk, and `aria-required` on the `combobox` input, which the label names |
|
|
295
303
|
| `disabled` | `boolean` | — | disables the input and each chip's remove button |
|
|
296
304
|
| `error` | `boolean` | — | error border on the chips box, error helper text, `aria-invalid` on the input |
|
|
297
305
|
|
|
306
|
+
### Searching a server
|
|
307
|
+
|
|
308
|
+
`onSearch` takes the query and an `AbortSignal`; hand the signal to `fetch`
|
|
309
|
+
so a search the user typed past is cancelled. The field shows "Loading…",
|
|
310
|
+
keeps the last results until the new ones arrive, and never lets an older
|
|
311
|
+
response overwrite a newer one, even from an API that ignores the signal.
|
|
312
|
+
Pass the selected option in `options` so its chip has a label before any
|
|
313
|
+
search; a picked option keeps its chip once a new search no longer returns
|
|
314
|
+
it.
|
|
315
|
+
|
|
316
|
+
```tsx
|
|
317
|
+
import { Autocomplete } from '@nxgt/material/components';
|
|
318
|
+
import { useState } from 'react';
|
|
319
|
+
|
|
320
|
+
type Person = { value: string; label: string };
|
|
321
|
+
|
|
322
|
+
async function searchPeople(query: string, { signal }: { signal: AbortSignal }) {
|
|
323
|
+
const response = await fetch(`/api/people?q=${encodeURIComponent(query)}`, { signal });
|
|
324
|
+
if (!response.ok) throw new Error(`Search failed: ${response.status}`);
|
|
325
|
+
return (await response.json()) as Person[];
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export function PersonField() {
|
|
329
|
+
const [value, setValue] = useState('');
|
|
330
|
+
return (
|
|
331
|
+
<Autocomplete<Person>
|
|
332
|
+
mode="single"
|
|
333
|
+
label="Person"
|
|
334
|
+
placeholder="Search by name"
|
|
335
|
+
value={value}
|
|
336
|
+
onValueChange={(next) => setValue(next ?? '')}
|
|
337
|
+
onSearch={searchPeople}
|
|
338
|
+
minQueryLength={2}
|
|
339
|
+
debounceMs={300}
|
|
340
|
+
/>
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
With `onSearch`, `minQueryLength` defaults to 1, `debounceMs` to 250 and `filter` to `'none'`
|
|
346
|
+
(the server filters). A rejected search shows and announces "The search
|
|
347
|
+
failed. Try again." by itself and hands the error to `onSearchError`; an abort is
|
|
348
|
+
never an error. Type your search with `AutocompleteSearch<T>` (its second
|
|
349
|
+
argument is `AutocompleteSearchContext`, `{ signal }`); `AutocompleteFilter<T>`
|
|
350
|
+
and `AutocompleteSearchProps<T>` are exported from `@nxgt/material/components` too.
|
|
351
|
+
|
|
352
|
+
To fetch it yourself instead, keep `options` and `loading` in your state,
|
|
353
|
+
update them from `onQueryChange`, and pass `filter="none"` when the server
|
|
354
|
+
already filtered.
|
|
355
|
+
|
|
356
|
+
**Accessibility.** A polite live region (`role="status"`) says "Loading…",
|
|
357
|
+
then "3 results" or "No results" (or the failure) once the search answers or
|
|
358
|
+
typing pauses — never on every keystroke. The listbox is `aria-busy` while
|
|
359
|
+
loading. The strings are `material.autocomplete.loading`, `.results`,
|
|
360
|
+
`.search-error` and `.min-query`. The keyboard works as before.
|
|
361
|
+
|
|
298
362
|
**Emits:** `string | null` in `single` mode, `string[]` in `multiple`.
|
|
299
363
|
**Form wrapper:** `AutocompleteFormField` — `control` and `name`, see
|
|
300
364
|
[forms](../guides/forms.md#the-pair) and [what each field emits](../guides/forms.md#what-each-field-emits).
|
|
@@ -409,7 +473,7 @@ full naming alignment is planned for 3.0.
|
|
|
409
473
|
|
|
410
474
|
| Prop | Type | Default | Effect |
|
|
411
475
|
| --- | --- | --- | --- |
|
|
412
|
-
| `options` | `{ value: string; label: ReactNode }[]` | — | the radios |
|
|
476
|
+
| `options` | `{ value: string; label: ReactNode; disabled?: boolean }[]` | — | the radios; `disabled` on an option disables only it |
|
|
413
477
|
| `value` / `defaultValue` | `string` | — | Radix radio group state |
|
|
414
478
|
| `onValueChange` | `(value: string) => void` | — | |
|
|
415
479
|
| `orientation` | `'vertical' \| 'horizontal'` | `'horizontal'` | layout |
|
|
@@ -422,6 +486,12 @@ before the first radio, and `error` sets `aria-invalid` on it (a `radiogroup`
|
|
|
422
486
|
may carry it; your own `aria-invalid` wins). Your own `aria-label` /
|
|
423
487
|
`aria-labelledby` wins, and your `aria-describedby` ids come first.
|
|
424
488
|
|
|
489
|
+
An option's type is exported as `RadioGroupOption`. A disabled option (`disabled: true` on it) is announced as disabled, skipped by
|
|
490
|
+
the arrow keys (as the Radix primitives do) and drawn with a muted label and a
|
|
491
|
+
faded radio; the label keeps 4.5:1 contrast in both themes. The group's own
|
|
492
|
+
`disabled` disables every option. An option disabled while it is the current
|
|
493
|
+
value stays checked.
|
|
494
|
+
|
|
425
495
|
**Emits:** `string`.
|
|
426
496
|
**Form wrapper:** `RadioGroupFormField` — `control` and `name`, see
|
|
427
497
|
[forms](../guides/forms.md#the-pair) and [what each field emits](../guides/forms.md#what-each-field-emits).
|
package/docs/getting-started.md
CHANGED
|
@@ -30,7 +30,9 @@ does not import that entry never has them in its tree.
|
|
|
30
30
|
| `@nxgt/material/print` | `bun add @react-pdf/renderer@^4.9 react-pdf-tailwind` ([printing](guides/printing.md)) |
|
|
31
31
|
| `@nxgt/material/map` | `bun add leaflet react-leaflet @react-leaflet/core @adamscybot/react-leaflet-component-marker react-geolocated` ([maps](guides/maps.md)) |
|
|
32
32
|
|
|
33
|
-
The tarball contains the built `dist
|
|
33
|
+
The tarball contains the built `dist/` (with KaTeX's fonts in
|
|
34
|
+
`dist/fonts/katex/`, which the compiled stylesheet loads),
|
|
35
|
+
`lib/styles.css`, the component
|
|
34
36
|
stylesheets it imports (`lib/components/**/*.css`), `lib/map/map.css`,
|
|
35
37
|
these docs and `CHANGELOG.md` (from the release after 2.6.1). There is no
|
|
36
38
|
`postinstall` build step.
|
|
@@ -45,6 +47,8 @@ In the app's root stylesheet, in this order:
|
|
|
45
47
|
@source "../node_modules/@nxgt/material/";
|
|
46
48
|
```
|
|
47
49
|
|
|
50
|
+
Toaster, Drawer and InputOTP take their CSS from this stylesheet: without it they render unstyled.
|
|
51
|
+
|
|
48
52
|
- **`styles.css` is source, not compiled CSS.** It holds the Tailwind v4
|
|
49
53
|
`@theme` layer (colours, `--radius`, the `dark` variant, base styles), so it
|
|
50
54
|
runs through *your* Tailwind build. Nothing injects it: import it
|