1e3060685SBartosz Kaszubowskiimport { ClassDefinitionData, GeneratedData } from '~/components/plugins/api/APIDataTypes'; 22c8d37c0SBartosz Kaszubowskiimport APISectionClasses from '~/components/plugins/api/APISectionClasses'; 31ef472c3SBartosz Kaszubowskiimport APISectionComponents from '~/components/plugins/api/APISectionComponents'; 4299f02f2SBartosz Kaszubowskiimport APISectionConstants from '~/components/plugins/api/APISectionConstants'; 5299f02f2SBartosz Kaszubowskiimport APISectionEnums from '~/components/plugins/api/APISectionEnums'; 6299f02f2SBartosz Kaszubowskiimport APISectionInterfaces from '~/components/plugins/api/APISectionInterfaces'; 7299f02f2SBartosz Kaszubowskiimport APISectionMethods from '~/components/plugins/api/APISectionMethods'; 86b7802baSBartosz Kaszubowskiimport APISectionNamespaces from '~/components/plugins/api/APISectionNamespaces'; 9299f02f2SBartosz Kaszubowskiimport APISectionProps from '~/components/plugins/api/APISectionProps'; 10299f02f2SBartosz Kaszubowskiimport APISectionTypes from '~/components/plugins/api/APISectionTypes'; 11*07ffa84cSBartosz Kaszubowskiimport { 12*07ffa84cSBartosz Kaszubowski getCommentContent, 13*07ffa84cSBartosz Kaszubowski getComponentName, 14*07ffa84cSBartosz Kaszubowski TypeDocKind, 15*07ffa84cSBartosz Kaszubowski} from '~/components/plugins/api/APISectionUtils'; 16e54a3f4bSCedric van Puttenimport { usePageApiVersion } from '~/providers/page-api-version'; 173f609562SBartosz Kaszubowskiimport versions from '~/public/static/constants/versions.json'; 1812abeb84SBartosz Kaszubowskiimport { P } from '~/ui/components/Text'; 19299f02f2SBartosz Kaszubowski 203f609562SBartosz Kaszubowskiconst { LATEST_VERSION } = versions; 21299f02f2SBartosz Kaszubowski 22299f02f2SBartosz Kaszubowskitype Props = { 23299f02f2SBartosz Kaszubowski packageName: string; 24299f02f2SBartosz Kaszubowski apiName?: string; 258de46705SBartosz Kaszubowski forceVersion?: string; 269f72d43bSBartosz Kaszubowski strictTypes?: boolean; 273f609562SBartosz Kaszubowski testRequire?: any; 28*07ffa84cSBartosz Kaszubowski headersMapping?: Record<string, string>; 29299f02f2SBartosz Kaszubowski}; 30299f02f2SBartosz Kaszubowski 31299f02f2SBartosz Kaszubowskiconst filterDataByKind = ( 32c8c9d6e8SBartosz Kaszubowski entries: GeneratedData[] = [], 33c8c9d6e8SBartosz Kaszubowski kind: TypeDocKind | TypeDocKind[], 34299f02f2SBartosz Kaszubowski additionalCondition: (entry: GeneratedData) => boolean = () => true 35299f02f2SBartosz Kaszubowski) => 36c8c9d6e8SBartosz Kaszubowski entries.filter( 37c8c9d6e8SBartosz Kaszubowski (entry: GeneratedData) => 38c8c9d6e8SBartosz Kaszubowski (Array.isArray(kind) ? kind.includes(entry.kind) : entry.kind === kind) && 39c8c9d6e8SBartosz Kaszubowski additionalCondition(entry) 40c8c9d6e8SBartosz Kaszubowski ); 41299f02f2SBartosz Kaszubowski 42a2ea8bc3SBartosz Kaszubowskiconst isHook = ({ name }: GeneratedData) => 43a2ea8bc3SBartosz Kaszubowski name.startsWith('use') && 44a2ea8bc3SBartosz Kaszubowski // note(simek): hardcode this exception until the method will be renamed 45a2ea8bc3SBartosz Kaszubowski name !== 'useSystemBrightnessAsync'; 46a2ea8bc3SBartosz Kaszubowski 4704eb1228SBartosz Kaszubowskiconst isListener = ({ name }: GeneratedData) => 4804eb1228SBartosz Kaszubowski name.endsWith('Listener') || name.endsWith('Listeners'); 49f128dd42SBartosz Kaszubowski 501db397d9SBartosz Kaszubowskiconst isProp = ({ name }: GeneratedData) => name.includes('Props') && name !== 'ErrorRecoveryProps'; 511db397d9SBartosz Kaszubowski 52e939dadbSBartosz Kaszubowskiconst isComponent = ({ type, extendedTypes, signatures }: GeneratedData) => { 53e939dadbSBartosz Kaszubowski if (type?.name && ['React.FC', 'ForwardRefExoticComponent'].includes(type?.name)) { 54e939dadbSBartosz Kaszubowski return true; 55e939dadbSBartosz Kaszubowski } else if (extendedTypes && extendedTypes.length) { 566d4adf53STomasz Sapeta return extendedTypes[0].name === 'Component' || extendedTypes[0].name === 'PureComponent'; 57e939dadbSBartosz Kaszubowski } else if (signatures && signatures.length) { 58e939dadbSBartosz Kaszubowski if ( 59e939dadbSBartosz Kaszubowski signatures[0].type.name === 'Element' || 605990cc31SBartosz Kaszubowski (signatures[0].type.types && signatures[0].type.types.map(t => t.name).includes('Element')) || 61144e76edSBartosz Kaszubowski (signatures[0].parameters && signatures[0].parameters[0].name === 'props') 62e939dadbSBartosz Kaszubowski ) { 63e939dadbSBartosz Kaszubowski return true; 64e939dadbSBartosz Kaszubowski } 65e939dadbSBartosz Kaszubowski } 66e939dadbSBartosz Kaszubowski return false; 67e939dadbSBartosz Kaszubowski}; 68f31f564bSBartosz Kaszubowski 69d0262524SBartosz Kaszubowskiconst isConstant = ({ name, type }: GeneratedData) => 70e3060685SBartosz Kaszubowski !['default', 'Constants', 'EventEmitter'].includes(name) && 71ce122823SBartłomiej Bukowski !(type?.name && ['React.FC', 'ForwardRefExoticComponent'].includes(type?.name)); 72f31f564bSBartosz Kaszubowski 73*07ffa84cSBartosz Kaszubowskiconst hasCategoryHeader = ({ signatures }: GeneratedData): boolean => 74*07ffa84cSBartosz Kaszubowski (signatures && 75*07ffa84cSBartosz Kaszubowski signatures[0].comment?.blockTags && 76*07ffa84cSBartosz Kaszubowski signatures[0].comment.blockTags.length > 0 && 77*07ffa84cSBartosz Kaszubowski signatures[0].comment.blockTags.filter(tag => tag?.tag === '@header').length > 0) ?? 78*07ffa84cSBartosz Kaszubowski false; 79*07ffa84cSBartosz Kaszubowski 80*07ffa84cSBartosz Kaszubowskiconst groupByHeader = (entries: GeneratedData[]) => { 81*07ffa84cSBartosz Kaszubowski return entries.reduce((group: Record<string, GeneratedData[]>, entry) => { 82*07ffa84cSBartosz Kaszubowski const signature = entry.signatures[0]; 83*07ffa84cSBartosz Kaszubowski const header = getCommentContent( 84*07ffa84cSBartosz Kaszubowski signature.comment?.blockTags?.filter(tag => tag.tag === '@header')[0].content ?? [] 85*07ffa84cSBartosz Kaszubowski ); 86*07ffa84cSBartosz Kaszubowski if (header) { 87*07ffa84cSBartosz Kaszubowski group[header] = group[header] ?? []; 88*07ffa84cSBartosz Kaszubowski group[header].push(entry); 89*07ffa84cSBartosz Kaszubowski } 90*07ffa84cSBartosz Kaszubowski return group; 91*07ffa84cSBartosz Kaszubowski }, {}); 92*07ffa84cSBartosz Kaszubowski}; 93*07ffa84cSBartosz Kaszubowski 94299f02f2SBartosz Kaszubowskiconst renderAPI = ( 95299f02f2SBartosz Kaszubowski packageName: string, 96299f02f2SBartosz Kaszubowski version: string = 'unversioned', 978de46705SBartosz Kaszubowski apiName?: string, 989f72d43bSBartosz Kaszubowski strictTypes: boolean = false, 99*07ffa84cSBartosz Kaszubowski testRequire: any = undefined, 100*07ffa84cSBartosz Kaszubowski headersMapping: Record<string, string> = {} 101299f02f2SBartosz Kaszubowski): JSX.Element => { 102299f02f2SBartosz Kaszubowski try { 1033f609562SBartosz Kaszubowski const { children: data } = testRequire 1043f609562SBartosz Kaszubowski ? testRequire(`~/public/static/data/${version}/${packageName}.json`) 1058de46705SBartosz Kaszubowski : require(`~/public/static/data/${version}/${packageName}.json`); 106299f02f2SBartosz Kaszubowski 1071b3dce65SBartosz Kaszubowski const methods = filterDataByKind( 1081b3dce65SBartosz Kaszubowski data, 1091b3dce65SBartosz Kaszubowski TypeDocKind.Function, 110*07ffa84cSBartosz Kaszubowski entry => 111*07ffa84cSBartosz Kaszubowski !isListener(entry) && !isHook(entry) && !isComponent(entry) && !hasCategoryHeader(entry) 1121b3dce65SBartosz Kaszubowski ); 113*07ffa84cSBartosz Kaszubowski const eventSubscriptions = filterDataByKind( 114*07ffa84cSBartosz Kaszubowski data, 115*07ffa84cSBartosz Kaszubowski TypeDocKind.Function, 116*07ffa84cSBartosz Kaszubowski entry => isListener(entry) && !hasCategoryHeader(entry) 117*07ffa84cSBartosz Kaszubowski ); 118*07ffa84cSBartosz Kaszubowski 119*07ffa84cSBartosz Kaszubowski const categorizedMethods = groupByHeader( 120*07ffa84cSBartosz Kaszubowski filterDataByKind( 121*07ffa84cSBartosz Kaszubowski data, 122*07ffa84cSBartosz Kaszubowski TypeDocKind.Function, 123*07ffa84cSBartosz Kaszubowski entry => !isComponent(entry) && hasCategoryHeader(entry) 124*07ffa84cSBartosz Kaszubowski ) 125*07ffa84cSBartosz Kaszubowski ); 126*07ffa84cSBartosz Kaszubowski const hasCategorizedMethods = Object.keys(categorizedMethods).length > 0; 127*07ffa84cSBartosz Kaszubowski const hasHeadersMapping = Object.keys(headersMapping).length; 128f128dd42SBartosz Kaszubowski 129299f02f2SBartosz Kaszubowski const types = filterDataByKind( 130299f02f2SBartosz Kaszubowski data, 131299f02f2SBartosz Kaszubowski TypeDocKind.TypeAlias, 1328e38d640SBartosz Kaszubowski entry => 1331db397d9SBartosz Kaszubowski !isProp(entry) && 1348e38d640SBartosz Kaszubowski !!( 1358e38d640SBartosz Kaszubowski entry.type.declaration || 1368e38d640SBartosz Kaszubowski entry.type.types || 1378e38d640SBartosz Kaszubowski entry.type.type || 1388e38d640SBartosz Kaszubowski entry.type.typeArguments 1399f72d43bSBartosz Kaszubowski ) && 1409f72d43bSBartosz Kaszubowski (strictTypes && apiName ? entry.name.startsWith(apiName) : true) 141299f02f2SBartosz Kaszubowski ); 142a404f439SBartosz Kaszubowski 14307337117SBartosz Kaszubowski const props = filterDataByKind( 14407337117SBartosz Kaszubowski data, 145c0b543d7SBartosz Kaszubowski [TypeDocKind.TypeAlias, TypeDocKind.Interface], 146c0b543d7SBartosz Kaszubowski entry => 147c0b543d7SBartosz Kaszubowski isProp(entry) && 148c0b543d7SBartosz Kaszubowski (entry.kind === TypeDocKind.TypeAlias 149c0b543d7SBartosz Kaszubowski ? !!(entry.type.types || entry.type.declaration?.children) 150c0b543d7SBartosz Kaszubowski : true) 151299f02f2SBartosz Kaszubowski ); 152299f02f2SBartosz Kaszubowski const defaultProps = filterDataByKind( 153299f02f2SBartosz Kaszubowski data 154299f02f2SBartosz Kaszubowski .filter((entry: GeneratedData) => entry.kind === TypeDocKind.Class) 155299f02f2SBartosz Kaszubowski .map((entry: GeneratedData) => entry.children) 156299f02f2SBartosz Kaszubowski .flat(), 157299f02f2SBartosz Kaszubowski TypeDocKind.Property, 158299f02f2SBartosz Kaszubowski entry => entry.name === 'defaultProps' 159299f02f2SBartosz Kaszubowski )[0]; 1601ef472c3SBartosz Kaszubowski 1616b7802baSBartosz Kaszubowski const enums = filterDataByKind(data, TypeDocKind.Enum, entry => entry.name !== 'default'); 162c0b543d7SBartosz Kaszubowski const interfaces = filterDataByKind( 163c0b543d7SBartosz Kaszubowski data, 164c0b543d7SBartosz Kaszubowski TypeDocKind.Interface, 165c0b543d7SBartosz Kaszubowski entry => !entry.name.includes('Props') 166c0b543d7SBartosz Kaszubowski ); 167f31f564bSBartosz Kaszubowski const constants = filterDataByKind(data, TypeDocKind.Variable, entry => isConstant(entry)); 1681ef472c3SBartosz Kaszubowski 169144e76edSBartosz Kaszubowski const components = filterDataByKind( 170144e76edSBartosz Kaszubowski data, 171144e76edSBartosz Kaszubowski [TypeDocKind.Variable, TypeDocKind.Class, TypeDocKind.Function], 172144e76edSBartosz Kaszubowski entry => isComponent(entry) 1731ef472c3SBartosz Kaszubowski ); 1749f72d43bSBartosz Kaszubowski const componentsPropNames = components.map( 1759f72d43bSBartosz Kaszubowski ({ name, children }) => `${getComponentName(name, children)}Props` 1769f72d43bSBartosz Kaszubowski ); 177c0b543d7SBartosz Kaszubowski const componentsProps = filterDataByKind( 178c0b543d7SBartosz Kaszubowski props, 179c0b543d7SBartosz Kaszubowski [TypeDocKind.TypeAlias, TypeDocKind.Interface], 180c0b543d7SBartosz Kaszubowski entry => componentsPropNames.includes(entry.name) 1811a91cb86SBartosz Kaszubowski ); 182299f02f2SBartosz Kaszubowski 1836b7802baSBartosz Kaszubowski const namespaces = filterDataByKind(data, TypeDocKind.Namespace); 1846b7802baSBartosz Kaszubowski 18535e5274fSBartosz Kaszubowski const classes = filterDataByKind( 18635e5274fSBartosz Kaszubowski data, 18735e5274fSBartosz Kaszubowski TypeDocKind.Class, 18835e5274fSBartosz Kaszubowski entry => !isComponent(entry) && entry.name !== 'default' 18935e5274fSBartosz Kaszubowski ); 1902c8d37c0SBartosz Kaszubowski 191e3060685SBartosz Kaszubowski const componentsChildren = components 192e3060685SBartosz Kaszubowski .map((cls: ClassDefinitionData) => 193e3060685SBartosz Kaszubowski cls.children?.filter( 194e3060685SBartosz Kaszubowski child => 195dd9570b9SBartosz Kaszubowski (child?.kind === TypeDocKind.Method || child?.kind === TypeDocKind.Property) && 196dd9570b9SBartosz Kaszubowski !child.inheritedFrom && 197e3060685SBartosz Kaszubowski child.name !== 'render' && 198e3060685SBartosz Kaszubowski // note(simek): hide unannotated "private" methods 199e3060685SBartosz Kaszubowski !child.name.startsWith('_') 200e3060685SBartosz Kaszubowski ) 201e3060685SBartosz Kaszubowski ) 202e3060685SBartosz Kaszubowski .flat(); 203e3060685SBartosz Kaszubowski 204e3060685SBartosz Kaszubowski const methodsNames = methods.map(method => method.name); 205e3060685SBartosz Kaszubowski const staticMethods = componentsChildren.filter( 206dd9570b9SBartosz Kaszubowski // note(simek): hide duplicate exports from class components 207dd9570b9SBartosz Kaszubowski method => 208dd9570b9SBartosz Kaszubowski method?.kind === TypeDocKind.Method && 209dd9570b9SBartosz Kaszubowski method?.flags?.isStatic === true && 210dd9570b9SBartosz Kaszubowski !methodsNames.includes(method.name) && 211dd9570b9SBartosz Kaszubowski !isHook(method as GeneratedData) 212e3060685SBartosz Kaszubowski ); 213e3060685SBartosz Kaszubowski const componentMethods = componentsChildren 214dd9570b9SBartosz Kaszubowski .filter( 215dd9570b9SBartosz Kaszubowski method => 216dd9570b9SBartosz Kaszubowski method?.kind === TypeDocKind.Method && 217dd9570b9SBartosz Kaszubowski method?.flags?.isStatic !== true && 218dd9570b9SBartosz Kaszubowski !method?.overwrites 219dd9570b9SBartosz Kaszubowski ) 220e3060685SBartosz Kaszubowski .filter(Boolean); 221e3060685SBartosz Kaszubowski 222dd9570b9SBartosz Kaszubowski const hooks = filterDataByKind( 223dd9570b9SBartosz Kaszubowski [...data, ...componentsChildren].filter(Boolean), 224dd9570b9SBartosz Kaszubowski [TypeDocKind.Function, TypeDocKind.Property], 225*07ffa84cSBartosz Kaszubowski entry => isHook(entry) && !hasCategoryHeader(entry) 226dd9570b9SBartosz Kaszubowski ); 227dd9570b9SBartosz Kaszubowski 228299f02f2SBartosz Kaszubowski return ( 229299f02f2SBartosz Kaszubowski <> 230*07ffa84cSBartosz Kaszubowski {hasCategorizedMethods && 231*07ffa84cSBartosz Kaszubowski (hasHeadersMapping 232*07ffa84cSBartosz Kaszubowski ? Object.entries(headersMapping).map(([key, header], index) => ( 233*07ffa84cSBartosz Kaszubowski <APISectionMethods 234*07ffa84cSBartosz Kaszubowski data={categorizedMethods[key]} 235*07ffa84cSBartosz Kaszubowski header={header} 236*07ffa84cSBartosz Kaszubowski key={`${header}-${index}`} 237*07ffa84cSBartosz Kaszubowski /> 238*07ffa84cSBartosz Kaszubowski )) 239*07ffa84cSBartosz Kaszubowski : Object.entries(categorizedMethods).map(([key, data], index) => ( 240*07ffa84cSBartosz Kaszubowski <APISectionMethods data={data} header={key} key={`${key}-${index}`} /> 241*07ffa84cSBartosz Kaszubowski )))} 2421ef472c3SBartosz Kaszubowski <APISectionComponents data={components} componentsProps={componentsProps} /> 243e3060685SBartosz Kaszubowski <APISectionMethods data={staticMethods} header="Static Methods" /> 244e3060685SBartosz Kaszubowski <APISectionMethods data={componentMethods} header="Component Methods" /> 245299f02f2SBartosz Kaszubowski <APISectionConstants data={constants} apiName={apiName} /> 246f128dd42SBartosz Kaszubowski <APISectionMethods data={hooks} header="Hooks" /> 247d8d79196SBartosz Kaszubowski <APISectionClasses data={classes} /> 248144e76edSBartosz Kaszubowski {props && !componentsProps.length ? ( 249144e76edSBartosz Kaszubowski <APISectionProps data={props} defaultProps={defaultProps} /> 250144e76edSBartosz Kaszubowski ) : null} 251299f02f2SBartosz Kaszubowski <APISectionMethods data={methods} apiName={apiName} /> 2521b3dce65SBartosz Kaszubowski <APISectionMethods 2531b3dce65SBartosz Kaszubowski data={eventSubscriptions} 2541b3dce65SBartosz Kaszubowski apiName={apiName} 2551b3dce65SBartosz Kaszubowski header="Event Subscriptions" 2561b3dce65SBartosz Kaszubowski /> 2576b7802baSBartosz Kaszubowski <APISectionNamespaces data={namespaces} /> 258299f02f2SBartosz Kaszubowski <APISectionInterfaces data={interfaces} /> 2594c73bbf6SBartosz Kaszubowski <APISectionTypes data={types} /> 260299f02f2SBartosz Kaszubowski <APISectionEnums data={enums} /> 261299f02f2SBartosz Kaszubowski </> 262299f02f2SBartosz Kaszubowski ); 2637274e17dSBartosz Kaszubowski } catch { 264299f02f2SBartosz Kaszubowski return <P>No API data file found, sorry!</P>; 265299f02f2SBartosz Kaszubowski } 266299f02f2SBartosz Kaszubowski}; 267299f02f2SBartosz Kaszubowski 2683f609562SBartosz Kaszubowskiconst APISection = ({ 2693f609562SBartosz Kaszubowski packageName, 2703f609562SBartosz Kaszubowski apiName, 2713f609562SBartosz Kaszubowski forceVersion, 2723f609562SBartosz Kaszubowski strictTypes = false, 2733f609562SBartosz Kaszubowski testRequire = undefined, 274*07ffa84cSBartosz Kaszubowski headersMapping = {}, 2753f609562SBartosz Kaszubowski}: Props) => { 276e54a3f4bSCedric van Putten const { version } = usePageApiVersion(); 277299f02f2SBartosz Kaszubowski const resolvedVersion = 2788de46705SBartosz Kaszubowski forceVersion || 2798de46705SBartosz Kaszubowski (version === 'unversioned' ? version : version === 'latest' ? LATEST_VERSION : version); 280*07ffa84cSBartosz Kaszubowski return renderAPI(packageName, resolvedVersion, apiName, strictTypes, testRequire, headersMapping); 281299f02f2SBartosz Kaszubowski}; 282299f02f2SBartosz Kaszubowski 283299f02f2SBartosz Kaszubowskiexport default APISection; 284