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