@optionfactory/fml 9.0.0-rc2 → 9.0.0-rc3
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 +2 -3
- package/dist/custom-elements.json +4 -0
- package/dist/fml.css +1 -1
- package/dist/fml.css.map +1 -1
- package/dist/fml.iife.js +159 -75
- 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/ful.css +1 -1
- package/dist/ful.css.map +1 -1
- package/dist/ful.d.mts +56 -2
- package/dist/ful.iife.js +158 -75
- 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 +158 -76
- package/dist/ful.mjs.map +1 -1
- package/dist/web-types.json +5 -1
- package/package.json +1 -1
package/dist/ful.d.mts
CHANGED
|
@@ -539,6 +539,52 @@ declare class InputFile extends Input {
|
|
|
539
539
|
get dropzone(): any;
|
|
540
540
|
set dropzone(v: any);
|
|
541
541
|
}
|
|
542
|
+
/**
|
|
543
|
+
* CSS anchor positioning for a popover and the invoker it belongs to, with the
|
|
544
|
+
* hand-placed fallback for the platforms that do not have it.
|
|
545
|
+
*/
|
|
546
|
+
declare class Anchors {
|
|
547
|
+
/**
|
|
548
|
+
* Anchors a popover to its invoker.
|
|
549
|
+
*
|
|
550
|
+
* The invoker is given an `anchor-name` and the popover a `position-anchor`
|
|
551
|
+
* pointing at it, which is what a stylesheet needs to place the popover
|
|
552
|
+
* itself: the library's own menus say `top: anchor(bottom); left:
|
|
553
|
+
* anchor(left)`. **Writing that css is the caller's half of this.** Without
|
|
554
|
+
* it the popover lands wherever the user agent puts a popover, which is not
|
|
555
|
+
* beside the invoker.
|
|
556
|
+
*
|
|
557
|
+
* Where the platform has no anchor positioning the popover is placed here
|
|
558
|
+
* instead, beside the invoker whenever it opens, clamped into the viewport,
|
|
559
|
+
* following it on scroll and resize, and cleaned up on close. That placement
|
|
560
|
+
* draws the geometry the css above describes, so the two agree.
|
|
561
|
+
*
|
|
562
|
+
* @param {HTMLElement} invoker the element the popover belongs to
|
|
563
|
+
* @param {HTMLElement} popover the `[popover]` element to place
|
|
564
|
+
* @param {object} [options]
|
|
565
|
+
* @param {string} [options.prefix] prefixes the generated anchor name and id,
|
|
566
|
+
* so the dom says which component a name belongs to
|
|
567
|
+
* @param {boolean} [options.invoke] points the invoker's `popovertarget` at
|
|
568
|
+
* the popover, giving toggle and light dismiss with no script of your own
|
|
569
|
+
* @param {boolean} [options.expanded] keeps the invoker's `aria-expanded` in
|
|
570
|
+
* step with the popover
|
|
571
|
+
* @param {boolean} [options.stretch] widens the popover to its invoker, which
|
|
572
|
+
* is what a combobox dropdown wants
|
|
573
|
+
* @param {boolean} [options.handPlace] places here on every platform rather
|
|
574
|
+
* than only as a fallback, which a popover asks for when it needs to know
|
|
575
|
+
* where its invoker ended up: the tooltip's note points a callout at it, and
|
|
576
|
+
* a pseudo-element cannot read an anchor outside its own containing block.
|
|
577
|
+
* Such a popover declares no anchor placement in css, there being none to
|
|
578
|
+
* agree with
|
|
579
|
+
*/
|
|
580
|
+
static wire(invoker: HTMLElement, popover: HTMLElement, { prefix, invoke, expanded, stretch, handPlace }?: {
|
|
581
|
+
prefix?: string;
|
|
582
|
+
invoke?: boolean;
|
|
583
|
+
expanded?: boolean;
|
|
584
|
+
stretch?: boolean;
|
|
585
|
+
handPlace?: boolean;
|
|
586
|
+
}): void;
|
|
587
|
+
}
|
|
542
588
|
/**
|
|
543
589
|
* Fetches a select's whole vocabulary from a url and serves every later read
|
|
544
590
|
* from it. Concurrent callers share one request, the options may be cached in
|
|
@@ -991,7 +1037,15 @@ declare class Dialog extends ParsedElement {
|
|
|
991
1037
|
refresh(): Promise<any[] | undefined>;
|
|
992
1038
|
close(result: any): void;
|
|
993
1039
|
}
|
|
994
|
-
/**
|
|
1040
|
+
/**
|
|
1041
|
+
* A side panel drawer on the native dialog platform, update() owning its
|
|
1042
|
+
* open-deliver cycle.
|
|
1043
|
+
*
|
|
1044
|
+
* The `header` slot is content beside the title, before it: an icon, a badge, a
|
|
1045
|
+
* status. It sits outside the heading rather than in it because `update()` sets
|
|
1046
|
+
* the title through `textContent`, which would take anything nested there with
|
|
1047
|
+
* it.
|
|
1048
|
+
*/
|
|
995
1049
|
declare class Drawer extends ParsedElement {
|
|
996
1050
|
#private;
|
|
997
1051
|
static attributes: string[];
|
|
@@ -1141,6 +1195,6 @@ declare class Plugin {
|
|
|
1141
1195
|
});
|
|
1142
1196
|
configure(registry: any): void;
|
|
1143
1197
|
}
|
|
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 };
|
|
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 };
|
|
1145
1199
|
|
|
1146
1200
|
export as namespace ful;
|
package/dist/ful.iife.js
CHANGED
|
@@ -681,12 +681,16 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
681
681
|
//the error region describes the control, or the host where there is no
|
|
682
682
|
//single control to describe (a radio group's legend names its fieldset)
|
|
683
683
|
if (error) {
|
|
684
|
-
|
|
684
|
+
//an attribute, not the aria element property: the property reflects to
|
|
685
|
+
//nothing, so the description lived in the accessibility tree alone and
|
|
686
|
+
//vanished entirely on a browser without aria element reflection
|
|
687
|
+
if (!error.id) {
|
|
688
|
+
error.id = index_mjs.Attributes.uid('ful-field-error');
|
|
689
|
+
}
|
|
690
|
+
(described ?? control).setAttribute('aria-describedby', error.id);
|
|
685
691
|
}
|
|
686
692
|
if (label) {
|
|
687
|
-
|
|
688
|
-
//a label that does not natively target the control still focuses it
|
|
689
|
-
label.addEventListener('click', () => this.focus());
|
|
693
|
+
Field.#name(this, label, control);
|
|
690
694
|
}
|
|
691
695
|
//the platform's implicit submission, stood in for where the field's own
|
|
692
696
|
//protocol took it away: the inner controls carry form="", so Enter in one
|
|
@@ -775,6 +779,49 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
775
779
|
}),
|
|
776
780
|
);
|
|
777
781
|
}
|
|
782
|
+
/** The html elements a label's `for` may point at, `input[type=hidden]` excepted. */
|
|
783
|
+
static #LABELABLE = new Set(['BUTTON', 'INPUT', 'METER', 'OUTPUT', 'PROGRESS', 'SELECT', 'TEXTAREA']);
|
|
784
|
+
/**
|
|
785
|
+
* Names the control from the field's label, natively wherever the platform
|
|
786
|
+
* allows it.
|
|
787
|
+
*
|
|
788
|
+
* `for` and `id` are the form the dom itself carries, so the association is
|
|
789
|
+
* there for anything reading the markup rather than the accessibility tree:
|
|
790
|
+
* an audit tool, the browser's autofill, a translation pass. It also makes
|
|
791
|
+
* the label's click reach the control the way it does in a plain form, which
|
|
792
|
+
* is focus for a text control and activation for a checkbox, so the field
|
|
793
|
+
* needs no handler of its own.
|
|
794
|
+
*
|
|
795
|
+
* A control the platform will not let a label target, a composite carrying
|
|
796
|
+
* `role="radiogroup"` among them, takes `aria-labelledby` instead. That is an
|
|
797
|
+
* attribute too, so the association is equally visible; what it does not carry
|
|
798
|
+
* is the label's click, which is why the handler stays on that path only.
|
|
799
|
+
*
|
|
800
|
+
* Neither branch uses `ariaLabelledByElements`. The property reflects to no
|
|
801
|
+
* attribute, so the name lived in the accessibility tree alone: nothing reading
|
|
802
|
+
* the dom saw it, and on a browser without aria element reflection the
|
|
803
|
+
* assignment is a silent expando and the field has no name at all.
|
|
804
|
+
* @param {any} field
|
|
805
|
+
* @param {HTMLElement} label
|
|
806
|
+
* @param {any} control
|
|
807
|
+
*/
|
|
808
|
+
static #name(field, label, control) {
|
|
809
|
+
const labelable =
|
|
810
|
+
Field.#LABELABLE.has(control.tagName) && control.getAttribute('type') !== 'hidden';
|
|
811
|
+
if (!labelable) {
|
|
812
|
+
if (!label.id) {
|
|
813
|
+
label.id = index_mjs.Attributes.uid('ful-label');
|
|
814
|
+
}
|
|
815
|
+
control.setAttribute('aria-labelledby', label.id);
|
|
816
|
+
//aria-labelledby carries the name but not the label's click
|
|
817
|
+
label.addEventListener('click', () => field.focus());
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
if (!control.id) {
|
|
821
|
+
control.id = index_mjs.Attributes.uid('ful-control');
|
|
822
|
+
}
|
|
823
|
+
label.setAttribute('for', control.id);
|
|
824
|
+
}
|
|
778
825
|
/**
|
|
779
826
|
* Whether the field's chrome should answer a gesture. Badges, dropzones,
|
|
780
827
|
* menus and labels are not form controls, so their handlers must ask the
|
|
@@ -1964,8 +2011,14 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
1964
2011
|
const box = invoker.getBoundingClientRect();
|
|
1965
2012
|
const here = popover.getBoundingClientRect();
|
|
1966
2013
|
//against the padding box, which is what a percentage inset resolves against
|
|
1967
|
-
popover.style.setProperty(
|
|
1968
|
-
|
|
2014
|
+
popover.style.setProperty(
|
|
2015
|
+
'--ful-note-callout-inline',
|
|
2016
|
+
`${box.left + box.width / 2 - here.left - popover.clientLeft}px`,
|
|
2017
|
+
);
|
|
2018
|
+
popover.style.setProperty(
|
|
2019
|
+
'--ful-note-callout-block',
|
|
2020
|
+
`${box.top + box.height / 2 - here.top - popover.clientTop}px`,
|
|
2021
|
+
);
|
|
1969
2022
|
};
|
|
1970
2023
|
|
|
1971
2024
|
const place = (popover, anchored) => {
|
|
@@ -2069,67 +2122,93 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
2069
2122
|
};
|
|
2070
2123
|
|
|
2071
2124
|
/**
|
|
2072
|
-
*
|
|
2073
|
-
*
|
|
2074
|
-
* invoker whenever it opens, stretched to the invoker's width when
|
|
2075
|
-
* asked, and cleaned up when it closes. Where the css works the call
|
|
2076
|
-
* is a no-op.
|
|
2077
|
-
*
|
|
2078
|
-
* `handPlace` takes the placement here on every platform, which a popover
|
|
2079
|
-
* asks for when it needs to know where its invoker ended up: the note's
|
|
2080
|
-
* callout points at the invoker, and a pseudo-element cannot read an anchor
|
|
2081
|
-
* that is not inside its own containing block, so the note is measured rather
|
|
2082
|
-
* than placed by the css. Its stylesheet declares no position-area to match.
|
|
2125
|
+
* CSS anchor positioning for a popover and the invoker it belongs to, with the
|
|
2126
|
+
* hand-placed fallback for the platforms that do not have it.
|
|
2083
2127
|
*/
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2128
|
+
class Anchors {
|
|
2129
|
+
/**
|
|
2130
|
+
* Anchors a popover to its invoker.
|
|
2131
|
+
*
|
|
2132
|
+
* The invoker is given an `anchor-name` and the popover a `position-anchor`
|
|
2133
|
+
* pointing at it, which is what a stylesheet needs to place the popover
|
|
2134
|
+
* itself: the library's own menus say `top: anchor(bottom); left:
|
|
2135
|
+
* anchor(left)`. **Writing that css is the caller's half of this.** Without
|
|
2136
|
+
* it the popover lands wherever the user agent puts a popover, which is not
|
|
2137
|
+
* beside the invoker.
|
|
2138
|
+
*
|
|
2139
|
+
* Where the platform has no anchor positioning the popover is placed here
|
|
2140
|
+
* instead, beside the invoker whenever it opens, clamped into the viewport,
|
|
2141
|
+
* following it on scroll and resize, and cleaned up on close. That placement
|
|
2142
|
+
* draws the geometry the css above describes, so the two agree.
|
|
2143
|
+
*
|
|
2144
|
+
* @param {HTMLElement} invoker the element the popover belongs to
|
|
2145
|
+
* @param {HTMLElement} popover the `[popover]` element to place
|
|
2146
|
+
* @param {object} [options]
|
|
2147
|
+
* @param {string} [options.prefix] prefixes the generated anchor name and id,
|
|
2148
|
+
* so the dom says which component a name belongs to
|
|
2149
|
+
* @param {boolean} [options.invoke] points the invoker's `popovertarget` at
|
|
2150
|
+
* the popover, giving toggle and light dismiss with no script of your own
|
|
2151
|
+
* @param {boolean} [options.expanded] keeps the invoker's `aria-expanded` in
|
|
2152
|
+
* step with the popover
|
|
2153
|
+
* @param {boolean} [options.stretch] widens the popover to its invoker, which
|
|
2154
|
+
* is what a combobox dropdown wants
|
|
2155
|
+
* @param {boolean} [options.handPlace] places here on every platform rather
|
|
2156
|
+
* than only as a fallback, which a popover asks for when it needs to know
|
|
2157
|
+
* where its invoker ended up: the tooltip's note points a callout at it, and
|
|
2158
|
+
* a pseudo-element cannot read an anchor outside its own containing block.
|
|
2159
|
+
* Such a popover declares no anchor placement in css, there being none to
|
|
2160
|
+
* agree with
|
|
2161
|
+
*/
|
|
2162
|
+
static wire(
|
|
2163
|
+
invoker,
|
|
2164
|
+
popover,
|
|
2165
|
+
{ prefix = 'ful-anchor', invoke = false, expanded = false, stretch = false, handPlace = false } = {},
|
|
2166
|
+
) {
|
|
2167
|
+
const uid = index_mjs.Attributes.uid(prefix);
|
|
2168
|
+
if (invoke) {
|
|
2169
|
+
//popovertarget needs a target that can be named
|
|
2170
|
+
popover.id = popover.id || uid;
|
|
2171
|
+
invoker.setAttribute('popovertarget', popover.id);
|
|
2172
|
+
}
|
|
2173
|
+
const anchor = `--${uid}`;
|
|
2174
|
+
invoker.style.anchorName = anchor;
|
|
2175
|
+
popover.style.positionAnchor = anchor;
|
|
2176
|
+
if (expanded) {
|
|
2177
|
+
invoker.setAttribute('aria-expanded', 'false');
|
|
2178
|
+
popover.addEventListener('toggle', (/** @type any */ evt) => {
|
|
2179
|
+
invoker.setAttribute('aria-expanded', evt.newState === 'open' ? 'true' : 'false');
|
|
2180
|
+
});
|
|
2181
|
+
}
|
|
2182
|
+
//the naming above is what the stylesheet reads, so it happens either way:
|
|
2183
|
+
//only the hand placement below is the fallback, and only for a popover that
|
|
2184
|
+
//did not ask to be placed here whatever the platform offers
|
|
2185
|
+
if (!handPlace && platformAnchors()) {
|
|
2186
|
+
return;
|
|
2187
|
+
}
|
|
2188
|
+
const anchored = { invoker, stretch };
|
|
2189
|
+
popover.addEventListener('beforetoggle', (/** @type any */ evt) => {
|
|
2190
|
+
//placed before the showing, refined once laid out: the platform's
|
|
2191
|
+
//centered or corner spot never paints
|
|
2192
|
+
if (evt.newState === 'open') {
|
|
2193
|
+
place(popover, anchored);
|
|
2194
|
+
}
|
|
2195
|
+
});
|
|
2100
2196
|
popover.addEventListener('toggle', (/** @type any */ evt) => {
|
|
2101
|
-
|
|
2197
|
+
if (evt.newState === 'open') {
|
|
2198
|
+
open.set(popover, anchored);
|
|
2199
|
+
place(popover, anchored);
|
|
2200
|
+
} else {
|
|
2201
|
+
open.delete(popover);
|
|
2202
|
+
unplace(popover);
|
|
2203
|
+
}
|
|
2102
2204
|
});
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
if (!handPlace && platformAnchors()) {
|
|
2108
|
-
return;
|
|
2109
|
-
}
|
|
2110
|
-
const anchored = { invoker, stretch };
|
|
2111
|
-
popover.addEventListener('beforetoggle', (/** @type any */ evt) => {
|
|
2112
|
-
//placed before the showing, refined once laid out: the platform's
|
|
2113
|
-
//centered or corner spot never paints
|
|
2114
|
-
if (evt.newState === 'open') {
|
|
2115
|
-
place(popover, anchored);
|
|
2116
|
-
}
|
|
2117
|
-
});
|
|
2118
|
-
popover.addEventListener('toggle', (/** @type any */ evt) => {
|
|
2119
|
-
if (evt.newState === 'open') {
|
|
2120
|
-
open.set(popover, anchored);
|
|
2121
|
-
place(popover, anchored);
|
|
2122
|
-
} else {
|
|
2123
|
-
open.delete(popover);
|
|
2124
|
-
unplace(popover);
|
|
2205
|
+
if (!reflowWired) {
|
|
2206
|
+
reflowWired = true;
|
|
2207
|
+
document.addEventListener('scroll', schedule, true);
|
|
2208
|
+
window.addEventListener('resize', schedule);
|
|
2125
2209
|
}
|
|
2126
|
-
});
|
|
2127
|
-
if (!reflowWired) {
|
|
2128
|
-
reflowWired = true;
|
|
2129
|
-
document.addEventListener('scroll', schedule, true);
|
|
2130
|
-
window.addEventListener('resize', schedule);
|
|
2131
2210
|
}
|
|
2132
|
-
}
|
|
2211
|
+
}
|
|
2133
2212
|
|
|
2134
2213
|
/**
|
|
2135
2214
|
* Fetches a select's whole vocabulary from a url and serves every later read
|
|
@@ -2658,7 +2737,7 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
2658
2737
|
});
|
|
2659
2738
|
//each pair carries its own anchor: two selects on a page must not share one
|
|
2660
2739
|
const group = fragment.querySelector('ful-control-group');
|
|
2661
|
-
|
|
2740
|
+
Anchors.wire(group, this.#ddmenu, { prefix: 'ful-select', stretch: true });
|
|
2662
2741
|
[this.#dload, this.#abortdload] = Timing.throttle(400, () => this.#open());
|
|
2663
2742
|
this.#wireChrome();
|
|
2664
2743
|
this.#wireChips();
|
|
@@ -3248,16 +3327,10 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
3248
3327
|
evt.stopPropagation();
|
|
3249
3328
|
this._notifyChange();
|
|
3250
3329
|
});
|
|
3330
|
+
//the base points the label at the input with for/id, so the click toggles
|
|
3331
|
+
//the way it does in a plain form: the input's own change listener above
|
|
3332
|
+
//carries the notification, and readonly is refused by the freeze below
|
|
3251
3333
|
const label = fragment.querySelector('label');
|
|
3252
|
-
//the label neither wraps the input nor targets it, so the toggle is the
|
|
3253
|
-
//field's; the base adds the focus
|
|
3254
|
-
label.addEventListener('click', () => {
|
|
3255
|
-
if (!this._interactive()) {
|
|
3256
|
-
return;
|
|
3257
|
-
}
|
|
3258
|
-
this.value = !this.value;
|
|
3259
|
-
this._notifyChange();
|
|
3260
|
-
});
|
|
3261
3334
|
//a checkbox has no editable text to preserve, so readonly freezes the
|
|
3262
3335
|
//whole choice, label click included: the container is the frozen piece
|
|
3263
3336
|
return {
|
|
@@ -4036,7 +4109,7 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
4036
4109
|
#wire() {
|
|
4037
4110
|
const button = this.#button;
|
|
4038
4111
|
const menu = this.#menu;
|
|
4039
|
-
|
|
4112
|
+
Anchors.wire(button, menu, { prefix: 'ful-filter-menu', invoke: true, expanded: true });
|
|
4040
4113
|
menu.addEventListener('toggle', (/** @type any */ evt) => {
|
|
4041
4114
|
if (evt.newState !== 'open') {
|
|
4042
4115
|
//give the invoker back the focus the menu had borrowed, without
|
|
@@ -4635,7 +4708,7 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
4635
4708
|
//placed here rather than by the anchor css: the note draws a callout that
|
|
4636
4709
|
//has to point at the trigger wherever the viewport left room for the note,
|
|
4637
4710
|
//which is a measurement the stylesheet cannot make for a pseudo-element
|
|
4638
|
-
|
|
4711
|
+
Anchors.wire(trigger, content, { prefix: 'ful-tooltip', invoke: true, expanded: true, handPlace: true });
|
|
4639
4712
|
const placement = this.declared('placement');
|
|
4640
4713
|
if (placement) {
|
|
4641
4714
|
content.setAttribute('placement', placement);
|
|
@@ -4727,13 +4800,22 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
4727
4800
|
}
|
|
4728
4801
|
}
|
|
4729
4802
|
|
|
4730
|
-
/**
|
|
4803
|
+
/**
|
|
4804
|
+
* A side panel drawer on the native dialog platform, update() owning its
|
|
4805
|
+
* open-deliver cycle.
|
|
4806
|
+
*
|
|
4807
|
+
* The `header` slot is content beside the title, before it: an icon, a badge, a
|
|
4808
|
+
* status. It sits outside the heading rather than in it because `update()` sets
|
|
4809
|
+
* the title through `textContent`, which would take anything nested there with
|
|
4810
|
+
* it.
|
|
4811
|
+
*/
|
|
4731
4812
|
class Drawer extends index_mjs.ParsedElement {
|
|
4732
4813
|
static attributes = ['title', 'placement'];
|
|
4733
4814
|
static slots = true;
|
|
4734
4815
|
static template = `
|
|
4735
4816
|
<dialog data-ref="dialog" class="ful-drawer">
|
|
4736
4817
|
<header>
|
|
4818
|
+
{{{{ slots.header }}}}
|
|
4737
4819
|
<h2 data-ref="title">{{ title }}</h2>
|
|
4738
4820
|
<button type="button" data-ref="close" data-tpl-aria-label="#l10n:t('drawer.close')"><ful-icon name="x-lg" aria-hidden="true"></ful-icon></button>
|
|
4739
4821
|
</header>
|
|
@@ -5474,6 +5556,7 @@ var ful = (function (exports, index_mjs, index_mjs$1) {
|
|
|
5474
5556
|
}
|
|
5475
5557
|
|
|
5476
5558
|
exports.Accordion = Accordion;
|
|
5559
|
+
exports.Anchors = Anchors;
|
|
5477
5560
|
exports.AsyncEvents = AsyncEvents;
|
|
5478
5561
|
exports.Bindings = Bindings;
|
|
5479
5562
|
exports.BooleanFilter = BooleanFilter;
|