rc-select
Advanced tools
Comparing version 1.0.0 to 2.0.0
@@ -1,2 +0,3 @@ | ||
# rc-select@1.x | ||
# rc-select@2.x | ||
--- | ||
@@ -6,28 +7,18 @@ <link href="../assets/index.css" rel="stylesheet" /> | ||
````html | ||
<style> | ||
#ex2 .select-menu{ | ||
height: 200px; | ||
overflow:auto; | ||
#ex1,#ex2,#ex3 { | ||
width:300px; | ||
} | ||
</style> | ||
<div class="wrapper"> | ||
<h3>single select</h3> | ||
<div id="ex1"></div> | ||
<h3>multiple select(scroll the menu)</h3> | ||
<div id="ex2"></div> | ||
<h3>combobox (autocomplete)</h3> | ||
<div id="ex3"></div> | ||
</div> | ||
```` | ||
## single select | ||
<div id="ex1"></div> | ||
````js | ||
/** @jsx React.DOM */ | ||
var React = require('react'); | ||
(function(){ | ||
var React = require('react'); | ||
var Select = require('../'); | ||
var Option = Select.Option; | ||
var Combobox = Select.Combobox; | ||
@@ -37,20 +28,40 @@ var style = { | ||
}; | ||
function handleSelect(selectedKey, obj) { | ||
console.log('selected ' + selectedKey, obj); | ||
function handleChange(value) { | ||
console.log('selected ' + value); | ||
} | ||
function handleDeselect(selectedKey, obj) { | ||
console.log('deselect ' + selectedKey, obj); | ||
} | ||
var c1 = ( | ||
<Select value="disabled" className="forTest" allowClear | ||
onSelect={handleSelect} onDeselect={handleDeselect}> | ||
<Select value="lucy" className="forTest" onChange={handleChange}> | ||
<Option value="jack" className="forTest"><b style={style}>jack</b></Option> | ||
<Option value="lucy">lucy</Option> | ||
<Option value="disabled" disabled>disabled</Option> | ||
<Option value="jim">jim</Option> | ||
<Option value="yiminghe">yiminghe</Option> | ||
</Select> | ||
); | ||
React.render(c1, document.getElementById('ex1')); | ||
})(); | ||
```` | ||
## multiple select(scroll the menu) | ||
<div id="ex2"></div> | ||
````html | ||
<style> | ||
#ex2 .rc-select-menu{ | ||
height: 200px; | ||
overflow:auto; | ||
} | ||
</style> | ||
```` | ||
````js | ||
(function(){ | ||
/** @jsx React.DOM */ | ||
var React = require('react'); | ||
var Select = require('../'); | ||
var Option = Select.Option; | ||
var children = []; | ||
@@ -60,4 +71,9 @@ for(var i = 10; i < 36; i++){ | ||
} | ||
function handleChange(value) { | ||
console.log('selected ' + value); | ||
} | ||
var c2 = ( | ||
<Select multiple value={['name2', 'name3']} maximumSelectionLength="3" > | ||
<Select multiple value={['name2', 'name3']} onChange={handleChange}> | ||
{children} | ||
@@ -67,15 +83,28 @@ </Select> | ||
React.render(c2, document.getElementById('ex2')); | ||
})(); | ||
```` | ||
## combobox | ||
<div id="ex3"></div> | ||
````js | ||
/** @jsx React.DOM */ | ||
var React = require('react'); | ||
var Select = require('../'); | ||
var Option = Select.Option; | ||
var style = { | ||
color: 'red' | ||
}; | ||
var c3 = ( | ||
<Combobox> | ||
<Select combobox> | ||
<Option value="jack"><b style={style}>jack</b></Option> | ||
<Option value="lucy" >lucy</Option> | ||
<Option value="disabled" disabled>disabled</Option> | ||
<Option value="jim">jim</Option> | ||
</Combobox> | ||
<Option value="yiminghe">yiminghe</Option> | ||
</Select> | ||
); | ||
React.render(c1, document.getElementById('ex1')); | ||
React.render(c2, document.getElementById('ex2')); | ||
React.render(c3, document.getElementById('ex3')); | ||
```` |
var Select = require('./lib/Select'); | ||
Select.Option = require('./lib/Option'); | ||
Select.Combobox = require('./lib/Combobox'); | ||
module.exports = Select; |
/** @jsx React.DOM */ | ||
/** | ||
*Select | ||
*/ | ||
*Select | ||
*/ | ||
var React = require('react'); | ||
var joinClasses = require('./utils/joinClasses'); | ||
var classSet = require('./utils/classSet'); | ||
var util = require('./utils/util'); | ||
var KeyCode = util.KeyCode; | ||
var rcUtil = require('rc-util'); | ||
var joinClasses = rcUtil.joinClasses; | ||
var classSet = rcUtil.classSet; | ||
var KeyCode = rcUtil.KeyCode; | ||
var Menu = require('rc-menu'); | ||
var MenuItem = Menu.Item; | ||
function noop() { | ||
} | ||
function getKeyFromOptionChild(child) { | ||
var optionProps = child.props; | ||
var children = optionProps.children; | ||
var ret = child.key || undefined; | ||
if (!ret) { | ||
if (typeof optionProps.value === 'string') { | ||
ret = optionProps.value; | ||
} else if (React.isValidElement(children)) { | ||
if (typeof children.props.children === 'string') { | ||
ret = children.props.children; | ||
} | ||
} | ||
} | ||
if (!ret && !child.props.disabled) { | ||
throw new Error('please set key on Option element!'); | ||
} | ||
return ret; | ||
} | ||
function getPropsFromOption(child) { | ||
var ret = { | ||
key: getKeyFromOptionChild(child) | ||
}; | ||
var optionProps = child.props; | ||
for (var i in optionProps) { | ||
if (i !== 'children') { | ||
ret[i] = optionProps[i]; | ||
} | ||
} | ||
return ret; | ||
} | ||
function normValue(value) { | ||
if (value === undefined) { | ||
value = []; | ||
} else if (!Array.isArray(value)) { | ||
value = [value]; | ||
} | ||
return value; | ||
} | ||
var Select = React.createClass({ | ||
propTypes: { | ||
multiple: React.PropTypes.bool, | ||
onSelect: React.PropTypes.func, | ||
onDeselect: React.PropTypes.func | ||
onChange: React.PropTypes.func | ||
}, | ||
mixins: [require('./OpenStateMixin')], | ||
getDefaultProps: function () { | ||
return { | ||
prefixCls: 'select' | ||
prefixCls: 'rc-select', | ||
allowClear: true, | ||
onChange: noop, | ||
notFoundContent: 'Not Found' | ||
}; | ||
}, | ||
_getOpenClassName: function () { | ||
return this.props.openClassName || this.props.prefixCls + '-open'; | ||
}, | ||
getInitialState: function () { | ||
var props = this.props; | ||
//handle select value attribute | ||
var selectValue = props.value; | ||
if (typeof selectValue === 'string') { | ||
selectValue = [selectValue]; | ||
} | ||
var selectedOptions = this._getDefaultSelected(props.children, selectValue); | ||
var len = selectedOptions.length; | ||
if (!props.multiple && len) { | ||
selectedOptions = [selectedOptions.pop()]; | ||
} | ||
// set the last selected option active | ||
if (len) { | ||
selectedOptions[selectedOptions.length - 1].props.active = true; | ||
} | ||
return { | ||
selectedOptions: this._setMaxSelectionLength(selectedOptions), | ||
inputVal: '' | ||
value: normValue(this.props.value), | ||
inputValue: '' | ||
}; | ||
}, | ||
_getDefaultSelected: function (children, selectValue) { | ||
componentWillReceiveProps: function (nextProps) { | ||
this.setState({ | ||
value: normValue(nextProps.value) | ||
}); | ||
}, | ||
_getFilterList: function (searchText) { | ||
var sel = []; | ||
React.Children.forEach(children, function (child) { | ||
if (React.isValidElement(child) && | ||
//(selectValue && selectValue.indexOf(child.props.value) > -1 || child.props.selected)) { | ||
(selectValue && selectValue.indexOf(child.props.value) > -1)) { | ||
React.Children.forEach(this.props.children, function (child) { | ||
if (!searchText || !child.props.disabled && getKeyFromOptionChild(child).indexOf(searchText) > -1) { | ||
sel.push(child); | ||
@@ -70,150 +96,137 @@ } | ||
_setMaxSelectionLength: function (sel) { | ||
var maxLen = this.props.maximumSelectionLength; | ||
if (maxLen && sel.length > maxLen) { | ||
sel = sel.slice(0, maxLen); | ||
} | ||
return sel; | ||
}, | ||
_resetSelect: function () { | ||
// reset input and children when close menu | ||
if (this.props.__combobox) { | ||
var selOpts = this.state.selectedOptions, len = selOpts.length; | ||
if (len) { | ||
this.setState({inputVal: selOpts[len - 1].props.value}); | ||
setOpenState: function (open) { | ||
var self = this; | ||
this.setState({ | ||
open: open | ||
}, function () { | ||
if (open || self.props.multiple || self.props.combobox) { | ||
self.refs.input.getDOMNode().focus(); | ||
} else { | ||
self.refs.selection.getDOMNode().focus(); | ||
} | ||
} else { | ||
this.setState({inputVal: ''}); | ||
} | ||
}, | ||
_getFilterList: function (children, searchText) { | ||
var sel = []; | ||
React.Children.forEach(children, function (child) { | ||
// option content can be string or html element | ||
var cc = child.props.value; | ||
if (React.isValidElement(child) && | ||
!child.props.__noResults && | ||
cc.indexOf(searchText) > -1) { | ||
sel.push(child); | ||
} | ||
}); | ||
return sel; | ||
}, | ||
handleSearch: function (e) { | ||
handleInputChange: function (e) { | ||
var val = e.target.value; | ||
if (!this.state.open) { | ||
this.handleClick(); | ||
this.setState({ | ||
inputValue: val, | ||
open: true | ||
}); | ||
if (this.props.combobox) { | ||
this.setState({ | ||
value: val ? [val] : [] | ||
}); | ||
this.props.onChange(val); | ||
} | ||
if (!val.length) { | ||
this.setOpenState(false); | ||
} | ||
this.setState({inputVal: val}); | ||
}, | ||
handleClick: function () { | ||
var open = this.state.open; | ||
var search = this.refs.search.getDOMNode(); | ||
if (this.props.__combobox) { | ||
search.focus(); | ||
if (!open && (this.state.inputVal.length || search.value)) { | ||
this.setOpenState(true); | ||
} | ||
return; | ||
} | ||
this.setOpenState(!open, function () { | ||
if (!open) { | ||
search.focus(); | ||
} else { | ||
this.refs.selection.getDOMNode().focus(); | ||
} | ||
}); | ||
this.setOpenState(!this.state.open); | ||
}, | ||
// combobox ignore | ||
handleKeyDown: function (e) { | ||
var keyCode = e.keyCode; | ||
if (keyCode !== KeyCode.ENTER) { | ||
return; | ||
if (keyCode === KeyCode.ENTER || e.keyCode === KeyCode.DOWN) { | ||
this.handleClick(e); | ||
e.preventDefault(); | ||
} | ||
this.handleClick(e); | ||
}, | ||
handleInputKeyDown: function (e) { | ||
if (e.keyCode === KeyCode.ESC) { | ||
e.preventDefault(); | ||
if (e.keyCode === KeyCode.DOWN) { | ||
if (!this.state.open) { | ||
this.setState({ | ||
open: true | ||
}); | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
return; | ||
} | ||
} else if (e.keyCode === KeyCode.ESC) { | ||
if (this.state.open) { | ||
this.setOpenState(false); | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
} | ||
return; | ||
} | ||
if (this.refs.menu) { | ||
this.refs.menu.handleKeyDown(e); | ||
if (this.refs.menu.handleKeyDown(e)) { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
} | ||
} | ||
}, | ||
// input keyDown event will bubble up when select is multiple, | ||
// so it will fire handleKeyDown automatically. | ||
if (!this.props.multiple) { | ||
this.handleKeyDown(e); | ||
handleMenuSelect: function (key, item) { | ||
var value; | ||
if (this.props.multiple) { | ||
value = this.state.value.concat(); | ||
value.push(item.props.value); | ||
} else { | ||
var selOpts = this.state.selectedOptions; | ||
if (KeyCode.Backspace === e.keyCode && selOpts.length) { | ||
selOpts.pop(); | ||
this.setState({selectedOptions: selOpts}); | ||
if (this.state.value[0] === item.props.value) { | ||
this.setOpenState(false); | ||
return; | ||
} | ||
value = [item.props.value]; | ||
} | ||
this.props.onChange(this.props.multiple ? value : value[0]); | ||
this.setState({ | ||
value: value, | ||
inputValue: '' | ||
}); | ||
this.setOpenState(false); | ||
if (this.props.combobox) { | ||
this.setState({ | ||
inputValue: value[0] | ||
}); | ||
} | ||
}, | ||
optionSelected: function (key, item) { | ||
var sel = []; | ||
if (this.props.onSelect) { | ||
this.props.onSelect(key, item); | ||
} | ||
if (this.props.multiple) { | ||
sel = this.state.selectedOptions; | ||
} | ||
sel.push(item); | ||
this.setState({selectedOptions: this._setMaxSelectionLength(sel)}); | ||
this.setOpenState(!this.state.open); | ||
handleMenuDeselect: function (key, item) { | ||
this.removeSelected(item.props.value); | ||
this.setOpenState(false); | ||
}, | ||
optionDeSelect: function (key, item) { | ||
var sel = this.state.selectedOptions.filter(function (option) { | ||
return option.props.value !== item.props.value; | ||
}); | ||
this.setState({selectedOptions: sel}); | ||
if (this.props.onDeselect) { | ||
this.props.onDeselect(key, item); | ||
handleBlur: function () { | ||
//return; | ||
var self = this; | ||
if (this._blurTimer) { | ||
clearTimeout(this._blurTimer); | ||
} | ||
this._blurTimer = setTimeout(function () { | ||
self.setState({ | ||
open: false | ||
}); | ||
}, 100); | ||
}, | ||
removeSelected: function (item) { | ||
this.optionDeSelect(item.props.value, item); | ||
handleFocus: function () { | ||
if (this._blurTimer) { | ||
clearTimeout(this._blurTimer); | ||
} | ||
}, | ||
clearSelection: function () { | ||
this.setState({selectedOptions: []}); | ||
removeSelected: function (value) { | ||
value = this.state.value.filter(function (v) { | ||
return v !== value; | ||
}); | ||
this.props.onChange(this.props.multiple ? value : value[0]); | ||
this.setState({ | ||
value: value | ||
}); | ||
}, | ||
setMenuProps: function (multiple, props, selection) { | ||
var menuProps = { | ||
onSelect: this.optionSelected | ||
}; | ||
if (multiple) { | ||
menuProps.multiple = true; | ||
menuProps.onDeselect = this.optionDeSelect; | ||
handleClearSelection: function (e) { | ||
e.stopPropagation(); | ||
if (this.state.value.length) { | ||
this.props.onChange(this.props.multiple ? [] : undefined); | ||
this.setState({ | ||
value: [], | ||
inputValue: '' | ||
}); | ||
} | ||
var selectedKeys = selection.selectedKeys; | ||
menuProps.selectedKeys = selectedKeys; | ||
menuProps.activeKey = selectedKeys.length ? selectedKeys[selectedKeys.length - 1] : ''; | ||
if (!util.toArray(props.children).some(function (item) { | ||
return item.props.value === menuProps.activeKey && !item.props.disabled; | ||
})) { | ||
menuProps.activeKey = null; | ||
} | ||
return menuProps; | ||
this.setOpenState(false); | ||
}, | ||
@@ -227,112 +240,135 @@ | ||
var input = ( | ||
<input ref="search" | ||
onChange={this.handleSearch} | ||
onKeyDown={this.handleInputKeyDown} | ||
value={this.state.inputVal} | ||
className={prefixCls + '-search__field'} | ||
type="search" tabIndex="0" role="textbox" /> | ||
<input ref="input" | ||
onChange={this.handleInputChange} | ||
onKeyDown={this.handleInputKeyDown} | ||
value={this.state.inputValue} | ||
className={prefixCls + '-search__field'} | ||
role="textbox" /> | ||
); | ||
var children = props.children; | ||
children = this._getFilterList(children, this.state.inputVal); | ||
var children = this._getFilterList(this.state.inputValue); | ||
if (!children.length) { | ||
if (props.__combobox) { | ||
children = null; | ||
} else { | ||
children = <MenuItem disabled __noResults>No results found</MenuItem>; | ||
} | ||
children = <MenuItem disabled>{props.notFoundContent}</MenuItem>; | ||
} | ||
var selection = this.renderSelection(multiple, input); | ||
var menuProps = this.setMenuProps(multiple, props, selection); | ||
menuProps.activeFirst = true; | ||
var ctrlNode = this.getTopControlNode(input); | ||
var dropDown; | ||
if (this.state.open) { | ||
// single and not combobox, input is inside dropdown | ||
dropDown = <span className= {joinClasses(prefixCls + '-dropdown', prefixCls + '-dropdown--below')} tabIndex="-1"> | ||
{multiple || props.combobox ? null : <span className={joinClasses(prefixCls + '-search', prefixCls + '-search--dropdown')}>{input}</span>} | ||
{this.renderMenu(children)} | ||
</span>; | ||
} | ||
return this.renderContainer(props, [ | ||
var extraSelectionProps = {}; | ||
if (!props.combobox) { | ||
extraSelectionProps = { | ||
onKeyDown: this.handleKeyDown, | ||
tabIndex: 0 | ||
}; | ||
} | ||
return this.renderRoot([ | ||
<span ref="selection" | ||
className={joinClasses(prefixCls + '-selection', | ||
prefixCls + '-selection--' + (multiple ? 'multiple' : 'single'))} | ||
tabIndex={props.__combobox ? '-1' : '0'} | ||
onClick={this.handleClick} | ||
onKeyDown={this.handleKeyDown} | ||
role="combobox" aria-autocomplete="list" aria-haspopup="true" | ||
aria-expanded={this.state.open} aria-owns=""> | ||
{selection.ctrlNode} | ||
{multiple ? '' : | ||
<span className={prefixCls + '-arrow'} role="presentation"><b role="presentation"></b></span>} | ||
className={joinClasses(prefixCls + '-selection', | ||
prefixCls + '-selection--' + (multiple ? 'multiple' : 'single'))} | ||
role="combobox" | ||
aria-autocomplete="list" | ||
onClick={this.handleClick} | ||
aria-haspopup="true" | ||
aria-expanded={this.state.open} | ||
{...extraSelectionProps} | ||
> | ||
{ctrlNode} | ||
{multiple ? null : | ||
<span className={prefixCls + '-arrow'}> | ||
<b></b> | ||
</span>} | ||
</span>, | ||
<span className="select-dropdown select-dropdown--below" aria-hidden={!this.state.open}> | ||
{multiple ? '' : <span className="select-search select-search--dropdown">{input}</span>} | ||
{this.renderMenu(props, menuProps, children)} | ||
</span> | ||
dropDown | ||
]); | ||
}, | ||
renderMenu: function (props, menuProps, children) { | ||
if (props.__combobox && !children) { | ||
return null; | ||
renderMenu: function (children) { | ||
var props = this.props; | ||
var menuProps = {}; | ||
if (props.multiple) { | ||
menuProps.onDeselect = this.handleMenuDeselect; | ||
} | ||
return <Menu ref="menu" {...menuProps} className="select-menu"> | ||
{util.mapValidComponents(children, this.renderOption)} | ||
</Menu>; | ||
var value = this.state.value; | ||
var menuItems = React.Children.map(children, this.renderOption); | ||
var selectedKeys = []; | ||
React.Children.forEach(menuItems, function (item) { | ||
if (value.indexOf(item.props.value) !== -1) { | ||
selectedKeys.push(item.key); | ||
} | ||
}); | ||
var activeKey; | ||
if (selectedKeys.length === 1) { | ||
activeKey = selectedKeys[0]; | ||
} | ||
return <Menu | ||
ref="menu" | ||
onSelect={this.handleMenuSelect} | ||
activeFirst={true} | ||
activeKey={activeKey} | ||
multiple={props.multiple} | ||
focusable={false} | ||
{...menuProps} | ||
selectedKeys={selectedKeys} | ||
prefixCls={props.prefixCls + '-menu'}> | ||
{menuItems} | ||
</Menu>; | ||
}, | ||
renderSelection: function (multiple, input) { | ||
var lis, selOpts = this.state.selectedOptions; | ||
var selectedKeys = [], ctrlNode; | ||
getTopControlNode: function (input) { | ||
var self = this; | ||
var value = this.state.value; | ||
var prefixCls = this.props.prefixCls; | ||
var allowClear = this.props.allowClear; | ||
var clear = <span className={prefixCls + '-selection__clear'} | ||
onClick={this.clearSelection}>×</span>; | ||
if (multiple) { | ||
lis = selOpts.map(function (item) { | ||
selectedKeys.push(item.props.value); | ||
onClick={this.handleClearSelection}>×</span>; | ||
var props = this.props; | ||
// single and not combobox, input is inside dropdown | ||
if (!props.combobox && !props.multiple) { | ||
return <span className={prefixCls + '-selection__rendered'}> | ||
{value[0]} | ||
{allowClear ? clear : null} | ||
</span>; | ||
} | ||
var selectedValueNodes; | ||
if (props.multiple) { | ||
selectedValueNodes = value.map(function (v) { | ||
return ( | ||
<li className={prefixCls + '-selection__choice'}> | ||
<span className={prefixCls + '-selection__choice__remove'} | ||
onClick={this.removeSelected.bind(this, item)} | ||
role="presentation">×</span> | ||
{item.props.value} | ||
onClick={self.removeSelected.bind(self, v)} | ||
>×</span> | ||
{v} | ||
</li> | ||
); | ||
}, this); | ||
ctrlNode = ( | ||
<ul className={prefixCls + '-selection__rendered'}> | ||
{this.props.__combobox ? '' : lis} | ||
{allowClear ? clear : ''} | ||
<li className="select-search select-search--inline">{input}</li> | ||
</ul> | ||
); | ||
} else { | ||
var sel = selOpts.length ? selOpts[selOpts.length - 1].props.value : ''; | ||
selectedKeys.push(sel); | ||
ctrlNode = ( | ||
<span className={prefixCls + '-selection__rendered'}> | ||
{sel} | ||
{allowClear ? clear : ''} | ||
</span> | ||
); | ||
}); | ||
} | ||
return { | ||
ctrlNode: ctrlNode, | ||
selectedKeys: selectedKeys | ||
}; | ||
return ( | ||
<ul className={prefixCls + '-selection__rendered'}> | ||
{selectedValueNodes} | ||
{allowClear && !props.multiple ? clear : null} | ||
<li className={joinClasses(prefixCls + '-search', prefixCls + '-search--inline')}>{input}</li> | ||
</ul> | ||
); | ||
}, | ||
renderContainer: function (props, children) { | ||
var rootPrefixCls = props.prefixCls; | ||
renderRoot: function (children) { | ||
var props = this.props; | ||
var prefixCls = props.prefixCls; | ||
var rootCls = {}; | ||
rootCls[rootPrefixCls] = true; | ||
rootCls[rootPrefixCls + '-container'] = true; | ||
rootCls[prefixCls] = true; | ||
if (this.state.open) { | ||
rootCls[this._getOpenClassName()] = true; | ||
rootCls[prefixCls + '-open'] = true; | ||
} | ||
return ( | ||
<span ref="container" | ||
className={joinClasses(props.className, classSet(rootCls))} dir="ltr"> | ||
<span className={joinClasses(props.className, classSet(rootCls))} dir="ltr" | ||
onFocus={this.handleFocus} | ||
onBlur={this.handleBlur}> | ||
{children} | ||
@@ -344,10 +380,6 @@ </span> | ||
renderOption: function (child) { | ||
var props = child.props; | ||
//child.key = props.value; // key is immutable in here | ||
props.eventKey = props.value; | ||
return <MenuItem className={props.prefixCls + '-menu-item'} {...props}>{child.props.children}</MenuItem>; | ||
var props = getPropsFromOption(child); | ||
return <MenuItem {...props}>{child.props.children}</MenuItem>; | ||
} | ||
}); | ||
module.exports = Select; | ||
module.exports = Select; |
{ | ||
"name": "rc-select", | ||
"version": "1.0.0", | ||
"version": "2.0.0", | ||
"description": "select ui component for react", | ||
@@ -25,7 +25,8 @@ "keywords": [ | ||
"react": "*", | ||
"rc-util": "^1.0.0", | ||
"rc-menu": "2.x" | ||
} | ||
}, | ||
"config":{ | ||
"port":8003 | ||
"config": { | ||
"port": 8003 | ||
}, | ||
@@ -70,6 +71,7 @@ "scripts": { | ||
"dependencies": { | ||
"browserify-jsx": "^0.1.0", | ||
"browserify-shim": "^3.8.0", | ||
"rc-menu": "2.x", | ||
"browserify-shim": "^3.8.0", | ||
"browserify-jsx": "^0.1.0" | ||
"rc-util": "^1.0.0" | ||
} | ||
} |
@@ -41,6 +41,4 @@ # rc-select | ||
* Open select (focus input || focus and click) | ||
* Previous item (PageUp) | ||
* Next item (PageDown) | ||
* KeyDown/KeyUp/Enter to navigate menu | ||
## install | ||
@@ -91,3 +89,3 @@ | ||
<td>value</td> | ||
<td>String | Array</td> | ||
<td>String | Array<String></td> | ||
<td></td> | ||
@@ -105,24 +103,17 @@ <td>specify the default selected item(s)</td> | ||
<td></td> | ||
<td>false</td> | ||
<td>true</td> | ||
<td></td> | ||
</tr> | ||
<tr> | ||
<td> maximumSelectionLength </td> | ||
<td>combobox</td> | ||
<td></td> | ||
<td></td> | ||
<td>Select multi-value select boxes can set restrictions regarding the maximum number of options selected</td> | ||
</tr> | ||
<tr> | ||
<td>onSelect</td> | ||
<td>function(key:String,child:ReactComponent)</td> | ||
<th></th> | ||
<td>called when select an option</td> | ||
<td>false</td> | ||
<td>enable combobox mode(can not set multiple at the same time)</td> | ||
</tr> | ||
<tr> | ||
<td>onDeselect</td> | ||
<td>function(key:String,child:ReactComponent)</td> | ||
<td>onChange</td> | ||
<td>function(value)</td> | ||
<th></th> | ||
<td>called when deselect an option (for mutiple select)</td> | ||
<td>called when select an option or input value change(combobox)</td> | ||
</tr> | ||
</tr> | ||
</tbody> | ||
@@ -164,31 +155,2 @@ </table> | ||
### Combobox props (autocomplete) | ||
<table class="table table-bordered table-striped"> | ||
<thead> | ||
<tr> | ||
<th style="width: 100px;">name</th> | ||
<th style="width: 50px;">type</th> | ||
<th style="width: 50px;">default</th> | ||
<th>description</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<tr> | ||
<td>className</td> | ||
<td>String</td> | ||
<td></td> | ||
<td>additional css class of root dom node</td> | ||
</tr> | ||
<tr> | ||
<td>value</td> | ||
<td>String</td> | ||
<td></td> | ||
<td>default value in input control</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
online docs: http://spmjs.io/docs/rc-select/ | ||
@@ -195,0 +157,0 @@ |
/** | ||
* only require other specs here | ||
*/ | ||
require('./Select.spec'); | ||
require('../assets/index.css'); | ||
require('./Select.spec'); |
@@ -7,7 +7,5 @@ /** @jsx React.DOM */ | ||
var Simulate = TestUtils.Simulate; | ||
var KeyCode = require('../lib/utils/util').KeyCode; | ||
var KeyCode = require('rc-util').KeyCode; | ||
var Select = require('../'); | ||
var Option = Select.Option; | ||
var Combobox = Select.Combobox; | ||
@@ -24,6 +22,6 @@ describe('Select', function () { | ||
); | ||
expect(instance.refs.container.getDOMNode().classList.contains('forTest')).to.be(true); | ||
expect(instance.getDOMNode().classList.contains('forTest')).to.be(true); | ||
}); | ||
it('should default select the right option', function () { | ||
it('should default select the right option', function (done) { | ||
var instance = TestUtils.renderIntoDocument( | ||
@@ -35,7 +33,12 @@ <Select value="2"> | ||
); | ||
expect(instance.refs.menu.refs['1'].props.selected).to.be(false); | ||
expect(instance.refs.menu.refs['2'].props.selected).to.be(true); | ||
instance.setState({ | ||
open: true | ||
}, function () { | ||
expect(instance.refs.menu.refs['1'].props.selected).to.be(false); | ||
expect(instance.refs.menu.refs['2'].props.selected).to.be(true); | ||
done(); | ||
}); | ||
}); | ||
it('should can select multiple items', function () { | ||
it('should can select multiple items', function (done) { | ||
var instance = TestUtils.renderIntoDocument( | ||
@@ -48,5 +51,10 @@ <Select multiple value={['1', '2']}> | ||
); | ||
expect(instance.refs.menu.refs['1'].props.selected).to.be(true); | ||
expect(instance.refs.menu.refs['2'].props.selected).to.be(true); | ||
expect(instance.refs.menu.refs['3'].props.selected).to.be(false); | ||
instance.setState({ | ||
open: true | ||
}, function () { | ||
expect(instance.refs.menu.refs['1'].props.selected).to.be(true); | ||
expect(instance.refs.menu.refs['2'].props.selected).to.be(true); | ||
expect(instance.refs.menu.refs['3'].props.selected).to.be(false); | ||
done(); | ||
}); | ||
}); | ||
@@ -56,3 +64,3 @@ | ||
var instance = TestUtils.renderIntoDocument( | ||
<Select allowClear> | ||
<Select> | ||
<Option value="1">1</Option> | ||
@@ -62,52 +70,48 @@ <Option value="2">2</Option> | ||
); | ||
expect(instance.refs.selection.getDOMNode().children[0].children[1].className.indexOf('-selection__clear') !== '-1').to.be(true); | ||
expect(TestUtils.scryRenderedDOMComponentsWithClass(instance, 'rc-select-selection__clear').length).to.be(1); | ||
}); | ||
it('should select less than two options', function () { | ||
it('should be combobox', function () { | ||
var instance = TestUtils.renderIntoDocument( | ||
<Select multiple value={['1', '2', '3']} maximumSelectionLength="2"> | ||
<Select combobox> | ||
<Option value="1">1</Option> | ||
<Option value="2">2</Option> | ||
<Option value="3">3</Option> | ||
</Select> | ||
); | ||
expect(instance.refs.menu.refs['1'].props.selected).to.be(true); | ||
expect(instance.refs.menu.refs['2'].props.selected).to.be(true); | ||
expect(instance.refs.menu.refs['3'].props.selected).to.be(false); | ||
expect(!!instance.refs.selection.getDOMNode().getAttribute('tabindex')).to.be(false); | ||
}); | ||
it('should be combobox', function () { | ||
var instance = TestUtils.renderIntoDocument( | ||
<Combobox> | ||
<Option value="1">1</Option> | ||
<Option value="2">2</Option> | ||
</Combobox> | ||
); | ||
expect(instance.refs.select.refs.selection.getDOMNode().getAttribute('tabindex') === '-1').to.be(true); | ||
}); | ||
it('should be empty', function () { | ||
var instance = TestUtils.renderIntoDocument( | ||
<Combobox></Combobox> | ||
); | ||
expect(instance.refs.select.props.children).to.be.an('undefined'); | ||
}); | ||
describe('when open', function () { | ||
var div; | ||
describe('when open', function () { | ||
beforeEach(function () { | ||
instance = TestUtils.renderIntoDocument( | ||
<Select allowClear> | ||
beforeEach(function (done) { | ||
div = document.createElement('div'); | ||
div.tabIndex = 0; | ||
document.body.appendChild(div); | ||
instance = React.render( | ||
<Select> | ||
<Option value="1">1</Option> | ||
<Option value="2">2</Option> | ||
</Select> | ||
); | ||
instance.setOpenState(true); | ||
</Select>, | ||
div); | ||
instance.refs.selection.getDOMNode().focus(); | ||
instance.setState({ | ||
open: true | ||
}, function () { | ||
done() | ||
}); | ||
}); | ||
it('should close on click', function () { | ||
var evt = document.createEvent('HTMLEvents'); | ||
evt.initEvent('click', true, true); | ||
document.documentElement.dispatchEvent(evt); | ||
afterEach(function () { | ||
React.unmountComponentAtNode(div); | ||
}); | ||
expect(instance.getDOMNode().className.match(/\bselect-open\b/)).to.be.ok; | ||
it('should close on blur', function (done) { | ||
expect(instance.getDOMNode().className.match(/\brc-select-open\b/)).to.be.ok(); | ||
div.focus(); | ||
setTimeout(function () { | ||
expect(instance.getDOMNode().className.match(/\brc-select-open\b/)).not.to.be.ok(); | ||
done(); | ||
}, 500); | ||
}); | ||
@@ -114,0 +118,0 @@ }); |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
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
33824
4
20
655
178
2
+ Addedrc-util@^1.0.0