Skip to content

Commit

Permalink
add duplicate support for multi select
Browse files Browse the repository at this point in the history
  • Loading branch information
Kim Yu Ng committed Sep 30, 2019
1 parent 677dd4f commit c92893e
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 37 deletions.
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8.4.0
8.16.1
2 changes: 2 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# React-Select
## v1.4.0 / 2019-09-27
* support duplicate for multiselect by passing `duplicate` prop to Select component

## v1.3.0 / 2018-06-23
* [#2777](https://github.com/JedWatson/react-select/pull/2777) pass entire event to `shouldKeyDownEventCreateNewOption`
Expand Down
67 changes: 58 additions & 9 deletions dist/react-select.es.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,34 @@ var possibleConstructorReturn = function (self, call) {
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};



















var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];

return arr2;
} else {
return Array.from(arr);
}
};

var Option = function (_React$Component) {
inherits(Option, _React$Component);

Expand Down Expand Up @@ -1285,13 +1313,17 @@ var Select$1 = function (_React$Component) {
inputValue: this.handleInputValueChange(updatedValue),
isOpen: !this.props.closeOnSelect
}, function () {
var valueArray = _this3.getValueArray(_this3.props.value);
if (valueArray.some(function (i) {
return i[_this3.props.valueKey] === value[_this3.props.valueKey];
})) {
_this3.removeValue(value);
} else {
if (_this3.props.duplicate) {
_this3.addValue(value);
} else {
var valueArray = _this3.getValueArray(_this3.props.value);
if (valueArray.some(function (i) {
return i[_this3.props.valueKey] === value[_this3.props.valueKey];
})) {
_this3.removeValue(value);
} else {
_this3.addValue(value);
}
}
});
} else {
Expand Down Expand Up @@ -1338,9 +1370,24 @@ var Select$1 = function (_React$Component) {
var _this4 = this;

var valueArray = this.getValueArray(this.props.value);
this.setValue(valueArray.filter(function (i) {
return i[_this4.props.valueKey] !== value[_this4.props.valueKey];
}));

if (this.props.duplicate) {
valueArray = [].concat(toConsumableArray(valueArray));
valueArray.reverse();
var index = valueArray.findIndex(function (i) {
return i[_this4.props.valueKey] === value[_this4.props.valueKey];
});
if (index > -1) {
valueArray.splice(index, 1);
}
valueArray.reverse();
this.setValue(valueArray);
} else {
this.setValue(valueArray.filter(function (i) {
return i[_this4.props.valueKey] !== value[_this4.props.valueKey];
}));
}

this.focus();
}
}, {
Expand Down Expand Up @@ -1922,6 +1969,7 @@ Select$1.propTypes = {
deleteRemoves: PropTypes.bool, // whether delete removes an item if there is no text input
delimiter: PropTypes.string, // delimiter to use to join multiple values for the hidden field value
disabled: PropTypes.bool, // whether the Select is disabled or not
duplicate: PropTypes.bool, // whether the Select allows the same option to be selected multiple times
escapeClearsValue: PropTypes.bool, // whether escape clears the value when the menu is closed
filterOption: PropTypes.func, // method to filter a single option (option, filterString)
filterOptions: PropTypes.any, // boolean to enable default filtering or function to filter the options array ([options], filterString, [values])
Expand Down Expand Up @@ -1994,6 +2042,7 @@ Select$1.defaultProps = {
deleteRemoves: true,
delimiter: ',',
disabled: false,
duplicate: false,
escapeClearsValue: true,
filterOptions: filterOptions,
ignoreAccents: true,
Expand Down
67 changes: 58 additions & 9 deletions dist/react-select.js
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,34 @@ var possibleConstructorReturn = function (self, call) {
return call && (typeof call === "object" || typeof call === "function") ? call : self;
};



















var toConsumableArray = function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];

return arr2;
} else {
return Array.from(arr);
}
};

var Option = function (_React$Component) {
inherits(Option, _React$Component);

Expand Down Expand Up @@ -1290,13 +1318,17 @@ var Select$1 = function (_React$Component) {
inputValue: this.handleInputValueChange(updatedValue),
isOpen: !this.props.closeOnSelect
}, function () {
var valueArray = _this3.getValueArray(_this3.props.value);
if (valueArray.some(function (i) {
return i[_this3.props.valueKey] === value[_this3.props.valueKey];
})) {
_this3.removeValue(value);
} else {
if (_this3.props.duplicate) {
_this3.addValue(value);
} else {
var valueArray = _this3.getValueArray(_this3.props.value);
if (valueArray.some(function (i) {
return i[_this3.props.valueKey] === value[_this3.props.valueKey];
})) {
_this3.removeValue(value);
} else {
_this3.addValue(value);
}
}
});
} else {
Expand Down Expand Up @@ -1343,9 +1375,24 @@ var Select$1 = function (_React$Component) {
var _this4 = this;

var valueArray = this.getValueArray(this.props.value);
this.setValue(valueArray.filter(function (i) {
return i[_this4.props.valueKey] !== value[_this4.props.valueKey];
}));

if (this.props.duplicate) {
valueArray = [].concat(toConsumableArray(valueArray));
valueArray.reverse();
var index = valueArray.findIndex(function (i) {
return i[_this4.props.valueKey] === value[_this4.props.valueKey];
});
if (index > -1) {
valueArray.splice(index, 1);
}
valueArray.reverse();
this.setValue(valueArray);
} else {
this.setValue(valueArray.filter(function (i) {
return i[_this4.props.valueKey] !== value[_this4.props.valueKey];
}));
}

this.focus();
}
}, {
Expand Down Expand Up @@ -1927,6 +1974,7 @@ Select$1.propTypes = {
deleteRemoves: PropTypes.bool, // whether delete removes an item if there is no text input
delimiter: PropTypes.string, // delimiter to use to join multiple values for the hidden field value
disabled: PropTypes.bool, // whether the Select is disabled or not
duplicate: PropTypes.bool, // whether the Select allows the same option to be selected multiple times
escapeClearsValue: PropTypes.bool, // whether escape clears the value when the menu is closed
filterOption: PropTypes.func, // method to filter a single option (option, filterString)
filterOptions: PropTypes.any, // boolean to enable default filtering or function to filter the options array ([options], filterString, [values])
Expand Down Expand Up @@ -1999,6 +2047,7 @@ Select$1.defaultProps = {
deleteRemoves: true,
delimiter: ',',
disabled: false,
duplicate: false,
escapeClearsValue: true,
filterOptions: filterOptions,
ignoreAccents: true,
Expand Down
2 changes: 1 addition & 1 deletion dist/react-select.min.js

Large diffs are not rendered by default.

41 changes: 32 additions & 9 deletions lib/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in ob

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
Expand Down Expand Up @@ -713,13 +715,17 @@ var Select = function (_React$Component) {
inputValue: this.handleInputValueChange(updatedValue),
isOpen: !this.props.closeOnSelect
}, function () {
var valueArray = _this3.getValueArray(_this3.props.value);
if (valueArray.some(function (i) {
return i[_this3.props.valueKey] === value[_this3.props.valueKey];
})) {
_this3.removeValue(value);
} else {
if (_this3.props.duplicate) {
_this3.addValue(value);
} else {
var valueArray = _this3.getValueArray(_this3.props.value);
if (valueArray.some(function (i) {
return i[_this3.props.valueKey] === value[_this3.props.valueKey];
})) {
_this3.removeValue(value);
} else {
_this3.addValue(value);
}
}
});
} else {
Expand Down Expand Up @@ -766,9 +772,24 @@ var Select = function (_React$Component) {
var _this4 = this;

var valueArray = this.getValueArray(this.props.value);
this.setValue(valueArray.filter(function (i) {
return i[_this4.props.valueKey] !== value[_this4.props.valueKey];
}));

if (this.props.duplicate) {
valueArray = [].concat(_toConsumableArray(valueArray));
valueArray.reverse();
var index = valueArray.findIndex(function (i) {
return i[_this4.props.valueKey] === value[_this4.props.valueKey];
});
if (index > -1) {
valueArray.splice(index, 1);
}
valueArray.reverse();
this.setValue(valueArray);
} else {
this.setValue(valueArray.filter(function (i) {
return i[_this4.props.valueKey] !== value[_this4.props.valueKey];
}));
}

this.focus();
}
}, {
Expand Down Expand Up @@ -1350,6 +1371,7 @@ Select.propTypes = {
deleteRemoves: _propTypes2.default.bool, // whether delete removes an item if there is no text input
delimiter: _propTypes2.default.string, // delimiter to use to join multiple values for the hidden field value
disabled: _propTypes2.default.bool, // whether the Select is disabled or not
duplicate: _propTypes2.default.bool, // whether the Select allows the same option to be selected multiple times
escapeClearsValue: _propTypes2.default.bool, // whether escape clears the value when the menu is closed
filterOption: _propTypes2.default.func, // method to filter a single option (option, filterString)
filterOptions: _propTypes2.default.any, // boolean to enable default filtering or function to filter the options array ([options], filterString, [values])
Expand Down Expand Up @@ -1422,6 +1444,7 @@ Select.defaultProps = {
deleteRemoves: true,
delimiter: ',',
disabled: false,
duplicate: false,
escapeClearsValue: true,
filterOptions: _defaultFilterOptions2.default,
ignoreAccents: true,
Expand Down
17 changes: 14 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
{
"name": "react-select",
"version": "1.3.0",
"version": "1.4.0",
"description": "A Select control built with and for ReactJS",
"main": "lib/index.js",
"jsnext:main": "dist/react-select.es.js",
"module": "dist/react-select.es.js",
"style": "dist/react-select.min.css",
"author": "Jed Watson",
"contributors": [
{
"name": "Kim Yu Ng",
"email": "[email protected]"
}
],
"license": "MIT",
"repository": {
"type": "git",
Expand Down Expand Up @@ -58,7 +64,7 @@
"react-highlight-words": "^0.8.1",
"react-test-renderer": "^15.6.1",
"react-virtualized": "^9.9.0",
"react-virtualized-select": "^3.1.0",
"react-virtualized-select": "^3.1.3",
"rollup": "^0.49.2",
"rollup-plugin-babel": "^3.0.2",
"rollup-plugin-commonjs": "^8.2.0",
Expand Down Expand Up @@ -88,7 +94,12 @@
"test": "cross-env NODE_ENV=test mocha --compilers js:babel-core/register",
"precommit": "lint-staged && yarn run test"
},
"files": ["dist", "less", "lib", "scss"],
"files": [
"dist",
"less",
"lib",
"scss"
],
"keywords": [
"combobox",
"form",
Expand Down
29 changes: 24 additions & 5 deletions src/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -619,11 +619,15 @@ class Select extends React.Component {
inputValue: this.handleInputValueChange(updatedValue),
isOpen: !this.props.closeOnSelect,
}, () => {
const valueArray = this.getValueArray(this.props.value);
if (valueArray.some(i => i[this.props.valueKey] === value[this.props.valueKey])) {
this.removeValue(value);
} else {
if (this.props.duplicate) {
this.addValue(value);
} else {
const valueArray = this.getValueArray(this.props.value);
if (valueArray.some(i => i[this.props.valueKey] === value[this.props.valueKey])) {
this.removeValue(value);
} else {
this.addValue(value);
}
}
});
} else {
Expand Down Expand Up @@ -661,7 +665,20 @@ class Select extends React.Component {

removeValue (value) {
let valueArray = this.getValueArray(this.props.value);
this.setValue(valueArray.filter(i => i[this.props.valueKey] !== value[this.props.valueKey]));

if (this.props.duplicate) {
valueArray = [...valueArray];
valueArray.reverse();
const index = valueArray.findIndex((i) => (i[this.props.valueKey] === value[this.props.valueKey]));
if (index > -1) {
valueArray.splice(index, 1);
}
valueArray.reverse();
this.setValue(valueArray);
} else {
this.setValue(valueArray.filter(i => i[this.props.valueKey] !== value[this.props.valueKey]));
}

this.focus();
}

Expand Down Expand Up @@ -1205,6 +1222,7 @@ Select.propTypes = {
deleteRemoves: PropTypes.bool, // whether delete removes an item if there is no text input
delimiter: PropTypes.string, // delimiter to use to join multiple values for the hidden field value
disabled: PropTypes.bool, // whether the Select is disabled or not
duplicate: PropTypes.bool, // whether the Select allows the same option to be selected multiple times
escapeClearsValue: PropTypes.bool, // whether escape clears the value when the menu is closed
filterOption: PropTypes.func, // method to filter a single option (option, filterString)
filterOptions: PropTypes.any, // boolean to enable default filtering or function to filter the options array ([options], filterString, [values])
Expand Down Expand Up @@ -1277,6 +1295,7 @@ Select.defaultProps = {
deleteRemoves: true,
delimiter: ',',
disabled: false,
duplicate: false,
escapeClearsValue: true,
filterOptions: defaultFilterOptions,
ignoreAccents: true,
Expand Down

0 comments on commit c92893e

Please sign in to comment.