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