@teipublisher/pb-components 2.25.3 → 2.26.0

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.
@@ -3254,6 +3254,125 @@
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 (no shadow DOM).",
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": "subscribe",
3274
+ "description": "The name of the channel to subscribe to. Only events on a channel corresponding\nto this property are listened to.",
3275
+ "type": "string"
3276
+ },
3277
+ {
3278
+ "name": "subscribe-config",
3279
+ "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.",
3280
+ "type": "object"
3281
+ },
3282
+ {
3283
+ "name": "emit",
3284
+ "description": "The name of the channel to send events to.",
3285
+ "type": "string"
3286
+ },
3287
+ {
3288
+ "name": "emit-config",
3289
+ "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.",
3290
+ "type": "object"
3291
+ },
3292
+ {
3293
+ "name": "wait-for",
3294
+ "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.",
3295
+ "type": "string"
3296
+ },
3297
+ {
3298
+ "name": "disabled",
3299
+ "description": "Common property to disable the functionality associated with a component.\n`pb-highlight` and `pb-popover` react to this.",
3300
+ "type": "boolean",
3301
+ "default": "false"
3302
+ }
3303
+ ],
3304
+ "properties": [
3305
+ {
3306
+ "name": "open",
3307
+ "attribute": "open",
3308
+ "type": "boolean",
3309
+ "default": "false"
3310
+ },
3311
+ {
3312
+ "name": "modal",
3313
+ "attribute": "modal",
3314
+ "type": "boolean",
3315
+ "default": "true"
3316
+ },
3317
+ {
3318
+ "name": "subscribe",
3319
+ "attribute": "subscribe",
3320
+ "description": "The name of the channel to subscribe to. Only events on a channel corresponding\nto this property are listened to.",
3321
+ "type": "string"
3322
+ },
3323
+ {
3324
+ "name": "subscribeConfig",
3325
+ "attribute": "subscribe-config",
3326
+ "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.",
3327
+ "type": "object"
3328
+ },
3329
+ {
3330
+ "name": "emit",
3331
+ "attribute": "emit",
3332
+ "description": "The name of the channel to send events to.",
3333
+ "type": "string"
3334
+ },
3335
+ {
3336
+ "name": "emitConfig",
3337
+ "attribute": "emit-config",
3338
+ "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.",
3339
+ "type": "object"
3340
+ },
3341
+ {
3342
+ "name": "waitFor",
3343
+ "attribute": "wait-for",
3344
+ "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.",
3345
+ "type": "string"
3346
+ },
3347
+ {
3348
+ "name": "disabled",
3349
+ "attribute": "disabled",
3350
+ "description": "Common property to disable the functionality associated with a component.\n`pb-highlight` and `pb-popover` react to this.",
3351
+ "type": "boolean",
3352
+ "default": "false"
3353
+ }
3354
+ ],
3355
+ "events": [
3356
+ {
3357
+ "name": "pb-dialog-opened",
3358
+ "description": "Fired when the dialog is opened"
3359
+ },
3360
+ {
3361
+ "name": "pb-dialog-closed",
3362
+ "description": "Fired when the dialog is closed"
3363
+ }
3364
+ ],
3365
+ "slots": [
3366
+ {
3367
+ "name": "",
3368
+ "description": "Content of the dialog"
3369
+ },
3370
+ {
3371
+ "name": "title",
3372
+ "description": "Title of the dialog"
3373
+ }
3374
+ ]
3375
+ },
3257
3376
  {
3258
3377
  "name": "pb-document",
3259
3378
  "path": "./src/pb-document.js",
@@ -5494,17 +5613,7 @@
5494
5613
  "slots": [
5495
5614
  {
5496
5615
  "name": "",
5497
- "description": "unnamed default slot for dropdown menu options"
5498
- }
5499
- ],
5500
- "cssProperties": [
5501
- {
5502
- "name": "--pb-lang-input-color",
5503
- "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"
5616
+ "description": "unnamed default slot for dropdown menu options given as <option> elements"
5508
5617
  }
5509
5618
  ]
5510
5619
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teipublisher/pb-components",
3
- "version": "2.25.3",
3
+ "version": "2.26.0",
4
4
  "description": "Collection of webcomponents underlying TEI Publisher",
5
5
  "repository": "https://github.com/eeditiones/tei-publisher-components.git",
6
6
  "main": "index.html",
package/pb-elements.json CHANGED
@@ -3254,6 +3254,125 @@
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 (no shadow DOM).",
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": "subscribe",
3274
+ "description": "The name of the channel to subscribe to. Only events on a channel corresponding\nto this property are listened to.",
3275
+ "type": "string"
3276
+ },
3277
+ {
3278
+ "name": "subscribe-config",
3279
+ "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.",
3280
+ "type": "object"
3281
+ },
3282
+ {
3283
+ "name": "emit",
3284
+ "description": "The name of the channel to send events to.",
3285
+ "type": "string"
3286
+ },
3287
+ {
3288
+ "name": "emit-config",
3289
+ "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.",
3290
+ "type": "object"
3291
+ },
3292
+ {
3293
+ "name": "wait-for",
3294
+ "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.",
3295
+ "type": "string"
3296
+ },
3297
+ {
3298
+ "name": "disabled",
3299
+ "description": "Common property to disable the functionality associated with a component.\n`pb-highlight` and `pb-popover` react to this.",
3300
+ "type": "boolean",
3301
+ "default": "false"
3302
+ }
3303
+ ],
3304
+ "properties": [
3305
+ {
3306
+ "name": "open",
3307
+ "attribute": "open",
3308
+ "type": "boolean",
3309
+ "default": "false"
3310
+ },
3311
+ {
3312
+ "name": "modal",
3313
+ "attribute": "modal",
3314
+ "type": "boolean",
3315
+ "default": "true"
3316
+ },
3317
+ {
3318
+ "name": "subscribe",
3319
+ "attribute": "subscribe",
3320
+ "description": "The name of the channel to subscribe to. Only events on a channel corresponding\nto this property are listened to.",
3321
+ "type": "string"
3322
+ },
3323
+ {
3324
+ "name": "subscribeConfig",
3325
+ "attribute": "subscribe-config",
3326
+ "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.",
3327
+ "type": "object"
3328
+ },
3329
+ {
3330
+ "name": "emit",
3331
+ "attribute": "emit",
3332
+ "description": "The name of the channel to send events to.",
3333
+ "type": "string"
3334
+ },
3335
+ {
3336
+ "name": "emitConfig",
3337
+ "attribute": "emit-config",
3338
+ "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.",
3339
+ "type": "object"
3340
+ },
3341
+ {
3342
+ "name": "waitFor",
3343
+ "attribute": "wait-for",
3344
+ "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.",
3345
+ "type": "string"
3346
+ },
3347
+ {
3348
+ "name": "disabled",
3349
+ "attribute": "disabled",
3350
+ "description": "Common property to disable the functionality associated with a component.\n`pb-highlight` and `pb-popover` react to this.",
3351
+ "type": "boolean",
3352
+ "default": "false"
3353
+ }
3354
+ ],
3355
+ "events": [
3356
+ {
3357
+ "name": "pb-dialog-opened",
3358
+ "description": "Fired when the dialog is opened"
3359
+ },
3360
+ {
3361
+ "name": "pb-dialog-closed",
3362
+ "description": "Fired when the dialog is closed"
3363
+ }
3364
+ ],
3365
+ "slots": [
3366
+ {
3367
+ "name": "",
3368
+ "description": "Content of the dialog"
3369
+ },
3370
+ {
3371
+ "name": "title",
3372
+ "description": "Title of the dialog"
3373
+ }
3374
+ ]
3375
+ },
3257
3376
  {
3258
3377
  "name": "pb-document",
3259
3378
  "path": "./src/pb-document.js",
@@ -5494,17 +5613,7 @@
5494
5613
  "slots": [
5495
5614
  {
5496
5615
  "name": "",
5497
- "description": "unnamed default slot for dropdown menu options"
5498
- }
5499
- ],
5500
- "cssProperties": [
5501
- {
5502
- "name": "--pb-lang-input-color",
5503
- "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"
5616
+ "description": "unnamed default slot for dropdown menu options given as <option> elements"
5508
5617
  }
5509
5618
  ]
5510
5619
  },
@@ -0,0 +1,51 @@
1
+ :root {
2
+ --pb-dialog-box-shadow: 0 2px 16px rgba(0, 0, 0, 0.3);
3
+ --pb-dialog-backdrop-color: rgba(0, 0, 0, 0.4);
4
+ --pb-dialog-padding-horizontal: 1em;
5
+ --pb-dialog-padding-vertical: 1em;
6
+ --pb-dialog-border-color: #eee;
7
+ --pb-dialog-min-width: 300px;
8
+ }
9
+
10
+ pb-dialog dialog {
11
+ min-width: var(--pb-dialog-min-width);
12
+ max-width: 100vw;
13
+ max-height: 90vh;
14
+ border-radius: 6px;
15
+ box-shadow: var(--pb-dialog-box-shadow);
16
+ border: none;
17
+ padding: 0;
18
+ }
19
+
20
+ pb-dialog dialog::backdrop {
21
+ background: var(--pb-dialog-backdrop-color);
22
+ }
23
+
24
+ pb-dialog>dialog>article>* {
25
+ padding-left: var(--pb-dialog-padding-horizontal);
26
+ padding-right: var(--pb-dialog-padding-horizontal);
27
+ }
28
+
29
+ pb-dialog>dialog>article>header {
30
+ border-bottom: 1px solid var(--pb-dialog-border-color);
31
+ display: flex;
32
+ margin-bottom: var(--pb-dialog-padding-vertical);
33
+ justify-content: space-between;
34
+ align-items: center;
35
+ }
36
+
37
+ pb-dialog>dialog>article>footer {
38
+ display: flex;
39
+ justify-content: flex-end;
40
+ gap: 0.5rem;
41
+ padding-top: var(--pb-dialog-padding-vertical);
42
+ padding-bottom: var(--pb-dialog-padding-vertical);
43
+ border-top: 1px solid var(--pb-dialog-border-color);
44
+ }
45
+
46
+ pb-dialog [rel="prev"] {
47
+ background: none;
48
+ border: none;
49
+ font-size: 1.2em;
50
+ cursor: pointer;
51
+ }
@@ -0,0 +1,78 @@
1
+ import { LitElement, html } from 'lit-element';
2
+ import { pbMixin } from './pb-mixin';
3
+ import { pbLightDom } from './pb-light-dom';
4
+
5
+ /**
6
+ * A simple dialog component using the HTML5 <dialog> element (no shadow DOM).
7
+ *
8
+ * @slot - Content of the dialog
9
+ * @slot title - Title of the dialog
10
+ * @fires pb-dialog-opened - Fired when the dialog is opened
11
+ * @fires pb-dialog-closed - Fired when the dialog is closed
12
+ */
13
+ export class PbDialog extends pbLightDom(pbMixin(LitElement)) {
14
+
15
+ static get properties() {
16
+ return {
17
+ ...super.properties,
18
+ open: { type: Boolean, reflect: true },
19
+ modal: { type: Boolean, reflect: true }
20
+ };
21
+ }
22
+
23
+ constructor() {
24
+ super();
25
+ this.open = false;
26
+ this.modal = true;
27
+ this._escListener = this._onEsc.bind(this);
28
+ }
29
+
30
+ _onEsc(e) {
31
+ if (e.key === 'Escape' && this.open) {
32
+ this.closeDialog();
33
+ }
34
+ }
35
+
36
+ openDialog() {
37
+ if (!this.open) {
38
+ if (this.modal) {
39
+ this._dialog.showModal();
40
+ } else {
41
+ this._dialog.show();
42
+ }
43
+ this.dispatchEvent(new CustomEvent('pb-dialog-opened', { bubbles: true, composed: true }));
44
+ this.open = true;
45
+ }
46
+ }
47
+
48
+ closeDialog() {
49
+ if (this.open) {
50
+ this._dialog.close();
51
+ this.dispatchEvent(new CustomEvent('pb-dialog-closed', { bubbles: true, composed: true }));
52
+ this.open = false;
53
+ }
54
+ }
55
+
56
+ render() {
57
+ return html`
58
+ <dialog @click="${(e) => e.target === this._dialog && this.modal && this.closeDialog()}" ?modal="${this.modal}">
59
+ <article>
60
+ <header>
61
+ ${ this.fillSlot('title') }
62
+ <button rel="prev" aria-label="Close" @click="${this.closeDialog}">&times;</button>
63
+ </header>
64
+ ${ this.fillSlot() }
65
+ <footer>
66
+ ${ this.fillSlot('footer') }
67
+ </footer>
68
+ </article>
69
+ </dialog>
70
+ `;
71
+ }
72
+
73
+ firstUpdated() {
74
+ this._dialog = this.querySelector('dialog');
75
+ }
76
+ }
77
+
78
+ customElements.define('pb-dialog', PbDialog);
package/src/pb-lang.js CHANGED
@@ -1,19 +1,17 @@
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 { pbLightDom } from './pb-light-dom.js';
6
5
 
7
6
  /**
8
7
  * A dropdown for switching the interface language.
9
8
  *
10
- * @slot - unnamed default slot for dropdown menu options
9
+ * @slot - unnamed default slot for dropdown menu options given as <option> elements
11
10
  * @fires pb-i18n-language - Sends selected language
12
11
  * @fires pb-i18n-update - When received, sets the selected language to the one received from the event
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
12
  */
16
- export class PbLang extends pbMixin(LitElement) {
13
+ export class PbLang extends pbLightDom(pbMixin(LitElement)) {
14
+
17
15
  static get properties() {
18
16
  return {
19
17
  ...super.properties,
@@ -52,38 +50,25 @@ export class PbLang extends pbMixin(LitElement) {
52
50
  }
53
51
 
54
52
  render() {
53
+ const slotted = this.fillSlot();
55
54
  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>`
55
+ <select name="select" @change="${this._changed}" aria-label="${this.nolabel ? this.selected : translate(this.label)}">
56
+ ${
57
+ slotted.map(option => {
58
+ if (option instanceof HTMLElement) {
59
+ return html`
60
+ <option value="${option.getAttribute('value')}" ?selected=${option.getAttribute('value') === this.selected}>${option.textContent}</option>
61
+ `;
62
+ }
63
+ return '';
64
+ })
71
65
  }
66
+ </select>
72
67
  `;
73
68
  }
74
69
 
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
- `;
83
- }
84
-
85
- _changed() {
86
- const lang = this.shadowRoot.getElementById('menu').selected;
70
+ _changed(e) {
71
+ const lang = e.target.value;
87
72
  if (lang !== this.selected) {
88
73
  console.log('<pb-lang> Language changed to %s', lang);
89
74
  this.emitTo('pb-i18n-language', { 'language': lang });
@@ -0,0 +1,40 @@
1
+ export const pbLightDom = (superclass) => class PbLightDom extends superclass {
2
+
3
+ createRenderRoot() {
4
+ // Render in light DOM
5
+ return this;
6
+ }
7
+
8
+ connectedCallback() {
9
+ super.connectedCallback();
10
+ this._content = document.createElement('div');
11
+ this._content.innerHTML = this.innerHTML;
12
+ console.log(this._content);
13
+ }
14
+
15
+ /**
16
+ * When the class is used without shadow DOM, use this method to find elements which should be
17
+ * rendered in the slot.
18
+ *
19
+ * @param {string|undefined|null} slotName - name of the slot to fill, if its a named slot
20
+ * @returns {Array<Node>} an array of cloned nodes
21
+ */
22
+ fillSlot(slotName = null, fallback = []) {
23
+ if (!slotName) {
24
+ const slots = this._content.querySelectorAll(':scope > :not([slot])');
25
+ return Array.from(slots).map(node => {
26
+ const clone = node.cloneNode(true);
27
+ /** @type {Element} */ (clone).removeAttribute('slot');
28
+ return clone;
29
+ });
30
+ } else {
31
+ const slot = this._content.querySelector(`:scope > [slot="${slotName}"]`);
32
+ if (slot) {
33
+ const clone = slot.cloneNode(true);
34
+ /** @type {Element} */ (clone).removeAttribute('slot');
35
+ return [clone];
36
+ }
37
+ return fallback;
38
+ }
39
+ }
40
+ };