From a141b97e600efb30e37167990cb1b7ae23f16352 Mon Sep 17 00:00:00 2001 From: Pedro Ladaria Date: Tue, 29 Oct 2024 13:01:22 +0100 Subject: [PATCH 1/3] 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 --- ...ld-lite-2145678901-in-vivo-skin-1-snap.png | Bin 0 -> 8779 bytes ...d-lite-34654834455-in-vivo-skin-1-snap.png | Bin 0 -> 7737 bytes ...lite-654834455-in-movistar-skin-1-snap.png | Bin 0 -> 8013 bytes .../input-fields-screenshot-test.tsx | 22 ++ .../phone-number-field-lite-story.tsx | 170 ++++++++++++ src/__stories__/phone-number-field-story.tsx | 4 +- .../phone-number-field-lite-test.tsx | 103 +++++++ src/index.tsx | 1 + src/phone-number-field-lite.tsx | 251 ++++++++++++++++++ src/phone-number-field.tsx | 3 +- 10 files changed, 550 insertions(+), 4 deletions(-) create mode 100644 src/__screenshot_tests__/__image_snapshots__/input-fields-screenshot-test-tsx-phone-number-field-lite-2145678901-in-vivo-skin-1-snap.png create mode 100644 src/__screenshot_tests__/__image_snapshots__/input-fields-screenshot-test-tsx-phone-number-field-lite-34654834455-in-vivo-skin-1-snap.png create mode 100644 src/__screenshot_tests__/__image_snapshots__/input-fields-screenshot-test-tsx-phone-number-field-lite-654834455-in-movistar-skin-1-snap.png create mode 100644 src/__stories__/phone-number-field-lite-story.tsx create mode 100644 src/__tests__/phone-number-field-lite-test.tsx create mode 100644 src/phone-number-field-lite.tsx diff --git a/src/__screenshot_tests__/__image_snapshots__/input-fields-screenshot-test-tsx-phone-number-field-lite-2145678901-in-vivo-skin-1-snap.png b/src/__screenshot_tests__/__image_snapshots__/input-fields-screenshot-test-tsx-phone-number-field-lite-2145678901-in-vivo-skin-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..af28fe5c4587b4f25f0bbaf10dde75fc96fc493e GIT binary patch literal 8779 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 literal 0 HcmV?d00001 diff --git a/src/__screenshot_tests__/__image_snapshots__/input-fields-screenshot-test-tsx-phone-number-field-lite-654834455-in-movistar-skin-1-snap.png b/src/__screenshot_tests__/__image_snapshots__/input-fields-screenshot-test-tsx-phone-number-field-lite-654834455-in-movistar-skin-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..7fa9daf526d900c4128ae66e3e3079d9e3a2ed17 GIT binary patch literal 8013 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 G;r{{OuH-WS literal 0 HcmV?d00001 diff --git a/src/__screenshot_tests__/input-fields-screenshot-test.tsx b/src/__screenshot_tests__/input-fields-screenshot-test.tsx index 051e869888..da4bcdcb66 100644 --- a/src/__screenshot_tests__/input-fields-screenshot-test.tsx +++ b/src/__screenshot_tests__/input-fields-screenshot-test.tsx @@ -521,6 +521,28 @@ test.each` expect(await fieldWrapper.screenshot()).toMatchImageSnapshot(); }); +test.each` + skin | number + ${'Vivo'} | ${'2145678901'} + ${'Vivo'} | ${'+34654834455'} + ${'Movistar'} | ${'654834455'} +`('PhoneNumberFieldLite - $number in $skin skin', async ({skin, number}) => { + await openStoryPage({ + id: 'components-input-fields-phonenumberfieldlite--uncontrolled', + device: 'MOBILE_IOS', + skin, + args: {defaultValue: number}, + }); + + const fieldWrapper = await screen.findByTestId('phone-number-field-lite'); + const field = await screen.findByLabelText('Label'); + + await field.click({clickCount: 3}); + await field.type(number); + + expect(await fieldWrapper.screenshot()).toMatchImageSnapshot(); +}); + test('CreditCardExpirationField', async () => { await openStoryPage({ id: 'components-input-fields-creditcardexpirationfield--uncontrolled', diff --git a/src/__stories__/phone-number-field-lite-story.tsx b/src/__stories__/phone-number-field-lite-story.tsx new file mode 100644 index 0000000000..75717f8286 --- /dev/null +++ b/src/__stories__/phone-number-field-lite-story.tsx @@ -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 ( + + + +

+ This is a "light" version of the PhoneNumberField component. It does not use google's + libphonenumber library to reduce bundle size. +
+ +
- Only supported countries are formatted
+
- Not all phone number types are formatted
+
- Numbers in E164 are returned unformatted
+
+ - A custom formatter can be provided via props and the formatter used by this + component is exported as `formatPhoneLite` +
+
+ + + + ); +}; + +export const Controlled: StoryComponent = ({ + inverse, + initialValue, + suggestions, + ...rest +}) => { + const [rawValue, setRawValue] = React.useState(initialValue); + const [value, setValue] = React.useState(undefined); + + return ( + + + + + { + setValue(value); + setRawValue(rawValue); + }} + name="phoneNumber" + autoComplete="off" + dataAttributes={{testid: 'phone-number-field-lite'}} + getSuggestions={suggestions ? getPhoneNumberSuggestions : undefined} + {...rest} + /> + + + value: {typeof value === 'undefined' ? '' : `(${typeof value}) ${inspect(value)}`} + + + rawValue:{' '} + {typeof rawValue === 'undefined' + ? '' + : `(${typeof rawValue}) ${inspect(rawValue)}`} + + + + + + ); +}; + +Controlled.storyName = 'controlled'; +Controlled.args = { + initialValue: '654834455', + ...defaultBaseArgs, + suggestions: false, +}; + +interface PhoneNumberFieldUncontrolledArgs extends PhoneNumberFieldBaseArgs { + defaultValue: string; +} + +export const Uncontrolled: StoryComponent = ({ + inverse, + defaultValue, + ...rest +}) => { + const [rawValue, setRawValue] = React.useState(undefined); + const [value, setValue] = React.useState(undefined); + + return ( + + + + + { + setValue(value); + setRawValue(rawValue); + }} + name="phoneNumber" + autoComplete="off" + dataAttributes={{testid: 'phone-number-field-lite'}} + {...rest} + /> + + + value: {typeof value === 'undefined' ? '' : `(${typeof value}) ${inspect(value)}`} + + + rawValue:{' '} + {typeof rawValue === 'undefined' + ? '' + : `(${typeof rawValue}) ${inspect(rawValue)}`} + + + + + + ); +}; + +Uncontrolled.storyName = 'uncontrolled'; +Uncontrolled.args = { + defaultValue: '654834455', + ...defaultBaseArgs, +}; diff --git a/src/__stories__/phone-number-field-story.tsx b/src/__stories__/phone-number-field-story.tsx index d58a6ef2ea..01570e403e 100644 --- a/src/__stories__/phone-number-field-story.tsx +++ b/src/__stories__/phone-number-field-story.tsx @@ -56,7 +56,7 @@ export const Controlled: StoryComponent = ({ const [value, setValue] = React.useState(undefined); return ( - + = ({ const [value, setValue] = React.useState(undefined); return ( - + { + const onChangeValue = jest.fn(); + const onChangeValueE164 = jest.fn(); + const onChangeValueUsingLibphonenumber = jest.fn(); + + render( + + + + + + ); + + 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( + + { + return number.replace(/\D/g, '').split('').join('-'); + }} + /> + + ); + + const input = screen.getByLabelText('Phone'); + await userEvent.type(input, '654834455'); + + expect(onChangeValue).toHaveBeenLastCalledWith('654834455', '6-5-4-8-3-4-4-5-5'); +}); diff --git a/src/index.tsx b/src/index.tsx index 6cc2c95791..e8d1dc47e8 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -136,6 +136,7 @@ export {TextFieldBase} from './text-field-base'; export {default as SearchField} from './search-field'; export {default as EmailField} from './email-field'; export {default as PhoneNumberField} from './phone-number-field'; +export {default as PhoneNumberFieldLite, formatPhoneLite} from './phone-number-field-lite'; export {default as CreditCardNumberField} from './credit-card-number-field'; export {default as CreditCardExpirationField} from './credit-card-expiration-field'; export {default as CreditCardFields} from './credit-card-fields'; diff --git a/src/phone-number-field-lite.tsx b/src/phone-number-field-lite.tsx new file mode 100644 index 0000000000..946954ada3 --- /dev/null +++ b/src/phone-number-field-lite.tsx @@ -0,0 +1,251 @@ +'use client'; +import * as React from 'react'; +import {useRifm} from 'rifm'; +import {useFieldProps} from './form-context'; +import {TextFieldBaseAutosuggest} from './text-field-base'; +import {useTheme} from './hooks'; +import {createChangeEvent} from './utils/dom'; +import {combineRefs} from './utils/common'; + +import type {CommonFormFieldProps} from './text-field-base'; +import type {RegionCode} from './utils/region-code'; + +const COUNTRY_CODE_TO_REGION_CODE: Record = { + '+34': 'ES', + '+55': 'BR', + '+49': 'DE', + '+44': 'GB', +}; + +const REGION_CODE_TO_COUNTRY_CODE: Record = Object.fromEntries( + Object.entries(COUNTRY_CODE_TO_REGION_CODE).map(([k, v]) => [v, k]) +); + +const clean = (number: string): string => { + return number.trim().replace(/[^\d\+]/g, ''); // keep digits and "+" +}; + +const asE164 = (number: string, regionCode: RegionCode): string => { + if (number.startsWith('+')) { + return number; + } + + switch (regionCode) { + case 'ES': + return `${REGION_CODE_TO_COUNTRY_CODE[regionCode]} ${number}`; + case 'BR': + return `${REGION_CODE_TO_COUNTRY_CODE[regionCode]} ${number.replace(/[\(\)]/g, '')}`; + case 'DE': + return `${REGION_CODE_TO_COUNTRY_CODE[regionCode]} ${number.replace(/^0/, '')}`; + case 'GB': + return `${REGION_CODE_TO_COUNTRY_CODE[regionCode]} ${number.replace(/^0/, '')}`; + default: + return number; + } +}; + +/** + * Simple phone formatter for a few countries and a subset of phone numbers + * + * Formatting conditions have been adapted to exactly match libphonenumber's as you type formatting + * Not all formatting rules are implemented, only the most common ones. For a more complete solution, use PhoneNumberField + */ +export const formatPhoneLite = (regionCode: RegionCode, number: string): string => { + const cleanNumber = clean(number); + const isE164 = cleanNumber.startsWith('+'); + let digits = cleanNumber.replace(/\D/g, ''); // keep digits only + let countryCode = ''; + let formattingRegionCode = regionCode; + + if (isE164) { + // check if the number matches a known country code + countryCode = + Object.keys(COUNTRY_CODE_TO_REGION_CODE).find((code) => cleanNumber.startsWith(code)) || ''; + + if (countryCode) { + digits = cleanNumber.slice(countryCode.length); // remove country code + formattingRegionCode = COUNTRY_CODE_TO_REGION_CODE[countryCode]; // override region code, the country code has precedence + } else { + // unknown E164 is returned without formatting + return '+' + digits; + } + } + + if (formattingRegionCode === 'ES') { + // https://en.wikipedia.org/wiki/Telephone_numbers_in_Spain + // Example mobile: 654 83 44 55 + // Example landline: 914 44 10 25 + if (digits.length <= 9) { + return `${countryCode} ${digits.slice(0, 3)} ${digits.slice(3, 5)} ${digits.slice(5, 7)} ${digits.slice(7)}`.trim(); + } + } else if (formattingRegionCode === 'BR') { + // https://en.wikipedia.org/wiki/Telephone_numbers_in_Brazil + // Example mobile: (xx) (6..9)xxxx-xxxx + // Example landline: (xx) xxxx-xxxx + let national: string | undefined; + if (digits.length === 11) { + national = `(${digits.slice(0, 2)}) ${digits.slice(2, 7)}-${digits.slice(7)}`.replace(/\D+$/, ''); + } else if (digits.length > 2 && digits.length <= 11 && digits[2] <= '5') { + national = `(${digits.slice(0, 2)}) ${digits.slice(2, 6)}-${digits.slice(6)}`.replace(/\D+$/, ''); + } + if (national) { + return isE164 ? asE164(national, formattingRegionCode) : national; + } + } else if (formattingRegionCode === 'DE') { + // https://en.wikipedia.org/wiki/Telephone_numbers_in_Germany + // Only formatting mobile numbers, landline numbers have a lot of variations: + // https://en.wikipedia.org/wiki/Telephone_numbers_in_Germany#/media/File:Karte_Telefonvorwahlen_Deutschland.png + // Example mobile: 0157 89012345 + // Example E164: +49 1578 9012345 + const zeroPadded = isE164 ? '0' + digits : digits; + if (zeroPadded.length >= 4 && zeroPadded.match(/^(015|016|017)/)) { + let national: string | undefined; + if (zeroPadded.length <= 12 && zeroPadded.startsWith('015')) { + national = `${zeroPadded.slice(0, 5)} ${zeroPadded.slice(5)}`.trim(); + } else { + national = `${countryCode} ${zeroPadded.slice(0, 4)} ${zeroPadded.slice(4)}`.trim(); + } + return isE164 ? asE164(national, formattingRegionCode) : national; + } + } else if (formattingRegionCode === 'GB') { + // https://en.wikipedia.org/wiki/Telephone_numbers_in_the_United_Kingdom#Mobile_telephones + // Like in DE, only mobile numbers are formatted + // Example mobile: 07xxx xxxxxx + const zeroPadded = isE164 ? '0' + digits : digits; + if (zeroPadded.length <= 11 && zeroPadded.startsWith('07')) { + const national = `${zeroPadded.slice(0, 5)} ${zeroPadded.slice(5)}`.trim(); + return isE164 ? asE164(national, formattingRegionCode) : national; + } + } + return isE164 ? `${countryCode} ${digits}` : digits; +}; + +type InputProps = Omit, 'value' | 'onInput'> & { + inputRef?: React.Ref; + value?: string; + defaultValue?: string; + onInput?: (event: React.FormEvent) => void; + prefix?: string; + format?: (number: string) => string; +}; + +const PhoneInput = ({ + inputRef, + value, + defaultValue, + onChange, + prefix, + format: formatFromProps, + ...other +}: InputProps) => { + const [selfValue, setSelfValue] = React.useState(defaultValue || ''); + const ref = React.useRef(null); + const { + i18n: {phoneNumberFormattingRegionCode: regionCode}, + } = useTheme(); + + const isControlledByParent = typeof value !== 'undefined'; + const controlledValue = (isControlledByParent ? value : selfValue) as string; + + const handleChangeValue = React.useCallback( + (newFormattedValue: string) => { + if (!isControlledByParent) { + setSelfValue(newFormattedValue); + } + if (ref.current) { + onChange?.(createChangeEvent(ref.current, newFormattedValue)); + } + }, + [isControlledByParent, onChange] + ); + + const format = React.useCallback( + (number: string): string => { + if (formatFromProps) { + return formatFromProps(number); + } + return formatPhoneLite(regionCode, number); + }, + [formatFromProps, regionCode] + ); + + const rifm = useRifm({ + format, + value: controlledValue, + accept: /[\d\+]+/g, + onChange: handleChangeValue, + }); + + return ( + + ); +}; + +export interface PhoneNumberFieldProps extends CommonFormFieldProps { + onChangeValue?: (value: string, rawValue: string) => void; + prefix?: string; + getSuggestions?: (value: string) => Array; + format?: (number: string) => string; + e164?: boolean; +} + +const PhoneNumberFieldLite = ({ + disabled, + error, + helperText, + name, + label, + optional, + validate, + onChange, + onChangeValue, + onBlur, + value, + defaultValue, + dataAttributes, + e164, + ...rest +}: PhoneNumberFieldProps): JSX.Element => { + const { + i18n: {phoneNumberFormattingRegionCode}, + } = useTheme(); + + const processValue = (value: string) => { + return e164 ? clean(asE164(value, phoneNumberFormattingRegionCode)) : clean(value); + }; + + const fieldProps = useFieldProps({ + name, + label, + value, + defaultValue, + processValue, + helperText, + optional, + error, + disabled, + onBlur, + validate, + onChange, + onChangeValue, + }); + + return ( + + ); +}; + +export default PhoneNumberFieldLite; diff --git a/src/phone-number-field.tsx b/src/phone-number-field.tsx index 032a5b965d..4082c58217 100644 --- a/src/phone-number-field.tsx +++ b/src/phone-number-field.tsx @@ -20,12 +20,11 @@ type InputProps = Omit, 'value' | 'o defaultValue?: string; onInput?: (event: React.FormEvent) => void; prefix?: string; - e164?: boolean; }; const isValidPrefix = (prefix: string): boolean => !!prefix.match(/^\+\d+$/); -const PhoneInput = ({inputRef, value, defaultValue, onChange, prefix, e164, ...other}: InputProps) => { +const PhoneInput = ({inputRef, value, defaultValue, onChange, prefix, ...other}: InputProps) => { const [selfValue, setSelfValue] = React.useState(defaultValue ?? ''); const ref = React.useRef(null); const {i18n} = useTheme(); From b68f317a1e0da272c227d11bfba8dc41bf448223 Mon Sep 17 00:00:00 2001 From: Marcos Kolodny Date: Tue, 29 Oct 2024 13:38:31 +0100 Subject: [PATCH 2/3] fix(useDisableBodyScroll): avoid affecting body's height (#1279) Issue: [Link](https://jira.tid.es/browse/WEB-2088) --- src/__tests__/hooks-test.tsx | 2 +- src/hooks.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/__tests__/hooks-test.tsx b/src/__tests__/hooks-test.tsx index e588173eee..784bc4468a 100644 --- a/src/__tests__/hooks-test.tsx +++ b/src/__tests__/hooks-test.tsx @@ -11,7 +11,7 @@ const INITIAL_BODY_STYLES = 'background: red;'; const DISABLED_BODY_STYLES = INITIAL_BODY_STYLES + ' ' + - 'overflow: hidden; overflow-y: scroll; position: fixed; top: 0px; left: 0px; right: 0px; bottom: 0px;'; + 'overflow: hidden; overflow-y: scroll; position: fixed; top: 0px; left: 0px; right: 0px;'; const DisableScroll = () => { useDisableBodyScroll(true); diff --git a/src/hooks.tsx b/src/hooks.tsx index a89af8d3f0..9b8293f4f2 100644 --- a/src/hooks.tsx +++ b/src/hooks.tsx @@ -53,7 +53,6 @@ export const useDisableBodyScroll = (disable: boolean): void => { `top: ${-bodyScrollTop}px;`, 'left: 0px;', 'right: 0px;', - 'bottom: 0px;', 'overscroll-behavior-y: contain;', // disable overscroll ].join(''); } From fda424e2874328be37a5566e57d0d3b87518b483 Mon Sep 17 00:00:00 2001 From: Marcos Kolodny Date: Wed, 30 Oct 2024 18:32:27 +0100 Subject: [PATCH 3/3] fix(TextField): adjust position of maxLength's screen reader label (#1283) See comments in [jira's ticket](https://jira.tid.es/browse/OBVIVO-2634) --- src/text-field-base.tsx | 10 +++++++--- src/text-field-components.tsx | 22 ++++++++++++---------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/text-field-base.tsx b/src/text-field-base.tsx index 201de0e7c0..7facace609 100644 --- a/src/text-field-base.tsx +++ b/src/text-field-base.tsx @@ -221,7 +221,8 @@ export const TextFieldBase = React.forwardRef( preventCopy = preventCopy ?? preventCopyInFormFields; const reactId = React.useId(); const id = idProp || reactId; - const helperTextid = React.useId(); + const leftHelperTextid = React.useId(); + const rightHelperTextid = React.useId(); const [inputState, setInputState] = React.useState( defaultValue?.length || value?.length ? 'filled' : 'default' @@ -317,7 +318,8 @@ export const TextFieldBase = React.forwardRef( ( defaultValue, value, ...(error && {'aria-invalid': true}), - ...(helperText && {'aria-describedby': helperTextid}), + ...((helperText || (multiline && maxLength)) && { + 'aria-describedby': `${leftHelperTextid} ${rightHelperTextid}`, + }), ...(preventCopy && { onCopy: preventCopyHandler, onCut: preventCopyHandler, diff --git a/src/text-field-components.tsx b/src/text-field-components.tsx index 4b9146c2ce..bdba1353d4 100644 --- a/src/text-field-components.tsx +++ b/src/text-field-components.tsx @@ -81,16 +81,18 @@ type HelperTextProps = { rightText?: string; rightTextLabel?: string; error?: boolean; - id?: string; + leftTextId?: string; + rightTextId?: string; children?: void; }; export const HelperText = ({ leftText, + leftTextId, rightText, + rightTextId, rightTextLabel, error, - id, }: HelperTextProps): JSX.Element => { const isInverse = useIsInverseOrMediaVariant(); const leftColor = isInverse @@ -112,7 +114,7 @@ export const HelperText = ({ )} - + {leftText}

@@ -122,20 +124,20 @@ export const HelperText = ({ className={classnames(styles.helperText, {[styles.rightHelperText]: !!leftText})} data-testid="endHelperText" > - {rightTextLabel && ( - - {rightTextLabel} - - )} - {rightText} + {rightTextLabel && ( + + {rightTextLabel} + + )} + {rightText} )}