@dloizides/ui-forms 1.13.4 → 1.15.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 CHANGED
@@ -1,5 +1,46 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.15.0
4
+
5
+ **`FormSwitch` now emits `aria-checked` / `aria-disabled` on web; `ChipSelector` gained an option icon slot and opt-in radio semantics.**
6
+
7
+ `FormSwitch` (A11Y-ARIA-CHECKED-1): react-native-web 0.21 emits nothing from `accessibilityState` on web, so the
8
+ switch wrapper rendered `role="switch"` with no `aria-checked` - an invalid switch that announced no state. The
9
+ state is now passed as literal `aria-checked` (always) and `aria-disabled` (only when disabled) web props;
10
+ `accessibilityState` also carries `disabled` for native.
11
+
12
+ `ChipSelector`:
13
+ - `ChipOption.icon?: React.ReactNode` - rendered before the label inside the chip, wrapped `aria-hidden`. Options
14
+ without an icon render the exact same tree as before.
15
+ - `singleSelectRole?: 'button' | 'radio'` (type `ChipSingleSelectRole`). Default `button` = unchanged. With
16
+ `radio` and `multiple` unset, the group is `role="radiogroup"` and each chip `role="radio"` + `aria-checked`.
17
+ Ignored for multi-select. Trade-off: RN-web renders a radio chip as a `<div>`, which activates on Enter but not
18
+ Space and has no arrow-key roving focus.
19
+
20
+ **Additive and backward-compatible.** No prop set = identical DOM for every existing consumer.
21
+
22
+ ## 1.14.0
23
+
24
+ **`FormField` gained an opt-in `recentKey` — remember the last N submitted values and offer them on focus.**
25
+
26
+ A search / filter / lookup box that the user retypes the same handful of values into now gets a
27
+ "recent values" dropdown for free. Set `recentKey="<namespace>"` on a `FormField` and the values it
28
+ submits are remembered (per key) and surfaced in a menu on focus; picking one fills the input. A
29
+ value is recorded on submit (Enter) **and** on blur-with-content, so both "hit enter" and "typed then
30
+ moved on" are captured. The dropdown reuses the kit's `AnchoredMenu` (portalled to `document.body`, so
31
+ it is never painted behind a table / card / the next field) with full a11y (menu name, per-row label +
32
+ hint + role).
33
+
34
+ Persistence is `localStorage` under `@dloizides/ui-forms:recent:<recentKey>`; the list de-dupes
35
+ case-insensitively, promotes a repeat to the front, and caps at `recentMax` (default 10). On native /
36
+ SSR / when storage is disabled it is a silent no-op (recents are always `[]`), and every storage
37
+ access is wrapped so a quota or privacy-mode failure can never throw into render.
38
+
39
+ **Additive and backward-compatible.** Leave `recentKey` unset — the default — and the field behaves
40
+ exactly as before: nothing rendered, no state/refs/effects, no storage touched. NEVER set it on a
41
+ password / secure field. The engine is also exported standalone as `useRecentValues(key, max?)` for
42
+ bespoke recents surfaces, and `AnchoredMenu` gained an optional `accessibilityLabel` for naming the menu.
43
+
3
44
  ## 1.13.3
4
45
 
5
46
  **Placeholder text was too dark — it read like an already-filled value.**
package/dist/index.d.mts CHANGED
@@ -394,8 +394,21 @@ interface FormFieldProps extends Omit<TextInputProps, 'style'> {
394
394
  required?: boolean;
395
395
  error?: string;
396
396
  containerStyle?: ViewStyle;
397
+ /**
398
+ * OPT-IN "recent values" behaviour. When set, the values submitted through this field are
399
+ * remembered (per this key) and offered in a dropdown on focus; picking one fills the input.
400
+ * Values are recorded on submit (Enter) and on blur-with-content. Persisted to `localStorage`
401
+ * under `@dloizides/ui-forms:recent:<recentKey>`; a silent no-op on native / when storage is
402
+ * unavailable.
403
+ *
404
+ * Leave it UNSET (the default) and the field behaves exactly as before — nothing rendered, no
405
+ * storage touched. NEVER set it on a password / secure field: recents must not persist secrets.
406
+ */
407
+ recentKey?: string;
408
+ /** Cap on remembered values when {@link recentKey} is set (most-recent-first). Default 10. */
409
+ recentMax?: number;
397
410
  }
398
- declare const FormField: ({ label, labelHidden, required, error, containerStyle, ...textInputProps }: FormFieldProps) => React.ReactElement;
411
+ declare const FormField: ({ label, labelHidden, required, error, containerStyle, recentKey, recentMax, ...textInputProps }: FormFieldProps) => React.ReactElement;
399
412
 
400
413
  /**
401
414
  * `ThemedTextInput` — the shared, readable + lively text-input primitive. A thin `<TextInput>`
@@ -479,28 +492,57 @@ interface ThemedInput {
479
492
  }
480
493
  declare function useThemedInput(options?: UseThemedInputOptions): ThemedInput;
481
494
 
495
+ interface RecentValues {
496
+ /** The remembered values, most-recent-first (never longer than `max`; `[]` when storage is unavailable). */
497
+ recents: string[];
498
+ /** Fold a value into the list (trim / de-dupe / promote / cap) and persist. Empty values are ignored. */
499
+ remember: (value: string) => void;
500
+ /** Forget every remembered value for this key and clear it from storage. */
501
+ clear: () => void;
502
+ }
482
503
  /**
483
- * Chip/pill selector for selecting one or multiple options.
484
- *
485
- * Two visual variants (both fully theme-driven):
486
- * - `solid` (default) — the original filled-pill look: selected = solid primary fill with
487
- * white ink. Unchanged, so existing consumers (erevna / katalogos / kefi) render identically.
488
- * - `outline` — the AML v1 console look: an outlined pill on a muted fill; selected = a subtle
489
- * tinted-outline (primary border + primary ink + a low-alpha primary wash), NOT a solid fill.
490
- * Hover (web) lifts the border/ink to the primary colour.
491
- *
492
- * The label row, the error line and the container spacing come from the shared `Field` wrapper —
493
- * NOT from a local `<Text>`. Its own label used to drift from `Field` on three of four axes
494
- * (`marginBottom: 8` vs 4, no `fontSize` at all so ~14 vs 13, `colors.text` vs `textSecondary`),
495
- * so a `ChipSelector` next to a `FormField` in a row/grid started a different distance down the
496
- * column and read as a different weight of text. Now there is exactly one label implementation.
504
+ * @param key logical name for this input's history (namespaced under `@dloizides/ui-forms:recent:`).
505
+ * @param max most-recent-first cap on remembered values. Default {@link DEFAULT_MAX_RECENTS}.
506
+ */
507
+ declare function useRecentValues(key: string, max?: number): RecentValues;
508
+
509
+ /**
510
+ * `recentValuesCore` — the pure + storage-facing internals of {@link useRecentValues}, kept out of
511
+ * the hook file so the list algebra (trim / de-dupe / promote / cap) and the `localStorage` access
512
+ * are each unit-testable in isolation.
513
+ *
514
+ * ## RN-web storage reality
515
+ *
516
+ * `ui-forms` runs on react-native-web, so a component using this may mount on web (where
517
+ * `window.localStorage` exists), on native (where it does NOT), or under SSR / a hardened browser
518
+ * where touching `window.localStorage` THROWS (disabled cookies, privacy mode, quota). Every access
519
+ * therefore goes through {@link getStorage}, which returns `null` rather than throwing, and every
520
+ * read/write is wrapped so a storage failure degrades to an in-memory-only no-op instead of
521
+ * exploding inside render. On native / when storage is unavailable the feature is simply inert and
522
+ * the recents list is always `[]`.
523
+ */
524
+ /** Default cap on remembered values (most-recent-first). */
525
+ declare const DEFAULT_MAX_RECENTS = 10;
526
+
527
+ /**
528
+ * Public + internal types for ChipSelector. Split out of `ChipSelector.tsx` so the component, its
529
+ * two chip variants and the radio keyboard hook can share them without a circular import.
497
530
  */
498
531
 
499
532
  /** Visual variant. `solid` = filled selected pill (default); `outline` = v1 tinted-outline. */
500
533
  type ChipVariant = 'solid' | 'outline';
534
+ /**
535
+ * Role of a SINGLE-select chip. `button` (default) = today's semantics; `radio` = opt-in
536
+ * `radiogroup` of `radio` chips carrying `aria-checked`. Ignored when `multiple` is set.
537
+ * A string union rather than a `const enum` to match `ChipVariant`: a const enum does not
538
+ * survive the package boundary for consumers compiled with `isolatedModules`.
539
+ */
540
+ type ChipSingleSelectRole = 'button' | 'radio';
501
541
  interface ChipOption<T> {
502
542
  value: T;
503
543
  label: string;
544
+ /** Optional decorative icon rendered before the label; hidden from assistive tech. */
545
+ icon?: React.ReactNode;
504
546
  }
505
547
  interface ChipSelectorProps<T> {
506
548
  /** Optional — with no label, no label row is rendered (no phantom gap above the chips). */
@@ -540,8 +582,37 @@ interface ChipSelectorProps<T> {
540
582
  * consumers keep their current announcement.
541
583
  */
542
584
  optionAccessibilityHint?: string;
585
+ /**
586
+ * Opt-in radio semantics for a SINGLE-select group: the group becomes `role="radiogroup"` and
587
+ * each chip `role="radio"` + `aria-checked`, with the WAI-ARIA radio group keyboard pattern
588
+ * (Space activates, arrow keys move focus + selection with wrap, one roving tab stop).
589
+ * Defaults to `button` (unchanged behaviour). Ignored when `multiple` is set — a multi chip
590
+ * stays a toggle button with `aria-pressed`.
591
+ */
592
+ singleSelectRole?: ChipSingleSelectRole;
543
593
  }
544
- declare const ChipSelector: <T extends string | number>({ label, options, value, onChange, multiple, disabled, variant, containerStyle, spacing, required, error, testID, chipTestIDPrefix, optionAccessibilityHint, }: ChipSelectorProps<T>) => React.ReactElement;
594
+
595
+ /**
596
+ * Chip/pill selector for selecting one or multiple options.
597
+ *
598
+ * Two visual variants (both fully theme-driven):
599
+ * - `solid` (default) — the original filled-pill look: selected = solid primary fill with
600
+ * white ink. Unchanged, so existing consumers (erevna / katalogos / kefi) render identically.
601
+ * - `outline` — the AML v1 console look: an outlined pill on a muted fill; selected = a subtle
602
+ * tinted-outline (primary border + primary ink + a low-alpha primary wash), NOT a solid fill.
603
+ * Hover (web) lifts the border/ink to the primary colour.
604
+ *
605
+ * The label row, the error line and the container spacing come from the shared `Field` wrapper —
606
+ * NOT from a local `<Text>`. Its own label used to drift from `Field` on three of four axes
607
+ * (`marginBottom: 8` vs 4, no `fontSize` at all so ~14 vs 13, `colors.text` vs `textSecondary`),
608
+ * so a `ChipSelector` next to a `FormField` in a row/grid started a different distance down the
609
+ * column and read as a different weight of text. Now there is exactly one label implementation.
610
+ *
611
+ * Structure: chip variants in `components/`, the radio keyboard wiring in `hooks/`, and the pure
612
+ * resolvers (`chipIdentity`, colours, radio key logic) in `utils/`.
613
+ */
614
+
615
+ declare const ChipSelector: <T extends string | number>({ label, options, value, onChange, multiple, disabled, variant, containerStyle, spacing, required, error, testID, chipTestIDPrefix, optionAccessibilityHint, singleSelectRole, }: ChipSelectorProps<T>) => React.ReactElement;
545
616
 
546
617
  /**
547
618
  * Reusable form switch/toggle with an optional description.
@@ -770,6 +841,12 @@ interface AnchoredMenuProps {
770
841
  colors: AnchoredMenuColors;
771
842
  /** PRE-LOCALIZED accessibility hint applied to every option. */
772
843
  optionHint: string;
844
+ /**
845
+ * PRE-LOCALIZED accessible NAME for the menu container itself (e.g. "Recent values"). Optional and
846
+ * additive — omitted, the menu keeps only its `role="menu"` as before, so existing callers are
847
+ * unaffected. Supplied, a screen reader announces the list's purpose, not just "menu".
848
+ */
849
+ accessibilityLabel?: string;
773
850
  /** Base testID: the menu is `${testID}-menu`, each option `${testID}-option-${value}`. */
774
851
  testID: string;
775
852
  /** Node whose clicks count as "inside" (the anchor) so its own press doesn't self-dismiss. */
@@ -788,7 +865,7 @@ interface AnchoredMenuProps {
788
865
  */
789
866
  usePortal?: boolean;
790
867
  }
791
- declare function AnchoredMenu({ options, selectedValue, onSelect, onDismiss, colors, optionHint, testID, anchorRef, usePortal, }: AnchoredMenuProps): React.ReactElement;
868
+ declare function AnchoredMenu({ options, selectedValue, onSelect, onDismiss, colors, optionHint, accessibilityLabel, testID, anchorRef, usePortal, }: AnchoredMenuProps): React.ReactElement;
792
869
 
793
870
  declare const controlStyles: {
794
871
  /**
@@ -893,4 +970,4 @@ declare function suggestOptions(options: readonly ControlOption[], query: string
893
970
  /** True when `text` is non-empty yet matches no option's value or label exactly (case-insensitive). */
894
971
  declare function isUnmatched(options: readonly ControlOption[], text: string): boolean;
895
972
 
896
- export { AnchoredMenu, type AnchoredMenuColors, type AnchoredMenuProps, type ChipOption, ChipSelector, type ChipSelectorProps, type ChipVariant, type ControlOption, DEFAULT_OPTIONAL_LABEL, DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS, DEFAULT_TYPEAHEAD_MIN_CHARS, DateRangeControl, type DateRangeControlProps, type DateRangeValue, Field, type FieldChildContext, type FieldChildren, type FieldLabelVariant, type FieldMarker, type FieldProps, type FieldSpacing, FormActions, type FormActionsProps, FormCell, type FormCellProps, FormCheckbox, type FormCheckboxProps, FormField, type FormFieldProps, FormGrid, type FormGridProps, FormSection, type FormSectionProps, FormSwitch, type FormSwitchProps, SelectControl, type SelectControlProps, type ThemedInput, ThemedTextInput, type ThemedTextInputProps, TypeaheadControl, type TypeaheadControlProps, type UseThemedInputOptions, controlStyles, isUnmatched, suggestOptions, useThemedInput };
973
+ export { AnchoredMenu, type AnchoredMenuColors, type AnchoredMenuProps, type ChipOption, ChipSelector, type ChipSelectorProps, type ChipSingleSelectRole, type ChipVariant, type ControlOption, DEFAULT_MAX_RECENTS, DEFAULT_OPTIONAL_LABEL, DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS, DEFAULT_TYPEAHEAD_MIN_CHARS, DateRangeControl, type DateRangeControlProps, type DateRangeValue, Field, type FieldChildContext, type FieldChildren, type FieldLabelVariant, type FieldMarker, type FieldProps, type FieldSpacing, FormActions, type FormActionsProps, FormCell, type FormCellProps, FormCheckbox, type FormCheckboxProps, FormField, type FormFieldProps, FormGrid, type FormGridProps, FormSection, type FormSectionProps, FormSwitch, type FormSwitchProps, type RecentValues, SelectControl, type SelectControlProps, type ThemedInput, ThemedTextInput, type ThemedTextInputProps, TypeaheadControl, type TypeaheadControlProps, type UseThemedInputOptions, controlStyles, isUnmatched, suggestOptions, useRecentValues, useThemedInput };
package/dist/index.d.ts CHANGED
@@ -394,8 +394,21 @@ interface FormFieldProps extends Omit<TextInputProps, 'style'> {
394
394
  required?: boolean;
395
395
  error?: string;
396
396
  containerStyle?: ViewStyle;
397
+ /**
398
+ * OPT-IN "recent values" behaviour. When set, the values submitted through this field are
399
+ * remembered (per this key) and offered in a dropdown on focus; picking one fills the input.
400
+ * Values are recorded on submit (Enter) and on blur-with-content. Persisted to `localStorage`
401
+ * under `@dloizides/ui-forms:recent:<recentKey>`; a silent no-op on native / when storage is
402
+ * unavailable.
403
+ *
404
+ * Leave it UNSET (the default) and the field behaves exactly as before — nothing rendered, no
405
+ * storage touched. NEVER set it on a password / secure field: recents must not persist secrets.
406
+ */
407
+ recentKey?: string;
408
+ /** Cap on remembered values when {@link recentKey} is set (most-recent-first). Default 10. */
409
+ recentMax?: number;
397
410
  }
398
- declare const FormField: ({ label, labelHidden, required, error, containerStyle, ...textInputProps }: FormFieldProps) => React.ReactElement;
411
+ declare const FormField: ({ label, labelHidden, required, error, containerStyle, recentKey, recentMax, ...textInputProps }: FormFieldProps) => React.ReactElement;
399
412
 
400
413
  /**
401
414
  * `ThemedTextInput` — the shared, readable + lively text-input primitive. A thin `<TextInput>`
@@ -479,28 +492,57 @@ interface ThemedInput {
479
492
  }
480
493
  declare function useThemedInput(options?: UseThemedInputOptions): ThemedInput;
481
494
 
495
+ interface RecentValues {
496
+ /** The remembered values, most-recent-first (never longer than `max`; `[]` when storage is unavailable). */
497
+ recents: string[];
498
+ /** Fold a value into the list (trim / de-dupe / promote / cap) and persist. Empty values are ignored. */
499
+ remember: (value: string) => void;
500
+ /** Forget every remembered value for this key and clear it from storage. */
501
+ clear: () => void;
502
+ }
482
503
  /**
483
- * Chip/pill selector for selecting one or multiple options.
484
- *
485
- * Two visual variants (both fully theme-driven):
486
- * - `solid` (default) — the original filled-pill look: selected = solid primary fill with
487
- * white ink. Unchanged, so existing consumers (erevna / katalogos / kefi) render identically.
488
- * - `outline` — the AML v1 console look: an outlined pill on a muted fill; selected = a subtle
489
- * tinted-outline (primary border + primary ink + a low-alpha primary wash), NOT a solid fill.
490
- * Hover (web) lifts the border/ink to the primary colour.
491
- *
492
- * The label row, the error line and the container spacing come from the shared `Field` wrapper —
493
- * NOT from a local `<Text>`. Its own label used to drift from `Field` on three of four axes
494
- * (`marginBottom: 8` vs 4, no `fontSize` at all so ~14 vs 13, `colors.text` vs `textSecondary`),
495
- * so a `ChipSelector` next to a `FormField` in a row/grid started a different distance down the
496
- * column and read as a different weight of text. Now there is exactly one label implementation.
504
+ * @param key logical name for this input's history (namespaced under `@dloizides/ui-forms:recent:`).
505
+ * @param max most-recent-first cap on remembered values. Default {@link DEFAULT_MAX_RECENTS}.
506
+ */
507
+ declare function useRecentValues(key: string, max?: number): RecentValues;
508
+
509
+ /**
510
+ * `recentValuesCore` — the pure + storage-facing internals of {@link useRecentValues}, kept out of
511
+ * the hook file so the list algebra (trim / de-dupe / promote / cap) and the `localStorage` access
512
+ * are each unit-testable in isolation.
513
+ *
514
+ * ## RN-web storage reality
515
+ *
516
+ * `ui-forms` runs on react-native-web, so a component using this may mount on web (where
517
+ * `window.localStorage` exists), on native (where it does NOT), or under SSR / a hardened browser
518
+ * where touching `window.localStorage` THROWS (disabled cookies, privacy mode, quota). Every access
519
+ * therefore goes through {@link getStorage}, which returns `null` rather than throwing, and every
520
+ * read/write is wrapped so a storage failure degrades to an in-memory-only no-op instead of
521
+ * exploding inside render. On native / when storage is unavailable the feature is simply inert and
522
+ * the recents list is always `[]`.
523
+ */
524
+ /** Default cap on remembered values (most-recent-first). */
525
+ declare const DEFAULT_MAX_RECENTS = 10;
526
+
527
+ /**
528
+ * Public + internal types for ChipSelector. Split out of `ChipSelector.tsx` so the component, its
529
+ * two chip variants and the radio keyboard hook can share them without a circular import.
497
530
  */
498
531
 
499
532
  /** Visual variant. `solid` = filled selected pill (default); `outline` = v1 tinted-outline. */
500
533
  type ChipVariant = 'solid' | 'outline';
534
+ /**
535
+ * Role of a SINGLE-select chip. `button` (default) = today's semantics; `radio` = opt-in
536
+ * `radiogroup` of `radio` chips carrying `aria-checked`. Ignored when `multiple` is set.
537
+ * A string union rather than a `const enum` to match `ChipVariant`: a const enum does not
538
+ * survive the package boundary for consumers compiled with `isolatedModules`.
539
+ */
540
+ type ChipSingleSelectRole = 'button' | 'radio';
501
541
  interface ChipOption<T> {
502
542
  value: T;
503
543
  label: string;
544
+ /** Optional decorative icon rendered before the label; hidden from assistive tech. */
545
+ icon?: React.ReactNode;
504
546
  }
505
547
  interface ChipSelectorProps<T> {
506
548
  /** Optional — with no label, no label row is rendered (no phantom gap above the chips). */
@@ -540,8 +582,37 @@ interface ChipSelectorProps<T> {
540
582
  * consumers keep their current announcement.
541
583
  */
542
584
  optionAccessibilityHint?: string;
585
+ /**
586
+ * Opt-in radio semantics for a SINGLE-select group: the group becomes `role="radiogroup"` and
587
+ * each chip `role="radio"` + `aria-checked`, with the WAI-ARIA radio group keyboard pattern
588
+ * (Space activates, arrow keys move focus + selection with wrap, one roving tab stop).
589
+ * Defaults to `button` (unchanged behaviour). Ignored when `multiple` is set — a multi chip
590
+ * stays a toggle button with `aria-pressed`.
591
+ */
592
+ singleSelectRole?: ChipSingleSelectRole;
543
593
  }
544
- declare const ChipSelector: <T extends string | number>({ label, options, value, onChange, multiple, disabled, variant, containerStyle, spacing, required, error, testID, chipTestIDPrefix, optionAccessibilityHint, }: ChipSelectorProps<T>) => React.ReactElement;
594
+
595
+ /**
596
+ * Chip/pill selector for selecting one or multiple options.
597
+ *
598
+ * Two visual variants (both fully theme-driven):
599
+ * - `solid` (default) — the original filled-pill look: selected = solid primary fill with
600
+ * white ink. Unchanged, so existing consumers (erevna / katalogos / kefi) render identically.
601
+ * - `outline` — the AML v1 console look: an outlined pill on a muted fill; selected = a subtle
602
+ * tinted-outline (primary border + primary ink + a low-alpha primary wash), NOT a solid fill.
603
+ * Hover (web) lifts the border/ink to the primary colour.
604
+ *
605
+ * The label row, the error line and the container spacing come from the shared `Field` wrapper —
606
+ * NOT from a local `<Text>`. Its own label used to drift from `Field` on three of four axes
607
+ * (`marginBottom: 8` vs 4, no `fontSize` at all so ~14 vs 13, `colors.text` vs `textSecondary`),
608
+ * so a `ChipSelector` next to a `FormField` in a row/grid started a different distance down the
609
+ * column and read as a different weight of text. Now there is exactly one label implementation.
610
+ *
611
+ * Structure: chip variants in `components/`, the radio keyboard wiring in `hooks/`, and the pure
612
+ * resolvers (`chipIdentity`, colours, radio key logic) in `utils/`.
613
+ */
614
+
615
+ declare const ChipSelector: <T extends string | number>({ label, options, value, onChange, multiple, disabled, variant, containerStyle, spacing, required, error, testID, chipTestIDPrefix, optionAccessibilityHint, singleSelectRole, }: ChipSelectorProps<T>) => React.ReactElement;
545
616
 
546
617
  /**
547
618
  * Reusable form switch/toggle with an optional description.
@@ -770,6 +841,12 @@ interface AnchoredMenuProps {
770
841
  colors: AnchoredMenuColors;
771
842
  /** PRE-LOCALIZED accessibility hint applied to every option. */
772
843
  optionHint: string;
844
+ /**
845
+ * PRE-LOCALIZED accessible NAME for the menu container itself (e.g. "Recent values"). Optional and
846
+ * additive — omitted, the menu keeps only its `role="menu"` as before, so existing callers are
847
+ * unaffected. Supplied, a screen reader announces the list's purpose, not just "menu".
848
+ */
849
+ accessibilityLabel?: string;
773
850
  /** Base testID: the menu is `${testID}-menu`, each option `${testID}-option-${value}`. */
774
851
  testID: string;
775
852
  /** Node whose clicks count as "inside" (the anchor) so its own press doesn't self-dismiss. */
@@ -788,7 +865,7 @@ interface AnchoredMenuProps {
788
865
  */
789
866
  usePortal?: boolean;
790
867
  }
791
- declare function AnchoredMenu({ options, selectedValue, onSelect, onDismiss, colors, optionHint, testID, anchorRef, usePortal, }: AnchoredMenuProps): React.ReactElement;
868
+ declare function AnchoredMenu({ options, selectedValue, onSelect, onDismiss, colors, optionHint, accessibilityLabel, testID, anchorRef, usePortal, }: AnchoredMenuProps): React.ReactElement;
792
869
 
793
870
  declare const controlStyles: {
794
871
  /**
@@ -893,4 +970,4 @@ declare function suggestOptions(options: readonly ControlOption[], query: string
893
970
  /** True when `text` is non-empty yet matches no option's value or label exactly (case-insensitive). */
894
971
  declare function isUnmatched(options: readonly ControlOption[], text: string): boolean;
895
972
 
896
- export { AnchoredMenu, type AnchoredMenuColors, type AnchoredMenuProps, type ChipOption, ChipSelector, type ChipSelectorProps, type ChipVariant, type ControlOption, DEFAULT_OPTIONAL_LABEL, DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS, DEFAULT_TYPEAHEAD_MIN_CHARS, DateRangeControl, type DateRangeControlProps, type DateRangeValue, Field, type FieldChildContext, type FieldChildren, type FieldLabelVariant, type FieldMarker, type FieldProps, type FieldSpacing, FormActions, type FormActionsProps, FormCell, type FormCellProps, FormCheckbox, type FormCheckboxProps, FormField, type FormFieldProps, FormGrid, type FormGridProps, FormSection, type FormSectionProps, FormSwitch, type FormSwitchProps, SelectControl, type SelectControlProps, type ThemedInput, ThemedTextInput, type ThemedTextInputProps, TypeaheadControl, type TypeaheadControlProps, type UseThemedInputOptions, controlStyles, isUnmatched, suggestOptions, useThemedInput };
973
+ export { AnchoredMenu, type AnchoredMenuColors, type AnchoredMenuProps, type ChipOption, ChipSelector, type ChipSelectorProps, type ChipSingleSelectRole, type ChipVariant, type ControlOption, DEFAULT_MAX_RECENTS, DEFAULT_OPTIONAL_LABEL, DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS, DEFAULT_TYPEAHEAD_MIN_CHARS, DateRangeControl, type DateRangeControlProps, type DateRangeValue, Field, type FieldChildContext, type FieldChildren, type FieldLabelVariant, type FieldMarker, type FieldProps, type FieldSpacing, FormActions, type FormActionsProps, FormCell, type FormCellProps, FormCheckbox, type FormCheckboxProps, FormField, type FormFieldProps, FormGrid, type FormGridProps, FormSection, type FormSectionProps, FormSwitch, type FormSwitchProps, type RecentValues, SelectControl, type SelectControlProps, type ThemedInput, ThemedTextInput, type ThemedTextInputProps, TypeaheadControl, type TypeaheadControlProps, type UseThemedInputOptions, controlStyles, isUnmatched, suggestOptions, useRecentValues, useThemedInput };