diff --git a/src/components/Fields/Field.tsx b/src/components/Fields/Field.tsx index 3f18b225..2fb5865f 100644 --- a/src/components/Fields/Field.tsx +++ b/src/components/Fields/Field.tsx @@ -32,7 +32,7 @@ export interface FieldProps extends SchemaOptions { export class Field extends React.Component { toggle = () => { if (this.props.field.expanded === undefined && this.props.expandByDefault) { - this.props.field.expanded = false; + this.props.field.collapse(); } else { this.props.field.toggle(); } @@ -94,6 +94,7 @@ export class Field extends React.Component { skipReadOnly={this.props.skipReadOnly} skipWriteOnly={this.props.skipWriteOnly} showTitle={this.props.showTitle} + level={this.props.level} /> diff --git a/src/components/Schema/ObjectSchema.tsx b/src/components/Schema/ObjectSchema.tsx index e115eb85..145ea98d 100644 --- a/src/components/Schema/ObjectSchema.tsx +++ b/src/components/Schema/ObjectSchema.tsx @@ -25,8 +25,10 @@ export const ObjectSchema = observer( discriminator, skipReadOnly, skipWriteOnly, + level, }: ObjectSchemaProps) => { - const { expandSingleSchemaField, showObjectSchemaExamples } = React.useContext(OptionsContext); + const { expandSingleSchemaField, showObjectSchemaExamples, schemaExpansionLevel } = + React.useContext(OptionsContext); const filteredFields = React.useMemo( () => @@ -42,7 +44,8 @@ export const ObjectSchema = observer( [skipReadOnly, skipWriteOnly, fields], ); - const expandByDefault = expandSingleSchemaField && filteredFields.length === 1; + const expandByDefault = + (expandSingleSchemaField && filteredFields.length === 1) || schemaExpansionLevel >= level!; return ( @@ -70,6 +73,7 @@ export const ObjectSchema = observer( skipReadOnly={skipReadOnly} skipWriteOnly={skipWriteOnly} showTitle={showTitle} + level={level} /> ); })} diff --git a/src/components/Schema/Schema.tsx b/src/components/Schema/Schema.tsx index f22fb9fe..3dc55497 100644 --- a/src/components/Schema/Schema.tsx +++ b/src/components/Schema/Schema.tsx @@ -16,6 +16,7 @@ export interface SchemaOptions { showTitle?: boolean; skipReadOnly?: boolean; skipWriteOnly?: boolean; + level?: number; } export interface SchemaProps extends SchemaOptions { @@ -25,7 +26,9 @@ export interface SchemaProps extends SchemaOptions { @observer export class Schema extends React.Component> { render() { - const { schema } = this.props; + const { schema, ...rest } = this.props; + const level = (rest.level || 0) + 1; + if (!schema) { return Schema not provided ; } @@ -50,7 +53,7 @@ export class Schema extends React.Component> { } return ( > { const types = Array.isArray(type) ? type : [type]; if (types.includes('object')) { if (schema.fields?.length) { - return ; + return ; } } else if (types.includes('array')) { - return ; + return ; } // TODO: maybe adjust FieldDetails to accept schema diff --git a/src/services/RedocNormalizedOptions.ts b/src/services/RedocNormalizedOptions.ts index 55bcba44..065f4166 100644 --- a/src/services/RedocNormalizedOptions.ts +++ b/src/services/RedocNormalizedOptions.ts @@ -37,6 +37,7 @@ export interface RedocRawOptions { simpleOneOfTypeLabel?: boolean | string; payloadSampleIdx?: number; expandSingleSchemaField?: boolean | string; + schemaExpansionLevel?: number | string | 'all'; showObjectSchemaExamples?: boolean | string; unstable_ignoreMimeParameters?: boolean; @@ -74,6 +75,12 @@ function argValueToNumber(value: number | string | undefined): number | undefine } } +function argValueToExpandLevel(value?: number | string | undefined, defaultValue = 0): number { + if (value === 'all') return Infinity; + + return argValueToNumber(value) || defaultValue; +} + export class RedocNormalizedOptions { static normalizeExpandResponses(value: RedocRawOptions['expandResponses']) { if (value === 'all') { @@ -225,6 +232,7 @@ export class RedocNormalizedOptions { simpleOneOfTypeLabel: boolean; payloadSampleIdx: number; expandSingleSchemaField: boolean; + schemaExpansionLevel: number; showObjectSchemaExamples: boolean; /* tslint:disable-next-line */ @@ -289,6 +297,7 @@ export class RedocNormalizedOptions { this.simpleOneOfTypeLabel = argValueToBoolean(raw.simpleOneOfTypeLabel); this.payloadSampleIdx = RedocNormalizedOptions.normalizePayloadSampleIdx(raw.payloadSampleIdx); this.expandSingleSchemaField = argValueToBoolean(raw.expandSingleSchemaField); + this.schemaExpansionLevel = argValueToExpandLevel(raw.schemaExpansionLevel); this.showObjectSchemaExamples = argValueToBoolean(raw.showObjectSchemaExamples); this.unstable_ignoreMimeParameters = argValueToBoolean(raw.unstable_ignoreMimeParameters); diff --git a/src/services/models/Field.ts b/src/services/models/Field.ts index ef031ab8..fe798e79 100644 --- a/src/services/models/Field.ts +++ b/src/services/models/Field.ts @@ -41,7 +41,7 @@ const DEFAULT_SERIALIZATION: Record< */ export class FieldModel { @observable - expanded: boolean | undefined = false; + expanded: boolean | undefined; schema: SchemaModel; name: string; @@ -120,4 +120,14 @@ export class FieldModel { toggle() { this.expanded = !this.expanded; } + + @action + collapse(): void { + this.expanded = false; + } + + @action + expand(): void { + this.expanded = true; + } }