@ngstarter-ui/components 21.0.31 → 21.0.33

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.
@@ -3,7 +3,7 @@
3
3
  "generatedBy": "scripts/generate-ai-metadata.mjs",
4
4
  "package": "@ngstarter-ui/components",
5
5
  "description": "AI-readable registry for NgStarter UI Angular secondary entry points.",
6
- "componentCount": 124,
6
+ "componentCount": 125,
7
7
  "conventions": {
8
8
  "importPattern": "@ngstarter-ui/components/<component>",
9
9
  "selectorPrefix": "ngs",
@@ -2925,7 +2925,9 @@
2925
2925
  ],
2926
2926
  "cssTokens": [
2927
2927
  "--ngs-color-neutral-500",
2928
- "--ngs-dropdown-item-gap"
2928
+ "--ngs-color-on-surface-variant",
2929
+ "--ngs-dropdown-item-gap",
2930
+ "--ngs-font-size-sm"
2929
2931
  ],
2930
2932
  "example": null
2931
2933
  },
@@ -3028,7 +3030,9 @@
3028
3030
  ],
3029
3031
  "cssTokens": [
3030
3032
  "--ngs-color-neutral-500",
3031
- "--ngs-dropdown-item-gap"
3033
+ "--ngs-color-on-surface-variant",
3034
+ "--ngs-dropdown-item-gap",
3035
+ "--ngs-font-size-sm"
3032
3036
  ],
3033
3037
  "example": null
3034
3038
  },
@@ -5916,7 +5920,6 @@
5916
5920
  "--ngs-menu-border",
5917
5921
  "--ngs-menu-divider-color",
5918
5922
  "--ngs-menu-divider-margin",
5919
- "--ngs-menu-footer-padding",
5920
5923
  "--ngs-menu-item-active-background",
5921
5924
  "--ngs-menu-item-color",
5922
5925
  "--ngs-menu-item-disabled-color",
@@ -5931,6 +5934,7 @@
5931
5934
  "--ngs-menu-max-width",
5932
5935
  "--ngs-menu-min-width",
5933
5936
  "--ngs-menu-padding",
5937
+ "--ngs-menu-panel-bg",
5934
5938
  "--ngs-menu-shadow"
5935
5939
  ],
5936
5940
  "example": null
@@ -6842,6 +6846,97 @@
6842
6846
  ],
6843
6847
  "example": null
6844
6848
  },
6849
+ {
6850
+ "name": "pdf-viewer",
6851
+ "title": "Pdf Viewer",
6852
+ "overviewName": "PDF Viewer",
6853
+ "category": "libraries",
6854
+ "package": "@ngstarter-ui/components",
6855
+ "importPath": "@ngstarter-ui/components/pdf-viewer",
6856
+ "publicApi": "projects/components/pdf-viewer/public-api.ts",
6857
+ "sourceRoot": "projects/components/pdf-viewer/src",
6858
+ "docsPath": "/libraries/pdf-viewer",
6859
+ "docsOverviewSource": "projects/docs/src/app/libraries/pdf-viewer/overview/overview.html",
6860
+ "purpose": "Import PDF Viewer from &#64;ngstarter-ui/components/pdf-viewer .",
6861
+ "useWhen": "Choose Pdf Viewer when the workflow matches examples such as Basic pdf viewer.",
6862
+ "exampleTopics": [
6863
+ "Basic pdf viewer"
6864
+ ],
6865
+ "minimalExample": "<div class=\"pdf-viewer-example-toolbar\">\n <input\n #pdfFileInput\n class=\"pdf-viewer-example-file-input\"\n type=\"file\"\n accept=\"application/pdf,.pdf\"\n (change)=\"onPdfSelected($event)\" />\n <button ngsButton=\"tonal\" type=\"button\" (click)=\"pdfFileInput.click()\">\n <ngs-icon name=\"fluent:arrow-upload-24-regular\" />\n Upload PDF\n </button>\n</div>\n<ngs-pdf-viewer\n [src]=\"src()\"\n [wasmUrl]=\"wasmUrl\"\n class=\"pdf-viewer-example\" />",
6866
+ "exampleFiles": [
6867
+ {
6868
+ "name": "basic-pdf-viewer-example",
6869
+ "title": "Basic pdf viewer",
6870
+ "file": "projects/docs/src/app/libraries/pdf-viewer/_examples/basic-pdf-viewer-example/basic-pdf-viewer-example.html",
6871
+ "source": "<div class=\"pdf-viewer-example-toolbar\">\n <input\n #pdfFileInput\n class=\"pdf-viewer-example-file-input\"\n type=\"file\"\n accept=\"application/pdf,.pdf\"\n (change)=\"onPdfSelected($event)\" />\n <button ngsButton=\"tonal\" type=\"button\" (click)=\"pdfFileInput.click()\">\n <ngs-icon name=\"fluent:arrow-upload-24-regular\" />\n Upload PDF\n </button>\n</div>\n<ngs-pdf-viewer\n [src]=\"src()\"\n [wasmUrl]=\"wasmUrl\"\n class=\"pdf-viewer-example\" />"
6872
+ }
6873
+ ],
6874
+ "previewAsset": "projects/components/pdf-viewer/preview.svg",
6875
+ "selectors": [
6876
+ "ngs-pdf-viewer"
6877
+ ],
6878
+ "exportedSymbols": [
6879
+ "PdfViewer",
6880
+ "PdfViewerEngineService",
6881
+ "PdfViewerLoadedEvent",
6882
+ "PdfViewerPageRenderedEvent",
6883
+ "PdfViewerPageView",
6884
+ "PdfViewerSelectionRectView",
6885
+ "PdfViewerSource",
6886
+ "PdfViewerTextGlyphView",
6887
+ "PdfViewerTextRectView",
6888
+ "PdfViewerThumbnailView"
6889
+ ],
6890
+ "inputs": [
6891
+ "maxScale",
6892
+ "minScale",
6893
+ "page",
6894
+ "renderAll",
6895
+ "scale",
6896
+ "showPageList",
6897
+ "showToolbar",
6898
+ "src",
6899
+ "wasmUrl",
6900
+ "withAnnotations",
6901
+ "withForms",
6902
+ "zoomStep"
6903
+ ],
6904
+ "outputs": [
6905
+ "error",
6906
+ "loaded",
6907
+ "pageChanged",
6908
+ "pageRendered"
6909
+ ],
6910
+ "cssTokens": [
6911
+ "--ngs-color-danger",
6912
+ "--ngs-color-on-surface",
6913
+ "--ngs-color-on-surface-variant",
6914
+ "--ngs-color-outline",
6915
+ "--ngs-color-outline-variant",
6916
+ "--ngs-color-primary",
6917
+ "--ngs-color-primary-container",
6918
+ "--ngs-color-surface",
6919
+ "--ngs-color-surface-container-low",
6920
+ "--ngs-font-size-sm",
6921
+ "--ngs-font-size-xs",
6922
+ "--ngs-pdf-viewer-background",
6923
+ "--ngs-pdf-viewer-border-color",
6924
+ "--ngs-pdf-viewer-height",
6925
+ "--ngs-pdf-viewer-page-background",
6926
+ "--ngs-pdf-viewer-page-shadow",
6927
+ "--ngs-pdf-viewer-radius",
6928
+ "--ngs-pdf-viewer-selection-background",
6929
+ "--ngs-pdf-viewer-sidebar-width",
6930
+ "--ngs-radius-md",
6931
+ "--ngs-shadow-md",
6932
+ "--ngs-shadow-xs",
6933
+ "--ngs-spacing-1",
6934
+ "--ngs-spacing-2",
6935
+ "--ngs-spacing-3",
6936
+ "--ngs-spacing-6"
6937
+ ],
6938
+ "example": null
6939
+ },
6845
6940
  {
6846
6941
  "name": "phone-input",
6847
6942
  "title": "Phone Input",
@@ -6911,7 +7006,8 @@
6911
7006
  "cssTokens": [
6912
7007
  "--ngs-color-neutral-500",
6913
7008
  "--ngs-color-neutral-600",
6914
- "--ngs-icon-size",
7009
+ "--ngs-color-on-surface-variant",
7010
+ "--ngs-font-size-sm",
6915
7011
  "--ngs-phone-input-color",
6916
7012
  "--ngs-phone-input-flag-display",
6917
7013
  "--ngs-phone-input-opacity"
@@ -263,6 +263,8 @@ const countries = [
263
263
  ];
264
264
 
265
265
  class CountrySelect {
266
+ static COUNTRY_RENDER_CHUNK_SIZE = 32;
267
+ static COUNTRY_RENDER_CHUNK_DELAY = 50;
266
268
  _elementRef = inject(ElementRef);
267
269
  _renderer = inject(Renderer2);
268
270
  _formField = inject(FORM_FIELD, { optional: true });
@@ -270,6 +272,7 @@ class CountrySelect {
270
272
  id = `ngs-country-select-${CountrySelect.nextId++}`;
271
273
  stateChanges = new Subject();
272
274
  searchTerm = model('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : /* istanbul ignore next */ []));
275
+ visibleCountryCount = signal(CountrySelect.COUNTRY_RENDER_CHUNK_SIZE, ...(ngDevMode ? [{ debugName: "visibleCountryCount" }] : /* istanbul ignore next */ []));
273
276
  _valueSignal = signal(null, ...(ngDevMode ? [{ debugName: "_valueSignal" }] : /* istanbul ignore next */ []));
274
277
  _focusedSignal = signal(false, ...(ngDevMode ? [{ debugName: "_focusedSignal" }] : /* istanbul ignore next */ []));
275
278
  _touched = false;
@@ -288,6 +291,9 @@ class CountrySelect {
288
291
  return countries.filter(country => country.name.toLowerCase().includes(filterValue) ||
289
292
  country.code.toLowerCase().includes(filterValue));
290
293
  }, ...(ngDevMode ? [{ debugName: "filteredCountries" }] : /* istanbul ignore next */ []));
294
+ visibleCountries = computed(() => {
295
+ return this.filteredCountries().slice(0, this.visibleCountryCount());
296
+ }, ...(ngDevMode ? [{ debugName: "visibleCountries" }] : /* istanbul ignore next */ []));
291
297
  selectedCountryDisplay = computed(() => {
292
298
  return this.internalCountries.find(c => c.code === this._valueSignal());
293
299
  }, ...(ngDevMode ? [{ debugName: "selectedCountryDisplay" }] : /* istanbul ignore next */ []));
@@ -301,11 +307,14 @@ class CountrySelect {
301
307
  closed = output();
302
308
  onChangeFn = () => { };
303
309
  onTouchedFn = () => { };
310
+ _countryRenderTimeout;
311
+ _countrySearchFocusTimeout;
304
312
  constructor() {
305
313
  if (this.ngControl) {
306
314
  this.ngControl.valueAccessor = this;
307
315
  }
308
316
  this.destroyRef.onDestroy(() => {
317
+ this.clearCountrySelectTimeouts();
309
318
  this.fm.stopMonitoring(this.elRef.nativeElement);
310
319
  this.stateChanges.complete();
311
320
  });
@@ -338,6 +347,7 @@ class CountrySelect {
338
347
  }
339
348
  }
340
349
  ngOnDestroy() {
350
+ this.clearCountrySelectTimeouts();
341
351
  }
342
352
  get value() {
343
353
  return this._valueSignal();
@@ -427,18 +437,27 @@ class CountrySelect {
427
437
  }
428
438
  clearSearch(event) {
429
439
  event.stopPropagation();
430
- this.searchTerm.set('');
440
+ this.onCountrySearch('');
431
441
  this.searchInput().nativeElement.focus();
432
442
  }
443
+ onCountrySearch(searchTerm) {
444
+ this.searchTerm.set(searchTerm);
445
+ this.visibleCountryCount.set(CountrySelect.COUNTRY_RENDER_CHUNK_SIZE);
446
+ this.scheduleCountryRendering();
447
+ }
433
448
  onSelectOpened() {
434
- setTimeout(() => {
449
+ this.visibleCountryCount.set(this.getInitialVisibleCountryCount());
450
+ this.scheduleCountryRendering();
451
+ this._countrySearchFocusTimeout = setTimeout(() => {
435
452
  this.searchInput().nativeElement.focus();
436
453
  });
437
454
  this.opened.emit();
438
455
  }
439
456
  onSelectClosed() {
457
+ this.clearCountrySelectTimeouts();
440
458
  this._focusedSignal.set(false);
441
459
  this.searchTerm.set('');
460
+ this.visibleCountryCount.set(CountrySelect.COUNTRY_RENDER_CHUNK_SIZE);
442
461
  if (!this._touched) {
443
462
  this.onTouchedFn();
444
463
  }
@@ -447,13 +466,55 @@ class CountrySelect {
447
466
  focus() {
448
467
  this.ngsSelect()?.focus();
449
468
  }
469
+ getInitialVisibleCountryCount() {
470
+ const countries = this.filteredCountries();
471
+ const selectedCountryCode = this._valueSignal();
472
+ if (!selectedCountryCode) {
473
+ return CountrySelect.COUNTRY_RENDER_CHUNK_SIZE;
474
+ }
475
+ const selectedCountryIndex = countries.findIndex((country) => country.code === selectedCountryCode);
476
+ if (selectedCountryIndex === -1) {
477
+ return CountrySelect.COUNTRY_RENDER_CHUNK_SIZE;
478
+ }
479
+ return Math.min(Math.max(selectedCountryIndex + 1, CountrySelect.COUNTRY_RENDER_CHUNK_SIZE), countries.length);
480
+ }
481
+ scheduleCountryRendering() {
482
+ this.clearCountryRenderTimeout();
483
+ if (this.visibleCountryCount() >= this.filteredCountries().length) {
484
+ return;
485
+ }
486
+ this._countryRenderTimeout = setTimeout(() => {
487
+ this.visibleCountryCount.update((count) => {
488
+ return Math.min(count + CountrySelect.COUNTRY_RENDER_CHUNK_SIZE, this.filteredCountries().length);
489
+ });
490
+ this.scheduleCountryRendering();
491
+ }, CountrySelect.COUNTRY_RENDER_CHUNK_DELAY);
492
+ }
493
+ clearCountrySelectTimeouts() {
494
+ this.clearCountryRenderTimeout();
495
+ this.clearCountrySearchFocusTimeout();
496
+ }
497
+ clearCountryRenderTimeout() {
498
+ if (!this._countryRenderTimeout) {
499
+ return;
500
+ }
501
+ clearTimeout(this._countryRenderTimeout);
502
+ this._countryRenderTimeout = undefined;
503
+ }
504
+ clearCountrySearchFocusTimeout() {
505
+ if (!this._countrySearchFocusTimeout) {
506
+ return;
507
+ }
508
+ clearTimeout(this._countrySearchFocusTimeout);
509
+ this._countrySearchFocusTimeout = undefined;
510
+ }
450
511
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CountrySelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
451
512
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: CountrySelect, isStandalone: true, selector: "ngs-country-select", inputs: { searchTerm: { classPropertyName: "searchTerm", publicName: "searchTerm", isSignal: true, isRequired: false, transformFunction: null }, placeholderInputSignal: { classPropertyName: "placeholderInputSignal", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, isRequiredSignal: { classPropertyName: "isRequiredSignal", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, isDisabledSignal: { classPropertyName: "isDisabledSignal", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showCountryCode: { classPropertyName: "showCountryCode", publicName: "showCountryCode", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { searchTerm: "searchTermChange", isRequiredSignal: "requiredChange", isDisabledSignal: "disabledChange", opened: "opened", closed: "closed" }, host: { listeners: { "focus": "onFocusIn()", "blur": "onFocusOut($event)" }, properties: { "class.floating": "shouldLabelFloat", "id": "id", "attr.tabindex": "disabled ? -1 : 0" }, classAttribute: "ngs-country-select" }, providers: [
452
513
  {
453
514
  provide: FormFieldControl,
454
515
  useExisting: forwardRef(() => CountrySelect),
455
516
  },
456
- ], viewQueries: [{ propertyName: "ngsSelect", first: true, predicate: ["ngsSelect"], descendants: true, isSignal: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], exportAs: ["ngsCountrySelect"], ngImport: i0, template: "<ngs-select\n #ngsSelect\n [value]=\"value\"\n (selectionChange)=\"onSelectionChange($event)\"\n (opened)=\"onSelectOpened()\"\n (closed)=\"onSelectClosed()\"\n [placeholder]=\"placeholder\"\n [required]=\"isRequiredSignal()\"\n [disabled]=\"isDisabledSignal()\">\n <ngs-select-trigger class=\"select-trigger\">\n @let selectedCountry = selectedCountryDisplay();\n @if (selectedCountry) {\n <span class=\"ngs-select-trigger-content\">\n <span class=\"ngs-select-trigger-icon\">{{ selectedCountry.flag }}</span>\n <span class=\"ngs-select-trigger-text\">\n {{ selectedCountry.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ selectedCountry.code }})</span>\n }\n </span>\n </span>\n }\n\n @if (!selectedCountryDisplay() && placeholder) {\n <span class=\"ngs-select-trigger-text placeholder-text\">\n {{ placeholder }}\n </span>\n }\n </ngs-select-trigger>\n\n <ngs-select-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 class=\"w-full text-sm focus:outline-none border-b border-surface-container-high 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-select-header>\n\n @for (country of filteredCountries(); track country.code) {\n <ngs-option [value]=\"country.code\">\n <span class=\"select-option-content\">\n <span class=\"select-option-icon\">{{ country.flag }}</span>\n <span class=\"select-option-text\">\n {{ country.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ country.code }})</span>\n }\n </span>\n </span>\n </ngs-option>\n } @empty {\n @if (searchTerm()) {\n <div class=\"text-sm px-4 py-3\">\n <span i18n>Country not found</span>.\n </div>\n }\n }\n</ngs-select>\n", styles: [":host{display:block}:host .ngs-select-trigger-icon,:host .select-option-icon{font-size:1.25rem}:host .select-option-content{display:flex;align-items:center;gap:var(--ngs-dropdown-item-gap, calc(var(--spacing, .25rem) * 2));min-width:0;width:100%;height:100%;overflow:hidden;white-space:nowrap}:host .select-option-icon{flex:none;line-height:0}:host .select-option-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .code{text-transform:uppercase;color:var(--ngs-color-neutral-500)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: Option, selector: "ngs-option", inputs: ["value", "data", "disabled", "selected"], outputs: ["onSelectionChange"], exportAs: ["ngsOption"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "component", type: Select, selector: "ngs-select", inputs: ["id", "placeholder", "disabled", "required", "multiple", "hideCheckIcon", "clearable", "aria-label", "tabIndex", "aria-describedby", "value"], outputs: ["selectionChange", "opened", "closed", "valueChange"], exportAs: ["ngsSelect"] }, { kind: "directive", type: SelectTrigger, selector: "ngs-select-trigger" }, { 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: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "component", type: SelectHeader, selector: "ngs-select-header" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
517
+ ], viewQueries: [{ propertyName: "ngsSelect", first: true, predicate: ["ngsSelect"], descendants: true, isSignal: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }], exportAs: ["ngsCountrySelect"], ngImport: i0, template: "<ngs-select\n #ngsSelect\n [value]=\"value\"\n (selectionChange)=\"onSelectionChange($event)\"\n (opened)=\"onSelectOpened()\"\n (closed)=\"onSelectClosed()\"\n [placeholder]=\"placeholder\"\n [required]=\"isRequiredSignal()\"\n [disabled]=\"isDisabledSignal()\">\n <ngs-select-trigger class=\"select-trigger\">\n @let selectedCountry = selectedCountryDisplay();\n @if (selectedCountry) {\n <span class=\"ngs-select-trigger-content\">\n <span class=\"flag-icon\" aria-hidden=\"true\">{{ selectedCountry.flag }}</span>\n <span class=\"ngs-select-trigger-text\">\n {{ selectedCountry.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ selectedCountry.code }})</span>\n }\n </span>\n </span>\n }\n\n @if (!selectedCountryDisplay() && placeholder) {\n <span class=\"ngs-select-trigger-text placeholder-text\">\n {{ placeholder }}\n </span>\n }\n </ngs-select-trigger>\n\n <ngs-select-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-surface-container-high 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-select-header>\n\n @for (country of visibleCountries(); track country.code) {\n <ngs-option [value]=\"country.code\">\n <div class=\"flex items-center gap-2\">\n <span class=\"select-option-icon text-2xl\" aria-hidden=\"true\">{{ country.flag }}</span>\n <span class=\"select-option-text\">\n {{ country.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ country.code }})</span>\n }\n </span>\n </div>\n </ngs-option>\n } @empty {\n @if (searchTerm()) {\n <div class=\"text-sm px-4 py-3\">\n <span i18n>Country not found</span>.\n </div>\n }\n }\n\n @if (visibleCountryCount() < filteredCountries().length) {\n <div class=\"select-loading\">\n Loading more countries...\n </div>\n }\n</ngs-select>\n", styles: [":host{display:block}:host .flag-icon{display:inline-flex;align-items:center;justify-content:center;width:22px;font-size:22px;line-height:1}:host .select-option-content{display:flex;align-items:center;gap:var(--ngs-dropdown-item-gap);min-width:0;width:100%;height:100%;overflow:hidden;white-space:nowrap}:host .select-option-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .code{text-transform:uppercase;color:var(--ngs-color-neutral-500)}:host .select-loading{padding:calc(var(--spacing, .25rem) * 2) calc(var(--spacing, .25rem) * 4);color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-sm)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: Option, selector: "ngs-option", inputs: ["value", "data", "disabled", "selected"], outputs: ["onSelectionChange"], exportAs: ["ngsOption"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "component", type: Select, selector: "ngs-select", inputs: ["id", "placeholder", "disabled", "required", "multiple", "hideCheckIcon", "clearable", "aria-label", "tabIndex", "aria-describedby", "value"], outputs: ["selectionChange", "opened", "closed", "valueChange"], exportAs: ["ngsSelect"] }, { kind: "directive", type: SelectTrigger, selector: "ngs-select-trigger" }, { 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: "component", type: Button, selector: " button[ngsButton], button[ngsIconButton], a[ngsButton], a[ngsIconButton] ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }, { kind: "component", type: SelectHeader, selector: "ngs-select-header" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
457
518
  }
458
519
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: CountrySelect, decorators: [{
459
520
  type: Component,
@@ -478,7 +539,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImpor
478
539
  '[attr.tabindex]': 'disabled ? -1 : 0',
479
540
  '(focus)': 'onFocusIn()',
480
541
  '(blur)': 'onFocusOut($event)',
481
- }, template: "<ngs-select\n #ngsSelect\n [value]=\"value\"\n (selectionChange)=\"onSelectionChange($event)\"\n (opened)=\"onSelectOpened()\"\n (closed)=\"onSelectClosed()\"\n [placeholder]=\"placeholder\"\n [required]=\"isRequiredSignal()\"\n [disabled]=\"isDisabledSignal()\">\n <ngs-select-trigger class=\"select-trigger\">\n @let selectedCountry = selectedCountryDisplay();\n @if (selectedCountry) {\n <span class=\"ngs-select-trigger-content\">\n <span class=\"ngs-select-trigger-icon\">{{ selectedCountry.flag }}</span>\n <span class=\"ngs-select-trigger-text\">\n {{ selectedCountry.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ selectedCountry.code }})</span>\n }\n </span>\n </span>\n }\n\n @if (!selectedCountryDisplay() && placeholder) {\n <span class=\"ngs-select-trigger-text placeholder-text\">\n {{ placeholder }}\n </span>\n }\n </ngs-select-trigger>\n\n <ngs-select-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 class=\"w-full text-sm focus:outline-none border-b border-surface-container-high 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-select-header>\n\n @for (country of filteredCountries(); track country.code) {\n <ngs-option [value]=\"country.code\">\n <span class=\"select-option-content\">\n <span class=\"select-option-icon\">{{ country.flag }}</span>\n <span class=\"select-option-text\">\n {{ country.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ country.code }})</span>\n }\n </span>\n </span>\n </ngs-option>\n } @empty {\n @if (searchTerm()) {\n <div class=\"text-sm px-4 py-3\">\n <span i18n>Country not found</span>.\n </div>\n }\n }\n</ngs-select>\n", styles: [":host{display:block}:host .ngs-select-trigger-icon,:host .select-option-icon{font-size:1.25rem}:host .select-option-content{display:flex;align-items:center;gap:var(--ngs-dropdown-item-gap, calc(var(--spacing, .25rem) * 2));min-width:0;width:100%;height:100%;overflow:hidden;white-space:nowrap}:host .select-option-icon{flex:none;line-height:0}:host .select-option-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .code{text-transform:uppercase;color:var(--ngs-color-neutral-500)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
542
+ }, template: "<ngs-select\n #ngsSelect\n [value]=\"value\"\n (selectionChange)=\"onSelectionChange($event)\"\n (opened)=\"onSelectOpened()\"\n (closed)=\"onSelectClosed()\"\n [placeholder]=\"placeholder\"\n [required]=\"isRequiredSignal()\"\n [disabled]=\"isDisabledSignal()\">\n <ngs-select-trigger class=\"select-trigger\">\n @let selectedCountry = selectedCountryDisplay();\n @if (selectedCountry) {\n <span class=\"ngs-select-trigger-content\">\n <span class=\"flag-icon\" aria-hidden=\"true\">{{ selectedCountry.flag }}</span>\n <span class=\"ngs-select-trigger-text\">\n {{ selectedCountry.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ selectedCountry.code }})</span>\n }\n </span>\n </span>\n }\n\n @if (!selectedCountryDisplay() && placeholder) {\n <span class=\"ngs-select-trigger-text placeholder-text\">\n {{ placeholder }}\n </span>\n }\n </ngs-select-trigger>\n\n <ngs-select-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-surface-container-high 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-select-header>\n\n @for (country of visibleCountries(); track country.code) {\n <ngs-option [value]=\"country.code\">\n <div class=\"flex items-center gap-2\">\n <span class=\"select-option-icon text-2xl\" aria-hidden=\"true\">{{ country.flag }}</span>\n <span class=\"select-option-text\">\n {{ country.name }}\n @if (showCountryCode()) {\n <span class=\"code\">({{ country.code }})</span>\n }\n </span>\n </div>\n </ngs-option>\n } @empty {\n @if (searchTerm()) {\n <div class=\"text-sm px-4 py-3\">\n <span i18n>Country not found</span>.\n </div>\n }\n }\n\n @if (visibleCountryCount() < filteredCountries().length) {\n <div class=\"select-loading\">\n Loading more countries...\n </div>\n }\n</ngs-select>\n", styles: [":host{display:block}:host .flag-icon{display:inline-flex;align-items:center;justify-content:center;width:22px;font-size:22px;line-height:1}:host .select-option-content{display:flex;align-items:center;gap:var(--ngs-dropdown-item-gap);min-width:0;width:100%;height:100%;overflow:hidden;white-space:nowrap}:host .select-option-text{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host .code{text-transform:uppercase;color:var(--ngs-color-neutral-500)}:host .select-loading{padding:calc(var(--spacing, .25rem) * 2) calc(var(--spacing, .25rem) * 4);color:var(--ngs-color-on-surface-variant);font-size:var(--ngs-font-size-sm)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
482
543
  }], ctorParameters: () => [], propDecorators: { searchTerm: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchTerm", required: false }] }, { type: i0.Output, args: ["searchTermChange"] }], placeholderInputSignal: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], isRequiredSignal: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }, { type: i0.Output, args: ["requiredChange"] }], isDisabledSignal: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], showCountryCode: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCountryCode", required: false }] }], ngsSelect: [{ type: i0.ViewChild, args: ['ngsSelect', { isSignal: true }] }], searchInput: [{ type: i0.ViewChild, args: ['searchInput', { isSignal: true }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
483
544
 
484
545
  /**