Skip to content

Commit

Permalink
Merge pull request #2 from deskpro/update-react-select
Browse files Browse the repository at this point in the history
Update react select and add async on drop downs
  • Loading branch information
jducro committed Jul 27, 2018
2 parents d1576e5 + ea45c12 commit f4817a6
Show file tree
Hide file tree
Showing 19 changed files with 4,661 additions and 4,321 deletions.
7,813 changes: 3,914 additions & 3,899 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@
"homepage": "https://deskpro.github.io/portal-components",
"dependencies": {
"@deskpro/js-utils": "^1.0.4",
"@deskpro/react-datepicker-hijri": "^1.4.2-beta.1",
"@deskpro/react-datepicker-hijri": "^1.5.0",
"@storybook/addon-knobs": "^3.4.3",
"classnames": "^2.2.5",
"emotion": "^9.2.6",
"formik": "^0.11.11",
"immutable": "^3.8.2",
"lodash": "^4.17.10",
"moment": "^2.22.1",
"moment-hijri": "^2.0.1",
"raw-loader": "^0.5.1",
"react-dropzone": "^4.2.9",
"react-select": "^1.2.1",
"react-select": "^2.0.0",
"react-svg-inline": "^2.1.0",
"react-textarea-autosize": "^6.1.0",
"yup": "^0.24.1"
Expand Down
76 changes: 65 additions & 11 deletions src/Components/Choices/DropDown.jsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,80 @@
import React from 'react';
import PropTypes from 'prop-types';
import { getIn } from 'formik';
import ReactSelect from 'react-select';

import ReactSelect, { components } from 'react-select';
import AsyncSelect from 'react-select/lib/Async';
import classNames from 'classnames';
import Field from '../Field';


const SelectContainer = ({ children, ...props }) => (
<components.SelectContainer {...props} className={classNames({ 'react-select__is-focused': props.isFocused })}>
{children}
</components.SelectContainer>
);

SelectContainer.propTypes = components.SelectContainer.propTypes;

class DropDown extends Field {
constructor(props) {
super(props);
this.state = {
value: null
};
}

handleChange = (form, value) => {
const { name, handleChange } = this.props;
this.setState({
value
});
const newValue = value ? value.value : null;
form.setFieldValue(name, newValue);
handleChange(newValue);
};

loadOptions = (form, inputValue) => {
const { dataSource, name } = this.props;
return dataSource.getOptions(inputValue).then((options) => {
const value = options.find(o => o.value === getIn(form.values, name));
this.setState({
value
});
return options;
});
};

renderField = (form) => {
const { name, options, ...props } = this.props;
const {
name, dataSource, isClearable, ...props
} = this.props;
if (Array.isArray(dataSource.getOptions)) {
return (
<ReactSelect
value={dataSource.getOptions.find(o => o.value === getIn(form.values, name))}
name={name}
isClearable={isClearable}
components={{ SelectContainer }}
onChange={value => this.handleChange(form, value)}
onBlur={() => form.setFieldTouched(name, true)}
options={dataSource.getOptions}
classNamePrefix="react-select"
{...props}
/>
);
}
return (
<ReactSelect
value={getIn(form.values, name)}
<AsyncSelect
value={this.state.value}
name={name}
isClearable={isClearable}
onChange={value => this.handleChange(form, value)}
onBlur={() => form.setFieldTouched(name, true)}
options={options}
defaultOptions
cacheOptions
components={{ SelectContainer }}
loadOptions={inputValue => this.loadOptions(form, inputValue)}
classNamePrefix="react-select"
{...props}
/>
);
Expand All @@ -30,15 +83,16 @@ class DropDown extends Field {

DropDown.propTypes = {
...Field.propTypes,
options: PropTypes.arrayOf(PropTypes.shape({
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
value: PropTypes.any.isRequired
})),
dataSource: PropTypes.shape({
getOptions: PropTypes.oneOfType([PropTypes.func, PropTypes.array]).isRequired,
}).isRequired,
handleChange: PropTypes.func,
isClearable: PropTypes.bool,
};

DropDown.defaultProps = {
handleChange() {}
handleChange() {},
isClearable: true,
};

export default DropDown;
127 changes: 99 additions & 28 deletions src/Components/Choices/MultipleDropDown.jsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,126 @@
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { css } from 'emotion';
import { getIn } from 'formik';
import ReactSelect from 'react-select';

import ReactSelect, { components } from 'react-select';
import AsyncSelect from 'react-select/lib/Async';
import Field from '../Field';

class MultipleDropDown extends Field {
handleChange = (form, value) => {
const { name, handleChange } = this.props;
const newValue = value ? value.map(e => e.value) : null;
form.setFieldValue(name, newValue);
handleChange(newValue);
};
const SelectContainer = ({ children, ...props }) => (
<components.SelectContainer {...props} className={classNames({ 'react-select__is-focused': props.isFocused })}>
{children}
</components.SelectContainer>
);

SelectContainer.propTypes = components.SelectContainer.propTypes;

renderCheckbox = (checked, label) => (
const Option = (props) => {
const {
className,
cx,
getStyles,
label,
isDisabled,
isFocused,
isSelected,
innerRef,
innerProps
} = props;
return (
<div
className={classNames('dp-pc_checkbox')}
ref={innerRef}
className={cx(
css(getStyles('option', props)),
{
option: true,
'option--is-disabled': isDisabled,
'option--is-focused': isFocused,
'option--is-selected': isSelected,
},
'dp-pc_checkbox',
className
)}
{...innerProps}
>
<span
className="dp-pc_checkbox__checkbox"
>
<input type="checkbox" checked={checked} readOnly />
<input type="checkbox" checked={isSelected} readOnly />
<i />
<span className="dp-pc_checkbox__label">
{label}
</span>
</span>
</div>
);
};

Option.propTypes = components.Option.propTypes;

renderOption = (option, form) => {
const { name } = this.props;
const checked = form.values[name].includes(option.value);
return this.renderCheckbox(checked, option.label);
class MultipleDropDown extends Field {
constructor(props) {
super(props);
this.state = {
value: null
};
}

handleChange = (form, value) => {
const { name, handleChange } = this.props;
this.setState({
value
});
const newValue = value ? value.map(e => e.value) : null;
form.setFieldValue(name, newValue);
handleChange(newValue);
};

loadOptions = (form, inputValue) => {
const { dataSource, name } = this.props;
return dataSource.getOptions(inputValue).then((options) => {
const value = options.find(o => o.value === getIn(form.values, name));
this.setState({
value
});
return options;
});
};

renderField = (form) => {
const { name, options, ...props } = this.props;
const { name, dataSource, ...props } = this.props;
if (Array.isArray(dataSource.getOptions)) {
return (
<ReactSelect
value={dataSource.getOptions.filter(o => getIn(form.values, name).includes(o.value))}
name={name}
isClearable={false}
onChange={value => this.handleChange(form, value)}
onBlur={() => form.setFieldTouched(name, true)}
options={dataSource.getOptions}
hideSelectedOptions={false}
components={{ Option, SelectContainer }}
classNamePrefix="react-select"
isMulti
{...props}
/>
);
}

return (
<ReactSelect
value={getIn(form.values, name)}
<AsyncSelect
value={this.state.value}
name={name}
clearable={false}
isClearable={false}
onChange={value => this.handleChange(form, value)}
onBlur={() => form.setFieldTouched(name, true)}
options={options}
removeSelected={false}
optionRenderer={option => this.renderOption(option, form)}
multi
hideSelectedOptions={false}
components={{ Option, SelectContainer }}
defaultOptions
cacheOptions
loadOptions={inputValue => this.loadOptions(form, inputValue)}
classNamePrefix="react-select"
isMulti
{...props}
/>
);
Expand All @@ -57,10 +129,9 @@ class MultipleDropDown extends Field {

MultipleDropDown.propTypes = {
...Field.propTypes,
options: PropTypes.arrayOf(PropTypes.shape({
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
value: PropTypes.any.isRequired
})),
dataSource: PropTypes.shape({
getOptions: PropTypes.oneOfType([PropTypes.func, PropTypes.array]).isRequired,
}).isRequired,
handleChange: PropTypes.func,
};

Expand Down
2 changes: 1 addition & 1 deletion src/Components/TicketDepartment.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class TicketDepartment extends React.Component {
<DropDown
name="department"
label="Department"
options={departments}
dataSource={{ getOptions: departments }}
handleChange={handleChange}
clearable={false}
/>
Expand Down
6 changes: 4 additions & 2 deletions src/Components/TicketField.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ class TicketField extends React.Component {
break;
case 'choice':
Component = DropDown;
props.options = field.getIn(['data', 'choices'], [])
props.dataSource = {};
props.dataSource.getOptions = field.getIn(['data', 'choices'], [])
.toArray().map(option => ({ value: option.get('id'), label: option.get('title') }));
break;
case 'radio':
Expand All @@ -58,7 +59,8 @@ class TicketField extends React.Component {
break;
case 'multichoice':
Component = MultipleDropDown;
props.options = field.getIn(['data', 'choices'], [])
props.dataSource = {};
props.dataSource.getOptions = field.getIn(['data', 'choices'], [])
.toArray().map(option => ({ value: option.get('id'), label: option.get('title') }));
break;
case 'text':
Expand Down
Loading

0 comments on commit f4817a6

Please sign in to comment.