import React from 'react'; import { P } from '~/components/base/paragraph'; import { ClassDefinitionData, GeneratedData } from '~/components/plugins/api/APIDataTypes'; import APISectionClasses from '~/components/plugins/api/APISectionClasses'; import APISectionComponents from '~/components/plugins/api/APISectionComponents'; import APISectionConstants from '~/components/plugins/api/APISectionConstants'; import APISectionEnums from '~/components/plugins/api/APISectionEnums'; import APISectionInterfaces from '~/components/plugins/api/APISectionInterfaces'; import APISectionMethods from '~/components/plugins/api/APISectionMethods'; import APISectionProps from '~/components/plugins/api/APISectionProps'; import APISectionTypes from '~/components/plugins/api/APISectionTypes'; import { getComponentName, TypeDocKind } from '~/components/plugins/api/APISectionUtils'; import { usePageApiVersion } from '~/providers/page-api-version'; import versions from '~/public/static/constants/versions.json'; const { LATEST_VERSION } = versions; type Props = { packageName: string; apiName?: string; forceVersion?: string; strictTypes?: boolean; testRequire?: any; }; const filterDataByKind = ( entries: GeneratedData[] = [], kind: TypeDocKind | TypeDocKind[], additionalCondition: (entry: GeneratedData) => boolean = () => true ) => entries.filter( (entry: GeneratedData) => (Array.isArray(kind) ? kind.includes(entry.kind) : entry.kind === kind) && additionalCondition(entry) ); const isHook = ({ name }: GeneratedData) => name.startsWith('use') && // note(simek): hardcode this exception until the method will be renamed name !== 'useSystemBrightnessAsync'; const isListener = ({ name }: GeneratedData) => name.endsWith('Listener') || name.endsWith('Listeners'); const isProp = ({ name }: GeneratedData) => name.includes('Props') && name !== 'ErrorRecoveryProps'; const isComponent = ({ type, extendedTypes, signatures }: GeneratedData) => { if (type?.name && ['React.FC', 'ForwardRefExoticComponent'].includes(type?.name)) { return true; } else if (extendedTypes && extendedTypes.length) { return extendedTypes[0].name === 'Component'; } else if (signatures && signatures.length) { if ( signatures[0].type.name === 'Element' || (signatures[0].parameters && signatures[0].parameters[0].name === 'props') ) { return true; } } return false; }; const isConstant = ({ name, type }: GeneratedData) => !['default', 'Constants', 'EventEmitter'].includes(name) && !(type?.name && ['React.FC', 'ForwardRefExoticComponent'].includes(type?.name)); const renderAPI = ( packageName: string, version: string = 'unversioned', apiName?: string, strictTypes: boolean = false, testRequire: any = undefined ): JSX.Element => { try { const { children: data } = testRequire ? testRequire(`~/public/static/data/${version}/${packageName}.json`) : require(`~/public/static/data/${version}/${packageName}.json`); const methods = filterDataByKind( data, TypeDocKind.Function, entry => !isListener(entry) && !isHook(entry) && !isComponent(entry) ); const eventSubscriptions = filterDataByKind(data, TypeDocKind.Function, isListener); const types = filterDataByKind( data, TypeDocKind.TypeAlias, entry => !isProp(entry) && !!( entry.type.declaration || entry.type.types || entry.type.type || entry.type.typeArguments ) && (strictTypes && apiName ? entry.name.startsWith(apiName) : true) ); const props = filterDataByKind( data, TypeDocKind.TypeAlias, entry => isProp(entry) && !!(entry.type.types || entry.type.declaration?.children) ); const defaultProps = filterDataByKind( data .filter((entry: GeneratedData) => entry.kind === TypeDocKind.Class) .map((entry: GeneratedData) => entry.children) .flat(), TypeDocKind.Property, entry => entry.name === 'defaultProps' )[0]; const enums = filterDataByKind( data, [TypeDocKind.Enum, TypeDocKind.LegacyEnum], entry => entry.name !== 'default' ); const interfaces = filterDataByKind(data, TypeDocKind.Interface); const constants = filterDataByKind(data, TypeDocKind.Variable, entry => isConstant(entry)); const components = filterDataByKind( data, [TypeDocKind.Variable, TypeDocKind.Class, TypeDocKind.Function], entry => isComponent(entry) ); const componentsPropNames = components.map( ({ name, children }) => `${getComponentName(name, children)}Props` ); const componentsProps = filterDataByKind(props, TypeDocKind.TypeAlias, entry => componentsPropNames.includes(entry.name) ); const classes = filterDataByKind(data, TypeDocKind.Class, entry => !isComponent(entry)); const componentsChildren = components .map((cls: ClassDefinitionData) => cls.children?.filter( child => (child?.kind === TypeDocKind.Method || child?.kind === TypeDocKind.Property) && child?.flags?.isExternal !== true && !child.inheritedFrom && child.name !== 'render' && // note(simek): hide unannotated "private" methods !child.name.startsWith('_') ) ) .flat(); const methodsNames = methods.map(method => method.name); const staticMethods = componentsChildren.filter( // note(simek): hide duplicate exports from class components method => method?.kind === TypeDocKind.Method && method?.flags?.isStatic === true && !methodsNames.includes(method.name) && !isHook(method as GeneratedData) ); const componentMethods = componentsChildren .filter( method => method?.kind === TypeDocKind.Method && method?.flags?.isStatic !== true && !method?.overwrites ) .filter(Boolean); const hooks = filterDataByKind( [...data, ...componentsChildren].filter(Boolean), [TypeDocKind.Function, TypeDocKind.Property], isHook ); return ( <> {props && !componentsProps.length ? ( ) : null} ); } catch { return

No API data file found, sorry!

; } }; const APISection = ({ packageName, apiName, forceVersion, strictTypes = false, testRequire = undefined, }: Props) => { const { version } = usePageApiVersion(); const resolvedVersion = forceVersion || (version === 'unversioned' ? version : version === 'latest' ? LATEST_VERSION : version); return renderAPI(packageName, resolvedVersion, apiName, strictTypes, testRequire); }; export default APISection;