UNPKG

@web-widget/container

Version:
3 lines (2 loc) 11.8 kB
const t="mounted",e="load-error",n="bootstrap-error",i="mount-error";var s=Object.freeze({__proto__:null,INITIAL:"initial",LOADING:"loading",LOADED:"loaded",BOOTSTRAPPING:"bootstrapping",BOOTSTRAPPED:"bootstrapped",MOUNTING:"mounting",MOUNTED:t,UPDATING:"updating",UNMOUNTING:"unmounting",UNLOADING:"unloading",LOAD_ERROR:e,BOOTSTRAP_ERROR:n,MOUNT_ERROR:i,UPDATE_ERROR:"update-error",UNMOUNT_ERROR:"unmount-error",UNLOAD_ERROR:"unload-error"});const o={load:{creator:!0,timeout:12e3,status:["initial","loading","loaded",e]},bootstrap:{pre:"load",timeout:4e3,status:["loaded","bootstrapping","bootstrapped",n]},mount:{pre:"bootstrap",timeout:3e3,status:["bootstrapped","mounting",t,i]},update:{verify:!0,timeout:3e3,status:[t,"updating",t,"update-error"]},unmount:{timeout:3e3,status:[t,"unmounting","bootstrapped","unmount-error"]},unload:{pre:"unmount",timeout:3e3,status:["bootstrapped","unloading","initial","unload-error"]}},r=Symbol("setState");class ApplicationService{constructor(t,e,n){this.timeouts=n,this.state="initial",this.lifecycles=Object.create(null),this.loader=t.bind(this.lifecycles),this.getDependencies=()=>("function"==typeof e&&(e=e()),e)}getState(){return this.state}[r](t){t!==this.state&&(this.state=t,this.stateChangeCallback())}stateChangeCallback(){}async trigger(t){const e=this.timeouts[t],n="number"==typeof e,i=o[t],[s,a,d,c]=i.status;if(!i)throw new Error(`Cannot ${t}`);if(this.pending&&await this.pending,i.creator&&!this.lifecycles[t]&&(this.lifecycles[t]=async t=>{let e=await this.loader(t);"function"==typeof e&&(e=e(t)),e||(e={}),Object.assign(this.lifecycles,e)}),s!==this.state&&i.pre&&await this.trigger(i.pre),[s,c].includes(this.state)){if(this[r](a),this.lifecycles[t])return this.pending=function(t,e,n,i=!1,s=1e3){return new Promise(((o,r)=>{const a=`Lifecycle function did not complete within ${n} ms: ${t}`;let d=!1,c=!1;function l(t){if(!d)if(!0===t)c=!0,i?r(new Error(a)):console.error(new Error(a));else if(!c){const e=t,i=e*s;console.warn(new Error(a)),i+s<n&&setTimeout((()=>l(e+1)),s)}}e().then((t=>{d=!0,o(t)})).catch((t=>{d=!0,r(t)})),i||setTimeout((()=>l(1)),s),setTimeout((()=>l(!0)),n)}))}(t,(async()=>this.lifecycles[t](this.getDependencies())),n?e:o[t].timeout,n,1e3).then((()=>{this[r](d),delete this.pending})).catch((t=>{throw this[r](c),delete this.pending,t})),this.pending;this[r](d)}else if(i.verify)throw new Error(`Cannot ${t}: Application state: ${this.state}`)}}function a(){const t=new Map;return{[Symbol("data")]:t,get:e=>t.get(e),define(e,n){t.set(e,n)}}}const d=HTMLScriptElement.supports&&HTMLScriptElement.supports("importmap");function c(t){return t.default||t}function l(t){return d||"function"!=typeof importShim?import(/* @vite-ignore */ /* webpackIgnore: true */t):importShim(t)}let u;const h="function"==typeof window.queueMicrotask?window.queueMicrotask.bind(window):t=>(u||(u=Promise.resolve())).then(t).catch((t=>setTimeout((()=>{throw t}),0)));var b=(t,e="")=>console.warn(`Web Widget: "${t}" API is about to be deprecated. ${e}`);const p=Symbol("context"),m=Symbol("createPortal");function g(t){return{mount:()=>t.mount(),update:e=>t.update(e),unmount:()=>t.unmount()}}class WebWidgetDependencies{constructor(t){Reflect.defineProperty(this,"ownerElement",{get:()=>t})}get container(){const t=this.ownerElement;return t.renderRoot||(t.renderRoot=t.createRenderRoot(),["mount","update","unmount"].forEach((e=>{t.renderRoot[e]||(t.renderRoot[e]=n=>t[e](n))}))),t.renderRoot}get context(){return b("context",'Please use "container" instead'),this[p]||(this[p]=g(this.ownerElement)),this[p]}get createPortal(){return b("createPortal"),this[m]||(this[m]=(t,e)=>{const n=this.ownerElement,i=n.constructor,s=i.portalDestinations.get(e),o=s?s():null;if(!o)throw new Error(`The portal cannot be found: ${e}`);if(!(o instanceof i))throw new Error(`Portal must be an instance of "HTMLWebWidgetElement": ${e}`);this.sandboxed&&!t.isConnected&&this.container.appendChild(t),t.slot||(t.slot="");const r=o.querySelector(`[slot="${t.slot}"]`);return r&&o.removeChild(r),o.appendChild(t),o.mount(),n.portals.push(o),g(o)}),this[m]}get data(){const t=this.ownerElement.data;return Array.isArray(t)?[...t]:{...t}}set data(t){this.ownerElement.data=t}get name(){return b("name"),this.ownerElement.name}get parameters(){return this.env}get env(){return[...this.ownerElement.attributes].reduce(((t,{name:e,value:n})=>(t[e]=n,t)),{})}get sandboxed(){b("sandboxed");const{sandboxed:t}=this.ownerElement;return t}}window.WebWidgetDependencies=WebWidgetDependencies;class WebWidgetSandbox{constructor(t){Reflect.defineProperty(this,"ownerElement",{get:()=>t})}unload(){}get window(){return null}}window.WebWidgetSandbox=WebWidgetSandbox;const f=Symbol("application"),w=Symbol("data"),y=Symbol("firstConnect"),E=Symbol("applicationService"),A=Symbol("moveing"),x=Symbol("parentWidget"),R=Symbol("statechangeCallback"),S=Symbol("throwGlobalError"),W=Symbol("timeouts"),T=Symbol("trigger"),O=Symbol("tryAutoLoad"),v=Symbol("tryAutoLoadTimer"),L=Symbol("tryAutoUnload"),C=Symbol("tryAutoUnloadTimer"),N=a(),D=a();let P=Object.create(null);const M=t=>!t.inactive,U=t=>t.isConnected&&(t.import||t.src||t.application||t.text),k=t=>M(t)&&U(t),I=M,$=new IntersectionObserver((t=>{t.forEach((({isIntersecting:t,target:e})=>{t&&k(e)&&(e[O](),$.unobserve(e))}))}),{rootMargin:"80%"});function j(t){!function(t,e){const n="web-widget";e([...t.querySelectorAll(`[is=${n}]`)].filter((t=>t.localName.includes("-")))),new MutationObserver((t=>{e(t.reduce(((t,{type:e,target:n,addedNodes:i})=>("attributes"===e?t.push(n):t.push(...i),t)),[]).filter((t=>t.nodeType===Node.ELEMENT_NODE&&t.localName.includes("-")&&t.getAttribute("is")===n)))})).observe(t,{attributeFilter:["is"],attributes:!0,childList:!0,subtree:!0})}(t,(t=>{t.forEach((t=>{const e=t.localName;if(!customElements.get(e)){customElements["define"](e,class extends HTMLWebWidgetElement{})}}))}))}class HTMLWebWidgetElement extends HTMLElement{constructor(){super();const t=this,e=new ApplicationService((function(e){if(!U(t))throw new Error("Cannot load: Not initialized");const{application:n}=t;if(t.sandbox=t.sandbox||t.sandboxed?t.createSandbox():null,t.renderRoot=null,t.loader=n||t.createLoader(),t.portals=[],t.sandboxed&&!t.sandbox.window)throw new Error("Sandbox mode is not implemented");return t.loader.call(this,e)}),(()=>{const t=this.createDependencies();return this.dependencies=t,t}),this.timeouts);e.stateChangeCallback=()=>{this[R](),this.dispatchEvent(new Event("statechange"))},this[E]=e}get application(){return this[f]||null}set application(t){"function"==typeof t&&(this[f]=t,this[O]())}get csp(){return b("csp"),this.getAttribute("csp")||""}set csp(t){b("csp"),this.setAttribute("csp",t)}get data(){if(!this[w]){const t=this.getAttribute("data");if(t)try{this[w]=JSON.parse(t)}catch(t){this[S](t),this[w]={}}else this[w]={...this.dataset}}return this[w]}set data(t){"object"==typeof t&&(this[w]=t)}get inactive(){return this.hasAttribute("inactive")}set inactive(t){t?this.setAttribute("inactive",""):this.removeAttribute("inactive")}get loading(){return this.getAttribute("loading")||"auto"}set loading(t){this.setAttribute("loading",t)}get type(){return this.getAttribute("type")||"module"}set type(t){this.setAttribute("type",t)}get state(){return this[E].getState()}get sandboxed(){return b("sandboxed"),this.hasAttribute("sandboxed")}set sandboxed(t){b("sandboxed"),t?this.setAttribute("sandboxed",""):this.removeAttribute("sandboxed")}get name(){return b("name"),this.getAttribute("name")||""}set name(t){b("name"),this.setAttribute("name",t)}get src(){const t=this.getAttribute("src");return null===t?"":new URL(t,this.baseURI).href}set src(t){this.setAttribute("src",t)}get import(){const t=this.getAttribute("import");return null===t?"":t}set import(t){this.setAttribute("import",t)}get rendertarget(){return this.getAttribute("rendertarget")||"shadow"}set rendertarget(t){this.setAttribute("rendertarget",t)}get text(){return b("text"),this.getAttribute("text")||""}set text(t){b("text"),this.setAttribute("text",t)}get timeouts(){return this[W]||(this[W]={...this.constructor.timeouts}),this[W]}set timeouts(t){this[W]=t}createDependencies(){return new WebWidgetDependencies(this)}createSandbox(){return b("createSandbox"),new WebWidgetSandbox(this)}createRenderRoot(){let t=null;const{sandboxed:e,sandbox:n}=this;if(e){const e=n.window.document,i=e.createElement("style");i.textContent="body{margin:0}",e.head.appendChild(i),t=e.body}else if("shadow"===this.rendertarget){if(this.hasAttribute("hydrateonly")&&this.attachInternals){t=this.attachInternals().shadowRoot}t||(t=this.attachShadow({mode:"open"})),j(t)}else"light"===this.rendertarget&&(t=this);return t}createLoader(){const{type:t}=this,e=this.constructor.loaders.get(t);if(!e)throw Error(`Loader is not defined: ${t}`);return()=>e(this)}async load(){await this[T]("load")}async bootstrap(){await this[T]("bootstrap")}async mount(){await this[T]("mount")}async update(t={}){const e=this.dependencies||{};Object.assign(e,t),await this[T]("update")}async unmount(){const t=this.portals||[];await this[T]("unmount"),await Promise.all(t.map((t=>t.unmount())))}async unload(){const t=this.portals||[],e=this.dependencies||{};await this[T]("unload"),await Promise.all(t.map((t=>t.unload()))),Object.getOwnPropertyNames(e).forEach((t=>{Reflect.deleteProperty(e,t)}))}connectedCallback(){this[y]?this[A]:(this.firstConnectedCallback(),this[y]=!0)}firstConnectedCallback(){if(this[x]()){const{sandboxed:t,csp:e}=this[x]();t&&(this.sandboxed=t),e&&(this.csp=e)}var t;"lazy"===this.loading?(t=this,$.observe(t)):this[O]()}disconnectedCallback(){this[A]=!0,h((()=>{this.isConnected||(this[A]=!1,this.destroyedCallback())}))}attributeChangedCallback(t){"data"===t?delete this[w]:"lazy"!==this.loading&&this[O]()}destroyedCallback(){var t;"lazy"===this.loading&&(t=this,$.unobserve(t)),this[L]()}[O](){this[v]=setTimeout((()=>{k(this)&&this.mount().catch(this[S].bind(this)),clearTimeout(this[v])}))}[L](){this[C]=setTimeout((()=>{I(this)&&(this.unload().catch(this[S].bind(this)),this.sandboxed&&this.sandbox.unload()),clearTimeout(this[C])}))}[T](t){return this[E].trigger(t,[this.dependencies])}[R](){const s=this.state;if(this.setAttribute("state",s),[t,e,n,i].includes(s)){let e,n;const i=s!==t;for(const t of this.children){const i=t.localName;"placeholder"===i?e=t:"fallback"===i&&(n=t)}e&&n?(e.hidden=i,n.hidden=!i):e?i||(e.hidden=!0):n&&(n.hidden=!i)}}[x](){const t=function(t,e){let n=t;do{if(n=n.getRootNode().host,n&&n instanceof e)return n}while(n);return null}(this,this.constructor);return t||null}[S](t){const e=`Web Widget application (${this.name||this.import||this.src||this.localName})`;"object"!=typeof t&&(t=new Error(t)),t.message.includes(e)||Reflect.defineProperty(t,"message",{value:`${e}: ${t.message}`,writable:!0,configurable:!0}),h((()=>{throw t}))}static get observedAttributes(){return["data","import","src","text","inactive"]}static get portalDestinations(){return b("portalDestinations"),N}static get loaders(){return D}static get timeouts(){return P}static set timeouts(t){P=t}}function _(){customElements.define("web-widget",HTMLWebWidgetElement),j(document)}Object.assign(HTMLWebWidgetElement,s),D.define("module",(async function(t){const{src:e,text:n,sandboxed:i}=t,s=t.import||e;if(i)throw new Error("The sandbox does not support ES module");if(s)return l(s).then(c);const o=new Blob([n],{type:"application/javascript"}),r=URL.createObjectURL(o);return l(r).then((t=>(URL.revokeObjectURL(r),c(t))),(t=>{throw URL.revokeObjectURL(r),t}))})),window.HTMLWebWidgetElement=HTMLWebWidgetElement,!1!==window.WEB_WIDGET_BOOTSTRAP&&_();export{HTMLWebWidgetElement,WebWidgetDependencies,WebWidgetSandbox,_ as bootstrap}; //# sourceMappingURL=main.js.map