Skip to content

Commit

Permalink
Refactoring around CountryList (#316)
Browse files Browse the repository at this point in the history
* refactor: clean up countrylist

* chore: add styled-components

* refactor: create sc comps to replace arrows

* refactor: sub in scc instead of the css arrows

* test: adjust coverage

* chore: purge unused style

* refactor: trim down code, prettier

* chore: move styled-component to peer + dev dep

* chore: purge arrow style

* refactor: unused bind on arrow function

* refactor: extract divider as sc

* refactor: clean up class switching
  • Loading branch information
mcataford committed Mar 1, 2020
1 parent 3964ba1 commit ab083ed
Show file tree
Hide file tree
Showing 13 changed files with 205 additions and 150 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"main": "dist/main.js",
"peerDependencies": {
"react": ">15.4.2 <17.0.0",
"react-dom": ">15.4.2 <17.0.0"
"react-dom": ">15.4.2 <17.0.0",
"styled-components": "^4.0.0"
},
"dependencies": {
"classnames": "^2.2.5",
Expand Down Expand Up @@ -91,6 +92,7 @@
"sass-loader": "^7.1.0",
"sinon": "^1.17.4",
"storybook-addon-react-docgen": "^1.0.4",
"styled-components": "^4.0.0",
"style-loader": "^0.23.1",
"uglifyjs-webpack-plugin": "^2.0.1",
"url-loader": "^1.1.2",
Expand Down
61 changes: 26 additions & 35 deletions src/components/CountryList.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import utils from './utils';

import FlagBox from './FlagBox'

function partial(fn, ...args) {
return fn.bind(fn, ...args);
}
import FlagBox from './FlagBox';
import { Divider } from './CountryList.styles'

export default class CountryList extends Component {
static propTypes = {
Expand All @@ -26,16 +24,15 @@ export default class CountryList extends Component {
const shouldUpdate = !utils.shallowEquals(this.props, nextProps);

if (shouldUpdate && nextProps.showDropdown) {
this.listElement.setAttribute('class', 'country-list v-hide');
this.listElement.classList.add('v-hide');
this.setDropdownPosition();
}

return shouldUpdate;
}

setDropdownPosition = () => {
utils.removeClass(this.listElement, 'hide');

this.listElement.classList.remove('hide')
const inputTop = this.props.inputTop;
const windowTop =
window.pageYOffset !== undefined
Expand Down Expand Up @@ -63,11 +60,7 @@ export default class CountryList extends Component {
: '';

this.listElement.style.top = cssTop;
this.listElement.setAttribute('class', 'country-list');
};

setFlag = iso2 => {
this.props.setFlag(iso2);
this.listElement.classList.remove('v-hide')
};

appendListItem = (countries, isPreferred = false) => {
Expand All @@ -81,23 +74,29 @@ export default class CountryList extends Component {
preferred: isPreferred,
};
const countryClass = classNames(countryClassObj);
const onMouseOverOrFocus = this.props.isMobile ? () => {} : this.handleMouseOver
const keyPrefix = isPreferred ? 'pref-' : ''

const onMouseOverOrFocus = this.props.isMobile
? () => {}
: this.handleMouseOver;
const keyPrefix = isPreferred ? 'pref-' : '';

return (
<FlagBox
key={`${keyPrefix}${country.iso2}`}
key={`${keyPrefix}${country.iso2}`}
dialCode={country.dialCode}
isoCode={country.iso2}
name={country.name}
onMouseOver={onMouseOverOrFocus}
onClick={partial(this.setFlag, country.iso2)}
onClick={() => this.props.setFlag(country.iso2)}
onFocus={onMouseOverOrFocus}
flagRef={selectedFlag => { this.selectedFlag = selectedFlag }}
innerFlagRef={selectedFlagInner => { this.selectedFlagInner = selectedFlagInner }}
flagRef={selectedFlag => {
this.selectedFlag = selectedFlag;
}}
innerFlagRef={selectedFlagInner => {
this.selectedFlagInner = selectedFlagInner;
}}
countryClass={countryClass}
/>
)
);
});
};

Expand All @@ -110,21 +109,13 @@ export default class CountryList extends Component {
};

render() {
const { preferredCountries, countries, showDropdown } = this.props
let options = '';
let preferredOptions = null;
const className = classNames({
'country-list': true,
const { preferredCountries, countries, showDropdown } = this.props;
const className = classNames('country-list', {
hide: !showDropdown,
});
let divider = null;

if (preferredCountries.length) {
preferredOptions = this.appendListItem(preferredCountries, true);
divider = <div className="divider" />;
}

options = this.appendListItem(countries);
const preferredOptions = this.appendListItem(preferredCountries, true);
const allOptions = this.appendListItem(countries);

return (
<ul
Expand All @@ -134,8 +125,8 @@ export default class CountryList extends Component {
className={className}
>
{preferredOptions}
{divider}
{options}
{preferredCountries.length > 0 ? <Divider /> : null}
{allOptions}
</ul>
);
}
Expand Down
8 changes: 8 additions & 0 deletions src/components/CountryList.styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import styled from 'styled-components'

// eslint-disable-next-line import/prefer-default-export
export const Divider = styled.div`
padding-bottom: 5px;
margin-bottom: 5px;
border-bottom: $borderWidth solid $greyBorder;
`
26 changes: 9 additions & 17 deletions src/components/FlagBox.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import PropTypes from 'prop-types'
import React from 'react';
import PropTypes from 'prop-types';

const FlagBox = ({
dialCode,
Expand All @@ -20,22 +20,14 @@ const FlagBox = ({
onFocus={onFocus}
onClick={onClick}
>
<div
ref={flagRef}
className="flag-box"
>
<div
ref={innerFlagRef}
className={`iti-flag ${isoCode}`}
/>
<div ref={flagRef} className="flag-box">
<div ref={innerFlagRef} className={`iti-flag ${isoCode}`} />
</div>

<span className="country-name">{name}</span>
<span className="dial-code">
{`+ ${dialCode}`}
</span>
<span className="dial-code">{`+ ${dialCode}`}</span>
</li>
)
);

FlagBox.propTypes = {
dialCode: PropTypes.string.isRequired,
Expand All @@ -47,12 +39,12 @@ FlagBox.propTypes = {
flagRef: PropTypes.func,
innerFlagRef: PropTypes.func,
countryClass: PropTypes.string.isRequired,
}
};

FlagBox.defaultProps = {
onFocus: () => {},
onMouseOver: () => {},
onClick: () => {},
}
};

export default FlagBox
export default FlagBox;
37 changes: 15 additions & 22 deletions src/components/FlagDropDown.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ import classNames from 'classnames';
import CountryList from './CountryList';
import RootModal from './RootModal';

import {
DownArrow,
UpArrow,
SelectedFlagPopoverButton,
} from './FlagDropDown.styles';

export default class FlagDropDown extends Component {
static propTypes = {
allowDropdown: PropTypes.bool,
Expand Down Expand Up @@ -31,33 +37,20 @@ export default class FlagDropDown extends Component {

return separateDialCode ? (
<div className="selected-dial-code">{dialCode}</div>
) : (
''
);
) : null;
};

genArrow = () => {
const { allowDropdown, showDropdown } = this.props;
const arrowClass = classNames({
'iti-arrow': true,
up: showDropdown,
});
const arrow = showDropdown ? <UpArrow /> : <DownArrow />;

return allowDropdown ? <div className={arrowClass} /> : '';
return allowDropdown ? arrow : null;
};

genFlagClassName = () => {
const { countryCode } = this.props;
const flagClassObj = {
'iti-flag': true,
};

if (countryCode) {
flagClassObj[countryCode] = true;
}

return classNames(flagClassObj);
};
genFlagClassName = () =>
classNames('iti-flag', {
[this.props.countryCode]: !!this.props.countryCode,
});

genCountryList = () => {
const {
Expand Down Expand Up @@ -106,7 +99,7 @@ export default class FlagDropDown extends Component {

return (
<div ref={refCallback} className="flag-container">
<div
<SelectedFlagPopoverButton
className="selected-flag"
tabIndex={allowDropdown ? '0' : ''}
onClick={clickSelectedFlag}
Expand All @@ -116,7 +109,7 @@ export default class FlagDropDown extends Component {
<div className={this.genFlagClassName()} />
{this.genSelectedDialCode()}
{this.genArrow()}
</div>
</SelectedFlagPopoverButton>
{dropdownContainer && showDropdown ? (
<RootModal>{this.genCountryList()}</RootModal>
) : (
Expand Down
24 changes: 24 additions & 0 deletions src/components/FlagDropDown.styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import styled from 'styled-components';

const ArrowBase = styled.div`
font-size: 6px;
margin-left: 5px;
`;

export const UpArrow = styled(ArrowBase)`
&:after {
content: '▲';
}
`;

export const DownArrow = styled(ArrowBase)`
&:after {
content: '▼';
}
`;

export const SelectedFlagPopoverButton = styled.div`
display: flex;
justify-content: center;
align-items: center;
`;
17 changes: 8 additions & 9 deletions src/components/IntlTelInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ class IntlTelInput extends Component {
}

if (this.props.defaultCountry !== prevProps.defaultCountry) {
this.updateFlagOnDefaultCountryChange(this.props.defaultCountry)
this.updateFlagOnDefaultCountryChange(this.props.defaultCountry);
}
}

Expand All @@ -176,8 +176,8 @@ class IntlTelInput extends Component {
}

// Updates flag when value of defaultCountry props change
updateFlagOnDefaultCountryChange = (countryCode) => {
this.setFlag(countryCode, false)
updateFlagOnDefaultCountryChange = countryCode => {
this.setFlag(countryCode, false);
};

getTempCountry = countryCode => {
Expand Down Expand Up @@ -1215,12 +1215,11 @@ class IntlTelInput extends Component {
: previousValue.substring(0, cursorPosition);

// Don't format if user is deleting chars
const formattedValue = previousValue.length < priorValue.length
? previousValue
: this.formatNumber(e.target.value);
const value = this.props.format
? formattedValue
: e.target.value;
const formattedValue =
previousValue.length < priorValue.length
? previousValue
: this.formatNumber(e.target.value);
const value = this.props.format ? formattedValue : e.target.value;

cursorPosition = utils.getCursorPositionAfterFormating(
previousStringBeforeCursor,
Expand Down
5 changes: 4 additions & 1 deletion src/components/__tests__/FlagDropDown.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ describe('FlagDropDown', function() {
expect(
subject.find(CountryList).find('.country-list.hide').length
).toBeTruthy();
flagComponent.find('.selected-flag').simulate('click');
flagComponent
.find('.selected-flag')
.last()
.simulate('click');

subject.update();
expect(
Expand Down
5 changes: 4 additions & 1 deletion src/components/__tests__/TelInput.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,10 @@ describe('TelInput', function() {

it('should set "expanded" class to wrapper only when flags are open', () => {
const subject = this.makeSubject();
const flagComponent = subject.find(FlagDropDown).find('.selected-flag');
const flagComponent = subject
.find(FlagDropDown)
.find('.selected-flag')
.last();

flagComponent.simulate('click');
expect(subject.instance().wrapperClass.expanded).toBe(true);
Expand Down
11 changes: 0 additions & 11 deletions src/components/__tests__/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,6 @@ describe('utils', () => {
expect(element.classList.contains('efg')).toBeTruthy();
});

it('removeClass', () => {
const DEFAULT_HTML = `<html><body>
<div class="abc cde">test</div>
</body></html>`;
const doc = jsdom.jsdom(DEFAULT_HTML);
const element = doc.querySelector('.abc');

utils.removeClass(element, 'abc');

expect(element.classList.contains('abc')).toBeFalsy();
});

it('findIndex', () => {
let array = [];
Expand Down
10 changes: 0 additions & 10 deletions src/components/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,16 +188,6 @@ export default {
}
},

removeClass(el, className) {
if (el.classList) {
el.classList.remove(className);
} else if (this.hasClass(el, className)) {
const reg = new RegExp(`(\\s|^)${className}(\\s|$)`);

el.className = el.className.replace(reg, ' ');
}
},

findIndex(items, predicate) {
let index = -1;

Expand Down
Loading

0 comments on commit ab083ed

Please sign in to comment.