1import ReactMarkdown from 'react-markdown'; 2 3import { H2, H2Nested, H3Code, H4 } from '~/components/plugins/Headings'; 4import { 5 ClassDefinitionData, 6 GeneratedData, 7 PropData, 8} from '~/components/plugins/api/APIDataTypes'; 9import { APISectionDeprecationNote } from '~/components/plugins/api/APISectionDeprecationNote'; 10import { renderMethod } from '~/components/plugins/api/APISectionMethods'; 11import { renderProp } from '~/components/plugins/api/APISectionProps'; 12import { 13 CommentTextBlock, 14 getTagData, 15 getTagNamesList, 16 mdComponents, 17 resolveTypeName, 18 STYLES_APIBOX, 19 STYLES_APIBOX_NESTED, 20 STYLES_NESTED_SECTION_HEADER, 21 TypeDocKind, 22} from '~/components/plugins/api/APISectionUtils'; 23import { BOLD, P, CODE } from '~/ui/components/Text'; 24 25export type APISectionClassesProps = { 26 data: GeneratedData[]; 27}; 28 29const classNamesMap: Record<string, string> = { 30 AccelerometerSensor: 'Accelerometer', 31 BarometerSensor: 'Barometer', 32 DeviceMotionSensor: 'DeviceMotion', 33 GyroscopeSensor: 'Gyroscope', 34 MagnetometerSensor: 'Magnetometer', 35} as const; 36 37const isProp = (child: PropData) => 38 child.kind === TypeDocKind.Property && 39 !child.overwrites && 40 !child.name.startsWith('_') && 41 !child.implementationOf; 42 43const isMethod = (child: PropData, allowOverwrites: boolean = false) => 44 child.kind && 45 [TypeDocKind.Method, TypeDocKind.Function, TypeDocKind.Accessor].includes(child.kind) && 46 (allowOverwrites || !child.overwrites) && 47 !child.name.startsWith('_') && 48 !child?.implementationOf; 49 50const remapClass = (clx: ClassDefinitionData) => { 51 clx.isSensor = clx.name.endsWith('Sensor'); 52 clx.name = classNamesMap[clx.name] ?? clx.name; 53 54 if (clx.isSensor && clx.extendedTypes) { 55 clx.extendedTypes = clx.extendedTypes.map(type => ({ 56 ...type, 57 name: type.name === 'default' ? 'DeviceSensor' : type.name, 58 })); 59 } 60 61 return clx; 62}; 63 64const renderClass = (clx: ClassDefinitionData, exposeInSidebar: boolean): JSX.Element => { 65 const { name, comment, type, extendedTypes, children, implementedTypes, isSensor } = clx; 66 const Header = exposeInSidebar ? H2Nested : H4; 67 68 const properties = children?.filter(isProp); 69 const methods = children 70 ?.filter(child => isMethod(child, isSensor)) 71 .sort((a: PropData, b: PropData) => a.name.localeCompare(b.name)); 72 const returnComment = getTagData('returns', comment); 73 74 return ( 75 <div key={`class-definition-${name}`} css={[STYLES_APIBOX, STYLES_APIBOX_NESTED]}> 76 <APISectionDeprecationNote comment={comment} /> 77 <H3Code tags={getTagNamesList(comment)}> 78 <CODE>{name}</CODE> 79 </H3Code> 80 {(extendedTypes?.length || implementedTypes?.length) && ( 81 <P> 82 <BOLD>Type: </BOLD> 83 {type ? <CODE>{resolveTypeName(type)}</CODE> : 'Class'} 84 {extendedTypes?.length && ( 85 <> 86 <span> extends </span> 87 {extendedTypes.map(extendedType => ( 88 <CODE key={`extends-${extendedType.name}`}>{resolveTypeName(extendedType)}</CODE> 89 ))} 90 </> 91 )} 92 {implementedTypes?.length && ( 93 <> 94 <span> implements </span> 95 {implementedTypes.map(implementedType => ( 96 <CODE key={`implements-${implementedType.name}`}> 97 {resolveTypeName(implementedType)} 98 </CODE> 99 ))} 100 </> 101 )} 102 </P> 103 )} 104 <CommentTextBlock comment={comment} /> 105 {returnComment && ( 106 <> 107 <div css={STYLES_NESTED_SECTION_HEADER}> 108 <H4>Returns</H4> 109 </div> 110 <ReactMarkdown components={mdComponents}>{returnComment.text}</ReactMarkdown> 111 </> 112 )} 113 {properties?.length ? ( 114 <> 115 <div css={STYLES_NESTED_SECTION_HEADER}> 116 <Header>{name} Properties</Header> 117 </div> 118 <div> 119 {properties.map(property => 120 renderProp(property, property?.defaultValue, exposeInSidebar) 121 )} 122 </div> 123 </> 124 ) : null} 125 {methods?.length && ( 126 <> 127 <div css={STYLES_NESTED_SECTION_HEADER}> 128 <Header>{name} Methods</Header> 129 </div> 130 {methods.map(method => renderMethod(method, { exposeInSidebar }))} 131 </> 132 )} 133 </div> 134 ); 135}; 136 137const APISectionClasses = ({ data }: APISectionClassesProps) => { 138 if (data?.length) { 139 const exposeInSidebar = data.length < 2; 140 return ( 141 <> 142 <H2>Classes</H2> 143 {data.map(clx => renderClass(remapClass(clx), exposeInSidebar))} 144 </> 145 ); 146 } 147 return null; 148}; 149 150export default APISectionClasses; 151