Skip to content
This repository was archived by the owner on Sep 11, 2019. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions src/ComboBox/examples.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import App from '../App';
import ComboBox from './index.js';
import Item from '../Item';

class ComboBoxExample extends React.Component {
constructor() {
super();
this.state = {
value: ['1902'],
};
this.years = Array.from({ length: 150 }, (_, i) => <Item key={`y${i}`} value={String(1900 + i)}>{1900 + i}</Item>);
}

render() {
return (
<ComboBox
theme="islands"
size="l"
name="year"
value={this.state.value}
onChange={value => this.setState({ value })}
>
{this.years}
</ComboBox>
);
}
}

function Example() {
return (
<App theme="islands">
<div className="examples">
<ComboBoxExample />
</div>
</App>
);
}

export default Example;
132 changes: 132 additions & 0 deletions src/ComboBox/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import React from 'react';
import Select from '../Select';
import Menu from '../Menu';
import TextInput from '../TextInput';

class ComboBox extends Select {
constructor(props) {
super(props);

this.state = {
...this.state,
textInputValue: '',
};

this.onKeyDown = this.onKeyDown.bind(this);
this.onTextInputChange = this.onTextInputChange.bind(this);
}

/** @override */
componentWillUpdate(_, nextState) {
if (nextState.popupVisible !== this.state.popupVisible && !nextState.popupVisible) {
this._wasPopupVisible = false;
this.setState({ textInputValue: '' });
this.getMenu().onBlur();
}
}

/** @override */
componentDidUpdate(prevProps) {
this._shouldRestoreControlFocus = false;

if (!this._wasPopupVisible && this.state.popupVisible) {
this._wasPopupVisible = true;
this.updateMenuWidth();
this.getMenu().onFocus();
} else if (this.props.value !== prevProps.value) {
this.updateMenuWidth();
}
}

/** @override */
renderControl() {
return this.state.popupVisible ? this.renderTextInput() : this.renderButton()
}

renderTextInput() {
const { theme, size } = this.props;
const { textInputValue } = this.state;
const placeholder = this.props.value[0];

return (
<TextInput ref="control" theme={theme} size={size} className="select__textinput input_width_available"
hasClear={true}
focused={true}
value={textInputValue}
placeholder={placeholder}
onChange={this.onTextInputChange}
onFocusChange={null}
/>
);
}

/** @override */
renderMenu() {
const { theme, size, disabled, mode, value } = this.props;
const { menuHeight } = this.state;
// NOTE: "nullify" the tabIndex of the Menu
const tabIndex = null;

return (
<Menu ref="menu" theme={theme} size={size} className="select__menu"
mode={mode}
value={value}
tabIndex={tabIndex}
disabled={disabled}
maxHeight={menuHeight}
onItemClick={this.onMenuItemClick}
onChange={this.onMenuChange}
>
{this.props.children}
</Menu>
);
}

/** @override */
onKeyDown(e) {
super.onKeyDown(e);

if (this.state.popupVisible) {
// NODE(narqo@): Proxy "some" keyDown events to the Menu
if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter') {
this.getMenu().onKeyDown(e);
} else if (e.key === 'Tab') {
this._shouldRestoreControlFocus = true;
this.setState({ popupVisible: false });
}
}
}

onTextInputChange(value) {
if (this.props.onTextInputChange) {
this.props.onTextInputChange(value, this.props);
}
this.setState({ textInputValue: value });
this.getMenu().hoverItemByText(value);
}
}

ComboBox.contextTypes = {
theme: React.PropTypes.string,
};

ComboBox.propTypes = {
theme: React.PropTypes.string,
size: React.PropTypes.string,
name: React.PropTypes.string,
value: React.PropTypes.any,
placeholder: React.PropTypes.string,
disabled: React.PropTypes.bool,
maxHeight: React.PropTypes.number,
onChange: React.PropTypes.func,
onTextInputChange: React.PropTypes.func,
};

ComboBox.defaultProps = {
placeholder: '—',
mode: 'radio',
maxHeight: 0,
onChange() {},
};

export default ComboBox;
1 change: 1 addition & 0 deletions src/Menu/MenuItem/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ MenuItem.propTypes = {
type: React.PropTypes.string,
disabled: React.PropTypes.bool,
checked: React.PropTypes.bool,
hovered: React.PropTypes.bool,
onClick: React.PropTypes.func,
onHover: React.PropTypes.func,
};
Expand Down
Loading