@occluze/tether 0.7.0 → 0.7.1
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 +21 -21
- package/dist/esm/chunks/{account-UIPWJQ3Y.js → account-CXMA5RPZ.js} +1 -1
- package/dist/esm/chunks/{account-pages-6ROA6Y4V.js → account-pages-IZO7FEOZ.js} +1 -1
- package/dist/esm/chunks/{analytics-2V632IRV.js → analytics-PG5FPRDN.js} +1 -1
- package/dist/esm/chunks/{chunk-4GCXM764.js → chunk-4HD4J5JC.js} +1 -1
- package/dist/esm/chunks/{chunk-BFTZR4OB.js → chunk-6TFMLT4A.js} +2 -2
- package/dist/esm/chunks/{chunk-T44MUL4Y.js → chunk-BBVUVPMO.js} +1 -1
- package/dist/esm/chunks/chunk-EW5SYO6L.js +1 -0
- package/dist/esm/chunks/chunk-HJY2JSNB.js +1 -0
- package/dist/esm/chunks/chunk-MQYB6BH4.js +1 -0
- package/dist/esm/chunks/{chunk-5Z5O3767.js → chunk-N3V45JPS.js} +1 -1
- package/dist/esm/chunks/{chunk-YLUULATY.js → chunk-RPMBCAGS.js} +1 -1
- package/dist/esm/chunks/{chunk-MPDWM2NN.js → chunk-VFNHIGCS.js} +1 -1
- package/dist/esm/chunks/{chunk-6OZJCAGZ.js → chunk-WT7RGGJU.js} +1 -1
- package/dist/esm/chunks/chunk-YN6LEBEN.js +1 -0
- package/dist/esm/chunks/chunk-Z6HS3H7K.js +1 -0
- package/dist/esm/chunks/{diagnose-3FEKRIEK.js → diagnose-XCEBQKBO.js} +1 -1
- package/dist/esm/chunks/extras-4HU3VSBQ.js +1 -0
- package/dist/esm/chunks/{markets-ui-FD6NI2OG.js → markets-ui-M4IQ62CT.js} +1 -1
- package/dist/esm/chunks/search-A5DS2IOS.js +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/server.js +2 -2
- package/dist/tether.account-pages.js +13 -3
- package/dist/tether.account-pages.min.js +1 -1
- package/dist/tether.account.js +13 -3
- package/dist/tether.account.min.js +1 -1
- package/dist/tether.analytics.js +18 -3
- package/dist/tether.analytics.min.js +1 -1
- package/dist/tether.diagnose.js +18 -3
- package/dist/tether.diagnose.min.js +2 -2
- package/dist/tether.extras.js +19 -6
- package/dist/tether.extras.min.js +1 -1
- package/dist/tether.js +162 -112
- package/dist/tether.markets.js +18 -3
- package/dist/tether.markets.min.js +1 -1
- package/dist/tether.min.js +3 -3
- package/dist/tether.min.js.map +4 -4
- package/dist/tether.search.js +18 -3
- package/dist/tether.search.min.js +1 -1
- package/dist/types/server/src/shared/cart-id.d.ts +2 -0
- package/dist/types/src/cart/mutations.d.ts +6 -0
- package/dist/types/src/cart/store.d.ts +5 -2
- package/dist/types/src/cart.d.ts +2 -2
- package/dist/types/src/client.d.ts +53 -19
- package/dist/types/src/config.d.ts +6 -1
- package/dist/types/src/index.d.ts +2 -2
- package/dist/types/src/product-shape.d.ts +3 -1
- package/package.json +1 -2
- package/dist/esm/chunks/chunk-56FCLJJD.js +0 -1
- package/dist/esm/chunks/chunk-A5SYCVQM.js +0 -1
- package/dist/esm/chunks/chunk-BA4LQJJQ.js +0 -1
- package/dist/esm/chunks/chunk-C5JYQCWH.js +0 -1
- package/dist/esm/chunks/extras-6POFBNOP.js +0 -1
- package/dist/esm/chunks/search-UJ73YBQ5.js +0 -1
- package/src/account/addresses-view.ts +0 -58
- package/src/account/answers.ts +0 -79
- package/src/account/markup.ts +0 -36
- package/src/account/operations.ts +0 -145
- package/src/account/order-lines.ts +0 -75
- package/src/account/order-list.ts +0 -107
- package/src/account/order-page.ts +0 -137
- package/src/account/page-answers.ts +0 -317
- package/src/account/page-events.ts +0 -253
- package/src/account/server-client.ts +0 -183
- package/src/account/subscriptions-view.ts +0 -115
- package/src/account-api.ts +0 -98
- package/src/account-marks.ts +0 -35
- package/src/account-pages.ts +0 -81
- package/src/account.ts +0 -284
- package/src/amounts.ts +0 -64
- package/src/analytics-shopify.ts +0 -246
- package/src/analytics.ts +0 -315
- package/src/api-version.ts +0 -79
- package/src/astro.ts +0 -272
- package/src/cart/cart-shape.ts +0 -25
- package/src/cart/checkout.ts +0 -101
- package/src/cart/drawer.ts +0 -125
- package/src/cart/mutations.ts +0 -237
- package/src/cart/render.ts +0 -266
- package/src/cart/store.ts +0 -279
- package/src/cart.ts +0 -345
- package/src/client.ts +0 -391
- package/src/collection.ts +0 -175
- package/src/config-sections.ts +0 -284
- package/src/config.ts +0 -480
- package/src/controls/cart-controls.ts +0 -123
- package/src/controls/discount.ts +0 -75
- package/src/controls/extras.ts +0 -54
- package/src/controls/navigation.ts +0 -77
- package/src/diagnose-markup.ts +0 -298
- package/src/diagnose.ts +0 -294
- package/src/dom.ts +0 -268
- package/src/extras.ts +0 -136
- package/src/fragments.ts +0 -261
- package/src/globals.d.ts +0 -15
- package/src/images.ts +0 -91
- package/src/index.ts +0 -415
- package/src/initial.ts +0 -101
- package/src/lazy-iife.ts +0 -197
- package/src/lazy.ts +0 -42
- package/src/loader.ts +0 -363
- package/src/market-codes.ts +0 -6
- package/src/markets-ui.ts +0 -227
- package/src/markets.ts +0 -246
- package/src/markup.ts +0 -127
- package/src/mounting.ts +0 -264
- package/src/page-market.ts +0 -110
- package/src/part-integrity.ts +0 -7
- package/src/parts/account-pages.ts +0 -7
- package/src/parts/account.ts +0 -7
- package/src/parts/analytics.ts +0 -7
- package/src/parts/diagnose.ts +0 -7
- package/src/parts/extras.ts +0 -7
- package/src/parts/markets.ts +0 -7
- package/src/parts/search.ts +0 -7
- package/src/presets/barba.ts +0 -194
- package/src/product-events.ts +0 -115
- package/src/product-render.ts +0 -218
- package/src/product-shape.ts +0 -49
- package/src/product-state.ts +0 -318
- package/src/product.ts +0 -308
- package/src/repeaters.ts +0 -161
- package/src/search.ts +0 -305
- package/src/selling-plans.ts +0 -145
- package/src/server.ts +0 -211
- package/src/shopify-values.ts +0 -91
- package/src/status.ts +0 -106
- package/src/storage.ts +0 -34
- package/src/store-html.ts +0 -359
- package/src/storefront/catalog.ts +0 -196
- package/src/storefront/json-ld.ts +0 -144
- package/src/variant-render.ts +0 -139
package/dist/tether.search.js
CHANGED
|
@@ -240,8 +240,23 @@
|
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
// server/src/shared/json.ts
|
|
244
|
+
function isRecord(value) {
|
|
245
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// src/part-registry.ts
|
|
249
|
+
function isTetherInternals(value) {
|
|
250
|
+
return isRecord(value) && isRecord(value["__core"]) && isRecord(value["__parts"]);
|
|
251
|
+
}
|
|
252
|
+
function registerPart(name, part) {
|
|
253
|
+
const tether = Reflect.get(window, "Tether");
|
|
254
|
+
if (!isTetherInternals(tether)) {
|
|
255
|
+
throw new Error(`tether.${name}.js runs after the Tether script, which loads it, and needs its window.Tether`);
|
|
256
|
+
}
|
|
257
|
+
tether.__parts[name] = part;
|
|
258
|
+
}
|
|
259
|
+
|
|
243
260
|
// src/parts/search.ts
|
|
244
|
-
|
|
245
|
-
if (!Tether) throw new Error("tether.search.js runs after the Tether script, which loads it");
|
|
246
|
-
Tether.__parts.search = search_exports;
|
|
261
|
+
registerPart("search", search_exports);
|
|
247
262
|
})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{var
|
|
1
|
+
(()=>{var y=Object.defineProperty;var D=(i,t,e)=>t in i?y(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e;var V=(i,t)=>{for(var e in t)y(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,x,A,ot]=j;var K=window.Tether.__core["dom.ts"],[lt,I,ct,L,ht,k,m,ut,mt,dt,pt,N,h,R,l,C,P,d]=K;var Q=window.Tether.__core["mounting.ts"],[gt,wt,Tt,yt,bt,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 H=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"?C(e,t.image?.url,t.image?.altText||t.title):(r==="title"||r==="price"||r==="text")&&t[r]!=null&&P(e,t[r])})}function U(i,t){let e=H(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(I("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=>{R(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}),U(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}),U(s,`${(u.collectionPath||"/collection").replace(/\/$/,"")}/${n.handle}`)}),this.fillList("search-queries",c,(s,n)=>{f(s,{text:n.text}),H(s)?.setAttribute("href",this.queryUrl(n.text))});let T=r.length+a.length+c.length;this.showCount(T),this.setState(T?"ready":"empty"),this.open(!0),L("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);})();
|
|
@@ -26,6 +26,12 @@ export interface CartLineInput {
|
|
|
26
26
|
* a line it refused), after which the saved cart is still good.
|
|
27
27
|
*/
|
|
28
28
|
export declare function isCartGone(error: unknown): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* @returns True when a change failed without saying whether Shopify applied it: no answer or no whole body came (the
|
|
31
|
+
* network), a 2xx whose body isn't valid, or a server error (5xx), which can come after the change was committed.
|
|
32
|
+
* Shopify's user errors and a 4xx are clear.
|
|
33
|
+
*/
|
|
34
|
+
export declare function isUnclearFailure(error: unknown): boolean;
|
|
29
35
|
/**
|
|
30
36
|
* @param input A variant id, or a line.
|
|
31
37
|
* @param quantity For a variant id.
|
|
@@ -136,8 +136,11 @@ export declare const cartStatus: () => CartStatus;
|
|
|
136
136
|
/** The cart as Shopify last sent it. */
|
|
137
137
|
export declare function currentCart(): ShopifyCart | null;
|
|
138
138
|
export declare const currentWarnings: () => readonly CartWarning[];
|
|
139
|
-
/**
|
|
140
|
-
|
|
139
|
+
/**
|
|
140
|
+
* The id of the visitor's cart, kept across pages. A stored value that isn't a cart id (written by another script,
|
|
141
|
+
* or edited by hand) is forgotten, so it is never sent to Shopify or the Worker and the next change starts a new cart.
|
|
142
|
+
*/
|
|
143
|
+
export declare function savedCartId(): string | null;
|
|
141
144
|
/** Forgets the saved cart, which Shopify no longer has. */
|
|
142
145
|
export declare function forgetSavedCart(): void;
|
|
143
146
|
/** Keeps a cart Shopify sent without showing it, for an answer a newer change will replace. */
|
package/dist/types/src/cart.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { checkout, setCheckoutResolver } from './cart/checkout.js';
|
|
2
2
|
import { isOpen, openCart, closeCart, toggleCart, trapFocus } from './cart/drawer.js';
|
|
3
|
-
import { render, subscribe } from './cart/store.js';
|
|
3
|
+
import { render, savedCartId, subscribe } from './cart/store.js';
|
|
4
4
|
import type { CartWarning } from './config.js';
|
|
5
5
|
import type { Attributes, LineSpec, LinePatch } from './cart/mutations.js';
|
|
6
6
|
import type { ShopifyCart, ShopifyCartLine, CartStatus } from './cart/store.js';
|
|
@@ -20,7 +20,7 @@ declare function init(): Promise<ShopifyCart | null>;
|
|
|
20
20
|
export declare const Cart: {
|
|
21
21
|
init: typeof init;
|
|
22
22
|
/** The saved cart's id. */
|
|
23
|
-
id:
|
|
23
|
+
id: typeof savedCartId;
|
|
24
24
|
readonly status: CartStatus;
|
|
25
25
|
readonly state: ShopifyCart | null;
|
|
26
26
|
/** The cart's lines, a copy: changing it changes nothing in the cart. */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TetherConfig } from './config.js';
|
|
2
|
-
export type TetherErrorCode = 'NOT_FOUND' | 'NETWORK' | 'NOT_CONFIGURED' | 'NOT_LOGGED_IN' | 'INVALID' | 'INVALID_COUNTRY' | 'INVALID_DISCOUNT' | 'ERROR' | `HTTP_${number}`;
|
|
2
|
+
export type TetherErrorCode = 'NOT_FOUND' | 'NETWORK' | 'NOT_CONFIGURED' | 'NOT_LOGGED_IN' | 'INVALID' | 'INVALID_COUNTRY' | 'INVALID_DISCOUNT' | 'INVALID_RESPONSE' | 'ERROR' | `HTTP_${number}`;
|
|
3
3
|
export interface GraphQLError {
|
|
4
4
|
message: string;
|
|
5
5
|
extensions?: {
|
|
@@ -17,16 +17,16 @@ interface TetherErrorDetails {
|
|
|
17
17
|
/** The HTTP status of the response that failed. */
|
|
18
18
|
status?: number;
|
|
19
19
|
/** The GraphQL errors of that response. */
|
|
20
|
-
errors?: GraphQLError[];
|
|
20
|
+
errors?: readonly GraphQLError[];
|
|
21
21
|
/** A mutation's user errors. */
|
|
22
22
|
userErrors?: readonly UserError[];
|
|
23
23
|
}
|
|
24
24
|
export declare class TetherError extends Error {
|
|
25
|
-
name: "TetherError";
|
|
26
|
-
code: TetherErrorCode;
|
|
27
|
-
status: number | undefined;
|
|
28
|
-
errors: GraphQLError[] | undefined;
|
|
29
|
-
userErrors: readonly UserError[] | undefined;
|
|
25
|
+
readonly name: "TetherError";
|
|
26
|
+
readonly code: TetherErrorCode;
|
|
27
|
+
readonly status: number | undefined;
|
|
28
|
+
readonly errors: readonly GraphQLError[] | undefined;
|
|
29
|
+
readonly userErrors: readonly UserError[] | undefined;
|
|
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. */
|
|
@@ -38,20 +38,46 @@ export type DataCheck<T> = (data: unknown) => data is T;
|
|
|
38
38
|
/**
|
|
39
39
|
* The structure of JSON a check accepts: a `typeof` name, `'object'` for a plain object, `[item]` for a list of
|
|
40
40
|
* items, an object's fields, or a check of its own. Fields it doesn't name aren't checked, so a shape names only what
|
|
41
|
-
* its reader walks without a fallback.
|
|
41
|
+
* its reader walks without a fallback. A field's `undefined` is the type of one `ShapeOf` leaves out, and checks
|
|
42
|
+
* nothing.
|
|
42
43
|
*/
|
|
43
44
|
export type Shape = 'string' | 'number' | 'boolean' | 'object' | ((value: unknown) => boolean) | readonly [Shape] | {
|
|
44
|
-
readonly [key: string]: Shape;
|
|
45
|
+
readonly [key: string]: Shape | undefined;
|
|
45
46
|
};
|
|
46
47
|
/** @returns True when `value` has the structure `shape` describes. */
|
|
47
48
|
export declare function matches(value: unknown, shape: Shape): boolean;
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
/**
|
|
50
|
+
* The shapes that describe a `T`: every structure such a shape names is one `T` declares at that place, and a check
|
|
51
|
+
* in it is a type guard for a type `T` accepts there. A shape for `T` therefore can't name a field `T` lacks or claim
|
|
52
|
+
* a type `T` contradicts, so a change to `T` that its shape no longer agrees with fails to compile. Fields of `T` the
|
|
53
|
+
* shape doesn't name stay unchecked (`Shape`).
|
|
54
|
+
*/
|
|
55
|
+
export type ShapeOf<T> = unknown extends T ? Shape : KnownShapeOf<T>;
|
|
56
|
+
type KnownShapeOf<T> = DataCheck<T> | (string extends T ? 'string' : never) | (number extends T ? 'number' : never) | (boolean extends T ? 'boolean' : never) | ListShapeOf<T> | FieldsShapeOf<T>;
|
|
57
|
+
type ListShapeOf<T> = T extends readonly (infer Item)[] ? readonly [ShapeOf<Item>] : never;
|
|
58
|
+
type FieldsShapeOf<T> = T extends readonly unknown[] ? never : T extends object ? 'object' | {
|
|
59
|
+
readonly [Key in keyof T]?: ShapeOf<T[Key]>;
|
|
60
|
+
} : never;
|
|
61
|
+
/** @returns A check that `value` is `null` or has the structure `shape` describes. */
|
|
62
|
+
export declare const orNull: <T>(shape: ShapeOf<T>) => DataCheck<T | null>;
|
|
63
|
+
/**
|
|
64
|
+
* @returns A check that `data` has the structure `shape` describes. `ShapeOf` ties `shape` to `T`; fields `shape`
|
|
65
|
+
* doesn't name are `T`'s claim.
|
|
66
|
+
*/
|
|
67
|
+
export declare const shaped: <T>(shape: ShapeOf<T>) => DataCheck<T>;
|
|
68
|
+
/**
|
|
69
|
+
* What an operation does to the store, which decides what is safe to retry. A query only reads, so a failure that may
|
|
70
|
+
* pass is retried: the network (no answer, or a body that stopped arriving), a 429, a 5xx and `THROTTLED`. Shopify may
|
|
71
|
+
* have applied a mutation before a 5xx or a dropped connection, so a mutation is retried only when Shopify answers
|
|
72
|
+
* that it didn't run it (429 or `THROTTLED`): sending it again could add a line twice. Other failures (a 4xx, a 430,
|
|
73
|
+
* an answer that isn't valid, other GraphQL errors) are never retried.
|
|
74
|
+
*/
|
|
75
|
+
export type Operation = 'query' | 'mutation';
|
|
53
76
|
interface RequestOptions {
|
|
77
|
+
/** `false` sends the query without `@inContext`. */
|
|
54
78
|
context?: boolean;
|
|
79
|
+
/** Default `'query'`. */
|
|
80
|
+
operation?: Operation;
|
|
55
81
|
}
|
|
56
82
|
/** What the store's token may read beyond the defaults. */
|
|
57
83
|
export interface StoreAccess {
|
|
@@ -64,6 +90,12 @@ export interface StoreAccess {
|
|
|
64
90
|
export type QueryText = string | ((access: StoreAccess) => string);
|
|
65
91
|
/** @returns The Storefront GraphQL endpoint of `conf`'s store. */
|
|
66
92
|
export declare function endpoint(conf?: Pick<TetherConfig, 'domain' | 'apiVersion'>): string;
|
|
93
|
+
/**
|
|
94
|
+
* The operation of a document Tether didn't write (`Tether.query()`, the server's `query()`). Outside strings and
|
|
95
|
+
* comments, any `mutation` keyword makes it a mutation: a document that starts with a fragment still has its
|
|
96
|
+
* operation found, and a misread errs on the side that is never sent twice.
|
|
97
|
+
*/
|
|
98
|
+
export declare function operationOf(document: string): Operation;
|
|
67
99
|
/**
|
|
68
100
|
* `inContext` for any country and language, as the public `Tether.withContext` takes them: one that isn't a valid
|
|
69
101
|
* code is left out, so page input never becomes query text.
|
|
@@ -76,19 +108,21 @@ export declare function withContext(query: string, ctx?: {
|
|
|
76
108
|
* One Storefront API request, for any config: the browser's shared one (`gql`) or one the server helpers build.
|
|
77
109
|
* Queries carry a time bucket so Shopify's cache of an identical query text is at most `maxAge` seconds old. A query
|
|
78
110
|
* written for the store's access leaves out inventory once the token turns out not to read it (`INVENTORY_FIELD`);
|
|
79
|
-
* a fixed query text is the caller's own, and that refusal is its error.
|
|
111
|
+
* a fixed query text is the caller's own, and that refusal is its error. How often a failure is retried is
|
|
112
|
+
* `conf.retries`; which failures are retried is the operation's (`Operation`).
|
|
80
113
|
*
|
|
81
114
|
* @param isData Checks that `data` has what the caller then reads, so a malformed answer fails here.
|
|
82
|
-
* @throws {TetherError} `NOT_CONFIGURED` without a domain or token, `NETWORK` when the store can't be reached
|
|
83
|
-
* `
|
|
115
|
+
* @throws {TetherError} `NOT_CONFIGURED` without a domain or token, `NETWORK` when the store can't be reached or
|
|
116
|
+
* the answer's body stops arriving, `INVALID_RESPONSE` for a 2xx whose body isn't valid (not JSON, not in the
|
|
117
|
+
* GraphQL shape, or `data` that `isData` refuses), `HTTP_<status>` for any other HTTP or GraphQL failure.
|
|
84
118
|
*/
|
|
85
|
-
export declare function request<T>(conf: StorefrontConfig, query: QueryText, variables: Record<string, unknown>, isData: DataCheck<T>, { context }?: RequestOptions): Promise<T>;
|
|
119
|
+
export declare function request<T>(conf: StorefrontConfig, query: QueryText, variables: Record<string, unknown>, isData: DataCheck<T>, { context, operation }?: RequestOptions): Promise<T>;
|
|
86
120
|
/** `request` with the browser's shared config. */
|
|
87
121
|
export declare function gql<T>(query: QueryText, variables: Record<string, unknown>, isData: DataCheck<T>, options?: RequestOptions): Promise<T>;
|
|
88
122
|
/** The check of `Tether.query()` and the server's `query()`, whose callers read `data` themselves. */
|
|
89
123
|
export declare const hasData: (data: unknown) => data is object;
|
|
90
124
|
/** `Tether.query()`: the caller's own query text decides the shape of `data`, and the caller's `T` states it. */
|
|
91
|
-
export declare function query<T>(text: QueryText, variables?: Record<string, unknown>, options?: RequestOptions): Promise<T>;
|
|
125
|
+
export declare function query<T>(text: QueryText, variables?: Record<string, unknown>, options?: Omit<RequestOptions, 'operation'>): Promise<T>;
|
|
92
126
|
/**
|
|
93
127
|
* @param payload A mutation's payload.
|
|
94
128
|
* @param name The mutation, for the error message.
|
|
@@ -91,7 +91,12 @@ export interface TetherConfig {
|
|
|
91
91
|
sellingPlanGroupsFirst: number;
|
|
92
92
|
sellingPlansFirst: number;
|
|
93
93
|
collectionFirst: number;
|
|
94
|
-
/**
|
|
94
|
+
/**
|
|
95
|
+
* How many times a failed request is sent again. A query is retried after a network error (no answer, or a body that
|
|
96
|
+
* stopped arriving), a 429, a 5xx or Shopify's `THROTTLED`. A mutation, a cart change included, is retried only
|
|
97
|
+
* after a 429 or `THROTTLED`, which Shopify sends without running it: after a network error or a 5xx it may
|
|
98
|
+
* already have applied the change.
|
|
99
|
+
*/
|
|
95
100
|
retries: number;
|
|
96
101
|
/** Refresh server-rendered products once in the background. */
|
|
97
102
|
revalidate: boolean;
|
|
@@ -33,7 +33,7 @@ export type { AddressFields as CustomerAddressInput } from './account/operations
|
|
|
33
33
|
export type { CustomerAddress, Fulfillment, MailingAddress, OrderDetail, OrderDetailLine, SubscriptionContract, SubscriptionLine, } from './account/page-answers.js';
|
|
34
34
|
/** The helpers for selling plans, `Tether.plans`. */
|
|
35
35
|
export type SellingPlanHelpers = typeof plans;
|
|
36
|
-
export declare const VERSION = "0.7.
|
|
36
|
+
export declare const VERSION = "0.7.1";
|
|
37
37
|
/**
|
|
38
38
|
* Mounts every product scope and product list inside `root`. Safe to call repeatedly.
|
|
39
39
|
*
|
|
@@ -70,7 +70,7 @@ declare const publicApi: {
|
|
|
70
70
|
withContext: typeof withContext;
|
|
71
71
|
cart: {
|
|
72
72
|
init: () => Promise<ShopifyCart | null>;
|
|
73
|
-
id: ()
|
|
73
|
+
id: typeof import("./cart/store.js").savedCartId;
|
|
74
74
|
readonly status: import("./cart/store.js").CartStatus;
|
|
75
75
|
readonly state: ShopifyCart | null;
|
|
76
76
|
readonly lines: import("./cart/store.js").ShopifyCartLine[];
|
|
@@ -85,4 +85,6 @@ export declare const isProductShape: (value: unknown) => value is Product;
|
|
|
85
85
|
* A node a lookup by gid answers: a product, or a node of another type, for which `... on Product` selects no field
|
|
86
86
|
* (no `id`).
|
|
87
87
|
*/
|
|
88
|
-
export declare const PRODUCT_NODE: (node: unknown) =>
|
|
88
|
+
export declare const PRODUCT_NODE: (node: unknown) => node is Product | {
|
|
89
|
+
id?: undefined;
|
|
90
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@occluze/tether",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
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",
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
28
|
"dist",
|
|
29
|
-
"src",
|
|
30
29
|
"LICENSE",
|
|
31
30
|
"README.md"
|
|
32
31
|
],
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as M,b as z,c as H,d as C,e as Z,f as tt,g as et,h as nt,i as it}from"./chunk-T44MUL4Y.js";import{b as $,e as rt}from"./chunk-MPDWM2NN.js";import{e as Y}from"./chunk-A5SYCVQM.js";import{g as J,h as N,i as S,n as K}from"./chunk-BFTZR4OB.js";import{A as D,B,C as L,D as U,E as G,F as d,H as x,I,K as V,L as j,M as Q,N as W,O as X,l as p,m as o,n as l,o as T,p as f,q as R,t as v,v as _,w as g,x as F,y}from"./chunk-BA4LQJJQ.js";import{b as h,r as A,z as w}from"./chunk-E5YO6274.js";var ft=/^image:(\d+)$/,at="metafield:",gt=/^(rich_text|multi_line_text)_field$/,vt=["","true","all","*"],q=t=>t.tagName==="SELECT",b=(t,e)=>t.$(`select${e}`).filter(q);function bt(t,e){let n=e.images.nodes,i=[...t.children].map(a=>a.tagName==="IMG"?a:a.querySelector("img"));!F(t)&&i.length===n.length&&i.every((a,s)=>_(a?.getAttribute("src"),n[s]?.url))||y(t,n,(a,s)=>{let c=a.matches(`img,${o("bind","image")}`)?a:f(a,"img")[0]??a;g(c,s.url,s.altText||e.title)})}function Et(t,e,n){let i=n.indexOf("."),r=n.slice(0,i),a=n.slice(i+1),s=(e.metafields??[]).find(u=>u?.namespace===r&&u.key===a);if(!s){d(t,"");return}let c=s.reference?.image;if(c){g(t,c.url,c.altText);return}gt.test(s.type)&&(t.style.whiteSpace="pre-line"),d(t,s.value)}var Pt=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=>U(t.publishedAt),"min-price":t=>L(t.priceRange.minVariantPrice),"max-price":t=>L(t.priceRange.maxVariantPrice)}));function Tt(t,e){let n=(t.getAttribute("exclude")??"").split(",").map(r=>r.trim()).filter(Boolean),i=e.tags.filter(r=>!n.includes(r));y(t,i,(r,a)=>{d(r,a)})}function yt(t,e,n){let i=Pt.get(e);if(i){d(t,i(n));return}switch(e){case"description":G(t,n.descriptionHtml);break;case"featured-image":g(t,n.featuredImage?.url,n.featuredImage?.altText||n.title);break;case"url":case"link":{let r=D(n.handle,n.id);r&&t.setAttribute("href",r),e==="url"&&!t.firstElementChild&&!t.textContent.trim()&&d(t,n.title);break}case"images":bt(t,n);break;case"tags":Tt(t,n);break;default:Lt(t,e,n)}}function Lt(t,e,n){let i=ft.exec(e);if(i){let r=n.images.nodes[Number(i[1])-1]??n.featuredImage;g(t,r?.url,r?.altText||n.title)}else e.startsWith(at)&&Et(t,n,e.slice(at.length))}function xt(t){let{product:e}=t;t.$(o("option-list")).forEach(n=>{let i=t.optName(l(n,"option-list")),r=e.options.find(a=>a.name===i);if(!r||r.optionValues.length<=1&&T(n,"hide-single")){x(n,!1);return}y(n,r.optionValues,(a,s)=>{a.setAttribute(p("option-value"),s.name);let c=f(a,o("bind","option-value"))[0];c?d(c,s.name):a.firstElementChild||d(a,s.name);let u=f(a,o("bind","swatch"))[0],{swatch:m}=s;!u||!m||(m.color&&(u.style.backgroundColor=m.color),m.image?.previewImage&&g(u,m.image.previewImage.url,s.name))})})}function It(t){let{product:e}=t;b(t,o("option")).forEach(n=>{let i=e.options.find(r=>r.name===t.optName(l(n,"option")));if(!i){x(n,!1);return}n.replaceChildren(...i.optionValues.map(r=>new Option(r.name,r.name)))}),b(t,o("variant-select")).forEach(n=>{n.replaceChildren(...e.variants.nodes.map(i=>new Option(i.title,i.id)))}),b(t,o("plan")).forEach(n=>{let i=t.plans.map(s=>new Option(s.name,s.id)),r=!e.requiresSellingPlan&&l(n,"plan")!=="subscription-only",a=n.getAttribute(p("one-time-label"))||"One-time purchase";n.replaceChildren(...r?[new Option(a,"")]:[],...i)})}function St(t){t.$(o("plan-list")).forEach(e=>{let n=(l(e,"plan-list")??"").trim(),i=vt.includes(n.toLowerCase())?null:n,r=t.plans.filter(a=>!i||a.group.name===i);y(e,r,(a,s)=>{a.setAttribute(p("plan-value"),s.id),!a.firstElementChild&&!a.querySelector(o("plan-bind"))&&d(a,s.name)})})}function st(t){t.$(o("bind")).forEach(e=>{yt(e,l(e,"bind")??"",t.product)}),xt(t),It(t),St(t)}var ot={money:L,percent:B},Mt=t=>t.tagName==="INPUT";function O(t){let e=f(t,o("add-label"))[0]??t,n=e.dataset.tetherLabel??(Mt(e)?e.value:e.textContent);return e.dataset.tetherLabel=n,{label:e,original:n}}function kt(t,e){let{product:n}=t,i=r=>e.selected[t.optName(r)]??"";t.$(o("option-selected")).forEach(r=>{d(r,i(l(r,"option-selected")))}),t.$(o("option-list")).forEach(r=>{let a=t.optName(l(r,"option-list"));f(r,o("option-value")).forEach(s=>{let c=l(s,"option-value")??"";I(s,e.selected[a]===c);let u=!z(n,e.selected,a,c);s.classList.toggle("is-unavailable",u),s.setAttribute("data-unavailable",u?"true":"false")})}),b(t,o("option")).forEach(r=>{r.value=i(l(r,"option"))}),b(t,o("variant-select")).forEach(r=>{r.value=e.variant.id})}function At(t,e){let{variant:n,purchase:i,line:r}=e;t.$(o("purchase")).forEach(a=>{if(q(a)){a.value=i.kind;return}let s=l(a,"purchase");I(a,s===i.kind);let c=s==="subscription"?!e.subscriptionAvailable:t.product.requiresSellingPlan;a.classList.toggle("is-unavailable",c)}),t.$(o("plan-value")).forEach(a=>{let s=l(a,"plan-value")??"";I(a,r.kind==="subscription"&&s===r.planId),a.classList.toggle("is-unavailable",!S(n,s));let c=t.plans.find(m=>m.id===s),u=it(n,s,c,ot);f(a,o("plan-bind")).forEach(m=>{let E=u.get(l(m,"plan-bind")??"");E&&d(m,E())})}),b(t,o("plan")).forEach(a=>{a.value=r.kind==="subscription"?r.planId:""})}function wt(t,e){let n=new Map(Object.entries(e.show));$.forEach(i=>n.set(i,i==="ready")),t.$(o("show")).forEach(i=>{let r=l(i,"show")??"",a=n.get(r);a!==void 0&&($.some(s=>s===r)&&!rt(i,t.root)||x(i,a))})}function Vt(t,e){let n=!e.variant.availableForSale;t.$(o("add-to-cart")).forEach(i=>{i.classList.toggle("is-disabled",n),i.setAttribute("aria-disabled",String(n)),"disabled"in i&&(i.disabled=n);let r=l(i,"soldout-text"),a=l(i,"subscribe-text");if(!r&&!a)return;let{label:s,original:c}=O(i),u=c;e.line.kind==="subscription"&&a&&(u=a),n&&r&&(u=r),i.getAttribute("aria-busy")!=="true"&&d(s,u)})}function lt(t,e){let{variant:n}=e,{product:i}=t,r=nt(e,ot);t.$(o("bind")).forEach(a=>{let s=l(a,"bind")??"";if(s==="variant-image"){g(a,n.image?.url||i.featuredImage?.url,n.image?.altText||i.title);return}let c=r.get(s);c&&d(a,c())}),kt(t,e),At(t,e),wt(t,e),t.root.classList.toggle("is-subscription",e.line.kind==="subscription"),t.root.setAttribute(p("purchase-mode"),e.line.kind),Vt(t,e)}var ut=()=>o("product"),Nt=t=>t.tagName==="INPUT"||t.tagName==="SELECT"||t.tagName==="TEXTAREA",ct=t=>t instanceof window.Element;function P(t,e,n){let i=e.closest(n);return i?.closest(ut())===t.root?i:null}function Ht(t,e){let{label:n,original:i}=O(e),r=l(e,"adding-text");Q(e,async()=>{r&&d(n,r);try{await t.addToCart()}catch(a){w(a,"add to cart failed"),v("error",{error:a,context:"add-to-cart"},t.root)}finally{r&&d(n,i)}}).then(()=>{t.renderVariant()}).catch(a=>{w(a,"add to cart render")})}function Ct(t,e,n){let i=P(t,n,o("option-value")),r=i?.closest(o("option-list"));if(i&&r){e.preventDefault(),t.select(t.optName(l(r,"option-list")),l(i,"option-value")??"");return}let a=P(t,n,o("plan-value"));if(a){e.preventDefault(),t.selectPlan(l(a,"plan-value"));return}let s=P(t,n,`${o("purchase")}:not(select)`);if(s){s.tagName!=="INPUT"&&e.preventDefault(),t.setPurchase(dt(l(s,"purchase")));return}let c=P(t,n,o("qty-plus")),u=c?null:P(t,n,o("qty-minus"));if(c||u){e.preventDefault(),t.setQuantity(t.quantity+(c?1:-1));return}let m=P(t,n,o("add-to-cart"));m&&(e.preventDefault(),Ht(t,m))}var dt=t=>t==="subscription"?"subscription":"one-time";function $t(t,e){let n=Nt(e)?e.value:"";e.matches(`select${o("option")}`)?t.select(t.optName(l(e,"option")),n):e.matches(`select${o("variant-select")}`)?t.selectVariant(n):e.matches(`select${o("plan")}`)?n?t.selectPlan(n):t.setPurchase("one-time"):e.matches(`select${o("purchase")}`)?t.setPurchase(dt(n)):e.matches(o("qty"))&&t.setQuantity(n)}function mt(t){t.root.addEventListener("click",e=>{ct(e.target)&&Ct(t,e,e.target)}),t.root.addEventListener("change",e=>{let{target:n}=e;ct(n)&&n.closest(ut())===t.root&&$t(t,n)})}var qt=new WeakMap,Ot=()=>o("product"),k=new Map;function Rt(t){t.forEach(e=>{k.has(e.handle)||k.set(e.handle,e.options.map(n=>n.name))})}var pt=t=>t.tagName==="INPUT",_t=t=>t.tagName==="INPUT"||t.tagName==="SELECT"||t.tagName==="TEXTAREA";function Ft(t){return pt(t)&&t.type==="checkbox"?t.checked?t.value&&t.value!=="on"?t.value:"Yes":null:pt(t)&&t.type==="radio"?t.checked?t.value:null:_t(t)&&t.value||null}var ht=class{constructor(e,n){h(this,"root");h(this,"product");h(this,"plans");h(this,"selected");h(this,"purchase");h(this,"variant");h(this,"quantity");this.root=e,this.product=n,this.plans=N(n);let i=new URLSearchParams(window.location.search),r=tt(n,{variant:i.get("variant")||l(e,"variant"),sellingPlan:i.get("selling_plan"),defaultPlan:l(e,"default-plan"),defaultPurchase:l(e,"default-purchase")||A.defaultPurchase});this.selected=r.selected,this.purchase=r.purchase,this.variant=null,this.quantity=T(e,"quantity")?Math.max(0,parseInt(l(e,"quantity")??"",10)||0):1,qt.set(e,this),e.setAttribute(p("state"),"ready"),e.removeAttribute(p("error")),this.renderProduct(),mt(this),this.renderVariant(),j(e,"product"),V("product"),v("product-ready",{product:n,scope:this},e)}update(e){let n=this.variant?.id;this.product=e,this.plans=N(e);let i=e.variants.nodes.find(r=>r.id===n);i&&(this.selected=M(i)),this.root.setAttribute(p("state"),"ready"),this.root.removeAttribute(p("error")),this.renderProduct(),this.renderVariant(),V("product"),v("product-updated",{product:e,scope:this},this.root)}$(e){let n=R(this.root,e,Ot());return this.root.matches(e)?[this.root,...n]:n}optName(e){if(!e)return"";let{options:n}=this.product;if(n.some(r=>r.name===e))return e;let i=(k.get(this.product.handle)??[]).indexOf(e);return n[i]?.name??e}get plan(){let e=H(this.purchase);return this.plans.find(n=>n.id===e)??null}get subscriptionAvailable(){return this.plans.some(e=>S(this.variant,e.id))}get isSubscription(){return C(this.purchase,this.variant).kind==="subscription"}getLine(){if(!this.variant)return null;let e={merchandiseId:this.variant.id,quantity:this.quantity},n=C(this.purchase,this.variant);n.kind==="subscription"&&(e.sellingPlanId=n.planId);let i=this.collectAttributes();return i.length&&(e.attributes=i),e}collectAttributes(){let e=X(W(this.root,"line-attributes")),n=this.$(o("line-attribute")).flatMap(i=>{let r=Ft(i);return r===null?[]:[{key:l(i,"line-attribute")??"",value:r}]});return[...e,...n]}select(e,n){if(this.selected[e]===n)return;let i=this.product.variants.nodes.filter(s=>s.selectedOptions.some(c=>c.name===e&&c.value===n)),[r]=i;if(!r)return;let a={...this.selected,[e]:n};if(!i.some(s=>s.selectedOptions.every(c=>a[c.name]===c.value))){let s=u=>u.selectedOptions.filter(E=>E.name!==e&&this.selected[E.name]===E.value).length*2+(u.availableForSale?1:0),c=i.reduce((u,m)=>s(m)>s(u)?m:u,r);Object.assign(a,M(c))}this.selected=a,this.renderVariant()}selectVariant(e){let n=this.product.variants.nodes.find(i=>i.id===J.variant(e));n&&(this.selected=M(n),this.renderVariant())}setPurchase(e){let n=Z(this.product,this.variant,e,H(this.purchase));n.kind!==this.purchase.kind&&(this.purchase=n,this.renderVariant())}selectPlan(e){let n=K(this.product,e);n&&(this.purchase={kind:"subscription",planId:n.id},this.renderVariant())}setQuantity(e){let n=T(this.root,"quantity")?0:1;this.quantity=Math.max(n,parseInt(String(e),10)||0),this.$(o("qty")).forEach(i=>{d(i,this.quantity)}),this.renderVariant()}async addToCart(){if(!this.variant?.availableForSale)return null;let e=this.getLine();if(!e||e.quantity<1)return null;let n=await Y.add(e);return v("product-added",{product:this.product,variant:this.variant,line:e},this.root),n}renderProduct(){let{product:e}=this;k.has(e.handle)||this.$(`${o("option-list")},select${o("option")}`).map(i=>l(i,"option-list")||l(i,"option")).some(i=>e.options.some(r=>r.name===i))&&Rt([e]),st(this)}renderVariant(){let e=et(this.product,{selected:this.selected,purchase:this.purchase,quantity:this.quantity},A.lowStock);if(!e){this.variant=null;return}this.variant=e.variant,this.selected=e.selected,this.purchase=e.purchase,lt(this,e),v("variant-changed",{product:this.product,variant:e.variant,selected:{...e.selected},purchase:e.purchase.kind,sellingPlanId:e.line.kind==="subscription"?e.line.planId:null},this.root)}};export{qt as a,Rt as b,ht as c};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{b as Y,d as ht,g as q,h as Ct,p as x,v as bt}from"./chunk-BFTZR4OB.js";import{A as gt,C as I,F as G,G as v,H as N,K as yt,P as M,a as y,c as $,d as R,h as W,k as lt,l as F,m as s,n as w,p as l,t as f,w as mt,y as pt,z as ft}from"./chunk-BA4LQJJQ.js";import{C as dt,r as a,x as ct,z as S}from"./chunk-E5YO6274.js";var jt={id:"string",quantity:"number",attributes:["object"],cost:{totalAmount:x,subtotalAmount:x,amountPerQuantity:x},merchandise:{id:"string",selectedOptions:["object"],product:"object"}},X={id:"string",checkoutUrl:"string",totalQuantity:"number",attributes:["object"],discountCodes:["object"],cost:{totalAmount:x,subtotalAmount:x},lines:{nodes:[jt]}};var Ht='a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])',Bt=60,z=!1,K=null,Gt=t=>t!==null&&"focus"in t,St=t=>l(t,Ht).filter(n=>n.offsetParent!==null||n===document.activeElement),k=()=>l(document,s("cart-drawer")),J=t=>t.classList.contains(a.cartDrawerOpenClass);function g(){let t=k();return t.length?t.some(J):z}function V(t){l(document,s("cart-open")).forEach(n=>{n.setAttribute("aria-expanded",String(t))}),k().forEach(n=>{n.hasAttribute("role")||n.setAttribute("role","dialog"),!n.hasAttribute("aria-label")&&!n.hasAttribute("aria-labelledby")&&n.setAttribute("aria-label",w(n,"cart-label")||"Cart"),n.setAttribute("aria-modal",String(t)),!J(n)&&(n.setAttribute("aria-hidden","true"),a.cartFocus&&(n.inert=!0))})}function Yt(t){let n=St(t)[0]??t;n===t&&!t.hasAttribute("tabindex")&&(t.tabIndex=-1),n.focus({preventScroll:!0})}function _(){if(g())return;z=!0;let t=k().filter(e=>w(e,"cart-drawer")!=="manual");t.forEach(e=>{e.inert=!1,e.classList.add(a.cartDrawerOpenClass),e.setAttribute("aria-hidden","false")}),V(!0);let[n]=t;a.cartFocus&&n&&(K=Gt(document.activeElement)?document.activeElement:null,setTimeout(()=>{Yt(n)},Bt)),a.onCartOpen?.(t),f("cart-toggled",{open:!0})}function Z(){if(!g())return;z=!1;let t=k(),n=t.some(e=>e.contains(document.activeElement));t.forEach(e=>{e.classList.remove(a.cartDrawerOpenClass),e.setAttribute("aria-hidden","true"),a.cartFocus&&(e.inert=!0)}),V(!1),n&&K?.isConnected&&K.focus({preventScroll:!0}),K=null,a.onCartClose?.(t),f("cart-toggled",{open:!1})}function wt(){g()?Z():_()}function Xt(t){if(t.key!=="Tab"||!a.cartFocus||!g())return;let n=k().find(J);if(!n)return;let e=St(n),r=e[0],i=e.at(-1);if(!r||!i)return;let o=document.activeElement,u=t.shiftKey?o===r:o===i;n.contains(o)&&!u||(t.preventDefault(),(t.shiftKey?i:r).focus())}var vt="Default Title",tt=(t,n)=>n.get(t.id)?.quantity??t.quantity,At=t=>t.split("/").pop()??t;function zt(t){let n=t.merchandise,e=gt(n.product.handle,n.product.id);if(!e)return null;let r=new URLSearchParams;r.set("variant",At(n.id));let i=t.sellingPlanAllocation?.sellingPlan.id;return i&&r.set("selling_plan",At(i)),`${e}${e.includes("?")?"&":"?"}${r.toString()}`}var kt=t=>t.merchandise.product.title,Lt={title:kt,"product-title":kt,"variant-title":t=>t.merchandise.title===vt?"":t.merchandise.title,options:t=>t.merchandise.selectedOptions.filter(n=>n.value!==vt).map(n=>`${n.name}: ${n.value}`).join(", "),vendor:t=>t.merchandise.product.vendor,sku:t=>t.merchandise.sku??"",price:t=>I(t.cost.amountPerQuantity),"compare-at-price":t=>I(t.cost.compareAtAmountPerQuantity??t.merchandise.compareAtPrice),"line-total":t=>I(t.cost.totalAmount),"line-subtotal":t=>I(t.cost.subtotalAmount),quantity:(t,n)=>tt(t,n.pending),plan:t=>t.sellingPlanAllocation?.sellingPlan.name??"","plan-description":t=>t.sellingPlanAllocation?.sellingPlan.description??"",components:t=>(t.lineComponents??[]).map(n=>`${n.quantity} \xD7 ${n.merchandise.product.title}`).join(", ")},Pt="attribute:";function Jt(t,n,e){if(Object.hasOwn(Lt,n))return Lt[n]?.(t,e);if(!n.startsWith(Pt))return;let r=n.slice(Pt.length);return t.attributes.find(i=>i.key===r)?.value??""}function Zt(t,n,e){let r=Ct(e),i=!e.requiresSellingPlan&&w(t,"line-plan")!=="subscription-only",o={value:"",label:t.getAttribute(F("one-time-label"))||"One-time purchase"},u=[...i?[o]:[],...r.map(m=>({value:m.id,label:m.name}))],c=u.map(m=>m.value).join("|");t.dataset.tetherSig!==c&&(t.replaceChildren(...u.map(m=>{let b=document.createElement("option");return b.value=m.value,b.textContent=m.label,b})),t.dataset.tetherSig=c),t.value=n.sellingPlanAllocation?.sellingPlan.id??"",N(t,r.length>0)}function tn(t,n,e){let r=!!n.sellingPlanAllocation;t.classList.toggle("is-subscription",r);let i=e.warnings.find(c=>c.target===n.id);t.classList.toggle("is-warning",!!i);let o=e.pending.has(n.id);t.classList.toggle("is-busy",o),o?t.setAttribute("aria-busy","true"):t.removeAttribute("aria-busy"),l(t,s("line","warning")).forEach(c=>{v(c,i?.message??"")});let u=new Map([["subscription",r],["one-time",!r],["on-sale",ht(n.cost.compareAtAmountPerQuantity?.amount,n.cost.amountPerQuantity.amount)],["has-components",(n.lineComponents??[]).length>0],["warning",!!i]]);l(t,s("line-show")).forEach(c=>{let m=w(c,"line-show"),b=m===null?void 0:u.get(m);b!==void 0&&N(c,b)})}function nn(t,n,e){let r=n.merchandise;t.setAttribute(F("line-id"),n.id),l(t,s("line")).forEach(i=>{let o=w(i,"line")??"";if(o==="image"){mt(i,r.image?.url??r.product.featuredImage?.url,r.product.title);return}if(o==="url"){let c=zt(n);c&&i.setAttribute("href",c);return}let u=Jt(n,o,e);u!==void 0&&v(i,u)}),tn(t,n,e),l(t,`select${s("line-plan")}`).forEach(i=>{bt(r.product.handle).then(o=>{Zt(i,n,o)}).catch(o=>{S(o,"line plan options")})})}function en(t,n){let e=t?.totalQuantity??0,r=(t?.lines.nodes??[]).some(o=>o.sellingPlanAllocation),i=new Map([["cart-empty",e===0],["cart-filled",e>0],["cart-has-subscription",r],["cart-no-subscription",!r],["cart-has-discount",(t?.discountCodes??[]).some(o=>o.applicable)],["cart-error",n.failed],["cart-warning",n.warnings.length>0]]);l(document,s("show")).forEach(o=>{let u=w(o,"show"),c=u===null?void 0:i.get(u);c===void 0||o.closest(s("product"))||N(o,c)}),l(document,s("checkout")).forEach(o=>{o.classList.toggle("is-disabled",!e),o.setAttribute("aria-disabled",String(!e))})}function rn(t){l(document,`textarea${s("cart-note")},input${s("cart-note")}`).forEach(n=>{document.activeElement!==n&&G(n,t?.note??"")}),l(document,s("cart-discounts")).forEach(n=>{pt(n,t?.discountCodes??[],(e,r)=>{e.setAttribute(F("discount-code"),r.code);let i=e.querySelector(s("discount","code"))??(e.firstElementChild?null:e);i&&G(i,r.code),e.classList.toggle("is-inapplicable",!r.applicable)})})}function It(t){let{cart:n}=t,e=r=>n?I(n.cost[r]):"";V(g()),l(document,s("cart-count")).forEach(r=>{v(r,n?.totalQuantity??0)}),l(document,s("cart-subtotal")).forEach(r=>{v(r,e("subtotalAmount"))}),l(document,s("cart-total")).forEach(r=>{v(r,e("totalAmount"))}),l(document,s("cart-checkout-charge")).forEach(r=>{v(r,e("checkoutChargeAmount"))}),en(n,t),l(document,s("cart-warning")).forEach(r=>{v(r,[...new Set(t.warnings.map(i=>i.message))].join(" "))}),rn(n),l(document,s("cart-lines")).forEach(r=>{ft(r,n?.lines.nodes??[],i=>i.id,(i,o)=>{nn(i,o,t)},{onEnter:a.onLineEnter,onLeave:a.onLineLeave})}),n&&yt("cart")}function xt(t){l(document,s("cart-count")).forEach(n=>{/^\s*0?\s*$/.test(n.textContent)&&(n.textContent=String(t))})}function nt(t,n="localStorage"){try{return window[n].getItem(t)}catch{return null}}function et(t,n,e="localStorage"){try{window[e].setItem(t,n)}catch{}}function Et(t,n="localStorage"){try{window[n].removeItem(t)}catch{}}var p={kind:"unknown"},E=[],L=new Map,j=()=>p;function d(){switch(p.kind){case"ready":case"error":return p.cart;case"unknown":case"empty":return null}}var $t=()=>E,rt=t=>t?{kind:"ready",cart:t}:{kind:"empty"},Mt=()=>`${a.storageKey}:seen`,P=()=>nt(a.storageKey)||null;function T(){Et(a.storageKey)}function it(t){p=rt(t),t&&et(a.storageKey,t.id)}function U(){It({cart:d(),warnings:E,pending:L,failed:p.kind==="error"})}function O(t){U(),f("cart-updated",{cart:d(),reason:t})}function h(t,n){return it(t),et(Mt(),`${Date.now()}|${t?.totalQuantity??0}`),O(n),t}function Q(t){p=t.kind==="loaded"?rt(t.cart):{kind:"error",error:t.error,cart:null},O("load")}function on(){let t=nt(Mt())?.split("|")[1]??"",n=Number(t);return/^\d+$/.test(t)&&Number.isSafeInteger(n)?n:null}function qt(){if(p.kind!=="unknown")return;let t=on();t!==null&&xt(t)}function Ut(t){E=t.filter((n,e)=>t.findIndex(r=>r.message===n.message)===e).map(n=>({...n,message:a.warningText?.(n)||n.message})),E.length&&f("cart-warning",{warnings:E})}var Tt=()=>{};function an(){let t=Promise.resolve();return n=>{let e=t.then(n);return t=e.then(Tt,Tt),e}}var sn=an();function C(t){return sn(t).then(n=>(p.kind==="error"&&(p=rt(p.cart),U()),n),n=>{throw p={kind:"error",error:n,cart:d()},U(),f("cart-error",{error:n}),n})}var ot=t=>tt(t,L),un=()=>({open:g(),count:d()?.totalQuantity??0,loaded:p.kind!=="unknown",warnings:[...E]});function Ot(t){let n=["cart-updated","cart-toggled"].map(r=>`${a.prefix}:${r}`),e=()=>{t(d(),un())};return n.forEach(r=>{document.addEventListener(r,e)}),e(),()=>{n.forEach(r=>{document.removeEventListener(r,e)})}}var cn=/does not exist|not found|invalid id/i,ln=t=>R({[t]:$({cart:$(X)})});function H(t){return t instanceof y?t.userErrors?.some(n=>n.field?.[0]==="cartId")?!0:(t.errors??[]).some(n=>cn.test(n.message)):!1}function Dt(t,n=1,e={}){let r=typeof t=="object"&&t!==null?t:{...e,quantity:n,...t==null?{}:{variantId:t}},i=q.variant(r.merchandiseId||r.variantId||r.id);if(!i)throw new y("add(): variantId is required");let o=parseInt(String(r.quantity??1),10),u={merchandiseId:i,quantity:Math.max(1,o||1)},c=q.sellingPlan(r.sellingPlanId||r.sellingPlan);c&&(u.sellingPlanId=c);let m=M(r.attributes);return m.length&&(u.attributes=m),u}function dn(t,n,e){return r=>`mutation Tether_${t}(${n}){${t}(${e}){cart{...TetherCart}userErrors{field message}warnings{code message target}}}${Y(r)}`}async function Rt(t,n,e,r){let i=await W(dn(t,n,e),r,ln(t)),o=lt(i[t],t);return Ut(o.warnings??[]),o.cart}function Qt(t){let n=a.country?{buyerIdentity:{countryCode:a.country},...t}:t;return Rt("cartCreate","$input: CartInput!","input: $input",{input:n})}async function A({name:t,args:n,inner:e,variables:r,createInput:i}){let o=P();if(!o)return i?Qt(i):null;try{return await Rt(t,`$cartId: ID!, ${n}`,`cartId: $cartId, ${e}`,{...r,cartId:o})}catch(u){if(!H(u)||(T(),!i))throw u;return ct("cart expired, creating a new one"),Qt(i)}}async function Wt(t){return(await W(e=>`query TetherCart($id:ID!){cart(id:$id){...TetherCart}}${Y(e)}`,{id:t},R({cart:$(X)}))).cart}async function Ft(t){return(await W("query TetherCheckout($id: ID!) { cart(id: $id) { checkoutUrl } }",{id:t},R({cart:$({checkoutUrl:"string"})}))).cart?.checkoutUrl??null}function Nt(t,n){let e=typeof n=="number"?{quantity:n}:n,r={id:t};e.quantity!==void 0&&(r.quantity=e.quantity),"sellingPlanId"in e&&(r.sellingPlanId=e.sellingPlanId?q.sellingPlan(e.sellingPlanId):null),e.attributes&&(r.attributes=M(e.attributes));let i=e.merchandiseId||e.variantId;return i&&(r.merchandiseId=q.variant(i)),r}var at=t=>A({name:"cartLinesUpdate",args:"$lines: [CartLineUpdateInput!]!",inner:"lines: $lines",variables:{lines:t},createInput:null}),st=t=>A({name:"cartLinesRemove",args:"$lineIds: [ID!]!",inner:"lineIds: $lineIds",variables:{lineIds:t},createInput:null}),Kt=(t,n)=>n>0?at([{id:t,quantity:n}]):st([t]);var ut=null;function Vt(t){ut=t}var mn=t=>Ft(t).then(n=>({kind:"url",url:n}),n=>({kind:"failed",error:n}));async function pn(){if(!ut)return null;try{let t=await ut();return t&&`${t}${t.includes("?")?"&":"?"}logged_in=true`}catch(t){return S(t,"account checkout"),null}}async function fn(t){let n=mn(t),e=await pn();if(e)return e;let r=await n;if(r.kind==="failed")throw r.error;if(!r.url)throw new y("No checkoutUrl (cart empty or expired)");return r.url}function gn(t){try{t.opener=null}catch{}}async function _t(t=a.checkoutTarget){let n=P(),e=d();if(!n||e&&!e.totalQuantity)return null;let r=t==="_blank"?window.open("","_blank"):null;r&&gn(r);try{let i=await fn(n);if(!dt(i))throw new y("The checkout URL is not https: not opened");return f("checkout",{url:i,cart:d()}),r&&!r.closed?r.location.href=i:window.location.href=i,i}catch(i){return r?.close(),S(i,"checkout failed"),null}}var B=()=>d()?.lines.nodes??[];function yn(t,n){let e=B().find(c=>c.id===t);if(!e)return Promise.resolve(d());let r=Math.max(0,ot(e)+n),i={quantity:r};L.set(t,i),O("pending");let o=()=>L.get(t)===i;return C(async()=>{if(!o())return d();if(B().find(b=>b.id===t)?.quantity===r)return d();let m=await Kt(t,r);return o()?h(m,r>0?"update":"remove"):(it(m),m)}).finally(()=>{o()&&(L.delete(t),O("settled"))})}function hn(t){let n=(d()?.discountCodes??[]).map(r=>r.code),e=typeof t=="function"?t(n):t;return(Array.isArray(e)?e:[e]).map(r=>r.trim()).filter(Boolean)}function Cn(t){let n=new Map((d()?.attributes??[]).map(e=>[e.key,e.value]));return M(t).forEach(e=>n.set(e.key,e.value)),[...n].filter(([,e])=>e!=="").map(([e,r])=>({key:e,value:r}))}async function bn(){let t=P();if(!t)return Q({kind:"loaded",cart:null}),null;qt();try{let n=await Wt(t);n||T(),Q({kind:"loaded",cart:n})}catch(n){S(n,"cart load failed"),H(n)&&T(),Q({kind:"failed",error:n})}return d()}var D={init:bn,id:P,get status(){return j()},get state(){return d()},get lines(){return[...B()]},get count(){return d()?.totalQuantity??0},get loaded(){return j().kind!=="unknown"},get lastError(){let t=j();return t.kind!=="error"?null:t.error instanceof Error?t.error:new Error(String(t.error))},get warnings(){return[...$t()]},get pendingQty(){return L},setCheckoutResolver:Vt,forgetSaved(){T(),Q({kind:"loaded",cart:null})},render:U,subscribe:Ot,add(t,n=1,e={}){let r=(Array.isArray(t)?t:[t]).map(i=>Dt(i,n,e));return C(async()=>{let i=await A({name:"cartLinesAdd",args:"$lines: [CartLineInput!]!",inner:"lines: $lines",variables:{lines:r},createInput:{lines:r}});if(!i)throw new y("Shopify answered the add without a cart");return h(i,"add"),f("added",{cart:i,lines:r}),a.openCartOnAdd&&_(),i})},updateLine(t,n){let e=typeof n=="number"?n:n.quantity;if(e!==void 0&&e<=0)return D.removeLine(t);let r=Nt(t,n);return C(async()=>h(await at([r]),"update"))},changeQuantity:yn,quantityOf:ot,removeLine(t){let n=Array.isArray(t)?t:[t];return C(async()=>h(await st(n),"remove"))},clear(){let t=B().map(n=>n.id);return t.length?D.removeLine(t):Promise.resolve(d())},setNote(t){let n={note:t??""};return C(async()=>h(await A({name:"cartNoteUpdate",args:"$note: String!",inner:"note: $note",variables:n,createInput:n}),"note"))},setAttributes(t){return C(async()=>{let n={attributes:Cn(t)},e=await A({name:"cartAttributesUpdate",args:"$attributes: [AttributeInput!]!",inner:"attributes: $attributes",variables:n,createInput:n});return h(e,"attributes")})},setDiscountCodes(t){return C(async()=>{let n={discountCodes:hn(t)},e=await A({name:"cartDiscountCodesUpdate",args:"$discountCodes: [String!]!",inner:"discountCodes: $discountCodes",variables:n,createInput:n});return h(e,"discount")})},async applyDiscount(t){let n=await D.setDiscountCodes(i=>[...new Set([...i,t])]),e=t.toLowerCase();if((n?.discountCodes??[]).find(i=>i.code.toLowerCase()===e)?.applicable)return n;try{await D.removeDiscount(t)}catch(i){S(i,"removing a discount code Shopify refused")}throw new y(`Discount code not valid: ${t}`,{code:"INVALID_DISCOUNT"})},removeDiscount(t){let n=t.toLowerCase();return D.setDiscountCodes(e=>e.filter(r=>r.toLowerCase()!==n))},setBuyerIdentity(t,{create:n=!0}={}){return C(async()=>{let e=await A({name:"cartBuyerIdentityUpdate",args:"$buyerIdentity: CartBuyerIdentityInput!",inner:"buyerIdentity: $buyerIdentity",variables:{buyerIdentity:t},createInput:n?{buyerIdentity:t}:null}).catch(r=>{if(n||!H(r))throw r;return null});return h(e,"buyer-identity")})},checkout:_t,drawers:k,isOpen:g,open:_,close:Z,toggle:wt};export{Xt as a,nt as b,et as c,Et as d,D as e};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{A as G,E as j,F as Q,b as y,d as h,e as S,o as F,p as V,r as u,x as C,y as T,z as E}from"./chunk-E5YO6274.js";var p=class extends Error{constructor(r,{status:n,errors:i,userErrors:o,code:s}={}){super(r);y(this,"name","TetherError");y(this,"code");y(this,"status");y(this,"errors");y(this,"userErrors");this.code=s??(n?`HTTP_${n}`:"ERROR"),this.status=n,this.errors=i,this.userErrors=o}};function x(t,e){return typeof e=="function"?e(t):typeof e=="string"?e==="object"?h(t):typeof t===e:mt(e)?Array.isArray(t)&&t.every(r=>x(r,e[0])):h(t)&&Object.entries(e).every(([r,n])=>x(t[r],n))}var mt=t=>Array.isArray(t),Re=t=>e=>e===null||x(e,t),Oe=t=>e=>x(e,t);function ht(t=u){return`https://${t.domain}/api/${t.apiVersion}/graphql.json`}var yt=/"(?:\\.|[^"\\\n])*"|#[^\n]*/g,Et=/^\s*(?:query|mutation)(?:\s+\w+)?\s*(?:\([^)]*\))?/;function Y(t,{country:e,language:r}){let n=[];if(e&&n.push(`country: ${e}`),r&&n.push(`language: ${r}`),!n.length)return t;let i=`@inContext(${n.join(", ")})`,o=t.replace(yt,d=>" ".repeat(d.length)),s=o.indexOf("{");if(o.slice(0,s).includes("@inContext"))return t;if(o.trimStart().startsWith("{"))return`query ${i} ${t.slice(s)}`;let c=Et.exec(o);if(!c)return t;let l=c[0].length;return`${t.slice(0,l).trimEnd()} ${i} ${t.slice(l).trimStart()}`}function Pe(t,e=u){let r=F(e.country)??void 0,n=V(e.language)??void 0;return Y(t,{country:r,language:n})}var W=300,Tt=500,B=430,bt=1e3,I="quantityAvailable",q=new Set,wt=t=>`${t.domain} ${t.apiVersion} ${t.token}`;function At(t,e,r,n){let i=typeof e=="string"?e:e(r),o=n?Y(i,t):i;return t.maxAge<=0||/^\s*mutation\b/.test(o)?o:`${o} #${Math.floor(Date.now()/(t.maxAge*bt))}`}var St=t=>new Promise(e=>setTimeout(e,t));function R(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 xt(t){let e=S(t,"message"),r=S(S(t,"extensions"),"code"),n=typeof e=="string"?e:"";return typeof r=="string"?{message:n,extensions:{code:r}}:{message:n}}function vt(t){if(!h(t))return null;let{data:e,errors:r}=t;return r==null?{data:e}:Array.isArray(r)?{data:e,errors:r.map(xt)}:null}function N(t,e){let r=t.ok?`Invalid response (${t.status})`:R(t.status,e);return new p(r,{status:t.status})}function z(t,e,r){let n=e.map(o=>o.message).filter(Boolean).join(" | "),i=n||"Storefront API error";return t.ok||(i=t.status===401||t.status===403||!n?R(t.status,r):n),new p(i,{status:t.status,errors:e})}async function kt(t,e,r,n,i){let o;try{o=await(t.fetch??fetch)(ht(t),{method:"POST",headers:{"Content-Type":"application/json","X-Shopify-Storefront-Access-Token":t.token},body:JSON.stringify({query:e,variables:r})})}catch(f){if(i)return{kind:"retry",backoffMs:W};throw new p(`Network error: ${G(f)}`,{code:"NETWORK"})}if(o.status===B)throw new p("Shopify security rejection (430)",{status:B});if(i&&(o.status===429||o.status>=500))return{kind:"retry",backoffMs:W};let s;try{s=await o.json()}catch{throw N(o,t)}let c=vt(s);if(!c)throw N(o,t);let{data:l,errors:d=[]}=c;if(d.length){if(e.includes(I)&&d.some(f=>f.message.includes(I)))return{kind:"inventory-refused",error:z(o,d,t)};if(i&&d.some(f=>f.extensions?.code==="THROTTLED"))return{kind:"retry",backoffMs:Tt};throw z(o,d,t)}if(!o.ok)throw new p(R(o.status,t),{status:o.status});if(!n(l))throw N(o,t);return{kind:"data",data:l}}async function Lt(t,e,r,n,{context:i=!0}={}){if(!t.domain||!t.token)throw new p("Tether is not configured: domain and token are required",{code:"NOT_CONFIGURED"});let o=wt(t),s=0;for(;;){let c=At(t,e,{inventory:!q.has(o)},i),l=await kt(t,c,r,n,s<t.retries);switch(l.kind){case"data":return l.data;case"inventory-refused":if(typeof e=="string")throw l.error;C(`the token can't read inventory: ${I} is left out from now on`),q.add(o);break;case"retry":s+=1,C("retry",s),await St(l.backoffMs*2**s);break}}}function Ct(t,e,r,n){return Lt(u,t,e,r,n)}var Nt=t=>typeof t=="object"&&t!==null;function Me(t,e={},r){return Ct(t,e,Nt,r)}function _e(t,e){if(!t)throw new p(`${e}: empty response`);let r=t.userErrors??[];if(r.length)throw new p(r.map(n=>n.message).join(" | "),{userErrors:r});return t}var g=t=>`${u.prefix}-${t}`,It=(t,e)=>e===void 0?`[${g(t)}]`:`[${g(t)}="${e}"]`,O=(t,e)=>t.getAttribute(g(e)),Rt=(t,e)=>t.hasAttribute(g(e));function K(t,e){return t?[...t.querySelectorAll(e)]:[]}var Ot=(t,e,r)=>K(t,e).filter(n=>n.closest(r)===t),Pt=["product-ready","list-ready","cart-updated","cart-toggled","checkout","search"],J=new WeakMap;function X(t,e){let r=new CustomEvent(`${u.prefix}:${t}`,{detail:e,bubbles:!0});return J.set(r,t),r}function Mt(t,e){return J.get(t)===e}function P(t,e,r=document){r.dispatchEvent(X(t,e))}function tt(t,{width:e,height:r,crop:n}={}){if(!t)return t;let i;try{i=new URL(t)}catch(o){if(o instanceof TypeError)return t;throw o}return e&&i.searchParams.set("width",String(e)),r&&i.searchParams.set("height",String(r)),n&&i.searchParams.set("crop",n),i.toString()}function M(t,e){return t.getAttribute(e)??t.getAttribute(g(e))??t.getAttribute(`data-${e}`)}function et(t,e){if(!t||!e)return t;let r=M(e,"max-width"),n=M(e,"max-height");return tt(t,{width:r,height:n,crop:r||n?M(e,"crop"):null})}var Z=t=>t.replace(/\?.*$/,"");function rt(t,e){return!t||!e?!1:Z(t)===Z(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 Ht(t,e,r){if(!e)return;let n=et(e,t);if(t.tagName!=="IMG"){t.style.backgroundImage=_t(n);return}if(rt(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 _=new WeakMap,Ut=t=>!!_.get(t),H=t=>t.cloneNode(!0);function nt(t){let e=_.get(t);if(e!==void 0)return e;let r=t.firstElementChild,n=r?H(r):null;return _.set(t,n),t.replaceChildren(),n}function $t(t,e,r){let n=nt(t);if(!n){e.length&&T("repeater without a template child",t);return}t.replaceChildren(),e.forEach((i,o)=>{let s=H(n);r(s,i,o),t.appendChild(s)})}function Dt(t,e){let r=()=>{t.remove()};if(!e){r();return}try{e(t,r)}catch(n){E(n,"repeater onLeave"),r()}}function Ft(t,e,r,n){e.forEach((i,o)=>{if(!r.has(i))return;let s=e[o-1];if(s?.parentNode===t?s.after(i):t.prepend(i),!!n)try{n(i)}catch(c){E(c,"repeater onEnter")}})}function Vt(t,e,r,n,{onEnter:i,onLeave:o}={}){let s=nt(t);if(!s){T("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])),b=[],w=new Set;e.forEach((a,A)=>{let L=String(r(a,A)),m=f.get(L);m?f.delete(L):(m=H(s),m.setAttribute(c,L),w.add(m)),n(m,a,A,w.has(m)),b.push(m)});let k=b.filter(a=>!w.has(a)),D=d().filter(a=>k.includes(a));if(!(D.length===k.length&&D.every((a,A)=>a===k[A]))){f.forEach(a=>{a.remove()}),b.forEach(a=>t.appendChild(a));return}Ft(t,b,w,i),f.forEach(a=>{a.setAttribute(l,""),a.removeAttribute(c),a.style.pointerEvents="none",a.inert=!0,Dt(a,o)})}var Gt="http://www.w3.org/1999/xhtml",jt=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"]),Qt=new Set(["script","style","template","noscript","textarea","select","title"]),Wt=new Set(["style","title","lang","dir","role","align","width","height"]),Bt=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"])]]),qt=new Set(["href","src","poster","cite"]),zt=/^(javascript|vbscript|data):/i,Yt=/^data:image\/(png|gif|jpeg|webp|avif);/i,Kt=new Set(["position","top","right","bottom","left","z-index","-webkit-box-reflect"]),Jt=["inset","transform","translate","rotate","scale","offset"],Xt=/\d(?:[sld]?v|cq)(?:w|h|i|b|min|max)\b/i,Zt=/^(?:outline|box-shadow|text-shadow|filter|text-decoration|text-underline-offset|text-stroke)|^(?:border-image|mask-border|mask-box-image)(?:-outset)?$/,ot=40,te=new Map([["letter-spacing",{px:4,em:.25}],["word-spacing",{px:4,em:.25}],["text-indent",{px:ot}]]),it=/(?<![\w#.-])[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?(%|[a-z]+)?/gi,ee=/(?<![\w-])(?!drop-shadow\(|blur\()[\w-]+\([^()]*\)/g,st=/(?:var|calc|min|max|clamp|env|attr)\(/i,re=/url\(|expression\(|@import/i,ne=/[\u0000- ]/g,oe="allow-scripts allow-same-origin allow-popups allow-presentation",ie=new Set(["autoplay","encrypted-media","picture-in-picture","fullscreen","clipboard-write","accelerometer","gyroscope","web-share"]),se="strict-origin-when-cross-origin",ae=["https://www.youtube.com","https://www.youtube-nocookie.com","https://player.vimeo.com","https://www.loom.com","https://fast.wistia.net"];function ue(t,e){return Wt.has(e)||e.startsWith("aria-")||(Bt.get(t)?.has(e)??!1)}function ce(t,e,r){let n=r.replace(ne,"");return zt.test(n)?t==="img"&&e==="src"&&Yt.test(n):!0}function at(t,e){try{return new URL(t,e)}catch{return null}}function le(t,e,r){let n=t.baseURI,i=at(n)?.origin??"null";return{origin:i==="null"?null:i,baseUrl:n,styleParser:e,embedOrigins:new Set([...ae,...r])}}function de(t,e){let r=at(t.trim(),e.baseUrl);return r!==null&&r.origin!==e.origin&&e.embedOrigins.has(r.origin)}function fe(t){let e=t.split(";").map(r=>r.trim().split(/\s+/)[0]?.toLowerCase()??"");return[...new Set(e.filter(r=>ie.has(r)))].join("; ")}function pe(t,e){if(Kt.has(t)||Jt.some(n=>t.startsWith(n))||Xt.test(e))return!0;let r=te.get(t);return r?st.test(e)||ge(e,r):t.startsWith("margin")&&e.includes("-")}function ge(t,e){return[...t.matchAll(it)].some(([r="",n=""])=>{let i=parseFloat(r);if(i>=0)return!1;let o=e[n.toLowerCase()];return o===void 0||-i>o})}function me(t,e){return Zt.test(t.replace(/^-webkit-/,""))?st.test(e)?!0:[...e.replace(ee,"").matchAll(it)].some(([r="",n=""])=>{let i=Math.abs(parseFloat(r));return i!==0&&(n.toLowerCase()!=="px"||i>ot)}):!1}function he(t,e){let r=e.style;r.cssText=t;let n=Array.from({length:r.length},(o,s)=>r.item(s));for(let o of n){let s=r.getPropertyValue(o);(pe(o,s)||me(o,s)||re.test(s))&&r.removeProperty(o)}let i=r.cssText;return e.removeAttribute("style"),i}function ye(t,e){let r=t.localName;for(let o of[...t.attributes]){let s=o.name.toLowerCase(),c=qt.has(s);ue(r,s)&&(!c||ce(r,s,o.value))||t.removeAttribute(o.name)}let n=t.getAttribute("style");if(n===null)return;let i=he(n,e.styleParser);i===""?t.removeAttribute("style"):t.setAttribute("style",i)}function Ee(t){if(t.localName==="iframe"){let r=fe(t.getAttribute("allow")??"");r===""?t.removeAttribute("allow"):t.setAttribute("allow",r),t.setAttribute("sandbox",oe),t.setAttribute("referrerpolicy",se);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 Te(t,e){let r=t.localName,n=t.namespaceURI===Gt;if(n&&Qt.has(r)){t.remove();return}if(!n||!jt.has(r)){t.replaceWith(...t.childNodes);return}if(r==="iframe"&&!de(t.getAttribute("src")??"",e)){t.remove();return}ye(t,e),Ee(t)}function ut(t,e=globalThis.document,r=[]){let n=e.createElement("template");n.innerHTML=t??"";let i=le(e,n,r);for(let o of[...n.content.querySelectorAll("*")])Te(o,i);return n.content}var ct="data-tether-seen",$="data-tether-shown",v="data-tether-prev-display",be=120;function Ke(t,e){return Q(u.productPath||"/product",t,e)}function pt(t,e){try{return t()}catch(r){if(r instanceof RangeError)return e;throw r}}function Je(t,e=u.locale){return t?pt(()=>new Intl.NumberFormat(e||void 0,{style:"percent",maximumFractionDigits:0}).format(t/100),`${t}%`):""}function Xe(t){return t?u.formatMoney?u.formatMoney(t,u.locale):j(t,u.locale):""}function Ze(t){return t?pt(()=>new Date(t).toLocaleDateString(u.locale||void 0),""):""}function tr(t,e){t.replaceChildren(ut(e,t.ownerDocument,u.embedOrigins))}var gt=t=>t.tagName==="INPUT"||t.tagName==="TEXTAREA",lt=t=>t.tagName==="INPUT";function we(t,e){let r=e==null?"":String(e);gt(t)?t.value=r:t.textContent=r}var dt=t=>gt(t)?t.value:t.textContent;function er(t,e){let r=dt(t);if(we(t,e),r!==dt(t)&&t.hasAttribute(ct)&&u.onValueChange)try{u.onValueChange(t,r)}catch(n){E(n,"onValueChange")}t.setAttribute(ct,"1")}function Ae(t){if(t.hasAttribute($))return;t.setAttribute($,""),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(g("display"))||"block")}function rr(t,e){if(e){Ae(t);return}t.removeAttribute($),!t.hasAttribute(v)&&t.style.display!=="none"&&t.setAttribute(v,t.style.display),t.style.display="none"}function nr(t,e){t.classList.toggle("is-selected",e),t.setAttribute("aria-pressed",e?"true":"false"),lt(t)&&(t.type==="radio"||t.type==="checkbox")&&(t.checked=e);let r=t.querySelector('input[type="radio"],input[type="checkbox"]');r&<(r)&&(r.checked=e)}var ft,Se=t=>Reflect.get(window,t);function xe(){let t=Se("ScrollTrigger");if(typeof t!="function")return;let e=Reflect.get(t,"refresh");typeof e=="function"&&Reflect.apply(e,t,[])}function ve(t){clearTimeout(ft),ft=setTimeout(()=>{try{u.onLayoutChange?u.onLayoutChange(t):xe()}catch(e){E(e,"layout-changed")}P("layout-changed",{reason:t})},be)}function or(t,e){let r=[...t.querySelectorAll("img")].filter(o=>!o.complete),n=r.length,i=()=>{n-=1,n===0&&ve(`${e}:images`)};r.forEach(o=>{o.addEventListener("load",i,{once:!0}),o.addEventListener("error",i,{once:!0})})}function ir(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 sr(t,e){let r=t?O(t,e):null;if(!r)return null;try{return JSON.parse(r)}catch{return T(`invalid JSON in ${g(e)}`,t),null}}function U(t){return t==null?"":typeof t=="string"?t:typeof t=="number"||typeof t=="boolean"?String(t):JSON.stringify(t)}function ar(t){return Array.isArray(t)?t.filter(h).map(r=>({key:U(r.key),value:U(r.value)})):h(t)?Object.entries(t).map(([e,r])=>({key:e,value:U(r)})):[]}function ur(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{p as a,x as b,Re as c,Oe as d,ht as e,Pe as f,Lt as g,Ct as h,Nt as i,Me as j,_e as k,g as l,It as m,O as n,Rt as o,K as p,Ot as q,Pt as r,Mt as s,P as t,tt as u,rt as v,Ht as w,Ut as x,$t as y,Vt as z,Ke as A,Je as B,Xe as C,Ze as D,tr as E,we as F,er as G,rr as H,nr as I,Se as J,ve as K,or as L,ir as M,sr as N,ar as O,ur as P};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var e={diagnose:()=>import("./diagnose-3FEKRIEK.js"),markets:()=>import("./markets-ui-FD6NI2OG.js"),search:()=>import("./search-UJ73YBQ5.js"),extras:()=>import("./extras-6POFBNOP.js"),account:()=>import("./account-UIPWJQ3Y.js"),"account-pages":()=>import("./account-pages-6ROA6Y4V.js"),analytics:()=>import("./analytics-2V632IRV.js")},a=t=>e[t](),r=void 0;export{a,r as b};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as S}from"./chunk-56FCLJJD.js";import"./chunk-T44MUL4Y.js";import"./chunk-MPDWM2NN.js";import{e as g}from"./chunk-A5SYCVQM.js";import"./chunk-BFTZR4OB.js";import{N as w,O as k,m as s,n as d,o as m,p as y,t as h}from"./chunk-BA4LQJJQ.js";import{d as p,r as u,y as f,z as l}from"./chunk-E5YO6274.js";function v(t,e){let r=k(w(t,"line-attributes"));return e?[{key:"_group",value:e},...r]:r}async function q(t){let e=t.closest(s("group"));if(!e)return null;let r=d(e,"group"),o=v(e,r),n=y(e,s("product")).flatMap(i=>{let a=S.get(i);if(!a?.variant?.availableForSale||a.quantity<=0)return[];let c=a.getLine();return c?[{...c,attributes:[...c.attributes??[],...o]}]:[]});if(!n.length)return f("group-add: nothing selected"),null;try{let i=await g.add(n);return h("group-added",{group:r,lines:n},e),i}catch(i){return l(i,"group add"),null}}function E(t){let e;try{e=JSON.parse(t)}catch{return null}if(!p(e))return null;let{country:r,language:o,locale:n}=e;return typeof r!="string"||!r?null:{country:r,language:typeof o=="string"?o:null,locale:typeof n=="string"?n:void 0}}function A(t){if(t.key===u.storageKey||t.key===`${u.storageKey}:seen`){g.init().catch(n=>{l(n,"cart from another tab")});return}if(t.key!==`${u.prefix}:market:${u.domain}`||!t.newValue)return;let e=E(t.newValue),r=Reflect.get(window,"Tether");if(!e||!r)return;let o={language:e.language,locale:e.locale,remember:!1};r.setCountry(e.country,o).catch(n=>{l(n,"market from another tab")})}var b=new WeakMap,C=t=>t.split("/").pop()??t;function M(t){try{window.history.replaceState(window.history.state,"",t)}catch{}}function J(t,{variant:e,sellingPlanId:r}){let o=`${e.id}|${r??""}`,n=b.get(t);if(b.set(t,o),!n||n===o)return;let i=u.variantUrl&&document.querySelector(s("product"))===t;if(!m(t,"variant-url")&&!i)return;let a=new URL(window.location.href);a.searchParams.set("variant",C(e.id)),r?a.searchParams.set("selling_plan",C(r)):a.searchParams.delete("selling_plan"),M(a)}export{q as addGroup,A as onStorage,J as writeVariantUrl};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{h as M}from"./chunk-4GCXM764.js";import"./chunk-56FCLJJD.js";import"./chunk-T44MUL4Y.js";import"./chunk-MPDWM2NN.js";import"./chunk-A5SYCVQM.js";import"./chunk-BFTZR4OB.js";import{A as x,C,F as q,H as d,c as S,d as E,h as T,l as A,m as o,n as m,p as h,t as I,w as L,y as w}from"./chunk-BA4LQJJQ.js";import{b as a,r as u,x as b,z as y}from"./chunk-E5YO6274.js";var N=E({predictiveSearch:S({products:[{priceRange:"object"}],collections:["object"],queries:[{text:"string"}]})}),U="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}}}",D=6,V=2,F="/search",R=new WeakSet,v=0;function $(s,t,e){return parseInt(m(s,t)||"",10)||e}var H=s=>s.tagName==="A"?s:s.querySelector("a");function p(s,t){h(s,o("search-bind")).forEach(e=>{let i=m(e,"search-bind");i==="image"?L(e,t.image?.url,t.image?.altText||t.title):(i==="title"||i==="price"||i==="text")&&t[i]!=null&&q(e,t[i])})}function k(s,t){let e=H(s);e&&(t&&e.setAttribute("href",t),e.setAttribute("role","option"))}var f=class{constructor(t,e,i){a(this,"root");a(this,"input");a(this,"results");a(this,"limit");a(this,"minCharacters");a(this,"resultsId");a(this,"searchNumber",0);a(this,"timer");a(this,"lastTerm","");a(this,"cache",new Map);this.root=t,this.input=e,this.results=i,this.limit=$(t,"search-limit",D),this.minCharacters=$(t,"search-min",V),i.id||(v+=1,i.id=`${u.prefix}-search-${v}`),this.resultsId=i.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(A("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 i=await T(U,{q:t,limit:this.limit},N);return this.cache.set(t,i.predictiveSearch),i.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 i=await this.fetchResults(t);e===this.searchNumber&&this.render(i,t)}catch(i){if(e!==this.searchNumber){b("a superseded search failed",i);return}this.setState("error"),y(i,"search")}}fillList(t,e,i){h(this.results,o(t)).forEach(l=>{w(l,e,i),d(l,e.length>0)})}queryUrl(t){let e=this.root.getAttribute("action")||F,i=e.includes("?")?"&":"?";return`${e}${i}${this.input.name||"q"}=${encodeURIComponent(t)}`}render(t,e){let i=t?.products??[],l=t?.collections??[],c=(t?.queries??[]).filter(n=>n.text.toLowerCase()!==e.toLowerCase());this.fillList("search-products",i,(n,r)=>{let P=C(r.priceRange.minVariantPrice);p(n,{title:r.title,price:P,image:r.featuredImage}),k(n,x(r.handle,r.id)),n.classList.toggle("is-sold-out",!r.availableForSale)}),this.fillList("search-collections",l,(n,r)=>{p(n,{title:r.title,image:r.image}),k(n,`${(u.collectionPath||"/collection").replace(/\/$/,"")}/${r.handle}`)}),this.fillList("search-queries",c,(n,r)=>{p(n,{text:r.text}),H(n)?.setAttribute("href",this.queryUrl(r.text))});let g=i.length+l.length+c.length;this.showCount(g),this.setState(g?"ready":"empty"),this.open(!0),I("search",{term:e,products:i,collections:l,queries:c},this.root)}showCount(t){h(this.root,o("show")).forEach(e=>{let i=m(e,"show");i==="search-empty"&&d(e,t===0),i==="search-results"&&d(e,t>0)}),this.options().forEach((e,i)=>{e.id||(e.id=`${this.resultsId}-${i}`),e.setAttribute("aria-selected","false")})}highlight(t,e){t.forEach((l,c)=>{l.setAttribute("aria-selected",String(c===e))});let i=t[e];i&&(this.input.setAttribute("aria-activedescendant",i.id),i.scrollIntoView?.({block:"nearest"}))}onKeydown(t){let e=this.options(),i=e.findIndex(l=>l.getAttribute("aria-selected")==="true");t.key==="ArrowDown"&&e.length?(t.preventDefault(),this.open(!0),this.highlight(e,(i+1)%e.length)):t.key==="ArrowUp"&&e.length?(t.preventDefault(),this.highlight(e,i<=0?e.length-1:i-1)):t.key==="Enter"&&i>=0?(t.preventDefault(),e[i]?.click()):t.key==="Escape"&&this.open(!1)}};function j(s=document){for(let t of M(s,o("search"))){if(R.has(t))continue;R.add(t);let e=t.querySelector(o("search-input"))??t.querySelector("input"),i=t.querySelector(o("search-results"));e&&i&&new f(t,e,i)}}export{j as mountSearch};
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The customer's addresses (`tether-addresses`), with `tether-show="addresses-loading"`, `addresses-empty` and
|
|
3
|
-
* `addresses-error`. The last list rendered is kept, so an edit button can fill the address form from it.
|
|
4
|
-
*/
|
|
5
|
-
import { reportError } from '../config.ts';
|
|
6
|
-
import { get, qsa, repeat, sel, setText } from '../dom.ts';
|
|
7
|
-
import { addressText, bindsIn, ownValue, showIn } from './markup.ts';
|
|
8
|
-
import { addresses } from './operations.ts';
|
|
9
|
-
import type { CustomerAddress } from './page-answers.ts';
|
|
10
|
-
|
|
11
|
-
let shown: readonly CustomerAddress[] = [];
|
|
12
|
-
|
|
13
|
-
/** @returns The address with this id in the list shown last. */
|
|
14
|
-
export const shownAddress = (id: string): CustomerAddress | undefined => shown.find((address) => address.id === id);
|
|
15
|
-
|
|
16
|
-
/** @returns The text of each `tether-address-bind` value. */
|
|
17
|
-
const addressTexts = (address: CustomerAddress): Record<string, string> => ({
|
|
18
|
-
formatted: addressText(address),
|
|
19
|
-
name: [address.firstName, address.lastName].filter(Boolean).join(' '),
|
|
20
|
-
company: address.company || '',
|
|
21
|
-
address1: address.address1 || '',
|
|
22
|
-
address2: address.address2 || '',
|
|
23
|
-
city: address.city || '',
|
|
24
|
-
zip: address.zip || '',
|
|
25
|
-
province: address.province || '',
|
|
26
|
-
country: address.country || '',
|
|
27
|
-
phone: address.phoneNumber || '',
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
function fillAddress(row: HTMLElement, address: CustomerAddress): void {
|
|
31
|
-
row.dataset['tetherAddress'] = address.id;
|
|
32
|
-
const texts = addressTexts(address);
|
|
33
|
-
bindsIn(row, 'address-bind').forEach((el) => {
|
|
34
|
-
const text = ownValue(texts, get(el, 'address-bind') ?? '');
|
|
35
|
-
if (text !== undefined) setText(el, text);
|
|
36
|
-
});
|
|
37
|
-
showIn(row, 'address-show', { default: address.isDefault, 'not-default': !address.isDefault });
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/** Loads and renders the addresses. A failure is reported and shows `addresses-error`, never "no addresses yet". */
|
|
41
|
-
export async function renderAddresses(root: ParentNode): Promise<void> {
|
|
42
|
-
const boxes = qsa(root, sel('addresses'));
|
|
43
|
-
if (!boxes.length) return;
|
|
44
|
-
showIn(root, 'show', { 'addresses-loading': true, 'addresses-empty': false });
|
|
45
|
-
let list: CustomerAddress[];
|
|
46
|
-
try {
|
|
47
|
-
list = await addresses();
|
|
48
|
-
} catch (error) {
|
|
49
|
-
reportError(error, 'addresses');
|
|
50
|
-
showIn(root, 'show', { 'addresses-loading': false, 'addresses-error': true });
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
shown = list;
|
|
54
|
-
showIn(root, 'show', { 'addresses-loading': false, 'addresses-empty': list.length === 0, 'addresses-error': false });
|
|
55
|
-
boxes.forEach((box) => {
|
|
56
|
-
repeat(box, list, fillAddress);
|
|
57
|
-
});
|
|
58
|
-
}
|
package/src/account/answers.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The Worker's account answers as typed values. The Worker passes on what Shopify answers to its fixed documents, and
|
|
3
|
-
* each answer is read once, field by field. Every field a document selects is kept. One that is missing or of another
|
|
4
|
-
* type reads as `null` (a list as empty, a count as 0): a page with one blank field is better than no page. The ids
|
|
5
|
-
* the pages act on are required, and an answer without one is an error. This module reads what the account part
|
|
6
|
-
* shows (the customer, their orders through the reader the Worker shares, Shopify's `userErrors`); page-answers.ts
|
|
7
|
-
* reads the account pages' answers.
|
|
8
|
-
*/
|
|
9
|
-
import { TetherError } from '../client.ts';
|
|
10
|
-
import type { UserError } from '../client.ts';
|
|
11
|
-
import { field, isRecord, listOf, textList, textOrNull } from '../../server/src/shared/json.ts';
|
|
12
|
-
import { readOrders } from '../../server/src/shared/account-orders.ts';
|
|
13
|
-
import type { AccountOrder } from '../../server/src/shared/account-orders.ts';
|
|
14
|
-
|
|
15
|
-
/** The logged-in customer. */
|
|
16
|
-
export interface AccountCustomer {
|
|
17
|
-
/** The customer's gid; left out when the Worker's `/me` doesn't send it. */
|
|
18
|
-
id?: string;
|
|
19
|
-
firstName: string | null;
|
|
20
|
-
lastName: string | null;
|
|
21
|
-
displayName: string | null;
|
|
22
|
-
emailAddress: { emailAddress: string } | null;
|
|
23
|
-
defaultAddress: { formatted: string[] } | null;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export const unexpected = (what: string): TetherError =>
|
|
27
|
-
new TetherError(`Customer accounts: the answer has no ${what}`);
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @param what Named in the error.
|
|
31
|
-
* @throws {TetherError} Without an id.
|
|
32
|
-
*/
|
|
33
|
-
export function requiredId(value: unknown, what: string): string {
|
|
34
|
-
const id = textOrNull(value);
|
|
35
|
-
if (!id) throw unexpected(what);
|
|
36
|
-
return id;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** @param value The `customer` of the Worker's `/me`, which flattens the email and the default address. */
|
|
40
|
-
export function toAccountCustomer(value: unknown): AccountCustomer {
|
|
41
|
-
const customer = isRecord(value) ? value : {};
|
|
42
|
-
const id = textOrNull(customer['id']);
|
|
43
|
-
const email = textOrNull(customer['email']);
|
|
44
|
-
const address = customer['address'];
|
|
45
|
-
return {
|
|
46
|
-
...(id === null ? {} : { id }),
|
|
47
|
-
firstName: textOrNull(customer['firstName']),
|
|
48
|
-
lastName: textOrNull(customer['lastName']),
|
|
49
|
-
displayName: textOrNull(customer['displayName']),
|
|
50
|
-
emailAddress: email === null ? null : { emailAddress: email },
|
|
51
|
-
defaultAddress: Array.isArray(address) ? { formatted: textList(address) } : null,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* @param value The `orders` of the Worker's `/orders`.
|
|
57
|
-
* @throws {TetherError} For an order without an id.
|
|
58
|
-
*/
|
|
59
|
-
export function toAccountOrders(value: unknown): AccountOrder[] {
|
|
60
|
-
const reading = readOrders(value);
|
|
61
|
-
if (reading.kind === 'missing-id') throw unexpected('order id');
|
|
62
|
-
return reading.orders;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** @returns `null` for an entry without a message, which has nothing to show. */
|
|
66
|
-
function toUserError(value: unknown): UserError | null {
|
|
67
|
-
const message = textOrNull(field(value, 'message'));
|
|
68
|
-
if (message === null) return null;
|
|
69
|
-
const fieldPath = field(value, 'field');
|
|
70
|
-
return {
|
|
71
|
-
message,
|
|
72
|
-
field: Array.isArray(fieldPath) ? textList(fieldPath) : null,
|
|
73
|
-
code: textOrNull(field(value, 'code')),
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/** @param value Shopify's `userErrors`, as Shopify or the Worker sends them. */
|
|
78
|
-
export const toUserErrors = (value: unknown): UserError[] =>
|
|
79
|
-
listOf(value, toUserError).filter((error) => error !== null);
|