1import { PropsWithChildren, useContext } from 'react';
2
3import { PageApiVersionContext } from '~/providers/page-api-version';
4import { usePageMetadata } from '~/providers/page-metadata';
5import { Terminal } from '~/ui/components/Snippet';
6import { A, P, DEMI } from '~/ui/components/Text';
7
8type InstallSectionProps = PropsWithChildren<{
9  packageName: string;
10  hideBareInstructions?: boolean;
11  cmd?: string[];
12  href?: string;
13}>;
14
15const getPackageLink = (packageNames: string) =>
16  `https://github.com/expo/expo/tree/main/packages/${packageNames.split(' ')[0]}`;
17
18const getInstallCmd = (packageName: string) => `$ npx expo install ${packageName}`;
19
20const InstallSection = ({
21  packageName,
22  hideBareInstructions = false,
23  cmd = [getInstallCmd(packageName)],
24  href = getPackageLink(packageName),
25}: InstallSectionProps) => {
26  const { sourceCodeUrl } = usePageMetadata();
27  const { version } = useContext(PageApiVersionContext);
28
29  // Recommend just `expo install` for SDK 45.
30  // TODO: remove this when we drop SDK 45 from docs
31  if (version.startsWith('v45')) {
32    if (cmd[0] === getInstallCmd(packageName)) {
33      cmd[0] = cmd[0].replace('npx expo', 'expo');
34    }
35  }
36
37  return (
38    <>
39      <Terminal cmd={cmd} />
40      {hideBareInstructions ? null : (
41        <P>
42          If you're installing this in a{' '}
43          <A href="/introduction/managed-vs-bare/#bare-workflow">bare React Native app</A>, you
44          should also follow{' '}
45          <A href={sourceCodeUrl ?? href}>
46            <DEMI>these additional installation instructions</DEMI>
47          </A>
48          .
49        </P>
50      )}
51    </>
52  );
53};
54
55export default InstallSection;
56
57export const APIInstallSection = (props: InstallSectionProps) => {
58  const { packageName } = usePageMetadata();
59  return <InstallSection {...props} packageName={props.packageName ?? packageName} />;
60};
61