@occluze/tether 0.6.7 → 0.7.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 +11 -11
- package/dist/esm/astro.js +2 -2
- package/dist/esm/chunks/account-UIPWJQ3Y.js +1 -0
- package/dist/esm/chunks/account-pages-6ROA6Y4V.js +1 -0
- package/dist/esm/chunks/analytics-2V632IRV.js +1 -0
- package/dist/esm/chunks/chunk-4GCXM764.js +1 -0
- package/dist/esm/chunks/chunk-56FCLJJD.js +1 -0
- package/dist/esm/chunks/chunk-5Z5O3767.js +1 -0
- package/dist/esm/chunks/chunk-6OZJCAGZ.js +1 -0
- package/dist/esm/chunks/chunk-A5SYCVQM.js +1 -0
- package/dist/esm/chunks/chunk-BA4LQJJQ.js +1 -0
- package/dist/esm/chunks/chunk-BFTZR4OB.js +4 -0
- package/dist/esm/chunks/chunk-C5JYQCWH.js +1 -0
- package/dist/esm/chunks/chunk-E5YO6274.js +1 -0
- package/dist/esm/chunks/chunk-MPDWM2NN.js +1 -0
- package/dist/esm/chunks/chunk-T44MUL4Y.js +1 -0
- package/dist/esm/chunks/chunk-YLUULATY.js +1 -0
- package/dist/esm/chunks/diagnose-3FEKRIEK.js +14 -0
- package/dist/esm/chunks/extras-6POFBNOP.js +1 -0
- package/dist/esm/chunks/markets-ui-FD6NI2OG.js +1 -0
- package/dist/esm/chunks/search-UJ73YBQ5.js +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/server.js +2 -1
- package/dist/presets/barba.esm.js +55 -39
- package/dist/tether.account-pages.js +781 -495
- package/dist/tether.account-pages.min.js +1 -1
- package/dist/tether.account.js +462 -381
- package/dist/tether.account.min.js +1 -1
- package/dist/tether.analytics.js +299 -194
- package/dist/tether.analytics.min.js +1 -1
- package/dist/tether.diagnose.js +354 -262
- package/dist/tether.diagnose.min.js +2 -2
- package/dist/tether.extras.js +82 -45
- package/dist/tether.extras.min.js +1 -1
- package/dist/tether.js +3653 -2116
- package/dist/tether.markets.js +238 -150
- 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 +207 -136
- package/dist/tether.search.min.js +1 -1
- package/dist/types/server/src/shared/account-orders.d.ts +44 -0
- package/dist/types/server/src/shared/account-routes.d.ts +153 -0
- package/dist/types/server/src/shared/api-versions.d.ts +13 -0
- package/dist/types/server/src/shared/error-message.d.ts +2 -0
- package/dist/types/server/src/shared/json.d.ts +25 -0
- package/dist/types/server/src/shared/market-codes.d.ts +16 -0
- package/dist/types/src/account/addresses-view.d.ts +5 -0
- package/dist/types/src/account/answers.d.ts +40 -0
- package/dist/types/src/account/markup.d.ts +19 -0
- package/dist/types/src/account/operations.d.ts +41 -0
- package/dist/types/src/account/order-lines.d.ts +13 -0
- package/dist/types/src/account/order-list.d.ts +12 -0
- package/dist/types/src/account/order-page.d.ts +6 -0
- package/dist/types/src/account/page-answers.d.ts +182 -0
- package/dist/types/src/account/page-events.d.ts +2 -0
- package/dist/types/src/account/server-client.d.ts +60 -0
- package/dist/types/src/account/subscriptions-view.d.ts +2 -0
- package/dist/types/src/account-api.d.ts +18 -0
- package/dist/types/src/account-marks.d.ts +15 -0
- package/dist/types/src/account-pages.d.ts +8 -0
- package/dist/types/src/account.d.ts +64 -0
- package/dist/types/src/amounts.d.ts +12 -0
- package/dist/types/src/analytics-shopify.d.ts +41 -0
- package/dist/types/src/analytics.d.ts +2 -0
- package/dist/types/src/api-version.d.ts +28 -0
- package/dist/types/src/astro.d.ts +42 -0
- package/dist/types/src/cart/cart-shape.d.ts +43 -0
- package/dist/types/src/cart/checkout.d.ts +16 -0
- package/dist/types/src/cart/drawer.d.ts +18 -0
- package/dist/types/src/cart/mutations.d.ts +79 -0
- package/dist/types/src/cart/render.d.ts +17 -0
- package/dist/types/src/cart/store.d.ts +182 -0
- package/dist/types/src/cart.d.ts +106 -0
- package/dist/types/src/client.d.ts +100 -0
- package/dist/types/src/collection.d.ts +25 -0
- package/dist/types/src/config-sections.d.ts +40 -0
- package/dist/types/src/config.d.ts +185 -0
- package/dist/types/src/controls/cart-controls.d.ts +2 -0
- package/dist/types/src/controls/discount.d.ts +2 -0
- package/dist/types/src/controls/extras.d.ts +5 -0
- package/dist/types/src/controls/navigation.d.ts +12 -0
- package/dist/types/src/diagnose-markup.d.ts +19 -0
- package/dist/types/src/diagnose.d.ts +60 -0
- package/dist/types/src/dom.d.ts +75 -0
- package/dist/types/src/extras.d.ts +21 -0
- package/dist/types/src/fragments.d.ts +158 -0
- package/dist/types/src/globals.d.ts +15 -0
- package/dist/types/src/images.d.ts +20 -0
- package/dist/types/src/index.d.ts +167 -0
- package/dist/types/src/initial.d.ts +56 -0
- package/dist/types/src/lazy.d.ts +28 -0
- package/dist/types/src/loader.d.ts +84 -0
- package/dist/types/src/market-codes.d.ts +6 -0
- package/dist/types/src/markets-ui.d.ts +32 -0
- package/dist/types/src/markets.d.ts +72 -0
- package/dist/types/src/markup.d.ts +131 -0
- package/dist/types/src/mounting.d.ts +46 -0
- package/dist/types/src/page-market.d.ts +27 -0
- package/dist/types/src/presets/barba.d.ts +56 -0
- package/dist/types/src/product-events.d.ts +2 -0
- package/dist/types/src/product-render.d.ts +17 -0
- package/dist/types/src/product-shape.d.ts +88 -0
- package/dist/types/src/product-state.d.ts +110 -0
- package/dist/types/src/product.d.ts +66 -0
- package/dist/types/src/repeaters.d.ts +16 -0
- package/dist/types/src/search.d.ts +33 -0
- package/dist/types/src/selling-plans.d.ts +64 -0
- package/dist/types/src/server.d.ts +88 -0
- package/dist/types/src/shopify-values.d.ts +46 -0
- package/dist/types/src/status.d.ts +33 -0
- package/dist/types/src/storage.d.ts +12 -0
- package/dist/types/src/store-html.d.ts +39 -0
- package/dist/types/src/storefront/catalog.d.ts +38 -0
- package/dist/types/src/storefront/json-ld.d.ts +20 -0
- package/dist/types/src/variant-render.d.ts +14 -0
- package/package.json +42 -22
- package/src/account/addresses-view.ts +58 -0
- package/src/account/answers.ts +79 -0
- package/src/account/markup.ts +36 -0
- package/src/account/operations.ts +145 -0
- package/src/account/order-lines.ts +75 -0
- package/src/account/order-list.ts +107 -0
- package/src/account/order-page.ts +137 -0
- package/src/account/page-answers.ts +317 -0
- package/src/account/page-events.ts +253 -0
- package/src/account/server-client.ts +183 -0
- package/src/account/subscriptions-view.ts +115 -0
- package/src/account-api.ts +98 -0
- package/src/account-marks.ts +35 -0
- package/src/account-pages.ts +81 -0
- package/src/account.ts +284 -0
- package/src/amounts.ts +64 -0
- package/src/analytics-shopify.ts +246 -0
- package/src/analytics.ts +315 -0
- package/src/api-version.ts +79 -0
- package/src/astro.ts +272 -0
- package/src/cart/cart-shape.ts +25 -0
- package/src/cart/checkout.ts +101 -0
- package/src/cart/drawer.ts +125 -0
- package/src/cart/mutations.ts +237 -0
- package/src/cart/render.ts +266 -0
- package/src/cart/store.ts +279 -0
- package/src/cart.ts +345 -0
- package/src/client.ts +391 -0
- package/src/collection.ts +175 -0
- package/src/config-sections.ts +284 -0
- package/src/config.ts +480 -0
- package/src/controls/cart-controls.ts +123 -0
- package/src/controls/discount.ts +75 -0
- package/src/controls/extras.ts +54 -0
- package/src/controls/navigation.ts +77 -0
- package/src/diagnose-markup.ts +298 -0
- package/src/diagnose.ts +294 -0
- package/src/dom.ts +268 -0
- package/src/extras.ts +136 -0
- package/src/fragments.ts +261 -0
- package/src/globals.d.ts +15 -0
- package/src/images.ts +91 -0
- package/src/index.ts +415 -0
- package/src/initial.ts +101 -0
- package/src/lazy-iife.ts +197 -0
- package/src/lazy.ts +42 -0
- package/src/loader.ts +363 -0
- package/src/market-codes.ts +6 -0
- package/src/markets-ui.ts +227 -0
- package/src/markets.ts +246 -0
- package/src/markup.ts +127 -0
- package/src/mounting.ts +264 -0
- package/src/page-market.ts +110 -0
- package/src/part-integrity.ts +7 -0
- package/src/parts/account-pages.ts +7 -0
- package/src/parts/account.ts +7 -0
- package/src/parts/analytics.ts +7 -0
- package/src/parts/diagnose.ts +7 -0
- package/src/parts/extras.ts +7 -0
- package/src/parts/markets.ts +7 -0
- package/src/parts/search.ts +7 -0
- package/src/presets/barba.ts +194 -0
- package/src/product-events.ts +115 -0
- package/src/product-render.ts +218 -0
- package/src/product-shape.ts +49 -0
- package/src/product-state.ts +318 -0
- package/src/product.ts +308 -0
- package/src/repeaters.ts +161 -0
- package/src/search.ts +305 -0
- package/src/selling-plans.ts +145 -0
- package/src/server.ts +211 -0
- package/src/shopify-values.ts +91 -0
- package/src/status.ts +106 -0
- package/src/storage.ts +34 -0
- package/src/store-html.ts +359 -0
- package/src/storefront/catalog.ts +196 -0
- package/src/storefront/json-ld.ts +144 -0
- package/src/variant-render.ts +139 -0
- package/dist/esm/chunks/account-Q6E2TFEV.js +0 -1
- package/dist/esm/chunks/account-pages-UZXR4R5F.js +0 -1
- package/dist/esm/chunks/analytics-IJBKATUP.js +0 -1
- package/dist/esm/chunks/chunk-4QJKLPYR.js +0 -1
- package/dist/esm/chunks/chunk-64TUD3QR.js +0 -1
- package/dist/esm/chunks/chunk-AJLPU2JC.js +0 -4
- package/dist/esm/chunks/chunk-FIOZPPC5.js +0 -1
- package/dist/esm/chunks/chunk-K2YEQAIH.js +0 -1
- package/dist/esm/chunks/chunk-KIDH76B7.js +0 -1
- package/dist/esm/chunks/chunk-PAYT5ZD7.js +0 -1
- package/dist/esm/chunks/chunk-RREHGH4A.js +0 -1
- package/dist/esm/chunks/chunk-SSJT43CJ.js +0 -1
- package/dist/esm/chunks/chunk-VC46IEJQ.js +0 -1
- package/dist/esm/chunks/diagnose-3WVAWNTX.js +0 -14
- package/dist/esm/chunks/extras-7I7WJX35.js +0 -1
- package/dist/esm/chunks/markets-ui-545XLFTE.js +0 -1
- package/dist/esm/chunks/search-NILMGYXG.js +0 -1
- package/src/account-pages.js +0 -318
- package/src/account.js +0 -385
- package/src/analytics.js +0 -232
- package/src/api-version.js +0 -35
- package/src/astro.js +0 -101
- package/src/cart.js +0 -559
- package/src/client.js +0 -131
- package/src/collection.js +0 -114
- package/src/config.js +0 -85
- package/src/diagnose.js +0 -246
- package/src/dom.js +0 -288
- package/src/extras.js +0 -63
- package/src/fragments.js +0 -144
- package/src/index.js +0 -395
- package/src/initial.js +0 -75
- package/src/lazy-iife.js +0 -46
- package/src/lazy.js +0 -18
- package/src/loader.js +0 -198
- package/src/markets-ui.js +0 -90
- package/src/markets.js +0 -133
- package/src/mounting.js +0 -154
- package/src/parts/account-pages.js +0 -3
- package/src/parts/account.js +0 -3
- package/src/parts/analytics.js +0 -3
- package/src/parts/diagnose.js +0 -3
- package/src/parts/extras.js +0 -3
- package/src/parts/markets.js +0 -3
- package/src/parts/search.js +0 -3
- package/src/presets/barba.js +0 -100
- package/src/product.js +0 -570
- package/src/search.js +0 -153
- package/src/selling-plans.js +0 -94
- package/src/server.js +0 -252
- package/src/status.js +0 -66
- package/types/astro.d.ts +0 -17
- package/types/barba.d.ts +0 -16
- package/types/index.d.ts +0 -426
- package/types/server.d.ts +0 -110
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preset for sites with page transitions (Barba, Swup), smooth scroll (Lenis) and GSAP. Nothing is read from globals
|
|
3
|
+
* except GSAP and ScrollTrigger by default: pass in what your site has.
|
|
4
|
+
*
|
|
5
|
+
* import Tether from "@occluze/tether";
|
|
6
|
+
* import { barbaPreset } from "@occluze/tether/presets/barba";
|
|
7
|
+
*
|
|
8
|
+
* Tether.init({
|
|
9
|
+
* ...window.TETHER_CONFIG,
|
|
10
|
+
* ...barbaPreset({
|
|
11
|
+
* lenis: () => myLenis, // resized after async renders
|
|
12
|
+
* lockScroll: (drawer) => myLock.lock(drawer), // when the cart opens
|
|
13
|
+
* unlockScroll: () => myLock.unlock(), // when the cart closes
|
|
14
|
+
* onValueChange: (el, previous) => {}, // e.g. a text scramble
|
|
15
|
+
* }),
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* // once per page container, e.g. in Barba's beforeEnter AND once():
|
|
19
|
+
* Tether.mount(container);
|
|
20
|
+
* // when leaving a page:
|
|
21
|
+
* Tether.unmount();
|
|
22
|
+
*/
|
|
23
|
+
import type { TetherConfig } from '../config.js';
|
|
24
|
+
/** `gsap`, `lenis` and `scrollTrigger` are getters, read each time they are used, so an instance made later is found. */
|
|
25
|
+
interface BarbaPresetOptions {
|
|
26
|
+
/** Default `window.gsap`. */
|
|
27
|
+
gsap?: () => unknown;
|
|
28
|
+
/** Resized after async renders. */
|
|
29
|
+
lenis?: (() => unknown) | null;
|
|
30
|
+
/** Default `window.ScrollTrigger`, refreshed after async renders. */
|
|
31
|
+
scrollTrigger?: () => unknown;
|
|
32
|
+
/** When the cart opens. */
|
|
33
|
+
lockScroll?: ((drawer: HTMLElement) => void) | null;
|
|
34
|
+
/** When the cart closes. */
|
|
35
|
+
unlockScroll?: (() => void) | null;
|
|
36
|
+
/** After a cart line animated in or out. */
|
|
37
|
+
onResize?: (() => void) | null;
|
|
38
|
+
onValueChange?: TetherConfig['onValueChange'];
|
|
39
|
+
/** Animate cart lines in and out (default true). */
|
|
40
|
+
animateLines?: boolean;
|
|
41
|
+
/** Seconds. */
|
|
42
|
+
lineDuration?: number;
|
|
43
|
+
}
|
|
44
|
+
/** The hooks the preset always sets, and `onValueChange` as passed (`null` when it isn't). */
|
|
45
|
+
type BarbaPresetConfig = {
|
|
46
|
+
autoMount: false;
|
|
47
|
+
} & {
|
|
48
|
+
[Hook in 'onLayoutChange' | 'onCartOpen' | 'onCartClose' | 'onLineEnter' | 'onLineLeave']: NonNullable<TetherConfig[Hook]>;
|
|
49
|
+
} & Pick<TetherConfig, 'onValueChange'>;
|
|
50
|
+
export type { BarbaPresetOptions, BarbaPresetConfig };
|
|
51
|
+
/**
|
|
52
|
+
* Hooks for sites with page transitions, smooth scroll and GSAP: spread into `Tether.init()`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function barbaPreset(options?: BarbaPresetOptions): BarbaPresetConfig;
|
|
55
|
+
/** @alias `barbaPreset`, for `import barbaPreset from '@occluze/tether/presets/barba'`. */
|
|
56
|
+
export default barbaPreset;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Product } from './fragments.js';
|
|
2
|
+
import type { PlanInGroup } from './selling-plans.js';
|
|
3
|
+
/** The product scope as its renders see it. */
|
|
4
|
+
export interface RenderScope {
|
|
5
|
+
readonly root: HTMLElement;
|
|
6
|
+
readonly product: Product;
|
|
7
|
+
readonly plans: PlanInGroup[];
|
|
8
|
+
/** Matches in this scope, the root included. */
|
|
9
|
+
$: (selector: string) => HTMLElement[];
|
|
10
|
+
/** The product's option name for one written in the markup. */
|
|
11
|
+
optName: (authored: string | null) => string;
|
|
12
|
+
}
|
|
13
|
+
export declare const isSelect: (el: Element) => el is HTMLSelectElement;
|
|
14
|
+
/** @returns The `<select>` elements in the scope that match `selector`. */
|
|
15
|
+
export declare const selectsIn: (scope: RenderScope, selector: string) => HTMLSelectElement[];
|
|
16
|
+
/** Writes what depends on the product alone: its binds, option and plan lists and the selects' options. */
|
|
17
|
+
export declare function writeProduct(scope: RenderScope): void;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Product } from './fragments.js';
|
|
2
|
+
import type { PageInfo } from './loader.js';
|
|
3
|
+
/** A page of a GraphQL connection of products. */
|
|
4
|
+
export interface ProductConnection {
|
|
5
|
+
nodes: Product[];
|
|
6
|
+
pageInfo: PageInfo;
|
|
7
|
+
}
|
|
8
|
+
/** A Storefront API `MoneyV2`. */
|
|
9
|
+
export declare const MONEY: {
|
|
10
|
+
readonly amount: "string";
|
|
11
|
+
readonly currencyCode: "string";
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* A product's id, handle and title, and every list and price a render walks without a fallback: images, options,
|
|
15
|
+
* variants (each with an id, a price and its options) and the price range. Text fields are written as text, and the
|
|
16
|
+
* selling plan lists are read with a fallback, so they need no check.
|
|
17
|
+
*/
|
|
18
|
+
export declare const PRODUCT: {
|
|
19
|
+
readonly id: "string";
|
|
20
|
+
readonly handle: "string";
|
|
21
|
+
readonly title: "string";
|
|
22
|
+
readonly options: readonly ["object"];
|
|
23
|
+
readonly images: {
|
|
24
|
+
readonly nodes: readonly ["object"];
|
|
25
|
+
};
|
|
26
|
+
readonly priceRange: {
|
|
27
|
+
readonly minVariantPrice: {
|
|
28
|
+
readonly amount: "string";
|
|
29
|
+
readonly currencyCode: "string";
|
|
30
|
+
};
|
|
31
|
+
readonly maxVariantPrice: {
|
|
32
|
+
readonly amount: "string";
|
|
33
|
+
readonly currencyCode: "string";
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
readonly variants: {
|
|
37
|
+
readonly nodes: readonly [{
|
|
38
|
+
readonly id: "string";
|
|
39
|
+
readonly price: {
|
|
40
|
+
readonly amount: "string";
|
|
41
|
+
readonly currencyCode: "string";
|
|
42
|
+
};
|
|
43
|
+
readonly selectedOptions: readonly ["object"];
|
|
44
|
+
}];
|
|
45
|
+
};
|
|
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
|
+
/** True for a value with the structure of `PRODUCT` and a non-empty id and handle. */
|
|
83
|
+
export declare const isProductShape: (value: unknown) => value is Product;
|
|
84
|
+
/**
|
|
85
|
+
* A node a lookup by gid answers: a product, or a node of another type, for which `... on Product` selects no field
|
|
86
|
+
* (no `id`).
|
|
87
|
+
*/
|
|
88
|
+
export declare const PRODUCT_NODE: (node: unknown) => boolean;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { Money } from './shopify-values.js';
|
|
2
|
+
import type { Product, ProductVariant } from './fragments.js';
|
|
3
|
+
import type { PlanInGroup } from './selling-plans.js';
|
|
4
|
+
/** Option name → chosen value. */
|
|
5
|
+
export type Selection = Record<string, string>;
|
|
6
|
+
/**
|
|
7
|
+
* How the visitor wants to buy. Buying once keeps the plan offered next to the one-time price (the subscription
|
|
8
|
+
* binds `subscription-price` and `plan-name` show it, and subscribing switches to it); `null` for a product without
|
|
9
|
+
* plans.
|
|
10
|
+
*/
|
|
11
|
+
export type Purchase = {
|
|
12
|
+
kind: 'one-time';
|
|
13
|
+
offeredPlanId: string | null;
|
|
14
|
+
} | {
|
|
15
|
+
kind: 'subscription';
|
|
16
|
+
planId: string;
|
|
17
|
+
};
|
|
18
|
+
/** How the line is bought: on a plan only when the visitor subscribes and the variant is on that plan. */
|
|
19
|
+
type LinePurchase = {
|
|
20
|
+
kind: 'one-time';
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'subscription';
|
|
23
|
+
planId: string;
|
|
24
|
+
};
|
|
25
|
+
/** What the visitor chose, before it is checked against the product. */
|
|
26
|
+
interface ProductChoice {
|
|
27
|
+
selected: Selection;
|
|
28
|
+
purchase: Purchase;
|
|
29
|
+
quantity: number;
|
|
30
|
+
}
|
|
31
|
+
export type ShowCondition = 'in-stock' | 'out-of-stock' | 'backorder' | 'on-sale' | 'not-on-sale' | 'has-variants' | 'single-variant' | 'low-stock' | 'plenty-in-stock' | 'subscription-available' | 'subscription-unavailable' | 'subscription-only' | 'one-time-available' | 'subscription-selected' | 'one-time-selected' | 'has-savings';
|
|
32
|
+
export interface ProductView {
|
|
33
|
+
variant: ProductVariant;
|
|
34
|
+
/** The selection, matching `variant`. */
|
|
35
|
+
selected: Selection;
|
|
36
|
+
/** The choice, made valid for the product and `variant`. */
|
|
37
|
+
purchase: Purchase;
|
|
38
|
+
/** The purchase's plan, offered or chosen. */
|
|
39
|
+
plan: PlanInGroup | null;
|
|
40
|
+
/** How the line is bought. */
|
|
41
|
+
line: LinePurchase;
|
|
42
|
+
/** The variant is on at least one plan. */
|
|
43
|
+
subscriptionAvailable: boolean;
|
|
44
|
+
quantity: number;
|
|
45
|
+
/** What one item costs as bought. */
|
|
46
|
+
price: Money;
|
|
47
|
+
/** Only when on sale. */
|
|
48
|
+
compareAtPrice: Money | null;
|
|
49
|
+
/** What `plan` saves on the one-time price. */
|
|
50
|
+
savings: {
|
|
51
|
+
amount: Money | null;
|
|
52
|
+
percentage: number;
|
|
53
|
+
};
|
|
54
|
+
show: Record<ShowCondition, boolean>;
|
|
55
|
+
}
|
|
56
|
+
/** How the caller writes values as text. */
|
|
57
|
+
export interface Formatters {
|
|
58
|
+
money: (money: Money | null) => string;
|
|
59
|
+
percent: (percentage: number) => string;
|
|
60
|
+
}
|
|
61
|
+
/** What a bind writes; `null` and `undefined` clear it. */
|
|
62
|
+
type BindText = string | number | null | undefined;
|
|
63
|
+
export declare const selectionOf: (variant: ProductVariant) => Selection;
|
|
64
|
+
/**
|
|
65
|
+
* @param name An option name.
|
|
66
|
+
* @returns True when a variant for sale has this value and the other selected values.
|
|
67
|
+
*/
|
|
68
|
+
export declare function isValueAvailable(product: Product, selected: Selection, name: string, value: string): boolean;
|
|
69
|
+
/** @returns The plan subscribed on, or offered while buying once. */
|
|
70
|
+
export declare const purchasePlanId: (purchase: Purchase) => string | null;
|
|
71
|
+
/** @returns On the plan when subscribing and the variant is on it, else once. */
|
|
72
|
+
export declare function linePurchase(purchase: Purchase, variant: ProductVariant | null): LinePurchase;
|
|
73
|
+
/**
|
|
74
|
+
* The purchase the visitor wants, made valid for the product and variant: one-time without plans, a subscription when
|
|
75
|
+
* the product requires one, and a plan the variant is on when it is on any (else a plan of the product, for the binds
|
|
76
|
+
* to offer).
|
|
77
|
+
*
|
|
78
|
+
* @param kind The way of buying the visitor asked for.
|
|
79
|
+
* @param preferredPlanId The plan to keep when it is the product's: the visitor's last one.
|
|
80
|
+
*/
|
|
81
|
+
export declare function normalisePurchase(product: Product, variant: ProductVariant | null, kind: Purchase['kind'], preferredPlanId: string | null): Purchase;
|
|
82
|
+
interface InitialChoiceOptions {
|
|
83
|
+
/** A variant id or gid (`?variant=`); the first variant for sale without. */
|
|
84
|
+
variant?: string | null | undefined;
|
|
85
|
+
/** A plan to subscribe on (`?selling_plan=`). */
|
|
86
|
+
sellingPlan?: string | null | undefined;
|
|
87
|
+
/** The plan offered first, by id, name or option value. */
|
|
88
|
+
defaultPlan?: string | null | undefined;
|
|
89
|
+
/** `subscription` subscribes; anything else buys once. */
|
|
90
|
+
defaultPurchase?: string | null | undefined;
|
|
91
|
+
}
|
|
92
|
+
/** What a product starts with before the visitor chooses anything. */
|
|
93
|
+
export declare function initialChoice(product: Product, { variant, sellingPlan, defaultPlan, defaultPurchase }: InitialChoiceOptions): Omit<ProductChoice, 'quantity'>;
|
|
94
|
+
/**
|
|
95
|
+
* The view for the visitor's choice. A selection no variant has falls back to the first variant.
|
|
96
|
+
*
|
|
97
|
+
* @param lowStock `low-stock` at this many or fewer.
|
|
98
|
+
* @returns `null` for a product without variants.
|
|
99
|
+
*/
|
|
100
|
+
export declare function productView(product: Product, choice: ProductChoice, lowStock: number): ProductView | null;
|
|
101
|
+
/** The `tether-bind` values that follow the variant and purchase. Thunks, so only the binds on the page are computed. */
|
|
102
|
+
export declare function variantBindTexts(view: ProductView, format: Formatters): Map<string, () => BindText>;
|
|
103
|
+
/**
|
|
104
|
+
* The `tether-plan-bind` values of one plan in a plan list, for the variant.
|
|
105
|
+
*
|
|
106
|
+
* @param planId The list item's `tether-plan-value`.
|
|
107
|
+
* @param plan The product's plan with that id.
|
|
108
|
+
*/
|
|
109
|
+
export declare function planBindTexts(variant: ProductVariant, planId: string, plan: PlanInGroup | undefined, format: Formatters): Map<string, () => BindText>;
|
|
110
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Product, ProductVariant } from './fragments.js';
|
|
2
|
+
import type { ShopifyCart } from './cart/store.js';
|
|
3
|
+
import type { PlanInGroup } from './selling-plans.js';
|
|
4
|
+
import type { Purchase, Selection } from './product-state.js';
|
|
5
|
+
/** What a scope adds to the cart. */
|
|
6
|
+
interface CartLineInput {
|
|
7
|
+
merchandiseId: string;
|
|
8
|
+
quantity: number;
|
|
9
|
+
sellingPlanId?: string;
|
|
10
|
+
attributes?: {
|
|
11
|
+
key: string;
|
|
12
|
+
value: string;
|
|
13
|
+
}[];
|
|
14
|
+
}
|
|
15
|
+
export declare const scopes: WeakMap<Element, ProductScope>;
|
|
16
|
+
export declare function rememberOptionNames(products: readonly Pick<Product, 'handle' | 'options'>[]): void;
|
|
17
|
+
export declare class ProductScope {
|
|
18
|
+
readonly root: HTMLElement;
|
|
19
|
+
product: Product;
|
|
20
|
+
plans: PlanInGroup[];
|
|
21
|
+
selected: Selection;
|
|
22
|
+
/** How the visitor buys; `setPurchase` and `selectPlan` change it. */
|
|
23
|
+
purchase: Purchase;
|
|
24
|
+
variant: ProductVariant | null;
|
|
25
|
+
quantity: number;
|
|
26
|
+
constructor(root: HTMLElement, product: Product);
|
|
27
|
+
/** New data for the same product (a country switch). Keeps the visitor's choice. */
|
|
28
|
+
update(product: Product): void;
|
|
29
|
+
/** @returns Matches in this scope, including the root itself (a card link with tether-bind="link"). */
|
|
30
|
+
$(selector: string): HTMLElement[];
|
|
31
|
+
/**
|
|
32
|
+
* @param authored An option name in the markup.
|
|
33
|
+
* @returns The product's option of that name, or at that position in the build's language.
|
|
34
|
+
*/
|
|
35
|
+
optName(authored: string | null): string;
|
|
36
|
+
get plan(): PlanInGroup | null;
|
|
37
|
+
/** True when the current variant can be bought on a plan. */
|
|
38
|
+
get subscriptionAvailable(): boolean;
|
|
39
|
+
/** True when the line is bought on a plan: subscribing, and the variant is on the plan. */
|
|
40
|
+
get isSubscription(): boolean;
|
|
41
|
+
/** @returns What would be added to the cart right now. */
|
|
42
|
+
getLine(): CartLineInput | null;
|
|
43
|
+
/** @returns `tether-line-attributes` and the filled `tether-line-attribute` fields. */
|
|
44
|
+
collectAttributes(): {
|
|
45
|
+
key: string;
|
|
46
|
+
value: string;
|
|
47
|
+
}[];
|
|
48
|
+
/**
|
|
49
|
+
* Selects an option value. A combination no variant has moves to the closest variant with the value: the most other
|
|
50
|
+
* choices kept, then one for sale.
|
|
51
|
+
*/
|
|
52
|
+
select(name: string, value: string): void;
|
|
53
|
+
/** @param id A variant gid or numeric id. */
|
|
54
|
+
selectVariant(id: string): void;
|
|
55
|
+
setPurchase(kind: Purchase['kind']): void;
|
|
56
|
+
/** @param ref A plan id, numeric id, name or option value. */
|
|
57
|
+
selectPlan(ref: string | null): void;
|
|
58
|
+
setQuantity(quantity: number | string): void;
|
|
59
|
+
/** @returns The cart after adding; `null` when the variant can't be added. */
|
|
60
|
+
addToCart(): Promise<ShopifyCart | null>;
|
|
61
|
+
/** Learns the markup's option names when they are the product's, then writes the product. */
|
|
62
|
+
renderProduct(): void;
|
|
63
|
+
/** Derives the view of the current choice, keeps its variant, selection and purchase, and writes it. */
|
|
64
|
+
renderVariant(): void;
|
|
65
|
+
}
|
|
66
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** @returns True once the repeater's template has been captured (it may be empty after that). */
|
|
2
|
+
export declare const hasTemplate: (container: Element) => boolean;
|
|
3
|
+
/** Rebuilds the list on every render. Fine for images, tags, options. */
|
|
4
|
+
export declare function repeat<Item>(container: Element, items: readonly Item[], render: (node: HTMLElement, item: Item, index: number) => void): void;
|
|
5
|
+
interface KeyedHooks {
|
|
6
|
+
/** Runs on a node inserted for a new item. */
|
|
7
|
+
onEnter?: ((node: HTMLElement) => void) | null;
|
|
8
|
+
/** Runs on a node whose item is gone; `done()` removes it. */
|
|
9
|
+
onLeave?: ((node: HTMLElement, done: () => void) => void) | null;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Keyed repeater: keeps existing nodes, inserts new ones, removes old ones. Used for cart lines, so values can
|
|
13
|
+
* animate and lines can slide in and out.
|
|
14
|
+
*/
|
|
15
|
+
export declare function repeatKeyed<Item>(container: Element, items: readonly Item[], keyOf: (item: Item, index: number) => string | number, render: (node: HTMLElement, item: Item, index: number, isNew: boolean) => void, { onEnter, onLeave }?: KeyedHooks): void;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Money } from './shopify-values.js';
|
|
2
|
+
interface SearchImage {
|
|
3
|
+
url: string;
|
|
4
|
+
altText: string | null;
|
|
5
|
+
}
|
|
6
|
+
interface SearchProduct {
|
|
7
|
+
id: string;
|
|
8
|
+
handle: string;
|
|
9
|
+
title: string;
|
|
10
|
+
availableForSale: boolean;
|
|
11
|
+
featuredImage: SearchImage | null;
|
|
12
|
+
priceRange: {
|
|
13
|
+
minVariantPrice: Money;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
interface SearchCollection {
|
|
17
|
+
handle: string;
|
|
18
|
+
title: string;
|
|
19
|
+
image: SearchImage | null;
|
|
20
|
+
}
|
|
21
|
+
interface SearchQuery {
|
|
22
|
+
text: string;
|
|
23
|
+
}
|
|
24
|
+
export interface SearchResults {
|
|
25
|
+
products: SearchProduct[];
|
|
26
|
+
collections: SearchCollection[];
|
|
27
|
+
queries: SearchQuery[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Sets up every `[tether-search]` in `root` (and `root` itself) once.
|
|
31
|
+
*/
|
|
32
|
+
export declare function mountSearch(root?: ParentNode & Partial<Pick<Element, 'matches'>>): void;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Money } from './shopify-values.js';
|
|
2
|
+
import type { SellingPlan, SellingPlanGroup, SellingPlanAllocation } from './fragments.js';
|
|
3
|
+
/** A plan with the group it belongs to. */
|
|
4
|
+
export type PlanInGroup = SellingPlan & {
|
|
5
|
+
group: SellingPlanGroup;
|
|
6
|
+
};
|
|
7
|
+
export interface ProductWithPlans {
|
|
8
|
+
sellingPlanGroups?: {
|
|
9
|
+
nodes: SellingPlanGroup[];
|
|
10
|
+
} | null;
|
|
11
|
+
}
|
|
12
|
+
/** A variant as far as plans go. A cart line's variant has no allocations. */
|
|
13
|
+
export interface VariantWithPlans {
|
|
14
|
+
price: Money;
|
|
15
|
+
sellingPlanAllocations?: {
|
|
16
|
+
nodes: SellingPlanAllocation[];
|
|
17
|
+
} | null;
|
|
18
|
+
}
|
|
19
|
+
export type PlanAdjustment = {
|
|
20
|
+
type: 'percentage';
|
|
21
|
+
value: number;
|
|
22
|
+
} | {
|
|
23
|
+
type: 'amount';
|
|
24
|
+
value: Money;
|
|
25
|
+
} | {
|
|
26
|
+
type: 'price';
|
|
27
|
+
value: Money;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* @param value A gid, a numeric id, or anything else.
|
|
31
|
+
* @param type The Shopify type, e.g. `ProductVariant`.
|
|
32
|
+
* @returns The gid of a numeric id; a gid or other value as written; `null` when empty.
|
|
33
|
+
*/
|
|
34
|
+
export declare function toGid(value: unknown, type: string): string | null;
|
|
35
|
+
export declare const GID: {
|
|
36
|
+
product: (value: unknown) => string | null;
|
|
37
|
+
variant: (value: unknown) => string | null;
|
|
38
|
+
sellingPlan: (value: unknown) => string | null;
|
|
39
|
+
};
|
|
40
|
+
/** @returns All plans of the product, flattened. */
|
|
41
|
+
export declare function allPlans(product: ProductWithPlans | null | undefined): PlanInGroup[];
|
|
42
|
+
export declare function hasPlans(product: ProductWithPlans | null | undefined): boolean;
|
|
43
|
+
/** @returns The variant's allocation on the plan; `null` when the variant isn't in it. */
|
|
44
|
+
export declare function allocationFor(variant: VariantWithPlans | null | undefined, planId: string | null | undefined): SellingPlanAllocation | null;
|
|
45
|
+
/** @returns The plans this variant can be bought on. */
|
|
46
|
+
export declare function plansForVariant(product: ProductWithPlans | null | undefined, variant: VariantWithPlans | null | undefined): PlanInGroup[];
|
|
47
|
+
/** @returns The price per delivery on the plan; the one-time price when the variant isn't on it. */
|
|
48
|
+
export declare function planPrice(variant: VariantWithPlans | null | undefined, planId: string | null | undefined): Money | null;
|
|
49
|
+
/** @returns What the customer pays at checkout on the plan (prepaid plans charge more up front). */
|
|
50
|
+
export declare function planCheckoutCharge(variant: VariantWithPlans | null | undefined, planId: string | null | undefined): Money | null;
|
|
51
|
+
/** @returns What the plan saves on the one-time price; no amount and 0% when it saves nothing. */
|
|
52
|
+
export declare function planSavings(variant: VariantWithPlans | null | undefined, planId: string | null | undefined): {
|
|
53
|
+
amount: Money | null;
|
|
54
|
+
percentage: number;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* @returns The plan's own discount, whatever the variant: a percentage, a fixed amount off or a fixed price.
|
|
58
|
+
*/
|
|
59
|
+
export declare function planAdjustment(plan: Pick<SellingPlan, 'priceAdjustments'> | null | undefined): PlanAdjustment | null;
|
|
60
|
+
/**
|
|
61
|
+
* Finds a plan by id, numeric id, name or option value (case-insensitive), so Webflow editors can write
|
|
62
|
+
* `tether-default-plan="Every month"`.
|
|
63
|
+
*/
|
|
64
|
+
export declare function findPlan(product: ProductWithPlans | null | undefined, ref: string | null | undefined): PlanInGroup | null;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { withContext, TetherError } from './client.js';
|
|
2
|
+
import * as plans from './selling-plans.js';
|
|
3
|
+
import { imageUrl, formatPercent } from './dom.js';
|
|
4
|
+
import { initialState } from './initial.js';
|
|
5
|
+
import { STORE_ENV_NAMES, formatMoney, productKey } from './shopify-values.js';
|
|
6
|
+
import type { TetherConfig, TetherOptions } from './config.js';
|
|
7
|
+
import type { Product } from './fragments.js';
|
|
8
|
+
import type { Money } from './shopify-values.js';
|
|
9
|
+
import type { InitialOptions, InitialState } from './initial.js';
|
|
10
|
+
import type { JsonLdOptions } from './storefront/json-ld.js';
|
|
11
|
+
export { imageUrl, initialState, formatPercent, formatMoney, productKey };
|
|
12
|
+
export { TetherError, plans, withContext };
|
|
13
|
+
export type { StorefrontOptions, HydrateOptions };
|
|
14
|
+
export type { Money } from './shopify-values.js';
|
|
15
|
+
export type { Product as ShopifyProduct, ProductVariant as ShopifyVariant } from './fragments.js';
|
|
16
|
+
export type { ShopifyCart, ShopifyCartLine } from './cart/store.js';
|
|
17
|
+
export type { Collection as ShopifyCollection, ProductQuery } from './loader.js';
|
|
18
|
+
export type { InitialOptions, InitialState } from './initial.js';
|
|
19
|
+
export type { ImageSize } from './images.js';
|
|
20
|
+
export type { JsonLdOptions } from './storefront/json-ld.js';
|
|
21
|
+
/** What `createStorefront()` returns. */
|
|
22
|
+
export type Storefront = ReturnType<typeof createStorefront>;
|
|
23
|
+
/** The options only a storefront has. */
|
|
24
|
+
interface ServerOptions {
|
|
25
|
+
/** Replaces the global `fetch` (tests, caching). */
|
|
26
|
+
fetch?: typeof fetch;
|
|
27
|
+
/** Products per request for `allProducts()` (default 25). */
|
|
28
|
+
pageSize?: number;
|
|
29
|
+
/** The site's address, for product URLs in `jsonLd()` without `url`. */
|
|
30
|
+
siteUrl?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The config options, or an `import.meta.env` spread into them: its `PUBLIC_SHOPIFY_*` names give the domain and
|
|
34
|
+
* token, its other keys are ignored.
|
|
35
|
+
*/
|
|
36
|
+
type StorefrontOptions = TetherOptions & ServerOptions & StoreEnv;
|
|
37
|
+
/** The environment names that give the domain and the token. */
|
|
38
|
+
type StoreEnv = Partial<Record<(typeof STORE_ENV_NAMES)['domain' | 'token'][number], string>>;
|
|
39
|
+
type ServerConfig = TetherConfig & ServerOptions;
|
|
40
|
+
interface HydrateOptions {
|
|
41
|
+
card?: boolean;
|
|
42
|
+
images?: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* @returns `productPath` `/products` → `/products/<handle>`; templates with `{handle}` and `{id}` work too. `null` when
|
|
46
|
+
* the path needs a handle or an id that is empty.
|
|
47
|
+
*/
|
|
48
|
+
export declare function productUrl(handle: string, { productPath, id }?: {
|
|
49
|
+
productPath?: string;
|
|
50
|
+
id?: string;
|
|
51
|
+
}): string | null;
|
|
52
|
+
/**
|
|
53
|
+
* A storefront: the store's products and collections for the server, and the tags that hand them to the page.
|
|
54
|
+
*
|
|
55
|
+
* @throws {TetherError} `NOT_CONFIGURED` without a domain and a token.
|
|
56
|
+
*/
|
|
57
|
+
export declare function createStorefront(options?: StorefrontOptions): {
|
|
58
|
+
hydrate: (products: Product | null | undefined | (Product | null | undefined)[], { card, images }?: HydrateOptions) => string;
|
|
59
|
+
formatMoney: (money: Money | null | undefined, locale?: string | undefined) => string;
|
|
60
|
+
formatPercent: (percentage: number, locale?: string | undefined) => string;
|
|
61
|
+
imageUrl: typeof imageUrl;
|
|
62
|
+
jsonLd: (product: Product | null | undefined, jsonLdOptions?: JsonLdOptions) => string;
|
|
63
|
+
jsonLdData: (product: Product | null | undefined, jsonLdOptions?: JsonLdOptions) => Record<string, unknown> | null;
|
|
64
|
+
initialState: {
|
|
65
|
+
(product: Product, initialOptions?: InitialOptions): InitialState;
|
|
66
|
+
(product: Product | null | undefined, initialOptions?: InitialOptions): InitialState | null;
|
|
67
|
+
};
|
|
68
|
+
productUrl: (handle: string, urlOptions?: {
|
|
69
|
+
productPath?: string;
|
|
70
|
+
id?: string;
|
|
71
|
+
}) => string | null;
|
|
72
|
+
plans: typeof plans;
|
|
73
|
+
getProduct: (raw: string | number | null | undefined) => Promise<Product | null>;
|
|
74
|
+
getProducts: (options?: import("./storefront/catalog.js").CatalogQuery) => Promise<import("./loader.js").ProductPage>;
|
|
75
|
+
allProducts: (options?: Omit<import("./storefront/catalog.js").CatalogQuery, "first" | "after">) => Promise<Product[]>;
|
|
76
|
+
getCollection: (handle: string, options?: Omit<import("./storefront/catalog.js").CatalogQuery, "collection">) => Promise<(import("./loader.js").Collection & {
|
|
77
|
+
products: Product[];
|
|
78
|
+
pageInfo: import("./loader.js").PageInfo;
|
|
79
|
+
}) | null>;
|
|
80
|
+
allCollections: () => Promise<import("./loader.js").Collection[]>;
|
|
81
|
+
getRecommendations: (product: string | number | {
|
|
82
|
+
id: string;
|
|
83
|
+
} | null | undefined, intent?: "RELATED" | "COMPLEMENTARY") => Promise<Product[]>;
|
|
84
|
+
config: ServerConfig;
|
|
85
|
+
query: <T>(query: string, variables?: Record<string, unknown>, requestOptions?: {
|
|
86
|
+
context?: boolean;
|
|
87
|
+
}) => Promise<T>;
|
|
88
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversions of Shopify values that the browser script and the server helpers (`src/server.ts`, `src/astro.ts`)
|
|
3
|
+
* share, so a server-rendered page and the script that takes it over agree. Pure: no config, no DOM.
|
|
4
|
+
*/
|
|
5
|
+
/** A Storefront API `MoneyV2`. */
|
|
6
|
+
export interface Money {
|
|
7
|
+
amount: string;
|
|
8
|
+
currencyCode: string;
|
|
9
|
+
}
|
|
10
|
+
/** The `.env` names a store's domain and public Storefront token are read from, first match wins. */
|
|
11
|
+
export declare const STORE_ENV_NAMES: {
|
|
12
|
+
readonly domain: readonly ["PUBLIC_SHOPIFY_DOMAIN", "PUBLIC_SHOPIFY_STORE_DOMAIN", "SHOPIFY_DOMAIN"];
|
|
13
|
+
readonly token: readonly ["PUBLIC_SHOPIFY_STOREFRONT_TOKEN", "PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN", "SHOPIFY_STOREFRONT_TOKEN"];
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* True for an absolute https URL. Links and redirects that come from Shopify (checkout, status pages,
|
|
17
|
+
* tracking) are only used when this holds.
|
|
18
|
+
*/
|
|
19
|
+
export declare function isHttpsUrl(url: unknown): url is string;
|
|
20
|
+
/**
|
|
21
|
+
* True for a token Shopify issues as a secret (`shpat_` Admin, `shpss_` shared secret, `shpca_` client credentials,
|
|
22
|
+
* `shppa_` private app, `shpua_` user). The public Storefront token has no such prefix. A secret token must never
|
|
23
|
+
* reach a page.
|
|
24
|
+
*/
|
|
25
|
+
export declare function isSecretShopifyToken(token: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Money as text in `locale`, e.g. `{ amount: '30.0', currencyCode: 'EUR' }` in `nl-NL` → `€ 30,00`.
|
|
28
|
+
*
|
|
29
|
+
* @param locale An `Intl` locale; the runtime's own when absent.
|
|
30
|
+
* @returns `''` without money or with an amount that isn't a number.
|
|
31
|
+
*/
|
|
32
|
+
export declare function formatMoney(money: Money | null | undefined, locale: string | undefined): string;
|
|
33
|
+
/**
|
|
34
|
+
* A product page's path. `productPath` is a folder (`/product` → `/product/<handle>`) or a template with `{handle}`
|
|
35
|
+
* and `{id}` (the numeric product id), e.g. `/product?handle={handle}`.
|
|
36
|
+
*
|
|
37
|
+
* @param id A product gid or numeric id.
|
|
38
|
+
* @returns `null` when the path needs a handle or an id the product lacks: no link beats a wrong one.
|
|
39
|
+
*/
|
|
40
|
+
export declare function productUrl(productPath: string, handle: string | null | undefined, id?: string | null): string | null;
|
|
41
|
+
/**
|
|
42
|
+
* The key Tether loads a product by: a handle, or a product gid.
|
|
43
|
+
*
|
|
44
|
+
* @param raw A handle, a numeric id, a gid or a product URL (`…/products/<handle>`).
|
|
45
|
+
*/
|
|
46
|
+
export declare function productKey(raw: string | number | null | undefined): string | null;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
interface ProductKeySource {
|
|
2
|
+
/** The product to load; `null` when the attribute or the page URL has none. */
|
|
3
|
+
key: string | null;
|
|
4
|
+
/** The key comes from the page URL (`url:…`). */
|
|
5
|
+
fromUrl: boolean;
|
|
6
|
+
/** The attribute's value as written. */
|
|
7
|
+
raw: string;
|
|
8
|
+
}
|
|
9
|
+
type ScopeStatus = 'loading' | 'ready' | 'error' | 'not-found';
|
|
10
|
+
/**
|
|
11
|
+
* Reads a `tether-product` value:
|
|
12
|
+
* - `coffee-box`: a handle, numeric id, gid or product URL;
|
|
13
|
+
* - `url:handle`: `?handle=` from the page URL (any parameter: `url:p` reads `?p=`);
|
|
14
|
+
* - `url:path`: the last segment of the page path (`/shop/coffee-box` → `coffee-box`).
|
|
15
|
+
*
|
|
16
|
+
* @param name The attribute, without prefix.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveProductKey(el: Element, location?: Pick<Location, 'pathname' | 'search'>, name?: string): ProductKeySource;
|
|
19
|
+
/** The values of `tether-show` that follow the scope's state. */
|
|
20
|
+
export declare const STATUS_KEYS: readonly ScopeStatus[];
|
|
21
|
+
/** @returns True for a `TetherError` with code `NOT_FOUND`. */
|
|
22
|
+
export declare const isNotFound: (error: unknown) => boolean;
|
|
23
|
+
/** @returns The selector of every scope that owns its state elements; the nearest one wins. */
|
|
24
|
+
export declare const boundary: () => string;
|
|
25
|
+
/** @returns True when `el` belongs to the scope `root`, not to a scope nested in it. */
|
|
26
|
+
export declare const ownedBy: (el: Element, root: Element) => boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Sets `tether-state` (loading | ready | error) and `tether-error` (not-found or an error code) on `root`, toggles
|
|
29
|
+
* `tether-show="loading|ready|error|not-found"` inside it, and disables its add-to-cart buttons when there's no
|
|
30
|
+
* product.
|
|
31
|
+
*/
|
|
32
|
+
export declare function setScopeStatus(root: Element, status: ScopeStatus, error?: unknown): void;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The browser's `localStorage` and `sessionStorage`, which may be blocked: accessing them throws in private mode, in
|
|
3
|
+
* sandboxed frames and where the visitor blocks site data, and writing throws when they are full. Tether then keeps
|
|
4
|
+
* nothing between pages: a read finds nothing, and a write or removal does nothing. Each call catches on its own, so a
|
|
5
|
+
* blocked area never stops a call on the other.
|
|
6
|
+
*/
|
|
7
|
+
type StorageArea = 'localStorage' | 'sessionStorage';
|
|
8
|
+
/** @returns `null` when nothing is stored under `key`, or the storage is blocked. */
|
|
9
|
+
export declare function getStored(key: string, area?: StorageArea): string | null;
|
|
10
|
+
export declare function setStored(key: string, value: string, area?: StorageArea): void;
|
|
11
|
+
export declare function removeStored(key: string, area?: StorageArea): void;
|
|
12
|
+
export {};
|