feat: address composite field (#4492)

Added new Address field input type.

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
rostaklein
2024-03-28 16:50:38 +01:00
committed by GitHub
parent 22d4af2e0c
commit 3171d0c87b
56 changed files with 1839 additions and 716 deletions

View File

@ -0,0 +1,37 @@
import { useMemo } from 'react';
import { IconComponentProps } from '@/ui/display/icon/types/IconComponent';
import { SELECT_COUNTRY_DROPDOWN_ID } from '@/ui/input/components/internal/country/constants/SelectCountryDropdownId';
import { useCountries } from '@/ui/input/components/internal/hooks/useCountries';
import { Select, SelectOption } from '@/ui/input/components/Select';
export const CountrySelect = ({
selectedCountryName,
onChange,
}: {
selectedCountryName: string;
onChange: (countryCode: string) => void;
}) => {
const countries = useCountries();
const options: SelectOption<string>[] = useMemo(() => {
return countries.map<SelectOption<string>>(({ countryName, Flag }) => ({
label: countryName,
value: countryName,
Icon: (props: IconComponentProps) =>
Flag({ width: props.size, height: props.size }), // TODO : improve this ?
}));
}, [countries]);
return (
<Select
fullWidth
dropdownId={SELECT_COUNTRY_DROPDOWN_ID}
options={options}
label="COUNTRY"
withSearchInput
onChange={onChange}
value={selectedCountryName}
/>
);
};

View File

@ -0,0 +1 @@
export const SELECT_COUNTRY_DROPDOWN_ID = 'select-country-picker';

View File

@ -0,0 +1,37 @@
import { useMemo } from 'react';
import { hasFlag } from 'country-flag-icons';
import * as Flags from 'country-flag-icons/react/3x2';
import { getCountries, getCountryCallingCode } from 'libphonenumber-js';
import { Country } from '@/ui/input/components/internal/types/Country';
export const useCountries = () => {
return useMemo<Country[]>(() => {
const regionNamesInEnglish = new Intl.DisplayNames(['en'], {
type: 'region',
});
const countryCodes = getCountries();
return countryCodes.reduce<Country[]>((result, countryCode) => {
const countryName = regionNamesInEnglish.of(countryCode);
if (!countryName) return result;
if (!hasFlag(countryCode)) return result;
const Flag = Flags[countryCode];
const callingCode = getCountryCallingCode(countryCode);
result.push({
countryCode,
countryName,
callingCode,
Flag,
});
return result;
}, []);
}, []);
};

View File

@ -1,19 +1,17 @@
import { useEffect, useMemo, useState } from 'react';
import { getCountries, getCountryCallingCode } from 'react-phone-number-input';
import { useEffect, useState } from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { hasFlag } from 'country-flag-icons';
import * as Flags from 'country-flag-icons/react/3x2';
import { CountryCallingCode } from 'libphonenumber-js';
import { IconChevronDown, IconWorld } from '@/ui/display/icon';
import { useCountries } from '@/ui/input/components/internal/hooks/useCountries';
import { Country } from '@/ui/input/components/internal/types/Country';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { isDefined } from '~/utils/isDefined';
import { CountryPickerHotkeyScope } from '../types/CountryPickerHotkeyScope';
import { CountryPickerDropdownSelect } from './CountryPickerDropdownSelect';
import { PhoneCountryPickerDropdownSelect } from './PhoneCountryPickerDropdownSelect';
import 'react-phone-number-input/style.css';
@ -57,14 +55,7 @@ const StyledIconContainer = styled.div`
}
`;
export type Country = {
countryCode: string;
countryName: string;
callingCode: CountryCallingCode;
Flag: Flags.FlagComponent;
};
export const CountryPickerDropdownButton = ({
export const PhoneCountryPickerDropdownButton = ({
value,
onChange,
}: {
@ -82,34 +73,7 @@ export const CountryPickerDropdownButton = ({
closeDropdown();
};
const countries = useMemo<Country[]>(() => {
const regionNamesInEnglish = new Intl.DisplayNames(['en'], {
type: 'region',
});
const countryCodes = getCountries();
return countryCodes.reduce<Country[]>((result, countryCode) => {
const countryName = regionNamesInEnglish.of(countryCode);
if (!countryName) return result;
if (!hasFlag(countryCode)) return result;
const Flag = Flags[countryCode];
const callingCode = getCountryCallingCode(countryCode);
result.push({
countryCode,
countryName,
callingCode,
Flag,
});
return result;
}, []);
}, []);
const countries = useCountries();
useEffect(() => {
const country = countries.find(({ countryCode }) => countryCode === value);
@ -132,7 +96,7 @@ export const CountryPickerDropdownButton = ({
</StyledDropdownButtonContainer>
}
dropdownComponents={
<CountryPickerDropdownSelect
<PhoneCountryPickerDropdownSelect
countries={countries}
selectedCountry={selectedCountry}
onChange={handleChange}

View File

@ -1,6 +1,7 @@
import { useMemo, useState } from 'react';
import styled from '@emotion/styled';
import { Country } from '@/ui/input/components/internal/types/Country';
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
@ -8,8 +9,6 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
import { MenuItemSelectAvatar } from '@/ui/navigation/menu-item/components/MenuItemSelectAvatar';
import { Country } from './CountryPickerDropdownButton';
import 'react-phone-number-input/style.css';
const StyledIconContainer = styled.div`
@ -27,7 +26,7 @@ const StyledIconContainer = styled.div`
}
`;
export const CountryPickerDropdownSelect = ({
export const PhoneCountryPickerDropdownSelect = ({
countries,
selectedCountry,
onChange,

View File

@ -0,0 +1,9 @@
import * as Flags from 'country-flag-icons/react/3x2';
import { CountryCallingCode } from 'libphonenumber-js';
export type Country = {
countryCode: string;
countryName: string;
callingCode: CountryCallingCode;
Flag: Flags.FlagComponent;
};