react-select-search
Advanced tools
Comparing version 1.0.0-rc3 to 1.0.0-rc4
@@ -21,3 +21,3 @@ import React from 'react'; | ||
<Context.Provider value={theme}> | ||
<Option name="Helvetica" value="helvetica" optionProps={{ className: classes.option }} /> | ||
<Option name="Helvetica" value="helvetica" snapshot={{}} /> | ||
</Context.Provider> | ||
@@ -46,3 +46,3 @@ )); | ||
<Context.Provider value={theme}> | ||
<Option name="Helvetica" value="helvetica" optionProps={{ className: classes.option, onClick: mockCallback }} /> | ||
<Option name="Helvetica" value="helvetica" onChange={mockCallback} snapshot={{}} /> | ||
</Context.Provider> | ||
@@ -62,3 +62,3 @@ )); | ||
<Context.Provider value={theme}> | ||
<Option name="Helvetica" value="helvetica" optionProps={{ className: classes.option, onClick: mockCallback, disabled: true }} /> | ||
<Option name="Helvetica" value="helvetica" disabled={true} snapshot={{ highlighted: null }} /> | ||
</Context.Provider> | ||
@@ -89,3 +89,3 @@ )); | ||
<Context.Provider value={themeWithRenderer}> | ||
<Option {...option} option={option} optionProps={{ className: classes.option }} /> | ||
<Option {...option} option={option} snapshot={{ highlighted: false, value: null }} /> | ||
</Context.Provider> | ||
@@ -92,0 +92,0 @@ )); |
@@ -44,3 +44,3 @@ import React from 'react'; | ||
<Context.Provider value={theme}> | ||
<Options options={groupedOptions} /> | ||
<Options options={groupedOptions} snapshot={{}} /> | ||
</Context.Provider> | ||
@@ -47,0 +47,0 @@ )); |
@@ -154,3 +154,3 @@ import React from 'react'; | ||
expect(wrapper.state('value')).toBe(''); | ||
expect(wrapper.find(Option).at(10).find('li').hasClass('is-disabled')).toBe(true); | ||
expect(wrapper.find(Option).at(10).find('button').hasClass('is-disabled')).toBe(true); | ||
@@ -157,0 +157,0 @@ done(); |
@@ -26,2 +26,4 @@ "use strict"; | ||
var render = theme.renderers.groupHeader; | ||
var onChange = props.onChange, | ||
snapshot = props.snapshot; | ||
var name = props.name; | ||
@@ -42,3 +44,5 @@ | ||
}, name), _react.default.createElement(_Options.default, { | ||
options: props.items | ||
options: props.items, | ||
onChange: onChange, | ||
snapshot: snapshot | ||
}))); | ||
@@ -50,3 +54,8 @@ }; | ||
name: _propTypes.default.string.isRequired, | ||
items: _propTypes.default.arrayOf(_propTypes.default.object).isRequired | ||
items: _propTypes.default.arrayOf(_propTypes.default.object).isRequired, | ||
onChange: _propTypes.default.func.isRequired, | ||
snapshot: _propTypes.default.shape({ | ||
value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.arrayOf(_propTypes.default.string)]), | ||
highlighted: _propTypes.default.number | ||
}).isRequired | ||
}; | ||
@@ -53,0 +62,0 @@ |
@@ -22,101 +22,152 @@ "use strict"; | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
var Option = function Option(props) { | ||
var type = props.type, | ||
groupId = props.groupId, | ||
name = props.name, | ||
optionProps = props.optionProps, | ||
highlighted = props.highlighted, | ||
selected = props.selected, | ||
option = props.option, | ||
disabled = props.disabled, | ||
focus = props.focus; | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
if (type && type === 'group') { | ||
return _react.default.createElement(_Group.default, _extends({}, props, { | ||
name: name, | ||
key: groupId | ||
})); | ||
} | ||
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } | ||
var ref = (0, _react.createRef)(); | ||
var theme = (0, _react.useContext)(_Context.default); | ||
var scrollConf = { | ||
behavior: 'auto', | ||
block: 'center' | ||
}; | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
if (!theme.multiple) { | ||
(0, _react.useEffect)(function () { | ||
if (!selected) return; | ||
ref.current.scrollIntoView(scrollConf); | ||
}, [selected, focus]); | ||
} | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
(0, _react.useEffect)(function () { | ||
if (!highlighted) return; | ||
ref.current.scrollIntoView(scrollConf); | ||
}, [highlighted]); | ||
var renderOption = theme.renderers.option; | ||
var className = theme.classes.row; | ||
var optionSnapshot = { | ||
highlighted: highlighted, | ||
selected: selected | ||
}; | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
if (disabled) { | ||
className += ' is-disabled'; | ||
} | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
if (typeof renderOption === 'function') { | ||
return _react.default.createElement("li", { | ||
ref: ref, | ||
role: "presentation", | ||
className: className | ||
}, renderOption(optionProps, option, optionSnapshot)); | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
var Option = | ||
/*#__PURE__*/ | ||
function (_React$PureComponent) { | ||
_inherits(Option, _React$PureComponent); | ||
function Option(props) { | ||
var _this; | ||
_classCallCheck(this, Option); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(Option).call(this, props)); | ||
_this.ref = (0, _react.createRef)(); | ||
return _this; | ||
} | ||
return _react.default.createElement("li", { | ||
ref: ref, | ||
role: "presentation", | ||
className: className | ||
}, _react.default.createElement("button", _extends({}, optionProps, { | ||
type: "button" | ||
}), name)); | ||
}; | ||
_createClass(Option, [{ | ||
key: "componentDidUpdate", | ||
value: function componentDidUpdate(prevProps) { | ||
var _this2 = this; | ||
var prevSnap = prevProps.snapshot; | ||
var prevFocus = prevSnap.focus; | ||
var _this$props = this.props, | ||
snapshot = _this$props.snapshot, | ||
value = _this$props.value, | ||
index = _this$props.index; | ||
var focus = snapshot.focus, | ||
highlighted = snapshot.highlighted; | ||
var scrollConf = { | ||
behavior: 'auto', | ||
block: 'center' | ||
}; | ||
setImmediate(function () { | ||
if (focus) { | ||
var selected = Array.isArray(snapshot.value) && snapshot.value.indexOf(value) >= 0 || value === snapshot.value; | ||
var isHighlighted = index === highlighted; | ||
var prevIsHighlighted = index === prevSnap.highlighted; | ||
if (isHighlighted && isHighlighted !== prevIsHighlighted || selected && focus !== prevFocus) { | ||
_this2.ref.current.scrollIntoView(scrollConf); | ||
} | ||
} | ||
}); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
if (this.props.type === 'group') { | ||
return _react.default.createElement(_Group.default, this.props); | ||
} | ||
var _this$props2 = this.props, | ||
name = _this$props2.name, | ||
value = _this$props2.value, | ||
index = _this$props2.index, | ||
disabled = _this$props2.disabled, | ||
onChange = _this$props2.onChange, | ||
snapshot = _this$props2.snapshot; | ||
var optionClass = [this.context.classes.option]; | ||
var renderOption = this.context.renderers.option; | ||
var highlighted = index === snapshot.highlighted; | ||
var selected = Array.isArray(snapshot.value) && snapshot.value.indexOf(value) >= 0 || value === snapshot.value; | ||
if (selected) { | ||
optionClass.push('is-selected'); | ||
} | ||
if (highlighted) { | ||
optionClass.push('is-highlighted'); | ||
} | ||
if (disabled) { | ||
optionClass.push('is-disabled'); | ||
} | ||
var optionSnapshot = { | ||
highlighted: highlighted, | ||
selected: selected | ||
}; | ||
var optionProps = { | ||
disabled: disabled, | ||
value: value, | ||
className: optionClass.join(' '), | ||
onClick: onChange, | ||
tabIndex: -1, | ||
role: 'menuitem', | ||
'data-selected': selected ? 'true' : null, | ||
'data-highlighted': highlighted ? 'true' : null, | ||
key: value | ||
}; | ||
var content = typeof renderOption === 'function' ? renderOption(optionProps, this.props, optionSnapshot) : _react.default.createElement("button", _extends({}, optionProps, { | ||
type: "button" | ||
}), name); | ||
return _react.default.createElement("li", { | ||
ref: this.ref, | ||
key: value, | ||
role: "presentation", | ||
className: this.context.classes.row | ||
}, content); | ||
} | ||
}]); | ||
return Option; | ||
}(_react.default.PureComponent); | ||
Option.contextType = _Context.default; | ||
Option.defaultProps = { | ||
type: null, | ||
groupId: null, | ||
type: null, | ||
selected: false, | ||
highlighted: false, | ||
disabled: false, | ||
items: [], | ||
optionProps: null, | ||
option: null | ||
index: null, | ||
value: null, | ||
items: null | ||
}; | ||
Option.propTypes = { | ||
highlighted: _propTypes.default.bool, | ||
selected: _propTypes.default.bool, | ||
disabled: _propTypes.default.bool, | ||
name: _propTypes.default.string.isRequired, | ||
optionProps: _propTypes.default.shape({ | ||
'data-selected': _propTypes.default.string, | ||
role: _propTypes.default.string, | ||
onClick: _propTypes.default.func, | ||
className: _propTypes.default.string, | ||
disabled: _propTypes.default.bool | ||
}), | ||
value: _propTypes.default.string, | ||
type: _propTypes.default.string, | ||
groupId: _propTypes.default.string, | ||
items: _propTypes.default.arrayOf(_propTypes.default.object), | ||
groupId: _propTypes.default.string, | ||
type: _propTypes.default.string, | ||
option: _propTypes.default.shape({ | ||
name: _propTypes.default.string.isRequired, | ||
value: _propTypes.default.string.isRequired | ||
}) | ||
disabled: _propTypes.default.bool, | ||
onChange: _propTypes.default.func.isRequired, | ||
index: _propTypes.default.number, | ||
snapshot: _propTypes.default.shape({ | ||
value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.arrayOf(_propTypes.default.string)]), | ||
highlighted: _propTypes.default.number, | ||
focus: _propTypes.default.bool | ||
}).isRequired | ||
}; | ||
var _default = (0, _react.memo)(Option); | ||
var _default = Option; | ||
exports.default = _default; |
@@ -25,3 +25,5 @@ "use strict"; | ||
var Options = function Options(_ref) { | ||
var options = _ref.options; | ||
var options = _ref.options, | ||
snapshot = _ref.snapshot, | ||
onChange = _ref.onChange; | ||
var theme = (0, _react.useContext)(_Context.default); | ||
@@ -34,2 +36,4 @@ return _react.default.createElement("ul", { | ||
return _react.default.createElement(_Option.default, _extends({}, option, { | ||
snapshot: snapshot, | ||
onChange: onChange, | ||
key: key | ||
@@ -41,3 +45,8 @@ })); | ||
Options.propTypes = { | ||
options: _propTypes.default.arrayOf(_propTypes.default.object).isRequired | ||
options: _propTypes.default.arrayOf(_propTypes.default.object).isRequired, | ||
onChange: _propTypes.default.func.isRequired, | ||
snapshot: _propTypes.default.shape({ | ||
value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.arrayOf(_propTypes.default.string)]), | ||
highlighted: _propTypes.default.number | ||
}).isRequired | ||
}; | ||
@@ -44,0 +53,0 @@ |
@@ -42,6 +42,2 @@ "use strict"; | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
@@ -71,4 +67,5 @@ | ||
// eslint-disable-next-line global-require | ||
fuse = require('fuse.js'); | ||
Fuse = require('fuse.js'); | ||
} catch (e) { | ||
/* istanbul ignore next */ | ||
if (process.env.NODE_ENV !== 'production') { | ||
@@ -110,2 +107,6 @@ console.warn('React Select Search: Not using fuzzy search. Please install fuse.js to enable this feature.'); | ||
_defineProperty(_assertThisInitialized(_this), "onOptionClick", function (e) { | ||
return _this.onChange(e.currentTarget.value); | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "onChange", function (value) { | ||
@@ -294,48 +295,2 @@ var currentValue = _this.getValue().slice(); | ||
}, { | ||
key: "getOptionsForRender", | ||
value: function getOptionsForRender() { | ||
var _this3 = this; | ||
var multiple = this.props.multiple; | ||
var _this$state2 = this.state, | ||
options = _this$state2.options, | ||
focus = _this$state2.focus, | ||
highlighted = _this$state2.highlighted; | ||
var value = this.getValue(); | ||
var mappedOptions = options.map(function (option, i) { | ||
var selected = multiple && Array.isArray(value) && value.indexOf(option.value) >= 0 || option.value === value; | ||
var isHighlighted = i === highlighted; | ||
var className = _this3.theme.classes.option; | ||
if (isHighlighted) { | ||
className += ' is-highlighted'; | ||
} | ||
if (selected) { | ||
className += ' is-selected'; | ||
} | ||
return _objectSpread({}, option, { | ||
option: option, | ||
selected: selected, | ||
focus: focus, | ||
highlighted: isHighlighted, | ||
disabled: option.disabled, | ||
optionProps: { | ||
className: className, | ||
onClick: function onClick() { | ||
return _this3.onChange(option.value); | ||
}, | ||
tabIndex: -1, | ||
role: 'menuitem', | ||
'data-selected': selected ? 'true' : null, | ||
'data-highlighted': highlighted ? 'true' : null, | ||
disabled: _this3.props.disabled || option.disabled | ||
}, | ||
key: "".concat(option.value, "-option") | ||
}); | ||
}); | ||
return (0, _GroupOptions.default)(mappedOptions); | ||
} | ||
}, { | ||
key: "getValueProps", | ||
@@ -348,6 +303,6 @@ value: function getValueProps(value) { | ||
multiple = _this$props2.multiple; | ||
var _this$state3 = this.state, | ||
focus = _this$state3.focus, | ||
error = _this$state3.error, | ||
searching = _this$state3.searching; | ||
var _this$state2 = this.state, | ||
focus = _this$state2.focus, | ||
error = _this$state2.error, | ||
searching = _this$state2.searching; | ||
var search = this.state.search; | ||
@@ -408,3 +363,3 @@ var val = value ? value.name : ''; | ||
value: function search() { | ||
var _this4 = this; | ||
var _this3 = this; | ||
@@ -415,5 +370,5 @@ if (this.searchPromise) { | ||
var _this$state4 = this.state, | ||
defaultOptions = _this$state4.defaultOptions, | ||
search = _this$state4.search; | ||
var _this$state3 = this.state, | ||
defaultOptions = _this$state3.defaultOptions, | ||
search = _this$state3.search; | ||
var promise = this.getNewOptionsList(defaultOptions, (0, _toString.default)(search)); | ||
@@ -425,8 +380,8 @@ this.searchPromise = (0, _cancelablePromise.default)(promise); | ||
this.searchPromise.promise.then(function (options) { | ||
_this4.setState({ | ||
options: options, | ||
_this3.setState({ | ||
options: (0, _GroupOptions.default)(options), | ||
searching: false | ||
}); | ||
}).catch(function (error) { | ||
_this4.setState({ | ||
_this3.setState({ | ||
error: error, | ||
@@ -440,14 +395,8 @@ searching: false | ||
value: function fuzzySearch(options, value, fuseOptions) { | ||
var _this5 = this; | ||
var _this4 = this; | ||
return new Promise(function (resolve) { | ||
if (!Fuse) { | ||
resolve(options); | ||
return; | ||
} | ||
if (_this5.props.fuse && options && options.length > 0 && value && value.length > 0) { | ||
var _fuse = new Fuse(options, fuseOptions); | ||
var newOptions = _fuse.search(value).map(function (item, index) { | ||
if (Fuse && _this4.props.fuse && options.length > 0 && value && value.length > 0) { | ||
var fuse = new Fuse(options, fuseOptions); | ||
var newOptions = fuse.search(value).map(function (item, index) { | ||
return Object.assign({}, item, { | ||
@@ -457,7 +406,7 @@ index: index | ||
}); | ||
resolve(newOptions); | ||
} else { | ||
resolve(options); | ||
return; | ||
} | ||
resolve(options); | ||
}); | ||
@@ -521,6 +470,8 @@ } | ||
value: function render() { | ||
var _this$state5 = this.state, | ||
defaultOptions = _this$state5.defaultOptions, | ||
focus = _this$state5.focus, | ||
searching = _this$state5.searching; | ||
var _this$state4 = this.state, | ||
defaultOptions = _this$state4.defaultOptions, | ||
focus = _this$state4.focus, | ||
searching = _this$state4.searching, | ||
options = _this$state4.options, | ||
highlighted = _this$state4.highlighted; | ||
var _this$props3 = this.props, | ||
@@ -530,5 +481,10 @@ search = _this$props3.search, | ||
disabled = _this$props3.disabled; | ||
var selectedOption = (0, _findByValue.default)(defaultOptions, this.getValue()); | ||
var mappedOptions = this.getOptionsForRender(); | ||
var value = this.getValue(); | ||
var selectedOption = (0, _findByValue.default)(defaultOptions, value); | ||
var valueProps = this.getValueProps(selectedOption); | ||
var snapshot = { | ||
value: value, | ||
highlighted: highlighted, | ||
focus: focus | ||
}; | ||
var className = this.theme.classes.main; | ||
@@ -566,3 +522,5 @@ | ||
}, _react.default.createElement(_Options.default, { | ||
options: mappedOptions | ||
options: options, | ||
snapshot: snapshot, | ||
onChange: this.onOptionClick | ||
})))); | ||
@@ -569,0 +527,0 @@ } |
@@ -10,2 +10,4 @@ import React, { useContext, memo } from 'react'; | ||
var render = theme.renderers.groupHeader; | ||
var onChange = props.onChange, | ||
snapshot = props.snapshot; | ||
var name = props.name; | ||
@@ -26,3 +28,5 @@ | ||
}, name), React.createElement(Options, { | ||
options: props.items | ||
options: props.items, | ||
onChange: onChange, | ||
snapshot: snapshot | ||
}))); | ||
@@ -34,4 +38,9 @@ }; | ||
name: PropTypes.string.isRequired, | ||
items: PropTypes.arrayOf(PropTypes.object).isRequired | ||
items: PropTypes.arrayOf(PropTypes.object).isRequired, | ||
onChange: PropTypes.func.isRequired, | ||
snapshot: PropTypes.shape({ | ||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), | ||
highlighted: PropTypes.number | ||
}).isRequired | ||
}; | ||
export default memo(Group); |
@@ -0,4 +1,22 @@ | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
import React, { useContext, memo, useEffect, createRef } from 'react'; | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } | ||
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | ||
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } | ||
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | ||
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | ||
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | ||
import React, { createRef } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
@@ -8,96 +26,131 @@ import Context from '../Context'; | ||
var Option = function Option(props) { | ||
var type = props.type, | ||
groupId = props.groupId, | ||
name = props.name, | ||
optionProps = props.optionProps, | ||
highlighted = props.highlighted, | ||
selected = props.selected, | ||
option = props.option, | ||
disabled = props.disabled, | ||
focus = props.focus; | ||
var Option = | ||
/*#__PURE__*/ | ||
function (_React$PureComponent) { | ||
_inherits(Option, _React$PureComponent); | ||
if (type && type === 'group') { | ||
return React.createElement(Group, _extends({}, props, { | ||
name: name, | ||
key: groupId | ||
})); | ||
} | ||
function Option(props) { | ||
var _this; | ||
var ref = createRef(); | ||
var theme = useContext(Context); | ||
var scrollConf = { | ||
behavior: 'auto', | ||
block: 'center' | ||
}; | ||
_classCallCheck(this, Option); | ||
if (!theme.multiple) { | ||
useEffect(function () { | ||
if (!selected) return; | ||
ref.current.scrollIntoView(scrollConf); | ||
}, [selected, focus]); | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(Option).call(this, props)); | ||
_this.ref = createRef(); | ||
return _this; | ||
} | ||
useEffect(function () { | ||
if (!highlighted) return; | ||
ref.current.scrollIntoView(scrollConf); | ||
}, [highlighted]); | ||
var renderOption = theme.renderers.option; | ||
var className = theme.classes.row; | ||
var optionSnapshot = { | ||
highlighted: highlighted, | ||
selected: selected | ||
}; | ||
_createClass(Option, [{ | ||
key: "componentDidUpdate", | ||
value: function componentDidUpdate(prevProps) { | ||
var _this2 = this; | ||
if (disabled) { | ||
className += ' is-disabled'; | ||
} | ||
var prevSnap = prevProps.snapshot; | ||
var prevFocus = prevSnap.focus; | ||
var _this$props = this.props, | ||
snapshot = _this$props.snapshot, | ||
value = _this$props.value, | ||
index = _this$props.index; | ||
var focus = snapshot.focus, | ||
highlighted = snapshot.highlighted; | ||
var scrollConf = { | ||
behavior: 'auto', | ||
block: 'center' | ||
}; | ||
setImmediate(function () { | ||
if (focus) { | ||
var selected = Array.isArray(snapshot.value) && snapshot.value.indexOf(value) >= 0 || value === snapshot.value; | ||
var isHighlighted = index === highlighted; | ||
var prevIsHighlighted = index === prevSnap.highlighted; | ||
if (typeof renderOption === 'function') { | ||
return React.createElement("li", { | ||
ref: ref, | ||
role: "presentation", | ||
className: className | ||
}, renderOption(optionProps, option, optionSnapshot)); | ||
} | ||
if (isHighlighted && isHighlighted !== prevIsHighlighted || selected && focus !== prevFocus) { | ||
_this2.ref.current.scrollIntoView(scrollConf); | ||
} | ||
} | ||
}); | ||
} | ||
}, { | ||
key: "render", | ||
value: function render() { | ||
if (this.props.type === 'group') { | ||
return React.createElement(Group, this.props); | ||
} | ||
return React.createElement("li", { | ||
ref: ref, | ||
role: "presentation", | ||
className: className | ||
}, React.createElement("button", _extends({}, optionProps, { | ||
type: "button" | ||
}), name)); | ||
}; | ||
var _this$props2 = this.props, | ||
name = _this$props2.name, | ||
value = _this$props2.value, | ||
index = _this$props2.index, | ||
disabled = _this$props2.disabled, | ||
onChange = _this$props2.onChange, | ||
snapshot = _this$props2.snapshot; | ||
var optionClass = [this.context.classes.option]; | ||
var renderOption = this.context.renderers.option; | ||
var highlighted = index === snapshot.highlighted; | ||
var selected = Array.isArray(snapshot.value) && snapshot.value.indexOf(value) >= 0 || value === snapshot.value; | ||
if (selected) { | ||
optionClass.push('is-selected'); | ||
} | ||
if (highlighted) { | ||
optionClass.push('is-highlighted'); | ||
} | ||
if (disabled) { | ||
optionClass.push('is-disabled'); | ||
} | ||
var optionSnapshot = { | ||
highlighted: highlighted, | ||
selected: selected | ||
}; | ||
var optionProps = { | ||
disabled: disabled, | ||
value: value, | ||
className: optionClass.join(' '), | ||
onClick: onChange, | ||
tabIndex: -1, | ||
role: 'menuitem', | ||
'data-selected': selected ? 'true' : null, | ||
'data-highlighted': highlighted ? 'true' : null, | ||
key: value | ||
}; | ||
var content = typeof renderOption === 'function' ? renderOption(optionProps, this.props, optionSnapshot) : React.createElement("button", _extends({}, optionProps, { | ||
type: "button" | ||
}), name); | ||
return React.createElement("li", { | ||
ref: this.ref, | ||
key: value, | ||
role: "presentation", | ||
className: this.context.classes.row | ||
}, content); | ||
} | ||
}]); | ||
return Option; | ||
}(React.PureComponent); | ||
Option.contextType = Context; | ||
Option.defaultProps = { | ||
type: null, | ||
groupId: null, | ||
type: null, | ||
selected: false, | ||
highlighted: false, | ||
disabled: false, | ||
items: [], | ||
optionProps: null, | ||
option: null | ||
index: null, | ||
value: null, | ||
items: null | ||
}; | ||
Option.propTypes = { | ||
highlighted: PropTypes.bool, | ||
selected: PropTypes.bool, | ||
disabled: PropTypes.bool, | ||
name: PropTypes.string.isRequired, | ||
optionProps: PropTypes.shape({ | ||
'data-selected': PropTypes.string, | ||
role: PropTypes.string, | ||
onClick: PropTypes.func, | ||
className: PropTypes.string, | ||
disabled: PropTypes.bool | ||
}), | ||
value: PropTypes.string, | ||
type: PropTypes.string, | ||
groupId: PropTypes.string, | ||
items: PropTypes.arrayOf(PropTypes.object), | ||
groupId: PropTypes.string, | ||
type: PropTypes.string, | ||
option: PropTypes.shape({ | ||
name: PropTypes.string.isRequired, | ||
value: PropTypes.string.isRequired | ||
}) | ||
disabled: PropTypes.bool, | ||
onChange: PropTypes.func.isRequired, | ||
index: PropTypes.number, | ||
snapshot: PropTypes.shape({ | ||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), | ||
highlighted: PropTypes.number, | ||
focus: PropTypes.bool | ||
}).isRequired | ||
}; | ||
export default memo(Option); | ||
export default Option; |
@@ -9,3 +9,5 @@ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
var Options = function Options(_ref) { | ||
var options = _ref.options; | ||
var options = _ref.options, | ||
snapshot = _ref.snapshot, | ||
onChange = _ref.onChange; | ||
var theme = useContext(Context); | ||
@@ -18,2 +20,4 @@ return React.createElement("ul", { | ||
return React.createElement(Option, _extends({}, option, { | ||
snapshot: snapshot, | ||
onChange: onChange, | ||
key: key | ||
@@ -25,4 +29,9 @@ })); | ||
Options.propTypes = { | ||
options: PropTypes.arrayOf(PropTypes.object).isRequired | ||
options: PropTypes.arrayOf(PropTypes.object).isRequired, | ||
onChange: PropTypes.func.isRequired, | ||
snapshot: PropTypes.shape({ | ||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), | ||
highlighted: PropTypes.number | ||
}).isRequired | ||
}; | ||
export default memo(Options); |
@@ -11,6 +11,2 @@ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
@@ -51,4 +47,5 @@ | ||
// eslint-disable-next-line global-require | ||
fuse = require('fuse.js'); | ||
Fuse = require('fuse.js'); | ||
} catch (e) { | ||
/* istanbul ignore next */ | ||
if (process.env.NODE_ENV !== 'production') { | ||
@@ -90,2 +87,6 @@ console.warn('React Select Search: Not using fuzzy search. Please install fuse.js to enable this feature.'); | ||
_defineProperty(_assertThisInitialized(_this), "onOptionClick", function (e) { | ||
return _this.onChange(e.currentTarget.value); | ||
}); | ||
_defineProperty(_assertThisInitialized(_this), "onChange", function (value) { | ||
@@ -274,48 +275,2 @@ var currentValue = _this.getValue().slice(); | ||
}, { | ||
key: "getOptionsForRender", | ||
value: function getOptionsForRender() { | ||
var _this3 = this; | ||
var multiple = this.props.multiple; | ||
var _this$state2 = this.state, | ||
options = _this$state2.options, | ||
focus = _this$state2.focus, | ||
highlighted = _this$state2.highlighted; | ||
var value = this.getValue(); | ||
var mappedOptions = options.map(function (option, i) { | ||
var selected = multiple && Array.isArray(value) && value.indexOf(option.value) >= 0 || option.value === value; | ||
var isHighlighted = i === highlighted; | ||
var className = _this3.theme.classes.option; | ||
if (isHighlighted) { | ||
className += ' is-highlighted'; | ||
} | ||
if (selected) { | ||
className += ' is-selected'; | ||
} | ||
return _objectSpread({}, option, { | ||
option: option, | ||
selected: selected, | ||
focus: focus, | ||
highlighted: isHighlighted, | ||
disabled: option.disabled, | ||
optionProps: { | ||
className: className, | ||
onClick: function onClick() { | ||
return _this3.onChange(option.value); | ||
}, | ||
tabIndex: -1, | ||
role: 'menuitem', | ||
'data-selected': selected ? 'true' : null, | ||
'data-highlighted': highlighted ? 'true' : null, | ||
disabled: _this3.props.disabled || option.disabled | ||
}, | ||
key: "".concat(option.value, "-option") | ||
}); | ||
}); | ||
return GroupOptions(mappedOptions); | ||
} | ||
}, { | ||
key: "getValueProps", | ||
@@ -328,6 +283,6 @@ value: function getValueProps(value) { | ||
multiple = _this$props2.multiple; | ||
var _this$state3 = this.state, | ||
focus = _this$state3.focus, | ||
error = _this$state3.error, | ||
searching = _this$state3.searching; | ||
var _this$state2 = this.state, | ||
focus = _this$state2.focus, | ||
error = _this$state2.error, | ||
searching = _this$state2.searching; | ||
var search = this.state.search; | ||
@@ -388,3 +343,3 @@ var val = value ? value.name : ''; | ||
value: function search() { | ||
var _this4 = this; | ||
var _this3 = this; | ||
@@ -395,5 +350,5 @@ if (this.searchPromise) { | ||
var _this$state4 = this.state, | ||
defaultOptions = _this$state4.defaultOptions, | ||
search = _this$state4.search; | ||
var _this$state3 = this.state, | ||
defaultOptions = _this$state3.defaultOptions, | ||
search = _this$state3.search; | ||
var promise = this.getNewOptionsList(defaultOptions, toString(search)); | ||
@@ -405,8 +360,8 @@ this.searchPromise = cancelablePromise(promise); | ||
this.searchPromise.promise.then(function (options) { | ||
_this4.setState({ | ||
options: options, | ||
_this3.setState({ | ||
options: GroupOptions(options), | ||
searching: false | ||
}); | ||
}).catch(function (error) { | ||
_this4.setState({ | ||
_this3.setState({ | ||
error: error, | ||
@@ -420,14 +375,8 @@ searching: false | ||
value: function fuzzySearch(options, value, fuseOptions) { | ||
var _this5 = this; | ||
var _this4 = this; | ||
return new Promise(function (resolve) { | ||
if (!Fuse) { | ||
resolve(options); | ||
return; | ||
} | ||
if (_this5.props.fuse && options && options.length > 0 && value && value.length > 0) { | ||
var _fuse = new Fuse(options, fuseOptions); | ||
var newOptions = _fuse.search(value).map(function (item, index) { | ||
if (Fuse && _this4.props.fuse && options.length > 0 && value && value.length > 0) { | ||
var fuse = new Fuse(options, fuseOptions); | ||
var newOptions = fuse.search(value).map(function (item, index) { | ||
return Object.assign({}, item, { | ||
@@ -437,7 +386,7 @@ index: index | ||
}); | ||
resolve(newOptions); | ||
} else { | ||
resolve(options); | ||
return; | ||
} | ||
resolve(options); | ||
}); | ||
@@ -501,6 +450,8 @@ } | ||
value: function render() { | ||
var _this$state5 = this.state, | ||
defaultOptions = _this$state5.defaultOptions, | ||
focus = _this$state5.focus, | ||
searching = _this$state5.searching; | ||
var _this$state4 = this.state, | ||
defaultOptions = _this$state4.defaultOptions, | ||
focus = _this$state4.focus, | ||
searching = _this$state4.searching, | ||
options = _this$state4.options, | ||
highlighted = _this$state4.highlighted; | ||
var _this$props3 = this.props, | ||
@@ -510,5 +461,10 @@ search = _this$props3.search, | ||
disabled = _this$props3.disabled; | ||
var selectedOption = findByValue(defaultOptions, this.getValue()); | ||
var mappedOptions = this.getOptionsForRender(); | ||
var value = this.getValue(); | ||
var selectedOption = findByValue(defaultOptions, value); | ||
var valueProps = this.getValueProps(selectedOption); | ||
var snapshot = { | ||
value: value, | ||
highlighted: highlighted, | ||
focus: focus | ||
}; | ||
var className = this.theme.classes.main; | ||
@@ -546,3 +502,5 @@ | ||
}, React.createElement(Options, { | ||
options: mappedOptions | ||
options: options, | ||
snapshot: snapshot, | ||
onChange: this.onOptionClick | ||
})))); | ||
@@ -549,0 +507,0 @@ } |
{ | ||
"name": "react-select-search", | ||
"version": "1.0.0-rc3", | ||
"version": "1.0.0-rc4", | ||
"description": "React powered selectbox with search", | ||
@@ -49,3 +49,3 @@ "main": "dist/esm/index.js", | ||
"coveralls": "^3.0.7", | ||
"css-loader": "^0.28.9", | ||
"css-loader": "^3.2.0", | ||
"enzyme": "^3.10.0", | ||
@@ -58,2 +58,3 @@ "enzyme-adapter-react-16": "^1.15.1", | ||
"eslint-plugin-react": "^7.16.0", | ||
"fuse.js": "^3.4.5", | ||
"html-webpack-plugin": "^3.2.0", | ||
@@ -70,3 +71,5 @@ "jest": "^24.9.0", | ||
"dependencies": {}, | ||
"optionalDependencies": {} | ||
"optionalDependencies": { | ||
"fuse.js": "^3.4.5" | ||
} | ||
} |
@@ -21,2 +21,5 @@ <p align="center"> | ||
</a> | ||
<a href="https://bundlephobia.com/result?p=react-select-search@next"> | ||
<img src="https://badgen.net/bundlephobia/minzip/react-select-search@next" /> | ||
</a> | ||
<a href="https://beerpay.io/tbleckert/react-select-search"> | ||
@@ -28,2 +31,3 @@ <img src="https://beerpay.io/tbleckert/react-select-search/badge.svg?style=flat" /> | ||
## Features | ||
* Lightweight, with zero dependencies* | ||
* Full test coverage | ||
@@ -38,2 +42,4 @@ * Accessible | ||
_*One optional dependency required for built-in fuzzy search_ | ||
## Demo | ||
@@ -40,0 +46,0 @@ |
@@ -10,2 +10,3 @@ import React, { useContext, memo } from 'react'; | ||
const { groupHeader: render } = theme.renderers; | ||
const { onChange, snapshot } = props; | ||
let { name } = props; | ||
@@ -23,2 +24,4 @@ | ||
options={props.items} | ||
onChange={onChange} | ||
snapshot={snapshot} | ||
/> | ||
@@ -34,4 +37,12 @@ </div> | ||
items: PropTypes.arrayOf(PropTypes.object).isRequired, | ||
onChange: PropTypes.func.isRequired, | ||
snapshot: PropTypes.shape({ | ||
value: PropTypes.oneOfType([ | ||
PropTypes.string, | ||
PropTypes.arrayOf(PropTypes.string), | ||
]), | ||
highlighted: PropTypes.number, | ||
}).isRequired | ||
}; | ||
export default memo(Group); |
@@ -1,2 +0,2 @@ | ||
import React, { useContext, memo, useEffect, createRef } from 'react'; | ||
import React, { createRef } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
@@ -6,101 +6,129 @@ import Context from '../Context'; | ||
const Option = (props) => { | ||
const { | ||
type, | ||
groupId, | ||
name, | ||
optionProps, | ||
highlighted, | ||
selected, | ||
option, | ||
disabled, | ||
focus, | ||
} = props; | ||
class Option extends React.PureComponent { | ||
constructor(props) { | ||
super(props); | ||
if (type && type === 'group') { | ||
return ( | ||
<Group | ||
{...props} | ||
name={name} | ||
key={groupId} | ||
/> | ||
); | ||
this.ref = createRef(); | ||
} | ||
const ref = createRef(); | ||
const theme = useContext(Context); | ||
const scrollConf = { | ||
behavior: 'auto', | ||
block: 'center', | ||
}; | ||
componentDidUpdate(prevProps) { | ||
const prevSnap = prevProps.snapshot; | ||
const prevFocus = prevSnap.focus; | ||
const { snapshot, value, index } = this.props; | ||
const { focus, highlighted } = snapshot; | ||
const scrollConf = { behavior: 'auto', block: 'center' }; | ||
if (!theme.multiple) { | ||
useEffect(() => { | ||
if (!selected) return; | ||
ref.current.scrollIntoView(scrollConf); | ||
}, [selected, focus]); | ||
setImmediate(() => { | ||
if (focus) { | ||
const selected = ( | ||
(Array.isArray(snapshot.value) && snapshot.value.indexOf(value) >= 0) | ||
|| value === snapshot.value | ||
); | ||
const isHighlighted = index === highlighted; | ||
const prevIsHighlighted = index === prevSnap.highlighted; | ||
if ( | ||
(isHighlighted && isHighlighted !== prevIsHighlighted) | ||
|| (selected && focus !== prevFocus) | ||
) { | ||
this.ref.current.scrollIntoView(scrollConf); | ||
} | ||
} | ||
}); | ||
} | ||
useEffect(() => { | ||
if (!highlighted) return; | ||
ref.current.scrollIntoView(scrollConf); | ||
}, [highlighted]); | ||
render() { | ||
if (this.props.type === 'group') { | ||
return <Group {...this.props} />; | ||
} | ||
const { option: renderOption } = theme.renderers; | ||
let className = theme.classes.row; | ||
const optionSnapshot = { highlighted, selected }; | ||
const { | ||
name, | ||
value, | ||
index, | ||
disabled, | ||
onChange, | ||
snapshot, | ||
} = this.props; | ||
if (disabled) { | ||
className += ' is-disabled'; | ||
} | ||
const optionClass = [this.context.classes.option]; | ||
const { option: renderOption } = this.context.renderers; | ||
const highlighted = index === snapshot.highlighted; | ||
const selected = ( | ||
(Array.isArray(snapshot.value) && snapshot.value.indexOf(value) >= 0) | ||
|| value === snapshot.value | ||
); | ||
if (typeof renderOption === 'function') { | ||
if (selected) { | ||
optionClass.push('is-selected'); | ||
} | ||
if (highlighted) { | ||
optionClass.push('is-highlighted'); | ||
} | ||
if (disabled) { | ||
optionClass.push('is-disabled'); | ||
} | ||
const optionSnapshot = { highlighted, selected }; | ||
const optionProps = { | ||
disabled, | ||
value, | ||
className: optionClass.join(' '), | ||
onClick: onChange, | ||
tabIndex: -1, | ||
role: 'menuitem', | ||
'data-selected': (selected) ? 'true' : null, | ||
'data-highlighted': (highlighted) ? 'true' : null, | ||
key: value, | ||
}; | ||
const content = (typeof renderOption === 'function') ? | ||
renderOption(optionProps, this.props, optionSnapshot) : | ||
( | ||
<button {...optionProps} type="button"> | ||
{name} | ||
</button> | ||
); | ||
return ( | ||
<li ref={ref} role="presentation" className={className}> | ||
{renderOption(optionProps, option, optionSnapshot)} | ||
<li ref={this.ref} key={value} role="presentation" className={this.context.classes.row}> | ||
{content} | ||
</li> | ||
); | ||
} | ||
} | ||
return ( | ||
<li ref={ref} role="presentation" className={className}> | ||
<button {...optionProps} type="button"> | ||
{name} | ||
</button> | ||
</li> | ||
); | ||
}; | ||
Option.contextType = Context; | ||
Option.defaultProps = { | ||
type: null, | ||
groupId: null, | ||
type: null, | ||
selected: false, | ||
highlighted: false, | ||
disabled: false, | ||
items: [], | ||
optionProps: null, | ||
option: null, | ||
index: null, | ||
value: null, | ||
items: null, | ||
}; | ||
Option.propTypes = { | ||
highlighted: PropTypes.bool, | ||
selected: PropTypes.bool, | ||
disabled: PropTypes.bool, | ||
name: PropTypes.string.isRequired, | ||
optionProps: PropTypes.shape({ | ||
'data-selected': PropTypes.string, | ||
role: PropTypes.string, | ||
onClick: PropTypes.func, | ||
className: PropTypes.string, | ||
disabled: PropTypes.bool, | ||
}), | ||
value: PropTypes.string, | ||
type: PropTypes.string, | ||
groupId: PropTypes.string, | ||
items: PropTypes.arrayOf(PropTypes.object), | ||
groupId: PropTypes.string, | ||
type: PropTypes.string, | ||
option: PropTypes.shape({ | ||
name: PropTypes.string.isRequired, | ||
value: PropTypes.string.isRequired, | ||
}), | ||
disabled: PropTypes.bool, | ||
onChange: PropTypes.func.isRequired, | ||
index: PropTypes.number, | ||
snapshot: PropTypes.shape({ | ||
value: PropTypes.oneOfType([ | ||
PropTypes.string, | ||
PropTypes.arrayOf(PropTypes.string), | ||
]), | ||
highlighted: PropTypes.number, | ||
focus: PropTypes.bool, | ||
}).isRequired, | ||
}; | ||
export default memo(Option); | ||
export default Option; |
@@ -6,3 +6,3 @@ import React, { useContext, memo } from 'react'; | ||
const Options = ({ options }) => { | ||
const Options = ({ options, snapshot, onChange }) => { | ||
const theme = useContext(Context); | ||
@@ -16,3 +16,3 @@ | ||
return ( | ||
<Option {...option} key={key} /> | ||
<Option {...option} snapshot={snapshot} onChange={onChange} key={key} /> | ||
); | ||
@@ -26,4 +26,12 @@ })} | ||
options: PropTypes.arrayOf(PropTypes.object).isRequired, | ||
onChange: PropTypes.func.isRequired, | ||
snapshot: PropTypes.shape({ | ||
value: PropTypes.oneOfType([ | ||
PropTypes.string, | ||
PropTypes.arrayOf(PropTypes.string), | ||
]), | ||
highlighted: PropTypes.number, | ||
}).isRequired, | ||
}; | ||
export default memo(Options); |
@@ -17,4 +17,5 @@ import React from 'react'; | ||
// eslint-disable-next-line global-require | ||
fuse = require('fuse.js'); | ||
Fuse = require('fuse.js'); | ||
} catch (e) { | ||
/* istanbul ignore next */ | ||
if (process.env.NODE_ENV !== 'production') { | ||
@@ -146,2 +147,4 @@ console.warn('React Select Search: Not using fuzzy search. Please install fuse.js to enable this feature.'); | ||
onOptionClick = e => this.onChange(e.currentTarget.value); | ||
onChange = (value) => { | ||
@@ -244,51 +247,2 @@ let currentValue = this.getValue().slice(); | ||
getOptionsForRender() { | ||
const { multiple } = this.props; | ||
const { | ||
options, | ||
focus, | ||
highlighted, | ||
} = this.state; | ||
const value = this.getValue(); | ||
const mappedOptions = options.map((option, i) => { | ||
const selected = ( | ||
(multiple && Array.isArray(value) && value.indexOf(option.value) >= 0) | ||
|| option.value === value | ||
); | ||
const isHighlighted = i === highlighted; | ||
let className = this.theme.classes.option; | ||
if (isHighlighted) { | ||
className += ' is-highlighted'; | ||
} | ||
if (selected) { | ||
className += ' is-selected'; | ||
} | ||
return { | ||
...option, | ||
option, | ||
selected, | ||
focus, | ||
highlighted: isHighlighted, | ||
disabled: option.disabled, | ||
optionProps: { | ||
className, | ||
onClick: () => this.onChange(option.value), | ||
tabIndex: -1, | ||
role: 'menuitem', | ||
'data-selected': (selected) ? 'true' : null, | ||
'data-highlighted': (highlighted) ? 'true' : null, | ||
disabled: this.props.disabled || option.disabled, | ||
}, | ||
key: `${option.value}-option`, | ||
}; | ||
}); | ||
return GroupOptions(mappedOptions); | ||
} | ||
getValueProps(value) { | ||
@@ -365,3 +319,6 @@ const { | ||
this.searchPromise.promise.then((options) => { | ||
this.setState({ options, searching: false }); | ||
this.setState({ | ||
options: GroupOptions(options), | ||
searching: false, | ||
}); | ||
}).catch((error) => { | ||
@@ -374,9 +331,3 @@ this.setState({ error, searching: false }); | ||
return new Promise((resolve) => { | ||
if (!Fuse) { | ||
resolve(options); | ||
return; | ||
} | ||
if (this.props.fuse && options && options.length > 0 && value && value.length > 0) { | ||
if (Fuse && this.props.fuse && options.length > 0 && value && value.length > 0) { | ||
const fuse = new Fuse(options, fuseOptions); | ||
@@ -388,5 +339,7 @@ const newOptions = fuse | ||
resolve(newOptions); | ||
} else { | ||
resolve(options); | ||
return; | ||
} | ||
resolve(options); | ||
}); | ||
@@ -446,2 +399,4 @@ } | ||
searching, | ||
options, | ||
highlighted, | ||
} = this.state; | ||
@@ -454,5 +409,12 @@ | ||
} = this.props; | ||
const selectedOption = findByValue(defaultOptions, this.getValue()); | ||
const mappedOptions = this.getOptionsForRender(); | ||
const value = this.getValue(); | ||
const selectedOption = findByValue(defaultOptions, value); | ||
const valueProps = this.getValueProps(selectedOption); | ||
const snapshot = { | ||
value, | ||
highlighted, | ||
focus, | ||
}; | ||
let className = this.theme.classes.main; | ||
@@ -489,3 +451,7 @@ | ||
<div className={this.theme.classes.select}> | ||
<Options options={mappedOptions} /> | ||
<Options | ||
options={options} | ||
snapshot={snapshot} | ||
onChange={this.onOptionClick} | ||
/> | ||
</div> | ||
@@ -492,0 +458,0 @@ )} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
192580
81
4410
100
4
29