1import { css } from '@emotion/react';
2import React from 'react';
3
4import { InlineCode } from '~/components/base/code';
5import { UL, LI } from '~/components/base/list';
6import { B, P } from '~/components/base/paragraph';
7import { H2, H4, H3Code } from '~/components/plugins/Headings';
8import {
9  ClassDefinitionData,
10  CommentData,
11  GeneratedData,
12  MethodSignatureData,
13  PropData,
14} from '~/components/plugins/api/APIDataTypes';
15import {
16  CommentTextBlock,
17  listParams,
18  mdInlineComponents,
19  renderParam,
20  renderTypeOrSignatureType,
21  resolveTypeName,
22  STYLES_OPTIONAL,
23  TypeDocKind,
24} from '~/components/plugins/api/APISectionUtils';
25
26export type APISectionClassesProps = {
27  data: GeneratedData[];
28};
29
30const renderPropertyComment = (comment?: CommentData, signatures?: MethodSignatureData[]) => {
31  if (signatures && signatures.length) {
32    const { type, parameters, comment: signatureComment } = signatures[0];
33    return (
34      <>
35        <UL>
36          {parameters?.map(param => renderParam(param))}
37          <LI returnType>
38            <InlineCode>{resolveTypeName(type)}</InlineCode>
39          </LI>
40        </UL>
41        {signatureComment && (
42          <CommentTextBlock comment={signatureComment} components={mdInlineComponents} />
43        )}
44      </>
45    );
46  } else {
47    return comment ? <CommentTextBlock comment={comment} components={mdInlineComponents} /> : null;
48  }
49};
50
51const renderProperty = ({ name, signatures, flags, type, comment }: PropData) => (
52  <LI customCss={css({ marginBottom: 6 })} key={`class-property-${name}`}>
53    <B>
54      {name}
55      {signatures && signatures.length ? `(${listParams(signatures[0].parameters)})` : null}
56    </B>
57    {!signatures ? <>&emsp;{renderTypeOrSignatureType(type, signatures)}</> : null}
58    {flags?.isOptional ? <span css={STYLES_OPTIONAL}>&emsp;&bull;&emsp;optional</span> : null}
59    {!signatures ? <br /> : null}
60    {renderPropertyComment(comment, signatures)}
61  </LI>
62);
63
64const renderClass = ({
65  name,
66  comment,
67  type,
68  extendedTypes,
69  children,
70}: ClassDefinitionData): JSX.Element => {
71  const properties = children?.filter(
72    child => child.kind === TypeDocKind.Property && !child.overwrites
73  );
74  const methods = children?.filter(child => child.kind === TypeDocKind.Method && !child.overwrites);
75  return (
76    <div key={`class-definition-${name}`}>
77      <H3Code>
78        <InlineCode>{name}</InlineCode>
79      </H3Code>
80      {extendedTypes?.length && (
81        <P>
82          <B>Type: </B>
83          {type ? <InlineCode>{resolveTypeName(type)}</InlineCode> : 'Class'}
84          <span> extends </span>
85          <InlineCode>{resolveTypeName(extendedTypes[0])}</InlineCode>
86        </P>
87      )}
88      <CommentTextBlock comment={comment} />
89      {properties?.length ? (
90        <>
91          <H4>Properties:</H4>
92          <UL>{properties.map(child => renderProperty(child))}</UL>
93        </>
94      ) : null}
95      {methods?.length ? (
96        <>
97          <H4>Methods:</H4>
98          <UL>{methods.map(child => renderProperty(child))}</UL>
99        </>
100      ) : null}
101    </div>
102  );
103};
104
105const APISectionClasses = ({ data }: APISectionClassesProps) =>
106  data?.length ? (
107    <>
108      <H2 key="classes-header">Classes</H2>
109      {data.map(cls => renderClass(cls))}
110    </>
111  ) : null;
112
113export default APISectionClasses;
114