1import { DocsLogo } from '@expo/styleguide'; 2import { PlanEnterpriseIcon, BookOpen02Icon } from '@expo/styleguide-icons'; 3import { Command } from 'cmdk'; 4 5import type { AlgoliaItemType } from '../types'; 6import { getContentHighlightHTML, getHighlightHTML, isEASPath, openLink } from '../utils'; 7import { FootnoteSection } from './FootnoteSection'; 8import { FootnoteArrowIcon } from './icons'; 9import { contentStyle, footnoteStyle, itemIconWrapperStyle, itemStyle } from './styles'; 10 11import versions from '~/public/static/constants/versions.json'; 12import { CALLOUT, FOOTNOTE } from '~/ui/components/Text'; 13 14const { LATEST_VERSION } = versions; 15 16type Props = { 17 item: AlgoliaItemType; 18 onSelect?: () => void; 19}; 20 21const isDev = process.env.NODE_ENV === 'development'; 22 23const ItemIcon = ({ url }: { url: string }) => { 24 if (url.includes('/versions/')) { 25 return <DocsLogo className="text-icon-secondary" />; 26 } else if (isEASPath(url)) { 27 return <PlanEnterpriseIcon className="text-icon-secondary" />; 28 } 29 return <BookOpen02Icon className="text-icon-secondary" />; 30}; 31 32const getFootnotePrefix = (url: string) => { 33 if (url.includes('/versions/')) { 34 return 'API Reference'; 35 } else if (isEASPath(url)) { 36 return 'Expo Application Services'; 37 } else { 38 return 'Guides'; 39 } 40}; 41 42const ItemFootnotePrefix = ({ url, isNested = false }: { url: string; isNested?: boolean }) => { 43 return isNested ? ( 44 <> 45 <span css={footnoteStyle}>{getFootnotePrefix(url)}</span> 46 <FootnoteArrowIcon /> 47 </> 48 ) : ( 49 <FOOTNOTE css={footnoteStyle}>{getFootnotePrefix(url)}</FOOTNOTE> 50 ); 51}; 52 53const transformUrl = (url: string) => { 54 if (url.includes(LATEST_VERSION)) { 55 url = url.replace(LATEST_VERSION, 'latest'); 56 } 57 if (isDev) { 58 url = url.replace('https://docs.expo.dev/', 'http://localhost:3002/'); 59 } 60 return url; 61}; 62 63export const ExpoDocsItem = ({ item, onSelect }: Props) => { 64 const { lvl0, lvl2, lvl3, lvl4, lvl6 } = item.hierarchy; 65 return ( 66 <Command.Item 67 value={`expodocs-${item.objectID}`} 68 onSelect={() => { 69 openLink(transformUrl(item.url)); 70 onSelect && onSelect(); 71 }}> 72 <div css={itemStyle}> 73 <div css={itemIconWrapperStyle}> 74 <ItemIcon url={item.url} /> 75 </div> 76 <div> 77 {lvl6 && ( 78 <> 79 <CALLOUT weight="medium" {...getHighlightHTML(item, 'lvl6')} /> 80 <FOOTNOTE css={footnoteStyle}> 81 <ItemFootnotePrefix url={item.url} isNested /> 82 <span {...getHighlightHTML(item, 'lvl0')} /> 83 <FootnoteSection item={item} levelKey="lvl2" /> 84 <FootnoteSection item={item} levelKey="lvl3" /> 85 <FootnoteSection item={item} levelKey="lvl4" /> 86 </FOOTNOTE> 87 </> 88 )} 89 {!lvl6 && lvl4 && ( 90 <> 91 <CALLOUT weight="medium" {...getHighlightHTML(item, 'lvl4')} /> 92 <FOOTNOTE css={footnoteStyle}> 93 <ItemFootnotePrefix url={item.url} isNested /> 94 <span {...getHighlightHTML(item, 'lvl0')} /> 95 <FootnoteSection item={item} levelKey="lvl2" /> 96 <FootnoteSection item={item} levelKey="lvl3" /> 97 </FOOTNOTE> 98 </> 99 )} 100 {!lvl6 && !lvl4 && lvl3 && ( 101 <> 102 <CALLOUT weight="medium" {...getHighlightHTML(item, 'lvl3')} /> 103 <FOOTNOTE css={footnoteStyle}> 104 <ItemFootnotePrefix url={item.url} isNested /> 105 <span {...getHighlightHTML(item, 'lvl0')} /> 106 <FootnoteSection item={item} levelKey="lvl2" /> 107 </FOOTNOTE> 108 </> 109 )} 110 {!lvl6 && !lvl4 && !lvl3 && lvl2 && ( 111 <> 112 <CALLOUT weight="medium" {...getHighlightHTML(item, 'lvl2')} /> 113 <FOOTNOTE css={footnoteStyle}> 114 <ItemFootnotePrefix url={item.url} isNested /> 115 <span {...getHighlightHTML(item, 'lvl0')} /> 116 </FOOTNOTE> 117 </> 118 )} 119 {!lvl6 && !lvl4 && !lvl3 && !lvl2 && lvl0 && ( 120 <> 121 <CALLOUT weight="medium" {...getHighlightHTML(item, 'lvl0')} /> 122 <ItemFootnotePrefix url={item.url} /> 123 </> 124 )} 125 <FOOTNOTE theme="secondary" {...getContentHighlightHTML(item)} css={contentStyle} /> 126 </div> 127 </div> 128 </Command.Item> 129 ); 130}; 131