@zeix/ui-element
Version:
UIElement - minimal reactive framework based on Web Components
2 lines (1 loc) • 21.8 kB
JavaScript
var M=(t)=>typeof t==="function",ft=(t,e)=>Object.prototype.toString.call(t)===`[object ${e}]`,dt=(t)=>(e)=>e instanceof t,nt=dt(Error),Ht=dt(Promise),T=(t)=>nt(t)?t:new Error(String(t)),F,E=new Set,Dt=0,I=new Map,V,bt=()=>{V=void 0;let t=Array.from(I.values());I.clear();for(let e of t)e()},Bt=()=>{if(V)cancelAnimationFrame(V);V=requestAnimationFrame(bt)};queueMicrotask(bt);var mt=(t)=>{if(F&&!t.includes(F))t.push(F)},K=(t)=>{for(let e of t)if(Dt)E.add(e);else e()},_t=()=>{while(E.size){let t=Array.from(E);E.clear();for(let e of t)e()}};var gt=(t,e)=>{let r=F;F=e;try{t()}finally{F=r}},ct=(t,e)=>new Promise((r,n)=>{let i=()=>{try{r(t())}catch(s){n(s)}};if(e)I.set(e,i);Bt()});function R(t,...e){let r=!1,n=()=>gt(()=>{if(r)throw new Error("Circular dependency in effect detected");r=!0;let i=St(e,t);if(nt(i))console.error("Unhandled error in effect:",i);r=!1},n);n()}var pt="Computed",Pt=(t,e)=>{if(!e)return!1;return t.name===e.name&&t.message===e.message},H=(t,...e)=>{let r=[],n=y,i,s=!0,a=!1,u=!1,o=(m)=>{if(!Object.is(m,n))n=m,s=!1,i=void 0,a=!1},g=()=>{a=y===n,n=y,i=void 0},h=(m)=>{let J=T(m);a=Pt(J,i),n=y,i=J},b=()=>{if(s=!0,!a)K(r)},w=()=>gt(()=>{if(u)throw new Error("Circular dependency in computed detected");a=!0,u=!0;let m=St(e,t);if(Ht(m))g(),m.then((J)=>{o(J),K(r)}).catch(h);else if(m==null||y===m)g();else if(nt(m))h(m);else o(m);u=!1},b),j={[Symbol.toStringTag]:pt,get:()=>{if(mt(r),_t(),s)w();if(i)throw i;return n},map:(m)=>H(m,j),match:(m)=>{return R(m,j),j}};return j},it=(t)=>ft(t,pt),yt="State",Mt=(t)=>{let e=[],r=t,n={[Symbol.toStringTag]:yt,get:()=>{return mt(e),r},set:(i)=>{if(Object.is(r,i))return;if(r=i,K(e),y===r)e.length=0},update:(i)=>{n.set(i(r))},map:(i)=>H(i,n),match:(i)=>{return R(i,n),n}};return n},$=(t)=>ft(t,yt),y=Symbol(),D=(t)=>$(t)||it(t),tt=(t)=>M(t)&&!t.length||typeof t==="object"&&t!==null&&("ok"in t)&&M(t.ok),wt=(t)=>D(t)?t:tt(t)?H(t):Mt(t),St=(t,e)=>{let{ok:r,nil:n,err:i}=M(e)?{ok:e}:e,s=[],a=[],u=!1;for(let g=0;g<t.length;g++){let h=t[g];try{let b=h.get();if(b===y)u=!0;s[g]=b}catch(b){a.push(T(b))}}let o=void 0;try{if(u&&n)o=n();else if(a.length)o=i?i(...a):a[0];else if(!u)o=r(...s)}catch(g){if(o=T(g),i)o=i(o)}return o},v=(t)=>typeof t==="function",et=(t)=>!!t&&typeof t==="object",X=(t)=>typeof t==="string",S=!1,Tt="debug";var O="warn",k="error",It=(t)=>t?`#${t}`:"",Kt=(t)=>t.length?`.${Array.from(t).join(".")}`:"",p=(t)=>`<${t.localName}${It(t.id)}${Kt(t.classList)}>`,C=(t)=>X(t)?`"${t}"`:et(t)?JSON.stringify(t):String(t),ut=(t)=>{if(t===null)return"null";if(typeof t!=="object")return typeof t;if(Array.isArray(t))return"Array";if(Symbol.toStringTag in Object(t))return t[Symbol.toStringTag];return t.constructor?.name||"Object"},f=(t,e,r=Tt)=>{if(S||[k,O].includes(r))console[r](e,t);return t},P=(t,e=[t])=>{let r={host:t,targets:e,on:(n,i)=>{return e.forEach((s,a)=>{let u;if(v(i))u=i.length===2?i(s,a):i;else if(et(i)&&v(i.handleEvent))u=i;else{f(i,`Invalid listener provided for ${n} event on element ${p(s)}`,k);return}s.addEventListener(n,u),t.cleanup.push(()=>s.removeEventListener(n,u))}),r},emit:(n,i)=>{return e.forEach((s)=>{s.dispatchEvent(new CustomEvent(n,{detail:i,bubbles:!0}))}),r},pass:(n)=>{return e.forEach(async(i,s)=>{if(await l.registry.whenDefined(i.localName),i instanceof l){let a;if(v(n)&&n.length===2)a=n(i,s);else if(et(n))a=n;else{f(n,"Invalid passed signals provided",k);return}Object.entries(a).forEach(([u,o])=>{if(X(o))if(o in t.signals)i.set(u,t.signals[o]);else f(o,`Invalid string key "${o}" for state ${C(u)}`,O);else try{i.set(u,wt(o))}catch(g){f(g,`Invalid source for state ${C(u)}`,O)}})}else f(i,"Target is not a UIElement",k)}),r},sync:(...n)=>{return e.forEach((i,s)=>n.forEach((a)=>a(t,i,s))),r}};return r},Ct="context-request";class qt extends Event{context;callback;subscribe;constructor(t,e,r=!1){super(Ct,{bubbles:!0,composed:!0});this.context=t,this.callback=e,this.subscribe=r}}var $t=(t)=>{let e=t.constructor,r=e.consumedContexts||[];queueMicrotask(()=>{for(let i of r)t.dispatchEvent(new qt(i,(s)=>t.set(String(i),s??x)))});let n=e.providedContexts||[];if(!n.length)return!1;return t.addEventListener(Ct,(i)=>{let{context:s,callback:a}=i;if(!n.includes(s)||!v(a))return;i.stopPropagation(),a(t.signals[String(s)])}),!0},x=Symbol(),jt=(t)=>v(t)&&!!t.length,ht=(t)=>v(t)&&!!t.length,rt=(t)=>v(t)?rt(t()):D(t)?rt(t.get()):t,kt=(t,e,r,n)=>{let i=t.init[e];return jt(i)?i(r,t,n):r??void 0};class l extends HTMLElement{static registry=customElements;static localName;static observedAttributes;static consumedContexts;static providedContexts;static define(t=this.localName){try{if(this.registry.define(t,this),S)f(t,"Registered custom element")}catch(e){f(e,`Failed to register custom element ${t}`,k)}return this}init={};signals={};cleanup=[];self=P(this);get root(){return this.shadowRoot||this}debug=!1;attributeChangedCallback(t,e,r){if(r===e||it(this.signals[t]))return;let n=kt(this,t,r,e);if(S&&this.debug)f(r,`Attribute "${t}" of ${p(this)} changed from ${C(e)} to ${C(r)}, parsed as <${ut(n)}> ${C(n)}`);this.set(t,n??x)}connectedCallback(){if(S){if(this.debug=this.hasAttribute("debug"),this.debug)f(this,"Connected")}for(let[t,e]of Object.entries(this.init)){if(this.constructor.observedAttributes?.includes(t))continue;let r=jt(e)?e(this.getAttribute(t),this):tt(e)?H(e):e;this.set(t,r??x,!1)}$t(this)}disconnectedCallback(){if(this.cleanup.forEach((t)=>t()),this.cleanup=[],S&&this.debug)f(this,"Disconnected")}adoptedCallback(){if(S&&this.debug)f(this,"Adopted")}has(t){return t in this.signals}get(t){let e=rt(this.signals[t]);if(S&&this.debug)f(e,`Get current value of Signal ${C(t)} in ${p(this)}`);return e}set(t,e,r=!0){if(e==null){f(e,`Attempt to set State ${C(t)} to null or undefined in ${p(this)}`,k);return}let n,i=this.signals[t],s=i?.get();if(!(t in this.signals)){if(ht(e)){f(e,`Cannot use updater function to create a Computed in ${p(this)}`,k);return}if(S&&this.debug)n="Create Signal of type";this.signals[t]=wt(e)}else if(r||s===y||s===x){if(tt(e)){f(e,`Cannot use computed callbacks to update Signal ${C(t)} in ${p(this)}`,k);return}if(D(e)){if(S&&this.debug)n="Replace";if(this.signals[t]=e,$(i))i.set(y)}else if($(i)){if(S&&this.debug)n="Update State of type";i.set(ht(e)?e(s):e)}else{f(e,`Computed ${C(t)} in ${p(this)} cannot be set`,O);return}}else return;if(S&&this.debug)f(e,`${n} ${ut(e)} ${C(t)} in ${p(this)}`)}delete(t){if(S&&this.debug)f(t,`Delete Signal ${C(t)} from ${p(this)}`);return delete this.signals[t]}first(t){let e=this.root.querySelector(t);if(this.shadowRoot&&!e)e=this.querySelector(t);return P(this,e?[e]:[])}all(t){let e=this.root.querySelectorAll(t);if(this.shadowRoot&&!e.length)e=this.querySelectorAll(t);return P(this,Array.from(e))}}var te=(t,e)=>{if(e==null)return;let r=t(e);return Number.isFinite(r)?r:void 0};var z=(t)=>t!=="false"&&t!=null,Q=(t=0)=>(e)=>te(parseInt,e)??t;var xt=(t="")=>(e)=>e??t;var W={a:"attribute ",c:"class ",h:"inner HTML",p:"property ",s:"style property ",t:"text content"},ee=(t,e,r,n)=>X(t)?e.get(t):D(t)?t.get():v(t)?t(r,n):x,re=(t)=>{if(/^(mailto|tel):/i.test(t))return!0;if(t.includes("://"))try{let e=new URL(t,window.location.origin);return["http:","https:","ftp:"].includes(e.protocol)}catch(e){return!1}return!0},ne=(t,e,r)=>{if(/^on/i.test(e))throw new Error(`Unsafe attribute: ${e}`);if(r=String(r).trim(),!re(r))throw new Error(`Unsafe URL for ${e}: ${r}`);t.setAttribute(e,r)},L=(t,e)=>(r,n,i)=>{let{op:s,read:a,update:u}=e,o=a(n);if(X(t)&&!it(r.signals[t])){let h=X(o)?kt(r,t,o):o;if(h!=null)r.set(t,h,!1)}let g=(h,b,w="element")=>f(h,`Failed to ${b} ${w} ${p(n)} in ${p(r)}`,k);R(()=>{let h=x;try{h=ee(t,r,n,i)}catch(b){g(b,"update");return}if(h===x)h=o;if(h===y)h=e.delete?null:o;if(e.delete&&h===null){let b="";ct(()=>{return b=e.delete(n),!0},[n,s]).then(()=>{f(n,`Deleted ${W[s]+b} of ${p(n)} in ${p(r)}`)}).catch((w)=>{g(w,"delete",`${W[s]+b} of`)})}else if(h!=null){let b=a(n);if(Object.is(h,b))return;let w="";ct(()=>{return w=u(n,h),!0},[n,s]).then(()=>{f(n,`Updated ${W[s]+w} of ${p(n)} in ${p(r)}`)}).catch((j)=>{g(j,"update",`${W[s]+w} of`)})}})};var d=(t)=>L(t,{op:"t",read:(e)=>e.textContent,update:(e,r)=>{return Array.from(e.childNodes).filter((n)=>n.nodeType!==Node.COMMENT_NODE).forEach((n)=>n.remove()),e.append(document.createTextNode(r)),""}}),c=(t,e=t)=>L(e,{op:"p",read:(r)=>(t in r)?r[t]:y,update:(r,n)=>{return r[t]=n,String(t)}}),q=(t,e=t)=>L(e,{op:"a",read:(r)=>r.getAttribute(t),update:(r,n)=>{return ne(r,t,n),t},delete:(r)=>{return r.removeAttribute(t),t}}),Y=(t,e=t)=>L(e,{op:"a",read:(r)=>r.hasAttribute(t),update:(r,n)=>{return r.toggleAttribute(t,n),t}}),U=(t,e=t)=>L(e,{op:"c",read:(r)=>r.classList.contains(t),update:(r,n)=>{return r.classList.toggle(t,n),t}});var vt=(t,e,r)=>L(t,{op:"h",read:(n)=>(n.shadowRoot||!e?n:null)?.innerHTML??"",update:(n,i)=>{if(!i){if(n.shadowRoot)n.shadowRoot.innerHTML="<slot></slot>";return""}if(e&&!n.shadowRoot)n.attachShadow({mode:e});let s=n.shadowRoot||n;if(s.innerHTML=i,!r)return"";return s.querySelectorAll("script").forEach((a)=>{let u=document.createElement("script");u.appendChild(document.createTextNode(a.textContent??"")),s.appendChild(u),a.remove()})," with scripts"}});class zt extends l{static localName="hello-world";connectedCallback(){this.first("span").sync(d("name")),this.first("input").on("input",(t)=>{this.set("name",t.target?.value||x)})}}zt.define();class Yt extends l{static localName="my-counter";static observedAttributes=["count"];init={count:Q()};connectedCallback(){super.connectedCallback(),this.first(".increment").on("click",()=>{this.set("count",(t)=>++t)}),this.first(".decrement").on("click",()=>{this.set("count",(t)=>--t)}),this.first(".count").sync(d("count")),this.first(".parity").sync(d(()=>this.get("count")%2?"odd":"even"))}}Yt.define();class Jt extends l{static localName="my-slider";init={active:0};connectedCallback(){super.connectedCallback();let t=this.querySelectorAll(".slide").length,e=(n)=>()=>{this.set("active",(i)=>(i+n+t)%t)};this.first(".prev").on("click",e(-1)),this.first(".next").on("click",e(1));let r=(n,i)=>this.get("active")===i;this.all(".slide").sync(U("active",r)),this.all(".dots span").sync(U("active",r))}}Jt.define();class Qt extends l{static localName="input-button";static observedAttributes=["disabled"];init={disabled:z};connectedCallback(){super.connectedCallback(),this.first("button").sync(c("disabled")),this.first(".label").sync(d("label")),this.first(".badge").sync(d("badge"))}}Qt.define();class Ut extends l{static localName="input-checkbox";static observedAttributes=["checked"];init={checked:z};connectedCallback(){super.connectedCallback(),this.first("input").sync(c("checked")).on("change",(t)=>{this.set("checked",t.target?.checked)}),this.self.sync(Y("checked"))}}Ut.define();class Ft extends l{static localName="input-radiogroup";static observedAttributes=["value"];init={value:xt()};connectedCallback(){super.connectedCallback(),this.self.sync(q("value")),this.all("input").on("change",(e)=>{this.set("value",e.target?.value)});let t=(e)=>this.get("value")===e.querySelector("input")?.value;this.all("label").sync(U("selected",t))}}Ft.define();var st=(t)=>typeof t==="number",ie=(t)=>!t||t==="false"?"false":"true",Z=(t,e=!1,r=0)=>{let n=e?parseInt(t,10):parseFloat(t);return Number.isFinite(n)?n:r};class Lt extends l{static observedAttributes=["value","description"];init={value:(t,e)=>e.isNumber?Z(t,e.isInteger,0):t??"",length:0,empty:()=>this.get("length")===0,error:"",ariaInvalid:()=>ie(this.get("error")),"aria-errormessage":()=>this.get("error")?this.querySelector(".error")?.id:y};isNumber=!1;isInteger=!1;input=null;step=1;min=0;max=100;connectedCallback(){if(super.connectedCallback(),this.input=this.querySelector("input"),this.isNumber=(this.input&&this.input.type==="number")??!1,this.isInteger=this.hasAttribute("integer"),this.input&&this.isNumber)this.step=Z(this.input.step,this.isInteger,1),this.min=Z(this.input.min,this.isInteger,0),this.max=Z(this.input.max,this.isInteger,100);if(this.set("length",this.input?.value.length??0),this.first("input").on("change",()=>{this.#t(this.isNumber?this.input?.valueAsNumber??0:this.input?.value??"")}).on("input",()=>{this.set("length",this.input?.value.length??0)}),this.isNumber)this.first("input").on("keydown",(r)=>{let n=r;if(["ArrowUp","ArrowDown"].includes(n.key)){if(r.stopPropagation(),r.preventDefault(),n.key==="ArrowDown")this.stepDown(n.shiftKey?this.step*10:this.step);if(n.key==="ArrowUp")this.stepUp(n.shiftKey?this.step*10:this.step)}});this.first(".error").sync(d("error")),this.first("input").sync(c("ariaInvalid"),q("aria-errormessage"));let t=this.querySelector(".description");if(t){let r=this.input?.maxLength,n=r&&t.dataset.remaining,i=t.textContent??"";this.set("description",n?()=>{let s=this.get("length");return s?n.replace("${x}",String(r-s)):i}:i),this.set("aria-describedby",()=>this.get("description")?t.id:y),this.first(".description").sync(d("description")),this.first("input").sync(q("aria-describedby"))}let e=this.querySelector(".spinbutton");if(this.isNumber&&e)this.first(".decrement").on("click",(r)=>{this.stepDown(r.shiftKey?this.step*10:this.step)}).sync(c("disabled",()=>st(this.min)&&(this.get("value")??0)-this.step<this.min)),this.first(".increment").on("click",(r)=>{this.stepUp(r.shiftKey?this.step*10:this.step)}).sync(c("disabled",()=>st(this.max)&&(this.get("value")??0)+this.step>this.max));this.first(".clear").on("click",()=>{this.clear(),this.input?.focus()}).sync(c("hidden","empty")),R(()=>{let r=this.get("value"),n=this.getAttribute("validate");if(r&&n)fetch(`${n}?name=${this.input?.name}value=${this.input?.value}`).then(async(i)=>{let s=await i.text();this.input?.setCustomValidity(s),this.set("error",s)}).catch((i)=>this.set("error",i.message));if(this.isNumber&&!st(r))return this.set("value",Z(r,this.isInteger,0));if(this.input&&this.isNumber&&Number.isFinite(r))this.input.value=String(r)})}clear(){if(this.set("value",""),this.set("length",0),this.input)this.input.value="",this.input.focus()}stepUp(t=this.step){if(this.isNumber)this.#t((e)=>this.#e(e+t))}stepDown(t=this.step){if(this.isNumber)this.#t((e)=>this.#e(e-t))}#t=(t)=>{if(this.set("value",t),this.set("error",this.input?.validationMessage??""),typeof t==="function")t=this.get("value");if(this.input?.value!==String(t))this.self.emit("value-change",t)};#e=(t)=>{let e=Math.round((this.max-this.min)/this.step),r=Math.round((t-this.min)*e/(this.max-this.min))/e;r=Math.min(Math.max(r,0),1);let n=r*(this.max-this.min)+this.min;return this.isInteger?Math.round(n):n}}Lt.define("input-field");class Gt extends l{static localName="code-block";static observedAttributes=["collapsed"];init={collapsed:z};connectedCallback(){let t=this.querySelector("code");if(t)this.first(".copy").on("click",async(e)=>{let r=e.currentTarget,n=r.textContent??"",i="success";try{await navigator.clipboard.writeText(t.textContent??"")}catch(s){console.error("Error when trying to use navigator.clipboard.writeText()",s),i="error"}r.set("disabled",!0),r.set("label",this.getAttribute(`copy-${i}`)??n),setTimeout(()=>{r.set("disabled",!1),r.set("label",n)},i==="success"?1000:3000)}),this.first(".overlay").on("click",()=>this.set("collapsed",!1)),this.self.sync(Y("collapsed"))}}Gt.define();class At extends l{static localName="tab-list";static observedAttributes=["accordion"];init={active:0,accordion:z};connectedCallback(){super.connectedCallback();let t=()=>{let e=Array.from(this.querySelectorAll("details"));for(let r=0;r<e.length;r++)if(e[r].hasAttribute("open"))return r;return 0};this.set("active",t()),this.self.sync(Y("accordion")),this.all("menu button").on("click",(e,r)=>()=>{this.set("active",r)}).sync(c("ariaPressed",(e,r)=>String(this.get("active")===r))),this.all("details").sync(c("open",(e,r)=>this.get("active")===r),q("aria-disabled",()=>String(!this.get("accordion")))),this.all("summary").sync(U("visually-hidden",()=>!this.get("accordion")))}}At.define();class Nt extends l{static localName="lazy-load";init={src:(t)=>{if(!t)return this.set("error","No URL provided in src attribute"),"";else if((this.parentElement||this.getRootNode().host)?.closest(`${this.localName}[src="${t}"]`))return this.set("error","Recursive loading detected"),"";let e=new URL(t,location.href);if(e.origin===location.origin)return e.toString();return this.set("error","Invalid URL origin"),""},content:async()=>{if(!this.get("src"))return"";try{let e=await fetch(this.get("src"));if(this.querySelector(".loading")?.remove(),e.ok)return e.text();else this.set("error",e.statusText)}catch(e){this.set("error",e.message)}return""},error:""};connectedCallback(){super.connectedCallback(),this.first(".error").sync(c("hidden",()=>!this.get("error")),d("error")),this.self.sync(vt("content"))}}Nt.define();var lt="media-motion",B="media-theme",G="media-viewport",Xt="media-orientation",_=(t,e)=>{let r=t?.trim();if(!r)return e;let n=r.match(/em$/)?"em":"px",i=parseFloat(r);return Number.isFinite(i)?i+n:e};class Rt extends l{static localName="media-context";static providedContexts=[lt,B,G,Xt];connectedCallback(){super.connectedCallback();let t="light",e="dark",r="xs",n="sm",i="md",s="lg",a="xl",u="landscape",o="portrait",h=(()=>({sm:_(this.getAttribute(n),"32em"),md:_(this.getAttribute(i),"48em"),lg:_(this.getAttribute(s),"72em"),xl:_(this.getAttribute(a),"108em")}))(),b=matchMedia("(prefers-reduced-motion: reduce)"),w=matchMedia("(prefers-color-scheme: dark)"),j=matchMedia(`(min-width: ${h.sm})`),m=matchMedia(`(min-width: ${h.md})`),J=matchMedia(`(min-width: ${h.lg})`),at=matchMedia(`(min-width: ${h.xl})`),ot=matchMedia("(orientation: landscape)"),A=()=>{if(at.matches)return a;if(J.matches)return s;if(m.matches)return i;if(j.matches)return n;return r};this.set(lt,b.matches),this.set(B,w.matches?e:t),this.set(G,A()),this.set(Xt,ot.matches?u:o),b.addEventListener("change",(N)=>this.set(lt,N.matches)),w.addEventListener("change",(N)=>this.set(B,N.matches?e:t)),j.addEventListener("change",()=>this.set(G,A())),m.addEventListener("change",()=>this.set(G,A())),J.addEventListener("change",()=>this.set(G,A())),at.addEventListener("change",()=>this.set(G,A())),ot.addEventListener("change",(N)=>this.set(B,N.matches?u:o))}}Rt.define();class Zt extends l{static localName="todo-app";init={tasks:[],total:()=>this.get("tasks").length,completed:()=>this.get("tasks").filter((t)=>t.get("checked")).length,active:()=>{let t=this.get("tasks");return t.length-t.filter((e)=>e.get("checked")).length},filter:()=>this.querySelector("input-radiogroup")?.get("value")??"all"};connectedCallback(){super.connectedCallback();let t=()=>{this.set("tasks",this.all("input-checkbox").targets)};t();let e=this.querySelector("input-field");this.first("form").on("submit",(r)=>{r.preventDefault(),queueMicrotask(()=>{let n=e?.get("value").toString().trim();if(n){let i=this.querySelector("ol"),s=this.querySelector("template")?.content.cloneNode(!0),a=s.querySelector("span");if(i&&s&&a)a.textContent=n,i.appendChild(s);t(),e?.clear()}})}),this.first(".submit").pass({disabled:()=>e?.get("empty")??!0}),this.first("ol").sync(q("filter","filter")).on("click",(r)=>{let n=r.target;if(n.localName==="button")n.closest("li")?.remove(),t()}),this.first(".count").sync(d("active")),this.first(".singular").sync(c("hidden",()=>(this.get("active")??0)>1)),this.first(".plural").sync(c("hidden",()=>this.get("active")===1)),this.first(".remaining").sync(c("hidden",()=>!this.get("active"))),this.first(".all-done").sync(c("hidden",()=>!!this.get("active"))),this.first(".clear-completed").on("click",()=>{this.get("tasks").filter((r)=>r.get("checked")).forEach((r)=>r.parentElement?.remove()),t()}).pass({disabled:()=>!this.get("completed")})}}Zt.define();var se=(t)=>typeof t==="number"&&Number.isInteger(t)&&t>0?String(t):"";class Wt extends l{static localName="product-catalog";connectedCallback(){this.first("input-button").pass({badge:()=>se(this.all("spin-button").targets.reduce((t,e)=>t+e.get("value"),0))})}}Wt.define();class Et extends l{static localName="spin-button";static observedAttributes=["value"];init={value:Q(),zero:()=>this.get("value")===0};connectedCallback(){super.connectedCallback();let t=this.getAttribute("zero-label")||"Add to Cart",e=this.getAttribute("increment-label")||"Increment",r=Q(9)(this.getAttribute("max")),n=(i=1)=>()=>{this.set("value",(s)=>s+i)};this.first(".value").sync(d("value"),c("hidden","zero")),this.first(".decrement").on("click",n(-1)).sync(c("hidden","zero")),this.first(".increment").on("click",n()).sync(d(()=>this.get("zero")?t:"+"),c("ariaLabel",()=>this.get("zero")?t:e),Y("disabled",()=>this.get("value")>=r))}}Et.define();class Vt extends l{static localName="rating-stars";static observedAttributes=["value"];init={value:Q()};connectedCallback(){super.connectedCallback(),this.all("input").on("change",(t,e)=>(r)=>{r.stopPropagation(),this.set("value",e+1),this.self.emit("change-rating",e+1)}).sync(q("checked",(t,e)=>String(this.get("value")===e+1))),this.all(".label").sync(d((t,e)=>e<this.get("value")?"★":"☆"))}}Vt.define();class Ot extends l{static localName="rating-feedback";init={rating:0,empty:!0,submitted:!1};connectedCallback(){super.connectedCallback(),this.self.on("change-rating",(e)=>{this.set("rating",e.detail)}).on("submit",(e)=>{e.preventDefault(),this.set("submitted",!0),console.log("Feedback submitted")}),this.first(".hide").on("click",()=>{let e=this.querySelector(".feedback");if(e)e.hidden=!0}),this.first("textarea").on("input",(e)=>{this.set("empty",e.target?.value.trim()==="")});let t=this.querySelector("rating-stars");this.first(".feedback").sync(c("hidden",()=>this.get("submitted")||!(t?.get("value")??0))),this.all(".feedback p").sync(c("hidden",(e,r)=>t?.get("value")!==r+1)),this.first("input-button").pass({disabled:"empty"})}}Ot.define();