Skip to content

Commit

Permalink
feat(kit): added search function in international phone component
Browse files Browse the repository at this point in the history
  • Loading branch information
Денис Буланов authored and splincode committed Oct 4, 2024
1 parent 2c9a668 commit 2dd960f
Show file tree
Hide file tree
Showing 30 changed files with 118 additions and 43 deletions.
2 changes: 2 additions & 0 deletions projects/core/tokens/common-icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ const COMMON_ICONS: TuiCommonIcons = {
close: '@tui.x',
error: '@tui.circle-alert',
more: '@tui.chevron-right',
search: '@tui.search',
};

export interface TuiCommonIcons {
readonly check: string;
readonly close: string;
readonly error: string;
readonly more: string;
readonly search: string;
}

export const TUI_COMMON_ICONS = tuiCreateToken(COMMON_ICONS);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<tui-input-phone-international
[countries]="(countries | tuiSortCountries | async) || []"
[countrySearch]="true"
[(countryIsoCode)]="countryIsoCode"
[(ngModel)]="value"
>
Expand Down
1 change: 1 addition & 0 deletions projects/i18n/languages/belarusian/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_BELARUSIAN_LANGUAGE_KIT: TuiLanguageKit = {
zoomOut: 'Паменшыць',
reset: 'Скінуць маштаб',
},
phoneSearch: 'Увядзіце краіну або код',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/chinese/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_CHINESE_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: '放大',
reset: '重置',
},
phoneSearch: '輸入國家或代碼',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/dutch/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_DUTCH_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: 'Inzoomen',
reset: 'Opnieuw instellen',
},
phoneSearch: 'Indtast land eller kode',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/english/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_ENGLISH_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: 'Zoom in',
reset: 'Reset',
},
phoneSearch: 'Type country or code',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/french/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,5 @@ export const TUI_FRENCH_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: 'Dézoomer',
reset: 'Réinitialiser',
},
phoneSearch: 'Tapez le pays ou le code',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/german/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/hebrew/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_HEBREW_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: 'לְהִתְמַקֵד',
reset: 'אִתחוּל',
},
phoneSearch: 'הקלד מדינה או קוד',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/italian/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_ITALIAN_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: 'Ingrandisci',
reset: 'Ripristina',
},
phoneSearch: 'Digitare il paese o il codice',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/japan/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_JAPAN_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: 'ズームイン',
reset: 'リセット',
},
phoneSearch: '国またはコードを入力',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/kazakh/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_KAZAKH_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: 'Үлкейту',
reset: 'Қалпына келтіру',
},
phoneSearch: 'Елді немесе кодты теріңіз',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/korean/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_KOREAN_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: '확대하다',
reset: '다시 놓기',
},
phoneSearch: '국가 또는 코드를 입력하세요',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/lithuanian/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,5 @@ export const TUI_LITHUANIAN_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: 'Didinti',
reset: 'Atstatyti',
},
phoneSearch: 'Ievadiet valsti vai kodu',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/malay/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_MALAY_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: 'Zum masuk',
reset: 'Set semula',
},
phoneSearch: 'Taip negara atau kod',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/polish/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_POLISH_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: 'Zbliżenie',
reset: 'Resetowanie',
},
phoneSearch: 'Nuna imaluunniit kode allaguk',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/portuguese/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_PORTUGUESE_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: 'Mais Zoom',
reset: 'Reiniciar',
},
phoneSearch: 'Introduza o país ou código',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/russian/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_RUSSIAN_LANGUAGE_KIT: TuiLanguageKit = {
zoomOut: 'Уменьшить масштаб',
reset: 'Сбросить масштаб',
},
phoneSearch: 'Введите страну или код',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/spanish/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_SPANISH_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: 'Acercarse',
reset: 'Reiniciar',
},
phoneSearch: 'Escriba el país o el código',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/turkish/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/ukrainian/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ export const TUI_UKRAINIAN_LANGUAGE_KIT: TuiLanguageKit = {
zoomIn: 'Збільшувати',
reset: 'Скинути',
},
phoneSearch: 'Введіть країну або код',
};
1 change: 1 addition & 0 deletions projects/i18n/languages/vietnamese/kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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ã',
};
1 change: 1 addition & 0 deletions projects/i18n/types/language.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export interface TuiLanguageKit {
zoomOut: string;
reset: string;
};
phoneSearch: string;
}

export interface TuiLanguageCommerce {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {CommonModule} from '@angular/common';
import {AsyncPipe, CommonModule} from '@angular/common';
import type {QueryList} from '@angular/core';
import {
ChangeDetectionStrategy,
Component,
Expand All @@ -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';
Expand All @@ -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,
Expand All @@ -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;
Expand All @@ -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',
Expand All @@ -92,13 +99,30 @@ export class TuiInputPhoneInternational extends TuiControl<string> {
@ViewChild(MaskitoDirective, {read: ElementRef})
private readonly input?: ElementRef<HTMLInputElement>;

@ViewChildren(TuiOption, {read: ElementRef})
private readonly listOptions?: QueryList<ElementRef<HTMLButtonElement>>;

protected readonly dropdown = tuiDropdown(null);
protected readonly options = inject(TUI_INPUT_PHONE_INTERNATIONAL_OPTIONS);
protected readonly size = inject(TUI_TEXTFIELD_OPTIONS).size;
protected readonly open = tuiDropdownOpen();
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<string>('');

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()),
);
Expand All @@ -114,6 +138,9 @@ export class TuiInputPhoneInternational extends TuiControl<string> {
@Input()
public countries = this.options.countries;

@Input()
public countrySearch = false;

@Output()
public readonly countryIsoCodeChange = toObservable(this.countryIsoCode).pipe(
skip(1),
Expand All @@ -124,6 +151,10 @@ export class TuiInputPhoneInternational extends TuiControl<string> {
this.countryIsoCode.set(code);
}

public focusFirstItem(): void {
this.listOptions?.get(0)?.nativeElement.focus();
}

public onPaste(event: Event): void {
const phonesMetadata = this.metadata();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,38 @@
</label>
</tui-textfield>

<tui-data-list *tuiTextfieldDropdown>
<button
*ngFor="let item of countries"
tuiOption
type="button"
(click)="onItemClick(item)"
<ng-container *tuiTextfieldDropdown>
<tui-textfield
*ngIf="countrySearch"
class="t-search"
[iconStart]="icons.search"
>
<img
alt=""
class="t-flag"
[src]="item | tuiFlag"
<label tuiLabel>{{ internationalSearchLabel$ | async }}</label>
<input
tuiAutoFocus
tuiTextfield
[ngModel]="search()"
(keydown.arrowDown)="focusFirstItem()"
(ngModelChange)="search.set($event)"
/>
<span class="t-name">{{ names()?.[item] }}</span>
<span class="t-code">
{{ item | tuiGetCountryCallingCode: metadata() }}
</span>
</button>
</tui-data-list>
</tui-textfield>

<tui-data-list>
<button
*ngFor="let item of filtered()"
tuiOption
type="button"
(click)="onItemClick(item.isoCode)"
>
<img
alt=""
class="t-flag"
[src]="item.iso | tuiFlag"
/>
<span class="t-name">{{ item.name }}</span>
<span class="t-code">
{{ item.code | tuiGetCountryCallingCode: metadata() }}
</span>
</button>
</tui-data-list>
</ng-container>
4 changes: 4 additions & 0 deletions projects/kit/tokens/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
);
1 change: 1 addition & 0 deletions projects/kit/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './create-time-periods';
export * from './is-flat';
export * from './maskito.binding';
export * from './phone';
export * from './toggle-day';
11 changes: 11 additions & 0 deletions projects/kit/utils/phone.ts
Original file line number Diff line number Diff line change
@@ -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) : '';
}

0 comments on commit 2dd960f

Please sign in to comment.