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} from '~/components/plugins/api/APISectionUtils'; 25import { H2, H4, BOLD, P, CODE } 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 const Header = getAPISectionHeader(exposeInSidebar); 69 70 const properties = children?.filter(isProp); 71 const methods = children 72 ?.filter(child => isMethod(child, isSensor)) 73 .sort((a: PropData, b: PropData) => a.name.localeCompare(b.name)); 74 const returnComment = getTagData('returns', comment); 75 76 return ( 77 <div key={`class-definition-${name}`} css={[STYLES_APIBOX, STYLES_APIBOX_NESTED]}> 78 <APISectionDeprecationNote comment={comment} /> 79 <APISectionPlatformTags comment={comment} prefix="Only for:" /> 80 <H3Code tags={getTagNamesList(comment)}> 81 <CODE>{name}</CODE> 82 </H3Code> 83 {(extendedTypes?.length || implementedTypes?.length) && ( 84 <P> 85 <BOLD>Type: </BOLD> 86 {type ? <CODE>{resolveTypeName(type)}</CODE> : 'Class'} 87 {extendedTypes?.length && ( 88 <> 89 <span> extends </span> 90 {extendedTypes.map(extendedType => ( 91 <CODE key={`extends-${extendedType.name}`}>{resolveTypeName(extendedType)}</CODE> 92 ))} 93 </> 94 )} 95 {implementedTypes?.length && ( 96 <> 97 <span> implements </span> 98 {implementedTypes.map(implementedType => ( 99 <CODE key={`implements-${implementedType.name}`}> 100 {resolveTypeName(implementedType)} 101 </CODE> 102 ))} 103 </> 104 )} 105 </P> 106 )} 107 <CommentTextBlock comment={comment} includePlatforms={false} /> 108 {returnComment && ( 109 <> 110 <div css={STYLES_NESTED_SECTION_HEADER}> 111 <H4>Returns</H4> 112 </div> 113 <ReactMarkdown components={mdComponents}>{returnComment.text}</ReactMarkdown> 114 </> 115 )} 116 {properties?.length ? ( 117 <> 118 <div css={STYLES_NESTED_SECTION_HEADER}> 119 <Header>{name} Properties</Header> 120 </div> 121 <div> 122 {properties.map(property => 123 renderProp(property, property?.defaultValue, exposeInSidebar) 124 )} 125 </div> 126 </> 127 ) : null} 128 {methods?.length && ( 129 <> 130 <div css={STYLES_NESTED_SECTION_HEADER}> 131 <Header>{name} Methods</Header> 132 </div> 133 {methods.map(method => renderMethod(method, { exposeInSidebar }))} 134 </> 135 )} 136 </div> 137 ); 138}; 139 140const APISectionClasses = ({ data }: APISectionClassesProps) => { 141 if (data?.length) { 142 const exposeInSidebar = data.length < 2; 143 return ( 144 <> 145 <H2>Classes</H2> 146 {data.map(clx => renderClass(remapClass(clx), exposeInSidebar))} 147 </> 148 ); 149 } 150 return null; 151}; 152 153export default APISectionClasses; 154