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 comment={signatureComment} components={mdInlineComponents} />
49            {renderDefaultValue(defaultValue)}
50          </>
51        )}
52      </>
53    );
54  } else {
55    const defaultValue = getTagData('default', comment);
56    return comment ? (
57      <>
58        <CommentTextBlock comment={comment} components={mdInlineComponents} />
59        {renderDefaultValue(defaultValue)}
60      </>
61    ) : (
62      '-'
63    );
64  }
65};
66
67const renderInterfacePropertyRow = ({
68  name,
69  flags,
70  type,
71  comment,
72  signatures,
73}: PropData): JSX.Element => (
74  <tr key={name}>
75    <td>
76      <B>
77        {name}
78        {signatures && signatures.length ? '()' : ''}
79      </B>
80      {renderFlags(flags)}
81    </td>
82    <td>{renderTypeOrSignatureType(type, signatures)}</td>
83    <td>{renderInterfaceComment(comment, signatures)}</td>
84  </tr>
85);
86
87const renderInterface = ({
88  name,
89  children,
90  comment,
91  extendedTypes,
92}: InterfaceDefinitionData): JSX.Element | null =>
93  children ? (
94    <div key={`interface-definition-${name}`}>
95      <H3Code>
96        <InlineCode>{name}</InlineCode>
97      </H3Code>
98      {extendedTypes?.length && (
99        <P>
100          <B>Extends: </B>
101          {extendedTypes.map(extendedType => (
102            <InlineCode key={`extend-${extendedType.name}`}>
103              {resolveTypeName(extendedType)}
104            </InlineCode>
105          ))}
106        </P>
107      )}
108      <CommentTextBlock comment={comment} />
109      <table>
110        <thead>
111          <tr>
112            <th>Name</th>
113            <th>Type</th>
114            <th>Description</th>
115          </tr>
116        </thead>
117        <tbody>
118          {children.filter(child => !child?.inheritedFrom).map(renderInterfacePropertyRow)}
119        </tbody>
120      </table>
121    </div>
122  ) : null;
123
124const APISectionInterfaces = ({ data }: APISectionInterfacesProps) =>
125  data?.length ? (
126    <>
127      <H2 key="interfaces-header">Interfaces</H2>
128      {data.map(renderInterface)}
129    </>
130  ) : null;
131
132export default APISectionInterfaces;
133