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