xref: /expo/docs/components/plugins/APISection.tsx (revision cbed40ab)
1import React, { useContext } from 'react';
2
3import DocumentationPageContext from '~/components/DocumentationPageContext';
4import { P } from '~/components/base/paragraph';
5import { GeneratedData } from '~/components/plugins/api/APIDataTypes';
6import APISectionComponents from '~/components/plugins/api/APISectionComponents';
7import APISectionConstants from '~/components/plugins/api/APISectionConstants';
8import APISectionEnums from '~/components/plugins/api/APISectionEnums';
9import APISectionInterfaces from '~/components/plugins/api/APISectionInterfaces';
10import APISectionMethods from '~/components/plugins/api/APISectionMethods';
11import APISectionProps from '~/components/plugins/api/APISectionProps';
12import APISectionTypes from '~/components/plugins/api/APISectionTypes';
13import { TypeDocKind } from '~/components/plugins/api/APISectionUtils';
14
15const LATEST_VERSION = `v${require('~/package.json').version}`;
16
17type Props = {
18  packageName: string;
19  apiName?: string;
20};
21
22const filterDataByKind = (
23  entries: GeneratedData[],
24  kind: TypeDocKind,
25  additionalCondition: (entry: GeneratedData) => boolean = () => true
26) =>
27  entries
28    ? entries.filter((entry: GeneratedData) => entry.kind === kind && additionalCondition(entry))
29    : [];
30
31const renderAPI = (
32  packageName: string,
33  version: string = 'unversioned',
34  apiName?: string
35): JSX.Element => {
36  try {
37    const data = require(`~/public/static/data/${version}/${packageName}.json`).children;
38
39    const methods = filterDataByKind(
40      data,
41      TypeDocKind.Function,
42      entry => !entry.name.includes('Listener')
43    );
44    const eventSubscriptions = filterDataByKind(data, TypeDocKind.Function, entry =>
45      entry.name.includes('Listener')
46    );
47    const types = filterDataByKind(
48      data,
49      TypeDocKind.TypeAlias,
50      entry =>
51        !entry.name.includes('Props') &&
52        !!(
53          entry.type.declaration ||
54          entry.type.types ||
55          entry.type.type ||
56          entry.type.typeArguments
57        )
58    );
59
60    const props = filterDataByKind(
61      data,
62      TypeDocKind.TypeAlias,
63      entry =>
64        entry.name.includes('Props') &&
65        (!!entry.type.types || // inheritance
66          !!entry.type.declaration?.children) // no inheritance
67    );
68    const defaultProps = filterDataByKind(
69      data
70        .filter((entry: GeneratedData) => entry.kind === TypeDocKind.Class)
71        .map((entry: GeneratedData) => entry.children)
72        .flat(),
73      TypeDocKind.Property,
74      entry => entry.name === 'defaultProps'
75    )[0];
76
77    const enums = filterDataByKind(data, TypeDocKind.Enum);
78    const interfaces = filterDataByKind(data, TypeDocKind.Interface);
79    const constants = filterDataByKind(
80      data,
81      TypeDocKind.Variable,
82      entry => (entry?.flags?.isConst || false) && entry?.type?.name !== 'React.FC'
83    );
84
85    const components = filterDataByKind(
86      data,
87      TypeDocKind.Variable,
88      entry => entry?.type?.name === 'React.FC'
89    );
90    const componentsPropNames = components.map(component => `${component.name}Props`);
91    const componentsProps = filterDataByKind(props, TypeDocKind.TypeAlias, entry =>
92      componentsPropNames.includes(entry.name)
93    );
94
95    return (
96      <>
97        <APISectionComponents data={components} componentsProps={componentsProps} />
98        <APISectionConstants data={constants} apiName={apiName} />
99        <APISectionMethods data={methods} apiName={apiName} />
100        <APISectionMethods
101          data={eventSubscriptions}
102          apiName={apiName}
103          header="Event Subscriptions"
104        />
105        {props && !componentsProps.length ? (
106          <APISectionProps data={props} defaultProps={defaultProps} />
107        ) : null}
108        <APISectionTypes data={types} />
109        <APISectionInterfaces data={interfaces} />
110        <APISectionEnums data={enums} />
111      </>
112    );
113  } catch (error) {
114    return <P>No API data file found, sorry!</P>;
115  }
116};
117
118const APISection: React.FC<Props> = ({ packageName, apiName }) => {
119  const { version } = useContext(DocumentationPageContext);
120  const resolvedVersion =
121    version === 'unversioned' ? version : version === 'latest' ? LATEST_VERSION : version;
122  return renderAPI(packageName, resolvedVersion, apiName);
123};
124
125export default APISection;
126