asma-ui-core 3.111.0 → 3.113.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/dist/asma-ui-core.css +1 -1
- package/dist/components/inputs/dynamic-select/components/DynamicSelectAutocomplete.js +95 -93
- package/dist/components/inputs/full-screen-picker/FullScreenPicker.js +93 -0
- package/dist/components/inputs/full-screen-picker/PickerLiveRegion.js +34 -0
- package/dist/components/inputs/full-screen-picker/pickerCopy.js +34 -0
- package/dist/components/inputs/full-screen-picker/useVisualViewportHeight.js +10 -0
- package/dist/components/inputs/input-field/StyledInputField.js +147 -157
- package/dist/components/inputs/phone-field/CountryCodeOptions.js +28 -24
- package/dist/components/inputs/phone-field/CountryCodeSelect.js +82 -75
- package/dist/components/inputs/select-autocomplete/SelectAutocompletePicker.js +217 -0
- package/dist/components/inputs/select-autocomplete/StyledSelectAutocomplete.js +270 -220
- package/dist/components/inputs/select-autocomplete/draftChanges.js +24 -0
- package/dist/components/inputs/select-autocomplete/listboxCursor.js +7 -0
- package/dist/components/inputs/select-autocomplete/readFieldName.js +18 -0
- package/dist/components/inputs/textarea/StyledTextarea.js +46 -47
- package/dist/hooks/useMediaQuery.hook.js +12 -8
- package/dist/index.js +137 -133
- package/dist/src/components/inputs/dynamic-select/StyledDynamicSelect.d.ts +4 -1
- package/dist/src/components/inputs/full-screen-picker/FullScreenPicker.d.ts +62 -0
- package/dist/src/components/inputs/full-screen-picker/PickerLiveRegion.d.ts +31 -0
- package/dist/src/components/inputs/full-screen-picker/index.d.ts +2 -0
- package/dist/src/components/inputs/full-screen-picker/pickerCopy.d.ts +29 -0
- package/dist/src/components/inputs/full-screen-picker/useVisualViewportHeight.d.ts +8 -0
- package/dist/src/components/inputs/input-field/StyledInputField.d.ts +4 -1
- package/dist/src/components/inputs/phone-field/CountryCodeOptions.d.ts +9 -1
- package/dist/src/components/inputs/phone-field/CountryCodeSelect.d.ts +4 -3
- package/dist/src/components/inputs/phone-field/useCountryPicker.d.ts +2 -1
- package/dist/src/components/inputs/select-autocomplete/SelectAutocompletePicker.d.ts +52 -0
- package/dist/src/components/inputs/select-autocomplete/StyledSelectAutocomplete.d.ts +21 -2
- package/dist/src/components/inputs/select-autocomplete/draftChanges.d.ts +17 -0
- package/dist/src/components/inputs/select-autocomplete/listboxCursor.d.ts +9 -0
- package/dist/src/components/inputs/select-autocomplete/readFieldName.d.ts +13 -0
- package/dist/src/helpers/CharacterCounter.d.ts +2 -1
- package/dist/src/hooks/useMediaQuery.hook.d.ts +6 -0
- package/dist/src/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { DialogCloseReason } from '../../feedback/dialog/StyledDialog';
|
|
3
|
+
import { PickerAnnouncement } from './PickerLiveRegion';
|
|
4
|
+
export type FullScreenPickerCloseReason = DialogCloseReason | 'closeButton';
|
|
5
|
+
export interface FullScreenPickerProps {
|
|
6
|
+
open: boolean;
|
|
7
|
+
/** Close button, Escape and native Back. Always a cancel: the caller discards anything not applied. */
|
|
8
|
+
onClose: (reason: FullScreenPickerCloseReason) => void;
|
|
9
|
+
dataTest: string;
|
|
10
|
+
/** The field label. Wraps onto as many lines as it needs; it is never truncated. */
|
|
11
|
+
title?: ReactNode;
|
|
12
|
+
/** Accessible name of the dialog when there is no `title`. */
|
|
13
|
+
fallbackName?: string;
|
|
14
|
+
/** Accessible name of the close button. */
|
|
15
|
+
closeLabel: string;
|
|
16
|
+
/** The search field — rendered full width under the title, or beside it on a short viewport. */
|
|
17
|
+
search: ReactNode;
|
|
18
|
+
/** The selection row (several choices) or the clear row (one choice). Part of the fixed header. */
|
|
19
|
+
headerRow?: ReactNode;
|
|
20
|
+
/** The list. It is the only part that scrolls. */
|
|
21
|
+
children: ReactNode;
|
|
22
|
+
/** Polite announcement rendered inside the dialog (counts, matches, clears). */
|
|
23
|
+
announcement?: PickerAnnouncement;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* @figmaNode wXrXt5uKNNzV2DnQCgyYZH#45614-217265
|
|
27
|
+
* Figma "Select mobile full-screen picker": a full-screen sheet with a fixed **Header** (title, close,
|
|
28
|
+
* search, optional selection/clear row; 1 px `border/separator` delta-200 under it) and one scrolling
|
|
29
|
+
* **List**. Title = Mobile/Page title, SemiBold 20/28, `text-icon/title-label` delta-800, wraps.
|
|
30
|
+
* Close = 40 × 40 Quaternary button with a 24 px ×. Search row = `pt-8 px-16`. On a short viewport
|
|
31
|
+
* (`Variant2`, ≤ 480 px high) title, search (max 240 px) and close share the first row.
|
|
32
|
+
*
|
|
33
|
+
* The shared shell for every full-screen picker in ui-core: `StyledSelectAutocomplete` and
|
|
34
|
+
* `CountryCodeSelect` both render through it (ASMA-8468). Presentation only — the caller owns the
|
|
35
|
+
* query, the list, the keyboard and what closing means. Nothing is focused for typing on open, so
|
|
36
|
+
* the on-screen keyboard appears only when the user taps the search field (REQ-006). Opened from
|
|
37
|
+
* the keyboard, focus goes to the `listbox` in `children` when it is a Tab stop (else to the close
|
|
38
|
+
* button), where the arrows work at once. Native Back comes from `StyledDialog` (D-004).
|
|
39
|
+
*
|
|
40
|
+
* For a project's own picker (exported from `asma-ui-core`): render it below the same breakpoint
|
|
41
|
+
* as the selects (`max-width: 743px` or `max-height: 480px`); pass the search field and the list;
|
|
42
|
+
* make the list a `role="listbox"` with `tabIndex={0}` and `aria-activedescendant` if it should
|
|
43
|
+
* take keyboard focus on open; announce counts with `useAnnouncer`.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* const [announcement, announce] = useAnnouncer()
|
|
47
|
+
* <FullScreenPicker
|
|
48
|
+
* open={open}
|
|
49
|
+
* onClose={() => setOpen(false)} // ×, Escape and Back: a cancel
|
|
50
|
+
* dataTest='templates-picker'
|
|
51
|
+
* title='Add questionnaires'
|
|
52
|
+
* closeLabel='Close'
|
|
53
|
+
* search={<StyledSearchField dataTest='templates-search' label='Search' value={query} fullWidth onChange={…} />}
|
|
54
|
+
* headerRow={<MySelectionRow />} // optional: count, clear, Done
|
|
55
|
+
* announcement={announcement}
|
|
56
|
+
* >
|
|
57
|
+
* <ul role='listbox' aria-label='Questionnaires' tabIndex={0} aria-activedescendant={activeId}>…</ul>
|
|
58
|
+
* </FullScreenPicker>
|
|
59
|
+
*
|
|
60
|
+
* @see asma-modules/_docs/frontend/plans/2026-10-19-11-04-plan-full-screen-select-picker-phones.md:203 — TASK-004
|
|
61
|
+
*/
|
|
62
|
+
export declare const FullScreenPicker: ({ open, onClose, dataTest, title, fallbackName, ...sheet }: FullScreenPickerProps) => JSX.Element;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** One message for a live region. `id` changes on every `announce`, so a repeated text is read again. */
|
|
2
|
+
export interface PickerAnnouncement {
|
|
3
|
+
text: string;
|
|
4
|
+
id: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Holds the latest announcement for `FullScreenPicker`'s `announcement` prop, which a screen reader
|
|
8
|
+
* reads out politely from inside the dialog (counts, matches, *No matches*). `announce` accepts the
|
|
9
|
+
* same text twice and still re-announces it; `reset` forgets it, so the next opening starts silent.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const [announcement, announce, resetAnnouncement] = useAnnouncer()
|
|
13
|
+
* // on a tick: announce(`${ticked.length} selected`); when the picker opens: resetAnnouncement()
|
|
14
|
+
* <FullScreenPicker announcement={announcement} … />
|
|
15
|
+
*/
|
|
16
|
+
export declare const useAnnouncer: () => [PickerAnnouncement | undefined, (text: string) => void, () => void];
|
|
17
|
+
/**
|
|
18
|
+
* Polite live region for the picker (ASMA-8468 REQ-011/013/016). Inside the dialog it must be
|
|
19
|
+
* rendered **in** the dialog: while `showModal()` is active everything outside is inert and not
|
|
20
|
+
* reliably announced (ALT-005).
|
|
21
|
+
*
|
|
22
|
+
* The text is emptied and set again on the next frame, so the same message twice in a row
|
|
23
|
+
* (`0 valgt` after two clears) is read out again. Both steps write the DOM directly, not React
|
|
24
|
+
* state: two state updates that land before React renders merge into "no change", and an unchanged
|
|
25
|
+
* region is not read out again. The frame's delay also lets a closing dialog leave the top layer
|
|
26
|
+
* first, so a message set as it closes is heard.
|
|
27
|
+
*/
|
|
28
|
+
export declare const PickerLiveRegion: ({ announcement, dataTest, }: {
|
|
29
|
+
announcement?: PickerAnnouncement;
|
|
30
|
+
dataTest?: string;
|
|
31
|
+
}) => JSX.Element;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { UiCoreLocale } from '../../../helpers/uiCoreLocale';
|
|
2
|
+
/**
|
|
3
|
+
* Every string the full-screen picker shows or announces (ASMA-8468). ui-core ships Norwegian and
|
|
4
|
+
* English defaults; a consumer overrides any of them through `pickerText`.
|
|
5
|
+
*
|
|
6
|
+
* @see asma-modules/_docs/frontend/plans/2026-10-19-11-04-plan-full-screen-select-picker-phones.md:206 — TASK-007
|
|
7
|
+
*/
|
|
8
|
+
export interface PickerText {
|
|
9
|
+
/** Accessible name of the close button. */
|
|
10
|
+
close: string;
|
|
11
|
+
/** Label of the search field. */
|
|
12
|
+
search: string;
|
|
13
|
+
/** Several choices: applies the ticks and closes. */
|
|
14
|
+
done: string;
|
|
15
|
+
/** One choice, optional field: empties the field. */
|
|
16
|
+
clearOne: string;
|
|
17
|
+
/** Several choices: unticks everything, including ticks hidden by the search. */
|
|
18
|
+
clearAll: string;
|
|
19
|
+
selectedCount: (count: number) => string;
|
|
20
|
+
noMatches: string;
|
|
21
|
+
matchCount: (count: number) => string;
|
|
22
|
+
/** Announced after `clearOne`. */
|
|
23
|
+
cleared: string;
|
|
24
|
+
/** Announced after `clearAll`. */
|
|
25
|
+
clearedAll: string;
|
|
26
|
+
truncated: (shown: number, total: number) => string;
|
|
27
|
+
}
|
|
28
|
+
/** Default picker copy for `locale`, with any consumer overrides applied on top. */
|
|
29
|
+
export declare const getPickerText: (locale: UiCoreLocale, overrides?: Partial<PickerText>) => PickerText;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The visible height in CSS px — the part of the screen the on-screen keyboard does not cover.
|
|
3
|
+
*
|
|
4
|
+
* iOS Safari keeps `100%`/`dvh` at the full layout height while the keyboard is up, so a list sized
|
|
5
|
+
* by CSS alone ends behind the keyboard. The picker sizes its column with this instead (ASMA-8468
|
|
6
|
+
* REQ-008, RISK-004 — verify on a real device).
|
|
7
|
+
*/
|
|
8
|
+
export declare const useVisualViewportHeight: () => number;
|
|
@@ -44,7 +44,10 @@ export interface StyledInputFieldProps {
|
|
|
44
44
|
expandHelperText?: boolean;
|
|
45
45
|
/** Character limit; also readable from `slotProps.htmlInput.maxLength`. */
|
|
46
46
|
maxLength?: number;
|
|
47
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* Count against `maxLength`, on by default whenever the field has a limit (WID-12). Pass `false`
|
|
49
|
+
* for a fixed format such as a postal code, whose length the label or hint already states.
|
|
50
|
+
*/
|
|
48
51
|
counter?: boolean;
|
|
49
52
|
/** Language of the counter text. */
|
|
50
53
|
locale?: UiCoreLocale;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { KeyboardEvent } from 'react';
|
|
1
2
|
import { PhoneCountryChoice, RenderCountryFlag } from './types';
|
|
2
3
|
export interface CountryCodeOptionsProps {
|
|
3
4
|
dataTest: string;
|
|
@@ -12,9 +13,16 @@ export interface CountryCodeOptionsProps {
|
|
|
12
13
|
label: string;
|
|
13
14
|
renderFlag?: RenderCountryFlag;
|
|
14
15
|
className?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Makes the list a Tab stop of its own (the mobile sheet, ASMA-8468), driven by these keys and
|
|
18
|
+
* the 3 px active-row marker. Without it the list is only driven from the combobox (desktop).
|
|
19
|
+
*/
|
|
20
|
+
onKeyDown?: (event: KeyboardEvent<HTMLElement>) => void;
|
|
21
|
+
/** Tabbing into the list: put the active-row marker on a row. */
|
|
22
|
+
onFocus?: () => void;
|
|
15
23
|
}
|
|
16
24
|
/**
|
|
17
25
|
* The country listbox. Presentation only — filtering, the active row and the keyboard live in
|
|
18
26
|
* [[useCountryPicker]], so the desktop trigger and the mobile sheet render the same list.
|
|
19
27
|
*/
|
|
20
|
-
export declare const CountryCodeOptions: ({ dataTest, visible, selectedIso2, activeIndex, optionId, onSelect, listId, label, renderFlag, className, }: CountryCodeOptionsProps) => JSX.Element;
|
|
28
|
+
export declare const CountryCodeOptions: ({ dataTest, visible, selectedIso2, activeIndex, optionId, onSelect, listId, label, renderFlag, className, onKeyDown, onFocus, }: CountryCodeOptionsProps) => JSX.Element;
|
|
@@ -23,8 +23,9 @@ export interface CountryCodeSelectProps {
|
|
|
23
23
|
* - **Desktop** — the trigger *is* the combobox. Opening it turns the calling-code slot into an
|
|
24
24
|
* input and typing filters the list below, which is what Figma draws (the open trigger carries a
|
|
25
25
|
* text cursor, and the menu holds rows only — node 8565:284950 has no search field).
|
|
26
|
-
* - **Mobile** — a full-screen sheet with its own search box, per node 8699:112423
|
|
27
|
-
* `
|
|
28
|
-
*
|
|
26
|
+
* - **Mobile** — a full-screen sheet with its own search box, per node 8699:112423, drawn by the
|
|
27
|
+
* shared `FullScreenPicker` (ASMA-8468). The break is the selects' picker break — below 744 px
|
|
28
|
+
* wide **or** at most 480 px high (D-002) — so a landscape phone gets the sheet too, not a
|
|
29
|
+
* popover squeezed against the keyboard.
|
|
29
30
|
*/
|
|
30
31
|
export declare const CountryCodeSelect: ({ dataTest, countries, value, onChange, disabled, selectCountryLabel, searchPlaceholder, renderFlag, labelledBy, className, }: CountryCodeSelectProps) => JSX.Element;
|
|
@@ -18,7 +18,8 @@ export interface CountryPicker {
|
|
|
18
18
|
activeIndex: number | null;
|
|
19
19
|
optionId: (index: number) => string;
|
|
20
20
|
openWithKeyboard: (direction: -1 | 1) => void;
|
|
21
|
-
|
|
21
|
+
/** Chooses a country; `close = false` keeps the list open (Space). */
|
|
22
|
+
select: (iso2: string, close?: boolean) => void;
|
|
22
23
|
dismiss: () => void;
|
|
23
24
|
handleKeyDown: (event: KeyboardEvent<HTMLElement>) => void;
|
|
24
25
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ReactNode, SyntheticEvent } from 'react';
|
|
2
|
+
import { PickerText } from '../full-screen-picker/pickerCopy';
|
|
3
|
+
import { AutocompleteRenderOptionState, OptionLiProps } from './StyledSelectAutocomplete';
|
|
4
|
+
export interface SelectAutocompletePickerProps<T> {
|
|
5
|
+
open: boolean;
|
|
6
|
+
dataTest: string;
|
|
7
|
+
listboxId: string;
|
|
8
|
+
title?: ReactNode;
|
|
9
|
+
/** Plain-text field name: names the listbox, and the dialog when there is no `title`. */
|
|
10
|
+
name: string;
|
|
11
|
+
text: PickerText;
|
|
12
|
+
options: readonly T[];
|
|
13
|
+
multiple: boolean;
|
|
14
|
+
/** Current value: the option (or `null`) with one choice, the chosen options with several. */
|
|
15
|
+
value: T | null | readonly T[];
|
|
16
|
+
/** The field may be emptied: not `disableClearable`, not read-only. */
|
|
17
|
+
clearable: boolean;
|
|
18
|
+
isEqual: (a: T, b: T) => boolean;
|
|
19
|
+
isOptionDisabled: (option: T) => boolean;
|
|
20
|
+
getLabel: (option: T) => string;
|
|
21
|
+
getOptionKey?: (option: T) => string | number;
|
|
22
|
+
filterOptions?: (options: T[], state: {
|
|
23
|
+
inputValue: string;
|
|
24
|
+
}) => T[];
|
|
25
|
+
renderOptionRow: (props: OptionLiProps, option: T, state: AutocompleteRenderOptionState) => ReactNode;
|
|
26
|
+
optionRowClassName: string;
|
|
27
|
+
loading?: boolean;
|
|
28
|
+
loadingText: ReactNode;
|
|
29
|
+
noOptionsText: ReactNode;
|
|
30
|
+
allowSelectAll?: boolean;
|
|
31
|
+
selectAllLabel: string;
|
|
32
|
+
/**
|
|
33
|
+
* One choice: an option was chosen. The caller applies it, and closes when `close` is set — a tap
|
|
34
|
+
* or Enter; Space chooses and keeps the picker open, as in the attached list.
|
|
35
|
+
*/
|
|
36
|
+
onSelect: (event: SyntheticEvent, option: T, close: boolean) => void;
|
|
37
|
+
/** One choice: *Fjern valget*. The caller empties the field, closes and announces. */
|
|
38
|
+
onClear: (event: SyntheticEvent) => void;
|
|
39
|
+
/** Several choices: *Ferdig*. The caller applies the draft (see `getDraftChanges`) and closes. */
|
|
40
|
+
onApply: (event: SyntheticEvent, draft: T[]) => void;
|
|
41
|
+
/** Close button, Escape, Back: a cancel — nothing is applied. */
|
|
42
|
+
onCancel: () => void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The body of `StyledSelectAutocomplete` on a small viewport (ASMA-8468): its own search query
|
|
46
|
+
* (the field's text is left alone), filtering, the 50-row cap, the keyboard, and the choice rules —
|
|
47
|
+
* one choice closes on tap; several choices tick a draft that only *Ferdig* applies. The draft and
|
|
48
|
+
* the clear-row visibility are taken at the moment it opens (REQ-011).
|
|
49
|
+
*
|
|
50
|
+
* @see asma-modules/_docs/frontend/plans/2026-10-19-11-04-plan-full-screen-select-picker-phones.md:218 — TASK-012..018
|
|
51
|
+
*/
|
|
52
|
+
export declare function SelectAutocompletePicker<T>({ open, dataTest, listboxId, title, name, text, options, multiple, value, clearable, isEqual, isOptionDisabled, getLabel, getOptionKey, filterOptions, renderOptionRow, optionRowClassName, loading, loadingText, noOptionsText, allowSelectAll, selectAllLabel, onSelect, onClear, onApply, onCancel, }: SelectAutocompletePickerProps<T>): JSX.Element;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { CSSProperties, HTMLAttributes, KeyboardEvent, ReactNode, SyntheticEvent } from 'react';
|
|
2
2
|
import { FieldWidth } from '../field-styles';
|
|
3
|
+
import { PickerText } from '../full-screen-picker/pickerCopy';
|
|
3
4
|
export type AutocompleteChangeReason = 'createOption' | 'selectOption' | 'removeOption' | 'clear' | 'blur';
|
|
4
5
|
export type AutocompleteInputChangeReason = 'input' | 'reset' | 'clear';
|
|
5
6
|
export interface AutocompleteRenderOptionState {
|
|
6
7
|
selected: boolean;
|
|
7
8
|
index: number;
|
|
8
9
|
inputValue: string;
|
|
10
|
+
/** The row is drawn in the full-screen picker (ASMA-8468): show the full label, no line clamp. */
|
|
11
|
+
inPicker?: boolean;
|
|
9
12
|
}
|
|
10
13
|
/** Props the combobox hands to `renderInput`; spread straight onto `StyledInputField`. */
|
|
11
14
|
export interface AutocompleteRenderInputParams {
|
|
@@ -29,7 +32,7 @@ export interface AutocompleteRenderInputParams {
|
|
|
29
32
|
};
|
|
30
33
|
};
|
|
31
34
|
}
|
|
32
|
-
type OptionLiProps = HTMLAttributes<HTMLLIElement> & {
|
|
35
|
+
export type OptionLiProps = HTMLAttributes<HTMLLIElement> & {
|
|
33
36
|
key?: string;
|
|
34
37
|
ref?: React.Ref<HTMLLIElement>;
|
|
35
38
|
[dataAttr: `data-${string}`]: unknown;
|
|
@@ -128,6 +131,22 @@ export interface StyledSelectAutocompleteProps<T, Multiple extends boolean | und
|
|
|
128
131
|
};
|
|
129
132
|
};
|
|
130
133
|
sx?: unknown;
|
|
134
|
+
/**
|
|
135
|
+
* Title of the full-screen picker on a small viewport (ASMA-8468). Defaults to the field's label,
|
|
136
|
+
* read when the picker opens from the input's `<label>`, `aria-labelledby` or `aria-label`. With
|
|
137
|
+
* none, there is no title and the dialog and list are named by the placeholder, else by
|
|
138
|
+
* `pickerText.search`.
|
|
139
|
+
*/
|
|
140
|
+
pickerTitle?: ReactNode;
|
|
141
|
+
/** Overrides for any picker string (*Ferdig*, *Fjern valget*, counts, …). */
|
|
142
|
+
pickerText?: Partial<PickerText>;
|
|
143
|
+
/** Language of the default picker copy. Defaults to English, like the rest of ui-core. */
|
|
144
|
+
locale?: 'no' | 'en';
|
|
145
|
+
/**
|
|
146
|
+
* Keep the attached list on every viewport. By default the list opens as a full-screen picker
|
|
147
|
+
* below 744 CSS px wide or at most 480 CSS px high (ASMA-8468).
|
|
148
|
+
*/
|
|
149
|
+
disableFullScreenPicker?: boolean;
|
|
131
150
|
}
|
|
132
151
|
/**
|
|
133
152
|
* single + multiple selection (with tag chips + optional select-all), type-ahead filtering,
|
|
@@ -136,5 +155,5 @@ export interface StyledSelectAutocompleteProps<T, Multiple extends boolean | und
|
|
|
136
155
|
* ponytail: `freeSolo` is accepted (arbitrary input is emitted via onInputChange) but not turned
|
|
137
156
|
* into option values; exact keyboard-parity edge cases are Chromatic/axe-gated.
|
|
138
157
|
*/
|
|
139
|
-
export declare function StyledSelectAutocomplete<T, Multiple extends boolean | undefined = false, DisableClearable extends boolean | undefined = false, FreeSolo extends boolean | undefined = false>({ dataTest, options, renderInput, value, onChange, getOptionLabel, getOptionKey, isOptionEqualToValue, renderOption, renderValue, filterOptions, loading, loadingText, noOptionsText, disabled, readOnly, error, helperText, size, rowSize, disableClearable, disableCloseOnSelect, popupIcon, autoHeight, multiple, allowSelectAll, selectAllLabel, width, fullWidth: _fullWidth, classes, inputValue: controlledInput, onInputChange, open: controlledOpen, onOpen, onClose, className, wrapperClassName, getOptionDisabled, slotProps, }: StyledSelectAutocompleteProps<T, Multiple, DisableClearable, FreeSolo>): JSX.Element;
|
|
158
|
+
export declare function StyledSelectAutocomplete<T, Multiple extends boolean | undefined = false, DisableClearable extends boolean | undefined = false, FreeSolo extends boolean | undefined = false>({ dataTest, options, renderInput, value, onChange, getOptionLabel, getOptionKey, isOptionEqualToValue, renderOption, renderValue, filterOptions, loading, loadingText, noOptionsText, disabled, readOnly, error, helperText, size, rowSize, disableClearable, disableCloseOnSelect, popupIcon, autoHeight, multiple, allowSelectAll, selectAllLabel, width, fullWidth: _fullWidth, classes, inputValue: controlledInput, onInputChange, open: controlledOpen, onOpen, onClose, className, wrapperClassName, getOptionDisabled, slotProps, pickerTitle, pickerText, locale, disableFullScreenPicker, }: StyledSelectAutocompleteProps<T, Multiple, DisableClearable, FreeSolo>): JSX.Element;
|
|
140
159
|
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type DraftChange<T> = {
|
|
2
|
+
value: T[];
|
|
3
|
+
reason: 'removeOption' | 'selectOption';
|
|
4
|
+
option: T;
|
|
5
|
+
} | {
|
|
6
|
+
value: T[];
|
|
7
|
+
reason: 'clear';
|
|
8
|
+
option?: undefined;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* The `onChange` calls that turn `applied` into `draft` the way ticking in the attached list would
|
|
12
|
+
* have (ASMA-8468 D-007): one `removeOption`/`selectOption` per changed option, carrying
|
|
13
|
+
* `details.option`, so consumers that act per tick keep working. Removals come first, additions in
|
|
14
|
+
* the order they were ticked. Emptying a non-empty value is one `clear`, as the field's × does. No
|
|
15
|
+
* change, no calls.
|
|
16
|
+
*/
|
|
17
|
+
export declare const getDraftChanges: <T>(applied: readonly T[], draft: readonly T[], isEqual: (a: T, b: T) => boolean) => DraftChange<T>[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where ArrowUp/ArrowDown moves the keyboard cursor of a select listbox. Shared by the attached list
|
|
3
|
+
* and the full-screen picker (ASMA-8468), which must step the same way.
|
|
4
|
+
*
|
|
5
|
+
* `stops` are the cursor positions in order (`-1` is the *Select all* row). Without a cursor the
|
|
6
|
+
* move starts from `fallback` (the chosen option); from outside the stops it lands on the first or
|
|
7
|
+
* the last one. Clamped at both ends, no wrap-around. `null` when there is nowhere to go.
|
|
8
|
+
*/
|
|
9
|
+
export declare const nextActiveIndex: (stops: readonly number[], current: number | null, fallback: number, direction: -1 | 1) => number | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface FieldName {
|
|
2
|
+
/** The field's label: shown as the picker title. */
|
|
3
|
+
label: string;
|
|
4
|
+
/** What names the dialog and list when there is no label: the label, else the placeholder. */
|
|
5
|
+
name: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The field's name for the full-screen picker (ASMA-8468 TASK-015), in the order a browser names an
|
|
9
|
+
* input: its first `<label>`, else the elements named by `aria-labelledby`, else `aria-label` — a
|
|
10
|
+
* visible label that is not linked to the input usually reaches it that way (RISK-002). A
|
|
11
|
+
* placeholder only names the dialog and list, it is no title. Empty strings when there is nothing.
|
|
12
|
+
*/
|
|
13
|
+
export declare const readFieldName: (input: HTMLInputElement | null) => FieldName;
|
|
@@ -11,6 +11,7 @@ export interface CharacterCounterProps {
|
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* The count of a free-text field with a character limit, such as *12 av 100 tegn* (field width
|
|
14
|
-
* pattern WID-2,
|
|
14
|
+
* pattern WID-2, WID-12), so typed text is never cut without notice.
|
|
15
|
+
* @figmaNode wXrXt5uKNNzV2DnQCgyYZH#45907-218317
|
|
15
16
|
*/
|
|
16
17
|
export declare const CharacterCounter: ({ id, length, limit, locale, className }: CharacterCounterProps) => JSX.Element;
|
|
@@ -2,3 +2,9 @@ export declare function makeMediaQueryStore(mediaQuery: string): () => boolean;
|
|
|
2
2
|
export declare const useMobileMediaQuery: () => boolean;
|
|
3
3
|
/** A phone in landscape: too short for a sheet capped at 90vh to leave a usable body. */
|
|
4
4
|
export declare const useShortViewportMediaQuery: () => boolean;
|
|
5
|
+
/**
|
|
6
|
+
* ASMA-8468 REQ-001: a searchable select opens as a full-screen picker below 744 CSS px wide or at
|
|
7
|
+
* most 480 CSS px high. The height half is the same boundary as {@link useShortViewportMediaQuery}
|
|
8
|
+
* (D-003), so a landscape phone counts as "small" for every overlay.
|
|
9
|
+
*/
|
|
10
|
+
export declare const useFullScreenPickerMediaQuery: () => boolean;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export * from './components/inputs/search-field';
|
|
|
21
21
|
export * from './components/inputs/textarea';
|
|
22
22
|
export * from './components/inputs/select';
|
|
23
23
|
export * from './components/inputs/select-autocomplete';
|
|
24
|
+
export * from './components/inputs/full-screen-picker';
|
|
24
25
|
export * from './components/inputs/slider';
|
|
25
26
|
export * from './components/inputs/switch';
|
|
26
27
|
export * from './components/inputs/radio-button';
|