fix(*): fix Select types and usages (#724)

* stash

* more

* stash

* Revert port change

* Fix test

* Fix

* Update snapshot
This commit is contained in:
Nathan Bierema 2021-06-07 00:54:05 -04:00 committed by GitHub
parent e7477833f0
commit 07e409de6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 105 additions and 58 deletions

View File

@ -4,13 +4,22 @@ import Select from '../Select';
import Slider from '../Slider'; import Slider from '../Slider';
/* eslint-disable react/prop-types */ /* eslint-disable react/prop-types */
const SelectWidget: Widget = ({ options, onChange, value, ...rest }) => ( const SelectWidget: Widget = ({
<Select options,
options={options.enumOptions} onChange,
onChange={(option: { value: string }) => { value,
onChange(option.value); onBlur,
defaultValue,
tabIndex,
onFocus,
...rest
}) => (
<Select<{ label: string; value: string }>
options={options.enumOptions as { label: string; value: string }[]}
onChange={(option) => {
onChange(option?.value);
}} }}
value={(options.enumOptions as { value: string }[]).find( value={(options.enumOptions as { label: string; value: string }[]).find(
(option) => option.value === value (option) => option.value === value
)} )}
{...rest} {...rest}

View File

@ -22,7 +22,10 @@ export default {
component: Select, component: Select,
}; };
type TemplateArgs = Omit<SelectProps, 'value'> & { value: string }; type TemplateArgs = Omit<
SelectProps<{ value: string; label: string }, boolean>,
'value'
> & { value: string };
// eslint-disable-next-line react/prop-types // eslint-disable-next-line react/prop-types
const Template: Story<TemplateArgs> = ({ value, ...args }) => ( const Template: Story<TemplateArgs> = ({ value, ...args }) => (

View File

@ -1,17 +1,26 @@
import React, { PureComponent, Component } from 'react'; import React, { PureComponent, Component, ReactElement } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import ReactSelect, { Props as ReactSelectProps } from 'react-select'; import ReactSelect, {
NamedProps as ReactSelectProps,
OptionTypeBase,
} from 'react-select';
import createThemedComponent from '../utils/createThemedComponent'; import createThemedComponent from '../utils/createThemedComponent';
import { Theme } from '../themes/default'; import { Theme } from '../themes/default';
export interface SelectProps extends Omit<ReactSelectProps, 'theme'> { export interface SelectProps<
Option extends OptionTypeBase = OptionTypeBase,
IsMulti extends boolean = false
> extends Omit<ReactSelectProps<Option, IsMulti>, 'theme'> {
theme: Theme; theme: Theme;
} }
/** /**
* Wrapper around [React Select](https://github.com/JedWatson/react-select). * Wrapper around [React Select](https://github.com/JedWatson/react-select).
*/ */
export class Select extends (PureComponent || Component)<SelectProps> { export class Select<
Option extends OptionTypeBase = OptionTypeBase,
IsMulti extends boolean = false
> extends (PureComponent || Component)<SelectProps<Option, IsMulti>> {
render() { render() {
return ( return (
<ReactSelect <ReactSelect
@ -45,7 +54,7 @@ export class Select extends (PureComponent || Component)<SelectProps> {
}, },
})} })}
styles={{ styles={{
container: (base, props) => ({ container: (base) => ({
...base, ...base,
flexGrow: 1, flexGrow: 1,
}), }),
@ -72,4 +81,20 @@ export class Select extends (PureComponent || Component)<SelectProps> {
}; };
} }
export default createThemedComponent(Select); export interface ExternalSelectProps<
Option extends OptionTypeBase = OptionTypeBase,
IsMulti extends boolean = false
> extends Omit<ReactSelectProps<Option, IsMulti>, 'theme'> {
theme?: Theme;
}
type SelectComponent = <
Option extends OptionTypeBase = OptionTypeBase,
IsMulti extends boolean = false
>(
props: ExternalSelectProps<Option, IsMulti>
) => ReactElement;
export default createThemedComponent(Select) as SelectComponent & {
theme?: Theme;
};

View File

@ -24,14 +24,14 @@ describe('Select', function () {
onChange={() => { onChange={() => {
// noop // noop
}} }}
value="one" value={options.filter((option) => option.value === 'one')}
menuMaxHeight={20} maxMenuHeight={20}
clearable isClearable
disabled isDisabled
isLoading isLoading
multi isMulti
searchable={false} isSearchable={false}
openOuterUp menuPlacement="top"
/> />
); );
expect(renderToJson(wrapper)).toMatchSnapshot(); expect(renderToJson(wrapper)).toMatchSnapshot();

View File

@ -70,7 +70,7 @@ exports[`Select renders correctly 1`] = `
exports[`Select renders with props 1`] = ` exports[`Select renders with props 1`] = `
<div <div
class=" css-butsr4-container" class=" css-ie73ge-container"
> >
<div <div
class=" css-vmgz7k-control" class=" css-vmgz7k-control"
@ -79,34 +79,39 @@ exports[`Select renders with props 1`] = `
class=" css-be27w2-ValueContainer" class=" css-be27w2-ValueContainer"
> >
<div <div
class=" css-1osw1h9-placeholder" class="css-syqu13-multiValue"
>
Select...
</div>
<div
class="css-187dxxn-Input"
> >
<div <div
class="" class="css-1lxn4sj"
style="display:inline-block"
> >
<input One
aria-autocomplete="list" </div>
autocapitalize="none" <div
autocomplete="off" class="css-19nhond"
autocorrect="off" >
id="react-select-3-input" <svg
spellcheck="false" aria-hidden="true"
style="box-sizing:content-box;width:1px;label:input;background:0;border:0;font-size:inherit;opacity:1;outline:0;padding:0;color:inherit" class="css-6q0nyr-Svg"
tabindex="0" focusable="false"
type="text" height="14"
value="" viewBox="0 0 20 20"
/> width="14"
<div >
style="position:absolute;top:0;left:0;visibility:hidden;height:0;overflow:scroll;white-space:pre" <path
/> d="M14.348 14.849c-0.469 0.469-1.229 0.469-1.697 0l-2.651-3.030-2.651 3.029c-0.469 0.469-1.229 0.469-1.697 0-0.469-0.469-0.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-0.469-0.469-0.469-1.228 0-1.697s1.228-0.469 1.697 0l2.652 3.031 2.651-3.031c0.469-0.469 1.228-0.469 1.697 0s0.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c0.469 0.469 0.469 1.229 0 1.698z"
/>
</svg>
</div> </div>
</div> </div>
<input
aria-autocomplete="list"
class="css-62g3xt-dummyInput"
disabled=""
id="react-select-3-input"
readonly=""
tabindex="0"
value=""
/>
</div> </div>
<div <div
class=" css-1hb7zxy-IndicatorsContainer" class=" css-1hb7zxy-IndicatorsContainer"

View File

@ -23,9 +23,10 @@ class InstanceSelector extends Component<Props> {
return ( return (
<Select <Select
options={this.select} options={this.select}
// TODO Where's the type-checking? onChange={(option) => this.props.onSelect(option!.value)}
onChange={this.props.onSelect} value={this.select.find(
value={this.props.selected || ''} (option) => option.value === this.props.selected
)}
/> />
); );
} }

View File

@ -182,9 +182,10 @@ class Dispatcher extends Component<Props, State> {
); );
} }
let options: { value: string | number; label: string }[] = [ let options: {
{ value: 'default', label: 'Custom action' }, value: 'default' | 'actions-help' | number;
]; label: string;
}[] = [{ value: 'default', label: 'Custom action' }];
if (actionCreators && actionCreators.length > 0) { if (actionCreators && actionCreators.length > 0) {
options = options.concat( options = options.concat(
actionCreators.map(({ name, args }, i) => ({ actionCreators.map(({ name, args }, i) => ({
@ -204,9 +205,12 @@ class Dispatcher extends Component<Props, State> {
{actionElement} {actionElement}
<Toolbar> <Toolbar>
<Select <Select
openOuterUp menuPlacement="top"
onChange={this.selectActionCreator} onChange={(option) => this.selectActionCreator(option!.value)}
value={this.state.selected || 'default'} value={
options.find((option) => option.value === this.state.selected) ||
options.find((option) => option.value === 'default')
}
options={options} options={options}
/> />
<Button onClick={this.dispatchAction} primary={this.state.changed}> <Button onClick={this.dispatchAction} primary={this.state.changed}>

View File

@ -52,9 +52,9 @@ export default class TestTab<S, A extends Action<unknown>> extends Component<
(this.props.monitorState as { testGenerator?: TestGeneratorMonitorState }) (this.props.monitorState as { testGenerator?: TestGeneratorMonitorState })
.testGenerator || {}; .testGenerator || {};
handleSelectTemplate = (selectedTemplate: Template) => { handleSelectTemplate = (selectedTemplate: Template | null | undefined) => {
const { templates = getDefaultTemplates() } = this.getPersistedState(); const { templates = getDefaultTemplates() } = this.getPersistedState();
this.updateState({ selected: templates.indexOf(selectedTemplate) }); this.updateState({ selected: templates.indexOf(selectedTemplate!) });
}; };
handleCloseTip = () => { handleCloseTip = () => {
@ -133,9 +133,9 @@ export default class TestTab<S, A extends Action<unknown>> extends Component<
<div style={{ flexGrow: 1, zIndex: 100 }}> <div style={{ flexGrow: 1, zIndex: 100 }}>
<Select <Select
options={templates} options={templates}
getOptionValue={(template: Template) => template.name} getOptionValue={(template: Template) => template.name!}
getOptionLabel={(template: Template) => template.name} getOptionLabel={(template: Template) => template.name!}
value={templates.filter((template) => template.name === name)} value={templates.find((template) => template.name === name)}
onChange={this.handleSelectTemplate} onChange={this.handleSelectTemplate}
/> />
</div> </div>