@teipublisher/pb-components 2.25.4 → 2.26.0-next-3.2

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/pb-elements.json CHANGED
@@ -3254,6 +3254,143 @@
3254
3254
  }
3255
3255
  ]
3256
3256
  },
3257
+ {
3258
+ "name": "pb-dialog",
3259
+ "path": "./src/pb-dialog.js",
3260
+ "description": "A simple dialog component using the HTML5 <dialog> element",
3261
+ "attributes": [
3262
+ {
3263
+ "name": "open",
3264
+ "type": "boolean",
3265
+ "default": "false"
3266
+ },
3267
+ {
3268
+ "name": "modal",
3269
+ "type": "boolean",
3270
+ "default": "true"
3271
+ },
3272
+ {
3273
+ "name": "title",
3274
+ "type": "string"
3275
+ },
3276
+ {
3277
+ "name": "message",
3278
+ "type": "string"
3279
+ },
3280
+ {
3281
+ "name": "subscribe",
3282
+ "description": "The name of the channel to subscribe to. Only events on a channel corresponding\nto this property are listened to.",
3283
+ "type": "string"
3284
+ },
3285
+ {
3286
+ "name": "subscribe-config",
3287
+ "description": "Configuration object to define a channel/event mapping. Every property\nin the object is interpreted as the name of a channel and its value should\nbe an array of event names to listen to.",
3288
+ "type": "object"
3289
+ },
3290
+ {
3291
+ "name": "emit",
3292
+ "description": "The name of the channel to send events to.",
3293
+ "type": "string"
3294
+ },
3295
+ {
3296
+ "name": "emit-config",
3297
+ "description": "Configuration object to define a channel/event mapping. Every property\nin the object is interpreted as the name of a channel and its value should\nbe an array of event names to be dispatched.",
3298
+ "type": "object"
3299
+ },
3300
+ {
3301
+ "name": "wait-for",
3302
+ "description": "A selector pointing to other components this component depends on.\nWhen method `wait` is called, it will wait until all referenced\ncomponents signal with a `pb-ready` event that they are ready and listening\nto events.",
3303
+ "type": "string"
3304
+ },
3305
+ {
3306
+ "name": "disabled",
3307
+ "description": "Common property to disable the functionality associated with a component.\n`pb-highlight` and `pb-popover` react to this.",
3308
+ "type": "boolean",
3309
+ "default": "false"
3310
+ }
3311
+ ],
3312
+ "properties": [
3313
+ {
3314
+ "name": "open",
3315
+ "attribute": "open",
3316
+ "type": "boolean",
3317
+ "default": "false"
3318
+ },
3319
+ {
3320
+ "name": "modal",
3321
+ "attribute": "modal",
3322
+ "type": "boolean",
3323
+ "default": "true"
3324
+ },
3325
+ {
3326
+ "name": "title",
3327
+ "attribute": "title",
3328
+ "type": "string"
3329
+ },
3330
+ {
3331
+ "name": "message",
3332
+ "attribute": "message",
3333
+ "type": "string"
3334
+ },
3335
+ {
3336
+ "name": "subscribe",
3337
+ "attribute": "subscribe",
3338
+ "description": "The name of the channel to subscribe to. Only events on a channel corresponding\nto this property are listened to.",
3339
+ "type": "string"
3340
+ },
3341
+ {
3342
+ "name": "subscribeConfig",
3343
+ "attribute": "subscribe-config",
3344
+ "description": "Configuration object to define a channel/event mapping. Every property\nin the object is interpreted as the name of a channel and its value should\nbe an array of event names to listen to.",
3345
+ "type": "object"
3346
+ },
3347
+ {
3348
+ "name": "emit",
3349
+ "attribute": "emit",
3350
+ "description": "The name of the channel to send events to.",
3351
+ "type": "string"
3352
+ },
3353
+ {
3354
+ "name": "emitConfig",
3355
+ "attribute": "emit-config",
3356
+ "description": "Configuration object to define a channel/event mapping. Every property\nin the object is interpreted as the name of a channel and its value should\nbe an array of event names to be dispatched.",
3357
+ "type": "object"
3358
+ },
3359
+ {
3360
+ "name": "waitFor",
3361
+ "attribute": "wait-for",
3362
+ "description": "A selector pointing to other components this component depends on.\nWhen method `wait` is called, it will wait until all referenced\ncomponents signal with a `pb-ready` event that they are ready and listening\nto events.",
3363
+ "type": "string"
3364
+ },
3365
+ {
3366
+ "name": "disabled",
3367
+ "attribute": "disabled",
3368
+ "description": "Common property to disable the functionality associated with a component.\n`pb-highlight` and `pb-popover` react to this.",
3369
+ "type": "boolean",
3370
+ "default": "false"
3371
+ }
3372
+ ],
3373
+ "events": [
3374
+ {
3375
+ "name": "pb-dialog-opened",
3376
+ "description": "Fired when the dialog is opened"
3377
+ },
3378
+ {
3379
+ "name": "pb-dialog-closed",
3380
+ "description": "Fired when the dialog is closed"
3381
+ }
3382
+ ],
3383
+ "slots": [
3384
+ {
3385
+ "name": "",
3386
+ "description": "Content of the dialog"
3387
+ },
3388
+ {
3389
+ "name": "title",
3390
+ "description": "Title of the dialog"
3391
+ }
3392
+ ]
3393
+ },
3257
3394
  {
3258
3395
  "name": "pb-document",
3259
3396
  "path": "./src/pb-document.js",
@@ -5381,11 +5518,6 @@
5381
5518
  "name": "selected",
5382
5519
  "type": "string"
5383
5520
  },
5384
- {
5385
- "name": "nolabel",
5386
- "description": "suppresses the label",
5387
- "type": "boolean"
5388
- },
5389
5521
  {
5390
5522
  "name": "label",
5391
5523
  "description": "The label for a language in the dropdown",
@@ -5430,12 +5562,6 @@
5430
5562
  "attribute": "selected",
5431
5563
  "type": "string"
5432
5564
  },
5433
- {
5434
- "name": "nolabel",
5435
- "attribute": "nolabel",
5436
- "description": "suppresses the label",
5437
- "type": "boolean"
5438
- },
5439
5565
  {
5440
5566
  "name": "label",
5441
5567
  "attribute": "label",
@@ -5492,6 +5618,10 @@
5492
5618
  }
5493
5619
  ],
5494
5620
  "slots": [
5621
+ {
5622
+ "name": "select",
5623
+ "description": "Optional select element to use for language selection. If not provided, a default one will be created."
5624
+ },
5495
5625
  {
5496
5626
  "name": "",
5497
5627
  "description": "unnamed default slot for dropdown menu options"
@@ -5501,10 +5631,6 @@
5501
5631
  {
5502
5632
  "name": "--pb-lang-input-color",
5503
5633
  "description": "Color of the text in the language field"
5504
- },
5505
- {
5506
- "name": "--pb-lang-label-color",
5507
- "description": "Color of the language field label"
5508
5634
  }
5509
5635
  ]
5510
5636
  },
@@ -61,6 +61,7 @@ import './pb-split-list.js';
61
61
  import './pb-timeline.js';
62
62
  import './pb-combo-box.js';
63
63
  import './pb-print-preview.js';
64
+ import './pb-dialog.js';
64
65
 
65
66
  import '@polymer/iron-icons/editor-icons';
66
67
  import '@polymer/iron-icons/social-icons';
@@ -0,0 +1,83 @@
1
+ import { LitElement, css, html } from 'lit-element';
2
+ import { pbMixin } from './pb-mixin';
3
+ import { unsafeHTML } from 'lit-html/directives/unsafe-html';
4
+ import { themableMixin } from './theming.js';
5
+
6
+ /**
7
+ * A simple dialog component using the HTML5 <dialog> element
8
+ *
9
+ * @slot - Content of the dialog
10
+ * @slot title - Title of the dialog
11
+ * @fires pb-dialog-opened - Fired when the dialog is opened
12
+ * @fires pb-dialog-closed - Fired when the dialog is closed
13
+ */
14
+ export class PbDialog extends themableMixin(pbMixin(LitElement)) {
15
+
16
+ static get properties() {
17
+ return {
18
+ ...super.properties,
19
+ open: { type: Boolean, reflect: true },
20
+ modal: { type: Boolean, reflect: true },
21
+ title: { type: String, reflect: true },
22
+ message: { type: String, reflect: true }
23
+ };
24
+ }
25
+
26
+ constructor() {
27
+ super();
28
+ this.open = false;
29
+ this.modal = true;
30
+ this._escListener = this._onEsc.bind(this);
31
+ this.title = null;
32
+ this.message = null;
33
+ }
34
+
35
+ _onEsc(e) {
36
+ if (e.key === 'Escape' && this.open) {
37
+ this.closeDialog();
38
+ }
39
+ }
40
+
41
+ openDialog() {
42
+ if (!this.open) {
43
+ if (this.modal) {
44
+ this._dialog.showModal();
45
+ } else {
46
+ this._dialog.show();
47
+ }
48
+ this.dispatchEvent(new CustomEvent('pb-dialog-opened', { bubbles: true, composed: true }));
49
+ this.open = true;
50
+ }
51
+ }
52
+
53
+ closeDialog() {
54
+ if (this.open) {
55
+ this._dialog.close();
56
+ this.dispatchEvent(new CustomEvent('pb-dialog-closed', { bubbles: true, composed: true }));
57
+ this.open = false;
58
+ }
59
+ }
60
+
61
+ render() {
62
+ return html`
63
+ <dialog @click="${(e) => e.target === this._dialog && this.modal && this.closeDialog()}">
64
+ <article>
65
+ <header>
66
+ ${this.title ? unsafeHTML(this.title) : html`<slot name="title"></slot>`}
67
+ <button rel="prev" aria-label="Close" @click="${this.closeDialog}">&times;</button>
68
+ </header>
69
+ ${this.message ? unsafeHTML(this.message) : html`<slot></slot>`}
70
+ <footer>
71
+ <slot name="footer"></slot>
72
+ </footer>
73
+ </article>
74
+ </dialog>
75
+ `;
76
+ }
77
+
78
+ firstUpdated() {
79
+ this._dialog = this.renderRoot.querySelector('dialog');
80
+ }
81
+ }
82
+
83
+ customElements.define('pb-dialog', PbDialog);
@@ -200,8 +200,9 @@ export class PbDownload extends pbMixin(LitElement) {
200
200
  if (this.dialog) {
201
201
  const dialog = document.getElementById(this.dialog);
202
202
 
203
- //todo: this will error when dialog is not found or defined on element.
204
- dialog.open();
203
+ if (dialog) {
204
+ dialog.openDialog();
205
+ }
205
206
 
206
207
  const token = this._token;
207
208
  const downloadCheck = window.setInterval(() => {
@@ -209,7 +210,9 @@ export class PbDownload extends pbMixin(LitElement) {
209
210
  if (cookieValue === token) {
210
211
  window.clearInterval(downloadCheck);
211
212
  Cookies.remove("simple.token");
212
- dialog.close();
213
+ if (dialog) {
214
+ dialog.closeDialog();
215
+ }
213
216
  }
214
217
  });
215
218
  }
package/src/pb-lang.js CHANGED
@@ -1,19 +1,35 @@
1
1
  import { LitElement, html, css } from 'lit-element';
2
- import '@polymer/paper-dropdown-menu/paper-dropdown-menu.js';
3
- import '@polymer/paper-listbox';
4
2
  import { pbMixin, waitOnce } from './pb-mixin.js';
5
3
  import { translate } from "./pb-i18n.js";
4
+ import { themableMixin } from './theming.js';
6
5
 
7
6
  /**
8
7
  * A dropdown for switching the interface language.
9
8
  *
9
+ * @slot select - Optional select element to use for language selection. If not provided, a default one will be created.
10
10
  * @slot - unnamed default slot for dropdown menu options
11
11
  * @fires pb-i18n-language - Sends selected language
12
12
  * @fires pb-i18n-update - When received, sets the selected language to the one received from the event
13
13
  * @cssprop --pb-lang-input-color - Color of the text in the language field
14
- * @cssprop --pb-lang-label-color - Color of the language field label
15
14
  */
16
- export class PbLang extends pbMixin(LitElement) {
15
+ export class PbLang extends themableMixin(pbMixin(LitElement)) {
16
+ static get styles() {
17
+ return css`
18
+ :host {
19
+ display: inline-block;
20
+ }
21
+ ::slotted(*) {
22
+ display: none;
23
+ }
24
+ ::slotted(select) {
25
+ display: inline-block;
26
+ }
27
+ select {
28
+ color: var(--pb-lang-input-color, inherit);
29
+ }
30
+ `;
31
+ }
32
+
17
33
  static get properties() {
18
34
  return {
19
35
  ...super.properties,
@@ -25,12 +41,6 @@ export class PbLang extends pbMixin(LitElement) {
25
41
  },
26
42
  selected: {
27
43
  type: String
28
- },
29
- /**
30
- * suppresses the label
31
- */
32
- nolabel:{
33
- type:Boolean
34
44
  }
35
45
  };
36
46
  }
@@ -45,45 +55,50 @@ export class PbLang extends pbMixin(LitElement) {
45
55
 
46
56
  this.subscribeTo('pb-i18n-update', (ev) => {
47
57
  this.selected = ev.detail.language.replace(/^([^-]+).*$/, '$1');
58
+ this._syncOptions();
48
59
  }, []);
49
60
  waitOnce('pb-i18n-update', (options) => {
50
61
  this.selected = options.language.replace(/^([^-]+).*$/, '$1');
62
+ this._syncOptions();
51
63
  });
52
64
  }
53
65
 
54
66
  render() {
55
67
  return html`
56
- ${this.nolabel?
57
- html`
58
- <paper-dropdown-menu>
59
- <paper-listbox id="menu" slot="dropdown-content" class="dropdown-content" selected="${this.selected}"
60
- attr-for-selected="value" @selected-item-changed="${this._changed}">
61
- <slot></slot>
62
- </paper-listbox>
63
- </paper-dropdown-menu>`:
64
- html`
65
- <paper-dropdown-menu label="${translate(this.label)}">
66
- <paper-listbox id="menu" slot="dropdown-content" class="dropdown-content" selected="${this.selected}"
67
- attr-for-selected="value" @selected-item-changed="${this._changed}">
68
- <slot></slot>
69
- </paper-listbox>
70
- </paper-dropdown-menu>`
71
- }
68
+ <select name="select" @change="${this._changed}" aria-label="${translate(this.label)}" title="${translate(this.label)}"></select>
69
+ <slot @slotchange="${this._syncOptions}"></slot>
72
70
  `;
73
71
  }
74
72
 
75
- static get styles() {
76
- return css`
77
- :host {
78
- display: block;
79
- --paper-input-container-input-color: var(--pb-lang-input-color, black);
80
- --paper-input-container-color: var(--pb-lang-label-color, --paper-grey-100);
81
- }
82
- `;
73
+ _syncOptions() {
74
+ // First try to find select in light DOM (slotted)
75
+ let select = this.querySelector('select');
76
+ // If not found, look in shadow DOM (default)
77
+ if (!select) {
78
+ select = this.shadowRoot.querySelector('select');
79
+ }
80
+ if (!select) return;
81
+
82
+ // Clear existing options
83
+ select.innerHTML = '';
84
+
85
+ // Get all option elements from the light DOM
86
+ const options = Array.from(this.querySelectorAll('option, paper-item'));
87
+ options.forEach(option => {
88
+ const newOption = document.createElement('option');
89
+ newOption.value = option.value || option.getAttribute('value');
90
+ newOption.textContent = option.textContent;
91
+ select.appendChild(newOption);
92
+ });
93
+
94
+ // Set the selected value
95
+ if (this.selected) {
96
+ select.value = this.selected;
97
+ }
83
98
  }
84
99
 
85
- _changed() {
86
- const lang = this.shadowRoot.getElementById('menu').selected;
100
+ _changed(e) {
101
+ const lang = e.target.value;
87
102
  if (lang !== this.selected) {
88
103
  console.log('<pb-lang> Language changed to %s', lang);
89
104
  this.emitTo('pb-i18n-language', { 'language': lang });
package/src/pb-login.js CHANGED
@@ -3,12 +3,9 @@ import { pbMixin, waitOnce } from './pb-mixin.js';
3
3
  import { translate } from "./pb-i18n.js";
4
4
  import { registry } from "./urls.js";
5
5
  import '@polymer/iron-ajax';
6
- import '@polymer/paper-dialog';
7
- import '@polymer/paper-dialog-scrollable';
8
- import '@polymer/paper-input/paper-input.js';
9
- import '@polymer/paper-button';
10
- import '@polymer/iron-icons';
11
6
  import { minVersion } from './utils.js';
7
+ import './pb-dialog.js';
8
+ import { themableMixin } from './theming.js';
12
9
 
13
10
  /**
14
11
  * Handles login/logout. Shows a link which opens a login dialog if clicked.
@@ -20,7 +17,7 @@ import { minVersion } from './utils.js';
20
17
  * @csspart message-invalid - Block displayed if login is invalid
21
18
  * @csspart group-invalid - Text displayed if login is invalid concerning group
22
19
  */
23
- export class PbLogin extends pbMixin(LitElement) {
20
+ export class PbLogin extends themableMixin(pbMixin(LitElement)) {
24
21
  static get properties() {
25
22
  return {
26
23
  ...super.properties,
@@ -107,7 +104,12 @@ export class PbLogin extends pbMixin(LitElement) {
107
104
  firstUpdated() {
108
105
  super.firstUpdated();
109
106
  this._checkLogin = this.shadowRoot.getElementById('checkLogin');
110
- this._loginDialog = this.shadowRoot.getElementById('loginDialog');
107
+ this._loginDialog = this.shadowRoot.querySelector('pb-dialog');
108
+
109
+ this.renderRoot.querySelector('form').addEventListener('submit', (e) => {
110
+ e.preventDefault();
111
+ this._confirmLogin();
112
+ });
111
113
 
112
114
  window.addEventListener('blur', () => {
113
115
  this._hasFocus = false;
@@ -141,34 +143,44 @@ export class PbLogin extends pbMixin(LitElement) {
141
143
 
142
144
  render() {
143
145
  return html`
144
- <a href="#" @click="${this._show}" role="button" title="${this.user ? this.user : this.loginLabel}">
146
+ <a href="#" @click="${this._show}" title="${this.user ? this.user : this.loginLabel}" part="trigger">
145
147
  ${
146
- this.loggedIn ?
147
- html`<iron-icon icon="${this.logoutIcon}"></iron-icon> <span class="label">${translate(this.logoutLabel, { user: this.user })}</span>` :
148
- html`<iron-icon icon="${this.loginIcon}"></iron-icon> <span class="label">${translate(this.loginLabel)}</span>`
149
- }
148
+ this.loggedIn ?
149
+ html`
150
+ <slot name="icon-login">
151
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person" viewBox="0 0 16 16" part="icon">
152
+ <path d="M8 8a3 3 0 1 0 0-6 3 3 0 0 0 0 6m2-3a2 2 0 1 1-4 0 2 2 0 0 1 4 0m4 8c0 1-1 1-1 1H3s-1 0-1-1 1-4 6-4 6 3 6 4m-1-.004c-.001-.246-.154-.986-.832-1.664C11.516 10.68 10.289 10 8 10s-3.516.68-4.168 1.332c-.678.678-.83 1.418-.832 1.664z"/>
153
+ </svg>
154
+ </slot>
155
+ ` :
156
+ html`
157
+ <slot name="icon-logout" part="icon">
158
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person-check" viewBox="0 0 16 16" part="icon">
159
+ <path d="M12.5 16a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7m1.679-4.493-1.335 2.226a.75.75 0 0 1-1.174.144l-.774-.773a.5.5 0 0 1 .708-.708l.547.548 1.17-1.951a.5.5 0 1 1 .858.514M11 5a3 3 0 1 1-6 0 3 3 0 0 1 6 0M8 7a2 2 0 1 0 0-4 2 2 0 0 0 0 4"/>
160
+ <path d="M8.256 14a4.5 4.5 0 0 1-.229-1.004H3c.001-.246.154-.986.832-1.664C4.484 10.68 5.711 10 8 10q.39 0 .74.025c.226-.341.496-.65.804-.918Q8.844 9.002 8 9c-5 0-6 3-6 4s1 1 1 1z"/>
161
+ </svg>
162
+ </slot>
163
+ `
164
+ }
165
+ <span class="label" part="label">${translate(this.loggedIn ? this.logoutLabel : this.loginLabel, { user: this.user })}</span>
150
166
  </a>
151
167
 
152
- <paper-dialog id="loginDialog" ?modal="${this.auto}">
153
- <h2>${translate('login.login')}</h2>
154
- <paper-dialog-scrollable>
155
- <form action="login">
156
- <paper-input id="user" name="user" label="${translate('login.user')}" value="${this.user}" autofocus></paper-input>
157
- <paper-input id="password" name="password" label="${translate('login.password')}" type="password"></paper-input>
158
- <input id="logout" type="hidden" name="logout"></input>
159
- </form>
168
+ <form action="login">
169
+ <pb-dialog ?modal="${this.auto}">
170
+ <div slot="title">${translate('login.login')}</div>
171
+ <label>
172
+ ${ translate('login.user') }
173
+ <input name="user" value="${this.user}" autofocus placeholder="${translate('login.user')}"></input>
174
+ </label>
175
+ <label>
176
+ ${ translate('login.password') }
177
+ <input name="password" type="password" placeholder="${translate('login.password')}"></input>
178
+ </label>
160
179
  <slot name="information"></slot>
161
- ${this._invalid ?
162
- html`
163
- <p id="message" part="message-invalid">${translate('login.invalid')}<span part="group-invalid">${this.group ? html` (${translate('login.requiredGroup', { group: this.group })})` : null}</span>.
164
- </p>
165
- `: null
166
- }
167
- </paper-dialog-scrollable>
168
- <div class="buttons">
169
- <paper-button autofocus @click="${this._confirmLogin}">${translate(this.loginLabel)}</paper-button>
170
- </div>
171
- </paper-dialog>
180
+ ${ this._invalid ? html`<p id="message" part="message-invalid">${translate('login.invalid')}<span part="group-invalid">${this.group ? html` (${translate('login.requiredGroup', { group: this.group })})` : null}</span>.</p>` : null }
181
+ <button autofocus slot="footer">${translate('login.login')}</button>
182
+ </pb-dialog>
183
+ </form>
172
184
 
173
185
  <iron-ajax id="checkLogin" with-credentials
174
186
  handle-as="json" @response="${this._handleResponse}" @error="${this._handleError}"
@@ -177,38 +189,6 @@ export class PbLogin extends pbMixin(LitElement) {
177
189
  `;
178
190
  }
179
191
 
180
- static get styles() {
181
- return css`
182
- :host {
183
- display: block;
184
- }
185
-
186
- paper-dialog {
187
- min-width: 320px;
188
- max-width: 640px;
189
- min-height: 128px;
190
- }
191
-
192
- paper-dialog h2 {
193
- background-color: #607D8B;
194
- padding: 16px 8px;
195
- margin-top: 0;
196
- color: #F0F0F0;
197
- }
198
-
199
- a {
200
- color: var(--pb-login-link-color, --pb-link-color);
201
- text-decoration: none;
202
- display: flex;
203
- gap:0.5rem;
204
- }
205
-
206
- #message {
207
- color: var(--paper-red-800);
208
- }
209
- `;
210
- }
211
-
212
192
  _show(ev) {
213
193
  ev.preventDefault();
214
194
  if (this.loggedIn) {
@@ -217,13 +197,13 @@ export class PbLogin extends pbMixin(LitElement) {
217
197
  };
218
198
  this._checkLogin.generateRequest();
219
199
  } else {
220
- this._loginDialog.open();
200
+ this._loginDialog.openDialog();
221
201
  }
222
202
  }
223
203
 
224
204
  _confirmLogin() {
225
- this.user = this.shadowRoot.getElementById('user').value;
226
- this.password = this.shadowRoot.getElementById('password').value;
205
+ this.user = this.renderRoot.querySelector('input[name="user"]').value;
206
+ this.password = this.renderRoot.querySelector('input[name="password"]').value;
227
207
  this._checkLogin.body = {
228
208
  user: this.user,
229
209
  password: this.password
@@ -239,15 +219,15 @@ export class PbLogin extends pbMixin(LitElement) {
239
219
  this.user = resp.user;
240
220
  this.groups = resp.groups;
241
221
  this._invalid = false;
242
- this._loginDialog.close();
222
+ this._loginDialog.closeDialog();
243
223
  } else {
244
224
  resp.userChanged = this.loggedIn;
245
225
  this.loggedIn = false;
246
226
  this.password = null;
247
- if (this._loginDialog.opened) {
227
+ if (this._loginDialog.open) {
248
228
  this._invalid = true;
249
229
  } else if (this.auto) {
250
- this._loginDialog.open();
230
+ this._loginDialog.openDialog();
251
231
  }
252
232
  }
253
233
  this.emitTo('pb-login', resp);
@@ -270,10 +250,10 @@ export class PbLogin extends pbMixin(LitElement) {
270
250
  userChanged: this.loggedIn,
271
251
  user: null
272
252
  };
273
- if (this._loginDialog.opened) {
253
+ if (this._loginDialog.open) {
274
254
  this._invalid = true;
275
255
  } else if (this.auto) {
276
- this._loginDialog.open();
256
+ this._loginDialog.openDialog();
277
257
  }
278
258
 
279
259
  registry.currentUser = null;
@@ -309,6 +289,14 @@ export class PbLogin extends pbMixin(LitElement) {
309
289
  return true;
310
290
  }
311
291
 
292
+ static get styles() {
293
+ return css`
294
+ #message {
295
+ color: var(--pb-login-message-invalid-color, var(--pb-error-color, #f44336));
296
+ }
297
+ `;
298
+ }
299
+
312
300
  /**
313
301
  * Fired on successful login.
314
302
  *