1import ReactMarkdown from 'react-markdown'; 2 3import { InlineCode } from '~/components/base/code'; 4import { B, P } from '~/components/base/paragraph'; 5import { H2, H2Nested, H3Code, H4 } from '~/components/plugins/Headings'; 6import { 7 ClassDefinitionData, 8 GeneratedData, 9 PropData, 10} from '~/components/plugins/api/APIDataTypes'; 11import { APISectionDeprecationNote } from '~/components/plugins/api/APISectionDeprecationNote'; 12import { renderMethod } from '~/components/plugins/api/APISectionMethods'; 13import { renderProp } from '~/components/plugins/api/APISectionProps'; 14import { 15 CommentTextBlock, 16 getTagData, 17 getTagNamesList, 18 mdComponents, 19 resolveTypeName, 20 STYLES_APIBOX, 21 STYLES_NESTED_SECTION_HEADER, 22 TypeDocKind, 23} from '~/components/plugins/api/APISectionUtils'; 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}> 76 <APISectionDeprecationNote comment={comment} /> 77 <H3Code tags={getTagNamesList(comment)}> 78 <InlineCode>{name}</InlineCode> 79 </H3Code> 80 {(extendedTypes?.length || implementedTypes?.length) && ( 81 <P> 82 <B>Type: </B> 83 {type ? <InlineCode>{resolveTypeName(type)}</InlineCode> : 'Class'} 84 {extendedTypes?.length && ( 85 <> 86 <span> extends </span> 87 {extendedTypes.map(extendedType => ( 88 <InlineCode key={`extends-${extendedType.name}`}> 89 {resolveTypeName(extendedType)} 90 </InlineCode> 91 ))} 92 </> 93 )} 94 {implementedTypes?.length && ( 95 <> 96 <span> implements </span> 97 {implementedTypes.map(implementedType => ( 98 <InlineCode key={`implements-${implementedType.name}`}> 99 {resolveTypeName(implementedType)} 100 </InlineCode> 101 ))} 102 </> 103 )} 104 </P> 105 )} 106 <CommentTextBlock comment={comment} /> 107 {returnComment && ( 108 <> 109 <div css={STYLES_NESTED_SECTION_HEADER}> 110 <H4>Returns</H4> 111 </div> 112 <ReactMarkdown components={mdComponents}>{returnComment.text}</ReactMarkdown> 113 </> 114 )} 115 {properties?.length ? ( 116 <> 117 <div css={STYLES_NESTED_SECTION_HEADER}> 118 <Header>{name} Properties</Header> 119 </div> 120 <div> 121 {properties.map(property => 122 renderProp(property, property?.defaultValue, exposeInSidebar) 123 )} 124 </div> 125 </> 126 ) : null} 127 {methods?.length && ( 128 <> 129 <div css={STYLES_NESTED_SECTION_HEADER}> 130 <Header>{name} Methods</Header> 131 </div> 132 {methods.map(method => renderMethod(method, { exposeInSidebar }))} 133 </> 134 )} 135 </div> 136 ); 137}; 138 139const APISectionClasses = ({ data }: APISectionClassesProps) => { 140 if (data?.length) { 141 const exposeInSidebar = data.length < 2; 142 return ( 143 <> 144 <H2>Classes</H2> 145 {data.map(clx => renderClass(remapClass(clx), exposeInSidebar))} 146 </> 147 ); 148 } 149 return null; 150}; 151 152export default APISectionClasses; 153