UNPKG

react-lacona

Version:

React Component to provide a friendly interface for lacona

257 lines (226 loc) 8.99 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.LaconaView = exports.hashArgument = undefined; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _option = require('./option'); Object.defineProperty(exports, 'hashArgument', { enumerable: true, get: function get() { return _option.hashArgument; } }); var _lodash = require('lodash'); var _lodash2 = _interopRequireDefault(_lodash); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _reactDom = require('react-dom'); var _options = require('./options'); var _input = require('./input'); 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; } function bound(number, max) { return Math.max(Math.min(number, max - 1), 0); } var LaconaView = exports.LaconaView = function (_React$Component) { _inherits(LaconaView, _React$Component); function LaconaView(props) { _classCallCheck(this, LaconaView); var _this = _possibleConstructorReturn(this, (LaconaView.__proto__ || Object.getPrototypeOf(LaconaView)).call(this, props)); _this.setByMouse = false; _this.blurMatters = true; var hasOutputs = props.length > 0; _this.state = { selection: hasOutputs ? 0 : -1 }; return _this; } _createClass(LaconaView, [{ key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { var hasOutputs = nextProps.outputs.length > 0; this.setState({ selection: hasOutputs ? bound(this.state.selection, nextProps.outputs.length) : -1 }); } }, { key: 'handleScroll', value: function handleScroll() { var optionsDOM = (0, _reactDom.findDOMNode)(this.options); var preview = document.getElementsByClassName('preview-wrapper')[0]; var option = this.options.getOption(this.state.selection); if (option && preview) { // scroll visible option into view var optionDOM = (0, _reactDom.findDOMNode)(option); var paddingTop = getComputedStyle(optionDOM).getPropertyValue('padding-top'); preview.style.marginTop = -optionsDOM.scrollTop - preview.clientHeight / 2 - parseInt(paddingTop) + optionDOM.clientHeight / 2 + 'px'; } } }, { key: 'componentDidMount', value: function componentDidMount() { var optionsDOM = (0, _reactDom.findDOMNode)(this.options); optionsDOM.addEventListener('scroll', this.handleScroll.bind(this)); this.componentDidUpdate(); } }, { key: 'componentDidUpdate', value: function componentDidUpdate() { this.handleScroll(); if (this.state.selection > -1 && !this.setByMouse) { var optionsDOM = (0, _reactDom.findDOMNode)(this.options); var optionsRect = optionsDOM.getBoundingClientRect(); var option = this.options.getOption(this.state.selection); if (option) { // scroll visible option into view var selectedRect = (0, _reactDom.findDOMNode)(option).getBoundingClientRect(); if (selectedRect.top < optionsRect.top) { optionsDOM.scrollTop -= optionsRect.top - selectedRect.top; } else if (selectedRect.bottom > optionsRect.bottom) { optionsDOM.scrollTop += selectedRect.bottom - optionsRect.bottom; } } } } }, { key: 'completeSelection', value: function completeSelection() { var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.state.selection; if (index > -1) { var result = this.props.outputs[index]; var newString = _lodash2.default.chain(result.words).takeWhile(function (item) { return !item.placeholder; }).map('text').join('').value(); this.update(newString); } } }, { key: 'moveSelection', value: function moveSelection(steps) { this.setByMouse = false; var selection = bound(this.state.selection + steps, this.props.outputs.length); this.setState({ selection: selection }); } }, { key: 'execute', value: function execute() { var index = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.state.selection; if (index > -1) { var result = this.props.outputs[index]; if (!result) return; if (_lodash2.default.some(result.words, 'placeholder')) { this.completeSelection(index); this.input.focusEnd(); } else { this.update(''); this.setState({ showHints: false }); this.props.execute(index); this.props.onBlur(); } } } }, { key: 'select', value: function select(index) { this.setByMouse = true; var selection = bound(index, this.props.outputs.length); this.setState({ selection: selection }); } }, { key: 'cancel', value: function cancel() { this.props.cancel(); } }, { key: 'update', value: function update(newText) { this.props.update(newText); } }, { key: 'focusEnd', value: function focusEnd() { this.input.focusEnd(); } }, { key: 'onFocus', value: function onFocus(event) { this.setState({ showHints: true }); this.props.onFocus(event); } }, { key: 'onBlur', value: function onBlur(event) { if (!this.blurMatters) return; this.setState({ showHints: false }); this.props.onBlur(event); } }, { key: 'mouseDown', value: function mouseDown() { this.blurMatters = false; } }, { key: 'mouseUp', value: function mouseUp() { this.blurMatters = true; this.focus(); } }, { key: 'focus', value: function focus() { this.input.focus(); } }, { key: 'blur', value: function blur() { this.input.blur(); } }, { key: 'render', value: function render() { var _this2 = this; return _react2.default.createElement( 'div', { className: 'lacona-view' }, _react2.default.createElement(_input.Input, { ref: function ref(c) { return _this2.input = c; }, update: this.update.bind(this), prefix: this.props.prefix, suffix: this.props.suffix, tabIndex: this.props.tabIndex, completeSelection: this.completeSelection.bind(this), moveSelection: this.moveSelection.bind(this), userInput: this.props.userInput, execute: this.execute.bind(this), cancel: this.cancel.bind(this), selectKey: this.props.selectKey, onFocus: this.onFocus.bind(this), onBlur: this.onBlur.bind(this), empty: !this.props.outputs.length, placeholder: this.props.placeholder }), _react2.default.createElement(_options.Options, { ref: function ref(c) { return _this2.options = c; }, outputs: this.props.outputs, selectKey: this.props.selectKey, selection: this.state.selection, execute: this.execute.bind(this), select: this.select.bind(this), showHints: this.props.selectKey !== 'none', onMouseDown: this.mouseDown.bind(this), onMouseUp: this.mouseUp.bind(this) }) ); } }]); return LaconaView; }(_react2.default.Component); LaconaView.defaultProps = { outputs: [], update: function update() {}, cancel: function cancel() {}, execute: function execute() {}, onFocus: function onFocus() {}, onBlur: function onBlur() {} };