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 === TypeDocKind.Method && 45 (allowOverwrites || !child.overwrites) && 46 !child.name.startsWith('_') && 47 !child?.implementationOf; 48 49const remapClass = (clx: ClassDefinitionData) => { 50 clx.isSensor = clx.name.endsWith('Sensor'); 51 clx.name = classNamesMap[clx.name] ?? clx.name; 52 53 if (clx.isSensor && clx.extendedTypes) { 54 clx.extendedTypes = clx.extendedTypes.map(type => ({ 55 ...type, 56 name: type.name === 'default' ? 'DeviceSensor' : type.name, 57 })); 58 } 59 60 return clx; 61}; 62 63const renderClass = (clx: ClassDefinitionData, exposeInSidebar: boolean): JSX.Element => { 64 const { name, comment, type, extendedTypes, children, implementedTypes, isSensor } = clx; 65 const Header = exposeInSidebar ? H2Nested : H4; 66 67 const properties = children?.filter(isProp); 68 const methods = children 69 ?.filter(child => isMethod(child, isSensor)) 70 .sort((a: PropData, b: PropData) => a.name.localeCompare(b.name)); 71 const returnComment = getTagData('returns', comment); 72 73 return ( 74 <div key={`class-definition-${name}`} css={STYLES_APIBOX}> 75 <APISectionDeprecationNote comment={comment} /> 76 <H3Code tags={getTagNamesList(comment)}> 77 <InlineCode>{name}</InlineCode> 78 </H3Code> 79 {(extendedTypes?.length || implementedTypes?.length) && ( 80 <P> 81 <B>Type: </B> 82 {type ? <InlineCode>{resolveTypeName(type)}</InlineCode> : 'Class'} 83 {extendedTypes?.length && ( 84 <> 85 <span> extends </span> 86 {extendedTypes.map(extendedType => ( 87 <InlineCode key={`extends-${extendedType.name}`}> 88 {resolveTypeName(extendedType)} 89 </InlineCode> 90 ))} 91 </> 92 )} 93 {implementedTypes?.length && ( 94 <> 95 <span> implements </span> 96 {implementedTypes.map(implementedType => ( 97 <InlineCode key={`implements-${implementedType.name}`}> 98 {resolveTypeName(implementedType)} 99 </InlineCode> 100 ))} 101 </> 102 )} 103 </P> 104 )} 105 <CommentTextBlock comment={comment} /> 106 {returnComment && ( 107 <> 108 <div css={STYLES_NESTED_SECTION_HEADER}> 109 <H4>Returns</H4> 110 </div> 111 <ReactMarkdown components={mdComponents}>{returnComment.text}</ReactMarkdown> 112 </> 113 )} 114 {properties?.length ? ( 115 <> 116 <div css={STYLES_NESTED_SECTION_HEADER}> 117 <Header>{name} Properties</Header> 118 </div> 119 <div> 120 {properties.map(property => 121 renderProp(property, property?.defaultValue, exposeInSidebar) 122 )} 123 </div> 124 </> 125 ) : null} 126 {methods?.length && ( 127 <> 128 <div css={STYLES_NESTED_SECTION_HEADER}> 129 <Header>{name} Methods</Header> 130 </div> 131 {methods.map(method => renderMethod(method, { exposeInSidebar }))} 132 </> 133 )} 134 </div> 135 ); 136}; 137 138const APISectionClasses = ({ data }: APISectionClassesProps) => { 139 if (data?.length) { 140 const exposeInSidebar = data.length < 2; 141 return ( 142 <> 143 <H2>Classes</H2> 144 {data.map(clx => renderClass(remapClass(clx), exposeInSidebar))} 145 </> 146 ); 147 } 148 return null; 149}; 150 151export default APISectionClasses; 152