1import { css } from '@emotion/react'; 2import { theme, spacing, UndoIcon, iconSize } from '@expo/styleguide'; 3import React from 'react'; 4import ReactMarkdown from 'react-markdown'; 5 6import { InlineCode } from '~/components/base/code'; 7import { LI, UL } from '~/components/base/list'; 8import { H2, H3Code, H4, H4Code } from '~/components/plugins/Headings'; 9import { APIDataType } from '~/components/plugins/api/APIDataType'; 10import { 11 MethodDefinitionData, 12 MethodSignatureData, 13 PropData, 14 TypeSignaturesData, 15} from '~/components/plugins/api/APIDataTypes'; 16import { APISectionDeprecationNote } from '~/components/plugins/api/APISectionDeprecationNote'; 17import { APISectionPlatformTags } from '~/components/plugins/api/APISectionPlatformTags'; 18import { 19 CommentTextBlock, 20 getTagNamesList, 21 listParams, 22 mdComponents, 23 renderParams, 24 resolveTypeName, 25 STYLES_APIBOX, 26 STYLES_APIBOX_NESTED, 27 STYLES_NESTED_SECTION_HEADER, 28 STYLES_NOT_EXPOSED_HEADER, 29} from '~/components/plugins/api/APISectionUtils'; 30 31export type APISectionMethodsProps = { 32 data: (MethodDefinitionData | PropData)[]; 33 apiName?: string; 34 header?: string; 35}; 36 37export type RenderMethodOptions = { 38 apiName?: string; 39 header?: string; 40 exposeInSidebar?: boolean; 41}; 42 43export const renderMethod = ( 44 method: MethodDefinitionData | PropData, 45 { apiName, exposeInSidebar = true }: RenderMethodOptions = {} 46): JSX.Element[] => { 47 const signatures = method.signatures || (method as PropData)?.type?.declaration?.signatures || []; 48 const HeaderComponent = exposeInSidebar ? H3Code : H4Code; 49 return signatures.map( 50 ({ name, parameters, comment, type }: MethodSignatureData | TypeSignaturesData) => ( 51 <div 52 key={`method-signature-${method.name || name}-${parameters?.length || 0}`} 53 css={[STYLES_APIBOX, !exposeInSidebar && STYLES_APIBOX_NESTED]}> 54 <APISectionDeprecationNote comment={comment} /> 55 <APISectionPlatformTags comment={comment} prefix="Only for:" /> 56 <HeaderComponent tags={getTagNamesList(comment)}> 57 <InlineCode css={!exposeInSidebar ? STYLES_NOT_EXPOSED_HEADER : undefined}> 58 {apiName && `${apiName}.`} 59 {`${method.name || name}(${parameters ? listParams(parameters) : ''})`} 60 </InlineCode> 61 </HeaderComponent> 62 {parameters && renderParams(parameters)} 63 <CommentTextBlock comment={comment} includePlatforms={false} /> 64 {resolveTypeName(type) !== 'undefined' && ( 65 <> 66 <div css={STYLES_NESTED_SECTION_HEADER}> 67 <H4>Returns</H4> 68 </div> 69 <UL hideBullets> 70 <LI> 71 <UndoIcon 72 color={theme.icon.secondary} 73 size={iconSize.small} 74 css={returnIconStyles} 75 /> 76 <APIDataType typeDefinition={type} /> 77 </LI> 78 </UL> 79 {comment?.returns && ( 80 <ReactMarkdown components={mdComponents}>{comment.returns}</ReactMarkdown> 81 )} 82 </> 83 )} 84 </div> 85 ) 86 ); 87}; 88 89const APISectionMethods = ({ data, apiName, header = 'Methods' }: APISectionMethodsProps) => 90 data?.length ? ( 91 <> 92 <H2 key="methods-header">{header}</H2> 93 {data.map((method: MethodDefinitionData | PropData) => 94 renderMethod(method, { apiName, header }) 95 )} 96 </> 97 ) : null; 98 99const returnIconStyles = css({ 100 transform: 'rotate(180deg)', 101 marginRight: spacing[2], 102 verticalAlign: 'middle', 103}); 104 105export default APISectionMethods; 106