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';
/* eslint-disable react/prop-types */
const SelectWidget: Widget = ({ options, onChange, value, ...rest }) => (
<Select
options={options.enumOptions}
onChange={(option: { value: string }) => {
onChange(option.value);
const SelectWidget: Widget = ({
options,
onChange,
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
)}
{...rest}

View File

@ -22,7 +22,10 @@ export default {
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
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 ReactSelect, { Props as ReactSelectProps } from 'react-select';
import ReactSelect, {
NamedProps as ReactSelectProps,
OptionTypeBase,
} from 'react-select';
import createThemedComponent from '../utils/createThemedComponent';
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;
}
/**
* 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() {
return (
<ReactSelect
@ -45,7 +54,7 @@ export class Select extends (PureComponent || Component)<SelectProps> {
},
})}
styles={{
container: (base, props) => ({
container: (base) => ({
...base,
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={() => {
// noop
}}
value="one"
menuMaxHeight={20}
clearable
disabled
value={options.filter((option) => option.value === 'one')}
maxMenuHeight={20}
isClearable
isDisabled
isLoading
multi
searchable={false}
openOuterUp
isMulti
isSearchable={false}
menuPlacement="top"
/>
);
expect(renderToJson(wrapper)).toMatchSnapshot();

View File

@ -70,7 +70,7 @@ exports[`Select renders correctly 1`] = `
exports[`Select renders with props 1`] = `
<div
class=" css-butsr4-container"
class=" css-ie73ge-container"
>
<div
class=" css-vmgz7k-control"
@ -79,34 +79,39 @@ exports[`Select renders with props 1`] = `
class=" css-be27w2-ValueContainer"
>
<div
class=" css-1osw1h9-placeholder"
>
Select...
</div>
<div
class="css-187dxxn-Input"
class="css-syqu13-multiValue"
>
<div
class=""
style="display:inline-block"
class="css-1lxn4sj"
>
<input
aria-autocomplete="list"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
id="react-select-3-input"
spellcheck="false"
style="box-sizing:content-box;width:1px;label:input;background:0;border:0;font-size:inherit;opacity:1;outline:0;padding:0;color:inherit"
tabindex="0"
type="text"
value=""
/>
<div
style="position:absolute;top:0;left:0;visibility:hidden;height:0;overflow:scroll;white-space:pre"
/>
One
</div>
<div
class="css-19nhond"
>
<svg
aria-hidden="true"
class="css-6q0nyr-Svg"
focusable="false"
height="14"
viewBox="0 0 20 20"
width="14"
>
<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>
<input
aria-autocomplete="list"
class="css-62g3xt-dummyInput"
disabled=""
id="react-select-3-input"
readonly=""
tabindex="0"
value=""
/>
</div>
<div
class=" css-1hb7zxy-IndicatorsContainer"

View File

@ -23,9 +23,10 @@ class InstanceSelector extends Component<Props> {
return (
<Select
options={this.select}
// TODO Where's the type-checking?
onChange={this.props.onSelect}
value={this.props.selected || ''}
onChange={(option) => this.props.onSelect(option!.value)}
value={this.select.find(
(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 }[] = [
{ value: 'default', label: 'Custom action' },
];
let options: {
value: 'default' | 'actions-help' | number;
label: string;
}[] = [{ value: 'default', label: 'Custom action' }];
if (actionCreators && actionCreators.length > 0) {
options = options.concat(
actionCreators.map(({ name, args }, i) => ({
@ -204,9 +205,12 @@ class Dispatcher extends Component<Props, State> {
{actionElement}
<Toolbar>
<Select
openOuterUp
onChange={this.selectActionCreator}
value={this.state.selected || 'default'}
menuPlacement="top"
onChange={(option) => this.selectActionCreator(option!.value)}
value={
options.find((option) => option.value === this.state.selected) ||
options.find((option) => option.value === 'default')
}
options={options}
/>
<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 })
.testGenerator || {};
handleSelectTemplate = (selectedTemplate: Template) => {
handleSelectTemplate = (selectedTemplate: Template | null | undefined) => {
const { templates = getDefaultTemplates() } = this.getPersistedState();
this.updateState({ selected: templates.indexOf(selectedTemplate) });
this.updateState({ selected: templates.indexOf(selectedTemplate!) });
};
handleCloseTip = () => {
@ -133,9 +133,9 @@ export default class TestTab<S, A extends Action<unknown>> extends Component<
<div style={{ flexGrow: 1, zIndex: 100 }}>
<Select
options={templates}
getOptionValue={(template: Template) => template.name}
getOptionLabel={(template: Template) => template.name}
value={templates.filter((template) => template.name === name)}
getOptionValue={(template: Template) => template.name!}
getOptionLabel={(template: Template) => template.name!}
value={templates.find((template) => template.name === name)}
onChange={this.handleSelectTemplate}
/>
</div>