1f4b1168bSBartosz Kaszubowskiimport { mergeClasses } from '@expo/styleguide';
2f4b1168bSBartosz Kaszubowski
3299f02f2SBartosz Kaszubowskiimport {
4299f02f2SBartosz Kaszubowski  DefaultPropsDefinitionData,
5299f02f2SBartosz Kaszubowski  PropData,
6299f02f2SBartosz Kaszubowski  PropsDefinitionData,
76062847eSBartosz Kaszubowski  TypeDefinitionData,
8299f02f2SBartosz Kaszubowski} from '~/components/plugins/api/APIDataTypes';
925b16883SBartosz Kaszubowskiimport { APISectionDeprecationNote } from '~/components/plugins/api/APISectionDeprecationNote';
10b3bd70ceSTomasz Sapetaimport { APISectionPlatformTags } from '~/components/plugins/api/APISectionPlatformTags';
1107337117SBartosz Kaszubowskiimport {
1207337117SBartosz Kaszubowski  CommentTextBlock,
13c0b543d7SBartosz Kaszubowski  getCommentContent,
14b15ebaf2SBartosz Kaszubowski  getCommentOrSignatureComment,
15c8c9d6e8SBartosz Kaszubowski  getTagData,
16c4c6b9d1SBartosz Kaszubowski  getTagNamesList,
17c0b543d7SBartosz Kaszubowski  H3Code,
18c0b543d7SBartosz Kaszubowski  H4Code,
19b15ebaf2SBartosz Kaszubowski  renderTypeOrSignatureType,
2007337117SBartosz Kaszubowski  resolveTypeName,
216a5c065cSBartosz Kaszubowski  STYLES_APIBOX,
226a5c065cSBartosz Kaszubowski  STYLES_APIBOX_NESTED,
23f4b1168bSBartosz Kaszubowski  ELEMENT_SPACING,
246a5c065cSBartosz Kaszubowski  STYLES_NESTED_SECTION_HEADER,
256a5c065cSBartosz Kaszubowski  STYLES_NOT_EXPOSED_HEADER,
2607337117SBartosz Kaszubowski  STYLES_SECONDARY,
27c0b543d7SBartosz Kaszubowski  TypeDocKind,
2807337117SBartosz Kaszubowski} from '~/components/plugins/api/APISectionUtils';
293324c13cSBartosz Kaszubowskiimport { CODE, H2, H3, H4, LI, MONOSPACE, P, UL } from '~/ui/components/Text';
30299f02f2SBartosz Kaszubowski
31299f02f2SBartosz Kaszubowskiexport type APISectionPropsProps = {
32299f02f2SBartosz Kaszubowski  data: PropsDefinitionData[];
331ef472c3SBartosz Kaszubowski  defaultProps?: DefaultPropsDefinitionData;
341ef472c3SBartosz Kaszubowski  header?: string;
35299f02f2SBartosz Kaszubowski};
36299f02f2SBartosz Kaszubowski
37299f02f2SBartosz Kaszubowskiconst UNKNOWN_VALUE = '...';
38299f02f2SBartosz Kaszubowski
39299f02f2SBartosz Kaszubowskiconst extractDefaultPropValue = (
40299f02f2SBartosz Kaszubowski  { comment, name }: PropData,
411ef472c3SBartosz Kaszubowski  defaultProps?: DefaultPropsDefinitionData
42299f02f2SBartosz Kaszubowski): string | undefined => {
43c8c9d6e8SBartosz Kaszubowski  const annotationDefault = getTagData('default', comment);
44c8c9d6e8SBartosz Kaszubowski  if (annotationDefault) {
455990cc31SBartosz Kaszubowski    return getCommentContent(annotationDefault.content);
46299f02f2SBartosz Kaszubowski  }
47299f02f2SBartosz Kaszubowski  return defaultProps?.type?.declaration?.children?.filter(
48ffc1cfa8SBartosz Kaszubowski    (defaultProp: PropData) => defaultProp.name === name
49299f02f2SBartosz Kaszubowski  )[0]?.defaultValue;
50299f02f2SBartosz Kaszubowski};
51299f02f2SBartosz Kaszubowski
526062847eSBartosz Kaszubowskiconst renderInheritedProp = (ip: TypeDefinitionData) => {
531ef472c3SBartosz Kaszubowski  return (
546062847eSBartosz Kaszubowski    <LI key={`inherited-prop-${ip.name}-${ip.type}`}>
5512abeb84SBartosz Kaszubowski      <CODE>{resolveTypeName(ip)}</CODE>
56299f02f2SBartosz Kaszubowski    </LI>
571ef472c3SBartosz Kaszubowski  );
58299f02f2SBartosz Kaszubowski};
59299f02f2SBartosz Kaszubowski
60f52aa21eSBartosz Kaszubowskiconst renderInheritedProps = (
61c0b543d7SBartosz Kaszubowski  data: PropsDefinitionData | undefined,
62f52aa21eSBartosz Kaszubowski  exposeInSidebar?: boolean
63f52aa21eSBartosz Kaszubowski): JSX.Element | undefined => {
64c0b543d7SBartosz Kaszubowski  const inheritedData = data?.type?.types ?? data?.extendedTypes ?? [];
65c0b543d7SBartosz Kaszubowski  const inheritedProps =
66c0b543d7SBartosz Kaszubowski    inheritedData.filter((ip: TypeDefinitionData) => ip.type === 'reference') ?? [];
67299f02f2SBartosz Kaszubowski  if (inheritedProps.length) {
68299f02f2SBartosz Kaszubowski    return (
69f52aa21eSBartosz Kaszubowski      <>
70f52aa21eSBartosz Kaszubowski        {exposeInSidebar ? <H3>Inherited Props</H3> : <H4>Inherited Props</H4>}
71299f02f2SBartosz Kaszubowski        <UL>{inheritedProps.map(renderInheritedProp)}</UL>
72f52aa21eSBartosz Kaszubowski      </>
73299f02f2SBartosz Kaszubowski    );
74299f02f2SBartosz Kaszubowski  }
75299f02f2SBartosz Kaszubowski  return undefined;
76299f02f2SBartosz Kaszubowski};
77299f02f2SBartosz Kaszubowski
78c0b543d7SBartosz Kaszubowskiconst getPropsBaseTypes = (def: PropsDefinitionData) => {
79c0b543d7SBartosz Kaszubowski  if (def.kind === TypeDocKind.TypeAlias) {
80c0b543d7SBartosz Kaszubowski    const baseTypes = def?.type?.types
81c0b543d7SBartosz Kaszubowski      ? def.type.types?.filter((t: TypeDefinitionData) => t.declaration)
82c0b543d7SBartosz Kaszubowski      : [def.type];
83c0b543d7SBartosz Kaszubowski    return baseTypes.map(def => def?.declaration?.children);
84c0b543d7SBartosz Kaszubowski  } else if (def.kind === TypeDocKind.Interface) {
85c0b543d7SBartosz Kaszubowski    return def.children?.filter(child => !child.inheritedFrom) ?? [];
86c0b543d7SBartosz Kaszubowski  }
87c0b543d7SBartosz Kaszubowski  return [];
88c0b543d7SBartosz Kaszubowski};
89c0b543d7SBartosz Kaszubowski
90299f02f2SBartosz Kaszubowskiconst renderProps = (
91c0b543d7SBartosz Kaszubowski  def: PropsDefinitionData,
92f52aa21eSBartosz Kaszubowski  defaultValues?: DefaultPropsDefinitionData,
93f52aa21eSBartosz Kaszubowski  exposeInSidebar?: boolean
94299f02f2SBartosz Kaszubowski): JSX.Element => {
95c0b543d7SBartosz Kaszubowski  const propsDeclarations = getPropsBaseTypes(def)
96ffc1cfa8SBartosz Kaszubowski    .flat()
97ffc1cfa8SBartosz Kaszubowski    .filter((dec, i, arr) => arr.findIndex(t => t?.name === dec?.name) === i);
98ffc1cfa8SBartosz Kaszubowski
99299f02f2SBartosz Kaszubowski  return (
100c0b543d7SBartosz Kaszubowski    <div key={`props-definition-${def.name}`}>
101ffc1cfa8SBartosz Kaszubowski      {propsDeclarations?.map(prop =>
102f52aa21eSBartosz Kaszubowski        prop
103f52aa21eSBartosz Kaszubowski          ? renderProp(prop, extractDefaultPropValue(prop, defaultValues), exposeInSidebar)
104f52aa21eSBartosz Kaszubowski          : null
105299f02f2SBartosz Kaszubowski      )}
106c0b543d7SBartosz Kaszubowski      {renderInheritedProps(def, exposeInSidebar)}
107299f02f2SBartosz Kaszubowski    </div>
108299f02f2SBartosz Kaszubowski  );
109299f02f2SBartosz Kaszubowski};
110299f02f2SBartosz Kaszubowski
111d8d79196SBartosz Kaszubowskiexport const renderProp = (
112b15ebaf2SBartosz Kaszubowski  { comment, name, type, flags, signatures }: PropData,
113f52aa21eSBartosz Kaszubowski  defaultValue?: string,
114f52aa21eSBartosz Kaszubowski  exposeInSidebar?: boolean
1156a5c065cSBartosz Kaszubowski) => {
1166a5c065cSBartosz Kaszubowski  const HeaderComponent = exposeInSidebar ? H3Code : H4Code;
1175990cc31SBartosz Kaszubowski  const extractedSignatures = signatures || type?.declaration?.signatures;
1185990cc31SBartosz Kaszubowski  const extractedComment = getCommentOrSignatureComment(comment, extractedSignatures);
119*9d5e5238SSimek
1206a5c065cSBartosz Kaszubowski  return (
12112abeb84SBartosz Kaszubowski    <div key={`prop-entry-${name}`} css={[STYLES_APIBOX, STYLES_APIBOX_NESTED]}>
12225b16883SBartosz Kaszubowski      <APISectionDeprecationNote comment={extractedComment} />
123d9bd5b6cSBartosz Kaszubowski      <APISectionPlatformTags comment={comment} prefix="Only for:" />
124c4c6b9d1SBartosz Kaszubowski      <HeaderComponent tags={getTagNamesList(comment)}>
1253324c13cSBartosz Kaszubowski        <MONOSPACE weight="medium" css={!exposeInSidebar && STYLES_NOT_EXPOSED_HEADER}>
1263324c13cSBartosz Kaszubowski          {name}
1273324c13cSBartosz Kaszubowski        </MONOSPACE>
1286a5c065cSBartosz Kaszubowski      </HeaderComponent>
129f4b1168bSBartosz Kaszubowski      <P className={mergeClasses(extractedComment && ELEMENT_SPACING)}>
13007337117SBartosz Kaszubowski        {flags?.isOptional && <span css={STYLES_SECONDARY}>Optional&emsp;&bull;&emsp;</span>}
1315990cc31SBartosz Kaszubowski        <span css={STYLES_SECONDARY}>Type:</span>{' '}
1325990cc31SBartosz Kaszubowski        {renderTypeOrSignatureType(type, extractedSignatures)}
133299f02f2SBartosz Kaszubowski        {defaultValue && defaultValue !== UNKNOWN_VALUE ? (
134299f02f2SBartosz Kaszubowski          <span>
13507337117SBartosz Kaszubowski            <span css={STYLES_SECONDARY}>&emsp;&bull;&emsp;Default:</span>{' '}
13612abeb84SBartosz Kaszubowski            <CODE>{defaultValue}</CODE>
137299f02f2SBartosz Kaszubowski          </span>
138299f02f2SBartosz Kaszubowski        ) : null}
13984745a05SBartosz Kaszubowski      </P>
14025b16883SBartosz Kaszubowski      <CommentTextBlock comment={extractedComment} includePlatforms={false} />
141f4b1168bSBartosz Kaszubowski      {!extractedComment && <br />}
1426a5c065cSBartosz Kaszubowski    </div>
143299f02f2SBartosz Kaszubowski  );
1446a5c065cSBartosz Kaszubowski};
145299f02f2SBartosz Kaszubowski
1469f72d43bSBartosz Kaszubowskiconst APISectionProps = ({ data, defaultProps, header = 'Props' }: APISectionPropsProps) => {
1479f72d43bSBartosz Kaszubowski  const baseProp = data.find(prop => prop.name === header);
148f4b1168bSBartosz Kaszubowski  return data?.length > 0 ? (
149299f02f2SBartosz Kaszubowski    <>
15013032b48SBartosz Kaszubowski      {data?.length === 1 || header === 'Props' ? (
1511ef472c3SBartosz Kaszubowski        <H2 key="props-header">{header}</H2>
1521ef472c3SBartosz Kaszubowski      ) : (
1536a5c065cSBartosz Kaszubowski        <div>
15425b16883SBartosz Kaszubowski          {baseProp && <APISectionDeprecationNote comment={baseProp.comment} />}
1556a5c065cSBartosz Kaszubowski          <div css={STYLES_NESTED_SECTION_HEADER}>
1566a5c065cSBartosz Kaszubowski            <H4 key={`${header}-props-header`}>{header}</H4>
1576a5c065cSBartosz Kaszubowski          </div>
1586a5c065cSBartosz Kaszubowski          {baseProp && baseProp.comment ? <CommentTextBlock comment={baseProp.comment} /> : null}
1596a5c065cSBartosz Kaszubowski        </div>
1601ef472c3SBartosz Kaszubowski      )}
161299f02f2SBartosz Kaszubowski      {data.map((propsDefinition: PropsDefinitionData) =>
16213032b48SBartosz Kaszubowski        renderProps(propsDefinition, defaultProps, data?.length === 1 || header === 'Props')
163299f02f2SBartosz Kaszubowski      )}
164299f02f2SBartosz Kaszubowski    </>
165299f02f2SBartosz Kaszubowski  ) : null;
1669f72d43bSBartosz Kaszubowski};
167299f02f2SBartosz Kaszubowski
168299f02f2SBartosz Kaszubowskiexport default APISectionProps;
169