codexly-ui 0.10.113 → 0.11.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/fesm2022/codexly-ui.mjs +317 -1
- package/fesm2022/codexly-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/codexly-ui.d.ts +126 -3
package/fesm2022/codexly-ui.mjs
CHANGED
|
@@ -627,6 +627,28 @@ class ClxThemeService {
|
|
|
627
627
|
bordered: t?.bordered ?? true,
|
|
628
628
|
};
|
|
629
629
|
}, ...(ngDevMode ? [{ debugName: "paginationStyle" }] : /* istanbul ignore next */ []));
|
|
630
|
+
/** Resolved style for ClxNotificationComponent — severity colors fall back to built-in
|
|
631
|
+
* green/amber/sky/red, unreadColor to primaryColor, borderColor to listBorderColor then
|
|
632
|
+
* primaryColor, radius to the app-wide borderRadius. Per-instance inputs on clx-notification
|
|
633
|
+
* still take precedence over this theme-wide default. */
|
|
634
|
+
notificationStyle = computed(() => {
|
|
635
|
+
const n = this._config().notification;
|
|
636
|
+
return {
|
|
637
|
+
severityColors: {
|
|
638
|
+
success: n?.severityColors?.success ?? this._config().successColor,
|
|
639
|
+
warning: n?.severityColors?.warning ?? this._config().warningColor,
|
|
640
|
+
info: n?.severityColors?.info ?? 'sky',
|
|
641
|
+
error: n?.severityColors?.error ?? this._config().dangerColor,
|
|
642
|
+
},
|
|
643
|
+
unreadColor: n?.unreadColor ?? this._config().primaryColor,
|
|
644
|
+
size: n?.size ?? 'md',
|
|
645
|
+
borderColor: n?.borderColor ?? this._config().listBorderColor ?? this._config().primaryColor,
|
|
646
|
+
radius: n?.radius ?? this._config().borderRadius,
|
|
647
|
+
titleWeight: n?.titleWeight ?? 600,
|
|
648
|
+
detailColor: n?.detailColor,
|
|
649
|
+
groupLabelWeight: n?.groupLabelWeight ?? 700,
|
|
650
|
+
};
|
|
651
|
+
}, ...(ngDevMode ? [{ debugName: "notificationStyle" }] : /* istanbul ignore next */ []));
|
|
630
652
|
/** Resolved text color for solid primary/secondary buttons — undefined means "let
|
|
631
653
|
* resolveColor() auto-pick white/dark-800 based on shade", same as today. */
|
|
632
654
|
buttonTextColor(role) {
|
|
@@ -11236,6 +11258,300 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
11236
11258
|
}]
|
|
11237
11259
|
}], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], showClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClose", required: false }] }], confirmButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmButton", required: false }] }], cancelButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelButton", required: false }] }], showCancelButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCancelButton", required: false }] }], confirmClick: [{ type: i0.Output, args: ["confirmClick"] }], cancelClick: [{ type: i0.Output, args: ["cancelClick"] }] } });
|
|
11238
11260
|
|
|
11261
|
+
// ── Size map — same density-token shape as LIST_SIZE_MAP ──────────────────────
|
|
11262
|
+
const NOTIFICATION_SIZE_MAP = {
|
|
11263
|
+
sm: { row: 'py-2', iconWrap: 'w-7 h-7', iconSize: 'xs', title: 'text-xs', detail: 'text-[11px]', time: 'text-[10px]' },
|
|
11264
|
+
md: { row: 'py-2.5', iconWrap: 'w-8.5 h-8.5', iconSize: 'sm', title: 'text-[13px]', detail: 'text-xs', time: 'text-[11px]' },
|
|
11265
|
+
lg: { row: 'py-3', iconWrap: 'w-10 h-10', iconSize: 'md', title: 'text-sm', detail: 'text-[13px]', time: 'text-xs' },
|
|
11266
|
+
};
|
|
11267
|
+
// ── Default icon per severity — used when an item doesn't specify its own `icon` ──
|
|
11268
|
+
const NOTIFICATION_SEVERITY_ICON = {
|
|
11269
|
+
success: 'check_circle',
|
|
11270
|
+
warning: 'notifications_active',
|
|
11271
|
+
info: 'info',
|
|
11272
|
+
error: 'error',
|
|
11273
|
+
};
|
|
11274
|
+
|
|
11275
|
+
/** "Dumb" panel: renders whatever list of items it's given via `items()` and emits intent
|
|
11276
|
+
* (itemClick/markRead/markAllRead/delete/deleteAllRead) outward — it never fetches, persists,
|
|
11277
|
+
* or connects to a real-time source itself. Callers (e.g. codexly-app's NotificationService,
|
|
11278
|
+
* backed by SSE) own that and just feed the current list in. Meant to be projected inside
|
|
11279
|
+
* clx-drawer's body, same as any other content. */
|
|
11280
|
+
class ClxNotificationComponent {
|
|
11281
|
+
_themeSvc = inject(ClxThemeService);
|
|
11282
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
11283
|
+
color = input(undefined, ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
|
|
11284
|
+
size = input(undefined, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
11285
|
+
itemClick = output();
|
|
11286
|
+
markRead = output();
|
|
11287
|
+
markAllRead = output();
|
|
11288
|
+
delete = output();
|
|
11289
|
+
deleteAllRead = output();
|
|
11290
|
+
_filter = signal('all', ...(ngDevMode ? [{ debugName: "_filter" }] : /* istanbul ignore next */ []));
|
|
11291
|
+
_style = this._themeSvc.notificationStyle;
|
|
11292
|
+
_color = computed(() => this.color() ?? this._themeSvc.config().primaryColor, ...(ngDevMode ? [{ debugName: "_color" }] : /* istanbul ignore next */ []));
|
|
11293
|
+
_resolvedSize = computed(() => this.size() ?? this._style().size, ...(ngDevMode ? [{ debugName: "_resolvedSize" }] : /* istanbul ignore next */ []));
|
|
11294
|
+
_sizeTokens = computed(() => NOTIFICATION_SIZE_MAP[this._resolvedSize()], ...(ngDevMode ? [{ debugName: "_sizeTokens" }] : /* istanbul ignore next */ []));
|
|
11295
|
+
_unreadCount = computed(() => this.items().filter(i => !i.read).length, ...(ngDevMode ? [{ debugName: "_unreadCount" }] : /* istanbul ignore next */ []));
|
|
11296
|
+
_readCount = computed(() => this.items().filter(i => i.read).length, ...(ngDevMode ? [{ debugName: "_readCount" }] : /* istanbul ignore next */ []));
|
|
11297
|
+
_visibleItems = computed(() => this._filter() === 'unread' ? this.items().filter(i => !i.read) : this.items(), ...(ngDevMode ? [{ debugName: "_visibleItems" }] : /* istanbul ignore next */ []));
|
|
11298
|
+
_groups = computed(() => {
|
|
11299
|
+
const byLabel = new Map();
|
|
11300
|
+
for (const item of this._visibleItems()) {
|
|
11301
|
+
const label = this._dayLabel(item.createdAt);
|
|
11302
|
+
const bucket = byLabel.get(label);
|
|
11303
|
+
if (bucket)
|
|
11304
|
+
bucket.push(item);
|
|
11305
|
+
else
|
|
11306
|
+
byLabel.set(label, [item]);
|
|
11307
|
+
}
|
|
11308
|
+
return Array.from(byLabel, ([label, items]) => ({ label, items }));
|
|
11309
|
+
}, ...(ngDevMode ? [{ debugName: "_groups" }] : /* istanbul ignore next */ []));
|
|
11310
|
+
_wrapClass = computed(() => `flex flex-col ${resolveContainerRadius(this._style().radius)}`, ...(ngDevMode ? [{ debugName: "_wrapClass" }] : /* istanbul ignore next */ []));
|
|
11311
|
+
_groupLabelClass = computed(() => {
|
|
11312
|
+
const w = this._style().groupLabelWeight;
|
|
11313
|
+
return `px-1 pt-3 pb-1.5 text-[11px] uppercase tracking-wide text-clx-text-subtle font-[${w}]`;
|
|
11314
|
+
}, ...(ngDevMode ? [{ debugName: "_groupLabelClass" }] : /* istanbul ignore next */ []));
|
|
11315
|
+
_linkClass = computed(() => resolveColor(this._color()).textSubtle, ...(ngDevMode ? [{ debugName: "_linkClass" }] : /* istanbul ignore next */ []));
|
|
11316
|
+
_unreadRailClass = computed(() => resolveColor(this._style().unreadColor).bg, ...(ngDevMode ? [{ debugName: "_unreadRailClass" }] : /* istanbul ignore next */ []));
|
|
11317
|
+
_unreadDotClass = computed(() => `w-1.5 h-1.5 rounded-full shrink-0 ${resolveColor(this._style().unreadColor).bg}`, ...(ngDevMode ? [{ debugName: "_unreadDotClass" }] : /* istanbul ignore next */ []));
|
|
11318
|
+
_detailClass = computed(() => this._style().detailColor ? resolveColor(this._style().detailColor).textSubtle : 'text-clx-text-muted', ...(ngDevMode ? [{ debugName: "_detailClass" }] : /* istanbul ignore next */ []));
|
|
11319
|
+
_titleClass(item) {
|
|
11320
|
+
const weight = item.read ? 500 : this._style().titleWeight;
|
|
11321
|
+
return `text-clx-text-label font-[${weight}]`;
|
|
11322
|
+
}
|
|
11323
|
+
_iconWrapClass(item) {
|
|
11324
|
+
const c = resolveColor(this._severityColor(item.severity));
|
|
11325
|
+
return `flex items-center justify-center rounded-lg shrink-0 ${c.bgSubtle} ${c.textSubtle} ${this._sizeTokens().iconWrap}`;
|
|
11326
|
+
}
|
|
11327
|
+
_defaultIcon(severity) {
|
|
11328
|
+
return NOTIFICATION_SEVERITY_ICON[severity];
|
|
11329
|
+
}
|
|
11330
|
+
_open(item) {
|
|
11331
|
+
this.itemClick.emit(item);
|
|
11332
|
+
if (!item.read)
|
|
11333
|
+
this.markRead.emit(item.id);
|
|
11334
|
+
}
|
|
11335
|
+
_countBadgeClass(tab) {
|
|
11336
|
+
const active = this._filter() === tab;
|
|
11337
|
+
return active
|
|
11338
|
+
? 'ml-0.5 text-[10px] font-bold tabular-nums'
|
|
11339
|
+
: 'ml-0.5 text-[10px] font-bold tabular-nums text-clx-text-subtle';
|
|
11340
|
+
}
|
|
11341
|
+
_severityColor(severity) {
|
|
11342
|
+
return this._style().severityColors[severity];
|
|
11343
|
+
}
|
|
11344
|
+
_dayLabel(iso) {
|
|
11345
|
+
const date = new Date(iso);
|
|
11346
|
+
const now = new Date();
|
|
11347
|
+
const startOf = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime();
|
|
11348
|
+
const diffDays = Math.round((startOf(now) - startOf(date)) / 86_400_000);
|
|
11349
|
+
if (diffDays === 0)
|
|
11350
|
+
return 'Hoy';
|
|
11351
|
+
if (diffDays === 1)
|
|
11352
|
+
return 'Ayer';
|
|
11353
|
+
if (diffDays > 1 && diffDays < 7)
|
|
11354
|
+
return `Hace ${diffDays} días`;
|
|
11355
|
+
return date.toLocaleDateString('es-CO', { day: 'numeric', month: 'short' });
|
|
11356
|
+
}
|
|
11357
|
+
_timeOf(iso) {
|
|
11358
|
+
return new Date(iso).toLocaleTimeString('es-CO', { hour: '2-digit', minute: '2-digit' });
|
|
11359
|
+
}
|
|
11360
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxNotificationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11361
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.15", type: ClxNotificationComponent, isStandalone: true, selector: "clx-notification", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemClick: "itemClick", markRead: "markRead", markAllRead: "markAllRead", delete: "delete", deleteAllRead: "deleteAllRead" }, ngImport: i0, template: `
|
|
11362
|
+
<div [class]="_wrapClass()">
|
|
11363
|
+
<!-- Filter -->
|
|
11364
|
+
<div class="flex items-center gap-2 px-1 pb-3">
|
|
11365
|
+
<button clx-button type="button" size="xs" shape="pill"
|
|
11366
|
+
[variant]="_filter() === 'all' ? 'solid' : 'ghost'"
|
|
11367
|
+
[color]="_filter() === 'all' ? _color() : 'slate'"
|
|
11368
|
+
(click)="_filter.set('all')">
|
|
11369
|
+
Todas
|
|
11370
|
+
@if (items().length) {
|
|
11371
|
+
<span [class]="_countBadgeClass('all')">{{ items().length }}</span>
|
|
11372
|
+
}
|
|
11373
|
+
</button>
|
|
11374
|
+
<button clx-button type="button" size="xs" shape="pill"
|
|
11375
|
+
[variant]="_filter() === 'unread' ? 'solid' : 'ghost'"
|
|
11376
|
+
[color]="_filter() === 'unread' ? _color() : 'slate'"
|
|
11377
|
+
(click)="_filter.set('unread')">
|
|
11378
|
+
Sin leer
|
|
11379
|
+
@if (_unreadCount() > 0) {
|
|
11380
|
+
<span [class]="_countBadgeClass('unread')">{{ _unreadCount() }}</span>
|
|
11381
|
+
}
|
|
11382
|
+
</button>
|
|
11383
|
+
<div class="flex-1"></div>
|
|
11384
|
+
@if (_unreadCount() > 0) {
|
|
11385
|
+
<button type="button" class="text-xs font-semibold shrink-0" [class]="_linkClass()"
|
|
11386
|
+
(click)="markAllRead.emit()">
|
|
11387
|
+
Marcar todo leído
|
|
11388
|
+
</button>
|
|
11389
|
+
}
|
|
11390
|
+
@if (_readCount() > 0) {
|
|
11391
|
+
<button type="button" class="text-xs font-semibold shrink-0 text-clx-text-subtle hover:text-red-500"
|
|
11392
|
+
(click)="deleteAllRead.emit()">
|
|
11393
|
+
Eliminar leídas
|
|
11394
|
+
</button>
|
|
11395
|
+
}
|
|
11396
|
+
</div>
|
|
11397
|
+
|
|
11398
|
+
<!-- List -->
|
|
11399
|
+
@if (_groups().length) {
|
|
11400
|
+
<div class="flex flex-col">
|
|
11401
|
+
@for (group of _groups(); track group.label) {
|
|
11402
|
+
<p [class]="_groupLabelClass()">{{ group.label }}</p>
|
|
11403
|
+
@for (item of group.items; track item.id) {
|
|
11404
|
+
<div
|
|
11405
|
+
class="group relative flex items-start gap-3 px-1 rounded-lg cursor-pointer hover:bg-clx-surface-2 {{ _sizeTokens().row }}"
|
|
11406
|
+
role="button"
|
|
11407
|
+
tabindex="0"
|
|
11408
|
+
(click)="_open(item)"
|
|
11409
|
+
(keydown.enter)="_open(item)">
|
|
11410
|
+
|
|
11411
|
+
<span class="absolute left-0 top-1.5 bottom-1.5 w-[3px] rounded-full {{ item.read ? '' : _unreadRailClass() }}"></span>
|
|
11412
|
+
|
|
11413
|
+
<span [class]="_iconWrapClass(item)">
|
|
11414
|
+
<span clx-icon [name]="item.icon || _defaultIcon(item.severity)" [size]="_sizeTokens().iconSize"></span>
|
|
11415
|
+
</span>
|
|
11416
|
+
|
|
11417
|
+
<div class="flex-1 min-w-0 pl-1.5">
|
|
11418
|
+
<p class="flex items-baseline gap-1.5 {{ _sizeTokens().title }}" [class]="_titleClass(item)">
|
|
11419
|
+
@if (!item.read) {
|
|
11420
|
+
<span [class]="_unreadDotClass()"></span>
|
|
11421
|
+
}
|
|
11422
|
+
<span class="truncate">{{ item.title }}</span>
|
|
11423
|
+
</p>
|
|
11424
|
+
@if (item.detail) {
|
|
11425
|
+
<p class="mt-0.5 line-clamp-2 {{ _sizeTokens().detail }}" [class]="_detailClass()">{{ item.detail }}</p>
|
|
11426
|
+
}
|
|
11427
|
+
</div>
|
|
11428
|
+
|
|
11429
|
+
<div class="flex flex-col items-end gap-1 shrink-0 pl-2">
|
|
11430
|
+
<span class="text-clx-text-subtle tabular-nums {{ _sizeTokens().time }}">{{ _timeOf(item.createdAt) }}</span>
|
|
11431
|
+
<button type="button"
|
|
11432
|
+
class="opacity-0 group-hover:opacity-100 focus-visible:opacity-100 transition-opacity rounded-md p-0.5 text-clx-text-subtle hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-950"
|
|
11433
|
+
aria-label="Eliminar notificación"
|
|
11434
|
+
(click)="$event.stopPropagation(); delete.emit(item.id)">
|
|
11435
|
+
<span clx-icon name="close" size="xs"></span>
|
|
11436
|
+
</button>
|
|
11437
|
+
</div>
|
|
11438
|
+
</div>
|
|
11439
|
+
}
|
|
11440
|
+
}
|
|
11441
|
+
</div>
|
|
11442
|
+
} @else {
|
|
11443
|
+
<div class="flex flex-col items-center justify-center gap-2 py-14 text-center">
|
|
11444
|
+
<span clx-icon name="notifications_off" size="xl" class="text-clx-text-subtle"></span>
|
|
11445
|
+
<p class="text-sm font-medium text-clx-text-label">
|
|
11446
|
+
{{ _filter() === 'unread' ? 'No tienes notificaciones sin leer' : 'No hay notificaciones' }}
|
|
11447
|
+
</p>
|
|
11448
|
+
</div>
|
|
11449
|
+
}
|
|
11450
|
+
</div>
|
|
11451
|
+
`, isInline: true, dependencies: [{ kind: "component", type: ClxButtonComponent, selector: "button[clx-button], a[clx-button]", inputs: ["variant", "color", "textColor", "size", "shape", "loading", "disabled", "block", "icon", "iconPosition", "iconOnly", "badge", "badgeColor"] }, { kind: "component", type: ClxIconComponent, selector: "span[clx-icon]", inputs: ["name", "size", "color", "fill"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
11452
|
+
}
|
|
11453
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImport: i0, type: ClxNotificationComponent, decorators: [{
|
|
11454
|
+
type: Component,
|
|
11455
|
+
args: [{
|
|
11456
|
+
selector: 'clx-notification',
|
|
11457
|
+
standalone: true,
|
|
11458
|
+
imports: [ClxButtonComponent, ClxIconComponent],
|
|
11459
|
+
template: `
|
|
11460
|
+
<div [class]="_wrapClass()">
|
|
11461
|
+
<!-- Filter -->
|
|
11462
|
+
<div class="flex items-center gap-2 px-1 pb-3">
|
|
11463
|
+
<button clx-button type="button" size="xs" shape="pill"
|
|
11464
|
+
[variant]="_filter() === 'all' ? 'solid' : 'ghost'"
|
|
11465
|
+
[color]="_filter() === 'all' ? _color() : 'slate'"
|
|
11466
|
+
(click)="_filter.set('all')">
|
|
11467
|
+
Todas
|
|
11468
|
+
@if (items().length) {
|
|
11469
|
+
<span [class]="_countBadgeClass('all')">{{ items().length }}</span>
|
|
11470
|
+
}
|
|
11471
|
+
</button>
|
|
11472
|
+
<button clx-button type="button" size="xs" shape="pill"
|
|
11473
|
+
[variant]="_filter() === 'unread' ? 'solid' : 'ghost'"
|
|
11474
|
+
[color]="_filter() === 'unread' ? _color() : 'slate'"
|
|
11475
|
+
(click)="_filter.set('unread')">
|
|
11476
|
+
Sin leer
|
|
11477
|
+
@if (_unreadCount() > 0) {
|
|
11478
|
+
<span [class]="_countBadgeClass('unread')">{{ _unreadCount() }}</span>
|
|
11479
|
+
}
|
|
11480
|
+
</button>
|
|
11481
|
+
<div class="flex-1"></div>
|
|
11482
|
+
@if (_unreadCount() > 0) {
|
|
11483
|
+
<button type="button" class="text-xs font-semibold shrink-0" [class]="_linkClass()"
|
|
11484
|
+
(click)="markAllRead.emit()">
|
|
11485
|
+
Marcar todo leído
|
|
11486
|
+
</button>
|
|
11487
|
+
}
|
|
11488
|
+
@if (_readCount() > 0) {
|
|
11489
|
+
<button type="button" class="text-xs font-semibold shrink-0 text-clx-text-subtle hover:text-red-500"
|
|
11490
|
+
(click)="deleteAllRead.emit()">
|
|
11491
|
+
Eliminar leídas
|
|
11492
|
+
</button>
|
|
11493
|
+
}
|
|
11494
|
+
</div>
|
|
11495
|
+
|
|
11496
|
+
<!-- List -->
|
|
11497
|
+
@if (_groups().length) {
|
|
11498
|
+
<div class="flex flex-col">
|
|
11499
|
+
@for (group of _groups(); track group.label) {
|
|
11500
|
+
<p [class]="_groupLabelClass()">{{ group.label }}</p>
|
|
11501
|
+
@for (item of group.items; track item.id) {
|
|
11502
|
+
<div
|
|
11503
|
+
class="group relative flex items-start gap-3 px-1 rounded-lg cursor-pointer hover:bg-clx-surface-2 {{ _sizeTokens().row }}"
|
|
11504
|
+
role="button"
|
|
11505
|
+
tabindex="0"
|
|
11506
|
+
(click)="_open(item)"
|
|
11507
|
+
(keydown.enter)="_open(item)">
|
|
11508
|
+
|
|
11509
|
+
<span class="absolute left-0 top-1.5 bottom-1.5 w-[3px] rounded-full {{ item.read ? '' : _unreadRailClass() }}"></span>
|
|
11510
|
+
|
|
11511
|
+
<span [class]="_iconWrapClass(item)">
|
|
11512
|
+
<span clx-icon [name]="item.icon || _defaultIcon(item.severity)" [size]="_sizeTokens().iconSize"></span>
|
|
11513
|
+
</span>
|
|
11514
|
+
|
|
11515
|
+
<div class="flex-1 min-w-0 pl-1.5">
|
|
11516
|
+
<p class="flex items-baseline gap-1.5 {{ _sizeTokens().title }}" [class]="_titleClass(item)">
|
|
11517
|
+
@if (!item.read) {
|
|
11518
|
+
<span [class]="_unreadDotClass()"></span>
|
|
11519
|
+
}
|
|
11520
|
+
<span class="truncate">{{ item.title }}</span>
|
|
11521
|
+
</p>
|
|
11522
|
+
@if (item.detail) {
|
|
11523
|
+
<p class="mt-0.5 line-clamp-2 {{ _sizeTokens().detail }}" [class]="_detailClass()">{{ item.detail }}</p>
|
|
11524
|
+
}
|
|
11525
|
+
</div>
|
|
11526
|
+
|
|
11527
|
+
<div class="flex flex-col items-end gap-1 shrink-0 pl-2">
|
|
11528
|
+
<span class="text-clx-text-subtle tabular-nums {{ _sizeTokens().time }}">{{ _timeOf(item.createdAt) }}</span>
|
|
11529
|
+
<button type="button"
|
|
11530
|
+
class="opacity-0 group-hover:opacity-100 focus-visible:opacity-100 transition-opacity rounded-md p-0.5 text-clx-text-subtle hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-950"
|
|
11531
|
+
aria-label="Eliminar notificación"
|
|
11532
|
+
(click)="$event.stopPropagation(); delete.emit(item.id)">
|
|
11533
|
+
<span clx-icon name="close" size="xs"></span>
|
|
11534
|
+
</button>
|
|
11535
|
+
</div>
|
|
11536
|
+
</div>
|
|
11537
|
+
}
|
|
11538
|
+
}
|
|
11539
|
+
</div>
|
|
11540
|
+
} @else {
|
|
11541
|
+
<div class="flex flex-col items-center justify-center gap-2 py-14 text-center">
|
|
11542
|
+
<span clx-icon name="notifications_off" size="xl" class="text-clx-text-subtle"></span>
|
|
11543
|
+
<p class="text-sm font-medium text-clx-text-label">
|
|
11544
|
+
{{ _filter() === 'unread' ? 'No tienes notificaciones sin leer' : 'No hay notificaciones' }}
|
|
11545
|
+
</p>
|
|
11546
|
+
</div>
|
|
11547
|
+
}
|
|
11548
|
+
</div>
|
|
11549
|
+
`,
|
|
11550
|
+
encapsulation: ViewEncapsulation.None,
|
|
11551
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
11552
|
+
}]
|
|
11553
|
+
}], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }], markRead: [{ type: i0.Output, args: ["markRead"] }], markAllRead: [{ type: i0.Output, args: ["markAllRead"] }], delete: [{ type: i0.Output, args: ["delete"] }], deleteAllRead: [{ type: i0.Output, args: ["deleteAllRead"] }] } });
|
|
11554
|
+
|
|
11239
11555
|
// ─── CDK overlay token (carries the resolved ref into the component) ──────────
|
|
11240
11556
|
const CLX_ALERT_OPTIONS = new InjectionToken('CLX_ALERT_OPTIONS');
|
|
11241
11557
|
const CLX_ALERT_RESOLVE = new InjectionToken('CLX_ALERT_RESOLVE');
|
|
@@ -17065,5 +17381,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.15", ngImpo
|
|
|
17065
17381
|
* Generated bundle index. Do not edit.
|
|
17066
17382
|
*/
|
|
17067
17383
|
|
|
17068
|
-
export { CLX_ADDON_BORDER, CLX_ADDON_TEXT, CLX_ALERT_OPTIONS, CLX_ALERT_RESOLVE, CLX_BG_ADDON, CLX_BG_DISABLED, CLX_BG_ICON_WRAP, CLX_BG_SECTION, CLX_BG_SURFACE, CLX_BORDER_DEFAULT, CLX_BORDER_DISABLED, CLX_BORDER_MEDIUM, CLX_COLOR_HEX, CLX_COLOR_HEX_100, CLX_COLOR_MAP, CLX_FONT_CATALOG, CLX_MODAL_ANIM_CONFIG, CLX_MODAL_DATA, CLX_MODAL_REF, CLX_OPTION_DISABLED, CLX_PLACEHOLDER, CLX_RADIO_GROUP, CLX_RADIUS_MAP, CLX_TEXT_BODY, CLX_TEXT_DISABLED, CLX_TEXT_HEADING, CLX_TEXT_HINT, CLX_TEXT_IDLE, CLX_TEXT_INPUT, CLX_TEXT_LABEL, CLX_TEXT_OPTION, CLX_TEXT_SUBTITLE, CLX_TEXT_TITLE, CLX_THEME_CONFIG, CLX_THEME_DEFAULTS, CLX_TOAST_DEFAULTS, ClxAlertComponent, ClxAlertService, ClxAnimateDirective, ClxAnimateGroupDirective, ClxAnimateService, ClxAppLayoutComponent, ClxAvatarComponent, ClxBadgeComponent, ClxBrandComponent, ClxButtonComponent, ClxButtonGroupComponent, ClxCardBodyDirective, ClxCardComponent, ClxCardFooterDirective, ClxCardHeaderActionsDirective, ClxCardHeaderDirective, ClxCarouselComponent, ClxCarouselDirective, ClxCartComponent, ClxCartSummaryDrawer, ClxCellDirective, ClxCheckboxComponent, ClxCollapseComponent, ClxColorPickerComponent, ClxColumnDefDirective, ClxDateRangePickerComponent, ClxDatepickerComponent, ClxDrawerComponent, ClxDrawerService, ClxEditorComponent, ClxEditorLinkModalComponent, ClxFabComponent, ClxFilterPanelComponent, ClxHeaderCellDirective, ClxIconComponent, ClxInputComponent, ClxListComponent, ClxListItemComponent, ClxMenuComponent, ClxMenuItemComponent, ClxMenuItemTrailingDirective, ClxModalComponent, ClxModalService, ClxNativeOverlayService, ClxNavGroupComponent, ClxNumberComponent, ClxOtpComponent, ClxPageEmptyComponent, ClxPageHeaderComponent, ClxPageHeaderTitleDirective, ClxPageNotFoundComponent, ClxPageServerErrorComponent, ClxPageUnauthorizedComponent, ClxPaginationComponent, ClxProductComponent, ClxProductDetailComponent, ClxProductQuickViewComponent, ClxProfileComponent, ClxProgressBarComponent, ClxRadioComponent, ClxRadioGroupComponent, ClxRatingComponent, ClxSearchComponent, ClxSelectComponent, ClxSkeletonComponent, ClxSliderComponent, ClxSocialIconComponent, ClxSpinnerComponent, ClxStatCardComponent, ClxStepComponent, ClxStepperComponent, ClxSwitchComponent, ClxTabDirective, ClxTableActionsComponent, ClxTableComponent, ClxTabsComponent, ClxTagComponent, ClxTextareaComponent, ClxThemeService, ClxTimelineComponent, ClxTimelineItemComponent, ClxTimepickerComponent, ClxToastComponent, ClxToastContainerComponent, ClxToastService, ClxTooltipComponent, ClxTooltipDirective, ClxTreeComponent, ClxUploadComponent, ClxWishlistComponent, ClxWizardComponent, TIMEPICKER_SIZE_MAP, parseColorInput, provideCodexlyTheme, resolveColor, resolveContainerRadius, resolveRadius };
|
|
17384
|
+
export { CLX_ADDON_BORDER, CLX_ADDON_TEXT, CLX_ALERT_OPTIONS, CLX_ALERT_RESOLVE, CLX_BG_ADDON, CLX_BG_DISABLED, CLX_BG_ICON_WRAP, CLX_BG_SECTION, CLX_BG_SURFACE, CLX_BORDER_DEFAULT, CLX_BORDER_DISABLED, CLX_BORDER_MEDIUM, CLX_COLOR_HEX, CLX_COLOR_HEX_100, CLX_COLOR_MAP, CLX_FONT_CATALOG, CLX_MODAL_ANIM_CONFIG, CLX_MODAL_DATA, CLX_MODAL_REF, CLX_OPTION_DISABLED, CLX_PLACEHOLDER, CLX_RADIO_GROUP, CLX_RADIUS_MAP, CLX_TEXT_BODY, CLX_TEXT_DISABLED, CLX_TEXT_HEADING, CLX_TEXT_HINT, CLX_TEXT_IDLE, CLX_TEXT_INPUT, CLX_TEXT_LABEL, CLX_TEXT_OPTION, CLX_TEXT_SUBTITLE, CLX_TEXT_TITLE, CLX_THEME_CONFIG, CLX_THEME_DEFAULTS, CLX_TOAST_DEFAULTS, ClxAlertComponent, ClxAlertService, ClxAnimateDirective, ClxAnimateGroupDirective, ClxAnimateService, ClxAppLayoutComponent, ClxAvatarComponent, ClxBadgeComponent, ClxBrandComponent, ClxButtonComponent, ClxButtonGroupComponent, ClxCardBodyDirective, ClxCardComponent, ClxCardFooterDirective, ClxCardHeaderActionsDirective, ClxCardHeaderDirective, ClxCarouselComponent, ClxCarouselDirective, ClxCartComponent, ClxCartSummaryDrawer, ClxCellDirective, ClxCheckboxComponent, ClxCollapseComponent, ClxColorPickerComponent, ClxColumnDefDirective, ClxDateRangePickerComponent, ClxDatepickerComponent, ClxDrawerComponent, ClxDrawerService, ClxEditorComponent, ClxEditorLinkModalComponent, ClxFabComponent, ClxFilterPanelComponent, ClxHeaderCellDirective, ClxIconComponent, ClxInputComponent, ClxListComponent, ClxListItemComponent, ClxMenuComponent, ClxMenuItemComponent, ClxMenuItemTrailingDirective, ClxModalComponent, ClxModalService, ClxNativeOverlayService, ClxNavGroupComponent, ClxNotificationComponent, ClxNumberComponent, ClxOtpComponent, ClxPageEmptyComponent, ClxPageHeaderComponent, ClxPageHeaderTitleDirective, ClxPageNotFoundComponent, ClxPageServerErrorComponent, ClxPageUnauthorizedComponent, ClxPaginationComponent, ClxProductComponent, ClxProductDetailComponent, ClxProductQuickViewComponent, ClxProfileComponent, ClxProgressBarComponent, ClxRadioComponent, ClxRadioGroupComponent, ClxRatingComponent, ClxSearchComponent, ClxSelectComponent, ClxSkeletonComponent, ClxSliderComponent, ClxSocialIconComponent, ClxSpinnerComponent, ClxStatCardComponent, ClxStepComponent, ClxStepperComponent, ClxSwitchComponent, ClxTabDirective, ClxTableActionsComponent, ClxTableComponent, ClxTabsComponent, ClxTagComponent, ClxTextareaComponent, ClxThemeService, ClxTimelineComponent, ClxTimelineItemComponent, ClxTimepickerComponent, ClxToastComponent, ClxToastContainerComponent, ClxToastService, ClxTooltipComponent, ClxTooltipDirective, ClxTreeComponent, ClxUploadComponent, ClxWishlistComponent, ClxWizardComponent, TIMEPICKER_SIZE_MAP, parseColorInput, provideCodexlyTheme, resolveColor, resolveContainerRadius, resolveRadius };
|
|
17069
17385
|
//# sourceMappingURL=codexly-ui.mjs.map
|