@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
|
@@ -0,0 +1,170 @@
|
|
|
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 { DelegateFocusMixin } from './delegate-focus-mixin.js';
|
|
8
|
+
import { FieldMixin } from './field-mixin.js';
|
|
9
|
+
import { InputConstraintsMixin } from './input-constraints-mixin.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A mixin to provide shared logic for the editable form input controls.
|
|
13
|
+
*
|
|
14
|
+
* @polymerMixin
|
|
15
|
+
* @mixes DelegateFocusMixin
|
|
16
|
+
* @mixes FieldMixin
|
|
17
|
+
* @mixes InputConstraintsMixin
|
|
18
|
+
* @mixes KeyboardMixin
|
|
19
|
+
*/
|
|
20
|
+
export const InputControlMixin = (superclass) =>
|
|
21
|
+
class InputControlMixinClass extends DelegateFocusMixin(
|
|
22
|
+
InputConstraintsMixin(FieldMixin(KeyboardMixin(superclass)))
|
|
23
|
+
) {
|
|
24
|
+
static get properties() {
|
|
25
|
+
return {
|
|
26
|
+
/**
|
|
27
|
+
* If true, the input text gets fully selected when the field is focused using click or touch / tap.
|
|
28
|
+
*/
|
|
29
|
+
autoselect: {
|
|
30
|
+
type: Boolean,
|
|
31
|
+
value: false
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Set to true to display the clear icon which clears the input.
|
|
36
|
+
* @attr {boolean} clear-button-visible
|
|
37
|
+
*/
|
|
38
|
+
clearButtonVisible: {
|
|
39
|
+
type: Boolean,
|
|
40
|
+
reflectToAttribute: true,
|
|
41
|
+
value: false
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The name of this field.
|
|
46
|
+
*/
|
|
47
|
+
name: {
|
|
48
|
+
type: String,
|
|
49
|
+
reflectToAttribute: true
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* A hint to the user of what can be entered in the field.
|
|
54
|
+
*/
|
|
55
|
+
placeholder: {
|
|
56
|
+
type: String,
|
|
57
|
+
reflectToAttribute: true
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* When present, it specifies that the field is read-only.
|
|
62
|
+
*/
|
|
63
|
+
readonly: {
|
|
64
|
+
type: Boolean,
|
|
65
|
+
value: false,
|
|
66
|
+
reflectToAttribute: true
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The text usually displayed in a tooltip popup when the mouse is over the field.
|
|
71
|
+
*/
|
|
72
|
+
title: {
|
|
73
|
+
type: String,
|
|
74
|
+
reflectToAttribute: true
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
static get delegateAttrs() {
|
|
80
|
+
return [...super.delegateAttrs, 'name', 'type', 'placeholder', 'readonly', 'invalid', 'title'];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Any element extending this mixin is required to implement this getter.
|
|
85
|
+
* It returns the reference to the clear button element.
|
|
86
|
+
* @protected
|
|
87
|
+
* @return {Element | null | undefined}
|
|
88
|
+
*/
|
|
89
|
+
get clearElement() {
|
|
90
|
+
console.warn(`Please implement the 'clearElement' property in <${this.localName}>`);
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** @protected */
|
|
95
|
+
ready() {
|
|
96
|
+
super.ready();
|
|
97
|
+
|
|
98
|
+
if (this.clearElement) {
|
|
99
|
+
this.clearElement.addEventListener('click', (e) => this._onClearButtonClick(e));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @param {Event} event
|
|
105
|
+
* @protected
|
|
106
|
+
*/
|
|
107
|
+
_onClearButtonClick(event) {
|
|
108
|
+
event.preventDefault();
|
|
109
|
+
this.inputElement.focus();
|
|
110
|
+
this.clear();
|
|
111
|
+
this.inputElement.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
|
|
112
|
+
this.inputElement.dispatchEvent(new Event('change', { bubbles: true }));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Override an event listener from `DelegateFocusMixin`.
|
|
117
|
+
* @param {FocusEvent} event
|
|
118
|
+
* @protected
|
|
119
|
+
* @override
|
|
120
|
+
*/
|
|
121
|
+
_onFocus(event) {
|
|
122
|
+
super._onFocus(event);
|
|
123
|
+
|
|
124
|
+
if (this.autoselect && this.inputElement) {
|
|
125
|
+
this.inputElement.select();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Override an event listener inherited from `KeydownMixin` to clear on Esc.
|
|
131
|
+
* Components that extend this mixin can prevent this behavior by overriding
|
|
132
|
+
* this method without calling `super._onKeyDown` to provide custom logic.
|
|
133
|
+
* @param {KeyboardEvent} event
|
|
134
|
+
* @protected
|
|
135
|
+
* @override
|
|
136
|
+
*/
|
|
137
|
+
_onKeyDown(event) {
|
|
138
|
+
super._onKeyDown(event);
|
|
139
|
+
|
|
140
|
+
if (event.key === 'Escape' && this.clearButtonVisible) {
|
|
141
|
+
const dispatchChange = !!this.value;
|
|
142
|
+
this.clear();
|
|
143
|
+
dispatchChange && this.inputElement.dispatchEvent(new Event('change', { bubbles: true }));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Override an event listener inherited from `InputMixin`
|
|
149
|
+
* to capture native `change` event and make sure that
|
|
150
|
+
* a new one is dispatched after validation runs.
|
|
151
|
+
* @param {Event} event
|
|
152
|
+
* @protected
|
|
153
|
+
* @override
|
|
154
|
+
*/
|
|
155
|
+
_onChange(event) {
|
|
156
|
+
event.stopPropagation();
|
|
157
|
+
|
|
158
|
+
this.validate();
|
|
159
|
+
|
|
160
|
+
this.dispatchEvent(
|
|
161
|
+
new CustomEvent('change', {
|
|
162
|
+
detail: {
|
|
163
|
+
sourceEvent: event
|
|
164
|
+
},
|
|
165
|
+
bubbles: event.bubbles,
|
|
166
|
+
cancelable: event.cancelable
|
|
167
|
+
})
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
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 { SlotController } from './slot-controller.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A controller to create and initialize slotted `<input>` element.
|
|
10
|
+
*/
|
|
11
|
+
export class InputController implements SlotController {}
|
|
@@ -0,0 +1,35 @@
|
|
|
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 { SlotController } from './slot-controller.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A controller to create and initialize slotted `<input>` element.
|
|
10
|
+
*/
|
|
11
|
+
export class InputController extends SlotController {
|
|
12
|
+
constructor(host, callback) {
|
|
13
|
+
super(host, [
|
|
14
|
+
'input',
|
|
15
|
+
() => document.createElement('input'),
|
|
16
|
+
(host, node) => {
|
|
17
|
+
if (host.value) {
|
|
18
|
+
node.setAttribute('value', host.value);
|
|
19
|
+
}
|
|
20
|
+
if (host.type) {
|
|
21
|
+
node.setAttribute('type', host.type);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Ensure every instance has unique ID
|
|
25
|
+
const uniqueId = (InputController._uniqueInputId = 1 + InputController._uniqueInputId || 0);
|
|
26
|
+
host._inputId = `${host.localName}-${uniqueId}`;
|
|
27
|
+
node.id = host._inputId;
|
|
28
|
+
|
|
29
|
+
if (typeof callback == 'function') {
|
|
30
|
+
callback(node);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
]);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -3,10 +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 {
|
|
7
|
-
import { DelegateFocusMixin } from './delegate-focus-mixin.js';
|
|
8
|
-
import { FieldAriaMixin } from './field-aria-mixin.js';
|
|
9
|
-
import { InputPropsMixin } from './input-props-mixin.js';
|
|
6
|
+
import { InputControlMixin } from './input-control-mixin.js';
|
|
10
7
|
|
|
11
8
|
/**
|
|
12
9
|
* A mixin to provide logic for vaadin-text-field and related components.
|
|
@@ -17,9 +14,7 @@ interface InputFieldMixinConstructor {
|
|
|
17
14
|
new (...args: any[]): InputFieldMixin;
|
|
18
15
|
}
|
|
19
16
|
|
|
20
|
-
interface InputFieldMixin extends
|
|
21
|
-
readonly inputElement: HTMLElement | undefined;
|
|
22
|
-
|
|
17
|
+
interface InputFieldMixin extends InputControlMixin {
|
|
23
18
|
/**
|
|
24
19
|
* Whether the value of the control can be automatically completed by the browser.
|
|
25
20
|
* List of available options at:
|
|
@@ -46,21 +41,6 @@ interface InputFieldMixin extends ClearButtonMixin, DelegateFocusMixin, FieldAri
|
|
|
46
41
|
* none: No capitalization.
|
|
47
42
|
*/
|
|
48
43
|
autocapitalize: 'on' | 'off' | 'none' | 'characters' | 'words' | 'sentences' | undefined;
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Specify that the value should be automatically selected when the field gains focus.
|
|
52
|
-
*/
|
|
53
|
-
autoselect: boolean;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* The value of the field.
|
|
57
|
-
*/
|
|
58
|
-
value: string;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Returns true if the current input value satisfies all constraints (if any).
|
|
62
|
-
*/
|
|
63
|
-
checkValidity(): boolean;
|
|
64
44
|
}
|
|
65
45
|
|
|
66
46
|
export { InputFieldMixin, InputFieldMixinConstructor };
|
package/src/input-field-mixin.js
CHANGED
|
@@ -3,16 +3,16 @@
|
|
|
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 {
|
|
7
|
-
import { animationFrame } from '@polymer/polymer/lib/utils/async.js';
|
|
8
|
-
import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js';
|
|
9
|
-
import { ClearButtonMixin } from './clear-button-mixin.js';
|
|
10
|
-
import { DelegateFocusMixin } from './delegate-focus-mixin.js';
|
|
11
|
-
import { FieldAriaMixin } from './field-aria-mixin.js';
|
|
12
|
-
import { InputPropsMixin } from './input-props-mixin.js';
|
|
6
|
+
import { InputControlMixin } from './input-control-mixin.js';
|
|
13
7
|
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
/**
|
|
9
|
+
* A mixin to provide logic for vaadin-text-field and related components.
|
|
10
|
+
*
|
|
11
|
+
* @polymerMixin
|
|
12
|
+
* @mixes InputControlMixin
|
|
13
|
+
*/
|
|
14
|
+
export const InputFieldMixin = (superclass) =>
|
|
15
|
+
class InputFieldMixinClass extends InputControlMixin(superclass) {
|
|
16
16
|
static get properties() {
|
|
17
17
|
return {
|
|
18
18
|
/**
|
|
@@ -49,112 +49,56 @@ const InputFieldMixinImplementation = (superclass) =>
|
|
|
49
49
|
},
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
|
-
*
|
|
52
|
+
* A pattern matched against individual characters the user inputs.
|
|
53
|
+
* When set, the field will prevent:
|
|
54
|
+
* - `keyDown` events if the entered key doesn't match `/^_enabledCharPattern$/`
|
|
55
|
+
* - `paste` events if the pasted text doesn't match `/^_enabledCharPattern*$/`
|
|
56
|
+
* - `drop` events if the dropped text doesn't match `/^_enabledCharPattern*$/`
|
|
57
|
+
*
|
|
58
|
+
* For example, to enable entering only numbers and minus signs,
|
|
59
|
+
* `_enabledCharPattern = "[\\d-]"`
|
|
60
|
+
* @protected
|
|
53
61
|
*/
|
|
54
|
-
|
|
55
|
-
type: Boolean,
|
|
56
|
-
value: false
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* The value of the field.
|
|
61
|
-
*/
|
|
62
|
-
value: {
|
|
62
|
+
_enabledCharPattern: {
|
|
63
63
|
type: String,
|
|
64
|
-
|
|
65
|
-
observer: '_valueChanged',
|
|
66
|
-
notify: true
|
|
64
|
+
observer: '_enabledCharPatternChanged'
|
|
67
65
|
}
|
|
68
66
|
};
|
|
69
67
|
}
|
|
70
68
|
|
|
71
|
-
static get
|
|
72
|
-
return [...super.
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
static get observers() {
|
|
76
|
-
return ['__observeOffsetHeight(errorMessage, invalid, label, helperText)'];
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Element used by `FieldAriaMixin` to set ARIA attributes.
|
|
81
|
-
* @protected
|
|
82
|
-
*/
|
|
83
|
-
get _ariaTarget() {
|
|
84
|
-
return this._inputNode;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Element used by `DelegatesFocusMixin` to handle focus.
|
|
89
|
-
* @return {!HTMLInputElement}
|
|
90
|
-
*/
|
|
91
|
-
get focusElement() {
|
|
92
|
-
return this._inputNode;
|
|
69
|
+
static get delegateAttrs() {
|
|
70
|
+
return [...super.delegateAttrs, 'autocapitalize', 'autocomplete', 'autocorrect'];
|
|
93
71
|
}
|
|
94
72
|
|
|
95
73
|
constructor() {
|
|
96
74
|
super();
|
|
97
75
|
|
|
98
|
-
this.
|
|
99
|
-
this.
|
|
100
|
-
this.
|
|
76
|
+
this._boundOnPaste = this._onPaste.bind(this);
|
|
77
|
+
this._boundOnDrop = this._onDrop.bind(this);
|
|
78
|
+
this._boundOnBeforeInput = this._onBeforeInput.bind(this);
|
|
101
79
|
}
|
|
102
80
|
|
|
103
|
-
/**
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
81
|
+
/**
|
|
82
|
+
* @param {HTMLElement} input
|
|
83
|
+
* @protected
|
|
84
|
+
* @override
|
|
85
|
+
*/
|
|
86
|
+
_inputElementChanged(input) {
|
|
87
|
+
super._inputElementChanged(input);
|
|
109
88
|
|
|
89
|
+
if (input) {
|
|
110
90
|
// Discard value set on the custom slotted input.
|
|
111
|
-
if (
|
|
91
|
+
if (input.value && input.value !== this.value) {
|
|
112
92
|
console.warn(`Please define value on the <${this.localName}> component!`);
|
|
113
|
-
|
|
93
|
+
input.value = '';
|
|
114
94
|
}
|
|
115
95
|
|
|
116
96
|
if (this.value) {
|
|
117
|
-
|
|
118
|
-
this.validate();
|
|
97
|
+
input.value = this.value;
|
|
119
98
|
}
|
|
120
99
|
}
|
|
121
100
|
}
|
|
122
101
|
|
|
123
|
-
/** @protected */
|
|
124
|
-
disconnectedCallback() {
|
|
125
|
-
super.disconnectedCallback();
|
|
126
|
-
|
|
127
|
-
if (this._inputNode) {
|
|
128
|
-
this._removeInputListeners(this._inputNode);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/** @protected */
|
|
133
|
-
ready() {
|
|
134
|
-
super.ready();
|
|
135
|
-
|
|
136
|
-
// Lumo theme defines a max-height transition for the "error-message"
|
|
137
|
-
// part on invalid state change.
|
|
138
|
-
const errorPart = this.shadowRoot.querySelector('[part="error-message"]');
|
|
139
|
-
if (errorPart) {
|
|
140
|
-
errorPart.addEventListener('transitionend', () => {
|
|
141
|
-
this.__observeOffsetHeight();
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Returns true if the current input value satisfies all constraints (if any).
|
|
148
|
-
* @return {boolean}
|
|
149
|
-
*/
|
|
150
|
-
checkValidity() {
|
|
151
|
-
if (this.required) {
|
|
152
|
-
return this._inputNode ? this._inputNode.checkValidity() : undefined;
|
|
153
|
-
} else {
|
|
154
|
-
return !this.invalid;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
102
|
// Workaround for https://github.com/Polymer/polymer/issues/5259
|
|
159
103
|
get __data() {
|
|
160
104
|
return this.__dataValue || {};
|
|
@@ -165,117 +109,122 @@ const InputFieldMixinImplementation = (superclass) =>
|
|
|
165
109
|
}
|
|
166
110
|
|
|
167
111
|
/**
|
|
168
|
-
*
|
|
112
|
+
* Override an event listener from `DelegateFocusMixin`.
|
|
113
|
+
* @param {FocusEvent} event
|
|
169
114
|
* @protected
|
|
115
|
+
* @override
|
|
170
116
|
*/
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
117
|
+
_onBlur(event) {
|
|
118
|
+
super._onBlur(event);
|
|
119
|
+
|
|
120
|
+
this.validate();
|
|
175
121
|
}
|
|
176
122
|
|
|
177
123
|
/**
|
|
178
|
-
*
|
|
124
|
+
* Override a method from `InputMixin` to validate the field
|
|
125
|
+
* when a new value is set programmatically.
|
|
126
|
+
* @param {string} value
|
|
179
127
|
* @protected
|
|
128
|
+
* @override
|
|
180
129
|
*/
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
node.removeEventListener('blur', this._boundOnBlur);
|
|
184
|
-
node.removeEventListener('focus', this._boundOnFocus);
|
|
185
|
-
}
|
|
130
|
+
_forwardInputValue(value) {
|
|
131
|
+
super._forwardInputValue(value);
|
|
186
132
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (this.autoselect && this._inputNode) {
|
|
190
|
-
this._inputNode.select();
|
|
133
|
+
if (this.invalid) {
|
|
134
|
+
this.validate();
|
|
191
135
|
}
|
|
192
136
|
}
|
|
193
137
|
|
|
194
|
-
/**
|
|
195
|
-
|
|
196
|
-
|
|
138
|
+
/**
|
|
139
|
+
* Override a method from `InputMixin`.
|
|
140
|
+
* @param {!HTMLElement} input
|
|
141
|
+
* @protected
|
|
142
|
+
* @override
|
|
143
|
+
*/
|
|
144
|
+
_addInputListeners(input) {
|
|
145
|
+
super._addInputListeners(input);
|
|
146
|
+
|
|
147
|
+
input.addEventListener('paste', this._boundOnPaste);
|
|
148
|
+
input.addEventListener('drop', this._boundOnDrop);
|
|
149
|
+
input.addEventListener('beforeinput', this._boundOnBeforeInput);
|
|
197
150
|
}
|
|
198
151
|
|
|
199
152
|
/**
|
|
200
|
-
*
|
|
153
|
+
* Override a method from `InputMixin`.
|
|
154
|
+
* @param {!HTMLElement} input
|
|
201
155
|
* @protected
|
|
156
|
+
* @override
|
|
202
157
|
*/
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
this.
|
|
158
|
+
_removeInputListeners(input) {
|
|
159
|
+
super._removeInputListeners(input);
|
|
160
|
+
|
|
161
|
+
input.removeEventListener('paste', this._boundOnPaste);
|
|
162
|
+
input.removeEventListener('drop', this._boundOnDrop);
|
|
163
|
+
input.removeEventListener('beforeinput', this._boundOnBeforeInput);
|
|
208
164
|
}
|
|
209
165
|
|
|
210
166
|
/**
|
|
211
|
-
*
|
|
212
|
-
*
|
|
167
|
+
* Override an event listener from `ClearButtonMixin`
|
|
168
|
+
* to avoid adding a separate listener.
|
|
169
|
+
* @param {!KeyboardEvent} event
|
|
213
170
|
* @protected
|
|
171
|
+
* @override
|
|
214
172
|
*/
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
this.dispatchEvent(new CustomEvent('iron-resize', { bubbles: true, composed: true }));
|
|
173
|
+
_onKeyDown(event) {
|
|
174
|
+
if (this._enabledCharPattern && !this.__shouldAcceptKey(event)) {
|
|
175
|
+
event.preventDefault();
|
|
219
176
|
}
|
|
220
177
|
|
|
221
|
-
|
|
178
|
+
super._onKeyDown(event);
|
|
222
179
|
}
|
|
223
180
|
|
|
224
181
|
/** @private */
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
182
|
+
__shouldAcceptKey(event) {
|
|
183
|
+
return (
|
|
184
|
+
event.metaKey ||
|
|
185
|
+
event.ctrlKey ||
|
|
186
|
+
!event.key || // allow typing anything if event.key is not supported
|
|
187
|
+
event.key.length !== 1 || // allow "Backspace", "ArrowLeft" etc.
|
|
188
|
+
this.__enabledCharRegExp.test(event.key)
|
|
232
189
|
);
|
|
233
190
|
}
|
|
234
191
|
|
|
235
|
-
/**
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if (newVal === '' && oldVal === undefined) {
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
if (newVal !== '' && newVal != null) {
|
|
247
|
-
this.setAttribute('has-value', '');
|
|
248
|
-
} else {
|
|
249
|
-
this.removeAttribute('has-value');
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// Value is set before an element is connected to the DOM:
|
|
253
|
-
// this case is handled separately in `connectedCallback`.
|
|
254
|
-
if (!this._inputNode) {
|
|
255
|
-
return;
|
|
192
|
+
/** @private */
|
|
193
|
+
_onPaste(e) {
|
|
194
|
+
if (this._enabledCharPattern) {
|
|
195
|
+
const pastedText = (e.clipboardData || window.clipboardData).getData('text');
|
|
196
|
+
if (!this.__enabledTextRegExp.test(pastedText)) {
|
|
197
|
+
e.preventDefault();
|
|
198
|
+
}
|
|
256
199
|
}
|
|
200
|
+
}
|
|
257
201
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
if (this.
|
|
261
|
-
|
|
202
|
+
/** @private */
|
|
203
|
+
_onDrop(e) {
|
|
204
|
+
if (this._enabledCharPattern) {
|
|
205
|
+
const draggedText = e.dataTransfer.getData('text');
|
|
206
|
+
if (!this.__enabledTextRegExp.test(draggedText)) {
|
|
207
|
+
e.preventDefault();
|
|
208
|
+
}
|
|
262
209
|
}
|
|
210
|
+
}
|
|
263
211
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
212
|
+
/** @private */
|
|
213
|
+
_onBeforeInput(e) {
|
|
214
|
+
// The `beforeinput` event covers all the cases for `_enabledCharPattern`: keyboard, pasting and dropping,
|
|
215
|
+
// but it is still experimental technology so we can't rely on it. It's used here just as an additional check,
|
|
216
|
+
// because it seems to be the only way to detect and prevent specific keys on mobile devices.
|
|
217
|
+
// See https://github.com/vaadin/vaadin-text-field/issues/429
|
|
218
|
+
if (this._enabledCharPattern && e.data && !this.__enabledTextRegExp.test(e.data)) {
|
|
219
|
+
e.preventDefault();
|
|
269
220
|
}
|
|
221
|
+
}
|
|
270
222
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
223
|
+
/** @private */
|
|
224
|
+
_enabledCharPatternChanged(charPattern) {
|
|
225
|
+
if (charPattern) {
|
|
226
|
+
this.__enabledCharRegExp = new RegExp('^' + charPattern + '$');
|
|
227
|
+
this.__enabledTextRegExp = new RegExp('^' + charPattern + '*$');
|
|
274
228
|
}
|
|
275
229
|
}
|
|
276
230
|
};
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* A mixin to provide logic for vaadin-text-field and related components.
|
|
280
|
-
*/
|
|
281
|
-
export const InputFieldMixin = dedupingMixin(InputFieldMixinImplementation);
|
package/src/input-mixin.d.ts
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
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 './slot-mixin.js';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
|
-
* A mixin to
|
|
8
|
+
* A mixin to store the reference to an input element
|
|
9
|
+
* and add input and change event listeners to it.
|
|
10
10
|
*/
|
|
11
11
|
declare function InputMixin<T extends new (...args: any[]) => {}>(base: T): T & InputMixinConstructor;
|
|
12
12
|
|
|
@@ -14,11 +14,27 @@ interface InputMixinConstructor {
|
|
|
14
14
|
new (...args: any[]): InputMixin;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
interface InputMixin
|
|
17
|
+
interface InputMixin {
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
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)` Polymer API.
|
|
22
|
+
*
|
|
23
|
+
* A typical case is using `InputController` that does this automatically.
|
|
24
|
+
* However, the input element does not have to always be native <input>:
|
|
25
|
+
* as an example, <vaadin-combo-box-light> accepts other components.
|
|
20
26
|
*/
|
|
21
|
-
readonly
|
|
27
|
+
readonly inputElement: HTMLInputElement;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The value of the field.
|
|
31
|
+
*/
|
|
32
|
+
value: string;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Clear the value of the field.
|
|
36
|
+
*/
|
|
37
|
+
clear(): void;
|
|
22
38
|
}
|
|
23
39
|
|
|
24
|
-
export {
|
|
40
|
+
export { InputMixin, InputMixinConstructor };
|