@occluze/tether 0.7.1 → 0.7.2
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 +51 -109
- package/dist/esm/astro.js +1 -1
- package/dist/esm/chunks/{account-CXMA5RPZ.js → account-W4FBRKXA.js} +1 -1
- package/dist/esm/chunks/{account-pages-IZO7FEOZ.js → account-pages-IM3OQTOP.js} +1 -1
- package/dist/esm/chunks/analytics-QDVOLZY3.js +1 -0
- package/dist/esm/chunks/{chunk-BBVUVPMO.js → chunk-AUVAN3KZ.js} +1 -1
- package/dist/esm/chunks/chunk-BMDYNMRC.js +1 -0
- package/dist/esm/chunks/chunk-CUL66KRA.js +1 -0
- package/dist/esm/chunks/{chunk-WT7RGGJU.js → chunk-CVNRODH3.js} +1 -1
- package/dist/esm/chunks/{chunk-N3V45JPS.js → chunk-CXHPBT7N.js} +1 -1
- package/dist/esm/chunks/chunk-GF6JTI65.js +1 -0
- package/dist/esm/chunks/chunk-MRSDJPBC.js +1 -0
- package/dist/esm/chunks/chunk-NYDZPTLP.js +1 -0
- package/dist/esm/chunks/chunk-QDHLXXAZ.js +1 -0
- package/dist/esm/chunks/{chunk-4HD4J5JC.js → chunk-QUECUXHD.js} +1 -1
- package/dist/esm/chunks/chunk-RJY76ESL.js +1 -0
- package/dist/esm/chunks/chunk-RPI5C3EJ.js +1 -0
- package/dist/esm/chunks/{chunk-6TFMLT4A.js → chunk-YC4JXWRG.js} +1 -1
- package/dist/esm/chunks/{diagnose-XCEBQKBO.js → diagnose-3XHPZZNP.js} +1 -1
- package/dist/esm/chunks/extras-C724KKG6.js +1 -0
- package/dist/esm/chunks/{markets-ui-M4IQ62CT.js → markets-ui-WBWWQAGU.js} +1 -1
- package/dist/esm/chunks/search-5NFIZBPJ.js +1 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/server.js +2 -2
- package/dist/tether.diagnose.js +2 -2
- package/dist/tether.diagnose.min.js +2 -2
- package/dist/tether.extras.js +33 -22
- package/dist/tether.extras.min.js +1 -1
- package/dist/tether.js +201 -186
- package/dist/tether.markets.js +13 -2
- 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/types/src/cart/mutations.d.ts +2 -2
- package/dist/types/src/cart.d.ts +1 -0
- package/dist/types/src/client.d.ts +16 -11
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/markets.d.ts +9 -2
- package/dist/types/src/uri.d.ts +6 -0
- package/package.json +54 -5
- package/dist/esm/chunks/analytics-PG5FPRDN.js +0 -1
- package/dist/esm/chunks/chunk-E5YO6274.js +0 -1
- package/dist/esm/chunks/chunk-EW5SYO6L.js +0 -1
- package/dist/esm/chunks/chunk-HJY2JSNB.js +0 -1
- package/dist/esm/chunks/chunk-MQYB6BH4.js +0 -1
- package/dist/esm/chunks/chunk-RPMBCAGS.js +0 -1
- package/dist/esm/chunks/chunk-VFNHIGCS.js +0 -1
- package/dist/esm/chunks/chunk-YN6LEBEN.js +0 -1
- package/dist/esm/chunks/chunk-Z6HS3H7K.js +0 -1
- package/dist/esm/chunks/extras-4HU3VSBQ.js +0 -1
- package/dist/esm/chunks/search-A5DS2IOS.js +0 -1
package/dist/tether.js
CHANGED
|
@@ -525,17 +525,28 @@
|
|
|
525
525
|
function invalidResponse(res, conf) {
|
|
526
526
|
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
527
|
}
|
|
528
|
-
function graphQLFailure(res, errors, conf) {
|
|
528
|
+
function graphQLFailure(res, errors, conf, code) {
|
|
529
529
|
const message = errors.map((error) => error.message).filter(Boolean).join(" | ");
|
|
530
530
|
let text2 = message || "Storefront API error";
|
|
531
531
|
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 });
|
|
532
|
+
return new TetherError(text2, { status: res.status, errors, code });
|
|
533
533
|
}
|
|
534
534
|
function networkFailure(error, retry) {
|
|
535
535
|
if (retry === "any") return { kind: "retry", backoffMs: RETRY_BACKOFF_MS };
|
|
536
536
|
throw new TetherError(`Network error: ${messageOf(error)}`, { code: "NETWORK" });
|
|
537
537
|
}
|
|
538
|
-
|
|
538
|
+
function graphQLOutcome(res, conf, query2, errors, data, retry, operation) {
|
|
539
|
+
if (query2.includes(INVENTORY_FIELD) && errors.some((error) => error.message.includes(INVENTORY_FIELD))) {
|
|
540
|
+
return { kind: "inventory-refused", error: graphQLFailure(res, errors, conf) };
|
|
541
|
+
}
|
|
542
|
+
const codes = errors.map((error) => error.extensions?.code);
|
|
543
|
+
if (retry !== "none" && codes.includes("THROTTLED")) return { kind: "retry", backoffMs: THROTTLE_BACKOFF_MS };
|
|
544
|
+
const serverError = codes.includes("INTERNAL_SERVER_ERROR");
|
|
545
|
+
if (retry === "any" && serverError) return { kind: "retry", backoffMs: RETRY_BACKOFF_MS };
|
|
546
|
+
const unclear = res.ok && (serverError || operation === "mutation" && data == null);
|
|
547
|
+
throw graphQLFailure(res, errors, conf, unclear ? "SERVER_ERROR" : void 0);
|
|
548
|
+
}
|
|
549
|
+
async function attempt(conf, query2, variables, isData, retry, operation) {
|
|
539
550
|
let res;
|
|
540
551
|
try {
|
|
541
552
|
res = await (conf.fetch ?? fetch)(endpoint(conf), {
|
|
@@ -562,15 +573,7 @@
|
|
|
562
573
|
const body = toGraphQLResponse(json);
|
|
563
574
|
if (!body) throw invalidResponse(res, conf);
|
|
564
575
|
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
|
-
}
|
|
576
|
+
if (errors.length) return graphQLOutcome(res, conf, query2, errors, data, retry, operation);
|
|
574
577
|
if (!res.ok) throw new TetherError(statusText(res.status, conf), { status: res.status });
|
|
575
578
|
if (!isData(data)) throw invalidResponse(res, conf);
|
|
576
579
|
return { kind: "data", data };
|
|
@@ -583,14 +586,15 @@
|
|
|
583
586
|
const retryWhileLeft = operation === "mutation" ? "not-run" : "any";
|
|
584
587
|
let retries = 0;
|
|
585
588
|
for (; ; ) {
|
|
586
|
-
const
|
|
589
|
+
const access = { inventory: !storesWithoutInventory.has(store) };
|
|
590
|
+
const sent = queryText(conf, query2, access, { context, operation });
|
|
587
591
|
const retry = retries < conf.retries ? retryWhileLeft : "none";
|
|
588
|
-
const outcome = await attempt(conf, sent, variables, isData, retry);
|
|
592
|
+
const outcome = await attempt(conf, sent, variables, isData, retry, operation);
|
|
589
593
|
switch (outcome.kind) {
|
|
590
594
|
case "data":
|
|
591
595
|
return outcome.data;
|
|
592
596
|
case "inventory-refused":
|
|
593
|
-
if (typeof query2 === "string") throw outcome.error;
|
|
597
|
+
if (typeof query2 === "string" || !access.inventory) throw outcome.error;
|
|
594
598
|
log(`the token can't read inventory: ${INVENTORY_FIELD} is left out from now on`);
|
|
595
599
|
storesWithoutInventory.add(store);
|
|
596
600
|
break;
|
|
@@ -606,9 +610,11 @@
|
|
|
606
610
|
return request(cfg, query2, variables, isData, options);
|
|
607
611
|
}
|
|
608
612
|
var hasData = (data) => typeof data === "object" && data !== null;
|
|
609
|
-
function
|
|
610
|
-
|
|
611
|
-
|
|
613
|
+
function untypedQuery(conf, text2, variables = {}, options) {
|
|
614
|
+
return request(conf, text2, variables, hasData, { ...options, operation: operationOf(text2) });
|
|
615
|
+
}
|
|
616
|
+
function query(text2, variables, options) {
|
|
617
|
+
return untypedQuery(cfg, text2, variables, options);
|
|
612
618
|
}
|
|
613
619
|
function unwrap(payload, name) {
|
|
614
620
|
if (!payload) throw new TetherError(`${name}: empty response`);
|
|
@@ -1680,6 +1686,160 @@
|
|
|
1680
1686
|
return list;
|
|
1681
1687
|
}
|
|
1682
1688
|
|
|
1689
|
+
// src/product-render.ts
|
|
1690
|
+
var NTH_IMAGE_BIND = /^image:(\d+)$/;
|
|
1691
|
+
var METAFIELD_BIND = "metafield:";
|
|
1692
|
+
var MULTI_LINE_METAFIELD = /^(rich_text|multi_line_text)_field$/;
|
|
1693
|
+
var ALL_PLAN_GROUPS = ["", "true", "all", "*"];
|
|
1694
|
+
var isSelect = (el) => el.tagName === "SELECT";
|
|
1695
|
+
var selectsIn = (scope, selector) => scope.$(`select${selector}`).filter(isSelect);
|
|
1696
|
+
function renderGallery(el, product) {
|
|
1697
|
+
const images = product.images.nodes;
|
|
1698
|
+
const rendered = [...el.children].map((node) => node.tagName === "IMG" ? node : node.querySelector("img"));
|
|
1699
|
+
const same = !hasTemplate(el) && rendered.length === images.length && rendered.every((img, index) => sameImage(img?.getAttribute("src"), images[index]?.url));
|
|
1700
|
+
if (same) return;
|
|
1701
|
+
repeat(el, images, (node, image) => {
|
|
1702
|
+
const target = node.matches(`img,${sel("bind", "image")}`) ? node : qsa(node, "img")[0] ?? node;
|
|
1703
|
+
setImage(target, image.url, image.altText || product.title);
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1706
|
+
function renderMetafield(el, product, ref) {
|
|
1707
|
+
const dot = ref.indexOf(".");
|
|
1708
|
+
const namespace = ref.slice(0, dot);
|
|
1709
|
+
const key = ref.slice(dot + 1);
|
|
1710
|
+
const metafield = (product.metafields ?? []).find((field2) => field2?.namespace === namespace && field2.key === key);
|
|
1711
|
+
if (!metafield) {
|
|
1712
|
+
setText(el, "");
|
|
1713
|
+
return;
|
|
1714
|
+
}
|
|
1715
|
+
const image = metafield.reference?.image;
|
|
1716
|
+
if (image) {
|
|
1717
|
+
setImage(el, image.url, image.altText);
|
|
1718
|
+
return;
|
|
1719
|
+
}
|
|
1720
|
+
if (MULTI_LINE_METAFIELD.test(metafield.type)) el.style.whiteSpace = "pre-line";
|
|
1721
|
+
setText(el, metafield.value);
|
|
1722
|
+
}
|
|
1723
|
+
var PRODUCT_TEXTS = new Map(
|
|
1724
|
+
Object.entries({
|
|
1725
|
+
title: (product) => product.title,
|
|
1726
|
+
"description-text": (product) => product.description,
|
|
1727
|
+
vendor: (product) => product.vendor,
|
|
1728
|
+
type: (product) => product.productType,
|
|
1729
|
+
handle: (product) => product.handle,
|
|
1730
|
+
"published-at": (product) => formatDate(product.publishedAt),
|
|
1731
|
+
"min-price": (product) => formatMoney2(product.priceRange.minVariantPrice),
|
|
1732
|
+
"max-price": (product) => formatMoney2(product.priceRange.maxVariantPrice)
|
|
1733
|
+
})
|
|
1734
|
+
);
|
|
1735
|
+
function renderTags(el, product) {
|
|
1736
|
+
const exclude = (el.getAttribute("exclude") ?? "").split(",").map((tag) => tag.trim()).filter(Boolean);
|
|
1737
|
+
const tags = product.tags.filter((tag) => !exclude.includes(tag));
|
|
1738
|
+
repeat(el, tags, (node, tag) => {
|
|
1739
|
+
setText(node, tag);
|
|
1740
|
+
});
|
|
1741
|
+
}
|
|
1742
|
+
function renderProductBind(el, key, product) {
|
|
1743
|
+
const text2 = PRODUCT_TEXTS.get(key);
|
|
1744
|
+
if (text2) {
|
|
1745
|
+
setText(el, text2(product));
|
|
1746
|
+
return;
|
|
1747
|
+
}
|
|
1748
|
+
switch (key) {
|
|
1749
|
+
case "description":
|
|
1750
|
+
setStoreHtml(el, product.descriptionHtml);
|
|
1751
|
+
break;
|
|
1752
|
+
case "featured-image":
|
|
1753
|
+
setImage(el, product.featuredImage?.url, product.featuredImage?.altText || product.title);
|
|
1754
|
+
break;
|
|
1755
|
+
case "url":
|
|
1756
|
+
case "link": {
|
|
1757
|
+
const url2 = productUrl2(product.handle, product.id);
|
|
1758
|
+
if (url2) el.setAttribute("href", url2);
|
|
1759
|
+
if (key === "url" && !el.firstElementChild && !el.textContent.trim()) setText(el, product.title);
|
|
1760
|
+
break;
|
|
1761
|
+
}
|
|
1762
|
+
case "images":
|
|
1763
|
+
renderGallery(el, product);
|
|
1764
|
+
break;
|
|
1765
|
+
case "tags":
|
|
1766
|
+
renderTags(el, product);
|
|
1767
|
+
break;
|
|
1768
|
+
default:
|
|
1769
|
+
renderIndexedBind(el, key, product);
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
function renderIndexedBind(el, key, product) {
|
|
1773
|
+
const nth = NTH_IMAGE_BIND.exec(key);
|
|
1774
|
+
if (nth) {
|
|
1775
|
+
const image = product.images.nodes[Number(nth[1]) - 1] ?? product.featuredImage;
|
|
1776
|
+
setImage(el, image?.url, image?.altText || product.title);
|
|
1777
|
+
} else if (key.startsWith(METAFIELD_BIND)) {
|
|
1778
|
+
renderMetafield(el, product, key.slice(METAFIELD_BIND.length));
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
function renderOptionLists(scope) {
|
|
1782
|
+
const { product } = scope;
|
|
1783
|
+
scope.$(sel("option-list")).forEach((container) => {
|
|
1784
|
+
const name = scope.optName(get(container, "option-list"));
|
|
1785
|
+
const option = product.options.find((candidate) => candidate.name === name);
|
|
1786
|
+
if (!option || option.optionValues.length <= 1 && has(container, "hide-single")) {
|
|
1787
|
+
show(container, false);
|
|
1788
|
+
return;
|
|
1789
|
+
}
|
|
1790
|
+
repeat(container, option.optionValues, (node, value) => {
|
|
1791
|
+
node.setAttribute(attr("option-value"), value.name);
|
|
1792
|
+
const text2 = qsa(node, sel("bind", "option-value"))[0];
|
|
1793
|
+
if (text2) setText(text2, value.name);
|
|
1794
|
+
else if (!node.firstElementChild) setText(node, value.name);
|
|
1795
|
+
const swatchEl = qsa(node, sel("bind", "swatch"))[0];
|
|
1796
|
+
const { swatch } = value;
|
|
1797
|
+
if (!swatchEl || !swatch) return;
|
|
1798
|
+
if (swatch.color) swatchEl.style.backgroundColor = swatch.color;
|
|
1799
|
+
if (swatch.image?.previewImage) setImage(swatchEl, swatch.image.previewImage.url, value.name);
|
|
1800
|
+
});
|
|
1801
|
+
});
|
|
1802
|
+
}
|
|
1803
|
+
function renderSelects(scope) {
|
|
1804
|
+
const { product } = scope;
|
|
1805
|
+
selectsIn(scope, sel("option")).forEach((select) => {
|
|
1806
|
+
const option = product.options.find((candidate) => candidate.name === scope.optName(get(select, "option")));
|
|
1807
|
+
if (!option) {
|
|
1808
|
+
show(select, false);
|
|
1809
|
+
return;
|
|
1810
|
+
}
|
|
1811
|
+
select.replaceChildren(...option.optionValues.map((value) => new Option(value.name, value.name)));
|
|
1812
|
+
});
|
|
1813
|
+
selectsIn(scope, sel("variant-select")).forEach((select) => {
|
|
1814
|
+
select.replaceChildren(...product.variants.nodes.map((variant) => new Option(variant.title, variant.id)));
|
|
1815
|
+
});
|
|
1816
|
+
selectsIn(scope, sel("plan")).forEach((select) => {
|
|
1817
|
+
const plans = scope.plans.map((plan) => new Option(plan.name, plan.id));
|
|
1818
|
+
const oneTime = !product.requiresSellingPlan && get(select, "plan") !== "subscription-only";
|
|
1819
|
+
const oneTimeLabel = select.getAttribute(attr("one-time-label")) || "One-time purchase";
|
|
1820
|
+
select.replaceChildren(...oneTime ? [new Option(oneTimeLabel, "")] : [], ...plans);
|
|
1821
|
+
});
|
|
1822
|
+
}
|
|
1823
|
+
function renderPlanLists(scope) {
|
|
1824
|
+
scope.$(sel("plan-list")).forEach((container) => {
|
|
1825
|
+
const raw = (get(container, "plan-list") ?? "").trim();
|
|
1826
|
+
const group = ALL_PLAN_GROUPS.includes(raw.toLowerCase()) ? null : raw;
|
|
1827
|
+
const plans = scope.plans.filter((plan) => !group || plan.group.name === group);
|
|
1828
|
+
repeat(container, plans, (node, plan) => {
|
|
1829
|
+
node.setAttribute(attr("plan-value"), plan.id);
|
|
1830
|
+
if (!node.firstElementChild && !node.querySelector(sel("plan-bind"))) setText(node, plan.name);
|
|
1831
|
+
});
|
|
1832
|
+
});
|
|
1833
|
+
}
|
|
1834
|
+
function writeProduct(scope) {
|
|
1835
|
+
scope.$(sel("bind")).forEach((el) => {
|
|
1836
|
+
renderProductBind(el, get(el, "bind") ?? "", scope.product);
|
|
1837
|
+
});
|
|
1838
|
+
renderOptionLists(scope);
|
|
1839
|
+
renderSelects(scope);
|
|
1840
|
+
renderPlanLists(scope);
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1683
1843
|
// src/cart/render.ts
|
|
1684
1844
|
var DEFAULT_TITLE = "Default Title";
|
|
1685
1845
|
var quantityOf = (line, pending2) => pending2.get(line.id)?.quantity ?? line.quantity;
|
|
@@ -1781,7 +1941,8 @@
|
|
|
1781
1941
|
if (value !== void 0) setTextTracked(el, value);
|
|
1782
1942
|
});
|
|
1783
1943
|
renderLineState(node, line, view);
|
|
1784
|
-
qsa(node,
|
|
1944
|
+
const planSelects = qsa(node, sel("line-plan")).filter(isSelect);
|
|
1945
|
+
planSelects.forEach((select) => {
|
|
1785
1946
|
getProduct(variant.product.handle).then((product) => {
|
|
1786
1947
|
fillPlanSelect(select, line, product);
|
|
1787
1948
|
}).catch((error) => {
|
|
@@ -2016,7 +2177,9 @@
|
|
|
2016
2177
|
return (error.errors ?? []).some((graphQLError) => UNKNOWN_CART_MESSAGE.test(graphQLError.message));
|
|
2017
2178
|
}
|
|
2018
2179
|
function isUnclearFailure(error) {
|
|
2019
|
-
|
|
2180
|
+
if (!(error instanceof TetherError)) return false;
|
|
2181
|
+
const { code, status: status2 = 0 } = error;
|
|
2182
|
+
return code === "NETWORK" || code === "INVALID_RESPONSE" || code === "SERVER_ERROR" || status2 >= 500;
|
|
2020
2183
|
}
|
|
2021
2184
|
function toLineInput(input, quantity = 1, options = {}) {
|
|
2022
2185
|
const spec = typeof input === "object" && input !== null ? input : { ...options, quantity, ...input === null || input === void 0 ? {} : { variantId: input } };
|
|
@@ -2329,10 +2492,13 @@
|
|
|
2329
2492
|
const ids = Array.isArray(lineIds) ? lineIds : [lineIds];
|
|
2330
2493
|
return runChange(async () => commit(await removeLines(ids), "remove"));
|
|
2331
2494
|
},
|
|
2495
|
+
/** Removes the lines the cart has when the change runs, so one queued just before it is cleared too. */
|
|
2332
2496
|
clear() {
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2497
|
+
return runChange(async () => {
|
|
2498
|
+
const ids = currentLines().map((line) => line.id);
|
|
2499
|
+
if (!ids.length) return currentCart();
|
|
2500
|
+
return commit(await removeLines(ids), "remove");
|
|
2501
|
+
});
|
|
2336
2502
|
},
|
|
2337
2503
|
setNote(note) {
|
|
2338
2504
|
const variables = { note: note ?? "" };
|
|
@@ -2582,170 +2748,18 @@
|
|
|
2582
2748
|
return new Map(Object.entries(texts));
|
|
2583
2749
|
}
|
|
2584
2750
|
|
|
2585
|
-
// src/
|
|
2586
|
-
|
|
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) {
|
|
2751
|
+
// src/uri.ts
|
|
2752
|
+
function decodeOrKeep(text2) {
|
|
2742
2753
|
try {
|
|
2743
|
-
return decodeURIComponent(
|
|
2754
|
+
return decodeURIComponent(text2);
|
|
2744
2755
|
} catch (error) {
|
|
2745
|
-
if (error instanceof URIError) return
|
|
2756
|
+
if (error instanceof URIError) return text2;
|
|
2746
2757
|
throw error;
|
|
2747
2758
|
}
|
|
2748
2759
|
}
|
|
2760
|
+
|
|
2761
|
+
// src/status.ts
|
|
2762
|
+
var URL_SOURCE = "url:";
|
|
2749
2763
|
function resolveProductKey(el, location2 = window.location, name = "product") {
|
|
2750
2764
|
const raw = (get(el, name) ?? "").trim();
|
|
2751
2765
|
if (!raw.toLowerCase().startsWith(URL_SOURCE)) return { key: raw || null, fromUrl: false, raw };
|
|
@@ -2754,7 +2768,7 @@
|
|
|
2754
2768
|
if (source.toLowerCase() === "path") {
|
|
2755
2769
|
const segments = location2.pathname.split("/").filter(Boolean);
|
|
2756
2770
|
const segment = segments[segments.length - 1];
|
|
2757
|
-
key = segment === void 0 ? null :
|
|
2771
|
+
key = segment === void 0 ? null : decodeOrKeep(segment);
|
|
2758
2772
|
} else {
|
|
2759
2773
|
key = new URLSearchParams(location2.search).get(source || "handle");
|
|
2760
2774
|
}
|
|
@@ -3510,9 +3524,10 @@
|
|
|
3510
3524
|
locale: typeof locale === "string" && locale ? locale : void 0
|
|
3511
3525
|
};
|
|
3512
3526
|
}
|
|
3527
|
+
var parseSavedMarket = (text2) => toMarket(parseJsonOrNull(text2));
|
|
3513
3528
|
function readSavedMarket(storage = pageStorage) {
|
|
3514
3529
|
const text2 = storage.getItem(storageKey());
|
|
3515
|
-
return text2 ?
|
|
3530
|
+
return text2 ? parseSavedMarket(text2) : null;
|
|
3516
3531
|
}
|
|
3517
3532
|
|
|
3518
3533
|
// src/page-market.ts
|
|
@@ -3567,7 +3582,7 @@
|
|
|
3567
3582
|
}
|
|
3568
3583
|
|
|
3569
3584
|
// src/part-integrity.ts
|
|
3570
|
-
var PART_INTEGRITY = { "tether.diagnose.js": "sha384-
|
|
3585
|
+
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
3586
|
|
|
3572
3587
|
// src/part-registry.ts
|
|
3573
3588
|
function isTetherInternals(value) {
|
|
@@ -4001,7 +4016,7 @@
|
|
|
4001
4016
|
}
|
|
4002
4017
|
|
|
4003
4018
|
// src/index.ts
|
|
4004
|
-
var VERSION = "0.7.
|
|
4019
|
+
var VERSION = "0.7.2";
|
|
4005
4020
|
var OBSERVE_DEBOUNCE_MS = 50;
|
|
4006
4021
|
function pageConfig() {
|
|
4007
4022
|
const config = pageGlobal("TETHER_CONFIG");
|
package/dist/tether.markets.js
CHANGED
|
@@ -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 ?
|
|
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 ?
|
|
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
|
|
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);})();
|