Skip to content

Commit

Permalink
Merge pull request #53 from stoplightio/feat/SL-1297/creatable-select
Browse files Browse the repository at this point in the history
[SL-1297] creatable select
  • Loading branch information
P0lip authored Jan 30, 2019
2 parents 84b98be + 315d9b5 commit 44e0b4f
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 5 deletions.
28 changes: 24 additions & 4 deletions src/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ 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';

import { Omit } from '@stoplight/types';
Expand Down Expand Up @@ -31,17 +33,25 @@ export interface ISelectBaseProps {
blurOnSelect?: boolean; // blurInputOnSelect
closeOnSelect?: boolean;
closeOnScroll?: boolean;

allowCreate?: boolean;
}

export interface ISelectProps
extends ISelectBaseProps,
Omit<Omit<Props<ISelectOption>, 'noOptionsMessage'>, 'loadingMessage'> {} // pipe doesn't work for some reason
Omit<Props<ISelectOption>, 'noOptionsMessage' | 'loadingMessage'> {}

export interface ISelectAsyncProps
extends ISelectBaseProps,
Omit<Omit<AsyncProps<ISelectOption>, 'noOptionsMessage'>, 'loadingMessage'> {} // pipe doesn't work for some reason
Omit<AsyncProps<ISelectOption>, 'noOptionsMessage' | 'loadingMessage'> {}

export interface ISelectCreatableProps
extends ISelectBaseProps,
Omit<CreatableProps<ISelectOption>, 'noOptionsMessage' | 'loadingMessage'> {}

export type ISelect = ISelectProps | ISelectAsyncProps;
export type ISelectAsyncCreatableProps = ISelectCreatableProps & ISelectAsyncProps;

export type ISelect = ISelectProps | ISelectAsyncProps | ISelectCreatableProps | ISelectAsyncCreatableProps;

export interface ISelectOption {
label: string;
Expand Down Expand Up @@ -71,6 +81,8 @@ export const Select: React.FunctionComponent<ISelect> = props => {
loadingMessage = 'Loading...',
noOptionsMessage = 'No Options',

allowCreate = false,

...selectProps
} = props;

Expand All @@ -97,10 +109,18 @@ export const Select: React.FunctionComponent<ISelect> = props => {
styles: customStyles(),
};

if ('loadOptions' in props || 'defaultOptions' in props) {
if ('loadOptions' in props && ('onCreateOption' in props || allowCreate)) {
return <ReactAsyncCreatableSelect {...actualProps} />;
}

if ('loadOptions' in props) {
return <ReactAsyncSelect {...actualProps} />;
}

if ('onCreateOption' in props || allowCreate) {
return <ReactCreatableSelect {...actualProps} />;
}

return <ReactSelect {...actualProps} />;
};

Expand Down
38 changes: 37 additions & 1 deletion src/__stories__/Forms/Select.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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)
Expand Down Expand Up @@ -67,4 +69,38 @@ storiesOf('Forms:Select', module)
}}
/>
</Box>
))
.add('creatable multi', () => (
<Box width="40%">
<Select
{...selectKnobs()}
isMulti={true}
allowCreate={true}
defaultOptions={[{ label: 'option1', value: 2 }]}
options={array('options', ['1', '2', '3', '4']).map(x => ({ value: x, label: x }))}
/>
</Box>
))
.add('creatable async', () => (
<Box width="40%">
<Select
{...selectKnobs()}
allowCreate={true}
defaultOptions={[{ label: 'option1', value: 2 }]}
loadOptions={inputValue => {
return new Promise(resolve => {
setTimeout(
() =>
resolve(
[0, 1, 2, 3].map(index => ({
label: `${inputValue}${index}`,
value: `${index}`,
}))
),
250
);
});
}}
/>
</Box>
));

0 comments on commit 44e0b4f

Please sign in to comment.