@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/password-field",
3
- "version": "24.3.2",
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/button": "~24.3.2",
39
- "@vaadin/component-base": "~24.3.2",
40
- "@vaadin/text-field": "~24.3.2",
41
- "@vaadin/vaadin-lumo-styles": "~24.3.2",
42
- "@vaadin/vaadin-material-styles": "~24.3.2",
43
- "@vaadin/vaadin-themable-mixin": "~24.3.2"
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": "615ee9dd4611f52db90445b0db13dcbb91ca74d4"
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 { Button } from '@vaadin/button/src/vaadin-button.js';
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 Button
19
+ * @extends HTMLElement
20
+ * @mixes ButtonMixin
21
+ * @mixes DirMixin
22
+ * @mixes ThemableMixin
15
23
  * @private
16
24
  */
17
- class PasswordFieldButton extends Button {
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,