@occluze/tether 0.9.6 → 0.9.8

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 (58) hide show
  1. package/README.md +1 -1
  2. package/dist/esm/astro.js +1 -1
  3. package/dist/esm/chunks/account-QFGF5FKX.js +1 -0
  4. package/dist/esm/chunks/{account-pages-32IFOHYU.js → account-pages-LMGIPFB7.js} +1 -1
  5. package/dist/esm/chunks/{analytics-OIQ4TFGM.js → analytics-YSTR6H2W.js} +1 -1
  6. package/dist/esm/chunks/{chunk-KW7UPDXI.js → chunk-4BZ4X2Z6.js} +1 -1
  7. package/dist/esm/chunks/{chunk-HZYW2TS3.js → chunk-ADA2ZGPO.js} +1 -1
  8. package/dist/esm/chunks/chunk-B7SC7UOJ.js +1 -0
  9. package/dist/esm/chunks/{chunk-DQJRQBJG.js → chunk-BGUUUMJO.js} +1 -1
  10. package/dist/esm/chunks/{chunk-JJVUNGJZ.js → chunk-GOGPMJ2U.js} +1 -1
  11. package/dist/esm/chunks/{chunk-33IQL4XN.js → chunk-HGNFQHEU.js} +1 -1
  12. package/dist/esm/chunks/{chunk-AMCCY6T4.js → chunk-I54NQEVK.js} +1 -1
  13. package/dist/esm/chunks/{chunk-UDJ62MPR.js → chunk-IBOX3YGQ.js} +1 -1
  14. package/dist/esm/chunks/chunk-KF76466X.js +1 -0
  15. package/dist/esm/chunks/chunk-KH7NEM4B.js +1 -0
  16. package/dist/esm/chunks/{chunk-TES2AUFT.js → chunk-PHTINCRN.js} +1 -1
  17. package/dist/esm/chunks/chunk-QUBBZNJ7.js +1 -0
  18. package/dist/esm/chunks/chunk-R3UWDQL5.js +1 -0
  19. package/dist/esm/chunks/{chunk-U5BYAOTP.js → chunk-SA5G3AUJ.js} +1 -1
  20. package/dist/esm/chunks/{chunk-TUVLYVMF.js → chunk-UJH5ZECZ.js} +1 -1
  21. package/dist/esm/chunks/chunk-XQCBGVU2.js +1 -0
  22. package/dist/esm/chunks/{diagnose-QTIUBMXT.js → diagnose-IOC3BCP5.js} +1 -1
  23. package/dist/esm/chunks/{extras-56DC6CHI.js → extras-5E72QFSJ.js} +1 -1
  24. package/dist/esm/chunks/{lists-SE5VBQ4K.js → lists-35SUHUOX.js} +1 -1
  25. package/dist/esm/chunks/markets-ui-B3ILTPN7.js +1 -0
  26. package/dist/esm/chunks/{search-ZAB5GJOK.js → search-QN457Q2G.js} +1 -1
  27. package/dist/esm/index.js +1 -1
  28. package/dist/esm/server.js +2 -2
  29. package/dist/tether.account.js +24 -11
  30. package/dist/tether.account.min.js +1 -1
  31. package/dist/tether.js +166 -153
  32. package/dist/tether.lists.js +13 -11
  33. package/dist/tether.lists.min.js +1 -1
  34. package/dist/tether.markets.js +12 -0
  35. package/dist/tether.markets.min.js +1 -1
  36. package/dist/tether.min.js +1 -1
  37. package/dist/tether.min.js.map +4 -4
  38. package/dist/types/server/src/shared/serial.d.ts +8 -0
  39. package/dist/types/src/account/server-client.d.ts +3 -1
  40. package/dist/types/src/cart/checkout.d.ts +2 -1
  41. package/dist/types/src/cart/drawer.d.ts +5 -1
  42. package/dist/types/src/cart/mutations.d.ts +13 -13
  43. package/dist/types/src/cart/store.d.ts +8 -4
  44. package/dist/types/src/cart.d.ts +5 -4
  45. package/dist/types/src/config.d.ts +8 -0
  46. package/dist/types/src/fragments.d.ts +0 -2
  47. package/dist/types/src/part-use.d.ts +3 -0
  48. package/dist/types/src/shopify-fields.d.ts +8 -0
  49. package/dist/types/src/version.d.ts +1 -1
  50. package/package.json +5 -2
  51. package/dist/esm/chunks/account-GZLRHV5Z.js +0 -1
  52. package/dist/esm/chunks/chunk-COXH5OXQ.js +0 -1
  53. package/dist/esm/chunks/chunk-ESYKAFMU.js +0 -1
  54. package/dist/esm/chunks/chunk-HO6SNO3A.js +0 -1
  55. package/dist/esm/chunks/chunk-LZINCBME.js +0 -1
  56. package/dist/esm/chunks/chunk-NOTL72DB.js +0 -1
  57. package/dist/esm/chunks/chunk-UU2VVXU2.js +0 -1
  58. package/dist/esm/chunks/markets-ui-GQOUGLUL.js +0 -1
package/dist/tether.js CHANGED
@@ -507,6 +507,19 @@
507
507
  warn("onError threw", hookError);
508
508
  }
509
509
  }
510
+ var reportedHookFailures = /* @__PURE__ */ new Set();
511
+ function callHook(name, hook2, fallback) {
512
+ try {
513
+ return hook2();
514
+ } catch (error) {
515
+ const failure = error instanceof Error && `${name}: ${error.message}`;
516
+ if (!failure || !reportedHookFailures.has(failure)) {
517
+ if (failure) reportedHookFailures.add(failure);
518
+ reportError(error, name);
519
+ }
520
+ return fallback?.();
521
+ }
522
+ }
510
523
 
511
524
  // server/src/shared/error-message.ts
512
525
  function messageOf(error) {
@@ -1035,12 +1048,13 @@
1035
1048
  done();
1036
1049
  return;
1037
1050
  }
1038
- try {
1039
- onLeave(node, done);
1040
- } catch (error) {
1041
- reportError(error, "repeater onLeave");
1042
- done();
1043
- }
1051
+ callHook(
1052
+ "repeater onLeave",
1053
+ () => {
1054
+ onLeave(node, done);
1055
+ },
1056
+ done
1057
+ );
1044
1058
  }
1045
1059
  function insertFresh(container, wanted, fresh, onEnter) {
1046
1060
  wanted.forEach((node, index) => {
@@ -1049,11 +1063,9 @@
1049
1063
  if (previous?.parentNode === container) previous.after(node);
1050
1064
  else container.prepend(node);
1051
1065
  if (!onEnter) return;
1052
- try {
1066
+ callHook("repeater onEnter", () => {
1053
1067
  onEnter(node);
1054
- } catch (error) {
1055
- reportError(error, "repeater onEnter");
1056
- }
1068
+ });
1057
1069
  });
1058
1070
  }
1059
1071
  function repeatKeyed(container, items, keyOf, render2, { onEnter, onLeave } = {}) {
@@ -1125,8 +1137,9 @@
1125
1137
  }
1126
1138
  function formatMoney2(money) {
1127
1139
  if (!money) return "";
1128
- if (cfg.formatMoney) return cfg.formatMoney(money, cfg.locale);
1129
- return formatMoney(money, cfg.locale);
1140
+ const { formatMoney: siteFormat, locale } = cfg;
1141
+ const builtIn = () => formatMoney(money, locale);
1142
+ return siteFormat ? callHook("formatMoney", () => siteFormat(money, locale), builtIn) : builtIn();
1130
1143
  }
1131
1144
  function formatDate(iso) {
1132
1145
  if (!iso) return "";
@@ -1146,13 +1159,8 @@
1146
1159
  function setTextTracked(el, value) {
1147
1160
  const before = readText(el);
1148
1161
  setText(el, value);
1149
- if (before !== readText(el) && el.hasAttribute(SEEN) && cfg.onValueChange) {
1150
- try {
1151
- cfg.onValueChange(el, before);
1152
- } catch (error) {
1153
- reportError(error, "onValueChange");
1154
- }
1155
- }
1162
+ if (before !== readText(el) && el.hasAttribute(SEEN))
1163
+ callHook("onValueChange", () => cfg.onValueChange?.(el, before));
1156
1164
  el.setAttribute(SEEN, "1");
1157
1165
  }
1158
1166
  function reveal(el) {
@@ -1238,12 +1246,10 @@
1238
1246
  function notifyLayoutChanged(reason) {
1239
1247
  clearTimeout(layoutTimer);
1240
1248
  layoutTimer = setTimeout(() => {
1241
- try {
1249
+ callHook("layout-changed", () => {
1242
1250
  if (cfg.onLayoutChange) cfg.onLayoutChange(reason);
1243
1251
  else refreshScrollTrigger();
1244
- } catch (error) {
1245
- reportError(error, "layout-changed");
1246
- }
1252
+ });
1247
1253
  emit("layout-changed", { reason });
1248
1254
  }, LAYOUT_DEBOUNCE_MS);
1249
1255
  }
@@ -1324,11 +1330,13 @@
1324
1330
  return Object.entries(attributes).map(([key, value]) => ({ key, value: String(value ?? "") }));
1325
1331
  }
1326
1332
 
1333
+ // src/shopify-fields.ts
1334
+ var IMAGE_FIELDS = "url altText width height";
1335
+
1327
1336
  // src/fragments.ts
1328
1337
  var MONEY = "amount currencyCode";
1329
1338
  var FULL_ACCESS = { inventory: true };
1330
1339
  var inventoryField = (access) => access.inventory ? "quantityAvailable" : "";
1331
- var IMAGE = "url altText width height";
1332
1340
  function metafieldsField(metafields) {
1333
1341
  const identifiers = [];
1334
1342
  for (const ref of metafields) {
@@ -1337,18 +1345,15 @@
1337
1345
  }
1338
1346
  if (!identifiers.length) return "";
1339
1347
  const list = identifiers.map(({ namespace, key }) => `{namespace: ${JSON.stringify(namespace)}, key: ${JSON.stringify(key)}}`).join(", ");
1340
- return `metafields(identifiers:[${list}]){namespace key type value reference{... on MediaImage{image{${IMAGE}}}}}`;
1348
+ return `metafields(identifiers:[${list}]){namespace key type value reference{... on MediaImage{image{${IMAGE_FIELDS}}}}}`;
1341
1349
  }
1342
1350
  var SELLING_PLAN_FIELDS = ` id name description recurringDeliveries options{name value}priceAdjustments{orderCount adjustmentValue{__typename ... on SellingPlanPercentagePriceAdjustment{adjustmentPercentage}... on SellingPlanFixedAmountPriceAdjustment{adjustmentAmount{${MONEY}}}... on SellingPlanFixedPriceAdjustment{price{${MONEY}}}}}`;
1343
1351
  var ALLOCATION_FIELDS = ` sellingPlan{id}checkoutChargeAmount{${MONEY}}remainingBalanceChargeAmount{${MONEY}}priceAdjustments{price{${MONEY}}compareAtPrice{${MONEY}}perDeliveryPrice{${MONEY}}unitPrice{${MONEY}}}`;
1344
1352
  function productFragment(o = cfg, access = FULL_ACCESS) {
1345
- return ` fragment TetherProduct on Product{id handle title description descriptionHtml productType vendor tags availableForSale publishedAt onlineStoreUrl requiresSellingPlan seo{title description}featuredImage{${IMAGE}}images(first:${o.imagesFirst}){nodes{${IMAGE}}}options{name optionValues{name swatch{color image{previewImage{${IMAGE}}}}}}priceRange{minVariantPrice{${MONEY}}maxVariantPrice{${MONEY}}}compareAtPriceRange{minVariantPrice{${MONEY}}maxVariantPrice{${MONEY}}}${metafieldsField(o.metafields)} sellingPlanGroups(first:${o.sellingPlanGroupsFirst}){nodes{name appName options{name values}sellingPlans(first:${o.sellingPlansFirst}){nodes{${SELLING_PLAN_FIELDS}}}}}variants(first:${o.variantsFirst}){nodes{id title availableForSale currentlyNotInStock ${inventoryField(access)} sku barcode selectedOptions{name value}image{${IMAGE}}price{${MONEY}}compareAtPrice{${MONEY}}unitPrice{${MONEY}}sellingPlanAllocations(first:${o.sellingPlansFirst}){nodes{${ALLOCATION_FIELDS}}}}}}`;
1353
+ return ` fragment TetherProduct on Product{id handle title description descriptionHtml productType vendor tags availableForSale publishedAt onlineStoreUrl requiresSellingPlan seo{title description}featuredImage{${IMAGE_FIELDS}}images(first:${o.imagesFirst}){nodes{${IMAGE_FIELDS}}}options{name optionValues{name swatch{color image{previewImage{${IMAGE_FIELDS}}}}}}priceRange{minVariantPrice{${MONEY}}maxVariantPrice{${MONEY}}}compareAtPriceRange{minVariantPrice{${MONEY}}maxVariantPrice{${MONEY}}}${metafieldsField(o.metafields)} sellingPlanGroups(first:${o.sellingPlanGroupsFirst}){nodes{name appName options{name values}sellingPlans(first:${o.sellingPlansFirst}){nodes{${SELLING_PLAN_FIELDS}}}}}variants(first:${o.variantsFirst}){nodes{id title availableForSale currentlyNotInStock ${inventoryField(access)} sku barcode selectedOptions{name value}image{${IMAGE_FIELDS}}price{${MONEY}}compareAtPrice{${MONEY}}unitPrice{${MONEY}}sellingPlanAllocations(first:${o.sellingPlansFirst}){nodes{${ALLOCATION_FIELDS}}}}}}`;
1346
1354
  }
1347
1355
  function cartFragment(access = FULL_ACCESS) {
1348
- return ` fragment TetherCart on Cart{id checkoutUrl totalQuantity note createdAt updatedAt attributes{key value}buyerIdentity{countryCode email}discountCodes{code applicable}cost{subtotalAmount{${MONEY}}totalAmount{${MONEY}}checkoutChargeAmount{${MONEY}}}lines(first:100){nodes{id quantity attributes{key value}cost{totalAmount{${MONEY}}subtotalAmount{${MONEY}}amountPerQuantity{${MONEY}}compareAtAmountPerQuantity{${MONEY}}}discountAllocations{discountedAmount{${MONEY}}}sellingPlanAllocation{sellingPlan{id name description recurringDeliveries options{name value}}checkoutChargeAmount{${MONEY}}priceAdjustments{price{${MONEY}}compareAtPrice{${MONEY}}perDeliveryPrice{${MONEY}}}}merchandise{... on ProductVariant{id title sku availableForSale requiresShipping ${inventoryField(access)} image{${IMAGE}}price{${MONEY}}compareAtPrice{${MONEY}}selectedOptions{name value}product{id title handle vendor featuredImage{${IMAGE}}}}}... on ComponentizableCartLine{lineComponents{id quantity merchandise{... on ProductVariant{id title product{title handle}}}}}}}}`;
1349
- }
1350
- function collectionFields() {
1351
- return ` id handle title description descriptionHtml image{${IMAGE}}seo{title description}`;
1356
+ return ` fragment TetherCart on Cart{id checkoutUrl totalQuantity note createdAt updatedAt attributes{key value}buyerIdentity{countryCode email}discountCodes{code applicable}cost{subtotalAmount{${MONEY}}totalAmount{${MONEY}}checkoutChargeAmount{${MONEY}}}lines(first:100){nodes{id quantity attributes{key value}cost{totalAmount{${MONEY}}subtotalAmount{${MONEY}}amountPerQuantity{${MONEY}}compareAtAmountPerQuantity{${MONEY}}}discountAllocations{discountedAmount{${MONEY}}}sellingPlanAllocation{sellingPlan{id name description recurringDeliveries options{name value}}checkoutChargeAmount{${MONEY}}priceAdjustments{price{${MONEY}}compareAtPrice{${MONEY}}perDeliveryPrice{${MONEY}}}}merchandise{... on ProductVariant{id title sku availableForSale requiresShipping ${inventoryField(access)} image{${IMAGE_FIELDS}}price{${MONEY}}compareAtPrice{${MONEY}}selectedOptions{name value}product{id title handle vendor featuredImage{${IMAGE_FIELDS}}}}}... on ComponentizableCartLine{lineComponents{id quantity merchandise{... on ProductVariant{id title product{title handle}}}}}}}}`;
1352
1357
  }
1353
1358
 
1354
1359
  // src/selling-plans.ts
@@ -1529,14 +1534,7 @@
1529
1534
  var openWithoutDrawer = false;
1530
1535
  var announcedOpen = false;
1531
1536
  var returnFocus = null;
1532
- var classWatcher = null;
1533
- function callHook(hook2, drawers2, name) {
1534
- try {
1535
- hook2?.(drawers2);
1536
- } catch (error) {
1537
- reportError(error, name);
1538
- }
1539
- }
1537
+ var pageWatcher = null;
1540
1538
  var isFocusable = (el) => el !== null && "focus" in el;
1541
1539
  var focusables = (drawer) => qsa(drawer, FOCUSABLE).filter((el) => el.offsetParent !== null || el === document.activeElement);
1542
1540
  var drawers = () => qsa(document, sel("cart-drawer"));
@@ -1544,18 +1542,15 @@
1544
1542
  var hasFocusInside = (all) => all.some((drawer) => drawer.contains(document.activeElement));
1545
1543
  var isManual = (drawer) => get(drawer, "cart-drawer") === "manual";
1546
1544
  function isOpen() {
1545
+ const openClassed = [...document.getElementsByClassName(cfg.cartDrawerOpenClass)];
1546
+ return openClassed.some((el) => el.matches(sel("cart-drawer"))) || openWithoutDrawer && !drawers().length;
1547
+ }
1548
+ function announceChange() {
1549
+ const open = isOpen();
1550
+ if (open === announcedOpen) return;
1547
1551
  const all = drawers();
1548
- return all.length ? all.some(isOpenDrawer) : openWithoutDrawer;
1549
- }
1550
- function watchOpenClass(drawer) {
1551
- classWatcher ?? (classWatcher = new MutationObserver(() => {
1552
- const open = isOpen();
1553
- if (open === announcedOpen) return;
1554
- const all = drawers();
1555
- if (open) announceOpen(all.filter(isOpenDrawer));
1556
- else announceClosed(all, hasFocusInside(all));
1557
- }));
1558
- classWatcher.observe(drawer, { attributes: true, attributeFilter: ["class"] });
1552
+ if (open) announceOpen(all.filter(isOpenDrawer));
1553
+ else announceClosed(all, hasFocusInside(all));
1559
1554
  }
1560
1555
  function syncDrawerAria() {
1561
1556
  qsa(document, sel("cart-open")).forEach((button) => {
@@ -1570,7 +1565,14 @@
1570
1565
  drawer.setAttribute("aria-modal", String(open));
1571
1566
  drawer.setAttribute("aria-hidden", String(!open));
1572
1567
  drawer.inert = !open;
1573
- watchOpenClass(drawer);
1568
+ });
1569
+ if (pageWatcher) return;
1570
+ pageWatcher = new MutationObserver(announceChange);
1571
+ pageWatcher.observe(document.documentElement, {
1572
+ attributes: true,
1573
+ attributeFilter: ["class"],
1574
+ childList: true,
1575
+ subtree: true
1574
1576
  });
1575
1577
  }
1576
1578
  function focusInto(drawer) {
@@ -1588,15 +1590,16 @@
1588
1590
  focusInto(first);
1589
1591
  }, FOCUS_AFTER_OPEN_MS);
1590
1592
  }
1591
- callHook(cfg.onCartOpen, opened, "onCartOpen");
1593
+ callHook("onCartOpen", () => cfg.onCartOpen?.(opened));
1592
1594
  emit("cart-toggled", { open: true });
1593
1595
  }
1594
1596
  function announceClosed(all, hadFocus) {
1595
1597
  announcedOpen = false;
1598
+ openWithoutDrawer = false;
1596
1599
  syncDrawerAria();
1597
1600
  if (hadFocus && returnFocus?.isConnected) returnFocus.focus({ preventScroll: true });
1598
1601
  returnFocus = null;
1599
- callHook(cfg.onCartClose, all, "onCartClose");
1602
+ callHook("onCartClose", () => cfg.onCartClose?.(all));
1600
1603
  emit("cart-toggled", { open: false });
1601
1604
  }
1602
1605
  function openCart() {
@@ -1604,7 +1607,7 @@
1604
1607
  const all = drawers();
1605
1608
  const opened = all.filter((drawer) => !isManual(drawer));
1606
1609
  if (all.length && !opened.length) return;
1607
- openWithoutDrawer = true;
1610
+ openWithoutDrawer = !all.length;
1608
1611
  opened.forEach((drawer) => {
1609
1612
  drawer.classList.add(cfg.cartDrawerOpenClass);
1610
1613
  });
@@ -1612,7 +1615,6 @@
1612
1615
  }
1613
1616
  function closeCart() {
1614
1617
  if (!isOpen()) return;
1615
- openWithoutDrawer = false;
1616
1618
  const all = drawers();
1617
1619
  const hadFocus = hasFocusInside(all);
1618
1620
  all.forEach((drawer) => {
@@ -2151,6 +2153,17 @@
2151
2153
  // server/src/shared/cart-id.ts
2152
2154
  var CART_ID = /^gid:\/\/shopify\/Cart\/[\w-]+(\?key=[\w-]+)?$/;
2153
2155
 
2156
+ // server/src/shared/serial.ts
2157
+ var settled = () => void 0;
2158
+ function createSerialQueue() {
2159
+ let tail = Promise.resolve();
2160
+ return (task) => {
2161
+ const result = tail.then(task);
2162
+ tail = result.then(settled, settled);
2163
+ return result;
2164
+ };
2165
+ }
2166
+
2154
2167
  // src/cart/store.ts
2155
2168
  var status = { kind: "unknown" };
2156
2169
  var warnings = [];
@@ -2216,19 +2229,23 @@
2216
2229
  if (count !== null) showSavedCount(count);
2217
2230
  }
2218
2231
  function setWarnings(notes) {
2219
- warnings = notes.filter((note, index) => notes.findIndex((other) => other.message === note.message) === index).map((note) => ({ ...note, message: cfg.warningText?.(note) || note.message }));
2232
+ const siteText = (note) => callHook(
2233
+ "warningText",
2234
+ () => cfg.warningText?.(note),
2235
+ () => null
2236
+ );
2237
+ warnings = notes.filter((note, index) => notes.findIndex((other) => other.message === note.message) === index).map((note) => ({ ...note, message: siteText(note) || note.message }));
2220
2238
  if (warnings.length) emit("cart-warning", { warnings });
2221
2239
  }
2222
- var waitOnly = () => void 0;
2223
- function serial() {
2224
- let previous = Promise.resolve();
2225
- return (task) => {
2226
- const run = previous.then(task);
2227
- previous = run.then(waitOnly, waitOnly);
2228
- return run;
2229
- };
2240
+ var runInOrder = createSerialQueue();
2241
+ var fillingTasks = 0;
2242
+ function queueFilling(queue) {
2243
+ fillingTasks++;
2244
+ return queue().finally(() => {
2245
+ fillingTasks--;
2246
+ });
2230
2247
  }
2231
- var runInOrder = serial();
2248
+ var mayFill = () => fillingTasks > 0;
2232
2249
  function enqueue(task) {
2233
2250
  return runInOrder(task).then(
2234
2251
  (value) => {
@@ -2307,17 +2324,15 @@
2307
2324
  const withIdentity = cfg.country ? { buyerIdentity: { countryCode: cfg.country }, ...input } : input;
2308
2325
  return send("cartCreate", "$input: CartInput!", "input: $input", { input: withIdentity });
2309
2326
  }
2310
- async function mutateCart({
2311
- name,
2312
- args,
2313
- inner,
2314
- variables,
2315
- createInput
2316
- }) {
2327
+ async function mutateCart({ name, variable, type, value, create }) {
2328
+ const createInput = create ? { [variable]: value } : null;
2317
2329
  const cartId = savedCartId();
2318
2330
  if (!cartId) return createInput ? createCart(createInput) : null;
2319
2331
  try {
2320
- return await send(name, `$cartId: ID!, ${args}`, `cartId: $cartId, ${inner}`, { ...variables, cartId });
2332
+ return await send(name, `$cartId: ID!, $${variable}: ${type}`, `cartId: $cartId, ${variable}: $${variable}`, {
2333
+ [variable]: value,
2334
+ cartId
2335
+ });
2321
2336
  } catch (error) {
2322
2337
  if (!isCartGone(error)) throw error;
2323
2338
  forgetSavedCart();
@@ -2355,17 +2370,17 @@
2355
2370
  }
2356
2371
  var updateLines = (lines) => mutateCart({
2357
2372
  name: "cartLinesUpdate",
2358
- args: "$lines: [CartLineUpdateInput!]!",
2359
- inner: "lines: $lines",
2360
- variables: { lines },
2361
- createInput: null
2373
+ variable: "lines",
2374
+ type: "[CartLineUpdateInput!]!",
2375
+ value: lines,
2376
+ create: false
2362
2377
  });
2363
2378
  var removeLines = (lineIds) => mutateCart({
2364
2379
  name: "cartLinesRemove",
2365
- args: "$lineIds: [ID!]!",
2366
- inner: "lineIds: $lineIds",
2367
- variables: { lineIds },
2368
- createInput: null
2380
+ variable: "lineIds",
2381
+ type: "[ID!]!",
2382
+ value: lineIds,
2383
+ create: false
2369
2384
  });
2370
2385
  var setLineQuantity = (lineId, target) => target > 0 ? updateLines([{ id: lineId, quantity: target }]) : removeLines([lineId]);
2371
2386
 
@@ -2408,7 +2423,7 @@
2408
2423
  return cart && !cart.totalQuantity ? null : savedCartId();
2409
2424
  }
2410
2425
  async function checkout(target = cfg.checkoutTarget) {
2411
- if (!cartToCheckOut()) return null;
2426
+ if (!cartToCheckOut() && !mayFill()) return null;
2412
2427
  const tab = target === "_blank" ? window.open("", "_blank") : null;
2413
2428
  if (tab) detachOpenerIfAllowed(tab);
2414
2429
  try {
@@ -2444,7 +2459,9 @@
2444
2459
  reportError(error, "cart reload after a failed change");
2445
2460
  }
2446
2461
  }
2462
+ var queuedLoad = null;
2447
2463
  function runChange(task) {
2464
+ queuedLoad = null;
2448
2465
  return enqueue(
2449
2466
  () => task().catch(async (error) => {
2450
2467
  if (isUnclearFailure(error)) await reloadAfterUnclearFailure();
@@ -2487,7 +2504,7 @@
2487
2504
  toAttributes(attributes).forEach((attribute) => merged.set(attribute.key, attribute.value));
2488
2505
  return [...merged].filter(([, value]) => value !== "").map(([key, value]) => ({ key, value }));
2489
2506
  }
2490
- async function init() {
2507
+ async function load() {
2491
2508
  const id = savedCartId();
2492
2509
  if (!id) {
2493
2510
  settleLoad({ kind: "loaded", cart: null });
@@ -2505,8 +2522,17 @@
2505
2522
  }
2506
2523
  return currentCart();
2507
2524
  }
2525
+ function reload() {
2526
+ queuedLoad ?? (queuedLoad = queueFilling(
2527
+ () => runInOrder(() => {
2528
+ queuedLoad = null;
2529
+ return load();
2530
+ })
2531
+ ));
2532
+ return queuedLoad;
2533
+ }
2508
2534
  var Cart = {
2509
- init,
2535
+ init: reload,
2510
2536
  /** The saved cart's id. */
2511
2537
  id: savedCartId,
2512
2538
  get status() {
@@ -2568,20 +2594,22 @@
2568
2594
  const lines = (Array.isArray(input) ? input : [input]).map(
2569
2595
  (line) => toLineInput(line, quantity, options)
2570
2596
  );
2571
- return runChange(async () => {
2572
- const cart = await mutateCart({
2573
- name: "cartLinesAdd",
2574
- args: "$lines: [CartLineInput!]!",
2575
- inner: "lines: $lines",
2576
- variables: { lines },
2577
- createInput: { lines }
2578
- });
2579
- if (!cart) throw new TetherError("Shopify answered the add without a cart");
2580
- commit(cart, "add");
2581
- emit("added", { cart, lines });
2582
- if (cfg.openCartOnAdd) openCart();
2583
- return cart;
2584
- });
2597
+ return queueFilling(
2598
+ () => runChange(async () => {
2599
+ const cart = await mutateCart({
2600
+ name: "cartLinesAdd",
2601
+ variable: "lines",
2602
+ type: "[CartLineInput!]!",
2603
+ value: lines,
2604
+ create: true
2605
+ });
2606
+ if (!cart) throw new TetherError("Shopify answered the add without a cart");
2607
+ commit(cart, "add");
2608
+ emit("added", { cart, lines });
2609
+ if (cfg.openCartOnAdd) openCart();
2610
+ return cart;
2611
+ })
2612
+ );
2585
2613
  },
2586
2614
  /**
2587
2615
  * `updateLine(lineId, 3)` or `updateLine(lineId, { quantity, sellingPlanId, attributes })`.
@@ -2610,15 +2638,14 @@
2610
2638
  });
2611
2639
  },
2612
2640
  setNote(note) {
2613
- const variables = { note: note ?? "" };
2614
2641
  return runChange(
2615
2642
  async () => commit(
2616
2643
  await mutateCart({
2617
2644
  name: "cartNoteUpdate",
2618
- args: "$note: String!",
2619
- inner: "note: $note",
2620
- variables,
2621
- createInput: variables
2645
+ variable: "note",
2646
+ type: "String!",
2647
+ value: note ?? "",
2648
+ create: true
2622
2649
  }),
2623
2650
  "note"
2624
2651
  )
@@ -2631,13 +2658,12 @@
2631
2658
  */
2632
2659
  setAttributes(attributes) {
2633
2660
  return runChange(async () => {
2634
- const variables = { attributes: mergedAttributes(attributes) };
2635
2661
  const cart = await mutateCart({
2636
2662
  name: "cartAttributesUpdate",
2637
- args: "$attributes: [AttributeInput!]!",
2638
- inner: "attributes: $attributes",
2639
- variables,
2640
- createInput: variables
2663
+ variable: "attributes",
2664
+ type: "[AttributeInput!]!",
2665
+ value: mergedAttributes(attributes),
2666
+ create: true
2641
2667
  });
2642
2668
  return commit(cart, "attributes");
2643
2669
  });
@@ -2645,13 +2671,12 @@
2645
2671
  /** Replaces the discount codes; `[]` removes them all. */
2646
2672
  setDiscountCodes(codes) {
2647
2673
  return runChange(async () => {
2648
- const variables = { discountCodes: discountCodesFrom(codes) };
2649
2674
  const cart = await mutateCart({
2650
2675
  name: "cartDiscountCodesUpdate",
2651
- args: "$discountCodes: [String!]!",
2652
- inner: "discountCodes: $discountCodes",
2653
- variables,
2654
- createInput: variables
2676
+ variable: "discountCodes",
2677
+ type: "[String!]!",
2678
+ value: discountCodesFrom(codes),
2679
+ create: true
2655
2680
  });
2656
2681
  return commit(cart, "discount");
2657
2682
  });
@@ -2688,10 +2713,10 @@
2688
2713
  return runChange(async () => {
2689
2714
  const cart = await mutateCart({
2690
2715
  name: "cartBuyerIdentityUpdate",
2691
- args: "$buyerIdentity: CartBuyerIdentityInput!",
2692
- inner: "buyerIdentity: $buyerIdentity",
2693
- variables: { buyerIdentity },
2694
- createInput: create ? { buyerIdentity } : null
2716
+ variable: "buyerIdentity",
2717
+ type: "CartBuyerIdentityInput!",
2718
+ value: buyerIdentity,
2719
+ create
2695
2720
  }).catch((error) => {
2696
2721
  if (create || !isCartGone(error)) throw error;
2697
2722
  return null;
@@ -3590,7 +3615,7 @@
3590
3615
  }
3591
3616
 
3592
3617
  // src/part-integrity.ts
3593
- var PART_INTEGRITY = { "tether.diagnose.js": "sha384-CqtXzvWbLD8aIgyTM43+KMXEFA7r7lhG+0XyQAw3Sp7B5qrzPsxlA9QfzBjoPqZz", "tether.markets.js": "sha384-WjowbRhM7OzzZOrCPZWSZqN7EjIiiR7u9cGmdI+9kgFVgmEQS8lVGWjgx+8jILOf", "tether.search.js": "sha384-fLQ7eKc5XOv0Cg2FfrZyeFAkRR4wDMjUWFpwvKrfPRnT2NvTuhKg80+KVu8Qce/G", "tether.lists.js": "sha384-l2uyr96zTetjo2WWhGsBamd1ZYkC3OB3G3+OScLEvxdok0c8k9GXLAh1WRALUr4S", "tether.extras.js": "sha384-qx7paZ/rjwtn1Yy9TgszulmBuJsIQ9y4eZ590AArnZ+IDB8IzwJ5dNOFJ+yMHPdb", "tether.account.js": "sha384-XUPSX/7R9chq2KlQ1RzLiV7jYcWGe7o5tj4rLZMnf8MEa2aDOOCW2269Bj/ZkbmX", "tether.account-pages.js": "sha384-ND3kIaRypgnHG3QMDb8CqDxt7fuukDCdHsIAHoOUUsz3+FjvBqXgRDV4Mjp6x8jr", "tether.analytics.js": "sha384-jnLesn/+edWBSPuXLj7VX1kSAGwEqtb0VbHjuU//ofqgxkndHlDFsS8Bc8htlGt8" };
3618
+ var PART_INTEGRITY = { "tether.diagnose.js": "sha384-CqtXzvWbLD8aIgyTM43+KMXEFA7r7lhG+0XyQAw3Sp7B5qrzPsxlA9QfzBjoPqZz", "tether.markets.js": "sha384-4UK4+noZOE06Ra3Eyin9kAUXz/bbvcbq3gvdwNBItnPCQzmPyD398YoM0P1aTL0Q", "tether.search.js": "sha384-fLQ7eKc5XOv0Cg2FfrZyeFAkRR4wDMjUWFpwvKrfPRnT2NvTuhKg80+KVu8Qce/G", "tether.lists.js": "sha384-C+ibx3RT6OStQI+eq0K+ai44lQsHeI4iueLoZaW/+AqVZ7D+gcjoHiohd0CFyNUd", "tether.extras.js": "sha384-qx7paZ/rjwtn1Yy9TgszulmBuJsIQ9y4eZ590AArnZ+IDB8IzwJ5dNOFJ+yMHPdb", "tether.account.js": "sha384-A5LC6eOq1My82IYPD0qA/NKhefGuBvA+9vwY7l/t0S40/SwIjWCBXJIO3YNyYGPc", "tether.account-pages.js": "sha384-ND3kIaRypgnHG3QMDb8CqDxt7fuukDCdHsIAHoOUUsz3+FjvBqXgRDV4Mjp6x8jr", "tether.analytics.js": "sha384-jnLesn/+edWBSPuXLj7VX1kSAGwEqtb0VbHjuU//ofqgxkndHlDFsS8Bc8htlGt8" };
3594
3619
 
3595
3620
  // src/part-registry.ts
3596
3621
  function isTetherInternals(value) {
@@ -3598,7 +3623,7 @@
3598
3623
  }
3599
3624
 
3600
3625
  // src/version.ts
3601
- var VERSION = "0.9.6";
3626
+ var VERSION = "0.9.8";
3602
3627
 
3603
3628
  // src/lazy-iife.ts
3604
3629
  var coreModules = {
@@ -3638,9 +3663,6 @@
3638
3663
  get "loader.ts"() {
3639
3664
  return [clearProductCache, getProduct, normalizeProductKey, primeProduct, withProductFragment];
3640
3665
  },
3641
- get "fragments.ts"() {
3642
- return [collectionFields];
3643
- },
3644
3666
  get "selling-plans.ts"() {
3645
3667
  return [allPlans];
3646
3668
  },
@@ -3757,7 +3779,7 @@
3757
3779
  }
3758
3780
 
3759
3781
  // src/analytics-queue.ts
3760
- function queueAnalyticsEvents(load) {
3782
+ function queueAnalyticsEvents(load2) {
3761
3783
  const queue = [];
3762
3784
  const listening = new window.AbortController();
3763
3785
  const options = { signal: listening.signal };
@@ -3765,7 +3787,7 @@
3765
3787
  document.addEventListener(`${cfg.prefix}:${name}`, (event) => queue.push(event), options);
3766
3788
  });
3767
3789
  document.addEventListener("astro:page-load", (event) => queue.push(event), options);
3768
- load().then((part) => part.startAnalytics(queue)).catch((error) => {
3790
+ load2().then((part) => part.startAnalytics(queue)).catch((error) => {
3769
3791
  listening.abort();
3770
3792
  queue.length = 0;
3771
3793
  reportError(error, "analytics");
@@ -3785,6 +3807,13 @@
3785
3807
  }
3786
3808
  var isLoginOutcome = (value) => value === "in" || value === "expired" || value === "error";
3787
3809
 
3810
+ // src/part-use.ts
3811
+ function withPart(name, use) {
3812
+ loadPart(name).then(use).catch((error) => {
3813
+ reportError(error, name);
3814
+ });
3815
+ }
3816
+
3788
3817
  // src/account-api.ts
3789
3818
  var ACCOUNT_ATTRIBUTES = [
3790
3819
  "account-login",
@@ -3805,9 +3834,7 @@
3805
3834
  if (!cfg.account) return;
3806
3835
  const needed = within(root, accountSelector()).length > 0 || isLoginOutcome(new URLSearchParams(window.location.search).get("account")) || hasLoginHint();
3807
3836
  if (!needed) return;
3808
- loadPart("account").then((part) => part.mountAccount(root)).catch((error) => {
3809
- reportError(error, "account");
3810
- });
3837
+ withPart("account", (part) => part.mountAccount(root));
3811
3838
  }
3812
3839
  function fromPart(name) {
3813
3840
  return (...args) => loadPart("account").then((part) => {
@@ -3986,30 +4013,29 @@
3986
4013
 
3987
4014
  // src/controls/extras.ts
3988
4015
  var addGroup = (button) => loadPart("extras").then((part) => part.addGroup(button));
3989
- var reportExtrasError = (error) => {
3990
- reportError(error, "extras");
3991
- };
3992
4016
  function onClick4(event) {
3993
4017
  const { target } = event;
3994
4018
  const button = target instanceof window.Element ? target.closest(sel("group-add")) : null;
3995
4019
  if (!button) return;
3996
4020
  event.preventDefault();
3997
- busy(button, () => addGroup(button)).catch(reportExtrasError);
4021
+ busy(button, () => addGroup(button)).catch((error) => {
4022
+ reportError(error, "extras");
4023
+ });
3998
4024
  }
3999
4025
  function onStorage(event) {
4000
4026
  if (!cfg.domain || !event.key?.startsWith(`${cfg.prefix}:`)) return;
4001
- loadPart("extras").then((part) => {
4027
+ withPart("extras", (part) => {
4002
4028
  part.onStorage(event);
4003
- }).catch(reportExtrasError);
4029
+ });
4004
4030
  }
4005
4031
  function onVariantChanged(event) {
4006
4032
  if (!isOwnEvent(event, "variant-changed")) return;
4007
4033
  const { target } = event;
4008
4034
  if (!(target instanceof window.Element)) return;
4009
4035
  if (!cfg.variantUrl && !target.hasAttribute(attr("variant-url"))) return;
4010
- loadPart("extras").then((part) => {
4036
+ withPart("extras", (part) => {
4011
4037
  part.writeVariantUrl(target, event.detail);
4012
- }).catch(reportExtrasError);
4038
+ });
4013
4039
  }
4014
4040
  function bindExtrasControls() {
4015
4041
  document.addEventListener("click", onClick4);
@@ -4047,14 +4073,6 @@
4047
4073
  hooks.unmount();
4048
4074
  });
4049
4075
  }
4050
- function onChange3(event) {
4051
- const { target } = event;
4052
- if (!(target instanceof window.HTMLSelectElement) || !target.matches(sel("country-select"))) return;
4053
- if (!target.value) return;
4054
- setCountry(target.value).catch((error) => {
4055
- reportError(error, "country");
4056
- });
4057
- }
4058
4076
  function onOnline() {
4059
4077
  retryFailed();
4060
4078
  liveLists.forEach((list) => {
@@ -4063,7 +4081,6 @@
4063
4081
  }
4064
4082
  function bindNavigation(hooks) {
4065
4083
  if (cfg.astro) bindAstroRouter(hooks);
4066
- document.addEventListener("change", onChange3);
4067
4084
  window.addEventListener("online", onOnline);
4068
4085
  }
4069
4086
 
@@ -4094,16 +4111,12 @@
4094
4111
  }
4095
4112
  function mountParts(root) {
4096
4113
  if (within(root, `${sel("country-select")},${sel("country-bind")}`).length) {
4097
- loadPart("markets").then((part) => part.renderCountrySelects(root)).catch((error) => {
4098
- reportError(error, "markets");
4099
- });
4114
+ withPart("markets", (part) => part.renderCountrySelects(root));
4100
4115
  }
4101
4116
  mountAccountIfUsed(root);
4102
4117
  if (within(root, sel("search")).length) {
4103
- loadPart("search").then((part) => {
4118
+ withPart("search", (part) => {
4104
4119
  part.mountSearch(root);
4105
- }).catch((error) => {
4106
- reportError(error, "search");
4107
4120
  });
4108
4121
  }
4109
4122
  }
@@ -4158,7 +4171,7 @@
4158
4171
  async function cartInPageMarket(cart) {
4159
4172
  const country = cfg.country;
4160
4173
  const cartCountry = cart?.buyerIdentity.countryCode;
4161
- if (!cart || !country || !cartCountry || cartCountry === country) return cart;
4174
+ if (!country || !cartCountry || cartCountry === country) return cart;
4162
4175
  try {
4163
4176
  return await Cart.setBuyerIdentity({ countryCode: country }, { create: false });
4164
4177
  } catch (error) {
@@ -4166,7 +4179,7 @@
4166
4179
  return cart;
4167
4180
  }
4168
4181
  }
4169
- function init2(overrides = {}) {
4182
+ function init(overrides = {}) {
4170
4183
  if (initPromise && !Object.keys(overrides).length) return initPromise;
4171
4184
  configure({ ...pageConfig(), ...overrides });
4172
4185
  if (!isConfigured()) {
@@ -4220,7 +4233,7 @@
4220
4233
  }
4221
4234
  var publicApi = {
4222
4235
  VERSION,
4223
- init: init2,
4236
+ init,
4224
4237
  mount,
4225
4238
  unmount,
4226
4239
  /** The live config, read-only. */
@@ -4261,7 +4274,7 @@
4261
4274
  const config = pageGlobal("TETHER_CONFIG");
4262
4275
  if (!config || field(config, "autoMount") === false || pageGlobal("TETHER_INTEGRATION")) return;
4263
4276
  const start = () => {
4264
- init2().then(() => mount(document)).catch((error) => {
4277
+ init().then(() => mount(document)).catch((error) => {
4265
4278
  reportError(error, "init");
4266
4279
  });
4267
4280
  };