@occluze/tether 0.6.7 → 0.6.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 (135) hide show
  1. package/README.md +3 -3
  2. package/dist/esm/astro.js +2 -2
  3. package/dist/esm/chunks/account-C3NP6HFB.js +1 -0
  4. package/dist/esm/chunks/account-pages-WLK374FO.js +1 -0
  5. package/dist/esm/chunks/analytics-G3SAWMNL.js +1 -0
  6. package/dist/esm/chunks/chunk-27PJJZGC.js +1 -0
  7. package/dist/esm/chunks/chunk-2FSXS55U.js +1 -0
  8. package/dist/esm/chunks/chunk-FCSWQDVV.js +1 -0
  9. package/dist/esm/chunks/chunk-FOMSMIAM.js +1 -0
  10. package/dist/esm/chunks/chunk-GZJTCLLW.js +1 -0
  11. package/dist/esm/chunks/chunk-HEQILZVR.js +1 -0
  12. package/dist/esm/chunks/chunk-JOOEXYF3.js +4 -0
  13. package/dist/esm/chunks/chunk-MPTQYLSM.js +1 -0
  14. package/dist/esm/chunks/chunk-NEHZ37TU.js +3 -0
  15. package/dist/esm/chunks/chunk-V74KGEJF.js +1 -0
  16. package/dist/esm/chunks/chunk-VT4CDUJJ.js +1 -0
  17. package/dist/esm/chunks/chunk-YJLWX2HK.js +1 -0
  18. package/dist/esm/chunks/diagnose-6VVGZNTY.js +14 -0
  19. package/dist/esm/chunks/extras-GJVRDFM3.js +1 -0
  20. package/dist/esm/chunks/markets-ui-UNB4PTA7.js +1 -0
  21. package/dist/esm/chunks/search-OU75RNQL.js +1 -0
  22. package/dist/esm/index.js +1 -1
  23. package/dist/esm/server.js +2 -1
  24. package/dist/presets/barba.esm.js +56 -36
  25. package/dist/tether.account-pages.js +773 -442
  26. package/dist/tether.account-pages.min.js +1 -1
  27. package/dist/tether.account.js +648 -318
  28. package/dist/tether.account.min.js +1 -1
  29. package/dist/tether.analytics.js +318 -191
  30. package/dist/tether.analytics.min.js +1 -1
  31. package/dist/tether.diagnose.js +331 -242
  32. package/dist/tether.diagnose.min.js +2 -2
  33. package/dist/tether.extras.js +78 -33
  34. package/dist/tether.extras.min.js +1 -1
  35. package/dist/tether.js +3176 -2015
  36. package/dist/tether.markets.js +231 -126
  37. package/dist/tether.markets.min.js +1 -1
  38. package/dist/tether.min.js +0 -0
  39. package/dist/tether.min.js.map +4 -4
  40. package/dist/tether.search.js +221 -126
  41. package/dist/tether.search.min.js +1 -1
  42. package/package.json +23 -4
  43. package/src/account/addresses-view.js +92 -0
  44. package/src/account/browser-session.js +359 -0
  45. package/src/account/markup.js +48 -0
  46. package/src/account/operations.js +180 -0
  47. package/src/account/order-lines.js +96 -0
  48. package/src/account/order-list.js +91 -0
  49. package/src/account/order-page.js +192 -0
  50. package/src/account/page-events.js +288 -0
  51. package/src/account/server-client.js +172 -0
  52. package/src/account/shared.js +111 -0
  53. package/src/account/shopify-auth.js +150 -0
  54. package/src/account/subscriptions-view.js +158 -0
  55. package/src/account-api.js +118 -0
  56. package/src/account-links.js +35 -0
  57. package/src/account-pages.js +69 -298
  58. package/src/account.js +280 -323
  59. package/src/amounts.js +36 -0
  60. package/src/analytics-shopify.js +241 -0
  61. package/src/analytics.js +304 -184
  62. package/src/api-version.js +75 -25
  63. package/src/astro.js +233 -68
  64. package/src/cart/checkout.js +97 -0
  65. package/src/cart/drawer.js +138 -0
  66. package/src/cart/mutations.js +234 -0
  67. package/src/cart/render.js +294 -0
  68. package/src/cart/store.js +326 -0
  69. package/src/cart.js +320 -488
  70. package/src/client.js +214 -78
  71. package/src/collection.js +126 -57
  72. package/src/config.js +323 -59
  73. package/src/controls/cart-controls.js +155 -0
  74. package/src/controls/discount.js +96 -0
  75. package/src/controls/extras.js +63 -0
  76. package/src/controls/navigation.js +83 -0
  77. package/src/diagnose-markup.js +333 -0
  78. package/src/diagnose.js +251 -202
  79. package/src/dom.js +219 -220
  80. package/src/extras.js +119 -37
  81. package/src/fragments.js +115 -22
  82. package/src/images.js +104 -0
  83. package/src/index.js +245 -287
  84. package/src/initial.js +78 -66
  85. package/src/lazy-iife.js +92 -22
  86. package/src/lazy.js +25 -4
  87. package/src/loader.js +263 -124
  88. package/src/market-codes.js +35 -0
  89. package/src/markets-ui.js +169 -55
  90. package/src/markets.js +286 -85
  91. package/src/markup.js +64 -0
  92. package/src/mounting.js +214 -91
  93. package/src/page-market.js +116 -0
  94. package/src/parts/account-pages.js +4 -1
  95. package/src/parts/account.js +4 -1
  96. package/src/parts/analytics.js +4 -1
  97. package/src/parts/diagnose.js +4 -1
  98. package/src/parts/extras.js +4 -1
  99. package/src/parts/markets.js +4 -1
  100. package/src/parts/search.js +4 -1
  101. package/src/presets/barba.js +120 -30
  102. package/src/product-events.js +130 -0
  103. package/src/product-render.js +257 -0
  104. package/src/product-state.js +318 -0
  105. package/src/product.js +233 -459
  106. package/src/repeaters.js +173 -0
  107. package/src/search.js +277 -107
  108. package/src/selling-plans.js +107 -47
  109. package/src/server.js +168 -205
  110. package/src/shopify-values.js +89 -0
  111. package/src/status.js +99 -39
  112. package/src/store-html.js +0 -0
  113. package/src/storefront/catalog.js +199 -0
  114. package/src/storefront/json-ld.js +167 -0
  115. package/src/variant-render.js +165 -0
  116. package/types/astro.d.ts +13 -2
  117. package/types/index.d.ts +178 -27
  118. package/types/server.d.ts +89 -17
  119. package/dist/esm/chunks/account-Q6E2TFEV.js +0 -1
  120. package/dist/esm/chunks/account-pages-UZXR4R5F.js +0 -1
  121. package/dist/esm/chunks/analytics-IJBKATUP.js +0 -1
  122. package/dist/esm/chunks/chunk-4QJKLPYR.js +0 -1
  123. package/dist/esm/chunks/chunk-64TUD3QR.js +0 -1
  124. package/dist/esm/chunks/chunk-AJLPU2JC.js +0 -4
  125. package/dist/esm/chunks/chunk-FIOZPPC5.js +0 -1
  126. package/dist/esm/chunks/chunk-K2YEQAIH.js +0 -1
  127. package/dist/esm/chunks/chunk-KIDH76B7.js +0 -1
  128. package/dist/esm/chunks/chunk-PAYT5ZD7.js +0 -1
  129. package/dist/esm/chunks/chunk-RREHGH4A.js +0 -1
  130. package/dist/esm/chunks/chunk-SSJT43CJ.js +0 -1
  131. package/dist/esm/chunks/chunk-VC46IEJQ.js +0 -1
  132. package/dist/esm/chunks/diagnose-3WVAWNTX.js +0 -14
  133. package/dist/esm/chunks/extras-7I7WJX35.js +0 -1
  134. package/dist/esm/chunks/markets-ui-545XLFTE.js +0 -1
  135. package/dist/esm/chunks/search-NILMGYXG.js +0 -1
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  (() => {
2
3
  var __defProp = Object.defineProperty;
3
4
  var __export = (target, all) => {
@@ -16,7 +17,7 @@
16
17
 
17
18
  // tether-core:config.js
18
19
  var m = window.Tether.__core["config.js"];
19
- var { DEFAULTS, cfg, configure, isConfigured, log, reportError, warn } = m;
20
+ var { DEFAULTS, cfg, configure, isConfigured, log, reportError, resolveConfig, toMetafieldIdentifier, warn } = m;
20
21
 
21
22
  // tether-core:client.js
22
23
  var m2 = window.Tether.__core["client.js"];
@@ -24,7 +25,7 @@
24
25
 
25
26
  // tether-core:cart.js
26
27
  var m3 = window.Tether.__core["cart.js"];
27
- var { Cart, focusables, toLineInput } = m3;
28
+ var { Cart, trapFocus } = m3;
28
29
 
29
30
  // tether-core:collection.js
30
31
  var m4 = window.Tether.__core["collection.js"];
@@ -36,165 +37,244 @@
36
37
 
37
38
  // tether-core:dom.js
38
39
  var m6 = window.Tether.__core["dom.js"];
39
- var { attr, busy, cdnUrl, dataKey, emit, formatDate, formatMoney, formatPercent, get, has, hasTemplate, imageUrl, notifyLayoutChanged, parseJSONAttr, productUrl, qsa, readText, repeat, repeatKeyed, sameImage, scoped, sel, setImage, setSelected, setText, setTextTracked, show, toAttributes, watchImages } = m6;
40
+ var { attr, busy, cdnUrl, emit, formatDate, formatMoney, formatPercent, get, has, hasTemplate, imageUrl, notifyLayoutChanged, parseJSONAttr, productUrl, qsa, repeat, repeatKeyed, sameImage, scoped, sel, setImage, setSelected, setStoreHtml, setText, setTextTracked, show, toAttributes, watchImages } = m6;
40
41
 
41
42
  // tether-core:mounting.js
42
43
  var m7 = window.Tether.__core["mounting.js"];
43
44
  var { hydrateFromPage, liveLists, liveProducts, mountProduct, mountedLists, mountedProducts, pruneLive, retryFailed, settleMarket, trackMarket, within } = m7;
44
45
 
46
+ // tether-core:market-codes.js
47
+ var m8 = window.Tether.__core["market-codes.js"];
48
+ var { toCountry, toLanguage } = m8;
49
+
45
50
  // src/markets.js
46
- var COUNTRY = /^[A-Z]{2}$/;
47
- var REGIONAL_LANGUAGES = /* @__PURE__ */ new Set(["PT_BR", "PT_PT", "ZH_CN", "ZH_TW"]);
51
+ var ALL_SOURCES = ["saved", "server", "webflow"];
52
+ var DEFAULT_COOKIE = "tether_country";
48
53
  var storageKey = () => `${cfg.prefix}:market:${cfg.domain}`;
49
- var defaultEnv = () => ({
50
- document: typeof document !== "undefined" ? document : null,
51
- location: typeof window !== "undefined" ? window.location : null,
52
- storage: (() => {
53
- try {
54
- return window.localStorage;
55
- } catch {
56
- return null;
57
- }
58
- })(),
59
- global: typeof window !== "undefined" ? window : {}
60
- });
61
- function toCountry(v) {
62
- const c = String(v || "").trim().toUpperCase();
63
- return COUNTRY.test(c) && c !== "XX" && c !== "T1" ? c : null;
54
+ function localStorageIfAllowed() {
55
+ if (typeof window === "undefined") return null;
56
+ try {
57
+ return window.localStorage;
58
+ } catch {
59
+ return null;
60
+ }
61
+ }
62
+ function pageEnv() {
63
+ const hasWindow = typeof window !== "undefined";
64
+ return {
65
+ document: typeof document !== "undefined" ? document : null,
66
+ location: hasWindow ? window.location : null,
67
+ storage: localStorageIfAllowed(),
68
+ global: hasWindow ? window : {}
69
+ };
64
70
  }
65
- function toLanguage(v) {
66
- const raw = String(v || "").trim().replace("-", "_").toUpperCase();
67
- if (!raw) return null;
68
- if (REGIONAL_LANGUAGES.has(raw)) return raw;
69
- const primary = raw.split("_")[0];
70
- return /^[A-Z]{2,3}$/.test(primary) ? primary : null;
71
+ function parseJsonOrNull(text) {
72
+ try {
73
+ return (
74
+ /** @type {unknown} */
75
+ JSON.parse(text)
76
+ );
77
+ } catch (error) {
78
+ if (error instanceof SyntaxError) return null;
79
+ throw error;
80
+ }
81
+ }
82
+ function toMarket(value) {
83
+ if (typeof value !== "object" || value === null) return null;
84
+ const country = toCountry(Reflect.get(value, "country"));
85
+ if (!country) return null;
86
+ const locale = (
87
+ /** @type {unknown} */
88
+ Reflect.get(value, "locale")
89
+ );
90
+ return {
91
+ country,
92
+ language: toLanguage(Reflect.get(value, "language")) ?? void 0,
93
+ locale: typeof locale === "string" && locale ? locale : void 0
94
+ };
95
+ }
96
+ function readSavedMarket(storage = localStorageIfAllowed()) {
97
+ const text = storage?.getItem(storageKey());
98
+ return text ? toMarket(parseJsonOrNull(text)) : null;
71
99
  }
72
100
  function readCookie(doc, name) {
73
101
  if (!doc || !name) return null;
74
- const hit = String(doc.cookie || "").split(";").map((c) => c.trim()).find((c) => c.startsWith(`${name}=`));
75
- return hit ? decodeURIComponent(hit.slice(name.length + 1)) : null;
102
+ const cookie = doc.cookie.split(";").map((part) => part.trim()).find((part) => part.startsWith(`${name}=`));
103
+ return cookie ? decodeURIComponent(cookie.slice(name.length + 1)) : null;
76
104
  }
77
- var lookup = (locales, key) => {
105
+ function lookupLocale(locales, key) {
78
106
  if (!locales || !key) return null;
79
- const k = String(key).toLowerCase();
80
- const found = Object.keys(locales).find((x) => x.toLowerCase() === k);
81
- return found ? locales[found] : null;
82
- };
83
- var readers = {
84
- saved(m8, env) {
85
- if (m8.remember === false || !env.storage) return null;
86
- try {
87
- return JSON.parse(env.storage.getItem(storageKey()) || "null");
88
- } catch {
89
- return null;
107
+ const wanted = key.toLowerCase();
108
+ const found = Object.keys(locales).find((name) => name.toLowerCase() === wanted);
109
+ return found ? locales[found] ?? null : null;
110
+ }
111
+ function readServerHint(markets, env) {
112
+ const meta = (name) => env.document?.querySelector(`meta[name="${name}"]`)?.getAttribute("content");
113
+ return {
114
+ country: Reflect.get(env.global, "TETHER_COUNTRY") || meta("tether-country") || readCookie(env.document, markets.cookie || DEFAULT_COOKIE),
115
+ language: Reflect.get(env.global, "TETHER_LANGUAGE") || meta("tether-language")
116
+ };
117
+ }
118
+ function readWebflowLocale(markets, env) {
119
+ const segment = (env.location?.pathname ?? "/").split("/").find((part) => part !== "");
120
+ const fromPath = lookupLocale(markets.locales, segment);
121
+ if (fromPath) return fromPath;
122
+ const lang = env.document?.documentElement.getAttribute("lang");
123
+ if (!lang) return null;
124
+ const mapped = lookupLocale(markets.locales, lang) ?? lookupLocale(markets.locales, lang.split("-")[0]);
125
+ if (mapped) return { locale: lang, ...mapped };
126
+ if (markets.locales && markets.strict) return null;
127
+ const region = lang.split("-")[1];
128
+ return { language: lang, country: region?.length === 2 ? region : null, locale: lang };
129
+ }
130
+ function readSource(source, markets, env) {
131
+ switch (source) {
132
+ case "saved":
133
+ return markets.remember === false ? null : readSavedMarket(env.storage);
134
+ case "server":
135
+ return readServerHint(markets, env);
136
+ case "webflow":
137
+ return readWebflowLocale(markets, env);
138
+ }
139
+ }
140
+ var isMarketSource = (name) => ALL_SOURCES.some((source) => source === name);
141
+ function sourcesFor(detect) {
142
+ if (!detect) return ["saved"];
143
+ if (detect === true) return ALL_SOURCES;
144
+ return (
145
+ /** @type {unknown[]} */
146
+ [detect].flat().filter(isMarketSource)
147
+ );
148
+ }
149
+ function detectMarket(markets = cfg.markets, env = pageEnv()) {
150
+ const config = markets ?? {};
151
+ if (config.detect === false) return {};
152
+ const sources = {};
153
+ const found = { sources };
154
+ for (const source of sourcesFor(config.detect)) {
155
+ const hint = readSource(source, config, env);
156
+ if (!hint) continue;
157
+ const country = toCountry(hint.country);
158
+ const language = toLanguage(hint.language);
159
+ const locale = typeof hint.locale === "string" && hint.locale ? hint.locale : null;
160
+ if (country && !found.country) {
161
+ found.country = country;
162
+ sources.country = source;
163
+ }
164
+ if (language && !found.language) {
165
+ found.language = language;
166
+ sources.language = source;
167
+ }
168
+ if (locale && !found.locale) {
169
+ found.locale = locale;
170
+ sources.locale = source;
90
171
  }
91
- },
92
- server(m8, env) {
93
- const meta = (name) => env.document?.querySelector?.(`meta[name="${name}"]`)?.getAttribute("content");
94
- const country = env.global.TETHER_COUNTRY || meta("tether-country") || readCookie(env.document, m8.cookie || "tether_country");
95
- const language = env.global.TETHER_LANGUAGE || meta("tether-language");
96
- return { country, language };
97
- },
98
- webflow(m8, env) {
99
- const segment = (env.location?.pathname || "/").split("/").filter(Boolean)[0];
100
- const fromPath = lookup(m8.locales, segment);
101
- if (fromPath) return fromPath;
102
- const lang = env.document?.documentElement?.getAttribute("lang");
103
- if (!lang) return null;
104
- const mapped = lookup(m8.locales, lang) || lookup(m8.locales, lang.split("-")[0]);
105
- if (mapped) return { locale: lang, ...mapped };
106
- if (m8.locales && m8.strict) return null;
107
- const region = lang.split("-")[1];
108
- return { language: lang, country: region && region.length === 2 ? region : null, locale: lang };
109
172
  }
110
- };
111
- function detectMarket(markets = cfg.markets, env = defaultEnv()) {
112
- const m8 = markets || {};
113
- if (m8.detect === false) return {};
114
- const list = !m8.detect ? ["saved"] : m8.detect === true ? ["saved", "server", "webflow"] : [].concat(m8.detect);
115
- markets = m8;
116
- const out = { sources: {} };
117
- list.forEach((name) => {
118
- const r = readers[name]?.(markets, env);
119
- if (!r) return;
120
- const vals = { country: toCountry(r.country), language: toLanguage(r.language), locale: r.locale || null };
121
- Object.entries(vals).forEach(([k, v]) => {
122
- if (v && !out[k]) {
123
- out[k] = v;
124
- out.sources[k] = name;
125
- }
126
- });
127
- });
128
- return out;
173
+ return found;
129
174
  }
130
- function rememberMarket(market) {
131
- if (cfg.markets?.remember === false) return;
175
+ function storeIfAllowed(key, value) {
132
176
  try {
133
- localStorage.setItem(storageKey(), JSON.stringify({ country: market.country, language: market.language || void 0, locale: market.locale || void 0 }));
177
+ localStorage.setItem(key, value);
134
178
  } catch {
179
+ return;
135
180
  }
136
181
  }
182
+ function rememberMarket(market) {
183
+ if (cfg.markets?.remember === false) return;
184
+ const saved = { country: market.country, language: market.language || void 0, locale: market.locale || void 0 };
185
+ storeIfAllowed(storageKey(), JSON.stringify(saved));
186
+ }
137
187
  var localizationPromise = null;
138
188
  function clearLocalization() {
139
189
  localizationPromise = null;
140
190
  }
191
+ var LOCALIZATION_QUERY = `query TetherLocalization{localization{country{isoCode name currency{isoCode symbol}}language{isoCode name}availableCountries{isoCode name currency{isoCode symbol}availableLanguages{isoCode name}}}}`;
141
192
  function getLocalization() {
142
193
  if (!localizationPromise) {
143
- localizationPromise = gql(`query TetherLocalization{localization{country{isoCode name currency{isoCode symbol}}language{isoCode name}availableCountries{isoCode name currency{isoCode symbol}availableLanguages{isoCode name}}}}`).then((d) => d.localization).catch((err) => {
144
- localizationPromise = null;
145
- throw err;
146
- });
194
+ const loading = gql(LOCALIZATION_QUERY);
195
+ localizationPromise = loading.then(
196
+ (data) => data.localization,
197
+ (error) => {
198
+ localizationPromise = null;
199
+ throw error;
200
+ }
201
+ );
147
202
  }
148
203
  return localizationPromise;
149
204
  }
150
205
 
151
206
  // src/markets-ui.js
207
+ var DEFAULT_LABEL = "{name} ({currency})";
208
+ var DEFAULT_BIND = "name";
209
+ function countryField(country, field) {
210
+ switch (field) {
211
+ case "name":
212
+ return country.name;
213
+ case "code":
214
+ return country.isoCode;
215
+ case "currency":
216
+ return country.currency.isoCode;
217
+ case "symbol":
218
+ return country.currency.symbol;
219
+ default:
220
+ return "";
221
+ }
222
+ }
223
+ var fillLabel = (template, country) => template.replace(
224
+ /\{(name|code|currency|symbol)\}/g,
225
+ (_match, field) => countryField(country, field)
226
+ );
227
+ function fillCountrySelect(select, countries, current) {
228
+ const template = select.getAttribute(attr("country-label")) || DEFAULT_LABEL;
229
+ const only = (select.getAttribute(attr("countries")) || "").toUpperCase().split(/[\s,]+/).filter(Boolean);
230
+ const listed = only.length ? only.map((code) => countries.find((country) => country.isoCode === code)).filter((country) => country !== void 0) : countries;
231
+ select.replaceChildren(...listed.map((country) => new Option(fillLabel(template, country), country.isoCode)));
232
+ select.value = current;
233
+ if (select.value !== current) select.selectedIndex = -1;
234
+ select.disabled = listed.length < 2 && !select.hasAttribute(attr("always-enabled"));
235
+ }
236
+ function fillCountries(selects, binds, localization) {
237
+ const current = (cfg.country || localization.country.isoCode).toUpperCase();
238
+ const countries = [...localization.availableCountries].sort(
239
+ (a, b) => a.name.localeCompare(b.name, cfg.locale || void 0)
240
+ );
241
+ const inUse = countries.find((country) => country.isoCode === current) ?? localization.country;
242
+ selects.forEach((select) => {
243
+ fillCountrySelect(select, countries, current);
244
+ });
245
+ binds.forEach((el) => {
246
+ el.textContent = countryField(inUse, get(el, "country-bind") || DEFAULT_BIND);
247
+ });
248
+ }
152
249
  function renderCountrySelects(root = document) {
153
- const selects = within(root, `select${sel("country-select")}`);
250
+ const selects = (
251
+ /** @type {HTMLSelectElement[]} */
252
+ within(root, `select${sel("country-select")}`)
253
+ );
154
254
  const binds = within(root, sel("country-bind"));
155
255
  if (!selects.length && !binds.length) return Promise.resolve();
156
- return getLocalization().then((loc) => {
157
- const current = (cfg.country || loc.country?.isoCode || "").toUpperCase();
158
- const countries = [...loc.availableCountries || []].sort((a, b) => a.name.localeCompare(b.name, cfg.locale || void 0));
159
- const info = countries.find((c) => c.isoCode === current) || loc.country;
160
- const fill = (tpl, c) => tpl.replace(/\{name\}/g, c.name).replace(/\{code\}/g, c.isoCode).replace(/\{currency\}/g, c.currency?.isoCode || "").replace(/\{symbol\}/g, c.currency?.symbol || "");
161
- selects.forEach((s) => {
162
- const tpl = s.getAttribute(attr("country-label")) || "{name} ({currency})";
163
- const only = (s.getAttribute(attr("countries")) || "").toUpperCase().split(/[\s,]+/).filter(Boolean);
164
- const list = only.length ? only.map((c) => countries.find((x) => x.isoCode === c)).filter(Boolean) : countries;
165
- s.innerHTML = "";
166
- list.forEach((c) => s.appendChild(new Option(fill(tpl, c), c.isoCode)));
167
- s.value = current;
168
- if (s.value !== current) s.selectedIndex = -1;
169
- s.disabled = list.length < 2 && !s.hasAttribute(attr("always-enabled"));
170
- });
171
- binds.forEach((el) => {
172
- const k = get(el, "country-bind") || "name";
173
- const v = { name: info?.name, code: info?.isoCode, currency: info?.currency?.isoCode, symbol: info?.currency?.symbol }[k];
174
- el.textContent = v || "";
175
- });
176
- }).catch((err) => reportError(err, "country select"));
256
+ return getLocalization().then((localization) => {
257
+ fillCountries(selects, binds, localization);
258
+ }).catch((error) => {
259
+ reportError(error, "country select");
260
+ });
177
261
  }
178
- async function setCountry(code, { language, locale, remember = true } = {}) {
179
- const country = toCountry(code);
180
- if (!country) throw new TetherError(`Not a country code: ${code}`, { code: "INVALID_COUNTRY" });
181
- const entry = Object.values(cfg.markets?.locales || {}).find((m8) => toCountry(m8?.country) === country);
182
- const own = locale || entry?.locale;
183
- const loc = own || cfg.locale;
184
- const lang = language !== void 0 ? toLanguage(language) : entry ? entry.language ? toLanguage(entry.language) : void 0 : cfg.language;
185
- const changed = country !== String(cfg.country || "").toUpperCase() || lang !== cfg.language || loc !== cfg.locale;
186
- cfg.country = country;
187
- cfg.language = lang || void 0;
188
- cfg.locale = loc;
189
- if (remember) rememberMarket({ country, language: lang, locale: own });
190
- if (!changed) {
191
- renderCountrySelects();
192
- return Cart.state;
193
- }
262
+ var localeEntryFor = (country) => Object.values(cfg.markets?.locales ?? {}).find((entry) => toCountry(entry.country) === country);
263
+ function languageFor(language, entry) {
264
+ if (language !== void 0) return toLanguage(language);
265
+ if (!entry) return cfg.language;
266
+ return entry.language ? toLanguage(entry.language) : void 0;
267
+ }
268
+ function rerenderInMarket(country) {
194
269
  clearProductCache();
195
270
  const jobs = [];
196
- if (language !== void 0) clearLocalization();
197
- if (Cart.id()) jobs.push(Cart.setBuyerIdentity({ countryCode: country }, { create: false }).catch((err) => reportError(err, "cart country")));
271
+ if (Cart.id()) {
272
+ jobs.push(
273
+ Cart.setBuyerIdentity({ countryCode: country }, { create: false }).catch((error) => {
274
+ reportError(error, "cart country");
275
+ })
276
+ );
277
+ }
198
278
  pruneLive();
199
279
  liveLists.forEach((list) => jobs.push(list.load()));
200
280
  liveProducts.forEach((el) => {
@@ -202,12 +282,37 @@
202
282
  mountedProducts.delete(el);
203
283
  mountProduct(el);
204
284
  });
205
- renderCountrySelects();
285
+ return jobs;
286
+ }
287
+ async function setCountry(code, { language, locale, remember = true } = {}) {
288
+ const country = toCountry(code);
289
+ if (!country) throw new TetherError(`Not a country code: ${code}`, { code: "INVALID_COUNTRY" });
290
+ const entry = localeEntryFor(country);
291
+ const ownLocale = locale || entry?.locale;
292
+ const nextLocale = ownLocale || cfg.locale;
293
+ const nextLanguage = languageFor(language, entry);
294
+ const changed = country !== cfg.country?.toUpperCase() || nextLanguage !== cfg.language || nextLocale !== cfg.locale;
295
+ cfg.country = country;
296
+ cfg.language = nextLanguage || void 0;
297
+ cfg.locale = nextLocale;
298
+ if (remember) rememberMarket({ country, language: nextLanguage, locale: ownLocale });
299
+ if (!changed) {
300
+ void renderCountrySelects();
301
+ return Cart.state;
302
+ }
303
+ if (language !== void 0) clearLocalization();
304
+ const jobs = rerenderInMarket(country);
305
+ void renderCountrySelects();
206
306
  emit("country-changed", { country, language: cfg.language });
207
307
  await Promise.all(jobs);
208
308
  return Cart.state;
209
309
  }
210
310
 
211
311
  // src/parts/markets.js
212
- window.Tether.__parts.markets = markets_ui_exports;
312
+ var { Tether } = (
313
+ /** @type {Window & { Tether?: { __parts: Record<string, unknown> } }} */
314
+ window
315
+ );
316
+ if (!Tether) throw new Error("tether.markets.js runs after the Tether script, which loads it");
317
+ Tether.__parts["markets"] = markets_ui_exports;
213
318
  })();
@@ -1 +1 @@
1
- (()=>{var G=Object.defineProperty;var H=(e,t)=>{for(var r in t)G(e,r,{get:t[r],enumerable:!0})};var P={};H(P,{detectMarket:()=>M,getLocalization:()=>C,renderCountrySelects:()=>x,setCountry:()=>oe});var K=window.Tether.__core["config.js"],{DEFAULTS:ne,cfg:a,configure:ce,isConfigured:ae,log:le,reportError:b,warn:se}=K;var Z=window.Tether.__core["client.js"],{TetherError:E,endpoint:ue,gql:S,request:de,unwrap:me,withContext:fe}=Z;var D=window.Tether.__core["cart.js"],{Cart:f,focusables:pe,toLineInput:ye}=D;var F=window.Tether.__core["collection.js"],{ListScope:we,listSelector:A}=F;var J=window.Tether.__core["loader.js"],{clearProductCache:v,getProduct:be,getProducts:Te,getRecommendations:_e,hydrateProducts:Le,normalizeProductKey:xe,primeProduct:Pe,refreshProducts:Ee,takeStale:Se}=J;var Y=window.Tether.__core["dom.js"],{attr:y,busy:ve,cdnUrl:Ue,dataKey:ke,emit:U,formatDate:Ie,formatMoney:Ne,formatPercent:je,get:k,has:Oe,hasTemplate:ze,imageUrl:Re,notifyLayoutChanged:Me,parseJSONAttr:$e,productUrl:qe,qsa:Be,readText:Ge,repeat:He,repeatKeyed:Ke,sameImage:Ze,scoped:De,sel:T,setImage:Fe,setSelected:Je,setText:Ye,setTextTracked:We,show:Xe,toAttributes:Ve,watchImages:Qe}=Y;var W=window.Tether.__core["mounting.js"],{hydrateFromPage:tt,liveLists:I,liveProducts:N,mountProduct:j,mountedLists:ot,mountedProducts:O,pruneLive:z,retryFailed:rt,settleMarket:nt,trackMarket:ct,within:_}=W;var X=/^[A-Z]{2}$/,V=new Set(["PT_BR","PT_PT","ZH_CN","ZH_TW"]),R=()=>`${a.prefix}:market:${a.domain}`,Q=()=>({document:typeof document<"u"?document:null,location:typeof window<"u"?window.location:null,storage:(()=>{try{return window.localStorage}catch{return null}})(),global:typeof window<"u"?window:{}});function h(e){let t=String(e||"").trim().toUpperCase();return X.test(t)&&t!=="XX"&&t!=="T1"?t:null}function w(e){let t=String(e||"").trim().replace("-","_").toUpperCase();if(!t)return null;if(V.has(t))return t;let r=t.split("_")[0];return/^[A-Z]{2,3}$/.test(r)?r:null}function ee(e,t){if(!e||!t)return null;let r=String(e.cookie||"").split(";").map(c=>c.trim()).find(c=>c.startsWith(`${t}=`));return r?decodeURIComponent(r.slice(t.length+1)):null}var L=(e,t)=>{if(!e||!t)return null;let r=String(t).toLowerCase(),c=Object.keys(e).find(o=>o.toLowerCase()===r);return c?e[c]:null},te={saved(e,t){if(e.remember===!1||!t.storage)return null;try{return JSON.parse(t.storage.getItem(R())||"null")}catch{return null}},server(e,t){let r=l=>t.document?.querySelector?.(`meta[name="${l}"]`)?.getAttribute("content"),c=t.global.TETHER_COUNTRY||r("tether-country")||ee(t.document,e.cookie||"tether_country"),o=t.global.TETHER_LANGUAGE||r("tether-language");return{country:c,language:o}},webflow(e,t){let r=(t.location?.pathname||"/").split("/").filter(Boolean)[0],c=L(e.locales,r);if(c)return c;let o=t.document?.documentElement?.getAttribute("lang");if(!o)return null;let l=L(e.locales,o)||L(e.locales,o.split("-")[0]);if(l)return{locale:o,...l};if(e.locales&&e.strict)return null;let s=o.split("-")[1];return{language:o,country:s&&s.length===2?s:null,locale:o}}};function M(e=a.markets,t=Q()){let r=e||{};if(r.detect===!1)return{};let c=r.detect?r.detect===!0?["saved","server","webflow"]:[].concat(r.detect):["saved"];e=r;let o={sources:{}};return c.forEach(l=>{let s=te[l]?.(e,t);if(!s)return;let m={country:h(s.country),language:w(s.language),locale:s.locale||null};Object.entries(m).forEach(([n,i])=>{i&&!o[n]&&(o[n]=i,o.sources[n]=l)})}),o}function $(e){if(a.markets?.remember!==!1)try{localStorage.setItem(R(),JSON.stringify({country:e.country,language:e.language||void 0,locale:e.locale||void 0}))}catch{}}var g=null;function q(){g=null}function C(){return g||(g=S("query TetherLocalization{localization{country{isoCode name currency{isoCode symbol}}language{isoCode name}availableCountries{isoCode name currency{isoCode symbol}availableLanguages{isoCode name}}}}").then(e=>e.localization).catch(e=>{throw g=null,e})),g}function x(e=document){let t=_(e,`select${T("country-select")}`),r=_(e,T("country-bind"));return!t.length&&!r.length?Promise.resolve():C().then(c=>{let o=(a.country||c.country?.isoCode||"").toUpperCase(),l=[...c.availableCountries||[]].sort((n,i)=>n.name.localeCompare(i.name,a.locale||void 0)),s=l.find(n=>n.isoCode===o)||c.country,m=(n,i)=>n.replace(/\{name\}/g,i.name).replace(/\{code\}/g,i.isoCode).replace(/\{currency\}/g,i.currency?.isoCode||"").replace(/\{symbol\}/g,i.currency?.symbol||"");t.forEach(n=>{let i=n.getAttribute(y("country-label"))||"{name} ({currency})",d=(n.getAttribute(y("countries"))||"").toUpperCase().split(/[\s,]+/).filter(Boolean),u=d.length?d.map(p=>l.find(B=>B.isoCode===p)).filter(Boolean):l;n.innerHTML="",u.forEach(p=>n.appendChild(new Option(m(i,p),p.isoCode))),n.value=o,n.value!==o&&(n.selectedIndex=-1),n.disabled=u.length<2&&!n.hasAttribute(y("always-enabled"))}),r.forEach(n=>{let i=k(n,"country-bind")||"name",d={name:s?.name,code:s?.isoCode,currency:s?.currency?.isoCode,symbol:s?.currency?.symbol}[i];n.textContent=d||""})}).catch(c=>b(c,"country select"))}async function oe(e,{language:t,locale:r,remember:c=!0}={}){let o=h(e);if(!o)throw new E(`Not a country code: ${e}`,{code:"INVALID_COUNTRY"});let l=Object.values(a.markets?.locales||{}).find(u=>h(u?.country)===o),s=r||l?.locale,m=s||a.locale,n=t!==void 0?w(t):l?l.language?w(l.language):void 0:a.language,i=o!==String(a.country||"").toUpperCase()||n!==a.language||m!==a.locale;if(a.country=o,a.language=n||void 0,a.locale=m,c&&$({country:o,language:n,locale:s}),!i)return x(),f.state;v();let d=[];return t!==void 0&&q(),f.id()&&d.push(f.setBuyerIdentity({countryCode:o},{create:!1}).catch(u=>b(u,"cart country"))),z(),I.forEach(u=>d.push(u.load())),N.forEach(u=>{u.closest(A())||(O.delete(u),j(u))}),x(),U("country-changed",{country:o,language:a.language}),await Promise.all(d),f.state}window.Tether.__parts.markets=P;})();
1
+ "use strict";(()=>{var B=Object.defineProperty;var H=(e,t)=>{for(var o in t)B(e,o,{get:t[o],enumerable:!0})};var T={};H(T,{detectMarket:()=>F,getLocalization:()=>y,renderCountrySelects:()=>L,setCountry:()=>be});var J=window.Tether.__core["config.js"],{DEFAULTS:Te,cfg:a,configure:_e,isConfigured:xe,log:Ee,reportError:h,resolveConfig:Se,toMetafieldIdentifier:Ae,warn:Pe}=J;var K=window.Tether.__core["client.js"],{TetherError:_,endpoint:ke,gql:x,request:Ue,unwrap:ve,withContext:je}=K;var W=window.Tether.__core["cart.js"],{Cart:f,trapFocus:Re}=W;var Y=window.Tether.__core["collection.js"],{ListScope:Fe,listSelector:E}=Y;var G=window.Tether.__core["loader.js"],{clearProductCache:S,getProduct:ze,getProducts:De,getRecommendations:qe,hydrateProducts:$e,normalizeProductKey:Be,primeProduct:He,refreshProducts:Je,takeStale:Ke}=G;var Q=window.Tether.__core["dom.js"],{attr:p,busy:Ye,cdnUrl:Ge,emit:A,formatDate:Qe,formatMoney:Ve,formatPercent:Ze,get:P,has:Xe,hasTemplate:et,imageUrl:tt,notifyLayoutChanged:ot,parseJSONAttr:nt,productUrl:rt,qsa:ct,repeat:at,repeatKeyed:lt,sameImage:it,scoped:ut,sel:w,setImage:st,setSelected:dt,setStoreHtml:ft,setText:gt,setTextTracked:mt,show:pt,toAttributes:yt,watchImages:ht}=Q;var V=window.Tether.__core["mounting.js"],{hydrateFromPage:Ct,liveLists:I,liveProducts:k,mountProduct:U,mountedLists:bt,mountedProducts:v,pruneLive:j,retryFailed:Lt,settleMarket:Tt,trackMarket:_t,within:C}=V;var Z=window.Tether.__core["market-codes.js"],{toCountry:s,toLanguage:d}=Z;var O=["saved","server","webflow"],X="tether_country",R=()=>`${a.prefix}:market:${a.domain}`;function M(){if(typeof window>"u")return null;try{return window.localStorage}catch{return null}}function ee(){let e=typeof window<"u";return{document:typeof document<"u"?document:null,location:e?window.location:null,storage:M(),global:e?window:{}}}function te(e){try{return JSON.parse(e)}catch(t){if(t instanceof SyntaxError)return null;throw t}}function oe(e){if(typeof e!="object"||e===null)return null;let t=s(Reflect.get(e,"country"));if(!t)return null;let o=Reflect.get(e,"locale");return{country:t,language:d(Reflect.get(e,"language"))??void 0,locale:typeof o=="string"&&o?o:void 0}}function ne(e=M()){let t=e?.getItem(R());return t?oe(te(t)):null}function re(e,t){if(!e||!t)return null;let o=e.cookie.split(";").map(r=>r.trim()).find(r=>r.startsWith(`${t}=`));return o?decodeURIComponent(o.slice(t.length+1)):null}function b(e,t){if(!e||!t)return null;let o=t.toLowerCase(),r=Object.keys(e).find(n=>n.toLowerCase()===o);return r?e[r]??null:null}function ce(e,t){let o=r=>t.document?.querySelector(`meta[name="${r}"]`)?.getAttribute("content");return{country:Reflect.get(t.global,"TETHER_COUNTRY")||o("tether-country")||re(t.document,e.cookie||X),language:Reflect.get(t.global,"TETHER_LANGUAGE")||o("tether-language")}}function ae(e,t){let o=(t.location?.pathname??"/").split("/").find(i=>i!==""),r=b(e.locales,o);if(r)return r;let n=t.document?.documentElement.getAttribute("lang");if(!n)return null;let l=b(e.locales,n)??b(e.locales,n.split("-")[0]);if(l)return{locale:n,...l};if(e.locales&&e.strict)return null;let c=n.split("-")[1];return{language:n,country:c?.length===2?c:null,locale:n}}function le(e,t,o){switch(e){case"saved":return t.remember===!1?null:ne(o.storage);case"server":return ce(t,o);case"webflow":return ae(t,o)}}var ie=e=>O.some(t=>t===e);function ue(e){return e?e===!0?O:[e].flat().filter(ie):["saved"]}function F(e=a.markets,t=ee()){let o=e??{};if(o.detect===!1)return{};let r={},n={sources:r};for(let l of ue(o.detect)){let c=le(l,o,t);if(!c)continue;let i=s(c.country),u=d(c.language),m=typeof c.locale=="string"&&c.locale?c.locale:null;i&&!n.country&&(n.country=i,r.country=l),u&&!n.language&&(n.language=u,r.language=l),m&&!n.locale&&(n.locale=m,r.locale=l)}return n}function se(e,t){try{localStorage.setItem(e,t)}catch{return}}function N(e){if(a.markets?.remember===!1)return;let t={country:e.country,language:e.language||void 0,locale:e.locale||void 0};se(R(),JSON.stringify(t))}var g=null;function z(){g=null}var de="query TetherLocalization{localization{country{isoCode name currency{isoCode symbol}}language{isoCode name}availableCountries{isoCode name currency{isoCode symbol}availableLanguages{isoCode name}}}}";function y(){return g||(g=x(de).then(t=>t.localization,t=>{throw g=null,t})),g}var fe="{name} ({currency})",ge="name";function D(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 me=(e,t)=>e.replace(/\{(name|code|currency|symbol)\}/g,(o,r)=>D(t,r));function pe(e,t,o){let r=e.getAttribute(p("country-label"))||fe,n=(e.getAttribute(p("countries"))||"").toUpperCase().split(/[\s,]+/).filter(Boolean),l=n.length?n.map(c=>t.find(i=>i.isoCode===c)).filter(c=>c!==void 0):t;e.replaceChildren(...l.map(c=>new Option(me(r,c),c.isoCode))),e.value=o,e.value!==o&&(e.selectedIndex=-1),e.disabled=l.length<2&&!e.hasAttribute(p("always-enabled"))}function ye(e,t,o){let r=(a.country||o.country.isoCode).toUpperCase(),n=[...o.availableCountries].sort((c,i)=>c.name.localeCompare(i.name,a.locale||void 0)),l=n.find(c=>c.isoCode===r)??o.country;e.forEach(c=>{pe(c,n,r)}),t.forEach(c=>{c.textContent=D(l,P(c,"country-bind")||ge)})}function L(e=document){let t=C(e,`select${w("country-select")}`),o=C(e,w("country-bind"));return!t.length&&!o.length?Promise.resolve():y().then(r=>{ye(t,o,r)}).catch(r=>{h(r,"country select")})}var he=e=>Object.values(a.markets?.locales??{}).find(t=>s(t.country)===e);function we(e,t){return e!==void 0?d(e):t?t.language?d(t.language):void 0:a.language}function Ce(e){S();let t=[];return f.id()&&t.push(f.setBuyerIdentity({countryCode:e},{create:!1}).catch(o=>{h(o,"cart country")})),j(),I.forEach(o=>t.push(o.load())),k.forEach(o=>{o.closest(E())||(v.delete(o),U(o))}),t}async function be(e,{language:t,locale:o,remember:r=!0}={}){let n=s(e);if(!n)throw new _(`Not a country code: ${e}`,{code:"INVALID_COUNTRY"});let l=he(n),c=o||l?.locale,i=c||a.locale,u=we(t,l),m=n!==a.country?.toUpperCase()||u!==a.language||i!==a.locale;if(a.country=n,a.language=u||void 0,a.locale=i,r&&N({country:n,language:u,locale:c}),!m)return L(),f.state;t!==void 0&&z();let $=Ce(n);return L(),A("country-changed",{country:n,language:a.language}),await Promise.all($),f.state}var{Tether:q}=window;if(!q)throw new Error("tether.markets.js runs after the Tether script, which loads it");q.__parts.markets=T;})();
Binary file