@jungherz-de/glasskit-elements 1.11.0 → 1.12.0
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 +1 -1
- package/dist/components/glk-accordion-item.js +1 -1
- package/dist/components/glk-accordion.js +1 -1
- package/dist/components/glk-avatar.js +1 -1
- package/dist/components/glk-badge.js +1 -1
- package/dist/components/glk-button.js +1 -1
- package/dist/components/glk-card.js +1 -1
- package/dist/components/glk-checkbox.js +1 -1
- package/dist/components/glk-divider.js +1 -1
- package/dist/components/glk-input.js +1 -1
- package/dist/components/glk-list-item.js +1 -1
- package/dist/components/glk-list.js +1 -1
- package/dist/components/glk-modal.js +19 -12
- package/dist/components/glk-nav.js +1 -1
- package/dist/components/glk-pill.js +1 -1
- package/dist/components/glk-popover.js +1 -1
- package/dist/components/glk-progress.js +1 -1
- package/dist/components/glk-radio.js +1 -1
- package/dist/components/glk-range.js +1 -1
- package/dist/components/glk-search.js +1 -1
- package/dist/components/glk-select.js +39 -8
- package/dist/components/glk-status.js +1 -1
- package/dist/components/glk-tab-accessory.js +1 -1
- package/dist/components/glk-tab-bar.js +1 -1
- package/dist/components/glk-tab-dock.js +1 -1
- package/dist/components/glk-tab-item.js +26 -15
- package/dist/components/glk-textarea.js +1 -1
- package/dist/components/glk-title.js +1 -1
- package/dist/components/glk-toast.js +1 -1
- package/dist/components/glk-toggle.js +1 -1
- package/dist/components/shared/{base-C0B1hgOt.js → base-BoN33KPe.js} +36 -3
- package/dist/glasskit-elements.esm.js +117 -35
- package/dist/glasskit-elements.js +117 -35
- package/dist/glasskit-elements.min.js +1 -1
- package/package.json +1 -1
- package/src/base.js +36 -3
- package/src/components/feedback/glk-modal.js +18 -11
- package/src/components/forms/glk-select.js +38 -7
- package/src/components/navigation/glk-tab-item.js +25 -14
|
@@ -104,6 +104,14 @@ class GlkElement extends HTMLElement {
|
|
|
104
104
|
*/
|
|
105
105
|
static get hostStyles() { return null; }
|
|
106
106
|
|
|
107
|
+
/**
|
|
108
|
+
* Opt in when the component copies light-DOM children into its shadow tree.
|
|
109
|
+
* A MutationObserver then calls projectLightDom() again whenever those
|
|
110
|
+
* children change, so a framework that swaps them keeps the rendered element
|
|
111
|
+
* in step. Without it the copy is made once and silently goes stale.
|
|
112
|
+
*/
|
|
113
|
+
static get observesLightDom() { return false; }
|
|
114
|
+
|
|
107
115
|
static get observedAttributes() {
|
|
108
116
|
return [];
|
|
109
117
|
}
|
|
@@ -130,15 +138,26 @@ class GlkElement extends HTMLElement {
|
|
|
130
138
|
this._shadow.appendChild(this._wrapper);
|
|
131
139
|
|
|
132
140
|
this.render();
|
|
133
|
-
|
|
141
|
+
}
|
|
134
142
|
|
|
135
|
-
|
|
136
|
-
|
|
143
|
+
// Everything below runs on every connect, not just the first. Moving an
|
|
144
|
+
// element in the DOM disconnects and reconnects it, and disconnectedCallback
|
|
145
|
+
// tears all of this down — without re-arming it here a moved element would
|
|
146
|
+
// keep its markup but silently stop reacting.
|
|
147
|
+
this.setupEvents();
|
|
148
|
+
instances.add(this);
|
|
149
|
+
|
|
150
|
+
if (this.constructor.observesLightDom) {
|
|
151
|
+
this._lightDomObserver ??= new MutationObserver(records => this.projectLightDom(records));
|
|
152
|
+
this._lightDomObserver.observe(this, {
|
|
153
|
+
childList: true, subtree: true, characterData: true
|
|
154
|
+
});
|
|
137
155
|
}
|
|
138
156
|
}
|
|
139
157
|
|
|
140
158
|
disconnectedCallback() {
|
|
141
159
|
instances.delete(this);
|
|
160
|
+
this._lightDomObserver?.disconnect();
|
|
142
161
|
this.teardownEvents();
|
|
143
162
|
}
|
|
144
163
|
|
|
@@ -166,6 +185,20 @@ class GlkElement extends HTMLElement {
|
|
|
166
185
|
/** Subclasses override to react to attribute changes. */
|
|
167
186
|
onAttributeChanged(name, oldValue, newValue) {}
|
|
168
187
|
|
|
188
|
+
/**
|
|
189
|
+
* Subclasses that set observesLightDom override this to (re-)copy their
|
|
190
|
+
* light-DOM children into the shadow tree. Runs on every change to those
|
|
191
|
+
* children, so it has to be safe to call repeatedly.
|
|
192
|
+
*/
|
|
193
|
+
projectLightDom() {}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Escape hatch: re-copy the light-DOM children now. The observer covers the
|
|
197
|
+
* ordinary cases; this is for the ones it cannot see, so nobody has to reach
|
|
198
|
+
* into element.shadowRoot.
|
|
199
|
+
*/
|
|
200
|
+
refresh() { this.projectLightDom(); }
|
|
201
|
+
|
|
169
202
|
// ── Utility Methods ──
|
|
170
203
|
|
|
171
204
|
getBoolAttr(name) {
|
|
@@ -354,6 +387,8 @@ class GlkTabItem extends GlkElement {
|
|
|
354
387
|
return ['label', 'active', 'badge'];
|
|
355
388
|
}
|
|
356
389
|
|
|
390
|
+
static get observesLightDom() { return true; }
|
|
391
|
+
|
|
357
392
|
render() {
|
|
358
393
|
this._btn = this.createElement('button', ['glass-tab-bar__item']);
|
|
359
394
|
if (this.getBoolAttr('active')) this._btn.classList.add('is-active');
|
|
@@ -379,23 +414,32 @@ class GlkTabItem extends GlkElement {
|
|
|
379
414
|
this._wrapper.appendChild(this._btn);
|
|
380
415
|
|
|
381
416
|
// Defer icon cloning — children may not be parsed yet
|
|
382
|
-
requestAnimationFrame(() => this.
|
|
417
|
+
requestAnimationFrame(() => this.projectLightDom());
|
|
383
418
|
}
|
|
384
419
|
|
|
385
|
-
|
|
420
|
+
projectLightDom() {
|
|
386
421
|
const svg = this.querySelector('svg');
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
422
|
+
const signature = svg ? svg.outerHTML : '';
|
|
423
|
+
if (signature === this._iconSignature) return;
|
|
424
|
+
this._iconSignature = signature;
|
|
425
|
+
|
|
426
|
+
// Drop the previous clone by hand: the icon container also holds the badge,
|
|
427
|
+
// and inserting without removing would stack a second icon on every update.
|
|
428
|
+
this._iconClone?.remove();
|
|
429
|
+
this._iconClone = null;
|
|
430
|
+
if (!svg) return;
|
|
431
|
+
|
|
432
|
+
const clone = svg.cloneNode(true);
|
|
433
|
+
// Remove inline attributes that would override GlassKit styles
|
|
434
|
+
clone.removeAttribute('width');
|
|
435
|
+
clone.removeAttribute('height');
|
|
436
|
+
clone.removeAttribute('stroke');
|
|
437
|
+
clone.removeAttribute('stroke-width');
|
|
438
|
+
clone.removeAttribute('stroke-linecap');
|
|
439
|
+
clone.removeAttribute('stroke-linejoin');
|
|
440
|
+
clone.removeAttribute('fill');
|
|
441
|
+
this._iconEl.insertBefore(clone, this._iconEl.firstChild);
|
|
442
|
+
this._iconClone = clone;
|
|
399
443
|
}
|
|
400
444
|
|
|
401
445
|
setupEvents() {
|
|
@@ -1058,6 +1102,8 @@ class GlkSelect extends GlkFormElement {
|
|
|
1058
1102
|
return ['label', 'disabled', 'name', 'value', 'required'];
|
|
1059
1103
|
}
|
|
1060
1104
|
|
|
1105
|
+
static get observesLightDom() { return true; }
|
|
1106
|
+
|
|
1061
1107
|
render() {
|
|
1062
1108
|
const group = this.createElement('div', ['glass-input-group']);
|
|
1063
1109
|
|
|
@@ -1078,12 +1124,29 @@ class GlkSelect extends GlkFormElement {
|
|
|
1078
1124
|
this._wrapper.appendChild(group);
|
|
1079
1125
|
|
|
1080
1126
|
// Defer option copying — children may not be parsed yet in connectedCallback
|
|
1081
|
-
requestAnimationFrame(() =>
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1127
|
+
requestAnimationFrame(() => this.projectLightDom());
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
projectLightDom() {
|
|
1131
|
+
// The options are pure data — the clones carry no listeners — so skipping an
|
|
1132
|
+
// unchanged rebuild is safe, and it keeps an open dropdown from snapping shut
|
|
1133
|
+
// on light-DOM churn elsewhere.
|
|
1134
|
+
const signature = [...this.querySelectorAll('option')].map(o => o.outerHTML).join('');
|
|
1135
|
+
if (signature === this._optionSignature) return;
|
|
1136
|
+
this._optionSignature = signature;
|
|
1137
|
+
|
|
1138
|
+
// innerHTML = '' below drops the selection, so remember it first. A
|
|
1139
|
+
// selectedIndex of -1 means "nothing is selected", which is not the same as
|
|
1140
|
+
// an option whose value happens to be the empty string.
|
|
1141
|
+
const previous = this._select.selectedIndex >= 0 ? this._select.value : null;
|
|
1142
|
+
|
|
1143
|
+
this._moveOptions();
|
|
1144
|
+
|
|
1145
|
+
// Keep the live selection when it survived the rebuild; otherwise fall back
|
|
1146
|
+
// to the value attribute. Without this the selection jumps back to the first
|
|
1147
|
+
// entry every time the list is updated.
|
|
1148
|
+
if (!this._applyValue(previous)) this._applyValue(this.getAttribute('value'));
|
|
1149
|
+
this._syncFormValue();
|
|
1087
1150
|
}
|
|
1088
1151
|
|
|
1089
1152
|
_moveOptions() {
|
|
@@ -1094,6 +1157,18 @@ class GlkSelect extends GlkFormElement {
|
|
|
1094
1157
|
});
|
|
1095
1158
|
}
|
|
1096
1159
|
|
|
1160
|
+
/**
|
|
1161
|
+
* Selects `value` if an option carries it, and reports whether it did. The
|
|
1162
|
+
* empty string is a value like any other — "" is a real option in plenty of
|
|
1163
|
+
* forms ("detect automatically", "enter your own below").
|
|
1164
|
+
*/
|
|
1165
|
+
_applyValue(value) {
|
|
1166
|
+
if (value === null) return false;
|
|
1167
|
+
if (![...this._select.options].some(o => o.value === value)) return false;
|
|
1168
|
+
this._select.value = value;
|
|
1169
|
+
return true;
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1097
1172
|
setupEvents() {
|
|
1098
1173
|
this._onChange = () => {
|
|
1099
1174
|
this._syncFormValue();
|
|
@@ -1120,7 +1195,7 @@ class GlkSelect extends GlkFormElement {
|
|
|
1120
1195
|
this._select.setAttribute('name', this.getAttribute('name') || '');
|
|
1121
1196
|
break;
|
|
1122
1197
|
case 'value':
|
|
1123
|
-
this.
|
|
1198
|
+
this._applyValue(this.getAttribute('value'));
|
|
1124
1199
|
this._syncFormValue();
|
|
1125
1200
|
break;
|
|
1126
1201
|
}
|
|
@@ -1830,6 +1905,8 @@ class GlkModal extends GlkElement {
|
|
|
1830
1905
|
return ['open', 'title'];
|
|
1831
1906
|
}
|
|
1832
1907
|
|
|
1908
|
+
static get observesLightDom() { return true; }
|
|
1909
|
+
|
|
1833
1910
|
render() {
|
|
1834
1911
|
this._overlay = this.createElement('div', ['glass-modal-overlay'], { part: 'overlay' });
|
|
1835
1912
|
|
|
@@ -1853,7 +1930,7 @@ class GlkModal extends GlkElement {
|
|
|
1853
1930
|
modal.appendChild(this._footer);
|
|
1854
1931
|
|
|
1855
1932
|
// Defer footer population — children may not be parsed yet
|
|
1856
|
-
requestAnimationFrame(() => this.
|
|
1933
|
+
requestAnimationFrame(() => this.projectLightDom());
|
|
1857
1934
|
|
|
1858
1935
|
this._overlay.appendChild(modal);
|
|
1859
1936
|
this._wrapper.appendChild(this._overlay);
|
|
@@ -1863,18 +1940,23 @@ class GlkModal extends GlkElement {
|
|
|
1863
1940
|
}
|
|
1864
1941
|
}
|
|
1865
1942
|
|
|
1866
|
-
|
|
1943
|
+
projectLightDom() {
|
|
1944
|
+
const buttons = [...this.querySelectorAll('[slot="actions"] button')];
|
|
1945
|
+
const signature = buttons.map(b => b.outerHTML).join('');
|
|
1946
|
+
if (signature === this._footerSignature) return;
|
|
1947
|
+
this._footerSignature = signature;
|
|
1948
|
+
|
|
1867
1949
|
this._footer.innerHTML = '';
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
this._footer.appendChild(clone);
|
|
1950
|
+
buttons.forEach((btn, i) => {
|
|
1951
|
+
const clone = btn.cloneNode(true);
|
|
1952
|
+
// Look the original up again at click time instead of closing over it: a
|
|
1953
|
+
// framework that re-renders replaces the node, and a captured reference
|
|
1954
|
+
// would then forward the click to a button no longer in the document.
|
|
1955
|
+
clone.addEventListener('click', () => {
|
|
1956
|
+
this.querySelectorAll('[slot="actions"] button')[i]?.click();
|
|
1876
1957
|
});
|
|
1877
|
-
|
|
1958
|
+
this._footer.appendChild(clone);
|
|
1959
|
+
});
|
|
1878
1960
|
}
|
|
1879
1961
|
|
|
1880
1962
|
setupEvents() {
|
|
@@ -107,6 +107,14 @@ var GlassKitElements = (function (exports) {
|
|
|
107
107
|
*/
|
|
108
108
|
static get hostStyles() { return null; }
|
|
109
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Opt in when the component copies light-DOM children into its shadow tree.
|
|
112
|
+
* A MutationObserver then calls projectLightDom() again whenever those
|
|
113
|
+
* children change, so a framework that swaps them keeps the rendered element
|
|
114
|
+
* in step. Without it the copy is made once and silently goes stale.
|
|
115
|
+
*/
|
|
116
|
+
static get observesLightDom() { return false; }
|
|
117
|
+
|
|
110
118
|
static get observedAttributes() {
|
|
111
119
|
return [];
|
|
112
120
|
}
|
|
@@ -133,15 +141,26 @@ var GlassKitElements = (function (exports) {
|
|
|
133
141
|
this._shadow.appendChild(this._wrapper);
|
|
134
142
|
|
|
135
143
|
this.render();
|
|
136
|
-
|
|
144
|
+
}
|
|
137
145
|
|
|
138
|
-
|
|
139
|
-
|
|
146
|
+
// Everything below runs on every connect, not just the first. Moving an
|
|
147
|
+
// element in the DOM disconnects and reconnects it, and disconnectedCallback
|
|
148
|
+
// tears all of this down — without re-arming it here a moved element would
|
|
149
|
+
// keep its markup but silently stop reacting.
|
|
150
|
+
this.setupEvents();
|
|
151
|
+
instances.add(this);
|
|
152
|
+
|
|
153
|
+
if (this.constructor.observesLightDom) {
|
|
154
|
+
this._lightDomObserver ??= new MutationObserver(records => this.projectLightDom(records));
|
|
155
|
+
this._lightDomObserver.observe(this, {
|
|
156
|
+
childList: true, subtree: true, characterData: true
|
|
157
|
+
});
|
|
140
158
|
}
|
|
141
159
|
}
|
|
142
160
|
|
|
143
161
|
disconnectedCallback() {
|
|
144
162
|
instances.delete(this);
|
|
163
|
+
this._lightDomObserver?.disconnect();
|
|
145
164
|
this.teardownEvents();
|
|
146
165
|
}
|
|
147
166
|
|
|
@@ -169,6 +188,20 @@ var GlassKitElements = (function (exports) {
|
|
|
169
188
|
/** Subclasses override to react to attribute changes. */
|
|
170
189
|
onAttributeChanged(name, oldValue, newValue) {}
|
|
171
190
|
|
|
191
|
+
/**
|
|
192
|
+
* Subclasses that set observesLightDom override this to (re-)copy their
|
|
193
|
+
* light-DOM children into the shadow tree. Runs on every change to those
|
|
194
|
+
* children, so it has to be safe to call repeatedly.
|
|
195
|
+
*/
|
|
196
|
+
projectLightDom() {}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Escape hatch: re-copy the light-DOM children now. The observer covers the
|
|
200
|
+
* ordinary cases; this is for the ones it cannot see, so nobody has to reach
|
|
201
|
+
* into element.shadowRoot.
|
|
202
|
+
*/
|
|
203
|
+
refresh() { this.projectLightDom(); }
|
|
204
|
+
|
|
172
205
|
// ── Utility Methods ──
|
|
173
206
|
|
|
174
207
|
getBoolAttr(name) {
|
|
@@ -357,6 +390,8 @@ var GlassKitElements = (function (exports) {
|
|
|
357
390
|
return ['label', 'active', 'badge'];
|
|
358
391
|
}
|
|
359
392
|
|
|
393
|
+
static get observesLightDom() { return true; }
|
|
394
|
+
|
|
360
395
|
render() {
|
|
361
396
|
this._btn = this.createElement('button', ['glass-tab-bar__item']);
|
|
362
397
|
if (this.getBoolAttr('active')) this._btn.classList.add('is-active');
|
|
@@ -382,23 +417,32 @@ var GlassKitElements = (function (exports) {
|
|
|
382
417
|
this._wrapper.appendChild(this._btn);
|
|
383
418
|
|
|
384
419
|
// Defer icon cloning — children may not be parsed yet
|
|
385
|
-
requestAnimationFrame(() => this.
|
|
420
|
+
requestAnimationFrame(() => this.projectLightDom());
|
|
386
421
|
}
|
|
387
422
|
|
|
388
|
-
|
|
423
|
+
projectLightDom() {
|
|
389
424
|
const svg = this.querySelector('svg');
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
425
|
+
const signature = svg ? svg.outerHTML : '';
|
|
426
|
+
if (signature === this._iconSignature) return;
|
|
427
|
+
this._iconSignature = signature;
|
|
428
|
+
|
|
429
|
+
// Drop the previous clone by hand: the icon container also holds the badge,
|
|
430
|
+
// and inserting without removing would stack a second icon on every update.
|
|
431
|
+
this._iconClone?.remove();
|
|
432
|
+
this._iconClone = null;
|
|
433
|
+
if (!svg) return;
|
|
434
|
+
|
|
435
|
+
const clone = svg.cloneNode(true);
|
|
436
|
+
// Remove inline attributes that would override GlassKit styles
|
|
437
|
+
clone.removeAttribute('width');
|
|
438
|
+
clone.removeAttribute('height');
|
|
439
|
+
clone.removeAttribute('stroke');
|
|
440
|
+
clone.removeAttribute('stroke-width');
|
|
441
|
+
clone.removeAttribute('stroke-linecap');
|
|
442
|
+
clone.removeAttribute('stroke-linejoin');
|
|
443
|
+
clone.removeAttribute('fill');
|
|
444
|
+
this._iconEl.insertBefore(clone, this._iconEl.firstChild);
|
|
445
|
+
this._iconClone = clone;
|
|
402
446
|
}
|
|
403
447
|
|
|
404
448
|
setupEvents() {
|
|
@@ -1061,6 +1105,8 @@ var GlassKitElements = (function (exports) {
|
|
|
1061
1105
|
return ['label', 'disabled', 'name', 'value', 'required'];
|
|
1062
1106
|
}
|
|
1063
1107
|
|
|
1108
|
+
static get observesLightDom() { return true; }
|
|
1109
|
+
|
|
1064
1110
|
render() {
|
|
1065
1111
|
const group = this.createElement('div', ['glass-input-group']);
|
|
1066
1112
|
|
|
@@ -1081,12 +1127,29 @@ var GlassKitElements = (function (exports) {
|
|
|
1081
1127
|
this._wrapper.appendChild(group);
|
|
1082
1128
|
|
|
1083
1129
|
// Defer option copying — children may not be parsed yet in connectedCallback
|
|
1084
|
-
requestAnimationFrame(() =>
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1130
|
+
requestAnimationFrame(() => this.projectLightDom());
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
projectLightDom() {
|
|
1134
|
+
// The options are pure data — the clones carry no listeners — so skipping an
|
|
1135
|
+
// unchanged rebuild is safe, and it keeps an open dropdown from snapping shut
|
|
1136
|
+
// on light-DOM churn elsewhere.
|
|
1137
|
+
const signature = [...this.querySelectorAll('option')].map(o => o.outerHTML).join('');
|
|
1138
|
+
if (signature === this._optionSignature) return;
|
|
1139
|
+
this._optionSignature = signature;
|
|
1140
|
+
|
|
1141
|
+
// innerHTML = '' below drops the selection, so remember it first. A
|
|
1142
|
+
// selectedIndex of -1 means "nothing is selected", which is not the same as
|
|
1143
|
+
// an option whose value happens to be the empty string.
|
|
1144
|
+
const previous = this._select.selectedIndex >= 0 ? this._select.value : null;
|
|
1145
|
+
|
|
1146
|
+
this._moveOptions();
|
|
1147
|
+
|
|
1148
|
+
// Keep the live selection when it survived the rebuild; otherwise fall back
|
|
1149
|
+
// to the value attribute. Without this the selection jumps back to the first
|
|
1150
|
+
// entry every time the list is updated.
|
|
1151
|
+
if (!this._applyValue(previous)) this._applyValue(this.getAttribute('value'));
|
|
1152
|
+
this._syncFormValue();
|
|
1090
1153
|
}
|
|
1091
1154
|
|
|
1092
1155
|
_moveOptions() {
|
|
@@ -1097,6 +1160,18 @@ var GlassKitElements = (function (exports) {
|
|
|
1097
1160
|
});
|
|
1098
1161
|
}
|
|
1099
1162
|
|
|
1163
|
+
/**
|
|
1164
|
+
* Selects `value` if an option carries it, and reports whether it did. The
|
|
1165
|
+
* empty string is a value like any other — "" is a real option in plenty of
|
|
1166
|
+
* forms ("detect automatically", "enter your own below").
|
|
1167
|
+
*/
|
|
1168
|
+
_applyValue(value) {
|
|
1169
|
+
if (value === null) return false;
|
|
1170
|
+
if (![...this._select.options].some(o => o.value === value)) return false;
|
|
1171
|
+
this._select.value = value;
|
|
1172
|
+
return true;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1100
1175
|
setupEvents() {
|
|
1101
1176
|
this._onChange = () => {
|
|
1102
1177
|
this._syncFormValue();
|
|
@@ -1123,7 +1198,7 @@ var GlassKitElements = (function (exports) {
|
|
|
1123
1198
|
this._select.setAttribute('name', this.getAttribute('name') || '');
|
|
1124
1199
|
break;
|
|
1125
1200
|
case 'value':
|
|
1126
|
-
this.
|
|
1201
|
+
this._applyValue(this.getAttribute('value'));
|
|
1127
1202
|
this._syncFormValue();
|
|
1128
1203
|
break;
|
|
1129
1204
|
}
|
|
@@ -1833,6 +1908,8 @@ var GlassKitElements = (function (exports) {
|
|
|
1833
1908
|
return ['open', 'title'];
|
|
1834
1909
|
}
|
|
1835
1910
|
|
|
1911
|
+
static get observesLightDom() { return true; }
|
|
1912
|
+
|
|
1836
1913
|
render() {
|
|
1837
1914
|
this._overlay = this.createElement('div', ['glass-modal-overlay'], { part: 'overlay' });
|
|
1838
1915
|
|
|
@@ -1856,7 +1933,7 @@ var GlassKitElements = (function (exports) {
|
|
|
1856
1933
|
modal.appendChild(this._footer);
|
|
1857
1934
|
|
|
1858
1935
|
// Defer footer population — children may not be parsed yet
|
|
1859
|
-
requestAnimationFrame(() => this.
|
|
1936
|
+
requestAnimationFrame(() => this.projectLightDom());
|
|
1860
1937
|
|
|
1861
1938
|
this._overlay.appendChild(modal);
|
|
1862
1939
|
this._wrapper.appendChild(this._overlay);
|
|
@@ -1866,18 +1943,23 @@ var GlassKitElements = (function (exports) {
|
|
|
1866
1943
|
}
|
|
1867
1944
|
}
|
|
1868
1945
|
|
|
1869
|
-
|
|
1946
|
+
projectLightDom() {
|
|
1947
|
+
const buttons = [...this.querySelectorAll('[slot="actions"] button')];
|
|
1948
|
+
const signature = buttons.map(b => b.outerHTML).join('');
|
|
1949
|
+
if (signature === this._footerSignature) return;
|
|
1950
|
+
this._footerSignature = signature;
|
|
1951
|
+
|
|
1870
1952
|
this._footer.innerHTML = '';
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
this._footer.appendChild(clone);
|
|
1953
|
+
buttons.forEach((btn, i) => {
|
|
1954
|
+
const clone = btn.cloneNode(true);
|
|
1955
|
+
// Look the original up again at click time instead of closing over it: a
|
|
1956
|
+
// framework that re-renders replaces the node, and a captured reference
|
|
1957
|
+
// would then forward the click to a button no longer in the document.
|
|
1958
|
+
clone.addEventListener('click', () => {
|
|
1959
|
+
this.querySelectorAll('[slot="actions"] button')[i]?.click();
|
|
1879
1960
|
});
|
|
1880
|
-
|
|
1961
|
+
this._footer.appendChild(clone);
|
|
1962
|
+
});
|
|
1881
1963
|
}
|
|
1882
1964
|
|
|
1883
1965
|
setupEvents() {
|