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