UNPKG

react-selectize

Version:

A Stateless & Flexible Select component for React inspired by Selectize

381 lines (380 loc) 14.9 kB
(function(){ var ref$, filter, id, map, isEqualToObject, React, createFactory, div, input, span, findDOMNode, ReactCSSTransitionGroup, ReactTether, DivWrapper, OptionWrapper, cancelEvent, classNameFromObject, DropdownMenu; ref$ = require('prelude-ls'), filter = ref$.filter, id = ref$.id, map = ref$.map; isEqualToObject = require('prelude-extension').isEqualToObject; React = require('react'), createFactory = React.createFactory; ref$ = require('react-dom-factories'), div = ref$.div, input = ref$.input, span = ref$.span; findDOMNode = require('react-dom').findDOMNode; ReactCSSTransitionGroup = createFactory(require('react-transition-group/CSSTransitionGroup')); ReactTether = createFactory(require('./ReactTether')); DivWrapper = createFactory(require('./DivWrapper')); OptionWrapper = createFactory(require('./OptionWrapper')); ref$ = require('./utils'), cancelEvent = ref$.cancelEvent, classNameFromObject = ref$.classNameFromObject; module.exports = DropdownMenu = (function(superclass){ var prototype = extend$((import$(DropdownMenu, superclass).displayName = 'DropdownMenu', DropdownMenu), superclass).prototype, constructor = DropdownMenu; DropdownMenu.defaultProps = { className: "", dropdownDirection: 1, groupId: function(it){ return it.groupId; }, groupsAsColumns: false, highlightedUid: undefined, onHighlightedUidChange: function(uid, callback){}, onOptionClick: function(uid){}, onScrollLockChange: function(scrollLock){}, options: [], renderNoResultsFound: function(){ return div({ className: 'no-results-found' }, "No results found"); }, renderGroupTitle: function(index, arg$){ var groupId, title; if (arg$ != null) { groupId = arg$.groupId, title = arg$.title; } return div({ className: 'simple-group-title', key: groupId }, title); }, renderOption: function(arg$){ var label, newOption, selectable, isSelectable; if (arg$ != null) { label = arg$.label, newOption = arg$.newOption, selectable = arg$.selectable; } isSelectable = typeof selectable === 'undefined' || selectable; return div({ className: "simple-option " + (isSelectable ? '' : 'not-selectable') }, span(null, !!newOption ? "Add " + label + " ..." : label)); }, scrollLock: false, style: {}, tether: false, tetherProps: {}, theme: 'default', transitionEnter: false, transitionLeave: false, transitionEnterTimeout: 200, transitionLeaveTimeout: 200, uid: id }; DropdownMenu.prototype.render = function(){ var dynamicClassName, ref$; dynamicClassName = classNameFromObject((ref$ = {}, ref$[this.props.theme + ""] = 1, ref$[this.props.className + ""] = 1, ref$.flipped = this.props.dropdownDirection === -1, ref$.tethered = this.props.tether, ref$)); if (this.props.tether) { return ReactTether((ref$ = import$({}, this.props.tetherProps), ref$.options = { attachment: "top left", targetAttachment: "bottom left", constraints: [{ to: 'scrollParent' }] }, ref$), this.renderAnimatedDropdown({ dynamicClassName: dynamicClassName })); } else { return this.renderAnimatedDropdown({ dynamicClassName: dynamicClassName }); } }; DropdownMenu.prototype.renderAnimatedDropdown = function(computedState){ var dynamicClassName; dynamicClassName = computedState.dynamicClassName; if (!!this.props.transitionEnter || !!this.props.transitionLeave) { return ReactCSSTransitionGroup({ ref: 'dropdownMenuWrapper', component: 'div', transitionName: 'custom', transitionEnter: this.props.transitionEnter, transitionLeave: this.props.transitionLeave, transitionEnterTimeout: this.props.transitionEnterTimeout, transitionLeaveTimeout: this.props.transitionLeaveTimeout, className: "dropdown-menu-wrapper " + dynamicClassName }, this.renderDropdown(computedState)); } else { return this.renderDropdown(computedState); } }; DropdownMenu.prototype.renderOptions = function(options){ var this$ = this; return map(function(index){ var option, uid; option = options[index]; uid = this$.props.uid(option); return OptionWrapper(import$({ uid: uid, ref: function(element){ this$["option-" + this$.uidToString(uid)] = element; }, key: this$.uidToString(uid), item: option, highlight: isEqualToObject(this$.props.highlightedUid, uid), selectable: option != null ? option.selectable : void 8, onMouseMove: function(arg$){ var currentTarget; currentTarget = arg$.currentTarget; if (this$.props.scrollLock) { this$.props.onScrollLockChange(false); } }, onMouseOut: function(){ if (!this$.props.scrollLock) { this$.props.onHighlightedUidChange(undefined, function(){}); } }, renderItem: this$.props.renderOption }, (function(){ switch (false) { case !(typeof (option != null ? option.selectable : void 8) === 'boolean' && !option.selectable): return { onClick: cancelEvent }; default: return { onClick: function(){ if (!this$.props.scrollLock) { this$.props.onHighlightedUidChange(uid, function(){}); } this$.props.onOptionClick(this$.props.highlightedUid); }, onMouseOver: function(arg$){ var currentTarget; currentTarget = arg$.currentTarget; if ('ontouchstart' in window) { return false; } if (!this$.props.scrollLock) { this$.props.onHighlightedUidChange(uid, function(){}); } } }; } }()))); })( (function(){ var i$, to$, results$ = []; for (i$ = 0, to$ = options.length; i$ < to$; ++i$) { results$.push(i$); } return results$; }())); }; DropdownMenu.prototype.renderDropdown = function(arg$){ var dynamicClassName, ref$, ref1$, groups, this$ = this; dynamicClassName = arg$.dynamicClassName; if (this.props.open) { return DivWrapper({ className: "dropdown-menu " + dynamicClassName, ref: function(element){ !!element && (this$.dropdownMenu = element); }, onHeightChange: function(height){ if (this$.refs.dropdownMenuWrapper) { findDOMNode(this$.refs.dropdownMenuWrapper).style.height = height + "px"; } } }, this.props.options.length === 0 ? this.props.renderNoResultsFound() : ((ref$ = this.props) != null ? (ref1$ = ref$.groups) != null ? ref1$.length : void 8 : void 8) > 0 ? (groups = map(function(index){ var group, groupId, options; group = this$.props.groups[index], groupId = group.groupId; options = filter(function(it){ return this$.props.groupId(it) === groupId; })( this$.props.options); return { index: index, group: group, options: options }; })( (function(){ var i$, to$, results$ = []; for (i$ = 0, to$ = this.props.groups.length; i$ < to$; ++i$) { results$.push(i$); } return results$; }.call(this))), div({ className: "groups " + (!!this.props.groupsAsColumns ? 'as-columns' : '') }, map(function(arg$){ var index, group, groupId, options; index = arg$.index, group = arg$.group, groupId = group.groupId, options = arg$.options; return div({ key: groupId }, this$.props.renderGroupTitle(index, group, options), div({ className: 'options' }, this$.renderOptions(options))); })( filter(function(it){ return it.options.length > 0; })( groups)))) : this.renderOptions(this.props.options)); } else { return null; } }; DropdownMenu.prototype.componentDidUpdate = function(prevProps){ var x$, dropdownMenu, ref$; if (!deepEq$(prevProps.dropdownDirection, this.props.dropdownDirection, '===') && this.props.open) { x$ = dropdownMenu = findDOMNode((ref$ = this.refs.dropdownMenuWrapper) != null ? ref$ : this.dropdownMenu); if (x$ != null) { x$.style.bottom = (function(){ switch (false) { case this.props.dropdownDirection !== -1: return (this.props.bottomAnchor().offsetHeight + dropdownMenu.style.marginBottom) + "px"; default: return ""; } }.call(this)); } } }; DropdownMenu.prototype.highlightAndScrollToOption = function(index, callback){ var uid, this$ = this; callback == null && (callback = function(){}); uid = this.props.uid(this.props.options[index]); this.props.onHighlightedUidChange(uid, function(){ var ref$, optionElement, parentElement, optionHeight; if ((ref$ = findDOMNode(this$ != null ? this$["option-" + this$.uidToString(uid)] : void 8)) != null) { optionElement = ref$; } if (!!optionElement) { parentElement = optionElement.parentElement; optionHeight = optionElement.offsetHeight - 1; if (optionElement.offsetTop - parentElement.scrollTop >= parentElement.offsetHeight) { parentElement.scrollTop = optionElement.offsetTop - parentElement.offsetHeight + optionHeight; } else if (optionElement.offsetTop - parentElement.scrollTop + optionHeight <= 0) { parentElement.scrollTop = optionElement.offsetTop; } } return callback(); }); }; DropdownMenu.prototype.highlightAndScrollToSelectableOption = function(index, direction, callback){ var option, ref$, ref1$, this$ = this; callback == null && (callback = function(){}); if (index < 0 || index >= this.props.options.length) { this.props.onHighlightedUidChange(undefined, function(){ return callback(false); }); } else { option = (ref$ = this.props) != null ? (ref1$ = ref$.options) != null ? ref1$[index] : void 8 : void 8; if (typeof (option != null ? option.selectable : void 8) === 'boolean' && !option.selectable) { this.highlightAndScrollToSelectableOption(index + direction, direction, callback); } else { this.highlightAndScrollToOption(index, function(){ return callback(true); }); } } }; DropdownMenu.prototype.uidToString = function(uid){ return (typeof uid === 'object' ? JSON.stringify : id)(uid); }; function DropdownMenu(){ DropdownMenu.superclass.apply(this, arguments); } return DropdownMenu; }(React.PureComponent)); function extend$(sub, sup){ function fun(){} fun.prototype = (sub.superclass = sup).prototype; (sub.prototype = new fun).constructor = sub; if (typeof sup.extended == 'function') sup.extended(sub); return sub; } function import$(obj, src){ var own = {}.hasOwnProperty; for (var key in src) if (own.call(src, key)) obj[key] = src[key]; return obj; } function deepEq$(x, y, type){ var toString = {}.toString, hasOwnProperty = {}.hasOwnProperty, has = function (obj, key) { return hasOwnProperty.call(obj, key); }; var first = true; return eq(x, y, []); function eq(a, b, stack) { var className, length, size, result, alength, blength, r, key, ref, sizeB; if (a == null || b == null) { return a === b; } if (a.__placeholder__ || b.__placeholder__) { return true; } if (a === b) { return a !== 0 || 1 / a == 1 / b; } className = toString.call(a); if (toString.call(b) != className) { return false; } switch (className) { case '[object String]': return a == String(b); case '[object Number]': return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); case '[object Date]': case '[object Boolean]': return +a == +b; case '[object RegExp]': return a.source == b.source && a.global == b.global && a.multiline == b.multiline && a.ignoreCase == b.ignoreCase; } if (typeof a != 'object' || typeof b != 'object') { return false; } length = stack.length; while (length--) { if (stack[length] == a) { return true; } } stack.push(a); size = 0; result = true; if (className == '[object Array]') { alength = a.length; blength = b.length; if (first) { switch (type) { case '===': result = alength === blength; break; case '<==': result = alength <= blength; break; case '<<=': result = alength < blength; break; } size = alength; first = false; } else { result = alength === blength; size = alength; } if (result) { while (size--) { if (!(result = size in a == size in b && eq(a[size], b[size], stack))){ break; } } } } else { if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) { return false; } for (key in a) { if (has(a, key)) { size++; if (!(result = has(b, key) && eq(a[key], b[key], stack))) { break; } } } if (result) { sizeB = 0; for (key in b) { if (has(b, key)) { ++sizeB; } } if (first) { if (type === '<<=') { result = size < sizeB; } else if (type === '<==') { result = size <= sizeB } else { result = size === sizeB; } } else { first = false; result = size === sizeB; } } } stack.pop(); return result; } } }).call(this);