@data-fair/frame 0.10.0 → 0.11.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/dist/d-frame.min.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var
|
|
1
|
+
var H=Object.defineProperty;var I=(l,u,f)=>u in l?H(l,u,{enumerable:!0,configurable:!0,writable:!0,value:f}):l[u]=f;var o=(l,u,f)=>I(l,typeof u!="symbol"?u+"":u,f);(function(){"use strict";function l(e){return e[0]==="df-global"&&e[1]==="mouse"}function u(e){return e[0]==="df-child"&&e[1]==="init"}function f(e){return e[0]==="df-child"&&e[1]==="height"}function b(e){return e[0]==="df-child"&&e[1]==="stateChange"}function y(e){return e[0]==="df-child"&&e[1]==="custom"}function w(e){return e[0]==="df-child"&&e[1]==="notif"}function E(e){return e[0]==="df-child"&&e[1]==="ready"}function v(e){return e.endsWith("/")?e:e===""?"/":e.slice(0,e.lastIndexOf("/")+1)}function p(e,a){if(a.origin!==e.origin)return a.href;if(a.pathname===e.pathname)return"";const t=v(e.pathname);return a.pathname.startsWith(t)?a.pathname.replace(t,"./"):a.pathname}const A=e=>e.replace(/[-[\]/{}()*+?.\\^$|]/g,"\\$&");function S(e){const a=[];for(const t of e.split(",")){const[s="*",i]=t.split(":"),r="^"+A(s).replace(/\\\*/g,"(.*)")+"$";a.push({regexp:new RegExp(r),append:i})}return a}function C(e,a,t,s){if(!t&&!s)return e;const i=new URL(e),r=new URL(a);if(t&&r.searchParams.forEach((n,c)=>{for(const h of t){if(h.append&&!c.startsWith(h.append)||c===s)continue;const d=h.append?c.replace(h.append,""):c;if(d.match(h.regexp)){i.searchParams.set(d,n);break}}}),s!==null){let n;s==="#"?n=r.hash.slice(1):s.startsWith("/")?r.pathname.startsWith(s)&&(n=p(new URL(s,a),r)):n=r.searchParams.get(s),n&&(i.pathname=new URL(n,e).pathname)}return i.href}function M(e,a,t,s,i){const r=new URL(e),n=new URL(t),c=new URL(a);if(s){for(const h of n.searchParams.keys().toArray())for(const d of s){if(d.append&&!h.startsWith(d.append))continue;const g=d.append?h.replace(d.append,""):h;if(g.match(d.regexp)){c.searchParams.get(g)===null&&n.searchParams.delete(h);break}}c.searchParams.forEach((h,d)=>{for(const g of s){if(!d.match(g.regexp)||(r==null?void 0:r.searchParams.get(d))===h)continue;const L=g.append?g.append+d:d;n.searchParams.set(L,h);break}})}if(i!==null&&r){const h=p(r,c);i==="#"?n.hash=h:i.startsWith("/")?n.pathname=new URL(h,new URL(i,t)).pathname:h?n.searchParams.set(i,h):n.searchParams.delete(i)}return n}function R(e){return e.vIframe===!0&&e.uiNotification!==void 0}function z(e){if(typeof e=="string")return{type:"default",title:e};if(e.error&&!e.errorMsg){const a=e.error.response&&(e.error.response.data||e.error.response.status)||e.error.message||e.error;return e.msg?{type:"error",title:e.msg,detail:a}:{type:"error",title:a}}return e.type==="error"?{type:e.clientError?"warning":"error",title:e.msg,detail:e.errorMsg}:{type:e.type??"default",title:e.msg}}class P{stateChange(a,t){a==="replace"&&window.history.replaceState(window.history.state,"",t),a==="push"&&window.history.pushState(window.history.state,"",t)}onStateChange(a){window.addEventListener("popstate",a)}}const m=document.createElement("template");m.innerHTML=`<style>
|
|
2
2
|
:host {
|
|
3
3
|
display: block;
|
|
4
4
|
}
|
|
@@ -11,5 +11,5 @@ var I=Object.defineProperty;var L=(l,u,f)=>u in l?I(l,u,{enumerable:!0,configura
|
|
|
11
11
|
height: 100%;
|
|
12
12
|
border: none;
|
|
13
13
|
}
|
|
14
|
-
</style><div class="d-frame-wrapper"><slot name="loading"><div style="min-height:150px;"></div></slot><iframe class="d-frame-iframe" style="visibility:hidden;position:absolute;height:0px;"></iframe></div>`;class
|
|
14
|
+
</style><div class="d-frame-wrapper"><slot name="loading"><div style="min-height:150px;"></div></slot><iframe class="d-frame-iframe" style="visibility:hidden;position:absolute;height:0px;"></iframe></div>`;class x extends HTMLElement{constructor(){super();o(this,"adapter");o(this,"windowAdapter");o(this,"connected",!1);o(this,"childInitialized",!1);o(this,"currentChildSrc",null);o(this,"parsedSyncParams");o(this,"wrapperElement");o(this,"slotElement");o(this,"iframeElement");o(this,"width");o(this,"aspectRatioHeight");o(this,"resizedHeight");o(this,"randomId");o(this,"iframeLoaded",!1);o(this,"ready",!1);o(this,"iframeExtraAttrs",{});o(this,"currentSyncedMouseEvents",new Set);this.randomId=Math.random().toString(36).slice(-6);const t=m.content.cloneNode(!0);this.wrapperElement=t.childNodes[1],this.slotElement=this.wrapperElement.childNodes[0],this.iframeElement=this.wrapperElement.childNodes[1],this.iframeElement.addEventListener("load",()=>{this.iframeElement.getAttribute("src")&&(this.log("debug","iframe loaded"),this.iframeLoaded=!0,this.dispatchEvent(new CustomEvent("iframe-load")),this.resize!=="yes"&&!this.readyMessage&&(this.ready=!0,this.dispatchEvent(new CustomEvent("ready")),this.updateStyle()))}),this.attachShadow({mode:"open"}).appendChild(t),new ResizeObserver(r=>{(this.width===void 0||Math.abs(this.width-r[0].contentRect.width)>2)&&(this.width=r[0].contentRect.width,this.updateAspectRatioHeight())}).observe(this),this.adapter=this.windowAdapter=new P,window.addEventListener("message",r=>this.onMessage(r))}get id(){return this.getAttribute("id")??this.randomId}set id(t){this.setAttribute("id",t)}get debug(){return this.hasAttribute("debug")}set debug(t){t?this.setAttribute("debug",""):this.removeAttribute("debug")}get src(){return this.getAttribute("src")}set src(t){this.setAttribute("src",t)}get fullSrc(){return this.src.startsWith("/")?window.location.origin+this.src:this.src}get aspectRatio(){const t=this.getAttribute("aspect-ratio");return t===""?"auto":t}set aspectRatio(t){t!==null?this.setAttribute("aspect-ratio",t):this.removeAttribute("aspect-ratio")}get height(){return this.getAttribute("height")}set height(t){t?this.setAttribute("height",t):this.removeAttribute("height")}set resize(t){this.setAttribute("resize",t)}get resize(){const t=this.getAttribute("resize");return t===null?"auto":t===""?"yes":t}get syncParams(){return this.getAttribute("sync-params")}set syncParams(t){t!==null?this.setAttribute("sync-params",t):this.removeAttribute("sync-params")}get syncPath(){const t=this.getAttribute("sync-path");return t===null?null:t||"p"}set syncPath(t){t!==null?this.setAttribute("sync-params",t):this.removeAttribute("sync-params")}get stateChangeEvents(){return this.hasAttribute("state-change-events")}set stateChangeEvents(t){t?this.setAttribute("state-change-events",""):this.removeAttribute("state-change-events")}get readyMessage(){return this.hasAttribute("ready-message")}set readyMessage(t){t?this.setAttribute("ready-message",""):this.removeAttribute("ready-message")}get mouseEvents(){const t=this.getAttribute("mouse-events");return t===null?null:t===""?["click","dblclick","mousedown","mouseup"]:t.split(",")}set mouseEvents(t){t===null?this.removeAttribute("mouse-events"):this.setAttribute("mouse-events",t.join(","))}get reload(){return this.getAttribute("reload")}set reload(t){this.setAttribute("reload",t)}get actualAspectRatio(){return this.aspectRatio!=="auto"?Number(this.aspectRatio):!this.width||this.width<500?1:this.width<800?4/3:this.width<1200?16/9:21/9}onMessage(t){var s;if(t.source===((s=this.iframeElement)==null?void 0:s.contentWindow)){const i=t.data;if(this.log("debug","received message from child",i),Array.isArray(t.data)){if(u(i)&&(this.postMessageToChild(["df-parent","init",{id:this.id,debug:this.debug,resize:this.resize,syncParams:this.syncParams!==null,syncPath:this.syncPath!==null,stateChangeEvents:this.stateChangeEvents,mouseEvents:this.mouseEvents}]),this.childInitialized=!0),f(i)&&(this.resizedHeight=i[2],this.resize==="yes"&&!this.ready&&!this.readyMessage&&(this.ready=!0,this.dispatchEvent(new CustomEvent("ready"))),this.updateStyle()),b(i)){if(this.currentChildSrc=i[3],this.parsedSyncParams||this.syncPath){const r=M(this.fullSrc,i[3],window.location.href,this.parsedSyncParams,this.syncPath);if(r.href!==window.location.href){this.log("debug","apply state change to parent",i[2],r.href);try{this.adapter.stateChange(i[2],r)}catch(n){this.log("error","failed to apply state change to parent using custom adapter",n),this.windowAdapter.stateChange(i[2],r)}}}this.stateChangeEvents&&this.dispatchEvent(new CustomEvent("state-change",{detail:[i[2],i[3]]}))}y(i)&&this.dispatchEvent(new CustomEvent("message",{detail:i[2]})),w(i)&&this.dispatchEvent(new CustomEvent("notif",{detail:i[2]})),E(i)&&(this.ready=!0,this.dispatchEvent(new CustomEvent("ready")),this.updateStyle()),l(i)&&this.applySyncedMouseEvent(i)}else R(i)&&this.dispatchEvent(new CustomEvent("notif",{detail:z(i.uiNotification)}))}}postMessageToChild(t){var s,i;this.log("debug","send message to child",t),(i=(s=this.iframeElement)==null?void 0:s.contentWindow)==null||i.postMessage(t)}updateSrc(){if(!this.connected)return;const t=C(this.fullSrc,window.location.href,this.parsedSyncParams,this.syncPath);t!==this.currentChildSrc&&(this.currentChildSrc=t,this.childInitialized?this.postMessageToChild(["df-parent","updateSrc",t]):(this.log("debug","set src attribute of iframe: "+t),this.iframeElement.setAttribute("src",t)))}updateStyle(){if(!this.connected)return;let t;this.resizedHeight?(this.log("debug","height of iframe based on resize message: "+this.resizedHeight),t=this.resizedHeight+"px"):this.height?(this.log("debug","height of iframe based on direct attribute: "+this.height),t=this.height):this.aspectRatio!==null&&(this.log("debug","height of iframe based on aspect ratio: "+this.aspectRatioHeight),t=this.aspectRatioHeight+"px"),t!==void 0?(this.log("debug","set height iframe wrapper: "+t),this.wrapperElement.setAttribute("style",`height:${t};min-height:0;`)):this.wrapperElement.setAttribute("style",""),this.resize==="yes"||this.resize==="auto"&&this.resizedHeight?this.iframeElement.getAttribute("scrolling")!=="no"&&(this.log("debug","set scrolling attribute of iframe: no"),this.iframeElement.setAttribute("scrolling","no")):this.iframeElement.getAttribute("scrolling")!=="auto"&&(this.log("debug","set scrolling attribute of iframe: auto"),this.iframeElement.setAttribute("scrolling","auto")),this.ready&&this.iframeElement.getAttribute("style")!==""&&(this.log("debug","toggle loading slot and iframe visibility"),this.iframeElement.setAttribute("style",""),this.slotElement.setAttribute("style","display:none;"))}updateAspectRatioHeight(){this.width&&this.aspectRatio!==null&&(this.resizedHeight||this.height||(this.aspectRatioHeight=Math.ceil(this.width/this.actualAspectRatio),this.updateStyle()))}updateIframeExtraAttrs(){const t=this.iframeExtraAttrs,s={};for(const i of this.getAttributeNames())if(i.startsWith("iframe-")){const r=this.getAttribute(i);if(r!==null){const n=i.slice(7);s[n]=r}}this.log("debug","update iframe extra attributes",t,s);for(const i of Object.keys(t))i in s||this.iframeElement.removeAttribute(i);for(const i of Object.keys(s))s[i]!==t[i]&&this.iframeElement.setAttribute(i,s[i])}initMouseEvents(t){this.log("debug","initMouseEvents");for(const s of t)document.addEventListener(s,i=>{i instanceof MouseEvent&&this.transmitSyncedMouseEvent(["df-global","mouse",s,{altKey:i.altKey,ctrlKey:i.ctrlKey,shiftKey:i.shiftKey,metaKey:i.metaKey}])},!0)}transmitSyncedMouseEvent(t){this.currentSyncedMouseEvents.has(t[2])?this.currentSyncedMouseEvents.delete(t[2]):this.postMessageToChild(t)}applySyncedMouseEvent(t){this.currentSyncedMouseEvents.add(t[2]);const s=new MouseEvent(t[2],{bubbles:!0,cancelable:!0,view:window,...t[3]});this.dispatchEvent(s)}log(t,...s){t==="debug"&&!this.debug||(t==="debug"&&console.timeLog(`d-frame:${this.id}`,...s),t==="info"&&console.info(`d-frame:${this.id}`,...s),t==="error"&&console.error(`d-frame:${this.id}`,...s))}connectedCallback(){if(!this.debug){const t=window.localStorage.getItem("debug");if(t){const s=t.split(",");(s.includes("d-frame")||s.includes("d-frame:"+this.id))&&(this.debug=!0)}}if(this.debug&&console.time(`d-frame:${this.id}`),!this.hasAttribute("src"))throw new Error("src is a required attribute");this.log("debug","connected"),this.connected=!0,this.adapter.onStateChange&&this.adapter.onStateChange(()=>{this.updateSrc()}),this.syncParams!==null&&(this.parsedSyncParams=S(this.syncParams||"*")),this.updateStyle(),this.updateIframeExtraAttrs(),this.updateSrc(),this.mouseEvents&&this.initMouseEvents(this.mouseEvents)}disconnectedCallback(){this.log("debug","disconnected"),this.debug&&console.timeEnd(`d-frame:${this.id}`)}static get observedAttributes(){return["src","aspect-ratio","height","sync-params","sync-path","reload"]}attributeChangedCallback(t,s,i){var r;if(t==="aspect-ratio"&&this.updateAspectRatioHeight(),!!this.connected&&(this.log("debug","attribute change",t,s,i),t==="src"&&this.updateSrc(),t==="height"&&this.updateStyle(),t==="sync-params"&&this.updateSrc(),t==="sync-path"&&this.updateSrc(),t==="reload")){if(!this.currentChildSrc){this.log("debug","reload attribute changed but no iframe previously src");return}if(!((r=this.iframeElement.contentWindow)!=null&&r.location)){this.log("debug","reload attribute changed but no iframe contentWindow, is this a cross domain iframe ?");return}this.log("debug","reload iframe with current src",this.currentChildSrc),this.childInitialized=!1,this.iframeElement.setAttribute("src",this.currentChildSrc),this.iframeElement.contentWindow.location.reload()}}}customElements.get("d-frame")||customElements.define("d-frame",x)})();
|
|
15
15
|
//# sourceMappingURL=d-frame.min.js.map
|
package/lib/DFrameElement.d.ts
CHANGED
|
@@ -30,6 +30,7 @@ export default class DFrameElement extends HTMLElement {
|
|
|
30
30
|
get reload(): string;
|
|
31
31
|
set reload(value: string);
|
|
32
32
|
adapter: StateChangeAdapter;
|
|
33
|
+
windowAdapter: StateChangeAdapter;
|
|
33
34
|
private connected;
|
|
34
35
|
private childInitialized;
|
|
35
36
|
private currentChildSrc;
|
|
@@ -56,7 +57,7 @@ export default class DFrameElement extends HTMLElement {
|
|
|
56
57
|
private initMouseEvents;
|
|
57
58
|
private transmitSyncedMouseEvent;
|
|
58
59
|
private applySyncedMouseEvent;
|
|
59
|
-
log(level: 'debug' | 'info', ...args: any[]): void;
|
|
60
|
+
log(level: 'debug' | 'info' | 'error', ...args: any[]): void;
|
|
60
61
|
connectedCallback(): void;
|
|
61
62
|
disconnectedCallback(): void;
|
|
62
63
|
static get observedAttributes(): string[];
|
package/lib/DFrameElement.js
CHANGED
|
@@ -126,6 +126,7 @@ export default class DFrameElement extends HTMLElement {
|
|
|
126
126
|
get reload() { return this.getAttribute('reload'); }
|
|
127
127
|
set reload(value) { this.setAttribute('reload', value); }
|
|
128
128
|
adapter;
|
|
129
|
+
windowAdapter;
|
|
129
130
|
/* internal state */
|
|
130
131
|
connected = false;
|
|
131
132
|
childInitialized = false;
|
|
@@ -181,7 +182,7 @@ export default class DFrameElement extends HTMLElement {
|
|
|
181
182
|
}
|
|
182
183
|
});
|
|
183
184
|
resizeObserver.observe(this);
|
|
184
|
-
this.adapter = new WindowStateChangeAdapter();
|
|
185
|
+
this.adapter = this.windowAdapter = new WindowStateChangeAdapter();
|
|
185
186
|
window.addEventListener('message', (e) => this.onMessage(e));
|
|
186
187
|
}
|
|
187
188
|
onMessage(e) {
|
|
@@ -215,8 +216,14 @@ export default class DFrameElement extends HTMLElement {
|
|
|
215
216
|
if ((this.parsedSyncParams || this.syncPath)) {
|
|
216
217
|
const newParentHUrl = getParentUrl(this.fullSrc, message[3], window.location.href, this.parsedSyncParams, this.syncPath);
|
|
217
218
|
if (newParentHUrl.href !== window.location.href) {
|
|
218
|
-
this.log('debug', 'apply state change to parent', message[2], newParentHUrl);
|
|
219
|
-
|
|
219
|
+
this.log('debug', 'apply state change to parent', message[2], newParentHUrl.href);
|
|
220
|
+
try {
|
|
221
|
+
this.adapter.stateChange(message[2], newParentHUrl);
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
this.log('error', 'failed to apply state change to parent using custom adapter', err);
|
|
225
|
+
this.windowAdapter.stateChange(message[2], newParentHUrl);
|
|
226
|
+
}
|
|
220
227
|
}
|
|
221
228
|
}
|
|
222
229
|
if (this.stateChangeEvents) {
|
|
@@ -375,6 +382,8 @@ export default class DFrameElement extends HTMLElement {
|
|
|
375
382
|
console.timeLog(`d-frame:${this.id}`, ...args);
|
|
376
383
|
if (level === 'info')
|
|
377
384
|
console.info(`d-frame:${this.id}`, ...args);
|
|
385
|
+
if (level === 'error')
|
|
386
|
+
console.error(`d-frame:${this.id}`, ...args);
|
|
378
387
|
}
|
|
379
388
|
/* standard custom element callbacks */
|
|
380
389
|
connectedCallback() {
|
package/lib/utils/sync-params.js
CHANGED
|
@@ -33,7 +33,18 @@ export function getChildSrc(fullSrc, parentHref, syncParams, syncPath) {
|
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
35
|
if (syncPath !== null) {
|
|
36
|
-
|
|
36
|
+
let path;
|
|
37
|
+
if (syncPath === '#') {
|
|
38
|
+
path = parentUrl.hash.slice(1);
|
|
39
|
+
}
|
|
40
|
+
else if (syncPath.startsWith('/')) {
|
|
41
|
+
if (parentUrl.pathname.startsWith(syncPath)) {
|
|
42
|
+
path = getUrlRelativePath(new URL(syncPath, parentHref), parentUrl);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
path = parentUrl.searchParams.get(syncPath);
|
|
47
|
+
}
|
|
37
48
|
if (path) {
|
|
38
49
|
childUrl.pathname = new URL(path, fullSrc).pathname;
|
|
39
50
|
}
|
|
@@ -74,10 +85,18 @@ export function getParentUrl(fullSrc, childHref, currentParentHref, syncParams,
|
|
|
74
85
|
}
|
|
75
86
|
if (syncPath !== null && srcUrl) {
|
|
76
87
|
const path = getUrlRelativePath(srcUrl, childUrl);
|
|
77
|
-
if (
|
|
78
|
-
parentUrl.
|
|
79
|
-
|
|
80
|
-
|
|
88
|
+
if (syncPath === '#') {
|
|
89
|
+
parentUrl.hash = path;
|
|
90
|
+
}
|
|
91
|
+
else if (syncPath.startsWith('/')) {
|
|
92
|
+
parentUrl.pathname = new URL(path, new URL(syncPath, currentParentHref)).pathname;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
if (path)
|
|
96
|
+
parentUrl.searchParams.set(syncPath, path);
|
|
97
|
+
else
|
|
98
|
+
parentUrl.searchParams.delete(syncPath);
|
|
99
|
+
}
|
|
81
100
|
}
|
|
82
101
|
return parentUrl;
|
|
83
102
|
}
|
|
@@ -4,10 +4,22 @@ class VueRouterDFrameStateChangeAdapter {
|
|
|
4
4
|
this.router = router;
|
|
5
5
|
}
|
|
6
6
|
stateChange(action, newUrl) {
|
|
7
|
+
// @ts-ignore vue-router v2
|
|
8
|
+
const base = this.router.options?.base ?? this.router.options.history?.base;
|
|
9
|
+
if (base === null || base === undefined) {
|
|
10
|
+
throw new Error('failed to access base path in router (no router.options.base nor router.options.history.base)');
|
|
11
|
+
}
|
|
12
|
+
const urlPrefix = window.location.origin + base;
|
|
13
|
+
if (!newUrl.href.startsWith(urlPrefix)) {
|
|
14
|
+
throw new Error('new URL does not start with base path');
|
|
15
|
+
}
|
|
16
|
+
let newRoute = newUrl.href.replace(urlPrefix, '');
|
|
17
|
+
if (!newRoute.startsWith('/'))
|
|
18
|
+
newRoute = '/' + newRoute;
|
|
7
19
|
if (action === 'push')
|
|
8
|
-
this.router.push(
|
|
20
|
+
this.router.push(newRoute);
|
|
9
21
|
if (action === 'replace')
|
|
10
|
-
this.router.replace(
|
|
22
|
+
this.router.replace(newRoute);
|
|
11
23
|
}
|
|
12
24
|
onStateChange(callback) {
|
|
13
25
|
this.router.afterEach(callback);
|