1import { css } from '@emotion/react';
2import { theme } from '@expo/styleguide';
3import { spacing } from '@expo/styleguide-base';
4
5import { EnumDefinitionData, EnumValueData } from '~/components/plugins/api/APIDataTypes';
6import { APISectionDeprecationNote } from '~/components/plugins/api/APISectionDeprecationNote';
7import { APISectionPlatformTags } from '~/components/plugins/api/APISectionPlatformTags';
8import {
9  CommentTextBlock,
10  getTagNamesList,
11  STYLES_APIBOX,
12  STYLES_APIBOX_NESTED,
13  H3Code,
14} from '~/components/plugins/api/APISectionUtils';
15import { H2, H4, CODE, MONOSPACE } from '~/ui/components/Text';
16
17export type APISectionEnumsProps = {
18  data: EnumDefinitionData[];
19};
20
21const sortByValue = (a: EnumValueData, b: EnumValueData) => {
22  if (a.type && a.type.value !== undefined && b.type && b.type.value !== undefined) {
23    if (typeof a.type.value === 'string' && typeof b.type.value === 'string') {
24      return a.type.value.localeCompare(b.type.value);
25    } else if (typeof a.type.value === 'number' && typeof b.type.value === 'number') {
26      return (a.type.value ?? Number.MIN_VALUE) - (b.type.value ?? Number.MIN_VALUE);
27    }
28  }
29  return 0;
30};
31
32const renderEnumValue = (value: any) => (typeof value === 'string' ? `"${value}"` : value);
33
34const renderEnum = ({ name, children, comment }: EnumDefinitionData): JSX.Element => (
35  <div key={`enum-definition-${name}`} css={[STYLES_APIBOX, enumContentStyles]}>
36    <APISectionDeprecationNote comment={comment} />
37    <APISectionPlatformTags comment={comment} prefix="Only for:" />
38    <H3Code tags={getTagNamesList(comment)}>
39      <MONOSPACE weight="medium">{name}</MONOSPACE>
40    </H3Code>
41    <CommentTextBlock comment={comment} includePlatforms={false} />
42    {children.sort(sortByValue).map((enumValue: EnumValueData) => (
43      <div css={[STYLES_APIBOX, STYLES_APIBOX_NESTED]} key={enumValue.name}>
44        <APISectionDeprecationNote comment={enumValue.comment} />
45        <APISectionPlatformTags comment={enumValue.comment} prefix="Only for:" />
46        <H4 css={enumValueNameStyle}>
47          <CODE>{enumValue.name}</CODE>
48        </H4>
49        <CODE css={enumValueStyles}>
50          {`${name}.${enumValue.name} = ${renderEnumValue(enumValue.type.value)}`}
51        </CODE>
52        <CommentTextBlock comment={enumValue.comment} includePlatforms={false} />
53      </div>
54    ))}
55  </div>
56);
57
58const APISectionEnums = ({ data }: APISectionEnumsProps) =>
59  data?.length ? (
60    <>
61      <H2 key="enums-header">Enums</H2>
62      {data.map(renderEnum)}
63    </>
64  ) : null;
65
66const enumValueNameStyle = css({
67  h4: {
68    marginTop: 0,
69  },
70});
71
72const enumValueStyles = css({
73  display: 'inline-block',
74  padding: `0 ${spacing[2]}px`,
75  color: theme.text.secondary,
76  fontSize: '75%',
77  marginBottom: spacing[4],
78});
79
80const enumContentStyles = css({
81  paddingBottom: 0,
82});
83
84export default APISectionEnums;
85