@occluze/tether 0.3.6 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,7 +19,7 @@ An open-source, free alternative to Smootify and Storesynk (formerly Shopyflow):
19
19
  - **Optional CMS sync:** a Webflow CMS item per Shopify product, kept up to date automatically ([one-click deploy](#sync-shopify-products-to-the-webflow-cms-optional)).
20
20
  - **Hand-over ready:** loading, error and not-found states, `Tether.diagnose()`, error reporting.
21
21
 
22
- MIT licensed · ~60 KB · no dependencies · [full reference](docs/reference.md) · [comparison](docs/comparison.md) · [changelog](CHANGELOG.md)
22
+ MIT licensed · 17 KB gzipped · no dependencies · TypeScript types · [full reference](docs/reference.md) · [comparison](docs/comparison.md) · [changelog](CHANGELOG.md)
23
23
 
24
24
  ---
25
25
 
@@ -45,11 +45,13 @@ Site settings → Custom code → **Head**:
45
45
  productPath: '/product', // your Webflow product template
46
46
  };
47
47
  </script>
48
- <script src="https://cdn.jsdelivr.net/gh/ravi-klaassens/tether@0.3/dist/tether.min.js" defer></script>
48
+ <script src="https://cdn.jsdelivr.net/gh/ravi-klaassens/tether@0.4/dist/tether.min.js" defer></script>
49
49
  ```
50
50
 
51
- **Versions:** `@0.3` gets every 0.3.x fix automatically (recommended), `@v0.3.6` pins one release,
52
- `@latest` always takes the newest.
51
+ **Versions:** `@0.4` gets every 0.4.x fix automatically (recommended), `@v0.4.0` pins one release,
52
+ `@latest` always takes the newest. Hosting the file yourself? Put `tether.markets.min.js` and
53
+ `tether.diagnose.min.js` next to it: those optional parts load only when a page uses markets or
54
+ `Tether.diagnose()`.
53
55
 
54
56
  ## 3. Add attributes in the Designer
55
57
 
@@ -117,9 +119,10 @@ npm run smoke # live test against Shopify's public demo store
117
119
  npm run build
118
120
  ```
119
121
 
120
- Bundlers: `npm install @occluze/tether`, then `import Tether from "@occluze/tether"`.
122
+ Bundlers: `npm install @occluze/tether`, then `import Tether from "@occluze/tether"` (TypeScript
123
+ types included; markets and diagnose are split into their own chunks).
121
124
  JavaScript API, config, releases and the Shopify API version policy are in the [reference](docs/reference.md).
122
125
 
123
126
  ## License
124
127
 
125
- MIT © Ravi Klaassens
128
+ MIT © Ravi Klaassens · [occluze.com](https://occluze.com)
@@ -0,0 +1 @@
1
+ import{B as f,C as o,D as l,E as T,F as H,G as m,H as K,I as g,J as $,K as vt,L as A,M as h,N as V,O as q,P as R,R as C,S as yt,T as _,U as wt,V as W,W as It,X as U,Y as At,Z as $t,_ as G,a as p,aa as Et,ba as k,d as Q,e as pt,f as I,g as et,j as M,k as it,l as st,o as F,q as ft,r as mt,s as x,t as N,u as L,v as nt,w as gt,x as at,y as bt,z as j}from"./chunk-LI3YDMGF.js";function Tt(s,t=1,e={}){let i=typeof s=="object"&&s!==null?s:{variantId:s,quantity:t,...e},n=x.variant(i.merchandiseId||i.variantId||i.id);if(!n)throw new et("add(): variantId is required");let a={merchandiseId:n,quantity:Math.max(1,parseInt(i.quantity??1,10)||1)},r=i.sellingPlanId||i.sellingPlan;r&&(a.sellingPlanId=x.sellingPlan(r));let u=U(i.attributes);return u.length&&(a.attributes=u),a}function Ct(s,t,e){return`mutation Tether_${s}(${t}){${s}(${e}){cart{...TetherCart}userErrors{field message}}}${st()}`}var _t='a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])',Y=null,Ot=s=>m(s,_t).filter(t=>t.offsetParent!==null||t===document.activeElement);function rt(s){m(document,o("cart-open")).forEach(t=>t.setAttribute("aria-expanded",String(s))),m(document,o("cart-drawer")).forEach(t=>{t.hasAttribute("role")||t.setAttribute("role","dialog"),!t.hasAttribute("aria-label")&&!t.hasAttribute("aria-labelledby")&&t.setAttribute("aria-label",l(t,"cart-label")||"Cart"),t.setAttribute("aria-modal",String(s)),t.classList.contains(p.cartDrawerOpenClass)||t.setAttribute("aria-hidden","true")})}var ot=s=>/does not exist|not found|invalid id/i.test(s?.message||""),Pt={state:null,_chain:Promise.resolve(),id(){try{return localStorage.getItem(p.storageKey)}catch{return null}},_setId(s){try{s?localStorage.setItem(p.storageKey,s):localStorage.removeItem(p.storageKey)}catch{}},get lines(){return this.state?.lines?.nodes||[]},get count(){return this.state?.totalQuantity||0},lastError:null,_queue(s){let t=this._chain.then(s,s).then(e=>(this.lastError&&(this.lastError=null,this.render()),e),e=>{throw this.lastError=e,this.render(),g("cart-error",{error:e}),e});return this._chain=t.catch(()=>{}),t},_commit(s,t){return this.state=s,s?.id&&this._setId(s.id),this.render(),g("cart-updated",{cart:s,reason:t}),s},async init(){let s=this.id();if(!s)return this.state=null,this.render(),null;try{let t=await M(`query TetherCart($id:ID!){cart(id:$id){...TetherCart}}${st()}`,{id:s});t.cart?this.state=t.cart:(this._setId(null),this.state=null)}catch(t){I(t,"cart load failed"),this.lastError=t,ot(t)&&this._setId(null),this.state=null}return this.render(),this.state},async _create(s={}){let t=p.country?{countryCode:String(p.country).toUpperCase()}:void 0,e=await M(Ct("cartCreate","$input: CartInput!","input: $input"),{input:{buyerIdentity:t,...s}});return it(e.cartCreate,"cartCreate").cart},async _mutate(s,t,e,i,n){let a=this.id();if(!a)return n?this._create(n):null;try{let r=await M(Ct(s,`$cartId: ID!, ${t}`,`cartId: $cartId, ${e}`),{...i,cartId:a});return it(r[s],s).cart}catch(r){if(n&&ot(r))return Q("cart expired, creating a new one"),this._setId(null),this._create(n);throw r}},add(s,t=1,e={}){let i=(Array.isArray(s)?s:[s]).map(n=>Tt(n,t,e));return this._queue(async()=>{let n=await this._mutate("cartLinesAdd","$lines: [CartLineInput!]!","lines: $lines",{lines:i},{lines:i});return this._commit(n,"add"),g("added",{cart:n,lines:i}),p.openCartOnAdd&&this.open(),n})},updateLine(s,t){let e=typeof t=="number"?{quantity:t}:{...t};if(e.quantity!==void 0&&e.quantity<=0)return this.removeLine(s);let i={id:s};return e.quantity!==void 0&&(i.quantity=e.quantity),"sellingPlanId"in e&&(i.sellingPlanId=e.sellingPlanId?x.sellingPlan(e.sellingPlanId):null),e.attributes&&(i.attributes=U(e.attributes)),(e.merchandiseId||e.variantId)&&(i.merchandiseId=x.variant(e.merchandiseId||e.variantId)),this._queue(async()=>this._commit(await this._mutate("cartLinesUpdate","$lines: [CartLineUpdateInput!]!","lines: $lines",{lines:[i]}),"update"))},removeLine(s){let t=Array.isArray(s)?s:[s];return this._queue(async()=>this._commit(await this._mutate("cartLinesRemove","$lineIds: [ID!]!","lineIds: $lineIds",{lineIds:t}),"remove"))},clear(){let s=this.lines.map(t=>t.id);return s.length?this.removeLine(s):Promise.resolve(this.state)},setNote(s){return this._queue(async()=>this._commit(await this._mutate("cartNoteUpdate","$note: String!","note: $note",{note:s??""},{note:s??""}),"note"))},setAttributes(s){let t=new Map((this.state?.attributes||[]).map(i=>[i.key,i.value]));U(s).forEach(i=>t.set(i.key,i.value));let e=[...t].filter(([,i])=>i!=="").map(([i,n])=>({key:i,value:n}));return this._queue(async()=>this._commit(await this._mutate("cartAttributesUpdate","$attributes: [AttributeInput!]!","attributes: $attributes",{attributes:e},{attributes:e}),"attributes"))},setDiscountCodes(s){let t=(Array.isArray(s)?s:[s]).map(e=>String(e).trim()).filter(Boolean);return this._queue(async()=>this._commit(await this._mutate("cartDiscountCodesUpdate","$discountCodes: [String!]!","discountCodes: $discountCodes",{discountCodes:t},{discountCodes:t}),"discount"))},applyDiscount(s){let t=(this.state?.discountCodes||[]).map(e=>e.code);return this.setDiscountCodes([...new Set([...t,s])])},removeDiscount(s){return this.setDiscountCodes((this.state?.discountCodes||[]).map(t=>t.code).filter(t=>t!==s))},setBuyerIdentity(s,{create:t=!0}={}){return this._queue(async()=>{let e=await this._mutate("cartBuyerIdentityUpdate","$buyerIdentity: CartBuyerIdentityInput!","buyerIdentity: $buyerIdentity",{buyerIdentity:s},t?{buyerIdentity:s}:null).catch(i=>{if(t||!ot(i))throw i;return this._setId(null),null});return this._commit(e,"buyer-identity")})},async checkout(s=p.checkoutTarget){let t=this.id();if(!t)return null;let e=s==="_blank"?window.open("","_blank"):null;if(e)try{e.opener=null}catch{}try{let n=(await M("query TetherCheckout($id: ID!) { cart(id: $id) { checkoutUrl } }",{id:t})).cart?.checkoutUrl;if(!n)throw new et("No checkoutUrl (cart empty or expired)");return g("checkout",{url:n,cart:this.state}),e&&!e.closed?e.location.href=n:window.location.href=n,n}catch(i){return e&&e.close(),I(i,"checkout failed"),null}},drawers(){return m(document,o("cart-drawer"))},isOpen(){return this.drawers().some(s=>s.classList.contains(p.cartDrawerOpenClass))},open(){if(this.isOpen())return;let s=this.drawers().filter(t=>l(t,"cart-drawer")!=="manual");s.forEach(t=>{t.classList.add(p.cartDrawerOpenClass),t.setAttribute("aria-hidden","false")}),rt(!0),p.cartFocus!==!1&&s[0]&&(Y=document.activeElement,setTimeout(()=>{let t=Ot(s[0])[0]||s[0];t===s[0]&&!s[0].hasAttribute("tabindex")&&(s[0].tabIndex=-1),t.focus?.({preventScroll:!0})},60)),typeof p.onCartOpen=="function"&&p.onCartOpen(s),g("cart-toggled",{open:!0})},close(){if(!this.isOpen())return;let s=this.drawers(),t=s.some(e=>e.contains(document.activeElement));s.forEach(e=>{e.classList.remove(p.cartDrawerOpenClass),e.setAttribute("aria-hidden","true")}),rt(!1),t&&Y?.isConnected&&Y.focus({preventScroll:!0}),Y=null,typeof p.onCartClose=="function"&&p.onCartClose(s),g("cart-toggled",{open:!1})},toggle(){this.isOpen()?this.close():this.open()},render(){let s=this.state,t=s?s.totalQuantity:0,e=a=>s?$(s.cost?.[a]):"";rt(this.isOpen()),m(document,o("cart-count")).forEach(a=>V(a,t)),m(document,o("cart-subtotal")).forEach(a=>V(a,e("subtotalAmount"))),m(document,o("cart-total")).forEach(a=>V(a,e("totalAmount"))),m(document,o("cart-checkout-charge")).forEach(a=>V(a,e("checkoutChargeAmount")));let i=this.lines.some(a=>a.sellingPlanAllocation),n={"cart-empty":t===0,"cart-filled":t>0,"cart-has-subscription":i,"cart-no-subscription":!i,"cart-has-discount":(s?.discountCodes||[]).some(a=>a.applicable),"cart-error":!!this.lastError};m(document,o("show")).forEach(a=>{let r=l(a,"show");r in n&&!a.closest(o("product"))&&q(a,n[r])}),m(document,`textarea${o("cart-note")},input${o("cart-note")}`).forEach(a=>{document.activeElement!==a&&(a.value=s?.note||"")}),m(document,o("cart-discounts")).forEach(a=>{C(a,s?.discountCodes||[],(r,u)=>{r.setAttribute(f("discount-code"),u.code);let b=r.querySelector(o("discount","code"))||(r.firstElementChild?null:r);b&&h(b,u.code),r.classList.toggle("is-inapplicable",!u.applicable)})}),m(document,o("cart-lines")).forEach(a=>{yt(a,this.lines,r=>r.id,(r,u)=>Ft(r,u),{onEnter:p.onLineEnter,onLeave:p.onLineLeave})}),s&&_("cart")}};function Dt(s,t){let e=s.merchandise||{},i=s.sellingPlanAllocation?.sellingPlan;switch(t){case"title":return e.product?.title;case"product-title":return e.product?.title;case"variant-title":return e.title==="Default Title"?"":e.title;case"options":return(e.selectedOptions||[]).filter(n=>n.value!=="Default Title").map(n=>`${n.name}: ${n.value}`).join(", ");case"vendor":return e.product?.vendor;case"sku":return e.sku;case"price":return $(s.cost?.amountPerQuantity||e.price);case"compare-at-price":return $(s.cost?.compareAtAmountPerQuantity||e.compareAtPrice);case"line-total":return $(s.cost?.totalAmount);case"line-subtotal":return $(s.cost?.subtotalAmount);case"quantity":return s.quantity;case"plan":return i?.name||"";case"plan-description":return i?.description||"";case"components":return(s.lineComponents||[]).map(n=>`${n.quantity} \xD7 ${n.merchandise?.product?.title||""}`).join(", ");default:if(t.startsWith("attribute:")){let n=t.slice(10);return(s.attributes||[]).find(a=>a.key===n)?.value||""}return}}function Ft(s,t){let e=t.merchandise||{},i=!!t.sellingPlanAllocation;s.setAttribute(f("line-id"),t.id),s.classList.toggle("is-subscription",i),m(s,o("line")).forEach(a=>{let r=l(a,"line");if(r==="image")return A(a,e.image?.url||e.product?.featuredImage?.url,e.product?.title);if(r==="url")return a.setAttribute("href",H(e.product?.handle,e.product?.id));let u=Dt(t,r);u!==void 0&&V(a,u)});let n={subscription:i,"one-time":!i,"on-sale":parseFloat(t.cost?.compareAtAmountPerQuantity?.amount)>parseFloat(t.cost?.amountPerQuantity?.amount),"has-components":(t.lineComponents||[]).length>0};m(s,o("line-show")).forEach(a=>{let r=l(a,"line-show");r in n&&q(a,n[r])}),m(s,`select${o("line-plan")}`).forEach(a=>{let r=e.product?.handle;r&&F(r).then(u=>{let b=N(u),O=[...!u.requiresSellingPlan&&l(a,"line-plan")!=="subscription-only"?[{value:"",label:a.getAttribute(f("one-time-label"))||"One-time purchase"}]:[],...b.map(E=>({value:E.id,label:E.name}))],D=O.map(E=>E.value).join("|");a.dataset.tetherSig!==D&&(a.innerHTML="",O.forEach(E=>{let v=document.createElement("option");v.value=E.value,v.textContent=E.label,a.appendChild(v)}),a.dataset.tetherSig=D),a.value=t.sellingPlanAllocation?.sellingPlan?.id||"",q(a,b.length>0)}).catch(u=>I(u,"line plan options"))})}var z=new WeakMap,St=()=>o("product");function Vt(s,t){let e=t.indexOf("."),i=t.slice(0,e),n=t.slice(e+1);return(s.metafields||[]).find(r=>r&&r.namespace===i&&r.key===n)||null}var J=class{constructor(t,e){this.root=t,this.product=e,this.selected={},this.variant=null,this.quantity=Math.max(0,parseInt(l(t,"quantity")??"1",10)||(T(t,"quantity")?0:1)),this.plans=N(e),this.purchase="one-time",this.planId=null,z.set(t,this),t.setAttribute(f("state"),"ready"),t.removeAttribute(f("error")),this.initSelection(),this.initPurchase(),this.renderProduct(),this.bind(),this.renderVariant(),wt(t,"product"),_("product"),g("product-ready",{product:e,scope:this},t)}update(t){let e=this.variant?.id;this.product=t,this.plans=N(t),this.planId&&!this.plans.some(n=>n.id===this.planId)&&(this.planId=this.plans[0]?.id||null),!this.plans.length&&this.purchase==="subscription"&&(this.purchase="one-time");let i=t.variants.nodes.find(n=>n.id===e);i&&(this.selected={},i.selectedOptions.forEach(n=>{this.selected[n.name]=n.value})),this.root.setAttribute(f("state"),"ready"),this.root.removeAttribute(f("error")),this.renderProduct(),this.renderVariant(),_("product"),g("product-updated",{product:t,scope:this},this.root)}$(t){let e=K(this.root,t,St());return this.root.matches(t)?[this.root,...e]:e}initSelection(){let t=this.product.variants.nodes,e=t.find(n=>n.availableForSale)||t[0];e&&e.selectedOptions.forEach(n=>{this.selected[n.name]=n.value});let i=new URLSearchParams(window.location.search).get("variant")||l(this.root,"variant");if(i){let n=x.variant(i),a=t.find(r=>r.id===n);a&&(this.selected={},a.selectedOptions.forEach(r=>{this.selected[r.name]=r.value}))}}initPurchase(){if(!this.plans.length)return;let t=new URLSearchParams(window.location.search),e=j(this.product,t.get("selling_plan")),i=j(this.product,l(this.root,"default-plan"));this.planId=(e||i||this.plans[0]).id;let n=e?"subscription":l(this.root,"default-purchase")||p.defaultPurchase;this.purchase=this.product.requiresSellingPlan||n==="subscription"?"subscription":"one-time"}findVariant(){return this.product.variants.nodes.find(t=>t.selectedOptions.every(e=>this.selected[e.name]===e.value))||null}isValueAvailable(t,e){return this.product.variants.nodes.some(i=>i.availableForSale&&i.selectedOptions.every(n=>n.name===t?n.value===e:this.selected[n.name]===n.value))}get plan(){return this.plans.find(t=>t.id===this.planId)||null}get subscriptionAvailable(){return!!(this.variant&&this.plans.some(t=>L(this.variant,t.id)))}get isSubscription(){return this.purchase==="subscription"&&!!L(this.variant,this.planId)}getLine(){if(!this.variant)return null;let t={merchandiseId:this.variant.id,quantity:this.quantity};this.isSubscription&&(t.sellingPlanId=this.planId);let e=this.collectAttributes();return e.length&&(t.attributes=e),t}collectAttributes(){let t=U(It(this.root,"line-attributes")),e=this.$(o("line-attribute")).map(i=>{let n=l(i,"line-attribute"),a;return i.type==="checkbox"?a=i.checked?i.value&&i.value!=="on"?i.value:"Yes":"":i.type==="radio"?a=i.checked?i.value:null:a=i.value,a==null||a===""?null:{key:n,value:String(a)}}).filter(Boolean);return[...t,...e]}select(t,e){this.selected[t]!==e&&(this.selected[t]=e,this.renderVariant())}selectVariant(t){let e=this.product.variants.nodes.find(i=>i.id===x.variant(t));e&&(this.selected={},e.selectedOptions.forEach(i=>{this.selected[i.name]=i.value}),this.renderVariant())}setPurchase(t){let e=t==="subscription"?"subscription":"one-time";e==="one-time"&&this.product.requiresSellingPlan||this.purchase!==e&&(this.purchase=e,this.renderVariant())}selectPlan(t){let e=j(this.product,t);e&&(this.planId=e.id,this.purchase="subscription",this.renderVariant())}setQuantity(t){let e=T(this.root,"quantity")?0:1;this.quantity=Math.max(e,parseInt(t,10)||0),this.$(o("qty")).forEach(i=>h(i,this.quantity)),this.renderVariant()}async addToCart(){if(!this.variant?.availableForSale)return null;let t=this.getLine();if(!t||t.quantity<1)return null;let e=await Pt.add(t);return g("product-added",{product:this.product,variant:this.variant,line:t},this.root),e}bind(){let t=e=>e&&e.closest(St())===this.root;this.root.addEventListener("click",e=>{let i=e.target;if(!i?.closest)return;let n=i.closest(o("option-value"));if(t(n)&&n.closest(o("option-list"))){e.preventDefault(),this.select(l(n.closest(o("option-list")),"option-list"),l(n,"option-value"));return}let a=i.closest(o("plan-value"));if(t(a)){e.preventDefault(),this.selectPlan(l(a,"plan-value"));return}let r=i.closest(`${o("purchase")}:not(select)`);if(t(r)){r.tagName!=="INPUT"&&e.preventDefault(),this.setPurchase(l(r,"purchase"));return}let u=i.closest(o("qty-plus"));if(t(u)){e.preventDefault(),this.setQuantity(this.quantity+1);return}let b=i.closest(o("qty-minus"));if(t(b)){e.preventDefault(),this.setQuantity(this.quantity-1);return}let B=i.closest(o("add-to-cart"));t(B)&&(e.preventDefault(),this.onAddClick(B))}),this.root.addEventListener("change",e=>{let i=e.target;t(i)&&(i.matches(`select${o("option")}`)?this.select(l(i,"option"),i.value):i.matches(`select${o("variant-select")}`)?this.selectVariant(i.value):i.matches(`select${o("plan")}`)?i.value?this.selectPlan(i.value):this.setPurchase("one-time"):i.matches(`select${o("purchase")}`)?this.setPurchase(i.value):i.matches(o("qty"))&&this.setQuantity(i.value))})}onAddClick(t){let e=t.querySelector(o("add-label"))||t,i=l(t,"adding-text"),n=a=>h(e,a);e.dataset.tetherLabel===void 0&&(e.dataset.tetherLabel=e.tagName==="INPUT"?e.value:e.textContent),W(t,async()=>{i&&n(i);try{await this.addToCart()}catch(a){I(a,"add to cart failed"),g("error",{error:a,context:"add-to-cart"},this.root)}finally{i&&n(e.dataset.tetherLabel)}}).then(()=>{this.renderVariant()})}renderProduct(){let t=this.product;this.$(o("bind")).forEach(e=>{let i=l(e,"bind")||"",n={title:t.title,"description-text":t.description,vendor:t.vendor,type:t.productType,handle:t.handle}[i];if(n!==void 0)return h(e,n);switch(i){case"description":e.innerHTML=t.descriptionHtml||"";return;case"published-at":return h(e,vt(t.publishedAt));case"min-price":return h(e,$(t.priceRange.minVariantPrice));case"max-price":return h(e,$(t.priceRange.maxVariantPrice));case"featured-image":return A(e,t.featuredImage?.url,t.featuredImage?.altText||t.title);case"url":case"link":e.setAttribute("href",H(t.handle,t.id)),i==="url"&&!e.firstElementChild&&!e.textContent.trim()&&h(e,t.title);return;case"images":return C(e,t.images.nodes,(a,r)=>{let u=a.matches(`img,${o("bind","image")}`)?a:a.querySelector("img")||a;A(u,r.url,r.altText||t.title)});case"tags":{let a=(e.getAttribute("exclude")||"").split(",").map(r=>r.trim()).filter(Boolean);return C(e,t.tags.filter(r=>!a.includes(r)),(r,u)=>h(r,u))}default:if(/^image:\d+$/.test(i)){let a=t.images.nodes[i.slice(6)-1]||t.featuredImage;return A(e,a?.url,a?.altText||t.title)}if(i.startsWith("metafield:")){let a=Vt(t,i.slice(10));return a?a.reference?.image?A(e,a.reference.image.url,a.reference.image.altText):(/^(rich_text|multi_line_text)_field$/.test(a.type)&&(e.style.whiteSpace="pre-line"),h(e,a.value)):h(e,"")}return}}),this.$(o("option-list")).forEach(e=>{let i=l(e,"option-list"),n=t.options.find(a=>a.name===i);return!n||n.optionValues.length<=1&&T(e,"hide-single")?q(e,!1):C(e,n.optionValues,(a,r)=>{a.setAttribute(f("option-value"),r.name);let u=a.querySelector(o("bind","option-value"));u?h(u,r.name):a.firstElementChild||h(a,r.name);let b=a.querySelector(o("bind","swatch"));b&&r.swatch?.color&&(b.style.backgroundColor=r.swatch.color),b&&r.swatch?.image?.previewImage&&A(b,r.swatch.image.previewImage.url,r.name)})}),this.$(`select${o("option")}`).forEach(e=>{let i=t.options.find(n=>n.name===l(e,"option"));if(!i)return q(e,!1);e.innerHTML="",i.optionValues.forEach(n=>e.appendChild(new Option(n.name,n.name)))}),this.$(`select${o("variant-select")}`).forEach(e=>{e.innerHTML="",t.variants.nodes.forEach(i=>e.appendChild(new Option(i.title,i.id)))}),this.$(o("plan-list")).forEach(e=>{let i=(l(e,"plan-list")||"").trim(),n=["","true","all","*"].includes(i.toLowerCase())?null:i,a=this.plans.filter(r=>!n||r.group.name===n);C(e,a,(r,u)=>{r.setAttribute(f("plan-value"),u.id),!r.firstElementChild&&!r.querySelector(o("plan-bind"))&&h(r,u.name)})}),this.$(`select${o("plan")}`).forEach(e=>{e.innerHTML="",!t.requiresSellingPlan&&l(e,"plan")!=="subscription-only"&&e.appendChild(new Option(e.getAttribute(f("one-time-label"))||"One-time purchase","")),this.plans.forEach(i=>e.appendChild(new Option(i.name,i.id)))})}renderVariant(){let t=this.product,e=this.findVariant();if(e||([e]=t.variants.nodes,e&&(this.selected={},e.selectedOptions.forEach(c=>{this.selected[c.name]=c.value}))),this.variant=e,!e)return;if(this.plans.length&&!L(e,this.planId)){let c=this.plans.find(d=>L(e,d.id));c&&(this.planId=c.id)}let i=this.isSubscription,n=e.price,a=this.planId?nt(e,this.planId):null,r=i?a:n,u=i&&L(e,this.planId)?.priceAdjustments?.[0]?.compareAtPrice||e.compareAtPrice,b=u&&parseFloat(u.amount)>parseFloat(r.amount),B=b?Math.round((1-parseFloat(r.amount)/parseFloat(u.amount))*100):0,O=this.planId?at(e,this.planId):{amount:null,percentage:0},D=this.plan,E={amount:(parseFloat(r.amount)*Math.max(1,this.quantity)).toFixed(2),currencyCode:r.currencyCode},v=$,ct=c=>c?`${c}%`:"",lt={price:()=>v(r),"total-price":()=>v(E),"one-time-price":()=>v(n),"subscription-price":()=>v(a),"subscription-savings":()=>ct(O.percentage),"subscription-savings-amount":()=>v(O.amount),"checkout-charge":()=>v(i?gt(e,this.planId):r),"plan-name":()=>D?.name,"plan-description":()=>D?.description,"plan-group":()=>D?.group?.name,"compare-at-price":()=>b?v(u):"","unit-price":()=>v(e.unitPrice),"discount-percentage":()=>`${B}%`,"discount-amount":()=>b?v({amount:String(parseFloat(u.amount)-parseFloat(r.amount)),currencyCode:r.currencyCode}):"","variant-title":()=>e.title,"variant-id":()=>e.id,sku:()=>e.sku,barcode:()=>e.barcode,stock:()=>e.quantityAvailable,quantity:()=>this.quantity};this.$(o("bind")).forEach(c=>{let d=l(c,"bind");d==="variant-image"?A(c,e.image?.url||t.featuredImage?.url,e.image?.altText||t.title):lt[d]&&h(c,lt[d]())}),this.$(o("option-selected")).forEach(c=>h(c,this.selected[l(c,"option-selected")]||"")),this.$(o("option-list")).forEach(c=>{let d=l(c,"option-list");m(c,o("option-value")).forEach(w=>{let P=l(w,"option-value");R(w,this.selected[d]===P);let y=!this.isValueAvailable(d,P);w.classList.toggle("is-unavailable",y),w.setAttribute("data-unavailable",y?"true":"false")})}),this.$(`select${o("option")}`).forEach(c=>{c.value=this.selected[l(c,"option")]||""}),this.$(`select${o("variant-select")}`).forEach(c=>{c.value=e.id}),this.$(o("purchase")).forEach(c=>{if(c.tagName==="SELECT"){c.value=this.purchase;return}let d=l(c,"purchase");R(c,d===this.purchase);let w=d==="subscription"?!this.subscriptionAvailable:t.requiresSellingPlan;c.classList.toggle("is-unavailable",w)}),this.$(o("plan-value")).forEach(c=>{let d=l(c,"plan-value"),w=this.plans.find(y=>y.id===d),P=!!L(e,d);R(c,i&&d===this.planId),c.classList.toggle("is-unavailable",!P),m(c,o("plan-bind")).forEach(y=>{let S=bt(w),dt=at(e,d),Lt=l(y,"plan-bind"),ht={name:()=>w?.name,description:()=>w?.description,price:()=>v(nt(e,d)),savings:()=>ct(dt.percentage),"savings-amount":()=>v(dt.amount),adjustment:()=>S?S.type==="percentage"?`${S.value}%`:v(S.value):""}[Lt];ht&&h(y,ht())})}),this.$(`select${o("plan")}`).forEach(c=>{c.value=i?this.planId:""});let ut={"in-stock":e.availableForSale,"out-of-stock":!e.availableForSale,backorder:e.availableForSale&&e.currentlyNotInStock,"on-sale":!!b,"not-on-sale":!b,"has-variants":t.variants.nodes.length>1,"single-variant":t.variants.nodes.length===1,"low-stock":e.quantityAvailable!=null&&e.quantityAvailable>0&&e.quantityAvailable<=5,"subscription-available":this.subscriptionAvailable,"subscription-unavailable":!this.subscriptionAvailable,"subscription-only":!!t.requiresSellingPlan,"one-time-available":!t.requiresSellingPlan,"subscription-selected":i,"one-time-selected":!i,"has-savings":i?O.percentage>0:!!b,loading:!1,ready:!0,error:!1,"not-found":!1};this.$(o("show")).forEach(c=>{let d=l(c,"show");d in ut&&($t.includes(d)&&!Et(c,this.root)||q(c,ut[d]))}),this.root.classList.toggle("is-subscription",i),this.root.setAttribute(f("purchase-mode"),i?"subscription":"one-time"),this.$(o("add-to-cart")).forEach(c=>{let d=!e.availableForSale;c.classList.toggle("is-disabled",d),c.setAttribute("aria-disabled",String(d)),"disabled"in c&&(c.disabled=d);let w=l(c,"soldout-text"),P=l(c,"subscribe-text");if(w||P){let y=c.querySelector(o("add-label"))||c;y.dataset.tetherLabel===void 0&&(y.dataset.tetherLabel=y.tagName==="INPUT"?y.value:y.textContent);let S=y.dataset.tetherLabel;i&&P&&(S=P),d&&w&&(S=w),c.getAttribute("aria-busy")!=="true"&&h(y,S)}}),g("variant-changed",{product:t,variant:e,selected:{...this.selected},purchase:this.purchase,sellingPlanId:i?this.planId:null},this.root)}};var X=()=>`${o("collection")},${o("products")},${o("recommendations")}`,xt=class{constructor(t){this.root=t,this.products=[],this.pageInfo=null,this.collection=null,k(t,"loading"),t.addEventListener("click",e=>{let i=e.target.closest?.(o("load-more"));i&&i.closest(X())===t&&(e.preventDefault(),W(i,()=>this.load(!0)))})}$(t){return K(this.root,t,X())}options(){let t=this.root,e={first:parseInt(l(t,"limit")||"",10)||void 0,sortKey:l(t,"sort")||void 0,reverse:l(t,"reverse")==="true"};return T(t,"collection")?e.collection=l(t,"collection"):e.query=l(t,"products")||"",e}async load(t=!1){let e=this.loadToken=(this.loadToken||0)+1,i=()=>e!==this.loadToken;try{if(T(this.root,"recommendations")){let n=l(this.root,"recommendations"),a=await F(n),r=await mt(a.id,l(this.root,"intent")||"RELATED");if(i())return;let u=parseInt(l(this.root,"limit")||"",10);this.products=u?r.slice(0,u):r}else{let n=await ft({...this.options(),after:t?this.pageInfo?.endCursor:null});if(i())return;this.collection=n.collection,this.pageInfo=n.pageInfo,this.products=t?[...this.products,...n.products]:n.products}this.render(),k(this.root,"ready"),g("list-ready",{products:this.products,collection:this.collection},this.root)}catch(n){if(i())return;t||k(this.root,G(n)?"not-found":"error",n),I(n,"list load failed"),g("error",{error:n,context:"list"},this.root)}}render(){let t=this.collection;this.$(o("collection-bind")).forEach(i=>{switch(l(i,"collection-bind")){case"title":return h(i,t?.title||"");case"description":i.innerHTML=t?.descriptionHtml||"";return;case"image":return A(i,t?.image?.url,t?.image?.altText||t?.title);case"count":return h(i,this.products.length);default:return}}),this.$(o("list")).forEach(i=>{C(i,this.products,(n,a)=>{n.setAttribute(f("product"),a.handle),n.removeAttribute(f("state"))}),g("list-rendered",{container:i},this.root)});let e=this.products.length===0;this.$(o("show")).forEach(i=>{let n=l(i,"show");n==="list-empty"&&(i.style.display=e?"":"none"),n==="list-filled"&&(i.style.display=e?"none":"")}),this.$(o("load-more")).forEach(i=>{i.style.display=this.pageInfo?.hasNextPage?"":"none"}),_("list")}};var Z=new WeakSet,he=new WeakSet,tt=new Set,qt=new Set,kt=new WeakMap;function Ut(){tt.forEach(s=>{s.isConnected||tt.delete(s)}),qt.forEach(s=>{s.root.isConnected||qt.delete(s)})}function pe(s,t){return[...s.matches?.(t)?[s]:[],...m(s,t)]}function Bt(s){if(Z.has(s))return!1;let{key:t,fromUrl:e,raw:i}=At(s);if(!t)return e?(Z.add(s),k(s,"not-found"),g("product-not-found",{key:null,source:i},s)):s.closest(X())||pt(`[${f("product")}] without a value. Bind it to the Shopify handle field, or use "url:handle".`,s),!1;Z.add(s),tt.add(s);let n={};kt.set(s,n);let a=()=>kt.get(s)===n;return z.get(s)?s.setAttribute(f("state"),"updating"):k(s,"loading"),F(t).then(r=>{if(!a())return;let u=z.get(s);u?u.update(r):new J(s,r),Mt(s,r)}).catch(r=>{if(!a())return;let u=G(r);k(s,u?"not-found":"error",r),u?(g("product-not-found",{key:t,source:i},s),e?Q(`product not found: ${t}`):I(r,`product ${t}`)):(I(r,`product ${t}`),g("error",{error:r,context:"product",key:t},s))}),!0}function Mt(s,t){let e=l(s,"page-title");!e||typeof document>"u"||(document.title=e.replace(/\{title\}/g,t.title).replace(/\{vendor\}/g,t.vendor||"").replace(/\{type\}/g,t.productType||""))}function fe(){Ut(),tt.forEach(s=>{s.getAttribute(f("state"))!=="error"||s.getAttribute(f("error"))==="not-found"||(Z.delete(s),Bt(s))})}export{Ot as a,Pt as b,z as c,X as d,xt as e,Z as f,he as g,tt as h,qt as i,Ut as j,pe as k,Bt as l,fe as m};
@@ -0,0 +1 @@
1
+ import{a as c,j as g}from"./chunk-LI3YDMGF.js";var p=/^[A-Z]{2}$/,y=new Set(["PT_BR","PT_PT","ZH_CN","ZH_TW"]),d=()=>`${c.prefix}:market:${c.domain}`,h=()=>({document:typeof document<"u"?document:null,location:typeof window<"u"?window.location:null,storage:(()=>{try{return window.localStorage}catch{return null}})(),global:typeof window<"u"?window:{}});function w(t){let e=String(t||"").trim().toUpperCase();return p.test(e)&&e!=="XX"&&e!=="T1"?e:null}function C(t){let e=String(t||"").trim().replace("-","_").toUpperCase();if(!e)return null;if(y.has(e))return e;let n=e.split("_")[0];return/^[A-Z]{2,3}$/.test(n)?n:null}function b(t,e){if(!t||!e)return null;let n=String(t.cookie||"").split(";").map(r=>r.trim()).find(r=>r.startsWith(`${e}=`));return n?decodeURIComponent(n.slice(e.length+1)):null}var s=(t,e)=>{if(!t||!e)return null;let n=String(e).toLowerCase(),r=Object.keys(t).find(o=>o.toLowerCase()===n);return r?t[r]:null},T={saved(t,e){if(t.remember===!1||!e.storage)return null;try{return JSON.parse(e.storage.getItem(d())||"null")}catch{return null}},server(t,e){let n=a=>e.document?.querySelector?.(`meta[name="${a}"]`)?.getAttribute("content"),r=e.global.TETHER_COUNTRY||n("tether-country")||b(e.document,t.cookie||"tether_country"),o=e.global.TETHER_LANGUAGE||n("tether-language");return{country:r,language:o}},webflow(t,e){let n=(e.location?.pathname||"/").split("/").filter(Boolean)[0],r=s(t.locales,n);if(r)return r;let o=e.document?.documentElement?.getAttribute("lang");if(!o)return null;let a=s(t.locales,o)||s(t.locales,o.split("-")[0]);if(a)return{locale:o,...a};if(t.locales&&t.strict)return null;let l=o.split("-")[1];return{language:o,country:l&&l.length===2?l:null,locale:o}}};function L(t=c.markets,e=h()){let n=t||{};if(n.detect===!1)return{};let r=n.detect?n.detect===!0?["saved","server","webflow"]:[].concat(n.detect):["saved"];t=n;let o={sources:{}};return r.forEach(a=>{let l=T[a]?.(t,e);if(!l)return;let m={country:w(l.country),language:C(l.language),locale:l.locale||null};Object.entries(m).forEach(([i,f])=>{f&&!o[i]&&(o[i]=f,o.sources[i]=a)})}),o}function _(t){if(c.markets?.remember!==!1)try{localStorage.setItem(d(),JSON.stringify({country:t.country,language:t.language||void 0}))}catch{}}var u=null;function A(){u=null}function x(){return u||(u=g("query TetherLocalization{localization{country{isoCode name currency{isoCode symbol}}language{isoCode name}availableCountries{isoCode name currency{isoCode symbol}availableLanguages{isoCode name}}}}").then(t=>t.localization).catch(t=>{throw u=null,t})),u}export{w as a,C as b,L as c,_ as d,A as e,x as f};
@@ -0,0 +1,4 @@
1
+ var Z=Object.defineProperty;var ee=(e,t)=>{for(var r in t)Z(e,r,{get:t[r],enumerable:!0})};var _={domain:"",token:"",apiVersion:"2026-07",country:void 0,language:void 0,locale:void 0,markets:null,prefix:"tether",productPath:"/product",collectionPath:"/collection",metafields:[],imagesFirst:25,variantsFirst:100,sellingPlanGroupsFirst:10,sellingPlansFirst:25,collectionFirst:24,retries:2,storageKey:null,cartDrawerOpenClass:"is-open",openCartOnAdd:!0,cartFocus:!0,checkoutTarget:"_self",defaultPurchase:"one-time",autoMount:!0,observe:!1,partsUrl:null,formatMoney:null,onLayoutChange:null,onCartOpen:null,onCartClose:null,onLineEnter:null,onLineLeave:null,onValueChange:null,onError:null,debug:!1},o={..._};function Se(e={}){return Object.keys(o).forEach(t=>delete o[t]),Object.assign(o,_,e),o.domain&&(o.domain=String(o.domain).replace(/^https?:\/\//,"").replace(/\/.*$/,"")),o.storageKey||(o.storageKey=`${o.prefix}:cart:${o.domain}`),o.apiVersion==="unstable"&&b('apiVersion "unstable" changes without notice. Pin a dated version (e.g. 2026-07).'),o}var Ce=()=>!!(o.domain&&o.token);function S(...e){o.debug&&console.log(`[${o.prefix}]`,...e)}function b(...e){console.warn(`[${o.prefix}]`,...e)}function Te(e,t){if(b(t,e&&e.message?e.message:e),typeof o.onError=="function")try{o.onError(e,t)}catch{}}var m=class extends Error{constructor(t,{status:r,errors:n,userErrors:i,code:s}={}){super(t),this.name="TetherError",this.code=s||(r?`HTTP_${r}`:"ERROR"),this.status=r,this.errors=n,this.userErrors=i}};function te(){return`https://${o.domain}/api/${o.apiVersion}/graphql.json`}function re(e,t=o){let r=[];return t.country&&r.push(`country: ${String(t.country).toUpperCase()}`),t.language&&r.push(`language: ${String(t.language).toUpperCase().replace("-","_")}`),!r.length||/@inContext/.test(e)?e:e.replace(/^(\s*(?:query|mutation)\s+\w+\s*(?:\([^)]*\))?)/,`$1 @inContext(${r.join(", ")})`)}var D=e=>new Promise(t=>setTimeout(t,e));async function v(e,t={},{context:r=!0}={}){if(!o.domain||!o.token)throw new m("Tether is not configured: domain and token are required",{code:"NOT_CONFIGURED"});let n=JSON.stringify({query:r?re(e):e,variables:t}),i=0;for(;;){let s;try{s=await fetch(te(),{method:"POST",headers:{"Content-Type":"application/json","X-Shopify-Storefront-Access-Token":o.token},body:n})}catch(g){if(i++<o.retries){await D(300*2**i);continue}throw new m(`Network error: ${g.message}`,{code:"NETWORK"})}if(s.status===430)throw new m("Shopify security rejection (430)",{status:430});if((s.status===429||s.status>=500)&&i++<o.retries){S("retry",s.status,i),await D(300*2**i);continue}let f;try{f=await s.json()}catch{throw new m(`Invalid response (${s.status})`,{status:s.status})}if(f.errors?.length){if(f.errors.some(a=>/quantityAvailable/.test(a.message||""))&&/\bquantityAvailable\b/.test(n))return S("no inventory permission, retrying without quantityAvailable"),v(e.replace(/\bquantityAvailable\b/g,""),t,{context:r});if(f.errors.some(a=>a.extensions?.code==="THROTTLED")&&i++<o.retries){await D(500*2**i);continue}throw new m(f.errors.map(a=>a.message).join(" | "),{status:s.status,errors:f.errors})}if(!s.ok)throw new m(`HTTP ${s.status}`,{status:s.status});return f.data}}function Fe(e,t){if(!e)throw new m(`${t}: empty response`);let r=e.userErrors||[];if(r.length)throw new m(r.map(n=>n.message).join(" | "),{userErrors:r});return e}var u="amount currencyCode",P="url altText width height";function ne(){return(o.metafields||[]).map(e=>{if(typeof e=="string"){let t=e.indexOf(".");return{namespace:e.slice(0,t),key:e.slice(t+1)}}return e}).filter(e=>e.namespace&&e.key)}function oe(){let e=ne();return e.length?`metafields(identifiers:[${e.map(r=>`{namespace: ${JSON.stringify(r.namespace)}, key: ${JSON.stringify(r.key)}}`).join(", ")}]){namespace key type value reference{... on MediaImage{image{${P}}}}}`:""}var ie=` id name description recurringDeliveries options{name value}priceAdjustments{orderCount adjustmentValue{__typename ... on SellingPlanPercentagePriceAdjustment{adjustmentPercentage}... on SellingPlanFixedAmountPriceAdjustment{adjustmentAmount{${u}}}... on SellingPlanFixedPriceAdjustment{price{${u}}}}}`,se=` sellingPlan{id}checkoutChargeAmount{${u}}remainingBalanceChargeAmount{${u}}priceAdjustments{price{${u}}compareAtPrice{${u}}perDeliveryPrice{${u}}unitPrice{${u}}}`;function T(){return` fragment TetherProduct on Product{id handle title description descriptionHtml productType vendor tags availableForSale publishedAt onlineStoreUrl requiresSellingPlan seo{title description}featuredImage{${P}}images(first:${o.imagesFirst}){nodes{${P}}}options{name optionValues{name swatch{color image{previewImage{${P}}}}}}priceRange{minVariantPrice{${u}}maxVariantPrice{${u}}}compareAtPriceRange{minVariantPrice{${u}}maxVariantPrice{${u}}}${oe()} sellingPlanGroups(first:${o.sellingPlanGroupsFirst}){nodes{name appName options{name values}sellingPlans(first:${o.sellingPlansFirst}){nodes{${ie}}}}}variants(first:${o.variantsFirst}){nodes{id title availableForSale currentlyNotInStock quantityAvailable sku barcode selectedOptions{name value}image{${P}}price{${u}}compareAtPrice{${u}}unitPrice{${u}}sellingPlanAllocations(first:${o.sellingPlansFirst}){nodes{${se}}}}}}`}function je(){return` fragment TetherCart on Cart{id checkoutUrl totalQuantity note createdAt updatedAt attributes{key value}buyerIdentity{countryCode email}discountCodes{code applicable}cost{subtotalAmount{${u}}totalAmount{${u}}checkoutChargeAmount{${u}}}lines(first:100){nodes{id quantity attributes{key value}cost{totalAmount{${u}}subtotalAmount{${u}}amountPerQuantity{${u}}compareAtAmountPerQuantity{${u}}}discountAllocations{discountedAmount{${u}}}sellingPlanAllocation{sellingPlan{id name description recurringDeliveries options{name value}}checkoutChargeAmount{${u}}priceAdjustments{price{${u}}compareAtPrice{${u}}perDeliveryPrice{${u}}}}merchandise{... on ProductVariant{id title sku availableForSale requiresShipping image{${P}}price{${u}}compareAtPrice{${u}}selectedOptions{name value}product{id title handle vendor featuredImage{${P}}}}}... on ComponentizableCartLine{lineComponents{id quantity merchandise{... on ProductVariant{id title product{title handle}}}}}}}}`}function G(){return`
2
+ id handle title description descriptionHtml
3
+ image { ${P} }
4
+ seo { title description }`}var x=new Map,B=[],U=new Map,q=!1,C=0,R=e=>typeof e=="string"&&e.startsWith("gid://");function ae(e){let t=String(e??"").trim();if(!t)return null;if(R(t))return t;if(/^\d+$/.test(t))return`gid://shopify/Product/${t}`;let r=t.match(/\/products\/([^/?#]+)/);return r?r[1]:t}function E(e){if(!e)return;let t=Promise.resolve(e);x.set(e.handle,t),x.set(e.id,t)}function qe(e){let t=ae(e);if(!t)return Promise.reject(new m("empty product key",{code:"NOT_FOUND"}));if(x.has(t))return x.get(t);let r=new Promise((n,i)=>{U.set(t,{resolve:n,reject:i}),B.push(t),q||(q=!0,setTimeout(ce,0))});return x.set(t,r),r}async function ce(){q=!1;let e=C,t=B.splice(0);if(!t.length)return;let r=t.filter(R),n=t.filter(d=>!R(d)),i=[],s=[],p={};r.length&&(i.push("$ids: [ID!]!"),p.ids=r,s.push("byId: nodes(ids: $ids) { ... on Product { ...TetherProduct } }")),n.forEach((d,a)=>{i.push(`$h${a}: String!`),p[`h${a}`]=d,s.push(`h${a}: product(handle: $h${a}) { ...TetherProduct }`)});let f=`query TetherProducts(${i.join(",")}){${s.join(" ")}}${T()}`;S("fetch products",t);let g=(d,a)=>{let l=U.get(d);U.delete(d),l&&a(l)};try{let d=await v(f,p),a=new Map;(d.byId||[]).forEach(l=>{l&&a.set(l.id,l)}),n.forEach((l,h)=>{d[`h${h}`]&&a.set(l,d[`h${h}`])}),t.forEach(l=>g(l,h=>{a.has(l)?(e===C&&E(a.get(l)),h.resolve(a.get(l))):(e===C&&x.delete(l),h.reject(new m(`Product not found: ${l}`,{code:"NOT_FOUND"})))}))}catch(d){t.forEach(a=>g(a,l=>{e===C&&x.delete(a),l.reject(d)}))}}function Re(){x.clear(),C++}async function Ke({collection:e,query:t,first:r=o.collectionFirst,after:n=null,sortKey:i,reverse:s=!1,filters:p}={}){let f=T();if(e){let d=await v(`query TetherCollection($handle:String!,$first:Int!,$after:String,$sortKey:ProductCollectionSortKeys,$reverse:Boolean,$filters:[ProductFilter!]){collection(handle:$handle){${G()} products(first:$first,after:$after,sortKey:$sortKey,reverse:$reverse,filters:$filters){nodes{...TetherProduct}pageInfo{hasNextPage endCursor}}}}${f}`,{handle:e,first:r,after:n,sortKey:i||void 0,reverse:s,filters:p||void 0});if(!d.collection)throw new m(`Collection not found: ${e}`,{code:"NOT_FOUND"});let{products:a,...l}=d.collection;return a.nodes.forEach(E),{collection:l,products:a.nodes,pageInfo:a.pageInfo}}let g=await v(`query TetherSearch($first:Int!,$after:String,$query:String,$sortKey:ProductSortKeys,$reverse:Boolean){products(first:$first,after:$after,query:$query,sortKey:$sortKey,reverse:$reverse){nodes{...TetherProduct}pageInfo{hasNextPage endCursor}}}${f}`,{first:r,after:n,query:t||void 0,sortKey:i||void 0,reverse:s});return g.products.nodes.forEach(E),{collection:null,products:g.products.nodes,pageInfo:g.products.pageInfo}}async function Ve(e,t="RELATED"){let n=(await v(`query TetherRecs($id:ID!,$intent:ProductRecommendationIntent){productRecommendations(productId:$id,intent:$intent){...TetherProduct}}${T()}`,{id:e,intent:t})).productRecommendations||[];return n.forEach(E),n}var ge={};ee(ge,{GID:()=>H,allPlans:()=>F,allocationFor:()=>k,findPlan:()=>me,hasPlans:()=>ue,planAdjustment:()=>fe,planCheckoutCharge:()=>de,planPrice:()=>J,planSavings:()=>pe,plansForVariant:()=>le,toGid:()=>N});var H={product:e=>N(e,"Product"),variant:e=>N(e,"ProductVariant"),sellingPlan:e=>N(e,"SellingPlan")};function N(e,t){let r=String(e??"").trim();return r?r.startsWith("gid://")?r:/^\d+$/.test(r)?`gid://shopify/${t}/${r}`:r:null}function F(e){return(e?.sellingPlanGroups?.nodes||[]).flatMap(r=>(r.sellingPlans?.nodes||[]).map(n=>({...n,group:r})))}function ue(e){return F(e).length>0}function k(e,t){return!e||!t?null:(e.sellingPlanAllocations?.nodes||[]).find(r=>r.sellingPlan?.id===t)||null}function le(e,t){return F(e).filter(r=>k(t,r.id))}function J(e,t){let n=k(e,t)?.priceAdjustments?.[0];return n?.perDeliveryPrice||n?.price||e?.price||null}function de(e,t){let r=k(e,t);return r?.checkoutChargeAmount||r?.priceAdjustments?.[0]?.price||e?.price||null}function pe(e,t){let r=parseFloat(e?.price?.amount),n=parseFloat(J(e,t)?.amount);return!Number.isFinite(r)||!Number.isFinite(n)||r<=0||n>=r?{amount:null,percentage:0}:{amount:{amount:(r-n).toFixed(2),currencyCode:e.price.currencyCode},percentage:Math.round((1-n/r)*100)}}function fe(e){let t=e?.priceAdjustments?.[0]?.adjustmentValue;if(!t)return null;switch(t.__typename){case"SellingPlanPercentagePriceAdjustment":return{type:"percentage",value:t.adjustmentPercentage};case"SellingPlanFixedAmountPriceAdjustment":return{type:"amount",value:t.adjustmentAmount};case"SellingPlanFixedPriceAdjustment":return{type:"price",value:t.price};default:return null}}function me(e,t){if(!t)return null;let r=F(e),n=H.sellingPlan(t),i=String(t).trim().toLowerCase();return r.find(s=>s.id===n)||r.find(s=>s.name.toLowerCase()===i)||r.find(s=>(s.options||[]).some(p=>String(p.value).toLowerCase()===i))||null}var $=e=>`${o.prefix}-${e}`,j=(e,t)=>t===void 0?`[${$(e)}]`:`[${$(e)}="${t}"]`,O=(e,t)=>e.getAttribute($(t)),Ge=(e,t)=>e.hasAttribute($(t)),he=()=>`data-${o.prefix}-key`;function Be(e,t){let r=o.productPath||"/product";if(!/\{(handle|id)\}/.test(r))return`${r.replace(/\/$/,"")}/${e}`;let n=t?String(t).split("/").pop():"";return r.replace(/\{handle\}/g,encodeURIComponent(e||"")).replace(/\{id\}/g,encodeURIComponent(n))}var Q=(e,t)=>e?[...e.querySelectorAll(t)]:[],K=(e,t,r)=>Q(e,t).filter(n=>n.closest(r)===e);function ye(e,t,r=document){r.dispatchEvent(new CustomEvent(`${o.prefix}:${e}`,{detail:t,bubbles:!0}))}function He(e){if(!e)return"";if(typeof o.formatMoney=="function")return o.formatMoney(e,o.locale);let t=parseFloat(e.amount);if(Number.isNaN(t))return"";try{return new Intl.NumberFormat(o.locale||void 0,{style:"currency",currency:e.currencyCode}).format(t)}catch{return`${e.currencyCode} ${t.toFixed(2)}`}}function Je(e){if(!e)return"";try{return new Date(e).toLocaleDateString(o.locale||void 0)}catch{return""}}function $e(e,t){if(!e||!t)return e;let r=t.getAttribute("max-width"),n=t.getAttribute("max-height"),i=t.getAttribute("crop");if(!r&&!n)return e;try{let s=new URL(e);return r&&s.searchParams.set("width",r),n&&s.searchParams.set("height",n),i&&s.searchParams.set("crop",i),s.toString()}catch{return e}}function We(e,t,r){if(!t)return;let n=$e(t,e);e.tagName==="IMG"?(e.removeAttribute("srcset"),e.removeAttribute("sizes"),e.setAttribute("src",n),r!=null&&e.setAttribute("alt",r),e.getAttribute("loading")||e.setAttribute("loading","lazy")):e.style.backgroundImage=`url("${n}")`}function Pe(e,t){let r=t==null?"":String(t);e.tagName==="INPUT"||e.tagName==="TEXTAREA"?e.value=r:e.textContent=r}var W=e=>e.tagName==="INPUT"||e.tagName==="TEXTAREA"?e.value:e.textContent;function ze(e,t){let r=W(e);Pe(e,t);let n=W(e);if(r!==n&&e.dataset.tetherSeen&&typeof o.onValueChange=="function")try{o.onValueChange(e,r)}catch{}e.dataset.tetherSeen="1"}function X(e,t){let r="tetherPrevDisplay";t?e.dataset[r]!==void 0?(e.style.display=e.dataset[r],delete e.dataset[r]):e.style.display==="none"&&(e.style.display=""):(e.dataset[r]===void 0&&(e.dataset[r]=e.style.display||""),e.style.display="none")}function Qe(e,t){e.classList.toggle("is-selected",t),e.setAttribute("aria-pressed",t?"true":"false"),e.tagName==="INPUT"&&(e.type==="radio"||e.type==="checkbox")&&(e.checked=t);let r=e.querySelector?.('input[type="radio"],input[type="checkbox"]');r&&(r.checked=t)}var I=new WeakMap,Xe=e=>!!I.get(e);function Y(e){if(!I.has(e)){let t=e.firstElementChild?.cloneNode(!0)??null;I.set(e,t),e.innerHTML=""}return I.get(e)}function Ye(e,t,r){let n=Y(e);if(!n){b("repeater without a template child",e);return}e.innerHTML="",t.forEach((i,s)=>{let p=n.cloneNode(!0);r(p,i,s),e.appendChild(p)})}function Ze(e,t,r,n,{onEnter:i,onLeave:s}={}){let p=Y(e);if(!p){b("repeater without a template child",e);return}let f=he(),g=`data-${o.prefix}-leaving`,d=()=>[...e.children].filter(c=>c.hasAttribute(f)&&!c.hasAttribute(g)),a=new Map(d().map(c=>[c.getAttribute(f),c])),l=[],h=new Set;t.forEach((c,y)=>{let A=String(r(c,y)),w=a.get(A);w?a.delete(A):(w=p.cloneNode(!0),w.setAttribute(f,A),h.add(w)),n(w,c,y,h.has(w)),l.push(w)});let L=l.filter(c=>!h.has(c)),M=d().filter(c=>L.includes(c));if(!(M.length===L.length&&M.every((c,y)=>c===L[y]))){a.forEach(c=>c.remove()),l.forEach(c=>e.appendChild(c));return}l.forEach((c,y)=>{if(!h.has(c))return;let A=l[y-1];if(A&&A.parentNode===e?A.after(c):e.prepend(c),i)try{i(c)}catch{}}),a.forEach(c=>{c.setAttribute(g,""),c.removeAttribute(f),c.style.pointerEvents="none",c.inert=!0;let y=()=>c.remove();if(s)try{s(c,y)}catch{y()}else y()})}var z=null;function xe(e){clearTimeout(z),z=setTimeout(()=>{typeof o.onLayoutChange=="function"?o.onLayoutChange(e):window.ScrollTrigger?.refresh&&window.ScrollTrigger.refresh(),ye("layout-changed",{reason:e})},120)}function et(e,t){let r=Q(e,"img").filter(s=>!s.complete);if(!r.length)return;let n=r.length,i=()=>{--n===0&&xe(`${t}:images`)};r.forEach(s=>{s.addEventListener("load",i,{once:!0}),s.addEventListener("error",i,{once:!0})})}function tt(e,t){return e.getAttribute("aria-busy")==="true"?Promise.resolve():(e.setAttribute("aria-busy","true"),Promise.resolve().then(t).finally(()=>e.removeAttribute("aria-busy")))}function rt(e,t){let r=e&&O(e,t);if(!r)return null;try{return JSON.parse(r)}catch{return b(`invalid JSON in ${$(t)}`,e),null}}function nt(e){return e?Array.isArray(e)?e.map(t=>({key:String(t.key),value:String(t.value??"")})):Object.entries(e).map(([t,r])=>({key:t,value:String(r??"")})):[]}function st(e,t=window.location){let r=(O(e,"product")||"").trim();if(!r.toLowerCase().startsWith("url:"))return{key:r||null,fromUrl:!1,raw:r};let n=r.slice(4).trim(),i=null;if(n.toLowerCase()==="path"){let s=t.pathname.split("/").filter(Boolean);i=s.length?Ae(s[s.length-1]):null}else i=new URLSearchParams(t.search).get(n||"handle");return i=i&&i.trim()?i.trim():null,{key:i,fromUrl:!0,raw:r}}function Ae(e){try{return decodeURIComponent(e)}catch{return e}}var we=["loading","ready","error","not-found"],at=e=>e?.code==="NOT_FOUND",V=()=>["product","collection","products","recommendations"].map(e=>j(e)).join(","),ct=(e,t)=>e===t||e.parentElement?.closest(V())===t;function ut(e,t,r){let n=t==="not-found";e.setAttribute($("state"),n?"error":t),t==="error"||n?e.setAttribute($("error"),n?"not-found":r?.code||"error"):e.removeAttribute($("error")),K(e,j("show"),V()).forEach(i=>{let s=O(i,"show");if(!we.includes(s))return;let p=s===t;X(i,p),p&&typeof getComputedStyle=="function"&&getComputedStyle(i).display==="none"&&(i.style.display=i.getAttribute($("display"))||"block")}),(t==="error"||n)&&K(e,j("add-to-cart"),V()).forEach(i=>{i.classList.add("is-disabled"),i.setAttribute("aria-disabled","true"),"disabled"in i&&(i.disabled=!0)})}export{o as a,Se as b,Ce as c,S as d,b as e,Te as f,m as g,te as h,re as i,v as j,Fe as k,je as l,ae as m,E as n,qe as o,Re as p,Ke as q,Ve as r,H as s,F as t,k as u,J as v,de as w,pe as x,fe as y,me as z,ge as A,$ as B,j as C,O as D,Ge as E,Be as F,Q as G,K as H,ye as I,He as J,Je as K,We as L,Pe as M,ze as N,X as O,Qe as P,Xe as Q,Ye as R,Ze as S,xe as T,et as U,tt as V,rt as W,nt as X,st as Y,we as Z,at as _,V as $,ct as aa,ut as ba};
@@ -0,0 +1 @@
1
+ import{c as V}from"./chunk-KYQ5OGBX.js";import{$ as P,B as u,C as a,D as g,G as c,Q as v,Y as y,a as l,c as b,h as k,j as w,o as S,t as E}from"./chunk-LI3YDMGF.js";var D=e=>{let o=/^(\d{4})-(01|04|07|10)$/.exec(String(e||""));return o?{y:+o[1],m:+o[2]}:null},A=(e,o)=>`${e}-${String(o).padStart(2,"0")}`;function x(e,o=1){let n=D(e);if(!n)throw new Error(`not a quarterly Shopify API version: ${e}`);let p=n.y*4+(n.m-1)/3+o;return A(Math.floor(p/4),p%4*3+1)}function M(e,o=new Date){if(e==="unstable")return{version:e,ok:!1,note:'"unstable" changes without notice: pin a dated version such as 2026-07'};let n=D(e);if(!n)return{version:e,ok:!1,note:"not a quarterly version (YYYY-01, -04, -07 or -10)"};let p=new Date(Date.UTC(n.y,n.m-1,1)),r=new Date(Date.UTC(n.y+1,n.m-1,1)),h=(r-o)/(30.44*24*3600*1e3),i=`supported until about ${r.toISOString().slice(0,7)}`;return p>o?i="not released yet (release candidate at best)":h<=0?i="no longer supported: Shopify falls back to the oldest supported version. Upgrade (see README)":h<3&&(i=`${i}: plan the upgrade to ${x(e)} or later (see README)`),{version:e,ok:p<=o&&h>0,monthsLeft:Math.round(h),next:x(e),note:i}}var q=e=>e?`${String(e).slice(0,4)}\u2026${String(e).slice(-4)} (${String(e).length} chars)`:"(missing)";function C(e){let o=e.id?`#${e.id}`:"",n=e.className&&typeof e.className=="string"?`.${e.className.trim().split(/\s+/).slice(0,2).join(".")}`:"";return`<${e.tagName.toLowerCase()}${o}${n}>`}function I(e=document){let o=[],n=(t,s,d)=>o.push({level:t,message:s,element:d?C(d):void 0,el:d}),p=t=>!!t.closest(a("product")),r=`${a("collection")},${a("products")},${a("recommendations")}`;c(e,a("product")).forEach(t=>{if(t.closest(r)&&t.closest(a("list")))return;let{key:s,fromUrl:d,raw:f}=y(t);f?d&&!s&&n("warn",`${u("product")}="${f}" but this URL has no value for it (e.g. ?handle=my-product).`,t):n("error",`${u("product")} has no value. Bind it to the Shopify handle (CMS field), or use "url:handle".`,t)}),["bind","option-list","option","variant-select","add-to-cart","purchase","plan-list","plan","qty","line-attribute"].forEach(t=>{c(e,a(t)).forEach(s=>{p(s)||t==="line-attribute"&&s.closest(a("group"))||n("warn",`${u(t)} outside any ${u("product")}: it does nothing here.`,s)})}),c(e,a("group-add")).forEach(t=>{t.closest(a("group"))||n("warn",`${u("group-add")} outside a ${u("group")}.`,t)}),[...c(e,a("option-list")),...c(e,a("plan-list")),...c(e,a("cart-lines")),...c(e,a("list"))].forEach(t=>{!t.firstElementChild&&!v(t)&&n("warn","Repeater without a template child: put one example element inside it.",t)}),c(e,r).forEach(t=>{c(t,a("list")).length||n("error",`List without a ${u("list")} child: products have nowhere to render.`,t)});let i=new Set(["in-stock","out-of-stock","backorder","low-stock","on-sale","not-on-sale","has-variants","single-variant","subscription-available","subscription-unavailable","subscription-only","one-time-available","subscription-selected","one-time-selected","has-savings","loading","ready","error","not-found","cart-empty","cart-filled","cart-has-subscription","cart-no-subscription","cart-has-discount","cart-error","list-empty","list-filled"]);return c(e,a("show")).forEach(t=>{let s=g(t,"show");i.has(s)||n("warn",`Unknown ${u("show")}="${s}".`,t)}),c(e,a("bind")).forEach(t=>{let s=g(t,"bind")||"";if(!s.startsWith("metafield:"))return;let d=s.slice(10);(l.metafields||[]).some(m=>(typeof m=="string"?m:`${m.namespace}.${m.key}`)===d)||n("error",`${u("bind")}="${s}" but "${d}" is not in config.metafields, so it stays empty.`,t)}),c(e,a("cart-open")).length&&!c(e,a("cart-drawer")).length&&n("warn",`${u("cart-open")} exists but there is no ${u("cart-drawer")} on this page.`),c(e,a("cart-drawer")).length>1&&n("warn",`More than one ${u("cart-drawer")}.`),c(e,`[${u("state")}="error"]`).forEach(t=>{t.matches(P())&&n("error",`Scope failed to load (${g(t,"error")||"error"}).`,t)}),o}async function F({root:e=document,silent:o=!1,version:n,now:p=new Date}={}){let r={version:n,config:{domain:l.domain||"(missing)",token:q(l.token),apiVersion:l.apiVersion,endpoint:l.domain?k():null,country:l.country,language:l.language,locale:l.locale,markets:l.markets||null,prefix:l.prefix,productPath:l.productPath,metafields:l.metafields,autoMount:l.autoMount,observe:l.observe,onError:typeof l.onError=="function"},apiVersion:M(l.apiVersion,p),market:l.markets?.detect?V(l.markets):null,reachable:!1,shop:null,latencyMs:null,products:[],sellingPlans:[],problems:[]};if(!b())r.problems.push({level:"error",message:"TETHER_CONFIG needs domain and token."});else{let h=Date.now();try{let i=await w("query TetherDiagnose { shop { name primaryDomain { url } paymentSettings { currencyCode } } }",{},{context:!1});r.reachable=!0,r.shop={name:i.shop?.name,url:i.shop?.primaryDomain?.url,currency:i.shop?.paymentSettings?.currencyCode}}catch(i){let t=i.status===401||i.status===403?"Token rejected: use the public Storefront token from the Headless channel, not an Admin token.":i.status===404?"Store or API version not found: check domain (x.myshopify.com) and apiVersion.":"";r.problems.push({level:"error",message:`Storefront API not reachable: ${i.message}${t?`. ${t}`:""}`})}if(r.latencyMs=Date.now()-h,r.reachable){let i=[...new Set(c(e,a("product")).map(s=>y(s).key).filter(Boolean))].slice(0,20);(await Promise.allSettled(i.map(s=>S(s)))).forEach((s,d)=>{if(s.status==="fulfilled"){let f=s.value,m=E(f);r.products.push({key:i[d],handle:f.handle,title:f.title,plans:m.length,requiresSellingPlan:f.requiresSellingPlan}),m.forEach($=>r.sellingPlans.push({product:f.handle,group:$.group?.name,plan:$.name,id:$.id}))}else r.products.push({key:i[d],error:s.reason?.message}),r.problems.push({level:"error",message:`Product "${i[d]}": ${s.reason?.message}. Is it published to the Headless channel?`})})}}return(!r.apiVersion.ok||(r.apiVersion.monthsLeft??99)<3)&&r.problems.push({level:r.apiVersion.ok?"warn":"error",message:`apiVersion ${l.apiVersion}: ${r.apiVersion.note}`}),typeof document<"u"&&r.problems.push(...I(e)),o||T(r),r}function T(e){let o=console,n=e.problems.filter(p=>p.level==="error").length;o.group?.(`[${l.prefix}] diagnose: ${n?`${n} error(s)`:"no errors"}, ${e.problems.length-n} warning(s)`),o.log("version",e.version,"| API",e.apiVersion.version,`(${e.apiVersion.note})`),o.log("config",e.config),e.market&&o.log("market detected",e.market,"(in use:",e.config.country,e.config.language,")"),o.log(e.reachable?`Storefront API reachable: ${e.shop?.name} (${e.latencyMs} ms)`:"Storefront API NOT reachable"),e.products.length&&(o.table||o.log)(e.products),e.sellingPlans.length?(o.table||o.log)(e.sellingPlans):e.reachable&&o.log("No selling plans on the products of this page."),e.problems.forEach(p=>(p.level==="error"?o.error:o.warn)(p.message,p.el||"")),o.groupEnd?.()}export{M as apiVersionStatus,I as checkMarkup,F as diagnose};
@@ -0,0 +1 @@
1
+ import{b as l,d as E,f as k,h as z,i as A,j as M,k as h,l as N}from"./chunk-GHIUMD5H.js";import{a as w,b as P,c as T,d as x,e as I,f as g}from"./chunk-KYQ5OGBX.js";import{B as y,C as p,D as v,I as L,a as n,f,g as C,p as b}from"./chunk-LI3YDMGF.js";function S(u=document){let i=h(u,`select${p("country-select")}`),d=h(u,p("country-bind"));return!i.length&&!d.length?Promise.resolve():g().then(t=>{let a=(n.country||t.country?.isoCode||"").toUpperCase(),s=[...t.availableCountries||[]].sort((e,r)=>e.name.localeCompare(r.name,n.locale||void 0)),c=s.find(e=>e.isoCode===a)||t.country,o=(e,r)=>e.replace(/\{name\}/g,r.name).replace(/\{code\}/g,r.isoCode).replace(/\{currency\}/g,r.currency?.isoCode||"").replace(/\{symbol\}/g,r.currency?.symbol||"");i.forEach(e=>{let r=e.getAttribute(y("country-label"))||"{name} ({currency})";e.innerHTML="",s.forEach(m=>e.appendChild(new Option(o(r,m),m.isoCode))),e.value=a,e.value!==a&&(e.selectedIndex=-1),e.disabled=s.length<2&&!e.hasAttribute(y("always-enabled"))}),d.forEach(e=>{let r=v(e,"country-bind")||"name",m={name:c?.name,code:c?.isoCode,currency:c?.currency?.isoCode,symbol:c?.currency?.symbol}[r];e.textContent=m||""})}).catch(t=>f(t,"country select"))}async function V(u,{language:i,remember:d=!0}={}){let t=w(u);if(!t)throw new C(`Not a country code: ${u}`,{code:"INVALID_COUNTRY"});let a=i===void 0?n.language:P(i),s=t!==String(n.country||"").toUpperCase()||a!==n.language;if(n.country=t,n.language=a||void 0,d&&x({country:t,language:a}),!s)return S(),l.state;b();let c=[];return i!==void 0&&I(),l.id()&&c.push(l.setBuyerIdentity({countryCode:t},{create:!1}).catch(o=>f(o,"cart country"))),M(),A.forEach(o=>c.push(o.load())),z.forEach(o=>{o.closest(E())||(k.delete(o),N(o))}),S(),L("country-changed",{country:t,language:n.language}),await Promise.all(c),l.state}export{T as detectMarket,g as getLocalization,S as renderCountrySelects,V as setCountry};
@@ -0,0 +1 @@
1
+ import{a as j,b as i,c as $,d as V,e as Z,g as T,i as O,j as Q,k as h,l as W,m as X}from"./chunks/chunk-GHIUMD5H.js";import{A as K,B as C,C as o,D as H,G as x,I as g,J as z,V as y,W as B,X as J,Y as U,a,b as P,c as w,d as b,e as L,f as l,g as I,i as M,j as q,m as N,n as _,o as A,p as F,q as R,r as G}from"./chunks/chunk-LI3YDMGF.js";var f=e=>e==="diagnose"?import("./chunks/diagnose-ZXXXJIQE.js"):import("./chunks/markets-ui-AG6Y5VUE.js");var Y="0.4.0",p=null,S=null;function v(e=document){if(!w())return 0;let t=0;return Q(),h(e,V()).forEach(r=>{if(T.has(r))return;T.add(r),t++;let n=new Z(r);O.add(n),r.addEventListener(`${a.prefix}:list-rendered`,c=>v(c.detail.container)),n.load()}),h(e,o("product")).forEach(r=>{W(r)&&t++}),h(e,`${o("country-select")},${o("country-bind")}`).length&&f("markets").then(r=>r.renderCountrySelects(e)).catch(r=>l(r,"markets")),x(e,o("account-link")).forEach(r=>{r.setAttribute("href",`https://${a.domain}/account`)}),i.render(),b(`mounted ${t} scope(s)`,e),t}function at(){i.close()}function st(e){let t=e?.closest?.(o("product"));return t&&$.get(t)||null}var tt=!1;function ut(){tt||(tt=!0,document.addEventListener("click",e=>{let t=e.target;if(!t?.closest)return;if(t.closest(o("cart-open"))){e.preventDefault(),i.toggle();return}if(t.closest(o("cart-close"))){e.preventDefault(),i.close();return}let r=t.closest(o("cart-clear"));if(r){e.preventDefault(),y(r,()=>i.clear().catch(u=>l(u,"cart clear")));return}let n=t.closest(o("checkout"));if(n){e.preventDefault(),y(n,()=>i.checkout());return}let c=t.closest(et());if(c&&c.closest(o("cart-lines"))){let u=c.getAttribute(`data-${a.prefix}-key`),m=i.lines.find(k=>k.id===u),E=k=>{e.preventDefault(),k().catch(ct=>l(ct,"cart line"))};if(t.closest(o("line-remove")))return E(()=>i.removeLine(u));if(m&&t.closest(o("line-plus")))return E(()=>i.updateLine(u,m.quantity+1));if(m&&t.closest(o("line-minus")))return E(()=>i.updateLine(u,m.quantity-1))}let d=t.closest(o("discount-remove"));if(d){e.preventDefault();let u=d.closest(o("discount-code"))?.getAttribute(C("discount-code"));u&&i.removeDiscount(u).catch(m=>l(m,"discount"));return}let s=t.closest(o("group-add"));s&&(e.preventDefault(),y(s,()=>rt(s)))}),document.addEventListener("change",e=>{let t=e.target;if(!t?.closest)return;let n=t.closest(et())?.getAttribute(`data-${a.prefix}-key`);n&&t.matches(`input${o("line","quantity")}`)?i.updateLine(n,parseInt(t.value,10)||0).catch(c=>l(c,"cart line")):n&&t.matches(`select${o("line-plan")}`)?i.updateLine(n,{sellingPlanId:t.value||null}).catch(c=>l(c,"cart line plan")):t.matches(`select${o("country-select")}`)?t.value&&ot(t.value).catch(c=>l(c,"country")):t.matches(o("cart-note"))&&i.setNote(t.value).catch(c=>l(c,"cart note"))}),document.addEventListener("submit",e=>{let t=e.target.closest?.(o("discount-form"));if(!t)return;e.preventDefault();let r=t.querySelector(o("discount-input"))||t.querySelector("input"),n=r?.value.trim();n&&y(t,async()=>{try{let d=((await i.applyDiscount(n))?.discountCodes||[]).find(s=>s.code.toLowerCase()===n.toLowerCase())?.applicable;t.classList.toggle("is-invalid",!d),g(d?"discount-applied":"discount-invalid",{code:n},t),d&&r&&(r.value="")}catch(c){t.classList.add("is-invalid"),l(c,"discount")}})}),window.addEventListener("online",()=>{X(),O.forEach(e=>{e.root.getAttribute(C("state"))==="error"&&e.load()})}),document.addEventListener("keydown",e=>{if(!i.isOpen())return;if(e.key==="Escape"){i.close();return}if(e.key!=="Tab"||a.cartFocus===!1)return;let t=i.drawers().find(d=>d.classList.contains(a.cartDrawerOpenClass)),r=t?j(t):[];if(!r.length)return;let n=r[0],c=r[r.length-1];(!t.contains(document.activeElement)||e.shiftKey&&document.activeElement===n||!e.shiftKey&&document.activeElement===c)&&(e.preventDefault(),(e.shiftKey?c:n).focus())}))}function et(){return`[data-${a.prefix}-key]`}async function rt(e){let t=e.closest(o("group"));if(!t)return null;let r=H(t,"group"),n=J(B(t,"line-attributes")),c=r?[{key:"_group",value:r},...n]:n,d=x(t,o("product")).map(s=>$.get(s)).filter(s=>s&&s.variant?.availableForSale&&s.quantity>0).map(s=>{let u=s.getLine();return u.attributes=[...u.attributes||[],...c],u});if(!d.length)return L("group-add: nothing selected"),null;try{let s=await i.add(d);return g("group-added",{group:r,lines:d},t),s}catch(s){return l(s,"group add"),null}}function nt(e={}){return p&&!Object.keys(e).length?p:(P({...window.TETHER_CONFIG||{},...e}),w()?(ut(),a.observe&&dt(),p=lt(e).then(()=>i.init()).then(async t=>{let r=a.country?String(a.country).toUpperCase():null;if(t&&r&&t.buyerIdentity?.countryCode&&t.buyerIdentity.countryCode!==r)try{t=await i.setBuyerIdentity({countryCode:r},{create:!1})}catch(n){l(n,"cart country")}return g("ready",{cart:t}),D}),p):(L("TETHER_CONFIG is missing domain or token. Tether is idle."),p=Promise.resolve(null),p))}async function lt(e){let t=a.markets||{};if(t.detect===!1)return;let r=null;if(t.detect)try{r=(await f("markets")).detectMarket(t)}catch(n){l(n,"markets");return}else if(t.remember!==!1){try{r=JSON.parse(localStorage.getItem(`${a.prefix}:market:${a.domain}`)||"null")}catch{}r&&!/^[A-Z]{2}$/.test(r.country||"")&&(r=null)}r&&(r.country&&(a.country=r.country),r.language&&(a.language=r.language),r.locale&&!e.locale&&!window.TETHER_CONFIG?.locale&&(a.locale=r.locale),b("market",r))}function ot(e,t){return f("markets").then(r=>r.setCountry(e,t))}function dt(){if(S||typeof MutationObserver>"u")return;let e=null,t=new Set;S=new MutationObserver(r=>{r.forEach(n=>n.addedNodes.forEach(c=>{c.nodeType===1&&t.add(c)})),clearTimeout(e),e=setTimeout(()=>{t.forEach(n=>{n.isConnected&&v(n)}),t.clear()},50)}),S.observe(document.body,{childList:!0,subtree:!0})}var D={VERSION:Y,init:nt,mount:v,unmount:at,get config(){return a},get ready(){return p||Promise.resolve(null)},query:q,withContext:M,cart:i,getProduct:A,getProducts:R,getRecommendations:G,getScope:st,addGroup:rt,primeProduct:_,normalizeProductKey:N,clearProductCache:F,formatMoney:z,plans:K,TetherError:I,resolveProductKey:U,setCountry:ot,detectMarket:e=>f("markets").then(t=>t.detectMarket(e||a.markets)),getLocalization:()=>f("markets").then(e=>e.getLocalization()),diagnose:e=>f("diagnose").then(t=>t.diagnose({...e,version:Y})),__core:void 0,__parts:{},on(e,t){let r=n=>t(n.detail,n);return document.addEventListener(`${a.prefix}:${e}`,r),()=>document.removeEventListener(`${a.prefix}:${e}`,r)}},Lt=D;if(typeof window<"u"&&typeof document<"u"&&(window.Tether=D,window.TETHER_CONFIG&&window.TETHER_CONFIG.autoMount!==!1)){let t=()=>nt().then(()=>v(document));document.readyState==="loading"?document.addEventListener("DOMContentLoaded",t,{once:!0}):t()}export{Y as VERSION,rt as addGroup,D as api,Lt as default,st as getScope,nt as init,v as mount,ot as setCountry,at as unmount};
@@ -19,9 +19,8 @@ function barbaPreset(options = {}) {
19
19
  return {
20
20
  autoMount: false,
21
21
  onLayoutChange() {
22
- var _a, _b, _c, _d;
23
- (_b = (_a = get(lenis)) == null ? void 0 : _a.resize) == null ? void 0 : _b.call(_a);
24
- (_d = (_c = get(scrollTrigger)) == null ? void 0 : _c.refresh) == null ? void 0 : _d.call(_c);
22
+ get(lenis)?.resize?.();
23
+ get(scrollTrigger)?.refresh?.();
25
24
  },
26
25
  onCartOpen(drawers) {
27
26
  if (!locked && typeof lockScroll === "function" && drawers[0]) {
@@ -52,7 +51,7 @@ function barbaPreset(options = {}) {
52
51
  opacity: 1,
53
52
  duration: lineDuration,
54
53
  clearProps: "height,paddingTop,paddingBottom,borderBottomWidth,opacity,overflow",
55
- onComplete: () => onResize == null ? void 0 : onResize()
54
+ onComplete: () => onResize?.()
56
55
  });
57
56
  },
58
57
  onLineLeave(node, done) {
@@ -71,7 +70,7 @@ function barbaPreset(options = {}) {
71
70
  duration: lineDuration,
72
71
  onComplete: () => {
73
72
  done();
74
- onResize == null ? void 0 : onResize();
73
+ onResize?.();
75
74
  }
76
75
  });
77
76
  },
@@ -0,0 +1,319 @@
1
+ (() => {
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, { get: all[name], enumerable: true });
6
+ };
7
+
8
+ // src/diagnose.js
9
+ var diagnose_exports = {};
10
+ __export(diagnose_exports, {
11
+ apiVersionStatus: () => apiVersionStatus,
12
+ checkMarkup: () => checkMarkup,
13
+ diagnose: () => diagnose
14
+ });
15
+
16
+ // tether-core:config.js
17
+ var m = window.Tether.__core["config.js"];
18
+ var { DEFAULTS, cfg, configure, isConfigured, log, reportError, warn } = m;
19
+
20
+ // tether-core:client.js
21
+ var m2 = window.Tether.__core["client.js"];
22
+ var { TetherError, endpoint, gql, unwrap, withContext } = m2;
23
+
24
+ // tether-core:dom.js
25
+ var m3 = window.Tether.__core["dom.js"];
26
+ var { attr, busy, cdnUrl, dataKey, emit, formatDate, formatMoney, get, has, hasTemplate, notifyLayoutChanged, parseJSONAttr, productUrl, qsa, readText, repeat, repeatKeyed, scoped, sel, setImage, setSelected, setText, setTextTracked, show, toAttributes, watchImages } = m3;
27
+
28
+ // tether-core:loader.js
29
+ var m4 = window.Tether.__core["loader.js"];
30
+ var { clearProductCache, getProduct, getProducts, getRecommendations, normalizeProductKey, primeProduct } = m4;
31
+
32
+ // tether-core:selling-plans.js
33
+ var m5 = window.Tether.__core["selling-plans.js"];
34
+ var { GID, allPlans, allocationFor, findPlan, hasPlans, planAdjustment, planCheckoutCharge, planPrice, planSavings, plansForVariant, toGid } = m5;
35
+
36
+ // tether-core:status.js
37
+ var m6 = window.Tether.__core["status.js"];
38
+ var { STATUS_KEYS, boundary, isNotFound, ownedBy, resolveProductKey, setScopeStatus } = m6;
39
+
40
+ // src/api-version.js
41
+ var parse = (v) => {
42
+ const m7 = /^(\d{4})-(01|04|07|10)$/.exec(String(v || ""));
43
+ return m7 ? { y: +m7[1], m: +m7[2] } : null;
44
+ };
45
+ var fmt = (y, m7) => `${y}-${String(m7).padStart(2, "0")}`;
46
+ function nextApiVersion(v, steps = 1) {
47
+ const p = parse(v);
48
+ if (!p) throw new Error(`not a quarterly Shopify API version: ${v}`);
49
+ const q = p.y * 4 + (p.m - 1) / 3 + steps;
50
+ return fmt(Math.floor(q / 4), q % 4 * 3 + 1);
51
+ }
52
+ function apiVersionStatus(version, now = /* @__PURE__ */ new Date()) {
53
+ if (version === "unstable") return { version, ok: false, note: '"unstable" changes without notice: pin a dated version such as 2026-07' };
54
+ const p = parse(version);
55
+ if (!p) return { version, ok: false, note: "not a quarterly version (YYYY-01, -04, -07 or -10)" };
56
+ const released = new Date(Date.UTC(p.y, p.m - 1, 1));
57
+ const supportedUntil = new Date(Date.UTC(p.y + 1, p.m - 1, 1));
58
+ const monthsLeft = (supportedUntil - now) / (30.44 * 24 * 3600 * 1e3);
59
+ let note = `supported until about ${supportedUntil.toISOString().slice(0, 7)}`;
60
+ if (released > now) note = "not released yet (release candidate at best)";
61
+ else if (monthsLeft <= 0) note = "no longer supported: Shopify falls back to the oldest supported version. Upgrade (see README)";
62
+ else if (monthsLeft < 3) note = `${note}: plan the upgrade to ${nextApiVersion(version)} or later (see README)`;
63
+ return { version, ok: released <= now && monthsLeft > 0, monthsLeft: Math.round(monthsLeft), next: nextApiVersion(version), note };
64
+ }
65
+
66
+ // src/markets.js
67
+ var COUNTRY = /^[A-Z]{2}$/;
68
+ var REGIONAL_LANGUAGES = /* @__PURE__ */ new Set(["PT_BR", "PT_PT", "ZH_CN", "ZH_TW"]);
69
+ var storageKey = () => `${cfg.prefix}:market:${cfg.domain}`;
70
+ var defaultEnv = () => ({
71
+ document: typeof document !== "undefined" ? document : null,
72
+ location: typeof window !== "undefined" ? window.location : null,
73
+ storage: (() => {
74
+ try {
75
+ return window.localStorage;
76
+ } catch {
77
+ return null;
78
+ }
79
+ })(),
80
+ global: typeof window !== "undefined" ? window : {}
81
+ });
82
+ function toCountry(v) {
83
+ const c = String(v || "").trim().toUpperCase();
84
+ return COUNTRY.test(c) && c !== "XX" && c !== "T1" ? c : null;
85
+ }
86
+ function toLanguage(v) {
87
+ const raw = String(v || "").trim().replace("-", "_").toUpperCase();
88
+ if (!raw) return null;
89
+ if (REGIONAL_LANGUAGES.has(raw)) return raw;
90
+ const primary = raw.split("_")[0];
91
+ return /^[A-Z]{2,3}$/.test(primary) ? primary : null;
92
+ }
93
+ function readCookie(doc, name) {
94
+ if (!doc || !name) return null;
95
+ const hit = String(doc.cookie || "").split(";").map((c) => c.trim()).find((c) => c.startsWith(`${name}=`));
96
+ return hit ? decodeURIComponent(hit.slice(name.length + 1)) : null;
97
+ }
98
+ var lookup = (locales, key) => {
99
+ if (!locales || !key) return null;
100
+ const k = String(key).toLowerCase();
101
+ const found = Object.keys(locales).find((x) => x.toLowerCase() === k);
102
+ return found ? locales[found] : null;
103
+ };
104
+ var readers = {
105
+ saved(m7, env) {
106
+ if (m7.remember === false || !env.storage) return null;
107
+ try {
108
+ return JSON.parse(env.storage.getItem(storageKey()) || "null");
109
+ } catch {
110
+ return null;
111
+ }
112
+ },
113
+ server(m7, env) {
114
+ const meta = (name) => env.document?.querySelector?.(`meta[name="${name}"]`)?.getAttribute("content");
115
+ const country = env.global.TETHER_COUNTRY || meta("tether-country") || readCookie(env.document, m7.cookie || "tether_country");
116
+ const language = env.global.TETHER_LANGUAGE || meta("tether-language");
117
+ return { country, language };
118
+ },
119
+ webflow(m7, env) {
120
+ const segment = (env.location?.pathname || "/").split("/").filter(Boolean)[0];
121
+ const fromPath = lookup(m7.locales, segment);
122
+ if (fromPath) return fromPath;
123
+ const lang = env.document?.documentElement?.getAttribute("lang");
124
+ if (!lang) return null;
125
+ const mapped = lookup(m7.locales, lang) || lookup(m7.locales, lang.split("-")[0]);
126
+ if (mapped) return { locale: lang, ...mapped };
127
+ if (m7.locales && m7.strict) return null;
128
+ const region = lang.split("-")[1];
129
+ return { language: lang, country: region && region.length === 2 ? region : null, locale: lang };
130
+ }
131
+ };
132
+ function detectMarket(markets = cfg.markets, env = defaultEnv()) {
133
+ const m7 = markets || {};
134
+ if (m7.detect === false) return {};
135
+ const list = !m7.detect ? ["saved"] : m7.detect === true ? ["saved", "server", "webflow"] : [].concat(m7.detect);
136
+ markets = m7;
137
+ const out = { sources: {} };
138
+ list.forEach((name) => {
139
+ const r = readers[name]?.(markets, env);
140
+ if (!r) return;
141
+ const vals = { country: toCountry(r.country), language: toLanguage(r.language), locale: r.locale || null };
142
+ Object.entries(vals).forEach(([k, v]) => {
143
+ if (v && !out[k]) {
144
+ out[k] = v;
145
+ out.sources[k] = name;
146
+ }
147
+ });
148
+ });
149
+ return out;
150
+ }
151
+
152
+ // src/diagnose.js
153
+ var mask = (t) => t ? `${String(t).slice(0, 4)}\u2026${String(t).slice(-4)} (${String(t).length} chars)` : "(missing)";
154
+ function describe(el) {
155
+ const id = el.id ? `#${el.id}` : "";
156
+ const cls = el.className && typeof el.className === "string" ? `.${el.className.trim().split(/\s+/).slice(0, 2).join(".")}` : "";
157
+ return `<${el.tagName.toLowerCase()}${id}${cls}>`;
158
+ }
159
+ function checkMarkup(root = document) {
160
+ const problems = [];
161
+ const add = (level, message, el) => problems.push({ level, message, element: el ? describe(el) : void 0, el });
162
+ const inProduct = (el) => Boolean(el.closest(sel("product")));
163
+ const listSel = `${sel("collection")},${sel("products")},${sel("recommendations")}`;
164
+ qsa(root, sel("product")).forEach((el) => {
165
+ if (el.closest(listSel) && el.closest(sel("list"))) return;
166
+ const { key, fromUrl, raw } = resolveProductKey(el);
167
+ if (!raw) add("error", `${attr("product")} has no value. Bind it to the Shopify handle (CMS field), or use "url:handle".`, el);
168
+ else if (fromUrl && !key) add("warn", `${attr("product")}="${raw}" but this URL has no value for it (e.g. ?handle=my-product).`, el);
169
+ });
170
+ const productOnly = ["bind", "option-list", "option", "variant-select", "add-to-cart", "purchase", "plan-list", "plan", "qty", "line-attribute"];
171
+ productOnly.forEach((name) => {
172
+ qsa(root, sel(name)).forEach((el) => {
173
+ if (inProduct(el)) return;
174
+ if (name === "line-attribute" && el.closest(sel("group"))) return;
175
+ add("warn", `${attr(name)} outside any ${attr("product")}: it does nothing here.`, el);
176
+ });
177
+ });
178
+ qsa(root, sel("group-add")).forEach((el) => {
179
+ if (!el.closest(sel("group"))) add("warn", `${attr("group-add")} outside a ${attr("group")}.`, el);
180
+ });
181
+ [...qsa(root, sel("option-list")), ...qsa(root, sel("plan-list")), ...qsa(root, sel("cart-lines")), ...qsa(root, sel("list"))].forEach((el) => {
182
+ if (!el.firstElementChild && !hasTemplate(el)) {
183
+ add("warn", "Repeater without a template child: put one example element inside it.", el);
184
+ }
185
+ });
186
+ qsa(root, listSel).forEach((el) => {
187
+ if (!qsa(el, sel("list")).length) add("error", `List without a ${attr("list")} child: products have nowhere to render.`, el);
188
+ });
189
+ const known = /* @__PURE__ */ new Set([
190
+ "in-stock",
191
+ "out-of-stock",
192
+ "backorder",
193
+ "low-stock",
194
+ "on-sale",
195
+ "not-on-sale",
196
+ "has-variants",
197
+ "single-variant",
198
+ "subscription-available",
199
+ "subscription-unavailable",
200
+ "subscription-only",
201
+ "one-time-available",
202
+ "subscription-selected",
203
+ "one-time-selected",
204
+ "has-savings",
205
+ "loading",
206
+ "ready",
207
+ "error",
208
+ "not-found",
209
+ "cart-empty",
210
+ "cart-filled",
211
+ "cart-has-subscription",
212
+ "cart-no-subscription",
213
+ "cart-has-discount",
214
+ "cart-error",
215
+ "list-empty",
216
+ "list-filled"
217
+ ]);
218
+ qsa(root, sel("show")).forEach((el) => {
219
+ const k = get(el, "show");
220
+ if (!known.has(k)) add("warn", `Unknown ${attr("show")}="${k}".`, el);
221
+ });
222
+ qsa(root, sel("bind")).forEach((el) => {
223
+ const k = get(el, "bind") || "";
224
+ if (!k.startsWith("metafield:")) return;
225
+ const ref = k.slice(10);
226
+ const listed = (cfg.metafields || []).some((m7) => (typeof m7 === "string" ? m7 : `${m7.namespace}.${m7.key}`) === ref);
227
+ if (!listed) add("error", `${attr("bind")}="${k}" but "${ref}" is not in config.metafields, so it stays empty.`, el);
228
+ });
229
+ if (qsa(root, sel("cart-open")).length && !qsa(root, sel("cart-drawer")).length) {
230
+ add("warn", `${attr("cart-open")} exists but there is no ${attr("cart-drawer")} on this page.`);
231
+ }
232
+ if (qsa(root, sel("cart-drawer")).length > 1) add("warn", `More than one ${attr("cart-drawer")}.`);
233
+ qsa(root, `[${attr("state")}="error"]`).forEach((el) => {
234
+ if (el.matches(boundary())) add("error", `Scope failed to load (${get(el, "error") || "error"}).`, el);
235
+ });
236
+ return problems;
237
+ }
238
+ async function diagnose({ root = document, silent = false, version, now = /* @__PURE__ */ new Date() } = {}) {
239
+ const report = {
240
+ version,
241
+ config: {
242
+ domain: cfg.domain || "(missing)",
243
+ token: mask(cfg.token),
244
+ apiVersion: cfg.apiVersion,
245
+ endpoint: cfg.domain ? endpoint() : null,
246
+ country: cfg.country,
247
+ language: cfg.language,
248
+ locale: cfg.locale,
249
+ markets: cfg.markets || null,
250
+ prefix: cfg.prefix,
251
+ productPath: cfg.productPath,
252
+ metafields: cfg.metafields,
253
+ autoMount: cfg.autoMount,
254
+ observe: cfg.observe,
255
+ onError: typeof cfg.onError === "function"
256
+ },
257
+ apiVersion: apiVersionStatus(cfg.apiVersion, now),
258
+ market: cfg.markets?.detect ? detectMarket(cfg.markets) : null,
259
+ reachable: false,
260
+ shop: null,
261
+ latencyMs: null,
262
+ products: [],
263
+ sellingPlans: [],
264
+ problems: []
265
+ };
266
+ if (!isConfigured()) {
267
+ report.problems.push({ level: "error", message: "TETHER_CONFIG needs domain and token." });
268
+ } else {
269
+ const t0 = Date.now();
270
+ try {
271
+ const data = await gql("query TetherDiagnose { shop { name primaryDomain { url } paymentSettings { currencyCode } } }", {}, { context: false });
272
+ report.reachable = true;
273
+ report.shop = { name: data.shop?.name, url: data.shop?.primaryDomain?.url, currency: data.shop?.paymentSettings?.currencyCode };
274
+ } catch (err) {
275
+ const hint = err.status === 401 || err.status === 403 ? "Token rejected: use the public Storefront token from the Headless channel, not an Admin token." : err.status === 404 ? "Store or API version not found: check domain (x.myshopify.com) and apiVersion." : "";
276
+ report.problems.push({ level: "error", message: `Storefront API not reachable: ${err.message}${hint ? `. ${hint}` : ""}` });
277
+ }
278
+ report.latencyMs = Date.now() - t0;
279
+ if (report.reachable) {
280
+ const keys = [...new Set(qsa(root, sel("product")).map((el) => resolveProductKey(el).key).filter(Boolean))].slice(0, 20);
281
+ const results = await Promise.allSettled(keys.map((k) => getProduct(k)));
282
+ results.forEach((r, i) => {
283
+ if (r.status === "fulfilled") {
284
+ const p = r.value;
285
+ const plans = allPlans(p);
286
+ report.products.push({ key: keys[i], handle: p.handle, title: p.title, plans: plans.length, requiresSellingPlan: p.requiresSellingPlan });
287
+ plans.forEach((pl) => report.sellingPlans.push({ product: p.handle, group: pl.group?.name, plan: pl.name, id: pl.id }));
288
+ } else {
289
+ report.products.push({ key: keys[i], error: r.reason?.message });
290
+ report.problems.push({ level: "error", message: `Product "${keys[i]}": ${r.reason?.message}. Is it published to the Headless channel?` });
291
+ }
292
+ });
293
+ }
294
+ }
295
+ if (!report.apiVersion.ok || (report.apiVersion.monthsLeft ?? 99) < 3) {
296
+ report.problems.push({ level: report.apiVersion.ok ? "warn" : "error", message: `apiVersion ${cfg.apiVersion}: ${report.apiVersion.note}` });
297
+ }
298
+ if (typeof document !== "undefined") report.problems.push(...checkMarkup(root));
299
+ if (!silent) print(report);
300
+ return report;
301
+ }
302
+ function print(r) {
303
+ const c = console;
304
+ const errors = r.problems.filter((p) => p.level === "error").length;
305
+ c.group?.(`[${cfg.prefix}] diagnose: ${errors ? `${errors} error(s)` : "no errors"}, ${r.problems.length - errors} warning(s)`);
306
+ c.log("version", r.version, "| API", r.apiVersion.version, `(${r.apiVersion.note})`);
307
+ c.log("config", r.config);
308
+ if (r.market) c.log("market detected", r.market, "(in use:", r.config.country, r.config.language, ")");
309
+ c.log(r.reachable ? `Storefront API reachable: ${r.shop?.name} (${r.latencyMs} ms)` : "Storefront API NOT reachable");
310
+ if (r.products.length) (c.table || c.log)(r.products);
311
+ if (r.sellingPlans.length) (c.table || c.log)(r.sellingPlans);
312
+ else if (r.reachable) c.log("No selling plans on the products of this page.");
313
+ r.problems.forEach((p) => (p.level === "error" ? c.error : c.warn)(p.message, p.el || ""));
314
+ c.groupEnd?.();
315
+ }
316
+
317
+ // src/parts/diagnose.js
318
+ window.Tether.__parts.diagnose = diagnose_exports;
319
+ })();
@@ -0,0 +1 @@
1
+ (()=>{var V=Object.defineProperty;var D=(e,t)=>{for(var o in t)V(e,o,{get:t[o],enumerable:!0})};var k={};D(k,{apiVersionStatus:()=>$,checkMarkup:()=>U,diagnose:()=>X});var N=window.Tether.__core["config.js"],{DEFAULTS:te,cfg:l,configure:oe,isConfigured:E,log:ne,reportError:re,warn:se}=N;var I=window.Tether.__core["client.js"],{TetherError:ie,endpoint:T,gql:w,unwrap:le,withContext:ce}=I;var M=window.Tether.__core["dom.js"],{attr:f,busy:de,cdnUrl:pe,dataKey:fe,emit:me,formatDate:ge,formatMoney:he,get:h,has:ye,hasTemplate:P,notifyLayoutChanged:we,parseJSONAttr:be,productUrl:$e,qsa:u,readText:Se,repeat:ke,repeatKeyed:Ee,scoped:Te,sel:c,setImage:Pe,setSelected:xe,setText:Ce,setTextTracked:ve,show:_e,toAttributes:Ae,watchImages:Le}=M;var q=window.Tether.__core["loader.js"],{clearProductCache:Ve,getProduct:x,getProducts:De,getRecommendations:Ne,normalizeProductKey:Ie,primeProduct:Me}=q;var O=window.Tether.__core["selling-plans.js"],{GID:Oe,allPlans:C,allocationFor:Re,findPlan:je,hasPlans:Ge,planAdjustment:ze,planCheckoutCharge:Be,planPrice:He,planSavings:Ke,plansForVariant:Ye,toGid:Fe}=O;var R=window.Tether.__core["status.js"],{STATUS_KEYS:Je,boundary:v,isNotFound:We,ownedBy:Xe,resolveProductKey:b,setScopeStatus:Qe}=R;var A=e=>{let t=/^(\d{4})-(01|04|07|10)$/.exec(String(e||""));return t?{y:+t[1],m:+t[2]}:null},j=(e,t)=>`${e}-${String(t).padStart(2,"0")}`;function _(e,t=1){let o=A(e);if(!o)throw new Error(`not a quarterly Shopify API version: ${e}`);let a=o.y*4+(o.m-1)/3+t;return j(Math.floor(a/4),a%4*3+1)}function $(e,t=new Date){if(e==="unstable")return{version:e,ok:!1,note:'"unstable" changes without notice: pin a dated version such as 2026-07'};let o=A(e);if(!o)return{version:e,ok:!1,note:"not a quarterly version (YYYY-01, -04, -07 or -10)"};let a=new Date(Date.UTC(o.y,o.m-1,1)),n=new Date(Date.UTC(o.y+1,o.m-1,1)),d=(n-t)/(30.44*24*3600*1e3),s=`supported until about ${n.toISOString().slice(0,7)}`;return a>t?s="not released yet (release candidate at best)":d<=0?s="no longer supported: Shopify falls back to the oldest supported version. Upgrade (see README)":d<3&&(s=`${s}: plan the upgrade to ${_(e)} or later (see README)`),{version:e,ok:a<=t&&d>0,monthsLeft:Math.round(d),next:_(e),note:s}}var G=/^[A-Z]{2}$/,z=new Set(["PT_BR","PT_PT","ZH_CN","ZH_TW"]),B=()=>`${l.prefix}:market:${l.domain}`,H=()=>({document:typeof document<"u"?document:null,location:typeof window<"u"?window.location:null,storage:(()=>{try{return window.localStorage}catch{return null}})(),global:typeof window<"u"?window:{}});function K(e){let t=String(e||"").trim().toUpperCase();return G.test(t)&&t!=="XX"&&t!=="T1"?t:null}function Y(e){let t=String(e||"").trim().replace("-","_").toUpperCase();if(!t)return null;if(z.has(t))return t;let o=t.split("_")[0];return/^[A-Z]{2,3}$/.test(o)?o:null}function F(e,t){if(!e||!t)return null;let o=String(e.cookie||"").split(";").map(a=>a.trim()).find(a=>a.startsWith(`${t}=`));return o?decodeURIComponent(o.slice(t.length+1)):null}var S=(e,t)=>{if(!e||!t)return null;let o=String(t).toLowerCase(),a=Object.keys(e).find(n=>n.toLowerCase()===o);return a?e[a]:null},Z={saved(e,t){if(e.remember===!1||!t.storage)return null;try{return JSON.parse(t.storage.getItem(B())||"null")}catch{return null}},server(e,t){let o=d=>t.document?.querySelector?.(`meta[name="${d}"]`)?.getAttribute("content"),a=t.global.TETHER_COUNTRY||o("tether-country")||F(t.document,e.cookie||"tether_country"),n=t.global.TETHER_LANGUAGE||o("tether-language");return{country:a,language:n}},webflow(e,t){let o=(t.location?.pathname||"/").split("/").filter(Boolean)[0],a=S(e.locales,o);if(a)return a;let n=t.document?.documentElement?.getAttribute("lang");if(!n)return null;let d=S(e.locales,n)||S(e.locales,n.split("-")[0]);if(d)return{locale:n,...d};if(e.locales&&e.strict)return null;let s=n.split("-")[1];return{language:n,country:s&&s.length===2?s:null,locale:n}}};function L(e=l.markets,t=H()){let o=e||{};if(o.detect===!1)return{};let a=o.detect?o.detect===!0?["saved","server","webflow"]:[].concat(o.detect):["saved"];e=o;let n={sources:{}};return a.forEach(d=>{let s=Z[d]?.(e,t);if(!s)return;let r={country:K(s.country),language:Y(s.language),locale:s.locale||null};Object.entries(r).forEach(([i,p])=>{p&&!n[i]&&(n[i]=p,n.sources[i]=d)})}),n}var J=e=>e?`${String(e).slice(0,4)}\u2026${String(e).slice(-4)} (${String(e).length} chars)`:"(missing)";function W(e){let t=e.id?`#${e.id}`:"",o=e.className&&typeof e.className=="string"?`.${e.className.trim().split(/\s+/).slice(0,2).join(".")}`:"";return`<${e.tagName.toLowerCase()}${t}${o}>`}function U(e=document){let t=[],o=(r,i,p)=>t.push({level:r,message:i,element:p?W(p):void 0,el:p}),a=r=>!!r.closest(c("product")),n=`${c("collection")},${c("products")},${c("recommendations")}`;u(e,c("product")).forEach(r=>{if(r.closest(n)&&r.closest(c("list")))return;let{key:i,fromUrl:p,raw:m}=b(r);m?p&&!i&&o("warn",`${f("product")}="${m}" but this URL has no value for it (e.g. ?handle=my-product).`,r):o("error",`${f("product")} has no value. Bind it to the Shopify handle (CMS field), or use "url:handle".`,r)}),["bind","option-list","option","variant-select","add-to-cart","purchase","plan-list","plan","qty","line-attribute"].forEach(r=>{u(e,c(r)).forEach(i=>{a(i)||r==="line-attribute"&&i.closest(c("group"))||o("warn",`${f(r)} outside any ${f("product")}: it does nothing here.`,i)})}),u(e,c("group-add")).forEach(r=>{r.closest(c("group"))||o("warn",`${f("group-add")} outside a ${f("group")}.`,r)}),[...u(e,c("option-list")),...u(e,c("plan-list")),...u(e,c("cart-lines")),...u(e,c("list"))].forEach(r=>{!r.firstElementChild&&!P(r)&&o("warn","Repeater without a template child: put one example element inside it.",r)}),u(e,n).forEach(r=>{u(r,c("list")).length||o("error",`List without a ${f("list")} child: products have nowhere to render.`,r)});let s=new Set(["in-stock","out-of-stock","backorder","low-stock","on-sale","not-on-sale","has-variants","single-variant","subscription-available","subscription-unavailable","subscription-only","one-time-available","subscription-selected","one-time-selected","has-savings","loading","ready","error","not-found","cart-empty","cart-filled","cart-has-subscription","cart-no-subscription","cart-has-discount","cart-error","list-empty","list-filled"]);return u(e,c("show")).forEach(r=>{let i=h(r,"show");s.has(i)||o("warn",`Unknown ${f("show")}="${i}".`,r)}),u(e,c("bind")).forEach(r=>{let i=h(r,"bind")||"";if(!i.startsWith("metafield:"))return;let p=i.slice(10);(l.metafields||[]).some(g=>(typeof g=="string"?g:`${g.namespace}.${g.key}`)===p)||o("error",`${f("bind")}="${i}" but "${p}" is not in config.metafields, so it stays empty.`,r)}),u(e,c("cart-open")).length&&!u(e,c("cart-drawer")).length&&o("warn",`${f("cart-open")} exists but there is no ${f("cart-drawer")} on this page.`),u(e,c("cart-drawer")).length>1&&o("warn",`More than one ${f("cart-drawer")}.`),u(e,`[${f("state")}="error"]`).forEach(r=>{r.matches(v())&&o("error",`Scope failed to load (${h(r,"error")||"error"}).`,r)}),t}async function X({root:e=document,silent:t=!1,version:o,now:a=new Date}={}){let n={version:o,config:{domain:l.domain||"(missing)",token:J(l.token),apiVersion:l.apiVersion,endpoint:l.domain?T():null,country:l.country,language:l.language,locale:l.locale,markets:l.markets||null,prefix:l.prefix,productPath:l.productPath,metafields:l.metafields,autoMount:l.autoMount,observe:l.observe,onError:typeof l.onError=="function"},apiVersion:$(l.apiVersion,a),market:l.markets?.detect?L(l.markets):null,reachable:!1,shop:null,latencyMs:null,products:[],sellingPlans:[],problems:[]};if(!E())n.problems.push({level:"error",message:"TETHER_CONFIG needs domain and token."});else{let d=Date.now();try{let s=await w("query TetherDiagnose { shop { name primaryDomain { url } paymentSettings { currencyCode } } }",{},{context:!1});n.reachable=!0,n.shop={name:s.shop?.name,url:s.shop?.primaryDomain?.url,currency:s.shop?.paymentSettings?.currencyCode}}catch(s){let r=s.status===401||s.status===403?"Token rejected: use the public Storefront token from the Headless channel, not an Admin token.":s.status===404?"Store or API version not found: check domain (x.myshopify.com) and apiVersion.":"";n.problems.push({level:"error",message:`Storefront API not reachable: ${s.message}${r?`. ${r}`:""}`})}if(n.latencyMs=Date.now()-d,n.reachable){let s=[...new Set(u(e,c("product")).map(i=>b(i).key).filter(Boolean))].slice(0,20);(await Promise.allSettled(s.map(i=>x(i)))).forEach((i,p)=>{if(i.status==="fulfilled"){let m=i.value,g=C(m);n.products.push({key:s[p],handle:m.handle,title:m.title,plans:g.length,requiresSellingPlan:m.requiresSellingPlan}),g.forEach(y=>n.sellingPlans.push({product:m.handle,group:y.group?.name,plan:y.name,id:y.id}))}else n.products.push({key:s[p],error:i.reason?.message}),n.problems.push({level:"error",message:`Product "${s[p]}": ${i.reason?.message}. Is it published to the Headless channel?`})})}}return(!n.apiVersion.ok||(n.apiVersion.monthsLeft??99)<3)&&n.problems.push({level:n.apiVersion.ok?"warn":"error",message:`apiVersion ${l.apiVersion}: ${n.apiVersion.note}`}),typeof document<"u"&&n.problems.push(...U(e)),t||Q(n),n}function Q(e){let t=console,o=e.problems.filter(a=>a.level==="error").length;t.group?.(`[${l.prefix}] diagnose: ${o?`${o} error(s)`:"no errors"}, ${e.problems.length-o} warning(s)`),t.log("version",e.version,"| API",e.apiVersion.version,`(${e.apiVersion.note})`),t.log("config",e.config),e.market&&t.log("market detected",e.market,"(in use:",e.config.country,e.config.language,")"),t.log(e.reachable?`Storefront API reachable: ${e.shop?.name} (${e.latencyMs} ms)`:"Storefront API NOT reachable"),e.products.length&&(t.table||t.log)(e.products),e.sellingPlans.length?(t.table||t.log)(e.sellingPlans):e.reachable&&t.log("No selling plans on the products of this page."),e.problems.forEach(a=>(a.level==="error"?t.error:t.warn)(a.message,a.el||"")),t.groupEnd?.()}window.Tether.__parts.diagnose=k;})();