diff --git a/CHANGELOG.md b/CHANGELOG.md index e81044af..4891aef3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Changed the rules for France (FRA) so the number field is shown to users. +## [4.25.2] - 2024-09-18 + +### Added +- "...-disabled", "...-empty", "...-focused" and "...-invalid" classNames for the StyleguideInput component. + +## [4.25.1] - 2024-09-17 + +### Added +- Tests to validate if a country should use Number Keyboard (shouldShowNumberKeyboard). + +### Fixed +- Logic to validate if a country should use Number Keyboard (shouldShowNumberKeyboard). + ## [4.25.0] - 2024-09-13 ### Fixed diff --git a/manifest.json b/manifest.json index ce62ac44..b006bbc5 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "name": "address-form", "vendor": "vtex", - "version": "4.25.0", + "version": "4.25.2", "title": "address-form React component", "description": "address-form React component", "defaultLocale": "en", diff --git a/react/PostalCodeGetter.js b/react/PostalCodeGetter.js index f1e5d2be..ceae6563 100644 --- a/react/PostalCodeGetter.js +++ b/react/PostalCodeGetter.js @@ -15,7 +15,7 @@ import { injectAddressContext, addressContextPropTypes, } from './addressContainerContext' -import { removeNonWords } from './transforms/utils' +import { shouldShowNumberKeyboard as determineShouldShowNumberKeyboard } from './transforms/shouldShowNumberKeyboard' class PostalCodeGetter extends Component { render() { @@ -89,12 +89,8 @@ class PostalCodeGetter extends Component { default: case POSTAL_CODE: { const field = getField('postalCode', rules) - const numericString = field.mask ? removeNonWords(field.mask) : '' - const isPurelyNumeric = - numericString === '' || /^\d+$/.test(numericString) - const shouldShowNumberKeyboard = isNaN(field.mask) - ? isPurelyNumeric - : false + const mask = field?.mask + const shouldShowNumberKeyboard = determineShouldShowNumberKeyboard(mask) return ( { - this.setState({ showErrorMessage: false }) + this.setState({ showErrorMessage: false, isFocused: true }) } handleSubmit = (event) => { @@ -60,7 +61,7 @@ class StyleguideInput extends Component { } handleBlur = (event) => { - this.setState({ showErrorMessage: true }) + this.setState({ showErrorMessage: true, isFocused: false }) this.props.onBlur && this.props.onBlur(event) } @@ -82,6 +83,8 @@ class StyleguideInput extends Component { const disabled = !!address[field.name].disabled + const valid = address[field.name].valid === false ? false : true + const loading = loadingProp != null ? loadingProp : address[field.name].loading @@ -137,6 +140,14 @@ class StyleguideInput extends Component { field.name } vtex-address-form__field--${field.size || 'xlarge'} ${ field.hidden ? 'dn' : '' + } ${ + disabled ? 'vtex-address-form__field-disabled' : '' + } ${ + !valid ? 'vtex-address-form__field-invalid' : '' + } ${ + !address[field.name].value ? 'vtex-address-form__field-empty' : '' + } ${ + this.state.isFocused ? 'vtex-address-form__field-focused' : '' }` if (field.name === 'postalCode') { diff --git a/react/package.json b/react/package.json index c825cea1..0c890f02 100644 --- a/react/package.json +++ b/react/package.json @@ -1,6 +1,6 @@ { "name": "@vtex/address-form", - "version": "4.25.0", + "version": "4.25.2", "description": "address-form React component", "main": "lib/index.js", "files": [ diff --git a/react/transforms/shouldShowNumberKeyboard.js b/react/transforms/shouldShowNumberKeyboard.js new file mode 100644 index 00000000..723b7c6a --- /dev/null +++ b/react/transforms/shouldShowNumberKeyboard.js @@ -0,0 +1,30 @@ +/** + * Removes non-numeric characters from a string, keeping only digits, spaces, and dashes. + * @param {string} string + * @returns {string} + */ +function removeNonWords(string) { + return (string || '').replace(/[^\d\s-]/g, '') +} + +/** + * Determines whether to show the number keyboard based on the input mask. + * @param {string|number|null|undefined|NaN} [mask] + * @returns {boolean} + */ +export function shouldShowNumberKeyboard(mask) { + if (mask === undefined || mask === null || mask === '') { + return true + } + + if (Number.isNaN(mask)) { + return false + } + + const maskString = typeof mask === 'number' ? mask.toString() : mask + + const numericString = removeNonWords(maskString) + const isPurelyNumeric = /^[\d\s-]+$/.test(numericString) + + return isPurelyNumeric && !/[a-zA-Z]/.test(maskString) +} diff --git a/react/transforms/shouldShowNumberKeyboard.test.js b/react/transforms/shouldShowNumberKeyboard.test.js new file mode 100644 index 00000000..7112199a --- /dev/null +++ b/react/transforms/shouldShowNumberKeyboard.test.js @@ -0,0 +1,43 @@ +import { shouldShowNumberKeyboard } from './shouldShowNumberKeyboard' + +describe('shouldShowNumberKeyboard', () => { + test('Should return true for mask rule undefined', () => { + expect(shouldShowNumberKeyboard(undefined)).toBe(true) + }) + + test('Should return true for mask rule null', () => { + expect(shouldShowNumberKeyboard(null)).toBe(true) + }) + + test('Should return true for mask rule empty string', () => { + expect(shouldShowNumberKeyboard('')).toBe(true) + }) + + test('Should return true for mask rule numeric string without separators', () => { + expect(shouldShowNumberKeyboard('9999')).toBe(true) + }) + + test('Should return true for mask rule numeric string with spaces', () => { + expect(shouldShowNumberKeyboard('999 99')).toBe(true) + }) + + test('Should return true for mask rule numeric string with dashes', () => { + expect(shouldShowNumberKeyboard('9999-99')).toBe(true) + }) + + test('Should return false for mask rulee for string with letters', () => { + expect(shouldShowNumberKeyboard('999AA')).toBe(false) + }) + + test('Should return false for mask rulee for string with mixed letters and spaces', () => { + expect(shouldShowNumberKeyboard('999 AA')).toBe(false) + }) + + test('Should return false for mask rulee for mixed numeric and letter string with dashes', () => { + expect(shouldShowNumberKeyboard('9AA9-99')).toBe(false) + }) + + test('Should return false for mask rulee for NaN', () => { + expect(shouldShowNumberKeyboard(NaN)).toBe(false) + }) +}) diff --git a/react/transforms/utils.js b/react/transforms/utils.js deleted file mode 100644 index 1fb2b0f8..00000000 --- a/react/transforms/utils.js +++ /dev/null @@ -1,3 +0,0 @@ -export function removeNonWords(string) { - return string && string.replace(/\W/g, '') -}