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