From 24bdbb44b72f678ef2bdc14eef050f05c92c7e24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ro=C5=BCek?= Date: Wed, 30 Jan 2019 15:42:25 +0100 Subject: [PATCH 1/3] feat: creatable select --- src/Select.tsx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Select.tsx b/src/Select.tsx index 41355215..fc3f3823 100644 --- a/src/Select.tsx +++ b/src/Select.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { ReactEventHandler } from 'react'; import ReactSelect from 'react-select'; import ReactAsyncSelect, { Props as AsyncProps } from 'react-select/lib/Async'; // we can live with it, as it adds very little overhead (just a wrapper around Select) +import ReactCreatableSelect, { Props as CreatableProps } from 'react-select/lib/Creatable'; import { Props } from 'react-select/lib/Select'; import { Omit } from '@stoplight/types'; @@ -35,13 +36,17 @@ export interface ISelectBaseProps { export interface ISelectProps extends ISelectBaseProps, - Omit, 'noOptionsMessage'>, 'loadingMessage'> {} // pipe doesn't work for some reason + Omit, 'noOptionsMessage' | 'loadingMessage'> {} export interface ISelectAsyncProps extends ISelectBaseProps, - Omit, 'noOptionsMessage'>, 'loadingMessage'> {} // pipe doesn't work for some reason + Omit, 'noOptionsMessage' | 'loadingMessage'> {} -export type ISelect = ISelectProps | ISelectAsyncProps; +export interface ISelectCreatableProps + extends ISelectBaseProps, + Omit, 'noOptionsMessage' | 'loadingMessage'> {} + +export type ISelect = ISelectProps | ISelectAsyncProps | ISelectCreatableProps; export interface ISelectOption { label: string; @@ -97,10 +102,14 @@ export const Select: React.FunctionComponent = props => { styles: customStyles(), }; - if ('loadOptions' in props || 'defaultOptions' in props) { + if ('loadOptions' in props) { return ; } + if ('onCreateOption' in props) { + return ; + } + return ; }; From 26c06f0944fe5c4b5d492d7736591257d2523727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ro=C5=BCek?= Date: Wed, 30 Jan 2019 16:56:57 +0100 Subject: [PATCH 2/3] feat: support AsyncCreatable as well --- src/Select.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Select.tsx b/src/Select.tsx index fc3f3823..126ff383 100644 --- a/src/Select.tsx +++ b/src/Select.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { ReactEventHandler } from 'react'; import ReactSelect from 'react-select'; import ReactAsyncSelect, { Props as AsyncProps } from 'react-select/lib/Async'; // we can live with it, as it adds very little overhead (just a wrapper around Select) +import ReactAsyncCreatableSelect from 'react-select/lib/AsyncCreatable'; import ReactCreatableSelect, { Props as CreatableProps } from 'react-select/lib/Creatable'; import { Props } from 'react-select/lib/Select'; @@ -46,7 +47,9 @@ export interface ISelectCreatableProps extends ISelectBaseProps, Omit, 'noOptionsMessage' | 'loadingMessage'> {} -export type ISelect = ISelectProps | ISelectAsyncProps | ISelectCreatableProps; +export type ISelectAsyncCreatableProps = ISelectCreatableProps & ISelectAsyncProps; + +export type ISelect = ISelectProps | ISelectAsyncProps | ISelectCreatableProps | ISelectAsyncCreatableProps; export interface ISelectOption { label: string; @@ -102,6 +105,10 @@ export const Select: React.FunctionComponent = props => { styles: customStyles(), }; + if ('loadOptions' in props && 'onCreateOption' in props) { + return ; + } + if ('loadOptions' in props) { return ; } From 315d9b5e7833c8ceb3358018bd5c066775d3d7ff Mon Sep 17 00:00:00 2001 From: William Hilton Date: Wed, 30 Jan 2019 11:48:36 -0500 Subject: [PATCH 3/3] feat: add allowCreate --- src/Select.tsx | 8 +++++-- src/__stories__/Forms/Select.tsx | 38 +++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/Select.tsx b/src/Select.tsx index 126ff383..abb34eab 100644 --- a/src/Select.tsx +++ b/src/Select.tsx @@ -33,6 +33,8 @@ export interface ISelectBaseProps { blurOnSelect?: boolean; // blurInputOnSelect closeOnSelect?: boolean; closeOnScroll?: boolean; + + allowCreate?: boolean; } export interface ISelectProps @@ -79,6 +81,8 @@ export const Select: React.FunctionComponent = props => { loadingMessage = 'Loading...', noOptionsMessage = 'No Options', + allowCreate = false, + ...selectProps } = props; @@ -105,7 +109,7 @@ export const Select: React.FunctionComponent = props => { styles: customStyles(), }; - if ('loadOptions' in props && 'onCreateOption' in props) { + if ('loadOptions' in props && ('onCreateOption' in props || allowCreate)) { return ; } @@ -113,7 +117,7 @@ export const Select: React.FunctionComponent = props => { return ; } - if ('onCreateOption' in props) { + if ('onCreateOption' in props || allowCreate) { return ; } diff --git a/src/__stories__/Forms/Select.tsx b/src/__stories__/Forms/Select.tsx index bcfe3aaf..1d8a754c 100644 --- a/src/__stories__/Forms/Select.tsx +++ b/src/__stories__/Forms/Select.tsx @@ -1,7 +1,8 @@ import * as React from 'react'; +import { action } from '@storybook/addon-actions'; import { withKnobs } from '@storybook/addon-knobs'; -import { boolean, number, select, text } from '@storybook/addon-knobs/react'; +import { array, boolean, number, select, text } from '@storybook/addon-knobs/react'; import { storiesOf } from '@storybook/react'; import { Box } from '../../Box'; @@ -25,6 +26,7 @@ export const selectKnobs = (tabName = 'Select'): ISelect => ({ closeOnScroll: boolean('closeOnScroll', false), hideSelectedOptions: boolean('hideSelectedOptions', false), backspaceRemovesValue: boolean('backspaceRemovesValue', true), + onChange: action('onChange'), }); storiesOf('Forms:Select', module) @@ -67,4 +69,38 @@ storiesOf('Forms:Select', module) }} /> + )) + .add('creatable multi', () => ( + + { + return new Promise(resolve => { + setTimeout( + () => + resolve( + [0, 1, 2, 3].map(index => ({ + label: `${inputValue}${index}`, + value: `${index}`, + })) + ), + 250 + ); + }); + }} + /> + ));