react-select-search
Advanced tools
Comparing version 2.2.4 to 3.0.0-beta.1
@@ -6,33 +6,25 @@ "use strict"; | ||
var _react = _interopRequireWildcard(require("react")); | ||
var _jsxRuntime = require("react/jsx-runtime"); | ||
var _react = require("react"); | ||
var _propTypes = _interopRequireDefault(require("prop-types")); | ||
var _classes2 = _interopRequireDefault(require("../lib/classes")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } | ||
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 _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
var Option = function Option(_ref) { | ||
var _classes; | ||
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(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
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 _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } | ||
var Option = function Option(_ref) { | ||
var optionProps = _ref.optionProps, | ||
highlighted = _ref.highlighted, | ||
selected = _ref.selected, | ||
option = _ref.option, | ||
cls = _ref.cls, | ||
renderOption = _ref.renderOption, | ||
option = _objectWithoutPropertiesLoose(_ref, ["optionProps", "highlighted", "selected", "cls", "renderOption"]); | ||
renderOption = _ref.renderOption; | ||
var optionClass = [cls('option'), selected ? cls('is-selected') : false, highlighted ? cls('is-highlighted') : false].filter(function (single) { | ||
return !!single; | ||
}).join(' '); | ||
var domProps = _objectSpread(_objectSpread({}, optionProps), {}, { | ||
var props = _extends({}, optionProps, { | ||
value: option.value, | ||
@@ -42,3 +34,4 @@ disabled: option.disabled | ||
return /*#__PURE__*/_react["default"].createElement("li", { | ||
var className = (0, _classes2["default"])((_classes = {}, _classes[cls('option')] = true, _classes[cls('is-selected')] = selected, _classes[cls('is-highlighted')] = highlighted, _classes)); | ||
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("li", { | ||
className: cls('row'), | ||
@@ -48,19 +41,24 @@ role: "menuitem", | ||
"data-value": escape(option.value), | ||
key: option.value | ||
}, renderOption(domProps, option, { | ||
selected: selected, | ||
highlighted: highlighted | ||
}, optionClass)); | ||
children: [renderOption && renderOption(props, option, { | ||
selected: selected, | ||
highlighted: highlighted | ||
}, className), !renderOption && /*#__PURE__*/(0, _jsxRuntime.jsx)("button", _extends({ | ||
type: "button", | ||
className: className | ||
}, props, { | ||
children: option.name | ||
}))] | ||
}, option.value); | ||
}; | ||
Option.defaultProps = { | ||
disabled: false, | ||
index: null, | ||
value: null | ||
renderOption: null | ||
}; | ||
Option.propTypes = process.env.NODE_ENV !== "production" ? { | ||
name: _propTypes["default"].string.isRequired, | ||
value: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]), | ||
disabled: _propTypes["default"].bool, | ||
index: _propTypes["default"].number, | ||
option: _propTypes["default"].shape({ | ||
name: _propTypes["default"].string.isRequired, | ||
value: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]), | ||
disabled: _propTypes["default"].bool, | ||
index: _propTypes["default"].number | ||
}).isRequired, | ||
highlighted: _propTypes["default"].bool.isRequired, | ||
@@ -73,3 +71,3 @@ selected: _propTypes["default"].bool.isRequired, | ||
cls: _propTypes["default"].func.isRequired, | ||
renderOption: _propTypes["default"].func.isRequired | ||
renderOption: _propTypes["default"].func | ||
} : {}; | ||
@@ -76,0 +74,0 @@ |
@@ -6,5 +6,5 @@ "use strict"; | ||
function highlightReducer(highlighted, value) { | ||
var key = value.key, | ||
options = value.options; | ||
function highlightReducer(highlighted, _ref) { | ||
var key = _ref.key, | ||
options = _ref.options; | ||
var max = options.length - 1; | ||
@@ -11,0 +11,0 @@ var newHighlighted = key === 'ArrowDown' ? highlighted + 1 : highlighted - 1; |
@@ -6,8 +6,4 @@ "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 _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 _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
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 flattenOptions(options) { | ||
@@ -23,6 +19,5 @@ if (!Array.isArray(options)) { | ||
option.items.forEach(function (groupOption) { | ||
nextOptions.push(_objectSpread(_objectSpread({}, groupOption), {}, { | ||
nextOptions.push(_extends({}, groupOption, { | ||
groupId: id, | ||
groupName: option.name, | ||
_id: "" + groupOption.value | ||
groupName: option.name | ||
})); | ||
@@ -33,4 +28,3 @@ }); | ||
nextOptions.push(_objectSpread(_objectSpread({}, option), {}, { | ||
_id: "" + option.value, | ||
nextOptions.push(_extends({}, option, { | ||
index: index | ||
@@ -37,0 +31,0 @@ })); |
@@ -6,23 +6,30 @@ "use strict"; | ||
function getNewValue(value, oldValue, multiple) { | ||
function getNewValue(value, oldValue, options, multiple) { | ||
var newValue = value === null && options.length ? options[0].value : value; | ||
if (!multiple) { | ||
return value; | ||
return newValue; | ||
} | ||
if (!newValue) { | ||
return []; | ||
} | ||
if (!oldValue) { | ||
return [value]; | ||
return !Array.isArray(newValue) ? [newValue] : [].concat(newValue); | ||
} | ||
var newValue = !Array.isArray(oldValue) ? [oldValue] : [].concat(oldValue); | ||
var valueIndex = newValue.findIndex(function (val) { | ||
return val === value; | ||
var newArrayValue = !Array.isArray(oldValue) ? [oldValue] : [].concat(oldValue); // eslint-disable-next-line eqeqeq | ||
var valueIndex = newArrayValue.findIndex(function (val) { | ||
return val == newValue; | ||
}); | ||
if (valueIndex >= 0) { | ||
newValue.splice(valueIndex, 1); | ||
newArrayValue.splice(valueIndex, 1); | ||
} else { | ||
newValue.push(value); | ||
newArrayValue.push(value); | ||
} | ||
return newValue; | ||
return newArrayValue; | ||
} |
@@ -6,14 +6,40 @@ "use strict"; | ||
function getOption(value, defaultOptions) { | ||
if (Array.isArray(value)) { | ||
return value.map(function (singleValue) { | ||
return defaultOptions.find(function (option) { | ||
return option.value === singleValue; | ||
}); | ||
function getOption(value, oldValue, options, multiple) { | ||
var newValue = value === null && options.length ? options[0].value : value; // eslint-disable-next-line eqeqeq | ||
var f = function f(ref) { | ||
return options.find(function (o) { | ||
return o.value == ref; | ||
}); | ||
}; | ||
var option = Array.isArray(value) ? newValue.map(function (v) { | ||
return f(v); | ||
}) : f(newValue); | ||
if (!multiple) { | ||
return option || oldValue; | ||
} | ||
return defaultOptions.find(function (option) { | ||
return option.value === value; | ||
}) || null; | ||
if (!option) { | ||
return oldValue; | ||
} | ||
if (!oldValue) { | ||
return !Array.isArray(option) ? [option] : [].concat(option); | ||
} | ||
var values = !Array.isArray(oldValue) ? [oldValue] : [].concat(oldValue); // eslint-disable-next-line eqeqeq | ||
var valueIndex = values.findIndex(function (v) { | ||
return v.value == option.value; | ||
}); | ||
if (valueIndex >= 0) { | ||
values.splice(valueIndex, 1); | ||
} else { | ||
values.push(option); | ||
} | ||
return values; | ||
} |
@@ -6,8 +6,4 @@ "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 _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 _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
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 groupOptions(options) { | ||
@@ -17,3 +13,3 @@ var nextOptions = []; | ||
if ('groupId' in option) { | ||
var nextOption = _objectSpread({}, option); | ||
var nextOption = _extends({}, option); | ||
@@ -20,0 +16,0 @@ var groupIndex = nextOptions.findIndex(function (el) { |
@@ -6,4 +6,6 @@ "use strict"; | ||
var _react = _interopRequireWildcard(require("react")); | ||
var _jsxRuntime = require("react/jsx-runtime"); | ||
var _react = require("react"); | ||
var _propTypes = _interopRequireDefault(require("prop-types")); | ||
@@ -15,21 +17,15 @@ | ||
var _Option = _interopRequireDefault(require("./Components/Option")); | ||
var _Options = _interopRequireDefault(require("./Components/Options")); | ||
var _isSelected = _interopRequireDefault(require("./lib/isSelected")); | ||
var _useClassName = _interopRequireDefault(require("./useClassName")); | ||
var _classes2 = _interopRequireDefault(require("./lib/classes")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } | ||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } | ||
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; } | ||
var SelectSearch = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) { | ||
var _classes; | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
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; } | ||
var SelectSearch = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) { | ||
var defaultValue = _ref.value, | ||
@@ -45,2 +41,4 @@ disabled = _ref.disabled, | ||
onChange = _ref.onChange, | ||
onFocus = _ref.onFocus, | ||
onBlur = _ref.onBlur, | ||
printOptions = _ref.printOptions, | ||
@@ -53,18 +51,22 @@ closeOnSelect = _ref.closeOnSelect, | ||
getOptions = _ref.getOptions, | ||
filterOptions = _ref.filterOptions, | ||
debounce = _ref.debounce, | ||
fuse = _ref.fuse, | ||
emptyMessage = _ref.emptyMessage; | ||
var selectRef = (0, _react.useRef)(null); | ||
var cls = (0, _useClassName["default"])(className); | ||
var _useSelect = (0, _useSelect2["default"])({ | ||
options: defaultOptions, | ||
value: defaultValue, | ||
value: defaultValue === null && (placeholder || multiple) ? '' : defaultValue, | ||
multiple: multiple, | ||
disabled: disabled, | ||
fuse: fuse, | ||
search: search, | ||
onChange: onChange, | ||
onFocus: onFocus, | ||
onBlur: onBlur, | ||
closeOnSelect: closeOnSelect && (!multiple || ['on-focus', 'always'].includes(printOptions)), | ||
getOptions: getOptions, | ||
closeOnSelect: closeOnSelect, | ||
closable: !multiple || printOptions === 'on-focus', | ||
allowEmpty: !!placeholder | ||
filterOptions: filterOptions, | ||
fuse: fuse, | ||
debounce: debounce | ||
}), | ||
@@ -75,54 +77,3 @@ snapshot = _useSelect[0], | ||
var focus = snapshot.focus, | ||
highlighted = snapshot.highlighted, | ||
value = snapshot.value, | ||
options = snapshot.options, | ||
searching = snapshot.searching, | ||
displayValue = snapshot.displayValue, | ||
searchValue = snapshot.search; | ||
var cls = (0, _react.useCallback)(function (key) { | ||
if (typeof className === 'function') { | ||
return className(key); | ||
} | ||
if (key.indexOf('container') === 0) { | ||
return key.replace('container', className); | ||
} | ||
if (key.indexOf('is-') === 0 || key.indexOf('has-') === 0) { | ||
return key; | ||
} | ||
return className.split(' ')[0] + "__" + key; | ||
}, [className]); | ||
var renderEmptyMessage = (0, _react.useCallback)(function () { | ||
if (emptyMessage === null) { | ||
return null; | ||
} | ||
var content = typeof emptyMessage === 'function' ? emptyMessage() : emptyMessage; | ||
return /*#__PURE__*/_react["default"].createElement("li", { | ||
className: cls('not-found') | ||
}, content); | ||
}, [emptyMessage, cls]); | ||
var wrapperClass = [cls('container'), disabled ? cls('is-disabled') : false, searching ? cls('is-loading') : false, focus ? cls('has-focus') : false].filter(function (single) { | ||
return !!single; | ||
}).join(' '); | ||
var inputValue = focus && search ? searchValue : displayValue; | ||
(0, _react.useEffect)(function () { | ||
var current = selectRef.current; | ||
if (!current || multiple || highlighted < 0 && !value) { | ||
return; | ||
} | ||
var query = highlighted > -1 ? "[data-index=\"" + highlighted + "\"]" : "[data-value=\"" + escape(value.value) + "\"]"; | ||
var selected = current.querySelector(query); | ||
if (selected) { | ||
var rect = current.getBoundingClientRect(); | ||
var selectedRect = selected.getBoundingClientRect(); | ||
current.scrollTop = selected.offsetTop - rect.height / 2 + selectedRect.height / 2; | ||
} | ||
}, [focus, value, highlighted, selectRef, multiple]); | ||
var wrapperClass = (0, _classes2["default"])((_classes = {}, _classes[cls('container')] = true, _classes[cls('is-disabled')] = disabled, _classes[cls('is-loading')] = snapshot.fetching, _classes[cls('has-focus')] = snapshot.focus, _classes)); | ||
var shouldRenderOptions; | ||
@@ -140,93 +91,51 @@ | ||
case 'on-focus': | ||
shouldRenderOptions = focus; | ||
shouldRenderOptions = snapshot.focus; | ||
break; | ||
default: | ||
shouldRenderOptions = !disabled && (focus || multiple); | ||
shouldRenderOptions = !disabled && (snapshot.focus || multiple); | ||
break; | ||
} | ||
return /*#__PURE__*/_react["default"].createElement("div", { | ||
ref: ref, | ||
className: wrapperClass, | ||
id: id | ||
}, (!multiple || placeholder || search) && /*#__PURE__*/_react["default"].createElement("div", { | ||
className: cls('value') | ||
}, renderValue(_objectSpread(_objectSpread({}, valueProps), {}, { | ||
var shouldRenderValue = !multiple || placeholder || search; | ||
var props = _extends({}, valueProps, { | ||
placeholder: placeholder, | ||
autoFocus: autoFocus, | ||
autoComplete: autoComplete, | ||
value: inputValue | ||
}), snapshot, cls('input'))), shouldRenderOptions && /*#__PURE__*/_react["default"].createElement("div", { | ||
className: cls('select'), | ||
ref: selectRef, | ||
onMouseDown: function onMouseDown(e) { | ||
return e.preventDefault(); | ||
} | ||
}, /*#__PURE__*/_react["default"].createElement("ul", { | ||
className: cls('options') | ||
}, options.length > 0 ? options.map(function (option) { | ||
var isGroup = option.type === 'group'; | ||
var items = isGroup ? option.items : [option]; | ||
var base = { | ||
value: snapshot.focus && search ? snapshot.search : snapshot.displayValue | ||
}); | ||
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", { | ||
ref: ref, | ||
className: wrapperClass, | ||
id: id, | ||
children: [shouldRenderValue && /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", { | ||
className: cls('value'), | ||
children: [renderValue && renderValue(props, snapshot, cls('input')), !renderValue && /*#__PURE__*/(0, _jsxRuntime.jsx)("input", _extends({}, props, { | ||
className: cls('input') | ||
}))] | ||
}), shouldRenderOptions && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Options["default"], { | ||
options: snapshot.options, | ||
optionProps: optionProps, | ||
snapshot: snapshot, | ||
cls: cls, | ||
optionProps: optionProps, | ||
renderOption: renderOption | ||
}; | ||
var rendered = items.map(function (o) { | ||
return /*#__PURE__*/_react["default"].createElement(_Option["default"], _extends({ | ||
key: o.value, | ||
selected: (0, _isSelected["default"])(o, value), | ||
highlighted: highlighted === o.index | ||
}, base, o)); | ||
}); | ||
if (isGroup) { | ||
return /*#__PURE__*/_react["default"].createElement("li", { | ||
role: "none", | ||
className: cls('row'), | ||
key: option.groupId | ||
}, /*#__PURE__*/_react["default"].createElement("div", { | ||
className: cls('group') | ||
}, /*#__PURE__*/_react["default"].createElement("div", { | ||
className: cls('group-header') | ||
}, renderGroupHeader(option.name)), /*#__PURE__*/_react["default"].createElement("ul", { | ||
className: cls('options') | ||
}, rendered))); | ||
} | ||
return rendered; | ||
}) : renderEmptyMessage() || null))); | ||
emptyMessage: emptyMessage, | ||
renderOption: renderOption, | ||
renderGroupHeader: renderGroupHeader | ||
})] | ||
}); | ||
}); | ||
SelectSearch.defaultProps = { | ||
className: 'select-search', | ||
// Data | ||
getOptions: null, | ||
filterOptions: null, | ||
value: null, | ||
// Interaction | ||
multiple: false, | ||
search: false, | ||
disabled: false, | ||
search: false, | ||
multiple: false, | ||
placeholder: null, | ||
id: null, | ||
autoFocus: false, | ||
autoComplete: 'on', | ||
value: '', | ||
onChange: function onChange() {}, | ||
printOptions: 'auto', | ||
closeOnSelect: true, | ||
renderOption: function renderOption(domProps, option, snapshot, className) { | ||
return ( | ||
/*#__PURE__*/ | ||
// eslint-disable-next-line react/button-has-type | ||
_react["default"].createElement("button", _extends({ | ||
type: "button", | ||
className: className | ||
}, domProps), option.name) | ||
); | ||
}, | ||
renderGroupHeader: function renderGroupHeader(name) { | ||
return name; | ||
}, | ||
renderValue: function renderValue(valueProps, snapshot, className) { | ||
return /*#__PURE__*/_react["default"].createElement("input", _extends({}, valueProps, { | ||
className: className | ||
})); | ||
}, | ||
debounce: 0, | ||
fuse: { | ||
@@ -236,13 +145,37 @@ keys: ['name', 'groupName'], | ||
}, | ||
getOptions: null, | ||
emptyMessage: null | ||
// Attributes | ||
placeholder: null, | ||
id: null, | ||
autoFocus: false, | ||
autoComplete: 'on', | ||
// Design | ||
className: 'select-search', | ||
// Renderers | ||
renderOption: undefined, | ||
renderGroupHeader: undefined, | ||
renderValue: undefined, | ||
emptyMessage: null, | ||
// Events | ||
onChange: function onChange() {}, | ||
onFocus: function onFocus() {}, | ||
onBlur: function onBlur() {} | ||
}; | ||
SelectSearch.propTypes = process.env.NODE_ENV !== "production" ? { | ||
// Data | ||
options: _propTypes["default"].arrayOf(_types.optionType).isRequired, | ||
getOptions: _propTypes["default"].func, | ||
value: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number, _propTypes["default"].arrayOf(_propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]))]), | ||
className: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].func]), | ||
filterOptions: _propTypes["default"].func, | ||
value: _types.valueType, | ||
// Interaction | ||
multiple: _propTypes["default"].bool, | ||
search: _propTypes["default"].bool, | ||
disabled: _propTypes["default"].bool, | ||
printOptions: _propTypes["default"].oneOf(['auto', 'always', 'never', 'on-focus']), | ||
closeOnSelect: _propTypes["default"].bool, | ||
debounce: _propTypes["default"].number, | ||
fuse: _propTypes["default"].oneOfType([_propTypes["default"].bool, _propTypes["default"].shape({ | ||
keys: _propTypes["default"].arrayOf(_propTypes["default"].string), | ||
threshold: _propTypes["default"].number | ||
})]), | ||
// Attributes | ||
placeholder: _propTypes["default"].string, | ||
@@ -252,13 +185,13 @@ id: _propTypes["default"].string, | ||
autoFocus: _propTypes["default"].bool, | ||
onChange: _propTypes["default"].func, | ||
printOptions: _propTypes["default"].oneOf(['auto', 'always', 'never', 'on-focus']), | ||
closeOnSelect: _propTypes["default"].bool, | ||
// Design | ||
className: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].func]), | ||
// Renderers | ||
renderOption: _propTypes["default"].func, | ||
renderGroupHeader: _propTypes["default"].func, | ||
renderValue: _propTypes["default"].func, | ||
fuse: _propTypes["default"].oneOfType([_propTypes["default"].bool, _propTypes["default"].shape({ | ||
keys: _propTypes["default"].arrayOf(_propTypes["default"].string), | ||
threshold: _propTypes["default"].number | ||
})]), | ||
emptyMessage: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].func]) | ||
emptyMessage: _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].func]), | ||
// Events | ||
onChange: _propTypes["default"].func, | ||
onFocus: _propTypes["default"].func, | ||
onBlur: _propTypes["default"].func | ||
} : {}; | ||
@@ -265,0 +198,0 @@ |
"use strict"; | ||
exports.__esModule = true; | ||
exports.classNameType = exports.valueType = exports.optionType = void 0; | ||
exports.valueType = exports.optionType = void 0; | ||
@@ -23,8 +23,4 @@ var _propTypes = _interopRequireDefault(require("prop-types")); | ||
var valueType = _propTypes["default"].oneOfType([_propTypes["default"].object, _propTypes["default"].arrayOf(_propTypes["default"].object)]); | ||
var valueType = _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number, _propTypes["default"].arrayOf(_propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].number]))]); | ||
exports.valueType = valueType; | ||
var classNameType = _propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].func]); | ||
exports.classNameType = classNameType; | ||
exports.valueType = valueType; |
@@ -8,23 +8,17 @@ "use strict"; | ||
var _highlightReducer = _interopRequireDefault(require("./highlightReducer")); | ||
var _getDisplayValue = _interopRequireDefault(require("./lib/getDisplayValue")); | ||
var _flattenOptions = _interopRequireDefault(require("./lib/flattenOptions")); | ||
var _groupOptions = _interopRequireDefault(require("./lib/groupOptions")); | ||
var _getNewValue = _interopRequireDefault(require("./lib/getNewValue")); | ||
var _highlightReducer = _interopRequireDefault(require("./highlightReducer")); | ||
var _getOption = _interopRequireDefault(require("./lib/getOption")); | ||
var _search = _interopRequireDefault(require("./search")); | ||
var _getDisplayValue = _interopRequireDefault(require("./lib/getDisplayValue")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
var _useFilter = _interopRequireDefault(require("./useFilter")); | ||
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; } | ||
var _useFetch2 = _interopRequireDefault(require("./useFetch")); | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
var _getValue = _interopRequireDefault(require("./lib/getValue")); | ||
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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
@@ -34,258 +28,153 @@ function useSelect(_ref) { | ||
defaultValue = _ref$value === void 0 ? null : _ref$value, | ||
_ref$options = _ref.options, | ||
defaultOptions = _ref$options === void 0 ? [] : _ref$options, | ||
_ref$search = _ref.search, | ||
canSearch = _ref$search === void 0 ? false : _ref$search, | ||
_ref$multiple = _ref.multiple, | ||
multiple = _ref$multiple === void 0 ? false : _ref$multiple, | ||
_ref$disabled = _ref.disabled, | ||
disabled = _ref$disabled === void 0 ? false : _ref$disabled, | ||
_ref$multiple = _ref.multiple, | ||
multiple = _ref$multiple === void 0 ? false : _ref$multiple, | ||
_ref$search = _ref.search, | ||
canSearch = _ref$search === void 0 ? false : _ref$search, | ||
_ref$closeOnSelect = _ref.closeOnSelect, | ||
closeOnSelect = _ref$closeOnSelect === void 0 ? true : _ref$closeOnSelect, | ||
_ref$getOptions = _ref.getOptions, | ||
getOptions = _ref$getOptions === void 0 ? null : _ref$getOptions, | ||
_ref$filterOptions = _ref.filterOptions, | ||
filterOptions = _ref$filterOptions === void 0 ? null : _ref$filterOptions, | ||
_ref$fuse = _ref.fuse, | ||
fuse = _ref$fuse === void 0 ? false : _ref$fuse, | ||
defaultOptions = _ref.options, | ||
_ref$onChange = _ref.onChange, | ||
onChange = _ref$onChange === void 0 ? function () {} : _ref$onChange, | ||
_ref$getOptions = _ref.getOptions, | ||
getOptions = _ref$getOptions === void 0 ? null : _ref$getOptions, | ||
_ref$allowEmpty = _ref.allowEmpty, | ||
allowEmpty = _ref$allowEmpty === void 0 ? true : _ref$allowEmpty, | ||
_ref$closeOnSelect = _ref.closeOnSelect, | ||
closeOnSelect = _ref$closeOnSelect === void 0 ? true : _ref$closeOnSelect, | ||
_ref$closable = _ref.closable, | ||
closable = _ref$closable === void 0 ? true : _ref$closable; | ||
_ref$onFocus = _ref.onFocus, | ||
_onFocus = _ref$onFocus === void 0 ? function () {} : _ref$onFocus, | ||
_ref$onBlur = _ref.onBlur, | ||
_onBlur = _ref$onBlur === void 0 ? function () {} : _ref$onBlur, | ||
_ref$debounce = _ref.debounce, | ||
debounce = _ref$debounce === void 0 ? 0 : _ref$debounce; | ||
var ref = (0, _react.useRef)(null); | ||
var flatDefaultOptions = (0, _react.useMemo)(function () { | ||
return (0, _flattenOptions["default"])(defaultOptions); | ||
}, [defaultOptions]); | ||
var valueRef = (0, _react.useRef)(undefined); | ||
var _useState = (0, _react.useState)({ | ||
flat: [], | ||
addedOptions: [], | ||
value: defaultValue, | ||
search: '', | ||
focus: false, | ||
searching: false, | ||
highlighted: -1, | ||
changed: false | ||
}), | ||
state = _useState[0], | ||
setState = _useState[1]; | ||
var _useState = (0, _react.useState)(null), | ||
value = _useState[0], | ||
setValue = _useState[1]; | ||
var flat = state.flat, | ||
addedOptions = state.addedOptions, | ||
value = state.value, | ||
search = state.search, | ||
focus = state.focus, | ||
searching = state.searching, | ||
highlighted = state.highlighted; | ||
var option = (0, _react.useMemo)(function () { | ||
var newOption = (0, _getOption["default"])(value, [].concat(flatDefaultOptions, addedOptions)); | ||
var _useState2 = (0, _react.useState)(''), | ||
search = _useState2[0], | ||
setSearch = _useState2[1]; | ||
if (!newOption && !allowEmpty && !multiple) { | ||
newOption = flatDefaultOptions[0]; | ||
} | ||
var _useState3 = (0, _react.useState)(false), | ||
focus = _useState3[0], | ||
setFocus = _useState3[1]; | ||
return newOption; | ||
}, [value, flatDefaultOptions, addedOptions, allowEmpty, multiple]); | ||
var options = (0, _react.useMemo)(function () { | ||
return (0, _groupOptions["default"])(flat); | ||
}, [flat]); | ||
var displayValue = (0, _react.useMemo)(function () { | ||
return (0, _getDisplayValue["default"])(option); | ||
}, [option]); | ||
var onBlur = (0, _react.useCallback)(function () { | ||
setState(function (oldState) { | ||
return _objectSpread(_objectSpread({}, oldState), {}, { | ||
focus: false, | ||
search: '', | ||
flat: flatDefaultOptions, | ||
highlighted: -1 | ||
}); | ||
}); | ||
var _useReducer = (0, _react.useReducer)(_highlightReducer["default"], -1), | ||
highlighted = _useReducer[0], | ||
dispatchHighlighted = _useReducer[1]; | ||
if (ref.current) { | ||
ref.current.blur(); | ||
} | ||
}, [flatDefaultOptions, ref]); | ||
var filter = (0, _useFilter["default"])(filterOptions, fuse); | ||
var setFocus = function setFocus(newFocus) { | ||
return setState(function (oldState) { | ||
return _objectSpread(_objectSpread({}, oldState), {}, { | ||
focus: newFocus | ||
}); | ||
}); | ||
}; | ||
var _useFetch = (0, _useFetch2["default"])(search, defaultOptions, { | ||
getOptions: getOptions, | ||
filter: filter, | ||
debounceTime: debounce | ||
}), | ||
options = _useFetch.options, | ||
fetching = _useFetch.fetching; | ||
var onClick = function onClick() { | ||
return setFocus(!focus); | ||
}; | ||
var snapshot = (0, _react.useMemo)(function () { | ||
return { | ||
options: (0, _groupOptions["default"])(options), | ||
option: value, | ||
displayValue: (0, _getDisplayValue["default"])(value), | ||
value: (0, _getValue["default"])(value), | ||
search: search, | ||
fetching: fetching, | ||
focus: focus, | ||
highlighted: highlighted, | ||
disabled: disabled | ||
}; | ||
}, [disabled, fetching, focus, options, highlighted, search, value]); | ||
var onSelect = (0, _react.useCallback)(function (newValue) { | ||
var newOption = (0, _getOption["default"])(newValue, value, Array.isArray(value) ? [].concat(value, options) : options, multiple); | ||
setValue(newOption); | ||
onChange((0, _getValue["default"])(newOption), newOption); | ||
var onFocus = function onFocus() { | ||
return setFocus(true); | ||
}; | ||
var onSelect = (0, _react.useCallback)(function (id) { | ||
setState(function (prevState) { | ||
var prevFlat = prevState.flat, | ||
prevHighlighted = prevState.highlighted; // eslint-disable-next-line no-underscore-dangle,eqeqeq | ||
var item = id ? prevFlat.find(function (i) { | ||
return i.value == id; | ||
}) : prevFlat[prevHighlighted]; | ||
if (!item) { | ||
return prevState; | ||
} | ||
var values = (0, _getNewValue["default"])(item.value, prevState.value, multiple); | ||
var newOptions = (0, _getOption["default"])(values, prevFlat); | ||
return _objectSpread(_objectSpread({}, prevState), {}, { | ||
addedOptions: multiple ? newOptions : [newOptions], | ||
value: values, | ||
changed: [values, newOptions] | ||
}); | ||
}); | ||
}, [multiple]); | ||
if (closeOnSelect) { | ||
ref.current.blur(); | ||
} | ||
}, [closeOnSelect, multiple, onChange, value, options]); | ||
var onMouseDown = (0, _react.useCallback)(function (e) { | ||
e.preventDefault(); | ||
if (closeOnSelect && ref.current) { | ||
ref.current.blur(); | ||
} | ||
onSelect(e.currentTarget.value); | ||
}, [onSelect, closeOnSelect]); | ||
}, [onSelect]); | ||
var onKeyDown = (0, _react.useCallback)(function (e) { | ||
var key = e.key; | ||
if (key === 'ArrowDown' || key === 'ArrowUp') { | ||
if (['ArrowDown', 'ArrowUp'].includes(key)) { | ||
e.preventDefault(); | ||
setState(function (oldState) { | ||
return _objectSpread(_objectSpread({}, oldState), {}, { | ||
highlighted: (0, _highlightReducer["default"])(oldState.highlighted, { | ||
key: key, | ||
options: oldState.flat | ||
}) | ||
}); | ||
dispatchHighlighted({ | ||
key: key, | ||
options: options | ||
}); | ||
} | ||
}, []); | ||
var onKeyPress = (0, _react.useCallback)(function (_ref2) { | ||
var key = _ref2.key; | ||
}, [options]); | ||
var onKeyPress = (0, _react.useCallback)(function (e) { | ||
if (e.key === 'Enter') { | ||
e.preventDefault(); | ||
var selected = options[highlighted]; | ||
if (key === 'Enter') { | ||
onSelect(); | ||
if (selected) { | ||
onSelect(selected.value); | ||
} | ||
if (closable && closeOnSelect) { | ||
onBlur(); | ||
if (closeOnSelect) { | ||
ref.current.blur(); | ||
} | ||
} | ||
}, [onSelect, closeOnSelect, onBlur, closable]); | ||
var onKeyUp = (0, _react.useCallback)(function (_ref3) { | ||
var key = _ref3.key; | ||
}, [options, highlighted, closeOnSelect, onSelect]); | ||
var valueProps = (0, _react.useMemo)(function () { | ||
return { | ||
tabIndex: '0', | ||
readOnly: !canSearch, | ||
onFocus: function onFocus(e) { | ||
setFocus(true); | ||
if (key === 'Escape') { | ||
onBlur(); | ||
} | ||
}, [onBlur]); | ||
_onFocus(e); | ||
}, | ||
onBlur: function onBlur(e) { | ||
setFocus(false); | ||
setSearch(''); | ||
var onSearch = function onSearch(_ref4) { | ||
var target = _ref4.target; | ||
var inputVal = target.value; | ||
var newState = { | ||
search: inputVal | ||
_onBlur(e); | ||
}, | ||
onKeyPress: onKeyPress, | ||
onKeyDown: onKeyDown, | ||
onKeyUp: function onKeyUp(e) { | ||
if (e.key === 'Escape') { | ||
e.preventDefault(); | ||
ref.current.blur(); | ||
} | ||
}, | ||
onChange: canSearch ? function (_ref2) { | ||
var target = _ref2.target; | ||
return setSearch(target.value); | ||
} : null, | ||
disabled: disabled, | ||
ref: ref | ||
}; | ||
var searchableOption = flatDefaultOptions; | ||
if (getOptions && inputVal.length) { | ||
newState.searching = true; | ||
searchableOption = getOptions(inputVal); | ||
} | ||
setState(function (oldState) { | ||
return _objectSpread(_objectSpread({}, oldState), newState); | ||
}); | ||
Promise.resolve(searchableOption).then(function (foundOptions) { | ||
var newOptions = foundOptions; | ||
if (inputVal.length) { | ||
newOptions = (0, _search["default"])(inputVal, foundOptions, fuse); | ||
} | ||
setState(function (oldState) { | ||
return _objectSpread(_objectSpread({}, oldState), {}, { | ||
flat: newOptions === false ? foundOptions : newOptions, | ||
searching: false | ||
}); | ||
}); | ||
})["catch"](function () { | ||
return setState(function (oldState) { | ||
return _objectSpread(_objectSpread({}, oldState), {}, { | ||
flat: flatDefaultOptions, | ||
searching: false | ||
}); | ||
}); | ||
}); | ||
}; | ||
var valueProps = { | ||
tabIndex: '0', | ||
readOnly: !canSearch, | ||
onChange: canSearch ? onSearch : null, | ||
disabled: disabled, | ||
onMouseDown: onClick, | ||
onBlur: onBlur, | ||
onFocus: onFocus, | ||
onKeyPress: onKeyPress, | ||
onKeyDown: onKeyDown, | ||
onKeyUp: onKeyUp, | ||
ref: ref | ||
}; | ||
}, [canSearch, _onFocus, _onBlur, onKeyPress, onKeyDown, disabled, ref]); | ||
var optionProps = (0, _react.useMemo)(function () { | ||
return { | ||
tabIndex: '-1', | ||
onMouseDown: onMouseDown, | ||
onKeyDown: onKeyDown, | ||
onKeyPress: onKeyPress, | ||
onBlur: onBlur | ||
onMouseDown: onMouseDown | ||
}; | ||
}, [onMouseDown, onKeyDown, onKeyPress, onBlur]); | ||
}, [onMouseDown]); | ||
(0, _react.useEffect)(function () { | ||
setState(function (oldState) { | ||
return _objectSpread(_objectSpread({}, oldState), {}, { | ||
value: defaultValue | ||
}); | ||
}); | ||
}, [defaultValue]); | ||
(0, _react.useEffect)(function () { | ||
setState(function (oldState) { | ||
return _objectSpread(_objectSpread({}, oldState), {}, { | ||
flat: flatDefaultOptions | ||
}); | ||
}); | ||
}, [flatDefaultOptions]); | ||
(0, _react.useEffect)(function () { | ||
if (state.changed !== false) { | ||
setState(function (oldState) { | ||
return _objectSpread(_objectSpread({}, oldState), {}, { | ||
changed: false | ||
}); | ||
}); | ||
onChange.apply(void 0, state.changed); | ||
if (valueRef.current === defaultValue) { | ||
return; | ||
} | ||
}, [state.changed, onChange]); | ||
return [{ | ||
value: option, | ||
highlighted: highlighted, | ||
options: options, | ||
disabled: disabled, | ||
displayValue: displayValue, | ||
focus: focus, | ||
search: search, | ||
searching: searching | ||
}, valueProps, optionProps, function (newValue) { | ||
return setState(function (oldState) { | ||
return _objectSpread(_objectSpread({}, oldState), {}, { | ||
value: newValue | ||
}); | ||
}); | ||
}]; | ||
valueRef.current = defaultValue; | ||
setValue((0, _getOption["default"])(defaultValue, null, options, multiple)); | ||
}, [defaultValue, multiple, options]); | ||
return [snapshot, valueProps, optionProps, setValue]; | ||
} |
@@ -1,27 +0,19 @@ | ||
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; } | ||
import { jsx as _jsx } from "react/jsx-runtime"; | ||
import { jsxs as _jsxs } from "react/jsx-runtime"; | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
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 _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 _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } | ||
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } | ||
import React, { memo } from 'react'; | ||
import { memo } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import classes from '../lib/classes'; | ||
const Option = (_ref) => { | ||
let { | ||
optionProps, | ||
highlighted, | ||
selected, | ||
cls, | ||
renderOption | ||
} = _ref, | ||
option = _objectWithoutProperties(_ref, ["optionProps", "highlighted", "selected", "cls", "renderOption"]); | ||
const optionClass = [cls('option'), selected ? cls('is-selected') : false, highlighted ? cls('is-highlighted') : false].filter(single => !!single).join(' '); | ||
const domProps = _objectSpread(_objectSpread({}, optionProps), {}, { | ||
const Option = ({ | ||
optionProps, | ||
highlighted, | ||
selected, | ||
option, | ||
cls, | ||
renderOption | ||
}) => { | ||
const props = _extends({}, optionProps, { | ||
value: option.value, | ||
@@ -31,3 +23,8 @@ disabled: option.disabled | ||
return /*#__PURE__*/React.createElement("li", { | ||
const className = classes({ | ||
[cls('option')]: true, | ||
[cls('is-selected')]: selected, | ||
[cls('is-highlighted')]: highlighted | ||
}); | ||
return /*#__PURE__*/_jsxs("li", { | ||
className: cls('row'), | ||
@@ -37,19 +34,24 @@ role: "menuitem", | ||
"data-value": escape(option.value), | ||
key: option.value | ||
}, renderOption(domProps, option, { | ||
selected, | ||
highlighted | ||
}, optionClass)); | ||
children: [renderOption && renderOption(props, option, { | ||
selected, | ||
highlighted | ||
}, className), !renderOption && /*#__PURE__*/_jsx("button", _extends({ | ||
type: "button", | ||
className: className | ||
}, props, { | ||
children: option.name | ||
}))] | ||
}, option.value); | ||
}; | ||
Option.defaultProps = { | ||
disabled: false, | ||
index: null, | ||
value: null | ||
renderOption: null | ||
}; | ||
Option.propTypes = process.env.NODE_ENV !== "production" ? { | ||
name: PropTypes.string.isRequired, | ||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), | ||
disabled: PropTypes.bool, | ||
index: PropTypes.number, | ||
option: PropTypes.shape({ | ||
name: PropTypes.string.isRequired, | ||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), | ||
disabled: PropTypes.bool, | ||
index: PropTypes.number | ||
}).isRequired, | ||
highlighted: PropTypes.bool.isRequired, | ||
@@ -62,4 +64,4 @@ selected: PropTypes.bool.isRequired, | ||
cls: PropTypes.func.isRequired, | ||
renderOption: PropTypes.func.isRequired | ||
renderOption: PropTypes.func | ||
} : {}; | ||
export default /*#__PURE__*/memo(Option); |
@@ -1,6 +0,5 @@ | ||
export default function highlightReducer(highlighted, value) { | ||
const { | ||
key, | ||
options | ||
} = value; | ||
export default function highlightReducer(highlighted, { | ||
key, | ||
options | ||
}) { | ||
const max = options.length - 1; | ||
@@ -7,0 +6,0 @@ let newHighlighted = key === 'ArrowDown' ? highlighted + 1 : highlighted - 1; |
@@ -1,7 +0,3 @@ | ||
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 _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 _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
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; } | ||
export default function flattenOptions(options) { | ||
@@ -17,6 +13,5 @@ if (!Array.isArray(options)) { | ||
option.items.forEach(groupOption => { | ||
nextOptions.push(_objectSpread(_objectSpread({}, groupOption), {}, { | ||
nextOptions.push(_extends({}, groupOption, { | ||
groupId: id, | ||
groupName: option.name, | ||
_id: "" + groupOption.value | ||
groupName: option.name | ||
})); | ||
@@ -27,4 +22,3 @@ }); | ||
nextOptions.push(_objectSpread(_objectSpread({}, option), {}, { | ||
_id: "" + option.value, | ||
nextOptions.push(_extends({}, option, { | ||
index | ||
@@ -31,0 +25,0 @@ })); |
@@ -1,20 +0,27 @@ | ||
export default function getNewValue(value, oldValue, multiple) { | ||
export default function getNewValue(value, oldValue, options, multiple) { | ||
const newValue = value === null && options.length ? options[0].value : value; | ||
if (!multiple) { | ||
return value; | ||
return newValue; | ||
} | ||
if (!newValue) { | ||
return []; | ||
} | ||
if (!oldValue) { | ||
return [value]; | ||
return !Array.isArray(newValue) ? [newValue] : [...newValue]; | ||
} | ||
const newValue = !Array.isArray(oldValue) ? [oldValue] : [...oldValue]; | ||
const valueIndex = newValue.findIndex(val => val === value); | ||
const newArrayValue = !Array.isArray(oldValue) ? [oldValue] : [...oldValue]; // eslint-disable-next-line eqeqeq | ||
const valueIndex = newArrayValue.findIndex(val => val == newValue); | ||
if (valueIndex >= 0) { | ||
newValue.splice(valueIndex, 1); | ||
newArrayValue.splice(valueIndex, 1); | ||
} else { | ||
newValue.push(value); | ||
newArrayValue.push(value); | ||
} | ||
return newValue; | ||
return newArrayValue; | ||
} |
@@ -1,7 +0,31 @@ | ||
export default function getOption(value, defaultOptions) { | ||
if (Array.isArray(value)) { | ||
return value.map(singleValue => defaultOptions.find(option => option.value === singleValue)); | ||
export default function getOption(value, oldValue, options, multiple) { | ||
const newValue = value === null && options.length ? options[0].value : value; // eslint-disable-next-line eqeqeq | ||
const f = ref => options.find(o => o.value == ref); | ||
const option = Array.isArray(value) ? newValue.map(v => f(v)) : f(newValue); | ||
if (!multiple) { | ||
return option || oldValue; | ||
} | ||
return defaultOptions.find(option => option.value === value) || null; | ||
if (!option) { | ||
return oldValue; | ||
} | ||
if (!oldValue) { | ||
return !Array.isArray(option) ? [option] : [...option]; | ||
} | ||
const values = !Array.isArray(oldValue) ? [oldValue] : [...oldValue]; // eslint-disable-next-line eqeqeq | ||
const valueIndex = values.findIndex(v => v.value == option.value); | ||
if (valueIndex >= 0) { | ||
values.splice(valueIndex, 1); | ||
} else { | ||
values.push(option); | ||
} | ||
return values; | ||
} |
@@ -1,7 +0,3 @@ | ||
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 _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 _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
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; } | ||
export default function groupOptions(options) { | ||
@@ -11,3 +7,3 @@ const nextOptions = []; | ||
if ('groupId' in option) { | ||
const nextOption = _objectSpread({}, option); | ||
const nextOption = _extends({}, option); | ||
@@ -14,0 +10,0 @@ const groupIndex = nextOptions.findIndex(el => 'groupId' in el && el.groupId === nextOption.groupId); |
@@ -0,15 +1,13 @@ | ||
import { jsx as _jsx } from "react/jsx-runtime"; | ||
import { jsxs as _jsxs } from "react/jsx-runtime"; | ||
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(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
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; } | ||
import React, { forwardRef, memo, useRef, useEffect, useCallback } from 'react'; | ||
import { forwardRef, memo } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import useSelect from './useSelect'; | ||
import { optionType } from './types'; | ||
import Option from './Components/Option'; | ||
import isSelected from './lib/isSelected'; | ||
import { optionType, valueType } from './types'; | ||
import Options from './Components/Options'; | ||
import useClassName from './useClassName'; | ||
import classes from './lib/classes'; | ||
const SelectSearch = /*#__PURE__*/forwardRef(({ | ||
@@ -26,2 +24,4 @@ value: defaultValue, | ||
onChange, | ||
onFocus, | ||
onBlur, | ||
printOptions, | ||
@@ -34,73 +34,29 @@ closeOnSelect, | ||
getOptions, | ||
filterOptions, | ||
debounce, | ||
fuse, | ||
emptyMessage | ||
}, ref) => { | ||
const selectRef = useRef(null); | ||
const cls = useClassName(className); | ||
const [snapshot, valueProps, optionProps] = useSelect({ | ||
options: defaultOptions, | ||
value: defaultValue, | ||
value: defaultValue === null && (placeholder || multiple) ? '' : defaultValue, | ||
multiple, | ||
disabled, | ||
fuse, | ||
search, | ||
onChange, | ||
onFocus, | ||
onBlur, | ||
closeOnSelect: closeOnSelect && (!multiple || ['on-focus', 'always'].includes(printOptions)), | ||
getOptions, | ||
closeOnSelect, | ||
closable: !multiple || printOptions === 'on-focus', | ||
allowEmpty: !!placeholder | ||
filterOptions, | ||
fuse, | ||
debounce | ||
}); | ||
const { | ||
focus, | ||
highlighted, | ||
value, | ||
options, | ||
searching, | ||
displayValue, | ||
search: searchValue | ||
} = snapshot; | ||
const cls = useCallback(key => { | ||
if (typeof className === 'function') { | ||
return className(key); | ||
} | ||
if (key.indexOf('container') === 0) { | ||
return key.replace('container', className); | ||
} | ||
if (key.indexOf('is-') === 0 || key.indexOf('has-') === 0) { | ||
return key; | ||
} | ||
return className.split(' ')[0] + "__" + key; | ||
}, [className]); | ||
const renderEmptyMessage = useCallback(() => { | ||
if (emptyMessage === null) { | ||
return null; | ||
} | ||
const content = typeof emptyMessage === 'function' ? emptyMessage() : emptyMessage; | ||
return /*#__PURE__*/React.createElement("li", { | ||
className: cls('not-found') | ||
}, content); | ||
}, [emptyMessage, cls]); | ||
const wrapperClass = [cls('container'), disabled ? cls('is-disabled') : false, searching ? cls('is-loading') : false, focus ? cls('has-focus') : false].filter(single => !!single).join(' '); | ||
const inputValue = focus && search ? searchValue : displayValue; | ||
useEffect(() => { | ||
const { | ||
current | ||
} = selectRef; | ||
if (!current || multiple || highlighted < 0 && !value) { | ||
return; | ||
} | ||
const query = highlighted > -1 ? "[data-index=\"" + highlighted + "\"]" : "[data-value=\"" + escape(value.value) + "\"]"; | ||
const selected = current.querySelector(query); | ||
if (selected) { | ||
const rect = current.getBoundingClientRect(); | ||
const selectedRect = selected.getBoundingClientRect(); | ||
current.scrollTop = selected.offsetTop - rect.height / 2 + selectedRect.height / 2; | ||
} | ||
}, [focus, value, highlighted, selectRef, multiple]); | ||
const wrapperClass = classes({ | ||
[cls('container')]: true, | ||
[cls('is-disabled')]: disabled, | ||
[cls('is-loading')]: snapshot.fetching, | ||
[cls('has-focus')]: snapshot.focus | ||
}); | ||
let shouldRenderOptions; | ||
@@ -118,82 +74,51 @@ | ||
case 'on-focus': | ||
shouldRenderOptions = focus; | ||
shouldRenderOptions = snapshot.focus; | ||
break; | ||
default: | ||
shouldRenderOptions = !disabled && (focus || multiple); | ||
shouldRenderOptions = !disabled && (snapshot.focus || multiple); | ||
break; | ||
} | ||
return /*#__PURE__*/React.createElement("div", { | ||
ref: ref, | ||
className: wrapperClass, | ||
id: id | ||
}, (!multiple || placeholder || search) && /*#__PURE__*/React.createElement("div", { | ||
className: cls('value') | ||
}, renderValue(_objectSpread(_objectSpread({}, valueProps), {}, { | ||
const shouldRenderValue = !multiple || placeholder || search; | ||
const props = _extends({}, valueProps, { | ||
placeholder, | ||
autoFocus, | ||
autoComplete, | ||
value: inputValue | ||
}), snapshot, cls('input'))), shouldRenderOptions && /*#__PURE__*/React.createElement("div", { | ||
className: cls('select'), | ||
ref: selectRef, | ||
onMouseDown: e => e.preventDefault() | ||
}, /*#__PURE__*/React.createElement("ul", { | ||
className: cls('options') | ||
}, options.length > 0 ? options.map(option => { | ||
const isGroup = option.type === 'group'; | ||
const items = isGroup ? option.items : [option]; | ||
const base = { | ||
cls, | ||
optionProps, | ||
renderOption | ||
}; | ||
const rendered = items.map(o => /*#__PURE__*/React.createElement(Option, _extends({ | ||
key: o.value, | ||
selected: isSelected(o, value), | ||
highlighted: highlighted === o.index | ||
}, base, o))); | ||
value: snapshot.focus && search ? snapshot.search : snapshot.displayValue | ||
}); | ||
if (isGroup) { | ||
return /*#__PURE__*/React.createElement("li", { | ||
role: "none", | ||
className: cls('row'), | ||
key: option.groupId | ||
}, /*#__PURE__*/React.createElement("div", { | ||
className: cls('group') | ||
}, /*#__PURE__*/React.createElement("div", { | ||
className: cls('group-header') | ||
}, renderGroupHeader(option.name)), /*#__PURE__*/React.createElement("ul", { | ||
className: cls('options') | ||
}, rendered))); | ||
} | ||
return rendered; | ||
}) : renderEmptyMessage() || null))); | ||
return /*#__PURE__*/_jsxs("div", { | ||
ref: ref, | ||
className: wrapperClass, | ||
id: id, | ||
children: [shouldRenderValue && /*#__PURE__*/_jsxs("div", { | ||
className: cls('value'), | ||
children: [renderValue && renderValue(props, snapshot, cls('input')), !renderValue && /*#__PURE__*/_jsx("input", _extends({}, props, { | ||
className: cls('input') | ||
}))] | ||
}), shouldRenderOptions && /*#__PURE__*/_jsx(Options, { | ||
options: snapshot.options, | ||
optionProps: optionProps, | ||
snapshot: snapshot, | ||
cls: cls, | ||
emptyMessage: emptyMessage, | ||
renderOption: renderOption, | ||
renderGroupHeader: renderGroupHeader | ||
})] | ||
}); | ||
}); | ||
SelectSearch.defaultProps = { | ||
className: 'select-search', | ||
// Data | ||
getOptions: null, | ||
filterOptions: null, | ||
value: null, | ||
// Interaction | ||
multiple: false, | ||
search: false, | ||
disabled: false, | ||
search: false, | ||
multiple: false, | ||
placeholder: null, | ||
id: null, | ||
autoFocus: false, | ||
autoComplete: 'on', | ||
value: '', | ||
onChange: () => {}, | ||
printOptions: 'auto', | ||
closeOnSelect: true, | ||
renderOption: (domProps, option, snapshot, className) => | ||
/*#__PURE__*/ | ||
// eslint-disable-next-line react/button-has-type | ||
React.createElement("button", _extends({ | ||
type: "button", | ||
className: className | ||
}, domProps), option.name), | ||
renderGroupHeader: name => name, | ||
renderValue: (valueProps, snapshot, className) => /*#__PURE__*/React.createElement("input", _extends({}, valueProps, { | ||
className: className | ||
})), | ||
debounce: 0, | ||
fuse: { | ||
@@ -203,13 +128,37 @@ keys: ['name', 'groupName'], | ||
}, | ||
getOptions: null, | ||
emptyMessage: null | ||
// Attributes | ||
placeholder: null, | ||
id: null, | ||
autoFocus: false, | ||
autoComplete: 'on', | ||
// Design | ||
className: 'select-search', | ||
// Renderers | ||
renderOption: undefined, | ||
renderGroupHeader: undefined, | ||
renderValue: undefined, | ||
emptyMessage: null, | ||
// Events | ||
onChange: () => {}, | ||
onFocus: () => {}, | ||
onBlur: () => {} | ||
}; | ||
SelectSearch.propTypes = process.env.NODE_ENV !== "production" ? { | ||
// Data | ||
options: PropTypes.arrayOf(optionType).isRequired, | ||
getOptions: PropTypes.func, | ||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number]))]), | ||
className: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), | ||
filterOptions: PropTypes.func, | ||
value: valueType, | ||
// Interaction | ||
multiple: PropTypes.bool, | ||
search: PropTypes.bool, | ||
disabled: PropTypes.bool, | ||
printOptions: PropTypes.oneOf(['auto', 'always', 'never', 'on-focus']), | ||
closeOnSelect: PropTypes.bool, | ||
debounce: PropTypes.number, | ||
fuse: PropTypes.oneOfType([PropTypes.bool, PropTypes.shape({ | ||
keys: PropTypes.arrayOf(PropTypes.string), | ||
threshold: PropTypes.number | ||
})]), | ||
// Attributes | ||
placeholder: PropTypes.string, | ||
@@ -219,14 +168,14 @@ id: PropTypes.string, | ||
autoFocus: PropTypes.bool, | ||
onChange: PropTypes.func, | ||
printOptions: PropTypes.oneOf(['auto', 'always', 'never', 'on-focus']), | ||
closeOnSelect: PropTypes.bool, | ||
// Design | ||
className: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), | ||
// Renderers | ||
renderOption: PropTypes.func, | ||
renderGroupHeader: PropTypes.func, | ||
renderValue: PropTypes.func, | ||
fuse: PropTypes.oneOfType([PropTypes.bool, PropTypes.shape({ | ||
keys: PropTypes.arrayOf(PropTypes.string), | ||
threshold: PropTypes.number | ||
})]), | ||
emptyMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.func]) | ||
emptyMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), | ||
// Events | ||
onChange: PropTypes.func, | ||
onFocus: PropTypes.func, | ||
onBlur: PropTypes.func | ||
} : {}; | ||
export default /*#__PURE__*/memo(SelectSearch); |
@@ -11,3 +11,2 @@ import PropTypes from 'prop-types'; | ||
})]); | ||
export const valueType = PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object)]); | ||
export const classNameType = PropTypes.oneOfType([PropTypes.string, PropTypes.func]); | ||
export const valueType = PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.number]))]); |
@@ -1,112 +0,63 @@ | ||
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(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
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; } | ||
import { useEffect, useMemo, useState, useRef, useCallback } from 'react'; | ||
import { useEffect, useMemo, useState, useReducer, useRef, useCallback } from 'react'; | ||
import groupOptions from './lib/groupOptions'; | ||
import highlightReducer from './highlightReducer'; | ||
import getOption from './lib/getOption'; | ||
import getDisplayValue from './lib/getDisplayValue'; | ||
import flattenOptions from './lib/flattenOptions'; | ||
import groupOptions from './lib/groupOptions'; | ||
import getNewValue from './lib/getNewValue'; | ||
import getOption from './lib/getOption'; | ||
import doSearch from './search'; | ||
import useFilter from './useFilter'; | ||
import useFetch from './useFetch'; | ||
import getValue from './lib/getValue'; | ||
export default function useSelect({ | ||
value: defaultValue = null, | ||
options: defaultOptions = [], | ||
search: canSearch = false, | ||
multiple = false, | ||
disabled = false, | ||
multiple = false, | ||
search: canSearch = false, | ||
closeOnSelect = true, | ||
getOptions = null, | ||
filterOptions = null, | ||
fuse = false, | ||
options: defaultOptions, | ||
onChange = () => {}, | ||
getOptions = null, | ||
allowEmpty = true, | ||
closeOnSelect = true, | ||
closable = true | ||
onFocus = () => {}, | ||
onBlur = () => {}, | ||
debounce = 0 | ||
}) { | ||
const ref = useRef(null); | ||
const flatDefaultOptions = useMemo(() => flattenOptions(defaultOptions), [defaultOptions]); | ||
const [state, setState] = useState({ | ||
flat: [], | ||
addedOptions: [], | ||
value: defaultValue, | ||
search: '', | ||
focus: false, | ||
searching: false, | ||
highlighted: -1, | ||
changed: false | ||
const valueRef = useRef(undefined); | ||
const [value, setValue] = useState(null); | ||
const [search, setSearch] = useState(''); | ||
const [focus, setFocus] = useState(false); | ||
const [highlighted, dispatchHighlighted] = useReducer(highlightReducer, -1); | ||
const filter = useFilter(filterOptions, fuse); | ||
const { | ||
options, | ||
fetching | ||
} = useFetch(search, defaultOptions, { | ||
getOptions, | ||
filter, | ||
debounceTime: debounce | ||
}); | ||
const { | ||
flat, | ||
addedOptions, | ||
value, | ||
const snapshot = useMemo(() => ({ | ||
options: groupOptions(options), | ||
option: value, | ||
displayValue: getDisplayValue(value), | ||
value: getValue(value), | ||
search, | ||
fetching, | ||
focus, | ||
searching, | ||
highlighted | ||
} = state; | ||
const option = useMemo(() => { | ||
let newOption = getOption(value, [...flatDefaultOptions, ...addedOptions]); | ||
highlighted, | ||
disabled | ||
}), [disabled, fetching, focus, options, highlighted, search, value]); | ||
const onSelect = useCallback(newValue => { | ||
const newOption = getOption(newValue, value, Array.isArray(value) ? [...value, ...options] : options, multiple); | ||
setValue(newOption); | ||
onChange(getValue(newOption), newOption); | ||
if (!newOption && !allowEmpty && !multiple) { | ||
[newOption] = flatDefaultOptions; | ||
} | ||
return newOption; | ||
}, [value, flatDefaultOptions, addedOptions, allowEmpty, multiple]); | ||
const options = useMemo(() => groupOptions(flat), [flat]); | ||
const displayValue = useMemo(() => getDisplayValue(option), [option]); | ||
const onBlur = useCallback(() => { | ||
setState(oldState => _objectSpread(_objectSpread({}, oldState), {}, { | ||
focus: false, | ||
search: '', | ||
flat: flatDefaultOptions, | ||
highlighted: -1 | ||
})); | ||
if (ref.current) { | ||
if (closeOnSelect) { | ||
ref.current.blur(); | ||
} | ||
}, [flatDefaultOptions, ref]); | ||
const setFocus = newFocus => setState(oldState => _objectSpread(_objectSpread({}, oldState), {}, { | ||
focus: newFocus | ||
})); | ||
const onClick = () => setFocus(!focus); | ||
const onFocus = () => setFocus(true); | ||
const onSelect = useCallback(id => { | ||
setState(prevState => { | ||
const { | ||
flat: prevFlat, | ||
highlighted: prevHighlighted | ||
} = prevState; // eslint-disable-next-line no-underscore-dangle,eqeqeq | ||
const item = id ? prevFlat.find(i => i.value == id) : prevFlat[prevHighlighted]; | ||
if (!item) { | ||
return prevState; | ||
} | ||
const values = getNewValue(item.value, prevState.value, multiple); | ||
const newOptions = getOption(values, prevFlat); | ||
return _objectSpread(_objectSpread({}, prevState), {}, { | ||
addedOptions: multiple ? newOptions : [newOptions], | ||
value: values, | ||
changed: [values, newOptions] | ||
}); | ||
}); | ||
}, [multiple]); | ||
}, [closeOnSelect, multiple, onChange, value, options]); | ||
const onMouseDown = useCallback(e => { | ||
e.preventDefault(); | ||
if (closeOnSelect && ref.current) { | ||
ref.current.blur(); | ||
} | ||
onSelect(e.currentTarget.value); | ||
}, [onSelect, closeOnSelect]); | ||
}, [onSelect]); | ||
const onKeyDown = useCallback(e => { | ||
@@ -117,115 +68,63 @@ const { | ||
if (key === 'ArrowDown' || key === 'ArrowUp') { | ||
if (['ArrowDown', 'ArrowUp'].includes(key)) { | ||
e.preventDefault(); | ||
setState(oldState => _objectSpread(_objectSpread({}, oldState), {}, { | ||
highlighted: highlightReducer(oldState.highlighted, { | ||
key, | ||
options: oldState.flat | ||
}) | ||
})); | ||
dispatchHighlighted({ | ||
key, | ||
options | ||
}); | ||
} | ||
}, []); | ||
const onKeyPress = useCallback(({ | ||
key | ||
}) => { | ||
if (key === 'Enter') { | ||
onSelect(); | ||
}, [options]); | ||
const onKeyPress = useCallback(e => { | ||
if (e.key === 'Enter') { | ||
e.preventDefault(); | ||
const selected = options[highlighted]; | ||
if (closable && closeOnSelect) { | ||
onBlur(); | ||
if (selected) { | ||
onSelect(selected.value); | ||
} | ||
} | ||
}, [onSelect, closeOnSelect, onBlur, closable]); | ||
const onKeyUp = useCallback(({ | ||
key | ||
}) => { | ||
if (key === 'Escape') { | ||
onBlur(); | ||
} | ||
}, [onBlur]); | ||
const onSearch = ({ | ||
target | ||
}) => { | ||
const { | ||
value: inputVal | ||
} = target; | ||
const newState = { | ||
search: inputVal | ||
}; | ||
let searchableOption = flatDefaultOptions; | ||
if (getOptions && inputVal.length) { | ||
newState.searching = true; | ||
searchableOption = getOptions(inputVal); | ||
if (closeOnSelect) { | ||
ref.current.blur(); | ||
} | ||
} | ||
setState(oldState => _objectSpread(_objectSpread({}, oldState), newState)); | ||
Promise.resolve(searchableOption).then(foundOptions => { | ||
let newOptions = foundOptions; | ||
if (inputVal.length) { | ||
newOptions = doSearch(inputVal, foundOptions, fuse); | ||
} | ||
setState(oldState => _objectSpread(_objectSpread({}, oldState), {}, { | ||
flat: newOptions === false ? foundOptions : newOptions, | ||
searching: false | ||
})); | ||
}).catch(() => setState(oldState => _objectSpread(_objectSpread({}, oldState), {}, { | ||
flat: flatDefaultOptions, | ||
searching: false | ||
}))); | ||
}; | ||
const valueProps = { | ||
}, [options, highlighted, closeOnSelect, onSelect]); | ||
const valueProps = useMemo(() => ({ | ||
tabIndex: '0', | ||
readOnly: !canSearch, | ||
onChange: canSearch ? onSearch : null, | ||
disabled, | ||
onMouseDown: onClick, | ||
onBlur, | ||
onFocus, | ||
onFocus: e => { | ||
setFocus(true); | ||
onFocus(e); | ||
}, | ||
onBlur: e => { | ||
setFocus(false); | ||
setSearch(''); | ||
onBlur(e); | ||
}, | ||
onKeyPress, | ||
onKeyDown, | ||
onKeyUp, | ||
onKeyUp: e => { | ||
if (e.key === 'Escape') { | ||
e.preventDefault(); | ||
ref.current.blur(); | ||
} | ||
}, | ||
onChange: canSearch ? ({ | ||
target | ||
}) => setSearch(target.value) : null, | ||
disabled, | ||
ref | ||
}; | ||
}), [canSearch, onFocus, onBlur, onKeyPress, onKeyDown, disabled, ref]); | ||
const optionProps = useMemo(() => ({ | ||
tabIndex: '-1', | ||
onMouseDown, | ||
onKeyDown, | ||
onKeyPress, | ||
onBlur | ||
}), [onMouseDown, onKeyDown, onKeyPress, onBlur]); | ||
onMouseDown | ||
}), [onMouseDown]); | ||
useEffect(() => { | ||
setState(oldState => _objectSpread(_objectSpread({}, oldState), {}, { | ||
value: defaultValue | ||
})); | ||
}, [defaultValue]); | ||
useEffect(() => { | ||
setState(oldState => _objectSpread(_objectSpread({}, oldState), {}, { | ||
flat: flatDefaultOptions | ||
})); | ||
}, [flatDefaultOptions]); | ||
useEffect(() => { | ||
if (state.changed !== false) { | ||
setState(oldState => _objectSpread(_objectSpread({}, oldState), {}, { | ||
changed: false | ||
})); | ||
onChange(...state.changed); | ||
if (valueRef.current === defaultValue) { | ||
return; | ||
} | ||
}, [state.changed, onChange]); | ||
return [{ | ||
value: option, | ||
highlighted, | ||
options, | ||
disabled, | ||
displayValue, | ||
focus, | ||
search, | ||
searching | ||
}, valueProps, optionProps, newValue => setState(oldState => _objectSpread(_objectSpread({}, oldState), {}, { | ||
value: newValue | ||
}))]; | ||
valueRef.current = defaultValue; | ||
setValue(getOption(defaultValue, null, options, multiple)); | ||
}, [defaultValue, multiple, options]); | ||
return [snapshot, valueProps, optionProps, setValue]; | ||
} |
157
package.json
{ | ||
"name": "react-select-search", | ||
"version": "2.2.4", | ||
"description": "Lightweight select component for React", | ||
"main": "dist/esm/index.js", | ||
"types": "src/index.d.ts", | ||
"scripts": { | ||
"lint": "eslint src --ext .js --ext .jsx", | ||
"test": "jest", | ||
"test:watch": "npm test -- --watch", | ||
"test:coverage": "npm test -- --coverage --silent", | ||
"coveralls": "npm run test:coverage && cat ./coverage/lcov.info | coveralls", | ||
"start": "start-storybook -p 6006", | ||
"bundle": "npx babel --config-file=./babel.config.esm.js src --out-dir dist/esm | npx babel --config-file=./babel.config.js src --out-dir dist/cjs", | ||
"storybook": "start-storybook -p 6006", | ||
"build": "build-storybook --output-dir public" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/tbleckert/react-select-search.git" | ||
}, | ||
"keywords": [ | ||
"react", | ||
"select", | ||
"js", | ||
"search", | ||
"react-component" | ||
], | ||
"author": "Tobias Bleckert (hola@tobiasbleckert.se)", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/tbleckert/react-select-search/issues" | ||
}, | ||
"homepage": "https://github.com/tbleckert/react-select-search", | ||
"peerDependencies": { | ||
"react": "^16.8.4", | ||
"react-dom": "^16.8.4", | ||
"prop-types": "^15.6.2" | ||
}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.11.6", | ||
"@babel/core": "^7.11.6", | ||
"@babel/plugin-proposal-class-properties": "^7.10.4", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.11.0", | ||
"@babel/preset-env": "^7.11.5", | ||
"@babel/preset-react": "^7.10.4", | ||
"@babel/register": "^7.11.5", | ||
"@storybook/addon-actions": "^6.0.4", | ||
"@storybook/addon-links": "^6.0.4", | ||
"@storybook/addon-storysource": "^6.0.4", | ||
"@storybook/addons": "^6.0.4", | ||
"@storybook/react": "^6.0.4", | ||
"babel-eslint": "^10.1.0", | ||
"babel-loader": "^8.1.0", | ||
"babel-plugin-transform-react-remove-prop-types": "^0.4.24", | ||
"browser-env": "^3.3.0", | ||
"coveralls": "^3.1.0", | ||
"enzyme": "^3.11.0", | ||
"enzyme-adapter-react-16": "^1.15.2", | ||
"enzyme-to-json": "^3.4.4", | ||
"eslint": "^7.0.0", | ||
"eslint-config-airbnb": "^18.1.0", | ||
"eslint-plugin-import": "^2.20.2", | ||
"eslint-plugin-jsx-a11y": "^6.2.3", | ||
"eslint-plugin-react": "^7.20.0", | ||
"eslint-plugin-react-hooks": "^4.0.2", | ||
"fuse.js": "^3.4.5", | ||
"jest": "^26.0.1", | ||
"prop-types": "^15.7.2", | ||
"react": "^16.13.1", | ||
"react-dom": "^16.13.1", | ||
"react-test-renderer": "^16.13.1", | ||
"react-transition-group": "^4.4.1" | ||
}, | ||
"dependencies": {}, | ||
"optionalDependencies": { | ||
"fuse.js": "^3.4.5" | ||
} | ||
"name": "react-select-search", | ||
"version": "3.0.0-beta.1", | ||
"description": "Lightweight select component for React", | ||
"main": "dist/esm/index.js", | ||
"types": "src/index.d.ts", | ||
"sideEffects": false, | ||
"scripts": { | ||
"lint": "eslint src --ext .js --ext .jsx", | ||
"test": "jest", | ||
"test:watch": "npm test -- --watch", | ||
"test:coverage": "npm test -- --coverage --silent", | ||
"coveralls": "npm run test:coverage && cat ./coverage/lcov.info | coveralls", | ||
"start": "start-storybook -p 6006", | ||
"bundle": "npx babel --config-file=./babel.config.esm.js src --out-dir dist/esm | npx babel --config-file=./babel.config.js src --out-dir dist/cjs", | ||
"storybook": "start-storybook -p 6006", | ||
"build": "build-storybook --output-dir public" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/tbleckert/react-select-search.git" | ||
}, | ||
"keywords": [ | ||
"react", | ||
"select", | ||
"js", | ||
"search", | ||
"react-component" | ||
], | ||
"author": "Tobias Bleckert (hola@tobiasbleckert.se)", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/tbleckert/react-select-search/issues" | ||
}, | ||
"homepage": "https://github.com/tbleckert/react-select-search", | ||
"peerDependencies": { | ||
"react": "^17.0.1", | ||
"react-dom": "^17.0.1", | ||
"prop-types": "^15.7.2" | ||
}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.12.1", | ||
"@babel/core": "^7.12.9", | ||
"@babel/plugin-proposal-class-properties": "^7.12.1", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.12.1", | ||
"@babel/preset-env": "^7.12.1", | ||
"@babel/preset-react": "^7.12.7", | ||
"@babel/register": "^7.12.1", | ||
"@storybook/addon-actions": "^6.2.0-alpha.0", | ||
"@storybook/addon-essentials": "^6.2.0-alpha.0", | ||
"@storybook/addon-links": "^6.2.0-alpha.0", | ||
"@storybook/addon-storyshots": "^6.2.0-alpha.0", | ||
"@storybook/addon-storysource": "^6.2.0-alpha.0", | ||
"@storybook/addons": "^6.2.0-alpha.0", | ||
"@storybook/react": "^6.2.0-alpha.0", | ||
"babel-eslint": "^10.1.0", | ||
"babel-loader": "^8.1.0", | ||
"babel-plugin-transform-react-remove-prop-types": "^0.4.24", | ||
"browser-env": "^3.3.0", | ||
"coveralls": "^3.1.0", | ||
"eslint": "^7.14.0", | ||
"eslint-config-airbnb": "^18.2.0", | ||
"eslint-plugin-import": "^2.22.0", | ||
"eslint-plugin-jsx-a11y": "^6.3.1", | ||
"eslint-plugin-react": "^7.21.5", | ||
"eslint-plugin-react-hooks": "^4.1.2", | ||
"fuse.js": "^3.4.5", | ||
"identity-obj-proxy": "^3.0.0", | ||
"jest": "^26.6.3", | ||
"pretty": "^2.0.0", | ||
"prop-types": "^15.7.2", | ||
"react": "^17.0.1", | ||
"react-dom": "^17.0.1", | ||
"react-is": "^17.0.1", | ||
"react-test-renderer": "^17.0.1", | ||
"react-transition-group": "^4.4.1" | ||
}, | ||
"dependencies": {}, | ||
"optionalDependencies": { | ||
"fuse.js": "^3.4.5" | ||
} | ||
} |
@@ -122,19 +122,24 @@ <p align="center"> | ||
| options | array | | Se the [options documentation](#the-options-object) below | | ||
| value | string, array | undefined | The value should be an array if multiple mode. | | ||
| getOptions | function | null | Get options through a function call, can return a promise for async usage. See [get options](#get-options) for more. | | ||
| filterOptions | function | null | Takes the current search query (if any) and the current options and returns a new array of options. Runs after getOptions and fuzzy search (if providing a fuse object). | | ||
| value | string, array | null | The value should be an array if multiple mode. | | ||
| fuse | object, boolean | true | Use fuse.js to apply fuzzy search on search. Set to true to use default options or pass a fuse.js config option. If `search` is enabled and no `filterOptions` callback is passed, this will be set to `true` automatically. | | ||
| multiple | boolean | false | Set to true if you want to allow multiple selected options. | | ||
| search | boolean | false | Set to true to enable search functionality | | ||
| emptyMessage | string, function | null | Set empty message for empty options list, you can provide render function without arguments instead plain string message| | ||
| disabled | boolean | false | Disables all functionality | | ||
| printOptions | string | auto | Can be: auto, always, never, on-focus. This property controls when the options list should be rendered. | | ||
| closeOnSelect | boolean | true | The selectbox will blur by default when selecting an option. Set this to false to prevent this behavior. | | ||
| debounce | number | 0 | Number of ms to wait until calling [get options](#get-options) when searching. | | ||
| placeholder | string | empty string | Displayed if no option is selected and/or when search field is focused with empty value. | | ||
| id | string | null | HTML ID on the top level element. | | ||
| autoComplete | string, on/off | off | Disables/Enables autoComplete functionality in search field. | | ||
| autoFocus | boolean | false | Autofocus on select | | ||
| fuse | object, boolean | true | Use fuse.js to apply fuzzy search on search. Set to true to use default options or pass a fuse.js config option. If `search` is enabled and no `filterOptions` callback is passed, this will be set to `true` automatically. | | ||
| className | string, function | select-search-box | Set a base class string or pass a function for complete control. Se [custom classNames](#custom-class-names) for more. | | ||
| onChange | function | null | Function to receive and handle value changes. | | ||
| printOptions | string | auto | Can be: auto, always, never, on-focus. This property controls when the options list should be rendered. | | ||
| closeOnSelect | boolean | true | The selectbox will blur by default when selecting an option. Set this to false to prevent this behavior. | | ||
| renderOption | function | null | Function that renders the options. See [custom renderers](#custom-renderers) for more. | | ||
| renderGroupHeader | function | null | Function that renders the group header. See [custom renderers](#custom-renderers) for more. | | ||
| renderValue | function | null | Function that renders the value/search field. See [custom renderers](#custom-renderers) for more. | | ||
| renderGroupHeader | function | null | Function that renders the group header. See [custom renderers](#custom-renderers) for more. | | ||
| getOptions | function | null | Get options through a function call, can return a promise for async usage. See [get options](#get-options) for more. | | ||
| emptyMessage | string, function | null | Set empty message for empty options list, you can provide render function without arguments instead plain string message| | ||
| onChange | function | null | Function to receive and handle value changes. | | ||
| onFocus | function | null | Focus callback. | | ||
| onBlur | function | null | Blur callback. | | ||
@@ -141,0 +146,0 @@ ## The options object |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
83503
51
2013
223
35
1
12
5