-
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathfacet.min.js
2 lines (2 loc) · 5.74 KB
/
facet.min.js
1
2
// Facet v0.1.2a | https://github.com/kgscialdone/facet
const facet=new function(){this.version="0.1.2a";this.defineComponent=function defineComponent(tagName,template,{shadowMode:shadowMode="closed",observeAttrs:observeAttrs=[],applyMixins:applyMixins=[],localFilters:localFilters={},extendsElement:extendsElement,formAssoc:formAssoc=false}){const extendsConstr=extendsElement?document.createElement(extendsElement).constructor:HTMLElement;const extendsOptions=extendsElement?{extends:extendsElement}:undefined;window.customElements.define(tagName,class FacetComponent extends extendsConstr{static observedAttributes=observeAttrs;static formAssociated=formAssoc;#root=shadowMode!=="none"?this.attachShadow({mode:shadowMode}):this;#localFilters={...localFilters};constructor(){super();if(formAssoc){let internals=this.attachInternals(),value;Object.defineProperties(this,{internals:{value:internals,writable:false},value:{get:()=>value,set:newValue=>internals.setFormValue(value=newValue)},name:{get:()=>this.getAttribute("name")},form:{get:()=>internals.form},labels:{get:()=>internals.labels},validity:{get:()=>internals.validity},validationMessage:{get:()=>internals.validationMessage},willValidate:{get:()=>internals.willValidate},setFormValue:{value:(n,s)=>internals.setFormValue(value=n,s),writable:false},setValidity:{value:internals.setValidity.bind(internals),writable:false},checkValidity:{value:internals.checkValidity.bind(internals),writable:false},reportValidity:{value:internals.reportValidity.bind(internals),writable:false}})}}connectedCallback(){const content=template.content.cloneNode(true);const mixins=Object.values(facet.mixins).filter((m=>m.applyGlobally||applyMixins.includes(m.name)));for(let mixin of mixins){content[mixin.attachPosition](mixin.template.content.cloneNode(true));Object.assign(this.#localFilters,mixin.localFilters)}for(let script of content.querySelectorAll("script[on]")){let parent=script.parentElement??this;let handler=new Function("host","root","event",script.innerText).bind(parent,this,this.#root);for(let event of script.getAttribute("on").split(/\s+/g))parent.addEventListener(event,handler,{once:script.hasAttribute("once"),capture:script.hasAttribute("capture"),...script.hasAttribute("passive")?{passive:true}:{}});script.remove()}for(let el of content.querySelectorAll("[inherit]")){for(let attr of el.getAttribute("inherit").split(/\s+/g)){const[,ogname,rename,fn]=attr.match(/^([^\/>"'=]+)(?:>([^\/>"'=]+))?(?:\/(\w+))?$/);const cv=this.getAttribute(ogname),filter=this.#localFilters[fn]?.bind(this,this,this.#root)??window[fn];if(cv)el.setAttribute(rename??ogname,filter?.(cv,undefined,el,this)??cv);if(observeAttrs.includes(ogname))this.addEventListener("attributeChanged",(({detail:{name:name,oldValue:oldValue,newValue:newValue}})=>{if(name!==ogname)return;el.setAttribute(rename??ogname,filter?.(newValue,oldValue,el,this)??newValue)}))}el.removeAttribute("inherit")}if(formAssoc)this.value=this.getAttribute("value");this.#root.append(content);this.#event("connect")}disconnectedCallback(){this.#event("disconnect")}adoptedCallback(){this.#event("adopt")}attributeChangedCallback(name,oldValue,newValue){this.#event("attributeChanged",{name:name,oldValue:oldValue,newValue:newValue})}formAssociatedCallback(form){this.#event("formAssociate",{form:form})}formDisabledCallback(disabled){this.#event("formDisable",{disabled:disabled})}formResetCallback(){this.#event("formReset")}formStateRestoreCallback(state,mode){this.#event("formStateRestore",{state:state,mode:mode})}#event(n,d={}){this.dispatchEvent(new CustomEvent(n,{detail:{...d,component:this}}))}},extendsOptions)};this.defineMixin=function defineMixin(name,template,options){this.mixins[name]={...options,name:name,template:template}};this.discoverDeclarativeComponents=function discoverDeclarativeComponents(root){let mixinSelector=`template[${facet.config.namespace}mixin]:not([defined])`;let cmpntSelector=`template[${facet.config.namespace}component]:not([defined])`;if(root.matches?.(mixinSelector))processMixin(root);if(root.matches?.(cmpntSelector))processComponent(root);for(let template of root.querySelectorAll(mixinSelector))processMixin(template);for(let template of root.querySelectorAll(cmpntSelector))processComponent(template);function processMixin(template){template.setAttribute("defined",true);facet.defineMixin(template.getAttribute(`${facet.config.namespace}mixin`),template,{applyGlobally:template.hasAttribute("global"),attachPosition:template.hasAttribute("prepend")?"prepend":"append",localFilters:discoverLocalFilters(template)})}function processComponent(template){template.setAttribute("defined",true);facet.defineComponent(template.getAttribute(`${facet.config.namespace}component`),template,{shadowMode:template.getAttribute("shadow")?.toLowerCase()??facet.config.defaultShadowMode,observeAttrs:template.getAttribute("observe")?.split(/\s+/g)??[],applyMixins:template.getAttribute("mixins")?.split(/\s+/g)??[],localFilters:discoverLocalFilters(template),extendsElement:template.getAttribute("extends"),formAssoc:template.hasAttribute("forminput")})}function discoverLocalFilters(template){return[...template.content.querySelectorAll("script[filter]")].map((script=>{script.remove();return[script.getAttribute("filter"),new Function("host","root","value",script.innerText)]})).reduce(((a,[k,v])=>{a[k]=v;return a}),{})}};this.mixins={};this.config={namespace:document.currentScript?.hasAttribute?.("namespace")?document.currentScript.getAttribute("namespace")||"facet-":"",autoDiscover:document.currentScript&&!document.currentScript.hasAttribute("libonly"),defaultShadowMode:document.currentScript?.getAttribute("shadow")??"closed"};(fn=>document.readyState==="interactive"?fn():document.addEventListener("DOMContentLoaded",fn,{once:true}))((()=>this.config.autoDiscover&&this.discoverDeclarativeComponents(document)))};