UNPKG

@massds/mayflower-react

Version:

React versions of Mayflower design system UI components

322 lines (321 loc) 13.6 kB
"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;