diff --git a/demo/playground/hmr-playground.tsx b/demo/playground/hmr-playground.tsx index 1cef075a..41b3c4ed 100644 --- a/demo/playground/hmr-playground.tsx +++ b/demo/playground/hmr-playground.tsx @@ -26,7 +26,7 @@ const specUrl = (userUrl && userUrl[1]) || (swagger ? 'swagger.yaml' : big ? 'big-openapi.json' : 'openapi.yaml'); let store; -const options: RedocRawOptions = { nativeScrollbars: false }; +const options: RedocRawOptions = { nativeScrollbars: false, maxDisplayedEnumValues: 2 }; async function init() { const spec = await loadAndBundleSpec(specUrl); diff --git a/src/components/Fields/EnumValues.tsx b/src/components/Fields/EnumValues.tsx index 09032147..9f82fabc 100644 --- a/src/components/Fields/EnumValues.tsx +++ b/src/components/Fields/EnumValues.tsx @@ -3,28 +3,52 @@ import { ExampleValue, FieldLabel } from '../../common-elements/fields'; import { l } from '../../services/Labels'; import { OptionsContext } from '../OptionsProvider'; +import styled from '../../styled-components'; +import { RedocRawOptions } from '../../services/RedocNormalizedOptions'; export interface EnumValuesProps { values: string[]; type: string; } -export class EnumValues extends React.PureComponent { +export interface EnumValuesState { + collapsed: boolean; +} + +export class EnumValues extends React.PureComponent { + state: EnumValuesState = { + collapsed: true, + }; + static contextType = OptionsContext; + + private toggle() { + this.setState({ collapsed: !this.state.collapsed }); + } + render() { const { values, type } = this.props; - const { enumSkipQuotes } = this.context; + const { collapsed } = this.state; + + // TODO: provide context interface in more elegant way + const { enumSkipQuotes, maxDisplayedEnumValues } = this.context as RedocRawOptions; + if (!values.length) { return null; } + const displayedItems = + this.state.collapsed && maxDisplayedEnumValues + ? values.slice(0, maxDisplayedEnumValues) + : values; + return (
{type === 'array' ? l('enumArray') : ''}{' '} {values.length === 1 ? l('enumSingleValue') : l('enum')}: {' '} - {values.map((value, idx) => { + {displayedItems.map((value, idx) => { const exampleValue = enumSkipQuotes ? value : JSON.stringify(value); return ( @@ -32,7 +56,25 @@ export class EnumValues extends React.PureComponent { ); })} + {maxDisplayedEnumValues ? ( + { + this.toggle(); + }} + > + {collapsed ? `… ${values.length - maxDisplayedEnumValues} more` : 'Hide'} + + ) : null}
); } } + +const ToggleButton = styled.span` + color: ${props => props.theme.colors.primary.main}; + vertical-align: middle; + font-size: 13px; + line-height: 20px; + padding: 0 5px; + cursor: pointer; +`; diff --git a/src/services/RedocNormalizedOptions.ts b/src/services/RedocNormalizedOptions.ts index 6007fe9c..75f3e9b4 100644 --- a/src/services/RedocNormalizedOptions.ts +++ b/src/services/RedocNormalizedOptions.ts @@ -38,6 +38,7 @@ export interface RedocRawOptions { enumSkipQuotes?: boolean | string; expandDefaultServerVariables?: boolean; + maxDisplayedEnumValues?: number; } function argValueToBoolean(val?: string | boolean, defaultValue?: boolean): boolean { @@ -50,6 +51,16 @@ function argValueToBoolean(val?: string | boolean, defaultValue?: boolean): bool return val; } +function argValueToNumber(value: number | string | undefined): number | undefined { + if (typeof value === 'string') { + return parseInt(value, 10); + } + + if (typeof value === 'number') { + return value; + } +} + export class RedocNormalizedOptions { static normalizeExpandResponses(value: RedocRawOptions['expandResponses']) { if (value === 'all') { @@ -177,6 +188,7 @@ export class RedocNormalizedOptions { allowedMdComponents: Record; expandDefaultServerVariables: boolean; + maxDisplayedEnumValues?: number; constructor(raw: RedocRawOptions, defaults: RedocRawOptions = {}) { raw = { ...defaults, ...raw }; @@ -232,5 +244,6 @@ export class RedocNormalizedOptions { this.allowedMdComponents = raw.allowedMdComponents || {}; this.expandDefaultServerVariables = argValueToBoolean(raw.expandDefaultServerVariables); + this.maxDisplayedEnumValues = argValueToNumber(raw.maxDisplayedEnumValues); } }