@vaadin/field-base 22.0.0-alpha5 → 22.0.0-alpha9
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/index.d.ts +7 -15
- package/index.js +7 -15
- package/package.json +24 -18
- package/src/aria-label-controller.d.ts +11 -0
- package/src/aria-label-controller.js +53 -0
- package/src/checked-mixin.d.ts +21 -0
- package/src/checked-mixin.js +54 -0
- package/src/delegate-focus-mixin.d.ts +2 -2
- package/src/delegate-focus-mixin.js +150 -133
- package/src/delegate-state-mixin.d.ts +1 -1
- package/src/delegate-state-mixin.js +100 -88
- package/src/field-mixin.d.ts +39 -0
- package/src/field-mixin.js +317 -0
- package/src/input-constraints-mixin.d.ts +4 -2
- package/src/input-constraints-mixin.js +107 -64
- package/src/input-control-mixin.d.ts +52 -0
- package/src/input-control-mixin.js +170 -0
- package/src/input-controller.d.ts +11 -0
- package/src/input-controller.js +35 -0
- package/src/input-field-mixin.d.ts +2 -16
- package/src/input-field-mixin.js +125 -80
- package/src/input-mixin.d.ts +1 -1
- package/src/input-mixin.js +156 -145
- package/src/label-mixin.d.ts +2 -2
- package/src/label-mixin.js +73 -60
- package/src/pattern-mixin.js +9 -9
- package/src/shadow-focus-mixin.d.ts +21 -0
- package/src/shadow-focus-mixin.js +87 -0
- package/src/slot-controller.d.ts +8 -0
- package/src/slot-controller.js +36 -0
- package/src/slot-label-mixin.d.ts +20 -0
- package/src/slot-label-mixin.js +38 -0
- package/src/slot-styles-mixin.js +38 -31
- package/src/slot-target-mixin.d.ts +32 -0
- package/src/slot-target-mixin.js +110 -0
- package/src/styles/clear-button-styles.d.ts +8 -0
- package/src/styles/clear-button-styles.js +21 -0
- package/src/styles/field-shared-styles.d.ts +8 -0
- package/src/styles/field-shared-styles.js +29 -0
- package/src/styles/input-field-container-styles.d.ts +8 -0
- package/src/styles/input-field-container-styles.js +16 -0
- package/src/styles/input-field-shared-styles.d.ts +8 -0
- package/src/styles/input-field-shared-styles.js +10 -0
- package/src/text-area-controller.d.ts +11 -0
- package/src/text-area-controller.js +38 -0
- package/src/validate-mixin.d.ts +1 -9
- package/src/validate-mixin.js +43 -118
- package/src/active-mixin.d.ts +0 -26
- package/src/active-mixin.js +0 -106
- package/src/aria-label-mixin.d.ts +0 -20
- package/src/aria-label-mixin.js +0 -71
- package/src/char-length-mixin.d.ts +0 -30
- package/src/char-length-mixin.js +0 -42
- package/src/clear-button-mixin.d.ts +0 -28
- package/src/clear-button-mixin.js +0 -82
- package/src/delegate-input-state-mixin.d.ts +0 -43
- package/src/delegate-input-state-mixin.js +0 -63
- package/src/disabled-mixin.d.ts +0 -23
- package/src/disabled-mixin.js +0 -60
- package/src/field-aria-mixin.d.ts +0 -24
- package/src/field-aria-mixin.js +0 -61
- package/src/focus-mixin.d.ts +0 -33
- package/src/focus-mixin.js +0 -104
- package/src/helper-text-mixin.d.ts +0 -24
- package/src/helper-text-mixin.js +0 -144
- package/src/input-slot-mixin.d.ts +0 -26
- package/src/input-slot-mixin.js +0 -71
- package/src/keyboard-mixin.d.ts +0 -32
- package/src/keyboard-mixin.js +0 -51
- package/src/slot-mixin.d.ts +0 -23
- package/src/slot-mixin.js +0 -49
- package/src/tabindex-mixin.d.ts +0 -29
- package/src/tabindex-mixin.js +0 -78
- package/src/text-area-slot-mixin.d.ts +0 -21
- package/src/text-area-slot-mixin.js +0 -56
- package/src/text-field-mixin.d.ts +0 -21
- package/src/text-field-mixin.js +0 -17
|
@@ -5,109 +5,121 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
console.warn(`Please implement the '_delegateStateTarget' property in <${this.localName}>`);
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/** @protected */
|
|
33
|
-
ready() {
|
|
34
|
-
super.ready();
|
|
8
|
+
/**
|
|
9
|
+
* A mixin to delegate properties and attributes to a target element.
|
|
10
|
+
*
|
|
11
|
+
* @polymerMixin
|
|
12
|
+
*/
|
|
13
|
+
export const DelegateStateMixin = dedupingMixin(
|
|
14
|
+
(superclass) =>
|
|
15
|
+
class DelegateStateMixinClass extends superclass {
|
|
16
|
+
static get properties() {
|
|
17
|
+
return {
|
|
18
|
+
/**
|
|
19
|
+
* A target element to which attributes and properties are delegated.
|
|
20
|
+
* @protected
|
|
21
|
+
*/
|
|
22
|
+
stateTarget: {
|
|
23
|
+
type: Object,
|
|
24
|
+
observer: '_stateTargetChanged'
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
35
28
|
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
/**
|
|
30
|
+
* An array of the host attributes to delegate to the target element.
|
|
31
|
+
*/
|
|
32
|
+
static get delegateAttrs() {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
38
35
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
/**
|
|
37
|
+
* An array of the host properties to delegate to the target element.
|
|
38
|
+
*/
|
|
39
|
+
static get delegateProps() {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
43
|
+
/** @protected */
|
|
44
|
+
ready() {
|
|
45
|
+
super.ready();
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
47
|
+
this._createDelegateAttrsObserver();
|
|
48
|
+
this._createDelegatePropsObserver();
|
|
49
|
+
}
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
/** @protected */
|
|
52
|
+
_stateTargetChanged(target) {
|
|
53
|
+
if (target) {
|
|
54
|
+
this._ensureAttrsDelegated();
|
|
55
|
+
this._ensurePropsDelegated();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
59
58
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
});
|
|
65
|
-
}
|
|
59
|
+
/** @protected */
|
|
60
|
+
_createDelegateAttrsObserver() {
|
|
61
|
+
this._createMethodObserver(`_delegateAttrsChanged(${this.constructor.delegateAttrs.join(', ')})`);
|
|
62
|
+
}
|
|
66
63
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
});
|
|
72
|
-
}
|
|
64
|
+
/** @protected */
|
|
65
|
+
_createDelegatePropsObserver() {
|
|
66
|
+
this._createMethodObserver(`_delegatePropsChanged(${this.constructor.delegateProps.join(', ')})`);
|
|
67
|
+
}
|
|
73
68
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
69
|
+
/** @protected */
|
|
70
|
+
_ensureAttrsDelegated() {
|
|
71
|
+
this.constructor.delegateAttrs.forEach((name) => {
|
|
72
|
+
this._delegateAttribute(name, this[name]);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
80
75
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
76
|
+
/** @protected */
|
|
77
|
+
_ensurePropsDelegated() {
|
|
78
|
+
this.constructor.delegateProps.forEach((name) => {
|
|
79
|
+
this._delegateProperty(name, this[name]);
|
|
80
|
+
});
|
|
85
81
|
}
|
|
86
82
|
|
|
87
|
-
|
|
88
|
-
|
|
83
|
+
/** @protected */
|
|
84
|
+
_delegateAttrsChanged(...values) {
|
|
85
|
+
this.constructor.delegateAttrs.forEach((name, index) => {
|
|
86
|
+
this._delegateAttribute(name, values[index]);
|
|
87
|
+
});
|
|
89
88
|
}
|
|
90
89
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
this._delegateStateTarget.removeAttribute(name);
|
|
90
|
+
/** @protected */
|
|
91
|
+
_delegatePropsChanged(...values) {
|
|
92
|
+
this.constructor.delegateProps.forEach((name, index) => {
|
|
93
|
+
this._delegateProperty(name, values[index]);
|
|
94
|
+
});
|
|
97
95
|
}
|
|
98
|
-
}
|
|
99
96
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
97
|
+
/** @protected */
|
|
98
|
+
_delegateAttribute(name, value) {
|
|
99
|
+
if (!this.stateTarget) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (name === 'invalid') {
|
|
104
|
+
this._delegateAttribute('aria-invalid', value ? 'true' : false);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (typeof value === 'boolean') {
|
|
108
|
+
this.stateTarget.toggleAttribute(name, value);
|
|
109
|
+
} else if (value) {
|
|
110
|
+
this.stateTarget.setAttribute(name, value);
|
|
111
|
+
} else {
|
|
112
|
+
this.stateTarget.removeAttribute(name);
|
|
113
|
+
}
|
|
104
114
|
}
|
|
105
115
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
116
|
+
/** @protected */
|
|
117
|
+
_delegateProperty(name, value) {
|
|
118
|
+
if (!this.stateTarget) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
109
121
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
122
|
+
this.stateTarget[name] = value;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { LabelMixin } from './label-mixin.js';
|
|
7
|
+
import { ValidateMixin } from './validate-mixin.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A mixin to provide common field logic: label, error message and helper text.
|
|
11
|
+
*/
|
|
12
|
+
declare function FieldMixin<T extends new (...args: any[]) => {}>(base: T): T & FieldMixinConstructor;
|
|
13
|
+
|
|
14
|
+
interface FieldMixinConstructor {
|
|
15
|
+
new (...args: any[]): FieldMixin;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface FieldMixin extends LabelMixin, ValidateMixin {
|
|
19
|
+
/**
|
|
20
|
+
* A target element to which ARIA attributes are set.
|
|
21
|
+
*/
|
|
22
|
+
ariaTarget: HTMLElement;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* String used for the helper text.
|
|
26
|
+
*
|
|
27
|
+
* @attr {string} helper-text
|
|
28
|
+
*/
|
|
29
|
+
helperText: string | null | undefined;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Error to show when the field is invalid.
|
|
33
|
+
*
|
|
34
|
+
* @attr {string} error-message
|
|
35
|
+
*/
|
|
36
|
+
errorMessage: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { FieldMixin, FieldMixinConstructor };
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { FlattenedNodesObserver } from '@polymer/polymer/lib/utils/flattened-nodes-observer.js';
|
|
7
|
+
import { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
|
8
|
+
import { animationFrame } from '@vaadin/component-base/src/async.js';
|
|
9
|
+
import { LabelMixin } from './label-mixin.js';
|
|
10
|
+
import { ValidateMixin } from './validate-mixin.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A mixin to provide common field logic: label, error message and helper text.
|
|
14
|
+
*
|
|
15
|
+
* @polymerMixin
|
|
16
|
+
* @mixes LabelMixin
|
|
17
|
+
* @mixes ValidateMixin
|
|
18
|
+
*/
|
|
19
|
+
export const FieldMixin = (superclass) =>
|
|
20
|
+
class FieldMixinClass extends ValidateMixin(LabelMixin(superclass)) {
|
|
21
|
+
static get properties() {
|
|
22
|
+
return {
|
|
23
|
+
/**
|
|
24
|
+
* A target element to which ARIA attributes are set.
|
|
25
|
+
* @protected
|
|
26
|
+
*/
|
|
27
|
+
ariaTarget: {
|
|
28
|
+
type: Object,
|
|
29
|
+
observer: '_ariaTargetChanged'
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Error to show when the field is invalid.
|
|
34
|
+
*
|
|
35
|
+
* @attr {string} error-message
|
|
36
|
+
*/
|
|
37
|
+
errorMessage: {
|
|
38
|
+
type: String
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* String used for the helper text.
|
|
43
|
+
* @attr {string} helper-text
|
|
44
|
+
*/
|
|
45
|
+
helperText: {
|
|
46
|
+
type: String,
|
|
47
|
+
observer: '_helperTextChanged'
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
/** @protected */
|
|
51
|
+
_helperId: String
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** @protected */
|
|
56
|
+
get slots() {
|
|
57
|
+
return {
|
|
58
|
+
...super.slots,
|
|
59
|
+
'error-message': () => {
|
|
60
|
+
const error = document.createElement('div');
|
|
61
|
+
error.textContent = this.errorMessage;
|
|
62
|
+
error.setAttribute('aria-live', 'assertive');
|
|
63
|
+
return error;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static get observers() {
|
|
69
|
+
return [
|
|
70
|
+
'__ariaChanged(invalid, _helperId)',
|
|
71
|
+
'__observeOffsetHeight(errorMessage, invalid, label, helperText)',
|
|
72
|
+
'_updateErrorMessage(invalid, errorMessage)'
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** @protected */
|
|
77
|
+
get _errorNode() {
|
|
78
|
+
return this._getDirectSlotChild('error-message');
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** @protected */
|
|
82
|
+
get _helperNode() {
|
|
83
|
+
return this._getDirectSlotChild('helper');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** @protected */
|
|
87
|
+
get _ariaAttr() {
|
|
88
|
+
return 'aria-describedby';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
constructor() {
|
|
92
|
+
super();
|
|
93
|
+
|
|
94
|
+
// Ensure every instance has unique ID
|
|
95
|
+
const uniqueId = (FieldMixinClass._uniqueFieldId = 1 + FieldMixinClass._uniqueFieldId || 0);
|
|
96
|
+
this._errorId = `error-${this.localName}-${uniqueId}`;
|
|
97
|
+
this._helperId = `helper-${this.localName}-${uniqueId}`;
|
|
98
|
+
|
|
99
|
+
// Save generated ID to restore later
|
|
100
|
+
this.__savedHelperId = this._helperId;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** @protected */
|
|
104
|
+
ready() {
|
|
105
|
+
super.ready();
|
|
106
|
+
|
|
107
|
+
const error = this._errorNode;
|
|
108
|
+
if (error) {
|
|
109
|
+
error.id = this._errorId;
|
|
110
|
+
|
|
111
|
+
this.__applyCustomError();
|
|
112
|
+
|
|
113
|
+
this._updateErrorMessage(this.invalid, this.errorMessage);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const helper = this._helperNode;
|
|
117
|
+
if (helper) {
|
|
118
|
+
this.__applyCustomHelper(helper);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
this.__helperSlot = this.shadowRoot.querySelector('[name="helper"]');
|
|
122
|
+
|
|
123
|
+
this.__helperSlotObserver = new FlattenedNodesObserver(this.__helperSlot, (info) => {
|
|
124
|
+
const helper = this._currentHelper;
|
|
125
|
+
|
|
126
|
+
const newHelper = info.addedNodes.find((node) => node !== helper);
|
|
127
|
+
const oldHelper = info.removedNodes.find((node) => node === helper);
|
|
128
|
+
|
|
129
|
+
if (newHelper) {
|
|
130
|
+
// Custom helper is added, remove the previous one.
|
|
131
|
+
if (helper && helper.isConnected) {
|
|
132
|
+
this.removeChild(helper);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
this.__applyCustomHelper(newHelper);
|
|
136
|
+
|
|
137
|
+
this.__helperIdObserver = new MutationObserver((mutations) => {
|
|
138
|
+
mutations.forEach((mutation) => {
|
|
139
|
+
// only handle helper nodes
|
|
140
|
+
if (
|
|
141
|
+
mutation.type === 'attributes' &&
|
|
142
|
+
mutation.attributeName === 'id' &&
|
|
143
|
+
mutation.target === this._currentHelper &&
|
|
144
|
+
mutation.target.id !== this.__savedHelperId
|
|
145
|
+
) {
|
|
146
|
+
this.__updateHelperId(mutation.target);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
this.__helperIdObserver.observe(newHelper, { attributes: true });
|
|
152
|
+
} else if (oldHelper) {
|
|
153
|
+
// The observer does not exist when default helper is removed.
|
|
154
|
+
if (this.__helperIdObserver) {
|
|
155
|
+
this.__helperIdObserver.disconnect();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
this.__applyDefaultHelper(this.helperText);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** @private */
|
|
164
|
+
__applyCustomError() {
|
|
165
|
+
const error = this.__errorMessage;
|
|
166
|
+
if (error && error !== this.errorMessage) {
|
|
167
|
+
this.errorMessage = error;
|
|
168
|
+
delete this.__errorMessage;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** @private */
|
|
173
|
+
__applyCustomHelper(helper) {
|
|
174
|
+
this.__updateHelperId(helper);
|
|
175
|
+
this._currentHelper = helper;
|
|
176
|
+
this.__toggleHasHelper(helper.children.length > 0 || this.__isNotEmpty(helper.textContent));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** @private */
|
|
180
|
+
__isNotEmpty(helperText) {
|
|
181
|
+
return helperText && helperText.trim() !== '';
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** @private */
|
|
185
|
+
__attachDefaultHelper() {
|
|
186
|
+
let helper = this.__defaultHelper;
|
|
187
|
+
|
|
188
|
+
if (!helper) {
|
|
189
|
+
helper = document.createElement('div');
|
|
190
|
+
helper.setAttribute('slot', 'helper');
|
|
191
|
+
this.__defaultHelper = helper;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
helper.id = this.__savedHelperId;
|
|
195
|
+
this.appendChild(helper);
|
|
196
|
+
this._currentHelper = helper;
|
|
197
|
+
|
|
198
|
+
return helper;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** @private */
|
|
202
|
+
__applyDefaultHelper(helperText) {
|
|
203
|
+
let helper = this._helperNode;
|
|
204
|
+
|
|
205
|
+
const hasHelperText = this.__isNotEmpty(helperText);
|
|
206
|
+
if (hasHelperText && !helper) {
|
|
207
|
+
// Create helper lazily
|
|
208
|
+
helper = this.__attachDefaultHelper();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Only set text content for default helper
|
|
212
|
+
if (helper && helper === this.__defaultHelper) {
|
|
213
|
+
helper.textContent = helperText;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
this.__toggleHasHelper(hasHelperText);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** @private */
|
|
220
|
+
__toggleHasHelper(hasHelper) {
|
|
221
|
+
this.toggleAttribute('has-helper', hasHelper);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Dispatch an event if a specific size measurement property has changed.
|
|
226
|
+
* Supporting multiple properties here is needed for `vaadin-text-area`.
|
|
227
|
+
* @protected
|
|
228
|
+
*/
|
|
229
|
+
_dispatchIronResizeEventIfNeeded(prop, value) {
|
|
230
|
+
const oldSize = '__old' + prop;
|
|
231
|
+
if (this[oldSize] !== undefined && this[oldSize] !== value) {
|
|
232
|
+
this.dispatchEvent(new CustomEvent('iron-resize', { bubbles: true, composed: true }));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
this[oldSize] = value;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** @private */
|
|
239
|
+
__observeOffsetHeight() {
|
|
240
|
+
this.__observeOffsetHeightDebouncer = Debouncer.debounce(
|
|
241
|
+
this.__observeOffsetHeightDebouncer,
|
|
242
|
+
animationFrame,
|
|
243
|
+
() => {
|
|
244
|
+
this._dispatchIronResizeEventIfNeeded('Height', this.offsetHeight);
|
|
245
|
+
}
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* @param {boolean} invalid
|
|
251
|
+
* @protected
|
|
252
|
+
*/
|
|
253
|
+
_updateErrorMessage(invalid, errorMessage) {
|
|
254
|
+
const error = this._errorNode;
|
|
255
|
+
if (!error) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// save the custom error message content
|
|
260
|
+
if (error.textContent && !errorMessage) {
|
|
261
|
+
this.__errorMessage = error.textContent.trim();
|
|
262
|
+
}
|
|
263
|
+
const hasError = Boolean(invalid && errorMessage);
|
|
264
|
+
error.textContent = hasError ? errorMessage : '';
|
|
265
|
+
this.toggleAttribute('has-error-message', hasError);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/** @private */
|
|
269
|
+
__updateHelperId(customHelper) {
|
|
270
|
+
let newId;
|
|
271
|
+
|
|
272
|
+
if (customHelper.id) {
|
|
273
|
+
newId = customHelper.id;
|
|
274
|
+
} else {
|
|
275
|
+
newId = this.__savedHelperId;
|
|
276
|
+
customHelper.id = newId;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
this._helperId = newId;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/** @protected */
|
|
283
|
+
_helperTextChanged(helperText) {
|
|
284
|
+
this.__applyDefaultHelper(helperText);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/** @protected */
|
|
288
|
+
_ariaTargetChanged(target) {
|
|
289
|
+
if (target) {
|
|
290
|
+
this._updateAriaAttribute(this.invalid, this._helperId);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/** @protected */
|
|
295
|
+
_updateAriaAttribute(invalid, helperId) {
|
|
296
|
+
const attr = this._ariaAttr;
|
|
297
|
+
|
|
298
|
+
if (this.ariaTarget && attr) {
|
|
299
|
+
// For groups, add all IDs to aria-labelledby rather than aria-describedby -
|
|
300
|
+
// that should guarantee that it's announced when the group is entered.
|
|
301
|
+
const ariaIds = attr === 'aria-describedby' ? [helperId] : [this._labelId, helperId];
|
|
302
|
+
|
|
303
|
+
// Error message ID needs to be dynamically added / removed based on the validity
|
|
304
|
+
// Otherwise assistive technologies would announce the error, even if we hide it.
|
|
305
|
+
if (invalid) {
|
|
306
|
+
ariaIds.push(this._errorId);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
this.ariaTarget.setAttribute(attr, ariaIds.join(' '));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/** @private */
|
|
314
|
+
__ariaChanged(invalid, helperId) {
|
|
315
|
+
this._updateAriaAttribute(invalid, helperId);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
* Copyright (c) 2021 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { DelegateStateMixin } from './delegate-state-mixin.js';
|
|
7
|
+
import { InputMixin } from './input-mixin.js';
|
|
8
|
+
import { ValidateMixin } from './validate-mixin.js';
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* A mixin to combine multiple input validation constraints.
|
|
@@ -16,7 +18,7 @@ interface InputConstraintsMixinConstructor {
|
|
|
16
18
|
new (...args: any[]): InputConstraintsMixin;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
interface InputConstraintsMixin extends
|
|
21
|
+
interface InputConstraintsMixin extends DelegateStateMixin, InputMixin, ValidateMixin {
|
|
20
22
|
/**
|
|
21
23
|
* Returns true if the current input value satisfies all constraints (if any).
|
|
22
24
|
*/
|