@ngstarter-ui/components 21.0.31 → 21.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ai/component-registry.json +9 -4
- package/fesm2022/ngstarter-ui-components-country-select.mjs +65 -4
- package/fesm2022/ngstarter-ui-components-country-select.mjs.map +1 -1
- package/fesm2022/ngstarter-ui-components-currency-select.mjs +65 -4
- package/fesm2022/ngstarter-ui-components-currency-select.mjs.map +1 -1
- package/fesm2022/ngstarter-ui-components-menu.mjs +10 -6
- package/fesm2022/ngstarter-ui-components-menu.mjs.map +1 -1
- package/fesm2022/ngstarter-ui-components-phone-input.mjs +113 -29
- package/fesm2022/ngstarter-ui-components-phone-input.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ngstarter-ui-components-country-select.d.ts +12 -0
- package/types/ngstarter-ui-components-currency-select.d.ts +12 -0
- package/types/ngstarter-ui-components-menu.d.ts +3 -3
- package/types/ngstarter-ui-components-phone-input.d.ts +19 -2
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { FocusMonitor } from '@angular/cdk/a11y';
|
|
2
2
|
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { Injectable,
|
|
4
|
+
import { Injectable, inject, DestroyRef, ChangeDetectorRef, ElementRef, viewChild, signal, output, computed, input, booleanAttribute, effect, Input as Input$1, Optional, Self, Component, Pipe } from '@angular/core';
|
|
5
5
|
import * as i1 from '@angular/forms';
|
|
6
6
|
import { NgForm, ReactiveFormsModule, FormsModule, NG_VALIDATORS } from '@angular/forms';
|
|
7
7
|
import * as i2 from '@ngstarter-ui/components/core';
|
|
8
8
|
import { ErrorStateMatcher, Ripple } from '@ngstarter-ui/components/core';
|
|
9
9
|
import { FormFieldControl } from '@ngstarter-ui/components/form-field';
|
|
10
|
-
import { MenuTrigger, Menu, MenuItem } from '@ngstarter-ui/components/menu';
|
|
10
|
+
import { MenuTrigger, Menu, MenuHeader, MenuItem, MenuDivider } from '@ngstarter-ui/components/menu';
|
|
11
11
|
import { parsePhoneNumber, parsePhoneNumberFromString, AsYouType } from 'libphonenumber-js';
|
|
12
12
|
import { Subject } from 'rxjs';
|
|
13
13
|
import { Icon } from '@ngstarter-ui/components/icon';
|
|
14
14
|
import { Input } from '@ngstarter-ui/components/input';
|
|
15
15
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
16
|
-
import {
|
|
16
|
+
import { Button } from '@ngstarter-ui/components/button';
|
|
17
17
|
|
|
18
18
|
class CountryCode {
|
|
19
19
|
allCountries = [
|
|
@@ -286,27 +286,10 @@ const phoneValidator = (control) => {
|
|
|
286
286
|
return null;
|
|
287
287
|
};
|
|
288
288
|
|
|
289
|
-
class SearchPipe {
|
|
290
|
-
transform(countries, searchCriteria) {
|
|
291
|
-
if (!searchCriteria || searchCriteria === '') {
|
|
292
|
-
return countries;
|
|
293
|
-
}
|
|
294
|
-
return countries.filter((country) => {
|
|
295
|
-
return `${country.name}${country.phoneCode}`
|
|
296
|
-
.toLowerCase()
|
|
297
|
-
.includes(searchCriteria.toLowerCase());
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: SearchPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
301
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.4", ngImport: i0, type: SearchPipe, isStandalone: true, name: "search" });
|
|
302
|
-
}
|
|
303
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: SearchPipe, decorators: [{
|
|
304
|
-
type: Pipe,
|
|
305
|
-
args: [{ name: 'search' }]
|
|
306
|
-
}] });
|
|
307
|
-
|
|
308
289
|
class PhoneInput {
|
|
309
290
|
ngControl;
|
|
291
|
+
static COUNTRY_RENDER_CHUNK_SIZE = 32;
|
|
292
|
+
static COUNTRY_RENDER_CHUNK_DELAY = 50;
|
|
310
293
|
_destroyRef = inject(DestroyRef);
|
|
311
294
|
_changeDetectorRef = inject(ChangeDetectorRef);
|
|
312
295
|
countryCodeData = inject(CountryCode);
|
|
@@ -315,7 +298,7 @@ class PhoneInput {
|
|
|
315
298
|
_errorStateMatcher = inject(ErrorStateMatcher);
|
|
316
299
|
_parentForm = inject(NgForm, { optional: true });
|
|
317
300
|
static nextId = 0;
|
|
318
|
-
|
|
301
|
+
searchInput = viewChild('searchInput', ...(ngDevMode ? [{ debugName: "searchInput" }] : /* istanbul ignore next */ []));
|
|
319
302
|
focusable = viewChild.required('focusable');
|
|
320
303
|
_focused = signal(false, ...(ngDevMode ? [{ debugName: "_focused" }] : /* istanbul ignore next */ []));
|
|
321
304
|
_errorState = signal(false, ...(ngDevMode ? [{ debugName: "_errorState" }] : /* istanbul ignore next */ []));
|
|
@@ -331,8 +314,25 @@ class PhoneInput {
|
|
|
331
314
|
selectedCountry = signal(null, ...(ngDevMode ? [{ debugName: "selectedCountry" }] : /* istanbul ignore next */ []));
|
|
332
315
|
numberInstance;
|
|
333
316
|
_value;
|
|
334
|
-
|
|
317
|
+
searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : /* istanbul ignore next */ []));
|
|
318
|
+
visibleCountryCount = signal(PhoneInput.COUNTRY_RENDER_CHUNK_SIZE, ...(ngDevMode ? [{ debugName: "visibleCountryCount" }] : /* istanbul ignore next */ []));
|
|
319
|
+
filteredCountries = computed(() => {
|
|
320
|
+
const searchTerm = this.searchTerm().trim().toLowerCase();
|
|
321
|
+
if (!searchTerm) {
|
|
322
|
+
return this.allCountries;
|
|
323
|
+
}
|
|
324
|
+
return this.allCountries.filter((country) => {
|
|
325
|
+
return `${country.name}${country.phoneCode}`
|
|
326
|
+
.toLowerCase()
|
|
327
|
+
.includes(searchTerm);
|
|
328
|
+
});
|
|
329
|
+
}, ...(ngDevMode ? [{ debugName: "filteredCountries" }] : /* istanbul ignore next */ []));
|
|
330
|
+
visibleCountries = computed(() => {
|
|
331
|
+
return this.filteredCountries().slice(0, this.visibleCountryCount());
|
|
332
|
+
}, ...(ngDevMode ? [{ debugName: "visibleCountries" }] : /* istanbul ignore next */ []));
|
|
335
333
|
_previousFormattedNumber;
|
|
334
|
+
_countryRenderTimeout;
|
|
335
|
+
_countrySearchFocusTimeout;
|
|
336
336
|
onTouched = () => { };
|
|
337
337
|
propagateChange = (_) => { };
|
|
338
338
|
get focused() {
|
|
@@ -445,6 +445,7 @@ class PhoneInput {
|
|
|
445
445
|
this._changeDetectorRef.detectChanges();
|
|
446
446
|
}
|
|
447
447
|
ngOnDestroy() {
|
|
448
|
+
this.clearCountryMenuTimeouts();
|
|
448
449
|
this.stateChanges.complete();
|
|
449
450
|
this._focusMonitor.stopMonitoring(this._elementRef);
|
|
450
451
|
}
|
|
@@ -492,6 +493,69 @@ class PhoneInput {
|
|
|
492
493
|
this.onPhoneNumberChange();
|
|
493
494
|
el.focus();
|
|
494
495
|
}
|
|
496
|
+
focusSearchInput() {
|
|
497
|
+
this.searchInput()?.nativeElement.focus();
|
|
498
|
+
}
|
|
499
|
+
openCountryMenu() {
|
|
500
|
+
this.visibleCountryCount.set(PhoneInput.COUNTRY_RENDER_CHUNK_SIZE);
|
|
501
|
+
this.scheduleCountryRendering();
|
|
502
|
+
this._countrySearchFocusTimeout = setTimeout(() => this.focusSearchInput());
|
|
503
|
+
}
|
|
504
|
+
closeCountryMenu() {
|
|
505
|
+
this.clearCountryMenuTimeouts();
|
|
506
|
+
this.searchTerm.set('');
|
|
507
|
+
this.visibleCountryCount.set(PhoneInput.COUNTRY_RENDER_CHUNK_SIZE);
|
|
508
|
+
}
|
|
509
|
+
onCountrySearch(searchTerm) {
|
|
510
|
+
this.searchTerm.set(searchTerm);
|
|
511
|
+
this.visibleCountryCount.set(PhoneInput.COUNTRY_RENDER_CHUNK_SIZE);
|
|
512
|
+
this.scheduleCountryRendering();
|
|
513
|
+
}
|
|
514
|
+
clearSearch(event) {
|
|
515
|
+
event.stopPropagation();
|
|
516
|
+
this.onCountrySearch('');
|
|
517
|
+
this.focusSearchInput();
|
|
518
|
+
}
|
|
519
|
+
countryFlagEmoji(shortCode) {
|
|
520
|
+
if (!shortCode || shortCode.length !== 2) {
|
|
521
|
+
return '';
|
|
522
|
+
}
|
|
523
|
+
const upperShortCode = shortCode.toUpperCase();
|
|
524
|
+
return Array.from(upperShortCode)
|
|
525
|
+
.map((letter) => String.fromCodePoint(0x1F1E6 + letter.charCodeAt(0) - 65))
|
|
526
|
+
.join('');
|
|
527
|
+
}
|
|
528
|
+
scheduleCountryRendering() {
|
|
529
|
+
this.clearCountryRenderTimeout();
|
|
530
|
+
if (this.visibleCountryCount() >= this.filteredCountries().length) {
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
this._countryRenderTimeout = setTimeout(() => {
|
|
534
|
+
this.visibleCountryCount.update((count) => {
|
|
535
|
+
return Math.min(count + PhoneInput.COUNTRY_RENDER_CHUNK_SIZE, this.filteredCountries().length);
|
|
536
|
+
});
|
|
537
|
+
this.scheduleCountryRendering();
|
|
538
|
+
this._changeDetectorRef.markForCheck();
|
|
539
|
+
}, PhoneInput.COUNTRY_RENDER_CHUNK_DELAY);
|
|
540
|
+
}
|
|
541
|
+
clearCountryMenuTimeouts() {
|
|
542
|
+
this.clearCountryRenderTimeout();
|
|
543
|
+
this.clearCountrySearchFocusTimeout();
|
|
544
|
+
}
|
|
545
|
+
clearCountryRenderTimeout() {
|
|
546
|
+
if (!this._countryRenderTimeout) {
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
clearTimeout(this._countryRenderTimeout);
|
|
550
|
+
this._countryRenderTimeout = undefined;
|
|
551
|
+
}
|
|
552
|
+
clearCountrySearchFocusTimeout() {
|
|
553
|
+
if (!this._countrySearchFocusTimeout) {
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
clearTimeout(this._countrySearchFocusTimeout);
|
|
557
|
+
this._countrySearchFocusTimeout = undefined;
|
|
558
|
+
}
|
|
495
559
|
getCountry(shortCode) {
|
|
496
560
|
return (this.allCountries.find((c) => c.shortCode === shortCode.toLowerCase()) || {
|
|
497
561
|
name: 'UN',
|
|
@@ -619,7 +683,7 @@ class PhoneInput {
|
|
|
619
683
|
useValue: phoneValidator,
|
|
620
684
|
multi: true,
|
|
621
685
|
},
|
|
622
|
-
], viewQueries: [{ propertyName: "
|
|
686
|
+
], viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }, { propertyName: "focusable", first: true, predicate: ["focusable"], descendants: true, isSignal: true }], exportAs: ["ngsPhoneInput"], ngImport: i0, template: "<div class=\"phone-input-container\">\n <button\n type=\"button\"\n ngsRipple\n [ngsMenuTriggerFor]=\"menu\"\n class=\"country-selector pe-1.5\"\n [disabled]=\"disabled\"\n (menuOpened)=\"openCountryMenu()\"\n (menuClosed)=\"closeCountryMenu()\">\n @if (selectedCountry()) {\n <span class=\"flag-icon\" aria-hidden=\"true\">{{ countryFlagEmoji(selectedCountry()?.shortCode) }}</span>\n\n @if (selectedCountry()?.phoneCode) {\n <span class=\"country-selector-code\">{{ selectedCountry()?.phoneCode }}</span>\n }\n }\n <ngs-icon name=\"fluent:chevron-down-24-regular\" class=\"text-neutral-500 size-4 relative ms-0.5\"/>\n </button>\n\n <input\n ngsInput\n type=\"tel\"\n inputmode=\"tel\"\n [autocomplete]=\"autocomplete()\"\n (blur)=\"onTouched()\"\n (keypress)=\"onInputKeyPress($event)\"\n [(ngModel)]=\"phoneNumber\"\n (ngModelChange)=\"onPhoneNumberChange()\"\n [errorStateMatcher]=\"errorStateMatcher()\"\n [placeholder]=\"_placeholder()\"\n [disabled]=\"disabled\"\n class=\"grow\"\n #focusable>\n</div>\n\n<ngs-menu #menu=\"ngsMenu\">\n <ngs-menu-header>\n <div class=\"sticky top-0 z-1 bg-surface-container-lowest\">\n <input #searchInput\n type=\"text\"\n placeholder=\"Search...\"\n autocomplete=\"off\"\n [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"onCountrySearch($event)\"\n class=\"w-full text-sm focus:outline-none border-b border-border focus:border-b-primary h-14 px-3\">\n @if (searchTerm().trim()) {\n <div class=\"absolute end-1 top-1/2 -translate-y-1/2\">\n <button\n ngsIconButton\n (click)=\"clearSearch($event)\"\n class=\"clear-button\"\n type=\"button\"\n aria-label=\"Clear search\">\n <ngs-icon name=\"fluent:dismiss-24-regular\"/>\n </button>\n </div>\n }\n </div>\n </ngs-menu-header>\n\n @for (country of preferredCountriesInDropDown; track country.shortCode) {\n <button type=\"button\" ngs-menu-item (click)=\"onCountrySelect(country, focusable)\">\n <div class=\"flex items-center gap-2\">\n <span class=\"flag-icon-option text-2xl\" aria-hidden=\"true\">{{ countryFlagEmoji(country.shortCode) }}</span>\n <div class=\"label-wrapper\">\n {{ country.name }}\n <span [class.whitespace-nowrap]=\"!searchTerm()\" class=\"text-neutral-500\">{{ country.phoneCode }}</span>\n </div>\n </div>\n </button>\n }\n\n @if (preferredCountriesInDropDown.length) {\n <ngs-menu-divider/>\n }\n\n @for (country of visibleCountries(); track country.shortCode) {\n <button type=\"button\" ngs-menu-item (click)=\"onCountrySelect(country, focusable)\">\n <div class=\"flex items-center gap-2\">\n <span class=\"flag-icon-option text-2xl\" aria-hidden=\"true\">{{ countryFlagEmoji(country.shortCode) }}</span>\n <div>\n {{ country.name }}\n <span [class.whitespace-nowrap]=\"!searchTerm()\" class=\"text-neutral-500\">{{ country.phoneCode }}</span>\n </div>\n </div>\n </button>\n } @empty {\n @if (searchTerm()) {\n <div class=\"text-sm px-4 py-3\">\n <span i18n>No countries found</span>.\n </div>\n }\n }\n\n @if (visibleCountryCount() < filteredCountries().length) {\n <div class=\"country-loading\">\n Loading more countries...\n </div>\n }\n</ngs-menu>\n", styles: [":host{--ngs-phone-input-color: var(--ngs-color-neutral-600);--ngs-phone-input-opacity: 0}@media print{:host{--ngs-phone-input-flag-display: none}}:host .flag-icon{display:var(--ngs-phone-input-flag-display, inline-flex);align-items:center;justify-content:center;width:22px;margin-inline-end:calc(var(--spacing, .25rem) * 1);font-size:22px;line-height:1}:host.is-floating .country-selector{opacity:1}:host .phone-input-container{display:flex;align-items:center}:host .country-empty,:host .country-loading{padding:calc(var(--spacing, .25rem) * 3);color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-sm)}:host .country-loading{padding-block:calc(var(--spacing, .25rem) * 2)}:host .phone-input-container input{border:none;background:none;outline:none;font:inherit;width:max-content;box-sizing:border-box;padding-right:6px;padding-left:4px;position:relative;z-index:0}:host .icon-wrapper{padding-right:24px}:host .mdc-button__label{margin-right:auto}:host .country-selector{display:flex;align-items:center;line-height:0;border-radius:0;color:var(--ngs-phone-input-color);flex-shrink:0;height:initial;opacity:var(--ngs-phone-input-opacity, 0);transition:opacity .2s;border:unset}:host .country-selector:disabled{opacity:.8}:host .country-selector-code{color:var(--ngs-phone-input-color);padding-right:0}:host-context(html.dark){--ngs-phone-input-color: var(--ngs-color-neutral-500)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: Ripple, selector: "[ngsRipple]", inputs: ["ngsRippleColor", "ngsRippleUnbounded", "ngsRippleCentered", "ngsRippleRadius", "ngsRippleAnimation", "ngsRippleDisabled", "ngsRippleTrigger"], outputs: ["ngsRippleCenteredChange", "ngsRippleDisabledChange", "ngsRippleTriggerChange"], exportAs: ["ngsRipple"] }, { kind: "directive", type: MenuTrigger, selector: "[ngsMenuTriggerFor]", inputs: ["ngsMenuTriggerFor", "ngsMenuTriggerData", "ngsMenuDisabled", "xPosition", "yPosition", "ngsMenuTriggerRestoreFocus"], outputs: ["menuOpened", "menuClosed"], exportAs: ["ngsMenuTrigger"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "component", type: Menu, selector: "ngs-menu", inputs: ["role", "classList", "xPosition", "yPosition"], outputs: ["closed"], exportAs: ["ngsMenu"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MenuHeader, selector: "ngs-menu-header", exportAs: ["ngsMenuHeader"] }, { kind: "component", type: MenuItem, selector: "ngs-menu-item, [ngs-menu-item]", inputs: ["disabled", "role", "selected"], outputs: ["_triggered"], exportAs: ["ngsMenuItem"] }, { kind: "component", type: MenuDivider, selector: "ngs-menu-divider" }, { kind: "directive", type: Input, selector: "input[ngsInput], textarea[ngsInput]", inputs: ["id", "placeholder", "required", "disabled", "readonly", "errorStateMatcher"], exportAs: ["ngsInput"] }, { kind: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }] });
|
|
623
687
|
}
|
|
624
688
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: PhoneInput, decorators: [{
|
|
625
689
|
type: Component,
|
|
@@ -630,10 +694,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
630
694
|
Menu,
|
|
631
695
|
ReactiveFormsModule,
|
|
632
696
|
FormsModule,
|
|
697
|
+
MenuHeader,
|
|
633
698
|
MenuItem,
|
|
699
|
+
MenuDivider,
|
|
634
700
|
Input,
|
|
635
|
-
|
|
636
|
-
Divider,
|
|
701
|
+
Button,
|
|
637
702
|
], providers: [
|
|
638
703
|
CountryCode,
|
|
639
704
|
{
|
|
@@ -648,7 +713,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
648
713
|
], host: {
|
|
649
714
|
'class': 'ngs-phone-input',
|
|
650
715
|
'[class.is-floating]': 'shouldLabelFloat',
|
|
651
|
-
}, template: "<div class=\"phone-input-container\">\n <button\n type=\"button\"\n ngsRipple\n [ngsMenuTriggerFor]=\"menu\"\n class=\"country-selector pe-1.5\"\n [disabled]=\"disabled\"\n (menuOpened)=\"
|
|
716
|
+
}, template: "<div class=\"phone-input-container\">\n <button\n type=\"button\"\n ngsRipple\n [ngsMenuTriggerFor]=\"menu\"\n class=\"country-selector pe-1.5\"\n [disabled]=\"disabled\"\n (menuOpened)=\"openCountryMenu()\"\n (menuClosed)=\"closeCountryMenu()\">\n @if (selectedCountry()) {\n <span class=\"flag-icon\" aria-hidden=\"true\">{{ countryFlagEmoji(selectedCountry()?.shortCode) }}</span>\n\n @if (selectedCountry()?.phoneCode) {\n <span class=\"country-selector-code\">{{ selectedCountry()?.phoneCode }}</span>\n }\n }\n <ngs-icon name=\"fluent:chevron-down-24-regular\" class=\"text-neutral-500 size-4 relative ms-0.5\"/>\n </button>\n\n <input\n ngsInput\n type=\"tel\"\n inputmode=\"tel\"\n [autocomplete]=\"autocomplete()\"\n (blur)=\"onTouched()\"\n (keypress)=\"onInputKeyPress($event)\"\n [(ngModel)]=\"phoneNumber\"\n (ngModelChange)=\"onPhoneNumberChange()\"\n [errorStateMatcher]=\"errorStateMatcher()\"\n [placeholder]=\"_placeholder()\"\n [disabled]=\"disabled\"\n class=\"grow\"\n #focusable>\n</div>\n\n<ngs-menu #menu=\"ngsMenu\">\n <ngs-menu-header>\n <div class=\"sticky top-0 z-1 bg-surface-container-lowest\">\n <input #searchInput\n type=\"text\"\n placeholder=\"Search...\"\n autocomplete=\"off\"\n [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"onCountrySearch($event)\"\n class=\"w-full text-sm focus:outline-none border-b border-border focus:border-b-primary h-14 px-3\">\n @if (searchTerm().trim()) {\n <div class=\"absolute end-1 top-1/2 -translate-y-1/2\">\n <button\n ngsIconButton\n (click)=\"clearSearch($event)\"\n class=\"clear-button\"\n type=\"button\"\n aria-label=\"Clear search\">\n <ngs-icon name=\"fluent:dismiss-24-regular\"/>\n </button>\n </div>\n }\n </div>\n </ngs-menu-header>\n\n @for (country of preferredCountriesInDropDown; track country.shortCode) {\n <button type=\"button\" ngs-menu-item (click)=\"onCountrySelect(country, focusable)\">\n <div class=\"flex items-center gap-2\">\n <span class=\"flag-icon-option text-2xl\" aria-hidden=\"true\">{{ countryFlagEmoji(country.shortCode) }}</span>\n <div class=\"label-wrapper\">\n {{ country.name }}\n <span [class.whitespace-nowrap]=\"!searchTerm()\" class=\"text-neutral-500\">{{ country.phoneCode }}</span>\n </div>\n </div>\n </button>\n }\n\n @if (preferredCountriesInDropDown.length) {\n <ngs-menu-divider/>\n }\n\n @for (country of visibleCountries(); track country.shortCode) {\n <button type=\"button\" ngs-menu-item (click)=\"onCountrySelect(country, focusable)\">\n <div class=\"flex items-center gap-2\">\n <span class=\"flag-icon-option text-2xl\" aria-hidden=\"true\">{{ countryFlagEmoji(country.shortCode) }}</span>\n <div>\n {{ country.name }}\n <span [class.whitespace-nowrap]=\"!searchTerm()\" class=\"text-neutral-500\">{{ country.phoneCode }}</span>\n </div>\n </div>\n </button>\n } @empty {\n @if (searchTerm()) {\n <div class=\"text-sm px-4 py-3\">\n <span i18n>No countries found</span>.\n </div>\n }\n }\n\n @if (visibleCountryCount() < filteredCountries().length) {\n <div class=\"country-loading\">\n Loading more countries...\n </div>\n }\n</ngs-menu>\n", styles: [":host{--ngs-phone-input-color: var(--ngs-color-neutral-600);--ngs-phone-input-opacity: 0}@media print{:host{--ngs-phone-input-flag-display: none}}:host .flag-icon{display:var(--ngs-phone-input-flag-display, inline-flex);align-items:center;justify-content:center;width:22px;margin-inline-end:calc(var(--spacing, .25rem) * 1);font-size:22px;line-height:1}:host.is-floating .country-selector{opacity:1}:host .phone-input-container{display:flex;align-items:center}:host .country-empty,:host .country-loading{padding:calc(var(--spacing, .25rem) * 3);color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-sm)}:host .country-loading{padding-block:calc(var(--spacing, .25rem) * 2)}:host .phone-input-container input{border:none;background:none;outline:none;font:inherit;width:max-content;box-sizing:border-box;padding-right:6px;padding-left:4px;position:relative;z-index:0}:host .icon-wrapper{padding-right:24px}:host .mdc-button__label{margin-right:auto}:host .country-selector{display:flex;align-items:center;line-height:0;border-radius:0;color:var(--ngs-phone-input-color);flex-shrink:0;height:initial;opacity:var(--ngs-phone-input-opacity, 0);transition:opacity .2s;border:unset}:host .country-selector:disabled{opacity:.8}:host .country-selector-code{color:var(--ngs-phone-input-color);padding-right:0}:host-context(html.dark){--ngs-phone-input-color: var(--ngs-color-neutral-500)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
|
|
652
717
|
}], ctorParameters: () => [{ type: i1.NgControl, decorators: [{
|
|
653
718
|
type: Optional
|
|
654
719
|
}, {
|
|
@@ -657,11 +722,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
|
|
|
657
722
|
type: Optional
|
|
658
723
|
}] }, { type: i1.FormGroupDirective, decorators: [{
|
|
659
724
|
type: Optional
|
|
660
|
-
}] }, { type: i2.ErrorStateMatcher }], propDecorators: {
|
|
725
|
+
}] }, { type: i2.ErrorStateMatcher }], propDecorators: { searchInput: [{ type: i0.ViewChild, args: ['searchInput', { isSignal: true }] }], focusable: [{ type: i0.ViewChild, args: ['focusable', { isSignal: true }] }], countryChanged: [{ type: i0.Output, args: ["countryChanged"] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], errorStateMatcher: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorStateMatcher", required: false }] }], onlyCountries: [{ type: i0.Input, args: [{ isSignal: true, alias: "onlyCountries", required: false }] }], preferredCountries: [{ type: i0.Input, args: [{ isSignal: true, alias: "preferredCountries", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], defaultSelectedCountryCode: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultSelectedCountryCode", required: false }] }], _placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], required: [{
|
|
661
726
|
type: Input$1,
|
|
662
727
|
args: [{ alias: 'required', transform: booleanAttribute }]
|
|
663
728
|
}], phoneDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
664
729
|
|
|
730
|
+
class SearchPipe {
|
|
731
|
+
transform(countries, searchCriteria) {
|
|
732
|
+
if (!searchCriteria || searchCriteria === '') {
|
|
733
|
+
return countries;
|
|
734
|
+
}
|
|
735
|
+
return countries.filter((country) => {
|
|
736
|
+
return `${country.name}${country.phoneCode}`
|
|
737
|
+
.toLowerCase()
|
|
738
|
+
.includes(searchCriteria.toLowerCase());
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: SearchPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
742
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.4", ngImport: i0, type: SearchPipe, isStandalone: true, name: "search" });
|
|
743
|
+
}
|
|
744
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: SearchPipe, decorators: [{
|
|
745
|
+
type: Pipe,
|
|
746
|
+
args: [{ name: 'search' }]
|
|
747
|
+
}] });
|
|
748
|
+
|
|
665
749
|
/**
|
|
666
750
|
* Generated bundle index. Do not edit.
|
|
667
751
|
*/
|