diff --git a/addons/knobs/src/__types__/knob-test-cases.ts b/addons/knobs/src/__types__/knob-test-cases.ts index c0ef4ab67e50..19a147f5000b 100644 --- a/addons/knobs/src/__types__/knob-test-cases.ts +++ b/addons/knobs/src/__types__/knob-test-cases.ts @@ -106,7 +106,7 @@ expectKnobOfType( }, 'none' ), - select('select with string array', ['yes', 'no'], 'yes'), + select('select with string array', ['yes', 'no'], 'yes'), select('select with string literal array', stringLiteralArray, stringLiteralArray[0]), select('select with readonly array', ['red', 'blue'] as const, 'red'), select('select with string enum options', ButtonVariant, ButtonVariant.primary) @@ -123,7 +123,7 @@ expectKnobOfType( { 'type a': SomeEnum.Type1, 'type b': SomeEnum.Type2 }, SomeEnum.Type2 ), - select('select with number array', [1, 2, 3, 4], 1), + select('select with number array', [1, 2, 3, 4], 1), select('select with readonly number array', [1, 2] as const, 1) ); @@ -131,6 +131,60 @@ expectKnobOfType( select('select with null option', { a: 1, b: null }, null, groupId) ); +expectKnobOfType( + select( + 'select with string and string array options', + { + Red: 'red', + Blue: 'blue', + Yellow: 'yellow', + Rainbow: ['red', 'orange', 'etc'], + None: 'transparent', + }, + 'red' + ) +); + +expectKnobOfType( + select( + 'select with number and number array options', + { + Red: 1, + Blue: 2, + Yellow: 3, + Rainbow: [4, 5, 6], + None: 7, + }, + 7 + ) +); + +expectKnobOfType( + select( + 'select with string, string array, and null options', + { + Red: 'red', + Blue: 'blue', + Yellow: 'yellow', + Rainbow: ['red', 'orange', 'etc'], + None: null, + }, + null + ) +); + +expectKnobOfType( + select( + 'select with number array options', + { + ones: [1], + twos: [2, 2], + threes: [3, 3, 3], + }, + [1] + ) +); + /** Object knob */ expectKnobOfType( @@ -163,6 +217,68 @@ expectKnobOfType( options('options with group', {}, '', { display: 'check' }) ); +expectKnobOfType( + options('select with null option', { a: 1, b: null }, null, { display: 'check' }) +); + +expectKnobOfType( + options( + 'options with string and string array options', + { + Red: 'red', + Blue: 'blue', + Yellow: 'yellow', + Rainbow: ['red', 'orange', 'etc'], + None: 'transparent', + }, + 'red', + { display: 'check' } + ) +); + +expectKnobOfType( + options( + 'select with number and number array options', + { + Red: 1, + Blue: 2, + Yellow: 3, + Rainbow: [4, 5, 6], + None: 7, + }, + 7, + { display: 'check' } + ) +); + +expectKnobOfType( + options( + 'select with string, string array, and null options', + { + Red: 'red', + Blue: 'blue', + Yellow: 'yellow', + Rainbow: ['red', 'orange', 'etc'], + None: null, + }, + null, + { display: 'check' } + ) +); + +expectKnobOfType( + options( + 'select with number array options', + { + ones: [1], + twos: [2, 2], + threes: [3, 3, 3], + }, + [1], + { display: 'check' } + ) +); + /** Array knob */ const arrayReadonly = array('array as readonly', ['hi', 'there'] as const); diff --git a/addons/knobs/src/components/types/Options.tsx b/addons/knobs/src/components/types/Options.tsx index 94e227841e37..54a49191fe70 100644 --- a/addons/knobs/src/components/types/Options.tsx +++ b/addons/knobs/src/components/types/Options.tsx @@ -9,7 +9,14 @@ import CheckboxesType from './Checkboxes'; // TODO: Apply the Storybook theme to react-select -export type OptionsTypeKnobSingleValue = string | number | null | undefined; +export type OptionsTypeKnobSingleValue = + | string + | number + | null + | undefined + | string[] + | number[] + | (string | number)[]; export type OptionsTypeKnobValue< T extends OptionsTypeKnobSingleValue = OptionsTypeKnobSingleValue @@ -24,7 +31,7 @@ export type OptionsKnobOptionsDisplay = | 'multi-select'; export interface OptionsKnobOptions { - display?: OptionsKnobOptionsDisplay; + display: OptionsKnobOptionsDisplay; } export interface OptionsTypeKnob extends KnobControlConfig { diff --git a/addons/knobs/src/components/types/Select.tsx b/addons/knobs/src/components/types/Select.tsx index 9b1f6ab62d6d..8a7f387859f4 100644 --- a/addons/knobs/src/components/types/Select.tsx +++ b/addons/knobs/src/components/types/Select.tsx @@ -4,13 +4,13 @@ import PropTypes from 'prop-types'; import { Form } from '@storybook/components'; import { KnobControlConfig, KnobControlProps } from './types'; -export type SelectTypeKnobValue = string | number | null | undefined; +export type SelectTypeKnobValue = string | number | null | undefined | PropertyKey[]; export type SelectTypeOptionsProp = - | Record - | Record, T[keyof T]> - | Exclude[] - | readonly Exclude[]; + | Record + | Record, T[keyof T]> + | Extract[] + | readonly Extract[]; export interface SelectTypeKnob extends KnobControlConfig { @@ -31,8 +31,8 @@ const SelectType: FunctionComponent & { } = ({ knob, onChange }) => { const { options } = knob; const entries = Array.isArray(options) - ? options.reduce>((acc, k) => ({ ...acc, [k]: k }), {}) - : (options as Record); + ? options.reduce>((acc, k) => ({ ...acc, [k]: k }), {}) + : (options as Record); const selectedKey = Object.keys(entries).find(k => { if (Array.isArray(knob.value)) {