@teipublisher/pb-components 2.26.0-next-3.11 → 2.26.0-next-3.13

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 (133) hide show
  1. package/.github/workflows/main.yml +3 -3
  2. package/.github/workflows/node.js.yml +3 -3
  3. package/.github/workflows/release.js.yml +3 -3
  4. package/CHANGELOG.md +38 -0
  5. package/Dockerfile +78 -70
  6. package/css/components.css +5 -5
  7. package/dist/demo/components.css +2 -8
  8. package/dist/demo/pb-drawer2.html +1 -1
  9. package/dist/demo/pb-leaflet-map.html +1 -1
  10. package/dist/demo/pb-progress.html +2 -2
  11. package/dist/demo/pb-repeat.html +1 -3
  12. package/dist/demo/pb-view3.html +1 -1
  13. package/dist/{paper-icon-button-0fb125c4.js → paper-icon-button-72125e67.js} +1 -1
  14. package/dist/pb-code-editor.js +25 -20
  15. package/dist/pb-component-docs.js +58 -54
  16. package/dist/pb-components-bundle.js +1937 -1782
  17. package/dist/pb-edit-app.js +167 -107
  18. package/dist/pb-elements.json +45 -45
  19. package/dist/{pb-i18n-0611135a.js → pb-i18n-4cc00bfe.js} +1 -1
  20. package/dist/pb-leaflet-map.js +23 -23
  21. package/dist/pb-mei.js +56 -41
  22. package/dist/{pb-mixin-b1caa22e.js → pb-mixin-886ece32.js} +1 -1
  23. package/dist/pb-odd-editor.js +923 -756
  24. package/dist/pb-tify.js +2 -2
  25. package/dist/{vaadin-element-mixin-6633322b.js → vaadin-element-mixin-84fb7d82.js} +181 -143
  26. package/gh-pages.js +5 -3
  27. package/i18n/common/pl.json +2 -2
  28. package/lib/openseadragon.min.js +1 -1
  29. package/package.json +2 -2
  30. package/pb-elements.json +45 -45
  31. package/src/assets/components.css +5 -5
  32. package/src/authority/airtable.js +20 -21
  33. package/src/authority/anton.js +129 -129
  34. package/src/authority/custom.js +23 -21
  35. package/src/authority/geonames.js +38 -32
  36. package/src/authority/gnd.js +47 -42
  37. package/src/authority/kbga.js +137 -134
  38. package/src/authority/metagrid.js +44 -46
  39. package/src/authority/reconciliation.js +66 -67
  40. package/src/authority/registry.js +4 -4
  41. package/src/docs/pb-component-docs.js +2 -2
  42. package/src/docs/pb-component-view.js +5 -5
  43. package/src/docs/pb-components-list.js +2 -2
  44. package/src/docs/pb-demo-snippet.js +2 -2
  45. package/src/dts-client.js +299 -297
  46. package/src/dts-select-endpoint.js +90 -82
  47. package/src/parse-date-service.js +184 -135
  48. package/src/pb-ajax.js +150 -146
  49. package/src/pb-authority-lookup.js +183 -146
  50. package/src/pb-autocomplete.js +292 -280
  51. package/src/pb-blacklab-highlight.js +264 -259
  52. package/src/pb-blacklab-results.js +236 -221
  53. package/src/pb-browse-docs.js +540 -475
  54. package/src/pb-browse.js +68 -65
  55. package/src/pb-clipboard.js +79 -76
  56. package/src/pb-code-editor.js +110 -102
  57. package/src/pb-code-highlight.js +209 -204
  58. package/src/pb-codepen.js +79 -72
  59. package/src/pb-collapse.js +212 -207
  60. package/src/pb-combo-box.js +190 -190
  61. package/src/pb-components-bundle.js +1 -1
  62. package/src/pb-custom-form.js +151 -149
  63. package/src/pb-dialog.js +96 -60
  64. package/src/pb-document.js +89 -90
  65. package/src/pb-download.js +210 -198
  66. package/src/pb-drawer.js +145 -148
  67. package/src/pb-edit-app.js +301 -229
  68. package/src/pb-edit-xml.js +98 -96
  69. package/src/pb-events.js +114 -107
  70. package/src/pb-facs-link.js +104 -102
  71. package/src/pb-facsimile.js +411 -413
  72. package/src/pb-formula.js +151 -153
  73. package/src/pb-geolocation.js +129 -131
  74. package/src/pb-grid-action.js +53 -56
  75. package/src/pb-grid.js +231 -228
  76. package/src/pb-highlight.js +140 -140
  77. package/src/pb-hotkeys.js +40 -42
  78. package/src/pb-i18n.js +101 -104
  79. package/src/pb-image-strip.js +84 -78
  80. package/src/pb-lang.js +132 -128
  81. package/src/pb-leaflet-map.js +488 -485
  82. package/src/pb-link.js +126 -124
  83. package/src/pb-load.js +431 -426
  84. package/src/pb-login.js +291 -248
  85. package/src/pb-manage-odds.js +364 -318
  86. package/src/pb-map-icon.js +89 -89
  87. package/src/pb-map-layer.js +85 -85
  88. package/src/pb-markdown.js +90 -99
  89. package/src/pb-media-query.js +74 -72
  90. package/src/pb-mei.js +306 -295
  91. package/src/pb-message.js +144 -144
  92. package/src/pb-mixin.js +269 -264
  93. package/src/pb-navigation.js +80 -82
  94. package/src/pb-observable.js +38 -38
  95. package/src/pb-odd-editor.js +1053 -955
  96. package/src/pb-odd-elementspec-editor.js +348 -297
  97. package/src/pb-odd-model-editor.js +1061 -901
  98. package/src/pb-odd-parameter-editor.js +200 -178
  99. package/src/pb-odd-rendition-editor.js +136 -124
  100. package/src/pb-page.js +431 -421
  101. package/src/pb-paginate.js +202 -190
  102. package/src/pb-panel.js +191 -179
  103. package/src/pb-popover-themes.js +7 -5
  104. package/src/pb-popover.js +296 -287
  105. package/src/pb-print-preview.js +127 -127
  106. package/src/pb-progress.js +51 -51
  107. package/src/pb-repeat.js +105 -104
  108. package/src/pb-restricted.js +84 -77
  109. package/src/pb-search.js +252 -241
  110. package/src/pb-select-feature.js +127 -120
  111. package/src/pb-select-odd.js +132 -124
  112. package/src/pb-select-template.js +89 -78
  113. package/src/pb-select.js +251 -227
  114. package/src/pb-split-list.js +179 -174
  115. package/src/pb-svg.js +80 -79
  116. package/src/pb-table-column.js +54 -54
  117. package/src/pb-table-grid.js +221 -203
  118. package/src/pb-tabs.js +61 -63
  119. package/src/pb-tify.js +154 -154
  120. package/src/pb-timeline.js +271 -229
  121. package/src/pb-toggle-feature.js +182 -175
  122. package/src/pb-upload.js +184 -174
  123. package/src/pb-version.js +30 -30
  124. package/src/pb-view-annotate.js +132 -98
  125. package/src/pb-view.js +1289 -1270
  126. package/src/pb-zoom.js +75 -59
  127. package/src/polymer-hack.js +1 -1
  128. package/src/search-result-service.js +256 -223
  129. package/src/seed-element.js +13 -20
  130. package/src/settings.js +4 -4
  131. package/src/theming.js +96 -96
  132. package/src/urls.js +289 -289
  133. package/src/utils.js +53 -51
@@ -19,159 +19,161 @@ import { PbLoad } from './pb-load.js';
19
19
  * @fires pb-submit - Fired when the form is submitted
20
20
  */
21
21
  export class PbCustomForm extends PbLoad {
22
-
23
- firstUpdated() {
24
- this.shadowRoot.getElementById('ironform').addEventListener('iron-form-presubmit', (ev) => {
25
- ev.preventDefault();
26
- this._submit();
27
- });
28
- this.addEventListener('click', (e) => {
29
- if (e.target.slot === 'searchButtonTop'){
30
- this.submit();
31
- }
32
- if (e.target.slot === 'searchButtonBottom'){
33
- this.submit();
34
- }
35
- if (e.target.slot === 'resetButton'){
36
- this._reset();
37
- }
38
- });
39
-
40
- this._submissionHandlers();
22
+ firstUpdated() {
23
+ this.shadowRoot.getElementById('ironform').addEventListener('iron-form-presubmit', ev => {
24
+ ev.preventDefault();
25
+ this._submit();
26
+ });
27
+ this.addEventListener('click', e => {
28
+ if (e.target.slot === 'searchButtonTop') {
29
+ this.submit();
30
+ }
31
+ if (e.target.slot === 'searchButtonBottom') {
32
+ this.submit();
33
+ }
34
+ if (e.target.slot === 'resetButton') {
35
+ this._reset();
36
+ }
37
+ });
38
+
39
+ this._submissionHandlers();
40
+ }
41
+
42
+ render() {
43
+ return html`
44
+ <iron-form id="ironform">
45
+ <form action="" accept="text/html" method="GET">
46
+ <slot name="searchButtonTop"></slot>
47
+ <slot></slot>
48
+ <slot name="searchButtonBottom"></slot>
49
+ <slot name="resetButton"></slot>
50
+ </form>
51
+ </iron-form>
52
+
53
+ <iron-ajax
54
+ id="loadContent"
55
+ verbose
56
+ handle-as="text"
57
+ method="get"
58
+ with-credentials
59
+ @response="${this._handleContent}"
60
+ @error="${this._handleError}"
61
+ ></iron-ajax>
62
+ <paper-dialog id="errorDialog">
63
+ <h2>Error</h2>
64
+ <paper-dialog-scrollable></paper-dialog-scrollable>
65
+ <div class="buttons">
66
+ <paper-button dialog-confirm="dialog-confirm" autofocus="autofocus"> Close </paper-button>
67
+ </div>
68
+ </paper-dialog>
69
+ `;
70
+ }
71
+
72
+ static get styles() {
73
+ return css`
74
+ :host {
75
+ display: block;
76
+ }
77
+ `;
78
+ }
79
+
80
+ submit() {
81
+ this.shadowRoot.getElementById('ironform').submit();
82
+ }
83
+
84
+ _submit() {
85
+ const json = this.serializeForm();
86
+ this.emitTo('pb-search-resubmit', { params: json });
87
+ this.emitTo('pb-submit', { params: json });
88
+ }
89
+
90
+ _reset() {
91
+ this.shadowRoot.getElementById('ironform').reset();
92
+ }
93
+
94
+ /**
95
+ * serialize custom form to object with name value pairs
96
+ * empty, unselected and undifined inputs will be returned
97
+ * as null while disabled elements will still be omitted
98
+ * this allows url parameters to be reset in the URL
99
+ * as IronForm.serializeform will omit names without a value
100
+ * @returns {Object} name value pairs
101
+ */
102
+ serializeForm() {
103
+ const elements = this.shadowRoot.getElementById('ironform')._getSubmittableElements();
104
+ const initial = {};
105
+ for (const element of elements) {
106
+ initial[element.name] = null;
41
107
  }
108
+ return Object.assign(initial, this.shadowRoot.getElementById('ironform').serializeForm());
109
+ }
42
110
 
43
- render() {
44
- return html`
45
- <iron-form id="ironform">
46
- <form action="" accept="text/html" method="GET">
47
- <slot name="searchButtonTop"></slot>
48
- <slot></slot>
49
- <slot name="searchButtonBottom"></slot>
50
- <slot name="resetButton"></slot>
51
- </form>
52
- </iron-form>
53
-
54
- <iron-ajax
55
- id="loadContent"
56
- verbose
57
- handle-as="text"
58
- method="get"
59
- with-credentials
60
- @response="${this._handleContent}"
61
- @error="${this._handleError}"></iron-ajax>
62
- <paper-dialog id="errorDialog">
63
- <h2>Error</h2>
64
- <paper-dialog-scrollable></paper-dialog-scrollable>
65
- <div class="buttons">
66
- <paper-button dialog-confirm="dialog-confirm" autofocus="autofocus">
67
- Close
68
- </paper-button>
69
- </div>
70
- </paper-dialog>
71
- `;
72
- }
111
+ _parseHeaders(xhr) {
112
+ // overwrite to avoid `pb-results-received` event being sent
113
+ }
73
114
 
74
- static get styles() {
75
- return css`
76
- :host {
77
- display: block;
78
- }
79
- `;
80
- }
81
-
82
- submit() {
83
- this.shadowRoot.getElementById('ironform').submit();
84
- }
115
+ _onLoad(content) {
116
+ super._onLoad(content);
85
117
 
86
- _submit() {
87
- const json = this.serializeForm();
88
- this.emitTo('pb-search-resubmit', { params: json });
89
- this.emitTo('pb-submit', { params: json});
90
- }
91
-
92
- _reset(){
93
- this.shadowRoot.getElementById('ironform').reset();
94
- }
95
-
96
- /**
97
- * serialize custom form to object with name value pairs
98
- * empty, unselected and undifined inputs will be returned
99
- * as null while disabled elements will still be omitted
100
- * this allows url parameters to be reset in the URL
101
- * as IronForm.serializeform will omit names without a value
102
- * @returns {Object} name value pairs
103
- */
104
- serializeForm() {
105
- const elements = this.shadowRoot.getElementById('ironform')._getSubmittableElements()
106
- const initial = {}
107
- for (const element of elements) {
108
- initial[element.name] = null;
109
- }
110
- return Object.assign(
111
- initial,
112
- this.shadowRoot.getElementById('ironform').serializeForm()
113
- );
114
- }
118
+ this.dispatchEvent(new CustomEvent('pb-custom-form-loaded', { detail: content }));
119
+ }
115
120
 
116
- _parseHeaders(xhr) {
117
- // overwrite to avoid `pb-results-received` event being sent
121
+ _submissionHandlers() {
122
+ if (!this.autoSubmit) {
123
+ return;
118
124
  }
119
-
120
- _onLoad(content) {
121
- super._onLoad(content);
122
-
123
- this.dispatchEvent(new CustomEvent('pb-custom-form-loaded', { detail: content }));
124
- }
125
-
126
- _submissionHandlers() {
127
- if (!this.autoSubmit) {
128
- return;
129
- }
130
- this.querySelectorAll(this.autoSubmit).forEach((control) => {
131
- const name = control.nodeName.toLowerCase();
132
- let event = 'change';
133
- if (control instanceof HTMLButtonElement ||
134
- name === 'paper-icon-button' || name === 'paper-button' ||
135
- (name === 'input' && (control.type === 'button' || control.type === 'submit' || control.type === 'reset'))
136
- ) {
137
- event = 'click';
138
- } else if (name === 'paper-input' || (control instanceof HTMLInputElement && (control.type === 'text' || control.type === 'search'))) {
139
- event = 'keyup';
140
- } else if (name === 'paper-dropdown-menu') {
141
- event = 'value-changed';
142
- }
143
- control.addEventListener(event, this._submit.bind(this));
144
- });
145
- }
146
-
147
- static get properties() {
148
- return {
149
- /**
150
- * Register event handlers on all descendant elements matching the given CSS selector and submit the form
151
- * automatically if any of those changes. For button-like controls,
152
- * a submit is triggered on click, for text input on keyUp, and for
153
- * all other form components on change.
154
- */
155
- autoSubmit: {
156
- type: String,
157
- attribute: 'auto-submit'
158
- },
159
- ...super.properties
160
- };
161
- }
162
-
163
- /**
164
- * Fired before the element updates its content
165
- *
166
- * @event pb-custom-form-loaded
167
- * @param {string} the loaded content
168
- */
169
-
170
- /**
171
- * Fired when form is submitted
172
- *
173
- * @event pb-search-resubmit
174
- * @param {object} params: serialized form parameters as json object
175
- */
125
+ this.querySelectorAll(this.autoSubmit).forEach(control => {
126
+ const name = control.nodeName.toLowerCase();
127
+ let event = 'change';
128
+ if (
129
+ control instanceof HTMLButtonElement ||
130
+ name === 'paper-icon-button' ||
131
+ name === 'paper-button' ||
132
+ (name === 'input' &&
133
+ (control.type === 'button' || control.type === 'submit' || control.type === 'reset'))
134
+ ) {
135
+ event = 'click';
136
+ } else if (
137
+ name === 'paper-input' ||
138
+ (control instanceof HTMLInputElement &&
139
+ (control.type === 'text' || control.type === 'search'))
140
+ ) {
141
+ event = 'keyup';
142
+ } else if (name === 'paper-dropdown-menu') {
143
+ event = 'value-changed';
144
+ }
145
+ control.addEventListener(event, this._submit.bind(this));
146
+ });
147
+ }
148
+
149
+ static get properties() {
150
+ return {
151
+ /**
152
+ * Register event handlers on all descendant elements matching the given CSS selector and submit the form
153
+ * automatically if any of those changes. For button-like controls,
154
+ * a submit is triggered on click, for text input on keyUp, and for
155
+ * all other form components on change.
156
+ */
157
+ autoSubmit: {
158
+ type: String,
159
+ attribute: 'auto-submit',
160
+ },
161
+ ...super.properties,
162
+ };
163
+ }
164
+
165
+ /**
166
+ * Fired before the element updates its content
167
+ *
168
+ * @event pb-custom-form-loaded
169
+ * @param {string} the loaded content
170
+ */
171
+
172
+ /**
173
+ * Fired when form is submitted
174
+ *
175
+ * @event pb-search-resubmit
176
+ * @param {object} params: serialized form parameters as json object
177
+ */
176
178
  }
177
- customElements.define('pb-custom-form', PbCustomForm);
179
+ customElements.define('pb-custom-form', PbCustomForm);
package/src/pb-dialog.js CHANGED
@@ -1,10 +1,12 @@
1
1
  import { LitElement, css, html } from 'lit-element';
2
- import { pbMixin } from './pb-mixin';
3
2
  import { unsafeHTML } from 'lit-html/directives/unsafe-html';
3
+ import { pbMixin } from './pb-mixin';
4
4
  import { themableMixin } from './theming.js';
5
5
 
6
6
  /**
7
- * A simple dialog component using the HTML5 <dialog> element
7
+ * A simple dialog component using the HTML5 <dialog> element.
8
+ *
9
+ * Any button with the attribute `rel="prev"` will close the dialog when clicked.
8
10
  *
9
11
  * @slot - Content of the dialog
10
12
  * @slot title - Title of the dialog
@@ -12,72 +14,106 @@ import { themableMixin } from './theming.js';
12
14
  * @fires pb-dialog-closed - Fired when the dialog is closed
13
15
  */
14
16
  export class PbDialog extends themableMixin(pbMixin(LitElement)) {
17
+ static get properties() {
18
+ return {
19
+ ...super.properties,
20
+ open: { type: Boolean, reflect: true },
21
+ modal: { type: Boolean, reflect: true },
22
+ title: { type: String, reflect: true },
23
+ message: { type: String, reflect: true },
24
+ };
25
+ }
15
26
 
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
- }
27
+ constructor() {
28
+ super();
29
+ this.open = false;
30
+ this.modal = true;
31
+ this._escListener = this._onEsc.bind(this);
32
+ this.title = null;
33
+ this.message = null;
34
+ }
25
35
 
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;
36
+ _onEsc(e) {
37
+ if (e.key === 'Escape' && this.open) {
38
+ this.closeDialog();
33
39
  }
40
+ }
34
41
 
35
- _onEsc(e) {
36
- if (e.key === 'Escape' && this.open) {
37
- this.closeDialog();
38
- }
42
+ openDialog() {
43
+ if (!this.open) {
44
+ if (this.modal) {
45
+ this._dialog.showModal();
46
+ } else {
47
+ this._dialog.show();
48
+ }
49
+ this.dispatchEvent(new CustomEvent('pb-dialog-opened', { bubbles: true, composed: true }));
50
+ this.open = true;
39
51
  }
52
+ }
40
53
 
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
- }
54
+ closeDialog() {
55
+ if (this.open) {
56
+ this._dialog.close();
57
+ this.dispatchEvent(new CustomEvent('pb-dialog-closed', { bubbles: true, composed: true }));
58
+ this.open = false;
51
59
  }
60
+ }
52
61
 
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
- }
62
+ render() {
63
+ return html`
64
+ <dialog @click="${e => e.target === this._dialog && this.modal && this.closeDialog()}">
65
+ <article>
66
+ <header>
67
+ ${this.title ? unsafeHTML(this.title) : html`<slot name="title"></slot>`}
68
+ <button rel="prev" aria-label="Close"></button>
69
+ </header>
70
+ ${this.message ? unsafeHTML(this.message) : html`<slot></slot>`}
71
+ <footer>
72
+ <slot name="footer"></slot>
73
+ </footer>
74
+ </article>
75
+ </dialog>
76
+ `;
77
+ }
60
78
 
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
- }
79
+ firstUpdated() {
80
+ this._dialog = this.renderRoot.querySelector('dialog');
81
+ // Add click listeners to close buttons in both shadow and light DOM
82
+ [
83
+ ...this._dialog.querySelectorAll('button[rel="prev"]'),
84
+ ...this.querySelectorAll('button[rel="prev"]'),
85
+ ].forEach(button => button.addEventListener('click', this.closeDialog.bind(this)));
86
+ }
87
+
88
+ static get styles() {
89
+ return css`
90
+ header {
91
+ display: flex;
92
+ justify-content: space-between;
93
+ align-items: center;
94
+ }
95
+ button[rel='prev'] {
96
+ display: block;
97
+ height: 1rem;
98
+ width: 1rem;
99
+ background-image: var(
100
+ --pb-dialog-background-image,
101
+ url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E")
102
+ );
103
+ background-position: center;
104
+ background-size: auto 1rem;
105
+ background-repeat: no-repeat;
106
+ background-color: transparent;
107
+ border: none;
108
+ }
109
+ footer {
110
+ display: flex;
111
+ justify-content: flex-end;
112
+ align-items: center;
113
+ margin-top: 16px;
114
+ }
115
+ `;
116
+ }
81
117
  }
82
118
 
83
- customElements.define('pb-dialog', PbDialog);
119
+ customElements.define('pb-dialog', PbDialog);