Skip to content
This repository was archived by the owner on Jan 21, 2019. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions source/components/Select/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Use `Select.createOption` to create options to feed to the `options` prop.
Basic usage:
```js
<Select
onBlur={(val, label) => console.log('blur', val, label)}
onChange={(val, label) => console.log('change', val, label)}
options={[
Select.createOption(1, "label 1"),
Select.createOption(2, "label 2"),
Expand Down Expand Up @@ -38,6 +40,8 @@ Multi-select
```js
<Select
multi
onBlur={(val) => console.log('blur', val)}
onChange={(val) => console.log('change', val)}
options={[
Select.createOption(1, "label 1"),
Select.createOption(2, "label 2"),
Expand Down
10 changes: 0 additions & 10 deletions source/components/Select/SelectContainer.js

This file was deleted.

16 changes: 16 additions & 0 deletions source/components/Select/createSelectContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import { components } from 'react-select';

function createSelectContainer(classNamePrefix, customClassName) {
const className = [`${classNamePrefix}__wrapper`, customClassName]
.filter(Boolean)
.join(' ');

return props => (
<div className={className}>
<components.SelectContainer {...props} />
</div>
);
}

export default createSelectContainer;
25 changes: 14 additions & 11 deletions source/components/Select/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import ReactSelect from 'react-select';

import IndicatorsContainer from './IndicatorsContainer';
import SelectContainer from './SelectContainer';
import createSelectContainer from './createSelectContainer';
import { DefaultDropdownIndicator, SearchDropdownIndicator } from './DropdownIndicator';
import LoadingIndicator from './LoadingIndicator';

Expand Down Expand Up @@ -97,19 +97,25 @@ export default class Select extends React.Component {
super(props);

this.selectRef = React.createRef();
// react-select blur immediately follows change, but the updated value isn't available yet, so we're
// going to manually fire the onBlur handler on a change so that we can reliably pass the value
this.preventBlur = false;
}

onBlur = () => {
if (!this.props.onBlur || !this.selectRef.current) {
if (this.preventBlur || !this.selectRef.current) {
this.preventBlur = false;
return;
}

callWithValues(this.props.onBlur, this.selectRef.current.select.getCommonProps().getValue(), this.props.multi);
}

onChange = (values) => {
this.preventBlur = true;
const valuesAsArray = this.props.multi ? values : [values];
callWithValues(this.props.onChange, valuesAsArray, this.props.multi);
callWithValues(this.props.onBlur, valuesAsArray, this.props.multi);
}

onFocus = () => {
Expand All @@ -135,12 +141,6 @@ export default class Select extends React.Component {
}
}

getRootClassName() {
return ['fandom-select', this.props.className]
.filter(Boolean)
.join(' ');
}

getValueFromProps() {
const { value, options } = this.props;

Expand Down Expand Up @@ -169,13 +169,16 @@ export default class Select extends React.Component {
}

render() {
const className = 'fandom-select';

return (
<ReactSelect
ref={this.selectRef}
openMenuOnFocus
autoFocus={this.props.autoFocus}
blurInputOnSelect
className={this.getRootClassName()}
classNamePrefix="fandom-select"
className={className}
classNamePrefix={className}
controlShouldRenderValue={this.props.multi ? this.props.multiValueRender : true}
isDisabled={this.props.disabled || this.props.loading}
isLoading={this.props.loading}
Expand All @@ -195,7 +198,7 @@ export default class Select extends React.Component {
DropdownIndicator: this.props.searchable ? SearchDropdownIndicator : DefaultDropdownIndicator,
LoadingIndicator,
IndicatorsContainer,
SelectContainer,
SelectContainer: createSelectContainer(className, this.props.className),
}}
/>
);
Expand Down
5 changes: 5 additions & 0 deletions source/components/Select/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,8 @@ test('onTextInputChange tests', () => {
input.props.onChange({ currentTarget: { value: '😀' } });
expect(onTextInputChangeSpy.withArgs('😀').calledOnce).toBe(true);
});

test('custom className is at root level', () => {
const wrapper = mount(<Select className="custom-select" />);
expect(wrapper.find('.fandom-select__wrapper.custom-select')).toHaveLength(1);
});
2 changes: 2 additions & 0 deletions source/components/Select/styles.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
@import "~design-system/dist/scss/wds-variables/index.scss";

.fandom-select__wrapper {
background-color: $wds-color-white;
border: 1px solid $wds-color-light-gray;
border-radius: 4px;
padding: 5px 10px;

// it's odd to have the separate selector here but it's needed for specificity to avoid !important
.fandom-select {
&__control {
background-color: inherit;
border: none;
border-radius: 0;
box-shadow: none;
Expand Down