@teipublisher/pb-components 2.26.0-next-3.12 → 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 (132) 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 +30 -0
  5. package/Dockerfile +78 -70
  6. package/css/components.css +5 -5
  7. package/dist/demo/pb-drawer2.html +1 -1
  8. package/dist/demo/pb-leaflet-map.html +1 -1
  9. package/dist/demo/pb-progress.html +2 -2
  10. package/dist/demo/pb-repeat.html +1 -3
  11. package/dist/demo/pb-view3.html +1 -1
  12. package/dist/{paper-icon-button-0fb125c4.js → paper-icon-button-72125e67.js} +1 -1
  13. package/dist/pb-code-editor.js +25 -20
  14. package/dist/pb-component-docs.js +58 -54
  15. package/dist/pb-components-bundle.js +1937 -1782
  16. package/dist/pb-edit-app.js +167 -107
  17. package/dist/pb-elements.json +45 -45
  18. package/dist/{pb-i18n-0611135a.js → pb-i18n-4cc00bfe.js} +1 -1
  19. package/dist/pb-leaflet-map.js +23 -23
  20. package/dist/pb-mei.js +56 -41
  21. package/dist/{pb-mixin-b1caa22e.js → pb-mixin-886ece32.js} +1 -1
  22. package/dist/pb-odd-editor.js +923 -756
  23. package/dist/pb-tify.js +2 -2
  24. package/dist/{vaadin-element-mixin-49ab4037.js → vaadin-element-mixin-84fb7d82.js} +178 -163
  25. package/gh-pages.js +5 -3
  26. package/i18n/common/pl.json +2 -2
  27. package/lib/openseadragon.min.js +1 -1
  28. package/package.json +2 -2
  29. package/pb-elements.json +45 -45
  30. package/src/assets/components.css +5 -5
  31. package/src/authority/airtable.js +20 -21
  32. package/src/authority/anton.js +129 -129
  33. package/src/authority/custom.js +23 -21
  34. package/src/authority/geonames.js +38 -32
  35. package/src/authority/gnd.js +47 -42
  36. package/src/authority/kbga.js +137 -134
  37. package/src/authority/metagrid.js +44 -46
  38. package/src/authority/reconciliation.js +66 -67
  39. package/src/authority/registry.js +4 -4
  40. package/src/docs/pb-component-docs.js +2 -2
  41. package/src/docs/pb-component-view.js +5 -5
  42. package/src/docs/pb-components-list.js +2 -2
  43. package/src/docs/pb-demo-snippet.js +2 -2
  44. package/src/dts-client.js +299 -297
  45. package/src/dts-select-endpoint.js +90 -82
  46. package/src/parse-date-service.js +184 -135
  47. package/src/pb-ajax.js +150 -146
  48. package/src/pb-authority-lookup.js +183 -146
  49. package/src/pb-autocomplete.js +292 -280
  50. package/src/pb-blacklab-highlight.js +264 -259
  51. package/src/pb-blacklab-results.js +236 -221
  52. package/src/pb-browse-docs.js +540 -475
  53. package/src/pb-browse.js +68 -65
  54. package/src/pb-clipboard.js +79 -76
  55. package/src/pb-code-editor.js +110 -102
  56. package/src/pb-code-highlight.js +209 -204
  57. package/src/pb-codepen.js +79 -72
  58. package/src/pb-collapse.js +212 -207
  59. package/src/pb-combo-box.js +190 -190
  60. package/src/pb-components-bundle.js +1 -1
  61. package/src/pb-custom-form.js +151 -149
  62. package/src/pb-dialog.js +94 -85
  63. package/src/pb-document.js +89 -90
  64. package/src/pb-download.js +210 -198
  65. package/src/pb-drawer.js +145 -148
  66. package/src/pb-edit-app.js +301 -229
  67. package/src/pb-edit-xml.js +98 -96
  68. package/src/pb-events.js +114 -107
  69. package/src/pb-facs-link.js +104 -102
  70. package/src/pb-facsimile.js +411 -413
  71. package/src/pb-formula.js +151 -153
  72. package/src/pb-geolocation.js +129 -131
  73. package/src/pb-grid-action.js +53 -56
  74. package/src/pb-grid.js +231 -228
  75. package/src/pb-highlight.js +140 -140
  76. package/src/pb-hotkeys.js +40 -42
  77. package/src/pb-i18n.js +101 -104
  78. package/src/pb-image-strip.js +84 -78
  79. package/src/pb-lang.js +132 -128
  80. package/src/pb-leaflet-map.js +488 -485
  81. package/src/pb-link.js +126 -124
  82. package/src/pb-load.js +431 -426
  83. package/src/pb-login.js +291 -248
  84. package/src/pb-manage-odds.js +364 -318
  85. package/src/pb-map-icon.js +89 -89
  86. package/src/pb-map-layer.js +85 -85
  87. package/src/pb-markdown.js +90 -99
  88. package/src/pb-media-query.js +74 -72
  89. package/src/pb-mei.js +306 -295
  90. package/src/pb-message.js +144 -144
  91. package/src/pb-mixin.js +269 -264
  92. package/src/pb-navigation.js +80 -82
  93. package/src/pb-observable.js +38 -38
  94. package/src/pb-odd-editor.js +1053 -955
  95. package/src/pb-odd-elementspec-editor.js +348 -297
  96. package/src/pb-odd-model-editor.js +1061 -901
  97. package/src/pb-odd-parameter-editor.js +200 -178
  98. package/src/pb-odd-rendition-editor.js +136 -124
  99. package/src/pb-page.js +431 -421
  100. package/src/pb-paginate.js +202 -190
  101. package/src/pb-panel.js +191 -179
  102. package/src/pb-popover-themes.js +7 -5
  103. package/src/pb-popover.js +296 -287
  104. package/src/pb-print-preview.js +127 -127
  105. package/src/pb-progress.js +51 -51
  106. package/src/pb-repeat.js +105 -104
  107. package/src/pb-restricted.js +84 -77
  108. package/src/pb-search.js +252 -241
  109. package/src/pb-select-feature.js +127 -120
  110. package/src/pb-select-odd.js +132 -124
  111. package/src/pb-select-template.js +89 -78
  112. package/src/pb-select.js +251 -227
  113. package/src/pb-split-list.js +179 -174
  114. package/src/pb-svg.js +80 -79
  115. package/src/pb-table-column.js +54 -54
  116. package/src/pb-table-grid.js +221 -203
  117. package/src/pb-tabs.js +61 -63
  118. package/src/pb-tify.js +154 -154
  119. package/src/pb-timeline.js +271 -229
  120. package/src/pb-toggle-feature.js +182 -175
  121. package/src/pb-upload.js +184 -174
  122. package/src/pb-version.js +30 -30
  123. package/src/pb-view-annotate.js +132 -98
  124. package/src/pb-view.js +1289 -1270
  125. package/src/pb-zoom.js +75 -59
  126. package/src/polymer-hack.js +1 -1
  127. package/src/search-result-service.js +256 -223
  128. package/src/seed-element.js +13 -20
  129. package/src/settings.js +4 -4
  130. package/src/theming.js +96 -96
  131. package/src/urls.js +289 -289
  132. package/src/utils.js +53 -51
package/src/pb-search.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { LitElement, html, css } from 'lit-element';
2
2
  import { pbMixin, waitOnce } from './pb-mixin.js';
3
- import { registry } from "./urls.js";
4
- import { translate } from "./pb-i18n.js";
3
+ import { registry } from './urls.js';
4
+ import { translate } from './pb-i18n.js';
5
5
  import '@polymer/iron-ajax';
6
- import {themableMixin} from "./theming.js";
6
+ import { themableMixin } from './theming.js';
7
7
 
8
8
  /**
9
9
  * Implements a basic search form, which can be extended with additional inputs.
@@ -22,270 +22,281 @@ import {themableMixin} from "./theming.js";
22
22
  * @fires pb-search-resubmit - When received, triggers the search again
23
23
  */
24
24
  export class PbSearch extends themableMixin(pbMixin(LitElement)) {
25
- static get properties() {
26
- return {
27
- ...super.properties,
28
- action: {
29
- type: String
30
- },
31
- name: {
32
- type: String
33
- },
34
- value: {
35
- type: String
36
- },
37
- start: {
38
- type: Number
39
- },
40
- placeHolder: {
41
- type: String,
42
- attribute: 'place-holder'
43
- },
44
- redirect: {
45
- type: Boolean
46
- },
47
- currentDoc: {
48
- type: String,
49
- attribute: 'current-doc'
50
- },
51
- submitOnLoad: {
52
- type: Boolean,
53
- attribute: 'submit-on-load'
54
- },
55
- subforms: {
56
- type: String
57
- },
58
- disableAutocomplete: {
59
- type: Boolean,
60
- attribute: 'disable-autocomplete'
61
- },
62
- /**
63
- * Optional URL to query for suggestions. If relative, it is interpreted
64
- * relative to the endpoint defined on a surrounding `pb-page`.
65
- *
66
- * Upon autocomplete, the current input by the user will be sent with a query parameter
67
- * `query`. The name/values of form controls nested within `pb-search` or subforms will also be
68
- * appended to the request as parameters. This allows the server side code to distinguish
69
- * different states.
70
- */
71
- source: {
72
- type: String
73
- }
74
- };
75
- }
25
+ static get properties() {
26
+ return {
27
+ ...super.properties,
28
+ action: {
29
+ type: String,
30
+ },
31
+ name: {
32
+ type: String,
33
+ },
34
+ value: {
35
+ type: String,
36
+ },
37
+ start: {
38
+ type: Number,
39
+ },
40
+ placeHolder: {
41
+ type: String,
42
+ attribute: 'place-holder',
43
+ },
44
+ redirect: {
45
+ type: Boolean,
46
+ },
47
+ currentDoc: {
48
+ type: String,
49
+ attribute: 'current-doc',
50
+ },
51
+ submitOnLoad: {
52
+ type: Boolean,
53
+ attribute: 'submit-on-load',
54
+ },
55
+ subforms: {
56
+ type: String,
57
+ },
58
+ disableAutocomplete: {
59
+ type: Boolean,
60
+ attribute: 'disable-autocomplete',
61
+ },
62
+ /**
63
+ * Optional URL to query for suggestions. If relative, it is interpreted
64
+ * relative to the endpoint defined on a surrounding `pb-page`.
65
+ *
66
+ * Upon autocomplete, the current input by the user will be sent with a query parameter
67
+ * `query`. The name/values of form controls nested within `pb-search` or subforms will also be
68
+ * appended to the request as parameters. This allows the server side code to distinguish
69
+ * different states.
70
+ */
71
+ source: {
72
+ type: String,
73
+ },
74
+ };
75
+ }
76
76
 
77
- constructor() {
78
- super();
79
- this.name = 'query';
80
- this.value = '';
81
- this.redirect = false;
82
- this.submitOnLoad = false;
83
- this.placeHolder = 'search.placeholder';
84
- this.disableAutocomplete = false;
85
- this.start = 1;
86
- }
77
+ constructor() {
78
+ super();
79
+ this.name = 'query';
80
+ this.value = '';
81
+ this.redirect = false;
82
+ this.submitOnLoad = false;
83
+ this.placeHolder = 'search.placeholder';
84
+ this.disableAutocomplete = false;
85
+ this.start = 1;
86
+ }
87
87
 
88
- connectedCallback() {
89
- super.connectedCallback();
88
+ connectedCallback() {
89
+ super.connectedCallback();
90
90
 
91
- this.subscribeTo('pb-search-resubmit', this._doSearch.bind(this));
92
- this.subscribeTo('pb-paginate', (ev) => {
93
- this.start = ev.detail.params.start;
94
- this._doSearch(true);
95
- });
91
+ this.subscribeTo('pb-search-resubmit', this._doSearch.bind(this));
92
+ this.subscribeTo('pb-paginate', ev => {
93
+ this.start = ev.detail.params.start;
94
+ this._doSearch(true);
95
+ });
96
96
 
97
- registry.subscribe(this, (state) => {
98
- this.value = state.query || '';
99
- this.start = state.start || 1;
100
- if (this.submitOnLoad) {
101
- this.emitTo('pb-load', {
102
- "url": this.action,
103
- "params": state
104
- });
105
- }
97
+ registry.subscribe(this, state => {
98
+ this.value = state.query || '';
99
+ this.start = state.start || 1;
100
+ if (this.submitOnLoad) {
101
+ this.emitTo('pb-load', {
102
+ url: this.action,
103
+ params: state,
106
104
  });
107
- }
105
+ }
106
+ });
107
+ }
108
108
 
109
- firstUpdated() {
110
- waitOnce('pb-page-ready', (options) => {
111
- const loader = this.shadowRoot.getElementById('autocompleteLoader');
112
- const url = this.source || "api/search/autocomplete";
113
- if (this.minApiVersion('1.0.0')) {
114
- loader.url = `${options.endpoint}/${url}`;
115
- } else {
116
- loader.url = `${options.endpoint}/modules/autocomplete.xql`;
117
- }
118
- });
119
-
120
- if (this.submitOnLoad) {
121
- const params = registry.state;
122
- registry.replace(this, params);
123
- this.emitTo('pb-load', {
124
- "url": this.action,
125
- "params": params
126
- });
127
- }
109
+ firstUpdated() {
110
+ waitOnce('pb-page-ready', options => {
111
+ const loader = this.shadowRoot.getElementById('autocompleteLoader');
112
+ const url = this.source || 'api/search/autocomplete';
113
+ if (this.minApiVersion('1.0.0')) {
114
+ loader.url = `${options.endpoint}/${url}`;
115
+ } else {
116
+ loader.url = `${options.endpoint}/modules/autocomplete.xql`;
117
+ }
118
+ });
128
119
 
129
- this.addEventListener('click', (e) => {
130
- const root = e.target.closest('[slot]');
131
- if (!root) {
132
- return;
133
- }
134
- if (root.slot === 'searchButton'){
135
- this._doSearch();
136
- }
137
- if (root.slot === 'resetButton'){
138
- this._reset();
139
- }
140
- });
120
+ if (this.submitOnLoad) {
121
+ const params = registry.state;
122
+ registry.replace(this, params);
123
+ this.emitTo('pb-load', {
124
+ url: this.action,
125
+ params,
126
+ });
141
127
  }
142
128
 
143
- render() {
144
- return html`
145
- <form id="searchPageForm" method="get" action="${this.action}" accept="text/html" @submit="${this._handleSubmit}">
146
- <slot name="beforeInput"></slot>
147
- <div class="input-wrapper">
148
- <input
149
- id="search"
150
- name="query"
151
- type="search"
152
- placeholder="${translate(this.placeHolder)}"
153
- .value="${this.value}"
154
- @keyup="${this._handleEnter}"
155
- list="suggestions"
156
- part="input"
157
- />
158
- <datalist id="suggestions"></datalist>
159
- <slot name="searchButton" part="search-button"></slot>
160
- <slot name="resetButton"></slot>
161
- </div>
162
- <slot></slot>
163
- </form>
164
- <iron-ajax
165
- id="autocompleteLoader"
166
- verbose
167
- handle-as="json"
168
- method="get"
169
- with-credentials
170
- @response="${this._updateSuggestions}"></iron-ajax>
171
- `;
172
- }
129
+ this.addEventListener('click', e => {
130
+ const root = e.target.closest('[slot]');
131
+ if (!root) {
132
+ return;
133
+ }
134
+ if (root.slot === 'searchButton') {
135
+ this._doSearch();
136
+ }
137
+ if (root.slot === 'resetButton') {
138
+ this._reset();
139
+ }
140
+ });
141
+ }
173
142
 
174
- static get styles() {
175
- return css`
176
- :host {
177
- display: inline-block;
178
- }
179
- .input-wrapper {
180
- display: flex;
181
- align-items: center;
182
- }
183
- #search {
184
- flex: 2;
185
- }
186
- `;
187
- }
143
+ render() {
144
+ return html`
145
+ <form
146
+ id="searchPageForm"
147
+ method="get"
148
+ action="${this.action}"
149
+ accept="text/html"
150
+ @submit="${this._handleSubmit}"
151
+ >
152
+ <slot name="beforeInput"></slot>
153
+ <div class="input-wrapper">
154
+ <input
155
+ id="search"
156
+ name="query"
157
+ type="search"
158
+ placeholder="${translate(this.placeHolder)}"
159
+ .value="${this.value}"
160
+ @keyup="${this._handleEnter}"
161
+ list="suggestions"
162
+ part="input"
163
+ />
164
+ <datalist id="suggestions"></datalist>
165
+ <slot name="searchButton" part="search-button"></slot>
166
+ <slot name="resetButton"></slot>
167
+ </div>
168
+ <slot></slot>
169
+ </form>
170
+ <iron-ajax
171
+ id="autocompleteLoader"
172
+ verbose
173
+ handle-as="json"
174
+ method="get"
175
+ with-credentials
176
+ @response="${this._updateSuggestions}"
177
+ ></iron-ajax>
178
+ `;
179
+ }
188
180
 
189
- _serializeForm() {
190
- const form = this.shadowRoot.getElementById('searchPageForm');
191
- const formData = new FormData(form);
192
- const json = {};
193
- // @ts-ignore - FormData.entries() is supported in modern browsers
194
- for (let [key, value] of formData.entries()) {
195
- json[key] = value;
196
- }
197
-
198
- // Also collect form controls from slots
199
- const formControls = this.querySelectorAll('input, select, textarea');
200
- formControls.forEach(control => {
201
- if (control.name && control.type !== 'button' && control.type !== 'submit' && control.type !== 'reset') {
202
- if (control.type === 'checkbox' || control.type === 'radio') {
203
- if (control.checked) {
204
- json[control.name] = control.value;
205
- }
206
- } else {
207
- json[control.name] = control.value;
208
- }
209
- }
210
- });
211
-
212
- return json;
181
+ static get styles() {
182
+ return css`
183
+ :host {
184
+ display: inline-block;
185
+ }
186
+ .input-wrapper {
187
+ display: flex;
188
+ align-items: center;
189
+ }
190
+ #search {
191
+ flex: 2;
192
+ }
193
+ `;
194
+ }
195
+
196
+ _serializeForm() {
197
+ const form = this.shadowRoot.getElementById('searchPageForm');
198
+ const formData = new FormData(form);
199
+ const json = {};
200
+ // @ts-ignore - FormData.entries() is supported in modern browsers
201
+ for (const [key, value] of formData.entries()) {
202
+ json[key] = value;
213
203
  }
214
204
 
215
- _doSearch(pagination = false) {
216
- let json = this._serializeForm();
217
- json = this._paramsFromSubforms(json);
218
- json.start = pagination ? this.start : 1;
219
- if (this.redirect) {
220
- const params = new URLSearchParams();
221
- Object.keys(json).forEach(key => {
222
- params.append(key, json[key]);
223
- });
224
- window.location.href = `${this.action}?${params}`;
205
+ // Also collect form controls from slots
206
+ const formControls = this.querySelectorAll('input, select, textarea');
207
+ formControls.forEach(control => {
208
+ if (
209
+ control.name &&
210
+ control.type !== 'button' &&
211
+ control.type !== 'submit' &&
212
+ control.type !== 'reset'
213
+ ) {
214
+ if (control.type === 'checkbox' || control.type === 'radio') {
215
+ if (control.checked) {
216
+ json[control.name] = control.value;
217
+ }
225
218
  } else {
226
- registry.commit(this, json);
227
- this.emitTo('pb-load', {
228
- "url": this.action,
229
- "params": json
230
- });
219
+ json[control.name] = control.value;
231
220
  }
232
- }
221
+ }
222
+ });
233
223
 
234
- _handleSubmit(e) {
235
- e.preventDefault();
236
- this._doSearch();
237
- }
224
+ return json;
225
+ }
238
226
 
239
- _paramsFromSubforms(params) {
240
- if (this.subforms) {
241
- document.querySelectorAll(this.subforms).forEach((form) => {
242
- if (form.serializeForm) {
243
- Object.assign(params, form.serializeForm());
244
- }
245
- });
246
- }
247
- return params;
227
+ _doSearch(pagination = false) {
228
+ let json = this._serializeForm();
229
+ json = this._paramsFromSubforms(json);
230
+ json.start = pagination ? this.start : 1;
231
+ if (this.redirect) {
232
+ const params = new URLSearchParams();
233
+ Object.keys(json).forEach(key => {
234
+ params.append(key, json[key]);
235
+ });
236
+ window.location.href = `${this.action}?${params}`;
237
+ } else {
238
+ registry.commit(this, json);
239
+ this.emitTo('pb-load', {
240
+ url: this.action,
241
+ params: json,
242
+ });
248
243
  }
244
+ }
249
245
 
250
- _handleEnter(e) {
251
- if (e.keyCode === 13) {
252
- return this._doSearch();
253
- }
254
- const value = this.shadowRoot.getElementById('search').value;
255
- if (value.length > 2) {
256
- const loader = this.shadowRoot.getElementById('autocompleteLoader');
257
- loader.params = {
258
- query: value
259
- };
260
- loader.generateRequest();
246
+ _handleSubmit(e) {
247
+ e.preventDefault();
248
+ this._doSearch();
249
+ }
250
+
251
+ _paramsFromSubforms(params) {
252
+ if (this.subforms) {
253
+ document.querySelectorAll(this.subforms).forEach(form => {
254
+ if (form.serializeForm) {
255
+ Object.assign(params, form.serializeForm());
261
256
  }
257
+ });
262
258
  }
259
+ return params;
260
+ }
263
261
 
264
- _doSubmit() {
265
- this._doSearch();
262
+ _handleEnter(e) {
263
+ if (e.keyCode === 13) {
264
+ return this._doSearch();
266
265
  }
267
-
268
- _reset() {
269
- const form = this.shadowRoot.getElementById('searchPageForm');
270
- form.reset();
271
- registry.commit(this, {}, true);
266
+ const { value } = this.shadowRoot.getElementById('search');
267
+ if (value.length > 2) {
268
+ const loader = this.shadowRoot.getElementById('autocompleteLoader');
269
+ loader.params = {
270
+ query: value,
271
+ };
272
+ loader.generateRequest();
272
273
  }
274
+ }
273
275
 
274
- _updateSuggestions() {
275
- const loader = this.shadowRoot.getElementById('autocompleteLoader');
276
- const datalist = this.shadowRoot.getElementById('suggestions');
277
- if (loader.lastResponse) {
278
- datalist.innerHTML = '';
279
- loader.lastResponse.forEach(({text, value}) => {
280
- const option = document.createElement('option');
281
- option.value = value;
282
- option.innerText = text;
283
- datalist.appendChild(option);
284
- });
285
- }
276
+ _doSubmit() {
277
+ this._doSearch();
278
+ }
279
+
280
+ _reset() {
281
+ const form = this.shadowRoot.getElementById('searchPageForm');
282
+ form.reset();
283
+ registry.commit(this, {}, true);
284
+ }
285
+
286
+ _updateSuggestions() {
287
+ const loader = this.shadowRoot.getElementById('autocompleteLoader');
288
+ const datalist = this.shadowRoot.getElementById('suggestions');
289
+ if (loader.lastResponse) {
290
+ datalist.innerHTML = '';
291
+ loader.lastResponse.forEach(({ text, value }) => {
292
+ const option = document.createElement('option');
293
+ option.value = value;
294
+ option.innerText = text;
295
+ datalist.appendChild(option);
296
+ });
286
297
  }
298
+ }
287
299
  }
288
300
  if (!customElements.get('pb-search')) {
289
- customElements.define('pb-search', PbSearch);
301
+ customElements.define('pb-search', PbSearch);
290
302
  }
291
-