@nuskin/react-search-sdk 1.0.0-comx-2233.2 → 1.0.0-comx-2233.4

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/dist/index.js CHANGED
@@ -343,17 +343,13 @@ function createSearchService(options = {}) {
343
343
  if (!trimmedQuery) return void 0;
344
344
  addRecentHeaderSearch(localeParts, trimmedQuery, storage);
345
345
  const optionHref = resolveOptionHref(option, localeParts);
346
- if (optionHref && locationLike && typeof locationLike.assign === "function") {
347
- locationLike.assign(optionHref);
346
+ if (optionHref) {
348
347
  return stripLocalePrefix(optionHref, localeParts);
349
348
  }
350
349
  const targetPath = buildSearchResultsPath(
351
350
  trimmedQuery,
352
351
  localeParts
353
352
  );
354
- if (locationLike && typeof locationLike.assign === "function") {
355
- locationLike.assign(targetPath);
356
- }
357
353
  return stripLocalePrefix(targetPath, localeParts);
358
354
  },
359
355
  activateSuggestionAction(option) {
@@ -366,9 +362,7 @@ function createSearchService(options = {}) {
366
362
  option,
367
363
  localeParts
368
364
  );
369
- if (optionHref2 && locationLike && typeof locationLike.assign === "function") {
370
- locationLike.assign(optionHref2);
371
- } else {
365
+ if (!optionHref2) {
372
366
  const optionQuery2 = option?.value ?? option?.label ?? option?.identifier ?? "";
373
367
  service.submitProductSearch(
374
368
  String(optionQuery2)
@@ -387,9 +381,8 @@ function createSearchService(options = {}) {
387
381
  }
388
382
  }
389
383
  const optionHref = resolveOptionHref(option, localeParts);
390
- if (optionHref && locationLike && typeof locationLike.assign === "function") {
391
- locationLike.assign(optionHref);
392
- return optionHref;
384
+ if (optionHref) {
385
+ return stripLocalePrefix(optionHref, localeParts);
393
386
  }
394
387
  const optionQuery = option?.value ?? option?.label ?? option?.identifier ?? "";
395
388
  return service.submitProductSearch(String(optionQuery));
@@ -1261,6 +1254,7 @@ function useSearchSuggestions({
1261
1254
  const [didYouMean, setDidYouMean] = React.useState([]);
1262
1255
  const [loading, setLoading] = React.useState(false);
1263
1256
  const [emptyFetched, setEmptyFetched] = React.useState(false);
1257
+ const [suggestionFetchFailed, setSuggestionFetchFailed] = React.useState(false);
1264
1258
  const [hasMoreResults, setHasMoreResults] = React.useState(false);
1265
1259
  const [totalResultsCount, setTotalResultsCount] = React.useState(0);
1266
1260
  const fetchDebounced = React.useRef(null);
@@ -1269,6 +1263,7 @@ function useSearchSuggestions({
1269
1263
  setSuggestions([]);
1270
1264
  setDidYouMean([]);
1271
1265
  setEmptyFetched(false);
1266
+ setSuggestionFetchFailed(false);
1272
1267
  setHasMoreResults(false);
1273
1268
  setTotalResultsCount(0);
1274
1269
  setLoading(false);
@@ -1277,6 +1272,7 @@ function useSearchSuggestions({
1277
1272
  (nextQuery) => {
1278
1273
  const hasNextQuery = Boolean(nextQuery.trim());
1279
1274
  setEmptyFetched(false);
1275
+ setSuggestionFetchFailed(false);
1280
1276
  setLoading(enabled && hasNextQuery);
1281
1277
  setQuery(nextQuery);
1282
1278
  },
@@ -1296,6 +1292,7 @@ function useSearchSuggestions({
1296
1292
  }
1297
1293
  setLoading(true);
1298
1294
  setEmptyFetched(false);
1295
+ setSuggestionFetchFailed(false);
1299
1296
  try {
1300
1297
  const fetchedSuggestions = await service.fetchSuggestions(trimmedQuery);
1301
1298
  if (requestId !== latestRequestId.current) {
@@ -1318,6 +1315,7 @@ function useSearchSuggestions({
1318
1315
  !hasDidYouMean && effectiveTotal > MAX_VISIBLE_SUGGESTIONS
1319
1316
  );
1320
1317
  setTotalResultsCount(effectiveTotal);
1318
+ setSuggestionFetchFailed(false);
1321
1319
  setEmptyFetched(
1322
1320
  hasDidYouMean ? false : visibleSuggestions.length === 0 && suggestedTerms.length === 0
1323
1321
  );
@@ -1328,6 +1326,7 @@ function useSearchSuggestions({
1328
1326
  setSuggestions([]);
1329
1327
  setDidYouMean([]);
1330
1328
  setEmptyFetched(true);
1329
+ setSuggestionFetchFailed(true);
1331
1330
  setHasMoreResults(false);
1332
1331
  setTotalResultsCount(0);
1333
1332
  } finally {
@@ -1365,6 +1364,7 @@ function useSearchSuggestions({
1365
1364
  loading,
1366
1365
  query,
1367
1366
  setQuery,
1367
+ suggestionFetchFailed,
1368
1368
  suggestions,
1369
1369
  totalResultsCount,
1370
1370
  updateQuery
@@ -1747,6 +1747,188 @@ function useVoiceSearch({
1747
1747
  return { listening, supported, start, stop };
1748
1748
  }
1749
1749
 
1750
+ // src/utils/commonUtils.ts
1751
+ var IS_BROWSER = typeof window !== "undefined";
1752
+ function toEventString(value, fallback = " ") {
1753
+ if (value === void 0 || value === null) return fallback;
1754
+ const str = String(value).trim();
1755
+ return str.length > 0 ? str : fallback;
1756
+ }
1757
+ function getLocaleFromUrl(pathname) {
1758
+ const path = pathname ?? (IS_BROWSER ? window.location.pathname : "");
1759
+ const [country, language] = path.split("/").filter(Boolean);
1760
+ if (!/^[a-z]{2}$/i.test(country ?? "") || !/^[a-z]{2}$/i.test(language ?? "")) {
1761
+ return {};
1762
+ }
1763
+ return {
1764
+ countryCode: country.toUpperCase(),
1765
+ language: language.toLowerCase()
1766
+ };
1767
+ }
1768
+ function safeParse(raw) {
1769
+ try {
1770
+ return JSON.parse(raw);
1771
+ } catch {
1772
+ return raw;
1773
+ }
1774
+ }
1775
+ function getLocalStorage(key) {
1776
+ if (!IS_BROWSER) return void 0;
1777
+ try {
1778
+ const raw = window.localStorage.getItem(key);
1779
+ return raw === null ? void 0 : safeParse(raw);
1780
+ } catch {
1781
+ return void 0;
1782
+ }
1783
+ }
1784
+ function getSessionStorage2(key) {
1785
+ if (!IS_BROWSER) return void 0;
1786
+ try {
1787
+ const raw = window.sessionStorage.getItem(key);
1788
+ return raw === null ? void 0 : safeParse(raw);
1789
+ } catch {
1790
+ return void 0;
1791
+ }
1792
+ }
1793
+
1794
+ // src/utils/gtmConstants.ts
1795
+ var SEARCH_GTM_EVENTS = {
1796
+ CHAT_ENTRY_POINT: "Begin_chat",
1797
+ SEARCH_TYPE: "Search_Type",
1798
+ PRODUCT_SEARCH: "ProductSearch",
1799
+ ERROR_POPUP: "Error_popup"
1800
+ };
1801
+ var SEARCH_GTM_SEARCH_TYPES = {
1802
+ SEMANTIC: "semantic search",
1803
+ AI_AGENT: "AI agent"
1804
+ };
1805
+ var SEARCH_GTM_USER_STATUS = {
1806
+ GUEST: "guest",
1807
+ LOGGED_IN: "logged_in"
1808
+ };
1809
+ var AI_CHAT_CONVERSATION_ID_KEY = "ai_chat_conversation_id";
1810
+ var IS_AUTHENTICATED_KEY = "IsAuthenticated";
1811
+ var ACCOUNT_TYPE_KEY = "accountType";
1812
+ var NUSKIN_ACCOUNT_DATA_KEY = "nuskin.account.data";
1813
+ var GTM_FALLBACK_NA = "NA";
1814
+
1815
+ // src/utils/gtmTracking.ts
1816
+ function readSessionChatId() {
1817
+ const raw = getSessionStorage2(AI_CHAT_CONVERSATION_ID_KEY);
1818
+ return typeof raw === "string" || typeof raw === "number" ? String(raw) : void 0;
1819
+ }
1820
+ function readUserStatusFromStorage() {
1821
+ const value = getLocalStorage(IS_AUTHENTICATED_KEY);
1822
+ if (value === void 0) return void 0;
1823
+ if (value === SEARCH_GTM_USER_STATUS.GUEST || value === SEARCH_GTM_USER_STATUS.LOGGED_IN) {
1824
+ return value;
1825
+ }
1826
+ const isAuthenticated = value === true || typeof value === "string" && ["true", "1", "yes", "y"].includes(value.toLowerCase().trim());
1827
+ return isAuthenticated ? SEARCH_GTM_USER_STATUS.LOGGED_IN : SEARCH_GTM_USER_STATUS.GUEST;
1828
+ }
1829
+ function readAccountTypeFromStorage() {
1830
+ const value = getLocalStorage(ACCOUNT_TYPE_KEY);
1831
+ return typeof value === "string" && value.trim().length > 0 ? value : void 0;
1832
+ }
1833
+ function readUserIdFromStorage() {
1834
+ const raw = getLocalStorage(NUSKIN_ACCOUNT_DATA_KEY);
1835
+ if (!raw || typeof raw !== "object") return void 0;
1836
+ const user = raw.user;
1837
+ if (!user || typeof user !== "object") return void 0;
1838
+ const id = user.id;
1839
+ return typeof id === "string" && id.trim().length > 0 ? id : void 0;
1840
+ }
1841
+ function resolveUserId(explicit) {
1842
+ return toEventString(explicit ?? readUserIdFromStorage(), GTM_FALLBACK_NA);
1843
+ }
1844
+ function baseEventPayload(ctx) {
1845
+ const urlLocale = getLocaleFromUrl();
1846
+ const chatId = ctx.chatId ?? readSessionChatId();
1847
+ const userStatus = ctx.userStatus ?? readUserStatusFromStorage();
1848
+ const accountType = ctx.accountType ?? readAccountTypeFromStorage();
1849
+ const resolvedUserStatus = userStatus ?? SEARCH_GTM_USER_STATUS.GUEST;
1850
+ const documentTitle = IS_BROWSER && typeof document?.title === "string" ? document.title : void 0;
1851
+ return {
1852
+ Chat_ID: toEventString(chatId, GTM_FALLBACK_NA),
1853
+ page_type: toEventString(
1854
+ ctx.pageType ?? documentTitle,
1855
+ GTM_FALLBACK_NA
1856
+ ),
1857
+ country_code: toEventString(
1858
+ ctx.countryCode ?? urlLocale.countryCode,
1859
+ GTM_FALLBACK_NA
1860
+ ),
1861
+ language: toEventString(
1862
+ ctx.language ?? urlLocale.language,
1863
+ GTM_FALLBACK_NA
1864
+ ),
1865
+ user_status: toEventString(
1866
+ resolvedUserStatus,
1867
+ SEARCH_GTM_USER_STATUS.GUEST
1868
+ ),
1869
+ account_type: toEventString(accountType, GTM_FALLBACK_NA)
1870
+ };
1871
+ }
1872
+ function serializeProductResults(productResultsData, productResults) {
1873
+ if (productResultsData !== void 0) {
1874
+ try {
1875
+ return JSON.stringify(productResultsData);
1876
+ } catch {
1877
+ return GTM_FALLBACK_NA;
1878
+ }
1879
+ }
1880
+ if (productResults === void 0 || productResults === null) {
1881
+ return GTM_FALLBACK_NA;
1882
+ }
1883
+ return String(productResults);
1884
+ }
1885
+ function pushGtmEvent(event) {
1886
+ if (!IS_BROWSER) return;
1887
+ try {
1888
+ const layer = window.dataLayer ?? (window.dataLayer = []);
1889
+ layer.push(event);
1890
+ } catch (err) {
1891
+ if (typeof console !== "undefined") {
1892
+ console.warn("[react-search-sdk] pushGtmEvent failed:", err);
1893
+ }
1894
+ }
1895
+ }
1896
+ function trackChatEntryPoint(ctx) {
1897
+ pushGtmEvent({
1898
+ event: SEARCH_GTM_EVENTS.CHAT_ENTRY_POINT,
1899
+ ...baseEventPayload(ctx)
1900
+ });
1901
+ }
1902
+ function trackSearchType(input) {
1903
+ pushGtmEvent({
1904
+ event: SEARCH_GTM_EVENTS.SEARCH_TYPE,
1905
+ ...baseEventPayload(input),
1906
+ id: resolveUserId(input.userId),
1907
+ type: input.searchType ?? SEARCH_GTM_SEARCH_TYPES.SEMANTIC,
1908
+ search_response: toEventString(input.searchResponse, GTM_FALLBACK_NA)
1909
+ });
1910
+ }
1911
+ function trackProductSearch(input) {
1912
+ pushGtmEvent({
1913
+ event: SEARCH_GTM_EVENTS.PRODUCT_SEARCH,
1914
+ ...baseEventPayload(input),
1915
+ id: resolveUserId(input.userId),
1916
+ search_type: input.searchType ?? SEARCH_GTM_SEARCH_TYPES.SEMANTIC,
1917
+ Product_results: serializeProductResults(
1918
+ input.productResultsData,
1919
+ input.productResults
1920
+ )
1921
+ });
1922
+ }
1923
+ function trackErrorPopup(input) {
1924
+ pushGtmEvent({
1925
+ event: SEARCH_GTM_EVENTS.ERROR_POPUP,
1926
+ ...baseEventPayload(input),
1927
+ id: resolveUserId(input.userId),
1928
+ search_type: input.searchType ?? SEARCH_GTM_SEARCH_TYPES.SEMANTIC
1929
+ });
1930
+ }
1931
+
1750
1932
  exports.CATALOG_SUGGESTIONS_PATH = CATALOG_SUGGESTIONS_PATH;
1751
1933
  exports.DEBOUNCE_MS = DEBOUNCE_MS;
1752
1934
  exports.DEFAULT_AI_CHAT_BASE_URL = DEFAULT_AI_CHAT_BASE_URL;
@@ -1758,6 +1940,9 @@ exports.DEFAULT_SUGGESTION_SIZE = DEFAULT_SUGGESTION_SIZE;
1758
1940
  exports.MAX_VISIBLE_SUGGESTIONS = MAX_VISIBLE_SUGGESTIONS;
1759
1941
  exports.RECENT_SEARCHES_DEFAULT_LIMIT = RECENT_SEARCHES_DEFAULT_LIMIT;
1760
1942
  exports.RECENT_SEARCHES_PREFIX = RECENT_SEARCHES_PREFIX;
1943
+ exports.SEARCH_GTM_EVENTS = SEARCH_GTM_EVENTS;
1944
+ exports.SEARCH_GTM_SEARCH_TYPES = SEARCH_GTM_SEARCH_TYPES;
1945
+ exports.SEARCH_GTM_USER_STATUS = SEARCH_GTM_USER_STATUS;
1761
1946
  exports.SEARCH_PLACEHOLDER = SEARCH_PLACEHOLDER;
1762
1947
  exports.STOREFRONT_SHOPPING_CONTEXT = STOREFRONT_SHOPPING_CONTEXT;
1763
1948
  exports.TRIGGER_PLACEHOLDER = TRIGGER_PLACEHOLDER;
@@ -1765,6 +1950,7 @@ exports.createChatService = createChatService;
1765
1950
  exports.createSearchService = createSearchService;
1766
1951
  exports.getImageFromProperty = getImageFromProperty;
1767
1952
  exports.getIngredientTerms = getIngredientTerms;
1953
+ exports.getLocaleFromUrl = getLocaleFromUrl;
1768
1954
  exports.getSeeMoreResultsPayload = getSeeMoreResultsPayload;
1769
1955
  exports.getVisibleSuggestions = getVisibleSuggestions;
1770
1956
  exports.isCartActionDisabled = isCartActionDisabled;
@@ -1772,8 +1958,13 @@ exports.isSellableProductStatus = isSellableProductStatus;
1772
1958
  exports.isSuggestionDisabled = isSuggestionDisabled;
1773
1959
  exports.mapCatalogProductToSuggestion = mapCatalogProductToSuggestion;
1774
1960
  exports.normalizeDidYouMean = normalizeDidYouMean;
1961
+ exports.pushGtmEvent = pushGtmEvent;
1775
1962
  exports.resolveApiGatewayPath = resolveApiGatewayPath;
1776
1963
  exports.resolveSuggestionImageSrc = resolveSuggestionImageSrc;
1964
+ exports.trackChatEntryPoint = trackChatEntryPoint;
1965
+ exports.trackErrorPopup = trackErrorPopup;
1966
+ exports.trackProductSearch = trackProductSearch;
1967
+ exports.trackSearchType = trackSearchType;
1777
1968
  exports.useSearchHistory = useSearchHistory;
1778
1969
  exports.useSearchHistoryStore = useSearchHistoryStore;
1779
1970
  exports.useSearchSuggestions = useSearchSuggestions;