@nxgt/material 2.18.0 → 2.19.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 (97) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +1 -0
  3. package/dist/{_Uint8Array-C7apDrb7.js → _Uint8Array-B6RHzY7k.js} +1 -1
  4. package/dist/{_overRest-CCAbV-eT.js → _overRest-Cs3RIAVd.js} +1 -1
  5. package/dist/{async-slice-Cuekts5f.js → async-slice-CgbRYTRY.js} +3 -3
  6. package/dist/{blockDiagram-BEXU5L5S-B63zbmDg.js → blockDiagram-BEXU5L5S-D5ptXmBP.js} +2 -2
  7. package/dist/{chunk-3FUC2YCW-CE9T5wr6.js → chunk-3FUC2YCW-al8CepY8.js} +2 -2
  8. package/dist/{chunk-7M6MHVWA-BjaezAbj.js → chunk-7M6MHVWA-BERAnmfo.js} +1 -1
  9. package/dist/{chunk-GNY47TPC-DjnciAsL.js → chunk-GNY47TPC-DMMDhC9T.js} +4 -4
  10. package/dist/{chunk-NETBCI7D-CxQxB74H.js → chunk-NETBCI7D-CsMBdu5o.js} +1 -1
  11. package/dist/{chunk-Z7XXMR3K-BBrCUBwp.js → chunk-Z7XXMR3K-CLYmaWUD.js} +1 -1
  12. package/dist/{classDiagram-v2-NBCMYWYE-FeyVcYCs.js → classDiagram-v2-NBCMYWYE-C-6ddqhF.js} +2 -2
  13. package/dist/components/base.css +3 -1
  14. package/dist/{components-CsPEBzNF.js → components-C5y9FL-6.js} +23667 -23283
  15. package/dist/components.js +6 -6
  16. package/dist/{dagre-6A5THRUB-BjO_Ytfq.js → dagre-6A5THRUB-Ck8np52h.js} +11 -11
  17. package/dist/{diagram-22UHCM2B-BBKawlhX.js → diagram-22UHCM2B-oIfSvE0L.js} +2 -2
  18. package/dist/{diagram-3UASUU5V-CKj_37_k.js → diagram-3UASUU5V-CAG93Qkg.js} +1 -1
  19. package/dist/dnd.js +1 -1
  20. package/dist/{elk-276RUBZZ-DmkPwZLS.js → elk-276RUBZZ-BfEvNh_f.js} +3 -3
  21. package/dist/{erDiagram-OPXOYQCR-Dja943M3.js → erDiagram-OPXOYQCR-B966QSkJ.js} +2 -2
  22. package/dist/{field-blur-DNHXOY0J.js → field-blur-B6VqkpE6.js} +35 -23
  23. package/dist/{flowDiagram-KWPJA3E3-jmbjSQZS.js → flowDiagram-KWPJA3E3-CzUHW7vw.js} +3 -3
  24. package/dist/{ganttDiagram-FUAMR5RP-BONNpqJt.js → ganttDiagram-FUAMR5RP-B4JstFXN.js} +1 -1
  25. package/dist/{graphlib-DxjKaXeR.js → graphlib-CORKO6lR.js} +6 -6
  26. package/dist/hooks.js +2 -2
  27. package/dist/{i18n-provider-Dv9ZSmgO.js → i18n-provider-BC7MMAID.js} +1 -1
  28. package/dist/i18n.js +6 -6
  29. package/dist/{isArrayLikeObject-H8k6W51O.js → isArrayLikeObject-gzSxxbGJ.js} +3 -3
  30. package/dist/{isEmpty-B0Bavg-e.js → isEmpty-SD8ldTK-.js} +3 -3
  31. package/dist/{journeyDiagram-ZHPQQLJL-C_omtnEz.js → journeyDiagram-ZHPQQLJL-DcgTl4Bw.js} +1 -1
  32. package/dist/lib/components/ui/fields/index.d.ts +1 -0
  33. package/dist/lib/components/ui/fields/repeatable-group/index.d.ts +2 -0
  34. package/dist/lib/components/ui/fields/repeatable-group/partials/repeatable-group-footer.d.ts +14 -0
  35. package/dist/lib/components/ui/fields/repeatable-group/partials/repeatable-group-row.d.ts +19 -0
  36. package/dist/lib/components/ui/fields/repeatable-group/partials/repeatable-group-rows.d.ts +21 -0
  37. package/dist/lib/components/ui/fields/repeatable-group/partials/repeatable-group-status.d.ts +11 -0
  38. package/dist/lib/components/ui/fields/repeatable-group/repeatable-group-classes.d.ts +33 -0
  39. package/dist/lib/components/ui/fields/repeatable-group/repeatable-group-form-field.d.ts +28 -0
  40. package/dist/lib/components/ui/fields/repeatable-group/repeatable-group-names.d.ts +16 -0
  41. package/dist/lib/components/ui/fields/repeatable-group/repeatable-group.d.ts +12 -0
  42. package/dist/lib/components/ui/fields/repeatable-group/types.d.ts +45 -0
  43. package/dist/lib/components/ui/fields/repeatable-group/use-repeatable-group.d.ts +32 -0
  44. package/dist/lib/components/ui/fields/search-field/search-field.d.ts +7 -1
  45. package/dist/lib/components/ui/overlays/command/command-item.d.ts +10 -0
  46. package/dist/lib/components/ui/overlays/command/command.d.ts +5 -2
  47. package/dist/lib/components/ui/primitives/typography/typography.d.ts +2 -1
  48. package/dist/lib/components/ui/selection/autocomplete/types.d.ts +1 -1
  49. package/dist/lib/components/ui/selection/autocomplete/use-query-report.d.ts +8 -0
  50. package/dist/lib/components/ui/selection/checkbox-group/checkbox-group.d.ts +2 -0
  51. package/dist/lib/components/ui/selection/option-count/option-count.d.ts +18 -0
  52. package/dist/lib/components/ui/selection/radio-group/radio-group.d.ts +2 -0
  53. package/dist/lib/components/ui/selection/select-chip-field/next-selection.d.ts +10 -0
  54. package/dist/lib/components/ui/selection/select-chip-field/select-chip-field.d.ts +8 -1
  55. package/dist/lib/components/ui/selection/select-chip-field/select-chip-header.d.ts +15 -0
  56. package/dist/lib/components/ui/selection/select-chip-field/select-chip-option.d.ts +13 -0
  57. package/dist/lib/i18n/resources/en/en.d.ts +14 -0
  58. package/dist/lib/i18n/resources/en/material.json.d.ts +14 -0
  59. package/dist/lib/i18n/resources/fr/fr.d.ts +14 -0
  60. package/dist/lib/i18n/resources/fr/material.json.d.ts +14 -0
  61. package/dist/lib/i18n/resources/resources.d.ts +28 -0
  62. package/dist/lib/i18n/translator.d.ts +1 -1
  63. package/dist/lib.js +2 -2
  64. package/dist/main.js +16 -16
  65. package/dist/map.js +2 -2
  66. package/dist/material.css +1 -1
  67. package/dist/{merge-Js8537dg.js → merge-Cek5eQP5.js} +4 -4
  68. package/dist/{mermaid.core-9dpDfc6Y.js → mermaid.core-DZMjEtsT.js} +21 -21
  69. package/dist/{mindmap-definition-NLK3R4M7-CjYayluH.js → mindmap-definition-NLK3R4M7-BWaJFjFb.js} +2 -2
  70. package/dist/{pieDiagram-5QR66LMP-BfFcf84S.js → pieDiagram-5QR66LMP-C8iomTeg.js} +1 -1
  71. package/dist/print.js +2 -2
  72. package/dist/{quadrantDiagram-O4NWA36T-DdvYjvR0.js → quadrantDiagram-O4NWA36T-D529X2yn.js} +1 -1
  73. package/dist/{requirementDiagram-PLB6GJNP-CGG6Y3SN.js → requirementDiagram-PLB6GJNP-Cs5ieS_S.js} +2 -2
  74. package/dist/{sankeyDiagram-IPEJSGJF-DJufZkAf.js → sankeyDiagram-IPEJSGJF-BOIAba-k.js} +1 -1
  75. package/dist/{sortable-provider-CUT5Wfdl.js → sortable-provider-DNmv3XmW.js} +1 -1
  76. package/dist/{stateDiagram-v2-GCMORJYK-vRvpKK9I.js → stateDiagram-v2-GCMORJYK-CT46B5KK.js} +2 -2
  77. package/dist/{stored-language-BKoohv2_.js → stored-language-FHwsTPoM.js} +24 -0
  78. package/dist/{swimlanes-2SLR337P-Czy9f6gp.js → swimlanes-2SLR337P-C8TrgNLm.js} +3 -3
  79. package/dist/{swimlanesDiagram-TC7HE7FX-C6RYBQ-A.js → swimlanesDiagram-TC7HE7FX-Dii9S4bC.js} +3 -3
  80. package/dist/{timeline-definition-EJHVYXUP-CS9RiAiW.js → timeline-definition-EJHVYXUP-K00somtn.js} +1 -1
  81. package/dist/{translate-material-CCJg3yfc.js → translate-material-cZ6VSQ98.js} +2 -2
  82. package/dist/{translator-DEde7BKz.js → translator-DX_ArUA5.js} +1 -1
  83. package/dist/{use-heading-spy-XkSExwoT.js → use-heading-spy-DR1jat6E.js} +2 -2
  84. package/dist/{use-material-translation-Cndoq_iK.js → use-material-translation-W6jOKCbO.js} +2 -2
  85. package/dist/{usecaseDiagram-POWQR4AR-CW-8YHgN.js → usecaseDiagram-POWQR4AR-liF9q6mE.js} +2 -2
  86. package/dist/{xychartDiagram-PMCCYNJV-G4PopeeF.js → xychartDiagram-PMCCYNJV-B9Qx3wAO.js} +1 -1
  87. package/docs/components/README.md +1 -1
  88. package/docs/components/form-fields.md +146 -0
  89. package/docs/components/overlays-and-menus.md +2 -0
  90. package/docs/components/primitives.md +3 -1
  91. package/docs/components/selection-and-choice.md +22 -6
  92. package/docs/guides/forms.md +35 -0
  93. package/docs/previews/form-fields-repeatablegroup.webp +0 -0
  94. package/docs/roadmap.md +7 -0
  95. package/docs/troubleshooting.md +57 -0
  96. package/lib/components/base.css +3 -1
  97. package/package.json +2 -2
@@ -294,8 +294,8 @@ Parts: `Autocomplete`, `AutocompleteChips` (the chips row it uses in
294
294
  | `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 |
295
295
  | `onSearchError` | `(error: unknown) => void` | — | `onSearch` rejected (an abort is not a rejection) |
296
296
  | `minQueryLength` | `number` | `1` | `onSearch` waits for this many characters; below it the list says "Type at least N characters to search." |
297
- | `debounceMs` | `number` | `250` | the pause before `onSearch` and `onQueryChange` run |
298
- | `onQueryChange` | `(query: string) => void` | — | the query once typing pauses — fetch `options` yourself here |
297
+ | `debounceMs` | `number` | `250` | the pause before `onSearch` and `onQueryChange` run on typed text; an emptied query is reported to `onQueryChange` at once, and `onSearch` never runs on it unless `minQueryLength` is `0` (then it follows the pause) |
298
+ | `onQueryChange` | `(query: string) => void` | — | the query once typing pauses, and `''` at once when it empties (a pick, a clear) — fetch `options` yourself here |
299
299
  | `loading` | `boolean` | — | with `onQueryChange`: "Loading…" in the list, `aria-busy` on the listbox, announced |
300
300
  | `searchError` | `ReactNode` | — | shown and announced in place of the options; with `onSearch` it replaces the generic "The search failed. Try again." |
301
301
  | `empty` | `ReactNode` | "No option found." | text when nothing matches |
@@ -427,7 +427,7 @@ export function Frameworks() {
427
427
 
428
428
  | Prop | Type | Default | Effect |
429
429
  | --- | --- | --- | --- |
430
- | `options` | `{ value: string; label: ReactNode }[]` | — | the boxes |
430
+ | `options` | `{ value: string; label: ReactNode; count?: number }[]` | — | the boxes; `count`: see [option counts](#option-counts). |
431
431
  | `value` | `string[]` | `[]` | the checked values |
432
432
  | `onValueChange` | `(value: string[]) => void` | — | the new list on each toggle |
433
433
  | `orientation` | `'vertical' \| 'horizontal'` | `'horizontal'` | layout |
@@ -446,6 +446,10 @@ error with no message (`setError(name, { type: 'server' })`) keeps your
446
446
  the group's description is "<helperText> This value is not valid." and the error
447
447
  is not only a red colour.
448
448
 
449
+ #### Option counts
450
+
451
+ `count` on an option of `CheckboxGroup`, `RadioGroup` or `SelectChipField` shows a number after the label, in muted `tabular-nums` text, and joins the accessible name: the number as plain text plus a visually hidden unit word, so the option is named "CE1 24 results" (it starts with the visible label). The unit is the ICU plural `material.option-count.label` (`result` / `results`; `résultat` / `résultats` in French), so override it in your resources for another noun. `0` is a valid count.
452
+
449
453
  **Emits:** `string[]`.
450
454
  **Form wrapper:** `CheckboxGroupFormField` — `control` and `name`, see
451
455
  [forms](../guides/forms.md#the-pair) and [what each field emits](../guides/forms.md#what-each-field-emits).
@@ -482,7 +486,7 @@ full naming alignment is planned for 3.0.
482
486
 
483
487
  | Prop | Type | Default | Effect |
484
488
  | --- | --- | --- | --- |
485
- | `options` | `{ value: string; label: ReactNode; disabled?: boolean }[]` | — | the radios; `disabled` on an option disables only it |
489
+ | `options` | `{ value: string; label: ReactNode; disabled?: boolean; count?: number }[]` | — | the radios; `disabled` on an option disables only it; `count`: see [option counts](#option-counts). |
486
490
  | `value` / `defaultValue` | `string` | — | Radix radio group state |
487
491
  | `onValueChange` | `(value: string) => void` | — | |
488
492
  | `orientation` | `'vertical' \| 'horizontal'` | `'horizontal'` | layout |
@@ -610,12 +614,24 @@ export function Topics() {
610
614
  }
611
615
  ```
612
616
 
617
+ With counts, and a single choice that stays chosen when pressed again:
618
+
619
+ ```tsx
620
+ const levels = [
621
+ { value: 'ce1', label: 'CE1', count: 24 },
622
+ { value: 'ce2', label: 'CE2', count: 1 },
623
+ ];
624
+
625
+ <SelectChipField label="Level" options={levels} value={value} onValueChange={setValue} deselectable={false} />
626
+ ```
627
+
613
628
  | Prop | Type | Default | Effect |
614
629
  | --- | --- | --- | --- |
615
- | `mode` | `'single' \| 'multiple'` | `'single'` | clicking the selected chip in `single` mode clears it |
630
+ | `mode` | `'single' \| 'multiple'` | `'single'` | clicking the selected chip in `single` mode clears it, unless `deselectable` is `false` |
631
+ | `deselectable` | `boolean` | `true` | `false`: in `single` mode a second press keeps the chosen chip chosen, as a radio group does; another chip still replaces it |
616
632
  | `value` | `string[]` | `[]` | the selected values, even in `single` mode |
617
633
  | `onValueChange` | `(value: string[]) => void` | — | |
618
- | `options` | `{ value, label, icon? }[]` | — | the chips |
634
+ | `options` | `{ value: string; label: string; icon?: ReactNode; count?: number }[]` | — | the chips; `count`: see [option counts](#option-counts). |
619
635
 
620
636
  **Accessibility:** the chips are toggle buttons in a `role="group"` named by
621
637
  `label` and described by the help text: a chosen chip is
@@ -567,6 +567,41 @@ export function SupplierForm({ onSave }: { onSave: (values: Values) => void }) {
567
567
  renders one input per attribute and writes `{ [attribute.name]: value }` to
568
568
  its `name`.
569
569
 
570
+ ### Rows a user adds and removes
571
+
572
+ When the rows are fields of their own — a school year's periods, each with a
573
+ name, a start date and an end date — use
574
+ [`RepeatableGroupFormField`](../components/form-fields.md#repeatablegroup)
575
+ over `useFieldArray`, and render each row's fields with the form's own
576
+ wrappers:
577
+
578
+ ```tsx
579
+ <RepeatableGroupFormField
580
+ control={form.control}
581
+ name="periods"
582
+ label="Periods"
583
+ rowLabel="period"
584
+ max={6}
585
+ reorderable
586
+ newRow={() => ({ name: '' })}
587
+ renderRow={({ index }) => (
588
+ <>
589
+ <TextFormField control={form.control} name={`periods.${index}.name`} label="Name" />
590
+ <DateFormField control={form.control} name={`periods.${index}.start`} label="Start date" />
591
+ </>
592
+ )}
593
+ />
594
+ ```
595
+
596
+ - A row's field shows its own error (`periods.1.name`); the array's own error
597
+ (`.min(2)` on the array, or a `useFieldArray` rule) shows under the rows and
598
+ describes the group.
599
+ - The group moves the focus as rows come and go (an added row's first field,
600
+ a removed row's neighbour or Add, a moved row's move button) and announces each change politely
601
+ ("Added period 3"). A row your own code appends takes
602
+ `{ shouldFocus: false }`
603
+ ([why](../troubleshooting.md#the-focus-jumps-away-from-a-new-row-of-a-repeatablegroupformfield)).
604
+
570
605
  ## Config-driven forms
571
606
 
572
607
  `FormField` renders the field that matches a config `type`, which is useful
package/docs/roadmap.md CHANGED
@@ -157,6 +157,13 @@ version they shipped in, and planned entries may name the major they target.
157
157
 
158
158
  ## Shipped
159
159
 
160
+ - **Rows a user adds, removes and reorders** — `RepeatableGroup` and
161
+ `RepeatableGroupFormField` over the form library's field array: rows from
162
+ `renderRow`, a list for assistive tech, Remove and move buttons named after
163
+ the row ("Remove period 2"), `max` and `min`, an empty state, focus that
164
+ follows each change, polite announcements, and the array's own error under
165
+ the rows. One column on a phone. 2.19.0.
166
+
160
167
  - **Signed-out pages and two-step verification** — `AuthCard`, the frame of a
161
168
  sign-in page (one `main`, the card's title its `h1`, a status or alert
162
169
  notice, safe-area padding); `EnrolmentSecret`, a TOTP enrolment's QR code,
@@ -130,6 +130,7 @@ words in your error.
130
130
  - ["Required" shows as soon as the calendar opens, or while a date is being picked](#required-shows-as-soon-as-the-calendar-opens-or-while-a-date-is-being-picked)
131
131
  - [`TypeError: values.map is not a function` (a `SliderFormField`)](#typeerror-valuesmap-is-not-a-function)
132
132
  - [An end-to-end test no longer finds `aria-expanded` on a `ResponsiveButton`](#an-end-to-end-test-no-longer-finds-aria-expanded-on-a-responsivebutton)
133
+ - [The focus jumps away from a new row of a `RepeatableGroupFormField`](#the-focus-jumps-away-from-a-new-row-of-a-repeatablegroupformfield)
133
134
  - [A multi-step form reopens at a later step](#a-multi-step-form-reopens-at-a-later-step)
134
135
  - [An end-to-end test no longer finds a `LinkButton` by the `button` role](#an-end-to-end-test-no-longer-finds-a-linkbutton-by-the-button-role)
135
136
  - [A test no longer finds a date or time picker by the `button` role, or a slider thumb by the exact name `Minimum`](#a-test-no-longer-finds-a-date-or-time-picker-by-the-button-role-or-a-slider-thumb-by-the-exact-name-minimum)
@@ -151,6 +152,7 @@ words in your error.
151
152
  - [A test no longer finds `aria-invalid` on a `Switch` row or an `Autocomplete`'s chips](#a-test-no-longer-finds-aria-invalid-on-a-switch-row-or-an-autocompletes-chips)
152
153
  - [An `Autocomplete` lists more options than before, or "ecole" finds "École"](#an-autocomplete-lists-more-options-than-before-or-ecole-finds-école)
153
154
  - [`onQueryChange` runs more often after upgrading](#onquerychange-runs-more-often-after-upgrading)
155
+ - [A click on the next field right after an `Autocomplete` pick is lost](#a-click-on-the-next-field-right-after-an-autocomplete-pick-is-lost)
154
156
  - [An older search's results replace the newer ones in an `Autocomplete`](#an-older-searchs-results-replace-the-newer-ones-in-an-autocomplete)
155
157
  - [An `Autocomplete` option does nothing on click or Enter](#an-autocomplete-option-does-nothing-on-click-or-enter)
156
158
  - ["The search failed. Try again." no longer shows in an `Autocomplete`](#the-search-failed-try-again-no-longer-shows-in-an-autocomplete)
@@ -161,6 +163,7 @@ words in your error.
161
163
  - [A `className` on `ActivityLayout` now styles the whole shell](#a-classname-on-activitylayout-now-styles-the-whole-shell)
162
164
  - [A test finds a new heading or a second `main`, or no longer finds a title in a `div`](#a-test-finds-a-new-heading-or-a-second-main-or-no-longer-finds-a-title-in-a-div)
163
165
  - [`[data-test="typogaphy"]` finds nothing](#data-testtypogaphy-finds-nothing)
166
+ - [Long text in `Typography` no longer scrolls](#long-text-in-typography-no-longer-scrolls)
164
167
  - [A test no longer finds a tooltip on an entry of an expanded sidebar](#a-test-no-longer-finds-a-tooltip-on-an-entry-of-an-expanded-sidebar)
165
168
  - [A test no longer finds a calendar day by its number, or by "Today" or "selected"](#a-test-no-longer-finds-a-calendar-day-by-its-number-or-by-today-or-selected)
166
169
  - [`#<name>` no longer finds a `SwitchFormField` or `CheckboxFormField`](#name-no-longer-finds-a-switchformfield-or-checkboxformfield)
@@ -2395,6 +2398,26 @@ On an older version, give the field an array default and keep an array:
2395
2398
  useForm({ defaultValues: { volume: [40] } }); // an array stays an array
2396
2399
  ```
2397
2400
 
2401
+ ### The focus jumps away from a new row of a `RepeatableGroupFormField`
2402
+
2403
+ **When:** a row is added to a `RepeatableGroupFormField` by your own code (a
2404
+ second "Add" button, a "Duplicate" action) through `useFieldArray`'s `append`,
2405
+ `prepend` or `insert` on the same `name`, and the focus lands on another field
2406
+ than the one you expected, or the page scrolls to it.
2407
+ **Why:** react-hook-form's `append` (and `prepend`, `insert`) default to
2408
+ `shouldFocus: true` and focus the new row's first registered field. The group
2409
+ moves the focus itself only after its own buttons (the new row's first field,
2410
+ a removed row's neighbour, a move button), so a second `useFieldArray` that
2411
+ focuses on its own fights with it.
2412
+ **Fix:** let the group's Add button add rows (`newRow` is what it appends).
2413
+ When your own code must add one, pass `{ shouldFocus: false }` and move the
2414
+ focus yourself if you want it moved:
2415
+
2416
+ ```tsx
2417
+ const { append } = useFieldArray({ control, name: 'periods' });
2418
+ append({ name: '' }, { shouldFocus: false });
2419
+ ```
2420
+
2398
2421
  ### A multi-step form reopens at a later step
2399
2422
 
2400
2423
  **When:** a wizard built on `createStepFormSlice` opens at the step (and with
@@ -2911,6 +2934,20 @@ was a fixed 1 s.
2911
2934
  **Fix:** set the pause you had, `debounceMs={1000}`, or move the fetch to `onSearch`, which
2912
2935
  also aborts the previous request and drops a stale response.
2913
2936
 
2937
+ ### A click on the next field right after an `Autocomplete` pick is lost
2938
+
2939
+ **When:** before 2.18.1, in a dialog, a `Select` (or any field) right below an
2940
+ `Autocomplete` whose `onQueryChange` shows or hides something (a line naming
2941
+ who is already linked, a result count): a click on that field's option just
2942
+ after a pick does nothing, now and then (more often in Firefox and on a slow
2943
+ machine; an end-to-end test flakes).
2944
+ **Why:** a pick empties the query, and `onQueryChange('')` came only after
2945
+ `debounceMs`. The line it removed then shrank the centred dialog, which moved
2946
+ the open list by half that height between the pointer's press and its release:
2947
+ the release landed on another option, and nothing was chosen.
2948
+ **Fix:** upgrade: an emptied query is reported at once, with the pick, before
2949
+ the next click. Waiting in a test until no `listbox` is left only hid it.
2950
+
2914
2951
  ### An older search's results replace the newer ones in an `Autocomplete`
2915
2952
 
2916
2953
  **When:** you fetch `options` yourself from `onQueryChange`, and a slow response
@@ -3092,6 +3129,26 @@ with its own `<main>` passes `contentAs="div"`.
3092
3129
  **Fix:** select `[data-test="typography"]` — or better, the text or the role
3093
3130
  the user sees.
3094
3131
 
3132
+ ### Long text in `Typography` no longer scrolls
3133
+
3134
+ **When:** after upgrading, a `Typography` with a fixed height or width used to
3135
+ scroll its overflowing text; it now overflows its box (or `truncate` and
3136
+ `line-clamp-*` are the only things that clip it).
3137
+ **Why:** `Typography` always carried `overflow-auto`, which made every block
3138
+ `Typography` a scroll region: Firefox counted a subpixel overflow, and axe
3139
+ reported `scrollable-region-focusable`. It sets no `overflow` now, so it is no
3140
+ longer a block formatting context (its margins can collapse with its
3141
+ neighbours'), and a text flex or grid item no longer has the zero minimum width a scroll container has.
3142
+ **Fix:** where you want scrolling, wrap the text in an element that owns it,
3143
+ focusable and named so keyboard users can scroll it; where you want a flex
3144
+ item to shrink, give it `min-w-0`:
3145
+
3146
+ ```tsx
3147
+ <div className="max-h-40 overflow-auto" tabIndex={0} aria-label="Release notes">
3148
+ <Typography>{longText}</Typography>
3149
+ </div>
3150
+ ```
3151
+
3095
3152
  ### A test no longer finds a tooltip on an entry of an expanded sidebar
3096
3153
 
3097
3154
  **When:** after upgrading, a test hovers or focuses a `SidebarMenuItem` of an
@@ -55,7 +55,9 @@
55
55
  font-size: var(--text-xs);
56
56
  font-weight: var(--font-weight-medium);
57
57
  }
58
- a:not(:has(> button)) {
58
+ /* A sidebar entry is a link styled as a menu entry: the prose link style
59
+ (underline, info tint on hover and focus) must not reach it (#566). */
60
+ a:not(:has(> button)):not([data-slot="sidebar-menu-item"]) {
59
61
  @apply focus:underline underline-offset-4 hover:underline cursor-pointer;
60
62
  @apply text-info [&_svg]:data-[slot=icon]:text-info hover:bg-info/10 active:bg-info/5 focus:bg-info/15;
61
63
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxgt/material",
3
- "version": "2.18.0",
3
+ "version": "2.19.0",
4
4
  "license": "MIT",
5
5
  "bugs": {
6
6
  "email": "stevegires@gmail.com"
@@ -119,7 +119,7 @@
119
119
  "docs:previews": "vitest run --project previews"
120
120
  },
121
121
  "dependencies": {
122
- "@nxgt/material-core": "^0.10.0",
122
+ "@nxgt/material-core": "^0.11.0",
123
123
  "@base-ui/react": "^1.6.0",
124
124
  "@dnd-kit/core": "^6.3.1",
125
125
  "@dnd-kit/sortable": "^10.0.0",