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 <H4>Returns</H4> 87 <ReactMarkdown components={mdComponents}>{returnComment.text}</ReactMarkdown> 88 </> 89 )} 90 {properties?.length ? ( 91 <> 92 {hasMultipleClasses ? ( 93 <div css={STYLES_NESTED_SECTION_HEADER}> 94 <H4>{name} Properties</H4> 95 </div> 96 ) : ( 97 <H2>{name} Properties</H2> 98 )} 99 <div> 100 {properties.map(property => 101 renderProp(property, property?.defaultValue, !hasMultipleClasses) 102 )} 103 </div> 104 </> 105 ) : null} 106 {methods?.length && ( 107 <> 108 {hasMultipleClasses ? ( 109 <div css={STYLES_NESTED_SECTION_HEADER}> 110 <H4>{name} Methods</H4> 111 </div> 112 ) : ( 113 <H2>{name} Methods</H2> 114 )} 115 {methods.map((method, index) => 116 renderMethod(method, index, methods.length, undefined, undefined, !hasMultipleClasses) 117 )} 118 </> 119 )} 120 </div> 121 ); 122}; 123 124const APISectionClasses = ({ data }: APISectionClassesProps) => { 125 if (data?.length) { 126 const hasMultipleClasses = data.length > 1; 127 return ( 128 <> 129 {hasMultipleClasses ? <H2>Classes</H2> : null} 130 {data.map(cls => renderClass(cls, hasMultipleClasses))} 131 </> 132 ); 133 } 134 return null; 135}; 136 137export default APISectionClasses; 138