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