@jungherz-de/glasskit-elements 1.22.2 → 1.22.3
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/CHANGELOG.md +19 -1
- package/README.md +2 -2
- package/SKILL.md +9 -6
- package/dist/components/base.js +34 -0
- package/dist/components/glk-button.js +6 -9
- package/dist/components/glk-calendar.js +10 -2
- package/dist/components/glk-checkbox.js +3 -8
- package/dist/components/glk-input.js +3 -8
- package/dist/components/glk-radio.js +8 -11
- package/dist/components/glk-range.js +3 -6
- package/dist/components/glk-search.js +3 -6
- package/dist/components/glk-segmented.js +14 -3
- package/dist/components/glk-select.js +3 -8
- package/dist/components/glk-textarea.js +3 -8
- package/dist/components/glk-toggle.js +3 -8
- package/dist/glasskit-elements.esm.js +93 -77
- package/dist/glasskit-elements.js +93 -77
- package/dist/glasskit-elements.min.js +1 -1
- package/package.json +1 -1
- package/src/base.js +34 -0
- package/src/components/buttons/glk-button.js +6 -9
- package/src/components/forms/glk-calendar.js +10 -2
- package/src/components/forms/glk-checkbox.js +3 -8
- package/src/components/forms/glk-input.js +3 -8
- package/src/components/forms/glk-radio.js +8 -11
- package/src/components/forms/glk-range.js +3 -6
- package/src/components/forms/glk-search.js +3 -6
- package/src/components/forms/glk-segmented.js +14 -3
- package/src/components/forms/glk-select.js +3 -8
- package/src/components/forms/glk-textarea.js +3 -8
- package/src/components/forms/glk-toggle.js +3 -8
|
@@ -258,6 +258,7 @@ class GlkElement extends HTMLElement {
|
|
|
258
258
|
this._shadow.appendChild(this._wrapper);
|
|
259
259
|
|
|
260
260
|
this.render();
|
|
261
|
+
if (this.constructor.formAssociated) this._syncDisabled();
|
|
261
262
|
} else {
|
|
262
263
|
// Back in the document. While it was out, the observer did not reach
|
|
263
264
|
// it, so a theme or density switched in the meantime is caught up here
|
|
@@ -360,6 +361,28 @@ class GlkElement extends HTMLElement {
|
|
|
360
361
|
*/
|
|
361
362
|
refresh() { this.projectLightDom(); }
|
|
362
363
|
|
|
364
|
+
/**
|
|
365
|
+
* Form-associated elements only. Such an element is disabled by its own
|
|
366
|
+
* `disabled` attribute or by a <fieldset disabled> around it: the browser
|
|
367
|
+
* counts both — :disabled, left out of the form data — and calls
|
|
368
|
+
* formDisabledCallback() on every change, also when the element moves into
|
|
369
|
+
* or out of such a fieldset. The native controls sit in the shadow root,
|
|
370
|
+
* out of every fieldset's reach, so the state is handed on to them through
|
|
371
|
+
* applyDisabled(). Until 1.22.2 only the element's own attribute reached
|
|
372
|
+
* them: inside a disabled fieldset every field stayed usable, and a submit
|
|
373
|
+
* button sent the form.
|
|
374
|
+
*/
|
|
375
|
+
get _actuallyDisabled() { return this.matches(':disabled'); }
|
|
376
|
+
|
|
377
|
+
formDisabledCallback() {
|
|
378
|
+
if (this._initialized) this._syncDisabled();
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
_syncDisabled() { this.applyDisabled(this._actuallyDisabled); }
|
|
382
|
+
|
|
383
|
+
/** Form-associated subclasses override to disable their native controls. */
|
|
384
|
+
applyDisabled(disabled) {}
|
|
385
|
+
|
|
363
386
|
// ── Utility Methods ──
|
|
364
387
|
|
|
365
388
|
/**
|
|
@@ -437,6 +460,17 @@ class GlkFormElement extends GlkElement {
|
|
|
437
460
|
if (this._initialized) this.syncValidity();
|
|
438
461
|
}
|
|
439
462
|
|
|
463
|
+
// Reflects the attribute, as on a native control: a disabled fieldset
|
|
464
|
+
// around the element disables it without changing this.
|
|
465
|
+
get disabled() { return this.getBoolAttr('disabled'); }
|
|
466
|
+
set disabled(v) { this.setBoolAttr('disabled', v); }
|
|
467
|
+
|
|
468
|
+
_syncDisabled() {
|
|
469
|
+
super._syncDisabled();
|
|
470
|
+
// A disabled field is barred from validation; enabled again, it counts.
|
|
471
|
+
this.syncValidity();
|
|
472
|
+
}
|
|
473
|
+
|
|
440
474
|
get form() { return this._internals.form; }
|
|
441
475
|
get validationMessage() { return this._internals.validationMessage; }
|
|
442
476
|
get validity() { return this._internals.validity; }
|
|
@@ -1520,12 +1554,13 @@ const FORWARDED_ARIA = ['aria-expanded', 'aria-haspopup', 'aria-pressed'];
|
|
|
1520
1554
|
|
|
1521
1555
|
class GlkButton extends GlkElement {
|
|
1522
1556
|
static get observedAttributes() {
|
|
1523
|
-
return ['variant', 'size', '
|
|
1557
|
+
return ['variant', 'size', 'type', ...FORWARDED_ARIA];
|
|
1524
1558
|
}
|
|
1525
1559
|
|
|
1526
1560
|
// The native button sits in the shadow root, outside every form. Form
|
|
1527
1561
|
// association gives the element its form, so type="submit" and "reset"
|
|
1528
|
-
// can act on it (see _activateForm)
|
|
1562
|
+
// can act on it (see _activateForm), and a disabled fieldset around it
|
|
1563
|
+
// disables it (since 1.22.3; before, it still sent the form).
|
|
1529
1564
|
static formAssociated = true;
|
|
1530
1565
|
|
|
1531
1566
|
constructor() {
|
|
@@ -1538,9 +1573,6 @@ class GlkButton extends GlkElement {
|
|
|
1538
1573
|
type: this.getAttribute('type') || 'button'
|
|
1539
1574
|
});
|
|
1540
1575
|
|
|
1541
|
-
if (this.getBoolAttr('disabled')) {
|
|
1542
|
-
this._btn.disabled = true;
|
|
1543
|
-
}
|
|
1544
1576
|
for (const attr of FORWARDED_ARIA) this._forward(attr);
|
|
1545
1577
|
|
|
1546
1578
|
this._btn.appendChild(document.createElement('slot'));
|
|
@@ -1549,7 +1581,7 @@ class GlkButton extends GlkElement {
|
|
|
1549
1581
|
|
|
1550
1582
|
setupEvents() {
|
|
1551
1583
|
this._onClick = (e) => {
|
|
1552
|
-
if (this.
|
|
1584
|
+
if (this._actuallyDisabled) {
|
|
1553
1585
|
e.preventDefault();
|
|
1554
1586
|
e.stopPropagation();
|
|
1555
1587
|
return;
|
|
@@ -1608,9 +1640,6 @@ class GlkButton extends GlkElement {
|
|
|
1608
1640
|
case 'size':
|
|
1609
1641
|
this._btn.className = this._computeClasses().join(' ');
|
|
1610
1642
|
break;
|
|
1611
|
-
case 'disabled':
|
|
1612
|
-
this._btn.disabled = this.getBoolAttr('disabled');
|
|
1613
|
-
break;
|
|
1614
1643
|
case 'type':
|
|
1615
1644
|
this._btn.setAttribute('type', this.getAttribute('type') || 'button');
|
|
1616
1645
|
break;
|
|
@@ -1619,6 +1648,8 @@ class GlkButton extends GlkElement {
|
|
|
1619
1648
|
}
|
|
1620
1649
|
}
|
|
1621
1650
|
|
|
1651
|
+
applyDisabled(disabled) { this._btn.disabled = disabled; }
|
|
1652
|
+
|
|
1622
1653
|
_forward(attr) {
|
|
1623
1654
|
const value = this.getAttribute(attr);
|
|
1624
1655
|
if (value === null) this._btn.removeAttribute(attr);
|
|
@@ -1687,7 +1718,7 @@ affixSheet.replaceSync(`
|
|
|
1687
1718
|
|
|
1688
1719
|
class GlkInput extends GlkFormElement {
|
|
1689
1720
|
static get observedAttributes() {
|
|
1690
|
-
return ['label', 'type', 'placeholder', 'error', 'hint', '
|
|
1721
|
+
return ['label', 'type', 'placeholder', 'error', 'hint', 'readonly', 'name', 'value', 'required', ...FORWARDED];
|
|
1691
1722
|
}
|
|
1692
1723
|
|
|
1693
1724
|
static get hostStyles() { return affixSheet; }
|
|
@@ -1718,7 +1749,6 @@ class GlkInput extends GlkFormElement {
|
|
|
1718
1749
|
this._pendingValue = undefined;
|
|
1719
1750
|
if (value) this._input.value = value;
|
|
1720
1751
|
|
|
1721
|
-
if (this.getBoolAttr('disabled')) this._input.disabled = true;
|
|
1722
1752
|
if (this.getBoolAttr('readonly')) this._input.readOnly = true;
|
|
1723
1753
|
if (this.getBoolAttr('required')) this._input.required = true;
|
|
1724
1754
|
for (const attr of FORWARDED) this._forward(attr);
|
|
@@ -1808,9 +1838,6 @@ class GlkInput extends GlkFormElement {
|
|
|
1808
1838
|
}
|
|
1809
1839
|
this._applyDescription();
|
|
1810
1840
|
break;
|
|
1811
|
-
case 'disabled':
|
|
1812
|
-
this._input.disabled = this.getBoolAttr('disabled');
|
|
1813
|
-
break;
|
|
1814
1841
|
case 'readonly':
|
|
1815
1842
|
this._input.readOnly = this.getBoolAttr('readonly');
|
|
1816
1843
|
break;
|
|
@@ -1829,6 +1856,8 @@ class GlkInput extends GlkFormElement {
|
|
|
1829
1856
|
}
|
|
1830
1857
|
}
|
|
1831
1858
|
|
|
1859
|
+
applyDisabled(disabled) { this._input.disabled = disabled; }
|
|
1860
|
+
|
|
1832
1861
|
/** An affix shows, and makes room in the field, only while something is slotted. */
|
|
1833
1862
|
_applyAffixes() {
|
|
1834
1863
|
for (const affix of [this._prefix, this._suffix]) {
|
|
@@ -1894,9 +1923,6 @@ class GlkInput extends GlkFormElement {
|
|
|
1894
1923
|
this._syncFormValue();
|
|
1895
1924
|
}
|
|
1896
1925
|
|
|
1897
|
-
get disabled() { return this.getBoolAttr('disabled'); }
|
|
1898
|
-
set disabled(v) { this.setBoolAttr('disabled', v); }
|
|
1899
|
-
|
|
1900
1926
|
get readOnly() { return this.getBoolAttr('readonly'); }
|
|
1901
1927
|
set readOnly(v) { this.setBoolAttr('readonly', v); }
|
|
1902
1928
|
|
|
@@ -1908,7 +1934,7 @@ customElements.define('glk-input', GlkInput);
|
|
|
1908
1934
|
|
|
1909
1935
|
class GlkTextarea extends GlkFormElement {
|
|
1910
1936
|
static get observedAttributes() {
|
|
1911
|
-
return ['label', 'placeholder', 'rows', '
|
|
1937
|
+
return ['label', 'placeholder', 'rows', 'readonly', 'name', 'value', 'required'];
|
|
1912
1938
|
}
|
|
1913
1939
|
|
|
1914
1940
|
render() {
|
|
@@ -1933,7 +1959,6 @@ class GlkTextarea extends GlkFormElement {
|
|
|
1933
1959
|
this._pendingValue = undefined;
|
|
1934
1960
|
if (value) this._textarea.value = value;
|
|
1935
1961
|
|
|
1936
|
-
if (this.getBoolAttr('disabled')) this._textarea.disabled = true;
|
|
1937
1962
|
if (this.getBoolAttr('readonly')) this._textarea.readOnly = true;
|
|
1938
1963
|
if (this.getBoolAttr('required')) this._textarea.required = true;
|
|
1939
1964
|
|
|
@@ -1969,9 +1994,6 @@ class GlkTextarea extends GlkFormElement {
|
|
|
1969
1994
|
case 'rows':
|
|
1970
1995
|
this._textarea.setAttribute('rows', this.getAttribute('rows') || '');
|
|
1971
1996
|
break;
|
|
1972
|
-
case 'disabled':
|
|
1973
|
-
this._textarea.disabled = this.getBoolAttr('disabled');
|
|
1974
|
-
break;
|
|
1975
1997
|
case 'readonly':
|
|
1976
1998
|
this._textarea.readOnly = this.getBoolAttr('readonly');
|
|
1977
1999
|
break;
|
|
@@ -1988,6 +2010,8 @@ class GlkTextarea extends GlkFormElement {
|
|
|
1988
2010
|
}
|
|
1989
2011
|
}
|
|
1990
2012
|
|
|
2013
|
+
applyDisabled(disabled) { this._textarea.disabled = disabled; }
|
|
2014
|
+
|
|
1991
2015
|
get _validityField() { return this._textarea; }
|
|
1992
2016
|
|
|
1993
2017
|
_syncFormValue() {
|
|
@@ -2009,9 +2033,6 @@ class GlkTextarea extends GlkFormElement {
|
|
|
2009
2033
|
this._syncFormValue();
|
|
2010
2034
|
}
|
|
2011
2035
|
|
|
2012
|
-
get disabled() { return this.getBoolAttr('disabled'); }
|
|
2013
|
-
set disabled(v) { this.setBoolAttr('disabled', v); }
|
|
2014
|
-
|
|
2015
2036
|
get readOnly() { return this.getBoolAttr('readonly'); }
|
|
2016
2037
|
set readOnly(v) { this.setBoolAttr('readonly', v); }
|
|
2017
2038
|
}
|
|
@@ -2030,7 +2051,7 @@ customElements.define('glk-textarea', GlkTextarea);
|
|
|
2030
2051
|
|
|
2031
2052
|
class GlkSelect extends GlkFormElement {
|
|
2032
2053
|
static get observedAttributes() {
|
|
2033
|
-
return ['label', '
|
|
2054
|
+
return ['label', 'name', 'value', 'required'];
|
|
2034
2055
|
}
|
|
2035
2056
|
|
|
2036
2057
|
static get observesLightDom() { return true; }
|
|
@@ -2049,7 +2070,6 @@ class GlkSelect extends GlkFormElement {
|
|
|
2049
2070
|
const name = this.getAttribute('name');
|
|
2050
2071
|
if (name) this._select.setAttribute('name', name);
|
|
2051
2072
|
|
|
2052
|
-
if (this.getBoolAttr('disabled')) this._select.disabled = true;
|
|
2053
2073
|
if (this.getBoolAttr('required')) this._select.required = true;
|
|
2054
2074
|
|
|
2055
2075
|
group.appendChild(this._labelEl);
|
|
@@ -2123,9 +2143,6 @@ class GlkSelect extends GlkFormElement {
|
|
|
2123
2143
|
case 'label':
|
|
2124
2144
|
this._labelEl.textContent = this.getAttribute('label') || '';
|
|
2125
2145
|
break;
|
|
2126
|
-
case 'disabled':
|
|
2127
|
-
this._select.disabled = this.getBoolAttr('disabled');
|
|
2128
|
-
break;
|
|
2129
2146
|
case 'name':
|
|
2130
2147
|
this._select.setAttribute('name', this.getAttribute('name') || '');
|
|
2131
2148
|
break;
|
|
@@ -2140,6 +2157,8 @@ class GlkSelect extends GlkFormElement {
|
|
|
2140
2157
|
}
|
|
2141
2158
|
}
|
|
2142
2159
|
|
|
2160
|
+
applyDisabled(disabled) { this._select.disabled = disabled; }
|
|
2161
|
+
|
|
2143
2162
|
get _validityField() { return this._select; }
|
|
2144
2163
|
|
|
2145
2164
|
_syncFormValue() {
|
|
@@ -2165,9 +2184,6 @@ class GlkSelect extends GlkFormElement {
|
|
|
2165
2184
|
this._applyValue(this._wanted);
|
|
2166
2185
|
this._syncFormValue();
|
|
2167
2186
|
}
|
|
2168
|
-
|
|
2169
|
-
get disabled() { return this.getBoolAttr('disabled'); }
|
|
2170
|
-
set disabled(v) { this.setBoolAttr('disabled', v); }
|
|
2171
2187
|
}
|
|
2172
2188
|
|
|
2173
2189
|
customElements.define('glk-select', GlkSelect);
|
|
@@ -2176,7 +2192,7 @@ const SEARCH_SVG = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" s
|
|
|
2176
2192
|
|
|
2177
2193
|
class GlkSearch extends GlkFormElement {
|
|
2178
2194
|
static get observedAttributes() {
|
|
2179
|
-
return ['placeholder', 'name', 'value', '
|
|
2195
|
+
return ['placeholder', 'name', 'value', 'label'];
|
|
2180
2196
|
}
|
|
2181
2197
|
|
|
2182
2198
|
render() {
|
|
@@ -2204,8 +2220,6 @@ class GlkSearch extends GlkFormElement {
|
|
|
2204
2220
|
this._pendingValue = undefined;
|
|
2205
2221
|
if (value) this._input.value = value;
|
|
2206
2222
|
|
|
2207
|
-
if (this.getBoolAttr('disabled')) this._input.disabled = true;
|
|
2208
|
-
|
|
2209
2223
|
container.appendChild(icon);
|
|
2210
2224
|
container.appendChild(this._input);
|
|
2211
2225
|
|
|
@@ -2239,15 +2253,14 @@ class GlkSearch extends GlkFormElement {
|
|
|
2239
2253
|
this._input.value = this.getAttribute('value') || '';
|
|
2240
2254
|
this._syncFormValue();
|
|
2241
2255
|
break;
|
|
2242
|
-
case 'disabled':
|
|
2243
|
-
this._input.disabled = this.getBoolAttr('disabled');
|
|
2244
|
-
break;
|
|
2245
2256
|
case 'label':
|
|
2246
2257
|
this._applyLabel();
|
|
2247
2258
|
break;
|
|
2248
2259
|
}
|
|
2249
2260
|
}
|
|
2250
2261
|
|
|
2262
|
+
applyDisabled(disabled) { this._input.disabled = disabled; }
|
|
2263
|
+
|
|
2251
2264
|
_applyLabel() {
|
|
2252
2265
|
const label = this.getAttribute('label');
|
|
2253
2266
|
if (label) this._input.setAttribute('aria-label', label);
|
|
@@ -2278,7 +2291,7 @@ customElements.define('glk-search', GlkSearch);
|
|
|
2278
2291
|
|
|
2279
2292
|
class GlkToggle extends GlkFormElement {
|
|
2280
2293
|
static get observedAttributes() {
|
|
2281
|
-
return ['checked', '
|
|
2294
|
+
return ['checked', 'label', 'name', 'value', 'required'];
|
|
2282
2295
|
}
|
|
2283
2296
|
|
|
2284
2297
|
static get hostStyles() { return checkControlSheet; }
|
|
@@ -2310,7 +2323,6 @@ class GlkToggle extends GlkFormElement {
|
|
|
2310
2323
|
label.appendChild(this._labelEl);
|
|
2311
2324
|
|
|
2312
2325
|
if (this.getBoolAttr('checked')) this._input.checked = true;
|
|
2313
|
-
if (this.getBoolAttr('disabled')) this._input.disabled = true;
|
|
2314
2326
|
if (this.getBoolAttr('required')) this._input.required = true;
|
|
2315
2327
|
|
|
2316
2328
|
this._defaultChecked = this.getBoolAttr('checked');
|
|
@@ -2345,9 +2357,6 @@ class GlkToggle extends GlkFormElement {
|
|
|
2345
2357
|
this._input.checked = this.getBoolAttr('checked');
|
|
2346
2358
|
this._syncFormValue();
|
|
2347
2359
|
break;
|
|
2348
|
-
case 'disabled':
|
|
2349
|
-
this._input.disabled = this.getBoolAttr('disabled');
|
|
2350
|
-
break;
|
|
2351
2360
|
case 'label':
|
|
2352
2361
|
this._labelEl.textContent = this.getAttribute('label') || '';
|
|
2353
2362
|
break;
|
|
@@ -2360,6 +2369,8 @@ class GlkToggle extends GlkFormElement {
|
|
|
2360
2369
|
}
|
|
2361
2370
|
}
|
|
2362
2371
|
|
|
2372
|
+
applyDisabled(disabled) { this._input.disabled = disabled; }
|
|
2373
|
+
|
|
2363
2374
|
get _validityField() { return this._input; }
|
|
2364
2375
|
|
|
2365
2376
|
_syncFormValue() {
|
|
@@ -2388,9 +2399,6 @@ class GlkToggle extends GlkFormElement {
|
|
|
2388
2399
|
if (this._input) this._syncFormValue();
|
|
2389
2400
|
}
|
|
2390
2401
|
|
|
2391
|
-
get disabled() { return this.getBoolAttr('disabled'); }
|
|
2392
|
-
set disabled(v) { this.setBoolAttr('disabled', v); }
|
|
2393
|
-
|
|
2394
2402
|
get name() { return this.getAttribute('name'); }
|
|
2395
2403
|
set name(v) { this.setAttribute('name', v); }
|
|
2396
2404
|
|
|
@@ -2407,7 +2415,7 @@ const CHECKMARK_SVG = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor
|
|
|
2407
2415
|
|
|
2408
2416
|
class GlkCheckbox extends GlkFormElement {
|
|
2409
2417
|
static get observedAttributes() {
|
|
2410
|
-
return ['checked', '
|
|
2418
|
+
return ['checked', 'label', 'name', 'value', 'required'];
|
|
2411
2419
|
}
|
|
2412
2420
|
|
|
2413
2421
|
static get hostStyles() { return checkControlSheet; }
|
|
@@ -2433,7 +2441,6 @@ class GlkCheckbox extends GlkFormElement {
|
|
|
2433
2441
|
label.appendChild(this._labelEl);
|
|
2434
2442
|
|
|
2435
2443
|
if (this.getBoolAttr('checked')) this._input.checked = true;
|
|
2436
|
-
if (this.getBoolAttr('disabled')) this._input.disabled = true;
|
|
2437
2444
|
if (this.getBoolAttr('required')) this._input.required = true;
|
|
2438
2445
|
|
|
2439
2446
|
this._defaultChecked = this.getBoolAttr('checked');
|
|
@@ -2467,9 +2474,6 @@ class GlkCheckbox extends GlkFormElement {
|
|
|
2467
2474
|
this._input.checked = this.getBoolAttr('checked');
|
|
2468
2475
|
this._syncFormValue();
|
|
2469
2476
|
break;
|
|
2470
|
-
case 'disabled':
|
|
2471
|
-
this._input.disabled = this.getBoolAttr('disabled');
|
|
2472
|
-
break;
|
|
2473
2477
|
case 'label':
|
|
2474
2478
|
this._labelEl.textContent = this.getAttribute('label') || '';
|
|
2475
2479
|
break;
|
|
@@ -2482,6 +2486,8 @@ class GlkCheckbox extends GlkFormElement {
|
|
|
2482
2486
|
}
|
|
2483
2487
|
}
|
|
2484
2488
|
|
|
2489
|
+
applyDisabled(disabled) { this._input.disabled = disabled; }
|
|
2490
|
+
|
|
2485
2491
|
get _validityField() { return this._input; }
|
|
2486
2492
|
|
|
2487
2493
|
_syncFormValue() {
|
|
@@ -2503,9 +2509,6 @@ class GlkCheckbox extends GlkFormElement {
|
|
|
2503
2509
|
if (this._input) this._syncFormValue();
|
|
2504
2510
|
}
|
|
2505
2511
|
|
|
2506
|
-
get disabled() { return this.getBoolAttr('disabled'); }
|
|
2507
|
-
set disabled(v) { this.setBoolAttr('disabled', v); }
|
|
2508
|
-
|
|
2509
2512
|
get name() { return this.getAttribute('name'); }
|
|
2510
2513
|
set name(v) { this.setAttribute('name', v); }
|
|
2511
2514
|
|
|
@@ -2534,7 +2537,7 @@ function ownerForm(el) {
|
|
|
2534
2537
|
|
|
2535
2538
|
/** Only the selected radio is a tab stop; arrow keys move within the group. */
|
|
2536
2539
|
function syncGroupTabIndex(group) {
|
|
2537
|
-
const enabled = group.filter(el => !el.
|
|
2540
|
+
const enabled = group.filter(el => !el._actuallyDisabled);
|
|
2538
2541
|
if (!enabled.length) return;
|
|
2539
2542
|
const focusable = enabled.find(el => el.checked) || enabled[0];
|
|
2540
2543
|
for (const el of group) {
|
|
@@ -2544,7 +2547,7 @@ function syncGroupTabIndex(group) {
|
|
|
2544
2547
|
|
|
2545
2548
|
class GlkRadio extends GlkFormElement {
|
|
2546
2549
|
static get observedAttributes() {
|
|
2547
|
-
return ['checked', '
|
|
2550
|
+
return ['checked', 'label', 'name', 'value', 'required'];
|
|
2548
2551
|
}
|
|
2549
2552
|
|
|
2550
2553
|
static get hostStyles() { return checkControlSheet; }
|
|
@@ -2574,7 +2577,6 @@ class GlkRadio extends GlkFormElement {
|
|
|
2574
2577
|
label.appendChild(this._labelEl);
|
|
2575
2578
|
|
|
2576
2579
|
if (this.getBoolAttr('checked')) this._input.checked = true;
|
|
2577
|
-
if (this.getBoolAttr('disabled')) this._input.disabled = true;
|
|
2578
2580
|
|
|
2579
2581
|
this._defaultChecked = this.getBoolAttr('checked');
|
|
2580
2582
|
this._wrapper.appendChild(label);
|
|
@@ -2592,7 +2594,7 @@ class GlkRadio extends GlkFormElement {
|
|
|
2592
2594
|
this._onKeyDown = (e) => {
|
|
2593
2595
|
const dir = ARROW_KEYS[e.key];
|
|
2594
2596
|
if (!dir || e.ctrlKey || e.metaKey || e.altKey) return;
|
|
2595
|
-
const group = this._group().filter(el => !el.
|
|
2597
|
+
const group = this._group().filter(el => !el._actuallyDisabled);
|
|
2596
2598
|
if (group.length < 2) return;
|
|
2597
2599
|
e.preventDefault();
|
|
2598
2600
|
const next = group[(group.indexOf(this) + dir + group.length) % group.length];
|
|
@@ -2674,10 +2676,6 @@ class GlkRadio extends GlkFormElement {
|
|
|
2674
2676
|
this._syncFormValue();
|
|
2675
2677
|
syncGroupTabIndex(this._group());
|
|
2676
2678
|
break;
|
|
2677
|
-
case 'disabled':
|
|
2678
|
-
this._input.disabled = this.getBoolAttr('disabled');
|
|
2679
|
-
syncGroupTabIndex(this._group());
|
|
2680
|
-
break;
|
|
2681
2679
|
case 'label':
|
|
2682
2680
|
this._labelEl.textContent = this.getAttribute('label') || '';
|
|
2683
2681
|
break;
|
|
@@ -2692,6 +2690,11 @@ class GlkRadio extends GlkFormElement {
|
|
|
2692
2690
|
}
|
|
2693
2691
|
}
|
|
2694
2692
|
|
|
2693
|
+
applyDisabled(disabled) {
|
|
2694
|
+
this._input.disabled = disabled;
|
|
2695
|
+
syncGroupTabIndex(this._group());
|
|
2696
|
+
}
|
|
2697
|
+
|
|
2695
2698
|
_syncFormValue() {
|
|
2696
2699
|
const val = this.getAttribute('value') || '';
|
|
2697
2700
|
this.setFormValue(this._input.checked ? val : null);
|
|
@@ -2716,9 +2719,6 @@ class GlkRadio extends GlkFormElement {
|
|
|
2716
2719
|
syncGroupTabIndex(this._group());
|
|
2717
2720
|
}
|
|
2718
2721
|
|
|
2719
|
-
get disabled() { return this.getBoolAttr('disabled'); }
|
|
2720
|
-
set disabled(v) { this.setBoolAttr('disabled', v); }
|
|
2721
|
-
|
|
2722
2722
|
get name() { return this.getAttribute('name'); }
|
|
2723
2723
|
set name(v) { this.setAttribute('name', v); }
|
|
2724
2724
|
|
|
@@ -2730,7 +2730,7 @@ customElements.define('glk-radio', GlkRadio);
|
|
|
2730
2730
|
|
|
2731
2731
|
class GlkRange extends GlkFormElement {
|
|
2732
2732
|
static get observedAttributes() {
|
|
2733
|
-
return ['label', 'min', 'max', 'value', 'step', 'name'
|
|
2733
|
+
return ['label', 'min', 'max', 'value', 'step', 'name'];
|
|
2734
2734
|
}
|
|
2735
2735
|
|
|
2736
2736
|
render() {
|
|
@@ -2761,8 +2761,6 @@ class GlkRange extends GlkFormElement {
|
|
|
2761
2761
|
const name = this.getAttribute('name');
|
|
2762
2762
|
if (name) this._input.setAttribute('name', name);
|
|
2763
2763
|
|
|
2764
|
-
if (this.getBoolAttr('disabled')) this._input.disabled = true;
|
|
2765
|
-
|
|
2766
2764
|
// The reset value is the attribute's; a value set as a property before
|
|
2767
2765
|
// render() has waited for it and comes on top.
|
|
2768
2766
|
this._defaultValue = this._input.value;
|
|
@@ -2814,12 +2812,11 @@ class GlkRange extends GlkFormElement {
|
|
|
2814
2812
|
case 'name':
|
|
2815
2813
|
this._input.setAttribute('name', this.getAttribute('name') || '');
|
|
2816
2814
|
break;
|
|
2817
|
-
case 'disabled':
|
|
2818
|
-
this._input.disabled = this.getBoolAttr('disabled');
|
|
2819
|
-
break;
|
|
2820
2815
|
}
|
|
2821
2816
|
}
|
|
2822
2817
|
|
|
2818
|
+
applyDisabled(disabled) { this._input.disabled = disabled; }
|
|
2819
|
+
|
|
2823
2820
|
_updateValueDisplay() {
|
|
2824
2821
|
this._valueEl.textContent = `${this._input.value}%`;
|
|
2825
2822
|
}
|
|
@@ -2854,8 +2851,11 @@ customElements.define('glk-range', GlkRange);
|
|
|
2854
2851
|
// Attributes: options (JSON [{value,label,tone?,disabled?}]), value, full,
|
|
2855
2852
|
// overflow ("scroll" | "wrap": what happens when the options
|
|
2856
2853
|
// do not fit — without it the row stays one line and runs past
|
|
2857
|
-
// the edge), label (aria-label of the group), name (form field)
|
|
2858
|
-
//
|
|
2854
|
+
// the edge), label (aria-label of the group), name (form field),
|
|
2855
|
+
// disabled (the whole row; since 1.22.3, as is a disabled
|
|
2856
|
+
// fieldset around it)
|
|
2857
|
+
// Properties: value, options (array or JSON text), full, overflow, label,
|
|
2858
|
+
// disabled
|
|
2859
2859
|
// Event: glk-change { value } — only on a change made by the user
|
|
2860
2860
|
// Part: group
|
|
2861
2861
|
//
|
|
@@ -2908,13 +2908,21 @@ class GlkSegmented extends GlkFormElement {
|
|
|
2908
2908
|
button.classList.add(`glass-segmented__item--${option.tone}`);
|
|
2909
2909
|
button.appendChild(this.createElement('span', ['glass-segmented__dot']));
|
|
2910
2910
|
}
|
|
2911
|
-
if (option.disabled) button.disabled = true;
|
|
2912
2911
|
button.appendChild(document.createTextNode(option.label ?? value));
|
|
2913
2912
|
this._group.appendChild(button);
|
|
2914
2913
|
}
|
|
2914
|
+
this.applyDisabled(this._actuallyDisabled);
|
|
2915
2915
|
this._syncValue();
|
|
2916
2916
|
}
|
|
2917
2917
|
|
|
2918
|
+
/** The whole row is disabled, or an option by its own `disabled`. */
|
|
2919
|
+
applyDisabled(disabled) {
|
|
2920
|
+
const options = this.options;
|
|
2921
|
+
this._group.querySelectorAll('button[data-value]').forEach((button, i) => {
|
|
2922
|
+
button.disabled = disabled || Boolean(options[i]?.disabled);
|
|
2923
|
+
});
|
|
2924
|
+
}
|
|
2925
|
+
|
|
2918
2926
|
_syncValue() {
|
|
2919
2927
|
const value = this.value;
|
|
2920
2928
|
for (const button of this._group.querySelectorAll('button[data-value]')) {
|
|
@@ -3017,8 +3025,9 @@ customElements.define('glk-segmented', GlkSegmented);
|
|
|
3017
3025
|
// the page language, else the browser's), week-start (0 = Sunday … 6 = Saturday;
|
|
3018
3026
|
// default from the locale, Monday where the browser cannot say),
|
|
3019
3027
|
// label (aria-label of the day group), prev-label / next-label
|
|
3020
|
-
// (names of the nav buttons, English by default)
|
|
3021
|
-
//
|
|
3028
|
+
// (names of the nav buttons, English by default), disabled
|
|
3029
|
+
// (since 1.22.3, as is a disabled fieldset around it)
|
|
3030
|
+
// Properties: month, value, marks, locale, label, disabled
|
|
3022
3031
|
// Form: associated — a surrounding <form> receives name=value, reset
|
|
3023
3032
|
// restores the initial value, like <glk-segmented>
|
|
3024
3033
|
// Events: glk-change { value } — on a pick by the user
|
|
@@ -3110,9 +3119,16 @@ class GlkCalendar extends GlkFormElement {
|
|
|
3110
3119
|
day.append(num, dots);
|
|
3111
3120
|
this._grid.appendChild(day);
|
|
3112
3121
|
}
|
|
3122
|
+
this.applyDisabled(this._actuallyDisabled);
|
|
3113
3123
|
this._syncValue();
|
|
3114
3124
|
}
|
|
3115
3125
|
|
|
3126
|
+
// Disabled as a whole: the arrows and every day. The days of another month
|
|
3127
|
+
// are built again, so _build() hands the state on to them too.
|
|
3128
|
+
applyDisabled(disabled) {
|
|
3129
|
+
for (const button of [this._prev, this._next, ...this._days()]) button.disabled = disabled;
|
|
3130
|
+
}
|
|
3131
|
+
|
|
3116
3132
|
_days() { return [...this._grid.querySelectorAll('button[data-value]')]; }
|
|
3117
3133
|
_dayFor(iso) { return this._grid.querySelector(`button[data-value="${iso}"]`); }
|
|
3118
3134
|
|