@jungherz-de/glasskit-elements 1.21.2 → 1.22.1
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 +31 -1
- package/README.md +6 -12
- package/SKILL.md +38 -68
- package/dist/components/base.js +27 -0
- package/dist/components/glk-checkbox.js +3 -2
- package/dist/components/glk-input.js +78 -10
- package/dist/components/glk-radio.js +3 -2
- package/dist/components/glk-range.js +11 -3
- package/dist/components/glk-search.js +9 -3
- package/dist/components/glk-select.js +31 -8
- package/dist/components/glk-textarea.js +17 -4
- package/dist/components/glk-toggle.js +3 -2
- package/dist/glasskit-elements.esm.js +184 -36
- package/dist/glasskit-elements.js +184 -36
- package/dist/glasskit-elements.min.js +1 -1
- package/package.json +3 -3
- package/src/base.js +27 -0
- package/src/components/forms/glk-checkbox.js +3 -2
- package/src/components/forms/glk-input.js +78 -10
- package/src/components/forms/glk-radio.js +3 -2
- package/src/components/forms/glk-range.js +11 -3
- package/src/components/forms/glk-search.js +9 -3
- package/src/components/forms/glk-select.js +31 -8
- package/src/components/forms/glk-textarea.js +17 -4
- package/src/components/forms/glk-toggle.js +3 -2
|
@@ -28,7 +28,9 @@ class GlkSearch extends GlkFormElement {
|
|
|
28
28
|
const name = this.getAttribute('name');
|
|
29
29
|
if (name) this._input.setAttribute('name', name);
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
// A value set as a property before render() has waited for it.
|
|
32
|
+
const value = this._pendingValue ?? this.getAttribute('value');
|
|
33
|
+
this._pendingValue = undefined;
|
|
32
34
|
if (value) this._input.value = value;
|
|
33
35
|
|
|
34
36
|
if (this.getBoolAttr('disabled')) this._input.disabled = true;
|
|
@@ -90,9 +92,13 @@ class GlkSearch extends GlkFormElement {
|
|
|
90
92
|
this._syncFormValue();
|
|
91
93
|
}
|
|
92
94
|
|
|
93
|
-
get value() { return this._input
|
|
95
|
+
get value() { return this._input ? this._input.value : (this._pendingValue ?? this.getAttribute('value') ?? ''); }
|
|
94
96
|
set value(v) {
|
|
95
|
-
|
|
97
|
+
const value = v == null ? '' : String(v);
|
|
98
|
+
// Frameworks set properties right after creating the element. Before
|
|
99
|
+
// render() the value waits for it — it used to throw.
|
|
100
|
+
if (!this._input) { this._pendingValue = value; return; }
|
|
101
|
+
this._input.value = value;
|
|
96
102
|
this._syncFormValue();
|
|
97
103
|
}
|
|
98
104
|
}
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { GlkFormElement } from './base.js';
|
|
2
2
|
import '@jungherz-de/glasskit/glasskit-styles.js';
|
|
3
3
|
|
|
4
|
+
// The wanted value. A select can show a value only once an option carries it,
|
|
5
|
+
// and the options arrive late: they are copied in a frame after connecting,
|
|
6
|
+
// and a framework may add them later still — while it sets `value` as a
|
|
7
|
+
// property right after creating the element. So the value the attribute or
|
|
8
|
+
// the property asks for is kept as wanted until an option carries it; a
|
|
9
|
+
// choice of the user replaces it. Before 1.22.0 only the attribute was kept:
|
|
10
|
+
// a property set before connecting threw, and one set before the options
|
|
11
|
+
// were copied was lost — the select showed its first option while the app
|
|
12
|
+
// held the other value.
|
|
13
|
+
|
|
4
14
|
class GlkSelect extends GlkFormElement {
|
|
5
15
|
static get observedAttributes() {
|
|
6
16
|
return ['label', 'disabled', 'name', 'value', 'required'];
|
|
@@ -16,6 +26,8 @@ class GlkSelect extends GlkFormElement {
|
|
|
16
26
|
this._labelEl.textContent = this.getAttribute('label') || '';
|
|
17
27
|
|
|
18
28
|
this._select = this.createElement('select', ['glass-select'], { id: 'field' });
|
|
29
|
+
// A value set as a property before render() is wanted already.
|
|
30
|
+
if (this._wanted === undefined) this._wanted = this.getAttribute('value');
|
|
19
31
|
|
|
20
32
|
const name = this.getAttribute('name');
|
|
21
33
|
if (name) this._select.setAttribute('name', name);
|
|
@@ -47,10 +59,10 @@ class GlkSelect extends GlkFormElement {
|
|
|
47
59
|
|
|
48
60
|
this._moveOptions();
|
|
49
61
|
|
|
50
|
-
//
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
if (!this._applyValue(
|
|
62
|
+
// The wanted value first, then the live selection if it survived the
|
|
63
|
+
// rebuild — without that, the selection would jump back to the first entry
|
|
64
|
+
// every time the list is updated.
|
|
65
|
+
if (!this._applyValue(this._wanted)) this._applyValue(previous);
|
|
54
66
|
this._syncFormValue();
|
|
55
67
|
}
|
|
56
68
|
|
|
@@ -76,6 +88,7 @@ class GlkSelect extends GlkFormElement {
|
|
|
76
88
|
|
|
77
89
|
setupEvents() {
|
|
78
90
|
this._onChange = () => {
|
|
91
|
+
this._wanted = null; // the user's choice replaces it
|
|
79
92
|
this._syncFormValue();
|
|
80
93
|
this.emit('glk-change', { value: this._select.value });
|
|
81
94
|
this.dispatchEvent(new Event('change', { bubbles: true }));
|
|
@@ -100,7 +113,8 @@ class GlkSelect extends GlkFormElement {
|
|
|
100
113
|
this._select.setAttribute('name', this.getAttribute('name') || '');
|
|
101
114
|
break;
|
|
102
115
|
case 'value':
|
|
103
|
-
this.
|
|
116
|
+
this._wanted = this.getAttribute('value');
|
|
117
|
+
this._applyValue(this._wanted);
|
|
104
118
|
this._syncFormValue();
|
|
105
119
|
break;
|
|
106
120
|
case 'required':
|
|
@@ -116,13 +130,22 @@ class GlkSelect extends GlkFormElement {
|
|
|
116
130
|
}
|
|
117
131
|
|
|
118
132
|
resetValue() {
|
|
119
|
-
|
|
133
|
+
// Back to what the markup asked for, else the first option.
|
|
134
|
+
this._wanted = this.getAttribute('value');
|
|
135
|
+
if (!this._applyValue(this._wanted)) this._select.selectedIndex = 0;
|
|
120
136
|
this._syncFormValue();
|
|
121
137
|
}
|
|
122
138
|
|
|
123
|
-
get value() {
|
|
139
|
+
get value() {
|
|
140
|
+
// Until options are there, the wanted value is the answer: a framework
|
|
141
|
+
// reads back what it has just set.
|
|
142
|
+
if (!this._select?.options.length) return this._wanted ?? this.getAttribute('value') ?? '';
|
|
143
|
+
return this._select.value;
|
|
144
|
+
}
|
|
124
145
|
set value(v) {
|
|
125
|
-
|
|
146
|
+
this._wanted = v == null ? '' : String(v);
|
|
147
|
+
if (!this._select) return; // render() takes it from here
|
|
148
|
+
this._applyValue(this._wanted);
|
|
126
149
|
this._syncFormValue();
|
|
127
150
|
}
|
|
128
151
|
|
|
@@ -3,7 +3,7 @@ import '@jungherz-de/glasskit/glasskit-styles.js';
|
|
|
3
3
|
|
|
4
4
|
class GlkTextarea extends GlkFormElement {
|
|
5
5
|
static get observedAttributes() {
|
|
6
|
-
return ['label', 'placeholder', 'rows', 'disabled', 'name', 'value', 'required'];
|
|
6
|
+
return ['label', 'placeholder', 'rows', 'disabled', 'readonly', 'name', 'value', 'required'];
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
render() {
|
|
@@ -23,10 +23,13 @@ class GlkTextarea extends GlkFormElement {
|
|
|
23
23
|
const name = this.getAttribute('name');
|
|
24
24
|
if (name) this._textarea.setAttribute('name', name);
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
// A value set as a property before render() has waited for it.
|
|
27
|
+
const value = this._pendingValue ?? this.getAttribute('value');
|
|
28
|
+
this._pendingValue = undefined;
|
|
27
29
|
if (value) this._textarea.value = value;
|
|
28
30
|
|
|
29
31
|
if (this.getBoolAttr('disabled')) this._textarea.disabled = true;
|
|
32
|
+
if (this.getBoolAttr('readonly')) this._textarea.readOnly = true;
|
|
30
33
|
if (this.getBoolAttr('required')) this._textarea.required = true;
|
|
31
34
|
|
|
32
35
|
group.appendChild(this._labelEl);
|
|
@@ -64,6 +67,9 @@ class GlkTextarea extends GlkFormElement {
|
|
|
64
67
|
case 'disabled':
|
|
65
68
|
this._textarea.disabled = this.getBoolAttr('disabled');
|
|
66
69
|
break;
|
|
70
|
+
case 'readonly':
|
|
71
|
+
this._textarea.readOnly = this.getBoolAttr('readonly');
|
|
72
|
+
break;
|
|
67
73
|
case 'name':
|
|
68
74
|
this._textarea.setAttribute('name', this.getAttribute('name') || '');
|
|
69
75
|
break;
|
|
@@ -88,14 +94,21 @@ class GlkTextarea extends GlkFormElement {
|
|
|
88
94
|
this._syncFormValue();
|
|
89
95
|
}
|
|
90
96
|
|
|
91
|
-
get value() { return this._textarea
|
|
97
|
+
get value() { return this._textarea ? this._textarea.value : (this._pendingValue ?? this.getAttribute('value') ?? ''); }
|
|
92
98
|
set value(v) {
|
|
93
|
-
|
|
99
|
+
const value = v == null ? '' : String(v);
|
|
100
|
+
// Frameworks set properties right after creating the element. Before
|
|
101
|
+
// render() the value waits for it — it used to throw.
|
|
102
|
+
if (!this._textarea) { this._pendingValue = value; return; }
|
|
103
|
+
this._textarea.value = value;
|
|
94
104
|
this._syncFormValue();
|
|
95
105
|
}
|
|
96
106
|
|
|
97
107
|
get disabled() { return this.getBoolAttr('disabled'); }
|
|
98
108
|
set disabled(v) { this.setBoolAttr('disabled', v); }
|
|
109
|
+
|
|
110
|
+
get readOnly() { return this.getBoolAttr('readonly'); }
|
|
111
|
+
set readOnly(v) { this.setBoolAttr('readonly', v); }
|
|
99
112
|
}
|
|
100
113
|
|
|
101
114
|
customElements.define('glk-textarea', GlkTextarea);
|
|
@@ -105,11 +105,12 @@ class GlkToggle extends GlkFormElement {
|
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
// Before render() the attribute carries the state: render() reads it.
|
|
109
|
+
get checked() { return this._input ? this._input.checked : this.getBoolAttr('checked'); }
|
|
109
110
|
set checked(v) {
|
|
110
111
|
if (this._input) this._input.checked = v;
|
|
111
112
|
this.setBoolAttr('checked', v);
|
|
112
|
-
this._syncFormValue();
|
|
113
|
+
if (this._input) this._syncFormValue();
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
get disabled() { return this.getBoolAttr('disabled'); }
|