@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
JavaScript
'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'];