@neural-ui/core 1.2.1 → 1.3.1

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 (239) hide show
  1. package/README.md +56 -88
  2. package/accordion/package.json +4 -0
  3. package/alert/package.json +4 -0
  4. package/autocomplete/package.json +4 -0
  5. package/avatar/package.json +4 -0
  6. package/badge/package.json +4 -0
  7. package/block-ui/package.json +4 -0
  8. package/breadcrumb/package.json +4 -0
  9. package/button/package.json +4 -0
  10. package/card/package.json +4 -0
  11. package/chart/package.json +4 -0
  12. package/checkbox/package.json +4 -0
  13. package/chip/package.json +4 -0
  14. package/code-block/package.json +4 -0
  15. package/color-picker/package.json +4 -0
  16. package/command-palette/package.json +4 -0
  17. package/confirm-dialog/package.json +4 -0
  18. package/context-menu/package.json +4 -0
  19. package/dashboard-grid/package.json +4 -0
  20. package/date-input/package.json +4 -0
  21. package/divider/package.json +4 -0
  22. package/empty-state/package.json +4 -0
  23. package/fesm2022/neural-ui-core-accordion.mjs +162 -0
  24. package/fesm2022/neural-ui-core-accordion.mjs.map +1 -0
  25. package/fesm2022/neural-ui-core-alert.mjs +116 -0
  26. package/fesm2022/neural-ui-core-alert.mjs.map +1 -0
  27. package/fesm2022/neural-ui-core-autocomplete.mjs +406 -0
  28. package/fesm2022/neural-ui-core-autocomplete.mjs.map +1 -0
  29. package/fesm2022/neural-ui-core-avatar.mjs +109 -0
  30. package/fesm2022/neural-ui-core-avatar.mjs.map +1 -0
  31. package/fesm2022/neural-ui-core-badge.mjs +54 -0
  32. package/fesm2022/neural-ui-core-badge.mjs.map +1 -0
  33. package/fesm2022/neural-ui-core-block-ui.mjs +95 -0
  34. package/fesm2022/neural-ui-core-block-ui.mjs.map +1 -0
  35. package/fesm2022/neural-ui-core-breadcrumb.mjs +84 -0
  36. package/fesm2022/neural-ui-core-breadcrumb.mjs.map +1 -0
  37. package/fesm2022/neural-ui-core-button.mjs +125 -0
  38. package/fesm2022/neural-ui-core-button.mjs.map +1 -0
  39. package/fesm2022/neural-ui-core-card.mjs +69 -0
  40. package/fesm2022/neural-ui-core-card.mjs.map +1 -0
  41. package/fesm2022/neural-ui-core-chart.mjs +287 -0
  42. package/fesm2022/neural-ui-core-chart.mjs.map +1 -0
  43. package/fesm2022/neural-ui-core-checkbox.mjs +138 -0
  44. package/fesm2022/neural-ui-core-checkbox.mjs.map +1 -0
  45. package/fesm2022/neural-ui-core-chip.mjs +130 -0
  46. package/fesm2022/neural-ui-core-chip.mjs.map +1 -0
  47. package/fesm2022/neural-ui-core-code-block.mjs +250 -0
  48. package/fesm2022/neural-ui-core-code-block.mjs.map +1 -0
  49. package/fesm2022/neural-ui-core-color-picker.mjs +435 -0
  50. package/fesm2022/neural-ui-core-color-picker.mjs.map +1 -0
  51. package/fesm2022/neural-ui-core-command-palette.mjs +235 -0
  52. package/fesm2022/neural-ui-core-command-palette.mjs.map +1 -0
  53. package/fesm2022/neural-ui-core-confirm-dialog.mjs +118 -0
  54. package/fesm2022/neural-ui-core-confirm-dialog.mjs.map +1 -0
  55. package/fesm2022/neural-ui-core-context-menu.mjs +158 -0
  56. package/fesm2022/neural-ui-core-context-menu.mjs.map +1 -0
  57. package/fesm2022/neural-ui-core-dashboard-grid.mjs +144 -0
  58. package/fesm2022/neural-ui-core-dashboard-grid.mjs.map +1 -0
  59. package/fesm2022/neural-ui-core-date-input.mjs +1332 -0
  60. package/fesm2022/neural-ui-core-date-input.mjs.map +1 -0
  61. package/fesm2022/neural-ui-core-divider.mjs +54 -0
  62. package/fesm2022/neural-ui-core-divider.mjs.map +1 -0
  63. package/fesm2022/neural-ui-core-empty-state.mjs +84 -0
  64. package/fesm2022/neural-ui-core-empty-state.mjs.map +1 -0
  65. package/fesm2022/neural-ui-core-filter-bar.mjs +118 -0
  66. package/fesm2022/neural-ui-core-filter-bar.mjs.map +1 -0
  67. package/fesm2022/neural-ui-core-icon.mjs +50 -0
  68. package/fesm2022/neural-ui-core-icon.mjs.map +1 -0
  69. package/fesm2022/neural-ui-core-image-viewer.mjs +309 -0
  70. package/fesm2022/neural-ui-core-image-viewer.mjs.map +1 -0
  71. package/fesm2022/neural-ui-core-input-otp.mjs +192 -0
  72. package/fesm2022/neural-ui-core-input-otp.mjs.map +1 -0
  73. package/fesm2022/neural-ui-core-input.mjs +320 -0
  74. package/fesm2022/neural-ui-core-input.mjs.map +1 -0
  75. package/fesm2022/neural-ui-core-knob.mjs +323 -0
  76. package/fesm2022/neural-ui-core-knob.mjs.map +1 -0
  77. package/fesm2022/neural-ui-core-meter-group.mjs +122 -0
  78. package/fesm2022/neural-ui-core-meter-group.mjs.map +1 -0
  79. package/fesm2022/neural-ui-core-modal.mjs +156 -0
  80. package/fesm2022/neural-ui-core-modal.mjs.map +1 -0
  81. package/fesm2022/neural-ui-core-multiselect.mjs +825 -0
  82. package/fesm2022/neural-ui-core-multiselect.mjs.map +1 -0
  83. package/fesm2022/neural-ui-core-nav.mjs +952 -0
  84. package/fesm2022/neural-ui-core-nav.mjs.map +1 -0
  85. package/fesm2022/neural-ui-core-notification-center.mjs +264 -0
  86. package/fesm2022/neural-ui-core-notification-center.mjs.map +1 -0
  87. package/fesm2022/neural-ui-core-number-input.mjs +331 -0
  88. package/fesm2022/neural-ui-core-number-input.mjs.map +1 -0
  89. package/fesm2022/neural-ui-core-pagination.mjs +198 -0
  90. package/fesm2022/neural-ui-core-pagination.mjs.map +1 -0
  91. package/fesm2022/neural-ui-core-popover.mjs +207 -0
  92. package/fesm2022/neural-ui-core-popover.mjs.map +1 -0
  93. package/fesm2022/neural-ui-core-progress-bar.mjs +105 -0
  94. package/fesm2022/neural-ui-core-progress-bar.mjs.map +1 -0
  95. package/fesm2022/neural-ui-core-radio.mjs +171 -0
  96. package/fesm2022/neural-ui-core-radio.mjs.map +1 -0
  97. package/fesm2022/neural-ui-core-rating.mjs +151 -0
  98. package/fesm2022/neural-ui-core-rating.mjs.map +1 -0
  99. package/fesm2022/neural-ui-core-select.mjs +710 -0
  100. package/fesm2022/neural-ui-core-select.mjs.map +1 -0
  101. package/fesm2022/neural-ui-core-sidebar.mjs +214 -0
  102. package/fesm2022/neural-ui-core-sidebar.mjs.map +1 -0
  103. package/fesm2022/neural-ui-core-skeleton.mjs +40 -0
  104. package/fesm2022/neural-ui-core-skeleton.mjs.map +1 -0
  105. package/fesm2022/neural-ui-core-slider.mjs +146 -0
  106. package/fesm2022/neural-ui-core-slider.mjs.map +1 -0
  107. package/fesm2022/neural-ui-core-spinner.mjs +113 -0
  108. package/fesm2022/neural-ui-core-spinner.mjs.map +1 -0
  109. package/fesm2022/neural-ui-core-split-button.mjs +252 -0
  110. package/fesm2022/neural-ui-core-split-button.mjs.map +1 -0
  111. package/fesm2022/neural-ui-core-splitter.mjs +174 -0
  112. package/fesm2022/neural-ui-core-splitter.mjs.map +1 -0
  113. package/fesm2022/neural-ui-core-stats-card.mjs +163 -0
  114. package/fesm2022/neural-ui-core-stats-card.mjs.map +1 -0
  115. package/fesm2022/neural-ui-core-stepper.mjs +204 -0
  116. package/fesm2022/neural-ui-core-stepper.mjs.map +1 -0
  117. package/fesm2022/neural-ui-core-switch.mjs +111 -0
  118. package/fesm2022/neural-ui-core-switch.mjs.map +1 -0
  119. package/fesm2022/neural-ui-core-table.mjs +1872 -0
  120. package/fesm2022/neural-ui-core-table.mjs.map +1 -0
  121. package/fesm2022/neural-ui-core-tabs.mjs +338 -0
  122. package/fesm2022/neural-ui-core-tabs.mjs.map +1 -0
  123. package/fesm2022/neural-ui-core-textarea.mjs +188 -0
  124. package/fesm2022/neural-ui-core-textarea.mjs.map +1 -0
  125. package/fesm2022/neural-ui-core-timeline.mjs +117 -0
  126. package/fesm2022/neural-ui-core-timeline.mjs.map +1 -0
  127. package/fesm2022/neural-ui-core-toast.mjs +171 -0
  128. package/fesm2022/neural-ui-core-toast.mjs.map +1 -0
  129. package/fesm2022/neural-ui-core-toggle-button-group.mjs +162 -0
  130. package/fesm2022/neural-ui-core-toggle-button-group.mjs.map +1 -0
  131. package/fesm2022/neural-ui-core-toolbar.mjs +67 -0
  132. package/fesm2022/neural-ui-core-toolbar.mjs.map +1 -0
  133. package/fesm2022/neural-ui-core-tooltip.mjs +151 -0
  134. package/fesm2022/neural-ui-core-tooltip.mjs.map +1 -0
  135. package/fesm2022/neural-ui-core-url-state.mjs +96 -0
  136. package/fesm2022/neural-ui-core-url-state.mjs.map +1 -0
  137. package/fesm2022/neural-ui-core-virtual-list.mjs +126 -0
  138. package/fesm2022/neural-ui-core-virtual-list.mjs.map +1 -0
  139. package/fesm2022/neural-ui-core.mjs +11 -8544
  140. package/fesm2022/neural-ui-core.mjs.map +1 -1
  141. package/filter-bar/package.json +4 -0
  142. package/icon/package.json +4 -0
  143. package/image-viewer/package.json +4 -0
  144. package/input/package.json +4 -0
  145. package/input-otp/package.json +4 -0
  146. package/knob/package.json +4 -0
  147. package/meter-group/package.json +4 -0
  148. package/modal/package.json +4 -0
  149. package/multiselect/package.json +4 -0
  150. package/nav/package.json +4 -0
  151. package/notification-center/package.json +4 -0
  152. package/number-input/package.json +4 -0
  153. package/package.json +252 -5
  154. package/pagination/package.json +4 -0
  155. package/popover/package.json +4 -0
  156. package/progress-bar/package.json +4 -0
  157. package/radio/package.json +4 -0
  158. package/rating/package.json +4 -0
  159. package/select/package.json +4 -0
  160. package/sidebar/package.json +4 -0
  161. package/skeleton/package.json +4 -0
  162. package/slider/package.json +4 -0
  163. package/spinner/package.json +4 -0
  164. package/split-button/package.json +4 -0
  165. package/splitter/package.json +4 -0
  166. package/stats-card/package.json +4 -0
  167. package/stepper/package.json +4 -0
  168. package/styles/_tokens.scss +202 -0
  169. package/styles.scss +1 -0
  170. package/switch/package.json +4 -0
  171. package/table/package.json +4 -0
  172. package/tabs/package.json +4 -0
  173. package/textarea/package.json +4 -0
  174. package/timeline/package.json +4 -0
  175. package/toast/package.json +4 -0
  176. package/toggle-button-group/package.json +4 -0
  177. package/toolbar/package.json +4 -0
  178. package/tooltip/package.json +4 -0
  179. package/types/neural-ui-core-accordion.d.ts +55 -0
  180. package/types/neural-ui-core-alert.d.ts +47 -0
  181. package/types/neural-ui-core-autocomplete.d.ts +75 -0
  182. package/types/neural-ui-core-avatar.d.ts +39 -0
  183. package/types/neural-ui-core-badge.d.ts +36 -0
  184. package/types/neural-ui-core-block-ui.d.ts +46 -0
  185. package/types/neural-ui-core-breadcrumb.d.ts +38 -0
  186. package/types/neural-ui-core-button.d.ts +55 -0
  187. package/types/neural-ui-core-card.d.ts +37 -0
  188. package/types/neural-ui-core-chart.d.ts +236 -0
  189. package/types/neural-ui-core-checkbox.d.ts +33 -0
  190. package/types/neural-ui-core-chip.d.ts +53 -0
  191. package/types/neural-ui-core-code-block.d.ts +55 -0
  192. package/types/neural-ui-core-color-picker.d.ts +55 -0
  193. package/types/neural-ui-core-command-palette.d.ts +56 -0
  194. package/types/neural-ui-core-confirm-dialog.d.ts +50 -0
  195. package/types/neural-ui-core-context-menu.d.ts +66 -0
  196. package/types/neural-ui-core-dashboard-grid.d.ts +41 -0
  197. package/types/neural-ui-core-date-input.d.ts +178 -0
  198. package/types/neural-ui-core-divider.d.ts +20 -0
  199. package/types/neural-ui-core-empty-state.d.ts +32 -0
  200. package/types/neural-ui-core-filter-bar.d.ts +49 -0
  201. package/types/neural-ui-core-icon.d.ts +33 -0
  202. package/types/neural-ui-core-image-viewer.d.ts +67 -0
  203. package/types/neural-ui-core-input-otp.d.ts +49 -0
  204. package/types/neural-ui-core-input.d.ts +86 -0
  205. package/types/neural-ui-core-knob.d.ts +68 -0
  206. package/types/neural-ui-core-meter-group.d.ts +52 -0
  207. package/types/neural-ui-core-modal.d.ts +54 -0
  208. package/types/neural-ui-core-multiselect.d.ts +138 -0
  209. package/types/neural-ui-core-nav.d.ts +69 -0
  210. package/types/neural-ui-core-notification-center.d.ts +60 -0
  211. package/types/neural-ui-core-number-input.d.ts +63 -0
  212. package/types/neural-ui-core-pagination.d.ts +30 -0
  213. package/types/neural-ui-core-popover.d.ts +73 -0
  214. package/types/neural-ui-core-progress-bar.d.ts +35 -0
  215. package/types/neural-ui-core-radio.d.ts +51 -0
  216. package/types/neural-ui-core-rating.d.ts +34 -0
  217. package/types/neural-ui-core-select.d.ts +170 -0
  218. package/types/neural-ui-core-sidebar.d.ts +57 -0
  219. package/types/neural-ui-core-skeleton.d.ts +22 -0
  220. package/types/neural-ui-core-slider.d.ts +42 -0
  221. package/types/neural-ui-core-spinner.d.ts +38 -0
  222. package/types/neural-ui-core-split-button.d.ts +65 -0
  223. package/types/neural-ui-core-splitter.d.ts +28 -0
  224. package/types/neural-ui-core-stats-card.d.ts +39 -0
  225. package/types/neural-ui-core-stepper.d.ts +51 -0
  226. package/types/neural-ui-core-switch.d.ts +34 -0
  227. package/types/neural-ui-core-table.d.ts +285 -0
  228. package/types/neural-ui-core-tabs.d.ts +88 -0
  229. package/types/neural-ui-core-textarea.d.ts +52 -0
  230. package/types/neural-ui-core-timeline.d.ts +33 -0
  231. package/types/neural-ui-core-toast.d.ts +70 -0
  232. package/types/neural-ui-core-toggle-button-group.d.ts +63 -0
  233. package/types/neural-ui-core-toolbar.d.ts +36 -0
  234. package/types/neural-ui-core-tooltip.d.ts +48 -0
  235. package/types/neural-ui-core-url-state.d.ts +58 -0
  236. package/types/neural-ui-core-virtual-list.d.ts +60 -0
  237. package/types/neural-ui-core.d.ts +3 -2105
  238. package/url-state/package.json +4 -0
  239. package/virtual-list/package.json +4 -0
@@ -0,0 +1,116 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, output, signal, computed, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
3
+
4
+ /** Icono por defecto para cada tipo */
5
+ const DEFAULT_ICONS = {
6
+ info: 'ℹ',
7
+ success: '✓',
8
+ warning: '⚠',
9
+ error: '✕',
10
+ };
11
+ let _seq = 0;
12
+ /**
13
+ * NeuralUI Alert Component
14
+ *
15
+ * Mensaje de alerta contextual con soporte de icono personalizado, slot de acciones y cierre.
16
+ *
17
+ * Uso: <neu-alert type="success">Operación completada</neu-alert>
18
+ * <neu-alert type="error" [closable]="true" (closed)="onClosed()">Error de red</neu-alert>
19
+ */
20
+ class NeuAlertComponent {
21
+ /** Tipo semántico / Semantic type */
22
+ type = input('info', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
23
+ /** Título opcional sobre el mensaje / Optional title above message */
24
+ title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
25
+ /** Icono personalizado. Vacío = usa el icono por defecto del tipo / Custom icon. Empty = use default type icon */
26
+ icon = input('', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
27
+ /** Muestra el icono / Shows the icon */
28
+ showIcon = input(true, ...(ngDevMode ? [{ debugName: "showIcon" }] : /* istanbul ignore next */ []));
29
+ /** Permite cerrarse / Can be dismissed */
30
+ closable = input(false, ...(ngDevMode ? [{ debugName: "closable" }] : /* istanbul ignore next */ []));
31
+ /** Variante outline (sin fondo sólido) / Outline variant (no solid background) */
32
+ outline = input(false, ...(ngDevMode ? [{ debugName: "outline" }] : /* istanbul ignore next */ []));
33
+ /** 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 */ []));
35
+ /** Emitido cuando se descarta la alerta / Emitted when the alert is dismissed */
36
+ closed = output();
37
+ _id = `neu-alert-${++_seq}`;
38
+ _dismissed = signal(false, ...(ngDevMode ? [{ debugName: "_dismissed" }] : /* istanbul ignore next */ []));
39
+ _resolvedIcon = computed(() => this.icon() || DEFAULT_ICONS[this.type()], ...(ngDevMode ? [{ debugName: "_resolvedIcon" }] : /* istanbul ignore next */ []));
40
+ liveRegion = computed(() => (this.type() === 'error' ? 'assertive' : 'polite'), ...(ngDevMode ? [{ debugName: "liveRegion" }] : /* istanbul ignore next */ []));
41
+ hostClasses = computed(() => ({
42
+ 'neu-alert': true,
43
+ [`neu-alert--${this.type()}`]: true,
44
+ 'neu-alert--outline': this.outline(),
45
+ 'neu-alert--closable': this.closable(),
46
+ 'neu-alert--with-icon': this.showIcon(),
47
+ 'neu-alert--dismissed': this._dismissed(),
48
+ }), ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
49
+ dismiss() {
50
+ this._dismissed.set(true);
51
+ this.closed.emit();
52
+ }
53
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuAlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
54
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", 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: `
55
+ @if (!_dismissed()) {
56
+ @if (showIcon()) {
57
+ <span class="neu-alert__icon" aria-hidden="true">{{ _resolvedIcon() }}</span>
58
+ }
59
+ <div class="neu-alert__body">
60
+ @if (title()) {
61
+ <strong class="neu-alert__title">{{ title() }}</strong>
62
+ }
63
+ <div class="neu-alert__content">
64
+ <ng-content />
65
+ </div>
66
+ <ng-content select="[neu-alert-actions]" />
67
+ </div>
68
+ @if (closable()) {
69
+ <button
70
+ class="neu-alert__close"
71
+ type="button"
72
+ [attr.aria-label]="closeLabel()"
73
+ (click)="dismiss()"
74
+ >
75
+ ×
76
+ </button>
77
+ }
78
+ }
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 });
80
+ }
81
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuAlertComponent, decorators: [{
82
+ type: Component,
83
+ args: [{ selector: 'neu-alert', imports: [], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: { '[class]': 'hostClasses()', role: 'alert', '[attr.aria-live]': 'liveRegion()' }, template: `
84
+ @if (!_dismissed()) {
85
+ @if (showIcon()) {
86
+ <span class="neu-alert__icon" aria-hidden="true">{{ _resolvedIcon() }}</span>
87
+ }
88
+ <div class="neu-alert__body">
89
+ @if (title()) {
90
+ <strong class="neu-alert__title">{{ title() }}</strong>
91
+ }
92
+ <div class="neu-alert__content">
93
+ <ng-content />
94
+ </div>
95
+ <ng-content select="[neu-alert-actions]" />
96
+ </div>
97
+ @if (closable()) {
98
+ <button
99
+ class="neu-alert__close"
100
+ type="button"
101
+ [attr.aria-label]="closeLabel()"
102
+ (click)="dismiss()"
103
+ >
104
+ ×
105
+ </button>
106
+ }
107
+ }
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"] }]
109
+ }], 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
+
111
+ /**
112
+ * Generated bundle index. Do not edit.
113
+ */
114
+
115
+ export { NeuAlertComponent };
116
+ //# sourceMappingURL=neural-ui-core-alert.mjs.map
@@ -0,0 +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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"}
@@ -0,0 +1,406 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, output, signal, computed, inject, ElementRef, forwardRef, HostListener, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
3
+ import { NG_VALUE_ACCESSOR } from '@angular/forms';
4
+
5
+ let _seq = 0;
6
+ /**
7
+ * NeuralUI Autocomplete
8
+ *
9
+ * Input con lista de sugerencias filtradas y navegación por teclado.
10
+ * Implementa CVA para uso en formularios reactivos.
11
+ *
12
+ * Uso:
13
+ * <neu-autocomplete
14
+ * [options]="opts"
15
+ * placeholder="Buscar…"
16
+ * [formControl]="selectedCtrl"
17
+ * (optionSelected)="onSelect($event)"
18
+ * />
19
+ */
20
+ class NeuAutocompleteComponent {
21
+ // ── Inputs / Outputs ────────────────────────────────────────────
22
+ options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
23
+ placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
24
+ label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
25
+ hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
26
+ errorMessage = input('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
27
+ emptyLabel = input('Sin resultados', ...(ngDevMode ? [{ debugName: "emptyLabel" }] : /* istanbul ignore next */ []));
28
+ minLength = input(0, ...(ngDevMode ? [{ debugName: "minLength" }] : /* istanbul ignore next */ []));
29
+ /** 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) */
30
+ floatingLabel = input(false, ...(ngDevMode ? [{ debugName: "floatingLabel" }] : /* istanbul ignore next */ []));
31
+ /** Tamaño del campo: 'sm' = 36px | 'md' = 48px | 'lg' = 56px / Field size */
32
+ size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
33
+ /** Emitido al seleccionar una opción / Emitted when an option is selected */
34
+ optionSelected = output();
35
+ /** Emitido al cambiar el texto del input / Emitted on query change */
36
+ queryChange = output();
37
+ // ── Internal state ───────────────────────────────────────────────
38
+ _id = `neu-autocomplete-${++_seq}`;
39
+ _listId = `${this._id}-list`;
40
+ _query = signal('', ...(ngDevMode ? [{ debugName: "_query" }] : /* istanbul ignore next */ []));
41
+ _isOpen = signal(false, ...(ngDevMode ? [{ debugName: "_isOpen" }] : /* istanbul ignore next */ []));
42
+ _activeIndex = signal(-1, ...(ngDevMode ? [{ debugName: "_activeIndex" }] : /* istanbul ignore next */ []));
43
+ _cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_cvaDisabled" }] : /* istanbul ignore next */ []));
44
+ _focused = signal(false, ...(ngDevMode ? [{ debugName: "_focused" }] : /* istanbul ignore next */ []));
45
+ _onChange = () => { };
46
+ _onTouched = () => { };
47
+ // ── Computed ─────────────────────────────────────────────────────
48
+ _filtered = computed(() => {
49
+ const q = this._query().toLowerCase().trim();
50
+ // Con query vacía nunca mostramos opciones (no queremos comportarnos como un select).
51
+ // Empty query → never show options (autocomplete ≠ select).
52
+ if (!q)
53
+ return [];
54
+ if (q.length < this.minLength())
55
+ return [];
56
+ return this.options().filter((o) => o.label.toLowerCase().includes(q));
57
+ }, ...(ngDevMode ? [{ debugName: "_filtered" }] : /* istanbul ignore next */ []));
58
+ _activeId = computed(() => {
59
+ const i = this._activeIndex();
60
+ return i >= 0 ? this._optionId(i) : null;
61
+ }, ...(ngDevMode ? [{ debugName: "_activeId" }] : /* istanbul ignore next */ []));
62
+ hasError = computed(() => !!this.errorMessage(), ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
63
+ describedBy = computed(() => {
64
+ if (this.hasError()) {
65
+ return `${this._id}-error`;
66
+ }
67
+ if (this.hint()) {
68
+ return `${this._id}-hint`;
69
+ }
70
+ return null;
71
+ }, ...(ngDevMode ? [{ debugName: "describedBy" }] : /* istanbul ignore next */ []));
72
+ resultsAnnouncement = computed(() => {
73
+ const query = this._query().trim();
74
+ if (!query || !this._isOpen()) {
75
+ return '';
76
+ }
77
+ const total = this._filtered().length;
78
+ if (!total) {
79
+ return this.emptyLabel();
80
+ }
81
+ return total === 1 ? '1 resultado disponible' : `${total} resultados disponibles`;
82
+ }, ...(ngDevMode ? [{ debugName: "resultsAnnouncement" }] : /* istanbul ignore next */ []));
83
+ _optionId(i) {
84
+ return `${this._listId}-opt-${i}`;
85
+ }
86
+ // ── HostListener close on outside click ─────────────────────────
87
+ _el = inject((ElementRef));
88
+ onDocClick(e) {
89
+ if (!this._el.nativeElement.contains(e.target)) {
90
+ this._isOpen.set(false);
91
+ }
92
+ }
93
+ // ── Event handlers ───────────────────────────────────────────────
94
+ onQueryChange(q) {
95
+ this._query.set(q);
96
+ this._activeIndex.set(-1);
97
+ // Sólo abrimos si hay texto suficiente; si no, cerramos.
98
+ // Only open when there is enough text; otherwise close.
99
+ const minLen = Math.max(1, this.minLength());
100
+ this._isOpen.set(q.trim().length >= minLen);
101
+ this.queryChange.emit(q);
102
+ // CVA — emit null when query is cleared
103
+ if (!q) {
104
+ this._onChange(null);
105
+ }
106
+ }
107
+ _onFocus() {
108
+ this._focused.set(true);
109
+ // Abre el dropdown solo si ya hay texto escrito / Only open when there is already a query.
110
+ if (this._query().trim().length >= Math.max(1, this.minLength())) {
111
+ this._isOpen.set(true);
112
+ }
113
+ }
114
+ _onBlur() {
115
+ this._focused.set(false);
116
+ this._onTouched();
117
+ // Small delay to allow mousedown on option to fire first
118
+ setTimeout(() => this._isOpen.set(false), 150);
119
+ }
120
+ onKeyDown(e) {
121
+ const total = this._filtered().length;
122
+ if (!total && e.key !== 'Escape')
123
+ return;
124
+ switch (e.key) {
125
+ case 'ArrowDown':
126
+ e.preventDefault();
127
+ this._moveActiveIndex(1);
128
+ this._isOpen.set(true);
129
+ break;
130
+ case 'ArrowUp':
131
+ e.preventDefault();
132
+ this._moveActiveIndex(-1);
133
+ break;
134
+ case 'Enter': {
135
+ const idx = this._activeIndex();
136
+ const opt = this._filtered()[idx];
137
+ if (opt && !opt.disabled)
138
+ this.selectOption(opt);
139
+ break;
140
+ }
141
+ case 'Escape':
142
+ this._isOpen.set(false);
143
+ this._activeIndex.set(-1);
144
+ break;
145
+ }
146
+ }
147
+ _moveActiveIndex(step) {
148
+ const filtered = this._filtered();
149
+ if (!filtered.length) {
150
+ this._activeIndex.set(-1);
151
+ return;
152
+ }
153
+ const currentIndex = this._activeIndex();
154
+ let nextIndex = currentIndex;
155
+ for (let count = 0; count < filtered.length; count += 1) {
156
+ nextIndex =
157
+ step === 1 ? Math.min(nextIndex + 1, filtered.length - 1) : Math.max(nextIndex - 1, 0);
158
+ if (!filtered[nextIndex]?.disabled) {
159
+ this._activeIndex.set(nextIndex);
160
+ return;
161
+ }
162
+ if ((step === 1 && nextIndex === filtered.length - 1) || (step === -1 && nextIndex === 0)) {
163
+ break;
164
+ }
165
+ }
166
+ if (currentIndex === -1) {
167
+ this._activeIndex.set(filtered.findIndex((option) => !option.disabled));
168
+ }
169
+ }
170
+ selectOption(opt) {
171
+ if (opt.disabled)
172
+ return;
173
+ this._query.set(opt.label);
174
+ this._isOpen.set(false);
175
+ this._activeIndex.set(-1);
176
+ this._onChange(opt.value);
177
+ this.optionSelected.emit(opt);
178
+ }
179
+ clear() {
180
+ this._query.set('');
181
+ this._onChange(null);
182
+ this._isOpen.set(false);
183
+ this.queryChange.emit('');
184
+ }
185
+ // ── CVA ──────────────────────────────────────────────────────────
186
+ writeValue(val) {
187
+ if (val === null || val === undefined) {
188
+ this._query.set('');
189
+ return;
190
+ }
191
+ const match = this.options().find((o) => o.value === val);
192
+ this._query.set(match ? match.label : String(val));
193
+ }
194
+ registerOnChange(fn) {
195
+ this._onChange = fn;
196
+ }
197
+ registerOnTouched(fn) {
198
+ this._onTouched = fn;
199
+ }
200
+ setDisabledState(d) {
201
+ this._cvaDisabled.set(d);
202
+ }
203
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuAutocompleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
204
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", 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 } }, outputs: { optionSelected: "optionSelected", queryChange: "queryChange" }, host: { listeners: { "document:mousedown": "onDocClick($event)" }, 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\"" }, classAttribute: "neu-autocomplete" }, providers: [
205
+ {
206
+ provide: NG_VALUE_ACCESSOR,
207
+ useExisting: forwardRef(() => NeuAutocompleteComponent),
208
+ multi: true,
209
+ },
210
+ ], ngImport: i0, template: `
211
+ @if (!floatingLabel() && label()) {
212
+ <label class="neu-autocomplete__label" [for]="_id">{{ label() }}</label>
213
+ }
214
+ <div
215
+ class="neu-autocomplete__input-wrap"
216
+ [class.neu-autocomplete__input-wrap--focused]="_focused()"
217
+ [class.neu-autocomplete__input-wrap--has-value]="!!_query()"
218
+ >
219
+ <input
220
+ #inputEl
221
+ class="neu-autocomplete__input"
222
+ type="text"
223
+ autocomplete="off"
224
+ role="combobox"
225
+ [id]="_id"
226
+ [attr.placeholder]="floatingLabel() ? ' ' : placeholder() || null"
227
+ [attr.aria-label]="label() || placeholder()"
228
+ [attr.aria-autocomplete]="'list'"
229
+ [attr.aria-haspopup]="'listbox'"
230
+ [attr.aria-expanded]="_isOpen() ? 'true' : 'false'"
231
+ [attr.aria-controls]="_listId"
232
+ [attr.aria-activedescendant]="_activeId()"
233
+ [attr.aria-invalid]="hasError() ? 'true' : null"
234
+ [attr.aria-describedby]="describedBy()"
235
+ [disabled]="_cvaDisabled()"
236
+ [value]="_query()"
237
+ (input)="onQueryChange($any($event.target).value)"
238
+ (focus)="_onFocus()"
239
+ (blur)="_onBlur()"
240
+ (keydown)="onKeyDown($event)"
241
+ />
242
+ @if (floatingLabel() && label()) {
243
+ <label class="neu-autocomplete__floating-label" [for]="_id">{{ label() }}</label>
244
+ }
245
+ @if (_query() && !_cvaDisabled()) {
246
+ <button
247
+ type="button"
248
+ class="neu-autocomplete__clear"
249
+ aria-label="Limpiar"
250
+ tabindex="-1"
251
+ (click)="clear()"
252
+ >
253
+ ×
254
+ </button>
255
+ }
256
+ </div>
257
+ <div class="neu-autocomplete__sr-status" aria-live="polite" aria-atomic="true">
258
+ {{ resultsAnnouncement() }}
259
+ </div>
260
+ @if (_isOpen() && _filtered().length) {
261
+ <ul
262
+ class="neu-autocomplete__list"
263
+ role="listbox"
264
+ [id]="_listId"
265
+ [attr.aria-label]="label() || placeholder()"
266
+ >
267
+ @for (opt of _filtered(); track opt.label; let i = $index) {
268
+ <li
269
+ class="neu-autocomplete__option"
270
+ role="option"
271
+ [id]="_optionId(i)"
272
+ [class.neu-autocomplete__option--active]="_activeIndex() === i"
273
+ [class.neu-autocomplete__option--disabled]="opt.disabled"
274
+ [attr.aria-selected]="_activeIndex() === i"
275
+ [attr.aria-disabled]="opt.disabled ?? false"
276
+ (mousedown)="selectOption(opt)"
277
+ >
278
+ {{ opt.label }}
279
+ </li>
280
+ }
281
+ </ul>
282
+ }
283
+ @if (_isOpen() && !_filtered().length) {
284
+ <div class="neu-autocomplete__empty" role="status">{{ emptyLabel() }}</div>
285
+ }
286
+ @if (hasError()) {
287
+ <p class="neu-autocomplete__error" [id]="_id + '-error'" role="alert">
288
+ {{ errorMessage() }}
289
+ </p>
290
+ } @else if (hint()) {
291
+ <p class="neu-autocomplete__hint" [id]="_id + '-hint'">{{ hint() }}</p>
292
+ }
293
+ `, isInline: true, styles: ["@charset \"UTF-8\";.neu-autocomplete{position:relative;display:block}.neu-autocomplete--disabled{opacity:.55;pointer-events:none}.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.neu-autocomplete--focused .neu-autocomplete__input::placeholder{color:var(--neu-text-disabled, #9ca3af)}.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--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__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:absolute;top:calc(100% + 4px);left:0;right:0;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}@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;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:absolute;top:calc(100% + 4px);left:0;right:0;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--sm .neu-autocomplete__input{height:36px;font-size:var(--neu-text-sm, .875rem)}.neu-autocomplete--lg .neu-autocomplete__input{height:56px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
294
+ }
295
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuAutocompleteComponent, decorators: [{
296
+ type: Component,
297
+ args: [{ selector: 'neu-autocomplete', imports: [], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
298
+ {
299
+ provide: NG_VALUE_ACCESSOR,
300
+ useExisting: forwardRef(() => NeuAutocompleteComponent),
301
+ multi: true,
302
+ },
303
+ ], host: {
304
+ class: 'neu-autocomplete',
305
+ '[class.neu-autocomplete--open]': '_isOpen()',
306
+ '[class.neu-autocomplete--disabled]': '_cvaDisabled()',
307
+ '[class.neu-autocomplete--floating]': 'floatingLabel()',
308
+ '[class.neu-autocomplete--focused]': '_focused()',
309
+ '[class.neu-autocomplete--has-value]': '!!_query()',
310
+ '[class.neu-autocomplete--sm]': 'size() === "sm"',
311
+ '[class.neu-autocomplete--lg]': 'size() === "lg"',
312
+ }, template: `
313
+ @if (!floatingLabel() && label()) {
314
+ <label class="neu-autocomplete__label" [for]="_id">{{ label() }}</label>
315
+ }
316
+ <div
317
+ class="neu-autocomplete__input-wrap"
318
+ [class.neu-autocomplete__input-wrap--focused]="_focused()"
319
+ [class.neu-autocomplete__input-wrap--has-value]="!!_query()"
320
+ >
321
+ <input
322
+ #inputEl
323
+ class="neu-autocomplete__input"
324
+ type="text"
325
+ autocomplete="off"
326
+ role="combobox"
327
+ [id]="_id"
328
+ [attr.placeholder]="floatingLabel() ? ' ' : placeholder() || null"
329
+ [attr.aria-label]="label() || placeholder()"
330
+ [attr.aria-autocomplete]="'list'"
331
+ [attr.aria-haspopup]="'listbox'"
332
+ [attr.aria-expanded]="_isOpen() ? 'true' : 'false'"
333
+ [attr.aria-controls]="_listId"
334
+ [attr.aria-activedescendant]="_activeId()"
335
+ [attr.aria-invalid]="hasError() ? 'true' : null"
336
+ [attr.aria-describedby]="describedBy()"
337
+ [disabled]="_cvaDisabled()"
338
+ [value]="_query()"
339
+ (input)="onQueryChange($any($event.target).value)"
340
+ (focus)="_onFocus()"
341
+ (blur)="_onBlur()"
342
+ (keydown)="onKeyDown($event)"
343
+ />
344
+ @if (floatingLabel() && label()) {
345
+ <label class="neu-autocomplete__floating-label" [for]="_id">{{ label() }}</label>
346
+ }
347
+ @if (_query() && !_cvaDisabled()) {
348
+ <button
349
+ type="button"
350
+ class="neu-autocomplete__clear"
351
+ aria-label="Limpiar"
352
+ tabindex="-1"
353
+ (click)="clear()"
354
+ >
355
+ ×
356
+ </button>
357
+ }
358
+ </div>
359
+ <div class="neu-autocomplete__sr-status" aria-live="polite" aria-atomic="true">
360
+ {{ resultsAnnouncement() }}
361
+ </div>
362
+ @if (_isOpen() && _filtered().length) {
363
+ <ul
364
+ class="neu-autocomplete__list"
365
+ role="listbox"
366
+ [id]="_listId"
367
+ [attr.aria-label]="label() || placeholder()"
368
+ >
369
+ @for (opt of _filtered(); track opt.label; let i = $index) {
370
+ <li
371
+ class="neu-autocomplete__option"
372
+ role="option"
373
+ [id]="_optionId(i)"
374
+ [class.neu-autocomplete__option--active]="_activeIndex() === i"
375
+ [class.neu-autocomplete__option--disabled]="opt.disabled"
376
+ [attr.aria-selected]="_activeIndex() === i"
377
+ [attr.aria-disabled]="opt.disabled ?? false"
378
+ (mousedown)="selectOption(opt)"
379
+ >
380
+ {{ opt.label }}
381
+ </li>
382
+ }
383
+ </ul>
384
+ }
385
+ @if (_isOpen() && !_filtered().length) {
386
+ <div class="neu-autocomplete__empty" role="status">{{ emptyLabel() }}</div>
387
+ }
388
+ @if (hasError()) {
389
+ <p class="neu-autocomplete__error" [id]="_id + '-error'" role="alert">
390
+ {{ errorMessage() }}
391
+ </p>
392
+ } @else if (hint()) {
393
+ <p class="neu-autocomplete__hint" [id]="_id + '-hint'">{{ hint() }}</p>
394
+ }
395
+ `, styles: ["@charset \"UTF-8\";.neu-autocomplete{position:relative;display:block}.neu-autocomplete--disabled{opacity:.55;pointer-events:none}.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.neu-autocomplete--focused .neu-autocomplete__input::placeholder{color:var(--neu-text-disabled, #9ca3af)}.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--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__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:absolute;top:calc(100% + 4px);left:0;right:0;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}@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;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:absolute;top:calc(100% + 4px);left:0;right:0;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--sm .neu-autocomplete__input{height:36px;font-size:var(--neu-text-sm, .875rem)}.neu-autocomplete--lg .neu-autocomplete__input{height:56px}\n"] }]
396
+ }], 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 }] }], optionSelected: [{ type: i0.Output, args: ["optionSelected"] }], queryChange: [{ type: i0.Output, args: ["queryChange"] }], onDocClick: [{
397
+ type: HostListener,
398
+ args: ['document:mousedown', ['$event']]
399
+ }] } });
400
+
401
+ /**
402
+ * Generated bundle index. Do not edit.
403
+ */
404
+
405
+ export { NeuAutocompleteComponent };
406
+ //# sourceMappingURL=neural-ui-core-autocomplete.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"neural-ui-core-autocomplete.mjs","sources":["../../../../projects/ui-core/autocomplete/neu-autocomplete.component.ts","../../../../projects/ui-core/autocomplete/neural-ui-core-autocomplete.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n HostListener,\n ViewEncapsulation,\n computed,\n forwardRef,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\nexport interface NeuAutocompleteOption {\n /** Valor / Value */\n value: unknown;\n /** Texto visible / Display text */\n label: string;\n /** Desactiva la opción / Disables the option */\n disabled?: boolean;\n}\n\nlet _seq = 0;\n\n/**\n * NeuralUI Autocomplete\n *\n * Input con lista de sugerencias filtradas y navegación por teclado.\n * Implementa CVA para uso en formularios reactivos.\n *\n * Uso:\n * <neu-autocomplete\n * [options]=\"opts\"\n * placeholder=\"Buscar…\"\n * [formControl]=\"selectedCtrl\"\n * (optionSelected)=\"onSelect($event)\"\n * />\n */\n@Component({\n selector: 'neu-autocomplete',\n imports: [],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => NeuAutocompleteComponent),\n multi: true,\n },\n ],\n host: {\n class: 'neu-autocomplete',\n '[class.neu-autocomplete--open]': '_isOpen()',\n '[class.neu-autocomplete--disabled]': '_cvaDisabled()',\n '[class.neu-autocomplete--floating]': 'floatingLabel()',\n '[class.neu-autocomplete--focused]': '_focused()',\n '[class.neu-autocomplete--has-value]': '!!_query()',\n '[class.neu-autocomplete--sm]': 'size() === \"sm\"',\n '[class.neu-autocomplete--lg]': 'size() === \"lg\"',\n },\n template: `\n @if (!floatingLabel() && label()) {\n <label class=\"neu-autocomplete__label\" [for]=\"_id\">{{ label() }}</label>\n }\n <div\n class=\"neu-autocomplete__input-wrap\"\n [class.neu-autocomplete__input-wrap--focused]=\"_focused()\"\n [class.neu-autocomplete__input-wrap--has-value]=\"!!_query()\"\n >\n <input\n #inputEl\n class=\"neu-autocomplete__input\"\n type=\"text\"\n autocomplete=\"off\"\n role=\"combobox\"\n [id]=\"_id\"\n [attr.placeholder]=\"floatingLabel() ? ' ' : placeholder() || null\"\n [attr.aria-label]=\"label() || placeholder()\"\n [attr.aria-autocomplete]=\"'list'\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-expanded]=\"_isOpen() ? 'true' : 'false'\"\n [attr.aria-controls]=\"_listId\"\n [attr.aria-activedescendant]=\"_activeId()\"\n [attr.aria-invalid]=\"hasError() ? 'true' : null\"\n [attr.aria-describedby]=\"describedBy()\"\n [disabled]=\"_cvaDisabled()\"\n [value]=\"_query()\"\n (input)=\"onQueryChange($any($event.target).value)\"\n (focus)=\"_onFocus()\"\n (blur)=\"_onBlur()\"\n (keydown)=\"onKeyDown($event)\"\n />\n @if (floatingLabel() && label()) {\n <label class=\"neu-autocomplete__floating-label\" [for]=\"_id\">{{ label() }}</label>\n }\n @if (_query() && !_cvaDisabled()) {\n <button\n type=\"button\"\n class=\"neu-autocomplete__clear\"\n aria-label=\"Limpiar\"\n tabindex=\"-1\"\n (click)=\"clear()\"\n >\n ×\n </button>\n }\n </div>\n <div class=\"neu-autocomplete__sr-status\" aria-live=\"polite\" aria-atomic=\"true\">\n {{ resultsAnnouncement() }}\n </div>\n @if (_isOpen() && _filtered().length) {\n <ul\n class=\"neu-autocomplete__list\"\n role=\"listbox\"\n [id]=\"_listId\"\n [attr.aria-label]=\"label() || placeholder()\"\n >\n @for (opt of _filtered(); track opt.label; let i = $index) {\n <li\n class=\"neu-autocomplete__option\"\n role=\"option\"\n [id]=\"_optionId(i)\"\n [class.neu-autocomplete__option--active]=\"_activeIndex() === i\"\n [class.neu-autocomplete__option--disabled]=\"opt.disabled\"\n [attr.aria-selected]=\"_activeIndex() === i\"\n [attr.aria-disabled]=\"opt.disabled ?? false\"\n (mousedown)=\"selectOption(opt)\"\n >\n {{ opt.label }}\n </li>\n }\n </ul>\n }\n @if (_isOpen() && !_filtered().length) {\n <div class=\"neu-autocomplete__empty\" role=\"status\">{{ emptyLabel() }}</div>\n }\n @if (hasError()) {\n <p class=\"neu-autocomplete__error\" [id]=\"_id + '-error'\" role=\"alert\">\n {{ errorMessage() }}\n </p>\n } @else if (hint()) {\n <p class=\"neu-autocomplete__hint\" [id]=\"_id + '-hint'\">{{ hint() }}</p>\n }\n `,\n styleUrl: './neu-autocomplete.component.scss',\n})\nexport class NeuAutocompleteComponent implements ControlValueAccessor {\n // ── Inputs / Outputs ────────────────────────────────────────────\n readonly options = input<NeuAutocompleteOption[]>([]);\n readonly placeholder = input<string>('');\n readonly label = input<string>('');\n readonly hint = input<string>('');\n readonly errorMessage = input<string>('');\n readonly emptyLabel = input<string>('Sin resultados');\n readonly minLength = input<number>(0);\n /** 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) */\n readonly floatingLabel = input<boolean>(false);\n /** Tamaño del campo: 'sm' = 36px | 'md' = 48px | 'lg' = 56px / Field size */\n readonly size = input<'sm' | 'md' | 'lg'>('md');\n\n /** Emitido al seleccionar una opción / Emitted when an option is selected */\n readonly optionSelected = output<NeuAutocompleteOption>();\n\n /** Emitido al cambiar el texto del input / Emitted on query change */\n readonly queryChange = output<string>();\n\n // ── Internal state ───────────────────────────────────────────────\n readonly _id = `neu-autocomplete-${++_seq}`;\n readonly _listId = `${this._id}-list`;\n\n readonly _query = signal('');\n readonly _isOpen = signal(false);\n readonly _activeIndex = signal(-1);\n readonly _cvaDisabled = signal(false);\n readonly _focused = signal(false);\n\n private _onChange: (v: unknown) => void = () => {};\n private _onTouched: () => void = () => {};\n\n // ── Computed ─────────────────────────────────────────────────────\n readonly _filtered = computed(() => {\n const q = this._query().toLowerCase().trim();\n // Con query vacía nunca mostramos opciones (no queremos comportarnos como un select).\n // Empty query → never show options (autocomplete ≠ select).\n if (!q) return [];\n if (q.length < this.minLength()) return [];\n return this.options().filter((o) => o.label.toLowerCase().includes(q));\n });\n\n readonly _activeId = computed(() => {\n const i = this._activeIndex();\n return i >= 0 ? this._optionId(i) : null;\n });\n\n readonly hasError = computed(() => !!this.errorMessage());\n\n readonly describedBy = computed(() => {\n if (this.hasError()) {\n return `${this._id}-error`;\n }\n if (this.hint()) {\n return `${this._id}-hint`;\n }\n return null;\n });\n\n readonly resultsAnnouncement = computed(() => {\n const query = this._query().trim();\n if (!query || !this._isOpen()) {\n return '';\n }\n\n const total = this._filtered().length;\n if (!total) {\n return this.emptyLabel();\n }\n\n return total === 1 ? '1 resultado disponible' : `${total} resultados disponibles`;\n });\n\n _optionId(i: number): string {\n return `${this._listId}-opt-${i}`;\n }\n\n // ── HostListener close on outside click ─────────────────────────\n private readonly _el = inject(ElementRef<HTMLElement>);\n\n @HostListener('document:mousedown', ['$event'])\n onDocClick(e: MouseEvent): void {\n if (!this._el.nativeElement.contains(e.target as Node)) {\n this._isOpen.set(false);\n }\n }\n\n // ── Event handlers ───────────────────────────────────────────────\n onQueryChange(q: string): void {\n this._query.set(q);\n this._activeIndex.set(-1);\n // Sólo abrimos si hay texto suficiente; si no, cerramos.\n // Only open when there is enough text; otherwise close.\n const minLen = Math.max(1, this.minLength());\n this._isOpen.set(q.trim().length >= minLen);\n this.queryChange.emit(q);\n // CVA — emit null when query is cleared\n if (!q) {\n this._onChange(null);\n }\n }\n\n _onFocus(): void {\n this._focused.set(true);\n // Abre el dropdown solo si ya hay texto escrito / Only open when there is already a query.\n if (this._query().trim().length >= Math.max(1, this.minLength())) {\n this._isOpen.set(true);\n }\n }\n\n _onBlur(): void {\n this._focused.set(false);\n this._onTouched();\n // Small delay to allow mousedown on option to fire first\n setTimeout(() => this._isOpen.set(false), 150);\n }\n\n onKeyDown(e: KeyboardEvent): void {\n const total = this._filtered().length;\n if (!total && e.key !== 'Escape') return;\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n this._moveActiveIndex(1);\n this._isOpen.set(true);\n break;\n case 'ArrowUp':\n e.preventDefault();\n this._moveActiveIndex(-1);\n break;\n case 'Enter': {\n const idx = this._activeIndex();\n const opt = this._filtered()[idx];\n if (opt && !opt.disabled) this.selectOption(opt);\n break;\n }\n case 'Escape':\n this._isOpen.set(false);\n this._activeIndex.set(-1);\n break;\n }\n }\n\n private _moveActiveIndex(step: 1 | -1): void {\n const filtered = this._filtered();\n if (!filtered.length) {\n this._activeIndex.set(-1);\n return;\n }\n\n const currentIndex = this._activeIndex();\n let nextIndex = currentIndex;\n\n for (let count = 0; count < filtered.length; count += 1) {\n nextIndex =\n step === 1 ? Math.min(nextIndex + 1, filtered.length - 1) : Math.max(nextIndex - 1, 0);\n\n if (!filtered[nextIndex]?.disabled) {\n this._activeIndex.set(nextIndex);\n return;\n }\n\n if ((step === 1 && nextIndex === filtered.length - 1) || (step === -1 && nextIndex === 0)) {\n break;\n }\n }\n\n if (currentIndex === -1) {\n this._activeIndex.set(filtered.findIndex((option) => !option.disabled));\n }\n }\n\n selectOption(opt: NeuAutocompleteOption): void {\n if (opt.disabled) return;\n this._query.set(opt.label);\n this._isOpen.set(false);\n this._activeIndex.set(-1);\n this._onChange(opt.value);\n this.optionSelected.emit(opt);\n }\n\n clear(): void {\n this._query.set('');\n this._onChange(null);\n this._isOpen.set(false);\n this.queryChange.emit('');\n }\n\n // ── CVA ──────────────────────────────────────────────────────────\n writeValue(val: unknown): void {\n if (val === null || val === undefined) {\n this._query.set('');\n return;\n }\n const match = this.options().find((o) => o.value === val);\n this._query.set(match ? match.label : String(val));\n }\n\n registerOnChange(fn: (v: unknown) => void): void {\n this._onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this._onTouched = fn;\n }\n\n setDisabledState(d: boolean): void {\n this._cvaDisabled.set(d);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":";;;;AAwBA,IAAI,IAAI,GAAG,CAAC;AAEZ;;;;;;;;;;;;;AAaG;MA6GU,wBAAwB,CAAA;;AAE1B,IAAA,OAAO,GAAG,KAAK,CAA0B,EAAE,8EAAC;AAC5C,IAAA,WAAW,GAAG,KAAK,CAAS,EAAE,kFAAC;AAC/B,IAAA,KAAK,GAAG,KAAK,CAAS,EAAE,4EAAC;AACzB,IAAA,IAAI,GAAG,KAAK,CAAS,EAAE,2EAAC;AACxB,IAAA,YAAY,GAAG,KAAK,CAAS,EAAE,mFAAC;AAChC,IAAA,UAAU,GAAG,KAAK,CAAS,gBAAgB,iFAAC;AAC5C,IAAA,SAAS,GAAG,KAAK,CAAS,CAAC,gFAAC;;AAE5B,IAAA,aAAa,GAAG,KAAK,CAAU,KAAK,oFAAC;;AAErC,IAAA,IAAI,GAAG,KAAK,CAAqB,IAAI,2EAAC;;IAGtC,cAAc,GAAG,MAAM,EAAyB;;IAGhD,WAAW,GAAG,MAAM,EAAU;;AAG9B,IAAA,GAAG,GAAG,CAAA,iBAAA,EAAoB,EAAE,IAAI,EAAE;AAClC,IAAA,OAAO,GAAG,CAAA,EAAG,IAAI,CAAC,GAAG,OAAO;AAE5B,IAAA,MAAM,GAAG,MAAM,CAAC,EAAE,6EAAC;AACnB,IAAA,OAAO,GAAG,MAAM,CAAC,KAAK,8EAAC;AACvB,IAAA,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,mFAAC;AACzB,IAAA,YAAY,GAAG,MAAM,CAAC,KAAK,mFAAC;AAC5B,IAAA,QAAQ,GAAG,MAAM,CAAC,KAAK,+EAAC;AAEzB,IAAA,SAAS,GAAyB,MAAK,EAAE,CAAC;AAC1C,IAAA,UAAU,GAAe,MAAK,EAAE,CAAC;;AAGhC,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAK;AACjC,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE;;;AAG5C,QAAA,IAAI,CAAC,CAAC;AAAE,YAAA,OAAO,EAAE;AACjB,QAAA,IAAI,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE;AAAE,YAAA,OAAO,EAAE;QAC1C,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxE,IAAA,CAAC,gFAAC;AAEO,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAK;AACjC,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,YAAY,EAAE;AAC7B,QAAA,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI;AAC1C,IAAA,CAAC,gFAAC;AAEO,IAAA,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,+EAAC;AAEhD,IAAA,WAAW,GAAG,QAAQ,CAAC,MAAK;AACnC,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;AACnB,YAAA,OAAO,CAAA,EAAG,IAAI,CAAC,GAAG,QAAQ;QAC5B;AACA,QAAA,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE;AACf,YAAA,OAAO,CAAA,EAAG,IAAI,CAAC,GAAG,OAAO;QAC3B;AACA,QAAA,OAAO,IAAI;AACb,IAAA,CAAC,kFAAC;AAEO,IAAA,mBAAmB,GAAG,QAAQ,CAAC,MAAK;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE;QAClC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE;AAC7B,YAAA,OAAO,EAAE;QACX;QAEA,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM;QACrC,IAAI,CAAC,KAAK,EAAE;AACV,YAAA,OAAO,IAAI,CAAC,UAAU,EAAE;QAC1B;AAEA,QAAA,OAAO,KAAK,KAAK,CAAC,GAAG,wBAAwB,GAAG,CAAA,EAAG,KAAK,yBAAyB;AACnF,IAAA,CAAC,0FAAC;AAEF,IAAA,SAAS,CAAC,CAAS,EAAA;AACjB,QAAA,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA,KAAA,EAAQ,CAAC,EAAE;IACnC;;AAGiB,IAAA,GAAG,GAAG,MAAM,EAAC,UAAuB,EAAC;AAGtD,IAAA,UAAU,CAAC,CAAa,EAAA;AACtB,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAc,CAAC,EAAE;AACtD,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;QACzB;IACF;;AAGA,IAAA,aAAa,CAAC,CAAS,EAAA;AACrB,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;;;AAGzB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;AAC5C,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,IAAI,MAAM,CAAC;AAC3C,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;;QAExB,IAAI,CAAC,CAAC,EAAE;AACN,YAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QACtB;IACF;IAEA,QAAQ,GAAA;AACN,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;;QAEvB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,EAAE;AAChE,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;QACxB;IACF;IAEA,OAAO,GAAA;AACL,QAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;QACxB,IAAI,CAAC,UAAU,EAAE;;AAEjB,QAAA,UAAU,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC;IAChD;AAEA,IAAA,SAAS,CAAC,CAAgB,EAAA;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM;AACrC,QAAA,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ;YAAE;AAClC,QAAA,QAAQ,CAAC,CAAC,GAAG;AACX,YAAA,KAAK,WAAW;gBACd,CAAC,CAAC,cAAc,EAAE;AAClB,gBAAA,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;AACxB,gBAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;gBACtB;AACF,YAAA,KAAK,SAAS;gBACZ,CAAC,CAAC,cAAc,EAAE;AAClB,gBAAA,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;gBACzB;YACF,KAAK,OAAO,EAAE;AACZ,gBAAA,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE;gBAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC;AACjC,gBAAA,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ;AAAE,oBAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC;gBAChD;YACF;AACA,YAAA,KAAK,QAAQ;AACX,gBAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;gBACvB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBACzB;;IAEN;AAEQ,IAAA,gBAAgB,CAAC,IAAY,EAAA;AACnC,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE;AACjC,QAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;YACpB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACzB;QACF;AAEA,QAAA,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE;QACxC,IAAI,SAAS,GAAG,YAAY;AAE5B,QAAA,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE;YACvD,SAAS;AACP,gBAAA,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC,CAAC;YAExF,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE;AAClC,gBAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC;gBAChC;YACF;YAEA,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,SAAS,KAAK,QAAQ,CAAC,MAAM,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE;gBACzF;YACF;QACF;AAEA,QAAA,IAAI,YAAY,KAAK,CAAC,CAAC,EAAE;YACvB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzE;IACF;AAEA,IAAA,YAAY,CAAC,GAA0B,EAAA;QACrC,IAAI,GAAG,CAAC,QAAQ;YAAE;QAClB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC;AAC1B,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;QACvB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACzB,QAAA,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACzB,QAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC;IAC/B;IAEA,KAAK,GAAA;AACH,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;AACnB,QAAA,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;AACpB,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;AACvB,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;IAC3B;;AAGA,IAAA,UAAU,CAAC,GAAY,EAAA;QACrB,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE;AACrC,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YACnB;QACF;QACA,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,KAAK,GAAG,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACpD;AAEA,IAAA,gBAAgB,CAAC,EAAwB,EAAA;AACvC,QAAA,IAAI,CAAC,SAAS,GAAG,EAAE;IACrB;AAEA,IAAA,iBAAiB,CAAC,EAAc,EAAA;AAC9B,QAAA,IAAI,CAAC,UAAU,GAAG,EAAE;IACtB;AAEA,IAAA,gBAAgB,CAAC,CAAU,EAAA;AACzB,QAAA,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B;uGAjNW,wBAAwB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAxB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,wBAAwB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,YAAA,EAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,UAAA,EAAA,cAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,WAAA,EAAA,aAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,oBAAA,EAAA,oBAAA,EAAA,EAAA,UAAA,EAAA,EAAA,8BAAA,EAAA,WAAA,EAAA,kCAAA,EAAA,gBAAA,EAAA,kCAAA,EAAA,iBAAA,EAAA,iCAAA,EAAA,YAAA,EAAA,mCAAA,EAAA,YAAA,EAAA,4BAAA,EAAA,mBAAA,EAAA,4BAAA,EAAA,mBAAA,EAAA,EAAA,cAAA,EAAA,kBAAA,EAAA,EAAA,SAAA,EAvGxB;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,iBAAiB;AAC1B,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,wBAAwB,CAAC;AACvD,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;SACF,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAWS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmFT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,ssJAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAGU,wBAAwB,EAAA,UAAA,EAAA,CAAA;kBA5GpC,SAAS;+BACE,kBAAkB,EAAA,OAAA,EACnB,EAAE,EAAA,aAAA,EACI,iBAAiB,CAAC,IAAI,EAAA,eAAA,EACpB,uBAAuB,CAAC,MAAM,EAAA,SAAA,EACpC;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,iBAAiB;AAC1B,4BAAA,WAAW,EAAE,UAAU,CAAC,8BAA8B,CAAC;AACvD,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;qBACF,EAAA,IAAA,EACK;AACJ,wBAAA,KAAK,EAAE,kBAAkB;AACzB,wBAAA,gCAAgC,EAAE,WAAW;AAC7C,wBAAA,oCAAoC,EAAE,gBAAgB;AACtD,wBAAA,oCAAoC,EAAE,iBAAiB;AACvD,wBAAA,mCAAmC,EAAE,YAAY;AACjD,wBAAA,qCAAqC,EAAE,YAAY;AACnD,wBAAA,8BAA8B,EAAE,iBAAiB;AACjD,wBAAA,8BAA8B,EAAE,iBAAiB;qBAClD,EAAA,QAAA,EACS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmFT,EAAA,CAAA,EAAA,MAAA,EAAA,CAAA,ssJAAA,CAAA,EAAA;;sBAoFA,YAAY;uBAAC,oBAAoB,EAAE,CAAC,QAAQ,CAAC;;;ACrOhD;;AAEG;;;;"}