@vaadin/login 24.2.0-alpha4 → 24.2.0-alpha6

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/login",
3
- "version": "24.2.0-alpha4",
3
+ "version": "24.2.0-alpha6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -37,23 +37,23 @@
37
37
  "dependencies": {
38
38
  "@open-wc/dedupe-mixin": "^1.3.0",
39
39
  "@polymer/polymer": "^3.0.0",
40
- "@vaadin/button": "24.2.0-alpha4",
41
- "@vaadin/component-base": "24.2.0-alpha4",
42
- "@vaadin/overlay": "24.2.0-alpha4",
43
- "@vaadin/password-field": "24.2.0-alpha4",
44
- "@vaadin/text-field": "24.2.0-alpha4",
45
- "@vaadin/vaadin-lumo-styles": "24.2.0-alpha4",
46
- "@vaadin/vaadin-material-styles": "24.2.0-alpha4",
47
- "@vaadin/vaadin-themable-mixin": "24.2.0-alpha4"
40
+ "@vaadin/button": "24.2.0-alpha6",
41
+ "@vaadin/component-base": "24.2.0-alpha6",
42
+ "@vaadin/overlay": "24.2.0-alpha6",
43
+ "@vaadin/password-field": "24.2.0-alpha6",
44
+ "@vaadin/text-field": "24.2.0-alpha6",
45
+ "@vaadin/vaadin-lumo-styles": "24.2.0-alpha6",
46
+ "@vaadin/vaadin-material-styles": "24.2.0-alpha6",
47
+ "@vaadin/vaadin-themable-mixin": "24.2.0-alpha6"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@esm-bundle/chai": "^4.3.4",
51
- "@vaadin/testing-helpers": "^0.4.2",
51
+ "@vaadin/testing-helpers": "^0.4.3",
52
52
  "sinon": "^13.0.2"
53
53
  },
54
54
  "web-types": [
55
55
  "web-types.json",
56
56
  "web-types.lit.json"
57
57
  ],
58
- "gitHead": "aaf7c5ebfea62628210eead4229be1718ac6b129"
58
+ "gitHead": "3ef6e6cd66919b3ef7637e42916e4c54656beb51"
59
59
  }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2018 - 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 { LoginMixinClass } from './vaadin-login-mixin.js';
8
+
9
+ export declare function LoginFormMixin<T extends Constructor<HTMLElement>>(
10
+ base: T,
11
+ ): Constructor<LoginFormMixinClass> & Constructor<LoginMixinClass> & T;
12
+
13
+ export declare class LoginFormMixinClass {
14
+ /**
15
+ * Submits the form.
16
+ */
17
+ submit(): void;
18
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2018 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { LoginMixin } from './vaadin-login-mixin.js';
7
+
8
+ /**
9
+ * @polymerMixin
10
+ * @mixes LoginMixin
11
+ */
12
+ export const LoginFormMixin = (superClass) =>
13
+ class LoginFormMixin extends LoginMixin(superClass) {
14
+ static get observers() {
15
+ return ['_errorChanged(error)'];
16
+ }
17
+
18
+ /** @protected */
19
+ connectedCallback() {
20
+ super.connectedCallback();
21
+
22
+ if (!this.noAutofocus) {
23
+ this.$.vaadinLoginUsername.focus();
24
+ }
25
+ }
26
+
27
+ /** @private */
28
+ _errorChanged() {
29
+ if (this.error && !this._preventAutoEnable) {
30
+ this.disabled = false;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Submits the form.
36
+ */
37
+ submit() {
38
+ const userName = this.$.vaadinLoginUsername;
39
+ const password = this.$.vaadinLoginPassword;
40
+
41
+ if (this.disabled || !(userName.validate() && password.validate())) {
42
+ return;
43
+ }
44
+
45
+ this.error = false;
46
+ this.disabled = true;
47
+
48
+ const loginEventDetails = {
49
+ bubbles: true,
50
+ cancelable: true,
51
+ detail: {
52
+ username: userName.value,
53
+ password: password.value,
54
+ },
55
+ };
56
+
57
+ const firedEvent = this.dispatchEvent(new CustomEvent('login', loginEventDetails));
58
+ if (this.action && firedEvent) {
59
+ const csrfMetaName = document.querySelector('meta[name=_csrf_parameter]');
60
+ const csrfMetaValue = document.querySelector('meta[name=_csrf]');
61
+ if (csrfMetaName && csrfMetaValue) {
62
+ this.$.csrf.name = csrfMetaName.content;
63
+ this.$.csrf.value = csrfMetaValue.content;
64
+ }
65
+ this.querySelector('form').submit();
66
+ }
67
+ }
68
+
69
+ /** @protected */
70
+ _handleInputKeydown(e) {
71
+ if (e.key === 'Enter') {
72
+ const { currentTarget: inputActive } = e;
73
+ const nextInput =
74
+ inputActive.id === 'vaadinLoginUsername' ? this.$.vaadinLoginPassword : this.$.vaadinLoginUsername;
75
+ if (inputActive.validate()) {
76
+ if (nextInput.checkValidity()) {
77
+ this.submit();
78
+ } else {
79
+ nextInput.focus();
80
+ }
81
+ }
82
+ }
83
+ }
84
+
85
+ /** @protected */
86
+ _handleInputKeyup(e) {
87
+ const input = e.currentTarget;
88
+ if (e.key === 'Tab' && input instanceof HTMLInputElement) {
89
+ input.select();
90
+ }
91
+ }
92
+
93
+ /** @protected */
94
+ _onForgotPasswordClick() {
95
+ this.dispatchEvent(new CustomEvent('forgot-password'));
96
+ }
97
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2018 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import type { CSSResult } from 'lit';
7
+
8
+ export const loginFormWrapperStyles: CSSResult;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2018 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { css } from 'lit';
7
+
8
+ export const loginFormWrapperStyles = css`
9
+ :host {
10
+ overflow: hidden;
11
+ display: inline-block;
12
+ }
13
+
14
+ :host([hidden]) {
15
+ display: none !important;
16
+ }
17
+
18
+ [part='form'] {
19
+ flex: 1;
20
+ display: flex;
21
+ flex-direction: column;
22
+ box-sizing: border-box;
23
+ }
24
+
25
+ [part='form-title'] {
26
+ margin: 0;
27
+ }
28
+
29
+ [part='error-message'] {
30
+ position: relative;
31
+ }
32
+ `;
@@ -4,7 +4,12 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
7
- import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
7
+ import { registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
8
+ import { loginFormWrapperStyles } from './vaadin-login-form-wrapper-styles.js';
9
+
10
+ registerStyles('vaadin-login-form-wrapper', loginFormWrapperStyles, {
11
+ moduleId: 'vaadin-login-form-wrapper-styles',
12
+ });
8
13
 
9
14
  /**
10
15
  * An element used internally by `<vaadin-login-form>`. Not intended to be used separately.
@@ -16,31 +21,6 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
16
21
  class LoginFormWrapper extends ThemableMixin(PolymerElement) {
17
22
  static get template() {
18
23
  return html`
19
- <style>
20
- :host {
21
- overflow: hidden;
22
- display: inline-block;
23
- }
24
-
25
- :host([hidden]) {
26
- display: none !important;
27
- }
28
-
29
- [part='form'] {
30
- flex: 1;
31
- display: flex;
32
- flex-direction: column;
33
- box-sizing: border-box;
34
- }
35
-
36
- [part='form-title'] {
37
- margin: 0;
38
- }
39
-
40
- [part='error-message'] {
41
- position: relative;
42
- }
43
- </style>
44
24
  <section part="form">
45
25
  <h2 part="form-title">[[i18n.form.title]]</h2>
46
26
  <div part="error-message" hidden$="[[!error]]">
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
7
7
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
8
- import { LoginMixin } from './vaadin-login-mixin.js';
8
+ import { LoginFormMixin } from './vaadin-login-form-mixin.js';
9
9
  export { LoginI18n } from './vaadin-login-mixin.js';
10
10
 
11
11
  /**
@@ -69,9 +69,7 @@ export interface LoginFormEventMap extends HTMLElementEventMap, LoginFormCustomE
69
69
  * @fires {CustomEvent} forgot-password - Fired when user clicks on the "Forgot password" button.
70
70
  * @fires {CustomEvent} login - Fired when a user submits the login.
71
71
  */
72
- declare class LoginForm extends ElementMixin(ThemableMixin(LoginMixin(HTMLElement))) {
73
- submit(): void;
74
-
72
+ declare class LoginForm extends LoginFormMixin(ElementMixin(ThemableMixin(HTMLElement))) {
75
73
  addEventListener<K extends keyof LoginFormEventMap>(
76
74
  type: K,
77
75
  listener: (this: LoginForm, ev: LoginFormEventMap[K]) => void,
@@ -10,7 +10,7 @@ import './vaadin-login-form-wrapper.js';
10
10
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
11
11
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
12
12
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
13
- import { LoginMixin } from './vaadin-login-mixin.js';
13
+ import { LoginFormMixin } from './vaadin-login-form-mixin.js';
14
14
 
15
15
  /**
16
16
  * `<vaadin-login-form>` is a Web Component providing an easy way to require users
@@ -49,9 +49,9 @@ import { LoginMixin } from './vaadin-login-mixin.js';
49
49
  * @extends HTMLElement
50
50
  * @mixes ElementMixin
51
51
  * @mixes ThemableMixin
52
- * @mixes LoginMixin
52
+ * @mixes LoginFormMixin
53
53
  */
54
- class LoginForm extends LoginMixin(ElementMixin(ThemableMixin(PolymerElement))) {
54
+ class LoginForm extends LoginFormMixin(ElementMixin(ThemableMixin(PolymerElement))) {
55
55
  static get template() {
56
56
  return html`
57
57
  <style>
@@ -111,19 +111,6 @@ class LoginForm extends LoginMixin(ElementMixin(ThemableMixin(PolymerElement)))
111
111
  return 'vaadin-login-form';
112
112
  }
113
113
 
114
- static get observers() {
115
- return ['_errorChanged(error)'];
116
- }
117
-
118
- /** @protected */
119
- connectedCallback() {
120
- super.connectedCallback();
121
-
122
- if (!this.noAutofocus) {
123
- this.$.vaadinLoginUsername.focus();
124
- }
125
- }
126
-
127
114
  /**
128
115
  * @param {StampedTemplate} dom
129
116
  * @return {null}
@@ -132,74 +119,6 @@ class LoginForm extends LoginMixin(ElementMixin(ThemableMixin(PolymerElement)))
132
119
  _attachDom(dom) {
133
120
  this.appendChild(dom);
134
121
  }
135
-
136
- /** @private */
137
- _errorChanged() {
138
- if (this.error && !this._preventAutoEnable) {
139
- this.disabled = false;
140
- }
141
- }
142
-
143
- submit() {
144
- const userName = this.$.vaadinLoginUsername;
145
- const password = this.$.vaadinLoginPassword;
146
-
147
- if (this.disabled || !(userName.validate() && password.validate())) {
148
- return;
149
- }
150
-
151
- this.error = false;
152
- this.disabled = true;
153
-
154
- const loginEventDetails = {
155
- bubbles: true,
156
- cancelable: true,
157
- detail: {
158
- username: userName.value,
159
- password: password.value,
160
- },
161
- };
162
-
163
- const firedEvent = this.dispatchEvent(new CustomEvent('login', loginEventDetails));
164
- if (this.action && firedEvent) {
165
- const csrfMetaName = document.querySelector('meta[name=_csrf_parameter]');
166
- const csrfMetaValue = document.querySelector('meta[name=_csrf]');
167
- if (csrfMetaName && csrfMetaValue) {
168
- this.$.csrf.name = csrfMetaName.content;
169
- this.$.csrf.value = csrfMetaValue.content;
170
- }
171
- this.querySelector('form').submit();
172
- }
173
- }
174
-
175
- /** @private */
176
- _handleInputKeydown(e) {
177
- if (e.key === 'Enter') {
178
- const { currentTarget: inputActive } = e;
179
- const nextInput =
180
- inputActive.id === 'vaadinLoginUsername' ? this.$.vaadinLoginPassword : this.$.vaadinLoginUsername;
181
- if (inputActive.validate()) {
182
- if (nextInput.checkValidity()) {
183
- this.submit();
184
- } else {
185
- nextInput.focus();
186
- }
187
- }
188
- }
189
- }
190
-
191
- /** @private */
192
- _handleInputKeyup(e) {
193
- const input = e.currentTarget;
194
- if (e.key === 'Tab' && input instanceof HTMLInputElement) {
195
- input.select();
196
- }
197
- }
198
-
199
- /** @private */
200
- _onForgotPasswordClick() {
201
- this.dispatchEvent(new CustomEvent('forgot-password'));
202
- }
203
122
  }
204
123
 
205
124
  customElements.define(LoginForm.is, LoginForm);
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2018 - 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 { OverlayClassMixinClass } from '@vaadin/component-base/src/overlay-class-mixin.js';
8
+ import type { LoginMixinClass } from './vaadin-login-mixin.js';
9
+
10
+ export declare function LoginOverlayMixin<T extends Constructor<HTMLElement>>(
11
+ base: T,
12
+ ): Constructor<LoginMixinClass> & Constructor<LoginOverlayMixinClass> & Constructor<OverlayClassMixinClass> & T;
13
+
14
+ export declare class LoginOverlayMixinClass {
15
+ /**
16
+ * Defines the application description
17
+ */
18
+ description: string;
19
+
20
+ /**
21
+ * True if the overlay is currently displayed.
22
+ */
23
+ opened: boolean;
24
+
25
+ /**
26
+ * Defines the application title
27
+ */
28
+ title: string;
29
+ }
@@ -0,0 +1,146 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2018 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
7
+ import { LoginMixin } from './vaadin-login-mixin.js';
8
+
9
+ /**
10
+ * @polymerMixin
11
+ * @mixes LoginMixin
12
+ * @mixes OverlayClassMixin
13
+ */
14
+ export const LoginOverlayMixin = (superClass) =>
15
+ class LoginOverlayMixin extends OverlayClassMixin(LoginMixin(superClass)) {
16
+ static get properties() {
17
+ return {
18
+ /**
19
+ * Defines the application description
20
+ * @type {string}
21
+ */
22
+ description: {
23
+ type: String,
24
+ value: 'Application description',
25
+ notify: true,
26
+ },
27
+
28
+ /**
29
+ * True if the overlay is currently displayed.
30
+ * @type {boolean}
31
+ */
32
+ opened: {
33
+ type: Boolean,
34
+ value: false,
35
+ observer: '_onOpenedChange',
36
+ },
37
+
38
+ /**
39
+ * Defines the application title
40
+ * @type {string}
41
+ */
42
+ title: {
43
+ type: String,
44
+ value: 'App name',
45
+ },
46
+ };
47
+ }
48
+
49
+ static get observers() {
50
+ return ['__i18nChanged(i18n)'];
51
+ }
52
+
53
+ /** @protected */
54
+ ready() {
55
+ super.ready();
56
+
57
+ this._overlayElement = this.$.vaadinLoginOverlayWrapper;
58
+ }
59
+
60
+ /** @protected */
61
+ connectedCallback() {
62
+ super.connectedCallback();
63
+
64
+ // Restore opened state if overlay was open when disconnecting
65
+ if (this.__restoreOpened) {
66
+ this.opened = true;
67
+ }
68
+ }
69
+
70
+ /** @protected */
71
+ disconnectedCallback() {
72
+ super.disconnectedCallback();
73
+
74
+ // Close overlay and memorize opened state
75
+ this.__restoreOpened = this.opened;
76
+ this.opened = false;
77
+ }
78
+
79
+ /** @private */
80
+ __i18nChanged(i18n) {
81
+ const header = i18n && i18n.header;
82
+ if (!header) {
83
+ return;
84
+ }
85
+ this.title = header.title;
86
+ this.description = header.description;
87
+ }
88
+
89
+ /** @protected */
90
+ _preventClosingLogin(e) {
91
+ e.preventDefault();
92
+ }
93
+
94
+ /**
95
+ * @param {!Event} e
96
+ * @protected
97
+ */
98
+ _retargetEvent(e) {
99
+ e.stopPropagation();
100
+ const { detail, composed, cancelable, bubbles } = e;
101
+
102
+ const firedEvent = this.dispatchEvent(new CustomEvent(e.type, { bubbles, cancelable, composed, detail }));
103
+ // Check if `eventTarget.preventDefault()` was called to prevent default in the original event
104
+ if (!firedEvent) {
105
+ e.preventDefault();
106
+ }
107
+ }
108
+
109
+ /** @private */
110
+ _onOpenedChange() {
111
+ if (!this.opened) {
112
+ this.$.vaadinLoginForm.$.vaadinLoginUsername.value = '';
113
+ this.$.vaadinLoginForm.$.vaadinLoginPassword.value = '';
114
+ this.disabled = false;
115
+
116
+ if (this._undoTeleport) {
117
+ this._undoTeleport();
118
+ }
119
+ } else {
120
+ this._undoTeleport = this._teleport(this._getElementsToTeleport());
121
+
122
+ // Overlay sets pointerEvents on body to `none`, which breaks LastPass popup
123
+ // Reverting it back to the previous state
124
+ // https://github.com/vaadin/vaadin-overlay/blob/041cde4481b6262eac68d3a699f700216d897373/src/vaadin-overlay.html#L660
125
+ document.body.style.pointerEvents = this.$.vaadinLoginOverlayWrapper._previousDocumentPointerEvents;
126
+ }
127
+ }
128
+
129
+ /** @private */
130
+ _teleport(elements) {
131
+ const teleported = Array.from(elements).map((e) => {
132
+ return this.$.vaadinLoginOverlayWrapper.appendChild(e);
133
+ });
134
+ // Function to undo the teleport
135
+ return () => {
136
+ while (teleported.length > 0) {
137
+ this.appendChild(teleported.shift());
138
+ }
139
+ };
140
+ }
141
+
142
+ /** @private */
143
+ _getElementsToTeleport() {
144
+ return this.querySelectorAll('[slot=title]');
145
+ }
146
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2018 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import type { CSSResult } from 'lit';
7
+
8
+ export const loginOverlayWrapperStyles: CSSResult;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2018 - 2023 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { css } from 'lit';
7
+
8
+ export const loginOverlayWrapperStyles = css`
9
+ [part='overlay'] {
10
+ outline: none;
11
+ }
12
+
13
+ [part='card'] {
14
+ max-width: 100%;
15
+ box-sizing: border-box;
16
+ overflow: hidden;
17
+ display: flex;
18
+ flex-direction: column;
19
+ }
20
+
21
+ [part='brand'] {
22
+ box-sizing: border-box;
23
+ overflow: hidden;
24
+ flex-grow: 1;
25
+ flex-shrink: 0;
26
+ display: flex;
27
+ flex-direction: column;
28
+ justify-content: flex-end;
29
+ }
30
+
31
+ [part='brand'] h1 {
32
+ color: inherit;
33
+ margin: 0;
34
+ }
35
+ `;
@@ -3,58 +3,16 @@
3
3
  * Copyright (c) 2018 - 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/lib/utils/html-tag.js';
7
- import { Overlay } from '@vaadin/overlay/src/vaadin-overlay.js';
8
- import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
6
+ import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
7
+ import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
8
+ import { OverlayMixin } from '@vaadin/overlay/src/vaadin-overlay-mixin.js';
9
+ import { overlayStyles } from '@vaadin/overlay/src/vaadin-overlay-styles.js';
10
+ import { registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
11
+ import { loginOverlayWrapperStyles } from './vaadin-login-overlay-wrapper-styles.js';
9
12
 
10
- registerStyles(
11
- 'vaadin-login-overlay-wrapper',
12
- css`
13
- [part='overlay'] {
14
- outline: none;
15
- }
16
-
17
- [part='card'] {
18
- max-width: 100%;
19
- box-sizing: border-box;
20
- overflow: hidden;
21
- display: flex;
22
- flex-direction: column;
23
- }
24
-
25
- [part='brand'] {
26
- box-sizing: border-box;
27
- overflow: hidden;
28
- flex-grow: 1;
29
- flex-shrink: 0;
30
- display: flex;
31
- flex-direction: column;
32
- justify-content: flex-end;
33
- }
34
-
35
- [part='brand'] h1 {
36
- color: inherit;
37
- margin: 0;
38
- }
39
- `,
40
- { moduleId: 'vaadin-login-overlay-wrapper-styles' },
41
- );
42
-
43
- const template = html`
44
- <section part="card">
45
- <div part="brand">
46
- <slot name="title">
47
- <h1 part="title">[[title]]</h1>
48
- </slot>
49
- <p part="description">[[description]]</p>
50
- </div>
51
- <div part="form">
52
- <slot></slot>
53
- </div>
54
- </section>
55
- `;
56
-
57
- let memoizedTemplate;
13
+ registerStyles('vaadin-login-overlay-wrapper', [overlayStyles, loginOverlayWrapperStyles], {
14
+ moduleId: 'vaadin-login-overlay-wrapper-styles',
15
+ });
58
16
 
59
17
  /**
60
18
  * An element used internally by `<vaadin-login-overlay>`. Not intended to be used separately.
@@ -62,7 +20,7 @@ let memoizedTemplate;
62
20
  * @extends Overlay
63
21
  * @private
64
22
  */
65
- class LoginOverlayWrapper extends Overlay {
23
+ class LoginOverlayWrapper extends OverlayMixin(DirMixin(ThemableMixin(PolymerElement))) {
66
24
  static get is() {
67
25
  return 'vaadin-login-overlay-wrapper';
68
26
  }
@@ -86,17 +44,24 @@ class LoginOverlayWrapper extends Overlay {
86
44
  }
87
45
 
88
46
  static get template() {
89
- if (!memoizedTemplate) {
90
- // Clone the superclass template
91
- memoizedTemplate = super.template.cloneNode(true);
92
-
93
- // Replace overlay slot with card
94
- const card = template.content.querySelector('[part=card]');
95
- const content = memoizedTemplate.content.querySelector('#content');
96
- content.replaceChild(card, content.children[0]);
97
- }
98
-
99
- return memoizedTemplate;
47
+ return html`
48
+ <div id="backdrop" part="backdrop" hidden$="[[!withBackdrop]]"></div>
49
+ <div part="overlay" id="overlay" tabindex="0">
50
+ <div part="content" id="content">
51
+ <section part="card">
52
+ <div part="brand">
53
+ <slot name="title">
54
+ <h1 part="title">[[title]]</h1>
55
+ </slot>
56
+ <p part="description">[[description]]</p>
57
+ </div>
58
+ <div part="form">
59
+ <slot></slot>
60
+ </div>
61
+ </section>
62
+ </div>
63
+ </div>
64
+ `;
100
65
  }
101
66
  }
102
67
 
@@ -4,9 +4,9 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
7
- import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
8
7
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
9
- import { LoginMixin } from './vaadin-login-mixin.js';
8
+ import { LoginOverlayMixin } from './vaadin-login-overlay-mixin.js';
9
+
10
10
  export { LoginI18n } from './vaadin-login-mixin.js';
11
11
 
12
12
  /**
@@ -76,22 +76,7 @@ export interface LoginOverlayEventMap extends HTMLElementEventMap, LoginOverlayC
76
76
  * @fires {CustomEvent} forgot-password - Fired when user clicks on the "Forgot password" button.
77
77
  * @fires {CustomEvent} login - Fired when a user submits the login.
78
78
  */
79
- declare class LoginOverlay extends LoginMixin(OverlayClassMixin(ElementMixin(ThemableMixin(HTMLElement)))) {
80
- /**
81
- * Defines the application description
82
- */
83
- description: string;
84
-
85
- /**
86
- * True if the overlay is currently displayed.
87
- */
88
- opened: boolean;
89
-
90
- /**
91
- * Defines the application title
92
- */
93
- title: string;
94
-
79
+ declare class LoginOverlay extends LoginOverlayMixin(ElementMixin(ThemableMixin(HTMLElement))) {
95
80
  addEventListener<K extends keyof LoginOverlayEventMap>(
96
81
  type: K,
97
82
  listener: (this: LoginOverlay, ev: LoginOverlayEventMap[K]) => void,
@@ -7,9 +7,8 @@ import './vaadin-login-form.js';
7
7
  import './vaadin-login-overlay-wrapper.js';
8
8
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
9
9
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
10
- import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
11
10
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
12
- import { LoginMixin } from './vaadin-login-mixin.js';
11
+ import { LoginOverlayMixin } from './vaadin-login-overlay-mixin.js';
13
12
 
14
13
  /**
15
14
  * `<vaadin-login-overlay>` is a wrapper of the `<vaadin-login-form>` which opens a login form in an overlay and
@@ -47,10 +46,9 @@ import { LoginMixin } from './vaadin-login-mixin.js';
47
46
  * @extends HTMLElement
48
47
  * @mixes ElementMixin
49
48
  * @mixes ThemableMixin
50
- * @mixes LoginMixin
51
- * @mixes OverlayClassMixin
49
+ * @mixes LoginOverlayMixin
52
50
  */
53
- class LoginOverlay extends LoginMixin(OverlayClassMixin(ElementMixin(ThemableMixin(PolymerElement)))) {
51
+ class LoginOverlay extends LoginOverlayMixin(ElementMixin(ThemableMixin(PolymerElement))) {
54
52
  static get template() {
55
53
  return html`
56
54
  <vaadin-login-overlay-wrapper
@@ -83,137 +81,6 @@ class LoginOverlay extends LoginMixin(OverlayClassMixin(ElementMixin(ThemableMix
83
81
  static get is() {
84
82
  return 'vaadin-login-overlay';
85
83
  }
86
-
87
- static get properties() {
88
- return {
89
- /**
90
- * Defines the application description
91
- * @type {string}
92
- */
93
- description: {
94
- type: String,
95
- value: 'Application description',
96
- notify: true,
97
- },
98
-
99
- /**
100
- * True if the overlay is currently displayed.
101
- * @type {boolean}
102
- */
103
- opened: {
104
- type: Boolean,
105
- value: false,
106
- observer: '_onOpenedChange',
107
- },
108
-
109
- /**
110
- * Defines the application title
111
- * @type {string}
112
- */
113
- title: {
114
- type: String,
115
- value: 'App name',
116
- },
117
- };
118
- }
119
-
120
- static get observers() {
121
- return ['__i18nChanged(i18n.header.*)'];
122
- }
123
-
124
- /** @protected */
125
- ready() {
126
- super.ready();
127
-
128
- this._overlayElement = this.$.vaadinLoginOverlayWrapper;
129
- }
130
-
131
- /** @protected */
132
- connectedCallback() {
133
- super.connectedCallback();
134
-
135
- // Restore opened state if overlay was open when disconnecting
136
- if (this.__restoreOpened) {
137
- this.opened = true;
138
- }
139
- }
140
-
141
- /** @protected */
142
- disconnectedCallback() {
143
- super.disconnectedCallback();
144
-
145
- // Close overlay and memorize opened state
146
- this.__restoreOpened = this.opened;
147
- this.opened = false;
148
- }
149
-
150
- /** @private */
151
- __i18nChanged(i18n) {
152
- const header = i18n.base;
153
- if (!header) {
154
- return;
155
- }
156
- this.title = header.title;
157
- this.description = header.description;
158
- }
159
-
160
- /** @private */
161
- _preventClosingLogin(e) {
162
- e.preventDefault();
163
- }
164
-
165
- /**
166
- * @param {!Event} e
167
- * @private
168
- */
169
- _retargetEvent(e) {
170
- e.stopPropagation();
171
- const { detail, composed, cancelable, bubbles } = e;
172
-
173
- const firedEvent = this.dispatchEvent(new CustomEvent(e.type, { bubbles, cancelable, composed, detail }));
174
- // Check if `eventTarget.preventDefault()` was called to prevent default in the original event
175
- if (!firedEvent) {
176
- e.preventDefault();
177
- }
178
- }
179
-
180
- /** @private */
181
- _onOpenedChange() {
182
- if (!this.opened) {
183
- this.$.vaadinLoginForm.$.vaadinLoginUsername.value = '';
184
- this.$.vaadinLoginForm.$.vaadinLoginPassword.value = '';
185
- this.disabled = false;
186
-
187
- if (this._undoTeleport) {
188
- this._undoTeleport();
189
- }
190
- } else {
191
- this._undoTeleport = this._teleport(this._getElementsToTeleport());
192
-
193
- // Overlay sets pointerEvents on body to `none`, which breaks LastPass popup
194
- // Reverting it back to the previous state
195
- // https://github.com/vaadin/vaadin-overlay/blob/041cde4481b6262eac68d3a699f700216d897373/src/vaadin-overlay.html#L660
196
- document.body.style.pointerEvents = this.$.vaadinLoginOverlayWrapper._previousDocumentPointerEvents;
197
- }
198
- }
199
-
200
- /** @private */
201
- _teleport(elements) {
202
- const teleported = Array.from(elements).map((e) => {
203
- return this.$.vaadinLoginOverlayWrapper.appendChild(e);
204
- });
205
- // Function to undo the teleport
206
- return () => {
207
- while (teleported.length > 0) {
208
- this.appendChild(teleported.shift());
209
- }
210
- };
211
- }
212
-
213
- /** @private */
214
- _getElementsToTeleport() {
215
- return this.querySelectorAll('[slot=title]');
216
- }
217
84
  }
218
85
 
219
86
  customElements.define(LoginOverlay.is, LoginOverlay);
@@ -1,6 +1,7 @@
1
1
  import '@vaadin/vaadin-lumo-styles/spacing.js';
2
2
  import './vaadin-login-form-wrapper-styles.js';
3
3
  import { color } from '@vaadin/vaadin-lumo-styles/color.js';
4
+ import { overlay } from '@vaadin/vaadin-lumo-styles/mixins/overlay.js';
4
5
  import { typography } from '@vaadin/vaadin-lumo-styles/typography.js';
5
6
  import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
6
7
 
@@ -169,8 +170,8 @@ const loginOverlayWrapper = css`
169
170
  }
170
171
  `;
171
172
 
172
- registerStyles('vaadin-login-overlay-wrapper', [color, typography, loginOverlayWrapper], {
173
- moduleId: 'vaadin-login-overlay-wrapper-lumo-styles',
173
+ registerStyles('vaadin-login-overlay-wrapper', [color, typography, overlay, loginOverlayWrapper], {
174
+ moduleId: 'lumo-login-overlay-wrapper',
174
175
  });
175
176
 
176
177
  const loginFormWrapper = css`
@@ -1,7 +1,6 @@
1
1
  import '@vaadin/text-field/theme/lumo/vaadin-text-field.js';
2
2
  import '@vaadin/password-field/theme/lumo/vaadin-password-field.js';
3
3
  import '@vaadin/button/theme/lumo/vaadin-button.js';
4
- import '@vaadin/overlay/theme/lumo/vaadin-overlay.js';
5
4
  import './vaadin-login-form.js';
6
5
  import './vaadin-login-overlay-styles.js';
7
6
  import '../../src/vaadin-login-overlay.js';
@@ -1,7 +1,6 @@
1
1
  import '@vaadin/text-field/theme/material/vaadin-text-field.js';
2
2
  import '@vaadin/password-field/theme/material/vaadin-password-field.js';
3
3
  import '@vaadin/button/theme/material/vaadin-button.js';
4
- import '@vaadin/overlay/theme/material/vaadin-overlay.js';
5
4
  import './vaadin-login-form.js';
6
5
  import './vaadin-login-overlay-styles.js';
7
6
  import '../../src/vaadin-login-overlay.js';
package/web-types.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/login",
4
- "version": "24.2.0-alpha4",
4
+ "version": "24.2.0-alpha6",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -148,7 +148,7 @@
148
148
  },
149
149
  {
150
150
  "name": "vaadin-login-overlay",
151
- "description": "`<vaadin-login-overlay>` is a wrapper of the `<vaadin-login-form>` which opens a login form in an overlay and\nhaving an additional `brand` part for application title and description. Using `<vaadin-login-overlay>` allows\npassword managers to work with login form.\n\n```\n<vaadin-login-overlay opened></vaadin-login-overlay>\n```\n\n### Styling\n\nThe component doesn't have a shadowRoot, so the `<form>` and input fields can be styled from a global scope.\nUse `<vaadin-login-overlay-wrapper>` and `<vaadin-login-form-wrapper>` to apply styles.\n\nThe following shadow DOM parts of the `<vaadin-login-overlay-wrapper>` are available for styling:\n\nPart name | Description\n----------------|---------------------------------------------------------|\n`card` | Container for the entire component's content\n`brand` | Container for application title and description\n`form` | Container for the `<vaadin-login-form>` component\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\nSee [`<vaadin-login-form>`](https://cdn.vaadin.com/vaadin-web-components/24.2.0-alpha4/#/elements/vaadin-login-form)\ndocumentation for `<vaadin-login-form-wrapper>` stylable parts.",
151
+ "description": "`<vaadin-login-overlay>` is a wrapper of the `<vaadin-login-form>` which opens a login form in an overlay and\nhaving an additional `brand` part for application title and description. Using `<vaadin-login-overlay>` allows\npassword managers to work with login form.\n\n```\n<vaadin-login-overlay opened></vaadin-login-overlay>\n```\n\n### Styling\n\nThe component doesn't have a shadowRoot, so the `<form>` and input fields can be styled from a global scope.\nUse `<vaadin-login-overlay-wrapper>` and `<vaadin-login-form-wrapper>` to apply styles.\n\nThe following shadow DOM parts of the `<vaadin-login-overlay-wrapper>` are available for styling:\n\nPart name | Description\n----------------|---------------------------------------------------------|\n`card` | Container for the entire component's content\n`brand` | Container for application title and description\n`form` | Container for the `<vaadin-login-form>` component\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\nSee [`<vaadin-login-form>`](https://cdn.vaadin.com/vaadin-web-components/24.2.0-alpha6/#/elements/vaadin-login-form)\ndocumentation for `<vaadin-login-form-wrapper>` stylable parts.",
152
152
  "attributes": [
153
153
  {
154
154
  "name": "action",
@@ -351,10 +351,6 @@
351
351
  "name": "login",
352
352
  "description": "Fired when an user submits the login.\nThe event contains `username` and `password` values in the `detail` property."
353
353
  },
354
- {
355
- "name": "description-changed",
356
- "description": "Fired when the `description` property changes."
357
- },
358
354
  {
359
355
  "name": "disabled-changed",
360
356
  "description": "Fired when the `disabled` property changes."
@@ -362,6 +358,10 @@
362
358
  {
363
359
  "name": "error-changed",
364
360
  "description": "Fired when the `error` property changes."
361
+ },
362
+ {
363
+ "name": "description-changed",
364
+ "description": "Fired when the `description` property changes."
365
365
  }
366
366
  ]
367
367
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/login",
4
- "version": "24.2.0-alpha4",
4
+ "version": "24.2.0-alpha6",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -93,7 +93,7 @@
93
93
  },
94
94
  {
95
95
  "name": "vaadin-login-overlay",
96
- "description": "`<vaadin-login-overlay>` is a wrapper of the `<vaadin-login-form>` which opens a login form in an overlay and\nhaving an additional `brand` part for application title and description. Using `<vaadin-login-overlay>` allows\npassword managers to work with login form.\n\n```\n<vaadin-login-overlay opened></vaadin-login-overlay>\n```\n\n### Styling\n\nThe component doesn't have a shadowRoot, so the `<form>` and input fields can be styled from a global scope.\nUse `<vaadin-login-overlay-wrapper>` and `<vaadin-login-form-wrapper>` to apply styles.\n\nThe following shadow DOM parts of the `<vaadin-login-overlay-wrapper>` are available for styling:\n\nPart name | Description\n----------------|---------------------------------------------------------|\n`card` | Container for the entire component's content\n`brand` | Container for application title and description\n`form` | Container for the `<vaadin-login-form>` component\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\nSee [`<vaadin-login-form>`](https://cdn.vaadin.com/vaadin-web-components/24.2.0-alpha4/#/elements/vaadin-login-form)\ndocumentation for `<vaadin-login-form-wrapper>` stylable parts.",
96
+ "description": "`<vaadin-login-overlay>` is a wrapper of the `<vaadin-login-form>` which opens a login form in an overlay and\nhaving an additional `brand` part for application title and description. Using `<vaadin-login-overlay>` allows\npassword managers to work with login form.\n\n```\n<vaadin-login-overlay opened></vaadin-login-overlay>\n```\n\n### Styling\n\nThe component doesn't have a shadowRoot, so the `<form>` and input fields can be styled from a global scope.\nUse `<vaadin-login-overlay-wrapper>` and `<vaadin-login-form-wrapper>` to apply styles.\n\nThe following shadow DOM parts of the `<vaadin-login-overlay-wrapper>` are available for styling:\n\nPart name | Description\n----------------|---------------------------------------------------------|\n`card` | Container for the entire component's content\n`brand` | Container for application title and description\n`form` | Container for the `<vaadin-login-form>` component\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\nSee [`<vaadin-login-form>`](https://cdn.vaadin.com/vaadin-web-components/24.2.0-alpha6/#/elements/vaadin-login-form)\ndocumentation for `<vaadin-login-form-wrapper>` stylable parts.",
97
97
  "extension": true,
98
98
  "attributes": [
99
99
  {
@@ -181,22 +181,22 @@
181
181
  }
182
182
  },
183
183
  {
184
- "name": "@description-changed",
185
- "description": "Fired when the `description` property changes.",
184
+ "name": "@disabled-changed",
185
+ "description": "Fired when the `disabled` property changes.",
186
186
  "value": {
187
187
  "kind": "expression"
188
188
  }
189
189
  },
190
190
  {
191
- "name": "@disabled-changed",
192
- "description": "Fired when the `disabled` property changes.",
191
+ "name": "@error-changed",
192
+ "description": "Fired when the `error` property changes.",
193
193
  "value": {
194
194
  "kind": "expression"
195
195
  }
196
196
  },
197
197
  {
198
- "name": "@error-changed",
199
- "description": "Fired when the `error` property changes.",
198
+ "name": "@description-changed",
199
+ "description": "Fired when the `description` property changes.",
200
200
  "value": {
201
201
  "kind": "expression"
202
202
  }