@optionfactory/fml 9.0.0-rc3 → 9.0.0-rc30
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 +16 -88
- package/dist/client-errors.iife.js +40 -49
- package/dist/client-errors.iife.js.map +1 -1
- package/dist/client-errors.iife.min.js +1 -1
- package/dist/client-errors.iife.min.js.map +1 -1
- package/dist/custom-elements.json +483 -50
- package/dist/fml.css +25 -20
- package/dist/fml.css.map +1 -1
- package/dist/fml.iife.js +5688 -2542
- package/dist/fml.iife.js.map +1 -1
- package/dist/fml.iife.min.js +1 -1
- package/dist/fml.iife.min.js.map +1 -1
- package/dist/ftl.d.mts +398 -227
- package/dist/ftl.iife.js +682 -1016
- package/dist/ftl.iife.js.map +1 -1
- package/dist/ftl.iife.min.js +1 -1
- package/dist/ftl.iife.min.js.map +1 -1
- package/dist/ftl.min.mjs +1 -1
- package/dist/ftl.min.mjs.map +1 -1
- package/dist/ftl.mjs +682 -1016
- package/dist/ftl.mjs.map +1 -1
- package/dist/ful.css +25 -20
- package/dist/ful.css.map +1 -1
- package/dist/ful.d.mts +3043 -546
- package/dist/ful.iife.js +4875 -1387
- package/dist/ful.iife.js.map +1 -1
- package/dist/ful.iife.min.js +1 -1
- package/dist/ful.iife.min.js.map +1 -1
- package/dist/ful.min.mjs +1 -1
- package/dist/ful.min.mjs.map +1 -1
- package/dist/ful.mjs +4873 -1389
- package/dist/ful.mjs.map +1 -1
- package/dist/httpc.d.mts +143 -123
- package/dist/httpc.iife.js +163 -175
- package/dist/httpc.iife.js.map +1 -1
- package/dist/httpc.iife.min.js +1 -1
- package/dist/httpc.iife.min.js.map +1 -1
- package/dist/httpc.min.mjs +1 -1
- package/dist/httpc.min.mjs.map +1 -1
- package/dist/httpc.mjs +163 -175
- package/dist/httpc.mjs.map +1 -1
- package/dist/vscode.html-custom-data.json +234 -38
- package/dist/web-types.json +489 -50
- package/package.json +2 -2
package/dist/ful.d.mts
CHANGED
|
@@ -1,25 +1,55 @@
|
|
|
1
1
|
import { ParsedElement } from './ftl.mjs';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
save: (k:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
2
|
+
import { HttpClient } from './httpc.mjs';
|
|
3
|
+
export type JsonStorage = {
|
|
4
|
+
/**
|
|
5
|
+
* stores `JSON.stringify(v)`
|
|
6
|
+
* under `k`, throwing what the encoding or the storage throws: an unreachable
|
|
7
|
+
* storage, a full quota, a value json cannot encode
|
|
8
|
+
*/
|
|
9
|
+
save: (k: string, v: any) => void;
|
|
10
|
+
/**
|
|
11
|
+
* the value stored under `k`, decoded;
|
|
12
|
+
* undefined when there is none, when the storage cannot be reached, or when the
|
|
13
|
+
* stored text is not json, in which case the entry is also removed
|
|
14
|
+
*/
|
|
15
|
+
load: (k: string) => any;
|
|
16
|
+
/**
|
|
17
|
+
* removes the entry under `k`
|
|
18
|
+
*/
|
|
19
|
+
remove: (k: string) => void;
|
|
20
|
+
/**
|
|
21
|
+
* what `load` answers for `k`, removing the
|
|
22
|
+
* entry
|
|
23
|
+
*/
|
|
24
|
+
pop: (k: string) => any;
|
|
17
25
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
26
|
+
export type VersionedJsonStorage = {
|
|
27
|
+
/**
|
|
28
|
+
* stores
|
|
29
|
+
* `data` with `revision` under `key`, throwing what `JsonStorage.save` throws
|
|
30
|
+
*/
|
|
31
|
+
save: (key: string, revision: string, data: any) => void;
|
|
32
|
+
/**
|
|
33
|
+
* the data stored under
|
|
34
|
+
* `key` when it was saved with this exact revision; otherwise undefined, and the
|
|
35
|
+
* entry is removed, whether it holds another revision, holds no revision at
|
|
36
|
+
* all, or is missing
|
|
37
|
+
*/
|
|
38
|
+
load: (key: string, revision: string) => any;
|
|
21
39
|
};
|
|
40
|
+
/** `localStorage`, holding json. */
|
|
41
|
+
declare const LocalStorage: JsonStorage;
|
|
42
|
+
/** `sessionStorage`, holding json. */
|
|
43
|
+
declare const SessionStorage: JsonStorage;
|
|
44
|
+
/** `localStorage`, holding json beside a revision. */
|
|
45
|
+
declare const VersionedLocalStorage: VersionedJsonStorage;
|
|
46
|
+
/** `sessionStorage`, holding json beside a revision. */
|
|
47
|
+
declare const VersionedSessionStorage: VersionedJsonStorage;
|
|
22
48
|
export type AsyncExtension = {
|
|
49
|
+
/**
|
|
50
|
+
* one per `asyncOn` listener the event
|
|
51
|
+
* reached, in the order they ran
|
|
52
|
+
*/
|
|
23
53
|
promises: Promise<any>[];
|
|
24
54
|
};
|
|
25
55
|
export type AsyncEvent = Event & {
|
|
@@ -27,7 +57,8 @@ export type AsyncEvent = Event & {
|
|
|
27
57
|
};
|
|
28
58
|
/**
|
|
29
59
|
* @typedef {Object} AsyncExtension
|
|
30
|
-
* @property {Promise<any>[]} promises
|
|
60
|
+
* @property {Promise<any>[]} promises one per `asyncOn` listener the event
|
|
61
|
+
* reached, in the order they ran
|
|
31
62
|
* @typedef {Event & { async?: AsyncExtension }} AsyncEvent
|
|
32
63
|
*/
|
|
33
64
|
/**
|
|
@@ -38,42 +69,80 @@ export type AsyncEvent = Event & {
|
|
|
38
69
|
*/
|
|
39
70
|
declare class AsyncEvents {
|
|
40
71
|
/**
|
|
41
|
-
* Dispatches
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
72
|
+
* Dispatches `evt` on `el` synchronously, then waits for the answers of the
|
|
73
|
+
* `asyncOn` listeners it reached, on `el` or, for a bubbling event, on its
|
|
74
|
+
* ancestors. Listeners added with a plain `addEventListener` run but are not
|
|
75
|
+
* awaited. In `broadcast` mode, the default, it resolves with every answer
|
|
76
|
+
* in the order the listeners ran, an empty array when none did. In
|
|
77
|
+
* `pipeline` mode it accepts at most one listener and resolves with its
|
|
78
|
+
* answer, or undefined when none ran. In `delegate` mode it requires exactly
|
|
79
|
+
* one listener and resolves with its answer.
|
|
80
|
+
* @param {HTMLElement} el the element to dispatch on
|
|
81
|
+
* @param {AsyncEvent} evt the event to dispatch
|
|
82
|
+
* @param {{mode?: 'broadcast' | 'pipeline' | 'delegate'}} [options]
|
|
83
|
+
* @returns {Promise<any>} the answer or answers as the mode describes
|
|
84
|
+
* @throws what the first answer to fail threw or rejected with; or an
|
|
85
|
+
* Error naming the event and the mode when `pipeline` reached more than one
|
|
86
|
+
* listener or `delegate` did not reach exactly one, in which case the
|
|
87
|
+
* listeners have already run and their outcome is discarded. Both arrive as
|
|
88
|
+
* the rejection of the returned promise.
|
|
46
89
|
*/
|
|
47
90
|
static fireAsync(el: HTMLElement, evt: AsyncEvent, options?: {
|
|
48
91
|
mode?: 'broadcast' | 'pipeline' | 'delegate';
|
|
49
92
|
}): Promise<any>;
|
|
50
93
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
94
|
+
* Adds a listener whose answer `fireAsync` can await. When the event
|
|
95
|
+
* reaches it, the listener attaches a promise to `evt.async.promises`,
|
|
96
|
+
* creating the list when it is the first, then calls `fn` with the event;
|
|
97
|
+
* the promise settles with what `fn` returns or throws, awaited when it is a
|
|
98
|
+
* promise. The event is dispatched the usual way, so an event fired with a
|
|
99
|
+
* plain `dispatchEvent` runs `fn` too, and nobody awaits its answer.
|
|
100
|
+
* @param {HTMLElement} el the element to listen on
|
|
101
|
+
* @param {string} type the event type
|
|
102
|
+
* @param {(evt: any) => any} fn called with the event; its result is the answer
|
|
103
|
+
* @param {AddEventListenerOptions} [options] passed to `addEventListener`
|
|
104
|
+
* @returns {EventListener} the listener actually added, which `asyncOff` takes
|
|
57
105
|
*/
|
|
58
|
-
static asyncOn(el: HTMLElement, type: string, fn:
|
|
106
|
+
static asyncOn(el: HTMLElement, type: string, fn: (evt: any) => any, options?: AddEventListenerOptions): EventListener;
|
|
59
107
|
/**
|
|
60
|
-
*
|
|
61
|
-
* @param {HTMLElement} el
|
|
62
|
-
* @param {string} type
|
|
63
|
-
* @param {EventListener} listener
|
|
64
|
-
* @param {EventListenerOptions} [options]
|
|
108
|
+
* Removes a listener added by `asyncOn`.
|
|
109
|
+
* @param {HTMLElement} el the element it listens on
|
|
110
|
+
* @param {string} type the event type it was added for
|
|
111
|
+
* @param {EventListener} listener what `asyncOn` returned, not the `fn` given to it
|
|
112
|
+
* @param {EventListenerOptions} [options] passed to `removeEventListener`
|
|
113
|
+
* @returns {void}
|
|
65
114
|
*/
|
|
66
115
|
static asyncOff(el: HTMLElement, type: string, listener: EventListener, options?: EventListenerOptions): void;
|
|
67
116
|
/**
|
|
68
|
-
*
|
|
69
|
-
*
|
|
117
|
+
* Assigns `fireAsync(evt, options)`, `asyncOn(type, fn, options)` and
|
|
118
|
+
* `asyncOff(type, listener, options)` onto each class's prototype, each
|
|
119
|
+
* calling the static of the same name with the instance as the element.
|
|
120
|
+
* Members of those names already on the prototype are overwritten.
|
|
121
|
+
* @param {...Function} classes the classes to extend
|
|
122
|
+
* @returns {void}
|
|
70
123
|
*/
|
|
71
124
|
static mixInto(...classes: Function[]): void;
|
|
72
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* Asks before the page is left, through the browser's own `beforeunload`
|
|
128
|
+
* prompt.
|
|
129
|
+
*/
|
|
130
|
+
declare class PageLeave {
|
|
131
|
+
/**
|
|
132
|
+
* Asks before the page is left while `isDirty()` answers true, until
|
|
133
|
+
* `signal` aborts. The browser words the prompt, and asks only once the
|
|
134
|
+
* user has interacted with the page.
|
|
135
|
+
* @param {() => boolean} isDirty
|
|
136
|
+
* @param {AbortSignal} [signal]
|
|
137
|
+
*/
|
|
138
|
+
static guard(isDirty: () => boolean, signal?: AbortSignal): void;
|
|
139
|
+
}
|
|
73
140
|
export type Claim = {
|
|
74
141
|
readonly stale: boolean;
|
|
75
142
|
};
|
|
76
143
|
/**
|
|
144
|
+
* A hold on one generation of a `Claims`: `stale` turns true once a later
|
|
145
|
+
* `take()` or `invalidate()` on it starts a newer generation.
|
|
77
146
|
* @typedef {{ readonly stale: boolean }} Claim
|
|
78
147
|
*/
|
|
79
148
|
/**
|
|
@@ -99,50 +168,95 @@ declare class Claims {
|
|
|
99
168
|
* @returns {Claim}
|
|
100
169
|
*/
|
|
101
170
|
hold(): Claim;
|
|
102
|
-
/**
|
|
171
|
+
/**
|
|
172
|
+
* Supersedes every claim without holding a new one.
|
|
173
|
+
* @returns {void}
|
|
174
|
+
*/
|
|
103
175
|
invalidate(): void;
|
|
104
176
|
}
|
|
177
|
+
export type Describable = {
|
|
178
|
+
describedBy(el: HTMLElement): boolean;
|
|
179
|
+
};
|
|
105
180
|
/**
|
|
106
|
-
*
|
|
107
|
-
*
|
|
181
|
+
* Something that adds elements to the accessible description of the control it
|
|
182
|
+
* owns, such as a field: `describedBy(el)` adds `el` to the control's
|
|
183
|
+
* `aria-describedby` and answers whether it did.
|
|
184
|
+
* @typedef {{ describedBy(el: HTMLElement): boolean }} Describable
|
|
185
|
+
*/
|
|
186
|
+
/**
|
|
187
|
+
* The nearest ancestor of `el` that has a `describedBy` method. Content
|
|
188
|
+
* slotted inside a field does not write the control's `aria-describedby`
|
|
189
|
+
* itself: once it has something to offer, it hands the element carrying the
|
|
190
|
+
* words to the `describedBy` of the ancestor this answers.
|
|
191
|
+
* @param {Element} el
|
|
192
|
+
* @returns {(Element & Describable) | null} null when no ancestor has one
|
|
193
|
+
*/
|
|
194
|
+
declare const describable: (el: Element) => (Element & Describable) | null;
|
|
195
|
+
/**
|
|
196
|
+
* Sleeping, debouncing and throttling. `debounce` and `throttle` both return
|
|
197
|
+
* the wrapped function together with an abort function, which cancels the call
|
|
198
|
+
* pending and leaves the wrapped function working.
|
|
108
199
|
*/
|
|
109
200
|
declare class Timing {
|
|
110
|
-
/** Resolves after the given milliseconds. @param {number} ms */
|
|
111
|
-
static sleep(ms: number): Promise<any>;
|
|
112
201
|
/**
|
|
113
|
-
*
|
|
114
|
-
*
|
|
202
|
+
* @param {number} ms
|
|
203
|
+
* @returns {Promise<void>} resolving after `ms` milliseconds
|
|
204
|
+
*/
|
|
205
|
+
static sleep(ms: number): Promise<void>;
|
|
206
|
+
/**
|
|
207
|
+
* Collapses a burst of calls into one call of `func`, a burst ending once
|
|
208
|
+
* `timeoutMs` pass without a call. By default `func` is called at the end
|
|
209
|
+
* of the burst with the arguments of its last call. With `immediate` it is
|
|
210
|
+
* called at the first call of a burst, with that call's arguments, and not
|
|
211
|
+
* at the end. Without `immediate`, a call the wrapped function receives
|
|
212
|
+
* from inside `func` starts a new burst.
|
|
115
213
|
* @param {number} timeoutMs
|
|
116
|
-
* @param {
|
|
117
|
-
* @param {{ immediate?: boolean }} [options]
|
|
118
|
-
* @returns {[
|
|
214
|
+
* @param {(...args: any[]) => any} func
|
|
215
|
+
* @param {{ immediate?: boolean }} [options]
|
|
216
|
+
* @returns {[(...args: any[]) => void, () => void]} the wrapped function
|
|
217
|
+
* and the abort function
|
|
119
218
|
*/
|
|
120
|
-
static debounce(timeoutMs: number, func:
|
|
219
|
+
static debounce(timeoutMs: number, func: (...args: any[]) => any, options?: {
|
|
121
220
|
immediate?: boolean;
|
|
122
|
-
}): [
|
|
221
|
+
}): [(...args: any[]) => void, () => void];
|
|
123
222
|
/**
|
|
124
|
-
*
|
|
223
|
+
* Calls `func` at most once per `timeoutMs`, always with the arguments of
|
|
224
|
+
* the latest call. With `leading`, on by default, a call arriving once the
|
|
225
|
+
* interval since the previous call of `func` has passed calls it at once;
|
|
226
|
+
* without it, the first call only starts the interval. With `trailing`, on
|
|
227
|
+
* by default, a call arriving inside the interval schedules `func` for the
|
|
228
|
+
* interval's end; without it, such a call is dropped.
|
|
125
229
|
* @param {number} timeoutMs
|
|
126
|
-
* @param {
|
|
127
|
-
* @param {{ leading?: boolean, trailing?: boolean }} [options]
|
|
128
|
-
* @returns {[
|
|
230
|
+
* @param {(...args: any[]) => any} func
|
|
231
|
+
* @param {{ leading?: boolean, trailing?: boolean }} [options]
|
|
232
|
+
* @returns {[(...args: any[]) => void, () => void]} the wrapped function
|
|
233
|
+
* and the abort function
|
|
129
234
|
*/
|
|
130
|
-
static throttle(timeoutMs: number, func:
|
|
235
|
+
static throttle(timeoutMs: number, func: (...args: any[]) => any, options?: {
|
|
131
236
|
leading?: boolean;
|
|
132
237
|
trailing?: boolean;
|
|
133
|
-
}): [
|
|
238
|
+
}): [(...args: any[]) => void, () => void];
|
|
134
239
|
}
|
|
135
|
-
/**
|
|
240
|
+
/**
|
|
241
|
+
* Moves values between a form's named controls and a nested object, and pins
|
|
242
|
+
* problems onto the controls they name. Works on any native form, not only
|
|
243
|
+
* the one inside a `ful-form`. Every method reads the controls through
|
|
244
|
+
* `form.elements`, so a control in the subtree that belongs to another form
|
|
245
|
+
* (a nested form, a `form` attribute pointing elsewhere) is never read,
|
|
246
|
+
* written or marked.
|
|
247
|
+
*/
|
|
136
248
|
declare class Bindings {
|
|
137
249
|
#private;
|
|
138
250
|
/**
|
|
139
|
-
* Flattens a nested object into dotted keys,
|
|
140
|
-
* a
|
|
141
|
-
* `address
|
|
251
|
+
* Flattens a nested object into dotted keys, array indexes becoming numeric
|
|
252
|
+
* segments (`a.0.b`). It does not descend below a key that `stops` names, so
|
|
253
|
+
* with a field named `address` the whole object is kept under `address`,
|
|
254
|
+
* while with one named `address.city` the leaf is kept under `address.city`.
|
|
255
|
+
* A null value is kept as a leaf.
|
|
142
256
|
* @param {{ [x: string]: any; }} obj
|
|
143
|
-
* @param {string} prefix
|
|
144
|
-
* @param {Set<
|
|
145
|
-
* @
|
|
257
|
+
* @param {string} prefix prepended to every key, `''` at the root
|
|
258
|
+
* @param {Set<string>} stops the dotted keys to keep whole
|
|
259
|
+
* @returns {{ [x: string]: any; }} a flat object keyed by dotted path
|
|
146
260
|
*/
|
|
147
261
|
static flatten(obj: {
|
|
148
262
|
[x: string]: any;
|
|
@@ -151,19 +265,37 @@ declare class Bindings {
|
|
|
151
265
|
};
|
|
152
266
|
/**
|
|
153
267
|
* Writes a value into an object at a dotted path, creating the intermediate
|
|
154
|
-
* objects and arrays the path implies
|
|
155
|
-
*
|
|
156
|
-
*
|
|
268
|
+
* objects and arrays the path implies: a numeric segment makes its container
|
|
269
|
+
* an array. Brackets are not parsed, so `a[0]` is a plain key.
|
|
270
|
+
*
|
|
271
|
+
* An undefined value declares the path without filling it: an entry already
|
|
272
|
+
* there is kept, a missing one is set to null. A scalar or a null left on the
|
|
273
|
+
* path by a shorter overlapping name (`a` written before `a.b`) is replaced
|
|
274
|
+
* by a container, so the longer name wins whichever order they arrive in.
|
|
275
|
+
* @param {any} result the object or array to write into
|
|
276
|
+
* @param {string} path a dotted name such as `a.b` or `a.0.b`
|
|
157
277
|
* @param {any} value
|
|
278
|
+
* @returns {any} the root written into, to be used in place of `result`: a
|
|
279
|
+
* new array replaces it when the first segment is numeric and `result` is
|
|
280
|
+
* not an array
|
|
281
|
+
* @throws {Error} when a segment is `__proto__`, `prototype` or `constructor`,
|
|
282
|
+
* before anything is written
|
|
158
283
|
*/
|
|
159
284
|
static providePath(result: any, path: string, value: any): any;
|
|
160
285
|
/**
|
|
161
|
-
* Reads one control's value
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
286
|
+
* Reads one control's value by its kind. The kind is read from the `type`
|
|
287
|
+
* attribute and the tag, so a ful element answers its own `value`.
|
|
288
|
+
*
|
|
289
|
+
* - a radio answers its `value` when checked and undefined otherwise
|
|
290
|
+
* - a checkbox answers its `checked` state
|
|
291
|
+
* - `data-ful-bind-type="boolean"` decodes the value: a radio answers
|
|
292
|
+
* whether its value is `'true'`, any other control answers null when
|
|
293
|
+
* blank and whether its value is `'true'` otherwise
|
|
294
|
+
* - a multiple select answers the array of its selected values
|
|
295
|
+
* - a native input, select or textarea answers null when blank
|
|
296
|
+
* - anything else answers its `value` unchanged
|
|
165
297
|
* @param {Element & {dataset?: any} & {checked?: boolean} & {value?: any}} el
|
|
166
|
-
* @returns {any} the value
|
|
298
|
+
* @returns {any} the value; undefined for an unchecked radio
|
|
167
299
|
*/
|
|
168
300
|
static extract(el: Element & {
|
|
169
301
|
dataset?: any;
|
|
@@ -172,13 +304,32 @@ declare class Bindings {
|
|
|
172
304
|
} & {
|
|
173
305
|
value?: any;
|
|
174
306
|
}): any;
|
|
175
|
-
static extractFrom(form: any, submitter: any): {};
|
|
176
307
|
/**
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
308
|
+
* Reads the form's named controls into a nested object, the dotted names
|
|
309
|
+
* deciding its shape (see `providePath`) and each value read by `extract`.
|
|
310
|
+
* Controls are read in document order, so of two overlapping names the
|
|
311
|
+
* later one decides. A control is skipped when it has no `name`, when it
|
|
312
|
+
* matches `:disabled` (its own `disabled` or a disabled fieldset's), or when
|
|
313
|
+
* it is a submit, reset or plain button. The submitter is the exception to
|
|
314
|
+
* both of the last two: it contributes its name and value even while
|
|
315
|
+
* disabled.
|
|
316
|
+
* @param {HTMLFormElement} form
|
|
317
|
+
* @param {HTMLElement} [submitter] the button that submitted, when there is one
|
|
318
|
+
* @returns {any} the nested values; an array when the first segment of a name is numeric
|
|
319
|
+
* @throws {Error} when a name has a segment `providePath` refuses
|
|
320
|
+
*/
|
|
321
|
+
static extractFrom(form: HTMLFormElement, submitter?: HTMLElement): any;
|
|
322
|
+
/**
|
|
323
|
+
* Writes a value into one control, the inverse of `extract`.
|
|
324
|
+
*
|
|
325
|
+
* - a radio is checked when `raw` is not null and its `value` attribute
|
|
326
|
+
* equals `String(raw)`, so a number or a boolean matches its text
|
|
327
|
+
* - a checkbox takes `raw` as its `checked` state
|
|
328
|
+
* - a multiple select selects the options whose value is in `raw`, compared
|
|
329
|
+
* as text: an array selects each entry, a scalar selects one, null selects none
|
|
330
|
+
* - anything else takes `raw` as its `value`
|
|
180
331
|
* @param {Element & {dataset?: any} & {checked?: boolean} & {value?: any}} el
|
|
181
|
-
* @param {any} raw
|
|
332
|
+
* @param {any} raw
|
|
182
333
|
*/
|
|
183
334
|
static mutate(el: Element & {
|
|
184
335
|
dataset?: any;
|
|
@@ -187,8 +338,60 @@ declare class Bindings {
|
|
|
187
338
|
} & {
|
|
188
339
|
value?: any;
|
|
189
340
|
}, raw: any): void;
|
|
190
|
-
|
|
191
|
-
|
|
341
|
+
/**
|
|
342
|
+
* Writes a nested object onto the form's named controls: the object is
|
|
343
|
+
* flattened with the control names as stops (see `flatten`), and each key
|
|
344
|
+
* is written by `mutate` into every control carrying exactly that name. A
|
|
345
|
+
* key naming no control is ignored, and a control the object does not name
|
|
346
|
+
* keeps its value.
|
|
347
|
+
* @param {HTMLFormElement} form
|
|
348
|
+
* @param {{ [x: string]: any; }} values
|
|
349
|
+
*/
|
|
350
|
+
static mutateIn(form: HTMLFormElement, values: {
|
|
351
|
+
[x: string]: any;
|
|
352
|
+
}): void;
|
|
353
|
+
/**
|
|
354
|
+
* Shows problems on the form, replacing whatever the previous call showed.
|
|
355
|
+
*
|
|
356
|
+
* Every named control's custom validity is first cleared. A problem whose
|
|
357
|
+
* `type` is `FIELD_ERROR` or `INVALID_FORMAT` and whose `context` is not
|
|
358
|
+
* empty is pinned to a control: brackets in the context are turned into
|
|
359
|
+
* dots (`users[0].name` becomes `users.0.name`), and the longest leading
|
|
360
|
+
* part of it that names a control wins, so an exact field takes the problem
|
|
361
|
+
* alone and a composite field named for a prefix catches the problems of its
|
|
362
|
+
* subtree. Each control of that name gets `setCustomValidity(reason, rest)`,
|
|
363
|
+
* `rest` being the remainder of the path (`''` on an exact match) that a
|
|
364
|
+
* composite can use to route the problem to an inner control. Several
|
|
365
|
+
* problems reaching one control with the same `rest` are joined one per
|
|
366
|
+
* line into a single call.
|
|
367
|
+
*
|
|
368
|
+
* A control counts only when it can show a problem, through a
|
|
369
|
+
* `setCustomValidity` of its own: a form-associated element that has none is
|
|
370
|
+
* skipped, so its problems fall to a shorter prefix or to the banner instead
|
|
371
|
+
* of being dropped.
|
|
372
|
+
*
|
|
373
|
+
* Every other problem, and a field problem naming no control, is shown in
|
|
374
|
+
* each `ful-errors` banner of the form: the banner gets `role="alert"`, is
|
|
375
|
+
* revealed and holds the reasons one per line. With no such problem the
|
|
376
|
+
* banner is emptied and hidden.
|
|
377
|
+
*
|
|
378
|
+
* Each `ful-field-error` of the form gets `aria-live="off"` when
|
|
379
|
+
* `scrollOnError` is set, since focusing the field announces its error, and
|
|
380
|
+
* `aria-live="polite"` otherwise. With `scrollOnError` and at least one
|
|
381
|
+
* problem, the topmost `:invalid` control is focused; a `<fieldset>`
|
|
382
|
+
* matching `:invalid` for the controls it holds is not a candidate.
|
|
383
|
+
*
|
|
384
|
+
* A banner or `ful-field-error` belongs to the nearest enclosing form, so
|
|
385
|
+
* those of a nested form are left alone.
|
|
386
|
+
* @param {HTMLFormElement} form
|
|
387
|
+
* @param {{ type: string; context?: string | null; reason: string; }[]} es the problems, as an httpc `Failure` carries them
|
|
388
|
+
* @param {boolean} scrollOnError
|
|
389
|
+
*/
|
|
390
|
+
static errors(form: HTMLFormElement, es: {
|
|
391
|
+
type: string;
|
|
392
|
+
context?: string | null;
|
|
393
|
+
reason: string;
|
|
394
|
+
}[], scrollOnError: boolean): void;
|
|
192
395
|
}
|
|
193
396
|
/**
|
|
194
397
|
* The base of every form-associated ful field: a form-associated custom element
|
|
@@ -197,181 +400,339 @@ declare class Bindings {
|
|
|
197
400
|
*
|
|
198
401
|
* A subclass owns its template, its value semantics and its change events. It
|
|
199
402
|
* implements `_build(conf)`, which builds its dom and returns the pieces the
|
|
200
|
-
* base drives
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
403
|
+
* base drives (see `_build`), and the `value` pair. The base wires the pieces,
|
|
404
|
+
* mounts the fragment and applies the declared state. Nothing in the base is
|
|
405
|
+
* there to be called from a subclass's build.
|
|
406
|
+
*
|
|
407
|
+
* The claim setters, the validity protocol and the aria wiring all act on the
|
|
408
|
+
* pieces, so a field with no native control returns a focusable piece of its
|
|
409
|
+
* own chrome as the control. The claims, `value` and `focus()` are the
|
|
410
|
+
* members that tolerate a not yet rendered element: before the render the
|
|
411
|
+
* `value` getter answers what the rendered field would answer from its current
|
|
412
|
+
* declared state, and a value written then is held and applied by the render
|
|
413
|
+
* (see `_holdValue`). The other members need the pieces and so work only after
|
|
414
|
+
* the render.
|
|
415
|
+
*
|
|
416
|
+
* The inner controls carry `form=""`, so the host is the only element the form
|
|
417
|
+
* sees. Enter pressed in an inner `<input>` of any type but `file`, `button`,
|
|
418
|
+
* `submit`, `reset` and `image` submits the field's form through
|
|
419
|
+
* `_requestSubmit()`, as Enter in a native input would. It does not when a
|
|
420
|
+
* listener inside the field already called `preventDefault()` on the keydown,
|
|
421
|
+
* while an input method is composing, or when the input is still associated
|
|
422
|
+
* with the form itself and so submits on its own.
|
|
212
423
|
*/
|
|
213
424
|
declare class Field extends ParsedElement {
|
|
214
425
|
#private;
|
|
215
426
|
static formAssociated: boolean;
|
|
216
427
|
/**
|
|
217
|
-
* The claim attributes and the value
|
|
218
|
-
* including
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
* `value:csv`, `value:json`).
|
|
428
|
+
* The claim attributes and the value, observed so that every field,
|
|
429
|
+
* including a custom one that never lists them, keeps them live after the
|
|
430
|
+
* upgrade. A subclass's own `static observed` adds to this list. The value
|
|
431
|
+
* is read with the string mapper; a field with another vocabulary redeclares
|
|
432
|
+
* it with its own (`value:bool`, `value:csv`, `value:json`).
|
|
433
|
+
* @type {string[]}
|
|
224
434
|
*/
|
|
225
435
|
static observed: string[];
|
|
226
|
-
/**
|
|
436
|
+
/**
|
|
437
|
+
* The role set on the element internals at construction. A field whose host
|
|
438
|
+
* is the widget itself overrides it, as `RadioGroup` does with `'radiogroup'`.
|
|
439
|
+
* @type {string}
|
|
440
|
+
*/
|
|
227
441
|
static ROLE: string;
|
|
442
|
+
/** Sets the internals' role from the subclass's `static ROLE`. */
|
|
228
443
|
constructor();
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
* control
|
|
239
|
-
*
|
|
240
|
-
*
|
|
444
|
+
/**
|
|
445
|
+
* Adds an element to the accessible description of the field and answers
|
|
446
|
+
* whether the field took it.
|
|
447
|
+
*
|
|
448
|
+
* The field takes a description before its own render as readily as after:
|
|
449
|
+
* one handed over early is written as soon as the field has rendered, so the
|
|
450
|
+
* caller does not need to know which of the two upgraded first. The element
|
|
451
|
+
* is given an id (`ful-described-*`) when it has none, is added once however
|
|
452
|
+
* often it is offered, and is referenced from the `aria-describedby`
|
|
453
|
+
* attribute of the `described` piece (the control by default). The
|
|
454
|
+
* descriptions come in the order they were offered, the error region always
|
|
455
|
+
* last.
|
|
456
|
+
*
|
|
457
|
+
* Pass the element that carries the words rather than a wrapper around it:
|
|
458
|
+
* a hidden element is part of a description only where it is referenced
|
|
459
|
+
* directly, so a popover that is closed until opened must be passed itself.
|
|
460
|
+
*
|
|
461
|
+
* This is the field's half of the description protocol; `describable` in
|
|
462
|
+
* `ful/descriptions.mjs` is the half the content uses to find the field.
|
|
463
|
+
* @param {HTMLElement | null | undefined} el
|
|
464
|
+
* @returns {boolean} false only when `el` is missing
|
|
465
|
+
*/
|
|
466
|
+
describedBy(el: HTMLElement | null | undefined): boolean;
|
|
467
|
+
/**
|
|
468
|
+
* Moves the focus to the `control` piece. Asked before the render, the
|
|
469
|
+
* request is kept (the last one wins) and applied once the control is
|
|
470
|
+
* mounted.
|
|
471
|
+
* @param {FocusOptions} [options]
|
|
472
|
+
*/
|
|
473
|
+
focus(options?: FocusOptions): void;
|
|
474
|
+
/**
|
|
475
|
+
* Clears or reports one validation problem. A message sets a custom error on
|
|
476
|
+
* the element internals, which makes the host match `:invalid`, renders the
|
|
477
|
+
* message into the `error` piece and sets `aria-invalid="true"` on the
|
|
478
|
+
* `announces` piece, or on the `control` when the field announces nowhere.
|
|
479
|
+
* An empty or missing message clears all three.
|
|
480
|
+
*
|
|
481
|
+
* Validation is the server's: the submit is sent regardless, and the form's
|
|
482
|
+
* error mapping calls this with the problems that come back. It calls the
|
|
483
|
+
* field with the most specific name a problem's context reaches and passes
|
|
484
|
+
* the rest of the path as `context`. The base ignores `context`; a composite
|
|
485
|
+
* field owning a whole subtree overrides this to route the message to the
|
|
486
|
+
* inner control the path names.
|
|
487
|
+
*
|
|
488
|
+
* Needs the render: before it there is no error region to write to.
|
|
489
|
+
* @param {string} [error] the message, empty or missing to clear
|
|
490
|
+
* @param {string} [context] the path below this field's name, '' on an exact match
|
|
241
491
|
*/
|
|
242
492
|
setCustomValidity(error?: string, context?: string): void;
|
|
243
|
-
/**
|
|
493
|
+
/**
|
|
494
|
+
* The form the platform associated the field with, as a native control's
|
|
495
|
+
* own `form`.
|
|
496
|
+
* @returns {HTMLFormElement | null} null outside a form
|
|
497
|
+
*/
|
|
498
|
+
get form(): HTMLFormElement | null;
|
|
499
|
+
/**
|
|
500
|
+
* Submits the associated form with `requestSubmit`, so constraint validation
|
|
501
|
+
* and the `submit` event run as for a user's submit. The submitter is the
|
|
502
|
+
* first enabled `button` or `input` of type `submit` in the form whose own
|
|
503
|
+
* `form` is that form; with none the form is submitted without one. Does
|
|
504
|
+
* nothing outside a form.
|
|
505
|
+
*/
|
|
244
506
|
_requestSubmit(): void;
|
|
245
507
|
/**
|
|
246
|
-
* Dispatches the field's change event: bubbling, not
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
508
|
+
* Dispatches the field's `change` event on the host: bubbling, not
|
|
509
|
+
* cancelable, with `{ value: this.value, ...extras }` as the detail. Call it
|
|
510
|
+
* for a change the user made. Every field in the library announces through this method and
|
|
511
|
+
* passes no `value` key in `extras`, so a listener can rely on
|
|
512
|
+
* `el.value === evt.detail.value`. The extras are spread after `value`, so a
|
|
513
|
+
* `value` key among them would replace it.
|
|
514
|
+
* @param {Record<string, any>} [extras] further detail keys beside `value`
|
|
252
515
|
*/
|
|
253
516
|
_notifyChange(extras?: Record<string, any>): void;
|
|
254
517
|
/**
|
|
255
|
-
* Whether the field's chrome should
|
|
256
|
-
* menus and labels are not form controls, so
|
|
257
|
-
*
|
|
258
|
-
* disabled
|
|
259
|
-
*
|
|
518
|
+
* Whether the field's own chrome should act on a gesture. Badges, dropzones,
|
|
519
|
+
* menus and labels are not form controls, so the platform does not disable
|
|
520
|
+
* them: every handler on them asks this first. False while the host matches
|
|
521
|
+
* `:disabled`, which covers a disabled `<fieldset>` ancestry as well as the
|
|
522
|
+
* claim, or while the readonly claim holds.
|
|
523
|
+
* @returns {boolean}
|
|
260
524
|
*/
|
|
261
525
|
_interactive(): boolean;
|
|
262
526
|
/**
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
527
|
+
* Upgrades as `ParsedElement.upgrade` does, then writes the value held by
|
|
528
|
+
* `_holdValue`, if any, through the `value` setter: the value written
|
|
529
|
+
* before the render wins over the declared one.
|
|
530
|
+
* @returns {Promise<void>} rejecting with what the render threw
|
|
531
|
+
*/
|
|
532
|
+
upgrade(): Promise<void>;
|
|
533
|
+
/**
|
|
534
|
+
* Keeps a value written before the field has its control, for a subclass's
|
|
535
|
+
* `value` setter to call in place of writing it: the upgrade writes it
|
|
536
|
+
* through the setter once the field has rendered, over the declared one.
|
|
537
|
+
* The `value` attribute is left alone, so a reset still restores it.
|
|
538
|
+
* @param {any} value
|
|
539
|
+
*/
|
|
540
|
+
_holdValue(value: any): void;
|
|
541
|
+
/**
|
|
542
|
+
* The value a subclass's `value` getter shapes before the field has its
|
|
543
|
+
* control: the one `_holdValue` kept, else the declared `value` attribute
|
|
544
|
+
* read through its mapper.
|
|
545
|
+
* @returns {any}
|
|
546
|
+
*/
|
|
547
|
+
_heldValue(): any;
|
|
548
|
+
/**
|
|
549
|
+
* The field's value, `null` when empty. Every concrete field overrides the
|
|
550
|
+
* pair with its own semantics; the form extraction, `values =` assignment,
|
|
551
|
+
* the `change` detail and `formResetCallback` all go through it. The base
|
|
552
|
+
* pair reads `undefined` and ignores writes. A concrete field answers and
|
|
553
|
+
* takes its value before the render too, through `_heldValue` and
|
|
554
|
+
* `_holdValue`.
|
|
267
555
|
* @type {any}
|
|
268
556
|
*/
|
|
269
557
|
get value(): any;
|
|
270
558
|
set value(v: any);
|
|
271
559
|
/**
|
|
272
|
-
*
|
|
273
|
-
*
|
|
274
|
-
* element's own mapper and value setter
|
|
275
|
-
*
|
|
560
|
+
* Restores the declared value on a form reset, as a native control restores
|
|
561
|
+
* its markup default: the current `value` attribute is decoded with the
|
|
562
|
+
* element's own mapper and written through the `value` setter. A field whose
|
|
563
|
+
* value is not attribute backed overrides this.
|
|
276
564
|
*/
|
|
277
565
|
formResetCallback(): void;
|
|
278
566
|
/**
|
|
279
|
-
* The
|
|
567
|
+
* The field's own disabled claim, which follows a native form control:
|
|
280
568
|
*
|
|
281
|
-
* - the `disabled` attribute on the host is the
|
|
282
|
-
*
|
|
283
|
-
*
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
* -
|
|
292
|
-
*
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
297
|
-
* composes the two on its own when it disables and re-enables a fieldset's
|
|
298
|
-
* descendants. Subclass setters call super for the claim, then reach their
|
|
299
|
-
* own controls, which mirror the claim like a native input's would.
|
|
300
|
-
*
|
|
301
|
-
* Because of this, formDisabledCallback carries nothing the framework needs
|
|
302
|
-
* to apply, and the protocol does not define it.
|
|
569
|
+
* - the `disabled` attribute on the host is the claim. Only the author writes
|
|
570
|
+
* or removes it, in markup or through this property; the library never
|
|
571
|
+
* claims on a form's or fieldset's behalf. A field declared disabled inside
|
|
572
|
+
* a disabled `<fieldset>` stays disabled when the fieldset is re-enabled.
|
|
573
|
+
* - the effective state is the claim or a disabled `<fieldset>` ancestry:
|
|
574
|
+
* `:disabled` matches both, and a disabled field is left out of the
|
|
575
|
+
* submitted values.
|
|
576
|
+
* - the property reads the claim only: a field disabled by its ancestry reads
|
|
577
|
+
* `false` while `matches(':disabled')` is true. Removing the claim inside a
|
|
578
|
+
* disabled fieldset does not enable the field.
|
|
579
|
+
* - writing it sets or removes the `disabled` attribute on the `claims`
|
|
580
|
+
* piece (the control by default) and on every `also` control. The
|
|
581
|
+
* ancestry is never written anywhere: the browser disables those controls
|
|
582
|
+
* as descendants of the fieldset. A subclass setter calls super, then
|
|
583
|
+
* reaches any further controls of its own.
|
|
584
|
+
* @type {boolean}
|
|
303
585
|
*/
|
|
304
586
|
get disabled(): boolean;
|
|
305
587
|
set disabled(d: boolean);
|
|
306
588
|
/**
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
589
|
+
* The readonly claim, read from the host attribute. Writing it sets
|
|
590
|
+
* `readOnly` on the `claims` piece (the control by default) and on every
|
|
591
|
+
* `also` control, sets `aria-readonly` on the `announces` piece, and
|
|
592
|
+
* reflects the attribute. A text control stays focusable and selectable
|
|
593
|
+
* with only editing off. A field whose control has no usable native
|
|
594
|
+
* `readOnly` names a `freeze` piece, whose clicks are cancelled while the
|
|
595
|
+
* claim holds.
|
|
596
|
+
* @type {boolean}
|
|
312
597
|
*/
|
|
313
598
|
get readonly(): boolean;
|
|
314
599
|
set readonly(v: boolean);
|
|
315
600
|
/**
|
|
316
|
-
*
|
|
317
|
-
*
|
|
601
|
+
* The required claim, read from the host attribute. Writing it sets
|
|
602
|
+
* `aria-required` on the `announces` piece and reflects the attribute; no
|
|
603
|
+
* native `required` is set, since validation is the server's.
|
|
604
|
+
* @type {boolean}
|
|
318
605
|
*/
|
|
319
606
|
get required(): boolean;
|
|
320
607
|
set required(d: boolean);
|
|
321
608
|
/**
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
609
|
+
* Calls `_build(conf)` and wires the pieces it answers. When `_build`
|
|
610
|
+
* returns a promise the pieces are wired once it settles; a field that
|
|
611
|
+
* builds synchronously renders synchronously.
|
|
612
|
+
* @param {{ slots: Record<string, DocumentFragment> | undefined }} conf
|
|
613
|
+
* @returns {void | Promise<void>}
|
|
327
614
|
*/
|
|
328
|
-
render(conf:
|
|
615
|
+
render(conf: {
|
|
616
|
+
slots: Record<string, DocumentFragment> | undefined;
|
|
617
|
+
}): void | Promise<void>;
|
|
329
618
|
/**
|
|
330
|
-
* Builds the field's dom and answers the pieces the base drives
|
|
331
|
-
* method a concrete field implements beside its
|
|
332
|
-
* place its dom is created
|
|
619
|
+
* Builds the field's dom and answers the pieces the base drives, or a
|
|
620
|
+
* promise of them. The one method a concrete field implements beside its
|
|
621
|
+
* value pair, and the only place its dom is created. A subclass extending
|
|
622
|
+
* another field's build spreads the pieces it answered and overrides the
|
|
623
|
+
* keys it owns.
|
|
333
624
|
*
|
|
334
|
-
* - `fragment`
|
|
335
|
-
* - `control` is the
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
* - `
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
* - `
|
|
342
|
-
*
|
|
343
|
-
*
|
|
344
|
-
*
|
|
345
|
-
*
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
349
|
-
*
|
|
625
|
+
* - `fragment` (required) replaces the host's children.
|
|
626
|
+
* - `control` (required) is the focus target of `focus()`. By default it also
|
|
627
|
+
* carries the description, `aria-invalid`, `aria-readonly`,
|
|
628
|
+
* `aria-required`, and the mirrored `disabled` and `readOnly`.
|
|
629
|
+
* - `error` (required) is the live region `setCustomValidity` writes into.
|
|
630
|
+
* It is given an id (`ful-field-error-*`) when it has none and is always
|
|
631
|
+
* the last entry of the description.
|
|
632
|
+
* - `label` names the control. For a labelable control (`button`, `input`
|
|
633
|
+
* other than hidden, `meter`, `output`, `progress`, `select`, `textarea`)
|
|
634
|
+
* the control is given an id when it has none and the label's `for`
|
|
635
|
+
* points at it, so a click on the label does what it does in a plain
|
|
636
|
+
* form. For any other control the label is given an id, the control's
|
|
637
|
+
* `aria-labelledby` points at it, and a click on the label calls `focus()`.
|
|
638
|
+
* - `described` carries `aria-describedby` in place of the control: the
|
|
639
|
+
* host, for a field with no single control to describe.
|
|
640
|
+
* - `claims` receives the mirrored `disabled` and `readOnly` in place of the
|
|
641
|
+
* control, for a wrapper such as a `<fieldset>` the field disables as a
|
|
642
|
+
* whole. Focus and the aria stay on the control.
|
|
643
|
+
* - `announces` carries `aria-readonly`, `aria-required` and `aria-invalid`
|
|
644
|
+
* in place of the control: the host, where the widget role lives there.
|
|
645
|
+
* `null` for a field whose control has no role that accepts
|
|
646
|
+
* `aria-readonly` and `aria-required`; `aria-invalid` then goes on the
|
|
647
|
+
* control.
|
|
648
|
+
* - `freeze` is for a field with no usable native `readOnly`: a capturing
|
|
649
|
+
* click listener on it cancels the default action of every click inside
|
|
650
|
+
* it while the readonly claim holds. It stays focusable and in the
|
|
651
|
+
* accessibility tree.
|
|
652
|
+
* - `also` are further controls that mirror `disabled` and `readOnly`
|
|
653
|
+
* beside the claim target.
|
|
350
654
|
*
|
|
351
|
-
*
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
655
|
+
* The pieces are elements the field rendered itself, native controls or
|
|
656
|
+
* wrappers of its own. A ful field is not one: it has no `readOnly`, its
|
|
657
|
+
* host's role takes no aria, and a label's `for` names its host rather than
|
|
658
|
+
* its control. A composite built from ful fields answers the inner field as
|
|
659
|
+
* `control`, which forwards `focus()`, lets it render its own label with
|
|
660
|
+
* `label` and `announces` null, and forwards the claims in its setters,
|
|
661
|
+
* calling super first.
|
|
662
|
+
* @param {{ slots: Record<string, DocumentFragment> | undefined }} conf
|
|
663
|
+
* @returns {any} the pieces, or a promise of them
|
|
664
|
+
* @throws {Error} when the subclass does not implement it
|
|
355
665
|
*/
|
|
356
666
|
_build(conf: {
|
|
357
|
-
slots:
|
|
667
|
+
slots: Record<string, DocumentFragment> | undefined;
|
|
358
668
|
}): any;
|
|
359
669
|
}
|
|
360
|
-
/**
|
|
670
|
+
/** Sends a form's request as a json body to a url, mapping the request and the response through the configured mappers. */
|
|
361
671
|
declare class RemoteJsonFormLoader {
|
|
362
672
|
#private;
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
673
|
+
/**
|
|
674
|
+
* @param {{ request(method: string, url: string): { json(body: any): { fetch(): Promise<any> } } }} http the `http-client` component
|
|
675
|
+
* @param {string} url
|
|
676
|
+
* @param {string} method
|
|
677
|
+
* @param {(value: any, form: Form) => any} requestMapper
|
|
678
|
+
* @param {(value: any, form: Form) => any} responseMapper
|
|
679
|
+
*/
|
|
680
|
+
constructor(http: {
|
|
681
|
+
request(method: string, url: string): {
|
|
682
|
+
json(body: any): {
|
|
683
|
+
fetch(): Promise<any>;
|
|
684
|
+
};
|
|
685
|
+
};
|
|
686
|
+
}, url: string, method: string, requestMapper: (value: any, form: Form) => any, responseMapper: (value: any, form: Form) => any);
|
|
687
|
+
/**
|
|
688
|
+
* @param {any} values
|
|
689
|
+
* @param {Form} form
|
|
690
|
+
* @returns {any} what the request mapper returns
|
|
691
|
+
*/
|
|
692
|
+
prepare(values: any, form: Form): any;
|
|
693
|
+
/**
|
|
694
|
+
* @param {any} request
|
|
695
|
+
* @param {Form} form
|
|
696
|
+
* @returns {Promise<any>} what the client's `fetch()` resolves to: with the
|
|
697
|
+
* library's client, the `Response` of a 2xx status, rejecting with an
|
|
698
|
+
* `HttpClientError` (a `Failure`) otherwise
|
|
699
|
+
*/
|
|
700
|
+
submit(request: any, form: Form): Promise<any>;
|
|
701
|
+
/**
|
|
702
|
+
* @param {any} response
|
|
703
|
+
* @param {Form} form
|
|
704
|
+
* @returns {any} what the response mapper returns
|
|
705
|
+
*/
|
|
706
|
+
transform(response: any, form: Form): any;
|
|
367
707
|
}
|
|
368
708
|
/** Submits a form without a request: the request mapper produces the result the response mapper then reads, for a form handled entirely on the page. */
|
|
369
709
|
declare class LocalFormLoader {
|
|
370
710
|
#private;
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
711
|
+
/**
|
|
712
|
+
* @param {(value: any, form: Form) => any} requestMapper
|
|
713
|
+
* @param {(value: any, form: Form) => any} responseMapper
|
|
714
|
+
*/
|
|
715
|
+
constructor(requestMapper: (value: any, form: Form) => any, responseMapper: (value: any, form: Form) => any);
|
|
716
|
+
/**
|
|
717
|
+
* @param {any} values
|
|
718
|
+
* @param {Form} form
|
|
719
|
+
* @returns {Promise<any>} what the request mapper returns or resolves to
|
|
720
|
+
*/
|
|
721
|
+
prepare(values: any, form: Form): Promise<any>;
|
|
722
|
+
/**
|
|
723
|
+
* Sends nothing.
|
|
724
|
+
* @param {any} request
|
|
725
|
+
* @param {Form} form
|
|
726
|
+
* @param {any} response what a `submit:requested` listener answered
|
|
727
|
+
* @returns {Promise<any>} `response`, unchanged
|
|
728
|
+
*/
|
|
729
|
+
submit(request: any, form: Form, response: any): Promise<any>;
|
|
730
|
+
/**
|
|
731
|
+
* @param {any} response
|
|
732
|
+
* @param {Form} form
|
|
733
|
+
* @returns {Promise<any>} what the response mapper returns or resolves to
|
|
734
|
+
*/
|
|
735
|
+
transform(response: any, form: Form): Promise<any>;
|
|
375
736
|
}
|
|
376
737
|
/**
|
|
377
738
|
* Builds the form's loader from its attributes: a local one when no action is
|
|
@@ -384,121 +745,464 @@ declare class LocalFormLoader {
|
|
|
384
745
|
* - `submit(request, form, response)` performs it and returns the response. The
|
|
385
746
|
* third argument is whatever a `submit:requested` listener already answered,
|
|
386
747
|
* which is how a loader with nothing to send returns it unchanged
|
|
387
|
-
* - `transform(response, form)` turns that response into the
|
|
388
|
-
* `submit:success`
|
|
748
|
+
* - `transform(response, form)` turns that response into the `response` of the
|
|
749
|
+
* `submit:success` detail
|
|
389
750
|
*
|
|
390
751
|
* A rejection from any of the three is reported as a `submit:failure`.
|
|
391
752
|
*/
|
|
392
753
|
declare class FormLoader {
|
|
393
|
-
|
|
754
|
+
/**
|
|
755
|
+
* The `request-mapper` and `response-mapper` attributes name registry
|
|
756
|
+
* components called as `(value, form)`; each defaults to the identity. A
|
|
757
|
+
* remote loader sends through the `http-client` component, with the
|
|
758
|
+
* `method` attribute or `POST`.
|
|
759
|
+
* @param {Form} el the form submitting
|
|
760
|
+
* @param {unknown} [conf] not read
|
|
761
|
+
* @returns {LocalFormLoader | RemoteJsonFormLoader}
|
|
762
|
+
*/
|
|
763
|
+
static create(el: Form, conf?: unknown): LocalFormLoader | RemoteJsonFormLoader;
|
|
394
764
|
}
|
|
395
765
|
/**
|
|
396
|
-
*
|
|
397
|
-
* them to a loader
|
|
398
|
-
*
|
|
766
|
+
* Moves its children into a native `<form novalidate>`, extracts their values
|
|
767
|
+
* on submit and hands them to a loader, reporting problems through `errors`.
|
|
768
|
+
* Being `novalidate`, the form submits whatever the validity of its fields:
|
|
769
|
+
* the browser does not block a submit on a field still marked invalid.
|
|
770
|
+
*
|
|
771
|
+
* Attributes on the host starting with `form-` are forwarded, without the
|
|
772
|
+
* prefix, to the native form. `autocomplete` is copied onto the native form as
|
|
773
|
+
* well and stays on the host, the fields reading it from either; a
|
|
774
|
+
* `form-autocomplete` has the last word on the native form.
|
|
775
|
+
* `clear-invalid-on-change` clears the custom validity of a field of this form
|
|
776
|
+
* when a `change` event bubbles from it; the field's form is read from its
|
|
777
|
+
* `form` property, or from `internals.form` for a form-associated element
|
|
778
|
+
* that has none. `scroll-on-error` is passed to `Bindings.errors` as
|
|
779
|
+
* `scrollOnError`.
|
|
780
|
+
*
|
|
781
|
+
* A native submit, by a button or by Enter in a field, is stopped and runs
|
|
782
|
+
* `submit` instead.
|
|
783
|
+
*
|
|
784
|
+
* `track-changes` keeps track of the edits not saved yet (see `dirty`), and
|
|
785
|
+
* `guard-leave`, which implies it, asks before the page is left while there
|
|
786
|
+
* are any.
|
|
399
787
|
*/
|
|
400
788
|
declare class Form extends ParsedElement {
|
|
401
789
|
#private;
|
|
790
|
+
/** Read once at the upgrade: changing one afterwards has no effect. */
|
|
402
791
|
static attributes: string[];
|
|
792
|
+
/** The native form holding the fields, created by the render. */
|
|
403
793
|
form: any;
|
|
794
|
+
/** Builds the native form and moves the element's children into it. */
|
|
404
795
|
render(): void;
|
|
796
|
+
connectedCallback(): void;
|
|
797
|
+
disconnectedCallback(): void;
|
|
798
|
+
/**
|
|
799
|
+
* Runs the submit pipeline, with the spinner up until its outcome:
|
|
800
|
+
*
|
|
801
|
+
* 1. builds the loader: the component the `loader` attribute names
|
|
802
|
+
* (`loaders:form` by default), called as `create(form)`
|
|
803
|
+
* 2. extracts the values with `Bindings.extractFrom` and has the loader
|
|
804
|
+
* `prepare` them into the request
|
|
805
|
+
* 3. fires a cancelable `submit` with `{ submitter, values, request }`.
|
|
806
|
+
* Cancelling it ends the submit there, reporting nothing and leaving the
|
|
807
|
+
* problems shown; a listener may replace `values` or `request` on the detail
|
|
808
|
+
* 4. clears the problems shown
|
|
809
|
+
* 5. fires `submit:requested` through `AsyncEvents.fireAsync` in `pipeline`
|
|
810
|
+
* mode: at most one async listener, whose answer is handed to the
|
|
811
|
+
* loader's `submit` as its third argument. A listener may replace
|
|
812
|
+
* `request` on the detail
|
|
813
|
+
* 6. has the loader `submit` the request and `transform` the response
|
|
814
|
+
* 7. under `track-changes`, commits the values extracted at step 2 (see
|
|
815
|
+
* `commit`): an edit made while the submit was in flight stays unsaved
|
|
816
|
+
* 8. releases the spinner and fires `submit:success` with `{ submitter,
|
|
817
|
+
* values, request, response }`, `response` being the transformed one
|
|
818
|
+
*
|
|
819
|
+
* Anything thrown from step 1 on, a missing loader or a throwing mapper
|
|
820
|
+
* included, fires `submit:failure` with `{ submitter, values, request,
|
|
821
|
+
* exception }` instead; the returned promise does not reject. A `Failure`
|
|
822
|
+
* has its problems shown through `errors`, anything else is logged with
|
|
823
|
+
* `console.warn`. The `values` of both outcome events are the extracted
|
|
824
|
+
* ones, not a replacement a `submit` listener put on its detail.
|
|
825
|
+
*
|
|
826
|
+
* The form settles before either outcome event (0016): its listeners see
|
|
827
|
+
* the spinner released and the buttons no longer held off, the problems of
|
|
828
|
+
* a `Failure` already shown, and the submit no longer in flight, so one
|
|
829
|
+
* of them may submit again.
|
|
830
|
+
*
|
|
831
|
+
* A call while a submit is in flight returns at once, doing nothing.
|
|
832
|
+
* @param {HTMLElement} [submitter] the button that submitted, if any; it is
|
|
833
|
+
* the only button whose name and value are submitted
|
|
834
|
+
* @returns {Promise<boolean>} settling once the submit has finished: true
|
|
835
|
+
* after `submit:success`, false when it failed, was cancelled or was dropped
|
|
836
|
+
* for one in flight
|
|
837
|
+
*/
|
|
838
|
+
submit(submitter?: HTMLElement): Promise<boolean>;
|
|
405
839
|
/**
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
*
|
|
409
|
-
*
|
|
410
|
-
* @
|
|
411
|
-
*
|
|
840
|
+
* Saves the unsaved edits, for a page action that would lose them, such as
|
|
841
|
+
* one reloading the page: under `track-changes` it submits only while the
|
|
842
|
+
* form is dirty, and without it always submits.
|
|
843
|
+
* @param {HTMLElement} [submitter] as `submit` takes it
|
|
844
|
+
* @returns {Promise<boolean>} whether no unsaved edit is left: false when
|
|
845
|
+
* the submit did not succeed, or when the user edited the form while it
|
|
846
|
+
* was in flight
|
|
847
|
+
*/
|
|
848
|
+
save(submitter?: HTMLElement): Promise<boolean>;
|
|
849
|
+
/**
|
|
850
|
+
* Resets the native form, each field returning to its default value. Under
|
|
851
|
+
* `track-changes` a reset, this one or a native reset button's, counts
|
|
852
|
+
* every control as edited: the form is dirty if the defaults differ from
|
|
853
|
+
* what was last committed.
|
|
412
854
|
*/
|
|
413
|
-
submit(submitter?: HTMLElement): Promise<void>;
|
|
414
|
-
/** The native reset, routing every field through its own value semantics. */
|
|
415
855
|
reset(): void;
|
|
416
|
-
/**
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
856
|
+
/**
|
|
857
|
+
* Whether, under `track-changes`, a control the user edited since the last
|
|
858
|
+
* commit holds a value other than the one committed. An edit is what the
|
|
859
|
+
* controls report as one: an `input` or a `change` bubbling from a control
|
|
860
|
+
* of this form (0019), so assigning `value`, a select's vocabulary dropping
|
|
861
|
+
* a key or a section delivering its fields is not one, and an edit undone
|
|
862
|
+
* is no longer dirty. A control the last commit did not see compares with
|
|
863
|
+
* its value when it was first focused. Always false without
|
|
864
|
+
* `track-changes`.
|
|
865
|
+
*
|
|
866
|
+
* While dirty, the host matches `:state(dirty)` and the submit buttons of
|
|
867
|
+
* this form carry `data-ful-dirty`; a change of the state dispatches
|
|
868
|
+
* `dirty:change` with `{ dirty }`. Both are refreshed at the next frame
|
|
869
|
+
* after an edit, while the property is exact at any time.
|
|
870
|
+
* @returns {boolean}
|
|
871
|
+
*/
|
|
872
|
+
get dirty(): boolean;
|
|
873
|
+
/**
|
|
874
|
+
* Records the values of the controls as saved, so that the form is no
|
|
875
|
+
* longer dirty. A submit commits by itself on success, and the form
|
|
876
|
+
* commits once its fields have rendered: a page calls this for a save of
|
|
877
|
+
* its own, or after writing the values it loaded. Does nothing without
|
|
878
|
+
* `track-changes`.
|
|
879
|
+
*/
|
|
880
|
+
commit(): void;
|
|
881
|
+
/**
|
|
882
|
+
* Counts controls as edited by the user, for values the page writes on
|
|
883
|
+
* the user's behalf: assigning `value` reports nothing, as 0019 wants.
|
|
884
|
+
* @param {...Element} els each a control, or an element inside one
|
|
885
|
+
*/
|
|
886
|
+
edited(...els: Element[]): void;
|
|
887
|
+
/**
|
|
888
|
+
* Marks the form busy or releases it. Calls nest: only the first
|
|
889
|
+
* `spinner(true)` and the matching last `spinner(false)` act, so a caller's
|
|
890
|
+
* own spin may wrap a submit.
|
|
891
|
+
*
|
|
892
|
+
* Busy, the host carries `aria-busy="true"` and each `ful-spinner` of this
|
|
893
|
+
* form is revealed; one without text of its own is given `role="status"`
|
|
894
|
+
* (unless it has a role) and a visually hidden localized `spinner.loading`
|
|
895
|
+
* label. Each submit and reset button of this form is held off with
|
|
896
|
+
* `aria-disabled="true"`, keeping its focus, and a click on it is refused
|
|
897
|
+
* ahead of any listener on the button. Holding the buttons off does not
|
|
898
|
+
* stop a programmatic `submit`.
|
|
899
|
+
*
|
|
900
|
+
* Released, the spinners are hidden and lose the label they were given, and
|
|
901
|
+
* each held button gets back the `aria-disabled` it had. A button that
|
|
902
|
+
* joined the form while it was busy keeps its own state.
|
|
903
|
+
* @param {boolean} spin
|
|
904
|
+
*/
|
|
905
|
+
spinner(spin: boolean): void;
|
|
906
|
+
/**
|
|
907
|
+
* Writes a nested object onto the fields of this form through
|
|
908
|
+
* `Bindings.mutateIn`: fields the object does not name keep their values.
|
|
909
|
+
* @param {{ [x: string]: any; }} vs
|
|
910
|
+
*/
|
|
911
|
+
set values(vs: {
|
|
912
|
+
[x: string]: any;
|
|
913
|
+
});
|
|
914
|
+
/**
|
|
915
|
+
* The fields of this form read into a nested object by
|
|
916
|
+
* `Bindings.extractFrom`, with no submitter, so no button contributes.
|
|
917
|
+
* @returns {any}
|
|
918
|
+
*/
|
|
919
|
+
get values(): any;
|
|
920
|
+
/**
|
|
921
|
+
* Shows problems through `Bindings.errors`, replacing the ones shown
|
|
922
|
+
* before: each is pinned to the field it names, and the rest go to the
|
|
923
|
+
* form's `ful-errors` banners. An empty array clears them.
|
|
924
|
+
* @param {{ type: string; context?: string | null; reason: string; }[]} es
|
|
925
|
+
*/
|
|
926
|
+
set errors(es: {
|
|
927
|
+
type: string;
|
|
928
|
+
context?: string | null;
|
|
929
|
+
reason: string;
|
|
930
|
+
}[]);
|
|
423
931
|
}
|
|
424
|
-
/**
|
|
932
|
+
/**
|
|
933
|
+
* A labelled text input over any native input type, or a `<textarea>` under
|
|
934
|
+
* `type="textarea"`; the temporal inputs are its subclasses. The label is the
|
|
935
|
+
* default slot, `info` follows it, and `before` and `after` are rendered as
|
|
936
|
+
* affixes around the control. Every `input-*` attribute is forwarded onto the
|
|
937
|
+
* control, after everything the field sets there, so it has the last word.
|
|
938
|
+
*
|
|
939
|
+
* `type`, `v-type`, `keep`, `reject`, `uppercase`, `trim`, `unsigned` and
|
|
940
|
+
* `autocomplete` are configuration: read once at the upgrade, so a later write
|
|
941
|
+
* to them changes nothing. `placeholder` stays live.
|
|
942
|
+
*
|
|
943
|
+
* - `type="numeric"` and `type="decimal"` render a text input carrying that
|
|
944
|
+
* `inputmode`, so the native `min`, `max` and `step` do not apply. Typing is
|
|
945
|
+
* filtered to digits and a leading minus; a decimal also keeps its first `.`
|
|
946
|
+
* or `,` and drops any later one; `unsigned` drops the minus.
|
|
947
|
+
* - `keep` and `reject` are regular expressions filtering what is typed:
|
|
948
|
+
* `keep` leaves every match, concatenated, and `reject` removes every match.
|
|
949
|
+
* Either replaces the type's own filter, and `keep` wins over `reject` with a
|
|
950
|
+
* warning. A pattern that does not compile is warned about once and filters
|
|
951
|
+
* nothing. The caret stays next to the same character when text before it
|
|
952
|
+
* is removed.
|
|
953
|
+
* - `autocomplete` is put on the control. Without one the field takes the
|
|
954
|
+
* `autocomplete` attribute of the nearest enclosing `<form>`, which the
|
|
955
|
+
* platform does not pass on because the control carries `form=""`.
|
|
956
|
+
* - `uppercase`, `trim` and `v-type` shape the value as it is read; see `value`.
|
|
957
|
+
* - The control's native `change` is stopped and the field dispatches its own
|
|
958
|
+
* once the user commits a new value, as a text input does. A date, time,
|
|
959
|
+
* datetime-local, month or week control fires its native `change` while its
|
|
960
|
+
* segments are typed, as soon as they make a valid value; for those the field
|
|
961
|
+
* reports when the control is left or Enter is pressed, at once for a value
|
|
962
|
+
* picked from the browser's picker, never with the dates a year passes
|
|
963
|
+
* through while it is typed. A control left incomplete reads as `null`, as
|
|
964
|
+
* the native one does.
|
|
965
|
+
*
|
|
966
|
+
* A subclass template may render more than one control, as the compare filters
|
|
967
|
+
* render the two bounds of a range: the first is `_input`, the one the field is
|
|
968
|
+
* named by, and every one of them gets the inputmode, `autocomplete`, the
|
|
969
|
+
* `input-` passthrough, the keystroke filter, the placeholder and the `change`
|
|
970
|
+
* reporting. The passthrough leaves `input-id` to the first alone, so no
|
|
971
|
+
* two controls share an id.
|
|
972
|
+
*/
|
|
425
973
|
declare class Input extends Field {
|
|
974
|
+
#private;
|
|
975
|
+
/** @type {string[]} */
|
|
426
976
|
static observed: string[];
|
|
977
|
+
/** @type {string[]} */
|
|
427
978
|
static attributes: string[];
|
|
428
979
|
static slots: boolean;
|
|
429
980
|
static template: string;
|
|
981
|
+
/**
|
|
982
|
+
* The inner control, set by `_build`: the `<input>`, or the `<textarea>`
|
|
983
|
+
* under `type="textarea"`. A subclass reads and writes it for the
|
|
984
|
+
* attributes it adds. Typed `any` so that a subclass can treat it as the
|
|
985
|
+
* one of the two it renders.
|
|
986
|
+
* @type {any}
|
|
987
|
+
*/
|
|
430
988
|
_input: any;
|
|
431
|
-
|
|
989
|
+
/**
|
|
990
|
+
* The type the field renders, which a subclass overrides to wrap another
|
|
991
|
+
* native type. The base answers the declared `type`, else `number` under
|
|
992
|
+
* `v-type="number"`, else `text`. It is also what selects the keystroke
|
|
993
|
+
* filter of `numeric` and `decimal` and the separator handling of `value`.
|
|
994
|
+
* @returns {string}
|
|
995
|
+
*/
|
|
996
|
+
_type(): string;
|
|
997
|
+
/**
|
|
998
|
+
* @param {{ slots: Record<string, DocumentFragment> | undefined }} conf
|
|
999
|
+
* @returns {{fragment: DocumentFragment, control: any, error: Element | null, label: HTMLLabelElement | null}}
|
|
1000
|
+
*/
|
|
432
1001
|
_build({ slots }: {
|
|
433
|
-
slots:
|
|
1002
|
+
slots: Record<string, DocumentFragment> | undefined;
|
|
434
1003
|
}): {
|
|
435
|
-
fragment:
|
|
1004
|
+
fragment: DocumentFragment;
|
|
436
1005
|
control: any;
|
|
437
|
-
error:
|
|
438
|
-
label:
|
|
1006
|
+
error: Element | null;
|
|
1007
|
+
label: HTMLLabelElement | null;
|
|
439
1008
|
};
|
|
1009
|
+
/**
|
|
1010
|
+
* The control's text, shaped in this order: upper cased under `uppercase`,
|
|
1011
|
+
* trimmed under `trim`, `null` when that leaves it empty, every `,` read as
|
|
1012
|
+
* `.` for `type="decimal"`, and decoded to a number under
|
|
1013
|
+
* `v-type="number"`, where text that does not decode is answered as it is.
|
|
1014
|
+
* Writing `null`, `undefined` or `''` empties the control; anything else is
|
|
1015
|
+
* written as its string, replacing whatever was being typed, as a native
|
|
1016
|
+
* control's value does, and is not an edit: a date or time control that
|
|
1017
|
+
* has the focus reports no `change` for it when it is left. Answers a
|
|
1018
|
+
* `string`, a `number` or `null`; typed `any` because subclasses answer
|
|
1019
|
+
* other values. Before the render the same shaping reads the value last
|
|
1020
|
+
* written, or the `value` attribute, as its text, and a write is held for
|
|
1021
|
+
* the render to apply.
|
|
1022
|
+
* @type {any}
|
|
1023
|
+
*/
|
|
440
1024
|
get value(): any;
|
|
441
1025
|
set value(value: any);
|
|
442
|
-
|
|
443
|
-
|
|
1026
|
+
/**
|
|
1027
|
+
* The control's placeholder, `null` when there is none. The control always
|
|
1028
|
+
* carries one, a single space standing in for none, so `:placeholder-shown`
|
|
1029
|
+
* matches an empty control and a floating label can rely on it; the blank
|
|
1030
|
+
* one is neither answered here nor reflected onto the host.
|
|
1031
|
+
* @type {string | null}
|
|
1032
|
+
*/
|
|
1033
|
+
get placeholder(): string | null;
|
|
1034
|
+
set placeholder(d: string | null);
|
|
444
1035
|
}
|
|
445
|
-
/**
|
|
1036
|
+
/**
|
|
1037
|
+
* Formats the yyyy-mm-dd date in its content as a numeric date, in the locale
|
|
1038
|
+
* its `locale` attribute names, else the page's, else the platform default.
|
|
1039
|
+
* Blank content, or content that does not name a date, renders the `default`
|
|
1040
|
+
* attribute, or nothing without one.
|
|
1041
|
+
*/
|
|
446
1042
|
declare class LocalDate extends ParsedElement {
|
|
447
1043
|
static attributes: string[];
|
|
448
1044
|
render(): void;
|
|
449
1045
|
}
|
|
450
|
-
/**
|
|
1046
|
+
/**
|
|
1047
|
+
* Formats the ISO instant in its content as a numeric date and 24 hour time
|
|
1048
|
+
* with seconds, in the page's timezone and in the locale chosen as ful-local-date
|
|
1049
|
+
* chooses it. Blank content, or content that does not name an instant, renders
|
|
1050
|
+
* the `default` attribute, or nothing without one. A date-only value is read as
|
|
1051
|
+
* local midnight of that day.
|
|
1052
|
+
*/
|
|
451
1053
|
declare class Instant extends ParsedElement {
|
|
452
1054
|
#private;
|
|
453
1055
|
static attributes: string[];
|
|
454
1056
|
render(): void;
|
|
455
|
-
|
|
456
|
-
|
|
1057
|
+
/**
|
|
1058
|
+
* Converts an ISO instant to the `yyyy-mm-ddThh:mm:ss.sss` wall clock time
|
|
1059
|
+
* a datetime-local input takes, in the page's timezone. A date-only value is
|
|
1060
|
+
* read as local midnight of the day it names, not as UTC midnight.
|
|
1061
|
+
* @param {string} iso
|
|
1062
|
+
* @returns {string} with NaN fields for a value that does not parse
|
|
1063
|
+
*/
|
|
1064
|
+
static isoToLocal(iso: string): string;
|
|
1065
|
+
/**
|
|
1066
|
+
* Converts a datetime-local wall clock time in the page's timezone to a UTC
|
|
1067
|
+
* ISO instant. A date-only value is read as local midnight of that day.
|
|
1068
|
+
* @param {string} local
|
|
1069
|
+
* @returns {string|null} null for a value that does not parse
|
|
1070
|
+
*/
|
|
1071
|
+
static localToIso(local: string): string | null;
|
|
457
1072
|
}
|
|
458
|
-
/**
|
|
1073
|
+
/**
|
|
1074
|
+
* A date input whose `min` and `max` accept a yyyy-mm-dd date, `now` for
|
|
1075
|
+
* today, or an offset from today such as `+1d`, `-2m` or `+1y` (days, months,
|
|
1076
|
+
* years). A month offset landing past the end of the target month takes its
|
|
1077
|
+
* last day. Anything else is passed to the input unchanged. The `step`
|
|
1078
|
+
* attribute is applied before `min` and `max`.
|
|
1079
|
+
*/
|
|
459
1080
|
declare class InputLocalDate extends Input {
|
|
460
1081
|
#private;
|
|
461
1082
|
static observed: string[];
|
|
462
1083
|
_type(): string;
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
get
|
|
468
|
-
|
|
1084
|
+
/**
|
|
1085
|
+
* The resolved lower bound, a yyyy-mm-dd date or whatever the input was given.
|
|
1086
|
+
* @returns {string|null} null when unset
|
|
1087
|
+
*/
|
|
1088
|
+
get min(): string | null;
|
|
1089
|
+
/** @param {string|null} v a date, `now` or an offset; null or blank removes the bound */
|
|
1090
|
+
set min(v: string | null);
|
|
1091
|
+
/**
|
|
1092
|
+
* The resolved upper bound, a yyyy-mm-dd date or whatever the input was given.
|
|
1093
|
+
* @returns {string|null} null when unset
|
|
1094
|
+
*/
|
|
1095
|
+
get max(): string | null;
|
|
1096
|
+
/** @param {string|null} v a date, `now` or an offset; null or blank removes the bound */
|
|
1097
|
+
set max(v: string | null);
|
|
1098
|
+
/**
|
|
1099
|
+
* The input's native step, in days on a date input and in seconds on a time input.
|
|
1100
|
+
* @returns {string|null} null when unset
|
|
1101
|
+
*/
|
|
1102
|
+
get step(): string | null;
|
|
1103
|
+
/** @param {string|null} v */
|
|
1104
|
+
set step(v: string | null);
|
|
469
1105
|
}
|
|
470
|
-
/**
|
|
1106
|
+
/**
|
|
1107
|
+
* A time input whose `min` and `max` accept a hh:mm time, `now`, or an offset
|
|
1108
|
+
* from now such as `+2h` or `-30m` (hours, minutes: `m` is minutes here, not
|
|
1109
|
+
* months), wrapping around midnight. A bound resolved from `now` or an offset
|
|
1110
|
+
* is floored to the `step` grid (60 seconds when unset), so that the values
|
|
1111
|
+
* on the grid stay valid, and carries seconds only when the step is not whole
|
|
1112
|
+
* minutes. A literal bound, and anything else, is passed to the input unchanged.
|
|
1113
|
+
*/
|
|
471
1114
|
declare class InputLocalTime extends InputLocalDate {
|
|
472
1115
|
#private;
|
|
473
1116
|
_type(): string;
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
1117
|
+
/**
|
|
1118
|
+
* The resolved lower bound, a time or whatever the input was given.
|
|
1119
|
+
* @returns {string|null} null when unset
|
|
1120
|
+
*/
|
|
1121
|
+
get min(): string | null;
|
|
1122
|
+
/** @param {string|null} v a time, `now` or an offset; null or blank removes the bound */
|
|
1123
|
+
set min(v: string | null);
|
|
1124
|
+
/**
|
|
1125
|
+
* The resolved upper bound, a time or whatever the input was given.
|
|
1126
|
+
* @returns {string|null} null when unset
|
|
1127
|
+
*/
|
|
1128
|
+
get max(): string | null;
|
|
1129
|
+
/** @param {string|null} v a time, `now` or an offset; null or blank removes the bound */
|
|
1130
|
+
set max(v: string | null);
|
|
478
1131
|
}
|
|
479
|
-
/**
|
|
1132
|
+
/**
|
|
1133
|
+
* A datetime-local input whose value and bounds are read and written as UTC
|
|
1134
|
+
* ISO instants, shown as wall clock time in the page's timezone. A date-only
|
|
1135
|
+
* value is read as local midnight of that day.
|
|
1136
|
+
*/
|
|
480
1137
|
declare class InputInstant extends Input {
|
|
481
1138
|
static observed: string[];
|
|
482
1139
|
_type(): string;
|
|
1140
|
+
/**
|
|
1141
|
+
* The entered time as a UTC ISO instant. Before the render it answers the
|
|
1142
|
+
* value last written, or the `value` attribute, as the rendered field
|
|
1143
|
+
* would, and a write is held for the render to apply.
|
|
1144
|
+
* @returns {string|null} null when empty or when the input holds text that does not parse
|
|
1145
|
+
*/
|
|
483
1146
|
get value(): string | null;
|
|
484
|
-
|
|
1147
|
+
/** @param {string|null|undefined} v an ISO instant; a falsy value empties the input */
|
|
1148
|
+
set value(v: string | null | undefined);
|
|
1149
|
+
/**
|
|
1150
|
+
* The lower bound as a UTC ISO instant.
|
|
1151
|
+
* @returns {string|null} null when unset
|
|
1152
|
+
*/
|
|
485
1153
|
get min(): string | null;
|
|
1154
|
+
/** @param {string|null} v an ISO instant; a falsy value removes the bound */
|
|
486
1155
|
set min(v: string | null);
|
|
1156
|
+
/**
|
|
1157
|
+
* The upper bound as a UTC ISO instant.
|
|
1158
|
+
* @returns {string|null} null when unset
|
|
1159
|
+
*/
|
|
487
1160
|
get max(): string | null;
|
|
1161
|
+
/** @param {string|null} v an ISO instant; a falsy value removes the bound */
|
|
488
1162
|
set max(v: string | null);
|
|
489
|
-
|
|
490
|
-
|
|
1163
|
+
/**
|
|
1164
|
+
* The input's native step, in seconds.
|
|
1165
|
+
* @returns {string|null} null when unset
|
|
1166
|
+
*/
|
|
1167
|
+
get step(): string | null;
|
|
1168
|
+
/** @param {string|null} v */
|
|
1169
|
+
set step(v: string | null);
|
|
491
1170
|
}
|
|
492
|
-
/**
|
|
1171
|
+
/**
|
|
1172
|
+
* A file input with an optional dropzone and item list, enforcing the type,
|
|
1173
|
+
* size and count limits it declares.
|
|
1174
|
+
*
|
|
1175
|
+
* The `dropzone` and `item-list` attributes show the dropzone and the list of
|
|
1176
|
+
* chosen files. A `dropzone` slot replaces the default dropzone's content, and
|
|
1177
|
+
* an `items` slot holding a template replaces the stock item, rendered with the
|
|
1178
|
+
* same `files` overlay so that it reads the File objects it lists. Clicking the
|
|
1179
|
+
* dropzone opens the picker, and the host carries a `dragover` attribute while
|
|
1180
|
+
* a drag hovers it. A drop selects the files it carries, ignoring entries that
|
|
1181
|
+
* are not files; a drop with no file, or with several on a field that is not
|
|
1182
|
+
* `multiple`, changes nothing.
|
|
1183
|
+
*
|
|
1184
|
+
* Every selection, picked, dropped or assigned, goes through the constraints
|
|
1185
|
+
* in order: `accept` and `max-file-size` drop the files they refuse,
|
|
1186
|
+
* `max-total-size` and `max-files` clear the whole selection. Each violation
|
|
1187
|
+
* shows a warning. The change event fires for a pick, a drop and a removal
|
|
1188
|
+
* through an item's button; the `files`, `file` and `value` setters are silent,
|
|
1189
|
+
* like a native input's.
|
|
1190
|
+
*
|
|
1191
|
+
* While disabled or readonly, the picker, the dropzone and the item removals
|
|
1192
|
+
* do nothing, and a drop still does not reach the browser's default handling.
|
|
1193
|
+
*/
|
|
493
1194
|
declare class InputFile extends Input {
|
|
494
1195
|
#private;
|
|
495
|
-
/**
|
|
1196
|
+
/**
|
|
1197
|
+
* Milliseconds a warning stays before the field removes it, whether or not
|
|
1198
|
+
* its css animation ran; read each time a warning is shown.
|
|
1199
|
+
* @type {number}
|
|
1200
|
+
*/
|
|
496
1201
|
static WARNING_TIMEOUT: number;
|
|
497
1202
|
/**
|
|
498
|
-
*
|
|
499
|
-
* build one but through a DataTransfer, and every place that narrows a
|
|
500
|
-
* selection rebuilt it by hand: five loops and three empty ones.
|
|
1203
|
+
* Builds a FileList holding exactly these files, the form `files` takes.
|
|
501
1204
|
* @param {Iterable<File>} [files]
|
|
1205
|
+
* @returns {FileList}
|
|
502
1206
|
*/
|
|
503
1207
|
static list(files?: Iterable<File>): FileList;
|
|
504
1208
|
static observed: string[];
|
|
@@ -509,73 +1213,187 @@ declare class InputFile extends Input {
|
|
|
509
1213
|
warning: string;
|
|
510
1214
|
};
|
|
511
1215
|
_build(conf: any): {
|
|
512
|
-
fragment:
|
|
1216
|
+
fragment: DocumentFragment;
|
|
513
1217
|
control: any;
|
|
514
|
-
error:
|
|
515
|
-
label:
|
|
1218
|
+
error: Element | null;
|
|
1219
|
+
label: HTMLLabelElement | null;
|
|
516
1220
|
freeze: any;
|
|
517
1221
|
};
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
1222
|
+
/**
|
|
1223
|
+
* Shows a warning in the field's polite live region: the localized message
|
|
1224
|
+
* for an l10n key and its arguments. It is removed when its animation ends,
|
|
1225
|
+
* or after `WARNING_TIMEOUT` milliseconds at the latest. The warnings are
|
|
1226
|
+
* cleared whenever the selection changes.
|
|
1227
|
+
* @param {string} key
|
|
1228
|
+
* @param {Record<string, any>} [args]
|
|
1229
|
+
*/
|
|
1230
|
+
warning(key: string, args?: Record<string, any>): void;
|
|
1231
|
+
/**
|
|
1232
|
+
* The accepted types, also set on the native input for its picker. A token
|
|
1233
|
+
* is a dot-prefixed extension matched against the end of the file name, a
|
|
1234
|
+
* mime type matched against the file's type with any parameters ignored, or
|
|
1235
|
+
* a family such as `image/*`; case is ignored, and any other token matches
|
|
1236
|
+
* nothing. A file matching no token is dropped with a warning; an empty list
|
|
1237
|
+
* accepts every file. Enforced from the next selection on.
|
|
1238
|
+
* @returns {string[]}
|
|
1239
|
+
*/
|
|
1240
|
+
get accept(): string[];
|
|
1241
|
+
/** @param {string[]} vs */
|
|
1242
|
+
set accept(vs: string[]);
|
|
1243
|
+
/**
|
|
1244
|
+
* Whether the field takes several files; a single-file field ignores a drop of several.
|
|
1245
|
+
* @returns {boolean}
|
|
1246
|
+
*/
|
|
1247
|
+
get multiple(): boolean;
|
|
1248
|
+
/** @param {boolean} v */
|
|
1249
|
+
set multiple(v: boolean);
|
|
1250
|
+
/**
|
|
1251
|
+
* The selected files, after the constraints; none before the render.
|
|
1252
|
+
* @returns {FileList}
|
|
1253
|
+
*/
|
|
1254
|
+
get files(): FileList;
|
|
1255
|
+
/**
|
|
1256
|
+
* Replaces the selection and runs the constraints over it, refreshing the
|
|
1257
|
+
* warnings and the item list, without firing change.
|
|
1258
|
+
* @param {FileList} vs
|
|
1259
|
+
*/
|
|
1260
|
+
set files(vs: FileList);
|
|
1261
|
+
/**
|
|
1262
|
+
* The first selected file.
|
|
1263
|
+
* @returns {File|null}
|
|
1264
|
+
*/
|
|
1265
|
+
get file(): File | null;
|
|
1266
|
+
/**
|
|
1267
|
+
* Replaces the selection with this one file, or empties it, as `files` does.
|
|
1268
|
+
* @param {File|null|undefined} v
|
|
1269
|
+
*/
|
|
1270
|
+
set file(v: File | null | undefined);
|
|
1271
|
+
/**
|
|
1272
|
+
* The names of the selected files: an array when `multiple`, otherwise the
|
|
1273
|
+
* one name or null. Before the render no file is selected yet.
|
|
1274
|
+
* @returns {string[]|string|null}
|
|
1275
|
+
*/
|
|
1276
|
+
get value(): string[] | string | null;
|
|
1277
|
+
/**
|
|
1278
|
+
* Empties the selection for a falsy value and ignores any other, since a
|
|
1279
|
+
* file name cannot select a file. Before the render there is nothing to
|
|
1280
|
+
* empty, so it does nothing.
|
|
1281
|
+
* @param {any} v
|
|
1282
|
+
*/
|
|
528
1283
|
set value(v: any);
|
|
1284
|
+
/** Empties the selection, as a native file input's reset does, whatever the `value` attribute says. */
|
|
529
1285
|
formResetCallback(): void;
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
1286
|
+
/**
|
|
1287
|
+
* The size of the selected files together, in bytes.
|
|
1288
|
+
* @returns {number}
|
|
1289
|
+
*/
|
|
1290
|
+
get totalsize(): number;
|
|
1291
|
+
/**
|
|
1292
|
+
* The most files a selection may hold; a larger selection is cleared
|
|
1293
|
+
* entirely with a warning. Enforced from the next selection on.
|
|
1294
|
+
* @returns {number|null} null for no limit
|
|
1295
|
+
*/
|
|
1296
|
+
get maxFiles(): number | null;
|
|
1297
|
+
/** @param {number|null} v */
|
|
1298
|
+
set maxFiles(v: number | null);
|
|
1299
|
+
/**
|
|
1300
|
+
* The largest size one file may have, in bytes; a larger file is dropped
|
|
1301
|
+
* from the selection with a warning. Enforced from the next selection on.
|
|
1302
|
+
* @returns {number|null} null for no limit
|
|
1303
|
+
*/
|
|
1304
|
+
get maxFileSize(): number | null;
|
|
1305
|
+
/** @param {number|null} v */
|
|
1306
|
+
set maxFileSize(v: number | null);
|
|
1307
|
+
/**
|
|
1308
|
+
* The largest size the selected files may have together, in bytes; a
|
|
1309
|
+
* larger selection is cleared entirely with a warning. Enforced from the
|
|
1310
|
+
* next selection on.
|
|
1311
|
+
* @returns {number|null} null for no limit
|
|
1312
|
+
*/
|
|
1313
|
+
get maxTotalSize(): number | null;
|
|
1314
|
+
/** @param {number|null} v */
|
|
1315
|
+
set maxTotalSize(v: number | null);
|
|
1316
|
+
/**
|
|
1317
|
+
* Whether the chosen files are listed, each with a button removing it; the
|
|
1318
|
+
* stylesheet shows the list from the reflected `item-list` attribute.
|
|
1319
|
+
* @returns {boolean}
|
|
1320
|
+
*/
|
|
1321
|
+
get itemList(): boolean;
|
|
1322
|
+
/** @param {boolean} v */
|
|
1323
|
+
set itemList(v: boolean);
|
|
1324
|
+
/**
|
|
1325
|
+
* Whether the dropzone is shown; the stylesheet shows it from the reflected
|
|
1326
|
+
* `dropzone` attribute.
|
|
1327
|
+
* @returns {boolean}
|
|
1328
|
+
*/
|
|
1329
|
+
get dropzone(): boolean;
|
|
1330
|
+
/** @param {boolean} v */
|
|
1331
|
+
set dropzone(v: boolean);
|
|
541
1332
|
}
|
|
542
1333
|
/**
|
|
543
|
-
*
|
|
544
|
-
*
|
|
1334
|
+
* Places a popover beside the element or the rectangle it belongs to.
|
|
1335
|
+
*
|
|
1336
|
+
* `wire` pairs a popover with one invoker for its lifetime and relies on css
|
|
1337
|
+
* anchor positioning, placing the popover in script only where the platform
|
|
1338
|
+
* lacks it or the caller asks for it. `show` places a popover once, beside
|
|
1339
|
+
* whatever anchor the call hands over.
|
|
545
1340
|
*/
|
|
546
1341
|
declare class Anchors {
|
|
547
1342
|
/**
|
|
548
|
-
* Anchors a popover to its invoker.
|
|
1343
|
+
* Anchors a popover to its invoker for the popover's lifetime.
|
|
549
1344
|
*
|
|
550
|
-
*
|
|
551
|
-
*
|
|
1345
|
+
* On every platform the invoker is given an inline `anchor-name` and the
|
|
1346
|
+
* popover a `position-anchor` naming it, `--` followed by a unique id
|
|
1347
|
+
* built from `prefix`. That is what a stylesheet needs to place the popover
|
|
552
1348
|
* itself: the library's own menus say `top: anchor(bottom); left:
|
|
553
1349
|
* anchor(left)`. **Writing that css is the caller's half of this.** Without
|
|
554
1350
|
* it the popover lands wherever the user agent puts a popover, which is not
|
|
555
1351
|
* beside the invoker.
|
|
556
1352
|
*
|
|
557
|
-
* Where the platform has no anchor positioning
|
|
558
|
-
* instead
|
|
559
|
-
*
|
|
560
|
-
*
|
|
1353
|
+
* Where the platform has no css anchor positioning, or under `handPlace`,
|
|
1354
|
+
* the popover is placed in script instead: beside the invoker whenever it
|
|
1355
|
+
* opens, clamped 8px inside the viewport, placed again on every scroll and
|
|
1356
|
+
* resize while open, and its inline placement removed on close. The gap to
|
|
1357
|
+
* the invoker is read from the popover's css margins. From `beforetoggle`
|
|
1358
|
+
* to the placing, in a microtask before the `toggle` event, the popover
|
|
1359
|
+
* carries an inline `visibility: hidden`, so a stylesheet setting
|
|
1360
|
+
* `visibility` on it competes with that. A popover removed from the
|
|
1361
|
+
* document while open, or whose invoker was removed, stops being placed.
|
|
1362
|
+
*
|
|
1363
|
+
* The script placement puts a plain popover below the invoker,
|
|
1364
|
+
* start-aligned. A popover matching `ful-note`, `.ful-note` or
|
|
1365
|
+
* `[placement]` reads its `placement` attribute instead: `top`, `right`,
|
|
1366
|
+
* `left`, or `bottom` by default, centred on the invoker along the other
|
|
1367
|
+
* axis. Such a popover is also given `--ful-note-callout-inline` and
|
|
1368
|
+
* `--ful-note-callout-block`: the invoker's centre, in pixels, measured
|
|
1369
|
+
* from the popover's padding box, which stays on the invoker when the
|
|
1370
|
+
* viewport pushes the popover off it.
|
|
1371
|
+
*
|
|
1372
|
+
* Wiring the same pair twice adds its listeners twice.
|
|
561
1373
|
*
|
|
562
1374
|
* @param {HTMLElement} invoker the element the popover belongs to
|
|
563
1375
|
* @param {HTMLElement} popover the `[popover]` element to place
|
|
564
1376
|
* @param {object} [options]
|
|
565
|
-
* @param {string} [options.prefix] prefixes the generated anchor name and
|
|
566
|
-
* so the dom says which component a name
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
*
|
|
572
|
-
*
|
|
573
|
-
*
|
|
574
|
-
*
|
|
575
|
-
*
|
|
576
|
-
*
|
|
577
|
-
*
|
|
578
|
-
*
|
|
1377
|
+
* @param {string} [options.prefix] prefixes the generated anchor name and
|
|
1378
|
+
* id, `ful-anchor` by default, so the dom says which component a name
|
|
1379
|
+
* belongs to
|
|
1380
|
+
* @param {boolean} [options.invoke] makes the invoker toggle the popover,
|
|
1381
|
+
* which light dismiss then closes with no script of your own. The popover
|
|
1382
|
+
* is given the generated id when it has none. A `button` or `input`
|
|
1383
|
+
* invoker gets a `popovertarget` naming it; any other element toggles it
|
|
1384
|
+
* on click and on the Enter and Space keys; a click on it while the
|
|
1385
|
+
* popover is open closes the popover rather than opening it again
|
|
1386
|
+
* @param {boolean} [options.expanded] sets the invoker's `aria-expanded` to
|
|
1387
|
+
* `false` at once and keeps it in step with the popover's `toggle` events
|
|
1388
|
+
* @param {boolean} [options.stretch] in the script placement, sizes the
|
|
1389
|
+
* popover to at least its invoker's width, capped by its own `max-width`
|
|
1390
|
+
* and the viewport, and flips it above the invoker where the viewport
|
|
1391
|
+
* leaves no room below, which is what a combobox dropdown wants. The
|
|
1392
|
+
* `placement` attribute is not read
|
|
1393
|
+
* @param {boolean} [options.handPlace] places in script on every platform
|
|
1394
|
+
* rather than only as a fallback, for a popover that needs to know where
|
|
1395
|
+
* its invoker ended up, such as a note pointing a callout at it. Such a
|
|
1396
|
+
* popover declares no anchor placement in css
|
|
579
1397
|
*/
|
|
580
1398
|
static wire(invoker: HTMLElement, popover: HTMLElement, { prefix, invoke, expanded, stretch, handPlace }?: {
|
|
581
1399
|
prefix?: string;
|
|
@@ -584,74 +1402,187 @@ declare class Anchors {
|
|
|
584
1402
|
stretch?: boolean;
|
|
585
1403
|
handPlace?: boolean;
|
|
586
1404
|
}): void;
|
|
1405
|
+
/**
|
|
1406
|
+
* Shows a popover and places it beside an anchor, once. It serves a
|
|
1407
|
+
* popover shared by many invokers, each open handing over its own anchor,
|
|
1408
|
+
* and an anchor that is a rectangle rather than an element, such as one
|
|
1409
|
+
* read out of an iframe. Nothing is paired and nothing follows a later
|
|
1410
|
+
* scroll or resize; closing is the caller's, or the platform's for a
|
|
1411
|
+
* light-dismissing popover.
|
|
1412
|
+
*
|
|
1413
|
+
* The popover goes below the anchor, start-aligned, clamped 8px inside the
|
|
1414
|
+
* viewport. `flip` moves it above the anchor where there is no room below
|
|
1415
|
+
* and there is room above. The placement is written as inline `top`, `left`,
|
|
1416
|
+
* `right`, `bottom` and `margin`, which stay after the popover closes and
|
|
1417
|
+
* are overwritten by the next call.
|
|
1418
|
+
*
|
|
1419
|
+
* A popover not already open is shown with `showPopover()` and placed
|
|
1420
|
+
* before the call returns, so the first position anybody sees is the right
|
|
1421
|
+
* one and the caller can move the focus into it on the next line. One
|
|
1422
|
+
* already open is placed without being shown again.
|
|
1423
|
+
*
|
|
1424
|
+
* @param {HTMLElement} popover the `[popover]` element to show, or an
|
|
1425
|
+
* already-shown element to place
|
|
1426
|
+
* @param {Element|DOMRect} anchor the element, or the rectangle in
|
|
1427
|
+
* viewport coordinates, to place beside
|
|
1428
|
+
* @param {object} [options]
|
|
1429
|
+
* @param {boolean} [options.flip] place above the anchor where no room is
|
|
1430
|
+
* left below, `false` by default
|
|
1431
|
+
* @param {number} [options.gap] the distance from the anchor, in pixels,
|
|
1432
|
+
* `0` by default
|
|
1433
|
+
* @returns {HTMLElement} the popover
|
|
1434
|
+
*/
|
|
1435
|
+
static show(popover: HTMLElement, anchor: Element | DOMRect, { flip, gap }?: {
|
|
1436
|
+
flip?: boolean;
|
|
1437
|
+
gap?: number;
|
|
1438
|
+
}): HTMLElement;
|
|
587
1439
|
}
|
|
1440
|
+
export type SelectEntry = {
|
|
1441
|
+
key: any;
|
|
1442
|
+
label: string;
|
|
1443
|
+
metadata: any;
|
|
1444
|
+
};
|
|
1445
|
+
export type SelectHttpClient = {
|
|
1446
|
+
request(method: string, url: string): any;
|
|
1447
|
+
};
|
|
588
1448
|
/**
|
|
589
1449
|
* Fetches a select's whole vocabulary from a url and serves every later read
|
|
590
1450
|
* from it. Concurrent callers share one request, the options may be cached in
|
|
591
|
-
* local storage under a revision, and
|
|
1451
|
+
* local storage under a revision, and invalidating discards both.
|
|
592
1452
|
*/
|
|
593
1453
|
declare class RemoteLoader {
|
|
594
1454
|
#private;
|
|
1455
|
+
/**
|
|
1456
|
+
* @param {{ http: SelectHttpClient, url: string, method: string, responseMapper: (response: any) => SelectEntry[], prefetch: boolean, revision: string|null }} conf
|
|
1457
|
+
* a null revision never reads nor writes local storage
|
|
1458
|
+
*/
|
|
595
1459
|
constructor({ http, url, method, responseMapper, prefetch, revision }: {
|
|
596
|
-
http:
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
responseMapper: any;
|
|
600
|
-
|
|
601
|
-
|
|
1460
|
+
http: SelectHttpClient;
|
|
1461
|
+
url: string;
|
|
1462
|
+
method: string;
|
|
1463
|
+
responseMapper: (response: any) => SelectEntry[];
|
|
1464
|
+
prefetch: boolean;
|
|
1465
|
+
revision: string | null;
|
|
602
1466
|
});
|
|
1467
|
+
/**
|
|
1468
|
+
* Fetches the vocabulary now when the loader was built with prefetch, and
|
|
1469
|
+
* does nothing otherwise.
|
|
1470
|
+
* @returns {Promise<void>}
|
|
1471
|
+
* @throws when the fetch fails, or when an invalidation supersedes it
|
|
1472
|
+
*/
|
|
603
1473
|
prefetch(): Promise<void>;
|
|
604
|
-
exact(...keys: any[]): Promise<any>;
|
|
605
|
-
load(needle: any): Promise<any>;
|
|
606
1474
|
/**
|
|
607
|
-
*
|
|
608
|
-
*
|
|
609
|
-
*
|
|
1475
|
+
* The entries whose key reads as the same text as one of the keys, in
|
|
1476
|
+
* vocabulary order.
|
|
1477
|
+
* @param {...any} keys
|
|
1478
|
+
* @returns {Promise<SelectEntry[]>}
|
|
1479
|
+
* @throws when the fetch fails, or when an invalidation supersedes it
|
|
1480
|
+
*/
|
|
1481
|
+
exact(...keys: any[]): Promise<SelectEntry[]>;
|
|
1482
|
+
/**
|
|
1483
|
+
* The entries whose label contains the needle, ignoring case; every entry
|
|
1484
|
+
* for a nullish or empty needle.
|
|
1485
|
+
* @param {string|null} [needle]
|
|
1486
|
+
* @returns {Promise<SelectEntry[]>}
|
|
1487
|
+
* @throws when the fetch fails, or when an invalidation supersedes it
|
|
1488
|
+
*/
|
|
1489
|
+
load(needle?: string | null): Promise<SelectEntry[]>;
|
|
1490
|
+
/**
|
|
1491
|
+
* Drops the vocabulary held in memory so the next question refetches it,
|
|
1492
|
+
* which may still be answered from local storage under the same revision.
|
|
1493
|
+
* A fetch still in flight is detached: its outcome is neither served nor
|
|
1494
|
+
* stored, and the callers waiting on it reject.
|
|
1495
|
+
* @returns {Promise<void>}
|
|
610
1496
|
*/
|
|
611
1497
|
invalidate(): Promise<void>;
|
|
612
|
-
reconfigureUrl(url: any): Promise<void>;
|
|
613
1498
|
}
|
|
614
1499
|
/** Asks the endpoint per query instead of fetching the vocabulary once, for a list too large to hold in memory. */
|
|
615
1500
|
declare class PartialRemoteLoader {
|
|
616
1501
|
#private;
|
|
1502
|
+
/**
|
|
1503
|
+
* @param {{ http: SelectHttpClient, url: string, method: string, responseMapper: (response: any) => SelectEntry[] }} conf
|
|
1504
|
+
*/
|
|
617
1505
|
constructor({ http, url, method, responseMapper }: {
|
|
618
|
-
http:
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
1506
|
+
http: SelectHttpClient;
|
|
1507
|
+
url: string;
|
|
1508
|
+
method: string;
|
|
1509
|
+
responseMapper: (response: any) => SelectEntry[];
|
|
622
1510
|
});
|
|
623
1511
|
/**
|
|
624
|
-
*
|
|
625
|
-
*
|
|
1512
|
+
* Does nothing, since nothing is held between queries.
|
|
1513
|
+
* @returns {Promise<void>}
|
|
626
1514
|
*/
|
|
627
1515
|
invalidate(): Promise<void>;
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
1516
|
+
/**
|
|
1517
|
+
* Asks the endpoint for the entries of the keys, sent as repeated `k`
|
|
1518
|
+
* parameters.
|
|
1519
|
+
* @param {...any} keys
|
|
1520
|
+
* @returns {Promise<SelectEntry[]>}
|
|
1521
|
+
* @throws when the request fails
|
|
1522
|
+
*/
|
|
1523
|
+
exact(...keys: any[]): Promise<SelectEntry[]>;
|
|
1524
|
+
/**
|
|
1525
|
+
* Asks the endpoint for the entries matching the needle, sent as the `s`
|
|
1526
|
+
* parameter; the filtering is the endpoint's.
|
|
1527
|
+
* @param {string|null} [needle]
|
|
1528
|
+
* @returns {Promise<SelectEntry[]>}
|
|
1529
|
+
* @throws when the request fails
|
|
1530
|
+
*/
|
|
1531
|
+
load(needle?: string | null): Promise<SelectEntry[]>;
|
|
631
1532
|
}
|
|
632
1533
|
/** Serves a select's options from an array held in memory, which is what the slotted `<option>` elements become. */
|
|
633
1534
|
declare class InMemoryLoader {
|
|
634
1535
|
#private;
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
1536
|
+
/**
|
|
1537
|
+
* @param {SelectEntry[]} data
|
|
1538
|
+
*/
|
|
1539
|
+
constructor(data: SelectEntry[]);
|
|
1540
|
+
/**
|
|
1541
|
+
* Replaces the vocabulary every later question is answered from.
|
|
1542
|
+
* @param {SelectEntry[]} data
|
|
1543
|
+
*/
|
|
1544
|
+
update(data: SelectEntry[]): void;
|
|
1545
|
+
/**
|
|
1546
|
+
* Does nothing: the vocabulary is the data itself, which only update replaces.
|
|
1547
|
+
* @returns {Promise<void>}
|
|
1548
|
+
*/
|
|
1549
|
+
invalidate(): Promise<void>;
|
|
1550
|
+
/**
|
|
1551
|
+
* The entries whose key reads as the same text as one of the keys, in
|
|
1552
|
+
* vocabulary order.
|
|
1553
|
+
* @param {...any} keys
|
|
1554
|
+
* @returns {SelectEntry[]}
|
|
1555
|
+
*/
|
|
1556
|
+
exact(...keys: any[]): SelectEntry[];
|
|
1557
|
+
/**
|
|
1558
|
+
* The entries whose label contains the needle, ignoring case; every entry
|
|
1559
|
+
* for a nullish or empty needle.
|
|
1560
|
+
* @param {string|null} [needle]
|
|
1561
|
+
* @returns {SelectEntry[]}
|
|
1562
|
+
*/
|
|
1563
|
+
load(needle?: string | null): SelectEntry[];
|
|
641
1564
|
}
|
|
642
1565
|
/**
|
|
643
1566
|
* Builds the select's loader from its attributes: the slotted options in
|
|
644
|
-
* memory, or a remote or chunked loader over src.
|
|
1567
|
+
* memory, or a remote or chunked loader over src. It is registered as the
|
|
1568
|
+
* `loaders:select` component.
|
|
645
1569
|
*
|
|
646
|
-
* A component
|
|
647
|
-
*
|
|
648
|
-
* metadata }` entries:
|
|
1570
|
+
* A component named by the select's `loader` attribute replaces this one: its
|
|
1571
|
+
* `create(el, conf)` answers an object with these methods, each answering
|
|
1572
|
+
* `{ key, label, metadata }` entries, directly or through a promise:
|
|
649
1573
|
*
|
|
650
|
-
* - `prefetch()` warms the vocabulary if it can, and resolves either way
|
|
651
1574
|
* - `load(needle)` answers the entries matching the typed text, all of them
|
|
652
|
-
* when the needle is
|
|
1575
|
+
* when the needle is empty, which is the search the list opens with
|
|
653
1576
|
* - `exact(...keys)` answers the entries for those keys, used to label a value
|
|
654
|
-
* assigned without going through the list
|
|
1577
|
+
* assigned without going through the list; a key it leaves out is dropped
|
|
1578
|
+
* from the selection
|
|
1579
|
+
* - `prefetch()`, optional, warms the vocabulary; the select calls it at the
|
|
1580
|
+
* upgrade without waiting, and awaits it in `reload()`
|
|
1581
|
+
* - `invalidate()`, optional, drops whatever the loader holds, called by
|
|
1582
|
+
* `reload()`
|
|
1583
|
+
*
|
|
1584
|
+
* An entry whose `metadata.disabled` is truthy is shown and cannot be picked,
|
|
1585
|
+
* with `metadata.reason`, when present, as the row's title.
|
|
655
1586
|
*/
|
|
656
1587
|
declare class SelectLoader {
|
|
657
1588
|
#private;
|
|
@@ -661,131 +1592,537 @@ declare class SelectLoader {
|
|
|
661
1592
|
* `mode: 'chunked'`, per query. A test, or a caller holding its own
|
|
662
1593
|
* configuration, builds a loader this way; `create` is the same thing with
|
|
663
1594
|
* an element's attributes parsed first.
|
|
664
|
-
*
|
|
1595
|
+
*
|
|
1596
|
+
* A remote loader fetches once and filters in memory, caching the response
|
|
1597
|
+
* in local storage under `method@url` when a revision is given; a chunked
|
|
1598
|
+
* one sends every search as `s` and every key lookup as `k`. The response
|
|
1599
|
+
* mapper turns the parsed response body into entries.
|
|
1600
|
+
* @param {{ data?: SelectEntry[], url?: undefined, http?: undefined, method?: undefined, mode?: undefined, prefetch?: undefined, revision?: undefined, responseMapper?: undefined }
|
|
1601
|
+
* | { data?: undefined, url: string, http: SelectHttpClient, method?: string, mode?: string, prefetch?: boolean, revision?: string|null, responseMapper: (response: any) => SelectEntry[] }} conf
|
|
1602
|
+
* `method` defaults to POST
|
|
1603
|
+
* @returns {InMemoryLoader|PartialRemoteLoader|RemoteLoader}
|
|
665
1604
|
*/
|
|
666
1605
|
static from({ data, http, url, method, mode, prefetch, revision, responseMapper }: {
|
|
667
|
-
data?:
|
|
668
|
-
|
|
669
|
-
|
|
1606
|
+
data?: SelectEntry[];
|
|
1607
|
+
url?: undefined;
|
|
1608
|
+
http?: undefined;
|
|
1609
|
+
method?: undefined;
|
|
1610
|
+
mode?: undefined;
|
|
1611
|
+
prefetch?: undefined;
|
|
1612
|
+
revision?: undefined;
|
|
1613
|
+
responseMapper?: undefined;
|
|
1614
|
+
} | {
|
|
1615
|
+
data?: undefined;
|
|
1616
|
+
url: string;
|
|
1617
|
+
http: SelectHttpClient;
|
|
670
1618
|
method?: string;
|
|
671
1619
|
mode?: string;
|
|
672
1620
|
prefetch?: boolean;
|
|
673
1621
|
revision?: string | null;
|
|
674
|
-
responseMapper
|
|
1622
|
+
responseMapper: (response: any) => SelectEntry[];
|
|
1623
|
+
}): InMemoryLoader | PartialRemoteLoader | RemoteLoader;
|
|
1624
|
+
/**
|
|
1625
|
+
* Builds the loader an element's attributes describe. Without `src` the
|
|
1626
|
+
* vocabulary is the `<option>` elements of `conf.options`, each keyed by its
|
|
1627
|
+
* `value` attribute or else its trimmed text. With `src` the url is
|
|
1628
|
+
* requested through the `http-client` component with `method` (POST by
|
|
1629
|
+
* default): once on first use, or at the upgrade under `preload`, or per
|
|
1630
|
+
* query under `mode="chunked"`. A `revision` caches the whole response in local storage; a
|
|
1631
|
+
* valueless one takes the `revision` component, calling it when it is a
|
|
1632
|
+
* function, and warns and does not cache when none is registered.
|
|
1633
|
+
*
|
|
1634
|
+
* The response becomes entries through `k-expr` and `l-expr` evaluated on
|
|
1635
|
+
* each row of `d-expr` (the response itself by default), with `m-expr` as
|
|
1636
|
+
* the metadata (the row by default); else through the `response-mapper`
|
|
1637
|
+
* component; else each row is read as a `[key, label, metadata]` array.
|
|
1638
|
+
* @param {ParsedElement} el the element declaring the loader attributes
|
|
1639
|
+
* @param {{ options?: DocumentFragment }} conf
|
|
1640
|
+
* @returns {InMemoryLoader|PartialRemoteLoader|RemoteLoader}
|
|
1641
|
+
*/
|
|
1642
|
+
static create(el: ParsedElement, conf: {
|
|
1643
|
+
options?: DocumentFragment;
|
|
675
1644
|
}): InMemoryLoader | PartialRemoteLoader | RemoteLoader;
|
|
676
|
-
static create(el: any, conf: any): InMemoryLoader | PartialRemoteLoader | RemoteLoader;
|
|
677
1645
|
}
|
|
678
|
-
/**
|
|
1646
|
+
/**
|
|
1647
|
+
* The options popup of a select, a `<ful-dropdown>` the owner shows as a
|
|
1648
|
+
* popover: a spinner while the loader runs, a localized empty state, and a
|
|
1649
|
+
* `role="listbox"` menu of `role="option"` rows.
|
|
1650
|
+
*
|
|
1651
|
+
* The owner drives it and listens to it. A pick dispatches a bubbling
|
|
1652
|
+
* `change` whose detail is `{ index, entry }`, the row's index as a string
|
|
1653
|
+
* and the entry it was rendered from. The active row is announced by a
|
|
1654
|
+
* non-bubbling `activechange` whose detail is `{ id }`, the row's id or null
|
|
1655
|
+
* when none is active, for the owner to set `aria-activedescendant`. A
|
|
1656
|
+
* pressed row does not take the focus from the owner's control.
|
|
1657
|
+
*/
|
|
679
1658
|
declare class Dropdown extends ParsedElement {
|
|
680
1659
|
#private;
|
|
1660
|
+
/**
|
|
1661
|
+
* `listbox` is the id given to the menu, so an owner can set
|
|
1662
|
+
* `aria-controls` before this element upgrades; a generated id otherwise.
|
|
1663
|
+
*/
|
|
681
1664
|
static attributes: string[];
|
|
1665
|
+
/** The default slot, when not blank, is the row template in place of the `options` template. */
|
|
682
1666
|
static slots: boolean;
|
|
683
1667
|
static template: string;
|
|
1668
|
+
/**
|
|
1669
|
+
* `options` renders one row per entry, each entry carrying its `index`
|
|
1670
|
+
* beside its own keys. A replacement must keep one `<li>` per entry, in
|
|
1671
|
+
* order, with the index as its `value`: picking reads the entry back from it.
|
|
1672
|
+
*/
|
|
684
1673
|
static templates: {
|
|
685
1674
|
options: string;
|
|
686
1675
|
};
|
|
1676
|
+
/**
|
|
1677
|
+
* @param {{ slots: Record<string, DocumentFragment> }} conf
|
|
1678
|
+
*/
|
|
687
1679
|
render({ slots }: {
|
|
688
|
-
slots:
|
|
1680
|
+
slots: Record<string, DocumentFragment>;
|
|
689
1681
|
}): void;
|
|
1682
|
+
/**
|
|
1683
|
+
* Picks the highlighted row, or the first enabled one when none is: hides
|
|
1684
|
+
* the dropdown and dispatches `change`. Does nothing when the highlighted
|
|
1685
|
+
* row is disabled, when no row is enabled, or while a search is loading
|
|
1686
|
+
* and the rows are hidden.
|
|
1687
|
+
*/
|
|
690
1688
|
acceptSelection(): void;
|
|
691
|
-
|
|
1689
|
+
/**
|
|
1690
|
+
* Renders the entries as rows and highlights the first one whose key is
|
|
1691
|
+
* picked, else the row the template marked `selected`, else the first
|
|
1692
|
+
* enabled row. A row is marked `picked` and
|
|
1693
|
+
* `aria-selected="true"` when its key reads as the same text as one of the keys, and
|
|
1694
|
+
* `aria-disabled="true"` when its `metadata.disabled` is truthy, titled with
|
|
1695
|
+
* `metadata.reason`. No entries shows the empty state instead of the menu.
|
|
1696
|
+
* @param {SelectEntry[]} values
|
|
1697
|
+
* @param {any[]} [keys] the keys currently selected
|
|
1698
|
+
* @throws {Error} when values is undefined
|
|
1699
|
+
*/
|
|
1700
|
+
update(values: SelectEntry[], keys?: any[]): void;
|
|
1701
|
+
/**
|
|
1702
|
+
* Closes the popover, if open, and announces that no row is active. A
|
|
1703
|
+
* `show` still waiting on its loader is superseded: its outcome is neither
|
|
1704
|
+
* rendered nor thrown.
|
|
1705
|
+
*/
|
|
692
1706
|
hide(): void;
|
|
1707
|
+
/**
|
|
1708
|
+
* Whether the popover is open.
|
|
1709
|
+
* @returns {boolean}
|
|
1710
|
+
*/
|
|
693
1711
|
get shown(): boolean;
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
1712
|
+
/**
|
|
1713
|
+
* Opens the popover with the spinner showing, then renders what the loader
|
|
1714
|
+
* answers as `update` does. A show overtaken by a later `show` or by `hide`
|
|
1715
|
+
* before its loader settles leaves the dropdown alone and resolves, even
|
|
1716
|
+
* when its loader rejected.
|
|
1717
|
+
* @param {() => SelectEntry[]|Promise<SelectEntry[]>} loader
|
|
1718
|
+
* @param {any[]} [keys] the keys currently selected
|
|
1719
|
+
* @returns {Promise<void>}
|
|
1720
|
+
* @throws what the loader threw, after hiding the dropdown, when this show
|
|
1721
|
+
* is still the current one
|
|
1722
|
+
*/
|
|
1723
|
+
show(loader: () => SelectEntry[] | Promise<SelectEntry[]>, keys?: any[]): Promise<void>;
|
|
1724
|
+
/**
|
|
1725
|
+
* Moves the highlight to the next or previous enabled row when the dropdown
|
|
1726
|
+
* is shown, staying put at the edge and while a search is loading, and
|
|
1727
|
+
* shows it otherwise.
|
|
1728
|
+
* @param {boolean} forward
|
|
1729
|
+
* @param {() => SelectEntry[]|Promise<SelectEntry[]>} loader used only to show
|
|
1730
|
+
* @param {any[]} [keys] the keys currently selected, used only to show
|
|
1731
|
+
* @returns {Promise<void>}
|
|
1732
|
+
* @throws what `show` throws
|
|
1733
|
+
*/
|
|
1734
|
+
moveOrShow(forward: boolean, loader: () => SelectEntry[] | Promise<SelectEntry[]>, keys?: any[]): Promise<void>;
|
|
1735
|
+
/**
|
|
1736
|
+
* Highlights the first enabled row, or the last one. Does nothing while a
|
|
1737
|
+
* search is loading and the rows are hidden.
|
|
1738
|
+
* @param {boolean} first
|
|
1739
|
+
*/
|
|
1740
|
+
jump(first: boolean): void;
|
|
1741
|
+
/**
|
|
1742
|
+
* Moves the highlight by as many enabled rows as the menu shows at once,
|
|
1743
|
+
* one when that cannot be measured, stopping at the last enabled row.
|
|
1744
|
+
* Does nothing while a search is loading.
|
|
1745
|
+
* @param {boolean} forward
|
|
1746
|
+
*/
|
|
1747
|
+
page(forward: boolean): void;
|
|
698
1748
|
}
|
|
699
|
-
/**
|
|
1749
|
+
/**
|
|
1750
|
+
* A `<ful-select>`: a combobox over a loader's vocabulary of
|
|
1751
|
+
* `{ key, label, metadata }` entries, holding one key or, under `multiple`,
|
|
1752
|
+
* several. Typing filters the list, opening it from rest offers the whole
|
|
1753
|
+
* vocabulary, and the keyboard follows the combobox pattern: arrows move and
|
|
1754
|
+
* open (Alt+ArrowDown opens, Alt+ArrowUp closes), Home, End, PageUp and
|
|
1755
|
+
* PageDown move in the open list, Enter accepts the highlighted entry or,
|
|
1756
|
+
* with the list closed, submits the form, Escape reverts the edit, and Tab
|
|
1757
|
+
* or leaving the field commits it. Emptying the text of a single select and
|
|
1758
|
+
* leaving the field clears it. Backspace with the caret at the start removes
|
|
1759
|
+
* the last entry, and ArrowLeft there moves the focus to the badges of a
|
|
1760
|
+
* multiple select, where Enter, Space, Backspace or Delete remove one.
|
|
1761
|
+
*
|
|
1762
|
+
* Slots: the default one is the label, `info` sits beside it, `before` and
|
|
1763
|
+
* `after` are affixes around the control, `options` holds the `<option>`
|
|
1764
|
+
* elements of an in-memory vocabulary, `dropdown` replaces the dropdown's
|
|
1765
|
+
* row template and `items` the `items` template.
|
|
1766
|
+
*
|
|
1767
|
+
* Every change of the selection made through the element dispatches a
|
|
1768
|
+
* bubbling `change` whose detail carries `value` and `entry`, as the getters
|
|
1769
|
+
* answer them; assigning `value` dispatches none.
|
|
1770
|
+
*/
|
|
700
1771
|
declare class Select extends Field {
|
|
701
1772
|
#private;
|
|
1773
|
+
/**
|
|
1774
|
+
* Read once at the upgrade, so a later write changes nothing: `name`,
|
|
1775
|
+
* `loader` (the component building the loader, `loaders:select` by
|
|
1776
|
+
* default), `k-type` (`number` or `boolean` coerce the keys, strings
|
|
1777
|
+
* otherwise), and the loader configuration `SelectLoader.create` reads,
|
|
1778
|
+
* but for `src` and `method`, which stay live.
|
|
1779
|
+
*/
|
|
702
1780
|
static attributes: string[];
|
|
1781
|
+
/**
|
|
1782
|
+
* Beside the field's claims: `multiple`, `item-list`, `value` as a comma
|
|
1783
|
+
* separated list of keys, trimmed, whether or not the select is multiple,
|
|
1784
|
+
* and `src` and `method`.
|
|
1785
|
+
*/
|
|
703
1786
|
static observed: string[];
|
|
1787
|
+
/**
|
|
1788
|
+
* Reads a present but empty `value` attribute of a single select as the
|
|
1789
|
+
* empty key, which an `<option value="">` can carry; a multiple select reads
|
|
1790
|
+
* it as no keys.
|
|
1791
|
+
* @param {string} attr
|
|
1792
|
+
* @param {string|null} str
|
|
1793
|
+
* @returns {any}
|
|
1794
|
+
* @throws when the class declares no such attribute
|
|
1795
|
+
*/
|
|
1796
|
+
unmarshal(attr: string, str: string | null): any;
|
|
704
1797
|
static slots: boolean;
|
|
705
1798
|
static template: string;
|
|
1799
|
+
/**
|
|
1800
|
+
* `items` renders the selection below the control, shown under `item-list`,
|
|
1801
|
+
* over `entries`, the selected entries in order. A replacement must keep one
|
|
1802
|
+
* `<ful-item>` per entry, in order, each with a `<button>` that removes it.
|
|
1803
|
+
*/
|
|
706
1804
|
static templates: {
|
|
707
1805
|
items: string;
|
|
708
1806
|
};
|
|
1807
|
+
/**
|
|
1808
|
+
* @param {{ slots: Record<string, DocumentFragment> }} conf
|
|
1809
|
+
* @returns {{ fragment: DocumentFragment, control: HTMLInputElement, error: Element|null, label: Element|null }}
|
|
1810
|
+
*/
|
|
709
1811
|
_build({ slots }: {
|
|
710
|
-
slots:
|
|
1812
|
+
slots: Record<string, DocumentFragment>;
|
|
711
1813
|
}): {
|
|
712
|
-
fragment:
|
|
713
|
-
control:
|
|
714
|
-
error:
|
|
715
|
-
label:
|
|
1814
|
+
fragment: DocumentFragment;
|
|
1815
|
+
control: HTMLInputElement;
|
|
1816
|
+
error: Element | null;
|
|
1817
|
+
label: Element | null;
|
|
716
1818
|
};
|
|
717
|
-
/**
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
*
|
|
721
|
-
*
|
|
722
|
-
*
|
|
723
|
-
|
|
724
|
-
|
|
1819
|
+
/**
|
|
1820
|
+
* Hands the loader to the callback, for runtime changes such as
|
|
1821
|
+
* `update(entries)` on an in-memory loader.
|
|
1822
|
+
* @template T
|
|
1823
|
+
* @param {(loader: any) => T|Promise<T>} fn
|
|
1824
|
+
* @returns {Promise<T>} what the callback answers
|
|
1825
|
+
*/
|
|
1826
|
+
withLoader<T>(fn: (loader: any) => T | Promise<T>): Promise<T>;
|
|
1827
|
+
/**
|
|
1828
|
+
* Drops whatever the loader is holding, awaits its prefetch (which fetches
|
|
1829
|
+
* again when the select declares `preload`), and asks it about the current
|
|
1830
|
+
* selection again, which is what a select whose vocabulary depends on
|
|
1831
|
+
* another control needs when that control changes. A key the loader no
|
|
1832
|
+
* longer knows is dropped from the selection, so a value invalidated by the
|
|
1833
|
+
* change does not survive it, and one it still knows keeps its place with a
|
|
1834
|
+
* fresh label. The badges and items follow, an open dropdown runs its
|
|
1835
|
+
* search again, and no `change` is dispatched.
|
|
725
1836
|
*
|
|
726
|
-
*
|
|
1837
|
+
* Where the vocabulary lives at a different address, write `src` or call
|
|
1838
|
+
* `reconfigure`, which build the loader for the new url and reload.
|
|
1839
|
+
* @returns {Promise<void>}
|
|
1840
|
+
* @throws what the loader's invalidate, prefetch, key lookup or search
|
|
1841
|
+
* throws
|
|
1842
|
+
*/
|
|
1843
|
+
reload(): Promise<void>;
|
|
1844
|
+
/**
|
|
1845
|
+
* The url the loader asks for the vocabulary, reflected as the `src`
|
|
1846
|
+
* attribute.
|
|
1847
|
+
* @returns {string|null}
|
|
1848
|
+
*/
|
|
1849
|
+
get src(): string | null;
|
|
1850
|
+
/**
|
|
1851
|
+
* Points the select at another vocabulary: the dropdown closes, the loader
|
|
1852
|
+
* is built again through its component's `create`, as at the render, and
|
|
1853
|
+
* the select reloads as `reload()` does, so a selected key the new
|
|
1854
|
+
* vocabulary does not know is dropped and one it knows is labelled again,
|
|
1855
|
+
* with no `change` dispatched. A write that does not change the url does
|
|
1856
|
+
* nothing.
|
|
727
1857
|
*
|
|
728
|
-
*
|
|
729
|
-
*
|
|
730
|
-
*
|
|
1858
|
+
* The reload is not awaited: a failed fetch or lookup surfaces as an
|
|
1859
|
+
* unhandled rejection.
|
|
1860
|
+
* @param {string|null|undefined} value null or undefined removes the url,
|
|
1861
|
+
* which the default loader answers with the slotted options
|
|
1862
|
+
*/
|
|
1863
|
+
set src(value: string | null | undefined);
|
|
1864
|
+
/**
|
|
1865
|
+
* The http method the default loader sends, reflected as the `method`
|
|
1866
|
+
* attribute; `POST` when absent.
|
|
1867
|
+
* @returns {string|null}
|
|
1868
|
+
*/
|
|
1869
|
+
get method(): string | null;
|
|
1870
|
+
/**
|
|
1871
|
+
* Changes the http method the way `src` changes the url: the loader is
|
|
1872
|
+
* built again and the select reloads.
|
|
1873
|
+
* @param {string|null|undefined} value
|
|
1874
|
+
*/
|
|
1875
|
+
set method(value: string | null | undefined);
|
|
1876
|
+
/**
|
|
1877
|
+
* Writes `src` and `method` together and reloads once: the loader is built
|
|
1878
|
+
* again for the pair when either changed, as a single write of either does,
|
|
1879
|
+
* and the select then reloads as `reload()` does, whether or not they
|
|
1880
|
+
* changed.
|
|
1881
|
+
*
|
|
1882
|
+
* citta.addEventListener('change', () => {
|
|
1883
|
+
* cap.reconfigure({ src: `/api/cap?citta=${citta.value}` }, { notify: true });
|
|
731
1884
|
* });
|
|
1885
|
+
* @param {{ src?: string|null, method?: string|null }} attributes a name
|
|
1886
|
+
* left out keeps its value, null removes the attribute
|
|
1887
|
+
* @param {{ notify?: boolean }} [options] `notify` dispatches `change` when
|
|
1888
|
+
* the reload dropped a selected key, so a form or a table filtered by the
|
|
1889
|
+
* select sees the value it lost; nothing is dispatched otherwise
|
|
1890
|
+
* @returns {Promise<void>} settling once the reload has
|
|
1891
|
+
* @throws what the loader's invalidate, prefetch or key lookup throws
|
|
1892
|
+
*/
|
|
1893
|
+
reconfigure(attributes: {
|
|
1894
|
+
src?: string | null;
|
|
1895
|
+
method?: string | null;
|
|
1896
|
+
}, { notify }?: {
|
|
1897
|
+
notify?: boolean;
|
|
1898
|
+
}): Promise<void>;
|
|
1899
|
+
/**
|
|
1900
|
+
* The text typed to search the vocabulary: what the dropdown was last
|
|
1901
|
+
* asked to match. `''` while the field is not being searched, its control
|
|
1902
|
+
* then showing the selection's label rather than a query.
|
|
1903
|
+
* @returns {string}
|
|
1904
|
+
*/
|
|
1905
|
+
get query(): string;
|
|
1906
|
+
/**
|
|
1907
|
+
* Selects the keys, coerced by `k-type`: a key, an array of keys, or null or
|
|
1908
|
+
* undefined for none. The empty string is a key like any other, and a
|
|
1909
|
+
* single select keeps only the first key. The keys are applied at once, each labeled by itself until the loader's `exact`
|
|
1910
|
+
* answers; a key it does not answer is then dropped, a key removed in the
|
|
1911
|
+
* meantime stays removed, and a later assignment wins over the late answer.
|
|
1912
|
+
* A failed lookup keeps the keys and surfaces as an unhandled rejection.
|
|
1913
|
+
* No `change` is dispatched. A key containing a
|
|
1914
|
+
* comma, which the value attribute cannot carry, is kept and warned about
|
|
1915
|
+
* once per element. Before the render the write is held for the render to
|
|
1916
|
+
* apply, over the `value` attribute, which it leaves alone.
|
|
1917
|
+
* @param {any} vs
|
|
732
1918
|
*/
|
|
733
|
-
reload(): Promise<void>;
|
|
734
1919
|
set value(vs: any);
|
|
1920
|
+
/**
|
|
1921
|
+
* The selected keys, in selection order, for a multiple select; the one
|
|
1922
|
+
* key, or null, for a single one. Before the render it answers the keys
|
|
1923
|
+
* last written, or the `value` attribute, coerced and cut to one key as the
|
|
1924
|
+
* rendered select would.
|
|
1925
|
+
* @returns {any}
|
|
1926
|
+
*/
|
|
735
1927
|
get value(): any;
|
|
736
|
-
/**
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
1928
|
+
/**
|
|
1929
|
+
* The selection as entries, the ones in the `change` detail: an array for
|
|
1930
|
+
* a multiple select, the one entry or null for a single one. An entry whose
|
|
1931
|
+
* label has not been resolved yet carries its key as the label.
|
|
1932
|
+
* @returns {SelectEntry|SelectEntry[]|null}
|
|
1933
|
+
*/
|
|
1934
|
+
get entry(): SelectEntry | SelectEntry[] | null;
|
|
1935
|
+
/**
|
|
1936
|
+
* The field's disabled claim; turning it on while the dropdown is open
|
|
1937
|
+
* closes it and drops a pending search.
|
|
1938
|
+
* @type {boolean}
|
|
1939
|
+
*/
|
|
1940
|
+
get disabled(): boolean;
|
|
1941
|
+
set disabled(v: boolean);
|
|
1942
|
+
/**
|
|
1943
|
+
* The field's readonly claim; turning it on while the dropdown is open
|
|
1944
|
+
* closes it and drops a pending search.
|
|
1945
|
+
* @type {boolean}
|
|
1946
|
+
*/
|
|
1947
|
+
get readonly(): boolean;
|
|
1948
|
+
set readonly(v: boolean);
|
|
1949
|
+
/**
|
|
1950
|
+
* Whether the select holds several keys: `value` and `entry` answer arrays,
|
|
1951
|
+
* the input stays empty and the selection shows as removable badges in the
|
|
1952
|
+
* control. Before the render it answers the `multiple` attribute.
|
|
1953
|
+
* @returns {boolean}
|
|
1954
|
+
*/
|
|
1955
|
+
get multiple(): boolean;
|
|
1956
|
+
/**
|
|
1957
|
+
* Turning it off keeps only the first selected key; either way the badges,
|
|
1958
|
+
* the items and the input follow at once.
|
|
1959
|
+
* @param {boolean} v
|
|
1960
|
+
*/
|
|
1961
|
+
set multiple(v: boolean);
|
|
1962
|
+
/**
|
|
1963
|
+
* Whether the selection shows as the `items` list below the control instead
|
|
1964
|
+
* of as badges in it.
|
|
1965
|
+
* @returns {boolean}
|
|
1966
|
+
*/
|
|
1967
|
+
get itemList(): boolean;
|
|
1968
|
+
/** @param {boolean} v */
|
|
1969
|
+
set itemList(v: boolean);
|
|
742
1970
|
}
|
|
743
|
-
/**
|
|
1971
|
+
/**
|
|
1972
|
+
* A group of radios declared as `ful-radio` children. Each `ful-radio` becomes
|
|
1973
|
+
* a radio input carrying its attributes, labelled by its content; every
|
|
1974
|
+
* `input-*` attribute on the group is forwarded onto each radio as well. The
|
|
1975
|
+
* default slot is the `<legend>`, and `header` and `footer` slots frame the
|
|
1976
|
+
* list. The radios share a name of their own, minted afresh for each group
|
|
1977
|
+
* (from `name` when there is one) so that same-named groups stay apart, and
|
|
1978
|
+
* carry `form=""`, so the group is the only element the form sees. A radio's
|
|
1979
|
+
* native `change` is stopped and republished as the group's own.
|
|
1980
|
+
*
|
|
1981
|
+
* The host carries the `radiogroup` role, `aria-readonly`, `aria-required`,
|
|
1982
|
+
* `aria-invalid` and the description. The disabled and readonly claims act on
|
|
1983
|
+
* the group's `<fieldset>`, and readonly refuses every click inside it.
|
|
1984
|
+
* `focus()` lands on the first radio.
|
|
1985
|
+
*/
|
|
744
1986
|
declare class RadioGroup extends Field {
|
|
745
1987
|
#private;
|
|
1988
|
+
/** @type {string[]} */
|
|
746
1989
|
static attributes: string[];
|
|
747
1990
|
static slots: boolean;
|
|
1991
|
+
/** @type {string} */
|
|
748
1992
|
static ROLE: string;
|
|
749
1993
|
static template: string;
|
|
750
1994
|
/**
|
|
751
1995
|
* @param {{slots: any}} conf
|
|
752
|
-
* @returns {any}
|
|
1996
|
+
* @returns {any} the pieces: the first radio as the control, the fieldset
|
|
1997
|
+
* as the `claims` and `freeze` pieces, and the host as the `described` and
|
|
1998
|
+
* `announces` pieces
|
|
753
1999
|
*/
|
|
754
2000
|
_build({ slots }: {
|
|
755
2001
|
slots: any;
|
|
756
2002
|
}): any;
|
|
2003
|
+
/**
|
|
2004
|
+
* The value of the checked radio, `null` when none is. Under
|
|
2005
|
+
* `type="boolean"` it answers `true` for a radio whose value is `true` and
|
|
2006
|
+
* `false` for any other. Writing a value checks the radio carrying it, and
|
|
2007
|
+
* writing `null` or a value no radio carries clears the selection. Before
|
|
2008
|
+
* the render it answers the value last written, or the `value` attribute,
|
|
2009
|
+
* when a `ful-radio` carries it, and a write is held for the render to
|
|
2010
|
+
* apply.
|
|
2011
|
+
* @type {string | boolean | null}
|
|
2012
|
+
*/
|
|
757
2013
|
get value(): string | boolean | null;
|
|
758
2014
|
set value(value: string | boolean | null);
|
|
759
2015
|
}
|
|
760
|
-
/**
|
|
2016
|
+
/**
|
|
2017
|
+
* A checkbox, or a switch with the `switch` role under `type="switch"`. The
|
|
2018
|
+
* label is the default slot, pointed at the input with `for` and `id`, so a
|
|
2019
|
+
* click on it toggles the value. Every `input-*` attribute is forwarded onto
|
|
2020
|
+
* the input. The input's native `change` is stopped and republished as the
|
|
2021
|
+
* field's own. Readonly freezes the whole choice, label included: no click
|
|
2022
|
+
* inside it toggles the value while the claim holds.
|
|
2023
|
+
*/
|
|
761
2024
|
declare class Checkbox extends Field {
|
|
762
2025
|
#private;
|
|
2026
|
+
/** @type {string[]} */
|
|
763
2027
|
static attributes: string[];
|
|
2028
|
+
/** @type {string[]} */
|
|
764
2029
|
static observed: string[];
|
|
765
2030
|
static slots: boolean;
|
|
766
2031
|
static template: string;
|
|
2032
|
+
/**
|
|
2033
|
+
* @param {{ slots: Record<string, DocumentFragment> | undefined }} conf
|
|
2034
|
+
* @returns {any} the pieces, the `ful-choice` container being the `freeze` piece
|
|
2035
|
+
*/
|
|
767
2036
|
_build({ slots }: {
|
|
768
|
-
slots:
|
|
769
|
-
}):
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
2037
|
+
slots: Record<string, DocumentFragment> | undefined;
|
|
2038
|
+
}): any;
|
|
2039
|
+
/**
|
|
2040
|
+
* Whether the box is checked. The `value` attribute is read with the `bool`
|
|
2041
|
+
* mapper, where only the text `true` means checked. Before the render it
|
|
2042
|
+
* answers the value last written, or the `value` attribute, and a write is
|
|
2043
|
+
* held for the render to apply.
|
|
2044
|
+
* @type {boolean}
|
|
2045
|
+
*/
|
|
2046
|
+
get value(): boolean;
|
|
2047
|
+
set value(value: boolean);
|
|
778
2048
|
}
|
|
779
|
-
|
|
2049
|
+
export type TablePageRequest = {
|
|
2050
|
+
page: number;
|
|
2051
|
+
size: number;
|
|
2052
|
+
};
|
|
2053
|
+
export type TableSortRequest = {
|
|
2054
|
+
sorter: string;
|
|
2055
|
+
order: string;
|
|
2056
|
+
};
|
|
2057
|
+
export type TablePageResponse = {
|
|
2058
|
+
data: any[];
|
|
2059
|
+
size: number;
|
|
2060
|
+
};
|
|
2061
|
+
export type TableRowLoader = {
|
|
2062
|
+
load(pageRequest: TablePageRequest, sortRequest: TableSortRequest | null, filterRequest: Record<string, any>): Promise<TablePageResponse>;
|
|
2063
|
+
};
|
|
2064
|
+
/**
|
|
2065
|
+
* @typedef {{ page: number, size: number }} TablePageRequest the zero based
|
|
2066
|
+
* index of the page and the number of rows in a page
|
|
2067
|
+
*/
|
|
2068
|
+
/**
|
|
2069
|
+
* @typedef {{ sorter: string, order: string }} TableSortRequest the sort key
|
|
2070
|
+
* of a column and its direction, `asc` or `desc`
|
|
2071
|
+
*/
|
|
2072
|
+
/**
|
|
2073
|
+
* @typedef {{ data: any[], size: number }} TablePageResponse the rows of the
|
|
2074
|
+
* requested page and the total number of rows across every page
|
|
2075
|
+
*/
|
|
2076
|
+
/**
|
|
2077
|
+
* @typedef {{ load(pageRequest: TablePageRequest, sortRequest: TableSortRequest|null, filterRequest: Record<string, any>): Promise<TablePageResponse> }} TableRowLoader
|
|
2078
|
+
*/
|
|
2079
|
+
/**
|
|
2080
|
+
* The sort control of a table header, `ful-sorter`: a `role="button"` with
|
|
2081
|
+
* `tabindex="0"`, activated by a click or by Enter, NumpadEnter or Space.
|
|
2082
|
+
*
|
|
2083
|
+
* Each activation dispatches `sort:requested` (bubbling, not cancelable) with
|
|
2084
|
+
* `detail.value` set to `{ sorter, order }`: `sorter` is the `sorter`
|
|
2085
|
+
* attribute, read once at the upgrade, and `order` is the one after the
|
|
2086
|
+
* current `order` in the cycle `asc`, `desc`, `null`. The button does not
|
|
2087
|
+
* change its own `order`: whoever handles the event sets it, which `ful-table`
|
|
2088
|
+
* does once the sorted page has loaded.
|
|
2089
|
+
*/
|
|
780
2090
|
declare class SortButton extends ParsedElement {
|
|
781
2091
|
#private;
|
|
782
2092
|
static attributes: string[];
|
|
783
2093
|
static observed: string[];
|
|
784
2094
|
render(): void;
|
|
785
|
-
|
|
786
|
-
|
|
2095
|
+
/**
|
|
2096
|
+
* The direction the column is sorted in, `null` when unsorted.
|
|
2097
|
+
* @returns {string|null}
|
|
2098
|
+
*/
|
|
2099
|
+
get order(): string | null;
|
|
2100
|
+
/**
|
|
2101
|
+
* Reflects the direction to the `order` attribute and sets `aria-sort` on
|
|
2102
|
+
* the enclosing `<th>`, if any: `ascending` for `asc`, `descending` for any
|
|
2103
|
+
* other non-empty value, removed for an empty one.
|
|
2104
|
+
* @param {string|null} value an empty string or `null` means unsorted
|
|
2105
|
+
*/
|
|
2106
|
+
set order(value: string | null);
|
|
787
2107
|
}
|
|
788
|
-
/**
|
|
2108
|
+
/**
|
|
2109
|
+
* The pager, `ful-pagination`: a previous button, a window of page buttons
|
|
2110
|
+
* around the current page, a next button, a reload button and a line saying
|
|
2111
|
+
* which page of how many is shown.
|
|
2112
|
+
*
|
|
2113
|
+
* The window holds at most `pages` buttons (read once at the upgrade, default 5),
|
|
2114
|
+
* centred on the current page and shifted back on the last pages so it stays
|
|
2115
|
+
* full. The current page's button carries `aria-current="page"` and stays
|
|
2116
|
+
* enabled. Previous and next are disabled where there is no page to go to.
|
|
2117
|
+
*
|
|
2118
|
+
* A click on an enabled button other than the current page dispatches
|
|
2119
|
+
* `page:requested` (bubbling, not cancelable) with `detail.value` the zero based
|
|
2120
|
+
* index of the page asked for; the reload button asks for the current page.
|
|
2121
|
+
* The pager does not move itself: whoever handles the event calls `update`,
|
|
2122
|
+
* which `ful-table` does once the page has loaded.
|
|
2123
|
+
*
|
|
2124
|
+
* The icons are the `ful-icon` names in `Pagination.config`.
|
|
2125
|
+
*/
|
|
789
2126
|
declare class Pagination extends ParsedElement {
|
|
790
2127
|
#private;
|
|
791
2128
|
static observed: string[];
|
|
@@ -798,47 +2135,130 @@ declare class Pagination extends ParsedElement {
|
|
|
798
2135
|
static template: string;
|
|
799
2136
|
render(): void;
|
|
800
2137
|
/**
|
|
801
|
-
* Moves the pager to a page, a page count, or both,
|
|
802
|
-
*
|
|
803
|
-
*
|
|
804
|
-
*
|
|
2138
|
+
* Moves the pager to a page, a page count, or both, reflects both to their
|
|
2139
|
+
* attributes and repaints the bar once. A key left out keeps its value; a
|
|
2140
|
+
* `null` one becomes 0. A count below one is shown as one empty page.
|
|
2141
|
+
*
|
|
2142
|
+
* The bar is replaced on every repaint. When the focus was inside it, it
|
|
2143
|
+
* moves to the equivalent control of the new bar: the button of the same
|
|
2144
|
+
* page, else the same enabled control, else the current page's button.
|
|
2145
|
+
* @param {{ current?: number|null, total?: number|null }} [state] `current`
|
|
2146
|
+
* is the zero based index of the page shown, `total` the number of pages
|
|
805
2147
|
*/
|
|
806
2148
|
update({ current: toCurrent, total: toTotal }?: {
|
|
807
2149
|
current?: number | null;
|
|
808
2150
|
total?: number | null;
|
|
809
2151
|
}): void;
|
|
2152
|
+
/**
|
|
2153
|
+
* The number of pages, as last written.
|
|
2154
|
+
* @returns {number}
|
|
2155
|
+
*/
|
|
810
2156
|
get total(): number;
|
|
811
|
-
|
|
2157
|
+
/**
|
|
2158
|
+
* Same as `update({ total: value })`.
|
|
2159
|
+
* @param {number|null} value
|
|
2160
|
+
*/
|
|
2161
|
+
set total(value: number | null);
|
|
2162
|
+
/**
|
|
2163
|
+
* The zero based index of the page shown.
|
|
2164
|
+
* @returns {number}
|
|
2165
|
+
*/
|
|
812
2166
|
get current(): number;
|
|
813
|
-
|
|
2167
|
+
/**
|
|
2168
|
+
* Same as `update({ current: value })`.
|
|
2169
|
+
* @param {number|null} value
|
|
2170
|
+
*/
|
|
2171
|
+
set current(value: number | null);
|
|
814
2172
|
}
|
|
815
2173
|
/** Reads the schema declaration into the header and row templates a table renders from. */
|
|
816
2174
|
declare class TableSchemaParser {
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
2175
|
+
/**
|
|
2176
|
+
* Builds a header `<tr>` and a row `<tr data-tpl-each="rows">` from the
|
|
2177
|
+
* `<schema>` child of the slot. The `<schema>` attributes are copied onto
|
|
2178
|
+
* both rows. Each `<column>` becomes a `<th>` and a `<td>` carrying the
|
|
2179
|
+
* column's attributes except `title`, `sorter` and `order`, so a
|
|
2180
|
+
* `data-tpl-*` on a column applies to both cells; the two templates carry
|
|
2181
|
+
* `inHeaders` and `inRows` in their scope, so a column can tell them apart,
|
|
2182
|
+
* as in `data-tpl-if="inRows"`. The header cell holds the `<title>` child
|
|
2183
|
+
* element of the column, else the text of its `title` attribute, wrapped
|
|
2184
|
+
* in a `ful-sorter` when the column declares `sorter` or `order`. The body
|
|
2185
|
+
* cell holds the column's remaining children.
|
|
2186
|
+
*
|
|
2187
|
+
* The column elements are consumed: their `<title>`, `title`, `sorter` and
|
|
2188
|
+
* `order` are removed and their children moved into the cells.
|
|
2189
|
+
* @param {DocumentFragment|Element|undefined} nodeOrFragment the `schema`
|
|
2190
|
+
* slot, undefined when the table has none
|
|
2191
|
+
* @param {ReturnType<ParsedElement['template']>} template the template the
|
|
2192
|
+
* header and row templates derive from, keeping its scope
|
|
2193
|
+
* @returns {{ headersTemplate: ReturnType<ParsedElement['template']>, rowsTemplate: ReturnType<ParsedElement['template']>, sort: { sorter: string|null, order: string|null } | null, length: number }}
|
|
2194
|
+
* `sort` is the initial sort, taken from the first column declaring both
|
|
2195
|
+
* `order` and `sorter` (a column with only `order` gets an arrow but no
|
|
2196
|
+
* initial sort), `null` when none does; `length` is the number of columns
|
|
2197
|
+
* @throws {Error} when the slot is missing or holds no `<schema>`
|
|
2198
|
+
*/
|
|
2199
|
+
static parse(nodeOrFragment: DocumentFragment | Element | undefined, template: ReturnType<ParsedElement['template']>): {
|
|
2200
|
+
headersTemplate: ReturnType<ParsedElement['template']>;
|
|
2201
|
+
rowsTemplate: ReturnType<ParsedElement['template']>;
|
|
820
2202
|
sort: {
|
|
821
2203
|
sorter: string | null;
|
|
822
2204
|
order: string | null;
|
|
823
|
-
};
|
|
2205
|
+
} | null;
|
|
824
2206
|
length: number;
|
|
825
2207
|
};
|
|
826
2208
|
}
|
|
827
2209
|
/** Serves a table's rows from an array held in memory, applying the sort and the paging itself. */
|
|
828
2210
|
declare class InMemoryTableLoader {
|
|
829
2211
|
#private;
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
2212
|
+
/**
|
|
2213
|
+
* @param {any[]} data the rows
|
|
2214
|
+
*/
|
|
2215
|
+
constructor(data: any[]);
|
|
2216
|
+
/**
|
|
2217
|
+
* Sorts a copy of the rows by the `sorter` property, rows missing it last
|
|
2218
|
+
* in either direction and rows with equal values in their original order,
|
|
2219
|
+
* then slices the requested page. The filters are ignored.
|
|
2220
|
+
* @param {TablePageRequest} pageRequest
|
|
2221
|
+
* @param {{ sorter?: string|null, order?: string|null } | null} sortRequest
|
|
2222
|
+
* `order` `desc` sorts descending, anything else ascending; no `sorter`
|
|
2223
|
+
* keeps the original order
|
|
2224
|
+
* @param {Record<string, any>} filterRequest not read
|
|
2225
|
+
* @returns {Promise<TablePageResponse>}
|
|
2226
|
+
*/
|
|
2227
|
+
load(pageRequest: TablePageRequest, sortRequest: {
|
|
2228
|
+
sorter?: string | null;
|
|
2229
|
+
order?: string | null;
|
|
2230
|
+
} | null, filterRequest: Record<string, any>): Promise<TablePageResponse>;
|
|
2231
|
+
/**
|
|
2232
|
+
* Replaces the rows. The table shows them at its next load.
|
|
2233
|
+
* @param {any[]} data
|
|
2234
|
+
*/
|
|
2235
|
+
update(data: any[]): void;
|
|
836
2236
|
}
|
|
837
2237
|
/** Requests one page of rows from a url, passing the page, the sort and the filters to the endpoint. */
|
|
838
2238
|
declare class RemoteTableLoader {
|
|
839
2239
|
#private;
|
|
840
|
-
|
|
841
|
-
|
|
2240
|
+
/**
|
|
2241
|
+
* @param {{ request(method: string, url: string): any }} http the `http-client` component
|
|
2242
|
+
* @param {string} url
|
|
2243
|
+
* @param {string} method
|
|
2244
|
+
* @param {(response: any) => TablePageResponse} [responseMapper] turns the
|
|
2245
|
+
* parsed json body into the page response; the identity when omitted
|
|
2246
|
+
*/
|
|
2247
|
+
constructor(http: {
|
|
2248
|
+
request(method: string, url: string): any;
|
|
2249
|
+
}, url: string, method: string, responseMapper?: (response: any) => TablePageResponse);
|
|
2250
|
+
/**
|
|
2251
|
+
* Sends the query parameters `page`, `size`, `sort` as `sorter,order`
|
|
2252
|
+
* (left out when `sortRequest` is null) and `filters` as a json object of
|
|
2253
|
+
* the filters with a truthy value (left out when there is none), and
|
|
2254
|
+
* answers the json body through the response mapper.
|
|
2255
|
+
* @param {TablePageRequest} pageRequest
|
|
2256
|
+
* @param {TableSortRequest|null} sortRequest
|
|
2257
|
+
* @param {Record<string, any>} filterRequest
|
|
2258
|
+
* @returns {Promise<TablePageResponse>} rejecting with what the client's
|
|
2259
|
+
* `fetchJson()` rejects with
|
|
2260
|
+
*/
|
|
2261
|
+
load(pageRequest: TablePageRequest, sortRequest: TableSortRequest | null, filterRequest: Record<string, any>): Promise<TablePageResponse>;
|
|
842
2262
|
}
|
|
843
2263
|
/**
|
|
844
2264
|
* Builds the table's loader from its attributes: an in-memory one, or the
|
|
@@ -846,98 +2266,449 @@ declare class RemoteTableLoader {
|
|
|
846
2266
|
*
|
|
847
2267
|
* A component registered under the `loader` attribute replaces this one and
|
|
848
2268
|
* must implement `load(pageRequest, sortRequest, filterRequest)`, answering
|
|
849
|
-
* `{ data,
|
|
850
|
-
* index and its size, `sortRequest` the column and direction, and
|
|
2269
|
+
* `{ data, size }`: the rows of the requested page and the total count of
|
|
2270
|
+
* rows. `pageRequest` carries the page index and its size, `sortRequest` the column and direction, and
|
|
851
2271
|
* `filterRequest` the values of the filters in the slot.
|
|
852
2272
|
*/
|
|
853
2273
|
declare class TableLoader {
|
|
854
|
-
|
|
2274
|
+
/**
|
|
2275
|
+
* A table with a `src` attribute gets a `RemoteTableLoader` sending through
|
|
2276
|
+
* the `http-client` component with the `method` attribute or `GET`, and
|
|
2277
|
+
* mapping the response through the component named by `response-mapper`,
|
|
2278
|
+
* if any. A table without `src` gets an empty `InMemoryTableLoader`, which
|
|
2279
|
+
* `withLoader` reaches to give it rows.
|
|
2280
|
+
* @param {Element & { component(name: string): any }} el the table
|
|
2281
|
+
* @param {unknown} [conf] not read
|
|
2282
|
+
* @returns {InMemoryTableLoader | RemoteTableLoader}
|
|
2283
|
+
*/
|
|
2284
|
+
static create(el: Element & {
|
|
2285
|
+
component(name: string): any;
|
|
2286
|
+
}, conf?: unknown): InMemoryTableLoader | RemoteTableLoader;
|
|
855
2287
|
}
|
|
856
|
-
/**
|
|
2288
|
+
/**
|
|
2289
|
+
* A table, `ful-table`, loading its rows a page at a time from a loader, with
|
|
2290
|
+
* a header sorter per sortable column, a `ful-pagination` under it and an
|
|
2291
|
+
* optional filter form.
|
|
2292
|
+
*
|
|
2293
|
+
* The loader is the component named by `loader`, default `loaders:table`
|
|
2294
|
+
* (see `TableLoader`). The `schema` slot declares the columns (see
|
|
2295
|
+
* `TableSchemaParser.parse`); the `filters` slot is wrapped in a `ful-form`,
|
|
2296
|
+
* whose values are the filter request; the `caption`, `footer` and `empty`
|
|
2297
|
+
* slots go in the table's caption, its `<tfoot>` and the panel shown for a
|
|
2298
|
+
* load answering no rows. Attributes starting with `table-` are forwarded,
|
|
2299
|
+
* without the prefix, to the inner `<table>`.
|
|
2300
|
+
*
|
|
2301
|
+
* With `autoload` the first load starts at the upgrade, which does not wait
|
|
2302
|
+
* for it. Without it the table shows an initial panel until `load`,
|
|
2303
|
+
* `reload` or `resetWithFilter` is called.
|
|
2304
|
+
*
|
|
2305
|
+
* Inside the table, and not inside a `ful-table` nested in it, a
|
|
2306
|
+
* `page:requested` loads that page with the current size,
|
|
2307
|
+
* sort and filters; a `sort:requested` loads the current page with the new
|
|
2308
|
+
* sort (none for a `null` order) and, once that load is the one showing, sets
|
|
2309
|
+
* the order of the sorter that asked and clears the others; a `submit:success`
|
|
2310
|
+
* of the filter form loads the first page with the submitted request as the
|
|
2311
|
+
* filters. The first load goes through the filter form too: `reload`, and so
|
|
2312
|
+
* `autoload`, submits it (see `reload`), so a `submit` listener rewriting
|
|
2313
|
+
* `detail.request` shapes every load alike. The filters a page, a sort or a size change carries are those of
|
|
2314
|
+
* the last load asked for, whether it is still running, loaded or failed, so
|
|
2315
|
+
* they are the ones the filter form shows. The loads these start, and the autoload, are not awaited by
|
|
2316
|
+
* anything: a failure shows the error panel and its rejection is unhandled.
|
|
2317
|
+
*/
|
|
857
2318
|
declare class Table extends ParsedElement {
|
|
858
2319
|
#private;
|
|
2320
|
+
/** Read once at the upgrade. */
|
|
859
2321
|
static attributes: string[];
|
|
860
|
-
/**
|
|
861
|
-
* The page size stays live: a rows-per-page control is a normal thing to
|
|
862
|
-
* put next to a table, and the size is the one piece of the request an
|
|
863
|
-
* author changes after the table is up. The rest of the request is the
|
|
864
|
-
* table's own state, moved by the pager, the sorters and the filter form.
|
|
865
|
-
*/
|
|
2322
|
+
/** These stay live after the upgrade: see `pageSize`, `src` and `method`. */
|
|
866
2323
|
static observed: string[];
|
|
867
2324
|
static slots: boolean;
|
|
868
2325
|
static config: {
|
|
869
2326
|
searchIcon: string;
|
|
2327
|
+
emptyIcon: string;
|
|
870
2328
|
};
|
|
871
2329
|
static template: string;
|
|
872
2330
|
static templates: {
|
|
873
2331
|
row: string;
|
|
874
2332
|
};
|
|
875
|
-
/**
|
|
2333
|
+
/**
|
|
2334
|
+
* How many rows a page asks the loader for: the size the next load will
|
|
2335
|
+
* carry. Ten before the render.
|
|
2336
|
+
* @returns {number}
|
|
2337
|
+
*/
|
|
876
2338
|
get pageSize(): number;
|
|
877
2339
|
/**
|
|
878
|
-
* Changes the page size and reloads from the first page, the
|
|
879
|
-
*
|
|
880
|
-
*
|
|
881
|
-
*
|
|
2340
|
+
* Changes the page size and reloads from the first page, keeping the sort
|
|
2341
|
+
* and the filters. A table that has not loaded yet only records it:
|
|
2342
|
+
* writing the size is not a request to start loading, which is what
|
|
2343
|
+
* `autoload` and `reload()` are for. A write that does not change the size
|
|
2344
|
+
* does nothing. A write made before the render is replaced by the declared
|
|
2345
|
+
* `page-size` when the table renders.
|
|
882
2346
|
*
|
|
883
|
-
*
|
|
884
|
-
*
|
|
2347
|
+
* The reload is not awaited: a failure shows the error panel and its
|
|
2348
|
+
* rejection is unhandled.
|
|
2349
|
+
* @param {number|string|null|undefined} value a number or a string of
|
|
2350
|
+
* one, such as a select's value; absent or null is the default of ten,
|
|
2351
|
+
* so removing the attribute restores it, and a value that is not a
|
|
2352
|
+
* number is ignored
|
|
2353
|
+
*/
|
|
2354
|
+
set pageSize(value: number | string | null | undefined);
|
|
2355
|
+
/**
|
|
2356
|
+
* The url the loader asks for rows, reflected as the `src` attribute.
|
|
2357
|
+
* @returns {string|null}
|
|
2358
|
+
*/
|
|
2359
|
+
get src(): string | null;
|
|
2360
|
+
/**
|
|
2361
|
+
* Points the table at another url: the loader is built again through its
|
|
2362
|
+
* component's `create`, as at the render, and the table reloads from the
|
|
2363
|
+
* first page, keeping the size, the sort and the filters. A table that has
|
|
2364
|
+
* not loaded yet only rebuilds its loader. A write that does not change the
|
|
2365
|
+
* url does nothing.
|
|
2366
|
+
*
|
|
2367
|
+
* The reload is not awaited: a failure shows the error panel and its
|
|
2368
|
+
* rejection is unhandled.
|
|
2369
|
+
* @param {string|null|undefined} value null or undefined removes the url,
|
|
2370
|
+
* which the default loader answers with an empty in-memory loader
|
|
2371
|
+
*/
|
|
2372
|
+
set src(value: string | null | undefined);
|
|
2373
|
+
/**
|
|
2374
|
+
* The http method the default loader sends with, reflected as the `method`
|
|
2375
|
+
* attribute; `GET` when absent.
|
|
2376
|
+
* @returns {string|null}
|
|
2377
|
+
*/
|
|
2378
|
+
get method(): string | null;
|
|
2379
|
+
/**
|
|
2380
|
+
* Changes the http method the way `src` changes the url: the loader is
|
|
2381
|
+
* built again and the table reloads from the first page.
|
|
2382
|
+
* @param {string|null|undefined} value
|
|
2383
|
+
*/
|
|
2384
|
+
set method(value: string | null | undefined);
|
|
2385
|
+
/**
|
|
2386
|
+
* Writes `src` and `method` together and loads once: the loader is built
|
|
2387
|
+
* again for the pair when either changed, the page going back to the first
|
|
2388
|
+
* one as a single write of either does, and the table then reloads as
|
|
2389
|
+
* `reload()` does, whether or not they changed. Unlike a write of either,
|
|
2390
|
+
* it loads a table that has not loaded yet.
|
|
2391
|
+
* @param {{ src?: string|null, method?: string|null }} attributes a name
|
|
2392
|
+
* left out keeps its value, null removes the attribute
|
|
2393
|
+
* @returns {Promise<void>} as `load`
|
|
2394
|
+
*/
|
|
2395
|
+
reconfigure(attributes: {
|
|
2396
|
+
src?: string | null;
|
|
2397
|
+
method?: string | null;
|
|
2398
|
+
}): Promise<void>;
|
|
2399
|
+
/**
|
|
2400
|
+
* @param {{ slots: Record<string, DocumentFragment> }} c
|
|
2401
|
+
* @returns {Promise<void>}
|
|
2402
|
+
* @throws {Error} when the `schema` slot is missing or holds no `<schema>`
|
|
885
2403
|
*/
|
|
886
|
-
set pageSize(value: number);
|
|
887
2404
|
render({ slots }: {
|
|
888
|
-
slots:
|
|
2405
|
+
slots: Record<string, DocumentFragment>;
|
|
889
2406
|
}): Promise<void>;
|
|
2407
|
+
/**
|
|
2408
|
+
* Loads the last request that loaded, or, before any has, the first page
|
|
2409
|
+
* with the declared size and sort. A size written through `pageSize` since
|
|
2410
|
+
* then replaces the page with the first one at that size.
|
|
2411
|
+
*
|
|
2412
|
+
* Before any load has loaded, a table with a `filters` slot submits its
|
|
2413
|
+
* filter form instead, so the first request goes through the same
|
|
2414
|
+
* `submit` listeners as the later ones, and the load its `submit:success`
|
|
2415
|
+
* starts is the one awaited. A filter submit that is cancelled, fails or
|
|
2416
|
+
* is dropped for one in flight loads nothing, and the promise resolves.
|
|
2417
|
+
* @returns {Promise<void>} as `load`
|
|
2418
|
+
*/
|
|
890
2419
|
reload(): Promise<void>;
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
2420
|
+
/**
|
|
2421
|
+
* Asks the loader for a page and shows it. Its filters are, from now on,
|
|
2422
|
+
* the ones a page, a sort or a size change carries, even while it runs
|
|
2423
|
+
* or once it failed.
|
|
2424
|
+
*
|
|
2425
|
+
* While the load runs the table carries `aria-busy="true"`, and the rows
|
|
2426
|
+
* already shown stay; the spinner panel shows only when there are none.
|
|
2427
|
+
* When the loader answers, the rows and the pager are replaced, the empty
|
|
2428
|
+
* panel shows for an answer with no rows (the `empty` slot rendered with
|
|
2429
|
+
* `schema`, `pageRequest`, `filterRequest` and `pageResponse` in scope),
|
|
2430
|
+
* the request becomes the one
|
|
2431
|
+
* `reload` repeats; once the elements of the rows and of the empty panel
|
|
2432
|
+
* have rendered, `aria-busy` is removed and `load:success` is
|
|
2433
|
+
* dispatched (bubbling, not cancelable) with `detail` set to
|
|
2434
|
+
* `{ pageRequest, sortRequest, filterRequest, response }`. A page beyond
|
|
2435
|
+
* the last one the answer reports is not shown: the last page is loaded
|
|
2436
|
+
* instead, and the returned promise settles with that load.
|
|
2437
|
+
*
|
|
2438
|
+
* When the loader rejects, the rows are removed, the error panel shows the
|
|
2439
|
+
* `reason` of each of the error's `problems`, one per line, or the error as text,
|
|
2440
|
+
* `aria-busy` is removed, `load:failure` is dispatched (bubbling, not
|
|
2441
|
+
* cancelable) with `detail` set to
|
|
2442
|
+
* `{ pageRequest, sortRequest, filterRequest, exception }`, and the
|
|
2443
|
+
* returned promise rejects with the same error.
|
|
2444
|
+
*
|
|
2445
|
+
* A load started after this one supersedes it: when this one's answer or
|
|
2446
|
+
* failure arrives it changes nothing, dispatches nothing and resolves;
|
|
2447
|
+
* superseded while its rows render, it leaves them to the newer load and
|
|
2448
|
+
* dispatches nothing.
|
|
2449
|
+
* @param {TablePageRequest} pageRequest
|
|
2450
|
+
* @param {TableSortRequest|null} sortRequest
|
|
2451
|
+
* @param {Record<string, any>} filterRequest
|
|
2452
|
+
* @returns {Promise<void>}
|
|
2453
|
+
* @throws what the loader rejects with, unless a newer load superseded this one
|
|
2454
|
+
*/
|
|
2455
|
+
load(pageRequest: TablePageRequest, sortRequest: TableSortRequest | null, filterRequest: Record<string, any>): Promise<void>;
|
|
2456
|
+
/**
|
|
2457
|
+
* Hands the loader to the callback, for runtime reconfigurations, such as
|
|
2458
|
+
* `update(rows)` on the in-memory loader. The loader exists from the
|
|
2459
|
+
* render on. Nothing is reloaded.
|
|
2460
|
+
* @template T
|
|
2461
|
+
* @param {(loader: any) => T | Promise<T>} fn
|
|
2462
|
+
* @returns {Promise<T>} what `fn` returns or resolves to
|
|
2463
|
+
*/
|
|
2464
|
+
withLoader<T>(fn: (loader: any) => T | Promise<T>): Promise<T>;
|
|
2465
|
+
/**
|
|
2466
|
+
* Loads the first page with the given filters, keeping the size and the sort.
|
|
2467
|
+
* @param {Record<string, any>} filterRequest
|
|
2468
|
+
* @returns {Promise<void>} as `load`
|
|
2469
|
+
*/
|
|
2470
|
+
resetWithFilter(filterRequest: Record<string, any>): Promise<void>;
|
|
895
2471
|
}
|
|
2472
|
+
/**
|
|
2473
|
+
* An invoker button paired with the `ul[popover][role=menu]` that follows it:
|
|
2474
|
+
* the chrome behind every filter's operator, sensitivity and boolean value.
|
|
2475
|
+
*
|
|
2476
|
+
* It fills the menu from a vocabulary, wires it the first time more than one
|
|
2477
|
+
* choice survives the whitelist, pins the button to a static glyph when a
|
|
2478
|
+
* single one does, takes the shared menu keyboard protocol, and keeps the
|
|
2479
|
+
* button's value, glyph and aria-label in step. A pick that changes the value
|
|
2480
|
+
* calls back; the host decides what that means.
|
|
2481
|
+
*
|
|
2482
|
+
* The button's `value` attribute is the store, as it is for a native control:
|
|
2483
|
+
* the menu protocol finds the current item by it, and nothing mirrors it.
|
|
2484
|
+
*/
|
|
2485
|
+
declare class ChoiceButton {
|
|
2486
|
+
#private;
|
|
2487
|
+
/**
|
|
2488
|
+
* The declared choices narrowed to a vocabulary, in the declared order.
|
|
2489
|
+
* When none of them is in the vocabulary, or none is declared, the answer
|
|
2490
|
+
* is a copy of the whole vocabulary.
|
|
2491
|
+
* @param {string[] | null | undefined} declared
|
|
2492
|
+
* @param {string[]} vocabulary
|
|
2493
|
+
* @returns {string[]}
|
|
2494
|
+
*/
|
|
2495
|
+
static narrow(declared: string[] | null | undefined, vocabulary: string[]): string[];
|
|
2496
|
+
/**
|
|
2497
|
+
* Takes the button's next sibling as its menu and listens for picks on it.
|
|
2498
|
+
* The menu is neither filled nor wired until `allowed` is first written.
|
|
2499
|
+
*
|
|
2500
|
+
* A click on an item, while `interactive()` answers true, sets the value,
|
|
2501
|
+
* hides the menu and, when the value changed, calls `onPick`.
|
|
2502
|
+
* @param {HTMLElement} button the invoker, whose next sibling is its menu
|
|
2503
|
+
* @param {{vocabulary: string[], glyphs?: Record<string,string>, labelFor?: (v: string) => string,
|
|
2504
|
+
* display?: ((v: string) => string)|null, interactive?: () => boolean, onPick?: (v: string) => void}} conf
|
|
2505
|
+
* `vocabulary` lists every choice; `glyphs` maps a choice to its compact
|
|
2506
|
+
* glyph; `labelFor` answers the localized word, used as the button's
|
|
2507
|
+
* `aria-label` and beside the glyph in the menu (the choice itself by
|
|
2508
|
+
* default); `display` answers the button's text (by default the glyph,
|
|
2509
|
+
* or the choice where it has none); `interactive` is asked before a
|
|
2510
|
+
* pick is taken; `onPick` receives a pick that changed the value
|
|
2511
|
+
*/
|
|
2512
|
+
constructor(button: HTMLElement, { vocabulary, glyphs, labelFor, display, interactive, onPick }: {
|
|
2513
|
+
vocabulary: string[];
|
|
2514
|
+
glyphs?: Record<string, string>;
|
|
2515
|
+
labelFor?: (v: string) => string;
|
|
2516
|
+
display?: ((v: string) => string) | null;
|
|
2517
|
+
interactive?: () => boolean;
|
|
2518
|
+
onPick?: (v: string) => void;
|
|
2519
|
+
});
|
|
2520
|
+
/**
|
|
2521
|
+
* The choices the menu offers. Writing it narrows the declared set with
|
|
2522
|
+
* `narrow`, refills the menu, wires the popover and the menu keyboard the
|
|
2523
|
+
* first time more than one choice is allowed, and updates the button's
|
|
2524
|
+
* disabled state and popup attributes. When one choice is left the button
|
|
2525
|
+
* is pinned and the value is set to it.
|
|
2526
|
+
* @type {string[]}
|
|
2527
|
+
*/
|
|
2528
|
+
get allowed(): string[];
|
|
2529
|
+
set allowed(declared: string[]);
|
|
2530
|
+
/**
|
|
2531
|
+
* The choice when the menu allows it, otherwise the first allowed one.
|
|
2532
|
+
* @param {string|null} choice
|
|
2533
|
+
* @returns {string}
|
|
2534
|
+
*/
|
|
2535
|
+
preferring(choice: string | null): string;
|
|
2536
|
+
/**
|
|
2537
|
+
* Whether fewer than two choices are allowed. A pinned button is disabled,
|
|
2538
|
+
* opens no menu and shows the single choice as its value.
|
|
2539
|
+
* @returns {boolean}
|
|
2540
|
+
*/
|
|
2541
|
+
get pinned(): boolean;
|
|
2542
|
+
/**
|
|
2543
|
+
* The host's fixed claim: hides the button with the `hidden` attribute
|
|
2544
|
+
* while `value` keeps answering.
|
|
2545
|
+
* @param {boolean} fixed
|
|
2546
|
+
*/
|
|
2547
|
+
set fixed(fixed: boolean);
|
|
2548
|
+
/**
|
|
2549
|
+
* The current choice, stored as the button's `value` attribute, where the
|
|
2550
|
+
* menu keyboard also finds it. Writing it sets the button's text from
|
|
2551
|
+
* `display`, its `aria-label` from `labelFor`, and `aria-checked` on the
|
|
2552
|
+
* menu item carrying it. It does not call `onPick`.
|
|
2553
|
+
* @type {string | null}
|
|
2554
|
+
*/
|
|
2555
|
+
get value(): string | null;
|
|
2556
|
+
set value(choice: string | null);
|
|
2557
|
+
/**
|
|
2558
|
+
* The host's disabled claim. The button is disabled while either the claim
|
|
2559
|
+
* or the pin holds, so lifting one does not enable it while the other holds.
|
|
2560
|
+
* @param {boolean} claimed
|
|
2561
|
+
*/
|
|
2562
|
+
set claimed(claimed: boolean);
|
|
2563
|
+
}
|
|
2564
|
+
export type FilterCriterion = {
|
|
2565
|
+
label: string | null;
|
|
2566
|
+
operator: string | null;
|
|
2567
|
+
operands: string[];
|
|
2568
|
+
};
|
|
896
2569
|
/**
|
|
897
2570
|
* The shared shape of every operator-and-operands filter: an operator menu, one
|
|
898
2571
|
* or two operands of the type the subclass declares, and a tuple that mirrors
|
|
899
2572
|
* the data-jpa compare annotations.
|
|
2573
|
+
*
|
|
2574
|
+
* The value is `[operator, operand]`, or `[operator, from, to]` for BETWEEN,
|
|
2575
|
+
* the only operator that shows the second operand. The `operators` attribute
|
|
2576
|
+
* whitelists the menu; the `operator` attribute fixes the operator for the
|
|
2577
|
+
* element's life instead, hiding its button, and every tuple then carries it.
|
|
2578
|
+
* Declaring both warns and the singular wins; a fixed name outside the
|
|
2579
|
+
* vocabulary warns and fixes the default operator.
|
|
2580
|
+
*
|
|
2581
|
+
* Both operands mirror the disabled and readonly claims, and readonly also
|
|
2582
|
+
* refuses the clicks that would open the operator menu. The change event fires
|
|
2583
|
+
* when either operand changes or a different operator is picked.
|
|
900
2584
|
*/
|
|
901
2585
|
declare class CompareFilter extends Input {
|
|
2586
|
+
#private;
|
|
902
2587
|
static observed: string[];
|
|
903
|
-
static
|
|
904
|
-
static DEFAULT_OPERATOR: string;
|
|
2588
|
+
static attributes: string[];
|
|
905
2589
|
static template: string;
|
|
906
2590
|
_operator: any;
|
|
907
2591
|
_container: any;
|
|
908
2592
|
_value1: any;
|
|
909
2593
|
_value2: any;
|
|
910
2594
|
_build(conf: any): {
|
|
911
|
-
fragment:
|
|
2595
|
+
fragment: DocumentFragment;
|
|
912
2596
|
control: any;
|
|
913
|
-
error:
|
|
914
|
-
label:
|
|
2597
|
+
error: Element | null;
|
|
2598
|
+
label: HTMLLabelElement | null;
|
|
915
2599
|
freeze: any;
|
|
916
2600
|
also: any[];
|
|
917
2601
|
};
|
|
918
2602
|
_showDefaultOperator(): void;
|
|
2603
|
+
/**
|
|
2604
|
+
* Restores the declared `value` tuple, operator included, as a field reset
|
|
2605
|
+
* does. Without a `value` attribute it empties the operands and also shows
|
|
2606
|
+
* the default operator again, or the first whitelisted one where the
|
|
2607
|
+
* default is not allowed.
|
|
2608
|
+
*/
|
|
919
2609
|
formResetCallback(): void;
|
|
2610
|
+
/**
|
|
2611
|
+
* The native input type both operands render with.
|
|
2612
|
+
* @returns {string}
|
|
2613
|
+
*/
|
|
920
2614
|
_type(): string;
|
|
921
|
-
|
|
922
|
-
|
|
2615
|
+
/**
|
|
2616
|
+
* Converts an operand from its input's value to the form the tuple carries.
|
|
2617
|
+
* @param {string} v
|
|
2618
|
+
* @returns {string|null}
|
|
2619
|
+
*/
|
|
2620
|
+
_serialize(v: string): string | null;
|
|
2621
|
+
/**
|
|
2622
|
+
* Converts an operand from the tuple to the value its input shows.
|
|
2623
|
+
* @param {string} v
|
|
2624
|
+
* @returns {string}
|
|
2625
|
+
*/
|
|
2626
|
+
_deserialize(v: string): string;
|
|
2627
|
+
/**
|
|
2628
|
+
* The operator shown on render and after a valueless reset, when the whitelist allows it.
|
|
2629
|
+
* @returns {string}
|
|
2630
|
+
*/
|
|
923
2631
|
_defaultOperator(): string;
|
|
2632
|
+
/**
|
|
2633
|
+
* Every operator the filter knows, which `operators` narrows.
|
|
2634
|
+
* @returns {string[]}
|
|
2635
|
+
*/
|
|
924
2636
|
_vocabulary(): string[];
|
|
925
2637
|
_declaredOperators: any;
|
|
926
|
-
|
|
927
|
-
|
|
2638
|
+
/**
|
|
2639
|
+
* The operators the menu offers, narrowed to the vocabulary: an empty list,
|
|
2640
|
+
* or one where no name is known, offers all of it. A single operator pins
|
|
2641
|
+
* the button, and an assigned tuple then carries that operator whatever it
|
|
2642
|
+
* names. When the operator shown leaves the list, the first listed one is
|
|
2643
|
+
* shown. An assignment made before the upgrade is held narrowed and
|
|
2644
|
+
* answered back until the render, when the `operators` attribute is applied
|
|
2645
|
+
* over it, an absent attribute meaning the whole vocabulary. Assignments are
|
|
2646
|
+
* ignored while the `operator` attribute fixes the operator.
|
|
2647
|
+
* @returns {string[]|undefined} undefined before the upgrade when nothing was assigned
|
|
2648
|
+
*/
|
|
2649
|
+
get operators(): string[] | undefined;
|
|
2650
|
+
/** @param {string[]|null} declared */
|
|
2651
|
+
set operators(declared: string[] | null);
|
|
2652
|
+
/**
|
|
2653
|
+
* The filter's tuple, `[operator, operand]` or `[operator, from, to]` for
|
|
2654
|
+
* BETWEEN, each operand converted by `_serialize` (an ISO instant for the
|
|
2655
|
+
* instant filter). Null while any operand the operator uses is empty.
|
|
2656
|
+
* Before the render it answers the tuple last written, or the `value`
|
|
2657
|
+
* attribute, as the rendered filter would show it.
|
|
2658
|
+
* @returns {any[]|null}
|
|
2659
|
+
*/
|
|
928
2660
|
get value(): any[] | null;
|
|
929
|
-
|
|
2661
|
+
/**
|
|
2662
|
+
* Shows a tuple: the operator it names, or the first allowed one where the
|
|
2663
|
+
* whitelist, a pin or a fixed operator does not allow it, and its operands, an operand missing from a shorter tuple
|
|
2664
|
+
* leaving its input empty. Null or undefined empties both operands and
|
|
2665
|
+
* keeps the operator. Before the render the tuple is held for the render
|
|
2666
|
+
* to apply, over the `value` attribute, which it leaves alone.
|
|
2667
|
+
* @param {any[]|null|undefined} v
|
|
2668
|
+
*/
|
|
2669
|
+
set value(v: any[] | null | undefined);
|
|
2670
|
+
/**
|
|
2671
|
+
* The tuple `_tuple` answers once `_applyTuple(v)` has shown `v`, read
|
|
2672
|
+
* from the declared `operator` and `operators` in place of the menu.
|
|
2673
|
+
* @param {any[]|null|undefined} v
|
|
2674
|
+
* @returns {any[]|null}
|
|
2675
|
+
*/
|
|
2676
|
+
_shownTuple(v: any[] | null | undefined): any[] | null;
|
|
930
2677
|
_tuple(): any[] | null;
|
|
931
2678
|
_applyTuple(v: any): void;
|
|
932
2679
|
_showOperator(operator: any): void;
|
|
933
|
-
/** only
|
|
2680
|
+
/** Shows the second operand only while the operator is BETWEEN. */
|
|
934
2681
|
_syncBetween(): void;
|
|
2682
|
+
/**
|
|
2683
|
+
* The operator and the operands the operator uses, as their inputs show
|
|
2684
|
+
* them rather than as serialized: a date filter describes what is in its
|
|
2685
|
+
* control, not the ISO string it sends. Null while every one of those
|
|
2686
|
+
* operands is empty, so a BETWEEN with one bound answers that bound while
|
|
2687
|
+
* its value is still null, and before the filter has rendered.
|
|
2688
|
+
* @returns {FilterCriterion|null}
|
|
2689
|
+
*/
|
|
2690
|
+
get criterion(): FilterCriterion | null;
|
|
2691
|
+
/**
|
|
2692
|
+
* The field's own disabled claim. Setting it disables both operands and
|
|
2693
|
+
* every menu button the filter composes; a button pinned to one choice
|
|
2694
|
+
* stays disabled when the claim is lifted.
|
|
2695
|
+
* @returns {boolean}
|
|
2696
|
+
*/
|
|
935
2697
|
get disabled(): boolean;
|
|
2698
|
+
/** @param {boolean} d */
|
|
936
2699
|
set disabled(d: boolean);
|
|
937
|
-
/**
|
|
938
|
-
|
|
2700
|
+
/**
|
|
2701
|
+
* The menu buttons the filter composes, which the disabled claim reaches. A
|
|
2702
|
+
* subclass adding a menu appends its own to the base's.
|
|
2703
|
+
* @returns {ChoiceButton[]}
|
|
2704
|
+
*/
|
|
2705
|
+
_choices(): ChoiceButton[];
|
|
939
2706
|
}
|
|
940
|
-
/**
|
|
2707
|
+
/**
|
|
2708
|
+
* The compare filter over ISO instants, defaulting to LTE. The operands are
|
|
2709
|
+
* shown as local date and time in the page's timezone and carried in the tuple
|
|
2710
|
+
* as UTC ISO instants.
|
|
2711
|
+
*/
|
|
941
2712
|
declare class InstantFilter extends CompareFilter {
|
|
942
2713
|
_defaultOperator(): string;
|
|
943
2714
|
_type(): string;
|
|
@@ -952,35 +2723,93 @@ declare class LocalDateFilter extends CompareFilter {
|
|
|
952
2723
|
declare class NumberFilter extends CompareFilter {
|
|
953
2724
|
_type(): string;
|
|
954
2725
|
}
|
|
955
|
-
/**
|
|
2726
|
+
/**
|
|
2727
|
+
* The compare filter over text, defaulting to CONTAINS and adding CONTAINS,
|
|
2728
|
+
* STARTS_WITH and ENDS_WITH to the compare operators.
|
|
2729
|
+
*
|
|
2730
|
+
* Its tuple carries a case sensitivity after the operator, `[operator,
|
|
2731
|
+
* sensitivity, operand]` or `[operator, sensitivity, from, to]`, the
|
|
2732
|
+
* sensitivity being IGNORE_CASE (the default) or CASE_SENSITIVE and switched
|
|
2733
|
+
* through a second menu. The `sensitivities` attribute whitelists that menu and
|
|
2734
|
+
* `sensitivity` fixes one mode, with the same rules and warnings as
|
|
2735
|
+
* `operators` and `operator`.
|
|
2736
|
+
*/
|
|
956
2737
|
declare class TextFilter extends CompareFilter {
|
|
957
2738
|
static observed: string[];
|
|
2739
|
+
static attributes: string[];
|
|
958
2740
|
static template: string;
|
|
959
2741
|
_defaultOperator(): string;
|
|
960
2742
|
_vocabulary(): string[];
|
|
961
2743
|
_sensitivityButton: any;
|
|
962
2744
|
_build(conf: any): {
|
|
963
|
-
fragment:
|
|
2745
|
+
fragment: DocumentFragment;
|
|
964
2746
|
control: any;
|
|
965
|
-
error:
|
|
966
|
-
label:
|
|
2747
|
+
error: Element | null;
|
|
2748
|
+
label: HTMLLabelElement | null;
|
|
967
2749
|
freeze: any;
|
|
968
2750
|
also: any[];
|
|
969
2751
|
};
|
|
970
2752
|
_choices(): any[];
|
|
971
2753
|
get _sensitivity(): any;
|
|
972
2754
|
_declaredSensitivities: any;
|
|
973
|
-
|
|
974
|
-
|
|
2755
|
+
/**
|
|
2756
|
+
* The sensitivities the menu offers, narrowed to IGNORE_CASE and
|
|
2757
|
+
* CASE_SENSITIVE: an empty list, or one where no name is known, offers both.
|
|
2758
|
+
* When the mode shown leaves the list, the first listed one is shown. Held
|
|
2759
|
+
* before the upgrade and ignored under a fixed `sensitivity`, as `operators` is.
|
|
2760
|
+
* @returns {string[]|undefined} undefined before the upgrade when nothing was assigned
|
|
2761
|
+
*/
|
|
2762
|
+
get sensitivities(): string[] | undefined;
|
|
2763
|
+
/** @param {string[]|null} declared */
|
|
2764
|
+
set sensitivities(declared: string[] | null);
|
|
2765
|
+
/**
|
|
2766
|
+
* The tuple with the sensitivity after the operator, `[operator,
|
|
2767
|
+
* sensitivity, ...operands]`. Null while any operand the operator uses is
|
|
2768
|
+
* empty. Before the render it answers the tuple last written, or the
|
|
2769
|
+
* `value` attribute, as the rendered filter would show it.
|
|
2770
|
+
* @returns {any[]|null}
|
|
2771
|
+
*/
|
|
975
2772
|
get value(): any[] | null;
|
|
976
|
-
|
|
2773
|
+
/**
|
|
2774
|
+
* Shows a tuple as the compare filter does, reading the sensitivity at
|
|
2775
|
+
* index 1. A sensitivity the whitelist does not allow leaves the current
|
|
2776
|
+
* one in place. Null or undefined empties the operands and keeps the
|
|
2777
|
+
* operator and the sensitivity. Before the render the tuple is held, as
|
|
2778
|
+
* on the compare filters.
|
|
2779
|
+
* @param {any[]|null|undefined} v
|
|
2780
|
+
*/
|
|
2781
|
+
set value(v: any[] | null | undefined);
|
|
2782
|
+
/**
|
|
2783
|
+
* Restores the declared `value` tuple, sensitivity included. Without a
|
|
2784
|
+
* `value` attribute it also shows the default operator and IGNORE_CASE
|
|
2785
|
+
* again, or the first whitelisted mode where IGNORE_CASE is not allowed.
|
|
2786
|
+
*/
|
|
977
2787
|
formResetCallback(): void;
|
|
978
2788
|
}
|
|
979
|
-
/**
|
|
2789
|
+
/**
|
|
2790
|
+
* The boolean filter: an EQ or NEQ operator menu and a value menu of any, yes
|
|
2791
|
+
* and no, the value button showing the localized word.
|
|
2792
|
+
*
|
|
2793
|
+
* The value is `[operator, 'true']` or `[operator, 'false']`, null while the
|
|
2794
|
+
* value menu is on any. The `operators` attribute whitelists the operator menu
|
|
2795
|
+
* as on the compare filters. The disabled claim reaches the value button and
|
|
2796
|
+
* both menus, and readonly refuses the clicks that would open them. The
|
|
2797
|
+
* required and readonly claims reflect on the host only: no `aria-required` or
|
|
2798
|
+
* `aria-readonly` is written, since the value button's role accepts neither.
|
|
2799
|
+
*/
|
|
980
2800
|
declare class BooleanFilter extends Field {
|
|
981
2801
|
static observed: string[];
|
|
982
2802
|
static slots: boolean;
|
|
2803
|
+
/**
|
|
2804
|
+
* The operators the filter knows, which `operators` narrows.
|
|
2805
|
+
* @type {string[]}
|
|
2806
|
+
*/
|
|
983
2807
|
static OPERATORS: string[];
|
|
2808
|
+
/**
|
|
2809
|
+
* The operator shown on render and after a valueless reset, or the first
|
|
2810
|
+
* whitelisted one where the whitelist excludes it.
|
|
2811
|
+
* @type {string}
|
|
2812
|
+
*/
|
|
984
2813
|
static DEFAULT_OPERATOR: string;
|
|
985
2814
|
static template: string;
|
|
986
2815
|
_operator: any;
|
|
@@ -989,212 +2818,880 @@ declare class BooleanFilter extends Field {
|
|
|
989
2818
|
_build({ slots }: {
|
|
990
2819
|
slots: any;
|
|
991
2820
|
}): {
|
|
992
|
-
fragment:
|
|
993
|
-
control:
|
|
994
|
-
error:
|
|
995
|
-
label:
|
|
2821
|
+
fragment: DocumentFragment;
|
|
2822
|
+
control: HTMLElement;
|
|
2823
|
+
error: Element | null;
|
|
2824
|
+
label: HTMLLabelElement | null;
|
|
996
2825
|
announces: null;
|
|
997
2826
|
freeze: any;
|
|
998
2827
|
};
|
|
999
2828
|
_declaredOperators: any;
|
|
1000
|
-
|
|
1001
|
-
|
|
2829
|
+
/**
|
|
2830
|
+
* The operators the menu offers, narrowed to EQ and NEQ: an empty list, or
|
|
2831
|
+
* one where no name is known, offers both, and a single one pins the
|
|
2832
|
+
* button. When the operator shown leaves the list, the first listed one is
|
|
2833
|
+
* shown. Held before the upgrade and replaced by the `operators` attribute
|
|
2834
|
+
* at the render, as on the compare filters.
|
|
2835
|
+
* @returns {string[]|undefined} undefined before the upgrade when nothing was assigned
|
|
2836
|
+
*/
|
|
2837
|
+
get operators(): string[] | undefined;
|
|
2838
|
+
/** @param {string[]|null} declared */
|
|
2839
|
+
set operators(declared: string[] | null);
|
|
2840
|
+
/** @returns {string[]} */
|
|
1002
2841
|
_vocabulary(): string[];
|
|
1003
|
-
|
|
1004
|
-
|
|
2842
|
+
/**
|
|
2843
|
+
* `[operator, token]`, the token being 'true' or 'false'; null while the
|
|
2844
|
+
* value menu is on any. Before the render it answers the tuple last
|
|
2845
|
+
* written, or the `value` attribute, as the rendered filter would show it.
|
|
2846
|
+
* @returns {string[]|null}
|
|
2847
|
+
*/
|
|
2848
|
+
get value(): string[] | null;
|
|
2849
|
+
/**
|
|
2850
|
+
* Shows a tuple: its operator, or the first allowed one where the whitelist
|
|
2851
|
+
* does not allow it, and its token, a missing token meaning any. Null or undefined sets the value menu
|
|
2852
|
+
* back to any and keeps the operator. Before the render the tuple is held,
|
|
2853
|
+
* as on the compare filters.
|
|
2854
|
+
* @param {any[]|null|undefined} v
|
|
2855
|
+
*/
|
|
2856
|
+
set value(v: any[] | null | undefined);
|
|
2857
|
+
/**
|
|
2858
|
+
* Restores the declared `value` tuple. Without a `value` attribute it sets
|
|
2859
|
+
* the value menu back to any and also shows the default operator again.
|
|
2860
|
+
*/
|
|
2861
|
+
formResetCallback(): void;
|
|
2862
|
+
/**
|
|
2863
|
+
* The operator and the localized word the value menu shows, not the token.
|
|
2864
|
+
* Null while the value menu is on any, and before the filter has rendered.
|
|
2865
|
+
* @returns {FilterCriterion|null}
|
|
2866
|
+
*/
|
|
2867
|
+
get criterion(): FilterCriterion | null;
|
|
2868
|
+
/**
|
|
2869
|
+
* The field's own disabled claim. Setting it disables the value button and
|
|
2870
|
+
* both menu buttons; an operator button pinned to one choice stays disabled
|
|
2871
|
+
* when the claim is lifted.
|
|
2872
|
+
* @returns {boolean}
|
|
2873
|
+
*/
|
|
1005
2874
|
get disabled(): boolean;
|
|
2875
|
+
/** @param {boolean} d */
|
|
1006
2876
|
set disabled(d: boolean);
|
|
1007
2877
|
}
|
|
1008
|
-
/**
|
|
2878
|
+
/**
|
|
2879
|
+
* Set membership over a select's vocabulary, answering for both of data-jpa's
|
|
2880
|
+
* set annotations: InEnum and InList take the same bare array of values and no
|
|
2881
|
+
* operator, differing only in what the server converts them to. A declared
|
|
2882
|
+
* `operator` attribute is sent in front of the keys instead, for a server field
|
|
2883
|
+
* that reads the set through a compare.
|
|
2884
|
+
*/
|
|
2885
|
+
declare class InFilter extends Select {
|
|
2886
|
+
#private;
|
|
2887
|
+
static attributes: string[];
|
|
2888
|
+
/**
|
|
2889
|
+
* The chosen keys as an array, a single choice included, led by the
|
|
2890
|
+
* declared `operator` when there is one. Null while nothing is chosen, so
|
|
2891
|
+
* that a table drops the filter instead of sending an empty set that
|
|
2892
|
+
* matches nothing. Before the render it answers the keys the select answers
|
|
2893
|
+
* then.
|
|
2894
|
+
* @returns {any[]|null}
|
|
2895
|
+
*/
|
|
2896
|
+
get value(): any[] | null;
|
|
2897
|
+
/**
|
|
2898
|
+
* Selects the keys of an array or a single bare key; a leading element equal
|
|
2899
|
+
* to the declared `operator` is dropped first, so the filter takes back what
|
|
2900
|
+
* it answered. A single select takes the first key. Null or undefined clears
|
|
2901
|
+
* the selection. Before the render the keys are held, as the select holds
|
|
2902
|
+
* them.
|
|
2903
|
+
* @param {any} v
|
|
2904
|
+
*/
|
|
2905
|
+
set value(v: any);
|
|
2906
|
+
/**
|
|
2907
|
+
* The declared operator, or null, and the labels of the chosen entries. Null
|
|
2908
|
+
* while nothing is chosen, as before the filter has rendered.
|
|
2909
|
+
* @returns {FilterCriterion|null}
|
|
2910
|
+
*/
|
|
2911
|
+
get criterion(): FilterCriterion | null;
|
|
2912
|
+
}
|
|
2913
|
+
/**
|
|
2914
|
+
* An icon button that toggles a native popover, a `ful-note`, holding the
|
|
2915
|
+
* default slot as a short explanation. The popover gives light dismiss and
|
|
2916
|
+
* Escape, and the button carries an `aria-expanded` kept in step with it and
|
|
2917
|
+
* a localized `aria-label`.
|
|
2918
|
+
*
|
|
2919
|
+
* The marker is the `ful-icon` that `Tooltip.config.icon` names for the whole
|
|
2920
|
+
* page, or the one the `icon` attribute names for a single tooltip. A name the
|
|
2921
|
+
* library does not paint is declared by the page as
|
|
2922
|
+
* `ful-icon[name='...'] { mask-image: ... }`.
|
|
2923
|
+
*
|
|
2924
|
+
* `placement` picks the side of the marker the note opens on: `top` (the
|
|
2925
|
+
* default), `bottom`, `left` or `right`. The note is placed in script on every
|
|
2926
|
+
* platform, centred on the marker, clamped into the viewport and following the
|
|
2927
|
+
* marker on scroll and resize, with a callout on the edge facing the marker.
|
|
2928
|
+
*
|
|
2929
|
+
* `describes` offers the note to the nearest ancestor that takes a description
|
|
2930
|
+
* (see `describable`), a field's control in practice: when it is taken, the
|
|
2931
|
+
* note becomes part of that control's accessible description and the marker
|
|
2932
|
+
* leaves the tab order, staying clickable. When nothing takes it, the marker
|
|
2933
|
+
* keeps its tab stop and a warning is logged.
|
|
2934
|
+
*/
|
|
1009
2935
|
declare class Tooltip extends ParsedElement {
|
|
2936
|
+
#private;
|
|
1010
2937
|
static slots: boolean;
|
|
1011
2938
|
static attributes: string[];
|
|
2939
|
+
/** The page-wide defaults: `icon` is the `ful-icon` name of the marker. */
|
|
1012
2940
|
static config: {
|
|
1013
2941
|
icon: string;
|
|
1014
2942
|
};
|
|
1015
2943
|
static template: string;
|
|
2944
|
+
/**
|
|
2945
|
+
* @param {{ slots: Record<string, DocumentFragment> }} c
|
|
2946
|
+
*/
|
|
1016
2947
|
render({ slots }: {
|
|
1017
|
-
slots:
|
|
2948
|
+
slots: Record<string, DocumentFragment>;
|
|
1018
2949
|
}): void;
|
|
1019
2950
|
}
|
|
1020
|
-
|
|
2951
|
+
export type DialogOutcome = {
|
|
2952
|
+
dismissed: boolean;
|
|
2953
|
+
result: string | null;
|
|
2954
|
+
response: any;
|
|
2955
|
+
};
|
|
2956
|
+
/**
|
|
2957
|
+
* How a dialog ended. `dismissed` is true for Escape, the close button, a
|
|
2958
|
+
* backdrop click, a `data-result=""` button, `close()` without a result and a
|
|
2959
|
+
* removal from the document; `result` is the `data-result` of the button, or
|
|
2960
|
+
* the argument of `close(result)`, that answered; `response` is what the form
|
|
2961
|
+
* answered with under `close-on-submit`. Whichever of `result` and `response`
|
|
2962
|
+
* did not answer is null, as both are on a dismissal.
|
|
2963
|
+
* @typedef {{ dismissed: boolean, result: string|null, response: any }} DialogOutcome
|
|
2964
|
+
*/
|
|
2965
|
+
/**
|
|
2966
|
+
* A modal dialog on the native `<dialog>`, rendered with a header, a body and
|
|
2967
|
+
* a footer. `open()` and `ask()` show it and resolve with a `DialogOutcome`.
|
|
2968
|
+
*
|
|
2969
|
+
* The `header` attribute is the title, rendered as an `h2` that names the
|
|
2970
|
+
* dialog through `aria-labelledby`; without it the dialog is unnamed. The
|
|
2971
|
+
* `header` slot is rendered in the header before the title, the default slot
|
|
2972
|
+
* is the body, and the `buttons` slot is rendered in the footer. Without a
|
|
2973
|
+
* `buttons` slot, and without `close-on-submit`, the footer holds a localized
|
|
2974
|
+
* acknowledge button answering `acknowledged`.
|
|
2975
|
+
*
|
|
2976
|
+
* Any button inside the dialog carrying `data-result` closes it with that
|
|
2977
|
+
* result, an empty one being a dismissal. The header carries a close button,
|
|
2978
|
+
* and a press and release both on the backdrop close the dialog, each as a
|
|
2979
|
+
* dismissal, as Escape does.
|
|
2980
|
+
*
|
|
2981
|
+
* Those three gestures go through `dismiss(reason)`, the reason being
|
|
2982
|
+
* `button`, `backdrop` or `escape`: before it closes the dialog, the element
|
|
2983
|
+
* dispatches a cancelable, non-bubbling `dialog:dismiss` with
|
|
2984
|
+
* `detail: { reason }`, and a listener calling `preventDefault()` keeps it
|
|
2985
|
+
* open. Under `guard-dismiss`, a dismissal nobody refused, while a `ful-form`
|
|
2986
|
+
* of the dialog holds unsaved edits (see `Form.dirty`), first asks the user,
|
|
2987
|
+
* through `Dialog.confirm`, whether to close and drop them. A `data-result`
|
|
2988
|
+
* button, `close-on-submit`, `close()` and `update()` are answers or the page
|
|
2989
|
+
* deciding: they dispatch nothing and ask nothing.
|
|
2990
|
+
*
|
|
2991
|
+
* The platform lets a page refuse Escape once per user interaction: a second
|
|
2992
|
+
* Escape with no click or keystroke in between closes the dialog whatever the
|
|
2993
|
+
* page does, `requires-answer` and `guard-dismiss` included. That close is
|
|
2994
|
+
* still announced by a `dialog:dismiss`, which is then not cancelable.
|
|
2995
|
+
*
|
|
2996
|
+
* `requires-answer` withholds the close button and refuses Escape and the
|
|
2997
|
+
* backdrop, so the dialog is closed only by a button carrying `data-result`
|
|
2998
|
+
* or from code, through `close()` or `dismiss()`.
|
|
2999
|
+
*
|
|
3000
|
+
* `close-on-submit` closes the dialog when a `ful-form` that is a direct child
|
|
3001
|
+
* of the body dispatches `submit:success`, answering with its
|
|
3002
|
+
* `detail.response`. A form deeper in the body, such as the filter form of a
|
|
3003
|
+
* `ful-table`, does not close it. The listener sits on the body, so a form
|
|
3004
|
+
* delivered by `update()` is covered as well.
|
|
3005
|
+
*
|
|
3006
|
+
* Every close dispatches a non-bubbling `close` event on the element carrying
|
|
3007
|
+
* the `DialogOutcome` as `detail`, before the pending `ask()` calls resolve.
|
|
3008
|
+
* An element anywhere in the page carrying `dialog-target` set to the
|
|
3009
|
+
* element's id opens it on click.
|
|
3010
|
+
*
|
|
3011
|
+
* The chrome is styled by class as well as by tag, so a plain `<dialog
|
|
3012
|
+
* class="ful-dialog">` written by a page gets the same look: the tag form
|
|
3013
|
+
* matches a direct child, and `ful-dialog-header`, `ful-dialog-body` and
|
|
3014
|
+
* `ful-dialog-footer` match at any depth, as a dialog whose content is wrapped
|
|
3015
|
+
* in a form needs.
|
|
3016
|
+
*/
|
|
1021
3017
|
declare class Dialog extends ParsedElement {
|
|
1022
3018
|
#private;
|
|
1023
3019
|
static attributes: string[];
|
|
1024
3020
|
static slots: boolean;
|
|
1025
3021
|
static template: string;
|
|
3022
|
+
/**
|
|
3023
|
+
* @param {{ slots: Record<string, DocumentFragment> }} c
|
|
3024
|
+
*/
|
|
1026
3025
|
render({ slots }: {
|
|
1027
|
-
slots:
|
|
3026
|
+
slots: Record<string, DocumentFragment>;
|
|
1028
3027
|
}): void;
|
|
3028
|
+
/**
|
|
3029
|
+
* Resolves every pending `ask()` and `open()` with the outcome so far,
|
|
3030
|
+
* a dismissal for a dialog still open, so that no caller waits on a dialog
|
|
3031
|
+
* that left the document. The native dialog is not closed and no `close`
|
|
3032
|
+
* event is dispatched.
|
|
3033
|
+
*/
|
|
1029
3034
|
disconnectedCallback(): void;
|
|
1030
|
-
open(): Promise<any>;
|
|
1031
|
-
ask(): Promise<any>;
|
|
1032
3035
|
/**
|
|
1033
|
-
*
|
|
1034
|
-
*
|
|
1035
|
-
|
|
3036
|
+
* The same as `ask()`.
|
|
3037
|
+
* @returns {Promise<DialogOutcome>}
|
|
3038
|
+
*/
|
|
3039
|
+
open(): Promise<DialogOutcome>;
|
|
3040
|
+
/**
|
|
3041
|
+
* Shows the dialog as a modal and resolves with how it ends.
|
|
3042
|
+
*
|
|
3043
|
+
* The call that opens the dialog resets the outcome of the previous
|
|
3044
|
+
* opening, hides the error and loading sections, and dispatches
|
|
3045
|
+
* `section:requested` on the element (bubbling, with
|
|
3046
|
+
* `detail: { section, first, name: null, index: null }`, `section` being
|
|
3047
|
+
* the body and `first` true only on the first answered request), so a
|
|
3048
|
+
* listener can fill the body. A failed request is painted into the body
|
|
3049
|
+
* and does not reject. On a dialog already open nothing is shown or
|
|
3050
|
+
* requested, and the call waits for the same ending as the calls before it;
|
|
3051
|
+
* one the page moved while open, which is no longer modal, opens anew.
|
|
3052
|
+
* @returns {Promise<DialogOutcome>} resolving on close, or on removal from
|
|
3053
|
+
* the document with a dismissal
|
|
3054
|
+
*/
|
|
3055
|
+
ask(): Promise<DialogOutcome>;
|
|
3056
|
+
/**
|
|
3057
|
+
* Empties and hides the body, shows the loading section, opens the dialog
|
|
3058
|
+
* if it is closed, and fills the body with what the callback resolves to.
|
|
3059
|
+
* A rejection is shown, as the problems' reasons, in the error section,
|
|
3060
|
+
* which has `role="alert"`, and the body is hidden. The title stays the
|
|
3061
|
+
* `header` attribute.
|
|
3062
|
+
*
|
|
3063
|
+
* No `section:requested` is dispatched, and no `ask()` waiter is added:
|
|
3064
|
+
* listen for the `close` event to learn how the dialog ended. When a newer
|
|
3065
|
+
* `update()` starts before the callback settles, this call paints nothing
|
|
3066
|
+
* and resolves `null`, the body being the newer call's; it still rejects
|
|
3067
|
+
* with the callback's error.
|
|
3068
|
+
* @param {() => Node|string|Promise<Node|string>} cb producing the body content
|
|
3069
|
+
* @returns {Promise<Element|null>} the body section, in the document, or
|
|
3070
|
+
* `null` for a call a newer one overtook
|
|
3071
|
+
* @throws {any} what the callback threw or rejected with
|
|
3072
|
+
*/
|
|
3073
|
+
update(cb: () => Node | string | Promise<Node | string>): Promise<Element | null>;
|
|
3074
|
+
/**
|
|
3075
|
+
* Dispatches `section:requested` for the body again, as `ask()` does,
|
|
3076
|
+
* whether the dialog is open or closed. A failed request is painted into
|
|
3077
|
+
* the body.
|
|
3078
|
+
* @returns {Promise<any[]|undefined>} the listeners' answers, undefined when
|
|
3079
|
+
* nobody answered or the request failed; it never rejects
|
|
1036
3080
|
*/
|
|
1037
3081
|
refresh(): Promise<any[] | undefined>;
|
|
1038
|
-
|
|
3082
|
+
/**
|
|
3083
|
+
* Dismisses the dialog as the user would: dispatches the cancelable
|
|
3084
|
+
* `dialog:dismiss` with `detail: { reason }` and, under `guard-dismiss`,
|
|
3085
|
+
* asks before dropping unsaved edits, closing the dialog as a dismissal
|
|
3086
|
+
* unless either refused. `requires-answer` does not refuse it, as it does
|
|
3087
|
+
* not refuse `close()`. Does nothing on a closed dialog.
|
|
3088
|
+
* @param {string} reason why it is dismissed, such as `navigation`
|
|
3089
|
+
* @returns {Promise<boolean>} whether the dialog is closed, false when a
|
|
3090
|
+
* listener or the user kept it open
|
|
3091
|
+
*/
|
|
3092
|
+
dismiss(reason: string): Promise<boolean>;
|
|
3093
|
+
/**
|
|
3094
|
+
* Closes an open dialog, doing nothing on a closed one. A non-empty result
|
|
3095
|
+
* answers as the button carrying that `data-result` would; no result, or
|
|
3096
|
+
* an empty one, is a dismissal.
|
|
3097
|
+
* @param {string} [result]
|
|
3098
|
+
*/
|
|
3099
|
+
close(result?: string): void;
|
|
3100
|
+
/**
|
|
3101
|
+
* Appends a new `ful-dialog` to `document.body`, asks it, and removes it
|
|
3102
|
+
* once it is answered or its render fails.
|
|
3103
|
+
*
|
|
3104
|
+
* A string body is set as text and never parsed as markup; a node is
|
|
3105
|
+
* appended as it is. Each button is either a `[result, label, className?]`
|
|
3106
|
+
* tuple, rendered as a `button` carrying `data-result`, or a node the
|
|
3107
|
+
* caller built, placed in the footer in the order given. With no buttons
|
|
3108
|
+
* the dialog shows its localized acknowledge button.
|
|
3109
|
+
* @param {string} header the title
|
|
3110
|
+
* @param {string|Node} body
|
|
3111
|
+
* @param {([string, string, string?]|Node)[]} [buttons]
|
|
3112
|
+
* @param {{ className?: string }} [options] `className` is set as the class
|
|
3113
|
+
* of the `ful-dialog` element
|
|
3114
|
+
* @returns {Promise<DialogOutcome>} rejecting with what the render threw
|
|
3115
|
+
*/
|
|
3116
|
+
static ask(header: string, body: string | Node, buttons?: ([string, string, string?] | Node)[], { className }?: {
|
|
3117
|
+
className?: string;
|
|
3118
|
+
}): Promise<DialogOutcome>;
|
|
3119
|
+
/**
|
|
3120
|
+
* Asks a yes/no question through `Dialog.ask`, with a cancel button and a
|
|
3121
|
+
* confirm button carrying the `ful-button` class.
|
|
3122
|
+
* @param {string} header the title
|
|
3123
|
+
* @param {string|Node} body as `Dialog.ask` takes it
|
|
3124
|
+
* @param {{ confirm?: string, cancel?: string }} [labels] the button labels,
|
|
3125
|
+
* `dialog.confirm` and `dialog.cancel` localized by default
|
|
3126
|
+
* @param {{ className?: string }} [options] as `Dialog.ask` takes them
|
|
3127
|
+
* @returns {Promise<boolean>} true only for the confirm button; the cancel
|
|
3128
|
+
* button, the close button and Escape answer false
|
|
3129
|
+
*/
|
|
3130
|
+
static confirm(header: string, body: string | Node, labels?: {
|
|
3131
|
+
confirm?: string;
|
|
3132
|
+
cancel?: string;
|
|
3133
|
+
}, options?: {
|
|
3134
|
+
className?: string;
|
|
3135
|
+
}): Promise<boolean>;
|
|
1039
3136
|
}
|
|
1040
3137
|
/**
|
|
1041
|
-
* A side panel
|
|
1042
|
-
*
|
|
3138
|
+
* A side panel on the native `<dialog>`, shown as a modal: a header holding
|
|
3139
|
+
* the title and a localized close button, then loading, error and content
|
|
3140
|
+
* sections, the default slot being the content.
|
|
3141
|
+
*
|
|
3142
|
+
* The `header` attribute is the initial title, rendered as an `h2` that names
|
|
3143
|
+
* the panel through `aria-labelledby`. The `header` slot is rendered in the
|
|
3144
|
+
* header before the title and outside it, so setting the title as text does
|
|
3145
|
+
* not remove it. `placement` is copied onto the native dialog: `end` (the
|
|
3146
|
+
* default, when absent) or `start`, following the writing direction.
|
|
3147
|
+
*
|
|
3148
|
+
* The close button, Escape, and a press and release both on the backdrop all
|
|
3149
|
+
* go through `dismiss(reason)`, the reason being `button`, `backdrop` or
|
|
3150
|
+
* `escape`: before it closes the drawer, the element dispatches a cancelable,
|
|
3151
|
+
* non-bubbling `drawer:dismiss` with `detail: { reason }`, and a listener
|
|
3152
|
+
* calling `preventDefault()` keeps it open. Under `guard-dismiss`, a dismissal
|
|
3153
|
+
* nobody refused, while a `ful-form` of the drawer holds unsaved edits (see
|
|
3154
|
+
* `Form.dirty`), first asks the user, through `Dialog.confirm`, whether to
|
|
3155
|
+
* close and drop them. A `data-result` button, `close-on-submit`, `close()`
|
|
3156
|
+
* and `update()` are answers or the page deciding: they dispatch nothing and
|
|
3157
|
+
* ask nothing. The platform lets a page refuse Escape once per user
|
|
3158
|
+
* interaction: a second Escape with no click or keystroke in between closes
|
|
3159
|
+
* the drawer at once, without the slide, `guard-dismiss` included, and its
|
|
3160
|
+
* `drawer:dismiss` is then not cancelable.
|
|
1043
3161
|
*
|
|
1044
|
-
*
|
|
1045
|
-
*
|
|
1046
|
-
*
|
|
1047
|
-
*
|
|
3162
|
+
* Any button inside the drawer carrying `data-result` closes it with that
|
|
3163
|
+
* result, an empty one being a dismissal. Every close dispatches a
|
|
3164
|
+
* non-bubbling `close` event on the element carrying the `DialogOutcome` as
|
|
3165
|
+
* `detail`, before the pending `ask()` calls resolve.
|
|
3166
|
+
*
|
|
3167
|
+
* `close-on-submit` closes the drawer when a `ful-form` that is a direct child
|
|
3168
|
+
* of the content section dispatches `submit:success`, carrying its
|
|
3169
|
+
* `detail.response`, which may be null. A form deeper in the content, such as
|
|
3170
|
+
* the filter form of a `ful-table`, does not close it. The listener sits on
|
|
3171
|
+
* the content section, so a form delivered by `update()` is covered as well.
|
|
3172
|
+
*
|
|
3173
|
+
* An element anywhere in the page carrying `dialog-target` set to the
|
|
3174
|
+
* element's id calls `open()` on click.
|
|
1048
3175
|
*/
|
|
1049
3176
|
declare class Drawer extends ParsedElement {
|
|
1050
3177
|
#private;
|
|
1051
3178
|
static attributes: string[];
|
|
1052
3179
|
static slots: boolean;
|
|
1053
3180
|
static template: string;
|
|
3181
|
+
/**
|
|
3182
|
+
* @param {{ slots: Record<string, DocumentFragment> }} c
|
|
3183
|
+
*/
|
|
1054
3184
|
render({ slots }: {
|
|
1055
|
-
slots:
|
|
3185
|
+
slots: Record<string, DocumentFragment>;
|
|
1056
3186
|
}): void;
|
|
1057
|
-
get title(): any;
|
|
1058
|
-
set title(v: any);
|
|
1059
3187
|
/**
|
|
1060
|
-
*
|
|
1061
|
-
*
|
|
1062
|
-
* rejection paints the problems and travels to the caller, and an update
|
|
1063
|
-
* superseded by a newer one paints nothing.
|
|
3188
|
+
* The title, read and written as the heading's text.
|
|
3189
|
+
* @type {string}
|
|
1064
3190
|
*/
|
|
1065
|
-
|
|
3191
|
+
get header(): string;
|
|
3192
|
+
/** @param {string|null|undefined} v written as text, `''` for null or undefined */
|
|
3193
|
+
set header(v: string | null | undefined);
|
|
1066
3194
|
/**
|
|
1067
|
-
*
|
|
1068
|
-
*
|
|
1069
|
-
*
|
|
3195
|
+
* Sets the title, empties and hides the content section, shows the loading
|
|
3196
|
+
* section, opens the drawer if it is closed (putting back one that is
|
|
3197
|
+
* sliding out), and fills the content with what the callback resolves to.
|
|
3198
|
+
* A rejection is shown, as the problems' reasons, in the error section,
|
|
3199
|
+
* which has `role="alert"`, and the content is hidden.
|
|
3200
|
+
*
|
|
3201
|
+
* No `section:requested` is dispatched. When a newer `update()` starts
|
|
3202
|
+
* before the callback settles, this call paints nothing and resolves
|
|
3203
|
+
* `null`, the content section being the newer call's; it still rejects with
|
|
3204
|
+
* the callback's error.
|
|
3205
|
+
* @param {string} header the title, set as text
|
|
3206
|
+
* @param {() => Node|string|Promise<Node|string>} cb producing the content
|
|
3207
|
+
* @returns {Promise<Element|null>} the content section, in the document, or
|
|
3208
|
+
* `null` for a call a newer one overtook
|
|
3209
|
+
* @throws {any} what the callback threw or rejected with
|
|
3210
|
+
*/
|
|
3211
|
+
update(header: string, cb: () => Node | string | Promise<Node | string>): Promise<Element | null>;
|
|
3212
|
+
/**
|
|
3213
|
+
* Dispatches `section:requested` for the content again, as `open()` does,
|
|
3214
|
+
* whether the drawer is open or closed. A failed request is painted into
|
|
3215
|
+
* the content section.
|
|
3216
|
+
* @returns {Promise<any[]|undefined>} the listeners' answers, undefined when
|
|
3217
|
+
* nobody answered or the request failed; it never rejects
|
|
1070
3218
|
*/
|
|
1071
3219
|
refresh(): Promise<any[] | undefined>;
|
|
1072
|
-
|
|
1073
|
-
|
|
3220
|
+
/**
|
|
3221
|
+
* Resolves every pending `ask()` and `open()` with the outcome so far,
|
|
3222
|
+
* a dismissal for a drawer still open, so that no caller waits on a drawer
|
|
3223
|
+
* that left the document. The native dialog is not closed and no `close`
|
|
3224
|
+
* event is dispatched.
|
|
3225
|
+
*/
|
|
3226
|
+
disconnectedCallback(): void;
|
|
3227
|
+
/**
|
|
3228
|
+
* The same as `ask()`.
|
|
3229
|
+
* @returns {Promise<{ dismissed: boolean, result: string|null, response: any }>}
|
|
3230
|
+
*/
|
|
3231
|
+
open(): Promise<{
|
|
3232
|
+
dismissed: boolean;
|
|
3233
|
+
result: string | null;
|
|
3234
|
+
response: any;
|
|
3235
|
+
}>;
|
|
3236
|
+
/**
|
|
3237
|
+
* Shows the drawer as a modal and resolves with how it ends.
|
|
3238
|
+
*
|
|
3239
|
+
* The call that opens the drawer resets the outcome of the previous
|
|
3240
|
+
* opening, hides the error and loading sections, and dispatches
|
|
3241
|
+
* `section:requested` on the element (bubbling, with
|
|
3242
|
+
* `detail: { section, first, name: null, index: null }`, `section` being
|
|
3243
|
+
* the content section and `first` true only on the first answered request),
|
|
3244
|
+
* so a listener can fill the content. A failed request is painted into the
|
|
3245
|
+
* content section and does not reject. On a drawer already open nothing is
|
|
3246
|
+
* shown or requested, except that one sliding out stops and stays open,
|
|
3247
|
+
* forgetting the result it was closing with, and the call waits for the
|
|
3248
|
+
* same ending as the calls before it, which is how a caller learns the
|
|
3249
|
+
* outcome of the opening an `update()` made. One the page moved while open,
|
|
3250
|
+
* which is no longer modal, opens anew.
|
|
3251
|
+
* @returns {Promise<{ dismissed: boolean, result: string|null, response: any }>} resolving on
|
|
3252
|
+
* close, or on removal from the document with a dismissal
|
|
3253
|
+
*/
|
|
3254
|
+
ask(): Promise<{
|
|
3255
|
+
dismissed: boolean;
|
|
3256
|
+
result: string | null;
|
|
3257
|
+
response: any;
|
|
3258
|
+
}>;
|
|
3259
|
+
/**
|
|
3260
|
+
* Dismisses the drawer as the user would: dispatches the cancelable
|
|
3261
|
+
* `drawer:dismiss` with `detail: { reason }` and, under `guard-dismiss`,
|
|
3262
|
+
* asks before dropping unsaved edits, sliding the drawer out as a
|
|
3263
|
+
* dismissal unless either refused. Does nothing on a drawer that is closed
|
|
3264
|
+
* or already sliding out.
|
|
3265
|
+
* @param {string} reason why it is dismissed, such as `navigation`
|
|
3266
|
+
* @returns {Promise<boolean>} whether the drawer is closed or closing,
|
|
3267
|
+
* false when a listener or the user kept it open
|
|
3268
|
+
*/
|
|
3269
|
+
dismiss(reason: string): Promise<boolean>;
|
|
3270
|
+
/**
|
|
3271
|
+
* Slides the drawer out and closes it when the animation ends, setting the
|
|
3272
|
+
* `closing` attribute on the native dialog meanwhile; the `close` event is
|
|
3273
|
+
* dispatched then, after this call has returned. Where the user prefers
|
|
3274
|
+
* reduced motion, or no animation runs, it closes at once. A non-empty
|
|
3275
|
+
* result answers as the button carrying that `data-result` would; no
|
|
3276
|
+
* result, or an empty one, is a dismissal. Does nothing on a drawer that is
|
|
3277
|
+
* closed or already sliding out.
|
|
3278
|
+
* @param {string} [result]
|
|
3279
|
+
*/
|
|
3280
|
+
close(result?: string): void;
|
|
3281
|
+
}
|
|
3282
|
+
/**
|
|
3283
|
+
* A menu of commands on the native popover platform. The menu is the popover
|
|
3284
|
+
* itself: light dismiss and Escape come from the browser.
|
|
3285
|
+
*
|
|
3286
|
+
* A menu naming an invoker by id through `for` belongs to that element: the
|
|
3287
|
+
* invoker toggles it, and it is anchored to the invoker through
|
|
3288
|
+
* `Anchors.wire`, placed in script where the platform has no css anchor
|
|
3289
|
+
* positioning. A menu without `for` is shared: one menu serves many
|
|
3290
|
+
* invokers, such as the "more" button of every row of a list, and a page
|
|
3291
|
+
* opens it beside the invoker it is for with `showFor(invoker)`.
|
|
3292
|
+
*
|
|
3293
|
+
* The items are the buttons and `a[href]` links written as its direct
|
|
3294
|
+
* children, kept as they are. Activation is the item's own click, which the
|
|
3295
|
+
* menu follows by hiding itself, so a page listens for the click where it
|
|
3296
|
+
* already listens. The menu fires no events of its own.
|
|
3297
|
+
*
|
|
3298
|
+
* The keyboard is the ARIA menu protocol: the focus moves to the
|
|
3299
|
+
* first item as the menu opens, the arrows, Home and End walk the items,
|
|
3300
|
+
* typing searches their text, Enter and Space activate the focused one, and
|
|
3301
|
+
* Escape and a close from inside the menu hand the focus back to the invoker
|
|
3302
|
+
* that opened it.
|
|
3303
|
+
*/
|
|
3304
|
+
declare class Menu extends ParsedElement {
|
|
3305
|
+
#private;
|
|
3306
|
+
/** @type {string[]} */
|
|
3307
|
+
static attributes: string[];
|
|
3308
|
+
/** Upgrades the menu, and has a shared one that came back follow the presses on its invoker again. */
|
|
3309
|
+
connectedCallback(): void;
|
|
3310
|
+
/** Stops a shared menu following the presses while it is out of the document. */
|
|
3311
|
+
disconnectedCallback(): void;
|
|
3312
|
+
/**
|
|
3313
|
+
* Gives the menu the `menu` role and an empty `popover` attribute unless
|
|
3314
|
+
* it already has one, and marks the items. With `for`, read here once, it
|
|
3315
|
+
* also gives the invoker `aria-haspopup="menu"`, an `aria-expanded` kept
|
|
3316
|
+
* in step, and the toggle of the menu.
|
|
3317
|
+
* @returns {void}
|
|
3318
|
+
* @throws {Error} when `for` is given and names no element in the document at the render
|
|
3319
|
+
*/
|
|
3320
|
+
render(): void;
|
|
3321
|
+
/**
|
|
3322
|
+
* Opens a shared menu, one without `for`, beside `invoker`, or moves it
|
|
3323
|
+
* there when it is open for another one. The menu goes below the invoker,
|
|
3324
|
+
* or above it where there is no room below, and is placed once, as
|
|
3325
|
+
* `Anchors.show` places it. The invoker gets `aria-haspopup="menu"` and an
|
|
3326
|
+
* `aria-expanded` that reads true until the menu closes, and the focus
|
|
3327
|
+
* goes back to it on Escape. A call for the invoker whose press has just
|
|
3328
|
+
* closed the menu does nothing, so a second click on the same button
|
|
3329
|
+
* closes the menu rather than opening it again.
|
|
3330
|
+
* @param {HTMLElement} invoker the element the menu opens for
|
|
3331
|
+
* @returns {void}
|
|
3332
|
+
* @throws {Error} when the menu names its invoker through `for`
|
|
3333
|
+
*/
|
|
3334
|
+
showFor(invoker: HTMLElement): void;
|
|
3335
|
+
/**
|
|
3336
|
+
* The commands, in the order the arrows walk them: the menu's direct
|
|
3337
|
+
* `button` and `a[href]` children, minus those carrying a `disabled` or
|
|
3338
|
+
* `hidden` attribute, which keep their role and leave the walk. Reading it
|
|
3339
|
+
* also marks any child added since the render, giving it the `menuitem`
|
|
3340
|
+
* role, unless it has a role already, and a `tabIndex` of -1.
|
|
3341
|
+
* @type {HTMLElement[]}
|
|
3342
|
+
*/
|
|
3343
|
+
get items(): HTMLElement[];
|
|
1074
3344
|
}
|
|
1075
|
-
|
|
3345
|
+
export type ToastOptions = {
|
|
3346
|
+
/**
|
|
3347
|
+
* the theme class and
|
|
3348
|
+
* the announcement, `info` when absent or unknown
|
|
3349
|
+
*/
|
|
3350
|
+
severity?: 'info' | 'success' | 'warning' | 'error';
|
|
3351
|
+
/**
|
|
3352
|
+
* the milliseconds before the toast retires, the
|
|
3353
|
+
* region's own timeout when absent
|
|
3354
|
+
*/
|
|
3355
|
+
timeout?: number;
|
|
3356
|
+
/**
|
|
3357
|
+
* a button labelled
|
|
3358
|
+
* with `label` as text, beside the message
|
|
3359
|
+
*/
|
|
3360
|
+
action?: {
|
|
3361
|
+
label: any;
|
|
3362
|
+
onClick?: () => void;
|
|
3363
|
+
};
|
|
3364
|
+
};
|
|
3365
|
+
/**
|
|
3366
|
+
* @typedef {object} ToastOptions
|
|
3367
|
+
* @property {'info'|'success'|'warning'|'error'} [severity] the theme class and
|
|
3368
|
+
* the announcement, `info` when absent or unknown
|
|
3369
|
+
* @property {number} [timeout] the milliseconds before the toast retires, the
|
|
3370
|
+
* region's own timeout when absent
|
|
3371
|
+
* @property {{ label: any, onClick?: () => void }} [action] a button labelled
|
|
3372
|
+
* with `label` as text, beside the message
|
|
3373
|
+
*/
|
|
3374
|
+
/**
|
|
3375
|
+
* A region of transient messages, with `role="region"` and a localized
|
|
3376
|
+
* `aria-label`. Each `show()` appends a `ful-toast` that retires on its own
|
|
3377
|
+
* timer, so concurrent toasts stack.
|
|
3378
|
+
*
|
|
3379
|
+
* The region is a manual popover, whatever `popover` the page declared, and
|
|
3380
|
+
* each `show()` shows it again, so it is on top of the top layer when a toast
|
|
3381
|
+
* arrives: above a modal dialog or drawer opened before it. While a modal is
|
|
3382
|
+
* open the page outside it is inert, the region included: its toasts show and
|
|
3383
|
+
* retire on their timers, and their buttons answer once the modal closes.
|
|
3384
|
+
*
|
|
3385
|
+
* `timeout` is the region's default timer in milliseconds, 5000 when absent
|
|
3386
|
+
* or zero.
|
|
3387
|
+
*
|
|
3388
|
+
* A `show-toast` event dispatched on the document, or bubbling to it, shows its
|
|
3389
|
+
* `detail` in every connected region that has rendered, `detail.message` being
|
|
3390
|
+
* the message and the other fields the `ToastOptions`. The document listener is
|
|
3391
|
+
* added once, so a second region shows each toast once, and an event with no
|
|
3392
|
+
* detail is ignored.
|
|
3393
|
+
*/
|
|
1076
3394
|
declare class Toasts extends ParsedElement {
|
|
1077
3395
|
#private;
|
|
1078
3396
|
static attributes: string[];
|
|
3397
|
+
/** Upgrades the region, and makes a re-attached one answer `show-toast` again. */
|
|
1079
3398
|
connectedCallback(): void;
|
|
3399
|
+
/** Stops the region answering `show-toast` while it is out of the document. */
|
|
1080
3400
|
disconnectedCallback(): void;
|
|
1081
3401
|
render(): void;
|
|
1082
3402
|
/**
|
|
1083
|
-
* Appends a toast
|
|
1084
|
-
* reasons
|
|
1085
|
-
*
|
|
3403
|
+
* Appends a `ful-toast` holding the message as text, a `Failure` showing
|
|
3404
|
+
* its problems' reasons one per line and anything else its string form
|
|
3405
|
+
* (`''` for null or undefined). The toast carries the severity as a class
|
|
3406
|
+
* and has `role="alert"` for `error` and `role="status"` otherwise.
|
|
3407
|
+
*
|
|
3408
|
+
* The toast retires when its timer runs out, when its localized dismiss
|
|
3409
|
+
* button is clicked, or when its action button is clicked, after
|
|
3410
|
+
* `action.onClick` runs. The timer pauses while the pointer is over the
|
|
3411
|
+
* toast or the focus is inside it, and resumes with the time that was left
|
|
3412
|
+
* once both have gone. A retiring toast holding the focus moves it to the
|
|
3413
|
+
* region, which has `tabindex="-1"` for this. The toast is removed once its
|
|
3414
|
+
* `ful-toast-out` animation ends, or at once where the user prefers reduced
|
|
3415
|
+
* motion or no animation runs.
|
|
3416
|
+
*
|
|
3417
|
+
* A connected region is shown again as a popover, which puts it above
|
|
3418
|
+
* whatever opened in the top layer since; the focus stays where it was.
|
|
1086
3419
|
* @param {any} message
|
|
1087
|
-
* @param {
|
|
1088
|
-
* @returns {HTMLElement}
|
|
3420
|
+
* @param {ToastOptions} [options]
|
|
3421
|
+
* @returns {HTMLElement} the toast, already in the region
|
|
1089
3422
|
*/
|
|
1090
|
-
show(message: any, options?:
|
|
3423
|
+
show(message: any, options?: ToastOptions): HTMLElement;
|
|
1091
3424
|
}
|
|
1092
3425
|
/**
|
|
1093
3426
|
* A tab panel: one visible panel at a time, announced through the tab pattern
|
|
1094
|
-
* (a tablist of tab buttons, each panel a tabpanel
|
|
1095
|
-
* are declared as
|
|
1096
|
-
* children, paired in order.
|
|
1097
|
-
*
|
|
1098
|
-
*
|
|
3427
|
+
* (a tablist of tab buttons, each panel a tabpanel labelled by its tab). The
|
|
3428
|
+
* tabs are declared as `<tab>` elements in the `tabs` slot, the panels as the
|
|
3429
|
+
* slotless children, paired in order. Each `<tab>` becomes a `button` with the
|
|
3430
|
+
* `tab` role carrying the tab's content, inside a `ful-tablist` with the
|
|
3431
|
+
* `tablist` role. A panel that already has an id keeps it and its tab points at
|
|
3432
|
+
* it; a panel without one gets a generated id. Every panel carries
|
|
3433
|
+
* `tabindex="0"`, so the visible one follows its tab in the tab order and the
|
|
3434
|
+
* hidden ones stay out of it.
|
|
3435
|
+
*
|
|
3436
|
+
* The tabs use a roving tabindex and automatic activation: a click activates
|
|
3437
|
+
* its tab, and on the tablist ArrowRight and ArrowLeft move to the next and
|
|
3438
|
+
* previous tab, wrapping around, while Home and End jump to the first and the
|
|
3439
|
+
* last, moving the focus with the activation.
|
|
3440
|
+
*
|
|
3441
|
+
* Entering a panel fires `section:requested` and `section:requested:#<index>`
|
|
3442
|
+
* on the host, bubbling, with detail `{ name: null, section, index, first }`,
|
|
3443
|
+
* and awaits the answers registered through `AsyncEvents.asyncOn`, so a panel
|
|
3444
|
+
* can deliver itself asynchronously: see `SectionRequests`.
|
|
3445
|
+
*
|
|
3446
|
+
* The tablist stays on one line. When the tabs do not fit it scrolls sideways,
|
|
3447
|
+
* and a previous and a next button appear at the side that has more tabs,
|
|
3448
|
+
* each bringing the next hidden tab into view. They stay out of the tab order:
|
|
3449
|
+
* the keyboard moves through the tabs with the arrow keys. The active tab is
|
|
3450
|
+
* kept in view when it changes and when the tablist changes width.
|
|
1099
3451
|
*/
|
|
1100
3452
|
declare class Tabs extends ParsedElement {
|
|
1101
3453
|
#private;
|
|
1102
3454
|
static slots: boolean;
|
|
1103
3455
|
static observed: string[];
|
|
1104
3456
|
static template: string;
|
|
3457
|
+
/**
|
|
3458
|
+
* Pairs the declared tabs with the panels in order. When the counts
|
|
3459
|
+
* differ, the unpaired tabs and panels are left in the dom as they are and
|
|
3460
|
+
* a warning is logged.
|
|
3461
|
+
* @param {{ slots: Record<string, DocumentFragment> }} conf
|
|
3462
|
+
* @returns {void}
|
|
3463
|
+
*/
|
|
1105
3464
|
render({ slots }: {
|
|
1106
|
-
slots:
|
|
3465
|
+
slots: Record<string, DocumentFragment>;
|
|
1107
3466
|
}): void;
|
|
3467
|
+
/**
|
|
3468
|
+
* The index of the visible panel, reflected to the `active` attribute.
|
|
3469
|
+
* Writing it clamps the value to the paired tabs, a value that is not a
|
|
3470
|
+
* number counting as 0, and selects that tab and shows its panel. When the
|
|
3471
|
+
* index changes on a rendered element it dispatches `tabs:change` on the
|
|
3472
|
+
* host (not bubbling) with detail `{ active, previous }`, then fires the
|
|
3473
|
+
* section requests for the entered panel. The first write, which applies
|
|
3474
|
+
* the attribute after the render, fires the requests without the event.
|
|
3475
|
+
* A failed delivery paints the panel's error and rejects nowhere.
|
|
3476
|
+
* @type {number}
|
|
3477
|
+
*/
|
|
1108
3478
|
get active(): number;
|
|
1109
3479
|
/**
|
|
1110
|
-
*
|
|
1111
|
-
*
|
|
1112
|
-
*
|
|
1113
|
-
*
|
|
3480
|
+
* Fires the section requests again for a panel, whether it is visible or
|
|
3481
|
+
* not, with `first` false once an earlier request was answered.
|
|
3482
|
+
* @param {number | Element} ref the panel's index, or the panel itself
|
|
3483
|
+
* @returns {Promise<any[] | undefined> | undefined} a promise resolving to
|
|
3484
|
+
* the answers, or to undefined when nobody listened or the delivery
|
|
3485
|
+
* failed (its error painted in the panel); undefined, with a warning, when
|
|
3486
|
+
* `ref` names no panel
|
|
1114
3487
|
*/
|
|
1115
|
-
refresh(ref:
|
|
3488
|
+
refresh(ref: number | Element): Promise<any[] | undefined> | undefined;
|
|
1116
3489
|
set active(v: number);
|
|
1117
3490
|
}
|
|
1118
3491
|
/**
|
|
1119
|
-
* An accordion over native details
|
|
1120
|
-
* the semantics, the keyboard and the toggling, the
|
|
1121
|
-
*
|
|
1122
|
-
*
|
|
3492
|
+
* An accordion over native `details`/`summary` disclosures: the browser
|
|
3493
|
+
* provides the semantics, the keyboard and the toggling, and the element adds
|
|
3494
|
+
* the group's styling. The `details` written as its children are rendered,
|
|
3495
|
+
* unchanged, inside a `ful-accordion-group`.
|
|
1123
3496
|
*/
|
|
1124
3497
|
declare class Accordion extends ParsedElement {
|
|
1125
3498
|
#private;
|
|
1126
3499
|
static slots: boolean;
|
|
3500
|
+
/** @type {string[]} */
|
|
1127
3501
|
static observed: string[];
|
|
1128
3502
|
static template: string;
|
|
3503
|
+
/**
|
|
3504
|
+
* @param {{ slots: Record<string, DocumentFragment> | undefined }} c
|
|
3505
|
+
* @returns {void}
|
|
3506
|
+
*/
|
|
1129
3507
|
render({ slots }: {
|
|
1130
|
-
slots:
|
|
3508
|
+
slots: Record<string, DocumentFragment> | undefined;
|
|
1131
3509
|
}): void;
|
|
3510
|
+
/**
|
|
3511
|
+
* Whether opening one panel closes the others, reflected to the
|
|
3512
|
+
* `exclusive` attribute; only `true` turns it on. Setting it gives the
|
|
3513
|
+
* group's direct `details` children one shared, newly generated `name`,
|
|
3514
|
+
* the platform's exclusive grouping, or removes their `name` when off.
|
|
3515
|
+
* A `details` added to the group afterwards is not named until the next
|
|
3516
|
+
* write.
|
|
3517
|
+
* @type {boolean}
|
|
3518
|
+
*/
|
|
1132
3519
|
get exclusive(): boolean;
|
|
1133
3520
|
set exclusive(v: boolean);
|
|
1134
3521
|
}
|
|
1135
3522
|
/**
|
|
1136
|
-
* A wizard: a progress of steps over one-of-N sections
|
|
1137
|
-
*
|
|
1138
|
-
*
|
|
1139
|
-
*
|
|
1140
|
-
*
|
|
1141
|
-
*
|
|
1142
|
-
*
|
|
1143
|
-
*
|
|
1144
|
-
*
|
|
1145
|
-
*
|
|
1146
|
-
*
|
|
1147
|
-
*
|
|
1148
|
-
*
|
|
3523
|
+
* A wizard: a progress of steps over one-of-N sections. The steps are declared
|
|
3524
|
+
* as `<step>` elements in the `steps` slot, the sections as the slotless
|
|
3525
|
+
* children, paired in order; each section may carry a `data-step` name, which
|
|
3526
|
+
* is what `move()` and `refresh()` answer to. The steps become the items of an
|
|
3527
|
+
* `ol` inside `ful-steps`, labelled by the localized `wizard.progress`.
|
|
3528
|
+
*
|
|
3529
|
+
* The current step is the `aria-current="step"` claim, carried by the step and
|
|
3530
|
+
* its section together, and the stylesheet hides every `section` child that
|
|
3531
|
+
* does not carry it. A section that carries the claim in the markup when the
|
|
3532
|
+
* wizard renders stays current; otherwise the first section is. Every paired
|
|
3533
|
+
* section gets `tabindex="-1"`, so a move can focus it.
|
|
3534
|
+
*
|
|
3535
|
+
* Entering a section, the first one at the render included, fires
|
|
3536
|
+
* `section:requested`, `section:requested:#<index>` and, when the section has a
|
|
3537
|
+
* `data-step`, `section:requested:<name>` on the host, bubbling, with detail
|
|
3538
|
+
* `{ name, section, index, first }`, and awaits the answers registered through
|
|
3539
|
+
* `AsyncEvents.asyncOn`: see `SectionRequests`. A failure of the initial entry
|
|
3540
|
+
* paints the section's error and rejects nowhere.
|
|
1149
3541
|
*/
|
|
1150
3542
|
declare class Wizard extends ParsedElement {
|
|
1151
3543
|
#private;
|
|
1152
3544
|
static slots: boolean;
|
|
1153
3545
|
static observed: string[];
|
|
1154
3546
|
static template: string;
|
|
3547
|
+
/**
|
|
3548
|
+
* Pairs the declared steps with the sections in order. When the counts
|
|
3549
|
+
* differ, the unpaired steps and sections are left in the dom as they are
|
|
3550
|
+
* and a warning is logged.
|
|
3551
|
+
* @param {{ slots: Record<string, DocumentFragment> }} conf
|
|
3552
|
+
* @returns {void}
|
|
3553
|
+
*/
|
|
1155
3554
|
render({ slots }: {
|
|
1156
|
-
slots:
|
|
3555
|
+
slots: Record<string, DocumentFragment>;
|
|
1157
3556
|
}): void;
|
|
3557
|
+
/**
|
|
3558
|
+
* The zero-based position of the current step.
|
|
3559
|
+
* @type {number}
|
|
3560
|
+
*/
|
|
1158
3561
|
get index(): number;
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
3562
|
+
/**
|
|
3563
|
+
* The `data-step` of the current section, or null when it has none or no
|
|
3564
|
+
* section is paired.
|
|
3565
|
+
* @type {string | null}
|
|
3566
|
+
*/
|
|
3567
|
+
get step(): string | null;
|
|
3568
|
+
/**
|
|
3569
|
+
* The shape of the progress chrome, reflected to the `progress` attribute:
|
|
3570
|
+
* unset shows the current step alone, `timeline` every step as done,
|
|
3571
|
+
* current or future, `dots` one dot per step, `none` no progress at all.
|
|
3572
|
+
* The value only drives the stylesheet; the moves are the same in every
|
|
3573
|
+
* shape.
|
|
3574
|
+
* @type {string | null}
|
|
3575
|
+
*/
|
|
3576
|
+
get progress(): string | null;
|
|
3577
|
+
set progress(v: string | null);
|
|
3578
|
+
/**
|
|
3579
|
+
* Moves to the following step; at the last step nothing happens.
|
|
3580
|
+
* @returns {Promise<any[] | undefined> | undefined} what `move()` answers
|
|
3581
|
+
* @throws what the entered section's delivery rejected with, as the rejection
|
|
3582
|
+
* of the returned promise
|
|
3583
|
+
*/
|
|
1162
3584
|
next(): Promise<any[] | undefined> | undefined;
|
|
3585
|
+
/**
|
|
3586
|
+
* Moves to the preceding step; at the first step nothing happens.
|
|
3587
|
+
* @returns {Promise<any[] | undefined> | undefined} what `move()` answers
|
|
3588
|
+
* @throws what the entered section's delivery rejected with, as the rejection
|
|
3589
|
+
* of the returned promise
|
|
3590
|
+
*/
|
|
1163
3591
|
prev(): Promise<any[] | undefined> | undefined;
|
|
1164
|
-
move(ref: any): Promise<any[] | undefined> | undefined;
|
|
1165
3592
|
/**
|
|
1166
|
-
*
|
|
1167
|
-
* section
|
|
1168
|
-
*
|
|
1169
|
-
*
|
|
3593
|
+
* Moves to the section carrying `data-step="<ref>"`. A move makes that step
|
|
3594
|
+
* and section current, moves the focus to the section, dispatches
|
|
3595
|
+
* `wizard:change` on the host (not bubbling) with detail `{ index, step }`,
|
|
3596
|
+
* then fires the section requests for it.
|
|
3597
|
+
* @param {string} ref the section's `data-step`
|
|
3598
|
+
* @returns {Promise<any[] | undefined> | undefined} a promise resolving to
|
|
3599
|
+
* the answers once they are delivered, or to undefined when nobody
|
|
3600
|
+
* listened; undefined when the section is already current, and undefined
|
|
3601
|
+
* with a warning when no section carries `ref` or the one carrying it has
|
|
3602
|
+
* no step paired with it
|
|
3603
|
+
* @throws what the entered section's delivery rejected with, as the rejection
|
|
3604
|
+
* of the returned promise, after its error is painted in the section
|
|
1170
3605
|
*/
|
|
1171
|
-
|
|
3606
|
+
move(ref: string): Promise<any[] | undefined> | undefined;
|
|
3607
|
+
/**
|
|
3608
|
+
* Fires the section requests again for a section, whether it is current or
|
|
3609
|
+
* not, with `first` false once an earlier request was answered.
|
|
3610
|
+
* @param {string | Element} ref the section's `data-step`, or the section
|
|
3611
|
+
* itself
|
|
3612
|
+
* @returns {Promise<any[] | undefined> | undefined} a promise resolving to
|
|
3613
|
+
* the answers, or to undefined when nobody listened or the delivery failed
|
|
3614
|
+
* (its error painted in the section); undefined, with a warning, when `ref`
|
|
3615
|
+
* names no section or one with no step paired with it
|
|
3616
|
+
*/
|
|
3617
|
+
refresh(ref: string | Element): Promise<any[] | undefined> | undefined;
|
|
1172
3618
|
}
|
|
1173
3619
|
/**
|
|
1174
3620
|
* Registers everything ful provides on a registry: the elements, the loader
|
|
1175
3621
|
* components, an http client, and the translations for the configured
|
|
1176
|
-
* language. A page calls `registry.plugin(new Plugin({…})).configure()` once
|
|
3622
|
+
* language. A page calls `registry.plugin(new Plugin({…})).configure()` once;
|
|
3623
|
+
* `registry.plugin` calls this plugin's `configure`.
|
|
1177
3624
|
*/
|
|
1178
3625
|
declare class Plugin {
|
|
1179
3626
|
#private;
|
|
1180
3627
|
/**
|
|
1181
|
-
* @param {{ language?: string, translations?: Record<string, any>, httpClient?:
|
|
3628
|
+
* @param {{ language?: string, translations?: Record<string, any>, httpClient?: HttpClient }} [options]
|
|
1182
3629
|
* `language` is fixed for the page: a full BCP-47 tag or a primary subtag,
|
|
1183
|
-
* defaulting to
|
|
1184
|
-
*
|
|
3630
|
+
* defaulting to `navigator.language`, then to 'en'. Its primary subtag,
|
|
3631
|
+
* lowercased, picks the built-in translations (en, it, es, fr); the messages
|
|
3632
|
+
* are the english ones, overridden by that language's, overridden by
|
|
3633
|
+
* `translations`, so a language without built-in translations reads in
|
|
3634
|
+
* english. `translations` is a flat map of keys to messages: reword built-in
|
|
1185
3635
|
* keys ('pagination.showing', …) or add your own ('checkout.total', …).
|
|
1186
3636
|
* `httpClient` is the client every ful component fetches through, registered
|
|
1187
|
-
* as the `http-client` component
|
|
1188
|
-
*
|
|
1189
|
-
* to '/' builds its own.
|
|
3637
|
+
* as the `http-client` component; without one, `configure` builds a client
|
|
3638
|
+
* that sends the csrf token and navigates to '/' on a 401 response.
|
|
1190
3639
|
*/
|
|
1191
3640
|
constructor(options?: {
|
|
1192
3641
|
language?: string;
|
|
1193
3642
|
translations?: Record<string, any>;
|
|
1194
|
-
httpClient?:
|
|
3643
|
+
httpClient?: HttpClient;
|
|
1195
3644
|
});
|
|
1196
|
-
|
|
3645
|
+
/**
|
|
3646
|
+
* Defines on `registry` the `l10n` module, the `http-client` component,
|
|
3647
|
+
* every `ful-*` element, the `loaders:select`, `loaders:form` and
|
|
3648
|
+
* `loaders:table` components, and an overlay publishing `l10n` (the merged
|
|
3649
|
+
* messages) and `locale` (the `language` as given) to every template.
|
|
3650
|
+
* @param {{ defineModule(name: string, module: any): any, defineComponent(name: string, component: any): any, defineElement(tag: string, klass: CustomElementConstructor): any, defineOverlay(...data: any[]): any }} registry
|
|
3651
|
+
* the ftl `Registry`, each of those methods answering the registry itself
|
|
3652
|
+
* @returns {void}
|
|
3653
|
+
*/
|
|
3654
|
+
configure(registry: {
|
|
3655
|
+
defineModule(name: string, module: any): any;
|
|
3656
|
+
defineComponent(name: string, component: any): any;
|
|
3657
|
+
defineElement(tag: string, klass: CustomElementConstructor): any;
|
|
3658
|
+
defineOverlay(...data: any[]): any;
|
|
3659
|
+
}): void;
|
|
3660
|
+
}
|
|
3661
|
+
export { Accordion, Anchors, AsyncEvents, Bindings, BooleanFilter, Checkbox, Claims, CompareFilter, Dialog, Drawer, Dropdown, Field, Form, FormLoader, InFilter, Input, InputFile, InputInstant, InputLocalDate, InputLocalTime, Instant, InstantFilter, LocalDate, LocalDateFilter, LocalStorage, Menu, NumberFilter, PageLeave, Pagination, Plugin, RadioGroup, Select, SelectLoader, SessionStorage, SortButton, Table, TableLoader, TableSchemaParser, Tabs, TextFilter, Timing, Toasts, Tooltip, VersionedLocalStorage, VersionedSessionStorage, Wizard, describable };
|
|
3662
|
+
|
|
3663
|
+
declare global {
|
|
3664
|
+
interface HTMLElementTagNameMap {
|
|
3665
|
+
'ful-tooltip': Tooltip;
|
|
3666
|
+
'ful-dialog': Dialog;
|
|
3667
|
+
'ful-drawer': Drawer;
|
|
3668
|
+
'ful-menu': Menu;
|
|
3669
|
+
'ful-toasts': Toasts;
|
|
3670
|
+
'ful-tabs': Tabs;
|
|
3671
|
+
'ful-accordion': Accordion;
|
|
3672
|
+
'ful-wizard': Wizard;
|
|
3673
|
+
'ful-form': Form;
|
|
3674
|
+
'ful-checkbox': Checkbox;
|
|
3675
|
+
'ful-input': Input;
|
|
3676
|
+
'ful-input-file': InputFile;
|
|
3677
|
+
'ful-local-date': LocalDate;
|
|
3678
|
+
'ful-instant': Instant;
|
|
3679
|
+
'ful-input-local-date': InputLocalDate;
|
|
3680
|
+
'ful-input-local-time': InputLocalTime;
|
|
3681
|
+
'ful-input-instant': InputInstant;
|
|
3682
|
+
'ful-radio-group': RadioGroup;
|
|
3683
|
+
'ful-table': Table;
|
|
3684
|
+
'ful-pagination': Pagination;
|
|
3685
|
+
'ful-sorter': SortButton;
|
|
3686
|
+
'ful-filter-instant': InstantFilter;
|
|
3687
|
+
'ful-filter-local-date': LocalDateFilter;
|
|
3688
|
+
'ful-filter-number': NumberFilter;
|
|
3689
|
+
'ful-filter-boolean': BooleanFilter;
|
|
3690
|
+
'ful-filter-text': TextFilter;
|
|
3691
|
+
'ful-filter-in': InFilter;
|
|
3692
|
+
'ful-select': Select;
|
|
3693
|
+
'ful-dropdown': Dropdown;
|
|
3694
|
+
}
|
|
1197
3695
|
}
|
|
1198
|
-
export { Accordion, Anchors, AsyncEvents, Bindings, BooleanFilter, Checkbox, Claims, CompareFilter, Dialog, Drawer, Dropdown, Field, Form, FormLoader, Input, InputFile, InputInstant, InputLocalDate, InputLocalTime, Instant, InstantFilter, LocalDate, LocalDateFilter, LocalStorage, NumberFilter, Pagination, Plugin, RadioGroup, Select, SelectLoader, SessionStorage, SortButton, Table, TableLoader, TableSchemaParser, Tabs, TextFilter, Timing, Toasts, Tooltip, VersionedLocalStorage, VersionedSessionStorage, Wizard };
|
|
1199
3696
|
|
|
1200
3697
|
export as namespace ful;
|