@cssints/headless 0.19.0 → 0.20.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/README.md +79 -2
- package/dist/index.d.mts +457 -203
- package/dist/index.mjs +877 -416
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1030,6 +1030,94 @@ export interface Checkbox {
|
|
|
1030
1030
|
* pass `value` + `onValueChange` to own the state.
|
|
1031
1031
|
*/
|
|
1032
1032
|
export declare const createCheckbox: (options?: CheckboxOptions) => Checkbox;
|
|
1033
|
+
export interface FieldOptions {
|
|
1034
|
+
/** Base of every id the field makes (`<id>-control`, `-label`, `-hint`, `-error`). */
|
|
1035
|
+
readonly id?: string | undefined;
|
|
1036
|
+
readonly required?: boolean | undefined;
|
|
1037
|
+
/**
|
|
1038
|
+
* `true` marks the control invalid; a string does too and is the error message
|
|
1039
|
+
* (unless `error` is set). `false` forces valid: an `error` is then not shown,
|
|
1040
|
+
* so a host can pass `touched() && failed()` and keep the message ready.
|
|
1041
|
+
* Left out, the field is invalid exactly when it has an error message.
|
|
1042
|
+
*/
|
|
1043
|
+
readonly invalid?: boolean | string | undefined;
|
|
1044
|
+
/** Help text; absent (or empty) means the hint element is hidden and not referenced. */
|
|
1045
|
+
readonly hint?: string | undefined;
|
|
1046
|
+
/** The error message; absent (or empty) means no error element. */
|
|
1047
|
+
readonly error?: string | undefined;
|
|
1048
|
+
/**
|
|
1049
|
+
* Ids of elements the host owns, appended to `aria-describedby` after the
|
|
1050
|
+
* field's own hint and error: a form-level error that belongs to several
|
|
1051
|
+
* controls ("the passwords do not match" names both). One id or a list;
|
|
1052
|
+
* empty strings are dropped, and the attribute is absent when nothing is left.
|
|
1053
|
+
* The host keeps that element rendered, and decides whether it is hidden.
|
|
1054
|
+
*/
|
|
1055
|
+
readonly describedby?: string | readonly string[] | undefined;
|
|
1056
|
+
}
|
|
1057
|
+
/** Spread onto the form control (`input`, `textarea`, `select`, or a custom widget). */
|
|
1058
|
+
export interface FieldControlProps {
|
|
1059
|
+
readonly id: string;
|
|
1060
|
+
/** The ids of the hint and the error that are shown, hint first, then the host's `describedby`; absent when there are none. */
|
|
1061
|
+
readonly "aria-describedby": string | undefined;
|
|
1062
|
+
readonly "aria-invalid": "true" | undefined;
|
|
1063
|
+
/** For a control that is not native (a native one has `required`). */
|
|
1064
|
+
readonly "aria-required": "true" | undefined;
|
|
1065
|
+
readonly required: true | undefined;
|
|
1066
|
+
}
|
|
1067
|
+
export interface FieldLabelProps {
|
|
1068
|
+
readonly id: string;
|
|
1069
|
+
readonly for: string;
|
|
1070
|
+
}
|
|
1071
|
+
/** Spread onto the hint and the error element; render both, always. */
|
|
1072
|
+
export interface FieldMessageProps {
|
|
1073
|
+
readonly id: string;
|
|
1074
|
+
readonly hidden: boolean;
|
|
1075
|
+
}
|
|
1076
|
+
/** The error element also announces itself: `role="alert"` while it is shown. */
|
|
1077
|
+
export interface FieldErrorProps extends FieldMessageProps {
|
|
1078
|
+
readonly role: "alert" | undefined;
|
|
1079
|
+
}
|
|
1080
|
+
export interface Field {
|
|
1081
|
+
readonly invalid: () => boolean;
|
|
1082
|
+
/** The hint, or `undefined` when there is none. */
|
|
1083
|
+
readonly hint: () => string | undefined;
|
|
1084
|
+
/** The error shown: `undefined` unless the field is invalid and has a message. */
|
|
1085
|
+
readonly error: () => string | undefined;
|
|
1086
|
+
/**
|
|
1087
|
+
* The ids `aria-describedby` lists now: hint, then error (never an id that is
|
|
1088
|
+
* hidden), then the host's `describedby`.
|
|
1089
|
+
*/
|
|
1090
|
+
readonly describedIds: () => readonly string[];
|
|
1091
|
+
readonly controlProps: FieldControlProps;
|
|
1092
|
+
readonly labelProps: FieldLabelProps;
|
|
1093
|
+
readonly hintProps: FieldMessageProps;
|
|
1094
|
+
readonly errorProps: FieldErrorProps;
|
|
1095
|
+
}
|
|
1096
|
+
/**
|
|
1097
|
+
* The ARIA contract of a form field: a label, a control, a hint and an error.
|
|
1098
|
+
* There is no APG pattern for it (APG has no "form field"; the nearest is the
|
|
1099
|
+
* label and description rules of the accessible name computation), so the
|
|
1100
|
+
* contract comes from WAI-ARIA 1.2 (`aria-describedby`, `aria-invalid`,
|
|
1101
|
+
* `aria-required`) and HTML (`label[for]`, `required`), and from the
|
|
1102
|
+
* majority of Base UI Field, react-aria TextField and ariakit FormControl,
|
|
1103
|
+
* which list the description and the error message together. It is not checked
|
|
1104
|
+
* against a Quint spec; `test/field.browser.test.tsx` is its oracle.
|
|
1105
|
+
*
|
|
1106
|
+
* Decisions: the error does not replace the hint, both are listed, hint first
|
|
1107
|
+
* (the hint is what tells the user how to fix the error); an error implies
|
|
1108
|
+
* invalid and `invalid: false` overrides it; a hidden message is never
|
|
1109
|
+
* referenced, so `aria-describedby` has no dangling id. The error element is
|
|
1110
|
+
* `role="alert"` only while it is shown (a hidden element announces nothing, and
|
|
1111
|
+
* one that appears is announced); the hint is never an alert.
|
|
1112
|
+
*
|
|
1113
|
+
* `describedby` lists host-owned ids after the field's own: one refusal that
|
|
1114
|
+
* belongs to two controls is one form-level element (with its own `role`), named
|
|
1115
|
+
* by both. The field cannot know whether that element is shown: the host
|
|
1116
|
+
* passes the id only while it is.
|
|
1117
|
+
*
|
|
1118
|
+
* Options are read when an attribute is read: pass getters, never destructure.
|
|
1119
|
+
*/
|
|
1120
|
+
export declare const createField: (options?: FieldOptions) => Field;
|
|
1033
1121
|
export type CheckboxGroupFocus = "none" | "parent" | "c0" | "c1" | "c2";
|
|
1034
1122
|
export type ParentChecked = "true" | "false" | "mixed";
|
|
1035
1123
|
export interface CheckboxGroupOptions<T = unknown> {
|
|
@@ -1043,6 +1131,22 @@ export interface CheckboxGroupOptions<T = unknown> {
|
|
|
1043
1131
|
readonly parent?: boolean;
|
|
1044
1132
|
/** Remember the last mixed combination for the controller's third activation. */
|
|
1045
1133
|
readonly remember?: boolean;
|
|
1134
|
+
/** Base of the group's ids (`<id>-control`, `-error`); a unique one when absent. */
|
|
1135
|
+
readonly id?: string;
|
|
1136
|
+
/** The group's name, as `aria-label`: a `role="group"` needs one. */
|
|
1137
|
+
readonly label?: string | undefined;
|
|
1138
|
+
/** The id of the element that names the group (`aria-labelledby`); wins over `label`. */
|
|
1139
|
+
readonly labelledby?: string | undefined;
|
|
1140
|
+
/** Ids of elements the host owns that describe the group, after the group's own error id. */
|
|
1141
|
+
readonly describedby?: string | undefined;
|
|
1142
|
+
/**
|
|
1143
|
+
* `true` marks the group invalid; a string does too and is the error message
|
|
1144
|
+
* (unless `error` is set). `false` forces valid. Left out, the group is invalid
|
|
1145
|
+
* exactly when it has an error message. Same contract as `createField`.
|
|
1146
|
+
*/
|
|
1147
|
+
readonly invalid?: boolean | string | undefined;
|
|
1148
|
+
/** The error message; absent (or empty) means no error element. */
|
|
1149
|
+
readonly error?: string | undefined;
|
|
1046
1150
|
/**
|
|
1047
1151
|
* A request to change the checked subset, called when the intent differs from
|
|
1048
1152
|
* the current value. Uncontrolled it is accepted; controlled the host may
|
|
@@ -1070,9 +1174,18 @@ export interface CheckboxGroupChildProps {
|
|
|
1070
1174
|
readonly onFocus: () => void;
|
|
1071
1175
|
}
|
|
1072
1176
|
export interface CheckboxGroupProps {
|
|
1177
|
+
/** The group element: a host's label can name it, and a controller can `aria-controls` it. */
|
|
1178
|
+
readonly id: string;
|
|
1073
1179
|
readonly role: "group";
|
|
1180
|
+
readonly "aria-label": string | undefined;
|
|
1181
|
+
readonly "aria-labelledby": string | undefined;
|
|
1182
|
+
/** The error id while one is shown, then the host's `describedby`. */
|
|
1183
|
+
readonly "aria-describedby": string | undefined;
|
|
1184
|
+
readonly "aria-invalid": "true" | undefined;
|
|
1074
1185
|
readonly onKeyDown: (event: KeyboardEvent) => void;
|
|
1075
1186
|
}
|
|
1187
|
+
/** The error element: render it always, it is `hidden` while there is no error. */
|
|
1188
|
+
export type CheckboxGroupErrorProps = FieldErrorProps;
|
|
1076
1189
|
export interface CheckboxGroup<T = unknown> {
|
|
1077
1190
|
readonly children: Accessor<ReadonlyArray<boolean>>;
|
|
1078
1191
|
readonly memory: Accessor<ReadonlyArray<boolean>>;
|
|
@@ -1080,6 +1193,14 @@ export interface CheckboxGroup<T = unknown> {
|
|
|
1080
1193
|
readonly focused: Accessor<CheckboxGroupFocus>;
|
|
1081
1194
|
readonly parentChecked: Accessor<ParentChecked>;
|
|
1082
1195
|
readonly checkedValues: () => ReadonlyArray<T>;
|
|
1196
|
+
/** The error shown: `undefined` unless the group is invalid and has a message. */
|
|
1197
|
+
readonly error: () => string | undefined;
|
|
1198
|
+
readonly invalid: () => boolean;
|
|
1199
|
+
/**
|
|
1200
|
+
* The ids `aria-describedby` lists now: the error (never while it is hidden),
|
|
1201
|
+
* then the host's `describedby`.
|
|
1202
|
+
*/
|
|
1203
|
+
readonly describedIds: () => readonly string[];
|
|
1083
1204
|
readonly click: (target: CheckboxGroupFocus) => void;
|
|
1084
1205
|
readonly keySpace: () => void;
|
|
1085
1206
|
readonly keyTab: () => void;
|
|
@@ -1088,6 +1209,7 @@ export interface CheckboxGroup<T = unknown> {
|
|
|
1088
1209
|
readonly setRemember: (value: boolean) => void;
|
|
1089
1210
|
readonly setChildren: (children: ReadonlyArray<boolean>) => void;
|
|
1090
1211
|
readonly groupProps: CheckboxGroupProps;
|
|
1212
|
+
readonly errorProps: CheckboxGroupErrorProps;
|
|
1091
1213
|
readonly parentProps: CheckboxGroupParentProps;
|
|
1092
1214
|
readonly childProps: (index: 0 | 1 | 2) => CheckboxGroupChildProps;
|
|
1093
1215
|
}
|
|
@@ -1103,7 +1225,17 @@ export interface CheckboxGroup<T = unknown> {
|
|
|
1103
1225
|
* pass `value` + `onValueChange` to own the checked subset. The checked set is
|
|
1104
1226
|
* packed internally so it rides the scalar `createControllable`.
|
|
1105
1227
|
*
|
|
1106
|
-
*
|
|
1228
|
+
* The name, the description and the error are `createField`'s contract on the
|
|
1229
|
+
* `role="group"` element (`aria-label` / `aria-labelledby`, `aria-describedby`,
|
|
1230
|
+
* `aria-invalid`, an error element that is `role="alert"` while it is shown), so
|
|
1231
|
+
* a group reads like the fields around it. The group is not a `<label for>`
|
|
1232
|
+
* target: a host names a visible label element's id with `labelledby`, or passes
|
|
1233
|
+
* `label` without one.
|
|
1234
|
+
*
|
|
1235
|
+
* Behaviour is checked against `specs/apg/checkbox-group.qnt` by the bridge. That
|
|
1236
|
+
* model leaves labelling out on purpose ("shift+Tab, accessible names,
|
|
1237
|
+
* fieldset/legend or role=group labelling" in its header), so the field contract
|
|
1238
|
+
* is checked by plain assertions in `test/checkbox-group.browser.test.tsx`.
|
|
1107
1239
|
*/
|
|
1108
1240
|
export declare const createCheckboxGroup: <T = unknown>(options: CheckboxGroupOptions<T>) => CheckboxGroup<T>;
|
|
1109
1241
|
/**
|
|
@@ -1294,6 +1426,215 @@ export interface DialogModal {
|
|
|
1294
1426
|
* are requests the host may ignore.
|
|
1295
1427
|
*/
|
|
1296
1428
|
export declare const createDialogModal: (options?: DialogModalOptions) => DialogModal;
|
|
1429
|
+
export interface StatusOptions {
|
|
1430
|
+
/** Rendered on `statusProps`; generated when absent. */
|
|
1431
|
+
readonly id?: string | undefined;
|
|
1432
|
+
}
|
|
1433
|
+
/** Spread onto the `role=status` live region. Render it once, always. */
|
|
1434
|
+
export interface StatusProps {
|
|
1435
|
+
readonly id: string;
|
|
1436
|
+
readonly role: "status";
|
|
1437
|
+
readonly "aria-live": "polite";
|
|
1438
|
+
readonly "aria-atomic": "true";
|
|
1439
|
+
}
|
|
1440
|
+
export interface Status {
|
|
1441
|
+
/** The text currently shown, or `undefined` before the first `show`. */
|
|
1442
|
+
readonly message: Accessor<string | undefined>;
|
|
1443
|
+
/** Writes the message, replacing the previous one; nothing is queued. */
|
|
1444
|
+
readonly show: (text: string) => void;
|
|
1445
|
+
readonly clear: () => void;
|
|
1446
|
+
readonly statusProps: StatusProps;
|
|
1447
|
+
}
|
|
1448
|
+
/**
|
|
1449
|
+
* APG Alert's polite sibling: one `role=status` live region whose text the host
|
|
1450
|
+
* replaces ("Link copied", "Saved"). It is not a queue: a second message shows
|
|
1451
|
+
* in place of the first, so a burst reads as the last state, not as N alerts.
|
|
1452
|
+
* The region is rendered once and stays mounted, which is what makes a change
|
|
1453
|
+
* of its text announced.
|
|
1454
|
+
*
|
|
1455
|
+
* A status is never for errors: an error that needs attention now is
|
|
1456
|
+
* `createAlert` (`role=alert`, assertive), and a message with a title, a
|
|
1457
|
+
* description and a timeout is `createToast`.
|
|
1458
|
+
*/
|
|
1459
|
+
export declare const createStatus: (options?: StatusOptions) => Status;
|
|
1460
|
+
/** The HTML `autocomplete` tokens worth naming; the attribute also takes an arbitrary token. */
|
|
1461
|
+
export type AutoCompleteToken = "off" | "on" | "name" | "given-name" | "family-name" | "username" | "email" | "tel" | "url" | "organization" | "street-address" | "postal-code" | "current-password" | "new-password" | "one-time-code" | "nickname";
|
|
1462
|
+
export interface TextInputOptions extends FieldOptions {
|
|
1463
|
+
readonly type?: "text" | "email" | "tel" | "url" | "search" | "password" | undefined;
|
|
1464
|
+
/** The HTML token list: the browser's own autofill is the accessible path. */
|
|
1465
|
+
readonly autoComplete?: AutoCompleteToken | undefined;
|
|
1466
|
+
readonly spellCheck?: boolean | undefined;
|
|
1467
|
+
readonly autoCapitalize?: "none" | "sentences" | "words" | "characters" | undefined;
|
|
1468
|
+
readonly inputMode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search" | undefined;
|
|
1469
|
+
readonly maxLength?: number | undefined;
|
|
1470
|
+
readonly readOnly?: boolean | undefined;
|
|
1471
|
+
readonly disabled?: boolean | undefined;
|
|
1472
|
+
readonly name?: string | undefined;
|
|
1473
|
+
readonly dir?: "ltr" | "rtl" | "auto" | undefined;
|
|
1474
|
+
readonly placeholder?: string | undefined;
|
|
1475
|
+
/** Change and input both land here; the host decides what a keystroke means. */
|
|
1476
|
+
readonly onValueChange?: ((value: string) => void) | undefined;
|
|
1477
|
+
}
|
|
1478
|
+
export interface TextAreaOptions extends TextInputOptions {
|
|
1479
|
+
readonly rows?: number | undefined;
|
|
1480
|
+
readonly wrap?: "soft" | "hard" | "off" | undefined;
|
|
1481
|
+
readonly resize?: "none" | "vertical" | "horizontal" | "both" | undefined;
|
|
1482
|
+
}
|
|
1483
|
+
export interface TextControlProps {
|
|
1484
|
+
readonly id: string;
|
|
1485
|
+
readonly "aria-describedby": string | undefined;
|
|
1486
|
+
readonly "aria-invalid": "true" | undefined;
|
|
1487
|
+
readonly "aria-required": "true" | undefined;
|
|
1488
|
+
readonly required: true | undefined;
|
|
1489
|
+
readonly type: TextInputOptions["type"];
|
|
1490
|
+
readonly autoComplete: AutoCompleteToken | undefined;
|
|
1491
|
+
readonly spellcheck: "true" | "false" | undefined;
|
|
1492
|
+
readonly autocapitalize: TextInputOptions["autoCapitalize"];
|
|
1493
|
+
readonly inputmode: TextInputOptions["inputMode"];
|
|
1494
|
+
readonly maxlength: number | undefined;
|
|
1495
|
+
readonly readOnly: true | undefined;
|
|
1496
|
+
readonly disabled: true | undefined;
|
|
1497
|
+
readonly name: string | undefined;
|
|
1498
|
+
readonly dir: "ltr" | "rtl" | "auto" | undefined;
|
|
1499
|
+
readonly placeholder: string | undefined;
|
|
1500
|
+
readonly onInput: (event: {
|
|
1501
|
+
currentTarget: {
|
|
1502
|
+
value: string;
|
|
1503
|
+
};
|
|
1504
|
+
}) => void;
|
|
1505
|
+
}
|
|
1506
|
+
export interface TextAreaControlProps extends TextControlProps {
|
|
1507
|
+
readonly rows: number | undefined;
|
|
1508
|
+
readonly wrap: TextAreaOptions["wrap"];
|
|
1509
|
+
readonly style: {
|
|
1510
|
+
readonly resize: "none" | "vertical" | "horizontal" | "both";
|
|
1511
|
+
} | undefined;
|
|
1512
|
+
}
|
|
1513
|
+
/** The field and the control, one object: every prop the element needs. */
|
|
1514
|
+
export interface TextInput extends Field {
|
|
1515
|
+
readonly controlProps: TextControlProps;
|
|
1516
|
+
}
|
|
1517
|
+
export interface TextArea extends Field {
|
|
1518
|
+
readonly controlProps: TextAreaControlProps;
|
|
1519
|
+
}
|
|
1520
|
+
/**
|
|
1521
|
+
* A text input with the field contract attached: label, hint, error (announced),
|
|
1522
|
+
* `aria-describedby` and `aria-invalid` come from `createField`; this adds the
|
|
1523
|
+
* props a host forgets — autofill tokens, spellcheck, inputmode, maxlength, the
|
|
1524
|
+
* disabled/readOnly pair. Platform: native (`input` is its own APG-equivalent;
|
|
1525
|
+
* no primitive re-implements text editing, which is why there is no key
|
|
1526
|
+
* handling here).
|
|
1527
|
+
*
|
|
1528
|
+
* Both `required` and `aria-required` are emitted: the native attribute is what
|
|
1529
|
+
* the browser enforces, the ARIA one is what a custom widget reading the same
|
|
1530
|
+
* props needs. A host that validates itself passes `noValidate` on the form
|
|
1531
|
+
* rather than dropping the attribute.
|
|
1532
|
+
*/
|
|
1533
|
+
export declare const createTextInput: (options?: TextInputOptions) => TextInput;
|
|
1534
|
+
/**
|
|
1535
|
+
* The same contract for a textarea, plus rows, wrap and resize. `resize` is a
|
|
1536
|
+
* style because CSS has no attribute for it; `none` is the value a layout that
|
|
1537
|
+
* owns its own height wants.
|
|
1538
|
+
*/
|
|
1539
|
+
export declare const createTextArea: (options?: TextAreaOptions) => TextArea;
|
|
1540
|
+
/** One command the host offers; `group` only picks the heading the host renders. */
|
|
1541
|
+
export interface PaletteCommand {
|
|
1542
|
+
readonly id: string;
|
|
1543
|
+
readonly label: string;
|
|
1544
|
+
readonly group?: string | undefined;
|
|
1545
|
+
readonly keywords?: ReadonlyArray<string> | undefined;
|
|
1546
|
+
readonly run: () => void | Promise<void>;
|
|
1547
|
+
}
|
|
1548
|
+
/** A command that survived the filter, in host order. */
|
|
1549
|
+
export interface PaletteResult {
|
|
1550
|
+
readonly id: string;
|
|
1551
|
+
readonly label: string;
|
|
1552
|
+
readonly group: string | undefined;
|
|
1553
|
+
}
|
|
1554
|
+
/** Every string the host puts on screen; override what you translate. */
|
|
1555
|
+
export interface CommandPaletteLabels {
|
|
1556
|
+
/** The dialog's name; `titleProps` heads it and the listbox is named by it. */
|
|
1557
|
+
readonly title: string;
|
|
1558
|
+
readonly placeholder: string;
|
|
1559
|
+
readonly empty: string;
|
|
1560
|
+
/** The result count the polite region announces, once per query. */
|
|
1561
|
+
readonly results: (count: number) => string;
|
|
1562
|
+
}
|
|
1563
|
+
export interface CommandPaletteOptions {
|
|
1564
|
+
readonly commands: ReadonlyArray<PaletteCommand>;
|
|
1565
|
+
/** Controlled: the host owns the open state and this is the only thing that changes it. */
|
|
1566
|
+
readonly open?: boolean | undefined;
|
|
1567
|
+
/** A request to change the open state, called when the intent differs. */
|
|
1568
|
+
readonly onOpenChange?: ((open: boolean) => void) | undefined;
|
|
1569
|
+
/** The `createHotkeys` chord `attach` binds; `"mod+k"` by default. */
|
|
1570
|
+
readonly hotkey?: string | undefined;
|
|
1571
|
+
readonly labels?: Partial<CommandPaletteLabels> | undefined;
|
|
1572
|
+
}
|
|
1573
|
+
export interface CommandPalette {
|
|
1574
|
+
readonly open: Accessor<boolean>;
|
|
1575
|
+
readonly openPalette: () => void;
|
|
1576
|
+
readonly closePalette: () => void;
|
|
1577
|
+
readonly query: Accessor<string>;
|
|
1578
|
+
readonly setQuery: (text: string) => void;
|
|
1579
|
+
/** Index into `results()`; `-1` = the search field holds the highlight. */
|
|
1580
|
+
readonly active: Accessor<number>;
|
|
1581
|
+
readonly setActive: (index: number) => void;
|
|
1582
|
+
readonly results: Accessor<ReadonlyArray<PaletteResult>>;
|
|
1583
|
+
readonly labels: CommandPaletteLabels;
|
|
1584
|
+
/** The live region's text; render it inside `statusProps`. */
|
|
1585
|
+
readonly status: Accessor<string | undefined>;
|
|
1586
|
+
readonly inputProps: TextControlProps & {
|
|
1587
|
+
readonly role: "searchbox";
|
|
1588
|
+
readonly value: string;
|
|
1589
|
+
readonly "aria-controls": string;
|
|
1590
|
+
readonly "aria-activedescendant": string | undefined;
|
|
1591
|
+
readonly onKeyDown: (event: KeyboardEvent) => void;
|
|
1592
|
+
};
|
|
1593
|
+
readonly listProps: {
|
|
1594
|
+
readonly id: string;
|
|
1595
|
+
readonly role: "listbox";
|
|
1596
|
+
readonly "aria-labelledby": string;
|
|
1597
|
+
/** A pointer click keeps the focus in the search field. */
|
|
1598
|
+
readonly onMouseDown: (event: MouseEvent) => void;
|
|
1599
|
+
};
|
|
1600
|
+
readonly optionProps: (id: string) => {
|
|
1601
|
+
readonly id: string;
|
|
1602
|
+
readonly role: "option";
|
|
1603
|
+
readonly "aria-selected": "true" | "false";
|
|
1604
|
+
readonly tabindex: -1;
|
|
1605
|
+
readonly onClick: () => void;
|
|
1606
|
+
readonly onMouseEnter: () => void;
|
|
1607
|
+
};
|
|
1608
|
+
readonly emptyProps: {
|
|
1609
|
+
readonly hidden: boolean;
|
|
1610
|
+
};
|
|
1611
|
+
readonly statusProps: StatusProps;
|
|
1612
|
+
readonly dialogProps: DialogContentProps;
|
|
1613
|
+
readonly backdropProps: DialogBackdropProps;
|
|
1614
|
+
readonly titleProps: {
|
|
1615
|
+
readonly id: string;
|
|
1616
|
+
};
|
|
1617
|
+
/** Runs the active command and closes the palette; a no-op with no highlight. */
|
|
1618
|
+
readonly runActive: () => void | Promise<void>;
|
|
1619
|
+
/** Binds the hotkey on the document; call once and call the teardown on cleanup. */
|
|
1620
|
+
readonly attach: () => () => void;
|
|
1621
|
+
}
|
|
1622
|
+
/**
|
|
1623
|
+
* A command palette: `createDialogModal` (a modal dialog, announced as one),
|
|
1624
|
+
* `createTextInput` (a `searchbox`, not a combobox — choosing runs a command,
|
|
1625
|
+
* it does not complete the field) and one filtered list. Focus stays in the
|
|
1626
|
+
* field; `aria-activedescendant` names the highlighted option, and ↓ on the
|
|
1627
|
+
* last / ↑ on the first return the highlight to the field. Home/End are menu
|
|
1628
|
+
* keys only while the field is empty, so the caret keeps them while typing.
|
|
1629
|
+
* Filtering is a plain case-insensitive substring match on the label and the
|
|
1630
|
+
* keywords, no fuzzy scoring: a palette is short and stable, and ranking
|
|
1631
|
+
* (recency, scopes) is a policy the host owns.
|
|
1632
|
+
*
|
|
1633
|
+
* The host's: rendering and grouping (the `group` field, headings, the CSS),
|
|
1634
|
+
* async commands (a rejected `run` is the host's to report), and any close
|
|
1635
|
+
* other than Escape / a command. `runActive` closes before it runs.
|
|
1636
|
+
*/
|
|
1637
|
+
export declare const createCommandPalette: (options: CommandPaletteOptions) => CommandPalette;
|
|
1297
1638
|
export interface ConfirmOptions {
|
|
1298
1639
|
readonly id?: string | undefined;
|
|
1299
1640
|
/** Called with `true` when a request opens the dialog and `false` when it settles. */
|
|
@@ -1684,94 +2025,6 @@ export interface Feed {
|
|
|
1684
2025
|
* request; `loadStart` / `loadFail` are adapter lifecycle events.
|
|
1685
2026
|
*/
|
|
1686
2027
|
export declare const createFeed: (options?: FeedOptions) => Feed;
|
|
1687
|
-
export interface FieldOptions {
|
|
1688
|
-
/** Base of every id the field makes (`<id>-control`, `-label`, `-hint`, `-error`). */
|
|
1689
|
-
readonly id?: string | undefined;
|
|
1690
|
-
readonly required?: boolean | undefined;
|
|
1691
|
-
/**
|
|
1692
|
-
* `true` marks the control invalid; a string does too and is the error message
|
|
1693
|
-
* (unless `error` is set). `false` forces valid: an `error` is then not shown,
|
|
1694
|
-
* so a host can pass `touched() && failed()` and keep the message ready.
|
|
1695
|
-
* Left out, the field is invalid exactly when it has an error message.
|
|
1696
|
-
*/
|
|
1697
|
-
readonly invalid?: boolean | string | undefined;
|
|
1698
|
-
/** Help text; absent (or empty) means the hint element is hidden and not referenced. */
|
|
1699
|
-
readonly hint?: string | undefined;
|
|
1700
|
-
/** The error message; absent (or empty) means no error element. */
|
|
1701
|
-
readonly error?: string | undefined;
|
|
1702
|
-
/**
|
|
1703
|
-
* Ids of elements the host owns, appended to `aria-describedby` after the
|
|
1704
|
-
* field's own hint and error: a form-level error that belongs to several
|
|
1705
|
-
* controls ("the passwords do not match" names both). One id or a list;
|
|
1706
|
-
* empty strings are dropped, and the attribute is absent when nothing is left.
|
|
1707
|
-
* The host keeps that element rendered, and decides whether it is hidden.
|
|
1708
|
-
*/
|
|
1709
|
-
readonly describedby?: string | readonly string[] | undefined;
|
|
1710
|
-
}
|
|
1711
|
-
/** Spread onto the form control (`input`, `textarea`, `select`, or a custom widget). */
|
|
1712
|
-
export interface FieldControlProps {
|
|
1713
|
-
readonly id: string;
|
|
1714
|
-
/** The ids of the hint and the error that are shown, hint first, then the host's `describedby`; absent when there are none. */
|
|
1715
|
-
readonly "aria-describedby": string | undefined;
|
|
1716
|
-
readonly "aria-invalid": "true" | undefined;
|
|
1717
|
-
/** For a control that is not native (a native one has `required`). */
|
|
1718
|
-
readonly "aria-required": "true" | undefined;
|
|
1719
|
-
readonly required: true | undefined;
|
|
1720
|
-
}
|
|
1721
|
-
export interface FieldLabelProps {
|
|
1722
|
-
readonly id: string;
|
|
1723
|
-
readonly for: string;
|
|
1724
|
-
}
|
|
1725
|
-
/** Spread onto the hint and the error element; render both, always. */
|
|
1726
|
-
export interface FieldMessageProps {
|
|
1727
|
-
readonly id: string;
|
|
1728
|
-
readonly hidden: boolean;
|
|
1729
|
-
}
|
|
1730
|
-
/** The error element also announces itself: `role="alert"` while it is shown. */
|
|
1731
|
-
export interface FieldErrorProps extends FieldMessageProps {
|
|
1732
|
-
readonly role: "alert" | undefined;
|
|
1733
|
-
}
|
|
1734
|
-
export interface Field {
|
|
1735
|
-
readonly invalid: () => boolean;
|
|
1736
|
-
/** The hint, or `undefined` when there is none. */
|
|
1737
|
-
readonly hint: () => string | undefined;
|
|
1738
|
-
/** The error shown: `undefined` unless the field is invalid and has a message. */
|
|
1739
|
-
readonly error: () => string | undefined;
|
|
1740
|
-
/**
|
|
1741
|
-
* The ids `aria-describedby` lists now: hint, then error (never an id that is
|
|
1742
|
-
* hidden), then the host's `describedby`.
|
|
1743
|
-
*/
|
|
1744
|
-
readonly describedIds: () => readonly string[];
|
|
1745
|
-
readonly controlProps: FieldControlProps;
|
|
1746
|
-
readonly labelProps: FieldLabelProps;
|
|
1747
|
-
readonly hintProps: FieldMessageProps;
|
|
1748
|
-
readonly errorProps: FieldErrorProps;
|
|
1749
|
-
}
|
|
1750
|
-
/**
|
|
1751
|
-
* The ARIA contract of a form field: a label, a control, a hint and an error.
|
|
1752
|
-
* There is no APG pattern for it (APG has no "form field"; the nearest is the
|
|
1753
|
-
* label and description rules of the accessible name computation), so the
|
|
1754
|
-
* contract comes from WAI-ARIA 1.2 (`aria-describedby`, `aria-invalid`,
|
|
1755
|
-
* `aria-required`) and HTML (`label[for]`, `required`), and from the
|
|
1756
|
-
* majority of Base UI Field, react-aria TextField and ariakit FormControl,
|
|
1757
|
-
* which list the description and the error message together. It is not checked
|
|
1758
|
-
* against a Quint spec; `test/field.browser.test.tsx` is its oracle.
|
|
1759
|
-
*
|
|
1760
|
-
* Decisions: the error does not replace the hint, both are listed, hint first
|
|
1761
|
-
* (the hint is what tells the user how to fix the error); an error implies
|
|
1762
|
-
* invalid and `invalid: false` overrides it; a hidden message is never
|
|
1763
|
-
* referenced, so `aria-describedby` has no dangling id. The error element is
|
|
1764
|
-
* `role="alert"` only while it is shown (a hidden element announces nothing, and
|
|
1765
|
-
* one that appears is announced); the hint is never an alert.
|
|
1766
|
-
*
|
|
1767
|
-
* `describedby` lists host-owned ids after the field's own: one refusal that
|
|
1768
|
-
* belongs to two controls is one form-level element (with its own `role`), named
|
|
1769
|
-
* by both. The field cannot know whether that element is shown: the host
|
|
1770
|
-
* passes the id only while it is.
|
|
1771
|
-
*
|
|
1772
|
-
* Options are read when an attribute is read: pass getters, never destructure.
|
|
1773
|
-
*/
|
|
1774
|
-
export declare const createField: (options?: FieldOptions) => Field;
|
|
1775
2028
|
export interface PaginationLabels {
|
|
1776
2029
|
/** The navigation landmark's name; defaults to "Pagination". */
|
|
1777
2030
|
readonly nav?: string | undefined;
|
|
@@ -2296,6 +2549,107 @@ export interface Hotkeys {
|
|
|
2296
2549
|
* browser would otherwise act on (Cmd/Ctrl+S, Cmd/Ctrl+K).
|
|
2297
2550
|
*/
|
|
2298
2551
|
export declare const createHotkeys: (options?: HotkeysOptions) => Hotkeys;
|
|
2552
|
+
/** How a drag turns the knob: the angle around the centre, a straight slide, or whichever the drag starts as. */
|
|
2553
|
+
export type KnobGesture = "spin" | "slide" | "both";
|
|
2554
|
+
export interface KnobLabels {
|
|
2555
|
+
/** The knob's accessible name (`aria-label`); "Knob" by default. */
|
|
2556
|
+
readonly knob?: string | undefined;
|
|
2557
|
+
}
|
|
2558
|
+
export interface KnobOptions {
|
|
2559
|
+
readonly min?: number | undefined;
|
|
2560
|
+
readonly max?: number | undefined;
|
|
2561
|
+
readonly step?: number | undefined;
|
|
2562
|
+
/** Controlled: the host owns the value and this is the only thing that changes it. */
|
|
2563
|
+
readonly value?: number | undefined;
|
|
2564
|
+
/** Starting value when uncontrolled (the middle of the range by default). */
|
|
2565
|
+
readonly defaultValue?: number | undefined;
|
|
2566
|
+
/**
|
|
2567
|
+
* `false` (default): clamp at `min` / `max`. `true`: a continuous dial — the
|
|
2568
|
+
* value wraps around (past `max` comes back at `min`), so a full turn of the
|
|
2569
|
+
* skin is a full cycle.
|
|
2570
|
+
*/
|
|
2571
|
+
readonly wrap?: boolean | undefined;
|
|
2572
|
+
/** Which drag turns the knob; "both" (default) locks per drag from the first movement. */
|
|
2573
|
+
readonly gesture?: KnobGesture | undefined;
|
|
2574
|
+
readonly labels?: KnobLabels | undefined;
|
|
2575
|
+
/** The spoken value (`aria-valuetext`); `String` by default. */
|
|
2576
|
+
readonly format?: ((value: number) => string) | undefined;
|
|
2577
|
+
/** Base for the generated value region id. */
|
|
2578
|
+
readonly id?: string | undefined;
|
|
2579
|
+
/**
|
|
2580
|
+
* A request to change the value, called when the intent differs from the
|
|
2581
|
+
* current value. Uncontrolled it is accepted; controlled the host may ignore it.
|
|
2582
|
+
*/
|
|
2583
|
+
readonly onValueChange?: ((value: number) => void) | undefined;
|
|
2584
|
+
}
|
|
2585
|
+
/** Spread onto the knob element, the focusable control. */
|
|
2586
|
+
export interface KnobProps {
|
|
2587
|
+
readonly role: "slider";
|
|
2588
|
+
readonly tabindex: number;
|
|
2589
|
+
readonly "aria-valuemin": string;
|
|
2590
|
+
readonly "aria-valuemax": string;
|
|
2591
|
+
readonly "aria-valuenow": string;
|
|
2592
|
+
readonly "aria-valuetext": string;
|
|
2593
|
+
readonly "aria-label": string;
|
|
2594
|
+
readonly onKeyDown: (event: KeyboardEvent) => void;
|
|
2595
|
+
readonly onPointerDown: (event: PointerEvent) => void;
|
|
2596
|
+
readonly onPointerMove: (event: PointerEvent) => void;
|
|
2597
|
+
readonly onPointerUp: (event: PointerEvent) => void;
|
|
2598
|
+
readonly onPointerCancel: (event: PointerEvent) => void;
|
|
2599
|
+
readonly onWheel: (event: WheelEvent) => void;
|
|
2600
|
+
}
|
|
2601
|
+
/** Spread onto the live value; render it once, always (hide it visually, never with `hidden`). */
|
|
2602
|
+
export interface KnobValueProps {
|
|
2603
|
+
readonly id: string;
|
|
2604
|
+
readonly role: "status";
|
|
2605
|
+
readonly "aria-live": "polite";
|
|
2606
|
+
}
|
|
2607
|
+
export interface Knob {
|
|
2608
|
+
readonly value: Accessor<number>;
|
|
2609
|
+
/** A request, like a key or a drag; `setValue` never bypasses a controlled `value`. */
|
|
2610
|
+
readonly setValue: (value: number) => void;
|
|
2611
|
+
/**
|
|
2612
|
+
* The fraction of a full turn the skin rotates by for `value`, 0..1 (multiply
|
|
2613
|
+
* by 360 for degrees). Clamped to 0..1, or the wrapped fraction when `wrap`.
|
|
2614
|
+
*/
|
|
2615
|
+
readonly percentOf: (value: number) => number;
|
|
2616
|
+
/** A request to move by `delta` value units (a key, a wheel, a host button). */
|
|
2617
|
+
readonly stepBy: (delta: number) => void;
|
|
2618
|
+
readonly knobProps: KnobProps;
|
|
2619
|
+
readonly valueProps: KnobValueProps;
|
|
2620
|
+
}
|
|
2621
|
+
/**
|
|
2622
|
+
* A virtual knob after GarageBand's (https://jherrm.github.io/knobs/): one
|
|
2623
|
+
* control turned three ways — spun around its centre, or slid vertically or
|
|
2624
|
+
* horizontally, one gesture locked per drag. Plain Solid signals, no elements,
|
|
2625
|
+
* no styling. **No ARIA role exists for a dial**, so the knob is a `role=slider`
|
|
2626
|
+
* with `aria-valuenow` / `aria-valuetext`; the value the host renders in
|
|
2627
|
+
* `valueProps` is the live announcement (`role=status`), and a numeric field
|
|
2628
|
+
* must sit next to the dial, because a dial is never the only control.
|
|
2629
|
+
*
|
|
2630
|
+
* Request/commit (map ticket `rt1p`): uncontrolled by default (`defaultValue`);
|
|
2631
|
+
* pass `value` + `onValueChange` to own the value. A key, a wheel, a drag and
|
|
2632
|
+
* `setValue`/`stepBy` are requests the host may ignore.
|
|
2633
|
+
*
|
|
2634
|
+
* Gestures (`gesture`, default "both"), decided once on the first meaningful
|
|
2635
|
+
* movement so a drag never switches modes:
|
|
2636
|
+
* - a movement that stays on one axis (the other axis under `SLIDE_VARIANCE` of
|
|
2637
|
+
* it) locks a slide — the reference's "slide in a straight line";
|
|
2638
|
+
* - any other movement is a turn around the centre: the angle the pointer
|
|
2639
|
+
* covers is the value, and the farther from the centre the finer it is;
|
|
2640
|
+
* - `gesture: "spin"` / `"slide"` disable the other.
|
|
2641
|
+
*
|
|
2642
|
+
* A vertical slide turns the knob the way the grabbed side would turn a real
|
|
2643
|
+
* one: down on the right half is clockwise (up in value), down on the left half
|
|
2644
|
+
* counter-clockwise. A horizontal slide uses the same left/right side (the
|
|
2645
|
+
* reference picks top/bottom for this one; one rule for both is simpler to
|
|
2646
|
+
* learn). `wrap` makes the dial continuous instead of clamped.
|
|
2647
|
+
*
|
|
2648
|
+
* ponytail: no momentum/inertia and no `disabled` — the reference has a
|
|
2649
|
+
* deceleration tail, and no host here has asked for one; add inertia in the
|
|
2650
|
+
* host's rAF loop if a look needs it.
|
|
2651
|
+
*/
|
|
2652
|
+
export declare const createKnob: (options?: KnobOptions) => Knob;
|
|
2299
2653
|
export interface LinkOptions {
|
|
2300
2654
|
readonly href?: string | undefined;
|
|
2301
2655
|
/** Render a native `<a href>` (the default when `href` is set). */
|
|
@@ -2451,8 +2805,12 @@ export declare const createListbox: (options: ListboxOptions) => Listbox;
|
|
|
2451
2805
|
* dismiss and Esc; `focusgroup` gives the menubar's roving tabindex. The
|
|
2452
2806
|
* library owns the menu keys, typeahead, submenus and checkable state.
|
|
2453
2807
|
*
|
|
2454
|
-
*
|
|
2455
|
-
*
|
|
2808
|
+
* Request/commit (map ticket `rt1p`): the open state, and the checked items of
|
|
2809
|
+
* the checkable variants, are controllable. Uncontrolled by default
|
|
2810
|
+
* (`defaultOpen` / `defaultValue`); pass `open` / `value` (+ `onOpenChange` /
|
|
2811
|
+
* `onCheckedValueChange`) to own them. Every opening and closing intent — the
|
|
2812
|
+
* trigger's click and keys, Escape, an item's activation, Tab, and the
|
|
2813
|
+
* programmatic `openMenu` / `closeMenu` — is a request the host may ignore.
|
|
2456
2814
|
*/
|
|
2457
2815
|
export type MenuItemKind = "item" | "checkbox" | "radio";
|
|
2458
2816
|
export interface MenuItemInput {
|
|
@@ -2465,6 +2823,9 @@ export type MenuVariant = "plain" | "checkbox-items" | "radio-items" | "mixed";
|
|
|
2465
2823
|
export interface MenuOptions {
|
|
2466
2824
|
readonly items: ReadonlyArray<string | MenuItemInput>;
|
|
2467
2825
|
readonly variant?: MenuVariant;
|
|
2826
|
+
/** Controlled: the host owns the open state and this is the only thing that opens or closes it. */
|
|
2827
|
+
readonly open?: boolean | undefined;
|
|
2828
|
+
/** Uncontrolled starting state; ignored while `open` is set. */
|
|
2468
2829
|
readonly defaultOpen?: boolean;
|
|
2469
2830
|
/**
|
|
2470
2831
|
* `outside` (menu button): focus can sit outside the widget, so keys are
|
|
@@ -2480,7 +2841,7 @@ export interface MenuOptions {
|
|
|
2480
2841
|
* Controlled: the host owns the checked items. Packed as
|
|
2481
2842
|
* `checkboxItem0 * 5 + radioChoice` (1-based), matching `menu-checkable.qnt`'s
|
|
2482
2843
|
* `checked(wrap, choice)`; pass `undefined` for uncontrolled. The open state
|
|
2483
|
-
*
|
|
2844
|
+
* has its own `open` pair.
|
|
2484
2845
|
*/
|
|
2485
2846
|
readonly value?: number | undefined;
|
|
2486
2847
|
/** The uncontrolled packed checked state at mount. */
|
|
@@ -2490,6 +2851,10 @@ export interface MenuOptions {
|
|
|
2490
2851
|
/** Item indices disabled (focusable, not activatable). */
|
|
2491
2852
|
readonly disabled?: ReadonlyArray<number>;
|
|
2492
2853
|
readonly id?: string;
|
|
2854
|
+
/**
|
|
2855
|
+
* A request to change the open state, called when the intent differs from the
|
|
2856
|
+
* current one. Uncontrolled it is accepted; controlled the host may ignore it.
|
|
2857
|
+
*/
|
|
2493
2858
|
readonly onOpenChange?: (open: boolean) => void;
|
|
2494
2859
|
readonly onItemClick?: (index: number) => void;
|
|
2495
2860
|
readonly onCheckedChange?: (checked: boolean, index: number) => void;
|
|
@@ -3190,37 +3555,6 @@ export interface Spinbutton {
|
|
|
3190
3555
|
* APG text.
|
|
3191
3556
|
*/
|
|
3192
3557
|
export declare const createSpinbutton: (options?: SpinbuttonOptions) => Spinbutton;
|
|
3193
|
-
export interface StatusOptions {
|
|
3194
|
-
/** Rendered on `statusProps`; generated when absent. */
|
|
3195
|
-
readonly id?: string | undefined;
|
|
3196
|
-
}
|
|
3197
|
-
/** Spread onto the `role=status` live region. Render it once, always. */
|
|
3198
|
-
export interface StatusProps {
|
|
3199
|
-
readonly id: string;
|
|
3200
|
-
readonly role: "status";
|
|
3201
|
-
readonly "aria-live": "polite";
|
|
3202
|
-
readonly "aria-atomic": "true";
|
|
3203
|
-
}
|
|
3204
|
-
export interface Status {
|
|
3205
|
-
/** The text currently shown, or `undefined` before the first `show`. */
|
|
3206
|
-
readonly message: Accessor<string | undefined>;
|
|
3207
|
-
/** Writes the message, replacing the previous one; nothing is queued. */
|
|
3208
|
-
readonly show: (text: string) => void;
|
|
3209
|
-
readonly clear: () => void;
|
|
3210
|
-
readonly statusProps: StatusProps;
|
|
3211
|
-
}
|
|
3212
|
-
/**
|
|
3213
|
-
* APG Alert's polite sibling: one `role=status` live region whose text the host
|
|
3214
|
-
* replaces ("Link copied", "Saved"). It is not a queue: a second message shows
|
|
3215
|
-
* in place of the first, so a burst reads as the last state, not as N alerts.
|
|
3216
|
-
* The region is rendered once and stays mounted, which is what makes a change
|
|
3217
|
-
* of its text announced.
|
|
3218
|
-
*
|
|
3219
|
-
* A status is never for errors: an error that needs attention now is
|
|
3220
|
-
* `createAlert` (`role=alert`, assertive), and a message with a title, a
|
|
3221
|
-
* description and a timeout is `createToast`.
|
|
3222
|
-
*/
|
|
3223
|
-
export declare const createStatus: (options?: StatusOptions) => Status;
|
|
3224
3558
|
export interface SwitchOptions {
|
|
3225
3559
|
/** Controlled: the host owns the state and this is the only thing that changes it. */
|
|
3226
3560
|
readonly value?: boolean | undefined;
|
|
@@ -3451,86 +3785,6 @@ export interface Table {
|
|
|
3451
3785
|
* destructured snapshot. `id` is captured once: it is the base of the caption id.
|
|
3452
3786
|
*/
|
|
3453
3787
|
export declare const createTable: (options: TableOptions) => Table;
|
|
3454
|
-
/** The HTML `autocomplete` tokens worth naming; the attribute also takes an arbitrary token. */
|
|
3455
|
-
export type AutoCompleteToken = "off" | "on" | "name" | "given-name" | "family-name" | "username" | "email" | "tel" | "url" | "organization" | "street-address" | "postal-code" | "current-password" | "new-password" | "one-time-code" | "nickname";
|
|
3456
|
-
export interface TextInputOptions extends FieldOptions {
|
|
3457
|
-
readonly type?: "text" | "email" | "tel" | "url" | "search" | "password" | undefined;
|
|
3458
|
-
/** The HTML token list: the browser's own autofill is the accessible path. */
|
|
3459
|
-
readonly autoComplete?: AutoCompleteToken | undefined;
|
|
3460
|
-
readonly spellCheck?: boolean | undefined;
|
|
3461
|
-
readonly autoCapitalize?: "none" | "sentences" | "words" | "characters" | undefined;
|
|
3462
|
-
readonly inputMode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search" | undefined;
|
|
3463
|
-
readonly maxLength?: number | undefined;
|
|
3464
|
-
readonly readOnly?: boolean | undefined;
|
|
3465
|
-
readonly disabled?: boolean | undefined;
|
|
3466
|
-
readonly name?: string | undefined;
|
|
3467
|
-
readonly dir?: "ltr" | "rtl" | "auto" | undefined;
|
|
3468
|
-
readonly placeholder?: string | undefined;
|
|
3469
|
-
/** Change and input both land here; the host decides what a keystroke means. */
|
|
3470
|
-
readonly onValueChange?: ((value: string) => void) | undefined;
|
|
3471
|
-
}
|
|
3472
|
-
export interface TextAreaOptions extends TextInputOptions {
|
|
3473
|
-
readonly rows?: number | undefined;
|
|
3474
|
-
readonly wrap?: "soft" | "hard" | "off" | undefined;
|
|
3475
|
-
readonly resize?: "none" | "vertical" | "horizontal" | "both" | undefined;
|
|
3476
|
-
}
|
|
3477
|
-
export interface TextControlProps {
|
|
3478
|
-
readonly id: string;
|
|
3479
|
-
readonly "aria-describedby": string | undefined;
|
|
3480
|
-
readonly "aria-invalid": "true" | undefined;
|
|
3481
|
-
readonly "aria-required": "true" | undefined;
|
|
3482
|
-
readonly required: true | undefined;
|
|
3483
|
-
readonly type: TextInputOptions["type"];
|
|
3484
|
-
readonly autoComplete: AutoCompleteToken | undefined;
|
|
3485
|
-
readonly spellcheck: "true" | "false" | undefined;
|
|
3486
|
-
readonly autocapitalize: TextInputOptions["autoCapitalize"];
|
|
3487
|
-
readonly inputmode: TextInputOptions["inputMode"];
|
|
3488
|
-
readonly maxlength: number | undefined;
|
|
3489
|
-
readonly readOnly: true | undefined;
|
|
3490
|
-
readonly disabled: true | undefined;
|
|
3491
|
-
readonly name: string | undefined;
|
|
3492
|
-
readonly dir: "ltr" | "rtl" | "auto" | undefined;
|
|
3493
|
-
readonly placeholder: string | undefined;
|
|
3494
|
-
readonly onInput: (event: {
|
|
3495
|
-
currentTarget: {
|
|
3496
|
-
value: string;
|
|
3497
|
-
};
|
|
3498
|
-
}) => void;
|
|
3499
|
-
}
|
|
3500
|
-
export interface TextAreaControlProps extends TextControlProps {
|
|
3501
|
-
readonly rows: number | undefined;
|
|
3502
|
-
readonly wrap: TextAreaOptions["wrap"];
|
|
3503
|
-
readonly style: {
|
|
3504
|
-
readonly resize: "none" | "vertical" | "horizontal" | "both";
|
|
3505
|
-
} | undefined;
|
|
3506
|
-
}
|
|
3507
|
-
/** The field and the control, one object: every prop the element needs. */
|
|
3508
|
-
export interface TextInput extends Field {
|
|
3509
|
-
readonly controlProps: TextControlProps;
|
|
3510
|
-
}
|
|
3511
|
-
export interface TextArea extends Field {
|
|
3512
|
-
readonly controlProps: TextAreaControlProps;
|
|
3513
|
-
}
|
|
3514
|
-
/**
|
|
3515
|
-
* A text input with the field contract attached: label, hint, error (announced),
|
|
3516
|
-
* `aria-describedby` and `aria-invalid` come from `createField`; this adds the
|
|
3517
|
-
* props a host forgets — autofill tokens, spellcheck, inputmode, maxlength, the
|
|
3518
|
-
* disabled/readOnly pair. Platform: native (`input` is its own APG-equivalent;
|
|
3519
|
-
* no primitive re-implements text editing, which is why there is no key
|
|
3520
|
-
* handling here).
|
|
3521
|
-
*
|
|
3522
|
-
* Both `required` and `aria-required` are emitted: the native attribute is what
|
|
3523
|
-
* the browser enforces, the ARIA one is what a custom widget reading the same
|
|
3524
|
-
* props needs. A host that validates itself passes `noValidate` on the form
|
|
3525
|
-
* rather than dropping the attribute.
|
|
3526
|
-
*/
|
|
3527
|
-
export declare const createTextInput: (options?: TextInputOptions) => TextInput;
|
|
3528
|
-
/**
|
|
3529
|
-
* The same contract for a textarea, plus rows, wrap and resize. `resize` is a
|
|
3530
|
-
* style because CSS has no attribute for it; `none` is the value a layout that
|
|
3531
|
-
* owns its own height wants.
|
|
3532
|
-
*/
|
|
3533
|
-
export declare const createTextArea: (options?: TextAreaOptions) => TextArea;
|
|
3534
3788
|
export type TabsOrientation = "horizontal" | "vertical";
|
|
3535
3789
|
export type TabsActivation = "automatic" | "manual";
|
|
3536
3790
|
/**
|