@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
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
-