@occluze/tether 0.6.8 → 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.
Files changed (259) hide show
  1. package/README.md +11 -11
  2. package/dist/esm/astro.js +2 -2
  3. package/dist/esm/chunks/account-UIPWJQ3Y.js +1 -0
  4. package/dist/esm/chunks/account-pages-6ROA6Y4V.js +1 -0
  5. package/dist/esm/chunks/analytics-2V632IRV.js +1 -0
  6. package/dist/esm/chunks/chunk-4GCXM764.js +1 -0
  7. package/dist/esm/chunks/chunk-56FCLJJD.js +1 -0
  8. package/dist/esm/chunks/chunk-5Z5O3767.js +1 -0
  9. package/dist/esm/chunks/chunk-6OZJCAGZ.js +1 -0
  10. package/dist/esm/chunks/chunk-A5SYCVQM.js +1 -0
  11. package/dist/esm/chunks/chunk-BA4LQJJQ.js +1 -0
  12. package/dist/esm/chunks/chunk-BFTZR4OB.js +4 -0
  13. package/dist/esm/chunks/chunk-C5JYQCWH.js +1 -0
  14. package/dist/esm/chunks/chunk-E5YO6274.js +1 -0
  15. package/dist/esm/chunks/chunk-MPDWM2NN.js +1 -0
  16. package/dist/esm/chunks/chunk-T44MUL4Y.js +1 -0
  17. package/dist/esm/chunks/chunk-YLUULATY.js +1 -0
  18. package/dist/esm/chunks/diagnose-3FEKRIEK.js +14 -0
  19. package/dist/esm/chunks/extras-6POFBNOP.js +1 -0
  20. package/dist/esm/chunks/markets-ui-FD6NI2OG.js +1 -0
  21. package/dist/esm/chunks/search-UJ73YBQ5.js +1 -0
  22. package/dist/esm/index.js +1 -1
  23. package/dist/esm/server.js +2 -2
  24. package/dist/presets/barba.esm.js +19 -23
  25. package/dist/tether.account-pages.js +320 -365
  26. package/dist/tether.account-pages.min.js +1 -1
  27. package/dist/tether.account.js +242 -491
  28. package/dist/tether.account.min.js +1 -1
  29. package/dist/tether.analytics.js +66 -88
  30. package/dist/tether.analytics.min.js +1 -1
  31. package/dist/tether.diagnose.js +36 -33
  32. package/dist/tether.diagnose.min.js +2 -2
  33. package/dist/tether.extras.js +28 -36
  34. package/dist/tether.extras.min.js +1 -1
  35. package/dist/tether.js +1270 -894
  36. package/dist/tether.markets.js +73 -90
  37. package/dist/tether.markets.min.js +1 -1
  38. package/dist/tether.min.js +0 -0
  39. package/dist/tether.min.js.map +4 -4
  40. package/dist/tether.search.js +44 -68
  41. package/dist/tether.search.min.js +1 -1
  42. package/dist/types/server/src/shared/account-orders.d.ts +44 -0
  43. package/dist/types/server/src/shared/account-routes.d.ts +153 -0
  44. package/dist/types/server/src/shared/api-versions.d.ts +13 -0
  45. package/dist/types/server/src/shared/error-message.d.ts +2 -0
  46. package/dist/types/server/src/shared/json.d.ts +25 -0
  47. package/dist/types/server/src/shared/market-codes.d.ts +16 -0
  48. package/dist/types/src/account/addresses-view.d.ts +5 -0
  49. package/dist/types/src/account/answers.d.ts +40 -0
  50. package/dist/types/src/account/markup.d.ts +19 -0
  51. package/dist/types/src/account/operations.d.ts +41 -0
  52. package/dist/types/src/account/order-lines.d.ts +13 -0
  53. package/dist/types/src/account/order-list.d.ts +12 -0
  54. package/dist/types/src/account/order-page.d.ts +6 -0
  55. package/dist/types/src/account/page-answers.d.ts +182 -0
  56. package/dist/types/src/account/page-events.d.ts +2 -0
  57. package/dist/types/src/account/server-client.d.ts +60 -0
  58. package/dist/types/src/account/subscriptions-view.d.ts +2 -0
  59. package/dist/types/src/account-api.d.ts +18 -0
  60. package/dist/types/src/account-marks.d.ts +15 -0
  61. package/dist/types/src/account-pages.d.ts +8 -0
  62. package/dist/types/src/account.d.ts +64 -0
  63. package/dist/types/src/amounts.d.ts +12 -0
  64. package/dist/types/src/analytics-shopify.d.ts +41 -0
  65. package/dist/types/src/analytics.d.ts +2 -0
  66. package/dist/types/src/api-version.d.ts +28 -0
  67. package/dist/types/src/astro.d.ts +42 -0
  68. package/dist/types/src/cart/cart-shape.d.ts +43 -0
  69. package/dist/types/src/cart/checkout.d.ts +16 -0
  70. package/dist/types/src/cart/drawer.d.ts +18 -0
  71. package/dist/types/src/cart/mutations.d.ts +79 -0
  72. package/dist/types/src/cart/render.d.ts +17 -0
  73. package/dist/types/src/cart/store.d.ts +182 -0
  74. package/dist/types/src/cart.d.ts +106 -0
  75. package/dist/types/src/client.d.ts +100 -0
  76. package/dist/types/src/collection.d.ts +25 -0
  77. package/dist/types/src/config-sections.d.ts +40 -0
  78. package/dist/types/src/config.d.ts +185 -0
  79. package/dist/types/src/controls/cart-controls.d.ts +2 -0
  80. package/dist/types/src/controls/discount.d.ts +2 -0
  81. package/dist/types/src/controls/extras.d.ts +5 -0
  82. package/dist/types/src/controls/navigation.d.ts +12 -0
  83. package/dist/types/src/diagnose-markup.d.ts +19 -0
  84. package/dist/types/src/diagnose.d.ts +60 -0
  85. package/dist/types/src/dom.d.ts +75 -0
  86. package/dist/types/src/extras.d.ts +21 -0
  87. package/dist/types/src/fragments.d.ts +158 -0
  88. package/dist/types/src/globals.d.ts +15 -0
  89. package/dist/types/src/images.d.ts +20 -0
  90. package/dist/types/src/index.d.ts +167 -0
  91. package/dist/types/src/initial.d.ts +56 -0
  92. package/dist/types/src/lazy.d.ts +28 -0
  93. package/dist/types/src/loader.d.ts +84 -0
  94. package/dist/types/src/market-codes.d.ts +6 -0
  95. package/dist/types/src/markets-ui.d.ts +32 -0
  96. package/dist/types/src/markets.d.ts +72 -0
  97. package/dist/types/src/markup.d.ts +131 -0
  98. package/dist/types/src/mounting.d.ts +46 -0
  99. package/dist/types/src/page-market.d.ts +27 -0
  100. package/dist/types/src/presets/barba.d.ts +56 -0
  101. package/dist/types/src/product-events.d.ts +2 -0
  102. package/dist/types/src/product-render.d.ts +17 -0
  103. package/dist/types/src/product-shape.d.ts +88 -0
  104. package/dist/types/src/product-state.d.ts +110 -0
  105. package/dist/types/src/product.d.ts +66 -0
  106. package/dist/types/src/repeaters.d.ts +16 -0
  107. package/dist/types/src/search.d.ts +33 -0
  108. package/dist/types/src/selling-plans.d.ts +64 -0
  109. package/dist/types/src/server.d.ts +88 -0
  110. package/dist/types/src/shopify-values.d.ts +46 -0
  111. package/dist/types/src/status.d.ts +33 -0
  112. package/dist/types/src/storage.d.ts +12 -0
  113. package/dist/types/src/store-html.d.ts +39 -0
  114. package/dist/types/src/storefront/catalog.d.ts +38 -0
  115. package/dist/types/src/storefront/json-ld.d.ts +20 -0
  116. package/dist/types/src/variant-render.d.ts +14 -0
  117. package/package.json +24 -23
  118. package/src/account/addresses-view.ts +58 -0
  119. package/src/account/answers.ts +79 -0
  120. package/src/account/markup.ts +36 -0
  121. package/src/account/operations.ts +145 -0
  122. package/src/account/{order-lines.js → order-lines.ts} +20 -41
  123. package/src/account/order-list.ts +107 -0
  124. package/src/account/order-page.ts +137 -0
  125. package/src/account/page-answers.ts +317 -0
  126. package/src/account/{page-events.js → page-events.ts} +55 -90
  127. package/src/account/server-client.ts +183 -0
  128. package/src/account/{subscriptions-view.js → subscriptions-view.ts} +25 -68
  129. package/src/account-api.ts +98 -0
  130. package/src/account-marks.ts +35 -0
  131. package/src/{account-pages.js → account-pages.ts} +29 -37
  132. package/src/account.ts +284 -0
  133. package/src/amounts.ts +64 -0
  134. package/src/{analytics-shopify.js → analytics-shopify.ts} +112 -107
  135. package/src/analytics.ts +315 -0
  136. package/src/{api-version.js → api-version.ts} +25 -31
  137. package/src/{astro.js → astro.ts} +110 -104
  138. package/src/cart/cart-shape.ts +25 -0
  139. package/src/cart/checkout.ts +101 -0
  140. package/src/cart/{drawer.js → drawer.ts} +18 -31
  141. package/src/cart/mutations.ts +237 -0
  142. package/src/cart/{render.js → render.ts} +68 -96
  143. package/src/cart/store.ts +279 -0
  144. package/src/{cart.js → cart.ts} +82 -128
  145. package/src/client.ts +391 -0
  146. package/src/{collection.js → collection.ts} +30 -38
  147. package/src/config-sections.ts +284 -0
  148. package/src/config.ts +480 -0
  149. package/src/controls/{cart-controls.js → cart-controls.ts} +22 -54
  150. package/src/controls/{discount.js → discount.ts} +13 -34
  151. package/src/controls/{extras.js → extras.ts} +15 -24
  152. package/src/controls/{navigation.js → navigation.ts} +24 -30
  153. package/src/{diagnose-markup.js → diagnose-markup.ts} +37 -72
  154. package/src/{diagnose.js → diagnose.ts} +95 -96
  155. package/src/dom.ts +268 -0
  156. package/src/{extras.js → extras.ts} +43 -52
  157. package/src/fragments.ts +261 -0
  158. package/src/globals.d.ts +15 -0
  159. package/src/{images.js → images.ts} +30 -43
  160. package/src/index.ts +415 -0
  161. package/src/initial.ts +101 -0
  162. package/src/lazy-iife.ts +197 -0
  163. package/src/lazy.ts +42 -0
  164. package/src/{loader.js → loader.ts} +149 -123
  165. package/src/market-codes.ts +6 -0
  166. package/src/{markets-ui.js → markets-ui.ts} +91 -68
  167. package/src/markets.ts +246 -0
  168. package/src/markup.ts +127 -0
  169. package/src/{mounting.js → mounting.ts} +88 -101
  170. package/src/{page-market.js → page-market.ts} +32 -38
  171. package/src/part-integrity.ts +7 -0
  172. package/src/parts/account-pages.ts +7 -0
  173. package/src/parts/account.ts +7 -0
  174. package/src/parts/analytics.ts +7 -0
  175. package/src/parts/diagnose.ts +7 -0
  176. package/src/parts/extras.ts +7 -0
  177. package/src/parts/markets.ts +7 -0
  178. package/src/parts/search.ts +7 -0
  179. package/src/presets/barba.ts +194 -0
  180. package/src/{product-events.js → product-events.ts} +33 -48
  181. package/src/{product-render.js → product-render.ts} +38 -77
  182. package/src/product-shape.ts +49 -0
  183. package/src/product-state.ts +318 -0
  184. package/src/{product.js → product.ts} +90 -126
  185. package/src/{repeaters.js → repeaters.ts} +40 -52
  186. package/src/{search.js → search.ts} +85 -103
  187. package/src/selling-plans.ts +145 -0
  188. package/src/server.ts +211 -0
  189. package/src/{shopify-values.js → shopify-values.ts} +24 -22
  190. package/src/{status.js → status.ts} +34 -54
  191. package/src/storage.ts +34 -0
  192. package/src/store-html.ts +359 -0
  193. package/src/storefront/catalog.ts +196 -0
  194. package/src/storefront/{json-ld.js → json-ld.ts} +45 -68
  195. package/src/{variant-render.js → variant-render.ts} +24 -50
  196. package/dist/esm/chunks/account-C3NP6HFB.js +0 -1
  197. package/dist/esm/chunks/account-pages-WLK374FO.js +0 -1
  198. package/dist/esm/chunks/analytics-G3SAWMNL.js +0 -1
  199. package/dist/esm/chunks/chunk-27PJJZGC.js +0 -1
  200. package/dist/esm/chunks/chunk-2FSXS55U.js +0 -1
  201. package/dist/esm/chunks/chunk-FCSWQDVV.js +0 -1
  202. package/dist/esm/chunks/chunk-FOMSMIAM.js +0 -1
  203. package/dist/esm/chunks/chunk-GZJTCLLW.js +0 -1
  204. package/dist/esm/chunks/chunk-HEQILZVR.js +0 -1
  205. package/dist/esm/chunks/chunk-JOOEXYF3.js +0 -4
  206. package/dist/esm/chunks/chunk-MPTQYLSM.js +0 -1
  207. package/dist/esm/chunks/chunk-NEHZ37TU.js +0 -3
  208. package/dist/esm/chunks/chunk-V74KGEJF.js +0 -1
  209. package/dist/esm/chunks/chunk-VT4CDUJJ.js +0 -1
  210. package/dist/esm/chunks/chunk-YJLWX2HK.js +0 -1
  211. package/dist/esm/chunks/diagnose-6VVGZNTY.js +0 -14
  212. package/dist/esm/chunks/extras-GJVRDFM3.js +0 -1
  213. package/dist/esm/chunks/markets-ui-UNB4PTA7.js +0 -1
  214. package/dist/esm/chunks/search-OU75RNQL.js +0 -1
  215. package/src/account/addresses-view.js +0 -92
  216. package/src/account/browser-session.js +0 -359
  217. package/src/account/markup.js +0 -48
  218. package/src/account/operations.js +0 -180
  219. package/src/account/order-list.js +0 -91
  220. package/src/account/order-page.js +0 -192
  221. package/src/account/server-client.js +0 -172
  222. package/src/account/shared.js +0 -111
  223. package/src/account/shopify-auth.js +0 -150
  224. package/src/account-api.js +0 -118
  225. package/src/account-links.js +0 -35
  226. package/src/account.js +0 -342
  227. package/src/amounts.js +0 -36
  228. package/src/analytics.js +0 -352
  229. package/src/cart/checkout.js +0 -97
  230. package/src/cart/mutations.js +0 -234
  231. package/src/cart/store.js +0 -326
  232. package/src/client.js +0 -267
  233. package/src/config.js +0 -349
  234. package/src/dom.js +0 -287
  235. package/src/fragments.js +0 -237
  236. package/src/index.js +0 -353
  237. package/src/initial.js +0 -87
  238. package/src/lazy-iife.js +0 -116
  239. package/src/lazy.js +0 -39
  240. package/src/market-codes.js +0 -35
  241. package/src/markets.js +0 -334
  242. package/src/markup.js +0 -64
  243. package/src/parts/account-pages.js +0 -6
  244. package/src/parts/account.js +0 -6
  245. package/src/parts/analytics.js +0 -6
  246. package/src/parts/diagnose.js +0 -6
  247. package/src/parts/extras.js +0 -6
  248. package/src/parts/markets.js +0 -6
  249. package/src/parts/search.js +0 -6
  250. package/src/presets/barba.js +0 -190
  251. package/src/product-state.js +0 -318
  252. package/src/selling-plans.js +0 -154
  253. package/src/server.js +0 -215
  254. package/src/store-html.js +0 -0
  255. package/src/storefront/catalog.js +0 -199
  256. package/types/astro.d.ts +0 -28
  257. package/types/barba.d.ts +0 -16
  258. package/types/index.d.ts +0 -577
  259. package/types/server.d.ts +0 -182
@@ -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;
@@ -0,0 +1,167 @@
1
+ /// <reference path="./globals.d.ts" />
2
+ import { query, TetherError, withContext } from './client.js';
3
+ import { getProduct, getProducts, getRecommendations, clearProductCache, primeProduct } from './loader.js';
4
+ import * as plans from './selling-plans.js';
5
+ import { resolveProductKey } from './status.js';
6
+ import { formatMoney, imageUrl } from './dom.js';
7
+ import { setCountry } from './page-market.js';
8
+ import { addGroup } from './controls/extras.js';
9
+ import type { TetherConfig, TetherOptions, MarketsConfig } from './config.js';
10
+ import type { ShopifyCart } from './cart/store.js';
11
+ import type { ProductScope } from './product.js';
12
+ import type { DiagnoseOptions } from './diagnose.js';
13
+ import type { TetherEvents } from './markup.js';
14
+ export { addGroup, setCountry };
15
+ export type { TetherOptions as TetherConfig, TetherConfig as ResolvedTetherConfig } from './config.js';
16
+ export type { MarketsConfig, CartWarning } from './config.js';
17
+ export type { Money } from './shopify-values.js';
18
+ export type { Image as ShopifyImage, Metafield as ShopifyMetafield, Product as ShopifyProduct, ProductVariant as ShopifyVariant, SellingPlan as ShopifySellingPlanNode, SellingPlanAdjustmentValue, SellingPlanAllocation as ShopifySellingPlanAllocation, SellingPlanGroup as ShopifySellingPlanGroup, } from './fragments.js';
19
+ export type { PlanInGroup as ShopifySellingPlan, PlanAdjustment, ProductWithPlans, VariantWithPlans, } from './selling-plans.js';
20
+ export type { CartStatus, CartVariant as ShopifyCartVariant, ShopifyCart, ShopifyCartLine } from './cart/store.js';
21
+ export type { Attributes, LineSpec as LineInput } from './cart/mutations.js';
22
+ export type { TetherError, TetherErrorCode, GraphQLError, UserError } from './client.js';
23
+ export type { ProductScope } from './product.js';
24
+ export type { Purchase } from './product-state.js';
25
+ export type { ProductPage, ProductQuery } from './loader.js';
26
+ export type { DetectedMarket, Localization, MarketSource } from './markets.js';
27
+ export type { SetCountryOptions } from './page-market.js';
28
+ export type { DiagnoseOptions, DiagnoseReport } from './diagnose.js';
29
+ export type { TetherEvents } from './markup.js';
30
+ export type { AccountCustomer } from './account/answers.js';
31
+ export type { AccountImage as ImageRef, AccountOrder, AccountOrderLine } from '../server/src/shared/account-orders.js';
32
+ export type { AddressFields as CustomerAddressInput } from './account/operations.js';
33
+ export type { CustomerAddress, Fulfillment, MailingAddress, OrderDetail, OrderDetailLine, SubscriptionContract, SubscriptionLine, } from './account/page-answers.js';
34
+ /** The helpers for selling plans, `Tether.plans`. */
35
+ export type SellingPlanHelpers = typeof plans;
36
+ export declare const VERSION = "0.7.0";
37
+ /**
38
+ * Mounts every product scope and product list inside `root`. Safe to call repeatedly.
39
+ *
40
+ * @returns The scopes and lists newly mounted.
41
+ */
42
+ export declare function mount(root?: Document | Element): number;
43
+ /** Call before a page transition removes the page: closes the cart drawer. */
44
+ export declare function unmount(): void;
45
+ /** @returns The product scope `el` is in. */
46
+ export declare function getScope(el: Element | null | undefined): ProductScope | null;
47
+ /**
48
+ * Configures Tether (`window.TETHER_CONFIG` with `overrides` over it), applies the visitor's market and loads the
49
+ * cart. A second call without overrides returns the first one's promise.
50
+ *
51
+ * @returns `null` without a domain and token, when Tether stays idle.
52
+ */
53
+ export declare function init(overrides?: TetherOptions): Promise<Tether | null>;
54
+ /**
55
+ * Listens to the Tether event `<prefix>:<name>`. Only the events Tether dispatched reach the listener: one another
56
+ * script dispatches under the same name is ignored, so the detail is always the one `TetherEvents` gives.
57
+ *
58
+ * @returns Stops listening.
59
+ */
60
+ declare function on<Name extends keyof TetherEvents>(name: Name, listener: (detail: TetherEvents[Name], event: CustomEvent<TetherEvents[Name]>) => void): () => void;
61
+ declare const publicApi: {
62
+ VERSION: string;
63
+ init: typeof init;
64
+ mount: typeof mount;
65
+ unmount: typeof unmount;
66
+ /** The live config, read-only. */
67
+ readonly config: Readonly<TetherConfig>;
68
+ readonly ready: Promise<Tether | null>;
69
+ query: typeof query;
70
+ withContext: typeof withContext;
71
+ cart: {
72
+ init: () => Promise<ShopifyCart | null>;
73
+ id: () => string | null;
74
+ readonly status: import("./cart/store.js").CartStatus;
75
+ readonly state: ShopifyCart | null;
76
+ readonly lines: import("./cart/store.js").ShopifyCartLine[];
77
+ readonly count: number;
78
+ readonly loaded: boolean;
79
+ readonly lastError: Error | null;
80
+ readonly warnings: import("./config.js").CartWarning[];
81
+ readonly pendingQty: ReadonlyMap<string, {
82
+ quantity: number;
83
+ }>;
84
+ setCheckoutResolver: typeof import("./cart/checkout.js").setCheckoutResolver;
85
+ forgetSaved(): void;
86
+ render: typeof import("./cart/store.js").render;
87
+ subscribe: typeof import("./cart/store.js").subscribe;
88
+ add(input: string | number | import("./cart/mutations.js").LineSpec | (string | number | import("./cart/mutations.js").LineSpec)[], quantity?: number, options?: Omit<import("./cart/mutations.js").LineSpec, "variantId" | "quantity">): Promise<ShopifyCart>;
89
+ updateLine(lineId: string, patch: number | import("./cart/mutations.js").LinePatch): Promise<ShopifyCart | null>;
90
+ changeQuantity: (lineId: string, delta: number) => Promise<ShopifyCart | null>;
91
+ quantityOf: (line: import("./cart/store.js").ShopifyCartLine) => number;
92
+ removeLine(lineIds: string | string[]): Promise<ShopifyCart | null>;
93
+ clear(): Promise<ShopifyCart | null>;
94
+ setNote(note: string | null | undefined): Promise<ShopifyCart | null>;
95
+ setAttributes(attributes: import("./cart/mutations.js").Attributes): Promise<ShopifyCart | null>;
96
+ setDiscountCodes(codes: string | string[] | ((current: string[]) => string[])): Promise<ShopifyCart | null>;
97
+ applyDiscount(code: string): Promise<ShopifyCart | null>;
98
+ removeDiscount(code: string): Promise<ShopifyCart | null>;
99
+ setBuyerIdentity(buyerIdentity: {
100
+ countryCode?: string;
101
+ email?: string;
102
+ phone?: string;
103
+ }, { create }?: {
104
+ create?: boolean;
105
+ }): Promise<ShopifyCart | null>;
106
+ checkout: typeof import("./cart/checkout.js").checkout;
107
+ drawers: () => HTMLElement[];
108
+ isOpen: typeof import("./cart/drawer.js").isOpen;
109
+ open: typeof import("./cart/drawer.js").openCart;
110
+ close: typeof import("./cart/drawer.js").closeCart;
111
+ toggle: typeof import("./cart/drawer.js").toggleCart;
112
+ };
113
+ getProduct: typeof getProduct;
114
+ getProducts: typeof getProducts;
115
+ getRecommendations: typeof getRecommendations;
116
+ getScope: typeof getScope;
117
+ addGroup: (button: Element) => Promise<ShopifyCart | null>;
118
+ account: {
119
+ login: (args_0?: {
120
+ returnTo?: string;
121
+ locale?: string;
122
+ } | undefined) => Promise<void>;
123
+ customer: () => Promise<import("./account/answers.js").AccountCustomer | null>;
124
+ orders: (args_0?: {
125
+ first?: number;
126
+ } | undefined) => Promise<import("../server/src/shared/account-orders.js").AccountOrder[]>;
127
+ logout: (args_0?: {
128
+ returnTo?: string;
129
+ } | undefined) => Promise<void>;
130
+ render: (root?: ParentNode | undefined) => Promise<void>;
131
+ mountAccount: (root?: ParentNode | undefined) => Promise<void>;
132
+ readonly isLoggedIn: () => Promise<boolean>;
133
+ readonly order: (id: string | number) => Promise<import("./account/page-answers.js").OrderDetail | null>;
134
+ readonly updateProfile: (fields?: {
135
+ firstName?: string;
136
+ lastName?: string;
137
+ }) => Promise<import("./account/page-answers.js").Profile>;
138
+ readonly addresses: () => Promise<import("./account/page-answers.js").CustomerAddress[]>;
139
+ readonly saveAddress: (address: import("./account/operations.js").AddressFields | null, options?: {
140
+ id?: string;
141
+ isDefault?: boolean;
142
+ }) => Promise<import("./account/page-answers.js").AccountAddress>;
143
+ readonly deleteAddress: (id: string) => Promise<string>;
144
+ readonly subscriptions: () => Promise<import("./account/page-answers.js").SubscriptionContract[]>;
145
+ readonly subscriptionAction: (id: string | number, action: import("../server/src/shared/account-routes.js").SubscriptionAction) => Promise<import("./account/page-answers.js").SubscriptionChange>;
146
+ readonly requestReturn: (orderId: string | number, lines: import("./account/operations.js").ReturnLine[]) => Promise<import("./account/page-answers.js").OpenedReturn>;
147
+ };
148
+ primeProduct: typeof primeProduct;
149
+ normalizeProductKey: typeof import("./shopify-values.js").productKey;
150
+ clearProductCache: typeof clearProductCache;
151
+ formatMoney: typeof formatMoney;
152
+ imageUrl: typeof imageUrl;
153
+ plans: typeof plans;
154
+ TetherError: typeof TetherError;
155
+ resolveProductKey: typeof resolveProductKey;
156
+ setCountry: typeof setCountry;
157
+ detectMarket: (markets?: MarketsConfig | null) => Promise<import("./markets.js").DetectedMarket>;
158
+ getLocalization: () => Promise<import("./markets.js").Localization>;
159
+ diagnose: (options?: Omit<DiagnoseOptions, "version">) => Promise<import("./diagnose.js").DiagnoseReport>;
160
+ on: typeof on;
161
+ };
162
+ /** `window.Tether`, and what `import Tether from '@occluze/tether'` gives. */
163
+ export type Tether = typeof publicApi;
164
+ /** `Tether`, also carrying `TetherInternals`, which the published type leaves out. */
165
+ export declare const api: Tether;
166
+ /** @alias `api`, for `import Tether from '@occluze/tether'`. */
167
+ export default api;
@@ -0,0 +1,56 @@
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
+ import type { Selection, ShowCondition } from './product-state.js';
5
+ export interface InitialOptions {
6
+ /** The page's `?variant=`; the first variant for sale without. */
7
+ variant?: string | null | undefined;
8
+ /** The page's `?selling_plan=`: subscribes on that plan. */
9
+ sellingPlan?: string | null | undefined;
10
+ /** `subscription` subscribes on the first plan. */
11
+ defaultPurchase?: string | null | undefined;
12
+ /** `low-stock` at this many or fewer. */
13
+ lowStock?: number | undefined;
14
+ }
15
+ /** A plan in the plan list (`tether-plan-list`). */
16
+ interface InitialPlan {
17
+ id: string;
18
+ name: string;
19
+ /** On this plan, for the variant. */
20
+ price: Money | null;
21
+ /** In %, 0 without savings. */
22
+ savings: number;
23
+ /** `is-selected`: the line is bought on this plan. */
24
+ selected: boolean;
25
+ /** The variant is on this plan; `is-unavailable` when not. */
26
+ available: boolean;
27
+ }
28
+ export interface InitialState {
29
+ variant: ProductVariant;
30
+ /** Option name → value of the variant: `is-selected` on those buttons. */
31
+ selected: Selection;
32
+ purchase: 'one-time' | 'subscription';
33
+ /** The plan the line is bought on, `null` when bought once. */
34
+ plan: PlanInGroup | null;
35
+ plans: InitialPlan[];
36
+ /** The offered plan's savings in % (`tether-bind="subscription-savings"`), 0 without. */
37
+ savings: number;
38
+ price: Money;
39
+ /** Only when on sale. */
40
+ compareAtPrice: Money | null;
41
+ available: boolean;
42
+ /** The `tether-show` conditions: `hidden={!state.show['out-of-stock']}`. */
43
+ show: Record<ShowCondition, boolean>;
44
+ /**
45
+ * Per option, the values without a variant for sale (given the other selected values), as plain data for
46
+ * frameworks that serialise props.
47
+ */
48
+ unavailable: Record<string, string[]>;
49
+ /** The same as a function: `is-unavailable`. */
50
+ isUnavailable: (name: string, value: string) => boolean;
51
+ }
52
+ /** @throws TetherError For a product without variants, which Shopify never sends: every product has one. */
53
+ export declare function initialState(product: Product, options?: InitialOptions): InitialState;
54
+ /** @returns `null` without a product. */
55
+ export declare function initialState(product: Product | null | undefined, options?: InitialOptions): InitialState | null;
56
+ export {};
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Optional parts that most pages never need, loaded on first use. In the ESM and Node builds they are dynamic
3
+ * imports, which bundlers split into their own chunks; the `<script>` build swaps this file for `lazy-iife.ts`
4
+ * (scripts/build.ts).
5
+ */
6
+ export interface Parts {
7
+ diagnose: typeof import('./diagnose.js');
8
+ markets: typeof import('./markets-ui.js');
9
+ search: typeof import('./search.js');
10
+ extras: typeof import('./extras.js');
11
+ account: typeof import('./account.js');
12
+ 'account-pages': typeof import('./account-pages.js');
13
+ analytics: typeof import('./analytics.js');
14
+ }
15
+ export type PartName = keyof Parts;
16
+ /**
17
+ * What `window.Tether` carries for the `<script>` build's separately loaded parts, besides the API sites use. Left out
18
+ * of the published `Tether` type.
19
+ */
20
+ export interface TetherInternals {
21
+ /** `coreModules`: the modules the parts use instead of bundling copies, in the `<script>` build only. */
22
+ __core: unknown;
23
+ /** Each part registers its module here when its file has loaded. */
24
+ __parts: Partial<Parts>;
25
+ }
26
+ export declare const loadPart: <Name extends PartName>(name: Name) => Promise<Parts[Name]>;
27
+ /** Only the `<script>` build shares its modules with separately loaded parts. */
28
+ export declare const coreModules: undefined;