UNPKG

ldx-widgets

Version:

widgets

277 lines (247 loc) 9.39 kB
(function() { var CircleXButton, DOWN_ARROW, ENTER, ESCAPE, FormValidation, LEFT_ARROW, PropTypes, RIGHT_ARROW, React, SPACE, SelectInputCustom, SelectInputCustomOptions, TAB, UP_ARROW, _, alphaNumericKeyCode, createClass, div, option, ref, ref1, select; React = require('react'); createClass = require('create-react-class'); PropTypes = require('prop-types'); _ = require('lodash'); 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; FormValidation = require('../mixins/form_validation'); CircleXButton = React.createFactory(require('./circle_x_button')); SelectInputCustomOptions = React.createFactory(require('./select_input_custom_options')); ref1 = React.DOM, div = ref1.div, select = ref1.select, option = ref1.option; /*& @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: [FormValidation], contextTypes: { openOverlay: PropTypes.func, closeOverlay: 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 }; }, getInitialState: function() { var ref2, val, value, valueField; ref2 = this.props, value = ref2.value, valueField = ref2.valueField; val = ''; if (typeof value === 'object') { val = value[valueField]; } else { val = value; } return { value: val }; }, render: function() { var disabled, id, isFilter, labelField, optionItems, options, ref2, roomForCircleXStyle, selectText, tabIndex, value, valueField; 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 = this.state.value; optionItems = []; optionItems.push(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)); this.getErrors(); roomForCircleXStyle = value && !disabled ? "x-room" : ""; return div({ className: "field-wrap filter-select " + this.invalidClass + " " + roomForCircleXStyle }, [ select({ key: 'select', ref: (function(_this) { return function(control) { return _this.control = control; }; })(this), tabIndex: tabIndex, id: id, disabled: disabled, value: value, onMouseDown: this.handleNativeEvent, onKeyDown: this.handleNativeEvent }, optionItems), value && !disabled ? CircleXButton({ key: 'clear', tabIndex: tabIndex, ref: (function(_this) { return function(clearBtn) { return _this.clearBtn = clearBtn; }; })(this), onClick: this.clear }) : void 0, this.validationErrors.length ? div({ className: 'field-errors-show', key: 'errors' }, [ div({ className: 'field-errors', key: 'err' }, ul({ className: 'field-errors-list' }, this.validationErrors)) ]) : void 0 ]); }, handleNativeEvent: function(e) { var alphaNum, closeKeys, height, isCloseKey, isFilter, isOpenKey, keyCode, labelField, nibColor, openKeys, optionHeight, options, overlay, placeholder, ref2, selectText, value, valueField, width; keyCode = e.keyCode; ref2 = this.props, options = ref2.options, selectText = ref2.selectText, labelField = ref2.labelField, valueField = ref2.valueField, height = ref2.height, width = ref2.width, placeholder = ref2.placeholder, isFilter = ref2.isFilter, nibColor = ref2.nibColor, optionHeight = ref2.optionHeight; value = this.state.value; openKeys = [DOWN_ARROW, RIGHT_ARROW, LEFT_ARROW, UP_ARROW, ENTER, SPACE]; closeKeys = [ESCAPE, TAB]; if (((options.length + 1) * optionHeight) < height) { height = (options.length + 2) * optionHeight; } overlay = { activeComponent: 'pvr', close: this.context.closeOverlay, direction: 'below', element: { key: 'fso', options: options, onChange: this.handleChange, labelField: labelField, valueField: valueField, placeholder: placeholder, value: value, SelectEl: this, isFilter: isFilter }, width: width, height: height, anchor: e.currentTarget, noBackdrop: true, nibColor: nibColor, optionHeight: optionHeight }; 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) { overlay.element.filter = e.key; } overlay.element = SelectInputCustomOptions(overlay.element); this.context.openOverlay(overlay); } else if (isCloseKey) { if (keyCode !== TAB) { e.preventDefault(); } this.context.closeOverlay(); } return; } overlay.element = SelectInputCustomOptions(overlay.element); e.preventDefault(); return this.context.openOverlay(overlay); }, handleChange: function(value, cb) { return this.setState({ value: value }, (function(_this) { return function() { _this.props.onChange(value); _this.focus(); return typeof cb === "function" ? cb() : void 0; }; })(this)); }, clear: function() { return this.handleChange(''); }, focus: function() { return this.control.focus(); }, getValue: function() { var ref2, returnFullObjects, valueField; ref2 = this.props, returnFullObjects = ref2.returnFullObjects, valueField = ref2.valueField; if (returnFullObjects) { return _.find(this.props.options, (function(_this) { return function(o) { var v; v = o[valueField]; if (typeof v === 'number') { v = v.toString(); } return v === _this.control.value; }; })(this)); } else { return this.control.value; } } }); module.exports = SelectInputCustom; }).call(this);