react-selectize
Advanced tools
Comparing version 0.1.6 to 0.2.0
@@ -18,3 +18,11 @@ # React Selectize | ||
## v0.1.6 / 19h September 2015 | ||
## v0.1.6 / 19th September 2015 | ||
* introduced a new prop `autosize`, allows consumers to provide custom autosize logic for search input, the default implementation now supports nonmodern browsers | ||
## v0.2.0 / 19th September 2015 | ||
* drop in replacement for React.DOM.Select, accepts options as children | ||
* added a new prop `dropdownDirection`, setting it to -1 forces the options menu to open upwards | ||
* option group support (as rows and columns) | ||
* updated the signature of refs.selectInstance.focus from `a -> Void` to `a -> (a -> Void) -> Void`, i.e. the focus function now accepts a callback as the first parameter which is fired when the options menu is visible | ||
* improved performance by implementing shouldComponentUpdate lifecycle method for *Wrapper classes, added `uid :: (Eq e) => Item -> e` prop | ||
* changed the signature of renderOption & renderValue props from `Int -> Item -> ReactElement` to `Item -> ReactElement` |
{ | ||
"name": "react-selectize", | ||
"version": "0.1.6", | ||
"version": "0.2.0", | ||
"description": "react implementation of selectize", | ||
@@ -20,3 +20,4 @@ "main": "src/index.js", | ||
"browserify": "^9.0.3", | ||
"gulp": "^3.8.11", | ||
"browserify-shim": "^3.8.10", | ||
"gulp": "^3.8.11", | ||
"gulp-connect": "^2.2.0", | ||
@@ -37,3 +38,3 @@ "gulp-if": "^1.2.5", | ||
"watchify": "^2.4.0" | ||
}, | ||
}, | ||
"repository": { | ||
@@ -54,2 +55,2 @@ "type": "git", | ||
] | ||
} | ||
} |
# React Selectize | ||
A flexible & stateless select component for ReactJS built with livescript and love. | ||
ReactSelectize comes in 3 flavours SimpleSelect (or single select), MultiSelect & ReactSelectize. Both the SimpleSelect & the MultiSelect components are built on top of the stateless ReactSelectize component. | ||
A flexible & stateless select component for ReactJS built with livescript and love. | ||
ReactSelectize comes in 3 flavors SimpleSelect (or single select), MultiSelect & ReactSelectize. Both the SimpleSelect & the MultiSelect components are built on top of the stateless ReactSelectize component. | ||
LIVE DEMO: [furqanZafar.github.io/react-selectize](http://furqanZafar.github.io/react-selectize/) | ||
@@ -9,2 +10,17 @@ | ||
## Features | ||
* Drop in replacement for React.DOM.Select | ||
* Stateless, therefore extremely flexible & extensible | ||
* Clean and compact API fully documented on GitHub | ||
* Multiselect support | ||
* Option groups | ||
* Custom filtering & option object | ||
* Custom option & value rendering | ||
* Remote data loading | ||
* Tagging or item creation | ||
* Caret between items | ||
* Customizable dropdown direction | ||
* Mark options as unselectable | ||
* Customizable styles, comes with Stylus files | ||
## Install | ||
@@ -53,5 +69,2 @@ | ||
placeholder = "Select a fruit" | ||
options = ["apple", "mango", "orange", "banana"].map(function(fruit){ | ||
return {label: fruit, value: fruit}; | ||
}); | ||
onValueChange = {function(value, callback){ | ||
@@ -61,6 +74,12 @@ alert(value); | ||
}} | ||
/> | ||
> | ||
<option value = "apple">apple</option> | ||
<option value = "mango">mango</option> | ||
<option value = "orange">orange</option> | ||
<option value = "banana">banana</option> | ||
</SimpleSelect> | ||
. | ||
. | ||
. | ||
// Note: options can be passed as props as well, for example | ||
<MultiSelect | ||
@@ -89,30 +108,36 @@ placeholder = "Select fruits" | ||
| Property | Type | Description| | ||
|----------------------------|------------------------------------|--------------------------------| | ||
| Property | Type | Description | | ||
|----------------------------|--------------------------------|--------------------------------| | ||
| autosize | InputElement -> Int | `function($search){return $search.value.length * 10}` custom logic for autosizing the input element| | ||
| className | String | class name for the outer element, in addition to "simple-select"| | ||
| disabled | Boolean | disables interaction with the Select control| | ||
| createFromSearch | [Item] -> String -> Item? | implement this function to create new items on the fly, `function(options, search){return {label: search, value: search}}`, return null to avoid option creation for the given parameters| | ||
| filterOptions | [Item]-> String -> [Item] | implement this function for custom synchronous filtering logic, `function(options, search) {return options}`| | ||
| onBlur | Item -> String -> Void | `function(value, reason){}` reason can be either "click" (loss of focus because the user clicked elsewhere), "tab" or "blur" (invoked refs.simpleSelect.blur())| | ||
| onFocus | Item -> String -> Void | `function(value, reason){}` reason can be either "event" (when the control gains focus outside) or "focus" (when the user invokes refs.simpleSelect.focus())| | ||
| onSearchChange | String -> (a -> Void) -> Void | `function(search, callback){self.setState({search: search}, callback);}` or `function(search,callback){callback();}` i.e. callback MUST always be invoked| | ||
| onValueChange | Item -> (a -> Void) -> Void | `function(selectedValue, callback){self.setState({selectedValue: selectedValue}, callback)}` or `function(value, callback){callback()}` i.e. callback MUST always be invoked| | ||
| options | [Item] | list of items by default each option object MUST have label & value property, otherwise you must implement the render* & filterOptions methods| | ||
| placeholder: | String | displayed when there is no value| | ||
| renderNoResultsFound | Item -> String -> ReactElement | `function(item, search){return React.DOM.div(null);}` returns a custom way for rendering the "No results found" error| | ||
| renderOption | Int -> Item -> ReactElement | `function(index, item){return React.DOM.div(null);}` returns a custom way for rendering each option| | ||
| renderValue | Int -> Item -> ReactElement | `function(index, item){return React.DOM.div(null);}` returns a custom way for rendering the selected value| | ||
| restoreOnBackspace | Item -> String | `function(item){return item.label;}` implement this method if you want to go back to editing the item when the user hits the [backspace] key instead of getting removed| | ||
| search | String | the text displayed in the search box| | ||
| style | Object | the CSS styles for the outer element| | ||
| value | Item | the selected value, i.e. one of the objects in the options array| | ||
| className | String | class name for the outer element, in addition to "simple-select"| | ||
| disabled | Boolean | disables interaction with the Select control| | ||
| dropdownDirection | Int | defaults to 1, setting it to -1 opens the dropdown upward| | ||
| createFromSearch | [Item] -> String -> Item? | implement this function to create new items on the fly, `function(options, search){return {label: search, value: search}}`, return null to avoid option creation for the given parameters| | ||
| filterOptions | [Item]-> String -> [Item] | implement this function for custom synchronous filtering logic, `function(options, search) {return options}`| | ||
| groupId | Item -> b | `function(item){return item.groupId}` this function is used to identify which group an option belongs to, it must return a value that matches the groupId property of an object in the groups collection| | ||
| groups | [Group] | collection of objects where each object must atleast have a groupId property| | ||
| groupsAsColumns | Boolean | display option groups in columns| | ||
| onBlur | Item -> String -> Void | `function(value, reason){}` reason can be either "click" (loss of focus because the user clicked elsewhere), "tab" or "blur" (invoked refs.simpleSelect.blur())| | ||
| onFocus | Item -> String -> Void | `function(value, reason){}` reason can be either "event" (when the control gains focus outside) or "focus" (when the user invokes refs.simpleSelect.focus())| | ||
| onSearchChange | String -> (a -> Void) -> Void | `function(search, callback){self.setState({search: search}, callback);}` or `function(search,callback){callback();}` i.e. callback MUST always be invoked| | ||
| onValueChange | Item -> (a -> Void) -> Void | `function(selectedValue, callback){self.setState({selectedValue: selectedValue}, callback)}` or `function(value, callback){callback()}` i.e. callback MUST always be invoked| | ||
| options | [Item] | list of items by default each option object MUST have label & value property, otherwise you must implement the render* & filterOptions methods| | ||
| placeholder | String | displayed when there is no value| | ||
| renderNoResultsFound | Item -> String -> ReactElement | `function(item, search){return React.DOM.div(null);}` returns a custom way for rendering the "No results found" error| | ||
| renderGroupTitle | Int -> Group -> ReactElement | `function(index, group){return React.DOM.div(null)}` returns a custom way for rendering the group title| | ||
| renderOption | Item -> ReactElement | `function(item){return React.DOM.div(null);}` returns a custom way for rendering each option| | ||
| renderValue | Item -> ReactElement | `function(item){return React.DOM.div(null);}` returns a custom way for rendering the selected value| | ||
| restoreOnBackspace | Item -> String | `function(item){return item.label;}` implement this method if you want to go back to editing the item when the user hits the [backspace] key instead of getting removed| | ||
| search | String | the text displayed in the search box| | ||
| style | Object | the CSS styles for the outer element| | ||
| uid | (Eq e) => Item -> e | `function(item){return item.value}` returns a unique id for a given option, defaults to the value property| | ||
| value | Item | the selected value, i.e. one of the objects in the options array| | ||
## SimpleSelect methods | ||
| Method | Type | Description | | ||
|---------------------------------|------------------------------------|--------------------------------| | ||
| focus | a -> Void | `this.refs.selectInstance.focus()` opens the list of options and positions the cursor in the input control| | ||
| highlightFirstSelectableOption | a -> Void | `this.refs.selectInstance.highlightFirstSelectableOption()`| | ||
| value | a -> Item | `this.refs.selectInstance.value()` returns the current selected item| | ||
| Method | Type | Description | | ||
|---------------------------------|--------------------------|--------------------------------| | ||
| focus | a -> (a -> Void) -> Void | `this.refs.selectInstance.focus(callback)` opens the list of options and positions the cursor in the input control, the callback fired when the options menu becomes visible| | ||
| highlightFirstSelectableOption | a -> Void | `this.refs.selectInstance.highlightFirstSelectableOption()`| | ||
| value | a -> Item | `this.refs.selectInstance.value()` returns the current selected item| | ||
@@ -134,3 +159,3 @@ ## MultiSelect Props | ||
## MultSelect methods | ||
## MultiSelect methods | ||
@@ -137,0 +162,0 @@ same as SimpleSelect but use `this.refs.multiSelectInstance.values()` to get the selected values instead of the `value` method. |
(function(){ | ||
var ref$, all, any, camelize, difference, drop, filter, find, findIndex, last, map, reject, isEqualToObject, React, createFactory, div, img, span, ReactSelectize; | ||
var ref$, all, any, camelize, difference, drop, filter, find, findIndex, last, map, reject, isEqualToObject, React, createFactory, div, img, span, ReactSelectize, toString$ = {}.toString; | ||
ref$ = require('prelude-ls'), all = ref$.all, any = ref$.any, camelize = ref$.camelize, difference = ref$.difference, drop = ref$.drop, filter = ref$.filter, find = ref$.find, findIndex = ref$.findIndex, last = ref$.last, map = ref$.map, reject = ref$.reject; | ||
@@ -37,9 +37,14 @@ isEqualToObject = require('prelude-extension').isEqualToObject; | ||
render: function(){ | ||
var ref$, anchor, search, values, onAnchorChange, onSearchChange, onValuesChange, filteredOptions, options, autosize, this$ = this; | ||
var ref$, anchor, search, values, onAnchorChange, onSearchChange, onValuesChange, filteredOptions, options, autosize, disabled, dropdownDirection, groupId, groups, groupsAsColumns, renderGroupTitle, this$ = this; | ||
ref$ = this.getComputedState(), anchor = ref$.anchor, search = ref$.search, values = ref$.values, onAnchorChange = ref$.onAnchorChange, onSearchChange = ref$.onSearchChange, onValuesChange = ref$.onValuesChange, filteredOptions = ref$.filteredOptions, options = ref$.options; | ||
autosize = this.props.autosize; | ||
ref$ = this.props, autosize = ref$.autosize, disabled = ref$.disabled, dropdownDirection = ref$.dropdownDirection, groupId = ref$.groupId, groups = ref$.groups, groupsAsColumns = ref$.groupsAsColumns, renderGroupTitle = ref$.renderGroupTitle; | ||
return ReactSelectize(import$({ | ||
autosize: autosize, | ||
className: "multi-select " + this.props.className, | ||
disabled: this.props.disabled, | ||
disabled: disabled, | ||
dropdownDirection: dropdownDirection, | ||
groupId: groupId, | ||
groups: groups, | ||
groupsAsColumns: groupsAsColumns, | ||
renderGroupTitle: renderGroupTitle, | ||
ref: 'select', | ||
@@ -58,2 +63,8 @@ anchor: anchor, | ||
}, | ||
highlightedUid: this.state.highlightedUid, | ||
onHighlightedUidChange: function(highlightedUid, callback){ | ||
return this$.setState({ | ||
highlightedUid: highlightedUid | ||
}, callback); | ||
}, | ||
firstOptionIndexToHighlight: function(){ | ||
@@ -71,3 +82,2 @@ return this$.firstOptionIndexToHighlight(options); | ||
return onValuesChange(newValues, function(){ | ||
this$.refs.select.focus(); | ||
if (this$.props.closeOnSelect || (!!this$.props.maxValues && newValues.length >= this$.props.maxValues)) { | ||
@@ -78,3 +88,3 @@ return this$.setState({ | ||
} else { | ||
return callback(); | ||
return this$.focus(callback); | ||
} | ||
@@ -119,3 +129,3 @@ }); | ||
getComputedState: function(){ | ||
var anchor, search, values, ref$, onAnchorChange, onSearchChange, onValuesChange, filteredOptions, newOption, options, this$ = this; | ||
var anchor, search, values, ref$, onAnchorChange, onSearchChange, onValuesChange, optionsFromChildren, unfilteredOptions, filteredOptions, newOption, options, this$ = this; | ||
anchor = this.props.hasOwnProperty('anchor') | ||
@@ -151,3 +161,25 @@ ? this.props.anchor | ||
['anchor', 'search', 'values']), onAnchorChange = ref$[0], onSearchChange = ref$[1], onValuesChange = ref$[2]; | ||
filteredOptions = this.props.filterOptions(this.props.options, values, search); | ||
optionsFromChildren = (function(){ | ||
var ref$; | ||
switch (false) { | ||
case !((ref$ = this.props) != null && ref$.children): | ||
return map(function(arg$){ | ||
var ref$, value, children; | ||
ref$ = arg$.props, value = ref$.value, children = ref$.children; | ||
return { | ||
label: children, | ||
value: value | ||
}; | ||
})( | ||
toString$.call(this.props.children).slice(8, -1) === 'Array' | ||
? this.props.children | ||
: [this.props.children]); | ||
default: | ||
return []; | ||
} | ||
}.call(this)); | ||
unfilteredOptions = this.props.hasOwnProperty('options') ? (ref$ = this.props.options) != null | ||
? ref$ | ||
: [] : optionsFromChildren; | ||
filteredOptions = this.props.filterOptions(unfilteredOptions, values, search); | ||
newOption = typeof this.props.createFromSearch === 'function' ? this.props.createFromSearch(filteredOptions, values, search) : null; | ||
@@ -171,2 +203,3 @@ options = (!!newOption | ||
anchor: !!this.props.values ? last(this.props.values) : undefined, | ||
highlightedUid: undefined, | ||
open: false, | ||
@@ -196,5 +229,5 @@ search: "", | ||
}, | ||
focus: function(){ | ||
focus: function(callback){ | ||
this.refs.select.focus(); | ||
this.showOptions; | ||
return this.showOptions(callback); | ||
}, | ||
@@ -201,0 +234,0 @@ highlightFirstSelectableOption: function(){ |
(function(){ | ||
var ref$, each, filter, find, findIndex, initial, last, map, objToPairs, partition, reject, reverse, sortBy, clamp, isEqualToObject, React, div, input, span, cancelEvent; | ||
ref$ = require('prelude-ls'), each = ref$.each, filter = ref$.filter, find = ref$.find, findIndex = ref$.findIndex, initial = ref$.initial, last = ref$.last, map = ref$.map, objToPairs = ref$.objToPairs, partition = ref$.partition, reject = ref$.reject, reverse = ref$.reverse, sortBy = ref$.sortBy; | ||
var ref$, each, filter, find, findIndex, initial, last, map, objToPairs, partition, reject, reverse, sortBy, sum, clamp, isEqualToObject, React, div, input, span, createClass, createFactory, cancelEvent, OptionWrapper, ValueWrapper; | ||
ref$ = require('prelude-ls'), each = ref$.each, filter = ref$.filter, find = ref$.find, findIndex = ref$.findIndex, initial = ref$.initial, last = ref$.last, map = ref$.map, objToPairs = ref$.objToPairs, partition = ref$.partition, reject = ref$.reject, reverse = ref$.reverse, sortBy = ref$.sortBy, sum = ref$.sum; | ||
ref$ = require('prelude-extension'), clamp = ref$.clamp, isEqualToObject = ref$.isEqualToObject; | ||
React = require('react'), ref$ = React.DOM, div = ref$.div, input = ref$.input, span = ref$.span; | ||
React = require('react'), ref$ = React.DOM, div = ref$.div, input = ref$.input, span = ref$.span, createClass = React.createClass, createFactory = React.createFactory; | ||
cancelEvent = function(e){ | ||
@@ -10,5 +10,30 @@ e.preventDefault(); | ||
}; | ||
module.exports = React.createClass({ | ||
OptionWrapper = createFactory(createClass({ | ||
render: function(){ | ||
return div({ | ||
className: "option-wrapper " + (!!this.props.highlight ? 'highlight' : ''), | ||
onClick: this.props.onClick, | ||
onMouseMove: this.props.onMouseMove, | ||
onMouseOut: this.props.onMouseOut, | ||
onMouseOver: this.props.onMouseOver | ||
}, this.props.renderItem(this.props.item)); | ||
}, | ||
shouldComponentUpdate: function(nextProps){ | ||
var ref$, ref1$; | ||
return (nextProps != null ? nextProps.uid : void 8) !== ((ref$ = this.props) != null ? ref$.uid : void 8) || (nextProps != null ? nextProps.highlight : void 8) !== ((ref1$ = this.props) != null ? ref1$.highlight : void 8); | ||
} | ||
})); | ||
ValueWrapper = createFactory(createClass({ | ||
render: function(){ | ||
return div({ | ||
className: 'value-wrapper' | ||
}, this.props.renderItem(this.props.item)); | ||
}, | ||
shouldComponentUpdate: function(nextProps){ | ||
var ref$; | ||
return (nextProps != null ? nextProps.uid : void 8) !== ((ref$ = this.props) != null ? ref$.uid : void 8); | ||
} | ||
})); | ||
module.exports = createClass({ | ||
displayName: 'ReactSelectize', | ||
highlightedOption: -1, | ||
focusLock: false, | ||
@@ -47,8 +72,15 @@ scrollLock: false, | ||
disabled: false, | ||
dropdownDirection: 1, | ||
firstOptionIndexToHighlight: function(options){ | ||
return 0; | ||
}, | ||
groupId: function(it){ | ||
return it.groupId; | ||
}, | ||
groupsAsColumns: false, | ||
highlightedUid: undefined, | ||
onAnchorChange: function(anchor){}, | ||
onBlur: function(values, reason){}, | ||
onFocus: function(values, reason){}, | ||
onHighlightedUidChange: function(uid, callback){}, | ||
onOpenChange: function(open, callback){}, | ||
@@ -64,3 +96,13 @@ onSearchChange: function(search, callback){}, | ||
}, | ||
renderOption: function(index, arg$){ | ||
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; | ||
@@ -72,12 +114,10 @@ if (arg$ != null) { | ||
return div({ | ||
className: "simple-option " + (isSelectable ? '' : 'not-selectable'), | ||
key: index | ||
className: "simple-option " + (isSelectable ? '' : 'not-selectable') | ||
}, span(null, !!newOption ? "Add " + label + " ..." : label)); | ||
}, | ||
renderValue: function(index, arg$){ | ||
renderValue: function(arg$){ | ||
var label; | ||
label = arg$.label; | ||
return div({ | ||
className: 'simple-value', | ||
key: index | ||
className: 'simple-value' | ||
}, span(null, label)); | ||
@@ -87,2 +127,5 @@ }, | ||
style: {}, | ||
uid: function(it){ | ||
return it.value; | ||
}, | ||
values: [] | ||
@@ -92,3 +135,3 @@ }; | ||
render: function(){ | ||
var anchorIndex, this$ = this; | ||
var anchorIndex, renderOptions, ref$, ref1$, groups, this$ = this; | ||
anchorIndex = (function(){ | ||
@@ -108,7 +151,7 @@ var ref$; | ||
return div({ | ||
className: "react-selectize " + this.props.className + " " + (this.props.disabled ? 'disabled' : '') + " " + (this.props.open ? 'open' : ''), | ||
className: ("react-selectize \n" + this.props.className + " \n" + (this.props.disabled ? 'disabled' : '') + " \n" + (this.props.open ? 'open' : '') + " \n" + (this.props.dropdownDirection === -1 ? 'flipped' : '')).replace(/\s+/g, ' '), | ||
style: this.props.style | ||
}, div({ | ||
className: 'control', | ||
key: 'control', | ||
ref: 'control', | ||
onClick: function(){ | ||
@@ -124,3 +167,9 @@ return this$.props.onAnchorChange(last(this$.props.values), function(){ | ||
}, this.props.placeholder) : void 8, map(function(index){ | ||
return this$.props.renderValue(index, this$.props.values[index]); | ||
var item; | ||
item = this$.props.values[index]; | ||
return ValueWrapper({ | ||
uid: this$.props.uid(item), | ||
item: item, | ||
renderItem: this$.props.renderValue | ||
}); | ||
})( | ||
@@ -143,3 +192,3 @@ (function(){ | ||
if (!this$.highlightAndScrollToSelectableOption(this$.props.firstOptionIndexToHighlight(this$.props.options), 1)) { | ||
return this$.lowlightOption(); | ||
return this$.props.onHighlightedUidChange(undefined); | ||
} | ||
@@ -164,2 +213,3 @@ }); | ||
onKeyDown: function(e){ | ||
var ref$; | ||
switch (e.which) { | ||
@@ -253,9 +303,3 @@ case 9: | ||
if (e.which === 13 && this$.props.open) { | ||
this$.selectHighlightedOption(anchorIndex, function(){ | ||
if (this$.props.open && !this$.highlightAndScrollToSelectableOption(this$.highlightedOption, 1)) { | ||
if (!this$.highlightAndScrollToSelectableOption(0, 1)) { | ||
return this$.lowlightOption(); | ||
} | ||
} | ||
}); | ||
this$.selectHighlightedUid(anchorIndex, function(){}); | ||
} else { | ||
@@ -265,7 +309,9 @@ switch (e.which) { | ||
this$.scrollLock = true; | ||
this$.highlightAndScrollToSelectableOption(this$.highlightedOption - 1, -1); | ||
this$.highlightAndScrollToSelectableOption(this$.optionIndexFromUid(this$.props.highlightedUid) - 1, -1); | ||
break; | ||
case 40: | ||
this$.scrollLock = true; | ||
this$.highlightAndScrollToSelectableOption(this$.highlightedOption + 1, 1); | ||
this$.highlightAndScrollToSelectableOption(((ref$ = this$.optionIndexFromUid(this$.props.highlightedUid)) != null | ||
? ref$ | ||
: -1) + 1, 1); | ||
break; | ||
@@ -279,3 +325,9 @@ default: | ||
}), map(function(index){ | ||
return this$.props.renderValue(index, this$.props.values[index]); | ||
var item; | ||
item = this$.props.values[index]; | ||
return ValueWrapper({ | ||
uid: this$.props.uid(item), | ||
item: item, | ||
renderItem: this$.props.renderValue | ||
}); | ||
})( | ||
@@ -302,13 +354,13 @@ (function(){ | ||
className: 'arrow' | ||
}, null)), this.props.open ? div({ | ||
className: 'options' | ||
}, this.props.options.length === 0 | ||
? this.props.renderNoResultsFound() | ||
: map(function(index){ | ||
var option; | ||
option = this$.props.options[index]; | ||
return div(import$({ | ||
className: 'option-wrapper', | ||
ref: "option-" + index, | ||
key: index + "", | ||
}, null)), this.props.open ? (renderOptions = function(options, indexOffset){ | ||
return map(function(index){ | ||
var option, uid; | ||
option = options[index]; | ||
uid = this$.props.uid(option); | ||
return OptionWrapper(import$({ | ||
uid: uid, | ||
ref: "option-" + uid, | ||
key: uid, | ||
item: option, | ||
highlight: this$.props.highlightedUid === uid, | ||
onMouseMove: function(arg$){ | ||
@@ -323,5 +375,6 @@ var currentTarget; | ||
if (!this$.scrollLock) { | ||
this$.lowlightOption(); | ||
this$.props.onHighlightedUidChange(undefined); | ||
} | ||
} | ||
}, | ||
renderItem: this$.props.renderOption | ||
}, (function(){ | ||
@@ -336,3 +389,3 @@ switch (false) { | ||
onClick: function(e){ | ||
this$.selectHighlightedOption(anchorIndex, function(){}); | ||
this$.selectHighlightedUid(anchorIndex, function(){}); | ||
}, | ||
@@ -343,3 +396,3 @@ onMouseOver: function(arg$){ | ||
if (!this$.scrollLock) { | ||
this$.highlightOption(index); | ||
this$.props.onHighlightedUidChange(uid); | ||
} | ||
@@ -349,11 +402,63 @@ } | ||
} | ||
}())), this$.props.renderOption(index, option)); | ||
}()))); | ||
})( | ||
(function(){ | ||
var i$, to$, results$ = []; | ||
for (i$ = 0, to$ = this.props.options.length; i$ < to$; ++i$) { | ||
for (i$ = 0, to$ = options.length; i$ < to$; ++i$) { | ||
results$.push(i$); | ||
} | ||
return results$; | ||
}.call(this)))) : void 8); | ||
}())); | ||
}, div({ | ||
className: 'dropdown', | ||
ref: 'dropdown' | ||
}, 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, offset; | ||
index = arg$.index, group = arg$.group, groupId = group.groupId, options = arg$.options; | ||
offset = sum( | ||
map(function(it){ | ||
return groups[it].options.length; | ||
})( | ||
(function(){ | ||
var i$, to$, results$ = []; | ||
for (i$ = 0, to$ = index; i$ < to$; ++i$) { | ||
results$.push(i$); | ||
} | ||
return results$; | ||
}()))); | ||
return div({ | ||
key: groupId | ||
}, this$.props.renderGroupTitle(index, group, options), div({ | ||
className: 'options' | ||
}, renderOptions(options, offset))); | ||
})( | ||
filter(function(it){ | ||
return it.options.length > 0; | ||
})( | ||
groups)))) | ||
: renderOptions(this.props.options, 0))) : void 8); | ||
}, | ||
@@ -386,3 +491,3 @@ componentDidMount: function(){ | ||
var x$, $search; | ||
if (this.props.open && !prevProps.open && (this.highlightedOption = -1)) { | ||
if (this.props.open && !prevProps.open && this.props.highlightedUid === undefined) { | ||
this.highlightAndScrollToSelectableOption(this.props.firstOptionIndexToHighlight(this.props.options), 1); | ||
@@ -392,3 +497,3 @@ this.focus(); | ||
if (!this.props.open && prevProps.open) { | ||
this.highlightedOption = -1; | ||
this.props.onHighlightedUidChange(undefined); | ||
} | ||
@@ -398,3 +503,5 @@ x$ = $search = this.refs.search.getDOMNode(); | ||
x$.style.width = this.props.autosize($search); | ||
return x$; | ||
if (!!this.refs.dropdown) { | ||
this.refs.dropdown.getDOMNode().style.bottom = this.props.dropdownDirection === -1 ? this.refs.control.getDOMNode().offsetHeight : ""; | ||
} | ||
}, | ||
@@ -406,7 +513,8 @@ componentWillReceiveProps: function(props){ | ||
}, | ||
focus: function(){ | ||
if (this.refs.search.getDOMNode() !== document.activeElement) { | ||
this.focusLock = true; | ||
this.refs.search.getDOMNode().focus(); | ||
} | ||
optionIndexFromUid: function(uid){ | ||
var this$ = this; | ||
return findIndex(function(it){ | ||
return uid === this$.props.uid(it); | ||
})( | ||
this.props.options); | ||
}, | ||
@@ -417,37 +525,27 @@ blur: function(){ | ||
}, | ||
highlightOption: function(index){ | ||
var x$, optionElement, ref$, ref1$; | ||
this.lowlightOption(); | ||
this.highlightedOption = index; | ||
x$ = optionElement = (ref$ = this.refs) != null ? (ref1$ = ref$["option-" + index]) != null ? ref1$.getDOMNode() : void 8 : void 8; | ||
if (x$ != null) { | ||
x$.className = "option-wrapper focused"; | ||
focus: function(){ | ||
if (this.refs.search.getDOMNode() !== document.activeElement) { | ||
this.focusLock = true; | ||
this.refs.search.getDOMNode().focus(); | ||
} | ||
return optionElement; | ||
}, | ||
lowlightOption: function(){ | ||
var ref$, ref1$, ref2$; | ||
if ((ref$ = this.refs) != null) { | ||
if ((ref1$ = ref$["option-" + this.highlightedOption]) != null) { | ||
if ((ref2$ = ref1$.getDOMNode()) != null) { | ||
ref2$.className = 'option-wrapper'; | ||
highlightAndScrollToOption: function(index){ | ||
var uid, this$ = this; | ||
uid = this.props.uid(this.props.options[index]); | ||
this.props.onHighlightedUidChange(uid, function(){ | ||
var ref$, ref1$, optionElement, parentElement, optionHeight; | ||
if ((ref$ = (ref1$ = this$.refs) != null ? ref1$["option-" + uid].getDOMNode() : void 8) != null) { | ||
optionElement = ref$; | ||
} | ||
parentElement = this$.refs.dropdown.getDOMNode(); | ||
if (!!optionElement) { | ||
optionHeight = optionElement.offsetHeight - 1; | ||
if (optionElement.offsetTop - parentElement.scrollTop >= parentElement.offsetHeight) { | ||
return parentElement.scrollTop = optionElement.offsetTop - parentElement.offsetHeight + optionHeight; | ||
} else if (optionElement.offsetTop - parentElement.scrollTop + optionHeight <= 0) { | ||
return parentElement.scrollTop = optionElement.offsetTop; | ||
} | ||
} | ||
} | ||
this.highlightedOption = -1; | ||
}); | ||
}, | ||
highlightAndScrollToOption: function(index){ | ||
var optionElement, parentElement, optionHeight; | ||
if ((optionElement = this.highlightOption(index)) != null) { | ||
parentElement = optionElement.parentElement; | ||
} | ||
if (!!optionElement) { | ||
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; | ||
} | ||
} | ||
}, | ||
highlightAndScrollToSelectableOption: function(index, direction){ | ||
@@ -480,36 +578,51 @@ var this$ = this; | ||
}, | ||
selectHighlightedOption: function(anchorIndex, callback){ | ||
var option, ref$, this$ = this; | ||
if (this.highlightedOption !== -1) { | ||
option = (ref$ = this.props.options) != null ? ref$[this.highlightedOption] : void 8; | ||
this.props.onValuesChange(map(function(it){ | ||
return this$.props.values[it]; | ||
}, (function(){ | ||
var i$, to$, results$ = []; | ||
for (i$ = 0, to$ = anchorIndex; i$ <= to$; ++i$) { | ||
results$.push(i$); | ||
} | ||
return results$; | ||
}())).concat([option], map(function(it){ | ||
return this$.props.values[it]; | ||
}, (function(){ | ||
var i$, to$, results$ = []; | ||
for (i$ = anchorIndex + 1, to$ = this.props.values.length; i$ < to$; ++i$) { | ||
results$.push(i$); | ||
} | ||
return results$; | ||
}.call(this)))), function(){ | ||
var value; | ||
value = find(function(it){ | ||
return isEqualToObject(it, option); | ||
}, this$.props.values); | ||
if (!!value) { | ||
return this$.props.onSearchChange("", function(){ | ||
return this$.props.onAnchorChange(value, callback); | ||
selectHighlightedUid: function(anchorIndex, callback){ | ||
var index, option, this$ = this; | ||
if (this.props.highlightedUid === undefined) { | ||
return; | ||
} | ||
index = this.optionIndexFromUid(this.props.highlightedUid); | ||
if (typeof index !== 'number') { | ||
return; | ||
} | ||
option = this.props.options[index]; | ||
this.props.onValuesChange(map(function(it){ | ||
return this$.props.values[it]; | ||
}, (function(){ | ||
var i$, to$, results$ = []; | ||
for (i$ = 0, to$ = anchorIndex; i$ <= to$; ++i$) { | ||
results$.push(i$); | ||
} | ||
return results$; | ||
}())).concat([option], map(function(it){ | ||
return this$.props.values[it]; | ||
}, (function(){ | ||
var i$, to$, results$ = []; | ||
for (i$ = anchorIndex + 1, to$ = this.props.values.length; i$ < to$; ++i$) { | ||
results$.push(i$); | ||
} | ||
return results$; | ||
}.call(this)))), function(){ | ||
var value; | ||
value = find(function(it){ | ||
return isEqualToObject(it, option); | ||
}, this$.props.values); | ||
if (!!value) { | ||
return this$.props.onSearchChange("", function(){ | ||
return this$.props.onAnchorChange(value, function(){ | ||
var ref$; | ||
if (!!this$.props.open) { | ||
if (!!((ref$ = this$.props.options) != null && ref$[index])) { | ||
return this$.props.onHighlightedUidChange(this$.props.uid(this$.props.options[index], callback)); | ||
} else { | ||
this$.highlightAndScrollToSelectableOption(this$.props.firstOptionIndexToHighlight(this$.props.options), 1); | ||
return callback(); | ||
} | ||
} | ||
}); | ||
} else { | ||
return callback(); | ||
} | ||
}); | ||
} | ||
}); | ||
} else { | ||
return callback(); | ||
} | ||
}); | ||
} | ||
@@ -516,0 +629,0 @@ }); |
(function(){ | ||
var ref$, all, any, drop, camelize, difference, filter, find, findIndex, last, map, reject, isEqualToObject, React, createFactory, div, img, span, ReactSelectize; | ||
var ref$, all, any, drop, camelize, difference, filter, find, findIndex, last, map, reject, isEqualToObject, React, createFactory, div, img, span, ReactSelectize, toString$ = {}.toString; | ||
ref$ = require('prelude-ls'), all = ref$.all, any = ref$.any, drop = ref$.drop, camelize = ref$.camelize, difference = ref$.difference, filter = ref$.filter, find = ref$.find, findIndex = ref$.findIndex, last = ref$.last, map = ref$.map, reject = ref$.reject; | ||
@@ -25,3 +25,2 @@ isEqualToObject = require('prelude-extension').isEqualToObject; | ||
onFocus: function(value, reason){}, | ||
options: [], | ||
placeholder: "", | ||
@@ -32,9 +31,15 @@ style: {} | ||
render: function(){ | ||
var ref$, search, value, values, onSearchChange, onValueChange, filteredOptions, options, autosize, ref1$, this$ = this; | ||
var ref$, search, value, values, onSearchChange, onValueChange, filteredOptions, options, autosize, disabled, dropdownDirection, groupId, groups, groupsAsColumns, renderGroupTitle, uid, ref1$, this$ = this; | ||
ref$ = this.getComputedState(), search = ref$.search, value = ref$.value, values = ref$.values, onSearchChange = ref$.onSearchChange, onValueChange = ref$.onValueChange, filteredOptions = ref$.filteredOptions, options = ref$.options; | ||
autosize = this.props.autosize; | ||
ref$ = this.props, autosize = ref$.autosize, disabled = ref$.disabled, dropdownDirection = ref$.dropdownDirection, groupId = ref$.groupId, groups = ref$.groups, groupsAsColumns = ref$.groupsAsColumns, renderGroupTitle = ref$.renderGroupTitle, uid = ref$.uid; | ||
return ReactSelectize(import$({ | ||
autosize: autosize, | ||
className: "simple-select " + ((ref$ = (ref1$ = this.props) != null ? ref1$.className : void 8) != null ? ref$ : ''), | ||
disabled: this.props.disabled, | ||
disabled: disabled, | ||
dropdownDirection: dropdownDirection, | ||
groupId: groupId, | ||
groups: groups, | ||
groupsAsColumns: groupsAsColumns, | ||
renderGroupTitle: renderGroupTitle, | ||
uid: uid, | ||
ref: 'select', | ||
@@ -55,2 +60,8 @@ anchor: last(values), | ||
}, | ||
highlightedUid: this.state.highlightedUid, | ||
onHighlightedUidChange: function(highlightedUid, callback){ | ||
return this$.setState({ | ||
highlightedUid: highlightedUid | ||
}, callback); | ||
}, | ||
firstOptionIndexToHighlight: function(){ | ||
@@ -81,6 +92,3 @@ return this$.firstOptionIndexToHighlight(options, value); | ||
return onValueChange(undefined, function(){ | ||
return this$.showOptions(function(){ | ||
this$.refs.select.focus(); | ||
return callback(); | ||
}); | ||
return this$.focus(callback); | ||
}); | ||
@@ -158,3 +166,3 @@ } else { | ||
getComputedState: function(){ | ||
var search, value, values, ref$, onSearchChange, onValueChange, filteredOptions, newOption, options, this$ = this; | ||
var search, value, values, ref$, onSearchChange, onValueChange, optionsFromChildren, unfilteredOptions, filteredOptions, newOption, options, this$ = this; | ||
search = this.props.hasOwnProperty('search') | ||
@@ -181,4 +189,3 @@ ? this.props.search | ||
return this$.setState((ref$ = {}, ref$[p + ""] = o, ref$), function(){ | ||
this$.props[camelize("on-" + p + "-change")](o, function(){}); | ||
return callback(); | ||
return this$.props[camelize("on-" + p + "-change")](o, callback); | ||
}); | ||
@@ -194,3 +201,25 @@ }; | ||
['search', 'value']), onSearchChange = ref$[0], onValueChange = ref$[1]; | ||
filteredOptions = this.props.filterOptions(this.props.options, search); | ||
optionsFromChildren = (function(){ | ||
var ref$; | ||
switch (false) { | ||
case !((ref$ = this.props) != null && ref$.children): | ||
return map(function(arg$){ | ||
var ref$, value, children; | ||
ref$ = arg$.props, value = ref$.value, children = ref$.children; | ||
return { | ||
label: children, | ||
value: value | ||
}; | ||
})( | ||
toString$.call(this.props.children).slice(8, -1) === 'Array' | ||
? this.props.children | ||
: [this.props.children]); | ||
default: | ||
return []; | ||
} | ||
}.call(this)); | ||
unfilteredOptions = this.props.hasOwnProperty('options') ? (ref$ = this.props.options) != null | ||
? ref$ | ||
: [] : optionsFromChildren; | ||
filteredOptions = this.props.filterOptions(unfilteredOptions, search); | ||
newOption = typeof this.props.createFromSearch === 'function' ? this.props.createFromSearch(filteredOptions, search) : null; | ||
@@ -212,2 +241,3 @@ options = (!!newOption | ||
return { | ||
highlightedUid: undefined, | ||
open: false, | ||
@@ -242,6 +272,5 @@ search: "", | ||
}, | ||
focus: function(){ | ||
var this$ = this; | ||
focus: function(callback){ | ||
this.refs.select.focus(); | ||
this.showOptions(function(){}); | ||
return this.showOptions(callback); | ||
}, | ||
@@ -248,0 +277,0 @@ highlightFirstSelectableOption: function(){ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
83764
1784
170
21