nexxtway/react-rainbow

View on GitHub
src/components/PhoneInput/countriesDropdown/index.js

Summary

Maintainability
C
1 day
Test Coverage
import React, { useRef, memo } from 'react';
import PropTypes from 'prop-types';
import {
    useFilterCountries,
    useKeyboardNavigation,
    useScrollControls,
    useItemsRef,
    useHandleCountryChange,
} from './hooks';
import {
    StyledScrollable,
    StyledUl,
    StyledDropdown,
    StyledSearchContainer,
    StyledSearch,
    StyledScrollControls,
} from './styled';
import { Arrow } from '../../InternalDropdown/styled';
import CountriesList from './countriesList';
import RenderIf from '../../RenderIf';
import StyledSearchIcon from '../../Lookup/options/styled/searchIcon';
import StyledOptionsContainer from '../../Lookup/options/styled/optionsContainer';
import StyledEmptyMessage from '../../Lookup/options/styled/emptyMessage';

const CountriesDropdown = memo(
    React.forwardRef((props, ref) => {
        const {
            country,
            countries,
            isOpen,
            searchRef,
            onCountryChange,
            onKeyDown,
            borderRadius,
        } = props;

        const scrollableRef = useRef();
        const [query, countriesFiltered, setQuery] = useFilterCountries(countries, country);
        const itemsRef = useItemsRef(countriesFiltered.length);
        const handleCountryChange = useHandleCountryChange(
            scrollableRef,
            onCountryChange,
            setQuery,
        );
        const handleActiveChange = useKeyboardNavigation(
            country,
            countriesFiltered,
            searchRef,
            scrollableRef,
            itemsRef,
            handleCountryChange,
        );
        const {
            showScrollUp,
            showScrollDown,
            handleScrollUpMouseEnter,
            handleScrollDownouseEnter,
            stopScroll,
        } = useScrollControls(scrollableRef);

        const listHeight = countriesFiltered.length * 45;

        return (
            <StyledDropdown
                isOpen={isOpen}
                onKeyDown={onKeyDown}
                ref={ref}
                borderRadius={borderRadius}
            >
                <StyledSearchContainer>
                    <StyledSearch
                        ref={searchRef}
                        type="text"
                        value={query}
                        onChange={event => setQuery(event.target.value)}
                    />
                </StyledSearchContainer>
                <StyledScrollControls>
                    <RenderIf isTrue={showScrollUp}>
                        <Arrow
                            direction="up"
                            onMouseEnter={handleScrollUpMouseEnter}
                            onMouseLeave={stopScroll}
                        />
                    </RenderIf>
                    <StyledScrollable ref={scrollableRef}>
                        <RenderIf isTrue={countriesFiltered.length > 0}>
                            <StyledUl role="listbox" listHeight={listHeight}>
                                <CountriesList
                                    countries={countriesFiltered}
                                    country={country}
                                    itemsRef={itemsRef}
                                    handleCountryChange={handleCountryChange}
                                    handleActiveChange={handleActiveChange}
                                />
                            </StyledUl>
                        </RenderIf>
                        <RenderIf isTrue={countriesFiltered.length === 0}>
                            <StyledOptionsContainer
                                as="div"
                                data-id="phone-country-empty-container"
                            >
                                <StyledSearchIcon />
                                <StyledEmptyMessage>
                                    Our robots did not find any match for
                                    <span>{` "${query}"`}</span>
                                </StyledEmptyMessage>
                            </StyledOptionsContainer>
                        </RenderIf>
                    </StyledScrollable>
                </StyledScrollControls>
                <RenderIf isTrue={showScrollDown}>
                    <Arrow
                        direction="down"
                        onMouseEnter={handleScrollDownouseEnter}
                        onMouseLeave={stopScroll}
                    />
                </RenderIf>
            </StyledDropdown>
        );
    }),
);

CountriesDropdown.propTypes = {
    countries: PropTypes.array,
    country: PropTypes.object,
    searchRef: PropTypes.object,
    isOpen: PropTypes.bool,
    onCountryChange: PropTypes.func,
    onKeyDown: PropTypes.func,
    borderRadius: PropTypes.oneOf(['square', 'semi-square', 'semi-rounded', 'rounded']),
};

CountriesDropdown.defaultProps = {
    countries: [],
    country: undefined,
    isOpen: false,
    searchRef: undefined,
    onCountryChange: () => {},
    onKeyDown: () => {},
    borderRadius: 'rounded',
};

export default CountriesDropdown;