@optionfactory/fml 9.0.0-rc1 → 9.0.0-rc10

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
@@ -102,6 +102,41 @@ declare class Claims {
102
102
  /** Supersedes every claim without holding a new one. */
103
103
  invalidate(): void;
104
104
  }
105
+ export type Describable = {
106
+ describedBy(el: HTMLElement): boolean;
107
+ };
108
+ /**
109
+ * The protocol by which content standing inside a field becomes part of the
110
+ * accessible description of that field's control.
111
+ *
112
+ * A field owns its control's `aria-describedby`: it is the only thing that
113
+ * knows which element the description belongs on, and it already writes the
114
+ * entry for its own error region. Content the author slotted into the field
115
+ * cannot write that attribute itself without becoming a second owner of it, and
116
+ * it cannot be wired by the field either, because a slotted custom element
117
+ * renders after the field has mounted and has nothing to point at when the
118
+ * field looks.
119
+ *
120
+ * So the content asks, once it has something to offer. `describable(el)`
121
+ * answers the nearest ancestor that accepts a description, and the caller hands
122
+ * its element to that ancestor's `describedBy`, which answers whether it was
123
+ * taken. Nothing here names a field or a tooltip: the relation is expressed as
124
+ * a capability, so the two ends need not import each other, which matters
125
+ * because the library's own arrow runs from the forms to the disclosures.
126
+ *
127
+ * The lookup lives here rather than at its one call site so the protocol has a
128
+ * name, a place to be documented and a single definition to change.
129
+ */
130
+ /**
131
+ * @typedef {{ describedBy(el: HTMLElement): boolean }} Describable
132
+ */
133
+ /**
134
+ * The nearest ancestor of `el` that accepts elements into the description of
135
+ * whatever it considers its control, or null when nothing in the ancestry does.
136
+ * @param {Element} el
137
+ * @returns {(Element & Describable) | null}
138
+ */
139
+ declare const describable: (el: Element) => (Element & Describable) | null;
105
140
  /**
106
141
  * Sleeping, debouncing and throttling. Debounce and throttle both return the
107
142
  * wrapped function together with a cancel function.
@@ -226,6 +261,34 @@ declare class Field extends ParsedElement {
226
261
  /** the role the element internals carry, 'presentation' unless the control is its own */
227
262
  static ROLE: string;
228
263
  constructor();
264
+ /**
265
+ * Adds an element to the accessible description of the field's control and
266
+ * answers whether the field took it.
267
+ *
268
+ * A field takes one whenever it is offered, before its own render as
269
+ * readily as after: content slotted into a field is a custom element of its
270
+ * own and may upgrade on either side of the field it stands in, which
271
+ * happens in both directions in practice, a tooltip beating an async select
272
+ * to its render while losing to a plain input. A description handed over
273
+ * early waits here and is written the moment the field has somewhere to
274
+ * write it, so the caller never has to know the order.
275
+ *
276
+ * The reference lands on the element handed over rather than on a wrapper
277
+ * around it: a hidden element is included in a description only where it is
278
+ * named directly, and content that reaches the description through a
279
+ * wrapper is skipped while it is hidden. A popover closed until someone
280
+ * opens it is exactly that, so the caller passes the popover itself.
281
+ *
282
+ * An attribute rather than `ariaDescribedByElements`: the property reflects
283
+ * to nothing, so the description would live in the accessibility tree alone
284
+ * and vanish entirely on a browser without aria element reflection.
285
+ *
286
+ * This is the field's half of the description protocol; `describable` in
287
+ * `ful/descriptions.mjs` is the half the content uses to find the field.
288
+ * @param {HTMLElement} el
289
+ * @returns {boolean}
290
+ */
291
+ describedBy(el: HTMLElement): boolean;
229
292
  focus(options: any): void;
230
293
  /**
231
294
  * Clears or reports one validation problem: the text lands on the field's
@@ -336,8 +399,9 @@ declare class Field extends ParsedElement {
336
399
  * three claims reach it
337
400
  * - `error` is the field's live region
338
401
  * - `label`, when given, names the control and focuses it on click
339
- * - `described` moves the error's description off the control and onto
340
- * another element, the host where no single control can carry it
402
+ * - `described` moves the description off the control and onto another
403
+ * element, the host where no single control can carry it: the error
404
+ * region and anything `describedBy` is later handed both land there
341
405
  * - `claims` moves the three claims onto a wrapper the field disables as a
342
406
  * whole, leaving focus and aria on the control
343
407
  * - `announces` is the element whose role carries `aria-readonly` and
@@ -539,6 +603,52 @@ declare class InputFile extends Input {
539
603
  get dropzone(): any;
540
604
  set dropzone(v: any);
541
605
  }
606
+ /**
607
+ * CSS anchor positioning for a popover and the invoker it belongs to, with the
608
+ * hand-placed fallback for the platforms that do not have it.
609
+ */
610
+ declare class Anchors {
611
+ /**
612
+ * Anchors a popover to its invoker.
613
+ *
614
+ * The invoker is given an `anchor-name` and the popover a `position-anchor`
615
+ * pointing at it, which is what a stylesheet needs to place the popover
616
+ * itself: the library's own menus say `top: anchor(bottom); left:
617
+ * anchor(left)`. **Writing that css is the caller's half of this.** Without
618
+ * it the popover lands wherever the user agent puts a popover, which is not
619
+ * beside the invoker.
620
+ *
621
+ * Where the platform has no anchor positioning the popover is placed here
622
+ * instead, beside the invoker whenever it opens, clamped into the viewport,
623
+ * following it on scroll and resize, and cleaned up on close. That placement
624
+ * draws the geometry the css above describes, so the two agree.
625
+ *
626
+ * @param {HTMLElement} invoker the element the popover belongs to
627
+ * @param {HTMLElement} popover the `[popover]` element to place
628
+ * @param {object} [options]
629
+ * @param {string} [options.prefix] prefixes the generated anchor name and id,
630
+ * so the dom says which component a name belongs to
631
+ * @param {boolean} [options.invoke] points the invoker's `popovertarget` at
632
+ * the popover, giving toggle and light dismiss with no script of your own
633
+ * @param {boolean} [options.expanded] keeps the invoker's `aria-expanded` in
634
+ * step with the popover
635
+ * @param {boolean} [options.stretch] widens the popover to its invoker, which
636
+ * is what a combobox dropdown wants
637
+ * @param {boolean} [options.handPlace] places here on every platform rather
638
+ * than only as a fallback, which a popover asks for when it needs to know
639
+ * where its invoker ended up: the tooltip's note points a callout at it, and
640
+ * a pseudo-element cannot read an anchor outside its own containing block.
641
+ * Such a popover declares no anchor placement in css, there being none to
642
+ * agree with
643
+ */
644
+ static wire(invoker: HTMLElement, popover: HTMLElement, { prefix, invoke, expanded, stretch, handPlace }?: {
645
+ prefix?: string;
646
+ invoke?: boolean;
647
+ expanded?: boolean;
648
+ stretch?: boolean;
649
+ handPlace?: boolean;
650
+ }): void;
651
+ }
542
652
  /**
543
653
  * Fetches a select's whole vocabulary from a url and serves every later read
544
654
  * from it. Concurrent callers share one request, the options may be cached in
@@ -959,8 +1069,24 @@ declare class BooleanFilter extends Field {
959
1069
  get disabled(): boolean;
960
1070
  set disabled(d: boolean);
961
1071
  }
962
- /** An info icon button toggling a popover with a short explanation. */
1072
+ /**
1073
+ * An info icon button toggling a popover with a short explanation.
1074
+ *
1075
+ * The marker is the page's `config.icon`, and the `icon` attribute names a
1076
+ * `ful-icon` for the tooltip that means something other than plain information:
1077
+ * a caveat, a warning, a setting. A name the library does not paint is the
1078
+ * page's own, declared as `ful-icon[name='...'] { mask-image: ... }`.
1079
+ *
1080
+ * `describes` is for the tooltip standing in a field: the note becomes part of
1081
+ * the accessible description of that field's control, so it is announced on
1082
+ * reaching the field rather than only on opening the marker, and the marker
1083
+ * leaves the tab order, so a form of hinted fields costs no extra keystrokes to
1084
+ * walk. The marker stays clickable, and stays a tab stop wherever the note was
1085
+ * not taken, a tooltip claiming `describes` outside a field among them: the
1086
+ * stop only goes where something else delivers the content.
1087
+ */
963
1088
  declare class Tooltip extends ParsedElement {
1089
+ #private;
964
1090
  static slots: boolean;
965
1091
  static attributes: string[];
966
1092
  static config: {
@@ -971,7 +1097,37 @@ declare class Tooltip extends ParsedElement {
971
1097
  slots: any;
972
1098
  }): void;
973
1099
  }
974
- /** A modal dialog on the native platform, open()/ask() resolving with the closer's data-result. */
1100
+ export type DialogOutcome = {
1101
+ dismissed: boolean;
1102
+ result: string | null;
1103
+ response: any;
1104
+ };
1105
+ /**
1106
+ * A modal dialog on the native platform, open()/ask() resolving with the
1107
+ * closer's data-result.
1108
+ *
1109
+ * The header carries a close button, as the drawer's does: Escape dismisses a
1110
+ * modal on its own, but nothing says so, and a dialog whose only exit is a key
1111
+ * you have to know about leaves a pointer with nowhere to go. It answers the way
1112
+ * Escape does, with null.
1113
+ *
1114
+ * `requires-answer` is for the dialog that must be answered: the close button is not
1115
+ * rendered and Escape is refused, so the only way out is a button that carries a
1116
+ * result. It has to be both, a close button withheld while Escape still worked
1117
+ * being decoration rather than a rule.
1118
+ *
1119
+ * The chrome is reachable by class as well as by tag, so a plain `<dialog
1120
+ * class="ful-dialog">` written by a page gets the same look whatever its
1121
+ * structure: the tag form matches a direct child, and `ful-dialog-header`,
1122
+ * `ful-dialog-body` and `ful-dialog-footer` match at any depth, which is what a
1123
+ * dialog whose content is wrapped in a form needs.
1124
+ */
1125
+ /**
1126
+ * How a dialog ended: `dismissed` tells a cancel from an answer, `result` carries
1127
+ * the `data-result` of the button that closed it and `response` what a submit
1128
+ * answered with, the one that did not happen being null.
1129
+ * @typedef {{ dismissed: boolean, result: string|null, response: any }} DialogOutcome
1130
+ */
975
1131
  declare class Dialog extends ParsedElement {
976
1132
  #private;
977
1133
  static attributes: string[];
@@ -983,15 +1139,31 @@ declare class Dialog extends ParsedElement {
983
1139
  disconnectedCallback(): void;
984
1140
  open(): Promise<any>;
985
1141
  ask(): Promise<any>;
1142
+ /**
1143
+ * Opens the dialog and waits for the callback, as `ful-drawer`'s does: a
1144
+ * resolved value paints the body (which is returned), a rejection paints the
1145
+ * problems and travels to the caller, and an update superseded by a newer one
1146
+ * paints nothing. The title is the `header` attribute, configuration like the
1147
+ * rest of the dialog's chrome, so what update() owns is the body alone.
1148
+ */
1149
+ update(cb: any): Promise<any>;
986
1150
  /**
987
1151
  * Re-fires section:requested on the body, open or closed: the explicit
988
1152
  * request for a body that wants refreshing. A failed refresh paints its
989
- * problems, nothing rejects: there is no caller to reject towards.
1153
+ * problems, nothing rejects: update() stays the rejecting call.
990
1154
  */
991
1155
  refresh(): Promise<any[] | undefined>;
992
1156
  close(result: any): void;
993
1157
  }
994
- /** A side panel drawer on the native dialog platform, update() owning its open-deliver cycle. */
1158
+ /**
1159
+ * A side panel drawer on the native dialog platform, update() owning its
1160
+ * open-deliver cycle.
1161
+ *
1162
+ * The `header` slot is content beside the title, before it: an icon, a badge, a
1163
+ * status. It sits outside the heading rather than in it because `update()` sets
1164
+ * the title through `textContent`, which would take anything nested there with
1165
+ * it.
1166
+ */
995
1167
  declare class Drawer extends ParsedElement {
996
1168
  #private;
997
1169
  static attributes: string[];
@@ -1141,6 +1313,6 @@ declare class Plugin {
1141
1313
  });
1142
1314
  configure(registry: any): void;
1143
1315
  }
1144
- export { Accordion, 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 };
1316
+ 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, describable };
1145
1317
 
1146
1318
  export as namespace ful;