UNPKG

@attivio/suit

Version:

Attivio SUIT, the Search UI Toolkit, is a library for creating search clients for searching the Attivio platform.

302 lines (265 loc) 10 kB
'use strict'; exports.__esModule = true; exports.default = undefined; var _class, _temp; var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _Scrollable = require('./Scrollable'); var _Scrollable2 = _interopRequireDefault(_Scrollable); var _SimpleAutoCompleteInput = require('./SimpleAutoCompleteInput'); var _SimpleAutoCompleteInput2 = _interopRequireDefault(_SimpleAutoCompleteInput); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var LozengeFilter = (_temp = _class = function (_React$Component) { _inherits(LozengeFilter, _React$Component); function LozengeFilter(props) { _classCallCheck(this, LozengeFilter); var _this = _possibleConstructorReturn(this, _React$Component.call(this, props)); _this.divs = new Map(); _this.state = { filterString: '', filteredItems: [] }; _this.itemClicked = _this.itemClicked.bind(_this); return _this; } /** * Given a filter string the user has typed in, find any of the items in * our list that match it. */ LozengeFilter.prototype.getFilteredItems = function getFilteredItems(filterString) { if (filterString.length > 0) { var lowercaseFilter = filterString.toLocaleLowerCase(); return this.props.values.filter(function (value) { if (value.toLocaleLowerCase().startsWith(lowercaseFilter)) { return true; } return false; }); } return []; }; LozengeFilter.prototype.makeItem = function makeItem(label, value, current) { var _this2 = this; var baseStyle = { display: 'block', width: '100%', lineHeight: '1em', paddingTop: '6px', paddingLeft: '8px', paddingBottom: '5px', paddingRight: '8px', marginBottom: '1px' }; var additionalStyle = current ? { color: '#fff', backgroundColor: '#2e75b3', borderRadius: '3px', border: 'none' } : { color: '#000', backgroundColor: 'inherit', borderRadius: '3px', borderBottom: '1px solid #fff' }; var style = Object.assign({}, baseStyle, additionalStyle); return _react2.default.createElement( 'div', { key: value, onClick: function onClick(event) { _this2.itemClicked(event, value); }, role: 'button', tabIndex: 0, style: style, ref: function ref(item) { if (typeof value === 'string') { _this2.divs.set(value, item); } else { _this2.divs.set('null', item); } } }, label ); }; /** * Add the specified value to the multi-select selection. */ LozengeFilter.prototype.addToSelection = function addToSelection(value) { var updatedSelection = void 0; if (typeof this.props.currentValue === 'string') { updatedSelection = [this.props.currentValue]; } else if (Array.isArray(this.props.currentValue)) { updatedSelection = this.props.currentValue; } else { updatedSelection = []; } if (!updatedSelection.includes(value)) { updatedSelection.push(value); } return updatedSelection; }; /** * Toggle the specified value in the multi-select selection. */ LozengeFilter.prototype.toggleSelection = function toggleSelection(value) { var updatedSelection = void 0; if (typeof this.props.currentValue === 'string') { updatedSelection = [this.props.currentValue]; } else if (Array.isArray(this.props.currentValue)) { updatedSelection = this.props.currentValue; } else { updatedSelection = []; } var valueIndex = updatedSelection.indexOf(value); if (valueIndex > -1) { // It's already in the selection, need to remove it updatedSelection.splice(valueIndex, 1); } else { // It's not in the selection, so just add it updatedSelection.push(value); } return updatedSelection; }; LozengeFilter.prototype.itemClicked = function itemClicked(event, value) { var newSelection = void 0; // Single select case or clearing selection by using the "All" button if (value === null || !this.props.multiSelect) { // If it's null, we're clearing everything, so multi is moot // and if we're not multi, then we're replacing the existing // selection. In either case, we just use value as-is. newSelection = value; } else if (event.ctrlKey || event.metaKey) { // The user has the control key (command key on the Mac) down // while clicking, toggle the state instead of just selecting newSelection = this.toggleSelection(value); } else { // Normal multi-select case, just add the new value to the // selection if it's not already there newSelection = this.addToSelection(value); } if (Array.isArray(newSelection) && newSelection.length === 0) { newSelection = null; } // Make sure to remove focus from the item that was clicked var div = this.divs.get(value || 'null'); if (div) { div.blur(); } this.props.onChange(newSelection); }; LozengeFilter.prototype.isSelected = function isSelected(item) { if (this.props.currentValue === item) { // If the item is null or the selection is a single string, // this will tell us if it matches return true; } else if (Array.isArray(this.props.currentValue)) { // If the selection is an array, we need to check if item is in the array if (this.props.currentValue.includes(item)) { return true; } } return false; }; LozengeFilter.prototype.render = function render() { var _this3 = this; var items = this.props.values.map(function (value) { return _this3.makeItem(value, value, _this3.isSelected(value)); }); var allItem = this.makeItem(this.props.allLabel, null, this.props.currentValue === null); var contents = void 0; if (this.props.values.length > this.props.itemCutoff) { // Set the height of the scrollable to fit the items we want to have visible and make the // user scroll for the rest (each item has a line height of 1em plus 6 pixels of padding // above and below). var height = 'calc(' + this.props.itemCutoff + 'em + ' + (this.props.itemCutoff * 12 + 6) + 'px)'; // In this case, we keep the "all" item outside the scrollable so it's always visible contents = _react2.default.createElement( 'div', null, allItem, _react2.default.createElement( _Scrollable2.default, { style: { height: height } }, items ), _react2.default.createElement( 'style', null, 'input[data-id=\'' + this.props.title + '\']::placeholder {\n color: #ccc\n }' ), _react2.default.createElement(_SimpleAutoCompleteInput2.default, { id: this.props.title, value: this.state.filterString, values: this.props.values, updateValue: function updateValue(newValue, chosen) { if (chosen) { // Turn on the item with the text of newValue var newSelection = _this3.props.multiSelect ? _this3.addToSelection(newValue) : newValue; _this3.setState({ filterString: '' }, function () { _this3.props.onChange(newSelection); // Scroll to the div of the newly selected item... var div = _this3.divs.get(newValue); if (div) { div.scrollIntoView({ block: 'end', behavior: 'smooth' }); } }); } else { // Just update the filter string _this3.setState({ filterString: newValue }); } }, placeholder: this.props.filterPlaceholder, style: { width: '100%', marginTop: '5[x', borderRadius: '3px', padding: '2px 4px', lineHeight: '1em', border: '1px solid #eee' }, outerStyle: { width: '100%', marginTop: '6px', marginBottom: '10px' } }) ); } else { // Add the "all" item to the top of the list items.unshift(allItem); contents = _react2.default.createElement( 'div', null, items ); } return _react2.default.createElement( 'div', { style: { padding: '10px' } }, _react2.default.createElement( 'h4', { style: { fontWeight: 'bold' } }, this.props.title ), contents ); }; return LozengeFilter; }(_react2.default.Component), _class.defaultProps = { allLabel: 'All Items', itemCutoff: 9, multiSelect: false, currentValue: null, filterPlaceholder: 'Filter\u2026' }, _class.displayName = 'LozengeFilter', _temp); exports.default = LozengeFilter; module.exports = exports['default'];