import { faSearch } from '@fortawesome/free-solid-svg-icons' ; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' ; import classNames from 'classnames' ; import dynamic from 'next/dynamic' ; import { useCallback , useRef , useState } from 'react' ; import type { Event } from '../../../types' ; import { useMousetrap } from '../../hooks/useMousetrap' ; import { Keyboard } from '../../ui/Keyboard' ; import { Typography } from '../../ui/Typography' ; import type { SearchProps } from '../Search' ; const Search = dynamic < SearchProps > ( async ( ) => import ( '../Search' ) . then ( ( m ) => m . Search ) , { ssr : false } ) ; export interface SearchButtonProps { readonly events ? : readonly Event [ ] ; readonly loading ? : boolean ; } export const SearchButton = ( props ) : JSX . Element => { const { events , loading } = props ; const ref = useRef < HTMLButtonElement | null > ( null ) ; const [ open , setOpen ] = useState ( false ) ; const handleOpen = useCallback ( ( ) => { setOpen ( true ) ; gtag ( 'event' , 'open_search' ) ; } , [ setOpen ] ) ; const handleClose = useCallback ( ( ) => { setOpen ( false ) ; ref . current ?. focus ( ) ; } , [ setOpen ] ) ; useMousetrap ( [ 'command+k' , 'ctrl+k' , '/' ] , ( ) => { handleOpen ( ) ; return false ; } ) ; return ( < > { typeof window !== 'undefined' && ( < Search show = { open } loading = { loading } events = { events } onHide = { handleClose } / > ) } < button ref = { ref } className = { classNames ( 'flex' , 'items-center' , 'justify-between' , 'w-full' , 'p-2' , 'box-border' , 'rounded-md' , 'bg-gray-100' , 'dark:bg-neutral-900' , 'text-gray-500' , 'dark:text-neutral-500' , 'focus:outline-none' , 'focus-visible:ring' , 'focus-visible:ring-primary-200' ) } onClick = { ( ) => void handleOpen ( ) } > < div className = "space-x-2" > < FontAwesomeIcon icon = { faSearch } fixedWidth / > < Typography variant = "wash" as = "span" > 検索 < /Typography> < /div> < Keyboard > Ctrl + K < /Keyboard> < /button> < />); } ;