@data-fair/frame 0.5.1 → 0.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.
@@ -1,2 +1,2 @@
1
- var DFrameContent=function(){"use strict";var g=Object.defineProperty;var l=(a,i,s)=>i in a?g(a,i,{enumerable:!0,configurable:!0,writable:!0,value:s}):a[i]=s;var n=(a,i,s)=>l(a,typeof i!="symbol"?i+"":i,s);function a(r){return r[0]==="df-parent"&&r[1]==="init"}function i(r){return r[0]==="df-parent"&&r[1]==="updateSrc"}const s=["animationstart","webkitAnimationStart","animationiteration","webkitAnimationIteration","animationend","webkitAnimationEnd","input","mouseup","mousedown","orientationchange","afterprint","beforeprint","readystatechange","touchstart","touchend","touchcancel","transitionstart","webkitTransitionStart","MSTransitionStart","oTransitionStart","otransitionstart","transitioniteration","webkitTransitionIteration","MSTransitionIteration","oTransitionIteration","otransitioniteration","transitionend","webkitTransitionEnd","MSTransitionEnd","oTransitionEnd","otransitionend","resize"];class c{constructor(e){n(this,"initialized",!1);n(this,"options");n(this,"pendingCheckHeight",!1);n(this,"debug",!1);n(this,"id");n(this,"throttledCheckHeight");n(this,"lastHeight",0);this.options=e??{};const t=()=>{this.checkHeight(),this.pendingCheckHeight=!1};this.throttledCheckHeight=()=>{this.pendingCheckHeight||(this.pendingCheckHeight=!0,requestAnimationFrame(t))},!(typeof window>"u")&&(window.addEventListener("message",o=>this.onMessage(o)),this.postMessageToParent(["df-child","init"]))}log(e,...t){e==="debug"&&!this.debug||(e==="debug"&&console.timeLog(`${this.id}:d-frame-content`,...t),e==="info"&&console.info(`${this.id}:d-frame-content`,...t))}onMessage(e){if(e.source===window.parent&&Array.isArray(e.data)){const t=e.data;a(t)&&(this.id=t[2].id,this.debug=!!t[2].debug,this.debug&&console.time(`${this.id}:d-frame-content`),t[2].resize!=="no"&&this.initResize(),(t[2].syncParams||t[2].syncPath||t[2].stateChangeEvents)&&this.initStateChangeWatcher(),this.initialized=!0),i(t)&&(this.options.updateSrc?this.options.updateSrc(t[2].startsWith("/")?window.location.origin+t[2]:t[2]):window.location.href=t[2])}}postMessageToParent(e){window.parent.postMessage(e)}sendNotif(e){this.postMessageToParent(["df-child","notif",e])}sendMessage(e){this.postMessageToParent(["df-child","custom",e])}initResize(){this.log("debug","initResize"),this.checkHeight(),this.createMutationObserver(),this.createWindowEventListeners()}initStateChangeWatcher(){this.log("debug","initStateChangeWatcher");const e=window.history.replaceState,t=(...h)=>{const d=e.apply(window.history,h);return this.postMessageToParent(["df-child","stateChange","push",window.location.href]),d};window.history.pushState=t;const o=(...h)=>{const d=e.apply(window.history,h);return this.postMessageToParent(["df-child","stateChange","replace",window.location.href]),d};window.history.replaceState=o}createMutationObserver(){const e=document.querySelector("body");if(!e)throw new Error("DFrameContentManager was initialized before the HTML body");new window.MutationObserver(this.throttledCheckHeight).observe(e,{attributes:!1,attributeOldValue:!1,characterData:!1,characterDataOldValue:!1,childList:!0,subtree:!0})}createWindowEventListeners(){for(const e of s)window.addEventListener(e,this.throttledCheckHeight,{passive:!0})}checkHeight(){const e=document.querySelectorAll("[data-iframe-height]");let t=0;for(const o of e){const h=o.getAttribute("data-iframe-height"),d=o.getBoundingClientRect().bottom+parseFloat(getComputedStyle(o).getPropertyValue("margin-bottom"))+(h?parseFloat(h):0);d>t&&(t=d)}t=Math.ceil(t),t!==this.lastHeight&&(this.postMessageToParent(["df-child","height",t]),this.lastHeight=t)}}return new c}();
1
+ var DFrameContent=function(){"use strict";var u=Object.defineProperty;var f=(o,n,r)=>n in o?u(o,n,{enumerable:!0,configurable:!0,writable:!0,value:r}):o[n]=r;var a=(o,n,r)=>f(o,typeof n!="symbol"?n+"":n,r);function o(h){return h[0]==="df-parent"&&h[1]==="init"}function n(h){return h[0]==="df-parent"&&h[1]==="updateSrc"}const r=["animationstart","webkitAnimationStart","animationiteration","webkitAnimationIteration","animationend","webkitAnimationEnd","input","mouseup","mousedown","orientationchange","afterprint","beforeprint","readystatechange","touchstart","touchend","touchcancel","transitionstart","webkitTransitionStart","MSTransitionStart","oTransitionStart","otransitionstart","transitioniteration","webkitTransitionIteration","MSTransitionIteration","oTransitionIteration","otransitioniteration","transitionend","webkitTransitionEnd","MSTransitionEnd","oTransitionEnd","otransitionend","resize"];class l{constructor(t){a(this,"initialized",!1);a(this,"options");a(this,"pendingCheckHeight",!1);a(this,"debug",!1);a(this,"id");a(this,"throttledCheckHeight");a(this,"lastHeight",0);this.options=t??{};const e=()=>{this.checkHeight(),this.pendingCheckHeight=!1};this.throttledCheckHeight=()=>{this.pendingCheckHeight||(this.pendingCheckHeight=!0,requestAnimationFrame(e))},!(typeof window>"u")&&(window.addEventListener("message",i=>this.onMessage(i)),this.postMessageToParent(["df-child","init"]))}log(t,...e){t==="debug"&&!this.debug||(t==="debug"&&console.timeLog(`d-frame:${this.id}:content`,...e),t==="info"&&console.info(`d-frame:${this.id}:content`,...e))}onMessage(t){if(t.source===window.parent&&Array.isArray(t.data)){const e=t.data;o(e)&&(this.id=e[2].id,this.debug=!!e[2].debug,this.debug&&console.time(`d-frame:${this.id}:content`),e[2].resize!=="no"&&this.initResize(),(e[2].syncParams||e[2].syncPath||e[2].stateChangeEvents)&&this.initStateChangeWatcher(),this.initialized=!0),n(e)&&(this.options.updateSrc?this.options.updateSrc(e[2].startsWith("/")?window.location.origin+e[2]:e[2]):window.location.href=e[2])}}postMessageToParent(t){window.parent.postMessage(t)}sendNotif(t){this.postMessageToParent(["df-child","notif",t])}sendMessage(t){this.postMessageToParent(["df-child","custom",t])}ready(){this.postMessageToParent(["df-child","ready"])}initResize(){this.log("debug","initResize"),this.checkHeight(),this.createMutationObserver(),this.createWindowEventListeners()}initStateChangeWatcher(){this.log("debug","initStateChangeWatcher");const t=window.history.replaceState,e=(...s)=>{const d=t.apply(window.history,s);return this.postMessageToParent(["df-child","stateChange","push",window.location.href]),d};window.history.pushState=e;const i=(...s)=>{const d=t.apply(window.history,s);return this.postMessageToParent(["df-child","stateChange","replace",window.location.href]),d};window.history.replaceState=i}createMutationObserver(){const t=document.querySelector("body");if(!t)throw new Error("DFrameContentManager was initialized before the HTML body");new window.MutationObserver(this.throttledCheckHeight).observe(t,{attributes:!1,attributeOldValue:!1,characterData:!1,characterDataOldValue:!1,childList:!0,subtree:!0})}createWindowEventListeners(){for(const t of r)window.addEventListener(t,this.throttledCheckHeight,{passive:!0})}checkHeight(){const t=document.querySelectorAll("[data-iframe-height]");let e=0,i=0;for(const s of t){const d=s.getAttribute("data-iframe-height"),c=s.getBoundingClientRect().bottom+parseFloat(getComputedStyle(s).getPropertyValue("margin-bottom")),g=d?c+parseFloat(d):c;c>e&&(e=c),g>i&&(i=g)}i=Math.ceil(i),e>0&&i!==this.lastHeight&&(this.postMessageToParent(["df-child","height",i]),this.lastHeight=i)}}return new l}();
2
2
  //# sourceMappingURL=d-frame-content.min.js.map
@@ -1,12 +1,15 @@
1
- var H=Object.defineProperty;var M=(u,c,g)=>c in u?H(u,c,{enumerable:!0,configurable:!0,writable:!0,value:g}):u[c]=g;var o=(u,c,g)=>M(u,typeof c!="symbol"?c+"":c,g);(function(){"use strict";function u(e){return e[0]==="df-child"&&e[1]==="init"}function c(e){return e[0]==="df-child"&&e[1]==="height"}function g(e){return e[0]==="df-child"&&e[1]==="stateChange"}function m(e){return e[0]==="df-child"&&e[1]==="custom"}function b(e){return e[0]==="df-child"&&e[1]==="notif"}function y(e){return e.endsWith("/")?e:e===""?"/":e.slice(0,e.lastIndexOf("/")+1)}function w(e,a){if(a.origin!==e.origin)return a.href;if(a.pathname===e.pathname)return"";const t=y(e.pathname);return a.pathname.startsWith(t)?a.pathname.replace(t,"./"):a.pathname}const A=e=>e.replace(/[-[\]/{}()*+?.\\^$|]/g,"\\$&");function E(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 z(e,a,t,s){if(!t&&!s)return e.href;const i=new URL(a);if(t&&i.searchParams.forEach((r,l)=>{for(const n of t){if(n.append&&!l.startsWith(n.append)||l===s)continue;const h=n.append?l.replace(n.append,""):l;if(h.match(n.regexp)){e.searchParams.set(h,r);break}}}),s!==null){const r=i.searchParams.get(s);r&&(e.pathname=new URL(r,e).pathname)}return e.href}function R(e,a,t,s,i){const r=new URL(t),l=new URL(a);if(s&&(r.searchParams.forEach((n,h)=>{for(const d of s){if(d.append&&!h.startsWith(d.append))continue;const f=d.append?h.replace(d.append,""):h;if(f.match(d.regexp)){l.searchParams.get(f)===null&&r.searchParams.delete(h);break}}}),l.searchParams.forEach((n,h)=>{for(const d of s){if(!h.match(d.regexp)||(e==null?void 0:e.searchParams.get(h))===n)continue;const f=d.append?d.append+h:h;r.searchParams.set(f,n);break}})),i!==null&&e){const n=w(e,l);n?r.searchParams.set(i,n):r.searchParams.delete(i)}return r}function S(e){return e.vIframe===!0&&e.uiNotification!==void 0}function v(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(null,"",t),a==="push"&&window.history.pushState(null,"",t)}}const p=document.createElement("template");p.innerHTML=`<style>
1
+ var H=Object.defineProperty;var x=(l,d,f)=>d in l?H(l,d,{enumerable:!0,configurable:!0,writable:!0,value:f}):l[d]=f;var n=(l,d,f)=>x(l,typeof d!="symbol"?d+"":d,f);(function(){"use strict";function l(e){return e[0]==="df-child"&&e[1]==="init"}function d(e){return e[0]==="df-child"&&e[1]==="height"}function f(e){return e[0]==="df-child"&&e[1]==="stateChange"}function m(e){return e[0]==="df-child"&&e[1]==="custom"}function b(e){return e[0]==="df-child"&&e[1]==="notif"}function y(e){return e[0]==="df-child"&&e[1]==="ready"}function w(e){return e.endsWith("/")?e:e===""?"/":e.slice(0,e.lastIndexOf("/")+1)}function E(e,a){if(a.origin!==e.origin)return a.href;if(a.pathname===e.pathname)return"";const t=w(e.pathname);return a.pathname.startsWith(t)?a.pathname.replace(t,"./"):a.pathname}const A=e=>e.replace(/[-[\]/{}()*+?.\\^$|]/g,"\\$&");function v(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 S(e,a,t,s){if(!t&&!s)return e.href;const i=new URL(a);if(t&&i.searchParams.forEach((r,u)=>{for(const h of t){if(h.append&&!u.startsWith(h.append)||u===s)continue;const o=h.append?u.replace(h.append,""):u;if(o.match(h.regexp)){e.searchParams.set(o,r);break}}}),s!==null){const r=i.searchParams.get(s);r&&(e.pathname=new URL(r,e).pathname)}return e.href}function C(e,a,t,s,i){const r=new URL(t),u=new URL(a);if(s&&(r.searchParams.forEach((h,o)=>{for(const c of s){if(c.append&&!o.startsWith(c.append))continue;const g=c.append?o.replace(c.append,""):o;if(g.match(c.regexp)){u.searchParams.get(g)===null&&r.searchParams.delete(o);break}}}),u.searchParams.forEach((h,o)=>{for(const c of s){if(!o.match(c.regexp)||(e==null?void 0:e.searchParams.get(o))===h)continue;const g=c.append?c.append+o:o;r.searchParams.set(g,h);break}})),i!==null&&e){const h=E(e,u);h?r.searchParams.set(i,h):r.searchParams.delete(i)}return r}function P(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 R{stateChange(a,t){a==="replace"&&window.history.replaceState(null,"",t),a==="push"&&window.history.pushState(null,"",t)}}const p=document.createElement("template");p.innerHTML=`<style>
2
2
  :host {
3
3
  display: block;
4
4
  }
5
+ .d-frame-wrapper {
6
+ height: 100%;
7
+ }
5
8
  iframe.d-frame-iframe {
6
9
  display: block;
7
10
  width: 100%;
8
11
  height: 100%;
9
12
  border: none;
10
13
  }
11
- </style><slot name="loader"></slot><iframe class="d-frame-iframe" frameborder="0">`;class C extends HTMLElement{constructor(){super();o(this,"adapter");o(this,"connected",!1);o(this,"initialSrc");o(this,"srcUrl");o(this,"parsedSyncParams");o(this,"iframeElement");o(this,"slotElement");o(this,"width");o(this,"aspectRatioHeight");o(this,"resizedHeight");o(this,"randomId");this.randomId=Math.random().toString(36).slice(-6);const t=p.content.cloneNode(!0);this.slotElement=t.childNodes[1],this.resize!=="yes"&&(this.slotElement.style.display="none"),this.iframeElement=t.childNodes[2],this.iframeElement.setAttribute("scrolling",this.resize==="yes"?"no":"auto"),this.iframeElement.setAttribute("loading",this.lazy?"lazy":"eager"),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=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 lazy(){return this.hasAttribute("lazy")}set lazy(t){t?this.setAttribute("lazy",""):this.removeAttribute("lazy")}get src(){return this.getAttribute("src")}set src(t){this.setAttribute("src",t)}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 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}]),this.init()),c(i)&&(this.resizedHeight=i[2],this.updateStyle()),g(i)){if(this.parsedSyncParams||this.syncPath){const r=R(this.srcUrl,i[3],window.location.href,this.parsedSyncParams,this.syncPath);r.href!==window.location.href&&this.adapter.stateChange(i[2],r)}this.stateChangeEvents&&this.dispatchEvent(new CustomEvent("state-change",{detail:[i[2],i[3]]}))}m(i)&&this.dispatchEvent(new CustomEvent("message",{detail:i[2]})),b(i)&&this.dispatchEvent(new CustomEvent("notif",{detail:i[2]}))}else S(i)&&this.dispatchEvent(new CustomEvent("notif",{detail:v(i.uiNotification)}))}}init(){this.initialSrc=this.src}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;this.srcUrl=new URL(this.src.startsWith("/")?window.location.origin+this.src:this.src);const t=z(this.srcUrl,window.location.href,this.parsedSyncParams,this.syncPath);this.initialSrc?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.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.resizedHeight?(this.log("debug","height of iframe based on resize message: "+this.resizedHeight),this.slotElement.style.display="none",t+=`height:${this.resizedHeight}px;`):this.height?(this.log("debug","height of iframe based on direct attribute: "+this.height),this.slotElement.style.display="none",t+=`height:${this.height};`):this.aspectRatio!=="auto"&&this.aspectRatio!==null?(this.log("debug","height of iframe based on aspect ratio: "+this.aspectRatioHeight),this.slotElement.style.display="none",t+=`height:${this.aspectRatioHeight}px;`):(this.log("debug","use slot element while waiting for resize message"),this.slotElement.style.display="block",t+="height:0;")),(this.resize==="no"||this.resize==="auto"&&!this.resizedHeight)&&(this.iframeElement.getAttribute("scrolling")!=="auto"&&(this.log("debug","set scrolling attribute of iframe: auto"),this.iframeElement.setAttribute("scrolling","auto")),this.height?(this.log("debug","height of iframe based on direct attribute: "+this.height),t+=`height:${this.height};`):this.aspectRatio!==null&&(this.log("debug","height of iframe based on aspect ratio: "+this.aspectRatioHeight),t+=`height:${this.aspectRatioHeight}px;`)),this.log("debug","set style attribute of iframe: "+t),this.iframeElement.setAttribute("style",t)}updateAspectRatioHeight(){this.width&&this.aspectRatio!==null&&(this.resizedHeight||this.height||(this.aspectRatioHeight=Math.ceil(this.width/this.actualAspectRatio),this.updateStyle()))}log(t,...s){t==="debug"&&!this.debug||(t==="debug"&&console.timeLog(`${this.id}:d-frame`,...s),t==="info"&&console.info(`${this.id}:d-frame`,...s))}connectedCallback(){if(this.debug&&console.time(`${this.id}:d-frame`),!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=E(this.syncParams||"*")),this.updateStyle(),this.updateSrc()}disconnectedCallback(){this.log("debug","disconnected"),this.debug&&console.timeEnd(`[${this.id}:d-frame]`)}static get observedAttributes(){return["src","aspect-ratio","height","sync-params","sync-path"]}attributeChangedCallback(t,s,i){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())}}customElements.define("d-frame",C)})();
14
+ </style><div class="d-frame-wrapper"><slot name="loading"><div style="min-height:150px;"></div></slot><iframe class="d-frame-iframe" frameborder="0" style="visibility:hidden;position:absolute;height:0px;"></iframe></div>`;class M extends HTMLElement{constructor(){super();n(this,"adapter");n(this,"connected",!1);n(this,"initialSrc");n(this,"srcUrl");n(this,"parsedSyncParams");n(this,"wrapperElement");n(this,"slotElement");n(this,"iframeElement");n(this,"width");n(this,"aspectRatioHeight");n(this,"resizedHeight");n(this,"randomId");n(this,"iframeLoaded",!1);n(this,"ready",!1);this.randomId=Math.random().toString(36).slice(-6);const t=p.content.cloneNode(!0);this.wrapperElement=t.childNodes[1],this.slotElement=this.wrapperElement.childNodes[0],this.iframeElement=this.wrapperElement.childNodes[1],this.iframeElement.setAttribute("scrolling",this.resize==="yes"?"no":"auto"),this.iframeElement.setAttribute("loading",this.lazy?"lazy":"eager"),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=new R,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 lazy(){return this.hasAttribute("lazy")}set lazy(t){t?this.setAttribute("lazy",""):this.removeAttribute("lazy")}get src(){return this.getAttribute("src")}set src(t){this.setAttribute("src",t)}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 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(l(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}]),this.init()),d(i)&&(this.resizedHeight=i[2],this.resize==="yes"&&!this.ready&&!this.readyMessage&&(this.ready=!0,this.dispatchEvent(new CustomEvent("ready"))),this.updateStyle()),f(i)){if(this.parsedSyncParams||this.syncPath){const r=C(this.srcUrl,i[3],window.location.href,this.parsedSyncParams,this.syncPath);r.href!==window.location.href&&this.adapter.stateChange(i[2],r)}this.stateChangeEvents&&this.dispatchEvent(new CustomEvent("state-change",{detail:[i[2],i[3]]}))}m(i)&&this.dispatchEvent(new CustomEvent("message",{detail:i[2]})),b(i)&&this.dispatchEvent(new CustomEvent("notif",{detail:i[2]})),y(i)&&(this.ready=!0,this.dispatchEvent(new CustomEvent("ready")),this.updateStyle())}else P(i)&&this.dispatchEvent(new CustomEvent("notif",{detail:z(i.uiNotification)}))}}init(){this.initialSrc=this.src}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;this.srcUrl=new URL(this.src.startsWith("/")?window.location.origin+this.src:this.src);const t=S(this.srcUrl,window.location.href,this.parsedSyncParams,this.syncPath);this.initialSrc?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()))}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))}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=v(this.syncParams||"*")),this.updateStyle(),this.updateSrc()}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"]}attributeChangedCallback(t,s,i){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())}}customElements.get("d-frame")||customElements.define("d-frame",M)})();
12
15
  //# sourceMappingURL=d-frame.min.js.map
@@ -1,2 +1,2 @@
1
- var VIframeCompatDFrameContent=function(){"use strict";var g=Object.defineProperty;var f=(h,s,d)=>s in h?g(h,s,{enumerable:!0,configurable:!0,writable:!0,value:d}):h[s]=d;var r=(h,s,d)=>f(h,typeof s!="symbol"?s+"":s,d);function h(n){return n[0]==="df-parent"&&n[1]==="init"}function s(n){return n[0]==="df-parent"&&n[1]==="updateSrc"}const d=["animationstart","webkitAnimationStart","animationiteration","webkitAnimationIteration","animationend","webkitAnimationEnd","input","mouseup","mousedown","orientationchange","afterprint","beforeprint","readystatechange","touchstart","touchend","touchcancel","transitionstart","webkitTransitionStart","MSTransitionStart","oTransitionStart","otransitionstart","transitioniteration","webkitTransitionIteration","MSTransitionIteration","oTransitionIteration","otransitioniteration","transitionend","webkitTransitionEnd","MSTransitionEnd","oTransitionEnd","otransitionend","resize"];class u{constructor(t){r(this,"initialized",!1);r(this,"options");r(this,"pendingCheckHeight",!1);r(this,"debug",!1);r(this,"id");r(this,"throttledCheckHeight");r(this,"lastHeight",0);this.options=t??{};const e=()=>{this.checkHeight(),this.pendingCheckHeight=!1};this.throttledCheckHeight=()=>{this.pendingCheckHeight||(this.pendingCheckHeight=!0,requestAnimationFrame(e))},!(typeof window>"u")&&(window.addEventListener("message",i=>this.onMessage(i)),this.postMessageToParent(["df-child","init"]))}log(t,...e){t==="debug"&&!this.debug||(t==="debug"&&console.timeLog(`${this.id}:d-frame-content`,...e),t==="info"&&console.info(`${this.id}:d-frame-content`,...e))}onMessage(t){if(t.source===window.parent&&Array.isArray(t.data)){const e=t.data;h(e)&&(this.id=e[2].id,this.debug=!!e[2].debug,this.debug&&console.time(`${this.id}:d-frame-content`),e[2].resize!=="no"&&this.initResize(),(e[2].syncParams||e[2].syncPath||e[2].stateChangeEvents)&&this.initStateChangeWatcher(),this.initialized=!0),s(e)&&(this.options.updateSrc?this.options.updateSrc(e[2].startsWith("/")?window.location.origin+e[2]:e[2]):window.location.href=e[2])}}postMessageToParent(t){window.parent.postMessage(t)}sendNotif(t){this.postMessageToParent(["df-child","notif",t])}sendMessage(t){this.postMessageToParent(["df-child","custom",t])}initResize(){this.log("debug","initResize"),this.checkHeight(),this.createMutationObserver(),this.createWindowEventListeners()}initStateChangeWatcher(){this.log("debug","initStateChangeWatcher");const t=window.history.replaceState,e=(...o)=>{const a=t.apply(window.history,o);return this.postMessageToParent(["df-child","stateChange","push",window.location.href]),a};window.history.pushState=e;const i=(...o)=>{const a=t.apply(window.history,o);return this.postMessageToParent(["df-child","stateChange","replace",window.location.href]),a};window.history.replaceState=i}createMutationObserver(){const t=document.querySelector("body");if(!t)throw new Error("DFrameContentManager was initialized before the HTML body");new window.MutationObserver(this.throttledCheckHeight).observe(t,{attributes:!1,attributeOldValue:!1,characterData:!1,characterDataOldValue:!1,childList:!0,subtree:!0})}createWindowEventListeners(){for(const t of d)window.addEventListener(t,this.throttledCheckHeight,{passive:!0})}checkHeight(){const t=document.querySelectorAll("[data-iframe-height]");let e=0;for(const i of t){const o=i.getAttribute("data-iframe-height"),a=i.getBoundingClientRect().bottom+parseFloat(getComputedStyle(i).getPropertyValue("margin-bottom"))+(o?parseFloat(o):0);a>e&&(e=a)}e=Math.ceil(e),e!==this.lastHeight&&(this.postMessageToParent(["df-child","height",e]),this.lastHeight=e)}}const c=new u({updateSrc:n=>{const t=window.vIframeOptions,e=t==null?void 0:t.reactiveParams;if(e){const i=new URL(n);if(i.origin===window.location.origin&&i.pathname===window.location.pathname){const o=Object.keys(e);i.searchParams.forEach((a,l)=>{e[l]=a,o.splice(o.indexOf(l),1)}),o.forEach(a=>{delete e[a]});return}}if(t!=null&&t.router){const i=window.location.origin+t.router.options.history.base;if(n.startsWith(i)){t.router.replace(n.replace(i,""));return}}window.location.href=n}});return window.dFrameContent=c,c}();
1
+ var VIframeCompatDFrameContent=function(){"use strict";var w=Object.defineProperty;var p=(r,a,h)=>a in r?w(r,a,{enumerable:!0,configurable:!0,writable:!0,value:h}):r[a]=h;var s=(r,a,h)=>p(r,typeof a!="symbol"?a+"":a,h);function r(n){return n[0]==="df-parent"&&n[1]==="init"}function a(n){return n[0]==="df-parent"&&n[1]==="updateSrc"}const h=["animationstart","webkitAnimationStart","animationiteration","webkitAnimationIteration","animationend","webkitAnimationEnd","input","mouseup","mousedown","orientationchange","afterprint","beforeprint","readystatechange","touchstart","touchend","touchcancel","transitionstart","webkitTransitionStart","MSTransitionStart","oTransitionStart","otransitionstart","transitioniteration","webkitTransitionIteration","MSTransitionIteration","oTransitionIteration","otransitioniteration","transitionend","webkitTransitionEnd","MSTransitionEnd","oTransitionEnd","otransitionend","resize"];class u{constructor(t){s(this,"initialized",!1);s(this,"options");s(this,"pendingCheckHeight",!1);s(this,"debug",!1);s(this,"id");s(this,"throttledCheckHeight");s(this,"lastHeight",0);this.options=t??{};const e=()=>{this.checkHeight(),this.pendingCheckHeight=!1};this.throttledCheckHeight=()=>{this.pendingCheckHeight||(this.pendingCheckHeight=!0,requestAnimationFrame(e))},!(typeof window>"u")&&(window.addEventListener("message",i=>this.onMessage(i)),this.postMessageToParent(["df-child","init"]))}log(t,...e){t==="debug"&&!this.debug||(t==="debug"&&console.timeLog(`d-frame:${this.id}:content`,...e),t==="info"&&console.info(`d-frame:${this.id}:content`,...e))}onMessage(t){if(t.source===window.parent&&Array.isArray(t.data)){const e=t.data;r(e)&&(this.id=e[2].id,this.debug=!!e[2].debug,this.debug&&console.time(`d-frame:${this.id}:content`),e[2].resize!=="no"&&this.initResize(),(e[2].syncParams||e[2].syncPath||e[2].stateChangeEvents)&&this.initStateChangeWatcher(),this.initialized=!0),a(e)&&(this.options.updateSrc?this.options.updateSrc(e[2].startsWith("/")?window.location.origin+e[2]:e[2]):window.location.href=e[2])}}postMessageToParent(t){window.parent.postMessage(t)}sendNotif(t){this.postMessageToParent(["df-child","notif",t])}sendMessage(t){this.postMessageToParent(["df-child","custom",t])}ready(){this.postMessageToParent(["df-child","ready"])}initResize(){this.log("debug","initResize"),this.checkHeight(),this.createMutationObserver(),this.createWindowEventListeners()}initStateChangeWatcher(){this.log("debug","initStateChangeWatcher");const t=window.history.replaceState,e=(...o)=>{const d=t.apply(window.history,o);return this.postMessageToParent(["df-child","stateChange","push",window.location.href]),d};window.history.pushState=e;const i=(...o)=>{const d=t.apply(window.history,o);return this.postMessageToParent(["df-child","stateChange","replace",window.location.href]),d};window.history.replaceState=i}createMutationObserver(){const t=document.querySelector("body");if(!t)throw new Error("DFrameContentManager was initialized before the HTML body");new window.MutationObserver(this.throttledCheckHeight).observe(t,{attributes:!1,attributeOldValue:!1,characterData:!1,characterDataOldValue:!1,childList:!0,subtree:!0})}createWindowEventListeners(){for(const t of h)window.addEventListener(t,this.throttledCheckHeight,{passive:!0})}checkHeight(){const t=document.querySelectorAll("[data-iframe-height]");let e=0,i=0;for(const o of t){const d=o.getAttribute("data-iframe-height"),c=o.getBoundingClientRect().bottom+parseFloat(getComputedStyle(o).getPropertyValue("margin-bottom")),f=d?c+parseFloat(d):c;c>e&&(e=c),f>i&&(i=f)}i=Math.ceil(i),e>0&&i!==this.lastHeight&&(this.postMessageToParent(["df-child","height",i]),this.lastHeight=i)}}const g=(n,t)=>{const e=Object.keys(n);t.forEach((i,o)=>{n[o]=i,e.splice(e.indexOf(o),1)}),e.forEach(i=>{delete n[i]})},l=new u({updateSrc:n=>{const t=window.vIframeOptions,e=t==null?void 0:t.reactiveParams;if(e&&typeof e=="object"){const i=new URL(n);if(i.origin===window.location.origin&&i.pathname===window.location.pathname){g(e,i.searchParams);return}}if(t!=null&&t.router){const i=window.location.origin+t.router.options.history.base;if(n.startsWith(i)){t.router.replace(n.replace(i,""));return}}window.location.href=n}});return window.dFrameContent=l,l}();
2
2
  //# sourceMappingURL=d-frame-content.min.js.map
@@ -16,6 +16,7 @@ export default class DFrameContent {
16
16
  private postMessageToParent;
17
17
  sendNotif(notif: Notif): void;
18
18
  sendMessage(msg: any): void;
19
+ ready(): void;
19
20
  private initResize;
20
21
  private initStateChangeWatcher;
21
22
  private createMutationObserver;
@@ -60,9 +60,9 @@ export default class DFrameContent {
60
60
  if (level === 'debug' && !this.debug)
61
61
  return;
62
62
  if (level === 'debug')
63
- console.timeLog(`${this.id}:d-frame-content`, ...args);
63
+ console.timeLog(`d-frame:${this.id}:content`, ...args);
64
64
  if (level === 'info')
65
- console.info(`${this.id}:d-frame-content`, ...args);
65
+ console.info(`d-frame:${this.id}:content`, ...args);
66
66
  }
67
67
  onMessage(e) {
68
68
  if (e.source === window.parent && Array.isArray(e.data)) {
@@ -71,7 +71,7 @@ export default class DFrameContent {
71
71
  this.id = message[2].id;
72
72
  this.debug = !!message[2].debug;
73
73
  if (this.debug)
74
- console.time(`${this.id}:d-frame-content`);
74
+ console.time(`d-frame:${this.id}:content`);
75
75
  if (message[2].resize !== 'no')
76
76
  this.initResize();
77
77
  if (message[2].syncParams || message[2].syncPath || message[2].stateChangeEvents)
@@ -97,6 +97,9 @@ export default class DFrameContent {
97
97
  sendMessage(msg) {
98
98
  this.postMessageToParent(['df-child', 'custom', msg]);
99
99
  }
100
+ ready() {
101
+ this.postMessageToParent(['df-child', 'ready']);
102
+ }
100
103
  initResize() {
101
104
  this.log('debug', 'initResize');
102
105
  this.checkHeight();
@@ -143,17 +146,20 @@ export default class DFrameContent {
143
146
  }
144
147
  checkHeight() {
145
148
  const elements = document.querySelectorAll('[data-iframe-height]');
149
+ let maxWithoutOffset = 0;
146
150
  let max = 0;
147
151
  for (const element of elements) {
148
152
  const dataAttribute = element.getAttribute('data-iframe-height');
149
- const bottom = element.getBoundingClientRect().bottom +
150
- parseFloat(getComputedStyle(element).getPropertyValue('margin-bottom')) +
151
- (dataAttribute ? parseFloat(dataAttribute) : 0);
153
+ const bottomWithoutOffset = element.getBoundingClientRect().bottom +
154
+ parseFloat(getComputedStyle(element).getPropertyValue('margin-bottom'));
155
+ const bottom = dataAttribute ? (bottomWithoutOffset + parseFloat(dataAttribute)) : bottomWithoutOffset;
156
+ if (bottomWithoutOffset > maxWithoutOffset)
157
+ maxWithoutOffset = bottomWithoutOffset;
152
158
  if (bottom > max)
153
159
  max = bottom;
154
160
  }
155
161
  max = Math.ceil(max);
156
- if (max !== this.lastHeight) {
162
+ if (maxWithoutOffset > 0 && max !== this.lastHeight) {
157
163
  this.postMessageToParent(['df-child', 'height', max]);
158
164
  this.lastHeight = max;
159
165
  }
@@ -24,17 +24,22 @@ export default class DFrameElement extends HTMLElement {
24
24
  set syncPath(value: string | null);
25
25
  get stateChangeEvents(): boolean;
26
26
  set stateChangeEvents(value: boolean);
27
+ get readyMessage(): boolean;
28
+ set readyMessage(value: boolean);
27
29
  adapter: StateChangeAdapter;
28
30
  private connected;
29
31
  private initialSrc;
30
32
  private srcUrl;
31
33
  private parsedSyncParams;
32
- private iframeElement;
34
+ private wrapperElement;
33
35
  private slotElement;
36
+ private iframeElement;
34
37
  private width;
35
38
  private aspectRatioHeight;
36
39
  private resizedHeight;
37
40
  private randomId;
41
+ private iframeLoaded;
42
+ private ready;
38
43
  get actualAspectRatio(): number;
39
44
  constructor();
40
45
  onMessage(e: MessageEvent): void;
@@ -1,5 +1,5 @@
1
1
  // this is a good doc about writing web components https://web.dev/articles/custom-elements-best-practices
2
- import { isCustomMessage, isHeightMessage, isInitChildMessage, isNotifMessage, isStateChangeMessage } from './messages.js';
2
+ import { isCustomMessage, isHeightMessage, isInitChildMessage, isNotifMessage, isReadyMessage, isStateChangeMessage } from './messages.js';
3
3
  import { parseSyncParams, getChildSrc, getParentUrl } from './utils/sync-params.js';
4
4
  import { isVIframeUiNotif, convertVIframeUiNotif } from './v-iframe-compat/ui-notif.js';
5
5
  class WindowStateChangeAdapter {
@@ -15,13 +15,16 @@ template.innerHTML = `<style>
15
15
  :host {
16
16
  display: block;
17
17
  }
18
+ .d-frame-wrapper {
19
+ height: 100%;
20
+ }
18
21
  iframe.d-frame-iframe {
19
22
  display: block;
20
23
  width: 100%;
21
24
  height: 100%;
22
25
  border: none;
23
26
  }
24
- </style><slot name="loader"></slot><iframe class="d-frame-iframe" frameborder="0">`;
27
+ </style><div class="d-frame-wrapper"><slot name="loading"><div style="min-height:150px;"></div></slot><iframe class="d-frame-iframe" frameborder="0" style="visibility:hidden;position:absolute;height:0px;"></iframe></div>`;
25
28
  export default class DFrameElement extends HTMLElement {
26
29
  get id() { return this.getAttribute('id') ?? this.randomId; }
27
30
  set id(value) {
@@ -97,18 +100,28 @@ export default class DFrameElement extends HTMLElement {
97
100
  else
98
101
  this.removeAttribute('state-change-events');
99
102
  }
103
+ get readyMessage() { return this.hasAttribute('ready-message'); }
104
+ set readyMessage(value) {
105
+ if (value)
106
+ this.setAttribute('ready-message', '');
107
+ else
108
+ this.removeAttribute('ready-message');
109
+ }
100
110
  adapter;
101
111
  /* internal state */
102
112
  connected = false;
103
113
  initialSrc;
104
114
  srcUrl;
105
115
  parsedSyncParams;
106
- iframeElement;
116
+ wrapperElement;
107
117
  slotElement;
118
+ iframeElement;
108
119
  width;
109
120
  aspectRatioHeight;
110
121
  resizedHeight;
111
122
  randomId;
123
+ iframeLoaded = false;
124
+ ready = false;
112
125
  get actualAspectRatio() {
113
126
  if (this.aspectRatio !== 'auto')
114
127
  return Number(this.aspectRatio);
@@ -124,12 +137,23 @@ export default class DFrameElement extends HTMLElement {
124
137
  super();
125
138
  this.randomId = Math.random().toString(36).slice(-6);
126
139
  const root = template.content.cloneNode(true);
127
- this.slotElement = root.childNodes[1];
128
- if (this.resize !== 'yes')
129
- this.slotElement.style.display = 'none';
130
- this.iframeElement = root.childNodes[2];
140
+ this.wrapperElement = root.childNodes[1];
141
+ this.slotElement = this.wrapperElement.childNodes[0];
142
+ this.iframeElement = this.wrapperElement.childNodes[1];
131
143
  this.iframeElement.setAttribute('scrolling', this.resize === 'yes' ? 'no' : 'auto');
132
144
  this.iframeElement.setAttribute('loading', this.lazy ? 'lazy' : 'eager');
145
+ this.iframeElement.addEventListener('load', () => {
146
+ if (this.iframeElement.getAttribute('src')) {
147
+ this.log('debug', 'iframe loaded');
148
+ this.iframeLoaded = true;
149
+ this.dispatchEvent(new CustomEvent('iframe-load'));
150
+ if (this.resize !== 'yes' && !this.readyMessage) {
151
+ this.ready = true;
152
+ this.dispatchEvent(new CustomEvent('ready'));
153
+ this.updateStyle();
154
+ }
155
+ }
156
+ });
133
157
  const shadowRoot = this.attachShadow({ mode: 'open' });
134
158
  shadowRoot.appendChild(root);
135
159
  const resizeObserver = new ResizeObserver((entries) => {
@@ -162,6 +186,10 @@ export default class DFrameElement extends HTMLElement {
162
186
  }
163
187
  if (isHeightMessage(message)) {
164
188
  this.resizedHeight = message[2];
189
+ if (this.resize === 'yes' && !this.ready && !this.readyMessage) {
190
+ this.ready = true;
191
+ this.dispatchEvent(new CustomEvent('ready'));
192
+ }
165
193
  this.updateStyle();
166
194
  }
167
195
  if (isStateChangeMessage(message)) {
@@ -181,6 +209,11 @@ export default class DFrameElement extends HTMLElement {
181
209
  if (isNotifMessage(message)) {
182
210
  this.dispatchEvent(new CustomEvent('notif', { detail: message[2] }));
183
211
  }
212
+ if (isReadyMessage(message)) {
213
+ this.ready = true;
214
+ this.dispatchEvent(new CustomEvent('ready'));
215
+ this.updateStyle();
216
+ }
184
217
  }
185
218
  else if (isVIframeUiNotif(message)) {
186
219
  // maintain compatibility with v-iframe notifications sent through postMessage
@@ -212,51 +245,48 @@ export default class DFrameElement extends HTMLElement {
212
245
  updateStyle() {
213
246
  if (!this.connected)
214
247
  return;
215
- let style = '';
248
+ // manage height of iframe wrapper
249
+ let wrapperHeight;
250
+ if (this.resizedHeight) {
251
+ this.log('debug', 'height of iframe based on resize message: ' + this.resizedHeight);
252
+ wrapperHeight = this.resizedHeight + 'px';
253
+ }
254
+ else {
255
+ if (this.height) {
256
+ this.log('debug', 'height of iframe based on direct attribute: ' + this.height);
257
+ wrapperHeight = this.height;
258
+ }
259
+ else if (this.aspectRatio !== null) {
260
+ this.log('debug', 'height of iframe based on aspect ratio: ' + this.aspectRatioHeight);
261
+ wrapperHeight = this.aspectRatioHeight + 'px';
262
+ }
263
+ }
264
+ if (wrapperHeight !== undefined) {
265
+ this.log('debug', 'set height iframe wrapper: ' + wrapperHeight);
266
+ this.wrapperElement.setAttribute('style', `height:${wrapperHeight};min-height:0;`);
267
+ }
268
+ else {
269
+ this.wrapperElement.setAttribute('style', '');
270
+ }
271
+ // set scrolling attribute of iframe
216
272
  if (this.resize === 'yes' || (this.resize === 'auto' && this.resizedHeight)) {
217
273
  if (this.iframeElement.getAttribute('scrolling') !== 'no') {
218
274
  this.log('debug', 'set scrolling attribute of iframe: no');
219
275
  this.iframeElement.setAttribute('scrolling', 'no');
220
276
  }
221
- if (this.resizedHeight) {
222
- this.log('debug', 'height of iframe based on resize message: ' + this.resizedHeight);
223
- this.slotElement.style.display = 'none';
224
- style += `height:${this.resizedHeight}px;`;
225
- }
226
- else {
227
- if (this.height) {
228
- this.log('debug', 'height of iframe based on direct attribute: ' + this.height);
229
- this.slotElement.style.display = 'none';
230
- style += `height:${this.height};`;
231
- }
232
- else if (this.aspectRatio !== 'auto' && this.aspectRatio !== null) {
233
- this.log('debug', 'height of iframe based on aspect ratio: ' + this.aspectRatioHeight);
234
- this.slotElement.style.display = 'none';
235
- style += `height:${this.aspectRatioHeight}px;`;
236
- }
237
- else {
238
- this.log('debug', 'use slot element while waiting for resize message');
239
- this.slotElement.style.display = 'block';
240
- style += 'height:0;';
241
- }
242
- }
243
277
  }
244
- if (this.resize === 'no' || (this.resize === 'auto' && !this.resizedHeight)) {
278
+ else {
245
279
  if (this.iframeElement.getAttribute('scrolling') !== 'auto') {
246
280
  this.log('debug', 'set scrolling attribute of iframe: auto');
247
281
  this.iframeElement.setAttribute('scrolling', 'auto');
248
282
  }
249
- if (this.height) {
250
- this.log('debug', 'height of iframe based on direct attribute: ' + this.height);
251
- style += `height:${this.height};`;
252
- }
253
- else if (this.aspectRatio !== null) {
254
- this.log('debug', 'height of iframe based on aspect ratio: ' + this.aspectRatioHeight);
255
- style += `height:${this.aspectRatioHeight}px;`;
256
- }
257
283
  }
258
- this.log('debug', 'set style attribute of iframe: ' + style);
259
- this.iframeElement.setAttribute('style', style);
284
+ // toggle loading slot vs iframe visibility
285
+ if (this.ready && this.iframeElement.getAttribute('style') !== '') {
286
+ this.log('debug', 'toggle loading slot and iframe visibility');
287
+ this.iframeElement.setAttribute('style', '');
288
+ this.slotElement.setAttribute('style', 'display:none;');
289
+ }
260
290
  }
261
291
  updateAspectRatioHeight() {
262
292
  if (!this.width)
@@ -274,15 +304,22 @@ export default class DFrameElement extends HTMLElement {
274
304
  if (level === 'debug' && !this.debug)
275
305
  return;
276
306
  if (level === 'debug')
277
- console.timeLog(`${this.id}:d-frame`, ...args);
278
- // if (level === 'debug') console.debug(`${this.id}:d-frame`, ...args)
307
+ console.timeLog(`d-frame:${this.id}`, ...args);
279
308
  if (level === 'info')
280
- console.info(`${this.id}:d-frame`, ...args);
309
+ console.info(`d-frame:${this.id}`, ...args);
281
310
  }
282
311
  /* standard custom element callbacks */
283
312
  connectedCallback() {
313
+ if (!this.debug) {
314
+ const globalDebug = window.localStorage.getItem('debug');
315
+ if (globalDebug) {
316
+ const debugParts = globalDebug.split(',');
317
+ if (debugParts.includes('d-frame') || debugParts.includes('d-frame:' + this.id))
318
+ this.debug = true;
319
+ }
320
+ }
284
321
  if (this.debug)
285
- console.time(`${this.id}:d-frame`);
322
+ console.time(`d-frame:${this.id}`);
286
323
  if (!this.hasAttribute('src'))
287
324
  throw new Error('src is a required attribute');
288
325
  this.log('debug', 'connected');
@@ -298,7 +335,7 @@ export default class DFrameElement extends HTMLElement {
298
335
  disconnectedCallback() {
299
336
  this.log('debug', 'disconnected');
300
337
  if (this.debug)
301
- console.timeEnd(`[${this.id}:d-frame]`);
338
+ console.timeEnd(`d-frame:${this.id}`);
302
339
  // TODO: more cleanup (resize observer, etc)
303
340
  }
304
341
  /* reflected attributes */
package/lib/d-frame.js CHANGED
@@ -1,2 +1,4 @@
1
1
  import DFrameElement from './DFrameElement.js';
2
- customElements.define('d-frame', DFrameElement);
2
+ if (!customElements.get('d-frame')) {
3
+ customElements.define('d-frame', DFrameElement);
4
+ }
package/lib/messages.d.ts CHANGED
@@ -3,7 +3,8 @@ export type HeightMessage = ['df-child', 'height', number];
3
3
  export type StateChangeMessage = ['df-child', 'stateChange', 'replace' | 'push', string];
4
4
  export type CustomMessage = ['df-child', 'custom', any];
5
5
  export type NotifMessage = ['df-child', 'notif', Notif];
6
- export type ChildMessage = InitChildMessage | HeightMessage | StateChangeMessage | CustomMessage | NotifMessage;
6
+ export type ReadyMessage = ['df-child', 'ready'];
7
+ export type ChildMessage = InitChildMessage | HeightMessage | StateChangeMessage | CustomMessage | NotifMessage | ReadyMessage;
7
8
  export type Notif = {
8
9
  type: 'default' | 'info' | 'success' | 'warning' | 'error';
9
10
  title: string;
@@ -14,14 +15,19 @@ export declare function isHeightMessage(message: any): message is HeightMessage;
14
15
  export declare function isStateChangeMessage(message: any): message is StateChangeMessage;
15
16
  export declare function isCustomMessage(message: any): message is CustomMessage;
16
17
  export declare function isNotifMessage(message: any): message is NotifMessage;
17
- export type InitParentMessage = ['df-parent', 'init', {
18
- id: string;
19
- debug?: boolean;
20
- resize: 'yes' | 'no' | 'auto';
21
- syncParams: boolean;
22
- syncPath: boolean;
23
- stateChangeEvents: boolean;
24
- }];
18
+ export declare function isReadyMessage(message: any): message is ReadyMessage;
19
+ export type InitParentMessage = [
20
+ 'df-parent',
21
+ 'init',
22
+ {
23
+ id: string;
24
+ debug?: boolean;
25
+ resize: 'yes' | 'no' | 'auto';
26
+ syncParams: boolean;
27
+ syncPath: boolean;
28
+ stateChangeEvents: boolean;
29
+ }
30
+ ];
25
31
  export type UpdateSrcMessage = ['df-parent', 'updateSrc', string];
26
32
  export type ParentMessage = InitParentMessage | UpdateSrcMessage;
27
33
  export declare function isInitParentMessage(message: any[]): message is InitParentMessage;
package/lib/messages.js CHANGED
@@ -13,6 +13,9 @@ export function isCustomMessage(message) {
13
13
  export function isNotifMessage(message) {
14
14
  return message[0] === 'df-child' && message[1] === 'notif';
15
15
  }
16
+ export function isReadyMessage(message) {
17
+ return message[0] === 'df-child' && message[1] === 'ready';
18
+ }
16
19
  export function isInitParentMessage(message) {
17
20
  return message[0] === 'df-parent' && message[1] === 'init';
18
21
  }
@@ -2,7 +2,7 @@ import DFrameContent from '../DFrameContent.js';
2
2
  import type { Router } from 'vue-router';
3
3
  export type VIframeOptions = {
4
4
  router?: Router;
5
- reactiveParams?: Record<string, string>;
5
+ reactiveParams?: Record<string, string> | boolean;
6
6
  };
7
7
  declare const dFrameContent: DFrameContent;
8
8
  export default dFrameContent;
@@ -1,19 +1,13 @@
1
1
  import DFrameContent from '../DFrameContent.js';
2
+ import { applySearchParams } from '../vue-reactive/util.js';
2
3
  const dFrameContent = new DFrameContent({
3
4
  updateSrc: (src) => {
4
5
  const vIframeOptions = window.vIframeOptions;
5
6
  const reactiveParams = vIframeOptions?.reactiveParams;
6
- if (reactiveParams) {
7
+ if (reactiveParams && typeof reactiveParams === 'object') {
7
8
  const srcUrl = new URL(src);
8
9
  if (srcUrl.origin === window.location.origin && srcUrl.pathname === window.location.pathname) {
9
- const existingKeys = Object.keys(reactiveParams);
10
- srcUrl.searchParams.forEach((value, key) => {
11
- reactiveParams[key] = value;
12
- existingKeys.splice(existingKeys.indexOf(key), 1);
13
- });
14
- existingKeys.forEach(key => {
15
- delete reactiveParams[key];
16
- });
10
+ applySearchParams(reactiveParams, srcUrl.searchParams);
17
11
  return;
18
12
  }
19
13
  }
@@ -0,0 +1,5 @@
1
+ import DFrameContent, { type DFrameContentOptions } from '../DFrameContent.js';
2
+ import type { Reactive } from 'vue';
3
+ type VueReactiveDFrameContentOptions = Omit<DFrameContentOptions, 'updateSrc'>;
4
+ export declare function VueReactiveDFrameContent(reactiveParams: Reactive<Record<string, string>>, options?: VueReactiveDFrameContentOptions): DFrameContent;
5
+ export default VueReactiveDFrameContent;
@@ -0,0 +1,17 @@
1
+ import DFrameContent from '../DFrameContent.js';
2
+ import { applySearchParams } from './util.js';
3
+ export function VueReactiveDFrameContent(reactiveParams, options) {
4
+ return new DFrameContent({
5
+ ...options,
6
+ updateSrc: (src) => {
7
+ const srcUrl = new URL(src);
8
+ if (srcUrl.origin === window.location.origin && srcUrl.pathname === window.location.pathname) {
9
+ applySearchParams(reactiveParams, srcUrl.searchParams);
10
+ }
11
+ else {
12
+ window.location.href = src;
13
+ }
14
+ }
15
+ });
16
+ }
17
+ export default VueReactiveDFrameContent;
@@ -0,0 +1,10 @@
1
+ import { type StateChangeAdapter } from '../DFrameElement.js';
2
+ import type { Reactive } from 'vue';
3
+ declare class VueReactiveDFrameStateChangeAdapter implements StateChangeAdapter {
4
+ reactiveParams: Reactive<Record<string, string>>;
5
+ constructor(reactiveParams: Reactive<Record<string, string>>);
6
+ stateChange(action: 'push' | 'replace', newUrl: URL): void;
7
+ onStateChange(callback: () => void): void;
8
+ }
9
+ declare const _default: (reactiveParams: Reactive<Record<string, string>>) => VueReactiveDFrameStateChangeAdapter;
10
+ export default _default;
@@ -0,0 +1,15 @@
1
+ import { watch } from 'vue';
2
+ import { applySearchParams } from './util.js';
3
+ class VueReactiveDFrameStateChangeAdapter {
4
+ reactiveParams;
5
+ constructor(reactiveParams) {
6
+ this.reactiveParams = reactiveParams;
7
+ }
8
+ stateChange(action, newUrl) {
9
+ applySearchParams(this.reactiveParams, newUrl.searchParams);
10
+ }
11
+ onStateChange(callback) {
12
+ watch(this.reactiveParams, callback);
13
+ }
14
+ }
15
+ export default (reactiveParams) => new VueReactiveDFrameStateChangeAdapter(reactiveParams);
@@ -0,0 +1 @@
1
+ export declare const applySearchParams: (reactiveParams: Record<string, string>, searchParams: URLSearchParams) => void;
@@ -0,0 +1,10 @@
1
+ export const applySearchParams = (reactiveParams, searchParams) => {
2
+ const existingKeys = Object.keys(reactiveParams);
3
+ searchParams.forEach((value, key) => {
4
+ reactiveParams[key] = value;
5
+ existingKeys.splice(existingKeys.indexOf(key), 1);
6
+ });
7
+ existingKeys.forEach(key => {
8
+ delete reactiveParams[key];
9
+ });
10
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@data-fair/frame",
3
- "version": "0.5.1",
3
+ "version": "0.7.0",
4
4
  "description": "An iframe wrapper for powerful web app integrations.",
5
5
  "main": "dist/frame.min.js",
6
6
  "directories": {
@@ -15,6 +15,7 @@
15
15
  "neostandard": "^0.11.9",
16
16
  "typescript": "^5.7.2",
17
17
  "vite": "^6.0.3",
18
+ "vue": "^3.5.13",
18
19
  "vue-router": "^4.5.0"
19
20
  },
20
21
  "scripts": {