@optionfactory/ful 4.0.13 → 4.0.15
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.css +1 -1
- package/dist/ful.css.map +1 -1
- package/dist/ful.iife.js +101 -148
- 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 +101 -148
- package/dist/ful.mjs.map +1 -1
- package/package.json +1 -1
package/dist/ful.mjs
CHANGED
|
@@ -1461,7 +1461,7 @@ class Input extends ParsedElement {
|
|
|
1461
1461
|
_fragment(type, slots) {
|
|
1462
1462
|
return this.template().withOverlay({ type, slots }).render();
|
|
1463
1463
|
}
|
|
1464
|
-
render({ slots, observed, disabled }) {
|
|
1464
|
+
render({ slots, observed, disabled, skipValueSetup }) {
|
|
1465
1465
|
const type = this._type();
|
|
1466
1466
|
const fragment = this._fragment(type, slots);
|
|
1467
1467
|
this._input = fragment.querySelector("input,textarea");
|
|
@@ -1469,7 +1469,9 @@ class Input extends ParsedElement {
|
|
|
1469
1469
|
Attributes.forward('input-', this, this._input);
|
|
1470
1470
|
this.disabled = disabled;
|
|
1471
1471
|
this.readonly = observed.readonly;
|
|
1472
|
-
|
|
1472
|
+
if(!skipValueSetup){
|
|
1473
|
+
this.value = observed.value;
|
|
1474
|
+
}
|
|
1473
1475
|
|
|
1474
1476
|
this._input.addEventListener('change', (evt) => {
|
|
1475
1477
|
evt.stopPropagation();
|
|
@@ -1724,24 +1726,24 @@ class InputFile extends Input {
|
|
|
1724
1726
|
<div data-ref="dropzone" class="dropzone" data-tpl-if="!slots.dropzone">
|
|
1725
1727
|
{{ #l10n:t('dropzonelabel') }}
|
|
1726
1728
|
</div>
|
|
1727
|
-
<
|
|
1729
|
+
<ful-item-list></ful-item-list>
|
|
1728
1730
|
<ful-field-warnings></ful-field-warnings>
|
|
1729
1731
|
<ful-field-error></ful-field-error>
|
|
1730
1732
|
`;
|
|
1731
1733
|
static templates = {
|
|
1732
1734
|
items: `
|
|
1733
|
-
<
|
|
1734
|
-
<div
|
|
1735
|
-
<div
|
|
1736
|
-
<button class="btn btn-sm btn-outline-danger
|
|
1737
|
-
</
|
|
1735
|
+
<ful-item data-tpl-each="files" data-tpl-var="file" data-tpl-data-name="file.name">
|
|
1736
|
+
<div>{{ file.name }}</div>
|
|
1737
|
+
<div>{{ #bytes:format(file.size) }}</div>
|
|
1738
|
+
<button type="button" class="btn btn-sm btn-outline-danger bi bi-x-lg"></button>
|
|
1739
|
+
</ful-item>
|
|
1738
1740
|
`,
|
|
1739
1741
|
warning: `<ful-field-warning>{{ #l10n:t(key, args) }}</ful-field-warning>`
|
|
1740
1742
|
}
|
|
1741
1743
|
render(conf) {
|
|
1742
1744
|
const { observed } = conf;
|
|
1743
1745
|
super.render(conf);
|
|
1744
|
-
this.#items = this.querySelector("
|
|
1746
|
+
this.#items = this.querySelector("ful-item-list");
|
|
1745
1747
|
this.#dropzone = this.querySelector("[data-ref=dropzone]");
|
|
1746
1748
|
this.#warnings = this.querySelector("ful-field-warnings");
|
|
1747
1749
|
this.accept = observed.accept;
|
|
@@ -1757,7 +1759,7 @@ class InputFile extends Input {
|
|
|
1757
1759
|
if (!e.target.closest("button")) {
|
|
1758
1760
|
return;
|
|
1759
1761
|
}
|
|
1760
|
-
const fileName = e.target.closest("
|
|
1762
|
+
const fileName = e.target.closest("ful-item").dataset.name;
|
|
1761
1763
|
const dt = new DataTransfer();
|
|
1762
1764
|
[...this.files].filter(f => f.name !== fileName).forEach(f => dt.items.add(f));
|
|
1763
1765
|
this.files = dt.files;
|
|
@@ -1789,11 +1791,7 @@ class InputFile extends Input {
|
|
|
1789
1791
|
this.#ensureAcceptable();
|
|
1790
1792
|
this.#ensureFileSizes();
|
|
1791
1793
|
this.#ensureTotalSize();
|
|
1792
|
-
|
|
1793
|
-
this.template('items').withOverlay({ files: this.files }).withModule('bytes', { format: this.#formatByteSize }).renderTo(this.#items);
|
|
1794
|
-
}else {
|
|
1795
|
-
this.#items.replaceChildren();
|
|
1796
|
-
}
|
|
1794
|
+
this.template('items').withOverlay({ files: this.files }).withModule('bytes', { format: this.#formatByteSize }).renderTo(this.#items);
|
|
1797
1795
|
}
|
|
1798
1796
|
warning(key, args) {
|
|
1799
1797
|
this.template('warning').withOverlay({ key, args }).renderTo(this.#warnings);
|
|
@@ -1854,7 +1852,7 @@ class InputFile extends Input {
|
|
|
1854
1852
|
set multiple(v) {
|
|
1855
1853
|
this._input.multiple = v;
|
|
1856
1854
|
this.reflect(() => {
|
|
1857
|
-
|
|
1855
|
+
Attributes.toggle(this, "multiple", v);
|
|
1858
1856
|
});
|
|
1859
1857
|
}
|
|
1860
1858
|
get files() {
|
|
@@ -1887,7 +1885,6 @@ class InputFile extends Input {
|
|
|
1887
1885
|
this.reflect(() => {
|
|
1888
1886
|
this.setAttribute('maxfilesize', v);
|
|
1889
1887
|
});
|
|
1890
|
-
|
|
1891
1888
|
}
|
|
1892
1889
|
#maxtotalsize;
|
|
1893
1890
|
get maxtotalsize() {
|
|
@@ -1905,7 +1902,6 @@ class InputFile extends Input {
|
|
|
1905
1902
|
}
|
|
1906
1903
|
set itemlist(v) {
|
|
1907
1904
|
this.#useItemlist = v;
|
|
1908
|
-
Attributes.toggle(this.#items, "hidden", !v);
|
|
1909
1905
|
this.reflect(() => {
|
|
1910
1906
|
Attributes.toggle(this, "itemlist", v);
|
|
1911
1907
|
});
|
|
@@ -1916,7 +1912,6 @@ class InputFile extends Input {
|
|
|
1916
1912
|
}
|
|
1917
1913
|
set dropzone(v) {
|
|
1918
1914
|
this.#useDropzone = v;
|
|
1919
|
-
Attributes.toggle(this.#dropzone, "hidden", !v);
|
|
1920
1915
|
this.reflect(() => {
|
|
1921
1916
|
Attributes.toggle(this, "dropzone", v);
|
|
1922
1917
|
});
|
|
@@ -2145,7 +2140,7 @@ class Dropdown extends ParsedElement {
|
|
|
2145
2140
|
}
|
|
2146
2141
|
|
|
2147
2142
|
class Select extends ParsedElement {
|
|
2148
|
-
static observed = ['value:csvm', 'readonly:presence']
|
|
2143
|
+
static observed = ['value:csvm', 'readonly:presence', 'itemlist:presence']
|
|
2149
2144
|
static slots = true
|
|
2150
2145
|
static template = `
|
|
2151
2146
|
<div class="form-label">
|
|
@@ -2165,8 +2160,17 @@ class Select extends ParsedElement {
|
|
|
2165
2160
|
{{{{ slots.after }}}}
|
|
2166
2161
|
<span data-tpl-if="slots.iafter" class="input-group-text">{{{{ slots.iafter }}}}</span>
|
|
2167
2162
|
</div>
|
|
2163
|
+
<ful-item-list></ful-item-list>
|
|
2168
2164
|
<ful-field-error></ful-field-error>
|
|
2169
2165
|
`;
|
|
2166
|
+
static templates = {
|
|
2167
|
+
items: `
|
|
2168
|
+
<ful-item data-tpl-each="entries" data-tpl-var="entry" data-tpl-data-key="entry[0]">
|
|
2169
|
+
<div>{{ entry[1][0] }}</div>
|
|
2170
|
+
<button type="button" class="btn btn-sm btn-outline-danger bi bi-x-lg"></button>
|
|
2171
|
+
</ful-item>
|
|
2172
|
+
`
|
|
2173
|
+
}
|
|
2170
2174
|
static mappers = {
|
|
2171
2175
|
"csvm": (v, name, el) => {
|
|
2172
2176
|
if (el.hasAttribute("multiple")) {
|
|
@@ -2181,6 +2185,7 @@ class Select extends ParsedElement {
|
|
|
2181
2185
|
#badges
|
|
2182
2186
|
#ddmenu
|
|
2183
2187
|
#input
|
|
2188
|
+
#items;
|
|
2184
2189
|
#multiple
|
|
2185
2190
|
#fieldError
|
|
2186
2191
|
#values = new Map()
|
|
@@ -2196,12 +2201,14 @@ class Select extends ParsedElement {
|
|
|
2196
2201
|
await this.#loader.prefetch?.();
|
|
2197
2202
|
const fragment = this.template().withOverlay({ slots, name }).render();
|
|
2198
2203
|
this.#input = fragment.querySelector('input');
|
|
2204
|
+
this.#items = fragment.querySelector("ful-item-list");
|
|
2199
2205
|
Attributes.forward('input-', this, this.#input);
|
|
2200
2206
|
this.#badges = fragment.querySelector('badges');
|
|
2201
2207
|
|
|
2202
2208
|
this.value = observed.value;
|
|
2203
2209
|
this.disabled = disabled;
|
|
2204
2210
|
this.readonly = observed.readonly;
|
|
2211
|
+
this.itemlist = observed.itemlist;
|
|
2205
2212
|
|
|
2206
2213
|
this.#ddmenu = fragment.querySelector('ful-dropdown');
|
|
2207
2214
|
const label = fragment.querySelector('label');
|
|
@@ -2226,6 +2233,22 @@ class Select extends ParsedElement {
|
|
|
2226
2233
|
this.#input.focus();
|
|
2227
2234
|
dload();
|
|
2228
2235
|
});
|
|
2236
|
+
this.#items.addEventListener('click', (e) => {
|
|
2237
|
+
e.stopPropagation();
|
|
2238
|
+
if (!e.target.closest("button")) {
|
|
2239
|
+
return;
|
|
2240
|
+
}
|
|
2241
|
+
if(this.disabled || this.readonly){
|
|
2242
|
+
return;
|
|
2243
|
+
}
|
|
2244
|
+
const idx = [...this.#items.children].indexOf(e.target.closest('ful-item'));
|
|
2245
|
+
if (idx === -1) {
|
|
2246
|
+
return;
|
|
2247
|
+
}
|
|
2248
|
+
this.#values.delete(Array.from(this.#values.keys()).pop());
|
|
2249
|
+
this.#changed();
|
|
2250
|
+
this.#syncBadges();
|
|
2251
|
+
});
|
|
2229
2252
|
this.#badges.addEventListener('click', (e) => {
|
|
2230
2253
|
e.stopPropagation();
|
|
2231
2254
|
if(this.disabled || this.readonly){
|
|
@@ -2333,6 +2356,8 @@ class Select extends ParsedElement {
|
|
|
2333
2356
|
});
|
|
2334
2357
|
this.#badges.replaceChildren();
|
|
2335
2358
|
this.#badges.append(...badges);
|
|
2359
|
+
this.#items.replaceChildren();
|
|
2360
|
+
this.template('items').withOverlay({ entries: this.#values.entries() }).renderTo(this.#items);
|
|
2336
2361
|
}
|
|
2337
2362
|
set value(vs) {
|
|
2338
2363
|
if(vs === null){
|
|
@@ -2374,6 +2399,16 @@ class Select extends ParsedElement {
|
|
|
2374
2399
|
Attributes.toggle(this, 'readonly', v);
|
|
2375
2400
|
});
|
|
2376
2401
|
}
|
|
2402
|
+
#useItemlist;
|
|
2403
|
+
get itemlist() {
|
|
2404
|
+
return this.#useItemlist;
|
|
2405
|
+
}
|
|
2406
|
+
set itemlist(v) {
|
|
2407
|
+
this.#useItemlist = v;
|
|
2408
|
+
this.reflect(() => {
|
|
2409
|
+
Attributes.toggle(this, "itemlist", v);
|
|
2410
|
+
});
|
|
2411
|
+
}
|
|
2377
2412
|
focus(options) {
|
|
2378
2413
|
this.#input.focus(options);
|
|
2379
2414
|
}
|
|
@@ -3011,15 +3046,16 @@ class Table extends ParsedElement {
|
|
|
3011
3046
|
}
|
|
3012
3047
|
}
|
|
3013
3048
|
|
|
3014
|
-
class InstantFilter extends
|
|
3015
|
-
static observed = [
|
|
3016
|
-
static slots = true;
|
|
3049
|
+
class InstantFilter extends Input {
|
|
3050
|
+
static observed = ['value:json', 'readonly:presence'];
|
|
3017
3051
|
static template = `
|
|
3018
|
-
<div class="form-label"
|
|
3019
|
-
<label>{{{{
|
|
3052
|
+
<div class="form-label">
|
|
3053
|
+
<label>{{{{ slots.default }}}}</label>
|
|
3020
3054
|
{{{{ slots.info }}}}
|
|
3021
3055
|
</div>
|
|
3022
3056
|
<div class="input-group">
|
|
3057
|
+
<span data-tpl-if="slots.ibefore" class="input-group-text">{{{{ slots.ibefore }}}}</span>
|
|
3058
|
+
{{{{ slots.before }}}}
|
|
3023
3059
|
<button data-ref="operator" class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" value="LTE" form="">≼</button>
|
|
3024
3060
|
<ul class="dropdown-menu">
|
|
3025
3061
|
<li><a class="dropdown-item" role="button" value="EQ">=</a></li>
|
|
@@ -3032,32 +3068,21 @@ class InstantFilter extends ParsedElement {
|
|
|
3032
3068
|
</ul>
|
|
3033
3069
|
<input data-ref="value1" type="datetime-local" class="form-control" form="">
|
|
3034
3070
|
<input data-ref="value2" type="datetime-local" class="form-control" form="" hidden>
|
|
3035
|
-
|
|
3071
|
+
{{{{ slots.after }}}}
|
|
3072
|
+
<span data-tpl-if="slots.iafter" class="input-group-text">{{{{ slots.iafter }}}}</span>
|
|
3036
3073
|
</div>
|
|
3037
3074
|
<ful-field-error></ful-field-error>
|
|
3038
3075
|
`;
|
|
3039
|
-
static formAssociated = true;
|
|
3040
3076
|
#operator;
|
|
3041
3077
|
#value1;
|
|
3042
3078
|
#value2;
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
this
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
const name = this.getAttribute("name");
|
|
3051
|
-
const fragment = this.template().withOverlay({ slots, label, name }).render();
|
|
3052
|
-
this.#operator = fragment.querySelector('[data-ref=operator]');
|
|
3053
|
-
this.#value1 = fragment.querySelector('[data-ref=value1]');
|
|
3054
|
-
this.#value2 = fragment.querySelector('[data-ref=value2]');
|
|
3055
|
-
this.#fieldError = fragment.querySelector('ful-field-error');
|
|
3056
|
-
const labelEl = fragment.querySelector('label');
|
|
3057
|
-
labelEl?.addEventListener('click', () => this.focus());
|
|
3058
|
-
this.#value1.ariaDescribedByElements = [this.#fieldError];
|
|
3059
|
-
this.#value1.ariaLabelledByElements = labelEl ? [labelEl] : [];
|
|
3060
|
-
this.replaceChildren(fragment);
|
|
3079
|
+
render(conf) {
|
|
3080
|
+
super.render({...conf, skipValueSetup: true});
|
|
3081
|
+
this.#operator = this.querySelector('[data-ref=operator]');
|
|
3082
|
+
this.#value1 = this.querySelector('[data-ref=value1]');
|
|
3083
|
+
this.#value2 = this.querySelector('[data-ref=value2]');
|
|
3084
|
+
this.value = conf.observed.value;
|
|
3085
|
+
|
|
3061
3086
|
this.addEventListener('click', (evt) => {
|
|
3062
3087
|
const target = /** @type HTMLElement */ (evt.target);
|
|
3063
3088
|
if (!target.matches('ul > li > a')) {
|
|
@@ -3080,42 +3105,25 @@ class InstantFilter extends ParsedElement {
|
|
|
3080
3105
|
if (v === null || v === undefined) {
|
|
3081
3106
|
this.#value1.value = '';
|
|
3082
3107
|
this.#value2.value = '';
|
|
3083
|
-
this.reflect(() => {
|
|
3084
|
-
this.removeAttribute('value');
|
|
3085
|
-
});
|
|
3086
3108
|
return;
|
|
3087
3109
|
}
|
|
3088
3110
|
const [operator, ...values] = v;
|
|
3089
3111
|
this.#operator.setAttribute('value', operator);
|
|
3090
3112
|
this.#value1.value = values[0] ? Instant.isoToLocal(values[0]) : values[0];
|
|
3091
3113
|
this.#value2.value = values[1] ? Instant.isoToLocal(values[1]) : values[1];
|
|
3092
|
-
this.reflect(() => {
|
|
3093
|
-
this.setAttribute('value', JSON.stringify(v));
|
|
3094
|
-
});
|
|
3095
|
-
}
|
|
3096
|
-
focus(options) {
|
|
3097
|
-
this.#value1.focus(options);
|
|
3098
|
-
}
|
|
3099
|
-
setCustomValidity(error) {
|
|
3100
|
-
if (!error) {
|
|
3101
|
-
this.internals.setValidity({});
|
|
3102
|
-
this.#fieldError.innerText = "";
|
|
3103
|
-
return;
|
|
3104
|
-
}
|
|
3105
|
-
this.internals.setValidity({ customError: true }, " ");
|
|
3106
|
-
this.#fieldError.innerText = error;
|
|
3107
3114
|
}
|
|
3108
3115
|
}
|
|
3109
3116
|
|
|
3110
|
-
class LocalDateFilter extends
|
|
3111
|
-
static observed = ["value:json"];
|
|
3112
|
-
static slots = true;
|
|
3117
|
+
class LocalDateFilter extends Input {
|
|
3118
|
+
static observed = ["value:json", 'readonly:presence'];
|
|
3113
3119
|
static template = `
|
|
3114
|
-
<div class="form-label"
|
|
3115
|
-
<label>{{{{
|
|
3120
|
+
<div class="form-label">
|
|
3121
|
+
<label>{{{{ slots.default }}}}</label>
|
|
3116
3122
|
{{{{ slots.info }}}}
|
|
3117
3123
|
</div>
|
|
3118
3124
|
<div class="input-group">
|
|
3125
|
+
<span data-tpl-if="slots.ibefore" class="input-group-text">{{{{ slots.ibefore }}}}</span>
|
|
3126
|
+
{{{{ slots.before }}}}
|
|
3119
3127
|
<button data-ref="operator" class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" value="EQ" form="">=</button>
|
|
3120
3128
|
<ul class="dropdown-menu">
|
|
3121
3129
|
<li><a class="dropdown-item" role="button" value="EQ">=</a></li>
|
|
@@ -3128,32 +3136,22 @@ class LocalDateFilter extends ParsedElement {
|
|
|
3128
3136
|
</ul>
|
|
3129
3137
|
<input data-ref="value1" type="date" class="form-control" form="">
|
|
3130
3138
|
<input data-ref="value2" type="date" class="form-control" form="" hidden>
|
|
3131
|
-
|
|
3139
|
+
{{{{ slots.after }}}}
|
|
3140
|
+
<span data-tpl-if="slots.iafter" class="input-group-text">{{{{ slots.iafter }}}}</span>
|
|
3132
3141
|
</div>
|
|
3133
3142
|
<ful-field-error></ful-field-error>
|
|
3134
3143
|
`;
|
|
3135
|
-
static formAssociated = true;
|
|
3136
3144
|
#operator;
|
|
3137
3145
|
#value1;
|
|
3138
3146
|
#value2;
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
this
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
const fragment = this.template().withOverlay({ slots, label, name }).render();
|
|
3148
|
-
this.#operator = fragment.querySelector('[data-ref=operator]');
|
|
3149
|
-
this.#value1 = fragment.querySelector('[data-ref=value1]');
|
|
3150
|
-
this.#value2 = fragment.querySelector('[data-ref=value2]');
|
|
3151
|
-
this.#fieldError = fragment.querySelector('ful-field-error');
|
|
3152
|
-
const labelEl = fragment.querySelector('label');
|
|
3153
|
-
labelEl?.addEventListener('click', () => this.focus());
|
|
3154
|
-
this.#value1.ariaDescribedByElements = [this.#fieldError];
|
|
3155
|
-
this.#value1.ariaLabelledByElements = labelEl ? [labelEl] : [];
|
|
3156
|
-
this.replaceChildren(fragment);
|
|
3147
|
+
render(conf) {
|
|
3148
|
+
super.render({...conf, skipValueSetup: true});
|
|
3149
|
+
|
|
3150
|
+
this.#operator = this.querySelector('[data-ref=operator]');
|
|
3151
|
+
this.#value1 = this.querySelector('[data-ref=value1]');
|
|
3152
|
+
this.#value2 = this.querySelector('[data-ref=value2]');
|
|
3153
|
+
this.value = conf.observed.value;
|
|
3154
|
+
|
|
3157
3155
|
this.addEventListener('click', (evt) => {
|
|
3158
3156
|
const target = /** @type HTMLElement */(evt.target);
|
|
3159
3157
|
if (!target.matches('ul > li > a')) {
|
|
@@ -3175,42 +3173,25 @@ class LocalDateFilter extends ParsedElement {
|
|
|
3175
3173
|
if (v === null || v === undefined) {
|
|
3176
3174
|
this.#value1.value = '';
|
|
3177
3175
|
this.#value2.value = '';
|
|
3178
|
-
this.reflect(() => {
|
|
3179
|
-
this.removeAttribute('value');
|
|
3180
|
-
});
|
|
3181
3176
|
return;
|
|
3182
3177
|
}
|
|
3183
3178
|
const [operator, ...values] = v;
|
|
3184
3179
|
this.#operator.setAttibute('value', operator);
|
|
3185
3180
|
this.#value1.value = values[0];
|
|
3186
3181
|
this.#value2.value = values[1];
|
|
3187
|
-
this.reflect(() => {
|
|
3188
|
-
this.setAttribute('value', JSON.stringify(v));
|
|
3189
|
-
});
|
|
3190
|
-
}
|
|
3191
|
-
focus(options) {
|
|
3192
|
-
this.#value1.focus(options);
|
|
3193
|
-
}
|
|
3194
|
-
setCustomValidity(error) {
|
|
3195
|
-
if (!error) {
|
|
3196
|
-
this.internals.setValidity({});
|
|
3197
|
-
this.#fieldError.innerText = "";
|
|
3198
|
-
return;
|
|
3199
|
-
}
|
|
3200
|
-
this.internals.setValidity({ customError: true }, " ");
|
|
3201
|
-
this.#fieldError.innerText = error;
|
|
3202
3182
|
}
|
|
3203
3183
|
}
|
|
3204
3184
|
|
|
3205
|
-
class TextFilter extends
|
|
3206
|
-
static observed = ["value:json"];
|
|
3207
|
-
static slots = true;
|
|
3185
|
+
class TextFilter extends Input {
|
|
3186
|
+
static observed = ["value:json", 'readonly:presence'];
|
|
3208
3187
|
static template = `
|
|
3209
|
-
<div class="form-label"
|
|
3210
|
-
<label>{{{{
|
|
3188
|
+
<div class="form-label">
|
|
3189
|
+
<label>{{{{ slots.default }}}}</label>
|
|
3211
3190
|
{{{{ slots.info }}}}
|
|
3212
3191
|
</div>
|
|
3213
3192
|
<div class="input-group">
|
|
3193
|
+
<span data-tpl-if="slots.ibefore" class="input-group-text">{{{{ slots.ibefore }}}}</span>
|
|
3194
|
+
{{{{ slots.before }}}}
|
|
3214
3195
|
<button data-ref="operator" class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" value="CONTAINS" form="">…a…</button>
|
|
3215
3196
|
<ul class="dropdown-menu">
|
|
3216
3197
|
<li><a class="dropdown-item" role="button" value="CONTAINS">…a…</a></li>
|
|
@@ -3219,30 +3200,20 @@ class TextFilter extends ParsedElement {
|
|
|
3219
3200
|
<li><a class="dropdown-item" role="button" value="EQ">=</a></li>
|
|
3220
3201
|
</ul>
|
|
3221
3202
|
<input data-ref="value" type="text" class="form-control" form="">
|
|
3222
|
-
|
|
3203
|
+
{{{{ slots.after }}}}
|
|
3204
|
+
<span data-tpl-if="slots.iafter" class="input-group-text">{{{{ slots.iafter }}}}</span>
|
|
3223
3205
|
</div>
|
|
3224
3206
|
<ful-field-error></ful-field-error>
|
|
3225
3207
|
`;
|
|
3226
|
-
static formAssociated = true;
|
|
3227
3208
|
#operator;
|
|
3228
3209
|
#value;
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
this
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
const name = this.getAttribute("name");
|
|
3237
|
-
const fragment = this.template().withOverlay({ slots, label, name }).render();
|
|
3238
|
-
this.#operator = fragment.querySelector('[data-ref=operator]');
|
|
3239
|
-
this.#value = fragment.querySelector('[data-ref=value]');
|
|
3240
|
-
this.#fieldError = fragment.querySelector('ful-field-error');
|
|
3241
|
-
const labelEl = fragment.querySelector('label');
|
|
3242
|
-
labelEl?.addEventListener('click', () => this.focus());
|
|
3243
|
-
this.#value.ariaDescribedByElements = [this.#fieldError];
|
|
3244
|
-
this.#value.ariaLabelledByElements = labelEl ? [labelEl] : [];
|
|
3245
|
-
this.replaceChildren(fragment);
|
|
3210
|
+
render(conf) {
|
|
3211
|
+
super.render({...conf, skipValueSetup: true});
|
|
3212
|
+
|
|
3213
|
+
this.#operator = this.querySelector('[data-ref=operator]');
|
|
3214
|
+
this.#value = this.querySelector('[data-ref=value]');
|
|
3215
|
+
this.value = conf.observed.value;
|
|
3216
|
+
|
|
3246
3217
|
this.addEventListener('click', (evt) => {
|
|
3247
3218
|
const target = /** @type HTMLElement */(evt.target);
|
|
3248
3219
|
if (!target.matches('ul > li > a')) {
|
|
@@ -3263,29 +3234,11 @@ class TextFilter extends ParsedElement {
|
|
|
3263
3234
|
set value(v) {
|
|
3264
3235
|
if (v === null || v === undefined) {
|
|
3265
3236
|
this.#value.value = '';
|
|
3266
|
-
this.reflect(() => {
|
|
3267
|
-
this.removeAttribute('value');
|
|
3268
|
-
});
|
|
3269
3237
|
return;
|
|
3270
3238
|
}
|
|
3271
3239
|
const [operator, sensitivity, value] = v;
|
|
3272
3240
|
this.#operator.setAttribute('value', operator);
|
|
3273
3241
|
this.#value.value = value;
|
|
3274
|
-
this.reflect(() => {
|
|
3275
|
-
this.setAttribute('value', JSON.stringify(v));
|
|
3276
|
-
});
|
|
3277
|
-
}
|
|
3278
|
-
focus(options) {
|
|
3279
|
-
this.#value.focus(options);
|
|
3280
|
-
}
|
|
3281
|
-
setCustomValidity(error) {
|
|
3282
|
-
if (!error) {
|
|
3283
|
-
this.internals.setValidity({});
|
|
3284
|
-
this.#fieldError.innerText = "";
|
|
3285
|
-
return;
|
|
3286
|
-
}
|
|
3287
|
-
this.internals.setValidity({ customError: true }, " ");
|
|
3288
|
-
this.#fieldError.innerText = error;
|
|
3289
3242
|
}
|
|
3290
3243
|
}
|
|
3291
3244
|
|