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