Skip to content
Snippets Groups Projects
Commit 44c707f3 authored by MB Pro's avatar MB Pro
Browse files

fix(menuCountry): New component for MenuCountry

parent 969629bf
No related branches found
No related tags found
3 merge requests!222Sprint #26,!217Sprint #26,!207Hin 1138 country menu
import React from 'react' import React from 'react'
import { Menu } from '@pubsweet/ui'
import { startsWith, toLower, get } from 'lodash' import { startsWith, toLower, get } from 'lodash'
import { compose, withState, withHandlers } from 'recompose' import { compose, withState, withHandlers } from 'recompose'
import styled from 'styled-components' import styled from 'styled-components'
import { th } from '@pubsweet/ui-toolkit' import { th, override } from '@pubsweet/ui-toolkit'
import { withCountries } from 'pubsweet-component-faraday-ui' import { withCountries } from 'pubsweet-component-faraday-ui'
...@@ -13,51 +12,119 @@ const filteredCountries = (countries, userInput) => ...@@ -13,51 +12,119 @@ const filteredCountries = (countries, userInput) =>
const firstFilteredCountry = props => const firstFilteredCountry = props =>
filteredCountries(props.countries, props.userInput)[0] filteredCountries(props.countries, props.userInput)[0]
const CustomOpener = ({ const Opener = ({
selected, selected,
userInput, userInput,
toggleMenu, toggleMenu,
placeholder, placeholder,
optionLabel, optionLabel,
removeSelectedOption,
onChange, onChange,
onEnter, onEnter,
}) => ( }) => (
<Input <Input
onChange={onChange} onChange={onChange}
onClick={toggleMenu} onClick={selected ? removeSelectedOption : toggleMenu}
onKeyUp={onEnter} onKeyUp={onEnter}
placeholder={selected ? optionLabel(selected) : placeholder} placeholder={placeholder}
value={userInput} value={selected ? optionLabel(selected) : userInput}
/> />
) )
const MenuCountry = ({ countries = [], ...input }) => ( const MenuCountry = ({ countries = [], ...input }) => (
<Menu <Menu
maxHeight={250}
maxWidth={200}
{...input} {...input}
options={filteredCountries(countries, input.userInput)} options={filteredCountries(countries, input.userInput)}
placeholder="Please select" placeholder="Please select"
renderOpener={CustomOpener}
/> />
) )
const Menu = props => (
<Root>
{props.label && <Label onClick={props.optionLabel}>{props.label}</Label>}
{props.open && <CloseOverlay onClick={props.toggleMenu} />}
<Main>
<Opener
open={props.open}
optionLabel={props.optionLabel}
placeholder={props.placeHolder}
removeSelectedOption={props.removeSelectedOption}
selected={props.selected}
toggleMenu={props.toggleMenu}
{...props}
/>
<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>
</Main>
</Root>
)
const MenuOption = ({ label, selected, value, handleSelect }) => (
<Option
active={value === selected}
key={value}
onClick={() => {
handleSelect(value)
}}
>
{label || value}
</Option>
)
const enhance = compose( const enhance = compose(
withCountries, withCountries,
withState('userInput', 'updateUserInput', ''), withState('userInput', 'updateUserInput', ''),
withState('open', 'updateOptionsVizibility', false),
withState('selected', 'setSelectedValue', ''),
withHandlers({ withHandlers({
onChange: ({ updateUserInput, onChange }) => value => { optionLabel: ({ countries }) => value => {
// this value is an input DOM event while typing and a dropdown value when const label = countries.find(country => country.value === value)
// selected ? countries.find(country => country.value === value).label
if (typeof value === 'string') { : ''
onChange(value) return label
} },
handleSelect: ({ setSelectedValue, updateOptionsVizibility }) => value => {
setSelectedValue(value)
updateOptionsVizibility(false)
},
}),
withHandlers({
onChange: ({ updateUserInput }) => value => {
updateUserInput(get(value, 'target.value', '')) updateUserInput(get(value, 'target.value', ''))
}, },
onEnter: props => event => { onEnter: props => event => {
if (event.which === 13) { if (event.which === 13) {
props.onChange(firstFilteredCountry(props).value) props.handleSelect(firstFilteredCountry(props).value)
props.updateUserInput(firstFilteredCountry(props).label) props.updateUserInput(firstFilteredCountry(props).label)
} }
}, },
toggleMenu: ({ updateOptionsVizibility, open }) => event => {
updateOptionsVizibility(!open)
},
removeSelectedOption: ({
setSelectedValue,
updateOptionsVizibility,
updateUserInput,
}) => event => {
setSelectedValue('')
updateUserInput('')
updateOptionsVizibility(true)
},
}), }),
) )
...@@ -69,13 +136,101 @@ const Input = styled.input` ...@@ -69,13 +136,101 @@ const Input = styled.input`
border: ${th('accordion.border')}; border: ${th('accordion.border')};
border-radius: ${th('borderRadius')}; border-radius: ${th('borderRadius')};
padding: 0 ${th('gridUnit')}; padding: 0 ${th('gridUnit')};
font-family: ${th('fontHeading')};
::placeholder { ::placeholder {
color: ${th('colorText')}; color: ${th('colorText')};
opacity: 1; opacity: 1;
font-family: ${th('fontWriting')}; font-family: ${th('fontWriting')};
font-style: italic;
} }
:focus { :focus {
border-color: ${th('action.colorActive')} border-color: ${th('action.colorActive')}
outline: none; outline: none;
} }
` `
const Root = styled.div``
const CloseOverlay = styled.div`
background-color: transparent;
position: fixed;
bottom: 0;
left: 0;
top: 0;
right: 0;
z-index: 10;
${override('ui.MenuCountry.CloseOverlay')};
`
const Label = styled.label`
font-size: ${th('fontSizeBaseSmall')};
line-height: ${th('lineHeightBaseSmall')};
display: block;
${override('ui.Label')};
${override('ui.MenuCountry.Label')};
`
const Main = styled.div.attrs(props => ({
role: 'listbox',
}))`
position: relative;
${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;
left: 0;
right: 0;
background-color: ${th('colorBackground')};
border: ${th('borderWidth')} ${th('borderStyle')} ${th('colorBorder')};
border-radius: ${th('borderRadius')};
overflow-y: auto;
max-height: ${({ maxHeight }) => `${maxHeight}px`};
max-width: ${({ maxWidth }) => `${maxWidth}px`};
z-index: 100;
${override('ui.MenuCountry.Options')};
`
const Option = styled.div.attrs(props => ({
role: 'option',
tabIndex: '0',
'aria-selected': props.active,
}))`
color: ${props => (props.active ? props.theme.textColor : '#444')};
font-weight: ${props => (props.active ? '600' : 'inherit')};
cursor: pointer;
font-family: ${th('fontAuthor')};
padding: calc(${th('gridUnit')} - ${th('borderWidth')} * 2)
calc(${th('gridUnit')} * 2);
border: ${th('borderWidth')} ${th('borderStyle')} transparent;
border-width: ${th('borderWidth')} 0 ${th('borderWidth')} 0;
white-space: nowrap;
&:hover {
background: ${th('colorBackgroundHue')};
border-color: ${th('colorBorder')};
}
&:first-child:hover {
border-top-color: ${th('colorBackgroundHue')};
}
&:last-child:hover {
border-bottom-color: ${th('colorBackgroundHue')};
}
${override('ui.MenuCountry.Option')};
`
...@@ -174,6 +174,7 @@ const hindawiTheme = { ...@@ -174,6 +174,7 @@ const hindawiTheme = {
{ {
Icon, Icon,
Menu, Menu,
MenuCountry: Menu,
Radio, Radio,
Steps, Steps,
Action, Action,
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment