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