@vaadin/login 25.0.0-alpha1 → 25.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.
Files changed (29) hide show
  1. package/package.json +16 -13
  2. package/src/styles/vaadin-login-form-wrapper-base-styles.js +65 -0
  3. package/src/styles/vaadin-login-form-wrapper-core-styles.d.ts +8 -0
  4. package/src/{vaadin-login-form-wrapper-styles.js → styles/vaadin-login-form-wrapper-core-styles.js} +8 -9
  5. package/src/styles/vaadin-login-overlay-wrapper-base-styles.js +55 -0
  6. package/src/styles/vaadin-login-overlay-wrapper-core-styles.d.ts +8 -0
  7. package/src/{vaadin-login-overlay-wrapper-styles.js → styles/vaadin-login-overlay-wrapper-core-styles.js} +5 -2
  8. package/src/title-controller.d.ts +11 -0
  9. package/src/title-controller.js +100 -0
  10. package/src/vaadin-login-form-mixin.js +93 -17
  11. package/src/vaadin-login-form-wrapper.js +16 -24
  12. package/src/vaadin-login-form.d.ts +2 -5
  13. package/src/vaadin-login-form.js +27 -69
  14. package/src/vaadin-login-overlay-mixin.d.ts +1 -2
  15. package/src/vaadin-login-overlay-mixin.js +58 -85
  16. package/src/vaadin-login-overlay-wrapper.js +30 -11
  17. package/src/vaadin-login-overlay.d.ts +29 -19
  18. package/src/vaadin-login-overlay.js +61 -45
  19. package/theme/lumo/vaadin-login-form-wrapper-styles.d.ts +3 -0
  20. package/theme/lumo/vaadin-login-form-wrapper-styles.js +11 -7
  21. package/theme/lumo/vaadin-login-overlay-styles.d.ts +2 -1
  22. package/theme/lumo/vaadin-login-overlay-styles.js +18 -33
  23. package/theme/lumo/vaadin-login-overlay.d.ts +4 -1
  24. package/theme/lumo/vaadin-login-overlay.js +4 -1
  25. package/web-types.json +7 -3
  26. package/web-types.lit.json +10 -3
  27. package/src/vaadin-login-overlay-wrapper-mixin.js +0 -78
  28. /package/src/{vaadin-login-form-wrapper-styles.d.ts → styles/vaadin-login-form-wrapper-base-styles.d.ts} +0 -0
  29. /package/src/{vaadin-login-overlay-wrapper-styles.d.ts → styles/vaadin-login-overlay-wrapper-base-styles.d.ts} +0 -0
@@ -7,7 +7,7 @@ import '@vaadin/button/src/vaadin-button.js';
7
7
  import '@vaadin/text-field/src/vaadin-text-field.js';
8
8
  import '@vaadin/password-field/src/vaadin-password-field.js';
9
9
  import './vaadin-login-form-wrapper.js';
10
- import { html, LitElement } from 'lit';
10
+ import { css, html, LitElement } from 'lit';
11
11
  import { ifDefined } from 'lit/directives/if-defined.js';
12
12
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
13
13
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
@@ -19,7 +19,7 @@ import { LoginFormMixin } from './vaadin-login-form-mixin.js';
19
19
  * `<vaadin-login-form>` is a Web Component providing an easy way to require users
20
20
  * to log in into an application. Note that component has no shadowRoot.
21
21
  *
22
- * ```
22
+ * ```html
23
23
  * <vaadin-login-form></vaadin-login-form>
24
24
  * ```
25
25
  *
@@ -28,10 +28,7 @@ import { LoginFormMixin } from './vaadin-login-form-mixin.js';
28
28
  *
29
29
  * ### Styling
30
30
  *
31
- * The component doesn't have a shadowRoot, so the `<form>` and input fields can be styled from a global scope.
32
- * Use `<vaadin-login-form-wrapper>` themable component to apply styles.
33
- *
34
- * The following shadow DOM parts of the `<vaadin-login-form-wrapper>` are available for styling:
31
+ * The following shadow DOM parts are available for styling:
35
32
  *
36
33
  * Part name | Description
37
34
  * ---------------|---------------------------------------------------------|
@@ -60,79 +57,40 @@ class LoginForm extends LoginFormMixin(ElementMixin(ThemableMixin(PolylitMixin(L
60
57
  return 'vaadin-login-form';
61
58
  }
62
59
 
63
- /**
64
- * @protected
65
- * @override
66
- */
67
- createRenderRoot() {
68
- return this;
60
+ static get styles() {
61
+ return css`
62
+ :host {
63
+ display: block;
64
+ max-width: max-content;
65
+ }
66
+
67
+ :host([hidden]) {
68
+ display: none !important;
69
+ }
70
+ `;
69
71
  }
70
72
 
71
73
  /** @protected */
72
74
  render() {
73
75
  return html`
74
- <style>
75
- vaadin-login-form-wrapper > form > * {
76
- width: 100%;
77
- }
78
- </style>
79
76
  <vaadin-login-form-wrapper
80
- id="vaadinLoginFormWrapper"
77
+ id="form"
81
78
  theme="${ifDefined(this._theme)}"
82
79
  .error="${this.error}"
83
80
  .i18n="${this.__effectiveI18n}"
84
- .headingLevel="${this.headingLevel}"
81
+ part="form"
82
+ role="region"
83
+ aria-labelledby="title"
84
+ exportparts="error-message, error-message-title, error-message-description, footer"
85
85
  >
86
- <form method="POST" action="${ifDefined(this.action)}" @formdata="${this._onFormData}" slot="form">
87
- <input id="csrf" type="hidden" />
88
- <vaadin-text-field
89
- name="username"
90
- .label="${this.__effectiveI18n.form.username}"
91
- .errorMessage="${this.__effectiveI18n.errorMessage.username}"
92
- id="vaadinLoginUsername"
93
- required
94
- @keydown="${this._handleInputKeydown}"
95
- autocapitalize="none"
96
- autocorrect="off"
97
- spellcheck="false"
98
- autocomplete="username"
99
- manual-validation
100
- >
101
- <input type="text" slot="input" @keyup="${this._handleInputKeyup}" />
102
- </vaadin-text-field>
103
-
104
- <vaadin-password-field
105
- name="password"
106
- .label="${this.__effectiveI18n.form.password}"
107
- .errorMessage="${this.__effectiveI18n.errorMessage.password}"
108
- id="vaadinLoginPassword"
109
- required
110
- @keydown="${this._handleInputKeydown}"
111
- spellcheck="false"
112
- autocomplete="current-password"
113
- manual-validation
114
- >
115
- <input type="password" slot="input" @keyup="${this._handleInputKeyup}" />
116
- </vaadin-password-field>
117
- </form>
118
-
119
- <vaadin-button
120
- slot="submit"
121
- theme="primary contained submit"
122
- @click="${this.submit}"
123
- .disabled="${this.disabled}"
124
- >
125
- ${this.__effectiveI18n.form.submit}
126
- </vaadin-button>
127
-
128
- <vaadin-button
129
- slot="forgot-password"
130
- theme="tertiary small"
131
- @click="${this._onForgotPasswordClick}"
132
- ?hidden="${this.noForgotPassword}"
133
- >
134
- ${this.__effectiveI18n.form.forgotPassword}
135
- </vaadin-button>
86
+ <div id="title" slot="form-title" part="form-title" role="heading" aria-level="${this.headingLevel}">
87
+ ${this.__effectiveI18n.form.title}
88
+ </div>
89
+ <slot name="form" slot="form"></slot>
90
+ <slot name="custom-form-area" slot="custom-form-area"></slot>
91
+ <slot name="submit" slot="submit"></slot>
92
+ <slot name="forgot-password" slot="forgot-password"></slot>
93
+ <slot name="footer" slot="footer"></slot>
136
94
  </vaadin-login-form-wrapper>
137
95
  `;
138
96
  }
@@ -5,11 +5,10 @@
5
5
  */
6
6
  import type { Constructor } from '@open-wc/dedupe-mixin';
7
7
  import type { OverlayClassMixinClass } from '@vaadin/component-base/src/overlay-class-mixin.js';
8
- import type { LoginMixinClass } from './vaadin-login-mixin.js';
9
8
 
10
9
  export declare function LoginOverlayMixin<T extends Constructor<HTMLElement>>(
11
10
  base: T,
12
- ): Constructor<LoginMixinClass> & Constructor<LoginOverlayMixinClass> & Constructor<OverlayClassMixinClass> & T;
11
+ ): Constructor<LoginOverlayMixinClass> & Constructor<OverlayClassMixinClass> & T;
13
12
 
14
13
  export declare class LoginOverlayMixinClass {
15
14
  /**
@@ -4,15 +4,14 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
7
- import { LoginMixin } from './vaadin-login-mixin.js';
7
+ import { TitleController } from './title-controller.js';
8
8
 
9
9
  /**
10
10
  * @polymerMixin
11
- * @mixes LoginMixin
12
11
  * @mixes OverlayClassMixin
13
12
  */
14
13
  export const LoginOverlayMixin = (superClass) =>
15
- class LoginOverlayMixin extends OverlayClassMixin(LoginMixin(superClass)) {
14
+ class LoginOverlayMixin extends OverlayClassMixin(superClass) {
16
15
  static get properties() {
17
16
  return {
18
17
  /**
@@ -32,8 +31,8 @@ export const LoginOverlayMixin = (superClass) =>
32
31
  opened: {
33
32
  type: Boolean,
34
33
  value: false,
34
+ reflectToAttribute: true,
35
35
  sync: true,
36
- observer: '_onOpenedChange',
37
36
  },
38
37
 
39
38
  /**
@@ -47,15 +46,43 @@ export const LoginOverlayMixin = (superClass) =>
47
46
  };
48
47
  }
49
48
 
50
- static get observers() {
51
- return ['__i18nChanged(__effectiveI18n)'];
49
+ /** @protected */
50
+ firstUpdated() {
51
+ super.firstUpdated();
52
+
53
+ this.setAttribute('role', 'dialog');
54
+
55
+ this.__titleController = new TitleController(this);
56
+ this.addController(this.__titleController);
57
+
58
+ this._overlayElement = this.$.overlay;
52
59
  }
53
60
 
54
61
  /** @protected */
55
- ready() {
56
- super.ready();
62
+ willUpdate(props) {
63
+ super.willUpdate(props);
64
+
65
+ if (props.has('__effectiveI18n') && this.__effectiveI18n.header) {
66
+ this.title = this.__effectiveI18n.header.title;
67
+ this.description = this.__effectiveI18n.header.description;
68
+ }
69
+ }
70
+
71
+ /** @protected */
72
+ updated(props) {
73
+ super.updated(props);
74
+
75
+ if (props.has('title') || props.has('__effectiveI18n')) {
76
+ this.__titleController.setTitle(this.title);
77
+ }
57
78
 
58
- this._overlayElement = this.$.vaadinLoginOverlayWrapper;
79
+ if (props.has('headingLevel')) {
80
+ this.__titleController.setLevel(this.headingLevel);
81
+ }
82
+
83
+ if (props.has('opened')) {
84
+ this._openedChanged(this.opened);
85
+ }
59
86
  }
60
87
 
61
88
  /** @protected */
@@ -72,19 +99,14 @@ export const LoginOverlayMixin = (superClass) =>
72
99
  disconnectedCallback() {
73
100
  super.disconnectedCallback();
74
101
 
75
- // Close overlay and memorize opened state
76
- this.__restoreOpened = this.opened;
77
- this.opened = false;
78
- }
79
-
80
- /** @private */
81
- __i18nChanged(effectiveI18n) {
82
- const header = effectiveI18n && effectiveI18n.header;
83
- if (!header) {
84
- return;
85
- }
86
- this.title = header.title;
87
- this.description = header.description;
102
+ // Using a timeout to avoid toggling opened state
103
+ // when just moving the overlay in the DOM
104
+ setTimeout(() => {
105
+ if (!this.isConnected) {
106
+ this.__restoreOpened = this.opened;
107
+ this.opened = false;
108
+ }
109
+ });
88
110
  }
89
111
 
90
112
  /** @protected */
@@ -92,77 +114,28 @@ export const LoginOverlayMixin = (superClass) =>
92
114
  e.preventDefault();
93
115
  }
94
116
 
95
- /**
96
- * @param {!Event} e
97
- * @protected
98
- */
99
- _retargetEvent(e) {
100
- e.stopPropagation();
101
- const { detail, composed, cancelable, bubbles } = e;
102
-
103
- const firedEvent = this.dispatchEvent(new CustomEvent(e.type, { bubbles, cancelable, composed, detail }));
104
- // Check if `eventTarget.preventDefault()` was called to prevent default in the original event
105
- if (!firedEvent) {
106
- e.preventDefault();
107
- }
117
+ /** @private */
118
+ __handleOverlayClosed() {
119
+ this.dispatchEvent(new CustomEvent('closed'));
108
120
  }
109
121
 
110
122
  /** @private */
111
- _onOpenedChange() {
112
- const form = this.$.vaadinLoginForm;
113
-
114
- if (!this.opened) {
115
- form.$.vaadinLoginUsername.value = '';
116
- form.$.vaadinLoginPassword.value = '';
123
+ _openedChanged(opened, oldOpened) {
124
+ if (oldOpened) {
125
+ this._userNameField.value = '';
126
+ this._passwordField.value = '';
117
127
  this.disabled = false;
118
-
119
- if (this._undoTitleTeleport) {
120
- this._undoTitleTeleport();
121
- }
122
-
123
- if (this._undoFieldsTeleport) {
124
- this._undoFieldsTeleport();
125
- }
126
-
127
- if (this._undoFooterTeleport) {
128
- this._undoFooterTeleport();
129
- }
130
- } else {
131
- this._undoTitleTeleport = this._teleport('title', this.$.vaadinLoginOverlayWrapper);
132
-
133
- this._undoFieldsTeleport = this._teleport(
134
- 'custom-form-area',
135
- form.$.vaadinLoginFormWrapper,
136
- form.querySelector('vaadin-button'),
137
- );
138
-
139
- this._undoFooterTeleport = this._teleport('footer', form.$.vaadinLoginFormWrapper);
140
-
128
+ } else if (opened) {
141
129
  // Overlay sets pointerEvents on body to `none`, which breaks LastPass popup
142
130
  // Reverting it back to the previous state
143
131
  // https://github.com/vaadin/vaadin-overlay/blob/041cde4481b6262eac68d3a699f700216d897373/src/vaadin-overlay.html#L660
144
- document.body.style.pointerEvents = this.$.vaadinLoginOverlayWrapper._previousDocumentPointerEvents;
132
+ document.body.style.pointerEvents = this.$.overlay._previousDocumentPointerEvents;
145
133
  }
146
134
  }
147
135
 
148
- /** @private */
149
- _teleport(slot, target, refNode) {
150
- const teleported = [...this.querySelectorAll(`[slot="${slot}"]`)].map((el) => {
151
- if (refNode) {
152
- target.insertBefore(el, refNode);
153
- } else {
154
- target.appendChild(el);
155
- }
156
- return el;
157
- });
158
- // Function to undo the teleport
159
- return () => {
160
- this.append(...teleported);
161
- };
162
- }
163
-
164
- /** @private */
165
- __computeHeadingLevel(headingLevel) {
166
- return headingLevel + 1;
167
- }
136
+ /**
137
+ * Fired when the overlay is closed.
138
+ *
139
+ * @event closed
140
+ */
168
141
  };
@@ -5,27 +5,48 @@
5
5
  */
6
6
  import { html, LitElement } from 'lit';
7
7
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
8
+ import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
8
9
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
9
- import { overlayStyles } from '@vaadin/overlay/src/vaadin-overlay-styles.js';
10
+ import { OverlayMixin } from '@vaadin/overlay/src/vaadin-overlay-mixin.js';
11
+ import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
10
12
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
11
- import { LoginOverlayWrapperMixin } from './vaadin-login-overlay-wrapper-mixin.js';
12
- import { loginOverlayWrapperStyles } from './vaadin-login-overlay-wrapper-styles.js';
13
+ import { loginOverlayWrapperStyles } from './styles/vaadin-login-overlay-wrapper-core-styles.js';
13
14
 
14
15
  /**
15
16
  * An element used internally by `<vaadin-login-overlay>`. Not intended to be used separately.
16
17
  *
17
18
  * @extends HTMLElement
18
- * @mixes LoginOverlayWrapperMixin
19
+ * @mixes DirMixin
20
+ * @mixes OverlayMixin
19
21
  * @mixes ThemableMixin
20
22
  * @private
21
23
  */
22
- class LoginOverlayWrapper extends LoginOverlayWrapperMixin(ThemableMixin(PolylitMixin(LitElement))) {
24
+ class LoginOverlayWrapper extends OverlayMixin(DirMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
23
25
  static get is() {
24
26
  return 'vaadin-login-overlay-wrapper';
25
27
  }
26
28
 
27
29
  static get styles() {
28
- return [overlayStyles, loginOverlayWrapperStyles];
30
+ return loginOverlayWrapperStyles;
31
+ }
32
+
33
+ static get properties() {
34
+ return {
35
+ /**
36
+ * Application description. Displayed under the title.
37
+ */
38
+ description: {
39
+ type: String,
40
+ },
41
+ };
42
+ }
43
+
44
+ /**
45
+ * @protected
46
+ * @override
47
+ */
48
+ get _modalRoot() {
49
+ return this.owner;
29
50
  }
30
51
 
31
52
  /** @protected */
@@ -36,12 +57,10 @@ class LoginOverlayWrapper extends LoginOverlayWrapperMixin(ThemableMixin(Polylit
36
57
  <div part="content" id="content">
37
58
  <section part="card">
38
59
  <div part="brand">
39
- <slot name="title">
40
- <div part="title" role="heading" aria-level="${this.headingLevel}">${this.title}</div>
41
- </slot>
42
- <p part="description">${this.description}</p>
60
+ <slot name="title"></slot>
61
+ <div part="description">${this.description}</div>
43
62
  </div>
44
- <div part="form">
63
+ <div part="form-wrapper">
45
64
  <slot></slot>
46
65
  </div>
47
66
  </section>
@@ -5,6 +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 { LoginFormMixin } from './vaadin-login-form-mixin.js';
8
9
  import { LoginOverlayMixin } from './vaadin-login-overlay-mixin.js';
9
10
 
10
11
  export { LoginI18n } from './vaadin-login-mixin.js';
@@ -33,6 +34,11 @@ export type LoginOverlayLoginEvent = CustomEvent<{
33
34
  custom?: Record<string, unknown>;
34
35
  }>;
35
36
 
37
+ /**
38
+ * Fired when the overlay is closed.
39
+ */
40
+ export type LoginOverlayClosedEvent = CustomEvent;
41
+
36
42
  export interface LoginOverlayCustomEventMap {
37
43
  'description-changed': LoginOverlayDescriptionChangedEvent;
38
44
 
@@ -43,44 +49,48 @@ export interface LoginOverlayCustomEventMap {
43
49
  'forgot-password': Event;
44
50
 
45
51
  login: LoginOverlayLoginEvent;
52
+
53
+ closed: LoginOverlayClosedEvent;
46
54
  }
47
55
 
48
56
  export interface LoginOverlayEventMap extends HTMLElementEventMap, LoginOverlayCustomEventMap {}
49
57
 
50
58
  /**
51
- * `<vaadin-login-overlay>` is a wrapper of the `<vaadin-login-form>` which opens a login form in an overlay and
52
- * having an additional `brand` part for application title and description. Using `<vaadin-login-overlay>` allows
53
- * password managers to work with login form.
59
+ * `<vaadin-login-overlay>` is a web component which renders a login form in an overlay and
60
+ * provides an additional `brand` part for application title and description.
54
61
  *
55
- * ```
62
+ * ```html
56
63
  * <vaadin-login-overlay opened></vaadin-login-overlay>
57
64
  * ```
58
65
  *
59
66
  * ### Styling
60
67
  *
61
- * The component doesn't have a shadowRoot, so the `<form>` and input fields can be styled from a global scope.
62
- * Use `<vaadin-login-overlay-wrapper>` and `<vaadin-login-form-wrapper>` to apply styles.
63
- *
64
- * The following Shadow DOM parts of the `<vaadin-login-overlay-wrapper>` are available for styling:
65
- *
66
- * Part name | Description
67
- * ----------------|---------------------------------------------------------|
68
- * `card` | Container for the entire component's content
69
- * `brand` | Container for application title and description
70
- * `form` | Container for the `<vaadin-login-form>` component
71
- *
72
- * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
68
+ * The following shadow DOM parts are available for styling:
73
69
  *
74
- * See [`<vaadin-login-form>`](#/elements/vaadin-login-form)
75
- * documentation for `<vaadin-login-form-wrapper>` stylable parts.
70
+ * Part name | Description
71
+ * -----------------------------|--------------------------------
72
+ * `backdrop` | Backdrop of the overlay
73
+ * `overlay` | The overlay container element
74
+ * `content` | The overlay content element
75
+ * `card` | Container for the brand and form wrapper
76
+ * `brand` | Container for application title and description
77
+ * `description` | The application description
78
+ * `form-wrapper` | The login form wrapper element
79
+ * `form` | The login form element
80
+ * `form-title` | Title of the login form
81
+ * `error-message` | Container for error message
82
+ * `error-message-title` | Container for error message title
83
+ * `error-message-description` | Container for error message description
84
+ * `footer` | Container for the footer element
76
85
  *
77
86
  * @fires {CustomEvent} description-changed - Fired when the `description` property changes.
78
87
  * @fires {CustomEvent} disabled-changed - Fired when the `disabled` property changes.
79
88
  * @fires {CustomEvent} error-changed - Fired when the `error` property changes.
80
89
  * @fires {CustomEvent} forgot-password - Fired when user clicks on the "Forgot password" button.
81
90
  * @fires {CustomEvent} login - Fired when a user submits the login.
91
+ * @fires {CustomEvent} closed - Fired when the overlay is closed.
82
92
  */
83
- declare class LoginOverlay extends LoginOverlayMixin(ElementMixin(ThemableMixin(HTMLElement))) {
93
+ declare class LoginOverlay extends LoginFormMixin(LoginOverlayMixin(ElementMixin(ThemableMixin(HTMLElement)))) {
84
94
  addEventListener<K extends keyof LoginOverlayEventMap>(
85
95
  type: K,
86
96
  listener: (this: LoginOverlay, ev: LoginOverlayEventMap[K]) => void,
@@ -3,97 +3,118 @@
3
3
  * Copyright (c) 2018 - 2025 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import './vaadin-login-form.js';
6
+ import '@vaadin/button/src/vaadin-button.js';
7
+ import '@vaadin/text-field/src/vaadin-text-field.js';
8
+ import '@vaadin/password-field/src/vaadin-password-field.js';
9
+ import './vaadin-login-form-wrapper.js';
7
10
  import './vaadin-login-overlay-wrapper.js';
8
- import { html, LitElement } from 'lit';
11
+ import { css, html, LitElement } from 'lit';
9
12
  import { ifDefined } from 'lit/directives/if-defined.js';
10
13
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
11
14
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
12
15
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
13
16
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
17
+ import { LoginFormMixin } from './vaadin-login-form-mixin.js';
14
18
  import { LoginOverlayMixin } from './vaadin-login-overlay-mixin.js';
15
19
 
16
20
  /**
17
- * `<vaadin-login-overlay>` is a wrapper of the `<vaadin-login-form>` which opens a login form in an overlay and
18
- * having an additional `brand` part for application title and description. Using `<vaadin-login-overlay>` allows
19
- * password managers to work with login form.
21
+ * `<vaadin-login-overlay>` is a web component which renders a login form in an overlay and
22
+ * provides an additional `brand` part for application title and description.
20
23
  *
21
- * ```
24
+ * ```html
22
25
  * <vaadin-login-overlay opened></vaadin-login-overlay>
23
26
  * ```
24
27
  *
25
28
  * ### Styling
26
29
  *
27
- * The component doesn't have a shadowRoot, so the `<form>` and input fields can be styled from a global scope.
28
- * Use `<vaadin-login-overlay-wrapper>` and `<vaadin-login-form-wrapper>` to apply styles.
29
- *
30
- * The following shadow DOM parts of the `<vaadin-login-overlay-wrapper>` are available for styling:
30
+ * The following shadow DOM parts are available for styling:
31
31
  *
32
- * Part name | Description
33
- * ----------------|---------------------------------------------------------|
34
- * `card` | Container for the entire component's content
35
- * `brand` | Container for application title and description
36
- * `form` | Container for the `<vaadin-login-form>` component
32
+ * Part name | Description
33
+ * -----------------------------|--------------------------------
34
+ * `backdrop` | Backdrop of the overlay
35
+ * `overlay` | The overlay container element
36
+ * `content` | The overlay content element
37
+ * `card` | Container for the brand and form wrapper
38
+ * `brand` | Container for application title and description
39
+ * `description` | The application description
40
+ * `form-wrapper` | The login form wrapper element
41
+ * `form` | The login form element
42
+ * `form-title` | Title of the login form
43
+ * `error-message` | Container for error message
44
+ * `error-message-title` | Container for error message title
45
+ * `error-message-description` | Container for error message description
46
+ * `footer` | Container for the footer element
37
47
  *
38
48
  * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.
39
49
  *
40
- * See [`<vaadin-login-form>`](#/elements/vaadin-login-form)
41
- * documentation for `<vaadin-login-form-wrapper>` stylable parts.
42
- *
43
50
  * @fires {CustomEvent} description-changed - Fired when the `description` property changes.
44
51
  * @fires {CustomEvent} disabled-changed - Fired when the `disabled` property changes.
45
52
  * @fires {CustomEvent} error-changed - Fired when the `error` property changes.
46
53
  * @fires {CustomEvent} forgot-password - Fired when user clicks on the "Forgot password" button.
47
54
  * @fires {CustomEvent} login - Fired when a user submits the login.
55
+ * @fires {CustomEvent} closed - Fired when the overlay is closed.
48
56
  *
49
57
  * @customElement
50
58
  * @extends HTMLElement
51
59
  * @mixes ElementMixin
52
60
  * @mixes ThemableMixin
61
+ * @mixes LoginFormMixin
53
62
  * @mixes LoginOverlayMixin
54
63
  */
55
- class LoginOverlay extends LoginOverlayMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
64
+ class LoginOverlay extends LoginFormMixin(LoginOverlayMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement))))) {
56
65
  static get is() {
57
66
  return 'vaadin-login-overlay';
58
67
  }
59
68
 
69
+ static get styles() {
70
+ return css`
71
+ :host {
72
+ display: block;
73
+ }
74
+
75
+ :host([hidden]) {
76
+ display: none !important;
77
+ }
78
+ `;
79
+ }
80
+
60
81
  /** @protected */
61
82
  render() {
62
83
  return html`
63
84
  <vaadin-login-overlay-wrapper
64
- id="vaadinLoginOverlayWrapper"
85
+ id="overlay"
86
+ .owner="${this}"
65
87
  .opened="${this.opened}"
66
- .title="${this.title}"
67
88
  .description="${this.description}"
68
- .headingLevel="${this.headingLevel}"
69
- role="dialog"
70
89
  focus-trap
71
90
  with-backdrop
72
91
  theme="${ifDefined(this._theme)}"
73
92
  @vaadin-overlay-escape-press="${this._preventClosingLogin}"
74
93
  @vaadin-overlay-outside-click="${this._preventClosingLogin}"
94
+ @vaadin-overlay-closed="${this.__handleOverlayClosed}"
75
95
  @opened-changed="${this._onOpenedChanged}"
96
+ exportparts="backdrop, overlay, content, card, brand, description, form-wrapper"
76
97
  >
77
- <vaadin-login-form
78
- theme="with-overlay"
79
- id="vaadinLoginForm"
80
- .action="${this.action}"
81
- .disabled="${this.disabled}"
98
+ <slot name="title" slot="title"></slot>
99
+ <vaadin-login-form-wrapper
100
+ id="form"
82
101
  .error="${this.error}"
83
- .noAutofocus="${this.noAutofocus}"
84
- .noForgotPassword="${this.noForgotPassword}"
85
- .headingLevel="${this.__computeHeadingLevel(this.headingLevel)}"
86
102
  .i18n="${this.__effectiveI18n}"
87
- @login="${this._retargetEvent}"
88
- @forgot-password="${this._retargetEvent}"
89
- @disabled-changed="${this._onDisabledChanged}"
90
- ></vaadin-login-form>
103
+ part="form"
104
+ role="region"
105
+ aria-labelledby="title"
106
+ exportparts="error-message, error-message-title, error-message-description, footer"
107
+ >
108
+ <div id="title" slot="form-title" part="form-title" role="heading" aria-level="${this.headingLevel + 1}">
109
+ ${this.__effectiveI18n.form.title}
110
+ </div>
111
+ <slot name="form" slot="form"></slot>
112
+ <slot name="custom-form-area" slot="custom-form-area"></slot>
113
+ <slot name="submit" slot="submit"></slot>
114
+ <slot name="forgot-password" slot="forgot-password"></slot>
115
+ <slot name="footer" slot="footer"></slot>
116
+ </vaadin-login-form-wrapper>
91
117
  </vaadin-login-overlay-wrapper>
92
-
93
- <div hidden>
94
- <slot name="custom-form-area"></slot>
95
- <slot name="footer"></slot>
96
- </div>
97
118
  `;
98
119
  }
99
120
 
@@ -101,11 +122,6 @@ class LoginOverlay extends LoginOverlayMixin(ElementMixin(ThemableMixin(PolylitM
101
122
  _onOpenedChanged(event) {
102
123
  this.opened = event.detail.value;
103
124
  }
104
-
105
- /** @private */
106
- _onDisabledChanged(event) {
107
- this.disabled = event.detail.value;
108
- }
109
125
  }
110
126
 
111
127
  defineCustomElement(LoginOverlay);