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  CommentTagData,
9  InterfaceDefinitionData,
10  MethodSignatureData,
11  PropData,
12} from '~/components/plugins/api/APIDataTypes';
13import {
14  CommentTextBlock,
15  getTagData,
16  mdInlineComponents,
17  renderFlags,
18  renderParam,
19  renderTypeOrSignatureType,
20  resolveTypeName,
21} from '~/components/plugins/api/APISectionUtils';
22
23export type APISectionInterfacesProps = {
24  data: InterfaceDefinitionData[];
25};
26
27const renderDefaultValue = (defaultValue?: CommentTagData) =>
28  defaultValue ? (
29    <>
30      <br />
31      <br />
32      <B>Default:</B> <InlineCode>{defaultValue.text}</InlineCode>
33    </>
34  ) : null;
35
36const renderInterfaceComment = (comment?: CommentData, signatures?: MethodSignatureData[]) => {
37  if (signatures && signatures.length) {
38    const { type, parameters, comment: signatureComment } = signatures[0];
39    const defaultValue = getTagData('default', signatureComment);
40    return (
41      <>
42        {parameters?.length ? parameters.map(param => renderParam(param)) : null}
43        <B>Returns: </B>
44        <InlineCode>{resolveTypeName(type)}</InlineCode>
45        {signatureComment && (
46          <>
47            <br />
48            <CommentTextBlock
49              comment={signatureComment}
50              components={mdInlineComponents}
51              afterContent={renderDefaultValue(defaultValue)}
52            />
53          </>
54        )}
55      </>
56    );
57  } else {
58    const defaultValue = getTagData('default', comment);
59    return comment ? (
60      <CommentTextBlock
61        comment={comment}
62        components={mdInlineComponents}
63        afterContent={renderDefaultValue(defaultValue)}
64      />
65    ) : (
66      '-'
67    );
68  }
69};
70
71const renderInterfacePropertyRow = ({
72  name,
73  flags,
74  type,
75  comment,
76  signatures,
77}: PropData): JSX.Element => (
78  <tr key={name}>
79    <td>
80      <B>
81        {name}
82        {signatures && signatures.length ? '()' : ''}
83      </B>
84      {renderFlags(flags)}
85    </td>
86    <td>{renderTypeOrSignatureType(type, signatures)}</td>
87    <td>{renderInterfaceComment(comment, signatures)}</td>
88  </tr>
89);
90
91const renderInterface = ({
92  name,
93  children,
94  comment,
95  extendedTypes,
96}: InterfaceDefinitionData): JSX.Element | null =>
97  children ? (
98    <div key={`interface-definition-${name}`}>
99      <H3Code>
100        <InlineCode>{name}</InlineCode>
101      </H3Code>
102      {extendedTypes?.length && (
103        <P>
104          <B>Extends: </B>
105          {extendedTypes.map(extendedType => (
106            <InlineCode key={`extend-${extendedType.name}`}>
107              {resolveTypeName(extendedType)}
108            </InlineCode>
109          ))}
110        </P>
111      )}
112      <CommentTextBlock comment={comment} />
113      <table>
114        <thead>
115          <tr>
116            <th>Name</th>
117            <th>Type</th>
118            <th>Description</th>
119          </tr>
120        </thead>
121        <tbody>
122          {children.filter(child => !child?.inheritedFrom).map(renderInterfacePropertyRow)}
123        </tbody>
124      </table>
125    </div>
126  ) : null;
127
128const APISectionInterfaces = ({ data }: APISectionInterfacesProps) =>
129  data?.length ? (
130    <>
131      <H2 key="interfaces-header">Interfaces</H2>
132      {data.map(renderInterface)}
133    </>
134  ) : null;
135
136export default APISectionInterfaces;
137