import type { AutocompleteState } from '@algolia/autocomplete-js' ; import type { SearchClient } from 'algoliasearch/lite' ; import classNames from 'classnames' ; import { m } from 'framer-motion' ; import { atom } from 'jotai' ; import { useAtomValue , useUpdateAtom } from 'jotai/utils' ; import { useRouter } from 'next/router' ; import { useCallback , useEffect , useMemo , useRef } from 'react' ; import { AutocompleteBasic , autocompleteStateAtom , } from '@autocomplete/basic/autocomplete-basic' ; import { searchQueryAtom } from '@/components/@instantsearch/hooks/useUrlSync' ; import { overlayAtom } from '@/components/overlay/overlay' ; import { configAtom } from '@/config/config' ; import { useIsMounted } from '@/hooks/useIsMounted' ; import { useTailwindScreens } from '@/hooks/useTailwindScreens' ; import { searchClientAtom } from '@/layouts/app-layout' ; const transition = { type : 'spring' , duration : 0.6 , } ; const isFocusedAtom = atom ( false ) ; const isExpandedAtom = atom ( ( get ) => get ( isFocusedAtom ) || Boolean ( get ( autocompleteStateAtom ) ?. query ) ) ; export function NavAutocomplete ( ) { const { laptop } = useTailwindScreens ( ) ; const router = useRouter ( ) ; const isHomePage = useMemo ( ( ) => router ?. pathname === '/' , [ router ?. pathname ] ) ; const { autocomplete : autocompleteConfig } = useAtomValue ( configAtom ) ; const { current : initialQuery } = useRef ( useAtomValue ( searchQueryAtom ) ) ; const searchClient = useAtomValue ( searchClientAtom ) as SearchClient ; const isMounted = useIsMounted ( ) ; const isExpanded = useAtomValue ( isExpandedAtom ) && isMounted ( ) ; const setIsFocused = useUpdateAtom ( isFocusedAtom ) ; const setOverlay = useUpdateAtom ( overlayAtom ) ; const autocompleteState = useAtomValue ( autocompleteStateAtom ) ; const autocompleteIsOpen = Boolean ( autocompleteState ?. isOpen ) ; useEffect ( ( ) => { setOverlay ( { visible : autocompleteIsOpen , blur : isHomePage , zIndex : 'z-overlay-header' , } ) ; } , [ setOverlay , autocompleteIsOpen , isHomePage ] ) ; const handleFocusBlur = useCallback ( ( focused ) => setIsFocused ( focused ) , [ ] ) ; const handleSelect = useCallback ( ( query = '' ) => { router . push ( `/catalog?q=${ query }` ) ; } , [ ] ) ; const handleShouldPanelOpen = useCallback ( ( { state } ) => ( Boolean ( state . query ) && Boolean ( state . collections . reduce ( ( acc , c ) => acc + c . items . length , 0 ) ) ) || ! laptop , [ ] ) ; const autocompleteCn = classNames ( 'w-full pl-2.5 laptop:w-80 laptop:p-0 laptop:ease-out laptop:absolute laptop:right-0' , { focused : isExpanded } ) ; const width = isExpanded ? '90%' : '20rem' ; return ( < m . div className = { autocompleteCn } animate = { { width : laptop ? width : '100%' } } transition = { transition } > < div className = "hidden absolute w-24 h-full -translate-x-full bg-gradient-to-l from-white laptop:block" / > < AutocompleteBasic initialQuery = { initialQuery } searchClient = { searchClient } placeholders = { autocompleteConfig . placeholders } shouldPanelOpen = { handleShouldPanelOpen } openOnFocus = { ! laptop } onFocusBlur = { handleFocusBlur } onSelect = { handleSelect } / > < /m.div>); }