@teipublisher/pb-components 2.6.0 → 2.7.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.
- package/CHANGELOG.md +26 -0
- package/dist/demo/pb-svg.html +2 -5
- package/dist/pb-components-bundle.js +197 -197
- package/dist/pb-elements.json +57 -20
- package/package.json +2 -1
- package/pb-elements.json +57 -20
- package/src/pb-browse-docs.js +2 -0
- package/src/pb-custom-form.js +17 -1
- package/src/pb-load.js +5 -0
- package/src/pb-page.js +28 -1
- package/src/pb-popover.js +398 -390
- package/src/pb-svg.js +27 -21
- package/src/pb-tabs.js +10 -0
- package/src/urls.js +81 -15
package/src/pb-svg.js
CHANGED
|
@@ -6,9 +6,10 @@ import { pbMixin } from './pb-mixin.js';
|
|
|
6
6
|
/**
|
|
7
7
|
* Show an SVG image with zoom and pan functionality. The image URL may
|
|
8
8
|
* either be specified via the `url` property or an `pb-show-annotation` event
|
|
9
|
-
* sent to this component.
|
|
9
|
+
* sent to this component. A relative URL will be resolved against the current API context.
|
|
10
10
|
*
|
|
11
|
-
* @fires pb-show-annotation - When received, loads the image from the URL passed
|
|
11
|
+
* @fires pb-show-annotation - When received, loads the image from the URL passed in property `file`
|
|
12
|
+
* within the event
|
|
12
13
|
* @cssprop --pb-svg-height - Height of the SVG element
|
|
13
14
|
* @cssprop --pb-svg-width - Width of the SVG element
|
|
14
15
|
*/
|
|
@@ -32,43 +33,48 @@ export class PbSvg extends pbMixin(LitElement) {
|
|
|
32
33
|
|
|
33
34
|
connectedCallback() {
|
|
34
35
|
super.connectedCallback();
|
|
35
|
-
}
|
|
36
36
|
|
|
37
|
-
firstUpdated() {
|
|
38
|
-
super.firstUpdated();
|
|
39
37
|
window.ESGlobalBridge.requestAvailability();
|
|
40
38
|
window.ESGlobalBridge.instance.load("svg-pan-zoom", `https://cdn.jsdelivr.net/npm/svg-pan-zoom@3.6.1/dist/svg-pan-zoom.min.js`);
|
|
41
|
-
window.addEventListener(
|
|
42
|
-
"es-bridge-svg-pan-zoom-loaded",
|
|
43
|
-
this._onSvgPanZoomLoaded.bind(this),
|
|
44
|
-
{ once: true }
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
this.container = this.shadowRoot.getElementById('image');
|
|
48
39
|
|
|
49
40
|
this.subscribeTo('pb-show-annotation', (ev) => {
|
|
50
|
-
|
|
41
|
+
if (this.url === ev.detail.file) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
51
44
|
this.url = ev.detail.file;
|
|
52
|
-
this.load();
|
|
53
45
|
});
|
|
54
46
|
}
|
|
55
47
|
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
firstUpdated() {
|
|
49
|
+
super.firstUpdated();
|
|
50
|
+
|
|
51
|
+
this.container = this.shadowRoot.getElementById('image');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
updated(changed) {
|
|
55
|
+
if (changed.has('url') && this.url && this.url !== changed.get('url')) {
|
|
56
|
+
this.load();
|
|
57
|
+
}
|
|
58
58
|
}
|
|
59
|
-
|
|
59
|
+
|
|
60
60
|
load() {
|
|
61
|
+
if (!this.url) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const uri = this.toAbsoluteURL(this.url);
|
|
65
|
+
console.log('<pb-svg> Loading %s', uri);
|
|
61
66
|
if (this._pan) {
|
|
62
67
|
this._pan.destroy();
|
|
63
68
|
this._pan = null;
|
|
64
69
|
this.container.innerHTML = '';
|
|
65
70
|
}
|
|
66
|
-
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
fetch(this.url)
|
|
71
|
+
fetch(uri)
|
|
70
72
|
.then((response) => response.text())
|
|
71
73
|
.then((data) => {
|
|
74
|
+
if (!window.svgPanZoom) {
|
|
75
|
+
console.error('<pb-svg> svgPanZoom not available');
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
72
78
|
const doc = new DOMParser().parseFromString(data, "image/svg+xml");
|
|
73
79
|
const svg = doc.documentElement;
|
|
74
80
|
this.container.appendChild(svg);
|
package/src/pb-tabs.js
CHANGED
|
@@ -11,6 +11,8 @@ import { registry } from "./urls.js";
|
|
|
11
11
|
* @slot tab - tab area
|
|
12
12
|
* @slot page - page area
|
|
13
13
|
* @csspart pages - wrapper around the tab pages
|
|
14
|
+
* @fires pb-tab - fired if selected tab changes. Details contain number of
|
|
15
|
+
* selected tab in propery `selected`.
|
|
14
16
|
*/
|
|
15
17
|
export class PbTabs extends pbMixin(LitElement) {
|
|
16
18
|
static get properties() {
|
|
@@ -43,11 +45,19 @@ export class PbTabs extends pbMixin(LitElement) {
|
|
|
43
45
|
});
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
firstUpdated() {
|
|
49
|
+
super.firstUpdated();
|
|
50
|
+
this.emitTo('pb-tab', { selected: this.selected });
|
|
51
|
+
}
|
|
52
|
+
|
|
46
53
|
_switchTab(ev) {
|
|
47
54
|
const current = parseInt(ev.detail.value, 10);
|
|
48
55
|
if (this.selected === current) {
|
|
49
56
|
return;
|
|
50
57
|
}
|
|
58
|
+
|
|
59
|
+
this.emitTo('pb-tab', { selected: current });
|
|
60
|
+
|
|
51
61
|
this.selected = current;
|
|
52
62
|
if (this._initialized) {
|
|
53
63
|
registry.commit(this, { tab: this.selected });
|
package/src/urls.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { match, compile, pathToRegexp } from "path-to-regexp";
|
|
1
2
|
import { PbEvents } from "./pb-events.js";
|
|
2
3
|
import { getSubscribedChannels } from "./pb-mixin.js";
|
|
3
4
|
|
|
@@ -60,12 +61,34 @@ class Registry {
|
|
|
60
61
|
*/
|
|
61
62
|
this.idHash = true;
|
|
62
63
|
this._listeners = [];
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* URL pattern to use for mapping parameters into the URL path
|
|
67
|
+
*/
|
|
68
|
+
this.urlPattern = null;
|
|
69
|
+
|
|
70
|
+
this.urlIgnore = new Set();
|
|
71
|
+
this._pathParams = new Set();
|
|
63
72
|
}
|
|
64
73
|
|
|
65
|
-
configure(usePath = true, idHash = false, rootPath = '') {
|
|
74
|
+
configure(usePath = true, idHash = false, rootPath = '', urlPattern, ignoredParams) {
|
|
66
75
|
this.rootPath = rootPath;
|
|
67
76
|
this.usePath = usePath;
|
|
68
77
|
this.idHash = idHash;
|
|
78
|
+
this.urlPattern = urlPattern;
|
|
79
|
+
if (ignoredParams) {
|
|
80
|
+
ignoredParams.split(/\s*,\s*/).forEach(param => this.urlIgnore.add(param));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (this.urlPattern) {
|
|
84
|
+
// save a list of parameter names which go into the path
|
|
85
|
+
const pathParams = [];
|
|
86
|
+
pathToRegexp(this.urlPattern, pathParams);
|
|
87
|
+
pathParams.forEach((param) => this._pathParams.add(param.name));
|
|
88
|
+
// compile URL pattern into a decode and encode function
|
|
89
|
+
this._decodePath = match(this.urlPattern);
|
|
90
|
+
this._encodePath = compile(this.urlPattern);
|
|
91
|
+
}
|
|
69
92
|
|
|
70
93
|
// determine initial state of the registry by parsing current URL
|
|
71
94
|
const initialState = this._stateFromURL();
|
|
@@ -115,16 +138,35 @@ class Registry {
|
|
|
115
138
|
if (this.idHash && this.hash.length > 0 && (!/^#\d+\./.test(this.hash))) {
|
|
116
139
|
params.id = this.hash.substring(1);
|
|
117
140
|
}
|
|
118
|
-
|
|
119
|
-
|
|
141
|
+
const relpath = window.location.pathname.replace(new RegExp(`^${this.rootPath}/?`), '');
|
|
142
|
+
if (this.urlPattern) {
|
|
143
|
+
const result = this._decodePath(relpath);
|
|
144
|
+
Object.assign(params, result.params);
|
|
145
|
+
log('decoded path %s using template %s: %o', relpath, this.urlPattern, params);
|
|
146
|
+
} else if (this.usePath) {
|
|
147
|
+
params.path = relpath;
|
|
120
148
|
}
|
|
149
|
+
|
|
121
150
|
const urlParams = new URLSearchParams(window.location.search);
|
|
122
151
|
urlParams.forEach((value, key) => {
|
|
123
|
-
if (
|
|
152
|
+
if (
|
|
153
|
+
(this.urlPattern && this._pathParams.has(key)) ||
|
|
154
|
+
(this.usePath && key === 'path')
|
|
155
|
+
) {
|
|
124
156
|
console.warn("Found path parameter in query, but usePath is set to true. The path parameter will be ignored.");
|
|
125
157
|
return;
|
|
126
158
|
}
|
|
127
|
-
|
|
159
|
+
// parameter already set
|
|
160
|
+
if ((key in params)) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
// check for multiple entries
|
|
164
|
+
const allValues = urlParams.getAll(key);
|
|
165
|
+
if (allValues.length === 1) {
|
|
166
|
+
params[key] = value; // single entry
|
|
167
|
+
} else {
|
|
168
|
+
params[key] = allValues; // array
|
|
169
|
+
}
|
|
128
170
|
});
|
|
129
171
|
return params;
|
|
130
172
|
}
|
|
@@ -196,7 +238,7 @@ class Registry {
|
|
|
196
238
|
}
|
|
197
239
|
|
|
198
240
|
_commit(elem, newState, overwrite, replace) {
|
|
199
|
-
this.state = overwrite ? newState :
|
|
241
|
+
this.state = overwrite ? newState : ({ ...this.state, ...newState});
|
|
200
242
|
const resolved = this.urlFromState();
|
|
201
243
|
|
|
202
244
|
const chs = getSubscribedChannels(elem);
|
|
@@ -220,22 +262,46 @@ class Registry {
|
|
|
220
262
|
|
|
221
263
|
urlFromState() {
|
|
222
264
|
const newUrl = new URL(window.location.href);
|
|
265
|
+
|
|
266
|
+
function setParam(value, param) {
|
|
267
|
+
if (value === null) {
|
|
268
|
+
newUrl.searchParams.delete(param);
|
|
269
|
+
} else if (Array.isArray(value)) {
|
|
270
|
+
// copy array before mutating it
|
|
271
|
+
const _v = Array.from(value);
|
|
272
|
+
// overwrite any previous value by setting the first member
|
|
273
|
+
newUrl.searchParams.set(param, _v.pop());
|
|
274
|
+
// add additional values
|
|
275
|
+
_v.forEach(v => newUrl.searchParams.append(param, v));
|
|
276
|
+
} else {
|
|
277
|
+
newUrl.searchParams.set(param, value);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
223
281
|
for (const [param, value] of Object.entries(this.state)) {
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
newUrl.searchParams.delete(param)
|
|
228
|
-
} else {
|
|
229
|
-
newUrl.searchParams.set(param, value)
|
|
282
|
+
if (this.urlPattern) {
|
|
283
|
+
if (!(this._pathParams.has(param) || this.urlIgnore.has(param))) {
|
|
284
|
+
setParam(value, param);
|
|
230
285
|
}
|
|
286
|
+
} else if (
|
|
287
|
+
(param !== 'path' || !this.usePath) &&
|
|
288
|
+
(param !== 'id' || !this.idHash) &&
|
|
289
|
+
(!this.urlIgnore.has(param))
|
|
290
|
+
) {
|
|
291
|
+
setParam(value, param);
|
|
231
292
|
}
|
|
232
293
|
}
|
|
233
294
|
|
|
234
|
-
if (this.
|
|
235
|
-
|
|
295
|
+
if (this.state.path && this.state.path.length > 0) {
|
|
296
|
+
if (this.urlPattern) {
|
|
297
|
+
const encoded = this._encodePath(this.state);
|
|
298
|
+
newUrl.pathname = `${this.rootPath}/${encoded}`;
|
|
299
|
+
} else if (this.usePath) {
|
|
300
|
+
newUrl.pathname = `${this.rootPath}/${this.state.path}`;
|
|
301
|
+
}
|
|
236
302
|
}
|
|
237
303
|
|
|
238
|
-
if (this.state.id) {
|
|
304
|
+
if (this.state.id && !this.urlPattern) {
|
|
239
305
|
newUrl.hash = `#${this.state.id}`;
|
|
240
306
|
}
|
|
241
307
|
|