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