1import React from 'react';
2
3import { InlineCode } from '~/components/base/code';
4import { B, P } from '~/components/base/paragraph';
5import { H2, H3Code } from '~/components/plugins/Headings';
6import {
7  CommentData,
8  GeneratedData,
9  MethodSignatureData,
10  PropData,
11  PropsDefinitionData,
12} from '~/components/plugins/api/APIDataTypes';
13import APISectionProps from '~/components/plugins/api/APISectionProps';
14import { CommentTextBlock, resolveTypeName } from '~/components/plugins/api/APISectionUtils';
15
16export type APISectionComponentsProps = {
17  data: GeneratedData[];
18  componentsProps: PropsDefinitionData[];
19};
20
21const getComponentName = (name?: string, children: PropData[] = []) => {
22  if (name && name !== 'default') return name;
23  const ctor = children.filter((child: PropData) => child.name === 'constructor')[0];
24  return ctor?.signatures?.[0]?.type?.name ?? 'default';
25};
26
27const getComponentComment = (comment: CommentData, signatures: MethodSignatureData[]) =>
28  comment || (signatures?.[0]?.comment ?? undefined);
29
30const renderComponent = (
31  { name, comment, type, extendedTypes, children, signatures }: GeneratedData,
32  componentsProps?: PropsDefinitionData[]
33): JSX.Element => {
34  const resolvedType = extendedTypes?.length ? extendedTypes[0] : type;
35  const resolvedName = getComponentName(name, children);
36  return (
37    <div key={`component-definition-${resolvedName}`}>
38      <H3Code>
39        <InlineCode>{resolvedName}</InlineCode>
40      </H3Code>
41      {resolvedType && (
42        <P>
43          <B>Type:</B> <InlineCode>{resolveTypeName(resolvedType)}</InlineCode>
44        </P>
45      )}
46      <CommentTextBlock comment={getComponentComment(comment, signatures)} />
47      {componentsProps && componentsProps.length ? (
48        <APISectionProps data={componentsProps} header={`${resolvedName}Props`} />
49      ) : null}
50    </div>
51  );
52};
53
54const APISectionComponents = ({ data, componentsProps }: APISectionComponentsProps) =>
55  data?.length ? (
56    <>
57      <H2 key="components-header">Components</H2>
58      {data.map(component =>
59        renderComponent(
60          component,
61          componentsProps.filter(cp => cp.name.includes(component.name))
62        )
63      )}
64    </>
65  ) : null;
66
67export default APISectionComponents;
68