1import React from 'react';
2import ReactMarkdown from 'react-markdown';
3
4import { InlineCode } from '~/components/base/code';
5import { UL } from '~/components/base/list';
6import { B, P } from '~/components/base/paragraph';
7import { H2, H3Code, H4 } from '~/components/plugins/Headings';
8import {
9  ClassDefinitionData,
10  GeneratedData,
11  PropData,
12} from '~/components/plugins/api/APIDataTypes';
13import { renderMethod } from '~/components/plugins/api/APISectionMethods';
14import { renderProp } from '~/components/plugins/api/APISectionProps';
15import {
16  CommentTextBlock,
17  getTagData,
18  mdComponents,
19  resolveTypeName,
20  TypeDocKind,
21} from '~/components/plugins/api/APISectionUtils';
22
23export type APISectionClassesProps = {
24  data: GeneratedData[];
25};
26
27const isProp = (child: PropData) =>
28  child.kind === TypeDocKind.Property &&
29  !child.overwrites &&
30  !child.name.startsWith('_') &&
31  !child.implementationOf;
32
33const isMethod = (child: PropData) =>
34  child.kind === TypeDocKind.Method &&
35  !child.overwrites &&
36  !child.name.startsWith('_') &&
37  !child?.implementationOf;
38
39const renderClass = (clx: ClassDefinitionData, hasMultipleClasses: boolean): JSX.Element => {
40  const { name, comment, type, extendedTypes, children, implementedTypes } = clx;
41  const properties = children?.filter(isProp);
42  const methods = children
43    ?.filter(isMethod)
44    .sort((a: PropData, b: PropData) => a.name.localeCompare(b.name));
45  const returnComment = getTagData('returns', comment);
46
47  return (
48    <div key={`class-definition-${name}`}>
49      {hasMultipleClasses ? (
50        <H3Code>
51          <InlineCode>{name}</InlineCode>
52        </H3Code>
53      ) : (
54        <H2>{name}</H2>
55      )}
56      {(extendedTypes?.length || implementedTypes?.length) && (
57        <P>
58          <B>Type: </B>
59          {type ? <InlineCode>{resolveTypeName(type)}</InlineCode> : 'Class'}
60          {extendedTypes?.length && (
61            <>
62              <span> extends </span>
63              {extendedTypes.map(extendedType => (
64                <InlineCode key={`extends-${extendedType.name}`}>
65                  {resolveTypeName(extendedType)}
66                </InlineCode>
67              ))}
68            </>
69          )}
70          {implementedTypes?.length && (
71            <>
72              <span> implements </span>
73              {implementedTypes.map(implementedType => (
74                <InlineCode key={`implements-${implementedType.name}`}>
75                  {resolveTypeName(implementedType)}
76                </InlineCode>
77              ))}
78            </>
79          )}
80        </P>
81      )}
82      <CommentTextBlock comment={comment} />
83      {returnComment && (
84        <>
85          <H4>Returns</H4>
86          <ReactMarkdown components={mdComponents}>{returnComment.text}</ReactMarkdown>
87        </>
88      )}
89      {properties?.length ? (
90        <>
91          {hasMultipleClasses ? (
92            <>
93              <H4>{name} Properties</H4>
94              <br />
95            </>
96          ) : (
97            <H2>{name} Properties</H2>
98          )}
99          <UL>
100            {properties.map(property =>
101              renderProp(property, property?.defaultValue, !hasMultipleClasses)
102            )}
103          </UL>
104        </>
105      ) : null}
106      {methods?.length ? (
107        <>
108          {hasMultipleClasses ? <H4>{name} Methods</H4> : <H2>{name} Methods</H2>}
109          <div style={{ paddingLeft: 8 }}>
110            {methods.map((method, index) =>
111              renderMethod(method, index, methods.length, undefined, undefined, !hasMultipleClasses)
112            )}
113          </div>
114        </>
115      ) : null}
116      <hr />
117    </div>
118  );
119};
120
121const APISectionClasses = ({ data }: APISectionClassesProps) => {
122  if (data?.length) {
123    const hasMultipleClasses = data.length > 1;
124    return (
125      <>
126        {hasMultipleClasses ? <H2>Classes</H2> : null}
127        {data.map(cls => renderClass(cls, hasMultipleClasses))}
128      </>
129    );
130  }
131  return null;
132};
133
134export default APISectionClasses;
135