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