1import { renderMethod } from './APISectionMethods';
2
3import { APIDataType } from '~/components/plugins/api/APIDataType';
4import {
5  CommentData,
6  InterfaceDefinitionData,
7  MethodSignatureData,
8  PropData,
9} from '~/components/plugins/api/APIDataTypes';
10import { APISectionDeprecationNote } from '~/components/plugins/api/APISectionDeprecationNote';
11import { APISectionPlatformTags } from '~/components/plugins/api/APISectionPlatformTags';
12import {
13  CommentTextBlock,
14  getTagData,
15  parseCommentContent,
16  renderFlags,
17  renderParamRow,
18  ParamsTableHeadRow,
19  resolveTypeName,
20  renderDefaultValue,
21  STYLES_APIBOX,
22  STYLES_NESTED_SECTION_HEADER,
23  getTagNamesList,
24  STYLES_APIBOX_NESTED,
25  STYLES_ELEMENT_SPACING,
26  H3Code,
27  getCommentContent,
28} from '~/components/plugins/api/APISectionUtils';
29import { Cell, Row, Table } from '~/ui/components/Table';
30import { H2, H4, BOLD, P, CODE } from '~/ui/components/Text';
31
32export type APISectionInterfacesProps = {
33  data: InterfaceDefinitionData[];
34};
35
36const renderInterfaceComment = (
37  comment?: CommentData,
38  signatures?: MethodSignatureData[],
39  defaultValue?: string
40) => {
41  if (signatures && signatures.length) {
42    const { type, parameters, comment: signatureComment } = signatures[0];
43    const defaultTag = getTagData('default', signatureComment);
44    const initValue =
45      defaultValue || (defaultTag ? getCommentContent(defaultTag.content) : undefined);
46    return (
47      <>
48        {parameters?.length ? parameters.map(param => renderParamRow(param)) : null}
49        <BOLD>Returns: </BOLD>
50        <CODE>{resolveTypeName(type)}</CODE>
51        {signatureComment && (
52          <>
53            <br />
54            <APISectionDeprecationNote comment={comment} />
55            <CommentTextBlock
56              inlineHeaders
57              comment={signatureComment}
58              afterContent={renderDefaultValue(initValue)}
59            />
60          </>
61        )}
62      </>
63    );
64  } else {
65    const defaultTag = getTagData('default', comment);
66    const initValue =
67      defaultValue || (defaultTag ? getCommentContent(defaultTag.content) : undefined);
68    return (
69      <>
70        <APISectionDeprecationNote comment={comment} />
71        <CommentTextBlock
72          comment={comment}
73          afterContent={renderDefaultValue(initValue)}
74          emptyCommentFallback="-"
75        />
76      </>
77    );
78  }
79};
80
81const renderInterfacePropertyRow = ({
82  name,
83  flags,
84  type,
85  comment,
86  signatures,
87  defaultValue,
88}: PropData): JSX.Element => {
89  const defaultTag = getTagData('default', comment);
90  const initValue = parseCommentContent(
91    defaultValue || (defaultTag ? getCommentContent(defaultTag.content) : '')
92  );
93  return (
94    <Row key={name}>
95      <Cell fitContent>
96        <BOLD>{name}</BOLD>
97        {renderFlags(flags, initValue)}
98      </Cell>
99      <Cell fitContent>
100        <APIDataType typeDefinition={type} />
101      </Cell>
102      <Cell fitContent>{renderInterfaceComment(comment, signatures, initValue)}</Cell>
103    </Row>
104  );
105};
106
107const renderInterface = ({
108  name,
109  children,
110  comment,
111  extendedTypes,
112}: InterfaceDefinitionData): JSX.Element | null => {
113  const interfaceChildren = children?.filter(child => !child?.inheritedFrom) || [];
114
115  if (!interfaceChildren.length) return null;
116
117  const interfaceMethods = interfaceChildren.filter(child => child.signatures);
118  const interfaceFields = interfaceChildren.filter(child => !child.signatures);
119
120  return (
121    <div key={`interface-definition-${name}`} css={[STYLES_APIBOX, STYLES_APIBOX_NESTED]}>
122      <APISectionDeprecationNote comment={comment} />
123      <APISectionPlatformTags comment={comment} prefix="Only for:" />
124      <H3Code tags={getTagNamesList(comment)}>
125        <CODE>{name}</CODE>
126      </H3Code>
127      {extendedTypes?.length ? (
128        <P css={STYLES_ELEMENT_SPACING}>
129          <BOLD>Extends: </BOLD>
130          {extendedTypes.map(extendedType => (
131            <CODE key={`extend-${extendedType.name}`}>{resolveTypeName(extendedType)}</CODE>
132          ))}
133        </P>
134      ) : null}
135      <CommentTextBlock comment={comment} includePlatforms={false} />
136      {interfaceMethods.length ? (
137        <>
138          <div css={STYLES_NESTED_SECTION_HEADER}>
139            <H4>{name} Methods</H4>
140          </div>
141          {interfaceMethods.map(method => renderMethod(method, { exposeInSidebar: false }))}
142        </>
143      ) : undefined}
144      {interfaceFields.length ? (
145        <>
146          <div css={STYLES_NESTED_SECTION_HEADER}>
147            <H4>{name} Properties</H4>
148          </div>
149          <Table>
150            <ParamsTableHeadRow />
151            <tbody>{interfaceFields.map(renderInterfacePropertyRow)}</tbody>
152          </Table>
153          <br />
154        </>
155      ) : undefined}
156    </div>
157  );
158};
159
160const APISectionInterfaces = ({ data }: APISectionInterfacesProps) =>
161  data?.length ? (
162    <>
163      <H2 key="interfaces-header">Interfaces</H2>
164      {data.map(renderInterface)}
165    </>
166  ) : null;
167
168export default APISectionInterfaces;
169