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, H2Nested, 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 getTagNamesList, 19 mdComponents, 20 resolveTypeName, 21 STYLES_APIBOX, 22 STYLES_NESTED_SECTION_HEADER, 23 TypeDocKind, 24} from '~/components/plugins/api/APISectionUtils'; 25 26export type APISectionClassesProps = { 27 data: GeneratedData[]; 28}; 29 30const isProp = (child: PropData) => 31 child.kind === TypeDocKind.Property && 32 !child.overwrites && 33 !child.name.startsWith('_') && 34 !child.implementationOf; 35 36const isMethod = (child: PropData) => 37 child.kind === TypeDocKind.Method && 38 !child.overwrites && 39 !child.name.startsWith('_') && 40 !child?.implementationOf; 41 42const renderClass = (clx: ClassDefinitionData, exposeInSidebar: boolean): JSX.Element => { 43 const { name, comment, type, extendedTypes, children, implementedTypes } = clx; 44 const properties = children?.filter(isProp); 45 const methods = children 46 ?.filter(isMethod) 47 .sort((a: PropData, b: PropData) => a.name.localeCompare(b.name)); 48 const returnComment = getTagData('returns', comment); 49 const Header = exposeInSidebar ? H2Nested : H4; 50 51 return ( 52 <div key={`class-definition-${name}`} css={STYLES_APIBOX}> 53 <APISectionDeprecationNote comment={comment} /> 54 <H3Code tags={getTagNamesList(comment)}> 55 <InlineCode>{name}</InlineCode> 56 </H3Code> 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 <div css={STYLES_NESTED_SECTION_HEADER}> 95 <Header>{name} Properties</Header> 96 </div> 97 <div> 98 {properties.map(property => 99 renderProp(property, property?.defaultValue, exposeInSidebar) 100 )} 101 </div> 102 </> 103 ) : null} 104 {methods?.length && ( 105 <> 106 <div css={STYLES_NESTED_SECTION_HEADER}> 107 <Header>{name} Methods</Header> 108 </div> 109 {methods.map(method => renderMethod(method, { exposeInSidebar }))} 110 </> 111 )} 112 </div> 113 ); 114}; 115 116const APISectionClasses = ({ data }: APISectionClassesProps) => { 117 if (data?.length) { 118 const exposeInSidebar = data.length < 2; 119 return ( 120 <> 121 <H2>Classes</H2> 122 {data.map(cls => renderClass(cls, exposeInSidebar))} 123 </> 124 ); 125 } 126 return null; 127}; 128 129export default APISectionClasses; 130