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