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';
22import { Cell, HeaderCell, Row, Table, TableHead } from '~/ui/components/Table';
23
24export type APISectionInterfacesProps = {
25  data: InterfaceDefinitionData[];
26};
27
28const renderDefaultValue = (defaultValue?: CommentTagData) =>
29  defaultValue ? (
30    <>
31      <br />
32      <br />
33      <B>Default:</B> <InlineCode>{defaultValue.text}</InlineCode>
34    </>
35  ) : null;
36
37const renderInterfaceComment = (comment?: CommentData, signatures?: MethodSignatureData[]) => {
38  if (signatures && signatures.length) {
39    const { type, parameters, comment: signatureComment } = signatures[0];
40    const defaultValue = getTagData('default', signatureComment);
41    return (
42      <>
43        {parameters?.length ? parameters.map(param => renderParam(param)) : null}
44        <B>Returns: </B>
45        <InlineCode>{resolveTypeName(type)}</InlineCode>
46        {signatureComment && (
47          <>
48            <br />
49            <CommentTextBlock
50              comment={signatureComment}
51              components={mdInlineComponents}
52              afterContent={renderDefaultValue(defaultValue)}
53            />
54          </>
55        )}
56      </>
57    );
58  } else {
59    const defaultValue = getTagData('default', comment);
60    return comment ? (
61      <CommentTextBlock
62        comment={comment}
63        components={mdInlineComponents}
64        afterContent={renderDefaultValue(defaultValue)}
65      />
66    ) : (
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        <TableHead>
116          <Row>
117            <HeaderCell>Name</HeaderCell>
118            <HeaderCell>Type</HeaderCell>
119            <HeaderCell>Description</HeaderCell>
120          </Row>
121        </TableHead>
122        <tbody>
123          {children.filter(child => !child?.inheritedFrom).map(renderInterfacePropertyRow)}
124        </tbody>
125      </Table>
126    </div>
127  ) : null;
128
129const APISectionInterfaces = ({ data }: APISectionInterfacesProps) =>
130  data?.length ? (
131    <>
132      <H2 key="interfaces-header">Interfaces</H2>
133      {data.map(renderInterface)}
134    </>
135  ) : null;
136
137export default APISectionInterfaces;
138