1import {
2  CommentData,
3  GeneratedData,
4  MethodSignatureData,
5  PropsDefinitionData,
6} from '~/components/plugins/api/APIDataTypes';
7import { APISectionDeprecationNote } from '~/components/plugins/api/APISectionDeprecationNote';
8import APISectionProps from '~/components/plugins/api/APISectionProps';
9import {
10  CommentTextBlock,
11  resolveTypeName,
12  getComponentName,
13  STYLES_APIBOX,
14  getTagNamesList,
15  H3Code,
16  ELEMENT_SPACING,
17} from '~/components/plugins/api/APISectionUtils';
18import { H2, BOLD, P, CODE, MONOSPACE } from '~/ui/components/Text';
19
20export type APISectionComponentsProps = {
21  data: GeneratedData[];
22  componentsProps: PropsDefinitionData[];
23};
24
25const getComponentComment = (comment: CommentData, signatures: MethodSignatureData[]) =>
26  comment || (signatures?.[0]?.comment ?? undefined);
27
28const getComponentType = ({ signatures }: Partial<GeneratedData>) => {
29  if (signatures?.length && signatures[0].type.types) {
30    return 'React.' + signatures[0].type.types.filter(t => t.type === 'reference')[0]?.name;
31  }
32  return 'React.Element';
33};
34
35const getComponentTypeParameters = ({
36  extendedTypes,
37  type,
38  signatures,
39}: Partial<GeneratedData>) => {
40  if (extendedTypes?.length) {
41    return extendedTypes[0];
42  } else if (signatures?.length && signatures[0].parameters.length) {
43    return signatures?.[0].parameters[0].type;
44  }
45  return type;
46};
47
48const renderComponent = (
49  { name, comment, type, extendedTypes, children, signatures }: GeneratedData,
50  componentsProps?: PropsDefinitionData[]
51): JSX.Element => {
52  const resolvedType = getComponentType({ signatures });
53  const resolvedTypeParameters = getComponentTypeParameters({ type, extendedTypes, signatures });
54  const resolvedName = getComponentName(name, children);
55  const extractedComment = getComponentComment(comment, signatures);
56  return (
57    <div key={`component-definition-${resolvedName}`} css={STYLES_APIBOX}>
58      <APISectionDeprecationNote comment={extractedComment} />
59      <H3Code tags={getTagNamesList(comment)}>
60        <MONOSPACE weight="medium">{resolvedName}</MONOSPACE>
61      </H3Code>
62      {resolvedType && resolvedTypeParameters && (
63        <P className={ELEMENT_SPACING}>
64          <BOLD>Type:</BOLD>{' '}
65          <CODE>
66            {extendedTypes ? (
67              <>React.{resolveTypeName(resolvedTypeParameters)}</>
68            ) : (
69              <>
70                {resolvedType}&lt;{resolveTypeName(resolvedTypeParameters)}&gt;
71              </>
72            )}
73          </CODE>
74        </P>
75      )}
76      <CommentTextBlock comment={extractedComment} />
77      {componentsProps && componentsProps.length ? (
78        <APISectionProps
79          data={componentsProps}
80          header={componentsProps.length === 1 ? 'Props' : `${resolvedName}Props`}
81        />
82      ) : null}
83    </div>
84  );
85};
86
87const APISectionComponents = ({ data, componentsProps }: APISectionComponentsProps) =>
88  data?.length ? (
89    <>
90      <H2 key="components-header">{data.length === 1 ? 'Component' : 'Components'}</H2>
91      {data.map(component =>
92        renderComponent(
93          component,
94          componentsProps.filter(cp =>
95            cp.name.includes(getComponentName(component.name, component.children))
96          )
97        )
98      )}
99    </>
100  ) : null;
101
102export default APISectionComponents;
103