From 2dd960fb147f9510ff6b583209797e82bc37e677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B5=D0=BD=D0=B8=D1=81=20=D0=91=D1=83=D0=BB=D0=B0?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2?= Date: Thu, 15 Aug 2024 00:41:45 +0300 Subject: [PATCH] feat(kit): added search function in international phone component --- projects/core/tokens/common-icons.ts | 2 + .../examples/2/index.html | 1 + projects/i18n/languages/belarusian/kit.ts | 1 + projects/i18n/languages/chinese/kit.ts | 1 + projects/i18n/languages/dutch/kit.ts | 1 + projects/i18n/languages/english/kit.ts | 1 + projects/i18n/languages/french/kit.ts | 1 + projects/i18n/languages/german/kit.ts | 1 + projects/i18n/languages/hebrew/kit.ts | 1 + projects/i18n/languages/italian/kit.ts | 1 + projects/i18n/languages/japan/kit.ts | 1 + projects/i18n/languages/kazakh/kit.ts | 1 + projects/i18n/languages/korean/kit.ts | 1 + projects/i18n/languages/lithuanian/kit.ts | 1 + projects/i18n/languages/malay/kit.ts | 1 + projects/i18n/languages/polish/kit.ts | 1 + projects/i18n/languages/portuguese/kit.ts | 1 + projects/i18n/languages/russian/kit.ts | 1 + projects/i18n/languages/spanish/kit.ts | 1 + projects/i18n/languages/turkish/kit.ts | 1 + projects/i18n/languages/ukrainian/kit.ts | 1 + projects/i18n/languages/vietnamese/kit.ts | 1 + projects/i18n/types/language.ts | 1 + .../get-country-calling-code.pipe.ts | 21 -------- .../input-phone-international.component.ts | 43 +++++++++++++--- .../input-phone-international.style.less | 8 +++ .../input-phone-international.template.html | 49 +++++++++++++------ projects/kit/tokens/i18n.ts | 4 ++ projects/kit/utils/index.ts | 1 + projects/kit/utils/phone.ts | 11 +++++ 30 files changed, 118 insertions(+), 43 deletions(-) delete mode 100644 projects/kit/components/input-phone-international/get-country-calling-code.pipe.ts create mode 100644 projects/kit/utils/phone.ts diff --git a/projects/core/tokens/common-icons.ts b/projects/core/tokens/common-icons.ts index 0000aa8155725..3ef3f6a349598 100644 --- a/projects/core/tokens/common-icons.ts +++ b/projects/core/tokens/common-icons.ts @@ -6,6 +6,7 @@ const COMMON_ICONS: TuiCommonIcons = { close: '@tui.x', error: '@tui.circle-alert', more: '@tui.chevron-right', + search: '@tui.search', }; export interface TuiCommonIcons { @@ -13,6 +14,7 @@ export interface TuiCommonIcons { readonly close: string; readonly error: string; readonly more: string; + readonly search: string; } export const TUI_COMMON_ICONS = tuiCreateToken(COMMON_ICONS); diff --git a/projects/demo/src/modules/components/input-phone-international/examples/2/index.html b/projects/demo/src/modules/components/input-phone-international/examples/2/index.html index 4d3f099ad6793..af29a71087503 100644 --- a/projects/demo/src/modules/components/input-phone-international/examples/2/index.html +++ b/projects/demo/src/modules/components/input-phone-international/examples/2/index.html @@ -1,5 +1,6 @@ diff --git a/projects/i18n/languages/belarusian/kit.ts b/projects/i18n/languages/belarusian/kit.ts index 1195fefe1e433..90167be086104 100644 --- a/projects/i18n/languages/belarusian/kit.ts +++ b/projects/i18n/languages/belarusian/kit.ts @@ -69,4 +69,5 @@ export const TUI_BELARUSIAN_LANGUAGE_KIT: TuiLanguageKit = { zoomOut: 'Паменшыць', reset: 'Скінуць маштаб', }, + phoneSearch: 'Увядзіце краіну або код', }; diff --git a/projects/i18n/languages/chinese/kit.ts b/projects/i18n/languages/chinese/kit.ts index 0f2d4e6059b8a..1e53143445a32 100644 --- a/projects/i18n/languages/chinese/kit.ts +++ b/projects/i18n/languages/chinese/kit.ts @@ -69,4 +69,5 @@ export const TUI_CHINESE_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: '放大', reset: '重置', }, + phoneSearch: '輸入國家或代碼', }; diff --git a/projects/i18n/languages/dutch/kit.ts b/projects/i18n/languages/dutch/kit.ts index 12552918f09ab..5a744304b0cad 100644 --- a/projects/i18n/languages/dutch/kit.ts +++ b/projects/i18n/languages/dutch/kit.ts @@ -69,4 +69,5 @@ export const TUI_DUTCH_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'Inzoomen', reset: 'Opnieuw instellen', }, + phoneSearch: 'Indtast land eller kode', }; diff --git a/projects/i18n/languages/english/kit.ts b/projects/i18n/languages/english/kit.ts index eaaeda6aaa89b..db65f7d77dda1 100644 --- a/projects/i18n/languages/english/kit.ts +++ b/projects/i18n/languages/english/kit.ts @@ -69,4 +69,5 @@ export const TUI_ENGLISH_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'Zoom in', reset: 'Reset', }, + phoneSearch: 'Type country or code', }; diff --git a/projects/i18n/languages/french/kit.ts b/projects/i18n/languages/french/kit.ts index 8cd7a94e7da3f..1c5539ef3e790 100644 --- a/projects/i18n/languages/french/kit.ts +++ b/projects/i18n/languages/french/kit.ts @@ -73,4 +73,5 @@ export const TUI_FRENCH_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'Dézoomer', reset: 'Réinitialiser', }, + phoneSearch: 'Tapez le pays ou le code', }; diff --git a/projects/i18n/languages/german/kit.ts b/projects/i18n/languages/german/kit.ts index e407cde991e83..389a6b08fad29 100644 --- a/projects/i18n/languages/german/kit.ts +++ b/projects/i18n/languages/german/kit.ts @@ -70,4 +70,5 @@ export const TUI_GERMAN_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'Vergrößern', reset: 'Zurücksetzen', }, + phoneSearch: 'Geben Sie das Land oder den Code ein', }; diff --git a/projects/i18n/languages/hebrew/kit.ts b/projects/i18n/languages/hebrew/kit.ts index b6ba435f23037..defcbe0ee306b 100644 --- a/projects/i18n/languages/hebrew/kit.ts +++ b/projects/i18n/languages/hebrew/kit.ts @@ -69,4 +69,5 @@ export const TUI_HEBREW_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'לְהִתְמַקֵד', reset: 'אִתחוּל', }, + phoneSearch: 'הקלד מדינה או קוד', }; diff --git a/projects/i18n/languages/italian/kit.ts b/projects/i18n/languages/italian/kit.ts index 3d4867fe282e7..3722e59de6874 100644 --- a/projects/i18n/languages/italian/kit.ts +++ b/projects/i18n/languages/italian/kit.ts @@ -69,4 +69,5 @@ export const TUI_ITALIAN_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'Ingrandisci', reset: 'Ripristina', }, + phoneSearch: 'Digitare il paese o il codice', }; diff --git a/projects/i18n/languages/japan/kit.ts b/projects/i18n/languages/japan/kit.ts index 7854ae092d745..0d74ec7be9642 100644 --- a/projects/i18n/languages/japan/kit.ts +++ b/projects/i18n/languages/japan/kit.ts @@ -69,4 +69,5 @@ export const TUI_JAPAN_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'ズームイン', reset: 'リセット', }, + phoneSearch: '国またはコードを入力', }; diff --git a/projects/i18n/languages/kazakh/kit.ts b/projects/i18n/languages/kazakh/kit.ts index 6a75a403f0e12..3730629a6706e 100644 --- a/projects/i18n/languages/kazakh/kit.ts +++ b/projects/i18n/languages/kazakh/kit.ts @@ -69,4 +69,5 @@ export const TUI_KAZAKH_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'Үлкейту', reset: 'Қалпына келтіру', }, + phoneSearch: 'Елді немесе кодты теріңіз', }; diff --git a/projects/i18n/languages/korean/kit.ts b/projects/i18n/languages/korean/kit.ts index 1961af66e5d57..c1bdf8af6e838 100644 --- a/projects/i18n/languages/korean/kit.ts +++ b/projects/i18n/languages/korean/kit.ts @@ -69,4 +69,5 @@ export const TUI_KOREAN_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: '확대하다', reset: '다시 놓기', }, + phoneSearch: '국가 또는 코드를 입력하세요', }; diff --git a/projects/i18n/languages/lithuanian/kit.ts b/projects/i18n/languages/lithuanian/kit.ts index 339adab816944..dc3f789167bf5 100644 --- a/projects/i18n/languages/lithuanian/kit.ts +++ b/projects/i18n/languages/lithuanian/kit.ts @@ -73,4 +73,5 @@ export const TUI_LITHUANIAN_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'Didinti', reset: 'Atstatyti', }, + phoneSearch: 'Ievadiet valsti vai kodu', }; diff --git a/projects/i18n/languages/malay/kit.ts b/projects/i18n/languages/malay/kit.ts index d4dfba033e6dc..e6f7878e553d3 100644 --- a/projects/i18n/languages/malay/kit.ts +++ b/projects/i18n/languages/malay/kit.ts @@ -69,4 +69,5 @@ export const TUI_MALAY_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'Zum masuk', reset: 'Set semula', }, + phoneSearch: 'Taip negara atau kod', }; diff --git a/projects/i18n/languages/polish/kit.ts b/projects/i18n/languages/polish/kit.ts index 996cfc0fab785..6f31b5deac781 100644 --- a/projects/i18n/languages/polish/kit.ts +++ b/projects/i18n/languages/polish/kit.ts @@ -69,4 +69,5 @@ export const TUI_POLISH_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'Zbliżenie', reset: 'Resetowanie', }, + phoneSearch: 'Nuna imaluunniit kode allaguk', }; diff --git a/projects/i18n/languages/portuguese/kit.ts b/projects/i18n/languages/portuguese/kit.ts index 4322a4e34f09e..17c37eae92896 100644 --- a/projects/i18n/languages/portuguese/kit.ts +++ b/projects/i18n/languages/portuguese/kit.ts @@ -69,4 +69,5 @@ export const TUI_PORTUGUESE_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'Mais Zoom', reset: 'Reiniciar', }, + phoneSearch: 'Introduza o país ou código', }; diff --git a/projects/i18n/languages/russian/kit.ts b/projects/i18n/languages/russian/kit.ts index ddbfe8a3e67ed..e01ce78cdbe9d 100644 --- a/projects/i18n/languages/russian/kit.ts +++ b/projects/i18n/languages/russian/kit.ts @@ -69,4 +69,5 @@ export const TUI_RUSSIAN_LANGUAGE_KIT: TuiLanguageKit = { zoomOut: 'Уменьшить масштаб', reset: 'Сбросить масштаб', }, + phoneSearch: 'Введите страну или код', }; diff --git a/projects/i18n/languages/spanish/kit.ts b/projects/i18n/languages/spanish/kit.ts index c49942843ca84..7cb2e4901a8ce 100644 --- a/projects/i18n/languages/spanish/kit.ts +++ b/projects/i18n/languages/spanish/kit.ts @@ -69,4 +69,5 @@ export const TUI_SPANISH_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'Acercarse', reset: 'Reiniciar', }, + phoneSearch: 'Escriba el país o el código', }; diff --git a/projects/i18n/languages/turkish/kit.ts b/projects/i18n/languages/turkish/kit.ts index 4cdc64f25b203..d9c520c27e39d 100644 --- a/projects/i18n/languages/turkish/kit.ts +++ b/projects/i18n/languages/turkish/kit.ts @@ -69,4 +69,5 @@ export const TUI_TURKISH_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'Yakınlaştır', reset: 'Sıfırla', }, + phoneSearch: 'Ülke veya kodu yazın', }; diff --git a/projects/i18n/languages/ukrainian/kit.ts b/projects/i18n/languages/ukrainian/kit.ts index c98b1e138c2f8..dda2afe6cc730 100644 --- a/projects/i18n/languages/ukrainian/kit.ts +++ b/projects/i18n/languages/ukrainian/kit.ts @@ -69,4 +69,5 @@ export const TUI_UKRAINIAN_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'Збільшувати', reset: 'Скинути', }, + phoneSearch: 'Введіть країну або код', }; diff --git a/projects/i18n/languages/vietnamese/kit.ts b/projects/i18n/languages/vietnamese/kit.ts index 7a984df786215..a0c1eadaa7f50 100644 --- a/projects/i18n/languages/vietnamese/kit.ts +++ b/projects/i18n/languages/vietnamese/kit.ts @@ -69,4 +69,5 @@ export const TUI_VIETNAMESE_LANGUAGE_KIT: TuiLanguageKit = { zoomIn: 'Phóng to', reset: 'Đặt lại', }, + phoneSearch: 'Nhập quốc gia hoặc mã', }; diff --git a/projects/i18n/types/language.ts b/projects/i18n/types/language.ts index f3651b241f8c2..f227ae5328a6f 100644 --- a/projects/i18n/types/language.ts +++ b/projects/i18n/types/language.ts @@ -109,6 +109,7 @@ export interface TuiLanguageKit { zoomOut: string; reset: string; }; + phoneSearch: string; } export interface TuiLanguageCommerce { diff --git a/projects/kit/components/input-phone-international/get-country-calling-code.pipe.ts b/projects/kit/components/input-phone-international/get-country-calling-code.pipe.ts deleted file mode 100644 index b2dc67923f486..0000000000000 --- a/projects/kit/components/input-phone-international/get-country-calling-code.pipe.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type {PipeTransform} from '@angular/core'; -import {Pipe} from '@angular/core'; -import {CHAR_PLUS} from '@taiga-ui/cdk/constants'; -import type {TuiCountryIsoCode} from '@taiga-ui/i18n/types'; -import type {MetadataJson} from 'libphonenumber-js/core'; -import {getCountryCallingCode} from 'libphonenumber-js/core'; - -@Pipe({ - standalone: true, - name: 'tuiGetCountryCallingCode', -}) -export class TuiGetCountryCallingCodePipe implements PipeTransform { - public transform( - countryIsoCode: TuiCountryIsoCode, - metadata?: MetadataJson | null, - ): string { - return metadata - ? CHAR_PLUS + getCountryCallingCode(countryIsoCode, metadata) - : ''; - } -} diff --git a/projects/kit/components/input-phone-international/input-phone-international.component.ts b/projects/kit/components/input-phone-international/input-phone-international.component.ts index bc4696a77ea6e..860180cfe535f 100644 --- a/projects/kit/components/input-phone-international/input-phone-international.component.ts +++ b/projects/kit/components/input-phone-international/input-phone-international.component.ts @@ -1,4 +1,5 @@ -import {CommonModule} from '@angular/common'; +import {AsyncPipe, CommonModule} from '@angular/common'; +import type {QueryList} from '@angular/core'; import { ChangeDetectionStrategy, Component, @@ -11,6 +12,7 @@ import { signal, TemplateRef, ViewChild, + ViewChildren, } from '@angular/core'; import {toObservable, toSignal} from '@angular/core/rxjs-interop'; import {FormsModule} from '@angular/forms'; @@ -20,11 +22,12 @@ import {maskitoInitialCalibrationPlugin, maskitoTransform} from '@maskito/core'; import {maskitoRemoveOnBlurPlugin} from '@maskito/kit'; import {maskitoGetCountryFromNumber, maskitoPhoneOptionsGenerator} from '@maskito/phone'; import {tuiAsControl, TuiControl} from '@taiga-ui/cdk/classes'; -import {CHAR_PLUS} from '@taiga-ui/cdk/constants'; +import {CHAR_PLUS, TUI_DEFAULT_MATCHER} from '@taiga-ui/cdk/constants'; +import {TuiAutoFocus} from '@taiga-ui/cdk/directives/auto-focus'; import {tuiFallbackValueProvider} from '@taiga-ui/cdk/tokens'; import {tuiIsInputEvent} from '@taiga-ui/cdk/utils/dom'; import {tuiDirectiveBinding} from '@taiga-ui/cdk/utils/miscellaneous'; -import {TuiDataList} from '@taiga-ui/core/components/data-list'; +import {TuiDataList, TuiOption} from '@taiga-ui/core/components/data-list'; import { TUI_TEXTFIELD_OPTIONS, TuiTextfield, @@ -42,16 +45,18 @@ import { } from '@taiga-ui/core/directives/dropdown'; import {TuiGroup} from '@taiga-ui/core/directives/group'; import {TuiFlagPipe} from '@taiga-ui/core/pipes/flag'; +import {TUI_COMMON_ICONS} from '@taiga-ui/core/tokens'; import type {TuiCountryIsoCode} from '@taiga-ui/i18n/types'; import {TuiChevron} from '@taiga-ui/kit/directives'; -import {TUI_COUNTRIES} from '@taiga-ui/kit/tokens'; +import {TUI_COUNTRIES, TUI_INTERNATIONAL_SEARCH} from '@taiga-ui/kit/tokens'; +import {tuiGetCallingCode} from '@taiga-ui/kit/utils'; +import {TuiInputModule} from '@taiga-ui/legacy/components/input'; import type {PolymorpheusContent} from '@taiga-ui/polymorpheus'; import {validatePhoneNumberLength} from 'libphonenumber-js'; import type {MetadataJson} from 'libphonenumber-js/core'; import {getCountryCallingCode} from 'libphonenumber-js/core'; import {from, skip} from 'rxjs'; -import {TuiGetCountryCallingCodePipe} from './get-country-calling-code.pipe'; import {TUI_INPUT_PHONE_INTERNATIONAL_OPTIONS} from './input-phone-international.options'; const NOT_FORM_CONTROL_SYMBOLS = /[^+\d]/g; @@ -60,15 +65,17 @@ const NOT_FORM_CONTROL_SYMBOLS = /[^+\d]/g; standalone: true, selector: 'tui-input-phone-international', imports: [ + AsyncPipe, CommonModule, FormsModule, MaskitoDirective, + TuiAutoFocus, TuiChevron, TuiDataList, TuiDropdown, TuiFlagPipe, - TuiGetCountryCallingCodePipe, TuiGroup, + TuiInputModule, TuiTextfield, ], templateUrl: './input-phone-international.template.html', @@ -92,6 +99,9 @@ export class TuiInputPhoneInternational extends TuiControl { @ViewChild(MaskitoDirective, {read: ElementRef}) private readonly input?: ElementRef; + @ViewChildren(TuiOption, {read: ElementRef}) + private readonly listOptions?: QueryList>; + protected readonly dropdown = tuiDropdown(null); protected readonly options = inject(TUI_INPUT_PHONE_INTERNATIONAL_OPTIONS); protected readonly size = inject(TUI_TEXTFIELD_OPTIONS).size; @@ -99,6 +109,20 @@ export class TuiInputPhoneInternational extends TuiControl { protected readonly names = toSignal(inject(TUI_COUNTRIES)); protected readonly metadata = toSignal(from(this.options.metadata)); protected readonly countryIsoCode = signal(this.options.countryIsoCode); + protected readonly icons = inject(TUI_COMMON_ICONS); + protected readonly internationalSearchLabel$ = inject(TUI_INTERNATIONAL_SEARCH); + protected readonly search = signal(''); + + protected readonly filtered = computed(() => + this.countries + .map((iso) => ({ + iso, + name: this.names()?.[iso] || '', + code: tuiGetCallingCode(iso, this.metadata()), + })) + .filter(({name, code}) => TUI_DEFAULT_MATCHER(name + code, this.search())), + ); + protected readonly mask = computed(() => this.computeMask(this.countryIsoCode(), this.metadata()), ); @@ -114,6 +138,9 @@ export class TuiInputPhoneInternational extends TuiControl { @Input() public countries = this.options.countries; + @Input() + public countrySearch = false; + @Output() public readonly countryIsoCodeChange = toObservable(this.countryIsoCode).pipe( skip(1), @@ -124,6 +151,10 @@ export class TuiInputPhoneInternational extends TuiControl { this.countryIsoCode.set(code); } + public focusFirstItem(): void { + this.listOptions?.get(0)?.nativeElement.focus(); + } + public onPaste(event: Event): void { const phonesMetadata = this.metadata(); diff --git a/projects/kit/components/input-phone-international/input-phone-international.style.less b/projects/kit/components/input-phone-international/input-phone-international.style.less index 6e48ef1a7389c..8eaf31d7786e7 100644 --- a/projects/kit/components/input-phone-international/input-phone-international.style.less +++ b/projects/kit/components/input-phone-international/input-phone-international.style.less @@ -27,3 +27,11 @@ color: var(--tui-text-secondary); margin-inline-end: 0.25rem; } + +.t-search { + position: sticky; + top: 0.25rem; + background: var(--tui-background-elevation-2); + box-shadow: 0 -1rem var(--tui-background-elevation-2); + margin: 0.25rem; +} diff --git a/projects/kit/components/input-phone-international/input-phone-international.template.html b/projects/kit/components/input-phone-international/input-phone-international.template.html index 22b74b61440dc..2a86f63ee8ca8 100644 --- a/projects/kit/components/input-phone-international/input-phone-international.template.html +++ b/projects/kit/components/input-phone-international/input-phone-international.template.html @@ -53,21 +53,38 @@ - - - + + + + + + diff --git a/projects/kit/tokens/i18n.ts b/projects/kit/tokens/i18n.ts index e80276bf5a980..706111e03818b 100644 --- a/projects/kit/tokens/i18n.ts +++ b/projects/kit/tokens/i18n.ts @@ -73,3 +73,7 @@ export const TUI_PREVIEW_TEXTS = tuiCreateTokenFromFactory( export const TUI_PREVIEW_ZOOM_TEXTS = tuiCreateTokenFromFactory( tuiExtractI18n('zoomTexts'), ); + +export const TUI_INTERNATIONAL_SEARCH = tuiCreateTokenFromFactory( + tuiExtractI18n('phoneSearch'), +); diff --git a/projects/kit/utils/index.ts b/projects/kit/utils/index.ts index 736196af15c73..bbab4d30a7984 100644 --- a/projects/kit/utils/index.ts +++ b/projects/kit/utils/index.ts @@ -1,4 +1,5 @@ export * from './create-time-periods'; export * from './is-flat'; export * from './maskito.binding'; +export * from './phone'; export * from './toggle-day'; diff --git a/projects/kit/utils/phone.ts b/projects/kit/utils/phone.ts new file mode 100644 index 0000000000000..1aca170d7e8ec --- /dev/null +++ b/projects/kit/utils/phone.ts @@ -0,0 +1,11 @@ +import {CHAR_PLUS} from '@taiga-ui/cdk/constants'; +import type {TuiCountryIsoCode} from '@taiga-ui/i18n/types/country-iso-code'; +import type {MetadataJson} from 'libphonenumber-js/core'; +import {getCountryCallingCode} from 'libphonenumber-js/core'; + +export function tuiGetCallingCode( + iso: TuiCountryIsoCode, + metadata?: MetadataJson | null, +): string { + return metadata ? CHAR_PLUS + getCountryCallingCode(iso, metadata) : ''; +}