@optionfactory/ful 1.0.13 → 1.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 +81 -11
- 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 +81 -11
- package/dist/ful.mjs.map +1 -1
- package/package.json +2 -2
package/dist/ful.mjs
CHANGED
|
@@ -1267,7 +1267,12 @@ class Bindings {
|
|
|
1267
1267
|
});
|
|
1268
1268
|
fieldErrors.forEach(e => {
|
|
1269
1269
|
const name = e.context.replace("[", ".").replace("].", ".").replace("]", "");
|
|
1270
|
-
|
|
1270
|
+
const parts = name.split(".");
|
|
1271
|
+
for (let i = parts.length; i != 0; --i) {
|
|
1272
|
+
const prefix = parts.slice(0, i).join(".");
|
|
1273
|
+
const suffix = parts.slice(i, parts.length).join(".");
|
|
1274
|
+
form.querySelectorAll(`[name='${CSS.escape(prefix)}']`).forEach(input => input.setCustomValidity?.(e.reason, suffix));
|
|
1275
|
+
}
|
|
1271
1276
|
});
|
|
1272
1277
|
form.querySelectorAll("ful-errors").forEach(el => {
|
|
1273
1278
|
const hel = /** @type HTMLElement} */ (el);
|
|
@@ -1386,7 +1391,9 @@ class Form extends ParsedElement {
|
|
|
1386
1391
|
this.spinner(false);
|
|
1387
1392
|
}
|
|
1388
1393
|
}
|
|
1389
|
-
|
|
1394
|
+
reset(){
|
|
1395
|
+
this.form.reset();
|
|
1396
|
+
}
|
|
1390
1397
|
spinner(spin) {
|
|
1391
1398
|
this.querySelectorAll('ful-spinner').forEach(el => {
|
|
1392
1399
|
const hel = /** @type HTMLElement */ (el);
|
|
@@ -1431,11 +1438,16 @@ class Input extends ParsedElement {
|
|
|
1431
1438
|
this.internals = this.attachInternals();
|
|
1432
1439
|
this.internals.role = 'presentation';
|
|
1433
1440
|
}
|
|
1434
|
-
render({ slots }) {
|
|
1441
|
+
render({ slots, observed, disabled }) {
|
|
1435
1442
|
const type = this.getAttribute("type") ?? 'text';
|
|
1436
1443
|
const fragment = this.template().withOverlay({ type, slots }).render();
|
|
1437
1444
|
this.#input = fragment.querySelector("input,textarea");
|
|
1445
|
+
|
|
1438
1446
|
Attributes.forward('input-', this, this.#input);
|
|
1447
|
+
this.disabled = disabled;
|
|
1448
|
+
this.readonly = observed.readonly;
|
|
1449
|
+
this.value = observed.value;
|
|
1450
|
+
|
|
1439
1451
|
this.#input.addEventListener('change', (evt) => {
|
|
1440
1452
|
evt.stopPropagation();
|
|
1441
1453
|
this.dispatchEvent(new CustomEvent('change', {
|
|
@@ -1465,6 +1477,12 @@ class Input extends ParsedElement {
|
|
|
1465
1477
|
set readonly(v) {
|
|
1466
1478
|
this.#input.readOnly = v;
|
|
1467
1479
|
}
|
|
1480
|
+
get disabled(){
|
|
1481
|
+
return this.#input.hasAttribute('disabled');
|
|
1482
|
+
}
|
|
1483
|
+
set disabled(d){
|
|
1484
|
+
Attributes.toggle(this.#input, 'disabled', d);
|
|
1485
|
+
}
|
|
1468
1486
|
focus(options) {
|
|
1469
1487
|
this.#input.focus(options);
|
|
1470
1488
|
}
|
|
@@ -1477,6 +1495,9 @@ class Input extends ParsedElement {
|
|
|
1477
1495
|
this.internals.setValidity({ customError: true }, " ");
|
|
1478
1496
|
this.#fieldError.innerText = error;
|
|
1479
1497
|
}
|
|
1498
|
+
formResetCallback(){
|
|
1499
|
+
this.value = this.getAttribute("value");
|
|
1500
|
+
}
|
|
1480
1501
|
}
|
|
1481
1502
|
|
|
1482
1503
|
class CompleteSelectLoader {
|
|
@@ -1677,7 +1698,7 @@ class Dropdown extends ParsedElement {
|
|
|
1677
1698
|
}
|
|
1678
1699
|
|
|
1679
1700
|
class Select extends ParsedElement {
|
|
1680
|
-
static observed = ['value:csvm']
|
|
1701
|
+
static observed = ['value:csvm', 'readonly:presence']
|
|
1681
1702
|
static slots = true
|
|
1682
1703
|
static template = `
|
|
1683
1704
|
<label class="form-label">{{{{ slots.default }}}}</label>
|
|
@@ -1716,13 +1737,18 @@ class Select extends ParsedElement {
|
|
|
1716
1737
|
this.internals = this.attachInternals();
|
|
1717
1738
|
this.internals.role = 'presentation';
|
|
1718
1739
|
}
|
|
1719
|
-
async render({ slots, observed }) {
|
|
1740
|
+
async render({ slots, observed, disabled }) {
|
|
1720
1741
|
const name = this.getAttribute("name");
|
|
1721
1742
|
this.#loader = Loaders.fromAttributes(this, 'loaders:select', { options: slots.options });
|
|
1722
1743
|
await this.#loader.prefetch?.();
|
|
1723
1744
|
const fragment = this.template().withOverlay({ slots, name }).render();
|
|
1724
1745
|
this.#input = fragment.querySelector('input');
|
|
1725
1746
|
this.#badges = fragment.querySelector('badges');
|
|
1747
|
+
|
|
1748
|
+
this.value = observed.value;
|
|
1749
|
+
this.disabled = disabled;
|
|
1750
|
+
this.readonly = observed.readonly;
|
|
1751
|
+
|
|
1726
1752
|
this.#ddmenu = fragment.querySelector('ful-dropdown');
|
|
1727
1753
|
this.#multiple = this.hasAttribute("multiple");
|
|
1728
1754
|
const label = fragment.querySelector('label');
|
|
@@ -1731,7 +1757,6 @@ class Select extends ParsedElement {
|
|
|
1731
1757
|
this.#input.ariaDescribedByElements = [this.#fieldError];
|
|
1732
1758
|
this.#input.ariaLabelledByElements = [label];
|
|
1733
1759
|
|
|
1734
|
-
|
|
1735
1760
|
const self = this;
|
|
1736
1761
|
const [dload, abortdload] = timing.debounce(400, () => self.#ddmenu.show(() => self.#loader.load(self.#input.value)));
|
|
1737
1762
|
this.addEventListener('click', (/** @type any */e) => {
|
|
@@ -1824,6 +1849,11 @@ class Select extends ParsedElement {
|
|
|
1824
1849
|
this.#badges.append(...badges);
|
|
1825
1850
|
}
|
|
1826
1851
|
set value(value) {
|
|
1852
|
+
if(value === null){
|
|
1853
|
+
this.#values = new Map();
|
|
1854
|
+
this.#syncBadges();
|
|
1855
|
+
return;
|
|
1856
|
+
}
|
|
1827
1857
|
(async () => {
|
|
1828
1858
|
const entries = await (this.#multiple ? this.#loader.exact(...value) : this.#loader.exact(value));
|
|
1829
1859
|
this.#values = new Map(entries);
|
|
@@ -1851,7 +1881,7 @@ class Select extends ParsedElement {
|
|
|
1851
1881
|
}
|
|
1852
1882
|
|
|
1853
1883
|
class RadioGroup extends ParsedElement {
|
|
1854
|
-
static observed = ['value'];
|
|
1884
|
+
static observed = ['value', 'readonly:presence'];
|
|
1855
1885
|
static slots = true;
|
|
1856
1886
|
static template = `
|
|
1857
1887
|
<fieldset>
|
|
@@ -1876,6 +1906,7 @@ class RadioGroup extends ParsedElement {
|
|
|
1876
1906
|
</fieldset>
|
|
1877
1907
|
`;
|
|
1878
1908
|
static formAssociated = true;
|
|
1909
|
+
#fieldset;
|
|
1879
1910
|
#fieldError;
|
|
1880
1911
|
#firstRadio;
|
|
1881
1912
|
#booleanType;
|
|
@@ -1884,7 +1915,7 @@ class RadioGroup extends ParsedElement {
|
|
|
1884
1915
|
this.internals = this.attachInternals();
|
|
1885
1916
|
this.internals.role = 'radiogroup';
|
|
1886
1917
|
}
|
|
1887
|
-
render({ slots }) {
|
|
1918
|
+
render({ slots, observed, disabled }) {
|
|
1888
1919
|
const name = this.getAttribute('name') ?? Attributes.uid('ful-radiogroup');
|
|
1889
1920
|
const radioEls = Array.from(slots.default.querySelectorAll('ful-radio'));
|
|
1890
1921
|
const inputsAndLabels = radioEls.map(el => {
|
|
@@ -1911,6 +1942,10 @@ class RadioGroup extends ParsedElement {
|
|
|
1911
1942
|
|
|
1912
1943
|
radioEls.forEach(el => el.remove());
|
|
1913
1944
|
this.template().withOverlay({ name, slots, inputsAndLabels }).renderTo(this);
|
|
1945
|
+
this.#fieldset = this.firstElementChild;
|
|
1946
|
+
this.disabled = disabled;
|
|
1947
|
+
this.readonly = observed.readonly;
|
|
1948
|
+
this.value = observed.value;
|
|
1914
1949
|
this.#fieldError = this.querySelector('ful-field-error');
|
|
1915
1950
|
this.ariaDescribedByElements = [this.#fieldError];
|
|
1916
1951
|
this.#firstRadio = this.querySelector('input[type=radio]');
|
|
@@ -1933,7 +1968,19 @@ class RadioGroup extends ParsedElement {
|
|
|
1933
1968
|
if (el) {
|
|
1934
1969
|
el.checked = true;
|
|
1935
1970
|
}
|
|
1971
|
+
}
|
|
1972
|
+
get readonly(){
|
|
1973
|
+
return this.#fieldset.inert;
|
|
1974
|
+
}
|
|
1975
|
+
set readonly(v) {
|
|
1976
|
+
this.#fieldset.inert = v;
|
|
1977
|
+
}
|
|
1978
|
+
get disabled(){
|
|
1979
|
+
return this.#fieldset.hasAttribute('disabled');
|
|
1936
1980
|
}
|
|
1981
|
+
set disabled(d){
|
|
1982
|
+
Attributes.toggle(this.#fieldset, 'disabled', d);
|
|
1983
|
+
}
|
|
1937
1984
|
focus(options) {
|
|
1938
1985
|
this.#firstRadio.focus(options);
|
|
1939
1986
|
}
|
|
@@ -1949,7 +1996,7 @@ class RadioGroup extends ParsedElement {
|
|
|
1949
1996
|
}
|
|
1950
1997
|
|
|
1951
1998
|
class Checkbox extends ParsedElement {
|
|
1952
|
-
static observed = ['value:bool'];
|
|
1999
|
+
static observed = ['value:bool', 'readonly:presence'];
|
|
1953
2000
|
static slots = true;
|
|
1954
2001
|
static template = `
|
|
1955
2002
|
<div data-tpl-class="klass">
|
|
@@ -1960,6 +2007,7 @@ class Checkbox extends ParsedElement {
|
|
|
1960
2007
|
</div>
|
|
1961
2008
|
<ful-field-error></ful-field-error>
|
|
1962
2009
|
`;
|
|
2010
|
+
#container;
|
|
1963
2011
|
#input;
|
|
1964
2012
|
#fieldError;
|
|
1965
2013
|
static formAssociated = true;
|
|
@@ -1968,11 +2016,15 @@ class Checkbox extends ParsedElement {
|
|
|
1968
2016
|
this.internals = this.attachInternals();
|
|
1969
2017
|
this.internals.role = 'presentation';
|
|
1970
2018
|
}
|
|
1971
|
-
render({ slots }) {
|
|
2019
|
+
render({ slots, observed, disabled }) {
|
|
1972
2020
|
const klass = this.getAttribute('type') == 'switch' ? "form-check form-switch" : "form-check";
|
|
1973
2021
|
const fragment = this.template().withOverlay({ slots, klass }).render();
|
|
2022
|
+
this.#container = fragment.firstElementChild;
|
|
1974
2023
|
this.#input = fragment.querySelector("input");
|
|
1975
2024
|
Attributes.forward('input-', this, this.#input);
|
|
2025
|
+
this.disabled = disabled;
|
|
2026
|
+
this.readonly = observed.readonly;
|
|
2027
|
+
this.value = observed.value;
|
|
1976
2028
|
this.#input.addEventListener('change', (evt) => {
|
|
1977
2029
|
evt.stopPropagation();
|
|
1978
2030
|
this.dispatchEvent(new CustomEvent('change', {
|
|
@@ -1984,7 +2036,13 @@ class Checkbox extends ParsedElement {
|
|
|
1984
2036
|
}));
|
|
1985
2037
|
});
|
|
1986
2038
|
const label = fragment.querySelector('label');
|
|
1987
|
-
label.addEventListener('click', () => {
|
|
2039
|
+
label.addEventListener('click', () => {
|
|
2040
|
+
this.focus();
|
|
2041
|
+
if (this.disabled || this.readonly) {
|
|
2042
|
+
return;
|
|
2043
|
+
}
|
|
2044
|
+
this.value = !this.value;
|
|
2045
|
+
});
|
|
1988
2046
|
this.#fieldError = fragment.querySelector('ful-field-error');
|
|
1989
2047
|
this.#input.ariaDescribedByElements = [this.#fieldError];
|
|
1990
2048
|
this.#input.ariaLabelledByElements = [label];
|
|
@@ -1996,6 +2054,18 @@ class Checkbox extends ParsedElement {
|
|
|
1996
2054
|
set value(value) {
|
|
1997
2055
|
this.#input.checked = value;
|
|
1998
2056
|
}
|
|
2057
|
+
get readonly(){
|
|
2058
|
+
return this.#container.inert;
|
|
2059
|
+
}
|
|
2060
|
+
set readonly(v) {
|
|
2061
|
+
this.#container.inert = v;
|
|
2062
|
+
}
|
|
2063
|
+
get disabled() {
|
|
2064
|
+
return this.#input.hasAttribute('disabled');
|
|
2065
|
+
}
|
|
2066
|
+
set disabled(d) {
|
|
2067
|
+
Attributes.toggle(this.#input, 'disabled', d);
|
|
2068
|
+
}
|
|
1999
2069
|
focus(options) {
|
|
2000
2070
|
this.#input.focus(options);
|
|
2001
2071
|
}
|