Skip to content

Instantly share code, notes, and snippets.

@souporserious
Last active August 7, 2017 01:37
Show Gist options
  • Save souporserious/248747f1381aacb4c3453de46947d0da to your computer and use it in GitHub Desktop.
Save souporserious/248747f1381aacb4c3453de46947d0da to your computer and use it in GitHub Desktop.
import React, { Component } from 'react'
import { Manager, Target, Popper, Arrow } from 'react-popper'
import Portal from 'react-travel'
import outy from 'outy'
import matchSorter, { rankings } from 'match-sorter'
import Autocomplete from '../Autocomplete'
import Badge from '../Badge'
import Button from '../Button'
import Card from '../Card'
import Checkbox from '../Checkbox'
import Flex from '../Flex'
import Icon from '../Icon'
import Input from '../Forms/Input'
function Menu(props) {
return (
<Card
maxHeight={12}
minWidth={12}
paddingVertical={0.5}
marginTop={0.5}
position="absolute"
top="100%"
width="100%"
overflow="auto"
elevation={1}
{...props}
/>
)
}
function Item({ isHighlighted, disabled, ...props }) {
const css = {
alignItems: 'center',
padding: 1,
backgroundColor: '#ffffff',
cursor: 'pointer',
userSelect: 'none',
}
if (isHighlighted) {
css.backgroundColor = '#f7f7f7'
}
if (disabled) {
css.opacity = 0.65
}
return <Flex {...css} {...props} />
}
function renderSingleValue({ selectedOption }) {
return selectedOption.label
}
function renderMultipleValues({ selectedOption = [], selectItem }) {
return (
<Flex.Row gutter={0.5} width="auto">
{selectedOption.map(option =>
<Badge.Close
key={option.label}
label={option.label}
size="xxs"
onClose={() => selectItem(option)}
/>
)}
</Flex.Row>
)
}
class Select extends Component {
render() {
let {
defaultValue,
value,
options,
multiple,
onChange,
placeholder = 'Select a value',
renderValue = multiple ? renderMultipleValues : renderSingleValue,
...restProps
} = this.props
return (
<Autocomplete
defaultValue={defaultValue}
value={value}
multiple={multiple}
onChange={onChange}
getValue={o => o.value}
{...restProps}
>
{({
getButtonProps,
getItemFromValue,
getItemProps,
getItemState,
getRootProps,
isOpen,
selectItem,
selectedValue,
}) =>
<Flex {...getRootProps({ refKey: 'innerRef' })} position="relative">
<Input
component="div"
display="flex"
tabIndex="0"
{...getButtonProps()}
>
{selectedValue.length > 0
? renderValue({
selectItem,
selectedOption: getItemFromValue(selectedValue, options),
})
: placeholder}
<Icon name={isOpen ? 'arrow-up' : 'arrow-down'} />
</Input>
{isOpen &&
<Menu>
{options.map((option, index) => {
const { isSelected, ...itemProps } = getItemProps({
value: option,
index,
})
return (
<Item key={index} {...itemProps}>
{multiple &&
<Icon
name={isSelected ? 'checkmark' : null}
marginRight={1}
/>}
{option.label}
</Item>
)
})}
</Menu>}
</Flex>}
</Autocomplete>
)
}
}
Select.rankings = rankings
export default Select
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment