1a077d175SBartosz Kaszubowskiimport { css } from '@emotion/react';
2*f4b1168bSBartosz Kaszubowskiimport { theme, typography } from '@expo/styleguide';
3*f4b1168bSBartosz Kaszubowskiimport { borderRadius, breakpoints, spacing } from '@expo/styleguide-base';
43f609562SBartosz Kaszubowskiimport ReactMarkdown from 'react-markdown';
5586106d6SBartłomiej Klocek
63f609562SBartosz Kaszubowskiimport { HeadingType } from '~/common/headingManager';
7a077d175SBartosz Kaszubowskiimport { APIBox } from '~/components/plugins/APIBox';
8f6311d0dSBartosz Kaszubowskiimport { mdComponents } from '~/components/plugins/api/APISectionUtils';
9f6311d0dSBartosz Kaszubowskiimport { Callout } from '~/ui/components/Callout';
103f609562SBartosz Kaszubowskiimport { Collapsible } from '~/ui/components/Collapsible';
11f6311d0dSBartosz Kaszubowskiimport { P, CALLOUT, CODE, createPermalinkedComponent, BOLD } from '~/ui/components/Text';
12586106d6SBartłomiej Klocek
13586106d6SBartłomiej Klocektype PropertyMeta = {
14586106d6SBartłomiej Klocek  regexHuman?: string;
15586106d6SBartłomiej Klocek  deprecated?: boolean;
16586106d6SBartłomiej Klocek  hidden?: boolean;
17586106d6SBartłomiej Klocek  expoKit?: string;
18586106d6SBartłomiej Klocek  bareWorkflow?: string;
19586106d6SBartłomiej Klocek};
20586106d6SBartłomiej Klocek
21586106d6SBartłomiej Klocekexport type Property = {
22586106d6SBartłomiej Klocek  description?: string;
23586106d6SBartłomiej Klocek  type?: string | string[];
24586106d6SBartłomiej Klocek  meta?: PropertyMeta;
25586106d6SBartłomiej Klocek  pattern?: string;
26586106d6SBartłomiej Klocek  enum?: string[];
27586106d6SBartłomiej Klocek  example?: any;
28586106d6SBartłomiej Klocek  exampleString?: string;
29586106d6SBartłomiej Klocek  host?: object;
30586106d6SBartłomiej Klocek  properties?: Record<string, Property>;
31586106d6SBartłomiej Klocek  items?: {
32586106d6SBartłomiej Klocek    properties?: Record<string, Property>;
33586106d6SBartłomiej Klocek    [key: string]: any;
34586106d6SBartłomiej Klocek  };
35586106d6SBartłomiej Klocek  uniqueItems?: boolean;
36586106d6SBartłomiej Klocek  additionalProperties?: boolean;
37586106d6SBartłomiej Klocek};
38586106d6SBartłomiej Klocek
39586106d6SBartłomiej Klocektype FormattedProperty = {
40586106d6SBartłomiej Klocek  name: string;
41586106d6SBartłomiej Klocek  description: string;
423f609562SBartosz Kaszubowski  type?: string;
433f609562SBartosz Kaszubowski  example?: string;
443f609562SBartosz Kaszubowski  expoKit?: string;
453f609562SBartosz Kaszubowski  bareWorkflow?: string;
46a077d175SBartosz Kaszubowski  subproperties: FormattedProperty[];
47a077d175SBartosz Kaszubowski  parent?: string;
48586106d6SBartłomiej Klocek};
49586106d6SBartłomiej Klocek
504167f2acSBartosz Kaszubowskitype AppConfigSchemaProps = {
514167f2acSBartosz Kaszubowski  schema: Record<string, Property>;
524167f2acSBartosz Kaszubowski};
534167f2acSBartosz Kaszubowski
543c9a6b96SBartosz Kaszubowskiconst Anchor = createPermalinkedComponent(P, {
553f609562SBartosz Kaszubowski  baseNestingLevel: 3,
563f609562SBartosz Kaszubowski  sidebarType: HeadingType.InlineCode,
573f609562SBartosz Kaszubowski});
583f609562SBartosz Kaszubowski
59a077d175SBartosz Kaszubowskiconst PropertyName = ({ name, nestingLevel }: { name: string; nestingLevel: number }) => (
603c9a6b96SBartosz Kaszubowski  <Anchor level={nestingLevel} data-testid={name} data-heading="true" css={propertyNameStyle}>
613c9a6b96SBartosz Kaszubowski    <CODE css={typography.fontSizes[16]}>{name}</CODE>
623f609562SBartosz Kaszubowski  </Anchor>
633f609562SBartosz Kaszubowski);
643f609562SBartosz Kaszubowski
653c9a6b96SBartosz Kaszubowskiconst propertyNameStyle = css({ marginBottom: spacing[4] });
663c9a6b96SBartosz Kaszubowski
67586106d6SBartłomiej Klocekexport function formatSchema(rawSchema: [string, Property][]) {
68586106d6SBartłomiej Klocek  const formattedSchema: FormattedProperty[] = [];
69586106d6SBartłomiej Klocek
70586106d6SBartłomiej Klocek  rawSchema.map(property => {
71a077d175SBartosz Kaszubowski    appendProperty(formattedSchema, property);
72586106d6SBartłomiej Klocek  });
73586106d6SBartłomiej Klocek
74586106d6SBartłomiej Klocek  return formattedSchema;
75586106d6SBartłomiej Klocek}
76586106d6SBartłomiej Klocek
77a077d175SBartosz Kaszubowskifunction appendProperty(formattedSchema: FormattedProperty[], property: [string, Property]) {
78586106d6SBartłomiej Klocek  const propertyValue = property[1];
79586106d6SBartłomiej Klocek
80586106d6SBartłomiej Klocek  if (propertyValue.meta && (propertyValue.meta.deprecated || propertyValue.meta.hidden)) {
81586106d6SBartłomiej Klocek    return;
82586106d6SBartłomiej Klocek  }
83586106d6SBartłomiej Klocek
84a077d175SBartosz Kaszubowski  formattedSchema.push(formatProperty(property));
85a077d175SBartosz Kaszubowski}
86586106d6SBartłomiej Klocek
87a077d175SBartosz Kaszubowskifunction formatProperty(property: [string, Property], parent?: string): FormattedProperty {
88a077d175SBartosz Kaszubowski  const propertyKey = property[0];
89a077d175SBartosz Kaszubowski  const propertyValue = property[1];
90a077d175SBartosz Kaszubowski
91a077d175SBartosz Kaszubowski  const subproperties: FormattedProperty[] = [];
92586106d6SBartłomiej Klocek
93586106d6SBartłomiej Klocek  if (propertyValue.properties) {
94586106d6SBartłomiej Klocek    Object.entries(propertyValue.properties).forEach(subproperty => {
95a077d175SBartosz Kaszubowski      subproperties.push(
96a077d175SBartosz Kaszubowski        formatProperty(subproperty, parent ? `${parent}.${propertyKey}` : propertyKey)
97a077d175SBartosz Kaszubowski      );
98586106d6SBartłomiej Klocek    });
99a077d175SBartosz Kaszubowski  } // note: sub-properties are sometimes nested within "items"
100586106d6SBartłomiej Klocek  else if (propertyValue.items && propertyValue.items.properties) {
101586106d6SBartłomiej Klocek    Object.entries(propertyValue.items.properties).forEach(subproperty => {
102a077d175SBartosz Kaszubowski      subproperties.push(
103a077d175SBartosz Kaszubowski        formatProperty(subproperty, parent ? `${parent}.${propertyKey}` : propertyKey)
104a077d175SBartosz Kaszubowski      );
105586106d6SBartłomiej Klocek    });
106586106d6SBartłomiej Klocek  }
107a077d175SBartosz Kaszubowski
108a077d175SBartosz Kaszubowski  return {
109a077d175SBartosz Kaszubowski    name: propertyKey,
110a077d175SBartosz Kaszubowski    description: createDescription(property),
111a077d175SBartosz Kaszubowski    type: _getType(propertyValue),
112a077d175SBartosz Kaszubowski    example: propertyValue.exampleString?.replaceAll('\n', ''),
113a077d175SBartosz Kaszubowski    expoKit: propertyValue?.meta?.expoKit,
114a077d175SBartosz Kaszubowski    bareWorkflow: propertyValue?.meta?.bareWorkflow,
115a077d175SBartosz Kaszubowski    subproperties,
116a077d175SBartosz Kaszubowski    parent,
117a077d175SBartosz Kaszubowski  };
118586106d6SBartłomiej Klocek}
119586106d6SBartłomiej Klocek
120a077d175SBartosz Kaszubowskiexport function _getType({ enum: enm, type }: Partial<Property>) {
121a077d175SBartosz Kaszubowski  return enm ? 'enum' : type?.toString().replace(',', ' || ');
122586106d6SBartłomiej Klocek}
123586106d6SBartłomiej Klocek
124586106d6SBartłomiej Klocekexport function createDescription(propertyEntry: [string, Property]) {
125a077d175SBartosz Kaszubowski  const { description, meta } = propertyEntry[1];
126586106d6SBartłomiej Klocek
127a077d175SBartosz Kaszubowski  let propertyDescription = ``;
128a077d175SBartosz Kaszubowski  if (description) {
129a077d175SBartosz Kaszubowski    propertyDescription += description;
130586106d6SBartłomiej Klocek  }
131a077d175SBartosz Kaszubowski  if (meta && meta.regexHuman) {
132a077d175SBartosz Kaszubowski    propertyDescription += `\n\n` + meta.regexHuman;
133586106d6SBartłomiej Klocek  }
134586106d6SBartłomiej Klocek
135586106d6SBartłomiej Klocek  return propertyDescription;
136586106d6SBartłomiej Klocek}
137586106d6SBartłomiej Klocek
1384167f2acSBartosz Kaszubowskiconst AppConfigSchemaPropertiesTable = ({ schema }: AppConfigSchemaProps) => {
1394167f2acSBartosz Kaszubowski  const rawSchema = Object.entries(schema);
140586106d6SBartłomiej Klocek  const formattedSchema = formatSchema(rawSchema);
141586106d6SBartłomiej Klocek
142586106d6SBartłomiej Klocek  return (
1433c9a6b96SBartosz Kaszubowski    <>
144a077d175SBartosz Kaszubowski      {formattedSchema.map((formattedProperty, index) => (
145a077d175SBartosz Kaszubowski        <AppConfigProperty
146a077d175SBartosz Kaszubowski          {...formattedProperty}
147a077d175SBartosz Kaszubowski          key={`${formattedProperty.name}-${index}`}
148a077d175SBartosz Kaszubowski          nestingLevel={0}
149a077d175SBartosz Kaszubowski        />
150a077d175SBartosz Kaszubowski      ))}
1513c9a6b96SBartosz Kaszubowski    </>
152a077d175SBartosz Kaszubowski  );
153a077d175SBartosz Kaszubowski};
154a077d175SBartosz Kaszubowski
155a077d175SBartosz Kaszubowskiconst AppConfigProperty = ({
156a077d175SBartosz Kaszubowski  name,
157a077d175SBartosz Kaszubowski  description,
158a077d175SBartosz Kaszubowski  example,
159a077d175SBartosz Kaszubowski  expoKit,
160a077d175SBartosz Kaszubowski  bareWorkflow,
161a077d175SBartosz Kaszubowski  type,
162a077d175SBartosz Kaszubowski  nestingLevel,
163a077d175SBartosz Kaszubowski  subproperties,
164a077d175SBartosz Kaszubowski  parent,
165a077d175SBartosz Kaszubowski}: FormattedProperty & { nestingLevel: number }) => (
166a077d175SBartosz Kaszubowski  <APIBox css={boxStyle}>
167a077d175SBartosz Kaszubowski    <PropertyName name={name} nestingLevel={nestingLevel} />
168db57e342SBartosz Kaszubowski    <CALLOUT theme="secondary" data-text="true" css={typeRow}>
1693c9a6b96SBartosz Kaszubowski      Type: <CODE>{type || 'undefined'}</CODE>
170a077d175SBartosz Kaszubowski      {nestingLevel > 0 && (
171a077d175SBartosz Kaszubowski        <>
172a077d175SBartosz Kaszubowski          &emsp;&bull;&emsp;Path:{' '}
173a077d175SBartosz Kaszubowski          <code css={secondaryCodeLineStyle}>
174a077d175SBartosz Kaszubowski            {parent}.{name}
175a077d175SBartosz Kaszubowski          </code>
176a077d175SBartosz Kaszubowski        </>
177a077d175SBartosz Kaszubowski      )}
178a077d175SBartosz Kaszubowski    </CALLOUT>
1793f609562SBartosz Kaszubowski    <ReactMarkdown components={mdComponents}>{description}</ReactMarkdown>
1803f609562SBartosz Kaszubowski    {expoKit && (
1813f609562SBartosz Kaszubowski      <Collapsible summary="ExpoKit">
1823f609562SBartosz Kaszubowski        <ReactMarkdown components={mdComponents}>{expoKit}</ReactMarkdown>
1833f609562SBartosz Kaszubowski      </Collapsible>
1843f609562SBartosz Kaszubowski    )}
1853f609562SBartosz Kaszubowski    {bareWorkflow && (
1863f609562SBartosz Kaszubowski      <Collapsible summary="Bare Workflow">
1873f609562SBartosz Kaszubowski        <ReactMarkdown components={mdComponents}>{bareWorkflow}</ReactMarkdown>
1883f609562SBartosz Kaszubowski      </Collapsible>
1893f609562SBartosz Kaszubowski    )}
190f6311d0dSBartosz Kaszubowski    {example && (
191f6311d0dSBartosz Kaszubowski      <Callout>
192f6311d0dSBartosz Kaszubowski        <BOLD>Example</BOLD>
193f6311d0dSBartosz Kaszubowski        <ReactMarkdown components={mdComponents}>{example}</ReactMarkdown>
194f6311d0dSBartosz Kaszubowski      </Callout>
195f6311d0dSBartosz Kaszubowski    )}
196a077d175SBartosz Kaszubowski    <div>
197a077d175SBartosz Kaszubowski      {subproperties.length > 0 &&
198a077d175SBartosz Kaszubowski        subproperties.map((formattedProperty, index) => (
199a077d175SBartosz Kaszubowski          <AppConfigProperty
200a077d175SBartosz Kaszubowski            {...formattedProperty}
201a077d175SBartosz Kaszubowski            key={`${name}-${index}`}
202a077d175SBartosz Kaszubowski            nestingLevel={nestingLevel + 1}
203a077d175SBartosz Kaszubowski          />
204a077d175SBartosz Kaszubowski        ))}
205a077d175SBartosz Kaszubowski    </div>
206a077d175SBartosz Kaszubowski  </APIBox>
207586106d6SBartłomiej Klocek);
208a077d175SBartosz Kaszubowski
209a077d175SBartosz Kaszubowskiconst boxStyle = css({
210a077d175SBartosz Kaszubowski  boxShadow: 'none',
211a077d175SBartosz Kaszubowski  marginBottom: 0,
212a077d175SBartosz Kaszubowski  borderRadius: 0,
213a077d175SBartosz Kaszubowski  borderBottomWidth: 0,
214db57e342SBartosz Kaszubowski  paddingBottom: 0,
215a077d175SBartosz Kaszubowski
216a077d175SBartosz Kaszubowski  '&:first-of-type': {
21714c78e61SJon Samp    borderTopLeftRadius: borderRadius.md,
21814c78e61SJon Samp    borderTopRightRadius: borderRadius.md,
219a077d175SBartosz Kaszubowski  },
220a077d175SBartosz Kaszubowski
221a077d175SBartosz Kaszubowski  '&:last-of-type': {
22214c78e61SJon Samp    borderBottomLeftRadius: borderRadius.md,
22314c78e61SJon Samp    borderBottomRightRadius: borderRadius.md,
224a077d175SBartosz Kaszubowski    marginBottom: spacing[4],
225a077d175SBartosz Kaszubowski    borderBottomWidth: 1,
226a077d175SBartosz Kaszubowski  },
227a077d175SBartosz Kaszubowski
228a077d175SBartosz Kaszubowski  [`@media screen and (max-width: ${breakpoints.medium + 124}px)`]: {
229a077d175SBartosz Kaszubowski    paddingTop: spacing[4],
230a077d175SBartosz Kaszubowski  },
231a077d175SBartosz Kaszubowski});
232a077d175SBartosz Kaszubowski
233a077d175SBartosz Kaszubowskiconst secondaryCodeLineStyle = css({
234a077d175SBartosz Kaszubowski  color: theme.text.secondary,
235a077d175SBartosz Kaszubowski  padding: `0 ${spacing[1]}px`,
236a077d175SBartosz Kaszubowski  wordBreak: 'break-word',
237a077d175SBartosz Kaszubowski});
2384167f2acSBartosz Kaszubowski
239db57e342SBartosz Kaszubowskiconst typeRow = css({
240db57e342SBartosz Kaszubowski  margin: `${spacing[3]}px 0`,
241db57e342SBartosz Kaszubowski});
242db57e342SBartosz Kaszubowski
2434167f2acSBartosz Kaszubowskiexport default AppConfigSchemaPropertiesTable;
244