1import React, { useContext } from 'react'; 2 3import DocumentationPageContext from '~/components/DocumentationPageContext'; 4import { P } from '~/components/base/paragraph'; 5import { GeneratedData } from '~/components/plugins/api/APIDataTypes'; 6import APISectionComponents from '~/components/plugins/api/APISectionComponents'; 7import APISectionConstants from '~/components/plugins/api/APISectionConstants'; 8import APISectionEnums from '~/components/plugins/api/APISectionEnums'; 9import APISectionInterfaces from '~/components/plugins/api/APISectionInterfaces'; 10import APISectionMethods from '~/components/plugins/api/APISectionMethods'; 11import APISectionProps from '~/components/plugins/api/APISectionProps'; 12import APISectionTypes from '~/components/plugins/api/APISectionTypes'; 13import { TypeDocKind } from '~/components/plugins/api/APISectionUtils'; 14 15const LATEST_VERSION = `v${require('~/package.json').version}`; 16 17type Props = { 18 packageName: string; 19 apiName?: string; 20 forceVersion?: string; 21}; 22 23const filterDataByKind = ( 24 entries: GeneratedData[] = [], 25 kind: TypeDocKind | TypeDocKind[], 26 additionalCondition: (entry: GeneratedData) => boolean = () => true 27) => 28 entries.filter( 29 (entry: GeneratedData) => 30 (Array.isArray(kind) ? kind.includes(entry.kind) : entry.kind === kind) && 31 additionalCondition(entry) 32 ); 33 34const isHook = ({ name }: GeneratedData) => 35 name.startsWith('use') && 36 // note(simek): hardcode this exception until the method will be renamed 37 name !== 'useSystemBrightnessAsync'; 38 39const isListener = ({ name }: GeneratedData) => 40 name.endsWith('Listener') || name.endsWith('Listeners'); 41 42const isProp = ({ name }: GeneratedData) => name.includes('Props') && name !== 'ErrorRecoveryProps'; 43 44const renderAPI = ( 45 packageName: string, 46 version: string = 'unversioned', 47 apiName?: string, 48 isTestMode: boolean = false 49): JSX.Element => { 50 try { 51 // note(simek): When the path prefix is interpolated Next or Webpack fails to locate the file 52 const { children: data } = isTestMode 53 ? require(`../../public/static/data/${version}/${packageName}.json`) 54 : require(`~/public/static/data/${version}/${packageName}.json`); 55 56 const methods = filterDataByKind( 57 data, 58 TypeDocKind.Function, 59 entry => !isListener(entry) && !isHook(entry) 60 ); 61 const hooks = filterDataByKind(data, TypeDocKind.Function, isHook); 62 const eventSubscriptions = filterDataByKind(data, TypeDocKind.Function, isListener); 63 64 const types = filterDataByKind( 65 data, 66 TypeDocKind.TypeAlias, 67 entry => 68 !isProp(entry) && 69 !!( 70 entry.type.declaration || 71 entry.type.types || 72 entry.type.type || 73 entry.type.typeArguments 74 ) 75 ); 76 77 const props = filterDataByKind( 78 data, 79 TypeDocKind.TypeAlias, 80 entry => isProp(entry) && !!(entry.type.types || entry.type.declaration?.children) 81 ); 82 const defaultProps = filterDataByKind( 83 data 84 .filter((entry: GeneratedData) => entry.kind === TypeDocKind.Class) 85 .map((entry: GeneratedData) => entry.children) 86 .flat(), 87 TypeDocKind.Property, 88 entry => entry.name === 'defaultProps' 89 )[0]; 90 91 const enums = filterDataByKind(data, [TypeDocKind.Enum, TypeDocKind.LegacyEnum]); 92 const interfaces = filterDataByKind(data, TypeDocKind.Interface); 93 const constants = filterDataByKind( 94 data, 95 TypeDocKind.Variable, 96 entry => 97 (entry?.flags?.isConst || false) && 98 entry.name !== 'default' && 99 entry?.type?.name !== 'React.FC' 100 ); 101 102 const components = filterDataByKind( 103 data, 104 TypeDocKind.Variable, 105 entry => entry?.type?.name === 'React.FC' 106 ); 107 const componentsPropNames = components.map(component => `${component.name}Props`); 108 const componentsProps = filterDataByKind(props, TypeDocKind.TypeAlias, entry => 109 componentsPropNames.includes(entry.name) 110 ); 111 112 return ( 113 <> 114 <APISectionComponents data={components} componentsProps={componentsProps} /> 115 <APISectionConstants data={constants} apiName={apiName} /> 116 <APISectionMethods data={hooks} header="Hooks" /> 117 <APISectionMethods data={methods} apiName={apiName} /> 118 <APISectionMethods 119 data={eventSubscriptions} 120 apiName={apiName} 121 header="Event Subscriptions" 122 /> 123 {props && !componentsProps.length ? ( 124 <APISectionProps data={props} defaultProps={defaultProps} /> 125 ) : null} 126 <APISectionTypes data={types} /> 127 <APISectionInterfaces data={interfaces} /> 128 <APISectionEnums data={enums} /> 129 </> 130 ); 131 } catch (error) { 132 return <P>No API data file found, sorry!</P>; 133 } 134}; 135 136const APISection: React.FC<Props> = ({ packageName, apiName, forceVersion }) => { 137 const { version } = useContext(DocumentationPageContext); 138 const resolvedVersion = 139 forceVersion || 140 (version === 'unversioned' ? version : version === 'latest' ? LATEST_VERSION : version); 141 return renderAPI(packageName, resolvedVersion, apiName, !!forceVersion); 142}; 143 144export default APISection; 145