@vaadin/field-base 22.0.0-alpha1 → 22.0.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/index.d.ts +10 -9
- package/index.js +10 -9
- package/package.json +25 -19
- package/src/aria-label-controller.d.ts +11 -0
- package/src/aria-label-controller.js +58 -0
- package/src/checked-mixin.d.ts +26 -0
- package/src/checked-mixin.js +54 -0
- package/src/delegate-focus-mixin.d.ts +7 -4
- package/src/delegate-focus-mixin.js +154 -72
- package/src/delegate-state-mixin.d.ts +23 -0
- package/src/delegate-state-mixin.js +125 -0
- package/src/field-mixin.d.ts +39 -0
- package/src/field-mixin.js +317 -0
- package/src/input-constraints-mixin.d.ts +28 -0
- package/src/input-constraints-mixin.js +126 -0
- 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 -22
- package/src/input-field-mixin.js +117 -168
- package/src/input-mixin.d.ts +22 -6
- package/src/input-mixin.js +161 -51
- package/src/label-mixin.d.ts +2 -2
- package/src/label-mixin.js +74 -60
- package/src/pattern-mixin.d.ts +32 -0
- package/src/pattern-mixin.js +72 -0
- 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.d.ts +24 -0
- package/src/slot-styles-mixin.js +76 -0
- 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/clear-button-mixin.d.ts +0 -32
- package/src/clear-button-mixin.js +0 -87
- package/src/disabled-mixin.d.ts +0 -23
- package/src/disabled-mixin.js +0 -48
- 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 -109
- package/src/input-aria-mixin.d.ts +0 -20
- package/src/input-aria-mixin.js +0 -69
- package/src/input-props-mixin.d.ts +0 -40
- package/src/input-props-mixin.js +0 -106
- package/src/slot-mixin.d.ts +0 -23
- package/src/slot-mixin.js +0 -55
- package/src/text-field-mixin.d.ts +0 -47
- package/src/text-field-mixin.js +0 -125
package/src/input-mixin.js
CHANGED
|
@@ -4,67 +4,177 @@
|
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
|
|
7
|
-
import { SlotMixin } from './slot-mixin.js';
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
/**
|
|
9
|
+
* A mixin to store the reference to an input element
|
|
10
|
+
* and add input and change event listeners to it.
|
|
11
|
+
*
|
|
12
|
+
* @polymerMixin
|
|
13
|
+
*/
|
|
14
|
+
export const InputMixin = dedupingMixin(
|
|
15
|
+
(superclass) =>
|
|
16
|
+
class InputMixinClass extends superclass {
|
|
17
|
+
static get properties() {
|
|
18
|
+
return {
|
|
19
|
+
/**
|
|
20
|
+
* A reference to the input element controlled by the mixin.
|
|
21
|
+
* Any component implementing this mixin is expected to provide it
|
|
22
|
+
* by using `this._setInputElement(input)` Polymer API.
|
|
23
|
+
*
|
|
24
|
+
* A typical case is using `InputController` that does this automatically.
|
|
25
|
+
* However, the input element does not have to always be native <input>:
|
|
26
|
+
* as an example, <vaadin-combo-box-light> accepts other components.
|
|
27
|
+
*
|
|
28
|
+
* @protected
|
|
29
|
+
* @type {!HTMLElement}
|
|
30
|
+
*/
|
|
31
|
+
inputElement: {
|
|
32
|
+
type: Object,
|
|
33
|
+
readOnly: true,
|
|
34
|
+
observer: '_inputElementChanged'
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* String used to define input type.
|
|
39
|
+
* @protected
|
|
40
|
+
*/
|
|
41
|
+
type: {
|
|
42
|
+
type: String,
|
|
43
|
+
readOnly: true
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The value of the field.
|
|
48
|
+
*/
|
|
49
|
+
value: {
|
|
50
|
+
type: String,
|
|
51
|
+
value: '',
|
|
52
|
+
observer: '_valueChanged',
|
|
53
|
+
notify: true
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
constructor() {
|
|
59
|
+
super();
|
|
60
|
+
|
|
61
|
+
this._boundOnInput = this._onInput.bind(this);
|
|
62
|
+
this._boundOnChange = this._onChange.bind(this);
|
|
63
|
+
}
|
|
64
|
+
|
|
12
65
|
/**
|
|
13
|
-
*
|
|
66
|
+
* Clear the value of the field.
|
|
14
67
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
68
|
+
clear() {
|
|
69
|
+
this.value = '';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Add event listeners to the input element instance.
|
|
74
|
+
* Override this method to add custom listeners.
|
|
75
|
+
* @param {!HTMLElement} input
|
|
76
|
+
*/
|
|
77
|
+
_addInputListeners(input) {
|
|
78
|
+
input.addEventListener('input', this._boundOnInput);
|
|
79
|
+
input.addEventListener('change', this._boundOnChange);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Remove event listeners from the input element instance.
|
|
84
|
+
* @param {!HTMLElement} input
|
|
85
|
+
*/
|
|
86
|
+
_removeInputListeners(input) {
|
|
87
|
+
input.removeEventListener('input', this._boundOnInput);
|
|
88
|
+
input.removeEventListener('change', this._boundOnChange);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* A method to forward the value property set on the field
|
|
93
|
+
* programmatically back to the input element value.
|
|
94
|
+
* Override this method to perform additional checks,
|
|
95
|
+
* for example to skip this in certain conditions.
|
|
96
|
+
* @param {string} value
|
|
97
|
+
* @protected
|
|
98
|
+
* @override
|
|
99
|
+
*/
|
|
100
|
+
_forwardInputValue(value) {
|
|
101
|
+
// Value might be set before an input element is initialized.
|
|
102
|
+
// This case should be handled separately by a component that
|
|
103
|
+
// implements this mixin, for example in `connectedCallback`.
|
|
104
|
+
if (!this.inputElement) {
|
|
105
|
+
return;
|
|
19
106
|
}
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
107
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const native = document.createElement('input');
|
|
28
|
-
const value = this.getAttribute('value');
|
|
29
|
-
if (value) {
|
|
30
|
-
native.setAttribute('value', value);
|
|
31
|
-
}
|
|
32
|
-
const name = this.getAttribute('name');
|
|
33
|
-
if (name) {
|
|
34
|
-
native.setAttribute('name', name);
|
|
35
|
-
}
|
|
36
|
-
if (this.type) {
|
|
37
|
-
native.setAttribute('type', this.type);
|
|
38
|
-
}
|
|
39
|
-
return native;
|
|
108
|
+
if (value != undefined) {
|
|
109
|
+
this.inputElement.value = value;
|
|
110
|
+
} else {
|
|
111
|
+
this.inputElement.value = '';
|
|
40
112
|
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
113
|
+
}
|
|
43
114
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
115
|
+
/** @protected */
|
|
116
|
+
_inputElementChanged(input, oldInput) {
|
|
117
|
+
if (input) {
|
|
118
|
+
this._addInputListeners(input);
|
|
119
|
+
} else if (oldInput) {
|
|
120
|
+
this._removeInputListeners(oldInput);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
48
123
|
|
|
49
|
-
|
|
50
|
-
|
|
124
|
+
/**
|
|
125
|
+
* An input event listener used to update the field value.
|
|
126
|
+
* Override this method with an actual implementation.
|
|
127
|
+
* @param {Event} _event
|
|
128
|
+
* @protected
|
|
129
|
+
* @override
|
|
130
|
+
*/
|
|
131
|
+
_onInput(event) {
|
|
132
|
+
// Ignore fake input events e.g. used by clear button.
|
|
133
|
+
this.__userInput = event.isTrusted;
|
|
134
|
+
this.value = event.target.value;
|
|
135
|
+
this.__userInput = false;
|
|
136
|
+
}
|
|
51
137
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
138
|
+
/**
|
|
139
|
+
* A change event listener.
|
|
140
|
+
* Override this method with an actual implementation.
|
|
141
|
+
* @param {Event} _event
|
|
142
|
+
* @protected
|
|
143
|
+
* @override
|
|
144
|
+
*/
|
|
145
|
+
_onChange(_event) {}
|
|
56
146
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Toggle the has-value attribute based on the value property.
|
|
149
|
+
* @param {boolean} hasValue
|
|
150
|
+
* @protected
|
|
151
|
+
*/
|
|
152
|
+
_toggleHasValue(hasValue) {
|
|
153
|
+
this.toggleAttribute('has-value', hasValue);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Observer called when a value property changes.
|
|
158
|
+
* @param {string | undefined} newVal
|
|
159
|
+
* @param {string | undefined} oldVal
|
|
160
|
+
* @protected
|
|
161
|
+
* @override
|
|
162
|
+
*/
|
|
163
|
+
_valueChanged(newVal, oldVal) {
|
|
164
|
+
this._toggleHasValue(newVal !== '' && newVal != null);
|
|
165
|
+
|
|
166
|
+
// Setting initial value to empty string, do nothing.
|
|
167
|
+
if (newVal === '' && oldVal === undefined) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Value is set by the user, no need to sync it back to input.
|
|
172
|
+
if (this.__userInput) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
60
175
|
|
|
61
|
-
|
|
62
|
-
this.
|
|
176
|
+
// Setting a value programmatically, sync it to input element.
|
|
177
|
+
this._forwardInputValue(newVal);
|
|
63
178
|
}
|
|
64
179
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* A mixin to add `<input>` element to the corresponding named slot.
|
|
69
|
-
*/
|
|
70
|
-
export const InputMixin = dedupingMixin(InputMixinImplementation);
|
|
180
|
+
);
|
package/src/label-mixin.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
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 { SlotMixin } from '
|
|
6
|
+
import { SlotMixin } from '@vaadin/component-base/src/slot-mixin.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* A mixin to provide label via corresponding property or named slot.
|
|
@@ -18,7 +18,7 @@ interface LabelMixin extends SlotMixin {
|
|
|
18
18
|
/**
|
|
19
19
|
* String used for a label element.
|
|
20
20
|
*/
|
|
21
|
-
label: string;
|
|
21
|
+
label: string | null | undefined;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export { LabelMixinConstructor, LabelMixin };
|
package/src/label-mixin.js
CHANGED
|
@@ -4,77 +4,91 @@
|
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
|
|
7
|
-
import { SlotMixin } from '
|
|
7
|
+
import { SlotMixin } from '@vaadin/component-base/src/slot-mixin.js';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
9
|
+
/**
|
|
10
|
+
* A mixin to provide label via corresponding property or named slot.
|
|
11
|
+
*
|
|
12
|
+
* @polymerMixin
|
|
13
|
+
* @mixes SlotMixin
|
|
14
|
+
*/
|
|
15
|
+
export const LabelMixin = dedupingMixin(
|
|
16
|
+
(superclass) =>
|
|
17
|
+
class LabelMixinClass extends SlotMixin(superclass) {
|
|
18
|
+
static get properties() {
|
|
19
|
+
return {
|
|
20
|
+
/**
|
|
21
|
+
* The label text for the input node.
|
|
22
|
+
* When no light dom defined via [slot=label], this value will be used.
|
|
23
|
+
*/
|
|
24
|
+
label: {
|
|
25
|
+
type: String,
|
|
26
|
+
observer: '_labelChanged'
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
23
30
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
/** @protected */
|
|
32
|
+
get slots() {
|
|
33
|
+
return {
|
|
34
|
+
...super.slots,
|
|
35
|
+
label: () => {
|
|
36
|
+
const label = document.createElement('label');
|
|
37
|
+
label.textContent = this.label;
|
|
38
|
+
return label;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
34
42
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
/** @protected */
|
|
44
|
+
get _labelNode() {
|
|
45
|
+
return this._getDirectSlotChild('label');
|
|
46
|
+
}
|
|
39
47
|
|
|
40
|
-
|
|
41
|
-
|
|
48
|
+
constructor() {
|
|
49
|
+
super();
|
|
42
50
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
51
|
+
// Ensure every instance has unique ID
|
|
52
|
+
const uniqueId = (LabelMixinClass._uniqueLabelId = 1 + LabelMixinClass._uniqueLabelId || 0);
|
|
53
|
+
this._labelId = `label-${this.localName}-${uniqueId}`;
|
|
47
54
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
/**
|
|
56
|
+
* @type {MutationObserver}
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
this.__labelNodeObserver = new MutationObserver(() => {
|
|
60
|
+
this._toggleHasLabelAttribute();
|
|
61
|
+
});
|
|
62
|
+
}
|
|
51
63
|
|
|
52
|
-
|
|
53
|
-
|
|
64
|
+
/** @protected */
|
|
65
|
+
ready() {
|
|
66
|
+
super.ready();
|
|
54
67
|
|
|
55
|
-
this.
|
|
56
|
-
|
|
57
|
-
|
|
68
|
+
if (this._labelNode) {
|
|
69
|
+
this._labelNode.id = this._labelId;
|
|
70
|
+
this._toggleHasLabelAttribute();
|
|
58
71
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const label = this._labelNode.textContent;
|
|
62
|
-
if (label !== this.label) {
|
|
63
|
-
this.label = label;
|
|
72
|
+
this.__labelNodeObserver.observe(this._labelNode, { childList: true });
|
|
73
|
+
}
|
|
64
74
|
}
|
|
65
|
-
}
|
|
66
75
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
/** @protected */
|
|
77
|
+
_labelChanged(label) {
|
|
78
|
+
if (this._labelNode) {
|
|
79
|
+
this._labelNode.textContent = label;
|
|
80
|
+
this._toggleHasLabelAttribute();
|
|
81
|
+
}
|
|
71
82
|
}
|
|
72
83
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
84
|
+
/** @protected */
|
|
85
|
+
_toggleHasLabelAttribute() {
|
|
86
|
+
if (this._labelNode) {
|
|
87
|
+
const hasLabel = this._labelNode.children.length > 0 || this._labelNode.textContent.trim() !== '';
|
|
76
88
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
89
|
+
this.toggleAttribute('has-label', hasLabel);
|
|
90
|
+
this.dispatchEvent(new CustomEvent('has-label-changed', { detail: { value: hasLabel } }));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
);
|
|
@@ -0,0 +1,32 @@
|
|
|
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 { InputConstraintsMixin } from './input-constraints-mixin.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A mixin to provide `pattern` and `preventInvalidInput` properties.
|
|
10
|
+
*/
|
|
11
|
+
declare function PatternMixin<T extends new (...args: any[]) => {}>(base: T): T & PatternMixinConstructor;
|
|
12
|
+
|
|
13
|
+
interface PatternMixinConstructor {
|
|
14
|
+
new (...args: any[]): PatternMixin;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface PatternMixin extends InputConstraintsMixin {
|
|
18
|
+
/**
|
|
19
|
+
* A regular expression that the value is checked against.
|
|
20
|
+
* The pattern must match the entire value, not just some subset.
|
|
21
|
+
*/
|
|
22
|
+
pattern: string;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* When set to true, user is prevented from typing a value that
|
|
26
|
+
* conflicts with the given `pattern`.
|
|
27
|
+
* @attr {boolean} prevent-invalid-input
|
|
28
|
+
*/
|
|
29
|
+
preventInvalidInput: boolean | null | undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { PatternMixin, PatternMixinConstructor };
|
|
@@ -0,0 +1,72 @@
|
|
|
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 { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
|
7
|
+
import { timeOut } from '@vaadin/component-base/src/async.js';
|
|
8
|
+
import { InputConstraintsMixin } from './input-constraints-mixin.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A mixin to provide `pattern` and `preventInvalidInput` properties.
|
|
12
|
+
*
|
|
13
|
+
* @polymerMixin
|
|
14
|
+
* @mixes InputConstraintsMixin
|
|
15
|
+
*/
|
|
16
|
+
export const PatternMixin = (superclass) =>
|
|
17
|
+
class PatternMixinClass extends InputConstraintsMixin(superclass) {
|
|
18
|
+
static get properties() {
|
|
19
|
+
return {
|
|
20
|
+
/**
|
|
21
|
+
* A regular expression that the value is checked against.
|
|
22
|
+
* The pattern must match the entire value, not just some subset.
|
|
23
|
+
*/
|
|
24
|
+
pattern: {
|
|
25
|
+
type: String
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* When set to true, user is prevented from typing a value that
|
|
30
|
+
* conflicts with the given `pattern`.
|
|
31
|
+
* @attr {boolean} prevent-invalid-input
|
|
32
|
+
*/
|
|
33
|
+
preventInvalidInput: {
|
|
34
|
+
type: Boolean
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static get delegateAttrs() {
|
|
40
|
+
return [...super.delegateAttrs, 'pattern'];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static get constraints() {
|
|
44
|
+
return [...super.constraints, 'pattern'];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** @private */
|
|
48
|
+
_checkInputValue() {
|
|
49
|
+
if (this.preventInvalidInput) {
|
|
50
|
+
const input = this.inputElement;
|
|
51
|
+
if (input && input.value.length > 0 && !this.checkValidity()) {
|
|
52
|
+
input.value = this.value || '';
|
|
53
|
+
// add input-prevented attribute for 200ms
|
|
54
|
+
this.setAttribute('input-prevented', '');
|
|
55
|
+
this._inputDebouncer = Debouncer.debounce(this._inputDebouncer, timeOut.after(200), () => {
|
|
56
|
+
this.removeAttribute('input-prevented');
|
|
57
|
+
});
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @param {Event} event
|
|
65
|
+
* @protected
|
|
66
|
+
*/
|
|
67
|
+
_onInput(event) {
|
|
68
|
+
this._checkInputValue();
|
|
69
|
+
|
|
70
|
+
super._onInput(event);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
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 { KeyboardMixin } from '@vaadin/component-base/src/keyboard-mixin.js';
|
|
7
|
+
import { TabindexMixin } from '@vaadin/component-base/src/tabindex-mixin.js';
|
|
8
|
+
import { DelegateFocusMixin } from './delegate-focus-mixin.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A mixin to forward focus to an element in the shadow DOM.
|
|
12
|
+
*/
|
|
13
|
+
declare function ShadowFocusMixin<T extends new (...args: any[]) => {}>(base: T): T & ShadowFocusMixinConstructor;
|
|
14
|
+
|
|
15
|
+
interface ShadowFocusMixinConstructor {
|
|
16
|
+
new (...args: any[]): ShadowFocusMixin;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface ShadowFocusMixin extends KeyboardMixin, TabindexMixin, DelegateFocusMixin {}
|
|
20
|
+
|
|
21
|
+
export { ShadowFocusMixinConstructor, ShadowFocusMixin };
|
|
@@ -0,0 +1,87 @@
|
|
|
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 { KeyboardMixin } from '@vaadin/component-base/src/keyboard-mixin.js';
|
|
7
|
+
import { TabindexMixin } from '@vaadin/component-base/src/tabindex-mixin.js';
|
|
8
|
+
import { DelegateFocusMixin } from './delegate-focus-mixin.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A mixin to forward focus to an element in the shadow DOM.
|
|
12
|
+
*
|
|
13
|
+
* @polymerMixin
|
|
14
|
+
* @mixes DelegateFocusMixin
|
|
15
|
+
* @mixes KeyboardMixin
|
|
16
|
+
* @mixes TabindexMixin
|
|
17
|
+
*/
|
|
18
|
+
export const ShadowFocusMixin = (superClass) =>
|
|
19
|
+
class ShadowFocusMixinClass extends TabindexMixin(DelegateFocusMixin(KeyboardMixin(superClass))) {
|
|
20
|
+
/**
|
|
21
|
+
* Override an event listener from `KeyboardMixin`
|
|
22
|
+
* to prevent setting `focused` on Shift Tab.
|
|
23
|
+
* @param {KeyboardEvent} event
|
|
24
|
+
* @protected
|
|
25
|
+
* @override
|
|
26
|
+
*/
|
|
27
|
+
_onKeyDown(event) {
|
|
28
|
+
super._onKeyDown(event);
|
|
29
|
+
|
|
30
|
+
// When focus moves with Shift + Tab, do not mark host as focused.
|
|
31
|
+
// The flag set here will be later used in focusin event listener.
|
|
32
|
+
if (!event.defaultPrevented && event.keyCode === 9 && event.shiftKey) {
|
|
33
|
+
this._isShiftTabbing = true;
|
|
34
|
+
HTMLElement.prototype.focus.apply(this);
|
|
35
|
+
this._setFocused(false);
|
|
36
|
+
setTimeout(() => (this._isShiftTabbing = false), 0);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Override method inherited from `FocusMixin`
|
|
42
|
+
* to support focusElement in Shadow DOM.
|
|
43
|
+
* @param {Event} event
|
|
44
|
+
* @return {boolean}
|
|
45
|
+
* @protected
|
|
46
|
+
* @override
|
|
47
|
+
*/
|
|
48
|
+
_shouldSetFocus(event) {
|
|
49
|
+
if (!this.disabled && this.focusElement) {
|
|
50
|
+
const path = event.composedPath();
|
|
51
|
+
|
|
52
|
+
// When focus moves from outside and not with Shift + Tab, delegate it to focusElement.
|
|
53
|
+
if (path[0] === this && !this.contains(event.relatedTarget) && !this._isShiftTabbing) {
|
|
54
|
+
this.focusElement.focus();
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (path.includes(this.focusElement)) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Override an observer from `TabindexMixin`.
|
|
68
|
+
* Do not call super to remove tabindex attribute
|
|
69
|
+
* from host when disabled by setting undefined.
|
|
70
|
+
* @param {string} tabindex
|
|
71
|
+
* @protected
|
|
72
|
+
* @override
|
|
73
|
+
*/
|
|
74
|
+
_tabindexChanged(tabindex) {
|
|
75
|
+
if (tabindex !== undefined) {
|
|
76
|
+
this.focusElement.tabIndex = tabindex;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (this.disabled && tabindex) {
|
|
80
|
+
// If tabindex attribute was changed while component was disabled
|
|
81
|
+
if (tabindex !== -1) {
|
|
82
|
+
this.__lastTabIndex = tabindex;
|
|
83
|
+
}
|
|
84
|
+
this.tabindex = undefined;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
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 { ReactiveController } from 'lit';
|
|
7
|
+
|
|
8
|
+
export class SlotController implements ReactiveController {}
|
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
export class SlotController {
|
|
7
|
+
constructor(host, [slotName, slotFactory, slotInitializer]) {
|
|
8
|
+
this.host = host;
|
|
9
|
+
this.slotName = slotName;
|
|
10
|
+
this.slotFactory = slotFactory;
|
|
11
|
+
this.slotInitializer = slotInitializer;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
hostConnected() {
|
|
15
|
+
if (!this.__initialized) {
|
|
16
|
+
const { host, slotName, slotFactory } = this;
|
|
17
|
+
|
|
18
|
+
const slotted = host.querySelector(`[slot=${slotName}]`);
|
|
19
|
+
|
|
20
|
+
if (!slotted) {
|
|
21
|
+
const slotContent = slotFactory(host);
|
|
22
|
+
if (slotContent instanceof Element) {
|
|
23
|
+
slotContent.setAttribute('slot', slotName);
|
|
24
|
+
host.appendChild(slotContent);
|
|
25
|
+
this.__slotContent = slotContent;
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
this.__slotContent = slotted;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
this.slotInitializer(host, this.__slotContent);
|
|
32
|
+
|
|
33
|
+
this.__initialized = true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
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 { SlotTargetMixin } from './slot-target-mixin.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A mixin to forward any content from the default slot to the label node.
|
|
11
|
+
*/
|
|
12
|
+
declare function SlotLabelMixin<T extends new (...args: any[]) => {}>(base: T): T & SlotLabelMixinConstructor;
|
|
13
|
+
|
|
14
|
+
interface SlotLabelMixinConstructor {
|
|
15
|
+
new (...args: any[]): SlotLabelMixin;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface SlotLabelMixin extends SlotTargetMixin, LabelMixin {}
|
|
19
|
+
|
|
20
|
+
export { SlotLabelMixinConstructor, SlotLabelMixin };
|