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