@occluze/tether 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/esm/astro.js +1 -1
- package/dist/esm/chunks/account-FKLGF264.js +1 -0
- package/dist/esm/chunks/{account-pages-XR6QZ3DX.js → account-pages-PNORWX72.js} +1 -1
- package/dist/esm/chunks/analytics-V24XX2J7.js +1 -0
- package/dist/esm/chunks/{chunk-255K6OZ7.js → chunk-2IHA3PVC.js} +1 -1
- package/dist/esm/chunks/chunk-2LYWZ72A.js +1 -0
- package/dist/esm/chunks/{chunk-3OEIEDTK.js → chunk-2NV5PSJ2.js} +1 -1
- package/dist/esm/chunks/chunk-2X5U24IC.js +1 -0
- package/dist/esm/chunks/chunk-5B36ISJF.js +1 -0
- package/dist/esm/chunks/chunk-6WE7XCHH.js +1 -0
- package/dist/esm/chunks/chunk-6ZIOAYKF.js +1 -0
- package/dist/esm/chunks/{chunk-FM7ZLLVP.js → chunk-CR5IGHCO.js} +1 -1
- package/dist/esm/chunks/{chunk-KNJB72OO.js → chunk-E3JL6WS3.js} +1 -1
- package/dist/esm/chunks/{chunk-KVPLRK6Y.js → chunk-F5CLIGSC.js} +1 -1
- package/dist/esm/chunks/{chunk-O4G2PAQC.js → chunk-GOKJQGLG.js} +1 -1
- package/dist/esm/chunks/chunk-RW23CJDZ.js +1 -0
- package/dist/esm/chunks/chunk-TW34GYSL.js +1 -0
- package/dist/esm/chunks/chunk-VKKKH75V.js +1 -0
- package/dist/esm/chunks/{chunk-A3GXCQJ4.js → chunk-YWQWLKFW.js} +1 -1
- package/dist/esm/chunks/chunk-YYNBHXQF.js +1 -0
- package/dist/esm/chunks/{diagnose-XQQTDHLQ.js → diagnose-3RTKEBNW.js} +1 -1
- package/dist/esm/chunks/extras-O54VUXK6.js +1 -0
- package/dist/esm/chunks/lists-MRTI5RXY.js +1 -0
- package/dist/esm/chunks/markets-ui-P7G33T6Y.js +1 -0
- package/dist/esm/chunks/search-YSRDFVD7.js +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/server.js +2 -2
- package/dist/tether.account-pages.js +2 -2
- package/dist/tether.account-pages.min.js +1 -1
- package/dist/tether.account.js +2 -2
- package/dist/tether.account.min.js +1 -1
- package/dist/tether.analytics.js +2 -2
- package/dist/tether.analytics.min.js +1 -1
- package/dist/tether.diagnose.js +4 -4
- package/dist/tether.diagnose.min.js +2 -2
- package/dist/tether.extras.js +1 -1
- package/dist/tether.extras.min.js +1 -1
- package/dist/tether.js +83 -206
- package/dist/tether.lists.js +268 -0
- package/dist/tether.lists.min.js +1 -0
- package/dist/tether.markets.js +3 -3
- package/dist/tether.markets.min.js +1 -1
- package/dist/tether.min.js +1 -4
- package/dist/tether.min.js.map +4 -4
- package/dist/tether.search.js +2 -2
- package/dist/tether.search.min.js +1 -1
- package/dist/types/src/client.d.ts +6 -6
- package/dist/types/src/collection.d.ts +7 -23
- package/dist/types/src/config-sections.d.ts +7 -0
- package/dist/types/src/config.d.ts +6 -0
- package/dist/types/src/index.d.ts +6 -5
- package/dist/types/src/lazy.d.ts +1 -0
- package/dist/types/src/lists.d.ts +20 -0
- package/dist/types/src/loader.d.ts +7 -27
- package/dist/types/src/mounting.d.ts +1 -6
- package/dist/types/src/product-shape.d.ts +13 -36
- package/dist/types/src/server.d.ts +5 -4
- package/dist/types/src/shopify-values.d.ts +6 -0
- package/dist/types/src/storefront/catalog.d.ts +2 -4
- package/dist/types/src/version.d.ts +1 -0
- package/package.json +5 -5
- package/dist/esm/chunks/account-5X563BON.js +0 -1
- package/dist/esm/chunks/analytics-JSFHDBU3.js +0 -1
- package/dist/esm/chunks/chunk-55OHYO66.js +0 -1
- package/dist/esm/chunks/chunk-EW3GKRT4.js +0 -1
- package/dist/esm/chunks/chunk-GXCCTPDF.js +0 -1
- package/dist/esm/chunks/chunk-J7GYROV4.js +0 -4
- package/dist/esm/chunks/chunk-WNFEYPHV.js +0 -1
- package/dist/esm/chunks/chunk-WXF4L42L.js +0 -1
- package/dist/esm/chunks/extras-6WLNUEGD.js +0 -1
- package/dist/esm/chunks/markets-ui-OAJW4PFU.js +0 -1
- package/dist/esm/chunks/search-LUECIYJR.js +0 -1
package/dist/tether.search.js
CHANGED
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
|
|
20
20
|
// tether-core:client.ts
|
|
21
21
|
var m2 = window.Tether.__core["client.ts"];
|
|
22
|
-
var [endpoint, gql, orNull, shaped, TetherError] = m2;
|
|
22
|
+
var [endpoint, gql, matches, orNull, shaped, TetherError] = m2;
|
|
23
23
|
|
|
24
24
|
// tether-core:dom.ts
|
|
25
25
|
var m3 = window.Tether.__core["dom.ts"];
|
|
26
|
-
var [ANALYTICS_EVENTS, attr, attributesFromJson, emit, formatDate, formatMoney, get, has, hasTemplate, isOwnEvent, parseJSONAttr, productUrl, qsa, repeat, sel, setImage, setText, show] = m3;
|
|
26
|
+
var [ANALYTICS_EVENTS, attr, attributesFromJson, busy, emit, formatDate, formatMoney, get, has, hasTemplate, isOwnEvent, notifyLayoutChanged, parseJSONAttr, productUrl, qsa, repeat, scoped, sel, setImage, setStoreHtml, setText, show] = m3;
|
|
27
27
|
|
|
28
28
|
// tether-core:mounting.ts
|
|
29
29
|
var m4 = window.Tether.__core["mounting.ts"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{var
|
|
1
|
+
(()=>{var T=Object.defineProperty;var D=(i,t,e)=>t in i?T(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var V=(i,t)=>{for(var e in t)T(i,e,{get:t[e],enumerable:!0})};var o=(i,t,e)=>D(i,typeof t!="symbol"?t+"":t,e);var w={};V(w,{mountSearch:()=>Z});var F=window.Tether.__core["config.ts"],[u,tt,b,et,rt,S,it]=F;var j=window.Tether.__core["client.ts"],[st,E,ot,x,A,at]=j;var K=window.Tether.__core["dom.ts"],[ct,L,ht,ut,I,mt,k,m,dt,pt,ft,gt,wt,N,h,C,yt,l,R,Tt,P,d]=K;var Q=window.Tether.__core["mounting.ts"],[St,Et,xt,At,Lt,q]=Q;var Y=A({predictiveSearch:x({products:[{priceRange:"object"}],collections:["object"],queries:[{text:"string"}]})}),B="query TetherPredictive($q:String!,$limit:Int!){predictiveSearch(query:$q,limit:$limit,limitScope:EACH,types:[PRODUCT,COLLECTION,QUERY]){products{id handle title availableForSale featuredImage{url altText}priceRange{minVariantPrice{amount currencyCode}}}collections{handle title image{url altText}}queries{text}}}",J=6,z=2,W="/search",M=new WeakSet,_=0;function $(i,t,e){return parseInt(m(i,t)||"",10)||e}var U=i=>i.tagName==="A"?i:i.querySelector("a");function f(i,t){h(i,l("search-bind")).forEach(e=>{let r=m(e,"search-bind");r==="image"?R(e,t.image?.url,t.image?.altText||t.title):(r==="title"||r==="price"||r==="text")&&t[r]!=null&&P(e,t[r])})}function H(i,t){let e=U(i);e&&(t&&e.setAttribute("href",t),e.setAttribute("role","option"))}var g=class{constructor(t,e,r){o(this,"root");o(this,"input");o(this,"results");o(this,"limit");o(this,"minCharacters");o(this,"resultsId");o(this,"searchNumber",0);o(this,"timer");o(this,"lastTerm","");o(this,"cache",new Map);this.root=t,this.input=e,this.results=r,this.limit=$(t,"search-limit",J),this.minCharacters=$(t,"search-min",z),r.id||(_+=1,r.id=`${u.prefix}-search-${_}`),this.resultsId=r.id,this.setUpAria(),this.listen()}setUpAria(){this.input.setAttribute("role","combobox"),this.input.setAttribute("aria-autocomplete","list"),this.input.setAttribute("aria-controls",this.resultsId),this.input.setAttribute("aria-expanded","false"),this.input.setAttribute("autocomplete","off"),this.results.hasAttribute("role")||this.results.setAttribute("role","listbox"),this.results.hidden=!0}listen(){this.input.addEventListener("input",()=>{let t=this.input.value.trim();t!==this.lastTerm&&(this.lastTerm=t,clearTimeout(this.timer),this.timer=setTimeout(()=>void this.search(t),u.searchDelay))}),this.input.addEventListener("focus",()=>{this.input.value.trim().length>=this.minCharacters&&this.options().length&&this.open(!0)}),this.input.addEventListener("keydown",t=>{this.onKeydown(t)}),document.addEventListener("click",t=>{this.root.contains(t.target)||this.open(!1)})}setState(t){this.root.setAttribute(L("search-state"),t)}open(t){this.root.classList.toggle("is-open",t),this.results.hidden=!t,this.input.setAttribute("aria-expanded",String(t)),t||this.input.removeAttribute("aria-activedescendant")}options(){return h(this.results,'[role="option"]')}async fetchResults(t){let e=this.cache.get(t);if(e)return e;let r=await E(B,{q:t,limit:this.limit},Y);return this.cache.set(t,r.predictiveSearch),r.predictiveSearch}async search(t){this.searchNumber+=1;let e=this.searchNumber;if(t.length<this.minCharacters){this.open(!1),this.setState("idle");return}this.setState("loading");try{let r=await this.fetchResults(t);e===this.searchNumber&&this.render(r,t)}catch(r){if(e!==this.searchNumber){b("a superseded search failed",r);return}this.setState("error"),S(r,"search")}}fillList(t,e,r){h(this.results,l(t)).forEach(a=>{C(a,e,r),d(a,e.length>0)})}queryUrl(t){let e=this.root.getAttribute("action")||W,r=e.includes("?")?"&":"?";return`${e}${r}${this.input.name||"q"}=${encodeURIComponent(t)}`}render(t,e){let r=t?.products??[],a=t?.collections??[],c=(t?.queries??[]).filter(s=>s.text.toLowerCase()!==e.toLowerCase());this.fillList("search-products",r,(s,n)=>{let O=k(n.priceRange.minVariantPrice);f(s,{title:n.title,price:O,image:n.featuredImage}),H(s,N(n.handle,n.id)),s.classList.toggle("is-sold-out",!n.availableForSale)}),this.fillList("search-collections",a,(s,n)=>{f(s,{title:n.title,image:n.image}),H(s,`${(u.collectionPath||"/collection").replace(/\/$/,"")}/${n.handle}`)}),this.fillList("search-queries",c,(s,n)=>{f(s,{text:n.text}),U(s)?.setAttribute("href",this.queryUrl(n.text))});let y=r.length+a.length+c.length;this.showCount(y),this.setState(y?"ready":"empty"),this.open(!0),I("search",{term:e,products:r,collections:a,queries:c},this.root)}showCount(t){h(this.root,l("show")).forEach(e=>{let r=m(e,"show");r==="search-empty"&&d(e,t===0),r==="search-results"&&d(e,t>0)}),this.options().forEach((e,r)=>{e.id||(e.id=`${this.resultsId}-${r}`),e.setAttribute("aria-selected","false")})}highlight(t,e){t.forEach((a,c)=>{a.setAttribute("aria-selected",String(c===e))});let r=t[e];r&&(this.input.setAttribute("aria-activedescendant",r.id),r.scrollIntoView?.({block:"nearest"}))}onKeydown(t){let e=this.options(),r=e.findIndex(a=>a.getAttribute("aria-selected")==="true");t.key==="ArrowDown"&&e.length?(t.preventDefault(),this.open(!0),this.highlight(e,(r+1)%e.length)):t.key==="ArrowUp"&&e.length?(t.preventDefault(),this.highlight(e,r<=0?e.length-1:r-1)):t.key==="Enter"&&r>=0?(t.preventDefault(),e[r]?.click()):t.key==="Escape"&&this.open(!1)}};function Z(i=document){for(let t of q(i,l("search"))){if(M.has(t))continue;M.add(t);let e=t.querySelector(l("search-input"))??t.querySelector("input"),r=t.querySelector(l("search-results"));e&&r&&new g(t,e,r)}}function p(i){return i!==null&&typeof i=="object"&&!Array.isArray(i)}function G(i){return p(i)&&p(i.__core)&&p(i.__parts)}function v(i,t){let e=Reflect.get(window,"Tether");if(!G(e))throw new Error(`tether.${i}.js runs after the Tether script, which loads it, and needs its window.Tether`);e.__parts[i]=t}v("search",w);})();
|
|
@@ -30,7 +30,7 @@ export declare class TetherError extends Error {
|
|
|
30
30
|
constructor(message: string, { status, errors, userErrors, code }?: TetherErrorDetails);
|
|
31
31
|
}
|
|
32
32
|
/** What a request needs from a config: the browser's `cfg`, or a config the server helpers build. */
|
|
33
|
-
export type StorefrontConfig = Pick<TetherConfig, 'domain' | 'token' | 'apiVersion' | 'country' | 'language' | 'maxAge' | 'retries'> & {
|
|
33
|
+
export type StorefrontConfig = Pick<TetherConfig, 'domain' | 'token' | 'apiVersion' | 'country' | 'language' | 'maxAge' | 'retries' | 'requestTimeout'> & {
|
|
34
34
|
fetch?: typeof fetch;
|
|
35
35
|
};
|
|
36
36
|
/** Checks a query's `data` before its caller reads it as a `T`. */
|
|
@@ -113,11 +113,11 @@ export declare function withContext(query: string, ctx?: {
|
|
|
113
113
|
* `conf.retries`; which failures are retried is the operation's (`Operation`).
|
|
114
114
|
*
|
|
115
115
|
* @param isData Checks that `data` has what the caller then reads, so a malformed answer fails here.
|
|
116
|
-
* @throws {TetherError} `NOT_CONFIGURED` without a domain or token, `NETWORK` when the store can't be reached
|
|
117
|
-
*
|
|
118
|
-
* GraphQL shape, or `data` that `isData` refuses),
|
|
119
|
-
* whether Shopify ran it (a top-level
|
|
120
|
-
* `HTTP_<status>` for any other HTTP or GraphQL failure.
|
|
116
|
+
* @throws {TetherError} `NOT_CONFIGURED` without a domain or token, `NETWORK` when the store can't be reached, the
|
|
117
|
+
* answer's body stops arriving or the whole answer takes longer than `conf.requestTimeout`, `INVALID_RESPONSE` for
|
|
118
|
+
* a 2xx whose body isn't valid (not JSON, not in the GraphQL shape, or `data` that `isData` refuses),
|
|
119
|
+
* `SERVER_ERROR` for a 2xx whose GraphQL errors leave open whether Shopify ran it (a top-level
|
|
120
|
+
* `INTERNAL_SERVER_ERROR`, or a mutation's errors without `data`), `HTTP_<status>` for any other HTTP or GraphQL failure.
|
|
121
121
|
*/
|
|
122
122
|
export declare function request<T>(conf: StorefrontConfig, query: QueryText, variables: Record<string, unknown>, isData: DataCheck<T>, { context, operation }?: RequestOptions): Promise<T>;
|
|
123
123
|
/** `request` with the browser's shared config. */
|
|
@@ -1,25 +1,9 @@
|
|
|
1
|
-
import type { Product } from './fragments.js';
|
|
2
|
-
import type { Collection, PageInfo, ProductQuery } from './loader.js';
|
|
3
1
|
export declare const listSelector: () => string;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/** Counts loads, so only the latest one renders. */
|
|
10
|
-
loadToken: number;
|
|
11
|
-
constructor(root: HTMLElement);
|
|
12
|
-
$(selector: string): HTMLElement[];
|
|
13
|
-
/** The collection or search query of the list's attributes. */
|
|
14
|
-
options(): ProductQuery;
|
|
15
|
-
/**
|
|
16
|
-
* The product of a recommendations list: a handle, `url:…` (one dynamic product page), or empty inside a product
|
|
17
|
-
* scope for that product.
|
|
18
|
-
*
|
|
19
|
-
* @throws {TetherError} `NOT_FOUND` when there is no product to recommend for.
|
|
20
|
-
*/
|
|
21
|
-
loadRecommendations(): Promise<Product[]>;
|
|
22
|
-
/** @param more Appends the next page instead of replacing the products. */
|
|
23
|
-
load(more?: boolean): Promise<void>;
|
|
24
|
-
render(): void;
|
|
2
|
+
/** A mounted list: its root, and loading its products again (after a country switch, or back online). */
|
|
3
|
+
export interface MountedList {
|
|
4
|
+
root: HTMLElement;
|
|
5
|
+
/** Never rejects: a failure shows in the list's state and is reported. */
|
|
6
|
+
load: () => Promise<void>;
|
|
25
7
|
}
|
|
8
|
+
/** @returns The list at `root`, in its loading state until its first load renders it. */
|
|
9
|
+
export declare function mountedList(root: HTMLElement): MountedList;
|
|
@@ -30,6 +30,13 @@ export declare function embedOriginsOption(value: unknown, invalid: Invalid): st
|
|
|
30
30
|
export declare function toMetafieldIdentifier(ref: unknown): MetafieldIdentifier | null;
|
|
31
31
|
/** @returns The refs that name a valid identifier, as written; each other one is skipped with a warning. */
|
|
32
32
|
export declare function metafieldsOption(value: unknown, invalid: Invalid): MetafieldRef[];
|
|
33
|
+
/** How each field of a nested option is read: the field's value when it is of the right kind, else `undefined`. */
|
|
34
|
+
type Schema<Section extends object> = {
|
|
35
|
+
[Key in keyof Section]-?: (value: unknown) => Section[Key] | undefined;
|
|
36
|
+
};
|
|
37
|
+
export declare const ACCOUNT: Schema<Partial<AccountConfig>>;
|
|
38
|
+
export declare const MARKETS: Schema<MarketsConfig>;
|
|
39
|
+
export declare const ANALYTICS: Schema<AnalyticsConfig>;
|
|
33
40
|
/**
|
|
34
41
|
* @param warn Says why an `account` without a usable `server` is off.
|
|
35
42
|
* @returns `null` without a usable `account.server`: nothing of the account part loads.
|
|
@@ -98,6 +98,12 @@ export interface TetherConfig {
|
|
|
98
98
|
* already have applied the change.
|
|
99
99
|
*/
|
|
100
100
|
retries: number;
|
|
101
|
+
/**
|
|
102
|
+
* Milliseconds a Storefront request may take, its body included, before it counts as a network error (0: no limit;
|
|
103
|
+
* at most 2147483647, the longest delay a timer keeps). A query is then retried; a mutation isn't, and a cart change
|
|
104
|
+
* loads the cart again.
|
|
105
|
+
*/
|
|
106
|
+
requestTimeout: number;
|
|
101
107
|
/** Refresh server-rendered products once in the background. */
|
|
102
108
|
revalidate: boolean;
|
|
103
109
|
/** The localStorage key of the cart id (default `<prefix>:cart:<domain>`). */
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/// <reference path="./globals.d.ts" />
|
|
2
2
|
import { query, TetherError, withContext } from './client.js';
|
|
3
|
-
import { getProduct,
|
|
3
|
+
import { getProduct, clearProductCache, primeProduct } from './loader.js';
|
|
4
4
|
import * as plans from './selling-plans.js';
|
|
5
5
|
import { resolveProductKey } from './status.js';
|
|
6
6
|
import { formatMoney, imageUrl } from './dom.js';
|
|
7
|
+
import { VERSION } from './version.js';
|
|
7
8
|
import { setCountry } from './page-market.js';
|
|
8
9
|
import { addGroup } from './controls/extras.js';
|
|
9
10
|
import type { TetherConfig, TetherOptions, MarketsConfig } from './config.js';
|
|
@@ -11,7 +12,8 @@ import type { ShopifyCart } from './cart/store.js';
|
|
|
11
12
|
import type { ProductScope } from './product.js';
|
|
12
13
|
import type { DiagnoseOptions } from './diagnose.js';
|
|
13
14
|
import type { TetherEvents } from './markup.js';
|
|
14
|
-
|
|
15
|
+
import type { ProductQuery } from './loader.js';
|
|
16
|
+
export { addGroup, setCountry, VERSION };
|
|
15
17
|
export type { TetherOptions as TetherConfig, TetherConfig as ResolvedTetherConfig } from './config.js';
|
|
16
18
|
export type { MarketsConfig, CartWarning } from './config.js';
|
|
17
19
|
export type { Money } from './shopify-values.js';
|
|
@@ -33,7 +35,6 @@ export type { AddressFields as CustomerAddressInput } from './account/operations
|
|
|
33
35
|
export type { CustomerAddress, Fulfillment, MailingAddress, OrderDetail, OrderDetailLine, SubscriptionContract, SubscriptionLine, } from './account/page-answers.js';
|
|
34
36
|
/** The helpers for selling plans, `Tether.plans`. */
|
|
35
37
|
export type SellingPlanHelpers = typeof plans;
|
|
36
|
-
export declare const VERSION = "0.8.0";
|
|
37
38
|
/**
|
|
38
39
|
* Mounts every product scope and product list inside `root`. Safe to call repeatedly.
|
|
39
40
|
*
|
|
@@ -111,8 +112,8 @@ declare const publicApi: {
|
|
|
111
112
|
toggle: typeof import("./cart/drawer.js").toggleCart;
|
|
112
113
|
};
|
|
113
114
|
getProduct: typeof getProduct;
|
|
114
|
-
getProducts:
|
|
115
|
-
getRecommendations: typeof getRecommendations;
|
|
115
|
+
getProducts: (query?: ProductQuery) => Promise<import("./loader.js").ProductPage>;
|
|
116
|
+
getRecommendations: typeof import("./lists.js").getRecommendations;
|
|
116
117
|
getScope: typeof getScope;
|
|
117
118
|
addGroup: (button: Element) => Promise<ShopifyCart | null>;
|
|
118
119
|
account: {
|
package/dist/types/src/lazy.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export interface Parts {
|
|
|
7
7
|
diagnose: typeof import('./diagnose.js');
|
|
8
8
|
markets: typeof import('./markets-ui.js');
|
|
9
9
|
search: typeof import('./search.js');
|
|
10
|
+
lists: typeof import('./lists.js');
|
|
10
11
|
extras: typeof import('./extras.js');
|
|
11
12
|
account: typeof import('./account.js');
|
|
12
13
|
'account-pages': typeof import('./account-pages.js');
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Product } from './fragments.js';
|
|
2
|
+
import type { ProductRef, RecommendationIntent } from './shopify-values.js';
|
|
3
|
+
import type { ProductPage, ProductQuery } from './loader.js';
|
|
4
|
+
/**
|
|
5
|
+
* A page of products from a collection (by handle) or from a search. Every product on it is cached.
|
|
6
|
+
*
|
|
7
|
+
* @throws {TetherError} `NOT_FOUND` for a collection the store doesn't have.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getProducts({ collection, query, first, after, sortKey, reverse, filters, }?: ProductQuery): Promise<ProductPage>;
|
|
10
|
+
/**
|
|
11
|
+
* Shopify's recommendations for a product. Every product in them is cached.
|
|
12
|
+
*
|
|
13
|
+
* @throws {TetherError} `NOT_FOUND` when `product` names no product (empty, `null` or `undefined`).
|
|
14
|
+
*/
|
|
15
|
+
export declare function getRecommendations(product: ProductRef | null | undefined, intent?: RecommendationIntent): Promise<Product[]>;
|
|
16
|
+
/**
|
|
17
|
+
* Loads the products of the list at `root` and renders them, replacing what it shows. Never rejects: a failure shows
|
|
18
|
+
* in the list's state and is reported.
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadList(root: HTMLElement): Promise<void>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { productKey } from './shopify-values.js';
|
|
2
2
|
import type { Product, Image } from './fragments.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { QueryText } from './client.js';
|
|
4
4
|
/** Accepts a handle, numeric id, gid or a full product URL. */
|
|
5
5
|
export declare const normalizeProductKey: typeof productKey;
|
|
6
6
|
/** Puts a product the page already has (from a collection query) in the cache, under its handle and its id. */
|
|
@@ -10,6 +10,12 @@ export declare function primeProduct(product: Product | null | undefined): void;
|
|
|
10
10
|
* @throws {TetherError} `NOT_FOUND` (rejected) for an empty key or a product the store doesn't have.
|
|
11
11
|
*/
|
|
12
12
|
export declare function getProduct(rawKey: string | number | null | undefined): Promise<Product>;
|
|
13
|
+
/**
|
|
14
|
+
* @param operation An operation that spreads `...TetherProduct`.
|
|
15
|
+
* @returns The operation with the product fragment (which starts on its own line), written for what the token may
|
|
16
|
+
* read.
|
|
17
|
+
*/
|
|
18
|
+
export declare const withProductFragment: (operation: string) => QueryText;
|
|
13
19
|
/** Forgets every product, for a new market: requests already sent no longer fill the cache. */
|
|
14
20
|
export declare function clearProductCache(): void;
|
|
15
21
|
/**
|
|
@@ -56,29 +62,3 @@ export interface ProductQuery {
|
|
|
56
62
|
/** `ProductFilter` values, for a collection. */
|
|
57
63
|
filters?: unknown[];
|
|
58
64
|
}
|
|
59
|
-
/** A collection's answer: `null` for a handle the store doesn't have. Its other fields are written as text. */
|
|
60
|
-
export declare const isCollectionAnswer: import("./client.js").DataCheck<{
|
|
61
|
-
collection: (Collection & {
|
|
62
|
-
products: ProductConnection;
|
|
63
|
-
}) | null;
|
|
64
|
-
}>;
|
|
65
|
-
export declare const isSearchAnswer: import("./client.js").DataCheck<{
|
|
66
|
-
products: ProductConnection;
|
|
67
|
-
}>;
|
|
68
|
-
export declare const isRecommendationsAnswer: import("./client.js").DataCheck<{
|
|
69
|
-
productRecommendations: Product[] | null;
|
|
70
|
-
}>;
|
|
71
|
-
/**
|
|
72
|
-
* A page of products from a collection (by handle) or from a search. Every product on it is cached.
|
|
73
|
-
*
|
|
74
|
-
* @throws {TetherError} `NOT_FOUND` for a collection the store doesn't have.
|
|
75
|
-
*/
|
|
76
|
-
export declare function getProducts({ collection, query, first, after, sortKey, reverse, filters, }?: ProductQuery): Promise<ProductPage>;
|
|
77
|
-
/**
|
|
78
|
-
* Shopify's recommendations for a product. Every product in them is cached.
|
|
79
|
-
*
|
|
80
|
-
* @param product A product, or its handle, id or gid.
|
|
81
|
-
*/
|
|
82
|
-
export declare function getRecommendations(product: string | number | {
|
|
83
|
-
id: string;
|
|
84
|
-
} | null | undefined, intent?: 'RELATED' | 'COMPLEMENTARY'): Promise<Product[]>;
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
interface MountedList {
|
|
3
|
-
root: Element;
|
|
4
|
-
load: (more?: boolean) => Promise<unknown>;
|
|
5
|
-
}
|
|
1
|
+
import type { MountedList } from './collection.js';
|
|
6
2
|
export declare const mountedProducts: WeakSet<Element>;
|
|
7
3
|
export declare const mountedLists: WeakSet<Element>;
|
|
8
4
|
/** Product roots to re-render after a country switch; pruned once disconnected. */
|
|
@@ -43,4 +39,3 @@ export declare function settleMarket(): void;
|
|
|
43
39
|
* added elements for `observe`.
|
|
44
40
|
*/
|
|
45
41
|
export declare function hydrateFromPage(root?: Document | Element): void;
|
|
46
|
-
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Product } from './fragments.js';
|
|
2
|
-
import type { PageInfo } from './loader.js';
|
|
2
|
+
import type { Collection, PageInfo } from './loader.js';
|
|
3
3
|
/** A page of a GraphQL connection of products. */
|
|
4
4
|
export interface ProductConnection {
|
|
5
5
|
nodes: Product[];
|
|
@@ -44,41 +44,6 @@ export declare const PRODUCT: {
|
|
|
44
44
|
}];
|
|
45
45
|
};
|
|
46
46
|
};
|
|
47
|
-
/** A page of products, with the `pageInfo` paging reads. */
|
|
48
|
-
export declare const PRODUCT_CONNECTION: {
|
|
49
|
-
readonly nodes: readonly [{
|
|
50
|
-
readonly id: "string";
|
|
51
|
-
readonly handle: "string";
|
|
52
|
-
readonly title: "string";
|
|
53
|
-
readonly options: readonly ["object"];
|
|
54
|
-
readonly images: {
|
|
55
|
-
readonly nodes: readonly ["object"];
|
|
56
|
-
};
|
|
57
|
-
readonly priceRange: {
|
|
58
|
-
readonly minVariantPrice: {
|
|
59
|
-
readonly amount: "string";
|
|
60
|
-
readonly currencyCode: "string";
|
|
61
|
-
};
|
|
62
|
-
readonly maxVariantPrice: {
|
|
63
|
-
readonly amount: "string";
|
|
64
|
-
readonly currencyCode: "string";
|
|
65
|
-
};
|
|
66
|
-
};
|
|
67
|
-
readonly variants: {
|
|
68
|
-
readonly nodes: readonly [{
|
|
69
|
-
readonly id: "string";
|
|
70
|
-
readonly price: {
|
|
71
|
-
readonly amount: "string";
|
|
72
|
-
readonly currencyCode: "string";
|
|
73
|
-
};
|
|
74
|
-
readonly selectedOptions: readonly ["object"];
|
|
75
|
-
}];
|
|
76
|
-
};
|
|
77
|
-
}];
|
|
78
|
-
readonly pageInfo: {
|
|
79
|
-
readonly hasNextPage: "boolean";
|
|
80
|
-
};
|
|
81
|
-
};
|
|
82
47
|
/** True for a value with the structure of `PRODUCT` and a non-empty id and handle. */
|
|
83
48
|
export declare const isProductShape: (value: unknown) => value is Product;
|
|
84
49
|
/**
|
|
@@ -88,3 +53,15 @@ export declare const isProductShape: (value: unknown) => value is Product;
|
|
|
88
53
|
export declare const PRODUCT_NODE: (node: unknown) => node is Product | {
|
|
89
54
|
id?: undefined;
|
|
90
55
|
};
|
|
56
|
+
/** A collection's answer: `null` for a handle the store doesn't have. Its other fields are written as text. */
|
|
57
|
+
export declare const isCollectionAnswer: import("./client.js").DataCheck<{
|
|
58
|
+
collection: (Collection & {
|
|
59
|
+
products: ProductConnection;
|
|
60
|
+
}) | null;
|
|
61
|
+
}>;
|
|
62
|
+
export declare const isSearchAnswer: import("./client.js").DataCheck<{
|
|
63
|
+
products: ProductConnection;
|
|
64
|
+
}>;
|
|
65
|
+
export declare const isRecommendationsAnswer: import("./client.js").DataCheck<{
|
|
66
|
+
productRecommendations: Product[] | null;
|
|
67
|
+
}>;
|
|
@@ -22,7 +22,10 @@ export type { JsonLdOptions } from './storefront/json-ld.js';
|
|
|
22
22
|
export type Storefront = ReturnType<typeof createStorefront>;
|
|
23
23
|
/** The options only a storefront has. */
|
|
24
24
|
interface ServerOptions {
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Replaces the global `fetch` (tests, caching). It must pass `init.signal` on to the request: `requestTimeout` ends a
|
|
27
|
+
* stalled request through that signal, and a request that ignores it is never ended.
|
|
28
|
+
*/
|
|
26
29
|
fetch?: typeof fetch;
|
|
27
30
|
/** Products per request for `allProducts()` (default 25). */
|
|
28
31
|
pageSize?: number;
|
|
@@ -78,9 +81,7 @@ export declare function createStorefront(options?: StorefrontOptions): {
|
|
|
78
81
|
pageInfo: import("./loader.js").PageInfo;
|
|
79
82
|
}) | null>;
|
|
80
83
|
allCollections: () => Promise<import("./loader.js").Collection[]>;
|
|
81
|
-
getRecommendations: (product:
|
|
82
|
-
id: string;
|
|
83
|
-
} | null | undefined, intent?: "RELATED" | "COMPLEMENTARY") => Promise<Product[]>;
|
|
84
|
+
getRecommendations: (product: import("./shopify-values.js").ProductRef | null | undefined, intent?: import("./shopify-values.js").RecommendationIntent) => Promise<Product[]>;
|
|
84
85
|
config: ServerConfig;
|
|
85
86
|
query: (query: string, variables?: Record<string, unknown>, requestOptions?: {
|
|
86
87
|
context?: boolean;
|
|
@@ -38,6 +38,12 @@ export declare function formatMoney(money: Money | null | undefined, locale: str
|
|
|
38
38
|
* @returns `null` when the path needs a handle or an id the product lacks: no link beats a wrong one.
|
|
39
39
|
*/
|
|
40
40
|
export declare function productUrl(productPath: string, handle: string | null | undefined, id?: string | null): string | null;
|
|
41
|
+
/** A product to recommend for: the product itself, or its handle, numeric id or gid. */
|
|
42
|
+
export type ProductRef = string | number | {
|
|
43
|
+
id: string;
|
|
44
|
+
};
|
|
45
|
+
/** Shopify's `ProductRecommendationIntent`. */
|
|
46
|
+
export type RecommendationIntent = 'RELATED' | 'COMPLEMENTARY';
|
|
41
47
|
/**
|
|
42
48
|
* The key Tether loads a product by: a handle, or a product gid.
|
|
43
49
|
*
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { StorefrontConfig } from '../client.js';
|
|
2
2
|
import type { ProductFragmentConfig, Product } from '../fragments.js';
|
|
3
|
+
import type { ProductRef, RecommendationIntent } from '../shopify-values.js';
|
|
3
4
|
import type { Collection, PageInfo, ProductPage } from '../loader.js';
|
|
4
5
|
/** What the catalog needs of a storefront's config. */
|
|
5
6
|
type CatalogConfig = StorefrontConfig & ProductFragmentConfig;
|
|
@@ -23,7 +24,6 @@ type CollectionWithProducts = Collection & {
|
|
|
23
24
|
products: Product[];
|
|
24
25
|
pageInfo: PageInfo;
|
|
25
26
|
};
|
|
26
|
-
type RecommendationIntent = 'RELATED' | 'COMPLEMENTARY';
|
|
27
27
|
/** @param pageSize Products per page when a query doesn't say. */
|
|
28
28
|
export declare function createCatalog(conf: CatalogConfig, pageSize: number): {
|
|
29
29
|
getProduct: (raw: string | number | null | undefined) => Promise<Product | null>;
|
|
@@ -31,8 +31,6 @@ export declare function createCatalog(conf: CatalogConfig, pageSize: number): {
|
|
|
31
31
|
allProducts: (options?: Omit<CatalogQuery, "first" | "after">) => Promise<Product[]>;
|
|
32
32
|
getCollection: (handle: string, options?: Omit<CatalogQuery, "collection">) => Promise<CollectionWithProducts | null>;
|
|
33
33
|
allCollections: () => Promise<Collection[]>;
|
|
34
|
-
getRecommendations: (product:
|
|
35
|
-
id: string;
|
|
36
|
-
} | null | undefined, intent?: RecommendationIntent) => Promise<Product[]>;
|
|
34
|
+
getRecommendations: (product: ProductRef | null | undefined, intent?: RecommendationIntent) => Promise<Product[]>;
|
|
37
35
|
};
|
|
38
36
|
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const VERSION = "0.9.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@occluze/tether",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Free, open-source alternative to Smootify and Storesynk (Shopyflow): Shopify products, cart and subscriptions in Webflow with HTML attributes. Optional Shopify to Webflow CMS sync.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/esm/index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"types": "./dist/types/src/presets/barba.d.ts",
|
|
23
23
|
"default": "./dist/presets/barba.esm.js"
|
|
24
24
|
},
|
|
25
|
-
"./dist
|
|
25
|
+
"./dist/tether.*": "./dist/tether.*"
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
28
|
"dist",
|
|
@@ -37,10 +37,11 @@
|
|
|
37
37
|
"lint": "eslint .",
|
|
38
38
|
"typecheck": "tsc -b",
|
|
39
39
|
"knip": "knip",
|
|
40
|
+
"lint:workflows": "node --experimental-strip-types scripts/lint-workflows.ts",
|
|
40
41
|
"deps": "depcruise --config .config/dependency-cruiser.cjs src server/src server/bin server/scripts scripts",
|
|
41
42
|
"check": "npm run format:check && npm run lint && npm run typecheck && npm run knip && npm run deps && npm test",
|
|
42
43
|
"prepare": "lefthook install",
|
|
43
|
-
"test": "node --experimental-strip-types --test test/*.test.js server/test/*.test.js && npm run test:types",
|
|
44
|
+
"test": "node --experimental-strip-types --import ./scripts/test-leaks.ts --test --test-timeout=600000 --test-force-exit --test-reporter=spec --test-reporter-destination=stdout --test-reporter=./scripts/test-leaks.ts --test-reporter-destination=stderr test/*.test.js server/test/*.test.js && npm run test:types",
|
|
44
45
|
"test:types": "tsc -p test/types/tsconfig.json",
|
|
45
46
|
"smoke": "node --experimental-strip-types scripts/smoke.ts",
|
|
46
47
|
"pretest": "node --experimental-strip-types scripts/build.ts --out .test-dist",
|
|
@@ -154,8 +155,7 @@
|
|
|
154
155
|
"scripts/*.ts",
|
|
155
156
|
"test/**/*.js",
|
|
156
157
|
"server/test/**/*.js",
|
|
157
|
-
"test/e2e/*.{js,mjs}"
|
|
158
|
-
"test/types/check.ts"
|
|
158
|
+
"test/e2e/*.{js,mjs}"
|
|
159
159
|
],
|
|
160
160
|
"project": [
|
|
161
161
|
"src/**/*.ts",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{f as j,g as V,h as G,i as R,m as v,n as H}from"./chunk-FM7ZLLVP.js";import{a as O,c as M}from"./chunk-KNJB72OO.js";import{a as W}from"./chunk-WNFEYPHV.js";import{f as q,g as F,h as P}from"./chunk-55OHYO66.js";import"./chunk-J7GYROV4.js";import{C as $,D as _,F as A,H as L,a as f,m as c,n as l,p as d,t as h,w as N,y as D}from"./chunk-EW3GKRT4.js";import{A as T,C as U,d as I,g as y,r as i,x as E,z as m}from"./chunk-GXCCTPDF.js";var g=null;function X(){let e=i.account?.server;if(!e)throw new f("Customer accounts need the Worker: set account.server",{code:"NOT_CONFIGURED"});return new URL(e,window.location.href).href.replace(/\/$/,"")}function B(e){e?q(O(),"1"):F(O())}async function ae(e,t){try{return await fetch(e,t)}catch(r){throw new f(`Network error: ${T(r)}`,{code:"NETWORK"})}}async function ue(e){let t;try{t=await e.json()}catch{return{}}return I(t)?t:{}}async function p(e,{method:t="GET",body:r}={}){let n={method:t,credentials:"include"};t==="POST"&&(n.headers={"Content-Type":"application/json","X-Tether-Account":"1"}),r&&(n.body=JSON.stringify(r));let s=await ae(`${X()}${e}`,n);if(s.status===401)return{kind:"logged-out"};let o=await ue(s);if(!s.ok){let u=y(o.error)??String(s.status),w=G(o.userErrors);throw new f(`Customer accounts: ${u}`,{status:s.status,...w.length>0&&{userErrors:w},...o.code==="INVALID"&&{code:"INVALID"}})}return{kind:"answer",data:o}}async function k(){if(!g){let e=await p("/me");g=e.kind==="answer"&&e.data.loggedIn===!0?{loggedIn:!0,customer:j(e.data.customer)}:{loggedIn:!1}}return B(g.loggedIn),g}var J=()=>g?.loggedIn===!0;function K(){g=null}function z(e){let t=i.account?.navigate;t?t(e):window.location.assign(e)}var de=e=>e||i.account?.locale||(i.locale||"").split("-")[0]||"";function Q({returnTo:e,locale:t}){let r=new URL(`${X()}/login`);r.searchParams.set("returnTo",e);let n=de(t);n&&r.searchParams.set("locale",n),i.country&&r.searchParams.set("country",i.country.toUpperCase()),z(r.toString())}async function Y(){let e=P.id();if(!(await k()).loggedIn||!e)return null;let t=await p("/cart",{method:"POST",body:{cartId:e}});return t.kind==="logged-out"?null:y(t.data.checkoutUrl)}async function Z(e){let t=await p("/logout",{method:"POST",body:{returnTo:e,cartId:P.id()}});g=null,B(!1),h("account-logout",{});let r=t.kind==="answer"?y(t.data.logoutUrl):null;return r?(z(r),"redirected"):"stayed"}var b=10,S=50,ee=e=>typeof e=="number"&&Number.isInteger(e)&&e>=1&&e<=S;function le(e){let t=Number.parseInt(e||String(b),10)||b;return Math.min(Math.max(t,1),S)}var me=e=>e.replace(/\?.*$/,"").replace(/^.*\//,"");function ge(e){let t=i.account?.orderUrl;if(t)return t.replaceAll("{id}",encodeURIComponent(me(e.id)));let r=e.statusPageUrl;return r!==null&&U(r)?r:null}var fe=e=>({name:e.name??"",date:_(e.processedAt),total:$(e.totalPrice),status:e.financialStatus?.toLowerCase(),fulfillment:e.fulfillmentStatus?.toLowerCase(),items:e.lineItems.nodes.map(t=>`${String(t.quantity)}\xD7 ${t.title??""}`).join(", ")});function pe(e,t){let r=t.lineItems.nodes,n=ge(t),s=fe(t);d(e,c("order-bind")).forEach(o=>{let u=l(o,"order-bind")??"";if(u==="url"){n&&o.setAttribute("href",n);return}if(u==="image"){let x=r.find(ce=>ce.image)?.image;x&&N(o,x.url,x.altText||r[0]?.title||"");return}let w=v(s,u);w!==void 0&&A(o,w)}),d(e,c("order-lines")).forEach(o=>{H(o,r,null)}),l(e,"order-bind")==="url"&&n&&e.setAttribute("href",n)}async function te(e,t){let r=d(e,c("orders")),n=r[0];if(!n)return;R(e,"show",{"orders-loading":!0,"orders-empty":!1});let s=le(l(n,"limit")),o;try{o=await t(s)}catch(u){m(u,"orders"),o=null}R(e,"show",{"orders-loading":!1,"orders-empty":o?.length===0}),r.forEach(u=>{D(u,o??[],pe)})}var we=["order","addresses","subscriptions","profile-form","address-form"],he=J;function Pe({returnTo:e=window.location.href,locale:t}={}){return new Promise(r=>{Q({returnTo:e,locale:t}),r()})}async function se(){let e=await k();return e.loggedIn?e.customer:null}async function ye({first:e=b}={}){if(!ee(e))throw new f(`Customer accounts: orders() takes first from 1 to ${String(S)}`,{code:"INVALID"});let t=await p(`/orders?${new URLSearchParams({first:String(e)}).toString()}`);return t.kind==="logged-out"?[]:V(t.data.orders)}async function Ae({returnTo:e=i.account?.logoutUrl||`${window.location.origin}/`}={}){await Z(e)==="stayed"&&await C(document)}async function ve(){try{return(await k()).loggedIn?{kind:"logged-in"}:{kind:"logged-out"}}catch(e){return{kind:"unknown",error:e}}}var re=e=>we.some(t=>d(e,c(t)).length>0);function ke(e){d(e,c("account-link")).forEach(t=>{t.setAttribute("href",be(l(t,"account-link")))})}function be(e){let t=i.account,r=`https://${i.domain}/account`;return e==="payment"?t?.paymentUrl||t?.subscriptionsUrl||r:e==="subscriptions"&&t?.subscriptionsUrl||r}async function C(e=document){let t=await ve();t.kind==="unknown"&&m(t.error,"account");let r=t.kind==="logged-in";if(d(e,c("show")).forEach(n=>{let s=l(n,"show");s==="logged-in"&&L(n,r),s==="logged-out"&&L(n,!r)}),ke(e),t.kind==="unknown"&&re(e)){(await a()).showUnavailable(e);return}r&&(await ie(e),await Promise.all([te(e,n=>ye({first:n})),re(e)?a().then(n=>n.renderPages(e)):null]))}async function ie(e){let t=d(e,c("account-bind"));if(!t.length)return;let r;try{r=await se()}catch(s){m(s,"account");return}if(!r)return;let n={"first-name":r.firstName,"last-name":r.lastName,name:r.displayName,email:r.emailAddress?.emailAddress,address:r.defaultAddress?.formatted.join(", ")};t.forEach(s=>{let o=v(n,l(s,"account-bind")??"");o!=null&&A(s,o)})}var ne=null;function a(){return ne??(ne=W("account-pages").then(e=>(e.setup({serverFetch:p,customer:se,bindCustomer:ie,reset:K}),e))),ne}var Ye=e=>a().then(t=>t.order(e)),Ze=e=>a().then(t=>t.updateProfile(e)),et=()=>a().then(e=>e.addresses()),tt=(e,t)=>a().then(r=>r.saveAddress(e,t)),rt=e=>a().then(t=>t.deleteAddress(e)),nt=()=>a().then(e=>e.subscriptions()),ot=(e,t)=>a().then(r=>r.subscriptionAction(e,t)),st=(e,t)=>a().then(r=>r.requestReturn(e,t));function Se(e){let t=e.target;t instanceof window.Element&&(t.closest(c("account-login"))?(e.preventDefault(),Pe().catch(r=>{m(r,"login")})):t.closest(c("account-logout"))&&(e.preventDefault(),Ae().catch(r=>{m(r,"logout")})))}function xe(){let e=new URL(window.location.href),t=e.searchParams.get("account");if(M(t))switch(e.searchParams.delete("account"),window.history.replaceState(window.history.state,"",e),t){case"in":h("account-login",{});break;case"expired":case"error":h("account-error",{error:t});break}}var oe=!1;async function it(e=document){if(oe){await C(e);return}oe=!0,document.addEventListener("click",Se),xe(),P.setCheckoutResolver(Y),await C(e),E("account",he()?"logged in":"logged out")}export{et as addresses,se as customer,rt as deleteAddress,he as isLoggedIn,Pe as login,Ae as logout,it as mountAccount,Ye as order,ye as orders,C as render,st as requestReturn,tt as saveAddress,ot as subscriptionAction,nt as subscriptions,Ze as updateProfile};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as A}from"./chunk-3OEIEDTK.js";import"./chunk-255K6OZ7.js";import"./chunk-A3GXCQJ4.js";import{h}from"./chunk-55OHYO66.js";import"./chunk-J7GYROV4.js";import{d as k,h as E,m as p,r as _,s as w}from"./chunk-EW3GKRT4.js";import{r as a,x as T,z as l}from"./chunk-GXCCTPDF.js";var F=500,S={"default-banner":"https://cdn.shopify.com/shopifycloud/privacy-banner/storefront-banner.js",other:"https://cdn.shopify.com/shopifycloud/consent-tracking-api/v0.2/consent-tracking-api.js"},O="https://cdn.shopify.com/storefront/analytics/shopify.js",x=()=>window,m=()=>x().Shopify;function L(){let t=a.analytics?.shopify;return typeof t=="object"?t:{}}function I(){try{let t=m()?.customerPrivacy;return t?.consentStatus==="loaded"&&t.currentVisitorConsent?.()?.analytics!=="no"&&!!t.analyticsProcessingAllowed?.()}catch{return!1}}function j(t){let e=`hydrogen:${t}`;return{getTrackingValues:()=>{let n=I()?m()?.customerPrivacy?.__internal:void 0;return{uniqueToken:n?.uniqueToken?.({generateFallback:!0,tag:e})??"",visitToken:n?.visitToken?.({generateFallback:!0,tag:e})??""}}}}var $=t=>(e,n)=>{let i=t.subscribers.get(e)??new Set;return t.subscribers.set(e,i),i.add(n),()=>t.subscribers.get(e)?.delete(n)};function U(t){let e=[],n=[],i={shop:{shopId:t,channel:"headless"},consent:{mode:L().consent||"no-banner"}},o=()=>{if(I())for(let r of e)for(;r.next<n.length;r.next+=1){let s=n[r.next];s&&G(r,s)}},c={getConfig:()=>i,publish(r,s={}){if(n.push({event:r,payload:{shop:i.shop,url:window.location.href,...s}}),n.length>F){n.shift();for(let d of e)d.next=Math.max(0,d.next-1)}o()},addDestination(r){let s={name:r.name,next:0,subscribers:new Map,context:j(r.name)};return Promise.resolve(r.setup?.({subscribe:$(s),getConfig:c.getConfig})).then(()=>{e.push(s),o()}).catch(d=>{l(d,`analytics ${r.name}`)}),()=>{let d=e.indexOf(s);d>=0&&e.splice(d,1)}}};return document.addEventListener("consentTrackingApiLoaded",o),document.addEventListener("visitorConsentCollected",o),c}function G(t,{event:e,payload:n}){t.subscribers.get(e)?.forEach(i=>{try{i(n,t.context)}catch(o){l(o,`analytics ${t.name}`)}})}function P(t){let e=document.createElement("script");e.src=t,e.async=!0,document.head.appendChild(e)}async function R(t){let e=m();if(e?.analytics)return e.analytics;let n=await E("query TetherShopId { shop { id } }",{},k({shop:{id:"string"}}),{context:!1}),i=m()??{};x().Shopify=i,i.country=a.country??"US";let[o="en"]=(a.locale||"en").split("-");i.locale=o.toLowerCase(),i.shop=a.domain,i.routes={root:"/",match:()=>({pageTemplateName:t()?"product":"page"}),...i.routes};let{proxy:c,consent:r}=L();i.customerPrivacy={...i.customerPrivacy,config:c?{isHeadless:!0,asyncConsent:!0,asyncVisitorState:!0,consentDomain:window.location.host}:{isHeadless:!0,storefrontAccessToken:a.token,checkoutRootDomain:a.domain}};let s=U(n.shop.id);return i.analytics=s,P(r==="default-banner"?S["default-banner"]:S.other),P(O),T("shopify analytics ready",n.shop.id),s}var W="Default Title",V=100,H=200,Y=t=>t?parseFloat(t.amount):0,N=t=>(t??"").split("/").pop()??"";function C(t,e,n=1,i){let o={item_id:e?.sku||N(e?.id)||N(t.id),item_name:t.title,item_variant:e?.title===W?void 0:e?.title,item_brand:t.vendor||void 0,item_category:t.productType||void 0,price:Y(e?.price??t.priceRange?.minVariantPrice),quantity:n};return i!=null&&(o.index=i),o}var g=(t,e=t.quantity)=>C(t.merchandise.product,t.merchandise,e);function f(t){let e=t.reduce((n,i)=>n+i.price*(i.quantity||1),0);return Math.round(e*V)/V}var X=(t,e,n=1)=>({id:t.id,title:t.title,price:e.price,vendor:t.vendor||"",variantId:e.id,variantTitle:e.title,quantity:n,sku:e.sku||void 0,productType:t.productType||void 0}),D=t=>({id:t.id,quantity:t.quantity,merchandise:{id:t.merchandise.id,title:t.merchandise.title,price:t.merchandise.price,sku:t.merchandise.sku,product:{id:t.merchandise.product.id,title:t.merchandise.product.title,vendor:t.merchandise.product.vendor||"",handle:t.merchandise.product.handle}}});function Z(){let{dataLayer:t}=a.analytics??{},e=typeof t=="string"?t:"dataLayer",n=Reflect.get(window,e);if(Array.isArray(n))return n;let i=[];return Reflect.set(window,e,i),i}function z(t,e){let n=Z();if(!e){n.push({event:t});return}n.push({ecommerce:null}),n.push({event:t,ecommerce:e})}var y=null,v=null,q=null,b=new WeakSet;function u(t,e,n,i){a.analytics?.dataLayer&&z(t,e),y&&n&&y.publish(n,i);try{a.analytics?.onEvent?.(t,e)}catch(o){l(o,"analytics onEvent")}}function M(){let t=document.querySelector(p("product"));return!t||t.closest(`${p("collection")},${p("products")},${p("recommendations")}`)?null:A.get(t)??null}function J({product:t,scope:e}){if(b.has(e.root)||M()!==e)return;b.add(e.root);let n=e.variant??t.variants.nodes[0],i=[C(t,n)],o=n?[X(t,n)]:[];u("view_item",{currency:n?.price.currencyCode,value:f(i),items:i},"product_viewed",{products:o})}function K({products:t,collection:e}){let n=t.slice(0,H).map((o,c)=>C(o,o.variants.nodes[0],1,c)),i={item_list_id:e?.handle||"products",item_list_name:e?.title||"Products"};if(!e){u("view_item_list",{...i,items:n});return}u("view_item_list",{...i,items:n},"collection_viewed",{collection:{id:e.id,handle:e.handle}})}function Q(t,e,n){let i=t?.cost.totalAmount.currencyCode;e.forEach((o,c)=>{let r=n.get(c),s=o.quantity-(r?.quantity??0);if(s<=0)return;let d=[g(o,s)];u("add_to_cart",{currency:i,value:f(d),items:d},"product_added_to_cart",{cart:t,prevCart:q,currentLine:D(o),prevLine:r?D(r):void 0})}),n.forEach((o,c)=>{let r=o.quantity-(e.get(c)?.quantity??0);if(r<=0)return;let s=[g(o,r)];u("remove_from_cart",{currency:i,value:f(s),items:s})})}function tt({cart:t,reason:e}){let n=new Map((t?.lines.nodes??[]).map(i=>[i.merchandise.id,i]));v&&e!=="load"&&e!=="pending"&&Q(t,n,v),v=n,q=t}function et(){let t=h.lines.map(e=>g(e));u("view_cart",{currency:h.state?.cost.totalAmount.currencyCode,value:f(t),items:t})}function nt({cart:t}){if(!t)return;let e=t.lines.nodes.map(i=>g(i)),n=t.discountCodes.filter(i=>i.applicable).map(i=>i.code);u("begin_checkout",{currency:t.cost.totalAmount.currencyCode,value:f(e),coupon:n.join(",")||void 0,items:e})}var it={"product-ready":J,"list-ready":K,"cart-updated":tt,"cart-toggled":({open:t})=>{t&&et()},checkout:nt,search:({term:t})=>{t&&u("search",{search_term:t},"search_viewed",{searchTerm:t})}};function ot(t,e){it[e](t.detail)}function B(t){if(t.type==="astro:page-load"){b=new WeakSet,y?.publish("page_viewed",{});return}_.forEach(e=>{w(t,e)&&ot(t,e)})}async function ft(t){a.analytics?.shopify&&(y=await R(()=>M()!=null).catch(e=>(l(e,"shopify analytics"),null))),y?.publish("page_viewed",{}),t.splice(0).forEach(B),t.push=(...e)=>(e.forEach(B),t.length)}export{ft as startAnalytics};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{b as Z,d as Pt,g as Q,h as kt,p as R,v as Et}from"./chunk-J7GYROV4.js";import{A as W,C as v,D as vt,E as At,F as g,G as k,H as M,K as Lt,P as D,a as b,c as q,d as H,h as V,k as ht,l as L,m as s,n as f,o as yt,p as d,t as y,v as bt,w as P,x as St,y as T,z as wt}from"./chunk-EW3GKRT4.js";import{C as Ct,r as l,x as gt,z as w}from"./chunk-GXCCTPDF.js";var ne={id:"string",quantity:"number",attributes:["object"],cost:{totalAmount:R,subtotalAmount:R,amountPerQuantity:R},merchandise:{id:"string",selectedOptions:["object"],product:"object"}},tt={id:"string",checkoutUrl:"string",totalQuantity:"number",attributes:["object"],discountCodes:["object"],cost:{totalAmount:R,subtotalAmount:R},lines:{nodes:[ne]}};var re='a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])',ie=60,et=!1,K=null,oe=t=>t!==null&&"focus"in t,It=t=>d(t,re).filter(e=>e.offsetParent!==null||e===document.activeElement),$=()=>d(document,s("cart-drawer")),nt=t=>t.classList.contains(l.cartDrawerOpenClass);function S(){let t=$();return t.length?t.some(nt):et}function j(t){d(document,s("cart-open")).forEach(e=>{e.setAttribute("aria-expanded",String(t))}),$().forEach(e=>{e.hasAttribute("role")||e.setAttribute("role","dialog"),!e.hasAttribute("aria-label")&&!e.hasAttribute("aria-labelledby")&&e.setAttribute("aria-label",f(e,"cart-label")||"Cart"),e.setAttribute("aria-modal",String(t)),!nt(e)&&(e.setAttribute("aria-hidden","true"),l.cartFocus&&(e.inert=!0))})}function ae(t){let e=It(t)[0]??t;e===t&&!t.hasAttribute("tabindex")&&(t.tabIndex=-1),e.focus({preventScroll:!0})}function B(){if(S())return;et=!0;let t=$().filter(n=>f(n,"cart-drawer")!=="manual");t.forEach(n=>{n.inert=!1,n.classList.add(l.cartDrawerOpenClass),n.setAttribute("aria-hidden","false")}),j(!0);let[e]=t;l.cartFocus&&e&&(K=oe(document.activeElement)?document.activeElement:null,setTimeout(()=>{ae(e)},ie)),l.onCartOpen?.(t),y("cart-toggled",{open:!0})}function rt(){if(!S())return;et=!1;let t=$(),e=t.some(n=>n.contains(document.activeElement));t.forEach(n=>{n.classList.remove(l.cartDrawerOpenClass),n.setAttribute("aria-hidden","true"),l.cartFocus&&(n.inert=!0)}),j(!1),e&&K?.isConnected&&K.focus({preventScroll:!0}),K=null,l.onCartClose?.(t),y("cart-toggled",{open:!1})}function xt(){S()?rt():B()}function se(t){if(t.key!=="Tab"||!l.cartFocus||!S())return;let e=$().find(nt);if(!e)return;let n=It(e),r=n[0],i=n.at(-1);if(!r||!i)return;let o=document.activeElement,a=t.shiftKey?o===r:o===i;e.contains(o)&&!a||(t.preventDefault(),(t.shiftKey?i:r).focus())}var ue=/^image:(\d+)$/,Tt="metafield:",ce=/^(rich_text|multi_line_text)_field$/,le=["","true","all","*"],ot=t=>t.tagName==="SELECT",it=(t,e)=>t.$(`select${e}`).filter(ot);function de(t,e){let n=e.images.nodes,r=[...t.children].map(o=>o.tagName==="IMG"?o:o.querySelector("img"));!St(t)&&r.length===n.length&&r.every((o,a)=>bt(o?.getAttribute("src"),n[a]?.url))||T(t,n,(o,a)=>{let u=o.matches(`img,${s("bind","image")}`)?o:d(o,"img")[0]??o;P(u,a.url,a.altText||e.title)})}function me(t,e,n){let r=n.indexOf("."),i=n.slice(0,r),o=n.slice(r+1),a=(e.metafields??[]).find(c=>c?.namespace===i&&c.key===o);if(!a){g(t,"");return}let u=a.reference?.image;if(u){P(t,u.url,u.altText);return}ce.test(a.type)&&(t.style.whiteSpace="pre-line"),g(t,a.value)}var pe=new Map(Object.entries({title:t=>t.title,"description-text":t=>t.description,vendor:t=>t.vendor,type:t=>t.productType,handle:t=>t.handle,"published-at":t=>vt(t.publishedAt),"min-price":t=>v(t.priceRange.minVariantPrice),"max-price":t=>v(t.priceRange.maxVariantPrice)}));function fe(t,e){let n=(t.getAttribute("exclude")??"").split(",").map(i=>i.trim()).filter(Boolean),r=e.tags.filter(i=>!n.includes(i));T(t,r,(i,o)=>{g(i,o)})}function ge(t,e,n){let r=pe.get(e);if(r){g(t,r(n));return}switch(e){case"description":At(t,n.descriptionHtml);break;case"featured-image":P(t,n.featuredImage?.url,n.featuredImage?.altText||n.title);break;case"url":case"link":{let i=W(n.handle,n.id);i&&t.setAttribute("href",i),e==="url"&&!t.firstElementChild&&!t.textContent.trim()&&g(t,n.title);break}case"images":de(t,n);break;case"tags":fe(t,n);break;default:he(t,e,n)}}function he(t,e,n){let r=ue.exec(e);if(r){let i=n.images.nodes[Number(r[1])-1]??n.featuredImage;P(t,i?.url,i?.altText||n.title)}else e.startsWith(Tt)&&me(t,n,e.slice(Tt.length))}function ye(t){let{product:e}=t;t.$(s("option-list")).forEach(n=>{let r=t.optName(f(n,"option-list")),i=e.options.find(o=>o.name===r);if(!i||i.optionValues.length<=1&&yt(n,"hide-single")){M(n,!1);return}T(n,i.optionValues,(o,a)=>{o.setAttribute(L("option-value"),a.name);let u=d(o,s("bind","option-value"))[0];u?g(u,a.name):o.firstElementChild||g(o,a.name);let c=d(o,s("bind","swatch"))[0],{swatch:p}=a;!c||!p||(p.color&&(c.style.backgroundColor=p.color),p.image?.previewImage&&P(c,p.image.previewImage.url,a.name))})})}function Ce(t){let{product:e}=t;it(t,s("option")).forEach(n=>{let r=e.options.find(i=>i.name===t.optName(f(n,"option")));if(!r){M(n,!1);return}n.replaceChildren(...r.optionValues.map(i=>new Option(i.name,i.name)))}),it(t,s("variant-select")).forEach(n=>{n.replaceChildren(...e.variants.nodes.map(r=>new Option(r.title,r.id)))}),it(t,s("plan")).forEach(n=>{let r=t.plans.map(a=>new Option(a.name,a.id)),i=!e.requiresSellingPlan&&f(n,"plan")!=="subscription-only",o=n.getAttribute(L("one-time-label"))||"One-time purchase";n.replaceChildren(...i?[new Option(o,"")]:[],...r)})}function be(t){t.$(s("plan-list")).forEach(e=>{let n=(f(e,"plan-list")??"").trim(),r=le.includes(n.toLowerCase())?null:n,i=t.plans.filter(o=>!r||o.group.name===r);T(e,i,(o,a)=>{o.setAttribute(L("plan-value"),a.id),!o.firstElementChild&&!o.querySelector(s("plan-bind"))&&g(o,a.name)})})}function Xe(t){t.$(s("bind")).forEach(e=>{ge(e,f(e,"bind")??"",t.product)}),ye(t),Ce(t),be(t)}var Mt="Default Title",at=(t,e)=>e.get(t.id)?.quantity??t.quantity,$t=t=>t.split("/").pop()??t;function Se(t){let e=t.merchandise,n=W(e.product.handle,e.product.id);if(!n)return null;let r=new URLSearchParams;r.set("variant",$t(e.id));let i=t.sellingPlanAllocation?.sellingPlan.id;return i&&r.set("selling_plan",$t(i)),`${n}${n.includes("?")?"&":"?"}${r.toString()}`}var Ot=t=>t.merchandise.product.title,Rt={title:Ot,"product-title":Ot,"variant-title":t=>t.merchandise.title===Mt?"":t.merchandise.title,options:t=>t.merchandise.selectedOptions.filter(e=>e.value!==Mt).map(e=>`${e.name}: ${e.value}`).join(", "),vendor:t=>t.merchandise.product.vendor,sku:t=>t.merchandise.sku??"",price:t=>v(t.cost.amountPerQuantity),"compare-at-price":t=>v(t.cost.compareAtAmountPerQuantity??t.merchandise.compareAtPrice),"line-total":t=>v(t.cost.totalAmount),"line-subtotal":t=>v(t.cost.subtotalAmount),quantity:(t,e)=>at(t,e.pending),plan:t=>t.sellingPlanAllocation?.sellingPlan.name??"","plan-description":t=>t.sellingPlanAllocation?.sellingPlan.description??"",components:t=>(t.lineComponents??[]).map(e=>`${e.quantity} \xD7 ${e.merchandise.product.title}`).join(", ")},Ut="attribute:";function we(t,e,n){if(Object.hasOwn(Rt,e))return Rt[e]?.(t,n);if(!e.startsWith(Ut))return;let r=e.slice(Ut.length);return t.attributes.find(i=>i.key===r)?.value??""}function ve(t,e,n){let r=kt(n),i=!n.requiresSellingPlan&&f(t,"line-plan")!=="subscription-only",o={value:"",label:t.getAttribute(L("one-time-label"))||"One-time purchase"},a=[...i?[o]:[],...r.map(c=>({value:c.id,label:c.name}))],u=a.map(c=>c.value).join("|");t.dataset.tetherSig!==u&&(t.replaceChildren(...a.map(c=>{let p=document.createElement("option");return p.value=c.value,p.textContent=c.label,p})),t.dataset.tetherSig=u),t.value=e.sellingPlanAllocation?.sellingPlan.id??"",M(t,r.length>0)}function Ae(t,e,n){let r=!!e.sellingPlanAllocation;t.classList.toggle("is-subscription",r);let i=n.warnings.find(u=>u.target===e.id);t.classList.toggle("is-warning",!!i);let o=n.pending.has(e.id);t.classList.toggle("is-busy",o),o?t.setAttribute("aria-busy","true"):t.removeAttribute("aria-busy"),d(t,s("line","warning")).forEach(u=>{k(u,i?.message??"")});let a=new Map([["subscription",r],["one-time",!r],["on-sale",Pt(e.cost.compareAtAmountPerQuantity?.amount,e.cost.amountPerQuantity.amount)],["has-components",(e.lineComponents??[]).length>0],["warning",!!i]]);d(t,s("line-show")).forEach(u=>{let c=f(u,"line-show"),p=c===null?void 0:a.get(c);p!==void 0&&M(u,p)})}function Le(t,e,n){let r=e.merchandise;t.setAttribute(L("line-id"),e.id),d(t,s("line")).forEach(o=>{let a=f(o,"line")??"";if(a==="image"){P(o,r.image?.url??r.product.featuredImage?.url,r.product.title);return}if(a==="url"){let c=Se(e);c&&o.setAttribute("href",c);return}let u=we(e,a,n);u!==void 0&&k(o,u)}),Ae(t,e,n),d(t,s("line-plan")).filter(ot).forEach(o=>{Et(r.product.handle).then(a=>{ve(o,e,a)}).catch(a=>{w(a,"line plan options")})})}function Pe(t,e){let n=t?.totalQuantity??0,r=(t?.lines.nodes??[]).some(o=>o.sellingPlanAllocation),i=new Map([["cart-empty",n===0],["cart-filled",n>0],["cart-has-subscription",r],["cart-no-subscription",!r],["cart-has-discount",(t?.discountCodes??[]).some(o=>o.applicable)],["cart-error",e.failed],["cart-warning",e.warnings.length>0]]);d(document,s("show")).forEach(o=>{let a=f(o,"show"),u=a===null?void 0:i.get(a);u===void 0||o.closest(s("product"))||M(o,u)}),d(document,s("checkout")).forEach(o=>{o.classList.toggle("is-disabled",!n),o.setAttribute("aria-disabled",String(!n))})}function ke(t){d(document,`textarea${s("cart-note")},input${s("cart-note")}`).forEach(e=>{document.activeElement!==e&&g(e,t?.note??"")}),d(document,s("cart-discounts")).forEach(e=>{T(e,t?.discountCodes??[],(n,r)=>{n.setAttribute(L("discount-code"),r.code);let i=n.querySelector(s("discount","code"))??(n.firstElementChild?null:n);i&&g(i,r.code),n.classList.toggle("is-inapplicable",!r.applicable)})})}function qt(t){let{cart:e}=t,n=r=>e?v(e.cost[r]):"";j(S()),d(document,s("cart-count")).forEach(r=>{k(r,e?.totalQuantity??0)}),d(document,s("cart-subtotal")).forEach(r=>{k(r,n("subtotalAmount"))}),d(document,s("cart-total")).forEach(r=>{k(r,n("totalAmount"))}),d(document,s("cart-checkout-charge")).forEach(r=>{k(r,n("checkoutChargeAmount"))}),Pe(e,t),d(document,s("cart-warning")).forEach(r=>{k(r,[...new Set(t.warnings.map(i=>i.message))].join(" "))}),ke(e),d(document,s("cart-lines")).forEach(r=>{wt(r,e?.lines.nodes??[],i=>i.id,(i,o)=>{Le(i,o,t)},{onEnter:l.onLineEnter,onLeave:l.onLineLeave})}),e&&Lt("cart")}function Dt(t){d(document,s("cart-count")).forEach(e=>{/^\s*0?\s*$/.test(e.textContent)&&(e.textContent=String(t))})}function st(t,e="localStorage"){try{return window[e].getItem(t)}catch{return null}}function ut(t,e,n="localStorage"){try{window[n].setItem(t,e)}catch{}}function Qt(t,e="localStorage"){try{window[e].removeItem(t)}catch{}}var Nt=/^gid:\/\/shopify\/Cart\/[\w-]+(\?key=[\w-]+)?$/;var h={kind:"unknown"},U=[],O=new Map,G=()=>h;function m(){switch(h.kind){case"ready":case"error":return h.cart;case"unknown":case"empty":return null}}var Ft=()=>U,ct=t=>t?{kind:"ready",cart:t}:{kind:"empty"},Ht=()=>`${l.storageKey}:seen`;function E(){let t=st(l.storageKey);return t?Nt.test(t)?t:(I(),null):null}function I(){Qt(l.storageKey)}function lt(t){h=ct(t),t&&ut(l.storageKey,t.id)}function N(){qt({cart:m(),warnings:U,pending:O,failed:h.kind==="error"})}function _(t){N(),y("cart-updated",{cart:m(),reason:t})}function C(t,e){return lt(t),ut(Ht(),`${Date.now()}|${t?.totalQuantity??0}`),_(e),t}function F(t){h=t.kind==="loaded"?ct(t.cart):{kind:"error",error:t.error,cart:null},_("load")}function Ee(){let t=st(Ht())?.split("|")[1]??"",e=Number(t);return/^\d+$/.test(t)&&Number.isSafeInteger(e)?e:null}function Vt(){if(h.kind!=="unknown")return;let t=Ee();t!==null&&Dt(t)}function Wt(t){U=t.filter((e,n)=>t.findIndex(r=>r.message===e.message)===n).map(e=>({...e,message:l.warningText?.(e)||e.message})),U.length&&y("cart-warning",{warnings:U})}var _t=()=>{};function Ie(){let t=Promise.resolve();return e=>{let n=t.then(e);return t=n.then(_t,_t),n}}var xe=Ie();function Kt(t){return xe(t).then(e=>(h.kind==="error"&&(h=ct(h.cart),N()),e),e=>{throw h={kind:"error",error:e,cart:m()},N(),y("cart-error",{error:e}),e})}var dt=t=>at(t,O),Te=()=>({open:S(),count:m()?.totalQuantity??0,loaded:h.kind!=="unknown",warnings:[...U]});function jt(t){let e=["cart-updated","cart-toggled"].map(r=>`${l.prefix}:${r}`),n=()=>{t(m(),Te())};return e.forEach(r=>{document.addEventListener(r,n)}),n(),()=>{e.forEach(r=>{document.removeEventListener(r,n)})}}var Me=/does not exist|not found|invalid id/i,$e=t=>H({[t]:q({cart:q(tt)})});function X(t){return t instanceof b?t.userErrors?.some(e=>e.field?.[0]==="cartId")?!0:(t.errors??[]).some(e=>Me.test(e.message)):!1}function Gt(t){if(!(t instanceof b))return!1;let{code:e,status:n=0}=t;return e==="NETWORK"||e==="INVALID_RESPONSE"||e==="SERVER_ERROR"||n>=500}function Xt(t,e=1,n={}){let r=typeof t=="object"&&t!==null?t:{...n,quantity:e,...t==null?{}:{variantId:t}},i=Q.variant(r.merchandiseId||r.variantId||r.id);if(!i)throw new b("add(): variantId is required");let o=parseInt(String(r.quantity??1),10),a={merchandiseId:i,quantity:Math.max(1,o||1)},u=Q.sellingPlan(r.sellingPlanId||r.sellingPlan);u&&(a.sellingPlanId=u);let c=D(r.attributes);return c.length&&(a.attributes=c),a}function Oe(t,e,n){return r=>`mutation Tether_${t}(${e}){${t}(${n}){cart{...TetherCart}userErrors{field message}warnings{code message target}}}${Z(r)}`}async function Yt(t,e,n,r){let i=await V(Oe(t,e,n),r,$e(t),{operation:"mutation"}),o=ht(i[t],t);return Wt(o.warnings??[]),o.cart}function Bt(t){let e=l.country?{buyerIdentity:{countryCode:l.country},...t}:t;return Yt("cartCreate","$input: CartInput!","input: $input",{input:e})}async function x({name:t,args:e,inner:n,variables:r,createInput:i}){let o=E();if(!o)return i?Bt(i):null;try{return await Yt(t,`$cartId: ID!, ${e}`,`cartId: $cartId, ${n}`,{...r,cartId:o})}catch(a){if(!X(a)||(I(),!i))throw a;return gt("cart expired, creating a new one"),Bt(i)}}async function mt(t){return(await V(n=>`query TetherCart($id:ID!){cart(id:$id){...TetherCart}}${Z(n)}`,{id:t},H({cart:q(tt)}))).cart}async function zt(t){return(await V("query TetherCheckout($id: ID!) { cart(id: $id) { checkoutUrl } }",{id:t},H({cart:q({checkoutUrl:"string"})}))).cart?.checkoutUrl??null}function Jt(t,e){let n=typeof e=="number"?{quantity:e}:e,r={id:t};n.quantity!==void 0&&(r.quantity=n.quantity),"sellingPlanId"in n&&(r.sellingPlanId=n.sellingPlanId?Q.sellingPlan(n.sellingPlanId):null),n.attributes&&(r.attributes=D(n.attributes));let i=n.merchandiseId||n.variantId;return i&&(r.merchandiseId=Q.variant(i)),r}var pt=t=>x({name:"cartLinesUpdate",args:"$lines: [CartLineUpdateInput!]!",inner:"lines: $lines",variables:{lines:t},createInput:null}),Y=t=>x({name:"cartLinesRemove",args:"$lineIds: [ID!]!",inner:"lineIds: $lineIds",variables:{lineIds:t},createInput:null}),Zt=(t,e)=>e>0?pt([{id:t,quantity:e}]):Y([t]);var ft=null;function te(t){ft=t}var Re=t=>zt(t).then(e=>({kind:"url",url:e}),e=>({kind:"failed",error:e}));async function Ue(){if(!ft)return null;try{let t=await ft();return t&&`${t}${t.includes("?")?"&":"?"}logged_in=true`}catch(t){return w(t,"account checkout"),null}}async function qe(t){let e=Re(t),n=await Ue();if(n)return n;let r=await e;if(r.kind==="failed")throw r.error;if(!r.url)throw new b("No checkoutUrl (cart empty or expired)");return r.url}function De(t){try{t.opener=null}catch{}}async function ee(t=l.checkoutTarget){let e=E(),n=m();if(!e||n&&!n.totalQuantity)return null;let r=t==="_blank"?window.open("","_blank"):null;r&&De(r);try{let i=await qe(e);if(!Ct(i))throw new b("The checkout URL is not https: not opened");return y("checkout",{url:i,cart:m()}),r&&!r.closed?r.location.href=i:window.location.href=i,i}catch(i){return r?.close(),w(i,"checkout failed"),null}}var J=()=>m()?.lines.nodes??[];async function Qe(){let t=E();if(t)try{let e=await mt(t);e||I(),C(e,"load")}catch(e){w(e,"cart reload after a failed change")}}function A(t){return Kt(()=>t().catch(async e=>{throw Gt(e)&&await Qe(),e}))}function Ne(t,e){let n=J().find(u=>u.id===t);if(!n)return Promise.resolve(m());let r=Math.max(0,dt(n)+e),i={quantity:r};O.set(t,i),_("pending");let o=()=>O.get(t)===i;return A(async()=>{if(!o())return m();if(J().find(p=>p.id===t)?.quantity===r)return m();let c=await Zt(t,r);return o()?C(c,r>0?"update":"remove"):(lt(c),c)}).finally(()=>{o()&&(O.delete(t),_("settled"))})}function _e(t){let e=(m()?.discountCodes??[]).map(r=>r.code),n=typeof t=="function"?t(e):t;return(Array.isArray(n)?n:[n]).map(r=>r.trim()).filter(Boolean)}function Fe(t){let e=new Map((m()?.attributes??[]).map(n=>[n.key,n.value]));return D(t).forEach(n=>e.set(n.key,n.value)),[...e].filter(([,n])=>n!=="").map(([n,r])=>({key:n,value:r}))}async function He(){let t=E();if(!t)return F({kind:"loaded",cart:null}),null;Vt();try{let e=await mt(t);e||I(),F({kind:"loaded",cart:e})}catch(e){w(e,"cart load failed"),X(e)&&I(),F({kind:"failed",error:e})}return m()}var z={init:He,id:E,get status(){return G()},get state(){return m()},get lines(){return[...J()]},get count(){return m()?.totalQuantity??0},get loaded(){return G().kind!=="unknown"},get lastError(){let t=G();return t.kind!=="error"?null:t.error instanceof Error?t.error:new Error(String(t.error))},get warnings(){return[...Ft()]},get pendingQty(){return O},setCheckoutResolver:te,forgetSaved(){I(),F({kind:"loaded",cart:null})},render:N,subscribe:jt,add(t,e=1,n={}){let r=(Array.isArray(t)?t:[t]).map(i=>Xt(i,e,n));return A(async()=>{let i=await x({name:"cartLinesAdd",args:"$lines: [CartLineInput!]!",inner:"lines: $lines",variables:{lines:r},createInput:{lines:r}});if(!i)throw new b("Shopify answered the add without a cart");return C(i,"add"),y("added",{cart:i,lines:r}),l.openCartOnAdd&&B(),i})},updateLine(t,e){let n=typeof e=="number"?e:e.quantity;if(n!==void 0&&n<=0)return z.removeLine(t);let r=Jt(t,e);return A(async()=>C(await pt([r]),"update"))},changeQuantity:Ne,quantityOf:dt,removeLine(t){let e=Array.isArray(t)?t:[t];return A(async()=>C(await Y(e),"remove"))},clear(){return A(async()=>{let t=J().map(e=>e.id);return t.length?C(await Y(t),"remove"):m()})},setNote(t){let e={note:t??""};return A(async()=>C(await x({name:"cartNoteUpdate",args:"$note: String!",inner:"note: $note",variables:e,createInput:e}),"note"))},setAttributes(t){return A(async()=>{let e={attributes:Fe(t)},n=await x({name:"cartAttributesUpdate",args:"$attributes: [AttributeInput!]!",inner:"attributes: $attributes",variables:e,createInput:e});return C(n,"attributes")})},setDiscountCodes(t){return A(async()=>{let e={discountCodes:_e(t)},n=await x({name:"cartDiscountCodesUpdate",args:"$discountCodes: [String!]!",inner:"discountCodes: $discountCodes",variables:e,createInput:e});return C(n,"discount")})},async applyDiscount(t){let e=await z.setDiscountCodes(i=>[...new Set([...i,t])]),n=t.toLowerCase();if((e?.discountCodes??[]).find(i=>i.code.toLowerCase()===n)?.applicable)return e;try{await z.removeDiscount(t)}catch(i){w(i,"removing a discount code Shopify refused")}throw new b(`Discount code not valid: ${t}`,{code:"INVALID_DISCOUNT"})},removeDiscount(t){let e=t.toLowerCase();return z.setDiscountCodes(n=>n.filter(r=>r.toLowerCase()!==e))},setBuyerIdentity(t,{create:e=!0}={}){return A(async()=>{let n=await x({name:"cartBuyerIdentityUpdate",args:"$buyerIdentity: CartBuyerIdentityInput!",inner:"buyerIdentity: $buyerIdentity",variables:{buyerIdentity:t},createInput:e?{buyerIdentity:t}:null}).catch(r=>{if(e||!X(r))throw r;return null});return C(n,"buyer-identity")})},checkout:ee,drawers:$,isOpen:S,open:B,close:rt,toggle:xt};export{se as a,ot as b,it as c,Xe as d,st as e,ut as f,Qt as g,z as h};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{A as j,E as Q,F as q,b as T,d as E,e as x,o as V,p as G,r as u,x as O,y as w,z as b}from"./chunk-GXCCTPDF.js";var g=class extends Error{constructor(r,{status:n,errors:o,userErrors:i,code:s}={}){super(r);T(this,"name","TetherError");T(this,"code");T(this,"status");T(this,"errors");T(this,"userErrors");this.code=s??(n?`HTTP_${n}`:"ERROR"),this.status=n,this.errors=o,this.userErrors=i}};function A(t,e){return typeof e=="function"?e(t):typeof e=="string"?e==="object"?E(t):typeof t===e:Et(e)?Array.isArray(t)&&t.every(r=>A(r,e[0])):E(t)&&Object.entries(e).every(([r,n])=>n===void 0||A(t[r],n))}var Et=t=>Array.isArray(t),Me=t=>e=>e===null||A(e,t),_e=t=>e=>A(e,t);function Tt(t=u){return`https://${t.domain}/api/${t.apiVersion}/graphql.json`}var Y=/"(?:\\.|[^"\\\n])*"|#[^\n]*/g,bt=/^\s*(?:query|mutation)(?:\s+\w+)?\s*(?:\([^)]*\))?/;function wt(t){return/\bmutation\b/.test(t.replace(Y,""))?"mutation":"query"}function J(t,{country:e,language:r}){let n=[];if(e&&n.push(`country: ${e}`),r&&n.push(`language: ${r}`),!n.length)return t;let o=`@inContext(${n.join(", ")})`,i=t.replace(Y,d=>" ".repeat(d.length)),s=i.indexOf("{");if(i.slice(0,s).includes("@inContext"))return t;if(i.trimStart().startsWith("{"))return`query ${o} ${t.slice(s)}`;let c=bt.exec(i);if(!c)return t;let l=c[0].length;return`${t.slice(0,l).trimEnd()} ${o} ${t.slice(l).trimStart()}`}function Ue(t,e=u){let r=V(e.country)??void 0,n=G(e.language)??void 0;return J(t,{country:r,language:n})}var N=300,St=500,W=430,xt=1e3,C="quantityAvailable",B=new Set,At=t=>`${t.domain} ${t.apiVersion} ${t.token}`;function vt(t,e,r,{context:n,operation:o}){let i=typeof e=="string"?e:e(r),s=n?J(i,t):i;return t.maxAge<=0||o==="mutation"?s:`${s} #${Math.floor(Date.now()/(t.maxAge*xt))}`}var kt=t=>new Promise(e=>setTimeout(e,t));function I(t,e){if(t===401||t===403){let r=e.token.startsWith("shpat_")?", not an Admin API token (shpat_\u2026)":"";return`Shopify rejected the Storefront token for ${e.domain} (${t}): use the public Storefront API token (Headless channel)${r}`}return t===404?`Store or API version not found (404): check domain ${e.domain} and apiVersion ${e.apiVersion}`:`HTTP ${t} from ${e.domain}`}function Rt(t){let e=x(t,"message"),r=x(x(t,"extensions"),"code"),n=typeof e=="string"?e:"";return typeof r=="string"?{message:n,extensions:{code:r}}:{message:n}}function Ot(t){if(!E(t))return null;let{data:e,errors:r}=t;return r==null?{data:e}:Array.isArray(r)?{data:e,errors:r.map(Rt)}:null}function L(t,e){return t.ok?new g(`Invalid response (${t.status})`,{code:"INVALID_RESPONSE",status:t.status}):new g(I(t.status,e),{status:t.status})}function K(t,e,r,n){let o=e.map(s=>s.message).filter(Boolean).join(" | "),i=o||"Storefront API error";return t.ok||(i=t.status===401||t.status===403||!o?I(t.status,r):o),new g(i,{status:t.status,errors:e,code:n})}function z(t,e){if(e==="any")return{kind:"retry",backoffMs:N};throw new g(`Network error: ${j(t)}`,{code:"NETWORK"})}function Lt(t,e,r,n,o,i,s){if(r.includes(C)&&n.some(f=>f.message.includes(C)))return{kind:"inventory-refused",error:K(t,n,e)};let c=n.map(f=>f.extensions?.code);if(i!=="none"&&c.includes("THROTTLED"))return{kind:"retry",backoffMs:St};let l=c.includes("INTERNAL_SERVER_ERROR");if(i==="any"&&l)return{kind:"retry",backoffMs:N};let d=t.ok&&(l||s==="mutation"&&o==null);throw K(t,n,e,d?"SERVER_ERROR":void 0)}async function Ct(t,e,r,n,o,i){let s;try{s=await(t.fetch??fetch)(Tt(t),{method:"POST",headers:{"Content-Type":"application/json","X-Shopify-Storefront-Access-Token":t.token},body:JSON.stringify({query:e,variables:r})})}catch(p){return z(p,o)}if(s.status===W)throw new g("Shopify security rejection (430)",{status:W});if(o!=="none"&&s.status===429||o==="any"&&s.status>=500)return{kind:"retry",backoffMs:N};let c;try{c=await s.json()}catch(p){if(p instanceof SyntaxError)throw L(s,t);return z(p,o)}let l=Ot(c);if(!l)throw L(s,t);let{data:d,errors:f=[]}=l;if(f.length)return Lt(s,t,e,f,d,o,i);if(!s.ok)throw new g(I(s.status,t),{status:s.status});if(!n(d))throw L(s,t);return{kind:"data",data:d}}async function X(t,e,r,n,{context:o=!0,operation:i="query"}={}){if(!t.domain||!t.token)throw new g("Tether is not configured: domain and token are required",{code:"NOT_CONFIGURED"});let s=At(t),c=i==="mutation"?"not-run":"any",l=0;for(;;){let d={inventory:!B.has(s)},f=vt(t,e,d,{context:o,operation:i}),p=l<t.retries?c:"none",h=await Ct(t,f,r,n,p,i);switch(h.kind){case"data":return h.data;case"inventory-refused":if(typeof e=="string"||!d.inventory)throw h.error;O(`the token can't read inventory: ${C} is left out from now on`),B.add(s);break;case"retry":l+=1,O("retry",l),await kt(h.backoffMs*2**l);break}}}function He(t,e,r,n){return X(u,t,e,r,n)}var Nt=t=>typeof t=="object"&&t!==null;function It(t,e,r={},n){return X(t,e,r,Nt,{...n,operation:wt(e)})}function $e(t,e,r){return It(u,t,e,r)}function De(t,e){if(!t)throw new g(`${e}: empty response`);let r=t.userErrors??[];if(r.length)throw new g(r.map(n=>n.message).join(" | "),{userErrors:r});return t}var m=t=>`${u.prefix}-${t}`,Pt=(t,e)=>e===void 0?`[${m(t)}]`:`[${m(t)}="${e}"]`,P=(t,e)=>t.getAttribute(m(e)),Mt=(t,e)=>t.hasAttribute(m(e));function Z(t,e){return t?[...t.querySelectorAll(e)]:[]}var _t=(t,e,r)=>Z(t,e).filter(n=>n.closest(r)===t),Ut=["product-ready","list-ready","cart-updated","cart-toggled","checkout","search"],tt=new WeakMap;function et(t,e){let r=new CustomEvent(`${u.prefix}:${t}`,{detail:e,bubbles:!0});return tt.set(r,t),r}function Ht(t,e){return tt.get(t)===e}function M(t,e,r=document){r.dispatchEvent(et(t,e))}function nt(t,{width:e,height:r,crop:n}={}){if(!t)return t;let o;try{o=new URL(t)}catch(i){if(i instanceof TypeError)return t;throw i}return e&&o.searchParams.set("width",String(e)),r&&o.searchParams.set("height",String(r)),n&&o.searchParams.set("crop",n),o.toString()}function _(t,e){return t.getAttribute(e)??t.getAttribute(m(e))??t.getAttribute(`data-${e}`)}function ot(t,e){if(!t||!e)return t;let r=_(e,"max-width"),n=_(e,"max-height");return nt(t,{width:r,height:n,crop:r||n?_(e,"crop"):null})}var rt=t=>t.replace(/\?.*$/,"");function it(t,e){return!t||!e?!1:rt(t)===rt(e)}function $t(t){return/^\s*[a-z][a-z0-9+.-]*:/i.test(t)&&!/^\s*(https?:|data:image\/)/i.test(t)?"none":`url("${t.replace(/["\\\n\r\f]/g,n=>`\\${n.charCodeAt(0).toString(16)} `)}")`}function Dt(t,e,r){if(!e)return;let n=ot(e,t);if(t.tagName!=="IMG"){t.style.backgroundImage=$t(n);return}if(it(t.getAttribute("src"),n)){r!=null&&!t.getAttribute("alt")&&t.setAttribute("alt",r);return}t.removeAttribute("srcset"),t.removeAttribute("sizes"),t.setAttribute("src",n),r!=null&&t.setAttribute("alt",r),t.getAttribute("loading")||t.setAttribute("loading","lazy")}var U=new WeakMap,Ft=t=>!!U.get(t),H=t=>t.cloneNode(!0);function st(t){let e=U.get(t);if(e!==void 0)return e;let r=t.firstElementChild,n=r?H(r):null;return U.set(t,n),t.replaceChildren(),n}function Vt(t,e,r){let n=st(t);if(!n){e.length&&w("repeater without a template child",t);return}t.replaceChildren(),e.forEach((o,i)=>{let s=H(n);r(s,o,i),t.appendChild(s)})}function Gt(t,e){let r=()=>{t.remove()};if(!e){r();return}try{e(t,r)}catch(n){b(n,"repeater onLeave"),r()}}function jt(t,e,r,n){e.forEach((o,i)=>{if(!r.has(o))return;let s=e[i-1];if(s?.parentNode===t?s.after(o):t.prepend(o),!!n)try{n(o)}catch(c){b(c,"repeater onEnter")}})}function Qt(t,e,r,n,{onEnter:o,onLeave:i}={}){let s=st(t);if(!s){w("repeater without a template child",t);return}let c=`data-${u.prefix}-key`,l=`data-${u.prefix}-leaving`,d=()=>[...t.children].filter(a=>a.hasAttribute(c)&&!a.hasAttribute(l)),f=new Map(d().map(a=>[a.getAttribute(c),a])),p=[],h=new Set;e.forEach((a,S)=>{let R=String(r(a,S)),y=f.get(R);y?f.delete(R):(y=H(s),y.setAttribute(c,R),h.add(y)),n(y,a,S,h.has(y)),p.push(y)});let k=p.filter(a=>!h.has(a)),F=d().filter(a=>k.includes(a));if(!(F.length===k.length&&F.every((a,S)=>a===k[S]))){f.forEach(a=>{a.remove()}),p.forEach(a=>t.appendChild(a));return}jt(t,p,h,o),f.forEach(a=>{a.setAttribute(l,""),a.removeAttribute(c),a.style.pointerEvents="none",a.inert=!0,Gt(a,i)})}var qt="http://www.w3.org/1999/xhtml",Wt=new Set(["h1","h2","h3","h4","h5","h6","p","span","div","br","hr","blockquote","code","pre","strong","em","b","i","u","s","small","sub","sup","ul","ol","li","dl","dt","dd","table","caption","colgroup","col","thead","tbody","tfoot","tr","th","td","a","img","picture","source","video","figure","figcaption","iframe"]),Bt=new Set(["script","style","template","noscript","textarea","select","title"]),Kt=new Set(["style","title","lang","dir","role","align","width","height"]),zt=new Map([["a",new Set(["href","target","rel","hreflang"])],["img",new Set(["src","srcset","sizes","alt","loading","decoding"])],["source",new Set(["src","srcset","sizes","type","media"])],["video",new Set(["src","poster","controls","autoplay","muted","loop","playsinline","preload"])],["iframe",new Set(["src","allow","allowfullscreen","frameborder","loading"])],["blockquote",new Set(["cite"])],["ol",new Set(["start","type","reversed"])],["li",new Set(["value"])],["table",new Set(["border","cellpadding","cellspacing","summary"])],["col",new Set(["span"])],["colgroup",new Set(["span"])],["th",new Set(["colspan","rowspan","headers","scope","valign"])],["td",new Set(["colspan","rowspan","headers","valign"])]]),Yt=new Set(["href","src","poster","cite"]),Jt=/^(javascript|vbscript|data):/i,Xt=/^data:image\/(png|gif|jpeg|webp|avif);/i,Zt=new Set(["position","top","right","bottom","left","z-index","-webkit-box-reflect"]),te=["inset","transform","translate","rotate","scale","offset"],ee=/\d(?:[sld]?v|cq)(?:w|h|i|b|min|max)\b/i,re=/^(?:outline|box-shadow|text-shadow|filter|text-decoration|text-underline-offset|text-stroke)|^(?:border-image|mask-border|mask-box-image)(?:-outset)?$/,at=40,ne=new Map([["letter-spacing",{px:4,em:.25}],["word-spacing",{px:4,em:.25}],["text-indent",{px:at}]]),ut=/(?<![\w#.-])[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?(%|[a-z]+)?/gi,oe=/(?<![\w-])(?!drop-shadow\(|blur\()[\w-]+\([^()]*\)/g,ct=/(?:var|calc|min|max|clamp|env|attr)\(/i,ie=/url\(|expression\(|@import/i,se=/[\u0000- ]/g,ae="allow-scripts allow-same-origin allow-popups allow-presentation",ue=new Set(["autoplay","encrypted-media","picture-in-picture","fullscreen","clipboard-write","accelerometer","gyroscope","web-share"]),ce="strict-origin-when-cross-origin",le=["https://www.youtube.com","https://www.youtube-nocookie.com","https://player.vimeo.com","https://www.loom.com","https://fast.wistia.net"];function de(t,e){return Kt.has(e)||e.startsWith("aria-")||(zt.get(t)?.has(e)??!1)}function fe(t,e,r){let n=r.replace(se,"");return Jt.test(n)?t==="img"&&e==="src"&&Xt.test(n):!0}function lt(t,e){try{return new URL(t,e)}catch{return null}}function pe(t,e,r){let n=t.baseURI,o=lt(n)?.origin??"null";return{origin:o==="null"?null:o,baseUrl:n,styleParser:e,embedOrigins:new Set([...le,...r])}}function ge(t,e){let r=lt(t.trim(),e.baseUrl);return r!==null&&r.origin!==e.origin&&e.embedOrigins.has(r.origin)}function me(t){let e=t.split(";").map(r=>r.trim().split(/\s+/)[0]?.toLowerCase()??"");return[...new Set(e.filter(r=>ue.has(r)))].join("; ")}function he(t,e){if(Zt.has(t)||te.some(n=>t.startsWith(n))||ee.test(e))return!0;let r=ne.get(t);return r?ct.test(e)||ye(e,r):t.startsWith("margin")&&e.includes("-")}function ye(t,e){return[...t.matchAll(ut)].some(([r="",n=""])=>{let o=parseFloat(r);if(o>=0)return!1;let i=e[n.toLowerCase()];return i===void 0||-o>i})}function Ee(t,e){return re.test(t.replace(/^-webkit-/,""))?ct.test(e)?!0:[...e.replace(oe,"").matchAll(ut)].some(([r="",n=""])=>{let o=Math.abs(parseFloat(r));return o!==0&&(n.toLowerCase()!=="px"||o>at)}):!1}function Te(t,e){let r=e.style;r.cssText=t;let n=Array.from({length:r.length},(i,s)=>r.item(s));for(let i of n){let s=r.getPropertyValue(i);(he(i,s)||Ee(i,s)||ie.test(s))&&r.removeProperty(i)}let o=r.cssText;return e.removeAttribute("style"),o}function be(t,e){let r=t.localName;for(let i of[...t.attributes]){let s=i.name.toLowerCase(),c=Yt.has(s);de(r,s)&&(!c||fe(r,s,i.value))||t.removeAttribute(i.name)}let n=t.getAttribute("style");if(n===null)return;let o=Te(n,e.styleParser);o===""?t.removeAttribute("style"):t.setAttribute("style",o)}function we(t){if(t.localName==="iframe"){let r=me(t.getAttribute("allow")??"");r===""?t.removeAttribute("allow"):t.setAttribute("allow",r),t.setAttribute("sandbox",ae),t.setAttribute("referrerpolicy",ce);return}if(t.localName!=="a"||t.getAttribute("target")?.toLowerCase()!=="_blank")return;let e=new Set((t.getAttribute("rel")??"").split(/\s+/).filter(Boolean));e.add("noopener"),e.add("noreferrer"),t.setAttribute("rel",[...e].join(" "))}function Se(t,e){let r=t.localName,n=t.namespaceURI===qt;if(n&&Bt.has(r)){t.remove();return}if(!n||!Wt.has(r)){t.replaceWith(...t.childNodes);return}if(r==="iframe"&&!ge(t.getAttribute("src")??"",e)){t.remove();return}be(t,e),we(t)}function dt(t,e=globalThis.document,r=[]){let n=e.createElement("template");n.innerHTML=t??"";let o=pe(e,n,r);for(let i of[...n.content.querySelectorAll("*")])Se(i,o);return n.content}var ft="data-tether-seen",D="data-tether-shown",v="data-tether-prev-display",xe=120;function tr(t,e){return q(u.productPath||"/product",t,e)}function ht(t,e){try{return t()}catch(r){if(r instanceof RangeError)return e;throw r}}function er(t,e=u.locale){return t?ht(()=>new Intl.NumberFormat(e||void 0,{style:"percent",maximumFractionDigits:0}).format(t/100),`${t}%`):""}function rr(t){return t?u.formatMoney?u.formatMoney(t,u.locale):Q(t,u.locale):""}function nr(t){return t?ht(()=>new Date(t).toLocaleDateString(u.locale||void 0),""):""}function or(t,e){t.replaceChildren(dt(e,t.ownerDocument,u.embedOrigins))}var yt=t=>t.tagName==="INPUT"||t.tagName==="TEXTAREA",pt=t=>t.tagName==="INPUT";function Ae(t,e){let r=e==null?"":String(e);yt(t)?t.value=r:t.textContent=r}var gt=t=>yt(t)?t.value:t.textContent;function ir(t,e){let r=gt(t);if(Ae(t,e),r!==gt(t)&&t.hasAttribute(ft)&&u.onValueChange)try{u.onValueChange(t,r)}catch(n){b(n,"onValueChange")}t.setAttribute(ft,"1")}function ve(t){if(t.hasAttribute(D))return;t.setAttribute(D,""),t.removeAttribute("hidden");let e=t.getAttribute(v);e!==null?(t.style.display=e,t.removeAttribute(v)):t.style.display==="none"&&(t.style.display=""),typeof getComputedStyle=="function"&&getComputedStyle(t).display==="none"&&(t.style.display=t.getAttribute(m("display"))||"block")}function sr(t,e){if(e){ve(t);return}t.removeAttribute(D),!t.hasAttribute(v)&&t.style.display!=="none"&&t.setAttribute(v,t.style.display),t.style.display="none"}function ar(t,e){t.classList.toggle("is-selected",e),t.setAttribute("aria-pressed",e?"true":"false"),pt(t)&&(t.type==="radio"||t.type==="checkbox")&&(t.checked=e);let r=t.querySelector('input[type="radio"],input[type="checkbox"]');r&&pt(r)&&(r.checked=e)}var mt,ke=t=>Reflect.get(window,t);function Re(){let t=ke("ScrollTrigger");if(typeof t!="function")return;let e=Reflect.get(t,"refresh");typeof e=="function"&&Reflect.apply(e,t,[])}function Oe(t){clearTimeout(mt),mt=setTimeout(()=>{try{u.onLayoutChange?u.onLayoutChange(t):Re()}catch(e){b(e,"layout-changed")}M("layout-changed",{reason:t})},xe)}function ur(t,e){let r=[...t.querySelectorAll("img")].filter(i=>!i.complete),n=r.length,o=()=>{n-=1,n===0&&Oe(`${e}:images`)};r.forEach(i=>{i.addEventListener("load",o,{once:!0}),i.addEventListener("error",o,{once:!0})})}function cr(t,e){return t.getAttribute("aria-busy")==="true"?Promise.resolve(void 0):(t.setAttribute("aria-busy","true"),Promise.resolve().then(e).finally(()=>{t.removeAttribute("aria-busy")}))}function lr(t,e){let r=t?P(t,e):null;if(!r)return null;try{return JSON.parse(r)}catch{return w(`invalid JSON in ${m(e)}`,t),null}}function $(t){return t==null?"":typeof t=="string"?t:typeof t=="number"||typeof t=="boolean"?String(t):JSON.stringify(t)}function dr(t){return Array.isArray(t)?t.filter(E).map(r=>({key:$(r.key),value:$(r.value)})):E(t)?Object.entries(t).map(([e,r])=>({key:e,value:$(r)})):[]}function fr(t){return t?Array.isArray(t)?t.map(e=>({key:String(e.key),value:String(e.value??"")})):Object.entries(t).map(([e,r])=>({key:e,value:String(r??"")})):[]}export{g as a,A as b,Me as c,_e as d,Tt as e,Ue as f,X as g,He as h,It as i,$e as j,De as k,m as l,Pt as m,P as n,Mt as o,Z as p,_t as q,Ut as r,Ht as s,M as t,nt as u,it as v,Dt as w,Ft as x,Vt as y,Qt as z,tr as A,er as B,rr as C,nr as D,or as E,Ae as F,ir as G,sr as H,ar as I,ke as J,Oe as K,ur as L,cr as M,lr as N,dr as O,fr as P};
|