@m1z23r/ngx-ui 1.1.32 → 1.1.34

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 { inject, PLATFORM_ID, signal, Injectable, computed, InjectionToken, ApplicationRef, EnvironmentInjector, createComponent, Injector, input, output, ChangeDetectionStrategy, Component, ElementRef, HostListener, effect, Directive, model, Pipe, contentChildren, ViewChild, TemplateRef, contentChild, viewChild, afterRenderEffect, DestroyRef } from '@angular/core';
2
+ import { inject, PLATFORM_ID, signal, Injectable, computed, InjectionToken, ApplicationRef, EnvironmentInjector, createComponent, Injector, input, output, ChangeDetectionStrategy, Component, ElementRef, HostListener, effect, Directive, model, Pipe, contentChildren, TemplateRef, contentChild, ViewChild, viewChild, afterRenderEffect, DestroyRef } from '@angular/core';
3
3
  import { isPlatformBrowser, NgTemplateOutlet, NgComponentOutlet, DOCUMENT, DecimalPipe } from '@angular/common';
4
4
  import * as i1 from '@angular/forms';
5
5
  import { FormsModule } from '@angular/forms';
@@ -1366,6 +1366,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImpor
1366
1366
  args: [{ selector: 'ui-option', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"ui-option\"\n [class.ui-option--selected]=\"selected()\"\n [class.ui-option--disabled]=\"disabled()\"\n [class.ui-option--focused]=\"focused()\"\n [class.ui-option--deletable]=\"deletable()\"\n [attr.role]=\"'option'\"\n [attr.aria-selected]=\"selected()\"\n [attr.aria-disabled]=\"disabled()\"\n>\n @if (multiple() && selected()) {\n <svg class=\"ui-option__check\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n <span class=\"ui-option__content\">\n <ng-content />\n </span>\n @if (deletable()) {\n <button\n type=\"button\"\n class=\"ui-option__delete\"\n (click)=\"onDelete($event)\"\n aria-label=\"Delete option\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n</div>\n", styles: [":host{display:block}.ui-option{display:flex;align-items:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-sm) var(--ui-spacing-md);cursor:pointer;transition:background-color var(--ui-transition-fast);-webkit-user-select:none;user-select:none}.ui-option:hover:not(.ui-option--disabled){background-color:var(--ui-option-hover-bg, var(--ui-bg-hover))}.ui-option--focused:not(.ui-option--disabled){background-color:var(--ui-option-hover-bg, var(--ui-bg-hover))}.ui-option--selected{background-color:var(--ui-option-selected-bg, color-mix(in srgb, var(--ui-primary) 10%, transparent));color:var(--ui-primary)}.ui-option--selected:hover:not(.ui-option--disabled){background-color:var(--ui-option-selected-bg, color-mix(in srgb, var(--ui-primary) 15%, transparent))}.ui-option--disabled{opacity:.5;cursor:not-allowed}.ui-option__check{flex-shrink:0;color:var(--ui-primary)}.ui-option__content{flex:1;min-width:0}.ui-option__delete{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border:none;border-radius:var(--ui-radius-sm);background:transparent;color:var(--ui-text-muted);cursor:pointer;opacity:0;transition:opacity var(--ui-transition-fast),background-color var(--ui-transition-fast),color var(--ui-transition-fast)}.ui-option:hover .ui-option__delete,.ui-option--focused .ui-option__delete{opacity:1}.ui-option__delete:hover{background-color:var(--ui-danger);color:#fff}.ui-option__delete:focus{outline:none;opacity:1}\n"] }]
1367
1367
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], deleteClicked: [{ type: i0.Output, args: ["deleteClicked"] }] } });
1368
1368
 
1369
+ class OptionTemplateDirective {
1370
+ templateRef = inject((TemplateRef));
1371
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: OptionTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1372
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.1", type: OptionTemplateDirective, isStandalone: true, selector: "[uiOptionTemplate]", ngImport: i0 });
1373
+ }
1374
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: OptionTemplateDirective, decorators: [{
1375
+ type: Directive,
1376
+ args: [{
1377
+ selector: '[uiOptionTemplate]',
1378
+ standalone: true,
1379
+ }]
1380
+ }] });
1381
+
1369
1382
  class SelectComponent {
1370
1383
  // Inputs
1371
1384
  variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : []));
@@ -1381,6 +1394,10 @@ class SelectComponent {
1381
1394
  creatable = input(false, ...(ngDevMode ? [{ debugName: "creatable" }] : []));
1382
1395
  deletable = input(false, ...(ngDevMode ? [{ debugName: "deletable" }] : []));
1383
1396
  selectable = input(true, ...(ngDevMode ? [{ debugName: "selectable" }] : []));
1397
+ // Async search inputs
1398
+ asyncSearch = input(null, ...(ngDevMode ? [{ debugName: "asyncSearch" }] : []));
1399
+ debounceTime = input(300, ...(ngDevMode ? [{ debugName: "debounceTime" }] : []));
1400
+ minSearchLength = input(0, ...(ngDevMode ? [{ debugName: "minSearchLength" }] : []));
1384
1401
  // Two-way binding
1385
1402
  value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : []));
1386
1403
  // Outputs
@@ -1390,6 +1407,7 @@ class SelectComponent {
1390
1407
  deleted = output();
1391
1408
  // Content children
1392
1409
  options = contentChildren(OptionComponent, ...(ngDevMode ? [{ debugName: "options" }] : []));
1410
+ optionTemplate = contentChild(OptionTemplateDirective, ...(ngDevMode ? [{ debugName: "optionTemplate" }] : []));
1393
1411
  // View children for dropdown portal
1394
1412
  triggerRef;
1395
1413
  dropdownRef;
@@ -1398,6 +1416,12 @@ class SelectComponent {
1398
1416
  isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
1399
1417
  searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
1400
1418
  focusedIndex = signal(-1, ...(ngDevMode ? [{ debugName: "focusedIndex" }] : []));
1419
+ // Async state
1420
+ asyncLoading = signal(false, ...(ngDevMode ? [{ debugName: "asyncLoading" }] : []));
1421
+ asyncOptions = signal([], ...(ngDevMode ? [{ debugName: "asyncOptions" }] : []));
1422
+ asyncError = signal(null, ...(ngDevMode ? [{ debugName: "asyncError" }] : []));
1423
+ asyncSearchAbortController = null;
1424
+ debounceTimer = null;
1401
1425
  elementRef = inject(ElementRef);
1402
1426
  positionCleanup = null;
1403
1427
  initializedOptions = new WeakSet();
@@ -1467,6 +1491,7 @@ class SelectComponent {
1467
1491
  document.body.removeChild(dropdown);
1468
1492
  }
1469
1493
  this.removePositionListeners();
1494
+ this.cancelAsyncSearch();
1470
1495
  }
1471
1496
  triggerClasses = computed(() => {
1472
1497
  return `ui-select__trigger--${this.variant()} ui-select__trigger--${this.size()}`;
@@ -1481,10 +1506,17 @@ class SelectComponent {
1481
1506
  displayValue = computed(() => {
1482
1507
  const val = this.value();
1483
1508
  const opts = this.options();
1509
+ const asyncOpts = this.asyncOptions();
1510
+ const isAsync = this.isAsyncMode();
1484
1511
  if (this.multiple() && Array.isArray(val)) {
1485
1512
  if (val.length === 0)
1486
1513
  return '';
1487
1514
  const labels = val.map((v) => {
1515
+ if (isAsync) {
1516
+ const asyncOpt = asyncOpts.find((o) => o.value === v);
1517
+ if (asyncOpt)
1518
+ return asyncOpt.label;
1519
+ }
1488
1520
  const opt = opts.find((o) => o.value() === v);
1489
1521
  return opt?.getLabel() || String(v);
1490
1522
  });
@@ -1492,6 +1524,11 @@ class SelectComponent {
1492
1524
  }
1493
1525
  if (val === null || val === undefined)
1494
1526
  return '';
1527
+ if (isAsync) {
1528
+ const asyncOpt = asyncOpts.find((o) => o.value === val);
1529
+ if (asyncOpt)
1530
+ return asyncOpt.label;
1531
+ }
1495
1532
  const opt = opts.find((o) => o.value() === val);
1496
1533
  return opt?.getLabel() || String(val);
1497
1534
  }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
@@ -1505,7 +1542,11 @@ class SelectComponent {
1505
1542
  }
1506
1543
  return this.displayValue() || this.placeholder();
1507
1544
  }, ...(ngDevMode ? [{ debugName: "inputPlaceholder" }] : []));
1545
+ isAsyncMode = computed(() => this.asyncSearch() !== null, ...(ngDevMode ? [{ debugName: "isAsyncMode" }] : []));
1508
1546
  visibleOptions = computed(() => {
1547
+ // In async mode, don't filter content children - they're not used
1548
+ if (this.isAsyncMode())
1549
+ return [];
1509
1550
  const query = this.searchQuery().toLowerCase().trim();
1510
1551
  const opts = this.options();
1511
1552
  if (!query)
@@ -1515,12 +1556,26 @@ class SelectComponent {
1515
1556
  return label.includes(query);
1516
1557
  });
1517
1558
  }, ...(ngDevMode ? [{ debugName: "visibleOptions" }] : []));
1559
+ visibleAsyncOptions = computed(() => {
1560
+ if (!this.isAsyncMode())
1561
+ return [];
1562
+ return this.asyncOptions();
1563
+ }, ...(ngDevMode ? [{ debugName: "visibleAsyncOptions" }] : []));
1518
1564
  exactMatchExists = computed(() => {
1519
1565
  const query = this.searchQuery().toLowerCase().trim();
1520
1566
  if (!query)
1521
1567
  return true;
1568
+ if (this.isAsyncMode()) {
1569
+ return this.asyncOptions().some((opt) => opt.label.toLowerCase() === query);
1570
+ }
1522
1571
  return this.options().some((opt) => opt.getLabel().toLowerCase() === query);
1523
1572
  }, ...(ngDevMode ? [{ debugName: "exactMatchExists" }] : []));
1573
+ totalVisibleCount = computed(() => {
1574
+ if (this.isAsyncMode()) {
1575
+ return this.visibleAsyncOptions().length;
1576
+ }
1577
+ return this.visibleOptions().length;
1578
+ }, ...(ngDevMode ? [{ debugName: "totalVisibleCount" }] : []));
1524
1579
  onDocumentClick(event) {
1525
1580
  const target = event.target;
1526
1581
  if (!this.elementRef.nativeElement.contains(target) &&
@@ -1575,6 +1630,21 @@ class SelectComponent {
1575
1630
  this.searchQuery.set('');
1576
1631
  this.focusedIndex.set(-1);
1577
1632
  this.closed.emit();
1633
+ // Clean up async state
1634
+ this.cancelAsyncSearch();
1635
+ this.asyncLoading.set(false);
1636
+ this.asyncError.set(null);
1637
+ // Keep asyncOptions so displayValue still works after selection
1638
+ }
1639
+ cancelAsyncSearch() {
1640
+ if (this.debounceTimer) {
1641
+ clearTimeout(this.debounceTimer);
1642
+ this.debounceTimer = null;
1643
+ }
1644
+ if (this.asyncSearchAbortController) {
1645
+ this.asyncSearchAbortController.abort();
1646
+ this.asyncSearchAbortController = null;
1647
+ }
1578
1648
  }
1579
1649
  selectOption(option, event) {
1580
1650
  event?.stopPropagation();
@@ -1617,6 +1687,44 @@ class SelectComponent {
1617
1687
  this.value.set(null);
1618
1688
  }
1619
1689
  }
1690
+ selectAsyncOption(option, event) {
1691
+ event?.stopPropagation();
1692
+ if (option.disabled)
1693
+ return;
1694
+ if (!this.selectable())
1695
+ return;
1696
+ const optionValue = option.value;
1697
+ if (this.multiple()) {
1698
+ const currentValue = this.value() || [];
1699
+ const index = currentValue.indexOf(optionValue);
1700
+ let newValue;
1701
+ if (index === -1) {
1702
+ newValue = [...currentValue, optionValue];
1703
+ }
1704
+ else {
1705
+ newValue = currentValue.filter((_, i) => i !== index);
1706
+ }
1707
+ this.value.set(newValue);
1708
+ // In multiple+searchable mode, clear search and refocus input
1709
+ if (this.searchable()) {
1710
+ this.searchQuery.set('');
1711
+ this.focusedIndex.set(-1);
1712
+ this.asyncOptions.set([]);
1713
+ setTimeout(() => this.searchInputRef?.nativeElement?.focus());
1714
+ }
1715
+ }
1716
+ else {
1717
+ this.value.set(optionValue);
1718
+ this.close();
1719
+ }
1720
+ }
1721
+ isAsyncOptionSelected(option) {
1722
+ const val = this.value();
1723
+ if (this.multiple() && Array.isArray(val)) {
1724
+ return val.includes(option.value);
1725
+ }
1726
+ return val === option.value;
1727
+ }
1620
1728
  deleteOption(optionValue) {
1621
1729
  // Remove from selection if selected
1622
1730
  if (this.multiple()) {
@@ -1636,10 +1744,7 @@ class SelectComponent {
1636
1744
  case ' ':
1637
1745
  event.preventDefault();
1638
1746
  if (this.isOpen()) {
1639
- const focused = this.visibleOptions()[this.focusedIndex()];
1640
- if (focused) {
1641
- this.selectOption(focused);
1642
- }
1747
+ this.selectFocusedOption();
1643
1748
  }
1644
1749
  else {
1645
1750
  this.open();
@@ -1692,13 +1797,24 @@ class SelectComponent {
1692
1797
  case 'Enter':
1693
1798
  event.preventDefault();
1694
1799
  if (this.isOpen()) {
1695
- const visible = this.visibleOptions();
1696
- const focused = visible[this.focusedIndex()];
1697
- if (focused) {
1698
- this.selectOption(focused);
1800
+ const focusedIdx = this.focusedIndex();
1801
+ if (focusedIdx >= 0) {
1802
+ this.selectFocusedOption();
1699
1803
  }
1700
- else if (visible.length === 1) {
1701
- this.selectOption(visible[0]);
1804
+ else if (this.totalVisibleCount() === 1) {
1805
+ // Auto-select single visible option
1806
+ if (this.isAsyncMode()) {
1807
+ const asyncOpts = this.visibleAsyncOptions();
1808
+ if (asyncOpts.length === 1) {
1809
+ this.selectAsyncOption(asyncOpts[0]);
1810
+ }
1811
+ }
1812
+ else {
1813
+ const visible = this.visibleOptions();
1814
+ if (visible.length === 1) {
1815
+ this.selectOption(visible[0]);
1816
+ }
1817
+ }
1702
1818
  }
1703
1819
  else if (this.creatable() && this.searchQuery().trim() && !this.exactMatchExists()) {
1704
1820
  this.handleCreate();
@@ -1717,18 +1833,95 @@ class SelectComponent {
1717
1833
  break;
1718
1834
  }
1719
1835
  }
1836
+ selectFocusedOption() {
1837
+ const focusedIdx = this.focusedIndex();
1838
+ if (focusedIdx < 0)
1839
+ return;
1840
+ if (this.isAsyncMode()) {
1841
+ const asyncOpts = this.visibleAsyncOptions();
1842
+ const focused = asyncOpts[focusedIdx];
1843
+ if (focused) {
1844
+ this.selectAsyncOption(focused);
1845
+ }
1846
+ }
1847
+ else {
1848
+ const focused = this.visibleOptions()[focusedIdx];
1849
+ if (focused) {
1850
+ this.selectOption(focused);
1851
+ }
1852
+ }
1853
+ }
1720
1854
  onSearchInput(value) {
1721
1855
  this.searchQuery.set(value);
1722
- // Auto-highlight when exactly one option is visible
1723
- const visible = this.visibleOptions();
1724
- this.focusedIndex.set(visible.length === 1 ? 0 : -1);
1725
1856
  if (!this.isOpen()) {
1726
- // Open without focus/select since user is already typing
1727
1857
  this.isOpen.set(true);
1728
1858
  this.focusedIndex.set(-1);
1729
1859
  this.opened.emit();
1730
1860
  this.portalDropdown();
1731
1861
  }
1862
+ if (this.isAsyncMode()) {
1863
+ this.triggerAsyncSearch(value);
1864
+ }
1865
+ else {
1866
+ // Auto-highlight when exactly one option is visible
1867
+ const visible = this.visibleOptions();
1868
+ this.focusedIndex.set(visible.length === 1 ? 0 : -1);
1869
+ }
1870
+ }
1871
+ triggerAsyncSearch(query) {
1872
+ // Clear previous debounce timer
1873
+ if (this.debounceTimer) {
1874
+ clearTimeout(this.debounceTimer);
1875
+ this.debounceTimer = null;
1876
+ }
1877
+ // Cancel previous request
1878
+ if (this.asyncSearchAbortController) {
1879
+ this.asyncSearchAbortController.abort();
1880
+ this.asyncSearchAbortController = null;
1881
+ }
1882
+ const trimmedQuery = query.trim();
1883
+ // Check minimum search length
1884
+ if (trimmedQuery.length < this.minSearchLength()) {
1885
+ this.asyncOptions.set([]);
1886
+ this.asyncLoading.set(false);
1887
+ this.asyncError.set(null);
1888
+ this.focusedIndex.set(-1);
1889
+ return;
1890
+ }
1891
+ // Set loading state immediately for visual feedback
1892
+ this.asyncLoading.set(true);
1893
+ this.asyncError.set(null);
1894
+ // Debounce the actual search
1895
+ this.debounceTimer = setTimeout(() => {
1896
+ this.executeAsyncSearch(trimmedQuery);
1897
+ }, this.debounceTime());
1898
+ }
1899
+ async executeAsyncSearch(query) {
1900
+ const searchFn = this.asyncSearch();
1901
+ if (!searchFn)
1902
+ return;
1903
+ this.asyncSearchAbortController = new AbortController();
1904
+ const signal = this.asyncSearchAbortController.signal;
1905
+ try {
1906
+ const results = await searchFn(query);
1907
+ // Check if request was aborted
1908
+ if (signal.aborted)
1909
+ return;
1910
+ this.asyncOptions.set(results);
1911
+ this.asyncLoading.set(false);
1912
+ this.asyncError.set(null);
1913
+ // Auto-highlight first option if results exist
1914
+ this.focusedIndex.set(results.length > 0 ? 0 : -1);
1915
+ }
1916
+ catch (error) {
1917
+ // Ignore abort errors
1918
+ if (signal.aborted)
1919
+ return;
1920
+ this.asyncOptions.set([]);
1921
+ this.asyncLoading.set(false);
1922
+ this.asyncError.set(error instanceof Error ? error.message : 'Search failed');
1923
+ this.focusedIndex.set(-1);
1924
+ }
1732
1925
  }
1733
1926
  handleCreate() {
1734
1927
  const query = this.searchQuery().trim();
@@ -1739,27 +1932,53 @@ class SelectComponent {
1739
1932
  this.close();
1740
1933
  }
1741
1934
  focusNext() {
1742
- const opts = this.visibleOptions();
1743
1935
  const current = this.focusedIndex();
1744
- let next = current + 1;
1745
- while (next < opts.length && opts[next].disabled()) {
1746
- next++;
1936
+ if (this.isAsyncMode()) {
1937
+ const opts = this.visibleAsyncOptions();
1938
+ let next = current + 1;
1939
+ while (next < opts.length && opts[next].disabled) {
1940
+ next++;
1941
+ }
1942
+ if (next < opts.length) {
1943
+ this.focusedIndex.set(next);
1944
+ this.scrollToFocusedAsync(next);
1945
+ }
1747
1946
  }
1748
- if (next < opts.length) {
1749
- this.focusedIndex.set(next);
1750
- this.scrollToFocused();
1947
+ else {
1948
+ const opts = this.visibleOptions();
1949
+ let next = current + 1;
1950
+ while (next < opts.length && opts[next].disabled()) {
1951
+ next++;
1952
+ }
1953
+ if (next < opts.length) {
1954
+ this.focusedIndex.set(next);
1955
+ this.scrollToFocused();
1956
+ }
1751
1957
  }
1752
1958
  }
1753
1959
  focusPrevious() {
1754
- const opts = this.visibleOptions();
1755
1960
  const current = this.focusedIndex();
1756
- let prev = current - 1;
1757
- while (prev >= 0 && opts[prev].disabled()) {
1758
- prev--;
1961
+ if (this.isAsyncMode()) {
1962
+ const opts = this.visibleAsyncOptions();
1963
+ let prev = current - 1;
1964
+ while (prev >= 0 && opts[prev].disabled) {
1965
+ prev--;
1966
+ }
1967
+ if (prev >= 0) {
1968
+ this.focusedIndex.set(prev);
1969
+ this.scrollToFocusedAsync(prev);
1970
+ }
1759
1971
  }
1760
- if (prev >= 0) {
1761
- this.focusedIndex.set(prev);
1762
- this.scrollToFocused();
1972
+ else {
1973
+ const opts = this.visibleOptions();
1974
+ let prev = current - 1;
1975
+ while (prev >= 0 && opts[prev].disabled()) {
1976
+ prev--;
1977
+ }
1978
+ if (prev >= 0) {
1979
+ this.focusedIndex.set(prev);
1980
+ this.scrollToFocused();
1981
+ }
1763
1982
  }
1764
1983
  }
1765
1984
  scrollToFocused() {
@@ -1768,6 +1987,16 @@ class SelectComponent {
1768
1987
  focused.elementRef.nativeElement.scrollIntoView({ block: 'nearest' });
1769
1988
  }
1770
1989
  }
1990
+ scrollToFocusedAsync(index) {
1991
+ const dropdown = this.dropdownRef?.nativeElement;
1992
+ if (!dropdown)
1993
+ return;
1994
+ const optionElements = dropdown.querySelectorAll('.ui-async-option');
1995
+ const focusedElement = optionElements[index];
1996
+ if (focusedElement) {
1997
+ focusedElement.scrollIntoView({ block: 'nearest' });
1998
+ }
1999
+ }
1771
2000
  portalDropdown() {
1772
2001
  const dropdown = this.dropdownRef?.nativeElement;
1773
2002
  if (!dropdown)
@@ -1840,12 +2069,12 @@ class SelectComponent {
1840
2069
  this.positionCleanup = null;
1841
2070
  }
1842
2071
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: SelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1843
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: SelectComponent, isStandalone: true, selector: "ui-select", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, creatable: { classPropertyName: "creatable", publicName: "creatable", isSignal: true, isRequired: false, transformFunction: null }, deletable: { classPropertyName: "deletable", publicName: "deletable", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", opened: "opened", closed: "closed", created: "created", deleted: "deleted" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, queries: [{ propertyName: "options", predicate: OptionComponent, isSignal: true }], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerRef"], descendants: true, static: true }, { propertyName: "dropdownRef", first: true, predicate: ["dropdownRef"], descendants: true, static: true }, { propertyName: "searchInputRef", first: true, predicate: ["searchInput"], descendants: true }], ngImport: i0, template: "<div\n class=\"ui-select-wrapper\"\n [class.ui-select-wrapper--error]=\"error()\"\n [class.ui-select-wrapper--disabled]=\"disabled()\"\n [class.ui-select-wrapper--open]=\"isOpen()\"\n>\n @if (label()) {\n <label class=\"ui-select__label\">\n {{ label() }}\n </label>\n }\n\n <div\n #triggerRef\n class=\"ui-select__trigger\"\n [class]=\"triggerClasses()\"\n [attr.role]=\"'combobox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.tabindex]=\"searchable() ? -1 : (disabled() ? -1 : 0)\"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\"\n >\n @if (searchable()) {\n <input\n #searchInput\n type=\"text\"\n class=\"ui-select__input\"\n [placeholder]=\"inputPlaceholder()\"\n [value]=\"isOpen() ? searchQuery() : (selectable() ? displayValue() : '')\"\n [disabled]=\"disabled()\"\n (input)=\"onSearchInput($any($event.target).value)\"\n (keydown)=\"handleSearchInputKeydown($event)\"\n (focus)=\"toggle()\"\n autocomplete=\"off\"\n />\n } @else {\n <span class=\"ui-select__value\">\n @if (displayValue()) {\n {{ displayValue() }}\n } @else {\n <span class=\"ui-select__placeholder\">{{ placeholder() }}</span>\n }\n </span>\n }\n\n <div class=\"ui-select__icons\">\n @if (clearable() && hasValue() && !disabled()) {\n <button\n type=\"button\"\n class=\"ui-select__clear\"\n (click)=\"clear($event)\"\n aria-label=\"Clear selection\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <svg\n class=\"ui-select__arrow\"\n [class.ui-select__arrow--open]=\"isOpen()\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </div>\n </div>\n\n <div\n #dropdownRef\n class=\"ui-select__dropdown\"\n [class.ui-select__dropdown--open]=\"isOpen()\"\n [attr.role]=\"'listbox'\"\n [attr.aria-multiselectable]=\"multiple()\"\n >\n <div class=\"ui-select__options\">\n <ng-content />\n @if (visibleOptions().length === 0 && !(creatable() && searchQuery().trim())) {\n <div class=\"ui-select__empty\">No options found</div>\n }\n </div>\n @if (creatable() && searchQuery().trim() && !exactMatchExists()) {\n <div\n class=\"ui-select__create\"\n (click)=\"handleCreate()\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"></line>\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\n </svg>\n Create \"{{ searchQuery().trim() }}\"\n </div>\n }\n </div>\n\n @if (error()) {\n <span class=\"ui-select__error\">{{ error() }}</span>\n }\n @if (hint() && !error()) {\n <span class=\"ui-select__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [":host{display:block;position:relative}.ui-select-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-select__label{font-size:var(--ui-font-sm);font-weight:500;color:var(--ui-text)}.ui-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--ui-spacing-sm);width:100%;background-color:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);cursor:pointer;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-select__trigger:hover:not([aria-disabled=true]){border-color:var(--ui-border-hover)}.ui-select__trigger:focus{outline:none;border-color:var(--ui-border-focus);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 20%,transparent)}.ui-select__trigger[aria-disabled=true]{background-color:var(--ui-bg-secondary);color:var(--ui-text-disabled);cursor:not-allowed}.ui-select__trigger--sm{padding:var(--ui-spacing-xs) var(--ui-spacing-sm);font-size:var(--ui-font-sm)}.ui-select__trigger--md{padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-size:var(--ui-font-md)}.ui-select__trigger--lg{padding:var(--ui-spacing-md) var(--ui-spacing-lg);font-size:var(--ui-font-lg)}.ui-select__trigger--outlined{background-color:transparent}.ui-select__trigger--filled{background-color:var(--ui-bg-secondary);border-color:transparent}.ui-select__trigger--filled:hover:not([aria-disabled=true]){background-color:var(--ui-bg-tertiary)}.ui-select__trigger--filled:focus{border-color:var(--ui-border-focus)}.ui-select__value{flex:1;min-width:0;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-select__placeholder{color:var(--ui-text-muted)}.ui-select__icons{display:flex;align-items:center;gap:var(--ui-spacing-xs);flex-shrink:0}.ui-select__clear{display:flex;align-items:center;justify-content:center;padding:2px;background:none;border:none;cursor:pointer;color:var(--ui-text-muted);border-radius:var(--ui-radius-sm);transition:color var(--ui-transition-fast),background-color var(--ui-transition-fast)}.ui-select__clear:hover{color:var(--ui-text);background-color:var(--ui-bg-hover)}.ui-select__arrow{color:var(--ui-text-muted);transition:transform var(--ui-transition-fast)}.ui-select__arrow--open{transform:rotate(180deg)}.ui-select__dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;margin-top:var(--ui-spacing-xs);background-color:var(--ui-dropdown-bg, var(--ui-bg));border:1px solid var(--ui-dropdown-border, var(--ui-border));border-radius:var(--ui-dropdown-radius, var(--ui-radius-md));box-shadow:var(--ui-dropdown-shadow, var(--ui-shadow-lg));overflow:hidden;display:none;opacity:0;transform:translateY(-8px);transition:opacity var(--ui-transition-fast),transform var(--ui-transition-fast)}.ui-select__dropdown--open{display:block;opacity:1;transform:translateY(0)}.ui-select__input{flex:1;min-width:0;background:none;border:none;outline:none;font:inherit;color:inherit;padding:0;text-align:left;text-overflow:ellipsis;cursor:pointer}.ui-select__input::placeholder{color:var(--ui-text-muted)}.ui-select__input:focus{cursor:text}.ui-select__input:disabled{cursor:not-allowed}.ui-select__create{display:flex;align-items:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-size:var(--ui-font-sm);color:var(--ui-primary);cursor:pointer;border-top:1px solid var(--ui-border);transition:background-color var(--ui-transition-fast)}.ui-select__create:hover{background-color:var(--ui-bg-hover)}.ui-select__options{max-height:var(--ui-dropdown-max-height, 300px);overflow-y:auto}.ui-select__empty{padding:var(--ui-spacing-md);text-align:center;color:var(--ui-text-muted);font-size:var(--ui-font-sm)}.ui-select-wrapper--error .ui-select__trigger{border-color:var(--ui-danger)}.ui-select-wrapper--error .ui-select__trigger:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-danger) 20%,transparent)}.ui-select__error{font-size:var(--ui-font-sm);color:var(--ui-danger)}.ui-select__hint{font-size:var(--ui-font-sm);color:var(--ui-text-muted)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2072
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: SelectComponent, isStandalone: true, selector: "ui-select", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, creatable: { classPropertyName: "creatable", publicName: "creatable", isSignal: true, isRequired: false, transformFunction: null }, deletable: { classPropertyName: "deletable", publicName: "deletable", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, asyncSearch: { classPropertyName: "asyncSearch", publicName: "asyncSearch", isSignal: true, isRequired: false, transformFunction: null }, debounceTime: { classPropertyName: "debounceTime", publicName: "debounceTime", isSignal: true, isRequired: false, transformFunction: null }, minSearchLength: { classPropertyName: "minSearchLength", publicName: "minSearchLength", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", opened: "opened", closed: "closed", created: "created", deleted: "deleted" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, queries: [{ propertyName: "options", predicate: OptionComponent, isSignal: true }, { propertyName: "optionTemplate", first: true, predicate: OptionTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerRef"], descendants: true, static: true }, { propertyName: "dropdownRef", first: true, predicate: ["dropdownRef"], descendants: true, static: true }, { propertyName: "searchInputRef", first: true, predicate: ["searchInput"], descendants: true }], ngImport: i0, template: "<div\n class=\"ui-select-wrapper\"\n [class.ui-select-wrapper--error]=\"error()\"\n [class.ui-select-wrapper--disabled]=\"disabled()\"\n [class.ui-select-wrapper--open]=\"isOpen()\"\n>\n @if (label()) {\n <label class=\"ui-select__label\">\n {{ label() }}\n </label>\n }\n\n <div\n #triggerRef\n class=\"ui-select__trigger\"\n [class]=\"triggerClasses()\"\n [attr.role]=\"'combobox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.tabindex]=\"searchable() ? -1 : (disabled() ? -1 : 0)\"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\"\n >\n @if (searchable()) {\n <input\n #searchInput\n type=\"text\"\n class=\"ui-select__input\"\n [placeholder]=\"inputPlaceholder()\"\n [value]=\"isOpen() ? searchQuery() : (selectable() ? displayValue() : '')\"\n [disabled]=\"disabled()\"\n (input)=\"onSearchInput($any($event.target).value)\"\n (keydown)=\"handleSearchInputKeydown($event)\"\n (focus)=\"toggle()\"\n autocomplete=\"off\"\n />\n } @else {\n <span class=\"ui-select__value\">\n @if (displayValue()) {\n {{ displayValue() }}\n } @else {\n <span class=\"ui-select__placeholder\">{{ placeholder() }}</span>\n }\n </span>\n }\n\n <div class=\"ui-select__icons\">\n @if (clearable() && hasValue() && !disabled()) {\n <button\n type=\"button\"\n class=\"ui-select__clear\"\n (click)=\"clear($event)\"\n aria-label=\"Clear selection\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <svg\n class=\"ui-select__arrow\"\n [class.ui-select__arrow--open]=\"isOpen()\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </div>\n </div>\n\n <div\n #dropdownRef\n class=\"ui-select__dropdown\"\n [class.ui-select__dropdown--open]=\"isOpen()\"\n [attr.role]=\"'listbox'\"\n [attr.aria-multiselectable]=\"multiple()\"\n >\n <div class=\"ui-select__options\">\n @if (isAsyncMode()) {\n <!-- Async mode: render options from asyncSearch results -->\n @if (asyncLoading()) {\n <div class=\"ui-select__loading\">\n <svg class=\"ui-select__spinner\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke-opacity=\"0.25\"></circle>\n <path d=\"M12 2a10 10 0 0 1 10 10\" stroke-linecap=\"round\"></path>\n </svg>\n <span>Searching...</span>\n </div>\n } @else if (asyncError()) {\n <div class=\"ui-select__error-message\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"></line>\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"></line>\n </svg>\n <span>{{ asyncError() }}</span>\n </div>\n } @else {\n @for (option of visibleAsyncOptions(); track option.value; let i = $index) {\n <div\n class=\"ui-async-option\"\n [class.ui-async-option--selected]=\"isAsyncOptionSelected(option)\"\n [class.ui-async-option--disabled]=\"option.disabled\"\n [class.ui-async-option--focused]=\"focusedIndex() === i\"\n [attr.role]=\"'option'\"\n [attr.aria-selected]=\"isAsyncOptionSelected(option)\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"selectAsyncOption(option, $event)\"\n >\n @if (multiple() && isAsyncOptionSelected(option)) {\n <svg class=\"ui-async-option__check\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n <span class=\"ui-async-option__content\">\n @if (optionTemplate(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl.templateRef; context: { $implicit: option.value, option: option.value, selected: isAsyncOptionSelected(option), disabled: !!option.disabled }\"></ng-container>\n } @else {\n {{ option.label }}\n }\n </span>\n </div>\n }\n @if (visibleAsyncOptions().length === 0 && searchQuery().trim().length >= minSearchLength()) {\n <div class=\"ui-select__empty\">No results found</div>\n }\n @if (searchQuery().trim().length < minSearchLength() && minSearchLength() > 0) {\n <div class=\"ui-select__empty\">Type at least {{ minSearchLength() }} characters to search</div>\n }\n }\n } @else {\n <!-- Static mode: render content children -->\n <ng-content />\n @if (visibleOptions().length === 0 && !(creatable() && searchQuery().trim())) {\n <div class=\"ui-select__empty\">No options found</div>\n }\n }\n </div>\n @if (creatable() && searchQuery().trim() && !exactMatchExists()) {\n <div\n class=\"ui-select__create\"\n (click)=\"handleCreate()\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"></line>\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\n </svg>\n Create \"{{ searchQuery().trim() }}\"\n </div>\n }\n </div>\n\n @if (error()) {\n <span class=\"ui-select__error\">{{ error() }}</span>\n }\n @if (hint() && !error()) {\n <span class=\"ui-select__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [":host{display:block;position:relative}.ui-select-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-select__label{font-size:var(--ui-font-sm);font-weight:500;color:var(--ui-text)}.ui-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--ui-spacing-sm);width:100%;background-color:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);cursor:pointer;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-select__trigger:hover:not([aria-disabled=true]){border-color:var(--ui-border-hover)}.ui-select__trigger:focus{outline:none;border-color:var(--ui-border-focus);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 20%,transparent)}.ui-select__trigger[aria-disabled=true]{background-color:var(--ui-bg-secondary);color:var(--ui-text-disabled);cursor:not-allowed}.ui-select__trigger--sm{padding:var(--ui-spacing-xs) var(--ui-spacing-sm);font-size:var(--ui-font-sm)}.ui-select__trigger--md{padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-size:var(--ui-font-md)}.ui-select__trigger--lg{padding:var(--ui-spacing-md) var(--ui-spacing-lg);font-size:var(--ui-font-lg)}.ui-select__trigger--outlined{background-color:transparent}.ui-select__trigger--filled{background-color:var(--ui-bg-secondary);border-color:transparent}.ui-select__trigger--filled:hover:not([aria-disabled=true]){background-color:var(--ui-bg-tertiary)}.ui-select__trigger--filled:focus{border-color:var(--ui-border-focus)}.ui-select__value{flex:1;min-width:0;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-select__placeholder{color:var(--ui-text-muted)}.ui-select__icons{display:flex;align-items:center;gap:var(--ui-spacing-xs);flex-shrink:0}.ui-select__clear{display:flex;align-items:center;justify-content:center;padding:2px;background:none;border:none;cursor:pointer;color:var(--ui-text-muted);border-radius:var(--ui-radius-sm);transition:color var(--ui-transition-fast),background-color var(--ui-transition-fast)}.ui-select__clear:hover{color:var(--ui-text);background-color:var(--ui-bg-hover)}.ui-select__arrow{color:var(--ui-text-muted);transition:transform var(--ui-transition-fast)}.ui-select__arrow--open{transform:rotate(180deg)}.ui-select__dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;margin-top:var(--ui-spacing-xs);background-color:var(--ui-dropdown-bg, var(--ui-bg));border:1px solid var(--ui-dropdown-border, var(--ui-border));border-radius:var(--ui-dropdown-radius, var(--ui-radius-md));box-shadow:var(--ui-dropdown-shadow, var(--ui-shadow-lg));overflow:hidden;display:none;opacity:0;transform:translateY(-8px);transition:opacity var(--ui-transition-fast),transform var(--ui-transition-fast);box-sizing:border-box}.ui-select__dropdown--open{display:block;opacity:1;transform:translateY(0)}.ui-select__input{flex:1;min-width:0;background:none;border:none;outline:none;font:inherit;color:inherit;padding:0;text-align:left;text-overflow:ellipsis;cursor:pointer}.ui-select__input::placeholder{color:var(--ui-text-muted)}.ui-select__input:focus{cursor:text}.ui-select__input:disabled{cursor:not-allowed}.ui-select__create{display:flex;align-items:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-size:var(--ui-font-sm);color:var(--ui-primary);cursor:pointer;border-top:1px solid var(--ui-border);transition:background-color var(--ui-transition-fast)}.ui-select__create:hover{background-color:var(--ui-bg-hover)}.ui-select__options{max-height:var(--ui-dropdown-max-height, 300px);overflow-y:auto}.ui-select__empty{padding:var(--ui-spacing-md);text-align:center;color:var(--ui-text-muted);font-size:var(--ui-font-sm)}.ui-select-wrapper--error .ui-select__trigger{border-color:var(--ui-danger)}.ui-select-wrapper--error .ui-select__trigger:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-danger) 20%,transparent)}.ui-select__error{font-size:var(--ui-font-sm);color:var(--ui-danger)}.ui-select__hint{font-size:var(--ui-font-sm);color:var(--ui-text-muted)}.ui-async-option{display:flex;align-items:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-sm) var(--ui-spacing-md);cursor:pointer;transition:background-color var(--ui-transition-fast)}.ui-async-option:hover:not(.ui-async-option--disabled){background-color:var(--ui-bg-hover)}.ui-async-option--selected{background-color:color-mix(in srgb,var(--ui-primary) 10%,transparent)}.ui-async-option--selected:hover:not(.ui-async-option--disabled){background-color:color-mix(in srgb,var(--ui-primary) 15%,transparent)}.ui-async-option--focused{background-color:var(--ui-bg-hover);outline:none}.ui-async-option--focused.ui-async-option--selected{background-color:color-mix(in srgb,var(--ui-primary) 15%,transparent)}.ui-async-option--disabled{opacity:.5;cursor:not-allowed}.ui-async-option__check{flex-shrink:0;color:var(--ui-primary)}.ui-async-option__content{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-select__loading{display:flex;align-items:center;justify-content:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-lg) var(--ui-spacing-md);color:var(--ui-text-muted);font-size:var(--ui-font-sm)}.ui-select__spinner{animation:ui-select-spin 1s linear infinite}@keyframes ui-select-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.ui-select__error-message{display:flex;align-items:center;justify-content:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-md);color:var(--ui-danger);font-size:var(--ui-font-sm)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1844
2073
  }
1845
2074
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: SelectComponent, decorators: [{
1846
2075
  type: Component,
1847
- args: [{ selector: 'ui-select', standalone: true, imports: [FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"ui-select-wrapper\"\n [class.ui-select-wrapper--error]=\"error()\"\n [class.ui-select-wrapper--disabled]=\"disabled()\"\n [class.ui-select-wrapper--open]=\"isOpen()\"\n>\n @if (label()) {\n <label class=\"ui-select__label\">\n {{ label() }}\n </label>\n }\n\n <div\n #triggerRef\n class=\"ui-select__trigger\"\n [class]=\"triggerClasses()\"\n [attr.role]=\"'combobox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.tabindex]=\"searchable() ? -1 : (disabled() ? -1 : 0)\"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\"\n >\n @if (searchable()) {\n <input\n #searchInput\n type=\"text\"\n class=\"ui-select__input\"\n [placeholder]=\"inputPlaceholder()\"\n [value]=\"isOpen() ? searchQuery() : (selectable() ? displayValue() : '')\"\n [disabled]=\"disabled()\"\n (input)=\"onSearchInput($any($event.target).value)\"\n (keydown)=\"handleSearchInputKeydown($event)\"\n (focus)=\"toggle()\"\n autocomplete=\"off\"\n />\n } @else {\n <span class=\"ui-select__value\">\n @if (displayValue()) {\n {{ displayValue() }}\n } @else {\n <span class=\"ui-select__placeholder\">{{ placeholder() }}</span>\n }\n </span>\n }\n\n <div class=\"ui-select__icons\">\n @if (clearable() && hasValue() && !disabled()) {\n <button\n type=\"button\"\n class=\"ui-select__clear\"\n (click)=\"clear($event)\"\n aria-label=\"Clear selection\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <svg\n class=\"ui-select__arrow\"\n [class.ui-select__arrow--open]=\"isOpen()\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </div>\n </div>\n\n <div\n #dropdownRef\n class=\"ui-select__dropdown\"\n [class.ui-select__dropdown--open]=\"isOpen()\"\n [attr.role]=\"'listbox'\"\n [attr.aria-multiselectable]=\"multiple()\"\n >\n <div class=\"ui-select__options\">\n <ng-content />\n @if (visibleOptions().length === 0 && !(creatable() && searchQuery().trim())) {\n <div class=\"ui-select__empty\">No options found</div>\n }\n </div>\n @if (creatable() && searchQuery().trim() && !exactMatchExists()) {\n <div\n class=\"ui-select__create\"\n (click)=\"handleCreate()\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"></line>\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\n </svg>\n Create \"{{ searchQuery().trim() }}\"\n </div>\n }\n </div>\n\n @if (error()) {\n <span class=\"ui-select__error\">{{ error() }}</span>\n }\n @if (hint() && !error()) {\n <span class=\"ui-select__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [":host{display:block;position:relative}.ui-select-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-select__label{font-size:var(--ui-font-sm);font-weight:500;color:var(--ui-text)}.ui-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--ui-spacing-sm);width:100%;background-color:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);cursor:pointer;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-select__trigger:hover:not([aria-disabled=true]){border-color:var(--ui-border-hover)}.ui-select__trigger:focus{outline:none;border-color:var(--ui-border-focus);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 20%,transparent)}.ui-select__trigger[aria-disabled=true]{background-color:var(--ui-bg-secondary);color:var(--ui-text-disabled);cursor:not-allowed}.ui-select__trigger--sm{padding:var(--ui-spacing-xs) var(--ui-spacing-sm);font-size:var(--ui-font-sm)}.ui-select__trigger--md{padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-size:var(--ui-font-md)}.ui-select__trigger--lg{padding:var(--ui-spacing-md) var(--ui-spacing-lg);font-size:var(--ui-font-lg)}.ui-select__trigger--outlined{background-color:transparent}.ui-select__trigger--filled{background-color:var(--ui-bg-secondary);border-color:transparent}.ui-select__trigger--filled:hover:not([aria-disabled=true]){background-color:var(--ui-bg-tertiary)}.ui-select__trigger--filled:focus{border-color:var(--ui-border-focus)}.ui-select__value{flex:1;min-width:0;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-select__placeholder{color:var(--ui-text-muted)}.ui-select__icons{display:flex;align-items:center;gap:var(--ui-spacing-xs);flex-shrink:0}.ui-select__clear{display:flex;align-items:center;justify-content:center;padding:2px;background:none;border:none;cursor:pointer;color:var(--ui-text-muted);border-radius:var(--ui-radius-sm);transition:color var(--ui-transition-fast),background-color var(--ui-transition-fast)}.ui-select__clear:hover{color:var(--ui-text);background-color:var(--ui-bg-hover)}.ui-select__arrow{color:var(--ui-text-muted);transition:transform var(--ui-transition-fast)}.ui-select__arrow--open{transform:rotate(180deg)}.ui-select__dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;margin-top:var(--ui-spacing-xs);background-color:var(--ui-dropdown-bg, var(--ui-bg));border:1px solid var(--ui-dropdown-border, var(--ui-border));border-radius:var(--ui-dropdown-radius, var(--ui-radius-md));box-shadow:var(--ui-dropdown-shadow, var(--ui-shadow-lg));overflow:hidden;display:none;opacity:0;transform:translateY(-8px);transition:opacity var(--ui-transition-fast),transform var(--ui-transition-fast)}.ui-select__dropdown--open{display:block;opacity:1;transform:translateY(0)}.ui-select__input{flex:1;min-width:0;background:none;border:none;outline:none;font:inherit;color:inherit;padding:0;text-align:left;text-overflow:ellipsis;cursor:pointer}.ui-select__input::placeholder{color:var(--ui-text-muted)}.ui-select__input:focus{cursor:text}.ui-select__input:disabled{cursor:not-allowed}.ui-select__create{display:flex;align-items:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-size:var(--ui-font-sm);color:var(--ui-primary);cursor:pointer;border-top:1px solid var(--ui-border);transition:background-color var(--ui-transition-fast)}.ui-select__create:hover{background-color:var(--ui-bg-hover)}.ui-select__options{max-height:var(--ui-dropdown-max-height, 300px);overflow-y:auto}.ui-select__empty{padding:var(--ui-spacing-md);text-align:center;color:var(--ui-text-muted);font-size:var(--ui-font-sm)}.ui-select-wrapper--error .ui-select__trigger{border-color:var(--ui-danger)}.ui-select-wrapper--error .ui-select__trigger:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-danger) 20%,transparent)}.ui-select__error{font-size:var(--ui-font-sm);color:var(--ui-danger)}.ui-select__hint{font-size:var(--ui-font-sm);color:var(--ui-text-muted)}\n"] }]
1848
- }], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], creatable: [{ type: i0.Input, args: [{ isSignal: true, alias: "creatable", required: false }] }], deletable: [{ type: i0.Input, args: [{ isSignal: true, alias: "deletable", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], created: [{ type: i0.Output, args: ["created"] }], deleted: [{ type: i0.Output, args: ["deleted"] }], options: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => OptionComponent), { isSignal: true }] }], triggerRef: [{
2076
+ args: [{ selector: 'ui-select', standalone: true, imports: [FormsModule, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"ui-select-wrapper\"\n [class.ui-select-wrapper--error]=\"error()\"\n [class.ui-select-wrapper--disabled]=\"disabled()\"\n [class.ui-select-wrapper--open]=\"isOpen()\"\n>\n @if (label()) {\n <label class=\"ui-select__label\">\n {{ label() }}\n </label>\n }\n\n <div\n #triggerRef\n class=\"ui-select__trigger\"\n [class]=\"triggerClasses()\"\n [attr.role]=\"'combobox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.tabindex]=\"searchable() ? -1 : (disabled() ? -1 : 0)\"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\"\n >\n @if (searchable()) {\n <input\n #searchInput\n type=\"text\"\n class=\"ui-select__input\"\n [placeholder]=\"inputPlaceholder()\"\n [value]=\"isOpen() ? searchQuery() : (selectable() ? displayValue() : '')\"\n [disabled]=\"disabled()\"\n (input)=\"onSearchInput($any($event.target).value)\"\n (keydown)=\"handleSearchInputKeydown($event)\"\n (focus)=\"toggle()\"\n autocomplete=\"off\"\n />\n } @else {\n <span class=\"ui-select__value\">\n @if (displayValue()) {\n {{ displayValue() }}\n } @else {\n <span class=\"ui-select__placeholder\">{{ placeholder() }}</span>\n }\n </span>\n }\n\n <div class=\"ui-select__icons\">\n @if (clearable() && hasValue() && !disabled()) {\n <button\n type=\"button\"\n class=\"ui-select__clear\"\n (click)=\"clear($event)\"\n aria-label=\"Clear selection\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <svg\n class=\"ui-select__arrow\"\n [class.ui-select__arrow--open]=\"isOpen()\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </div>\n </div>\n\n <div\n #dropdownRef\n class=\"ui-select__dropdown\"\n [class.ui-select__dropdown--open]=\"isOpen()\"\n [attr.role]=\"'listbox'\"\n [attr.aria-multiselectable]=\"multiple()\"\n >\n <div class=\"ui-select__options\">\n @if (isAsyncMode()) {\n <!-- Async mode: render options from asyncSearch results -->\n @if (asyncLoading()) {\n <div class=\"ui-select__loading\">\n <svg class=\"ui-select__spinner\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke-opacity=\"0.25\"></circle>\n <path d=\"M12 2a10 10 0 0 1 10 10\" stroke-linecap=\"round\"></path>\n </svg>\n <span>Searching...</span>\n </div>\n } @else if (asyncError()) {\n <div class=\"ui-select__error-message\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"></circle>\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\"></line>\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\"></line>\n </svg>\n <span>{{ asyncError() }}</span>\n </div>\n } @else {\n @for (option of visibleAsyncOptions(); track option.value; let i = $index) {\n <div\n class=\"ui-async-option\"\n [class.ui-async-option--selected]=\"isAsyncOptionSelected(option)\"\n [class.ui-async-option--disabled]=\"option.disabled\"\n [class.ui-async-option--focused]=\"focusedIndex() === i\"\n [attr.role]=\"'option'\"\n [attr.aria-selected]=\"isAsyncOptionSelected(option)\"\n [attr.aria-disabled]=\"option.disabled\"\n (click)=\"selectAsyncOption(option, $event)\"\n >\n @if (multiple() && isAsyncOptionSelected(option)) {\n <svg class=\"ui-async-option__check\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n }\n <span class=\"ui-async-option__content\">\n @if (optionTemplate(); as tpl) {\n <ng-container *ngTemplateOutlet=\"tpl.templateRef; context: { $implicit: option.value, option: option.value, selected: isAsyncOptionSelected(option), disabled: !!option.disabled }\"></ng-container>\n } @else {\n {{ option.label }}\n }\n </span>\n </div>\n }\n @if (visibleAsyncOptions().length === 0 && searchQuery().trim().length >= minSearchLength()) {\n <div class=\"ui-select__empty\">No results found</div>\n }\n @if (searchQuery().trim().length < minSearchLength() && minSearchLength() > 0) {\n <div class=\"ui-select__empty\">Type at least {{ minSearchLength() }} characters to search</div>\n }\n }\n } @else {\n <!-- Static mode: render content children -->\n <ng-content />\n @if (visibleOptions().length === 0 && !(creatable() && searchQuery().trim())) {\n <div class=\"ui-select__empty\">No options found</div>\n }\n }\n </div>\n @if (creatable() && searchQuery().trim() && !exactMatchExists()) {\n <div\n class=\"ui-select__create\"\n (click)=\"handleCreate()\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"></line>\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\"></line>\n </svg>\n Create \"{{ searchQuery().trim() }}\"\n </div>\n }\n </div>\n\n @if (error()) {\n <span class=\"ui-select__error\">{{ error() }}</span>\n }\n @if (hint() && !error()) {\n <span class=\"ui-select__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [":host{display:block;position:relative}.ui-select-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-select__label{font-size:var(--ui-font-sm);font-weight:500;color:var(--ui-text)}.ui-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--ui-spacing-sm);width:100%;background-color:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);cursor:pointer;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-select__trigger:hover:not([aria-disabled=true]){border-color:var(--ui-border-hover)}.ui-select__trigger:focus{outline:none;border-color:var(--ui-border-focus);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 20%,transparent)}.ui-select__trigger[aria-disabled=true]{background-color:var(--ui-bg-secondary);color:var(--ui-text-disabled);cursor:not-allowed}.ui-select__trigger--sm{padding:var(--ui-spacing-xs) var(--ui-spacing-sm);font-size:var(--ui-font-sm)}.ui-select__trigger--md{padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-size:var(--ui-font-md)}.ui-select__trigger--lg{padding:var(--ui-spacing-md) var(--ui-spacing-lg);font-size:var(--ui-font-lg)}.ui-select__trigger--outlined{background-color:transparent}.ui-select__trigger--filled{background-color:var(--ui-bg-secondary);border-color:transparent}.ui-select__trigger--filled:hover:not([aria-disabled=true]){background-color:var(--ui-bg-tertiary)}.ui-select__trigger--filled:focus{border-color:var(--ui-border-focus)}.ui-select__value{flex:1;min-width:0;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-select__placeholder{color:var(--ui-text-muted)}.ui-select__icons{display:flex;align-items:center;gap:var(--ui-spacing-xs);flex-shrink:0}.ui-select__clear{display:flex;align-items:center;justify-content:center;padding:2px;background:none;border:none;cursor:pointer;color:var(--ui-text-muted);border-radius:var(--ui-radius-sm);transition:color var(--ui-transition-fast),background-color var(--ui-transition-fast)}.ui-select__clear:hover{color:var(--ui-text);background-color:var(--ui-bg-hover)}.ui-select__arrow{color:var(--ui-text-muted);transition:transform var(--ui-transition-fast)}.ui-select__arrow--open{transform:rotate(180deg)}.ui-select__dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;margin-top:var(--ui-spacing-xs);background-color:var(--ui-dropdown-bg, var(--ui-bg));border:1px solid var(--ui-dropdown-border, var(--ui-border));border-radius:var(--ui-dropdown-radius, var(--ui-radius-md));box-shadow:var(--ui-dropdown-shadow, var(--ui-shadow-lg));overflow:hidden;display:none;opacity:0;transform:translateY(-8px);transition:opacity var(--ui-transition-fast),transform var(--ui-transition-fast);box-sizing:border-box}.ui-select__dropdown--open{display:block;opacity:1;transform:translateY(0)}.ui-select__input{flex:1;min-width:0;background:none;border:none;outline:none;font:inherit;color:inherit;padding:0;text-align:left;text-overflow:ellipsis;cursor:pointer}.ui-select__input::placeholder{color:var(--ui-text-muted)}.ui-select__input:focus{cursor:text}.ui-select__input:disabled{cursor:not-allowed}.ui-select__create{display:flex;align-items:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-size:var(--ui-font-sm);color:var(--ui-primary);cursor:pointer;border-top:1px solid var(--ui-border);transition:background-color var(--ui-transition-fast)}.ui-select__create:hover{background-color:var(--ui-bg-hover)}.ui-select__options{max-height:var(--ui-dropdown-max-height, 300px);overflow-y:auto}.ui-select__empty{padding:var(--ui-spacing-md);text-align:center;color:var(--ui-text-muted);font-size:var(--ui-font-sm)}.ui-select-wrapper--error .ui-select__trigger{border-color:var(--ui-danger)}.ui-select-wrapper--error .ui-select__trigger:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-danger) 20%,transparent)}.ui-select__error{font-size:var(--ui-font-sm);color:var(--ui-danger)}.ui-select__hint{font-size:var(--ui-font-sm);color:var(--ui-text-muted)}.ui-async-option{display:flex;align-items:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-sm) var(--ui-spacing-md);cursor:pointer;transition:background-color var(--ui-transition-fast)}.ui-async-option:hover:not(.ui-async-option--disabled){background-color:var(--ui-bg-hover)}.ui-async-option--selected{background-color:color-mix(in srgb,var(--ui-primary) 10%,transparent)}.ui-async-option--selected:hover:not(.ui-async-option--disabled){background-color:color-mix(in srgb,var(--ui-primary) 15%,transparent)}.ui-async-option--focused{background-color:var(--ui-bg-hover);outline:none}.ui-async-option--focused.ui-async-option--selected{background-color:color-mix(in srgb,var(--ui-primary) 15%,transparent)}.ui-async-option--disabled{opacity:.5;cursor:not-allowed}.ui-async-option__check{flex-shrink:0;color:var(--ui-primary)}.ui-async-option__content{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-select__loading{display:flex;align-items:center;justify-content:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-lg) var(--ui-spacing-md);color:var(--ui-text-muted);font-size:var(--ui-font-sm)}.ui-select__spinner{animation:ui-select-spin 1s linear infinite}@keyframes ui-select-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.ui-select__error-message{display:flex;align-items:center;justify-content:center;gap:var(--ui-spacing-sm);padding:var(--ui-spacing-md);color:var(--ui-danger);font-size:var(--ui-font-sm)}\n"] }]
2077
+ }], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], creatable: [{ type: i0.Input, args: [{ isSignal: true, alias: "creatable", required: false }] }], deletable: [{ type: i0.Input, args: [{ isSignal: true, alias: "deletable", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], asyncSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "asyncSearch", required: false }] }], debounceTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceTime", required: false }] }], minSearchLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSearchLength", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], created: [{ type: i0.Output, args: ["created"] }], deleted: [{ type: i0.Output, args: ["deleted"] }], options: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => OptionComponent), { isSignal: true }] }], optionTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => OptionTemplateDirective), { isSignal: true }] }], triggerRef: [{
1849
2078
  type: ViewChild,
1850
2079
  args: ['triggerRef', { static: true }]
1851
2080
  }], dropdownRef: [{
@@ -1859,19 +2088,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImpor
1859
2088
  args: ['document:click', ['$event']]
1860
2089
  }] } });
1861
2090
 
1862
- class OptionTemplateDirective {
1863
- templateRef = inject((TemplateRef));
1864
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: OptionTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1865
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.1", type: OptionTemplateDirective, isStandalone: true, selector: "[uiOptionTemplate]", ngImport: i0 });
1866
- }
1867
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: OptionTemplateDirective, decorators: [{
1868
- type: Directive,
1869
- args: [{
1870
- selector: '[uiOptionTemplate]',
1871
- standalone: true,
1872
- }]
1873
- }] });
1874
-
1875
2091
  class DropdownTriggerDirective {
1876
2092
  elementRef = inject(ElementRef);
1877
2093
  toggleDropdown = output();