@neural-ui/core 1.5.7 → 1.5.9
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/fesm2022/neural-ui-core-autocomplete.mjs +193 -90
- package/fesm2022/neural-ui-core-autocomplete.mjs.map +1 -1
- package/fesm2022/neural-ui-core-color-picker.mjs +66 -8
- package/fesm2022/neural-ui-core-color-picker.mjs.map +1 -1
- package/fesm2022/neural-ui-core-date-input.mjs +139 -19
- package/fesm2022/neural-ui-core-date-input.mjs.map +1 -1
- package/fesm2022/neural-ui-core-multiselect.mjs +86 -32
- package/fesm2022/neural-ui-core-multiselect.mjs.map +1 -1
- package/fesm2022/neural-ui-core-notification-center.mjs +63 -7
- package/fesm2022/neural-ui-core-notification-center.mjs.map +1 -1
- package/fesm2022/neural-ui-core-select.mjs +87 -39
- package/fesm2022/neural-ui-core-select.mjs.map +1 -1
- package/fesm2022/neural-ui-core-split-button.mjs +67 -8
- package/fesm2022/neural-ui-core-split-button.mjs.map +1 -1
- package/package.json +1 -1
- package/styles/_cdk-overlay.scss +69 -0
- package/styles/index.scss +1 -0
- package/types/neural-ui-core-autocomplete.d.ts +11 -0
- package/types/neural-ui-core-color-picker.d.ts +6 -0
- package/types/neural-ui-core-date-input.d.ts +7 -1
- package/types/neural-ui-core-multiselect.d.ts +8 -3
- package/types/neural-ui-core-notification-center.d.ts +6 -0
- package/types/neural-ui-core-select.d.ts +8 -2
- package/types/neural-ui-core-split-button.d.ts +6 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { signal, computed, Injectable, inject, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/cdk/overlay';
|
|
4
|
+
import { Overlay, OverlayModule } from '@angular/cdk/overlay';
|
|
3
5
|
|
|
4
6
|
const DEFAULT_ICONS = {
|
|
5
7
|
info: 'ℹ️',
|
|
@@ -69,8 +71,34 @@ let _panelSeq = 0;
|
|
|
69
71
|
*/
|
|
70
72
|
class NeuNotificationCenterComponent {
|
|
71
73
|
_svc = inject(NeuNotificationService);
|
|
74
|
+
overlay = inject(Overlay);
|
|
72
75
|
_isOpen = signal(false, ...(ngDevMode ? [{ debugName: "_isOpen" }] : /* istanbul ignore next */ []));
|
|
73
76
|
_panelId = `neu-nc-panel-${++_panelSeq}`;
|
|
77
|
+
_viewportMargin = 16;
|
|
78
|
+
overlayPositions = [
|
|
79
|
+
{
|
|
80
|
+
originX: 'end',
|
|
81
|
+
originY: 'bottom',
|
|
82
|
+
overlayX: 'end',
|
|
83
|
+
overlayY: 'top',
|
|
84
|
+
offsetY: 8,
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
originX: 'end',
|
|
88
|
+
originY: 'top',
|
|
89
|
+
overlayX: 'end',
|
|
90
|
+
overlayY: 'bottom',
|
|
91
|
+
offsetY: -8,
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
originX: 'start',
|
|
95
|
+
originY: 'bottom',
|
|
96
|
+
overlayX: 'start',
|
|
97
|
+
overlayY: 'top',
|
|
98
|
+
offsetY: 8,
|
|
99
|
+
},
|
|
100
|
+
];
|
|
101
|
+
overlayScrollStrategy = this.overlay.scrollStrategies.reposition();
|
|
74
102
|
_toggle() {
|
|
75
103
|
const opening = !this._isOpen();
|
|
76
104
|
this._isOpen.set(opening);
|
|
@@ -95,6 +123,8 @@ class NeuNotificationCenterComponent {
|
|
|
95
123
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: NeuNotificationCenterComponent, isStandalone: true, selector: "neu-notification-center", host: { properties: { "attr.aria-label": "\"Centro de notificaciones\"" }, classAttribute: "neu-nc" }, ngImport: i0, template: `
|
|
96
124
|
<!-- Bell button -->
|
|
97
125
|
<button
|
|
126
|
+
cdkOverlayOrigin
|
|
127
|
+
#notificationOrigin="cdkOverlayOrigin"
|
|
98
128
|
type="button"
|
|
99
129
|
class="neu-nc__bell"
|
|
100
130
|
[attr.aria-expanded]="_isOpen()"
|
|
@@ -111,7 +141,19 @@ class NeuNotificationCenterComponent {
|
|
|
111
141
|
</button>
|
|
112
142
|
|
|
113
143
|
<!-- Panel -->
|
|
114
|
-
|
|
144
|
+
<ng-template
|
|
145
|
+
cdkConnectedOverlay
|
|
146
|
+
[cdkConnectedOverlayOrigin]="notificationOrigin"
|
|
147
|
+
[cdkConnectedOverlayOpen]="_isOpen()"
|
|
148
|
+
[cdkConnectedOverlayPositions]="overlayPositions"
|
|
149
|
+
[cdkConnectedOverlayScrollStrategy]="overlayScrollStrategy"
|
|
150
|
+
[cdkConnectedOverlayHasBackdrop]="true"
|
|
151
|
+
[cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'"
|
|
152
|
+
[cdkConnectedOverlayPush]="true"
|
|
153
|
+
[cdkConnectedOverlayViewportMargin]="_viewportMargin"
|
|
154
|
+
(backdropClick)="_isOpen.set(false)"
|
|
155
|
+
(detach)="_isOpen.set(false)"
|
|
156
|
+
>
|
|
115
157
|
<div
|
|
116
158
|
class="neu-nc__panel"
|
|
117
159
|
[id]="_panelId"
|
|
@@ -168,17 +210,19 @@ class NeuNotificationCenterComponent {
|
|
|
168
210
|
}
|
|
169
211
|
</div>
|
|
170
212
|
</div>
|
|
171
|
-
|
|
172
|
-
`, isInline: true, styles: ["@charset \"UTF-8\";.neu-nc{position:relative;display:inline-block}.neu-nc__bell{all:unset;position:relative;display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--neu-radius-lg, 12px);cursor:pointer;transition:background .12s}.neu-nc__bell:hover{background:var(--neu-surface-2, #f3f4f6)}.neu-nc__bell:focus-visible{outline:2px solid var(--neu-focus-ring, #0ea5e9);outline-offset:2px}.neu-nc__bell-icon{font-size:1.2rem}.neu-nc__badge{position:absolute;top:4px;right:4px;min-width:16px;height:16px;padding:0 4px;border-radius:999px;background:var(--neu-error);color:var(--neu-text-inverse);font-size:.625rem;font-weight:700;display:flex;align-items:center;justify-content:center;line-height:1}.neu-nc__panel{position:
|
|
213
|
+
</ng-template>
|
|
214
|
+
`, isInline: true, styles: ["@charset \"UTF-8\";.neu-nc{position:relative;display:inline-block}.neu-nc__bell{all:unset;position:relative;display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--neu-radius-lg, 12px);cursor:pointer;transition:background .12s}.neu-nc__bell:hover{background:var(--neu-surface-2, #f3f4f6)}.neu-nc__bell:focus-visible{outline:2px solid var(--neu-focus-ring, #0ea5e9);outline-offset:2px}.neu-nc__bell-icon{font-size:1.2rem}.neu-nc__badge{position:absolute;top:4px;right:4px;min-width:16px;height:16px;padding:0 4px;border-radius:999px;background:var(--neu-error);color:var(--neu-text-inverse);font-size:.625rem;font-weight:700;display:flex;align-items:center;justify-content:center;line-height:1}.neu-nc__panel{position:relative;width:320px;max-height:420px;display:flex;flex-direction:column;background:var(--neu-surface-1, #ffffff);border:1px solid var(--neu-border-color, #e5e7eb);border-radius:var(--neu-radius-xl, 16px);box-shadow:0 12px 28px -6px #00000024;z-index:1001;overflow:hidden;animation:neu-nc-in .1s ease}@keyframes neu-nc-in{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}.neu-nc__panel-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--neu-border-color, #e5e7eb);flex-shrink:0}.neu-nc__panel-title{font-size:.9375rem;font-weight:600;color:var(--neu-text-primary, #111)}.neu-nc__panel-actions{display:flex;gap:8px}.neu-nc__action-btn{all:unset;font-size:.75rem;color:var(--neu-color-primary, #0ea5e9);cursor:pointer;padding:2px 6px;border-radius:var(--neu-radius-sm, 4px)}.neu-nc__action-btn:hover{background:var(--neu-color-primary-alpha, rgba(14, 165, 233, .1))}.neu-nc__list{overflow-y:auto;flex:1;padding:6px}.neu-nc__empty{padding:24px;text-align:center;font-size:.875rem;color:var(--neu-text-secondary, #6b7280)}.neu-nc__item{display:flex;align-items:flex-start;gap:10px;padding:10px 10px 10px 12px;border-radius:var(--neu-radius-lg, 12px);position:relative;transition:background .1s}.neu-nc__item:hover{background:var(--neu-surface-2, #f3f4f6)}.neu-nc__item--unread:before{content:\"\";position:absolute;left:4px;top:50%;transform:translateY(-50%);width:6px;height:6px;border-radius:50%;background:var(--neu-color-primary, #0ea5e9)}.neu-nc__item-icon{font-size:1.1rem;flex-shrink:0;padding-top:2px}.neu-nc__item-body{flex:1;min-width:0}.neu-nc__item-title{margin:0 0 2px;font-size:.8125rem;font-weight:600;color:var(--neu-text-primary, #111)}.neu-nc__item-msg{margin:0 0 4px;font-size:.8125rem;color:var(--neu-text-secondary, #4b5563);line-height:1.4}.neu-nc__item-time{font-size:.6875rem;color:var(--neu-text-secondary, #9ca3af)}.neu-nc__item-close{all:unset;opacity:0;cursor:pointer;padding:2px 6px;border-radius:4px;font-size:1rem;color:var(--neu-text-secondary, #9ca3af);flex-shrink:0;transition:opacity .1s}.neu-nc__item:hover .neu-nc__item-close{opacity:1}.neu-nc__item-close:hover{color:var(--neu-text-primary, #111)}\n"], dependencies: [{ kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
173
215
|
}
|
|
174
216
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuNotificationCenterComponent, decorators: [{
|
|
175
217
|
type: Component,
|
|
176
|
-
args: [{ selector: 'neu-notification-center', imports: [], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
218
|
+
args: [{ selector: 'neu-notification-center', imports: [OverlayModule], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
177
219
|
class: 'neu-nc',
|
|
178
220
|
'[attr.aria-label]': '"Centro de notificaciones"',
|
|
179
221
|
}, template: `
|
|
180
222
|
<!-- Bell button -->
|
|
181
223
|
<button
|
|
224
|
+
cdkOverlayOrigin
|
|
225
|
+
#notificationOrigin="cdkOverlayOrigin"
|
|
182
226
|
type="button"
|
|
183
227
|
class="neu-nc__bell"
|
|
184
228
|
[attr.aria-expanded]="_isOpen()"
|
|
@@ -195,7 +239,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
195
239
|
</button>
|
|
196
240
|
|
|
197
241
|
<!-- Panel -->
|
|
198
|
-
|
|
242
|
+
<ng-template
|
|
243
|
+
cdkConnectedOverlay
|
|
244
|
+
[cdkConnectedOverlayOrigin]="notificationOrigin"
|
|
245
|
+
[cdkConnectedOverlayOpen]="_isOpen()"
|
|
246
|
+
[cdkConnectedOverlayPositions]="overlayPositions"
|
|
247
|
+
[cdkConnectedOverlayScrollStrategy]="overlayScrollStrategy"
|
|
248
|
+
[cdkConnectedOverlayHasBackdrop]="true"
|
|
249
|
+
[cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'"
|
|
250
|
+
[cdkConnectedOverlayPush]="true"
|
|
251
|
+
[cdkConnectedOverlayViewportMargin]="_viewportMargin"
|
|
252
|
+
(backdropClick)="_isOpen.set(false)"
|
|
253
|
+
(detach)="_isOpen.set(false)"
|
|
254
|
+
>
|
|
199
255
|
<div
|
|
200
256
|
class="neu-nc__panel"
|
|
201
257
|
[id]="_panelId"
|
|
@@ -252,8 +308,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
252
308
|
}
|
|
253
309
|
</div>
|
|
254
310
|
</div>
|
|
255
|
-
|
|
256
|
-
`, styles: ["@charset \"UTF-8\";.neu-nc{position:relative;display:inline-block}.neu-nc__bell{all:unset;position:relative;display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--neu-radius-lg, 12px);cursor:pointer;transition:background .12s}.neu-nc__bell:hover{background:var(--neu-surface-2, #f3f4f6)}.neu-nc__bell:focus-visible{outline:2px solid var(--neu-focus-ring, #0ea5e9);outline-offset:2px}.neu-nc__bell-icon{font-size:1.2rem}.neu-nc__badge{position:absolute;top:4px;right:4px;min-width:16px;height:16px;padding:0 4px;border-radius:999px;background:var(--neu-error);color:var(--neu-text-inverse);font-size:.625rem;font-weight:700;display:flex;align-items:center;justify-content:center;line-height:1}.neu-nc__panel{position:
|
|
311
|
+
</ng-template>
|
|
312
|
+
`, styles: ["@charset \"UTF-8\";.neu-nc{position:relative;display:inline-block}.neu-nc__bell{all:unset;position:relative;display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--neu-radius-lg, 12px);cursor:pointer;transition:background .12s}.neu-nc__bell:hover{background:var(--neu-surface-2, #f3f4f6)}.neu-nc__bell:focus-visible{outline:2px solid var(--neu-focus-ring, #0ea5e9);outline-offset:2px}.neu-nc__bell-icon{font-size:1.2rem}.neu-nc__badge{position:absolute;top:4px;right:4px;min-width:16px;height:16px;padding:0 4px;border-radius:999px;background:var(--neu-error);color:var(--neu-text-inverse);font-size:.625rem;font-weight:700;display:flex;align-items:center;justify-content:center;line-height:1}.neu-nc__panel{position:relative;width:320px;max-height:420px;display:flex;flex-direction:column;background:var(--neu-surface-1, #ffffff);border:1px solid var(--neu-border-color, #e5e7eb);border-radius:var(--neu-radius-xl, 16px);box-shadow:0 12px 28px -6px #00000024;z-index:1001;overflow:hidden;animation:neu-nc-in .1s ease}@keyframes neu-nc-in{0%{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:translateY(0)}}.neu-nc__panel-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid var(--neu-border-color, #e5e7eb);flex-shrink:0}.neu-nc__panel-title{font-size:.9375rem;font-weight:600;color:var(--neu-text-primary, #111)}.neu-nc__panel-actions{display:flex;gap:8px}.neu-nc__action-btn{all:unset;font-size:.75rem;color:var(--neu-color-primary, #0ea5e9);cursor:pointer;padding:2px 6px;border-radius:var(--neu-radius-sm, 4px)}.neu-nc__action-btn:hover{background:var(--neu-color-primary-alpha, rgba(14, 165, 233, .1))}.neu-nc__list{overflow-y:auto;flex:1;padding:6px}.neu-nc__empty{padding:24px;text-align:center;font-size:.875rem;color:var(--neu-text-secondary, #6b7280)}.neu-nc__item{display:flex;align-items:flex-start;gap:10px;padding:10px 10px 10px 12px;border-radius:var(--neu-radius-lg, 12px);position:relative;transition:background .1s}.neu-nc__item:hover{background:var(--neu-surface-2, #f3f4f6)}.neu-nc__item--unread:before{content:\"\";position:absolute;left:4px;top:50%;transform:translateY(-50%);width:6px;height:6px;border-radius:50%;background:var(--neu-color-primary, #0ea5e9)}.neu-nc__item-icon{font-size:1.1rem;flex-shrink:0;padding-top:2px}.neu-nc__item-body{flex:1;min-width:0}.neu-nc__item-title{margin:0 0 2px;font-size:.8125rem;font-weight:600;color:var(--neu-text-primary, #111)}.neu-nc__item-msg{margin:0 0 4px;font-size:.8125rem;color:var(--neu-text-secondary, #4b5563);line-height:1.4}.neu-nc__item-time{font-size:.6875rem;color:var(--neu-text-secondary, #9ca3af)}.neu-nc__item-close{all:unset;opacity:0;cursor:pointer;padding:2px 6px;border-radius:4px;font-size:1rem;color:var(--neu-text-secondary, #9ca3af);flex-shrink:0;transition:opacity .1s}.neu-nc__item:hover .neu-nc__item-close{opacity:1}.neu-nc__item-close:hover{color:var(--neu-text-primary, #111)}\n"] }]
|
|
257
313
|
}] });
|
|
258
314
|
|
|
259
315
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"neural-ui-core-notification-center.mjs","sources":["../../../../projects/ui-core/notification-center/neu-notification-center.component.ts","../../../../projects/ui-core/notification-center/neural-ui-core-notification-center.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n Injectable,\n OnDestroy,\n ViewEncapsulation,\n computed,\n inject,\n signal,\n} from '@angular/core';\n\nexport type NeuNotificationType = 'info' | 'success' | 'warning' | 'error';\n\nexport interface NeuNotification {\n id: string;\n type: NeuNotificationType;\n title?: string;\n message: string;\n /** Auto-dismiss duration in ms (0 = persistent) */\n duration?: number;\n /** Icon text / emoji */\n icon?: string;\n timestamp: Date;\n read: boolean;\n}\n\nexport interface NeuNotificationOptions extends Omit<\n NeuNotification,\n 'id' | 'timestamp' | 'read'\n> {}\n\nconst DEFAULT_ICONS: Record<NeuNotificationType, string> = {\n info: 'ℹ️',\n success: '✅',\n warning: '⚠️',\n error: '❌',\n};\n\nlet _idSeq = 0;\n\n/**\n * NeuralUI NotificationService\n *\n * Servicio inyectable que gestiona la cola de notificaciones.\n *\n * Uso:\n * inject(NeuNotificationService).push({ type: 'success', message: '¡Guardado!' });\n */\n@Injectable({ providedIn: 'root' })\nexport class NeuNotificationService {\n readonly notifications = signal<NeuNotification[]>([]);\n\n readonly unreadCount = computed(() => this.notifications().filter((n) => !n.read).length);\n\n /** Agrega una notificación / Adds a notification */\n push(opts: Partial<NeuNotificationOptions> & Pick<NeuNotificationOptions, 'message'>): string {\n const id = `neu-notif-${++_idSeq}`;\n const n: NeuNotification = {\n id,\n type: opts.type ?? 'info',\n title: opts.title,\n message: opts.message,\n icon: opts.icon ?? DEFAULT_ICONS[opts.type ?? 'info'],\n duration: opts.duration ?? 5000,\n timestamp: new Date(),\n read: false,\n };\n this.notifications.update((list) => [n, ...list]);\n\n if (n.duration && n.duration > 0) {\n setTimeout(() => this.remove(id), n.duration);\n }\n return id;\n }\n\n /** Elimina una notificación / Removes a notification */\n remove(id: string): void {\n this.notifications.update((list) => list.filter((n) => n.id !== id));\n }\n\n /** Marca todas como leídas / Marks all as read */\n markAllRead(): void {\n this.notifications.update((list) => list.map((n) => ({ ...n, read: true })));\n }\n\n /** Elimina todas / Clears all */\n clearAll(): void {\n this.notifications.set([]);\n }\n}\n\nlet _panelSeq = 0;\n\n/**\n * NeuralUI NotificationCenter Component\n *\n * Icono de campana con badge de no leídos y panel de notificaciones\n * deslizante. Consume NeuNotificationService.\n *\n * Uso:\n * <neu-notification-center />\n */\n@Component({\n selector: 'neu-notification-center',\n imports: [],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'neu-nc',\n '[attr.aria-label]': '\"Centro de notificaciones\"',\n },\n template: `\n <!-- Bell button -->\n <button\n type=\"button\"\n class=\"neu-nc__bell\"\n [attr.aria-expanded]=\"_isOpen()\"\n [attr.aria-controls]=\"_panelId\"\n [attr.aria-label]=\"'Notificaciones. ' + _svc.unreadCount() + ' sin leer'\"\n (click)=\"_toggle()\"\n >\n <span class=\"neu-nc__bell-icon\" aria-hidden=\"true\">🔔</span>\n @if (_svc.unreadCount() > 0) {\n <span class=\"neu-nc__badge\" aria-hidden=\"true\">{{\n _svc.unreadCount() > 99 ? '99+' : _svc.unreadCount()\n }}</span>\n }\n </button>\n\n <!-- Panel -->\n @if (_isOpen()) {\n <div\n class=\"neu-nc__panel\"\n [id]=\"_panelId\"\n role=\"dialog\"\n aria-modal=\"false\"\n aria-label=\"Notificaciones\"\n >\n <div class=\"neu-nc__panel-header\">\n <span class=\"neu-nc__panel-title\">Notificaciones</span>\n <div class=\"neu-nc__panel-actions\">\n @if (_svc.unreadCount() > 0) {\n <button type=\"button\" class=\"neu-nc__action-btn\" (click)=\"_svc.markAllRead()\">\n Leer todo\n </button>\n }\n @if (_svc.notifications().length > 0) {\n <button type=\"button\" class=\"neu-nc__action-btn\" (click)=\"_svc.clearAll()\">\n Limpiar\n </button>\n }\n </div>\n </div>\n\n <div class=\"neu-nc__list\" role=\"list\">\n @if (!_svc.notifications().length) {\n <div class=\"neu-nc__empty\" role=\"status\">No hay notificaciones</div>\n }\n @for (n of _svc.notifications(); track n.id) {\n <div\n class=\"neu-nc__item\"\n role=\"listitem\"\n [class.neu-nc__item--unread]=\"!n.read\"\n [class]=\"'neu-nc__item--' + n.type\"\n >\n <span class=\"neu-nc__item-icon\" aria-hidden=\"true\">{{ n.icon }}</span>\n <div class=\"neu-nc__item-body\">\n @if (n.title) {\n <p class=\"neu-nc__item-title\">{{ n.title }}</p>\n }\n <p class=\"neu-nc__item-msg\">{{ n.message }}</p>\n <time class=\"neu-nc__item-time\" [dateTime]=\"n.timestamp.toISOString()\">\n {{ _relativeTime(n.timestamp) }}\n </time>\n </div>\n <button\n type=\"button\"\n class=\"neu-nc__item-close\"\n [attr.aria-label]=\"'Cerrar notificación'\"\n (click)=\"_svc.remove(n.id)\"\n >\n ×\n </button>\n </div>\n }\n </div>\n </div>\n }\n `,\n styleUrl: './neu-notification-center.component.scss',\n})\nexport class NeuNotificationCenterComponent {\n readonly _svc = inject(NeuNotificationService);\n readonly _isOpen = signal(false);\n readonly _panelId = `neu-nc-panel-${++_panelSeq}`;\n\n _toggle(): void {\n const opening = !this._isOpen();\n this._isOpen.set(opening);\n if (opening) {\n // Mark all as read when panel opens\n setTimeout(() => this._svc.markAllRead(), 500);\n }\n }\n\n _relativeTime(date: Date): string {\n const diff = Date.now() - date.getTime();\n const mins = Math.floor(diff / 60000);\n if (mins < 1) return 'Ahora';\n if (mins < 60) return `Hace ${mins} min`;\n const hours = Math.floor(mins / 60);\n if (hours < 24) return `Hace ${hours}h`;\n return `Hace ${Math.floor(hours / 24)}d`;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"neural-ui-core-notification-center.mjs","sources":["../../../../projects/ui-core/notification-center/neu-notification-center.component.ts","../../../../projects/ui-core/notification-center/neural-ui-core-notification-center.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n Injectable,\n OnDestroy,\n ViewEncapsulation,\n computed,\n inject,\n signal,\n} from '@angular/core';\nimport { ConnectedPosition, Overlay, OverlayModule } from '@angular/cdk/overlay';\n\nexport type NeuNotificationType = 'info' | 'success' | 'warning' | 'error';\n\nexport interface NeuNotification {\n id: string;\n type: NeuNotificationType;\n title?: string;\n message: string;\n /** Auto-dismiss duration in ms (0 = persistent) */\n duration?: number;\n /** Icon text / emoji */\n icon?: string;\n timestamp: Date;\n read: boolean;\n}\n\nexport interface NeuNotificationOptions extends Omit<\n NeuNotification,\n 'id' | 'timestamp' | 'read'\n> {}\n\nconst DEFAULT_ICONS: Record<NeuNotificationType, string> = {\n info: 'ℹ️',\n success: '✅',\n warning: '⚠️',\n error: '❌',\n};\n\nlet _idSeq = 0;\n\n/**\n * NeuralUI NotificationService\n *\n * Servicio inyectable que gestiona la cola de notificaciones.\n *\n * Uso:\n * inject(NeuNotificationService).push({ type: 'success', message: '¡Guardado!' });\n */\n@Injectable({ providedIn: 'root' })\nexport class NeuNotificationService {\n readonly notifications = signal<NeuNotification[]>([]);\n\n readonly unreadCount = computed(() => this.notifications().filter((n) => !n.read).length);\n\n /** Agrega una notificación / Adds a notification */\n push(opts: Partial<NeuNotificationOptions> & Pick<NeuNotificationOptions, 'message'>): string {\n const id = `neu-notif-${++_idSeq}`;\n const n: NeuNotification = {\n id,\n type: opts.type ?? 'info',\n title: opts.title,\n message: opts.message,\n icon: opts.icon ?? DEFAULT_ICONS[opts.type ?? 'info'],\n duration: opts.duration ?? 5000,\n timestamp: new Date(),\n read: false,\n };\n this.notifications.update((list) => [n, ...list]);\n\n if (n.duration && n.duration > 0) {\n setTimeout(() => this.remove(id), n.duration);\n }\n return id;\n }\n\n /** Elimina una notificación / Removes a notification */\n remove(id: string): void {\n this.notifications.update((list) => list.filter((n) => n.id !== id));\n }\n\n /** Marca todas como leídas / Marks all as read */\n markAllRead(): void {\n this.notifications.update((list) => list.map((n) => ({ ...n, read: true })));\n }\n\n /** Elimina todas / Clears all */\n clearAll(): void {\n this.notifications.set([]);\n }\n}\n\nlet _panelSeq = 0;\n\n/**\n * NeuralUI NotificationCenter Component\n *\n * Icono de campana con badge de no leídos y panel de notificaciones\n * deslizante. Consume NeuNotificationService.\n *\n * Uso:\n * <neu-notification-center />\n */\n@Component({\n selector: 'neu-notification-center',\n imports: [OverlayModule],\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'neu-nc',\n '[attr.aria-label]': '\"Centro de notificaciones\"',\n },\n template: `\n <!-- Bell button -->\n <button\n cdkOverlayOrigin\n #notificationOrigin=\"cdkOverlayOrigin\"\n type=\"button\"\n class=\"neu-nc__bell\"\n [attr.aria-expanded]=\"_isOpen()\"\n [attr.aria-controls]=\"_panelId\"\n [attr.aria-label]=\"'Notificaciones. ' + _svc.unreadCount() + ' sin leer'\"\n (click)=\"_toggle()\"\n >\n <span class=\"neu-nc__bell-icon\" aria-hidden=\"true\">🔔</span>\n @if (_svc.unreadCount() > 0) {\n <span class=\"neu-nc__badge\" aria-hidden=\"true\">{{\n _svc.unreadCount() > 99 ? '99+' : _svc.unreadCount()\n }}</span>\n }\n </button>\n\n <!-- Panel -->\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"notificationOrigin\"\n [cdkConnectedOverlayOpen]=\"_isOpen()\"\n [cdkConnectedOverlayPositions]=\"overlayPositions\"\n [cdkConnectedOverlayScrollStrategy]=\"overlayScrollStrategy\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n [cdkConnectedOverlayBackdropClass]=\"'cdk-overlay-transparent-backdrop'\"\n [cdkConnectedOverlayPush]=\"true\"\n [cdkConnectedOverlayViewportMargin]=\"_viewportMargin\"\n (backdropClick)=\"_isOpen.set(false)\"\n (detach)=\"_isOpen.set(false)\"\n >\n <div\n class=\"neu-nc__panel\"\n [id]=\"_panelId\"\n role=\"dialog\"\n aria-modal=\"false\"\n aria-label=\"Notificaciones\"\n >\n <div class=\"neu-nc__panel-header\">\n <span class=\"neu-nc__panel-title\">Notificaciones</span>\n <div class=\"neu-nc__panel-actions\">\n @if (_svc.unreadCount() > 0) {\n <button type=\"button\" class=\"neu-nc__action-btn\" (click)=\"_svc.markAllRead()\">\n Leer todo\n </button>\n }\n @if (_svc.notifications().length > 0) {\n <button type=\"button\" class=\"neu-nc__action-btn\" (click)=\"_svc.clearAll()\">\n Limpiar\n </button>\n }\n </div>\n </div>\n\n <div class=\"neu-nc__list\" role=\"list\">\n @if (!_svc.notifications().length) {\n <div class=\"neu-nc__empty\" role=\"status\">No hay notificaciones</div>\n }\n @for (n of _svc.notifications(); track n.id) {\n <div\n class=\"neu-nc__item\"\n role=\"listitem\"\n [class.neu-nc__item--unread]=\"!n.read\"\n [class]=\"'neu-nc__item--' + n.type\"\n >\n <span class=\"neu-nc__item-icon\" aria-hidden=\"true\">{{ n.icon }}</span>\n <div class=\"neu-nc__item-body\">\n @if (n.title) {\n <p class=\"neu-nc__item-title\">{{ n.title }}</p>\n }\n <p class=\"neu-nc__item-msg\">{{ n.message }}</p>\n <time class=\"neu-nc__item-time\" [dateTime]=\"n.timestamp.toISOString()\">\n {{ _relativeTime(n.timestamp) }}\n </time>\n </div>\n <button\n type=\"button\"\n class=\"neu-nc__item-close\"\n [attr.aria-label]=\"'Cerrar notificación'\"\n (click)=\"_svc.remove(n.id)\"\n >\n ×\n </button>\n </div>\n }\n </div>\n </div>\n </ng-template>\n `,\n styleUrl: './neu-notification-center.component.scss',\n})\nexport class NeuNotificationCenterComponent {\n readonly _svc = inject(NeuNotificationService);\n private readonly overlay = inject(Overlay);\n readonly _isOpen = signal(false);\n readonly _panelId = `neu-nc-panel-${++_panelSeq}`;\n readonly _viewportMargin = 16;\n readonly overlayPositions: ConnectedPosition[] = [\n {\n originX: 'end',\n originY: 'bottom',\n overlayX: 'end',\n overlayY: 'top',\n offsetY: 8,\n },\n {\n originX: 'end',\n originY: 'top',\n overlayX: 'end',\n overlayY: 'bottom',\n offsetY: -8,\n },\n {\n originX: 'start',\n originY: 'bottom',\n overlayX: 'start',\n overlayY: 'top',\n offsetY: 8,\n },\n ];\n readonly overlayScrollStrategy = this.overlay.scrollStrategies.reposition();\n\n _toggle(): void {\n const opening = !this._isOpen();\n this._isOpen.set(opening);\n if (opening) {\n // Mark all as read when panel opens\n setTimeout(() => this._svc.markAllRead(), 500);\n }\n }\n\n _relativeTime(date: Date): string {\n const diff = Date.now() - date.getTime();\n const mins = Math.floor(diff / 60000);\n if (mins < 1) return 'Ahora';\n if (mins < 60) return `Hace ${mins} min`;\n const hours = Math.floor(mins / 60);\n if (hours < 24) return `Hace ${hours}h`;\n return `Hace ${Math.floor(hours / 24)}d`;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { inject, TemplateRef, Directive, ElementRef, viewChild, effect, untracked, contentChild, input, output, signal, computed, forwardRef, ChangeDetectionStrategy, ViewEncapsulation, Component } from '@angular/core';
|
|
3
3
|
import { NeuUrlStateService } from '@neural-ui/core/url-state';
|
|
4
|
-
import { NgTemplateOutlet } from '@angular/common';
|
|
5
|
-
import * as i1 from '@angular/cdk/
|
|
4
|
+
import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
|
|
5
|
+
import * as i1 from '@angular/cdk/overlay';
|
|
6
|
+
import { Overlay, OverlayModule } from '@angular/cdk/overlay';
|
|
6
7
|
import { CdkVirtualScrollViewport, ScrollingModule } from '@angular/cdk/scrolling';
|
|
7
8
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
8
9
|
|
|
@@ -68,8 +69,9 @@ let _neuSelectIdSeq = 0;
|
|
|
68
69
|
*/
|
|
69
70
|
class NeuSelectComponent {
|
|
70
71
|
elementRef = inject(ElementRef);
|
|
72
|
+
_document = inject(DOCUMENT);
|
|
73
|
+
_overlay = inject(Overlay);
|
|
71
74
|
_urlState = inject(NeuUrlStateService);
|
|
72
|
-
_mobileViewportMax = 768;
|
|
73
75
|
_viewportMargin = 16;
|
|
74
76
|
_panelMaxHeight = 240;
|
|
75
77
|
_urlParamSignals = new Map();
|
|
@@ -149,6 +151,37 @@ class NeuSelectComponent {
|
|
|
149
151
|
_value = signal(null, ...(ngDevMode ? [{ debugName: "_value" }] : /* istanbul ignore next */ []));
|
|
150
152
|
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
151
153
|
searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : /* istanbul ignore next */ []));
|
|
154
|
+
overlayPositions = [
|
|
155
|
+
{
|
|
156
|
+
originX: 'start',
|
|
157
|
+
originY: 'bottom',
|
|
158
|
+
overlayX: 'start',
|
|
159
|
+
overlayY: 'top',
|
|
160
|
+
offsetY: 6,
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
originX: 'start',
|
|
164
|
+
originY: 'top',
|
|
165
|
+
overlayX: 'start',
|
|
166
|
+
overlayY: 'bottom',
|
|
167
|
+
offsetY: -6,
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
originX: 'end',
|
|
171
|
+
originY: 'bottom',
|
|
172
|
+
overlayX: 'end',
|
|
173
|
+
overlayY: 'top',
|
|
174
|
+
offsetY: 6,
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
originX: 'end',
|
|
178
|
+
originY: 'top',
|
|
179
|
+
overlayX: 'end',
|
|
180
|
+
overlayY: 'bottom',
|
|
181
|
+
offsetY: -6,
|
|
182
|
+
},
|
|
183
|
+
];
|
|
184
|
+
overlayScrollStrategy = this._overlay.scrollStrategies.reposition();
|
|
152
185
|
panelPosition = signal({
|
|
153
186
|
position: null,
|
|
154
187
|
top: null,
|
|
@@ -302,7 +335,10 @@ class NeuSelectComponent {
|
|
|
302
335
|
this.close();
|
|
303
336
|
}
|
|
304
337
|
onDocumentClick(event) {
|
|
305
|
-
|
|
338
|
+
const target = event.target;
|
|
339
|
+
const isInsideHost = this.elementRef.nativeElement.contains(target);
|
|
340
|
+
const isInsidePanel = !!target?.closest('.neu-select__panel');
|
|
341
|
+
if (!isInsideHost && !isInsidePanel) {
|
|
306
342
|
this.close();
|
|
307
343
|
}
|
|
308
344
|
}
|
|
@@ -324,28 +360,16 @@ class NeuSelectComponent {
|
|
|
324
360
|
const viewportWidth = window.innerWidth;
|
|
325
361
|
const viewportHeight = window.innerHeight;
|
|
326
362
|
const gap = 6;
|
|
327
|
-
const configuratorControls = trigger.closest('.demo-configurator__controls');
|
|
328
|
-
const controlsDisplay = configuratorControls
|
|
329
|
-
? window.getComputedStyle(configuratorControls).display
|
|
330
|
-
: null;
|
|
331
|
-
const boundaryRect = controlsDisplay === 'grid' ? null : configuratorControls?.getBoundingClientRect();
|
|
332
|
-
const boundaryTop = boundaryRect
|
|
333
|
-
? Math.max(boundaryRect.top, this._viewportMargin)
|
|
334
|
-
: this._viewportMargin;
|
|
335
|
-
const boundaryBottom = boundaryRect
|
|
336
|
-
? Math.min(boundaryRect.bottom, viewportHeight - this._viewportMargin)
|
|
337
|
-
: viewportHeight - this._viewportMargin;
|
|
338
363
|
const width = Math.min(triggerRect.width, viewportWidth - this._viewportMargin * 2);
|
|
339
|
-
const
|
|
340
|
-
const
|
|
341
|
-
const availableAbove = Math.max(0, triggerRect.top - boundaryTop - gap);
|
|
364
|
+
const availableBelow = Math.max(0, viewportHeight - this._viewportMargin - triggerRect.bottom - gap);
|
|
365
|
+
const availableAbove = Math.max(0, triggerRect.top - this._viewportMargin - gap);
|
|
342
366
|
const openAbove = availableAbove > availableBelow && availableAbove >= 140;
|
|
343
367
|
const maxHeight = Math.max(140, openAbove ? availableAbove : availableBelow);
|
|
344
368
|
this.panelPosition.set({
|
|
345
369
|
position: 'fixed',
|
|
346
370
|
top: openAbove ? 'auto' : `${triggerRect.bottom + gap}px`,
|
|
347
371
|
bottom: openAbove ? `${viewportHeight - triggerRect.top + gap}px` : 'auto',
|
|
348
|
-
left: `${left}px`,
|
|
372
|
+
left: `${Math.min(Math.max(triggerRect.left, this._viewportMargin), viewportWidth - width - this._viewportMargin)}px`,
|
|
349
373
|
width: `${width}px`,
|
|
350
374
|
maxHeight: `${maxHeight}px`,
|
|
351
375
|
});
|
|
@@ -354,6 +378,9 @@ class NeuSelectComponent {
|
|
|
354
378
|
requestAnimationFrame(() => this._viewport()?.checkViewportSize());
|
|
355
379
|
}
|
|
356
380
|
}
|
|
381
|
+
onOverlayPositionChange(event) {
|
|
382
|
+
this.isPanelAbove.set(event.connectionPair.overlayY === 'bottom');
|
|
383
|
+
}
|
|
357
384
|
focusFirstOption() {
|
|
358
385
|
const firstEnabled = this.filteredOptions().find((option) => !option.disabled);
|
|
359
386
|
if (!firstEnabled) {
|
|
@@ -369,12 +396,13 @@ class NeuSelectComponent {
|
|
|
369
396
|
this._viewport()?.checkViewportSize();
|
|
370
397
|
}
|
|
371
398
|
requestAnimationFrame(() => {
|
|
372
|
-
const optionElement = this.elementRef.nativeElement.querySelector(`#neu-select-opt-${value}`);
|
|
399
|
+
const optionElement = this.elementRef.nativeElement.querySelector(`#neu-select-opt-${value}`) ?? this._document.getElementById(`neu-select-opt-${value}`);
|
|
373
400
|
optionElement?.focus();
|
|
374
401
|
});
|
|
375
402
|
return;
|
|
376
403
|
}
|
|
377
|
-
const optionElement = this.elementRef.nativeElement.querySelector(`#neu-select-opt-${value}`)
|
|
404
|
+
const optionElement = this.elementRef.nativeElement.querySelector(`#neu-select-opt-${value}`) ??
|
|
405
|
+
this._document.getElementById(`neu-select-opt-${value}`);
|
|
378
406
|
optionElement?.focus();
|
|
379
407
|
}
|
|
380
408
|
resetPanelPosition() {
|
|
@@ -389,7 +417,7 @@ class NeuSelectComponent {
|
|
|
389
417
|
this.isPanelAbove.set(false);
|
|
390
418
|
}
|
|
391
419
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
392
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: NeuSelectComponent, isStandalone: true, selector: "neu-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", 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 }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollVisibleItems: { classPropertyName: "virtualScrollVisibleItems", publicName: "virtualScrollVisibleItems", isSignal: true, isRequired: false, transformFunction: null }, noResultsMessage: { classPropertyName: "noResultsMessage", publicName: "noResultsMessage", isSignal: true, isRequired: false, transformFunction: null }, clearAriaLabel: { classPropertyName: "clearAriaLabel", publicName: "clearAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, urlParam: { classPropertyName: "urlParam", publicName: "urlParam", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, host: { listeners: { "
|
|
420
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: NeuSelectComponent, isStandalone: true, selector: "neu-select", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", 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 }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, virtualScroll: { classPropertyName: "virtualScroll", publicName: "virtualScroll", isSignal: true, isRequired: false, transformFunction: null }, virtualScrollVisibleItems: { classPropertyName: "virtualScrollVisibleItems", publicName: "virtualScrollVisibleItems", isSignal: true, isRequired: false, transformFunction: null }, noResultsMessage: { classPropertyName: "noResultsMessage", publicName: "noResultsMessage", isSignal: true, isRequired: false, transformFunction: null }, clearAriaLabel: { classPropertyName: "clearAriaLabel", publicName: "clearAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, urlParam: { classPropertyName: "urlParam", publicName: "urlParam", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, host: { listeners: { "keydown.escape": "close()", "window:resize": "onWindowResize()" } }, providers: [
|
|
393
421
|
{
|
|
394
422
|
provide: NG_VALUE_ACCESSOR,
|
|
395
423
|
useExisting: forwardRef(() => NeuSelectComponent),
|
|
@@ -416,6 +444,8 @@ class NeuSelectComponent {
|
|
|
416
444
|
>
|
|
417
445
|
<!-- Trigger ------>
|
|
418
446
|
<div
|
|
447
|
+
cdkOverlayOrigin
|
|
448
|
+
#selectOrigin="cdkOverlayOrigin"
|
|
419
449
|
class="neu-select__trigger"
|
|
420
450
|
[id]="_triggerId"
|
|
421
451
|
[attr.tabindex]="isDisabledFinal() ? '-1' : '0'"
|
|
@@ -493,7 +523,20 @@ class NeuSelectComponent {
|
|
|
493
523
|
</div>
|
|
494
524
|
|
|
495
525
|
<!-- Panel ------>
|
|
496
|
-
|
|
526
|
+
<ng-template
|
|
527
|
+
cdkConnectedOverlay
|
|
528
|
+
[cdkConnectedOverlayOrigin]="selectOrigin"
|
|
529
|
+
[cdkConnectedOverlayOpen]="isOpen()"
|
|
530
|
+
[cdkConnectedOverlayPositions]="overlayPositions"
|
|
531
|
+
[cdkConnectedOverlayScrollStrategy]="overlayScrollStrategy"
|
|
532
|
+
[cdkConnectedOverlayHasBackdrop]="true"
|
|
533
|
+
[cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'"
|
|
534
|
+
[cdkConnectedOverlayPush]="true"
|
|
535
|
+
[cdkConnectedOverlayViewportMargin]="_viewportMargin"
|
|
536
|
+
(backdropClick)="close()"
|
|
537
|
+
(detach)="close()"
|
|
538
|
+
(positionChange)="onOverlayPositionChange($event)"
|
|
539
|
+
>
|
|
497
540
|
<div
|
|
498
541
|
class="neu-select__panel"
|
|
499
542
|
[class.neu-select__panel--above]="isPanelAbove()"
|
|
@@ -501,10 +544,6 @@ class NeuSelectComponent {
|
|
|
501
544
|
role="listbox"
|
|
502
545
|
[id]="_panelId"
|
|
503
546
|
[attr.aria-label]="label()"
|
|
504
|
-
[style.position]="panelPosition().position"
|
|
505
|
-
[style.top]="panelPosition().top"
|
|
506
|
-
[style.bottom]="panelPosition().bottom"
|
|
507
|
-
[style.left]="panelPosition().left"
|
|
508
547
|
[style.width]="panelPosition().width"
|
|
509
548
|
[style.max-height]="panelPosition().maxHeight"
|
|
510
549
|
>
|
|
@@ -613,7 +652,7 @@ class NeuSelectComponent {
|
|
|
613
652
|
<div class="neu-select__empty">{{ noResultsMessage() }}</div>
|
|
614
653
|
}
|
|
615
654
|
</div>
|
|
616
|
-
|
|
655
|
+
</ng-template>
|
|
617
656
|
<div class="neu-select__sr-status" aria-live="polite" aria-atomic="true">
|
|
618
657
|
{{ resultsAnnouncement() }}
|
|
619
658
|
</div>
|
|
@@ -627,21 +666,19 @@ class NeuSelectComponent {
|
|
|
627
666
|
} @else if (hint()) {
|
|
628
667
|
<p class="neu-select__hint" [id]="_triggerId + '-hint'">{{ hint() }}</p>
|
|
629
668
|
}
|
|
630
|
-
`, isInline: true, styles: [".neu-select{position:relative;display:block}.neu-select--disabled{opacity:.6;pointer-events:none}.neu-select--sm .neu-select__trigger{height:36px;font-size:var(--neu-text-sm)}.neu-select--lg .neu-select__trigger{height:56px}.neu-select__trigger{display:flex;align-items:center;width:100%;height:48px;padding:0 var(--neu-space-3);padding-right:36px;background:var(--neu-surface);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);font-family:var(--neu-font-sans);font-size:var(--neu-text-base);color:var(--neu-text);cursor:pointer;text-align:left;outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition);position:relative}.neu-select__trigger:hover:not([aria-disabled=true]){border-color:var(--neu-border-hover)}.neu-select__trigger[aria-disabled=true]{cursor:not-allowed;background:var(--neu-surface-2)}.neu-select__trigger:focus-visible{border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f}.neu-select--open .neu-select__trigger{border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f;border-bottom-left-radius:0;border-bottom-right-radius:0}.neu-select--open-above .neu-select__trigger{border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:var(--neu-radius);border-bottom-right-radius:var(--neu-radius)}.neu-select--error .neu-select__trigger{border-color:var(--neu-error)}.neu-select--error .neu-select__trigger:focus-visible{box-shadow:0 0 0 3px #ef44441f}.neu-select__label{position:absolute;left:var(--neu-space-3);top:50%;transform:translateY(-50%);font-size:var(--neu-text-base);color:color-mix(in srgb,var(--neu-text) 68%,var(--neu-surface) 32%);pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - var(--neu-space-6));transition:top var(--neu-transition),font-size var(--neu-transition),color var(--neu-transition),transform var(--neu-transition),padding var(--neu-transition),background var(--neu-transition)}.neu-select--open .neu-select__label,.neu-select--has-value .neu-select__label{top:0;transform:translateY(-50%);font-size:12px;font-weight:600;letter-spacing:.01em;background:var(--neu-surface);padding:0 4px;left:calc(var(--neu-space-3) - 4px)}.neu-select--open .neu-select__label{color:var(--neu-primary)}.neu-select--error .neu-select__label{color:var(--neu-error)}.neu-select--disabled .neu-select__label{background:var(--neu-surface-2)}.neu-select__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.neu-select--no-float .neu-select__value{padding-top:0}.neu-select__placeholder{color:color-mix(in srgb,var(--neu-text) 62%,var(--neu-surface) 38%)}.neu-select:not(.neu-select--no-float):not(.neu-select--open) .neu-select__placeholder{visibility:hidden}.neu-select__chevron{position:absolute;right:var(--neu-space-3);top:50%;transform:translateY(-50%);width:18px;height:18px;color:var(--neu-text-muted);flex-shrink:0;transition:transform var(--neu-transition)}.neu-select--open .neu-select__chevron{transform:translateY(-50%) rotate(180deg);color:var(--neu-primary)}.neu-select__clear{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-right:2px;padding:0;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);flex-shrink:0;transition:color var(--neu-transition),background var(--neu-transition)}.neu-select__clear svg{width:14px;height:14px}.neu-select__clear:hover{color:var(--neu-text);background:var(--neu-surface-3)}.neu-select__clear:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-select__panel{position:
|
|
669
|
+
`, isInline: true, styles: [".neu-select{position:relative;display:block}.neu-select--disabled{opacity:.6;pointer-events:none}.neu-select--sm .neu-select__trigger{height:36px;font-size:var(--neu-text-sm)}.neu-select--lg .neu-select__trigger{height:56px}.neu-select__trigger{display:flex;align-items:center;width:100%;height:48px;padding:0 var(--neu-space-3);padding-right:36px;background:var(--neu-surface);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);font-family:var(--neu-font-sans);font-size:var(--neu-text-base);color:var(--neu-text);cursor:pointer;text-align:left;outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition);position:relative}.neu-select__trigger:hover:not([aria-disabled=true]){border-color:var(--neu-border-hover)}.neu-select__trigger[aria-disabled=true]{cursor:not-allowed;background:var(--neu-surface-2)}.neu-select__trigger:focus-visible{border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f}.neu-select--open .neu-select__trigger{border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f;border-bottom-left-radius:0;border-bottom-right-radius:0}.neu-select--open-above .neu-select__trigger{border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:var(--neu-radius);border-bottom-right-radius:var(--neu-radius)}.neu-select--error .neu-select__trigger{border-color:var(--neu-error)}.neu-select--error .neu-select__trigger:focus-visible{box-shadow:0 0 0 3px #ef44441f}.neu-select__label{position:absolute;left:var(--neu-space-3);top:50%;transform:translateY(-50%);font-size:var(--neu-text-base);color:color-mix(in srgb,var(--neu-text) 68%,var(--neu-surface) 32%);pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - var(--neu-space-6));transition:top var(--neu-transition),font-size var(--neu-transition),color var(--neu-transition),transform var(--neu-transition),padding var(--neu-transition),background var(--neu-transition)}.neu-select--open .neu-select__label,.neu-select--has-value .neu-select__label{top:0;transform:translateY(-50%);font-size:12px;font-weight:600;letter-spacing:.01em;background:var(--neu-surface);padding:0 4px;left:calc(var(--neu-space-3) - 4px)}.neu-select--open .neu-select__label{color:var(--neu-primary)}.neu-select--error .neu-select__label{color:var(--neu-error)}.neu-select--disabled .neu-select__label{background:var(--neu-surface-2)}.neu-select__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.neu-select--no-float .neu-select__value{padding-top:0}.neu-select__placeholder{color:color-mix(in srgb,var(--neu-text) 62%,var(--neu-surface) 38%)}.neu-select:not(.neu-select--no-float):not(.neu-select--open) .neu-select__placeholder{visibility:hidden}.neu-select__chevron{position:absolute;right:var(--neu-space-3);top:50%;transform:translateY(-50%);width:18px;height:18px;color:var(--neu-text-muted);flex-shrink:0;transition:transform var(--neu-transition)}.neu-select--open .neu-select__chevron{transform:translateY(-50%) rotate(180deg);color:var(--neu-primary)}.neu-select__clear{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-right:2px;padding:0;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);flex-shrink:0;transition:color var(--neu-transition),background var(--neu-transition)}.neu-select__clear svg{width:14px;height:14px}.neu-select__clear:hover{color:var(--neu-text);background:var(--neu-surface-3)}.neu-select__clear:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-select__panel{position:relative;z-index:var(--neu-z-dropdown);background:var(--neu-surface);border:1.5px solid var(--neu-primary);border-top:none;border-bottom-left-radius:var(--neu-radius);border-bottom-right-radius:var(--neu-radius);box-shadow:var(--neu-shadow-lg);max-height:240px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--neu-surface-3) transparent;animation:neu-select-open .15s ease forwards}.neu-select__panel::-webkit-scrollbar{width:4px}.neu-select__panel::-webkit-scrollbar-thumb{background:var(--neu-surface-3);border-radius:99px}.neu-select__panel--above{border-top:1.5px solid var(--neu-primary);border-bottom:none;border-top-left-radius:var(--neu-radius);border-top-right-radius:var(--neu-radius);border-bottom-left-radius:0;border-bottom-right-radius:0}.neu-select__panel--virtual{overflow:visible}.neu-select__viewport{width:100%}@media(max-width:600px){.neu-select__panel{left:auto;right:0;width:min(max(100%,220px),100vw - 2rem);max-width:calc(100vw - 2rem)}}@keyframes neu-select-open{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-select__option{display:flex;align-items:center;gap:var(--neu-space-2);padding:var(--neu-space-3) var(--neu-space-4);min-height:var(--neu-select-option-height, 44px);box-sizing:border-box;font-size:var(--neu-text-sm);color:var(--neu-text);cursor:pointer;transition:background-color var(--neu-transition)}.neu-select__option:hover:not(.neu-select__option--disabled){background:var(--neu-primary-50);color:var(--neu-primary)}.neu-select__option--selected{color:var(--neu-primary);font-weight:600;background:var(--neu-primary-50)}.neu-select__option--disabled{opacity:.4;cursor:not-allowed}.neu-select__check{width:14px;height:14px;flex-shrink:0}.neu-select__error{margin-top:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-error-text);font-family:var(--neu-font-sans)}.neu-select__hint{margin-top:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-text-muted);font-family:var(--neu-font-sans)}.neu-select__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-select__static-label{display:block;font-size:var(--neu-text-sm);font-weight:500;color:var(--neu-text-muted);margin-bottom:var(--neu-space-2)}.neu-select__search{padding:var(--neu-space-2);border-bottom:1px solid var(--neu-border);position:sticky;top:0;background:var(--neu-surface);z-index:1}.neu-select__search-input{width:100%;height:34px;padding:0 var(--neu-space-3);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius-sm);background:var(--neu-bg);font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);color:var(--neu-text);outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-select__search-input:focus{border-color:var(--neu-primary);box-shadow:0 0 0 2px #007aff1f}.neu-select__search-input::placeholder{color:var(--neu-text-disabled)}.neu-select__empty{padding:var(--neu-space-4);text-align:center;font-size:var(--neu-text-sm);color:var(--neu-text-disabled);font-family:var(--neu-font-sans)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i1.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i1.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: i1.ɵɵCdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i1.ɵɵCdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i1.ɵɵCdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "ngmodule", type: ScrollingModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
631
670
|
}
|
|
632
671
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: NeuSelectComponent, decorators: [{
|
|
633
672
|
type: Component,
|
|
634
|
-
args: [{ selector: 'neu-select', imports: [NgTemplateOutlet, ScrollingModule], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
673
|
+
args: [{ selector: 'neu-select', imports: [NgTemplateOutlet, OverlayModule, ScrollingModule], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
635
674
|
{
|
|
636
675
|
provide: NG_VALUE_ACCESSOR,
|
|
637
676
|
useExisting: forwardRef(() => NeuSelectComponent),
|
|
638
677
|
multi: true,
|
|
639
678
|
},
|
|
640
679
|
], host: {
|
|
641
|
-
'(document:click)': 'onDocumentClick($event)',
|
|
642
680
|
'(keydown.escape)': 'close()',
|
|
643
681
|
'(window:resize)': 'onWindowResize()',
|
|
644
|
-
'(window:scroll)': 'onWindowScroll()',
|
|
645
682
|
}, template: `
|
|
646
683
|
@if (!floatingLabel() && label()) {
|
|
647
684
|
<label class="neu-select__static-label" [for]="_triggerId" (click)="focusTrigger()">{{
|
|
@@ -663,6 +700,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
663
700
|
>
|
|
664
701
|
<!-- Trigger ------>
|
|
665
702
|
<div
|
|
703
|
+
cdkOverlayOrigin
|
|
704
|
+
#selectOrigin="cdkOverlayOrigin"
|
|
666
705
|
class="neu-select__trigger"
|
|
667
706
|
[id]="_triggerId"
|
|
668
707
|
[attr.tabindex]="isDisabledFinal() ? '-1' : '0'"
|
|
@@ -740,7 +779,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
740
779
|
</div>
|
|
741
780
|
|
|
742
781
|
<!-- Panel ------>
|
|
743
|
-
|
|
782
|
+
<ng-template
|
|
783
|
+
cdkConnectedOverlay
|
|
784
|
+
[cdkConnectedOverlayOrigin]="selectOrigin"
|
|
785
|
+
[cdkConnectedOverlayOpen]="isOpen()"
|
|
786
|
+
[cdkConnectedOverlayPositions]="overlayPositions"
|
|
787
|
+
[cdkConnectedOverlayScrollStrategy]="overlayScrollStrategy"
|
|
788
|
+
[cdkConnectedOverlayHasBackdrop]="true"
|
|
789
|
+
[cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'"
|
|
790
|
+
[cdkConnectedOverlayPush]="true"
|
|
791
|
+
[cdkConnectedOverlayViewportMargin]="_viewportMargin"
|
|
792
|
+
(backdropClick)="close()"
|
|
793
|
+
(detach)="close()"
|
|
794
|
+
(positionChange)="onOverlayPositionChange($event)"
|
|
795
|
+
>
|
|
744
796
|
<div
|
|
745
797
|
class="neu-select__panel"
|
|
746
798
|
[class.neu-select__panel--above]="isPanelAbove()"
|
|
@@ -748,10 +800,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
748
800
|
role="listbox"
|
|
749
801
|
[id]="_panelId"
|
|
750
802
|
[attr.aria-label]="label()"
|
|
751
|
-
[style.position]="panelPosition().position"
|
|
752
|
-
[style.top]="panelPosition().top"
|
|
753
|
-
[style.bottom]="panelPosition().bottom"
|
|
754
|
-
[style.left]="panelPosition().left"
|
|
755
803
|
[style.width]="panelPosition().width"
|
|
756
804
|
[style.max-height]="panelPosition().maxHeight"
|
|
757
805
|
>
|
|
@@ -860,7 +908,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
860
908
|
<div class="neu-select__empty">{{ noResultsMessage() }}</div>
|
|
861
909
|
}
|
|
862
910
|
</div>
|
|
863
|
-
|
|
911
|
+
</ng-template>
|
|
864
912
|
<div class="neu-select__sr-status" aria-live="polite" aria-atomic="true">
|
|
865
913
|
{{ resultsAnnouncement() }}
|
|
866
914
|
</div>
|
|
@@ -874,7 +922,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
874
922
|
} @else if (hint()) {
|
|
875
923
|
<p class="neu-select__hint" [id]="_triggerId + '-hint'">{{ hint() }}</p>
|
|
876
924
|
}
|
|
877
|
-
`, styles: [".neu-select{position:relative;display:block}.neu-select--disabled{opacity:.6;pointer-events:none}.neu-select--sm .neu-select__trigger{height:36px;font-size:var(--neu-text-sm)}.neu-select--lg .neu-select__trigger{height:56px}.neu-select__trigger{display:flex;align-items:center;width:100%;height:48px;padding:0 var(--neu-space-3);padding-right:36px;background:var(--neu-surface);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);font-family:var(--neu-font-sans);font-size:var(--neu-text-base);color:var(--neu-text);cursor:pointer;text-align:left;outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition);position:relative}.neu-select__trigger:hover:not([aria-disabled=true]){border-color:var(--neu-border-hover)}.neu-select__trigger[aria-disabled=true]{cursor:not-allowed;background:var(--neu-surface-2)}.neu-select__trigger:focus-visible{border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f}.neu-select--open .neu-select__trigger{border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f;border-bottom-left-radius:0;border-bottom-right-radius:0}.neu-select--open-above .neu-select__trigger{border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:var(--neu-radius);border-bottom-right-radius:var(--neu-radius)}.neu-select--error .neu-select__trigger{border-color:var(--neu-error)}.neu-select--error .neu-select__trigger:focus-visible{box-shadow:0 0 0 3px #ef44441f}.neu-select__label{position:absolute;left:var(--neu-space-3);top:50%;transform:translateY(-50%);font-size:var(--neu-text-base);color:color-mix(in srgb,var(--neu-text) 68%,var(--neu-surface) 32%);pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - var(--neu-space-6));transition:top var(--neu-transition),font-size var(--neu-transition),color var(--neu-transition),transform var(--neu-transition),padding var(--neu-transition),background var(--neu-transition)}.neu-select--open .neu-select__label,.neu-select--has-value .neu-select__label{top:0;transform:translateY(-50%);font-size:12px;font-weight:600;letter-spacing:.01em;background:var(--neu-surface);padding:0 4px;left:calc(var(--neu-space-3) - 4px)}.neu-select--open .neu-select__label{color:var(--neu-primary)}.neu-select--error .neu-select__label{color:var(--neu-error)}.neu-select--disabled .neu-select__label{background:var(--neu-surface-2)}.neu-select__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.neu-select--no-float .neu-select__value{padding-top:0}.neu-select__placeholder{color:color-mix(in srgb,var(--neu-text) 62%,var(--neu-surface) 38%)}.neu-select:not(.neu-select--no-float):not(.neu-select--open) .neu-select__placeholder{visibility:hidden}.neu-select__chevron{position:absolute;right:var(--neu-space-3);top:50%;transform:translateY(-50%);width:18px;height:18px;color:var(--neu-text-muted);flex-shrink:0;transition:transform var(--neu-transition)}.neu-select--open .neu-select__chevron{transform:translateY(-50%) rotate(180deg);color:var(--neu-primary)}.neu-select__clear{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-right:2px;padding:0;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);flex-shrink:0;transition:color var(--neu-transition),background var(--neu-transition)}.neu-select__clear svg{width:14px;height:14px}.neu-select__clear:hover{color:var(--neu-text);background:var(--neu-surface-3)}.neu-select__clear:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-select__panel{position:
|
|
925
|
+
`, styles: [".neu-select{position:relative;display:block}.neu-select--disabled{opacity:.6;pointer-events:none}.neu-select--sm .neu-select__trigger{height:36px;font-size:var(--neu-text-sm)}.neu-select--lg .neu-select__trigger{height:56px}.neu-select__trigger{display:flex;align-items:center;width:100%;height:48px;padding:0 var(--neu-space-3);padding-right:36px;background:var(--neu-surface);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius);font-family:var(--neu-font-sans);font-size:var(--neu-text-base);color:var(--neu-text);cursor:pointer;text-align:left;outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition);position:relative}.neu-select__trigger:hover:not([aria-disabled=true]){border-color:var(--neu-border-hover)}.neu-select__trigger[aria-disabled=true]{cursor:not-allowed;background:var(--neu-surface-2)}.neu-select__trigger:focus-visible{border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f}.neu-select--open .neu-select__trigger{border-color:var(--neu-primary);box-shadow:0 0 0 3px #007aff1f;border-bottom-left-radius:0;border-bottom-right-radius:0}.neu-select--open-above .neu-select__trigger{border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:var(--neu-radius);border-bottom-right-radius:var(--neu-radius)}.neu-select--error .neu-select__trigger{border-color:var(--neu-error)}.neu-select--error .neu-select__trigger:focus-visible{box-shadow:0 0 0 3px #ef44441f}.neu-select__label{position:absolute;left:var(--neu-space-3);top:50%;transform:translateY(-50%);font-size:var(--neu-text-base);color:color-mix(in srgb,var(--neu-text) 68%,var(--neu-surface) 32%);pointer-events:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:calc(100% - var(--neu-space-6));transition:top var(--neu-transition),font-size var(--neu-transition),color var(--neu-transition),transform var(--neu-transition),padding var(--neu-transition),background var(--neu-transition)}.neu-select--open .neu-select__label,.neu-select--has-value .neu-select__label{top:0;transform:translateY(-50%);font-size:12px;font-weight:600;letter-spacing:.01em;background:var(--neu-surface);padding:0 4px;left:calc(var(--neu-space-3) - 4px)}.neu-select--open .neu-select__label{color:var(--neu-primary)}.neu-select--error .neu-select__label{color:var(--neu-error)}.neu-select--disabled .neu-select__label{background:var(--neu-surface-2)}.neu-select__value{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.neu-select--no-float .neu-select__value{padding-top:0}.neu-select__placeholder{color:color-mix(in srgb,var(--neu-text) 62%,var(--neu-surface) 38%)}.neu-select:not(.neu-select--no-float):not(.neu-select--open) .neu-select__placeholder{visibility:hidden}.neu-select__chevron{position:absolute;right:var(--neu-space-3);top:50%;transform:translateY(-50%);width:18px;height:18px;color:var(--neu-text-muted);flex-shrink:0;transition:transform var(--neu-transition)}.neu-select--open .neu-select__chevron{transform:translateY(-50%) rotate(180deg);color:var(--neu-primary)}.neu-select__clear{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-right:2px;padding:0;border:none;background:transparent;color:var(--neu-text-muted);cursor:pointer;border-radius:var(--neu-radius-sm);flex-shrink:0;transition:color var(--neu-transition),background var(--neu-transition)}.neu-select__clear svg{width:14px;height:14px}.neu-select__clear:hover{color:var(--neu-text);background:var(--neu-surface-3)}.neu-select__clear:focus-visible{outline:2px solid var(--neu-primary);outline-offset:2px}.neu-select__panel{position:relative;z-index:var(--neu-z-dropdown);background:var(--neu-surface);border:1.5px solid var(--neu-primary);border-top:none;border-bottom-left-radius:var(--neu-radius);border-bottom-right-radius:var(--neu-radius);box-shadow:var(--neu-shadow-lg);max-height:240px;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--neu-surface-3) transparent;animation:neu-select-open .15s ease forwards}.neu-select__panel::-webkit-scrollbar{width:4px}.neu-select__panel::-webkit-scrollbar-thumb{background:var(--neu-surface-3);border-radius:99px}.neu-select__panel--above{border-top:1.5px solid var(--neu-primary);border-bottom:none;border-top-left-radius:var(--neu-radius);border-top-right-radius:var(--neu-radius);border-bottom-left-radius:0;border-bottom-right-radius:0}.neu-select__panel--virtual{overflow:visible}.neu-select__viewport{width:100%}@media(max-width:600px){.neu-select__panel{left:auto;right:0;width:min(max(100%,220px),100vw - 2rem);max-width:calc(100vw - 2rem)}}@keyframes neu-select-open{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.neu-select__option{display:flex;align-items:center;gap:var(--neu-space-2);padding:var(--neu-space-3) var(--neu-space-4);min-height:var(--neu-select-option-height, 44px);box-sizing:border-box;font-size:var(--neu-text-sm);color:var(--neu-text);cursor:pointer;transition:background-color var(--neu-transition)}.neu-select__option:hover:not(.neu-select__option--disabled){background:var(--neu-primary-50);color:var(--neu-primary)}.neu-select__option--selected{color:var(--neu-primary);font-weight:600;background:var(--neu-primary-50)}.neu-select__option--disabled{opacity:.4;cursor:not-allowed}.neu-select__check{width:14px;height:14px;flex-shrink:0}.neu-select__error{margin-top:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-error-text);font-family:var(--neu-font-sans)}.neu-select__hint{margin-top:var(--neu-space-1);font-size:var(--neu-text-xs);color:var(--neu-text-muted);font-family:var(--neu-font-sans)}.neu-select__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-select__static-label{display:block;font-size:var(--neu-text-sm);font-weight:500;color:var(--neu-text-muted);margin-bottom:var(--neu-space-2)}.neu-select__search{padding:var(--neu-space-2);border-bottom:1px solid var(--neu-border);position:sticky;top:0;background:var(--neu-surface);z-index:1}.neu-select__search-input{width:100%;height:34px;padding:0 var(--neu-space-3);border:1.5px solid var(--neu-border);border-radius:var(--neu-radius-sm);background:var(--neu-bg);font-family:var(--neu-font-sans);font-size:var(--neu-text-sm);color:var(--neu-text);outline:none;transition:border-color var(--neu-transition),box-shadow var(--neu-transition)}.neu-select__search-input:focus{border-color:var(--neu-primary);box-shadow:0 0 0 2px #007aff1f}.neu-select__search-input::placeholder{color:var(--neu-text-disabled)}.neu-select__empty{padding:var(--neu-space-4);text-align:center;font-size:var(--neu-text-sm);color:var(--neu-text-disabled);font-family:var(--neu-font-sans)}\n"] }]
|
|
878
926
|
}], ctorParameters: () => [], propDecorators: { _viewport: [{ type: i0.ViewChild, args: [i0.forwardRef(() => CdkVirtualScrollViewport), { isSignal: true }] }], itemTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NeuSelectItemDirective), { isSignal: true }] }], selectedItemTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NeuSelectSelectedDirective), { isSignal: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], floatingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "floatingLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], virtualScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScroll", required: false }] }], virtualScrollVisibleItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "virtualScrollVisibleItems", required: false }] }], noResultsMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noResultsMessage", required: false }] }], clearAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearAriaLabel", required: false }] }], urlParam: [{ type: i0.Input, args: [{ isSignal: true, alias: "urlParam", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }] } });
|
|
879
927
|
|
|
880
928
|
/**
|