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 { renderProp } from '~/components/plugins/api/APISectionProps'; 11import { 12 CommentTextBlock, 13 getAPISectionHeader, 14 H3Code, 15 getTagData, 16 getTagNamesList, 17 mdComponents, 18 resolveTypeName, 19 STYLES_APIBOX, 20 STYLES_APIBOX_NESTED, 21 STYLES_NESTED_SECTION_HEADER, 22 TypeDocKind, 23} from '~/components/plugins/api/APISectionUtils'; 24import { H2, H4, BOLD, P, CODE } from '~/ui/components/Text'; 25 26export type APISectionClassesProps = { 27 data: GeneratedData[]; 28}; 29 30const classNamesMap: Record<string, string> = { 31 AccelerometerSensor: 'Accelerometer', 32 BarometerSensor: 'Barometer', 33 DeviceMotionSensor: 'DeviceMotion', 34 GyroscopeSensor: 'Gyroscope', 35 MagnetometerSensor: 'Magnetometer', 36} as const; 37 38const isProp = (child: PropData) => 39 child.kind === TypeDocKind.Property && 40 !child.overwrites && 41 !child.name.startsWith('_') && 42 !child.implementationOf; 43 44const isMethod = (child: PropData, allowOverwrites: boolean = false) => 45 child.kind && 46 [TypeDocKind.Method, TypeDocKind.Function, TypeDocKind.Accessor].includes(child.kind) && 47 (allowOverwrites || !child.overwrites) && 48 !child.name.startsWith('_') && 49 !child?.implementationOf; 50 51const remapClass = (clx: ClassDefinitionData) => { 52 clx.isSensor = clx.name.endsWith('Sensor'); 53 clx.name = classNamesMap[clx.name] ?? clx.name; 54 55 if (clx.isSensor && clx.extendedTypes) { 56 clx.extendedTypes = clx.extendedTypes.map(type => ({ 57 ...type, 58 name: type.name === 'default' ? 'DeviceSensor' : type.name, 59 })); 60 } 61 62 return clx; 63}; 64 65const renderClass = (clx: ClassDefinitionData, exposeInSidebar: boolean): JSX.Element => { 66 const { name, comment, type, extendedTypes, children, implementedTypes, isSensor } = clx; 67 const Header = getAPISectionHeader(exposeInSidebar); 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 <H3Code tags={getTagNamesList(comment)}> 79 <CODE>{name}</CODE> 80 </H3Code> 81 {(extendedTypes?.length || implementedTypes?.length) && ( 82 <P> 83 <BOLD>Type: </BOLD> 84 {type ? <CODE>{resolveTypeName(type)}</CODE> : 'Class'} 85 {extendedTypes?.length && ( 86 <> 87 <span> extends </span> 88 {extendedTypes.map(extendedType => ( 89 <CODE key={`extends-${extendedType.name}`}>{resolveTypeName(extendedType)}</CODE> 90 ))} 91 </> 92 )} 93 {implementedTypes?.length && ( 94 <> 95 <span> implements </span> 96 {implementedTypes.map(implementedType => ( 97 <CODE key={`implements-${implementedType.name}`}> 98 {resolveTypeName(implementedType)} 99 </CODE> 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