UNPKG

@massds/mayflower-react

Version:

React versions of Mayflower design system UI components

349 lines (291 loc) 11.8 kB
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 _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; } 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; } /** * 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 */ import React from "react"; import Autosuggest from "react-autosuggest"; import PropTypes from "prop-types"; import Fuse from "fuse.js"; import parse from "autosuggest-highlight/parse"; import classNames from "classnames"; import is from "is"; import Label from "../Label"; let InputTextFuzzy = /*#__PURE__*/function (_React$Component) { _inheritsLoose(InputTextFuzzy, _React$Component); function InputTextFuzzy(props) { var _this; _this = _React$Component.call(this, props) || this; _defineProperty(_assertThisInitialized(_this), "onSuggestionsFetchRequested", (_ref) => { let value = _ref.value; const suggestions = is.empty(value) ? _this.optionsToSuggestions(_this.props.options) : _this.fuse.search(value); _this.setState({ suggestions: suggestions }); }); _defineProperty(_assertThisInitialized(_this), "onSuggestionsClearRequested", () => { _this.setState({ suggestions: [] }); }); _defineProperty(_assertThisInitialized(_this), "onSuggestionSelected", (event, _ref2) => { let suggestion = _ref2.suggestion, method = _ref2.method; // invokes custom function if passed in the component if (is.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(_assertThisInitialized(_this), "getSuggestionValue", suggestion => suggestion.item.text); _defineProperty(_assertThisInitialized(_this), "handleChange", (event, _ref3) => { let newValue = _ref3.newValue, method = _ref3.method; if (event && event.persist) { event.persist(); } const value = newValue; _this.setState({ value: value }, () => { if (is.fn(_this.props.onChange)) { _this.props.onChange({ event: event, method: method, value: value, suggestions: _this.state.suggestions }); } }); }); _defineProperty(_assertThisInitialized(_this), "handleBlur", event => { if (is.fn(_this.props.onBlur)) { if (event && event.persist()) { event.persist(); } _this.props.onBlur({ event: event, value: _this.state.value, suggestions: _this.state.suggestions }); } }); _defineProperty(_assertThisInitialized(_this), "handleKeyPress", event => { const _this$state = _this.state, value = _this$state.value, suggestions = _this$state.suggestions; if (is.fn(_this.props.onKeyDown)) { _this.props.onKeyDown(event); } const match = suggestions.find(el => el.item.text === value); if (event.key === 'Enter') { event.persist(); event.preventDefault(); if (is.fn(_this.props.onSuggestionClick) && match) { _this.props.onSuggestionClick(event, { method: 'enter', suggestion: { item: { text: value } } }); } } }); _defineProperty(_assertThisInitialized(_this), "handleFocus", event => { if (is.fn(_this.props.onFocus)) { event.persist(); _this.props.onFocus(event, { event: event, value: _this.state.value, suggestions: _this.state.suggestions }); } }); _defineProperty(_assertThisInitialized(_this), "optionsToSuggestions", options => { const suggestions = options.map(item => ({ item: { text: item.text, value: item.value }, matches: [{ indices: [], value: item.text, key: 'text', arrayIndex: 0 }] })); return suggestions; }); _defineProperty(_assertThisInitialized(_this), "shouldRenderSuggestions", value => _this.props.renderDefaultSuggestion === true ? value.trim().length >= 0 : value.trim().length > 0); _defineProperty(_assertThisInitialized(_this), "renderItem", suggestion => { const item = suggestion.item, matches = suggestion.matches; let renderItems = []; if (is.empty(_this.state.value)) { renderItems = _this.props.keys.map(key => /*#__PURE__*/React.createElement("span", { key: key + ".suggestion_" + item.optionIndex }, item[key])); } else { matches.forEach(match => { if (_this.props.keys.indexOf(match.key) > -1) { // Add one to each range to get a proper highlight match. const ranges = match.indices.map(range => { const start = range[0], end = range[1]; return [start, Number(end) + 1]; }); const parts = parse(match.value, ranges); renderItems = parts.filter(part => part.text.length > 0).map((part, index) => { const className = part.highlight === true ? 'highlight' : null; const key = match.key + ".suggestion_" + index; return /*#__PURE__*/React.createElement("span", { className: className, key: key }, part.text); }); } }); } return /*#__PURE__*/React.createElement("span", { className: "ma__suggestion-content" }, /*#__PURE__*/React.createElement("span", { className: "ma__suggestion-content-name" }, renderItems)); }); _defineProperty(_assertThisInitialized(_this), "renderItemsContainer", (_ref4) => { let children = _ref4.children, containerProps = _ref4.containerProps; return /*#__PURE__*/React.createElement("div", _extends({ className: "ma__input-fuzzy" }, containerProps), children); }); _this.state = { value: _this.props.selected || '', suggestions: [] }; const fuseOptions = _this.props.fuseOptions; fuseOptions.keys = _this.props.keys; _this.fuse = new Fuse(_this.props.options, fuseOptions); return _this; } var _proto = InputTextFuzzy.prototype; _proto.render = function render() { const _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; const 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 }; const inputTextTypeAheadClasses = classNames({ 'ma__input-typeahead': true, 'ma__input-typeahead--disabled': disabled, 'ma__input-typeahead--boxed': boxed }); return /*#__PURE__*/React.createElement(React.Fragment, null, label && /*#__PURE__*/React.createElement(Label, { inputId: inputId, disabled: disabled }, label), /*#__PURE__*/React.createElement("div", { className: inputTextTypeAheadClasses }, /*#__PURE__*/React.createElement(Autosuggest, autoProps))); }; return InputTextFuzzy; }(React.Component); InputTextFuzzy.propTypes = process.env.NODE_ENV !== "production" ? { /** The id of the typeahead element. */ id: PropTypes.string.isRequired, /** The label text above the input text box. */ label: PropTypes.string, /** The placeholder text to appear in the input text box. */ placeholder: PropTypes.string, /** Style the input with a box outline. */ boxed: PropTypes.bool, /** The keys within options that will be searched (part of fuseOptions). * https://fusejs.io/api/options.html#keys */ keys: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.object])).isRequired, /** An array of objects representing all searchable values. */ options: PropTypes.arrayOf(PropTypes.object).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.object, /** Disables input. */ disabled: PropTypes.bool, /** Function that runs after changes to the input happen. */ onChange: PropTypes.func, onFocus: PropTypes.func, onBlur: PropTypes.func, /** Function that runs after a suggestion has been clicked. */ onSuggestionClick: PropTypes.func, /** Custom keydown callback */ onKeyDown: PropTypes.func, /** The default value for the select box. */ selected: PropTypes.string, /** The id of the the input tag */ inputId: PropTypes.string, /** By default all options will be rendered as suggestions on input focus */ renderDefaultSuggestion: PropTypes.bool, /** Focus on typeahead input */ autoFocusInput: PropTypes.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 }; export default InputTextFuzzy;