@neural-ui/core 1.2.1 → 1.3.0
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.
- package/README.md +56 -88
- package/accordion/package.json +4 -0
- package/alert/package.json +4 -0
- package/autocomplete/package.json +4 -0
- package/avatar/package.json +4 -0
- package/badge/package.json +4 -0
- package/block-ui/package.json +4 -0
- package/breadcrumb/package.json +4 -0
- package/button/package.json +4 -0
- package/card/package.json +4 -0
- package/chart/package.json +4 -0
- package/checkbox/package.json +4 -0
- package/chip/package.json +4 -0
- package/code-block/package.json +4 -0
- package/color-picker/package.json +4 -0
- package/command-palette/package.json +4 -0
- package/confirm-dialog/package.json +4 -0
- package/context-menu/package.json +4 -0
- package/dashboard-grid/package.json +4 -0
- package/date-input/package.json +4 -0
- package/divider/package.json +4 -0
- package/empty-state/package.json +4 -0
- package/fesm2022/neural-ui-core-accordion.mjs +162 -0
- package/fesm2022/neural-ui-core-accordion.mjs.map +1 -0
- package/fesm2022/neural-ui-core-alert.mjs +116 -0
- package/fesm2022/neural-ui-core-alert.mjs.map +1 -0
- package/fesm2022/neural-ui-core-autocomplete.mjs +332 -0
- package/fesm2022/neural-ui-core-autocomplete.mjs.map +1 -0
- package/fesm2022/neural-ui-core-avatar.mjs +109 -0
- package/fesm2022/neural-ui-core-avatar.mjs.map +1 -0
- package/fesm2022/neural-ui-core-badge.mjs +54 -0
- package/fesm2022/neural-ui-core-badge.mjs.map +1 -0
- package/fesm2022/neural-ui-core-block-ui.mjs +95 -0
- package/fesm2022/neural-ui-core-block-ui.mjs.map +1 -0
- package/fesm2022/neural-ui-core-breadcrumb.mjs +84 -0
- package/fesm2022/neural-ui-core-breadcrumb.mjs.map +1 -0
- package/fesm2022/neural-ui-core-button.mjs +125 -0
- package/fesm2022/neural-ui-core-button.mjs.map +1 -0
- package/fesm2022/neural-ui-core-card.mjs +69 -0
- package/fesm2022/neural-ui-core-card.mjs.map +1 -0
- package/fesm2022/neural-ui-core-chart.mjs +287 -0
- package/fesm2022/neural-ui-core-chart.mjs.map +1 -0
- package/fesm2022/neural-ui-core-checkbox.mjs +138 -0
- package/fesm2022/neural-ui-core-checkbox.mjs.map +1 -0
- package/fesm2022/neural-ui-core-chip.mjs +130 -0
- package/fesm2022/neural-ui-core-chip.mjs.map +1 -0
- package/fesm2022/neural-ui-core-code-block.mjs +250 -0
- package/fesm2022/neural-ui-core-code-block.mjs.map +1 -0
- package/fesm2022/neural-ui-core-color-picker.mjs +435 -0
- package/fesm2022/neural-ui-core-color-picker.mjs.map +1 -0
- package/fesm2022/neural-ui-core-command-palette.mjs +235 -0
- package/fesm2022/neural-ui-core-command-palette.mjs.map +1 -0
- package/fesm2022/neural-ui-core-confirm-dialog.mjs +118 -0
- package/fesm2022/neural-ui-core-confirm-dialog.mjs.map +1 -0
- package/fesm2022/neural-ui-core-context-menu.mjs +158 -0
- package/fesm2022/neural-ui-core-context-menu.mjs.map +1 -0
- package/fesm2022/neural-ui-core-dashboard-grid.mjs +144 -0
- package/fesm2022/neural-ui-core-dashboard-grid.mjs.map +1 -0
- package/fesm2022/neural-ui-core-date-input.mjs +1332 -0
- package/fesm2022/neural-ui-core-date-input.mjs.map +1 -0
- package/fesm2022/neural-ui-core-divider.mjs +54 -0
- package/fesm2022/neural-ui-core-divider.mjs.map +1 -0
- package/fesm2022/neural-ui-core-empty-state.mjs +84 -0
- package/fesm2022/neural-ui-core-empty-state.mjs.map +1 -0
- package/fesm2022/neural-ui-core-filter-bar.mjs +118 -0
- package/fesm2022/neural-ui-core-filter-bar.mjs.map +1 -0
- package/fesm2022/neural-ui-core-icon.mjs +50 -0
- package/fesm2022/neural-ui-core-icon.mjs.map +1 -0
- package/fesm2022/neural-ui-core-image-viewer.mjs +309 -0
- package/fesm2022/neural-ui-core-image-viewer.mjs.map +1 -0
- package/fesm2022/neural-ui-core-input-otp.mjs +192 -0
- package/fesm2022/neural-ui-core-input-otp.mjs.map +1 -0
- package/fesm2022/neural-ui-core-input.mjs +320 -0
- package/fesm2022/neural-ui-core-input.mjs.map +1 -0
- package/fesm2022/neural-ui-core-knob.mjs +323 -0
- package/fesm2022/neural-ui-core-knob.mjs.map +1 -0
- package/fesm2022/neural-ui-core-meter-group.mjs +122 -0
- package/fesm2022/neural-ui-core-meter-group.mjs.map +1 -0
- package/fesm2022/neural-ui-core-modal.mjs +156 -0
- package/fesm2022/neural-ui-core-modal.mjs.map +1 -0
- package/fesm2022/neural-ui-core-multiselect.mjs +748 -0
- package/fesm2022/neural-ui-core-multiselect.mjs.map +1 -0
- package/fesm2022/neural-ui-core-nav.mjs +952 -0
- package/fesm2022/neural-ui-core-nav.mjs.map +1 -0
- package/fesm2022/neural-ui-core-notification-center.mjs +264 -0
- package/fesm2022/neural-ui-core-notification-center.mjs.map +1 -0
- package/fesm2022/neural-ui-core-number-input.mjs +331 -0
- package/fesm2022/neural-ui-core-number-input.mjs.map +1 -0
- package/fesm2022/neural-ui-core-pagination.mjs +198 -0
- package/fesm2022/neural-ui-core-pagination.mjs.map +1 -0
- package/fesm2022/neural-ui-core-popover.mjs +207 -0
- package/fesm2022/neural-ui-core-popover.mjs.map +1 -0
- package/fesm2022/neural-ui-core-progress-bar.mjs +105 -0
- package/fesm2022/neural-ui-core-progress-bar.mjs.map +1 -0
- package/fesm2022/neural-ui-core-radio.mjs +171 -0
- package/fesm2022/neural-ui-core-radio.mjs.map +1 -0
- package/fesm2022/neural-ui-core-rating.mjs +151 -0
- package/fesm2022/neural-ui-core-rating.mjs.map +1 -0
- package/fesm2022/neural-ui-core-select.mjs +638 -0
- package/fesm2022/neural-ui-core-select.mjs.map +1 -0
- package/fesm2022/neural-ui-core-sidebar.mjs +214 -0
- package/fesm2022/neural-ui-core-sidebar.mjs.map +1 -0
- package/fesm2022/neural-ui-core-skeleton.mjs +40 -0
- package/fesm2022/neural-ui-core-skeleton.mjs.map +1 -0
- package/fesm2022/neural-ui-core-slider.mjs +146 -0
- package/fesm2022/neural-ui-core-slider.mjs.map +1 -0
- package/fesm2022/neural-ui-core-spinner.mjs +113 -0
- package/fesm2022/neural-ui-core-spinner.mjs.map +1 -0
- package/fesm2022/neural-ui-core-split-button.mjs +252 -0
- package/fesm2022/neural-ui-core-split-button.mjs.map +1 -0
- package/fesm2022/neural-ui-core-splitter.mjs +174 -0
- package/fesm2022/neural-ui-core-splitter.mjs.map +1 -0
- package/fesm2022/neural-ui-core-stats-card.mjs +163 -0
- package/fesm2022/neural-ui-core-stats-card.mjs.map +1 -0
- package/fesm2022/neural-ui-core-stepper.mjs +204 -0
- package/fesm2022/neural-ui-core-stepper.mjs.map +1 -0
- package/fesm2022/neural-ui-core-switch.mjs +111 -0
- package/fesm2022/neural-ui-core-switch.mjs.map +1 -0
- package/fesm2022/neural-ui-core-table.mjs +1860 -0
- package/fesm2022/neural-ui-core-table.mjs.map +1 -0
- package/fesm2022/neural-ui-core-tabs.mjs +246 -0
- package/fesm2022/neural-ui-core-tabs.mjs.map +1 -0
- package/fesm2022/neural-ui-core-textarea.mjs +188 -0
- package/fesm2022/neural-ui-core-textarea.mjs.map +1 -0
- package/fesm2022/neural-ui-core-timeline.mjs +117 -0
- package/fesm2022/neural-ui-core-timeline.mjs.map +1 -0
- package/fesm2022/neural-ui-core-toast.mjs +171 -0
- package/fesm2022/neural-ui-core-toast.mjs.map +1 -0
- package/fesm2022/neural-ui-core-toggle-button-group.mjs +162 -0
- package/fesm2022/neural-ui-core-toggle-button-group.mjs.map +1 -0
- package/fesm2022/neural-ui-core-toolbar.mjs +67 -0
- package/fesm2022/neural-ui-core-toolbar.mjs.map +1 -0
- package/fesm2022/neural-ui-core-tooltip.mjs +151 -0
- package/fesm2022/neural-ui-core-tooltip.mjs.map +1 -0
- package/fesm2022/neural-ui-core-url-state.mjs +96 -0
- package/fesm2022/neural-ui-core-url-state.mjs.map +1 -0
- package/fesm2022/neural-ui-core-virtual-list.mjs +126 -0
- package/fesm2022/neural-ui-core-virtual-list.mjs.map +1 -0
- package/fesm2022/neural-ui-core.mjs +11 -8544
- package/fesm2022/neural-ui-core.mjs.map +1 -1
- package/filter-bar/package.json +4 -0
- package/icon/package.json +4 -0
- package/image-viewer/package.json +4 -0
- package/input/package.json +4 -0
- package/input-otp/package.json +4 -0
- package/knob/package.json +4 -0
- package/meter-group/package.json +4 -0
- package/modal/package.json +4 -0
- package/multiselect/package.json +4 -0
- package/nav/package.json +4 -0
- package/notification-center/package.json +4 -0
- package/number-input/package.json +4 -0
- package/package.json +252 -5
- package/pagination/package.json +4 -0
- package/popover/package.json +4 -0
- package/progress-bar/package.json +4 -0
- package/radio/package.json +4 -0
- package/rating/package.json +4 -0
- package/select/package.json +4 -0
- package/sidebar/package.json +4 -0
- package/skeleton/package.json +4 -0
- package/slider/package.json +4 -0
- package/spinner/package.json +4 -0
- package/split-button/package.json +4 -0
- package/splitter/package.json +4 -0
- package/stats-card/package.json +4 -0
- package/stepper/package.json +4 -0
- package/styles/_tokens.scss +202 -0
- package/styles.scss +1 -0
- package/switch/package.json +4 -0
- package/table/package.json +4 -0
- package/tabs/package.json +4 -0
- package/textarea/package.json +4 -0
- package/timeline/package.json +4 -0
- package/toast/package.json +4 -0
- package/toggle-button-group/package.json +4 -0
- package/toolbar/package.json +4 -0
- package/tooltip/package.json +4 -0
- package/types/neural-ui-core-accordion.d.ts +55 -0
- package/types/neural-ui-core-alert.d.ts +47 -0
- package/types/neural-ui-core-autocomplete.d.ts +69 -0
- package/types/neural-ui-core-avatar.d.ts +39 -0
- package/types/neural-ui-core-badge.d.ts +36 -0
- package/types/neural-ui-core-block-ui.d.ts +46 -0
- package/types/neural-ui-core-breadcrumb.d.ts +38 -0
- package/types/neural-ui-core-button.d.ts +55 -0
- package/types/neural-ui-core-card.d.ts +37 -0
- package/types/neural-ui-core-chart.d.ts +236 -0
- package/types/neural-ui-core-checkbox.d.ts +33 -0
- package/types/neural-ui-core-chip.d.ts +53 -0
- package/types/neural-ui-core-code-block.d.ts +55 -0
- package/types/neural-ui-core-color-picker.d.ts +55 -0
- package/types/neural-ui-core-command-palette.d.ts +56 -0
- package/types/neural-ui-core-confirm-dialog.d.ts +50 -0
- package/types/neural-ui-core-context-menu.d.ts +66 -0
- package/types/neural-ui-core-dashboard-grid.d.ts +41 -0
- package/types/neural-ui-core-date-input.d.ts +178 -0
- package/types/neural-ui-core-divider.d.ts +20 -0
- package/types/neural-ui-core-empty-state.d.ts +32 -0
- package/types/neural-ui-core-filter-bar.d.ts +49 -0
- package/types/neural-ui-core-icon.d.ts +33 -0
- package/types/neural-ui-core-image-viewer.d.ts +67 -0
- package/types/neural-ui-core-input-otp.d.ts +49 -0
- package/types/neural-ui-core-input.d.ts +86 -0
- package/types/neural-ui-core-knob.d.ts +68 -0
- package/types/neural-ui-core-meter-group.d.ts +52 -0
- package/types/neural-ui-core-modal.d.ts +54 -0
- package/types/neural-ui-core-multiselect.d.ts +129 -0
- package/types/neural-ui-core-nav.d.ts +69 -0
- package/types/neural-ui-core-notification-center.d.ts +60 -0
- package/types/neural-ui-core-number-input.d.ts +63 -0
- package/types/neural-ui-core-pagination.d.ts +30 -0
- package/types/neural-ui-core-popover.d.ts +73 -0
- package/types/neural-ui-core-progress-bar.d.ts +35 -0
- package/types/neural-ui-core-radio.d.ts +51 -0
- package/types/neural-ui-core-rating.d.ts +34 -0
- package/types/neural-ui-core-select.d.ts +161 -0
- package/types/neural-ui-core-sidebar.d.ts +57 -0
- package/types/neural-ui-core-skeleton.d.ts +22 -0
- package/types/neural-ui-core-slider.d.ts +42 -0
- package/types/neural-ui-core-spinner.d.ts +38 -0
- package/types/neural-ui-core-split-button.d.ts +65 -0
- package/types/neural-ui-core-splitter.d.ts +28 -0
- package/types/neural-ui-core-stats-card.d.ts +39 -0
- package/types/neural-ui-core-stepper.d.ts +51 -0
- package/types/neural-ui-core-switch.d.ts +34 -0
- package/types/neural-ui-core-table.d.ts +282 -0
- package/types/neural-ui-core-tabs.d.ts +76 -0
- package/types/neural-ui-core-textarea.d.ts +52 -0
- package/types/neural-ui-core-timeline.d.ts +33 -0
- package/types/neural-ui-core-toast.d.ts +70 -0
- package/types/neural-ui-core-toggle-button-group.d.ts +63 -0
- package/types/neural-ui-core-toolbar.d.ts +36 -0
- package/types/neural-ui-core-tooltip.d.ts +48 -0
- package/types/neural-ui-core-url-state.d.ts +58 -0
- package/types/neural-ui-core-virtual-list.d.ts +60 -0
- package/types/neural-ui-core.d.ts +3 -2105
- package/url-state/package.json +4 -0
- 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,332 @@
|
|
|
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
|
+
emptyLabel = input('Sin resultados', ...(ngDevMode ? [{ debugName: "emptyLabel" }] : /* istanbul ignore next */ []));
|
|
26
|
+
minLength = input(0, ...(ngDevMode ? [{ debugName: "minLength" }] : /* istanbul ignore next */ []));
|
|
27
|
+
/** 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) */
|
|
28
|
+
floatingLabel = input(false, ...(ngDevMode ? [{ debugName: "floatingLabel" }] : /* istanbul ignore next */ []));
|
|
29
|
+
/** Tamaño del campo: 'sm' = 36px | 'md' = 48px | 'lg' = 56px / Field size */
|
|
30
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
31
|
+
/** Emitido al seleccionar una opción / Emitted when an option is selected */
|
|
32
|
+
optionSelected = output();
|
|
33
|
+
/** Emitido al cambiar el texto del input / Emitted on query change */
|
|
34
|
+
queryChange = output();
|
|
35
|
+
// ── Internal state ───────────────────────────────────────────────
|
|
36
|
+
_id = `neu-autocomplete-${++_seq}`;
|
|
37
|
+
_listId = `${this._id}-list`;
|
|
38
|
+
_query = signal('', ...(ngDevMode ? [{ debugName: "_query" }] : /* istanbul ignore next */ []));
|
|
39
|
+
_isOpen = signal(false, ...(ngDevMode ? [{ debugName: "_isOpen" }] : /* istanbul ignore next */ []));
|
|
40
|
+
_activeIndex = signal(-1, ...(ngDevMode ? [{ debugName: "_activeIndex" }] : /* istanbul ignore next */ []));
|
|
41
|
+
_cvaDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_cvaDisabled" }] : /* istanbul ignore next */ []));
|
|
42
|
+
_focused = signal(false, ...(ngDevMode ? [{ debugName: "_focused" }] : /* istanbul ignore next */ []));
|
|
43
|
+
_onChange = () => { };
|
|
44
|
+
_onTouched = () => { };
|
|
45
|
+
// ── Computed ─────────────────────────────────────────────────────
|
|
46
|
+
_filtered = computed(() => {
|
|
47
|
+
const q = this._query().toLowerCase().trim();
|
|
48
|
+
// Con query vacía nunca mostramos opciones (no queremos comportarnos como un select).
|
|
49
|
+
// Empty query → never show options (autocomplete ≠ select).
|
|
50
|
+
if (!q)
|
|
51
|
+
return [];
|
|
52
|
+
if (q.length < this.minLength())
|
|
53
|
+
return [];
|
|
54
|
+
return this.options().filter((o) => o.label.toLowerCase().includes(q));
|
|
55
|
+
}, ...(ngDevMode ? [{ debugName: "_filtered" }] : /* istanbul ignore next */ []));
|
|
56
|
+
_activeId = computed(() => {
|
|
57
|
+
const i = this._activeIndex();
|
|
58
|
+
return i >= 0 ? this._optionId(i) : null;
|
|
59
|
+
}, ...(ngDevMode ? [{ debugName: "_activeId" }] : /* istanbul ignore next */ []));
|
|
60
|
+
_optionId(i) {
|
|
61
|
+
return `${this._listId}-opt-${i}`;
|
|
62
|
+
}
|
|
63
|
+
// ── HostListener close on outside click ─────────────────────────
|
|
64
|
+
_el = inject((ElementRef));
|
|
65
|
+
onDocClick(e) {
|
|
66
|
+
if (!this._el.nativeElement.contains(e.target)) {
|
|
67
|
+
this._isOpen.set(false);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// ── Event handlers ───────────────────────────────────────────────
|
|
71
|
+
onQueryChange(q) {
|
|
72
|
+
this._query.set(q);
|
|
73
|
+
this._activeIndex.set(-1);
|
|
74
|
+
// Sólo abrimos si hay texto suficiente; si no, cerramos.
|
|
75
|
+
// Only open when there is enough text; otherwise close.
|
|
76
|
+
const minLen = Math.max(1, this.minLength());
|
|
77
|
+
this._isOpen.set(q.trim().length >= minLen);
|
|
78
|
+
this.queryChange.emit(q);
|
|
79
|
+
// CVA — emit null when query is cleared
|
|
80
|
+
if (!q) {
|
|
81
|
+
this._onChange(null);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
_onFocus() {
|
|
85
|
+
this._focused.set(true);
|
|
86
|
+
// Abre el dropdown solo si ya hay texto escrito / Only open when there is already a query.
|
|
87
|
+
if (this._query().trim().length >= Math.max(1, this.minLength())) {
|
|
88
|
+
this._isOpen.set(true);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
_onBlur() {
|
|
92
|
+
this._focused.set(false);
|
|
93
|
+
this._onTouched();
|
|
94
|
+
// Small delay to allow mousedown on option to fire first
|
|
95
|
+
setTimeout(() => this._isOpen.set(false), 150);
|
|
96
|
+
}
|
|
97
|
+
onKeyDown(e) {
|
|
98
|
+
const total = this._filtered().length;
|
|
99
|
+
if (!total && e.key !== 'Escape')
|
|
100
|
+
return;
|
|
101
|
+
switch (e.key) {
|
|
102
|
+
case 'ArrowDown':
|
|
103
|
+
e.preventDefault();
|
|
104
|
+
this._activeIndex.update((i) => Math.min(i + 1, total - 1));
|
|
105
|
+
this._isOpen.set(true);
|
|
106
|
+
break;
|
|
107
|
+
case 'ArrowUp':
|
|
108
|
+
e.preventDefault();
|
|
109
|
+
this._activeIndex.update((i) => Math.max(i - 1, 0));
|
|
110
|
+
break;
|
|
111
|
+
case 'Enter': {
|
|
112
|
+
const idx = this._activeIndex();
|
|
113
|
+
const opt = this._filtered()[idx];
|
|
114
|
+
if (opt && !opt.disabled)
|
|
115
|
+
this.selectOption(opt);
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
case 'Escape':
|
|
119
|
+
this._isOpen.set(false);
|
|
120
|
+
this._activeIndex.set(-1);
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
selectOption(opt) {
|
|
125
|
+
if (opt.disabled)
|
|
126
|
+
return;
|
|
127
|
+
this._query.set(opt.label);
|
|
128
|
+
this._isOpen.set(false);
|
|
129
|
+
this._activeIndex.set(-1);
|
|
130
|
+
this._onChange(opt.value);
|
|
131
|
+
this.optionSelected.emit(opt);
|
|
132
|
+
}
|
|
133
|
+
clear() {
|
|
134
|
+
this._query.set('');
|
|
135
|
+
this._onChange(null);
|
|
136
|
+
this._isOpen.set(false);
|
|
137
|
+
this.queryChange.emit('');
|
|
138
|
+
}
|
|
139
|
+
// ── CVA ──────────────────────────────────────────────────────────
|
|
140
|
+
writeValue(val) {
|
|
141
|
+
if (val === null || val === undefined) {
|
|
142
|
+
this._query.set('');
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const match = this.options().find((o) => o.value === val);
|
|
146
|
+
this._query.set(match ? match.label : String(val));
|
|
147
|
+
}
|
|
148
|
+
registerOnChange(fn) {
|
|
149
|
+
this._onChange = fn;
|
|
150
|
+
}
|
|
151
|
+
registerOnTouched(fn) {
|
|
152
|
+
this._onTouched = fn;
|
|
153
|
+
}
|
|
154
|
+
setDisabledState(d) {
|
|
155
|
+
this._cvaDisabled.set(d);
|
|
156
|
+
}
|
|
157
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuAutocompleteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
158
|
+
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 }, 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: [
|
|
159
|
+
{
|
|
160
|
+
provide: NG_VALUE_ACCESSOR,
|
|
161
|
+
useExisting: forwardRef(() => NeuAutocompleteComponent),
|
|
162
|
+
multi: true,
|
|
163
|
+
},
|
|
164
|
+
], ngImport: i0, template: `
|
|
165
|
+
@if (!floatingLabel() && label()) {
|
|
166
|
+
<label class="neu-autocomplete__label" [for]="_id">{{ label() }}</label>
|
|
167
|
+
}
|
|
168
|
+
<div
|
|
169
|
+
class="neu-autocomplete__input-wrap"
|
|
170
|
+
[class.neu-autocomplete__input-wrap--focused]="_focused()"
|
|
171
|
+
[class.neu-autocomplete__input-wrap--has-value]="!!_query()"
|
|
172
|
+
>
|
|
173
|
+
<input
|
|
174
|
+
#inputEl
|
|
175
|
+
class="neu-autocomplete__input"
|
|
176
|
+
type="text"
|
|
177
|
+
autocomplete="off"
|
|
178
|
+
role="combobox"
|
|
179
|
+
[id]="_id"
|
|
180
|
+
[attr.placeholder]="floatingLabel() ? ' ' : placeholder() || null"
|
|
181
|
+
[attr.aria-label]="label() || placeholder()"
|
|
182
|
+
[attr.aria-expanded]="_isOpen()"
|
|
183
|
+
[attr.aria-controls]="_listId"
|
|
184
|
+
[attr.aria-activedescendant]="_activeId()"
|
|
185
|
+
[disabled]="_cvaDisabled()"
|
|
186
|
+
[value]="_query()"
|
|
187
|
+
(input)="onQueryChange($any($event.target).value)"
|
|
188
|
+
(focus)="_onFocus()"
|
|
189
|
+
(blur)="_onBlur()"
|
|
190
|
+
(keydown)="onKeyDown($event)"
|
|
191
|
+
/>
|
|
192
|
+
@if (floatingLabel() && label()) {
|
|
193
|
+
<label class="neu-autocomplete__floating-label" [for]="_id">{{ label() }}</label>
|
|
194
|
+
}
|
|
195
|
+
@if (_query() && !_cvaDisabled()) {
|
|
196
|
+
<button
|
|
197
|
+
type="button"
|
|
198
|
+
class="neu-autocomplete__clear"
|
|
199
|
+
aria-label="Limpiar"
|
|
200
|
+
tabindex="-1"
|
|
201
|
+
(click)="clear()"
|
|
202
|
+
>
|
|
203
|
+
×
|
|
204
|
+
</button>
|
|
205
|
+
}
|
|
206
|
+
</div>
|
|
207
|
+
@if (_isOpen() && _filtered().length) {
|
|
208
|
+
<ul
|
|
209
|
+
class="neu-autocomplete__list"
|
|
210
|
+
role="listbox"
|
|
211
|
+
[id]="_listId"
|
|
212
|
+
[attr.aria-label]="label() || placeholder()"
|
|
213
|
+
>
|
|
214
|
+
@for (opt of _filtered(); track opt.label; let i = $index) {
|
|
215
|
+
<li
|
|
216
|
+
class="neu-autocomplete__option"
|
|
217
|
+
role="option"
|
|
218
|
+
[id]="_optionId(i)"
|
|
219
|
+
[class.neu-autocomplete__option--active]="_activeIndex() === i"
|
|
220
|
+
[class.neu-autocomplete__option--disabled]="opt.disabled"
|
|
221
|
+
[attr.aria-selected]="_activeIndex() === i"
|
|
222
|
+
[attr.aria-disabled]="opt.disabled ?? false"
|
|
223
|
+
(mousedown)="selectOption(opt)"
|
|
224
|
+
>
|
|
225
|
+
{{ opt.label }}
|
|
226
|
+
</li>
|
|
227
|
+
}
|
|
228
|
+
</ul>
|
|
229
|
+
}
|
|
230
|
+
@if (_isOpen() && !_filtered().length) {
|
|
231
|
+
<div class="neu-autocomplete__empty" role="status">{{ emptyLabel() }}</div>
|
|
232
|
+
}
|
|
233
|
+
`, 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{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__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--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 });
|
|
234
|
+
}
|
|
235
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuAutocompleteComponent, decorators: [{
|
|
236
|
+
type: Component,
|
|
237
|
+
args: [{ selector: 'neu-autocomplete', imports: [], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
238
|
+
{
|
|
239
|
+
provide: NG_VALUE_ACCESSOR,
|
|
240
|
+
useExisting: forwardRef(() => NeuAutocompleteComponent),
|
|
241
|
+
multi: true,
|
|
242
|
+
},
|
|
243
|
+
], host: {
|
|
244
|
+
class: 'neu-autocomplete',
|
|
245
|
+
'[class.neu-autocomplete--open]': '_isOpen()',
|
|
246
|
+
'[class.neu-autocomplete--disabled]': '_cvaDisabled()',
|
|
247
|
+
'[class.neu-autocomplete--floating]': 'floatingLabel()',
|
|
248
|
+
'[class.neu-autocomplete--focused]': '_focused()',
|
|
249
|
+
'[class.neu-autocomplete--has-value]': '!!_query()',
|
|
250
|
+
'[class.neu-autocomplete--sm]': 'size() === "sm"',
|
|
251
|
+
'[class.neu-autocomplete--lg]': 'size() === "lg"',
|
|
252
|
+
}, template: `
|
|
253
|
+
@if (!floatingLabel() && label()) {
|
|
254
|
+
<label class="neu-autocomplete__label" [for]="_id">{{ label() }}</label>
|
|
255
|
+
}
|
|
256
|
+
<div
|
|
257
|
+
class="neu-autocomplete__input-wrap"
|
|
258
|
+
[class.neu-autocomplete__input-wrap--focused]="_focused()"
|
|
259
|
+
[class.neu-autocomplete__input-wrap--has-value]="!!_query()"
|
|
260
|
+
>
|
|
261
|
+
<input
|
|
262
|
+
#inputEl
|
|
263
|
+
class="neu-autocomplete__input"
|
|
264
|
+
type="text"
|
|
265
|
+
autocomplete="off"
|
|
266
|
+
role="combobox"
|
|
267
|
+
[id]="_id"
|
|
268
|
+
[attr.placeholder]="floatingLabel() ? ' ' : placeholder() || null"
|
|
269
|
+
[attr.aria-label]="label() || placeholder()"
|
|
270
|
+
[attr.aria-expanded]="_isOpen()"
|
|
271
|
+
[attr.aria-controls]="_listId"
|
|
272
|
+
[attr.aria-activedescendant]="_activeId()"
|
|
273
|
+
[disabled]="_cvaDisabled()"
|
|
274
|
+
[value]="_query()"
|
|
275
|
+
(input)="onQueryChange($any($event.target).value)"
|
|
276
|
+
(focus)="_onFocus()"
|
|
277
|
+
(blur)="_onBlur()"
|
|
278
|
+
(keydown)="onKeyDown($event)"
|
|
279
|
+
/>
|
|
280
|
+
@if (floatingLabel() && label()) {
|
|
281
|
+
<label class="neu-autocomplete__floating-label" [for]="_id">{{ label() }}</label>
|
|
282
|
+
}
|
|
283
|
+
@if (_query() && !_cvaDisabled()) {
|
|
284
|
+
<button
|
|
285
|
+
type="button"
|
|
286
|
+
class="neu-autocomplete__clear"
|
|
287
|
+
aria-label="Limpiar"
|
|
288
|
+
tabindex="-1"
|
|
289
|
+
(click)="clear()"
|
|
290
|
+
>
|
|
291
|
+
×
|
|
292
|
+
</button>
|
|
293
|
+
}
|
|
294
|
+
</div>
|
|
295
|
+
@if (_isOpen() && _filtered().length) {
|
|
296
|
+
<ul
|
|
297
|
+
class="neu-autocomplete__list"
|
|
298
|
+
role="listbox"
|
|
299
|
+
[id]="_listId"
|
|
300
|
+
[attr.aria-label]="label() || placeholder()"
|
|
301
|
+
>
|
|
302
|
+
@for (opt of _filtered(); track opt.label; let i = $index) {
|
|
303
|
+
<li
|
|
304
|
+
class="neu-autocomplete__option"
|
|
305
|
+
role="option"
|
|
306
|
+
[id]="_optionId(i)"
|
|
307
|
+
[class.neu-autocomplete__option--active]="_activeIndex() === i"
|
|
308
|
+
[class.neu-autocomplete__option--disabled]="opt.disabled"
|
|
309
|
+
[attr.aria-selected]="_activeIndex() === i"
|
|
310
|
+
[attr.aria-disabled]="opt.disabled ?? false"
|
|
311
|
+
(mousedown)="selectOption(opt)"
|
|
312
|
+
>
|
|
313
|
+
{{ opt.label }}
|
|
314
|
+
</li>
|
|
315
|
+
}
|
|
316
|
+
</ul>
|
|
317
|
+
}
|
|
318
|
+
@if (_isOpen() && !_filtered().length) {
|
|
319
|
+
<div class="neu-autocomplete__empty" role="status">{{ emptyLabel() }}</div>
|
|
320
|
+
}
|
|
321
|
+
`, 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{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__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--sm .neu-autocomplete__input{height:36px;font-size:var(--neu-text-sm, .875rem)}.neu-autocomplete--lg .neu-autocomplete__input{height:56px}\n"] }]
|
|
322
|
+
}], 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 }] }], 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: [{
|
|
323
|
+
type: HostListener,
|
|
324
|
+
args: ['document:mousedown', ['$event']]
|
|
325
|
+
}] } });
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Generated bundle index. Do not edit.
|
|
329
|
+
*/
|
|
330
|
+
|
|
331
|
+
export { NeuAutocompleteComponent };
|
|
332
|
+
//# 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-expanded]=\"_isOpen()\"\n [attr.aria-controls]=\"_listId\"\n [attr.aria-activedescendant]=\"_activeId()\"\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 @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 `,\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 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 _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._activeIndex.update((i) => Math.min(i + 1, total - 1));\n this._isOpen.set(true);\n break;\n case 'ArrowUp':\n e.preventDefault();\n this._activeIndex.update((i) => Math.max(i - 1, 0));\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 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":"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"}
|