1import { css } from '@emotion/react'; 2import { theme, typography } from '@expo/styleguide'; 3import { PropsWithChildren, useContext } from 'react'; 4 5import { PageApiVersionContext } from '~/providers/page-api-version'; 6import { usePageMetadata } from '~/providers/page-metadata'; 7import { Terminal } from '~/ui/components/Snippet'; 8import { A } from '~/ui/components/Text'; 9 10const STYLES_P = css` 11 line-height: 1.8rem; 12 margin-top: 1.4rem; 13 margin-bottom: 1.4rem; 14 color: ${theme.text.default}; 15`; 16 17const STYLES_BOLD = css` 18 font-family: ${typography.fontFaces.medium}; 19 font-weight: 400; 20 text-decoration: none; 21 color: ${theme.link.default}; 22 :hover { 23 text-decoration: underline; 24 } 25`; 26const STYLES_LINK = css` 27 text-decoration: none; 28 color: ${theme.link.default}; 29 :hover { 30 text-decoration: underline; 31 } 32`; 33 34type InstallSectionProps = PropsWithChildren<{ 35 packageName: string; 36 hideBareInstructions?: boolean; 37 cmd?: string[]; 38 href?: string; 39}>; 40 41const getPackageLink = (packageNames: string) => 42 `https://github.com/expo/expo/tree/main/packages/${packageNames.split(' ')[0]}`; 43 44function getInstallCmd(packageName: string) { 45 return `$ npx expo install ${packageName}`; 46} 47 48const InstallSection = ({ 49 packageName, 50 hideBareInstructions = false, 51 cmd = [getInstallCmd(packageName)], 52 href = getPackageLink(packageName), 53}: InstallSectionProps) => { 54 const { sourceCodeUrl } = usePageMetadata(); 55 const { version } = useContext(PageApiVersionContext); 56 57 // Recommend just `expo install` for SDK 43, 44, and 45. 58 // TODO: remove this when we drop SDK 45 from docs 59 if (version.startsWith('v43') || version.startsWith('v44') || version.startsWith('v45')) { 60 if (cmd[0] === getInstallCmd(packageName)) { 61 cmd[0] = cmd[0].replace('npx expo', 'expo'); 62 } 63 } 64 65 return ( 66 <> 67 <Terminal cmd={cmd} /> 68 {hideBareInstructions ? null : ( 69 <p css={STYLES_P}> 70 If you're installing this in a{' '} 71 <A css={STYLES_LINK} href="/introduction/managed-vs-bare/#bare-workflow"> 72 bare React Native app 73 </A> 74 , you should also follow{' '} 75 <A css={STYLES_BOLD} href={sourceCodeUrl ?? href}> 76 these additional installation instructions 77 </A> 78 . 79 </p> 80 )} 81 </> 82 ); 83}; 84 85export default InstallSection; 86 87export const APIInstallSection = (props: InstallSectionProps) => { 88 const { packageName } = usePageMetadata(); 89 return <InstallSection {...props} packageName={props.packageName ?? packageName} />; 90}; 91