@vaadin/field-base 25.2.0-alpha1 → 25.2.0-alpha10
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/custom-elements.json +1141 -13
- package/package.json +7 -7
- package/src/field-mixin.js +1 -1
- package/src/input-constraints-mixin.js +100 -99
- package/src/input-control-mixin.js +0 -13
- package/src/input-mixin.js +208 -207
- package/src/label-mixin.js +1 -1
- package/src/styles/button-base-styles.js +2 -2
- package/src/validate-mixin.js +86 -94
package/src/input-mixin.js
CHANGED
|
@@ -11,219 +11,220 @@ import { dedupeMixin } from '@open-wc/dedupe-mixin';
|
|
|
11
11
|
*
|
|
12
12
|
* @polymerMixin
|
|
13
13
|
*/
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
type:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
14
|
+
const InputMixinImplementation = (superclass) => {
|
|
15
|
+
return class InputMixinClass extends superclass {
|
|
16
|
+
static get properties() {
|
|
17
|
+
return {
|
|
18
|
+
/**
|
|
19
|
+
* A reference to the input element controlled by the mixin.
|
|
20
|
+
* Any component implementing this mixin is expected to provide it
|
|
21
|
+
* by using `this._setInputElement(input)` API. A typical case is
|
|
22
|
+
* using `InputController` that does this automatically.
|
|
23
|
+
*
|
|
24
|
+
* @protected
|
|
25
|
+
* @type {!HTMLElement}
|
|
26
|
+
*/
|
|
27
|
+
inputElement: {
|
|
28
|
+
type: Object,
|
|
29
|
+
readOnly: true,
|
|
30
|
+
observer: '_inputElementChanged',
|
|
31
|
+
sync: true,
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* String used to define input type.
|
|
36
|
+
* @protected
|
|
37
|
+
*/
|
|
38
|
+
type: {
|
|
39
|
+
type: String,
|
|
40
|
+
readOnly: true,
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The value of the field.
|
|
45
|
+
*/
|
|
46
|
+
value: {
|
|
47
|
+
type: String,
|
|
48
|
+
value: '',
|
|
49
|
+
observer: '_valueChanged',
|
|
50
|
+
notify: true,
|
|
51
|
+
sync: true,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
constructor() {
|
|
57
|
+
super();
|
|
58
|
+
|
|
59
|
+
this._boundOnInput = this._onInput.bind(this);
|
|
60
|
+
this._boundOnChange = this._onChange.bind(this);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Indicates whether the value is different from the default one.
|
|
65
|
+
* Override if the `value` property has a type other than `string`.
|
|
66
|
+
*
|
|
67
|
+
* @protected
|
|
68
|
+
*/
|
|
69
|
+
get _hasValue() {
|
|
70
|
+
return this.value != null && this.value !== '';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* A property for accessing the input element's value.
|
|
75
|
+
*
|
|
76
|
+
* Override this getter if the property is different from the default `value` one.
|
|
77
|
+
*
|
|
78
|
+
* @protected
|
|
79
|
+
* @return {string}
|
|
80
|
+
*/
|
|
81
|
+
get _inputElementValueProperty() {
|
|
82
|
+
return 'value';
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The input element's value.
|
|
87
|
+
*
|
|
88
|
+
* @protected
|
|
89
|
+
* @return {string}
|
|
90
|
+
*/
|
|
91
|
+
get _inputElementValue() {
|
|
92
|
+
return this.inputElement ? this.inputElement[this._inputElementValueProperty] : undefined;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The input element's value.
|
|
97
|
+
*
|
|
98
|
+
* @protected
|
|
99
|
+
*/
|
|
100
|
+
set _inputElementValue(value) {
|
|
101
|
+
if (this.inputElement) {
|
|
102
|
+
this.inputElement[this._inputElementValueProperty] = value;
|
|
55
103
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Clear the value of the field.
|
|
108
|
+
*/
|
|
109
|
+
clear() {
|
|
110
|
+
this.value = '';
|
|
111
|
+
|
|
112
|
+
// Clear the input immediately without waiting for the observer.
|
|
113
|
+
// Otherwise, when using Lit, the old value would be restored.
|
|
114
|
+
this._inputElementValue = '';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Add event listeners to the input element instance.
|
|
119
|
+
* Override this method to add custom listeners.
|
|
120
|
+
* @param {!HTMLElement} input
|
|
121
|
+
* @protected
|
|
122
|
+
*/
|
|
123
|
+
_addInputListeners(input) {
|
|
124
|
+
input.addEventListener('input', this._boundOnInput);
|
|
125
|
+
input.addEventListener('change', this._boundOnChange);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Remove event listeners from the input element instance.
|
|
130
|
+
* @param {!HTMLElement} input
|
|
131
|
+
* @protected
|
|
132
|
+
*/
|
|
133
|
+
_removeInputListeners(input) {
|
|
134
|
+
input.removeEventListener('input', this._boundOnInput);
|
|
135
|
+
input.removeEventListener('change', this._boundOnChange);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* A method to forward the value property set on the field
|
|
140
|
+
* programmatically back to the input element value.
|
|
141
|
+
* Override this method to perform additional checks,
|
|
142
|
+
* for example to skip this in certain conditions.
|
|
143
|
+
* @param {string} value
|
|
144
|
+
* @protected
|
|
145
|
+
*/
|
|
146
|
+
_forwardInputValue(value) {
|
|
147
|
+
// Value might be set before an input element is initialized.
|
|
148
|
+
// This case should be handled separately by a component that
|
|
149
|
+
// implements this mixin, for example in `connectedCallback`.
|
|
150
|
+
if (!this.inputElement) {
|
|
151
|
+
return;
|
|
105
152
|
}
|
|
106
153
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
* Override this method to add custom listeners.
|
|
121
|
-
* @param {!HTMLElement} input
|
|
122
|
-
* @protected
|
|
123
|
-
*/
|
|
124
|
-
_addInputListeners(input) {
|
|
125
|
-
input.addEventListener('input', this._boundOnInput);
|
|
126
|
-
input.addEventListener('change', this._boundOnChange);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Remove event listeners from the input element instance.
|
|
131
|
-
* @param {!HTMLElement} input
|
|
132
|
-
* @protected
|
|
133
|
-
*/
|
|
134
|
-
_removeInputListeners(input) {
|
|
135
|
-
input.removeEventListener('input', this._boundOnInput);
|
|
136
|
-
input.removeEventListener('change', this._boundOnChange);
|
|
154
|
+
this._inputElementValue = value != null ? value : '';
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* @param {HTMLElement | undefined} input
|
|
159
|
+
* @param {HTMLElement | undefined} oldInput
|
|
160
|
+
* @protected
|
|
161
|
+
*/
|
|
162
|
+
_inputElementChanged(input, oldInput) {
|
|
163
|
+
if (input) {
|
|
164
|
+
this._addInputListeners(input);
|
|
165
|
+
} else if (oldInput) {
|
|
166
|
+
this._removeInputListeners(oldInput);
|
|
137
167
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* An input event listener used to update the field value.
|
|
172
|
+
*
|
|
173
|
+
* @param {Event} event
|
|
174
|
+
* @protected
|
|
175
|
+
*/
|
|
176
|
+
_onInput(event) {
|
|
177
|
+
// In the case a custom web component is passed as `inputElement`,
|
|
178
|
+
// the actual native input element, on which the event occurred,
|
|
179
|
+
// can be inside shadow trees.
|
|
180
|
+
const target = event.composedPath()[0];
|
|
181
|
+
// Ignore fake input events e.g. used by clear button.
|
|
182
|
+
this.__userInput = event.isTrusted;
|
|
183
|
+
this.value = target.value;
|
|
184
|
+
this.__userInput = false;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* A change event listener.
|
|
189
|
+
* Override this method with an actual implementation.
|
|
190
|
+
* @param {Event} _event
|
|
191
|
+
* @protected
|
|
192
|
+
*/
|
|
193
|
+
_onChange(_event) {}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Toggle the has-value attribute based on the value property.
|
|
197
|
+
*
|
|
198
|
+
* @param {boolean} hasValue
|
|
199
|
+
* @protected
|
|
200
|
+
*/
|
|
201
|
+
_toggleHasValue(hasValue) {
|
|
202
|
+
this.toggleAttribute('has-value', hasValue);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Observer called when a value property changes.
|
|
207
|
+
* @param {string | undefined} newVal
|
|
208
|
+
* @param {string | undefined} oldVal
|
|
209
|
+
* @protected
|
|
210
|
+
*/
|
|
211
|
+
_valueChanged(newVal, oldVal) {
|
|
212
|
+
this._toggleHasValue(this._hasValue);
|
|
213
|
+
|
|
214
|
+
// Setting initial value to empty string, do nothing.
|
|
215
|
+
if (newVal === '' && oldVal === undefined) {
|
|
216
|
+
return;
|
|
156
217
|
}
|
|
157
218
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
* @protected
|
|
162
|
-
*/
|
|
163
|
-
_inputElementChanged(input, oldInput) {
|
|
164
|
-
if (input) {
|
|
165
|
-
this._addInputListeners(input);
|
|
166
|
-
} else if (oldInput) {
|
|
167
|
-
this._removeInputListeners(oldInput);
|
|
168
|
-
}
|
|
219
|
+
// Value is set by the user, no need to sync it back to input.
|
|
220
|
+
if (this.__userInput) {
|
|
221
|
+
return;
|
|
169
222
|
}
|
|
170
223
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
*/
|
|
177
|
-
_onInput(event) {
|
|
178
|
-
// In the case a custom web component is passed as `inputElement`,
|
|
179
|
-
// the actual native input element, on which the event occurred,
|
|
180
|
-
// can be inside shadow trees.
|
|
181
|
-
const target = event.composedPath()[0];
|
|
182
|
-
// Ignore fake input events e.g. used by clear button.
|
|
183
|
-
this.__userInput = event.isTrusted;
|
|
184
|
-
this.value = target.value;
|
|
185
|
-
this.__userInput = false;
|
|
186
|
-
}
|
|
224
|
+
// Setting a value programmatically, sync it to input element.
|
|
225
|
+
this._forwardInputValue(newVal);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
};
|
|
187
229
|
|
|
188
|
-
|
|
189
|
-
* A change event listener.
|
|
190
|
-
* Override this method with an actual implementation.
|
|
191
|
-
* @param {Event} _event
|
|
192
|
-
* @protected
|
|
193
|
-
*/
|
|
194
|
-
_onChange(_event) {}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Toggle the has-value attribute based on the value property.
|
|
198
|
-
*
|
|
199
|
-
* @param {boolean} hasValue
|
|
200
|
-
* @protected
|
|
201
|
-
*/
|
|
202
|
-
_toggleHasValue(hasValue) {
|
|
203
|
-
this.toggleAttribute('has-value', hasValue);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Observer called when a value property changes.
|
|
208
|
-
* @param {string | undefined} newVal
|
|
209
|
-
* @param {string | undefined} oldVal
|
|
210
|
-
* @protected
|
|
211
|
-
*/
|
|
212
|
-
_valueChanged(newVal, oldVal) {
|
|
213
|
-
this._toggleHasValue(this._hasValue);
|
|
214
|
-
|
|
215
|
-
// Setting initial value to empty string, do nothing.
|
|
216
|
-
if (newVal === '' && oldVal === undefined) {
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// Value is set by the user, no need to sync it back to input.
|
|
221
|
-
if (this.__userInput) {
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Setting a value programmatically, sync it to input element.
|
|
226
|
-
this._forwardInputValue(newVal);
|
|
227
|
-
}
|
|
228
|
-
},
|
|
229
|
-
);
|
|
230
|
+
export const InputMixin = dedupeMixin(InputMixinImplementation);
|
package/src/label-mixin.js
CHANGED
|
@@ -15,8 +15,8 @@ export const button = css`
|
|
|
15
15
|
-webkit-user-select: none;
|
|
16
16
|
user-select: none;
|
|
17
17
|
/* Ensure minimum click target (WCAG) */
|
|
18
|
-
padding: max(0px, (24px - 1lh) / 2);
|
|
19
|
-
margin: min(0px, (24px - 1lh) / -2);
|
|
18
|
+
padding: max(0px, (24px - var(--vaadin-icon-size, 1lh)) / 2);
|
|
19
|
+
margin: min(0px, (24px - var(--vaadin-icon-size, 1lh)) / -2);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/* Icon */
|
package/src/validate-mixin.js
CHANGED
|
@@ -10,107 +10,99 @@ import { dedupeMixin } from '@open-wc/dedupe-mixin';
|
|
|
10
10
|
*
|
|
11
11
|
* @polymerMixin
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
},
|
|
13
|
+
const ValidateMixinImplementation = (superclass) =>
|
|
14
|
+
class extends superclass {
|
|
15
|
+
static get properties() {
|
|
16
|
+
return {
|
|
17
|
+
/**
|
|
18
|
+
* Set to true when the field is invalid.
|
|
19
|
+
*/
|
|
20
|
+
invalid: {
|
|
21
|
+
type: Boolean,
|
|
22
|
+
reflectToAttribute: true,
|
|
23
|
+
notify: true,
|
|
24
|
+
value: false,
|
|
25
|
+
sync: true,
|
|
26
|
+
},
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Set to true to enable manual validation mode. This mode disables automatic
|
|
30
|
+
* constraint validation, allowing you to control the validation process yourself.
|
|
31
|
+
* You can still trigger constraint validation manually with the `validate()` method
|
|
32
|
+
* or use `checkValidity()` to assess the component's validity without affecting
|
|
33
|
+
* the invalid state. In manual validation mode, you can also manipulate
|
|
34
|
+
* the `invalid` property directly through your application logic without conflicts
|
|
35
|
+
* with the component's internal validation.
|
|
36
|
+
*
|
|
37
|
+
* @attr {boolean} manual-validation
|
|
38
|
+
*/
|
|
39
|
+
manualValidation: {
|
|
40
|
+
type: Boolean,
|
|
41
|
+
value: false,
|
|
42
|
+
},
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Specifies that the user must fill in a value.
|
|
46
|
+
*/
|
|
47
|
+
required: {
|
|
48
|
+
type: Boolean,
|
|
49
|
+
reflectToAttribute: true,
|
|
50
|
+
sync: true,
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Validates the field and sets the `invalid` property based on the result.
|
|
57
|
+
*
|
|
58
|
+
* The method fires a `validated` event with the result of the validation.
|
|
59
|
+
*
|
|
60
|
+
* @return {boolean} True if the value is valid.
|
|
61
|
+
*/
|
|
62
|
+
validate() {
|
|
63
|
+
const isValid = this.checkValidity();
|
|
64
|
+
this._setInvalid(!isValid);
|
|
65
|
+
this.dispatchEvent(new CustomEvent('validated', { detail: { valid: isValid } }));
|
|
66
|
+
return isValid;
|
|
67
|
+
}
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Returns true if the field value satisfies all constraints (if any).
|
|
71
|
+
*
|
|
72
|
+
* @return {boolean}
|
|
73
|
+
*/
|
|
74
|
+
checkValidity() {
|
|
75
|
+
return !this.required || !!this.value;
|
|
76
|
+
}
|
|
78
77
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
78
|
+
/**
|
|
79
|
+
* @param {boolean} invalid
|
|
80
|
+
* @protected
|
|
81
|
+
*/
|
|
82
|
+
_setInvalid(invalid) {
|
|
83
|
+
if (this._shouldSetInvalid(invalid)) {
|
|
84
|
+
this.invalid = invalid;
|
|
87
85
|
}
|
|
86
|
+
}
|
|
88
87
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Override this method to define whether the given `invalid` state should be set.
|
|
90
|
+
*
|
|
91
|
+
* @param {boolean} _invalid
|
|
92
|
+
* @return {boolean}
|
|
93
|
+
* @protected
|
|
94
|
+
*/
|
|
95
|
+
_shouldSetInvalid(_invalid) {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
99
|
+
/** @protected */
|
|
100
|
+
_requestValidation() {
|
|
101
|
+
if (!this.manualValidation) {
|
|
102
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
103
|
+
this.validate();
|
|
106
104
|
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
* Fired whenever the field is validated.
|
|
110
|
-
*
|
|
111
|
-
* @event validated
|
|
112
|
-
* @param {Object} detail
|
|
113
|
-
* @param {boolean} detail.valid the result of the validation.
|
|
114
|
-
*/
|
|
115
|
-
},
|
|
116
|
-
);
|
|
108
|
+
export const ValidateMixin = dedupeMixin(ValidateMixinImplementation);
|