@neural-ui/core 1.7.0 → 1.7.2

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.
Files changed (125) hide show
  1. package/bottom-sheet/package.json +4 -0
  2. package/confirm-popup/package.json +4 -0
  3. package/data-view/package.json +4 -0
  4. package/fesm2022/neural-ui-core-alert.mjs +48 -21
  5. package/fesm2022/neural-ui-core-alert.mjs.map +1 -1
  6. package/fesm2022/neural-ui-core-autocomplete.mjs +141 -68
  7. package/fesm2022/neural-ui-core-autocomplete.mjs.map +1 -1
  8. package/fesm2022/neural-ui-core-block-ui.mjs +2 -2
  9. package/fesm2022/neural-ui-core-block-ui.mjs.map +1 -1
  10. package/fesm2022/neural-ui-core-bottom-sheet.mjs +121 -0
  11. package/fesm2022/neural-ui-core-bottom-sheet.mjs.map +1 -0
  12. package/fesm2022/neural-ui-core-breadcrumb.mjs +2 -2
  13. package/fesm2022/neural-ui-core-breadcrumb.mjs.map +1 -1
  14. package/fesm2022/neural-ui-core-button.mjs +2 -2
  15. package/fesm2022/neural-ui-core-button.mjs.map +1 -1
  16. package/fesm2022/neural-ui-core-calendar.mjs +2 -2
  17. package/fesm2022/neural-ui-core-calendar.mjs.map +1 -1
  18. package/fesm2022/neural-ui-core-checkbox.mjs +69 -39
  19. package/fesm2022/neural-ui-core-checkbox.mjs.map +1 -1
  20. package/fesm2022/neural-ui-core-chip.mjs +2 -2
  21. package/fesm2022/neural-ui-core-chip.mjs.map +1 -1
  22. package/fesm2022/neural-ui-core-code-block.mjs +2 -2
  23. package/fesm2022/neural-ui-core-code-block.mjs.map +1 -1
  24. package/fesm2022/neural-ui-core-confirm-popup.mjs +105 -0
  25. package/fesm2022/neural-ui-core-confirm-popup.mjs.map +1 -0
  26. package/fesm2022/neural-ui-core-data-view.mjs +386 -0
  27. package/fesm2022/neural-ui-core-data-view.mjs.map +1 -0
  28. package/fesm2022/neural-ui-core-date-input.mjs +185 -10
  29. package/fesm2022/neural-ui-core-date-input.mjs.map +1 -1
  30. package/fesm2022/neural-ui-core-empty-state.mjs +19 -5
  31. package/fesm2022/neural-ui-core-empty-state.mjs.map +1 -1
  32. package/fesm2022/neural-ui-core-form-field.mjs +81 -0
  33. package/fesm2022/neural-ui-core-form-field.mjs.map +1 -0
  34. package/fesm2022/neural-ui-core-inline-editor.mjs +428 -0
  35. package/fesm2022/neural-ui-core-inline-editor.mjs.map +1 -0
  36. package/fesm2022/neural-ui-core-input-mask.mjs +110 -0
  37. package/fesm2022/neural-ui-core-input-mask.mjs.map +1 -0
  38. package/fesm2022/neural-ui-core-input.mjs +2 -2
  39. package/fesm2022/neural-ui-core-input.mjs.map +1 -1
  40. package/fesm2022/neural-ui-core-listbox.mjs +219 -0
  41. package/fesm2022/neural-ui-core-listbox.mjs.map +1 -0
  42. package/fesm2022/neural-ui-core-menu.mjs +229 -0
  43. package/fesm2022/neural-ui-core-menu.mjs.map +1 -0
  44. package/fesm2022/neural-ui-core-modal.mjs +34 -10
  45. package/fesm2022/neural-ui-core-modal.mjs.map +1 -1
  46. package/fesm2022/neural-ui-core-multiselect.mjs +159 -174
  47. package/fesm2022/neural-ui-core-multiselect.mjs.map +1 -1
  48. package/fesm2022/neural-ui-core-nav.mjs +2 -2
  49. package/fesm2022/neural-ui-core-nav.mjs.map +1 -1
  50. package/fesm2022/neural-ui-core-number-input.mjs +2 -2
  51. package/fesm2022/neural-ui-core-number-input.mjs.map +1 -1
  52. package/fesm2022/neural-ui-core-panel.mjs +92 -0
  53. package/fesm2022/neural-ui-core-panel.mjs.map +1 -0
  54. package/fesm2022/neural-ui-core-password.mjs +106 -0
  55. package/fesm2022/neural-ui-core-password.mjs.map +1 -0
  56. package/fesm2022/neural-ui-core-pick-list.mjs +133 -0
  57. package/fesm2022/neural-ui-core-pick-list.mjs.map +1 -0
  58. package/fesm2022/neural-ui-core-select.mjs +118 -162
  59. package/fesm2022/neural-ui-core-select.mjs.map +1 -1
  60. package/fesm2022/neural-ui-core-sidebar.mjs +14 -3
  61. package/fesm2022/neural-ui-core-sidebar.mjs.map +1 -1
  62. package/fesm2022/neural-ui-core-slider.mjs +2 -2
  63. package/fesm2022/neural-ui-core-slider.mjs.map +1 -1
  64. package/fesm2022/neural-ui-core-spinner.mjs +19 -9
  65. package/fesm2022/neural-ui-core-spinner.mjs.map +1 -1
  66. package/fesm2022/neural-ui-core-split-button.mjs +2 -2
  67. package/fesm2022/neural-ui-core-split-button.mjs.map +1 -1
  68. package/fesm2022/neural-ui-core-table.mjs +501 -62
  69. package/fesm2022/neural-ui-core-table.mjs.map +1 -1
  70. package/fesm2022/neural-ui-core-tags.mjs +134 -0
  71. package/fesm2022/neural-ui-core-tags.mjs.map +1 -0
  72. package/fesm2022/neural-ui-core-textarea.mjs +2 -2
  73. package/fesm2022/neural-ui-core-textarea.mjs.map +1 -1
  74. package/fesm2022/neural-ui-core-toggle-button-group.mjs +2 -2
  75. package/fesm2022/neural-ui-core-toggle-button-group.mjs.map +1 -1
  76. package/fesm2022/neural-ui-core-toolbar.mjs +16 -4
  77. package/fesm2022/neural-ui-core-toolbar.mjs.map +1 -1
  78. package/fesm2022/neural-ui-core-tree-select.mjs +259 -0
  79. package/fesm2022/neural-ui-core-tree-select.mjs.map +1 -0
  80. package/fesm2022/neural-ui-core-tree-table.mjs +267 -8
  81. package/fesm2022/neural-ui-core-tree-table.mjs.map +1 -1
  82. package/fesm2022/neural-ui-core-tree.mjs +15 -14
  83. package/fesm2022/neural-ui-core-tree.mjs.map +1 -1
  84. package/fesm2022/neural-ui-core-uploader.mjs +103 -12
  85. package/fesm2022/neural-ui-core-uploader.mjs.map +1 -1
  86. package/form-field/package.json +4 -0
  87. package/inline-editor/package.json +4 -0
  88. package/input-mask/package.json +4 -0
  89. package/listbox/package.json +4 -0
  90. package/menu/package.json +4 -0
  91. package/package.json +53 -1
  92. package/panel/package.json +4 -0
  93. package/password/package.json +4 -0
  94. package/pick-list/package.json +4 -0
  95. package/styles/_tokens.scss +30 -15
  96. package/tags/package.json +4 -0
  97. package/tree-select/package.json +4 -0
  98. package/types/neural-ui-core-alert.d.ts +2 -1
  99. package/types/neural-ui-core-autocomplete.d.ts +20 -2
  100. package/types/neural-ui-core-bottom-sheet.d.ts +20 -0
  101. package/types/neural-ui-core-checkbox.d.ts +6 -1
  102. package/types/neural-ui-core-confirm-popup.d.ts +38 -0
  103. package/types/neural-ui-core-data-view.d.ts +95 -0
  104. package/types/neural-ui-core-date-input.d.ts +35 -5
  105. package/types/neural-ui-core-empty-state.d.ts +11 -1
  106. package/types/neural-ui-core-form-field.d.ts +33 -0
  107. package/types/neural-ui-core-inline-editor.d.ts +66 -0
  108. package/types/neural-ui-core-input-mask.d.ts +26 -0
  109. package/types/neural-ui-core-listbox.d.ts +54 -0
  110. package/types/neural-ui-core-menu.d.ts +49 -0
  111. package/types/neural-ui-core-modal.d.ts +10 -2
  112. package/types/neural-ui-core-multiselect.d.ts +8 -1
  113. package/types/neural-ui-core-panel.d.ts +25 -0
  114. package/types/neural-ui-core-password.d.ts +29 -0
  115. package/types/neural-ui-core-pick-list.d.ts +40 -0
  116. package/types/neural-ui-core-select.d.ts +5 -1
  117. package/types/neural-ui-core-sidebar.d.ts +5 -1
  118. package/types/neural-ui-core-spinner.d.ts +4 -2
  119. package/types/neural-ui-core-table.d.ts +89 -5
  120. package/types/neural-ui-core-tags.d.ts +32 -0
  121. package/types/neural-ui-core-toolbar.d.ts +8 -2
  122. package/types/neural-ui-core-tree-select.d.ts +57 -0
  123. package/types/neural-ui-core-tree-table.d.ts +111 -4
  124. package/types/neural-ui-core-tree.d.ts +1 -1
  125. package/types/neural-ui-core-uploader.d.ts +26 -3
@@ -0,0 +1,4 @@
1
+ {
2
+ "module": "../fesm2022/neural-ui-core-bottom-sheet.mjs",
3
+ "typings": "../types/neural-ui-core-bottom-sheet.d.ts"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "module": "../fesm2022/neural-ui-core-confirm-popup.mjs",
3
+ "typings": "../types/neural-ui-core-confirm-popup.d.ts"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "module": "../fesm2022/neural-ui-core-data-view.mjs",
3
+ "typings": "../types/neural-ui-core-data-view.d.ts"
4
+ }
@@ -1,12 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { input, output, signal, computed, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
3
+ import { NeuButtonComponent } from '@neural-ui/core/button';
4
+ import { NeuIconComponent } from '@neural-ui/core/icon';
3
5
 
4
6
  /** Icono por defecto para cada tipo */
5
- const DEFAULT_ICONS = {
6
- info: '',
7
- success: '',
8
- warning: '',
9
- error: '',
7
+ const DEFAULT_ICON_NAMES = {
8
+ info: 'lucideInfo',
9
+ success: 'lucideCheckCircle',
10
+ warning: 'lucideAlertTriangle',
11
+ error: 'lucideXCircle',
10
12
  };
11
13
  let _seq = 0;
12
14
  /**
@@ -31,13 +33,14 @@ class NeuAlertComponent {
31
33
  /** Variante outline (sin fondo sólido) / Outline variant (no solid background) */
32
34
  outline = input(false, ...(ngDevMode ? [{ debugName: "outline" }] : /* istanbul ignore next */ []));
33
35
  /** Aria-label para el botón de cierre / Aria-label for the close button */
34
- closeLabel = input('Cerrar alerta', ...(ngDevMode ? [{ debugName: "closeLabel" }] : /* istanbul ignore next */ []));
36
+ closeLabel = input('Close alert', ...(ngDevMode ? [{ debugName: "closeLabel" }] : /* istanbul ignore next */ []));
35
37
  /** Emitido cuando se descarta la alerta / Emitted when the alert is dismissed */
36
38
  closed = output();
37
39
  _id = `neu-alert-${++_seq}`;
38
40
  _dismissed = signal(false, ...(ngDevMode ? [{ debugName: "_dismissed" }] : /* istanbul ignore next */ []));
39
- _resolvedIcon = computed(() => this.icon() || DEFAULT_ICONS[this.type()], ...(ngDevMode ? [{ debugName: "_resolvedIcon" }] : /* istanbul ignore next */ []));
41
+ _defaultIconName = computed(() => DEFAULT_ICON_NAMES[this.type()], ...(ngDevMode ? [{ debugName: "_defaultIconName" }] : /* istanbul ignore next */ []));
40
42
  liveRegion = computed(() => (this.type() === 'error' ? 'assertive' : 'polite'), ...(ngDevMode ? [{ debugName: "liveRegion" }] : /* istanbul ignore next */ []));
43
+ alertRole = computed(() => (this.type() === 'error' ? 'alert' : 'status'), ...(ngDevMode ? [{ debugName: "alertRole" }] : /* istanbul ignore next */ []));
41
44
  hostClasses = computed(() => ({
42
45
  'neu-alert': true,
43
46
  [`neu-alert--${this.type()}`]: true,
@@ -51,10 +54,16 @@ class NeuAlertComponent {
51
54
  this.closed.emit();
52
55
  }
53
56
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuAlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
54
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: NeuAlertComponent, isStandalone: true, selector: "neu-alert", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, outline: { classPropertyName: "outline", publicName: "outline", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { attributes: { "role": "alert" }, properties: { "class": "hostClasses()", "attr.aria-live": "liveRegion()" } }, ngImport: i0, template: `
57
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: NeuAlertComponent, isStandalone: true, selector: "neu-alert", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, showIcon: { classPropertyName: "showIcon", publicName: "showIcon", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, outline: { classPropertyName: "outline", publicName: "outline", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed" }, host: { properties: { "class": "hostClasses()", "attr.role": "alertRole()", "attr.aria-live": "liveRegion()" } }, ngImport: i0, template: `
55
58
  @if (!_dismissed()) {
56
59
  @if (showIcon()) {
57
- <span class="neu-alert__icon" aria-hidden="true">{{ _resolvedIcon() }}</span>
60
+ <span class="neu-alert__icon" aria-hidden="true">
61
+ @if (icon()) {
62
+ {{ icon() }}
63
+ } @else {
64
+ <neu-icon [name]="_defaultIconName()" size="1.1em" />
65
+ }
66
+ </span>
58
67
  }
59
68
  <div class="neu-alert__body">
60
69
  @if (title()) {
@@ -67,23 +76,37 @@ class NeuAlertComponent {
67
76
  </div>
68
77
  @if (closable()) {
69
78
  <button
79
+ neu-button
70
80
  class="neu-alert__close"
71
81
  type="button"
82
+ variant="ghost"
83
+ size="sm"
84
+ icon="lucideX"
85
+ [iconOnly]="true"
86
+ [ariaLabel]="closeLabel()"
72
87
  [attr.aria-label]="closeLabel()"
73
- (click)="dismiss()"
74
- >
75
- ×
76
- </button>
88
+ (neuClick)="dismiss()"
89
+ ></button>
77
90
  }
78
91
  }
79
- `, isInline: true, styles: ["@charset \"UTF-8\";.neu-alert{display:flex;align-items:flex-start;gap:10px;padding:12px 16px;border-radius:var(--neu-radius-md, 8px);border:1px solid transparent;font-size:.875rem;line-height:1.5;position:relative}.neu-alert--dismissed{display:none}.neu-alert--info{background:var(--neu-alert-info-bg, #eff6ff);border-color:var(--neu-alert-info-border, #bfdbfe);color:var(--neu-alert-info-text, #1d4ed8)}.neu-alert--success{background:var(--neu-alert-success-bg, #f0fdf4);border-color:var(--neu-alert-success-border, #bbf7d0);color:var(--neu-alert-success-text, #15803d)}.neu-alert--warning{background:var(--neu-alert-warning-bg, #fffbeb);border-color:var(--neu-alert-warning-border, #fde68a);color:var(--neu-alert-warning-text, #b45309)}.neu-alert--error{background:var(--neu-alert-error-bg, #fef2f2);border-color:var(--neu-alert-error-border, #fecaca);color:var(--neu-alert-error-text, #b91c1c)}.neu-alert--outline{background:transparent}.neu-alert__icon{flex-shrink:0;font-size:1.1em;line-height:1.5;font-style:normal}.neu-alert__body{flex:1;min-width:0}.neu-alert__title{display:block;font-weight:600;margin-bottom:2px}.neu-alert__content{opacity:.9}.neu-alert__close{all:unset;cursor:pointer;flex-shrink:0;font-size:1.1rem;line-height:1;opacity:.6;transition:opacity .15s;padding:2px 4px;border-radius:var(--neu-radius-sm, 4px)}.neu-alert__close:hover{opacity:1;background:var(--neu-alert-dismiss-hover-bg)}.neu-alert__close:focus-visible{outline:2px solid var(--neu-focus-ring, #0ea5e9);outline-offset:1px;opacity:1}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
92
+ `, isInline: true, styles: ["@charset \"UTF-8\";.neu-alert{display:flex;align-items:flex-start;gap:10px;padding:12px 16px;border-radius:var(--neu-radius-md, 8px);border:1px solid transparent;font-size:.875rem;line-height:1.5;position:relative}.neu-alert--dismissed{display:none}.neu-alert--info{background:var(--neu-alert-info-bg, #eff6ff);border-color:var(--neu-alert-info-border, #bfdbfe);color:var(--neu-alert-info-text, #1d4ed8)}.neu-alert--success{background:var(--neu-alert-success-bg, #f0fdf4);border-color:var(--neu-alert-success-border, #bbf7d0);color:var(--neu-alert-success-text, #15803d)}.neu-alert--warning{background:var(--neu-alert-warning-bg, #fffbeb);border-color:var(--neu-alert-warning-border, #fde68a);color:var(--neu-alert-warning-text, #b45309)}.neu-alert--error{background:var(--neu-alert-error-bg, #fef2f2);border-color:var(--neu-alert-error-border, #fecaca);color:var(--neu-alert-error-text, #b91c1c)}.neu-alert--outline{background:transparent}.neu-alert__icon{flex-shrink:0;font-size:1.1em;line-height:1.5;font-style:normal}.neu-alert__body{flex:1;min-width:0}.neu-alert__title{display:block;font-weight:600;margin-bottom:2px}.neu-alert__content{color:inherit}.neu-alert__close{flex-shrink:0;align-self:flex-start;color:inherit;opacity:.78;--neu-button-ghost-hover-bg: var(--neu-alert-dismiss-hover-bg, rgba(0, 0, 0, .08))}.neu-alert__close:hover{opacity:1}.neu-alert__close:focus-visible{opacity:1}\n"], dependencies: [{ kind: "component", type: NeuButtonComponent, selector: "button[neu-button]", inputs: ["variant", "size", "disabled", "loading", "fullWidth", "icon", "iconPosition", "iconOnly", "ariaLabel"], outputs: ["neuClick"] }, { kind: "component", type: NeuIconComponent, selector: "neu-icon", inputs: ["name", "strokeWidth", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
80
93
  }
81
94
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuAlertComponent, decorators: [{
82
95
  type: Component,
83
- args: [{ selector: 'neu-alert', imports: [], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: { '[class]': 'hostClasses()', role: 'alert', '[attr.aria-live]': 'liveRegion()' }, template: `
96
+ args: [{ selector: 'neu-alert', imports: [NeuButtonComponent, NeuIconComponent], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
97
+ '[class]': 'hostClasses()',
98
+ '[attr.role]': 'alertRole()',
99
+ '[attr.aria-live]': 'liveRegion()',
100
+ }, template: `
84
101
  @if (!_dismissed()) {
85
102
  @if (showIcon()) {
86
- <span class="neu-alert__icon" aria-hidden="true">{{ _resolvedIcon() }}</span>
103
+ <span class="neu-alert__icon" aria-hidden="true">
104
+ @if (icon()) {
105
+ {{ icon() }}
106
+ } @else {
107
+ <neu-icon [name]="_defaultIconName()" size="1.1em" />
108
+ }
109
+ </span>
87
110
  }
88
111
  <div class="neu-alert__body">
89
112
  @if (title()) {
@@ -96,16 +119,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
96
119
  </div>
97
120
  @if (closable()) {
98
121
  <button
122
+ neu-button
99
123
  class="neu-alert__close"
100
124
  type="button"
125
+ variant="ghost"
126
+ size="sm"
127
+ icon="lucideX"
128
+ [iconOnly]="true"
129
+ [ariaLabel]="closeLabel()"
101
130
  [attr.aria-label]="closeLabel()"
102
- (click)="dismiss()"
103
- >
104
- ×
105
- </button>
131
+ (neuClick)="dismiss()"
132
+ ></button>
106
133
  }
107
134
  }
108
- `, styles: ["@charset \"UTF-8\";.neu-alert{display:flex;align-items:flex-start;gap:10px;padding:12px 16px;border-radius:var(--neu-radius-md, 8px);border:1px solid transparent;font-size:.875rem;line-height:1.5;position:relative}.neu-alert--dismissed{display:none}.neu-alert--info{background:var(--neu-alert-info-bg, #eff6ff);border-color:var(--neu-alert-info-border, #bfdbfe);color:var(--neu-alert-info-text, #1d4ed8)}.neu-alert--success{background:var(--neu-alert-success-bg, #f0fdf4);border-color:var(--neu-alert-success-border, #bbf7d0);color:var(--neu-alert-success-text, #15803d)}.neu-alert--warning{background:var(--neu-alert-warning-bg, #fffbeb);border-color:var(--neu-alert-warning-border, #fde68a);color:var(--neu-alert-warning-text, #b45309)}.neu-alert--error{background:var(--neu-alert-error-bg, #fef2f2);border-color:var(--neu-alert-error-border, #fecaca);color:var(--neu-alert-error-text, #b91c1c)}.neu-alert--outline{background:transparent}.neu-alert__icon{flex-shrink:0;font-size:1.1em;line-height:1.5;font-style:normal}.neu-alert__body{flex:1;min-width:0}.neu-alert__title{display:block;font-weight:600;margin-bottom:2px}.neu-alert__content{opacity:.9}.neu-alert__close{all:unset;cursor:pointer;flex-shrink:0;font-size:1.1rem;line-height:1;opacity:.6;transition:opacity .15s;padding:2px 4px;border-radius:var(--neu-radius-sm, 4px)}.neu-alert__close:hover{opacity:1;background:var(--neu-alert-dismiss-hover-bg)}.neu-alert__close:focus-visible{outline:2px solid var(--neu-focus-ring, #0ea5e9);outline-offset:1px;opacity:1}\n"] }]
135
+ `, styles: ["@charset \"UTF-8\";.neu-alert{display:flex;align-items:flex-start;gap:10px;padding:12px 16px;border-radius:var(--neu-radius-md, 8px);border:1px solid transparent;font-size:.875rem;line-height:1.5;position:relative}.neu-alert--dismissed{display:none}.neu-alert--info{background:var(--neu-alert-info-bg, #eff6ff);border-color:var(--neu-alert-info-border, #bfdbfe);color:var(--neu-alert-info-text, #1d4ed8)}.neu-alert--success{background:var(--neu-alert-success-bg, #f0fdf4);border-color:var(--neu-alert-success-border, #bbf7d0);color:var(--neu-alert-success-text, #15803d)}.neu-alert--warning{background:var(--neu-alert-warning-bg, #fffbeb);border-color:var(--neu-alert-warning-border, #fde68a);color:var(--neu-alert-warning-text, #b45309)}.neu-alert--error{background:var(--neu-alert-error-bg, #fef2f2);border-color:var(--neu-alert-error-border, #fecaca);color:var(--neu-alert-error-text, #b91c1c)}.neu-alert--outline{background:transparent}.neu-alert__icon{flex-shrink:0;font-size:1.1em;line-height:1.5;font-style:normal}.neu-alert__body{flex:1;min-width:0}.neu-alert__title{display:block;font-weight:600;margin-bottom:2px}.neu-alert__content{color:inherit}.neu-alert__close{flex-shrink:0;align-self:flex-start;color:inherit;opacity:.78;--neu-button-ghost-hover-bg: var(--neu-alert-dismiss-hover-bg, rgba(0, 0, 0, .08))}.neu-alert__close:hover{opacity:1}.neu-alert__close:focus-visible{opacity:1}\n"] }]
109
136
  }], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], showIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "showIcon", required: false }] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], outline: [{ type: i0.Input, args: [{ isSignal: true, alias: "outline", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
110
137
 
111
138
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"neural-ui-core-alert.mjs","sources":["../../../../projects/ui-core/alert/neu-alert.component.ts","../../../../projects/ui-core/alert/neural-ui-core-alert.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n input,\n output,\n signal,\n} from '@angular/core';\n\nexport type NeuAlertType = 'info' | 'success' | 'warning' | 'error';\n\n/** Icono por defecto para cada tipo */\nconst DEFAULT_ICONS: Record<NeuAlertType, string> = {\n info: '',\n success: '',\n warning: '',\n error: '',\n};\n\nlet _seq = 0;\n\n/**\n * NeuralUI Alert Component\n *\n * Mensaje de alerta contextual con soporte de icono personalizado, slot de acciones y cierre.\n *\n * Uso: <neu-alert type=\"success\">Operación completada</neu-alert>\n * <neu-alert type=\"error\" [closable]=\"true\" (closed)=\"onClosed()\">Error de red</neu-alert>\n */\n@Component({\n selector: 'neu-alert',\n imports: [],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: { '[class]': 'hostClasses()', role: 'alert', '[attr.aria-live]': 'liveRegion()' },\n template: `\n @if (!_dismissed()) {\n @if (showIcon()) {\n <span class=\"neu-alert__icon\" aria-hidden=\"true\">{{ _resolvedIcon() }}</span>\n }\n <div class=\"neu-alert__body\">\n @if (title()) {\n <strong class=\"neu-alert__title\">{{ title() }}</strong>\n }\n <div class=\"neu-alert__content\">\n <ng-content />\n </div>\n <ng-content select=\"[neu-alert-actions]\" />\n </div>\n @if (closable()) {\n <button\n class=\"neu-alert__close\"\n type=\"button\"\n [attr.aria-label]=\"closeLabel()\"\n (click)=\"dismiss()\"\n >\n ×\n </button>\n }\n }\n `,\n styleUrl: './neu-alert.component.scss',\n})\nexport class NeuAlertComponent {\n /** Tipo semántico / Semantic type */\n readonly type = input<NeuAlertType>('info');\n\n /** Título opcional sobre el mensaje / Optional title above message */\n readonly title = input<string>('');\n\n /** Icono personalizado. Vacío = usa el icono por defecto del tipo / Custom icon. Empty = use default type icon */\n readonly icon = input<string>('');\n\n /** Muestra el icono / Shows the icon */\n readonly showIcon = input<boolean>(true);\n\n /** Permite cerrarse / Can be dismissed */\n readonly closable = input<boolean>(false);\n\n /** Variante outline (sin fondo sólido) / Outline variant (no solid background) */\n readonly outline = input<boolean>(false);\n\n /** Aria-label para el botón de cierre / Aria-label for the close button */\n readonly closeLabel = input<string>('Cerrar alerta');\n\n /** Emitido cuando se descarta la alerta / Emitted when the alert is dismissed */\n readonly closed = output<void>();\n\n readonly _id = `neu-alert-${++_seq}`;\n readonly _dismissed = signal(false);\n\n readonly _resolvedIcon = computed(() => this.icon() || DEFAULT_ICONS[this.type()]);\n\n readonly liveRegion = computed(() => (this.type() === 'error' ? 'assertive' : 'polite'));\n\n readonly hostClasses = computed(() => ({\n 'neu-alert': true,\n [`neu-alert--${this.type()}`]: true,\n 'neu-alert--outline': this.outline(),\n 'neu-alert--closable': this.closable(),\n 'neu-alert--with-icon': this.showIcon(),\n 'neu-alert--dismissed': this._dismissed(),\n }));\n\n dismiss(): void {\n this._dismissed.set(true);\n this.closed.emit();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"neural-ui-core-alert.mjs","sources":["../../../../projects/ui-core/alert/neu-alert.component.ts","../../../../projects/ui-core/alert/neural-ui-core-alert.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { NeuButtonComponent } from '@neural-ui/core/button';\nimport { NeuIconComponent } from '@neural-ui/core/icon';\n\nexport type NeuAlertType = 'info' | 'success' | 'warning' | 'error';\n\n/** Icono por defecto para cada tipo */\nconst DEFAULT_ICON_NAMES: Record<NeuAlertType, string> = {\n info: 'lucideInfo',\n success: 'lucideCheckCircle',\n warning: 'lucideAlertTriangle',\n error: 'lucideXCircle',\n};\n\nlet _seq = 0;\n\n/**\n * NeuralUI Alert Component\n *\n * Mensaje de alerta contextual con soporte de icono personalizado, slot de acciones y cierre.\n *\n * Uso: <neu-alert type=\"success\">Operación completada</neu-alert>\n * <neu-alert type=\"error\" [closable]=\"true\" (closed)=\"onClosed()\">Error de red</neu-alert>\n */\n@Component({\n selector: 'neu-alert',\n imports: [NeuButtonComponent, NeuIconComponent],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'hostClasses()',\n '[attr.role]': 'alertRole()',\n '[attr.aria-live]': 'liveRegion()',\n },\n template: `\n @if (!_dismissed()) {\n @if (showIcon()) {\n <span class=\"neu-alert__icon\" aria-hidden=\"true\">\n @if (icon()) {\n {{ icon() }}\n } @else {\n <neu-icon [name]=\"_defaultIconName()\" size=\"1.1em\" />\n }\n </span>\n }\n <div class=\"neu-alert__body\">\n @if (title()) {\n <strong class=\"neu-alert__title\">{{ title() }}</strong>\n }\n <div class=\"neu-alert__content\">\n <ng-content />\n </div>\n <ng-content select=\"[neu-alert-actions]\" />\n </div>\n @if (closable()) {\n <button\n neu-button\n class=\"neu-alert__close\"\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n icon=\"lucideX\"\n [iconOnly]=\"true\"\n [ariaLabel]=\"closeLabel()\"\n [attr.aria-label]=\"closeLabel()\"\n (neuClick)=\"dismiss()\"\n ></button>\n }\n }\n `,\n styleUrl: './neu-alert.component.scss',\n})\nexport class NeuAlertComponent {\n /** Tipo semántico / Semantic type */\n readonly type = input<NeuAlertType>('info');\n\n /** Título opcional sobre el mensaje / Optional title above message */\n readonly title = input<string>('');\n\n /** Icono personalizado. Vacío = usa el icono por defecto del tipo / Custom icon. Empty = use default type icon */\n readonly icon = input<string>('');\n\n /** Muestra el icono / Shows the icon */\n readonly showIcon = input<boolean>(true);\n\n /** Permite cerrarse / Can be dismissed */\n readonly closable = input<boolean>(false);\n\n /** Variante outline (sin fondo sólido) / Outline variant (no solid background) */\n readonly outline = input<boolean>(false);\n\n /** Aria-label para el botón de cierre / Aria-label for the close button */\n readonly closeLabel = input<string>('Close alert');\n\n /** Emitido cuando se descarta la alerta / Emitted when the alert is dismissed */\n readonly closed = output<void>();\n\n readonly _id = `neu-alert-${++_seq}`;\n readonly _dismissed = signal(false);\n\n readonly _defaultIconName = computed(() => DEFAULT_ICON_NAMES[this.type()]);\n\n readonly liveRegion = computed(() => (this.type() === 'error' ? 'assertive' : 'polite'));\n\n readonly alertRole = computed(() => (this.type() === 'error' ? 'alert' : 'status'));\n\n readonly hostClasses = computed(() => ({\n 'neu-alert': true,\n [`neu-alert--${this.type()}`]: true,\n 'neu-alert--outline': this.outline(),\n 'neu-alert--closable': this.closable(),\n 'neu-alert--with-icon': this.showIcon(),\n 'neu-alert--dismissed': this._dismissed(),\n }));\n\n dismiss(): void {\n this._dismissed.set(true);\n this.closed.emit();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
@@ -1,11 +1,23 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, output, signal, viewChild, inject, computed, ElementRef, forwardRef, HostListener, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
3
- import { DOCUMENT } from '@angular/common';
2
+ import { Directive, input, output, contentChild, signal, viewChild, inject, computed, ElementRef, forwardRef, HostListener, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
3
+ import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
4
4
  import * as i1 from '@angular/cdk/overlay';
5
5
  import { Overlay, OverlayModule } from '@angular/cdk/overlay';
6
6
  import { CdkVirtualScrollViewport, ScrollingModule } from '@angular/cdk/scrolling';
7
7
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
8
8
 
9
+ class NeuAutocompleteItemDirective {
10
+ templateRef;
11
+ constructor(templateRef) {
12
+ this.templateRef = templateRef;
13
+ }
14
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuAutocompleteItemDirective, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive });
15
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.17", type: NeuAutocompleteItemDirective, isStandalone: true, selector: "ng-template[neuAutocompleteItem]", ngImport: i0 });
16
+ }
17
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuAutocompleteItemDirective, decorators: [{
18
+ type: Directive,
19
+ args: [{ selector: 'ng-template[neuAutocompleteItem]' }]
20
+ }], ctorParameters: () => [{ type: i0.TemplateRef }] });
9
21
  let _seq = 0;
10
22
  /**
11
23
  * NeuralUI Autocomplete
@@ -30,6 +42,11 @@ class NeuAutocompleteComponent {
30
42
  errorMessage = input('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
31
43
  emptyLabel = input('Sin resultados', ...(ngDevMode ? [{ debugName: "emptyLabel" }] : /* istanbul ignore next */ []));
32
44
  minLength = input(0, ...(ngDevMode ? [{ debugName: "minLength" }] : /* istanbul ignore next */ []));
45
+ loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
46
+ loadingLabel = input('Loading...', ...(ngDevMode ? [{ debugName: "loadingLabel" }] : /* istanbul ignore next */ []));
47
+ dropdown = input(false, ...(ngDevMode ? [{ debugName: "dropdown" }] : /* istanbul ignore next */ []));
48
+ dropdownAriaLabel = input('Show suggestions', ...(ngDevMode ? [{ debugName: "dropdownAriaLabel" }] : /* istanbul ignore next */ []));
49
+ forceSelection = input(false, ...(ngDevMode ? [{ debugName: "forceSelection" }] : /* istanbul ignore next */ []));
33
50
  /** Muestra el label como flotante (true) o estático encima del campo (false) / Shows the label as floating (true) or static above the field (false) */
34
51
  floatingLabel = input(false, ...(ngDevMode ? [{ debugName: "floatingLabel" }] : /* istanbul ignore next */ []));
35
52
  /** Tamaño del campo: 'sm' = 36px | 'md' = 48px | 'lg' = 56px / Field size */
@@ -42,6 +59,7 @@ class NeuAutocompleteComponent {
42
59
  optionSelected = output();
43
60
  /** Emitido al cambiar el texto del input / Emitted on query change */
44
61
  queryChange = output();
62
+ itemTpl = contentChild(NeuAutocompleteItemDirective, ...(ngDevMode ? [{ debugName: "itemTpl" }] : /* istanbul ignore next */ []));
45
63
  // ── Internal state ───────────────────────────────────────────────
46
64
  _id = `neu-autocomplete-${++_seq}`;
47
65
  _listId = `${this._id}-list`;
@@ -91,9 +109,7 @@ class NeuAutocompleteComponent {
91
109
  // ── Computed ─────────────────────────────────────────────────────
92
110
  _filtered = computed(() => {
93
111
  const q = this._query().toLowerCase().trim();
94
- // Con query vacía nunca mostramos opciones (no queremos comportarnos como un select).
95
- // Empty query → never show options (autocomplete ≠ select).
96
- if (!q)
112
+ if (!q && !this.dropdown())
97
113
  return [];
98
114
  if (q.length < this.minLength())
99
115
  return [];
@@ -182,9 +198,20 @@ class NeuAutocompleteComponent {
182
198
  _onBlur() {
183
199
  this._focused.set(false);
184
200
  this._onTouched();
201
+ if (this.forceSelection() && this._query()) {
202
+ const match = this.options().find((option) => option.label === this._query());
203
+ if (!match) {
204
+ this.clear();
205
+ }
206
+ }
185
207
  // Small delay to allow mousedown on option to fire first
186
208
  setTimeout(() => this._closePanel(), 150);
187
209
  }
210
+ openAll() {
211
+ this._syncOverlayWidth();
212
+ this._isOpen.set(true);
213
+ this._activeIndex.set(this._filtered().findIndex((option) => !option.disabled));
214
+ }
188
215
  onKeyDown(e) {
189
216
  const total = this._filtered().length;
190
217
  if (!total && e.key !== 'Escape')
@@ -310,13 +337,13 @@ class NeuAutocompleteComponent {
310
337
  this._cvaDisabled.set(d);
311
338
  }
312
339
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuAutocompleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
313
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: NeuAutocompleteComponent, isStandalone: true, selector: "neu-autocomplete", inputs: { options: { classPropertyName: "options", publicName: "options", 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 }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, emptyLabel: { classPropertyName: "emptyLabel", publicName: "emptyLabel", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, floatingLabel: { classPropertyName: "floatingLabel", publicName: "floatingLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollVisibleItems: { classPropertyName: "virtualScrollVisibleItems", publicName: "virtualScrollVisibleItems", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { optionSelected: "optionSelected", queryChange: "queryChange" }, host: { listeners: { "document:mousedown": "onDocClick($event)", "window:resize": "onWindowResize()" }, properties: { "class.neu-autocomplete--open": "_isOpen()", "class.neu-autocomplete--disabled": "_cvaDisabled()", "class.neu-autocomplete--floating": "floatingLabel()", "class.neu-autocomplete--focused": "_focused()", "class.neu-autocomplete--has-value": "!!_query()", "class.neu-autocomplete--sm": "size() === \"sm\"", "class.neu-autocomplete--lg": "size() === \"lg\"", "style.--neu-autocomplete-option-height": "virtualScrollItemSize() + \"px\"" }, classAttribute: "neu-autocomplete" }, providers: [
340
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: NeuAutocompleteComponent, isStandalone: true, selector: "neu-autocomplete", inputs: { options: { classPropertyName: "options", publicName: "options", 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 }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, emptyLabel: { classPropertyName: "emptyLabel", publicName: "emptyLabel", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, loadingLabel: { classPropertyName: "loadingLabel", publicName: "loadingLabel", isSignal: true, isRequired: false, transformFunction: null }, dropdown: { classPropertyName: "dropdown", publicName: "dropdown", isSignal: true, isRequired: false, transformFunction: null }, dropdownAriaLabel: { classPropertyName: "dropdownAriaLabel", publicName: "dropdownAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, forceSelection: { classPropertyName: "forceSelection", publicName: "forceSelection", isSignal: true, isRequired: false, transformFunction: null }, floatingLabel: { classPropertyName: "floatingLabel", publicName: "floatingLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollVisibleItems: { classPropertyName: "virtualScrollVisibleItems", publicName: "virtualScrollVisibleItems", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { optionSelected: "optionSelected", queryChange: "queryChange" }, host: { listeners: { "document:mousedown": "onDocClick($event)", "window:resize": "onWindowResize()" }, properties: { "class.neu-autocomplete--open": "_isOpen()", "class.neu-autocomplete--disabled": "_cvaDisabled()", "class.neu-autocomplete--floating": "floatingLabel()", "class.neu-autocomplete--focused": "_focused()", "class.neu-autocomplete--has-value": "!!_query()", "class.neu-autocomplete--sm": "size() === \"sm\"", "class.neu-autocomplete--lg": "size() === \"lg\"", "style.--neu-autocomplete-option-height": "virtualScrollItemSize() + \"px\"" }, classAttribute: "neu-autocomplete" }, providers: [
314
341
  {
315
342
  provide: NG_VALUE_ACCESSOR,
316
343
  useExisting: forwardRef(() => NeuAutocompleteComponent),
317
344
  multi: true,
318
345
  },
319
- ], viewQueries: [{ propertyName: "_viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }], ngImport: i0, template: `
346
+ ], queries: [{ propertyName: "itemTpl", first: true, predicate: NeuAutocompleteItemDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_viewport", first: true, predicate: CdkVirtualScrollViewport, descendants: true, isSignal: true }], ngImport: i0, template: `
320
347
  @if (!floatingLabel() && label()) {
321
348
  <label class="neu-autocomplete__label" [for]="_id">{{ label() }}</label>
322
349
  }
@@ -364,6 +391,18 @@ class NeuAutocompleteComponent {
364
391
  ×
365
392
  </button>
366
393
  }
394
+ @if (dropdown()) {
395
+ <button
396
+ type="button"
397
+ class="neu-autocomplete__dropdown"
398
+ [attr.aria-label]="dropdownAriaLabel()"
399
+ tabindex="-1"
400
+ [disabled]="_cvaDisabled()"
401
+ (click)="openAll()"
402
+ >
403
+
404
+ </button>
405
+ }
367
406
  </div>
368
407
  <div class="neu-autocomplete__sr-status" aria-live="polite" aria-atomic="true">
369
408
  {{ resultsAnnouncement() }}
@@ -378,7 +417,33 @@ class NeuAutocompleteComponent {
378
417
  [cdkConnectedOverlayViewportMargin]="_viewportMargin"
379
418
  (detach)="_closePanel()"
380
419
  >
381
- @if (_filtered().length) {
420
+ @if (loading()) {
421
+ <div class="neu-autocomplete__empty" role="status" [style.width.px]="overlayWidth()">
422
+ {{ loadingLabel() }}
423
+ </div>
424
+ } @else if (_filtered().length) {
425
+ <ng-template #autocompleteOptionTpl let-opt let-i="index">
426
+ <div
427
+ class="neu-autocomplete__option"
428
+ role="option"
429
+ [id]="_optionId(i)"
430
+ [class.neu-autocomplete__option--active]="_activeIndex() === i"
431
+ [class.neu-autocomplete__option--disabled]="opt.disabled"
432
+ [attr.aria-selected]="_activeIndex() === i"
433
+ [attr.aria-disabled]="opt.disabled ?? false"
434
+ (mousedown)="selectOption(opt)"
435
+ >
436
+ @if (itemTpl()) {
437
+ <ng-container
438
+ [ngTemplateOutlet]="itemTpl()!.templateRef"
439
+ [ngTemplateOutletContext]="{ $implicit: opt }"
440
+ />
441
+ } @else {
442
+ {{ opt.label }}
443
+ }
444
+ </div>
445
+ </ng-template>
446
+
382
447
  @if (virtualScroll()) {
383
448
  <cdk-virtual-scroll-viewport
384
449
  class="neu-autocomplete__list neu-autocomplete__list--virtual"
@@ -389,22 +454,15 @@ class NeuAutocompleteComponent {
389
454
  [style.height]="virtualViewportHeight()"
390
455
  [style.width.px]="overlayWidth()"
391
456
  >
392
- <div
393
- *cdkVirtualFor="let opt of _filtered(); trackBy: trackByOption; let i = index"
394
- class="neu-autocomplete__option"
395
- role="option"
396
- [id]="_optionId(i)"
397
- [class.neu-autocomplete__option--active]="_activeIndex() === i"
398
- [class.neu-autocomplete__option--disabled]="opt.disabled"
399
- [attr.aria-selected]="_activeIndex() === i"
400
- [attr.aria-disabled]="opt.disabled ?? false"
401
- (mousedown)="selectOption(opt)"
402
- >
403
- {{ opt.label }}
404
- </div>
457
+ <ng-container *cdkVirtualFor="let opt of _filtered(); trackBy: trackByOption; let i = index">
458
+ <ng-container
459
+ [ngTemplateOutlet]="autocompleteOptionTpl"
460
+ [ngTemplateOutletContext]="{ $implicit: opt, index: i }"
461
+ />
462
+ </ng-container>
405
463
  </cdk-virtual-scroll-viewport>
406
464
  } @else {
407
- <ul
465
+ <div
408
466
  class="neu-autocomplete__list"
409
467
  role="listbox"
410
468
  [id]="_listId"
@@ -412,20 +470,12 @@ class NeuAutocompleteComponent {
412
470
  [style.width.px]="overlayWidth()"
413
471
  >
414
472
  @for (opt of _filtered(); track opt.label; let i = $index) {
415
- <li
416
- class="neu-autocomplete__option"
417
- role="option"
418
- [id]="_optionId(i)"
419
- [class.neu-autocomplete__option--active]="_activeIndex() === i"
420
- [class.neu-autocomplete__option--disabled]="opt.disabled"
421
- [attr.aria-selected]="_activeIndex() === i"
422
- [attr.aria-disabled]="opt.disabled ?? false"
423
- (mousedown)="selectOption(opt)"
424
- >
425
- {{ opt.label }}
426
- </li>
473
+ <ng-container
474
+ [ngTemplateOutlet]="autocompleteOptionTpl"
475
+ [ngTemplateOutletContext]="{ $implicit: opt, index: i }"
476
+ />
427
477
  }
428
- </ul>
478
+ </div>
429
479
  }
430
480
  } @else {
431
481
  <div class="neu-autocomplete__empty" role="status" [style.width.px]="overlayWidth()">
@@ -440,11 +490,11 @@ class NeuAutocompleteComponent {
440
490
  } @else if (hint()) {
441
491
  <p class="neu-autocomplete__hint" [id]="_id + '-hint'">{{ hint() }}</p>
442
492
  }
443
- `, isInline: true, styles: ["@charset \"UTF-8\";.neu-autocomplete{position:relative;display:block}.neu-autocomplete--disabled{opacity:.55;pointer-events:none}.neu-autocomplete--sm .neu-autocomplete__input{height:36px;font-size:var(--neu-text-sm, .875rem)}.neu-autocomplete--lg .neu-autocomplete__input{height:56px}.neu-autocomplete--floating.neu-autocomplete--focused .neu-autocomplete__input::placeholder{color:var(--neu-text-disabled, #9ca3af)}.neu-autocomplete--floating.neu-autocomplete--focused .neu-autocomplete__input{border-color:var(--neu-primary, #0ea5e9);box-shadow:var(--neu-focus-ring, 0 0 0 3px rgba(14, 165, 233, .2))}.neu-autocomplete__label{display:block;margin-bottom:6px;font-size:var(--neu-text-sm, .875rem);font-weight:500;color:var(--neu-text, #0f172a);line-height:1.4}.neu-autocomplete__input-wrap{position:relative;display:flex;align-items:center}.neu-autocomplete__input{width:100%;height:48px;padding:0 36px 0 12px;border:1.5px solid var(--neu-border, #d1d5db);border-radius:var(--neu-radius, 8px);background:var(--neu-surface, #ffffff);color:var(--neu-text, #111);font-size:.875rem;line-height:1.4;outline:none;transition:border-color var(--neu-transition, .12s),box-shadow var(--neu-transition, .12s),background-color var(--neu-transition, .12s)}.neu-autocomplete__input:hover{border-color:var(--neu-border-hover, var(--neu-border, #d1d5db))}.neu-autocomplete__input:focus,.neu-autocomplete__input:focus-visible{border-color:var(--neu-primary, #0ea5e9);box-shadow:var(--neu-focus-ring, 0 0 0 3px rgba(14, 165, 233, .2))}.neu-autocomplete__input[disabled]{background:var(--neu-surface-2, #f3f4f6);color:var(--neu-text-disabled, #9ca3af)}.neu-autocomplete--floating .neu-autocomplete__input::placeholder{color:transparent;transition:color var(--neu-transition)}.neu-autocomplete__floating-label{position:absolute;left:var(--neu-space-3, 12px);top:50%;transform:translateY(-50%);font-size:var(--neu-text-base, .875rem);color:var(--neu-text-muted, #6b7280);pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - var(--neu-space-6, 24px));transition:top var(--neu-transition, .12s),font-size var(--neu-transition, .12s),color var(--neu-transition, .12s),transform var(--neu-transition, .12s),padding var(--neu-transition, .12s),background var(--neu-transition, .12s)}.neu-autocomplete--focused .neu-autocomplete__floating-label,.neu-autocomplete--has-value .neu-autocomplete__floating-label{top:0;transform:translateY(-50%);font-size:12px;font-weight:600;letter-spacing:.01em;background:var(--neu-surface, #fff);padding:0 4px;left:calc(var(--neu-space-3, 12px) - 4px)}.neu-autocomplete--focused .neu-autocomplete__floating-label{color:var(--neu-primary, #0ea5e9)}.neu-autocomplete__clear{all:unset;position:absolute;right:10px;display:flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;font-size:.875rem;color:var(--neu-text-muted, #6b7280);cursor:pointer}.neu-autocomplete__clear:hover{color:var(--neu-text, #111);background:var(--neu-surface-3, #e5e7eb)}.neu-autocomplete__clear:focus-visible{outline:2px solid var(--neu-primary, #0ea5e9);outline-offset:2px}.neu-autocomplete__list{all:unset;display:block;position:relative;background:var(--neu-surface, #ffffff);border:1.5px solid var(--neu-border, #e5e7eb);border-radius:var(--neu-radius-lg, 12px);box-shadow:var(--neu-shadow-lg, 0 8px 20px -4px rgba(0, 0, 0, .1));max-height:240px;overflow-y:auto;padding:6px;z-index:1000;animation:neu-ac-in 80ms ease}.neu-autocomplete__list--virtual{padding:0;overflow:hidden}@keyframes neu-ac-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-autocomplete__option{display:flex;align-items:center;padding:7px 10px;min-height:var(--neu-autocomplete-option-height, 40px);box-sizing:border-box;border-radius:var(--neu-radius-md, 8px);font-size:.875rem;color:var(--neu-text, #111);cursor:pointer}.neu-autocomplete__option:hover:not(.neu-autocomplete__option--disabled){background:var(--neu-surface-2, #f3f4f6)}.neu-autocomplete__option--active{background:var(--neu-primary-50, rgba(14, 165, 233, .12));color:var(--neu-primary, #0ea5e9);font-weight:500}.neu-autocomplete__option--disabled{opacity:.4;cursor:not-allowed}.neu-autocomplete__empty{position:relative;background:var(--neu-surface, #ffffff);border:1.5px solid var(--neu-border, #e5e7eb);border-radius:var(--neu-radius-lg, 12px);padding:12px 16px;font-size:.875rem;color:var(--neu-text-muted, #6b7280);text-align:center}.neu-autocomplete__hint,.neu-autocomplete__error{margin:6px 0 0;font-size:var(--neu-text-sm, .875rem);line-height:1.4}.neu-autocomplete__hint{color:var(--neu-text-muted, #6b7280)}.neu-autocomplete__error{color:var(--neu-danger, #dc2626)}.neu-autocomplete__sr-status{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: i1.ɵɵCdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.ɵɵCdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.ɵɵCdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "ngmodule", type: ScrollingModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
493
+ `, isInline: true, styles: ["@charset \"UTF-8\";.neu-autocomplete{position:relative;display:block}.neu-autocomplete--disabled{opacity:.55;pointer-events:none}.neu-autocomplete--sm .neu-autocomplete__input{height:36px;font-size:var(--neu-text-sm, .875rem)}.neu-autocomplete--lg .neu-autocomplete__input{height:56px}.neu-autocomplete--floating.neu-autocomplete--focused .neu-autocomplete__input::placeholder{color:var(--neu-text-disabled, #9ca3af)}.neu-autocomplete--floating.neu-autocomplete--focused .neu-autocomplete__input{border-color:var(--neu-primary, #0ea5e9);box-shadow:var(--neu-focus-ring, 0 0 0 3px rgba(14, 165, 233, .2))}.neu-autocomplete__label{display:block;margin-bottom:6px;font-size:var(--neu-text-sm, .875rem);font-weight:500;color:var(--neu-text, #0f172a);line-height:1.4}.neu-autocomplete__input-wrap{position:relative;display:flex;align-items:center}.neu-autocomplete__input{width:100%;height:48px;padding:0 36px 0 12px;border:1.5px solid var(--neu-border, #d1d5db);border-radius:var(--neu-radius, 8px);background:var(--neu-surface, #ffffff);color:var(--neu-text, #111);font-size:.875rem;line-height:1.4;outline:none;transition:border-color var(--neu-transition, .12s),box-shadow var(--neu-transition, .12s),background-color var(--neu-transition, .12s)}.neu-autocomplete__input:hover{border-color:var(--neu-border-hover, var(--neu-border, #d1d5db))}.neu-autocomplete__input:focus,.neu-autocomplete__input:focus-visible{border-color:var(--neu-primary, #0ea5e9);box-shadow:var(--neu-focus-ring, 0 0 0 3px rgba(14, 165, 233, .2))}.neu-autocomplete__input[disabled]{background:var(--neu-surface-2, #f3f4f6);color:var(--neu-text-disabled, #9ca3af)}.neu-autocomplete--floating .neu-autocomplete__input::placeholder{color:transparent;transition:color var(--neu-transition)}.neu-autocomplete__floating-label{position:absolute;left:var(--neu-space-3, 12px);top:50%;transform:translateY(-50%);font-size:var(--neu-text-base, .875rem);color:var(--neu-text-muted, #6b7280);pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - var(--neu-space-6, 24px));transition:top var(--neu-transition, .12s),font-size var(--neu-transition, .12s),color var(--neu-transition, .12s),transform var(--neu-transition, .12s),padding var(--neu-transition, .12s),background var(--neu-transition, .12s)}.neu-autocomplete--focused .neu-autocomplete__floating-label,.neu-autocomplete--has-value .neu-autocomplete__floating-label{top:0;transform:translateY(-50%);font-size:12px;font-weight:600;letter-spacing:.01em;background:var(--neu-surface, #fff);padding:0 4px;left:calc(var(--neu-space-3, 12px) - 4px)}.neu-autocomplete--focused .neu-autocomplete__floating-label{color:var(--neu-primary, #0ea5e9)}.neu-autocomplete__clear{all:unset;position:absolute;right:10px;display:flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;font-size:.875rem;color:var(--neu-text-muted, #6b7280);cursor:pointer}.neu-autocomplete__clear:hover{color:var(--neu-text, #111);background:var(--neu-surface-3, #e5e7eb)}.neu-autocomplete__clear:focus-visible{outline:2px solid var(--neu-primary, #0ea5e9);outline-offset:2px}.neu-autocomplete__list{all:unset;display:block;position:relative;background:var(--neu-surface, #ffffff);border:1.5px solid var(--neu-border, #e5e7eb);border-radius:var(--neu-radius-lg, 12px);box-shadow:var(--neu-shadow-lg, 0 8px 20px -4px rgba(0, 0, 0, .1));max-height:240px;overflow-y:auto;padding:6px;z-index:1000;animation:neu-ac-in 80ms ease}.neu-autocomplete__list--virtual{padding:0;overflow:hidden}@keyframes neu-ac-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-autocomplete__option{display:flex;align-items:center;padding:7px 10px;min-height:var(--neu-autocomplete-option-height, 40px);box-sizing:border-box;border-radius:var(--neu-radius-md, 8px);font-size:.875rem;color:var(--neu-text, #111);cursor:pointer}.neu-autocomplete__option:hover:not(.neu-autocomplete__option--disabled){background:var(--neu-surface-2, #f3f4f6)}.neu-autocomplete__option--active{background:var(--neu-primary-50, rgba(14, 165, 233, .12));color:var(--neu-primary, #0ea5e9);font-weight:500}.neu-autocomplete__option--disabled{opacity:.4;cursor:not-allowed}.neu-autocomplete__empty{position:relative;background:var(--neu-surface, #ffffff);border:1.5px solid var(--neu-border, #e5e7eb);border-radius:var(--neu-radius-lg, 12px);padding:12px 16px;font-size:.875rem;color:var(--neu-text-muted, #6b7280);text-align:center}.neu-autocomplete__hint,.neu-autocomplete__error{margin:6px 0 0;font-size:var(--neu-text-sm, .875rem);line-height:1.4}.neu-autocomplete__hint{color:var(--neu-text-muted, #6b7280)}.neu-autocomplete__error{color:var(--neu-danger, #dc2626)}.neu-autocomplete__sr-status{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.neu-autocomplete__dropdown{position:absolute;right:6px;top:50%;transform:translateY(-50%);border:0;border-radius:var(--neu-radius-md, 8px);background:transparent;color:var(--neu-text-muted, #6b7280);cursor:pointer;padding:4px 6px}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: i1.ɵɵCdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.ɵɵCdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.ɵɵCdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "ngmodule", type: ScrollingModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
444
494
  }
445
495
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: NeuAutocompleteComponent, decorators: [{
446
496
  type: Component,
447
- args: [{ selector: 'neu-autocomplete', imports: [OverlayModule, ScrollingModule], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
497
+ args: [{ selector: 'neu-autocomplete', imports: [NgTemplateOutlet, OverlayModule, ScrollingModule], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
448
498
  {
449
499
  provide: NG_VALUE_ACCESSOR,
450
500
  useExisting: forwardRef(() => NeuAutocompleteComponent),
@@ -508,6 +558,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
508
558
  ×
509
559
  </button>
510
560
  }
561
+ @if (dropdown()) {
562
+ <button
563
+ type="button"
564
+ class="neu-autocomplete__dropdown"
565
+ [attr.aria-label]="dropdownAriaLabel()"
566
+ tabindex="-1"
567
+ [disabled]="_cvaDisabled()"
568
+ (click)="openAll()"
569
+ >
570
+
571
+ </button>
572
+ }
511
573
  </div>
512
574
  <div class="neu-autocomplete__sr-status" aria-live="polite" aria-atomic="true">
513
575
  {{ resultsAnnouncement() }}
@@ -522,7 +584,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
522
584
  [cdkConnectedOverlayViewportMargin]="_viewportMargin"
523
585
  (detach)="_closePanel()"
524
586
  >
525
- @if (_filtered().length) {
587
+ @if (loading()) {
588
+ <div class="neu-autocomplete__empty" role="status" [style.width.px]="overlayWidth()">
589
+ {{ loadingLabel() }}
590
+ </div>
591
+ } @else if (_filtered().length) {
592
+ <ng-template #autocompleteOptionTpl let-opt let-i="index">
593
+ <div
594
+ class="neu-autocomplete__option"
595
+ role="option"
596
+ [id]="_optionId(i)"
597
+ [class.neu-autocomplete__option--active]="_activeIndex() === i"
598
+ [class.neu-autocomplete__option--disabled]="opt.disabled"
599
+ [attr.aria-selected]="_activeIndex() === i"
600
+ [attr.aria-disabled]="opt.disabled ?? false"
601
+ (mousedown)="selectOption(opt)"
602
+ >
603
+ @if (itemTpl()) {
604
+ <ng-container
605
+ [ngTemplateOutlet]="itemTpl()!.templateRef"
606
+ [ngTemplateOutletContext]="{ $implicit: opt }"
607
+ />
608
+ } @else {
609
+ {{ opt.label }}
610
+ }
611
+ </div>
612
+ </ng-template>
613
+
526
614
  @if (virtualScroll()) {
527
615
  <cdk-virtual-scroll-viewport
528
616
  class="neu-autocomplete__list neu-autocomplete__list--virtual"
@@ -533,22 +621,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
533
621
  [style.height]="virtualViewportHeight()"
534
622
  [style.width.px]="overlayWidth()"
535
623
  >
536
- <div
537
- *cdkVirtualFor="let opt of _filtered(); trackBy: trackByOption; let i = index"
538
- class="neu-autocomplete__option"
539
- role="option"
540
- [id]="_optionId(i)"
541
- [class.neu-autocomplete__option--active]="_activeIndex() === i"
542
- [class.neu-autocomplete__option--disabled]="opt.disabled"
543
- [attr.aria-selected]="_activeIndex() === i"
544
- [attr.aria-disabled]="opt.disabled ?? false"
545
- (mousedown)="selectOption(opt)"
546
- >
547
- {{ opt.label }}
548
- </div>
624
+ <ng-container *cdkVirtualFor="let opt of _filtered(); trackBy: trackByOption; let i = index">
625
+ <ng-container
626
+ [ngTemplateOutlet]="autocompleteOptionTpl"
627
+ [ngTemplateOutletContext]="{ $implicit: opt, index: i }"
628
+ />
629
+ </ng-container>
549
630
  </cdk-virtual-scroll-viewport>
550
631
  } @else {
551
- <ul
632
+ <div
552
633
  class="neu-autocomplete__list"
553
634
  role="listbox"
554
635
  [id]="_listId"
@@ -556,20 +637,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
556
637
  [style.width.px]="overlayWidth()"
557
638
  >
558
639
  @for (opt of _filtered(); track opt.label; let i = $index) {
559
- <li
560
- class="neu-autocomplete__option"
561
- role="option"
562
- [id]="_optionId(i)"
563
- [class.neu-autocomplete__option--active]="_activeIndex() === i"
564
- [class.neu-autocomplete__option--disabled]="opt.disabled"
565
- [attr.aria-selected]="_activeIndex() === i"
566
- [attr.aria-disabled]="opt.disabled ?? false"
567
- (mousedown)="selectOption(opt)"
568
- >
569
- {{ opt.label }}
570
- </li>
640
+ <ng-container
641
+ [ngTemplateOutlet]="autocompleteOptionTpl"
642
+ [ngTemplateOutletContext]="{ $implicit: opt, index: i }"
643
+ />
571
644
  }
572
- </ul>
645
+ </div>
573
646
  }
574
647
  } @else {
575
648
  <div class="neu-autocomplete__empty" role="status" [style.width.px]="overlayWidth()">
@@ -584,8 +657,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
584
657
  } @else if (hint()) {
585
658
  <p class="neu-autocomplete__hint" [id]="_id + '-hint'">{{ hint() }}</p>
586
659
  }
587
- `, styles: ["@charset \"UTF-8\";.neu-autocomplete{position:relative;display:block}.neu-autocomplete--disabled{opacity:.55;pointer-events:none}.neu-autocomplete--sm .neu-autocomplete__input{height:36px;font-size:var(--neu-text-sm, .875rem)}.neu-autocomplete--lg .neu-autocomplete__input{height:56px}.neu-autocomplete--floating.neu-autocomplete--focused .neu-autocomplete__input::placeholder{color:var(--neu-text-disabled, #9ca3af)}.neu-autocomplete--floating.neu-autocomplete--focused .neu-autocomplete__input{border-color:var(--neu-primary, #0ea5e9);box-shadow:var(--neu-focus-ring, 0 0 0 3px rgba(14, 165, 233, .2))}.neu-autocomplete__label{display:block;margin-bottom:6px;font-size:var(--neu-text-sm, .875rem);font-weight:500;color:var(--neu-text, #0f172a);line-height:1.4}.neu-autocomplete__input-wrap{position:relative;display:flex;align-items:center}.neu-autocomplete__input{width:100%;height:48px;padding:0 36px 0 12px;border:1.5px solid var(--neu-border, #d1d5db);border-radius:var(--neu-radius, 8px);background:var(--neu-surface, #ffffff);color:var(--neu-text, #111);font-size:.875rem;line-height:1.4;outline:none;transition:border-color var(--neu-transition, .12s),box-shadow var(--neu-transition, .12s),background-color var(--neu-transition, .12s)}.neu-autocomplete__input:hover{border-color:var(--neu-border-hover, var(--neu-border, #d1d5db))}.neu-autocomplete__input:focus,.neu-autocomplete__input:focus-visible{border-color:var(--neu-primary, #0ea5e9);box-shadow:var(--neu-focus-ring, 0 0 0 3px rgba(14, 165, 233, .2))}.neu-autocomplete__input[disabled]{background:var(--neu-surface-2, #f3f4f6);color:var(--neu-text-disabled, #9ca3af)}.neu-autocomplete--floating .neu-autocomplete__input::placeholder{color:transparent;transition:color var(--neu-transition)}.neu-autocomplete__floating-label{position:absolute;left:var(--neu-space-3, 12px);top:50%;transform:translateY(-50%);font-size:var(--neu-text-base, .875rem);color:var(--neu-text-muted, #6b7280);pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - var(--neu-space-6, 24px));transition:top var(--neu-transition, .12s),font-size var(--neu-transition, .12s),color var(--neu-transition, .12s),transform var(--neu-transition, .12s),padding var(--neu-transition, .12s),background var(--neu-transition, .12s)}.neu-autocomplete--focused .neu-autocomplete__floating-label,.neu-autocomplete--has-value .neu-autocomplete__floating-label{top:0;transform:translateY(-50%);font-size:12px;font-weight:600;letter-spacing:.01em;background:var(--neu-surface, #fff);padding:0 4px;left:calc(var(--neu-space-3, 12px) - 4px)}.neu-autocomplete--focused .neu-autocomplete__floating-label{color:var(--neu-primary, #0ea5e9)}.neu-autocomplete__clear{all:unset;position:absolute;right:10px;display:flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;font-size:.875rem;color:var(--neu-text-muted, #6b7280);cursor:pointer}.neu-autocomplete__clear:hover{color:var(--neu-text, #111);background:var(--neu-surface-3, #e5e7eb)}.neu-autocomplete__clear:focus-visible{outline:2px solid var(--neu-primary, #0ea5e9);outline-offset:2px}.neu-autocomplete__list{all:unset;display:block;position:relative;background:var(--neu-surface, #ffffff);border:1.5px solid var(--neu-border, #e5e7eb);border-radius:var(--neu-radius-lg, 12px);box-shadow:var(--neu-shadow-lg, 0 8px 20px -4px rgba(0, 0, 0, .1));max-height:240px;overflow-y:auto;padding:6px;z-index:1000;animation:neu-ac-in 80ms ease}.neu-autocomplete__list--virtual{padding:0;overflow:hidden}@keyframes neu-ac-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-autocomplete__option{display:flex;align-items:center;padding:7px 10px;min-height:var(--neu-autocomplete-option-height, 40px);box-sizing:border-box;border-radius:var(--neu-radius-md, 8px);font-size:.875rem;color:var(--neu-text, #111);cursor:pointer}.neu-autocomplete__option:hover:not(.neu-autocomplete__option--disabled){background:var(--neu-surface-2, #f3f4f6)}.neu-autocomplete__option--active{background:var(--neu-primary-50, rgba(14, 165, 233, .12));color:var(--neu-primary, #0ea5e9);font-weight:500}.neu-autocomplete__option--disabled{opacity:.4;cursor:not-allowed}.neu-autocomplete__empty{position:relative;background:var(--neu-surface, #ffffff);border:1.5px solid var(--neu-border, #e5e7eb);border-radius:var(--neu-radius-lg, 12px);padding:12px 16px;font-size:.875rem;color:var(--neu-text-muted, #6b7280);text-align:center}.neu-autocomplete__hint,.neu-autocomplete__error{margin:6px 0 0;font-size:var(--neu-text-sm, .875rem);line-height:1.4}.neu-autocomplete__hint{color:var(--neu-text-muted, #6b7280)}.neu-autocomplete__error{color:var(--neu-danger, #dc2626)}.neu-autocomplete__sr-status{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
588
- }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", 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 }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], emptyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyLabel", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], floatingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "floatingLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollVisibleItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollVisibleItems", required: false }] }], optionSelected: [{ type: i0.Output, args: ["optionSelected"] }], queryChange: [{ type: i0.Output, args: ["queryChange"] }], _viewport: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }] }], onDocClick: [{
660
+ `, styles: ["@charset \"UTF-8\";.neu-autocomplete{position:relative;display:block}.neu-autocomplete--disabled{opacity:.55;pointer-events:none}.neu-autocomplete--sm .neu-autocomplete__input{height:36px;font-size:var(--neu-text-sm, .875rem)}.neu-autocomplete--lg .neu-autocomplete__input{height:56px}.neu-autocomplete--floating.neu-autocomplete--focused .neu-autocomplete__input::placeholder{color:var(--neu-text-disabled, #9ca3af)}.neu-autocomplete--floating.neu-autocomplete--focused .neu-autocomplete__input{border-color:var(--neu-primary, #0ea5e9);box-shadow:var(--neu-focus-ring, 0 0 0 3px rgba(14, 165, 233, .2))}.neu-autocomplete__label{display:block;margin-bottom:6px;font-size:var(--neu-text-sm, .875rem);font-weight:500;color:var(--neu-text, #0f172a);line-height:1.4}.neu-autocomplete__input-wrap{position:relative;display:flex;align-items:center}.neu-autocomplete__input{width:100%;height:48px;padding:0 36px 0 12px;border:1.5px solid var(--neu-border, #d1d5db);border-radius:var(--neu-radius, 8px);background:var(--neu-surface, #ffffff);color:var(--neu-text, #111);font-size:.875rem;line-height:1.4;outline:none;transition:border-color var(--neu-transition, .12s),box-shadow var(--neu-transition, .12s),background-color var(--neu-transition, .12s)}.neu-autocomplete__input:hover{border-color:var(--neu-border-hover, var(--neu-border, #d1d5db))}.neu-autocomplete__input:focus,.neu-autocomplete__input:focus-visible{border-color:var(--neu-primary, #0ea5e9);box-shadow:var(--neu-focus-ring, 0 0 0 3px rgba(14, 165, 233, .2))}.neu-autocomplete__input[disabled]{background:var(--neu-surface-2, #f3f4f6);color:var(--neu-text-disabled, #9ca3af)}.neu-autocomplete--floating .neu-autocomplete__input::placeholder{color:transparent;transition:color var(--neu-transition)}.neu-autocomplete__floating-label{position:absolute;left:var(--neu-space-3, 12px);top:50%;transform:translateY(-50%);font-size:var(--neu-text-base, .875rem);color:var(--neu-text-muted, #6b7280);pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - var(--neu-space-6, 24px));transition:top var(--neu-transition, .12s),font-size var(--neu-transition, .12s),color var(--neu-transition, .12s),transform var(--neu-transition, .12s),padding var(--neu-transition, .12s),background var(--neu-transition, .12s)}.neu-autocomplete--focused .neu-autocomplete__floating-label,.neu-autocomplete--has-value .neu-autocomplete__floating-label{top:0;transform:translateY(-50%);font-size:12px;font-weight:600;letter-spacing:.01em;background:var(--neu-surface, #fff);padding:0 4px;left:calc(var(--neu-space-3, 12px) - 4px)}.neu-autocomplete--focused .neu-autocomplete__floating-label{color:var(--neu-primary, #0ea5e9)}.neu-autocomplete__clear{all:unset;position:absolute;right:10px;display:flex;align-items:center;justify-content:center;width:18px;height:18px;border-radius:50%;font-size:.875rem;color:var(--neu-text-muted, #6b7280);cursor:pointer}.neu-autocomplete__clear:hover{color:var(--neu-text, #111);background:var(--neu-surface-3, #e5e7eb)}.neu-autocomplete__clear:focus-visible{outline:2px solid var(--neu-primary, #0ea5e9);outline-offset:2px}.neu-autocomplete__list{all:unset;display:block;position:relative;background:var(--neu-surface, #ffffff);border:1.5px solid var(--neu-border, #e5e7eb);border-radius:var(--neu-radius-lg, 12px);box-shadow:var(--neu-shadow-lg, 0 8px 20px -4px rgba(0, 0, 0, .1));max-height:240px;overflow-y:auto;padding:6px;z-index:1000;animation:neu-ac-in 80ms ease}.neu-autocomplete__list--virtual{padding:0;overflow:hidden}@keyframes neu-ac-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-autocomplete__option{display:flex;align-items:center;padding:7px 10px;min-height:var(--neu-autocomplete-option-height, 40px);box-sizing:border-box;border-radius:var(--neu-radius-md, 8px);font-size:.875rem;color:var(--neu-text, #111);cursor:pointer}.neu-autocomplete__option:hover:not(.neu-autocomplete__option--disabled){background:var(--neu-surface-2, #f3f4f6)}.neu-autocomplete__option--active{background:var(--neu-primary-50, rgba(14, 165, 233, .12));color:var(--neu-primary, #0ea5e9);font-weight:500}.neu-autocomplete__option--disabled{opacity:.4;cursor:not-allowed}.neu-autocomplete__empty{position:relative;background:var(--neu-surface, #ffffff);border:1.5px solid var(--neu-border, #e5e7eb);border-radius:var(--neu-radius-lg, 12px);padding:12px 16px;font-size:.875rem;color:var(--neu-text-muted, #6b7280);text-align:center}.neu-autocomplete__hint,.neu-autocomplete__error{margin:6px 0 0;font-size:var(--neu-text-sm, .875rem);line-height:1.4}.neu-autocomplete__hint{color:var(--neu-text-muted, #6b7280)}.neu-autocomplete__error{color:var(--neu-danger, #dc2626)}.neu-autocomplete__sr-status{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.neu-autocomplete__dropdown{position:absolute;right:6px;top:50%;transform:translateY(-50%);border:0;border-radius:var(--neu-radius-md, 8px);background:transparent;color:var(--neu-text-muted, #6b7280);cursor:pointer;padding:4px 6px}\n"] }]
661
+ }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", 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 }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], emptyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyLabel", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], loadingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingLabel", required: false }] }], dropdown: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdown", required: false }] }], dropdownAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropdownAriaLabel", required: false }] }], forceSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "forceSelection", required: false }] }], floatingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "floatingLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollVisibleItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollVisibleItems", required: false }] }], optionSelected: [{ type: i0.Output, args: ["optionSelected"] }], queryChange: [{ type: i0.Output, args: ["queryChange"] }], itemTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NeuAutocompleteItemDirective), { isSignal: true }] }], _viewport: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }] }], onDocClick: [{
589
662
  type: HostListener,
590
663
  args: ['document:mousedown', ['$event']]
591
664
  }], onWindowResize: [{
@@ -597,5 +670,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
597
670
  * Generated bundle index. Do not edit.
598
671
  */
599
672
 
600
- export { NeuAutocompleteComponent };
673
+ export { NeuAutocompleteComponent, NeuAutocompleteItemDirective };
601
674
  //# sourceMappingURL=neural-ui-core-autocomplete.mjs.map