1import React from 'react';
2import ReactMarkdown from 'react-markdown';
3
4import { InlineCode } from '~/components/base/code';
5import { B } from '~/components/base/paragraph';
6import { H2, H3Code } from '~/components/plugins/Headings';
7import {
8  CommentData,
9  InterfaceDefinitionData,
10  InterfaceValueData,
11  MethodSignatureData,
12  TypeDefinitionData,
13} from '~/components/plugins/api/APIDataTypes';
14import {
15  CommentTextBlock,
16  listParams,
17  mdInlineRenderers,
18  renderParam,
19  resolveTypeName,
20  STYLES_OPTIONAL,
21} from '~/components/plugins/api/APISectionUtils';
22
23export type APISectionInterfacesProps = {
24  data: InterfaceDefinitionData[];
25};
26
27const renderInterfaceType = (type?: TypeDefinitionData, signatures?: MethodSignatureData[]) => {
28  if (type) {
29    return <InlineCode>{resolveTypeName(type)}</InlineCode>;
30  } else if (signatures && signatures.length) {
31    const { type, parameters } = signatures[0];
32    return (
33      <InlineCode>
34        ({listParams(parameters)}) =&gt; {resolveTypeName(type)}
35      </InlineCode>
36    );
37  }
38  return undefined;
39};
40
41const renderInterfaceComment = (comment?: CommentData, signatures?: MethodSignatureData[]) => {
42  if (signatures && signatures.length) {
43    const { type, parameters } = signatures[0];
44    return (
45      <>
46        {parameters.map(param => renderParam(param))}
47        <B>Returns: </B>
48        <InlineCode>{resolveTypeName(type)}</InlineCode>
49      </>
50    );
51  } else {
52    return comment?.shortText ? (
53      <ReactMarkdown renderers={mdInlineRenderers}>{comment.shortText}</ReactMarkdown>
54    ) : (
55      '-'
56    );
57  }
58};
59
60const renderInterfacePropertyRow = ({
61  name,
62  flags,
63  type,
64  comment,
65  signatures,
66}: InterfaceValueData): JSX.Element => (
67  <tr key={name}>
68    <td>
69      <B>
70        {name}
71        {signatures && signatures.length ? '()' : ''}
72      </B>
73      {flags?.isOptional ? (
74        <>
75          <br />
76          <span css={STYLES_OPTIONAL}>(optional)</span>
77        </>
78      ) : null}
79    </td>
80    <td>{renderInterfaceType(type, signatures)}</td>
81    <td>{renderInterfaceComment(comment, signatures)}</td>
82  </tr>
83);
84
85const renderInterface = ({
86  name,
87  children,
88  comment,
89}: InterfaceDefinitionData): JSX.Element | null =>
90  children ? (
91    <div key={`interface-definition-${name}`}>
92      <H3Code>
93        <InlineCode>{name}</InlineCode>
94      </H3Code>
95      <CommentTextBlock comment={comment} />
96      <table>
97        <thead>
98          <tr>
99            <th>Name</th>
100            <th>Type</th>
101            <th>Description</th>
102          </tr>
103        </thead>
104        <tbody>{children.map(renderInterfacePropertyRow)}</tbody>
105      </table>
106    </div>
107  ) : null;
108
109const APISectionInterfaces: React.FC<APISectionInterfacesProps> = ({ data }) =>
110  data?.length ? (
111    <>
112      <H2 key="interfaces-header">Interfaces</H2>
113      {data.map(renderInterface)}
114    </>
115  ) : null;
116
117export default APISectionInterfaces;
118