@occluze/tether 0.6.6 → 0.6.8
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 +3 -3
- package/dist/esm/astro.js +2 -2
- package/dist/esm/chunks/account-C3NP6HFB.js +1 -0
- package/dist/esm/chunks/account-pages-WLK374FO.js +1 -0
- package/dist/esm/chunks/analytics-G3SAWMNL.js +1 -0
- package/dist/esm/chunks/chunk-27PJJZGC.js +1 -0
- package/dist/esm/chunks/chunk-2FSXS55U.js +1 -0
- package/dist/esm/chunks/chunk-FCSWQDVV.js +1 -0
- package/dist/esm/chunks/chunk-FOMSMIAM.js +1 -0
- package/dist/esm/chunks/chunk-GZJTCLLW.js +1 -0
- package/dist/esm/chunks/chunk-HEQILZVR.js +1 -0
- package/dist/esm/chunks/chunk-JOOEXYF3.js +4 -0
- package/dist/esm/chunks/chunk-MPTQYLSM.js +1 -0
- package/dist/esm/chunks/chunk-NEHZ37TU.js +3 -0
- package/dist/esm/chunks/chunk-V74KGEJF.js +1 -0
- package/dist/esm/chunks/chunk-VT4CDUJJ.js +1 -0
- package/dist/esm/chunks/chunk-YJLWX2HK.js +1 -0
- package/dist/esm/chunks/diagnose-6VVGZNTY.js +14 -0
- package/dist/esm/chunks/extras-GJVRDFM3.js +1 -0
- package/dist/esm/chunks/markets-ui-UNB4PTA7.js +1 -0
- package/dist/esm/chunks/search-OU75RNQL.js +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/server.js +2 -1
- package/dist/presets/barba.esm.js +56 -36
- package/dist/tether.account-pages.js +776 -432
- package/dist/tether.account-pages.min.js +1 -1
- package/dist/tether.account.js +655 -321
- package/dist/tether.account.min.js +1 -1
- package/dist/tether.analytics.js +318 -191
- package/dist/tether.analytics.min.js +1 -1
- package/dist/tether.diagnose.js +334 -243
- package/dist/tether.diagnose.min.js +2 -2
- package/dist/tether.extras.js +78 -33
- package/dist/tether.extras.min.js +1 -1
- package/dist/tether.js +3171 -1998
- package/dist/tether.markets.js +231 -126
- package/dist/tether.markets.min.js +1 -1
- package/dist/tether.min.js +0 -0
- package/dist/tether.min.js.map +4 -4
- package/dist/tether.search.js +221 -126
- package/dist/tether.search.min.js +1 -1
- package/package.json +23 -4
- package/src/account/addresses-view.js +92 -0
- package/src/account/browser-session.js +359 -0
- package/src/account/markup.js +48 -0
- package/src/account/operations.js +180 -0
- package/src/account/order-lines.js +96 -0
- package/src/account/order-list.js +91 -0
- package/src/account/order-page.js +192 -0
- package/src/account/page-events.js +288 -0
- package/src/account/server-client.js +172 -0
- package/src/account/shared.js +111 -0
- package/src/account/shopify-auth.js +150 -0
- package/src/account/subscriptions-view.js +158 -0
- package/src/account-api.js +118 -0
- package/src/account-links.js +35 -0
- package/src/account-pages.js +68 -284
- package/src/account.js +281 -317
- package/src/amounts.js +36 -0
- package/src/analytics-shopify.js +241 -0
- package/src/analytics.js +304 -184
- package/src/api-version.js +75 -25
- package/src/astro.js +233 -68
- package/src/cart/checkout.js +97 -0
- package/src/cart/drawer.js +138 -0
- package/src/cart/mutations.js +234 -0
- package/src/cart/render.js +294 -0
- package/src/cart/store.js +326 -0
- package/src/cart.js +322 -481
- package/src/client.js +214 -78
- package/src/collection.js +126 -57
- package/src/config.js +323 -59
- package/src/controls/cart-controls.js +155 -0
- package/src/controls/discount.js +96 -0
- package/src/controls/extras.js +63 -0
- package/src/controls/navigation.js +83 -0
- package/src/diagnose-markup.js +333 -0
- package/src/diagnose.js +251 -202
- package/src/dom.js +219 -220
- package/src/extras.js +119 -37
- package/src/fragments.js +115 -22
- package/src/images.js +104 -0
- package/src/index.js +245 -285
- package/src/initial.js +78 -66
- package/src/lazy-iife.js +92 -22
- package/src/lazy.js +25 -4
- package/src/loader.js +263 -124
- package/src/market-codes.js +35 -0
- package/src/markets-ui.js +169 -55
- package/src/markets.js +286 -85
- package/src/markup.js +64 -0
- package/src/mounting.js +214 -91
- package/src/page-market.js +116 -0
- package/src/parts/account-pages.js +4 -1
- package/src/parts/account.js +4 -1
- package/src/parts/analytics.js +4 -1
- package/src/parts/diagnose.js +4 -1
- package/src/parts/extras.js +4 -1
- package/src/parts/markets.js +4 -1
- package/src/parts/search.js +4 -1
- package/src/presets/barba.js +120 -30
- package/src/product-events.js +130 -0
- package/src/product-render.js +257 -0
- package/src/product-state.js +318 -0
- package/src/product.js +233 -459
- package/src/repeaters.js +173 -0
- package/src/search.js +277 -107
- package/src/selling-plans.js +107 -47
- package/src/server.js +168 -205
- package/src/shopify-values.js +89 -0
- package/src/status.js +99 -39
- package/src/store-html.js +0 -0
- package/src/storefront/catalog.js +199 -0
- package/src/storefront/json-ld.js +167 -0
- package/src/variant-render.js +165 -0
- package/types/astro.d.ts +13 -2
- package/types/index.d.ts +178 -27
- package/types/server.d.ts +89 -17
- package/dist/esm/chunks/account-QUBHQG3C.js +0 -1
- package/dist/esm/chunks/account-pages-VWDHF6WA.js +0 -1
- package/dist/esm/chunks/analytics-SLATWPLC.js +0 -1
- package/dist/esm/chunks/chunk-64TUD3QR.js +0 -1
- package/dist/esm/chunks/chunk-AJLPU2JC.js +0 -4
- package/dist/esm/chunks/chunk-FIOZPPC5.js +0 -1
- package/dist/esm/chunks/chunk-K2YEQAIH.js +0 -1
- package/dist/esm/chunks/chunk-L2TRRKYV.js +0 -1
- package/dist/esm/chunks/chunk-RREHGH4A.js +0 -1
- package/dist/esm/chunks/chunk-VC46IEJQ.js +0 -1
- package/dist/esm/chunks/chunk-VCPI7MJ2.js +0 -1
- package/dist/esm/chunks/chunk-VPVJPNB4.js +0 -1
- package/dist/esm/chunks/chunk-ZIUIWEON.js +0 -1
- package/dist/esm/chunks/diagnose-VXQBSD3A.js +0 -14
- package/dist/esm/chunks/extras-R4X34VQL.js +0 -1
- package/dist/esm/chunks/markets-ui-F3R5T5EL.js +0 -1
- package/dist/esm/chunks/search-NILMGYXG.js +0 -1
package/dist/tether.min.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/config.js", "../src/client.js", "../src/cart.js", "../src/
|
|
4
|
-
"sourcesContent": ["/**\n * Runtime config. One shared object, mutated by configure(), read everywhere.\n */\n\nexport const DEFAULTS = {\n // Shopify Storefront API\n domain: '', // 'your-store.myshopify.com'\n token: '', // public Storefront API access token\n apiVersion: '2026-07',\n country: undefined, // ISO code, e.g. 'NL' -> @inContext(country: NL)\n language: undefined, // e.g. 'NL' -> @inContext(language: NL)\n locale: undefined, // Intl locale for money/dates, e.g. 'nl-NL'\n markets: null, // { detect: true, locales: { de: { country: 'DE', language: 'DE' } }, cookie, remember } (markets.js)\n\n // Markup\n prefix: 'tether', // attribute prefix: tether-product, tether-bind, ...\n productPath: '/product', // Webflow CMS template path for products\n collectionPath: '/collection',\n\n // Fetching\n metafields: [], // ['custom.material', { namespace, key }]\n imagesFirst: 25,\n variantsFirst: 100,\n sellingPlanGroupsFirst: 10,\n sellingPlansFirst: 25,\n collectionFirst: 24,\n retries: 2,\n revalidate: true, // products from the server (tether/server hydrate()): refresh once in the background\n\n // Cart\n storageKey: null, // defaults to `tether:cart:<domain>`\n cartDrawerOpenClass: 'is-open',\n openCartOnAdd: true,\n cartFocus: true, // move focus into the open cart, keep Tab inside it, restore it on close\n checkoutTarget: '_self', // '_self' or '_blank'\n\n // Subscriptions\n defaultPurchase: 'one-time', // 'one-time' | 'subscription'\n variantUrl: false, // true: ?variant= follows the visitor's choice on the main product (shareable links)\n maxAge: 60, // seconds a Shopify answer may be cached (0 = Shopify's own caching, can be hours)\n lowStock: 5, // tether-show=\"low-stock\" at this many or fewer (needs inventory access)\n\n // Mounting\n autoMount: true, // mount document on DOMContentLoaded\n observe: false, // auto-mount nodes added later (CMS load-more, filters)\n astro: true, // mount on Astro View Transitions (astro:page-load); false if you do it yourself\n partsUrl: null, // folder of tether.markets/diagnose(.min).js for the <script> build (default: next to it)\n\n // Formatting\n formatMoney: null, // (money, locale) => string\n\n // Hooks (all optional)\n onLayoutChange: null, // (reason) => void. Default refreshes ScrollTrigger if present\n onCartOpen: null, // (drawers) => void, e.g. lock scroll\n onCartClose: null, // (drawers) => void\n onLineEnter: null, // (node) => void, animate a new cart line in\n onLineLeave: null, // (node, done) => void, animate out, then call done()\n onValueChange: null, // (el, previousText) => void, e.g. text scramble\n onError: null, // (error, context) => void\n\n debug: false,\n};\n\nexport const cfg = { ...DEFAULTS };\n\nexport function configure(overrides = {}) {\n Object.keys(cfg).forEach((k) => delete cfg[k]);\n Object.assign(cfg, DEFAULTS, overrides);\n if (cfg.domain) cfg.domain = String(cfg.domain).replace(/^https?:\\/\\//, '').replace(/\\/.*$/, '');\n if (!cfg.storageKey) cfg.storageKey = `${cfg.prefix}:cart:${cfg.domain}`;\n if (cfg.apiVersion === 'unstable') warn('apiVersion \"unstable\" changes without notice. Pin a dated version (e.g. 2026-07).');\n return cfg;\n}\n\nexport const isConfigured = () => Boolean(cfg.domain && cfg.token);\n\nexport function log(...a) { if (cfg.debug) console.log(`[${cfg.prefix}]`, ...a); }\nexport function warn(...a) { console.warn(`[${cfg.prefix}]`, ...a); }\n\nexport function reportError(err, context) {\n warn(context, err && (err.message || err.code) ? err.message || err.code : err);\n if (typeof cfg.onError === 'function') {\n try { cfg.onError(err, context); } catch { /* never let a hook break us */ }\n }\n}\n", "/**\n * Storefront API client: one fetch wrapper with @inContext, retries and\n * readable errors. Exposed as Tether.query() for anything Tether doesn't cover.\n */\nimport { cfg, log } from './config.js';\n\nexport class TetherError extends Error {\n constructor(message, { status, errors, userErrors, code } = {}) {\n super(message);\n this.name = 'TetherError';\n this.code = code || (status ? `HTTP_${status}` : 'ERROR');\n this.status = status;\n this.errors = errors;\n this.userErrors = userErrors;\n }\n}\n\nexport function endpoint(conf = cfg) {\n return `https://${conf.domain}/api/${conf.apiVersion}/graphql.json`;\n}\n\n/**\n * Adds @inContext(country, language) to the first operation in the document,\n * so prices, currency and translations follow the configured market.\n * Operations are always written first, fragments after, so the first match is\n * the operation.\n */\nexport function withContext(query, ctx = cfg) {\n const args = [];\n if (ctx.country) args.push(`country: ${String(ctx.country).toUpperCase()}`);\n if (ctx.language) args.push(`language: ${String(ctx.language).toUpperCase().replace('-', '_')}`);\n if (!args.length || /@inContext/.test(query)) return query;\n\n const tag = `@inContext(${args.join(', ')})`;\n // Named (query Name($x: T)), anonymous (query { \u2026 }) and shorthand ({ \u2026 }) queries.\n if (/^\\s*\\{/.test(query)) return `query ${tag} ${query.trimStart()}`;\n return query.replace(/^(\\s*(?:query|mutation)(?:\\s+\\w+)?\\s*(?:\\([^)]*\\))?)/, `$1 ${tag}`);\n}\n\nconst sleep = (ms) => new Promise((r) => setTimeout(r, ms));\n\n/** What a status means, for errors Shopify sends without a message (401/403 have none). */\nfunction statusText(status, conf) {\n if (status === 401 || status === 403) {\n return `Shopify rejected the Storefront token for ${conf.domain} (${status}): use the public Storefront API token (Headless channel)${/^shpat_/.test(conf.token) ? ', not an Admin API token (shpat_\u2026)' : ''}`;\n }\n return status === 404 ? `Store or API version not found (404): check domain ${conf.domain} and apiVersion ${conf.apiVersion}` : `HTTP ${status} from ${conf.domain}`;\n}\n\n/**\n * One Storefront API request with retries, for any config object (the browser's shared config,\n * or the server module's own). gql() below is the browser version.\n */\nexport async function request(conf, query, variables = {}, { context = true } = {}) {\n if (!conf.domain || !conf.token) {\n throw new TetherError('Tether is not configured: domain and token are required', { code: 'NOT_CONFIGURED' });\n }\n\n // Shopify caches the response of an identical query text (prices included, for hours after a\n // change). A time bucket in a comment keeps answers at most maxAge seconds old (default 60).\n let text = context ? withContext(query, conf) : query;\n const age = conf.maxAge ?? 60;\n if (age > 0 && !/^\\s*mutation\\b/.test(text)) text += ` #${Math.floor(Date.now() / (age * 1000))}`;\n const body = JSON.stringify({ query: text, variables });\n let attempt = 0;\n\n for (;;) {\n let res;\n try {\n res = await (conf.fetch || fetch)(endpoint(conf), {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Shopify-Storefront-Access-Token': conf.token,\n },\n body,\n });\n } catch (err) {\n if (attempt++ < conf.retries) { await sleep(300 * 2 ** attempt); continue; }\n throw new TetherError(`Network error: ${err.message}`, { code: 'NETWORK' });\n }\n\n if (res.status === 430) throw new TetherError('Shopify security rejection (430)', { status: 430 });\n\n const retryable = res.status === 429 || res.status >= 500;\n if (retryable && attempt++ < conf.retries) {\n log('retry', res.status, attempt);\n await sleep(300 * 2 ** attempt);\n continue;\n }\n\n let json;\n try { json = await res.json(); } catch {\n throw new TetherError(res.ok ? `Invalid response (${res.status})` : statusText(res.status, conf), { status: res.status });\n }\n\n if (json.errors?.length) {\n // Token without unauthenticated_read_product_inventory: drop the field and retry.\n const inventoryDenied = json.errors.some((e) => /quantityAvailable/.test(e.message || ''));\n if (inventoryDenied && /\\bquantityAvailable\\b/.test(body)) {\n log('no inventory permission, retrying without quantityAvailable');\n return request(conf, query.replace(/\\bquantityAvailable\\b/g, ''), variables, { context });\n }\n // An older apiVersion without cart warnings (before 2024-07): retry without them.\n if (json.errors.some((e) => /'warnings'/.test(e.message || '')) && /warnings \\{ code message target \\}/.test(query)) {\n return request(conf, query.replace(/ warnings \\{ code message target \\}/g, ''), variables, { context });\n }\n const throttled = json.errors.some((e) => e.extensions?.code === 'THROTTLED');\n if (throttled && attempt++ < conf.retries) { await sleep(500 * 2 ** attempt); continue; }\n const message = json.errors.map((e) => e.message).filter(Boolean).join(' | ');\n throw new TetherError(res.ok ? message || 'Storefront API error' : (res.status === 401 || res.status === 403 || !message ? statusText(res.status, conf) : message), {\n status: res.status, errors: json.errors,\n });\n }\n if (!res.ok) throw new TetherError(statusText(res.status, conf), { status: res.status });\n\n return json.data;\n }\n}\n\nexport const gql = (query, variables, opts) => request(cfg, query, variables, opts);\n\n/** Throws on mutation userErrors, returns the payload otherwise. */\nexport function unwrap(payload, name) {\n if (!payload) throw new TetherError(`${name}: empty response`);\n const errs = payload.userErrors || [];\n if (errs.length) {\n throw new TetherError(errs.map((e) => e.message).join(' | '), { userErrors: errs });\n }\n return payload;\n}\n", "/**\n * Cart: Shopify Cart API, state in localStorage, document-wide rendering.\n *\n * Every mutation is queued, so fast clicking never races. All public methods\n * return the updated cart.\n */\nimport { cfg, log, reportError } from './config.js';\nimport { gql, unwrap, TetherError } from './client.js';\nimport { cartFragment } from './fragments.js';\nimport { getProduct } from './loader.js';\nimport { allPlans, GID } from './selling-plans.js';\nimport {\n attr, sel, get, qsa, emit, formatMoney, setText, setTextTracked, setImage, show,\n repeat, repeatKeyed, toAttributes, productUrl, notifyLayoutChanged,\n} from './dom.js';\n\n/** Accepts many shapes and returns a Shopify CartLineInput. */\nexport function toLineInput(input, quantity = 1, opts = {}) {\n const src = typeof input === 'object' && input !== null ? input : { variantId: input, quantity, ...opts };\n const merchandiseId = GID.variant(src.merchandiseId || src.variantId || src.id);\n if (!merchandiseId) throw new TetherError('add(): variantId is required');\n const line = { merchandiseId, quantity: Math.max(1, parseInt(src.quantity ?? 1, 10) || 1) };\n const plan = src.sellingPlanId || src.sellingPlan;\n if (plan) line.sellingPlanId = GID.sellingPlan(plan);\n const attrs = toAttributes(src.attributes);\n if (attrs.length) line.attributes = attrs;\n return line;\n}\n\nfunction mutation(name, args, inner) {\n return `mutation Tether_${name}(${args}){${name}(${inner}){cart{...TetherCart}userErrors{field message}warnings{code message target}}}${cartFragment()}`;\n}\n\nconst FOCUSABLE = 'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex=\"-1\"])';\nlet returnFocus = null;\n\n/** Focusable elements inside an open drawer, in order (visible ones only). */\nexport const focusables = (d) => qsa(d, FOCUSABLE).filter((el) => el.offsetParent !== null || el === document.activeElement);\n\n/** aria-expanded on the open buttons; dialog semantics on drawers (unless the markup has its own). */\nfunction ariaState(open) {\n qsa(document, sel('cart-open')).forEach((b) => b.setAttribute('aria-expanded', String(open)));\n qsa(document, sel('cart-drawer')).forEach((d) => {\n if (!d.hasAttribute('role')) d.setAttribute('role', 'dialog');\n if (!d.hasAttribute('aria-label') && !d.hasAttribute('aria-labelledby')) d.setAttribute('aria-label', get(d, 'cart-label') || 'Cart');\n d.setAttribute('aria-modal', String(open));\n // Closed: hidden from screen readers and out of the Tab order (inert), like a closed dialog.\n if (!d.classList.contains(cfg.cartDrawerOpenClass)) { d.setAttribute('aria-hidden', 'true'); if (cfg.cartFocus !== false) d.inert = true; }\n });\n}\n\nconst isMissingCart = (err) => /does not exist|not found|invalid id/i.test(err?.message || '');\n\nexport const Cart = {\n state: null,\n _chain: Promise.resolve(),\n\n id() { try { return localStorage.getItem(cfg.storageKey); } catch { return null; } },\n _setId(id) {\n try {\n if (id) localStorage.setItem(cfg.storageKey, id);\n else localStorage.removeItem(cfg.storageKey);\n } catch { /* private mode */ }\n },\n\n get lines() { return this.state?.lines?.nodes || []; },\n get count() { return this.state?.totalQuantity || 0; },\n\n lastError: null,\n /** Set by the account part while a customer is logged in (Customer Account API token). */\n customerAccessToken: null,\n /** line id -> { qty, done }: what quick +/- clicks asked for, shown until Shopify has answered. */\n pendingQty: new Map(),\n /** Shopify's notes on the last change, e.g. less stock than asked: [{ code, message }]. */\n warnings: [],\n /** true once the saved cart (or the absence of one) is known. */\n loaded: false,\n\n _take(payload, name) {\n const p = unwrap(payload, name);\n // Shopify can repeat a warning per line or code: each message once.\n this.warnings = (p.warnings || []).filter((w, i, all) => all.findIndex((x) => x.message === w.message) === i)\n .map((w) => ({ ...w, message: (typeof cfg.warningText === 'function' && cfg.warningText(w)) || w.message }));\n if (this.warnings.length) emit('cart-warning', { warnings: this.warnings });\n return p.cart;\n },\n\n _queue(fn) {\n const run = this._chain.then(fn, fn).then((value) => {\n if (this.lastError) { this.lastError = null; this.render(); }\n return value;\n }, (err) => {\n // tether-show=\"cart-error\" becomes visible until the next successful cart call.\n this.lastError = err;\n this.render();\n emit('cart-error', { error: err });\n throw err;\n });\n this._chain = run.catch(() => {});\n return run;\n },\n\n _commit(cart, reason) {\n this.state = cart;\n if (cart?.id) this._setId(cart.id);\n // Other tabs reload the cart (storage event); the count also shows at once on the next page.\n try { localStorage.setItem(`${cfg.storageKey}:seen`, `${Date.now()}|${cart?.totalQuantity || 0}`); } catch { /* private mode */ }\n this.render();\n emit('cart-updated', { cart, reason });\n return cart;\n },\n\n async init() {\n const id = this.id();\n if (!id) { this.state = null; this.loaded = true; this.render(); emit('cart-updated', { cart: null, reason: 'load' }); return null; }\n // Until the saved cart has loaded, show its last known count instead of the page's 0.\n if (!this.loaded) {\n try {\n const n = (localStorage.getItem(`${cfg.storageKey}:seen`) || '').split('|')[1];\n if (n) qsa(document, sel('cart-count')).forEach((el) => { if (/^\\s*0?\\s*$/.test(el.textContent)) el.textContent = n; });\n } catch { /* private mode */ }\n }\n try {\n const data = await gql(`query TetherCart($id:ID!){cart(id:$id){...TetherCart}}${cartFragment()}`, { id });\n if (!data.cart) { this._setId(null); this.state = null; } else this.state = data.cart;\n } catch (err) {\n reportError(err, 'cart load failed');\n this.lastError = err;\n // Keep the cart id on network/API errors: the cart is probably fine, Shopify isn't reachable.\n if (isMissingCart(err)) this._setId(null);\n this.state = null;\n }\n this.loaded = true;\n this.render();\n emit('cart-updated', { cart: this.state, reason: 'load' }); // islands (cart.subscribe) hear the loaded cart\n return this.state;\n },\n\n async _create(input = {}) {\n const buyerIdentity = cfg.country || this.customerAccessToken ? {\n ...(cfg.country ? { countryCode: String(cfg.country).toUpperCase() } : {}),\n ...(this.customerAccessToken ? { customerAccessToken: this.customerAccessToken } : {}),\n } : undefined;\n const data = await gql(\n mutation('cartCreate', '$input: CartInput!', 'input: $input'),\n { input: { buyerIdentity, ...input } },\n );\n return this._take(data.cartCreate, 'cartCreate');\n },\n\n /** Runs a cart mutation; creates a fresh cart if ours expired. */\n async _mutate(name, args, inner, variables, createInput) {\n const cartId = this.id();\n if (!cartId) return createInput ? this._create(createInput) : null;\n try {\n const data = await gql(mutation(name, `$cartId: ID!, ${args}`, `cartId: $cartId, ${inner}`), { ...variables, cartId });\n return this._take(data[name], name);\n } catch (err) {\n if (createInput && isMissingCart(err)) {\n log('cart expired, creating a new one');\n this._setId(null);\n return this._create(createInput);\n }\n throw err;\n }\n },\n\n /**\n * add('gid://shopify/ProductVariant/1', 2)\n * add({ variantId, quantity, sellingPlanId, attributes })\n * add([line, line]) // bundles / build-a-box in one request\n */\n add(input, quantity = 1, opts = {}) {\n const lines = (Array.isArray(input) ? input : [input]).map((l) => toLineInput(l, quantity, opts));\n return this._queue(async () => {\n const cart = await this._mutate('cartLinesAdd', '$lines: [CartLineInput!]!', 'lines: $lines', { lines }, { lines });\n this._commit(cart, 'add');\n emit('added', { cart, lines });\n if (cfg.openCartOnAdd) this.open();\n return cart;\n });\n },\n\n /**\n * updateLine(lineId, 3)\n * updateLine(lineId, { quantity, sellingPlanId, attributes })\n * sellingPlanId: null switches a line back to one-time purchase.\n */\n updateLine(lineId, patch) {\n const p = typeof patch === 'number' ? { quantity: patch } : { ...patch };\n if (p.quantity !== undefined && p.quantity <= 0) return this.removeLine(lineId);\n\n const line = { id: lineId };\n if (p.quantity !== undefined) line.quantity = p.quantity;\n if ('sellingPlanId' in p) line.sellingPlanId = p.sellingPlanId ? GID.sellingPlan(p.sellingPlanId) : null;\n if (p.attributes) line.attributes = toAttributes(p.attributes);\n if (p.merchandiseId || p.variantId) line.merchandiseId = GID.variant(p.merchandiseId || p.variantId);\n\n return this._queue(async () => this._commit(\n await this._mutate('cartLinesUpdate', '$lines: [CartLineUpdateInput!]!', 'lines: $lines', { lines: [line] }),\n 'update',\n ));\n },\n\n /**\n * +1 / -1 for a line. Quick clicks add up: each builds on the quantity the last click asked for,\n * which shows at once (tether-line=\"quantity\", Cart.lines) until Shopify has answered.\n */\n changeQuantity(lineId, delta) {\n const current = this.lines.find((l) => l.id === lineId);\n if (!current) return Promise.resolve(this.state);\n const target = Math.max(0, (this.pendingQty.get(lineId)?.qty ?? current.quantity) + delta);\n const job = { qty: target, done: false };\n this.pendingQty.set(lineId, job);\n this.render();\n emit('cart-updated', { cart: this.state, reason: 'pending' });\n const latest = () => this.pendingQty.get(lineId) === job;\n return this._queue(async () => {\n // Quick clicks: only the latest target goes to Shopify; the ones it replaced are skipped.\n if (!latest()) return this.state;\n const now = this.lines.find((l) => l.id === lineId);\n if (now && now.quantity === target) return this.state; // e.g. + then -: nothing to change\n const cart = target > 0\n ? await this._mutate('cartLinesUpdate', '$lines: [CartLineUpdateInput!]!', 'lines: $lines', { lines: [{ id: lineId, quantity: target }] })\n : await this._mutate('cartLinesRemove', '$lineIds: [ID!]!', 'lineIds: $lineIds', { lineIds: [lineId] });\n // A newer click is on its way: keep this answer, but show totals and count only once that\n // one is in (no stepping through every reply).\n if (!latest()) { this.state = cart; if (cart?.id) this._setId(cart.id); return cart; }\n return this._commit(cart, target > 0 ? 'update' : 'remove');\n }).finally(() => {\n if (latest()) { this.pendingQty.delete(lineId); this.render(); emit('cart-updated', { cart: this.state, reason: 'settled' }); }\n });\n },\n\n /** Quantity to show for a line: the one asked for while an update is on its way. */\n quantityOf(line) { return this.pendingQty.get(line.id)?.qty ?? line.quantity; },\n\n removeLine(lineIds) {\n const ids = Array.isArray(lineIds) ? lineIds : [lineIds];\n return this._queue(async () => this._commit(\n await this._mutate('cartLinesRemove', '$lineIds: [ID!]!', 'lineIds: $lineIds', { lineIds: ids }),\n 'remove',\n ));\n },\n\n clear() {\n const ids = this.lines.map((l) => l.id);\n if (!ids.length) return Promise.resolve(this.state);\n return this.removeLine(ids);\n },\n\n setNote(note) {\n return this._queue(async () => this._commit(\n await this._mutate('cartNoteUpdate', '$note: String!', 'note: $note', { note: note ?? '' }, { note: note ?? '' }),\n 'note',\n ));\n },\n\n /** Cart-level attributes, merged with existing ones. Value '' removes a key. */\n setAttributes(obj) {\n const merged = new Map((this.state?.attributes || []).map((a) => [a.key, a.value]));\n toAttributes(obj).forEach((a) => merged.set(a.key, a.value));\n const attributes = [...merged].filter(([, v]) => v !== '').map(([key, value]) => ({ key, value }));\n return this._queue(async () => this._commit(\n await this._mutate('cartAttributesUpdate', '$attributes: [AttributeInput!]!', 'attributes: $attributes', { attributes }, { attributes }),\n 'attributes',\n ));\n },\n\n /** Replaces the discount codes. Pass [] to remove all. */\n setDiscountCodes(codes) {\n const discountCodes = (Array.isArray(codes) ? codes : [codes]).map((c) => String(c).trim()).filter(Boolean);\n return this._queue(async () => this._commit(\n await this._mutate('cartDiscountCodesUpdate', '$discountCodes: [String!]!', 'discountCodes: $discountCodes', { discountCodes }, { discountCodes }),\n 'discount',\n ));\n },\n\n /**\n * Adds a code. A code Shopify doesn't accept isn't kept in the cart (it would warn on every change):\n * it's removed again and the promise rejects with code INVALID_DISCOUNT.\n */\n async applyDiscount(code) {\n const current = (this.state?.discountCodes || []).map((d) => d.code);\n const cart = await this.setDiscountCodes([...new Set([...current, code])]);\n const hit = (cart?.discountCodes || []).find((d) => d.code.toLowerCase() === String(code).toLowerCase());\n if (hit?.applicable) return cart;\n await this.removeDiscount(code).catch(() => {});\n throw new TetherError(`Discount code not valid: ${code}`, { code: 'INVALID_DISCOUNT' });\n },\n\n removeDiscount(code) {\n const k = String(code).toLowerCase();\n return this.setDiscountCodes((this.state?.discountCodes || []).map((d) => d.code).filter((c) => c.toLowerCase() !== k));\n },\n\n /** { countryCode, email, phone } \u2014 changes currency/prices for that market. */\n setBuyerIdentity(buyerIdentity, { create = true } = {}) {\n return this._queue(async () => {\n const cart = await this._mutate('cartBuyerIdentityUpdate', '$buyerIdentity: CartBuyerIdentityInput!', 'buyerIdentity: $buyerIdentity', { buyerIdentity }, create ? { buyerIdentity } : null)\n .catch((err) => {\n if (create || !isMissingCart(err)) throw err;\n this._setId(null); // expired cart: forget it instead of creating an empty one\n return null;\n });\n return this._commit(cart, 'buyer-identity');\n });\n },\n\n /**\n * Goes to Shopify checkout. With checkoutTarget '_blank' the tab is opened\n * inside the click (Safari blocks window.open after an await) and gets its\n * URL once we have it.\n */\n async checkout(target = cfg.checkoutTarget) {\n const id = this.id();\n if (!id || (this.state && !this.count)) return null; // nothing to check out\n const tab = target === '_blank' ? window.open('', '_blank') : null;\n if (tab) { try { tab.opener = null; } catch { /* ignore */ } }\n\n try {\n const data = await gql('query TetherCheckout($id: ID!) { cart(id: $id) { checkoutUrl } }', { id });\n let url = (this.beforeCheckout && await this.beforeCheckout().catch(() => null)) || data.cart?.checkoutUrl;\n if (url && this.customerAccessToken) url += `${url.includes('?') ? '&' : '?'}logged_in=true`;\n if (!url) throw new TetherError('No checkoutUrl (cart empty or expired)');\n emit('checkout', { url, cart: this.state });\n if (tab && !tab.closed) tab.location.href = url;\n else window.location.href = url;\n return url;\n } catch (err) {\n if (tab) tab.close();\n reportError(err, 'checkout failed');\n return null;\n }\n },\n\n // -------------------------------------------------------------- drawer\n\n drawers() { return qsa(document, sel('cart-drawer')); },\n\n /** Without a tether-cart-drawer (a React/Svelte/Vue cart), open/close still work: as state for subscribe. */\n _open: false,\n isOpen() {\n const ds = this.drawers();\n return ds.length ? ds.some((d) => d.classList.contains(cfg.cartDrawerOpenClass)) : this._open;\n },\n\n open() {\n if (this.isOpen()) return;\n this._open = true;\n const ds = this.drawers().filter((d) => get(d, 'cart-drawer') !== 'manual');\n ds.forEach((d) => { d.inert = false; d.classList.add(cfg.cartDrawerOpenClass); d.setAttribute('aria-hidden', 'false'); });\n ariaState(true);\n if (cfg.cartFocus !== false && ds[0]) {\n // Move focus into the cart (after the open transition has made it visible).\n returnFocus = document.activeElement;\n setTimeout(() => {\n const target = focusables(ds[0])[0] || ds[0];\n if (target === ds[0] && !ds[0].hasAttribute('tabindex')) ds[0].tabIndex = -1;\n target.focus?.({ preventScroll: true });\n }, 60);\n }\n if (typeof cfg.onCartOpen === 'function') cfg.onCartOpen(ds);\n emit('cart-toggled', { open: true });\n },\n\n close() {\n if (!this.isOpen()) return;\n this._open = false;\n const ds = this.drawers();\n const hadFocus = ds.some((d) => d.contains(document.activeElement));\n ds.forEach((d) => { d.classList.remove(cfg.cartDrawerOpenClass); d.setAttribute('aria-hidden', 'true'); if (cfg.cartFocus !== false) d.inert = true; });\n ariaState(false);\n if (hadFocus && returnFocus?.isConnected) returnFocus.focus({ preventScroll: true });\n returnFocus = null;\n if (typeof cfg.onCartClose === 'function') cfg.onCartClose(ds);\n emit('cart-toggled', { open: false });\n },\n\n toggle() { if (this.isOpen()) this.close(); else this.open(); },\n\n /**\n * For framework islands (React, Svelte, Vue): fn(cart, { open }) now and on every change.\n * Returns a function that stops listening.\n */\n subscribe(fn) {\n const call = () => fn(this.state, { open: this.isOpen(), count: this.count, loaded: this.loaded, warnings: this.warnings });\n const h = () => call();\n ['cart-updated', 'cart-toggled'].forEach((e) => document.addEventListener(`${cfg.prefix}:${e}`, h));\n call();\n return () => ['cart-updated', 'cart-toggled'].forEach((e) => document.removeEventListener(`${cfg.prefix}:${e}`, h));\n },\n\n // -------------------------------------------------------------- render\n\n render() {\n const cart = this.state;\n const count = cart ? cart.totalQuantity : 0;\n const money = (k) => (cart ? formatMoney(cart.cost?.[k]) : '');\n\n ariaState(this.isOpen());\n qsa(document, sel('cart-count')).forEach((el) => setTextTracked(el, count));\n qsa(document, sel('cart-subtotal')).forEach((el) => setTextTracked(el, money('subtotalAmount')));\n qsa(document, sel('cart-total')).forEach((el) => setTextTracked(el, money('totalAmount')));\n qsa(document, sel('cart-checkout-charge')).forEach((el) => setTextTracked(el, money('checkoutChargeAmount')));\n\n const hasSub = this.lines.some((l) => l.sellingPlanAllocation);\n const conds = {\n 'cart-empty': count === 0,\n 'cart-filled': count > 0,\n 'cart-has-subscription': hasSub,\n 'cart-no-subscription': !hasSub,\n 'cart-has-discount': (cart?.discountCodes || []).some((d) => d.applicable),\n 'cart-error': Boolean(this.lastError),\n 'cart-warning': this.warnings.length > 0,\n };\n qsa(document, sel('cart-warning')).forEach((el) => setTextTracked(el, [...new Set(this.warnings.map((w) => w.message))].join(' ')));\n qsa(document, sel('show')).forEach((el) => {\n const k = get(el, 'show');\n if (k in conds && !el.closest(sel('product'))) show(el, conds[k]);\n });\n qsa(document, sel('checkout')).forEach((el) => {\n el.classList.toggle('is-disabled', !count);\n el.setAttribute('aria-disabled', String(!count));\n });\n\n qsa(document, `textarea${sel('cart-note')},input${sel('cart-note')}`).forEach((el) => {\n if (document.activeElement !== el) el.value = cart?.note || '';\n });\n\n qsa(document, sel('cart-discounts')).forEach((container) => {\n repeat(container, cart?.discountCodes || [], (node, d) => {\n node.setAttribute(attr('discount-code'), d.code);\n const t = node.querySelector(sel('discount', 'code')) || (node.firstElementChild ? null : node);\n if (t) setText(t, d.code);\n node.classList.toggle('is-inapplicable', !d.applicable);\n });\n });\n\n qsa(document, sel('cart-lines')).forEach((container) => {\n repeatKeyed(container, this.lines, (l) => l.id, (node, line) => renderLine(node, line), {\n onEnter: cfg.onLineEnter, onLeave: cfg.onLineLeave,\n });\n });\n\n if (cart) notifyLayoutChanged('cart');\n },\n};\n\nfunction lineValue(line, key) {\n const m = line.merchandise || {};\n const plan = line.sellingPlanAllocation?.sellingPlan;\n switch (key) {\n case 'title': return m.product?.title;\n case 'product-title': return m.product?.title;\n case 'variant-title': return m.title === 'Default Title' ? '' : m.title;\n case 'options': return (m.selectedOptions || [])\n .filter((o) => o.value !== 'Default Title').map((o) => `${o.name}: ${o.value}`).join(', ');\n case 'vendor': return m.product?.vendor;\n case 'sku': return m.sku;\n case 'price': return formatMoney(line.cost?.amountPerQuantity || m.price);\n case 'compare-at-price': return formatMoney(line.cost?.compareAtAmountPerQuantity || m.compareAtPrice);\n case 'line-total': return formatMoney(line.cost?.totalAmount);\n case 'line-subtotal': return formatMoney(line.cost?.subtotalAmount);\n case 'quantity': return Cart.quantityOf(line);\n case 'plan': return plan?.name || '';\n case 'plan-description': return plan?.description || '';\n case 'components': return (line.lineComponents || [])\n .map((c) => `${c.quantity} \u00D7 ${c.merchandise?.product?.title || ''}`).join(', ');\n default:\n if (key.startsWith('attribute:')) {\n const k = key.slice('attribute:'.length);\n return (line.attributes || []).find((a) => a.key === k)?.value || '';\n }\n return undefined;\n }\n}\n\nfunction renderLine(node, line) {\n const m = line.merchandise || {};\n const isSub = Boolean(line.sellingPlanAllocation);\n node.setAttribute(attr('line-id'), line.id);\n node.classList.toggle('is-subscription', isSub);\n\n qsa(node, sel('line')).forEach((el) => {\n const key = get(el, 'line');\n if (key === 'image') return setImage(el, m.image?.url || m.product?.featuredImage?.url, m.product?.title);\n if (key === 'url') {\n const u = productUrl(m.product?.handle, m.product?.id);\n const q = new URLSearchParams();\n if (m.id) q.set('variant', String(m.id).split('/').pop());\n const plan = line.sellingPlanAllocation?.sellingPlan?.id;\n if (plan) q.set('selling_plan', plan.split('/').pop());\n const qs = q.toString();\n return el.setAttribute('href', qs ? `${u}${u.includes('?') ? '&' : '?'}${qs}` : u);\n }\n const v = lineValue(line, key);\n if (v !== undefined) setTextTracked(el, v);\n return undefined;\n });\n\n // Shopify's note about this line (e.g. less stock than asked): class is-warning, tether-line=\"warning\".\n const warning = Cart.warnings.find((w) => w.target === line.id);\n node.classList.toggle('is-warning', Boolean(warning));\n const pending = Cart.pendingQty.has(line.id);\n node.classList.toggle('is-busy', pending);\n if (pending) node.setAttribute('aria-busy', 'true'); else node.removeAttribute('aria-busy');\n qsa(node, sel('line', 'warning')).forEach((el) => setTextTracked(el, warning?.message || ''));\n const lineConds = {\n subscription: isSub,\n 'one-time': !isSub,\n 'on-sale': parseFloat(line.cost?.compareAtAmountPerQuantity?.amount) > parseFloat(line.cost?.amountPerQuantity?.amount),\n 'has-components': (line.lineComponents || []).length > 0,\n warning: Boolean(warning),\n };\n qsa(node, sel('line-show')).forEach((el) => {\n const k = get(el, 'line-show');\n if (k in lineConds) show(el, lineConds[k]);\n });\n\n // Change frequency in the cart: <select tether-line-plan> lists the product's plans.\n qsa(node, `select${sel('line-plan')}`).forEach((select) => {\n const handle = m.product?.handle;\n if (!handle) return;\n getProduct(handle).then((product) => {\n const plans = allPlans(product);\n const allowOneTime = !product.requiresSellingPlan && get(select, 'line-plan') !== 'subscription-only';\n const want = [\n ...(allowOneTime ? [{ value: '', label: select.getAttribute(attr('one-time-label')) || 'One-time purchase' }] : []),\n ...plans.map((p) => ({ value: p.id, label: p.name })),\n ];\n const sig = want.map((w) => w.value).join('|');\n if (select.dataset.tetherSig !== sig) {\n select.innerHTML = '';\n want.forEach((w) => {\n const o = document.createElement('option');\n o.value = w.value; o.textContent = w.label;\n select.appendChild(o);\n });\n select.dataset.tetherSig = sig;\n }\n select.value = line.sellingPlanAllocation?.sellingPlan?.id || '';\n show(select, plans.length > 0);\n }).catch((err) => reportError(err, 'line plan options'));\n });\n}\n\n", "/**\n * GraphQL fragments. Built at call time because counts and metafields come\n * from config. Operations put these AFTER the operation (see withContext).\n */\nimport { cfg } from './config.js';\n\nconst MONEY = 'amount currencyCode';\nconst IMAGE = 'url altText width height';\n\nexport function metafieldIdentifiers(o = cfg) {\n return (o.metafields || []).map((m) => {\n if (typeof m === 'string') {\n const i = m.indexOf('.');\n return { namespace: m.slice(0, i), key: m.slice(i + 1) };\n }\n return m;\n }).filter((m) => m.namespace && m.key);\n}\n\nfunction metafieldsField(o = cfg) {\n const ids = metafieldIdentifiers(o);\n if (!ids.length) return '';\n const list = ids\n .map((m) => `{namespace: ${JSON.stringify(m.namespace)}, key: ${JSON.stringify(m.key)}}`)\n .join(', ');\n return `metafields(identifiers:[${list}]){namespace key type value reference{... on MediaImage{image{${IMAGE}}}}}`;\n}\n\nexport const SELLING_PLAN_FIELDS = ` id name description recurringDeliveries options{name value}priceAdjustments{orderCount adjustmentValue{__typename ... on SellingPlanPercentagePriceAdjustment{adjustmentPercentage}... on SellingPlanFixedAmountPriceAdjustment{adjustmentAmount{${MONEY}}}... on SellingPlanFixedPriceAdjustment{price{${MONEY}}}}}`;\n\nexport const ALLOCATION_FIELDS = ` sellingPlan{id}checkoutChargeAmount{${MONEY}}remainingBalanceChargeAmount{${MONEY}}priceAdjustments{price{${MONEY}}compareAtPrice{${MONEY}}perDeliveryPrice{${MONEY}}unitPrice{${MONEY}}}`;\n\n/** The product fields Tether renders. `o` = config (counts, metafields); the server module passes its own. */\nexport function productFragment(o = cfg) {\n return ` fragment TetherProduct on Product{id handle title description descriptionHtml productType vendor tags availableForSale publishedAt onlineStoreUrl requiresSellingPlan seo{title description}featuredImage{${IMAGE}}images(first:${o.imagesFirst}){nodes{${IMAGE}}}options{name optionValues{name swatch{color image{previewImage{${IMAGE}}}}}}priceRange{minVariantPrice{${MONEY}}maxVariantPrice{${MONEY}}}compareAtPriceRange{minVariantPrice{${MONEY}}maxVariantPrice{${MONEY}}}${metafieldsField(o)} sellingPlanGroups(first:${o.sellingPlanGroupsFirst}){nodes{name appName options{name values}sellingPlans(first:${o.sellingPlansFirst}){nodes{${SELLING_PLAN_FIELDS}}}}}variants(first:${o.variantsFirst}){nodes{id title availableForSale currentlyNotInStock quantityAvailable sku barcode selectedOptions{name value}image{${IMAGE}}price{${MONEY}}compareAtPrice{${MONEY}}unitPrice{${MONEY}}sellingPlanAllocations(first:${o.sellingPlansFirst}){nodes{${ALLOCATION_FIELDS}}}}}}`;\n}\n\nexport function cartFragment() {\n return ` fragment TetherCart on Cart{id checkoutUrl totalQuantity note createdAt updatedAt attributes{key value}buyerIdentity{countryCode email}discountCodes{code applicable}cost{subtotalAmount{${MONEY}}totalAmount{${MONEY}}checkoutChargeAmount{${MONEY}}}lines(first:100){nodes{id quantity attributes{key value}cost{totalAmount{${MONEY}}subtotalAmount{${MONEY}}amountPerQuantity{${MONEY}}compareAtAmountPerQuantity{${MONEY}}}discountAllocations{discountedAmount{${MONEY}}}sellingPlanAllocation{sellingPlan{id name description recurringDeliveries options{name value}}checkoutChargeAmount{${MONEY}}priceAdjustments{price{${MONEY}}compareAtPrice{${MONEY}}perDeliveryPrice{${MONEY}}}}merchandise{... on ProductVariant{id title sku availableForSale requiresShipping quantityAvailable image{${IMAGE}}price{${MONEY}}compareAtPrice{${MONEY}}selectedOptions{name value}product{id title handle vendor featuredImage{${IMAGE}}}}}... on ComponentizableCartLine{lineComponents{id quantity merchandise{... on ProductVariant{id title product{title handle}}}}}}}}`;\n}\n\nexport function collectionFields() {\n return `\n id handle title description descriptionHtml\n image { ${IMAGE} }\n seo { title description }`;\n}\n", "/**\n * Data loading. Products are batched per tick into one request and cached for\n * the lifetime of the page (survives Barba/Swup page swaps).\n */\nimport { cfg, log } from './config.js';\nimport { gql, TetherError } from './client.js';\nimport { productFragment, collectionFields } from './fragments.js';\n\nconst productCache = new Map(); // key -> Promise<product>\nlet pending = [];\nconst resolvers = new Map();\nlet scheduled = false;\n// Bumped by clearProductCache(): responses to requests sent before that (e.g. in the old\n// market after a country switch) still reach their callers but never refill the cache.\nlet generation = 0;\n\nconst isGid = (v) => typeof v === 'string' && v.startsWith('gid://');\n\n/** Accepts a handle, numeric id, gid or a full product URL. */\nexport function normalizeProductKey(raw) {\n const v = String(raw ?? '').trim();\n if (!v) return null;\n if (isGid(v)) return v;\n if (/^\\d+$/.test(v)) return `gid://shopify/Product/${v}`;\n const m = v.match(/\\/products\\/([^/?#]+)/);\n return m ? m[1] : v;\n}\n\n/** Put a product we already have (from a collection query) in the cache. */\nexport function primeProduct(product) {\n if (!product) return;\n const p = Promise.resolve(product);\n productCache.set(product.handle, p);\n productCache.set(product.id, p);\n}\n\nexport function getProduct(rawKey) {\n const key = normalizeProductKey(rawKey);\n if (!key) return Promise.reject(new TetherError('empty product key', { code: 'NOT_FOUND' }));\n if (productCache.has(key)) return productCache.get(key);\n\n const p = new Promise((resolve, reject) => {\n resolvers.set(key, { resolve, reject });\n pending.push(key);\n if (!scheduled) {\n scheduled = true;\n setTimeout(flush, 0);\n }\n });\n productCache.set(key, p);\n return p;\n}\n\nasync function flush() {\n scheduled = false;\n const gen = generation;\n const keys = pending.splice(0);\n if (!keys.length) return;\n\n const ids = keys.filter(isGid);\n const handles = keys.filter((k) => !isGid(k));\n const defs = [];\n const parts = [];\n const vars = {};\n\n if (ids.length) {\n defs.push('$ids: [ID!]!');\n vars.ids = ids;\n parts.push('byId: nodes(ids: $ids) { ... on Product { ...TetherProduct } }');\n }\n handles.forEach((h, i) => {\n defs.push(`$h${i}: String!`);\n vars[`h${i}`] = h;\n parts.push(`h${i}: product(handle: $h${i}) { ...TetherProduct }`);\n });\n\n const query = `query TetherProducts(${defs.join(',')}){${parts.join(' ')}}${productFragment()}`;\n log('fetch products', keys);\n\n const settle = (k, fn) => {\n const r = resolvers.get(k);\n resolvers.delete(k);\n if (r) fn(r);\n };\n\n try {\n const data = await gql(query, vars);\n const got = new Map();\n (data.byId || []).forEach((p) => { if (p) got.set(p.id, p); });\n handles.forEach((h, i) => { if (data[`h${i}`]) got.set(h, data[`h${i}`]); });\n\n keys.forEach((k) => settle(k, (r) => {\n if (got.has(k)) {\n const p = got.get(k);\n if (gen === generation) { primeProduct(p); freshAt.set(p.handle, Date.now()); freshAt.set(p.id, Date.now()); }\n r.resolve(p);\n } else {\n // A miss is remembered for a few seconds (one page load asking twice makes one request),\n // not longer: a product published in Shopify shows up on the next visit.\n const miss = productCache.get(k);\n if (gen === generation) setTimeout(() => { if (productCache.get(k) === miss) productCache.delete(k); }, 10000);\n r.reject(new TetherError(`Product not found: ${k}`, { code: 'NOT_FOUND' }));\n }\n }));\n } catch (err) {\n keys.forEach((k) => settle(k, (r) => { if (gen === generation) productCache.delete(k); r.reject(err); }));\n }\n}\n\nexport function clearProductCache() { productCache.clear(); generation++; stale.clear(); freshAt.clear(); }\n\n// ---------------------------------------------------------------------------\n// Hydration: products rendered on the server (tether/server hydrate()) are used at once and\n// refreshed once in the background, so prices and stock are live without a loading state.\n// ---------------------------------------------------------------------------\n\nconst stale = new Set(); // keys of products that came from the server and weren't refreshed yet\nconst freshAt = new Map(); // key -> when it was last loaded live (this page session)\nconst FRESH_MS = 60000;\n\nexport function hydrateProducts(products) {\n (products || []).forEach((p) => {\n if (!p?.id || !p.handle) return;\n // Loaded live in the last minute (an earlier page of a View Transition visit): that copy is newer.\n if (Date.now() - (freshAt.get(p.handle) || 0) < FRESH_MS && productCache.has(p.handle)) return;\n primeProduct(p);\n stale.add(p.handle);\n stale.add(p.id);\n });\n}\n\n/** True once per server-provided product: the caller refreshes it. */\nexport function takeStale(key) {\n const k = normalizeProductKey(key);\n if (!stale.has(k)) return false;\n const p = productCache.get(k);\n stale.delete(k);\n // Both keys point to the same product: refresh it once.\n p?.then?.((x) => { stale.delete(x.handle); stale.delete(x.id); });\n return true;\n}\n\n/** Fetch these products again (bypassing the cache). */\nexport function refreshProducts(keys) {\n keys.forEach((k) => productCache.delete(normalizeProductKey(k)));\n return keys.map((k) => getProduct(k));\n}\n\n/**\n * A page of products from a collection (by handle) or from a search query.\n * Returns { collection, products, pageInfo }.\n */\nexport async function getProducts({\n collection, query, first = cfg.collectionFirst, after = null, sortKey, reverse = false, filters,\n} = {}) {\n const fragment = productFragment();\n\n if (collection) {\n const data = await gql(`query TetherCollection($handle:String!,$first:Int!,$after:String,$sortKey:ProductCollectionSortKeys,$reverse:Boolean,$filters:[ProductFilter!]){collection(handle:$handle){${collectionFields()} products(first:$first,after:$after,sortKey:$sortKey,reverse:$reverse,filters:$filters){nodes{...TetherProduct}pageInfo{hasNextPage endCursor}}}}${fragment}`, {\n handle: collection, first, after, sortKey: sortKey || undefined, reverse, filters: filters || undefined,\n });\n if (!data.collection) throw new TetherError(`Collection not found: ${collection}`, { code: 'NOT_FOUND' });\n const { products, ...rest } = data.collection;\n products.nodes.forEach(primeProduct);\n return { collection: rest, products: products.nodes, pageInfo: products.pageInfo };\n }\n\n const data = await gql(`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}}}${fragment}`, { first, after, query: query || undefined, sortKey: sortKey || undefined, reverse });\n data.products.nodes.forEach(primeProduct);\n return { collection: null, products: data.products.nodes, pageInfo: data.products.pageInfo };\n}\n\nexport async function getRecommendations(product, intent = 'RELATED') {\n const key = normalizeProductKey(typeof product === 'object' ? product?.id : product);\n const byId = key?.startsWith('gid://');\n const data = await gql(`query TetherRecs(${byId ? '$id: ID!' : '$handle: String!'},$intent:ProductRecommendationIntent){productRecommendations(${byId ? 'productId: $id' : 'productHandle: $handle'},intent:$intent){...TetherProduct}}${productFragment()}`, byId ? { id: key, intent } : { handle: key, intent });\n const list = data.productRecommendations || [];\n list.forEach(primeProduct);\n return list;\n}\n", "/**\n * Pure helpers for Shopify selling plans (subscriptions). No DOM, easy to test.\n */\n\nexport const GID = {\n product: (v) => toGid(v, 'Product'),\n variant: (v) => toGid(v, 'ProductVariant'),\n sellingPlan: (v) => toGid(v, 'SellingPlan'),\n};\n\nexport function toGid(value, type) {\n const v = String(value ?? '').trim();\n if (!v) return null;\n if (v.startsWith('gid://')) return v;\n if (/^\\d+$/.test(v)) return `gid://shopify/${type}/${v}`;\n return v;\n}\n\n/** All plans of a product, flattened, each with its group attached. */\nexport function allPlans(product) {\n const groups = product?.sellingPlanGroups?.nodes || [];\n return groups.flatMap((g) => (g.sellingPlans?.nodes || []).map((p) => ({ ...p, group: g })));\n}\n\nexport function hasPlans(product) {\n return allPlans(product).length > 0;\n}\n\n/** The allocation of `planId` on `variant`, or null when the variant isn't in that plan. */\nexport function allocationFor(variant, planId) {\n if (!variant || !planId) return null;\n return (variant.sellingPlanAllocations?.nodes || []).find((a) => a.sellingPlan?.id === planId) || null;\n}\n\n/** Plans that can actually be bought with this variant. */\nexport function plansForVariant(product, variant) {\n return allPlans(product).filter((p) => allocationFor(variant, p.id));\n}\n\n/** Price per delivery for a variant on a plan (falls back to the one-time price). */\nexport function planPrice(variant, planId) {\n const a = allocationFor(variant, planId);\n const adj = a?.priceAdjustments?.[0];\n return adj?.perDeliveryPrice || adj?.price || variant?.price || null;\n}\n\n/** What the customer pays at checkout for this plan (prepaid plans charge more up front). */\nexport function planCheckoutCharge(variant, planId) {\n const a = allocationFor(variant, planId);\n return a?.checkoutChargeAmount || a?.priceAdjustments?.[0]?.price || variant?.price || null;\n}\n\n/** Savings of a plan vs the one-time price, as { amount, percentage }. */\nexport function planSavings(variant, planId) {\n const base = parseFloat(variant?.price?.amount);\n const sub = parseFloat(planPrice(variant, planId)?.amount);\n if (!Number.isFinite(base) || !Number.isFinite(sub) || base <= 0 || sub >= base) {\n return { amount: null, percentage: 0 };\n }\n return {\n amount: { amount: (base - sub).toFixed(2), currencyCode: variant.price.currencyCode },\n percentage: Math.round((1 - sub / base) * 100),\n };\n}\n\n/**\n * The plan's own discount description, independent of a variant:\n * '10%', or a fixed amount / fixed price.\n */\nexport function planAdjustment(plan) {\n const v = plan?.priceAdjustments?.[0]?.adjustmentValue;\n if (!v) return null;\n switch (v.__typename) {\n case 'SellingPlanPercentagePriceAdjustment': return { type: 'percentage', value: v.adjustmentPercentage };\n case 'SellingPlanFixedAmountPriceAdjustment': return { type: 'amount', value: v.adjustmentAmount };\n case 'SellingPlanFixedPriceAdjustment': return { type: 'price', value: v.price };\n default: return null;\n }\n}\n\n/**\n * Finds a plan by id, numeric id, name or option value (case-insensitive),\n * so Webflow editors can write tether-default-plan=\"Every month\".\n */\nexport function findPlan(product, ref) {\n if (!ref) return null;\n const plans = allPlans(product);\n const gid = GID.sellingPlan(ref);\n const needle = String(ref).trim().toLowerCase();\n return plans.find((p) => p.id === gid)\n || plans.find((p) => p.name.toLowerCase() === needle)\n || plans.find((p) => (p.options || []).some((o) => String(o.value).toLowerCase() === needle))\n || null;\n}\n", "/**\n * DOM helpers. Attribute names go through attr() so the prefix is configurable\n * (e.g. prefix: 'wfs' for markup that uses wfs-* attributes).\n */\nimport { cfg, warn } from './config.js';\n\nexport const attr = (name) => `${cfg.prefix}-${name}`;\nexport const sel = (name, value) =>\n value === undefined ? `[${attr(name)}]` : `[${attr(name)}=\"${value}\"]`;\nexport const get = (el, name) => el.getAttribute(attr(name));\nexport const has = (el, name) => el.hasAttribute(attr(name));\nexport const dataKey = () => `data-${cfg.prefix}-key`;\n\n/**\n * productPath '/product' -> /product/<handle>.\n * Templates: '/product?handle={handle}' (one static page for every product,\n * with tether-product=\"url:handle\"), '/p/{id}' (numeric product id).\n */\nexport function productUrl(handle, id) {\n const path = cfg.productPath || '/product';\n if (!/\\{(handle|id)\\}/.test(path)) return `${path.replace(/\\/$/, '')}/${handle}`;\n const numeric = id ? String(id).split('/').pop() : '';\n return path.replace(/\\{handle\\}/g, encodeURIComponent(handle || '')).replace(/\\{id\\}/g, encodeURIComponent(numeric));\n}\n\nexport const qsa = (root, s) => (root ? [...root.querySelectorAll(s)] : []);\n\n/** Elements in `root` whose nearest `scopeSelector` ancestor is `root` itself. */\nexport const scoped = (root, s, scopeSelector) =>\n qsa(root, s).filter((el) => el.closest(scopeSelector) === root);\n\nexport function emit(name, detail, target = document) {\n target.dispatchEvent(new CustomEvent(`${cfg.prefix}:${name}`, { detail, bubbles: true }));\n}\n\n/** 30 -> \"30%\" (en, nl) or \"30 %\" (de, fr), in the configured locale. */\nexport function formatPercent(n, locale = cfg.locale) {\n if (!n) return '';\n try { return new Intl.NumberFormat(locale || undefined, { style: 'percent', maximumFractionDigits: 0 }).format(n / 100); } catch { return `${n}%`; }\n}\n\nexport function formatMoney(money) {\n if (!money) return '';\n if (typeof cfg.formatMoney === 'function') return cfg.formatMoney(money, cfg.locale);\n const amount = parseFloat(money.amount);\n if (Number.isNaN(amount)) return '';\n try {\n return new Intl.NumberFormat(cfg.locale || undefined, {\n style: 'currency', currency: money.currencyCode,\n }).format(amount);\n } catch {\n return `${money.currencyCode} ${amount.toFixed(2)}`;\n }\n}\n\nexport function formatDate(iso) {\n if (!iso) return '';\n try { return new Date(iso).toLocaleDateString(cfg.locale || undefined); } catch { return ''; }\n}\n\n/** Shopify CDN resize via max-width / max-height / crop attributes on the element. */\n/**\n * Shopify CDN image at a size: imageUrl(url, { width: 800 }). Use the same width as the element's\n * max-width attribute, so the browser script keeps the image instead of loading it again.\n */\nexport function imageUrl(url, { width, height, crop } = {}) {\n if (!url) return url;\n try {\n const u = new URL(url);\n if (width) u.searchParams.set('width', String(width));\n if (height) u.searchParams.set('height', String(height));\n if (crop) u.searchParams.set('crop', crop);\n return u.toString();\n } catch { return url; }\n}\n\nexport function cdnUrl(url, el) {\n if (!url || !el) return url;\n // max-width (Webflow's custom attribute), or valid HTML: tether-max-width / data-max-width.\n const g = (k) => el.getAttribute(k) ?? el.getAttribute(`${cfg.prefix}-${k}`) ?? el.getAttribute(`data-${k}`);\n return imageUrl(url, { width: g('max-width'), height: g('max-height'), crop: g('max-width') || g('max-height') ? g('crop') : null });\n}\n\n/** Same image, whatever size parameters: the server-rendered one is kept (no second download). */\nexport const sameImage = (a, b) => Boolean(a && b) && a.split('?')[0] === b.split('?')[0];\n\nexport function setImage(el, url, alt) {\n if (!url) return;\n const src = cdnUrl(url, el);\n if (el.tagName === 'IMG' && sameImage(el.getAttribute('src'), src)) {\n if (alt != null && !el.getAttribute('alt')) el.setAttribute('alt', alt);\n return;\n }\n if (el.tagName === 'IMG') {\n el.removeAttribute('srcset');\n el.removeAttribute('sizes');\n el.setAttribute('src', src);\n if (alt != null) el.setAttribute('alt', alt);\n if (!el.getAttribute('loading')) el.setAttribute('loading', 'lazy');\n } else {\n el.style.backgroundImage = `url(\"${src}\")`;\n }\n}\n\nexport function setText(el, v) {\n const text = v == null ? '' : String(v);\n if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') el.value = text;\n else el.textContent = text;\n}\n\nexport const readText = (el) => (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' ? el.value : el.textContent);\n\n/** setText that reports changes to cfg.onValueChange (for scramble/roll effects). */\nexport function setTextTracked(el, v) {\n const before = readText(el);\n setText(el, v);\n const after = readText(el);\n if (before !== after && el.dataset.tetherSeen && typeof cfg.onValueChange === 'function') {\n try { cfg.onValueChange(el, before); } catch { /* ignore */ }\n }\n el.dataset.tetherSeen = '1';\n}\n\nexport function show(el, visible) {\n const k = 'tetherPrevDisplay';\n if (visible) {\n if (el.dataset.tetherShown !== undefined) return; // already visible, nothing to check\n el.dataset.tetherShown = '';\n el.removeAttribute('hidden');\n if (el.dataset[k] !== undefined) {\n el.style.display = el.dataset[k];\n delete el.dataset[k];\n } else if (el.style.display === 'none') {\n el.style.display = '';\n }\n // Hidden before the script ran (a class, an inline display:none, a hidden attribute): show it\n // as block or the value of tether-display.\n if (typeof getComputedStyle === 'function' && getComputedStyle(el).display === 'none') {\n el.style.display = el.getAttribute(`${cfg.prefix}-display`) || 'block';\n }\n } else {\n delete el.dataset.tetherShown;\n // Remember a real display value to restore, never 'none'.\n if (el.dataset[k] === undefined && el.style.display !== 'none') el.dataset[k] = el.style.display || '';\n el.style.display = 'none';\n }\n}\n\nexport function setSelected(el, selected) {\n el.classList.toggle('is-selected', selected);\n el.setAttribute('aria-pressed', selected ? 'true' : 'false');\n if (el.tagName === 'INPUT' && (el.type === 'radio' || el.type === 'checkbox')) el.checked = selected;\n const input = el.querySelector?.('input[type=\"radio\"],input[type=\"checkbox\"]');\n if (input) input.checked = selected;\n}\n\n// ---------------------------------------------------------------------------\n// Repeaters: the first child in Webflow is the template, the rest is removed.\n// ---------------------------------------------------------------------------\n\nconst templates = new WeakMap();\n\n/** True once a repeater's template has been captured (it may be empty after that). */\nexport const hasTemplate = (container) => Boolean(templates.get(container));\n\nfunction template(container) {\n if (!templates.has(container)) {\n const tpl = container.firstElementChild?.cloneNode(true) ?? null;\n templates.set(container, tpl);\n container.innerHTML = '';\n }\n return templates.get(container);\n}\n\n/** Rebuilds the list on every render. Fine for images, tags, options. */\nexport function repeat(container, items, render) {\n const tpl = template(container);\n if (!tpl) { if (items.length) warn('repeater without a template child', container); return; }\n container.innerHTML = '';\n items.forEach((item, i) => {\n const node = tpl.cloneNode(true);\n render(node, item, i);\n container.appendChild(node);\n });\n}\n\n/**\n * Keyed repeater: keeps existing nodes, inserts new ones, removes old ones.\n * Used for cart lines, so values can animate and lines can slide in/out.\n */\nexport function repeatKeyed(container, items, keyOf, render, { onEnter, onLeave } = {}) {\n const tpl = template(container);\n if (!tpl) { warn('repeater without a template child', container); return; }\n\n const KEY = dataKey();\n const LEAVING = `data-${cfg.prefix}-leaving`;\n const live = () => [...container.children].filter((n) => n.hasAttribute(KEY) && !n.hasAttribute(LEAVING));\n\n const existing = new Map(live().map((n) => [n.getAttribute(KEY), n]));\n const wanted = [];\n const fresh = new Set();\n\n items.forEach((item, i) => {\n const k = String(keyOf(item, i));\n let node = existing.get(k);\n if (node) existing.delete(k);\n else {\n node = tpl.cloneNode(true);\n node.setAttribute(KEY, k);\n fresh.add(node);\n }\n render(node, item, i, fresh.has(node));\n wanted.push(node);\n });\n\n const staying = wanted.filter((n) => !fresh.has(n));\n const current = live().filter((n) => staying.includes(n));\n const orderOk = current.length === staying.length && current.every((n, i) => n === staying[i]);\n\n if (!orderOk) {\n existing.forEach((n) => n.remove());\n wanted.forEach((n) => container.appendChild(n));\n return;\n }\n\n wanted.forEach((node, i) => {\n if (!fresh.has(node)) return;\n const prev = wanted[i - 1];\n if (prev && prev.parentNode === container) prev.after(node);\n else container.prepend(node);\n if (onEnter) { try { onEnter(node); } catch { /* ignore */ } }\n });\n\n existing.forEach((node) => {\n node.setAttribute(LEAVING, '');\n node.removeAttribute(KEY);\n node.style.pointerEvents = 'none';\n node.inert = true;\n const done = () => node.remove();\n if (onLeave) { try { onLeave(node, done); } catch { done(); } } else done();\n });\n}\n\n// ---------------------------------------------------------------------------\n// Layout notifications: async renders change page height after your\n// page-transition hooks ran. Debounced, then cfg.onLayoutChange or a default.\n// ---------------------------------------------------------------------------\n\nlet layoutTimer = null;\n\nexport function notifyLayoutChanged(reason) {\n clearTimeout(layoutTimer);\n layoutTimer = setTimeout(() => {\n if (typeof cfg.onLayoutChange === 'function') cfg.onLayoutChange(reason);\n else if (window.ScrollTrigger?.refresh) window.ScrollTrigger.refresh();\n emit('layout-changed', { reason });\n }, 120);\n}\n\nexport function watchImages(root, reason) {\n const imgs = qsa(root, 'img').filter((i) => !i.complete);\n if (!imgs.length) return;\n let left = imgs.length;\n const done = () => { if (--left === 0) notifyLayoutChanged(`${reason}:images`); };\n imgs.forEach((img) => {\n img.addEventListener('load', done, { once: true });\n img.addEventListener('error', done, { once: true });\n });\n}\n\nexport function busy(el, fn) {\n if (el.getAttribute('aria-busy') === 'true') return Promise.resolve();\n el.setAttribute('aria-busy', 'true');\n return Promise.resolve().then(fn).finally(() => el.removeAttribute('aria-busy'));\n}\n\nexport function parseJSONAttr(el, name) {\n const raw = el && get(el, name);\n if (!raw) return null;\n try { return JSON.parse(raw); } catch { warn(`invalid JSON in ${attr(name)}`, el); return null; }\n}\n\n/** {a: 1} or [{key, value}] -> [{key, value}] as Shopify wants it. */\nexport function toAttributes(obj) {\n if (!obj) return [];\n if (Array.isArray(obj)) return obj.map((a) => ({ key: String(a.key), value: String(a.value ?? '') }));\n return Object.entries(obj).map(([key, value]) => ({ key, value: String(value ?? '') }));\n}\n", "/**\n * ProductScope: everything inside [tether-product=\"<handle>\"] binds to one\n * Shopify product: options, variants, quantity, subscriptions, add to cart.\n */\nimport { cfg, reportError } from './config.js';\nimport {\n attr, sel, get, has, qsa, scoped, emit, formatMoney, formatDate, setText, setImage, show,\n setSelected, repeat, productUrl, notifyLayoutChanged, watchImages, busy, parseJSONAttr, toAttributes, sameImage, hasTemplate, formatPercent,\n} from './dom.js';\nimport { Cart } from './cart.js';\nimport { STATUS_KEYS, ownedBy } from './status.js';\nimport {\n allPlans, allocationFor, planPrice, planCheckoutCharge, planSavings, planAdjustment, findPlan, GID,\n} from './selling-plans.js';\n\nexport const scopes = new WeakMap(); // element -> ProductScope\n\nconst productSel = () => sel('product');\n\nfunction metafieldValue(product, ref) {\n const i = ref.indexOf('.');\n const ns = ref.slice(0, i);\n const key = ref.slice(i + 1);\n const mf = (product.metafields || []).find((m) => m && m.namespace === ns && m.key === key);\n return mf || null;\n}\n\n// Option names as written in the markup (the build's language), by product handle. With another\n// language Shopify translates them (Size -> Gr\u00F6\u00DFe), so attributes are matched by position instead.\nconst knownOptionNames = new Map();\nexport function rememberOptionNames(products) {\n (products || []).forEach((p) => { if (p?.handle && !knownOptionNames.has(p.handle)) knownOptionNames.set(p.handle, (p.options || []).map((o) => o.name)); });\n}\n\nexport class ProductScope {\n constructor(root, product) {\n this.root = root;\n this.product = product;\n this.selected = {};\n this.variant = null;\n this.quantity = Math.max(0, parseInt(get(root, 'quantity') ?? '1', 10) || (has(root, 'quantity') ? 0 : 1));\n this.plans = allPlans(product);\n this.purchase = 'one-time';\n this.planId = null;\n\n scopes.set(root, this);\n root.setAttribute(attr('state'), 'ready');\n root.removeAttribute(attr('error'));\n\n this.initSelection();\n this.initPurchase();\n this.renderProduct();\n this.bind();\n this.renderVariant();\n\n watchImages(root, 'product');\n notifyLayoutChanged('product');\n emit('product-ready', { product, scope: this }, root);\n }\n\n /** New data for the same product (e.g. after a country switch). Keeps the selection. */\n update(product) {\n const variantId = this.variant?.id;\n this.product = product;\n this.plans = allPlans(product);\n if (this.planId && !this.plans.some((p) => p.id === this.planId)) this.planId = this.plans[0]?.id || null;\n if (!this.plans.length && this.purchase === 'subscription') this.purchase = 'one-time';\n const v = product.variants.nodes.find((x) => x.id === variantId);\n if (v) { this.selected = {}; v.selectedOptions.forEach((o) => { this.selected[o.name] = o.value; }); }\n this.root.setAttribute(attr('state'), 'ready');\n this.root.removeAttribute(attr('error'));\n this.renderProduct();\n this.renderVariant();\n notifyLayoutChanged('product');\n emit('product-updated', { product, scope: this }, this.root);\n }\n\n /** Matching elements in this scope, including the root itself (e.g. a card link with tether-bind=\"link\"). */\n $(s) {\n const inner = scoped(this.root, s, productSel());\n return this.root.matches(s) ? [this.root, ...inner] : inner;\n }\n\n // ------------------------------------------------------------ state\n\n /** The product's option name for a name used in the markup (same name, or same position). */\n optName(authored) {\n const opts = this.product?.options || [];\n if (!authored || opts.some((o) => o.name === authored)) return authored;\n const i = (knownOptionNames.get(this.product.handle) || []).indexOf(authored);\n return i >= 0 && opts[i] ? opts[i].name : authored;\n }\n\n initSelection() {\n const vs = this.product.variants.nodes;\n const first = vs.find((v) => v.availableForSale) || vs[0];\n if (first) first.selectedOptions.forEach((o) => { this.selected[o.name] = o.value; });\n\n const param = new URLSearchParams(window.location.search).get('variant') || get(this.root, 'variant');\n if (param) {\n const gid = GID.variant(param);\n const match = vs.find((v) => v.id === gid);\n if (match) {\n this.selected = {};\n match.selectedOptions.forEach((o) => { this.selected[o.name] = o.value; });\n }\n }\n }\n\n initPurchase() {\n if (!this.plans.length) return;\n const params = new URLSearchParams(window.location.search);\n const fromUrl = findPlan(this.product, params.get('selling_plan'));\n const fromAttr = findPlan(this.product, get(this.root, 'default-plan'));\n this.planId = (fromUrl || fromAttr || this.plans[0]).id;\n\n const wanted = fromUrl ? 'subscription' : (get(this.root, 'default-purchase') || cfg.defaultPurchase);\n this.purchase = this.product.requiresSellingPlan || wanted === 'subscription' ? 'subscription' : 'one-time';\n }\n\n findVariant() {\n return this.product.variants.nodes.find((v) =>\n v.selectedOptions.every((o) => this.selected[o.name] === o.value)) || null;\n }\n\n isValueAvailable(name, value) {\n return this.product.variants.nodes.some((v) =>\n v.availableForSale && v.selectedOptions.every((o) =>\n (o.name === name ? o.value === value : this.selected[o.name] === o.value)));\n }\n\n get plan() { return this.plans.find((p) => p.id === this.planId) || null; }\n\n /** True when the current variant can be bought on the selected plan. */\n get subscriptionAvailable() {\n return Boolean(this.variant && this.plans.some((p) => allocationFor(this.variant, p.id)));\n }\n\n get isSubscription() {\n return this.purchase === 'subscription' && Boolean(allocationFor(this.variant, this.planId));\n }\n\n /** What would be added to the cart right now. */\n getLine() {\n if (!this.variant) return null;\n const line = { merchandiseId: this.variant.id, quantity: this.quantity };\n if (this.isSubscription) line.sellingPlanId = this.planId;\n const attrs = this.collectAttributes();\n if (attrs.length) line.attributes = attrs;\n return line;\n }\n\n collectAttributes() {\n const fixed = toAttributes(parseJSONAttr(this.root, 'line-attributes'));\n const inputs = this.$(sel('line-attribute')).map((el) => {\n const key = get(el, 'line-attribute');\n let value;\n if (el.type === 'checkbox') value = el.checked ? (el.value && el.value !== 'on' ? el.value : 'Yes') : '';\n else if (el.type === 'radio') value = el.checked ? el.value : null;\n else value = el.value;\n return value == null || value === '' ? null : { key, value: String(value) };\n }).filter(Boolean);\n return [...fixed, ...inputs];\n }\n\n // ------------------------------------------------------------ actions\n\n select(name, value) {\n if (this.selected[name] === value) return;\n const vs = this.product.variants.nodes.filter((v) => v.selectedOptions.some((o) => o.name === name && o.value === value));\n if (!vs.length) return; // a value no variant has: nothing to select, keep the visitor's choice\n const next = { ...this.selected, [name]: value };\n if (!vs.some((v) => v.selectedOptions.every((o) => next[o.name] === o.value))) {\n // That combination doesn't exist: the closest variant with this value (most other choices kept, available first).\n const score = (v) => v.selectedOptions.filter((o) => o.name !== name && this.selected[o.name] === o.value).length * 2 + (v.availableForSale ? 1 : 0);\n const best = vs.reduce((a, b) => (score(b) > score(a) ? b : a));\n best.selectedOptions.forEach((o) => { next[o.name] = o.value; });\n }\n this.selected = next;\n this.renderVariant();\n }\n\n selectVariant(id) {\n const v = this.product.variants.nodes.find((x) => x.id === GID.variant(id));\n if (!v) return;\n this.selected = {};\n v.selectedOptions.forEach((o) => { this.selected[o.name] = o.value; });\n this.renderVariant();\n }\n\n setPurchase(mode) {\n const next = mode === 'subscription' ? 'subscription' : 'one-time';\n if (next === 'one-time' && this.product.requiresSellingPlan) return;\n if (this.purchase === next) return;\n this.purchase = next;\n this.renderVariant();\n }\n\n selectPlan(ref) {\n const p = findPlan(this.product, ref);\n if (!p) return;\n this.planId = p.id;\n this.purchase = 'subscription';\n this.renderVariant();\n }\n\n setQuantity(n) {\n const min = has(this.root, 'quantity') ? 0 : 1;\n this.quantity = Math.max(min, parseInt(n, 10) || 0);\n this.$(sel('qty')).forEach((i) => setText(i, this.quantity));\n this.renderVariant();\n }\n\n async addToCart() {\n if (!this.variant?.availableForSale) return null;\n const line = this.getLine();\n if (!line || line.quantity < 1) return null;\n const cart = await Cart.add(line);\n emit('product-added', { product: this.product, variant: this.variant, line }, this.root);\n return cart;\n }\n\n // ------------------------------------------------------------ events\n\n bind() {\n const own = (el) => el && el.closest(productSel()) === this.root;\n\n this.root.addEventListener('click', (e) => {\n const t = e.target;\n if (!t?.closest) return;\n\n const opt = t.closest(sel('option-value'));\n if (own(opt) && opt.closest(sel('option-list'))) {\n e.preventDefault();\n this.select(this.optName(get(opt.closest(sel('option-list')), 'option-list')), get(opt, 'option-value'));\n return;\n }\n\n const plan = t.closest(sel('plan-value'));\n if (own(plan)) { e.preventDefault(); this.selectPlan(get(plan, 'plan-value')); return; }\n\n const purchase = t.closest(`${sel('purchase')}:not(select)`);\n if (own(purchase)) {\n if (purchase.tagName !== 'INPUT') e.preventDefault();\n this.setPurchase(get(purchase, 'purchase'));\n return;\n }\n\n const plus = t.closest(sel('qty-plus'));\n if (own(plus)) { e.preventDefault(); this.setQuantity(this.quantity + 1); return; }\n const minus = t.closest(sel('qty-minus'));\n if (own(minus)) { e.preventDefault(); this.setQuantity(this.quantity - 1); return; }\n\n const add = t.closest(sel('add-to-cart'));\n if (own(add)) { e.preventDefault(); this.onAddClick(add); }\n });\n\n this.root.addEventListener('change', (e) => {\n const t = e.target;\n if (!own(t)) return;\n if (t.matches(`select${sel('option')}`)) this.select(this.optName(get(t, 'option')), t.value);\n else if (t.matches(`select${sel('variant-select')}`)) this.selectVariant(t.value);\n else if (t.matches(`select${sel('plan')}`)) {\n if (t.value) this.selectPlan(t.value); else this.setPurchase('one-time');\n } else if (t.matches(`select${sel('purchase')}`)) this.setPurchase(t.value);\n else if (t.matches(sel('qty'))) this.setQuantity(t.value);\n });\n }\n\n onAddClick(btn) {\n const label = btn.querySelector(sel('add-label')) || btn;\n const busyText = get(btn, 'adding-text');\n const write = (txt) => setText(label, txt);\n if (label.dataset.tetherLabel === undefined) label.dataset.tetherLabel = label.tagName === 'INPUT' ? label.value : label.textContent;\n\n busy(btn, async () => {\n if (busyText) write(busyText);\n try { await this.addToCart(); } catch (err) {\n reportError(err, 'add to cart failed');\n emit('error', { error: err, context: 'add-to-cart' }, this.root);\n } finally {\n if (busyText) write(label.dataset.tetherLabel);\n }\n }).then(() => {\n // Restore mode-dependent labels (subscribe-text / soldout-text) after aria-busy is cleared.\n this.renderVariant();\n });\n }\n\n // ------------------------------------------------------------ render\n\n renderProduct() {\n const p0 = this.product;\n if (!knownOptionNames.has(p0.handle)) {\n const authored = this.$(`${sel('option-list')},select${sel('option')}`).map((e) => get(e, 'option-list') || get(e, 'option'));\n if (authored.some((n) => p0.options.some((o) => o.name === n))) rememberOptionNames([p0]);\n }\n const p = this.product;\n\n this.$(sel('bind')).forEach((el) => {\n const key = get(el, 'bind') || '';\n const txt = {\n title: p.title,\n 'description-text': p.description,\n vendor: p.vendor,\n type: p.productType,\n handle: p.handle,\n }[key];\n if (txt !== undefined) return setText(el, txt);\n switch (key) {\n case 'description': el.innerHTML = p.descriptionHtml || ''; return undefined;\n case 'published-at': return setText(el, formatDate(p.publishedAt));\n case 'min-price': return setText(el, formatMoney(p.priceRange.minVariantPrice));\n case 'max-price': return setText(el, formatMoney(p.priceRange.maxVariantPrice));\n case 'featured-image': return setImage(el, p.featuredImage?.url, p.featuredImage?.altText || p.title);\n case 'url':\n case 'link':\n el.setAttribute('href', productUrl(p.handle, p.id));\n if (key === 'url' && !el.firstElementChild && !el.textContent.trim()) setText(el, p.title);\n return undefined;\n case 'images': {\n // Server-rendered gallery with the same images: keep it as it is.\n const imgs = [...el.children].map((n) => (n.tagName === 'IMG' ? n : n.querySelector('img')));\n if (!hasTemplate(el) && imgs.length === p.images.nodes.length && imgs.every((im, i) => sameImage(im?.getAttribute('src'), p.images.nodes[i].url))) return undefined;\n }\n return repeat(el, p.images.nodes, (node, img) => {\n const target = node.matches(`img,${sel('bind', 'image')}`) ? node : node.querySelector('img') || node;\n setImage(target, img.url, img.altText || p.title);\n });\n case 'tags': {\n const exclude = (el.getAttribute('exclude') || '').split(',').map((s) => s.trim()).filter(Boolean);\n return repeat(el, p.tags.filter((t) => !exclude.includes(t)), (node, tag) => setText(node, tag));\n }\n default:\n // image:2 = the second product image (falls back to the featured image)\n if (/^image:\\d+$/.test(key)) {\n const img = p.images.nodes[key.slice(6) - 1] || p.featuredImage;\n return setImage(el, img?.url, img?.altText || p.title);\n }\n if (key.startsWith('metafield:')) {\n const mf = metafieldValue(p, key.slice(10));\n if (!mf) return setText(el, '');\n if (mf.reference?.image) return setImage(el, mf.reference.image.url, mf.reference.image.altText);\n if (/^(rich_text|multi_line_text)_field$/.test(mf.type)) el.style.whiteSpace = 'pre-line';\n return setText(el, mf.value);\n }\n return undefined;\n }\n });\n\n this.$(sel('option-list')).forEach((container) => {\n const name = this.optName(get(container, 'option-list'));\n const opt = p.options.find((o) => o.name === name);\n if (!opt || (opt.optionValues.length <= 1 && has(container, 'hide-single'))) return show(container, false);\n return repeat(container, opt.optionValues, (node, v) => {\n node.setAttribute(attr('option-value'), v.name);\n const t = node.querySelector(sel('bind', 'option-value'));\n if (t) setText(t, v.name); else if (!node.firstElementChild) setText(node, v.name);\n const sw = node.querySelector(sel('bind', 'swatch'));\n if (sw && v.swatch?.color) sw.style.backgroundColor = v.swatch.color;\n if (sw && v.swatch?.image?.previewImage) setImage(sw, v.swatch.image.previewImage.url, v.name);\n });\n });\n\n this.$(`select${sel('option')}`).forEach((s) => {\n const opt = p.options.find((o) => o.name === this.optName(get(s, 'option')));\n if (!opt) return show(s, false);\n s.innerHTML = '';\n opt.optionValues.forEach((v) => s.appendChild(new Option(v.name, v.name)));\n return undefined;\n });\n\n this.$(`select${sel('variant-select')}`).forEach((s) => {\n s.innerHTML = '';\n p.variants.nodes.forEach((v) => s.appendChild(new Option(v.title, v.id)));\n });\n\n // Subscriptions\n this.$(sel('plan-list')).forEach((container) => {\n // Value = selling plan group name. Empty, \"true\", \"all\" or \"*\" = every plan\n // (Webflow's Designer doesn't always allow empty attribute values).\n const raw = (get(container, 'plan-list') || '').trim();\n const group = ['', 'true', 'all', '*'].includes(raw.toLowerCase()) ? null : raw;\n const plans = this.plans.filter((pl) => !group || pl.group.name === group);\n repeat(container, plans, (node, plan) => {\n node.setAttribute(attr('plan-value'), plan.id);\n if (!node.firstElementChild && !node.querySelector(sel('plan-bind'))) setText(node, plan.name);\n });\n });\n\n this.$(`select${sel('plan')}`).forEach((s) => {\n s.innerHTML = '';\n if (!p.requiresSellingPlan && get(s, 'plan') !== 'subscription-only') {\n s.appendChild(new Option(s.getAttribute(attr('one-time-label')) || 'One-time purchase', ''));\n }\n this.plans.forEach((pl) => s.appendChild(new Option(pl.name, pl.id)));\n });\n }\n\n renderVariant() {\n const p = this.product;\n let v = this.findVariant();\n if (!v) {\n [v] = p.variants.nodes;\n if (v) {\n this.selected = {};\n v.selectedOptions.forEach((o) => { this.selected[o.name] = o.value; });\n }\n }\n this.variant = v;\n if (!v) return;\n\n // A plan the variant isn't in -> pick the first one it is in.\n if (this.plans.length && !allocationFor(v, this.planId)) {\n const alt = this.plans.find((pl) => allocationFor(v, pl.id));\n if (alt) this.planId = alt.id;\n }\n\n const sub = this.isSubscription;\n const oneTimePrice = v.price;\n const subPrice = this.planId ? planPrice(v, this.planId) : null;\n const price = sub ? subPrice : oneTimePrice;\n const compareAt = sub ? (allocationFor(v, this.planId)?.priceAdjustments?.[0]?.compareAtPrice || v.compareAtPrice) : v.compareAtPrice;\n const onSale = compareAt && parseFloat(compareAt.amount) > parseFloat(price.amount);\n const discountPct = onSale ? Math.round((1 - parseFloat(price.amount) / parseFloat(compareAt.amount)) * 100) : 0;\n const savings = this.planId ? planSavings(v, this.planId) : { amount: null, percentage: 0 };\n const plan = this.plan;\n const total = { amount: (parseFloat(price.amount) * Math.max(1, this.quantity)).toFixed(2), currencyCode: price.currencyCode };\n\n const fm = formatMoney;\n const pct = (n) => formatPercent(n);\n // Text binds: name -> value (functions, so only the binds on the page are computed).\n const text = {\n price: () => fm(price),\n 'total-price': () => fm(total),\n 'one-time-price': () => fm(oneTimePrice),\n 'subscription-price': () => fm(subPrice),\n 'subscription-savings': () => pct(savings.percentage),\n 'subscription-savings-amount': () => fm(savings.amount),\n // What the visitor pays today for the chosen quantity (prepaid plans charge more up front).\n 'checkout-charge': () => { const c = sub ? planCheckoutCharge(v, this.planId) : price; return c && fm({ amount: (parseFloat(c.amount) * Math.max(1, this.quantity)).toFixed(2), currencyCode: c.currencyCode }); },\n 'plan-name': () => plan?.name,\n 'plan-description': () => plan?.description,\n 'plan-group': () => plan?.group?.name,\n 'compare-at-price': () => (onSale ? fm(compareAt) : ''),\n 'unit-price': () => fm(v.unitPrice),\n 'discount-percentage': () => `${discountPct}%`,\n 'discount-amount': () => (onSale ? fm({ amount: String(parseFloat(compareAt.amount) - parseFloat(price.amount)), currencyCode: price.currencyCode }) : ''),\n 'variant-title': () => v.title,\n 'variant-id': () => v.id,\n sku: () => v.sku,\n barcode: () => v.barcode,\n stock: () => v.quantityAvailable,\n quantity: () => this.quantity,\n };\n this.$(sel('bind')).forEach((el) => {\n const k = get(el, 'bind');\n if (k === 'variant-image') setImage(el, v.image?.url || p.featuredImage?.url, v.image?.altText || p.title);\n else if (text[k]) setText(el, text[k]());\n });\n\n this.$(sel('option-selected')).forEach((el) => setText(el, this.selected[this.optName(get(el, 'option-selected'))] || ''));\n\n this.$(sel('option-list')).forEach((container) => {\n const name = this.optName(get(container, 'option-list'));\n qsa(container, sel('option-value')).forEach((node) => {\n const value = get(node, 'option-value');\n setSelected(node, this.selected[name] === value);\n const unavailable = !this.isValueAvailable(name, value);\n node.classList.toggle('is-unavailable', unavailable);\n node.setAttribute('data-unavailable', unavailable ? 'true' : 'false');\n });\n });\n\n this.$(`select${sel('option')}`).forEach((s) => { s.value = this.selected[this.optName(get(s, 'option'))] || ''; });\n this.$(`select${sel('variant-select')}`).forEach((s) => { s.value = v.id; });\n\n // Subscription UI\n this.$(sel('purchase')).forEach((el) => {\n if (el.tagName === 'SELECT') { el.value = this.purchase; return; }\n const mode = get(el, 'purchase');\n setSelected(el, mode === this.purchase);\n const unavailable = mode === 'subscription' ? !this.subscriptionAvailable : p.requiresSellingPlan;\n el.classList.toggle('is-unavailable', unavailable);\n });\n\n this.$(sel('plan-value')).forEach((node) => {\n const id = get(node, 'plan-value');\n const planObj = this.plans.find((pl) => pl.id === id);\n const inVariant = Boolean(allocationFor(v, id));\n setSelected(node, sub && id === this.planId);\n node.classList.toggle('is-unavailable', !inVariant);\n qsa(node, sel('plan-bind')).forEach((el) => {\n const adj = planAdjustment(planObj);\n const s = planSavings(v, id);\n const k = get(el, 'plan-bind');\n const val = {\n name: () => planObj?.name,\n option: () => (planObj?.options || []).map((o) => o.value).join(', '), // e.g. \"1 month\", without the store's price text\n description: () => planObj?.description,\n price: () => fm(planPrice(v, id)),\n savings: () => pct(s.percentage),\n 'savings-amount': () => fm(s.amount),\n adjustment: () => (!adj ? '' : adj.type === 'percentage' ? `${adj.value}%` : fm(adj.value)),\n }[k];\n if (val) setText(el, val());\n });\n });\n\n this.$(`select${sel('plan')}`).forEach((s) => { s.value = sub ? this.planId : ''; });\n\n const low = v.quantityAvailable != null && v.quantityAvailable > 0 && v.quantityAvailable <= (cfg.lowStock ?? 5);\n const conds = {\n 'in-stock': v.availableForSale,\n 'out-of-stock': !v.availableForSale,\n 'backorder': v.availableForSale && v.currentlyNotInStock,\n 'on-sale': Boolean(onSale),\n 'not-on-sale': !onSale,\n 'has-variants': p.variants.nodes.length > 1,\n 'single-variant': p.variants.nodes.length === 1,\n 'low-stock': low,\n 'plenty-in-stock': v.availableForSale && !low,\n 'subscription-available': this.subscriptionAvailable,\n 'subscription-unavailable': !this.subscriptionAvailable,\n 'subscription-only': Boolean(p.requiresSellingPlan),\n 'one-time-available': !p.requiresSellingPlan,\n 'subscription-selected': sub,\n 'one-time-selected': !sub,\n 'has-savings': sub ? savings.percentage > 0 : Boolean(onSale),\n // scope state (see status.js)\n 'loading': false,\n 'ready': true,\n 'error': false,\n 'not-found': false,\n };\n this.$(sel('show')).forEach((el) => {\n const k = get(el, 'show');\n if (!(k in conds)) return;\n // State blocks of a list nested in this product belong to that list.\n if (STATUS_KEYS.includes(k) && !ownedBy(el, this.root)) return;\n show(el, conds[k]);\n });\n\n this.root.classList.toggle('is-subscription', sub);\n this.root.setAttribute(attr('purchase-mode'), sub ? 'subscription' : 'one-time');\n\n this.$(sel('add-to-cart')).forEach((btn) => {\n const disabled = !v.availableForSale;\n btn.classList.toggle('is-disabled', disabled);\n btn.setAttribute('aria-disabled', String(disabled));\n if ('disabled' in btn) btn.disabled = disabled;\n const soldOut = get(btn, 'soldout-text');\n const subText = get(btn, 'subscribe-text');\n if (soldOut || subText) {\n const label = btn.querySelector(sel('add-label')) || btn;\n if (label.dataset.tetherLabel === undefined) label.dataset.tetherLabel = label.tagName === 'INPUT' ? label.value : label.textContent;\n let text = label.dataset.tetherLabel;\n if (sub && subText) text = subText;\n if (disabled && soldOut) text = soldOut;\n if (btn.getAttribute('aria-busy') !== 'true') setText(label, text);\n }\n });\n\n emit('variant-changed', {\n product: p, variant: v, selected: { ...this.selected },\n purchase: this.purchase, sellingPlanId: sub ? this.planId : null,\n }, this.root);\n\n }\n}\n", "/**\n * Where a product scope gets its key from, and the loading / ready / error /\n * not-found state of a scope (so a failing API never leaves a broken page).\n */\nimport { attr, sel, get, scoped, show } from './dom.js';\n\n/**\n * tether-product values:\n * \"coffee-box\" handle, numeric id, gid or product URL (as before)\n * \"url:handle\" ?handle=... from the page URL (any param name: \"url:p\" -> ?p=)\n * \"url:path\" the last segment of the page path (/shop/coffee-box -> coffee-box)\n * Returns { key, fromUrl, raw }. key is null when the URL has no value.\n */\nexport function resolveProductKey(el, location = window.location, name = 'product') {\n const raw = (get(el, name) || '').trim();\n if (!raw.toLowerCase().startsWith('url:')) return { key: raw || null, fromUrl: false, raw };\n const what = raw.slice(4).trim();\n let key = null;\n if (what.toLowerCase() === 'path') {\n const parts = location.pathname.split('/').filter(Boolean);\n key = parts.length ? safeDecode(parts[parts.length - 1]) : null;\n } else {\n key = new URLSearchParams(location.search).get(what || 'handle');\n }\n key = key && key.trim() ? key.trim() : null;\n return { key, fromUrl: true, raw };\n}\n\nfunction safeDecode(s) { try { return decodeURIComponent(s); } catch { return s; } }\n\n/** Values of tether-show that follow the scope state. */\nexport const STATUS_KEYS = ['loading', 'ready', 'error', 'not-found'];\n\nexport const isNotFound = (err) => err?.code === 'NOT_FOUND';\n\n/** Product scopes and lists both own their state elements; the nearest one wins. */\nexport const boundary = () => ['product', 'collection', 'products', 'recommendations'].map((n) => sel(n)).join(',');\n\n/** True when `el` belongs to the scope `root` (not to a nested product or list). */\nexport const ownedBy = (el, root) => el === root || el.parentElement?.closest(boundary()) === root;\n\n/**\n * Sets tether-state (loading | ready | error) and tether-error (not-found or an\n * error code) on `root`, toggles tether-show=\"loading|ready|error|not-found\"\n * inside it, and disables add-to-cart buttons when there's no product.\n */\nexport function setScopeStatus(root, status, err) {\n const notFound = status === 'not-found';\n root.setAttribute(attr('state'), notFound ? 'error' : status);\n if (status === 'error' || notFound) root.setAttribute(attr('error'), notFound ? 'not-found' : (err?.code || 'error'));\n else root.removeAttribute(attr('error'));\n\n scoped(root, sel('show'), boundary()).forEach((el) => {\n const k = get(el, 'show');\n if (!STATUS_KEYS.includes(k)) return;\n show(el, k === status);\n });\n\n if (status === 'error' || notFound) {\n scoped(root, sel('add-to-cart'), boundary()).forEach((btn) => {\n btn.classList.add('is-disabled');\n btn.setAttribute('aria-disabled', 'true');\n if ('disabled' in btn) btn.disabled = true;\n });\n }\n}\n", "/**\n * Product lists: [tether-collection=\"handle\"] or [tether-products=\"search query\"].\n * The first child of [tether-list] is the card template; every card becomes a\n * product scope, so all product attributes work inside cards (including\n * quick-add with a subscription toggle).\n */\nimport { reportError } from './config.js';\nimport { TetherError } from './client.js';\nimport { attr, sel, get, has, scoped, emit, setText, setImage, repeat, notifyLayoutChanged, busy, show } from './dom.js';\nimport { getProducts, getRecommendations } from './loader.js';\nimport { setScopeStatus, isNotFound, resolveProductKey } from './status.js';\n\nexport const listSelector = () => `${sel('collection')},${sel('products')},${sel('recommendations')}`;\n\nexport class ListScope {\n constructor(root) {\n this.root = root;\n this.products = [];\n this.pageInfo = null;\n this.collection = null;\n setScopeStatus(root, 'loading');\n root.addEventListener('click', (e) => {\n const more = e.target.closest?.(sel('load-more'));\n if (more && more.closest(listSelector()) === root) {\n e.preventDefault();\n busy(more, () => this.load(true));\n }\n });\n }\n\n $(s) { return scoped(this.root, s, listSelector()); }\n\n options() {\n const r = this.root;\n const opts = {\n first: parseInt(get(r, 'limit') || '', 10) || undefined,\n sortKey: get(r, 'sort') || undefined,\n reverse: get(r, 'reverse') === 'true',\n };\n if (has(r, 'collection')) opts.collection = get(r, 'collection');\n else {\n // url:q = the search in the page's ?q= (a results page on a static site).\n const raw = get(r, 'products') || '';\n opts.query = raw.startsWith('url:') ? new URL(window.location.href).searchParams.get(raw.slice(4)) || '' : raw;\n }\n return opts;\n }\n\n async load(more = false) {\n const token = (this.loadToken = (this.loadToken || 0) + 1);\n const stale = () => token !== this.loadToken;\n try {\n if (has(this.root, 'recommendations')) {\n // A handle, url:handle (one dynamic product page), or empty inside a product: that product.\n let { key } = resolveProductKey(this.root, window.location, 'recommendations');\n const scope = this.root.closest(sel('product'));\n if (!key && scope) ({ key } = resolveProductKey(scope));\n if (!key) throw new TetherError('No product for recommendations', { code: 'NOT_FOUND' });\n const recs = await getRecommendations(key, get(this.root, 'intent') || 'RELATED');\n if (stale()) return;\n const limit = parseInt(get(this.root, 'limit') || '', 10);\n this.products = limit ? recs.slice(0, limit) : recs;\n } else {\n const res = await getProducts({ ...this.options(), after: more ? this.pageInfo?.endCursor : null });\n if (stale()) return;\n this.collection = res.collection;\n this.pageInfo = res.pageInfo;\n this.products = more ? [...this.products, ...res.products] : res.products;\n }\n this.render();\n setScopeStatus(this.root, 'ready');\n emit('list-ready', { products: this.products, collection: this.collection }, this.root);\n } catch (err) {\n if (stale()) return;\n // Keep what's already rendered on a failed \"load more\"; otherwise show the error state.\n if (!more) setScopeStatus(this.root, isNotFound(err) ? 'not-found' : 'error', err);\n // A missing product for recommendations is a page detail, not an error to report.\n if (!(isNotFound(err) && has(this.root, 'recommendations'))) reportError(err, 'list load failed');\n emit('error', { error: err, context: 'list' }, this.root);\n }\n }\n\n render() {\n const c = this.collection;\n this.$(sel('collection-bind')).forEach((el) => {\n switch (get(el, 'collection-bind')) {\n case 'title': return setText(el, c?.title || '');\n case 'description': el.innerHTML = c?.descriptionHtml || ''; return undefined;\n case 'image': return setImage(el, c?.image?.url, c?.image?.altText || c?.title);\n case 'count': return setText(el, this.products.length);\n default: return undefined;\n }\n });\n\n this.$(sel('list')).forEach((container) => {\n repeat(container, this.products, (node, p) => {\n node.setAttribute(attr('product'), p.handle);\n node.removeAttribute(attr('state'));\n });\n // Cards are new elements: mount them (product data is already cached).\n emit('list-rendered', { container }, this.root);\n });\n\n const empty = this.products.length === 0;\n this.$(sel('show')).forEach((el) => {\n const k = get(el, 'show');\n if (k === 'list-empty') show(el, empty);\n if (k === 'list-filled') show(el, !empty);\n });\n this.$(sel('load-more')).forEach((el) => show(el, Boolean(this.pageInfo?.hasNextPage)));\n notifyLayoutChanged('list');\n }\n}\n\n", "/** Product scopes and lists that are mounted, shared by index.js and the optional markets part. */\nimport { cfg, log, warn, reportError } from './config.js';\nimport { ProductScope, scopes, rememberOptionNames } from './product.js';\nimport { listSelector } from './collection.js';\nimport { getProduct, takeStale, refreshProducts, hydrateProducts } from './loader.js';\nimport { resolveProductKey, setScopeStatus, isNotFound } from './status.js';\nimport { attr, get, qsa, emit } from './dom.js';\n\nexport const mountedProducts = new WeakSet();\nexport const mountedLists = new WeakSet();\n// Live roots, for re-rendering after a country switch (pruned when disconnected).\nexport const liveProducts = new Set();\nexport const liveLists = new Set();\nconst requestToken = new WeakMap(); // product root -> latest request, so a slow old response can't win\n\nexport function pruneLive() {\n liveProducts.forEach((el) => { if (!el.isConnected) liveProducts.delete(el); });\n liveLists.forEach((l) => { if (!l.root.isConnected) liveLists.delete(l); });\n}\nexport function within(root, selector) {\n return [...(root.matches?.(selector) ? [root] : []), ...qsa(root, selector)];\n}\n\nexport /** Mounts one product root. Returns true when a product request was started. */\nfunction mountProduct(el) {\n if (mountedProducts.has(el)) return false;\n const { key, fromUrl, raw } = resolveProductKey(el);\n if (!key) {\n if (fromUrl) {\n // Dynamic product page opened without ?handle= (or an empty path).\n mountedProducts.add(el);\n setScopeStatus(el, 'not-found');\n emit('product-not-found', { key: null, source: raw }, el);\n } else if (!el.closest(listSelector())) {\n // List cards get their handle when the list renders.\n warn(`[${attr('product')}] without a value. Bind it to the Shopify handle field, or use \"url:handle\".`, el);\n }\n return false;\n }\n mountedProducts.add(el);\n liveProducts.add(el);\n const token = {};\n requestToken.set(el, token);\n const current = () => requestToken.get(el) === token;\n // A rendered scope keeps showing its content while it refreshes (e.g. country switch).\n if (!scopes.get(el)) setScopeStatus(el, 'loading');\n else el.setAttribute(attr('state'), 'updating');\n const loading = getProduct(key);\n marketPending?.add(loading);\n loading\n .then((p) => {\n if (!current()) return;\n const existing = scopes.get(el);\n if (existing) existing.update(p);\n // eslint-disable-next-line no-new\n else new ProductScope(el, p);\n applyPageTitle(el, p);\n if (cfg.revalidate !== false && takeStale(key)) queueRefresh(key);\n })\n .catch((err) => {\n if (!current()) return;\n const notFound = isNotFound(err);\n setScopeStatus(el, notFound ? 'not-found' : 'error', err);\n if (notFound) {\n emit('product-not-found', { key, source: raw }, el);\n // A typo in a URL isn't worth an alert; a CMS item pointing at a deleted product is.\n if (fromUrl) log(`product not found: ${key}`); else reportError(err, `product ${key}`);\n } else {\n reportError(err, `product ${key}`);\n emit('error', { error: err, context: 'product', key }, el);\n }\n });\n return true;\n}\n\n/** tether-page-title=\"{title} | My shop\" on a product root sets document.title (dynamic product pages). */\nfunction applyPageTitle(el, p) {\n const tpl = get(el, 'page-title');\n if (!tpl || typeof document === 'undefined') return;\n document.title = tpl.replace(/\\{title\\}/g, p.title).replace(/\\{vendor\\}/g, p.vendor || '').replace(/\\{type\\}/g, p.productType || '');\n}\n\n\n/** Product scopes that failed on a network/API error: loaded again when the browser is back online. */\nexport function retryFailed() {\n pruneLive();\n liveProducts.forEach((el) => {\n if (el.getAttribute(attr('state')) !== 'error' || el.getAttribute(attr('error')) === 'not-found') return;\n mountedProducts.delete(el);\n mountProduct(el);\n });\n}\n\n// Server-rendered products: one batched background request refreshes them all.\nlet refreshQueue = new Set();\nfunction queueRefresh(key) {\n if (!refreshQueue.size) setTimeout(flushRefresh, 0);\n refreshQueue.add(key);\n}\nfunction flushRefresh() {\n const keys = [...refreshQueue];\n refreshQueue = new Set();\n refreshProducts(keys).forEach((promise, i) => promise.then((fresh) => {\n liveProducts.forEach((el) => {\n const scope = scopes.get(el);\n if (!scope || !el.isConnected) return;\n const k = resolveProductKey(el).key;\n if (k !== keys[i] && k !== fresh.handle && k !== fresh.id) return;\n if (JSON.stringify(scope.product) !== JSON.stringify(fresh)) scope.update(fresh);\n });\n }).catch((err) => reportError(err, `refresh ${keys[i]}`)));\n}\n\n/**\n * <script type=\"application/json\" data-tether-hydrate> tags written by tether/server's hydrate():\n * their products are used without a request. Ignored when they were made for another market.\n */\nconst readScripts = new WeakSet();\nlet marketPending = null; // product loads to wait for before html.tether-market-pending goes\n\n/** Lists (and anything else that loads prices) wait too. */\nexport const trackMarket = (p) => { marketPending?.add(p); return p; };\n\n/** After a mount: drop html.tether-market-pending once this page's products are live. */\nexport function settleMarket() {\n if (!marketPending) return;\n const waits = [...marketPending];\n Promise.allSettled(waits).then(() => {\n if (!marketPending || waits.some((w) => !marketPending.has(w))) return;\n if (waits.length === marketPending.size) {\n marketPending = null;\n document.documentElement.classList.remove(`${cfg.prefix}-market-pending`);\n } else settleMarket(); // more products came in meanwhile\n });\n}\n\nexport function hydrateFromPage(root = document) {\n qsa(root.ownerDocument || root, 'script[type=\"application/json\"][data-tether-hydrate]').forEach((s) => {\n if (readScripts.has(s)) return;\n readScripts.add(s);\n try {\n const data = JSON.parse(s.textContent);\n rememberOptionNames(data.products); // the build's option names, also for other languages\n const same = (a, b) => String(a || '').toUpperCase() === String(b || '').toUpperCase();\n if (same(data.country, cfg.country) && same(data.language, cfg.language)) hydrateProducts(data.products);\n else {\n // The page was built for another market: its prices aren't this visitor's. Mark the page\n // (html.tether-market-pending) until the live ones are in, so CSS can hide prices meanwhile.\n log('hydration skipped: other market');\n if (!marketPending) { marketPending = new Set(); document.documentElement.classList.add(`${cfg.prefix}-market-pending`); }\n }\n } catch (err) { warn('bad data-tether-hydrate', err); }\n });\n}\n", "/**\n * <script> build: optional parts are separate files next to tether(.min).js, e.g.\n * tether.markets.min.js, loaded on first use. Override the folder with config.partsUrl.\n */\nimport * as config from './config.js';\nimport * as client from './client.js';\nimport * as dom from './dom.js';\nimport * as fragments from './fragments.js';\nimport * as loader from './loader.js';\nimport * as sellingPlans from './selling-plans.js';\nimport * as status from './status.js';\nimport * as cart from './cart.js';\nimport * as product from './product.js';\nimport * as collection from './collection.js';\nimport * as mounting from './mounting.js';\n\nconst { cfg } = config;\n\n/** The modules a part may use, shared instead of bundled twice (scripts/build.mjs maps imports to these). */\nexport const coreModules = {\n 'config.js': config, 'client.js': client, 'dom.js': dom, 'fragments.js': fragments, 'loader.js': loader,\n 'selling-plans.js': sellingPlans, 'status.js': status, 'cart.js': cart, 'product.js': product,\n 'collection.js': collection, 'mounting.js': mounting,\n};\n\nconst self = typeof document !== 'undefined' ? document.currentScript?.src || '' : '';\nconst parts = {};\n\nexport function loadPart(name) {\n if (parts[name]) return parts[name];\n const base = cfg.partsUrl || self.replace(/[^/]*$/, '');\n const min = /\\.min\\.js(\\?|$)/.test(self) || !self ? '.min' : '';\n const url = `${base.replace(/\\/?$/, '/')}tether.${name}${min}.js`;\n parts[name] = new Promise((resolve, reject) => {\n const s = document.createElement('script');\n s.src = url;\n s.async = true;\n s.onload = () => (window.Tether?.__parts?.[name] ? resolve(window.Tether.__parts[name]) : reject(new Error(`${url} did not register`)));\n s.onerror = () => { delete parts[name]; reject(new Error(`Could not load ${url}. Host it next to the Tether script, or set partsUrl.`)); };\n document.head.appendChild(s);\n });\n return parts[name];\n}\n\n// Parts that load other parts (account -> account-pages) use this same loader.\ncoreModules['lazy.js'] = { loadPart, coreModules };\n", "/**\n * Tether \u2014 Shopify <-> Webflow (or any HTML) sync via the Storefront API.\n *\n * <script>window.TETHER_CONFIG = { domain: 'x.myshopify.com', token: '...' }</script>\n * <script src=\"tether.min.js\" defer></script>\n *\n * With page transitions (Barba, Swup): set autoMount: false, call\n * Tether.init() once and Tether.mount(container) after every page enter.\n */\nimport { cfg, configure, isConfigured, log, warn, reportError } from './config.js';\nimport { gql, TetherError, withContext } from './client.js';\nimport { Cart, focusables } from './cart.js';\nimport { scopes } from './product.js';\nimport { ListScope, listSelector } from './collection.js';\nimport {\n getProduct, getProducts, getRecommendations, clearProductCache, primeProduct, normalizeProductKey,\n} from './loader.js';\nimport * as plans from './selling-plans.js';\nimport { resolveProductKey } from './status.js';\nimport { attr, sel, get, qsa, emit, formatMoney, busy, parseJSONAttr, toAttributes, imageUrl } from './dom.js';\nimport { loadPart, coreModules } from './lazy.js';\nimport { mountedLists, liveLists, pruneLive, within, mountProduct, retryFailed, hydrateFromPage, settleMarket, trackMarket } from './mounting.js';\n\nexport const VERSION = '0.6.6';\n\nlet initPromise = null;\nlet observer = null;\n\n/** Mount every product scope and product list inside `root`. Safe to call repeatedly. */\nexport function mount(root = document) {\n if (!isConfigured()) return 0;\n let count = 0;\n pruneLive(); // page transitions detach old roots: don't keep them alive\n hydrateFromPage(root); // products the server already rendered: no request needed\n\n within(root, listSelector()).forEach((el) => {\n if (mountedLists.has(el)) return;\n mountedLists.add(el);\n count++;\n const list = new ListScope(el);\n liveLists.add(list);\n el.addEventListener(`${cfg.prefix}:list-rendered`, (e) => mount(e.detail.container));\n trackMarket(list.load());\n });\n\n within(root, sel('product')).forEach((el) => { if (mountProduct(el)) count++; });\n\n // The country select lives in the optional markets part: load it only when the page uses it.\n if (within(root, `${sel('country-select')},${sel('country-bind')}`).length) {\n loadPart('markets').then((m) => m.renderCountrySelects(root)).catch((err) => reportError(err, 'markets'));\n }\n\n // Customer accounts: their own optional part, when configured and the page (or a login) needs it.\n if ((cfg.account?.clientId || cfg.account?.server) && (within(root, ['account-login', 'account-bind', 'account-link', 'orders', 'order', 'addresses', 'subscriptions', 'profile-form', 'address-form'].map((n) => `[${attr(n)}]`).join(',') + `,[${attr('show')}^=\"logged-\"]`).length\n || /[?&]code=/.test(window.location.search) || hasAccountSession())) {\n loadPart('account').then((m) => m.mountAccount(root)).catch((err) => reportError(err, 'account'));\n }\n\n // Search as you type: its own optional part, only for pages that have it.\n if (within(root, sel('search')).length) {\n loadPart('search').then((m) => m.mountSearch(root)).catch((err) => reportError(err, 'search'));\n }\n\n\n settleMarket();\n Cart.render();\n log(`mounted ${count} scope(s)`, root);\n return count;\n}\n\n// ---------------------------------------------------------------------------\n// Markets: country select + switching\n// ---------------------------------------------------------------------------\n\n/** Call before a page transition removes `root` (closes the drawer etc.). */\nexport function unmount() {\n Cart.close();\n}\n\nexport function getScope(el) {\n const root = el?.closest?.(sel('product'));\n return root ? scopes.get(root) || null : null;\n}\n\n// ---------------------------------------------------------------------------\n// Document-wide controls (delegated, so they survive page swaps)\n// ---------------------------------------------------------------------------\n\nlet controlsBound = false;\n\nfunction bindControls() {\n if (controlsBound) return;\n controlsBound = true;\n\n document.addEventListener('click', (e) => {\n const t = e.target;\n if (!t?.closest) return;\n\n if (t.closest(sel('cart-open'))) { e.preventDefault(); Cart.toggle(); return; }\n if (t.closest(sel('cart-close'))) { e.preventDefault(); Cart.close(); return; }\n\n const clear = t.closest(sel('cart-clear'));\n if (clear) { e.preventDefault(); busy(clear, () => Cart.clear().catch((err) => reportError(err, 'cart clear'))); return; }\n\n const checkout = t.closest(sel('checkout'));\n if (checkout) { e.preventDefault(); busy(checkout, () => Cart.checkout()); return; }\n\n const line = t.closest(dataKeySel());\n if (line && line.closest(sel('cart-lines'))) {\n const id = line.getAttribute(`data-${cfg.prefix}-key`);\n const current = Cart.lines.find((l) => l.id === id);\n const run = (fn) => { e.preventDefault(); fn().catch((err) => reportError(err, 'cart line')); };\n if (t.closest(sel('line-remove'))) { line.classList.add('is-busy'); return run(() => Cart.removeLine(id)); }\n if (current && t.closest(sel('line-plus'))) return run(() => Cart.changeQuantity(id, 1));\n if (current && t.closest(sel('line-minus'))) return run(() => Cart.changeQuantity(id, -1));\n }\n\n const removeCode = t.closest(sel('discount-remove'));\n if (removeCode) {\n e.preventDefault();\n const code = removeCode.closest(sel('discount-code'))?.getAttribute(attr('discount-code'));\n if (code) Cart.removeDiscount(code).catch((err) => reportError(err, 'discount'));\n return;\n }\n\n const groupBtn = t.closest(sel('group-add'));\n if (groupBtn) { e.preventDefault(); busy(groupBtn, () => addGroup(groupBtn)); }\n });\n\n document.addEventListener('change', (e) => {\n const t = e.target;\n if (!t?.closest) return;\n const lineEl = t.closest(dataKeySel());\n const id = lineEl?.getAttribute(`data-${cfg.prefix}-key`);\n // The line shows is-busy / aria-busy until Shopify has answered (removed by the next render).\n const busyLine = (p, what) => { lineEl.classList.add('is-busy'); lineEl.setAttribute('aria-busy', 'true'); p.catch((err) => reportError(err, what)); };\n if (id && t.matches(`input${sel('line', 'quantity')}`)) {\n busyLine(Cart.updateLine(id, parseInt(t.value, 10) || 0), 'cart line');\n } else if (id && t.matches(`select${sel('line-plan')}`)) {\n busyLine(Cart.updateLine(id, { sellingPlanId: t.value || null }), 'cart line plan');\n } else if (t.matches(`select${sel('country-select')}`)) {\n if (t.value) setCountry(t.value).catch((err) => reportError(err, 'country'));\n } else if (t.matches(sel('cart-note'))) {\n Cart.setNote(t.value).catch((err) => reportError(err, 'cart note'));\n }\n });\n\n document.addEventListener('submit', (e) => {\n const form = e.target.closest?.(sel('discount-form'));\n if (!form) return;\n e.preventDefault();\n const input = form.querySelector(sel('discount-input')) || form.querySelector('input');\n const code = input?.value.trim();\n if (!code) return;\n busy(form, async () => {\n const mark = (bad) => {\n form.classList.toggle('is-invalid', bad);\n if (input) { if (bad) input.setAttribute('aria-invalid', 'true'); else input.removeAttribute('aria-invalid'); }\n };\n try {\n await Cart.applyDiscount(code);\n mark(false);\n emit('discount-applied', { code }, form);\n if (input) input.value = '';\n } catch (err) {\n mark(true);\n if (err?.code === 'INVALID_DISCOUNT') emit('discount-invalid', { code }, form); else reportError(err, 'discount');\n }\n });\n }, true); // capture: before a router (Astro's ClientRouter) turns the submit into a navigation\n document.addEventListener('input', (e) => {\n const f = e.target.closest?.(sel('discount-form'));\n if (f) { f.classList.remove('is-invalid'); e.target.removeAttribute?.('aria-invalid'); }\n });\n\n // Other tabs: the cart or the market changed there (handled by the extras part, loaded then).\n window.addEventListener('storage', (e) => {\n if (cfg.domain && e.key?.startsWith(`${cfg.prefix}:`)) loadPart('extras').then((m) => m.onStorage(e)).catch(() => {});\n });\n // Shareable variant links: only when turned on.\n document.addEventListener(`${cfg.prefix}:variant-changed`, (e) => {\n const root = e.target;\n if (cfg.variantUrl || root.hasAttribute?.(attr('variant-url'))) loadPart('extras').then((m) => m.writeVariantUrl(root, e.detail)).catch(() => {});\n });\n\n // Astro View Transitions (<ClientRouter />): mount every new page, close the cart while leaving.\n if (cfg.astro !== false) {\n // Astro fires this on the first load too: wait for init (the visitor's saved market) first.\n document.addEventListener('astro:page-load', () => (initPromise || Promise.resolve()).then(() => {\n // Navigated to a page of another market (e.g. /de/): switch first, then mount in that market.\n // Back on a normal page after one: the visitor's own choice, else the default market.\n let target = pageMarket();\n if (!target && onPageMarket) {\n try { target = JSON.parse(localStorage.getItem(`${cfg.prefix}:market:${cfg.domain}`) || 'null'); } catch { target = null; }\n target = target?.country ? target : baseMarket;\n }\n onPageMarket = Boolean(pageMarket());\n const differs = target?.country && (String(target.country).toUpperCase() !== String(cfg.country || '').toUpperCase()\n || String(target.language || '').toUpperCase() !== String(cfg.language || '').toUpperCase());\n if (differs) setCountry(target.country, { language: target.language ?? null, locale: target.locale, remember: false }).then(() => mount(document), () => mount(document));\n else mount(document);\n }));\n document.addEventListener('astro:before-swap', () => unmount());\n }\n\n // Back online after a failed load: try the failed products and lists again.\n window.addEventListener('online', () => {\n retryFailed();\n liveLists.forEach((l) => { if (l.root.getAttribute(attr('state')) === 'error') l.load(); });\n });\n\n document.addEventListener('keydown', (e) => {\n if (!Cart.isOpen()) return;\n if (e.key === 'Escape') { Cart.close(); return; }\n if (e.key !== 'Tab' || cfg.cartFocus === false) return;\n // Keep Tab inside the open cart.\n const d = Cart.drawers().find((x) => x.classList.contains(cfg.cartDrawerOpenClass));\n const f = d ? focusables(d) : [];\n if (!f.length) return;\n const first = f[0];\n const last = f[f.length - 1];\n if (!d.contains(document.activeElement) || (e.shiftKey && document.activeElement === first) || (!e.shiftKey && document.activeElement === last)) {\n e.preventDefault();\n (e.shiftKey ? last : first).focus();\n }\n });\n}\n\nfunction dataKeySel() { return `[data-${cfg.prefix}-key]`; }\n\n/**\n * [tether-group] + [tether-group-add]: adds every product scope inside the\n * group in one request. Bundles, build-a-box, \"complete the set\".\n * Lines get attribute _group (and the group's tether-line-attributes).\n */\nexport const addGroup = (btn) => loadPart('extras').then((m) => m.addGroup(btn));\n\n// ---------------------------------------------------------------------------\n// Init\n// ---------------------------------------------------------------------------\n\nlet analyticsQueue = null;\n\nexport function init(overrides = {}) {\n if (initPromise && !Object.keys(overrides).length) return initPromise;\n configure({ ...(window.TETHER_CONFIG || {}), ...overrides });\n\n if (!isConfigured()) {\n warn('TETHER_CONFIG is missing domain or token. Tether is idle.');\n initPromise = Promise.resolve(null);\n return initPromise;\n }\n\n bindControls();\n if (cfg.observe) startObserver();\n // Analytics (optional part): buffer Tether's events until it has loaded, so none are missed.\n if (cfg.analytics && !analyticsQueue) {\n analyticsQueue = [];\n ['product-ready', 'list-ready', 'cart-updated', 'cart-toggled', 'checkout', 'search'].forEach((n) => document.addEventListener(`${cfg.prefix}:${n}`, (e) => analyticsQueue.push(e)));\n document.addEventListener('astro:page-load', () => analyticsQueue.push(new CustomEvent(`${cfg.prefix}:page`)));\n loadPart('analytics').then((m) => m.startAnalytics(analyticsQueue)).catch((err) => reportError(err, 'analytics'));\n }\n\n initPromise = applyMarket(overrides).then(() => Cart.init()).then(async (cart) => {\n // A saved cart from another market: move it to this one, so prices match the page.\n const want = cfg.country ? String(cfg.country).toUpperCase() : null;\n if (cart && want && cart.buyerIdentity?.countryCode && cart.buyerIdentity.countryCode !== want) {\n try { cart = await Cart.setBuyerIdentity({ countryCode: want }, { create: false }); } catch (err) { reportError(err, 'cart country'); }\n }\n emit('ready', { cart });\n return api;\n });\n return initPromise;\n}\n\n/**\n * Detected market (saved choice, server hint, Webflow locale) wins over the static config.\n * Without markets.detect only the visitor's saved choice applies, read here without loading\n * the markets part.\n */\n/**\n * A page built for one market (e.g. /de/ pages): <meta name=\"tether-page-country\" content=\"DE\">,\n * tether-page-language, tether-page-locale. Wins over the visitor's saved choice, isn't remembered.\n */\nfunction pageMarket(doc = document) {\n const get = (n) => doc.querySelector(`meta[name=\"${cfg.prefix}-page-${n}\"]`)?.getAttribute('content') || undefined;\n const country = get('country');\n return country ? { country: country.toUpperCase(), language: get('language'), locale: get('locale') } : null;\n}\n\nlet baseMarket = null; // the configured market, before a visitor's or page's market applied\nlet onPageMarket = false;\n\nasync function applyMarket(overrides) {\n const m = cfg.markets || {};\n baseMarket = { country: cfg.country, language: cfg.language, locale: cfg.locale };\n const page = pageMarket();\n onPageMarket = Boolean(page);\n if (page) {\n cfg.country = page.country;\n cfg.language = page.language ? page.language.toUpperCase() : undefined;\n if (page.locale) cfg.locale = page.locale;\n return;\n }\n if (m.detect === false) return;\n let market = null;\n if (m.detect) {\n try { market = (await loadPart('markets')).detectMarket(m); } catch (err) { reportError(err, 'markets'); return; }\n } else if (m.remember !== false) {\n try { market = JSON.parse(localStorage.getItem(`${cfg.prefix}:market:${cfg.domain}`) || 'null'); } catch { /* none */ }\n if (market && !/^[A-Z]{2}$/.test(market.country || '')) market = null;\n }\n if (!market) return;\n if (market.country) cfg.country = market.country;\n if (market.language) cfg.language = market.language;\n if (market.locale && !overrides.locale) cfg.locale = market.locale; // the visitor's market wins over the default\n log('market', market);\n}\n\nfunction hasAccountSession() {\n try { return Boolean(sessionStorage[`${cfg.prefix}:account:${cfg.domain}`] || localStorage[`${cfg.prefix}:account:${cfg.domain}`] || localStorage[`${cfg.prefix}:account-hint:${cfg.domain}`]); } catch { return false; }\n}\n\n/** Customer accounts (optional part, loaded on first use). See src/account.js. */\nconst accountApi = new Proxy({}, { get: (_, n) => (...a) => loadPart('account').then((m) => m[n](...a)) });\n\n/** Tether.setCountry('DE'): loads the markets part on first use. */\nexport function setCountry(code, opts) {\n return loadPart('markets').then((m) => m.setCountry(code, opts));\n}\n\nfunction startObserver() {\n if (observer || typeof MutationObserver === 'undefined') return;\n let t = null;\n const queued = new Set();\n observer = new MutationObserver((muts) => {\n muts.forEach((m) => m.addedNodes.forEach((n) => { if (n.nodeType === 1) queued.add(n); }));\n clearTimeout(t);\n t = setTimeout(() => { queued.forEach((n) => { if (n.isConnected) mount(n); }); queued.clear(); }, 50);\n });\n observer.observe(document.body, { childList: true, subtree: true });\n}\n\nexport const api = {\n VERSION,\n init,\n mount,\n unmount,\n get config() { return cfg; },\n get ready() { return initPromise || Promise.resolve(null); },\n query: gql,\n withContext,\n cart: Cart,\n getProduct,\n getProducts,\n getRecommendations,\n getScope,\n addGroup,\n account: accountApi,\n primeProduct,\n normalizeProductKey,\n clearProductCache,\n formatMoney,\n imageUrl,\n plans,\n TetherError,\n resolveProductKey,\n setCountry,\n detectMarket: (markets) => loadPart('markets').then((m) => m.detectMarket(markets || cfg.markets)),\n getLocalization: () => loadPart('markets').then((m) => m.getLocalization()),\n diagnose: (opts) => loadPart('diagnose').then((m) => m.diagnose({ ...opts, version: VERSION })),\n __core: coreModules,\n __parts: {},\n on(name, fn) {\n const h = (e) => fn(e.detail, e);\n document.addEventListener(`${cfg.prefix}:${name}`, h);\n return () => document.removeEventListener(`${cfg.prefix}:${name}`, h);\n },\n};\n\nexport default api;\n\n// Auto-start for the plain <script> setup.\nif (typeof window !== 'undefined' && typeof document !== 'undefined') {\n window.Tether = api;\n // Not with a framework integration (Astro), which starts Tether itself.\n const auto = window.TETHER_CONFIG && window.TETHER_CONFIG.autoMount !== false && !window.TETHER_INTEGRATION;\n if (auto) {\n const start = () => init().then(() => mount(document));\n if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start, { once: true });\n else start();\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["config_exports", "__export", "DEFAULTS", "cfg", "configure", "isConfigured", "log", "reportError", "warn", "overrides", "k", "a", "err", "context", "client_exports", "__export", "TetherError", "endpoint", "gql", "request", "unwrap", "withContext", "TetherError", "message", "status", "errors", "userErrors", "code", "endpoint", "conf", "cfg", "withContext", "query", "ctx", "args", "tag", "sleep", "ms", "r", "statusText", "request", "variables", "context", "text", "age", "body", "attempt", "res", "err", "log", "json", "e", "gql", "opts", "unwrap", "payload", "name", "errs", "cart_exports", "__export", "Cart", "focusables", "toLineInput", "fragments_exports", "__export", "ALLOCATION_FIELDS", "SELLING_PLAN_FIELDS", "cartFragment", "collectionFields", "metafieldIdentifiers", "productFragment", "MONEY", "IMAGE", "metafieldIdentifiers", "o", "cfg", "m", "i", "metafieldsField", "ids", "SELLING_PLAN_FIELDS", "ALLOCATION_FIELDS", "productFragment", "cartFragment", "collectionFields", "loader_exports", "__export", "clearProductCache", "getProduct", "getProducts", "getRecommendations", "hydrateProducts", "normalizeProductKey", "primeProduct", "refreshProducts", "takeStale", "productCache", "pending", "resolvers", "scheduled", "generation", "isGid", "v", "normalizeProductKey", "raw", "m", "primeProduct", "product", "p", "getProduct", "rawKey", "key", "TetherError", "resolve", "reject", "flush", "gen", "keys", "ids", "handles", "k", "defs", "parts", "vars", "h", "i", "query", "productFragment", "log", "settle", "fn", "r", "data", "gql", "got", "freshAt", "miss", "err", "clearProductCache", "stale", "FRESH_MS", "hydrateProducts", "products", "takeStale", "x", "refreshProducts", "getProducts", "collection", "first", "cfg", "after", "sortKey", "reverse", "filters", "fragment", "collectionFields", "rest", "getRecommendations", "intent", "byId", "list", "selling_plans_exports", "__export", "GID", "allPlans", "allocationFor", "findPlan", "hasPlans", "planAdjustment", "planCheckoutCharge", "planPrice", "planSavings", "plansForVariant", "toGid", "v", "value", "type", "product", "g", "p", "variant", "planId", "a", "adj", "base", "sub", "plan", "ref", "plans", "gid", "needle", "o", "dom_exports", "__export", "attr", "busy", "cdnUrl", "dataKey", "emit", "formatDate", "formatMoney", "formatPercent", "get", "has", "hasTemplate", "imageUrl", "notifyLayoutChanged", "parseJSONAttr", "productUrl", "qsa", "readText", "repeat", "repeatKeyed", "sameImage", "scoped", "sel", "setImage", "setSelected", "setText", "setTextTracked", "show", "toAttributes", "watchImages", "attr", "name", "cfg", "sel", "value", "get", "el", "has", "dataKey", "productUrl", "handle", "id", "path", "numeric", "qsa", "root", "s", "scoped", "scopeSelector", "emit", "detail", "target", "formatPercent", "n", "locale", "formatMoney", "money", "amount", "formatDate", "iso", "imageUrl", "url", "width", "height", "crop", "u", "cdnUrl", "g", "k", "sameImage", "a", "b", "setImage", "alt", "src", "setText", "v", "text", "readText", "setTextTracked", "before", "after", "show", "visible", "setSelected", "selected", "input", "templates", "hasTemplate", "container", "template", "tpl", "repeat", "items", "render", "warn", "item", "i", "node", "repeatKeyed", "keyOf", "onEnter", "onLeave", "KEY", "LEAVING", "live", "existing", "wanted", "fresh", "staying", "current", "prev", "done", "layoutTimer", "notifyLayoutChanged", "reason", "watchImages", "imgs", "left", "img", "busy", "fn", "parseJSONAttr", "raw", "toAttributes", "obj", "key", "toLineInput", "input", "quantity", "opts", "src", "merchandiseId", "GID", "TetherError", "line", "plan", "attrs", "toAttributes", "mutation", "name", "args", "inner", "cartFragment", "FOCUSABLE", "returnFocus", "focusables", "d", "qsa", "el", "ariaState", "open", "sel", "b", "get", "cfg", "isMissingCart", "err", "Cart", "id", "payload", "p", "unwrap", "w", "all", "x", "emit", "fn", "run", "value", "cart", "reason", "n", "data", "gql", "reportError", "buyerIdentity", "variables", "createInput", "cartId", "log", "lines", "l", "lineId", "patch", "delta", "current", "target", "job", "latest", "now", "lineIds", "ids", "note", "obj", "merged", "a", "attributes", "v", "key", "codes", "discountCodes", "c", "code", "k", "create", "tab", "url", "ds", "hadFocus", "call", "h", "e", "count", "money", "formatMoney", "setTextTracked", "hasSub", "conds", "show", "container", "repeat", "node", "attr", "t", "setText", "repeatKeyed", "renderLine", "notifyLayoutChanged", "lineValue", "m", "o", "isSub", "setImage", "u", "productUrl", "q", "qs", "warning", "pending", "lineConds", "select", "handle", "getProduct", "product", "plans", "allPlans", "want", "sig", "product_exports", "__export", "ProductScope", "rememberOptionNames", "scopes", "status_exports", "__export", "STATUS_KEYS", "boundary", "isNotFound", "ownedBy", "resolveProductKey", "setScopeStatus", "resolveProductKey", "el", "location", "name", "raw", "get", "what", "key", "parts", "safeDecode", "s", "STATUS_KEYS", "isNotFound", "err", "boundary", "n", "sel", "ownedBy", "root", "setScopeStatus", "status", "notFound", "attr", "scoped", "k", "show", "btn", "scopes", "productSel", "sel", "metafieldValue", "product", "ref", "i", "ns", "key", "m", "knownOptionNames", "rememberOptionNames", "products", "p", "o", "ProductScope", "root", "get", "has", "allPlans", "attr", "watchImages", "notifyLayoutChanged", "emit", "variantId", "v", "x", "s", "inner", "scoped", "authored", "opts", "vs", "first", "param", "gid", "GID", "match", "params", "fromUrl", "findPlan", "fromAttr", "wanted", "cfg", "name", "value", "allocationFor", "line", "attrs", "fixed", "toAttributes", "parseJSONAttr", "inputs", "el", "next", "score", "a", "b", "id", "mode", "n", "min", "setText", "cart", "Cart", "own", "e", "t", "opt", "plan", "purchase", "plus", "minus", "add", "btn", "label", "busyText", "write", "txt", "busy", "err", "reportError", "p0", "formatDate", "formatMoney", "setImage", "productUrl", "imgs", "hasTemplate", "im", "sameImage", "repeat", "node", "img", "target", "exclude", "tag", "mf", "container", "show", "sw", "raw", "group", "plans", "pl", "alt", "sub", "oneTimePrice", "subPrice", "planPrice", "price", "compareAt", "onSale", "discountPct", "savings", "planSavings", "total", "fm", "pct", "formatPercent", "text", "c", "planCheckoutCharge", "k", "qsa", "setSelected", "unavailable", "planObj", "inVariant", "adj", "planAdjustment", "val", "low", "conds", "STATUS_KEYS", "ownedBy", "disabled", "soldOut", "subText", "collection_exports", "__export", "ListScope", "listSelector", "listSelector", "sel", "ListScope", "root", "setScopeStatus", "e", "more", "busy", "s", "scoped", "r", "opts", "get", "has", "raw", "token", "stale", "key", "resolveProductKey", "scope", "TetherError", "recs", "getRecommendations", "limit", "res", "getProducts", "emit", "err", "isNotFound", "reportError", "c", "el", "setText", "setImage", "container", "repeat", "node", "p", "attr", "empty", "k", "show", "notifyLayoutChanged", "mounting_exports", "__export", "hydrateFromPage", "liveLists", "liveProducts", "mountProduct", "mountedLists", "mountedProducts", "pruneLive", "retryFailed", "settleMarket", "trackMarket", "within", "mountedProducts", "mountedLists", "liveProducts", "liveLists", "requestToken", "pruneLive", "el", "l", "within", "root", "selector", "qsa", "mountProduct", "key", "fromUrl", "raw", "resolveProductKey", "setScopeStatus", "emit", "listSelector", "warn", "attr", "token", "current", "scopes", "loading", "getProduct", "marketPending", "p", "existing", "ProductScope", "applyPageTitle", "cfg", "takeStale", "queueRefresh", "err", "notFound", "isNotFound", "log", "reportError", "tpl", "get", "retryFailed", "refreshQueue", "flushRefresh", "keys", "refreshProducts", "promise", "i", "fresh", "scope", "k", "readScripts", "trackMarket", "settleMarket", "waits", "w", "hydrateFromPage", "s", "data", "rememberOptionNames", "same", "a", "b", "hydrateProducts", "cfg", "config_exports", "coreModules", "client_exports", "dom_exports", "fragments_exports", "loader_exports", "selling_plans_exports", "status_exports", "cart_exports", "product_exports", "collection_exports", "mounting_exports", "self", "parts", "loadPart", "name", "base", "min", "url", "resolve", "reject", "s", "VERSION", "initPromise", "observer", "mount", "root", "isConfigured", "count", "pruneLive", "hydrateFromPage", "within", "listSelector", "el", "mountedLists", "list", "ListScope", "liveLists", "cfg", "e", "trackMarket", "sel", "mountProduct", "loadPart", "m", "err", "reportError", "attr", "hasAccountSession", "settleMarket", "Cart", "log", "unmount", "getScope", "scopes", "controlsBound", "bindControls", "t", "clear", "busy", "checkout", "line", "dataKeySel", "id", "current", "l", "run", "fn", "removeCode", "code", "groupBtn", "addGroup", "lineEl", "busyLine", "p", "what", "setCountry", "form", "input", "mark", "bad", "emit", "f", "target", "pageMarket", "onPageMarket", "baseMarket", "retryFailed", "d", "x", "focusables", "first", "last", "btn", "analyticsQueue", "init", "overrides", "configure", "startObserver", "n", "applyMarket", "cart", "want", "api", "warn", "doc", "get", "country", "page", "market", "accountApi", "_", "a", "opts", "queued", "muts", "gql", "withContext", "getProduct", "getProducts", "getRecommendations", "primeProduct", "normalizeProductKey", "clearProductCache", "formatMoney", "imageUrl", "selling_plans_exports", "TetherError", "resolveProductKey", "markets", "coreModules", "name", "h", "index_default", "start"]
|
|
3
|
+
"sources": ["../src/config.js", "../src/client.js", "../src/market-codes.js", "../src/cart.js", "../src/dom.js", "../src/markup.js", "../src/store-html.js", "../src/shopify-values.js", "../src/images.js", "../src/repeaters.js", "../src/fragments.js", "../src/selling-plans.js", "../src/cart/drawer.js", "../src/loader.js", "../src/amounts.js", "../src/cart/render.js", "../src/cart/store.js", "../src/cart/mutations.js", "../src/cart/checkout.js", "../src/product.js", "../src/product-state.js", "../src/product-render.js", "../src/status.js", "../src/variant-render.js", "../src/product-events.js", "../src/collection.js", "../src/mounting.js", "../src/lazy-iife.js", "../src/markets.js", "../src/page-market.js", "../src/account-api.js", "../src/controls/cart-controls.js", "../src/controls/discount.js", "../src/controls/extras.js", "../src/controls/navigation.js", "../src/index.js"],
|
|
4
|
+
"sourcesContent": ["/**\n * The runtime configuration. `cfg` is one shared object that every browser module imports; `configure()` replaces its\n * contents in place, so those imports see the new values, and `setCountry()` changes its market keys the same way.\n * Options that end up in query text or attribute names are validated here, once, where they arrive.\n */\n/** @import { Money } from './shopify-values.js' */\n\n/**\n * @typedef {object} MarketsConfig Where the visitor's market comes from (`markets.js`).\n * @property {boolean | ('saved' | 'server' | 'webflow')[]} [detect] true: every source; a list: only those.\n * @property {Record<string, { country?: string, language?: string, locale?: string }>} [locales] Webflow locale\n * (subdirectory or html lang) to market.\n * @property {string} [cookie] The cookie a server sets with the visitor's country.\n * @property {boolean} [remember] Remember the visitor's choice (default true).\n * @property {boolean} [strict] With `locales`: ignore an html lang that isn't in the map.\n */\n\n/**\n * @typedef {object} AnalyticsConfig The optional analytics part.\n * @property {boolean | string} [dataLayer] GA4/GTM events, into `window.dataLayer` or the named array.\n * @property {boolean | { consent?: 'no-banner' | 'default-banner' | 'custom-banner', proxy?: string }} [shopify]\n * Shopify's own analytics.\n * @property {(name: string, data: Record<string, unknown>) => void} [onEvent]\n */\n\n/**\n * @typedef {object} AccountConfig The optional customer accounts part.\n * @property {string} [clientId] Browser mode: the Customer Account API client id.\n * @property {string} [server] Server mode: the Worker's account routes, a URL or a path on this site.\n * @property {string} [orderUrl] The site's own order page, with `{id}` for the numeric order id.\n * @property {string} [subscriptionsUrl] Shopify's subscription management page.\n * @property {string} [paymentUrl] A separate page for payment methods (default `subscriptionsUrl`).\n * @property {string} [callbackUrl] Where Shopify sends the visitor after login (default the current page).\n * @property {string} [logoutUrl] Where Shopify sends the visitor after logout (default the home page).\n * @property {boolean} [remember] Keep the login across tabs and restarts (localStorage, not sessionStorage).\n * @property {string} [tokenUrl] The site's own token endpoint, for when the browser can't call Shopify's.\n * @property {string} [shopDomain] The *.myshopify.com domain, when `domain` is another one.\n * @property {string} [locale] The language of Shopify's login pages.\n * @property {(url: string) => void} [navigate] Replaces `location.assign` for the login redirect (popups, tests).\n */\n\n/** @typedef {{ namespace: string, key: string }} MetafieldIdentifier */\n/** @typedef {string | MetafieldIdentifier} MetafieldRef `'namespace.key'` or the identifier itself. */\n/** @typedef {{ code: string, message: string, target?: string }} CartWarning Shopify's note on a cart change. */\n/** @typedef {'_self' | '_blank'} CheckoutTarget */\n/** @typedef {'one-time' | 'subscription'} PurchaseKind */\n\n/**\n * @typedef {object} TetherConfig Every option, with its default filled in.\n * @property {string} domain The store's domain, without protocol or path.\n * @property {string} token The public Storefront API access token.\n * @property {string} apiVersion A dated Shopify API version.\n * @property {string | undefined} country An ISO country code for `@inContext(country:)`.\n * @property {string | undefined} language A language for `@inContext(language:)`.\n * @property {string | undefined} locale An `Intl` locale for money and dates.\n * @property {MarketsConfig | null} markets\n * @property {string} prefix The attribute prefix: `tether` reads `tether-product`, `tether-bind`.\n * @property {string} productPath A folder (`/product`) or a template with `{handle}` / `{id}`.\n * @property {string} collectionPath\n * @property {MetafieldRef[]} metafields The product metafields to fetch.\n * @property {number} imagesFirst\n * @property {number} variantsFirst\n * @property {number} sellingPlanGroupsFirst\n * @property {number} sellingPlansFirst\n * @property {number} collectionFirst\n * @property {number} retries Retries of a request that failed on the network, a 429/5xx or Shopify's throttling.\n * @property {boolean} revalidate Refresh server-rendered products once in the background.\n * @property {string} storageKey The localStorage key of the cart id (default `<prefix>:cart:<domain>`).\n * @property {string} cartDrawerOpenClass\n * @property {boolean} openCartOnAdd\n * @property {boolean} cartFocus Move focus into the open cart, keep Tab inside it, restore it on close.\n * @property {CheckoutTarget} checkoutTarget\n * @property {PurchaseKind} defaultPurchase\n * @property {boolean} variantUrl `?variant=` follows the visitor's choice on the page's main product.\n * @property {number} maxAge Seconds a Shopify answer may be cached; 0 leaves it to Shopify, which can be hours.\n * @property {number} lowStock `tether-show=\"low-stock\"` at this many or fewer (needs inventory access).\n * @property {number} searchDelay Milliseconds the search part waits after the last keystroke.\n * @property {boolean} autoMount Mount the document on DOMContentLoaded.\n * @property {boolean} observe Mount elements added later (CMS load more, filters).\n * @property {boolean} astro Mount on Astro's `astro:page-load` and close the cart on navigation.\n * @property {string | null} partsUrl The folder of the optional parts, for the `<script>` build.\n * @property {AnalyticsConfig | null} analytics\n * @property {AccountConfig | null} account\n * @property {((warning: CartWarning) => string | null | undefined) | null} warningText The site's text for a cart\n * warning; nothing keeps Shopify's.\n * @property {((money: Money, locale: string | undefined) => string) | null} formatMoney\n * @property {((reason: string) => void) | null} onLayoutChange Default: `ScrollTrigger.refresh()` when present.\n * @property {((drawers: HTMLElement[]) => void) | null} onCartOpen\n * @property {((drawers: HTMLElement[]) => void) | null} onCartClose\n * @property {((node: HTMLElement) => void) | null} onLineEnter\n * @property {((node: HTMLElement, done: () => void) => void) | null} onLineLeave Animates a line out, then calls\n * `done()`.\n * @property {((element: HTMLElement, previousText: string) => void) | null} onValueChange\n * @property {((error: unknown, context: string) => void) | null} onError Every failure that reaches the visitor.\n * @property {boolean} debug\n */\n\n/** @typedef {{ [Key in keyof TetherConfig]?: TetherConfig[Key] }} TetherOptions */\n\n/** @type {Readonly<TetherConfig>} */\nexport const DEFAULTS = {\n domain: '',\n token: '',\n apiVersion: '2026-07',\n country: undefined,\n language: undefined,\n locale: undefined,\n markets: null,\n prefix: 'tether',\n productPath: '/product',\n collectionPath: '/collection',\n metafields: [],\n imagesFirst: 25,\n variantsFirst: 100,\n sellingPlanGroupsFirst: 10,\n sellingPlansFirst: 25,\n collectionFirst: 24,\n retries: 2,\n revalidate: true,\n storageKey: '',\n cartDrawerOpenClass: 'is-open',\n openCartOnAdd: true,\n cartFocus: true,\n checkoutTarget: '_self',\n defaultPurchase: 'one-time',\n variantUrl: false,\n maxAge: 60,\n lowStock: 5,\n searchDelay: 150,\n autoMount: true,\n observe: false,\n astro: true,\n partsUrl: null,\n analytics: null,\n account: null,\n warningText: null,\n formatMoney: null,\n onLayoutChange: null,\n onCartOpen: null,\n onCartClose: null,\n onLineEnter: null,\n onLineLeave: null,\n onValueChange: null,\n onError: null,\n debug: false,\n};\n\n/** @type {TetherConfig} */\nexport const cfg = { ...DEFAULTS };\n\n/** The prefix becomes part of attribute names, CSS selectors and event names, so it is kept to those characters. */\nconst PREFIX = /^[a-z][a-z0-9-]*$/;\n/**\n * Metafield identifiers are written into the product fragment's text: a GraphQL fragment can't declare variables, so\n * they can't be sent as variables. Only these characters are let through, which covers Shopify's namespaces and keys.\n */\nconst METAFIELD_PART = /^[A-Za-z0-9_.-]+$/;\n/** A namespace is the same, or an app-reserved one: `$app` or `$app:<name>`. */\nconst METAFIELD_NAMESPACE = /^(\\$app(:[A-Za-z0-9_-]+)?|[A-Za-z0-9_.-]+)$/;\n\n/**\n * @typedef {'imagesFirst' | 'variantsFirst' | 'sellingPlanGroupsFirst' | 'sellingPlansFirst' | 'collectionFirst'\n * | 'retries' | 'maxAge' | 'lowStock'} CountOption\n */\n/**\n * @typedef {'warningText' | 'formatMoney' | 'onLayoutChange' | 'onCartOpen' | 'onCartClose' | 'onLineEnter'\n * | 'onLineLeave' | 'onValueChange' | 'onError'} HookOption\n */\n\n/** @type {readonly CountOption[]} Options that are written into queries as list sizes or used as counts. */\nconst COUNT_OPTIONS = [\n 'imagesFirst',\n 'variantsFirst',\n 'sellingPlanGroupsFirst',\n 'sellingPlansFirst',\n 'collectionFirst',\n 'retries',\n 'maxAge',\n 'lowStock',\n];\n/** @type {readonly HookOption[]} */\nconst HOOK_OPTIONS = [\n 'warningText',\n 'formatMoney',\n 'onLayoutChange',\n 'onCartOpen',\n 'onCartClose',\n 'onLineEnter',\n 'onLineLeave',\n 'onValueChange',\n 'onError',\n];\n\n/**\n * @template T\n * @param {string} name\n * @param {unknown} value\n * @param {T} fallback\n * @returns {T} `fallback`, with a warning unless `value` was left out.\n */\nfunction invalidOption(name, value, fallback) {\n if (value !== undefined) warn(`invalid ${name} ${JSON.stringify(value)}: using ${JSON.stringify(fallback)}`);\n return fallback;\n}\n\n/**\n * @param {CountOption} name\n * @param {unknown} value\n * @returns {number} `value` when it is a non-negative integer, else the default.\n */\nfunction countOption(name, value) {\n if (typeof value === 'number' && Number.isInteger(value) && value >= 0) return value;\n return invalidOption(name, value, DEFAULTS[name]);\n}\n\n/**\n * @template {string} Choice\n * @param {string} name\n * @param {unknown} value\n * @param {readonly [Choice, ...Choice[]]} choices The first one is the default.\n * @returns {Choice}\n */\nfunction choiceOption(name, value, choices) {\n return choices.find((choice) => choice === value) ?? invalidOption(name, value, choices[0]);\n}\n\n/**\n * @param {unknown} value\n * @returns {string} The store's domain without protocol or path: `https://shop.example/x` \u2192 `shop.example`.\n */\nfunction domainOption(value) {\n if (typeof value !== 'string') return '';\n return value.replace(/^https?:\\/\\//, '').replace(/\\/.*$/, '');\n}\n\n/**\n * @param {unknown} ref\n * @returns {MetafieldIdentifier | null} The identifier of `'namespace.key'` or `{ namespace, key }`, when both parts are\n * valid identifiers.\n */\nexport function toMetafieldIdentifier(ref) {\n /** @type {unknown} */\n let namespace;\n /** @type {unknown} */\n let key;\n if (typeof ref === 'string') {\n const dot = ref.indexOf('.');\n namespace = dot > 0 ? ref.slice(0, dot) : '';\n key = ref.slice(dot + 1);\n } else if (typeof ref === 'object' && ref !== null) {\n namespace = Reflect.get(ref, 'namespace');\n key = Reflect.get(ref, 'key');\n }\n if (typeof namespace !== 'string' || typeof key !== 'string') return null;\n return METAFIELD_NAMESPACE.test(namespace) && METAFIELD_PART.test(key) ? { namespace, key } : null;\n}\n\n/**\n * @param {unknown} value\n * @returns {MetafieldRef[]} The refs that name a valid identifier, as written; each other one is skipped with a warning.\n */\nfunction metafieldsOption(value) {\n if (!Array.isArray(value)) return invalidOption('metafields', value, []);\n /** @type {MetafieldRef[]} */\n const refs = [];\n for (const ref of /** @type {unknown[]} */ (value)) {\n const identifier = toMetafieldIdentifier(ref);\n if (identifier) refs.push(typeof ref === 'string' ? ref : identifier);\n else invalidOption('metafield', ref, null);\n }\n return refs;\n}\n\n/**\n * The configuration `options` describe: defaults filled in, counts, prefix, choices and metafields validated (an\n * invalid value warns and falls back to its default), hooks that aren't functions dropped so callers only check for\n * null.\n *\n * @param {TetherOptions} options\n * @returns {TetherConfig}\n */\nexport function resolveConfig(options) {\n const domain = domainOption(options.domain);\n const prefix =\n typeof options.prefix === 'string' && PREFIX.test(options.prefix)\n ? options.prefix\n : invalidOption('prefix', options.prefix, DEFAULTS.prefix);\n /** @type {TetherConfig} */\n const resolved = {\n ...DEFAULTS,\n ...options,\n domain,\n prefix,\n storageKey: options.storageKey || `${prefix}:cart:${domain}`,\n metafields: metafieldsOption(options.metafields ?? []),\n checkoutTarget: choiceOption('checkoutTarget', options.checkoutTarget, ['_self', '_blank']),\n defaultPurchase: choiceOption('defaultPurchase', options.defaultPurchase, ['one-time', 'subscription']),\n };\n for (const name of COUNT_OPTIONS) resolved[name] = countOption(name, options[name]);\n for (const name of HOOK_OPTIONS) if (typeof resolved[name] !== 'function') resolved[name] = null;\n if (resolved.apiVersion === 'unstable') {\n warn('apiVersion \"unstable\" changes without notice. Pin a dated version (e.g. 2026-07).');\n }\n return resolved;\n}\n\n/**\n * Replaces the shared configuration with `options` over the defaults (see `resolveConfig`).\n *\n * @param {TetherOptions} [options]\n * @returns {TetherConfig} The shared `cfg`.\n */\nexport function configure(options = {}) {\n const resolved = resolveConfig(options);\n for (const key of Object.keys(cfg)) {\n if (!(key in resolved)) Reflect.deleteProperty(cfg, key);\n }\n return Object.assign(cfg, resolved);\n}\n\n/** @returns {boolean} True once a domain and a token are set. */\nexport const isConfigured = () => Boolean(cfg.domain && cfg.token);\n\n/** @param {...unknown} args */\nexport function log(...args) {\n if (cfg.debug) console.log(`[${cfg.prefix}]`, ...args);\n}\n\n/** @param {...unknown} args */\nexport function warn(...args) {\n console.warn(`[${cfg.prefix}]`, ...args);\n}\n\n/**\n * Logs a failure that reaches the visitor and hands it to `onError`. A throwing `onError` is logged, never rethrown:\n * the site's hook must not break the render that reported the failure.\n *\n * @param {unknown} error\n * @param {string} context What failed, e.g. `product coffee-box`.\n */\nexport function reportError(error, context) {\n warn(context, error instanceof Error && error.message ? error.message : error);\n if (!cfg.onError) return;\n try {\n cfg.onError(error, context);\n } catch (hookError) {\n warn('onError threw', hookError);\n }\n}\n", "/**\n * The one Storefront API client: a fetch wrapper that adds the market (`@inContext`), retries what Shopify asks to be\n * retried, and turns every failure into a `TetherError`. The browser (`gql`, also `Tether.query()`) and the server\n * helpers (`request` with their own config) share it.\n */\nimport { cfg, log } from './config.js';\nimport { toCountry, toLanguage } from './market-codes.js';\n/** @import { TetherConfig } from './config.js' */\n\n/**\n * @typedef {'NOT_FOUND' | 'NETWORK' | 'NOT_CONFIGURED' | 'NOT_LOGGED_IN' | 'NOT_ALLOWED' | 'INVALID'\n * | 'INVALID_COUNTRY' | 'INVALID_DISCOUNT' | 'SESSION_ENDED' | 'TOKEN_FAILED' | 'ERROR' | `HTTP_${number}`}\n * TetherErrorCode\n */\n/** @typedef {{ message: string, extensions?: { code?: string } }} GraphQLError */\n/** @typedef {{ data?: unknown, errors?: GraphQLError[] }} GraphQLResponse The response shape the GraphQL spec sets. */\n/** @typedef {{ message: string, field?: string[] | null, code?: string | null }} UserError */\n/**\n * @typedef {object} TetherErrorDetails\n * @property {TetherErrorCode} [code] Default `HTTP_<status>` with a status, else `ERROR`.\n * @property {number} [status] The HTTP status of the response that failed.\n * @property {GraphQLError[]} [errors] The GraphQL errors of that response.\n * @property {readonly UserError[]} [userErrors] A mutation's user errors.\n */\n\nexport class TetherError extends Error {\n /**\n * @param {string} message\n * @param {TetherErrorDetails} [details]\n */\n constructor(message, { status, errors, userErrors, code } = {}) {\n super(message);\n this.name = 'TetherError';\n /** @type {TetherErrorCode} */\n this.code = code ?? (status ? `HTTP_${status}` : 'ERROR');\n /** @type {number | undefined} */\n this.status = status;\n /** @type {GraphQLError[] | undefined} */\n this.errors = errors;\n /** @type {readonly UserError[] | undefined} */\n this.userErrors = userErrors;\n }\n}\n\n/**\n * What a request needs from a config: the browser's `cfg`, or a config the server helpers build.\n *\n * @typedef {Pick<TetherConfig, 'domain' | 'token' | 'apiVersion' | 'country' | 'language' | 'maxAge' | 'retries'>\n * & { fetch?: typeof fetch }} StorefrontConfig\n */\n/** @typedef {{ context?: boolean }} RequestOptions `context: false` sends the query without `@inContext`. */\n\n/**\n * @param {Pick<TetherConfig, 'domain' | 'apiVersion'>} [conf]\n * @returns {string} The Storefront GraphQL endpoint of `conf`'s store.\n */\nexport function endpoint(conf = cfg) {\n return `https://${conf.domain}/api/${conf.apiVersion}/graphql.json`;\n}\n\n/**\n * Adds @inContext(country, language) to the first operation in the document, so prices, currency and translations\n * follow the configured market. Operations are always written first, fragments after, so the first match is the\n * operation. A country or language that isn't a valid code is left out.\n *\n * @param {string} query\n * @param {{ country?: string | undefined, language?: string | undefined }} [ctx]\n * @returns {string}\n */\nexport function withContext(query, ctx = cfg) {\n const args = [];\n const country = toCountry(ctx.country);\n const language = toLanguage(ctx.language);\n if (country) args.push(`country: ${country}`);\n if (language) args.push(`language: ${language}`);\n if (!args.length || query.includes('@inContext')) return query;\n\n const tag = `@inContext(${args.join(', ')})`;\n // Named (query Name($x: T)), anonymous (query { \u2026 }) and shorthand ({ \u2026 }) queries.\n if (/^\\s*\\{/.test(query)) return `query ${tag} ${query.trimStart()}`;\n return query.replace(/^(\\s*(?:query|mutation)(?:\\s+\\w+)?\\s*(?:\\([^)]*\\))?)/, `$1 ${tag}`);\n}\n\n/** Backoff after a network error or a 429/5xx: this times 2^attempt. */\nconst RETRY_BACKOFF_MS = 300;\n/** Backoff after Shopify's `THROTTLED` error, which asks for a longer wait: this times 2^attempt. */\nconst THROTTLE_BACKOFF_MS = 500;\n/** Shopify's status for a request its bot protection rejected; retrying doesn't help. */\nconst SECURITY_REJECTION = 430;\n\n/**\n * `quantityAvailable` needs the token's `unauthenticated_read_product_inventory` scope; without it Shopify refuses the\n * whole query with an error naming the field. That refusal is learned once per page and store: every later query to\n * the store goes out without the field, so stock levels are unknown and everything else works for one extra request.\n */\nconst INVENTORY_FIELD = 'quantityAvailable';\n\n/** @type {Set<string>} The stores (domain, version and token) whose token can't read inventory. */\nconst storesWithoutInventory = new Set();\n\n/** @param {StorefrontConfig} conf */\nconst storeOf = (conf) => `${conf.domain} ${conf.apiVersion} ${conf.token}`;\n\n/** @param {number} ms */\nconst sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * What a status means, for errors Shopify sends without a message (401/403 have none).\n *\n * @param {number} status\n * @param {StorefrontConfig} conf\n */\nfunction statusText(status, conf) {\n if (status === 401 || status === 403) {\n const adminHint = conf.token.startsWith('shpat_') ? ', not an Admin API token (shpat_\u2026)' : '';\n return `Shopify rejected the Storefront token for ${conf.domain} (${status}): use the public Storefront API token (Headless channel)${adminHint}`;\n }\n if (status === 404) {\n return `Store or API version not found (404): check domain ${conf.domain} and apiVersion ${conf.apiVersion}`;\n }\n return `HTTP ${status} from ${conf.domain}`;\n}\n\n/**\n * @param {Response} res\n * @param {GraphQLError[]} errors\n * @param {StorefrontConfig} conf\n */\nfunction graphQLFailure(res, errors, conf) {\n const message = errors\n .map((error) => error.message)\n .filter(Boolean)\n .join(' | ');\n let text = message || 'Storefront API error';\n if (!res.ok) text = res.status === 401 || res.status === 403 || !message ? statusText(res.status, conf) : message;\n return new TetherError(text, { status: res.status, errors });\n}\n\n/**\n * @typedef {{ kind: 'data', data: unknown }\n * | { kind: 'retry', backoffMs: number }\n * | { kind: 'inventory-refused' }} Attempt\n */\n\n/**\n * One request. Failures that retrying can't fix throw.\n *\n * @param {StorefrontConfig} conf\n * @param {string} query\n * @param {Record<string, unknown>} variables\n * @param {boolean} canRetry False on the last attempt: a retryable failure then throws too.\n * @returns {Promise<Attempt>}\n */\nasync function attempt(conf, query, variables, canRetry) {\n let res;\n try {\n res = await (conf.fetch ?? fetch)(endpoint(conf), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-Shopify-Storefront-Access-Token': conf.token },\n body: JSON.stringify({ query, variables }),\n });\n } catch (error) {\n if (canRetry) return { kind: 'retry', backoffMs: RETRY_BACKOFF_MS };\n throw new TetherError(`Network error: ${error instanceof Error ? error.message : String(error)}`, {\n code: 'NETWORK',\n });\n }\n if (res.status === SECURITY_REJECTION) {\n throw new TetherError('Shopify security rejection (430)', { status: SECURITY_REJECTION });\n }\n if (canRetry && (res.status === 429 || res.status >= 500)) {\n return { kind: 'retry', backoffMs: RETRY_BACKOFF_MS };\n }\n\n /** @type {unknown} */\n let json;\n try {\n json = await res.json();\n } catch {\n const text = res.ok ? `Invalid response (${res.status})` : statusText(res.status, conf);\n throw new TetherError(text, { status: res.status });\n }\n // The Storefront API answers in the shape the GraphQL spec sets, or with an error page that isn't JSON.\n const { data, errors = [] } = /** @type {GraphQLResponse | null} */ (json) ?? {};\n if (errors.length) {\n if (query.includes(INVENTORY_FIELD) && errors.some((error) => error.message.includes(INVENTORY_FIELD))) {\n return { kind: 'inventory-refused' };\n }\n if (canRetry && errors.some((error) => error.extensions?.code === 'THROTTLED')) {\n return { kind: 'retry', backoffMs: THROTTLE_BACKOFF_MS };\n }\n throw graphQLFailure(res, errors, conf);\n }\n if (!res.ok) throw new TetherError(statusText(res.status, conf), { status: res.status });\n return { kind: 'data', data };\n}\n\n/**\n * One Storefront API request, for any config: the browser's shared one (`gql`) or one the server helpers build.\n * Queries carry a time bucket so Shopify's cache of an identical query text is at most `maxAge` seconds old, and\n * leave out inventory for a store whose token can't read it (`INVENTORY_FIELD`).\n *\n * @template T The shape of the query's `data`, which the caller's query text decides.\n * @param {StorefrontConfig} conf\n * @param {string} query\n * @param {Record<string, unknown>} [variables]\n * @param {RequestOptions} [options]\n * @returns {Promise<T>}\n * @throws {TetherError} `NOT_CONFIGURED` without a domain or token, `NETWORK` when the store can't be reached,\n * `HTTP_<status>` for an HTTP or GraphQL failure.\n */\nexport async function request(conf, query, variables = {}, { context = true } = {}) {\n if (!conf.domain || !conf.token) {\n throw new TetherError('Tether is not configured: domain and token are required', { code: 'NOT_CONFIGURED' });\n }\n let text = context ? withContext(query, conf) : query;\n if (conf.maxAge > 0 && !/^\\s*mutation\\b/.test(text)) {\n text += ` #${Math.floor(Date.now() / (conf.maxAge * 1000))}`;\n }\n const store = storeOf(conf);\n let retries = 0;\n for (;;) {\n const sent = storesWithoutInventory.has(store) ? text.replaceAll(INVENTORY_FIELD, '') : text;\n const outcome = await attempt(conf, sent, variables, retries < conf.retries);\n switch (outcome.kind) {\n case 'data':\n // The query text decides the shape of `data`; the caller's `T` states it.\n return /** @type {T} */ (outcome.data);\n case 'inventory-refused':\n log(`the token can't read inventory: ${INVENTORY_FIELD} is left out from now on`);\n storesWithoutInventory.add(store);\n break;\n case 'retry':\n retries += 1;\n log('retry', retries);\n await sleep(outcome.backoffMs * 2 ** retries);\n break;\n }\n }\n}\n\n/**\n * `request` with the browser's shared config.\n *\n * @template T\n * @param {string} query\n * @param {Record<string, unknown>} [variables]\n * @param {RequestOptions} [options]\n * @returns {Promise<T>}\n */\nexport const gql = (query, variables, options) => request(cfg, query, variables, options);\n\n/**\n * @template {{ userErrors?: readonly UserError[] | null }} Payload\n * @param {Payload | null | undefined} payload A mutation's payload.\n * @param {string} name The mutation, for the error message.\n * @returns {Payload}\n * @throws {TetherError} `ERROR` on an empty payload or on user errors (in `userErrors`).\n */\nexport function unwrap(payload, name) {\n if (!payload) throw new TetherError(`${name}: empty response`);\n const userErrors = payload.userErrors ?? [];\n if (userErrors.length) {\n throw new TetherError(userErrors.map((error) => error.message).join(' | '), { userErrors });\n }\n return payload;\n}\n", "/**\n * Country and language codes as Shopify's `@inContext` takes them. Every market value that reaches a query passes\n * through here: they are written into the query text, so anything else is dropped rather than sent.\n */\n\n/** @typedef {string & { readonly __brand: 'CountryCode' }} CountryCode An ISO 3166-1 alpha-2 code, upper case. */\n/** @typedef {string & { readonly __brand: 'LanguageCode' }} LanguageCode A Shopify `LanguageCode` value. */\n\nconst COUNTRY = /^[A-Z]{2}$/;\n/** Cloudflare's codes for an unknown country (XX) and Tor (T1), which a `cf-ipcountry` cookie can carry. */\nconst NOT_A_COUNTRY = new Set(['XX', 'T1']);\n/** Shopify `LanguageCode` values with a region. Every other language is its plain ISO 639 code. */\nconst REGIONAL_LANGUAGES = new Set(['PT_BR', 'PT_PT', 'ZH_CN', 'ZH_TW']);\nconst LANGUAGE = /^[A-Z]{2,3}$/;\n\n/**\n * @param {unknown} value\n * @returns {CountryCode | null} `'de'` \u2192 `'DE'`; `null` for anything that is not a country code.\n */\nexport function toCountry(value) {\n const code = (typeof value === 'string' ? value : '').trim().toUpperCase();\n if (!COUNTRY.test(code) || NOT_A_COUNTRY.has(code)) return null;\n return /** @type {CountryCode} */ (code);\n}\n\n/**\n * @param {unknown} value\n * @returns {LanguageCode | null} `'de-DE'` \u2192 `'DE'`, `'pt-BR'` \u2192 `'PT_BR'`, `'en'` \u2192 `'EN'`; `null` otherwise.\n */\nexport function toLanguage(value) {\n const raw = (typeof value === 'string' ? value : '').trim().replace('-', '_').toUpperCase();\n if (REGIONAL_LANGUAGES.has(raw)) return /** @type {LanguageCode} */ (raw);\n const primary = raw.split('_')[0] ?? '';\n return LANGUAGE.test(primary) ? /** @type {LanguageCode} */ (primary) : null;\n}\n", "/**\n * The cart, as one object: `Tether.cart`. Every change goes through one queue (fast clicks never race) and resolves\n * with the cart Shopify sent back. The state lives in `cart/store.js`, the Cart API calls in `cart/mutations.js`, the\n * drawer in `cart/drawer.js`, the document rendering in `cart/render.js` and the checkout in `cart/checkout.js`.\n */\nimport { cfg, reportError } from './config.js';\nimport { TetherError } from './client.js';\nimport { emit, toAttributes } from './dom.js';\nimport {\n fetchCart,\n isCartGone,\n mutateCart,\n removeLines,\n setLineQuantity,\n toLineInput,\n toLineUpdate,\n updateLines,\n} from './cart/mutations.js';\nimport { checkout } from './cart/checkout.js';\nimport { drawers, isOpen, openCart, closeCart, toggleCart, trapFocus } from './cart/drawer.js';\nimport {\n announce,\n cartStatus,\n commit,\n currentCart,\n currentWarnings,\n customer,\n enqueue,\n forgetSavedCart,\n keepQuietly,\n pendingQuantities,\n pendingQuantityOf,\n render,\n savedCartId,\n setFailure,\n settleLoad,\n showLastKnownCount,\n subscribe,\n} from './cart/store.js';\n/** @import { CartWarning } from './config.js' */\n/** @import { Attributes, LineSpec, CartLineInput, LinePatch } from './cart/mutations.js' */\n/** @import { ShopifyCart, ShopifyCartLine, CustomerLink, CartStatus } from './cart/store.js' */\n\nexport { trapFocus };\n\n/** @returns {readonly ShopifyCartLine[]} */\nconst currentLines = () => currentCart()?.lines.nodes ?? [];\n\n/**\n * +1 / -1 for a line. Quick clicks add up: each builds on the quantity the click before asked for, which shows at once\n * (`tether-line=\"quantity\"`, `quantityOf`) until Shopify has answered. Only the latest target is sent; the ones it\n * replaced are skipped.\n *\n * @param {string} lineId\n * @param {number} delta\n * @returns {Promise<ShopifyCart | null>}\n */\nfunction changeQuantity(lineId, delta) {\n const line = currentLines().find((candidate) => candidate.id === lineId);\n if (!line) return Promise.resolve(currentCart());\n const target = Math.max(0, pendingQuantityOf(line) + delta);\n const job = { quantity: target };\n pendingQuantities.set(lineId, job);\n announce('pending');\n const isLatest = () => pendingQuantities.get(lineId) === job;\n const sent = enqueue(async () => {\n if (!isLatest()) return currentCart();\n const now = currentLines().find((candidate) => candidate.id === lineId);\n // A + then a -: Shopify already has the quantity.\n if (now?.quantity === target) return currentCart();\n const cart = await setLineQuantity(lineId, target);\n // A newer click is on its way: keep this answer, but show totals and count once that one is in, instead of\n // stepping through every reply.\n if (!isLatest()) {\n keepQuietly(cart);\n return cart;\n }\n return commit(cart, target > 0 ? 'update' : 'remove');\n });\n return sent.finally(() => {\n if (!isLatest()) return;\n pendingQuantities.delete(lineId);\n announce('settled');\n });\n}\n\n/**\n * The codes the cart has once a change is its turn in the queue.\n *\n * @param {string[] | string | ((current: string[]) => string[])} codes A function gets the codes as they are by then.\n * @returns {string[]}\n */\nfunction discountCodesFrom(codes) {\n const current = (currentCart()?.discountCodes ?? []).map((discount) => discount.code);\n const list = typeof codes === 'function' ? codes(current) : codes;\n return (Array.isArray(list) ? list : [list]).map((code) => code.trim()).filter(Boolean);\n}\n\n/**\n * @param {Attributes} attributes\n * @returns {{ key: string, value: string }[]} The cart's attributes with `attributes` merged in; `''` removes a key.\n */\nfunction mergedAttributes(attributes) {\n const merged = new Map((currentCart()?.attributes ?? []).map((attribute) => [attribute.key, attribute.value]));\n toAttributes(attributes).forEach((attribute) => merged.set(attribute.key, attribute.value));\n return [...merged].filter(([, value]) => value !== '').map(([key, value]) => ({ key, value }));\n}\n\n/**\n * Loads the saved cart. A cart Shopify no longer has is forgotten; one it can't be asked about (the network, the\n * token) is kept, because it is probably fine.\n *\n * @returns {Promise<ShopifyCart | null>}\n */\nasync function init() {\n const id = savedCartId();\n if (!id) {\n settleLoad({ kind: 'loaded', cart: null });\n return null;\n }\n showLastKnownCount();\n try {\n const cart = await fetchCart(id);\n if (!cart) forgetSavedCart();\n settleLoad({ kind: 'loaded', cart });\n } catch (error) {\n reportError(error, 'cart load failed');\n if (isCartGone(error)) forgetSavedCart();\n settleLoad({ kind: 'failed', error });\n }\n return currentCart();\n}\n\nexport const Cart = {\n init,\n /** @returns {string | null} The saved cart's id. */\n id: savedCartId,\n\n /** @returns {CartStatus} */\n get status() {\n return cartStatus();\n },\n /** @returns {ShopifyCart | null} */\n get state() {\n return currentCart();\n },\n /** @returns {readonly ShopifyCartLine[]} */\n get lines() {\n return currentLines();\n },\n /** @returns {number} */\n get count() {\n return currentCart()?.totalQuantity ?? 0;\n },\n /** @returns {boolean} True once the saved cart, or that there is none, is known. */\n get loaded() {\n return cartStatus().kind !== 'unknown';\n },\n /** @returns {unknown} The failure of the last load or change, until a change succeeds. */\n get lastError() {\n const current = cartStatus();\n return current.kind === 'error' ? current.error : null;\n },\n set lastError(error) {\n setFailure(error);\n },\n /** @returns {readonly CartWarning[]} Shopify's notes on the last change. */\n get warnings() {\n return currentWarnings();\n },\n /** @returns {ReadonlyMap<string, { quantity: number }>} Line id \u2192 the quantity quick clicks asked for. */\n get pendingQty() {\n return pendingQuantities;\n },\n\n /** @returns {string | null} The logged-in customer's Customer Account API token (set by the account part). */\n get customerAccessToken() {\n return customer.accessToken;\n },\n set customerAccessToken(token) {\n customer.accessToken = token || null;\n },\n /** @returns {(() => Promise<string | null>) | null} The account's own checkout URL (set by the account part). */\n get beforeCheckout() {\n return customer.beforeCheckout;\n },\n set beforeCheckout(fetchUrl) {\n customer.beforeCheckout = typeof fetchUrl === 'function' ? fetchUrl : null;\n },\n /**\n * Links the cart to a logged-in customer, or unlinks it with `null`s. Carts created from now on belong to the\n * customer; `beforeCheckout` gives the checkout URL (`null` from it uses the cart's).\n *\n * @param {Partial<CustomerLink>} link Fields left out keep their value.\n */\n setCustomer(link) {\n if (link.accessToken !== undefined) customer.accessToken = link.accessToken;\n if (link.beforeCheckout !== undefined) customer.beforeCheckout = link.beforeCheckout;\n },\n\n /** Keeps a cart and shows it, as a change does; tests seed the cart with it. */\n _commit: commit,\n render,\n subscribe,\n\n /**\n * `add(variantId, 2)`, `add({ variantId, quantity, sellingPlanId, attributes })`, or `add([line, line])` for\n * bundles in one request. Creates the cart when there is none.\n *\n * @param {string | number | LineSpec | (string | number | LineSpec)[]} input\n * @param {number} [quantity]\n * @param {Omit<LineSpec, 'variantId' | 'quantity'>} [options]\n * @returns {Promise<ShopifyCart | null>}\n */\n add(input, quantity = 1, options = {}) {\n /** @type {CartLineInput[]} */\n const lines = (Array.isArray(input) ? input : [input]).map((line) => toLineInput(line, quantity, options));\n return enqueue(async () => {\n const cart = await mutateCart({\n name: 'cartLinesAdd',\n args: '$lines: [CartLineInput!]!',\n inner: 'lines: $lines',\n variables: { lines },\n createInput: { lines },\n });\n commit(cart, 'add');\n emit('added', { cart, lines });\n if (cfg.openCartOnAdd) openCart();\n return cart;\n });\n },\n\n /**\n * `updateLine(lineId, 3)` or `updateLine(lineId, { quantity, sellingPlanId, attributes })`.\n *\n * @param {string} lineId\n * @param {number | LinePatch} patch A quantity of 0 or less removes the line.\n * @returns {Promise<ShopifyCart | null>}\n */\n updateLine(lineId, patch) {\n const quantity = typeof patch === 'number' ? patch : patch.quantity;\n if (quantity !== undefined && quantity <= 0) return Cart.removeLine(lineId);\n const line = toLineUpdate(lineId, patch);\n return enqueue(async () => commit(await updateLines([line]), 'update'));\n },\n\n changeQuantity,\n\n /**\n * @param {ShopifyCartLine} line\n * @returns {number} The quantity to show: the one asked for while an update is on its way.\n */\n quantityOf: pendingQuantityOf,\n\n /**\n * @param {string | string[]} lineIds\n * @returns {Promise<ShopifyCart | null>}\n */\n removeLine(lineIds) {\n const ids = Array.isArray(lineIds) ? lineIds : [lineIds];\n return enqueue(async () => commit(await removeLines(ids), 'remove'));\n },\n\n /** @returns {Promise<ShopifyCart | null>} */\n clear() {\n const ids = currentLines().map((line) => line.id);\n if (!ids.length) return Promise.resolve(currentCart());\n return Cart.removeLine(ids);\n },\n\n /**\n * @param {string | null | undefined} note\n * @returns {Promise<ShopifyCart | null>}\n */\n setNote(note) {\n const variables = { note: note ?? '' };\n return enqueue(async () =>\n commit(\n await mutateCart({\n name: 'cartNoteUpdate',\n args: '$note: String!',\n inner: 'note: $note',\n variables,\n createInput: variables,\n }),\n 'note',\n ),\n );\n },\n\n /**\n * Cart attributes, merged with the cart's (as it is when the change runs, so quick calls don't drop each other).\n *\n * @param {Attributes} attributes The value `''` removes a key.\n * @returns {Promise<ShopifyCart | null>}\n */\n setAttributes(attributes) {\n return enqueue(async () => {\n const variables = { attributes: mergedAttributes(attributes) };\n const cart = await mutateCart({\n name: 'cartAttributesUpdate',\n args: '$attributes: [AttributeInput!]!',\n inner: 'attributes: $attributes',\n variables,\n createInput: variables,\n });\n return commit(cart, 'attributes');\n });\n },\n\n /**\n * Replaces the discount codes; `[]` removes them all.\n *\n * @param {string[] | string | ((current: string[]) => string[])} codes\n * @returns {Promise<ShopifyCart | null>}\n */\n setDiscountCodes(codes) {\n return enqueue(async () => {\n const variables = { discountCodes: discountCodesFrom(codes) };\n const cart = await mutateCart({\n name: 'cartDiscountCodesUpdate',\n args: '$discountCodes: [String!]!',\n inner: 'discountCodes: $discountCodes',\n variables,\n createInput: variables,\n });\n return commit(cart, 'discount');\n });\n },\n\n /**\n * Adds a code. A code Shopify doesn't accept is removed again, so it doesn't warn on every later change.\n *\n * @param {string} code\n * @returns {Promise<ShopifyCart | null>}\n * @throws {TetherError} `INVALID_DISCOUNT` (rejected) when Shopify doesn't accept the code.\n */\n async applyDiscount(code) {\n const cart = await Cart.setDiscountCodes((current) => [...new Set([...current, code])]);\n const wanted = code.toLowerCase();\n const applied = (cart?.discountCodes ?? []).find((discount) => discount.code.toLowerCase() === wanted);\n if (applied?.applicable) return cart;\n try {\n await Cart.removeDiscount(code);\n } catch (error) {\n reportError(error, 'removing a discount code Shopify refused');\n }\n throw new TetherError(`Discount code not valid: ${code}`, { code: 'INVALID_DISCOUNT' });\n },\n\n /**\n * @param {string} code\n * @returns {Promise<ShopifyCart | null>}\n */\n removeDiscount(code) {\n const unwanted = code.toLowerCase();\n return Cart.setDiscountCodes((current) => current.filter((existing) => existing.toLowerCase() !== unwanted));\n },\n\n /**\n * Sets who is buying; a country changes the cart's currency and prices to that market's.\n *\n * @param {{ countryCode?: string, email?: string, phone?: string, customerAccessToken?: string | null }} buyerIdentity\n * @param {{ create?: boolean }} [options] `create: false` forgets an expired cart instead of creating an empty one.\n * @returns {Promise<ShopifyCart | null>}\n */\n setBuyerIdentity(buyerIdentity, { create = true } = {}) {\n return enqueue(async () => {\n const cart = await mutateCart({\n name: 'cartBuyerIdentityUpdate',\n args: '$buyerIdentity: CartBuyerIdentityInput!',\n inner: 'buyerIdentity: $buyerIdentity',\n variables: { buyerIdentity },\n createInput: create ? { buyerIdentity } : null,\n }).catch((/** @type {unknown} */ error) => {\n // mutateCart has forgotten the cart Shopify no longer has; without `create` that leaves no cart.\n if (create || !isCartGone(error)) throw error;\n return null;\n });\n return commit(cart, 'buyer-identity');\n });\n },\n\n checkout,\n\n drawers,\n isOpen,\n open: openCart,\n close: closeCart,\n toggle: toggleCart,\n};\n", "/**\n * The browser modules' DOM toolkit: what Shopify values look like on the page (money, dates, text, images, lists)\n * and how elements show, hide and report layout changes. Attribute names go through `attr()` so the prefix is\n * configurable. The optional parts import all of it from here (`window.Tether.__core['dom.js']`).\n */\nimport { cfg, reportError, warn } from './config.js';\nimport { attr, emit, get } from './markup.js';\nimport { storeHtmlFragment } from './store-html.js';\nimport { formatMoney as formatMoneyIn, productUrl as productUrlFor } from './shopify-values.js';\n/** @import { Money } from './shopify-values.js' */\n\nexport { attr, sel, get, has, qsa, scoped, emit } from './markup.js';\nexport { imageUrl, cdnUrl, sameImage, setImage } from './images.js';\nexport { hasTemplate, repeat, repeatKeyed } from './repeaters.js';\n\n/**\n * State Tether keeps on elements, as `data-tether-*` attributes whatever the prefix: sites style and test against\n * these names, so they stay fixed where the `tether-*` markup attributes follow `prefix`.\n */\nconst SEEN = 'data-tether-seen';\nconst SHOWN = 'data-tether-shown';\nconst PREVIOUS_DISPLAY = 'data-tether-prev-display';\n\n/** Async renders change the page height in bursts; one notification per burst. */\nconst LAYOUT_DEBOUNCE_MS = 120;\n\n/**\n * The product page of a product (`productPath`).\n *\n * @param {string | null | undefined} handle\n * @param {string | null} [id]\n */\nexport function productUrl(handle, id) {\n return productUrlFor(cfg.productPath || '/product', handle, id);\n}\n\n/**\n * `Intl` throws a RangeError for a locale or currency it doesn't know; the caller then shows a plain fallback.\n *\n * @template T\n * @param {() => T} format\n * @param {T} fallback\n * @returns {T}\n */\nfunction formatOr(format, fallback) {\n try {\n return format();\n } catch (error) {\n if (error instanceof RangeError) return fallback;\n throw error;\n }\n}\n\n/**\n * `30` \u2192 `30%` (en, nl) or `30 %` (de, fr), in the configured locale.\n *\n * @param {number | null | undefined} percentage\n * @param {string | undefined} [locale]\n * @returns {string} `''` for no or a zero percentage.\n */\nexport function formatPercent(percentage, locale = cfg.locale) {\n if (!percentage) return '';\n const format = () =>\n new Intl.NumberFormat(locale || undefined, { style: 'percent', maximumFractionDigits: 0 }).format(percentage / 100);\n return formatOr(format, `${percentage}%`);\n}\n\n/**\n * Money in the configured locale, through the site's `formatMoney` when it has one.\n *\n * @param {Money | null | undefined} money\n */\nexport function formatMoney(money) {\n if (!money) return '';\n if (cfg.formatMoney) return cfg.formatMoney(money, cfg.locale);\n return formatMoneyIn(money, cfg.locale);\n}\n\n/**\n * @param {string | null | undefined} iso\n * @returns {string} The date in the configured locale, `''` without one.\n */\nexport function formatDate(iso) {\n if (!iso) return '';\n return formatOr(() => new Date(iso).toLocaleDateString(cfg.locale || undefined), '');\n}\n\n/**\n * Writes HTML from the Shopify admin (product and collection descriptions) into `el`, with script removed\n * (`store-html.js`). Everything else from Shopify is written as text (`setText`).\n *\n * @param {Element} el\n * @param {string | null | undefined} html\n */\nexport function setStoreHtml(el, html) {\n el.replaceChildren(storeHtmlFragment(html, el.ownerDocument));\n}\n\n/**\n * @param {Element} el\n * @returns {el is HTMLInputElement | HTMLTextAreaElement}\n */\nconst isTextField = (el) => el.tagName === 'INPUT' || el.tagName === 'TEXTAREA';\n\n/**\n * @param {Element} el\n * @returns {el is HTMLInputElement}\n */\nconst isInput = (el) => el.tagName === 'INPUT';\n\n/**\n * Sets the text of `el`, or its value when it is a form field.\n *\n * @param {Element} el\n * @param {string | number | boolean | null | undefined} value `null` and `undefined` clear it.\n */\nexport function setText(el, value) {\n const text = value == null ? '' : String(value);\n if (isTextField(el)) el.value = text;\n else el.textContent = text;\n}\n\n/** @param {Element} el */\nconst readText = (el) => (isTextField(el) ? el.value : el.textContent);\n\n/**\n * `setText` that hands a change after the first render to `onValueChange`, for scramble and roll effects.\n *\n * @param {HTMLElement} el\n * @param {string | number | boolean | null | undefined} value\n */\nexport function setTextTracked(el, value) {\n const before = readText(el);\n setText(el, value);\n if (before !== readText(el) && el.hasAttribute(SEEN) && cfg.onValueChange) {\n try {\n cfg.onValueChange(el, before);\n } catch (error) {\n reportError(error, 'onValueChange');\n }\n }\n el.setAttribute(SEEN, '1');\n}\n\n/**\n * Shows an element hidden before the script ran (a class, an inline `display: none`, a `hidden` attribute), as\n * `block` or the value of `tether-display`.\n *\n * @param {HTMLElement} el\n */\nfunction reveal(el) {\n if (el.hasAttribute(SHOWN)) return;\n el.setAttribute(SHOWN, '');\n el.removeAttribute('hidden');\n const previous = el.getAttribute(PREVIOUS_DISPLAY);\n if (previous !== null) {\n el.style.display = previous;\n el.removeAttribute(PREVIOUS_DISPLAY);\n } else if (el.style.display === 'none') {\n el.style.display = '';\n }\n if (typeof getComputedStyle === 'function' && getComputedStyle(el).display === 'none') {\n el.style.display = el.getAttribute(attr('display')) || 'block';\n }\n}\n\n/**\n * Shows or hides `el`, restoring its own display value when shown again.\n *\n * @param {HTMLElement} el\n * @param {boolean} visible\n */\nexport function show(el, visible) {\n if (visible) {\n reveal(el);\n return;\n }\n el.removeAttribute(SHOWN);\n // The display value to restore is a real one, never 'none'.\n if (!el.hasAttribute(PREVIOUS_DISPLAY) && el.style.display !== 'none') {\n el.setAttribute(PREVIOUS_DISPLAY, el.style.display);\n }\n el.style.display = 'none';\n}\n\n/**\n * Marks an option button or input as chosen: `is-selected`, `aria-pressed`, and its own or inner radio/checkbox.\n *\n * @param {Element} el\n * @param {boolean} selected\n */\nexport function setSelected(el, selected) {\n el.classList.toggle('is-selected', selected);\n el.setAttribute('aria-pressed', selected ? 'true' : 'false');\n if (isInput(el) && (el.type === 'radio' || el.type === 'checkbox')) el.checked = selected;\n const input = el.querySelector('input[type=\"radio\"],input[type=\"checkbox\"]');\n if (input && isInput(input)) input.checked = selected;\n}\n\n/** @type {ReturnType<typeof setTimeout> | undefined} */\nlet layoutTimer;\n\n/**\n * Async renders change the page height after the site's page-transition hooks ran. After a burst of them this calls\n * `onLayoutChange` (else refreshes ScrollTrigger) and emits `tether:layout-changed`.\n *\n * @param {string} reason\n */\nexport function notifyLayoutChanged(reason) {\n clearTimeout(layoutTimer);\n layoutTimer = setTimeout(() => {\n // GSAP's ScrollTrigger, when the site has it, measures positions that a height change makes stale.\n const { ScrollTrigger } = /** @type {Window & { ScrollTrigger?: { refresh?: () => void } }} */ (window);\n if (cfg.onLayoutChange) cfg.onLayoutChange(reason);\n else ScrollTrigger?.refresh?.();\n emit('layout-changed', { reason });\n }, LAYOUT_DEBOUNCE_MS);\n}\n\n/**\n * Notifies a layout change (`<reason>:images`) once every image in `root` that is still loading has loaded or failed.\n *\n * @param {ParentNode} root\n * @param {string} reason\n */\nexport function watchImages(root, reason) {\n const loading = [...root.querySelectorAll('img')].filter((img) => !img.complete);\n let left = loading.length;\n const done = () => {\n left -= 1;\n if (left === 0) notifyLayoutChanged(`${reason}:images`);\n };\n loading.forEach((img) => {\n img.addEventListener('load', done, { once: true });\n img.addEventListener('error', done, { once: true });\n });\n}\n\n/**\n * Runs `task` with `aria-busy` on `el`; does nothing while `el` is already busy.\n *\n * @template T\n * @param {Element} el\n * @param {() => T | Promise<T>} task\n * @returns {Promise<T | undefined>} The task's result, `undefined` when it didn't run.\n */\nexport function busy(el, task) {\n if (el.getAttribute('aria-busy') === 'true') return Promise.resolve(undefined);\n el.setAttribute('aria-busy', 'true');\n return Promise.resolve()\n .then(task)\n .finally(() => {\n el.removeAttribute('aria-busy');\n });\n}\n\n/**\n * @param {Element | null | undefined} el\n * @param {string} name\n * @returns {unknown} The attribute's JSON, `null` when it is missing or not JSON (with a warning).\n */\nexport function parseJSONAttr(el, name) {\n const raw = el ? get(el, name) : null;\n if (!raw) return null;\n try {\n return /** @type {unknown} */ (JSON.parse(raw));\n } catch {\n warn(`invalid JSON in ${attr(name)}`, el);\n return null;\n }\n}\n\n/** @typedef {string | number | boolean | null | undefined} AttributeValue */\n\n/**\n * `{ a: 1 }` or `[{ key, value }]` \u2192 `[{ key, value }]` as Shopify wants cart and line attributes.\n *\n * @param {Record<string, AttributeValue> | { key: string | number, value?: AttributeValue }[] | null | undefined} attributes\n * @returns {{ key: string, value: string }[]}\n */\nexport function toAttributes(attributes) {\n if (!attributes) return [];\n if (Array.isArray(attributes)) {\n return attributes.map((attribute) => ({ key: String(attribute.key), value: String(attribute.value ?? '') }));\n }\n return Object.entries(attributes).map(([key, value]) => ({ key, value: String(value ?? '') }));\n}\n", "/**\n * How Tether finds its markup: attribute names carry the configured prefix (`tether-product`, or `wfs-product` with\n * `prefix: 'wfs'`), and so do the selectors and the DOM events built from them.\n */\nimport { cfg } from './config.js';\n\n/**\n * @param {string} name\n * @returns {string} The prefixed attribute name: `product` \u2192 `tether-product`.\n */\nexport const attr = (name) => `${cfg.prefix}-${name}`;\n\n/**\n * @param {string} name\n * @param {string} [value]\n * @returns {string} A selector for the attribute, with that exact value when given.\n */\nexport const sel = (name, value) => (value === undefined ? `[${attr(name)}]` : `[${attr(name)}=\"${value}\"]`);\n\n/**\n * @param {Element} el\n * @param {string} name\n */\nexport const get = (el, name) => el.getAttribute(attr(name));\n\n/**\n * @param {Element} el\n * @param {string} name\n */\nexport const has = (el, name) => el.hasAttribute(attr(name));\n\n/**\n * Tether's attributes go on HTML elements, so matches are typed as such. An SVG element that carries one still has\n * the `style`, `dataset` and attribute methods Tether uses.\n *\n * @param {ParentNode | null | undefined} root\n * @param {string} selector\n * @returns {HTMLElement[]} The matches in `root`, none without a root.\n */\nexport function qsa(root, selector) {\n if (!root) return [];\n return [.../** @type {NodeListOf<HTMLElement>} */ (root.querySelectorAll(selector))];\n}\n\n/**\n * @param {Element | null | undefined} root\n * @param {string} selector\n * @param {string} scopeSelector\n * @returns {HTMLElement[]} Matches in `root` whose nearest `scopeSelector` ancestor is `root` itself, not a nested\n * scope.\n */\nexport const scoped = (root, selector, scopeSelector) =>\n qsa(root, selector).filter((el) => el.closest(scopeSelector) === root);\n\n/**\n * Dispatches the bubbling event `<prefix>:<name>`.\n *\n * @param {string} name\n * @param {unknown} [detail]\n * @param {EventTarget} [target]\n */\nexport function emit(name, detail, target = document) {\n target.dispatchEvent(new CustomEvent(`${cfg.prefix}:${name}`, { detail, bubbles: true }));\n}\n", "/**\n * HTML written in the Shopify admin (product and collection descriptions), made safe to insert into the site. Store\n * staff and apps that can edit products are not trusted to run script on the storefront, where customer sessions\n * live: script, event handlers and script URLs are removed, and everything that only shows content (markup, styles,\n * images, links, video embeds) is kept as written.\n */\n\n/** Elements that run code or change how the page loads. Removed with their content. */\nconst BLOCKED_ELEMENTS = new Set([\n 'SCRIPT',\n 'OBJECT',\n 'EMBED',\n 'BASE',\n 'META',\n 'LINK',\n 'NOSCRIPT',\n 'TEMPLATE',\n // SVG animation can set an attribute such as href to a script URL after the attributes were checked.\n 'ANIMATE',\n 'SET',\n]);\n/** Attributes whose value is fetched or navigated to. */\nconst URL_ATTRIBUTES = new Set(['href', 'src', 'action', 'formaction', 'xlink:href', 'poster', 'data', 'background']);\n/** Schemes that run code when navigated to. */\nconst SCRIPT_URL = /^\\s*(javascript|vbscript|data):/i;\n/** `data:` stays allowed for images, which only decode pixels. */\nconst DATA_IMAGE = /^\\s*data:image\\/(png|gif|jpeg|webp|avif);/i;\n\n/** Browsers ignore control characters and spaces in a URL's scheme (`java\tscript:`), so the check does too. */\n// eslint-disable-next-line no-control-regex -- control characters are exactly what browsers skip in a scheme\nconst IGNORED_IN_SCHEME = /[\u0000- ]/g;\n\n/** @param {Element} element @param {Attr} attribute */\nfunction isUnsafeAttribute(element, attribute) {\n const name = attribute.name.toLowerCase();\n if (name.startsWith('on') || name === 'srcdoc') return true;\n const url = attribute.value.replace(IGNORED_IN_SCHEME, '');\n if (!URL_ATTRIBUTES.has(name) || !SCRIPT_URL.test(url)) return false;\n return !(element.tagName === 'IMG' && name === 'src' && DATA_IMAGE.test(url));\n}\n\n/** @param {ParentNode} root */\nfunction clean(root) {\n for (const element of [...root.querySelectorAll('*')]) {\n if (BLOCKED_ELEMENTS.has(element.tagName.toUpperCase())) {\n element.remove();\n continue;\n }\n for (const attribute of [...element.attributes]) {\n if (isUnsafeAttribute(element, attribute)) element.removeAttribute(attribute.name);\n }\n }\n}\n\n/**\n * Store HTML as a fragment, with script removed.\n *\n * @param {string | null | undefined} html\n * @param {Document} [document] The document the fragment is for.\n * @returns {DocumentFragment}\n */\nexport function storeHtmlFragment(html, document = globalThis.document) {\n const template = document.createElement('template');\n // A <template>'s content is parsed inert: nothing in it loads or runs before it is cleaned.\n // eslint-disable-next-line no-restricted-syntax -- parsing into an inert template is the sanctioned way in\n template.innerHTML = html ?? '';\n clean(template.content);\n return template.content;\n}\n", "/**\n * Conversions of Shopify values that the browser script and the server helpers (`src/server.js`, `src/astro.js`)\n * share, so a server-rendered page and the script that takes it over agree. Pure: no config, no DOM.\n */\n\n/** @typedef {{ amount: string, currencyCode: string }} Money A Storefront API `MoneyV2`. */\n\n/** The `.env` names a store's domain and public Storefront token are read from, first match wins. */\nexport const STORE_ENV_NAMES = {\n domain: ['PUBLIC_SHOPIFY_DOMAIN', 'PUBLIC_SHOPIFY_STORE_DOMAIN', 'SHOPIFY_DOMAIN'],\n token: ['PUBLIC_SHOPIFY_STOREFRONT_TOKEN', 'PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN', 'SHOPIFY_STOREFRONT_TOKEN'],\n};\n\n/**\n * True for an absolute https URL. Links and redirects that come from Shopify (checkout, status pages,\n * tracking) are only used when this holds.\n *\n * @param {unknown} url\n */\nexport function isHttpsUrl(url) {\n if (typeof url !== 'string') return false;\n try {\n return new URL(url).protocol === 'https:';\n } catch {\n return false;\n }\n}\n\n/**\n * True for a token Shopify issues as a secret (`shpat_` Admin, `shpss_` shared secret, `shpca_` client credentials,\n * `shppa_` private app, `shpua_` user). The public Storefront token has no such prefix. A secret token must never\n * reach a page.\n *\n * @param {string} token\n */\nexport function isSecretShopifyToken(token) {\n return /^shp[a-z]{2}_/.test(token.trim());\n}\n\n/**\n * Money as text in `locale`, e.g. `{amount:'30.0',currencyCode:'EUR'}` in `nl-NL` \u2192 `\u20AC 30,00`.\n *\n * @param {Money | null | undefined} money\n * @param {string | undefined} locale An `Intl` locale; the runtime's own when absent.\n * @returns {string} `''` without money or with an amount that isn't a number.\n */\nexport function formatMoney(money, locale) {\n if (!money) return '';\n const amount = parseFloat(money.amount);\n if (Number.isNaN(amount)) return '';\n try {\n return new Intl.NumberFormat(locale || undefined, { style: 'currency', currency: money.currencyCode }).format(\n amount,\n );\n } catch {\n // A currency code Intl doesn't know.\n return `${money.currencyCode} ${amount.toFixed(2)}`;\n }\n}\n\n/**\n * A product page's path. `productPath` is a folder (`/product` \u2192 `/product/<handle>`) or a template with `{handle}`\n * and `{id}` (the numeric product id), e.g. `/product?handle={handle}`.\n *\n * @param {string} productPath\n * @param {string | null | undefined} handle\n * @param {string | null | undefined} [id] A product gid or numeric id.\n */\nexport function productUrl(productPath, handle, id) {\n if (!/\\{(handle|id)\\}/.test(productPath)) return `${productPath.replace(/\\/$/, '')}/${handle ?? String(handle)}`;\n const numericId = id ? (id.split('/').pop() ?? '') : '';\n return productPath\n .replace(/\\{handle\\}/g, encodeURIComponent(handle ?? ''))\n .replace(/\\{id\\}/g, encodeURIComponent(numericId));\n}\n\n/**\n * The key Tether loads a product by: a handle, or a product gid.\n *\n * @param {string | number | null | undefined} raw A handle, a numeric id, a gid or a product URL (`\u2026/products/<handle>`).\n * @returns {string | null}\n */\nexport function productKey(raw) {\n const value = String(raw ?? '').trim();\n if (!value) return null;\n if (value.startsWith('gid://')) return value;\n if (/^\\d+$/.test(value)) return `gid://shopify/Product/${value}`;\n return /\\/products\\/([^/?#]+)/.exec(value)?.[1] ?? value;\n}\n", "/**\n * Shopify images on the page: sized through the CDN's URL parameters, written to an `<img>` or as a CSS background,\n * and never downloaded twice when the server already rendered the same image.\n */\nimport { attr } from './markup.js';\n\n/**\n * @typedef {object} ImageSize Shopify CDN parameters.\n * @property {string | number | null} [width]\n * @property {string | number | null} [height]\n * @property {string | null} [crop] `center`, `top`, `bottom`, `left` or `right`; only applies with a width or height.\n */\n\n/**\n * Shopify CDN image at a size: `imageUrl(url, { width: 800 })`. Use the same width as the element's max-width\n * attribute, so the browser script keeps the image instead of loading it again.\n *\n * @template {string | null | undefined} Url\n * @param {Url} url\n * @param {ImageSize} [size]\n * @returns {Url} The sized URL; `url` itself when it is empty or not absolute.\n */\nexport function imageUrl(url, { width, height, crop } = {}) {\n if (!url) return url;\n let parsed;\n try {\n parsed = new URL(url);\n } catch (error) {\n // A relative or malformed URL has no CDN parameters to set: it is used as written.\n if (error instanceof TypeError) return url;\n throw error;\n }\n if (width) parsed.searchParams.set('width', String(width));\n if (height) parsed.searchParams.set('height', String(height));\n if (crop) parsed.searchParams.set('crop', crop);\n return /** @type {Url} */ (parsed.toString());\n}\n\n/**\n * @param {Element} el\n * @param {string} name\n * @returns {string | null} `name` as Webflow's custom attribute, or in valid HTML as `<prefix>-name` / `data-name`.\n */\nfunction sizeAttribute(el, name) {\n return el.getAttribute(name) ?? el.getAttribute(attr(name)) ?? el.getAttribute(`data-${name}`);\n}\n\n/**\n * @template {string | null | undefined} Url\n * @param {Url} url\n * @param {Element | null | undefined} el The element whose max-width / max-height / crop attributes size the image.\n * @returns {Url}\n */\nexport function cdnUrl(url, el) {\n if (!url || !el) return url;\n const width = sizeAttribute(el, 'max-width');\n const height = sizeAttribute(el, 'max-height');\n return imageUrl(url, { width, height, crop: width || height ? sizeAttribute(el, 'crop') : null });\n}\n\n/**\n * @param {string | null | undefined} a\n * @param {string | null | undefined} b\n * @returns {boolean} True for the same image at any size parameters: the server-rendered one is kept.\n */\nexport const sameImage = (a, b) => Boolean(a && b) && a?.split('?')[0] === b?.split('?')[0];\n\n/**\n * A CSS `url()` for an image URL from Shopify. Characters that would end the string are escaped, so the URL can't\n * add declarations; only http(s), relative and data:image URLs are used.\n *\n * @param {string} url\n */\nfunction cssUrl(url) {\n const hasScheme = /^\\s*[a-z][a-z0-9+.-]*:/i.test(url);\n if (hasScheme && !/^\\s*(https?:|data:image\\/)/i.test(url)) return 'none';\n const escaped = url.replace(/[\"\\\\\\n\\r\\f]/g, (char) => `\\\\${char.charCodeAt(0).toString(16)} `);\n return `url(\"${escaped}\")`;\n}\n\n/**\n * Shows `url` in `el`: as the `src` of an `<img>` (lazy unless it says otherwise), else as its background image.\n *\n * @param {HTMLElement} el\n * @param {string | null | undefined} url\n * @param {string | null} [alt]\n */\nexport function setImage(el, url, alt) {\n if (!url) return;\n const src = cdnUrl(url, el);\n if (el.tagName !== 'IMG') {\n el.style.backgroundImage = cssUrl(src);\n return;\n }\n if (sameImage(el.getAttribute('src'), src)) {\n if (alt != null && !el.getAttribute('alt')) el.setAttribute('alt', alt);\n return;\n }\n el.removeAttribute('srcset');\n el.removeAttribute('sizes');\n el.setAttribute('src', src);\n if (alt != null) el.setAttribute('alt', alt);\n if (!el.getAttribute('loading')) el.setAttribute('loading', 'lazy');\n}\n", "/**\n * Lists rendered from a template: a repeater's first child in the designer is the template, and every item gets a\n * copy of it. The other children are placeholder content and are removed.\n */\nimport { cfg, reportError, warn } from './config.js';\n\n/** @type {WeakMap<Element, HTMLElement | null>} Each repeater's template, captured on first render. */\nconst templates = new WeakMap();\n\n/**\n * @param {Element} container\n * @returns {boolean} True once the repeater's template has been captured (it may be empty after that).\n */\nexport const hasTemplate = (container) => Boolean(templates.get(container));\n\n/**\n * A deep copy of a template. `cloneNode` is typed as returning a `Node`; a copy of an element is an element of the\n * same kind.\n *\n * @param {HTMLElement} template\n */\nconst copyOf = (template) => /** @type {HTMLElement} */ (template.cloneNode(true));\n\n/** @param {Element} container */\nfunction templateOf(container) {\n const known = templates.get(container);\n if (known !== undefined) return known;\n const first = container.firstElementChild;\n // Repeaters are HTML lists in the designer; their first child is an HTML element.\n const template = first ? copyOf(/** @type {HTMLElement} */ (first)) : null;\n templates.set(container, template);\n container.replaceChildren();\n return template;\n}\n\n/**\n * Rebuilds the list on every render. Fine for images, tags, options.\n *\n * @template Item\n * @param {Element} container\n * @param {readonly Item[]} items\n * @param {(node: HTMLElement, item: Item, index: number) => void} render\n */\nexport function repeat(container, items, render) {\n const template = templateOf(container);\n if (!template) {\n if (items.length) warn('repeater without a template child', container);\n return;\n }\n container.replaceChildren();\n items.forEach((item, index) => {\n const node = copyOf(template);\n render(node, item, index);\n container.appendChild(node);\n });\n}\n\n/**\n * @typedef {object} KeyedHooks\n * @property {((node: HTMLElement) => void) | null} [onEnter] Runs on a node inserted for a new item.\n * @property {((node: HTMLElement, done: () => void) => void) | null} [onLeave] Runs on a node whose item is gone;\n * `done()` removes it.\n */\n\n/**\n * @param {HTMLElement} node\n * @param {KeyedHooks['onLeave']} onLeave\n */\nfunction leave(node, onLeave) {\n const done = () => {\n node.remove();\n };\n if (!onLeave) {\n done();\n return;\n }\n try {\n onLeave(node, done);\n } catch (error) {\n reportError(error, 'repeater onLeave');\n done();\n }\n}\n\n/**\n * Inserts the nodes of new items next to the item before them, leaving the existing nodes where they are.\n *\n * @param {Element} container\n * @param {HTMLElement[]} wanted Every item's node, in order.\n * @param {Set<HTMLElement>} fresh The nodes not yet in the container.\n * @param {KeyedHooks['onEnter']} onEnter\n */\nfunction insertFresh(container, wanted, fresh, onEnter) {\n wanted.forEach((node, index) => {\n if (!fresh.has(node)) return;\n const previous = wanted[index - 1];\n if (previous?.parentNode === container) previous.after(node);\n else container.prepend(node);\n if (!onEnter) return;\n try {\n onEnter(node);\n } catch (error) {\n reportError(error, 'repeater onEnter');\n }\n });\n}\n\n/**\n * Keyed repeater: keeps existing nodes, inserts new ones, removes old ones. Used for cart lines, so values can\n * animate and lines can slide in and out.\n *\n * @template Item\n * @param {Element} container\n * @param {readonly Item[]} items\n * @param {(item: Item, index: number) => string | number} keyOf\n * @param {(node: HTMLElement, item: Item, index: number, isNew: boolean) => void} render\n * @param {KeyedHooks} [hooks]\n */\nexport function repeatKeyed(container, items, keyOf, render, { onEnter, onLeave } = {}) {\n const template = templateOf(container);\n if (!template) {\n warn('repeater without a template child', container);\n return;\n }\n\n const keyAttribute = `data-${cfg.prefix}-key`;\n const leavingAttribute = `data-${cfg.prefix}-leaving`;\n const live = () =>\n [.../** @type {HTMLCollectionOf<HTMLElement>} */ (container.children)].filter(\n (node) => node.hasAttribute(keyAttribute) && !node.hasAttribute(leavingAttribute),\n );\n\n const existing = new Map(live().map((node) => [node.getAttribute(keyAttribute), node]));\n /** @type {HTMLElement[]} */\n const wanted = [];\n /** @type {Set<HTMLElement>} */\n const fresh = new Set();\n\n items.forEach((item, index) => {\n const key = String(keyOf(item, index));\n let node = existing.get(key);\n if (node) existing.delete(key);\n else {\n node = copyOf(template);\n node.setAttribute(keyAttribute, key);\n fresh.add(node);\n }\n render(node, item, index, fresh.has(node));\n wanted.push(node);\n });\n\n const staying = wanted.filter((node) => !fresh.has(node));\n const current = live().filter((node) => staying.includes(node));\n const inOrder = current.length === staying.length && current.every((node, index) => node === staying[index]);\n\n if (!inOrder) {\n existing.forEach((node) => {\n node.remove();\n });\n wanted.forEach((node) => container.appendChild(node));\n return;\n }\n\n insertFresh(container, wanted, fresh, onEnter);\n\n existing.forEach((node) => {\n node.setAttribute(leavingAttribute, '');\n node.removeAttribute(keyAttribute);\n node.style.pointerEvents = 'none';\n node.inert = true;\n leave(node, onLeave);\n });\n}\n", "/**\n * The GraphQL fragments of what Tether renders. They are built at call time because the list sizes and metafields come\n * from the config; the browser passes its validated `cfg`, the server helpers their own. Operations put these after\n * the operation, where `withContext` expects them.\n */\nimport { cfg, toMetafieldIdentifier } from './config.js';\n/** @import { TetherConfig, MetafieldIdentifier } from './config.js' */\n/** @import { Money } from './shopify-values.js' */\n\n/** @typedef {{ url: string, altText: string | null, width: number | null, height: number | null }} Image */\n/**\n * @typedef {{ __typename: 'SellingPlanPercentagePriceAdjustment', adjustmentPercentage: number }\n * | { __typename: 'SellingPlanFixedAmountPriceAdjustment', adjustmentAmount: Money }\n * | { __typename: 'SellingPlanFixedPriceAdjustment', price: Money }} SellingPlanAdjustmentValue\n */\n/**\n * @typedef {object} SellingPlan\n * @property {string} id\n * @property {string} name\n * @property {string | null} description\n * @property {boolean} recurringDeliveries\n * @property {{ name: string, value: string }[]} options\n * @property {{ orderCount: number | null, adjustmentValue: SellingPlanAdjustmentValue }[]} priceAdjustments\n */\n/**\n * @typedef {object} SellingPlanGroup\n * @property {string} name\n * @property {string | null} appName\n * @property {{ name: string, values: string[] }[]} options\n * @property {{ nodes: SellingPlan[] }} sellingPlans\n */\n/**\n * @typedef {object} SellingPlanAllocation A variant's price on one plan.\n * @property {{ id: string }} sellingPlan\n * @property {Money} checkoutChargeAmount What the customer pays at checkout (more for a prepaid plan).\n * @property {Money} remainingBalanceChargeAmount\n * @property {{ price: Money, compareAtPrice: Money, perDeliveryPrice: Money, unitPrice: Money | null }[]}\n * priceAdjustments\n */\n/**\n * @typedef {object} ProductVariant\n * @property {string} id\n * @property {string} title\n * @property {boolean} availableForSale\n * @property {boolean} currentlyNotInStock\n * @property {number | null} [quantityAvailable] Absent when the store's token can't read inventory.\n * @property {string | null} sku\n * @property {string | null} barcode\n * @property {{ name: string, value: string }[]} selectedOptions\n * @property {Image | null} image\n * @property {Money} price\n * @property {Money | null} compareAtPrice\n * @property {Money | null} unitPrice\n * @property {{ nodes: SellingPlanAllocation[] }} sellingPlanAllocations\n */\n/**\n * @typedef {object} Metafield\n * @property {string} namespace\n * @property {string} key\n * @property {string} type\n * @property {string} value\n * @property {{ image?: Image } | null} reference A file reference's image.\n */\n/**\n * @typedef {object} Product The fields of `fragment TetherProduct`.\n * @property {string} id\n * @property {string} handle\n * @property {string} title\n * @property {string} description\n * @property {string} descriptionHtml\n * @property {string} productType\n * @property {string} vendor\n * @property {string[]} tags\n * @property {boolean} availableForSale\n * @property {string | null} publishedAt\n * @property {string | null} onlineStoreUrl\n * @property {boolean} requiresSellingPlan\n * @property {{ title: string | null, description: string | null }} seo\n * @property {Image | null} featuredImage\n * @property {{ nodes: Image[] }} images\n * @property {{ name: string, optionValues: { name: string, swatch: unknown }[] }[]} options\n * @property {{ minVariantPrice: Money, maxVariantPrice: Money }} priceRange\n * @property {{ minVariantPrice: Money, maxVariantPrice: Money }} compareAtPriceRange\n * @property {(Metafield | null)[]} [metafields] Present when metafields are configured; `null` for one that isn't set.\n * @property {{ nodes: SellingPlanGroup[] }} sellingPlanGroups\n * @property {{ nodes: ProductVariant[] }} variants\n */\n\n/**\n * @typedef {Pick<TetherConfig, 'imagesFirst' | 'variantsFirst' | 'sellingPlanGroupsFirst' | 'sellingPlansFirst'\n * | 'metafields'>} ProductFragmentConfig\n */\n\nconst MONEY = 'amount currencyCode';\nconst IMAGE = 'url altText width height';\n\n/**\n * The `metafields(identifiers:)` field. A fragment can't declare variables, so the identifiers are written into the\n * text: only valid ones (`toMetafieldIdentifier`), each quoted as a string literal.\n *\n * @param {ProductFragmentConfig['metafields']} metafields\n */\nfunction metafieldsField(metafields) {\n /** @type {MetafieldIdentifier[]} */\n const identifiers = [];\n for (const ref of metafields) {\n const identifier = toMetafieldIdentifier(ref);\n if (identifier) identifiers.push(identifier);\n }\n if (!identifiers.length) return '';\n const list = identifiers\n .map(({ namespace, key }) => `{namespace: ${JSON.stringify(namespace)}, key: ${JSON.stringify(key)}}`)\n .join(', ');\n return `metafields(identifiers:[${list}]){namespace key type value reference{... on MediaImage{image{${IMAGE}}}}}`;\n}\n\nconst SELLING_PLAN_FIELDS = ` id name description recurringDeliveries options{name value}priceAdjustments{orderCount adjustmentValue{__typename ... on SellingPlanPercentagePriceAdjustment{adjustmentPercentage}... on SellingPlanFixedAmountPriceAdjustment{adjustmentAmount{${MONEY}}}... on SellingPlanFixedPriceAdjustment{price{${MONEY}}}}}`;\n\nconst ALLOCATION_FIELDS = ` sellingPlan{id}checkoutChargeAmount{${MONEY}}remainingBalanceChargeAmount{${MONEY}}priceAdjustments{price{${MONEY}}compareAtPrice{${MONEY}}perDeliveryPrice{${MONEY}}unitPrice{${MONEY}}}`;\n\n/**\n * @param {ProductFragmentConfig} [o] The list sizes and metafields.\n * @returns {string} `fragment TetherProduct on Product`.\n */\nexport function productFragment(o = cfg) {\n return ` fragment TetherProduct on Product{id handle title description descriptionHtml productType vendor tags availableForSale publishedAt onlineStoreUrl requiresSellingPlan seo{title description}featuredImage{${IMAGE}}images(first:${o.imagesFirst}){nodes{${IMAGE}}}options{name optionValues{name swatch{color image{previewImage{${IMAGE}}}}}}priceRange{minVariantPrice{${MONEY}}maxVariantPrice{${MONEY}}}compareAtPriceRange{minVariantPrice{${MONEY}}maxVariantPrice{${MONEY}}}${metafieldsField(o.metafields)} sellingPlanGroups(first:${o.sellingPlanGroupsFirst}){nodes{name appName options{name values}sellingPlans(first:${o.sellingPlansFirst}){nodes{${SELLING_PLAN_FIELDS}}}}}variants(first:${o.variantsFirst}){nodes{id title availableForSale currentlyNotInStock quantityAvailable sku barcode selectedOptions{name value}image{${IMAGE}}price{${MONEY}}compareAtPrice{${MONEY}}unitPrice{${MONEY}}sellingPlanAllocations(first:${o.sellingPlansFirst}){nodes{${ALLOCATION_FIELDS}}}}}}`;\n}\n\n/** @returns {string} `fragment TetherCart on Cart`. */\nexport function cartFragment() {\n return ` fragment TetherCart on Cart{id checkoutUrl totalQuantity note createdAt updatedAt attributes{key value}buyerIdentity{countryCode email}discountCodes{code applicable}cost{subtotalAmount{${MONEY}}totalAmount{${MONEY}}checkoutChargeAmount{${MONEY}}}lines(first:100){nodes{id quantity attributes{key value}cost{totalAmount{${MONEY}}subtotalAmount{${MONEY}}amountPerQuantity{${MONEY}}compareAtAmountPerQuantity{${MONEY}}}discountAllocations{discountedAmount{${MONEY}}}sellingPlanAllocation{sellingPlan{id name description recurringDeliveries options{name value}}checkoutChargeAmount{${MONEY}}priceAdjustments{price{${MONEY}}compareAtPrice{${MONEY}}perDeliveryPrice{${MONEY}}}}merchandise{... on ProductVariant{id title sku availableForSale requiresShipping quantityAvailable image{${IMAGE}}price{${MONEY}}compareAtPrice{${MONEY}}selectedOptions{name value}product{id title handle vendor featuredImage{${IMAGE}}}}}... on ComponentizableCartLine{lineComponents{id quantity merchandise{... on ProductVariant{id title product{title handle}}}}}}}}`;\n}\n\n/** @returns {string} The collection fields Tether renders, for inside a `collection { }` selection. */\nexport function collectionFields() {\n return `\n id handle title description descriptionHtml\n image { ${IMAGE} }\n seo { title description }`;\n}\n", "/**\n * Shopify selling plans (subscriptions): which plans a product and a variant have, and what each costs. Pure, no DOM,\n * shared by the browser script and the server helpers.\n */\n/** @import { Money } from './shopify-values.js' */\n/** @import { SellingPlan, SellingPlanGroup, SellingPlanAllocation } from './fragments.js' */\n\n/** @typedef {SellingPlan & { group: SellingPlanGroup }} PlanInGroup A plan with the group it belongs to. */\n/** @typedef {{ sellingPlanGroups?: { nodes: SellingPlanGroup[] } | null }} ProductWithPlans */\n/**\n * A variant as far as plans go. A cart line's variant has no allocations.\n *\n * @typedef {{ price: Money, sellingPlanAllocations?: { nodes: SellingPlanAllocation[] } | null }} VariantWithPlans\n */\n/**\n * @typedef {{ type: 'percentage', value: number } | { type: 'amount', value: Money } | { type: 'price', value: Money }}\n * PlanAdjustment\n */\n\n/**\n * @param {unknown} value A gid, a numeric id, or anything else.\n * @param {string} type The Shopify type, e.g. `ProductVariant`.\n * @returns {string | null} The gid of a numeric id; a gid or other value as written; `null` when empty.\n */\nexport function toGid(value, type) {\n const text = typeof value === 'string' || typeof value === 'number' ? String(value).trim() : '';\n if (!text) return null;\n if (text.startsWith('gid://')) return text;\n if (/^\\d+$/.test(text)) return `gid://shopify/${type}/${text}`;\n return text;\n}\n\nexport const GID = {\n /** @param {unknown} value */\n product: (value) => toGid(value, 'Product'),\n /** @param {unknown} value */\n variant: (value) => toGid(value, 'ProductVariant'),\n /** @param {unknown} value */\n sellingPlan: (value) => toGid(value, 'SellingPlan'),\n};\n\n/**\n * @param {ProductWithPlans | null | undefined} product\n * @returns {PlanInGroup[]} All plans of the product, flattened.\n */\nexport function allPlans(product) {\n const groups = product?.sellingPlanGroups?.nodes ?? [];\n return groups.flatMap((group) => group.sellingPlans.nodes.map((plan) => ({ ...plan, group })));\n}\n\n/** @param {ProductWithPlans | null | undefined} product */\nexport function hasPlans(product) {\n return allPlans(product).length > 0;\n}\n\n/**\n * @param {VariantWithPlans | null | undefined} variant\n * @param {string | null | undefined} planId\n * @returns {SellingPlanAllocation | null} The variant's allocation on the plan; `null` when the variant isn't in it.\n */\nexport function allocationFor(variant, planId) {\n if (!variant || !planId) return null;\n const allocations = variant.sellingPlanAllocations?.nodes ?? [];\n return allocations.find((allocation) => allocation.sellingPlan.id === planId) ?? null;\n}\n\n/**\n * @param {ProductWithPlans | null | undefined} product\n * @param {VariantWithPlans | null | undefined} variant\n * @returns {PlanInGroup[]} The plans this variant can be bought on.\n */\nexport function plansForVariant(product, variant) {\n return allPlans(product).filter((plan) => allocationFor(variant, plan.id));\n}\n\n/**\n * @param {VariantWithPlans | null | undefined} variant\n * @param {string | null | undefined} planId\n * @returns {Money | null} The price per delivery on the plan; the one-time price when the variant isn't on it.\n */\nexport function planPrice(variant, planId) {\n const adjustment = allocationFor(variant, planId)?.priceAdjustments[0];\n return adjustment?.perDeliveryPrice ?? adjustment?.price ?? variant?.price ?? null;\n}\n\n/**\n * @param {VariantWithPlans | null | undefined} variant\n * @param {string | null | undefined} planId\n * @returns {Money | null} What the customer pays at checkout on the plan (prepaid plans charge more up front).\n */\nexport function planCheckoutCharge(variant, planId) {\n const allocation = allocationFor(variant, planId);\n return allocation?.checkoutChargeAmount ?? allocation?.priceAdjustments[0]?.price ?? variant?.price ?? null;\n}\n\n/**\n * @param {VariantWithPlans | null | undefined} variant\n * @param {string | null | undefined} planId\n * @returns {{ amount: Money | null, percentage: number }} What the plan saves on the one-time price; no amount and\n * 0% when it saves nothing.\n */\nexport function planSavings(variant, planId) {\n const oneTime = parseFloat(variant?.price.amount ?? '');\n const onPlan = parseFloat(planPrice(variant, planId)?.amount ?? '');\n if (!variant || !Number.isFinite(oneTime) || !Number.isFinite(onPlan) || oneTime <= 0 || onPlan >= oneTime) {\n return { amount: null, percentage: 0 };\n }\n return {\n amount: { amount: (oneTime - onPlan).toFixed(2), currencyCode: variant.price.currencyCode },\n percentage: Math.round((1 - onPlan / oneTime) * 100),\n };\n}\n\n/**\n * @param {Pick<SellingPlan, 'priceAdjustments'> | null | undefined} plan\n * @returns {PlanAdjustment | null} The plan's own discount, whatever the variant: a percentage, a fixed amount off or\n * a fixed price.\n */\nexport function planAdjustment(plan) {\n const value = plan?.priceAdjustments[0]?.adjustmentValue;\n if (!value) return null;\n switch (value.__typename) {\n case 'SellingPlanPercentagePriceAdjustment':\n return { type: 'percentage', value: value.adjustmentPercentage };\n case 'SellingPlanFixedAmountPriceAdjustment':\n return { type: 'amount', value: value.adjustmentAmount };\n case 'SellingPlanFixedPriceAdjustment':\n return { type: 'price', value: value.price };\n default:\n // An adjustment type newer than the API version Tether was written for.\n return null;\n }\n}\n\n/**\n * Finds a plan by id, numeric id, name or option value (case-insensitive), so Webflow editors can write\n * `tether-default-plan=\"Every month\"`.\n *\n * @param {ProductWithPlans | null | undefined} product\n * @param {string | null | undefined} ref\n * @returns {PlanInGroup | null}\n */\nexport function findPlan(product, ref) {\n if (!ref) return null;\n const plans = allPlans(product);\n const gid = GID.sellingPlan(ref);\n const needle = ref.trim().toLowerCase();\n return (\n plans.find((plan) => plan.id === gid) ??\n plans.find((plan) => plan.name.toLowerCase() === needle) ??\n plans.find((plan) => plan.options.some((option) => option.value.toLowerCase() === needle)) ??\n null\n );\n}\n", "/**\n * The cart drawer: every `[tether-cart-drawer]` on the page opens and closes together, as a modal dialog. Focus moves\n * into the open cart, Tab stays inside it and focus returns on close (`cartFocus`). A page without a drawer (a cart\n * built in React, Svelte or Vue) still has an open state, for `Tether.cart.subscribe`.\n */\nimport { cfg } from '../config.js';\nimport { sel, get, qsa, emit } from '../dom.js';\n\nconst FOCUSABLE =\n 'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex=\"-1\"])';\n\n/** Long enough for the drawer's open transition to make its content visible: hidden elements can't take focus. */\nconst FOCUS_AFTER_OPEN_MS = 60;\n\n/** The open state of a page without a drawer element. */\nlet openWithoutDrawer = false;\n\n/** @type {HTMLElement | null} Where focus was before the cart opened. */\nlet returnFocus = null;\n\n/**\n * @param {Element | null} el\n * @returns {el is HTMLElement}\n */\nconst isFocusable = (el) => el !== null && 'focus' in el;\n\n/**\n * @param {ParentNode} drawer\n * @returns {HTMLElement[]} The visible focusable elements inside `drawer`, in document order.\n */\nconst focusables = (drawer) =>\n qsa(drawer, FOCUSABLE).filter((el) => el.offsetParent !== null || el === document.activeElement);\n\n/** @returns {HTMLElement[]} Every cart drawer on the page. */\nexport const drawers = () => qsa(document, sel('cart-drawer'));\n\n/** @param {HTMLElement} drawer */\nconst isOpenDrawer = (drawer) => drawer.classList.contains(cfg.cartDrawerOpenClass);\n\n/** @returns {boolean} True while a drawer, or the drawer-less cart, is open. */\nexport function isOpen() {\n const all = drawers();\n return all.length ? all.some(isOpenDrawer) : openWithoutDrawer;\n}\n\n/**\n * `aria-expanded` on the open buttons, and dialog semantics on the drawers unless their markup has its own. A closed\n * drawer is hidden from screen readers and, with `cartFocus`, out of the Tab order (inert), like a closed dialog.\n *\n * @param {boolean} open\n */\nexport function syncDrawerAria(open) {\n qsa(document, sel('cart-open')).forEach((button) => {\n button.setAttribute('aria-expanded', String(open));\n });\n drawers().forEach((drawer) => {\n if (!drawer.hasAttribute('role')) drawer.setAttribute('role', 'dialog');\n if (!drawer.hasAttribute('aria-label') && !drawer.hasAttribute('aria-labelledby')) {\n drawer.setAttribute('aria-label', get(drawer, 'cart-label') || 'Cart');\n }\n drawer.setAttribute('aria-modal', String(open));\n if (isOpenDrawer(drawer)) return;\n drawer.setAttribute('aria-hidden', 'true');\n if (cfg.cartFocus) drawer.inert = true;\n });\n}\n\n/** @param {HTMLElement} drawer */\nfunction focusInto(drawer) {\n const target = focusables(drawer)[0] ?? drawer;\n if (target === drawer && !drawer.hasAttribute('tabindex')) drawer.tabIndex = -1;\n target.focus({ preventScroll: true });\n}\n\n/** Opens every drawer except `tether-cart-drawer=\"manual\"` ones, which the site opens itself. */\nexport function openCart() {\n if (isOpen()) return;\n openWithoutDrawer = true;\n const opened = drawers().filter((drawer) => get(drawer, 'cart-drawer') !== 'manual');\n opened.forEach((drawer) => {\n drawer.inert = false;\n drawer.classList.add(cfg.cartDrawerOpenClass);\n drawer.setAttribute('aria-hidden', 'false');\n });\n syncDrawerAria(true);\n const [first] = opened;\n if (cfg.cartFocus && first) {\n returnFocus = isFocusable(document.activeElement) ? document.activeElement : null;\n setTimeout(() => {\n focusInto(first);\n }, FOCUS_AFTER_OPEN_MS);\n }\n cfg.onCartOpen?.(opened);\n emit('cart-toggled', { open: true });\n}\n\nexport function closeCart() {\n if (!isOpen()) return;\n openWithoutDrawer = false;\n const all = drawers();\n const hadFocus = all.some((drawer) => drawer.contains(document.activeElement));\n all.forEach((drawer) => {\n drawer.classList.remove(cfg.cartDrawerOpenClass);\n drawer.setAttribute('aria-hidden', 'true');\n if (cfg.cartFocus) drawer.inert = true;\n });\n syncDrawerAria(false);\n if (hadFocus && returnFocus?.isConnected) returnFocus.focus({ preventScroll: true });\n returnFocus = null;\n cfg.onCartClose?.(all);\n emit('cart-toggled', { open: false });\n}\n\nexport function toggleCart() {\n if (isOpen()) closeCart();\n else openCart();\n}\n\n/**\n * Keeps Tab inside the open drawer (`cartFocus`): from the last focusable element it wraps to the first, with Shift\n * from the first to the last, and from outside the drawer it goes in. For a document `keydown` listener.\n *\n * @param {KeyboardEvent} event\n */\nexport function trapFocus(event) {\n if (event.key !== 'Tab' || !cfg.cartFocus || !isOpen()) return;\n const drawer = drawers().find(isOpenDrawer);\n if (!drawer) return;\n const inside = focusables(drawer);\n const first = inside[0];\n const last = inside.at(-1);\n if (!first || !last) return;\n const active = document.activeElement;\n const leaving = event.shiftKey ? active === first : active === last;\n if (drawer.contains(active) && !leaving) return;\n event.preventDefault();\n (event.shiftKey ? last : first).focus();\n}\n", "/**\n * Product data for the browser script. Products asked for in the same tick go out as one request, and every product\n * is cached for the life of the page, which survives Barba/Swup page swaps. Products the server rendered\n * (`tether/server` `hydrate()`) are used at once and refreshed once in the background.\n */\nimport { cfg, log } from './config.js';\nimport { gql, TetherError } from './client.js';\nimport { productFragment, collectionFields } from './fragments.js';\nimport { productKey } from './shopify-values.js';\n/** @import { Product, Image } from './fragments.js' */\n\n/**\n * A product request that missed is remembered this long, so one page asking twice sends one request, and a product\n * published in Shopify meanwhile shows up on the next visit.\n */\nconst MISS_CACHE_MS = 10_000;\n/** A product loaded live this recently is newer than a server-rendered copy of it, which is then ignored. */\nconst FRESH_MS = 60_000;\n\n/** @type {Map<string, Promise<Product>>} Handle or gid to the product, loaded or loading. */\nconst productCache = new Map();\n/** @type {Map<string, { resolve: (product: Product) => void, reject: (error: unknown) => void }>} */\nconst waiting = new Map();\n/** @type {Set<string>} Keys of products that came from the server and weren't refreshed yet. */\nconst stale = new Set();\n/** @type {Map<string, number>} Handle or gid to when it last loaded live, in ms since the epoch. */\nconst freshAt = new Map();\n/** @type {string[]} Keys for the next batch. */\nconst pending = [];\nlet flushScheduled = false;\n/**\n * Bumped by `clearProductCache()`: responses to requests sent before that (in the old market, after a country\n * switch) still reach their callers but never refill the cache.\n */\nlet generation = 0;\n\n/** @param {string} key */\nconst isGid = (key) => key.startsWith('gid://');\n\n/** Accepts a handle, numeric id, gid or a full product URL. */\nexport const normalizeProductKey = productKey;\n\n/**\n * Puts a product the page already has (from a collection query) in the cache, under its handle and its id.\n *\n * @param {Product | null | undefined} product\n */\nexport function primeProduct(product) {\n if (!product) return;\n const loaded = Promise.resolve(product);\n productCache.set(product.handle, loaded);\n productCache.set(product.id, loaded);\n}\n\n/**\n * @param {string | number | null | undefined} rawKey A handle, numeric id, gid or product URL.\n * @returns {Promise<Product>}\n * @throws {TetherError} `NOT_FOUND` (rejected) for an empty key or a product the store doesn't have.\n */\nexport function getProduct(rawKey) {\n const key = normalizeProductKey(rawKey);\n if (!key) return Promise.reject(new TetherError('empty product key', { code: 'NOT_FOUND' }));\n const cached = productCache.get(key);\n if (cached) return cached;\n\n /** @type {Promise<Product>} */\n const loading = new Promise((resolve, reject) => {\n waiting.set(key, { resolve, reject });\n pending.push(key);\n if (!flushScheduled) {\n flushScheduled = true;\n setTimeout(() => void flush(), 0);\n }\n });\n productCache.set(key, loading);\n return loading;\n}\n\n/**\n * @param {string[]} keys Handles and gids.\n * @returns {{ query: string, variables: Record<string, unknown>, handles: string[] }} One query for all of them: gids\n * through `nodes(ids:)` as `byId`, each handle as its own alias `h<index>`.\n */\nfunction batchQuery(keys) {\n const ids = keys.filter(isGid);\n const handles = keys.filter((key) => !isGid(key));\n const definitions = [];\n const selections = [];\n /** @type {Record<string, unknown>} */\n const variables = {};\n if (ids.length) {\n definitions.push('$ids: [ID!]!');\n variables['ids'] = ids;\n selections.push('byId: nodes(ids: $ids) { ... on Product { ...TetherProduct } }');\n }\n handles.forEach((handle, index) => {\n definitions.push(`$h${index}: String!`);\n variables[`h${index}`] = handle;\n selections.push(`h${index}: product(handle: $h${index}) { ...TetherProduct }`);\n });\n const query = `query TetherProducts(${definitions.join(',')}){${selections.join(' ')}}${productFragment()}`;\n return { query, variables, handles };\n}\n\n/**\n * @param {string} key\n * @param {(waiter: { resolve: (product: Product) => void, reject: (error: unknown) => void }) => void} settle\n */\nfunction settleWaiting(key, settle) {\n const waiter = waiting.get(key);\n waiting.delete(key);\n if (waiter) settle(waiter);\n}\n\n/**\n * @param {string} key\n * @param {number} batchGeneration\n */\nfunction forgetMissLater(key, batchGeneration) {\n if (batchGeneration !== generation) return;\n const miss = productCache.get(key);\n setTimeout(() => {\n if (productCache.get(key) === miss) productCache.delete(key);\n }, MISS_CACHE_MS);\n}\n\nasync function flush() {\n flushScheduled = false;\n const batchGeneration = generation;\n const keys = pending.splice(0);\n if (!keys.length) return;\n const { query, variables, handles } = batchQuery(keys);\n log('fetch products', keys);\n\n /** @type {Record<string, Product | null> & { byId?: (Product | null)[] }} */\n let data;\n try {\n data = await gql(query, variables);\n } catch (error) {\n keys.forEach((key) => {\n settleWaiting(key, (waiter) => {\n if (batchGeneration === generation) productCache.delete(key);\n waiter.reject(error);\n });\n });\n return;\n }\n\n /** @type {Map<string, Product>} */\n const found = new Map();\n for (const product of data.byId ?? []) if (product) found.set(product.id, product);\n handles.forEach((handle, index) => {\n const product = data[`h${index}`];\n if (product) found.set(handle, product);\n });\n\n const now = Date.now();\n keys.forEach((key) => {\n settleWaiting(key, (waiter) => {\n const product = found.get(key);\n if (!product) {\n forgetMissLater(key, batchGeneration);\n waiter.reject(new TetherError(`Product not found: ${key}`, { code: 'NOT_FOUND' }));\n return;\n }\n if (batchGeneration === generation) {\n primeProduct(product);\n freshAt.set(product.handle, now);\n freshAt.set(product.id, now);\n }\n waiter.resolve(product);\n });\n });\n}\n\n/** Forgets every product, for a new market: requests already sent no longer fill the cache. */\nexport function clearProductCache() {\n productCache.clear();\n generation += 1;\n stale.clear();\n freshAt.clear();\n}\n\n/**\n * Uses products the server rendered, unless the page loaded the same product live in the last `FRESH_MS` (an earlier\n * page of a View Transition visit), whose copy is newer.\n *\n * @param {readonly Product[] | null | undefined} products\n */\nexport function hydrateProducts(products) {\n for (const product of products ?? []) {\n if (!product.id || !product.handle) continue;\n const loadedAgo = Date.now() - (freshAt.get(product.handle) ?? 0);\n if (loadedAgo < FRESH_MS && productCache.has(product.handle)) continue;\n primeProduct(product);\n stale.add(product.handle);\n stale.add(product.id);\n }\n}\n\n/**\n * @param {string | number | null | undefined} rawKey\n * @returns {boolean} True once per server-rendered product: the caller then refreshes it.\n */\nexport function takeStale(rawKey) {\n const key = normalizeProductKey(rawKey);\n if (!key || !stale.has(key)) return false;\n stale.delete(key);\n // The handle and the id point to the same product: one refresh covers both.\n void productCache.get(key)?.then((product) => {\n stale.delete(product.handle);\n stale.delete(product.id);\n });\n return true;\n}\n\n/**\n * Loads these products again, past the cache.\n *\n * @param {readonly (string | number)[]} keys\n * @returns {Promise<Product>[]}\n */\nexport function refreshProducts(keys) {\n for (const key of keys) {\n const normalized = normalizeProductKey(key);\n if (normalized) productCache.delete(normalized);\n }\n return keys.map((key) => getProduct(key));\n}\n\n/** @typedef {{ hasNextPage: boolean, endCursor: string | null }} PageInfo */\n/**\n * @typedef {object} Collection\n * @property {string} id\n * @property {string} handle\n * @property {string} title\n * @property {string} description\n * @property {string} descriptionHtml\n * @property {Image | null} image\n * @property {{ title: string | null, description: string | null }} seo\n */\n/** @typedef {{ collection: Collection | null, products: Product[], pageInfo: PageInfo }} ProductPage */\n/**\n * @typedef {object} ProductQuery\n * @property {string} [collection] A collection handle; without one, a search.\n * @property {string} [query] Storefront search syntax, for a search.\n * @property {number} [first]\n * @property {string | null} [after] The cursor of the page before.\n * @property {string} [sortKey] `ProductCollectionSortKeys` for a collection, `ProductSortKeys` for a search.\n * @property {boolean} [reverse]\n * @property {unknown[]} [filters] `ProductFilter` values, for a collection.\n */\n\nconst COLLECTION_QUERY = `query TetherCollection($handle:String!,$first:Int!,$after:String,$sortKey:ProductCollectionSortKeys,$reverse:Boolean,$filters:[ProductFilter!]){collection(handle:$handle){${collectionFields()} products(first:$first,after:$after,sortKey:$sortKey,reverse:$reverse,filters:$filters){nodes{...TetherProduct}pageInfo{hasNextPage endCursor}}}}`;\n\nconst SEARCH_QUERY = `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}}}`;\n\n/**\n * A page of products from a collection (by handle) or from a search. Every product on it is cached.\n *\n * @param {ProductQuery} [options]\n * @returns {Promise<ProductPage>}\n * @throws {TetherError} `NOT_FOUND` for a collection the store doesn't have.\n */\nexport async function getProducts({\n collection,\n query,\n first = cfg.collectionFirst,\n after = null,\n sortKey,\n reverse = false,\n filters,\n} = {}) {\n const fragment = productFragment();\n if (collection) {\n /** @type {{ collection: (Collection & { products: { nodes: Product[], pageInfo: PageInfo } }) | null }} */\n const data = await gql(`${COLLECTION_QUERY}\\n${fragment}`, {\n handle: collection,\n first,\n after,\n sortKey: sortKey || undefined,\n reverse,\n filters: filters ?? undefined,\n });\n if (!data.collection) throw new TetherError(`Collection not found: ${collection}`, { code: 'NOT_FOUND' });\n const { products, ...rest } = data.collection;\n products.nodes.forEach(primeProduct);\n return { collection: rest, products: products.nodes, pageInfo: products.pageInfo };\n }\n\n /** @type {{ products: { nodes: Product[], pageInfo: PageInfo } }} */\n const data = await gql(`${SEARCH_QUERY}\\n${fragment}`, {\n first,\n after,\n query: query || undefined,\n sortKey: sortKey || undefined,\n reverse,\n });\n data.products.nodes.forEach(primeProduct);\n return { collection: null, products: data.products.nodes, pageInfo: data.products.pageInfo };\n}\n\n/**\n * Shopify's recommendations for a product. Every product in them is cached.\n *\n * @param {string | number | { id: string } | null | undefined} product A product, or its handle, id or gid.\n * @param {'RELATED' | 'COMPLEMENTARY'} [intent]\n * @returns {Promise<Product[]>}\n */\nexport async function getRecommendations(product, intent = 'RELATED') {\n const key = normalizeProductKey(typeof product === 'object' ? product?.id : product);\n const byId = key?.startsWith('gid://') ?? false;\n /** @type {{ productRecommendations: Product[] | null }} */\n const data = await gql(\n `query TetherRecs(${byId ? '$id: ID!' : '$handle: String!'},$intent:ProductRecommendationIntent){productRecommendations(${byId ? 'productId: $id' : 'productHandle: $handle'},intent:$intent){...TetherProduct}}${productFragment()}`,\n byId ? { id: key, intent } : { handle: key, intent },\n );\n const list = data.productRecommendations ?? [];\n list.forEach(primeProduct);\n return list;\n}\n", "/**\n * Shopify sends money amounts as decimal strings (`'27.50'`). Comparing them as floats can misjudge two amounts that\n * differ only past float precision, so they are compared digit by digit, as integers of the smallest unit present.\n */\n\nconst DECIMAL = /^(-?)(\\d+)(?:\\.(\\d+))?$/;\n\n/**\n * @param {string} amount\n * @param {number} fractionDigits Digits after the point to scale to.\n * @returns {bigint | null} The amount in units of 10^-fractionDigits, `null` when it isn't a decimal number.\n */\nfunction toScaledInteger(amount, fractionDigits) {\n const match = DECIMAL.exec(amount.trim());\n if (!match) return null;\n const [, sign = '', whole = '0', fraction = ''] = match;\n const digits = BigInt(`${whole}${fraction.padEnd(fractionDigits, '0')}`);\n return sign === '-' ? -digits : digits;\n}\n\n/** @param {string} amount */\nconst fractionLength = (amount) => amount.split('.')[1]?.length ?? 0;\n\n/**\n * @param {string | null | undefined} amount\n * @param {string | null | undefined} other\n * @returns {boolean} True when both are decimal numbers and `amount` is the larger one.\n */\nexport function isGreaterAmount(amount, other) {\n if (amount == null || other == null) return false;\n const fractionDigits = Math.max(fractionLength(amount.trim()), fractionLength(other.trim()));\n const scaled = toScaledInteger(amount, fractionDigits);\n const scaledOther = toScaledInteger(other, fractionDigits);\n if (scaled === null || scaledOther === null) return false;\n return scaled > scaledOther;\n}\n", "/**\n * Shows the cart everywhere on the page: counts, totals, `tether-show=\"cart-*\"` conditions, the note, the discount\n * codes and the `[tether-cart-lines]` repeaters. It renders what it is given (a `CartView`) and holds no state, so\n * every render shows the cart as the store has it at that moment.\n */\nimport { cfg, reportError } from '../config.js';\nimport { getProduct } from '../loader.js';\nimport { allPlans } from '../selling-plans.js';\nimport { isGreaterAmount } from '../amounts.js';\nimport {\n attr,\n sel,\n get,\n qsa,\n formatMoney,\n setText,\n setTextTracked,\n setImage,\n show,\n repeat,\n repeatKeyed,\n productUrl,\n notifyLayoutChanged,\n} from '../dom.js';\nimport { isOpen, syncDrawerAria } from './drawer.js';\n/** @import { CartWarning } from '../config.js' */\n/** @import { Product } from '../fragments.js' */\n/** @import { ShopifyCart, ShopifyCartLine, PendingQuantity } from './store.js' */\n\n/**\n * @typedef {object} CartView What a render shows.\n * @property {ShopifyCart | null} cart\n * @property {readonly CartWarning[]} warnings\n * @property {ReadonlyMap<string, PendingQuantity>} pending Line id \u2192 the quantity quick clicks asked for.\n * @property {boolean} failed The last load or change failed (`tether-show=\"cart-error\"`).\n */\n\n/** Shopify's title of a variant of a product without options. */\nconst DEFAULT_TITLE = 'Default Title';\n\n/**\n * @param {ShopifyCartLine} line\n * @param {ReadonlyMap<string, PendingQuantity>} pending\n * @returns {number} The quantity to show: the one asked for while an update is on its way.\n */\nexport const quantityOf = (line, pending) => pending.get(line.id)?.quantity ?? line.quantity;\n\n/** @param {string} gid */\nconst numericId = (gid) => gid.split('/').pop() ?? gid;\n\n/**\n * @param {ShopifyCartLine} line\n * @returns {string} The product page, with the line's variant and plan selected.\n */\nfunction lineUrl(line) {\n const variant = line.merchandise;\n const base = productUrl(variant.product.handle, variant.product.id);\n const query = new URLSearchParams();\n query.set('variant', numericId(variant.id));\n const planId = line.sellingPlanAllocation?.sellingPlan.id;\n if (planId) query.set('selling_plan', numericId(planId));\n return `${base}${base.includes('?') ? '&' : '?'}${query.toString()}`;\n}\n\n/** @typedef {(line: ShopifyCartLine, view: CartView) => string | number} LineText */\n\n/** @type {LineText} */\nconst productTitle = (line) => line.merchandise.product.title;\n\n/** @type {Record<string, LineText>} The text of each `tether-line` key. */\nconst LINE_TEXT = {\n title: productTitle,\n 'product-title': productTitle,\n 'variant-title': (line) => (line.merchandise.title === DEFAULT_TITLE ? '' : line.merchandise.title),\n options: (line) =>\n line.merchandise.selectedOptions\n .filter((option) => option.value !== DEFAULT_TITLE)\n .map((option) => `${option.name}: ${option.value}`)\n .join(', '),\n vendor: (line) => line.merchandise.product.vendor,\n sku: (line) => line.merchandise.sku ?? '',\n price: (line) => formatMoney(line.cost.amountPerQuantity),\n 'compare-at-price': (line) => formatMoney(line.cost.compareAtAmountPerQuantity ?? line.merchandise.compareAtPrice),\n 'line-total': (line) => formatMoney(line.cost.totalAmount),\n 'line-subtotal': (line) => formatMoney(line.cost.subtotalAmount),\n quantity: (line, view) => quantityOf(line, view.pending),\n plan: (line) => line.sellingPlanAllocation?.sellingPlan.name ?? '',\n 'plan-description': (line) => line.sellingPlanAllocation?.sellingPlan.description ?? '',\n components: (line) =>\n (line.lineComponents ?? [])\n .map((component) => `${component.quantity} \u00D7 ${component.merchandise.product.title}`)\n .join(', '),\n};\n\nconst ATTRIBUTE_KEY = 'attribute:';\n\n/**\n * @param {ShopifyCartLine} line\n * @param {string} key The `tether-line` value.\n * @param {CartView} view\n * @returns {string | number | undefined} The text for `key`, `undefined` for a key Tether doesn't know.\n */\nfunction lineValue(line, key, view) {\n if (Object.hasOwn(LINE_TEXT, key)) return LINE_TEXT[key]?.(line, view);\n if (!key.startsWith(ATTRIBUTE_KEY)) return undefined;\n const name = key.slice(ATTRIBUTE_KEY.length);\n return line.attributes.find((attribute) => attribute.key === name)?.value ?? '';\n}\n\n/**\n * Fills a `<select tether-line-plan>` with the product's plans (and one-time purchase, when the product allows it and\n * the select isn't `subscription-only`), keeping the options when they haven't changed.\n *\n * @param {HTMLSelectElement} select\n * @param {ShopifyCartLine} line\n * @param {Product} product\n */\nfunction fillPlanSelect(select, line, product) {\n const plans = allPlans(product);\n const allowOneTime = !product.requiresSellingPlan && get(select, 'line-plan') !== 'subscription-only';\n const oneTime = { value: '', label: select.getAttribute(attr('one-time-label')) || 'One-time purchase' };\n const choices = [...(allowOneTime ? [oneTime] : []), ...plans.map((plan) => ({ value: plan.id, label: plan.name }))];\n const signature = choices.map((choice) => choice.value).join('|');\n if (select.dataset['tetherSig'] !== signature) {\n select.replaceChildren(\n ...choices.map((choice) => {\n const option = document.createElement('option');\n option.value = choice.value;\n option.textContent = choice.label;\n return option;\n }),\n );\n select.dataset['tetherSig'] = signature;\n }\n select.value = line.sellingPlanAllocation?.sellingPlan.id ?? '';\n show(select, plans.length > 0);\n}\n\n/**\n * @param {HTMLElement} node\n * @param {ShopifyCartLine} line\n * @param {CartView} view\n */\nfunction renderLineState(node, line, view) {\n const isSubscription = Boolean(line.sellingPlanAllocation);\n node.classList.toggle('is-subscription', isSubscription);\n // Shopify's note about this line, such as less stock than asked.\n const warning = view.warnings.find((candidate) => candidate.target === line.id);\n node.classList.toggle('is-warning', Boolean(warning));\n const pending = view.pending.has(line.id);\n node.classList.toggle('is-busy', pending);\n if (pending) node.setAttribute('aria-busy', 'true');\n else node.removeAttribute('aria-busy');\n qsa(node, sel('line', 'warning')).forEach((el) => {\n setTextTracked(el, warning?.message ?? '');\n });\n const conditions = {\n subscription: isSubscription,\n 'one-time': !isSubscription,\n 'on-sale': isGreaterAmount(line.cost.compareAtAmountPerQuantity?.amount, line.cost.amountPerQuantity.amount),\n 'has-components': (line.lineComponents ?? []).length > 0,\n warning: Boolean(warning),\n };\n qsa(node, sel('line-show')).forEach((el) => {\n const key = get(el, 'line-show');\n if (key !== null && Object.hasOwn(conditions, key)) show(el, conditions[/** @type {keyof conditions} */ (key)]);\n });\n}\n\n/**\n * @param {HTMLElement} node\n * @param {ShopifyCartLine} line\n * @param {CartView} view\n */\nfunction renderLine(node, line, view) {\n const variant = line.merchandise;\n node.setAttribute(attr('line-id'), line.id);\n qsa(node, sel('line')).forEach((el) => {\n const key = get(el, 'line') ?? '';\n if (key === 'image') {\n setImage(el, variant.image?.url ?? variant.product.featuredImage?.url, variant.product.title);\n return;\n }\n if (key === 'url') {\n el.setAttribute('href', lineUrl(line));\n return;\n }\n const value = lineValue(line, key, view);\n if (value !== undefined) setTextTracked(el, value);\n });\n renderLineState(node, line, view);\n qsa(node, `select${sel('line-plan')}`).forEach((select) => {\n getProduct(variant.product.handle)\n .then((product) => {\n // The selector matches only <select> elements.\n fillPlanSelect(/** @type {HTMLSelectElement} */ (select), line, product);\n })\n .catch((/** @type {unknown} */ error) => {\n reportError(error, 'line plan options');\n });\n });\n}\n\n/**\n * @param {ShopifyCart | null} cart\n * @param {CartView} view\n */\nfunction renderConditions(cart, view) {\n const count = cart?.totalQuantity ?? 0;\n const hasSubscription = (cart?.lines.nodes ?? []).some((line) => line.sellingPlanAllocation);\n const conditions = {\n 'cart-empty': count === 0,\n 'cart-filled': count > 0,\n 'cart-has-subscription': hasSubscription,\n 'cart-no-subscription': !hasSubscription,\n 'cart-has-discount': (cart?.discountCodes ?? []).some((code) => code.applicable),\n 'cart-error': view.failed,\n 'cart-warning': view.warnings.length > 0,\n };\n qsa(document, sel('show')).forEach((el) => {\n const key = get(el, 'show');\n if (key === null || !Object.hasOwn(conditions, key) || el.closest(sel('product'))) return;\n show(el, conditions[/** @type {keyof conditions} */ (key)]);\n });\n qsa(document, sel('checkout')).forEach((el) => {\n el.classList.toggle('is-disabled', !count);\n el.setAttribute('aria-disabled', String(!count));\n });\n}\n\n/** @param {ShopifyCart | null} cart */\nfunction renderFields(cart) {\n qsa(document, `textarea${sel('cart-note')},input${sel('cart-note')}`).forEach((el) => {\n // The visitor may be typing in it.\n if (document.activeElement !== el) setText(el, cart?.note ?? '');\n });\n qsa(document, sel('cart-discounts')).forEach((container) => {\n repeat(container, cart?.discountCodes ?? [], (node, discount) => {\n node.setAttribute(attr('discount-code'), discount.code);\n const target = node.querySelector(sel('discount', 'code')) ?? (node.firstElementChild ? null : node);\n if (target) setText(target, discount.code);\n node.classList.toggle('is-inapplicable', !discount.applicable);\n });\n });\n}\n\n/** @param {CartView} view */\nexport function renderCart(view) {\n const { cart } = view;\n /** @param {'subtotalAmount' | 'totalAmount' | 'checkoutChargeAmount'} key */\n const money = (key) => (cart ? formatMoney(cart.cost[key]) : '');\n\n syncDrawerAria(isOpen());\n qsa(document, sel('cart-count')).forEach((el) => {\n setTextTracked(el, cart?.totalQuantity ?? 0);\n });\n qsa(document, sel('cart-subtotal')).forEach((el) => {\n setTextTracked(el, money('subtotalAmount'));\n });\n qsa(document, sel('cart-total')).forEach((el) => {\n setTextTracked(el, money('totalAmount'));\n });\n qsa(document, sel('cart-checkout-charge')).forEach((el) => {\n setTextTracked(el, money('checkoutChargeAmount'));\n });\n renderConditions(cart, view);\n qsa(document, sel('cart-warning')).forEach((el) => {\n setTextTracked(el, [...new Set(view.warnings.map((warning) => warning.message))].join(' '));\n });\n renderFields(cart);\n qsa(document, sel('cart-lines')).forEach((container) => {\n repeatKeyed(\n container,\n cart?.lines.nodes ?? [],\n (line) => line.id,\n (node, line) => {\n renderLine(node, line, view);\n },\n { onEnter: cfg.onLineEnter, onLeave: cfg.onLineLeave },\n );\n });\n if (cart) notifyLayoutChanged('cart');\n}\n\n/**\n * Shows the count a saved cart had on the last page in the cart counts the page left at 0, until it has loaded.\n *\n * @param {string} count\n */\nexport function showSavedCount(count) {\n qsa(document, sel('cart-count')).forEach((el) => {\n if (/^\\s*0?\\s*$/.test(el.textContent)) el.textContent = count;\n });\n}\n", "/**\n * The cart on this page: what Shopify last said about it (`CartStatus`), the quantities quick clicks asked for, the\n * customer it belongs to, and the one queue every change goes through. A change of what the page shows goes through\n * here, so the document (`renderCart`) and the listeners (`tether:cart-updated`) always see the store's cart.\n */\nimport { cfg } from '../config.js';\nimport { emit } from '../dom.js';\nimport { isOpen } from './drawer.js';\nimport { renderCart, quantityOf, showSavedCount } from './render.js';\n/** @import { CartWarning } from '../config.js' */\n/** @import { Image } from '../fragments.js' */\n/** @import { Money } from '../shopify-values.js' */\n\n/** @typedef {{ key: string, value: string }} Attribute */\n/**\n * @typedef {object} CartVariant A line's `merchandise`: Shopify's `Merchandise` union has only `ProductVariant`.\n * @property {string} id\n * @property {string} title\n * @property {string | null} sku\n * @property {boolean} availableForSale\n * @property {boolean} requiresShipping\n * @property {number | null} [quantityAvailable] Absent when the store's token can't read inventory.\n * @property {Image | null} image\n * @property {Money} price\n * @property {Money | null} compareAtPrice\n * @property {{ name: string, value: string }[]} selectedOptions\n * @property {{ id: string, title: string, handle: string, vendor: string, featuredImage: Image | null }} product\n */\n/**\n * @typedef {object} LinePlanAllocation\n * @property {{ id: string, name: string, description: string | null, recurringDeliveries: boolean,\n * options: { name: string, value: string }[] }} sellingPlan\n * @property {Money} checkoutChargeAmount\n * @property {{ price: Money, compareAtPrice: Money, perDeliveryPrice: Money }[]} priceAdjustments\n */\n/**\n * @typedef {object} ShopifyCartLine\n * @property {string} id\n * @property {number} quantity\n * @property {Attribute[]} attributes\n * @property {{ totalAmount: Money, subtotalAmount: Money, amountPerQuantity: Money,\n * compareAtAmountPerQuantity: Money | null }} cost\n * @property {{ discountedAmount: Money }[]} discountAllocations\n * @property {LinePlanAllocation | null} sellingPlanAllocation\n * @property {CartVariant} merchandise\n * @property {{ id: string, quantity: number, merchandise: { id: string, title: string,\n * product: { title: string, handle: string } } }[]} [lineComponents] Only on a bundle (`ComponentizableCartLine`).\n */\n/**\n * @typedef {object} ShopifyCart The fields of `fragment TetherCart`.\n * @property {string} id\n * @property {string} checkoutUrl\n * @property {number} totalQuantity\n * @property {string | null} note\n * @property {string} createdAt\n * @property {string} updatedAt\n * @property {Attribute[]} attributes\n * @property {{ countryCode: string | null, email: string | null }} buyerIdentity\n * @property {{ code: string, applicable: boolean }[]} discountCodes\n * @property {{ subtotalAmount: Money, totalAmount: Money, checkoutChargeAmount: Money }} cost\n * @property {{ nodes: ShopifyCartLine[] }} lines\n */\n\n/**\n * @typedef {{ kind: 'unknown' }\n * | { kind: 'empty' }\n * | { kind: 'ready', cart: ShopifyCart }\n * | { kind: 'error', error: unknown, cart: ShopifyCart | null }} CartStatus\n * `unknown` until the saved cart has loaded (the page's own markup shows); `empty` without a cart (none saved, or\n * Shopify no longer has it); `error` after a failed load or change, with the cart as Shopify last sent it.\n */\n\n/** @typedef {{ quantity: number }} PendingQuantity What one quick +/- click asked for; a newer click replaces it. */\n\n/**\n * @typedef {object} CustomerLink What the account part sets while a customer is logged in.\n * @property {string | null} accessToken The Customer Account API token: carts created now belong to the customer.\n * @property {(() => Promise<string | null>) | null} beforeCheckout The account's own checkout URL; `null` from it, or\n * no function, uses the cart's.\n */\n\n/**\n * @typedef {object} CartMeta The second argument of a `subscribe` listener.\n * @property {boolean} open\n * @property {number} count\n * @property {boolean} loaded\n * @property {readonly CartWarning[]} warnings\n */\n\n/** @type {CartStatus} */\nlet status = { kind: 'unknown' };\n\n/** @type {readonly CartWarning[]} Shopify's notes on the last change. */\nlet warnings = [];\n\n/** @type {Map<string, PendingQuantity>} Line id \u2192 what quick +/- clicks asked for, until Shopify has answered. */\nexport const pendingQuantities = new Map();\n\n/** @type {CustomerLink} */\nexport const customer = { accessToken: null, beforeCheckout: null };\n\n/** @returns {CartStatus} */\nexport const cartStatus = () => status;\n\n/** @returns {ShopifyCart | null} The cart as Shopify last sent it. */\nexport function currentCart() {\n switch (status.kind) {\n case 'ready':\n case 'error':\n return status.cart;\n case 'unknown':\n case 'empty':\n return null;\n }\n}\n\n/** @returns {readonly CartWarning[]} */\nexport const currentWarnings = () => warnings;\n\n/**\n * @param {ShopifyCart | null} cart\n * @returns {CartStatus}\n */\nconst statusOf = (cart) => (cart ? { kind: 'ready', cart } : { kind: 'empty' });\n\nconst seenKey = () => `${cfg.storageKey}:seen`;\n\n/**\n * localStorage throws in private mode and where the visitor blocks site data: the cart then lasts for this page.\n *\n * @param {string} key\n * @returns {string | null}\n */\nfunction readStorageIfAllowed(key) {\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n}\n\n/**\n * Like `readStorageIfAllowed`: without storage, nothing is remembered.\n *\n * @param {string} key\n * @param {string | null} value `null` removes the key.\n */\nfunction writeStorageIfAllowed(key, value) {\n try {\n if (value === null) localStorage.removeItem(key);\n else localStorage.setItem(key, value);\n } catch {\n // Private mode or blocked storage: see readStorageIfAllowed.\n }\n}\n\n/** @returns {string | null} The id of the visitor's cart, kept across pages. */\nexport const savedCartId = () => readStorageIfAllowed(cfg.storageKey) || null;\n\n/** Forgets the saved cart, which Shopify no longer has. */\nexport function forgetSavedCart() {\n writeStorageIfAllowed(cfg.storageKey, null);\n}\n\n/**\n * Keeps a cart Shopify sent without showing it, for an answer a newer change will replace.\n *\n * @param {ShopifyCart | null} cart\n */\nexport function keepQuietly(cart) {\n status = statusOf(cart);\n if (cart) writeStorageIfAllowed(cfg.storageKey, cart.id);\n}\n\n/** Renders the document with the store's cart. */\nexport function render() {\n renderCart({\n cart: currentCart(),\n warnings,\n pending: pendingQuantities,\n failed: status.kind === 'error',\n });\n}\n\n/**\n * @param {string} reason The `reason` of `tether:cart-updated`.\n */\nexport function announce(reason) {\n render();\n emit('cart-updated', { cart: currentCart(), reason });\n}\n\n/**\n * Keeps a cart Shopify sent after a change, shows it, and tells this page and the visitor's other tabs.\n *\n * @param {ShopifyCart | null} cart\n * @param {string} reason\n * @returns {ShopifyCart | null} `cart`.\n */\nexport function commit(cart, reason) {\n keepQuietly(cart);\n // Other tabs reload the cart on this storage event; the next page shows the count before its cart has loaded.\n writeStorageIfAllowed(seenKey(), `${Date.now()}|${cart?.totalQuantity ?? 0}`);\n announce(reason);\n return cart;\n}\n\n/**\n * The outcome of loading the saved cart: the cart, `null` when there is none, or the failure.\n *\n * @param {{ kind: 'loaded', cart: ShopifyCart | null } | { kind: 'failed', error: unknown }} outcome\n */\nexport function settleLoad(outcome) {\n status = outcome.kind === 'loaded' ? statusOf(outcome.cart) : { kind: 'error', error: outcome.error, cart: null };\n announce('load');\n}\n\n/**\n * Sets or clears the failure without rendering, for `Tether.cart.lastError`, which the public types declare writable.\n *\n * @param {unknown} error `null` or `undefined` clears it.\n */\nexport function setFailure(error) {\n const cart = currentCart();\n status = error == null ? statusOf(cart) : { kind: 'error', error, cart };\n}\n\n/** Until the saved cart has loaded, the counts show the count it had on the last page instead of the page's 0. */\nexport function showLastKnownCount() {\n if (status.kind !== 'unknown') return;\n const count = readStorageIfAllowed(seenKey())?.split('|')[1];\n if (count) showSavedCount(count);\n}\n\n/**\n * Sets Shopify's notes on the last change: each message once, in the site's words (`warningText`).\n *\n * @param {readonly CartWarning[]} notes\n */\nexport function setWarnings(notes) {\n warnings = notes\n .filter((note, index) => notes.findIndex((other) => other.message === note.message) === index)\n .map((note) => ({ ...note, message: cfg.warningText?.(note) || note.message }));\n if (warnings.length) emit('cart-warning', { warnings });\n}\n\n/** The queue only waits for a task: its result, or failure, reaches the caller through the promise `run` returns. */\nconst waitOnly = () => undefined;\n\n/**\n * @returns {<T>(task: () => Promise<T>) => Promise<T>} A runner that starts each task once the one before has\n * settled, whether it succeeded or failed.\n */\nexport function serial() {\n /** @type {Promise<unknown>} */\n let previous = Promise.resolve();\n return (task) => {\n const run = previous.then(task);\n previous = run.then(waitOnly, waitOnly);\n return run;\n };\n}\n\nconst runInOrder = serial();\n\n/**\n * Runs a cart change after the ones before it, so quick clicks never race. A failure sets the `error` status (shown by\n * `tether-show=\"cart-error\"` until the next change succeeds), emits `tether:cart-error` and rejects.\n *\n * @template T\n * @param {() => Promise<T>} task\n * @returns {Promise<T>}\n */\nexport function enqueue(task) {\n return runInOrder(task).then(\n (value) => {\n if (status.kind === 'error') {\n status = statusOf(status.cart);\n render();\n }\n return value;\n },\n (/** @type {unknown} */ error) => {\n status = { kind: 'error', error, cart: currentCart() };\n render();\n emit('cart-error', { error });\n throw error;\n },\n );\n}\n\n/**\n * @param {ShopifyCartLine} line\n * @returns {number} The quantity to show for `line`.\n */\nexport const pendingQuantityOf = (line) => quantityOf(line, pendingQuantities);\n\n/** @returns {CartMeta} */\nconst meta = () => ({\n open: isOpen(),\n count: currentCart()?.totalQuantity ?? 0,\n loaded: status.kind !== 'unknown',\n warnings,\n});\n\n/**\n * Calls `listener` now and after every change of the cart or the drawer.\n *\n * @param {(cart: ShopifyCart | null, meta: CartMeta) => void} listener\n * @returns {() => void} Stops listening.\n */\nexport function subscribe(listener) {\n const events = ['cart-updated', 'cart-toggled'].map((name) => `${cfg.prefix}:${name}`);\n const call = () => {\n listener(currentCart(), meta());\n };\n events.forEach((name) => {\n document.addEventListener(name, call);\n });\n call();\n return () => {\n events.forEach((name) => {\n document.removeEventListener(name, call);\n });\n };\n}\n", "/**\n * The Storefront Cart API: loading the saved cart, creating one, and the mutations that change it. Shopify forgets a\n * cart some days after its last change and once it has been checked out; a change that needs a cart then creates a\n * new one with the same input, so the visitor's click still lands.\n */\nimport { cfg, log } from '../config.js';\nimport { gql, unwrap, TetherError } from '../client.js';\nimport { cartFragment } from '../fragments.js';\nimport { GID } from '../selling-plans.js';\nimport { toAttributes } from '../dom.js';\nimport { customer, savedCartId, forgetSavedCart, setWarnings } from './store.js';\n/** @import { CartWarning } from '../config.js' */\n/** @import { UserError } from '../client.js' */\n/** @import { AttributeValue } from '../dom.js' */\n/** @import { ShopifyCart, Attribute } from './store.js' */\n\n/** @typedef {Record<string, AttributeValue> | { key: string | number, value?: AttributeValue }[]} Attributes */\n/**\n * @typedef {object} LineSpec A line to add, in any of the shapes `Cart.add` takes.\n * @property {string | number} [variantId]\n * @property {string | number} [merchandiseId]\n * @property {string | number} [id]\n * @property {number | string} [quantity]\n * @property {string | number | null} [sellingPlanId]\n * @property {string | number | null} [sellingPlan]\n * @property {Attributes | null} [attributes]\n */\n/**\n * @typedef {object} CartLineInput Shopify's `CartLineInput`.\n * @property {string} merchandiseId\n * @property {number} quantity\n * @property {string} [sellingPlanId]\n * @property {Attribute[]} [attributes]\n */\n/**\n * @typedef {object} CartPayload What every cart mutation answers.\n * @property {ShopifyCart | null} cart\n * @property {UserError[]} userErrors\n * @property {CartWarning[]} [warnings]\n */\n\n/**\n * Shopify answers a cart id it can't resolve, in a mutation, with a top-level GraphQL error whose only detail is\n * this message (no `extensions.code`). A user error on the `cartId` field is recognised by its shape instead.\n */\nconst UNKNOWN_CART_MESSAGE = /does not exist|not found|invalid id/i;\n\n/**\n * @param {unknown} error\n * @returns {boolean} True when `error` says Shopify doesn't have the cart, false for any other failure (the network,\n * the token, a line it refused), after which the saved cart is still good.\n */\nexport function isCartGone(error) {\n if (!(error instanceof TetherError)) return false;\n if (error.userErrors?.some((userError) => userError.field?.[0] === 'cartId')) return true;\n return (error.errors ?? []).some((graphQLError) => UNKNOWN_CART_MESSAGE.test(graphQLError.message));\n}\n\n/**\n * @param {string | number | LineSpec | null | undefined} input A variant id, or a line.\n * @param {number} [quantity] For a variant id.\n * @param {Omit<LineSpec, 'variantId' | 'quantity'>} [options] For a variant id.\n * @returns {CartLineInput}\n * @throws {TetherError} `ERROR` without a variant id.\n */\nexport function toLineInput(input, quantity = 1, options = {}) {\n const spec = typeof input === 'object' && input !== null ? input : { ...options, variantId: input, quantity };\n const merchandiseId = GID.variant(spec.merchandiseId || spec.variantId || spec.id);\n if (!merchandiseId) throw new TetherError('add(): variantId is required');\n const asked = parseInt(String(spec.quantity ?? 1), 10);\n /** @type {CartLineInput} */\n const line = { merchandiseId, quantity: Math.max(1, asked || 1) };\n const planId = GID.sellingPlan(spec.sellingPlanId || spec.sellingPlan);\n if (planId) line.sellingPlanId = planId;\n const attributes = toAttributes(spec.attributes);\n if (attributes.length) line.attributes = attributes;\n return line;\n}\n\n/**\n * @param {string} name The mutation, which is also its payload's field.\n * @param {string} args The operation's variable definitions.\n * @param {string} inner The mutation field's arguments.\n */\nfunction mutationText(name, args, inner) {\n return `mutation Tether_${name}(${args}){${name}(${inner}){cart{...TetherCart}userErrors{field message}warnings{code message target}}}${cartFragment()}`;\n}\n\n/**\n * @param {string} name\n * @param {string} args\n * @param {string} inner\n * @param {Record<string, unknown>} variables\n * @returns {Promise<ShopifyCart | null>} The cart in Shopify's answer, after keeping its warnings.\n * @throws {TetherError} For a failed request, or the mutation's user errors.\n */\nasync function send(name, args, inner, variables) {\n /** @type {Record<string, CartPayload | null | undefined>} */\n const data = await gql(mutationText(name, args, inner), variables);\n const payload = unwrap(data[name], name);\n setWarnings(payload.warnings ?? []);\n return payload.cart;\n}\n\n/**\n * A new cart in the visitor's market, for the logged-in customer if there is one.\n *\n * @param {Record<string, unknown>} input More of Shopify's `CartInput`, e.g. the first lines.\n * @returns {Promise<ShopifyCart | null>}\n */\nfunction createCart(input) {\n const buyerIdentity = {\n ...(cfg.country ? { countryCode: cfg.country.toUpperCase() } : {}),\n ...(customer.accessToken ? { customerAccessToken: customer.accessToken } : {}),\n };\n const withIdentity = Object.keys(buyerIdentity).length ? { buyerIdentity, ...input } : input;\n return send('cartCreate', '$input: CartInput!', 'input: $input', { input: withIdentity });\n}\n\n/**\n * @typedef {object} CartMutation A mutation on the saved cart.\n * @property {string} name The mutation, e.g. `cartLinesAdd`.\n * @property {string} args Its variable definitions besides `$cartId`.\n * @property {string} inner Its arguments besides `cartId`.\n * @property {Record<string, unknown>} variables\n * @property {Record<string, unknown> | null} createInput The `CartInput` of a new cart that does what the mutation\n * asks, when there is no cart (or Shopify no longer has it); `null` leaves the visitor without a cart instead.\n */\n\n/**\n * Runs a mutation on the saved cart, or creates a cart from `createInput` when there is none to change.\n *\n * @param {CartMutation} mutation\n * @returns {Promise<ShopifyCart | null>} The changed cart; `null` without a cart and without a `createInput`.\n * @throws {TetherError} For a failed request or Shopify's user errors; also when the cart is gone and there is no\n * `createInput` (the saved cart is forgotten first).\n */\nexport async function mutateCart({ name, args, inner, variables, createInput }) {\n const cartId = savedCartId();\n if (!cartId) return createInput ? createCart(createInput) : null;\n try {\n return await send(name, `$cartId: ID!, ${args}`, `cartId: $cartId, ${inner}`, { ...variables, cartId });\n } catch (error) {\n if (!isCartGone(error)) throw error;\n forgetSavedCart();\n if (!createInput) throw error;\n log('cart expired, creating a new one');\n return createCart(createInput);\n }\n}\n\n/**\n * @param {string} id\n * @returns {Promise<ShopifyCart | null>} The cart, `null` when Shopify doesn't have it (expired or checked out).\n */\nexport async function fetchCart(id) {\n /** @type {{ cart: ShopifyCart | null }} */\n const data = await gql(`query TetherCart($id:ID!){cart(id:$id){...TetherCart}}${cartFragment()}`, { id });\n return data.cart;\n}\n\n/**\n * @param {string} id\n * @returns {Promise<string | null>} The cart's current checkout URL, `null` when Shopify doesn't have the cart.\n */\nexport async function fetchCheckoutUrl(id) {\n /** @type {{ cart: { checkoutUrl: string } | null }} */\n const data = await gql('query TetherCheckout($id: ID!) { cart(id: $id) { checkoutUrl } }', { id });\n return data.cart?.checkoutUrl ?? null;\n}\n\n/**\n * @typedef {object} LinePatch A change to one line, for `updateLine`.\n * @property {number} [quantity] 0 or less removes the line.\n * @property {string | number | null} [sellingPlanId] `null` switches the line back to one-time purchase.\n * @property {Attributes} [attributes]\n * @property {string | number} [merchandiseId]\n * @property {string | number} [variantId]\n */\n\n/**\n * @param {string} lineId\n * @param {number | LinePatch} patch\n * @returns {Record<string, unknown>} Shopify's `CartLineUpdateInput`.\n */\nexport function toLineUpdate(lineId, patch) {\n const change = typeof patch === 'number' ? { quantity: patch } : patch;\n /** @type {Record<string, unknown>} */\n const line = { id: lineId };\n if (change.quantity !== undefined) line['quantity'] = change.quantity;\n if ('sellingPlanId' in change)\n line['sellingPlanId'] = change.sellingPlanId ? GID.sellingPlan(change.sellingPlanId) : null;\n if (change.attributes) line['attributes'] = toAttributes(change.attributes);\n const variantId = change.merchandiseId || change.variantId;\n if (variantId) line['merchandiseId'] = GID.variant(variantId);\n return line;\n}\n\n/**\n * @param {Record<string, unknown>[]} lines\n * @returns {Promise<ShopifyCart | null>}\n */\nexport const updateLines = (lines) =>\n mutateCart({\n name: 'cartLinesUpdate',\n args: '$lines: [CartLineUpdateInput!]!',\n inner: 'lines: $lines',\n variables: { lines },\n createInput: null,\n });\n\n/**\n * @param {string[]} lineIds\n * @returns {Promise<ShopifyCart | null>}\n */\nexport const removeLines = (lineIds) =>\n mutateCart({\n name: 'cartLinesRemove',\n args: '$lineIds: [ID!]!',\n inner: 'lineIds: $lineIds',\n variables: { lineIds },\n createInput: null,\n });\n\n/**\n * @param {string} lineId\n * @param {number} target\n * @returns {Promise<ShopifyCart | null>} The cart once `lineId` has `target` (0 removes it).\n */\nexport const setLineQuantity = (lineId, target) =>\n target > 0 ? updateLines([{ id: lineId, quantity: target }]) : removeLines([lineId]);\n", "/**\n * Sending the visitor to Shopify's checkout. The URL comes from Shopify at click time, because the cart's checkout URL\n * changes with its market and customer; a logged-in customer's account part may supply its own (`beforeCheckout`).\n */\nimport { cfg, reportError } from '../config.js';\nimport { TetherError } from '../client.js';\nimport { isHttpsUrl } from '../shopify-values.js';\nimport { emit } from '../dom.js';\nimport { fetchCheckoutUrl } from './mutations.js';\nimport { customer, currentCart, savedCartId } from './store.js';\n/** @import { CheckoutTarget } from '../config.js' */\n\n/** @typedef {{ kind: 'url', url: string | null } | { kind: 'failed', error: unknown }} CheckoutUrlAnswer */\n\n/**\n * @param {string} cartId\n * @returns {Promise<CheckoutUrlAnswer>} Shopify's answer as a value, so the request can run alongside the account's\n * and its failure is read only when its URL is the one used.\n */\nconst askCheckoutUrl = (cartId) =>\n fetchCheckoutUrl(cartId).then(\n (url) => ({ kind: /** @type {const} */ ('url'), url }),\n (/** @type {unknown} */ error) => ({ kind: /** @type {const} */ ('failed'), error }),\n );\n\n/**\n * @returns {Promise<string | null>} The logged-in customer's checkout URL. When the account can't give one, the\n * failure is reported and the cart's own checkout URL is used, which still checks out (without the login).\n */\nasync function accountCheckoutUrl() {\n if (!customer.beforeCheckout) return null;\n try {\n return await customer.beforeCheckout();\n } catch (error) {\n reportError(error, 'account checkout');\n return null;\n }\n}\n\n/**\n * @param {string} cartId\n * @returns {Promise<string>}\n * @throws {TetherError} `ERROR` without a checkout URL (the cart is empty or Shopify no longer has it).\n */\nasync function checkoutUrl(cartId) {\n const cartAnswer = askCheckoutUrl(cartId);\n let url = await accountCheckoutUrl();\n if (!url) {\n const answer = await cartAnswer;\n if (answer.kind === 'failed') throw answer.error;\n url = answer.url;\n }\n if (!url) throw new TetherError('No checkoutUrl (cart empty or expired)');\n if (!customer.accessToken) return url;\n return `${url}${url.includes('?') ? '&' : '?'}logged_in=true`;\n}\n\n/**\n * A new tab's `opener` gives the checkout page a handle on this one; a browser that doesn't let a script clear it\n * leaves the tab as it opened.\n *\n * @param {Window} tab\n */\nfunction detachOpenerIfAllowed(tab) {\n try {\n tab.opener = null;\n } catch {\n // The browser keeps `opener` read-only: see the function's comment.\n }\n}\n\n/**\n * Goes to Shopify's checkout. With `_blank` the tab opens inside the click (Safari blocks `window.open` after an\n * await) and gets its URL once there is one.\n *\n * @param {CheckoutTarget} target\n * @returns {Promise<string | null>} The checkout URL, `null` with nothing to check out or after a reported failure.\n */\nexport async function checkout(target = cfg.checkoutTarget) {\n const cartId = savedCartId();\n const cart = currentCart();\n if (!cartId || (cart && !cart.totalQuantity)) return null;\n const tab = target === '_blank' ? window.open('', '_blank') : null;\n if (tab) detachOpenerIfAllowed(tab);\n try {\n const url = await checkoutUrl(cartId);\n if (!isHttpsUrl(url)) throw new TetherError('The checkout URL is not https: not opened');\n emit('checkout', { url, cart: currentCart() });\n if (tab && !tab.closed) tab.location.href = url;\n else window.location.href = url;\n return url;\n } catch (error) {\n tab?.close();\n reportError(error, 'checkout failed');\n return null;\n }\n}\n", "/**\n * ProductScope: everything inside [tether-product=\"<handle>\"] binds to one Shopify product: options, variants,\n * quantity, subscriptions and add to cart. The scope holds the visitor's choice and the actions on it;\n * `product-state.js` derives what the choice shows, `product-render.js` and `variant-render.js` write it, and\n * `product-events.js` turns clicks and changes into actions.\n */\nimport { cfg } from './config.js';\nimport {\n attr,\n sel,\n get,\n has,\n scoped,\n emit,\n setText,\n notifyLayoutChanged,\n watchImages,\n parseJSONAttr,\n toAttributes,\n} from './dom.js';\nimport { Cart } from './cart.js';\nimport { allPlans, allocationFor, findPlan, GID } from './selling-plans.js';\nimport { initialChoice, normalisePurchase, productView, selectionOf } from './product-state.js';\nimport { writeProduct } from './product-render.js';\nimport { writeVariant } from './variant-render.js';\nimport { bindProductEvents } from './product-events.js';\n/** @import { Product, ProductVariant } from './fragments.js' */\n/** @import { PlanInGroup } from './selling-plans.js' */\n/** @import { Purchase, Selection } from './product-state.js' */\n\n/**\n * @typedef {object} CartLineInput What a scope adds to the cart.\n * @property {string} merchandiseId\n * @property {number} quantity\n * @property {string} [sellingPlanId]\n * @property {{ key: string, value: string }[]} [attributes]\n */\n\n/** @type {WeakMap<Element, ProductScope>} */\nexport const scopes = new WeakMap();\n\nconst productSelector = () => sel('product');\n\n/**\n * Option names as written in the markup (the build's language), by product handle. In another language Shopify\n * translates them (Size \u2192 Gr\u00F6\u00DFe), so markup names that aren't the product's are matched by position.\n *\n * @type {Map<string, string[]>}\n */\nconst knownOptionNames = new Map();\n\n/** @param {readonly Pick<Product, 'handle' | 'options'>[]} products */\nexport function rememberOptionNames(products) {\n products.forEach((product) => {\n if (!knownOptionNames.has(product.handle)) {\n knownOptionNames.set(\n product.handle,\n product.options.map((option) => option.name),\n );\n }\n });\n}\n\n/**\n * @param {Element} el\n * @returns {el is HTMLInputElement}\n */\nconst isInput = (el) => el.tagName === 'INPUT';\n\n/**\n * @param {Element} el\n * @returns {el is HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement}\n */\nconst isField = (el) => el.tagName === 'INPUT' || el.tagName === 'SELECT' || el.tagName === 'TEXTAREA';\n\n/**\n * @param {HTMLElement} el A `tether-line-attribute` field.\n * @returns {string | null} Its value for the cart line; `null` for an unchecked or empty field.\n */\nfunction lineAttributeValue(el) {\n if (isInput(el) && el.type === 'checkbox') {\n if (!el.checked) return null;\n return el.value && el.value !== 'on' ? el.value : 'Yes';\n }\n if (isInput(el) && el.type === 'radio') return el.checked ? el.value : null;\n return (isField(el) && el.value) || null;\n}\n\nexport class ProductScope {\n /**\n * @param {HTMLElement} root\n * @param {Product} product\n */\n constructor(root, product) {\n this.root = root;\n this.product = product;\n this.plans = allPlans(product);\n const params = new URLSearchParams(window.location.search);\n const choice = initialChoice(product, {\n variant: params.get('variant') || get(root, 'variant'),\n sellingPlan: params.get('selling_plan'),\n defaultPlan: get(root, 'default-plan'),\n defaultPurchase: get(root, 'default-purchase') || cfg.defaultPurchase,\n });\n /** @type {Selection} */\n this.selected = choice.selected;\n /** @type {Purchase} */\n this.purchaseChoice = choice.purchase;\n /** @type {ProductVariant | null} */\n this.variant = null;\n this.quantity = has(root, 'quantity') ? Math.max(0, parseInt(get(root, 'quantity') ?? '', 10) || 0) : 1;\n\n scopes.set(root, this);\n root.setAttribute(attr('state'), 'ready');\n root.removeAttribute(attr('error'));\n this.renderProduct();\n bindProductEvents(this);\n this.renderVariant();\n\n watchImages(root, 'product');\n notifyLayoutChanged('product');\n emit('product-ready', { product, scope: this }, root);\n }\n\n /**\n * New data for the same product (a country switch). Keeps the visitor's choice.\n *\n * @param {Product} product\n */\n update(product) {\n const variantId = this.variant?.id;\n this.product = product;\n this.plans = allPlans(product);\n const same = product.variants.nodes.find((variant) => variant.id === variantId);\n if (same) this.selected = selectionOf(same);\n this.root.setAttribute(attr('state'), 'ready');\n this.root.removeAttribute(attr('error'));\n this.renderProduct();\n this.renderVariant();\n notifyLayoutChanged('product');\n emit('product-updated', { product, scope: this }, this.root);\n }\n\n /**\n * @param {string} selector\n * @returns {HTMLElement[]} Matches in this scope, including the root itself (a card link with tether-bind=\"link\").\n */\n $(selector) {\n const inner = scoped(this.root, selector, productSelector());\n return this.root.matches(selector) ? [this.root, ...inner] : inner;\n }\n\n /**\n * @param {string | null} authored An option name in the markup.\n * @returns {string} The product's option of that name, or at that position in the build's language.\n */\n optName(authored) {\n if (!authored) return '';\n const { options } = this.product;\n if (options.some((option) => option.name === authored)) return authored;\n const index = (knownOptionNames.get(this.product.handle) ?? []).indexOf(authored);\n return options[index]?.name ?? authored;\n }\n\n /** @returns {'one-time' | 'subscription'} */\n get purchase() {\n return this.purchaseChoice.kind;\n }\n\n /** @param {string} kind */\n set purchase(kind) {\n const wanted = kind === 'subscription' ? 'subscription' : 'one-time';\n this.purchaseChoice = normalisePurchase(this.product, this.variant, { kind: wanted, planId: this.planId });\n }\n\n /** @returns {string | null} The plan bought on, or offered while buying once. */\n get planId() {\n return this.purchaseChoice.planId;\n }\n\n /** @param {string | null} planId */\n set planId(planId) {\n this.purchaseChoice = normalisePurchase(this.product, this.variant, { kind: this.purchase, planId });\n }\n\n /** @returns {PlanInGroup | null} */\n get plan() {\n return this.plans.find((plan) => plan.id === this.planId) ?? null;\n }\n\n /** True when the current variant can be bought on a plan. */\n get subscriptionAvailable() {\n return this.plans.some((plan) => allocationFor(this.variant, plan.id));\n }\n\n get isSubscription() {\n return this.purchase === 'subscription' && allocationFor(this.variant, this.planId) !== null;\n }\n\n /** @returns {CartLineInput | null} What would be added to the cart right now. */\n getLine() {\n if (!this.variant) return null;\n /** @type {CartLineInput} */\n const line = { merchandiseId: this.variant.id, quantity: this.quantity };\n if (this.isSubscription && this.planId) line.sellingPlanId = this.planId;\n const attributes = this.collectAttributes();\n if (attributes.length) line.attributes = attributes;\n return line;\n }\n\n /** @returns {{ key: string, value: string }[]} `tether-line-attributes` and the filled `tether-line-attribute` fields. */\n collectAttributes() {\n // The site's own JSON: toAttributes writes every value with String(), whatever its type.\n const json = /** @type {Parameters<typeof toAttributes>[0]} */ (parseJSONAttr(this.root, 'line-attributes'));\n const fixed = toAttributes(json);\n const fields = this.$(sel('line-attribute')).flatMap((el) => {\n const value = lineAttributeValue(el);\n return value === null ? [] : [{ key: get(el, 'line-attribute') ?? '', value }];\n });\n return [...fixed, ...fields];\n }\n\n /**\n * Selects an option value. A combination no variant has moves to the closest variant with the value: the most other\n * choices kept, then one for sale.\n *\n * @param {string} name\n * @param {string} value\n */\n select(name, value) {\n if (this.selected[name] === value) return;\n const withValue = this.product.variants.nodes.filter((variant) =>\n variant.selectedOptions.some((option) => option.name === name && option.value === value),\n );\n const [firstWithValue] = withValue;\n // A value no variant has: nothing to select, the visitor's choice stays.\n if (!firstWithValue) return;\n const next = { ...this.selected, [name]: value };\n if (!withValue.some((variant) => variant.selectedOptions.every((option) => next[option.name] === option.value))) {\n const score = (/** @type {ProductVariant} */ variant) => {\n const kept = variant.selectedOptions.filter(\n (option) => option.name !== name && this.selected[option.name] === option.value,\n ).length;\n // One kept choice outweighs being for sale.\n return kept * 2 + (variant.availableForSale ? 1 : 0);\n };\n const closest = withValue.reduce(\n (best, variant) => (score(variant) > score(best) ? variant : best),\n firstWithValue,\n );\n Object.assign(next, selectionOf(closest));\n }\n this.selected = next;\n this.renderVariant();\n }\n\n /** @param {string} id A variant gid or numeric id. */\n selectVariant(id) {\n const variant = this.product.variants.nodes.find((candidate) => candidate.id === GID.variant(id));\n if (!variant) return;\n this.selected = selectionOf(variant);\n this.renderVariant();\n }\n\n /** @param {string | null} mode `subscription`, else buying once. */\n setPurchase(mode) {\n const kind = mode === 'subscription' ? 'subscription' : 'one-time';\n const next = normalisePurchase(this.product, this.variant, { kind, planId: this.planId });\n // The product decides when the wanted kind isn't possible (no plans, or a plan required).\n if (next.kind === this.purchase) return;\n this.purchaseChoice = next;\n this.renderVariant();\n }\n\n /** @param {string | null} ref A plan id, numeric id, name or option value. */\n selectPlan(ref) {\n const plan = findPlan(this.product, ref);\n if (!plan) return;\n this.purchaseChoice = { kind: 'subscription', planId: plan.id };\n this.renderVariant();\n }\n\n /** @param {number | string} quantity */\n setQuantity(quantity) {\n const minimum = has(this.root, 'quantity') ? 0 : 1;\n this.quantity = Math.max(minimum, parseInt(String(quantity), 10) || 0);\n this.$(sel('qty')).forEach((el) => {\n setText(el, this.quantity);\n });\n this.renderVariant();\n }\n\n /** @returns {Promise<unknown>} The cart after adding; `null` when the variant can't be added. */\n async addToCart() {\n if (!this.variant?.availableForSale) return null;\n const line = this.getLine();\n if (!line || line.quantity < 1) return null;\n const cart = await Cart.add(line);\n emit('product-added', { product: this.product, variant: this.variant, line }, this.root);\n return cart;\n }\n\n /** Learns the markup's option names when they are the product's, then writes the product. */\n renderProduct() {\n const { product } = this;\n if (!knownOptionNames.has(product.handle)) {\n const authored = this.$(`${sel('option-list')},select${sel('option')}`).map(\n (el) => get(el, 'option-list') || get(el, 'option'),\n );\n if (authored.some((name) => product.options.some((option) => option.name === name))) {\n rememberOptionNames([product]);\n }\n }\n writeProduct(this);\n }\n\n /** Derives the view of the current choice, keeps its variant, selection and purchase, and writes it. */\n renderVariant() {\n const view = productView(\n this.product,\n { selected: this.selected, purchase: this.purchaseChoice, quantity: this.quantity },\n cfg.lowStock,\n );\n if (!view) {\n this.variant = null;\n return;\n }\n this.variant = view.variant;\n this.selected = view.selected;\n this.purchaseChoice = view.purchase;\n writeVariant(this, view);\n emit(\n 'variant-changed',\n {\n product: this.product,\n variant: view.variant,\n selected: { ...view.selected },\n purchase: view.purchase.kind,\n sellingPlanId: view.isSubscription ? view.purchase.planId : null,\n },\n this.root,\n );\n }\n}\n", "/**\n * What a product scope shows for the visitor's choice: the variant, the purchase it is bought as, its prices, the\n * text of every `tether-bind` and every `tether-show` condition. Pure, no DOM and no config: the browser scope\n * (`product.js`) and the server's `initialState()` (`initial.js`) derive their view here, so a server-rendered page\n * shows what the script shows when it takes over.\n */\nimport {\n GID,\n allPlans,\n allocationFor,\n findPlan,\n planAdjustment,\n planCheckoutCharge,\n planPrice,\n planSavings,\n} from './selling-plans.js';\n/** @import { Money } from './shopify-values.js' */\n/** @import { Product, ProductVariant } from './fragments.js' */\n/** @import { PlanInGroup } from './selling-plans.js' */\n\n/** @typedef {Record<string, string>} Selection Option name \u2192 chosen value. */\n/**\n * How the visitor buys. Buying once still names the product's plan when it has plans: the plan the subscription\n * binds (`subscription-price`, `plan-name`) offer next to the one-time price, and the one subscribing switches to.\n *\n * @typedef {{ kind: 'one-time', planId: string | null } | { kind: 'subscription', planId: string }} Purchase\n */\n/**\n * @typedef {object} ProductChoice What the visitor chose, before it is checked against the product.\n * @property {Selection} selected\n * @property {Purchase} purchase\n * @property {number} quantity\n */\n/**\n * @typedef {'in-stock' | 'out-of-stock' | 'backorder' | 'on-sale' | 'not-on-sale' | 'has-variants' | 'single-variant'\n * | 'low-stock' | 'plenty-in-stock' | 'subscription-available' | 'subscription-unavailable' | 'subscription-only'\n * | 'one-time-available' | 'subscription-selected' | 'one-time-selected' | 'has-savings'} ShowCondition\n */\n/**\n * @typedef {object} ProductView\n * @property {ProductVariant} variant\n * @property {Selection} selected The selection, matching `variant`.\n * @property {Purchase} purchase The choice, made valid for the product and `variant`.\n * @property {PlanInGroup | null} plan The purchase's plan, offered or chosen.\n * @property {boolean} isSubscription The line is bought on `plan`: subscription chosen and the variant is on it.\n * @property {boolean} subscriptionAvailable The variant is on at least one plan.\n * @property {number} quantity\n * @property {Money} price What one item costs as bought.\n * @property {Money | null} compareAtPrice Only when on sale.\n * @property {{ amount: Money | null, percentage: number }} savings What `plan` saves on the one-time price.\n * @property {Record<ShowCondition, boolean>} show\n */\n/**\n * @typedef {object} Formatters How the caller writes values as text.\n * @property {(money: Money | null) => string} money\n * @property {(percentage: number) => string} percent\n */\n/** @typedef {string | number | null | undefined} BindText What a bind writes; `null` and `undefined` clear it. */\n\n/** Money arithmetic works in hundredths, the precision Tether shows Shopify's amounts in. */\nconst MINOR_UNITS_PER_UNIT = 100;\nconst PERCENT = 100;\n\n/** @param {Money} money */\nconst toMinorUnits = (money) => Math.round(parseFloat(money.amount) * MINOR_UNITS_PER_UNIT);\n\n/**\n * @param {number} minorUnits\n * @param {string} currencyCode\n * @returns {Money}\n */\nconst fromMinorUnits = (minorUnits, currencyCode) => ({\n amount: (minorUnits / MINOR_UNITS_PER_UNIT).toFixed(2),\n currencyCode,\n});\n\n/**\n * @param {Money} money\n * @param {number} quantity\n */\nconst timesQuantity = (money, quantity) => fromMinorUnits(toMinorUnits(money) * quantity, money.currencyCode);\n\n/**\n * @param {ProductVariant} variant\n * @returns {Selection}\n */\nexport const selectionOf = (variant) =>\n Object.fromEntries(variant.selectedOptions.map((option) => [option.name, option.value]));\n\n/**\n * @param {Product} product\n * @param {Selection} selected\n * @returns {ProductVariant | null} The variant with exactly these option values.\n */\nfunction findVariant(product, selected) {\n return (\n product.variants.nodes.find((variant) =>\n variant.selectedOptions.every((option) => selected[option.name] === option.value),\n ) ?? null\n );\n}\n\n/**\n * @param {Product} product\n * @param {Selection} selected\n * @param {string} name An option name.\n * @param {string} value\n * @returns {boolean} True when a variant for sale has this value and the other selected values.\n */\nexport function isValueAvailable(product, selected, name, value) {\n return product.variants.nodes.some(\n (variant) =>\n variant.availableForSale &&\n variant.selectedOptions.every((option) =>\n option.name === name ? option.value === value : selected[option.name] === option.value,\n ),\n );\n}\n\n/**\n * The purchase made valid for the product and variant: one-time without plans, a subscription when the product\n * requires one, and a plan the variant is on when it is on any (else a plan of the product, for the binds to offer).\n *\n * @param {Product} product\n * @param {ProductVariant | null} variant\n * @param {{ kind: Purchase['kind'], planId: string | null }} wanted\n * @returns {Purchase}\n */\nexport function normalisePurchase(product, variant, wanted) {\n const plans = allPlans(product);\n const known = plans.find((plan) => plan.id === wanted.planId) ?? plans[0];\n if (!known) return { kind: 'one-time', planId: null };\n const onVariant = allocationFor(variant, known.id)\n ? known\n : (plans.find((plan) => allocationFor(variant, plan.id)) ?? known);\n if (product.requiresSellingPlan || wanted.kind === 'subscription')\n return { kind: 'subscription', planId: onVariant.id };\n return { kind: 'one-time', planId: onVariant.id };\n}\n\n/**\n * @typedef {object} InitialChoiceOptions\n * @property {string | null | undefined} [variant] A variant id or gid (`?variant=`); the first variant for sale without.\n * @property {string | null | undefined} [sellingPlan] A plan to subscribe on (`?selling_plan=`).\n * @property {string | null | undefined} [defaultPlan] The plan offered first, by id, name or option value.\n * @property {string | null | undefined} [defaultPurchase] `subscription` subscribes; anything else buys once.\n */\n\n/**\n * What a product starts with before the visitor chooses anything.\n *\n * @param {Product} product\n * @param {InitialChoiceOptions} options\n * @returns {Omit<ProductChoice, 'quantity'>}\n */\nexport function initialChoice(product, { variant, sellingPlan, defaultPlan, defaultPurchase }) {\n const variants = product.variants.nodes;\n const wantedId = GID.variant(variant);\n const start =\n variants.find((candidate) => candidate.id === wantedId) ??\n variants.find((candidate) => candidate.availableForSale) ??\n variants[0] ??\n null;\n const fromUrl = findPlan(product, sellingPlan);\n const offered = fromUrl ?? findPlan(product, defaultPlan);\n const kind = fromUrl || defaultPurchase === 'subscription' ? 'subscription' : 'one-time';\n return {\n selected: start ? selectionOf(start) : {},\n purchase: normalisePurchase(product, start, { kind, planId: offered?.id ?? null }),\n };\n}\n\n/**\n * @param {ProductVariant} variant\n * @param {number} lowStock\n * @param {number} variantCount\n * @param {Pick<ProductView, 'isSubscription' | 'subscriptionAvailable' | 'compareAtPrice' | 'savings'>} sale\n * @param {boolean} requiresSellingPlan\n * @returns {Record<ShowCondition, boolean>}\n */\nfunction showConditions(variant, lowStock, variantCount, sale, requiresSellingPlan) {\n const stock = variant.quantityAvailable;\n const low = stock != null && stock > 0 && stock <= lowStock;\n const onSale = sale.compareAtPrice !== null;\n return {\n 'in-stock': variant.availableForSale,\n 'out-of-stock': !variant.availableForSale,\n backorder: variant.availableForSale && variant.currentlyNotInStock,\n 'on-sale': onSale,\n 'not-on-sale': !onSale,\n 'has-variants': variantCount > 1,\n 'single-variant': variantCount === 1,\n 'low-stock': low,\n 'plenty-in-stock': variant.availableForSale && !low,\n 'subscription-available': sale.subscriptionAvailable,\n 'subscription-unavailable': !sale.subscriptionAvailable,\n 'subscription-only': requiresSellingPlan,\n 'one-time-available': !requiresSellingPlan,\n 'subscription-selected': sale.isSubscription,\n 'one-time-selected': !sale.isSubscription,\n 'has-savings': sale.isSubscription ? sale.savings.percentage > 0 : onSale,\n };\n}\n\n/**\n * The view for the visitor's choice. A selection no variant has falls back to the first variant.\n *\n * @param {Product} product\n * @param {ProductChoice} choice\n * @param {number} lowStock `low-stock` at this many or fewer.\n * @returns {ProductView | null} `null` for a product without variants.\n */\nexport function productView(product, choice, lowStock) {\n const exact = findVariant(product, choice.selected);\n const variant = exact ?? product.variants.nodes[0];\n if (!variant) return null;\n const purchase = normalisePurchase(product, variant, choice.purchase);\n const { planId } = purchase;\n const plans = allPlans(product);\n const allocation = purchase.kind === 'subscription' ? allocationFor(variant, planId) : null;\n // The plan helpers fall back to the one-time price only without a variant, which `variant` rules out.\n const price = allocation ? (planPrice(variant, planId) ?? variant.price) : variant.price;\n const compareAt = allocation?.priceAdjustments[0]?.compareAtPrice ?? variant.compareAtPrice;\n const sale = {\n isSubscription: allocation !== null,\n subscriptionAvailable: plans.some((plan) => allocationFor(variant, plan.id)),\n compareAtPrice: compareAt && parseFloat(compareAt.amount) > parseFloat(price.amount) ? compareAt : null,\n savings: planSavings(variant, planId),\n };\n return {\n ...sale,\n variant,\n selected: exact ? choice.selected : selectionOf(variant),\n purchase,\n plan: plans.find((plan) => plan.id === planId) ?? null,\n quantity: choice.quantity,\n price,\n show: showConditions(variant, lowStock, product.variants.nodes.length, sale, product.requiresSellingPlan),\n };\n}\n\n/**\n * The `tether-bind` values that follow the variant and purchase. Thunks, so only the binds on the page are computed.\n *\n * @param {ProductView} view\n * @param {Formatters} format\n * @returns {Map<string, () => BindText>}\n */\nexport function variantBindTexts(view, format) {\n const { variant, plan, price, compareAtPrice, quantity } = view;\n const planId = view.purchase.planId;\n // Prices for the quantity count one item when it is 0 (an optional bundle item).\n const forQuantity = (/** @type {Money} */ money) => timesQuantity(money, Math.max(1, quantity));\n const checkoutCharge = () => {\n const charge = view.isSubscription ? (planCheckoutCharge(variant, planId) ?? price) : price;\n return format.money(forQuantity(charge));\n };\n const discountPercentage = () => {\n if (!compareAtPrice) return '0%';\n return `${Math.round((1 - parseFloat(price.amount) / parseFloat(compareAtPrice.amount)) * PERCENT)}%`;\n };\n const discountAmount = () => {\n if (!compareAtPrice) return '';\n return format.money(fromMinorUnits(toMinorUnits(compareAtPrice) - toMinorUnits(price), price.currencyCode));\n };\n /** @type {Record<string, () => BindText>} */\n const texts = {\n price: () => format.money(price),\n 'total-price': () => format.money(forQuantity(price)),\n 'one-time-price': () => format.money(variant.price),\n 'subscription-price': () => format.money(planId ? planPrice(variant, planId) : null),\n 'subscription-savings': () => format.percent(view.savings.percentage),\n 'subscription-savings-amount': () => format.money(view.savings.amount),\n 'checkout-charge': checkoutCharge,\n 'plan-name': () => plan?.name,\n 'plan-description': () => plan?.description,\n 'plan-group': () => plan?.group.name,\n 'compare-at-price': () => format.money(compareAtPrice),\n 'unit-price': () => format.money(variant.unitPrice),\n 'discount-percentage': discountPercentage,\n 'discount-amount': discountAmount,\n 'variant-title': () => variant.title,\n 'variant-id': () => variant.id,\n sku: () => variant.sku,\n barcode: () => variant.barcode,\n stock: () => variant.quantityAvailable,\n quantity: () => quantity,\n };\n return new Map(Object.entries(texts));\n}\n/**\n * The `tether-plan-bind` values of one plan in a plan list, for the variant.\n *\n * @param {ProductVariant} variant\n * @param {string} planId The list item's `tether-plan-value`.\n * @param {PlanInGroup | undefined} plan The product's plan with that id.\n * @param {Formatters} format\n * @returns {Map<string, () => BindText>}\n */\nexport function planBindTexts(variant, planId, plan, format) {\n const adjustmentText = () => {\n const adjustment = planAdjustment(plan);\n if (!adjustment) return '';\n return adjustment.type === 'percentage' ? `${adjustment.value}%` : format.money(adjustment.value);\n };\n /** @type {Record<string, () => BindText>} */\n const texts = {\n name: () => plan?.name,\n // The option values alone (\"1 month\"), without the price text a store may put in the plan name.\n option: () => (plan?.options ?? []).map((option) => option.value).join(', '),\n description: () => plan?.description,\n price: () => format.money(planPrice(variant, planId)),\n savings: () => format.percent(planSavings(variant, planId).percentage),\n 'savings-amount': () => format.money(planSavings(variant, planId).amount),\n adjustment: adjustmentText,\n };\n return new Map(Object.entries(texts));\n}\n", "/**\n * The DOM writes of a product scope that depend on the product alone, once per product: its binds, the option and\n * plan lists and the options of its selects. `variant-render.js` writes what follows the visitor's choice.\n */\nimport {\n attr,\n sel,\n get,\n has,\n qsa,\n formatMoney,\n formatDate,\n setText,\n setImage,\n setStoreHtml,\n show,\n repeat,\n hasTemplate,\n sameImage,\n productUrl,\n} from './dom.js';\n/** @import { Product, Image } from './fragments.js' */\n/** @import { PlanInGroup } from './selling-plans.js' */\n\n/**\n * @typedef {object} RenderScope The product scope as its renders see it.\n * @property {HTMLElement} root\n * @property {Product} product\n * @property {PlanInGroup[]} plans\n * @property {(selector: string) => HTMLElement[]} $ Matches in this scope, the root included.\n * @property {(authored: string | null) => string} optName The product's option name for one written in the markup.\n */\n/**\n * The shape `fragments.js` selects for an option value's swatch, which it types as `unknown`.\n *\n * @typedef {{ color: string | null, image: { previewImage: Image | null } | null } | null} Swatch\n */\n\n/** `tether-bind=\"image:2\"`: the second product image. */\nconst NTH_IMAGE_BIND = /^image:(\\d+)$/;\nconst METAFIELD_BIND = 'metafield:';\nconst MULTI_LINE_METAFIELD = /^(rich_text|multi_line_text)_field$/;\n/** `tether-plan-list` values that list every plan, not one group: Webflow's Designer can't always leave it empty. */\nconst ALL_PLAN_GROUPS = ['', 'true', 'all', '*'];\n\n/**\n * @param {Element} el\n * @returns {el is HTMLSelectElement}\n */\nexport const isSelect = (el) => el.tagName === 'SELECT';\n\n/**\n * @param {RenderScope} scope\n * @param {string} selector\n * @returns {HTMLSelectElement[]} The `<select>` elements in the scope that match `selector`.\n */\nexport const selectsIn = (scope, selector) => scope.$(`select${selector}`).filter(isSelect);\n\n/**\n * Leaves a server-rendered gallery with the same images as it is.\n *\n * @param {HTMLElement} el\n * @param {Product} product\n */\nfunction renderGallery(el, product) {\n const images = product.images.nodes;\n const rendered = [...el.children].map((node) => (node.tagName === 'IMG' ? node : node.querySelector('img')));\n const same =\n !hasTemplate(el) &&\n rendered.length === images.length &&\n rendered.every((img, index) => sameImage(img?.getAttribute('src'), images[index]?.url));\n if (same) return;\n repeat(el, images, (node, image) => {\n const target = node.matches(`img,${sel('bind', 'image')}`) ? node : (qsa(node, 'img')[0] ?? node);\n setImage(target, image.url, image.altText || product.title);\n });\n}\n\n/**\n * @param {HTMLElement} el\n * @param {Product} product\n * @param {string} ref `namespace.key`\n */\nfunction renderMetafield(el, product, ref) {\n const dot = ref.indexOf('.');\n const namespace = ref.slice(0, dot);\n const key = ref.slice(dot + 1);\n const metafield = (product.metafields ?? []).find((field) => field?.namespace === namespace && field.key === key);\n if (!metafield) {\n setText(el, '');\n return;\n }\n const image = metafield.reference?.image;\n if (image) {\n setImage(el, image.url, image.altText);\n return;\n }\n if (MULTI_LINE_METAFIELD.test(metafield.type)) el.style.whiteSpace = 'pre-line';\n setText(el, metafield.value);\n}\n\n/** @type {Map<string, (product: Product) => string>} The product binds written as text. */\nconst PRODUCT_TEXTS = new Map(\n Object.entries({\n title: (product) => product.title,\n 'description-text': (product) => product.description,\n vendor: (product) => product.vendor,\n type: (product) => product.productType,\n handle: (product) => product.handle,\n 'published-at': (product) => formatDate(product.publishedAt),\n 'min-price': (product) => formatMoney(product.priceRange.minVariantPrice),\n 'max-price': (product) => formatMoney(product.priceRange.maxVariantPrice),\n }),\n);\n\n/**\n * @param {HTMLElement} el\n * @param {Product} product\n */\nfunction renderTags(el, product) {\n const exclude = (el.getAttribute('exclude') ?? '')\n .split(',')\n .map((tag) => tag.trim())\n .filter(Boolean);\n const tags = product.tags.filter((tag) => !exclude.includes(tag));\n repeat(el, tags, (node, tag) => {\n setText(node, tag);\n });\n}\n\n/**\n * A `tether-bind` of the product itself; binds of the variant are left to `writeVariant`.\n *\n * @param {HTMLElement} el\n * @param {string} key\n * @param {Product} product\n */\nfunction renderProductBind(el, key, product) {\n const text = PRODUCT_TEXTS.get(key);\n if (text) {\n setText(el, text(product));\n return;\n }\n switch (key) {\n case 'description':\n setStoreHtml(el, product.descriptionHtml);\n break;\n case 'featured-image':\n setImage(el, product.featuredImage?.url, product.featuredImage?.altText || product.title);\n break;\n case 'url':\n case 'link':\n el.setAttribute('href', productUrl(product.handle, product.id));\n if (key === 'url' && !el.firstElementChild && !el.textContent.trim()) setText(el, product.title);\n break;\n case 'images':\n renderGallery(el, product);\n break;\n case 'tags':\n renderTags(el, product);\n break;\n default:\n renderIndexedBind(el, key, product);\n }\n}\n\n/**\n * `image:<n>` (falling back to the featured image) and `metafield:<namespace.key>`.\n *\n * @param {HTMLElement} el\n * @param {string} key\n * @param {Product} product\n */\nfunction renderIndexedBind(el, key, product) {\n const nth = NTH_IMAGE_BIND.exec(key);\n if (nth) {\n const image = product.images.nodes[Number(nth[1]) - 1] ?? product.featuredImage;\n setImage(el, image?.url, image?.altText || product.title);\n } else if (key.startsWith(METAFIELD_BIND)) {\n renderMetafield(el, product, key.slice(METAFIELD_BIND.length));\n }\n}\n\n/** @param {RenderScope} scope */\nfunction renderOptionLists(scope) {\n const { product } = scope;\n scope.$(sel('option-list')).forEach((container) => {\n const name = scope.optName(get(container, 'option-list'));\n const option = product.options.find((candidate) => candidate.name === name);\n if (!option || (option.optionValues.length <= 1 && has(container, 'hide-single'))) {\n show(container, false);\n return;\n }\n repeat(container, option.optionValues, (node, value) => {\n node.setAttribute(attr('option-value'), value.name);\n const text = qsa(node, sel('bind', 'option-value'))[0];\n if (text) setText(text, value.name);\n else if (!node.firstElementChild) setText(node, value.name);\n const swatchEl = qsa(node, sel('bind', 'swatch'))[0];\n // fragments.js selects `swatch { color image { previewImage { \u2026 } } }`.\n const swatch = /** @type {Swatch} */ (value.swatch);\n if (!swatchEl || !swatch) return;\n if (swatch.color) swatchEl.style.backgroundColor = swatch.color;\n if (swatch.image?.previewImage) setImage(swatchEl, swatch.image.previewImage.url, value.name);\n });\n });\n}\n\n/** @param {RenderScope} scope */\nfunction renderSelects(scope) {\n const { product } = scope;\n selectsIn(scope, sel('option')).forEach((select) => {\n const option = product.options.find((candidate) => candidate.name === scope.optName(get(select, 'option')));\n if (!option) {\n show(select, false);\n return;\n }\n select.replaceChildren(...option.optionValues.map((value) => new Option(value.name, value.name)));\n });\n selectsIn(scope, sel('variant-select')).forEach((select) => {\n select.replaceChildren(...product.variants.nodes.map((variant) => new Option(variant.title, variant.id)));\n });\n selectsIn(scope, sel('plan')).forEach((select) => {\n const plans = scope.plans.map((plan) => new Option(plan.name, plan.id));\n const oneTime = !product.requiresSellingPlan && get(select, 'plan') !== 'subscription-only';\n const oneTimeLabel = select.getAttribute(attr('one-time-label')) || 'One-time purchase';\n select.replaceChildren(...(oneTime ? [new Option(oneTimeLabel, '')] : []), ...plans);\n });\n}\n\n/** @param {RenderScope} scope */\nfunction renderPlanLists(scope) {\n scope.$(sel('plan-list')).forEach((container) => {\n // The value is a selling plan group's name, or one of ALL_PLAN_GROUPS.\n const raw = (get(container, 'plan-list') ?? '').trim();\n const group = ALL_PLAN_GROUPS.includes(raw.toLowerCase()) ? null : raw;\n const plans = scope.plans.filter((plan) => !group || plan.group.name === group);\n repeat(container, plans, (node, plan) => {\n node.setAttribute(attr('plan-value'), plan.id);\n if (!node.firstElementChild && !node.querySelector(sel('plan-bind'))) setText(node, plan.name);\n });\n });\n}\n\n/**\n * Writes what depends on the product alone: its binds, option and plan lists and the selects' options.\n *\n * @param {RenderScope} scope\n */\nexport function writeProduct(scope) {\n scope.$(sel('bind')).forEach((el) => {\n renderProductBind(el, get(el, 'bind') ?? '', scope.product);\n });\n renderOptionLists(scope);\n renderSelects(scope);\n renderPlanLists(scope);\n}\n", "/**\n * Where a product scope gets its key from, and the state of a scope (loading, ready, error, not found), so a failing\n * API never leaves a broken page.\n */\nimport { attr, sel, get, scoped, show } from './dom.js';\n\n/**\n * @typedef {object} ProductKeySource\n * @property {string | null} key The product to load; `null` when the attribute or the page URL has none.\n * @property {boolean} fromUrl The key comes from the page URL (`url:\u2026`).\n * @property {string} raw The attribute's value as written.\n */\n\n/** @typedef {'loading' | 'ready' | 'error' | 'not-found'} ScopeStatus */\n\nconst URL_SOURCE = 'url:';\n\n/**\n * A path segment as text. A malformed escape (`%E0%A4%A`) is kept as written, which is how the browser shows it.\n *\n * @param {string} segment\n */\nfunction decodePathSegment(segment) {\n try {\n return decodeURIComponent(segment);\n } catch (error) {\n if (error instanceof URIError) return segment;\n throw error;\n }\n}\n\n/**\n * Reads a `tether-product` value:\n * - `coffee-box`: a handle, numeric id, gid or product URL;\n * - `url:handle`: `?handle=` from the page URL (any parameter: `url:p` reads `?p=`);\n * - `url:path`: the last segment of the page path (`/shop/coffee-box` \u2192 `coffee-box`).\n *\n * @param {Element} el\n * @param {Pick<Location, 'pathname' | 'search'>} [location]\n * @param {string} [name] The attribute, without prefix.\n * @returns {ProductKeySource}\n */\nexport function resolveProductKey(el, location = window.location, name = 'product') {\n const raw = (get(el, name) ?? '').trim();\n if (!raw.toLowerCase().startsWith(URL_SOURCE)) return { key: raw || null, fromUrl: false, raw };\n const source = raw.slice(URL_SOURCE.length).trim();\n let key;\n if (source.toLowerCase() === 'path') {\n const segments = location.pathname.split('/').filter(Boolean);\n const segment = segments[segments.length - 1];\n key = segment === undefined ? null : decodePathSegment(segment);\n } else {\n key = new URLSearchParams(location.search).get(source || 'handle');\n }\n return { key: key?.trim() || null, fromUrl: true, raw };\n}\n\n/** @type {readonly ScopeStatus[]} The values of `tether-show` that follow the scope's state. */\nexport const STATUS_KEYS = ['loading', 'ready', 'error', 'not-found'];\n\n/**\n * @param {unknown} value\n * @returns {value is ScopeStatus}\n */\nconst isScopeStatus = (value) => STATUS_KEYS.some((status) => status === value);\n\n/**\n * @param {unknown} error\n * @returns {unknown} The error's `code` (a `TetherError` has one).\n */\nconst codeOf = (error) => (typeof error === 'object' && error !== null && 'code' in error ? error.code : undefined);\n\n/**\n * @param {unknown} error\n * @returns {boolean} True for a `TetherError` with code `NOT_FOUND`.\n */\nexport const isNotFound = (error) => codeOf(error) === 'NOT_FOUND';\n\n/** @returns {string} The selector of every scope that owns its state elements; the nearest one wins. */\nexport const boundary = () =>\n ['product', 'collection', 'products', 'recommendations'].map((name) => sel(name)).join(',');\n\n/**\n * @param {Element} el\n * @param {Element} root\n * @returns {boolean} True when `el` belongs to the scope `root`, not to a scope nested in it.\n */\nexport const ownedBy = (el, root) => el === root || el.parentElement?.closest(boundary()) === root;\n\n/**\n * @param {unknown} error\n * @returns {string} The error's code for `tether-error`, `error` without one.\n */\nfunction errorCode(error) {\n const code = codeOf(error);\n return typeof code === 'string' && code ? code : 'error';\n}\n\n/**\n * Sets `tether-state` (loading | ready | error) and `tether-error` (not-found or an error code) on `root`, toggles\n * `tether-show=\"loading|ready|error|not-found\"` inside it, and disables its add-to-cart buttons when there's no\n * product.\n *\n * @param {Element} root\n * @param {ScopeStatus} status\n * @param {unknown} [error]\n */\nexport function setScopeStatus(root, status, error) {\n const notFound = status === 'not-found';\n const failed = status === 'error' || notFound;\n root.setAttribute(attr('state'), notFound ? 'error' : status);\n if (failed) root.setAttribute(attr('error'), notFound ? 'not-found' : errorCode(error));\n else root.removeAttribute(attr('error'));\n\n scoped(root, sel('show'), boundary()).forEach((el) => {\n const shows = get(el, 'show');\n if (isScopeStatus(shows)) show(el, shows === status);\n });\n\n if (!failed) return;\n scoped(root, sel('add-to-cart'), boundary()).forEach((button) => {\n button.classList.add('is-disabled');\n button.setAttribute('aria-disabled', 'true');\n if ('disabled' in button) button.disabled = true;\n });\n}\n", "/**\n * The DOM writes of a product scope that follow the visitor's choice, on every change: `product-state.js`'s view as\n * text, selected and unavailable states, `tether-show` conditions and the add-to-cart buttons.\n */\nimport { attr, sel, get, qsa, formatMoney, formatPercent, setText, setImage, setSelected, show } from './dom.js';\nimport { STATUS_KEYS, ownedBy } from './status.js';\nimport { allocationFor } from './selling-plans.js';\nimport { isValueAvailable, planBindTexts, variantBindTexts } from './product-state.js';\nimport { isSelect, selectsIn } from './product-render.js';\n/** @import { Formatters, ProductView } from './product-state.js' */\n/** @import { RenderScope } from './product-render.js' */\n\n/** @type {Formatters} */\nconst FORMAT = { money: formatMoney, percent: formatPercent };\n\n/**\n * @param {Element} el\n * @returns {el is HTMLInputElement}\n */\nconst isInput = (el) => el.tagName === 'INPUT';\n\n/**\n * The element of an add-to-cart button that holds its label, with the label as written kept in\n * `data-tether-label`, so mode-dependent texts (`tether-subscribe-text`, `tether-soldout-text`) can be undone.\n *\n * @param {HTMLElement} button\n * @returns {{ label: HTMLElement, original: string }}\n */\nexport function addButtonLabel(button) {\n const label = qsa(button, sel('add-label'))[0] ?? button;\n const original = label.dataset['tetherLabel'] ?? (isInput(label) ? label.value : label.textContent);\n label.dataset['tetherLabel'] = original;\n return { label, original };\n}\n\n/**\n * @param {RenderScope} scope\n * @param {ProductView} view\n */\nfunction renderOptionStates(scope, view) {\n const { product } = scope;\n const selectedValue = (/** @type {string | null} */ authored) => view.selected[scope.optName(authored)] ?? '';\n scope.$(sel('option-selected')).forEach((el) => {\n setText(el, selectedValue(get(el, 'option-selected')));\n });\n scope.$(sel('option-list')).forEach((container) => {\n const name = scope.optName(get(container, 'option-list'));\n qsa(container, sel('option-value')).forEach((node) => {\n const value = get(node, 'option-value') ?? '';\n setSelected(node, view.selected[name] === value);\n const unavailable = !isValueAvailable(product, view.selected, name, value);\n node.classList.toggle('is-unavailable', unavailable);\n node.setAttribute('data-unavailable', unavailable ? 'true' : 'false');\n });\n });\n selectsIn(scope, sel('option')).forEach((select) => {\n select.value = selectedValue(get(select, 'option'));\n });\n selectsIn(scope, sel('variant-select')).forEach((select) => {\n select.value = view.variant.id;\n });\n}\n\n/**\n * The purchase toggles and the plan list and select.\n *\n * @param {RenderScope} scope\n * @param {ProductView} view\n */\nfunction renderPurchaseStates(scope, view) {\n const { variant, purchase, isSubscription } = view;\n scope.$(sel('purchase')).forEach((el) => {\n if (isSelect(el)) {\n el.value = purchase.kind;\n return;\n }\n const mode = get(el, 'purchase');\n setSelected(el, mode === purchase.kind);\n const unavailable = mode === 'subscription' ? !view.subscriptionAvailable : scope.product.requiresSellingPlan;\n el.classList.toggle('is-unavailable', unavailable);\n });\n scope.$(sel('plan-value')).forEach((node) => {\n const planId = get(node, 'plan-value') ?? '';\n setSelected(node, isSubscription && planId === purchase.planId);\n node.classList.toggle('is-unavailable', !allocationFor(variant, planId));\n const plan = scope.plans.find((candidate) => candidate.id === planId);\n const texts = planBindTexts(variant, planId, plan, FORMAT);\n qsa(node, sel('plan-bind')).forEach((el) => {\n const text = texts.get(get(el, 'plan-bind') ?? '');\n if (text) setText(el, text());\n });\n });\n selectsIn(scope, sel('plan')).forEach((select) => {\n select.value = isSubscription ? (purchase.planId ?? '') : '';\n });\n}\n\n/**\n * The `tether-show` conditions, with the scope's own status: a product scope that renders is ready.\n *\n * @param {RenderScope} scope\n * @param {ProductView} view\n */\nfunction renderConditions(scope, view) {\n /** @type {Map<string, boolean>} */\n const conditions = new Map(Object.entries(view.show));\n STATUS_KEYS.forEach((status) => conditions.set(status, status === 'ready'));\n scope.$(sel('show')).forEach((el) => {\n const key = get(el, 'show') ?? '';\n const visible = conditions.get(key);\n if (visible === undefined) return;\n // State blocks of a list nested in this product belong to that list.\n if (STATUS_KEYS.some((status) => status === key) && !ownedBy(el, scope.root)) return;\n show(el, visible);\n });\n}\n\n/**\n * @param {RenderScope} scope\n * @param {ProductView} view\n */\nfunction renderAddButtons(scope, view) {\n const disabled = !view.variant.availableForSale;\n scope.$(sel('add-to-cart')).forEach((button) => {\n button.classList.toggle('is-disabled', disabled);\n button.setAttribute('aria-disabled', String(disabled));\n // A <button> or <input> is disabled; a link or div carries only aria-disabled.\n if ('disabled' in button) button.disabled = disabled;\n const soldOutText = get(button, 'soldout-text');\n const subscribeText = get(button, 'subscribe-text');\n if (!soldOutText && !subscribeText) return;\n const { label, original } = addButtonLabel(button);\n let text = original;\n if (view.isSubscription && subscribeText) text = subscribeText;\n if (disabled && soldOutText) text = soldOutText;\n if (button.getAttribute('aria-busy') !== 'true') setText(label, text);\n });\n}\n\n/**\n * Writes what follows the variant and purchase.\n *\n * @param {RenderScope} scope\n * @param {ProductView} view\n */\nexport function writeVariant(scope, view) {\n const { variant } = view;\n const { product } = scope;\n const texts = variantBindTexts(view, FORMAT);\n scope.$(sel('bind')).forEach((el) => {\n const key = get(el, 'bind') ?? '';\n if (key === 'variant-image') {\n setImage(el, variant.image?.url || product.featuredImage?.url, variant.image?.altText || product.title);\n return;\n }\n const text = texts.get(key);\n if (text) setText(el, text());\n });\n renderOptionStates(scope, view);\n renderPurchaseStates(scope, view);\n renderConditions(scope, view);\n scope.root.classList.toggle('is-subscription', view.isSubscription);\n scope.root.setAttribute(attr('purchase-mode'), view.isSubscription ? 'subscription' : 'one-time');\n renderAddButtons(scope, view);\n}\n", "/**\n * A product scope's clicks and changes: option and plan buttons, purchase toggles, quantity steppers, the selects and\n * add to cart. One delegated listener of each kind on the root, so cards a list re-renders need no new listeners.\n */\nimport { reportError } from './config.js';\nimport { sel, get, emit, setText, busy } from './dom.js';\nimport { addButtonLabel } from './variant-render.js';\n/** @import { ProductScope } from './product.js' */\n\nconst productSelector = () => sel('product');\n\n/**\n * @param {Element} el\n * @returns {el is HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement}\n */\nconst isField = (el) => el.tagName === 'INPUT' || el.tagName === 'SELECT' || el.tagName === 'TEXTAREA';\n\n/**\n * @param {EventTarget | null} target\n * @returns {target is Element}\n */\nconst isElement = (target) => target instanceof window.Element;\n\n/**\n * @param {ProductScope} scope\n * @param {Element} target\n * @param {string} selector\n * @returns {HTMLElement | null} The nearest `selector` around `target` that belongs to the scope, not to a nested one.\n * Typed as an HTML element, as `qsa` types its matches.\n */\nfunction closestOwn(scope, target, selector) {\n const el = /** @type {HTMLElement | null} */ (target.closest(selector));\n return el?.closest(productSelector()) === scope.root ? el : null;\n}\n\n/**\n * Adds to the cart with `aria-busy` on the button and `tether-adding-text` as its label meanwhile.\n *\n * @param {ProductScope} scope\n * @param {HTMLElement} button\n */\nfunction onAddClick(scope, button) {\n const { label, original } = addButtonLabel(button);\n const addingText = get(button, 'adding-text');\n void busy(button, async () => {\n if (addingText) setText(label, addingText);\n try {\n await scope.addToCart();\n } catch (error) {\n reportError(error, 'add to cart failed');\n emit('error', { error, context: 'add-to-cart' }, scope.root);\n } finally {\n if (addingText) setText(label, original);\n }\n }).then(() => {\n // The mode-dependent labels (tether-subscribe-text, tether-soldout-text) wait for aria-busy to clear.\n scope.renderVariant();\n });\n}\n\n/**\n * @param {ProductScope} scope\n * @param {Event} event\n * @param {Element} target\n */\nfunction onClick(scope, event, target) {\n const optionValue = closestOwn(scope, target, sel('option-value'));\n const optionList = optionValue?.closest(sel('option-list'));\n if (optionValue && optionList) {\n event.preventDefault();\n scope.select(scope.optName(get(optionList, 'option-list')), get(optionValue, 'option-value') ?? '');\n return;\n }\n const plan = closestOwn(scope, target, sel('plan-value'));\n if (plan) {\n event.preventDefault();\n scope.selectPlan(get(plan, 'plan-value'));\n return;\n }\n const purchase = closestOwn(scope, target, `${sel('purchase')}:not(select)`);\n if (purchase) {\n // A radio or checkbox input keeps its own click, so it shows checked.\n if (purchase.tagName !== 'INPUT') event.preventDefault();\n scope.setPurchase(get(purchase, 'purchase'));\n return;\n }\n const plus = closestOwn(scope, target, sel('qty-plus'));\n const minus = plus ? null : closestOwn(scope, target, sel('qty-minus'));\n if (plus || minus) {\n event.preventDefault();\n scope.setQuantity(scope.quantity + (plus ? 1 : -1));\n return;\n }\n const add = closestOwn(scope, target, sel('add-to-cart'));\n if (add) {\n event.preventDefault();\n onAddClick(scope, add);\n }\n}\n\n/**\n * @param {ProductScope} scope\n * @param {Element} target A form field in the scope.\n */\nfunction onChange(scope, target) {\n const value = isField(target) ? target.value : '';\n if (target.matches(`select${sel('option')}`)) {\n scope.select(scope.optName(get(target, 'option')), value);\n } else if (target.matches(`select${sel('variant-select')}`)) {\n scope.selectVariant(value);\n } else if (target.matches(`select${sel('plan')}`)) {\n if (value) scope.selectPlan(value);\n else scope.setPurchase('one-time');\n } else if (target.matches(`select${sel('purchase')}`)) {\n scope.setPurchase(value);\n } else if (target.matches(sel('qty'))) {\n scope.setQuantity(value);\n }\n}\n\n/** @param {ProductScope} scope */\nexport function bindProductEvents(scope) {\n scope.root.addEventListener('click', (event) => {\n if (isElement(event.target)) onClick(scope, event, event.target);\n });\n scope.root.addEventListener('change', (event) => {\n const { target } = event;\n if (isElement(target) && target.closest(productSelector()) === scope.root) onChange(scope, target);\n });\n}\n", "/**\n * Product lists: [tether-collection=\"handle\"], [tether-products=\"search query\"] and [tether-recommendations]. The\n * first child of [tether-list] is the card template; every card becomes a product scope, so all product attributes\n * work inside cards (including quick-add with a subscription toggle).\n */\nimport { reportError } from './config.js';\nimport { TetherError } from './client.js';\nimport {\n attr,\n sel,\n get,\n has,\n scoped,\n emit,\n setText,\n setStoreHtml,\n setImage,\n repeat,\n notifyLayoutChanged,\n busy,\n show,\n} from './dom.js';\nimport { getProducts, getRecommendations } from './loader.js';\nimport { setScopeStatus, isNotFound, resolveProductKey } from './status.js';\n/** @import { Product } from './fragments.js' */\n/** @import { Collection, PageInfo, ProductQuery } from './loader.js' */\n\n/** `tether-products=\"url:q\"`: the search in the page's `?q=`, for a results page on a static site. */\nconst URL_QUERY_SOURCE = 'url:';\n\nexport const listSelector = () => `${sel('collection')},${sel('products')},${sel('recommendations')}`;\n\n/**\n * @param {EventTarget | null} target\n * @returns {target is Element}\n */\nconst isElement = (target) => target instanceof window.Element;\n\n/**\n * @param {string | null} raw A `tether-limit`.\n * @returns {number | undefined} The limit; `undefined` for none, zero or not a number.\n */\nconst toLimit = (raw) => parseInt(raw ?? '', 10) || undefined;\n\n/**\n * @param {string | null} raw A `tether-intent`.\n * @returns {'RELATED' | 'COMPLEMENTARY'} Shopify's recommendation intent, `RELATED` unless `COMPLEMENTARY` is written.\n */\nconst toIntent = (raw) => (raw === 'COMPLEMENTARY' ? 'COMPLEMENTARY' : 'RELATED');\n\nexport class ListScope {\n /** @param {HTMLElement} root */\n constructor(root) {\n this.root = root;\n /** @type {Product[]} */\n this.products = [];\n /** @type {PageInfo | null} */\n this.pageInfo = null;\n /** @type {Collection | null} */\n this.collection = null;\n /** Counts loads, so only the latest one renders. */\n this.loadToken = 0;\n setScopeStatus(root, 'loading');\n root.addEventListener('click', (event) => {\n if (!isElement(event.target)) return;\n const more = event.target.closest(sel('load-more'));\n if (more?.closest(listSelector()) !== root) return;\n event.preventDefault();\n void busy(more, () => this.load(true));\n });\n }\n\n /** @param {string} selector */\n $(selector) {\n return scoped(this.root, selector, listSelector());\n }\n\n /** @returns {ProductQuery} The collection or search query of the list's attributes. */\n options() {\n const { root } = this;\n /** @type {ProductQuery} */\n const query = { reverse: get(root, 'reverse') === 'true' };\n const first = toLimit(get(root, 'limit'));\n if (first) query.first = first;\n const sortKey = get(root, 'sort');\n if (sortKey) query.sortKey = sortKey;\n if (has(root, 'collection')) {\n query.collection = get(root, 'collection') ?? '';\n return query;\n }\n const raw = get(root, 'products') ?? '';\n query.query = raw.startsWith(URL_QUERY_SOURCE)\n ? new URL(window.location.href).searchParams.get(raw.slice(URL_QUERY_SOURCE.length)) || ''\n : raw;\n return query;\n }\n\n /**\n * The product of a recommendations list: a handle, `url:\u2026` (one dynamic product page), or empty inside a product\n * scope for that product.\n *\n * @returns {Promise<Product[]>}\n * @throws {TetherError} `NOT_FOUND` when there is no product to recommend for.\n */\n async loadRecommendations() {\n let { key } = resolveProductKey(this.root, window.location, 'recommendations');\n const scope = this.root.closest(sel('product'));\n if (!key && scope) ({ key } = resolveProductKey(scope));\n if (!key) throw new TetherError('No product for recommendations', { code: 'NOT_FOUND' });\n return getRecommendations(key, toIntent(get(this.root, 'intent')));\n }\n\n /** @param {boolean} [more] Appends the next page instead of replacing the products. */\n async load(more = false) {\n this.loadToken += 1;\n const token = this.loadToken;\n const stale = () => token !== this.loadToken;\n try {\n if (has(this.root, 'recommendations')) {\n const recommendations = await this.loadRecommendations();\n if (stale()) return;\n const limit = toLimit(get(this.root, 'limit'));\n this.products = limit ? recommendations.slice(0, limit) : recommendations;\n } else {\n const page = await getProducts({ ...this.options(), after: more ? (this.pageInfo?.endCursor ?? null) : null });\n if (stale()) return;\n this.collection = page.collection;\n this.pageInfo = page.pageInfo;\n this.products = more ? [...this.products, ...page.products] : page.products;\n }\n this.render();\n setScopeStatus(this.root, 'ready');\n emit('list-ready', { products: this.products, collection: this.collection }, this.root);\n } catch (error) {\n if (stale()) return;\n // A failed \"load more\" keeps what is rendered; otherwise the list shows its error state.\n if (!more) setScopeStatus(this.root, isNotFound(error) ? 'not-found' : 'error', error);\n // A missing product for recommendations is a page detail, not an error to report.\n if (!(isNotFound(error) && has(this.root, 'recommendations'))) reportError(error, 'list load failed');\n emit('error', { error, context: 'list' }, this.root);\n }\n }\n\n render() {\n const { collection } = this;\n this.$(sel('collection-bind')).forEach((el) => {\n switch (get(el, 'collection-bind') ?? '') {\n case 'title':\n setText(el, collection?.title ?? '');\n break;\n case 'description':\n setStoreHtml(el, collection?.descriptionHtml);\n break;\n case 'image':\n setImage(el, collection?.image?.url, collection?.image?.altText || collection?.title);\n break;\n case 'count':\n setText(el, this.products.length);\n break;\n }\n });\n\n this.$(sel('list')).forEach((container) => {\n repeat(container, this.products, (node, product) => {\n node.setAttribute(attr('product'), product.handle);\n node.removeAttribute(attr('state'));\n });\n // Cards are new elements: mounting them uses the product data already cached.\n emit('list-rendered', { container }, this.root);\n });\n\n const empty = this.products.length === 0;\n this.$(sel('show')).forEach((el) => {\n const key = get(el, 'show');\n if (key === 'list-empty') show(el, empty);\n if (key === 'list-filled') show(el, !empty);\n });\n this.$(sel('load-more')).forEach((el) => {\n show(el, Boolean(this.pageInfo?.hasNextPage));\n });\n notifyLayoutChanged('list');\n }\n}\n", "/**\n * The product scopes and lists on the page: mounting a product root, the live roots a country switch re-renders, and\n * the products the server rendered into the page. Shared by `index.js` and the optional markets part.\n */\nimport { cfg, log, warn, reportError } from './config.js';\nimport { ProductScope, scopes, rememberOptionNames } from './product.js';\nimport { listSelector } from './collection.js';\nimport { getProduct, takeStale, refreshProducts, hydrateProducts } from './loader.js';\nimport { resolveProductKey, setScopeStatus, isNotFound } from './status.js';\nimport { attr, get, qsa, emit } from './dom.js';\n/** @import { Product } from './fragments.js' */\n\n/** @typedef {{ root: Element, load: (more?: boolean) => Promise<unknown> }} MountedList A mounted `ListScope`. */\n\n/**\n * The marker on the `<script type=\"application/json\">` tags `tether/server`'s `hydrate()` writes. It is fixed, not\n * `<prefix>-hydrate`, because the server writes it without knowing the browser's prefix.\n */\nconst HYDRATE_SELECTOR = 'script[type=\"application/json\"][data-tether-hydrate]';\n\n/** @type {WeakSet<Element>} */\nexport const mountedProducts = new WeakSet();\n/** @type {WeakSet<Element>} */\nexport const mountedLists = new WeakSet();\n/** @type {Set<HTMLElement>} Product roots to re-render after a country switch; pruned once disconnected. */\nexport const liveProducts = new Set();\n/** @type {Set<MountedList>} Lists to reload after a country switch; pruned once disconnected. */\nexport const liveLists = new Set();\n/** @type {WeakMap<Element, object>} Each product root's latest request, so a slow older response can't win. */\nconst latestRequest = new WeakMap();\n\n/** Forgets roots a page transition removed, so they aren't kept alive. */\nexport function pruneLive() {\n liveProducts.forEach((el) => {\n if (!el.isConnected) liveProducts.delete(el);\n });\n liveLists.forEach((list) => {\n if (!list.root.isConnected) liveLists.delete(list);\n });\n}\n\n/**\n * @param {ParentNode & Partial<Pick<Element, 'matches'>>} root\n * @param {string} selector\n * @returns {HTMLElement[]} `root` itself when it matches, then the matches inside it.\n */\nexport function within(root, selector) {\n const self = root.matches?.(selector) ? [/** @type {HTMLElement} */ (root)] : [];\n return [...self, ...qsa(root, selector)];\n}\n\n/**\n * `tether-page-title=\"{title} | My shop\"` on a product root sets `document.title`, for dynamic product pages.\n *\n * @param {Element} el\n * @param {Product} product\n */\nfunction applyPageTitle(el, product) {\n const template = get(el, 'page-title');\n if (!template || typeof document === 'undefined') return;\n document.title = template\n .replace(/\\{title\\}/g, product.title)\n .replace(/\\{vendor\\}/g, product.vendor || '')\n .replace(/\\{type\\}/g, product.productType || '');\n}\n\n/**\n * A product root without a key: on a dynamic page opened without `?handle=` (or with an empty path) it is a product\n * that isn't there; inside a list it gets its handle when the list renders.\n *\n * @param {HTMLElement} el\n * @param {{ fromUrl: boolean, raw: string }} source\n */\nfunction mountWithoutKey(el, { fromUrl, raw }) {\n if (fromUrl) {\n mountedProducts.add(el);\n setScopeStatus(el, 'not-found');\n emit('product-not-found', { key: null, source: raw }, el);\n } else if (!el.closest(listSelector())) {\n warn(`[${attr('product')}] without a value. Bind it to the Shopify handle field, or use \"url:handle\".`, el);\n }\n}\n\n/**\n * @param {HTMLElement} el\n * @param {string} key\n * @param {{ fromUrl: boolean, raw: string }} source\n * @param {unknown} error\n */\nfunction showLoadFailure(el, key, { fromUrl, raw }, error) {\n const notFound = isNotFound(error);\n setScopeStatus(el, notFound ? 'not-found' : 'error', error);\n if (!notFound) {\n reportError(error, `product ${key}`);\n emit('error', { error, context: 'product', key }, el);\n return;\n }\n emit('product-not-found', { key, source: raw }, el);\n // A typo in a URL isn't worth an alert; a CMS item pointing at a deleted product is.\n if (fromUrl) log(`product not found: ${key}`);\n else reportError(error, `product ${key}`);\n}\n\n/**\n * Mounts one product root.\n *\n * @param {HTMLElement} el\n * @returns {boolean} True when a product request was started.\n */\nexport function mountProduct(el) {\n if (mountedProducts.has(el)) return false;\n const { key, ...source } = resolveProductKey(el);\n if (!key) {\n mountWithoutKey(el, source);\n return false;\n }\n mountedProducts.add(el);\n liveProducts.add(el);\n const request = {};\n latestRequest.set(el, request);\n const isLatest = () => latestRequest.get(el) === request;\n // A rendered scope keeps showing its content while it refreshes (a country switch).\n if (scopes.get(el)) el.setAttribute(attr('state'), 'updating');\n else setScopeStatus(el, 'loading');\n const loading = trackMarket(getProduct(key));\n loading\n .then((product) => {\n if (!isLatest()) return;\n const existing = scopes.get(el);\n if (existing) existing.update(product);\n else new ProductScope(el, product);\n applyPageTitle(el, product);\n if (cfg.revalidate && takeStale(key)) queueRefresh(key);\n })\n .catch((/** @type {unknown} */ error) => {\n if (isLatest()) showLoadFailure(el, key, source, error);\n });\n return true;\n}\n\n/** Loads again the product scopes that failed on a network or API error, for when the browser is back online. */\nexport function retryFailed() {\n pruneLive();\n liveProducts.forEach((el) => {\n if (el.getAttribute(attr('state')) !== 'error' || el.getAttribute(attr('error')) === 'not-found') return;\n mountedProducts.delete(el);\n mountProduct(el);\n });\n}\n\n/** @type {Set<string>} Server-rendered products to refresh in the next batch. */\nlet refreshQueue = new Set();\n\n/** @param {string} key */\nfunction queueRefresh(key) {\n if (!refreshQueue.size) setTimeout(flushRefresh, 0);\n refreshQueue.add(key);\n}\n\n/**\n * @param {string} key The key the refresh was asked for.\n * @param {Product} fresh\n */\nfunction applyRefresh(key, fresh) {\n liveProducts.forEach((el) => {\n const scope = scopes.get(el);\n if (!scope || !el.isConnected) return;\n const rootKey = resolveProductKey(el).key;\n if (rootKey !== key && rootKey !== fresh.handle && rootKey !== fresh.id) return;\n if (JSON.stringify(scope.product) !== JSON.stringify(fresh)) scope.update(fresh);\n });\n}\n\n/** One batched background request refreshes every server-rendered product queued. */\nfunction flushRefresh() {\n const keys = [...refreshQueue];\n refreshQueue = new Set();\n refreshProducts(keys).forEach((promise, index) => {\n const key = /** @type {string} */ (keys[index]);\n promise\n .then((fresh) => {\n applyRefresh(key, fresh);\n })\n .catch((/** @type {unknown} */ error) => {\n reportError(error, `refresh ${key}`);\n });\n });\n}\n\n/**\n * @type {Set<Promise<unknown>> | null} While the page's server-rendered prices are another market's: the loads to\n * wait for before `html.tether-market-pending` goes. `null` when no market is pending.\n */\nlet marketPending = null;\n\n/**\n * Lists, and anything else that loads prices, hold `html.tether-market-pending` until they are in.\n *\n * @template T\n * @param {Promise<T>} loading\n * @returns {Promise<T>} `loading` itself.\n */\nexport const trackMarket = (loading) => {\n marketPending?.add(loading);\n return loading;\n};\n\n/** After a mount: drops `html.tether-market-pending` once this page's products are live. */\nexport function settleMarket() {\n if (!marketPending) return;\n const waits = [...marketPending];\n void Promise.allSettled(waits).then(() => {\n if (!marketPending || waits.some((wait) => !marketPending?.has(wait))) return;\n if (waits.length !== marketPending.size) {\n settleMarket(); // more loads came in meanwhile\n return;\n }\n marketPending = null;\n document.documentElement.classList.remove(`${cfg.prefix}-market-pending`);\n });\n}\n\n/**\n * What `tether/server`'s `hydrate()` writes. The tag is the site's own markup, so its shape is trusted; a product\n * without an id or a handle is skipped.\n *\n * @typedef {{ country?: string | null, language?: string | null, products?: (Product | null)[] }} HydratePayload\n */\n\n/**\n * @param {Product | null} product\n * @returns {product is Product}\n */\nconst isUsable = (product) => Boolean(product?.id && product.handle);\n\n/**\n * @param {string | null | undefined} a\n * @param {string | null | undefined} b\n */\nconst sameCode = (a, b) => (a ?? '').toUpperCase() === (b ?? '').toUpperCase();\n\n/** @type {WeakSet<Element>} Hydrate tags already read. */\nconst readScripts = new WeakSet();\n\n/**\n * Uses the products in the page's hydrate tags (`tether/server` `hydrate()`) without a request. A tag made for another\n * market is skipped, and marks the page (`html.tether-market-pending`) until the live prices are in, so CSS can hide\n * prices meanwhile.\n *\n * @param {Document | Element} [root]\n */\nexport function hydrateFromPage(root = document) {\n qsa(root.ownerDocument ?? root, HYDRATE_SELECTOR).forEach((script) => {\n if (readScripts.has(script)) return;\n readScripts.add(script);\n /** @type {unknown} */\n let json;\n try {\n json = JSON.parse(script.textContent);\n } catch (error) {\n warn('bad data-tether-hydrate', error);\n return;\n }\n const { country, language, products } = /** @type {HydratePayload | null} */ (json) ?? {};\n const usable = Array.isArray(products) ? products.filter(isUsable) : [];\n rememberOptionNames(usable); // the build's option names, also for other languages\n if (sameCode(country, cfg.country) && sameCode(language, cfg.language)) {\n hydrateProducts(usable);\n return;\n }\n log('hydration skipped: other market');\n if (!marketPending) {\n marketPending = new Set();\n document.documentElement.classList.add(`${cfg.prefix}-market-pending`);\n }\n });\n}\n", "/**\n * `<script>` build: the optional parts are separate files next to tether(.min).js (tether.markets.min.js), loaded on\n * first use. `partsUrl` sets another folder. A part registers itself in `window.Tether.__parts` and uses the core\n * modules in `window.Tether.__core` instead of bundling copies of them.\n */\nimport * as config from './config.js';\nimport * as client from './client.js';\nimport * as dom from './dom.js';\nimport * as fragments from './fragments.js';\nimport * as loader from './loader.js';\nimport * as sellingPlans from './selling-plans.js';\nimport * as status from './status.js';\nimport * as cart from './cart.js';\nimport * as product from './product.js';\nimport * as collection from './collection.js';\nimport * as mounting from './mounting.js';\nimport * as marketCodes from './market-codes.js';\nimport * as shopifyValues from './shopify-values.js';\nimport * as storeHtml from './store-html.js';\n/** @import { Parts, PartName } from './lazy.js' */\n\nconst { cfg } = config;\n\n/**\n * The modules a part may use, shared instead of bundled twice (scripts/build.mjs maps a part's imports to these).\n *\n * @type {Record<string, object>}\n */\nexport const coreModules = {\n 'config.js': config,\n 'client.js': client,\n 'dom.js': dom,\n 'fragments.js': fragments,\n 'loader.js': loader,\n 'selling-plans.js': sellingPlans,\n 'status.js': status,\n 'cart.js': cart,\n 'product.js': product,\n 'collection.js': collection,\n 'mounting.js': mounting,\n 'market-codes.js': marketCodes,\n 'shopify-values.js': shopifyValues,\n 'store-html.js': storeHtml,\n};\n\nconst MINIFIED_SCRIPT = /\\.min\\.js(\\?|$)/;\nconst coreScript = typeof document === 'undefined' ? '' : (document.currentScript?.getAttribute('src') ?? '');\nconst coreScriptUrl = coreScript ? new URL(coreScript, document.baseURI).href : '';\n\n/** @type {Map<PartName, Promise<unknown>>} Parts loaded or loading. */\nconst parts = new Map();\n\n/**\n * The folder parts load from: `partsUrl`, else the core script's own folder. A `partsUrl` must be https or on this\n * site, because the parts run with the same access as the core (the account part holds customer sessions).\n *\n * @throws {Error} For a `partsUrl` that is neither.\n */\nfunction partsFolder() {\n if (!cfg.partsUrl) return coreScriptUrl.replace(/[^/]*$/, '');\n const folder = new URL(cfg.partsUrl, document.baseURI);\n if (folder.protocol !== 'https:' && folder.origin !== window.location.origin) {\n throw new Error(`partsUrl must be https or on this site: ${folder.href}`);\n }\n return folder.href;\n}\n\n/**\n * @param {PartName} name\n * @param {string} url\n * @returns {Promise<unknown>}\n */\nfunction loadScript(name, url) {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = url;\n script.async = true;\n script.onload = () => {\n const { Tether } = /** @type {Window & { Tether?: { __parts?: Record<string, unknown> } }} */ (window);\n const part = Tether?.__parts?.[name];\n if (part) resolve(part);\n else reject(new Error(`${url} did not register`));\n };\n script.onerror = () => {\n parts.delete(name);\n reject(new Error(`Could not load ${url}. Host it next to the Tether script, or set partsUrl.`));\n };\n document.head.appendChild(script);\n });\n}\n\n/**\n * @template {PartName} Name\n * @param {Name} name\n * @returns {Promise<Parts[Name]>}\n * @throws {Error} (rejected) When the part's file can't be loaded or doesn't register.\n */\nexport function loadPart(name) {\n let loading = parts.get(name);\n if (!loading) {\n let folder;\n try {\n folder = partsFolder();\n } catch (error) {\n return Promise.reject(error instanceof Error ? error : new Error(String(error)));\n }\n const suffix = MINIFIED_SCRIPT.test(coreScriptUrl) || !coreScriptUrl ? '.min' : '';\n loading = loadScript(name, `${folder.replace(/\\/?$/, '/')}tether.${name}${suffix}.js`);\n parts.set(name, loading);\n }\n // A part's file is built from the module `Parts[Name]` names (scripts/build.mjs), and registers that module.\n return /** @type {Promise<Parts[Name]>} */ (loading);\n}\n\n// Parts that load other parts (account \u2192 account-pages) use this same loader.\ncoreModules['lazy.js'] = { loadPart, coreModules };\n", "/**\n * Markets: which country and language prices, currency and translations follow.\n *\n * markets: {\n * detect: true, // or a list: ['saved', 'server', 'webflow']\n * locales: { // Webflow Localization: locale subdirectory or <html lang>\n * de: { country: 'DE', language: 'DE', locale: 'de-DE' },\n * 'fr-be': { country: 'BE', language: 'FR' },\n * },\n * cookie: 'tether_country', // a cookie your server or Worker sets (from cf-ipcountry)\n * remember: true, // keep the visitor's tether-country-select choice\n * }\n *\n * Sources, first match wins per field:\n * saved the visitor's own choice (localStorage), from tether-country-select / Tether.setCountry()\n * server window.TETHER_COUNTRY, <meta name=\"tether-country\" content=\"DE\">, or the cookie\n * webflow locale subdirectory (/de/...) or <html lang=\"de-DE\">, through `locales`\n * then the static `country` / `language` config. Without `detect`, only `saved` applies, so a country select keeps\n * working across pages; `detect: false` turns even that off. Tether never calls an IP lookup service: a country from\n * the visitor's IP only comes from the site's own server (see README).\n */\nimport { cfg } from './config.js';\nimport { gql } from './client.js';\nimport { toCountry, toLanguage } from './market-codes.js';\n/** @import { MarketsConfig } from './config.js' */\n/** @import { CountryCode, LanguageCode } from './market-codes.js' */\n\n/**\n * @typedef {object} Market A market a visitor chose, as `setCountry()` stores it.\n * @property {CountryCode} country\n * @property {LanguageCode | undefined} language\n * @property {string | undefined} locale An `Intl` locale for money and dates.\n */\n\n/** @typedef {'saved' | 'server' | 'webflow'} MarketSource */\n/** @typedef {'country' | 'language' | 'locale'} MarketField */\n/** @typedef {Partial<Record<MarketField, MarketSource>>} MarketSources */\n\n/**\n * @typedef {object} DetectedMarket The fields detection found, and the source each came from.\n * @property {CountryCode} [country]\n * @property {LanguageCode} [language]\n * @property {string} [locale]\n * @property {MarketSources} [sources] Absent when `detect: false` turns detection off.\n */\n\n/**\n * @typedef {object} MarketEnv What detection reads, passed in so it runs on any document.\n * @property {Pick<Document, 'cookie' | 'querySelector' | 'documentElement'> | null} document\n * @property {Pick<Location, 'pathname'> | null} location\n * @property {Pick<Storage, 'getItem'> | null} storage\n * @property {object} global Where `TETHER_COUNTRY` and `TETHER_LANGUAGE` are read from (`window`).\n */\n\n/** @typedef {{ country?: unknown, language?: unknown, locale?: unknown }} MarketHint A source's raw values. */\n\n/** @typedef {{ isoCode: string, name: string }} NamedCode */\n/** @typedef {{ isoCode: string, symbol: string }} Currency */\n/** @typedef {NamedCode & { currency: Currency }} LocalizedCountry */\n/**\n * @typedef {object} Localization The store's markets, from the Storefront API's `localization`.\n * @property {LocalizedCountry} country The country of the current `@inContext`.\n * @property {NamedCode} language\n * @property {(LocalizedCountry & { availableLanguages: NamedCode[] })[]} availableCountries\n */\n\n/** @type {readonly MarketSource[]} */\nconst ALL_SOURCES = ['saved', 'server', 'webflow'];\nconst DEFAULT_COOKIE = 'tether_country';\n\n/** @returns {string} The localStorage key of the visitor's market: `<prefix>:market:<domain>`. */\nexport const storageKey = () => `${cfg.prefix}:market:${cfg.domain}`;\n\n/**\n * Accessing `localStorage` throws where the browser blocks storage (sandboxed frames, cookies turned off); the visitor\n * then simply has no saved market.\n *\n * @returns {Storage | null}\n */\nfunction localStorageIfAllowed() {\n if (typeof window === 'undefined') return null;\n try {\n return window.localStorage;\n } catch {\n return null;\n }\n}\n\n/** @returns {MarketEnv} The page this script runs on. */\nfunction pageEnv() {\n const hasWindow = typeof window !== 'undefined';\n return {\n document: typeof document !== 'undefined' ? document : null,\n location: hasWindow ? window.location : null,\n storage: localStorageIfAllowed(),\n global: hasWindow ? window : {},\n };\n}\n\n/**\n * @param {string} text\n * @returns {unknown} The JSON value, `null` for text that isn't JSON (a key another script wrote).\n */\nfunction parseJsonOrNull(text) {\n try {\n return /** @type {unknown} */ (JSON.parse(text));\n } catch (error) {\n if (error instanceof SyntaxError) return null;\n throw error;\n }\n}\n\n/**\n * @param {unknown} value\n * @returns {Market | null} `value` as a market, when it has a valid country. A language or locale that isn't valid is\n * left out.\n */\nfunction toMarket(value) {\n if (typeof value !== 'object' || value === null) return null;\n const country = toCountry(Reflect.get(value, 'country'));\n if (!country) return null;\n const locale = /** @type {unknown} */ (Reflect.get(value, 'locale'));\n return {\n country,\n language: toLanguage(Reflect.get(value, 'language')) ?? undefined,\n locale: typeof locale === 'string' && locale ? locale : undefined,\n };\n}\n\n/**\n * The visitor's saved market (`setCountry()`, `tether-country-select`), validated: storage is written by other tabs,\n * older versions and other scripts too.\n *\n * @param {Pick<Storage, 'getItem'> | null} [storage] Default `localStorage`, `null` where the browser blocks it.\n * @returns {Market | null} `null` when nothing valid is saved.\n */\nexport function readSavedMarket(storage = localStorageIfAllowed()) {\n const text = storage?.getItem(storageKey());\n return text ? toMarket(parseJsonOrNull(text)) : null;\n}\n\n/**\n * @param {Pick<Document, 'cookie'> | null} doc\n * @param {string} name\n * @returns {string | null}\n */\nfunction readCookie(doc, name) {\n if (!doc || !name) return null;\n const cookie = doc.cookie\n .split(';')\n .map((part) => part.trim())\n .find((part) => part.startsWith(`${name}=`));\n return cookie ? decodeURIComponent(cookie.slice(name.length + 1)) : null;\n}\n\n/**\n * @param {MarketsConfig['locales']} locales\n * @param {string | undefined} key\n * @returns {MarketHint | null} The entry for `key`, ignoring case.\n */\nfunction lookupLocale(locales, key) {\n if (!locales || !key) return null;\n const wanted = key.toLowerCase();\n const found = Object.keys(locales).find((name) => name.toLowerCase() === wanted);\n return found ? (locales[found] ?? null) : null;\n}\n\n/**\n * @param {MarketsConfig} markets\n * @param {MarketEnv} env\n * @returns {MarketHint}\n */\nfunction readServerHint(markets, env) {\n /** @param {string} name */\n const meta = (name) => env.document?.querySelector(`meta[name=\"${name}\"]`)?.getAttribute('content');\n return {\n country:\n Reflect.get(env.global, 'TETHER_COUNTRY') ||\n meta('tether-country') ||\n readCookie(env.document, markets.cookie || DEFAULT_COOKIE),\n language: Reflect.get(env.global, 'TETHER_LANGUAGE') || meta('tether-language'),\n };\n}\n\n/**\n * @param {MarketsConfig} markets\n * @param {MarketEnv} env\n * @returns {MarketHint | null}\n */\nfunction readWebflowLocale(markets, env) {\n const segment = (env.location?.pathname ?? '/').split('/').find((part) => part !== '');\n const fromPath = lookupLocale(markets.locales, segment);\n if (fromPath) return fromPath;\n const lang = env.document?.documentElement.getAttribute('lang');\n if (!lang) return null;\n const mapped = lookupLocale(markets.locales, lang) ?? lookupLocale(markets.locales, lang.split('-')[0]);\n if (mapped) return { locale: lang, ...mapped };\n if (markets.locales && markets.strict) return null;\n // Unmapped: the language from <html lang>, a country only from a region subtag (de-CH -> CH).\n const region = lang.split('-')[1];\n return { language: lang, country: region?.length === 2 ? region : null, locale: lang };\n}\n\n/**\n * @param {MarketSource} source\n * @param {MarketsConfig} markets\n * @param {MarketEnv} env\n * @returns {MarketHint | null}\n */\nfunction readSource(source, markets, env) {\n switch (source) {\n case 'saved':\n return markets.remember === false ? null : readSavedMarket(env.storage);\n case 'server':\n return readServerHint(markets, env);\n case 'webflow':\n return readWebflowLocale(markets, env);\n }\n}\n\n/**\n * @param {unknown} name\n * @returns {name is MarketSource}\n */\nconst isMarketSource = (name) => ALL_SOURCES.some((source) => source === name);\n\n/**\n * @param {MarketsConfig['detect']} detect\n * @returns {readonly MarketSource[]} Without `detect`, only the visitor's own choice from a country select.\n */\nfunction sourcesFor(detect) {\n if (!detect) return ['saved'];\n if (detect === true) return ALL_SOURCES;\n // The config comes from the page unvalidated, so a single name or an unknown one can arrive here.\n return /** @type {unknown[]} */ ([detect].flat()).filter(isMarketSource);\n}\n\n/**\n * The market the page's sources point to. Reads the DOM and storage only, so it can run on any `env`.\n *\n * @param {MarketsConfig | null | undefined} [markets]\n * @param {MarketEnv} [env]\n * @returns {DetectedMarket} Only the fields found; `{}` with `detect: false`.\n */\nexport function detectMarket(markets = cfg.markets, env = pageEnv()) {\n const config = markets ?? {};\n if (config.detect === false) return {};\n /** @type {MarketSources} */\n const sources = {};\n /** @type {DetectedMarket} */\n const found = { sources };\n for (const source of sourcesFor(config.detect)) {\n const hint = readSource(source, config, env);\n if (!hint) continue;\n const country = toCountry(hint.country);\n const language = toLanguage(hint.language);\n const locale = typeof hint.locale === 'string' && hint.locale ? hint.locale : null;\n if (country && !found.country) {\n found.country = country;\n sources.country = source;\n }\n if (language && !found.language) {\n found.language = language;\n sources.language = source;\n }\n if (locale && !found.locale) {\n found.locale = locale;\n sources.locale = source;\n }\n }\n return found;\n}\n\n/**\n * `setItem` throws when storage is full or blocked (Safari's private mode); the choice then lasts for this page only.\n *\n * @param {string} key\n * @param {string} value\n */\nfunction storeIfAllowed(key, value) {\n try {\n localStorage.setItem(key, value);\n } catch {\n return;\n }\n}\n\n/**\n * Saves the visitor's choice for the next pages, unless `markets.remember` is false.\n *\n * @param {{ country: CountryCode, language?: string | null | undefined, locale?: string | null | undefined }} market\n */\nexport function rememberMarket(market) {\n if (cfg.markets?.remember === false) return;\n const saved = { country: market.country, language: market.language || undefined, locale: market.locale || undefined };\n storeIfAllowed(storageKey(), JSON.stringify(saved));\n}\n\n/** @type {Promise<Localization> | null} */\nlet localizationPromise = null;\n\n/** Forgets the cached localization, for when country names change language. */\nexport function clearLocalization() {\n localizationPromise = null;\n}\n\nconst LOCALIZATION_QUERY = `query TetherLocalization{localization{country{isoCode name currency{isoCode symbol}}language{isoCode name}availableCountries{isoCode name currency{isoCode symbol}availableLanguages{isoCode name}}}}`;\n\n/**\n * The countries the store sells to (Shopify Markets), with their currency. Cached per page; a failed request is not\n * cached, so the next call tries again.\n *\n * @returns {Promise<Localization>}\n */\nexport function getLocalization() {\n if (!localizationPromise) {\n /** @type {Promise<{ localization: Localization }>} */\n const loading = gql(LOCALIZATION_QUERY);\n localizationPromise = loading.then(\n (data) => data.localization,\n (/** @type {unknown} */ error) => {\n localizationPromise = null;\n throw error;\n },\n );\n }\n return localizationPromise;\n}\n", "/**\n * The market the page uses: a page built for one market (`<meta name=\"tether-page-country\">`) wins, then the visitor's\n * saved or detected market, then the configured one. Init applies it to `cfg` once. Astro's ClientRouter keeps the\n * script running across pages, so each arrival asks again: the next page may be built for another market, or for none.\n */\nimport { cfg, log, reportError } from './config.js';\nimport { loadPart } from './lazy.js';\nimport { toCountry, toLanguage } from './market-codes.js';\nimport { readSavedMarket } from './markets.js';\n/** @import { TetherOptions } from './config.js' */\n/** @import { Market, DetectedMarket } from './markets.js' */\n/** @import { SetCountryOptions } from './markets-ui.js' */\n/** @import { ShopifyCart } from './cart/store.js' */\n\n/**\n * @typedef {object} ConfiguredMarket The market of the config, before a page's or visitor's market applied.\n * @property {string | undefined} country\n * @property {string | undefined} language\n * @property {string | undefined} locale\n */\n\n/** @type {ConfiguredMarket} */\nlet configuredMarket = { country: undefined, language: undefined, locale: undefined };\n\n/** Whether the page arrived at last was built for its own market, which the next page without one switches back from. */\nlet lastPageHadOwnMarket = false;\n\n/**\n * `<meta name=\"tether-page-country\" content=\"DE\">`, with `tether-page-language` and `tether-page-locale`. Never\n * remembered: it belongs to the page, not to the visitor.\n *\n * @returns {Market | null} `null` when the page has no valid country of its own.\n */\nfunction pageMarket() {\n /** @param {string} name */\n const meta = (name) =>\n document.querySelector(`meta[name=\"${cfg.prefix}-page-${name}\"]`)?.getAttribute('content') || undefined;\n const country = toCountry(meta('country'));\n if (!country) return null;\n return { country, language: toLanguage(meta('language')) ?? undefined, locale: meta('locale') };\n}\n\n/**\n * Without `markets.detect` only the visitor's saved choice applies, read without loading the markets part.\n *\n * @returns {Promise<Market | DetectedMarket | null>}\n */\nasync function visitorMarket() {\n const markets = cfg.markets ?? {};\n if (markets.detect === false) return null;\n if (!markets.detect) return markets.remember === false ? null : readSavedMarket();\n try {\n return (await loadPart('markets')).detectMarket(markets);\n } catch (error) {\n reportError(error, 'markets');\n return null;\n }\n}\n\n/**\n * Sets `cfg`'s market for the first page, over the configured one.\n *\n * @param {TetherOptions} overrides What `init()` was called with: a `locale` there wins over the visitor's.\n * @returns {Promise<void>}\n */\nexport async function applyStartMarket(overrides) {\n configuredMarket = { country: cfg.country, language: cfg.language, locale: cfg.locale };\n const page = pageMarket();\n lastPageHadOwnMarket = page !== null;\n if (page) {\n cfg.country = page.country;\n cfg.language = page.language;\n if (page.locale) cfg.locale = page.locale;\n return;\n }\n const market = await visitorMarket();\n if (!market) return;\n if (market.country) cfg.country = market.country;\n if (market.language) cfg.language = market.language;\n if (market.locale && !overrides.locale) cfg.locale = market.locale;\n log('market', market);\n}\n\n/**\n * @param {string | undefined} a\n * @param {string | undefined} b\n */\nconst sameCode = (a, b) => (a ?? '').toUpperCase() === (b ?? '').toUpperCase();\n\n/**\n * The market to switch to on arriving at the current page. A page built for a market switches to it; the first page\n * without one after such a page switches back to the visitor's own choice, else to the configured market.\n *\n * @returns {{ country: string, language: string | undefined, locale: string | undefined } | null} `null` when the page\n * stays in the market in use.\n */\nexport function marketForArrival() {\n const page = pageMarket();\n const leftOwnMarket = page === null && lastPageHadOwnMarket;\n lastPageHadOwnMarket = page !== null;\n const target = page ?? (leftOwnMarket ? (readSavedMarket() ?? configuredMarket) : null);\n if (!target?.country) return null;\n if (sameCode(target.country, cfg.country) && sameCode(target.language, cfg.language)) return null;\n return { country: target.country, language: target.language, locale: target.locale };\n}\n\n/**\n * `Tether.setCountry('DE')`: loads the markets part on first use.\n *\n * @param {string} code\n * @param {SetCountryOptions} [options]\n * @returns {Promise<ShopifyCart | null>} The cart once everything is in the new market.\n */\nexport function setCountry(code, options) {\n return loadPart('markets').then((part) => part.setCountry(code, options));\n}\n", "/**\n * The core's side of customer accounts, which are an optional part: whether a page needs the part, and\n * `Tether.account`, whose functions load it on first call. Every function returns a promise, the part's own sync ones\n * (`isLoggedIn`) too, because the part may still have to load.\n */\nimport { cfg, reportError } from './config.js';\nimport { attr } from './dom.js';\nimport { loadPart } from './lazy.js';\nimport { within } from './mounting.js';\n/** @import { Parts } from './lazy.js' */\n\n/** @typedef {Parts['account']} AccountPart */\n/**\n * @template {keyof AccountPart} Name\n * @typedef {Awaited<ReturnType<AccountPart[Name]>>} AccountResult\n */\n/**\n * @template {keyof AccountPart} Name\n * @typedef {(...args: Parameters<AccountPart[Name]>) => Promise<AccountResult<Name>>} AccountFunction\n */\n/** @typedef {{ [Name in keyof AccountPart]: AccountFunction<Name> }} AccountApi */\n\n/** The attributes of the account markup: a page with one of them loads the part. */\nconst ACCOUNT_ATTRIBUTES = [\n 'account-login',\n 'account-bind',\n 'account-link',\n 'orders',\n 'order',\n 'addresses',\n 'subscriptions',\n 'profile-form',\n 'address-form',\n];\n\n/** @returns {string} A selector for every element the account part fills in or shows. */\nconst accountSelector = () =>\n [...ACCOUNT_ATTRIBUTES.map((name) => `[${attr(name)}]`), `[${attr('show')}^=\"logged-\"]`].join(',');\n\n/**\n * Whether this browser keeps an account session or the hint of one, so a page without account markup still finishes\n * a login. Storage throws where the browser blocks it, and then there is no session.\n *\n * @returns {boolean}\n */\nfunction hasSavedSession() {\n const sessionKey = `${cfg.prefix}:account:${cfg.domain}`;\n const hintKey = `${cfg.prefix}:account-hint:${cfg.domain}`;\n try {\n return Boolean(\n sessionStorage.getItem(sessionKey) || localStorage.getItem(sessionKey) || localStorage.getItem(hintKey),\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Loads the account part and mounts it on `root`, when accounts are configured and the page needs them: account\n * markup in `root`, a login coming back from Shopify (`?code=`), or a saved session.\n *\n * @param {ParentNode} root\n */\nexport function mountAccountIfUsed(root) {\n if (!cfg.account?.clientId && !cfg.account?.server) return;\n const needed =\n within(root, accountSelector()).length > 0 || /[?&]code=/.test(window.location.search) || hasSavedSession();\n if (!needed) return;\n loadPart('account')\n .then((part) => part.mountAccount(root))\n .catch((/** @type {unknown} */ error) => {\n reportError(error, 'account');\n });\n}\n\n/**\n * @template {keyof AccountPart} Name\n * @param {Name} name\n * @returns {AccountFunction<Name>} `name` of the account part, called once the part has loaded.\n */\nfunction fromPart(name) {\n return (...args) =>\n loadPart('account').then((part) => {\n // `Name` picks one function of the part, and `args` are that function's parameters.\n const call =\n /**\n * @type {(...callArgs: Parameters<AccountPart[Name]>) => AccountResult<Name> | PromiseLike<AccountResult<Name>>}\n */ (part[name]);\n return call(...args);\n });\n}\n\n/**\n * `Tether.account`: the account part's functions, each loading the part on first call. A plain object, so `await\n * Tether.account` and `Object.keys(Tether.account)` behave as for any object.\n *\n * @type {AccountApi}\n */\nexport const accountApi = {\n login: fromPart('login'),\n logout: fromPart('logout'),\n handleCallback: fromPart('handleCallback'),\n getToken: fromPart('getToken'),\n isLoggedIn: fromPart('isLoggedIn'),\n query: fromPart('query'),\n customer: fromPart('customer'),\n orders: fromPart('orders'),\n order: fromPart('order'),\n updateProfile: fromPart('updateProfile'),\n addresses: fromPart('addresses'),\n saveAddress: fromPart('saveAddress'),\n deleteAddress: fromPart('deleteAddress'),\n subscriptions: fromPart('subscriptions'),\n subscriptionAction: fromPart('subscriptionAction'),\n requestReturn: fromPart('requestReturn'),\n render: fromPart('render'),\n mountAccount: fromPart('mountAccount'),\n};\n", "/**\n * The cart's markup controls, delegated from the document so they keep working across page swaps: open, close,\n * clear and checkout buttons, a line's +, - and remove buttons, its quantity input and plan select, the cart note, and\n * the keyboard of the open drawer (Escape closes it, Tab stays inside it).\n */\nimport { cfg, reportError } from '../config.js';\nimport { Cart, trapFocus } from '../cart.js';\nimport { sel, busy } from '../dom.js';\n\n/** @returns {string} The attribute a rendered cart line carries its line id in. */\nconst lineKeyAttribute = () => `data-${cfg.prefix}-key`;\n\n/**\n * @param {EventTarget | null} target\n * @returns {target is Element}\n */\nconst isElement = (target) => target instanceof window.Element;\n\n/**\n * @param {Element} target\n * @returns {{ line: Element, id: string } | null} The rendered cart line `target` is in, with its line id.\n */\nfunction lineOf(target) {\n const line = target.closest(`[${lineKeyAttribute()}]`);\n const id = line?.getAttribute(lineKeyAttribute());\n return line && id ? { line, id } : null;\n}\n\n/**\n * @param {Promise<unknown>} change\n * @param {string} context\n */\nfunction reportFailure(change, context) {\n change.catch((/** @type {unknown} */ error) => {\n reportError(error, context);\n });\n}\n\n/**\n * A line's remove, + and - buttons.\n *\n * @param {MouseEvent} event\n * @param {Element} target\n */\nfunction onLineClick(event, target) {\n const found = lineOf(target);\n if (!found?.line.closest(sel('cart-lines'))) return;\n const { line, id } = found;\n if (target.closest(sel('line-remove'))) {\n event.preventDefault();\n line.classList.add('is-busy');\n reportFailure(Cart.removeLine(id), 'cart line');\n return;\n }\n const delta = lineDelta(target);\n if (!delta || !Cart.lines.some((candidate) => candidate.id === id)) return;\n event.preventDefault();\n reportFailure(Cart.changeQuantity(id, delta), 'cart line');\n}\n\n/**\n * @param {Element} target\n * @returns {1 | -1 | 0} The quantity change of a + or - button, 0 for anything else.\n */\nfunction lineDelta(target) {\n if (target.closest(sel('line-plus'))) return 1;\n if (target.closest(sel('line-minus'))) return -1;\n return 0;\n}\n\n/** @param {MouseEvent} event */\nfunction onClick(event) {\n const { target } = event;\n if (!isElement(target)) return;\n if (target.closest(sel('cart-open'))) {\n event.preventDefault();\n Cart.toggle();\n return;\n }\n if (target.closest(sel('cart-close'))) {\n event.preventDefault();\n Cart.close();\n return;\n }\n const clear = target.closest(sel('cart-clear'));\n if (clear) {\n event.preventDefault();\n void busy(clear, () =>\n Cart.clear().catch((/** @type {unknown} */ error) => {\n reportError(error, 'cart clear');\n }),\n );\n return;\n }\n const checkout = target.closest(sel('checkout'));\n if (checkout) {\n event.preventDefault();\n void busy(checkout, () => Cart.checkout());\n return;\n }\n onLineClick(event, target);\n}\n\n/**\n * The line shows `is-busy` and `aria-busy` until Shopify has answered; the next render removes them.\n *\n * @param {Element} line\n * @param {Promise<unknown>} change\n * @param {string} context\n */\nfunction showLineBusy(line, change, context) {\n line.classList.add('is-busy');\n line.setAttribute('aria-busy', 'true');\n reportFailure(change, context);\n}\n\n/** @param {Event} event */\nfunction onChange(event) {\n const { target } = event;\n if (!isElement(target)) return;\n const found = lineOf(target);\n if (found && target instanceof window.HTMLInputElement && target.matches(sel('line', 'quantity'))) {\n showLineBusy(found.line, Cart.updateLine(found.id, parseInt(target.value, 10) || 0), 'cart line');\n } else if (found && target instanceof window.HTMLSelectElement && target.matches(sel('line-plan'))) {\n showLineBusy(found.line, Cart.updateLine(found.id, { sellingPlanId: target.value || null }), 'cart line plan');\n } else if (hasValue(target) && target.matches(sel('cart-note'))) {\n reportFailure(Cart.setNote(target.value), 'cart note');\n }\n}\n\n/**\n * @param {Element} target\n * @returns {target is HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement}\n */\nconst hasValue = (target) =>\n target instanceof window.HTMLInputElement ||\n target instanceof window.HTMLTextAreaElement ||\n target instanceof window.HTMLSelectElement;\n\n/** @param {KeyboardEvent} event */\nfunction onKeydown(event) {\n if (!Cart.isOpen()) return;\n if (event.key === 'Escape') {\n Cart.close();\n return;\n }\n trapFocus(event);\n}\n\n/** Binds the document-wide listeners, once per page load of the script. */\nexport function bindCartControls() {\n document.addEventListener('click', onClick);\n document.addEventListener('change', onChange);\n document.addEventListener('keydown', onKeydown);\n}\n", "/**\n * The discount code form (`tether-discount-form` with `tether-discount-input`) and the remove buttons of applied codes\n * (`tether-discount-remove` inside `tether-discount-code`), delegated from the document. A code Shopify refuses marks\n * the form `is-invalid` (and the input `aria-invalid`) until the visitor types again.\n */\nimport { reportError } from '../config.js';\nimport { TetherError } from '../client.js';\nimport { Cart } from '../cart.js';\nimport { attr, sel, busy, emit } from '../dom.js';\n\n/**\n * @param {EventTarget | null} target\n * @returns {target is Element}\n */\nconst isElement = (target) => target instanceof window.Element;\n\n/**\n * @param {Element} form\n * @returns {HTMLInputElement | null}\n */\nfunction codeInputOf(form) {\n const input = form.querySelector(sel('discount-input')) ?? form.querySelector('input');\n return input instanceof window.HTMLInputElement ? input : null;\n}\n\n/**\n * @param {Element} form\n * @param {HTMLInputElement | null} input\n * @param {boolean} invalid\n */\nfunction markInvalid(form, input, invalid) {\n form.classList.toggle('is-invalid', invalid);\n if (invalid) input?.setAttribute('aria-invalid', 'true');\n else input?.removeAttribute('aria-invalid');\n}\n\n/**\n * @param {Element} form\n * @param {HTMLInputElement | null} input\n * @param {string} code\n */\nasync function applyCode(form, input, code) {\n try {\n await Cart.applyDiscount(code);\n markInvalid(form, input, false);\n emit('discount-applied', { code }, form);\n if (input) input.value = '';\n } catch (error) {\n markInvalid(form, input, true);\n if (error instanceof TetherError && error.code === 'INVALID_DISCOUNT') emit('discount-invalid', { code }, form);\n else reportError(error, 'discount');\n }\n}\n\n/** @param {SubmitEvent} event */\nfunction onSubmit(event) {\n const { target } = event;\n const form = isElement(target) ? target.closest(sel('discount-form')) : null;\n if (!form) return;\n event.preventDefault();\n const input = codeInputOf(form);\n const code = input?.value.trim();\n if (!code) return;\n void busy(form, () => applyCode(form, input, code));\n}\n\n/** @param {Event} event */\nfunction onInput(event) {\n const { target } = event;\n if (!isElement(target)) return;\n const form = target.closest(sel('discount-form'));\n if (!form) return;\n form.classList.remove('is-invalid');\n target.removeAttribute('aria-invalid');\n}\n\n/** @param {MouseEvent} event */\nfunction onClick(event) {\n const { target } = event;\n const remove = isElement(target) ? target.closest(sel('discount-remove')) : null;\n if (!remove) return;\n event.preventDefault();\n const code = remove.closest(sel('discount-code'))?.getAttribute(attr('discount-code'));\n if (!code) return;\n Cart.removeDiscount(code).catch((/** @type {unknown} */ error) => {\n reportError(error, 'discount');\n });\n}\n\n/** Binds the document-wide listeners, once per page load of the script. */\nexport function bindDiscountControls() {\n // Capture: the submit is handled before a router (Astro's ClientRouter) turns it into a navigation.\n document.addEventListener('submit', onSubmit, true);\n document.addEventListener('input', onInput);\n document.addEventListener('click', onClick);\n}\n", "/**\n * The document-wide listeners whose work is in the optional extras part, loaded when one of them first has work:\n * group add buttons, the cart or market changing in another tab, and shareable variant links. A part that can't load\n * (a self-hosted site without `tether.extras.min.js`) is reported, so the missing file shows.\n */\nimport { cfg, reportError } from '../config.js';\nimport { attr, sel, busy } from '../dom.js';\nimport { loadPart } from '../lazy.js';\n/** @import { ShopifyCart } from '../cart/store.js' */\n\n/** @typedef {Parameters<typeof import('../extras.js').writeVariantUrl>[1]} VariantChoice */\n\n/**\n * `[tether-group]` with `[tether-group-add]`: adds every product scope inside the group in one request.\n *\n * @param {Element} button\n * @returns {Promise<ShopifyCart | null>}\n */\nexport const addGroup = (button) => loadPart('extras').then((part) => part.addGroup(button));\n\n/** @param {unknown} error */\nconst reportExtrasError = (error) => {\n reportError(error, 'extras');\n};\n\n/** @param {MouseEvent} event */\nfunction onClick(event) {\n const { target } = event;\n const button = target instanceof window.Element ? target.closest(sel('group-add')) : null;\n if (!button) return;\n event.preventDefault();\n busy(button, () => addGroup(button)).catch(reportExtrasError);\n}\n\n/** @param {StorageEvent} event */\nfunction onStorage(event) {\n if (!cfg.domain || !event.key?.startsWith(`${cfg.prefix}:`)) return;\n loadPart('extras')\n .then((part) => {\n part.onStorage(event);\n })\n .catch(reportExtrasError);\n}\n\n/** @param {CustomEvent<VariantChoice>} event `tether:variant-changed`, which a product scope emits. */\nfunction onVariantChanged(event) {\n const { target } = event;\n if (!(target instanceof window.Element)) return;\n if (!cfg.variantUrl && !target.hasAttribute(attr('variant-url'))) return;\n loadPart('extras')\n .then((part) => {\n part.writeVariantUrl(target, event.detail);\n })\n .catch(reportExtrasError);\n}\n\n/** Binds the document-wide listeners, once per page load of the script. */\nexport function bindExtrasControls() {\n document.addEventListener('click', onClick);\n window.addEventListener('storage', onStorage);\n // Only product scopes emit this event, always with a CustomEvent.\n document.addEventListener(`${cfg.prefix}:variant-changed`, /** @type {EventListener} */ (onVariantChanged));\n}\n", "/**\n * How the page follows the visitor across pages and markets: Astro's ClientRouter (`astro:page-load`,\n * `astro:before-swap`) mounts each new page in its market and closes the cart while leaving; a country select\n * switches the market; back online, what failed to load loads again.\n */\nimport { cfg, reportError } from '../config.js';\nimport { attr, sel } from '../dom.js';\nimport { liveLists, retryFailed } from '../mounting.js';\nimport { marketForArrival, setCountry } from '../page-market.js';\n\n/**\n * @typedef {object} PageHooks What the entry module does for a page.\n * @property {() => Promise<unknown>} ready Settles once `init()` has applied the visitor's market.\n * @property {(root: Document) => unknown} mount\n * @property {() => void} unmount\n */\n\n/**\n * The body the last full-document mount ran on: Astro's first `astro:page-load` comes after that mount.\n *\n * @type {HTMLElement | null} */\nlet mountedBody = null;\n\n/** Records a mount of the whole document, so the `astro:page-load` of the same page sends no second round of requests. */\nexport function rememberDocumentMount() {\n mountedBody = document.body;\n}\n\n/** @param {PageHooks} hooks */\nasync function onPageLoad(hooks) {\n await hooks.ready();\n const target = marketForArrival();\n if (!target) {\n if (mountedBody !== document.body) hooks.mount(document);\n return;\n }\n try {\n await setCountry(target.country, { language: target.language ?? null, locale: target.locale, remember: false });\n } catch (error) {\n reportError(error, 'country');\n }\n hooks.mount(document);\n}\n\n/** @param {PageHooks} hooks */\nfunction bindAstroRouter(hooks) {\n document.addEventListener('astro:page-load', () => {\n void onPageLoad(hooks);\n });\n document.addEventListener('astro:before-swap', () => {\n mountedBody = null;\n hooks.unmount();\n });\n}\n\n/** @param {Event} event */\nfunction onChange(event) {\n const { target } = event;\n if (!(target instanceof window.HTMLSelectElement) || !target.matches(sel('country-select'))) return;\n if (!target.value) return;\n setCountry(target.value).catch((/** @type {unknown} */ error) => {\n reportError(error, 'country');\n });\n}\n\n/** Loads the failed products and lists again. */\nfunction onOnline() {\n retryFailed();\n liveLists.forEach((list) => {\n if (list.root.getAttribute(attr('state')) === 'error') void list.load();\n });\n}\n\n/**\n * Binds the document-wide listeners, once per page load of the script.\n *\n * @param {PageHooks} hooks\n */\nexport function bindNavigation(hooks) {\n if (cfg.astro) bindAstroRouter(hooks);\n document.addEventListener('change', onChange);\n window.addEventListener('online', onOnline);\n}\n", "/**\n * Tether's entry: `window.Tether`, `init()`, `mount()` and the start of the plain `<script>` setup.\n *\n * <script>window.TETHER_CONFIG = { domain: 'x.myshopify.com', token: '...' }</script>\n * <script src=\"tether.min.js\" defer></script>\n *\n * With page transitions (Barba, Swup): set `autoMount: false`, call `Tether.init()` once and\n * `Tether.mount(container)` after every page enter.\n */\nimport { cfg, configure, isConfigured, log, warn, reportError } from './config.js';\nimport { gql, TetherError, withContext } from './client.js';\nimport { Cart } from './cart.js';\nimport { scopes } from './product.js';\nimport { ListScope, listSelector } from './collection.js';\nimport {\n getProduct,\n getProducts,\n getRecommendations,\n clearProductCache,\n primeProduct,\n normalizeProductKey,\n} from './loader.js';\nimport * as plans from './selling-plans.js';\nimport { resolveProductKey } from './status.js';\nimport { sel, emit, formatMoney, imageUrl } from './dom.js';\nimport { loadPart, coreModules } from './lazy.js';\nimport {\n mountedLists,\n liveLists,\n pruneLive,\n within,\n mountProduct,\n hydrateFromPage,\n settleMarket,\n trackMarket,\n} from './mounting.js';\nimport { applyStartMarket, setCountry } from './page-market.js';\nimport { accountApi, mountAccountIfUsed } from './account-api.js';\nimport { bindCartControls } from './controls/cart-controls.js';\nimport { bindDiscountControls } from './controls/discount.js';\nimport { addGroup, bindExtrasControls } from './controls/extras.js';\nimport { bindNavigation, rememberDocumentMount } from './controls/navigation.js';\n/** @import { TetherConfig, TetherOptions, MarketsConfig } from './config.js' */\n/** @import { ShopifyCart } from './cart/store.js' */\n/** @import { ProductScope } from './product.js' */\n/** @import { DiagnoseOptions } from './diagnose.js' */\n\nexport { addGroup, setCountry };\n\nexport const VERSION = '0.6.8';\n\n/** The events the analytics part reports, buffered from `init()` until the part has loaded. */\nconst ANALYTICS_EVENTS = ['product-ready', 'list-ready', 'cart-updated', 'cart-toggled', 'checkout', 'search'];\n\n/** Milliseconds `observe` waits after the last added node, so a burst of additions mounts once. */\nconst OBSERVE_DEBOUNCE_MS = 50;\n\n/**\n * @typedef {object} TetherGlobals What the page sets on `window` for Tether, and `window.Tether` itself.\n * @property {TetherOptions} [TETHER_CONFIG] The site's config; `configure()` validates it.\n * @property {string} [TETHER_INTEGRATION] Set by a framework integration (Astro) that starts Tether itself.\n * @property {TetherApi} [Tether]\n */\n\n/** @returns {Window & TetherGlobals} */\nconst pageGlobals = () => window;\n\n/** @type {Promise<TetherApi | null> | null} */\nlet initPromise = null;\n\n/** @type {MutationObserver | null} */\nlet observer = null;\n\n/** @type {Event[] | null} The analytics part's queue, created once by the first `init()` with `analytics`. */\nlet analyticsQueue = null;\n\n/** @type {boolean} The document-wide listeners are bound once, by the first configured `init()`. */\nlet controlsBound = false;\n\n/**\n * Mounts the lists of `root` and the product scopes in them as they render.\n *\n * @param {ParentNode} root\n * @returns {number} The lists mounted.\n */\nfunction mountLists(root) {\n let count = 0;\n within(root, listSelector()).forEach((el) => {\n if (mountedLists.has(el)) return;\n mountedLists.add(el);\n count++;\n const list = new ListScope(el);\n liveLists.add(list);\n el.addEventListener(`${cfg.prefix}:list-rendered`, (event) => {\n // The list emits this CustomEvent once its products are in the page.\n mount(/** @type {CustomEvent<{ container: ParentNode }>} */ (event).detail.container);\n });\n void trackMarket(list.load());\n });\n return count;\n}\n\n/**\n * Loads each optional part `root` uses: the country select, customer accounts and search as you type.\n *\n * @param {ParentNode} root\n */\nfunction mountParts(root) {\n if (within(root, `${sel('country-select')},${sel('country-bind')}`).length) {\n loadPart('markets')\n .then((part) => part.renderCountrySelects(root))\n .catch((/** @type {unknown} */ error) => {\n reportError(error, 'markets');\n });\n }\n mountAccountIfUsed(root);\n if (within(root, sel('search')).length) {\n loadPart('search')\n .then((part) => {\n part.mountSearch(root);\n })\n .catch((/** @type {unknown} */ error) => {\n reportError(error, 'search');\n });\n }\n}\n\n/**\n * Mounts every product scope and product list inside `root`. Safe to call repeatedly.\n *\n * @param {ParentNode} [root]\n * @returns {number} The scopes and lists newly mounted.\n */\nexport function mount(root = document) {\n if (!isConfigured()) return 0;\n if (root === document) rememberDocumentMount();\n // Page transitions detach old roots: they aren't kept alive.\n pruneLive();\n // Products the server rendered into the page need no request.\n hydrateFromPage(root.ownerDocument ?? document);\n let count = mountLists(root);\n within(root, sel('product')).forEach((el) => {\n if (mountProduct(el)) count++;\n });\n mountParts(root);\n settleMarket();\n Cart.render();\n log(`mounted ${count} scope(s)`, root);\n return count;\n}\n\n/** Call before a page transition removes the page: closes the cart drawer. */\nexport function unmount() {\n Cart.close();\n}\n\n/**\n * @param {Element | null | undefined} el\n * @returns {ProductScope | null} The product scope `el` is in.\n */\nexport function getScope(el) {\n const root = el?.closest(sel('product'));\n return root ? (scopes.get(root) ?? null) : null;\n}\n\nfunction bindControls() {\n if (controlsBound) return;\n controlsBound = true;\n bindCartControls();\n bindDiscountControls();\n bindExtrasControls();\n bindNavigation({ ready: () => initPromise ?? Promise.resolve(null), mount, unmount });\n}\n\n/** Buffers Tether's events until the analytics part has loaded, so none are missed. */\nfunction startAnalyticsQueue() {\n /** @type {Event[]} */\n const queue = [];\n analyticsQueue = queue;\n ANALYTICS_EVENTS.forEach((name) => {\n document.addEventListener(`${cfg.prefix}:${name}`, (event) => queue.push(event));\n });\n document.addEventListener('astro:page-load', () => queue.push(new CustomEvent(`${cfg.prefix}:page`)));\n loadPart('analytics')\n .then((part) => part.startAnalytics(queue))\n .catch((/** @type {unknown} */ error) => {\n reportError(error, 'analytics');\n });\n}\n\n/**\n * A saved cart from another market moves to this one, so its prices match the page's.\n *\n * @param {ShopifyCart | null} cart\n * @returns {Promise<ShopifyCart | null>}\n */\nasync function cartInPageMarket(cart) {\n const country = cfg.country?.toUpperCase();\n const cartCountry = cart?.buyerIdentity.countryCode;\n if (!cart || !country || !cartCountry || cartCountry === country) return cart;\n try {\n return await Cart.setBuyerIdentity({ countryCode: country }, { create: false });\n } catch (error) {\n reportError(error, 'cart country');\n return cart;\n }\n}\n\n/**\n * Configures Tether (`window.TETHER_CONFIG` with `overrides` over it), applies the visitor's market and loads the\n * cart. A second call without overrides returns the first one's promise.\n *\n * @param {TetherOptions} [overrides]\n * @returns {Promise<TetherApi | null>} `null` without a domain and token, when Tether stays idle.\n */\nexport function init(overrides = {}) {\n if (initPromise && !Object.keys(overrides).length) return initPromise;\n configure({ ...pageGlobals().TETHER_CONFIG, ...overrides });\n if (!isConfigured()) {\n warn('TETHER_CONFIG is missing domain or token. Tether is idle.');\n initPromise = Promise.resolve(null);\n return initPromise;\n }\n bindControls();\n if (cfg.observe) startObserver();\n if (cfg.analytics && !analyticsQueue) startAnalyticsQueue();\n initPromise = applyStartMarket(overrides)\n .then(() => Cart.init())\n .then(cartInPageMarket)\n .then((cart) => {\n emit('ready', { cart });\n return api;\n });\n return initPromise;\n}\n\n/** `observe`: mounts the elements added to the page later. */\nfunction startObserver() {\n if (observer || typeof MutationObserver === 'undefined') return;\n /** @type {ReturnType<typeof setTimeout> | undefined} */\n let timer;\n /** @type {Set<Element>} */\n const queued = new Set();\n observer = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n mutation.addedNodes.forEach((node) => {\n if (node instanceof window.Element) queued.add(node);\n });\n });\n clearTimeout(timer);\n timer = setTimeout(() => {\n queued.forEach((node) => {\n if (node.isConnected) mount(node);\n });\n queued.clear();\n }, OBSERVE_DEBOUNCE_MS);\n });\n observer.observe(document.body, { childList: true, subtree: true });\n}\n\n/**\n * @param {MarketsConfig | null} [markets] Default `markets` of the config.\n */\nconst detectMarket = (markets) => loadPart('markets').then((part) => part.detectMarket(markets ?? cfg.markets));\n\nconst getLocalization = () => loadPart('markets').then((part) => part.getLocalization());\n\n/** @param {Omit<DiagnoseOptions, 'version'>} [options] */\nconst diagnose = (options) => loadPart('diagnose').then((part) => part.diagnose({ ...options, version: VERSION }));\n\n/**\n * Listens to the Tether event `<prefix>:<name>`.\n *\n * @param {string} name\n * @param {(detail: unknown, event: CustomEvent) => void} listener\n * @returns {() => void} Stops listening.\n */\nfunction on(name, listener) {\n /** @param {Event} event */\n const handler = (event) => {\n const custom = /** @type {CustomEvent} Tether's events are CustomEvents. */ (event);\n listener(custom.detail, custom);\n };\n document.addEventListener(`${cfg.prefix}:${name}`, handler);\n return () => {\n document.removeEventListener(`${cfg.prefix}:${name}`, handler);\n };\n}\n\nexport const api = {\n VERSION,\n init,\n mount,\n unmount,\n /** @returns {TetherConfig} */\n get config() {\n return cfg;\n },\n /** @returns {Promise<TetherApi | null>} */\n get ready() {\n return initPromise ?? Promise.resolve(null);\n },\n query: gql,\n withContext,\n cart: Cart,\n getProduct,\n getProducts,\n getRecommendations,\n getScope,\n addGroup,\n account: accountApi,\n primeProduct,\n normalizeProductKey,\n clearProductCache,\n formatMoney,\n imageUrl,\n plans,\n TetherError,\n resolveProductKey,\n setCountry,\n detectMarket,\n getLocalization,\n diagnose,\n __core: coreModules,\n // The `<script>` build's parts register here when their file has loaded.\n __parts: /** @type {Record<string, unknown>} */ ({}),\n on,\n};\n\n/** @typedef {typeof api} TetherApi */\n\nexport default api;\n\n/**\n * The plain `<script>` setup starts by itself, unless `autoMount: false` or a framework integration (Astro), which\n * starts Tether itself.\n */\nfunction autoStart() {\n const globals = pageGlobals();\n globals.Tether = api;\n if (!globals.TETHER_CONFIG || globals.TETHER_CONFIG.autoMount === false || globals.TETHER_INTEGRATION) return;\n const start = () => {\n init()\n .then(() => mount(document))\n .catch((/** @type {unknown} */ error) => {\n reportError(error, 'init');\n });\n };\n if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start, { once: true });\n else start();\n}\n\nif (typeof window !== 'undefined' && typeof document !== 'undefined') autoStart();\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["config_exports", "__export", "DEFAULTS", "cfg", "configure", "isConfigured", "log", "reportError", "resolveConfig", "toMetafieldIdentifier", "warn", "PREFIX", "METAFIELD_PART", "METAFIELD_NAMESPACE", "COUNT_OPTIONS", "HOOK_OPTIONS", "invalidOption", "name", "value", "fallback", "countOption", "choiceOption", "choices", "choice", "domainOption", "ref", "namespace", "key", "dot", "metafieldsOption", "refs", "identifier", "options", "domain", "prefix", "resolved", "args", "error", "context", "hookError", "client_exports", "__export", "TetherError", "endpoint", "gql", "request", "unwrap", "withContext", "market_codes_exports", "__export", "toCountry", "toLanguage", "COUNTRY", "NOT_A_COUNTRY", "REGIONAL_LANGUAGES", "LANGUAGE", "value", "code", "raw", "primary", "TetherError", "message", "status", "errors", "userErrors", "code", "endpoint", "conf", "cfg", "withContext", "query", "ctx", "args", "country", "toCountry", "language", "toLanguage", "tag", "RETRY_BACKOFF_MS", "THROTTLE_BACKOFF_MS", "SECURITY_REJECTION", "INVENTORY_FIELD", "storesWithoutInventory", "storeOf", "sleep", "ms", "resolve", "statusText", "adminHint", "graphQLFailure", "res", "error", "text", "attempt", "variables", "canRetry", "json", "data", "request", "context", "store", "retries", "sent", "outcome", "log", "gql", "options", "unwrap", "payload", "name", "cart_exports", "__export", "Cart", "trapFocus", "dom_exports", "__export", "attr", "busy", "cdnUrl", "emit", "formatDate", "formatMoney", "formatPercent", "get", "has", "hasTemplate", "imageUrl", "notifyLayoutChanged", "parseJSONAttr", "productUrl", "qsa", "repeat", "repeatKeyed", "sameImage", "scoped", "sel", "setImage", "setSelected", "setStoreHtml", "setText", "setTextTracked", "show", "toAttributes", "watchImages", "attr", "name", "cfg", "sel", "value", "get", "el", "has", "qsa", "root", "selector", "scoped", "scopeSelector", "emit", "detail", "target", "store_html_exports", "__export", "storeHtmlFragment", "BLOCKED_ELEMENTS", "URL_ATTRIBUTES", "SCRIPT_URL", "DATA_IMAGE", "IGNORED_IN_SCHEME", "isUnsafeAttribute", "element", "attribute", "name", "url", "clean", "root", "html", "document", "template", "shopify_values_exports", "__export", "STORE_ENV_NAMES", "formatMoney", "isHttpsUrl", "isSecretShopifyToken", "productKey", "productUrl", "url", "token", "money", "locale", "amount", "productPath", "handle", "id", "numericId", "raw", "value", "imageUrl", "url", "width", "height", "crop", "parsed", "error", "sizeAttribute", "el", "name", "attr", "cdnUrl", "sameImage", "a", "b", "cssUrl", "char", "setImage", "alt", "src", "templates", "hasTemplate", "container", "copyOf", "template", "templateOf", "known", "first", "repeat", "items", "render", "warn", "item", "index", "node", "leave", "onLeave", "done", "error", "reportError", "insertFresh", "wanted", "fresh", "onEnter", "previous", "repeatKeyed", "keyOf", "keyAttribute", "cfg", "leavingAttribute", "live", "existing", "key", "staying", "current", "SEEN", "SHOWN", "PREVIOUS_DISPLAY", "LAYOUT_DEBOUNCE_MS", "productUrl", "handle", "id", "cfg", "formatOr", "format", "fallback", "error", "formatPercent", "percentage", "locale", "formatMoney", "money", "formatDate", "iso", "setStoreHtml", "el", "html", "storeHtmlFragment", "isTextField", "isInput", "setText", "value", "text", "readText", "setTextTracked", "before", "reportError", "reveal", "previous", "attr", "show", "visible", "setSelected", "selected", "input", "layoutTimer", "notifyLayoutChanged", "reason", "ScrollTrigger", "emit", "watchImages", "root", "loading", "img", "left", "done", "busy", "task", "parseJSONAttr", "name", "raw", "get", "warn", "toAttributes", "attributes", "attribute", "key", "fragments_exports", "__export", "cartFragment", "collectionFields", "productFragment", "MONEY", "IMAGE", "metafieldsField", "metafields", "identifiers", "ref", "identifier", "toMetafieldIdentifier", "namespace", "key", "SELLING_PLAN_FIELDS", "ALLOCATION_FIELDS", "productFragment", "o", "cfg", "cartFragment", "collectionFields", "selling_plans_exports", "__export", "GID", "allPlans", "allocationFor", "findPlan", "hasPlans", "planAdjustment", "planCheckoutCharge", "planPrice", "planSavings", "plansForVariant", "toGid", "value", "type", "text", "product", "group", "plan", "variant", "planId", "allocation", "adjustment", "oneTime", "onPlan", "ref", "plans", "gid", "needle", "option", "FOCUSABLE", "FOCUS_AFTER_OPEN_MS", "openWithoutDrawer", "returnFocus", "isFocusable", "el", "focusables", "drawer", "qsa", "drawers", "sel", "isOpenDrawer", "cfg", "isOpen", "all", "syncDrawerAria", "open", "button", "get", "focusInto", "target", "openCart", "opened", "first", "emit", "closeCart", "hadFocus", "toggleCart", "trapFocus", "event", "inside", "last", "active", "leaving", "loader_exports", "__export", "clearProductCache", "getProduct", "getProducts", "getRecommendations", "hydrateProducts", "normalizeProductKey", "primeProduct", "refreshProducts", "takeStale", "MISS_CACHE_MS", "FRESH_MS", "productCache", "waiting", "stale", "freshAt", "pending", "flushScheduled", "generation", "isGid", "key", "normalizeProductKey", "productKey", "primeProduct", "product", "loaded", "getProduct", "rawKey", "TetherError", "cached", "loading", "resolve", "reject", "flush", "batchQuery", "keys", "ids", "handles", "definitions", "selections", "variables", "handle", "index", "productFragment", "settleWaiting", "settle", "waiter", "forgetMissLater", "batchGeneration", "miss", "query", "log", "data", "gql", "error", "found", "now", "clearProductCache", "hydrateProducts", "products", "takeStale", "refreshProducts", "normalized", "COLLECTION_QUERY", "collectionFields", "SEARCH_QUERY", "getProducts", "collection", "first", "cfg", "after", "sortKey", "reverse", "filters", "fragment", "rest", "getRecommendations", "intent", "byId", "list", "DECIMAL", "toScaledInteger", "amount", "fractionDigits", "match", "sign", "whole", "fraction", "digits", "fractionLength", "isGreaterAmount", "other", "scaled", "scaledOther", "DEFAULT_TITLE", "quantityOf", "line", "pending", "numericId", "gid", "lineUrl", "variant", "base", "productUrl", "query", "planId", "productTitle", "LINE_TEXT", "option", "formatMoney", "view", "component", "ATTRIBUTE_KEY", "lineValue", "key", "name", "attribute", "fillPlanSelect", "select", "product", "plans", "allPlans", "allowOneTime", "get", "oneTime", "attr", "choices", "plan", "signature", "choice", "show", "renderLineState", "node", "isSubscription", "warning", "candidate", "qsa", "sel", "el", "setTextTracked", "conditions", "isGreaterAmount", "renderLine", "setImage", "value", "getProduct", "error", "reportError", "renderConditions", "cart", "count", "hasSubscription", "code", "renderFields", "setText", "container", "repeat", "discount", "target", "renderCart", "money", "syncDrawerAria", "isOpen", "repeatKeyed", "cfg", "notifyLayoutChanged", "showSavedCount", "status", "warnings", "pendingQuantities", "customer", "cartStatus", "currentCart", "currentWarnings", "statusOf", "cart", "seenKey", "cfg", "readStorageIfAllowed", "key", "writeStorageIfAllowed", "value", "savedCartId", "forgetSavedCart", "keepQuietly", "render", "renderCart", "announce", "reason", "emit", "commit", "settleLoad", "outcome", "setFailure", "error", "showLastKnownCount", "count", "showSavedCount", "setWarnings", "notes", "note", "index", "other", "waitOnly", "serial", "previous", "task", "run", "runInOrder", "enqueue", "pendingQuantityOf", "line", "quantityOf", "meta", "isOpen", "subscribe", "listener", "events", "name", "call", "UNKNOWN_CART_MESSAGE", "isCartGone", "error", "TetherError", "userError", "graphQLError", "toLineInput", "input", "quantity", "options", "spec", "merchandiseId", "GID", "asked", "line", "planId", "attributes", "toAttributes", "mutationText", "name", "args", "inner", "cartFragment", "send", "variables", "data", "gql", "payload", "unwrap", "setWarnings", "createCart", "buyerIdentity", "cfg", "customer", "withIdentity", "mutateCart", "createInput", "cartId", "savedCartId", "forgetSavedCart", "log", "fetchCart", "id", "fetchCheckoutUrl", "toLineUpdate", "lineId", "patch", "change", "variantId", "updateLines", "lines", "removeLines", "lineIds", "setLineQuantity", "target", "askCheckoutUrl", "cartId", "fetchCheckoutUrl", "url", "error", "accountCheckoutUrl", "customer", "reportError", "checkoutUrl", "cartAnswer", "answer", "TetherError", "detachOpenerIfAllowed", "tab", "checkout", "target", "cfg", "savedCartId", "cart", "currentCart", "isHttpsUrl", "emit", "currentLines", "currentCart", "changeQuantity", "lineId", "delta", "line", "candidate", "target", "pendingQuantityOf", "job", "pendingQuantities", "announce", "isLatest", "enqueue", "cart", "setLineQuantity", "commit", "keepQuietly", "discountCodesFrom", "codes", "current", "discount", "list", "code", "mergedAttributes", "attributes", "merged", "attribute", "toAttributes", "value", "key", "init", "id", "savedCartId", "settleLoad", "showLastKnownCount", "fetchCart", "forgetSavedCart", "error", "reportError", "isCartGone", "Cart", "cartStatus", "setFailure", "currentWarnings", "customer", "token", "fetchUrl", "link", "render", "subscribe", "input", "quantity", "options", "lines", "toLineInput", "mutateCart", "emit", "cfg", "openCart", "patch", "toLineUpdate", "updateLines", "lineIds", "ids", "removeLines", "note", "variables", "wanted", "TetherError", "unwanted", "existing", "buyerIdentity", "create", "checkout", "drawers", "isOpen", "closeCart", "toggleCart", "product_exports", "__export", "ProductScope", "rememberOptionNames", "scopes", "MINOR_UNITS_PER_UNIT", "PERCENT", "toMinorUnits", "money", "fromMinorUnits", "minorUnits", "currencyCode", "timesQuantity", "quantity", "selectionOf", "variant", "option", "findVariant", "product", "selected", "isValueAvailable", "name", "value", "normalisePurchase", "wanted", "plans", "allPlans", "known", "plan", "onVariant", "allocationFor", "initialChoice", "sellingPlan", "defaultPlan", "defaultPurchase", "variants", "wantedId", "GID", "start", "candidate", "fromUrl", "findPlan", "offered", "kind", "showConditions", "lowStock", "variantCount", "sale", "requiresSellingPlan", "stock", "low", "onSale", "productView", "choice", "exact", "purchase", "planId", "allocation", "price", "planPrice", "compareAt", "planSavings", "variantBindTexts", "view", "format", "compareAtPrice", "forQuantity", "texts", "charge", "planCheckoutCharge", "planBindTexts", "adjustment", "planAdjustment", "NTH_IMAGE_BIND", "METAFIELD_BIND", "MULTI_LINE_METAFIELD", "ALL_PLAN_GROUPS", "isSelect", "el", "selectsIn", "scope", "selector", "renderGallery", "product", "images", "rendered", "node", "hasTemplate", "img", "index", "sameImage", "repeat", "image", "target", "sel", "qsa", "setImage", "renderMetafield", "ref", "dot", "namespace", "key", "metafield", "field", "setText", "PRODUCT_TEXTS", "formatDate", "formatMoney", "renderTags", "exclude", "tag", "tags", "renderProductBind", "text", "setStoreHtml", "productUrl", "renderIndexedBind", "nth", "renderOptionLists", "container", "name", "get", "option", "candidate", "has", "show", "value", "attr", "swatchEl", "swatch", "renderSelects", "select", "variant", "plans", "plan", "oneTime", "oneTimeLabel", "renderPlanLists", "raw", "group", "writeProduct", "status_exports", "__export", "STATUS_KEYS", "boundary", "isNotFound", "ownedBy", "resolveProductKey", "setScopeStatus", "URL_SOURCE", "decodePathSegment", "segment", "error", "resolveProductKey", "el", "location", "name", "raw", "get", "source", "key", "segments", "STATUS_KEYS", "isScopeStatus", "value", "status", "codeOf", "isNotFound", "boundary", "sel", "ownedBy", "root", "errorCode", "code", "setScopeStatus", "notFound", "failed", "attr", "scoped", "shows", "show", "button", "FORMAT", "formatMoney", "formatPercent", "isInput", "el", "addButtonLabel", "button", "label", "qsa", "sel", "original", "renderOptionStates", "scope", "view", "product", "selectedValue", "authored", "setText", "get", "container", "name", "node", "value", "setSelected", "unavailable", "isValueAvailable", "selectsIn", "select", "renderPurchaseStates", "variant", "purchase", "isSubscription", "isSelect", "mode", "planId", "allocationFor", "plan", "candidate", "texts", "planBindTexts", "text", "renderConditions", "conditions", "STATUS_KEYS", "status", "key", "visible", "ownedBy", "show", "renderAddButtons", "disabled", "soldOutText", "subscribeText", "writeVariant", "variantBindTexts", "setImage", "attr", "productSelector", "sel", "isField", "el", "isElement", "target", "closestOwn", "scope", "selector", "onAddClick", "button", "label", "original", "addButtonLabel", "addingText", "get", "busy", "setText", "error", "reportError", "emit", "onClick", "event", "optionValue", "optionList", "plan", "purchase", "plus", "minus", "add", "onChange", "value", "bindProductEvents", "scopes", "productSelector", "sel", "knownOptionNames", "rememberOptionNames", "products", "product", "option", "isInput", "el", "isField", "lineAttributeValue", "ProductScope", "root", "allPlans", "params", "choice", "initialChoice", "get", "cfg", "has", "attr", "bindProductEvents", "watchImages", "notifyLayoutChanged", "emit", "variantId", "same", "variant", "selectionOf", "selector", "inner", "scoped", "authored", "options", "index", "kind", "wanted", "normalisePurchase", "planId", "plan", "allocationFor", "line", "attributes", "json", "parseJSONAttr", "fixed", "toAttributes", "fields", "value", "name", "withValue", "firstWithValue", "next", "score", "closest", "best", "id", "candidate", "GID", "mode", "ref", "findPlan", "quantity", "minimum", "setText", "cart", "Cart", "writeProduct", "view", "productView", "writeVariant", "collection_exports", "__export", "ListScope", "listSelector", "URL_QUERY_SOURCE", "listSelector", "sel", "isElement", "target", "toLimit", "raw", "toIntent", "ListScope", "root", "setScopeStatus", "event", "more", "busy", "selector", "scoped", "query", "get", "first", "sortKey", "has", "key", "resolveProductKey", "scope", "TetherError", "getRecommendations", "token", "stale", "recommendations", "limit", "page", "getProducts", "emit", "error", "isNotFound", "reportError", "collection", "el", "setText", "setStoreHtml", "setImage", "container", "repeat", "node", "product", "attr", "empty", "show", "notifyLayoutChanged", "mounting_exports", "__export", "hydrateFromPage", "liveLists", "liveProducts", "mountProduct", "mountedLists", "mountedProducts", "pruneLive", "retryFailed", "settleMarket", "trackMarket", "within", "HYDRATE_SELECTOR", "mountedProducts", "mountedLists", "liveProducts", "liveLists", "latestRequest", "pruneLive", "el", "list", "within", "root", "selector", "qsa", "applyPageTitle", "product", "template", "get", "mountWithoutKey", "fromUrl", "raw", "setScopeStatus", "emit", "listSelector", "warn", "attr", "showLoadFailure", "key", "error", "notFound", "isNotFound", "reportError", "log", "mountProduct", "source", "resolveProductKey", "request", "isLatest", "scopes", "trackMarket", "getProduct", "existing", "ProductScope", "cfg", "takeStale", "queueRefresh", "retryFailed", "refreshQueue", "flushRefresh", "applyRefresh", "fresh", "scope", "rootKey", "keys", "refreshProducts", "promise", "index", "marketPending", "loading", "settleMarket", "waits", "wait", "isUsable", "sameCode", "a", "b", "readScripts", "hydrateFromPage", "script", "json", "country", "language", "products", "usable", "rememberOptionNames", "hydrateProducts", "cfg", "config_exports", "coreModules", "client_exports", "dom_exports", "fragments_exports", "loader_exports", "selling_plans_exports", "status_exports", "cart_exports", "product_exports", "collection_exports", "mounting_exports", "market_codes_exports", "shopify_values_exports", "store_html_exports", "MINIFIED_SCRIPT", "coreScript", "coreScriptUrl", "parts", "partsFolder", "folder", "loadScript", "name", "url", "resolve", "reject", "script", "Tether", "part", "loadPart", "loading", "error", "suffix", "storageKey", "cfg", "localStorageIfAllowed", "parseJsonOrNull", "text", "error", "toMarket", "value", "country", "toCountry", "locale", "toLanguage", "readSavedMarket", "storage", "localStorageIfAllowed", "storageKey", "configuredMarket", "lastPageHadOwnMarket", "pageMarket", "meta", "name", "cfg", "country", "toCountry", "toLanguage", "visitorMarket", "markets", "readSavedMarket", "loadPart", "error", "reportError", "applyStartMarket", "overrides", "page", "market", "log", "sameCode", "a", "b", "marketForArrival", "leftOwnMarket", "target", "setCountry", "code", "options", "part", "ACCOUNT_ATTRIBUTES", "accountSelector", "name", "attr", "hasSavedSession", "sessionKey", "cfg", "hintKey", "mountAccountIfUsed", "root", "within", "loadPart", "part", "error", "reportError", "fromPart", "args", "call", "accountApi", "lineKeyAttribute", "cfg", "isElement", "target", "lineOf", "line", "id", "reportFailure", "change", "context", "error", "reportError", "onLineClick", "event", "found", "sel", "Cart", "delta", "lineDelta", "candidate", "onClick", "clear", "busy", "checkout", "showLineBusy", "onChange", "hasValue", "onKeydown", "trapFocus", "bindCartControls", "isElement", "target", "codeInputOf", "form", "input", "sel", "markInvalid", "invalid", "applyCode", "code", "Cart", "emit", "error", "TetherError", "reportError", "onSubmit", "event", "busy", "onInput", "onClick", "remove", "attr", "bindDiscountControls", "addGroup", "button", "loadPart", "part", "reportExtrasError", "error", "reportError", "onClick", "event", "target", "sel", "busy", "onStorage", "cfg", "onVariantChanged", "attr", "bindExtrasControls", "mountedBody", "rememberDocumentMount", "onPageLoad", "hooks", "target", "marketForArrival", "setCountry", "error", "reportError", "bindAstroRouter", "onChange", "event", "sel", "onOnline", "retryFailed", "liveLists", "list", "attr", "bindNavigation", "cfg", "VERSION", "ANALYTICS_EVENTS", "OBSERVE_DEBOUNCE_MS", "pageGlobals", "initPromise", "observer", "analyticsQueue", "controlsBound", "mountLists", "root", "count", "within", "listSelector", "el", "mountedLists", "list", "ListScope", "liveLists", "cfg", "event", "mount", "trackMarket", "mountParts", "sel", "loadPart", "part", "error", "reportError", "mountAccountIfUsed", "isConfigured", "rememberDocumentMount", "pruneLive", "hydrateFromPage", "mountProduct", "settleMarket", "Cart", "log", "unmount", "getScope", "scopes", "bindControls", "bindCartControls", "bindDiscountControls", "bindExtrasControls", "bindNavigation", "startAnalyticsQueue", "queue", "name", "cartInPageMarket", "cart", "country", "cartCountry", "init", "overrides", "configure", "startObserver", "applyStartMarket", "emit", "api", "warn", "timer", "queued", "mutations", "mutation", "node", "detectMarket", "markets", "getLocalization", "diagnose", "options", "on", "listener", "handler", "custom", "gql", "withContext", "getProduct", "getProducts", "getRecommendations", "addGroup", "accountApi", "primeProduct", "normalizeProductKey", "clearProductCache", "formatMoney", "imageUrl", "selling_plans_exports", "TetherError", "resolveProductKey", "setCountry", "coreModules", "index_default", "autoStart", "globals", "start"]
|
|
7
7
|
}
|