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  • 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