@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 +41 -0
- package/dist/index.d.mts +95 -18
- package/dist/index.d.ts +95 -18
- package/dist/index.js +519 -243
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +520 -246
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
-
*
|
|
484
|
-
*
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
*
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
484
|
-
*
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
*
|
|
492
|
-
*
|
|
493
|
-
*
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
*
|
|
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
|
-
|
|
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 };
|