Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sumup-oss/circuit-ui': minor
---

Added a new `shouldDisplayCountryNames` prop to PhoneNumberInput to opt out of `Intl.DisplayNames` localization and display calling codes from `countryCode.options` directly.
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,15 @@ export const WithPrefix = (args: PhoneNumberInputProps) => {

WithPrefix.args = Base.args;

export const WithoutCountryNames = (args: PhoneNumberInputProps) => (
<PhoneNumberInput {...args} />
);

WithoutCountryNames.args = {
...Base.args,
shouldDisplayCountryNames: false,
};

export const Sizes = (args: PhoneNumberInputProps) => (
<Stack>
<PhoneNumberInput {...args} size="s" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,14 @@ export interface PhoneNumberInputProps
* preselected country code. Defaults to `navigator.languages`.
*/
locale?: string | string[];
/**
* When `true`, displays the localised country name in the country code selector using
* `Intl.DisplayNames`. When `false`, displays the calling codes from
* `countryCode.options` without localization.
*
* @default true
*/
shouldDisplayCountryNames?: boolean;
/**
* Choose from 2 sizes.
* @default m
Expand Down Expand Up @@ -232,6 +240,7 @@ export const PhoneNumberInput = forwardRef<
readOnly,
'aria-describedby': descriptionId,
locale,
shouldDisplayCountryNames = true,
size = 'm',
className,
style,
Expand All @@ -257,8 +266,13 @@ export const PhoneNumberInput = forwardRef<
);

const options = useMemo(
() => mapCountryCodeOptions(countryCode.options, locale),
[countryCode.options, locale],
() =>
mapCountryCodeOptions(
countryCode.options,
locale,
shouldDisplayCountryNames,
),
[countryCode.options, locale, shouldDisplayCountryNames],
);

const handleChange = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,5 +182,30 @@ describe('PhoneNumberInputService', () => {
const actual = mapCountryCodeOptions(options, locale);
expect(actual[0].value).toBe('DE');
});

it('should use calling codes as labels when shouldDisplayCountryNames is false', () => {
const options = [
{ country: 'CA', code: '+1' },
{ country: 'US', code: '+1' },
{ country: 'DE', code: '+49' },
];
const actual = mapCountryCodeOptions(options, undefined, false);
expect(actual[0].label).toBe('+1');
expect(actual[0].value).toBe('CA');
expect(actual[1].label).toBe('+1');
expect(actual[1].value).toBe('US');
expect(actual[2].label).toBe('+49');
expect(actual[2].value).toBe('DE');
});

it('should sort calling code labels when shouldDisplayCountryNames is false', () => {
const options = [
{ country: 'DE', code: '+49' },
{ country: 'CA', code: '+1' },
{ country: 'US', code: '+1' },
];
const actual = mapCountryCodeOptions(options, undefined, false);
expect(actual.map(({ label }) => label)).toEqual(['+1', '+1', '+49']);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,17 @@ export function normalizePhoneNumber(
export function mapCountryCodeOptions(
countryCodeOptions: CountryCodeOption[],
locale: Locale | undefined,
shouldDisplayCountryNames = true,
): Required<SelectProps>['options'] {
if (!shouldDisplayCountryNames) {
return countryCodeOptions
.map(({ code, country }) => ({
label: code,
value: country,
}))
.sort((a, b) => a.label.localeCompare(b.label));
}

const getCountryName = (country: string) => {
// eslint-disable-next-line compat/compat
const isIntlDisplayNamesSupported = typeof Intl.DisplayNames === 'function';
Expand Down
Loading