@optionfactory/fml 9.0.0-rc22 → 9.0.0-rc24

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
@@ -363,6 +363,11 @@ declare class Bindings {
363
363
  * `rest` being the remainder of the path (`''` on an exact match) that a
364
364
  * composite can use to route the problem to an inner control.
365
365
  *
366
+ * A control counts only when it can show a problem, through a
367
+ * `setCustomValidity` of its own: a form-associated element that has none is
368
+ * skipped, so its problems fall to a shorter prefix or to the banner instead
369
+ * of being dropped.
370
+ *
366
371
  * Every other problem, and a field problem naming no control, is shown in
367
372
  * each `ful-errors` banner of the form: the banner gets `role="alert"`, is
368
373
  * revealed and holds the reasons one per line. With no such problem the
@@ -616,6 +621,14 @@ declare class Field extends ParsedElement {
616
621
  * accessibility tree.
617
622
  * - `also` are further controls that mirror `disabled` and `readOnly`
618
623
  * beside the claim target.
624
+ *
625
+ * The pieces are elements the field rendered itself, native controls or
626
+ * wrappers of its own. A ful field is not one: it has no `readOnly`, its
627
+ * host's role takes no aria, and a label's `for` names its host rather than
628
+ * its control. A composite built from ful fields answers the inner field as
629
+ * `control`, which forwards `focus()`, lets it render its own label with
630
+ * `label` and `announces` null, and forwards the claims in its setters,
631
+ * calling super first.
619
632
  * @param {{ slots: Record<string, DocumentFragment> | undefined }} conf
620
633
  * @returns {any} the pieces, or a promise of them
621
634
  * @throws {Error} when the subclass does not implement it
@@ -782,9 +795,21 @@ declare class Form extends ParsedElement {
782
795
  * A call while a submit is in flight returns at once, doing nothing.
783
796
  * @param {HTMLElement} [submitter] the button that submitted, if any; it is
784
797
  * the only button whose name and value are submitted
785
- * @returns {Promise<void>} settling once the submit has finished, whatever its outcome
798
+ * @returns {Promise<boolean>} settling once the submit has finished: true
799
+ * after `submit:success`, false when it failed, was cancelled or was dropped
800
+ * for one in flight
786
801
  */
787
- submit(submitter?: HTMLElement): Promise<void>;
802
+ submit(submitter?: HTMLElement): Promise<boolean>;
803
+ /**
804
+ * Saves the unsaved edits, for a page action that would lose them, such as
805
+ * one reloading the page: under `track-changes` it submits only while the
806
+ * form is dirty, and without it always submits.
807
+ * @param {HTMLElement} [submitter] as `submit` takes it
808
+ * @returns {Promise<boolean>} whether no unsaved edit is left: false when
809
+ * the submit did not succeed, or when the user edited the form while it
810
+ * was in flight
811
+ */
812
+ save(submitter?: HTMLElement): Promise<boolean>;
788
813
  /**
789
814
  * Resets the native form, each field returning to its default value. Under
790
815
  * `track-changes` every control counts as edited: the form is dirty if the
@@ -817,11 +842,11 @@ declare class Form extends ParsedElement {
817
842
  */
818
843
  commit(): void;
819
844
  /**
820
- * Counts a control as edited by the user, for a value the page writes on
845
+ * Counts controls as edited by the user, for values the page writes on
821
846
  * the user's behalf: assigning `value` reports nothing, as 0019 wants.
822
- * @param {Element} el the control, or an element inside it
847
+ * @param {...Element} els each a control, or an element inside one
823
848
  */
824
- edited(el: Element): void;
849
+ edited(...els: Element[]): void;
825
850
  /**
826
851
  * Marks the form busy or releases it. Calls nest: only the first
827
852
  * `spinner(true)` and the matching last `spinner(false)` act, so a caller's
@@ -2836,21 +2861,24 @@ export type DialogOutcome = {
2836
2861
  * and a press and release both on the backdrop close the dialog, each as a
2837
2862
  * dismissal, as Escape does.
2838
2863
  *
2839
- * Before any of those three gestures closes it, the element dispatches a
2840
- * cancelable, non-bubbling `dialog:dismiss` with `detail: { reason }`, the
2841
- * reason being `button`, `backdrop` or `escape`; a listener calling
2842
- * `preventDefault()` keeps it open, to guard unsaved edits. A `data-result`
2843
- * button, `close-on-submit` and `close()` answer rather than dismiss, and
2844
- * dispatch none.
2864
+ * Those three gestures go through `dismiss(reason)`, the reason being
2865
+ * `button`, `backdrop` or `escape`: before it closes the dialog, the element
2866
+ * dispatches a cancelable, non-bubbling `dialog:dismiss` with
2867
+ * `detail: { reason }`, and a listener calling `preventDefault()` keeps it
2868
+ * open. Under `guard-dismiss`, a dismissal nobody refused, while a `ful-form`
2869
+ * of the dialog holds unsaved edits (see `Form.dirty`), first asks the user,
2870
+ * through `Dialog.confirm`, whether to close and drop them. A `data-result`
2871
+ * button, `close-on-submit`, `close()` and `update()` are answers or the page
2872
+ * deciding: they dispatch nothing and ask nothing.
2845
2873
  *
2846
2874
  * The platform lets a page refuse Escape once per user interaction: a second
2847
2875
  * Escape with no click or keystroke in between closes the dialog whatever the
2848
- * page does, `requires-answer` included. That close is still announced by a
2849
- * `dialog:dismiss`, which is then not cancelable.
2876
+ * page does, `requires-answer` and `guard-dismiss` included. That close is
2877
+ * still announced by a `dialog:dismiss`, which is then not cancelable.
2850
2878
  *
2851
2879
  * `requires-answer` withholds the close button and refuses Escape and the
2852
2880
  * backdrop, so the dialog is closed only by a button carrying `data-result`
2853
- * or from code through `close()`.
2881
+ * or from code, through `close()` or `dismiss()`.
2854
2882
  *
2855
2883
  * `close-on-submit` closes the dialog when a `ful-form` that is a direct child
2856
2884
  * of the body dispatches `submit:success`, answering with its
@@ -2916,14 +2944,15 @@ declare class Dialog extends ParsedElement {
2916
2944
  *
2917
2945
  * No `section:requested` is dispatched, and no `ask()` waiter is added:
2918
2946
  * listen for the `close` event to learn how the dialog ended. When a newer
2919
- * `update()` starts before the callback settles, this call paints nothing:
2920
- * it resolves with the body regardless, and still rejects with the
2921
- * callback's error.
2947
+ * `update()` starts before the callback settles, this call paints nothing
2948
+ * and resolves `null`, the body being the newer call's; it still rejects
2949
+ * with the callback's error.
2922
2950
  * @param {() => Node|string|Promise<Node|string>} cb producing the body content
2923
- * @returns {Promise<Element>} the body section, in the document
2951
+ * @returns {Promise<Element|null>} the body section, in the document, or
2952
+ * `null` for a call a newer one overtook
2924
2953
  * @throws {any} what the callback threw or rejected with
2925
2954
  */
2926
- update(cb: () => Node | string | Promise<Node | string>): Promise<Element>;
2955
+ update(cb: () => Node | string | Promise<Node | string>): Promise<Element | null>;
2927
2956
  /**
2928
2957
  * Dispatches `section:requested` for the body again, as `ask()` does,
2929
2958
  * whether the dialog is open or closed. A failed request is painted into
@@ -2932,6 +2961,17 @@ declare class Dialog extends ParsedElement {
2932
2961
  * nobody answered or the request failed; it never rejects
2933
2962
  */
2934
2963
  refresh(): Promise<any[] | undefined>;
2964
+ /**
2965
+ * Dismisses the dialog as the user would: dispatches the cancelable
2966
+ * `dialog:dismiss` with `detail: { reason }` and, under `guard-dismiss`,
2967
+ * asks before dropping unsaved edits, closing the dialog as a dismissal
2968
+ * unless either refused. `requires-answer` does not refuse it, as it does
2969
+ * not refuse `close()`. Does nothing on a closed dialog.
2970
+ * @param {string} reason why it is dismissed, such as `navigation`
2971
+ * @returns {Promise<boolean>} whether the dialog is closed, false when a
2972
+ * listener or the user kept it open
2973
+ */
2974
+ dismiss(reason: string): Promise<boolean>;
2935
2975
  /**
2936
2976
  * Closes an open dialog, doing nothing on a closed one. A non-empty result
2937
2977
  * answers as the button carrying that `data-result` would; no result, or
@@ -2988,17 +3028,23 @@ declare class Dialog extends ParsedElement {
2988
3028
  * default, when absent) or `start`, following the writing direction.
2989
3029
  *
2990
3030
  * The close button, Escape, and a press and release both on the backdrop all
2991
- * go through `close()`, once a cancelable, non-bubbling `drawer:dismiss` with
2992
- * `detail: { reason }` (`button`, `backdrop` or `escape`) has been dispatched
2993
- * on the element and no listener prevented it: `preventDefault()` keeps the
2994
- * drawer open, to guard unsaved edits. `close()` and `close-on-submit`
2995
- * dispatch none. The platform lets a page refuse Escape once per user
3031
+ * go through `dismiss(reason)`, the reason being `button`, `backdrop` or
3032
+ * `escape`: before it closes the drawer, the element dispatches a cancelable,
3033
+ * non-bubbling `drawer:dismiss` with `detail: { reason }`, and a listener
3034
+ * calling `preventDefault()` keeps it open. Under `guard-dismiss`, a dismissal
3035
+ * nobody refused, while a `ful-form` of the drawer holds unsaved edits (see
3036
+ * `Form.dirty`), first asks the user, through `Dialog.confirm`, whether to
3037
+ * close and drop them. A `data-result` button, `close-on-submit`, `close()`
3038
+ * and `update()` are answers or the page deciding: they dispatch nothing and
3039
+ * ask nothing. The platform lets a page refuse Escape once per user
2996
3040
  * interaction: a second Escape with no click or keystroke in between closes
2997
- * the drawer at once, without the slide, and its `drawer:dismiss` is then not
2998
- * cancelable. Every close dispatches a non-bubbling `close` event on
2999
- * the element with `detail: { dismissed, response }`: `{ dismissed: false,
3000
- * response }` when a form closed it under `close-on-submit`, and
3001
- * `{ dismissed: true, response: null }` for any other close.
3041
+ * the drawer at once, without the slide, `guard-dismiss` included, and its
3042
+ * `drawer:dismiss` is then not cancelable.
3043
+ *
3044
+ * Any button inside the drawer carrying `data-result` closes it with that
3045
+ * result, an empty one being a dismissal. Every close dispatches a
3046
+ * non-bubbling `close` event on the element carrying the `DialogOutcome` as
3047
+ * `detail`, before the pending `ask()` calls resolve.
3002
3048
  *
3003
3049
  * `close-on-submit` closes the drawer when a `ful-form` that is a direct child
3004
3050
  * of the content section dispatches `submit:success`, carrying its
@@ -3035,15 +3081,16 @@ declare class Drawer extends ParsedElement {
3035
3081
  * which has `role="alert"`, and the content is hidden.
3036
3082
  *
3037
3083
  * No `section:requested` is dispatched. When a newer `update()` starts
3038
- * before the callback settles, this call paints nothing: it resolves with
3039
- * the content section regardless, and still rejects with the callback's
3040
- * error.
3084
+ * before the callback settles, this call paints nothing and resolves
3085
+ * `null`, the content section being the newer call's; it still rejects with
3086
+ * the callback's error.
3041
3087
  * @param {string} header the title, set as text
3042
3088
  * @param {() => Node|string|Promise<Node|string>} cb producing the content
3043
- * @returns {Promise<Element>} the content section, in the document
3089
+ * @returns {Promise<Element|null>} the content section, in the document, or
3090
+ * `null` for a call a newer one overtook
3044
3091
  * @throws {any} what the callback threw or rejected with
3045
3092
  */
3046
- update(header: string, cb: () => Node | string | Promise<Node | string>): Promise<Element>;
3093
+ update(header: string, cb: () => Node | string | Promise<Node | string>): Promise<Element | null>;
3047
3094
  /**
3048
3095
  * Dispatches `section:requested` for the content again, as `open()` does,
3049
3096
  * whether the drawer is open or closed. A failed request is painted into
@@ -3053,8 +3100,23 @@ declare class Drawer extends ParsedElement {
3053
3100
  */
3054
3101
  refresh(): Promise<any[] | undefined>;
3055
3102
  /**
3056
- * Shows the drawer as a modal. On a drawer already open nothing happens,
3057
- * except that one sliding out stops and stays open.
3103
+ * Resolves every pending `ask()` and `open()` with the outcome so far,
3104
+ * a dismissal for a drawer still open, so that no caller waits on a drawer
3105
+ * that left the document. The native dialog is not closed and no `close`
3106
+ * event is dispatched.
3107
+ */
3108
+ disconnectedCallback(): void;
3109
+ /**
3110
+ * The same as `ask()`.
3111
+ * @returns {Promise<{ dismissed: boolean, result: string|null, response: any }>}
3112
+ */
3113
+ open(): Promise<{
3114
+ dismissed: boolean;
3115
+ result: string | null;
3116
+ response: any;
3117
+ }>;
3118
+ /**
3119
+ * Shows the drawer as a modal and resolves with how it ends.
3058
3120
  *
3059
3121
  * The call that opens the drawer resets the outcome of the previous
3060
3122
  * opening, hides the error and loading sections, and dispatches
@@ -3062,17 +3124,40 @@ declare class Drawer extends ParsedElement {
3062
3124
  * `detail: { section, first, name: null, index: null }`, `section` being
3063
3125
  * the content section and `first` true only on the first answered request),
3064
3126
  * so a listener can fill the content. A failed request is painted into the
3065
- * content section.
3066
- */
3067
- open(): void;
3127
+ * content section and does not reject. On a drawer already open nothing is
3128
+ * shown or requested, except that one sliding out stops and stays open, and
3129
+ * the call waits for the same ending as the calls before it, which is how
3130
+ * a caller learns the outcome of the opening an `update()` made.
3131
+ * @returns {Promise<{ dismissed: boolean, result: string|null, response: any }>} resolving on
3132
+ * close, or on removal from the document with a dismissal
3133
+ */
3134
+ ask(): Promise<{
3135
+ dismissed: boolean;
3136
+ result: string | null;
3137
+ response: any;
3138
+ }>;
3139
+ /**
3140
+ * Dismisses the drawer as the user would: dispatches the cancelable
3141
+ * `drawer:dismiss` with `detail: { reason }` and, under `guard-dismiss`,
3142
+ * asks before dropping unsaved edits, sliding the drawer out as a
3143
+ * dismissal unless either refused. Does nothing on a drawer that is closed
3144
+ * or already sliding out.
3145
+ * @param {string} reason why it is dismissed, such as `navigation`
3146
+ * @returns {Promise<boolean>} whether the drawer is closed or closing,
3147
+ * false when a listener or the user kept it open
3148
+ */
3149
+ dismiss(reason: string): Promise<boolean>;
3068
3150
  /**
3069
3151
  * Slides the drawer out and closes it when the animation ends, setting the
3070
3152
  * `closing` attribute on the native dialog meanwhile; the `close` event is
3071
3153
  * dispatched then, after this call has returned. Where the user prefers
3072
- * reduced motion, or no animation runs, it closes at once. Does nothing on
3073
- * a drawer that is closed or already sliding out.
3154
+ * reduced motion, or no animation runs, it closes at once. A non-empty
3155
+ * result answers as the button carrying that `data-result` would; no
3156
+ * result, or an empty one, is a dismissal. Does nothing on a drawer that is
3157
+ * closed or already sliding out.
3158
+ * @param {string} [result]
3074
3159
  */
3075
- close(): void;
3160
+ close(result?: string): void;
3076
3161
  }
3077
3162
  /**
3078
3163
  * A menu of commands on the native popover platform, opened by the element