1import React from 'react'; 2 3import { InlineCode } from '~/components/base/code'; 4import { LI, UL } from '~/components/base/list'; 5import { P } from '~/components/base/paragraph'; 6import { H2, H4 } from '~/components/plugins/Headings'; 7import { 8 CommentTagData, 9 DefaultPropsDefinitionData, 10 PropData, 11 PropsDefinitionData, 12 TypeDeclarationData, 13 TypePropertyData, 14} from '~/components/plugins/api/APIDataTypes'; 15import { 16 CommentTextBlock, 17 resolveTypeName, 18 STYLES_SECONDARY, 19} from '~/components/plugins/api/APISectionUtils'; 20 21export type APISectionPropsProps = { 22 data: PropsDefinitionData[]; 23 defaultProps: DefaultPropsDefinitionData; 24}; 25 26const UNKNOWN_VALUE = '...'; 27 28const extractDefaultPropValue = ( 29 { comment, name }: PropData, 30 defaultProps: DefaultPropsDefinitionData 31): string | undefined => { 32 const annotationDefault = comment?.tags?.filter((tag: CommentTagData) => tag.tag === 'default'); 33 if (annotationDefault?.length) { 34 return annotationDefault[0].text; 35 } 36 return defaultProps?.type?.declaration?.children?.filter( 37 (defaultProp: TypePropertyData) => defaultProp.name === name 38 )[0]?.defaultValue; 39}; 40 41const renderInheritedProp = (ip: TypeDeclarationData) => { 42 const component = ip?.typeArguments ? ip.typeArguments[0]?.queryType?.name : null; 43 return component ? ( 44 <LI key={`inherited-prop-${component}`}> 45 <InlineCode>{component}</InlineCode> 46 </LI> 47 ) : null; 48}; 49 50const renderInheritedProps = (data: TypeDeclarationData[]): JSX.Element | undefined => { 51 const inheritedProps = data?.filter((ip: TypeDeclarationData) => ip.type === 'reference') ?? []; 52 if (inheritedProps.length) { 53 return ( 54 <div> 55 <H4>Inherited Props</H4> 56 <UL>{inheritedProps.map(renderInheritedProp)}</UL> 57 </div> 58 ); 59 } 60 return undefined; 61}; 62 63const renderProps = ( 64 { name, type }: PropsDefinitionData, 65 defaultValues: DefaultPropsDefinitionData 66): JSX.Element => { 67 const propsDeclarations = type.types?.filter((e: TypeDeclarationData) => e.declaration); 68 return ( 69 <div key={`props-definition-${name}`}> 70 <UL> 71 {propsDeclarations?.map((def: TypeDeclarationData) => 72 def.declaration?.children?.map((prop: PropData) => 73 renderProp(prop, extractDefaultPropValue(prop, defaultValues)) 74 ) 75 )} 76 </UL> 77 {renderInheritedProps(type.types)} 78 </div> 79 ); 80}; 81 82const renderProp = ({ comment, name, type, flags }: PropData, defaultValue?: string) => ( 83 <LI key={`prop-entry-${name}`}> 84 <H4>{name}</H4> 85 <P> 86 {flags?.isOptional && <span css={STYLES_SECONDARY}>Optional • </span>} 87 <span css={STYLES_SECONDARY}>Type:</span> <InlineCode>{resolveTypeName(type)}</InlineCode> 88 {defaultValue && defaultValue !== UNKNOWN_VALUE ? ( 89 <span> 90 <span css={STYLES_SECONDARY}> • Default:</span>{' '} 91 <InlineCode>{defaultValue}</InlineCode> 92 </span> 93 ) : null} 94 </P> 95 <CommentTextBlock comment={comment} /> 96 </LI> 97); 98 99const APISectionProps: React.FC<APISectionPropsProps> = ({ data, defaultProps }) => 100 data?.length ? ( 101 <> 102 <H2 key="props-header">Props</H2> 103 {data.map((propsDefinition: PropsDefinitionData) => 104 renderProps(propsDefinition, defaultProps) 105 )} 106 </> 107 ) : null; 108 109export default APISectionProps; 110