@orkestrel/form 0.0.11 → 0.0.13
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 +6 -1
- package/dist/src/browser/index.d.ts +6 -572
- package/dist/src/browser/index.js +84 -182
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/core/index.cjs +63 -15
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +30 -9
- package/dist/src/core/index.d.ts +30 -9
- package/dist/src/core/index.js +63 -15
- package/dist/src/core/index.js.map +1 -1
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ npm install @orkestrel/form
|
|
|
20
20
|
|
|
21
21
|
## Requirements
|
|
22
22
|
|
|
23
|
-
- Node.js >= 22.
|
|
23
|
+
- Node.js >= 22.18
|
|
24
24
|
- Host-independent: no `node:*`, no DOM. Ships dual ESM+CJS builds.
|
|
25
25
|
|
|
26
26
|
## Usage
|
|
@@ -72,6 +72,11 @@ binding in ESM. Both include declarations. The binding supports password reveal,
|
|
|
72
72
|
without duplicate native feedback, presented-control write notifications and touch, and optional
|
|
73
73
|
blur deferral through footer presses. See [Native binding](./guides/form.md#native-binding).
|
|
74
74
|
|
|
75
|
+
Use `control: 'list'` for free-text tags or recipient arrays. Its `required` rule requires an entry,
|
|
76
|
+
`minimum` and `maximum` count entries, and `email: true` checks each address. Bind it to a native
|
|
77
|
+
`select multiple` for repeated FormData values and authored-option reset. See
|
|
78
|
+
[List fields](./guides/form.md#list).
|
|
79
|
+
|
|
75
80
|
## Development
|
|
76
81
|
|
|
77
82
|
```sh
|
|
@@ -1,33 +1,11 @@
|
|
|
1
1
|
import type { EmitterErrorHandler } from '@orkestrel/emitter';
|
|
2
2
|
import type { EmitterHooks } from '@orkestrel/emitter';
|
|
3
3
|
import type { EmitterInterface } from '@orkestrel/emitter';
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*
|
|
10
|
-
* @remarks
|
|
11
|
-
* A field offering one box that means yes or no is a {@link ConfirmField}, not a one-choice
|
|
12
|
-
* checkbox.
|
|
13
|
-
*/
|
|
14
|
-
declare interface CheckboxField extends FieldBase {
|
|
15
|
-
readonly control: 'checkbox';
|
|
16
|
-
readonly choices: readonly FieldChoice[];
|
|
17
|
-
readonly default?: readonly string[];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** Represents a color, held as the control's own six-digit `#rrggbb` string. */
|
|
21
|
-
declare interface ColorField extends FieldBase {
|
|
22
|
-
readonly control: 'color';
|
|
23
|
-
readonly default?: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** Represents a single on/off box, holding a boolean. */
|
|
27
|
-
declare interface ConfirmField extends FieldBase {
|
|
28
|
-
readonly control: 'confirm';
|
|
29
|
-
readonly default?: boolean;
|
|
30
|
-
}
|
|
4
|
+
import type { FieldError } from '@orkestrel/form';
|
|
5
|
+
import type { FieldValue } from '@orkestrel/form';
|
|
6
|
+
import type { FormField } from '@orkestrel/form';
|
|
7
|
+
import type { FormInterface } from '@orkestrel/form';
|
|
8
|
+
import type { FormSubmission } from '@orkestrel/form';
|
|
31
9
|
|
|
32
10
|
/**
|
|
33
11
|
* Creates a native form binding exposed through its lifecycle interface.
|
|
@@ -43,170 +21,6 @@ declare interface ConfirmField extends FieldBase {
|
|
|
43
21
|
*/
|
|
44
22
|
export declare function createFormBinding(element: HTMLFormElement, document: FormInterface, options?: FormBindingOptions): FormBindingInterface;
|
|
45
23
|
|
|
46
|
-
/** Represents a calendar date, held as the control's own `YYYY-MM-DD` string. */
|
|
47
|
-
declare interface DateField extends FieldBase {
|
|
48
|
-
readonly control: 'date';
|
|
49
|
-
readonly default?: string;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/** Represents a date and a time of day together, with no zone, held as the control's own string. */
|
|
53
|
-
declare interface DatetimeField extends FieldBase {
|
|
54
|
-
readonly control: 'datetime';
|
|
55
|
-
readonly default?: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/** Represents text over many lines. */
|
|
59
|
-
declare interface EditorField extends FieldBase {
|
|
60
|
-
readonly control: 'editor';
|
|
61
|
-
readonly default?: string;
|
|
62
|
-
readonly placeholder?: string;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Declares what every field carries, whatever its control.
|
|
67
|
-
*
|
|
68
|
-
* @remarks
|
|
69
|
-
* `name` keys the field in {@link FormValues} and `group` names a {@link FormGroup}.
|
|
70
|
-
*
|
|
71
|
-
* `hidden`, `locked`, and `disabled` differ in what they remove. `hidden` keeps the field out of
|
|
72
|
-
* the rendered form, `locked` renders it unwritable, and both are still validated and still
|
|
73
|
-
* submitted. `disabled` takes the field out of the form entirely: it is neither validated nor
|
|
74
|
-
* submitted. It is the field's declared, opening state; {@link FormInterface.disabled} is the
|
|
75
|
-
* current fact, because a live form can move a field either way.
|
|
76
|
-
*
|
|
77
|
-
* `meta` is a bounded JSON carrier for whatever the schema declines to model. Evaluation never
|
|
78
|
-
* reads it, no rule sees it, and it round-trips verbatim through serialization. This package
|
|
79
|
-
* defines no key in it, so every key belongs to the host.
|
|
80
|
-
*/
|
|
81
|
-
declare interface FieldBase {
|
|
82
|
-
readonly name: string;
|
|
83
|
-
readonly label?: string;
|
|
84
|
-
readonly help?: string;
|
|
85
|
-
readonly group?: string;
|
|
86
|
-
readonly hidden?: boolean;
|
|
87
|
-
readonly disabled?: boolean;
|
|
88
|
-
readonly locked?: boolean;
|
|
89
|
-
readonly rule?: FieldRule;
|
|
90
|
-
readonly meta?: JSONRecord;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Represents one option a `select` or `checkbox` field offers.
|
|
95
|
-
*
|
|
96
|
-
* @remarks
|
|
97
|
-
* `value` is what the form stores and `label` is what the person reads. `help` explains the
|
|
98
|
-
* option, and `disabled` shows it while refusing its value at every input door, including
|
|
99
|
-
* seeded values.
|
|
100
|
-
*/
|
|
101
|
-
declare interface FieldChoice {
|
|
102
|
-
readonly value: string;
|
|
103
|
-
readonly label: string;
|
|
104
|
-
readonly help?: string;
|
|
105
|
-
readonly disabled?: boolean;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Represents one failed check against one field.
|
|
110
|
-
*
|
|
111
|
-
* @remarks
|
|
112
|
-
* `rule` names the constraint that failed. It is absent when the message came from a
|
|
113
|
-
* {@link FieldRule.custom} validator or from {@link FormInterface.invalidate}, because
|
|
114
|
-
* neither failure belongs to a named rule.
|
|
115
|
-
*/
|
|
116
|
-
declare interface FieldError {
|
|
117
|
-
readonly field: string;
|
|
118
|
-
readonly message: string;
|
|
119
|
-
readonly rule?: FieldRuleName;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Represents the constraints one field's value must satisfy.
|
|
124
|
-
*
|
|
125
|
-
* @remarks
|
|
126
|
-
* `minimum` and `maximum` measure whatever the control makes countable: characters for
|
|
127
|
-
* `text`, `editor`, and `password`; magnitude for `number`; chronology for `date`, `time`,
|
|
128
|
-
* and `datetime`, whose operand is a string written in that control's own format; and the
|
|
129
|
-
* number of selections for `checkbox` and `file`.
|
|
130
|
-
*
|
|
131
|
-
* `step` is the interval a numeric value must land on. `pattern` is regular-expression
|
|
132
|
-
* source. `email`, `url`, `integer`, and `alphanumeric` each assert one shape over the whole
|
|
133
|
-
* value. `custom` runs last and is the only rule that sees the rest of the form.
|
|
134
|
-
*
|
|
135
|
-
* @example
|
|
136
|
-
* ```ts
|
|
137
|
-
* const rule: FieldRule = { required: true, minimum: 8, pattern: '\\d' }
|
|
138
|
-
* ```
|
|
139
|
-
*/
|
|
140
|
-
declare interface FieldRule {
|
|
141
|
-
readonly required?: boolean;
|
|
142
|
-
readonly minimum?: number | string;
|
|
143
|
-
readonly maximum?: number | string;
|
|
144
|
-
readonly step?: number;
|
|
145
|
-
readonly pattern?: string;
|
|
146
|
-
readonly email?: boolean;
|
|
147
|
-
readonly url?: boolean;
|
|
148
|
-
readonly integer?: boolean;
|
|
149
|
-
readonly alphanumeric?: boolean;
|
|
150
|
-
readonly custom?: FieldValidator;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Lists every rule that reports its failure by name.
|
|
155
|
-
*
|
|
156
|
-
* @remarks
|
|
157
|
-
* `custom` is excluded because it supplies its own message, so nothing keyed by a rule name
|
|
158
|
-
* would ever be read for it. {@link FormOptions.messages} is keyed by this name.
|
|
159
|
-
*/
|
|
160
|
-
declare type FieldRuleName = Exclude<keyof FieldRule, 'custom'>;
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Checks one value against the whole form.
|
|
164
|
-
*
|
|
165
|
-
* @remarks
|
|
166
|
-
* It runs after every named rule, and it runs on an absent value as well as a present one. That
|
|
167
|
-
* is what makes a rule such as "required once the sibling says yes" expressible, and it means an
|
|
168
|
-
* unanswered field can carry both a `required` message and this validator's own.
|
|
169
|
-
*
|
|
170
|
-
* @param value - The value the field holds, or `undefined` when nobody has answered it.
|
|
171
|
-
* @param values - Every answer the form holds, so a rule can read its siblings.
|
|
172
|
-
* @returns `true` when the value passes, or the message explaining why it failed.
|
|
173
|
-
* @throws Thrown when a {@link FieldValidator} throws; its own thrown value escapes the mutation
|
|
174
|
-
* call unchanged. When a form mutation has already changed state, the throw leaves those
|
|
175
|
-
* changes beside the error list from before that mutation. An invalidation can therefore be
|
|
176
|
-
* recorded without appearing in `errors`, and a clear can reset state without emitting `clear`.
|
|
177
|
-
* Form-owned refusals use
|
|
178
|
-
* {@link FormError} instead.
|
|
179
|
-
* @example
|
|
180
|
-
* ```ts
|
|
181
|
-
* const matches: FieldValidator = (value, values) =>
|
|
182
|
-
* value === values.password ? true : 'Both passwords must match'
|
|
183
|
-
* ```
|
|
184
|
-
*/
|
|
185
|
-
declare type FieldValidator = (value: FieldValue | undefined, values: FormValues) => true | string;
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Represents every value a field can hold.
|
|
189
|
-
*
|
|
190
|
-
* @remarks
|
|
191
|
-
* The variant follows the control: text-like controls hold a `string`, `number` holds a
|
|
192
|
-
* `number`, `confirm` holds a `boolean`, and `checkbox` holds its checked values as a
|
|
193
|
-
* `readonly string[]`.
|
|
194
|
-
*/
|
|
195
|
-
declare type FieldValue = string | number | boolean | readonly string[];
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Represents one or more files, by name.
|
|
199
|
-
*
|
|
200
|
-
* @remarks
|
|
201
|
-
* A value is the names alone: bytes never enter the document. `accept` lists the media types
|
|
202
|
-
* and extensions the control offers, in the form the host expects.
|
|
203
|
-
*/
|
|
204
|
-
declare interface FileField extends FieldBase {
|
|
205
|
-
readonly control: 'file';
|
|
206
|
-
readonly accept?: readonly string[];
|
|
207
|
-
readonly multiple?: boolean;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
24
|
/** Implements a controlled native form over a borrowed document. */
|
|
211
25
|
export declare class FormBinding implements FormBindingInterface {
|
|
212
26
|
#private;
|
|
@@ -283,7 +97,7 @@ export declare interface FormBindingInterface {
|
|
|
283
97
|
export declare interface FormBindingOptions {
|
|
284
98
|
readonly feedback?: ReadonlyMap<string, HTMLElement>;
|
|
285
99
|
readonly summary?: HTMLElement;
|
|
286
|
-
/** Maps native controls to focus targets whose departure touches the
|
|
100
|
+
/** Maps native controls to feedback and summary focus targets whose departure touches the field. */
|
|
287
101
|
readonly presentations?: ReadonlyMap<FormControl, HTMLElement>;
|
|
288
102
|
/** Defers blur touch until a same-form button's primary pointer press finishes. Default: false. */
|
|
289
103
|
readonly defer?: boolean;
|
|
@@ -300,340 +114,6 @@ export declare interface FormBindingValidity {
|
|
|
300
114
|
/** Represents a native answer control admitted by the binding. */
|
|
301
115
|
export declare type FormControl = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
|
|
302
116
|
|
|
303
|
-
/**
|
|
304
|
-
* Lists everything a form announces.
|
|
305
|
-
*
|
|
306
|
-
* @remarks
|
|
307
|
-
* `fill` carries the field that changed and its new value, where `undefined` is the value
|
|
308
|
-
* being cleared. `validate` carries the errors a check produced, empty when it found none.
|
|
309
|
-
* `disable` and `enable` each carry one field, and fire once per field whose state actually
|
|
310
|
-
* moved, in the order the schema declares them. `submit` fires only on a submit that passed.
|
|
311
|
-
* `touch` announces the first visit since clear. `prepare`, `accept`, and `abort` carry the receipt
|
|
312
|
-
* after their state is committed. `clear` and `abandon` are signals.
|
|
313
|
-
*/
|
|
314
|
-
declare type FormEventMap = {
|
|
315
|
-
readonly fill: readonly [name: string, value: FieldValue | undefined];
|
|
316
|
-
readonly touch: readonly [name: string];
|
|
317
|
-
readonly validate: readonly [errors: readonly FieldError[]];
|
|
318
|
-
readonly disable: readonly [name: string];
|
|
319
|
-
readonly enable: readonly [name: string];
|
|
320
|
-
readonly submit: readonly [values: FormValues];
|
|
321
|
-
readonly prepare: readonly [submission: FormSubmission];
|
|
322
|
-
readonly accept: readonly [submission: FormSubmission];
|
|
323
|
-
readonly abort: readonly [submission: FormSubmission];
|
|
324
|
-
readonly clear: readonly [];
|
|
325
|
-
readonly abandon: readonly [];
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* Represents any field a schema can declare.
|
|
330
|
-
*
|
|
331
|
-
* @remarks
|
|
332
|
-
* The union discriminates on `control`, so narrowing on that member reaches each variant's
|
|
333
|
-
* own options.
|
|
334
|
-
*
|
|
335
|
-
* @example
|
|
336
|
-
* ```ts
|
|
337
|
-
* function choices(field: FormField): readonly FieldChoice[] {
|
|
338
|
-
* return field.control === 'select' || field.control === 'checkbox' ? field.choices : []
|
|
339
|
-
* }
|
|
340
|
-
* ```
|
|
341
|
-
*/
|
|
342
|
-
declare type FormField = TextField | EditorField | PasswordField | NumberField | DateField | TimeField | DatetimeField | ColorField | ConfirmField | SelectField | CheckboxField | FileField;
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* Represents a named section of a form.
|
|
346
|
-
*
|
|
347
|
-
* @remarks
|
|
348
|
-
* A field joins a group through {@link FieldBase.group}. Grouping arranges the form and
|
|
349
|
-
* changes no answer.
|
|
350
|
-
*/
|
|
351
|
-
declare interface FormGroup {
|
|
352
|
-
readonly name: string;
|
|
353
|
-
readonly label: string;
|
|
354
|
-
readonly help?: string;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Declares the contract a form exposes: the state it holds and the calls that move it.
|
|
359
|
-
*
|
|
360
|
-
* @remarks
|
|
361
|
-
* `valid` is true when the last completed evaluation found no error, and `dirty` is true once
|
|
362
|
-
* an answer differs from its acknowledged baseline. Both are derived, never stored.
|
|
363
|
-
*
|
|
364
|
-
* `touched` holds the fields somebody has visited, which is what lets a renderer withhold an
|
|
365
|
-
* error until the person has had their turn at it.
|
|
366
|
-
*
|
|
367
|
-
* @example
|
|
368
|
-
* ```ts
|
|
369
|
-
* form.fill('email', 'ada@example.com')
|
|
370
|
-
* const result = form.submit()
|
|
371
|
-
* if (result.success) await form.answer
|
|
372
|
-
* ```
|
|
373
|
-
*/
|
|
374
|
-
declare interface FormInterface {
|
|
375
|
-
/** Holds the form's event emitter. */
|
|
376
|
-
readonly emitter: EmitterInterface<FormEventMap>;
|
|
377
|
-
/** Holds the schema this form asks. */
|
|
378
|
-
readonly schema: FormSchema;
|
|
379
|
-
/** Reports the answers the form holds. */
|
|
380
|
-
readonly values: FormValues;
|
|
381
|
-
/**
|
|
382
|
-
* Holds the acknowledged answers, initially the schema's defaults overlaid with seeded values.
|
|
383
|
-
*
|
|
384
|
-
* @remarks
|
|
385
|
-
* Acceptance advances only the enabled fields captured by the submission, including absence.
|
|
386
|
-
* It is what `dirty` measures against and what {@link FormInterface.clear} returns to.
|
|
387
|
-
*/
|
|
388
|
-
readonly baseline: FormValues;
|
|
389
|
-
/** Holds the submission awaiting acknowledgement, or `undefined` when none is pending. */
|
|
390
|
-
readonly pending: FormSubmission | undefined;
|
|
391
|
-
/** Holds every error the last check produced. */
|
|
392
|
-
readonly errors: readonly FieldError[];
|
|
393
|
-
/** Lists the names of the fields somebody has visited. */
|
|
394
|
-
readonly touched: ReadonlySet<string>;
|
|
395
|
-
/**
|
|
396
|
-
* Lists the names of the fields that are out of the form.
|
|
397
|
-
*
|
|
398
|
-
* @remarks
|
|
399
|
-
* It opens as the set the schema declares through {@link FieldBase.disabled} and moves with
|
|
400
|
-
* every {@link FormInterface.disable} and {@link FormInterface.enable} call, so the schema
|
|
401
|
-
* holds the declaration and this holds the current fact.
|
|
402
|
-
*/
|
|
403
|
-
readonly disabled: ReadonlySet<string>;
|
|
404
|
-
/** Reports where the form sits in its life. */
|
|
405
|
-
readonly status: FormStatus;
|
|
406
|
-
/** Reports whether the last completed evaluation found no error. */
|
|
407
|
-
readonly valid: boolean;
|
|
408
|
-
/** Reports whether any answer differs from its acknowledged baseline. */
|
|
409
|
-
readonly dirty: boolean;
|
|
410
|
-
/**
|
|
411
|
-
* Holds the answers after the form settles.
|
|
412
|
-
*
|
|
413
|
-
* @remarks
|
|
414
|
-
* It resolves with the submitted values on the first valid submit, and rejects when teardown
|
|
415
|
-
* abandons the form before it settles.
|
|
416
|
-
*/
|
|
417
|
-
readonly answer: Promise<FormValues>;
|
|
418
|
-
/**
|
|
419
|
-
* Finds one field by name.
|
|
420
|
-
*
|
|
421
|
-
* @param name - The field's name.
|
|
422
|
-
* @returns The field, or `undefined` when the schema declares no such name.
|
|
423
|
-
*/
|
|
424
|
-
field(name: string): FormField | undefined;
|
|
425
|
-
/**
|
|
426
|
-
* Answers one field, or several at once.
|
|
427
|
-
*
|
|
428
|
-
* @param values - The answers to write, each keyed by its field name.
|
|
429
|
-
*/
|
|
430
|
-
fill(values: FormValues): void;
|
|
431
|
-
/**
|
|
432
|
-
* Answers one field.
|
|
433
|
-
*
|
|
434
|
-
* @param name - The field's name.
|
|
435
|
-
* @param value - The answer to write, or `undefined` to clear it.
|
|
436
|
-
*/
|
|
437
|
-
fill(name: string, value: FieldValue | undefined): void;
|
|
438
|
-
/**
|
|
439
|
-
* Records that somebody has visited a field.
|
|
440
|
-
*
|
|
441
|
-
* @param name - The field's name.
|
|
442
|
-
*/
|
|
443
|
-
touch(name: string): void;
|
|
444
|
-
/**
|
|
445
|
-
* Fails a field from outside, for what the rules cannot see.
|
|
446
|
-
*
|
|
447
|
-
* @remarks
|
|
448
|
-
* One field holds one external failure, so a second call replaces the first, and the failure
|
|
449
|
-
* lasts until that field is filled again or the form is cleared.
|
|
450
|
-
* A receipt admits only a captured enabled field whose fill revision still matches. Stale,
|
|
451
|
-
* foreign, copied, consumed, and teardown-invalidated receipts return `false`; unknown fields
|
|
452
|
-
* still throw `FIELD`.
|
|
453
|
-
*
|
|
454
|
-
* @param name - The field's name.
|
|
455
|
-
* @param message - What to tell the person.
|
|
456
|
-
* @param submission - The active receipt to check against the field's captured revision.
|
|
457
|
-
* @returns True if the failure was applied; false if the receipt or field revision is stale.
|
|
458
|
-
*/
|
|
459
|
-
invalidate(name: string, message: string, submission?: FormSubmission): boolean;
|
|
460
|
-
/**
|
|
461
|
-
* Takes one field, several fields, or every field out of the form.
|
|
462
|
-
*
|
|
463
|
-
* @remarks
|
|
464
|
-
* A disabled field is neither evaluated nor submitted. Its answer is kept, and so is any
|
|
465
|
-
* {@link FormInterface.invalidate} failure it carries, which is withheld from `errors` while
|
|
466
|
-
* the field is out and restored when it comes back. The form emits `disable` once per field
|
|
467
|
-
* whose state actually moved, in schema order, so a call that moves nothing announces
|
|
468
|
-
* nothing. Disabling is a write, so a settled or abandoned form refuses it.
|
|
469
|
-
*/
|
|
470
|
-
disable(): void;
|
|
471
|
-
/**
|
|
472
|
-
* Takes one field out of the form.
|
|
473
|
-
*
|
|
474
|
-
* @param name - The field's name.
|
|
475
|
-
* @throws A {@link FormError} coded `FIELD` when the schema declares no such name.
|
|
476
|
-
*/
|
|
477
|
-
disable(name: string): void;
|
|
478
|
-
/**
|
|
479
|
-
* Takes several fields out of the form.
|
|
480
|
-
*
|
|
481
|
-
* @param names - The field names.
|
|
482
|
-
* @throws A {@link FormError} coded `FIELD` when the schema declares no such name. Every name
|
|
483
|
-
* is checked before any field moves, so one bad name leaves the whole call undone.
|
|
484
|
-
*/
|
|
485
|
-
disable(names: readonly string[]): void;
|
|
486
|
-
/**
|
|
487
|
-
* Puts one field, several fields, or every field back into the form.
|
|
488
|
-
*
|
|
489
|
-
* @remarks
|
|
490
|
-
* An enabled field is evaluated and submitted again, and any invalidation held while it was
|
|
491
|
-
* out reappears in `errors`. The form emits `enable` once per field whose state actually
|
|
492
|
-
* moved, in schema order. Enabling is a write, so a settled or abandoned form refuses it.
|
|
493
|
-
*/
|
|
494
|
-
enable(): void;
|
|
495
|
-
/**
|
|
496
|
-
* Puts one field back into the form.
|
|
497
|
-
*
|
|
498
|
-
* @param name - The field's name.
|
|
499
|
-
* @throws A {@link FormError} coded `FIELD` when the schema declares no such name.
|
|
500
|
-
*/
|
|
501
|
-
enable(name: string): void;
|
|
502
|
-
/**
|
|
503
|
-
* Puts several fields back into the form.
|
|
504
|
-
*
|
|
505
|
-
* @param names - The field names.
|
|
506
|
-
* @throws A {@link FormError} coded `FIELD` when the schema declares no such name. Every name
|
|
507
|
-
* is checked before any field moves, so one bad name leaves the whole call undone.
|
|
508
|
-
*/
|
|
509
|
-
enable(names: readonly string[]): void;
|
|
510
|
-
/**
|
|
511
|
-
* Checks every answer and settles the form when they all pass.
|
|
512
|
-
*
|
|
513
|
-
* @returns The values on success, or every error that stopped them.
|
|
514
|
-
*/
|
|
515
|
-
submit(): FormResult;
|
|
516
|
-
/**
|
|
517
|
-
* Prepares an owned enabled snapshot for acknowledgement while leaving the form editable.
|
|
518
|
-
*
|
|
519
|
-
* @returns The submission on success, or the errors that prevented preparation.
|
|
520
|
-
* @throws A {@link FormError} coded `PENDING` for an overlapping preparation or pending receipt,
|
|
521
|
-
* or when clear interrupts preparation; terminal forms retain their terminal refusals.
|
|
522
|
-
*/
|
|
523
|
-
prepare(): FormPreparationResult;
|
|
524
|
-
/**
|
|
525
|
-
* Adopts the active submission's captured answers into the baseline without changing live state.
|
|
526
|
-
*
|
|
527
|
-
* @param submission - The receipt returned by preparation.
|
|
528
|
-
* @returns True if this active receipt was accepted; false otherwise, including after teardown.
|
|
529
|
-
*/
|
|
530
|
-
accept(submission: FormSubmission): boolean;
|
|
531
|
-
/**
|
|
532
|
-
* Consumes the active submission and aborts its signal without changing answers or baseline.
|
|
533
|
-
*
|
|
534
|
-
* @param submission - The receipt returned by preparation.
|
|
535
|
-
* @returns True if this active receipt was aborted; false otherwise, including after teardown.
|
|
536
|
-
*/
|
|
537
|
-
abort(submission: FormSubmission): boolean;
|
|
538
|
-
/**
|
|
539
|
-
* Returns every answer to its acknowledged baseline and aborts pending acknowledgement.
|
|
540
|
-
*
|
|
541
|
-
* @remarks
|
|
542
|
-
* Those answers are {@link FormInterface.baseline}. The runtime disabled overlay resets with
|
|
543
|
-
* them, so {@link FormInterface.disabled} reads the schema's declarations again.
|
|
544
|
-
*/
|
|
545
|
-
clear(): void;
|
|
546
|
-
/**
|
|
547
|
-
* Tears the form down, abandoning it when it has not settled.
|
|
548
|
-
*
|
|
549
|
-
* @remarks
|
|
550
|
-
* Tearing down twice does nothing the second time. A request from inside a listener defers
|
|
551
|
-
* teardown until the outermost mutation batch closes, so an in-flight settlement can win and
|
|
552
|
-
* leave the form `settled` rather than `abandoned`.
|
|
553
|
-
*/
|
|
554
|
-
destroy(): void;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
/** Reports a prepared submission, or every error that prevented its preparation. */
|
|
558
|
-
declare type FormPreparationResult = Result<FormSubmission, readonly FieldError[]>;
|
|
559
|
-
|
|
560
|
-
/**
|
|
561
|
-
* Reports what a submit answers with: the values, or every error that stopped them.
|
|
562
|
-
*
|
|
563
|
-
* @example
|
|
564
|
-
* ```ts
|
|
565
|
-
* const result: FormResult = form.submit()
|
|
566
|
-
* const email = result.success ? result.value.email : undefined
|
|
567
|
-
* ```
|
|
568
|
-
*/
|
|
569
|
-
declare type FormResult = Result<FormValues, readonly FieldError[]>;
|
|
570
|
-
|
|
571
|
-
/**
|
|
572
|
-
* Describes everything a form asks.
|
|
573
|
-
*
|
|
574
|
-
* @remarks
|
|
575
|
-
* `fields` is the schema's only required member, and the order it declares is the order the
|
|
576
|
-
* form presents. `name`, `label`, and `help` describe the form itself.
|
|
577
|
-
*
|
|
578
|
-
* @example
|
|
579
|
-
* ```ts
|
|
580
|
-
* const schema: FormSchema = {
|
|
581
|
-
* label: 'Sign up',
|
|
582
|
-
* fields: [
|
|
583
|
-
* { control: 'text', name: 'email', label: 'Email', rule: { required: true, email: true } },
|
|
584
|
-
* { control: 'confirm', name: 'terms', label: 'I accept the terms' },
|
|
585
|
-
* ],
|
|
586
|
-
* }
|
|
587
|
-
* ```
|
|
588
|
-
*/
|
|
589
|
-
declare interface FormSchema {
|
|
590
|
-
readonly name?: string;
|
|
591
|
-
readonly label?: string;
|
|
592
|
-
readonly help?: string;
|
|
593
|
-
readonly groups?: readonly FormGroup[];
|
|
594
|
-
readonly fields: readonly FormField[];
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
/**
|
|
598
|
-
* Represents where a form sits in its life.
|
|
599
|
-
*
|
|
600
|
-
* @remarks
|
|
601
|
-
* A form opens `editing`, turns `settled` on its first valid submit, and turns `abandoned`
|
|
602
|
-
* when it is destroyed before settling. Both end states are terminal, and a write to a form
|
|
603
|
-
* in either one is refused. A destroy requested while a mutation batch is open is recorded,
|
|
604
|
-
* refuses every subsequent write immediately, and defers teardown until the outermost batch
|
|
605
|
-
* closes. The batch outcome wins: a batch that settles the form leaves it `settled`, resolves
|
|
606
|
-
* `answer`, and emits no `abandon`. Teardown never advances into, aborts, or rolls back the
|
|
607
|
-
* batch. The pending request is private, unnamed state and adds no fourth status.
|
|
608
|
-
*/
|
|
609
|
-
declare type FormStatus = 'editing' | 'settled' | 'abandoned';
|
|
610
|
-
|
|
611
|
-
/**
|
|
612
|
-
* Carries an owned, frozen answer snapshot and the signal for its pending acknowledgement.
|
|
613
|
-
*
|
|
614
|
-
* @remarks
|
|
615
|
-
* Only the producing form accepts this object's identity. Copying its members cannot create a
|
|
616
|
-
* receipt. The values and their lists are frozen; the native signal remains usable by transports.
|
|
617
|
-
*/
|
|
618
|
-
declare interface FormSubmission {
|
|
619
|
-
readonly values: FormValues;
|
|
620
|
-
readonly signal: AbortSignal;
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
/**
|
|
624
|
-
* Represents a form's answers, keyed by field name.
|
|
625
|
-
*
|
|
626
|
-
* @remarks
|
|
627
|
-
* A name with no key is a field nobody has answered. A disabled field's value may appear so a
|
|
628
|
-
* renderer can show it, but the value is never evaluated or submitted.
|
|
629
|
-
*
|
|
630
|
-
* @example
|
|
631
|
-
* ```ts
|
|
632
|
-
* const values: FormValues = { email: 'ada@example.com', terms: true }
|
|
633
|
-
* ```
|
|
634
|
-
*/
|
|
635
|
-
declare type FormValues = Readonly<Record<string, FieldValue>>;
|
|
636
|
-
|
|
637
117
|
/**
|
|
638
118
|
* Checks whether a value is a native binding refusal.
|
|
639
119
|
* @param value - The value to inspect.
|
|
@@ -668,25 +148,6 @@ export declare function isFormControl(value: unknown): value is FormControl;
|
|
|
668
148
|
*/
|
|
669
149
|
export declare function matchesFormControls(field: FormField, controls: readonly FormControl[]): boolean;
|
|
670
150
|
|
|
671
|
-
/** Represents a number. */
|
|
672
|
-
declare interface NumberField extends FieldBase {
|
|
673
|
-
readonly control: 'number';
|
|
674
|
-
readonly default?: number;
|
|
675
|
-
readonly placeholder?: string;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
/**
|
|
679
|
-
* Represents a secret, obscured as it is typed.
|
|
680
|
-
*
|
|
681
|
-
* @remarks
|
|
682
|
-
* It carries no `default` deliberately: a seeded secret is a secret written down. `mask` is
|
|
683
|
-
* the character the control repeats in place of the text.
|
|
684
|
-
*/
|
|
685
|
-
declare interface PasswordField extends FieldBase {
|
|
686
|
-
readonly control: 'password';
|
|
687
|
-
readonly mask?: string;
|
|
688
|
-
}
|
|
689
|
-
|
|
690
151
|
/**
|
|
691
152
|
* Reads one compatible native population using the document's blank-to-absence semantics.
|
|
692
153
|
* @param field - The field declaring the answer shape.
|
|
@@ -720,31 +181,4 @@ export declare function readFormControls(field: FormField, controls: readonly Fo
|
|
|
720
181
|
*/
|
|
721
182
|
export declare function readNativeMessages(control: FormControl, errors: readonly FieldError[]): readonly string[];
|
|
722
183
|
|
|
723
|
-
/**
|
|
724
|
-
* Represents one choice out of a list.
|
|
725
|
-
*
|
|
726
|
-
* @remarks
|
|
727
|
-
* `open` admits a value the list does not offer, which is what turns a closed menu into a
|
|
728
|
-
* suggestion list.
|
|
729
|
-
*/
|
|
730
|
-
declare interface SelectField extends FieldBase {
|
|
731
|
-
readonly control: 'select';
|
|
732
|
-
readonly choices: readonly FieldChoice[];
|
|
733
|
-
readonly default?: string;
|
|
734
|
-
readonly open?: boolean;
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
/** Represents a single line of text. */
|
|
738
|
-
declare interface TextField extends FieldBase {
|
|
739
|
-
readonly control: 'text';
|
|
740
|
-
readonly default?: string;
|
|
741
|
-
readonly placeholder?: string;
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
/** Represents a time of day, held as the control's own `HH:MM` string, with seconds optional. */
|
|
745
|
-
declare interface TimeField extends FieldBase {
|
|
746
|
-
readonly control: 'time';
|
|
747
|
-
readonly default?: string;
|
|
748
|
-
}
|
|
749
|
-
|
|
750
184
|
export { }
|