diff --git a/projects/demo-integrations/cypress/tests/addons/phone/phone-basic.cy.ts b/projects/demo-integrations/cypress/tests/addons/phone/phone-basic.cy.ts index 8c346c57d..1739901db 100644 --- a/projects/demo-integrations/cypress/tests/addons/phone/phone-basic.cy.ts +++ b/projects/demo-integrations/cypress/tests/addons/phone/phone-basic.cy.ts @@ -275,6 +275,13 @@ describe('Phone', () => { cy.get('@input').type('447488269'); cy.get('@input').should('have.value', '+375 44 748-82-69'); }); + + it('TR: +90 539 377-07-43', () => { + openCountry('TR'); + + cy.get('@input').type('5393770743'); + cy.get('@input').should('have.value', '+90 539 377-07-43'); + }); }); }); diff --git a/projects/demo-integrations/cypress/tests/addons/phone/phone-non-strict.cy.ts b/projects/demo-integrations/cypress/tests/addons/phone/phone-non-strict.cy.ts index a0af13a7f..cc4ca6cfa 100644 --- a/projects/demo-integrations/cypress/tests/addons/phone/phone-non-strict.cy.ts +++ b/projects/demo-integrations/cypress/tests/addons/phone/phone-non-strict.cy.ts @@ -173,29 +173,36 @@ describe('Phone', () => { describe('Some countries', () => { it('US: +1 212 343-3355', () => { - openCounrty('US'); + openCountry('US'); cy.get('@input').type('12123433355'); cy.get('@input').should('have.value', '+1 212 343-3355'); }); it('KZ: +7 771 931-1111', () => { - openCounrty('KZ'); + openCountry('KZ'); cy.get('@input').type('77719311111'); cy.get('@input').should('have.value', '+7 771 931-1111'); }); it('BY: +375 44 748-82-69', () => { - openCounrty('BY'); + openCountry('BY'); cy.get('@input').type('375447488269'); cy.get('@input').should('have.value', '+375 44 748-82-69'); }); + + it('TR: +90 539 377-07-43', () => { + openCountry('TR'); + + cy.get('@input').type('905393770743'); + cy.get('@input').should('have.value', '+90 539 377-07-43'); + }); }); }); -function openCounrty(code: string): void { +function openCountry(code: string): void { cy.visit(`/${DemoPath.PhonePackage}/API?strict=false&countryCode=${code}`); cy.get('#demo-content input').should('be.visible').first().focus().as('input'); } diff --git a/projects/demo/src/pages/phone/examples/3-non-strict/component.ts b/projects/demo/src/pages/phone/examples/3-non-strict/component.ts index 08c408856..fd472099b 100644 --- a/projects/demo/src/pages/phone/examples/3-non-strict/component.ts +++ b/projects/demo/src/pages/phone/examples/3-non-strict/component.ts @@ -1,5 +1,6 @@ -import {ChangeDetectionStrategy, Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject} from '@angular/core'; import {maskitoGetCountryFromNumber} from '@maskito/phone'; +import {TUI_IS_APPLE} from '@taiga-ui/cdk'; import metadata from 'libphonenumber-js/min/metadata'; import mask from './mask'; @@ -17,6 +18,7 @@ import mask from './mask'; autocomplete="tel" inputmode="tel" tuiTextfield + [attr.pattern]="pattern" [maskito]="mask" /> @@ -32,4 +34,10 @@ export class PhoneMaskDocExample3 { get countryIsoCode(): string { return maskitoGetCountryFromNumber(this.value, metadata) || ''; } + + constructor(@Inject(TUI_IS_APPLE) private readonly isApple: boolean) {} + + get pattern(): string { + return this.isApple ? '+{1}[0-9]{1,3} [0-9]{1,14}' : ''; + } } diff --git a/projects/demo/src/pages/phone/phone-doc.component.ts b/projects/demo/src/pages/phone/phone-doc.component.ts index 9fe079afd..8e8216913 100644 --- a/projects/demo/src/pages/phone/phone-doc.component.ts +++ b/projects/demo/src/pages/phone/phone-doc.component.ts @@ -1,8 +1,9 @@ -import {ChangeDetectionStrategy, Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component, Inject} from '@angular/core'; import {FormControl} from '@angular/forms'; import {DocExamplePrimaryTab} from '@demo/constants'; import {maskitoPhoneOptionsGenerator} from '@maskito/phone'; import {TuiDocExample} from '@taiga-ui/addon-doc'; +import {TUI_IS_APPLE} from '@taiga-ui/cdk'; import {CountryCode, getCountries} from 'libphonenumber-js/core'; import metadata from 'libphonenumber-js/min/metadata'; @@ -55,6 +56,12 @@ export class PhoneDocComponent implements GeneratorOptions { maskitoOptions = maskitoPhoneOptionsGenerator(this); + constructor(@Inject(TUI_IS_APPLE) private readonly isApple: boolean) {} + + get pattern(): string { + return this.isApple ? '+{1}[0-9]{1,3} [0-9]{1,14}' : ''; + } + updateOptions(): void { this.maskitoOptions = maskitoPhoneOptionsGenerator(this); } diff --git a/projects/demo/src/pages/phone/phone-doc.template.html b/projects/demo/src/pages/phone/phone-doc.template.html index 86f9ae155..50a71e600 100644 --- a/projects/demo/src/pages/phone/phone-doc.template.html +++ b/projects/demo/src/pages/phone/phone-doc.template.html @@ -90,6 +90,7 @@ diff --git a/projects/phone/src/lib/masks/phone/phone-mask-free.ts b/projects/phone/src/lib/masks/phone/phone-mask-free.ts index 6ee64c76c..3873f5fee 100644 --- a/projects/phone/src/lib/masks/phone/phone-mask-free.ts +++ b/projects/phone/src/lib/masks/phone/phone-mask-free.ts @@ -16,11 +16,20 @@ export function maskitoPhoneFreeOptionsGenerator({ }): Required { const formatter = new AsYouType(defaultIsoCode, metadata); const prefix = '+'; + let template = ''; + let prevPhoneLength = 0; return { ...MASKITO_DEFAULT_OPTIONS, mask: ({value}) => { - const template = getPhoneTemplate(formatter, value); + const newTemplate = getPhoneTemplate(formatter, value); + const phoneLength = value.replace(/\D/g, '').length; + + template = + newTemplate.length < template.length && phoneLength > prevPhoneLength + ? template + : newTemplate; + prevPhoneLength = phoneLength; const mask = generatePhoneMask({value, template, prefix}); diff --git a/projects/phone/src/lib/masks/phone/phone-mask-strict.ts b/projects/phone/src/lib/masks/phone/phone-mask-strict.ts index a3eb85030..bfab00375 100644 --- a/projects/phone/src/lib/masks/phone/phone-mask-strict.ts +++ b/projects/phone/src/lib/masks/phone/phone-mask-strict.ts @@ -30,10 +30,20 @@ export function maskitoPhoneStrictOptionsGenerator({ const formatter = new AsYouType(countryIsoCode, metadata); const prefix = `+${code} `; + let template = ''; + let prevPhoneLength = 0; + return { ...MASKITO_DEFAULT_OPTIONS, mask: ({value}) => { - const template = getPhoneTemplate(formatter, value); + const newTemplate = getPhoneTemplate(formatter, value); + const phoneLength = value.replace(/\D/g, '').length; + + template = + newTemplate.length < template.length && phoneLength > prevPhoneLength + ? template + : newTemplate; + prevPhoneLength = phoneLength; return generatePhoneMask({value, template, prefix}); }, diff --git a/projects/phone/src/lib/masks/phone/tests/phone-mask.spec.ts b/projects/phone/src/lib/masks/phone/tests/phone-mask.spec.ts index 5dc33af8a..0d5e70006 100644 --- a/projects/phone/src/lib/masks/phone/tests/phone-mask.spec.ts +++ b/projects/phone/src/lib/masks/phone/tests/phone-mask.spec.ts @@ -32,4 +32,30 @@ describe('Phone (maskitoTransform)', () => { ); }); }); + + describe('non-strict', () => { + let options: MaskitoOptions = MASKITO_DEFAULT_OPTIONS; + + beforeEach(() => { + options = maskitoPhoneOptionsGenerator({ + metadata, + strict: false, + countryIsoCode: 'RU', + }); + }); + + it('full number +7 code', () => { + expect(maskitoTransform('+79202800155', options)).toBe('+7 920 280-01-55'); + }); + + it('full number 8 code', () => { + expect(maskitoTransform('89202800155', options)).toBe('+7 920 280-01-55'); + }); + + it('full number with extra chars', () => { + expect(maskitoTransform('8 (920) 280-01-55', options)).toBe( + '+7 920 280-01-55', + ); + }); + }); }); diff --git a/projects/phone/src/lib/masks/phone/utils/cut-phone-by-valid-length.ts b/projects/phone/src/lib/masks/phone/utils/cut-phone-by-valid-length.ts index 8985d6546..7d01e88b2 100644 --- a/projects/phone/src/lib/masks/phone/utils/cut-phone-by-valid-length.ts +++ b/projects/phone/src/lib/masks/phone/utils/cut-phone-by-valid-length.ts @@ -9,7 +9,7 @@ export function cutPhoneByValidLength({ }): string { const validationResult = validatePhoneNumberLength(phone, metadata); - if (validationResult === 'INVALID_LENGTH' || validationResult === 'TOO_LONG') { + if (validationResult === 'TOO_LONG') { return cutPhoneByValidLength({ phone: phone.slice(0, phone.length - 1), metadata,