1f4b1168bSBartosz Kaszubowskiimport { SearchSmIcon, XIcon } from '@expo/styleguide-icons'; 289d2c67fSBartosz Kaszubowskiimport { Command } from 'cmdk'; 389d2c67fSBartosz Kaszubowskiimport { useEffect, useState } from 'react'; 489d2c67fSBartosz Kaszubowskiimport type { Dispatch, SetStateAction } from 'react'; 589d2c67fSBartosz Kaszubowski 689d2c67fSBartosz Kaszubowskiimport { BarLoader } from './BarLoader'; 789d2c67fSBartosz Kaszubowskiimport { CommandFooter } from './CommandFooter'; 889d2c67fSBartosz Kaszubowskiimport { RNDirectoryItem, RNDocsItem, ExpoDocsItem, ExpoItem } from './Items'; 989d2c67fSBartosz Kaszubowskiimport { entries } from './expoEntries'; 1089d2c67fSBartosz Kaszubowskiimport { searchIconStyle, closeIconStyle } from './styles'; 1189d2c67fSBartosz Kaszubowskiimport type { ExpoItemType, RNDirectoryItemType, AlgoliaItemType } from './types'; 1289d2c67fSBartosz Kaszubowskiimport { getExpoDocsResults, getRNDocsResults, getDirectoryResults, getItemsAsync } from './utils'; 1389d2c67fSBartosz Kaszubowski 1489d2c67fSBartosz Kaszubowskiimport { CALLOUT } from '~/ui/components/Text'; 1589d2c67fSBartosz Kaszubowski 1689d2c67fSBartosz Kaszubowskitype Props = { 1789d2c67fSBartosz Kaszubowski version: string; 1889d2c67fSBartosz Kaszubowski open: boolean; 1989d2c67fSBartosz Kaszubowski setOpen: Dispatch<SetStateAction<boolean>>; 2089d2c67fSBartosz Kaszubowski}; 2189d2c67fSBartosz Kaszubowski 2289d2c67fSBartosz Kaszubowskiexport const CommandMenu = ({ version, open, setOpen }: Props) => { 238a411220SBartosz Kaszubowski const [initialized, setInitialized] = useState(false); 2489d2c67fSBartosz Kaszubowski const [loading, setLoading] = useState(false); 2589d2c67fSBartosz Kaszubowski const [query, setQuery] = useState(''); 2689d2c67fSBartosz Kaszubowski const [expoDocsItems, setExpoDocsItems] = useState<AlgoliaItemType[]>([]); 2789d2c67fSBartosz Kaszubowski const [expoItems, setExpoItems] = useState<ExpoItemType[]>([]); 2889d2c67fSBartosz Kaszubowski const [rnDocsItems, setRnDocsItems] = useState<AlgoliaItemType[]>([]); 2989d2c67fSBartosz Kaszubowski const [directoryItems, setDirectoryItems] = useState<RNDirectoryItemType[]>([]); 3089d2c67fSBartosz Kaszubowski 3189d2c67fSBartosz Kaszubowski const getExpoDocsItems = async () => 3289d2c67fSBartosz Kaszubowski getItemsAsync(query, getExpoDocsResults, setExpoDocsItems, version); 3389d2c67fSBartosz Kaszubowski const getRNDocsItems = async () => getItemsAsync(query, getRNDocsResults, setRnDocsItems); 3489d2c67fSBartosz Kaszubowski const getDirectoryItems = async () => 3589d2c67fSBartosz Kaszubowski getItemsAsync(query, getDirectoryResults, setDirectoryItems); 3689d2c67fSBartosz Kaszubowski 3789d2c67fSBartosz Kaszubowski const getExpoItems = async () => { 3889d2c67fSBartosz Kaszubowski setExpoItems(entries.filter(entry => entry.label.toLowerCase().includes(query.toLowerCase()))); 3989d2c67fSBartosz Kaszubowski }; 4089d2c67fSBartosz Kaszubowski 4189d2c67fSBartosz Kaszubowski const dismiss = () => setOpen(false); 4289d2c67fSBartosz Kaszubowski 438a411220SBartosz Kaszubowski const fetchData = (callback: () => void) => { 4489d2c67fSBartosz Kaszubowski Promise.all([getExpoDocsItems(), getRNDocsItems(), getDirectoryItems(), getExpoItems()]).then( 458a411220SBartosz Kaszubowski callback 4689d2c67fSBartosz Kaszubowski ); 4789d2c67fSBartosz Kaszubowski }; 4889d2c67fSBartosz Kaszubowski 4989d2c67fSBartosz Kaszubowski const onQueryChange = () => { 508a411220SBartosz Kaszubowski if (open) { 5189d2c67fSBartosz Kaszubowski setLoading(true); 528a411220SBartosz Kaszubowski const inputTimeout = setTimeout(() => fetchData(() => setLoading(false)), 150); 5389d2c67fSBartosz Kaszubowski return () => clearTimeout(inputTimeout); 548a411220SBartosz Kaszubowski } 5589d2c67fSBartosz Kaszubowski }; 5689d2c67fSBartosz Kaszubowski 578a411220SBartosz Kaszubowski const onMenuOpen = () => { 588a411220SBartosz Kaszubowski if (open && !initialized) { 598a411220SBartosz Kaszubowski fetchData(() => { 608a411220SBartosz Kaszubowski setInitialized(true); 618a411220SBartosz Kaszubowski setLoading(false); 628a411220SBartosz Kaszubowski }); 638a411220SBartosz Kaszubowski } 648a411220SBartosz Kaszubowski }; 658a411220SBartosz Kaszubowski 668a411220SBartosz Kaszubowski useEffect(onMenuOpen, [open]); 6789d2c67fSBartosz Kaszubowski useEffect(onQueryChange, [query]); 6889d2c67fSBartosz Kaszubowski 6989d2c67fSBartosz Kaszubowski const totalCount = 7089d2c67fSBartosz Kaszubowski expoDocsItems.length + rnDocsItems.length + directoryItems.length + expoItems.length; 7189d2c67fSBartosz Kaszubowski 7289d2c67fSBartosz Kaszubowski return ( 7389d2c67fSBartosz Kaszubowski <Command.Dialog open={open} onOpenChange={setOpen} label="Search Menu" shouldFilter={false}> 74f4b1168bSBartosz Kaszubowski <SearchSmIcon className="text-icon-secondary" css={searchIconStyle} /> 75f4b1168bSBartosz Kaszubowski <div css={closeIconStyle}> 76f4b1168bSBartosz Kaszubowski <XIcon className="text-icon-secondary" onClick={() => setOpen(false)} /> 77f4b1168bSBartosz Kaszubowski </div> 78*e5be0ff4SAman Mittal <Command.Input value={query} onValueChange={setQuery} placeholder="Search…" /> 7989d2c67fSBartosz Kaszubowski <BarLoader isLoading={loading} /> 8089d2c67fSBartosz Kaszubowski <Command.List> 818a411220SBartosz Kaszubowski {initialized && ( 828a411220SBartosz Kaszubowski <> 8389d2c67fSBartosz Kaszubowski {expoDocsItems.length > 0 && ( 8489d2c67fSBartosz Kaszubowski <Command.Group heading="Expo documentation"> 8589d2c67fSBartosz Kaszubowski {expoDocsItems.map(item => ( 868a411220SBartosz Kaszubowski <ExpoDocsItem 878a411220SBartosz Kaszubowski item={item} 888a411220SBartosz Kaszubowski onSelect={dismiss} 898a411220SBartosz Kaszubowski key={`hit-expo-docs-${item.objectID}`} 908a411220SBartosz Kaszubowski /> 9189d2c67fSBartosz Kaszubowski ))} 9289d2c67fSBartosz Kaszubowski </Command.Group> 9389d2c67fSBartosz Kaszubowski )} 9489d2c67fSBartosz Kaszubowski {expoItems.length > 0 && ( 9589d2c67fSBartosz Kaszubowski <Command.Group heading="Expo dashboard"> 9689d2c67fSBartosz Kaszubowski {expoItems.map((item: ExpoItemType) => ( 978a411220SBartosz Kaszubowski <ExpoItem 988a411220SBartosz Kaszubowski item={item} 998a411220SBartosz Kaszubowski onSelect={dismiss} 1008a411220SBartosz Kaszubowski key={`hit-expo-${item.url}`} 1018a411220SBartosz Kaszubowski query={query} 1028a411220SBartosz Kaszubowski /> 10389d2c67fSBartosz Kaszubowski ))} 10489d2c67fSBartosz Kaszubowski </Command.Group> 10589d2c67fSBartosz Kaszubowski )} 10689d2c67fSBartosz Kaszubowski {rnDocsItems.length > 0 && ( 10789d2c67fSBartosz Kaszubowski <Command.Group heading="React Native documentation"> 10889d2c67fSBartosz Kaszubowski {rnDocsItems.map(item => ( 10989d2c67fSBartosz Kaszubowski <RNDocsItem item={item} onSelect={dismiss} key={`hit-rn-docs-${item.objectID}`} /> 11089d2c67fSBartosz Kaszubowski ))} 11189d2c67fSBartosz Kaszubowski </Command.Group> 11289d2c67fSBartosz Kaszubowski )} 11389d2c67fSBartosz Kaszubowski {directoryItems.length > 0 && ( 11489d2c67fSBartosz Kaszubowski <Command.Group heading="React Native directory"> 11589d2c67fSBartosz Kaszubowski {directoryItems.map(item => ( 11689d2c67fSBartosz Kaszubowski <RNDirectoryItem 11789d2c67fSBartosz Kaszubowski item={item} 11889d2c67fSBartosz Kaszubowski onSelect={dismiss} 11989d2c67fSBartosz Kaszubowski key={`hit-rn-dir-${item.npmPkg}`} 12089d2c67fSBartosz Kaszubowski query={query} 12189d2c67fSBartosz Kaszubowski /> 12289d2c67fSBartosz Kaszubowski ))} 12389d2c67fSBartosz Kaszubowski </Command.Group> 12489d2c67fSBartosz Kaszubowski )} 1258a411220SBartosz Kaszubowski {!loading && totalCount === 0 && ( 12689d2c67fSBartosz Kaszubowski <Command.Empty> 12789d2c67fSBartosz Kaszubowski <CALLOUT theme="secondary">No results found.</CALLOUT> 12889d2c67fSBartosz Kaszubowski </Command.Empty> 12989d2c67fSBartosz Kaszubowski )} 1308a411220SBartosz Kaszubowski </> 1318a411220SBartosz Kaszubowski )} 13289d2c67fSBartosz Kaszubowski </Command.List> 13389d2c67fSBartosz Kaszubowski <CommandFooter /> 13489d2c67fSBartosz Kaszubowski </Command.Dialog> 13589d2c67fSBartosz Kaszubowski ); 13689d2c67fSBartosz Kaszubowski}; 137