@occluze/tether 0.7.1 → 0.8.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 (61) hide show
  1. package/README.md +52 -110
  2. package/dist/esm/astro.js +1 -1
  3. package/dist/esm/chunks/{account-CXMA5RPZ.js → account-5X563BON.js} +1 -1
  4. package/dist/esm/chunks/{account-pages-IZO7FEOZ.js → account-pages-XR6QZ3DX.js} +1 -1
  5. package/dist/esm/chunks/analytics-JSFHDBU3.js +1 -0
  6. package/dist/esm/chunks/{chunk-BBVUVPMO.js → chunk-255K6OZ7.js} +1 -1
  7. package/dist/esm/chunks/chunk-3OEIEDTK.js +1 -0
  8. package/dist/esm/chunks/chunk-55OHYO66.js +1 -0
  9. package/dist/esm/chunks/chunk-A3GXCQJ4.js +1 -0
  10. package/dist/esm/chunks/chunk-EW3GKRT4.js +1 -0
  11. package/dist/esm/chunks/{chunk-N3V45JPS.js → chunk-FM7ZLLVP.js} +1 -1
  12. package/dist/esm/chunks/chunk-GXCCTPDF.js +1 -0
  13. package/dist/esm/chunks/{chunk-6TFMLT4A.js → chunk-J7GYROV4.js} +1 -1
  14. package/dist/esm/chunks/{chunk-WT7RGGJU.js → chunk-KNJB72OO.js} +1 -1
  15. package/dist/esm/chunks/chunk-KVPLRK6Y.js +1 -0
  16. package/dist/esm/chunks/chunk-O4G2PAQC.js +1 -0
  17. package/dist/esm/chunks/chunk-WNFEYPHV.js +1 -0
  18. package/dist/esm/chunks/{chunk-4HD4J5JC.js → chunk-WXF4L42L.js} +1 -1
  19. package/dist/esm/chunks/{diagnose-XCEBQKBO.js → diagnose-XQQTDHLQ.js} +1 -1
  20. package/dist/esm/chunks/extras-6WLNUEGD.js +1 -0
  21. package/dist/esm/chunks/{markets-ui-M4IQ62CT.js → markets-ui-OAJW4PFU.js} +1 -1
  22. package/dist/esm/chunks/search-LUECIYJR.js +1 -0
  23. package/dist/esm/index.js +1 -1
  24. package/dist/esm/server.js +2 -2
  25. package/dist/tether.diagnose.js +2 -2
  26. package/dist/tether.diagnose.min.js +2 -2
  27. package/dist/tether.extras.js +33 -22
  28. package/dist/tether.extras.min.js +1 -1
  29. package/dist/tether.js +210 -196
  30. package/dist/tether.markets.js +13 -2
  31. package/dist/tether.markets.min.js +1 -1
  32. package/dist/tether.min.js +3 -3
  33. package/dist/tether.min.js.map +4 -4
  34. package/dist/types/src/account/page-answers.d.ts +3 -1
  35. package/dist/types/src/analytics.d.ts +3 -1
  36. package/dist/types/src/cart/mutations.d.ts +2 -2
  37. package/dist/types/src/cart/store.d.ts +8 -2
  38. package/dist/types/src/cart.d.ts +1 -0
  39. package/dist/types/src/client.d.ts +21 -11
  40. package/dist/types/src/controls/navigation.d.ts +3 -1
  41. package/dist/types/src/dom.d.ts +3 -1
  42. package/dist/types/src/index.d.ts +2 -2
  43. package/dist/types/src/markets.d.ts +9 -2
  44. package/dist/types/src/markup.d.ts +7 -5
  45. package/dist/types/src/presets/barba.d.ts +3 -1
  46. package/dist/types/src/product-state.d.ts +3 -1
  47. package/dist/types/src/server.d.ts +4 -4
  48. package/dist/types/src/store-html.d.ts +4 -4
  49. package/dist/types/src/uri.d.ts +6 -0
  50. package/package.json +57 -5
  51. package/dist/esm/chunks/analytics-PG5FPRDN.js +0 -1
  52. package/dist/esm/chunks/chunk-E5YO6274.js +0 -1
  53. package/dist/esm/chunks/chunk-EW5SYO6L.js +0 -1
  54. package/dist/esm/chunks/chunk-HJY2JSNB.js +0 -1
  55. package/dist/esm/chunks/chunk-MQYB6BH4.js +0 -1
  56. package/dist/esm/chunks/chunk-RPMBCAGS.js +0 -1
  57. package/dist/esm/chunks/chunk-VFNHIGCS.js +0 -1
  58. package/dist/esm/chunks/chunk-YN6LEBEN.js +0 -1
  59. package/dist/esm/chunks/chunk-Z6HS3H7K.js +0 -1
  60. package/dist/esm/chunks/extras-4HU3VSBQ.js +0 -1
  61. package/dist/esm/chunks/search-A5DS2IOS.js +0 -1
package/dist/tether.js CHANGED
@@ -141,11 +141,10 @@
141
141
  return null;
142
142
  }
143
143
  const section = {};
144
- const readers = schema;
145
- for (const [key, read] of Object.entries(readers)) {
144
+ for (const key in schema) {
146
145
  const field2 = value[key];
147
146
  if (field2 === void 0) continue;
148
- const parsed = read(field2);
147
+ const parsed = schema[key](field2);
149
148
  if (parsed === void 0) invalid(`${name}.${key}`, field2);
150
149
  else section[key] = parsed;
151
150
  }
@@ -332,12 +331,12 @@
332
331
  if (!(key in DEFAULTS)) warn(`unknown option ${JSON.stringify(key)}: ignored`);
333
332
  }
334
333
  }
335
- function hookOption(value) {
336
- return typeof value === "function" ? value : null;
337
- }
338
- function hookOptions(options) {
339
- const hooks = Object.fromEntries(HOOK_OPTIONS.map((name) => [name, hookOption(options[name])]));
340
- return hooks;
334
+ function setHook(config, name, value) {
335
+ if (typeof value === "function") {
336
+ config[name] = value;
337
+ } else if (value !== void 0 && value !== null) {
338
+ dropped(name, value);
339
+ }
341
340
  }
342
341
  function countOption(name, value) {
343
342
  if (typeof value === "number" && Number.isInteger(value) && value >= 0) return value;
@@ -381,7 +380,6 @@
381
380
  const prefix = typeof options.prefix === "string" && PREFIX.test(options.prefix) ? options.prefix : invalidOption("prefix", options.prefix, DEFAULTS.prefix);
382
381
  const resolved = {
383
382
  ...DEFAULTS,
384
- ...hookOptions(options),
385
383
  domain,
386
384
  apiVersion: apiVersionOption(options.apiVersion),
387
385
  country: codeOption("country", options.country, toCountry),
@@ -401,6 +399,7 @@
401
399
  for (const name of COUNT_OPTIONS) resolved[name] = countOption(name, options[name]);
402
400
  for (const name of SWITCH_OPTIONS) resolved[name] = switchOption(name, options[name]);
403
401
  for (const name of TEXT_OPTIONS) resolved[name] = textOption(name, options[name]);
402
+ for (const name of HOOK_OPTIONS) setHook(resolved, name, options[name]);
404
403
  return resolved;
405
404
  }
406
405
  var parseMarkets = (value) => marketsOption(value, dropped);
@@ -525,17 +524,28 @@
525
524
  function invalidResponse(res, conf) {
526
525
  return res.ok ? new TetherError(`Invalid response (${res.status})`, { code: "INVALID_RESPONSE", status: res.status }) : new TetherError(statusText(res.status, conf), { status: res.status });
527
526
  }
528
- function graphQLFailure(res, errors, conf) {
527
+ function graphQLFailure(res, errors, conf, code) {
529
528
  const message = errors.map((error) => error.message).filter(Boolean).join(" | ");
530
529
  let text2 = message || "Storefront API error";
531
530
  if (!res.ok) text2 = res.status === 401 || res.status === 403 || !message ? statusText(res.status, conf) : message;
532
- return new TetherError(text2, { status: res.status, errors });
531
+ return new TetherError(text2, { status: res.status, errors, code });
533
532
  }
534
533
  function networkFailure(error, retry) {
535
534
  if (retry === "any") return { kind: "retry", backoffMs: RETRY_BACKOFF_MS };
536
535
  throw new TetherError(`Network error: ${messageOf(error)}`, { code: "NETWORK" });
537
536
  }
538
- async function attempt(conf, query2, variables, isData, retry) {
537
+ function graphQLOutcome(res, conf, query2, errors, data, retry, operation) {
538
+ if (query2.includes(INVENTORY_FIELD) && errors.some((error) => error.message.includes(INVENTORY_FIELD))) {
539
+ return { kind: "inventory-refused", error: graphQLFailure(res, errors, conf) };
540
+ }
541
+ const codes = errors.map((error) => error.extensions?.code);
542
+ if (retry !== "none" && codes.includes("THROTTLED")) return { kind: "retry", backoffMs: THROTTLE_BACKOFF_MS };
543
+ const serverError = codes.includes("INTERNAL_SERVER_ERROR");
544
+ if (retry === "any" && serverError) return { kind: "retry", backoffMs: RETRY_BACKOFF_MS };
545
+ const unclear = res.ok && (serverError || operation === "mutation" && data == null);
546
+ throw graphQLFailure(res, errors, conf, unclear ? "SERVER_ERROR" : void 0);
547
+ }
548
+ async function attempt(conf, query2, variables, isData, retry, operation) {
539
549
  let res;
540
550
  try {
541
551
  res = await (conf.fetch ?? fetch)(endpoint(conf), {
@@ -562,15 +572,7 @@
562
572
  const body = toGraphQLResponse(json);
563
573
  if (!body) throw invalidResponse(res, conf);
564
574
  const { data, errors = [] } = body;
565
- if (errors.length) {
566
- if (query2.includes(INVENTORY_FIELD) && errors.some((error) => error.message.includes(INVENTORY_FIELD))) {
567
- return { kind: "inventory-refused", error: graphQLFailure(res, errors, conf) };
568
- }
569
- if (retry !== "none" && errors.some((error) => error.extensions?.code === "THROTTLED")) {
570
- return { kind: "retry", backoffMs: THROTTLE_BACKOFF_MS };
571
- }
572
- throw graphQLFailure(res, errors, conf);
573
- }
575
+ if (errors.length) return graphQLOutcome(res, conf, query2, errors, data, retry, operation);
574
576
  if (!res.ok) throw new TetherError(statusText(res.status, conf), { status: res.status });
575
577
  if (!isData(data)) throw invalidResponse(res, conf);
576
578
  return { kind: "data", data };
@@ -583,14 +585,15 @@
583
585
  const retryWhileLeft = operation === "mutation" ? "not-run" : "any";
584
586
  let retries = 0;
585
587
  for (; ; ) {
586
- const sent = queryText(conf, query2, { inventory: !storesWithoutInventory.has(store) }, { context, operation });
588
+ const access = { inventory: !storesWithoutInventory.has(store) };
589
+ const sent = queryText(conf, query2, access, { context, operation });
587
590
  const retry = retries < conf.retries ? retryWhileLeft : "none";
588
- const outcome = await attempt(conf, sent, variables, isData, retry);
591
+ const outcome = await attempt(conf, sent, variables, isData, retry, operation);
589
592
  switch (outcome.kind) {
590
593
  case "data":
591
594
  return outcome.data;
592
595
  case "inventory-refused":
593
- if (typeof query2 === "string") throw outcome.error;
596
+ if (typeof query2 === "string" || !access.inventory) throw outcome.error;
594
597
  log(`the token can't read inventory: ${INVENTORY_FIELD} is left out from now on`);
595
598
  storesWithoutInventory.add(store);
596
599
  break;
@@ -606,9 +609,11 @@
606
609
  return request(cfg, query2, variables, isData, options);
607
610
  }
608
611
  var hasData = (data) => typeof data === "object" && data !== null;
609
- function query(text2, variables = {}, options) {
610
- const operation = operationOf(typeof text2 === "string" ? text2 : text2({ inventory: true }));
611
- return gql(text2, variables, hasData, { ...options, operation });
612
+ function untypedQuery(conf, text2, variables = {}, options) {
613
+ return request(conf, text2, variables, hasData, { ...options, operation: operationOf(text2) });
614
+ }
615
+ function query(text2, variables, options) {
616
+ return untypedQuery(cfg, text2, variables, options);
612
617
  }
613
618
  function unwrap(payload, name) {
614
619
  if (!payload) throw new TetherError(`${name}: empty response`);
@@ -1680,6 +1685,160 @@
1680
1685
  return list;
1681
1686
  }
1682
1687
 
1688
+ // src/product-render.ts
1689
+ var NTH_IMAGE_BIND = /^image:(\d+)$/;
1690
+ var METAFIELD_BIND = "metafield:";
1691
+ var MULTI_LINE_METAFIELD = /^(rich_text|multi_line_text)_field$/;
1692
+ var ALL_PLAN_GROUPS = ["", "true", "all", "*"];
1693
+ var isSelect = (el) => el.tagName === "SELECT";
1694
+ var selectsIn = (scope, selector) => scope.$(`select${selector}`).filter(isSelect);
1695
+ function renderGallery(el, product) {
1696
+ const images = product.images.nodes;
1697
+ const rendered = [...el.children].map((node) => node.tagName === "IMG" ? node : node.querySelector("img"));
1698
+ const same = !hasTemplate(el) && rendered.length === images.length && rendered.every((img, index) => sameImage(img?.getAttribute("src"), images[index]?.url));
1699
+ if (same) return;
1700
+ repeat(el, images, (node, image) => {
1701
+ const target = node.matches(`img,${sel("bind", "image")}`) ? node : qsa(node, "img")[0] ?? node;
1702
+ setImage(target, image.url, image.altText || product.title);
1703
+ });
1704
+ }
1705
+ function renderMetafield(el, product, ref) {
1706
+ const dot = ref.indexOf(".");
1707
+ const namespace = ref.slice(0, dot);
1708
+ const key = ref.slice(dot + 1);
1709
+ const metafield = (product.metafields ?? []).find((field2) => field2?.namespace === namespace && field2.key === key);
1710
+ if (!metafield) {
1711
+ setText(el, "");
1712
+ return;
1713
+ }
1714
+ const image = metafield.reference?.image;
1715
+ if (image) {
1716
+ setImage(el, image.url, image.altText);
1717
+ return;
1718
+ }
1719
+ if (MULTI_LINE_METAFIELD.test(metafield.type)) el.style.whiteSpace = "pre-line";
1720
+ setText(el, metafield.value);
1721
+ }
1722
+ var PRODUCT_TEXTS = new Map(
1723
+ Object.entries({
1724
+ title: (product) => product.title,
1725
+ "description-text": (product) => product.description,
1726
+ vendor: (product) => product.vendor,
1727
+ type: (product) => product.productType,
1728
+ handle: (product) => product.handle,
1729
+ "published-at": (product) => formatDate(product.publishedAt),
1730
+ "min-price": (product) => formatMoney2(product.priceRange.minVariantPrice),
1731
+ "max-price": (product) => formatMoney2(product.priceRange.maxVariantPrice)
1732
+ })
1733
+ );
1734
+ function renderTags(el, product) {
1735
+ const exclude = (el.getAttribute("exclude") ?? "").split(",").map((tag) => tag.trim()).filter(Boolean);
1736
+ const tags = product.tags.filter((tag) => !exclude.includes(tag));
1737
+ repeat(el, tags, (node, tag) => {
1738
+ setText(node, tag);
1739
+ });
1740
+ }
1741
+ function renderProductBind(el, key, product) {
1742
+ const text2 = PRODUCT_TEXTS.get(key);
1743
+ if (text2) {
1744
+ setText(el, text2(product));
1745
+ return;
1746
+ }
1747
+ switch (key) {
1748
+ case "description":
1749
+ setStoreHtml(el, product.descriptionHtml);
1750
+ break;
1751
+ case "featured-image":
1752
+ setImage(el, product.featuredImage?.url, product.featuredImage?.altText || product.title);
1753
+ break;
1754
+ case "url":
1755
+ case "link": {
1756
+ const url2 = productUrl2(product.handle, product.id);
1757
+ if (url2) el.setAttribute("href", url2);
1758
+ if (key === "url" && !el.firstElementChild && !el.textContent.trim()) setText(el, product.title);
1759
+ break;
1760
+ }
1761
+ case "images":
1762
+ renderGallery(el, product);
1763
+ break;
1764
+ case "tags":
1765
+ renderTags(el, product);
1766
+ break;
1767
+ default:
1768
+ renderIndexedBind(el, key, product);
1769
+ }
1770
+ }
1771
+ function renderIndexedBind(el, key, product) {
1772
+ const nth = NTH_IMAGE_BIND.exec(key);
1773
+ if (nth) {
1774
+ const image = product.images.nodes[Number(nth[1]) - 1] ?? product.featuredImage;
1775
+ setImage(el, image?.url, image?.altText || product.title);
1776
+ } else if (key.startsWith(METAFIELD_BIND)) {
1777
+ renderMetafield(el, product, key.slice(METAFIELD_BIND.length));
1778
+ }
1779
+ }
1780
+ function renderOptionLists(scope) {
1781
+ const { product } = scope;
1782
+ scope.$(sel("option-list")).forEach((container) => {
1783
+ const name = scope.optName(get(container, "option-list"));
1784
+ const option = product.options.find((candidate) => candidate.name === name);
1785
+ if (!option || option.optionValues.length <= 1 && has(container, "hide-single")) {
1786
+ show(container, false);
1787
+ return;
1788
+ }
1789
+ repeat(container, option.optionValues, (node, value) => {
1790
+ node.setAttribute(attr("option-value"), value.name);
1791
+ const text2 = qsa(node, sel("bind", "option-value"))[0];
1792
+ if (text2) setText(text2, value.name);
1793
+ else if (!node.firstElementChild) setText(node, value.name);
1794
+ const swatchEl = qsa(node, sel("bind", "swatch"))[0];
1795
+ const { swatch } = value;
1796
+ if (!swatchEl || !swatch) return;
1797
+ if (swatch.color) swatchEl.style.backgroundColor = swatch.color;
1798
+ if (swatch.image?.previewImage) setImage(swatchEl, swatch.image.previewImage.url, value.name);
1799
+ });
1800
+ });
1801
+ }
1802
+ function renderSelects(scope) {
1803
+ const { product } = scope;
1804
+ selectsIn(scope, sel("option")).forEach((select) => {
1805
+ const option = product.options.find((candidate) => candidate.name === scope.optName(get(select, "option")));
1806
+ if (!option) {
1807
+ show(select, false);
1808
+ return;
1809
+ }
1810
+ select.replaceChildren(...option.optionValues.map((value) => new Option(value.name, value.name)));
1811
+ });
1812
+ selectsIn(scope, sel("variant-select")).forEach((select) => {
1813
+ select.replaceChildren(...product.variants.nodes.map((variant) => new Option(variant.title, variant.id)));
1814
+ });
1815
+ selectsIn(scope, sel("plan")).forEach((select) => {
1816
+ const plans = scope.plans.map((plan) => new Option(plan.name, plan.id));
1817
+ const oneTime = !product.requiresSellingPlan && get(select, "plan") !== "subscription-only";
1818
+ const oneTimeLabel = select.getAttribute(attr("one-time-label")) || "One-time purchase";
1819
+ select.replaceChildren(...oneTime ? [new Option(oneTimeLabel, "")] : [], ...plans);
1820
+ });
1821
+ }
1822
+ function renderPlanLists(scope) {
1823
+ scope.$(sel("plan-list")).forEach((container) => {
1824
+ const raw = (get(container, "plan-list") ?? "").trim();
1825
+ const group = ALL_PLAN_GROUPS.includes(raw.toLowerCase()) ? null : raw;
1826
+ const plans = scope.plans.filter((plan) => !group || plan.group.name === group);
1827
+ repeat(container, plans, (node, plan) => {
1828
+ node.setAttribute(attr("plan-value"), plan.id);
1829
+ if (!node.firstElementChild && !node.querySelector(sel("plan-bind"))) setText(node, plan.name);
1830
+ });
1831
+ });
1832
+ }
1833
+ function writeProduct(scope) {
1834
+ scope.$(sel("bind")).forEach((el) => {
1835
+ renderProductBind(el, get(el, "bind") ?? "", scope.product);
1836
+ });
1837
+ renderOptionLists(scope);
1838
+ renderSelects(scope);
1839
+ renderPlanLists(scope);
1840
+ }
1841
+
1683
1842
  // src/cart/render.ts
1684
1843
  var DEFAULT_TITLE = "Default Title";
1685
1844
  var quantityOf = (line, pending2) => pending2.get(line.id)?.quantity ?? line.quantity;
@@ -1781,7 +1940,8 @@
1781
1940
  if (value !== void 0) setTextTracked(el, value);
1782
1941
  });
1783
1942
  renderLineState(node, line, view);
1784
- qsa(node, `select${sel("line-plan")}`).forEach((select) => {
1943
+ const planSelects = qsa(node, sel("line-plan")).filter(isSelect);
1944
+ planSelects.forEach((select) => {
1785
1945
  getProduct(variant.product.handle).then((product) => {
1786
1946
  fillPlanSelect(select, line, product);
1787
1947
  }).catch((error) => {
@@ -2016,7 +2176,9 @@
2016
2176
  return (error.errors ?? []).some((graphQLError) => UNKNOWN_CART_MESSAGE.test(graphQLError.message));
2017
2177
  }
2018
2178
  function isUnclearFailure(error) {
2019
- return error instanceof TetherError && (error.code === "NETWORK" || error.code === "INVALID_RESPONSE" || (error.status ?? 0) >= 500);
2179
+ if (!(error instanceof TetherError)) return false;
2180
+ const { code, status: status2 = 0 } = error;
2181
+ return code === "NETWORK" || code === "INVALID_RESPONSE" || code === "SERVER_ERROR" || status2 >= 500;
2020
2182
  }
2021
2183
  function toLineInput(input, quantity = 1, options = {}) {
2022
2184
  const spec = typeof input === "object" && input !== null ? input : { ...options, quantity, ...input === null || input === void 0 ? {} : { variantId: input } };
@@ -2329,10 +2491,13 @@
2329
2491
  const ids = Array.isArray(lineIds) ? lineIds : [lineIds];
2330
2492
  return runChange(async () => commit(await removeLines(ids), "remove"));
2331
2493
  },
2494
+ /** Removes the lines the cart has when the change runs, so one queued just before it is cleared too. */
2332
2495
  clear() {
2333
- const ids = currentLines().map((line) => line.id);
2334
- if (!ids.length) return Promise.resolve(currentCart());
2335
- return Cart.removeLine(ids);
2496
+ return runChange(async () => {
2497
+ const ids = currentLines().map((line) => line.id);
2498
+ if (!ids.length) return currentCart();
2499
+ return commit(await removeLines(ids), "remove");
2500
+ });
2336
2501
  },
2337
2502
  setNote(note) {
2338
2503
  const variables = { note: note ?? "" };
@@ -2582,170 +2747,18 @@
2582
2747
  return new Map(Object.entries(texts));
2583
2748
  }
2584
2749
 
2585
- // src/product-render.ts
2586
- var NTH_IMAGE_BIND = /^image:(\d+)$/;
2587
- var METAFIELD_BIND = "metafield:";
2588
- var MULTI_LINE_METAFIELD = /^(rich_text|multi_line_text)_field$/;
2589
- var ALL_PLAN_GROUPS = ["", "true", "all", "*"];
2590
- var isSelect = (el) => el.tagName === "SELECT";
2591
- var selectsIn = (scope, selector) => scope.$(`select${selector}`).filter(isSelect);
2592
- function renderGallery(el, product) {
2593
- const images = product.images.nodes;
2594
- const rendered = [...el.children].map((node) => node.tagName === "IMG" ? node : node.querySelector("img"));
2595
- const same = !hasTemplate(el) && rendered.length === images.length && rendered.every((img, index) => sameImage(img?.getAttribute("src"), images[index]?.url));
2596
- if (same) return;
2597
- repeat(el, images, (node, image) => {
2598
- const target = node.matches(`img,${sel("bind", "image")}`) ? node : qsa(node, "img")[0] ?? node;
2599
- setImage(target, image.url, image.altText || product.title);
2600
- });
2601
- }
2602
- function renderMetafield(el, product, ref) {
2603
- const dot = ref.indexOf(".");
2604
- const namespace = ref.slice(0, dot);
2605
- const key = ref.slice(dot + 1);
2606
- const metafield = (product.metafields ?? []).find((field2) => field2?.namespace === namespace && field2.key === key);
2607
- if (!metafield) {
2608
- setText(el, "");
2609
- return;
2610
- }
2611
- const image = metafield.reference?.image;
2612
- if (image) {
2613
- setImage(el, image.url, image.altText);
2614
- return;
2615
- }
2616
- if (MULTI_LINE_METAFIELD.test(metafield.type)) el.style.whiteSpace = "pre-line";
2617
- setText(el, metafield.value);
2618
- }
2619
- var PRODUCT_TEXTS = new Map(
2620
- Object.entries({
2621
- title: (product) => product.title,
2622
- "description-text": (product) => product.description,
2623
- vendor: (product) => product.vendor,
2624
- type: (product) => product.productType,
2625
- handle: (product) => product.handle,
2626
- "published-at": (product) => formatDate(product.publishedAt),
2627
- "min-price": (product) => formatMoney2(product.priceRange.minVariantPrice),
2628
- "max-price": (product) => formatMoney2(product.priceRange.maxVariantPrice)
2629
- })
2630
- );
2631
- function renderTags(el, product) {
2632
- const exclude = (el.getAttribute("exclude") ?? "").split(",").map((tag) => tag.trim()).filter(Boolean);
2633
- const tags = product.tags.filter((tag) => !exclude.includes(tag));
2634
- repeat(el, tags, (node, tag) => {
2635
- setText(node, tag);
2636
- });
2637
- }
2638
- function renderProductBind(el, key, product) {
2639
- const text2 = PRODUCT_TEXTS.get(key);
2640
- if (text2) {
2641
- setText(el, text2(product));
2642
- return;
2643
- }
2644
- switch (key) {
2645
- case "description":
2646
- setStoreHtml(el, product.descriptionHtml);
2647
- break;
2648
- case "featured-image":
2649
- setImage(el, product.featuredImage?.url, product.featuredImage?.altText || product.title);
2650
- break;
2651
- case "url":
2652
- case "link": {
2653
- const url2 = productUrl2(product.handle, product.id);
2654
- if (url2) el.setAttribute("href", url2);
2655
- if (key === "url" && !el.firstElementChild && !el.textContent.trim()) setText(el, product.title);
2656
- break;
2657
- }
2658
- case "images":
2659
- renderGallery(el, product);
2660
- break;
2661
- case "tags":
2662
- renderTags(el, product);
2663
- break;
2664
- default:
2665
- renderIndexedBind(el, key, product);
2666
- }
2667
- }
2668
- function renderIndexedBind(el, key, product) {
2669
- const nth = NTH_IMAGE_BIND.exec(key);
2670
- if (nth) {
2671
- const image = product.images.nodes[Number(nth[1]) - 1] ?? product.featuredImage;
2672
- setImage(el, image?.url, image?.altText || product.title);
2673
- } else if (key.startsWith(METAFIELD_BIND)) {
2674
- renderMetafield(el, product, key.slice(METAFIELD_BIND.length));
2675
- }
2676
- }
2677
- function renderOptionLists(scope) {
2678
- const { product } = scope;
2679
- scope.$(sel("option-list")).forEach((container) => {
2680
- const name = scope.optName(get(container, "option-list"));
2681
- const option = product.options.find((candidate) => candidate.name === name);
2682
- if (!option || option.optionValues.length <= 1 && has(container, "hide-single")) {
2683
- show(container, false);
2684
- return;
2685
- }
2686
- repeat(container, option.optionValues, (node, value) => {
2687
- node.setAttribute(attr("option-value"), value.name);
2688
- const text2 = qsa(node, sel("bind", "option-value"))[0];
2689
- if (text2) setText(text2, value.name);
2690
- else if (!node.firstElementChild) setText(node, value.name);
2691
- const swatchEl = qsa(node, sel("bind", "swatch"))[0];
2692
- const { swatch } = value;
2693
- if (!swatchEl || !swatch) return;
2694
- if (swatch.color) swatchEl.style.backgroundColor = swatch.color;
2695
- if (swatch.image?.previewImage) setImage(swatchEl, swatch.image.previewImage.url, value.name);
2696
- });
2697
- });
2698
- }
2699
- function renderSelects(scope) {
2700
- const { product } = scope;
2701
- selectsIn(scope, sel("option")).forEach((select) => {
2702
- const option = product.options.find((candidate) => candidate.name === scope.optName(get(select, "option")));
2703
- if (!option) {
2704
- show(select, false);
2705
- return;
2706
- }
2707
- select.replaceChildren(...option.optionValues.map((value) => new Option(value.name, value.name)));
2708
- });
2709
- selectsIn(scope, sel("variant-select")).forEach((select) => {
2710
- select.replaceChildren(...product.variants.nodes.map((variant) => new Option(variant.title, variant.id)));
2711
- });
2712
- selectsIn(scope, sel("plan")).forEach((select) => {
2713
- const plans = scope.plans.map((plan) => new Option(plan.name, plan.id));
2714
- const oneTime = !product.requiresSellingPlan && get(select, "plan") !== "subscription-only";
2715
- const oneTimeLabel = select.getAttribute(attr("one-time-label")) || "One-time purchase";
2716
- select.replaceChildren(...oneTime ? [new Option(oneTimeLabel, "")] : [], ...plans);
2717
- });
2718
- }
2719
- function renderPlanLists(scope) {
2720
- scope.$(sel("plan-list")).forEach((container) => {
2721
- const raw = (get(container, "plan-list") ?? "").trim();
2722
- const group = ALL_PLAN_GROUPS.includes(raw.toLowerCase()) ? null : raw;
2723
- const plans = scope.plans.filter((plan) => !group || plan.group.name === group);
2724
- repeat(container, plans, (node, plan) => {
2725
- node.setAttribute(attr("plan-value"), plan.id);
2726
- if (!node.firstElementChild && !node.querySelector(sel("plan-bind"))) setText(node, plan.name);
2727
- });
2728
- });
2729
- }
2730
- function writeProduct(scope) {
2731
- scope.$(sel("bind")).forEach((el) => {
2732
- renderProductBind(el, get(el, "bind") ?? "", scope.product);
2733
- });
2734
- renderOptionLists(scope);
2735
- renderSelects(scope);
2736
- renderPlanLists(scope);
2737
- }
2738
-
2739
- // src/status.ts
2740
- var URL_SOURCE = "url:";
2741
- function decodePathSegment(segment) {
2750
+ // src/uri.ts
2751
+ function decodeOrKeep(text2) {
2742
2752
  try {
2743
- return decodeURIComponent(segment);
2753
+ return decodeURIComponent(text2);
2744
2754
  } catch (error) {
2745
- if (error instanceof URIError) return segment;
2755
+ if (error instanceof URIError) return text2;
2746
2756
  throw error;
2747
2757
  }
2748
2758
  }
2759
+
2760
+ // src/status.ts
2761
+ var URL_SOURCE = "url:";
2749
2762
  function resolveProductKey(el, location2 = window.location, name = "product") {
2750
2763
  const raw = (get(el, name) ?? "").trim();
2751
2764
  if (!raw.toLowerCase().startsWith(URL_SOURCE)) return { key: raw || null, fromUrl: false, raw };
@@ -2754,7 +2767,7 @@
2754
2767
  if (source.toLowerCase() === "path") {
2755
2768
  const segments = location2.pathname.split("/").filter(Boolean);
2756
2769
  const segment = segments[segments.length - 1];
2757
- key = segment === void 0 ? null : decodePathSegment(segment);
2770
+ key = segment === void 0 ? null : decodeOrKeep(segment);
2758
2771
  } else {
2759
2772
  key = new URLSearchParams(location2.search).get(source || "handle");
2760
2773
  }
@@ -3510,9 +3523,10 @@
3510
3523
  locale: typeof locale === "string" && locale ? locale : void 0
3511
3524
  };
3512
3525
  }
3526
+ var parseSavedMarket = (text2) => toMarket(parseJsonOrNull(text2));
3513
3527
  function readSavedMarket(storage = pageStorage) {
3514
3528
  const text2 = storage.getItem(storageKey());
3515
- return text2 ? toMarket(parseJsonOrNull(text2)) : null;
3529
+ return text2 ? parseSavedMarket(text2) : null;
3516
3530
  }
3517
3531
 
3518
3532
  // src/page-market.ts
@@ -3567,7 +3581,7 @@
3567
3581
  }
3568
3582
 
3569
3583
  // src/part-integrity.ts
3570
- var PART_INTEGRITY = { "tether.diagnose.js": "sha384-My35ltXsPvspuBHm0xCTu7wl6C4ORwigmKQMCaTKI6VP9ELMCCLYCETpAYW3Fus+", "tether.markets.js": "sha384-m9u+yVeYzqljJYufGt6C6E2xCgqgBSJstvmjU5a2lXZLK3q2saH19EYgP/EC5ox3", "tether.search.js": "sha384-ZrByfRsWNOHbbWOocY4WOD2RWe4QI2qQRZ4Eb+fM5v/UHIQ8mlWxbSwrxJt8yLbc", "tether.extras.js": "sha384-sE3c2fclN/3LKtuYUtC4CjVk76Zu0Mv/jR3p8YYLisAvyDvqJxpx4nj8PbJ3KzXH", "tether.account.js": "sha384-UF36poTg1vnXE7Pg+FYFGMJ4qjKhx9mbOug9bqTYhzgqRppOKS9M/1uY5D/cz9KF", "tether.account-pages.js": "sha384-jJYvZswrRw+pGDYrk0FswWcYqGpZkbR6ooxJGFu0lTYkUlVOcsCXuLLLU6M5kO54", "tether.analytics.js": "sha384-10v5pBMzgfF7BuLGQBg3cdbgMk701Uto5rGjhByiRD2jI9+/WF8DFcSWplIcdRNg" };
3584
+ var PART_INTEGRITY = { "tether.diagnose.js": "sha384-exWttcEw4tQTiJ4OU0r/Y+0T5vVIYIo3kcmieqDPkUUmJQGr2HZzWxZCOmMhsvaY", "tether.markets.js": "sha384-hn9741hCQun49mIj7A2bazMG2wXxTpMDScOQK+8wMeY6KT1p+ovXcKDi3m6BK04C", "tether.search.js": "sha384-ZrByfRsWNOHbbWOocY4WOD2RWe4QI2qQRZ4Eb+fM5v/UHIQ8mlWxbSwrxJt8yLbc", "tether.extras.js": "sha384-lt7I8DOnCx8wwVHQM4ZT39+Jlv95WVED5eVDezUKchNXo4+j1oBXYtxzPFiPyxgm", "tether.account.js": "sha384-UF36poTg1vnXE7Pg+FYFGMJ4qjKhx9mbOug9bqTYhzgqRppOKS9M/1uY5D/cz9KF", "tether.account-pages.js": "sha384-jJYvZswrRw+pGDYrk0FswWcYqGpZkbR6ooxJGFu0lTYkUlVOcsCXuLLLU6M5kO54", "tether.analytics.js": "sha384-10v5pBMzgfF7BuLGQBg3cdbgMk701Uto5rGjhByiRD2jI9+/WF8DFcSWplIcdRNg" };
3571
3585
 
3572
3586
  // src/part-registry.ts
3573
3587
  function isTetherInternals(value) {
@@ -4001,7 +4015,7 @@
4001
4015
  }
4002
4016
 
4003
4017
  // src/index.ts
4004
- var VERSION = "0.7.1";
4018
+ var VERSION = "0.8.0";
4005
4019
  var OBSERVE_DEBOUNCE_MS = 50;
4006
4020
  function pageConfig() {
4007
4021
  const config = pageGlobal("TETHER_CONFIG");
@@ -61,6 +61,16 @@
61
61
  }
62
62
  }
63
63
 
64
+ // src/uri.ts
65
+ function decodeOrKeep(text) {
66
+ try {
67
+ return decodeURIComponent(text);
68
+ } catch (error) {
69
+ if (error instanceof URIError) return text;
70
+ throw error;
71
+ }
72
+ }
73
+
64
74
  // src/markets.ts
65
75
  var DEFAULT_COOKIE = "tether_country";
66
76
  var storageKey = () => `${cfg.prefix}:market:${cfg.domain}`;
@@ -93,14 +103,15 @@
93
103
  locale: typeof locale === "string" && locale ? locale : void 0
94
104
  };
95
105
  }
106
+ var parseSavedMarket = (text) => toMarket(parseJsonOrNull(text));
96
107
  function readSavedMarket(storage = pageStorage) {
97
108
  const text = storage.getItem(storageKey());
98
- return text ? toMarket(parseJsonOrNull(text)) : null;
109
+ return text ? parseSavedMarket(text) : null;
99
110
  }
100
111
  function readCookie(doc, name) {
101
112
  if (!doc || !name) return null;
102
113
  const cookie = doc.cookie.split(";").map((part) => part.trim()).find((part) => part.startsWith(`${name}=`));
103
- return cookie ? decodeURIComponent(cookie.slice(name.length + 1)) : null;
114
+ return cookie ? decodeOrKeep(cookie.slice(name.length + 1)) : null;
104
115
  }
105
116
  function lookupLocale(locales, key) {
106
117
  if (!locales || !key) return null;
@@ -1 +1 @@
1
- (()=>{var W=Object.defineProperty;var G=(e,t)=>{for(var n in t)W(e,n,{get:t[n],enumerable:!0})};var b={};G(b,{detectMarket:()=>j,getLocalization:()=>J,renderCountrySelects:()=>L,setCountry:()=>xe});var V=window.Tether.__core["config.ts"],[c,_e,Pe,M,S,C,Ae]=V;var Z=window.Tether.__core["client.ts"],[ve,x,Oe,T,E]=Z;var Q=window.Tether.__core["cart.ts"],[g]=Q;var X=window.Tether.__core["collection.ts"],[_]=X;var ee=window.Tether.__core["loader.ts"],[P,Ue]=ee;var te=window.Tether.__core["dom.ts"],[De,m,Fe,A,je,$e,N,qe,Je,Ye,Be,Ke,We,Ge,w,Ve,Ze,Qe]=te;var ne=window.Tether.__core["mounting.ts"],[v,O,I,z,R,k]=ne;var oe=window.Tether.__core["market-codes.ts"],[s,d]=oe;function U(e,t="localStorage"){try{return window[t].getItem(e)}catch{return null}}function H(e,t,n="localStorage"){try{window[n].setItem(e,t)}catch{}}var re="tether_country",D=()=>`${c.prefix}:market:${c.domain}`,F={getItem:e=>U(e)};function ae(){let e=typeof window<"u";return{document:typeof document<"u"?document:null,location:e?window.location:null,storage:F,global:e?window:{}}}function ce(e){try{return JSON.parse(e)}catch(t){if(t instanceof SyntaxError)return null;throw t}}function ie(e){if(typeof e!="object"||e===null)return null;let t=s(Reflect.get(e,"country"));if(!t)return null;let n=Reflect.get(e,"locale");return{country:t,language:d(Reflect.get(e,"language"))??void 0,locale:typeof n=="string"&&n?n:void 0}}function ue(e=F){let t=e.getItem(D());return t?ie(ce(t)):null}function le(e,t){if(!e||!t)return null;let n=e.cookie.split(";").map(a=>a.trim()).find(a=>a.startsWith(`${t}=`));return n?decodeURIComponent(n.slice(t.length+1)):null}function h(e,t){if(!e||!t)return null;let n=t.toLowerCase(),a=Object.keys(e).find(o=>o.toLowerCase()===n);return a?e[a]??null:null}function se(e,t){let n=r=>t.document?.querySelector(`meta[name="${r}"]`)?.getAttribute("content"),a=Reflect.get(t.global,"TETHER_COUNTRY"),o=Reflect.get(t.global,"TETHER_LANGUAGE"),i=n("tether-country")||le(t.document,e.cookie||re);return{country:a||i,language:o||n("tether-language")}}function de(e,t){let n=(t.location?.pathname??"/").split("/").find(u=>u!==""),a=h(e.locales,n);if(a)return a;let o=t.document?.documentElement.getAttribute("lang");if(!o)return null;let i=h(e.locales,o)??h(e.locales,o.split("-")[0]);if(i)return{locale:o,...i};if(e.locales&&e.strict)return null;let r=o.split("-")[1];return{language:o,country:r?.length===2?r:null,locale:o}}function ge(e,t,n){switch(e){case"saved":return t.remember===!1?null:ue(n.storage);case"server":return se(t,n);case"webflow":return de(t,n)}}function fe(e){return e?e===!0?M:e:["saved"]}function j(e=c.markets,t=ae()){let n=(e===c.markets?e:S(e))??{};if(n.detect===!1)return{};let a={},o={sources:a};for(let i of fe(n.detect)){let r=ge(i,n,t);if(!r)continue;let u=s(r.country),l=d(r.language),f=typeof r.locale=="string"&&r.locale?r.locale:null;u&&!o.country&&(o.country=u,a.country=i),l&&!o.language&&(o.language=l,a.language=i),f&&!o.locale&&(o.locale=f,a.locale=i)}return o}function $(e){if(c.markets?.remember===!1)return;let t={country:e.country,language:e.language||void 0,locale:e.locale||void 0};H(D(),JSON.stringify(t))}var me="{name} ({currency})",pe="name",p=null;function ye(){p=null}var Ce="query TetherLocalization{localization{country{isoCode name currency{isoCode symbol}}language{isoCode name}availableCountries{isoCode name currency{isoCode symbol}availableLanguages{isoCode name}}}}",q={isoCode:"string",name:"string",currency:"object"},we=T({localization:{country:q,availableCountries:[q]}});function J(){return p??(p=x(Ce,{},we).then(e=>e.localization,e=>{throw p=null,e})),p}function Y(e,t){switch(t){case"name":return e.name;case"code":return e.isoCode;case"currency":return e.currency.isoCode;case"symbol":return e.currency.symbol;default:return""}}var ke=(e,t)=>e.replace(/\{(name|code|currency|symbol)\}/g,(n,a)=>Y(t,a));function he(e,t,n){let a=e.getAttribute(m("country-label"))||me,o=(e.getAttribute(m("countries"))||"").toUpperCase().split(/[\s,]+/).filter(Boolean),i=o.length?o.map(r=>t.find(u=>u.isoCode===r)).filter(r=>r!==void 0):t;e.replaceChildren(...i.map(r=>new Option(ke(a,r),r.isoCode))),e.value=n,e.value!==n&&(e.selectedIndex=-1),e.disabled=i.length<2&&!e.hasAttribute(m("always-enabled"))}function Le(e,t,n){let a=(c.country||n.country.isoCode).toUpperCase(),o=[...n.availableCountries].sort((r,u)=>r.name.localeCompare(u.name,c.locale||void 0)),i=o.find(r=>r.isoCode===a)??n.country;e.forEach(r=>{he(r,o,a)}),t.forEach(r=>{r.textContent=Y(i,N(r,"country-bind")||pe)})}function L(e=document){let t=k(e,`select${w("country-select")}`),n=k(e,w("country-bind"));return!t.length&&!n.length?Promise.resolve():J().then(a=>{Le(t,n,a)}).catch(a=>{C(a,"country select")})}var be=e=>Object.values(c.markets?.locales??{}).find(t=>s(t.country)===e);function Me(e,t){return e!==void 0?d(e):t?t.language?d(t.language):void 0:c.language}function Se(e){P();let t=[];return g.id()&&t.push(g.setBuyerIdentity({countryCode:e},{create:!1}).catch(n=>{C(n,"cart country")})),R(),v.forEach(n=>t.push(n.load())),O.forEach(n=>{n.closest(_())||(I.delete(n),z(n))}),t}async function xe(e,{language:t,locale:n,remember:a=!0}={}){let o=s(e);if(!o)throw new E(`Not a country code: ${e}`,{code:"INVALID_COUNTRY"});let i=be(o),r=n||i?.locale,u=r||c.locale,l=Me(t,i),f=o!==c.country||l!==c.language||u!==c.locale;if(c.country=o,c.language=l||void 0,c.locale=u,a&&$({country:o,language:l,locale:r}),!f)return L(),g.state;t!==void 0&&ye();let K=Se(o);return L(),A("country-changed",{country:o,language:c.language}),await Promise.all(K),g.state}function y(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Te(e){return y(e)&&y(e.__core)&&y(e.__parts)}function B(e,t){let n=Reflect.get(window,"Tether");if(!Te(n))throw new Error(`tether.${e}.js runs after the Tether script, which loads it, and needs its window.Tether`);n.__parts[e]=t}B("markets",b);})();
1
+ (()=>{var G=Object.defineProperty;var V=(e,t)=>{for(var n in t)G(e,n,{get:t[n],enumerable:!0})};var b={};V(b,{detectMarket:()=>$,getLocalization:()=>J,renderCountrySelects:()=>L,setCountry:()=>Ee});var Z=window.Tether.__core["config.ts"],[c,Ae,Ne,M,S,C,ve]=Z;var Q=window.Tether.__core["client.ts"],[Ie,x,Re,T,E]=Q;var X=window.Tether.__core["cart.ts"],[g]=X;var ee=window.Tether.__core["collection.ts"],[_]=ee;var te=window.Tether.__core["loader.ts"],[P,De]=te;var ne=window.Tether.__core["dom.ts"],[je,m,$e,A,qe,Ke,N,Je,Ye,Be,We,Ge,Ve,Ze,w,Qe,Xe,et]=ne;var oe=window.Tether.__core["mounting.ts"],[v,O,I,R,z,k]=oe;var re=window.Tether.__core["market-codes.ts"],[s,d]=re;function U(e,t="localStorage"){try{return window[t].getItem(e)}catch{return null}}function H(e,t,n="localStorage"){try{window[n].setItem(e,t)}catch{}}function D(e){try{return decodeURIComponent(e)}catch(t){if(t instanceof URIError)return e;throw t}}var ae="tether_country",F=()=>`${c.prefix}:market:${c.domain}`,j={getItem:e=>U(e)};function ce(){let e=typeof window<"u";return{document:typeof document<"u"?document:null,location:e?window.location:null,storage:j,global:e?window:{}}}function ie(e){try{return JSON.parse(e)}catch(t){if(t instanceof SyntaxError)return null;throw t}}function ue(e){if(typeof e!="object"||e===null)return null;let t=s(Reflect.get(e,"country"));if(!t)return null;let n=Reflect.get(e,"locale");return{country:t,language:d(Reflect.get(e,"language"))??void 0,locale:typeof n=="string"&&n?n:void 0}}var le=e=>ue(ie(e));function se(e=j){let t=e.getItem(F());return t?le(t):null}function de(e,t){if(!e||!t)return null;let n=e.cookie.split(";").map(a=>a.trim()).find(a=>a.startsWith(`${t}=`));return n?D(n.slice(t.length+1)):null}function h(e,t){if(!e||!t)return null;let n=t.toLowerCase(),a=Object.keys(e).find(o=>o.toLowerCase()===n);return a?e[a]??null:null}function ge(e,t){let n=r=>t.document?.querySelector(`meta[name="${r}"]`)?.getAttribute("content"),a=Reflect.get(t.global,"TETHER_COUNTRY"),o=Reflect.get(t.global,"TETHER_LANGUAGE"),i=n("tether-country")||de(t.document,e.cookie||ae);return{country:a||i,language:o||n("tether-language")}}function fe(e,t){let n=(t.location?.pathname??"/").split("/").find(u=>u!==""),a=h(e.locales,n);if(a)return a;let o=t.document?.documentElement.getAttribute("lang");if(!o)return null;let i=h(e.locales,o)??h(e.locales,o.split("-")[0]);if(i)return{locale:o,...i};if(e.locales&&e.strict)return null;let r=o.split("-")[1];return{language:o,country:r?.length===2?r:null,locale:o}}function me(e,t,n){switch(e){case"saved":return t.remember===!1?null:se(n.storage);case"server":return ge(t,n);case"webflow":return fe(t,n)}}function pe(e){return e?e===!0?M:e:["saved"]}function $(e=c.markets,t=ce()){let n=(e===c.markets?e:S(e))??{};if(n.detect===!1)return{};let a={},o={sources:a};for(let i of pe(n.detect)){let r=me(i,n,t);if(!r)continue;let u=s(r.country),l=d(r.language),f=typeof r.locale=="string"&&r.locale?r.locale:null;u&&!o.country&&(o.country=u,a.country=i),l&&!o.language&&(o.language=l,a.language=i),f&&!o.locale&&(o.locale=f,a.locale=i)}return o}function q(e){if(c.markets?.remember===!1)return;let t={country:e.country,language:e.language||void 0,locale:e.locale||void 0};H(F(),JSON.stringify(t))}var ye="{name} ({currency})",Ce="name",p=null;function we(){p=null}var ke="query TetherLocalization{localization{country{isoCode name currency{isoCode symbol}}language{isoCode name}availableCountries{isoCode name currency{isoCode symbol}availableLanguages{isoCode name}}}}",K={isoCode:"string",name:"string",currency:"object"},he=T({localization:{country:K,availableCountries:[K]}});function J(){return p??(p=x(ke,{},he).then(e=>e.localization,e=>{throw p=null,e})),p}function Y(e,t){switch(t){case"name":return e.name;case"code":return e.isoCode;case"currency":return e.currency.isoCode;case"symbol":return e.currency.symbol;default:return""}}var Le=(e,t)=>e.replace(/\{(name|code|currency|symbol)\}/g,(n,a)=>Y(t,a));function be(e,t,n){let a=e.getAttribute(m("country-label"))||ye,o=(e.getAttribute(m("countries"))||"").toUpperCase().split(/[\s,]+/).filter(Boolean),i=o.length?o.map(r=>t.find(u=>u.isoCode===r)).filter(r=>r!==void 0):t;e.replaceChildren(...i.map(r=>new Option(Le(a,r),r.isoCode))),e.value=n,e.value!==n&&(e.selectedIndex=-1),e.disabled=i.length<2&&!e.hasAttribute(m("always-enabled"))}function Me(e,t,n){let a=(c.country||n.country.isoCode).toUpperCase(),o=[...n.availableCountries].sort((r,u)=>r.name.localeCompare(u.name,c.locale||void 0)),i=o.find(r=>r.isoCode===a)??n.country;e.forEach(r=>{be(r,o,a)}),t.forEach(r=>{r.textContent=Y(i,N(r,"country-bind")||Ce)})}function L(e=document){let t=k(e,`select${w("country-select")}`),n=k(e,w("country-bind"));return!t.length&&!n.length?Promise.resolve():J().then(a=>{Me(t,n,a)}).catch(a=>{C(a,"country select")})}var Se=e=>Object.values(c.markets?.locales??{}).find(t=>s(t.country)===e);function xe(e,t){return e!==void 0?d(e):t?t.language?d(t.language):void 0:c.language}function Te(e){P();let t=[];return g.id()&&t.push(g.setBuyerIdentity({countryCode:e},{create:!1}).catch(n=>{C(n,"cart country")})),z(),v.forEach(n=>t.push(n.load())),O.forEach(n=>{n.closest(_())||(I.delete(n),R(n))}),t}async function Ee(e,{language:t,locale:n,remember:a=!0}={}){let o=s(e);if(!o)throw new E(`Not a country code: ${e}`,{code:"INVALID_COUNTRY"});let i=Se(o),r=n||i?.locale,u=r||c.locale,l=xe(t,i),f=o!==c.country||l!==c.language||u!==c.locale;if(c.country=o,c.language=l||void 0,c.locale=u,a&&q({country:o,language:l,locale:r}),!f)return L(),g.state;t!==void 0&&we();let W=Te(o);return L(),A("country-changed",{country:o,language:c.language}),await Promise.all(W),g.state}function y(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function _e(e){return y(e)&&y(e.__core)&&y(e.__parts)}function B(e,t){let n=Reflect.get(window,"Tether");if(!_e(n))throw new Error(`tether.${e}.js runs after the Tether script, which loads it, and needs its window.Tether`);n.__parts[e]=t}B("markets",b);})();