UNPKG

ldx-widgets

Version:

widgets

310 lines (278 loc) 10.9 kB
(function() { var CircleXButton, DOWN_ARROW, ENTER, ESCAPE, InputMixin, LEFT_ARROW, OPTION_PADDING, PropTypes, Pvr, RIGHT_ARROW, React, SPACE, SelectInputCustom, SelectInputCustomOptions, TAB, UP_ARROW, alphaNumericKeyCode, createClass, div, find, option, ref, ref1, select; React = require('react'); createClass = require('create-react-class'); PropTypes = require('prop-types'); find = require('lodash/find'); ref = require('../constants/keyboard'), DOWN_ARROW = ref.DOWN_ARROW, RIGHT_ARROW = ref.RIGHT_ARROW, LEFT_ARROW = ref.LEFT_ARROW, UP_ARROW = ref.UP_ARROW, ENTER = ref.ENTER, SPACE = ref.SPACE, ESCAPE = ref.ESCAPE, TAB = ref.TAB; alphaNumericKeyCode = require('../utils').alphaNumericKeyCode; InputMixin = require('../mixins/input_mixin'); CircleXButton = React.createFactory(require('./circle_x_button')); SelectInputCustomOptions = React.createFactory(require('./select_input_custom_options')); Pvr = React.createFactory(require('./pvr')); ref1 = require('react-dom-factories'), div = ref1.div, select = ref1.select, option = ref1.option; OPTION_PADDING = 10; /*& @general Filterable select menu. This component lives on the overlay layer, and requires integrated context methods closeOverlay and openOverlay within the application. @props.options - [Array] - Required Full list of options to display on component @props.value - [String|Object] - Optional The value that corresponds to the option object with the matching value @props.selectText - [String] - Optional Text displayed as the default value @props.onChange - [Function] - Required Function fired when a change is made to the selection @props.tabIndex - [Number] - Optional Tab order index @props.disabled - [Boolean] - Optional Disabled state of the component @props.isFilter - [Boolean] - Optional Show/hide the filter typeahead input. Default is no @props.returnFullObjects - [Boolean] - Optional Determine whether `getValue` returns the full option object, or just the default value string @props.placeholder - [String] - Optional Placeholder text for the filter input @props.valueField - [String] - Optional The name of the key used to reference the value on the option object @props.labelField - [String] - Optional The name of the key used to reference the label on the option object @props.width - [Number] - Optional The width of the menu popover @props.height - [Number] - Optional The height of the menu popover @props.optionHeight - [Number] - Optional The fixed height of each menu option & */ SelectInputCustom = createClass({ displayName: 'SelectInputCustom', mixins: [InputMixin], contextTypes: { openOverlay: PropTypes.func, closeOverlay: PropTypes.func, clearValidationError: PropTypes.func, addValidationError: PropTypes.func, getValidationStatus: PropTypes.func, toggleValidationError: PropTypes.func }, propTypes: { options: PropTypes.array.isRequired, selectText: PropTypes.string, onChange: PropTypes.func.isRequired, tabIndex: PropTypes.number, disabled: PropTypes.bool, isFilter: PropTypes.bool, returnFullObjects: PropTypes.bool, placeholder: PropTypes.string, valueField: PropTypes.string, labelField: PropTypes.string, width: PropTypes.number, height: PropTypes.number, optionHeight: PropTypes.number, value: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), nibColor: PropTypes.string }, getDefaultProps: function() { return { options: [], selectText: 'Select from list...', placeholder: 'Filter options', valueField: 'value', labelField: 'title', width: 250, height: 400, isFilter: false, nibColor: 'white', optionHeight: 20, returnFullObjects: false }; }, componentWillMount: function() { var value; value = this.props.value; this.value = value; return this.overlayId = null; }, componentWillUnmount: function() { return clearInterval(this.timer); }, render: function() { var disabled, error, forceShowAllErrors, id, isFilter, isValid, labelField, optionItems, options, outerClass, ref2, ref3, returnFullObjects, selectText, tabIndex, value, valueField, valueHasChanged; ref2 = this.props, options = ref2.options, id = ref2.id, selectText = ref2.selectText, valueField = ref2.valueField, labelField = ref2.labelField, tabIndex = ref2.tabIndex, disabled = ref2.disabled, isFilter = ref2.isFilter, value = ref2.value, returnFullObjects = ref2.returnFullObjects; valueHasChanged = this.state.valueHasChanged; ref3 = this.context.getValidationStatus(this.inputId), error = ref3.error, forceShowAllErrors = ref3.forceShowAllErrors; isValid = error == null; outerClass = 'field-wrap filter-select'; if (typeof wrapperClass !== "undefined" && wrapperClass !== null) { outerClass += " " + wrapperClass; } if (!isValid && (valueHasChanged || forceShowAllErrors)) { outerClass += ' invalid shrink'; } if (value && !disabled) { outerClass += ' x-room'; } optionItems = [ option({ key: "none", value: "" }, selectText) ]; options.forEach((function(_this) { return function(o, i) { return optionItems.push(option({ key: i, value: o[valueField] }, o[labelField])); }; })(this)); if (returnFullObjects && (value != null)) { value = value[valueField] || ''; } this.value = value; return div({ className: outerClass }, [ select({ key: 'select', ref: 'input', tabIndex: tabIndex, id: id, disabled: disabled, value: value, onChange: function() {}, onMouseDown: this.handleNativeEvent, onKeyDown: this.handleNativeEvent }, optionItems), value && !disabled ? CircleXButton({ key: 'clear', tabIndex: -1, ref: (function(_this) { return function(clearBtn) { return _this.clearBtn = clearBtn; }; })(this), onClick: this.clearValue }) : void 0, div({ className: 'field-errors-show', key: 'textInputErrorsShow', ref: 'errorAnchor', onMouseOver: this.handleErrorMouseOver, onMouseOut: this.handleErrorMouseOut }) ]); }, handleNativeEvent: function(e) { var alphaNum, closeKeys, currentTarget, filter, isCloseKey, isOpenKey, keyCode, openKeys, options; keyCode = e.keyCode, currentTarget = e.currentTarget; options = this.props.options; openKeys = [DOWN_ARROW, RIGHT_ARROW, LEFT_ARROW, UP_ARROW, ENTER, SPACE]; closeKeys = [ESCAPE, TAB]; if (keyCode != null) { isOpenKey = openKeys.indexOf(keyCode) > -1; isCloseKey = closeKeys.indexOf(keyCode) > -1; alphaNum = alphaNumericKeyCode(keyCode); if (isOpenKey || alphaNum) { e.preventDefault(); e.stopPropagation(); if (alphaNum) { filter = e.key; } this.openOptionsList(currentTarget, filter); } else if (isCloseKey) { if (keyCode !== TAB) { e.preventDefault(); } if (this.overlayId != null) { this.context.closeOverlay({ overlayId: this.overlayId }); this.overlayId = null; } } return; } e.preventDefault(); this.openOptionsList(currentTarget); if (options.length === 0) { return this.timer = setInterval((function(_this) { return function() { if (_this.props.options.length > 0) { _this.context.closeOverlay({ overlayId: _this.overlayId }); _this.openOptionsList(currentTarget); return clearInterval(_this.timer); } }; })(this), 100); } }, openOptionsList: function(anchor, filter) { var height, isFilter, labelField, nibColor, optionHeight, options, placeholder, ref2, returnFullObjects, value, valueField, width; ref2 = this.props, value = ref2.value, options = ref2.options, labelField = ref2.labelField, valueField = ref2.valueField, height = ref2.height, width = ref2.width, placeholder = ref2.placeholder, isFilter = ref2.isFilter, nibColor = ref2.nibColor, optionHeight = ref2.optionHeight, returnFullObjects = ref2.returnFullObjects; if (((options.length + 1) * optionHeight) < height) { height = options.length * (optionHeight + OPTION_PADDING); } if (returnFullObjects && (value != null)) { value = value[valueField] || ''; } return this.overlayId = this.context.openOverlay({ component: Pvr, noBackdrop: true, id: "popover", props: { direction: 'below', width: width, height: height === 0 ? 58 : height, anchor: anchor, nibColor: nibColor, enterStateStart: { scale: 1 }, enterDuration: 50, element: SelectInputCustomOptions({ key: 'fso', options: this.props.options, onChange: this.handleValueChange, labelField: labelField, valueField: valueField, placeholder: placeholder, value: value, SelectEl: this, isFilter: isFilter, searchWidth: width - 10, optionHeight: optionHeight, OPTION_PADDING: OPTION_PADDING, filter: filter }) } }); }, handleValueChange: function(value, cb) { var jsonPath, onChange, ref2, validation, valueHasChanged; ref2 = this.props, onChange = ref2.onChange, validation = ref2.validation, jsonPath = ref2.jsonPath; valueHasChanged = this.state.valueHasChanged; return this.setState({ valueHasChanged: true }, (function(_this) { return function() { _this.validate(validation, value); _this.value = value; if (typeof onChange === "function") { onChange(_this.getValue(), jsonPath); } if (typeof cb === "function") { cb(); } _this.focus(); return _this.fireDelayedAction(); }; })(this)); }, clearValue: function() { return this.handleValueChange(''); } }); module.exports = SelectInputCustom; }).call(this);