@nuskin/react-search-sdk 1.0.0-comx-2233.4 → 1.0.0-trying-again.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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/services/SearchApiService.ts","../node_modules/eventsource-parser/src/errors.ts","../node_modules/eventsource-parser/src/parse.ts","../src/services/ChatService.ts","../src/utils/catalogHelpers.ts","../src/hooks/useSearchSuggestions.ts","../node_modules/zustand/esm/vanilla.mjs","../node_modules/zustand/esm/react.mjs","../node_modules/zustand/esm/middleware.mjs","../src/store/searchHistoryStore.ts","../src/hooks/useSearchHistory.ts","../src/hooks/useVoiceSearch.ts","../src/utils/commonUtils.ts","../src/utils/gtmConstants.ts","../src/utils/gtmTracking.ts"],"names":["optionHref","optionQuery","value","line","useState","useRef","useCallback","useEffect","React","getSessionStorage"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Constants for the search SDK. Ported from\n * `header-mfe/src/utils/search/search.constants.js` — only the values the\n * SDK itself needs (Phase 0 lift-and-shift). CMS keys, GTM tracking config,\n * and mobile-only placeholder rotation constants stay in header-mfe.\n */\n\n/** API shopping-context segment used when resolving the Equinox gateway URL. */\nexport const STOREFRONT_SHOPPING_CONTEXT = 'storefront';\n\n/** Catalog suggestions path appended when the market gateway is not already\n * under the storefront shopping context. */\nexport const CATALOG_SUGGESTIONS_PATH =\n '/storefront/catalogs/search/suggestions';\n\n/** Prefix for the `sessionStorage` key that persists recent searches.\n * Full key format: `${RECENT_SEARCHES_PREFIX}:{locale}:{COUNTRY}:{lang}`.\n * Must not change — existing sessions rely on this key. */\nexport const RECENT_SEARCHES_PREFIX = 'nuskin:header:recentSearches';\n\n/** Maximum number of recent searches persisted per locale bucket. */\nexport const RECENT_SEARCHES_DEFAULT_LIMIT = 10;\n\n/** Equinox suggestion pagination — page is 1-indexed. */\nexport const DEFAULT_SUGGESTION_PAGE = 1;\n\n/** Number of suggestion rows requested from the Equinox catalog per call. */\nexport const DEFAULT_SUGGESTION_SIZE = 6;\n\n/** Segment used when building the fallback search-results URL. */\nexport const DEFAULT_SEARCH_PATH = '/search';\n\n/** Debounce for typeahead input → API dispatch. Preserved from header-mfe. */\nexport const DEBOUNCE_MS = 220;\n\n/** Cap on suggestions rendered in the dropdown, regardless of API response size. */\nexport const MAX_VISIBLE_SUGGESTIONS = 6;\n\n/** Fallback placeholder shown inside the expanded search input. */\nexport const SEARCH_PLACEHOLDER =\n 'Search by product name, ingredient, benefits, or SKU';\n\n/** Fallback placeholder shown on the collapsed search trigger. */\nexport const TRIGGER_PLACEHOLDER = 'Product Search';\n\n/* -------------------------------------------------------------------------- */\n/* AI Search API paths */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Full path segment for the AI commerce chat SSE endpoint.\n * Appended to the consumer-provided `chatBaseUrl`.\n * Source: https://admin.tst.nuskin.ai/api/analytics/v1/embed\n */\nexport const DEFAULT_AI_CHAT_BASE_URL =\n 'https://admin.tst.nuskin.ai/api/analytics/v1/embed';\n\n/** Default POST endpoint for creating an AI chat conversation. */\nexport const DEFAULT_AI_CHAT_CONVERSATIONS_URL = `${DEFAULT_AI_CHAT_BASE_URL}/conversations`;\n\n/** Default POST endpoint for sending AI chat messages. */\nexport const DEFAULT_AI_CHAT_MESSAGES_URL = `${DEFAULT_AI_CHAT_BASE_URL}/messages`;\n","/**\n * SearchApiService — Phase 0 lift-and-shift of\n * `header-mfe/src/services/HeaderSearchService.js`.\n *\n * Behaviour follows the header search contract for URL formats,\n * `sessionStorage` key format, fetch parameter shape, and fallback values.\n * Navigation side effects are left to the consuming router.\n *\n * Two responsibilities were intentionally moved OUT of the SDK to preserve\n * the SDK-narrow boundary:\n * 1. Market-config resolution (`equinoxMarketsConfig.js` — depends on\n * `@nuskin/configuration-sdk`). Consumers inject a `getMarketConfig`\n * callback if they want automatic URL/store-id resolution.\n * 2. Locale resolution from the browser URL (`getLocale`). Consumers must\n * pass `country`/`language` explicitly.\n */\n\nimport {\n CATALOG_SUGGESTIONS_PATH,\n DEFAULT_SEARCH_PATH,\n DEFAULT_SUGGESTION_PAGE,\n DEFAULT_SUGGESTION_SIZE,\n RECENT_SEARCHES_DEFAULT_LIMIT,\n RECENT_SEARCHES_PREFIX,\n SEARCH_PLACEHOLDER,\n STOREFRONT_SHOPPING_CONTEXT,\n TRIGGER_PLACEHOLDER,\n} from '../constants';\nimport type {\n GetMarketConfig,\n LocaleParts,\n LocationLike,\n MarketConfig,\n SearchChromeCopy,\n SearchService,\n SearchServiceOptions,\n SuggestionOption,\n SuggestionsResponse,\n} from '../types';\n\nconst DEFAULT_SEARCH_PLACEHOLDER = TRIGGER_PLACEHOLDER;\nconst DEFAULT_INPUT_ARIA_LABEL = SEARCH_PLACEHOLDER;\n\n/* -------------------------------------------------------------------------- */\n/* Storage guards */\n/* -------------------------------------------------------------------------- */\n\nfunction canUseStorage(\n storage: Storage | null | undefined,\n): storage is Storage {\n return (\n Boolean(storage) && typeof (storage as Storage).getItem === 'function'\n );\n}\n\nfunction getSessionStorage(\n providedStorage: Storage | null | undefined,\n): Storage | null {\n if (providedStorage) return providedStorage;\n\n if (typeof window !== 'undefined') {\n try {\n return window.sessionStorage;\n } catch {\n return null;\n }\n }\n\n return null;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Locale + storage-key helpers */\n/* -------------------------------------------------------------------------- */\n\nfunction normalizeLocaleParts({\n country,\n language,\n locale,\n}: {\n country?: string | undefined;\n language?: string | undefined;\n locale?: string | undefined;\n} = {}): LocaleParts {\n const normalizedCountry = String(country ?? '')\n .trim()\n .toUpperCase();\n const normalizedLanguage = String(language ?? '')\n .trim()\n .toLowerCase();\n const normalizedLocale = String(locale ?? '').trim() || 'UNKNOWN';\n\n return {\n country: normalizedCountry || 'UNKNOWN',\n language: normalizedLanguage || 'unknown',\n locale: normalizedLocale,\n };\n}\n\nfunction getRecentHeaderSearchesStorageKey(localeParts: LocaleParts): string {\n const { country, language, locale } = normalizeLocaleParts(localeParts);\n return `${RECENT_SEARCHES_PREFIX}:${locale}:${country}:${language}`;\n}\n\nfunction getRecentHeaderSearches(\n localeParts: LocaleParts,\n storage: Storage | null,\n): string[] {\n if (!canUseStorage(storage)) {\n return [];\n }\n\n try {\n const rawValue = storage.getItem(\n getRecentHeaderSearchesStorageKey(localeParts),\n );\n if (!rawValue) {\n return [];\n }\n\n const parsedValue: unknown = JSON.parse(rawValue);\n if (!Array.isArray(parsedValue)) {\n return [];\n }\n\n return parsedValue\n .map((item) => String(item ?? '').trim())\n .filter(Boolean);\n } catch {\n return [];\n }\n}\n\nfunction addRecentHeaderSearch(\n localeParts: LocaleParts,\n query: string,\n storage: Storage | null,\n limit: number = RECENT_SEARCHES_DEFAULT_LIMIT,\n): string[] {\n const normalizedQuery = String(query ?? '').trim();\n if (!normalizedQuery || !canUseStorage(storage)) {\n return [];\n }\n\n try {\n const existingValues = getRecentHeaderSearches(\n localeParts,\n storage,\n ).filter(\n (item) => item.toLowerCase() !== normalizedQuery.toLowerCase(),\n );\n const nextValues = [normalizedQuery, ...existingValues].slice(0, limit);\n storage.setItem(\n getRecentHeaderSearchesStorageKey(localeParts),\n JSON.stringify(nextValues),\n );\n return nextValues;\n } catch {\n return [];\n }\n}\n\nfunction clearRecentHeaderSearches(\n localeParts: LocaleParts,\n storage: Storage | null,\n): void {\n if (!canUseStorage(storage)) {\n return;\n }\n\n try {\n storage.removeItem(getRecentHeaderSearchesStorageKey(localeParts));\n } catch {\n // intentionally quiet when storage is blocked/unavailable\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* Location helpers */\n/* -------------------------------------------------------------------------- */\n\nfunction getBrowserLocation(\n providedLocation: LocationLike | null | undefined,\n): LocationLike | null {\n if (providedLocation) return providedLocation;\n if (typeof window !== 'undefined' && window.location)\n return window.location;\n return null;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Market-config → URL/storeId resolution */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Replaces `{api_name}` in a market-config gateway path with the given API\n * name, then trims a single trailing slash. Ported from the equivalent helper\n * in `equinoxMarketsConfig.js` so the SDK has no runtime dependency on it.\n */\nexport function resolveApiGatewayPath(\n apiGatewayPath: string | undefined | null,\n apiName: string = STOREFRONT_SHOPPING_CONTEXT,\n): string {\n const apiGateway = String(apiGatewayPath ?? '').trim();\n if (!apiGateway) return '';\n return apiGateway.replace(/\\{api_name\\}/gi, apiName).replace(/\\/$/, '');\n}\n\nfunction resolveCatalogApiBaseUrl(\n marketConfig: MarketConfig | null | undefined,\n): string {\n return resolveApiGatewayPath(marketConfig?.api_gateway_path);\n}\n\nfunction resolveCatalogStoreId(\n marketConfig: MarketConfig | null | undefined,\n): string {\n return String(marketConfig?.store_id ?? '').trim();\n}\n\nfunction buildCatalogSuggestionsUrl(apiBaseUrl: string): string {\n const normalizedBase = String(apiBaseUrl ?? '')\n .trim()\n .replace(/\\/$/, '');\n if (!normalizedBase) return '';\n\n const suggestionsPath = normalizedBase.endsWith(\n `/${STOREFRONT_SHOPPING_CONTEXT}`,\n )\n ? '/catalogs/search/suggestions'\n : CATALOG_SUGGESTIONS_PATH;\n\n return `${normalizedBase}${suggestionsPath}`;\n}\n\nfunction resolveSuggestionsUrl(\n suggestionsApi: string | undefined,\n locationLike: LocationLike | null,\n): string {\n const pathOrUrl = String(suggestionsApi ?? '').trim();\n if (!pathOrUrl) return '';\n\n if (pathOrUrl.startsWith('http://') || pathOrUrl.startsWith('https://')) {\n return pathOrUrl;\n }\n\n const normalizedPath = pathOrUrl.startsWith('/')\n ? pathOrUrl\n : `/${pathOrUrl}`;\n const origin = String(locationLike?.origin ?? '').trim();\n return origin ? `${origin}${normalizedPath}` : normalizedPath;\n}\n\nasync function resolveCatalogRequestConfig({\n suggestionsApi,\n storeIdOption,\n locationLike,\n country,\n getMarketConfig,\n}: {\n suggestionsApi: string | undefined;\n storeIdOption: string | number | undefined;\n locationLike: LocationLike | null;\n country: string;\n getMarketConfig: GetMarketConfig | undefined;\n}): Promise<{ suggestionsUrl: string; storeId: string }> {\n const explicitStoreId =\n storeIdOption !== undefined &&\n storeIdOption !== null &&\n String(storeIdOption).trim() !== ''\n ? String(storeIdOption).trim()\n : '';\n\n const marketConfig = getMarketConfig\n ? ((await getMarketConfig({ locationLike, country })) ?? null)\n : null;\n const configuredApiBase = resolveCatalogApiBaseUrl(marketConfig);\n const configuredStoreId = resolveCatalogStoreId(marketConfig);\n const explicitSuggestionsApi = String(suggestionsApi ?? '').trim();\n\n return {\n suggestionsUrl: explicitSuggestionsApi\n ? resolveSuggestionsUrl(explicitSuggestionsApi, locationLike)\n : buildCatalogSuggestionsUrl(configuredApiBase),\n storeId: explicitStoreId || configuredStoreId,\n };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Path + slug helpers */\n/* -------------------------------------------------------------------------- */\n\nfunction toCatalogLocale(localeParts: LocaleParts): string {\n const language = String(localeParts.language ?? 'en').toLowerCase();\n const country = String(localeParts.country ?? 'US').toUpperCase();\n return `${language}_${country}`;\n}\n\nfunction buildSearchResultsPath(\n query: string,\n localeParts: LocaleParts,\n): string {\n const trimmedQuery = String(query ?? '').trim();\n const hyphenatedQuery = trimmedQuery.replace(/\\s+/g, '-');\n const encodedQuery = encodeURIComponent(hyphenatedQuery).replace(\n /%2D/gi,\n '-',\n );\n const country = localeParts.country.toLowerCase();\n const language = localeParts.language.toLowerCase();\n return `/${country}/${language}${DEFAULT_SEARCH_PATH}/${encodedQuery}`;\n}\n\nfunction normalizeOptionUrl(rawValue: unknown): string {\n if (typeof rawValue !== 'string') return '';\n return rawValue.trim();\n}\n\nfunction safeDecodeURIComponent(value: string): string {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n}\n\nfunction trimEdgeHyphens(value: string): string {\n let normalizedValue = value;\n while (normalizedValue.startsWith('-')) {\n normalizedValue = normalizedValue.slice(1);\n }\n while (normalizedValue.endsWith('-')) {\n normalizedValue = normalizedValue.slice(0, -1);\n }\n return normalizedValue;\n}\n\nfunction slugifyPathSegment(value: string | undefined | null): string {\n const decoded = safeDecodeURIComponent(String(value ?? '')).replace(\n /\\+/g,\n ' ',\n );\n const normalized = decoded\n .normalize('NFKD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/[^a-zA-Z0-9]+/g, '-')\n .replace(/-{2,}/g, '-')\n .toLowerCase();\n return trimEdgeHyphens(normalized);\n}\n\nfunction buildProductSlugPath(\n slugValue: string | undefined | null,\n localeParts: LocaleParts,\n): string {\n const slug = slugifyPathSegment(slugValue);\n if (!slug) return '';\n const country = String(localeParts.country ?? 'US').toLowerCase();\n const language = String(localeParts.language ?? 'en').toLowerCase();\n return `/${country}/${language}/product/${slug}`;\n}\n\nfunction isNavigableUrl(value: string): boolean {\n if (!value) return false;\n return value.startsWith('/') || /^https?:\\/\\//i.test(value);\n}\n\nfunction stripLocalePrefix(path: string, localeParts: LocaleParts): string {\n const prefix = `/${localeParts.country.toLowerCase()}/${localeParts.language.toLowerCase()}`;\n return path.startsWith(prefix) ? path.slice(prefix.length) || '/' : path;\n}\n\nfunction resolveOptionHref(\n option: SuggestionOption | null | undefined,\n localeParts: LocaleParts,\n): string {\n const productSlugPath = buildProductSlugPath(\n option?.slug ?? option?.productSlug ?? option?.product_slug ?? null,\n localeParts,\n );\n if (productSlugPath) {\n return productSlugPath;\n }\n\n const directUrl = normalizeOptionUrl(option?.href ?? option?.url);\n if (isNavigableUrl(directUrl) && !directUrl.includes('/chr/')) {\n return directUrl;\n }\n return '';\n}\n\n/* -------------------------------------------------------------------------- */\n/* Fetch helper */\n/* -------------------------------------------------------------------------- */\n\nasync function fetchJsonFromCandidates(\n fetchImpl: typeof fetch,\n requestUrls: string[],\n): Promise<unknown> {\n let lastError: unknown;\n\n for (const requestUrl of requestUrls) {\n try {\n const response = await fetchImpl(requestUrl, {\n method: 'GET',\n credentials: 'include',\n headers: { Accept: 'application/json' },\n });\n\n if (!response.ok) {\n lastError = new Error(\n `Request failed with status ${response.status}`,\n );\n continue;\n }\n\n return await response.json();\n } catch (error) {\n lastError = error;\n }\n }\n\n throw lastError ?? new Error('Unable to fetch header search data');\n}\n\n/* -------------------------------------------------------------------------- */\n/* Factory */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Creates a search service instance. All options are optional; sensible\n * fallbacks are used when the browser environment is absent (SSR).\n */\nexport function createSearchService(\n options: SearchServiceOptions = {},\n): SearchService {\n const {\n fetchImpl: fetchImplOption,\n location: providedLocation,\n storage: providedStorage,\n suggestionsApi,\n storeId: storeIdOption,\n country,\n language,\n locale,\n searchPlaceholder = DEFAULT_SEARCH_PLACEHOLDER,\n inputAriaLabel = DEFAULT_INPUT_ARIA_LABEL,\n getMarketConfig,\n } = options;\n\n const fetchImpl: typeof fetch | null =\n fetchImplOption !== undefined\n ? fetchImplOption\n : typeof fetch === 'function'\n ? fetch.bind(globalThis)\n : null;\n\n const locationLike = getBrowserLocation(providedLocation);\n const storage = getSessionStorage(providedStorage);\n const localeParts = normalizeLocaleParts({ country, language, locale });\n\n let catalogRequestConfigPromise: Promise<{\n suggestionsUrl: string;\n storeId: string;\n }> | null = null;\n\n function loadCatalogRequestConfig() {\n if (!catalogRequestConfigPromise) {\n catalogRequestConfigPromise = resolveCatalogRequestConfig({\n suggestionsApi,\n storeIdOption,\n locationLike,\n country: localeParts.country,\n getMarketConfig,\n });\n }\n return catalogRequestConfigPromise;\n }\n\n const service: SearchService = {\n async getSearchChromeCopy(): Promise<SearchChromeCopy> {\n return {\n placeholder: searchPlaceholder || DEFAULT_SEARCH_PLACEHOLDER,\n inputAriaLabel: inputAriaLabel || DEFAULT_INPUT_ARIA_LABEL,\n };\n },\n\n async fetchSuggestions(\n searchTerm: string,\n ): Promise<SuggestionsResponse> {\n const trimmedSearchTerm = String(searchTerm ?? '').trim();\n if (!trimmedSearchTerm || !fetchImpl) {\n return {\n suggestions: [],\n didYouMean: [],\n totalResultsCount: 0,\n };\n }\n\n const { suggestionsUrl, storeId } =\n await loadCatalogRequestConfig();\n\n if (!suggestionsUrl || !storeId) {\n return {\n suggestions: [],\n didYouMean: [],\n totalResultsCount: 0,\n };\n }\n\n const queryParams = new URLSearchParams({\n searchTerm: trimmedSearchTerm,\n page: String(DEFAULT_SUGGESTION_PAGE),\n size: String(DEFAULT_SUGGESTION_SIZE),\n locale: toCatalogLocale(localeParts),\n storeId: String(storeId),\n });\n\n const requestUrls = [`${suggestionsUrl}?${queryParams.toString()}`];\n\n const responsePayload = (await fetchJsonFromCandidates(\n fetchImpl,\n requestUrls,\n )) as SuggestionsResponse | null | undefined;\n\n const suggestionsField = Array.isArray(responsePayload?.suggestions)\n ? (responsePayload?.suggestions as unknown[])\n : [];\n const productField = Array.isArray(responsePayload?.product)\n ? (responsePayload?.product as unknown[])\n : null;\n\n const rawDidYouMean =\n responsePayload?.didYouMean ?? responsePayload?.did_you_mean;\n const didYouMeanField = Array.isArray(rawDidYouMean)\n ? (rawDidYouMean as unknown[])\n : [];\n\n const pageableTotal = Number(\n responsePayload?.pageableInfo?.totalCount ?? Number.NaN,\n );\n const totalResultsCount =\n typeof responsePayload?.totalResultsCount === 'number'\n ? responsePayload.totalResultsCount\n : !Number.isNaN(pageableTotal)\n ? pageableTotal\n : (productField?.length ?? suggestionsField.length);\n\n return {\n ...(responsePayload ?? {}),\n suggestions: suggestionsField,\n didYouMean: didYouMeanField,\n totalResultsCount,\n };\n },\n\n submitProductSearch(\n query: string,\n option?: SuggestionOption,\n ): string | undefined {\n const trimmedQuery = String(query ?? '').trim();\n if (!trimmedQuery) return undefined;\n\n addRecentHeaderSearch(localeParts, trimmedQuery, storage);\n\n const optionHref = resolveOptionHref(option, localeParts);\n if (optionHref) {\n return stripLocalePrefix(optionHref, localeParts);\n }\n\n const targetPath = buildSearchResultsPath(\n trimmedQuery,\n localeParts,\n );\n\n return stripLocalePrefix(targetPath, localeParts);\n },\n\n activateSuggestionAction(option: SuggestionOption): string | undefined {\n // If a cart action handler is provided, invoke it first\n if (options.onSuggestionAction) {\n const result = options.onSuggestionAction(option);\n // Handle both sync and async results\n if (result instanceof Promise) {\n result\n .then((handled) => {\n if (!handled) {\n // If not handled by callback, fall back to default navigation\n const optionHref = resolveOptionHref(\n option,\n localeParts,\n );\n if (!optionHref) {\n const optionQuery =\n option?.value ??\n option?.label ??\n option?.identifier ??\n '';\n service.submitProductSearch(\n String(optionQuery),\n );\n }\n }\n })\n .catch((error) => {\n console.error(\n 'Error in onSuggestionAction:',\n error,\n );\n });\n return 'action-pending';\n } else if (result === true) {\n // Callback handled the action, don't navigate\n return 'action-handled';\n }\n // result is false/undefined, fall through to default navigation\n }\n\n // Default behavior: navigate to URL or submit search\n const optionHref = resolveOptionHref(option, localeParts);\n if (optionHref) {\n return stripLocalePrefix(optionHref, localeParts);\n }\n\n const optionQuery =\n option?.value ?? option?.label ?? option?.identifier ?? '';\n return service.submitProductSearch(String(optionQuery));\n },\n\n getSuggestionHref(option: SuggestionOption): string {\n return stripLocalePrefix(\n resolveOptionHref(option, localeParts),\n localeParts,\n );\n },\n\n viewMoreResults({ query }: { query: string }): string | undefined {\n return service.submitProductSearch(query);\n },\n\n getRecentSearches(): string[] {\n return getRecentHeaderSearches(localeParts, storage);\n },\n\n clearRecentSearches(): void {\n clearRecentHeaderSearches(localeParts, storage);\n },\n };\n\n return service;\n}\n","/**\n * The type of error that occurred.\n * @public\n */\nexport type ErrorType = 'invalid-retry' | 'unknown-field' | 'max-buffer-size-exceeded'\n\n/**\n * Error thrown when encountering an issue during parsing.\n *\n * @public\n */\nexport class ParseError extends Error {\n /**\n * The type of error that occurred.\n */\n type: ErrorType\n\n /**\n * In the case of a completed unknown field encountered in the stream, this will be the field name.\n */\n field?: string | undefined\n\n /**\n * In the case of a completed unknown field encountered in the stream, this will be the value of the field.\n */\n value?: string | undefined\n\n /**\n * The line that caused the error, if available.\n */\n line?: string | undefined\n\n constructor(\n message: string,\n options: {type: ErrorType; field?: string; value?: string; line?: string},\n ) {\n super(message)\n this.name = 'ParseError'\n this.type = options.type\n this.field = options.field\n this.value = options.value\n this.line = options.line\n }\n}\n","/**\n * EventSource/Server-Sent Events parser\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html\n */\nimport {ParseError} from './errors.ts'\nimport type {EventSourceParser, ParserConfig} from './types.ts'\n\n// ASCII codes used in the hot parsing paths.\nconst LF = 10\nconst CR = 13\nconst SPACE = 32\nconst MAX_FIELD_PREFIX_LENGTH = 6\n\n// oxlint-disable-next-line no-unused-vars\nfunction noop(_arg: unknown) {\n // intentional noop\n}\n\n/**\n * Creates a new EventSource parser.\n *\n * @param config - Parser configuration. Accepts callbacks (see {@link ParserCallbacks})\n * and options like `maxBufferSize` (see {@link ParserConfig}).\n *\n * @returns A new EventSource parser, with `feed` and `reset` methods.\n * @public\n */\nexport function createParser(config: ParserConfig): EventSourceParser {\n if (typeof config === 'function') {\n throw new TypeError(\n '`config` must be an object, got a function instead. Did you mean `createParser({onEvent: fn})`?',\n )\n }\n\n const {onEvent = noop, onError = noop, onRetry = noop, onComment, maxBufferSize} = config\n\n // Trailing bytes from prior `feed()` calls that did not yet form a complete line.\n // Stored as an array of fragments and only joined when a line terminator arrives.\n // Concatenating per-feed (`prefix + chunk`) is O(N²) when a single SSE line spans\n // many chunks (e.g. a large `data:` payload streamed in tiny slices, or an MCP-style\n // server that emits one giant content block). Buffering as fragments + joining once\n // makes the same workload linear.\n const pendingFragments: string[] = []\n\n // Running total of `pendingFragments` lengths, kept in sync with the array so the\n // `maxBufferSize` check doesn't have to walk the fragment list on every feed.\n let pendingFragmentsLength = 0\n\n let isFirstChunk = true\n let id: string | undefined\n let data = ''\n let dataLines = 0\n let eventType: string | undefined\n\n // Set after a `maxBufferSize` overflow. Once tripped, `feed()` throws until\n // `reset()` is called — see the comment on `maxBufferSize` in `ParserConfig`.\n let terminated = false\n let skippingLine = false\n\n // Set when a line (parsed or discarded) was terminated by a trailing `\\r` at the very\n // end of a chunk. That `\\r` is ambiguous: it may be a bare-CR terminator or the first\n // half of a `\\r\\n` whose `\\n` lands in the next chunk. The line itself is complete\n // either way, but we must remember to swallow a single leading `\\n` from the next\n // chunk so the pair is treated as one terminator rather than a blank line (which\n // would dispatch an event prematurely).\n let skipNextLineFeed = false\n\n /**\n * Feeds a chunk of the SSE stream to the parser. Any trailing bytes that do\n * not yet form a complete line are held back and prepended to the next chunk,\n * so callers can pass arbitrary slices of the stream without worrying about\n * line boundaries.\n *\n * Per the SSE spec, one leading UTF-8 BOM at the start of the very first chunk\n * is stripped before parsing. This handles both the raw 3-byte form (0xEF 0xBB\n * 0xBF) and a single decoded U+FEFF, so a leading BOM is ignored regardless of\n * how the caller decoded the bytes.\n *\n * @see https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream\n */\n function feed(chunk: string) {\n if (terminated) {\n throw new Error(\n 'Cannot feed parser: it was terminated after exceeding the configured max buffer size. Call `reset()` to resume parsing.',\n )\n }\n\n if (isFirstChunk) {\n isFirstChunk = false\n // Strip one leading UTF-8 BOM from the start of the stream, if present.\n // (Per the spec, this is only valid at the very start of the stream.)\n // Two representations can reach us depending on how the caller decoded the\n // bytes: a single decoded U+FEFF (e.g. a `TextDecoder` created with\n // `ignoreBOM`) or the raw 3-byte sequence (0xEF 0xBB 0xBF, e.g. a latin1 or\n // passthrough decode). Both are stripped so a leading BOM is ignored\n // regardless of decode path.\n if (chunk.charCodeAt(0) === 0xfeff) {\n chunk = chunk.slice(1)\n } else if (\n chunk.charCodeAt(0) === 0xef &&\n chunk.charCodeAt(1) === 0xbb &&\n chunk.charCodeAt(2) === 0xbf\n ) {\n chunk = chunk.slice(3)\n }\n }\n\n // Rare resume states from a prior chunk boundary: a pending `\\r\\n` split or a\n // line being discarded. Single combined check keeps the hot path to one branch;\n // the actual handling lives out-of-line in `resumeAfterSkip`.\n if (skippingLine || skipNextLineFeed) {\n chunk = resumeAfterSkip(chunk)\n if (!chunk) {\n return\n }\n }\n\n // Hot path: no buffered prefix from a prior partial line. Hand the chunk\n // straight to `processLines`, exactly like the original implementation.\n // Zero new work in the common case (every chunk ends with `\\n\\n`).\n if (!pendingFragments.length) {\n const trailing = processLines(chunk)\n if (trailing !== '') {\n storeTrailing(trailing)\n }\n checkBufferSize()\n return\n }\n\n // We have a buffered prefix. If this chunk also has no terminator, append\n // to the buffer without concatenating — that's the O(N²) trap we're\n // avoiding (large single `data:` payload split across many tiny chunks).\n if (chunk.indexOf('\\n') === -1 && chunk.indexOf('\\r') === -1) {\n if (pendingFragmentsLength < MAX_FIELD_PREFIX_LENGTH) {\n const head =\n pendingFragments.join('') +\n chunk.slice(0, MAX_FIELD_PREFIX_LENGTH - pendingFragmentsLength)\n if (!shouldBufferTrailing(head)) {\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n skippingLine = true\n return\n }\n }\n pendingFragments.push(chunk)\n pendingFragmentsLength += chunk.length\n checkBufferSize()\n return\n }\n\n // Terminator arrived. Join the accumulated fragments + this chunk once,\n // process, and buffer any new trailing partial line.\n pendingFragments.push(chunk)\n const input = pendingFragments.join('')\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n storeTrailing(processLines(input))\n checkBufferSize()\n }\n\n // Out-of-line handler for the rare post-boundary states. `skipNextLineFeed` means a\n // line (parsed or discarded) ended with a trailing `\\r` at the previous chunk boundary,\n // so a single leading `\\n` must be swallowed to consume a split `\\r\\n` as one terminator.\n // `skippingLine` means we are discarding an invalid line until its terminator arrives.\n // The two states are mutually exclusive. Returns the remaining chunk to parse ('' if\n // this chunk was fully consumed).\n function resumeAfterSkip(chunk: string): string {\n if (chunk.length === 0) {\n return chunk\n }\n\n if (skipNextLineFeed) {\n skipNextLineFeed = false\n return chunk.charCodeAt(0) === LF ? chunk.slice(1) : chunk\n }\n\n const crIndex = chunk.indexOf('\\r')\n const lfIndex = chunk.indexOf('\\n')\n const lineEnd =\n crIndex === -1 ? lfIndex : lfIndex === -1 ? crIndex : crIndex < lfIndex ? crIndex : lfIndex\n\n if (lineEnd === -1) {\n return ''\n }\n\n // Trailing `\\r` at the very end of the chunk: defer the CRLF/CR decision to the\n // next chunk (see `skipNextLineFeed`) rather than greedily consuming just the `\\r`.\n if (lineEnd === chunk.length - 1 && chunk.charCodeAt(lineEnd) === CR) {\n skippingLine = false\n skipNextLineFeed = true\n return ''\n }\n\n skippingLine = false\n return chunk.slice(\n lineEnd + (chunk.charCodeAt(lineEnd) === CR && chunk.charCodeAt(lineEnd + 1) === LF ? 2 : 1),\n )\n }\n\n function storeTrailing(trailing: string) {\n if (!trailing) return\n\n // A trailing that ends with `\\r` is not a partial line: the `\\r` terminates it,\n // and only the CRLF-vs-CR ambiguity remains (the matching `\\n` may start the next\n // chunk). Parse the completed line now — buffering it could grow unbounded through\n // the no-terminator append path, and discarding it would eat the terminator and\n // make skip mode swallow the next line.\n if (trailing.charCodeAt(trailing.length - 1) === CR) {\n parseLine(trailing, 0, trailing.length - 1)\n skipNextLineFeed = true\n return\n }\n\n if (shouldBufferTrailing(trailing)) {\n pendingFragments.push(trailing)\n pendingFragmentsLength = trailing.length\n return\n }\n\n skippingLine = true\n }\n\n function shouldBufferTrailing(trailing: string) {\n const firstCharCode = trailing.charCodeAt(0)\n return (\n (firstCharCode === 58 && !!onComment) ||\n (firstCharCode === 100 && isPotentialField(trailing, 'data')) ||\n (firstCharCode === 101 && isPotentialField(trailing, 'event')) ||\n (firstCharCode === 105 && isPotentialField(trailing, 'id')) ||\n (firstCharCode === 114 && isPotentialField(trailing, 'retry'))\n )\n }\n\n function checkBufferSize() {\n if (maxBufferSize === undefined) return\n if (pendingFragmentsLength + data.length <= maxBufferSize) return\n\n terminated = true\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n skippingLine = false\n skipNextLineFeed = false\n onError(\n new ParseError(`Buffered data exceeded max buffer size of ${maxBufferSize} characters`, {\n type: 'max-buffer-size-exceeded',\n }),\n )\n }\n\n /**\n * Splits `chunk` into SSE lines and dispatches each to the appropriate handler.\n * Returns any trailing bytes that did not terminate with a line break, so the\n * caller can prepend them to the next chunk.\n *\n * The SSE spec permits three line terminators: `\\n`, `\\r`, and `\\r\\n`. Real-world\n * streams almost always use plain `\\n`, so we take a fast path when no `\\r` is\n * present in the chunk. The slow path is spec-correct but does more work per line.\n */\n function processLines(chunk: string): string {\n let searchIndex = 0\n\n // Fast path: LF-only chunk (the common case for typical SSE servers).\n // We can scan forward with a single `indexOf('\\n')` per line and inline\n // the hot-path branches for `data:` and `event:` without the CR bookkeeping\n // the slow path needs.\n if (chunk.indexOf('\\r') === -1) {\n let lfIndex = chunk.indexOf('\\n', searchIndex)\n while (lfIndex !== -1) {\n // Blank line: end-of-event marker. Dispatch the accumulated event (if any)\n // and reset the buffered fields. This is hoisted out of `parseLine` because\n // it's the single most common line shape after `data:` lines.\n if (searchIndex === lfIndex) {\n if (dataLines > 0) {\n onEvent({id, event: eventType, data})\n }\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n searchIndex = lfIndex + 1\n lfIndex = chunk.indexOf('\\n', searchIndex)\n continue\n }\n const firstCharCode = chunk.charCodeAt(searchIndex)\n if (isDataPrefix(chunk, searchIndex, firstCharCode)) {\n // `data:` line — append the value to the event's data buffer.\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart =\n chunk.charCodeAt(searchIndex + 5) === SPACE ? searchIndex + 6 : searchIndex + 5\n const value = chunk.slice(valueStart, lfIndex)\n // Fast path within a fast path: if this is the first data line AND the\n // next char is another LF (i.e. `data:foo\\n\\n`), dispatch immediately\n // without ever writing to the `data` buffer. This is the shape of a\n // typical single-line SSE event (ChatGPT-style streams, etc.) and is\n // hot enough to be worth the duplication.\n if (dataLines === 0 && chunk.charCodeAt(lfIndex + 1) === LF) {\n onEvent({id, event: eventType, data: value})\n id = undefined\n data = ''\n eventType = undefined\n searchIndex = lfIndex + 2\n lfIndex = chunk.indexOf('\\n', searchIndex)\n continue\n }\n // Multi-line data: concatenate with newline separator per spec.\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n } else if (isEventPrefix(chunk, searchIndex, firstCharCode)) {\n // `event:` line — set the event type for the next dispatch. Per spec,\n // an empty value resets `event type` to its default (undefined here).\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(\n chunk.charCodeAt(searchIndex + 6) === SPACE ? searchIndex + 7 : searchIndex + 6,\n lfIndex,\n ) || undefined\n } else {\n // Everything else: `id:`, `retry:`, comment lines (`:` prefix), unknown\n // fields, or malformed lines. These are rarer and go through the full\n // per-line parser, which handles the SSE field grammar in detail.\n parseLine(chunk, searchIndex, lfIndex)\n }\n searchIndex = lfIndex + 1\n lfIndex = chunk.indexOf('\\n', searchIndex)\n }\n return chunk.slice(searchIndex)\n }\n\n // Slow path: the chunk contains at least one `\\r`, so lines may be terminated\n // by `\\r`, `\\n`, or `\\r\\n`. We locate the next terminator by looking at both\n // the nearest `\\r` and `\\n` and picking whichever comes first.\n while (searchIndex < chunk.length) {\n const crIndex = chunk.indexOf('\\r', searchIndex)\n const lfIndex = chunk.indexOf('\\n', searchIndex)\n\n let lineEnd = -1\n if (crIndex !== -1 && lfIndex !== -1) {\n lineEnd = crIndex < lfIndex ? crIndex : lfIndex\n } else if (crIndex !== -1) {\n // A trailing `\\r` at the very end of the chunk is ambiguous: it could be\n // a bare-CR terminator, or the first half of a `\\r\\n` whose `\\n` arrives\n // in the next chunk. Defer until we see more input.\n if (crIndex === chunk.length - 1) {\n lineEnd = -1\n } else {\n lineEnd = crIndex\n }\n } else if (lfIndex !== -1) {\n lineEnd = lfIndex\n }\n\n if (lineEnd === -1) {\n break\n }\n\n parseLine(chunk, searchIndex, lineEnd)\n searchIndex = lineEnd + 1\n // If we just consumed a `\\r` and the next char is `\\n`, skip it so the\n // pair is treated as a single terminator rather than an empty line.\n if (chunk.charCodeAt(searchIndex - 1) === CR && chunk.charCodeAt(searchIndex) === LF) {\n searchIndex++\n }\n }\n\n return chunk.slice(searchIndex)\n }\n\n function parseLine(chunk: string, start: number, end: number) {\n if (start === end) {\n dispatchEvent()\n return\n }\n\n const firstCharCode = chunk.charCodeAt(start)\n\n if (isDataPrefix(chunk, start, firstCharCode)) {\n // 'data:'.length === 5, 'data: '.length === 6\n const valueStart = chunk.charCodeAt(start + 5) === SPACE ? start + 6 : start + 5\n const value = chunk.slice(valueStart, end)\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n return\n }\n\n if (isEventPrefix(chunk, start, firstCharCode)) {\n // 'event:'.length === 6, 'event: '.length === 7\n eventType =\n chunk.slice(chunk.charCodeAt(start + 6) === SPACE ? start + 7 : start + 6, end) || undefined\n return\n }\n\n // Fast path for \"id:\" — 'i' = 105, 'd' = 100, ':' = 58\n if (\n firstCharCode === 105 &&\n chunk.charCodeAt(start + 1) === 100 &&\n chunk.charCodeAt(start + 2) === 58\n ) {\n // 'id:'.length === 3, 'id: '.length === 4\n const value = chunk.slice(chunk.charCodeAt(start + 3) === SPACE ? start + 4 : start + 3, end)\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n if (!value.includes('\\0')) id = value\n return\n }\n\n // Comment line — ':' = 58\n if (firstCharCode === 58) {\n if (onComment) {\n const line = chunk.slice(start, end)\n // skip ':' (+1), or ': ' (+2) when a space follows\n onComment(line.slice(chunk.charCodeAt(start + 1) === SPACE ? 2 : 1))\n }\n return\n }\n\n const line = chunk.slice(start, end)\n const fieldSeparatorIndex = line.indexOf(':')\n if (fieldSeparatorIndex === -1) {\n processField(line, '', line)\n return\n }\n\n const field = line.slice(0, fieldSeparatorIndex)\n // skip ':' (+1), or ': ' (+2) when a space follows\n const offset = line.charCodeAt(fieldSeparatorIndex + 1) === SPACE ? 2 : 1\n const value = line.slice(fieldSeparatorIndex + offset)\n processField(field, value, line)\n }\n\n function processField(field: string, value: string, line: string) {\n // Field names must be compared literally, with no case folding performed.\n switch (field) {\n case 'event':\n // Set the `event type` buffer to field value\n eventType = value || undefined\n break\n case 'data':\n data = dataLines === 0 ? value : `${data}\\n${value}`\n dataLines++\n break\n case 'id':\n // If the field value does not contain U+0000 NULL, then set the `ID` buffer to\n // the field value. Otherwise, ignore the field.\n if (!value.includes('\\0')) id = value\n break\n case 'retry':\n // If the field value consists of only ASCII digits, then interpret the field value as an\n // integer in base ten, and set the event stream's reconnection time to that integer.\n // Otherwise, ignore the field.\n if (/^\\d+$/.test(value)) {\n onRetry(parseInt(value, 10))\n } else {\n onError(\n new ParseError(`Invalid \\`retry\\` value: \"${value}\"`, {\n type: 'invalid-retry',\n value,\n line,\n }),\n )\n }\n break\n default:\n // Otherwise, the field is ignored.\n onError(\n new ParseError(\n `Unknown field \"${field.length > 20 ? `${field.slice(0, 20)}…` : field}\"`,\n {type: 'unknown-field', field, value, line},\n ),\n )\n break\n }\n }\n\n function dispatchEvent() {\n if (dataLines > 0) {\n onEvent({\n id,\n event: eventType,\n data,\n })\n }\n\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n }\n\n function reset(options: {consume?: boolean} = {}) {\n if (options.consume && pendingFragments.length > 0) {\n const incompleteLine = pendingFragments.join('')\n parseLine(incompleteLine, 0, incompleteLine.length)\n }\n\n isFirstChunk = true\n id = undefined\n data = ''\n dataLines = 0\n eventType = undefined\n pendingFragments.length = 0\n pendingFragmentsLength = 0\n terminated = false\n skippingLine = false\n skipNextLineFeed = false\n }\n\n return {feed, reset}\n}\n\n/**\n * Checks if `chunk` starts with the literal `data:` at index `i`.\n *\n * Equivalent to `chunk.startsWith('data:', i)`, but benchmarks show this\n * hand-unrolled char-code comparison is ~20% faster on common event types.\n * The caller passes `firstCharCode` (the code at `i`) so it can be reused\n * across prefix checks.\n *\n * ASCII: 'd' = 100, 'a' = 97, 't' = 116, 'a' = 97, ':' = 58\n */\nfunction isDataPrefix(chunk: string, i: number, firstCharCode: number): boolean {\n return (\n firstCharCode === 100 &&\n chunk.charCodeAt(i + 1) === 97 &&\n chunk.charCodeAt(i + 2) === 116 &&\n chunk.charCodeAt(i + 3) === 97 &&\n chunk.charCodeAt(i + 4) === 58\n )\n}\n\n/**\n * Checks if `chunk` starts with the literal `event:` at index `i`.\n *\n * See {@link isDataPrefix} for why this is hand-unrolled rather than using\n * `String.prototype.startsWith`.\n *\n * ASCII: 'e' = 101, 'v' = 118, 'e' = 101, 'n' = 110, 't' = 116, ':' = 58\n */\nfunction isEventPrefix(chunk: string, i: number, firstCharCode: number): boolean {\n return (\n firstCharCode === 101 &&\n chunk.charCodeAt(i + 1) === 118 &&\n chunk.charCodeAt(i + 2) === 101 &&\n chunk.charCodeAt(i + 3) === 110 &&\n chunk.charCodeAt(i + 4) === 116 &&\n chunk.charCodeAt(i + 5) === 58\n )\n}\n\nfunction isPotentialField(line: string, field: string): boolean {\n let i = 1\n while (i < line.length && i < field.length) {\n if (line.charCodeAt(i) !== field.charCodeAt(i)) {\n return false\n }\n i++\n }\n\n return line.length <= field.length || line.charCodeAt(field.length) === 58\n}\n","/**\n * ChatService — two-step NuSkin AI chat API.\n *\n * Step 1: POST /chat/conversations → receives conversation_id\n * Step 2: POST /chat/messages → SSE stream parsed with eventsource-parser\n *\n * Products are embedded in AI response content as ```products [...] ``` code blocks.\n */\n\nimport { createParser } from 'eventsource-parser';\nimport {\n DEFAULT_AI_CHAT_CONVERSATIONS_URL,\n DEFAULT_AI_CHAT_MESSAGES_URL,\n} from '../constants';\n\n/* -------------------------------------------------------------------------- */\n/* Public types */\n/* -------------------------------------------------------------------------- */\n\nexport interface ChatProduct {\n sku: string;\n name: string;\n category?: string;\n pv?: number;\n retail_price?: number;\n description?: string;\n image_url?: string;\n badge?: string;\n [key: string]: unknown;\n}\n\nexport interface ChatMessageResult {\n summary: string;\n products: ChatProduct[];\n /** Raw accumulated content including markdown, for downstream rendering. */\n rawContent: string;\n}\n\nexport interface ChatServiceOptions {\n /** POST endpoint for creating a conversation. */\n conversationsUrl?: string;\n /** POST endpoint for sending a message (SSE response). */\n messagesUrl?: string;\n /** X-Sales-AI-App-Key header value (from CS configurations). */\n salesAiAppKey?: string;\n /** X-Sales-AI-Parent-Origin header value (from CS configurations). */\n salesAiParentOrigin?: string;\n /** Market code (e.g., \"US\", \"JP\") for scope_context in message requests. */\n market?: string;\n /** Language code (e.g., \"en\", \"ja\") for scope_context in message requests. */\n language?: string;\n /** Override fetch for testing. */\n fetchImpl?: typeof fetch | null;\n}\n\nexport interface ChatService {\n /** Creates a conversation and returns the numeric conversation ID. */\n createConversation: (title?: string) => Promise<number>;\n /** Sends a message and streams back a parsed result. */\n sendMessage: (\n conversationId: number,\n content: string,\n onChunk?: (type: string, text: string) => void,\n ) => Promise<ChatMessageResult>;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Helpers */\n/* -------------------------------------------------------------------------- */\n\nconst PRODUCTS_OPENING_FENCE = '```products';\nconst MARKDOWN_CLOSING_FENCE = '\\n```';\n\nfunction findProductsBlockStart(\n content: string,\n openingFenceIndex: number,\n): number | null {\n let blockStart = openingFenceIndex + PRODUCTS_OPENING_FENCE.length;\n while (\n blockStart < content.length &&\n (content[blockStart] === ' ' ||\n content[blockStart] === '\\t' ||\n content[blockStart] === '\\r')\n ) {\n blockStart += 1;\n }\n return content[blockStart] === '\\n' ? blockStart + 1 : null;\n}\n\nfunction isStandaloneClosingFence(content: string, fenceEnd: number): boolean {\n const lineEnd = content.indexOf('\\n', fenceEnd);\n const suffixEnd = lineEnd === -1 ? content.length : lineEnd;\n return content.slice(fenceEnd, suffixEnd).trim() === '';\n}\n\nfunction findClosingFence(content: string, fromIndex: number): number {\n let candidate = content.indexOf(MARKDOWN_CLOSING_FENCE, fromIndex);\n while (candidate !== -1) {\n const fenceEnd = candidate + MARKDOWN_CLOSING_FENCE.length;\n if (isStandaloneClosingFence(content, fenceEnd)) {\n return candidate;\n }\n candidate = content.indexOf(MARKDOWN_CLOSING_FENCE, fenceEnd);\n }\n return -1;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object';\n}\n\nfunction getRenderProductListItems(\n event: Record<string, unknown>,\n): ChatProduct[] {\n if (event['type'] !== 'render' || event['pattern'] !== 'product_list') {\n return [];\n }\n\n const data = event['data'];\n if (!isRecord(data) || !Array.isArray(data['items'])) {\n return [];\n }\n\n return data['items'].filter(isRecord) as ChatProduct[];\n}\n\n/** Extracts ```products [...] ``` JSON blocks from markdown content. */\nfunction extractProductsFromMarkdown(content: string): {\n summary: string;\n products: ChatProduct[];\n} {\n const products: ChatProduct[] = [];\n const summaryParts: string[] = [];\n let summaryCursor = 0;\n let searchCursor = 0;\n\n while (searchCursor < content.length) {\n const start = content.indexOf(PRODUCTS_OPENING_FENCE, searchCursor);\n if (start === -1) break;\n\n const blockStart = findProductsBlockStart(content, start);\n if (blockStart === null) {\n searchCursor = start + PRODUCTS_OPENING_FENCE.length;\n continue;\n }\n\n const nextOpeningFence = content.indexOf(\n PRODUCTS_OPENING_FENCE,\n blockStart,\n );\n const end = findClosingFence(content, blockStart);\n if (end === -1) break;\n if (nextOpeningFence !== -1 && nextOpeningFence < end) {\n searchCursor = nextOpeningFence;\n continue;\n }\n\n try {\n const parsed: unknown = JSON.parse(content.slice(blockStart, end));\n if (Array.isArray(parsed)) {\n products.push(...(parsed as ChatProduct[]));\n }\n } catch (e) {\n console.error('Failed to parse products block:', e);\n }\n summaryParts.push(content.slice(summaryCursor, start));\n summaryCursor = end + MARKDOWN_CLOSING_FENCE.length;\n searchCursor = summaryCursor;\n }\n\n summaryParts.push(content.slice(summaryCursor));\n\n return { summary: summaryParts.join('').trim(), products };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Factory */\n/* -------------------------------------------------------------------------- */\n\nexport function createChatService(options: ChatServiceOptions): ChatService {\n const {\n conversationsUrl = DEFAULT_AI_CHAT_CONVERSATIONS_URL,\n messagesUrl = DEFAULT_AI_CHAT_MESSAGES_URL,\n salesAiAppKey,\n salesAiParentOrigin,\n market,\n language,\n fetchImpl: fetchImplOption,\n } = options;\n\n let fetchImpl: typeof fetch;\n if (fetchImplOption !== undefined) {\n fetchImpl = fetchImplOption as typeof fetch;\n } else if (typeof fetch === 'function') {\n fetchImpl = fetch.bind(globalThis);\n } else {\n fetchImpl = (() => {\n throw new Error('ChatService: no fetch implementation available');\n }) as unknown as typeof fetch;\n }\n\n function buildHeaders(\n extra?: Record<string, string>,\n includeJsonContentType = true,\n ): Record<string, string> {\n const headers: Record<string, string> = {\n ...extra,\n };\n\n if (includeJsonContentType) {\n headers['Content-Type'] = 'application/json';\n }\n\n // Get access token from localStorage (if \"accessToken\" key exists)\n const accessToken =\n typeof window !== 'undefined'\n ? window.localStorage?.getItem('accessToken')\n : null;\n if (accessToken) {\n headers['Authorization'] = `Bearer ${accessToken}`;\n }\n\n // Add X-Sales-AI-App-Key if provided\n if (salesAiAppKey) {\n headers['X-Sales-AI-App-Key'] = salesAiAppKey;\n }\n\n // Add X-Sales-AI-Parent-Origin if provided\n if (salesAiParentOrigin) {\n headers['X-Sales-AI-Parent-Origin'] = salesAiParentOrigin;\n }\n\n return headers;\n }\n\n return {\n async createConversation(): Promise<number> {\n const res = await fetchImpl(conversationsUrl, {\n method: 'POST',\n headers: buildHeaders(undefined, false),\n });\n if (!res.ok) {\n throw new Error(\n `ChatService.createConversation: ${res.status} ${res.statusText}`,\n );\n }\n const data = (await res.json()) as Record<string, unknown>;\n const id = data['id'] ?? data['conversation_id'];\n if (typeof id !== 'number') {\n throw new TypeError(\n 'ChatService.createConversation: response missing numeric id',\n );\n }\n return id;\n },\n\n async sendMessage(\n conversationId,\n content,\n onChunk,\n ): Promise<ChatMessageResult> {\n const requestBody: Record<string, unknown> = {\n conversation_id: conversationId,\n content,\n };\n\n // Add scope_context with market and language if available\n if (market || language) {\n requestBody.scope_context = {\n market: market ?? 'US',\n language: language ?? 'en',\n };\n }\n\n // Add client_capabilities with product_list and follow_up patterns\n requestBody.client_capabilities = {\n patterns: {\n product_list: [1],\n follow_up: [1],\n },\n };\n\n const res = await fetchImpl(messagesUrl, {\n method: 'POST',\n headers: buildHeaders({ Accept: 'text/event-stream' }),\n body: JSON.stringify(requestBody),\n });\n if (!res.ok) {\n throw new Error(\n `ChatService.sendMessage: ${res.status} ${res.statusText}`,\n );\n }\n\n let accumulated = '';\n const renderedProducts: ChatProduct[] = [];\n\n const parser = createParser({\n onEvent(event) {\n const data = event.data;\n if (!data || data === '[DONE]') return;\n try {\n const parsed = JSON.parse(data) as Record<\n string,\n unknown\n >;\n const parsedType = parsed['type'];\n const type =\n typeof parsedType === 'string' ? parsedType : '';\n renderedProducts.push(\n ...getRenderProductListItems(parsed),\n );\n if (\n type === 'content' &&\n typeof parsed['text'] === 'string'\n ) {\n const text = parsed['text'];\n accumulated += text;\n onChunk?.(type, text);\n } else if (\n type === 'status' &&\n typeof parsed['message'] === 'string'\n ) {\n const message = parsed['message'];\n onChunk?.(type, message);\n }\n } catch {\n // skip malformed event\n }\n },\n });\n\n // Stream the SSE body so status events surface as they arrive\n const body = res.body;\n if (body && typeof body.getReader === 'function') {\n const reader = body.getReader();\n const decoder = new TextDecoder();\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n parser.feed(decoder.decode(value, { stream: true }));\n }\n parser.feed(decoder.decode());\n } else {\n const rawBody = await res.text();\n parser.feed(rawBody);\n }\n\n const { summary, products } =\n extractProductsFromMarkdown(accumulated);\n\n const finalProducts =\n renderedProducts.length > 0 ? renderedProducts : products;\n\n return {\n summary,\n products: finalProducts,\n rawContent: accumulated,\n };\n },\n };\n}\n","/**\n * Catalog-product normalisation helpers — Phase 0 lift-and-shift of the\n * relevant portions of\n * `header-mfe/src/components/search/auto-complete/autoComplete.helpers.js`.\n *\n * Only the data-processing helpers are included here. UI-specific helpers\n * (keyboard event handlers, ARIA attribute computation, display-data\n * extraction) live in `react-search-components` because they depend on DOM\n * refs and component-level props.\n *\n * Key difference from the original:\n * `resolveSuggestionImageSrc` returns `\"\"` when the source is absent\n * instead of falling back to a bundled PNG asset. Components apply their\n * own `<img onError>` / CSS placeholder; the SDK must not bundle assets.\n */\n\nimport type {\n CatalogSuggestionItem,\n DidYouMeanItem,\n ProductType,\n} from '../types';\n\n/* -------------------------------------------------------------------------- */\n/* Product-status helpers */\n/* -------------------------------------------------------------------------- */\n\nconst CART_DISABLED_PRODUCT_STATUSES = new Set([\n 'discontinued',\n 'preview',\n 'previewproduct',\n 'test',\n 'stopped',\n 'replacement',\n 'bundleonly',\n 'inactive',\n 'notavailable',\n]);\n\nfunction normalizeProductStatusValue(value: unknown): string {\n return String(value ?? '')\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '');\n}\n\n/** Returns `true` when `productStatus` is `\"sellable\"`. */\nexport function isSellableProductStatus(productStatus: unknown): boolean {\n return normalizeProductStatusValue(productStatus) === 'sellable';\n}\n\nfunction resolveSkuStatusValues(\n suggestionOption: Record<string, unknown>,\n): string[] {\n return [\n suggestionOption['productStatus'],\n suggestionOption['product_status'],\n suggestionOption['status'],\n suggestionOption['sku_status'],\n ]\n .map(normalizeProductStatusValue)\n .filter(Boolean);\n}\n\nfunction isNonSellableStatusValue(statusValue: string): boolean {\n if (CART_DISABLED_PRODUCT_STATUSES.has(statusValue)) {\n return true;\n }\n return statusValue !== 'sellable' && statusValue !== 'active';\n}\n\n/**\n * Returns `true` when the suggestion option should not allow add-to-cart\n * (out of stock, discontinued, inactive, etc.).\n */\nexport function isCartActionDisabled(\n suggestionOption: Record<string, unknown> | null | undefined,\n): boolean {\n if (!suggestionOption) {\n return true;\n }\n\n const outOfStock =\n suggestionOption['out_of_stock'] ?? suggestionOption['outOfStock'];\n if (outOfStock) {\n return true;\n }\n\n const statusValues = resolveSkuStatusValues(suggestionOption);\n if (statusValues.length === 0) {\n return false;\n }\n\n return statusValues.some(isNonSellableStatusValue);\n}\n\n/**\n * Returns `true` when the suggestion row should be displayed as\n * non-interactive (out-of-stock only — a subset of `isCartActionDisabled`).\n */\nexport function isSuggestionDisabled(\n suggestionOption: Record<string, unknown> | null | undefined,\n): boolean {\n return Boolean(\n !suggestionOption ||\n suggestionOption['out_of_stock'] ||\n suggestionOption['outOfStock'],\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Image helpers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Reads the first non-empty image URL from a Contentstack / catalog property\n * bag. Returns `\"\"` when no image is found.\n */\nexport function getImageFromProperty(\n properties: Record<string, unknown> = {},\n): string {\n let image =\n String(properties['primaryimage'] ?? '').trim() ||\n String(properties['imageURL'] ?? '').trim();\n\n if (!image) {\n try {\n const parsed: unknown = JSON.parse(\n String(properties['productImages'] ?? '{}'),\n );\n if (\n Array.isArray(parsed) &&\n parsed[0] &&\n typeof parsed[0] === 'object'\n ) {\n image = String(\n (parsed[0] as Record<string, unknown>)['url'] ?? '',\n ).trim();\n }\n } catch {\n image = '';\n }\n }\n\n return image;\n}\n\n/**\n * Normalises an image source value. Returns `\"\"` when the source is absent or\n * blank. Components are responsible for applying a fallback placeholder image.\n */\nexport function resolveSuggestionImageSrc(imageSrc: unknown): string {\n const trimmed =\n typeof imageSrc === 'string'\n ? imageSrc.trim()\n : String(imageSrc ?? '').trim();\n return trimmed;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Ingredient terms */\n/* -------------------------------------------------------------------------- */\n\nfunction safeParseJsonArray(value: unknown): unknown[] {\n if (Array.isArray(value)) {\n return value;\n }\n\n if (typeof value !== 'string' || !value.trim()) {\n return [];\n }\n\n try {\n const parsed: unknown = JSON.parse(value);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\n/**\n * Extracts a flat list of ingredient terms from a Contentstack ingredient\n * structure. Used to populate `CatalogSuggestionItem.ingredientTerms`.\n */\nexport function getIngredientTerms(rawIngredients: unknown): string[] {\n const ingredientGroups = safeParseJsonArray(rawIngredients);\n\n return ingredientGroups\n .flatMap((ingredientGroup) => {\n if (!ingredientGroup || typeof ingredientGroup !== 'object') {\n return [];\n }\n const group = ingredientGroup as Record<string, unknown>;\n const keyIngredients = Array.isArray(group['keyIngredients'])\n ? (\n group['keyIngredients'] as Array<Record<string, unknown>>\n ).map((ingredient) => ingredient['name'])\n : [];\n\n return [\n group['productName'],\n group['activeIngredients'],\n group['inactiveIngredients'],\n group['allIngredients'],\n group['otherIngredients'],\n ...keyIngredients,\n ];\n })\n .filter(Boolean)\n .map((term) => String(term).trim())\n .filter(Boolean);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Catalog product → suggestion mapping */\n/* -------------------------------------------------------------------------- */\n\nfunction getSkuProperties(product: Record<string, unknown>): {\n defaultSku: Record<string, unknown> | null;\n skuProperties: Record<string, unknown>;\n} {\n const skuList = Array.isArray(product['sku'])\n ? (product['sku'] as Array<Record<string, unknown>>)\n : [];\n const defaultSku =\n skuList.find((skuEntry) => skuEntry?.['default'] === true) ??\n skuList[0] ??\n null;\n return {\n defaultSku: defaultSku ?? null,\n skuProperties:\n ((defaultSku as Record<string, unknown> | null)?.[\n 'properties'\n ] as Record<string, unknown>) ?? {},\n };\n}\n\nfunction getIdentifier(\n product: Record<string, unknown>,\n defaultSku: Record<string, unknown> | null,\n index: number,\n): string {\n return String(\n defaultSku?.['identifier'] ??\n product['identifier'] ??\n `catalog-product-${index}`,\n ).trim();\n}\n\nfunction getDisplayLabel(\n identifier: string,\n productProperties: Record<string, unknown>,\n skuProperties: Record<string, unknown>,\n): string {\n return String(\n skuProperties['title'] ??\n productProperties['name'] ??\n productProperties['title'] ??\n skuProperties['name'] ??\n identifier,\n );\n}\n\nfunction getTypeData(\n product: Record<string, unknown>,\n productProperties: Record<string, unknown>,\n skuProperties: Record<string, unknown>,\n): { customProductType: string; isBundle: boolean } {\n const customProductType = String(\n productProperties['customProductType'] ??\n skuProperties['customProductType'] ??\n '',\n ).trim();\n const normalizedType = String(\n product['type'] ??\n productProperties['producttype'] ??\n skuProperties['producttype'] ??\n '',\n )\n .trim()\n .toLowerCase();\n return {\n customProductType,\n isBundle:\n normalizedType === 'bundle' ||\n customProductType.toLowerCase().includes('bundle'),\n };\n}\n\nfunction getNavigationUrls(\n productProperties: Record<string, unknown>,\n skuProperties: Record<string, unknown>,\n): { navigableUrl: string | null; slug: string | null } {\n const slug =\n String(\n skuProperties['slug'] ?? productProperties['slug'] ?? '',\n ).trim() || null;\n const navigableUrl =\n String(\n skuProperties['url'] ??\n skuProperties['href'] ??\n productProperties['url'] ??\n productProperties['href'] ??\n '',\n ).trim() || null;\n return { navigableUrl, slug };\n}\n\nfunction isOutOfStock(inventoryStatus: unknown): boolean {\n return String(inventoryStatus).toUpperCase() === 'OUT OF STOCK';\n}\n\nfunction getCatalogStatusFields(\n skuProperties: Record<string, unknown>,\n productProperties: Record<string, unknown>,\n): {\n normalizedProductStatus: string;\n normalizedSkuStatus: string;\n outOfStock: boolean;\n cartActionDisabled: boolean;\n} {\n const inventoryStatus =\n skuProperties['inventoryStatus'] ??\n productProperties['inventoryStatus'] ??\n '';\n const productStatus =\n skuProperties['productStatus'] ??\n productProperties['productStatus'] ??\n '';\n const skuStatus =\n skuProperties['status'] ?? productProperties['status'] ?? '';\n const normalizedProductStatus = String(productStatus).trim();\n const normalizedSkuStatus = String(skuStatus).trim();\n const outOfStock = isOutOfStock(inventoryStatus);\n\n return {\n normalizedProductStatus,\n normalizedSkuStatus,\n outOfStock,\n cartActionDisabled: isCartActionDisabled({\n outOfStock,\n productStatus: normalizedProductStatus || undefined,\n status: normalizedSkuStatus || undefined,\n }),\n };\n}\n\nfunction optionalNonEmptyString(value: string): string | undefined {\n const normalized = String(value ?? '').trim();\n return normalized || undefined;\n}\n\nfunction getProductImageSrc(opts: {\n product: Record<string, unknown>;\n productProperties: Record<string, unknown>;\n skuProperties: Record<string, unknown>;\n}): string {\n const normalizedType = String(opts.product['type'] ?? '')\n .trim()\n .toLowerCase();\n\n if (normalizedType === 'kit' || normalizedType === 'bundle') {\n return getImageFromProperty(opts.productProperties);\n }\n\n return getImageFromProperty(opts.skuProperties);\n}\n\n/**\n * Maps a raw Equinox catalog product object to the normalised\n * `CatalogSuggestionItem` shape consumed by the UI components.\n * Returns `null` for invalid input so callers can `.filter(Boolean)`.\n */\nexport function mapCatalogProductToSuggestion(\n product: unknown,\n index: number = 0,\n): CatalogSuggestionItem | null {\n if (!product || typeof product !== 'object') {\n return null;\n }\n\n const p = product as Record<string, unknown>;\n const productProperties =\n (p['properties'] as Record<string, unknown>) ?? {};\n const { defaultSku, skuProperties } = getSkuProperties(p);\n const identifier = getIdentifier(p, defaultSku, index);\n const { customProductType, isBundle } = getTypeData(\n p,\n productProperties,\n skuProperties,\n );\n const { navigableUrl, slug } = getNavigationUrls(\n productProperties,\n skuProperties,\n );\n const statusFields = getCatalogStatusFields(\n skuProperties,\n productProperties,\n );\n const imageSrc = resolveSuggestionImageSrc(\n getProductImageSrc({ product: p, productProperties, skuProperties }),\n );\n const mappedProductType: ProductType = isBundle ? 'bundle' : 'single';\n\n return {\n id: identifier,\n identifier,\n sku: identifier,\n label: getDisplayLabel(identifier, productProperties, skuProperties),\n value: getDisplayLabel(identifier, productProperties, skuProperties),\n imageURL: imageSrc,\n thumbnail: imageSrc,\n productType: mappedProductType,\n product_type: mappedProductType,\n outOfStock: statusFields.outOfStock,\n productStatus: optionalNonEmptyString(\n statusFields.normalizedProductStatus,\n ),\n status: optionalNonEmptyString(statusFields.normalizedSkuStatus),\n cartActionDisabled: statusFields.cartActionDisabled,\n customProductType,\n slug,\n productSlug: slug,\n url: navigableUrl,\n href: navigableUrl,\n keywords: String(\n (productProperties['keyword'] as unknown) ??\n (skuProperties['keyword'] as unknown) ??\n '',\n ),\n ingredientTerms: getIngredientTerms(\n skuProperties['ingredients'] ?? productProperties['ingredients'],\n ),\n };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Did-you-mean normalisation */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Normalises the raw `didYouMean` / `did_you_mean` array from the Equinox\n * API into a consistent shape consumed by `useSearchSuggestions`.\n */\nexport function normalizeDidYouMean(didYouMean: unknown): DidYouMeanItem[] {\n if (!Array.isArray(didYouMean)) {\n return [];\n }\n\n return didYouMean\n .map((item: unknown, index: number): DidYouMeanItem | null => {\n if (typeof item === 'string') {\n return {\n id: `did-you-mean-${index}-${item}`,\n value: item,\n suggestionType: 'did-you-mean',\n };\n }\n\n if (item && typeof item === 'object') {\n const obj = item as Record<string, unknown>;\n return {\n ...obj,\n id: String(\n obj['id'] ??\n `did-you-mean-${index}-${obj['value'] ?? obj['label'] ?? ''}`,\n ),\n value: String(obj['value'] ?? ''),\n suggestionType: 'did-you-mean',\n };\n }\n\n return null;\n })\n .filter((item): item is DidYouMeanItem => item !== null);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Suggestion list helpers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Returns the items that should actually be rendered in the suggestions list.\n * When \"Did You Mean?\" results are present they take precedence over product\n * suggestions (matching the original header-mfe behaviour).\n */\nexport function getVisibleSuggestions(opts: {\n didYouMean: DidYouMeanItem[];\n suggestions: CatalogSuggestionItem[];\n}): DidYouMeanItem[] | CatalogSuggestionItem[] {\n if (opts.didYouMean.length > 0) {\n return opts.didYouMean;\n }\n return opts.suggestions;\n}\n\n/**\n * Builds the analytics payload emitted when the user clicks \"See More Results\".\n */\nexport function getSeeMoreResultsPayload(\n query: string,\n totalResultsCount: number,\n suggestions: CatalogSuggestionItem[],\n): {\n query: string;\n source: string;\n totalResultsCount: number;\n visibleResultsCount: number;\n} {\n return {\n query,\n source: 'autocomplete-footer',\n totalResultsCount,\n visibleResultsCount: suggestions.length,\n };\n}\n","/**\n * useSearchSuggestions — Phase 0 lift-and-shift of\n * `header-mfe/src/components/search/auto-complete/hooks/useAutoComplete.js`\n * (`useAutoCompleteSuggestions` export).\n *\n * Behaviour is preserved verbatim:\n * - 220 ms debounce (DEBOUNCE_MS constant — do not change)\n * - Request-ID stale-response guard (replaces AbortController in the original)\n * - `MAX_VISIBLE_SUGGESTIONS` cap applied before setting state\n * - `didYouMean` items take precedence: when present, `suggestions` is set\n * to `[]` and the DYM items are used as the visible list\n * - `emptyFetched` is only set to `true` when BOTH arrays are empty after\n * a successful fetch\n * - `enabled = false` clears state without firing an API call\n *\n * Keyboard navigation (`useAutoCompleteKeyboard`) and all display-data helpers\n * live in `react-search-components` — they depend on DOM refs and component props.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type React from 'react';\n\nimport { DEBOUNCE_MS, MAX_VISIBLE_SUGGESTIONS } from '../constants';\nimport {\n mapCatalogProductToSuggestion,\n normalizeDidYouMean,\n} from '../utils/catalogHelpers';\nimport type {\n CatalogSuggestionItem,\n DidYouMeanItem,\n SuggestionsResponse,\n UseSearchSuggestionsOptions,\n UseSearchSuggestionsResult,\n} from '../types';\n\n/* -------------------------------------------------------------------------- */\n/* Internal normalisation (mirrors useAutoComplete.js) */\n/* -------------------------------------------------------------------------- */\n\ninterface NormalizedSuggestions {\n suggestions: CatalogSuggestionItem[];\n didYouMean: DidYouMeanItem[];\n}\n\nfunction normalizeSuggestionsResponse(\n response: SuggestionsResponse | unknown,\n): NormalizedSuggestions {\n // Raw array fallback (some API variants return an array directly)\n if (Array.isArray(response)) {\n return {\n suggestions: response as CatalogSuggestionItem[],\n didYouMean: [],\n };\n }\n\n if (!response || typeof response !== 'object') {\n return { suggestions: [], didYouMean: [] };\n }\n\n const r = response as SuggestionsResponse;\n\n // Equinox catalog API returns a `product` array\n if (Array.isArray(r.product)) {\n return {\n suggestions: (r.product as unknown[])\n .map((product, index) =>\n mapCatalogProductToSuggestion(product, index),\n )\n .filter((item): item is CatalogSuggestionItem => item !== null),\n didYouMean: normalizeDidYouMean(r.didYouMean ?? r.did_you_mean),\n };\n }\n\n // Generic suggestions array fallback\n return {\n suggestions: Array.isArray(r.suggestions)\n ? (r.suggestions as CatalogSuggestionItem[])\n : [],\n didYouMean: normalizeDidYouMean(r.didYouMean),\n };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Hook */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Manages debounced typeahead suggestions from the Equinox catalog API.\n *\n * @example\n * ```tsx\n * const service = createSearchService({ country, language, locale, suggestionsApi, storeId });\n * const { suggestions, didYouMean, loading, updateQuery, clearQuery } =\n * useSearchSuggestions({ service });\n * ```\n */\nexport function useSearchSuggestions({\n service,\n enabled = true,\n}: UseSearchSuggestionsOptions): UseSearchSuggestionsResult {\n const [query, setQuery] = useState('');\n const [suggestions, setSuggestions] = useState<CatalogSuggestionItem[]>([]);\n const [didYouMean, setDidYouMean] = useState<DidYouMeanItem[]>([]);\n const [loading, setLoading] = useState(false);\n const [emptyFetched, setEmptyFetched] = useState(false);\n const [suggestionFetchFailed, setSuggestionFetchFailed] = useState(false);\n const [hasMoreResults, setHasMoreResults] = useState(false);\n const [totalResultsCount, setTotalResultsCount] = useState(0);\n\n const fetchDebounced = useRef<ReturnType<typeof setTimeout> | null>(null);\n const latestRequestId = useRef(0);\n\n const resetSuggestionsState = useCallback(() => {\n setSuggestions([]);\n setDidYouMean([]);\n setEmptyFetched(false);\n setSuggestionFetchFailed(false);\n setHasMoreResults(false);\n setTotalResultsCount(0);\n setLoading(false);\n }, []);\n\n const updateQuery = useCallback(\n (nextQuery: string) => {\n const hasNextQuery = Boolean(nextQuery.trim());\n setEmptyFetched(false);\n setSuggestionFetchFailed(false);\n setLoading(enabled && hasNextQuery);\n setQuery(nextQuery);\n },\n [enabled],\n );\n\n const clearQuery = useCallback(() => {\n resetSuggestionsState();\n setQuery('');\n }, [resetSuggestionsState]);\n\n const runFetch = useCallback(\n async (nextQuery: string) => {\n const trimmedQuery = nextQuery.trim();\n const requestId = latestRequestId.current;\n\n if (!trimmedQuery || !enabled) {\n resetSuggestionsState();\n return;\n }\n\n setLoading(true);\n setEmptyFetched(false);\n setSuggestionFetchFailed(false);\n\n try {\n const fetchedSuggestions =\n await service.fetchSuggestions(trimmedQuery);\n\n // Discard stale response if a newer request has since been issued\n if (requestId !== latestRequestId.current) {\n return;\n }\n\n const {\n suggestions: allSuggestions,\n didYouMean: suggestedTerms,\n } = normalizeSuggestionsResponse(fetchedSuggestions);\n\n const visibleSuggestions = allSuggestions.slice(\n 0,\n MAX_VISIBLE_SUGGESTIONS,\n );\n const hasDidYouMean = suggestedTerms.length > 0;\n\n const normalizedTotal =\n typeof fetchedSuggestions.totalResultsCount === 'number'\n ? fetchedSuggestions.totalResultsCount\n : typeof fetchedSuggestions.pageableInfo?.totalCount ===\n 'number'\n ? fetchedSuggestions.pageableInfo.totalCount\n : allSuggestions.length;\n\n const effectiveTotal = hasDidYouMean\n ? suggestedTerms.length\n : Math.max(normalizedTotal, allSuggestions.length);\n\n setDidYouMean(suggestedTerms);\n setSuggestions(hasDidYouMean ? [] : visibleSuggestions);\n setHasMoreResults(\n !hasDidYouMean && effectiveTotal > MAX_VISIBLE_SUGGESTIONS,\n );\n setTotalResultsCount(effectiveTotal);\n setSuggestionFetchFailed(false);\n setEmptyFetched(\n hasDidYouMean\n ? false\n : visibleSuggestions.length === 0 &&\n suggestedTerms.length === 0,\n );\n } catch {\n if (requestId !== latestRequestId.current) {\n return;\n }\n setSuggestions([]);\n setDidYouMean([]);\n setEmptyFetched(true);\n setSuggestionFetchFailed(true);\n setHasMoreResults(false);\n setTotalResultsCount(0);\n } finally {\n if (requestId === latestRequestId.current) {\n setLoading(false);\n }\n }\n },\n [enabled, service, resetSuggestionsState],\n );\n\n useEffect(() => {\n if (!enabled) {\n resetSuggestionsState();\n return undefined;\n }\n\n if (fetchDebounced.current) {\n clearTimeout(fetchDebounced.current);\n }\n\n // Mark any in-flight request as stale before the debounce fires\n latestRequestId.current += 1;\n\n fetchDebounced.current = setTimeout(() => {\n void runFetch(query);\n }, DEBOUNCE_MS);\n\n return () => {\n if (fetchDebounced.current) {\n clearTimeout(fetchDebounced.current);\n }\n };\n }, [enabled, query, resetSuggestionsState, runFetch]);\n\n return {\n clearQuery,\n emptyFetched,\n hasMoreResults,\n hasQuery: Boolean(query.trim()),\n didYouMean,\n loading,\n query,\n setQuery: setQuery as React.Dispatch<React.SetStateAction<string>>,\n suggestionFetchFailed,\n suggestions,\n totalResultsCount,\n updateQuery,\n };\n}\n","const createStoreImpl = (createState) => {\n let state;\n const listeners = /* @__PURE__ */ new Set();\n const setState = (partial, replace) => {\n const nextState = typeof partial === \"function\" ? partial(state) : partial;\n if (!Object.is(nextState, state)) {\n const previousState = state;\n state = (replace != null ? replace : typeof nextState !== \"object\" || nextState === null) ? nextState : Object.assign({}, state, nextState);\n listeners.forEach((listener) => listener(state, previousState));\n }\n };\n const getState = () => state;\n const getInitialState = () => initialState;\n const subscribe = (listener) => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n };\n const api = { setState, getState, getInitialState, subscribe };\n const initialState = state = createState(setState, getState, api);\n return api;\n};\nconst createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;\n\nexport { createStore };\n","import React from 'react';\nimport { createStore } from 'zustand/vanilla';\n\nconst identity = (arg) => arg;\nfunction useStore(api, selector = identity) {\n const slice = React.useSyncExternalStore(\n api.subscribe,\n () => selector(api.getState()),\n () => selector(api.getInitialState())\n );\n React.useDebugValue(slice);\n return slice;\n}\nconst createImpl = (createState) => {\n const api = createStore(createState);\n const useBoundStore = (selector) => useStore(api, selector);\n Object.assign(useBoundStore, api);\n return useBoundStore;\n};\nconst create = (createState) => createState ? createImpl(createState) : createImpl;\n\nexport { create, useStore };\n","const reduxImpl = (reducer, initial) => (set, _get, api) => {\n api.dispatch = (action) => {\n set((state) => reducer(state, action), false, action);\n return action;\n };\n api.dispatchFromDevtools = true;\n return { dispatch: (...a) => api.dispatch(...a), ...initial };\n};\nconst redux = reduxImpl;\n\nconst trackedConnections = /* @__PURE__ */ new Map();\nconst getTrackedConnectionState = (name) => {\n const api = trackedConnections.get(name);\n if (!api) return {};\n return Object.fromEntries(\n Object.entries(api.stores).map(([key, api2]) => [key, api2.getState()])\n );\n};\nconst extractConnectionInformation = (store, extensionConnector, options) => {\n if (store === void 0) {\n return {\n type: \"untracked\",\n connection: extensionConnector.connect(options)\n };\n }\n const existingConnection = trackedConnections.get(options.name);\n if (existingConnection) {\n return { type: \"tracked\", store, ...existingConnection };\n }\n const newConnection = {\n connection: extensionConnector.connect(options),\n stores: {}\n };\n trackedConnections.set(options.name, newConnection);\n return { type: \"tracked\", store, ...newConnection };\n};\nconst devtoolsImpl = (fn, devtoolsOptions = {}) => (set, get, api) => {\n const { enabled, anonymousActionType, store, ...options } = devtoolsOptions;\n let extensionConnector;\n try {\n extensionConnector = (enabled != null ? enabled : (import.meta.env ? import.meta.env.MODE : void 0) !== \"production\") && window.__REDUX_DEVTOOLS_EXTENSION__;\n } catch (e) {\n }\n if (!extensionConnector) {\n return fn(set, get, api);\n }\n const { connection, ...connectionInformation } = extractConnectionInformation(store, extensionConnector, options);\n let isRecording = true;\n api.setState = (state, replace, nameOrAction) => {\n const r = set(state, replace);\n if (!isRecording) return r;\n const action = nameOrAction === void 0 ? { type: anonymousActionType || \"anonymous\" } : typeof nameOrAction === \"string\" ? { type: nameOrAction } : nameOrAction;\n if (store === void 0) {\n connection == null ? void 0 : connection.send(action, get());\n return r;\n }\n connection == null ? void 0 : connection.send(\n {\n ...action,\n type: `${store}/${action.type}`\n },\n {\n ...getTrackedConnectionState(options.name),\n [store]: api.getState()\n }\n );\n return r;\n };\n const setStateFromDevtools = (...a) => {\n const originalIsRecording = isRecording;\n isRecording = false;\n set(...a);\n isRecording = originalIsRecording;\n };\n const initialState = fn(api.setState, get, api);\n if (connectionInformation.type === \"untracked\") {\n connection == null ? void 0 : connection.init(initialState);\n } else {\n connectionInformation.stores[connectionInformation.store] = api;\n connection == null ? void 0 : connection.init(\n Object.fromEntries(\n Object.entries(connectionInformation.stores).map(([key, store2]) => [\n key,\n key === connectionInformation.store ? initialState : store2.getState()\n ])\n )\n );\n }\n if (api.dispatchFromDevtools && typeof api.dispatch === \"function\") {\n let didWarnAboutReservedActionType = false;\n const originalDispatch = api.dispatch;\n api.dispatch = (...a) => {\n if ((import.meta.env ? import.meta.env.MODE : void 0) !== \"production\" && a[0].type === \"__setState\" && !didWarnAboutReservedActionType) {\n console.warn(\n '[zustand devtools middleware] \"__setState\" action type is reserved to set state from the devtools. Avoid using it.'\n );\n didWarnAboutReservedActionType = true;\n }\n originalDispatch(...a);\n };\n }\n connection.subscribe((message) => {\n var _a;\n switch (message.type) {\n case \"ACTION\":\n if (typeof message.payload !== \"string\") {\n console.error(\n \"[zustand devtools middleware] Unsupported action format\"\n );\n return;\n }\n return parseJsonThen(\n message.payload,\n (action) => {\n if (action.type === \"__setState\") {\n if (store === void 0) {\n setStateFromDevtools(action.state);\n return;\n }\n if (Object.keys(action.state).length !== 1) {\n console.error(\n `\n [zustand devtools middleware] Unsupported __setState action format.\n When using 'store' option in devtools(), the 'state' should have only one key, which is a value of 'store' that was passed in devtools(),\n and value of this only key should be a state object. Example: { \"type\": \"__setState\", \"state\": { \"abc123Store\": { \"foo\": \"bar\" } } }\n `\n );\n }\n const stateFromDevtools = action.state[store];\n if (stateFromDevtools === void 0 || stateFromDevtools === null) {\n return;\n }\n if (JSON.stringify(api.getState()) !== JSON.stringify(stateFromDevtools)) {\n setStateFromDevtools(stateFromDevtools);\n }\n return;\n }\n if (!api.dispatchFromDevtools) return;\n if (typeof api.dispatch !== \"function\") return;\n api.dispatch(action);\n }\n );\n case \"DISPATCH\":\n switch (message.payload.type) {\n case \"RESET\":\n setStateFromDevtools(initialState);\n if (store === void 0) {\n return connection == null ? void 0 : connection.init(api.getState());\n }\n return connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n case \"COMMIT\":\n if (store === void 0) {\n connection == null ? void 0 : connection.init(api.getState());\n return;\n }\n return connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n case \"ROLLBACK\":\n return parseJsonThen(message.state, (state) => {\n if (store === void 0) {\n setStateFromDevtools(state);\n connection == null ? void 0 : connection.init(api.getState());\n return;\n }\n setStateFromDevtools(state[store]);\n connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n });\n case \"JUMP_TO_STATE\":\n case \"JUMP_TO_ACTION\":\n return parseJsonThen(message.state, (state) => {\n if (store === void 0) {\n setStateFromDevtools(state);\n return;\n }\n if (JSON.stringify(api.getState()) !== JSON.stringify(state[store])) {\n setStateFromDevtools(state[store]);\n }\n });\n case \"IMPORT_STATE\": {\n const { nextLiftedState } = message.payload;\n const lastComputedState = (_a = nextLiftedState.computedStates.slice(-1)[0]) == null ? void 0 : _a.state;\n if (!lastComputedState) return;\n if (store === void 0) {\n setStateFromDevtools(lastComputedState);\n } else {\n setStateFromDevtools(lastComputedState[store]);\n }\n connection == null ? void 0 : connection.send(\n null,\n // FIXME no-any\n nextLiftedState\n );\n return;\n }\n case \"PAUSE_RECORDING\":\n return isRecording = !isRecording;\n }\n return;\n }\n });\n return initialState;\n};\nconst devtools = devtoolsImpl;\nconst parseJsonThen = (stringified, f) => {\n let parsed;\n try {\n parsed = JSON.parse(stringified);\n } catch (e) {\n console.error(\n \"[zustand devtools middleware] Could not parse the received json\",\n e\n );\n }\n if (parsed !== void 0) f(parsed);\n};\n\nconst subscribeWithSelectorImpl = (fn) => (set, get, api) => {\n const origSubscribe = api.subscribe;\n api.subscribe = (selector, optListener, options) => {\n let listener = selector;\n if (optListener) {\n const equalityFn = (options == null ? void 0 : options.equalityFn) || Object.is;\n let currentSlice = selector(api.getState());\n listener = (state) => {\n const nextSlice = selector(state);\n if (!equalityFn(currentSlice, nextSlice)) {\n const previousSlice = currentSlice;\n optListener(currentSlice = nextSlice, previousSlice);\n }\n };\n if (options == null ? void 0 : options.fireImmediately) {\n optListener(currentSlice, currentSlice);\n }\n }\n return origSubscribe(listener);\n };\n const initialState = fn(set, get, api);\n return initialState;\n};\nconst subscribeWithSelector = subscribeWithSelectorImpl;\n\nconst combine = (initialState, create) => (...a) => Object.assign({}, initialState, create(...a));\n\nfunction createJSONStorage(getStorage, options) {\n let storage;\n try {\n storage = getStorage();\n } catch (e) {\n return;\n }\n const persistStorage = {\n getItem: (name) => {\n var _a;\n const parse = (str2) => {\n if (str2 === null) {\n return null;\n }\n return JSON.parse(str2, options == null ? void 0 : options.reviver);\n };\n const str = (_a = storage.getItem(name)) != null ? _a : null;\n if (str instanceof Promise) {\n return str.then(parse);\n }\n return parse(str);\n },\n setItem: (name, newValue) => storage.setItem(\n name,\n JSON.stringify(newValue, options == null ? void 0 : options.replacer)\n ),\n removeItem: (name) => storage.removeItem(name)\n };\n return persistStorage;\n}\nconst toThenable = (fn) => (input) => {\n try {\n const result = fn(input);\n if (result instanceof Promise) {\n return result;\n }\n return {\n then(onFulfilled) {\n return toThenable(onFulfilled)(result);\n },\n catch(_onRejected) {\n return this;\n }\n };\n } catch (e) {\n return {\n then(_onFulfilled) {\n return this;\n },\n catch(onRejected) {\n return toThenable(onRejected)(e);\n }\n };\n }\n};\nconst persistImpl = (config, baseOptions) => (set, get, api) => {\n let options = {\n storage: createJSONStorage(() => localStorage),\n partialize: (state) => state,\n version: 0,\n merge: (persistedState, currentState) => ({\n ...currentState,\n ...persistedState\n }),\n ...baseOptions\n };\n let hasHydrated = false;\n const hydrationListeners = /* @__PURE__ */ new Set();\n const finishHydrationListeners = /* @__PURE__ */ new Set();\n let storage = options.storage;\n if (!storage) {\n return config(\n (...args) => {\n console.warn(\n `[zustand persist middleware] Unable to update item '${options.name}', the given storage is currently unavailable.`\n );\n set(...args);\n },\n get,\n api\n );\n }\n const setItem = () => {\n const state = options.partialize({ ...get() });\n return storage.setItem(options.name, {\n state,\n version: options.version\n });\n };\n const savedSetState = api.setState;\n api.setState = (state, replace) => {\n savedSetState(state, replace);\n void setItem();\n };\n const configResult = config(\n (...args) => {\n set(...args);\n void setItem();\n },\n get,\n api\n );\n api.getInitialState = () => configResult;\n let stateFromStorage;\n const hydrate = () => {\n var _a, _b;\n if (!storage) return;\n hasHydrated = false;\n hydrationListeners.forEach((cb) => {\n var _a2;\n return cb((_a2 = get()) != null ? _a2 : configResult);\n });\n const postRehydrationCallback = ((_b = options.onRehydrateStorage) == null ? void 0 : _b.call(options, (_a = get()) != null ? _a : configResult)) || void 0;\n return toThenable(storage.getItem.bind(storage))(options.name).then((deserializedStorageValue) => {\n if (deserializedStorageValue) {\n if (typeof deserializedStorageValue.version === \"number\" && deserializedStorageValue.version !== options.version) {\n if (options.migrate) {\n return [\n true,\n options.migrate(\n deserializedStorageValue.state,\n deserializedStorageValue.version\n )\n ];\n }\n console.error(\n `State loaded from storage couldn't be migrated since no migrate function was provided`\n );\n } else {\n return [false, deserializedStorageValue.state];\n }\n }\n return [false, void 0];\n }).then((migrationResult) => {\n var _a2;\n const [migrated, migratedState] = migrationResult;\n stateFromStorage = options.merge(\n migratedState,\n (_a2 = get()) != null ? _a2 : configResult\n );\n set(stateFromStorage, true);\n if (migrated) {\n return setItem();\n }\n }).then(() => {\n postRehydrationCallback == null ? void 0 : postRehydrationCallback(stateFromStorage, void 0);\n stateFromStorage = get();\n hasHydrated = true;\n finishHydrationListeners.forEach((cb) => cb(stateFromStorage));\n }).catch((e) => {\n postRehydrationCallback == null ? void 0 : postRehydrationCallback(void 0, e);\n });\n };\n api.persist = {\n setOptions: (newOptions) => {\n options = {\n ...options,\n ...newOptions\n };\n if (newOptions.storage) {\n storage = newOptions.storage;\n }\n },\n clearStorage: () => {\n storage == null ? void 0 : storage.removeItem(options.name);\n },\n getOptions: () => options,\n rehydrate: () => hydrate(),\n hasHydrated: () => hasHydrated,\n onHydrate: (cb) => {\n hydrationListeners.add(cb);\n return () => {\n hydrationListeners.delete(cb);\n };\n },\n onFinishHydration: (cb) => {\n finishHydrationListeners.add(cb);\n return () => {\n finishHydrationListeners.delete(cb);\n };\n }\n };\n if (!options.skipHydration) {\n hydrate();\n }\n return stateFromStorage || configResult;\n};\nconst persist = persistImpl;\n\nexport { combine, createJSONStorage, devtools, persist, redux, subscribeWithSelector };\n","/**\n * Tab-scoped recent search history store.\n * Each entry records the query, whether it was an AI search, and (for AI) the response payload.\n * Uses sessionStorage so entries survive page refresh but are cleared on tab close.\n */\nimport { create } from 'zustand';\nimport { persist, createJSONStorage } from 'zustand/middleware';\n\nconst MAX_HISTORY = 10;\n\nexport interface SearchHistoryEntry {\n query: string;\n isAI: boolean;\n /** Serialized AI result payload; consumers cast to their concrete result type */\n aiResult?: unknown;\n timestamp: number;\n}\n\nexport interface SearchHistoryState {\n entries: SearchHistoryEntry[];\n /** Save a full entry (AI or non-AI); deduplicates by query (case-insensitive). */\n addEntry: (entry: Omit<SearchHistoryEntry, 'timestamp'>) => void;\n /** Convenience alias — saves a plain non-AI query entry. */\n addQuery: (query: string) => void;\n removeEntry: (query: string) => void;\n clearAll: () => void;\n}\n\nexport const useSearchHistoryStore = create<SearchHistoryState>()(\n persist(\n (set) => ({\n entries: [],\n\n addEntry: (entry) => {\n const trimmed = entry.query.trim();\n if (!trimmed) return;\n set((state) => {\n const deduped = state.entries.filter(\n (e) => e.query.toLowerCase() !== trimmed.toLowerCase(),\n );\n const newEntry: SearchHistoryEntry = {\n ...entry,\n query: trimmed,\n timestamp: Date.now(),\n };\n return {\n entries: [newEntry, ...deduped].slice(0, MAX_HISTORY),\n };\n });\n },\n\n addQuery: (query: string) => {\n const trimmed = query.trim();\n if (!trimmed) return;\n set((state) => {\n const deduped = state.entries.filter(\n (e) => e.query.toLowerCase() !== trimmed.toLowerCase(),\n );\n return {\n entries: [\n {\n query: trimmed,\n isAI: false,\n timestamp: Date.now(),\n },\n ...deduped,\n ].slice(0, MAX_HISTORY),\n };\n });\n },\n\n removeEntry: (query: string) =>\n set((state) => ({\n entries: state.entries.filter((e) => e.query !== query),\n })),\n\n clearAll: () => set({ entries: [] }),\n }),\n {\n name: 'ai_search_recent_queries',\n version: 1,\n storage: createJSONStorage(() =>\n typeof window !== 'undefined'\n ? window.sessionStorage\n : ({} as Storage),\n ),\n // Migrate from v0 (queries: string[]) to v1 (entries: SearchHistoryEntry[])\n migrate(persistedState: unknown, version: number) {\n if (version === 0) {\n const old = persistedState as { queries?: string[] };\n if (Array.isArray(old?.queries)) {\n return {\n entries: old.queries.map((q) => ({\n query: q,\n isAI: false,\n timestamp: Date.now(),\n })),\n };\n }\n }\n return persistedState as SearchHistoryState;\n },\n },\n ),\n);\n","import { useSearchHistoryStore } from '../store/searchHistoryStore';\nimport type { SearchHistoryEntry } from '../store/searchHistoryStore';\n\nexport type { SearchHistoryEntry };\n\nexport interface UseSearchHistoryResult {\n entries: SearchHistoryEntry[];\n /** Derived string list of queries (backward compat) */\n queries: string[];\n addEntry: (entry: Omit<SearchHistoryEntry, 'timestamp'>) => void;\n /** @deprecated prefer addEntry */\n addQuery: (query: string) => void;\n removeEntry: (query: string) => void;\n clearAll: () => void;\n}\n\n/** React hook that subscribes to the tab-scoped search history store. */\nexport function useSearchHistory(): UseSearchHistoryResult {\n const entries = useSearchHistoryStore((s) => s.entries);\n const addEntry = useSearchHistoryStore((s) => s.addEntry);\n const addQuery = useSearchHistoryStore((s) => s.addQuery);\n const removeEntry = useSearchHistoryStore((s) => s.removeEntry);\n const clearAll = useSearchHistoryStore((s) => s.clearAll);\n return {\n entries,\n queries: entries.map((e) => e.query),\n addEntry,\n addQuery,\n removeEntry,\n clearAll,\n };\n}\n","import { useCallback, useRef, useState } from 'react';\n\n/* Speech Recognition API types — not always in lib.dom.d.ts */\ninterface SpeechRecognitionResult {\n readonly 0: { transcript: string };\n readonly isFinal?: boolean;\n}\ninterface SpeechRecognitionResultList {\n readonly length: number;\n readonly [index: number]: SpeechRecognitionResult | undefined;\n}\ninterface SpeechRecognitionEventLike {\n resultIndex?: number;\n results: SpeechRecognitionResultList;\n}\ninterface SpeechRecognitionErrorEventLike {\n error: string;\n}\ninterface SpeechRecognitionLike {\n lang: string;\n interimResults: boolean;\n maxAlternatives: number;\n onresult: ((e: SpeechRecognitionEventLike) => void) | null;\n onerror: ((e: SpeechRecognitionErrorEventLike) => void) | null;\n onend: (() => void) | null;\n start(): void;\n stop(): void;\n}\ntype SpeechRecognitionCtor = new () => SpeechRecognitionLike;\n\nfunction getSpeechRecognition(): SpeechRecognitionCtor | null {\n if (typeof window === 'undefined') return null;\n const w = window as typeof window & {\n webkitSpeechRecognition?: SpeechRecognitionCtor;\n SpeechRecognition?: SpeechRecognitionCtor;\n };\n return w.SpeechRecognition ?? w.webkitSpeechRecognition ?? null;\n}\n\nexport interface UseVoiceSearchOptions {\n lang?: string;\n onResult: (transcript: string) => void;\n onInterimResult?: (transcript: string) => void;\n onError?: (error: SpeechRecognitionErrorEventLike) => void;\n}\n\nexport interface UseVoiceSearchResult {\n listening: boolean;\n supported: boolean;\n start: () => void;\n stop: () => void;\n}\n\nexport function useVoiceSearch({\n lang,\n onInterimResult,\n onResult,\n onError,\n}: UseVoiceSearchOptions): UseVoiceSearchResult {\n const [listening, setListening] = useState(false);\n const recognitionRef = useRef<SpeechRecognitionLike | null>(null);\n const supported = getSpeechRecognition() !== null;\n\n const stop = useCallback(() => {\n recognitionRef.current?.stop();\n recognitionRef.current = null;\n setListening(false);\n }, []);\n\n const start = useCallback(() => {\n const SR = getSpeechRecognition();\n if (!SR) return;\n stop();\n\n const rec = new SR();\n rec.lang = lang ?? navigator.language ?? 'en-US';\n rec.interimResults = true;\n rec.maxAlternatives = 1;\n\n rec.onresult = (event: SpeechRecognitionEventLike) => {\n let finalTranscript = '';\n let interimTranscript = '';\n const startIndex = event.resultIndex ?? 0;\n\n for (\n let index = startIndex;\n index < event.results.length;\n index += 1\n ) {\n const result = event.results[index];\n const transcript = result?.[0]?.transcript ?? '';\n if (!transcript) continue;\n\n if (result?.isFinal) {\n finalTranscript += transcript;\n } else {\n interimTranscript += transcript;\n }\n }\n\n if (interimTranscript) onInterimResult?.(interimTranscript);\n if (finalTranscript) onResult(finalTranscript);\n };\n rec.onerror = (event: SpeechRecognitionErrorEventLike) => {\n onError?.(event);\n setListening(false);\n };\n rec.onend = () => setListening(false);\n\n recognitionRef.current = rec;\n rec.start();\n setListening(true);\n }, [lang, onInterimResult, onResult, onError, stop]);\n\n return { listening, supported, start, stop };\n}\n","/**\n * Generic browser helpers shared across SDK utilities.\n * Nothing here should be GTM-specific — keep this file free of tracker logic.\n */\n\nexport const IS_BROWSER = typeof window !== 'undefined';\n\n/**\n * Coerces a value to a trimmed string for use in analytics payloads.\n * Empty / nullish input returns `fallback` (default: single space, matching\n * the placeholder convention the data team specified).\n */\nexport function toEventString(\n value: string | number | undefined | null,\n fallback = ' ',\n): string {\n if (value === undefined || value === null) return fallback;\n const str = String(value).trim();\n return str.length > 0 ? str : fallback;\n}\n\n/**\n * Extracts `{ countryCode, language }` from a storefront-shaped path\n * (`/{country}/{language}/...`, e.g. `/us/en/product/x`).\n *\n * Reads `window.location.pathname` when called with no argument. Returns `{}`\n * if the first two path segments are not both 2-letter locale codes.\n */\nexport function getLocaleFromUrl(pathname?: string): {\n countryCode?: string;\n language?: string;\n} {\n const path = pathname ?? (IS_BROWSER ? window.location.pathname : '');\n const [country, language] = path.split('/').filter(Boolean);\n\n if (\n !/^[a-z]{2}$/i.test(country ?? '') ||\n !/^[a-z]{2}$/i.test(language ?? '')\n ) {\n return {};\n }\n\n return {\n countryCode: country!.toUpperCase(),\n language: language!.toLowerCase(),\n };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Safe localStorage / sessionStorage wrappers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Match the pattern used by the storefront `configUtils` — JSON-parse the\n * stored value, fall back to the raw string when parsing fails, and never\n * throw (SSR, private-mode Safari, quota errors, etc.).\n */\nfunction safeParse(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n}\n\n/** Reads a localStorage key and JSON-parses it. Returns `undefined` if absent. */\nexport function getLocalStorage(key: string): unknown {\n if (!IS_BROWSER) return undefined;\n try {\n const raw = window.localStorage.getItem(key);\n return raw === null ? undefined : safeParse(raw);\n } catch {\n return undefined;\n }\n}\n\n/** JSON-stringifies and writes a value to localStorage. Silent on failure. */\nexport function setLocalStorage(key: string, value: unknown): void {\n if (!IS_BROWSER) return;\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch {\n /* silent — storage failures never break the caller */\n }\n}\n\n/** Reads a sessionStorage key and JSON-parses it. Returns `undefined` if absent. */\nexport function getSessionStorage(key: string): unknown {\n if (!IS_BROWSER) return undefined;\n try {\n const raw = window.sessionStorage.getItem(key);\n return raw === null ? undefined : safeParse(raw);\n } catch {\n return undefined;\n }\n}\n\n/** JSON-stringifies and writes a value to sessionStorage. Silent on failure. */\nexport function setSessionStorage(key: string, value: unknown): void {\n if (!IS_BROWSER) return;\n try {\n window.sessionStorage.setItem(key, JSON.stringify(value));\n } catch {\n /* silent */\n }\n}\n","/**\n * GTM constants — event names, storage keys, and enum-like value maps.\n * Types are declared in `./gtmTypes` and imported here only for `satisfies`.\n */\n\nimport type { SearchGtmSearchType, SearchGtmUserStatus } from './gtmTypes';\n\n/* -------------------------------------------------------------------------- */\n/* Event names (COMX-3277) */\n/* -------------------------------------------------------------------------- */\n\nexport const SEARCH_GTM_EVENTS = {\n CHAT_ENTRY_POINT: 'Begin_chat',\n SEARCH_TYPE: 'Search_Type',\n PRODUCT_SEARCH: 'ProductSearch',\n ERROR_POPUP: 'Error_popup',\n} as const;\n\n/* -------------------------------------------------------------------------- */\n/* Enum-like value maps */\n/* -------------------------------------------------------------------------- */\n\nexport const SEARCH_GTM_SEARCH_TYPES = {\n SEMANTIC: 'semantic search',\n AI_AGENT: 'AI agent',\n} as const satisfies Record<string, SearchGtmSearchType>;\n\nexport const SEARCH_GTM_USER_STATUS = {\n GUEST: 'guest',\n LOGGED_IN: 'logged_in',\n} as const satisfies Record<string, SearchGtmUserStatus>;\n\n/* -------------------------------------------------------------------------- */\n/* Storage keys the SDK reads from the host storefront */\n/* -------------------------------------------------------------------------- */\n\n/** sessionStorage key written by ChatService after createConversation. */\nexport const AI_CHAT_CONVERSATION_ID_KEY = 'ai_chat_conversation_id';\n\n/** localStorage key set by the storefront Session model on login. */\nexport const IS_AUTHENTICATED_KEY = 'IsAuthenticated';\n\n/** localStorage key set by the storefront Customer profile flows. */\nexport const ACCOUNT_TYPE_KEY = 'accountType';\n\n/** localStorage key holding the authenticated user's account bundle. */\nexport const NUSKIN_ACCOUNT_DATA_KEY = 'nuskin.account.data';\n\n/** Fallback string used for the GTM `id` and `Chat_ID` fields when unknown. */\nexport const GTM_FALLBACK_NA = 'NA';\n","/**\n * GTM (Google Tag Manager) dataLayer tracking for the AI Chat Bot.\n *\n * Implements the events specified in COMX-3277:\n * 1. Chatentry_Point - user initiates the AI chat from an entry point\n * 2. Search_Type - user submits a query in the AI chat\n * 3. ProductSearch - AI chat returns product results (fires even on 0)\n * 4. Error_popup - API errors / unhandled exceptions during a session\n *\n * All UI repos (react-search-components, and any host consuming the SDK)\n * should call these helpers instead of touching `window.dataLayer` directly,\n * so that payload shape and error handling stay consistent.\n *\n * Types live in `./gtmTypes`, constants in `./gtmConstants`, and generic\n * helpers in `./commonUtils` / `./storage`.\n */\n\nimport {\n IS_BROWSER,\n getLocalStorage,\n getLocaleFromUrl,\n getSessionStorage,\n toEventString,\n} from './commonUtils';\nimport {\n ACCOUNT_TYPE_KEY,\n AI_CHAT_CONVERSATION_ID_KEY,\n GTM_FALLBACK_NA,\n IS_AUTHENTICATED_KEY,\n NUSKIN_ACCOUNT_DATA_KEY,\n SEARCH_GTM_EVENTS,\n SEARCH_GTM_SEARCH_TYPES,\n SEARCH_GTM_USER_STATUS,\n} from './gtmConstants';\nimport type {\n ErrorPopupEventInput,\n ProductSearchEventInput,\n SearchGtmContext,\n SearchGtmUserStatus,\n SearchTypeEventInput,\n} from './gtmTypes';\n\n/* -------------------------------------------------------------------------- */\n/* Re-exports so `./gtmTracking` remains the single public entry point */\n/* -------------------------------------------------------------------------- */\n\nexport { getLocaleFromUrl } from './commonUtils';\nexport {\n SEARCH_GTM_EVENTS,\n SEARCH_GTM_SEARCH_TYPES,\n SEARCH_GTM_USER_STATUS,\n} from './gtmConstants';\nexport type {\n ErrorPopupEventInput,\n ProductSearchEventInput,\n SearchGtmContext,\n SearchGtmSearchType,\n SearchGtmUserStatus,\n SearchTypeEventInput,\n} from './gtmTypes';\n\n/* -------------------------------------------------------------------------- */\n/* Storage-backed fallbacks */\n/* -------------------------------------------------------------------------- */\n\n/** Chat_ID falls back to the sessionStorage conversation id written by ChatService. */\nfunction readSessionChatId(): string | undefined {\n const raw = getSessionStorage(AI_CHAT_CONVERSATION_ID_KEY);\n return typeof raw === 'string' || typeof raw === 'number'\n ? String(raw)\n : undefined;\n}\n\n/** Derives user_status from the storefront Session model`s `IsAuthenticated` flag. */\nfunction readUserStatusFromStorage(): SearchGtmUserStatus | undefined {\n const value = getLocalStorage(IS_AUTHENTICATED_KEY);\n if (value === undefined) return undefined;\n if (\n value === SEARCH_GTM_USER_STATUS.GUEST ||\n value === SEARCH_GTM_USER_STATUS.LOGGED_IN\n ) {\n return value;\n }\n const isAuthenticated =\n value === true ||\n (typeof value === 'string' &&\n ['true', '1', 'yes', 'y'].includes(value.toLowerCase().trim()));\n return isAuthenticated\n ? SEARCH_GTM_USER_STATUS.LOGGED_IN\n : SEARCH_GTM_USER_STATUS.GUEST;\n}\n\n/** account_type falls back to the storefront `accountType` localStorage value. */\nfunction readAccountTypeFromStorage(): string | undefined {\n const value = getLocalStorage(ACCOUNT_TYPE_KEY);\n return typeof value === 'string' && value.trim().length > 0\n ? value\n : undefined;\n}\n\n/** Reads `nuskin.account.data.user.id` from localStorage. */\nfunction readUserIdFromStorage(): string | undefined {\n const raw = getLocalStorage(NUSKIN_ACCOUNT_DATA_KEY);\n if (!raw || typeof raw !== 'object') return undefined;\n const user = (raw as { user?: unknown }).user;\n if (!user || typeof user !== 'object') return undefined;\n const id = (user as { id?: unknown }).id;\n return typeof id === 'string' && id.trim().length > 0 ? id : undefined;\n}\n\n/** Resolves the GTM `id` field: explicit override -> localStorage -> `'NA'`. */\nfunction resolveUserId(explicit: string | undefined): string {\n return toEventString(explicit ?? readUserIdFromStorage(), GTM_FALLBACK_NA);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Base payload + dataLayer push */\n/* -------------------------------------------------------------------------- */\n\nfunction baseEventPayload(ctx: SearchGtmContext): Record<string, string> {\n const urlLocale = getLocaleFromUrl();\n const chatId = ctx.chatId ?? readSessionChatId();\n const userStatus = ctx.userStatus ?? readUserStatusFromStorage();\n const accountType = ctx.accountType ?? readAccountTypeFromStorage();\n const resolvedUserStatus = userStatus ?? SEARCH_GTM_USER_STATUS.GUEST;\n const documentTitle =\n IS_BROWSER && typeof document?.title === 'string'\n ? document.title\n : undefined;\n return {\n Chat_ID: toEventString(chatId, GTM_FALLBACK_NA),\n page_type: toEventString(\n ctx.pageType ?? documentTitle,\n GTM_FALLBACK_NA,\n ),\n country_code: toEventString(\n ctx.countryCode ?? urlLocale.countryCode,\n GTM_FALLBACK_NA,\n ),\n language: toEventString(\n ctx.language ?? urlLocale.language,\n GTM_FALLBACK_NA,\n ),\n user_status: toEventString(\n resolvedUserStatus,\n SEARCH_GTM_USER_STATUS.GUEST,\n ),\n account_type: toEventString(accountType, GTM_FALLBACK_NA),\n };\n}\n\nfunction serializeProductResults(\n productResultsData: unknown,\n productResults?: number,\n): string {\n if (productResultsData !== undefined) {\n try {\n return JSON.stringify(productResultsData);\n } catch {\n return GTM_FALLBACK_NA;\n }\n }\n\n if (productResults === undefined || productResults === null) {\n return GTM_FALLBACK_NA;\n }\n\n return String(productResults);\n}\n\n/**\n * Pushes a raw event object onto `window.dataLayer`.\n *\n * Silently no-ops when `window` is unavailable (SSR) or the dataLayer is\n * missing - GTM tag firing is a best-effort side effect, never a blocker for\n * the search flow.\n */\nexport function pushGtmEvent(event: Record<string, unknown>): void {\n if (!IS_BROWSER) return;\n try {\n const layer = (window.dataLayer ??= []);\n layer.push(event);\n } catch (err) {\n if (typeof console !== 'undefined') {\n console.warn('[react-search-sdk] pushGtmEvent failed:', err);\n }\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* Event trackers */\n/* -------------------------------------------------------------------------- */\n\n/** Fires `Begin_chat` when the user initiates the AI chat. */\nexport function trackChatEntryPoint(ctx: SearchGtmContext): void {\n pushGtmEvent({\n event: SEARCH_GTM_EVENTS.CHAT_ENTRY_POINT,\n ...baseEventPayload(ctx),\n });\n}\n\n/** Fires `Search_Type` when the user submits a query in the AI chat. */\nexport function trackSearchType(input: SearchTypeEventInput): void {\n pushGtmEvent({\n event: SEARCH_GTM_EVENTS.SEARCH_TYPE,\n ...baseEventPayload(input),\n id: resolveUserId(input.userId),\n type: input.searchType ?? SEARCH_GTM_SEARCH_TYPES.SEMANTIC,\n search_response: toEventString(input.searchResponse, GTM_FALLBACK_NA),\n });\n}\n\n/**\n * Fires `ProductSearch` when the AI chat returns results.\n * Must be called even when 0 products are returned.\n */\nexport function trackProductSearch(input: ProductSearchEventInput): void {\n pushGtmEvent({\n event: SEARCH_GTM_EVENTS.PRODUCT_SEARCH,\n ...baseEventPayload(input),\n id: resolveUserId(input.userId),\n search_type: input.searchType ?? SEARCH_GTM_SEARCH_TYPES.SEMANTIC,\n Product_results: serializeProductResults(\n input.productResultsData,\n input.productResults,\n ),\n });\n}\n\n/** Fires `Error_popup` for API errors and unhandled exceptions during chat. */\nexport function trackErrorPopup(input: ErrorPopupEventInput): void {\n pushGtmEvent({\n event: SEARCH_GTM_EVENTS.ERROR_POPUP,\n ...baseEventPayload(input),\n id: resolveUserId(input.userId),\n search_type: input.searchType ?? SEARCH_GTM_SEARCH_TYPES.SEMANTIC,\n });\n}\n"]}
1
+ {"version":3,"sources":["../src/config/configurationSdk.ts","../src/constants.ts","../src/config/commerceSearchConfig.ts","../src/hooks/useCommerceSearchConfig.ts","../src/services/SearchApiService.ts","../src/services/marketConfig.ts","../src/utils/gtmConstants.ts","../src/utils/navigationTarget.ts","../src/utils/catalogHelpers.ts","../src/hooks/useSearchSuggestions.ts","../src/utils/commonUtils.ts","../src/utils/gtmTracking.ts","../src/utils/nuiSearchGate.ts","../src/utils/searchRouting.ts","../src/components/CommerceSearch/NuiAgentPanel.tsx","../src/components/CommerceSearch/CommerceSearchView.tsx","../src/components/CommerceSearch/CommerceSearch.tsx"],"names":["configurationSdk","useState","useEffect","useRef","useCallback","lazy","Component","jsx","Suspense","SearchModal","useMemo"],"mappings":"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","file":"index.js","sourcesContent":["import configurationSdk from '@nuskin/configuration-sdk';\n\n/**\n * `@nuskin/configuration-sdk` is CommonJS. Node's ESM loader cannot see all of its named exports\n * (`getEnvironmentCode` is missed), so import the default and read the functions off it.\n */\nexport const { getConfiguration, getEnvironmentCode } = configurationSdk;\n","/**\n * Constants for the search SDK. Ported from\n * `header-mfe/src/utils/search/search.constants.js` — only the values the\n * SDK itself needs (Phase 0 lift-and-shift). CMS keys, GTM tracking config,\n * and mobile-only placeholder rotation constants stay in header-mfe.\n */\n\n/** API shopping-context segment used when resolving the Equinox gateway URL. */\nexport const STOREFRONT_SHOPPING_CONTEXT = 'storefront';\n\n/** Catalog suggestions path appended when the market gateway is not already\n * under the storefront shopping context. */\nexport const CATALOG_SUGGESTIONS_PATH =\n '/storefront/catalogs/search/suggestions';\n\n/** Prefix for the `sessionStorage` key that persists recent searches.\n * Full key format: `${RECENT_SEARCHES_PREFIX}:{locale}:{COUNTRY}:{lang}`.\n * Must not change — existing sessions rely on this key. */\nexport const RECENT_SEARCHES_PREFIX = 'nuskin:header:recentSearches';\n\n/** Maximum number of recent searches persisted per locale bucket. */\nexport const RECENT_SEARCHES_DEFAULT_LIMIT = 10;\n\n/** Equinox suggestion pagination — page is 1-indexed. */\nexport const DEFAULT_SUGGESTION_PAGE = 1;\n\n/** Number of suggestion rows requested from the Equinox catalog per call. */\nexport const DEFAULT_SUGGESTION_SIZE = 6;\n\n/** Segment used when building the fallback search-results URL. */\nexport const DEFAULT_SEARCH_PATH = '/search';\n\n/** Debounce for typeahead input → API dispatch. Preserved from header-mfe. */\nexport const DEBOUNCE_MS = 220;\n\n/** Terms shorter than this are not sent to the suggestions API (as in header-mfe). */\nexport const MINIMUM_SEARCH_CHAR_LENGTH = 2;\n\n/** Cap on suggestions rendered in the dropdown, regardless of API response size. */\nexport const MAX_VISIBLE_SUGGESTIONS = 6;\n\n/** The configuration map holding each market's API gateway and store. */\nexport const EQUINOX_MARKETS_MAP = 'Equinox_Markets';\n\n/**\n * TODO: move this client id into the configuration store with the other values read per\n * environment.\n */\nexport const DEFAULT_EQUINOX_CLIENT_ID = '63056848d7532f9923f3d08cb48c423b';\n","import { getEnvironmentCode } from './configurationSdk';\nimport { MINIMUM_SEARCH_CHAR_LENGTH } from '../constants';\n\n/**\n * Everything about the product search that is meant to be configuration, in one place, behind\n * one async reader. `fetchCommerceSearchConfig` is the only function that knows where the values\n * come from, so moving them to a configuration store changes that function and nothing else.\n */\n\n/** The NUi app the search can hand off to. */\nexport interface CommerceSearchAgentConfig {\n appKey: string;\n apiBaseUrl: string;\n /** UI language, taken from the market the config was read for. */\n language?: string;\n}\n\n/**\n * The contract the configuration store entry has to satisfy:\n * - `minimumSearchLength`: characters a term needs before the typeahead looks it up\n * - `agent`: the NUi app to hand off to; absent means plain search only\n */\nexport interface CommerceSearchConfig {\n minimumSearchLength: number;\n agent?: CommerceSearchAgentConfig;\n}\n\nexport interface FetchCommerceSearchConfigOptions {\n country?: string;\n language?: string;\n}\n\nexport const COMMERCE_SEARCH_CONFIG_DEFAULTS: Readonly<CommerceSearchConfig> =\n Object.freeze({\n minimumSearchLength: MINIMUM_SEARCH_CHAR_LENGTH,\n });\n\n/**\n * TODO: Replace this with a configuration store (Contentstack, read through the Configuration\n * SDK) that holds these values per environment, then delete the values below.\n *\n * TEMPORARY: values for the test environment, used only when the page is served from a test\n * host or localhost (`getEnvironmentCode()` is `test`). Every other environment gets the\n * defaults, so search stays plain search.\n */\nconst TEST_ENVIRONMENT_VALUES = {\n agent: {\n appKey: 'pk_commerce_product_advisor_624aea4305b09240e8c8f41d0f6527b2',\n apiBaseUrl: 'https://nui.tst.nuskin.ai/',\n },\n};\n\nfunction nonEmptyString(value: unknown): string {\n return typeof value === 'string' ? value.trim() : '';\n}\n\n/**\n * Turns whatever the store returned into a safe configuration: anything missing or malformed\n * falls back to the default, and the agent is dropped unless it is complete.\n */\nexport function normalizeCommerceSearchConfig(\n raw?: {\n minimumSearchLength?: unknown;\n agent?: { appKey?: unknown; apiBaseUrl?: unknown };\n } | null,\n { language }: { language?: string } = {},\n): CommerceSearchConfig {\n const minimumSearchLength = Number(raw?.minimumSearchLength);\n const appKey = nonEmptyString(raw?.agent?.appKey);\n const apiBaseUrl = nonEmptyString(raw?.agent?.apiBaseUrl);\n\n return {\n minimumSearchLength:\n Number.isInteger(minimumSearchLength) && minimumSearchLength >= 1\n ? minimumSearchLength\n : COMMERCE_SEARCH_CONFIG_DEFAULTS.minimumSearchLength,\n ...(appKey && apiBaseUrl\n ? {\n agent: {\n appKey,\n apiBaseUrl,\n ...(language ? { language } : {}),\n },\n }\n : {}),\n };\n}\n\n/** Reads the product search configuration for a market and host. */\nexport async function fetchCommerceSearchConfig({\n language,\n}: FetchCommerceSearchConfigOptions = {}): Promise<CommerceSearchConfig> {\n const raw = getEnvironmentCode() === 'test' ? TEST_ENVIRONMENT_VALUES : {};\n\n return normalizeCommerceSearchConfig(raw, language ? { language } : {});\n}\n","import { useEffect, useState } from 'react';\nimport {\n COMMERCE_SEARCH_CONFIG_DEFAULTS,\n fetchCommerceSearchConfig,\n} from '../config/commerceSearchConfig';\nimport type { CommerceSearchConfig } from '../config/commerceSearchConfig';\n\nexport interface UseCommerceSearchConfigOptions {\n country?: string;\n language?: string;\n /** Nothing is read until this is true (for example, until the panel first opens). */\n enabled: boolean;\n}\n\n/**\n * The product search configuration for a market: the defaults until the read finishes, and\n * again if it fails. A read that finishes after the market changed is ignored.\n */\nexport function useCommerceSearchConfig({\n country,\n language,\n enabled,\n}: UseCommerceSearchConfigOptions): CommerceSearchConfig {\n const [config, setConfig] = useState<CommerceSearchConfig>(\n COMMERCE_SEARCH_CONFIG_DEFAULTS,\n );\n\n useEffect(() => {\n if (!enabled) return undefined;\n let isStale = false;\n\n fetchCommerceSearchConfig({\n ...(country ? { country } : {}),\n ...(language ? { language } : {}),\n })\n .then((next) => {\n if (!isStale) setConfig(next);\n })\n .catch((error: unknown) => {\n // eslint-disable-next-line no-console\n console.warn(\n '[search] Could not load the product search configuration:',\n error,\n );\n });\n\n return () => {\n isStale = true;\n };\n }, [enabled, country, language]);\n\n return config;\n}\n","/**\n * SearchApiService — Phase 0 lift-and-shift of\n * `header-mfe/src/services/HeaderSearchService.js`.\n *\n * Behaviour follows the header search contract for URL formats,\n * `sessionStorage` key format, fetch parameter shape, and fallback values.\n * Navigation side effects are left to the consuming router.\n *\n * Two responsibilities were intentionally moved OUT of the SDK to preserve\n * the SDK-narrow boundary:\n * 1. Market-config resolution (`equinoxMarketsConfig.js` — depends on\n * `@nuskin/configuration-sdk`). Consumers inject a `getMarketConfig`\n * callback if they want automatic URL/store-id resolution.\n * 2. Locale resolution from the browser URL (`getLocale`). Consumers must\n * pass `country`/`language` explicitly.\n */\n\nimport {\n CATALOG_SUGGESTIONS_PATH,\n DEFAULT_SEARCH_PATH,\n DEFAULT_SUGGESTION_PAGE,\n DEFAULT_SUGGESTION_SIZE,\n MINIMUM_SEARCH_CHAR_LENGTH,\n RECENT_SEARCHES_DEFAULT_LIMIT,\n RECENT_SEARCHES_PREFIX,\n STOREFRONT_SHOPPING_CONTEXT,\n} from '../constants';\nimport type {\n GetMarketConfig,\n LocaleParts,\n LocationLike,\n MarketConfig,\n SearchServiceOptions,\n SuggestionOption,\n SuggestionsResponse,\n} from '../types';\n\n/** Returned by `createSearchService`. Internal to the package. */\nexport interface SearchService {\n /** Fetches typeahead suggestions from the Equinox catalog. */\n fetchSuggestions: (searchTerm: string) => Promise<SuggestionsResponse>;\n /**\n * Records the query in recent searches, then returns the option URL or the\n * fallback search-results path for the consuming router to navigate.\n */\n submitProductSearch: (\n query: string,\n option?: SuggestionOption,\n ) => string | undefined;\n /**\n * Returns the suggestion's URL if one is resolvable; otherwise submits the\n * suggestion's textual value as a product search.\n */\n activateSuggestionAction: (option: SuggestionOption) => string | undefined;\n /** Returns the navigable URL for a suggestion option (or `\"\"`). */\n getSuggestionHref: (option: SuggestionOption) => string;\n /** Returns the search-results page path for `query`. */\n viewMoreResults: (input: { query: string }) => string | undefined;\n /** Returns the persisted recent searches for the current locale bucket. */\n getRecentSearches: () => string[];\n /** Removes all persisted recent searches for the current locale bucket. */\n clearRecentSearches: () => void;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Storage guards */\n/* -------------------------------------------------------------------------- */\n\nfunction canUseStorage(\n storage: Storage | null | undefined,\n): storage is Storage {\n return (\n Boolean(storage) && typeof (storage as Storage).getItem === 'function'\n );\n}\n\nfunction getSessionStorage(\n providedStorage: Storage | null | undefined,\n): Storage | null {\n if (providedStorage) return providedStorage;\n\n if (typeof window !== 'undefined') {\n try {\n return window.sessionStorage;\n } catch {\n return null;\n }\n }\n\n return null;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Locale + storage-key helpers */\n/* -------------------------------------------------------------------------- */\n\nfunction normalizeLocaleParts({\n country,\n language,\n locale,\n}: {\n country: string | undefined;\n language: string | undefined;\n locale: string | undefined;\n}): LocaleParts {\n const normalizedCountry = String(country ?? '')\n .trim()\n .toUpperCase();\n const normalizedLanguage = String(language ?? '')\n .trim()\n .toLowerCase();\n const normalizedLocale = String(locale ?? '').trim() || 'UNKNOWN';\n\n return {\n country: normalizedCountry || 'UNKNOWN',\n language: normalizedLanguage || 'unknown',\n locale: normalizedLocale,\n };\n}\n\nfunction getRecentHeaderSearchesStorageKey(localeParts: LocaleParts): string {\n const { country, language, locale } = normalizeLocaleParts(localeParts);\n return `${RECENT_SEARCHES_PREFIX}:${locale}:${country}:${language}`;\n}\n\nfunction getRecentHeaderSearches(\n localeParts: LocaleParts,\n storage: Storage | null,\n): string[] {\n if (!canUseStorage(storage)) {\n return [];\n }\n\n try {\n const rawValue = storage.getItem(\n getRecentHeaderSearchesStorageKey(localeParts),\n );\n if (!rawValue) {\n return [];\n }\n\n const parsedValue: unknown = JSON.parse(rawValue);\n if (!Array.isArray(parsedValue)) {\n return [];\n }\n\n return parsedValue\n .map((item) => String(item ?? '').trim())\n .filter(Boolean);\n } catch {\n return [];\n }\n}\n\nfunction addRecentHeaderSearch(\n localeParts: LocaleParts,\n query: string,\n storage: Storage | null,\n limit: number = RECENT_SEARCHES_DEFAULT_LIMIT,\n): string[] {\n const normalizedQuery = String(query ?? '').trim();\n if (!normalizedQuery || !canUseStorage(storage)) {\n return [];\n }\n\n try {\n const existingValues = getRecentHeaderSearches(\n localeParts,\n storage,\n ).filter(\n (item) => item.toLowerCase() !== normalizedQuery.toLowerCase(),\n );\n const nextValues = [normalizedQuery, ...existingValues].slice(0, limit);\n storage.setItem(\n getRecentHeaderSearchesStorageKey(localeParts),\n JSON.stringify(nextValues),\n );\n return nextValues;\n } catch {\n return [];\n }\n}\n\nfunction clearRecentHeaderSearches(\n localeParts: LocaleParts,\n storage: Storage | null,\n): void {\n if (!canUseStorage(storage)) {\n return;\n }\n\n try {\n storage.removeItem(getRecentHeaderSearchesStorageKey(localeParts));\n } catch {\n // intentionally quiet when storage is blocked/unavailable\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* Location helpers */\n/* -------------------------------------------------------------------------- */\n\nfunction getBrowserLocation(\n providedLocation: LocationLike | null | undefined,\n): LocationLike | null {\n if (providedLocation) return providedLocation;\n if (typeof window !== 'undefined' && window.location)\n return window.location;\n return null;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Market-config → URL/storeId resolution */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Replaces `{api_name}` in a market-config gateway path with the given API\n * name, then trims a single trailing slash. Ported from the equivalent helper\n * in `equinoxMarketsConfig.js` so the SDK has no runtime dependency on it.\n */\nexport function resolveApiGatewayPath(\n apiGatewayPath: string | undefined | null,\n apiName: string = STOREFRONT_SHOPPING_CONTEXT,\n): string {\n const apiGateway = String(apiGatewayPath ?? '').trim();\n if (!apiGateway) return '';\n return apiGateway.replace(/\\{api_name\\}/gi, apiName).replace(/\\/$/, '');\n}\n\nfunction resolveCatalogApiBaseUrl(\n marketConfig: MarketConfig | null | undefined,\n): string {\n return resolveApiGatewayPath(marketConfig?.api_gateway_path);\n}\n\nfunction resolveCatalogStoreId(\n marketConfig: MarketConfig | null | undefined,\n): string {\n return String(marketConfig?.store_id ?? '').trim();\n}\n\nfunction buildCatalogSuggestionsUrl(apiBaseUrl: string): string {\n const normalizedBase = String(apiBaseUrl ?? '')\n .trim()\n .replace(/\\/$/, '');\n if (!normalizedBase) return '';\n\n const suggestionsPath = normalizedBase.endsWith(\n `/${STOREFRONT_SHOPPING_CONTEXT}`,\n )\n ? '/catalogs/search/suggestions'\n : CATALOG_SUGGESTIONS_PATH;\n\n return `${normalizedBase}${suggestionsPath}`;\n}\n\nfunction resolveSuggestionsUrl(\n suggestionsApi: string | undefined,\n locationLike: LocationLike | null,\n): string {\n const pathOrUrl = String(suggestionsApi ?? '').trim();\n if (!pathOrUrl) return '';\n\n if (pathOrUrl.startsWith('http://') || pathOrUrl.startsWith('https://')) {\n return pathOrUrl;\n }\n\n const normalizedPath = pathOrUrl.startsWith('/')\n ? pathOrUrl\n : `/${pathOrUrl}`;\n const origin = String(locationLike?.origin ?? '').trim();\n return origin ? `${origin}${normalizedPath}` : normalizedPath;\n}\n\nasync function resolveCatalogRequestConfig({\n suggestionsApi,\n storeIdOption,\n locationLike,\n country,\n getMarketConfig,\n}: {\n suggestionsApi: string | undefined;\n storeIdOption: string | number | undefined;\n locationLike: LocationLike | null;\n country: string;\n getMarketConfig: GetMarketConfig | undefined;\n}): Promise<{ suggestionsUrl: string; storeId: string }> {\n const explicitStoreId =\n storeIdOption !== undefined &&\n storeIdOption !== null &&\n String(storeIdOption).trim() !== ''\n ? String(storeIdOption).trim()\n : '';\n\n const marketConfig = getMarketConfig\n ? ((await getMarketConfig({ locationLike, country })) ?? null)\n : null;\n const configuredApiBase = resolveCatalogApiBaseUrl(marketConfig);\n const configuredStoreId = resolveCatalogStoreId(marketConfig);\n const explicitSuggestionsApi = String(suggestionsApi ?? '').trim();\n\n return {\n suggestionsUrl: explicitSuggestionsApi\n ? resolveSuggestionsUrl(explicitSuggestionsApi, locationLike)\n : buildCatalogSuggestionsUrl(configuredApiBase),\n storeId: explicitStoreId || configuredStoreId,\n };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Path + slug helpers */\n/* -------------------------------------------------------------------------- */\n\nfunction toCatalogLocale(localeParts: LocaleParts): string {\n const language = String(localeParts.language ?? 'en').toLowerCase();\n const country = String(localeParts.country ?? 'US').toUpperCase();\n return `${language}_${country}`;\n}\n\nfunction buildSearchResultsPath(\n query: string,\n localeParts: LocaleParts,\n): string {\n const trimmedQuery = String(query ?? '').trim();\n const hyphenatedQuery = trimmedQuery.replace(/\\s+/g, '-');\n const encodedQuery = encodeURIComponent(hyphenatedQuery).replace(\n /%2D/gi,\n '-',\n );\n const country = localeParts.country.toLowerCase();\n const language = localeParts.language.toLowerCase();\n return `/${country}/${language}${DEFAULT_SEARCH_PATH}/${encodedQuery}`;\n}\n\nfunction normalizeOptionUrl(rawValue: unknown): string {\n if (typeof rawValue !== 'string') return '';\n return rawValue.trim();\n}\n\nfunction safeDecodeURIComponent(value: string): string {\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n}\n\nfunction trimEdgeHyphens(value: string): string {\n let normalizedValue = value;\n while (normalizedValue.startsWith('-')) {\n normalizedValue = normalizedValue.slice(1);\n }\n while (normalizedValue.endsWith('-')) {\n normalizedValue = normalizedValue.slice(0, -1);\n }\n return normalizedValue;\n}\n\nfunction slugifyPathSegment(value: string | undefined | null): string {\n const decoded = safeDecodeURIComponent(String(value ?? '')).replace(\n /\\+/g,\n ' ',\n );\n const normalized = decoded\n .normalize('NFKD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/[^a-zA-Z0-9]+/g, '-')\n .replace(/-{2,}/g, '-')\n .toLowerCase();\n return trimEdgeHyphens(normalized);\n}\n\nfunction buildProductSlugPath(\n slugValue: string | undefined | null,\n localeParts: LocaleParts,\n): string {\n const slug = slugifyPathSegment(slugValue);\n if (!slug) return '';\n const country = String(localeParts.country ?? 'US').toLowerCase();\n const language = String(localeParts.language ?? 'en').toLowerCase();\n return `/${country}/${language}/product/${slug}`;\n}\n\nfunction isNavigableUrl(value: string): boolean {\n if (!value) return false;\n return value.startsWith('/') || /^https?:\\/\\//i.test(value);\n}\n\nfunction stripLocalePrefix(path: string, localeParts: LocaleParts): string {\n const prefix = `/${localeParts.country.toLowerCase()}/${localeParts.language.toLowerCase()}`;\n return path.startsWith(prefix) ? path.slice(prefix.length) || '/' : path;\n}\n\nfunction resolveOptionHref(\n option: SuggestionOption | null | undefined,\n localeParts: LocaleParts,\n): string {\n const productSlugPath = buildProductSlugPath(\n option?.slug ?? option?.productSlug ?? option?.product_slug ?? null,\n localeParts,\n );\n if (productSlugPath) {\n return productSlugPath;\n }\n\n const directUrl = normalizeOptionUrl(option?.href ?? option?.url);\n if (isNavigableUrl(directUrl) && !directUrl.includes('/chr/')) {\n return directUrl;\n }\n return '';\n}\n\n/* -------------------------------------------------------------------------- */\n/* Fetch helper */\n/* -------------------------------------------------------------------------- */\n\n/** The `X-Customer-Type` header for a request, or none when there is no customer type to send. */\nfunction resolveCustomerTypeHeaders(\n getCustomerType: (() => string | undefined) | undefined,\n): Record<string, string> | undefined {\n const customerType = getCustomerType?.()?.trim();\n return customerType ? { 'X-Customer-Type': customerType } : undefined;\n}\n\nasync function fetchJsonFromCandidates(\n fetchImpl: typeof fetch,\n requestUrls: string[],\n requestHeaders: Record<string, string> = {},\n): Promise<unknown> {\n let lastError: unknown;\n\n for (const requestUrl of requestUrls) {\n try {\n const response = await fetchImpl(requestUrl, {\n method: 'GET',\n credentials: 'include',\n headers: { Accept: 'application/json', ...requestHeaders },\n });\n\n if (!response.ok) {\n lastError = new Error(\n `Request failed with status ${response.status}`,\n );\n continue;\n }\n\n return await response.json();\n } catch (error) {\n lastError = error;\n }\n }\n\n throw lastError ?? new Error('Unable to fetch header search data');\n}\n\n/* -------------------------------------------------------------------------- */\n/* Factory */\n/* -------------------------------------------------------------------------- */\n\n/**\n * What `createSearchService` accepts. Internal: `CommerceSearch` adds the minimum search length\n * from its configuration, so hosts never set it.\n */\ninterface ResolvedSearchServiceOptions extends SearchServiceOptions {\n /**\n * The visitor's account type, sent as `X-Customer-Type` on every suggestions request. Read\n * when the request is made, because it can change after the visitor signs in.\n */\n getCustomerType?: () => string | undefined;\n /**\n * Terms shorter than this are not sent to the suggestions API. Defaults to\n * `MINIMUM_SEARCH_CHAR_LENGTH`.\n */\n minimumSearchLength?: number;\n}\n\n/**\n * Creates a search service instance. All options are optional; sensible\n * fallbacks are used when the browser environment is absent (SSR).\n */\nexport function createSearchService(\n options: ResolvedSearchServiceOptions = {},\n): SearchService {\n const {\n fetchImpl: fetchImplOption,\n location: providedLocation,\n storage: providedStorage,\n suggestionsApi,\n storeId: storeIdOption,\n country,\n language,\n locale,\n getMarketConfig,\n getCustomerType,\n minimumSearchLength = MINIMUM_SEARCH_CHAR_LENGTH,\n } = options;\n\n const fetchImpl: typeof fetch | null =\n fetchImplOption !== undefined\n ? fetchImplOption\n : typeof fetch === 'function'\n ? fetch.bind(globalThis)\n : null;\n\n const locationLike = getBrowserLocation(providedLocation);\n const storage = getSessionStorage(providedStorage);\n const localeParts = normalizeLocaleParts({ country, language, locale });\n\n let catalogRequestConfigPromise: Promise<{\n suggestionsUrl: string;\n storeId: string;\n }> | null = null;\n\n function loadCatalogRequestConfig() {\n if (!catalogRequestConfigPromise) {\n catalogRequestConfigPromise = resolveCatalogRequestConfig({\n suggestionsApi,\n storeIdOption,\n locationLike,\n country: localeParts.country,\n getMarketConfig,\n });\n }\n return catalogRequestConfigPromise;\n }\n\n const service: SearchService = {\n async fetchSuggestions(\n searchTerm: string,\n ): Promise<SuggestionsResponse> {\n const trimmedSearchTerm = String(searchTerm ?? '').trim();\n if (\n !trimmedSearchTerm ||\n trimmedSearchTerm.length < minimumSearchLength ||\n !fetchImpl\n ) {\n return {\n suggestions: [],\n didYouMean: [],\n totalResultsCount: 0,\n };\n }\n\n const { suggestionsUrl, storeId } =\n await loadCatalogRequestConfig();\n\n if (!suggestionsUrl || !storeId) {\n return {\n suggestions: [],\n didYouMean: [],\n totalResultsCount: 0,\n };\n }\n\n const queryParams = new URLSearchParams({\n searchTerm: trimmedSearchTerm,\n page: String(DEFAULT_SUGGESTION_PAGE),\n size: String(DEFAULT_SUGGESTION_SIZE),\n locale: toCatalogLocale(localeParts),\n storeId: String(storeId),\n });\n\n const requestUrls = [`${suggestionsUrl}?${queryParams.toString()}`];\n\n const responsePayload = (await fetchJsonFromCandidates(\n fetchImpl,\n requestUrls,\n resolveCustomerTypeHeaders(getCustomerType),\n )) as SuggestionsResponse | null | undefined;\n\n const suggestionsField = Array.isArray(responsePayload?.suggestions)\n ? (responsePayload?.suggestions as unknown[])\n : [];\n const productField = Array.isArray(responsePayload?.product)\n ? (responsePayload?.product as unknown[])\n : null;\n\n const rawDidYouMean =\n responsePayload?.didYouMean ?? responsePayload?.did_you_mean;\n const didYouMeanField = Array.isArray(rawDidYouMean)\n ? (rawDidYouMean as unknown[])\n : [];\n\n const pageableTotal = Number(\n responsePayload?.pageableInfo?.totalCount ?? Number.NaN,\n );\n const totalResultsCount =\n typeof responsePayload?.totalResultsCount === 'number'\n ? responsePayload.totalResultsCount\n : !Number.isNaN(pageableTotal)\n ? pageableTotal\n : (productField?.length ?? suggestionsField.length);\n\n return {\n ...(responsePayload ?? {}),\n suggestions: suggestionsField,\n didYouMean: didYouMeanField,\n totalResultsCount,\n };\n },\n\n submitProductSearch(\n query: string,\n option?: SuggestionOption,\n ): string | undefined {\n const trimmedQuery = String(query ?? '').trim();\n if (!trimmedQuery) return undefined;\n\n addRecentHeaderSearch(localeParts, trimmedQuery, storage);\n\n const optionHref = resolveOptionHref(option, localeParts);\n if (optionHref) {\n return stripLocalePrefix(optionHref, localeParts);\n }\n\n const targetPath = buildSearchResultsPath(\n trimmedQuery,\n localeParts,\n );\n\n return stripLocalePrefix(targetPath, localeParts);\n },\n\n activateSuggestionAction(option: SuggestionOption): string | undefined {\n // The suggestion's page, or a search for its text.\n const optionHref = resolveOptionHref(option, localeParts);\n if (optionHref) {\n return stripLocalePrefix(optionHref, localeParts);\n }\n\n const optionQuery =\n option?.value ?? option?.label ?? option?.identifier ?? '';\n return service.submitProductSearch(String(optionQuery));\n },\n\n getSuggestionHref(option: SuggestionOption): string {\n return stripLocalePrefix(\n resolveOptionHref(option, localeParts),\n localeParts,\n );\n },\n\n viewMoreResults({ query }: { query: string }): string | undefined {\n return service.submitProductSearch(query);\n },\n\n getRecentSearches(): string[] {\n return getRecentHeaderSearches(localeParts, storage);\n },\n\n clearRecentSearches(): void {\n clearRecentHeaderSearches(localeParts, storage);\n },\n };\n\n return service;\n}\n","import {\n getConfiguration,\n getEnvironmentCode,\n} from '../config/configurationSdk';\nimport {\n DEFAULT_EQUINOX_CLIENT_ID,\n EQUINOX_MARKETS_MAP,\n STOREFRONT_SHOPPING_CONTEXT,\n} from '../constants';\nimport type { GetMarketConfig, MarketConfig } from '../types';\n\n/**\n * Reads the market's API gateway and store from the `Equinox_Markets` configuration, for the\n * environment the page is served from.\n */\nexport const fetchMarketConfig: GetMarketConfig = async ({ country }) => {\n const countryCode =\n String(country ?? '')\n .trim()\n .toUpperCase() || 'US';\n const configuration = await getConfiguration([EQUINOX_MARKETS_MAP], {\n country: countryCode,\n ...(getEnvironmentCode()\n ? { environment: getEnvironmentCode() as string }\n : {}),\n clientId: DEFAULT_EQUINOX_CLIENT_ID,\n shoppingContext: STOREFRONT_SHOPPING_CONTEXT,\n });\n\n return (\n (configuration?.[EQUINOX_MARKETS_MAP] as MarketConfig | undefined) ??\n null\n );\n};\n","/**\n * GTM constants — event names, storage keys, and enum-like value maps.\n * Types are declared in `./gtmTypes` and imported here only for `satisfies`.\n */\n\nimport type { SearchGtmSearchType, SearchGtmUserStatus } from './gtmTypes';\n\n/* -------------------------------------------------------------------------- */\n/* Event names (COMX-3277) */\n/* -------------------------------------------------------------------------- */\n\nexport const SEARCH_GTM_EVENTS = {\n CHAT_ENTRY_POINT: 'Begin_chat',\n SEARCH_TYPE: 'Search_Type',\n PRODUCT_SEARCH: 'ProductSearch',\n ERROR_POPUP: 'Error_popup',\n} as const;\n\n/* -------------------------------------------------------------------------- */\n/* Enum-like value maps */\n/* -------------------------------------------------------------------------- */\n\nexport const SEARCH_GTM_SEARCH_TYPES = {\n SEMANTIC: 'semantic search',\n AI_AGENT: 'AI agent',\n} as const satisfies Record<string, SearchGtmSearchType>;\n\nexport const SEARCH_GTM_USER_STATUS = {\n GUEST: 'guest',\n LOGGED_IN: 'logged_in',\n} as const satisfies Record<string, SearchGtmUserStatus>;\n\n/* -------------------------------------------------------------------------- */\n/* Storage keys the SDK reads from the host storefront */\n/* -------------------------------------------------------------------------- */\n\n/** Fallback string used for the GTM `id` and `Chat_ID` fields when unknown. */\nexport const GTM_FALLBACK_NA = 'NA';\n","/**\n * Where `CommerceSearch` wants the host to take the shopper: a page inside the app (a path for\n * the host's router, with the market prefix already removed), or somewhere that needs a full\n * page load.\n */\nexport type NavigationTarget =\n { type: 'internal'; path: string } | { type: 'external'; url: string };\n\n/** Classifies a path from the search service as internal or external. */\nexport function toNavigationTarget(path: string): NavigationTarget {\n return /^https?:\\/\\//i.test(path)\n ? { type: 'external', url: path }\n : { type: 'internal', path };\n}\n","/**\n * Catalog-product normalisation helpers — Phase 0 lift-and-shift of the\n * relevant portions of\n * `header-mfe/src/components/search/auto-complete/autoComplete.helpers.js`.\n *\n * Only the data-processing helpers are included here. UI-specific helpers\n * (keyboard event handlers, ARIA attribute computation, display-data\n * extraction) live in `react-search-components` because they depend on DOM\n * refs and component-level props.\n *\n * Key difference from the original:\n * `resolveSuggestionImageSrc` returns `\"\"` when the source is absent\n * instead of falling back to a bundled PNG asset. Components apply their\n * own `<img onError>` / CSS placeholder; the SDK must not bundle assets.\n */\n\nimport type {\n CatalogSuggestionItem,\n DidYouMeanItem,\n ProductType,\n} from '../types';\n\n/* -------------------------------------------------------------------------- */\n/* Product-status helpers */\n/* -------------------------------------------------------------------------- */\n\nconst CART_DISABLED_PRODUCT_STATUSES = new Set([\n 'discontinued',\n 'preview',\n 'previewproduct',\n 'test',\n 'stopped',\n 'replacement',\n 'bundleonly',\n 'inactive',\n 'notavailable',\n]);\n\nfunction normalizeProductStatusValue(value: unknown): string {\n return String(value ?? '')\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '');\n}\n\n/** Returns `true` when `productStatus` is `\"sellable\"`. */\nexport function isSellableProductStatus(productStatus: unknown): boolean {\n return normalizeProductStatusValue(productStatus) === 'sellable';\n}\n\nfunction resolveSkuStatusValues(\n suggestionOption: Record<string, unknown>,\n): string[] {\n return [\n suggestionOption['productStatus'],\n suggestionOption['product_status'],\n suggestionOption['status'],\n suggestionOption['sku_status'],\n ]\n .map(normalizeProductStatusValue)\n .filter(Boolean);\n}\n\nfunction isNonSellableStatusValue(statusValue: string): boolean {\n if (CART_DISABLED_PRODUCT_STATUSES.has(statusValue)) {\n return true;\n }\n return statusValue !== 'sellable' && statusValue !== 'active';\n}\n\n/**\n * Returns `true` when the suggestion option should not allow add-to-cart\n * (out of stock, discontinued, inactive, etc.).\n */\nexport function isCartActionDisabled(\n suggestionOption: Record<string, unknown> | null | undefined,\n): boolean {\n if (!suggestionOption) {\n return true;\n }\n\n const outOfStock =\n suggestionOption['out_of_stock'] ?? suggestionOption['outOfStock'];\n if (outOfStock) {\n return true;\n }\n\n const statusValues = resolveSkuStatusValues(suggestionOption);\n if (statusValues.length === 0) {\n return false;\n }\n\n return statusValues.some(isNonSellableStatusValue);\n}\n\n/**\n * Returns `true` when the suggestion row should be displayed as\n * non-interactive (out-of-stock only — a subset of `isCartActionDisabled`).\n */\nexport function isSuggestionDisabled(\n suggestionOption: Record<string, unknown> | null | undefined,\n): boolean {\n return Boolean(\n !suggestionOption ||\n suggestionOption['out_of_stock'] ||\n suggestionOption['outOfStock'],\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Image helpers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Reads the first non-empty image URL from a Contentstack / catalog property\n * bag. Returns `\"\"` when no image is found.\n */\nexport function getImageFromProperty(\n properties: Record<string, unknown> = {},\n): string {\n let image =\n String(properties['primaryimage'] ?? '').trim() ||\n String(properties['imageURL'] ?? '').trim();\n\n if (!image) {\n try {\n const parsed: unknown = JSON.parse(\n String(properties['productImages'] ?? '{}'),\n );\n if (\n Array.isArray(parsed) &&\n parsed[0] &&\n typeof parsed[0] === 'object'\n ) {\n image = String(\n (parsed[0] as Record<string, unknown>)['url'] ?? '',\n ).trim();\n }\n } catch {\n image = '';\n }\n }\n\n return image;\n}\n\n/**\n * Normalises an image source value. Returns `\"\"` when the source is absent or\n * blank. Components are responsible for applying a fallback placeholder image.\n */\nexport function resolveSuggestionImageSrc(imageSrc: unknown): string {\n const trimmed =\n typeof imageSrc === 'string'\n ? imageSrc.trim()\n : String(imageSrc ?? '').trim();\n return trimmed;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Ingredient terms */\n/* -------------------------------------------------------------------------- */\n\nfunction safeParseJsonArray(value: unknown): unknown[] {\n if (Array.isArray(value)) {\n return value;\n }\n\n if (typeof value !== 'string' || !value.trim()) {\n return [];\n }\n\n try {\n const parsed: unknown = JSON.parse(value);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\n/**\n * Extracts a flat list of ingredient terms from a Contentstack ingredient\n * structure. Used to populate `CatalogSuggestionItem.ingredientTerms`.\n */\nexport function getIngredientTerms(rawIngredients: unknown): string[] {\n const ingredientGroups = safeParseJsonArray(rawIngredients);\n\n return ingredientGroups\n .flatMap((ingredientGroup) => {\n if (!ingredientGroup || typeof ingredientGroup !== 'object') {\n return [];\n }\n const group = ingredientGroup as Record<string, unknown>;\n const keyIngredients = Array.isArray(group['keyIngredients'])\n ? (\n group['keyIngredients'] as Array<Record<string, unknown>>\n ).map((ingredient) => ingredient['name'])\n : [];\n\n return [\n group['productName'],\n group['activeIngredients'],\n group['inactiveIngredients'],\n group['allIngredients'],\n group['otherIngredients'],\n ...keyIngredients,\n ];\n })\n .filter(Boolean)\n .map((term) => String(term).trim())\n .filter(Boolean);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Catalog product → suggestion mapping */\n/* -------------------------------------------------------------------------- */\n\nfunction getSkuProperties(product: Record<string, unknown>): {\n defaultSku: Record<string, unknown> | null;\n skuProperties: Record<string, unknown>;\n} {\n const skuList = Array.isArray(product['sku'])\n ? (product['sku'] as Array<Record<string, unknown>>)\n : [];\n const defaultSku =\n skuList.find((skuEntry) => skuEntry?.['default'] === true) ??\n skuList[0] ??\n null;\n return {\n defaultSku: defaultSku ?? null,\n skuProperties:\n ((defaultSku as Record<string, unknown> | null)?.[\n 'properties'\n ] as Record<string, unknown>) ?? {},\n };\n}\n\nfunction getIdentifier(\n product: Record<string, unknown>,\n defaultSku: Record<string, unknown> | null,\n index: number,\n): string {\n return String(\n defaultSku?.['identifier'] ??\n product['identifier'] ??\n `catalog-product-${index}`,\n ).trim();\n}\n\nfunction getDisplayLabel(\n identifier: string,\n productProperties: Record<string, unknown>,\n skuProperties: Record<string, unknown>,\n): string {\n return String(\n skuProperties['title'] ??\n productProperties['name'] ??\n productProperties['title'] ??\n skuProperties['name'] ??\n identifier,\n );\n}\n\nfunction getTypeData(\n product: Record<string, unknown>,\n productProperties: Record<string, unknown>,\n skuProperties: Record<string, unknown>,\n): { customProductType: string; isBundle: boolean } {\n const customProductType = String(\n productProperties['customProductType'] ??\n skuProperties['customProductType'] ??\n '',\n ).trim();\n const normalizedType = String(\n product['type'] ??\n productProperties['producttype'] ??\n skuProperties['producttype'] ??\n '',\n )\n .trim()\n .toLowerCase();\n return {\n customProductType,\n isBundle:\n normalizedType === 'bundle' ||\n customProductType.toLowerCase().includes('bundle'),\n };\n}\n\nfunction getNavigationUrls(\n productProperties: Record<string, unknown>,\n skuProperties: Record<string, unknown>,\n): { navigableUrl: string | null; slug: string | null } {\n const slug =\n String(\n skuProperties['slug'] ?? productProperties['slug'] ?? '',\n ).trim() || null;\n const navigableUrl =\n String(\n skuProperties['url'] ??\n skuProperties['href'] ??\n productProperties['url'] ??\n productProperties['href'] ??\n '',\n ).trim() || null;\n return { navigableUrl, slug };\n}\n\nfunction isOutOfStock(inventoryStatus: unknown): boolean {\n return String(inventoryStatus).toUpperCase() === 'OUT OF STOCK';\n}\n\nfunction getCatalogStatusFields(\n skuProperties: Record<string, unknown>,\n productProperties: Record<string, unknown>,\n): {\n normalizedProductStatus: string;\n normalizedSkuStatus: string;\n outOfStock: boolean;\n cartActionDisabled: boolean;\n} {\n const inventoryStatus =\n skuProperties['inventoryStatus'] ??\n productProperties['inventoryStatus'] ??\n '';\n const productStatus =\n skuProperties['productStatus'] ??\n productProperties['productStatus'] ??\n '';\n const skuStatus =\n skuProperties['status'] ?? productProperties['status'] ?? '';\n const normalizedProductStatus = String(productStatus).trim();\n const normalizedSkuStatus = String(skuStatus).trim();\n const outOfStock = isOutOfStock(inventoryStatus);\n\n return {\n normalizedProductStatus,\n normalizedSkuStatus,\n outOfStock,\n cartActionDisabled: isCartActionDisabled({\n outOfStock,\n productStatus: normalizedProductStatus || undefined,\n status: normalizedSkuStatus || undefined,\n }),\n };\n}\n\nfunction optionalNonEmptyString(value: string): string | undefined {\n const normalized = String(value ?? '').trim();\n return normalized || undefined;\n}\n\nfunction getProductImageSrc(opts: {\n product: Record<string, unknown>;\n productProperties: Record<string, unknown>;\n skuProperties: Record<string, unknown>;\n}): string {\n const normalizedType = String(opts.product['type'] ?? '')\n .trim()\n .toLowerCase();\n\n if (normalizedType === 'kit' || normalizedType === 'bundle') {\n return getImageFromProperty(opts.productProperties);\n }\n\n return getImageFromProperty(opts.skuProperties);\n}\n\n/**\n * Maps a raw Equinox catalog product object to the normalised\n * `CatalogSuggestionItem` shape consumed by the UI components.\n * Returns `null` for invalid input so callers can `.filter(Boolean)`.\n */\nexport function mapCatalogProductToSuggestion(\n product: unknown,\n index: number = 0,\n): CatalogSuggestionItem | null {\n if (!product || typeof product !== 'object') {\n return null;\n }\n\n const p = product as Record<string, unknown>;\n const productProperties =\n (p['properties'] as Record<string, unknown>) ?? {};\n const { defaultSku, skuProperties } = getSkuProperties(p);\n const identifier = getIdentifier(p, defaultSku, index);\n const { customProductType, isBundle } = getTypeData(\n p,\n productProperties,\n skuProperties,\n );\n const { navigableUrl, slug } = getNavigationUrls(\n productProperties,\n skuProperties,\n );\n const statusFields = getCatalogStatusFields(\n skuProperties,\n productProperties,\n );\n const imageSrc = resolveSuggestionImageSrc(\n getProductImageSrc({ product: p, productProperties, skuProperties }),\n );\n const mappedProductType: ProductType = isBundle ? 'bundle' : 'single';\n\n return {\n id: identifier,\n identifier,\n sku: identifier,\n label: getDisplayLabel(identifier, productProperties, skuProperties),\n value: getDisplayLabel(identifier, productProperties, skuProperties),\n imageURL: imageSrc,\n thumbnail: imageSrc,\n productType: mappedProductType,\n product_type: mappedProductType,\n outOfStock: statusFields.outOfStock,\n productStatus: optionalNonEmptyString(\n statusFields.normalizedProductStatus,\n ),\n status: optionalNonEmptyString(statusFields.normalizedSkuStatus),\n cartActionDisabled: statusFields.cartActionDisabled,\n customProductType,\n slug,\n productSlug: slug,\n url: navigableUrl,\n href: navigableUrl,\n keywords: String(\n (productProperties['keyword'] as unknown) ??\n (skuProperties['keyword'] as unknown) ??\n '',\n ),\n ingredientTerms: getIngredientTerms(\n skuProperties['ingredients'] ?? productProperties['ingredients'],\n ),\n };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Did-you-mean normalisation */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Normalises the raw `didYouMean` / `did_you_mean` array from the Equinox\n * API into a consistent shape consumed by `useSearchSuggestions`.\n */\nexport function normalizeDidYouMean(didYouMean: unknown): DidYouMeanItem[] {\n if (!Array.isArray(didYouMean)) {\n return [];\n }\n\n return didYouMean\n .map((item: unknown, index: number): DidYouMeanItem | null => {\n if (typeof item === 'string') {\n return {\n id: `did-you-mean-${index}-${item}`,\n value: item,\n suggestionType: 'did-you-mean',\n };\n }\n\n if (item && typeof item === 'object') {\n const obj = item as Record<string, unknown>;\n return {\n ...obj,\n id: String(\n obj['id'] ??\n `did-you-mean-${index}-${obj['value'] ?? obj['label'] ?? ''}`,\n ),\n value: String(obj['value'] ?? ''),\n suggestionType: 'did-you-mean',\n };\n }\n\n return null;\n })\n .filter((item): item is DidYouMeanItem => item !== null);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Suggestion list helpers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Returns the items that should actually be rendered in the suggestions list.\n * When \"Did You Mean?\" results are present they take precedence over product\n * suggestions (matching the original header-mfe behaviour).\n */\nexport function getVisibleSuggestions(opts: {\n didYouMean: DidYouMeanItem[];\n suggestions: CatalogSuggestionItem[];\n}): DidYouMeanItem[] | CatalogSuggestionItem[] {\n if (opts.didYouMean.length > 0) {\n return opts.didYouMean;\n }\n return opts.suggestions;\n}\n\n/**\n * Builds the analytics payload emitted when the user clicks \"See More Results\".\n */\nexport function getSeeMoreResultsPayload(\n query: string,\n totalResultsCount: number,\n suggestions: CatalogSuggestionItem[],\n): {\n query: string;\n source: string;\n totalResultsCount: number;\n visibleResultsCount: number;\n} {\n return {\n query,\n source: 'autocomplete-footer',\n totalResultsCount,\n visibleResultsCount: suggestions.length,\n };\n}\n","/**\n * useSearchSuggestions — Phase 0 lift-and-shift of\n * `header-mfe/src/components/search/auto-complete/hooks/useAutoComplete.js`\n * (`useAutoCompleteSuggestions` export).\n *\n * Behaviour is preserved verbatim:\n * - 220 ms debounce (DEBOUNCE_MS constant — do not change)\n * - Request-ID stale-response guard (replaces AbortController in the original)\n * - `MAX_VISIBLE_SUGGESTIONS` cap applied before setting state\n * - `didYouMean` items take precedence: when present, `suggestions` is set\n * to `[]` and the DYM items are used as the visible list\n * - `emptyFetched` is only set to `true` when BOTH arrays are empty after\n * a successful fetch\n * - `enabled = false` clears state without firing an API call\n *\n * Keyboard navigation (`useAutoCompleteKeyboard`) and all display-data helpers\n * live in `react-search-components` — they depend on DOM refs and component props.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type React from 'react';\n\nimport { DEBOUNCE_MS, MAX_VISIBLE_SUGGESTIONS } from '../constants';\nimport {\n mapCatalogProductToSuggestion,\n normalizeDidYouMean,\n} from '../utils/catalogHelpers';\nimport type { SearchService } from '../services/SearchApiService';\nimport type {\n CatalogSuggestionItem,\n DidYouMeanItem,\n SuggestionsResponse,\n} from '../types';\n\n/** Options accepted by `useSearchSuggestions`. */\nexport interface UseSearchSuggestionsOptions {\n /** The search service `CommerceSearch` creates. */\n service: SearchService;\n /**\n * When `false` the hook clears state and skips all API calls.\n * Useful for suppressing suggestions while the user is typing a question.\n * Defaults to `true`.\n */\n enabled?: boolean;\n}\n\n/** State and actions returned by `useSearchSuggestions`. */\nexport interface UseSearchSuggestionsResult {\n /**\n * Resets the query to `\"\"` and clears all suggestions state.\n * Call when the user clicks the Clear button.\n */\n clearQuery: () => void;\n /**\n * `true` after a fetch completes with an empty result set.\n * Use this to show a \"No suggestions\" message.\n */\n emptyFetched: boolean;\n /** `true` when the server has more matches than `MAX_VISIBLE_SUGGESTIONS`. */\n hasMoreResults: boolean;\n /** `true` when the trimmed query is non-empty. */\n hasQuery: boolean;\n /** `true` when the latest suggestions request failed. */\n suggestionFetchFailed: boolean;\n /** Normalised \"Did You Mean?\" items from the API. */\n didYouMean: DidYouMeanItem[];\n /** `true` while a debounced fetch is in flight. */\n loading: boolean;\n /** The current query string (unmodified, as typed by the user). */\n query: string;\n /**\n * The trimmed query the current results (or failure) belong to; `\"\"` until a\n * fetch has finished. Compare with `query.trim()` to know whether the\n * results on screen are for the term the user has typed.\n */\n settledQuery: string;\n /** Raw React state setter — prefer `updateQuery` for controlled inputs. */\n setQuery: React.Dispatch<React.SetStateAction<string>>;\n /** Normalised product suggestion items from the catalog API. */\n suggestions: CatalogSuggestionItem[];\n /** Total match count reported by the Equinox API. */\n totalResultsCount: number;\n /**\n * Preferred setter — updates `query`, optimistically sets `loading`, and\n * clears `emptyFetched` before the debounce fires.\n */\n updateQuery: (query: string) => void;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Internal normalisation (mirrors useAutoComplete.js) */\n/* -------------------------------------------------------------------------- */\n\ninterface NormalizedSuggestions {\n suggestions: CatalogSuggestionItem[];\n didYouMean: DidYouMeanItem[];\n}\n\nfunction normalizeSuggestionsResponse(\n response: SuggestionsResponse | unknown,\n): NormalizedSuggestions {\n // Raw array fallback (some API variants return an array directly)\n if (Array.isArray(response)) {\n return {\n suggestions: response as CatalogSuggestionItem[],\n didYouMean: [],\n };\n }\n\n if (!response || typeof response !== 'object') {\n return { suggestions: [], didYouMean: [] };\n }\n\n const r = response as SuggestionsResponse;\n\n // Equinox catalog API returns a `product` array\n if (Array.isArray(r.product)) {\n return {\n suggestions: (r.product as unknown[])\n .map((product, index) =>\n mapCatalogProductToSuggestion(product, index),\n )\n .filter((item): item is CatalogSuggestionItem => item !== null),\n didYouMean: normalizeDidYouMean(r.didYouMean ?? r.did_you_mean),\n };\n }\n\n // Generic suggestions array fallback\n return {\n suggestions: Array.isArray(r.suggestions)\n ? (r.suggestions as CatalogSuggestionItem[])\n : [],\n didYouMean: normalizeDidYouMean(r.didYouMean),\n };\n}\n\n/* -------------------------------------------------------------------------- */\n/* Hook */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Manages debounced typeahead suggestions from the Equinox catalog API.\n *\n * @example\n * ```tsx\n * const service = createSearchService({ country, language, locale, suggestionsApi, storeId });\n * const { suggestions, didYouMean, loading, updateQuery, clearQuery } =\n * useSearchSuggestions({ service });\n * ```\n */\nexport function useSearchSuggestions({\n service,\n enabled = true,\n}: UseSearchSuggestionsOptions): UseSearchSuggestionsResult {\n const [query, setQuery] = useState('');\n const [suggestions, setSuggestions] = useState<CatalogSuggestionItem[]>([]);\n const [didYouMean, setDidYouMean] = useState<DidYouMeanItem[]>([]);\n const [loading, setLoading] = useState(false);\n const [emptyFetched, setEmptyFetched] = useState(false);\n const [suggestionFetchFailed, setSuggestionFetchFailed] = useState(false);\n const [hasMoreResults, setHasMoreResults] = useState(false);\n const [totalResultsCount, setTotalResultsCount] = useState(0);\n const [settledQuery, setSettledQuery] = useState('');\n\n const fetchDebounced = useRef<ReturnType<typeof setTimeout> | null>(null);\n const latestRequestId = useRef(0);\n\n const resetSuggestionsState = useCallback(() => {\n setSuggestions([]);\n setDidYouMean([]);\n setEmptyFetched(false);\n setSuggestionFetchFailed(false);\n setHasMoreResults(false);\n setTotalResultsCount(0);\n setSettledQuery('');\n setLoading(false);\n }, []);\n\n const updateQuery = useCallback(\n (nextQuery: string) => {\n const hasNextQuery = Boolean(nextQuery.trim());\n setEmptyFetched(false);\n setSuggestionFetchFailed(false);\n setLoading(enabled && hasNextQuery);\n setQuery(nextQuery);\n },\n [enabled],\n );\n\n const clearQuery = useCallback(() => {\n resetSuggestionsState();\n setQuery('');\n }, [resetSuggestionsState]);\n\n const runFetch = useCallback(\n async (nextQuery: string) => {\n const trimmedQuery = nextQuery.trim();\n const requestId = latestRequestId.current;\n\n if (!trimmedQuery || !enabled) {\n resetSuggestionsState();\n return;\n }\n\n setLoading(true);\n setEmptyFetched(false);\n setSuggestionFetchFailed(false);\n\n try {\n const fetchedSuggestions =\n await service.fetchSuggestions(trimmedQuery);\n\n // Discard stale response if a newer request has since been issued\n if (requestId !== latestRequestId.current) {\n return;\n }\n\n const {\n suggestions: allSuggestions,\n didYouMean: suggestedTerms,\n } = normalizeSuggestionsResponse(fetchedSuggestions);\n\n const visibleSuggestions = allSuggestions.slice(\n 0,\n MAX_VISIBLE_SUGGESTIONS,\n );\n const hasDidYouMean = suggestedTerms.length > 0;\n\n const normalizedTotal =\n typeof fetchedSuggestions.totalResultsCount === 'number'\n ? fetchedSuggestions.totalResultsCount\n : typeof fetchedSuggestions.pageableInfo?.totalCount ===\n 'number'\n ? fetchedSuggestions.pageableInfo.totalCount\n : allSuggestions.length;\n\n const effectiveTotal = hasDidYouMean\n ? suggestedTerms.length\n : Math.max(normalizedTotal, allSuggestions.length);\n\n setDidYouMean(suggestedTerms);\n setSuggestions(hasDidYouMean ? [] : visibleSuggestions);\n setHasMoreResults(\n !hasDidYouMean && effectiveTotal > MAX_VISIBLE_SUGGESTIONS,\n );\n setTotalResultsCount(effectiveTotal);\n setSuggestionFetchFailed(false);\n setSettledQuery(trimmedQuery);\n setEmptyFetched(\n hasDidYouMean\n ? false\n : visibleSuggestions.length === 0 &&\n suggestedTerms.length === 0,\n );\n } catch {\n if (requestId !== latestRequestId.current) {\n return;\n }\n setSuggestions([]);\n setDidYouMean([]);\n setEmptyFetched(true);\n setSuggestionFetchFailed(true);\n setHasMoreResults(false);\n setTotalResultsCount(0);\n setSettledQuery(trimmedQuery);\n } finally {\n if (requestId === latestRequestId.current) {\n setLoading(false);\n }\n }\n },\n [enabled, service, resetSuggestionsState],\n );\n\n useEffect(() => {\n if (!enabled) {\n resetSuggestionsState();\n return undefined;\n }\n\n if (fetchDebounced.current) {\n clearTimeout(fetchDebounced.current);\n }\n\n // Mark any in-flight request as stale before the debounce fires\n latestRequestId.current += 1;\n\n fetchDebounced.current = setTimeout(() => {\n void runFetch(query);\n }, DEBOUNCE_MS);\n\n return () => {\n if (fetchDebounced.current) {\n clearTimeout(fetchDebounced.current);\n }\n };\n }, [enabled, query, resetSuggestionsState, runFetch]);\n\n return {\n clearQuery,\n emptyFetched,\n hasMoreResults,\n hasQuery: Boolean(query.trim()),\n didYouMean,\n loading,\n query,\n settledQuery,\n setQuery: setQuery as React.Dispatch<React.SetStateAction<string>>,\n suggestionFetchFailed,\n suggestions,\n totalResultsCount,\n updateQuery,\n };\n}\n","/**\n * Generic browser helpers shared across SDK utilities.\n * Nothing here should be GTM-specific — keep this file free of tracker logic.\n */\n\nexport const IS_BROWSER = typeof window !== 'undefined';\n\n/**\n * Coerces a value to a trimmed string for use in analytics payloads.\n * Empty / nullish input returns `fallback` (default: single space, matching\n * the placeholder convention the data team specified).\n */\nexport function toEventString(\n value: string | number | undefined | null,\n fallback = ' ',\n): string {\n if (value === undefined || value === null) return fallback;\n const str = String(value).trim();\n return str.length > 0 ? str : fallback;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Safe localStorage / sessionStorage wrappers */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Match the pattern used by the storefront `configUtils` — JSON-parse the\n * stored value, fall back to the raw string when parsing fails, and never\n * throw (SSR, private-mode Safari, quota errors, etc.).\n */\nfunction safeParse(raw: string): unknown {\n try {\n return JSON.parse(raw);\n } catch {\n return raw;\n }\n}\n\n/** JSON-stringifies and writes a value to localStorage. Silent on failure. */\nexport function setLocalStorage(key: string, value: unknown): void {\n if (!IS_BROWSER) return;\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch {\n /* silent — storage failures never break the caller */\n }\n}\n\n/** Reads a sessionStorage key and JSON-parses it. Returns `undefined` if absent. */\nexport function getSessionStorage(key: string): unknown {\n if (!IS_BROWSER) return undefined;\n try {\n const raw = window.sessionStorage.getItem(key);\n return raw === null ? undefined : safeParse(raw);\n } catch {\n return undefined;\n }\n}\n\n/** JSON-stringifies and writes a value to sessionStorage. Silent on failure. */\nexport function setSessionStorage(key: string, value: unknown): void {\n if (!IS_BROWSER) return;\n try {\n window.sessionStorage.setItem(key, JSON.stringify(value));\n } catch {\n /* silent */\n }\n}\n","/**\n * GTM (Google Tag Manager) dataLayer tracking for the AI Chat Bot.\n *\n * Implements the events specified in COMX-3277:\n * 1. Chatentry_Point - user initiates the AI chat from an entry point\n * 2. Search_Type - user submits a query in the AI chat\n * 3. ProductSearch - AI chat returns product results (fires even on 0)\n * 4. Error_popup - API errors / unhandled exceptions during a session\n *\n * All UI repos (react-search-components, and any host consuming the SDK)\n * should call these helpers instead of touching `window.dataLayer` directly,\n * so that payload shape and error handling stay consistent.\n *\n * Types live in `./gtmTypes`, constants in `./gtmConstants`, and generic\n * helpers in `./commonUtils` / `./storage`.\n */\n\nimport { IS_BROWSER, toEventString } from './commonUtils';\nimport {\n GTM_FALLBACK_NA,\n SEARCH_GTM_EVENTS,\n SEARCH_GTM_SEARCH_TYPES,\n SEARCH_GTM_USER_STATUS,\n} from './gtmConstants';\nimport type {\n ErrorPopupEventInput,\n ProductSearchEventInput,\n SearchGtmContext,\n SearchTypeEventInput,\n} from './gtmTypes';\n\n/* -------------------------------------------------------------------------- */\n/* Re-exports so `./gtmTracking` remains the single public entry point */\n/* -------------------------------------------------------------------------- */\n\nexport {\n SEARCH_GTM_EVENTS,\n SEARCH_GTM_SEARCH_TYPES,\n SEARCH_GTM_USER_STATUS,\n} from './gtmConstants';\nexport type {\n ErrorPopupEventInput,\n ProductSearchEventInput,\n SearchGtmContext,\n SearchGtmSearchType,\n SearchGtmUserStatus,\n SearchTypeEventInput,\n} from './gtmTypes';\n\n/** The GTM `id` field: the user id the host supplied, or `'NA'`. */\nfunction resolveUserId(explicit: string | undefined): string {\n return toEventString(explicit, GTM_FALLBACK_NA);\n}\n\n/* -------------------------------------------------------------------------- */\n/* Base payload + dataLayer push */\n/* -------------------------------------------------------------------------- */\n\nfunction baseEventPayload(ctx: SearchGtmContext): Record<string, string> {\n return {\n Chat_ID: toEventString(ctx.chatId, GTM_FALLBACK_NA),\n // TODO: COMX-3277 puts `page_type` in every event but defines no values. Send `NA` until\n // the data team says what it should hold (perhaps the page path).\n page_type: GTM_FALLBACK_NA,\n country_code: toEventString(ctx.countryCode, GTM_FALLBACK_NA),\n language: toEventString(ctx.language, GTM_FALLBACK_NA),\n user_status: toEventString(\n ctx.userStatus ?? SEARCH_GTM_USER_STATUS.GUEST,\n SEARCH_GTM_USER_STATUS.GUEST,\n ),\n account_type: toEventString(ctx.accountType, GTM_FALLBACK_NA),\n };\n}\n\nfunction serializeProductResults(\n productResultsData: unknown,\n productResults?: number,\n): string {\n if (productResultsData !== undefined) {\n try {\n return JSON.stringify(productResultsData);\n } catch {\n return GTM_FALLBACK_NA;\n }\n }\n\n if (productResults === undefined || productResults === null) {\n return GTM_FALLBACK_NA;\n }\n\n return String(productResults);\n}\n\n/**\n * Pushes a raw event object onto `window.dataLayer`.\n *\n * Silently no-ops when `window` is unavailable (SSR) or the dataLayer is\n * missing - GTM tag firing is a best-effort side effect, never a blocker for\n * the search flow.\n */\nexport function pushGtmEvent(event: Record<string, unknown>): void {\n if (!IS_BROWSER) return;\n try {\n const layer = (window.dataLayer ??= []);\n layer.push(event);\n } catch (err) {\n if (typeof console !== 'undefined') {\n console.warn('[react-search-sdk] pushGtmEvent failed:', err);\n }\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* Event trackers */\n/* -------------------------------------------------------------------------- */\n\n/** Fires `Begin_chat` when the user initiates the AI chat. */\nexport function trackChatEntryPoint(ctx: SearchGtmContext): void {\n pushGtmEvent({\n event: SEARCH_GTM_EVENTS.CHAT_ENTRY_POINT,\n ...baseEventPayload(ctx),\n });\n}\n\n/** Fires `Search_Type` when the user submits a query in the AI chat. */\nexport function trackSearchType(input: SearchTypeEventInput): void {\n pushGtmEvent({\n event: SEARCH_GTM_EVENTS.SEARCH_TYPE,\n ...baseEventPayload(input),\n id: resolveUserId(input.userId),\n type: input.searchType ?? SEARCH_GTM_SEARCH_TYPES.SEMANTIC,\n search_response: toEventString(input.searchResponse, GTM_FALLBACK_NA),\n });\n}\n\n/**\n * Fires `ProductSearch` when the AI chat returns results.\n * Must be called even when 0 products are returned.\n */\nexport function trackProductSearch(input: ProductSearchEventInput): void {\n pushGtmEvent({\n event: SEARCH_GTM_EVENTS.PRODUCT_SEARCH,\n ...baseEventPayload(input),\n id: resolveUserId(input.userId),\n search_type: input.searchType ?? SEARCH_GTM_SEARCH_TYPES.SEMANTIC,\n Product_results: serializeProductResults(\n input.productResultsData,\n input.productResults,\n ),\n });\n}\n\n/** Fires `Error_popup` for API errors and unhandled exceptions during chat. */\nexport function trackErrorPopup(input: ErrorPopupEventInput): void {\n pushGtmEvent({\n event: SEARCH_GTM_EVENTS.ERROR_POPUP,\n ...baseEventPayload(input),\n id: resolveUserId(input.userId),\n search_type: input.searchType ?? SEARCH_GTM_SEARCH_TYPES.SEMANTIC,\n });\n}\n","/**\n * The enable gate for NUi search.\n *\n * NUi search is on only for signed-in visitors who have switched it on with\n * the `enableNuiSearch` flag, set by a cookie or by a URL query parameter\n * (`?enableNuiSearch=true` or `=false`). The query parameter also writes the\n * cookie, so the choice sticks while the visitor navigates. Off by default.\n *\n * The flag is a client-side feature toggle, not a security control. Real\n * per-market and per-locale switching is a later step.\n */\n\n/** Name shared by the cookie and the URL query parameter. */\nexport const NUI_SEARCH_FLAG = 'enableNuiSearch';\n\nfunction parseFlagValue(raw: string | null | undefined): boolean | undefined {\n const value = raw?.trim().toLowerCase();\n if (value === 'true' || value === '1') return true;\n if (value === 'false' || value === '0') return false;\n return undefined;\n}\n\nfunction readCookieFlag(cookie: string): boolean | undefined {\n for (const part of cookie.split(';')) {\n const separator = part.indexOf('=');\n if (separator < 0) continue;\n if (part.slice(0, separator).trim() !== NUI_SEARCH_FLAG) continue;\n const rawValue = part.slice(separator + 1);\n try {\n return parseFlagValue(decodeURIComponent(rawValue));\n } catch {\n return undefined;\n }\n }\n return undefined;\n}\n\n/** Where the flag is read from and written to. Defaults to the browser. */\nexport interface NuiSearchFlagEnv {\n /** Query string, with or without the leading `?`. */\n search?: string;\n /** Cookie string, as in `document.cookie`. */\n cookie?: string;\n /** Called with a cookie string to store when the query parameter is set. */\n setCookie?: (cookie: string) => void;\n}\n\n/**\n * Resolves the flag. A valid query parameter wins over the cookie and is\n * written back to the cookie; otherwise the cookie decides. `undefined` means\n * it was never set. Safe to call during server rendering.\n */\nexport function resolveNuiSearchFlag(\n env: NuiSearchFlagEnv = {},\n): boolean | undefined {\n const inBrowser =\n typeof window !== 'undefined' && typeof document !== 'undefined';\n const search = env.search ?? (inBrowser ? window.location.search : '');\n const cookie = env.cookie ?? (inBrowser ? document.cookie : '');\n const setCookie =\n env.setCookie ??\n (inBrowser\n ? (value: string) => {\n document.cookie = value;\n }\n : undefined);\n\n const fromQuery = parseFlagValue(\n new URLSearchParams(search).get(NUI_SEARCH_FLAG),\n );\n if (fromQuery !== undefined) {\n const secure =\n inBrowser && window.location.protocol === 'https:'\n ? '; Secure'\n : '';\n setCookie?.(\n `${NUI_SEARCH_FLAG}=${fromQuery}; path=/; SameSite=Lax${secure}`,\n );\n return fromQuery;\n }\n return readCookieFlag(cookie);\n}\n\nexport interface IsNuiSearchEnabledInput {\n /** From the host (the storefront's `customerData.isAuthenticated`). */\n isAuthenticated: boolean | undefined;\n /** The resolved flag; see `resolveNuiSearchFlag`. */\n flag: boolean | undefined;\n}\n\n/** On only when the visitor is signed in and the flag is explicitly on. */\nexport function isNuiSearchEnabled({\n isAuthenticated,\n flag,\n}: IsNuiSearchEnabledInput): boolean {\n return isAuthenticated === true && flag === true;\n}\n","/**\n * Routing between Solr search and the NUi agent.\n *\n * Rule: when the shopper submits a search and the typeahead response for that\n * exact term shows no products, the NUi widget takes over in the same panel.\n * Anything else stays plain search. A pure function, so a smarter intent\n * heuristic can replace it later without touching any UI.\n */\n\nimport type { UseSearchSuggestionsResult } from '../hooks/useSearchSuggestions';\n\n/**\n * - `search` — stay on Solr search (submit behaves as it does today).\n * - `handoff` — hand the query to the NUi agent.\n * - `wait` — the typeahead for this term has not settled yet; ask again when\n * the snapshot changes. Callers should apply their own timeout and\n * fall back to `search`, so a slow request never blocks a submit.\n */\nexport type SearchRoute = 'search' | 'handoff' | 'wait';\n\n/** The slice of `useSearchSuggestions` state the rule reads. */\nexport type RoutingSnapshot = Pick<\n UseSearchSuggestionsResult,\n | 'query'\n | 'loading'\n | 'settledQuery'\n | 'suggestions'\n | 'suggestionFetchFailed'\n>;\n\nexport interface DecideSearchRouteInput {\n /** Whether NUi search is on for this visitor (see `isNuiSearchEnabled`). */\n enabled: boolean;\n snapshot: RoutingSnapshot;\n}\n\n/**\n * Decides what a submitted search does.\n *\n * \"No products\" means the hook has nothing to show for the term. A response\n * that only offers \"did you mean\" terms counts as no products: the hook hides\n * the products in that case, so the shopper sees none either. A failed request\n * is not \"no products\": an outage must not send every shopper to the agent.\n */\nexport function decideSearchRoute({\n enabled,\n snapshot,\n}: DecideSearchRouteInput): SearchRoute {\n const term = snapshot.query.trim();\n if (!enabled || !term) return 'search';\n\n // The results on screen must belong to the term being submitted.\n if (snapshot.loading || snapshot.settledQuery !== term) return 'wait';\n\n if (snapshot.suggestionFetchFailed) return 'search';\n\n return snapshot.suggestions.length > 0 ? 'search' : 'handoff';\n}\n","import { Component, Suspense, lazy, useEffect } from 'react';\nimport type { ErrorInfo, ReactElement, ReactNode } from 'react';\nimport type { SalesAIChatWidgetProps } from '@nuskin/react-nui-chat-sdk';\n\n/** How often to look for the widget's `window.SalesAI` handle while it loads. */\nconst HANDLE_POLL_MS = 50;\n/** How long to wait for the widget to load before giving up and falling back to plain search. */\nconst HANDLE_TIMEOUT_MS = 15000;\n\n/** The NUi widget and its stylesheet are code-split: they stay out of the host's main bundle. */\nconst SalesAIChatWidget = lazy(async () => {\n const [widget] = await Promise.all([\n import('@nuskin/react-nui-chat-sdk'),\n import('@nuskin/react-nui-chat-sdk/styles.css'),\n ]);\n return { default: widget.SalesAIChatWidget };\n});\n\n/** The imperative handle the widget registers on `window` (see the widget's `open` options). */\ninterface SalesAIHandle {\n open: (options?: {\n query?: string;\n context?: Record<string, unknown> | null;\n }) => void;\n}\n\nfunction getSalesAIHandle(): SalesAIHandle | undefined {\n return (window as Window & { SalesAI?: SalesAIHandle }).SalesAI;\n}\n\n/** How the host's NUi app is reached and presented. */\nexport interface NuiAgentConfig {\n /** The NUi app key for the search surface. */\n appKey: string;\n /** Origin of the NUi API. */\n apiBaseUrl: string;\n /** UI language, e.g. `en-US`. */\n language?: string;\n /** Widget theme. Defaults to `nui-light`. */\n theme?: SalesAIChatWidgetProps['theme'];\n /** Context sent with every turn of the conversation, under the handoff context. */\n context?: Record<string, unknown>;\n /** Lets the host draw the agent's product recommendations. */\n renderProduct?: SalesAIChatWidgetProps['renderProduct'];\n}\n\nexport interface NuiAgentPanelProps {\n agent: NuiAgentConfig;\n /** The search the shopper submitted; sent to the agent as the first message. */\n query: string;\n /** Describes how the conversation started; layered over `agent.context`. */\n handoffContext: Record<string, unknown>;\n /** Called when the agent cannot be shown, so the host can fall back to plain search. */\n onUnavailable: () => void;\n}\n\ninterface BoundaryProps {\n children: ReactNode;\n onError: () => void;\n}\n\n/** Turns a failure to load or render the widget into a fallback instead of a broken panel. */\nclass AgentErrorBoundary extends Component<BoundaryProps, { failed: boolean }> {\n override state = { failed: false };\n\n static getDerivedStateFromError() {\n return { failed: true };\n }\n\n override componentDidCatch(_error: Error, _info: ErrorInfo) {\n this.props.onError();\n }\n\n override render() {\n return this.state.failed ? null : this.props.children;\n }\n}\n\n/** Hands the submitted query to the widget once its handle is available. */\nfunction useHandoff({\n query,\n handoffContext,\n agentContext,\n onUnavailable,\n}: {\n query: string;\n handoffContext: Record<string, unknown>;\n agentContext: Record<string, unknown> | undefined;\n onUnavailable: () => void;\n}) {\n useEffect(() => {\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n const startedAt = Date.now();\n\n const tryOpen = () => {\n if (cancelled) return;\n const handle = getSalesAIHandle();\n if (handle) {\n handle.open({\n query,\n context: { ...agentContext, ...handoffContext },\n });\n return;\n }\n if (Date.now() - startedAt >= HANDLE_TIMEOUT_MS) {\n onUnavailable();\n return;\n }\n timer = setTimeout(tryOpen, HANDLE_POLL_MS);\n };\n\n tryOpen();\n return () => {\n cancelled = true;\n if (timer !== undefined) clearTimeout(timer);\n };\n // The handoff happens once per submitted query.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [query]);\n}\n\n/** The NUi widget, mounted in the search panel and handed the shopper's query. */\nexport function NuiAgentPanel({\n agent,\n query,\n handoffContext,\n onUnavailable,\n}: Readonly<NuiAgentPanelProps>): ReactElement {\n useHandoff({\n query,\n handoffContext,\n agentContext: agent.context,\n onUnavailable,\n });\n\n return (\n <AgentErrorBoundary onError={onUnavailable}>\n <Suspense fallback={null}>\n <SalesAIChatWidget\n appKey={agent.appKey}\n apiBaseUrl={agent.apiBaseUrl}\n theme={agent.theme ?? 'nui-light'}\n defaultOpen\n hideFab\n placement=\"host\"\n {...(agent.language === undefined\n ? {}\n : { language: agent.language })}\n {...(agent.renderProduct === undefined\n ? {}\n : { renderProduct: agent.renderProduct })}\n />\n </Suspense>\n </AgentErrorBoundary>\n );\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport type { ReactElement, ReactNode } from 'react';\nimport { SearchModal } from '@nuskin/react-search-components';\nimport type { SuggestionOptionWithTracking } from '@nuskin/react-search-components';\nimport { useSearchSuggestions } from '../../hooks/useSearchSuggestions';\nimport type { SearchService } from '../../services/SearchApiService';\nimport type { SuggestionOption } from '../../types';\nimport {\n getVisibleSuggestions,\n isSuggestionDisabled,\n} from '../../utils/catalogHelpers';\nimport { MINIMUM_SEARCH_CHAR_LENGTH } from '../../constants';\nimport { SEARCH_GTM_SEARCH_TYPES } from '../../utils/gtmConstants';\nimport {\n trackChatEntryPoint,\n trackProductSearch,\n} from '../../utils/gtmTracking';\nimport type { SearchGtmContext } from '../../utils/gtmTypes';\nimport {\n isNuiSearchEnabled,\n resolveNuiSearchFlag,\n} from '../../utils/nuiSearchGate';\nimport { decideSearchRoute } from '../../utils/searchRouting';\nimport type { SearchRoute } from '../../utils/searchRouting';\nimport { NuiAgentPanel } from './NuiAgentPanel';\nimport type { NuiAgentConfig } from './NuiAgentPanel';\n\n/** How long a submit waits for the typeahead of that exact term before it stays on search. */\nexport const SUBMIT_WAIT_TIMEOUT_MS = 2000;\n\nexport interface CommerceSearchViewProps {\n isOpen: boolean;\n onClose: () => void;\n /** From `createSearchService`. Keep its identity stable (memoize it). */\n service: SearchService;\n /** Takes the shopper to a path, using the host's router. The panel closes afterwards. */\n navigate: (path: string) => void;\n /** Whether the visitor is signed in (the storefront's `customerData.isAuthenticated`). */\n isAuthenticated: boolean;\n /** The NUi app the agent runs on. Without it the agent never shows and search stays plain. */\n agent?: NuiAgentConfig;\n logo?: ReactNode;\n /**\n * Terms shorter than this never hand off to the agent. Keep it equal to the\n * `minimumSearchLength` the `service` was created with. Defaults to\n * `MINIMUM_SEARCH_CHAR_LENGTH`.\n */\n minimumSearchLength?: number;\n /** Host-known values for the search analytics events. */\n gtmContext?: Omit<SearchGtmContext, 'chatId'>;\n}\n\nfunction uniqueRecentSearches(queries: ReadonlyArray<string>): string[] {\n const seen = new Set<string>();\n return queries.filter((query) => {\n const key = query.trim().toLowerCase();\n if (!key || seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\n/**\n * Product search with an agent fallback, for a `service` and `agent` the caller already has.\n * `CommerceSearch` is the entry point that reads the configuration and builds them.\n *\n * Shows Solr typeahead and recent searches in the library's `SearchModal`. When a signed-in\n * shopper submits a term whose typeahead shows no products, the NUi agent takes over in the same\n * panel with that term as the first message. Everything else behaves as plain search.\n */\nexport function CommerceSearchView({\n isOpen,\n onClose,\n service,\n navigate,\n isAuthenticated,\n agent,\n logo,\n minimumSearchLength = MINIMUM_SEARCH_CHAR_LENGTH,\n gtmContext,\n}: Readonly<CommerceSearchViewProps>): ReactElement {\n const [flag, setFlag] = useState<boolean | undefined>(undefined);\n // The agent's start: what was submitted and the \"did you mean\" terms Solr offered for it.\n const [handoff, setHandoff] = useState<{\n query: string;\n didYouMean: string[];\n } | null>(null);\n const agentQuery = handoff?.query ?? null;\n const [pendingTerm, setPendingTerm] = useState<string | null>(null);\n const [recentSearches, setRecentSearches] = useState<string[]>([]);\n\n const search = useSearchSuggestions({\n service,\n enabled: isOpen && agentQuery === null,\n });\n const {\n clearQuery,\n didYouMean,\n emptyFetched,\n hasMoreResults,\n loading,\n query,\n settledQuery,\n suggestionFetchFailed,\n suggestions,\n updateQuery,\n } = search;\n\n const enabled =\n agent !== undefined && isNuiSearchEnabled({ isAuthenticated, flag });\n const items = getVisibleSuggestions({\n didYouMean,\n suggestions,\n }) as unknown as SuggestionOptionWithTracking[];\n const showDidYouMean = didYouMean.length > 0;\n\n useEffect(() => {\n if (isOpen) setFlag(resolveNuiSearchFlag());\n }, [isOpen]);\n\n useEffect(() => {\n if (isOpen) {\n setRecentSearches(\n uniqueRecentSearches(service.getRecentSearches()),\n );\n }\n }, [isOpen, service, agentQuery]);\n\n const close = useCallback(() => {\n setHandoff(null);\n setPendingTerm(null);\n clearQuery();\n onClose();\n }, [clearQuery, onClose]);\n\n // The host can also close the panel from outside.\n useEffect(() => {\n if (!isOpen) {\n setHandoff(null);\n setPendingTerm(null);\n clearQuery();\n }\n }, [isOpen, clearQuery]);\n\n /** Navigates and closes. */\n const navigateTo = useCallback(\n (path: string | undefined) => {\n if (!path) return;\n navigate(path);\n close();\n },\n [navigate, close],\n );\n\n const trackSemantic = useCallback(\n (productResultsData: unknown) => {\n trackProductSearch({\n ...gtmContext,\n searchType: SEARCH_GTM_SEARCH_TYPES.SEMANTIC,\n productResultsData,\n });\n },\n [gtmContext],\n );\n\n const runSearch = useCallback(\n (term: string) => {\n trackSemantic(items.length > 0 ? items : { query: term });\n navigateTo(service.submitProductSearch(term));\n },\n [items, navigateTo, service, trackSemantic],\n );\n\n const decide = useCallback(\n (term: string): SearchRoute =>\n decideSearchRoute({\n enabled,\n snapshot: {\n query: term,\n loading,\n settledQuery,\n suggestions,\n suggestionFetchFailed,\n },\n }),\n [enabled, loading, settledQuery, suggestions, suggestionFetchFailed],\n );\n\n const act = useCallback(\n (term: string, route: SearchRoute) => {\n setPendingTerm(null);\n if (route === 'handoff') {\n trackChatEntryPoint(gtmContext ?? {});\n setHandoff({\n query: term,\n didYouMean: didYouMean.map((item) => item.value),\n });\n return;\n }\n runSearch(term);\n },\n [didYouMean, gtmContext, runSearch],\n );\n\n const handleSubmit = useCallback(\n (value: string) => {\n const term = value.trim();\n if (!term) return;\n // Too short for the typeahead to have looked: plain search, never the agent.\n if (term.length < minimumSearchLength) {\n runSearch(term);\n return;\n }\n const route = decide(term);\n if (route === 'wait') {\n setPendingTerm(term);\n return;\n }\n act(term, route);\n },\n [act, decide, minimumSearchLength, runSearch],\n );\n\n // A submit that beat the typeahead waits for it to settle, then re-decides. If it never\n // settles, the shopper gets plain search rather than a stuck panel.\n const latest = useRef({ act, decide });\n latest.current = { act, decide };\n useEffect(() => {\n if (pendingTerm === null) return undefined;\n const route = latest.current.decide(pendingTerm);\n if (route !== 'wait') {\n latest.current.act(pendingTerm, route);\n return undefined;\n }\n const timer = setTimeout(\n () => latest.current.act(pendingTerm, 'search'),\n SUBMIT_WAIT_TIMEOUT_MS,\n );\n return () => clearTimeout(timer);\n }, [\n pendingTerm,\n loading,\n settledQuery,\n suggestions,\n suggestionFetchFailed,\n ]);\n\n const handleSelect = useCallback(\n (option: SuggestionOptionWithTracking) => {\n if (\n isSuggestionDisabled(\n option as unknown as Record<string, unknown>,\n )\n ) {\n return;\n }\n const term = String(option['value'] ?? option['label'] ?? '');\n if (term.trim()) trackSemantic([option]);\n\n const suggestionOption = option as unknown as SuggestionOption;\n const href = service.getSuggestionHref(suggestionOption);\n navigateTo(\n href || service.submitProductSearch(term, suggestionOption),\n );\n },\n [navigateTo, service, trackSemantic],\n );\n\n const handleRunAction = useCallback(\n (option: SuggestionOptionWithTracking) => {\n if (\n isSuggestionDisabled(\n option as unknown as Record<string, unknown>,\n )\n ) {\n return;\n }\n const result = service.activateSuggestionAction(\n option as unknown as SuggestionOption,\n );\n void Promise.resolve(result)\n .then(navigateTo)\n .catch(() => undefined);\n },\n [navigateTo, service],\n );\n\n const handleSeeMore = useCallback(() => {\n const term = query.trim();\n if (term) navigateTo(service.viewMoreResults({ query: term }));\n }, [navigateTo, query, service]);\n\n const handleRecentSelect = useCallback(\n (recentQuery: string) => {\n trackSemantic({ query: recentQuery });\n navigateTo(service.submitProductSearch(recentQuery));\n },\n [navigateTo, service, trackSemantic],\n );\n\n const handleClearRecent = useCallback(() => {\n service.clearRecentSearches();\n setRecentSearches([]);\n }, [service]);\n\n // The agent could not be shown: give the shopper the search they asked for.\n const handleAgentUnavailable = useCallback(() => {\n if (agentQuery !== null)\n navigateTo(service.submitProductSearch(agentQuery));\n }, [agentQuery, navigateTo, service]);\n\n return (\n <SearchModal\n isOpen={isOpen}\n onClose={close}\n logo={logo}\n input={{\n value: query,\n onChange: updateQuery,\n onSubmit: handleSubmit,\n }}\n suggestions={{\n items,\n loading,\n showNoResults: !loading && emptyFetched && items.length === 0,\n showDidYouMean,\n hasMore: hasMoreResults,\n query,\n onSelect: handleSelect,\n onRunAction: handleRunAction,\n onSeeMore: handleSeeMore,\n }}\n recentSearches={{\n items: recentSearches,\n onSelect: handleRecentSelect,\n onClear: handleClearRecent,\n }}\n agentPanel={\n handoff === null || agent === undefined ? undefined : (\n <NuiAgentPanel\n agent={agent}\n query={handoff.query}\n handoffContext={{\n source: 'storefront_search',\n trigger: 'zero_results',\n query: handoff.query,\n did_you_mean: handoff.didYouMean,\n }}\n onUnavailable={handleAgentUnavailable}\n />\n )\n }\n />\n );\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type { ReactElement, ReactNode } from 'react';\nimport { useCommerceSearchConfig } from '../../hooks/useCommerceSearchConfig';\nimport { createSearchService } from '../../services/SearchApiService';\nimport { fetchMarketConfig } from '../../services/marketConfig';\nimport { SEARCH_GTM_USER_STATUS } from '../../utils/gtmConstants';\nimport type { SearchGtmContext } from '../../utils/gtmTypes';\nimport { toNavigationTarget } from '../../utils/navigationTarget';\nimport type { NavigationTarget } from '../../utils/navigationTarget';\nimport { CommerceSearchView } from './CommerceSearchView';\n\n/**\n * The account types the suggestions API distinguishes, sent as `X-Customer-Type`.\n *\n * TODO: this set is a best guess from the values the storefront sends. Confirm what the\n * suggestions API accepts, experimentally, once the search runs against it.\n */\nexport type CustomerAccountType =\n | 'guest'\n | 'Brand Affiliate'\n | 'Retail Customer'\n | 'Preferred Customer/Member';\n\n/** Who is searching. */\nexport interface CommerceSearchCustomer {\n /** Whether the visitor is signed in. The NUi agent is for signed-in visitors only. */\n isAuthenticated: boolean;\n /** Defaults to `guest`. Ignored for a visitor who is not signed in. */\n accountType?: CustomerAccountType;\n /** The signed-in visitor's id, for analytics. */\n userId?: string;\n}\n\nexport interface CommerceSearchProps {\n isOpen: boolean;\n onClose: () => void;\n /**\n * Takes the shopper to a destination, using the host's router for an internal path and a\n * full page load for an external URL. The panel closes afterwards.\n */\n navigate: (target: NavigationTarget) => void;\n /** Read on every request, so a change after sign-in is picked up. */\n customer: CommerceSearchCustomer;\n /** ISO 3166-1 alpha-2 market, for example `US`. */\n country: string;\n /** ISO 639-1 language, for example `en`. */\n language: string;\n /** Shown at the top of the panel, for example the brand logo. */\n logo?: ReactNode;\n}\n\nconst GUEST: CustomerAccountType = 'guest';\n\n/**\n * The commerce website's single search entry point: typeahead and recent searches over the\n * product catalog today, with the NUi agent taking over in the same panel when a signed-in\n * shopper searches for something with no products. What it can answer is not limited to\n * products — it is the commerce site's search, not a product-only search box.\n *\n * The package works out the rest itself: the market's catalog lookup, the minimum search length,\n * which NUi app to use, the panel's text and the analytics fields.\n */\nexport function CommerceSearch({\n isOpen,\n onClose,\n navigate,\n customer,\n country,\n language,\n logo,\n}: Readonly<CommerceSearchProps>): ReactElement {\n const [hasOpened, setHasOpened] = useState(false);\n useEffect(() => {\n if (isOpen) setHasOpened(true);\n }, [isOpen]);\n\n const { minimumSearchLength, agent } = useCommerceSearchConfig({\n country,\n language,\n enabled: hasOpened,\n });\n\n // Read per request, so a change of customer does not rebuild the service.\n const customerTypeRef = useRef<CustomerAccountType>(GUEST);\n customerTypeRef.current = customer.isAuthenticated\n ? (customer.accountType ?? GUEST)\n : GUEST;\n\n const service = useMemo(\n () =>\n createSearchService({\n country,\n language,\n locale: `${country.toUpperCase()}-${language.toLowerCase()}`,\n getMarketConfig: fetchMarketConfig,\n minimumSearchLength,\n getCustomerType: () => customerTypeRef.current,\n }),\n [country, language, minimumSearchLength],\n );\n\n const navigateToPath = useCallback(\n (path: string) => navigate(toNavigationTarget(path)),\n [navigate],\n );\n\n const { isAuthenticated, accountType, userId } = customer;\n const gtmContext = useMemo<Omit<SearchGtmContext, 'chatId'>>(\n () => ({\n countryCode: country,\n language,\n userStatus: isAuthenticated\n ? SEARCH_GTM_USER_STATUS.LOGGED_IN\n : SEARCH_GTM_USER_STATUS.GUEST,\n ...(isAuthenticated && accountType ? { accountType } : {}),\n ...(isAuthenticated && userId ? { userId } : {}),\n }),\n [country, language, isAuthenticated, accountType, userId],\n );\n\n return (\n <CommerceSearchView\n isOpen={isOpen}\n onClose={onClose}\n service={service}\n navigate={navigateToPath}\n isAuthenticated={isAuthenticated}\n {...(agent ? { agent } : {})}\n logo={logo}\n minimumSearchLength={minimumSearchLength}\n gtmContext={gtmContext}\n />\n );\n}\n"]}