@vaadin/password-field 24.3.2 → 24.4.0-dev.223e39f050
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/package.json +11 -8
- package/src/vaadin-password-field-button.js +13 -16
- package/src/vaadin-password-field-mixin.d.ts +46 -0
- package/src/vaadin-password-field-mixin.js +265 -0
- package/src/vaadin-password-field.d.ts +2 -26
- package/src/vaadin-password-field.js +3 -247
- package/web-types.json +0 -594
- package/web-types.lit.json +0 -237
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/password-field",
|
|
3
|
-
"version": "24.
|
|
3
|
+
"version": "24.4.0-dev.223e39f050",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -34,13 +34,16 @@
|
|
|
34
34
|
"web-component"
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
|
+
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
37
38
|
"@polymer/polymer": "^3.0.0",
|
|
38
|
-
"@vaadin/
|
|
39
|
-
"@vaadin/
|
|
40
|
-
"@vaadin/
|
|
41
|
-
"@vaadin/
|
|
42
|
-
"@vaadin/
|
|
43
|
-
"@vaadin/vaadin-
|
|
39
|
+
"@vaadin/a11y-base": "24.4.0-dev.223e39f050",
|
|
40
|
+
"@vaadin/button": "24.4.0-dev.223e39f050",
|
|
41
|
+
"@vaadin/component-base": "24.4.0-dev.223e39f050",
|
|
42
|
+
"@vaadin/field-base": "24.4.0-dev.223e39f050",
|
|
43
|
+
"@vaadin/text-field": "24.4.0-dev.223e39f050",
|
|
44
|
+
"@vaadin/vaadin-lumo-styles": "24.4.0-dev.223e39f050",
|
|
45
|
+
"@vaadin/vaadin-material-styles": "24.4.0-dev.223e39f050",
|
|
46
|
+
"@vaadin/vaadin-themable-mixin": "24.4.0-dev.223e39f050"
|
|
44
47
|
},
|
|
45
48
|
"devDependencies": {
|
|
46
49
|
"@esm-bundle/chai": "^4.3.4",
|
|
@@ -51,5 +54,5 @@
|
|
|
51
54
|
"web-types.json",
|
|
52
55
|
"web-types.lit.json"
|
|
53
56
|
],
|
|
54
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "5e2e3bfc811c95aed9354235fab93fdbf43eb354"
|
|
55
58
|
}
|
|
@@ -3,35 +3,32 @@
|
|
|
3
3
|
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
-
import { html } from '@polymer/polymer/polymer-element.js';
|
|
7
|
-
import {
|
|
6
|
+
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
|
|
7
|
+
import { buttonStyles } from '@vaadin/button/src/vaadin-button-base.js';
|
|
8
|
+
import { ButtonMixin } from '@vaadin/button/src/vaadin-button-mixin.js';
|
|
8
9
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
10
|
+
import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
|
|
11
|
+
import { registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
12
|
+
|
|
13
|
+
registerStyles('vaadin-password-field-button', buttonStyles, { moduleId: 'vaadin-password-field-button-styles' });
|
|
9
14
|
|
|
10
15
|
/**
|
|
11
16
|
* An element used internally by `<vaadin-password-field>`. Not intended to be used separately.
|
|
12
17
|
*
|
|
13
18
|
* @customElement
|
|
14
|
-
* @extends
|
|
19
|
+
* @extends HTMLElement
|
|
20
|
+
* @mixes ButtonMixin
|
|
21
|
+
* @mixes DirMixin
|
|
22
|
+
* @mixes ThemableMixin
|
|
15
23
|
* @private
|
|
16
24
|
*/
|
|
17
|
-
class PasswordFieldButton extends
|
|
25
|
+
class PasswordFieldButton extends ButtonMixin(DirMixin(ThemableMixin(PolymerElement))) {
|
|
18
26
|
static get is() {
|
|
19
27
|
return 'vaadin-password-field-button';
|
|
20
28
|
}
|
|
21
29
|
|
|
22
30
|
static get template() {
|
|
23
|
-
return html
|
|
24
|
-
<style>
|
|
25
|
-
:host {
|
|
26
|
-
display: block;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
:host([hidden]) {
|
|
30
|
-
display: none !important;
|
|
31
|
-
}
|
|
32
|
-
</style>
|
|
33
|
-
<slot name="tooltip"></slot>
|
|
34
|
-
`;
|
|
31
|
+
return html``;
|
|
35
32
|
}
|
|
36
33
|
}
|
|
37
34
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
7
|
+
import type { DisabledMixinClass } from '@vaadin/a11y-base/src/disabled-mixin.js';
|
|
8
|
+
import type { FocusMixinClass } from '@vaadin/a11y-base/src/focus-mixin.js';
|
|
9
|
+
import type { SlotStylesMixinClass } from '@vaadin/component-base/src/slot-styles-mixin.js';
|
|
10
|
+
import type { InputMixinClass } from '@vaadin/field-base/src/input-mixin.js';
|
|
11
|
+
|
|
12
|
+
export declare function PasswordFieldMixin<T extends Constructor<HTMLElement>>(
|
|
13
|
+
base: T,
|
|
14
|
+
): Constructor<DisabledMixinClass> &
|
|
15
|
+
Constructor<FocusMixinClass> &
|
|
16
|
+
Constructor<InputMixinClass> &
|
|
17
|
+
Constructor<PasswordFieldMixinClass> &
|
|
18
|
+
Constructor<SlotStylesMixinClass> &
|
|
19
|
+
T;
|
|
20
|
+
|
|
21
|
+
export declare class PasswordFieldMixinClass {
|
|
22
|
+
/**
|
|
23
|
+
* Set to true to hide the eye icon which toggles the password visibility.
|
|
24
|
+
* @attr {boolean} reveal-button-hidden
|
|
25
|
+
*/
|
|
26
|
+
revealButtonHidden: boolean;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* True if the password is visible ([type=text]).
|
|
30
|
+
* @attr {boolean} password-visible
|
|
31
|
+
*/
|
|
32
|
+
readonly passwordVisible: boolean;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* An object with translated strings used for localization.
|
|
36
|
+
* It has the following structure and default values:
|
|
37
|
+
*
|
|
38
|
+
* ```
|
|
39
|
+
* {
|
|
40
|
+
* // Translation of the reveal icon button accessible label
|
|
41
|
+
* reveal: 'Show password'
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
i18n: { reveal: string };
|
|
46
|
+
}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 - 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { DisabledMixin } from '@vaadin/a11y-base/src/disabled-mixin.js';
|
|
7
|
+
import { FocusMixin } from '@vaadin/a11y-base/src/focus-mixin.js';
|
|
8
|
+
import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
|
|
9
|
+
import { SlotStylesMixin } from '@vaadin/component-base/src/slot-styles-mixin.js';
|
|
10
|
+
import { InputMixin } from '@vaadin/field-base/src/input-mixin.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @polymerMixin
|
|
14
|
+
* @mixes DisabledMixin
|
|
15
|
+
* @mixes FocusMixin
|
|
16
|
+
* @mixes InputMixin
|
|
17
|
+
* @mixes SlotStylesMixin
|
|
18
|
+
*/
|
|
19
|
+
export const PasswordFieldMixin = (superClass) =>
|
|
20
|
+
class PasswordFieldMixinClass extends SlotStylesMixin(DisabledMixin(FocusMixin(InputMixin(superClass)))) {
|
|
21
|
+
static get properties() {
|
|
22
|
+
return {
|
|
23
|
+
/**
|
|
24
|
+
* Set to true to hide the eye icon which toggles the password visibility.
|
|
25
|
+
* @attr {boolean} reveal-button-hidden
|
|
26
|
+
*/
|
|
27
|
+
revealButtonHidden: {
|
|
28
|
+
type: Boolean,
|
|
29
|
+
observer: '_revealButtonHiddenChanged',
|
|
30
|
+
value: false,
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* True if the password is visible ([type=text]).
|
|
35
|
+
* @attr {boolean} password-visible
|
|
36
|
+
*/
|
|
37
|
+
passwordVisible: {
|
|
38
|
+
type: Boolean,
|
|
39
|
+
value: false,
|
|
40
|
+
reflectToAttribute: true,
|
|
41
|
+
observer: '_passwordVisibleChanged',
|
|
42
|
+
readOnly: true,
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* An object with translated strings used for localization.
|
|
47
|
+
* It has the following structure and default values:
|
|
48
|
+
*
|
|
49
|
+
* ```
|
|
50
|
+
* {
|
|
51
|
+
* // Translation of the reveal icon button accessible label
|
|
52
|
+
* reveal: 'Show password'
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
i18n: {
|
|
57
|
+
type: Object,
|
|
58
|
+
value: () => {
|
|
59
|
+
return {
|
|
60
|
+
reveal: 'Show password',
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static get observers() {
|
|
68
|
+
return ['__i18nChanged(i18n.*)'];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
constructor() {
|
|
72
|
+
super();
|
|
73
|
+
this._setType('password');
|
|
74
|
+
this.__boundRevealButtonClick = this._onRevealButtonClick.bind(this);
|
|
75
|
+
this.__boundRevealButtonMouseDown = this._onRevealButtonMouseDown.bind(this);
|
|
76
|
+
this.__lastChange = '';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** @protected */
|
|
80
|
+
get slotStyles() {
|
|
81
|
+
const tag = this.localName;
|
|
82
|
+
return [
|
|
83
|
+
...super.slotStyles,
|
|
84
|
+
`
|
|
85
|
+
${tag} [slot="input"]::-ms-reveal {
|
|
86
|
+
display: none;
|
|
87
|
+
}
|
|
88
|
+
`,
|
|
89
|
+
];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** @protected */
|
|
93
|
+
get _revealNode() {
|
|
94
|
+
return this._revealButtonController && this._revealButtonController.node;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** @protected */
|
|
98
|
+
ready() {
|
|
99
|
+
super.ready();
|
|
100
|
+
|
|
101
|
+
this._revealPart = this.shadowRoot.querySelector('[part="reveal-button"]');
|
|
102
|
+
|
|
103
|
+
this._revealButtonController = new SlotController(this, 'reveal', 'vaadin-password-field-button', {
|
|
104
|
+
initializer: (btn) => {
|
|
105
|
+
btn.disabled = this.disabled;
|
|
106
|
+
|
|
107
|
+
btn.addEventListener('click', this.__boundRevealButtonClick);
|
|
108
|
+
btn.addEventListener('mousedown', this.__boundRevealButtonMouseDown);
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
this.addController(this._revealButtonController);
|
|
112
|
+
|
|
113
|
+
this.__updateAriaLabel(this.i18n);
|
|
114
|
+
|
|
115
|
+
this._updateToggleState(false);
|
|
116
|
+
this._toggleRevealHidden(this.revealButtonHidden);
|
|
117
|
+
|
|
118
|
+
if (this.inputElement) {
|
|
119
|
+
this.inputElement.autocapitalize = 'off';
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Override an event listener inherited from `InputControlMixin`
|
|
125
|
+
* to store the value at the moment of the native `change` event.
|
|
126
|
+
* @param {Event} event
|
|
127
|
+
* @protected
|
|
128
|
+
* @override
|
|
129
|
+
*/
|
|
130
|
+
_onChange(event) {
|
|
131
|
+
super._onChange(event);
|
|
132
|
+
|
|
133
|
+
this.__lastChange = this.inputElement.value;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Override method inherited from `FocusMixin` to mark field as focused
|
|
138
|
+
* when focus moves to the reveal button using Shift Tab.
|
|
139
|
+
* @param {Event} event
|
|
140
|
+
* @return {boolean}
|
|
141
|
+
* @protected
|
|
142
|
+
*/
|
|
143
|
+
_shouldSetFocus(event) {
|
|
144
|
+
return event.target === this.inputElement || event.target === this._revealNode;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Override method inherited from `FocusMixin` to not hide password
|
|
149
|
+
* when focus moves to the reveal button or back to the input.
|
|
150
|
+
* @param {Event} event
|
|
151
|
+
* @return {boolean}
|
|
152
|
+
* @protected
|
|
153
|
+
*/
|
|
154
|
+
_shouldRemoveFocus(event) {
|
|
155
|
+
return !(
|
|
156
|
+
event.relatedTarget === this._revealNode ||
|
|
157
|
+
(event.relatedTarget === this.inputElement && event.target === this._revealNode)
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Override method inherited from `FocusMixin` to toggle password visibility.
|
|
163
|
+
* @param {boolean} focused
|
|
164
|
+
* @protected
|
|
165
|
+
* @override
|
|
166
|
+
*/
|
|
167
|
+
_setFocused(focused) {
|
|
168
|
+
super._setFocused(focused);
|
|
169
|
+
|
|
170
|
+
if (!focused) {
|
|
171
|
+
this._setPasswordVisible(false);
|
|
172
|
+
|
|
173
|
+
// Detect if `focusout` was prevented and if so, dispatch `change` event manually.
|
|
174
|
+
if (this.__lastChange !== this.inputElement.value) {
|
|
175
|
+
this.__lastChange = this.inputElement.value;
|
|
176
|
+
this.dispatchEvent(new CustomEvent('change', { bubbles: true }));
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
const isButtonFocused = this.getRootNode().activeElement === this._revealNode;
|
|
180
|
+
// Remove focus-ring from the field when the reveal button gets focused
|
|
181
|
+
this.toggleAttribute('focus-ring', this._keyboardActive && !isButtonFocused);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** @private */
|
|
186
|
+
__updateAriaLabel(i18n) {
|
|
187
|
+
if (i18n.reveal && this._revealNode) {
|
|
188
|
+
this._revealNode.setAttribute('aria-label', i18n.reveal);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** @private */
|
|
193
|
+
__i18nChanged(i18n) {
|
|
194
|
+
this.__updateAriaLabel(i18n.base);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** @private */
|
|
198
|
+
_revealButtonHiddenChanged(hidden) {
|
|
199
|
+
this._toggleRevealHidden(hidden);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** @private */
|
|
203
|
+
_togglePasswordVisibility() {
|
|
204
|
+
this._setPasswordVisible(!this.passwordVisible);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** @private */
|
|
208
|
+
_onRevealButtonClick() {
|
|
209
|
+
this._togglePasswordVisibility();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** @private */
|
|
213
|
+
_onRevealButtonMouseDown(e) {
|
|
214
|
+
// Cancel the following focusout event
|
|
215
|
+
e.preventDefault();
|
|
216
|
+
|
|
217
|
+
// Focus the input to avoid problem with password still visible
|
|
218
|
+
// when user clicks the reveal button and then clicks outside.
|
|
219
|
+
this.inputElement.focus();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** @private */
|
|
223
|
+
_toggleRevealHidden(hidden) {
|
|
224
|
+
if (this._revealNode) {
|
|
225
|
+
if (hidden) {
|
|
226
|
+
this._revealPart.setAttribute('hidden', '');
|
|
227
|
+
this._revealNode.setAttribute('tabindex', '-1');
|
|
228
|
+
this._revealNode.setAttribute('aria-hidden', 'true');
|
|
229
|
+
} else {
|
|
230
|
+
this._revealPart.removeAttribute('hidden');
|
|
231
|
+
this._revealNode.setAttribute('tabindex', '0');
|
|
232
|
+
this._revealNode.removeAttribute('aria-hidden');
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** @private */
|
|
238
|
+
_updateToggleState(passwordVisible) {
|
|
239
|
+
if (this._revealNode) {
|
|
240
|
+
this._revealNode.setAttribute('aria-pressed', passwordVisible ? 'true' : 'false');
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/** @private */
|
|
245
|
+
_passwordVisibleChanged(passwordVisible) {
|
|
246
|
+
this._setType(passwordVisible ? 'text' : 'password');
|
|
247
|
+
|
|
248
|
+
this._updateToggleState(passwordVisible);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Override method inherited from `DisabledMixin` to synchronize the reveal button
|
|
253
|
+
* disabled state with the password field disabled state.
|
|
254
|
+
* @param {boolean} disabled
|
|
255
|
+
* @param {boolean} oldDisabled
|
|
256
|
+
* @protected
|
|
257
|
+
*/
|
|
258
|
+
_disabledChanged(disabled, oldDisabled) {
|
|
259
|
+
super._disabledChanged(disabled, oldDisabled);
|
|
260
|
+
|
|
261
|
+
if (this._revealNode) {
|
|
262
|
+
this._revealNode.disabled = disabled;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
};
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
6
|
import { TextField } from '@vaadin/text-field/src/vaadin-text-field.js';
|
|
7
|
+
import { PasswordFieldMixin } from './vaadin-password-field-mixin.js';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Fired when the user commits a value change.
|
|
@@ -71,32 +72,7 @@ export interface PasswordFieldEventMap extends HTMLElementEventMap, PasswordFiel
|
|
|
71
72
|
* @fires {CustomEvent} value-changed - Fired when the `value` property changes.
|
|
72
73
|
* @fires {CustomEvent} validated - Fired whenever the field is validated.
|
|
73
74
|
*/
|
|
74
|
-
declare class PasswordField extends TextField {
|
|
75
|
-
/**
|
|
76
|
-
* Set to true to hide the eye icon which toggles the password visibility.
|
|
77
|
-
* @attr {boolean} reveal-button-hidden
|
|
78
|
-
*/
|
|
79
|
-
revealButtonHidden: boolean;
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* True if the password is visible ([type=text]).
|
|
83
|
-
* @attr {boolean} password-visible
|
|
84
|
-
*/
|
|
85
|
-
readonly passwordVisible: boolean;
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* An object with translated strings used for localization.
|
|
89
|
-
* It has the following structure and default values:
|
|
90
|
-
*
|
|
91
|
-
* ```
|
|
92
|
-
* {
|
|
93
|
-
* // Translation of the reveal icon button accessible label
|
|
94
|
-
* reveal: 'Show password'
|
|
95
|
-
* }
|
|
96
|
-
* ```
|
|
97
|
-
*/
|
|
98
|
-
i18n: { reveal: string };
|
|
99
|
-
|
|
75
|
+
declare class PasswordField extends PasswordFieldMixin(TextField) {
|
|
100
76
|
addEventListener<K extends keyof PasswordFieldEventMap>(
|
|
101
77
|
type: K,
|
|
102
78
|
listener: (this: PasswordField, ev: PasswordFieldEventMap[K]) => void,
|