-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(PhoneNumberFieldLite): Phone number field with simple formatting…
… to reduce bundle size (#1276) WEB-2081 Review re-requested because E164 support has been added Related commits: https://github.com/Telefonica/mistica-web/pull/1276/files/59f3ec30947f358fddff18befe4e1db69726fb4d..7cb3c6f1eef8445bba2b247d1f246b2fba9c904e --------- Co-authored-by: Pedro Ladaria <[email protected]>
- Loading branch information
Showing
10 changed files
with
550 additions
and
4 deletions.
There are no files selected for viewing
Binary file added
BIN
+8.57 KB
...-screenshot-test-tsx-phone-number-field-lite-2145678901-in-vivo-skin-1-snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+7.56 KB
...screenshot-test-tsx-phone-number-field-lite-34654834455-in-vivo-skin-1-snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+7.83 KB
...reenshot-test-tsx-phone-number-field-lite-654834455-in-movistar-skin-1-snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
import * as React from 'react'; | ||
import {Box, Text1, Stack, ResponsiveLayout, PhoneNumberFieldLite, Boxed} from '..'; | ||
import {inspect} from 'util'; | ||
import {phoneNumbersList} from './helpers'; | ||
|
||
export default { | ||
title: 'Components/Input fields/PhoneNumberFieldLite', | ||
parameters: {fullScreen: true}, | ||
}; | ||
|
||
const getPhoneNumberSuggestions = (value: string) => | ||
phoneNumbersList | ||
.filter((s) => String(s).toLocaleLowerCase().startsWith(value.toLocaleLowerCase())) | ||
.slice(0, 5); | ||
|
||
interface PhoneNumberFieldBaseArgs { | ||
label: string; | ||
placeholder: string; | ||
prefix: string; | ||
helperText: string; | ||
error: boolean; | ||
inverse: boolean; | ||
optional: boolean; | ||
disabled: boolean; | ||
readOnly: boolean; | ||
preventCopy: boolean; | ||
} | ||
|
||
const defaultBaseArgs: PhoneNumberFieldBaseArgs = { | ||
label: 'Label', | ||
placeholder: '', | ||
prefix: '', | ||
helperText: '', | ||
error: false, | ||
inverse: false, | ||
optional: false, | ||
disabled: false, | ||
readOnly: false, | ||
preventCopy: false, | ||
}; | ||
|
||
interface PhoneNumberFieldControlledArgs extends PhoneNumberFieldBaseArgs { | ||
initialValue: string; | ||
suggestions: boolean; | ||
} | ||
|
||
const Description = () => { | ||
return ( | ||
<Boxed> | ||
<Box padding={16}> | ||
<Stack space={16}> | ||
<div> | ||
This is a "light" version of the PhoneNumberField component. It does not use google's | ||
libphonenumber library to reduce bundle size. | ||
</div> | ||
<Stack space={8}> | ||
<div>- Only supported countries are formatted</div> | ||
<div>- Not all phone number types are formatted</div> | ||
<div>- Numbers in E164 are returned unformatted</div> | ||
<div> | ||
- A custom formatter can be provided via props and the formatter used by this | ||
component is exported as `formatPhoneLite` | ||
</div> | ||
</Stack> | ||
</Stack> | ||
</Box> | ||
</Boxed> | ||
); | ||
}; | ||
|
||
export const Controlled: StoryComponent<PhoneNumberFieldControlledArgs> = ({ | ||
inverse, | ||
initialValue, | ||
suggestions, | ||
...rest | ||
}) => { | ||
const [rawValue, setRawValue] = React.useState<any>(initialValue); | ||
const [value, setValue] = React.useState<any>(undefined); | ||
|
||
return ( | ||
<ResponsiveLayout variant={inverse ? 'inverse' : undefined} fullWidth> | ||
<Box padding={16}> | ||
<Stack space={16}> | ||
<Description /> | ||
<PhoneNumberFieldLite | ||
value={rawValue} | ||
onChangeValue={(value, rawValue) => { | ||
setValue(value); | ||
setRawValue(rawValue); | ||
}} | ||
name="phoneNumber" | ||
autoComplete="off" | ||
dataAttributes={{testid: 'phone-number-field-lite'}} | ||
getSuggestions={suggestions ? getPhoneNumberSuggestions : undefined} | ||
{...rest} | ||
/> | ||
<Stack space={8}> | ||
<Text1 regular> | ||
value: {typeof value === 'undefined' ? '' : `(${typeof value}) ${inspect(value)}`} | ||
</Text1> | ||
<Text1 regular> | ||
rawValue:{' '} | ||
{typeof rawValue === 'undefined' | ||
? '' | ||
: `(${typeof rawValue}) ${inspect(rawValue)}`} | ||
</Text1> | ||
</Stack> | ||
</Stack> | ||
</Box> | ||
</ResponsiveLayout> | ||
); | ||
}; | ||
|
||
Controlled.storyName = 'controlled'; | ||
Controlled.args = { | ||
initialValue: '654834455', | ||
...defaultBaseArgs, | ||
suggestions: false, | ||
}; | ||
|
||
interface PhoneNumberFieldUncontrolledArgs extends PhoneNumberFieldBaseArgs { | ||
defaultValue: string; | ||
} | ||
|
||
export const Uncontrolled: StoryComponent<PhoneNumberFieldUncontrolledArgs> = ({ | ||
inverse, | ||
defaultValue, | ||
...rest | ||
}) => { | ||
const [rawValue, setRawValue] = React.useState<any>(undefined); | ||
const [value, setValue] = React.useState<any>(undefined); | ||
|
||
return ( | ||
<ResponsiveLayout variant={inverse ? 'inverse' : undefined} fullWidth> | ||
<Box padding={16}> | ||
<Stack space={16}> | ||
<Description /> | ||
<PhoneNumberFieldLite | ||
defaultValue={defaultValue} | ||
onChangeValue={(value, rawValue) => { | ||
setValue(value); | ||
setRawValue(rawValue); | ||
}} | ||
name="phoneNumber" | ||
autoComplete="off" | ||
dataAttributes={{testid: 'phone-number-field-lite'}} | ||
{...rest} | ||
/> | ||
<Stack space={8}> | ||
<Text1 regular> | ||
value: {typeof value === 'undefined' ? '' : `(${typeof value}) ${inspect(value)}`} | ||
</Text1> | ||
<Text1 regular> | ||
rawValue:{' '} | ||
{typeof rawValue === 'undefined' | ||
? '' | ||
: `(${typeof rawValue}) ${inspect(rawValue)}`} | ||
</Text1> | ||
</Stack> | ||
</Stack> | ||
</Box> | ||
</ResponsiveLayout> | ||
); | ||
}; | ||
|
||
Uncontrolled.storyName = 'uncontrolled'; | ||
Uncontrolled.args = { | ||
defaultValue: '654834455', | ||
...defaultBaseArgs, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import {render, screen} from '@testing-library/react'; | ||
import PhoneNumberFieldLite from '../phone-number-field-lite'; | ||
import {getMovistarSkin} from '../skins/movistar'; | ||
import ThemeContextProvider from '../theme-context-provider'; | ||
import userEvent from '@testing-library/user-event'; | ||
import * as React from 'react'; | ||
import PhoneNumberField from '../phone-number-field'; | ||
|
||
test.each` | ||
regionCode | number | expected | expectedRaw | expectedE164 | description | ||
${'ZZ'} | ${'123456789012345'} | ${'123456789012345'} | ${'123456789012345'} | ${'123456789012345'} | ${'Unknown region'} | ||
${'ES'} | ${'654834455'} | ${'654834455'} | ${'654 83 44 55'} | ${'+34654834455'} | ${'ES mobile'} | ||
${'ES'} | ${'914-44/10 25'} | ${'914441025'} | ${'914 44 10 25'} | ${'+34914441025'} | ${'ES landline'} | ||
${'ES'} | ${'6548344556'} | ${'6548344556'} | ${'6548344556'} | ${'+346548344556'} | ${'ES mobile too long'} | ||
${'ES'} | ${'914-44/10 256'} | ${'9144410256'} | ${'9144410256'} | ${'+349144410256'} | ${'ES landline too long'} | ||
${'ES'} | ${'+34 654 834 455'} | ${'+34654834455'} | ${'+34 654 83 44 55'} | ${'+34654834455'} | ${'ES E164 mobile'} | ||
${'ES'} | ${'+34 914-44/10 25'} | ${'+34914441025'} | ${'+34 914 44 10 25'} | ${'+34914441025'} | ${'ES E164 landline'} | ||
${'BR'} | ${'21987654321'} | ${'21987654321'} | ${'(21) 98765-4321'} | ${'+5521987654321'} | ${'BR mobile'} | ||
${'BR'} | ${'219876543210'} | ${'219876543210'} | ${'219876543210'} | ${'+55219876543210'} | ${'BR mobile too long'} | ||
${'BR'} | ${'2123456789'} | ${'2123456789'} | ${'(21) 2345-6789'} | ${'+552123456789'} | ${'BR landline'} | ||
${'BR'} | ${'21234567890'} | ${'21234567890'} | ${'(21) 23456-7890'} | ${'+5521234567890'} | ${'BR landline long'} | ||
${'BR'} | ${'212345678901'} | ${'212345678901'} | ${'212345678901'} | ${'+55212345678901'} | ${'BR landline too long'} | ||
${'BR'} | ${'+5521987654321'} | ${'+5521987654321'} | ${'+55 21 98765-4321'} | ${'+5521987654321'} | ${'BR E164 mobile'} | ||
${'BR'} | ${'+34654834455'} | ${'+34654834455'} | ${'+34 654 83 44 55'} | ${'+34654834455'} | ${'BR with ES E164'} | ||
${'DE'} | ${'015789012345'} | ${'015789012345'} | ${'01578 9012345'} | ${'+4915789012345'} | ${'DE mobile 15'} | ||
${'DE'} | ${'01601234567'} | ${'01601234567'} | ${'0160 1234567'} | ${'+491601234567'} | ${'DE mobile 16'} | ||
${'DE'} | ${'01701234567'} | ${'01701234567'} | ${'0170 1234567'} | ${'+491701234567'} | ${'DE mobile 17'} | ||
${'DE'} | ${'12345678901'} | ${'12345678901'} | ${'12345678901'} | ${'+4912345678901'} | ${'DE unknown'} | ||
${'DE'} | ${'+4915789012345'} | ${'+4915789012345'} | ${'+49 1578 9012345'} | ${'+4915789012345'} | ${'DE E164 mobile'} | ||
${'DE'} | ${'+49015789012345'} | ${'+49015789012345'} | ${'+49 015789012345'} | ${'+49015789012345'} | ${'DE E164 mobile wrong zero'} | ||
${'GB'} | ${'07123456789'} | ${'07123456789'} | ${'07123 456789'} | ${'+447123456789'} | ${'GB mobile'} | ||
${'GB'} | ${'071234567890'} | ${'071234567890'} | ${'071234567890'} | ${'+4471234567890'} | ${'GB mobile too long'} | ||
${'GB'} | ${'+447123456789'} | ${'+447123456789'} | ${'+44 7123 456789'} | ${'+447123456789'} | ${'GB E164 mobile'} | ||
${'GB'} | ${'+4407123456789'} | ${'+4407123456789'} | ${'+44 07123456789'} | ${'+4407123456789'} | ${'GB E164 mobile wrong zero'} | ||
`( | ||
'PhoneNumberFieldLite - $description - $number', | ||
async ({regionCode, number, expected, expectedRaw, expectedE164}) => { | ||
const onChangeValue = jest.fn(); | ||
const onChangeValueE164 = jest.fn(); | ||
const onChangeValueUsingLibphonenumber = jest.fn(); | ||
|
||
render( | ||
<ThemeContextProvider | ||
theme={{ | ||
skin: getMovistarSkin(), | ||
i18n: {locale: 'es-ES', phoneNumberFormattingRegionCode: regionCode}, | ||
}} | ||
> | ||
<PhoneNumberFieldLite name="phone" label="Phone" onChangeValue={onChangeValue} /> | ||
<PhoneNumberFieldLite name="e164" label="Phone E164" onChangeValue={onChangeValueE164} e164 /> | ||
<PhoneNumberField | ||
name="ref" | ||
label="Reference" | ||
onChangeValue={onChangeValueUsingLibphonenumber} | ||
/> | ||
</ThemeContextProvider> | ||
); | ||
|
||
const input = screen.getByLabelText('Phone'); | ||
const inputE164 = screen.getByLabelText('Phone E164'); | ||
const referenceInput = screen.getByLabelText('Reference'); | ||
|
||
await userEvent.type(input, number); | ||
await userEvent.type(inputE164, number); | ||
await userEvent.type(referenceInput, number); | ||
|
||
expect(onChangeValue).toHaveBeenLastCalledWith(expected, expectedRaw); | ||
expect(onChangeValueE164).toHaveBeenLastCalledWith(expectedE164, expectedRaw); | ||
|
||
// We expect the same result as the libphonenumber version, except for the E164 format | ||
if (!number.startsWith('+')) { | ||
// This checks all the calls to onChangeValue (as you type) | ||
expect(onChangeValue.mock.calls).toEqual(onChangeValueUsingLibphonenumber.mock.calls); | ||
} | ||
} | ||
); | ||
|
||
test('PhoneNumberFieldLite custom formatter', async () => { | ||
const onChangeValue = jest.fn(); | ||
|
||
render( | ||
<ThemeContextProvider | ||
theme={{ | ||
skin: getMovistarSkin(), | ||
i18n: {locale: 'es-ES', phoneNumberFormattingRegionCode: 'ES'}, | ||
}} | ||
> | ||
<PhoneNumberFieldLite | ||
name="a" | ||
label="Phone" | ||
onChangeValue={onChangeValue} | ||
format={(number) => { | ||
return number.replace(/\D/g, '').split('').join('-'); | ||
}} | ||
/> | ||
</ThemeContextProvider> | ||
); | ||
|
||
const input = screen.getByLabelText('Phone'); | ||
await userEvent.type(input, '654834455'); | ||
|
||
expect(onChangeValue).toHaveBeenLastCalledWith('654834455', '6-5-4-8-3-4-4-5-5'); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
a141b97
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deploy preview for mistica-web ready!
✅ Preview
https://mistica-24d59x3u2-flows-projects-65bb050e.vercel.app
Built with commit a141b97.
This pull request is being automatically deployed with vercel-action