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 getMethodName, 21 getTagNamesList, 22 mdComponents, 23 renderParams, 24 resolveTypeName, 25 STYLES_APIBOX, 26 STYLES_APIBOX_NESTED, 27 STYLES_NESTED_SECTION_HEADER, 28 STYLES_NOT_EXPOSED_HEADER, 29 TypeDocKind, 30} from '~/components/plugins/api/APISectionUtils'; 31 32export type APISectionMethodsProps = { 33 data: (MethodDefinitionData | PropData)[]; 34 apiName?: string; 35 header?: string; 36 exposeInSidebar?: boolean; 37}; 38 39export type RenderMethodOptions = { 40 apiName?: string; 41 header?: string; 42 exposeInSidebar?: boolean; 43}; 44 45export const renderMethod = ( 46 method: MethodDefinitionData | PropData, 47 { apiName, exposeInSidebar = true }: RenderMethodOptions = {} 48): JSX.Element[] => { 49 const signatures = method.signatures || (method as PropData)?.type?.declaration?.signatures || []; 50 const HeaderComponent = exposeInSidebar ? H3Code : H4Code; 51 return signatures.map( 52 ({ name, parameters, comment, type }: MethodSignatureData | TypeSignaturesData) => ( 53 <div 54 key={`method-signature-${method.name || name}-${parameters?.length || 0}`} 55 css={[STYLES_APIBOX, !exposeInSidebar && STYLES_APIBOX_NESTED]}> 56 <APISectionDeprecationNote comment={comment} /> 57 <APISectionPlatformTags comment={comment} prefix="Only for:" /> 58 <HeaderComponent tags={getTagNamesList(comment)}> 59 <InlineCode css={!exposeInSidebar ? STYLES_NOT_EXPOSED_HEADER : undefined}> 60 {getMethodName(method as MethodDefinitionData, apiName, name, parameters)} 61 </InlineCode> 62 </HeaderComponent> 63 {parameters && parameters.length > 0 && renderParams(parameters)} 64 <CommentTextBlock comment={comment} includePlatforms={false} /> 65 {resolveTypeName(type) !== 'undefined' && ( 66 <> 67 <div css={STYLES_NESTED_SECTION_HEADER}> 68 <H4>Returns</H4> 69 </div> 70 <UL hideBullets> 71 <LI> 72 <UndoIcon 73 color={theme.icon.secondary} 74 size={iconSize.small} 75 css={returnIconStyles} 76 /> 77 <APIDataType typeDefinition={type} /> 78 </LI> 79 </UL> 80 {comment?.returns && ( 81 <ReactMarkdown components={mdComponents}>{comment.returns}</ReactMarkdown> 82 )} 83 </> 84 )} 85 </div> 86 ) 87 ); 88}; 89 90const APISectionMethods = ({ 91 data, 92 apiName, 93 header = 'Methods', 94 exposeInSidebar = true, 95}: APISectionMethodsProps) => 96 data?.length ? ( 97 <> 98 <H2 key="methods-header">{header}</H2> 99 {data.map((method: MethodDefinitionData | PropData) => 100 renderMethod(method, { apiName, header, exposeInSidebar }) 101 )} 102 </> 103 ) : null; 104 105const returnIconStyles = css({ 106 transform: 'rotate(180deg)', 107 marginRight: spacing[2], 108 verticalAlign: 'middle', 109}); 110 111export default APISectionMethods; 112 113export const APIMethod = ({ 114 name, 115 comment, 116 returnTypeName, 117 isProperty = false, 118 isReturnTypeReference = false, 119 exposeInSidebar = false, 120 parameters = [], 121}: { 122 exposeInSidebar?: boolean; 123 name: string; 124 comment: string; 125 returnTypeName: string; 126 isProperty: boolean; 127 isReturnTypeReference: boolean; 128 parameters: { 129 name: string; 130 comment?: string; 131 typeName: string; 132 isReference?: boolean; 133 }[]; 134}): JSX.Element[] => { 135 const parsedParameters = parameters.map(param => ({ 136 name: param.name, 137 type: { name: param.typeName, type: param.isReference ? 'reference' : 'literal' }, 138 comment: { 139 text: param.comment, 140 }, 141 })); 142 return renderMethod( 143 { 144 name, 145 signatures: [ 146 { 147 name, 148 parameters: parsedParameters, 149 comment: { 150 text: comment, 151 }, 152 type: { name: returnTypeName, type: isReturnTypeReference ? 'reference' : 'literal' }, 153 }, 154 ], 155 kind: isProperty ? TypeDocKind.Property : TypeDocKind.Function, 156 }, 157 { exposeInSidebar } 158 ); 159}; 160