@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.
@@ -261,6 +261,7 @@ var GlassKitElements = (function (exports) {
261
261
  this._shadow.appendChild(this._wrapper);
262
262
 
263
263
  this.render();
264
+ if (this.constructor.formAssociated) this._syncDisabled();
264
265
  } else {
265
266
  // Back in the document. While it was out, the observer did not reach
266
267
  // it, so a theme or density switched in the meantime is caught up here
@@ -363,6 +364,28 @@ var GlassKitElements = (function (exports) {
363
364
  */
364
365
  refresh() { this.projectLightDom(); }
365
366
 
367
+ /**
368
+ * Form-associated elements only. Such an element is disabled by its own
369
+ * `disabled` attribute or by a <fieldset disabled> around it: the browser
370
+ * counts both — :disabled, left out of the form data — and calls
371
+ * formDisabledCallback() on every change, also when the element moves into
372
+ * or out of such a fieldset. The native controls sit in the shadow root,
373
+ * out of every fieldset's reach, so the state is handed on to them through
374
+ * applyDisabled(). Until 1.22.2 only the element's own attribute reached
375
+ * them: inside a disabled fieldset every field stayed usable, and a submit
376
+ * button sent the form.
377
+ */
378
+ get _actuallyDisabled() { return this.matches(':disabled'); }
379
+
380
+ formDisabledCallback() {
381
+ if (this._initialized) this._syncDisabled();
382
+ }
383
+
384
+ _syncDisabled() { this.applyDisabled(this._actuallyDisabled); }
385
+
386
+ /** Form-associated subclasses override to disable their native controls. */
387
+ applyDisabled(disabled) {}
388
+
366
389
  // ── Utility Methods ──
367
390
 
368
391
  /**
@@ -440,6 +463,17 @@ var GlassKitElements = (function (exports) {
440
463
  if (this._initialized) this.syncValidity();
441
464
  }
442
465
 
466
+ // Reflects the attribute, as on a native control: a disabled fieldset
467
+ // around the element disables it without changing this.
468
+ get disabled() { return this.getBoolAttr('disabled'); }
469
+ set disabled(v) { this.setBoolAttr('disabled', v); }
470
+
471
+ _syncDisabled() {
472
+ super._syncDisabled();
473
+ // A disabled field is barred from validation; enabled again, it counts.
474
+ this.syncValidity();
475
+ }
476
+
443
477
  get form() { return this._internals.form; }
444
478
  get validationMessage() { return this._internals.validationMessage; }
445
479
  get validity() { return this._internals.validity; }
@@ -1523,12 +1557,13 @@ var GlassKitElements = (function (exports) {
1523
1557
 
1524
1558
  class GlkButton extends GlkElement {
1525
1559
  static get observedAttributes() {
1526
- return ['variant', 'size', 'disabled', 'type', ...FORWARDED_ARIA];
1560
+ return ['variant', 'size', 'type', ...FORWARDED_ARIA];
1527
1561
  }
1528
1562
 
1529
1563
  // The native button sits in the shadow root, outside every form. Form
1530
1564
  // association gives the element its form, so type="submit" and "reset"
1531
- // can act on it (see _activateForm).
1565
+ // can act on it (see _activateForm), and a disabled fieldset around it
1566
+ // disables it (since 1.22.3; before, it still sent the form).
1532
1567
  static formAssociated = true;
1533
1568
 
1534
1569
  constructor() {
@@ -1541,9 +1576,6 @@ var GlassKitElements = (function (exports) {
1541
1576
  type: this.getAttribute('type') || 'button'
1542
1577
  });
1543
1578
 
1544
- if (this.getBoolAttr('disabled')) {
1545
- this._btn.disabled = true;
1546
- }
1547
1579
  for (const attr of FORWARDED_ARIA) this._forward(attr);
1548
1580
 
1549
1581
  this._btn.appendChild(document.createElement('slot'));
@@ -1552,7 +1584,7 @@ var GlassKitElements = (function (exports) {
1552
1584
 
1553
1585
  setupEvents() {
1554
1586
  this._onClick = (e) => {
1555
- if (this.getBoolAttr('disabled')) {
1587
+ if (this._actuallyDisabled) {
1556
1588
  e.preventDefault();
1557
1589
  e.stopPropagation();
1558
1590
  return;
@@ -1611,9 +1643,6 @@ var GlassKitElements = (function (exports) {
1611
1643
  case 'size':
1612
1644
  this._btn.className = this._computeClasses().join(' ');
1613
1645
  break;
1614
- case 'disabled':
1615
- this._btn.disabled = this.getBoolAttr('disabled');
1616
- break;
1617
1646
  case 'type':
1618
1647
  this._btn.setAttribute('type', this.getAttribute('type') || 'button');
1619
1648
  break;
@@ -1622,6 +1651,8 @@ var GlassKitElements = (function (exports) {
1622
1651
  }
1623
1652
  }
1624
1653
 
1654
+ applyDisabled(disabled) { this._btn.disabled = disabled; }
1655
+
1625
1656
  _forward(attr) {
1626
1657
  const value = this.getAttribute(attr);
1627
1658
  if (value === null) this._btn.removeAttribute(attr);
@@ -1690,7 +1721,7 @@ var GlassKitElements = (function (exports) {
1690
1721
 
1691
1722
  class GlkInput extends GlkFormElement {
1692
1723
  static get observedAttributes() {
1693
- return ['label', 'type', 'placeholder', 'error', 'hint', 'disabled', 'readonly', 'name', 'value', 'required', ...FORWARDED];
1724
+ return ['label', 'type', 'placeholder', 'error', 'hint', 'readonly', 'name', 'value', 'required', ...FORWARDED];
1694
1725
  }
1695
1726
 
1696
1727
  static get hostStyles() { return affixSheet; }
@@ -1721,7 +1752,6 @@ var GlassKitElements = (function (exports) {
1721
1752
  this._pendingValue = undefined;
1722
1753
  if (value) this._input.value = value;
1723
1754
 
1724
- if (this.getBoolAttr('disabled')) this._input.disabled = true;
1725
1755
  if (this.getBoolAttr('readonly')) this._input.readOnly = true;
1726
1756
  if (this.getBoolAttr('required')) this._input.required = true;
1727
1757
  for (const attr of FORWARDED) this._forward(attr);
@@ -1811,9 +1841,6 @@ var GlassKitElements = (function (exports) {
1811
1841
  }
1812
1842
  this._applyDescription();
1813
1843
  break;
1814
- case 'disabled':
1815
- this._input.disabled = this.getBoolAttr('disabled');
1816
- break;
1817
1844
  case 'readonly':
1818
1845
  this._input.readOnly = this.getBoolAttr('readonly');
1819
1846
  break;
@@ -1832,6 +1859,8 @@ var GlassKitElements = (function (exports) {
1832
1859
  }
1833
1860
  }
1834
1861
 
1862
+ applyDisabled(disabled) { this._input.disabled = disabled; }
1863
+
1835
1864
  /** An affix shows, and makes room in the field, only while something is slotted. */
1836
1865
  _applyAffixes() {
1837
1866
  for (const affix of [this._prefix, this._suffix]) {
@@ -1897,9 +1926,6 @@ var GlassKitElements = (function (exports) {
1897
1926
  this._syncFormValue();
1898
1927
  }
1899
1928
 
1900
- get disabled() { return this.getBoolAttr('disabled'); }
1901
- set disabled(v) { this.setBoolAttr('disabled', v); }
1902
-
1903
1929
  get readOnly() { return this.getBoolAttr('readonly'); }
1904
1930
  set readOnly(v) { this.setBoolAttr('readonly', v); }
1905
1931
 
@@ -1911,7 +1937,7 @@ var GlassKitElements = (function (exports) {
1911
1937
 
1912
1938
  class GlkTextarea extends GlkFormElement {
1913
1939
  static get observedAttributes() {
1914
- return ['label', 'placeholder', 'rows', 'disabled', 'readonly', 'name', 'value', 'required'];
1940
+ return ['label', 'placeholder', 'rows', 'readonly', 'name', 'value', 'required'];
1915
1941
  }
1916
1942
 
1917
1943
  render() {
@@ -1936,7 +1962,6 @@ var GlassKitElements = (function (exports) {
1936
1962
  this._pendingValue = undefined;
1937
1963
  if (value) this._textarea.value = value;
1938
1964
 
1939
- if (this.getBoolAttr('disabled')) this._textarea.disabled = true;
1940
1965
  if (this.getBoolAttr('readonly')) this._textarea.readOnly = true;
1941
1966
  if (this.getBoolAttr('required')) this._textarea.required = true;
1942
1967
 
@@ -1972,9 +1997,6 @@ var GlassKitElements = (function (exports) {
1972
1997
  case 'rows':
1973
1998
  this._textarea.setAttribute('rows', this.getAttribute('rows') || '');
1974
1999
  break;
1975
- case 'disabled':
1976
- this._textarea.disabled = this.getBoolAttr('disabled');
1977
- break;
1978
2000
  case 'readonly':
1979
2001
  this._textarea.readOnly = this.getBoolAttr('readonly');
1980
2002
  break;
@@ -1991,6 +2013,8 @@ var GlassKitElements = (function (exports) {
1991
2013
  }
1992
2014
  }
1993
2015
 
2016
+ applyDisabled(disabled) { this._textarea.disabled = disabled; }
2017
+
1994
2018
  get _validityField() { return this._textarea; }
1995
2019
 
1996
2020
  _syncFormValue() {
@@ -2012,9 +2036,6 @@ var GlassKitElements = (function (exports) {
2012
2036
  this._syncFormValue();
2013
2037
  }
2014
2038
 
2015
- get disabled() { return this.getBoolAttr('disabled'); }
2016
- set disabled(v) { this.setBoolAttr('disabled', v); }
2017
-
2018
2039
  get readOnly() { return this.getBoolAttr('readonly'); }
2019
2040
  set readOnly(v) { this.setBoolAttr('readonly', v); }
2020
2041
  }
@@ -2033,7 +2054,7 @@ var GlassKitElements = (function (exports) {
2033
2054
 
2034
2055
  class GlkSelect extends GlkFormElement {
2035
2056
  static get observedAttributes() {
2036
- return ['label', 'disabled', 'name', 'value', 'required'];
2057
+ return ['label', 'name', 'value', 'required'];
2037
2058
  }
2038
2059
 
2039
2060
  static get observesLightDom() { return true; }
@@ -2052,7 +2073,6 @@ var GlassKitElements = (function (exports) {
2052
2073
  const name = this.getAttribute('name');
2053
2074
  if (name) this._select.setAttribute('name', name);
2054
2075
 
2055
- if (this.getBoolAttr('disabled')) this._select.disabled = true;
2056
2076
  if (this.getBoolAttr('required')) this._select.required = true;
2057
2077
 
2058
2078
  group.appendChild(this._labelEl);
@@ -2126,9 +2146,6 @@ var GlassKitElements = (function (exports) {
2126
2146
  case 'label':
2127
2147
  this._labelEl.textContent = this.getAttribute('label') || '';
2128
2148
  break;
2129
- case 'disabled':
2130
- this._select.disabled = this.getBoolAttr('disabled');
2131
- break;
2132
2149
  case 'name':
2133
2150
  this._select.setAttribute('name', this.getAttribute('name') || '');
2134
2151
  break;
@@ -2143,6 +2160,8 @@ var GlassKitElements = (function (exports) {
2143
2160
  }
2144
2161
  }
2145
2162
 
2163
+ applyDisabled(disabled) { this._select.disabled = disabled; }
2164
+
2146
2165
  get _validityField() { return this._select; }
2147
2166
 
2148
2167
  _syncFormValue() {
@@ -2168,9 +2187,6 @@ var GlassKitElements = (function (exports) {
2168
2187
  this._applyValue(this._wanted);
2169
2188
  this._syncFormValue();
2170
2189
  }
2171
-
2172
- get disabled() { return this.getBoolAttr('disabled'); }
2173
- set disabled(v) { this.setBoolAttr('disabled', v); }
2174
2190
  }
2175
2191
 
2176
2192
  customElements.define('glk-select', GlkSelect);
@@ -2179,7 +2195,7 @@ var GlassKitElements = (function (exports) {
2179
2195
 
2180
2196
  class GlkSearch extends GlkFormElement {
2181
2197
  static get observedAttributes() {
2182
- return ['placeholder', 'name', 'value', 'disabled', 'label'];
2198
+ return ['placeholder', 'name', 'value', 'label'];
2183
2199
  }
2184
2200
 
2185
2201
  render() {
@@ -2207,8 +2223,6 @@ var GlassKitElements = (function (exports) {
2207
2223
  this._pendingValue = undefined;
2208
2224
  if (value) this._input.value = value;
2209
2225
 
2210
- if (this.getBoolAttr('disabled')) this._input.disabled = true;
2211
-
2212
2226
  container.appendChild(icon);
2213
2227
  container.appendChild(this._input);
2214
2228
 
@@ -2242,15 +2256,14 @@ var GlassKitElements = (function (exports) {
2242
2256
  this._input.value = this.getAttribute('value') || '';
2243
2257
  this._syncFormValue();
2244
2258
  break;
2245
- case 'disabled':
2246
- this._input.disabled = this.getBoolAttr('disabled');
2247
- break;
2248
2259
  case 'label':
2249
2260
  this._applyLabel();
2250
2261
  break;
2251
2262
  }
2252
2263
  }
2253
2264
 
2265
+ applyDisabled(disabled) { this._input.disabled = disabled; }
2266
+
2254
2267
  _applyLabel() {
2255
2268
  const label = this.getAttribute('label');
2256
2269
  if (label) this._input.setAttribute('aria-label', label);
@@ -2281,7 +2294,7 @@ var GlassKitElements = (function (exports) {
2281
2294
 
2282
2295
  class GlkToggle extends GlkFormElement {
2283
2296
  static get observedAttributes() {
2284
- return ['checked', 'disabled', 'label', 'name', 'value', 'required'];
2297
+ return ['checked', 'label', 'name', 'value', 'required'];
2285
2298
  }
2286
2299
 
2287
2300
  static get hostStyles() { return checkControlSheet; }
@@ -2313,7 +2326,6 @@ var GlassKitElements = (function (exports) {
2313
2326
  label.appendChild(this._labelEl);
2314
2327
 
2315
2328
  if (this.getBoolAttr('checked')) this._input.checked = true;
2316
- if (this.getBoolAttr('disabled')) this._input.disabled = true;
2317
2329
  if (this.getBoolAttr('required')) this._input.required = true;
2318
2330
 
2319
2331
  this._defaultChecked = this.getBoolAttr('checked');
@@ -2348,9 +2360,6 @@ var GlassKitElements = (function (exports) {
2348
2360
  this._input.checked = this.getBoolAttr('checked');
2349
2361
  this._syncFormValue();
2350
2362
  break;
2351
- case 'disabled':
2352
- this._input.disabled = this.getBoolAttr('disabled');
2353
- break;
2354
2363
  case 'label':
2355
2364
  this._labelEl.textContent = this.getAttribute('label') || '';
2356
2365
  break;
@@ -2363,6 +2372,8 @@ var GlassKitElements = (function (exports) {
2363
2372
  }
2364
2373
  }
2365
2374
 
2375
+ applyDisabled(disabled) { this._input.disabled = disabled; }
2376
+
2366
2377
  get _validityField() { return this._input; }
2367
2378
 
2368
2379
  _syncFormValue() {
@@ -2391,9 +2402,6 @@ var GlassKitElements = (function (exports) {
2391
2402
  if (this._input) this._syncFormValue();
2392
2403
  }
2393
2404
 
2394
- get disabled() { return this.getBoolAttr('disabled'); }
2395
- set disabled(v) { this.setBoolAttr('disabled', v); }
2396
-
2397
2405
  get name() { return this.getAttribute('name'); }
2398
2406
  set name(v) { this.setAttribute('name', v); }
2399
2407
 
@@ -2410,7 +2418,7 @@ var GlassKitElements = (function (exports) {
2410
2418
 
2411
2419
  class GlkCheckbox extends GlkFormElement {
2412
2420
  static get observedAttributes() {
2413
- return ['checked', 'disabled', 'label', 'name', 'value', 'required'];
2421
+ return ['checked', 'label', 'name', 'value', 'required'];
2414
2422
  }
2415
2423
 
2416
2424
  static get hostStyles() { return checkControlSheet; }
@@ -2436,7 +2444,6 @@ var GlassKitElements = (function (exports) {
2436
2444
  label.appendChild(this._labelEl);
2437
2445
 
2438
2446
  if (this.getBoolAttr('checked')) this._input.checked = true;
2439
- if (this.getBoolAttr('disabled')) this._input.disabled = true;
2440
2447
  if (this.getBoolAttr('required')) this._input.required = true;
2441
2448
 
2442
2449
  this._defaultChecked = this.getBoolAttr('checked');
@@ -2470,9 +2477,6 @@ var GlassKitElements = (function (exports) {
2470
2477
  this._input.checked = this.getBoolAttr('checked');
2471
2478
  this._syncFormValue();
2472
2479
  break;
2473
- case 'disabled':
2474
- this._input.disabled = this.getBoolAttr('disabled');
2475
- break;
2476
2480
  case 'label':
2477
2481
  this._labelEl.textContent = this.getAttribute('label') || '';
2478
2482
  break;
@@ -2485,6 +2489,8 @@ var GlassKitElements = (function (exports) {
2485
2489
  }
2486
2490
  }
2487
2491
 
2492
+ applyDisabled(disabled) { this._input.disabled = disabled; }
2493
+
2488
2494
  get _validityField() { return this._input; }
2489
2495
 
2490
2496
  _syncFormValue() {
@@ -2506,9 +2512,6 @@ var GlassKitElements = (function (exports) {
2506
2512
  if (this._input) this._syncFormValue();
2507
2513
  }
2508
2514
 
2509
- get disabled() { return this.getBoolAttr('disabled'); }
2510
- set disabled(v) { this.setBoolAttr('disabled', v); }
2511
-
2512
2515
  get name() { return this.getAttribute('name'); }
2513
2516
  set name(v) { this.setAttribute('name', v); }
2514
2517
 
@@ -2537,7 +2540,7 @@ var GlassKitElements = (function (exports) {
2537
2540
 
2538
2541
  /** Only the selected radio is a tab stop; arrow keys move within the group. */
2539
2542
  function syncGroupTabIndex(group) {
2540
- const enabled = group.filter(el => !el.disabled);
2543
+ const enabled = group.filter(el => !el._actuallyDisabled);
2541
2544
  if (!enabled.length) return;
2542
2545
  const focusable = enabled.find(el => el.checked) || enabled[0];
2543
2546
  for (const el of group) {
@@ -2547,7 +2550,7 @@ var GlassKitElements = (function (exports) {
2547
2550
 
2548
2551
  class GlkRadio extends GlkFormElement {
2549
2552
  static get observedAttributes() {
2550
- return ['checked', 'disabled', 'label', 'name', 'value', 'required'];
2553
+ return ['checked', 'label', 'name', 'value', 'required'];
2551
2554
  }
2552
2555
 
2553
2556
  static get hostStyles() { return checkControlSheet; }
@@ -2577,7 +2580,6 @@ var GlassKitElements = (function (exports) {
2577
2580
  label.appendChild(this._labelEl);
2578
2581
 
2579
2582
  if (this.getBoolAttr('checked')) this._input.checked = true;
2580
- if (this.getBoolAttr('disabled')) this._input.disabled = true;
2581
2583
 
2582
2584
  this._defaultChecked = this.getBoolAttr('checked');
2583
2585
  this._wrapper.appendChild(label);
@@ -2595,7 +2597,7 @@ var GlassKitElements = (function (exports) {
2595
2597
  this._onKeyDown = (e) => {
2596
2598
  const dir = ARROW_KEYS[e.key];
2597
2599
  if (!dir || e.ctrlKey || e.metaKey || e.altKey) return;
2598
- const group = this._group().filter(el => !el.disabled);
2600
+ const group = this._group().filter(el => !el._actuallyDisabled);
2599
2601
  if (group.length < 2) return;
2600
2602
  e.preventDefault();
2601
2603
  const next = group[(group.indexOf(this) + dir + group.length) % group.length];
@@ -2677,10 +2679,6 @@ var GlassKitElements = (function (exports) {
2677
2679
  this._syncFormValue();
2678
2680
  syncGroupTabIndex(this._group());
2679
2681
  break;
2680
- case 'disabled':
2681
- this._input.disabled = this.getBoolAttr('disabled');
2682
- syncGroupTabIndex(this._group());
2683
- break;
2684
2682
  case 'label':
2685
2683
  this._labelEl.textContent = this.getAttribute('label') || '';
2686
2684
  break;
@@ -2695,6 +2693,11 @@ var GlassKitElements = (function (exports) {
2695
2693
  }
2696
2694
  }
2697
2695
 
2696
+ applyDisabled(disabled) {
2697
+ this._input.disabled = disabled;
2698
+ syncGroupTabIndex(this._group());
2699
+ }
2700
+
2698
2701
  _syncFormValue() {
2699
2702
  const val = this.getAttribute('value') || '';
2700
2703
  this.setFormValue(this._input.checked ? val : null);
@@ -2719,9 +2722,6 @@ var GlassKitElements = (function (exports) {
2719
2722
  syncGroupTabIndex(this._group());
2720
2723
  }
2721
2724
 
2722
- get disabled() { return this.getBoolAttr('disabled'); }
2723
- set disabled(v) { this.setBoolAttr('disabled', v); }
2724
-
2725
2725
  get name() { return this.getAttribute('name'); }
2726
2726
  set name(v) { this.setAttribute('name', v); }
2727
2727
 
@@ -2733,7 +2733,7 @@ var GlassKitElements = (function (exports) {
2733
2733
 
2734
2734
  class GlkRange extends GlkFormElement {
2735
2735
  static get observedAttributes() {
2736
- return ['label', 'min', 'max', 'value', 'step', 'name', 'disabled'];
2736
+ return ['label', 'min', 'max', 'value', 'step', 'name'];
2737
2737
  }
2738
2738
 
2739
2739
  render() {
@@ -2764,8 +2764,6 @@ var GlassKitElements = (function (exports) {
2764
2764
  const name = this.getAttribute('name');
2765
2765
  if (name) this._input.setAttribute('name', name);
2766
2766
 
2767
- if (this.getBoolAttr('disabled')) this._input.disabled = true;
2768
-
2769
2767
  // The reset value is the attribute's; a value set as a property before
2770
2768
  // render() has waited for it and comes on top.
2771
2769
  this._defaultValue = this._input.value;
@@ -2817,12 +2815,11 @@ var GlassKitElements = (function (exports) {
2817
2815
  case 'name':
2818
2816
  this._input.setAttribute('name', this.getAttribute('name') || '');
2819
2817
  break;
2820
- case 'disabled':
2821
- this._input.disabled = this.getBoolAttr('disabled');
2822
- break;
2823
2818
  }
2824
2819
  }
2825
2820
 
2821
+ applyDisabled(disabled) { this._input.disabled = disabled; }
2822
+
2826
2823
  _updateValueDisplay() {
2827
2824
  this._valueEl.textContent = `${this._input.value}%`;
2828
2825
  }
@@ -2857,8 +2854,11 @@ var GlassKitElements = (function (exports) {
2857
2854
  // Attributes: options (JSON [{value,label,tone?,disabled?}]), value, full,
2858
2855
  // overflow ("scroll" | "wrap": what happens when the options
2859
2856
  // do not fit — without it the row stays one line and runs past
2860
- // the edge), label (aria-label of the group), name (form field)
2861
- // Properties: value, options (array or JSON text), full, overflow, label
2857
+ // the edge), label (aria-label of the group), name (form field),
2858
+ // disabled (the whole row; since 1.22.3, as is a disabled
2859
+ // fieldset around it)
2860
+ // Properties: value, options (array or JSON text), full, overflow, label,
2861
+ // disabled
2862
2862
  // Event: glk-change { value } — only on a change made by the user
2863
2863
  // Part: group
2864
2864
  //
@@ -2911,13 +2911,21 @@ var GlassKitElements = (function (exports) {
2911
2911
  button.classList.add(`glass-segmented__item--${option.tone}`);
2912
2912
  button.appendChild(this.createElement('span', ['glass-segmented__dot']));
2913
2913
  }
2914
- if (option.disabled) button.disabled = true;
2915
2914
  button.appendChild(document.createTextNode(option.label ?? value));
2916
2915
  this._group.appendChild(button);
2917
2916
  }
2917
+ this.applyDisabled(this._actuallyDisabled);
2918
2918
  this._syncValue();
2919
2919
  }
2920
2920
 
2921
+ /** The whole row is disabled, or an option by its own `disabled`. */
2922
+ applyDisabled(disabled) {
2923
+ const options = this.options;
2924
+ this._group.querySelectorAll('button[data-value]').forEach((button, i) => {
2925
+ button.disabled = disabled || Boolean(options[i]?.disabled);
2926
+ });
2927
+ }
2928
+
2921
2929
  _syncValue() {
2922
2930
  const value = this.value;
2923
2931
  for (const button of this._group.querySelectorAll('button[data-value]')) {
@@ -3020,8 +3028,9 @@ var GlassKitElements = (function (exports) {
3020
3028
  // the page language, else the browser's), week-start (0 = Sunday … 6 = Saturday;
3021
3029
  // default from the locale, Monday where the browser cannot say),
3022
3030
  // label (aria-label of the day group), prev-label / next-label
3023
- // (names of the nav buttons, English by default)
3024
- // Properties: month, value, marks, locale, label
3031
+ // (names of the nav buttons, English by default), disabled
3032
+ // (since 1.22.3, as is a disabled fieldset around it)
3033
+ // Properties: month, value, marks, locale, label, disabled
3025
3034
  // Form: associated — a surrounding <form> receives name=value, reset
3026
3035
  // restores the initial value, like <glk-segmented>
3027
3036
  // Events: glk-change { value } — on a pick by the user
@@ -3113,9 +3122,16 @@ var GlassKitElements = (function (exports) {
3113
3122
  day.append(num, dots);
3114
3123
  this._grid.appendChild(day);
3115
3124
  }
3125
+ this.applyDisabled(this._actuallyDisabled);
3116
3126
  this._syncValue();
3117
3127
  }
3118
3128
 
3129
+ // Disabled as a whole: the arrows and every day. The days of another month
3130
+ // are built again, so _build() hands the state on to them too.
3131
+ applyDisabled(disabled) {
3132
+ for (const button of [this._prev, this._next, ...this._days()]) button.disabled = disabled;
3133
+ }
3134
+
3119
3135
  _days() { return [...this._grid.querySelectorAll('button[data-value]')]; }
3120
3136
  _dayFor(iso) { return this._grid.querySelector(`button[data-value="${iso}"]`); }
3121
3137