@massds/mayflower-react
Version:
React versions of Mayflower design system UI components
322 lines (321 loc) • 13.6 kB
JavaScript
"use strict";
exports.__esModule = true;
exports["default"] = void 0;
var _react = _interopRequireDefault(require("react"));
var _reactAutosuggest = _interopRequireDefault(require("react-autosuggest"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _fuse = _interopRequireDefault(require("fuse.js"));
var _parse = _interopRequireDefault(require("autosuggest-highlight/parse"));
var _classnames = _interopRequireDefault(require("classnames"));
var _is = _interopRequireDefault(require("is"));
var _Label = _interopRequireDefault(require("../Label"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
function _inheritsLoose(t, o) { t.prototype = Object.create(o.prototype), t.prototype.constructor = t, _setPrototypeOf(t, o); }
function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /**
* InputTextFuzzy module.
* @module @massds/mayflower-react/InputTextFuzzy
* @requires module:@massds/mayflower-assets/scss/01-atoms/input-typeahead
* @requires module:@massds/mayflower-assets/scss/01-atoms/input-fuzzy
* @requires module:@massds/mayflower-assets/scss/01-atoms/helper-text
*/
var InputTextFuzzy = /*#__PURE__*/function (_React$Component) {
function InputTextFuzzy(props) {
var _this;
_this = _React$Component.call(this, props) || this;
_defineProperty(_this, "onSuggestionsFetchRequested", function (_ref) {
var value = _ref.value;
var suggestions = _is["default"].empty(value) ? _this.optionsToSuggestions(_this.props.options) : _this.fuse.search(value);
_this.setState({
suggestions: suggestions
});
});
_defineProperty(_this, "onSuggestionsClearRequested", function () {
_this.setState({
suggestions: []
});
});
_defineProperty(_this, "onSuggestionSelected", function (event, _ref2) {
var suggestion = _ref2.suggestion,
method = _ref2.method;
// invokes custom function if passed in the component
if (_is["default"].fn(_this.props.onSuggestionClick)) {
event.persist();
// Suggestion is an object that can contain info on score, matches, etc.
_this.props.onSuggestionClick(event, {
suggestion: suggestion,
method: method,
suggestions: _this.state.suggestions
});
}
});
_defineProperty(_this, "getSuggestionValue", function (suggestion) {
return suggestion.item.text;
});
_defineProperty(_this, "handleChange", function (event, _ref3) {
var newValue = _ref3.newValue,
method = _ref3.method;
if (event && event.persist) {
event.persist();
}
var value = newValue;
_this.setState({
value: value
}, function () {
if (_is["default"].fn(_this.props.onChange)) {
_this.props.onChange({
event: event,
method: method,
value: value,
suggestions: _this.state.suggestions
});
}
});
});
_defineProperty(_this, "handleBlur", function (event) {
if (_is["default"].fn(_this.props.onBlur)) {
if (event && event.persist()) {
event.persist();
}
_this.props.onBlur({
event: event,
value: _this.state.value,
suggestions: _this.state.suggestions
});
}
});
// handleChange and onSuggestionSelected both do not fire when enter is hit.
// This is a workaround for that. Use handleChange for keyboard presses.
_defineProperty(_this, "handleKeyPress", function (event) {
var _this$state = _this.state,
value = _this$state.value,
suggestions = _this$state.suggestions;
if (_is["default"].fn(_this.props.onKeyDown)) {
_this.props.onKeyDown(event);
}
var match = suggestions.find(function (el) {
return el.item.text === value;
});
if (event.key === 'Enter') {
event.persist();
event.preventDefault();
if (_is["default"].fn(_this.props.onSuggestionClick) && match) {
_this.props.onSuggestionClick(event, {
method: 'enter',
suggestion: {
item: {
text: value
}
}
});
}
}
});
_defineProperty(_this, "handleFocus", function (event) {
if (_is["default"].fn(_this.props.onFocus)) {
event.persist();
_this.props.onFocus(event, {
event: event,
value: _this.state.value,
suggestions: _this.state.suggestions
});
}
});
_defineProperty(_this, "optionsToSuggestions", function (options) {
var suggestions = options.map(function (item) {
return {
item: {
text: item.text,
value: item.value
},
matches: [{
indices: [],
value: item.text,
key: 'text',
arrayIndex: 0
}]
};
});
return suggestions;
});
_defineProperty(_this, "shouldRenderSuggestions", function (value) {
return _this.props.renderDefaultSuggestion === true ? value.trim().length >= 0 : value.trim().length > 0;
});
_defineProperty(_this, "renderItem", function (suggestion) {
var item = suggestion.item,
matches = suggestion.matches;
var renderItems = [];
if (_is["default"].empty(_this.state.value)) {
renderItems = _this.props.keys.map(function (key) {
return /*#__PURE__*/_react["default"].createElement("span", {
key: key + ".suggestion_" + item.optionIndex
}, item[key]);
});
} else {
matches.forEach(function (match) {
if (_this.props.keys.indexOf(match.key) > -1) {
// Add one to each range to get a proper highlight match.
var ranges = match.indices.map(function (range) {
var start = range[0],
end = range[1];
return [start, Number(end) + 1];
});
var parts = (0, _parse["default"])(match.value, ranges);
renderItems = parts.filter(function (part) {
return part.text.length > 0;
}).map(function (part, index) {
var className = part.highlight === true ? 'highlight' : null;
var key = match.key + ".suggestion_" + index;
return /*#__PURE__*/_react["default"].createElement("span", {
className: className,
key: key
}, part.text);
});
}
});
}
return /*#__PURE__*/_react["default"].createElement("span", {
className: "ma__suggestion-content"
}, /*#__PURE__*/_react["default"].createElement("span", {
className: "ma__suggestion-content-name"
}, renderItems));
});
_defineProperty(_this, "renderItemsContainer", function (_ref4) {
var children = _ref4.children,
containerProps = _ref4.containerProps;
return /*#__PURE__*/_react["default"].createElement("div", _extends({
className: "ma__input-fuzzy"
}, containerProps), children);
});
_this.state = {
value: _this.props.selected || '',
suggestions: []
};
var fuseOptions = _this.props.fuseOptions;
fuseOptions.keys = _this.props.keys;
_this.fuse = new _fuse["default"](_this.props.options, fuseOptions);
return _this;
}
_inheritsLoose(InputTextFuzzy, _React$Component);
var _proto = InputTextFuzzy.prototype;
_proto.render = function render() {
var _this$props = this.props,
inputId = _this$props.inputId,
id = _this$props.id,
placeholder = _this$props.placeholder,
disabled = _this$props.disabled,
label = _this$props.label,
boxed = _this$props.boxed,
autoFocusInput = _this$props.autoFocusInput;
var autoProps = {
suggestions: this.state.suggestions,
renderSuggestionsContainer: this.renderItemsContainer,
renderSuggestion: this.renderItem,
onSuggestionsFetchRequested: this.onSuggestionsFetchRequested,
onSuggestionsClearRequested: this.onSuggestionsClearRequested,
getSuggestionValue: this.getSuggestionValue,
shouldRenderSuggestions: this.shouldRenderSuggestions,
onSuggestionSelected: this.onSuggestionSelected,
focusInputOnSuggestionClick: false,
inputProps: {
type: 'search',
placeholder: placeholder,
onChange: this.handleChange,
value: this.state.value,
disabled: disabled,
id: inputId,
onFocus: this.handleFocus,
autoFocus: autoFocusInput,
onBlur: this.handleBlur,
onKeyPress: this.handleKeyPress
},
id: id
};
var inputTextTypeAheadClasses = (0, _classnames["default"])({
'ma__input-typeahead': true,
'ma__input-typeahead--disabled': disabled,
'ma__input-typeahead--boxed': boxed
});
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, label && /*#__PURE__*/_react["default"].createElement(_Label["default"], {
inputId: inputId,
disabled: disabled
}, label), /*#__PURE__*/_react["default"].createElement("div", {
className: inputTextTypeAheadClasses
}, /*#__PURE__*/_react["default"].createElement(_reactAutosuggest["default"], autoProps)));
};
return InputTextFuzzy;
}(_react["default"].Component);
InputTextFuzzy.propTypes = process.env.NODE_ENV !== "production" ? {
/** The id of the typeahead element. */
id: _propTypes["default"].string.isRequired,
/** The label text above the input text box. */
label: _propTypes["default"].string,
/** The placeholder text to appear in the input text box. */
placeholder: _propTypes["default"].string,
/** Style the input with a box outline. */
boxed: _propTypes["default"].bool,
/** The keys within options that will be searched (part of fuseOptions).
* https://fusejs.io/api/options.html#keys
*/
keys: _propTypes["default"].arrayOf(_propTypes["default"].oneOfType([_propTypes["default"].string, _propTypes["default"].object])).isRequired,
/** An array of objects representing all searchable values. */
options: _propTypes["default"].arrayOf(_propTypes["default"].shape({
label: _propTypes["default"].string,
id: _propTypes["default"].string,
// eslint-disable-next-line react/forbid-prop-types
options: _propTypes["default"].any,
keys: _propTypes["default"].arrayOf(_propTypes["default"].string),
selected: _propTypes["default"].string,
placeholder: _propTypes["default"].string,
onChange: _propTypes["default"].func
})).isRequired,
/** Any Fusejs options to override the default options set in this component.
* API doc: https://fusejs.io/api/options.html
*
*/
/* eslint-disable-next-line react/forbid-prop-types */
fuseOptions: _propTypes["default"].object,
/** Disables input. */
disabled: _propTypes["default"].bool,
/** Function that runs after changes to the input happen. */
onChange: _propTypes["default"].func,
onFocus: _propTypes["default"].func,
onBlur: _propTypes["default"].func,
/** Function that runs after a suggestion has been clicked. */
onSuggestionClick: _propTypes["default"].func,
/** Custom keydown callback */
onKeyDown: _propTypes["default"].func,
/** The default value for the select box. */
selected: _propTypes["default"].string,
/** The id of the the input tag */
inputId: _propTypes["default"].string,
/** By default all options will be rendered as suggestions on input focus */
renderDefaultSuggestion: _propTypes["default"].bool,
/** Focus on typeahead input */
autoFocusInput: _propTypes["default"].bool
} : {};
InputTextFuzzy.defaultProps = {
fuseOptions: {
/** Set the result list to sort by score. */
shouldSort: true,
/** Prevents matching from stopping at the first match found. */
findAllMatches: true,
/** Lets the matches found be included in the result set. This field must be true for the highlight to work. */
includeMatches: true,
/** Match sensitivity. 0 means what's been typed must be a perfect match, 1 means anything typed matches. */
threshold: 0.3,
/** Prevents matches against empty strings. */
minMatchCharLength: 1,
/** Allows more characters for long queries. */
maxPatternLength: 300
},
autoFocusInput: false,
disabled: false,
boxed: false,
renderDefaultSuggestion: true
};
var _default = exports["default"] = InputTextFuzzy;
module.exports = exports.default;