{"version":3,"file":"search.fbf8092338fccad47d7a.js?ssi=0","mappings":"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","sources":["webpack://@logos/commerceweb-frontend/./Scripts/site/components/shared/scroll-threshold-bar/index.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/shared/books-by-author/index.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/hooks/use-publisher.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/content/section-content.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/clients/content-client.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/category-content.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/user-search-filter-context.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/accordion/accordion.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/facet-label.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/search-resources.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/bounded-responses-cache.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/algolia-search-context.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/util.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/filters.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/refinements.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/hidden-facet-refinements.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/skeleton/index.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/shared/enhanced-for-logos-label/index.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/shared/enhanced-for-logos-with-tooltip/index.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/product-card/use-product-card.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/product-card/product-image.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/product-card/discount-badge.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/product-card/product-title.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/product-card/product-authors.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/product-card/product-pricing.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/product-card/algolia-grid-card.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/product-card/product-overview.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/product-card/algolia-list-card.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/products.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/radio-accordion.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/sort-by-accordion.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/hits-per-page-accordion.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/use-view-mode.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/routing.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/use-hydration-settled.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/use-effective-search-parameters.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/index.tsx","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/hooks/use-search-impressions.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/components/search/hooks/use-search-analytics.ts","webpack://@logos/commerceweb-frontend/./Scripts/site/util/safe-json-parse.ts"],"sourcesContent":["import React, { useCallback, useEffect, useState } from 'react';\nimport type { ReactNode, RefObject } from 'react';\nimport { cn } from '../../../util/cn';\n\nexport interface ScrollThresholdBarProps {\n\ttargetRef: RefObject<HTMLElement | null>;\n\tchildren: ReactNode;\n\tthreshold?: number;\n\tposition?: 'top' | 'bottom';\n\trefreshKey?: unknown;\n\tclassName?: string;\n}\n\nexport function ScrollThresholdBar({\n\ttargetRef,\n\tchildren,\n\tthreshold = 1,\n\tposition = 'top',\n\trefreshKey,\n\tclassName,\n}: ScrollThresholdBarProps) {\n\tconst [isVisible, setIsVisible] = useState(false);\n\n\tuseEffect(() => {\n\t\tconst target = targetRef.current;\n\n\t\tif (!target) {\n\t\t\tsetIsVisible(false);\n\t\t\treturn;\n\t\t}\n\n\t\tconst normalizedThreshold = Number.isFinite(threshold) ? Math.min(1, Math.max(0, threshold)) : 1;\n\n\t\tlet scrollContainer = target.parentElement;\n\t\twhile (scrollContainer && scrollContainer !== document.body && scrollContainer !== document.documentElement) {\n\t\t\tconst { overflowY } = window.getComputedStyle(scrollContainer);\n\t\t\tif (['auto', 'scroll', 'overlay'].includes(overflowY)) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tscrollContainer = scrollContainer.parentElement;\n\t\t}\n\n\t\tconst scrollTarget =\n\t\t\tscrollContainer && scrollContainer !== document.body && scrollContainer !== document.documentElement\n\t\t\t\t? scrollContainer\n\t\t\t\t: null;\n\n\t\tlet animationFrame = 0;\n\n\t\tconst updateVisibility = () => {\n\t\t\tanimationFrame = 0;\n\t\t\tconst targetBounds = target.getBoundingClientRect();\n\t\t\tconst triggerPosition = targetBounds.top + targetBounds.height * normalizedThreshold;\n\t\t\tconst scrollportTop = scrollTarget ? scrollTarget.getBoundingClientRect().top + scrollTarget.clientTop : 0;\n\t\t\tsetIsVisible(triggerPosition <= scrollportTop);\n\t\t};\n\n\t\tconst scheduleUpdate = () => {\n\t\t\tif (!animationFrame) {\n\t\t\t\tanimationFrame = window.requestAnimationFrame(updateVisibility);\n\t\t\t}\n\t\t};\n\n\t\tupdateVisibility();\n\t\tconst eventTarget = scrollTarget ?? window;\n\t\teventTarget.addEventListener('scroll', scheduleUpdate, { passive: true });\n\t\twindow.addEventListener('resize', scheduleUpdate);\n\n\t\treturn () => {\n\t\t\teventTarget.removeEventListener('scroll', scheduleUpdate);\n\t\t\twindow.removeEventListener('resize', scheduleUpdate);\n\t\t\tif (animationFrame) {\n\t\t\t\twindow.cancelAnimationFrame(animationFrame);\n\t\t\t}\n\t\t};\n\t}, [refreshKey, targetRef, threshold]);\n\n\tconst stickyBarRef = useCallback(\n\t\t(stickyBar: HTMLDivElement | null) => {\n\t\t\tif (!stickyBar) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// React 16 drops boolean values for unknown attributes, so update inert through the DOM.\n\t\t\tif (isVisible) {\n\t\t\t\tstickyBar.removeAttribute('inert');\n\t\t\t} else {\n\t\t\t\tstickyBar.setAttribute('inert', '');\n\t\t\t}\n\t\t},\n\t\t[isVisible]\n\t);\n\n\tconst isAtTop = position === 'top';\n\n\treturn (\n\t\t<div\n\t\t\taria-hidden={!isVisible}\n\t\t\tclassName={cn(\n\t\t\t\t'fixed inset-x-0 transition-[transform,translate,visibility] duration-300 ease-in-out motion-reduce:transition-none',\n\t\t\t\tisAtTop ? 'top-0' : 'bottom-0',\n\t\t\t\tisVisible\n\t\t\t\t\t? 'visible translate-y-0'\n\t\t\t\t\t: isAtTop\n\t\t\t\t\t\t? 'invisible pointer-events-none -translate-y-full'\n\t\t\t\t\t\t: 'invisible pointer-events-none translate-y-full',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tref={stickyBarRef}\n\t\t>\n\t\t\t{children}\n\t\t</div>\n\t);\n}\n\nexport default ScrollThresholdBar;\n","import React, { useState } from 'react';\nimport { IconButton, Typography } from '@faithlife/commerce-components';\nimport { ChevronDown, ChevronUp } from 'lucide-react';\nimport { useRefinementList } from 'react-instantsearch';\nimport { AuthorBio } from '../author-bio';\nimport { useAuthor } from '../../../hooks/use-author';\n\nconst useGetRefinedValues = (attribute: string) =>\n\tuseRefinementList({ attribute })\n\t\t.items.filter(item => item.isRefined)\n\t\t.map(item => item.value) ?? [];\n\ninterface BooksByAuthorProps {\n\tresources: {\n\t\tbooksBy: string;\n\t\tshowMore: string;\n\t\tshowLess: string;\n\t};\n}\n\nexport const BooksByAuthor = ({ resources }: BooksByAuthorProps) => {\n\tconst refinedAuthorIds = useGetRefinedValues('authorIds');\n\tconst authorId = refinedAuthorIds?.length === 1 ? refinedAuthorIds[0] : '';\n\tconst { data: author, isLoading } = useAuthor(authorId);\n\n\tconst [isCollapsed, setIsCollapsed] = useState(false);\n\n\tif (isLoading || !authorId || !author || !author.displayName || !author.longDescription) {\n\t\treturn <></>;\n\t}\n\n\treturn (\n\t\t<div className=\"bg-[#f2f2f2] border-t border-b border-[#b1b1b1] px-3 py-4 md:p-6\">\n\t\t\t<div className=\"flex justify-between\">\n\t\t\t\t<Typography variant=\"headingH6\">\n\t\t\t\t\t{resources.booksBy} {author?.displayName}\n\t\t\t\t</Typography>\n\t\t\t\t<IconButton aria-label=\"Toggle collapse\" scale=\"sm\" onClick={() => setIsCollapsed(!isCollapsed)}>\n\t\t\t\t\t{isCollapsed ? <ChevronDown /> : <ChevronUp />}\n\t\t\t\t</IconButton>\n\t\t\t</div>\n\t\t\t{!isCollapsed && (\n\t\t\t\t<AuthorBio\n\t\t\t\t\tclassName=\"mt-4 rounded-[3px] border border-[#d8d8d8] bg-white p-4 md:p-8\"\n\t\t\t\t\tresources={resources}\n\t\t\t\t\tdisplayName={author?.displayName}\n\t\t\t\t\timageUrl={author?.imageUrlLarge}\n\t\t\t\t\tbio={author?.longDescription}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</div>\n\t);\n};\n","import { createBatchContext } from './use-batch';\n\nexport interface PublisherInfo {\n\tid: string;\n\tdisplayName: string;\n}\n\nexport const PublisherBatch = createBatchContext<string, PublisherInfo>(\n\tasync ids => {\n\t\tconst nonEmptyIds = ids.filter(id => id);\n\t\tif (nonEmptyIds.length === 0) {\n\t\t\treturn [];\n\t\t}\n\t\tconst response = await fetch(`/api/publisher?ids=${nonEmptyIds.join(',')}`);\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`HTTP error! status: ${response.status}`);\n\t\t}\n\n\t\treturn (await response.json()) as PublisherInfo[];\n\t},\n\t(id, data) => data.find(d => d.id === id)\n);\n\nexport function usePublisher(id: string) {\n\treturn PublisherBatch.useData(id);\n}\n","import React, { useEffect, useRef, useState } from 'react';\n\nimport { RenderBuilderContent } from '../builder';\nimport { getSections } from '../../clients/content-client';\nimport { useLocation } from '../../location';\nimport { useIsPreviewingThisBuilderModel, SectionContentViewModel, SectionKind } from '../../builder';\nimport { c_defaultUserInfo } from '../per-user-data/per-user-data-context';\nimport { notifyWarning } from '../notifications';\n\ninterface ContentChangeEvent {\n\thasContent: boolean;\n\tcontentKey: string;\n}\n\nconst builderIoModelNamesBySectionKindMap: Record<SectionKind, string> = {\n\tsearchResultsAbove: 'search-results-above',\n\tsearchResultsBelow: 'search-results-below',\n\tuniversalHeader: 'universal-header',\n\tuniversalFooter: 'universal-footer',\n\tsubscriptionChurnPrevention: 'subscription-churn-prevention',\n\tconfigurationWizardSubscriptionsBanner: 'configuration-wizard-subscriptions-banner',\n\tconfigurationWizardSubscriptionsContent: 'configuration-wizard-subscriptions-content',\n\tconfigurationWizardLibrariesBanner: 'configuration-wizard-libraries-banner',\n\torderSummary: 'order-summary',\n\torderSummaryFooter: 'order-summary-footer',\n\tproductPage: 'product-page',\n\tadzone: 'adzone',\n\tnotifications: 'notifications',\n\tpdpBanner: 'pdp-banner',\n};\n\nfunction getContentKey(sectionContents: SectionContentViewModel[]): string {\n\treturn sectionContents\n\t\t.filter(sc => !!sc)\n\t\t.map(sc => `${sc.sectionKind}:${sc.contentSourceKind}:${sc.contentId}`)\n\t\t.join('|');\n}\n\nconst SectionContent = ({\n\tsectionKind,\n\tinitialSectionContents,\n\tonContentChange,\n\trenderFallback,\n}: {\n\tsectionKind: SectionKind;\n\tinitialSectionContents?: SectionContentViewModel[];\n\tonContentChange?: (event: ContentChangeEvent) => void;\n\trenderFallback?: () => React.ReactNode;\n}) => {\n\tconst builderIoModel = builderIoModelNamesBySectionKindMap[sectionKind];\n\tconst isBuilderIoPreviewingThisModel = useIsPreviewingThisBuilderModel(builderIoModel);\n\tconst location = useLocation();\n\tconst renderFallbackRef = useRef(renderFallback);\n\trenderFallbackRef.current = renderFallback;\n\tconst [{ sectionContents, fallback }, setContent] = useState(() => ({\n\t\tsectionContents: initialSectionContents ?? [],\n\t\tfallback: renderFallback?.(),\n\t}));\n\tconst lastRequestedLocationHref = useRef(initialSectionContents === undefined ? undefined : location.href);\n\tconst initialPathname = useRef(location.pathname);\n\tconst hasInitialSections = useRef(initialSectionContents !== undefined);\n\n\tuseEffect(() => {\n\t\tconst fetchSections = async () => {\n\t\t\tconst sections = await getSections({\n\t\t\t\tkind: sectionKind,\n\t\t\t\turl: location.href,\n\t\t\t});\n\n\t\t\tconst fallback = renderFallbackRef.current?.();\n\t\t\tsetContent({ sectionContents: sections, fallback });\n\n\t\t\tconst filteredSections = sections.filter(sc => !!sc);\n\t\t\tonContentChange?.({\n\t\t\t\thasContent: filteredSections.length > 0 || isBuilderIoPreviewingThisModel || !!fallback,\n\t\t\t\tcontentKey: getContentKey(filteredSections),\n\t\t\t});\n\t\t};\n\n\t\tif (!location.isQueryStringReady || isBuilderIoPreviewingThisModel) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (hasInitialSections.current) {\n\t\t\thasInitialSections.current = false;\n\t\t\tif (location.pathname === initialPathname.current) {\n\t\t\t\tlastRequestedLocationHref.current = location.href;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif (location.href !== lastRequestedLocationHref.current) {\n\t\t\tlastRequestedLocationHref.current = location.href;\n\t\t\tfetchSections();\n\t\t}\n\t}, [\n\t\tsectionKind,\n\t\tlocation.href,\n\t\tlocation.pathname,\n\t\tlocation.isQueryStringReady,\n\t\tonContentChange,\n\t\tisBuilderIoPreviewingThisModel,\n\t\tinitialSectionContents,\n\t]);\n\n\tuseEffect(() => {\n\t\tif (isBuilderIoPreviewingThisModel) {\n\t\t\tnotifyWarning(`You are previewing the \"${builderIoModel}\" Builder.io model.`);\n\t\t}\n\t}, [isBuilderIoPreviewingThisModel, builderIoModel]);\n\n\tif (isBuilderIoPreviewingThisModel) {\n\t\treturn (\n\t\t\t<RenderBuilderContent\n\t\t\t\tmodel={builderIoModel}\n\t\t\t\tstaticData={{\n\t\t\t\t\tstaticProductData: [],\n\t\t\t\t\tuserInfo: c_defaultUserInfo,\n\t\t\t\t}}\n\t\t\t/>\n\t\t);\n\t}\n\n\tconst filteredContents = sectionContents.filter(sc => !!sc);\n\tconst hasContent = filteredContents.length > 0;\n\n\tif (!hasContent) {\n\t\treturn <>{fallback}</>;\n\t}\n\n\treturn (\n\t\t<>\n\t\t\t{filteredContents.map(sc =>\n\t\t\t\tsc.contentSourceKind === 'builderIo' ? <RenderBuilderContent key={sc.contentId} {...sc.builderIo} /> : null\n\t\t\t)}\n\t\t</>\n\t);\n};\n\nexport default SectionContent;\n","import { fetch } from '../util/fetch';\nimport { SectionContentViewModel, SectionKind } from '../builder';\n\ninterface Params {\n\tkind: SectionKind;\n\turl: string;\n}\n\nexport async function getSections({ kind, url }: Params): Promise<SectionContentViewModel[]> {\n\ttry {\n\t\tconst response = await fetch.get({\n\t\t\turl: '/api/sections',\n\t\t\tparams: { kind, url },\n\t\t});\n\n\t\tconst results = await response.json();\n\t\treturn results as unknown as SectionContentViewModel[];\n\t} catch (error) {\n\t\treturn [];\n\t}\n}\n","import React, { useState, useCallback } from 'react';\n\nimport ReadMoreReadLess from '../read-more-read-less';\nimport { SectionContent } from '../content';\nimport ErrorBoundary from '../error-boundary';\nimport type { SectionContentViewModel, SectionKind } from '../../builder';\n\ninterface Props {\n\tsectionKind: SectionKind;\n\tinitialSectionContents?: SectionContentViewModel[];\n\trenderFallback?: () => React.ReactNode;\n}\n\ninterface ContentChangeEvent {\n\thasContent: boolean;\n\tcontentKey: string;\n}\n\nconst CategoryContent = ({ sectionKind, initialSectionContents, renderFallback }: Props) => {\n\t// Merged into one state object so both values update in a single render,\n\t// avoiding separate re-renders that can cause SectionContent to remount.\n\tconst [{ hasContent, contentKey }, setContentState] = useState(() => {\n\t\tconst filteredSections = initialSectionContents?.filter(sc => !!sc) ?? [];\n\t\treturn {\n\t\t\thasContent: filteredSections.length > 0 || !!renderFallback?.(),\n\t\t\tcontentKey: filteredSections.map(sc => `${sc.sectionKind}:${sc.contentSourceKind}:${sc.contentId}`).join('|'),\n\t\t};\n\t});\n\n\tconst handleContentChange = useCallback((event: ContentChangeEvent) => {\n\t\tsetContentState(prev =>\n\t\t\tprev.hasContent === event.hasContent && prev.contentKey === event.contentKey\n\t\t\t\t? prev\n\t\t\t\t: { hasContent: event.hasContent, contentKey: event.contentKey }\n\t\t);\n\t}, []);\n\n\t// SectionContent always stays in the same tree position (inside ReadMoreReadLess).\n\t// Changing the parent conditionally would cause SectionContent to unmount/remount\n\t// and re-fire the sections AJAX on every hasContent or contentKey state change.\n\treturn (\n\t\t<ErrorBoundary>\n\t\t\t<div className={hasContent ? 'w-full' : 'hidden'}>\n\t\t\t\t<ReadMoreReadLess contentKey={contentKey}>\n\t\t\t\t\t<SectionContent\n\t\t\t\t\t\tsectionKind={sectionKind}\n\t\t\t\t\t\tinitialSectionContents={initialSectionContents}\n\t\t\t\t\t\tonContentChange={handleContentChange}\n\t\t\t\t\t\trenderFallback={renderFallback}\n\t\t\t\t\t/>\n\t\t\t\t</ReadMoreReadLess>\n\t\t\t</div>\n\t\t</ErrorBoundary>\n\t);\n};\n\nexport default CategoryContent;\n","import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';\n\nimport { useLocation } from '../../location';\n\nexport interface UserSearchFilterOption {\n\tdisplayName: string;\n\tisDefault?: boolean;\n\talgoliaValue: string;\n\ttoken: string;\n}\n\nexport interface UserSearchFilter {\n\ttitle: string;\n\toptions: UserSearchFilterOption[];\n\ttoken: string;\n}\n\nexport interface UserSearchFilters {\n\tfilters: UserSearchFilter[];\n}\n\ninterface UserSearchFilterContextValue {\n\tselectedFilterOptions: Record<string, string>;\n\tsetSelectedFilterOption: (filterToken: string, optionToken: string) => void;\n\tuserSearchFilters: UserSearchFilter[];\n}\n\nconst UserSearchFilterContext = createContext<UserSearchFilterContextValue | null>(null);\n\nfunction getDefaultSelectedFilterOptions(userSearchFilters: UserSearchFilter[]) {\n\treturn userSearchFilters.reduce<Record<string, string>>((selectedOptions, filter) => {\n\t\tconst options = Array.isArray(filter?.options) ? filter.options : [];\n\t\tconst selectedOption = options.find(option => option?.isDefault) ?? options[0];\n\n\t\tif (selectedOption?.token) {\n\t\t\tselectedOptions[filter.token] = selectedOption.token;\n\t\t}\n\n\t\treturn selectedOptions;\n\t}, {});\n}\n\nfunction areSelectedFilterOptionsEqual(first: Record<string, string>, second: Record<string, string>): boolean {\n\tconst firstKeys = Object.keys(first);\n\tconst secondKeys = Object.keys(second);\n\n\treturn firstKeys.length === secondKeys.length && firstKeys.every(key => first[key] === second[key]);\n}\n\nfunction readUserFilterSelectionsFromUrl(\n\tuserSearchFilters: UserSearchFilter[],\n\tsearchParams: URLSearchParams\n): Record<string, string> {\n\tconst defaults = getDefaultSelectedFilterOptions(userSearchFilters);\n\n\treturn userSearchFilters.reduce<Record<string, string>>((selectedOptions, filter) => {\n\t\tconst options = Array.isArray(filter?.options) ? filter.options : [];\n\t\tconst urlValue = searchParams.get(filter.token);\n\t\tconst matchingOption = urlValue ? options.find(option => option?.token === urlValue) : undefined;\n\n\t\tconst resolved = matchingOption?.token ?? defaults[filter.token];\n\t\tif (resolved) {\n\t\t\tselectedOptions[filter.token] = resolved;\n\t\t}\n\n\t\treturn selectedOptions;\n\t}, {});\n}\n\nfunction writeUserFilterSelectionsToUrl(\n\tselectedFilterOptions: Record<string, string>,\n\tuserSearchFilters: UserSearchFilter[],\n\tsearch: string,\n\tpathname: string,\n\treplaceUrl: (url: string) => void\n) {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(`https://placeholder${pathname}${search}`);\n\t} catch {\n\t\t// Malformed pathname/search — skip URL update rather than crash.\n\t\treturn;\n\t}\n\n\tfor (const filter of userSearchFilters) {\n\t\tconst selectedToken = selectedFilterOptions[filter.token];\n\n\t\tif (selectedToken) {\n\t\t\turl.searchParams.set(filter.token, selectedToken);\n\t\t} else {\n\t\t\turl.searchParams.delete(filter.token);\n\t\t}\n\t}\n\n\ttry {\n\t\tif (`${url.pathname}${url.search}` !== `${pathname}${search}`) {\n\t\t\treplaceUrl(`${url.pathname}${url.search}`);\n\t\t}\n\t} catch {\n\t\t// History replacement can fail in some browsers / iframes.\n\t}\n}\n\nexport function useUserSearchFilterContext() {\n\tconst context = useContext(UserSearchFilterContext);\n\tif (!context) {\n\t\tthrow new Error('useUserSearchFilterContext must be used within UserSearchFilterProvider');\n\t}\n\treturn context;\n}\n\nexport function UserSearchFilterProvider({\n\tuserSearchFilters,\n\tinitialSelectedFilterOptions,\n\tsetSelectedFilterOptionsOverride,\n\tchildren,\n}: {\n\tuserSearchFilters: UserSearchFilter[];\n\tinitialSelectedFilterOptions?: Record<string, string>;\n\tsetSelectedFilterOptionsOverride?: () => Record<string, string>;\n\tchildren: React.ReactNode;\n}) {\n\tconst { search, replaceUrl, isQueryStringReady } = useLocation();\n\tconst searchParams = useMemo(() => new URLSearchParams(search), [search]);\n\tconst [hasReadQuery, setHasReadQuery] = useState(false);\n\n\tconst [selectedFilterOptions, setSelectedFilterOptions] = useState<Record<string, string>>(() => {\n\t\tconst urlSelections = readUserFilterSelectionsFromUrl(userSearchFilters, searchParams);\n\n\t\treturn userSearchFilters.reduce<Record<string, string>>((selectedOptions, filter) => {\n\t\t\tconst initialSelection = initialSelectedFilterOptions?.[filter.token];\n\t\t\tconst isInitialSelectionValid = filter.options.some(option => option.token === initialSelection);\n\t\t\tconst selectedOption = isInitialSelectionValid ? initialSelection : urlSelections[filter.token];\n\n\t\t\tif (selectedOption) {\n\t\t\t\tselectedOptions[filter.token] = selectedOption;\n\t\t\t}\n\n\t\t\treturn selectedOptions;\n\t\t}, {});\n\t});\n\n\tuseEffect(() => {\n\t\tif (!isQueryStringReady) {\n\t\t\treturn;\n\t\t}\n\t\tsetSelectedFilterOptions(prev => {\n\t\t\tlet next: Record<string, string>;\n\n\t\t\tif (setSelectedFilterOptionsOverride) {\n\t\t\t\tnext = setSelectedFilterOptionsOverride();\n\t\t\t} else {\n\t\t\t\tconst urlSelections = readUserFilterSelectionsFromUrl(userSearchFilters, searchParams);\n\n\t\t\t\t// Only reset if userSearchFilters changed (not a URL-driven update).\n\t\t\t\t// Preserve current selection if the option is still valid for the new filter set.\n\t\t\t\tnext = userSearchFilters.reduce<Record<string, string>>((selectedOptions, filter) => {\n\t\t\t\t\tconst currentSelection = prev[filter.token];\n\t\t\t\t\tconst isStillValid = filter.options.some(option => option.token === currentSelection);\n\t\t\t\t\tconst selectedOption =\n\t\t\t\t\t\t(hasReadQuery || initialSelectedFilterOptions) && isStillValid\n\t\t\t\t\t\t\t? currentSelection\n\t\t\t\t\t\t\t: urlSelections[filter.token];\n\n\t\t\t\t\tif (selectedOption) {\n\t\t\t\t\t\tselectedOptions[filter.token] = selectedOption;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn selectedOptions;\n\t\t\t\t}, {});\n\t\t\t}\n\n\t\t\treturn areSelectedFilterOptionsEqual(prev, next) ? prev : next;\n\t\t});\n\t\tsetHasReadQuery(true);\n\t}, [\n\t\tsetSelectedFilterOptionsOverride,\n\t\tuserSearchFilters,\n\t\tsearchParams,\n\t\tisQueryStringReady,\n\t\thasReadQuery,\n\t\tinitialSelectedFilterOptions,\n\t]);\n\n\tuseEffect(() => {\n\t\tif (isQueryStringReady && hasReadQuery) {\n\t\t\twriteUserFilterSelectionsToUrl(\n\t\t\t\tselectedFilterOptions,\n\t\t\t\tuserSearchFilters,\n\t\t\t\twindow.location.search,\n\t\t\t\twindow.location.pathname,\n\t\t\t\treplaceUrl\n\t\t\t);\n\t\t}\n\t}, [selectedFilterOptions, userSearchFilters, search, replaceUrl, isQueryStringReady, hasReadQuery]);\n\n\tconst handleSetSelectedFilterOption = (filterToken: string, optionToken: string) => {\n\t\tsetSelectedFilterOptions(prev => ({\n\t\t\t...prev,\n\t\t\t[filterToken]: optionToken,\n\t\t}));\n\t};\n\n\tconst contextValue = useMemo(\n\t\t() => ({\n\t\t\tselectedFilterOptions,\n\t\t\tsetSelectedFilterOption: handleSetSelectedFilterOption,\n\t\t\tuserSearchFilters,\n\t\t}),\n\t\t[selectedFilterOptions, userSearchFilters]\n\t);\n\n\treturn <UserSearchFilterContext.Provider value={contextValue}>{children}</UserSearchFilterContext.Provider>;\n}\n","import * as React from 'react';\nimport * as AccordionPrimitive from '@radix-ui/react-accordion';\nimport { ChevronDown } from 'lucide-react';\n\nimport { cn } from '../../util/cn';\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n\tReact.ComponentRef<typeof AccordionPrimitive.Item>,\n\tReact.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => <AccordionPrimitive.Item className={cn('', className)} ref={ref} {...props} />);\n\nAccordionItem.displayName = AccordionPrimitive.Item.displayName;\n\nconst AccordionTrigger = React.forwardRef<\n\tReact.ComponentRef<typeof AccordionPrimitive.Trigger>,\n\tReact.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n\t<AccordionPrimitive.Header className=\"flex\">\n\t\t<AccordionPrimitive.Trigger\n\t\t\tclassName={cn(\n\t\t\t\t'flex flex-1 items-center justify-between py-[9.5px] text-lg font-bold outline-hidden transition-all hover:text-secondary focus-visible:text-secondary [&[data-state=open]>svg]:rotate-180',\n\t\t\t\tclassName\n\t\t\t)}\n\t\t\tref={ref}\n\t\t\t{...props}\n\t\t>\n\t\t\t{children}\n\t\t\t{/* TODO: For the sake of moving fast we are leaving this in, but in the future we need to figure out how enable custom icons */}\n\t\t\t<ChevronDown className=\"h-6 w-6 shrink-0 transition-transform duration-200\" />\n\t\t</AccordionPrimitive.Trigger>\n\t</AccordionPrimitive.Header>\n));\n\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n\tReact.ComponentRef<typeof AccordionPrimitive.Content>,\n\tReact.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n\t<AccordionPrimitive.Content\n\t\tclassName={cn(\n\t\t\t'data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down mb-4 overflow-hidden transition-all',\n\t\t\tclassName\n\t\t)}\n\t\tref={ref}\n\t\t{...props}\n\t>\n\t\t{children}\n\t</AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n","import { useLocalization } from '../../localization/use-localization';\n\nconst c_nonWordCharacters = /[^\\p{L}\\p{Mn}\\p{Nd}\\p{Pc}]/gu;\nconst c_leadingDecimalDigit = /^\\p{Nd}/u;\nconst c_facetResourceKeyAliases: Readonly<Record<string, Readonly<Record<string, string>>>> = {\n\t// The existing resource key for 3 John is John4.\n\tbibleAndApocrypha: {\n\t\t'3 John': 'John4',\n\t},\n\tcontainment: {\n\t\tsingle: 'SingleTitle',\n\t\tstandalone: 'SoldIndividually',\n\t},\n\tformat: {\n\t\treader: 'ReaderEdition',\n\t},\n\treligiousGroup: {\n\t\t'Pentecostal/Charismatic': 'PentecostalCharismatic1',\n\t},\n\ttopic: {\n\t\t'Angelology/Demonology': 'AngelologyDemonology1',\n\t},\n};\n\nexport function getFacetDisplayLabel(rawLabel: string, resources: Record<string, string>, attribute?: string): string {\n\tconst leaf = getFacetLeaf(rawLabel);\n\tconst resourceName = leaf.replace(c_nonWordCharacters, '');\n\tconst baseAttribute = attribute?.replace(/\\.lvl\\d+$/, '');\n\tconst resourceKeyAlias = baseAttribute ? c_facetResourceKeyAliases[baseAttribute]?.[leaf] : undefined;\n\tconst resourceKeys = resourceKeyAlias ? [resourceKeyAlias] : getResourceKeys(resourceName);\n\n\tfor (const resourceKey of resourceKeys) {\n\t\tconst translation = getResourceValue(resources, resourceKey);\n\t\tif (typeof translation === 'string') {\n\t\t\treturn translation.trim();\n\t\t}\n\t}\n\n\treturn leaf;\n}\n\nfunction getResourceKeys(resourceName: string): string[] {\n\tconst leadingDigitKey = c_leadingDecimalDigit.test(resourceName) ? `_${resourceName}` : resourceName;\n\tconst keys = [leadingDigitKey];\n\tconst leadingDigits = resourceName.match(/^(\\p{Nd}+)(.+)$/u);\n\n\tif (leadingDigits) {\n\t\tkeys.push(`${leadingDigits[2]}${leadingDigits[1]}`);\n\t}\n\n\treturn keys;\n}\n\nfunction getResourceValue(resources: Record<string, string>, resourceKey: string): string | undefined {\n\tif (Object.prototype.hasOwnProperty.call(resources, resourceKey)) {\n\t\treturn resources[resourceKey];\n\t}\n\n\tconst caseInsensitiveKey = Object.keys(resources).find(key => key.toLowerCase() === resourceKey.toLowerCase());\n\treturn caseInsensitiveKey ? resources[caseInsensitiveKey] : undefined;\n}\n\nexport function useFacetConstraints() {\n\treturn useLocalization('CommerceWeb.Resources.Search.FacetConstraints', { allKeys: true });\n}\n\nfunction getFacetLeaf(rawLabel: string): string {\n\tconst separatorIndex = rawLabel.lastIndexOf('>');\n\tif (separatorIndex === -1) {\n\t\treturn rawLabel;\n\t}\n\n\treturn rawLabel.slice(separatorIndex + 1).trim();\n}\n","import { createContext, useContext } from 'react';\n\nexport const SearchResourcesContext = createContext<Record<string, string>>({});\n\nexport function useSearchResources(): Record<string, string> {\n\treturn useContext(SearchResourcesContext);\n}\n","import type { Cache, CacheEvents } from '@algolia/client-common';\n\n// Algolia's default `createMemoryCache` never evicts, so a long filtering session retains every\n// distinct search indefinitely. That is costly here because ownership-filtered searches carry a\n// `filters` string listing every owned productId, and it is stored twice: once as the cache key and\n// again inside the response, which echoes the request params back. Measured against a 20k-product\n// library, each cached search retained ~2.1MB (~1.0MB key, ~1.1MB value) against a ~0.15MB baseline,\n// and 14 cached searches held 26.6MB.\n//\n// Because entry size scales with the size of the user's library, the budget is in characters rather\n// than entries. This cache otherwise keeps `createMemoryCache`'s exact semantics -- same\n// `JSON.stringify` key, same serialized value, same miss handling -- and only adds eviction, so an\n// evicted entry behaves precisely like the cache miss that would have happened before it was ever\n// cached.\n\nconst defaultMaxCharacters = 8 * 1024 * 1024;\n\nfunction serializeKey(key: Record<string, any> | string): string {\n\treturn JSON.stringify(key);\n}\n\nexport function createBoundedResponsesCache(maxCharacters: number = defaultMaxCharacters): Cache {\n\tconst cache = new Map<string, string>();\n\tlet characters = 0;\n\n\tfunction evict() {\n\t\t// Always keep the most recently written entry, so a single oversized response still caches.\n\t\twhile (characters > maxCharacters && cache.size > 1) {\n\t\t\tconst oldestKey = cache.keys().next().value;\n\t\t\tif (oldestKey === undefined) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcharacters -= oldestKey.length + (cache.get(oldestKey)?.length ?? 0);\n\t\t\tcache.delete(oldestKey);\n\t\t}\n\t}\n\n\treturn {\n\t\tget<TValue>(\n\t\t\tkey: Record<string, any> | string,\n\t\t\tdefaultValue: () => Promise<TValue>,\n\t\t\tevents: CacheEvents<TValue> = { miss: () => Promise.resolve() }\n\t\t): Promise<TValue> {\n\t\t\tconst serializedKey = serializeKey(key);\n\t\t\tconst cached = cache.get(serializedKey);\n\n\t\t\tif (cached !== undefined) {\n\t\t\t\tcache.delete(serializedKey);\n\t\t\t\tcache.set(serializedKey, cached);\n\n\t\t\t\treturn Promise.resolve(JSON.parse(cached) as TValue);\n\t\t\t}\n\n\t\t\tconst promise = defaultValue();\n\n\t\t\treturn promise.then(value => events.miss(value)).then(() => promise);\n\t\t},\n\n\t\tset<TValue>(key: Record<string, any> | string, value: TValue): Promise<TValue> {\n\t\t\tconst serializedKey = serializeKey(key);\n\t\t\tconst serializedValue = JSON.stringify(value);\n\n\t\t\tconst existing = cache.get(serializedKey);\n\t\t\tif (existing !== undefined) {\n\t\t\t\tcharacters -= serializedKey.length + existing.length;\n\t\t\t\tcache.delete(serializedKey);\n\t\t\t}\n\n\t\t\tcache.set(serializedKey, serializedValue);\n\t\t\tcharacters += serializedKey.length + serializedValue.length;\n\t\t\tevict();\n\n\t\t\treturn Promise.resolve(value);\n\t\t},\n\n\t\tdelete(key: Record<string, any> | string): Promise<void> {\n\t\t\tconst serializedKey = serializeKey(key);\n\t\t\tconst existing = cache.get(serializedKey);\n\t\t\tif (existing !== undefined) {\n\t\t\t\tcharacters -= serializedKey.length + existing.length;\n\t\t\t\tcache.delete(serializedKey);\n\t\t\t}\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\n\t\tclear(): Promise<void> {\n\t\t\tcache.clear();\n\t\t\tcharacters = 0;\n\n\t\t\treturn Promise.resolve();\n\t\t},\n\t};\n}\n","import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';\nimport { algoliasearch } from 'algoliasearch';\nimport insightsClient from 'search-insights';\nimport { createAlgoliaInsightsInitOptions } from '../../util/algolia';\nimport { createBoundedResponsesCache } from './bounded-responses-cache';\n\n// ---------------------------------------------------------------------------\n// Algolia search context — provides the configured Algolia client\n// ---------------------------------------------------------------------------\n\ninterface AlgoliaSearchContextValue {\n\tclient: ReturnType<typeof algoliasearch>;\n\tindexName: string;\n\tstorefrontShortname: string;\n\tuserId: string | null;\n\tisSignedIn: boolean;\n\tanonymousUserToken: string | null;\n}\n\nconst AlgoliaSearchContext = createContext<AlgoliaSearchContextValue | null>(null);\n\ninterface AlgoliaSearchContextProviderProps {\n\tappId: string;\n\tappKey: string;\n\tcookieDuration?: number | null;\n\tindexName: string;\n\tstorefrontShortname: string;\n\tuserId?: string | null;\n\tisSignedIn?: boolean;\n\tchildren: React.ReactNode;\n}\n\nexport function AlgoliaSearchContextProvider({\n\tappId,\n\tappKey,\n\tcookieDuration,\n\tindexName,\n\tstorefrontShortname,\n\tuserId = null,\n\tisSignedIn = false,\n\tchildren,\n}: AlgoliaSearchContextProviderProps) {\n\tconst client = useMemo(\n\t\t() => algoliasearch(appId, appKey, { responsesCache: createBoundedResponsesCache() }),\n\t\t[appId, appKey]\n\t);\n\tconst [anonymousUserToken, setAnonymousUserToken] = useState<string | null>(null);\n\n\tuseEffect(() => {\n\t\tinsightsClient('init', createAlgoliaInsightsInitOptions(appId, appKey, cookieDuration));\n\t\tinsightsClient('getUserToken', {}, (error, userToken) => {\n\t\t\tif (!error && userToken !== undefined) {\n\t\t\t\tsetAnonymousUserToken(String(userToken));\n\t\t\t}\n\t\t});\n\t\tif (userId) {\n\t\t\tinsightsClient('setAuthenticatedUserToken', userId);\n\t\t}\n\t}, [appId, appKey, cookieDuration, userId]);\n\n\tconst value = useMemo(\n\t\t() => ({ client, indexName, storefrontShortname, userId, isSignedIn, anonymousUserToken }),\n\t\t[client, indexName, storefrontShortname, userId, isSignedIn, anonymousUserToken]\n\t);\n\n\treturn <AlgoliaSearchContext.Provider value={value}>{children}</AlgoliaSearchContext.Provider>;\n}\n\nexport function useAlgoliaSearch(): AlgoliaSearchContextValue {\n\tconst context = useContext(AlgoliaSearchContext);\n\n\tif (!context) {\n\t\tthrow new Error('useAlgoliaSearch must be used within an AlgoliaSearchContextProvider');\n\t}\n\n\treturn context;\n}\n","import type { ProductPriceAmount } from '../per-user-data/per-user-data-context';\n\ninterface SavingsPrices {\n\tsalePrice?: Pick<ProductPriceAmount, 'amount'> | null;\n\tanchorPrice?: Pick<ProductPriceAmount, 'amount'> | null;\n}\n\n/**\n * Transliterates Unicode characters to their closest ASCII equivalents.\n * Approximates the behavior of the .NET Unidecode library used by SlugHelper on the server.\n */\nfunction unidecode(text: string): string {\n\t// Handle characters that don't decompose via NFD but have ASCII equivalents.\n\t// Order matters: apply multi-char replacements before NFD strips combining marks.\n\tconst result = text\n\t\t.replace(/ß/g, 'ss')\n\t\t.replace(/[æÆ]/g, 'ae')\n\t\t.replace(/[œŒ]/g, 'oe')\n\t\t.replace(/[øØ]/g, 'o')\n\t\t.replace(/[ðÐ]/g, 'd')\n\t\t.replace(/[þÞ]/g, 'th')\n\t\t.replace(/[łŁ]/g, 'l');\n\n\t// Strip combining diacritical marks from remaining Latin characters via NFD normalization.\n\treturn result.normalize('NFD').replace(/\\p{Mn}/gu, '');\n}\n\n/**\n * Converts a string to a URL-friendly slug.\n * Matches the server-side SlugHelper.Slugify method used to generate product URL slugs.\n */\nexport function slugify(value: string | undefined): string {\n\tif (!value) {\n\t\treturn '';\n\t}\n\n\t// Remove trademark/registered symbols\n\tlet input = value.replace(/®/g, '').replace(/™/g, '');\n\n\t// Transliterate Unicode → ASCII, then lowercase (matches .Unidecode().ToLowerInvariant())\n\tinput = unidecode(input).toLowerCase();\n\n\t// Remove trailing parenthetical and bracket blocks, e.g. \"Title (Subtitle) [Edition]\"\n\t// Matches s_parenBlocks = new Regex(\"(\\\\(.*\\\\))?(\\\\s*\\\\[.*\\\\])*$\")\n\tinput = input.replace(/(\\(.*\\))?(\\s*\\[.*\\])*$/g, '');\n\n\t// Strip HTML tags — matches s_htmlTags = new Regex(\"</?[^>]+>\")\n\tinput = input.replace(/<\\/?[^>]+>/g, '');\n\n\t// Expand ampersand\n\tinput = input.replace(/ & /g, ' and ');\n\n\t// Convert separating punctuation to spaces — matches s_punctuationForSpace = new Regex(\"[/\\\\-:_]\")\n\tinput = input.replace(/[/\\-:_]/g, ' ');\n\n\t// Remove all remaining non-alphanumeric, non-space characters — matches s_punctuationAndNonAlpha = new Regex(\"[^a-z0-9 ]\")\n\tinput = input.replace(/[^a-z0-9 ]/g, '');\n\n\t// Collapse whitespace runs to hyphens — matches s_excessWhitespace = new Regex(\"\\\\s+\")\n\treturn input.trim().replace(/\\s+/g, '-');\n}\n\nexport function getSavingsPercent(prices: SavingsPrices | null | undefined): number {\n\tconst anchor = prices?.anchorPrice?.amount;\n\tconst sale = prices?.salePrice?.amount;\n\tif (!anchor || !sale) {\n\t\treturn 0;\n\t}\n\tif (anchor <= 0) {\n\t\treturn 0;\n\t}\n\treturn ((anchor - sale) / anchor) * 100;\n}\n\n/**\n * Splits an author/publisher facet value of the form \"id:displayName\" into its parts.\n * Uses the first colon as the separator so display names that themselves contain colons\n * are preserved. When no colon is present, the whole value is treated as both id and name.\n */\nexport function parseFacetValue(value: string): { id: string; displayName: string } {\n\tconst separatorIndex = value.indexOf(':');\n\tif (separatorIndex === -1) {\n\t\treturn { id: value, displayName: value };\n\t}\n\treturn {\n\t\tid: value.substring(0, separatorIndex),\n\t\tdisplayName: value.substring(separatorIndex + 1),\n\t};\n}\n\nexport function safeUrl(input: string, base?: string): URL | null {\n\ttry {\n\t\treturn new URL(input, base);\n\t} catch {\n\t\treturn null;\n\t}\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport insightsClient from 'search-insights';\nimport { LinkButton, Typography } from '@faithlife/commerce-components';\nimport {\n\tRefinementListItem,\n\tRefinementListRenderState,\n} from 'instantsearch.js/es/connectors/refinement-list/connectRefinementList';\nimport { useRefinementList } from 'react-instantsearch';\nimport { cn } from '../../util/cn';\n\nimport { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '../accordion';\nimport { getFacetDisplayLabel, useFacetConstraints } from './facet-label';\nimport { useSearchResources } from './search-resources';\nimport { UserSearchFilter, UserSearchFilterOption, useUserSearchFilterContext } from './user-search-filter-context';\nimport { useAlgoliaSearch } from './algolia-search-context';\nimport { parseFacetValue } from './util';\n\nfunction Check({ className, checked }: { className?: string; checked: boolean }) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={cn('inline', className)}\n\t\t\tfill=\"none\"\n\t\t\theight=\"14\"\n\t\t\tviewBox=\"0 0 13 14\"\n\t\t\twidth=\"13\"\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t>\n\t\t\t<rect\n\t\t\t\tfill={checked ? '#1E6AFE' : 'white'}\n\t\t\t\theight=\"13\"\n\t\t\t\trx=\"1\"\n\t\t\t\tstroke={checked ? undefined : '#C7C7C7'}\n\t\t\t\twidth=\"13\"\n\t\t\t\ty=\"0.5\"\n\t\t\t/>\n\t\t\t<path d=\"M3.28223 7.73706L5.2634 9.71824L9.71857 5.26308\" stroke=\"white\" strokeLinecap=\"round\" />\n\t\t</svg>\n\t);\n}\n\nconst c_statusLabelKeys: Record<string, string> = {\n\t'status > live': 'liveStatusText',\n\t'status > prepub': 'prepubStatusText',\n\t'status > prepub > gatheringinterest': 'gatheringInterestStatusText',\n\t'status > prepub > undercontract': 'underContractStatusText',\n\t'status > prepub > gatheringinterest > almostfunded': 'almostFundedStatusText',\n\t'status > prepub > undercontract > shippingsoon': 'shippingSoonStatusText',\n};\n\nfunction ShowMoreToggle({\n\tshowMore,\n\tattribute,\n\tsetShowMore,\n}: {\n\tshowMore: string | undefined;\n\tattribute: string;\n\tsetShowMore: (showMore: string | undefined) => void;\n}) {\n\tconst resources = useSearchResources();\n\tconst isShowingMore = showMore === attribute;\n\n\treturn (\n\t\t<LinkButton as=\"button\" onClick={() => setShowMore(isShowingMore ? undefined : attribute)} scale=\"sm\">\n\t\t\t{isShowingMore ? resources['showLess'] : resources['showMore']}\n\t\t</LinkButton>\n\t);\n}\n\nfunction countDepth(value: string) {\n\tlet index = value.indexOf('>');\n\tlet depth = 0;\n\n\twhile (index !== -1) {\n\t\tindex = value.indexOf('>', index + 1);\n\t\tdepth += 1;\n\t}\n\n\treturn depth;\n}\n\nexport interface RefinementItem {\n\trefinement: RefinementListRenderState;\n\titem: RefinementListItem;\n}\n\nfunction hasChildren(items: RefinementItem[], { item: parent }: RefinementItem) {\n\treturn items.some(({ item }) => parent !== item && item.value.startsWith(parent.value));\n}\n\nfunction getChildren(items: RefinementItem[], parent: RefinementItem) {\n\tconst depth = countDepth(parent.item.value);\n\n\treturn items.filter(({ item }) => countDepth(item.value) === depth + 1 && item.value.startsWith(parent.item.value));\n}\n\nexport function getAccordions(category: string, items: RefinementItem[]) {\n\tconst root = {\n\t\tkey: category,\n\t\tlabel: category,\n\t\tlabelKind: 'search' as const,\n\t\titems: items.filter(({ item }) => countDepth(item.value) === 0),\n\t};\n\n\tconst subCategories = items\n\t\t.filter(({ item }) => item.isRefined)\n\t\t.filter(parent => hasChildren(items, parent))\n\t\t.map(c => ({\n\t\t\tkey: c.item.value,\n\t\t\tlabel: c.item.label.replace(/^((.*) > )*/, ''),\n\t\t\tlabelKind: 'facetConstraints' as const,\n\t\t\titems: getChildren(items, c),\n\t\t}));\n\n\treturn [root, ...subCategories];\n}\n\nfunction useRefinementLists(category: string, levels?: number) {\n\t// not neccessary, but let's avoid shooting ourselves in the foot, shall we?\n\tconst levelsRef = useRef(levels);\n\tconst items: RefinementItem[] = [];\n\n\tif (levelsRef.current !== undefined) {\n\t\tfor (let level = 0; level <= levelsRef.current; level += 1) {\n\t\t\tconst attribute = `${category}.lvl${level}`;\n\t\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\t\tconst refinement = useRefinementList({ attribute, limit: 1000 }, { skipSuspense: level < levelsRef.current - 1 });\n\n\t\t\titems.push(...refinement.items.map(item => ({ item, refinement })));\n\t\t}\n\t} else {\n\t\t// eslint-disable-next-line react-hooks/rules-of-hooks\n\t\tconst refinement = useRefinementList({ attribute: category, limit: 1000 });\n\n\t\titems.push(...refinement.items.map(item => ({ item, refinement })));\n\t}\n\n\treturn items;\n}\n\nfunction Category({\n\tcategory,\n\tsetExpandedFacets,\n\tsetShowMore,\n\tshowMore,\n\tmaxLevel,\n}: {\n\tcategory: string;\n\tsetExpandedFacets: (setState: (expandedFacets: string[]) => string[]) => void;\n\tsetShowMore: (showMore: string | undefined) => void;\n\tshowMore: string | undefined;\n\tmaxLevel?: number;\n}) {\n\tconst resources = useSearchResources();\n\tconst facetConstraints = useFacetConstraints();\n\tconst { indexName } = useAlgoliaSearch();\n\tconst items = useRefinementLists(category, maxLevel);\n\n\tif (!items?.length) {\n\t\treturn null;\n\t}\n\n\tconst accordions = getAccordions(category, items);\n\n\treturn accordions.map(accordion => (\n\t\t<AccordionItem key={accordion.key} value={accordion.key}>\n\t\t\t<AccordionTrigger className=\"border-t border-primary-100 p-4 lg:border-t-0 [&>svg]:text-primary\">\n\t\t\t\t<Typography className=\"text-primary-400\" variant=\"bodyRegular\" tag=\"div\">\n\t\t\t\t\t{accordion.labelKind === 'search'\n\t\t\t\t\t\t? (resources[accordion.label] ?? accordion.label)\n\t\t\t\t\t\t: getFacetDisplayLabel(accordion.label, facetConstraints, category)}\n\t\t\t\t</Typography>\n\t\t\t</AccordionTrigger>\n\t\t\t<AccordionContent className=\"m-0 bg-grey-200 p-4\">\n\t\t\t\t<div className=\"flex flex-col gap-y-4\">\n\t\t\t\t\t{(showMore === accordion.key ? accordion.items : accordion.items.slice(0, 7)).map(({ item, refinement }) => (\n\t\t\t\t\t\t<div key={item.value}>\n\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t'text-black-200 hover:text-secondary-200': !item.isRefined,\n\t\t\t\t\t\t\t\t\t\t'text-primary': item.isRefined,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t'bodySm w-full text-left capitalize'\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\trefinement.refine(item.value);\n\n\t\t\t\t\t\t\t\t\tinsightsClient('clickedFilters', {\n\t\t\t\t\t\t\t\t\t\tindex: indexName,\n\t\t\t\t\t\t\t\t\t\teventName: 'Clicked filter',\n\t\t\t\t\t\t\t\t\t\tfilters: [`${category}:${item.value}`],\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\tif (!item.isRefined) {\n\t\t\t\t\t\t\t\t\t\tsetExpandedFacets(old => [...old, item.value]);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\titems\n\t\t\t\t\t\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t\t\t\t\t\t({ item: child }) =>\n\t\t\t\t\t\t\t\t\t\t\t\t\tchild.isRefined && child.value !== item.value && child.value.startsWith(item.value)\n\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t.forEach(({ item: child, refinement: childRefinement }) => {\n\t\t\t\t\t\t\t\t\t\t\t\tchildRefinement.refine(child.value);\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\tsetExpandedFacets(old => old.filter(v => !v.startsWith(item.value)));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Check checked={item.isRefined} className=\"mr-3\" />\n\t\t\t\t\t\t\t\t<span className=\"normal-case\">\n\t\t\t\t\t\t\t\t\t{`${getFacetDisplayLabel(item.label, facetConstraints, category)} `}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t<span className=\"text-black-100\">\n\t\t\t\t\t\t\t\t\t{'('}\n\t\t\t\t\t\t\t\t\t{item.count}\n\t\t\t\t\t\t\t\t\t{')'}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))}\n\t\t\t\t\t{accordion.items.length > 7 && (\n\t\t\t\t\t\t<ShowMoreToggle attribute={accordion.key} setShowMore={setShowMore} showMore={showMore} />\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</AccordionContent>\n\t\t</AccordionItem>\n\t));\n}\n\nfunction AuthorFacetItem({\n\tid,\n\tdisplayName,\n\tcount,\n\tisRefined,\n\tonRefine,\n}: {\n\tid: string;\n\tdisplayName: string;\n\tcount: number;\n\tisRefined: boolean;\n\tonRefine: (id: string) => void;\n}) {\n\treturn (\n\t\t<div>\n\t\t\t<button\n\t\t\t\tclassName={cn(\n\t\t\t\t\t{\n\t\t\t\t\t\t'text-black-200 hover:text-secondary-200': !isRefined,\n\t\t\t\t\t\t'text-primary': isRefined,\n\t\t\t\t\t},\n\t\t\t\t\t'bodySm w-full text-left capitalize'\n\t\t\t\t)}\n\t\t\t\tonClick={() => onRefine(id)}\n\t\t\t>\n\t\t\t\t{displayName}{' '}\n\t\t\t\t<span className=\"text-black-100\">\n\t\t\t\t\t{'('}\n\t\t\t\t\t{count}\n\t\t\t\t\t{')'}\n\t\t\t\t</span>\n\t\t\t</button>\n\t\t</div>\n\t);\n}\n\nfunction PublisherFacetItem({\n\tid,\n\tdisplayName,\n\tcount,\n\tisRefined,\n\tonRefine,\n}: {\n\tid: string;\n\tdisplayName: string;\n\tcount: number;\n\tisRefined: boolean;\n\tonRefine: (id: string) => void;\n}) {\n\treturn (\n\t\t<div>\n\t\t\t<button\n\t\t\t\tclassName={cn(\n\t\t\t\t\t{\n\t\t\t\t\t\t'text-black-200 hover:text-secondary-200': !isRefined,\n\t\t\t\t\t\t'text-primary': isRefined,\n\t\t\t\t\t},\n\t\t\t\t\t'bodySm w-full text-left capitalize'\n\t\t\t\t)}\n\t\t\t\tonClick={() => onRefine(id)}\n\t\t\t>\n\t\t\t\t{displayName}{' '}\n\t\t\t\t<span className=\"text-black-100\">\n\t\t\t\t\t{'('}\n\t\t\t\t\t{count}\n\t\t\t\t\t{')'}\n\t\t\t\t</span>\n\t\t\t</button>\n\t\t</div>\n\t);\n}\n\nfunction AuthorsOrPublishers({\n\tattribute,\n\tnameAttribute,\n\tsetShowMore,\n\tshowMore,\n}: {\n\tattribute: 'authorIds' | 'publisherIds';\n\tnameAttribute: 'authorFacets' | 'publisherFacets';\n\tshowMore: string | undefined;\n\tsetShowMore: (showMore: string | undefined) => void;\n}) {\n\tconst resources = useSearchResources();\n\tconst { indexName } = useAlgoliaSearch();\n\n\tconst { isShowingMore, items, canToggleShowMore, toggleShowMore } = useRefinementList({\n\t\tattribute: nameAttribute,\n\t\tlimit: 7,\n\t\tshowMore: true,\n\t});\n\tconst { items: idItems, refine } = useRefinementList({\n\t\tattribute,\n\t});\n\n\tuseEffect(() => {\n\t\tif ((showMore === attribute) !== isShowingMore) {\n\t\t\ttoggleShowMore();\n\t\t}\n\t}, [attribute, isShowingMore, showMore, toggleShowMore]);\n\n\tconst FacetItem = attribute === 'authorIds' ? AuthorFacetItem : PublisherFacetItem;\n\n\tconst facetItems = items.map(item => {\n\t\tconst { id, displayName } = parseFacetValue(item.value);\n\t\treturn {\n\t\t\tid,\n\t\t\tdisplayName,\n\t\t\tcount: item.count,\n\t\t\tisRefined: idItems.some(idItem => idItem.value === id && idItem.isRefined),\n\t\t};\n\t});\n\n\tfacetItems.sort((a, b) => {\n\t\tif (a.isRefined && !b.isRefined) {\n\t\t\treturn -1;\n\t\t}\n\n\t\tif (!a.isRefined && b.isRefined) {\n\t\t\treturn 1;\n\t\t}\n\n\t\treturn b.count - a.count;\n\t});\n\n\treturn (\n\t\t<AccordionItem value={attribute}>\n\t\t\t<AccordionTrigger className=\"border-t border-primary-100 p-4 lg:border-t-0 [&>svg]:text-primary\">\n\t\t\t\t<Typography className=\"text-primary-400\" variant=\"bodyRegular\" tag=\"div\">\n\t\t\t\t\t{resources[attribute] ?? attribute}\n\t\t\t\t</Typography>\n\t\t\t</AccordionTrigger>\n\t\t\t<AccordionContent className=\"m-0 bg-grey-200 p-4\">\n\t\t\t\t<div className=\"flex flex-col gap-y-4\">\n\t\t\t\t\t{facetItems.map(i => {\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<FacetItem\n\t\t\t\t\t\t\t\tkey={i.id}\n\t\t\t\t\t\t\t\t{...i}\n\t\t\t\t\t\t\t\tonRefine={id => {\n\t\t\t\t\t\t\t\t\trefine(id);\n\t\t\t\t\t\t\t\t\tinsightsClient('clickedFilters', {\n\t\t\t\t\t\t\t\t\t\tindex: indexName,\n\t\t\t\t\t\t\t\t\t\teventName: 'Clicked filter',\n\t\t\t\t\t\t\t\t\t\tfilters: [`${attribute}:${id}`],\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t\t{canToggleShowMore && <ShowMoreToggle attribute={attribute} setShowMore={setShowMore} showMore={showMore} />}\n\t\t\t\t</div>\n\t\t\t</AccordionContent>\n\t\t</AccordionItem>\n\t);\n}\n\nfunction Statuses({\n\tsetExpandedFacets,\n}: {\n\tsetExpandedFacets: (setState: (expandedFacets: string[]) => string[]) => void;\n}) {\n\tconst resources = useSearchResources();\n\tconst { indexName } = useAlgoliaSearch();\n\tconst level1 = useRefinementList({ attribute: 'categories.lvl1', limit: 100 }, { skipSuspense: true });\n\tconst level2 = useRefinementList({ attribute: 'categories.lvl2', limit: 1000 }, { skipSuspense: true });\n\tconst level3 = useRefinementList({ attribute: 'categories.lvl3', limit: 1000 }, { skipSuspense: true });\n\tconst level4 = useRefinementList({ attribute: 'categories.lvl4', limit: 1000 }, { skipSuspense: true });\n\n\tconst sections: {\n\t\tvalue: string;\n\t\trefinement: RefinementListRenderState;\n\t\titems: RefinementListItem[];\n\t}[] = [\n\t\t{\n\t\t\tvalue: 'status',\n\t\t\trefinement: level1,\n\t\t\titems: level1.items.filter(i => i.value.startsWith('status')),\n\t\t},\n\t\t...level1.items\n\t\t\t.filter(i => i.isRefined && i.value.startsWith('status'))\n\t\t\t.map(status => ({\n\t\t\t\tvalue: status.value,\n\t\t\t\trefinement: level2,\n\t\t\t\titems: level2.items.filter(i => i.value.startsWith(status.value)),\n\t\t\t})),\n\t\t...level2.items\n\t\t\t.filter(i => i.isRefined && i.value.startsWith('status'))\n\t\t\t.map(status => ({\n\t\t\t\tvalue: status.value,\n\t\t\t\trefinement: level3,\n\t\t\t\titems: level3.items.filter(i => i.value.startsWith(status.value)),\n\t\t\t})),\n\t\t...level3.items\n\t\t\t.filter(i => i.isRefined && i.value.startsWith('status'))\n\t\t\t.map(status => ({\n\t\t\t\tvalue: status.value,\n\t\t\t\trefinement: level4,\n\t\t\t\titems: level4.items.filter(i => i.value.startsWith(status.value)),\n\t\t\t})),\n\t];\n\n\treturn (\n\t\t<>\n\t\t\t{sections.map(({ value, refinement, items }) =>\n\t\t\t\titems.length ? (\n\t\t\t\t\t<AccordionItem key={value} value={value}>\n\t\t\t\t\t\t<AccordionTrigger className=\"border-t border-primary-100 p-4 lg:border-t-0 [&>svg]:text-primary\">\n\t\t\t\t\t\t\t<Typography className=\"text-primary-400\" variant=\"bodyRegular\" tag=\"div\">\n\t\t\t\t\t\t\t\t{resources[c_statusLabelKeys[value] ?? value] ?? value}\n\t\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t</AccordionTrigger>\n\t\t\t\t\t\t<AccordionContent className=\"m-0 bg-grey-200 p-4\">\n\t\t\t\t\t\t\t<div className=\"flex flex-col gap-y-4\">\n\t\t\t\t\t\t\t\t{items.map(item => (\n\t\t\t\t\t\t\t\t\t<div key={item.value}>\n\t\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t'text-black-200 hover:text-secondary-200': !item.isRefined,\n\t\t\t\t\t\t\t\t\t\t\t\t\t'text-primary': item.isRefined,\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t'bodySm w-full text-left capitalize'\n\t\t\t\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\trefinement.refine(item.value);\n\n\t\t\t\t\t\t\t\t\t\t\t\tinsightsClient('clickedFilters', {\n\t\t\t\t\t\t\t\t\t\t\t\t\tindex: indexName,\n\t\t\t\t\t\t\t\t\t\t\t\t\teventName: 'Clicked filter',\n\t\t\t\t\t\t\t\t\t\t\t\t\tfilters: [`categories:${item.value}`],\n\t\t\t\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (!item.isRefined) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tsetExpandedFacets(old => [...old, item.value]);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{resources[c_statusLabelKeys[item.value] ?? item.value] ?? item.value}{' '}\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"text-black-100\">\n\t\t\t\t\t\t\t\t\t\t\t\t{'('}\n\t\t\t\t\t\t\t\t\t\t\t\t{item.count}\n\t\t\t\t\t\t\t\t\t\t\t\t{')'}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</AccordionContent>\n\t\t\t\t\t</AccordionItem>\n\t\t\t\t) : null\n\t\t\t)}\n\t\t</>\n\t);\n}\n\nexport function UserSearchFilterAccordionItem({ filter }: { filter: UserSearchFilter }) {\n\tconst { selectedFilterOptions, setSelectedFilterOption } = useUserSearchFilterContext();\n\tconst selectedFilterOption = selectedFilterOptions[filter.token];\n\tconst title = filter.title;\n\tconst options = (Array.isArray(filter.options) ? filter.options : []).filter(\n\t\t(option: { displayName: string }) => option && option.displayName !== ''\n\t);\n\n\tif (!title || options.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<AccordionItem value={`user-filter-${title}`}>\n\t\t\t<AccordionTrigger className=\"border-t border-primary-100 p-4 lg:border-t-0 [&>svg]:text-primary\">\n\t\t\t\t<Typography className=\"text-primary-400\" variant=\"bodyRegular\" tag=\"div\">\n\t\t\t\t\t{title}\n\t\t\t\t</Typography>\n\t\t\t</AccordionTrigger>\n\t\t\t<AccordionContent className=\"m-0 bg-grey-200 p-4\">\n\t\t\t\t<div className=\"flex flex-col gap-y-4\">\n\t\t\t\t\t{options.map((option: UserSearchFilterOption) => {\n\t\t\t\t\t\tconst label = option.displayName;\n\t\t\t\t\t\tconst isSelected = selectedFilterOption === option.token;\n\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<Typography\n\t\t\t\t\t\t\t\tvariant=\"bodySmall\"\n\t\t\t\t\t\t\t\tclassName=\"flex cursor-pointer items-center text-black-200\"\n\t\t\t\t\t\t\t\tkey={label}\n\t\t\t\t\t\t\t\ttag=\"label\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tchecked={isSelected}\n\t\t\t\t\t\t\t\t\tclassName=\"mr-3 h-[13px] w-[13px] border-grey-100 text-primary\"\n\t\t\t\t\t\t\t\t\tonChange={() => setSelectedFilterOption(filter.token, option.token)}\n\t\t\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\t\t\tvalue={option.token}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<span className={cn(isSelected ? 'text-primary' : 'text-black-200 hover:text-secondary-200')}>\n\t\t\t\t\t\t\t\t\t{label}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t</AccordionContent>\n\t\t</AccordionItem>\n\t);\n}\n\nexport function Categories() {\n\tconst [expandedFacets, setExpandedFacets] = useState<string[]>([]);\n\tconst [showMore, setShowMore] = useState<string>();\n\tconst { userSearchFilters } = useUserSearchFilterContext();\n\n\treturn (\n\t\t<Accordion onValueChange={setExpandedFacets} type=\"multiple\" value={expandedFacets}>\n\t\t\t{userSearchFilters?.map((filter, index) => {\n\t\t\t\tconst key = `${filter.title}-${index}`;\n\n\t\t\t\treturn <UserSearchFilterAccordionItem filter={filter} key={key} />;\n\t\t\t})}\n\t\t\t<Category\n\t\t\t\tcategory=\"topic\"\n\t\t\t\tmaxLevel={3}\n\t\t\t\tsetExpandedFacets={setExpandedFacets}\n\t\t\t\tsetShowMore={setShowMore}\n\t\t\t\tshowMore={showMore}\n\t\t\t/>\n\t\t\t<Category\n\t\t\t\tcategory=\"resourceType\"\n\t\t\t\tmaxLevel={1}\n\t\t\t\tsetExpandedFacets={setExpandedFacets}\n\t\t\t\tsetShowMore={setShowMore}\n\t\t\t\tshowMore={showMore}\n\t\t\t/>\n\t\t\t<AuthorsOrPublishers\n\t\t\t\tattribute=\"authorIds\"\n\t\t\t\tnameAttribute=\"authorFacets\"\n\t\t\t\tsetShowMore={setShowMore}\n\t\t\t\tshowMore={showMore}\n\t\t\t/>\n\t\t\t<Statuses setExpandedFacets={setExpandedFacets} />\n\t\t\t<Category\n\t\t\t\tcategory=\"specials\"\n\t\t\t\tsetExpandedFacets={setExpandedFacets}\n\t\t\t\tsetShowMore={setShowMore}\n\t\t\t\tshowMore={showMore}\n\t\t\t/>\n\t\t\t<Category\n\t\t\t\tcategory=\"language\"\n\t\t\t\tsetExpandedFacets={setExpandedFacets}\n\t\t\t\tsetShowMore={setShowMore}\n\t\t\t\tshowMore={showMore}\n\t\t\t/>\n\t\t\t<Category\n\t\t\t\tcategory=\"seriesSets\"\n\t\t\t\tmaxLevel={1}\n\t\t\t\tsetExpandedFacets={setExpandedFacets}\n\t\t\t\tsetShowMore={setShowMore}\n\t\t\t\tshowMore={showMore}\n\t\t\t/>\n\t\t\t<AuthorsOrPublishers\n\t\t\t\tattribute=\"publisherIds\"\n\t\t\t\tnameAttribute=\"publisherFacets\"\n\t\t\t\tsetShowMore={setShowMore}\n\t\t\t\tshowMore={showMore}\n\t\t\t/>\n\t\t\t<Category\n\t\t\t\tcategory=\"bibleAndApocrypha\"\n\t\t\t\tmaxLevel={3}\n\t\t\t\tsetExpandedFacets={setExpandedFacets}\n\t\t\t\tsetShowMore={setShowMore}\n\t\t\t\tshowMore={showMore}\n\t\t\t/>\n\t\t\t<Category\n\t\t\t\tcategory=\"containment\"\n\t\t\t\tmaxLevel={1}\n\t\t\t\tsetExpandedFacets={setExpandedFacets}\n\t\t\t\tsetShowMore={setShowMore}\n\t\t\t\tshowMore={showMore}\n\t\t\t/>\n\t\t\t<Category category=\"format\" setExpandedFacets={setExpandedFacets} setShowMore={setShowMore} showMore={showMore} />\n\t\t\t<Category\n\t\t\t\tcategory=\"genre\"\n\t\t\t\tmaxLevel={2}\n\t\t\t\tsetExpandedFacets={setExpandedFacets}\n\t\t\t\tsetShowMore={setShowMore}\n\t\t\t\tshowMore={showMore}\n\t\t\t/>\n\t\t\t<Category\n\t\t\t\tcategory=\"licensingMethod\"\n\t\t\t\tsetExpandedFacets={setExpandedFacets}\n\t\t\t\tsetShowMore={setShowMore}\n\t\t\t\tshowMore={showMore}\n\t\t\t/>\n\t\t\t<Category\n\t\t\t\tcategory=\"religiousGroup\"\n\t\t\t\tmaxLevel={0}\n\t\t\t\tsetExpandedFacets={setExpandedFacets}\n\t\t\t\tsetShowMore={setShowMore}\n\t\t\t\tshowMore={showMore}\n\t\t\t/>\n\t\t</Accordion>\n\t);\n}\n","import React, { useEffect, useRef } from 'react';\nimport {\n\tCurrentRefinementsConnectorParamsItem,\n\tCurrentRefinementsConnectorParamsRefinement,\n} from 'instantsearch.js/es/connectors/current-refinements/connectCurrentRefinements';\nimport { X } from 'lucide-react';\nimport { useCurrentRefinements, useRefinementList, useSearchBox } from 'react-instantsearch';\n\nimport { useLocation } from '../../location';\nimport { useAuthor } from '../../hooks/use-author';\nimport { usePublisher } from '../../hooks/use-publisher';\nimport { getFacetDisplayLabel, useFacetConstraints } from './facet-label';\nimport { parseFacetValue } from './util';\n\n// ---------------------------------------------------------------------------\n// CurrentRefinements — chips for active facet refinements\n// ---------------------------------------------------------------------------\n\nfunction isStatusRefinement(attribute: string, value: string): boolean {\n\treturn /^categories\\.lvl\\d+$/.test(attribute) && value.split('>')[0].trim() === 'status';\n}\n\nfunction isGenericLocalizableFacet(attribute: string, value: string): boolean {\n\treturn attribute !== 'authorIds' && attribute !== 'publisherIds' && !isStatusRefinement(attribute, value);\n}\n\nfunction RefinementLabel({ attribute, value, facetLabel }: { attribute: string; value: string; facetLabel: string }) {\n\tconst stringValue = typeof value === 'string' ? value : String(value ?? '');\n\n\tif (attribute === 'authorIds') {\n\t\treturn <AuthorLabel value={stringValue} />;\n\t}\n\n\tif (attribute === 'publisherIds') {\n\t\treturn <PublisherLabel value={stringValue} />;\n\t}\n\n\tif (!isGenericLocalizableFacet(attribute, stringValue)) {\n\t\treturn <span>{stringValue.replace(/^((.*) > )*/, '')}</span>;\n\t}\n\n\treturn <span className=\"normal-case\">{facetLabel}</span>;\n}\n\nfunction AuthorLabel({ value }: { value: string }) {\n\tconst { items } = useRefinementList({ attribute: 'authorFacets' });\n\n\tif (!items.length) {\n\t\treturn <span>{'…'}</span>;\n\t}\n\n\tconst item = items.find(i => i.value.startsWith(`${value}:`));\n\n\tif (item) {\n\t\tconst { displayName } = parseFacetValue(item.label);\n\t\treturn <span>{displayName}</span>;\n\t}\n\n\treturn <AuthorApiLabel value={value} />;\n}\n\nfunction AuthorApiLabel({ value }: { value: string }) {\n\tconst { data, isLoading } = useAuthor(value);\n\n\tif (isLoading) {\n\t\treturn <span>{'…'}</span>;\n\t}\n\n\tif (!data) {\n\t\treturn null;\n\t}\n\n\treturn <span>{data.displayName}</span>;\n}\n\nfunction PublisherLabel({ value }: { value: string }) {\n\tconst { items } = useRefinementList({ attribute: 'publisherFacets' });\n\n\tif (!items.length) {\n\t\treturn <span>{'…'}</span>;\n\t}\n\n\tconst item = items.find(i => i.value.startsWith(`${value}:`));\n\n\tif (item) {\n\t\tconst { displayName } = parseFacetValue(item.label);\n\t\treturn <span>{displayName}</span>;\n\t}\n\n\treturn <PublisherApiLabel value={value} />;\n}\n\nfunction PublisherApiLabel({ value }: { value: string }) {\n\tconst { data, isLoading } = usePublisher(value);\n\n\tif (isLoading) {\n\t\treturn <span>{'…'}</span>;\n\t}\n\n\tif (!data) {\n\t\treturn null;\n\t}\n\n\treturn <span>{data.displayName}</span>;\n}\n\nexport function CurrentRefinements() {\n\tconst currentRefinements = useCurrentRefinements();\n\tconst itemsByAttribute: Record<string, CurrentRefinementsConnectorParamsItem> = {};\n\tconst refinementList: CurrentRefinementsConnectorParamsRefinement[] = [];\n\n\tfor (const item of currentRefinements?.items ?? []) {\n\t\titemsByAttribute[item.attribute] = item;\n\n\t\tfor (const refinement of item.refinements ?? []) {\n\t\t\trefinementList.push(refinement);\n\t\t}\n\t}\n\n\treturn refinementList.map(item => {\n\t\tconst itemValue = item.value;\n\t\tconst itemAndChildren =\n\t\t\ttypeof itemValue === 'string'\n\t\t\t\t? refinementList.filter(r => typeof r.value === 'string' && r.value.startsWith(itemValue))\n\t\t\t\t: [item];\n\n\t\treturn (\n\t\t\t<RefinementChip\n\t\t\t\tattribute={item.attribute}\n\t\t\t\titemAndChildren={itemAndChildren}\n\t\t\t\titemsByAttribute={itemsByAttribute}\n\t\t\t\tkey={`${item.attribute}:${String(itemValue)}`}\n\t\t\t\tlabel={item.label}\n\t\t\t\tvalue={String(itemValue)}\n\t\t\t/>\n\t\t);\n\t});\n}\n\nfunction RefinementChip({\n\tattribute,\n\tvalue,\n\tlabel,\n\titemAndChildren,\n\titemsByAttribute,\n}: {\n\tattribute: string;\n\tvalue: string;\n\tlabel: string;\n\titemAndChildren: CurrentRefinementsConnectorParamsRefinement[];\n\titemsByAttribute: Record<string, CurrentRefinementsConnectorParamsItem>;\n}) {\n\tconst facetConstraints = useFacetConstraints();\n\tconst facetLabel = isGenericLocalizableFacet(attribute, value)\n\t\t? getFacetDisplayLabel(value, facetConstraints, attribute)\n\t\t: label;\n\n\treturn (\n\t\t<button\n\t\t\taria-label={`Remove ${facetLabel} from filters`}\n\t\t\tclassName=\"flex items-center gap-x-1 bg-grey-200 py-[6px] pl-3 pr-2 text-xs capitalize text-black-100\"\n\t\t\tonClick={() => itemAndChildren.forEach(i => itemsByAttribute[attribute]?.refine(i))}\n\t\t>\n\t\t\t<RefinementLabel attribute={attribute} facetLabel={facetLabel} value={value} />\n\t\t\t<X aria-hidden=\"true\" height={14} width={14} />\n\t\t</button>\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// CurrentQueryRefinement — chip for the active search query\n// ---------------------------------------------------------------------------\n\nexport default function CurrentQueryRefinement() {\n\tconst { searchParams, isQueryStringReady } = useLocation();\n\tconst urlQuery = searchParams.get('query')?.trim() ?? '';\n\n\tconst { query, refine, clear } = useSearchBox();\n\tconst queryRef = useRef(query);\n\tqueryRef.current = query;\n\n\tuseEffect(() => {\n\t\tif (isQueryStringReady && urlQuery && queryRef.current !== urlQuery) {\n\t\t\trefine(urlQuery);\n\t\t}\n\t}, [urlQuery, refine, isQueryStringReady]);\n\n\tconst removeQuery = () => {\n\t\tclear();\n\t};\n\n\treturn query ? (\n\t\t<button\n\t\t\taria-label=\"remove search term from filters\"\n\t\t\tclassName=\"flex items-center gap-x-1 bg-grey-200 py-[6px] pl-3 pr-2 text-xs capitalize text-black-100\"\n\t\t\tonClick={removeQuery}\n\t\t>\n\t\t\t<span>\n\t\t\t\t{'\"'}\n\t\t\t\t{query}\n\t\t\t\t{'\"'}\n\t\t\t</span>\n\t\t\t<X aria-hidden=\"true\" height={14} width={14} />\n\t\t</button>\n\t) : null;\n}\n","import React from 'react';\nimport { useRefinementList } from 'react-instantsearch';\n\nimport type { FacetConfiguration } from './routing';\n\n// Keeps a real refinementList widget mounted for each hidden facet attribute (and, for hierarchical facets,\n// each of its levels) so Algolia treats it as refinable, without rendering any UI. Filtering itself is driven\n// entirely by the URL via routing.ts.\n// skipSuspense avoids blocking rendering on data that is never displayed.\nfunction HiddenRefinementList({ attribute }: { attribute: string }) {\n\tuseRefinementList({ attribute }, { skipSuspense: true });\n\n\treturn null;\n}\n\nfunction getHiddenAlgoliaAttributes(config: FacetConfiguration): string[] {\n\tif (config.type === 'simple') {\n\t\treturn [config.algoliaAttribute];\n\t}\n\n\tconst attributes: string[] = [];\n\n\tfor (let level = config.minLevel; level <= config.maxLevel; level += 1) {\n\t\tattributes.push(`${config.algoliaAttributeBase}.lvl${level}`);\n\t}\n\n\treturn attributes;\n}\n\nexport default function HiddenFacetRefinements({ facetConfigurations }: { facetConfigurations: FacetConfiguration[] }) {\n\tconst attributes = facetConfigurations.filter(config => config.isHidden).flatMap(getHiddenAlgoliaAttributes);\n\n\treturn (\n\t\t<>\n\t\t\t{attributes.map(attribute => (\n\t\t\t\t<HiddenRefinementList attribute={attribute} key={attribute} />\n\t\t\t))}\n\t\t</>\n\t);\n}\n","import React, { ReactNode } from 'react';\nimport { cn } from '../../util/cn';\n\nfunction SkeletonRoot({\n\tclassName,\n\tchildren,\n\tpending = false,\n\thideOverflow = false,\n}: {\n\tclassName?: string;\n\tchildren?: React.ReactNode;\n\tpending?: boolean;\n\thideOverflow?: boolean;\n}) {\n\treturn (\n\t\t<div\n\t\t\tclassName={cn('@container', hideOverflow && 'overflow-hidden', className)}\n\t\t\tdata-pending={pending ? '' : undefined}\n\t\t\trole={pending ? 'status' : undefined}\n\t\t>\n\t\t\t{children}\n\t\t\t{pending && <span className=\"sr-only\">{'Loading...'}</span>}\n\t\t</div>\n\t);\n}\n\nfunction SkeletonBox({ className }: { className?: string }) {\n\treturn <div className={cn('rounded-lg bg-gray-300', className)} />;\n}\n\nfunction SkeletonText({ characterCount = 10, className }: { characterCount?: number | 'full'; className?: string }) {\n\treturn (\n\t\t<div className={cn('flex h-[1lh] items-center', className)}>\n\t\t\t<div\n\t\t\t\tclassName={cn(`h-[1ex] max-w-full rounded-[inherit] bg-gray-300`)}\n\t\t\t\tstyle={{ width: characterCount === 'full' ? '100%' : `${characterCount}ch` }}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\nfunction SkeletonIcon({ className, icon }: { className?: string; icon: ReactNode }) {\n\treturn <div className={cn('text-gray-300 opacity-25', className)}>{icon}</div>;\n}\n\nexport { SkeletonIcon as Icon, SkeletonRoot as Root, SkeletonBox as Box, SkeletonText as Text };\n","import React from 'react';\n\nimport { CommandSentence } from '@faithlife/command-sentence-control';\nimport { useLocalization } from '../../../localization';\nimport { useBrandName } from '../../../util/brand-name-context';\n\nexport default function EnhancedForLogosLabel() {\n\tconst resources = useLocalization('CommerceWeb.Resources.Search.DisplayTemplates.ProductSearchResultViewModel');\n\tconst logosOrVerbum = useBrandName();\n\tconst isVerbum = logosOrVerbum?.toLowerCase() === 'verbum';\n\treturn (\n\t\t<CommandSentence className=\"text-xs text-primary\" template={resources.EnhancedForLogos}>\n\t\t\t<CommandSentence.Field name=\"ICON\">\n\t\t\t\t<img\n\t\t\t\t\tclassName={\n\t\t\t\t\t\tisVerbum\n\t\t\t\t\t\t\t? 'inline-block w-[17px] h-[12px] [vertical-align:-1.5px]'\n\t\t\t\t\t\t\t: 'inline-block w-[14px] h-[14px] [vertical-align:-2px] mx-px'\n\t\t\t\t\t}\n\t\t\t\t\talt={logosOrVerbum}\n\t\t\t\t\tsrc={\n\t\t\t\t\t\tisVerbum\n\t\t\t\t\t\t\t? 'https://files.logoscdn.com/v1/files/70496318/assets/14995970/content.svg?signature=SsnOeyt3lPzdfqreDLuA7km2gRs'\n\t\t\t\t\t\t\t: 'https://files.logoscdn.com/v1/files/71036773/assets/14991834/content.svg?signature=NlgSyNjXKmP7caOrWgZiZv5hSEE'\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t</CommandSentence.Field>\n\t\t</CommandSentence>\n\t);\n}\n","import React from 'react';\nimport { CommandSentence } from '@faithlife/command-sentence-control';\n\nimport EnhancedForLogosLabel from '../enhanced-for-logos-label';\nimport Tooltip from '../tooltip';\nimport { InfoIconSvgUrl } from '../svgs';\n\nimport { useLocalization } from '../../../localization';\nimport { useBrandName } from '../../../util/brand-name-context';\n\nexport interface EnhancedForLogosWithTooltipProps {\n\tclassName?: string;\n}\n\nconst EnhancedForLogosWithTooltip = ({ className }: EnhancedForLogosWithTooltipProps) => {\n\tconst resources = useLocalization('CommerceWeb.Resources.Search.DisplayTemplates.ProductSearchResultViewModel');\n\n\tconst logosOrVerbum = useBrandName();\n\n\treturn (\n\t\t<Tooltip placement=\"bottom\" className={className} link={<EnhancedForLogosLabel />}>\n\t\t\t<div className={'w-[250px] text-start flex items-start gap-sp8'}>\n\t\t\t\t<div>\n\t\t\t\t\t<img className=\"max-w-none w-[20px] h-[20px]\" src={InfoIconSvgUrl} alt=\"\" />\n\t\t\t\t</div>\n\t\t\t\t<div>\n\t\t\t\t\t<CommandSentence className=\"text-xs\" template={resources.EnhancedForLogosTooltipContent}>\n\t\t\t\t\t\t<CommandSentence.Field name=\"LOGOSORVERBUM\">{logosOrVerbum}</CommandSentence.Field>\n\t\t\t\t\t</CommandSentence>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</Tooltip>\n\t);\n};\n\nexport default EnhancedForLogosWithTooltip;\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport insightsClient from 'search-insights';\n\nimport { PrepubProductStatus, useCurrentUser, usePricing } from '../../per-user-data/per-user-data-context';\nimport type { PrepubProductStatusSummary, ProductPrices } from '../../per-user-data/per-user-data-context';\nimport { detectIsAmberOptimizedUrl } from '../../shared/enhanced-image-tag/image';\nimport { useLocale } from '../../../localization/use-localization';\nimport { getSavingsPercent, slugify } from '../util';\nimport { ProductHitResult } from '../types';\nimport { useSearchResources } from '../search-resources';\nimport { useAlgoliaSearch } from '../algolia-search-context';\n\ntype AlgoliaPrepubStatus = Exclude<PrepubProductStatus, PrepubProductStatus.none>;\n\nconst c_gatheringInterestPercent = 75;\n\nconst usdFormat = new Intl.NumberFormat('en-US', {\n\tstyle: 'currency',\n\tcurrency: 'USD',\n\tminimumFractionDigits: 2,\n\tmaximumFractionDigits: 2,\n});\n\nconst placeholderImage = 'https://files.logoscdn.com/v1/assets/15953102/optimized';\n\nfunction getPrepubStatus(status: ProductHitResult['status'], percentCommitted: number): AlgoliaPrepubStatus | null {\n\tconst statusValues = Array.isArray(status) ? status : status ? [status] : [];\n\tconst normalizedStatusValues = statusValues.map(value => value.toLowerCase().replace(/[^a-z0-9]/g, ''));\n\n\tif (normalizedStatusValues.some(value => value.includes('shippingsoon'))) {\n\t\treturn PrepubProductStatus.shippingSoon;\n\t}\n\tif (normalizedStatusValues.some(value => value.includes('almostfunded'))) {\n\t\treturn PrepubProductStatus.almostThere;\n\t}\n\tif (normalizedStatusValues.some(value => value.includes('undercontract'))) {\n\t\treturn PrepubProductStatus.underContract;\n\t}\n\tif (normalizedStatusValues.some(value => value.includes('gatheringinterest'))) {\n\t\treturn percentCommitted >= c_gatheringInterestPercent\n\t\t\t? PrepubProductStatus.almostThere\n\t\t\t: PrepubProductStatus.gatheringInterest;\n\t}\n\n\treturn null;\n}\n\nfunction parsePrepubShipDate(value: ProductHitResult['prepubShipDate']): Date | null {\n\tif (typeof value === 'number') {\n\t\tif (!Number.isFinite(value)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst milliseconds = Math.abs(value) < 1_000_000_000_000 ? value * 1000 : value;\n\t\tconst date = new Date(milliseconds);\n\t\treturn Number.isNaN(date.getTime()) ? null : date;\n\t}\n\n\tif (!value) {\n\t\treturn null;\n\t}\n\n\tconst dateOnlyMatch = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(value);\n\tconst date = dateOnlyMatch\n\t\t? new Date(Number(dateOnlyMatch[1]), Number(dateOnlyMatch[2]) - 1, Number(dateOnlyMatch[3]))\n\t\t: new Date(value);\n\n\tif (\n\t\tNumber.isNaN(date.getTime()) ||\n\t\t(dateOnlyMatch &&\n\t\t\t(date.getFullYear() !== Number(dateOnlyMatch[1]) ||\n\t\t\t\tdate.getMonth() !== Number(dateOnlyMatch[2]) - 1 ||\n\t\t\t\tdate.getDate() !== Number(dateOnlyMatch[3])))\n\t) {\n\t\treturn null;\n\t}\n\n\treturn date;\n}\n\nfunction getShippingDateDescription(shipDate: Date, locale: string, resources: Record<string, string>): string {\n\tconst now = new Date();\n\tconst thirtyDaysFromNow = new Date(now);\n\tthirtyDaysFromNow.setDate(thirtyDaysFromNow.getDate() + 30);\n\tconst ninetyDaysFromNow = new Date(now);\n\tninetyDaysFromNow.setDate(ninetyDaysFromNow.getDate() + 90);\n\n\tlet shipDateString: string;\n\tif (shipDate < thirtyDaysFromNow) {\n\t\tshipDateString = new Intl.DateTimeFormat(locale).format(shipDate);\n\t} else if (shipDate < ninetyDaysFromNow) {\n\t\tshipDateString = new Intl.DateTimeFormat(locale, { month: 'short', year: 'numeric' }).format(shipDate);\n\t} else {\n\t\tshipDateString = `Q${Math.floor(shipDate.getMonth() / 3) + 1}-${shipDate.getFullYear()}`;\n\t}\n\n\treturn resources['shipsFormat'].replace('{0}', shipDateString);\n}\n\nfunction getPrepubProductStatusSummary(\n\thit: ProductHitResult,\n\tlocale: string,\n\tresources: Record<string, string>\n): PrepubProductStatusSummary | null {\n\tconst rawPercentCommitted = hit.percentCommitted;\n\tconst percentCommitted =\n\t\ttypeof rawPercentCommitted === 'number' && Number.isFinite(rawPercentCommitted)\n\t\t\t? Math.min(100, Math.max(0, rawPercentCommitted))\n\t\t\t: 0;\n\tconst status = getPrepubStatus(hit.status, percentCommitted);\n\n\tif (!status) {\n\t\treturn null;\n\t}\n\n\tconst shipDate = parsePrepubShipDate(hit.prepubShipDate);\n\tconst description =\n\t\tstatus === PrepubProductStatus.shippingSoon && shipDate\n\t\t\t? getShippingDateDescription(shipDate, locale, resources)\n\t\t\t: resources[\n\t\t\t\t\tstatus === PrepubProductStatus.gatheringInterest\n\t\t\t\t\t\t? 'gatheringInterestStatusText'\n\t\t\t\t\t\t: status === PrepubProductStatus.almostThere\n\t\t\t\t\t\t\t? 'almostFundedStatusText'\n\t\t\t\t\t\t\t: status === PrepubProductStatus.underContract\n\t\t\t\t\t\t\t\t? 'inProductionStatusText'\n\t\t\t\t\t\t\t\t: 'shippingSoonStatusText'\n\t\t\t\t];\n\n\treturn {\n\t\tstatus,\n\t\tpercentCommitted,\n\t\tshipDate: shipDate?.toISOString(),\n\t\tdescription,\n\t};\n}\n\nfunction getIndexedPrimarySkuId(\n\tprimarySkuStorefronts: ProductHitResult['primarySkuStorefronts'],\n\tstorefrontShortname: string\n): string | undefined {\n\tif (!primarySkuStorefronts) {\n\t\treturn undefined;\n\t}\n\n\tconst normalizedStorefrontShortname = storefrontShortname.toLowerCase();\n\treturn Object.entries(primarySkuStorefronts).find(([, storefronts]) =>\n\t\tstorefronts.some(storefront => storefront.toLowerCase() === normalizedStorefrontShortname)\n\t)?.[0];\n}\n\ninterface UseProductCardProps {\n\thit: ProductHitResult;\n\tqueryId?: string | null;\n\tposition?: number;\n}\n\nexport function useProductCard({ hit, queryId = null, position }: UseProductCardProps) {\n\tconst { data: pricingData } = usePricing(hit.productId);\n\tconst { preferredCurrency, isSignedIn: currentUserIsSignedIn } = useCurrentUser();\n\tconst { indexName, anonymousUserToken, storefrontShortname, isSignedIn: searchIsSignedIn } = useAlgoliaSearch();\n\tconst locale = useLocale();\n\tconst hasGeoRestriction = pricingData?.isGeographicallyRestricted;\n\tconst [isAddingToCart, setIsAddingToCart] = useState(false);\n\tconst resources = useSearchResources();\n\tconst productId = hit?.productId;\n\tconst requestIdRef = useRef<string | null>(null);\n\n\t// Use API pricing when available, fall back to Algolia pricing\n\tconst prices: ProductPrices = pricingData?.primarySku?.prices ?? {\n\t\tsalePrice: {\n\t\t\tamount: hit.salePrice ?? 0,\n\t\t\tdisplayAmount: usdFormat.format(hit.salePrice ?? 0),\n\t\t\tcurrencyCode: 'USD',\n\t\t},\n\t\tanchorPrice:\n\t\t\thit.salePrice !== hit.anchorPrice\n\t\t\t\t? {\n\t\t\t\t\t\tamount: hit.anchorPrice ?? 0,\n\t\t\t\t\t\tdisplayAmount: usdFormat.format(hit.anchorPrice ?? 0),\n\t\t\t\t\t\tdisplayAmountCurrencyCode: 'USD',\n\t\t\t\t\t\tcurrencyCode: 'USD',\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t};\n\n\tconst accessKind = pricingData?.accessKind;\n\tconst isOwned = accessKind === 'Permanent' || accessKind === 'Temporary';\n\tconst hasPreorder = pricingData?.hasPreorder;\n\tconst prepubProductStatusSummary = getPrepubProductStatusSummary(hit, locale, resources);\n\tconst isPrepubProduct = pricingData ? pricingData.isPrepubProduct : Boolean(prepubProductStatusSummary);\n\tconst indexedPrimarySkuId = getIndexedPrimarySkuId(hit.primarySkuStorefronts, storefrontShortname);\n\tconst hasIndexedPrimarySkuData = hit.primarySkuStorefronts !== undefined;\n\tconst canUseIndexedPrimarySku = !(currentUserIsSignedIn || searchIsSignedIn);\n\tconst skuId = pricingData ? pricingData.primarySku?.skuId : canUseIndexedPrimarySku ? indexedPrimarySkuId : undefined;\n\tconst isPurchasable = pricingData\n\t\t? pricingData.primarySku?.isPurchasable\n\t\t: canUseIndexedPrimarySku && hasIndexedPrimarySkuData\n\t\t\t? Boolean(indexedPrimarySkuId)\n\t\t\t: undefined;\n\n\tuseEffect(() => {\n\t\tconst handleCartUpdated = (e: CustomEvent) => {\n\t\t\tif (e.detail.requestId === requestIdRef.current) {\n\t\t\t\tsetIsAddingToCart(false);\n\t\t\t}\n\t\t};\n\n\t\tconst handleCartUpdateError = (e: CustomEvent) => {\n\t\t\tif (e.detail.requestId === requestIdRef.current) {\n\t\t\t\tsetIsAddingToCart(false);\n\t\t\t}\n\t\t};\n\n\t\tdocument.addEventListener('faithlife.sites.cart.updated', handleCartUpdated as EventListener);\n\t\tdocument.addEventListener('faithlife.sites.cart.updateError', handleCartUpdateError as EventListener);\n\n\t\treturn () => {\n\t\t\tdocument.removeEventListener('faithlife.sites.cart.updated', handleCartUpdated as EventListener);\n\t\t\tdocument.removeEventListener('faithlife.sites.cart.updateError', handleCartUpdateError as EventListener);\n\t\t};\n\t}, []);\n\n\tconst slug = slugify(hit.title);\n\tconst productPath = slug ? `/product/${productId}/${slug}` : `/product/${productId}`;\n\tconst productUrl = queryId ? `${productPath}?queryId=${encodeURIComponent(queryId)}` : productPath;\n\tconst productName = hit.title ?? '';\n\tconst regularPrice = prices?.anchorPrice?.displayAmount;\n\tconst salePrice = prices?.salePrice?.displayAmount;\n\tconst salePriceCurrency = preferredCurrency !== 'USD' ? 'USD' : undefined;\n\tconst localizedSalePrice = prices?.salePrice?.localizedDisplayAmount ?? undefined;\n\tconst discountPercentage = getSavingsPercent(prices);\n\tconst isDiscounted = !!pricingData?.primarySku?.prices?.discountSavings;\n\tconst productImageSrc = hit.primaryImageUri;\n\tconst imageSrc = detectIsAmberOptimizedUrl(productImageSrc ?? '') ? productImageSrc : placeholderImage;\n\tconst isLogosEdition = hit.isLogosEdition ?? false;\n\n\tconst handleProductClick = useCallback(() => {\n\t\tif (!productId) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (queryId && position) {\n\t\t\tinsightsClient('clickedObjectIDsAfterSearch', {\n\t\t\t\tindex: indexName,\n\t\t\t\teventName: `Clicked result on ${window.location.pathname}`.substring(0, 64),\n\t\t\t\tqueryID: queryId,\n\t\t\t\tobjectIDs: [productId],\n\t\t\t\tpositions: [position],\n\t\t\t});\n\t\t} else {\n\t\t\tinsightsClient('clickedObjectIDs', {\n\t\t\t\tindex: indexName,\n\t\t\t\teventName: `Clicked result on ${window.location.pathname}`.substring(0, 64),\n\t\t\t\tobjectIDs: [productId],\n\t\t\t});\n\t\t}\n\t}, [productId, queryId, position, indexName]);\n\n\tconst handleAddToCart = (e: React.MouseEvent<HTMLButtonElement>) => {\n\t\tif (!skuId || isAddingToCart) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Track add-to-cart with Algolia insights\n\t\tif (productId) {\n\t\t\tconst eventType = queryId ? 'addedToCartObjectIDsAfterSearch' : 'addedToCartObjectIDs';\n\t\t\tconst eventData: Record<string, any> = {\n\t\t\t\tindex: indexName,\n\t\t\t\teventName: `Added product to cart on ${window.location.pathname}`.substring(0, 64),\n\t\t\t\tobjectIDs: [productId],\n\t\t\t};\n\t\t\tif (queryId) {\n\t\t\t\teventData.queryID = queryId;\n\t\t\t}\n\t\t\tinsightsClient(eventType as any, eventData);\n\t\t}\n\n\t\tconst requestId = (requestIdRef.current = `${Date.now()}-${Math.random()}`);\n\n\t\tconst eventDetail: Record<string, any> = {\n\t\t\taddToCartUrl: pricingData?.primarySku?.routes?.addToCartUrl,\n\t\t\tskuIds: [pricingData?.primarySku?.addToCartSkuId ?? skuId],\n\t\t\tquantity: 1,\n\t\t\tpayInFull: true,\n\t\t\trequestId,\n\t\t};\n\n\t\t// Include the query ID for Algolia purchase attribution\n\t\tif (queryId) {\n\t\t\teventDetail.searchData = {\n\t\t\t\tqueryId,\n\t\t\t\t...(productId ? { productIds: [productId] } : {}),\n\t\t\t\tanonymousUserToken,\n\t\t\t};\n\t\t}\n\n\t\te.currentTarget.dispatchEvent(\n\t\t\tnew CustomEvent('faithlife.sites.addToCartButton.click', {\n\t\t\t\tbubbles: true,\n\t\t\t\tdetail: eventDetail,\n\t\t\t})\n\t\t);\n\n\t\tsetIsAddingToCart(true);\n\t};\n\n\treturn {\n\t\tresources,\n\t\tproductUrl,\n\t\tproductName,\n\t\timageSrc,\n\t\tisLogosEdition,\n\t\tregularPrice,\n\t\tsalePrice,\n\t\tsalePriceCurrency,\n\t\tlocalizedSalePrice,\n\t\tdiscountPercentage,\n\t\tisDiscounted,\n\t\taccessKind,\n\t\tisOwned,\n\t\thasGeoRestriction,\n\t\tisPurchasable,\n\t\thasPreorder,\n\t\tisPrepubProduct,\n\t\tprepubProductStatusSummary,\n\t\tskuId,\n\t\tisAddingToCart,\n\t\thandleProductClick,\n\t\thandleAddToCart,\n\t\thit,\n\t};\n}\n\nexport type ProductCardData = ReturnType<typeof useProductCard>;\n","import React from 'react';\n\nimport { Image } from '../../shared/enhanced-image-tag/image';\n\ninterface ProductImageProps {\n\tproductName: string;\n\timageSrc: string;\n\tproductUrl: string;\n\tpriority?: boolean;\n\thandleProductClick: () => void;\n}\n\nexport function ProductImage({ productName, imageSrc, productUrl, priority, handleProductClick }: ProductImageProps) {\n\treturn (\n\t\t<a\n\t\t\tclassName=\"flex aspect-[100/122] w-auto justify-center lg:aspect-[129/158]\"\n\t\t\thref={productUrl}\n\t\t\tonClick={handleProductClick}\n\t\t\tonAuxClick={handleProductClick}\n\t\t>\n\t\t\t<Image\n\t\t\t\talt={productName}\n\t\t\t\tbelowTheFold={!priority}\n\t\t\t\tclassName=\"w-[100px] h-[122px] object-contain lg:h-[158px] lg:w-[129px]\"\n\t\t\t\tsizes={{ mobile: 100, desktop: 129 }}\n\t\t\t\tsrc={imageSrc}\n\t\t\t\ttargetAspectRatio={[129, 158]}\n\t\t\t/>\n\t\t</a>\n\t);\n}\n","import React from 'react';\nimport { Typography } from '@faithlife/commerce-components';\n\nimport { useSearchResources } from '../search-resources';\n\ninterface DiscountBadgeProps {\n\tdiscountPercentage: number;\n\tisDiscounted: boolean;\n\tclassName?: string;\n}\n\nexport function DiscountBadge({ discountPercentage, isDiscounted, className }: DiscountBadgeProps) {\n\tconst resources = useSearchResources();\n\n\tif (discountPercentage <= 1) {\n\t\treturn null;\n\t}\n\n\tconst badgeClassName = isDiscounted ? 'bg-red-300 text-white' : 'bg-primary-200 text-primary-400';\n\n\treturn (\n\t\t<Typography className={`rounded-full px-2 py-[2px] ${badgeClassName} ${className ?? ''}`} variant=\"finePrint\">\n\t\t\t{resources['discountFormat']?.replace('%DISCOUNT_PERCENTAGE%', discountPercentage.toFixed())}\n\t\t</Typography>\n\t);\n}\n","import React from 'react';\nimport { Typography } from '@faithlife/commerce-components';\n\nimport { cn } from '../../../util/cn';\n\ninterface ProductTitleProps {\n\tproductName: string;\n\tproductUrl: string;\n\thandleProductClick: () => void;\n\tclassName?: string;\n}\n\nexport function ProductTitle({ productName, productUrl, handleProductClick, className }: ProductTitleProps) {\n\treturn (\n\t\t<a href={productUrl} onAuxClick={handleProductClick} onClick={handleProductClick} title={productName}>\n\t\t\t<Typography\n\t\t\t\tclassName={cn('line-clamp-2 hover:underline focus-visible:underline', className)}\n\t\t\t\ttag=\"h3\"\n\t\t\t\tvariant=\"bodySmall\"\n\t\t\t>\n\t\t\t\t{productName}\n\t\t\t</Typography>\n\t\t</a>\n\t);\n}\n","import React from 'react';\nimport { Typography } from '@faithlife/commerce-components';\n\ninterface ProductAuthorsProps {\n\tauthors?: string[];\n}\n\nexport function ProductAuthors({ authors }: ProductAuthorsProps) {\n\treturn (\n\t\t<Typography className=\"bodyMd line-clamp-1 text-black\" variant=\"finePrint\">\n\t\t\t{authors?.join(', ')}\n\t\t</Typography>\n\t);\n}\n","import React from 'react';\nimport { Button, PriceLabel, Typography } from '@faithlife/commerce-components';\nimport type { buttonScaleOptions } from '@faithlife/commerce-components';\n\nimport { cn } from '../../../util/cn';\nimport * as Skeleton from '../../skeleton';\nimport { useSearchResources } from '../search-resources';\nimport { ProductCardData } from './use-product-card';\n\ntype ButtonScale = (typeof buttonScaleOptions)[number];\n\nconst ctaButtonScale: ButtonScale = 'medium';\nconst skeletonHeightByButtonScale = {\n\tsmall: 'h-8',\n\tmedium: 'h-12',\n\tlarge: 'h-[60px]',\n} satisfies Record<ButtonScale, string>;\n\ninterface ProductPricingProps {\n\tcardData: ProductCardData;\n\tbuttonLayoutClassName: string;\n}\n\nfunction getOwnershipLabel(\n\tresources: ReturnType<typeof useSearchResources>,\n\thasGeoRestriction: boolean | undefined,\n\taccessKind: string | undefined,\n\thasPreorder: boolean | undefined\n): string | null {\n\tif (hasGeoRestriction) {\n\t\treturn resources['geoRestrictionMessage'];\n\t}\n\tif (accessKind === 'Permanent') {\n\t\treturn resources['permanentOwnMessage'];\n\t}\n\tif (accessKind === 'Temporary') {\n\t\treturn resources['temporaryOwnMessage'];\n\t}\n\tif (hasPreorder) {\n\t\treturn resources['hasPreorderMessage'];\n\t}\n\treturn null;\n}\n\nexport function ProductPricing({ cardData, buttonLayoutClassName }: ProductPricingProps) {\n\treturn (\n\t\t<>\n\t\t\t<ProductPrice cardData={cardData} className=\"items-end\" />\n\t\t\t<ProductCta\n\t\t\t\tbuttonLayoutClassName={buttonLayoutClassName}\n\t\t\t\tcardData={cardData}\n\t\t\t\townershipLabelClassName=\"text-right\"\n\t\t\t/>\n\t\t</>\n\t);\n}\n\ninterface ProductPriceProps {\n\tcardData: ProductCardData;\n\tclassName?: string;\n}\n\nexport function ProductPrice({ cardData, className }: ProductPriceProps) {\n\tconst { salePrice, salePriceCurrency, regularPrice, localizedSalePrice, isDiscounted, accessKind } = cardData;\n\n\tif (accessKind === 'Permanent' || accessKind === 'Temporary') {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<PriceLabel\n\t\t\tvariant={isDiscounted ? 'sale' : 'value'}\n\t\t\tlayout=\"vertical\"\n\t\t\tsalePrice={salePrice ?? ''}\n\t\t\tsalePriceCurrency={salePriceCurrency ?? undefined}\n\t\t\tanchorPrice={regularPrice}\n\t\t\tlocalizedSalePrice={localizedSalePrice ?? undefined}\n\t\t\tclassName={cn(className)}\n\t\t/>\n\t);\n}\n\ninterface ProductCtaProps {\n\tcardData: ProductCardData;\n\tbuttonLayoutClassName: string;\n\townershipLabelClassName?: string;\n}\n\nexport function ProductCta({ cardData, buttonLayoutClassName, ownershipLabelClassName }: ProductCtaProps) {\n\tconst resources = useSearchResources();\n\tconst {\n\t\tisPurchasable,\n\t\thasGeoRestriction,\n\t\taccessKind,\n\t\thasPreorder,\n\t\tskuId,\n\t\tisAddingToCart,\n\t\tisPrepubProduct,\n\t\thandleAddToCart,\n\t} = cardData;\n\n\tlet purchaseStatusMessage = getOwnershipLabel(resources, hasGeoRestriction, accessKind, hasPreorder);\n\n\tif (isPurchasable !== undefined && !isPurchasable && !purchaseStatusMessage) {\n\t\tpurchaseStatusMessage = resources['UnavailableToPurchase'];\n\t}\n\n\tif (purchaseStatusMessage) {\n\t\treturn (\n\t\t\t<Typography\n\t\t\t\tvariant=\"bodyRegular\"\n\t\t\t\tclassName={cn('text-primary-500', ownershipLabelClassName ?? cn('text-center', !hasPreorder && 'md:pt-sp16'))}\n\t\t\t>\n\t\t\t\t{purchaseStatusMessage}\n\t\t\t</Typography>\n\t\t);\n\t}\n\n\tif (skuId) {\n\t\treturn (\n\t\t\t<div className={cn('inline-flex gap-2 lg:gap-3', buttonLayoutClassName)}>\n\t\t\t\t<Button\n\t\t\t\t\tdisabled={isAddingToCart}\n\t\t\t\t\tonClick={handleAddToCart}\n\t\t\t\t\tscale={ctaButtonScale}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t>\n\t\t\t\t\t{isAddingToCart\n\t\t\t\t\t\t? resources['addingToCart']\n\t\t\t\t\t\t: isPrepubProduct\n\t\t\t\t\t\t\t? resources['preorder']\n\t\t\t\t\t\t\t: resources['addToCart']}\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Skeleton.Root className={cn('animate-pulse inline-flex gap-2 lg:gap-3', buttonLayoutClassName)}>\n\t\t\t<Skeleton.Box className={cn('w-full', skeletonHeightByButtonScale[ctaButtonScale])} />\n\t\t</Skeleton.Root>\n\t);\n}\n","import React from 'react';\nimport { StarRating } from '@faithlife/commerce-components';\n\nimport { ProductHitResult } from '../types';\nimport { useProductInWishList } from '../../add-to-wish-list/hooks';\nimport { AddToWishList } from '../../add-to-wish-list';\nimport EnhancedForLogosWithTooltip from '../../shared/enhanced-for-logos-with-tooltip';\nimport { hasValidReviewData } from '../../shared/ratings/review-data';\nimport { PrepubProductStatusSummary } from '../../product/product-details-page/right-column/prepub-product-status-summary';\nimport { useProductCard } from './use-product-card';\nimport { ProductImage } from './product-image';\nimport { DiscountBadge } from './discount-badge';\nimport { ProductTitle } from './product-title';\nimport { ProductAuthors } from './product-authors';\nimport { ProductPrice, ProductCta } from './product-pricing';\n\ninterface AlgoliaGridCardProps {\n\thit: ProductHitResult;\n\tpriority?: boolean;\n\tqueryId?: string | null;\n\tposition?: number;\n}\n\nexport function AlgoliaGridCard({ hit, priority, queryId = null, position }: AlgoliaGridCardProps) {\n\tconst cardData = useProductCard({ hit, queryId, position });\n\tconst {\n\t\tproductUrl,\n\t\tproductName,\n\t\timageSrc,\n\t\tdiscountPercentage,\n\t\tisDiscounted,\n\t\thandleProductClick,\n\t\tskuId,\n\t\tisLogosEdition,\n\t\tprepubProductStatusSummary,\n\t\tisOwned,\n\t\tisPrepubProduct,\n\t} = cardData;\n\tconst productWishlistData = useProductInWishList(hit.productId, skuId, !isOwned && !isPrepubProduct);\n\tconst averageRating = hit.averageRating ?? 0;\n\tconst reviewCount = hit.reviewCount ?? 0;\n\tconst hasReviewData = hasValidReviewData(averageRating, reviewCount);\n\n\treturn (\n\t\t<div className=\"grid gap-y-0 grid-rows-subgrid row-span-5 grid-cols-1\">\n\t\t\t{/* Row 1: Image — fixed aspect ratio, never grows */}\n\t\t\t<div className=\"relative flex flex-col items-center justify-start gap-sp12 pt-3 lg:pt-4\">\n\t\t\t\t<div className=\"flex h-43.5 w-full items-end justify-center\">\n\t\t\t\t\t<ProductImage\n\t\t\t\t\t\thandleProductClick={handleProductClick}\n\t\t\t\t\t\timageSrc={imageSrc}\n\t\t\t\t\t\tpriority={priority}\n\t\t\t\t\t\tproductName={productName}\n\t\t\t\t\t\tproductUrl={productUrl}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"h-4 text-center\">{isLogosEdition && <EnhancedForLogosWithTooltip />}</div>\n\t\t\t\t{!isOwned && (\n\t\t\t\t\t<DiscountBadge\n\t\t\t\t\t\tclassName=\"absolute top-2 left-2\"\n\t\t\t\t\t\tdiscountPercentage={discountPercentage}\n\t\t\t\t\t\tisDiscounted={isDiscounted}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\n\t\t\t\t{productWishlistData !== null && <AddToWishList {...productWishlistData} variant=\"icon\" isOwned={isOwned} />}\n\t\t\t</div>\n\n\t\t\t{/* Row 2: Info — grows to absorb variable space */}\n\t\t\t<div className=\"px-2 pt-sp12 pb-1 lg:px-4 lg:pb-2\">\n\t\t\t\t<ProductTitle\n\t\t\t\t\tclassName=\"line-clamp-2\"\n\t\t\t\t\thandleProductClick={handleProductClick}\n\t\t\t\t\tproductName={productName}\n\t\t\t\t\tproductUrl={productUrl}\n\t\t\t\t/>\n\n\t\t\t\t<div className=\"mt-sp8\">\n\t\t\t\t\t<ProductAuthors authors={hit.authors} />\n\t\t\t\t</div>\n\n\t\t\t\t{hasReviewData && (\n\t\t\t\t\t<div className=\"mt-sp8\">\n\t\t\t\t\t\t<StarRating rating={averageRating} reviewCount={reviewCount} />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Row 3: Prepub summary — empty when not present */}\n\t\t\t<div className=\"px-2 lg:px-4\">\n\t\t\t\t{prepubProductStatusSummary && (\n\t\t\t\t\t<PrepubProductStatusSummary {...prepubProductStatusSummary} variant=\"search-grid\" />\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{/* Row 4: Price — always aligned across cards */}\n\t\t\t<div className=\"flex items-end px-2 md:pb-1 lg:px-4\">\n\t\t\t\t<ProductPrice cardData={cardData} />\n\t\t\t</div>\n\n\t\t\t{/* Row 5: CTA — always aligned across cards */}\n\t\t\t<ProductCta buttonLayoutClassName=\"w-full flex-col px-2 pb-2 pt-2 lg:px-4 lg:pb-4\" cardData={cardData} />\n\t\t</div>\n\t);\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { LinkButton } from '@faithlife/commerce-components';\n\nimport { cn } from '../../../util/cn';\nimport { useSearchResources } from '../search-resources';\n\ninterface ProductOverviewProps {\n\toverview?: string;\n}\n\nexport function ProductOverview({ overview }: ProductOverviewProps) {\n\tconst [isExpanded, setIsExpanded] = useState(false);\n\tconst [showButton, setShowButton] = useState(false);\n\tconst overviewRef = useRef<HTMLDivElement>(null);\n\tconst resources = useSearchResources();\n\n\tuseEffect(() => {\n\t\tconst element = overviewRef.current;\n\n\t\tif (element) {\n\t\t\ttry {\n\t\t\t\tconst height = element.scrollHeight;\n\t\t\t\tconst computedLineHeight = getComputedStyle(element).lineHeight;\n\t\t\t\tconst parsedLineHeight = parseInt(computedLineHeight, 10);\n\t\t\t\tconst lineHeight = Number.isFinite(parsedLineHeight) && parsedLineHeight > 0 ? parsedLineHeight : 20;\n\t\t\t\tconst maxHeight = lineHeight * 4;\n\t\t\t\tconst maxHeightMobile = lineHeight * 2;\n\n\t\t\t\tif (height > maxHeight || height > maxHeightMobile) {\n\t\t\t\t\tsetShowButton(true);\n\t\t\t\t} else {\n\t\t\t\t\tsetShowButton(false);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tsetShowButton(false);\n\t\t\t}\n\t\t}\n\t}, [overview]);\n\n\tconst toggleExpand = () => {\n\t\tsetIsExpanded(!isExpanded);\n\t};\n\n\treturn (\n\t\t<>\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'hidden text-black [&>*:first-child]:mt-0',\n\t\t\t\t\t!isExpanded && 'md:line-clamp-2',\n\t\t\t\t\tisExpanded && 'md:line-clamp-none'\n\t\t\t\t)}\n\t\t\t\tdangerouslySetInnerHTML={{ __html: overview ?? '' }}\n\t\t\t\tref={overviewRef}\n\t\t\t/>\n\t\t\t{showButton && (\n\t\t\t\t<LinkButton\n\t\t\t\t\tas=\"button\"\n\t\t\t\t\tclassName=\"hidden md:inline-flex bodyMd !font-normal\"\n\t\t\t\t\tintent=\"none\"\n\t\t\t\t\tonClick={toggleExpand}\n\t\t\t\t\tscale=\"sm\"\n\t\t\t\t>\n\t\t\t\t\t{isExpanded ? resources['readLess'] : resources['readMore']}\n\t\t\t\t</LinkButton>\n\t\t\t)}\n\t\t</>\n\t);\n}\n","import React from 'react';\nimport { StarRating } from '@faithlife/commerce-components';\n\nimport { ProductHitResult } from '../types';\nimport { AddToWishList } from '../../add-to-wish-list';\nimport { useProductInWishList } from '../../add-to-wish-list/hooks';\nimport EnhancedForLogosWithTooltip from '../../shared/enhanced-for-logos-with-tooltip';\nimport { hasValidReviewData } from '../../shared/ratings/review-data';\nimport { PrepubProductStatusSummary } from '../../product/product-details-page/right-column/prepub-product-status-summary';\nimport { useProductCard } from './use-product-card';\nimport { DiscountBadge } from './discount-badge';\nimport { ProductTitle } from './product-title';\nimport { ProductAuthors } from './product-authors';\nimport { ProductOverview } from './product-overview';\nimport { ProductPricing } from './product-pricing';\nimport { ProductImage } from './product-image';\n\ninterface AlgoliaListCardProps {\n\thit: ProductHitResult;\n\tpriority?: boolean;\n\tqueryId?: string | null;\n\tposition?: number;\n}\n\nexport function AlgoliaListCard({ hit, priority, queryId = null, position }: AlgoliaListCardProps) {\n\tconst cardData = useProductCard({ hit, queryId, position });\n\tconst {\n\t\tproductUrl,\n\t\tproductName,\n\t\timageSrc,\n\t\tdiscountPercentage,\n\t\tisDiscounted,\n\t\thandleProductClick,\n\t\tskuId,\n\t\tisOwned,\n\t\tisLogosEdition,\n\t\tprepubProductStatusSummary,\n\t\tisPrepubProduct,\n\t} = cardData;\n\tconst productWishlistData = useProductInWishList(hit.productId, skuId, !isOwned && !isPrepubProduct);\n\tconst averageRating = hit.averageRating ?? 0;\n\tconst reviewCount = hit.reviewCount ?? 0;\n\tconst hasReviewData = hasValidReviewData(averageRating, reviewCount);\n\n\treturn (\n\t\t<div className=\"grid grid-cols-[139px_auto] md:grid-cols-[190px_auto]\">\n\t\t\t<div className=\"relative col-span-1 flex w-full items-start justify-center\">\n\t\t\t\t<div className=\"flex w-auto flex-col gap-sp8 pt-2 pb-[43px] lg:pt-3 md:pb-9\">\n\t\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t\t<ProductImage\n\t\t\t\t\t\t\thandleProductClick={handleProductClick}\n\t\t\t\t\t\t\timageSrc={imageSrc}\n\t\t\t\t\t\t\tpriority={priority}\n\t\t\t\t\t\t\tproductName={productName}\n\t\t\t\t\t\t\tproductUrl={productUrl}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{!isOwned && (\n\t\t\t\t\t\t\t<DiscountBadge\n\t\t\t\t\t\t\t\tclassName=\"absolute top-0 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none\"\n\t\t\t\t\t\t\t\tdiscountPercentage={discountPercentage}\n\t\t\t\t\t\t\t\tisDiscounted={isDiscounted}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{isLogosEdition && (\n\t\t\t\t\t\t<div className=\"text-center\">\n\t\t\t\t\t\t\t<EnhancedForLogosWithTooltip />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\n\t\t\t<div className=\"grid p-2 pb-8 md:grid-cols-[auto_168px] md:gap-8 md:pb-2 lg:p-3\">\n\t\t\t\t<div className=\"flex-1\">\n\t\t\t\t\t<ProductTitle handleProductClick={handleProductClick} productName={productName} productUrl={productUrl} />\n\n\t\t\t\t\t<div className=\"mt-sp8\">\n\t\t\t\t\t\t<ProductAuthors authors={hit.authors} />\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{hasReviewData && (\n\t\t\t\t\t\t<div className=\"mt-sp8\">\n\t\t\t\t\t\t\t<StarRating rating={averageRating} reviewCount={reviewCount} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t\t<div className=\"mt-sp12\">\n\t\t\t\t\t\t<ProductOverview overview={hit.overview} />\n\t\t\t\t\t</div>\n\t\t\t\t\t{prepubProductStatusSummary && (\n\t\t\t\t\t\t<PrepubProductStatusSummary {...prepubProductStatusSummary} variant=\"search-list\" />\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"flex grow-0 flex-col gap-2 lg:gap-3 items-end\">\n\t\t\t\t\t<ProductPricing\n\t\t\t\t\t\tbuttonLayoutClassName=\"w-full flex-col xmd:flex-row md:flex-col max-w-[145px]\"\n\t\t\t\t\t\tcardData={cardData}\n\t\t\t\t\t/>\n\t\t\t\t\t{productWishlistData !== null && <AddToWishList {...productWishlistData} variant=\"link\" isOwned={isOwned} />}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n","import React, { useCallback } from 'react';\nimport { Hit } from 'instantsearch.js';\nimport { Hits, useInstantSearch } from 'react-instantsearch';\n\nimport { cn } from '../../util/cn';\nimport * as Skeleton from '../skeleton';\nimport { WishlistContextProvider } from '../add-to-wish-list/wishlist-context-provider';\nimport { ProductHit, ProductHitResult } from './types';\nimport { AlgoliaGridCard } from './product-card/algolia-grid-card';\nimport { AlgoliaListCard } from './product-card/algolia-list-card';\n\n// ---------------------------------------------------------------------------\n// ProductHits — grid/list of search result cards\n// ---------------------------------------------------------------------------\n\ninterface ProductHitsProps {\n\tlayoutType: 'grid' | 'list';\n\twishListsProductsUrl: string;\n\tcurrentHitsPerPage: number;\n}\n\nfunction SkeletonBlock({ className, rootClassName }: { className: string; rootClassName?: string }) {\n\treturn <Skeleton.Box className={cn(className, rootClassName)} />;\n}\n\nfunction SkeletonButton({ className }: { className: string }) {\n\treturn <Skeleton.Box className={cn('h-12 inline-flex gap-2 lg:gap-3', className)} />;\n}\n\nfunction ProductSkeleton({ layoutType }: { layoutType: 'grid' | 'list' }) {\n\tif (layoutType === 'list') {\n\t\treturn (\n\t\t\t<Skeleton.Root className=\"animate-pulse\">\n\t\t\t\t<div className=\"grid grid-cols-[139px_auto] md:grid-cols-[190px_auto]\">\n\t\t\t\t\t<div className=\"relative col-span-1 flex w-full items-start justify-center\">\n\t\t\t\t\t\t<div className=\"flex w-auto flex-col gap-sp8 pt-2 pb-[43px] lg:pt-3 md:pb-9\">\n\t\t\t\t\t\t\t<div className=\"relative\">\n\t\t\t\t\t\t\t\t<SkeletonBlock className=\"h-[122px] w-[122px] lg:h-[158px] lg:w-[158px]\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div className=\"text-center\">\n\t\t\t\t\t\t\t\t<SkeletonBlock className=\"h-4 w-20\" rootClassName=\"mx-auto h-4 w-20\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"grid gap-sp8 p-2 pb-8 md:grid-cols-[auto_168px] md:gap-8 md:pb-2 lg:p-3\">\n\t\t\t\t\t\t<div className=\"flex-1\">\n\t\t\t\t\t\t\t<SkeletonBlock className=\"h-12 w-full\" />\n\t\t\t\t\t\t\t<SkeletonBlock className=\"mt-sp8 h-4 w-3/5\" />\n\t\t\t\t\t\t\t<SkeletonBlock className=\"mt-sp8 h-5 w-2/5\" />\n\t\t\t\t\t\t\t<SkeletonBlock className=\"mt-sp12 h-16 w-full\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div className=\"flex flex-col items-end gap-2 lg:gap-3\">\n\t\t\t\t\t\t\t<div className=\"flex flex-col items-end gap-sp4\">\n\t\t\t\t\t\t\t\t<SkeletonBlock className=\"h-4 w-20\" />\n\t\t\t\t\t\t\t\t<SkeletonBlock className=\"h-7 w-24\" />\n\t\t\t\t\t\t\t\t<SkeletonBlock className=\"h-4 w-16\" />\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<SkeletonButton className=\"w-full max-w-[145px]\" />\n\t\t\t\t\t\t\t<SkeletonBlock className=\"h-4 w-24\" />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</Skeleton.Root>\n\t\t);\n\t}\n\n\treturn (\n\t\t<Skeleton.Root className=\"animate-pulse grid gap-y-0 grid-rows-subgrid row-span-5 grid-cols-1\">\n\t\t\t<div className=\"relative flex flex-col items-center justify-start gap-sp12 pt-3 lg:pt-4\">\n\t\t\t\t<div className=\"flex h-43.5 w-full items-end justify-center\">\n\t\t\t\t\t<SkeletonBlock\n\t\t\t\t\t\tclassName=\"h-[122px] w-[100px] lg:h-[158px] lg:w-[129px]\"\n\t\t\t\t\t\trootClassName=\"h-[122px] w-[100px] lg:h-[158px] lg:w-[129px]\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<SkeletonBlock className=\"h-4 w-20\" rootClassName=\"mx-auto h-4 w-20\" />\n\t\t\t</div>\n\t\t\t<div className=\"px-2 pt-sp12 pb-1 lg:px-4 lg:pb-2\">\n\t\t\t\t<SkeletonBlock className=\"h-12 w-full\" />\n\t\t\t\t<SkeletonBlock className=\"mt-sp8 h-4 w-3/5\" />\n\t\t\t\t<SkeletonBlock className=\"mt-sp8 h-5 w-2/5\" />\n\t\t\t</div>\n\t\t\t<div className=\"px-2 lg:px-4\" />\n\t\t\t<div className=\"flex items-end px-2 md:pb-1 lg:px-4\">\n\t\t\t\t<div className=\"flex w-full flex-col gap-sp4\">\n\t\t\t\t\t<SkeletonBlock className=\"h-4 w-3/5\" rootClassName=\"h-4 w-3/5\" />\n\t\t\t\t\t<SkeletonBlock className=\"h-7 w-4/5\" rootClassName=\"h-7 w-4/5\" />\n\t\t\t\t\t<SkeletonBlock className=\"h-4 w-2/5\" rootClassName=\"h-4 w-2/5\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div className=\"flex items-end justify-center px-2 pb-2 pt-2 lg:px-4 lg:pb-4\">\n\t\t\t\t<SkeletonButton className=\"w-full\" />\n\t\t\t</div>\n\t\t</Skeleton.Root>\n\t);\n}\n\nfunction ProductSkeletons({\n\tlayoutType,\n\tcurrentHitsPerPage,\n}: {\n\tlayoutType: 'grid' | 'list';\n\tcurrentHitsPerPage: number;\n}) {\n\treturn (\n\t\t<ol\n\t\t\taria-label=\"Loading search results\"\n\t\t\tclassName={cn(\n\t\t\t\t'grid grid-cols-1',\n\t\t\t\tlayoutType === 'grid' &&\n\t\t\t\t\t'auto-rows-[max-content_auto_max-content_max-content_max-content] grid-cols-2 gap-sp8 lg:grid-cols-3 lg:gap-sp16',\n\t\t\t\tlayoutType === 'list' && 'gap-6 md:gap-8'\n\t\t\t)}\n\t\t>\n\t\t\t{Array.from({ length: currentHitsPerPage }, (_, index) => (\n\t\t\t\t<li\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\tlayoutType === 'grid' &&\n\t\t\t\t\t\t\t'grid gap-y-0 grid-rows-subgrid row-span-5 grid-cols-1 outline outline-1 outline-grey',\n\t\t\t\t\t\tlayoutType === 'list' && 'first:border-t border-b border-grey-200 first:pt-6 first:md:pt-8'\n\t\t\t\t\t)}\n\t\t\t\t\tkey={index}\n\t\t\t\t>\n\t\t\t\t\t<ProductSkeleton layoutType={layoutType} />\n\t\t\t\t</li>\n\t\t\t))}\n\t\t</ol>\n\t);\n}\n\nfunction toProductHitResult(hit: Hit<ProductHit>): ProductHitResult {\n\treturn {\n\t\t...hit,\n\t\tproductId: hit.productId !== null && hit.productId !== undefined ? hit.productId.toString() : undefined,\n\t};\n}\n\nexport function ProductHits({ layoutType, wishListsProductsUrl, currentHitsPerPage }: ProductHitsProps) {\n\tconst { status } = useInstantSearch();\n\tconst HitComponent = useCallback(\n\t\t({ hit }: { hit: Hit<ProductHit> }) => {\n\t\t\tconst cardProps = {\n\t\t\t\thit: toProductHitResult(hit),\n\t\t\t\t// eslint-disable-next-line no-underscore-dangle\n\t\t\t\tpriority: typeof hit.__position === 'number' && hit.__position <= 6,\n\t\t\t\t// eslint-disable-next-line no-underscore-dangle\n\t\t\t\tqueryId: (hit as any).__queryID ?? null,\n\t\t\t\t// eslint-disable-next-line no-underscore-dangle\n\t\t\t\tposition: hit.__position,\n\t\t\t};\n\t\t\treturn layoutType === 'list' ? <AlgoliaListCard {...cardProps} /> : <AlgoliaGridCard {...cardProps} />;\n\t\t},\n\t\t[layoutType]\n\t);\n\n\treturn (\n\t\t<WishlistContextProvider wishListsProductsUrl={wishListsProductsUrl}>\n\t\t\t<section aria-label=\"Search results\">\n\t\t\t\t{status === 'stalled' && (\n\t\t\t\t\t<div className=\"pt-4 pb-6 lg:px-4 lg:py-8\">\n\t\t\t\t\t\t<ProductSkeletons layoutType={layoutType} currentHitsPerPage={currentHitsPerPage} />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\t\t\t\t<Hits\n\t\t\t\t\tclassNames={{\n\t\t\t\t\t\troot: cn('pt-4 pb-6 lg:px-4 lg:py-8', status === 'stalled' && 'hidden'),\n\t\t\t\t\t\tlist: cn(\n\t\t\t\t\t\t\t'grid grid-cols-1',\n\t\t\t\t\t\t\tlayoutType === 'grid' &&\n\t\t\t\t\t\t\t\t'auto-rows-[max-content_auto_max-content_max-content_max-content] grid-cols-2 gap-sp8 lg:grid-cols-3 lg:gap-sp16',\n\t\t\t\t\t\t\tlayoutType === 'list' && 'gap-6 md:gap-8'\n\t\t\t\t\t\t),\n\t\t\t\t\t\titem: cn(\n\t\t\t\t\t\t\t/* the grid definition must match AlgoliaGridCard to pass subgrid tracks to it correctly */\n\t\t\t\t\t\t\tlayoutType === 'grid' &&\n\t\t\t\t\t\t\t\t'grid gap-y-0 grid-rows-subgrid row-span-5 grid-cols-1 outline outline-1 outline-grey',\n\t\t\t\t\t\t\t/* first:pt matches the gap-6/md:gap-8 list gutter so item 1's top spacing matches the gap preceding every other item */\n\t\t\t\t\t\t\tlayoutType === 'list' && 'first:border-t border-b border-grey-200 first:pt-6 first:md:pt-8'\n\t\t\t\t\t\t),\n\t\t\t\t\t}}\n\t\t\t\t\thitComponent={HitComponent}\n\t\t\t\t/>\n\t\t\t</section>\n\t\t</WishlistContextProvider>\n\t);\n}\n\nexport default ProductHits;\n","import React from 'react';\nimport { Typography } from '@faithlife/commerce-components';\n\nimport { cn } from '../../util/cn';\nimport { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '../accordion';\n\nexport interface RadioAccordionItem<TValue extends string | number> {\n\tchecked: boolean;\n\tlabel: string;\n\tvalue: TValue;\n}\n\ninterface RadioAccordionProps<TValue extends string | number> {\n\tradioGroupName: string;\n\titems: RadioAccordionItem<TValue>[];\n\tonSelect: (value: TValue) => void;\n\tprefixLabel: string;\n}\n\nexport default function RadioAccordion<TValue extends string | number>({\n\tradioGroupName,\n\titems,\n\tonSelect,\n\tprefixLabel,\n}: RadioAccordionProps<TValue>) {\n\tconst currentItem = items.find(item => item.checked);\n\n\treturn (\n\t\t<Accordion collapsible type=\"single\">\n\t\t\t<AccordionItem value={radioGroupName}>\n\t\t\t\t<AccordionTrigger className=\"border-t border-primary-100 p-4 lg:border-t-0 [&>svg]:text-primary\">\n\t\t\t\t\t<Typography className=\"text-primary-400\" variant=\"bodyRegular\">\n\t\t\t\t\t\t{prefixLabel} {}\n\t\t\t\t\t\t{currentItem && <span className=\"font-semibold\">{currentItem.label}</span>}\n\t\t\t\t\t</Typography>\n\t\t\t\t</AccordionTrigger>\n\t\t\t\t<AccordionContent className=\"m-0 bg-grey-200 p-4\">\n\t\t\t\t\t<div className=\"flex flex-col gap-y-4\">\n\t\t\t\t\t\t{items.map(item => (\n\t\t\t\t\t\t\t<label className=\"bodySm flex cursor-pointer items-center text-black-200\" key={item.value}>\n\t\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\t\tchecked={item.checked}\n\t\t\t\t\t\t\t\t\tname={radioGroupName}\n\t\t\t\t\t\t\t\t\tclassName=\"mr-3 h-3.25 w-3.25 border-grey-100 text-primary\"\n\t\t\t\t\t\t\t\t\tonChange={() => onSelect(item.value)}\n\t\t\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\t\t\tvalue={item.value}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t<span className={cn(item.checked ? 'text-primary' : 'text-black-200 hover:text-secondary-200')}>\n\t\t\t\t\t\t\t\t\t{item.label}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</label>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t</AccordionContent>\n\t\t\t</AccordionItem>\n\t\t</Accordion>\n\t);\n}\n","import React from 'react';\nimport { useSortBy } from 'react-instantsearch';\n\nimport { useSearchResources } from './search-resources';\nimport RadioAccordion from './radio-accordion';\n\ninterface SortByItem {\n\tlabel: string;\n\tvalue: string;\n}\n\ninterface SortByAccordionProps {\n\titems: SortByItem[];\n}\n\nexport default function SortByAccordion({ items }: SortByAccordionProps) {\n\tconst resources = useSearchResources();\n\tconst { currentRefinement, refine } = useSortBy({ items });\n\n\treturn (\n\t\t<RadioAccordion\n\t\t\tradioGroupName=\"sort-by\"\n\t\t\titems={items.map(item => ({ ...item, checked: item.value === currentRefinement }))}\n\t\t\tonSelect={refine}\n\t\t\tprefixLabel={resources['sortBy']}\n\t\t/>\n\t);\n}\n","import React from 'react';\nimport { useHitsPerPage } from 'react-instantsearch';\n\nimport { useSearchResources } from './search-resources';\nimport RadioAccordion from './radio-accordion';\n\ninterface HitsPerPageItem {\n\tdefault?: boolean;\n\tlabel: string;\n\tvalue: number;\n}\n\ninterface HitsPerPageAccordionProps {\n\titems: HitsPerPageItem[];\n}\n\nexport default function HitsPerPageAccordion({ items }: HitsPerPageAccordionProps) {\n\tconst resources = useSearchResources();\n\tconst { items: showItems, refine } = useHitsPerPage({ items });\n\n\treturn (\n\t\t<RadioAccordion\n\t\t\tradioGroupName=\"hits-per-page\"\n\t\t\titems={showItems.map(item => ({ ...item, checked: item.isRefined }))}\n\t\t\tonSelect={refine}\n\t\t\tprefixLabel={resources['show']}\n\t\t/>\n\t);\n}\n","import React, { createContext, useContext, useEffect, useState } from 'react';\nimport Cookies from 'js-cookie';\nimport { useLocation } from '../../location';\nimport { safeUrl } from './util';\n\nexport enum ViewMode {\n\tgrid = 'grid',\n\tlist = 'list',\n}\n\ninterface ViewModeContextType {\n\tviewMode: ViewMode;\n\tsetViewMode: (mode: ViewMode) => void;\n}\n\nconst ViewModeContext = createContext<ViewModeContextType | null>(null);\n\nexport const viewModeKey = 'viewMode';\n\nexport const ViewModeProvider = ({\n\tchildren,\n\tinitialViewMode,\n}: {\n\tchildren: React.ReactNode;\n\tinitialViewMode: ViewMode;\n}) => {\n\tconst [viewMode, setViewMode] = useState(initialViewMode);\n\tconst { isQueryStringReady } = useLocation();\n\n\tuseEffect(() => {\n\t\tif (!isQueryStringReady) {\n\t\t\treturn;\n\t\t}\n\t\tconst url = typeof window !== 'undefined' ? safeUrl(window.location.href) : null;\n\t\tif (url) {\n\t\t\turl?.searchParams.set(viewModeKey, viewMode);\n\t\t\twindow.history.replaceState({}, '', url);\n\t\t}\n\t\tCookies.set(viewModeKey, viewMode);\n\t}, [viewMode, isQueryStringReady]);\n\n\treturn <ViewModeContext.Provider value={{ viewMode, setViewMode }}>{children}</ViewModeContext.Provider>;\n};\n\nexport const useViewMode = () => {\n\tconst context = useContext(ViewModeContext);\n\n\tif (!context) {\n\t\tthrow new Error('useViewMode must be used within ViewModeProvider');\n\t}\n\n\treturn context;\n};\n","import { StateMapping, UiState } from 'instantsearch.js';\nimport history from 'instantsearch.js/es/lib/routers/history';\nimport { isEqual } from 'instantsearch.js/es/lib/utils/isEqual';\n\nimport { SearchCategory, SearchSortOrder } from './types';\nimport { UserSearchFilter } from './user-search-filter-context';\nimport { safeUrl } from './util';\nimport { viewModeKey } from './use-view-mode';\n\n// ---------------------------------------------------------------------------\n// Facet configuration\n// ---------------------------------------------------------------------------\n\nexport interface SimpleFacetConfiguration {\n\ttype: 'simple';\n\talgoliaAttribute: string;\n\trouteKey: string;\n\tisHidden?: boolean;\n}\n\nexport interface HierarchicalFacetConfiguration {\n\ttype: 'hierarchical';\n\talgoliaAttributeBase: string;\n\trouteKeyPrefix: string;\n\tminLevel: number;\n\tmaxLevel: number;\n\tcategoryToken?: string;\n\tisHidden?: boolean;\n}\n\nexport type FacetConfiguration = SimpleFacetConfiguration | HierarchicalFacetConfiguration;\n\n// ---------------------------------------------------------------------------\n// Route state types and helpers\n// ---------------------------------------------------------------------------\n\ntype RouteStateFacets = Record<string, string[]>;\ntype RouteStateFilters = Record<string, string>;\n\nfunction getAllFacetingKeys(facetConfigurations: FacetConfiguration[]): string[] {\n\treturn [\n\t\t...facetConfigurations\n\t\t\t.filter((config): config is SimpleFacetConfiguration => config.type === 'simple')\n\t\t\t.map(config => config.routeKey),\n\t\t...facetConfigurations\n\t\t\t.filter((config): config is HierarchicalFacetConfiguration => config.type === 'hierarchical')\n\t\t\t.flatMap(config => {\n\t\t\t\tconst keys: string[] = [];\n\n\t\t\t\tfor (let level = config.minLevel; level <= config.maxLevel; level += 1) {\n\t\t\t\t\tkeys.push(`${config.routeKeyPrefix}${level}`);\n\t\t\t\t}\n\n\t\t\t\treturn keys;\n\t\t\t}),\n\t];\n}\n\nexport interface RouteState {\n\tquery?: string;\n\n\tfacets?: RouteStateFacets;\n\tfilters?: RouteStateFilters;\n\n\tsortBy?: string;\n\tlimit?: number;\n\tpage?: number;\n}\n\nconst delimiter = '+';\n\nfunction arrayToQueryParam(array: string[] | undefined): string | undefined {\n\treturn array?.length ? array.join(delimiter) : undefined;\n}\n\nfunction emptyIfUndefined<T>(array: T[] | undefined): T[] {\n\treturn array && array.length > 0 ? array : [];\n}\n\nfunction getTrimmedOrUndefinedIfStringEmpty(value: string): string | undefined {\n\tconst trimmed = value.trim();\n\n\treturn trimmed.length > 0 ? trimmed : undefined;\n}\n\ninterface CategoryPageFacetConfiguration {\n\tqueryParamName: string;\n\tvalue: string;\n}\n\ninterface CategoryPageConfiguration {\n\tfacets: CategoryPageFacetConfiguration[];\n\tcategoryPageUrl: string;\n\tpageTitle: string;\n\tisPageTitleOverride?: boolean;\n}\n\nfunction getMatchingCategoryPageFromRouteState(\n\trouteState: RouteState,\n\tcategoryPageConfigurations: CategoryPageConfiguration[],\n\tallFacetingKeys: string[]\n): CategoryPageConfiguration | null {\n\tconst facetKeys = new Set([...allFacetingKeys, ...Object.keys(routeState.facets ?? {})]);\n\tconst facets = [...facetKeys].map(key => ({\n\t\tkey,\n\t\tvalue: routeState.facets?.[key],\n\t}));\n\n\tfor (const categoryPageConfiguration of categoryPageConfigurations) {\n\t\tconst matches = checkCategoryPageConfigurationMatches(categoryPageConfiguration, facets);\n\n\t\tif (matches) {\n\t\t\treturn categoryPageConfiguration;\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction preserveCustomQueryParams(sourceUrl: URL, targetUrl: URL, preserveKeys: Set<string>) {\n\tfor (const [key, value] of sourceUrl.searchParams.entries()) {\n\t\tif (preserveKeys.has(key)) {\n\t\t\ttargetUrl.searchParams.set(key, value);\n\t\t}\n\t}\n}\n\nfunction preserveNonSearchQueryParams(sourceUrl: URL, targetUrl: URL, searchParamKeys: Set<string>) {\n\tfor (const [key, value] of sourceUrl.searchParams.entries()) {\n\t\tif (!searchParamKeys.has(key)) {\n\t\t\ttargetUrl.searchParams.set(key, value);\n\t\t}\n\t}\n}\n\nfunction writeFacetsSearchParams(url: URL, facets?: RouteStateFacets, excludedKeys?: Set<string>) {\n\tif (!facets) {\n\t\treturn;\n\t}\n\n\tfor (const [key, value] of Object.entries(facets)) {\n\t\tif (excludedKeys?.has(key)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst candidateQueryParamValue = arrayToQueryParam(value);\n\n\t\tif (candidateQueryParamValue !== undefined) {\n\t\t\turl.searchParams.set(key, candidateQueryParamValue);\n\t\t}\n\t}\n}\n\nfunction writeUserFilterSearchParams(targetUrl: URL, userSearchFilters: UserSearchFilter[], sourceUrl: URL) {\n\tfor (const filter of userSearchFilters) {\n\t\tconst value = sourceUrl.searchParams.get(filter.token);\n\n\t\tif (value) {\n\t\t\ttargetUrl.searchParams.set(filter.token, value);\n\t\t}\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// State mapping — Algolia UI state ↔ route state\n// ---------------------------------------------------------------------------\n\nexport function makeStateMapping(\n\tindex: string,\n\tfacetConfigurations: FacetConfiguration[],\n\tsortOrders: SearchSortOrder[]\n): StateMapping<UiState, RouteState> {\n\treturn {\n\t\tstateToRoute: (uiState: UiState) => {\n\t\t\tconst indexUiState = uiState[index];\n\n\t\t\tif (!indexUiState) {\n\t\t\t\treturn {};\n\t\t\t}\n\n\t\t\tconst facets: RouteStateFacets = {};\n\n\t\t\tfor (const config of facetConfigurations) {\n\t\t\t\tif (config.type === 'simple') {\n\t\t\t\t\tconst facetValues = indexUiState.refinementList?.[config.algoliaAttribute];\n\n\t\t\t\t\tif (facetValues) {\n\t\t\t\t\t\tfacets[config.routeKey] = facetValues;\n\t\t\t\t\t}\n\t\t\t\t} else if (config.type === 'hierarchical') {\n\t\t\t\t\tfor (let level = config.minLevel; level <= config.maxLevel; level += 1) {\n\t\t\t\t\t\tconst routeKey = `${config.routeKeyPrefix}${level}`;\n\t\t\t\t\t\tconst algoliaAttribute = `${config.algoliaAttributeBase}.lvl${level}`;\n\n\t\t\t\t\t\tconst facetValues = indexUiState.refinementList?.[algoliaAttribute];\n\n\t\t\t\t\t\tif (facetValues) {\n\t\t\t\t\t\t\tfacets[routeKey] = facetValues;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst sortOrder = sortOrders.find(order => order.value === indexUiState.sortBy);\n\n\t\t\treturn {\n\t\t\t\tquery: indexUiState.query,\n\t\t\t\tfacets,\n\t\t\t\tsortBy: sortOrder?.routeValue ?? undefined,\n\t\t\t\tlimit: indexUiState.hitsPerPage,\n\t\t\t\tpage: indexUiState.page,\n\t\t\t} satisfies RouteState;\n\t\t},\n\t\trouteToState: (routeState: RouteState) => {\n\t\t\tconst refinementList: Record<string, string[]> = {};\n\n\t\t\tfor (const config of facetConfigurations) {\n\t\t\t\tif (config.type === 'simple') {\n\t\t\t\t\trefinementList[config.algoliaAttribute] = emptyIfUndefined(routeState.facets?.[config.routeKey]);\n\t\t\t\t} else if (config.type === 'hierarchical') {\n\t\t\t\t\tfor (let level = config.minLevel; level <= config.maxLevel; level += 1) {\n\t\t\t\t\t\tconst routeKey = `${config.routeKeyPrefix}${level}`;\n\n\t\t\t\t\t\tconst algoliaAttribute = `${config.algoliaAttributeBase}.lvl${level}`;\n\n\t\t\t\t\t\trefinementList[algoliaAttribute] = emptyIfUndefined(routeState.facets?.[routeKey]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst sortBy = routeState.sortBy\n\t\t\t\t? sortOrders.find(order => order.routeValue === routeState.sortBy)?.value\n\t\t\t\t: undefined;\n\n\t\t\treturn {\n\t\t\t\t[index]: {\n\t\t\t\t\tquery: routeState.query,\n\t\t\t\t\tsortBy,\n\t\t\t\t\thitsPerPage: routeState.limit,\n\t\t\t\t\trefinementList,\n\t\t\t\t\tpage: routeState.page,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Category page configuration\n// ---------------------------------------------------------------------------\n\nfunction checkFacetValueConfigurationMatches(\n\tfacetValueConfiguration: string,\n\trouteStateFacetValue: string[] | undefined\n): boolean {\n\tif (routeStateFacetValue === undefined) {\n\t\treturn false;\n\t}\n\n\tif (routeStateFacetValue.length !== 1) {\n\t\treturn false;\n\t}\n\n\treturn facetValueConfiguration === routeStateFacetValue[0];\n}\n\nfunction checkCategoryPageConfigurationMatches(\n\tcategoryPageConfiguration: CategoryPageConfiguration,\n\trouteStateFacets: {\n\t\tkey: string;\n\t\tvalue: string[] | undefined;\n\t}[]\n): boolean {\n\tconst { facets: facetsConfiguration } = categoryPageConfiguration;\n\n\tlet matches = true;\n\n\tfor (const routeStateFacet of routeStateFacets) {\n\t\tconst facetConfiguration = facetsConfiguration.find(f => f.queryParamName === routeStateFacet.key);\n\n\t\tif (facetConfiguration) {\n\t\t\tif (!checkFacetValueConfigurationMatches(facetConfiguration.value, routeStateFacet.value)) {\n\t\t\t\tmatches = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} else if (routeStateFacet.value !== undefined && routeStateFacet.value.length > 0) {\n\t\t\tmatches = false;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn matches;\n}\n\nfunction writeCommonSearchParams(url: URL, routeState: RouteState) {\n\tif (routeState.query) {\n\t\turl.searchParams.set('query', routeState.query);\n\t}\n\n\tif (routeState.sortBy) {\n\t\turl.searchParams.set('sortBy', routeState.sortBy);\n\t}\n\n\tif (routeState.limit !== undefined) {\n\t\turl.searchParams.set('limit', String(routeState.limit));\n\t}\n\n\tif (routeState.page !== undefined) {\n\t\turl.searchParams.set('page', String(routeState.page));\n\t}\n}\n\nexport function getCanonicalSearchUrl({\n\trouteState,\n\tcanonicalOrigin,\n\tcategoryPageConfigurations,\n\tfacetConfigurations,\n\tindexName,\n\tpageLimits,\n\tsortOrders,\n}: {\n\trouteState: RouteState;\n\tcanonicalOrigin: string;\n\tcategoryPageConfigurations: CategoryPageConfiguration[];\n\tfacetConfigurations: FacetConfiguration[];\n\tindexName: string;\n\tpageLimits: number[];\n\tsortOrders: SearchSortOrder[];\n}): string {\n\tconst canonicalUrl = new URL('/search', canonicalOrigin);\n\tconst allFacetingKeys = getAllFacetingKeys(facetConfigurations);\n\tconst matchingCategoryPage = getMatchingCategoryPageFromRouteState(\n\t\trouteState,\n\t\tcategoryPageConfigurations,\n\t\tallFacetingKeys\n\t);\n\n\tif (matchingCategoryPage) {\n\t\tconst categoryUrl = safeUrl(matchingCategoryPage.categoryPageUrl, canonicalOrigin);\n\t\tif (categoryUrl) {\n\t\t\tcanonicalUrl.pathname = categoryUrl.pathname;\n\t\t}\n\t}\n\n\tconst sortOrder = sortOrders.find(order => order.routeValue === routeState.sortBy);\n\twriteCommonSearchParams(canonicalUrl, {\n\t\tquery: routeState.query,\n\t\tsortBy: sortOrder?.routeValue && sortOrder.value !== indexName ? sortOrder.routeValue : undefined,\n\t\tlimit: routeState.limit !== pageLimits[0] ? routeState.limit : undefined,\n\t\tpage: routeState.page !== undefined && routeState.page > 1 ? routeState.page : undefined,\n\t});\n\n\tconst facets = Object.fromEntries(\n\t\t[...new Set(allFacetingKeys)].sort().map(key => [key, [...new Set(routeState.facets?.[key] ?? [])].sort()])\n\t);\n\tconst categoryFacetKeys = new Set(matchingCategoryPage?.facets.map(facet => facet.queryParamName) ?? []);\n\twriteFacetsSearchParams(canonicalUrl, facets, categoryFacetKeys);\n\n\treturn canonicalUrl.href;\n}\n\n// ---------------------------------------------------------------------------\n// Router — URL creation and parsing\n// ---------------------------------------------------------------------------\n\nexport function makeRouter(\n\tcategoryPageConfigurations: CategoryPageConfiguration[],\n\tfacetConfigurations: FacetConfiguration[],\n\tuserSearchFilters: UserSearchFilter[] = [],\n\tinitialUrl?: string,\n\ttitlePostfix: string | null = '',\n\tsearchPageTitle = 'Search',\n\thydration?: { initialRouteState: RouteState; isReady: () => boolean }\n) {\n\tconst normalizedTitlePostfix = titlePostfix ?? '';\n\tconst initialLocation = hydration ? safeUrl(initialUrl ?? '') : null;\n\tif (initialLocation && hydration) {\n\t\twriteCommonSearchParams(initialLocation, hydration.initialRouteState);\n\t\twriteFacetsSearchParams(initialLocation, hydration.initialRouteState.facets);\n\t\tfor (const [key, value] of Object.entries(hydration.initialRouteState.filters ?? {})) {\n\t\t\tinitialLocation.searchParams.set(key, value);\n\t\t}\n\t}\n\tconst allFacetingKeys = getAllFacetingKeys(facetConfigurations);\n\tconst allFacetingKeysSet = new Set<string>(allFacetingKeys);\n\tconst userFilterKeysSet = new Set<string>(userSearchFilters.map(f => f.token));\n\tconst preserveCustomKeysSet = new Set<string>([viewModeKey, 'ownership', 'geographicAvailability']);\n\tconst searchParamKeysSet = new Set<string>([\n\t\t'query',\n\t\t'sortBy',\n\t\t'limit',\n\t\t'page',\n\t\t...allFacetingKeys,\n\t\t...userFilterKeysSet,\n\t\t...preserveCustomKeysSet,\n\t]);\n\tconst categoryPagesByCategoryPageUrl: Map<string, CategoryPageConfiguration> = new Map<\n\t\tstring,\n\t\tCategoryPageConfiguration\n\t>();\n\n\tfor (const configuration of categoryPageConfigurations) {\n\t\tcategoryPagesByCategoryPageUrl.set(configuration.categoryPageUrl, configuration);\n\t}\n\n\tconst router = history<RouteState>({\n\t\tgetLocation: () => {\n\t\t\tif (typeof window !== 'undefined' && (!hydration || hydration.isReady())) {\n\t\t\t\treturn window.location;\n\t\t\t}\n\n\t\t\tconst location = initialLocation ?? safeUrl(initialUrl ?? '');\n\t\t\tif (!location) {\n\t\t\t\tthrow new Error('A valid initial URL is required to render search server-side.');\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tancestorOrigins: {\n\t\t\t\t\tcontains: () => false,\n\t\t\t\t\titem: () => null,\n\t\t\t\t\tlength: 0,\n\t\t\t\t\t[Symbol.iterator]: function (): IterableIterator<string> {\n\t\t\t\t\t\treturn [][Symbol.iterator]();\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tassign: () => {\n\t\t\t\t\tthrow new Error('Search routing cannot navigate while rendering server-side.');\n\t\t\t\t},\n\t\t\t\thash: location.hash,\n\t\t\t\thost: location.host,\n\t\t\t\thostname: location.hostname,\n\t\t\t\thref: location.href,\n\t\t\t\torigin: location.origin,\n\t\t\t\tpathname: location.pathname,\n\t\t\t\tport: location.port,\n\t\t\t\tprotocol: location.protocol,\n\t\t\t\treload: () => {\n\t\t\t\t\tthrow new Error('Search routing cannot reload while rendering server-side.');\n\t\t\t\t},\n\t\t\t\treplace: () => {\n\t\t\t\t\tthrow new Error('Search routing cannot navigate while rendering server-side.');\n\t\t\t\t},\n\t\t\t\tsearch: location.search,\n\t\t\t\ttoString: () => location.toString(),\n\t\t\t};\n\t\t},\n\t\tcleanUrlOnDispose: false,\n\t\tcreateURL({ location, routeState }: { location: { href: string }; routeState: RouteState }) {\n\t\t\ttry {\n\t\t\t\t// detect if we match a category page\n\t\t\t\tconst matchingCategoryPage = getMatchingCategoryPageFromRouteState(\n\t\t\t\t\trouteState,\n\t\t\t\t\tcategoryPageConfigurations,\n\t\t\t\t\tallFacetingKeys\n\t\t\t\t);\n\n\t\t\t\tconst currentUrl = safeUrl(location.href);\n\t\t\t\tif (!currentUrl) {\n\t\t\t\t\treturn location.href;\n\t\t\t\t}\n\n\t\t\t\tif (matchingCategoryPage) {\n\t\t\t\t\tconst categoryPageUrl = safeUrl(matchingCategoryPage.categoryPageUrl, location.href);\n\t\t\t\t\tif (categoryPageUrl) {\n\t\t\t\t\t\twriteCommonSearchParams(categoryPageUrl, routeState);\n\t\t\t\t\t\tconst categoryFacetKeys = new Set(\n\t\t\t\t\t\t\tmatchingCategoryPage.facets.map(facetConfiguration => facetConfiguration.queryParamName)\n\t\t\t\t\t\t);\n\t\t\t\t\t\twriteFacetsSearchParams(categoryPageUrl, routeState.facets, categoryFacetKeys);\n\t\t\t\t\t\twriteUserFilterSearchParams(categoryPageUrl, userSearchFilters, currentUrl);\n\t\t\t\t\t\tpreserveCustomQueryParams(currentUrl, categoryPageUrl, preserveCustomKeysSet);\n\t\t\t\t\t\tpreserveNonSearchQueryParams(currentUrl, categoryPageUrl, searchParamKeysSet);\n\n\t\t\t\t\t\treturn categoryPageUrl.href;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst url = safeUrl('/search', location.href);\n\t\t\t\tif (!url) {\n\t\t\t\t\treturn location.href;\n\t\t\t\t}\n\n\t\t\t\twriteCommonSearchParams(url, routeState);\n\t\t\t\twriteFacetsSearchParams(url, routeState.facets);\n\t\t\t\twriteUserFilterSearchParams(url, userSearchFilters, currentUrl);\n\t\t\t\tpreserveCustomQueryParams(currentUrl, url, preserveCustomKeysSet);\n\t\t\t\tpreserveNonSearchQueryParams(currentUrl, url, searchParamKeysSet);\n\n\t\t\t\treturn url.href;\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[search] router.createURL failed', err);\n\t\t\t\treturn location.href;\n\t\t\t}\n\t\t},\n\n\t\tparseURL({ location }: { location: { href: string } }) {\n\t\t\ttry {\n\t\t\t\tconst locationUrl = safeUrl(location.href);\n\t\t\t\tif (!locationUrl) {\n\t\t\t\t\treturn {};\n\t\t\t\t}\n\t\t\t\tconst locationPathname = locationUrl.pathname;\n\n\t\t\t\tconst matchingCategoryPage = categoryPagesByCategoryPageUrl.get(locationPathname);\n\n\t\t\t\tconst routeState: RouteState = {};\n\n\t\t\t\tconst addRouteStateFacetValues = (key: string, values: string[]) => {\n\t\t\t\t\tif (values.length === 0) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\trouteState.facets ??= {};\n\t\t\t\t\trouteState.facets[key] ??= [];\n\n\t\t\t\t\tfor (const value of values) {\n\t\t\t\t\t\trouteState.facets[key].push(value);\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tif (matchingCategoryPage) {\n\t\t\t\t\tfor (const facetConfiguration of matchingCategoryPage.facets) {\n\t\t\t\t\t\taddRouteStateFacetValues(facetConfiguration.queryParamName, [facetConfiguration.value]);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst queryParams = locationUrl.searchParams;\n\n\t\t\t\tfor (const [paramName, paramValue] of queryParams.entries()) {\n\t\t\t\t\tif (allFacetingKeysSet.has(paramName)) {\n\t\t\t\t\t\tif (matchingCategoryPage?.facets.some(facet => facet.queryParamName === paramName)) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\taddRouteStateFacetValues(\n\t\t\t\t\t\t\tparamName,\n\t\t\t\t\t\t\tparamValue\n\t\t\t\t\t\t\t\t.split(delimiter)\n\t\t\t\t\t\t\t\t.map(v => getTrimmedOrUndefinedIfStringEmpty(v))\n\t\t\t\t\t\t\t\t.filter((v): v is string => v !== undefined)\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (userFilterKeysSet.has(paramName)) {\n\t\t\t\t\t\trouteState.filters ??= {};\n\t\t\t\t\t\trouteState.filters[paramName] = paramValue;\n\t\t\t\t\t} else if (paramName === 'query') {\n\t\t\t\t\t\trouteState.query = getTrimmedOrUndefinedIfStringEmpty(paramValue);\n\t\t\t\t\t} else if (paramName === 'sortBy') {\n\t\t\t\t\t\trouteState.sortBy = paramValue;\n\t\t\t\t\t} else if (paramName === 'limit') {\n\t\t\t\t\t\tconst limit = parseInt(paramValue, 10);\n\n\t\t\t\t\t\tif (Number.isFinite(limit) && limit > 0) {\n\t\t\t\t\t\t\trouteState.limit = limit;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (paramName === 'page') {\n\t\t\t\t\t\tconst page = parseInt(paramValue, 10);\n\n\t\t\t\t\t\tif (Number.isFinite(page) && page >= 1) {\n\t\t\t\t\t\t\trouteState.page = page;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn routeState;\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[search] router.parseURL failed', err);\n\t\t\t\treturn {};\n\t\t\t}\n\t\t},\n\n\t\twindowTitle(routeState: RouteState) {\n\t\t\ttry {\n\t\t\t\tconst matchingCategoryPage = getMatchingCategoryPageFromRouteState(\n\t\t\t\t\trouteState,\n\t\t\t\t\tcategoryPageConfigurations,\n\t\t\t\t\tallFacetingKeys\n\t\t\t\t);\n\n\t\t\t\tif (matchingCategoryPage?.isPageTitleOverride) {\n\t\t\t\t\treturn matchingCategoryPage.pageTitle;\n\t\t\t\t}\n\t\t\t\treturn `${matchingCategoryPage?.pageTitle ?? searchPageTitle} ${normalizedTitlePostfix}`.trim();\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('[search] router.windowTitle failed', err);\n\t\t\t\treturn `${searchPageTitle} ${normalizedTitlePostfix}`.trim();\n\t\t\t}\n\t\t},\n\t});\n\n\tlet lastRoute = router.read();\n\tconst write = router.write.bind(router);\n\trouter.write = routeState => {\n\t\tif (!hydration || hydration.isReady()) {\n\t\t\tlastRoute = routeState;\n\t\t\twrite(routeState);\n\t\t}\n\t};\n\tlet notify: ((routeState: RouteState) => void) | undefined;\n\tconst onUpdate = router.onUpdate.bind(router);\n\trouter.onUpdate = callback => {\n\t\tnotify = routeState => {\n\t\t\tlastRoute = routeState;\n\t\t\tcallback(routeState);\n\t\t};\n\t\tonUpdate(notify);\n\t};\n\treturn Object.assign(router, {\n\t\tsyncFromBrowser: () => {\n\t\t\tconst route = router.read();\n\t\t\tif (!isEqual(route, lastRoute)) {\n\t\t\t\tnotify?.(route);\n\t\t\t}\n\t\t},\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// Convert search categories to category page configurations\n// ---------------------------------------------------------------------------\n\nexport function convertSearchCategoriesToCategoryPageConfiguration(\n\tcategories: SearchCategory[]\n): CategoryPageConfiguration[] {\n\treturn (categories ?? [])\n\t\t.map((category): CategoryPageConfiguration | null => {\n\t\t\tif (!category) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst categoryPageUrl = category.categoryPageUrl;\n\t\t\tif (!categoryPageUrl) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif (!category.facetRouteKey) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcategoryPageUrl,\n\t\t\t\tfacets: [\n\t\t\t\t\t{\n\t\t\t\t\t\tqueryParamName: category.facetRouteKey,\n\t\t\t\t\t\tvalue: category.displayName,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tpageTitle: category.pageTitle,\n\t\t\t\tisPageTitleOverride: category.isPageTitleOverride,\n\t\t\t} satisfies CategoryPageConfiguration;\n\t\t})\n\t\t.filter((x): x is CategoryPageConfiguration => x !== null);\n}\n","import { useEffect, useState } from 'react';\n\nexport const hydrationSettledAttribute = 'data-hydration-settled';\n\n/**\n * Reports when the calling component has stopped re-rendering after hydration.\n *\n * End-to-end tests need to know that no further widget can mount, because mounting one calls\n * `addWidgets`, which schedules a search once `ResetScheduleSearch` has restored `scheduleSearch`.\n * The timer is re-armed by every render and fires from a macrotask, so once it resolves any search\n * deferred to a microtask has already reached the network layer.\n *\n * The caller must subscribe to InstantSearch renders (via `useInstantSearch`) so that search\n * cycles re-arm the timer too.\n */\nexport default function useHydrationSettled(): boolean {\n\tconst [isSettled, setIsSettled] = useState(false);\n\n\tuseEffect(() => {\n\t\tconst timeoutId = window.setTimeout(() => setIsSettled(true), 0);\n\t\treturn () => window.clearTimeout(timeoutId);\n\t});\n\n\treturn isSettled;\n}\n","import { useMemo } from 'react';\nimport type { ConfigureProps } from 'react-instantsearch';\n\nimport { useUserSearchFilterContext } from './user-search-filter-context';\n\nconst parameterBlacklist = new Set(['facets']);\n\nexport default function useEffectiveSearchParameters(searchParameters?: ConfigureProps) {\n\tconst { selectedFilterOptions, userSearchFilters } = useUserSearchFilterContext();\n\n\treturn useMemo(() => {\n\t\tconst mergedParams = { ...(searchParameters ?? {}) };\n\t\tconst userFilters = Array.isArray(userSearchFilters) ? userSearchFilters : [];\n\t\tconst selectedOptions = userFilters\n\t\t\t.map(filter => {\n\t\t\t\tconst selectedToken = selectedFilterOptions[filter.token];\n\t\t\t\treturn selectedToken ? filter.options?.find(option => option.token === selectedToken)?.algoliaValue : null;\n\t\t\t})\n\t\t\t.filter((value): value is string => typeof value === 'string' && value.length > 0);\n\t\tconst filterParts = [mergedParams.filters, ...selectedOptions].filter(\n\t\t\t(value): value is string => typeof value === 'string' && value.length > 0\n\t\t);\n\t\tif (filterParts.length > 0) {\n\t\t\tmergedParams.filters = filterParts.join(' AND ');\n\t\t} else {\n\t\t\tdelete mergedParams.filters;\n\t\t}\n\n\t\treturn Object.fromEntries(Object.entries(mergedParams).filter(([key]) => !parameterBlacklist.has(key)));\n\t}, [searchParameters, userSearchFilters, selectedFilterOptions]);\n}\n","import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { CommandSentence } from '@faithlife/command-sentence-control';\nimport { Button, Typography } from '@faithlife/commerce-components';\nimport { ChevronDown } from 'lucide-react';\nimport { UiState } from 'instantsearch.js';\nimport type { InstantSearchServerState } from 'react-instantsearch-core';\nimport {\n\tConfigure,\n\tConfigureProps,\n\tInstantSearch,\n\tInstantSearchProps,\n\tInstantSearchSSRProvider,\n} from 'react-instantsearch';\nimport {\n\tPagination,\n\tuseHitsPerPage,\n\tuseInstantSearch,\n\tuseCurrentRefinements,\n\tusePagination,\n\tuseSearchBox,\n\tuseSortBy,\n} from 'react-instantsearch';\nimport Drawer from '../shared/drawer';\nimport ScrollThresholdBar from '../shared/scroll-threshold-bar';\nimport {\n\tDropdownMenu,\n\tDropdownMenuContent,\n\tDropdownMenuRadioGroup,\n\tDropdownMenuRadioItem,\n\tDropdownMenuTrigger,\n} from '../shared/dropdown-menu';\nimport useScreensize from '../../util/hooks/use-screensize';\n\nimport { cn } from '../../util/cn';\nimport { PerUserDataContextProvider, useCurrentUser } from '../per-user-data/per-user-data-context';\n\nimport { safeJsonParse } from '../../util/safe-json-parse';\nimport { useLocalization } from '../../localization';\nimport { useLocation } from '../../location';\nimport ErrorBoundary from '../error-boundary';\nimport { BooksByAuthor } from '../shared/books-by-author';\nimport { AuthorBatch } from '../../hooks/use-author';\nimport type { AuthorInfo } from '../../hooks/use-author';\nimport { PublisherBatch } from '../../hooks/use-publisher';\nimport type { SectionContentViewModel } from '../../builder';\nimport CategoryContent from './category-content';\nimport {\n\tUserSearchFilter,\n\tUserSearchFilters,\n\tUserSearchFilterProvider,\n\tuseUserSearchFilterContext,\n} from './user-search-filter-context';\nimport { Categories } from './filters';\nimport CurrentQueryRefinement, { CurrentRefinements } from './refinements';\nimport HiddenFacetRefinements from './hidden-facet-refinements';\nimport ProductHits from './products';\nimport SortByAccordion from './sort-by-accordion';\nimport HitsPerPageAccordion from './hits-per-page-accordion';\nimport { SearchCategory, SearchSortOrder } from './types';\nimport {\n\tconvertSearchCategoriesToCategoryPageConfiguration,\n\tgetCanonicalSearchUrl,\n\tmakeRouter,\n\tmakeStateMapping,\n} from './routing';\nimport type { FacetConfiguration, RouteState } from './routing';\nexport { SearchResourcesContext, useSearchResources } from './search-resources';\nimport { SearchResourcesContext, useSearchResources } from './search-resources';\nimport { useSearchImpressions } from './hooks/use-search-impressions';\nimport { useSearchAnalytics } from './hooks/use-search-analytics';\nexport { AlgoliaSearchContextProvider, useAlgoliaSearch } from './algolia-search-context';\nimport { AlgoliaSearchContextProvider, useAlgoliaSearch } from './algolia-search-context';\nimport { useViewMode, ViewMode, ViewModeProvider } from './use-view-mode';\nimport useHydrationSettled, { hydrationSettledAttribute } from './use-hydration-settled';\nimport useEffectiveSearchParameters from './use-effective-search-parameters';\n\n// ---------------------------------------------------------------------------\n// AlgoliaSSRProvider / AlgoliaProvider — InstantSearch + Configure wrappers\n// ---------------------------------------------------------------------------\n\ntype AlgoliaSearchParameters = Record<string, any>;\n\ntype ConfigurableConfigureProps = Pick<\n\tConfigureProps,\n\t'attributesToHighlight' | 'attributesToRetrieve' | 'queryType' | 'restrictSearchableAttributes'\n> & { searchParameters?: AlgoliaSearchParameters; userSearchFilters?: UserSearchFilter[] };\n\ntype AlgoliaProviderProps<TUiState extends UiState, TRouteState> = Pick<\n\tInstantSearchProps<TUiState, TRouteState>,\n\t'routing' | 'searchClient'\n> &\n\tConfigurableConfigureProps & { initialViewMode: ViewMode };\n\nfunction AlgoliaSSRProvider<TUiState extends UiState = UiState, TRouteState = TUiState>(\n\tprops: React.PropsWithChildren<AlgoliaProviderProps<TUiState, TRouteState>>\n) {\n\treturn <AlgoliaProvider {...props} />;\n}\n\nfunction AlgoliaProvider<TUiState extends UiState = UiState, TRouteState = TUiState>({\n\tattributesToHighlight,\n\tattributesToRetrieve,\n\tqueryType,\n\trestrictSearchableAttributes,\n\trouting,\n\tsearchClient,\n\tsearchParameters,\n\tinitialViewMode,\n\tchildren,\n}: React.PropsWithChildren<AlgoliaProviderProps<TUiState, TRouteState>>) {\n\tconst { indexName } = useAlgoliaSearch();\n\n\treturn (\n\t\t<ViewModeProvider initialViewMode={initialViewMode}>\n\t\t\t<InstantSearch\n\t\t\t\tfuture={{\n\t\t\t\t\tpreserveSharedStateOnUnmount: true,\n\t\t\t\t}}\n\t\t\t\tindexName={indexName}\n\t\t\t\tinsights\n\t\t\t\trouting={routing}\n\t\t\t\tsearchClient={searchClient}\n\t\t\t>\n\t\t\t\t<ConfigureCore\n\t\t\t\t\tattributesToHighlight={attributesToHighlight}\n\t\t\t\t\tattributesToRetrieve={attributesToRetrieve}\n\t\t\t\t\tqueryType={queryType}\n\t\t\t\t\trestrictSearchableAttributes={restrictSearchableAttributes}\n\t\t\t\t\tsearchParameters={searchParameters}\n\t\t\t\t/>\n\t\t\t\t{children}\n\t\t\t</InstantSearch>\n\t\t</ViewModeProvider>\n\t);\n}\n\nfunction ConfigureCore({\n\tattributesToHighlight,\n\tattributesToRetrieve,\n\tqueryType,\n\trestrictSearchableAttributes,\n\tsearchParameters,\n}: ConfigurableConfigureProps) {\n\tconst props = useEffectiveSearchParameters(searchParameters);\n\n\treturn (\n\t\t<Configure\n\t\t\tattributesToHighlight={attributesToHighlight}\n\t\t\tattributesToRetrieve={attributesToRetrieve}\n\t\t\tdistinct\n\t\t\tqueryType={queryType}\n\t\t\trestrictSearchableAttributes={restrictSearchableAttributes}\n\t\t\tclickAnalytics\n\t\t\t{...props}\n\t\t/>\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Icons\n// ---------------------------------------------------------------------------\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nfunction CloseIcon({ className, fillColor: _fillColor, ...rest }: any) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\tfill=\"none\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 16 16\"\n\t\t\twidth=\"16\"\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...rest}\n\t\t>\n\t\t\t<path d=\"M12.5 3.5L3.5 12.5M3.5 3.5l9 9\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeWidth=\"1.5\" />\n\t\t</svg>\n\t);\n}\n\nfunction FilterIcon({ className, ...rest }: any) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\tfill=\"none\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 16 16\"\n\t\t\twidth=\"16\"\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...rest}\n\t\t>\n\t\t\t<path d=\"M2 4h12M4 8h8M6 12h4\" stroke=\"currentColor\" strokeLinecap=\"round\" strokeWidth=\"1.5\" />\n\t\t</svg>\n\t);\n}\n\nfunction FilterAndSortButton({ onClick, testId = 'filter-and-sort-button' }: { onClick: () => void; testId?: string }) {\n\tconst resources = useSearchResources();\n\n\treturn (\n\t\t<button\n\t\t\tclassName=\"inline-flex cursor-pointer items-center gap-sp8 rounded-[4px] border border-primary-500 px-sp16 py-sp16 text-primary-500 focus:outline-0 focus:ring-0\"\n\t\t\tdata-testid={testId}\n\t\t\tonClick={onClick}\n\t\t\ttype=\"button\"\n\t\t>\n\t\t\t<FilterIcon />\n\t\t\t<Typography className=\"text-primary-500 font-medium leading-[100%]\" variant=\"bodySmall\">\n\t\t\t\t{resources['filterAndSort']}\n\t\t\t</Typography>\n\t\t</button>\n\t);\n}\n\nfunction LayoutGridIcon({ className, ...rest }: any) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\tfill=\"none\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 16 16\"\n\t\t\twidth=\"16\"\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...rest}\n\t\t>\n\t\t\t<rect height=\"5\" rx=\"1\" stroke=\"currentColor\" width=\"5\" x=\"1.5\" y=\"1.5\" />\n\t\t\t<rect height=\"5\" rx=\"1\" stroke=\"currentColor\" width=\"5\" x=\"9.5\" y=\"1.5\" />\n\t\t\t<rect height=\"5\" rx=\"1\" stroke=\"currentColor\" width=\"5\" x=\"1.5\" y=\"9.5\" />\n\t\t\t<rect height=\"5\" rx=\"1\" stroke=\"currentColor\" width=\"5\" x=\"9.5\" y=\"9.5\" />\n\t\t</svg>\n\t);\n}\n\nfunction LayoutListIcon({ className, ...rest }: any) {\n\treturn (\n\t\t<svg\n\t\t\tclassName={className}\n\t\t\tfill=\"none\"\n\t\t\theight=\"16\"\n\t\t\tviewBox=\"0 0 16 16\"\n\t\t\twidth=\"16\"\n\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t{...rest}\n\t\t>\n\t\t\t<rect height=\"3\" rx=\"1\" stroke=\"currentColor\" width=\"14\" x=\"1\" y=\"1.5\" />\n\t\t\t<rect height=\"3\" rx=\"1\" stroke=\"currentColor\" width=\"14\" x=\"1\" y=\"6.5\" />\n\t\t\t<rect height=\"3\" rx=\"1\" stroke=\"currentColor\" width=\"14\" x=\"1\" y=\"11.5\" />\n\t\t</svg>\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// Layout buttons — grid/list toggle\n// ---------------------------------------------------------------------------\n\nconst LayoutButtonOptions = [\n\t{ label: 'Grid Layout', value: ViewMode.grid, icon: LayoutGridIcon, additionalClassNames: 'lg:p-[6px]' },\n\t{ label: 'List Layout', value: ViewMode.list, icon: LayoutListIcon, additionalClassNames: 'lg:px-[3px] lg:py-[6px]' },\n];\n\nfunction LayoutButtons({\n\tcurrentLayoutType,\n\tsetLayoutType,\n}: {\n\tcurrentLayoutType: ViewMode;\n\tsetLayoutType: (mode: ViewMode) => void;\n}) {\n\treturn (\n\t\t<div className=\"flex gap-[6px]\">\n\t\t\t{LayoutButtonOptions.map(option => {\n\t\t\t\tconst isSelected = currentLayoutType === option.value;\n\t\t\t\tconst IconComponent = option.icon;\n\n\t\t\t\treturn (\n\t\t\t\t\t<button\n\t\t\t\t\t\tkey={option.value}\n\t\t\t\t\t\taria-label={option.label}\n\t\t\t\t\t\taria-pressed={isSelected}\n\t\t\t\t\t\tonClick={() => setLayoutType(option.value)}\n\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t'px-sp16 py-sp16',\n\t\t\t\t\t\t\t'inline-flex items-center gap-sp8',\n\t\t\t\t\t\t\t'rounded-[4px] border border-primary-500 lg:border-0',\n\t\t\t\t\t\t\t'cursor-pointer',\n\t\t\t\t\t\t\t'text-black-100 aria-pressed:text-primary-400',\n\t\t\t\t\t\t\toption.additionalClassNames\n\t\t\t\t\t\t)}\n\t\t\t\t\t>\n\t\t\t\t\t\t<IconComponent />\n\t\t\t\t\t</button>\n\t\t\t\t);\n\t\t\t})}\n\t\t</div>\n\t);\n}\n\n// ---------------------------------------------------------------------------\n// ScrollToTopOnPaginationChange\n// ---------------------------------------------------------------------------\n\nfunction DesktopSearchControl({\n\tprefixText,\n\tvalue,\n\titems,\n\tonChange,\n\ttestId,\n\tcontentClassName,\n}: {\n\tprefixText: string;\n\tvalue: string | number;\n\titems: { label: string; value: string | number }[];\n\tonChange: (value: string | number) => void;\n\ttestId: string;\n\tcontentClassName?: string;\n}) {\n\tconst selectedItem = useMemo(() => {\n\t\treturn items.find(item => item.value === value) ?? items[0];\n\t}, [items, value]);\n\n\tconst selectedLabel = selectedItem?.label ?? value.toString();\n\n\tconst handleValueChange = useCallback(\n\t\t(newValue: string) => {\n\t\t\tconst matchedItem = items.find(item => item.value.toString() === newValue);\n\t\t\tif (matchedItem) {\n\t\t\t\tonChange(matchedItem.value);\n\t\t\t}\n\t\t},\n\t\t[items, onChange]\n\t);\n\n\treturn (\n\t\t<DropdownMenu>\n\t\t\t<DropdownMenuTrigger\n\t\t\t\tclassName=\"inline-flex cursor-pointer items-center whitespace-nowrap border-0 bg-transparent p-0 text-black [&[data-state=open]>svg]:rotate-180\"\n\t\t\t\tdata-testid={testId}\n\t\t\t>\n\t\t\t\t<span className=\"mr-[3px] font-normal\">{prefixText}</span>\n\t\t\t\t<span className=\"font-semibold\">{selectedLabel}</span>\n\t\t\t\t<ChevronDown className=\"ml-[2px] h-4 w-4 transition-transform\" />\n\t\t\t</DropdownMenuTrigger>\n\t\t\t<DropdownMenuContent className={contentClassName}>\n\t\t\t\t<DropdownMenuRadioGroup onValueChange={handleValueChange} value={value.toString()}>\n\t\t\t\t\t{items.map(item => (\n\t\t\t\t\t\t<DropdownMenuRadioItem\n\t\t\t\t\t\t\tclassName=\"w-full data-[state=checked]:bg-primary-100 active:bg-secondary-100 focus-visible:ring-2 focus-visible:ring-primary\"\n\t\t\t\t\t\t\tkey={item.value.toString()}\n\t\t\t\t\t\t\tvalue={item.value.toString()}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{item.label}\n\t\t\t\t\t\t</DropdownMenuRadioItem>\n\t\t\t\t\t))}\n\t\t\t\t</DropdownMenuRadioGroup>\n\t\t\t</DropdownMenuContent>\n\t\t</DropdownMenu>\n\t);\n}\n\nfunction ScrollToTopOnPaginationChange() {\n\tconst { currentRefinement } = usePagination();\n\n\tuseEffect(() => {\n\t\twindow.scrollTo({ top: 0, behavior: 'smooth' });\n\t}, [currentRefinement]);\n\n\treturn null;\n}\n\nfunction NoResultsState({ query }: { query: string }) {\n\tconst resources = useSearchResources();\n\tconst normalizedQuery = query.trim();\n\tconst noResultsMessageTemplate = resources['noResults'];\n\tconst searchTips = [resources['checkSpelling'], resources['differentKeywords'], resources['lessSpecific']];\n\n\treturn (\n\t\t<section className=\"mx-auto flex w-full max-w-[640px] flex-col items-start gap-sp48 rounded-md border border-grey-200 bg-grey-50 p-sp60 text-left shadow-sm\">\n\t\t\t<Typography className=\"break-words text-left font-semibold text-black\" tag=\"p\" variant=\"bodyLarge\">\n\t\t\t\t{normalizedQuery && (\n\t\t\t\t\t<CommandSentence Container={React.Fragment} template={noResultsMessageTemplate}>\n\t\t\t\t\t\t<CommandSentence.Field name=\"QUERY\">{normalizedQuery}</CommandSentence.Field>\n\t\t\t\t\t</CommandSentence>\n\t\t\t\t)}\n\t\t\t</Typography>\n\t\t\t<div className=\"flex flex-col items-start gap-sp8 text-left text-black\">\n\t\t\t\t<Typography className=\"font-semibold text-black\" tag=\"p\" variant=\"bodyRegular\">\n\t\t\t\t\t{resources['searchTips']}\n\t\t\t\t</Typography>\n\t\t\t\t<ul className=\"list-disc pl-5\">\n\t\t\t\t\t{searchTips.map(tip => (\n\t\t\t\t\t\t<li className=\"bodyMd\" key={tip}>\n\t\t\t\t\t\t\t{tip}\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t\t<Button onClick={() => window.location.assign('/search')} type=\"button\" variant=\"primary\">\n\t\t\t\t{resources['seeAllProducts']}\n\t\t\t</Button>\n\t\t</section>\n\t);\n}\n// ---------------------------------------------------------------------------\n// FilterSortLayout — main search page layout\n// ---------------------------------------------------------------------------\n\nconst FilterSortLayout = ({\n\twishListsProductsUrl,\n\tenableAuthorBioView,\n\tpageLimits,\n\tsortOrders,\n\tsearchResultsAbove,\n\tcategories,\n}: {\n\twishListsProductsUrl: string;\n\tenableAuthorBioView: boolean;\n\tpageLimits: number[];\n\tsortOrders: SearchSortOrder[];\n\tsearchResultsAbove?: SectionContentViewModel[];\n\tcategories: SearchCategory[];\n}) => {\n\tconst resources = useSearchResources();\n\tconst authorBioResources = useLocalization('CommerceWeb.Resources.Search.AuthorBio');\n\tconst { href } = useLocation();\n\tconst renderCategoryHeading = useCallback(() => {\n\t\tconst path = new URL(href).pathname.toLowerCase();\n\t\tconst category = categories.find(category => category.categoryPageUrl.toLowerCase() === path);\n\t\treturn category ? (\n\t\t\t<Typography className=\"font-semibold text-primary-400\" tag=\"h1\" variant=\"bodyLarge\">\n\t\t\t\t{category.displayName}\n\t\t\t</Typography>\n\t\t) : null;\n\t}, [categories, href]);\n\n\tconst [isMobileFilterOpen, setIsMobileFilterOpen] = useState(false);\n\n\tconst { viewMode, setViewMode } = useViewMode();\n\tconst { isMobile, isDesktop } = useScreensize();\n\tconst isHydrationSettled = useHydrationSettled();\n\tconst { selectedFilterOptions } = useUserSearchFilterContext();\n\n\tuseSearchImpressions();\n\tuseSearchAnalytics();\n\tconst { results } = useInstantSearch();\n\tconst { query } = useSearchBox();\n\tconst hasNoSearchResults = !results.__isArtificial && results.nbHits === 0;\n\tconst shouldShowResultsRoute = !hasNoSearchResults;\n\tconst { items: currentRefinements } = useCurrentRefinements();\n\n\tconst allSortItems = useMemo(\n\t\t() =>\n\t\t\tsortOrders.map(sortOrder => ({\n\t\t\t\tlabel: resources[sortOrder.label] ?? sortOrder.label,\n\t\t\t\tvalue: sortOrder.value,\n\t\t\t\tisPrepub: sortOrder.isPrepub,\n\t\t\t})),\n\t\t[resources, sortOrders]\n\t);\n\tconst { currentRefinement: currentSortBy, refine: refineSortBy } = useSortBy({ items: allSortItems });\n\tconst hasPrepubCategory = currentRefinements.some(\n\t\titem =>\n\t\t\titem.attribute === 'categories.lvl1' &&\n\t\t\titem.refinements?.some(refinement => refinement.value === 'status > prepub')\n\t);\n\tconst sortItems = useMemo(\n\t\t() => allSortItems.filter(item => !item.isPrepub || hasPrepubCategory || item.value === currentSortBy),\n\t\t[allSortItems, currentSortBy, hasPrepubCategory]\n\t);\n\n\tconst hitsPerPageItems = useMemo(\n\t\t() => pageLimits.map((pageLimit, index) => ({ default: index === 0, label: String(pageLimit), value: pageLimit })),\n\t\t[pageLimits]\n\t);\n\tconst { items: showItems, refine: refineHitsPerPage } = useHitsPerPage({\n\t\titems: hitsPerPageItems,\n\t});\n\tconst currentHitsPerPage = showItems.find(item => item.isRefined)?.value ?? hitsPerPageItems[0].value;\n\tconst searchStateKey = useMemo(\n\t\t() =>\n\t\t\tJSON.stringify({\n\t\t\t\tquery,\n\t\t\t\tsortBy: currentSortBy,\n\t\t\t\thitsPerPage: currentHitsPerPage,\n\t\t\t\trefinements: currentRefinements\n\t\t\t\t\t.map(item => ({\n\t\t\t\t\t\tattribute: item.attribute,\n\t\t\t\t\t\tvalues: item.refinements.map(refinement => String(refinement.value)).sort(),\n\t\t\t\t\t}))\n\t\t\t\t\t.sort((left, right) => left.attribute.localeCompare(right.attribute)),\n\t\t\t\tuserFilters: selectedFilterOptions,\n\t\t\t}),\n\t\t[currentHitsPerPage, currentRefinements, currentSortBy, query, selectedFilterOptions]\n\t);\n\tconst previousSearchStateKey = useRef<string | undefined>(undefined);\n\tuseEffect(() => {\n\t\tif (!isHydrationSettled) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\t!isDesktop &&\n\t\t\tpreviousSearchStateKey.current !== undefined &&\n\t\t\tpreviousSearchStateKey.current !== searchStateKey\n\t\t) {\n\t\t\twindow.scrollTo({ top: 0, behavior: 'smooth' });\n\t\t}\n\n\t\tpreviousSearchStateKey.current = searchStateKey;\n\t}, [isDesktop, isHydrationSettled, searchStateKey]);\n\n\tconst toggleFilter = useCallback(() => setIsMobileFilterOpen(prev => !prev), []);\n\n\tconst staticFilterAndSortControlsRef = useRef<HTMLDivElement>(null);\n\tconst closeFilter = useCallback(() => setIsMobileFilterOpen(false), []);\n\n\t// Close when resized to desktop\n\tuseEffect(() => {\n\t\tif (isDesktop) {\n\t\t\tcloseFilter();\n\t\t}\n\t}, [isDesktop, closeFilter]);\n\n\tuseEffect(() => {\n\t\tif (hasNoSearchResults) {\n\t\t\tcloseFilter();\n\t\t}\n\t}, [hasNoSearchResults, closeFilter]);\n\n\t// Shared filter panel content used in both mobile fullscreen and tablet drawer\n\tconst filterPanelContent = (\n\t\t<div className=\"isolate flex h-full flex-col\">\n\t\t\t{/* Sticky header — title + close button always visible */}\n\t\t\t<div className=\"sticky top-0 z-10 flex items-center justify-between bg-white py-4 pl-4 pr-5 shadow-sm\">\n\t\t\t\t<Typography className=\"!font-medium text-primary-400\" variant=\"bodyLarge\">\n\t\t\t\t\t{resources['filterAndSort']}\n\t\t\t\t</Typography>\n\t\t\t\t<button\n\t\t\t\t\taria-label=\"Close\"\n\t\t\t\t\tclassName=\"w-auto border-0 bg-transparent p-0 hover:bg-transparent\"\n\t\t\t\t\tonClick={closeFilter}\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t>\n\t\t\t\t\t<CloseIcon className=\"h-4 w-4\" fillColor=\"fill-primary-400\" />\n\t\t\t\t</button>\n\t\t\t</div>\n\n\t\t\t<div className=\"flex-1 overflow-y-auto\">\n\t\t\t\t<div className=\"px-4 pt-4\">\n\t\t\t\t\t<Typography className=\"mb-2 text-black\" variant=\"bodySmall\">\n\t\t\t\t\t\t{resources['allFilters']}\n\t\t\t\t\t</Typography>\n\t\t\t\t\t<div className=\"mb-4 flex flex-wrap gap-1\">\n\t\t\t\t\t\t<CurrentQueryRefinement />\n\t\t\t\t\t\t<CurrentRefinements />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<SortByAccordion items={sortItems} />\n\t\t\t\t<HitsPerPageAccordion items={hitsPerPageItems} />\n\t\t\t\t<Categories />\n\t\t\t</div>\n\t\t\t<div className=\"border-t border-grey-200 p-4\">\n\t\t\t\t<Button className=\"w-full\" onClick={closeFilter} type=\"button\" variant=\"primary\">\n\t\t\t\t\t{resources['seeResults']}\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t</div>\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t{/* Tablet & Mobile: left-side slide-in drawer with scrim via react-modern-drawer, full screen on mobile*/}\n\t\t\t{!isDesktop && shouldShowResultsRoute && (\n\t\t\t\t<Drawer\n\t\t\t\t\tid=\"search-filter-drawer\"\n\t\t\t\t\tisOpen={isMobileFilterOpen}\n\t\t\t\t\tonClose={closeFilter}\n\t\t\t\t\tplacement=\"left\"\n\t\t\t\t\tsize={isMobile ? '100vw' : '320px' /* isTablet */}\n\t\t\t\t\tzIndex={5000}\n\t\t\t\t>\n\t\t\t\t\t<div className=\"h-full bg-white\">{filterPanelContent}</div>\n\t\t\t\t</Drawer>\n\t\t\t)}\n\t\t\t{!isDesktop && shouldShowResultsRoute && (\n\t\t\t\t<ScrollThresholdBar\n\t\t\t\t\trefreshKey={isMobileFilterOpen}\n\t\t\t\t\ttargetRef={staticFilterAndSortControlsRef}\n\t\t\t\t\tclassName=\"z-10 flex items-center justify-between border-y border-grey bg-white p-sp16 shadow-sm\"\n\t\t\t\t>\n\t\t\t\t\t<FilterAndSortButton onClick={toggleFilter} testId=\"sticky-filter-and-sort-button\" />\n\t\t\t\t\t<LayoutButtons currentLayoutType={viewMode} setLayoutType={setViewMode} />\n\t\t\t\t</ScrollThresholdBar>\n\t\t\t)}\n\n\t\t\t<div\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'relative grid gap-8 px-4 md:px-6 lg:mx-auto lg:max-w-[1323px] xxlg:px-4',\n\t\t\t\t\tshouldShowResultsRoute ? 'lg:grid-cols-[300px_auto] xl:grid-cols-[375px_auto]' : 'lg:grid-cols-1'\n\t\t\t\t)}\n\t\t\t\t{...{ [hydrationSettledAttribute]: isHydrationSettled || undefined }}\n\t\t\t>\n\t\t\t\t<ScrollToTopOnPaginationChange />\n\n\t\t\t\t{/* Desktop: static sidebar (always visible in grid flow) */}\n\t\t\t\t{shouldShowResultsRoute && (\n\t\t\t\t\t<div className=\"mt-sp20 hidden self-start border-b border-primary-100 lg:block\">\n\t\t\t\t\t\t<Typography className=\"mb-8 text-black\" variant=\"bodyLarge\">\n\t\t\t\t\t\t\t{resources['allFilters']}\n\t\t\t\t\t\t</Typography>\n\t\t\t\t\t\t<Categories />\n\t\t\t\t\t</div>\n\t\t\t\t)}\n\n\t\t\t\t<div>\n\t\t\t\t\t<div className={cn(hasNoSearchResults ? 'my-sp60' : 'mt-sp20', 'flex flex-col gap-8')}>\n\t\t\t\t\t\t<CategoryContent\n\t\t\t\t\t\t\tsectionKind=\"searchResultsAbove\"\n\t\t\t\t\t\t\tinitialSectionContents={searchResultsAbove}\n\t\t\t\t\t\t\trenderFallback={renderCategoryHeading}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{enableAuthorBioView && (\n\t\t\t\t\t\t\t<BooksByAuthor\n\t\t\t\t\t\t\t\tresources={{\n\t\t\t\t\t\t\t\t\tbooksBy: authorBioResources.booksBy,\n\t\t\t\t\t\t\t\t\tshowMore: authorBioResources.showMore,\n\t\t\t\t\t\t\t\t\tshowLess: authorBioResources.showLess,\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t{hasNoSearchResults ? (\n\t\t\t\t\t\t\t<NoResultsState query={query} />\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<div className=\"-mx-4 flex flex-col-reverse justify-between px-4 md:-mx-6 md:px-6 lg:mx-0 lg:flex-row lg:items-start lg:px-0\">\n\t\t\t\t\t\t\t\t<div className=\"mt-4 flex flex-wrap items-center gap-1 lg:mt-0 lg:min-w-0 lg:flex-1\">\n\t\t\t\t\t\t\t\t\t<CurrentQueryRefinement />\n\t\t\t\t\t\t\t\t\t<CurrentRefinements />\n\t\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\t\tref={staticFilterAndSortControlsRef}\n\t\t\t\t\t\t\t\t\tclassName=\"flex shrink-0 gap-8\"\n\t\t\t\t\t\t\t\t\tdata-testid=\"static-filter-and-sort-controls\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<div className=\"mr-auto lg:hidden\">\n\t\t\t\t\t\t\t\t\t\t<FilterAndSortButton onClick={toggleFilter} />\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<LayoutButtons currentLayoutType={viewMode} setLayoutType={setViewMode} />\n\t\t\t\t\t\t\t\t\t<div className=\"bodyMd hidden shrink-0 items-center text-black lg:flex\">\n\t\t\t\t\t\t\t\t\t\t<DesktopSearchControl\n\t\t\t\t\t\t\t\t\t\t\tonChange={newSortBy => refineSortBy(newSortBy.toString())}\n\t\t\t\t\t\t\t\t\t\t\titems={sortItems}\n\t\t\t\t\t\t\t\t\t\t\tprefixText={resources['sortBy']}\n\t\t\t\t\t\t\t\t\t\t\ttestId=\"sort-by-menu-button\"\n\t\t\t\t\t\t\t\t\t\t\tvalue={currentSortBy ?? sortItems[0].value}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t<div className=\"bodyMd hidden shrink-0 items-center text-black lg:flex\">\n\t\t\t\t\t\t\t\t\t\t<DesktopSearchControl\n\t\t\t\t\t\t\t\t\t\t\tcontentClassName=\"w-(--radix-popper-anchor-width) min-w-0\"\n\t\t\t\t\t\t\t\t\t\t\tonChange={newHitsPerPage => refineHitsPerPage(Number(newHitsPerPage))}\n\t\t\t\t\t\t\t\t\t\t\titems={showItems.map(item => ({\n\t\t\t\t\t\t\t\t\t\t\t\tlabel: item.label,\n\t\t\t\t\t\t\t\t\t\t\t\tvalue: item.value,\n\t\t\t\t\t\t\t\t\t\t\t}))}\n\t\t\t\t\t\t\t\t\t\t\tprefixText={resources['show']}\n\t\t\t\t\t\t\t\t\t\t\ttestId=\"hits-per-page-menu-button\"\n\t\t\t\t\t\t\t\t\t\t\tvalue={currentHitsPerPage ?? hitsPerPageItems[0].value}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t{shouldShowResultsRoute && (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<ProductHits\n\t\t\t\t\t\t\t\tlayoutType={viewMode}\n\t\t\t\t\t\t\t\twishListsProductsUrl={wishListsProductsUrl}\n\t\t\t\t\t\t\t\tcurrentHitsPerPage={currentHitsPerPage}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<Pagination\n\t\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\t'[&>ul>li.previous-page-item>.ais-Pagination-link]:bodyLg',\n\t\t\t\t\t\t\t\t\t'[&>ul>li.next-page-item>.ais-Pagination-link]:bodyLg'\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\tclassNames={{\n\t\t\t\t\t\t\t\t\troot: 'py-4 lg:px-4 lg:py-8',\n\t\t\t\t\t\t\t\t\tnoRefinementRoot: 'hidden',\n\t\t\t\t\t\t\t\t\tlist: 'flex gap-[2px] items-center justify-center',\n\t\t\t\t\t\t\t\t\titem: 'bodySm text-black h-6 w-[23px]',\n\t\t\t\t\t\t\t\t\tpreviousPageItem: 'previous-page-item text-primary',\n\t\t\t\t\t\t\t\t\tpageItem: 'pageItem',\n\t\t\t\t\t\t\t\t\tselectedItem: 'bg-primary-100 text-primary',\n\t\t\t\t\t\t\t\t\tdisabledItem: 'opacity-25',\n\t\t\t\t\t\t\t\t\tnextPageItem: 'next-page-item text-primary',\n\t\t\t\t\t\t\t\t\tlink: 'flex items-center justify-center px-2 py-1 h-full w-full',\n\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\tshowFirst={false}\n\t\t\t\t\t\t\t\tshowLast={false}\n\t\t\t\t\t\t\t\tshowNext\n\t\t\t\t\t\t\t\tshowPrevious\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</>\n\t);\n};\n\n// ---------------------------------------------------------------------------\n// InstantSearchWrapper — wires up Algolia routing + providers\n// ---------------------------------------------------------------------------\n\nconst InstantSearchWrapper = ({\n\ttitlePostfix,\n\tsearchPageTitle,\n\tcategories,\n\tfacetConfigurations,\n\tsearchParameters,\n\twishListsProductsUrl,\n\tenableAuthorBioView,\n\tpageLimits,\n\tsortOrders,\n\tattributesToRetrieve,\n\tsearchResultsAbove,\n\tinitialViewMode,\n\tinitialAuthor,\n\tinitialRouteState,\n\tinitialUserSearchFilterSelections,\n}: {\n\ttitlePostfix: string | null;\n\tsearchPageTitle: string;\n\tcategories: SearchCategory[];\n\tfacetConfigurations: FacetConfiguration[];\n\tsearchParameters: AlgoliaSearchParameters;\n\twishListsProductsUrl: string;\n\tenableAuthorBioView: boolean;\n\tpageLimits: number[];\n\tsortOrders: SearchSortOrder[];\n\tattributesToRetrieve: string[];\n\tsearchResultsAbove?: SectionContentViewModel[];\n\tinitialViewMode: ViewMode;\n\tinitialAuthor?: AuthorInfo;\n\tinitialRouteState?: RouteState;\n\tinitialUserSearchFilterSelections?: Record<string, string>;\n}) => {\n\tconst { client: searchClient, indexName } = useAlgoliaSearch();\n\tconst { userSearchFilters } = useUserSearchFilterContext();\n\tconst { href, isQueryStringReady } = useLocation();\n\tconst queryReady = useRef(isQueryStringReady);\n\tqueryReady.current = isQueryStringReady;\n\tconst initialLocation = useRef(href);\n\tconst stateMapping = useMemo(\n\t\t() => makeStateMapping(indexName, facetConfigurations, sortOrders),\n\t\t[indexName, facetConfigurations, sortOrders]\n\t);\n\tconst categoryPageConfigurations = useMemo(\n\t\t() => convertSearchCategoriesToCategoryPageConfiguration(categories),\n\t\t[categories]\n\t);\n\tconst router = useMemo(\n\t\t() =>\n\t\t\tmakeRouter(\n\t\t\t\tcategoryPageConfigurations,\n\t\t\t\tfacetConfigurations,\n\t\t\t\tuserSearchFilters,\n\t\t\t\tinitialLocation.current,\n\t\t\t\ttitlePostfix,\n\t\t\t\tsearchPageTitle,\n\t\t\t\t{\n\t\t\t\t\tinitialRouteState: { ...initialRouteState, filters: initialUserSearchFilterSelections },\n\t\t\t\t\tisReady: () => queryReady.current,\n\t\t\t\t}\n\t\t\t),\n\t\t[\n\t\t\tcategoryPageConfigurations,\n\t\t\tfacetConfigurations,\n\t\t\tuserSearchFilters,\n\t\t\ttitlePostfix,\n\t\t\tsearchPageTitle,\n\t\t\tinitialRouteState,\n\t\t\tinitialUserSearchFilterSelections,\n\t\t]\n\t);\n\tconst routing = useMemo(() => ({ router, stateMapping }), [router, stateMapping]);\n\n\tuseEffect(() => {\n\t\tif (isQueryStringReady) {\n\t\t\trouter.syncFromBrowser();\n\t\t}\n\t}, [router, href, isQueryStringReady]);\n\n\tuseEffect(() => {\n\t\tif (!isQueryStringReady) {\n\t\t\treturn;\n\t\t}\n\t\tconst canonicalLink = document.head.querySelector<HTMLLinkElement>('link[rel=\"canonical\"]');\n\t\tif (!canonicalLink) {\n\t\t\treturn;\n\t\t}\n\n\t\tcanonicalLink.href = getCanonicalSearchUrl({\n\t\t\trouteState: router.read(),\n\t\t\tcanonicalOrigin: new URL(canonicalLink.href).origin,\n\t\t\tcategoryPageConfigurations,\n\t\t\tfacetConfigurations,\n\t\t\tindexName,\n\t\t\tpageLimits,\n\t\t\tsortOrders,\n\t\t});\n\t}, [\n\t\trouter,\n\t\thref,\n\t\tisQueryStringReady,\n\t\tcategoryPageConfigurations,\n\t\tfacetConfigurations,\n\t\tindexName,\n\t\tpageLimits,\n\t\tsortOrders,\n\t]);\n\n\treturn (\n\t\t<AlgoliaSSRProvider<UiState, RouteState>\n\t\t\tattributesToRetrieve={attributesToRetrieve}\n\t\t\tqueryType=\"prefixNone\"\n\t\t\trouting={routing}\n\t\t\tsearchClient={searchClient}\n\t\t\tsearchParameters={searchParameters}\n\t\t\tinitialViewMode={initialViewMode}\n\t\t>\n\t\t\t<HiddenFacetRefinements facetConfigurations={facetConfigurations} />\n\t\t\t<AuthorBatch.Provider initialData={initialAuthor ? [{ id: initialAuthor.id, data: initialAuthor }] : undefined}>\n\t\t\t\t<PublisherBatch.Provider>\n\t\t\t\t\t<FilterSortLayout\n\t\t\t\t\t\tpageLimits={pageLimits}\n\t\t\t\t\t\tsortOrders={sortOrders}\n\t\t\t\t\t\twishListsProductsUrl={wishListsProductsUrl}\n\t\t\t\t\t\tenableAuthorBioView={enableAuthorBioView}\n\t\t\t\t\t\tsearchResultsAbove={searchResultsAbove}\n\t\t\t\t\t\tcategories={categories}\n\t\t\t\t\t/>\n\t\t\t\t</PublisherBatch.Provider>\n\t\t\t</AuthorBatch.Provider>\n\t\t</AlgoliaSSRProvider>\n\t);\n};\n\n// ---------------------------------------------------------------------------\n// Search — top-level entry component (default export)\n// ---------------------------------------------------------------------------\n\ninterface SearchProps {\n\ttitlePostfix?: string | null;\n\talgoliaAppId?: string;\n\talgoliaAppKey?: string;\n\talgoliaUserTokenCookieDurationInMilliseconds?: number | null;\n\talgoliaIndexName?: string;\n\tstorefrontShortname?: string;\n\talgoliaSearchParametersJson?: string;\n\tuserSearchFiltersJson?: string;\n\tinitialUserSearchFilterSelections?: Record<string, string>;\n\tfacetConfigurations?: FacetConfiguration[];\n\tsearchCategories?: SearchCategory[];\n\twishListsProductsUrl?: string;\n\tenableAuthorBioView?: boolean;\n\tsearchResultsAbove?: SectionContentViewModel[];\n\tsearchResultsBelow?: SectionContentViewModel[];\n\tinitialViewMode: ViewMode;\n\tpageLimits: number[];\n\tsortOrders: SearchSortOrder[];\n\tattributesToRetrieve: string[];\n\tinitialIsSignedIn?: boolean;\n\tserverState?: InstantSearchServerState;\n\tinitialAuthor?: AuthorInfo;\n\tinitialRouteState?: RouteState;\n}\n\nexport default function Search({\n\ttitlePostfix = '',\n\talgoliaAppId = '',\n\talgoliaAppKey = '',\n\talgoliaUserTokenCookieDurationInMilliseconds,\n\talgoliaIndexName = '',\n\tstorefrontShortname = '',\n\talgoliaSearchParametersJson,\n\tuserSearchFiltersJson,\n\tinitialUserSearchFilterSelections,\n\tfacetConfigurations = [],\n\tsearchCategories = [],\n\twishListsProductsUrl = '',\n\tenableAuthorBioView = false,\n\tpageLimits,\n\tsortOrders,\n\tattributesToRetrieve,\n\tinitialViewMode,\n\tserverState,\n\tinitialAuthor,\n\tinitialRouteState,\n\tsearchResultsAbove,\n\tsearchResultsBelow,\n\tinitialIsSignedIn,\n}: SearchProps) {\n\tconst localizedResources = useLocalization('CommerceWeb.Resources.Search.Search');\n\tconst resources = {\n\t\tallFilters: localizedResources.allFilters,\n\t\tfilterAndSort: localizedResources.filterAndSort,\n\t\tseeResults: localizedResources.seeResults,\n\t\tsortBy: localizedResources.sortBy,\n\t\tshow: localizedResources.show,\n\t\tshowMore: localizedResources.showMore,\n\t\tshowLess: localizedResources.showLess,\n\t\tnoResults: localizedResources.noResults,\n\t\tsearchTips: localizedResources.searchTips,\n\t\tcheckSpelling: localizedResources.checkSpelling,\n\t\tdifferentKeywords: localizedResources.differentKeywords,\n\t\tlessSpecific: localizedResources.lessSpecific,\n\t\tseeAllProducts: localizedResources.seeAllProducts,\n\t\tbestselling: localizedResources.bestselling,\n\t\tnewest: localizedResources.newest,\n\t\toldest: localizedResources.oldest,\n\t\tpriceHighToLow: localizedResources.priceHighToLow,\n\t\tpriceLowToHigh: localizedResources.priceLowToHigh,\n\t\tsavings: localizedResources.savings,\n\t\ttitleSort: localizedResources.titleSort,\n\t\tprogress: localizedResources.progress,\n\t\trelevance: localizedResources.relevance,\n\t\tauthorIds: localizedResources.authorIds,\n\t\tbibleAndApocrypha: localizedResources.bibleAndApocrypha,\n\t\tcontainment: localizedResources.containment,\n\t\tformat: localizedResources.format,\n\t\tgenre: localizedResources.genre,\n\t\tlanguage: localizedResources.language,\n\t\tlicensingMethod: localizedResources.licensingMethod,\n\t\tproductType: localizedResources.productType,\n\t\tpublisherIds: localizedResources.publisherIds,\n\t\tregion: localizedResources.region,\n\t\treligiousGroup: localizedResources.religiousGroup,\n\t\tresourceType: localizedResources.resourceType,\n\t\tseriesSets: localizedResources.seriesSets,\n\t\tspecials: localizedResources.specials,\n\t\tstatus: localizedResources.status,\n\t\ttopic: localizedResources.topic,\n\t\tliveStatusText: localizedResources.liveStatusText,\n\t\tprepubStatusText: localizedResources.prepubStatusText,\n\t\tgatheringInterestStatusText: localizedResources.gatheringInterestStatusText,\n\t\tunderContractStatusText: localizedResources.underContractStatusText,\n\t\talmostFundedStatusText: localizedResources.almostFundedStatusText,\n\t\tshippingSoonStatusText: localizedResources.shippingSoonStatusText,\n\t\tinProductionStatusText: localizedResources.inProductionStatusText,\n\t\tshipsFormat: localizedResources.shipsFormat,\n\t\tdiscountFormat: localizedResources.discountFormat,\n\t\treadMore: localizedResources.readMore,\n\t\treadLess: localizedResources.readLess,\n\t\taddToCart: localizedResources.addToCart,\n\t\taddingToCart: localizedResources.addingToCart,\n\t\tquickBuy: localizedResources.quickBuy,\n\t\tgeoRestrictionMessage: localizedResources.geoRestrictionMessage,\n\t\tpermanentOwnMessage: localizedResources.permanentOwnMessage,\n\t\ttemporaryOwnMessage: localizedResources.temporaryOwnMessage,\n\t\thasPreorderMessage: localizedResources.hasPreorderMessage,\n\t\tpreorder: localizedResources.preorder,\n\t\tUnavailableToPurchase: localizedResources.UnavailableToPurchase,\n\t};\n\tconst { userId, isSignedIn } = useCurrentUser();\n\tconst effectiveIsSignedIn = isSignedIn || initialIsSignedIn === true;\n\tconst searchParameters = useMemo(\n\t\t() => safeJsonParse(algoliaSearchParametersJson) ?? {},\n\t\t[algoliaSearchParametersJson]\n\t);\n\tconst userSearchFilters = useMemo((): UserSearchFilter[] => {\n\t\tconst parsedFilters = safeJsonParse<UserSearchFilters>(userSearchFiltersJson);\n\t\treturn (\n\t\t\tparsedFilters?.filters?.map(filter => ({\n\t\t\t\t...filter,\n\t\t\t\toptions: filter.options.map(option => ({ ...option, isSelected: option.isDefault })),\n\t\t\t})) ?? []\n\t\t);\n\t}, [userSearchFiltersJson]);\n\n\treturn (\n\t\t<div className=\"tw-preflight\">\n\t\t\t<PerUserDataContextProvider requestAnonymousPricing>\n\t\t\t\t<SearchResourcesContext.Provider value={resources}>\n\t\t\t\t\t<ErrorBoundary>\n\t\t\t\t\t\t<AlgoliaSearchContextProvider\n\t\t\t\t\t\t\tappId={algoliaAppId}\n\t\t\t\t\t\t\tappKey={algoliaAppKey}\n\t\t\t\t\t\t\tcookieDuration={algoliaUserTokenCookieDurationInMilliseconds}\n\t\t\t\t\t\t\tindexName={algoliaIndexName}\n\t\t\t\t\t\t\tstorefrontShortname={storefrontShortname}\n\t\t\t\t\t\t\tuserId={userId}\n\t\t\t\t\t\t\tisSignedIn={effectiveIsSignedIn}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<UserSearchFilterProvider\n\t\t\t\t\t\t\t\tinitialSelectedFilterOptions={initialUserSearchFilterSelections}\n\t\t\t\t\t\t\t\tuserSearchFilters={userSearchFilters}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<InstantSearchSSRProvider initialResults={serverState?.initialResults}>\n\t\t\t\t\t\t\t\t\t<InstantSearchWrapper\n\t\t\t\t\t\t\t\t\t\ttitlePostfix={titlePostfix}\n\t\t\t\t\t\t\t\t\t\tsearchPageTitle={localizedResources.searchPageTitle}\n\t\t\t\t\t\t\t\t\t\tcategories={searchCategories}\n\t\t\t\t\t\t\t\t\t\tfacetConfigurations={facetConfigurations}\n\t\t\t\t\t\t\t\t\t\tsearchParameters={searchParameters}\n\t\t\t\t\t\t\t\t\t\twishListsProductsUrl={wishListsProductsUrl}\n\t\t\t\t\t\t\t\t\t\tenableAuthorBioView={enableAuthorBioView}\n\t\t\t\t\t\t\t\t\t\tpageLimits={pageLimits}\n\t\t\t\t\t\t\t\t\t\tsortOrders={sortOrders}\n\t\t\t\t\t\t\t\t\t\tattributesToRetrieve={attributesToRetrieve}\n\t\t\t\t\t\t\t\t\t\tsearchResultsAbove={searchResultsAbove}\n\t\t\t\t\t\t\t\t\t\tinitialViewMode={initialViewMode}\n\t\t\t\t\t\t\t\t\t\tinitialAuthor={initialAuthor}\n\t\t\t\t\t\t\t\t\t\tinitialRouteState={initialRouteState}\n\t\t\t\t\t\t\t\t\t\tinitialUserSearchFilterSelections={initialUserSearchFilterSelections}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</InstantSearchSSRProvider>\n\t\t\t\t\t\t\t</UserSearchFilterProvider>\n\t\t\t\t\t\t</AlgoliaSearchContextProvider>\n\t\t\t\t\t</ErrorBoundary>\n\t\t\t\t</SearchResourcesContext.Provider>\n\t\t\t\t<CategoryContent sectionKind=\"searchResultsBelow\" initialSectionContents={searchResultsBelow} />\n\t\t\t</PerUserDataContextProvider>\n\t\t</div>\n\t);\n}\n","import { useEffect, useRef } from 'react';\nimport { useHits } from 'react-instantsearch';\n\nimport { ProductHit } from '../types';\n\n/**\n * Pushes UA Enhanced Ecommerce impression data to the dataLayer when search results change.\n * Matches the Skeletor pattern of `dataLayer.push({ ecommerce: { impressions: [...] } })`.\n */\nexport function useSearchImpressions() {\n\tconst { results } = useHits<ProductHit>();\n\tconst lastPushedQueryRef = useRef<string | null>(null);\n\n\tuseEffect(() => {\n\t\tif (!results?.hits?.length) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Deduplicate pushes by using the Algolia query ID (or query string + page as fallback)\n\t\tconst queryKey = (results as any).queryID ?? `${results.query ?? ''}_${results.page ?? 0}`;\n\t\tif (queryKey === lastPushedQueryRef.current) {\n\t\t\treturn;\n\t\t}\n\t\tlastPushedQueryRef.current = queryKey;\n\n\t\tconst impressions = results.hits.map((hit, index) => ({\n\t\t\tid: String(hit.productId),\n\t\t\tname: hit.title ?? '',\n\t\t\tprice: String(hit.salePrice ?? 0),\n\t\t\tlist: 'Search Results',\n\t\t\tposition: String(index),\n\t\t}));\n\n\t\t(window as any).dataLayer = (window as any).dataLayer || [];\n\t\t(window as any).dataLayer.push({\n\t\t\tecommerce: {\n\t\t\t\timpressions,\n\t\t\t},\n\t\t});\n\t}, [results]);\n}\n","import { useEffect, useRef } from 'react';\nimport { useInstantSearch } from 'react-instantsearch';\n\n/**\n * Pushes GTM dataLayer events when users interact with search facets, sort options,\n * and hits-per-page controls. Matches the Skeletor `facet_search` and `results_search` events.\n */\nexport function useSearchAnalytics() {\n\tconst { indexUiState } = useInstantSearch();\n\tconst previousStateRef = useRef<typeof indexUiState | null>(null);\n\n\tuseEffect(() => {\n\t\tconst prevState = previousStateRef.current;\n\t\tpreviousStateRef.current = indexUiState;\n\n\t\t// Skip the initial render — only track user-initiated changes\n\t\tif (!prevState) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst dataLayer = ((window as any).dataLayer = (window as any).dataLayer || []);\n\n\t\t// Track sort changes\n\t\tif (indexUiState.sortBy !== prevState.sortBy) {\n\t\t\tdataLayer.push({\n\t\t\t\tevent: 'results_search',\n\t\t\t\tselection: {\n\t\t\t\t\tgroup: 'Sort By',\n\t\t\t\t\toption: indexUiState.sortBy ?? 'default',\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\t// Track hits-per-page changes\n\t\tif (indexUiState.hitsPerPage !== prevState.hitsPerPage) {\n\t\t\tdataLayer.push({\n\t\t\t\tevent: 'results_search',\n\t\t\t\tselection: {\n\t\t\t\t\tgroup: 'Show',\n\t\t\t\t\toption: String(indexUiState.hitsPerPage ?? 15),\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\n\t\t// Track refinement list (facet) changes\n\t\tconst currentRefinements = indexUiState.refinementList ?? {};\n\t\tconst previousRefinements = prevState.refinementList ?? {};\n\n\t\tconst allFacetKeys = new Set([...Object.keys(currentRefinements), ...Object.keys(previousRefinements)]);\n\n\t\tfor (const facetKey of allFacetKeys) {\n\t\t\tconst currentValues = new Set(currentRefinements[facetKey] ?? []);\n\t\t\tconst previousValues = new Set(previousRefinements[facetKey] ?? []);\n\n\t\t\t// Find newly selected facets\n\t\t\tfor (const value of currentValues) {\n\t\t\t\tif (!previousValues.has(value)) {\n\t\t\t\t\tdataLayer.push({\n\t\t\t\t\t\tevent: 'facet_search',\n\t\t\t\t\t\tselection: {\n\t\t\t\t\t\t\tfacetGroup: facetKey,\n\t\t\t\t\t\t\tfacet: value,\n\t\t\t\t\t\t\tchecked: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Find deselected facets\n\t\t\tfor (const value of previousValues) {\n\t\t\t\tif (!currentValues.has(value)) {\n\t\t\t\t\tdataLayer.push({\n\t\t\t\t\t\tevent: 'facet_search',\n\t\t\t\t\t\tselection: {\n\t\t\t\t\t\t\tfacetGroup: facetKey,\n\t\t\t\t\t\t\tfacet: value,\n\t\t\t\t\t\t\tchecked: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Track page changes\n\t\tif (indexUiState.page !== prevState.page) {\n\t\t\tdataLayer.push({\n\t\t\t\tevent: 'results_search',\n\t\t\t\tselection: {\n\t\t\t\t\tgroup: 'Page',\n\t\t\t\t\toption: String(indexUiState.page ?? 1),\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}, [indexUiState]);\n}\n","export function safeJsonParse<T = any>(json: string | null | undefined): T | null {\n\tif (json === null || json === undefined) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\treturn JSON.parse(json) as T;\n\t} catch {\n\t\treturn null;\n\t}\n}\n"],"names":["scroll_threshold_bar","targetRef","children","threshold","position","refreshKey","className","isVisible","setIsVisible","useState","useEffect","target","current","normalizedThreshold","Number","isFinite","Math","min","max","scrollContainer","parentElement","document","body","documentElement","overflowY","window","getComputedStyle","includes","scrollTarget","animationFrame","updateVisibility","targetBounds","getBoundingClientRect","triggerPosition","top","height","scrollportTop","clientTop","scheduleUpdate","requestAnimationFrame","eventTarget","addEventListener","passive","removeEventListener","cancelAnimationFrame","stickyBarRef","useCallback","stickyBar","removeAttribute","setAttribute","isAtTop","React","cn","ref","BooksByAuthor","resources","refinedAuthorIds","useRefinementList","attribute","items","filter","item","isRefined","map","value","authorId","length","data","author","isLoading","useAuthor","isCollapsed","setIsCollapsed","displayName","longDescription","Typography","variant","booksBy","IconButton","scale","onClick","ChevronDown","ChevronUp","AuthorBio","imageUrl","imageUrlLarge","bio","PublisherBatch","createBatchContext","async","nonEmptyIds","ids","id","response","fetch","join","ok","Error","status","json","find","d","builderIoModelNamesBySectionKindMap","searchResultsAbove","searchResultsBelow","universalHeader","universalFooter","subscriptionChurnPrevention","configurationWizardSubscriptionsBanner","configurationWizardSubscriptionsContent","configurationWizardLibrariesBanner","orderSummary","orderSummaryFooter","productPage","adzone","notifications","pdpBanner","getContentKey","sectionContents","sc","sectionKind","contentSourceKind","contentId","section_content","SectionContent","initialSectionContents","onContentChange","renderFallback","builderIoModel","isBuilderIoPreviewingThisModel","useIsPreviewingThisBuilderModel","location","useLocation","renderFallbackRef","useRef","fallback","setContent","lastRequestedLocationHref","undefined","href","initialPathname","pathname","hasInitialSections","isQueryStringReady","sections","kind","url","get","params","error","getSections","filteredSections","hasContent","contentKey","fetchSections","notifyWarning","RenderBuilderContent","model","staticData","staticProductData","userInfo","c_defaultUserInfo","filteredContents","_extends","key","builderIo","category_content","CategoryContent","setContentState","handleContentChange","event","prev","ErrorBoundary","ReadMoreReadLess","UserSearchFilterContext","createContext","readUserFilterSelectionsFromUrl","userSearchFilters","searchParams","defaults","reduce","selectedOptions","options","Array","isArray","selectedOption","option","isDefault","token","getDefaultSelectedFilterOptions","urlValue","matchingOption","resolved","useUserSearchFilterContext","context","useContext","UserSearchFilterProvider","initialSelectedFilterOptions","setSelectedFilterOptionsOverride","search","replaceUrl","useMemo","URLSearchParams","hasReadQuery","setHasReadQuery","selectedFilterOptions","setSelectedFilterOptions","urlSelections","initialSelection","some","next","currentSelection","isStillValid","first","second","firstKeys","Object","keys","secondKeys","every","areSelectedFilterOptionsEqual","URL","selectedToken","set","delete","writeUserFilterSelectionsToUrl","handleSetSelectedFilterOption","filterToken","optionToken","contextValue","setSelectedFilterOption","Provider","Accordion","AccordionPrimitive","AccordionItem","props","AccordionTrigger","AccordionContent","c_nonWordCharacters","c_leadingDecimalDigit","c_facetResourceKeyAliases","bibleAndApocrypha","containment","single","standalone","format","reader","religiousGroup","topic","getFacetDisplayLabel","rawLabel","leaf","separatorIndex","lastIndexOf","slice","trim","getFacetLeaf","resourceName","replace","baseAttribute","resourceKeyAlias","resourceKeys","test","leadingDigits","match","push","getResourceKeys","resourceKey","translation","getResourceValue","prototype","hasOwnProperty","call","caseInsensitiveKey","toLowerCase","useFacetConstraints","useLocalization","allKeys","SearchResourcesContext","useSearchResources","serializeKey","JSON","stringify","createBoundedResponsesCache","maxCharacters","cache","Map","characters","defaultValue","events","miss","Promise","resolve","serializedKey","cached","parse","promise","then","serializedValue","existing","size","oldestKey","evict","clear","AlgoliaSearchContext","AlgoliaSearchContextProvider","appId","appKey","cookieDuration","indexName","storefrontShortname","userId","isSignedIn","client","algoliasearch","responsesCache","anonymousUserToken","setAnonymousUserToken","insightsClient","createAlgoliaInsightsInitOptions","userToken","String","useAlgoliaSearch","parseFacetValue","indexOf","substring","safeUrl","input","base","Check","checked","fill","viewBox","width","xmlns","rx","stroke","y","strokeLinecap","c_statusLabelKeys","ShowMoreToggle","showMore","setShowMore","isShowingMore","LinkButton","as","countDepth","index","depth","getChildren","parent","startsWith","Category","category","setExpandedFacets","maxLevel","facetConstraints","levels","levelsRef","level","refinement","limit","skipSuspense","useRefinementLists","accordions","root","label","labelKind","subCategories","hasChildren","c","getAccordions","accordion","tag","refine","eventName","filters","child","forEach","childRefinement","old","v","count","AuthorFacetItem","onRefine","PublisherFacetItem","AuthorsOrPublishers","nameAttribute","canToggleShowMore","toggleShowMore","idItems","FacetItem","facetItems","idItem","sort","a","b","i","Statuses","level1","level2","level3","level4","UserSearchFilterAccordionItem","selectedFilterOption","title","isSelected","onChange","type","Categories","expandedFacets","onValueChange","isGenericLocalizableFacet","split","isStatusRefinement","RefinementLabel","facetLabel","stringValue","AuthorLabel","PublisherLabel","AuthorApiLabel","PublisherApiLabel","useData","CurrentRefinements","currentRefinements","useCurrentRefinements","itemsByAttribute","refinementList","refinements","itemValue","itemAndChildren","r","RefinementChip","X","CurrentQueryRefinement","urlQuery","query","useSearchBox","queryRef","removeQuery","HiddenRefinementList","getHiddenAlgoliaAttributes","config","algoliaAttribute","attributes","minLevel","algoliaAttributeBase","HiddenFacetRefinements","facetConfigurations","isHidden","flatMap","SkeletonRoot","pending","hideOverflow","role","SkeletonBox","EnhancedForLogosLabel","logosOrVerbum","useBrandName","isVerbum","CommandSentence","template","EnhancedForLogos","Field","name","alt","src","enhanced_for_logos_with_tooltip","EnhancedForLogosWithTooltip","Tooltip","placement","link","InfoIconSvgUrl","EnhancedForLogosTooltipContent","usdFormat","Intl","NumberFormat","style","currency","minimumFractionDigits","maximumFractionDigits","useProductCard","hit","queryId","pricingData","usePricing","productId","preferredCurrency","currentUserIsSignedIn","useCurrentUser","searchIsSignedIn","locale","useLocale","hasGeoRestriction","isGeographicallyRestricted","isAddingToCart","setIsAddingToCart","requestIdRef","prices","primarySku","salePrice","amount","displayAmount","currencyCode","anchorPrice","displayAmountCurrencyCode","accessKind","isOwned","hasPreorder","prepubProductStatusSummary","rawPercentCommitted","percentCommitted","normalizedStatusValues","PrepubProductStatus","shippingSoon","almostThere","underContract","gatheringInterest","getPrepubStatus","shipDate","milliseconds","abs","date","Date","isNaN","getTime","dateOnlyMatch","exec","getFullYear","getMonth","getDate","parsePrepubShipDate","prepubShipDate","description","now","thirtyDaysFromNow","setDate","ninetyDaysFromNow","shipDateString","DateTimeFormat","month","year","floor","getShippingDateDescription","toISOString","getPrepubProductStatusSummary","isPrepubProduct","Boolean","indexedPrimarySkuId","primarySkuStorefronts","normalizedStorefrontShortname","entries","storefronts","storefront","getIndexedPrimarySkuId","hasIndexedPrimarySkuData","canUseIndexedPrimarySku","skuId","isPurchasable","handleCartUpdated","e","detail","requestId","handleCartUpdateError","slug","text","normalize","slugify","productPath","productUrl","encodeURIComponent","productName","regularPrice","salePriceCurrency","localizedSalePrice","localizedDisplayAmount","discountPercentage","anchor","sale","getSavingsPercent","isDiscounted","discountSavings","productImageSrc","primaryImageUri","imageSrc","detectIsAmberOptimizedUrl","isLogosEdition","handleProductClick","queryID","objectIDs","positions","handleAddToCart","eventType","eventData","random","eventDetail","addToCartUrl","routes","skuIds","addToCartSkuId","quantity","payInFull","searchData","productIds","currentTarget","dispatchEvent","CustomEvent","bubbles","ProductImage","priority","onAuxClick","Image","belowTheFold","sizes","mobile","desktop","targetAspectRatio","DiscountBadge","badgeClassName","toFixed","ProductTitle","ProductAuthors","authors","ctaButtonScale","skeletonHeightByButtonScale","small","medium","large","ProductPricing","cardData","buttonLayoutClassName","ProductPrice","ProductCta","ownershipLabelClassName","PriceLabel","layout","purchaseStatusMessage","getOwnershipLabel","Button","disabled","Skeleton","AlgoliaGridCard","productWishlistData","useProductInWishList","averageRating","reviewCount","hasReviewData","hasValidReviewData","AddToWishList","StarRating","rating","PrepubProductStatusSummary","ProductOverview","overview","isExpanded","setIsExpanded","showButton","setShowButton","overviewRef","element","scrollHeight","computedLineHeight","lineHeight","parsedLineHeight","parseInt","dangerouslySetInnerHTML","__html","intent","toggleExpand","AlgoliaListCard","SkeletonBlock","rootClassName","SkeletonButton","ProductSkeleton","layoutType","ProductSkeletons","currentHitsPerPage","from","_","toProductHitResult","toString","products","wishListsProductsUrl","useInstantSearch","HitComponent","cardProps","__position","__queryID","WishlistContextProvider","Hits","classNames","list","hitComponent","RadioAccordion","radioGroupName","onSelect","prefixLabel","currentItem","collapsible","SortByAccordion","currentRefinement","useSortBy","HitsPerPageAccordion","showItems","useHitsPerPage","ViewMode","ViewModeContext","viewModeKey","ViewModeProvider","initialViewMode","viewMode","setViewMode","history","replaceState","Cookies","getAllFacetingKeys","routeKey","routeKeyPrefix","arrayToQueryParam","array","emptyIfUndefined","getTrimmedOrUndefinedIfStringEmpty","trimmed","getMatchingCategoryPageFromRouteState","routeState","categoryPageConfigurations","allFacetingKeys","facets","Set","categoryPageConfiguration","checkCategoryPageConfigurationMatches","preserveCustomQueryParams","sourceUrl","targetUrl","preserveKeys","has","preserveNonSearchQueryParams","searchParamKeys","writeFacetsSearchParams","excludedKeys","candidateQueryParamValue","writeUserFilterSearchParams","checkFacetValueConfigurationMatches","facetValueConfiguration","routeStateFacetValue","routeStateFacets","facetsConfiguration","matches","routeStateFacet","facetConfiguration","f","queryParamName","writeCommonSearchParams","sortBy","page","hydrationSettledAttribute","parameterBlacklist","AlgoliaSSRProvider","AlgoliaProvider","attributesToHighlight","attributesToRetrieve","queryType","restrictSearchableAttributes","routing","searchClient","searchParameters","InstantSearch","future","preserveSharedStateOnUnmount","insights","ConfigureCore","mergedParams","algoliaValue","filterParts","fromEntries","useEffectiveSearchParameters","Configure","distinct","clickAnalytics","CloseIcon","fillColor","_fillColor","rest","strokeWidth","FilterIcon","FilterAndSortButton","testId","LayoutButtonOptions","grid","icon","x","additionalClassNames","LayoutButtons","currentLayoutType","setLayoutType","IconComponent","DesktopSearchControl","prefixText","contentClassName","selectedItem","selectedLabel","handleValueChange","newValue","matchedItem","DropdownMenu","DropdownMenuTrigger","DropdownMenuContent","DropdownMenuRadioGroup","DropdownMenuRadioItem","ScrollToTopOnPaginationChange","usePagination","scrollTo","behavior","NoResultsState","normalizedQuery","noResultsMessageTemplate","searchTips","Container","tip","assign","FilterSortLayout","enableAuthorBioView","pageLimits","sortOrders","categories","authorBioResources","renderCategoryHeading","path","categoryPageUrl","isMobileFilterOpen","setIsMobileFilterOpen","useViewMode","isMobile","isDesktop","useScreensize","isHydrationSettled","isSettled","setIsSettled","timeoutId","setTimeout","clearTimeout","useHydrationSettled","results","useHits","lastPushedQueryRef","hits","queryKey","impressions","price","dataLayer","ecommerce","useSearchImpressions","indexUiState","previousStateRef","prevState","selection","group","hitsPerPage","previousRefinements","allFacetKeys","facetKey","currentValues","previousValues","facetGroup","facet","useSearchAnalytics","hasNoSearchResults","__isArtificial","nbHits","shouldShowResultsRoute","allSortItems","sortOrder","isPrepub","currentSortBy","refineSortBy","hasPrepubCategory","sortItems","hitsPerPageItems","pageLimit","default","refineHitsPerPage","searchStateKey","values","left","right","localeCompare","userFilters","previousSearchStateKey","toggleFilter","staticFilterAndSortControlsRef","closeFilter","filterPanelContent","Drawer","isOpen","onClose","zIndex","ScrollThresholdBar","showLess","newSortBy","newHitsPerPage","ProductHits","Pagination","noRefinementRoot","previousPageItem","pageItem","disabledItem","nextPageItem","showFirst","showLast","showNext","showPrevious","InstantSearchWrapper","titlePostfix","searchPageTitle","initialAuthor","initialRouteState","initialUserSearchFilterSelections","queryReady","initialLocation","stateMapping","stateToRoute","uiState","facetValues","order","routeValue","routeToState","makeStateMapping","facetRouteKey","pageTitle","isPageTitleOverride","convertSearchCategoriesToCategoryPageConfiguration","router","initialUrl","hydration","normalizedTitlePostfix","allFacetingKeysSet","userFilterKeysSet","preserveCustomKeysSet","searchParamKeysSet","categoryPagesByCategoryPageUrl","configuration","getLocation","isReady","ancestorOrigins","contains","Symbol","iterator","hash","host","hostname","origin","port","protocol","reload","cleanUrlOnDispose","createURL","matchingCategoryPage","currentUrl","categoryFacetKeys","err","console","parseURL","locationUrl","locationPathname","addRouteStateFacetValues","queryParams","paramName","paramValue","windowTitle","lastRoute","read","write","bind","notify","onUpdate","callback","syncFromBrowser","route","isEqual","makeRouter","canonicalLink","head","querySelector","canonicalOrigin","canonicalUrl","categoryUrl","getCanonicalSearchUrl","AuthorBatch","initialData","Search","algoliaAppId","algoliaAppKey","algoliaUserTokenCookieDurationInMilliseconds","algoliaIndexName","algoliaSearchParametersJson","userSearchFiltersJson","searchCategories","serverState","initialIsSignedIn","localizedResources","allFilters","filterAndSort","seeResults","show","noResults","checkSpelling","differentKeywords","lessSpecific","seeAllProducts","bestselling","newest","oldest","priceHighToLow","priceLowToHigh","savings","titleSort","progress","relevance","authorIds","genre","language","licensingMethod","productType","publisherIds","region","resourceType","seriesSets","specials","liveStatusText","prepubStatusText","gatheringInterestStatusText","underContractStatusText","almostFundedStatusText","shippingSoonStatusText","inProductionStatusText","shipsFormat","discountFormat","readMore","readLess","addToCart","addingToCart","quickBuy","geoRestrictionMessage","permanentOwnMessage","temporaryOwnMessage","hasPreorderMessage","preorder","UnavailableToPurchase","effectiveIsSignedIn","safeJsonParse","parsedFilters","PerUserDataContextProvider","requestAnonymousPricing","InstantSearchSSRProvider","initialResults"],"sourceRoot":""}