Skip to content
This repository has been archived by the owner on Jul 19, 2019. It is now read-only.

[added] Allow users to opt-out of the wrapper element #364

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
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
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,13 @@ Default value: `''`

The value to display in the input field

#### `wrapper: Boolean` (optional)
Default value: `true`

Whether or not to wrap the input and menu items in a `<div>` tag. Setting
this to `false` will render without a wrapper, discarding any overrides from
`wrapperProps` and `wrapperStyle`.

#### `wrapperProps: Object` (optional)
Default value: `{}`

Expand Down
72 changes: 45 additions & 27 deletions lib/Autocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ class Autocomplete extends React.Component {
* placeholder, event handlers (onFocus, onBlur, etc.), autoFocus, etc..
*/
inputProps: PropTypes.object,
/**
* Whether or not to wrap the input and menu items in a div.
*/
wrapper: PropTypes.bool,
/**
* Props that are applied to the element which wraps the `<input />` and
* dropdown menu elements rendered by `Autocomplete`.
Expand Down Expand Up @@ -161,19 +165,20 @@ class Autocomplete extends React.Component {

static defaultProps = {
value: '',
wrapper: true,
wrapperProps: {},
wrapperStyle: {
display: 'inline-block'
},
inputProps: {},
renderInput(props) {
return <input {...props} />
return <input key="autocomplete:input" {...props} />
},
onChange() {},
onSelect() {},
isItemSelectable() { return true },
renderMenu(items, value, style) {
return <div style={{ ...style, ...this.menuStyle }} children={items}/>
return <div key="autocomplete:menu" style={{ ...style, ...this.menuStyle }} children={items}/>
},
menuStyle: {
borderRadius: '3px',
Expand Down Expand Up @@ -475,6 +480,7 @@ class Autocomplete extends React.Component {
}
const menu = this.props.renderMenu(items, this.props.value, style)
return React.cloneElement(menu, {
key: 'autocomplete:menu',
ref: e => this.refs.menu = e,
// Ignore blur to prevent menu from de-rendering before we can process click
onTouchStart: () => this.setIgnoreBlur(true),
Expand Down Expand Up @@ -570,32 +576,44 @@ class Autocomplete extends React.Component {

const { inputProps } = this.props
const open = this.isOpen()
return (
<div style={{ ...this.props.wrapperStyle }} {...this.props.wrapperProps}>
{this.props.renderInput({
...inputProps,
role: 'combobox',
'aria-autocomplete': 'list',
'aria-expanded': open,
autoComplete: 'off',
ref: this.exposeAPI,
onFocus: this.handleInputFocus,
onBlur: this.handleInputBlur,
onChange: this.handleChange,
onKeyDown: this.composeEventHandlers(this.handleKeyDown, inputProps.onKeyDown),
onClick: this.composeEventHandlers(this.handleInputClick, inputProps.onClick),
value: this.props.value,
})}
{open && this.renderMenu()}
{this.props.debug && (
<pre style={{ marginLeft: 300 }}>
{JSON.stringify(this._debugStates.slice(Math.max(0, this._debugStates.length - 5), this._debugStates.length), null, 2)}
</pre>
)}
</div>
)
const input = this.props.renderInput({
...inputProps,
role: 'combobox',
'aria-autocomplete': 'list',
'aria-expanded': open,
autoComplete: 'off',
ref: this.exposeAPI,
onFocus: this.handleInputFocus,
onBlur: this.handleInputBlur,
onChange: this.handleChange,
onKeyDown: this.composeEventHandlers(this.handleKeyDown, inputProps.onKeyDown),
onClick: this.composeEventHandlers(this.handleInputClick, inputProps.onClick),
value: this.props.value,
})

const menu = open ? this.renderMenu() : null

const debug = this.props.debug ? (
<pre key="autocomplete:debug" style={{ marginLeft: 300 }}>
{JSON.stringify(this._debugStates.slice(Math.max(0, this._debugStates.length - 5), this._debugStates.length), null, 2)}
</pre>
) : null

if (this.props.wrapper) {
return (
<div
style={{ ...this.props.wrapperStyle }}
{...this.props.wrapperProps}
>
{input}
{menu}
{debug}
</div>
)
} else {
return [input, menu, debug]
}
}
}

module.exports = Autocomplete