@optionfactory/fml 9.0.0-rc30 → 9.0.0-rc32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/ful.d.mts CHANGED
@@ -406,12 +406,13 @@ declare class Bindings {
406
406
  *
407
407
  * The claim setters, the validity protocol and the aria wiring all act on the
408
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.
409
+ * own chrome as the control. The claims, `value`, `focus()` and
410
+ * `setCustomValidity` are the members that tolerate a not yet rendered
411
+ * element: before the render the `value` getter answers what the rendered
412
+ * field would answer from its current declared state, a value written then is
413
+ * held and applied by the render (see `_holdValue`), and a problem reported
414
+ * then is shown by it. The other members need the pieces and so work only
415
+ * after the render.
415
416
  *
416
417
  * The inner controls carry `form=""`, so the host is the only element the form
417
418
  * sees. Enter pressed in an inner `<input>` of any type but `file`, `button`,
@@ -485,7 +486,9 @@ declare class Field extends ParsedElement {
485
486
  * field owning a whole subtree overrides this to route the message to the
486
487
  * inner control the path names.
487
488
  *
488
- * Needs the render: before it there is no error region to write to.
489
+ * Before the render there is no error region to write to: a message is
490
+ * kept (the last one wins) and shown once the field has rendered, and a
491
+ * clear drops the one kept. A field whose render failed shows nothing.
489
492
  * @param {string} [error] the message, empty or missing to clear
490
493
  * @param {string} [context] the path below this field's name, '' on an exact match
491
494
  */
@@ -608,7 +611,9 @@ declare class Field extends ParsedElement {
608
611
  /**
609
612
  * Calls `_build(conf)` and wires the pieces it answers. When `_build`
610
613
  * returns a promise the pieces are wired once it settles; a field that
611
- * builds synchronously renders synchronously.
614
+ * builds synchronously renders synchronously. A default slot holding
615
+ * nothing but whitespace is emptied first, so the label it becomes is
616
+ * `:empty` and takes no row.
612
617
  * @param {{ slots: Record<string, DocumentFragment> | undefined }} conf
613
618
  * @returns {void | Promise<void>}
614
619
  */
@@ -1173,7 +1178,8 @@ declare class InputInstant extends Input {
1173
1178
  * size and count limits it declares.
1174
1179
  *
1175
1180
  * 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
1181
+ * chosen files, and `no-input` takes the picker control out of sight, leaving
1182
+ * it to the keyboard and to assistive technology. A `dropzone` slot replaces the default dropzone's content, and
1177
1183
  * an `items` slot holding a template replaces the stock item, rendered with the
1178
1184
  * same `files` overlay so that it reads the File objects it lists. Clicking the
1179
1185
  * dropzone opens the picker, and the host carries a `dragover` attribute while
@@ -1287,7 +1293,7 @@ declare class InputFile extends Input {
1287
1293
  * The size of the selected files together, in bytes.
1288
1294
  * @returns {number}
1289
1295
  */
1290
- get totalsize(): number;
1296
+ get totalSize(): number;
1291
1297
  /**
1292
1298
  * The most files a selection may hold; a larger selection is cleared
1293
1299
  * entirely with a warning. Enforced from the next selection on.
@@ -1329,6 +1335,17 @@ declare class InputFile extends Input {
1329
1335
  get dropzone(): boolean;
1330
1336
  /** @param {boolean} v */
1331
1337
  set dropzone(v: boolean);
1338
+ /**
1339
+ * Whether the picker control is taken out of sight, the dropzone and the
1340
+ * item list carrying the field alone; the stylesheet hides it from the
1341
+ * reflected `no-input` attribute. The control stays in the tab order and
1342
+ * keeps the label, the description and the error, and the dropzone shows
1343
+ * the focus ring while it holds the focus.
1344
+ * @returns {boolean}
1345
+ */
1346
+ get noInput(): boolean;
1347
+ /** @param {boolean} v */
1348
+ set noInput(v: boolean);
1332
1349
  }
1333
1350
  /**
1334
1351
  * Places a popover beside the element or the rectangle it belongs to.
@@ -2058,6 +2075,12 @@ export type TablePageResponse = {
2058
2075
  data: any[];
2059
2076
  size: number;
2060
2077
  };
2078
+ export type TableStatus = {
2079
+ count: Element;
2080
+ appending: Element;
2081
+ failure: Element;
2082
+ error: Element;
2083
+ };
2061
2084
  export type TableRowLoader = {
2062
2085
  load(pageRequest: TablePageRequest, sortRequest: TableSortRequest | null, filterRequest: Record<string, any>): Promise<TablePageResponse>;
2063
2086
  };
@@ -2073,6 +2096,10 @@ export type TableRowLoader = {
2073
2096
  * @typedef {{ data: any[], size: number }} TablePageResponse the rows of the
2074
2097
  * requested page and the total number of rows across every page
2075
2098
  */
2099
+ /**
2100
+ * @typedef {{ count: Element, appending: Element, failure: Element, error: Element }} TableStatus the pieces
2101
+ * of the status bar `paging="infinite"` and `paging="virtual"` show in place of the pager
2102
+ */
2076
2103
  /**
2077
2104
  * @typedef {{ load(pageRequest: TablePageRequest, sortRequest: TableSortRequest|null, filterRequest: Record<string, any>): Promise<TablePageResponse> }} TableRowLoader
2078
2105
  */
@@ -2086,6 +2113,10 @@ export type TableRowLoader = {
2086
2113
  * current `order` in the cycle `asc`, `desc`, `null`. The button does not
2087
2114
  * change its own `order`: whoever handles the event sets it, which `ful-table`
2088
2115
  * does once the sorted page has loaded.
2116
+ *
2117
+ * The stylesheet draws an up arrow for `asc` and a down arrow for `desc`. An
2118
+ * unsorted button shows the up arrow dimmed, `asc` being the order its first
2119
+ * activation asks for.
2089
2120
  */
2090
2121
  declare class SortButton extends ParsedElement {
2091
2122
  #private;
@@ -2170,42 +2201,6 @@ declare class Pagination extends ParsedElement {
2170
2201
  */
2171
2202
  set current(value: number | null);
2172
2203
  }
2173
- /** Reads the schema declaration into the header and row templates a table renders from. */
2174
- declare class TableSchemaParser {
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']>;
2202
- sort: {
2203
- sorter: string | null;
2204
- order: string | null;
2205
- } | null;
2206
- length: number;
2207
- };
2208
- }
2209
2204
  /** Serves a table's rows from an array held in memory, applying the sort and the paging itself. */
2210
2205
  declare class InMemoryTableLoader {
2211
2206
  #private;
@@ -2302,6 +2297,21 @@ declare class TableLoader {
2302
2297
  * for it. Without it the table shows an initial panel until `load`,
2303
2298
  * `reload` or `resetWithFilter` is called.
2304
2299
  *
2300
+ * `paging="infinite"`, read once at the upgrade, replaces the pager with a
2301
+ * status bar saying how many rows of how many are shown, with a reload
2302
+ * button. A load still replaces the rows with one page, scrolling the rows
2303
+ * back to the top; from then on, whenever a row of the last half page
2304
+ * comes into view, the next page is asked with the same size, sort and
2305
+ * filters and appended (see `load`). `reload`, a sort, a filter submit and a
2306
+ * size change start over from the first page.
2307
+ *
2308
+ * `paging="virtual"` shows the same status bar, saying which rows of how many
2309
+ * are in view, and keeps in the page only the page in view and one on either
2310
+ * side of it, the others standing in as empty space sized on the height of
2311
+ * the rows. The rows must scroll inside the table, as `ful-fill` makes them:
2312
+ * a table whose rows the page scrolls appends as `paging="infinite"` does,
2313
+ * and warns. See `load` and `reload`.
2314
+ *
2305
2315
  * Inside the table, and not inside a `ful-table` nested in it, a
2306
2316
  * `page:requested` loads that page with the current size,
2307
2317
  * sort and filters; a `sort:requested` loads the current page with the new
@@ -2325,6 +2335,7 @@ declare class Table extends ParsedElement {
2325
2335
  static config: {
2326
2336
  searchIcon: string;
2327
2337
  emptyIcon: string;
2338
+ reloadIcon: string;
2328
2339
  };
2329
2340
  static template: string;
2330
2341
  static templates: {
@@ -2342,14 +2353,15 @@ declare class Table extends ParsedElement {
2342
2353
  * writing the size is not a request to start loading, which is what
2343
2354
  * `autoload` and `reload()` are for. A write that does not change the size
2344
2355
  * does nothing. A write made before the render is replaced by the declared
2345
- * `page-size` when the table renders.
2356
+ * `page-size` when the table renders, or by ten when that is not a number
2357
+ * above zero.
2346
2358
  *
2347
2359
  * The reload is not awaited: a failure shows the error panel and its
2348
2360
  * rejection is unhandled.
2349
2361
  * @param {number|string|null|undefined} value a number or a string of
2350
2362
  * one, such as a select's value; absent or null is the default of ten,
2351
2363
  * so removing the attribute restores it, and a value that is not a
2352
- * number is ignored
2364
+ * finite number above zero is ignored
2353
2365
  */
2354
2366
  set pageSize(value: number | string | null | undefined);
2355
2367
  /**
@@ -2414,6 +2426,14 @@ declare class Table extends ParsedElement {
2414
2426
  * `submit` listeners as the later ones, and the load its `submit:success`
2415
2427
  * starts is the one awaited. A filter submit that is cancelled, fails or
2416
2428
  * is dropped for one in flight loads nothing, and the promise resolves.
2429
+ *
2430
+ * Under `paging="virtual"`, once rows show, it asks again for the pages in
2431
+ * the page, with the same size, sort and filters, and shows them where
2432
+ * they are, the scroll position and the widths of the columns kept; the
2433
+ * table is busy and settles, fails and dispatches as a load does, one
2434
+ * `load:success` per page. When the answers report fewer rows than the
2435
+ * window starts at, it loads the first page instead. A `src` or `method`
2436
+ * write still starts over from the first page.
2417
2437
  * @returns {Promise<void>} as `load`
2418
2438
  */
2419
2439
  reload(): Promise<void>;
@@ -2440,12 +2460,49 @@ declare class Table extends ParsedElement {
2440
2460
  * `aria-busy` is removed, `load:failure` is dispatched (bubbling, not
2441
2461
  * cancelable) with `detail` set to
2442
2462
  * `{ pageRequest, sortRequest, filterRequest, exception }`, and the
2443
- * returned promise rejects with the same error.
2463
+ * returned promise rejects with the same error. An answer the table cannot
2464
+ * page fails the same way, with an error saying so: one whose `size` is
2465
+ * not a number, as a response of another shape read without a
2466
+ * `response-mapper` is, or a page size of zero.
2444
2467
  *
2445
2468
  * A load started after this one supersedes it: when this one's answer or
2446
2469
  * failure arrives it changes nothing, dispatches nothing and resolves;
2447
2470
  * superseded while its rows render, it leaves them to the newer load and
2448
2471
  * dispatches nothing.
2472
+ *
2473
+ * Under `paging="infinite"` the status bar takes the pager's place, and
2474
+ * once the load has dispatched `load:success` the next page is awaited:
2475
+ * when a row of the last half page comes into view, through
2476
+ * whatever scrolls it, the following page is asked for with the same
2477
+ * size, sort and filters and its rows are appended. An append runs
2478
+ * without `aria-busy`, a spinner in the status bar standing in, and
2479
+ * dispatches `load:success` or `load:failure` as a load does, its
2480
+ * `pageRequest` naming the appended page. A failed append keeps the
2481
+ * rows, shows the error in the status bar with a retry button and
2482
+ * rejects to nobody, nothing awaiting it. Appending stops once the rows
2483
+ * shown reach the total the last answer reported, or an answer carries
2484
+ * no rows. A load supersedes an append in flight; `reload` repeats this
2485
+ * load, not the pages appended to it.
2486
+ *
2487
+ * Under `paging="virtual"` the load shows its page as the window, scrolled
2488
+ * to where it sits among the total, and measures two things on its rows:
2489
+ * the height the empty space standing in for the other rows is sized on,
2490
+ * and the width of the columns, which then stay as they are, in
2491
+ * proportion, until the next load, so that the pages coming and going do
2492
+ * not move them. From then on the window follows the scroll: the page in
2493
+ * view and one on either side stay in the page and the others are dropped,
2494
+ * the page holding the focus kept while it is within two pages of them. A
2495
+ * page next to the window is asked for at once; a scroll landing farther
2496
+ * waits for the scroll to rest. Window pages are asked for without
2497
+ * `aria-busy`, a spinner in the status bar standing in, and dispatch
2498
+ * `load:success` or `load:failure` per page as appends do; a failure keeps
2499
+ * the rows and offers a retry. The row in view stays where it is as pages
2500
+ * come and go above it: the table measures it before and after and
2501
+ * corrects the scroll by whatever the browser's own scroll anchoring has
2502
+ * not kept, which is all of it where the browser anchors no table rows
2503
+ * (Firefox), has no scroll anchoring or the rows' container declares
2504
+ * `overflow-anchor: none`, and nothing where it has. The table carries
2505
+ * `aria-rowcount` and each row its `aria-rowindex`.
2449
2506
  * @param {TablePageRequest} pageRequest
2450
2507
  * @param {TableSortRequest|null} sortRequest
2451
2508
  * @param {Record<string, any>} filterRequest
@@ -3044,7 +3101,7 @@ declare class Dialog extends ParsedElement {
3044
3101
  * opening, hides the error and loading sections, and dispatches
3045
3102
  * `section:requested` on the element (bubbling, with
3046
3103
  * `detail: { section, first, name: null, index: null }`, `section` being
3047
- * the body and `first` true only on the first answered request), so a
3104
+ * the body and `first` true until a delivery succeeds), so a
3048
3105
  * listener can fill the body. A failed request is painted into the body
3049
3106
  * and does not reject. On a dialog already open nothing is shown or
3050
3107
  * requested, and the call waits for the same ending as the calls before it;
@@ -3240,7 +3297,7 @@ declare class Drawer extends ParsedElement {
3240
3297
  * opening, hides the error and loading sections, and dispatches
3241
3298
  * `section:requested` on the element (bubbling, with
3242
3299
  * `detail: { section, first, name: null, index: null }`, `section` being
3243
- * the content section and `first` true only on the first answered request),
3300
+ * the content section and `first` true until a delivery succeeds),
3244
3301
  * so a listener can fill the content. A failed request is painted into the
3245
3302
  * content section and does not reject. On a drawer already open nothing is
3246
3303
  * shown or requested, except that one sliding out stops and stays open,
@@ -3270,11 +3327,13 @@ declare class Drawer extends ParsedElement {
3270
3327
  /**
3271
3328
  * Slides the drawer out and closes it when the animation ends, setting the
3272
3329
  * `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.
3330
+ * dispatched then, after this call has returned. An animation the page
3331
+ * cancels, by hiding the drawer or an ancestor of it, closes it as one
3332
+ * that ended does. Where the user prefers reduced motion, or no animation
3333
+ * runs, it closes at once. A non-empty result answers as the button
3334
+ * carrying that `data-result` would; no result, or an empty one, is a
3335
+ * dismissal. Does nothing on a drawer that is closed or already sliding
3336
+ * out.
3278
3337
  * @param {string} [result]
3279
3338
  */
3280
3339
  close(result?: string): void;
@@ -3478,7 +3537,7 @@ declare class Tabs extends ParsedElement {
3478
3537
  get active(): number;
3479
3538
  /**
3480
3539
  * Fires the section requests again for a panel, whether it is visible or
3481
- * not, with `first` false once an earlier request was answered.
3540
+ * not, with `first` false once an earlier delivery succeeded.
3482
3541
  * @param {number | Element} ref the panel's index, or the panel itself
3483
3542
  * @returns {Promise<any[] | undefined> | undefined} a promise resolving to
3484
3543
  * the answers, or to undefined when nobody listened or the delivery
@@ -3606,7 +3665,7 @@ declare class Wizard extends ParsedElement {
3606
3665
  move(ref: string): Promise<any[] | undefined> | undefined;
3607
3666
  /**
3608
3667
  * Fires the section requests again for a section, whether it is current or
3609
- * not, with `first` false once an earlier request was answered.
3668
+ * not, with `first` false once an earlier delivery succeeded.
3610
3669
  * @param {string | Element} ref the section's `data-step`, or the section
3611
3670
  * itself
3612
3671
  * @returns {Promise<any[] | undefined> | undefined} a promise resolving to
@@ -3627,8 +3686,11 @@ declare class Plugin {
3627
3686
  /**
3628
3687
  * @param {{ language?: string, translations?: Record<string, any>, httpClient?: HttpClient }} [options]
3629
3688
  * `language` is fixed for the page: a full BCP-47 tag or a primary subtag,
3630
- * defaulting to `navigator.language`, then to 'en'. Its primary subtag,
3631
- * lowercased, picks the built-in translations (en, it, es, fr); the messages
3689
+ * defaulting to `navigator.language`, then to 'en', an empty one included.
3690
+ * It is canonicalized (`IT-it` and `it_IT` both read `it-IT`), and one that
3691
+ * is no language tag at all throws here, rather than at the first message
3692
+ * or number formatted in it. Its primary subtag picks the built-in
3693
+ * translations (en, it, es, fr); the messages
3632
3694
  * are the english ones, overridden by that language's, overridden by
3633
3695
  * `translations`, so a language without built-in translations reads in
3634
3696
  * english. `translations` is a flat map of keys to messages: reword built-in
@@ -3636,6 +3698,7 @@ declare class Plugin {
3636
3698
  * `httpClient` is the client every ful component fetches through, registered
3637
3699
  * as the `http-client` component; without one, `configure` builds a client
3638
3700
  * that sends the csrf token and navigates to '/' on a 401 response.
3701
+ * @throws {RangeError} when `language` is not a language tag
3639
3702
  */
3640
3703
  constructor(options?: {
3641
3704
  language?: string;
@@ -3646,7 +3709,7 @@ declare class Plugin {
3646
3709
  * Defines on `registry` the `l10n` module, the `http-client` component,
3647
3710
  * every `ful-*` element, the `loaders:select`, `loaders:form` and
3648
3711
  * `loaders:table` components, and an overlay publishing `l10n` (the merged
3649
- * messages) and `locale` (the `language` as given) to every template.
3712
+ * messages) and `locale` (the `language`, canonicalized) to every template.
3650
3713
  * @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
3714
  * the ftl `Registry`, each of those methods answering the registry itself
3652
3715
  * @returns {void}
@@ -3658,7 +3721,7 @@ declare class Plugin {
3658
3721
  defineOverlay(...data: any[]): any;
3659
3722
  }): void;
3660
3723
  }
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 };
3724
+ 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, Tabs, TextFilter, Timing, Toasts, Tooltip, VersionedLocalStorage, VersionedSessionStorage, Wizard, describable };
3662
3725
 
3663
3726
  declare global {
3664
3727
  interface HTMLElementTagNameMap {