Skip to content
Snippets Groups Projects

Hin 1138 country menu

Merged Larisa Andrici requested to merge HIN-1138-Country-Menu into develop
2 files
+ 60
120
Compare changes
  • Side-by-side
  • Inline
Files
2
import React from 'react'
import { startsWith, toLower, get } from 'lodash'
import { compose, withState, withHandlers } from 'recompose'
import React, { Fragment } from 'react'
import styled from 'styled-components'
import { startsWith, toLower, get } from 'lodash'
import { th, override } from '@pubsweet/ui-toolkit'
import { withCountries } from 'pubsweet-component-faraday-ui'
import { compose, withState, withHandlers, withProps } from 'recompose'
const filteredCountries = (countries, userInput) =>
const filteredCountries = ({ countries, userInput }) =>
countries.filter(o => startsWith(toLower(o.label), toLower(userInput)))
const firstFilteredCountry = props =>
filteredCountries(props.countries, props.userInput)[0]
const firstFilteredCountry = ({ countries, userInput }) =>
filteredCountries({ countries, userInput })[0]
const Opener = ({
selected,
const Menu = ({
open,
options,
onEnter,
userInput,
toggleMenu,
placeholder,
optionLabel,
removeSelectedOption,
onChange,
onEnter,
handleSelect,
onTextChange,
}) => (
<Input
onChange={onChange}
onClick={selected ? removeSelectedOption : toggleMenu}
onKeyUp={onEnter}
placeholder={placeholder}
value={selected ? optionLabel(selected) : userInput}
/>
)
const MenuCountry = ({ countries = [], ...input }) => (
<Menu
maxHeight={250}
maxWidth={200}
{...input}
options={filteredCountries(countries, input.userInput)}
placeholder="Please select"
/>
)
const Menu = props => (
<Root>
{props.label && <Label onClick={props.optionLabel}>{props.label}</Label>}
{props.open && <CloseOverlay onClick={props.toggleMenu} />}
<Fragment>
{open && <CloseOverlay onClick={toggleMenu} />}
<Main>
<Opener
open={props.open}
optionLabel={props.optionLabel}
placeholder={props.placeHolder}
removeSelectedOption={props.removeSelectedOption}
selected={props.selected}
toggleMenu={props.toggleMenu}
{...props}
<Input
onChange={onTextChange}
onClick={toggleMenu}
onKeyUp={onEnter}
placeholder={placeholder}
value={userInput}
/>
<OptionsContainer>
{props.open && (
<Options maxHeight={props.maxHeight} open={props.open}>
{props.options.map(option => (
<MenuOption
handleSelect={props.handleSelect}
key={option.value}
label={option.label}
selected={props.selected}
value={option.value}
/>
))}
</Options>
)}
</OptionsContainer>
{open && (
<Options>
{options.map(option => (
<Option key={option.value} onClick={handleSelect(option.value)}>
{option.label}
</Option>
))}
</Options>
)}
</Main>
</Root>
)
const MenuOption = ({ label, selected, value, handleSelect }) => (
<Option
active={value === selected}
key={value}
onClick={() => {
handleSelect(value)
}}
>
{label || value}
</Option>
</Fragment>
)
const enhance = compose(
export default compose(
withCountries,
withState('userInput', 'updateUserInput', ''),
withState('open', 'updateOptionsVizibility', false),
withState('selected', 'setSelectedValue', ''),
withState('open', 'updateOptionsVisibility', false),
withHandlers({
optionLabel: ({ countries }) => value => {
const label = countries.find(country => country.value === value)
? countries.find(country => country.value === value).label
: ''
return label
},
handleSelect: ({ setSelectedValue, updateOptionsVizibility }) => value => {
setSelectedValue(value)
updateOptionsVizibility(false)
handleSelect: ({
onChange,
countryLabel,
updateUserInput,
updateOptionsVisibility,
}) => value => () => {
onChange(value)
updateUserInput(countryLabel(value))
updateOptionsVisibility(false)
},
}),
withHandlers({
onChange: ({ updateUserInput }) => value => {
updateUserInput(get(value, 'target.value', ''))
toggleMenu: ({ updateOptionsVisibility, open }) => () => {
updateOptionsVisibility(!open)
},
onEnter: props => event => {
onTextChange: ({ updateUserInput }) => event => {
updateUserInput(get(event, 'target.value', ''))
},
onEnter: ({ handleSelect, userInput, countries }) => event => {
if (event.which === 13) {
props.handleSelect(firstFilteredCountry(props).value)
props.updateUserInput(firstFilteredCountry(props).label)
handleSelect(firstFilteredCountry({ countries, userInput }).value)()
}
},
toggleMenu: ({ updateOptionsVizibility, open }) => event => {
updateOptionsVizibility(!open)
},
removeSelectedOption: ({
setSelectedValue,
updateOptionsVizibility,
updateUserInput,
}) => event => {
setSelectedValue('')
updateUserInput('')
updateOptionsVizibility(true)
},
}),
)
export default enhance(MenuCountry)
withProps(({ countries, userInput }) => ({
options: filteredCountries({ countries, userInput }),
})),
)(Menu)
// #region styles
const Input = styled.input`
width: 100%;
height: calc(${th('gridUnit')} * 4);
@@ -148,7 +97,6 @@ const Input = styled.input`
outline: none;
}
`
const Root = styled.div``
const CloseOverlay = styled.div`
background-color: transparent;
@@ -179,17 +127,9 @@ const Main = styled.div.attrs(props => ({
${override('ui.MenuCountry.Main')};
`
const OptionsContainer = styled.div`
position: absolute;
left: 0;
right: 0;
${override('ui.MenuCountry.OptionsContainer')};
`
const Options = styled.div`
position: absolute;
top: 0;
top: 35px;
left: 0;
right: 0;
@@ -197,8 +137,8 @@ const Options = styled.div`
border: ${th('borderWidth')} ${th('borderStyle')} ${th('colorBorder')};
border-radius: ${th('borderRadius')};
overflow-y: auto;
max-height: ${({ maxHeight }) => `${maxHeight}px`};
max-width: ${({ maxWidth }) => `${maxWidth}px`};
max-height: ${({ maxHeight }) => `${maxHeight || 250}px`};
max-width: ${({ maxWidth }) => `${maxWidth || 200}px`};
z-index: 100;
${override('ui.MenuCountry.Options')};
@@ -234,3 +174,4 @@ const Option = styled.div.attrs(props => ({
${override('ui.MenuCountry.Option')};
`
// #endregion