@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,40 @@
|
|
|
1
|
+
import type { AccountConfig, AnalyticsConfig, MarketsConfig, MetafieldIdentifier, MetafieldRef } from './config.js';
|
|
2
|
+
/** Warns that an option was dropped. */
|
|
3
|
+
type Invalid = (name: string, value: unknown) => void;
|
|
4
|
+
/** A host name, without protocol or path: what `domainOption` keeps of the `domain` option. */
|
|
5
|
+
export type ShopDomain = string & {
|
|
6
|
+
readonly __brand: 'ShopDomain';
|
|
7
|
+
};
|
|
8
|
+
/** Every source `markets.detect` reads. */
|
|
9
|
+
export declare const MARKET_SOURCES: readonly ('saved' | 'server' | 'webflow')[];
|
|
10
|
+
/**
|
|
11
|
+
* @returns The store's domain without protocol or path (`https://shop.example/x` → `shop.example`), `''` for anything
|
|
12
|
+
* that isn't a host name.
|
|
13
|
+
*/
|
|
14
|
+
export declare function domainOption(value: unknown, invalid: Invalid): ShopDomain | '';
|
|
15
|
+
/**
|
|
16
|
+
* The folder of the optional parts. It must be https or on this site, which keeps parts off plain http (mixed content,
|
|
17
|
+
* rewritable on the way); it doesn't vouch for the host, which the site chose.
|
|
18
|
+
*
|
|
19
|
+
* @returns The folder as written, `null` for none or one elsewhere (the parts then load beside the core).
|
|
20
|
+
*/
|
|
21
|
+
export declare function partsUrlOption(value: unknown, invalid: Invalid): string | null;
|
|
22
|
+
/**
|
|
23
|
+
* The origins a site lets description iframes load from. Each one is trusted to show only what the site expects in a
|
|
24
|
+
* description, so only a bare https origin is taken: a path would suggest a narrower trust than is given.
|
|
25
|
+
*
|
|
26
|
+
* @returns The valid origins; each other entry is skipped with a warning.
|
|
27
|
+
*/
|
|
28
|
+
export declare function embedOriginsOption(value: unknown, invalid: Invalid): string[];
|
|
29
|
+
/** @returns The identifier of `'namespace.key'` or `{ namespace, key }`, when both parts are valid identifiers. */
|
|
30
|
+
export declare function toMetafieldIdentifier(ref: unknown): MetafieldIdentifier | null;
|
|
31
|
+
/** @returns The refs that name a valid identifier, as written; each other one is skipped with a warning. */
|
|
32
|
+
export declare function metafieldsOption(value: unknown, invalid: Invalid): MetafieldRef[];
|
|
33
|
+
/**
|
|
34
|
+
* @param warn Says why an `account` without a usable `server` is off.
|
|
35
|
+
* @returns `null` without a usable `account.server`: nothing of the account part loads.
|
|
36
|
+
*/
|
|
37
|
+
export declare function accountOption(value: unknown, invalid: Invalid, warn: (message: string) => void): AccountConfig | null;
|
|
38
|
+
export declare const marketsOption: (value: unknown, invalid: Invalid) => MarketsConfig | null;
|
|
39
|
+
export declare const analyticsOption: (value: unknown, invalid: Invalid) => AnalyticsConfig | null;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
export { MARKET_SOURCES } from './config-sections.js';
|
|
2
|
+
import type { ApiVersion } from '../server/src/shared/api-versions.js';
|
|
3
|
+
import type { ShopDomain } from './config-sections.js';
|
|
4
|
+
import type { Money } from './shopify-values.js';
|
|
5
|
+
import type { CountryCode, LanguageCode } from './market-codes.js';
|
|
6
|
+
/** Where the visitor's market comes from (`markets.ts`). */
|
|
7
|
+
export interface MarketsConfig {
|
|
8
|
+
/** True: every source; a list: only those. */
|
|
9
|
+
detect?: boolean | ('saved' | 'server' | 'webflow')[];
|
|
10
|
+
/** Webflow locale (subdirectory or html lang) to market. */
|
|
11
|
+
locales?: Record<string, {
|
|
12
|
+
country?: string;
|
|
13
|
+
language?: string;
|
|
14
|
+
locale?: string;
|
|
15
|
+
}>;
|
|
16
|
+
/** The cookie a server sets with the visitor's country. */
|
|
17
|
+
cookie?: string;
|
|
18
|
+
/** Remember the visitor's choice (default true). */
|
|
19
|
+
remember?: boolean;
|
|
20
|
+
/** With `locales`: ignore an html lang that isn't in the map. */
|
|
21
|
+
strict?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** The optional analytics part. */
|
|
24
|
+
export interface AnalyticsConfig {
|
|
25
|
+
/** GA4/GTM events, into `window.dataLayer` or the named array. */
|
|
26
|
+
dataLayer?: boolean | string;
|
|
27
|
+
/** Shopify's own analytics. `proxy`: the site serves the Storefront API on its own domain. */
|
|
28
|
+
shopify?: boolean | {
|
|
29
|
+
consent?: 'no-banner' | 'default-banner' | 'custom-banner';
|
|
30
|
+
proxy?: boolean;
|
|
31
|
+
};
|
|
32
|
+
onEvent?: (name: string, data: Record<string, unknown>) => void;
|
|
33
|
+
}
|
|
34
|
+
/** The optional customer accounts part, which runs through the site's Worker. */
|
|
35
|
+
export interface AccountConfig {
|
|
36
|
+
/** The Worker's account routes, a URL or a path on this site. */
|
|
37
|
+
server: string;
|
|
38
|
+
/** The site's own order page, with `{id}` for the numeric order id. */
|
|
39
|
+
orderUrl?: string;
|
|
40
|
+
/** Shopify's subscription management page. */
|
|
41
|
+
subscriptionsUrl?: string;
|
|
42
|
+
/** A separate page for payment methods (default `subscriptionsUrl`). */
|
|
43
|
+
paymentUrl?: string;
|
|
44
|
+
/** Where Shopify sends the visitor after logout (default the home page). */
|
|
45
|
+
logoutUrl?: string;
|
|
46
|
+
/** The language of Shopify's login pages. */
|
|
47
|
+
locale?: string;
|
|
48
|
+
/** Replaces `location.assign` for the login redirect (popups, tests). */
|
|
49
|
+
navigate?: (url: string) => void;
|
|
50
|
+
}
|
|
51
|
+
export interface MetafieldIdentifier {
|
|
52
|
+
namespace: string;
|
|
53
|
+
key: string;
|
|
54
|
+
}
|
|
55
|
+
/** `'namespace.key'` or the identifier itself. */
|
|
56
|
+
export type MetafieldRef = string | MetafieldIdentifier;
|
|
57
|
+
/** Shopify's note on a cart change. */
|
|
58
|
+
export interface CartWarning {
|
|
59
|
+
code: string;
|
|
60
|
+
message: string;
|
|
61
|
+
target?: string;
|
|
62
|
+
}
|
|
63
|
+
export type CheckoutTarget = '_self' | '_blank';
|
|
64
|
+
type PurchaseKind = 'one-time' | 'subscription';
|
|
65
|
+
/** Every option, with its default filled in. */
|
|
66
|
+
export interface TetherConfig {
|
|
67
|
+
/** The store's domain, without protocol or path; `''` until one is set. */
|
|
68
|
+
domain: ShopDomain | '';
|
|
69
|
+
/** The public Storefront API access token. */
|
|
70
|
+
token: string;
|
|
71
|
+
/** A dated Shopify API version (or `unstable`, with a warning). */
|
|
72
|
+
apiVersion: ApiVersion | 'unstable';
|
|
73
|
+
/** The market's country, for `@inContext(country:)`. */
|
|
74
|
+
country: CountryCode | undefined;
|
|
75
|
+
/** The market's language, for `@inContext(language:)`. */
|
|
76
|
+
language: LanguageCode | undefined;
|
|
77
|
+
/** An `Intl` locale for money and dates. */
|
|
78
|
+
locale: string | undefined;
|
|
79
|
+
markets: MarketsConfig | null;
|
|
80
|
+
/** The attribute prefix: `tether` reads `tether-product`, `tether-bind`. */
|
|
81
|
+
prefix: string;
|
|
82
|
+
/** A folder (`/product`) or a template with `{handle}` / `{id}`. */
|
|
83
|
+
productPath: string;
|
|
84
|
+
collectionPath: string;
|
|
85
|
+
/** The product metafields to fetch. */
|
|
86
|
+
metafields: MetafieldRef[];
|
|
87
|
+
/** Origins (`https://video.example`) a description's iframes may load from, besides the built-in video players. */
|
|
88
|
+
embedOrigins: string[];
|
|
89
|
+
imagesFirst: number;
|
|
90
|
+
variantsFirst: number;
|
|
91
|
+
sellingPlanGroupsFirst: number;
|
|
92
|
+
sellingPlansFirst: number;
|
|
93
|
+
collectionFirst: number;
|
|
94
|
+
/** Retries of a request that failed on the network, a 429/5xx or Shopify's throttling. */
|
|
95
|
+
retries: number;
|
|
96
|
+
/** Refresh server-rendered products once in the background. */
|
|
97
|
+
revalidate: boolean;
|
|
98
|
+
/** The localStorage key of the cart id (default `<prefix>:cart:<domain>`). */
|
|
99
|
+
storageKey: string;
|
|
100
|
+
cartDrawerOpenClass: string;
|
|
101
|
+
openCartOnAdd: boolean;
|
|
102
|
+
/** Move focus into the open cart, keep Tab inside it, restore it on close. */
|
|
103
|
+
cartFocus: boolean;
|
|
104
|
+
checkoutTarget: CheckoutTarget;
|
|
105
|
+
defaultPurchase: PurchaseKind;
|
|
106
|
+
/** `?variant=` follows the visitor's choice on the page's main product. */
|
|
107
|
+
variantUrl: boolean;
|
|
108
|
+
/** Seconds a Shopify answer may be cached; 0 leaves it to Shopify, which can be hours. */
|
|
109
|
+
maxAge: number;
|
|
110
|
+
/** `tether-show="low-stock"` at this many or fewer (needs inventory access). */
|
|
111
|
+
lowStock: number;
|
|
112
|
+
/** Milliseconds the search part waits after the last keystroke. */
|
|
113
|
+
searchDelay: number;
|
|
114
|
+
/** Mount the document on DOMContentLoaded. */
|
|
115
|
+
autoMount: boolean;
|
|
116
|
+
/** Mount elements added later (CMS load more, filters). */
|
|
117
|
+
observe: boolean;
|
|
118
|
+
/** Mount on Astro's `astro:page-load` and close the cart on navigation. */
|
|
119
|
+
astro: boolean;
|
|
120
|
+
/** The folder of the optional parts, for the `<script>` build. */
|
|
121
|
+
partsUrl: string | null;
|
|
122
|
+
analytics: AnalyticsConfig | null;
|
|
123
|
+
account: AccountConfig | null;
|
|
124
|
+
/** The site's text for a cart warning; nothing keeps Shopify's. */
|
|
125
|
+
warningText: ((warning: CartWarning) => string | null | undefined) | null;
|
|
126
|
+
formatMoney: ((money: Money, locale: string | undefined) => string) | null;
|
|
127
|
+
/** Default: `ScrollTrigger.refresh()` when present. */
|
|
128
|
+
onLayoutChange: ((reason: string) => void) | null;
|
|
129
|
+
onCartOpen: ((drawers: HTMLElement[]) => void) | null;
|
|
130
|
+
onCartClose: ((drawers: HTMLElement[]) => void) | null;
|
|
131
|
+
onLineEnter: ((node: HTMLElement) => void) | null;
|
|
132
|
+
/** Animates a line out, then calls `done()`. */
|
|
133
|
+
onLineLeave: ((node: HTMLElement, done: () => void) => void) | null;
|
|
134
|
+
onValueChange: ((element: HTMLElement, previousText: string) => void) | null;
|
|
135
|
+
/** Every failure that reaches the visitor. */
|
|
136
|
+
onError: ((error: unknown, context: string) => void) | null;
|
|
137
|
+
debug: boolean;
|
|
138
|
+
}
|
|
139
|
+
/** The options a site writes as plain text, which `resolveConfig` checks into their typed form. */
|
|
140
|
+
type ParsedFromText = 'domain' | 'apiVersion' | 'country' | 'language' | 'storageKey';
|
|
141
|
+
/**
|
|
142
|
+
* What a site passes: any option, the market as the codes people write (`'de'`, `'pt-BR'`), and `null` for the
|
|
143
|
+
* default storage key.
|
|
144
|
+
*/
|
|
145
|
+
export type TetherOptions = {
|
|
146
|
+
[Key in Exclude<keyof TetherConfig, ParsedFromText>]?: TetherConfig[Key];
|
|
147
|
+
} & Partial<Record<Exclude<ParsedFromText, 'storageKey'>, string | undefined>> & {
|
|
148
|
+
storageKey?: string | null | undefined;
|
|
149
|
+
};
|
|
150
|
+
export declare const DEFAULTS: Readonly<TetherConfig>;
|
|
151
|
+
export declare const cfg: TetherConfig;
|
|
152
|
+
/**
|
|
153
|
+
* `cfg` as `Tether.config` shows it. A value written there would skip the validation `configure()` does, so the view
|
|
154
|
+
* is read-only; `Tether.init(options)` is how a site changes the config.
|
|
155
|
+
*/
|
|
156
|
+
export declare const configView: TetherConfig;
|
|
157
|
+
/**
|
|
158
|
+
* The configuration `options` describe: defaults filled in, every value validated (an invalid one warns and falls
|
|
159
|
+
* back to its default), hooks that aren't functions dropped so callers only check for null.
|
|
160
|
+
*
|
|
161
|
+
* @param options What the site set, or any object (the server helpers take their options from code and `.env`).
|
|
162
|
+
*/
|
|
163
|
+
export declare function resolveConfig(options: TetherOptions | Readonly<Record<string, unknown>>): TetherConfig;
|
|
164
|
+
/**
|
|
165
|
+
* @param value A `markets` option from code other than the config (`Tether.detectMarket(markets)`).
|
|
166
|
+
* @returns It validated as the config's own is, with the same warnings.
|
|
167
|
+
*/
|
|
168
|
+
export declare const parseMarkets: (value: unknown) => MarketsConfig | null;
|
|
169
|
+
/**
|
|
170
|
+
* Replaces the shared configuration with `options` over the defaults (see `resolveConfig`).
|
|
171
|
+
*
|
|
172
|
+
* @returns The shared `cfg`.
|
|
173
|
+
*/
|
|
174
|
+
export declare function configure(options?: TetherOptions | Readonly<Record<string, unknown>>): TetherConfig;
|
|
175
|
+
/** @returns True once a domain and a token are set. */
|
|
176
|
+
export declare const isConfigured: () => boolean;
|
|
177
|
+
export declare function log(...args: unknown[]): void;
|
|
178
|
+
export declare function warn(...args: unknown[]): void;
|
|
179
|
+
/**
|
|
180
|
+
* Logs a failure that reaches the visitor and hands it to `onError`. A throwing `onError` is logged, never rethrown:
|
|
181
|
+
* the site's hook must not break the render that reported the failure.
|
|
182
|
+
*
|
|
183
|
+
* @param context What failed, e.g. `product coffee-box`.
|
|
184
|
+
*/
|
|
185
|
+
export declare function reportError(error: unknown, context: string): void;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ShopifyCart } from '../cart/store.js';
|
|
2
|
+
/** `[tether-group]` with `[tether-group-add]`: adds every product scope inside the group in one request. */
|
|
3
|
+
export declare const addGroup: (button: Element) => Promise<ShopifyCart | null>;
|
|
4
|
+
/** Binds the document-wide listeners, once per page load of the script. */
|
|
5
|
+
export declare function bindExtrasControls(): void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** What the entry module does for a page. */
|
|
2
|
+
interface PageHooks {
|
|
3
|
+
/** Settles once `init()` has applied the visitor's market. */
|
|
4
|
+
ready: () => Promise<unknown>;
|
|
5
|
+
mount: (root: Document) => unknown;
|
|
6
|
+
unmount: () => void;
|
|
7
|
+
}
|
|
8
|
+
/** Records a mount of the whole document, so the `astro:page-load` of the same page sends no second round of requests. */
|
|
9
|
+
export declare function rememberDocumentMount(): void;
|
|
10
|
+
/** Binds the document-wide listeners, once per page load of the script. */
|
|
11
|
+
export declare function bindNavigation(hooks: PageHooks): void;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type ProblemLevel = 'error' | 'warn';
|
|
2
|
+
export interface Problem {
|
|
3
|
+
level: ProblemLevel;
|
|
4
|
+
message: string;
|
|
5
|
+
/** The element, described for people: `<div#id.class>`. */
|
|
6
|
+
element?: string;
|
|
7
|
+
/** The element itself, for the console. */
|
|
8
|
+
el?: Element;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* @param value What the markup says.
|
|
12
|
+
* @param options What Tether reads.
|
|
13
|
+
* @param prefix Put before the suggestion, e.g. `tether-`.
|
|
14
|
+
* @returns ` Did you mean "…"?` for an option close enough to `value`, else `''`.
|
|
15
|
+
*/
|
|
16
|
+
export declare function didYouMean(value: string, options: Iterable<string>, prefix?: string): string;
|
|
17
|
+
/** The markup problems in `root`, in page order per check. */
|
|
18
|
+
export declare function checkMarkup(root?: ParentNode): Problem[];
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { apiVersionStatus } from './api-version.js';
|
|
2
|
+
import { checkMarkup, didYouMean } from './diagnose-markup.js';
|
|
3
|
+
import type { ApiVersionStatus } from './api-version.js';
|
|
4
|
+
import type { DetectedMarket } from './markets.js';
|
|
5
|
+
import type { Problem } from './diagnose-markup.js';
|
|
6
|
+
export { apiVersionStatus, checkMarkup, didYouMean };
|
|
7
|
+
/** The market in use (a visitor's choice included), and what detection would pick. */
|
|
8
|
+
interface MarketReport {
|
|
9
|
+
country: string | null;
|
|
10
|
+
language: string | null;
|
|
11
|
+
locale: string | null;
|
|
12
|
+
/** `null` without `markets.detect`. */
|
|
13
|
+
detected: DetectedMarket | null;
|
|
14
|
+
}
|
|
15
|
+
interface ShopReport {
|
|
16
|
+
name: string;
|
|
17
|
+
url: string;
|
|
18
|
+
currency: string;
|
|
19
|
+
}
|
|
20
|
+
type ProductReport = {
|
|
21
|
+
key: string;
|
|
22
|
+
handle: string;
|
|
23
|
+
title: string;
|
|
24
|
+
plans: number;
|
|
25
|
+
requiresSellingPlan: boolean;
|
|
26
|
+
} | {
|
|
27
|
+
key: string;
|
|
28
|
+
error: string | undefined;
|
|
29
|
+
};
|
|
30
|
+
interface SellingPlanReport {
|
|
31
|
+
product: string;
|
|
32
|
+
group: string;
|
|
33
|
+
plan: string;
|
|
34
|
+
id: string;
|
|
35
|
+
}
|
|
36
|
+
export interface DiagnoseReport {
|
|
37
|
+
/** Tether's version, `''` when the caller didn't say. */
|
|
38
|
+
version: string;
|
|
39
|
+
/** The config, with the token masked. */
|
|
40
|
+
config: Record<string, unknown>;
|
|
41
|
+
apiVersion: ApiVersionStatus;
|
|
42
|
+
market: MarketReport;
|
|
43
|
+
reachable: boolean;
|
|
44
|
+
shop: ShopReport | null;
|
|
45
|
+
latencyMs: number | null;
|
|
46
|
+
products: ProductReport[];
|
|
47
|
+
sellingPlans: SellingPlanReport[];
|
|
48
|
+
problems: Problem[];
|
|
49
|
+
}
|
|
50
|
+
export interface DiagnoseOptions {
|
|
51
|
+
root?: ParentNode;
|
|
52
|
+
/** Return the report without logging it. */
|
|
53
|
+
silent?: boolean;
|
|
54
|
+
/** Tether's version, for the report. */
|
|
55
|
+
version?: string;
|
|
56
|
+
/** The date the API version's support is measured against. */
|
|
57
|
+
now?: Date;
|
|
58
|
+
}
|
|
59
|
+
/** What's wrong on the page: config, token, API version, products, plans, markup. */
|
|
60
|
+
export declare function diagnose({ root, silent, version, now, }?: DiagnoseOptions): Promise<DiagnoseReport>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { Money } from './shopify-values.js';
|
|
2
|
+
export { attr, sel, get, has, qsa, scoped, emit, ownEvent, isOwnEvent, ANALYTICS_EVENTS } from './markup.js';
|
|
3
|
+
export { imageUrl, cdnUrl, sameImage, setImage } from './images.js';
|
|
4
|
+
export { hasTemplate, repeat, repeatKeyed } from './repeaters.js';
|
|
5
|
+
/**
|
|
6
|
+
* The product page of a product (`productPath`).
|
|
7
|
+
*
|
|
8
|
+
* @returns `null` without the handle or id the path needs.
|
|
9
|
+
*/
|
|
10
|
+
export declare function productUrl(handle: string | null | undefined, id?: string | null): string | null;
|
|
11
|
+
/**
|
|
12
|
+
* `30` → `30%` (en, nl) or `30 %` (de, fr), in the configured locale.
|
|
13
|
+
*
|
|
14
|
+
* @returns `''` for no or a zero percentage.
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatPercent(percentage: number | null | undefined, locale?: string | undefined): string;
|
|
17
|
+
/** Money in the configured locale, through the site's `formatMoney` when it has one. */
|
|
18
|
+
export declare function formatMoney(money: Money | null | undefined): string;
|
|
19
|
+
/** @returns The date in the configured locale, `''` without one. */
|
|
20
|
+
export declare function formatDate(iso: string | null | undefined): string;
|
|
21
|
+
/**
|
|
22
|
+
* Writes HTML from the Shopify admin (product and collection descriptions) into `el`, with script removed
|
|
23
|
+
* (`store-html.ts`). Everything else from Shopify is written as text (`setText`).
|
|
24
|
+
*/
|
|
25
|
+
export declare function setStoreHtml(el: Element, html: string | null | undefined): void;
|
|
26
|
+
/**
|
|
27
|
+
* Sets the text of `el`, or its value when it is a form field.
|
|
28
|
+
*
|
|
29
|
+
* @param value `null` and `undefined` clear it.
|
|
30
|
+
*/
|
|
31
|
+
export declare function setText(el: Element, value: string | number | boolean | null | undefined): void;
|
|
32
|
+
/** `setText` that hands a change after the first render to `onValueChange`, for scramble and roll effects. */
|
|
33
|
+
export declare function setTextTracked(el: HTMLElement, value: string | number | boolean | null | undefined): void;
|
|
34
|
+
/** Shows or hides `el`, restoring its own display value when shown again. */
|
|
35
|
+
export declare function show(el: HTMLElement, visible: boolean): void;
|
|
36
|
+
/** Marks an option button or input as chosen: `is-selected`, `aria-pressed`, and its own or inner radio/checkbox. */
|
|
37
|
+
export declare function setSelected(el: Element, selected: boolean): void;
|
|
38
|
+
/**
|
|
39
|
+
* A global the page's own scripts set on `window`: `TETHER_CONFIG`, the site's config, `TETHER_INTEGRATION`, set by a
|
|
40
|
+
* framework integration (Astro) that starts Tether itself, and GSAP's `ScrollTrigger`. Another script wrote it, so it
|
|
41
|
+
* is read as unknown and checked where it is used.
|
|
42
|
+
*/
|
|
43
|
+
export declare const pageGlobal: (name: "TETHER_CONFIG" | "TETHER_INTEGRATION" | "ScrollTrigger") => unknown;
|
|
44
|
+
/**
|
|
45
|
+
* Async renders change the page height after the site's page-transition hooks ran. After a burst of them this calls
|
|
46
|
+
* `onLayoutChange` (else refreshes ScrollTrigger) and emits `tether:layout-changed`, also when either of those throws.
|
|
47
|
+
*/
|
|
48
|
+
export declare function notifyLayoutChanged(reason: string): void;
|
|
49
|
+
/** Notifies a layout change (`<reason>:images`) once every image in `root` that is still loading has loaded or failed. */
|
|
50
|
+
export declare function watchImages(root: ParentNode, reason: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Runs `task` with `aria-busy` on `el`; does nothing while `el` is already busy.
|
|
53
|
+
*
|
|
54
|
+
* @returns The task's result, `undefined` when it didn't run.
|
|
55
|
+
*/
|
|
56
|
+
export declare function busy<T>(el: Element, task: () => T | Promise<T>): Promise<T | undefined>;
|
|
57
|
+
/** @returns The attribute's JSON, `null` when it is missing or not JSON (with a warning). */
|
|
58
|
+
export declare function parseJSONAttr(el: Element | null | undefined, name: string): unknown;
|
|
59
|
+
export type AttributeValue = string | number | boolean | null | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* `tether-line-attributes`, JSON the site writes: `{ a: 1 }` or `[{ key, value }]`. An array entry that isn't an
|
|
62
|
+
* object is skipped.
|
|
63
|
+
*/
|
|
64
|
+
export declare function attributesFromJson(json: unknown): {
|
|
65
|
+
key: string;
|
|
66
|
+
value: string;
|
|
67
|
+
}[];
|
|
68
|
+
/** `{ a: 1 }` or `[{ key, value }]` → `[{ key, value }]` as Shopify wants cart and line attributes. */
|
|
69
|
+
export declare function toAttributes(attributes: Record<string, AttributeValue> | {
|
|
70
|
+
key: string | number;
|
|
71
|
+
value?: AttributeValue;
|
|
72
|
+
}[] | null | undefined): {
|
|
73
|
+
key: string;
|
|
74
|
+
value: string;
|
|
75
|
+
}[];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ShopifyCart } from './cart/store.js';
|
|
2
|
+
/**
|
|
3
|
+
* `[tether-group]` with `[tether-group-add]`: adds every product scope inside the group in one request, for bundles,
|
|
4
|
+
* build-a-box and "complete the set". The lines get the attribute `_group` and the group's `tether-line-attributes`.
|
|
5
|
+
*
|
|
6
|
+
* @returns The cart, `null` with nothing to add or after a reported failure.
|
|
7
|
+
*/
|
|
8
|
+
export declare function addGroup(button: Element): Promise<ShopifyCart | null>;
|
|
9
|
+
/** Another tab changed the cart (it is loaded again here) or the visitor's market (this tab follows it). */
|
|
10
|
+
export declare function onStorage(event: StorageEvent): void;
|
|
11
|
+
/**
|
|
12
|
+
* `?variant=` (and `selling_plan=`) follow the visitor's choice.
|
|
13
|
+
*
|
|
14
|
+
* @param root The product scope's root.
|
|
15
|
+
*/
|
|
16
|
+
export declare function writeVariantUrl(root: Element, { variant, sellingPlanId }: {
|
|
17
|
+
variant: {
|
|
18
|
+
id: string;
|
|
19
|
+
};
|
|
20
|
+
sellingPlanId: string | null | undefined;
|
|
21
|
+
}): void;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import type { TetherConfig } from './config.js';
|
|
2
|
+
import type { Money } from './shopify-values.js';
|
|
3
|
+
import type { StoreAccess } from './client.js';
|
|
4
|
+
export interface Image {
|
|
5
|
+
url: string;
|
|
6
|
+
altText: string | null;
|
|
7
|
+
width: number | null;
|
|
8
|
+
height: number | null;
|
|
9
|
+
}
|
|
10
|
+
/** An option value's swatch: a colour, an image, or both, as the merchant set them in the admin. */
|
|
11
|
+
interface Swatch {
|
|
12
|
+
color: string | null;
|
|
13
|
+
image: {
|
|
14
|
+
previewImage: Image | null;
|
|
15
|
+
} | null;
|
|
16
|
+
}
|
|
17
|
+
export type SellingPlanAdjustmentValue = {
|
|
18
|
+
__typename: 'SellingPlanPercentagePriceAdjustment';
|
|
19
|
+
adjustmentPercentage: number;
|
|
20
|
+
} | {
|
|
21
|
+
__typename: 'SellingPlanFixedAmountPriceAdjustment';
|
|
22
|
+
adjustmentAmount: Money;
|
|
23
|
+
} | {
|
|
24
|
+
__typename: 'SellingPlanFixedPriceAdjustment';
|
|
25
|
+
price: Money;
|
|
26
|
+
};
|
|
27
|
+
export interface SellingPlan {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
description: string | null;
|
|
31
|
+
recurringDeliveries: boolean;
|
|
32
|
+
options: {
|
|
33
|
+
name: string;
|
|
34
|
+
value: string;
|
|
35
|
+
}[];
|
|
36
|
+
priceAdjustments: {
|
|
37
|
+
orderCount: number | null;
|
|
38
|
+
adjustmentValue: SellingPlanAdjustmentValue;
|
|
39
|
+
}[];
|
|
40
|
+
}
|
|
41
|
+
export interface SellingPlanGroup {
|
|
42
|
+
name: string;
|
|
43
|
+
appName: string | null;
|
|
44
|
+
options: {
|
|
45
|
+
name: string;
|
|
46
|
+
values: string[];
|
|
47
|
+
}[];
|
|
48
|
+
sellingPlans: {
|
|
49
|
+
nodes: SellingPlan[];
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/** A variant's price on one plan. */
|
|
53
|
+
export interface SellingPlanAllocation {
|
|
54
|
+
sellingPlan: {
|
|
55
|
+
id: string;
|
|
56
|
+
};
|
|
57
|
+
/** What the customer pays at checkout (more for a prepaid plan). */
|
|
58
|
+
checkoutChargeAmount: Money;
|
|
59
|
+
remainingBalanceChargeAmount: Money;
|
|
60
|
+
priceAdjustments: {
|
|
61
|
+
price: Money;
|
|
62
|
+
compareAtPrice: Money;
|
|
63
|
+
perDeliveryPrice: Money;
|
|
64
|
+
unitPrice: Money | null;
|
|
65
|
+
}[];
|
|
66
|
+
}
|
|
67
|
+
export interface ProductVariant {
|
|
68
|
+
id: string;
|
|
69
|
+
title: string;
|
|
70
|
+
availableForSale: boolean;
|
|
71
|
+
currentlyNotInStock: boolean;
|
|
72
|
+
/** Absent when the store's token can't read inventory. */
|
|
73
|
+
quantityAvailable?: number | null;
|
|
74
|
+
sku: string | null;
|
|
75
|
+
barcode: string | null;
|
|
76
|
+
selectedOptions: {
|
|
77
|
+
name: string;
|
|
78
|
+
value: string;
|
|
79
|
+
}[];
|
|
80
|
+
image: Image | null;
|
|
81
|
+
price: Money;
|
|
82
|
+
compareAtPrice: Money | null;
|
|
83
|
+
unitPrice: Money | null;
|
|
84
|
+
sellingPlanAllocations: {
|
|
85
|
+
nodes: SellingPlanAllocation[];
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
export interface Metafield {
|
|
89
|
+
namespace: string;
|
|
90
|
+
key: string;
|
|
91
|
+
type: string;
|
|
92
|
+
value: string;
|
|
93
|
+
/** A file reference's image. */
|
|
94
|
+
reference: {
|
|
95
|
+
image?: Image;
|
|
96
|
+
} | null;
|
|
97
|
+
}
|
|
98
|
+
/** The fields of `fragment TetherProduct`. */
|
|
99
|
+
export interface Product {
|
|
100
|
+
id: string;
|
|
101
|
+
handle: string;
|
|
102
|
+
title: string;
|
|
103
|
+
description: string;
|
|
104
|
+
descriptionHtml: string;
|
|
105
|
+
productType: string;
|
|
106
|
+
vendor: string;
|
|
107
|
+
tags: string[];
|
|
108
|
+
availableForSale: boolean;
|
|
109
|
+
publishedAt: string | null;
|
|
110
|
+
onlineStoreUrl: string | null;
|
|
111
|
+
requiresSellingPlan: boolean;
|
|
112
|
+
seo: {
|
|
113
|
+
title: string | null;
|
|
114
|
+
description: string | null;
|
|
115
|
+
};
|
|
116
|
+
featuredImage: Image | null;
|
|
117
|
+
images: {
|
|
118
|
+
nodes: Image[];
|
|
119
|
+
};
|
|
120
|
+
options: {
|
|
121
|
+
name: string;
|
|
122
|
+
optionValues: {
|
|
123
|
+
name: string;
|
|
124
|
+
swatch: Swatch | null;
|
|
125
|
+
}[];
|
|
126
|
+
}[];
|
|
127
|
+
priceRange: {
|
|
128
|
+
minVariantPrice: Money;
|
|
129
|
+
maxVariantPrice: Money;
|
|
130
|
+
};
|
|
131
|
+
compareAtPriceRange: {
|
|
132
|
+
minVariantPrice: Money;
|
|
133
|
+
maxVariantPrice: Money;
|
|
134
|
+
};
|
|
135
|
+
/** Present when metafields are configured; `null` for one that isn't set. */
|
|
136
|
+
metafields?: (Metafield | null)[];
|
|
137
|
+
sellingPlanGroups: {
|
|
138
|
+
nodes: SellingPlanGroup[];
|
|
139
|
+
};
|
|
140
|
+
variants: {
|
|
141
|
+
nodes: ProductVariant[];
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
export type ProductFragmentConfig = Pick<TetherConfig, 'imagesFirst' | 'variantsFirst' | 'sellingPlanGroupsFirst' | 'sellingPlansFirst' | 'metafields'>;
|
|
145
|
+
/**
|
|
146
|
+
* @param o The list sizes and metafields.
|
|
147
|
+
* @param access What the token may read.
|
|
148
|
+
* @returns `fragment TetherProduct on Product`.
|
|
149
|
+
*/
|
|
150
|
+
export declare function productFragment(o?: ProductFragmentConfig, access?: StoreAccess): string;
|
|
151
|
+
/**
|
|
152
|
+
* @param access What the token may read.
|
|
153
|
+
* @returns `fragment TetherCart on Cart`.
|
|
154
|
+
*/
|
|
155
|
+
export declare function cartFragment(access?: StoreAccess): string;
|
|
156
|
+
/** The collection fields Tether renders, for inside a `collection { }` selection. */
|
|
157
|
+
export declare function collectionFields(): string;
|
|
158
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What Tether reads from and sets on `window`, for sites that use the `<script>` build or `window.Tether`. Only the
|
|
3
|
+
* published declarations carry it (scripts/build.ts adds it to the generated `index.d.ts`): the source reads these
|
|
4
|
+
* names as unknown and validates them, so they stay out of its own program.
|
|
5
|
+
*/
|
|
6
|
+
import type { Tether, TetherConfig } from './index.js';
|
|
7
|
+
|
|
8
|
+
declare global {
|
|
9
|
+
interface Window {
|
|
10
|
+
Tether: Tether;
|
|
11
|
+
TETHER_CONFIG?: TetherConfig;
|
|
12
|
+
TETHER_COUNTRY?: string;
|
|
13
|
+
TETHER_LANGUAGE?: string;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Shopify CDN parameters. */
|
|
2
|
+
export interface ImageSize {
|
|
3
|
+
width?: string | number | null;
|
|
4
|
+
height?: string | number | null;
|
|
5
|
+
/** `center`, `top`, `bottom`, `left` or `right`; only applies with a width or height. */
|
|
6
|
+
crop?: string | null;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Shopify CDN image at a size: `imageUrl(url, { width: 800 })`. Use the same width as the element's max-width
|
|
10
|
+
* attribute, so the browser script keeps the image instead of loading it again.
|
|
11
|
+
*
|
|
12
|
+
* @returns The sized URL; `url` itself when it is empty or not absolute.
|
|
13
|
+
*/
|
|
14
|
+
export declare function imageUrl<Url extends string | null | undefined>(url: Url, { width, height, crop }?: ImageSize): Url;
|
|
15
|
+
/** @param el The element whose max-width / max-height / crop attributes size the image. */
|
|
16
|
+
export declare function cdnUrl<Url extends string | null | undefined>(url: Url, el: Element | null | undefined): Url;
|
|
17
|
+
/** @returns True for the same image at any size parameters: the server-rendered one is kept. */
|
|
18
|
+
export declare function sameImage(a: string | null | undefined, b: string | null | undefined): boolean;
|
|
19
|
+
/** Shows `url` in `el`: as the `src` of an `<img>` (lazy unless it says otherwise), else as its background image. */
|
|
20
|
+
export declare function setImage(el: HTMLElement, url: string | null | undefined, alt?: string | null): void;
|