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, allowOverwrites: boolean = false) => 37 child.kind === TypeDocKind.Method && 38 (allowOverwrites || !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 Header = exposeInSidebar ? H2Nested : H4; 45 46 const isSensorClass = name.endsWith('Sensor'); 47 const className = isSensorClass ? name.replace('Sensor', '') : name; 48 49 const properties = children?.filter(isProp); 50 const methods = children 51 ?.filter(child => isMethod(child, isSensorClass)) 52 .sort((a: PropData, b: PropData) => a.name.localeCompare(b.name)); 53 const returnComment = getTagData('returns', comment); 54 55 return ( 56 <div key={`class-definition-${className}`} css={STYLES_APIBOX}> 57 <APISectionDeprecationNote comment={comment} /> 58 <H3Code tags={getTagNamesList(comment)}> 59 <InlineCode>{className}</InlineCode> 60 </H3Code> 61 {(extendedTypes?.length || implementedTypes?.length) && ( 62 <P> 63 <B>Type: </B> 64 {type ? <InlineCode>{resolveTypeName(type)}</InlineCode> : 'Class'} 65 {extendedTypes?.length && ( 66 <> 67 <span> extends </span> 68 {extendedTypes.map(extendedType => { 69 if (isSensorClass && extendedType.name === 'default') { 70 extendedType.name = 'DeviceSensor'; 71 } 72 return ( 73 <InlineCode key={`extends-${extendedType.name}`}> 74 {resolveTypeName(extendedType)} 75 </InlineCode> 76 ); 77 })} 78 </> 79 )} 80 {implementedTypes?.length && ( 81 <> 82 <span> implements </span> 83 {implementedTypes.map(implementedType => ( 84 <InlineCode key={`implements-${implementedType.name}`}> 85 {resolveTypeName(implementedType)} 86 </InlineCode> 87 ))} 88 </> 89 )} 90 </P> 91 )} 92 <CommentTextBlock comment={comment} /> 93 {returnComment && ( 94 <> 95 <div css={STYLES_NESTED_SECTION_HEADER}> 96 <H4>Returns</H4> 97 </div> 98 <ReactMarkdown components={mdComponents}>{returnComment.text}</ReactMarkdown> 99 </> 100 )} 101 {properties?.length ? ( 102 <> 103 <div css={STYLES_NESTED_SECTION_HEADER}> 104 <Header>{className} Properties</Header> 105 </div> 106 <div> 107 {properties.map(property => 108 renderProp(property, property?.defaultValue, exposeInSidebar) 109 )} 110 </div> 111 </> 112 ) : null} 113 {methods?.length && ( 114 <> 115 <div css={STYLES_NESTED_SECTION_HEADER}> 116 <Header>{className} Methods</Header> 117 </div> 118 {methods.map(method => renderMethod(method, { exposeInSidebar }))} 119 </> 120 )} 121 </div> 122 ); 123}; 124 125const APISectionClasses = ({ data }: APISectionClassesProps) => { 126 if (data?.length) { 127 const exposeInSidebar = data.length < 2; 128 return ( 129 <> 130 <H2>Classes</H2> 131 {data.map(cls => renderClass(cls, exposeInSidebar))} 132 </> 133 ); 134 } 135 return null; 136}; 137 138export default APISectionClasses; 139