tecnualng 21.1.9 → 21.1.10

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, ChangeDetectionStrategy, ViewEncapsulation, Component, inject, model, signal, computed, ElementRef, DestroyRef, effect, HostListener, Directive, contentChild, forwardRef, viewChild, TemplateRef, contentChildren, Injectable, createComponent, Input, output, ContentChildren, ViewContainerRef, booleanAttribute } from '@angular/core';
2
+ import { input, ChangeDetectionStrategy, ViewEncapsulation, Component, inject, model, signal, computed, ElementRef, DestroyRef, effect, HostListener, Directive, contentChild, forwardRef, viewChild, TemplateRef, contentChildren, Injectable, createComponent, Input, output, ContentChildren, ViewContainerRef, booleanAttribute, untracked } from '@angular/core';
3
3
  import * as i1$2 from '@angular/forms';
4
4
  import { NgControl, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
5
5
  import * as i1 from '@angular/common';
@@ -1780,17 +1780,18 @@ class TngSelectPanelComponent {
1780
1780
  this.optionSelected.emit(index);
1781
1781
  }
1782
1782
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngSelectPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1783
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TngSelectPanelComponent, isStandalone: true, selector: "tng-select-panel", outputs: { optionSelected: "optionSelected", searchQueryChanged: "searchQueryChanged", closeRequested: "closeRequested" }, ngImport: i0, template: "<div class=\"tng-select-panel\" \n role=\"listbox\"\n [attr.aria-multiselectable]=\"enableMulti()\">\n \n @if (enableSearch()) {\n <div class=\"tng-select-search\">\n <input \n type=\"text\"\n class=\"tng-select-search-input\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n placeholder=\"Search...\"\n aria-label=\"Search options\"\n (click)=\"$event.stopPropagation()\"\n />\n <i class=\"fa fa-search tng-select-search-icon\"></i>\n </div>\n }\n \n <div class=\"tng-select-options\" role=\"list\">\n @if (options().length === 0) {\n <div class=\"tng-select-no-results\">\n No options found\n </div>\n }\n \n @for (option of options(); track $index) {\n <div \n class=\"tng-select-option\"\n [class.selected]=\"isSelected($index)\"\n [class.disabled]=\"option.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isSelected($index)\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"onOptionClick($index, option)\"\n >\n @if (enableMulti()) {\n <input \n type=\"checkbox\"\n class=\"tng-select-checkbox\"\n [checked]=\"isSelected($index)\"\n [disabled]=\"option.disabled\"\n tabindex=\"-1\"\n />\n }\n <span class=\"tng-select-option-label\">{{ option.label }}</span>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.tng-select-panel{background:var(--tng-surface, #ffffff);border:1px solid var(--tng-border, #e0e0e0);border-radius:var(--tng-border-radius, 4px);box-shadow:var(--tng-shadow-md, 0 4px 8px rgba(0, 0, 0, .12));overflow:hidden;animation:slideDown .2s cubic-bezier(.4,0,.2,1)}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.tng-select-search{position:relative;padding:.75rem;border-bottom:1px solid var(--tng-border, #e0e0e0)}.tng-select-search-input{width:100%;padding:.5rem 2rem .5rem .75rem;border:1px solid var(--tng-border, #e0e0e0);border-radius:var(--tng-border-radius, 4px);font-size:.9rem;color:var(--tng-text, #333);outline:none;transition:border-color .2s ease}.tng-select-search-input:focus{border-color:var(--tng-primary, #00f2ff)}.tng-select-search-icon{position:absolute;right:1.5rem;top:50%;transform:translateY(-50%);color:var(--tng-text-secondary, #757575);pointer-events:none}.tng-select-options{max-height:300px;overflow-y:auto;padding:.25rem 0}.tng-select-options::-webkit-scrollbar{width:8px}.tng-select-options::-webkit-scrollbar-track{background:var(--tng-background, #fafafa)}.tng-select-options::-webkit-scrollbar-thumb{background:var(--tng-border, #e0e0e0);border-radius:4px}.tng-select-options::-webkit-scrollbar-thumb:hover{background:var(--tng-text-secondary, #757575)}.tng-select-option{display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem;cursor:pointer;transition:background-color .15s ease;-webkit-user-select:none;user-select:none}.tng-select-option:hover:not(.disabled){background:var(--tng-background, #fafafa)}.tng-select-option.selected{background:#00f2ff1a;color:var(--tng-primary, #00f2ff)}.tng-select-option.disabled{opacity:.5;cursor:not-allowed}.tng-select-checkbox{appearance:none;-webkit-appearance:none;-moz-appearance:none;width:18px;height:18px;min-width:18px;min-height:18px;border:2px solid var(--tng-border, #999);border-radius:var(--tng-border-radius, 4px);background-color:var(--tng-surface, #ffffff);cursor:pointer;position:relative;transition:all .2s cubic-bezier(.4,0,.2,1);margin:0;pointer-events:none}.tng-select-checkbox:checked{background-color:var(--tng-primary, #00f2ff);border-color:var(--tng-primary, #00f2ff)}.tng-select-checkbox:checked:before{content:\"\";position:absolute;width:4px;height:8px;border:solid var(--tng-primary-contrast, #000000);border-width:0 2px 2px 0;transform:rotate(45deg);top:2px;left:5px}.tng-select-checkbox:disabled{opacity:.5;cursor:not-allowed}.tng-select-option-label{flex:1;font-size:.95rem}.tng-select-no-results{padding:1.5rem 1rem;text-align:center;color:var(--tng-text-secondary, #757575);font-size:.9rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1783
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TngSelectPanelComponent, isStandalone: true, selector: "tng-select-panel", outputs: { optionSelected: "optionSelected", searchQueryChanged: "searchQueryChanged", closeRequested: "closeRequested" }, ngImport: i0, template: "<div class=\"tng-select-panel\" \n role=\"listbox\"\n [attr.aria-multiselectable]=\"enableMulti()\">\n \n @if (enableSearch()) {\n <div class=\"tng-select-search\">\n <input \n type=\"text\"\n class=\"tng-select-search-input\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n placeholder=\"Search...\"\n aria-label=\"Search options\"\n (click)=\"$event.stopPropagation()\"\n />\n <i class=\"fa fa-search tng-select-search-icon\"></i>\n </div>\n }\n \n <div class=\"tng-select-options\" role=\"list\">\n @if (options().length === 0) {\n <div class=\"tng-select-no-results\">\n No options found\n </div>\n }\n \n @for (option of options(); track $index) {\n <div \n class=\"tng-select-option\"\n [class.selected]=\"isSelected($index)\"\n [class.disabled]=\"option.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isSelected($index)\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"onOptionClick($index, option)\"\n >\n @if (enableMulti()) {\n <input \n type=\"checkbox\"\n class=\"tng-select-checkbox\"\n [checked]=\"isSelected($index)\"\n [disabled]=\"option.disabled\"\n tabindex=\"-1\"\n />\n }\n <span class=\"tng-select-option-label\">{{ option.label }}</span>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.tng-select-panel{background:var(--tng-surface, #ffffff);border:1px solid var(--tng-border, #e0e0e0);border-radius:var(--tng-border-radius, 4px);box-shadow:var(--tng-shadow-md, 0 4px 8px rgba(0, 0, 0, .12));overflow:hidden;animation:slideDown .2s cubic-bezier(.4,0,.2,1)}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.tng-select-search{position:relative;padding:.75rem;border-bottom:1px solid var(--tng-border, #e0e0e0)}.tng-select-search-input{width:100%;padding:.5rem 2rem .5rem .75rem;border:1px solid var(--tng-border, #e0e0e0);border-radius:var(--tng-border-radius, 4px);font-size:.9rem;color:var(--tng-text, #333);background-color:var(--tng-surface, #ffffff);outline:none;transition:border-color .2s ease}.tng-select-search-input:focus{border-color:var(--tng-primary, #00f2ff)}.tng-select-search-icon{position:absolute;right:1.5rem;top:50%;transform:translateY(-50%);color:var(--tng-text-secondary, #757575);pointer-events:none}.tng-select-options{max-height:300px;overflow-y:auto;padding:.25rem 0}.tng-select-options::-webkit-scrollbar{width:8px}.tng-select-options::-webkit-scrollbar-track{background:var(--tng-background, #fafafa)}.tng-select-options::-webkit-scrollbar-thumb{background:var(--tng-border, #e0e0e0);border-radius:4px}.tng-select-options::-webkit-scrollbar-thumb:hover{background:var(--tng-text-secondary, #757575)}.tng-select-option{display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem;cursor:pointer;transition:background-color .15s ease;-webkit-user-select:none;user-select:none}.tng-select-option:hover:not(.disabled){background:var(--tng-background, #fafafa)}.tng-select-option.selected{background:#00f2ff1a;color:var(--tng-primary, #00f2ff)}.tng-select-option.disabled{opacity:.5;cursor:not-allowed}.tng-select-checkbox{appearance:none;-webkit-appearance:none;-moz-appearance:none;width:18px;height:18px;min-width:18px;min-height:18px;border:2px solid var(--tng-border, #999);border-radius:var(--tng-border-radius, 4px);background-color:var(--tng-surface, #ffffff);cursor:pointer;position:relative;transition:all .2s cubic-bezier(.4,0,.2,1);margin:0;pointer-events:none}.tng-select-checkbox:checked{background-color:var(--tng-primary, #00f2ff);border-color:var(--tng-primary, #00f2ff)}.tng-select-checkbox:checked:before{content:\"\";position:absolute;width:4px;height:8px;border:solid var(--tng-primary-contrast, #000000);border-width:0 2px 2px 0;transform:rotate(45deg);top:2px;left:5px}.tng-select-checkbox:disabled{opacity:.5;cursor:not-allowed}.tng-select-option-label{flex:1;font-size:.95rem}.tng-select-no-results{padding:1.5rem 1rem;text-align:center;color:var(--tng-text-secondary, #757575);font-size:.9rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1784
1784
  }
1785
1785
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngSelectPanelComponent, decorators: [{
1786
1786
  type: Component,
1787
- args: [{ selector: 'tng-select-panel', standalone: true, imports: [CommonModule, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"tng-select-panel\" \n role=\"listbox\"\n [attr.aria-multiselectable]=\"enableMulti()\">\n \n @if (enableSearch()) {\n <div class=\"tng-select-search\">\n <input \n type=\"text\"\n class=\"tng-select-search-input\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n placeholder=\"Search...\"\n aria-label=\"Search options\"\n (click)=\"$event.stopPropagation()\"\n />\n <i class=\"fa fa-search tng-select-search-icon\"></i>\n </div>\n }\n \n <div class=\"tng-select-options\" role=\"list\">\n @if (options().length === 0) {\n <div class=\"tng-select-no-results\">\n No options found\n </div>\n }\n \n @for (option of options(); track $index) {\n <div \n class=\"tng-select-option\"\n [class.selected]=\"isSelected($index)\"\n [class.disabled]=\"option.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isSelected($index)\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"onOptionClick($index, option)\"\n >\n @if (enableMulti()) {\n <input \n type=\"checkbox\"\n class=\"tng-select-checkbox\"\n [checked]=\"isSelected($index)\"\n [disabled]=\"option.disabled\"\n tabindex=\"-1\"\n />\n }\n <span class=\"tng-select-option-label\">{{ option.label }}</span>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.tng-select-panel{background:var(--tng-surface, #ffffff);border:1px solid var(--tng-border, #e0e0e0);border-radius:var(--tng-border-radius, 4px);box-shadow:var(--tng-shadow-md, 0 4px 8px rgba(0, 0, 0, .12));overflow:hidden;animation:slideDown .2s cubic-bezier(.4,0,.2,1)}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.tng-select-search{position:relative;padding:.75rem;border-bottom:1px solid var(--tng-border, #e0e0e0)}.tng-select-search-input{width:100%;padding:.5rem 2rem .5rem .75rem;border:1px solid var(--tng-border, #e0e0e0);border-radius:var(--tng-border-radius, 4px);font-size:.9rem;color:var(--tng-text, #333);outline:none;transition:border-color .2s ease}.tng-select-search-input:focus{border-color:var(--tng-primary, #00f2ff)}.tng-select-search-icon{position:absolute;right:1.5rem;top:50%;transform:translateY(-50%);color:var(--tng-text-secondary, #757575);pointer-events:none}.tng-select-options{max-height:300px;overflow-y:auto;padding:.25rem 0}.tng-select-options::-webkit-scrollbar{width:8px}.tng-select-options::-webkit-scrollbar-track{background:var(--tng-background, #fafafa)}.tng-select-options::-webkit-scrollbar-thumb{background:var(--tng-border, #e0e0e0);border-radius:4px}.tng-select-options::-webkit-scrollbar-thumb:hover{background:var(--tng-text-secondary, #757575)}.tng-select-option{display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem;cursor:pointer;transition:background-color .15s ease;-webkit-user-select:none;user-select:none}.tng-select-option:hover:not(.disabled){background:var(--tng-background, #fafafa)}.tng-select-option.selected{background:#00f2ff1a;color:var(--tng-primary, #00f2ff)}.tng-select-option.disabled{opacity:.5;cursor:not-allowed}.tng-select-checkbox{appearance:none;-webkit-appearance:none;-moz-appearance:none;width:18px;height:18px;min-width:18px;min-height:18px;border:2px solid var(--tng-border, #999);border-radius:var(--tng-border-radius, 4px);background-color:var(--tng-surface, #ffffff);cursor:pointer;position:relative;transition:all .2s cubic-bezier(.4,0,.2,1);margin:0;pointer-events:none}.tng-select-checkbox:checked{background-color:var(--tng-primary, #00f2ff);border-color:var(--tng-primary, #00f2ff)}.tng-select-checkbox:checked:before{content:\"\";position:absolute;width:4px;height:8px;border:solid var(--tng-primary-contrast, #000000);border-width:0 2px 2px 0;transform:rotate(45deg);top:2px;left:5px}.tng-select-checkbox:disabled{opacity:.5;cursor:not-allowed}.tng-select-option-label{flex:1;font-size:.95rem}.tng-select-no-results{padding:1.5rem 1rem;text-align:center;color:var(--tng-text-secondary, #757575);font-size:.9rem}\n"] }]
1787
+ args: [{ selector: 'tng-select-panel', standalone: true, imports: [CommonModule, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"tng-select-panel\" \n role=\"listbox\"\n [attr.aria-multiselectable]=\"enableMulti()\">\n \n @if (enableSearch()) {\n <div class=\"tng-select-search\">\n <input \n type=\"text\"\n class=\"tng-select-search-input\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n placeholder=\"Search...\"\n aria-label=\"Search options\"\n (click)=\"$event.stopPropagation()\"\n />\n <i class=\"fa fa-search tng-select-search-icon\"></i>\n </div>\n }\n \n <div class=\"tng-select-options\" role=\"list\">\n @if (options().length === 0) {\n <div class=\"tng-select-no-results\">\n No options found\n </div>\n }\n \n @for (option of options(); track $index) {\n <div \n class=\"tng-select-option\"\n [class.selected]=\"isSelected($index)\"\n [class.disabled]=\"option.disabled\"\n role=\"option\"\n [attr.aria-selected]=\"isSelected($index)\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"onOptionClick($index, option)\"\n >\n @if (enableMulti()) {\n <input \n type=\"checkbox\"\n class=\"tng-select-checkbox\"\n [checked]=\"isSelected($index)\"\n [disabled]=\"option.disabled\"\n tabindex=\"-1\"\n />\n }\n <span class=\"tng-select-option-label\">{{ option.label }}</span>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}.tng-select-panel{background:var(--tng-surface, #ffffff);border:1px solid var(--tng-border, #e0e0e0);border-radius:var(--tng-border-radius, 4px);box-shadow:var(--tng-shadow-md, 0 4px 8px rgba(0, 0, 0, .12));overflow:hidden;animation:slideDown .2s cubic-bezier(.4,0,.2,1)}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}.tng-select-search{position:relative;padding:.75rem;border-bottom:1px solid var(--tng-border, #e0e0e0)}.tng-select-search-input{width:100%;padding:.5rem 2rem .5rem .75rem;border:1px solid var(--tng-border, #e0e0e0);border-radius:var(--tng-border-radius, 4px);font-size:.9rem;color:var(--tng-text, #333);background-color:var(--tng-surface, #ffffff);outline:none;transition:border-color .2s ease}.tng-select-search-input:focus{border-color:var(--tng-primary, #00f2ff)}.tng-select-search-icon{position:absolute;right:1.5rem;top:50%;transform:translateY(-50%);color:var(--tng-text-secondary, #757575);pointer-events:none}.tng-select-options{max-height:300px;overflow-y:auto;padding:.25rem 0}.tng-select-options::-webkit-scrollbar{width:8px}.tng-select-options::-webkit-scrollbar-track{background:var(--tng-background, #fafafa)}.tng-select-options::-webkit-scrollbar-thumb{background:var(--tng-border, #e0e0e0);border-radius:4px}.tng-select-options::-webkit-scrollbar-thumb:hover{background:var(--tng-text-secondary, #757575)}.tng-select-option{display:flex;align-items:center;gap:.75rem;padding:.75rem 1rem;cursor:pointer;transition:background-color .15s ease;-webkit-user-select:none;user-select:none}.tng-select-option:hover:not(.disabled){background:var(--tng-background, #fafafa)}.tng-select-option.selected{background:#00f2ff1a;color:var(--tng-primary, #00f2ff)}.tng-select-option.disabled{opacity:.5;cursor:not-allowed}.tng-select-checkbox{appearance:none;-webkit-appearance:none;-moz-appearance:none;width:18px;height:18px;min-width:18px;min-height:18px;border:2px solid var(--tng-border, #999);border-radius:var(--tng-border-radius, 4px);background-color:var(--tng-surface, #ffffff);cursor:pointer;position:relative;transition:all .2s cubic-bezier(.4,0,.2,1);margin:0;pointer-events:none}.tng-select-checkbox:checked{background-color:var(--tng-primary, #00f2ff);border-color:var(--tng-primary, #00f2ff)}.tng-select-checkbox:checked:before{content:\"\";position:absolute;width:4px;height:8px;border:solid var(--tng-primary-contrast, #000000);border-width:0 2px 2px 0;transform:rotate(45deg);top:2px;left:5px}.tng-select-checkbox:disabled{opacity:.5;cursor:not-allowed}.tng-select-option-label{flex:1;font-size:.95rem}.tng-select-no-results{padding:1.5rem 1rem;text-align:center;color:var(--tng-text-secondary, #757575);font-size:.9rem}\n"] }]
1788
1788
  }], propDecorators: { optionSelected: [{ type: i0.Output, args: ["optionSelected"] }], searchQueryChanged: [{ type: i0.Output, args: ["searchQueryChanged"] }], closeRequested: [{ type: i0.Output, args: ["closeRequested"] }] } });
1789
1789
 
1790
1790
  class TngSelectDirective {
1791
1791
  el = inject((ElementRef));
1792
1792
  viewContainerRef = inject(ViewContainerRef);
1793
1793
  ngControl = inject(NgControl, { optional: true, self: true });
1794
+ destroyRef = inject(DestroyRef);
1794
1795
  // Inputs
1795
1796
  enableMulti = input(false, ...(ngDevMode ? [{ debugName: "enableMulti" }] : []));
1796
1797
  // Support native multiple attribute
@@ -1805,7 +1806,23 @@ class TngSelectDirective {
1805
1806
  isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
1806
1807
  searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
1807
1808
  _options = signal([], ...(ngDevMode ? [{ debugName: "_options" }] : []));
1808
- _selectedIndices = signal([], ...(ngDevMode ? [{ debugName: "_selectedIndices" }] : []));
1809
+ _selectedIndices = signal([], ...(ngDevMode ? [{ debugName: "_selectedIndices", equal: (a, b) => {
1810
+ if (a === b)
1811
+ return true;
1812
+ if (a.length !== b.length)
1813
+ return false;
1814
+ const sortedA = [...a].sort();
1815
+ const sortedB = [...b].sort();
1816
+ return sortedA.every((val, index) => val === sortedB[index]);
1817
+ } }] : [{ equal: (a, b) => {
1818
+ if (a === b)
1819
+ return true;
1820
+ if (a.length !== b.length)
1821
+ return false;
1822
+ const sortedA = [...a].sort();
1823
+ const sortedB = [...b].sort();
1824
+ return sortedA.every((val, index) => val === sortedB[index]);
1825
+ } }]));
1809
1826
  // Component reference for the panel
1810
1827
  panelRef = null;
1811
1828
  // Generated trigger element
@@ -1837,16 +1854,29 @@ class TngSelectDirective {
1837
1854
  return selected.map(opt => opt.label).join(', ');
1838
1855
  }, ...(ngDevMode ? [{ debugName: "displayText" }] : []));
1839
1856
  constructor() {
1840
- // Sync selected values with model
1857
+ // Sync selected values with model (Output)
1841
1858
  effect(() => {
1842
1859
  const selected = this.selectedOptions();
1860
+ // Use untracked to avoid loop if selectedValues write triggers immediate read dependency? No.
1843
1861
  this.selectedValues.set(selected.map(opt => opt.value));
1844
1862
  });
1863
+ // Sync model with internal (Input)
1864
+ effect(() => {
1865
+ const values = this.selectedValues();
1866
+ // Avoid infinite loop by checking if values actally represent a change
1867
+ const currentSelected = untracked(() => this.selectedOptions());
1868
+ const currentValues = currentSelected.map(o => o.value);
1869
+ // Simple equality check (value-based)
1870
+ if (values.length !== currentValues.length || !values.every((v, i) => v == currentValues[i])) { // weak eq
1871
+ this.updateSelectionFromValue(values);
1872
+ }
1873
+ });
1845
1874
  // Update form control value
1846
1875
  effect(() => {
1847
1876
  if (this.ngControl?.control) {
1848
1877
  const values = this.selectedValues();
1849
1878
  const newValue = this.isMulti() ? values : (values[0] ?? null);
1879
+ // Only setValue if changed? internal control handles checks usually
1850
1880
  this.ngControl.control.setValue(newValue, { emitEvent: false });
1851
1881
  }
1852
1882
  });
@@ -1874,6 +1904,33 @@ class TngSelectDirective {
1874
1904
  }
1875
1905
  });
1876
1906
  }
1907
+ ngOnInit() {
1908
+ if (this.ngControl) {
1909
+ this.ngControl.valueChanges?.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((val) => {
1910
+ // Find indices matching value
1911
+ this.updateSelectionFromValue(val);
1912
+ });
1913
+ }
1914
+ }
1915
+ updateSelectionFromValue(value) {
1916
+ const opts = this._options();
1917
+ const indices = [];
1918
+ if (this.isMulti()) {
1919
+ const valArray = Array.isArray(value) ? value : (value ? [value] : []);
1920
+ valArray.forEach((v) => {
1921
+ const idx = opts.findIndex(o => o.value == v); // weak equality for numbers/strings?
1922
+ if (idx !== -1)
1923
+ indices.push(idx);
1924
+ });
1925
+ }
1926
+ else {
1927
+ const idx = opts.findIndex(o => o.value == value);
1928
+ if (idx !== -1)
1929
+ indices.push(idx);
1930
+ }
1931
+ this._selectedIndices.set(indices);
1932
+ this.updateNativeSelect(false);
1933
+ }
1877
1934
  ngAfterViewInit() {
1878
1935
  this.loadOptionsFromSelect();
1879
1936
  this.loadInitialSelection();
@@ -2078,7 +2135,7 @@ class TngSelectDirective {
2078
2135
  // Update native select
2079
2136
  this.updateNativeSelect();
2080
2137
  }
2081
- updateNativeSelect() {
2138
+ updateNativeSelect(emitEvents = true) {
2082
2139
  const selectEl = this.el.nativeElement;
2083
2140
  const selectedIndices = this._selectedIndices();
2084
2141
  // Clear all selections
@@ -2091,10 +2148,12 @@ class TngSelectDirective {
2091
2148
  selectEl.options[idx].selected = true;
2092
2149
  }
2093
2150
  });
2094
- // Trigger change event
2095
- selectEl.dispatchEvent(new Event('change', { bubbles: true }));
2096
- // Also trigger input event for some frameworks
2097
- selectEl.dispatchEvent(new Event('input', { bubbles: true }));
2151
+ if (emitEvents) {
2152
+ // Trigger change event
2153
+ selectEl.dispatchEvent(new Event('change', { bubbles: true }));
2154
+ // Also trigger input event for some frameworks
2155
+ selectEl.dispatchEvent(new Event('input', { bubbles: true }));
2156
+ }
2098
2157
  }
2099
2158
  onDocumentClick = (event) => {
2100
2159
  const target = event.target;
@@ -2136,6 +2195,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
2136
2195
  }] } });
2137
2196
 
2138
2197
  class TngSelectComponent {
2198
+ ngControl = inject(NgControl, { optional: true, self: true });
2139
2199
  // Inputs
2140
2200
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
2141
2201
  options = input.required(...(ngDevMode ? [{ debugName: "options" }] : []));
@@ -2167,18 +2227,20 @@ class TngSelectComponent {
2167
2227
  onChange = () => { };
2168
2228
  onTouched = () => { };
2169
2229
  constructor() {
2170
- // Sync model changes to CVA
2171
- effect(() => {
2172
- const val = this.value();
2173
- // Avoid circular updates if possible, but for now just emit
2174
- if (this.enableMulti()) {
2175
- this.onChange(val);
2176
- }
2177
- else {
2178
- this.onChange(val.length > 0 ? val[0] : null);
2179
- }
2180
- this.onTouched();
2181
- });
2230
+ if (this.ngControl) {
2231
+ this.ngControl.valueAccessor = this;
2232
+ }
2233
+ }
2234
+ onSelectionChange(newValues) {
2235
+ this.value.set(newValues);
2236
+ // Avoid circular updates if possible, but for now just emit
2237
+ if (this.enableMulti()) {
2238
+ this.onChange(newValues);
2239
+ }
2240
+ else {
2241
+ this.onChange(newValues.length > 0 ? newValues[0] : null);
2242
+ }
2243
+ this.onTouched();
2182
2244
  }
2183
2245
  onDisplayClick(event) {
2184
2246
  if (this.effectiveDisabled())
@@ -2211,23 +2273,11 @@ class TngSelectComponent {
2211
2273
  this.cvaDisabled.set(isDisabled);
2212
2274
  }
2213
2275
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2214
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TngSelectComponent, isStandalone: true, selector: "tng-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, enableMulti: { classPropertyName: "enableMulti", publicName: "enableMulti", isSignal: true, isRequired: false, transformFunction: null }, enableSearch: { classPropertyName: "enableSearch", publicName: "enableSearch", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, providers: [
2215
- {
2216
- provide: NG_VALUE_ACCESSOR,
2217
- useExisting: forwardRef(() => TngSelectComponent),
2218
- multi: true
2219
- }
2220
- ], viewQueries: [{ propertyName: "selectDirective", first: true, predicate: TngSelectDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"tng-select-wrapper\" [class.tng-select-open]=\"selectDirective()?.isOpen()\">\n @if (label()) {\n <label class=\"tng-select-label\" [attr.for]=\"selectId()\">\n {{ label() }}\n </label>\n }\n\n <div class=\"tng-select-container\">\n <select\n [id]=\"selectId()\"\n tngSelect\n [enableMulti]=\"enableMulti()\"\n [enableSearch]=\"enableSearch()\"\n [placeholder]=\"placeholder()\"\n [customTrigger]=\"true\"\n [multiple]=\"enableMulti()\"\n [triggerRef]=\"triggerDisplay\"\n [(selectedValues)]=\"value\"\n [disabled]=\"effectiveDisabled()\"\n [attr.aria-label]=\"ariaLabel() || label()\"\n >\n @for (option of options(); track option.value) {\n <option [value]=\"option.value\" [disabled]=\"option.disabled\">\n {{ option.label }}\n </option>\n }\n </select>\n\n <div\n class=\"tng-select-display\"\n #triggerDisplay\n [class.disabled]=\"effectiveDisabled()\"\n (click)=\"onDisplayClick($event)\"\n >\n <span class=\"tng-select-display-text\">\n {{ displayText() }}\n </span>\n <i class=\"fa fa-chevron-down tng-select-arrow\"></i>\n </div>\n </div>\n\n @if (hint()) {\n <div class=\"tng-select-hint\">\n {{ hint() }}\n </div>\n }\n</div>\n", styles: [":host{display:block;margin-bottom:1.5rem;font-family:var(--tng-font-family, \"Inter\", sans-serif)}.tng-select-wrapper{width:100%}.tng-select-label{display:block;margin-bottom:.5rem;font-size:.9rem;font-weight:500;color:var(--tng-text, #333)}.tng-select-container{position:relative}.tng-select-display{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.75rem 1rem;border:1px solid var(--tng-border, #999);border-radius:var(--tng-border-radius, 4px);background:var(--tng-surface, #ffffff);cursor:pointer;transition:all .2s ease;min-height:48px;font-family:var(--tng-font-family, \"Inter\", sans-serif)}.tng-select-display:hover:not(.disabled){border-color:var(--tng-text-secondary, #757575)}.tng-select-display.disabled{opacity:.6;cursor:not-allowed;background:var(--tng-background, #fafafa)}.tng-select-wrapper.tng-select-open .tng-select-display,.tng-select-display.tng-select-open{border-color:var(--tng-primary, #00f2ff);border-width:2px;padding:calc(.75rem - 1px) calc(1rem - 1px)}.tng-select-display-text{flex:1;color:var(--tng-text, #333);font-size:1rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tng-select-display-text:empty:before{content:attr(data-placeholder);color:var(--tng-text-secondary, #757575)}.tng-select-arrow{color:var(--tng-text-secondary, #757575);transition:transform .2s ease;font-size:.8rem}.tng-select-wrapper.tng-select-open .tng-select-arrow,.tng-select-display.tng-select-open .tng-select-arrow{transform:rotate(180deg)}.tng-select-hint{margin-top:.25rem;font-size:.85rem;color:var(--tng-text-secondary, #757575)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: TngSelectDirective, selector: "select[tngSelect]", inputs: ["enableMulti", "multiple", "enableSearch", "placeholder", "customTrigger", "triggerRef", "selectedValues"], outputs: ["selectedValuesChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2276
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TngSelectComponent, isStandalone: true, selector: "tng-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, enableMulti: { classPropertyName: "enableMulti", publicName: "enableMulti", isSignal: true, isRequired: false, transformFunction: null }, enableSearch: { classPropertyName: "enableSearch", publicName: "enableSearch", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, viewQueries: [{ propertyName: "selectDirective", first: true, predicate: TngSelectDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"tng-select-wrapper\" [class.tng-select-open]=\"selectDirective()?.isOpen()\">\n @if (label()) {\n <label class=\"tng-select-label\" [attr.for]=\"selectId()\">\n {{ label() }}\n </label>\n }\n\n <div class=\"tng-select-container\">\n <select\n [id]=\"selectId()\"\n tngSelect\n [enableMulti]=\"enableMulti()\"\n [enableSearch]=\"enableSearch()\"\n [placeholder]=\"placeholder()\"\n [customTrigger]=\"true\"\n [multiple]=\"enableMulti()\"\n [triggerRef]=\"triggerDisplay\"\n [selectedValues]=\"value()\"\n (selectedValuesChange)=\"onSelectionChange($event)\"\n [disabled]=\"effectiveDisabled()\"\n [attr.aria-label]=\"ariaLabel() || label()\"\n >\n @for (option of options(); track option.value) {\n <option [value]=\"option.value\" [disabled]=\"option.disabled\">\n {{ option.label }}\n </option>\n }\n </select>\n\n <div\n class=\"tng-select-display\"\n #triggerDisplay\n [class.disabled]=\"effectiveDisabled()\"\n (click)=\"onDisplayClick($event)\"\n >\n <span class=\"tng-select-display-text\">\n {{ displayText() }}\n </span>\n <i class=\"fa fa-chevron-down tng-select-arrow\"></i>\n </div>\n </div>\n\n @if (hint()) {\n <div class=\"tng-select-hint\">\n {{ hint() }}\n </div>\n }\n</div>\n", styles: [":host{display:block;margin-bottom:1.5rem;font-family:var(--tng-font-family, \"Inter\", sans-serif)}.tng-select-wrapper{width:100%}.tng-select-label{display:block;margin-bottom:.5rem;font-size:.9rem;font-weight:500;color:var(--tng-text, #333)}.tng-select-container{position:relative}.tng-select-display{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.75rem 1rem;border:1px solid var(--tng-border, #999);border-radius:var(--tng-border-radius, 4px);background:var(--tng-surface, #ffffff);cursor:pointer;transition:all .2s ease;min-height:48px;font-family:var(--tng-font-family, \"Inter\", sans-serif)}.tng-select-display:hover:not(.disabled){border-color:var(--tng-text-secondary, #757575)}.tng-select-display.disabled{opacity:.6;cursor:not-allowed;background:var(--tng-background, #fafafa)}.tng-select-wrapper.tng-select-open .tng-select-display,.tng-select-display.tng-select-open{border-color:var(--tng-primary, #00f2ff);border-width:2px;padding:calc(.75rem - 1px) calc(1rem - 1px)}.tng-select-display-text{flex:1;color:var(--tng-text, #333);font-size:1rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tng-select-display-text:empty:before{content:attr(data-placeholder);color:var(--tng-text-secondary, #757575)}.tng-select-arrow{color:var(--tng-text-secondary, #757575);transition:transform .2s ease;font-size:.8rem}.tng-select-wrapper.tng-select-open .tng-select-arrow,.tng-select-display.tng-select-open .tng-select-arrow{transform:rotate(180deg)}.tng-select-hint{margin-top:.25rem;font-size:.85rem;color:var(--tng-text-secondary, #757575)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: TngSelectDirective, selector: "select[tngSelect]", inputs: ["enableMulti", "multiple", "enableSearch", "placeholder", "customTrigger", "triggerRef", "selectedValues"], outputs: ["selectedValuesChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
2221
2277
  }
2222
2278
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TngSelectComponent, decorators: [{
2223
2279
  type: Component,
2224
- args: [{ selector: 'tng-select', standalone: true, imports: [CommonModule, FormsModule, TngSelectDirective], providers: [
2225
- {
2226
- provide: NG_VALUE_ACCESSOR,
2227
- useExisting: forwardRef(() => TngSelectComponent),
2228
- multi: true
2229
- }
2230
- ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"tng-select-wrapper\" [class.tng-select-open]=\"selectDirective()?.isOpen()\">\n @if (label()) {\n <label class=\"tng-select-label\" [attr.for]=\"selectId()\">\n {{ label() }}\n </label>\n }\n\n <div class=\"tng-select-container\">\n <select\n [id]=\"selectId()\"\n tngSelect\n [enableMulti]=\"enableMulti()\"\n [enableSearch]=\"enableSearch()\"\n [placeholder]=\"placeholder()\"\n [customTrigger]=\"true\"\n [multiple]=\"enableMulti()\"\n [triggerRef]=\"triggerDisplay\"\n [(selectedValues)]=\"value\"\n [disabled]=\"effectiveDisabled()\"\n [attr.aria-label]=\"ariaLabel() || label()\"\n >\n @for (option of options(); track option.value) {\n <option [value]=\"option.value\" [disabled]=\"option.disabled\">\n {{ option.label }}\n </option>\n }\n </select>\n\n <div\n class=\"tng-select-display\"\n #triggerDisplay\n [class.disabled]=\"effectiveDisabled()\"\n (click)=\"onDisplayClick($event)\"\n >\n <span class=\"tng-select-display-text\">\n {{ displayText() }}\n </span>\n <i class=\"fa fa-chevron-down tng-select-arrow\"></i>\n </div>\n </div>\n\n @if (hint()) {\n <div class=\"tng-select-hint\">\n {{ hint() }}\n </div>\n }\n</div>\n", styles: [":host{display:block;margin-bottom:1.5rem;font-family:var(--tng-font-family, \"Inter\", sans-serif)}.tng-select-wrapper{width:100%}.tng-select-label{display:block;margin-bottom:.5rem;font-size:.9rem;font-weight:500;color:var(--tng-text, #333)}.tng-select-container{position:relative}.tng-select-display{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.75rem 1rem;border:1px solid var(--tng-border, #999);border-radius:var(--tng-border-radius, 4px);background:var(--tng-surface, #ffffff);cursor:pointer;transition:all .2s ease;min-height:48px;font-family:var(--tng-font-family, \"Inter\", sans-serif)}.tng-select-display:hover:not(.disabled){border-color:var(--tng-text-secondary, #757575)}.tng-select-display.disabled{opacity:.6;cursor:not-allowed;background:var(--tng-background, #fafafa)}.tng-select-wrapper.tng-select-open .tng-select-display,.tng-select-display.tng-select-open{border-color:var(--tng-primary, #00f2ff);border-width:2px;padding:calc(.75rem - 1px) calc(1rem - 1px)}.tng-select-display-text{flex:1;color:var(--tng-text, #333);font-size:1rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tng-select-display-text:empty:before{content:attr(data-placeholder);color:var(--tng-text-secondary, #757575)}.tng-select-arrow{color:var(--tng-text-secondary, #757575);transition:transform .2s ease;font-size:.8rem}.tng-select-wrapper.tng-select-open .tng-select-arrow,.tng-select-display.tng-select-open .tng-select-arrow{transform:rotate(180deg)}.tng-select-hint{margin-top:.25rem;font-size:.85rem;color:var(--tng-text-secondary, #757575)}\n"] }]
2280
+ args: [{ selector: 'tng-select', standalone: true, imports: [CommonModule, FormsModule, TngSelectDirective], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div class=\"tng-select-wrapper\" [class.tng-select-open]=\"selectDirective()?.isOpen()\">\n @if (label()) {\n <label class=\"tng-select-label\" [attr.for]=\"selectId()\">\n {{ label() }}\n </label>\n }\n\n <div class=\"tng-select-container\">\n <select\n [id]=\"selectId()\"\n tngSelect\n [enableMulti]=\"enableMulti()\"\n [enableSearch]=\"enableSearch()\"\n [placeholder]=\"placeholder()\"\n [customTrigger]=\"true\"\n [multiple]=\"enableMulti()\"\n [triggerRef]=\"triggerDisplay\"\n [selectedValues]=\"value()\"\n (selectedValuesChange)=\"onSelectionChange($event)\"\n [disabled]=\"effectiveDisabled()\"\n [attr.aria-label]=\"ariaLabel() || label()\"\n >\n @for (option of options(); track option.value) {\n <option [value]=\"option.value\" [disabled]=\"option.disabled\">\n {{ option.label }}\n </option>\n }\n </select>\n\n <div\n class=\"tng-select-display\"\n #triggerDisplay\n [class.disabled]=\"effectiveDisabled()\"\n (click)=\"onDisplayClick($event)\"\n >\n <span class=\"tng-select-display-text\">\n {{ displayText() }}\n </span>\n <i class=\"fa fa-chevron-down tng-select-arrow\"></i>\n </div>\n </div>\n\n @if (hint()) {\n <div class=\"tng-select-hint\">\n {{ hint() }}\n </div>\n }\n</div>\n", styles: [":host{display:block;margin-bottom:1.5rem;font-family:var(--tng-font-family, \"Inter\", sans-serif)}.tng-select-wrapper{width:100%}.tng-select-label{display:block;margin-bottom:.5rem;font-size:.9rem;font-weight:500;color:var(--tng-text, #333)}.tng-select-container{position:relative}.tng-select-display{display:flex;align-items:center;justify-content:space-between;gap:.75rem;padding:.75rem 1rem;border:1px solid var(--tng-border, #999);border-radius:var(--tng-border-radius, 4px);background:var(--tng-surface, #ffffff);cursor:pointer;transition:all .2s ease;min-height:48px;font-family:var(--tng-font-family, \"Inter\", sans-serif)}.tng-select-display:hover:not(.disabled){border-color:var(--tng-text-secondary, #757575)}.tng-select-display.disabled{opacity:.6;cursor:not-allowed;background:var(--tng-background, #fafafa)}.tng-select-wrapper.tng-select-open .tng-select-display,.tng-select-display.tng-select-open{border-color:var(--tng-primary, #00f2ff);border-width:2px;padding:calc(.75rem - 1px) calc(1rem - 1px)}.tng-select-display-text{flex:1;color:var(--tng-text, #333);font-size:1rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tng-select-display-text:empty:before{content:attr(data-placeholder);color:var(--tng-text-secondary, #757575)}.tng-select-arrow{color:var(--tng-text-secondary, #757575);transition:transform .2s ease;font-size:.8rem}.tng-select-wrapper.tng-select-open .tng-select-arrow,.tng-select-display.tng-select-open .tng-select-arrow{transform:rotate(180deg)}.tng-select-hint{margin-top:.25rem;font-size:.85rem;color:var(--tng-text-secondary, #757575)}\n"] }]
2231
2281
  }], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], enableMulti: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableMulti", required: false }] }], enableSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableSearch", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], selectDirective: [{ type: i0.ViewChild, args: [i0.forwardRef(() => TngSelectDirective), { isSignal: true }] }] } });
2232
2282
 
2233
2283
  class TngSliderComponent {