@shortfuse/materialdesignweb 0.7.2 → 0.7.5
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/components/Button.js +1 -2
- package/components/Checkbox.js +0 -1
- package/components/FilterChip.js +0 -1
- package/components/ListSelect.js +1 -1
- package/components/Radio.js +0 -2
- package/components/SegmentedButton.js +0 -1
- package/components/Select.js +12 -24
- package/components/Slider.js +1 -2
- package/components/Switch.js +0 -1
- package/components/TextArea.js +206 -219
- package/core/CustomElement.js +23 -5
- package/core/ICustomElement.d.ts +8 -5
- package/core/observe.js +17 -19
- package/core/typings.d.ts +2 -1
- package/dist/index.min.js +72 -69
- package/dist/index.min.js.map +4 -4
- package/dist/meta.json +1 -1
- package/mixins/ControlMixin.js +193 -247
- package/mixins/FormAssociatedMixin.js +166 -30
- package/mixins/InputMixin.js +211 -290
- package/mixins/TextFieldMixin.js +18 -13
- package/package.json +8 -5
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
/** @typedef {import('../core/CustomElement.js').default} CustomElement */
|
|
6
6
|
|
|
7
|
-
const DOMString = { nullParser: String };
|
|
8
|
-
|
|
9
7
|
const FORM_IPC_EVENT = 'mdw-form-associated-changed';
|
|
10
8
|
|
|
9
|
+
const DOMString = { nullParser: String, value: '' };
|
|
10
|
+
|
|
11
11
|
/**
|
|
12
12
|
* @param {ReturnType<import('./StateMixin.js').default>} Base
|
|
13
13
|
*/
|
|
@@ -18,7 +18,6 @@ export default function FormAssociatedMixin(Base) {
|
|
|
18
18
|
formAssociated: true,
|
|
19
19
|
})
|
|
20
20
|
.set({
|
|
21
|
-
_valueDirty: false,
|
|
22
21
|
/** @type {EventListener} */
|
|
23
22
|
_ipcListener: null,
|
|
24
23
|
/** @type {EventTarget} */
|
|
@@ -29,44 +28,116 @@ export default function FormAssociatedMixin(Base) {
|
|
|
29
28
|
autocomplete: DOMString,
|
|
30
29
|
name: DOMString,
|
|
31
30
|
readOnly: { attr: 'readonly', type: 'boolean' },
|
|
31
|
+
defaultChecked: { attr: 'checked', type: 'boolean' },
|
|
32
|
+
_checkedDirty: 'boolean',
|
|
33
|
+
/* "Checkedness" */
|
|
34
|
+
_checked: 'boolean',
|
|
32
35
|
required: 'boolean',
|
|
33
36
|
type: DOMString,
|
|
34
37
|
// [CEReactions] attribute [LegacyNullToEmptyString] DOMString value;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
* @param {string} oldValue
|
|
39
|
-
* @param {string} newValue
|
|
40
|
-
*/
|
|
41
|
-
changedCallback(oldValue, newValue) {
|
|
42
|
-
this.propChangedCallback('value', oldValue, newValue);
|
|
43
|
-
},
|
|
44
|
-
},
|
|
38
|
+
_defaultValue: { reflect: true, attr: 'value' },
|
|
39
|
+
_value: { empty: '' },
|
|
40
|
+
_valueDirty: 'boolean',
|
|
45
41
|
_invalid: 'boolean',
|
|
46
42
|
_badInput: 'boolean',
|
|
47
43
|
_validationMessage: 'string',
|
|
48
44
|
_formDisabled: 'boolean',
|
|
45
|
+
_formReset: 'boolean',
|
|
49
46
|
})
|
|
50
47
|
.observe({
|
|
51
48
|
erroredState({ _invalid }) { return _invalid; },
|
|
49
|
+
defaultValue: {
|
|
50
|
+
reflect: false,
|
|
51
|
+
get({ _defaultValue }) {
|
|
52
|
+
return _defaultValue ?? '';
|
|
53
|
+
},
|
|
54
|
+
set(value) {
|
|
55
|
+
this._defaultValue = String(value);
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
_valueBehavior({ type }) {
|
|
59
|
+
switch (type) {
|
|
60
|
+
case 'radio':
|
|
61
|
+
case 'checkbox':
|
|
62
|
+
return 'default/on';
|
|
63
|
+
case 'hidden':
|
|
64
|
+
case 'button':
|
|
65
|
+
case 'submit':
|
|
66
|
+
case 'image':
|
|
67
|
+
case 'reset':
|
|
68
|
+
return 'default';
|
|
69
|
+
case 'file': return 'filename';
|
|
70
|
+
default: return 'value';
|
|
71
|
+
}
|
|
72
|
+
},
|
|
52
73
|
})
|
|
53
|
-
.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
74
|
+
.methods({
|
|
75
|
+
/**
|
|
76
|
+
* Default behavior can should likely be overridden
|
|
77
|
+
* @param {string} value
|
|
78
|
+
*/
|
|
79
|
+
_onSetValue(value) {
|
|
80
|
+
this._value = value;
|
|
81
|
+
},
|
|
82
|
+
/**
|
|
83
|
+
* Default behavior can should likely be overridden
|
|
84
|
+
* @param {boolean} checked
|
|
85
|
+
*/
|
|
86
|
+
_onSetChecked(checked) {
|
|
87
|
+
this._checked = checked;
|
|
88
|
+
},
|
|
89
|
+
})
|
|
90
|
+
.observe({
|
|
59
91
|
value: {
|
|
60
|
-
|
|
61
|
-
|
|
92
|
+
reflect: false,
|
|
93
|
+
get({ _valueBehavior, _defaultValue, _value }) {
|
|
94
|
+
switch (_valueBehavior) {
|
|
95
|
+
default:
|
|
96
|
+
return _value;
|
|
97
|
+
case 'default':
|
|
98
|
+
return _defaultValue ?? '';
|
|
99
|
+
case 'default/on':
|
|
100
|
+
return _defaultValue ?? 'on';
|
|
101
|
+
case 'filename':
|
|
102
|
+
throw new Error('Not supported!');
|
|
103
|
+
}
|
|
62
104
|
},
|
|
63
105
|
/** @param {string} v */
|
|
64
106
|
set(v) {
|
|
65
|
-
this.
|
|
66
|
-
|
|
107
|
+
switch (this._valueBehavior) {
|
|
108
|
+
case 'value':
|
|
109
|
+
this._valueDirty = true;
|
|
110
|
+
this._onSetValue(v);
|
|
111
|
+
break;
|
|
112
|
+
default:
|
|
113
|
+
this.defaultValue = v;
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
/**
|
|
118
|
+
* Part of FormAssociatedMixin for simplicity.
|
|
119
|
+
* Enumerability doesn't guarantee checked state will be passed or used.
|
|
120
|
+
*/
|
|
121
|
+
checked: {
|
|
122
|
+
reflect: false,
|
|
123
|
+
type: 'boolean',
|
|
124
|
+
get({ _checked }) {
|
|
125
|
+
return _checked;
|
|
126
|
+
},
|
|
127
|
+
/** @param {boolean} checked */
|
|
128
|
+
set(checked) {
|
|
129
|
+
this._checkedDirty = true;
|
|
130
|
+
this._onSetChecked(checked);
|
|
67
131
|
},
|
|
68
132
|
},
|
|
69
133
|
})
|
|
134
|
+
.define({
|
|
135
|
+
form() { return this.elementInternals.form; },
|
|
136
|
+
validity() { return this.elementInternals.validity; },
|
|
137
|
+
validationMessage() { return this.elementInternals.validationMessage; },
|
|
138
|
+
willValidate() { return this.elementInternals.willValidate; },
|
|
139
|
+
labels() { return this.elementInternals.labels; },
|
|
140
|
+
})
|
|
70
141
|
.observe({
|
|
71
142
|
disabledState({ _formDisabled, disabled }) {
|
|
72
143
|
if (_formDisabled) return true;
|
|
@@ -124,16 +195,31 @@ export default function FormAssociatedMixin(Base) {
|
|
|
124
195
|
*/
|
|
125
196
|
formAssociatedCallback(form) {
|
|
126
197
|
this.refreshFormAssociation();
|
|
198
|
+
console.debug('FormAssociatedMixin: formAssociatedCallback', this);
|
|
199
|
+
// Set value on association (not done by default?)
|
|
127
200
|
},
|
|
128
201
|
|
|
129
202
|
/**
|
|
130
203
|
* @param {CustomEvent<[string, string]>} event
|
|
131
204
|
* @return {void}
|
|
132
205
|
*/
|
|
133
|
-
|
|
134
206
|
formIPCEvent(event) {
|
|
135
|
-
|
|
136
|
-
|
|
207
|
+
if (event.target instanceof HTMLFormElement && event.target !== this.form) {
|
|
208
|
+
console.warn('Control.formIPCEvent: Abort from wrong form');
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (this.type !== 'radio') {
|
|
212
|
+
console.warn('Control.formIPCEvent: Abort from not radio');
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const [name, value] = event.detail;
|
|
216
|
+
if (this.name !== name) return;
|
|
217
|
+
if (value === this.value) {
|
|
218
|
+
// console.log('Control.formIPCEvent: Continue match', this.name, this.value);
|
|
219
|
+
} else {
|
|
220
|
+
console.debug('FormAssociatedMixin: Unchecking', this);
|
|
221
|
+
this.checked = false;
|
|
222
|
+
}
|
|
137
223
|
},
|
|
138
224
|
|
|
139
225
|
/** @param {boolean} disabled */
|
|
@@ -142,8 +228,10 @@ export default function FormAssociatedMixin(Base) {
|
|
|
142
228
|
},
|
|
143
229
|
|
|
144
230
|
formResetCallback() {
|
|
231
|
+
this._formReset = true; // Fires Change Event
|
|
145
232
|
this._valueDirty = false;
|
|
146
233
|
this.checkValidity();
|
|
234
|
+
this._formReset = false;
|
|
147
235
|
},
|
|
148
236
|
|
|
149
237
|
/**
|
|
@@ -151,10 +239,52 @@ export default function FormAssociatedMixin(Base) {
|
|
|
151
239
|
* @param {'autocomplete'|'restore'} mode
|
|
152
240
|
*/
|
|
153
241
|
formStateRestoreCallback(state, mode) {
|
|
154
|
-
if (
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
242
|
+
if (navigator.userAgent.includes('Edg/')) {
|
|
243
|
+
console.warn('Chromium Bug: 1429585 - Ignoring formStateRestoreCallback on Edge', { state, mode });
|
|
244
|
+
// formStateRestoreCallback is broken on Edge
|
|
245
|
+
// https://bugs.chromium.org/p/chromium/issues/detail?id=1429585
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (typeof state !== 'string') {
|
|
249
|
+
console.warn('FormAssociatedMixin: (Restore) Could not restore', state);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (this.type === 'checkbox' || this.type === 'radio') {
|
|
253
|
+
console.debug('FormAssociatedMixin: (Restore) Setting Checkbox checked state.', state, this);
|
|
254
|
+
this.checked = (state === 'checked');
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
if (this.type === 'radio') {
|
|
258
|
+
// Due to lifecycle quirks, other radio elements on the page may not have
|
|
259
|
+
// been upgraded to Custom Element yet and would not receive
|
|
260
|
+
// the 'uncheck' communication. Delay notice until then.
|
|
261
|
+
this.checked = (state === 'checked');
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
console.debug('FormAssociatedMixin: (Restore) Setting value state.', state, this);
|
|
266
|
+
this.value = state;
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
_updateFormAssociatedValue() {
|
|
270
|
+
switch (this.type) {
|
|
271
|
+
case 'radio':
|
|
272
|
+
if (this.checked) {
|
|
273
|
+
this._notifyRadioChange(this.name, this.value || 'on');
|
|
274
|
+
}
|
|
275
|
+
// Fallthrough
|
|
276
|
+
case 'checkbox':
|
|
277
|
+
if (this.checked) {
|
|
278
|
+
console.log('FormAssociatedMixin: setFormValue', this.name, `(${this.value}, 'checked')`, this);
|
|
279
|
+
this.elementInternals.setFormValue(this.value, 'checked');
|
|
280
|
+
} else {
|
|
281
|
+
console.log('FormAssociatedMixin: setFormValue', this.name, "(null, 'unchecked')", this);
|
|
282
|
+
this.elementInternals.setFormValue(null, 'unchecked');
|
|
283
|
+
}
|
|
284
|
+
break;
|
|
285
|
+
default:
|
|
286
|
+
console.log('FormAssociatedMixin: updating form value', this.name, this.value);
|
|
287
|
+
this.elementInternals.setFormValue(this.value);
|
|
158
288
|
}
|
|
159
289
|
},
|
|
160
290
|
})
|
|
@@ -166,5 +296,11 @@ export default function FormAssociatedMixin(Base) {
|
|
|
166
296
|
// Bind to global if no form is present (used by radio)
|
|
167
297
|
this.refreshFormAssociation();
|
|
168
298
|
},
|
|
299
|
+
checkedChanged() {
|
|
300
|
+
this._updateFormAssociatedValue();
|
|
301
|
+
},
|
|
302
|
+
valueChanged() {
|
|
303
|
+
this._updateFormAssociatedValue();
|
|
304
|
+
},
|
|
169
305
|
});
|
|
170
306
|
}
|